├── snap
├── btn1.png
├── btn2.png
├── btn3.png
├── avatar1.png
├── card1.png
├── msgbox2.png
├── msgbox3.png
├── slider1.png
├── checkbox1.png
├── inputnum1.png
├── radiobtn1.png
├── switchbtn1.png
├── lineprogress1.png
└── circleprogress1.png
├── example
├── avatar.png
├── resource.qrc
├── widget.h
├── widget.ui
├── main.cpp
├── example.pro
└── widget.cpp
├── qelement
├── images
│ ├── arrow-up.png
│ └── arrow-down.png
├── qelement.qrc
├── el_tooltip.cpp
├── el_global.h
├── el_select.h
├── el_tooltip.h
├── el_awesome.h
├── el_input.h
├── el_card.h
├── el_inputnumber.h
├── el_radio.h
├── el_checkbox.h
├── el_lineprogress.h
├── el_circleprogress.h
├── el_imageprovider.h
├── el_link.h
├── el_lineprogress.cpp
├── qelement.pri
├── el_avatar.h
├── el_select.cpp
├── el_circleprogress.cpp
├── el_style.h
├── el_switch.h
├── el_button.h
├── el_input.cpp
├── el_messagebox.h
├── el_link.cpp
├── el_imageprovider.cpp
├── el_radio.cpp
├── el_checkbox.cpp
├── el_card.cpp
├── el_inputnumber.cpp
├── el_slider.h
├── el_avatar.cpp
├── el_button.cpp
├── el_messagebox.cpp
├── el_switch.cpp
└── el_slider.cpp
├── .gitmodules
├── LICENSE
└── README.md
/snap/btn1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/devcxx/qelement/HEAD/snap/btn1.png
--------------------------------------------------------------------------------
/snap/btn2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/devcxx/qelement/HEAD/snap/btn2.png
--------------------------------------------------------------------------------
/snap/btn3.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/devcxx/qelement/HEAD/snap/btn3.png
--------------------------------------------------------------------------------
/snap/avatar1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/devcxx/qelement/HEAD/snap/avatar1.png
--------------------------------------------------------------------------------
/snap/card1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/devcxx/qelement/HEAD/snap/card1.png
--------------------------------------------------------------------------------
/snap/msgbox2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/devcxx/qelement/HEAD/snap/msgbox2.png
--------------------------------------------------------------------------------
/snap/msgbox3.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/devcxx/qelement/HEAD/snap/msgbox3.png
--------------------------------------------------------------------------------
/snap/slider1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/devcxx/qelement/HEAD/snap/slider1.png
--------------------------------------------------------------------------------
/example/avatar.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/devcxx/qelement/HEAD/example/avatar.png
--------------------------------------------------------------------------------
/snap/checkbox1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/devcxx/qelement/HEAD/snap/checkbox1.png
--------------------------------------------------------------------------------
/snap/inputnum1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/devcxx/qelement/HEAD/snap/inputnum1.png
--------------------------------------------------------------------------------
/snap/radiobtn1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/devcxx/qelement/HEAD/snap/radiobtn1.png
--------------------------------------------------------------------------------
/snap/switchbtn1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/devcxx/qelement/HEAD/snap/switchbtn1.png
--------------------------------------------------------------------------------
/snap/lineprogress1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/devcxx/qelement/HEAD/snap/lineprogress1.png
--------------------------------------------------------------------------------
/snap/circleprogress1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/devcxx/qelement/HEAD/snap/circleprogress1.png
--------------------------------------------------------------------------------
/qelement/images/arrow-up.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/devcxx/qelement/HEAD/qelement/images/arrow-up.png
--------------------------------------------------------------------------------
/qelement/images/arrow-down.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/devcxx/qelement/HEAD/qelement/images/arrow-down.png
--------------------------------------------------------------------------------
/example/resource.qrc:
--------------------------------------------------------------------------------
1 |
2 |
3 | avatar.png
4 |
5 |
6 |
--------------------------------------------------------------------------------
/qelement/qelement.qrc:
--------------------------------------------------------------------------------
1 |
2 |
3 | images/arrow-down.png
4 | images/arrow-up.png
5 |
6 |
7 |
--------------------------------------------------------------------------------
/qelement/el_tooltip.cpp:
--------------------------------------------------------------------------------
1 | #include "el_tooltip.h"
2 |
3 | EL_BEGIN_NAMESPACE
4 |
5 | Tooltip::Tooltip(Effect effect, QWidget* parent)
6 | : QToolTip (parent)
7 | {
8 | }
9 |
10 | EL_END_NAMESPACE
11 |
--------------------------------------------------------------------------------
/.gitmodules:
--------------------------------------------------------------------------------
1 | [submodule "QtAwesome"]
2 | path = QtAwesome
3 | url = https://github.com/gamecreature/QtAwesome
4 | branch = main
5 | [submodule "FramelessWindow"]
6 | path = FramelessWindow
7 | url = https://github.com/winsoft666/Qt-FramelessWindow.git
8 | branch = master
9 |
--------------------------------------------------------------------------------
/qelement/el_global.h:
--------------------------------------------------------------------------------
1 | #ifndef EL_GLOBAL_H
2 | #define EL_GLOBAL_H
3 |
4 | #include
5 |
6 | #if defined(EL_LIBRARY)
7 | #define EL_EXPORT Q_DECL_EXPORT
8 | #else
9 | #define EL_EXPORT
10 | #endif
11 |
12 | #define EL_BEGIN_NAMESPACE namespace el {
13 | #define EL_END_NAMESPACE }
14 |
15 |
16 | #endif // EL_GLOBAL_H
17 |
--------------------------------------------------------------------------------
/example/widget.h:
--------------------------------------------------------------------------------
1 | #ifndef WIDGET_H
2 | #define WIDGET_H
3 |
4 | #include
5 |
6 | QT_BEGIN_NAMESPACE
7 | namespace Ui {
8 | class Widget;
9 | }
10 | QT_END_NAMESPACE
11 |
12 | class Widget : public QWidget
13 | {
14 | Q_OBJECT
15 |
16 | public:
17 | Widget(QWidget *parent = nullptr);
18 | ~Widget();
19 |
20 | private:
21 | Ui::Widget *ui;
22 | };
23 | #endif // WIDGET_H
24 |
--------------------------------------------------------------------------------
/qelement/el_select.h:
--------------------------------------------------------------------------------
1 | #ifndef EL_SELECT_H
2 | #define EL_SELECT_H
3 |
4 | #include "el_global.h"
5 |
6 | #include
7 |
8 | EL_BEGIN_NAMESPACE
9 |
10 | // Select 选择器
11 | class Select : public QComboBox {
12 | Q_OBJECT
13 | public:
14 | Select(QWidget* parent = nullptr);
15 |
16 | protected:
17 | QSize sizeHint() const;
18 | void showPopup();
19 | };
20 |
21 | EL_END_NAMESPACE
22 |
23 | #endif // EL_SELECT_H
24 |
--------------------------------------------------------------------------------
/example/widget.ui:
--------------------------------------------------------------------------------
1 |
2 |
3 | Widget
4 |
5 |
6 |
7 | 0
8 | 0
9 | 800
10 | 600
11 |
12 |
13 |
14 | Widget
15 |
16 |
17 |
18 |
19 |
20 |
--------------------------------------------------------------------------------
/qelement/el_tooltip.h:
--------------------------------------------------------------------------------
1 | #ifndef EL_TOOLTIP_H
2 | #define EL_TOOLTIP_H
3 |
4 | #include "el_global.h"
5 | #include
6 |
7 | EL_BEGIN_NAMESPACE
8 |
9 | class Tooltip : public QToolTip {
10 | Q_OBJECT
11 | public:
12 | enum Effect {
13 | Dark, // 深色
14 | Light, // 浅色
15 | };
16 | Q_ENUM(Effect)
17 |
18 | Tooltip(Effect effect = Dark, QWidget* parent = nullptr);
19 | };
20 |
21 | EL_END_NAMESPACE
22 |
23 | #endif // EL_TOOLTIP_H
24 |
--------------------------------------------------------------------------------
/qelement/el_awesome.h:
--------------------------------------------------------------------------------
1 | #ifndef EL_AWESOME_H
2 | #define EL_AWESOME_H
3 |
4 | #include "QtAwesome.h"
5 | #include "el_global.h"
6 |
7 | EL_BEGIN_NAMESPACE
8 |
9 | class Awesome : public fa::QtAwesome {
10 | Q_OBJECT
11 | public:
12 | static Awesome& instance()
13 | {
14 | static Awesome _instance;
15 | return _instance;
16 | }
17 | };
18 |
19 | EL_END_NAMESPACE
20 |
21 | #define qAwesome (static_cast(&el::Awesome::instance()))
22 |
23 | #endif // EL_AWESOME_H
24 |
--------------------------------------------------------------------------------
/example/main.cpp:
--------------------------------------------------------------------------------
1 | #include "widget.h"
2 |
3 | #include "QtAwesome.h"
4 | #include "el_awesome.h"
5 | #include
6 | #include
7 |
8 | int main(int argc, char* argv[])
9 | {
10 | #if (QT_VERSION >= QT_VERSION_CHECK(5, 6, 0))
11 | QGuiApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
12 | QCoreApplication::setAttribute(Qt::AA_UseHighDpiPixmaps);
13 | #endif
14 | QApplication a(argc, argv);
15 |
16 | qAwesome->initFontAwesome();
17 |
18 | Widget w;
19 | w.show();
20 | return a.exec();
21 | }
22 |
--------------------------------------------------------------------------------
/qelement/el_input.h:
--------------------------------------------------------------------------------
1 | #ifndef EL_INPUT_H
2 | #define EL_INPUT_H
3 |
4 | #include "el_global.h"
5 | #include
6 | #include
7 |
8 | EL_BEGIN_NAMESPACE
9 |
10 | // Input 输入框
11 | class EL_EXPORT Input : public QLineEdit {
12 | Q_OBJECT
13 |
14 | public:
15 | enum Type {
16 | Default,
17 | Clearable, // 可清空
18 | ShowPassword, // 密码框
19 | Calendar, // 日历
20 | };
21 | Q_ENUM(Type)
22 |
23 | Input(Type type = Default, QWidget* parent = nullptr);
24 | };
25 |
26 | EL_END_NAMESPACE
27 |
28 | #endif // EL_INPUT_H
29 |
--------------------------------------------------------------------------------
/qelement/el_card.h:
--------------------------------------------------------------------------------
1 | #ifndef EL_CARD_H
2 | #define EL_CARD_H
3 |
4 | #include "el_global.h"
5 | #include
6 |
7 | EL_BEGIN_NAMESPACE
8 |
9 | // Card 卡片
10 | class EL_EXPORT Card : public QAbstractButton {
11 | Q_OBJECT
12 | public:
13 | Card(const QIcon& icon, const QString& title, const QString& content, QWidget* parent = nullptr);
14 |
15 | protected:
16 | QSize sizeHint() const Q_DECL_OVERRIDE;
17 | void paintEvent(QPaintEvent* event);
18 | void iconToGrayscale(QPixmap* pm);
19 |
20 | private:
21 | QString _content;
22 | };
23 |
24 | EL_END_NAMESPACE
25 |
26 | #endif // EL_CARD_H
27 |
--------------------------------------------------------------------------------
/qelement/el_inputnumber.h:
--------------------------------------------------------------------------------
1 | #ifndef INPUTNUMBER_H
2 | #define INPUTNUMBER_H
3 |
4 | #include "el_global.h"
5 | #include
6 |
7 | class QPushButton;
8 |
9 | EL_BEGIN_NAMESPACE
10 |
11 | // InputNumber 计数器
12 | class EL_EXPORT InputNumber : public QLineEdit {
13 | Q_OBJECT
14 | public:
15 | explicit InputNumber(int min, int max, QWidget* parent = nullptr);
16 |
17 | protected:
18 | void resizeEvent(QResizeEvent* event);
19 | void mouseMoveEvent(QMouseEvent* event);
20 |
21 | signals:
22 |
23 | private:
24 | QPushButton* _minusBtn;
25 | QPushButton* _plusBtn;
26 | };
27 |
28 | EL_END_NAMESPACE
29 |
30 | #endif // INPUTNUMBER_H
31 |
--------------------------------------------------------------------------------
/qelement/el_radio.h:
--------------------------------------------------------------------------------
1 | #ifndef EL_RADIO_H
2 | #define EL_RADIO_H
3 |
4 | #include "el_global.h"
5 | #include
6 |
7 | EL_BEGIN_NAMESPACE
8 |
9 | // Radio 单选框
10 | class EL_EXPORT Radio : public QAbstractButton {
11 | Q_OBJECT
12 | public:
13 | // 文本位置
14 | enum LabelPosition {
15 | LP_Left, // 文字在左
16 | LP_Right, // 文字在右
17 | };
18 |
19 | Radio(const QString& text, LabelPosition placement = LP_Right, QWidget* parent = nullptr);
20 |
21 | protected:
22 | QSize sizeHint() const;
23 | void paintEvent(QPaintEvent* event);
24 | QColor getColor();
25 | QIcon getIcon();
26 |
27 | private:
28 | LabelPosition _placement;
29 | };
30 |
31 | EL_END_NAMESPACE
32 |
33 | #endif // EL_RADIO_H
34 |
--------------------------------------------------------------------------------
/qelement/el_checkbox.h:
--------------------------------------------------------------------------------
1 | #ifndef EL_CHECKBOX_H
2 | #define EL_CHECKBOX_H
3 |
4 | #include "el_global.h"
5 | #include
6 |
7 | EL_BEGIN_NAMESPACE
8 |
9 | // Checkbox 多选框
10 | class EL_EXPORT Checkbox : public QAbstractButton {
11 | Q_OBJECT
12 | public:
13 | // 文本位置
14 | enum LabelPosition {
15 | LP_Left, // 文字在左
16 | LP_Right, // 文字在右
17 | };
18 | Checkbox(const QString& text, LabelPosition placement = LP_Right, QWidget* parent = nullptr);
19 |
20 | protected:
21 | QSize sizeHint() const;
22 | void paintEvent(QPaintEvent* event);
23 | QColor getColor();
24 | QIcon getIcon();
25 |
26 | private:
27 | LabelPosition _placement;
28 | };
29 |
30 | EL_END_NAMESPACE
31 |
32 | #endif // EL_CHECKBOX_H
33 |
--------------------------------------------------------------------------------
/qelement/el_lineprogress.h:
--------------------------------------------------------------------------------
1 | #ifndef LINEPROGRESS_H
2 | #define LINEPROGRESS_H
3 |
4 | #include "el_global.h"
5 | #include
6 |
7 | EL_BEGIN_NAMESPACE
8 |
9 | // 线形进度条
10 | class EL_EXPORT LineProgress : public QProgressBar {
11 | Q_OBJECT
12 | public:
13 | // 进度条状态
14 | enum Status {
15 | Default,
16 | Success,
17 | Warning,
18 | Exception
19 | };
20 | Q_ENUM(Status)
21 |
22 | LineProgress(QWidget* parent = nullptr);
23 | // 设置进度条当前状态
24 | void setStatus(Status status);
25 |
26 | protected:
27 | void paintEvent(QPaintEvent*) Q_DECL_OVERRIDE;
28 | QColor getColor();
29 |
30 | private:
31 | Status _status = Default;
32 | };
33 |
34 | EL_END_NAMESPACE
35 |
36 | #endif // LINEPROGRESS_H
37 |
--------------------------------------------------------------------------------
/example/example.pro:
--------------------------------------------------------------------------------
1 | QT += core gui
2 |
3 | greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
4 |
5 | CONFIG += c++17
6 |
7 | QMAKE_CFLAGS += /utf-8
8 | QMAKE_CXXFLAGS += /utf-8
9 |
10 | include(../qelement/qelement.pri)
11 |
12 | # You can make your code fail to compile if it uses deprecated APIs.
13 | # In order to do so, uncomment the following line.
14 | #DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0
15 |
16 | SOURCES += \
17 | main.cpp \
18 | widget.cpp
19 |
20 | HEADERS += \
21 | widget.h
22 |
23 | FORMS += \
24 | widget.ui
25 |
26 | # Default rules for deployment.
27 | qnx: target.path = /tmp/$${TARGET}/bin
28 | else: unix:!android: target.path = /opt/$${TARGET}/bin
29 | !isEmpty(target.path): INSTALLS += target
30 |
31 | RESOURCES += \
32 | resource.qrc
33 |
--------------------------------------------------------------------------------
/qelement/el_circleprogress.h:
--------------------------------------------------------------------------------
1 | #ifndef EL_CIRCLEPROGRESS_H
2 | #define EL_CIRCLEPROGRESS_H
3 |
4 | #include "el_global.h"
5 | #include
6 |
7 | EL_BEGIN_NAMESPACE
8 |
9 | // 环形进度条
10 | class EL_EXPORT CircleProgress : public QWidget {
11 | Q_OBJECT
12 | public:
13 | // 进度条状态
14 | enum Status {
15 | Default,
16 | Success,
17 | Warning,
18 | Exception
19 | };
20 | Q_ENUM(Status)
21 |
22 | explicit CircleProgress(QWidget* parent = nullptr);
23 | void setPercent(int percent);
24 | // 设置进度条当前状态
25 | void setStatus(Status status);
26 |
27 | protected:
28 | void paintEvent(QPaintEvent*);
29 | QSize sizeHint() const;
30 | QColor getColor();
31 |
32 | private:
33 | int _percent = 0;
34 | int _rotateAngle = 0;
35 | Status _status = Default;
36 | };
37 |
38 | EL_END_NAMESPACE
39 |
40 | #endif // EL_CIRCLEPROGRESS_H
41 |
--------------------------------------------------------------------------------
/qelement/el_imageprovider.h:
--------------------------------------------------------------------------------
1 | #ifndef EL_IMAGEPROVIDER_H
2 | #define EL_IMAGEPROVIDER_H
3 |
4 | #include
5 | #include
6 | #include
7 |
8 | #include "el_global.h"
9 |
10 | EL_BEGIN_NAMESPACE
11 |
12 | class ImageRunnable : public QObject, public QRunnable {
13 | Q_OBJECT
14 | public:
15 | ImageRunnable(const QString& url, const QString& fileName);
16 | void run();
17 |
18 | signals:
19 | void taskStart(QString, QString);
20 | void taskEnd(QString, QString);
21 |
22 | private:
23 | QString _url;
24 | QString _fileName;
25 | };
26 |
27 | class ImageProvider : public QObject {
28 | Q_OBJECT
29 | public:
30 | explicit ImageProvider(QObject* parent = nullptr);
31 | ~ImageProvider();
32 | void getNetworkImage(const QString& url);
33 | QString generateId(const QString& url);
34 |
35 | signals:
36 | void imageReady(QString url, QString filePath);
37 |
38 | private:
39 | QThreadPool* _pool = nullptr;
40 | QString _cacheDir;
41 | };
42 |
43 | EL_END_NAMESPACE
44 |
45 | #endif // EL_IMAGEPROVIDER_H
46 |
--------------------------------------------------------------------------------
/qelement/el_link.h:
--------------------------------------------------------------------------------
1 | #ifndef EL_LINK_H
2 | #define EL_LINK_H
3 |
4 | #include "el_global.h"
5 | #include
6 |
7 | EL_BEGIN_NAMESPACE
8 |
9 | // Link 文字链接
10 | class EL_EXPORT Link : public QLabel {
11 |
12 | Q_OBJECT
13 | public:
14 | enum Type {
15 | Default, // 默认链接
16 | Primary, // 主要链接
17 | Success, // 成功链接
18 | Warning, // 警告链接
19 | Danger, // 危险链接
20 | Info // 信息链接
21 | };
22 | Q_ENUM(Type)
23 |
24 | Link(const QString& text, const QString link, Type type = Default, QWidget* parent = nullptr);
25 | void setLink(const QString& link);
26 | QString getLink();
27 |
28 | signals:
29 | void linkClicked(const QString& link);
30 |
31 | protected:
32 | void mousePressEvent(QMouseEvent* event);
33 | QSize sizeHint() const;
34 | void enterEvent(QEvent* event);
35 | void leaveEvent(QEvent* event);
36 |
37 | QString getColor(Type type);
38 | QString getDisabledColor(Type type);
39 |
40 | private:
41 | QString _link;
42 | };
43 |
44 | EL_END_NAMESPACE
45 |
46 | #endif // EL_LINK_H
47 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2024 hk0x
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/qelement/el_lineprogress.cpp:
--------------------------------------------------------------------------------
1 | #include "el_lineprogress.h"
2 | #include
3 |
4 | EL_BEGIN_NAMESPACE
5 |
6 | LineProgress::LineProgress(QWidget* parent)
7 | : QProgressBar(parent)
8 | {
9 | setMinimum(0);
10 | setMaximum(100);
11 | setValue(0);
12 | }
13 |
14 | void LineProgress::setStatus(Status status)
15 | {
16 | _status = status;
17 | }
18 |
19 | void LineProgress::paintEvent(QPaintEvent*)
20 | {
21 | QPainter painter(this);
22 | QRect rect = QRect(0, 0, width(), height() / 2);
23 | // QRect textRect = QRect(0, height() / 2, width(), height() / 2);
24 |
25 | const double k = (double)(value() - minimum()) / (maximum() - minimum());
26 | int x = (int)(rect.width() * k);
27 | QRect fillRect = rect.adjusted(0, 0, x - rect.width(), 0);
28 |
29 | painter.fillRect(rect, QBrush(QColor(0xebeef5)));
30 | painter.fillRect(fillRect, QBrush(getColor()));
31 | }
32 |
33 | QColor LineProgress::getColor()
34 | {
35 | switch (_status) {
36 | case Default:
37 | return QColor(0x409eff);
38 | case Success:
39 | return QColor(0x67c23a);
40 | case Warning:
41 | return QColor(0xe6a23c);
42 | case Exception:
43 | return QColor(0xf56c6c);
44 | }
45 | }
46 |
47 | EL_END_NAMESPACE
48 |
--------------------------------------------------------------------------------
/qelement/qelement.pri:
--------------------------------------------------------------------------------
1 |
2 | QT += network
3 |
4 | CONFIG += fontAwesomeFree
5 |
6 | include($$PWD/../QtAwesome/QtAwesome/QtAwesome.pri)
7 |
8 | INCLUDEPATH += $$PWD/../FramelessWindow
9 |
10 | INCLUDEPATH += $$PWD
11 |
12 | HEADERS += \
13 | $$PWD/el_avatar.h \
14 | $$PWD/el_awesome.h \
15 | $$PWD/el_button.h \
16 | $$PWD/el_card.h \
17 | $$PWD/el_checkbox.h \
18 | $$PWD/el_circleprogress.h \
19 | $$PWD/el_global.h \
20 | $$PWD/el_imageprovider.h \
21 | $$PWD/el_inputnumber.h \
22 | $$PWD/el_lineprogress.h \
23 | $$PWD/el_link.h \
24 | $$PWD/el_input.h \
25 | $$PWD/el_messagebox.h \
26 | $$PWD/el_radio.h \
27 | $$PWD/el_select.h \
28 | $$PWD/el_slider.h \
29 | $$PWD/el_style.h \
30 | $$PWD/el_switch.h \
31 |
32 | SOURCES += \
33 | $$PWD/el_avatar.cpp \
34 | $$PWD/el_button.cpp \
35 | $$PWD/el_card.cpp \
36 | $$PWD/el_checkbox.cpp \
37 | $$PWD/el_circleprogress.cpp \
38 | $$PWD/el_imageprovider.cpp \
39 | $$PWD/el_inputnumber.cpp \
40 | $$PWD/el_lineprogress.cpp \
41 | $$PWD/el_link.cpp \
42 | $$PWD/el_input.cpp \
43 | $$PWD/el_messagebox.cpp \
44 | $$PWD/el_radio.cpp \
45 | $$PWD/el_select.cpp \
46 | $$PWD/el_slider.cpp \
47 | $$PWD/el_switch.cpp \
48 |
49 | RESOURCES += \
50 | $$PWD/qelement.qrc
51 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Element3 风格 Qt Widgets
2 |
3 | [Element3](https://e3.shengxinjing.cn/#/),一套为开发者、设计师和产品经理准备的基于 Vue 3.0 的桌面端组件库
4 |
5 | 部分控件通过QSS方式实现,部分通过重写QWidget的paintEvent方式实现
6 |
7 | ## Button 按钮
8 | - 默认按钮
9 |
10 | 
11 |
12 | - 圆角按钮
13 |
14 | 
15 |
16 | - 图标按钮
17 |
18 | 
19 |
20 | ## Checkbox 多选框
21 |
22 | 
23 |
24 | ## Radio 单选框
25 |
26 | 
27 |
28 | ## Switch 开关
29 |
30 | 
31 |
32 | ## Avatar 头像
33 |
34 | 
35 |
36 | ## InputNumber 计数器
37 |
38 | 
39 |
40 | ## Card 卡片
41 |
42 | 
43 |
44 | ## Slider 滑块
45 |
46 | 
47 |
48 | ## MessageBox 弹框
49 |
50 | - 消息提示
51 |
52 | 
53 |
54 | - 错误提示
55 |
56 | 
57 |
58 | ## Progress 进度条
59 |
60 | - 线形进度条
61 |
62 | 
63 |
64 | - 环形进度条
65 |
66 | 
67 |
68 | ## 已实现组件
69 |
70 | - [x] Button 按钮
71 | - [x] Checkbox 多选框
72 | - [x] Radio 单选框
73 | - [x] Input 输入框
74 | - [x] InputNumber 计数器
75 | - [x] Select 选择器
76 | - [x] Link 文字链接
77 | - [x] Switch 开关
78 | - [x] Avatar 头像
79 | - [x] MessageBox 弹框
80 | - [x] Slider 滑块
81 | - [x] Progress 进度条
82 |
83 | ## 未实现组件
84 |
85 | - [ ] Tabs 标签页
86 | - [ ] Badge 标记
87 | - [ ] Table 表格
88 | - [ ] Tag 标签
89 | - [ ] Alert 警告
90 | - [ ] Loading 加载
91 | - [ ] Tooltip 文字提示
92 |
--------------------------------------------------------------------------------
/qelement/el_avatar.h:
--------------------------------------------------------------------------------
1 | #ifndef EL_AVATAR_H
2 | #define EL_AVATAR_H
3 |
4 | #include "el_global.h"
5 | #include "el_imageprovider.h"
6 |
7 | #include
8 | #include
9 | #include
10 |
11 | EL_BEGIN_NAMESPACE
12 |
13 | // Avatar 头像
14 | class EL_EXPORT Avatar : public QWidget {
15 | Q_OBJECT
16 | public:
17 | enum Type {
18 | Icon, // 图标
19 | Image, // 图片
20 | Letter, // 字符
21 | };
22 | Q_ENUM(Type)
23 |
24 | explicit Avatar(QWidget* parent = nullptr);
25 | explicit Avatar(const QIcon& icon, QWidget* parent = 0);
26 | explicit Avatar(const QString& letter, QWidget* parent = 0);
27 | explicit Avatar(const QImage& image, QWidget* parent = 0);
28 |
29 | QSize sizeHint() const Q_DECL_OVERRIDE;
30 |
31 | void setSize(int size);
32 | int size() const;
33 |
34 | void setLetter(const QString& letter);
35 | void setImage(const QImage& image);
36 | void setIcon(const QIcon& icon);
37 |
38 | void setUrl(const QString& url);
39 |
40 | Type type() const;
41 |
42 | protected:
43 | void paintEvent(QPaintEvent* event) Q_DECL_OVERRIDE;
44 |
45 | protected slots:
46 | void onImageReady(QString url, QString filePath);
47 |
48 | private:
49 | int _size = 40;
50 | Type _type = Letter;
51 | QString _letter;
52 | QImage _image;
53 | QIcon _icon;
54 | QPixmap _pixmap;
55 | ImageProvider _provider;
56 | };
57 |
58 | EL_END_NAMESPACE
59 |
60 | #endif // EL_AVATAR_H
61 |
--------------------------------------------------------------------------------
/qelement/el_select.cpp:
--------------------------------------------------------------------------------
1 | #include "el_select.h"
2 | #include
3 | #include
4 |
5 | EL_BEGIN_NAMESPACE
6 |
7 | Select::Select(QWidget* parent)
8 | : QComboBox(parent)
9 | {
10 | setItemDelegate(new QStyledItemDelegate());
11 | QString styleSheet;
12 | styleSheet += "QComboBox { border: 1px solid #dcdfe6; border-radius: 4px; background-color: white;}";
13 | styleSheet += "QComboBox:on { border: 1px solid #409eff;}";
14 | styleSheet += "QComboBox { color: #606266; font-family: Microsoft YaHei; font-size: 14px; padding-left: 15px;}";
15 | styleSheet += "QComboBox QAbstractItemView { border: 1px solid #dcdfe6; border-radius: 4px; background-color: white; outline: 0px;}";
16 | styleSheet += "QComboBox QAbstractItemView::item { color: #606266; font-family: Microsoft YaHei; font-size: 14px; height: 34px;}";
17 | styleSheet += "QComboBox QAbstractItemView::item:hover { color: #606266; background-color: #f5f7fa; padding-left: 15px;}";
18 | styleSheet += "QComboBox QAbstractItemView::item:selected {color: #409eff;}";
19 | styleSheet += "QComboBox::drop-down { subcontrol-origin: padding; subcontrol-position: center right; width: 14px; height: 14px; border: none; image: url(:/images/arrow-down.png); padding-right: 8px;}";
20 | styleSheet += "QComboBox::drop-down:on { image: url(:/images/arrow-up.png);}";
21 | setStyleSheet(styleSheet);
22 | }
23 |
24 | QSize Select::sizeHint() const
25 | {
26 | return QSize(200, 40);
27 | }
28 |
29 | void Select::showPopup()
30 | {
31 | QComboBox::showPopup();
32 | QWidget* popup = this->findChild();
33 | if (popup != NULL) {
34 | popup->move(popup->pos().x(), popup->pos().y() + 4);
35 | }
36 | }
37 | EL_END_NAMESPACE
38 |
--------------------------------------------------------------------------------
/qelement/el_circleprogress.cpp:
--------------------------------------------------------------------------------
1 | #include "el_circleprogress.h"
2 | #include
3 |
4 | EL_BEGIN_NAMESPACE
5 |
6 | CircleProgress::CircleProgress(QWidget* parent)
7 | : QWidget { parent }
8 | {
9 | }
10 |
11 | void CircleProgress::setPercent(int percent)
12 | {
13 | if (_percent != percent) {
14 | _percent = percent;
15 | update();
16 | }
17 | }
18 |
19 | void CircleProgress::setStatus(Status status)
20 | {
21 | _status = status;
22 | }
23 |
24 | void CircleProgress::paintEvent(QPaintEvent*)
25 | {
26 | QPainter p(this);
27 | p.setRenderHint(QPainter::Antialiasing);
28 |
29 | _rotateAngle = 360 * _percent / 100;
30 |
31 | int side = qMin(width(), height());
32 | QRectF outRect(0, 0, side, side);
33 | QRectF inRect(10, 10, side - 20, side - 20);
34 | QString valueStr = QString("%1%").arg(QString::number(_percent));
35 |
36 | //画外圆
37 | p.setPen(Qt::NoPen);
38 | p.setBrush(QBrush(QColor(0xebeef5)));
39 | p.drawEllipse(outRect);
40 | p.setBrush(QBrush(getColor()));
41 | p.drawPie(outRect, (90 - _rotateAngle) * 16, _rotateAngle * 16);
42 | //画遮罩
43 | p.setBrush(palette().window().color());
44 | p.drawEllipse(inRect);
45 | //画文字
46 | QFont f = QFont("Microsoft YaHei");
47 | f.setPixelSize(14);
48 | p.setFont(f);
49 | p.setPen(QColor(0x606266));
50 | p.drawText(inRect, Qt::AlignCenter, valueStr);
51 | }
52 |
53 | QSize CircleProgress::sizeHint() const
54 | {
55 | return QSize(120, 120);
56 | }
57 |
58 | QColor CircleProgress::getColor()
59 | {
60 | switch (_status) {
61 | case Default:
62 | return QColor(0x409eff);
63 | case Success:
64 | return QColor(0x67c23a);
65 | case Warning:
66 | return QColor(0xe6a23c);
67 | case Exception:
68 | return QColor(0xf56c6c);
69 | }
70 | }
71 |
72 | EL_END_NAMESPACE
73 |
--------------------------------------------------------------------------------
/qelement/el_style.h:
--------------------------------------------------------------------------------
1 | #ifndef EL_STYLE_H
2 | #define EL_STYLE_H
3 |
4 | #include "el_global.h"
5 |
6 | EL_BEGIN_NAMESPACE
7 |
8 | // Color 色彩
9 | // https://e3.shengxinjing.cn/#/component/color
10 | namespace Color {
11 | // 主色
12 | const Q_DECL_UNUSED char Brand[] = "#409EFF";
13 | // 辅助色 除了主色外的场景色,需要在不同的场景中使用(例如危险色表示危险的操作)
14 | const Q_DECL_UNUSED char Success[] = "#67C23A";
15 | const Q_DECL_UNUSED char SuccessDisabled[] = "#b3e19d";
16 | const Q_DECL_UNUSED char Warning[] = "#E6A23C";
17 | const Q_DECL_UNUSED char WarningDisabled[] = "#f3d19e";
18 | const Q_DECL_UNUSED char Danger[] = "#F56C6C";
19 | const Q_DECL_UNUSED char DangerDisabled[] = "#fab6b6";
20 | const Q_DECL_UNUSED char Info[] = "#909399";
21 | const Q_DECL_UNUSED char InfoDisabled[] = "#c8c9cc";
22 | // 中性色
23 | // 中性色用于文本、背景和边框颜色。通过运用不同的中性色,来表现层次结构
24 | // 主要文字
25 | const Q_DECL_UNUSED char PrimaryText[] = "#303133";
26 | const Q_DECL_UNUSED char PrimaryTextDisabled[] = "#a0cfff";
27 | // 常规文字
28 | const Q_DECL_UNUSED char DefaultText[] = "#606266";
29 | const Q_DECL_UNUSED char DefaultTextDisabled[] = "#c0c4cc";
30 | // 次要文字
31 | const Q_DECL_UNUSED char SecondaryText[] = "#909399";
32 | //占位文字
33 | const Q_DECL_UNUSED char PlaceholderText[] = "#C0C4CC";
34 | }
35 |
36 | // Border 边框
37 | // https://e3.shengxinjing.cn/#/component/border
38 | namespace Border {
39 | // 无圆角
40 | const Q_DECL_UNUSED int None = 0;
41 | // 小圆角
42 | const Q_DECL_UNUSED int Small = 2;
43 | // 大圆角
44 | const Q_DECL_UNUSED int Big = 4;
45 | // 圆形圆角
46 | const Q_DECL_UNUSED int Circle = 30;
47 | }
48 |
49 | // 字号 (像素px)
50 | namespace FontSize {
51 | // 辅助文字
52 | const Q_DECL_UNUSED int ExtraSamll = 12;
53 | // 正文(小)
54 | const Q_DECL_UNUSED int Samll = 13;
55 | // 正文
56 | const Q_DECL_UNUSED int Base = 14;
57 | // 小标题
58 | const Q_DECL_UNUSED int Medium = 16;
59 | // 标题
60 | const Q_DECL_UNUSED int Large = 18;
61 | // 主标题
62 | const Q_DECL_UNUSED int ExtraLarge = 20;
63 | }
64 |
65 | EL_END_NAMESPACE
66 |
67 | #endif // EL_STYLE_H
68 |
--------------------------------------------------------------------------------
/qelement/el_switch.h:
--------------------------------------------------------------------------------
1 |
2 | #ifndef EL_SWITCH_H
3 | #define EL_SWITCH_H
4 |
5 | #include "el_global.h"
6 | #include
7 |
8 | QT_BEGIN_NAMESPACE
9 | class QPropertyAnimation;
10 | QT_END_NAMESPACE
11 |
12 | EL_BEGIN_NAMESPACE
13 |
14 | // Switch 开关
15 | class EL_EXPORT Switch final : public QAbstractButton {
16 | Q_OBJECT
17 | Q_PROPERTY(int thumbPosition READ thumbPosition WRITE setThumbPosition NOTIFY thumbPositionChanged FINAL)
18 |
19 | public:
20 | explicit Switch(QWidget* const parent = nullptr);
21 | explicit Switch(const QString& text, QWidget* const parent = nullptr);
22 | virtual ~Switch() = default;
23 | // 设置背景 激活/未激活 颜色
24 | void setTrackColor(const QColor& trackOnColor, const QColor& trackOffColor);
25 | // 设置滑块 激活/未激活 颜色
26 | void setThumbColor(const QColor& thumbOnColor, const QColor& thumbOffColor);
27 | void setHieght(int nHeight);
28 | void setRadius(qreal corner_radius, qreal thumb_radius);
29 |
30 | virtual QSize sizeHint() const override;
31 |
32 | signals:
33 | void stateChanged(int);
34 | void thumbPositionChanged();
35 |
36 | protected:
37 | QRect indicatorRect();
38 | QRect textRect();
39 |
40 | virtual void paintEvent(QPaintEvent* const) override;
41 | virtual void nextCheckState() override;
42 | virtual void checkStateSet() override;
43 |
44 | void toggle(const Qt::CheckState& state);
45 |
46 | private:
47 | void setThumbPosition(const int& thumbPosition);
48 | int thumbPosition();
49 |
50 | qreal CORNER_RADIUS, THUMB_RADIUS, SHADOW_ELEVATION;
51 | int height;
52 | QMargins indicatorMargin;
53 |
54 | QColor trackOnColor, trackOffColor,
55 | thumbOnColor, thumbOffColor,
56 | trackDisabledColor, thumbDisabledColor;
57 | qreal trackDisabledOpacity, disabledTextOpacity;
58 |
59 | QPropertyAnimation* const thumbPosAnimation;
60 | int _thumbPosition;
61 | QPixmap shadowPixmap;
62 | };
63 |
64 | EL_END_NAMESPACE
65 |
66 | #endif // EL_SWITCH_H
67 |
--------------------------------------------------------------------------------
/qelement/el_button.h:
--------------------------------------------------------------------------------
1 | #ifndef EL_BUTTON_H
2 | #define EL_BUTTON_H
3 |
4 | #include "el_global.h"
5 | #include
6 |
7 | EL_BEGIN_NAMESPACE
8 |
9 | // Button 按钮
10 | class EL_EXPORT Button : public QPushButton {
11 | Q_OBJECT
12 | public:
13 | enum ButtonType {
14 | BT_Default, // 默认按钮
15 | BT_Primary, // 主要按钮
16 | BT_Success, // 成功按钮
17 | BT_Warning, // 警告按钮
18 | BT_Danger, // 危险按钮
19 | BT_Info // 信息按钮
20 | };
21 | Q_ENUM(ButtonType)
22 |
23 | enum ButtonStyle {
24 | BS_Default, // 默认
25 | BS_Round, // 圆角
26 | BS_Circle // 圆形
27 | };
28 | Q_ENUM(ButtonStyle)
29 |
30 | explicit Button(QWidget *parent = nullptr);
31 | // 默认按钮
32 | Button(const QString& text, ButtonType type = BT_Default, ButtonStyle style = BS_Default, QWidget* parent = nullptr);
33 | // 图标按钮
34 | Button(const QIcon& icon, ButtonType type = BT_Default, ButtonStyle style = BS_Default, QWidget* parent = nullptr);
35 | // 文字图标按钮
36 | Button(const QString& text, const QIcon& icon, ButtonType type = BT_Default, ButtonStyle style = BS_Default, QWidget* parent = nullptr);
37 | // FontAwesome图标按钮
38 | Button(int character, ButtonType type = BT_Default, ButtonStyle style = BS_Circle, QWidget* parent = nullptr);
39 | // FontAwesome文字图标按钮
40 | Button(const QString& text, int character, ButtonType type = BT_Default, ButtonStyle style = BS_Default, QWidget* parent = nullptr);
41 |
42 | void init(ButtonType type = BT_Default, ButtonStyle style = BS_Default);
43 | void init(const QIcon& icon, ButtonType type = BT_Default, ButtonStyle style = BS_Default);
44 | void init(int character, ButtonType type = BT_Default, ButtonStyle style = BS_Circle);
45 | protected:
46 | QSize sizeHint() const;
47 |
48 | QString getBorderStyle(ButtonType type, ButtonStyle style);
49 | QString getColorStyle(ButtonType type);
50 | QString getBkColorStyle(ButtonType type);
51 | };
52 |
53 | EL_END_NAMESPACE
54 |
55 | #endif // EL_BUTTON_H
56 |
--------------------------------------------------------------------------------
/qelement/el_input.cpp:
--------------------------------------------------------------------------------
1 | #include "el_input.h"
2 | #include "el_awesome.h"
3 | #include "el_style.h"
4 | #include
5 | #include
6 |
7 | EL_BEGIN_NAMESPACE
8 |
9 | Input::Input(Type type, QWidget* parent)
10 | : QLineEdit(parent)
11 | {
12 | QString styleSheet;
13 | styleSheet += "QLineEdit { border: 1px solid #dcdfe6; border-radius: 4px; }";
14 | styleSheet += "QLineEdit:focus { border: 1px solid #409eff; }";
15 | styleSheet += "QLineEdit { font-family: Microsoft YaHei; font-size: 14px; }";
16 | styleSheet += "QLineEdit { padding-left: 15px; padding-right: 15px; }";
17 | styleSheet += "QLineEdit { color: #606266; min-height: 40px; }";
18 |
19 | setStyleSheet(styleSheet);
20 | QVariantMap options;
21 | options.insert("color", QColor(Color::PlaceholderText));
22 | options.insert("color-active", QColor(Color::SecondaryText));
23 |
24 | if (type == Type::Clearable) {
25 | QAction* clearAction = new QAction;
26 | clearAction->setIcon(qAwesome->icon(fa::fa_solid, fa::fa_xmark_circle, options));
27 | addAction(clearAction, QLineEdit::TrailingPosition);
28 | connect(clearAction, &QAction::triggered, this, [this] { this->clear(); });
29 | } else if (type == Type::ShowPassword) {
30 | setEchoMode(QLineEdit::Password);
31 | QAction* showPasswordAction = new QAction;
32 | showPasswordAction->setCheckable(true);
33 | showPasswordAction->setIcon(qAwesome->icon(fa::fa_solid, fa::fa_eye, options));
34 | addAction(showPasswordAction, QLineEdit::TrailingPosition);
35 | connect(showPasswordAction, &QAction::triggered, this, [this](bool show) { this->setEchoMode(show ? QLineEdit::Normal : QLineEdit::Password); });
36 | } else if (type == Type::Calendar) {
37 | QAction* calendarAction = new QAction;
38 | calendarAction->setIcon(qAwesome->icon(fa::fa_solid, fa::fa_calendar_days, options));
39 | calendarAction->setCheckable(true);
40 | addAction(calendarAction, QLineEdit::TrailingPosition);
41 | connect(calendarAction, &QAction::triggered, this, [this](bool show) {
42 | // TODO: 显示日历控件
43 | });
44 | }
45 | }
46 |
47 | EL_END_NAMESPACE
48 |
--------------------------------------------------------------------------------
/qelement/el_messagebox.h:
--------------------------------------------------------------------------------
1 | #ifndef MESSAGEBOX_H
2 | #define MESSAGEBOX_H
3 |
4 | #include "FramelessWindow.hpp"
5 | #include "el_global.h"
6 | #include
7 |
8 | class QLabel;
9 | class QHBoxLayout;
10 | class QPushButton;
11 |
12 | EL_BEGIN_NAMESPACE
13 |
14 | // MessageBox 弹框
15 | class EL_EXPORT MessageBox : public FramelessWindow {
16 | Q_OBJECT
17 | public:
18 | enum StandardButton {
19 | NoButton = 1 << 0, // 无按钮
20 | Ok = 1 << 1, // 确定
21 | Yes = 1 << 2, // 是
22 | No = 1 << 3, // 否
23 | Close = 1 << 4, // 关闭
24 | Cancel = 1 << 5, // 取消
25 |
26 | FirstButton = Ok,
27 | LastButton = Cancel,
28 | };
29 |
30 | Q_DECLARE_FLAGS(StandardButtons, StandardButton)
31 | Q_FLAG(StandardButtons)
32 |
33 | typedef QMap ButtonText;
34 |
35 | MessageBox(const QIcon& icon, const QString& title, const QString& text, QWidget* parent = nullptr);
36 |
37 | // 消息提示
38 | static int alert(QWidget* parent, const QString& title, const QString& text, const QString& confirmButtonText);
39 | // 确认消息
40 | static int confirm(QWidget* parent, const QString& title, const QString& text,
41 | const QString& confirmButtonText, const QString& cancelButtonText);
42 | // 错误消息
43 | static int error(QWidget* parent, const QString& title, const QString& text, const QString& confirmButtonText);
44 |
45 | protected:
46 | static StandardButton showNewMessageBox(QWidget* parent, const QIcon& icon, const QString& title, const QString& text,
47 | StandardButtons buttons, StandardButton defaultButton, ButtonText buttonText);
48 | QPushButton* addButton(StandardButton button, const QString& buttonText);
49 | void init(const QIcon& icon, const QString& title, const QString& text);
50 | void setupLayout();
51 | void setText(const QString& text);
52 | void setIcon(const QIcon& icon);
53 | void setDefaultButton(QPushButton* button);
54 | QPushButton* closeButton();
55 |
56 | private:
57 | QLabel* _iconLabel = nullptr;
58 | QLabel* _label = nullptr;
59 | QLabel* _titleLabel = nullptr;
60 | QLabel* _titleIcon = nullptr;
61 | QHBoxLayout* _buttonBox = nullptr;
62 | };
63 |
64 | Q_DECLARE_OPERATORS_FOR_FLAGS(MessageBox::StandardButtons)
65 |
66 | EL_END_NAMESPACE
67 |
68 | #endif // MESSAGEBOX_H
69 |
--------------------------------------------------------------------------------
/qelement/el_link.cpp:
--------------------------------------------------------------------------------
1 | #include "el_link.h"
2 | #include "el_style.h"
3 | #include
4 |
5 | EL_BEGIN_NAMESPACE
6 |
7 | Link::Link(const QString& text, const QString link, Type type, QWidget* parent)
8 | : QLabel(text, parent)
9 | , _link(link)
10 | {
11 | QWidget::setAttribute(Qt::WA_TranslucentBackground);
12 | QString styleSheet;
13 | styleSheet += QString("QLabel { color : %1;font-family: Microsoft YaHei;font-size: 14px;}").arg(getColor(type));
14 | styleSheet += QString("QLabel::disabled { color : %1;}").arg(getDisabledColor(type));
15 | setStyleSheet(styleSheet);
16 | setMouseTracking(true);
17 | }
18 |
19 | void Link::setLink(const QString& url)
20 | {
21 | _link = url;
22 | }
23 |
24 | QString Link::getLink()
25 | {
26 | return _link;
27 | }
28 |
29 | void Link::mousePressEvent(QMouseEvent* event)
30 | {
31 | Q_UNUSED(event);
32 | emit linkClicked(_link);
33 | }
34 |
35 | QSize Link::sizeHint() const
36 | {
37 | QFont font("Microsoft YaHei");
38 | font.setPixelSize(14);
39 | QFontMetrics metrics(font);
40 | return QSize(metrics.boundingRect(text()).size().width() + 30, 40);
41 | }
42 |
43 | void Link::enterEvent(QEvent* event)
44 | {
45 | setCursor(Qt::PointingHandCursor);
46 | QLabel::enterEvent(event);
47 | }
48 |
49 | void Link::leaveEvent(QEvent* event)
50 | {
51 | setCursor(Qt::ArrowCursor);
52 | QLabel::leaveEvent(event);
53 | }
54 |
55 | QString Link::getColor(Type type)
56 | {
57 | switch (type) {
58 | case Default:
59 | return Color::DefaultText;
60 | case Primary:
61 | return Color::PrimaryText;
62 | case Success:
63 | return Color::Success;
64 | case Warning:
65 | return Color::Warning;
66 | case Danger:
67 | return Color::Danger;
68 | case Info:
69 | return Color::Info;
70 | default:
71 | return Color::DefaultText;
72 | }
73 | }
74 |
75 | QString Link::getDisabledColor(Type type)
76 | {
77 | switch (type) {
78 | case Default:
79 | return Color::DefaultTextDisabled;
80 | case Primary:
81 | return Color::PrimaryTextDisabled;
82 | case Success:
83 | return Color::SuccessDisabled;
84 | case Warning:
85 | return Color::WarningDisabled;
86 | case Danger:
87 | return Color::DangerDisabled;
88 | case Info:
89 | return Color::InfoDisabled;
90 | default:
91 | return Color::DefaultTextDisabled;
92 | }
93 | }
94 |
95 | EL_END_NAMESPACE
96 |
--------------------------------------------------------------------------------
/qelement/el_imageprovider.cpp:
--------------------------------------------------------------------------------
1 | #include "el_imageprovider.h"
2 | #include
3 | #include
4 | #include
5 | #include
6 | #include
7 | #include
8 |
9 | EL_BEGIN_NAMESPACE
10 |
11 | ImageRunnable::ImageRunnable(const QString& url, const QString& fileName)
12 | : _url(url)
13 | , _fileName(fileName)
14 | {
15 | }
16 |
17 | void ImageRunnable::run()
18 | {
19 | emit taskStart(_url, _fileName);
20 |
21 | QNetworkAccessManager manager;
22 | QNetworkRequest request;
23 | request.setUrl(QUrl(_url));
24 |
25 | QEventLoop eventLoop;
26 | QObject::connect(&manager, SIGNAL(finished(QNetworkReply*)), &eventLoop, SLOT(quit()));
27 | QNetworkReply* reply = manager.get(request);
28 | eventLoop.exec();
29 |
30 | if (reply->error() != QNetworkReply::NoError) {
31 | qDebug() << "Download Failed at {}\n"
32 | << _url;
33 | }
34 |
35 | QFile file(_fileName);
36 | if (!file.open(QIODevice::WriteOnly)) {
37 | qDebug() << "Failed to write " << _fileName;
38 | }
39 | file.write(reply->readAll());
40 | file.flush();
41 | file.close();
42 | qDebug() << "Download compeleted: " << _fileName;
43 |
44 | emit taskEnd(_url, _fileName);
45 | }
46 |
47 | ImageProvider::ImageProvider(QObject* parent)
48 | : QObject { parent }
49 | {
50 | _pool = new QThreadPool(this);
51 | QString appDataDir = QStandardPaths::standardLocations(QStandardPaths::AppDataLocation).first();
52 | _cacheDir = appDataDir + "/imagecached";
53 | QDir dir(_cacheDir);
54 | if (!dir.exists()) {
55 | dir.mkpath(_cacheDir);
56 | }
57 | }
58 |
59 | ImageProvider::~ImageProvider()
60 | {
61 | _pool->clear();
62 | _pool->waitForDone();
63 | }
64 |
65 | void ImageProvider::getNetworkImage(const QString& url)
66 | {
67 | QString id = generateId(url);
68 | QString filePath = _cacheDir + "/" + id;
69 | if (QFile::exists(filePath)) {
70 | emit imageReady(url, filePath);
71 | return;
72 | }
73 | ImageRunnable* runnable = new ImageRunnable(url, filePath);
74 | runnable->setAutoDelete(true);
75 | connect(runnable, &ImageRunnable::taskEnd, this, &ImageProvider::imageReady);
76 | _pool->start(runnable);
77 | }
78 |
79 | QString ImageProvider::generateId(const QString& url)
80 | {
81 | return QString(QCryptographicHash::hash(url.toUtf8(), QCryptographicHash::Md5).toHex());
82 | }
83 |
84 | EL_END_NAMESPACE
85 |
--------------------------------------------------------------------------------
/qelement/el_radio.cpp:
--------------------------------------------------------------------------------
1 | #include "el_radio.h"
2 | #include "el_awesome.h"
3 | #include
4 |
5 | EL_BEGIN_NAMESPACE
6 |
7 | Radio::Radio(const QString& text, LabelPosition placement, QWidget* parent)
8 | : QAbstractButton(parent)
9 | , _placement(placement)
10 | {
11 | setText(text);
12 | setCursor(Qt::PointingHandCursor);
13 | setCheckable(true);
14 | }
15 |
16 | QSize Radio::sizeHint() const
17 | {
18 | if (text().isEmpty()) {
19 | return QSize(40, 40);
20 | }
21 | QFont font("Microsoft YaHei");
22 | font.setPixelSize(14);
23 | QFontMetrics metrics(font);
24 | return QSize(metrics.boundingRect(text()).size().width() + 30, 40);
25 | }
26 |
27 | QColor Radio::getColor()
28 | {
29 | if (isEnabled()) {
30 | if (isChecked()) {
31 | return QColor(0x409eff);
32 | } else {
33 | return QColor(0x606266);
34 | }
35 | } else {
36 | return QColor(0xc0c4cc);
37 | }
38 | }
39 |
40 | QIcon Radio::getIcon()
41 | {
42 | if (isEnabled()) {
43 | if (isChecked()) {
44 | return qAwesome->icon(fa::fa_solid, fa::fa_circle_dot,
45 | { { "color", QColor(0x409eff) } });
46 | } else {
47 | return qAwesome->icon(fa::fa_regular, fa::fa_o,
48 | { { "color", QColor(0x606266) } });
49 | }
50 | } else {
51 | if (isChecked()) {
52 | return qAwesome->icon(fa::fa_solid, fa::fa_circle_dot,
53 | { { "color", QColor(0xc0c4cc) } });
54 | } else {
55 | return qAwesome->icon(fa::fa_regular, fa::fa_o,
56 | { { "color", QColor(0xc0c4cc) } });
57 | }
58 | }
59 | }
60 |
61 | void Radio::paintEvent(QPaintEvent* event)
62 | {
63 | Q_UNUSED(event)
64 | QPainter painter(this);
65 |
66 | QPen pen;
67 | pen.setColor(getColor());
68 | QFont f("Microsoft YaHei");
69 | const int fontSize = 14;
70 | f.setPixelSize(fontSize);
71 | QFontMetrics metrics(f);
72 | int textWidth = metrics.boundingRect(text()).size().width();
73 | painter.setFont(f);
74 | painter.setPen(pen);
75 | const int iconSize = 16;
76 | const int margin = 4;
77 | if (LabelPosition::LP_Left == _placement) {
78 | painter.drawText(margin, 0, textWidth, height(), Qt::AlignCenter, text());
79 | } else {
80 | painter.drawText(iconSize + margin * 2, 0, textWidth, height(), Qt::AlignCenter, text());
81 | }
82 | QPixmap pixmap = getIcon().pixmap(iconSize, iconSize);
83 | int posY = (height() - iconSize) / 2 + 1;
84 | if (LabelPosition::LP_Left == _placement) {
85 | painter.drawPixmap(textWidth + margin * 2, posY, iconSize, iconSize, pixmap);
86 | } else {
87 | painter.drawPixmap(margin, posY, iconSize, iconSize, pixmap);
88 | }
89 | }
90 |
91 | EL_END_NAMESPACE
92 |
--------------------------------------------------------------------------------
/qelement/el_checkbox.cpp:
--------------------------------------------------------------------------------
1 | #include "el_checkbox.h"
2 | #include "el_awesome.h"
3 |
4 | #include
5 |
6 | EL_BEGIN_NAMESPACE
7 |
8 | Checkbox::Checkbox(const QString& text, LabelPosition placement, QWidget* parent)
9 | : QAbstractButton(parent)
10 | , _placement(placement)
11 | {
12 | setText(text);
13 | setCursor(Qt::PointingHandCursor);
14 | setCheckable(true);
15 | }
16 |
17 | QColor Checkbox::getColor()
18 | {
19 | if (isEnabled()) {
20 | if (isChecked()) {
21 | return QColor(0x409eff);
22 | } else {
23 | return QColor(0x606266);
24 | }
25 | } else {
26 | return QColor(0xc0c4cc);
27 | }
28 | }
29 |
30 | QIcon Checkbox::getIcon()
31 | {
32 | if (isEnabled()) {
33 | if (isChecked()) {
34 | return qAwesome->icon(fa::fa_solid, fa::fa_square_check,
35 | { { "color", QColor(0x409eff) } });
36 | } else {
37 | return qAwesome->icon(fa::fa_regular, fa::fa_square,
38 | { { "color", QColor(0x606266) } });
39 | }
40 | } else {
41 | if (isChecked()) {
42 | return qAwesome->icon(fa::fa_solid, fa::fa_square_check,
43 | { { "color", QColor(0xc0c4cc) } });
44 | } else {
45 | return qAwesome->icon(fa::fa_regular, fa::fa_square,
46 | { { "color", QColor(0xc0c4cc) } });
47 | }
48 | }
49 | }
50 |
51 | QSize Checkbox::sizeHint() const
52 | {
53 | if (text().isEmpty()) {
54 | return QSize(40, 40);
55 | }
56 | QFont font("Microsoft YaHei");
57 | font.setPixelSize(14);
58 | QFontMetrics metrics(font);
59 | return QSize(metrics.boundingRect(text()).size().width() + 30, 40);
60 | }
61 |
62 | void Checkbox::paintEvent(QPaintEvent* event)
63 | {
64 | Q_UNUSED(event)
65 | QPainter painter(this);
66 |
67 | QPen pen;
68 | pen.setColor(getColor());
69 | QFont f("Microsoft YaHei");
70 | const int fontSize = 14;
71 | f.setPixelSize(fontSize);
72 | QFontMetrics metrics(f);
73 | int textWidth = metrics.boundingRect(text()).size().width();
74 | painter.setFont(f);
75 | painter.setPen(pen);
76 | const int iconSize = 16;
77 | const int margin = 4;
78 | if (LabelPosition::LP_Left == _placement) {
79 | painter.drawText(margin, 0, textWidth, height(), Qt::AlignCenter, text());
80 | } else {
81 | painter.drawText(iconSize + margin * 2, 0, textWidth, height(), Qt::AlignCenter, text());
82 | }
83 | QPixmap pixmap = getIcon().pixmap(iconSize, iconSize);
84 | int posY = (height() - iconSize) / 2 + 1;
85 | if (LabelPosition::LP_Left == _placement) {
86 | painter.drawPixmap(textWidth + margin * 2, posY, iconSize, iconSize, pixmap);
87 | } else {
88 | painter.drawPixmap(margin, posY, iconSize, iconSize, pixmap);
89 | }
90 | }
91 |
92 | EL_END_NAMESPACE
93 |
--------------------------------------------------------------------------------
/qelement/el_card.cpp:
--------------------------------------------------------------------------------
1 | #include "el_card.h"
2 | #include
3 | #include
4 |
5 | EL_BEGIN_NAMESPACE
6 |
7 | Card::Card(const QIcon& icon, const QString& title, const QString& content, QWidget* parent)
8 | : QAbstractButton(parent)
9 | , _content(content)
10 | {
11 | setIcon(icon);
12 | setText(title);
13 | }
14 |
15 | QSize Card::sizeHint() const
16 | {
17 | return QSize(230, 70);
18 | }
19 |
20 | void Card::paintEvent(QPaintEvent* event)
21 | {
22 | Q_UNUSED(event)
23 |
24 | const int leftOffsetX = 15;
25 | const int topOffsetY = 15;
26 |
27 | QString title = text();
28 |
29 | QFont titleFont("Microsoft YaHei");
30 | titleFont.setPixelSize(14);
31 | QFontMetrics fmTitle(titleFont);
32 | QRect fmRectTitle = fmTitle.boundingRect(title);
33 |
34 | int iconSize = 40;
35 |
36 | double titlePosX = iconSize + leftOffsetX * 2;
37 | double titlePosY = (height() - iconSize) / 2;
38 | double titleWidth = fmRectTitle.width();
39 | double titleHeight = fmRectTitle.height();
40 |
41 | QFont contentFont("Microsoft YaHei");
42 | contentFont.setPixelSize(12);
43 | QFontMetrics fmContent(contentFont);
44 | QRect fmRectContext = fmContent.boundingRect(_content);
45 |
46 | double contentPosX = titlePosX;
47 | double contentPosY = height() / 2 + iconSize / 2 - fmRectContext.height();
48 | double contentWidth = fmRectContext.width();
49 | double contentHeight = fmRectContext.height();
50 |
51 | QColor titleColor(0x606266);
52 | QColor contentColor(0x909399);
53 |
54 | if (!isEnabled()) {
55 | titleColor = QColor(0xc0c4cc);
56 | contentColor = QColor(0xc0c4cc);
57 | }
58 |
59 | QPainter painter(this);
60 |
61 | QStyleOptionButton option;
62 | option.initFrom(this);
63 | if (option.state & QStyle::State_MouseOver) {
64 | painter.fillRect(option.rect, QBrush(QColor(0xf6f9fc)));
65 | }
66 |
67 | QRectF titleRect(titlePosX, titlePosY, titleWidth, titleHeight);
68 | painter.setPen(titleColor);
69 | painter.setFont(titleFont);
70 | painter.drawText(titleRect, Qt::AlignLeft | Qt::AlignTop, title);
71 |
72 | QRectF contentRect(contentPosX, contentPosY, contentWidth, contentHeight);
73 | painter.setPen(contentColor);
74 | painter.setFont(contentFont);
75 | painter.drawText(contentRect, Qt::AlignLeft | Qt::AlignBottom, _content);
76 |
77 | QPixmap pixmap = icon().pixmap(iconSize, iconSize);
78 | if (!isEnabled()) {
79 | iconToGrayscale(&pixmap);
80 | }
81 | painter.drawPixmap(QRect(leftOffsetX, topOffsetY, iconSize, iconSize), pixmap);
82 | }
83 |
84 | void Card::iconToGrayscale(QPixmap* pm)
85 | {
86 | QImage qi(pm->toImage());
87 | int h = qi.height();
88 | int w = qi.width();
89 | QRgb c_rgb;
90 | for (int i = 0; i < w; ++i) {
91 | for (int j = 0; j < h; ++j) {
92 | c_rgb = qi.pixel(i, j);
93 | int k = qMin(qRound(0.3 * qRed(c_rgb) + 0.59 * qGreen(c_rgb) + 0.11 * qBlue(c_rgb)), 255);
94 | qi.setPixel(i, j, qRgba(k, k, k, qAlpha(c_rgb)));
95 | }
96 | }
97 | *pm = QPixmap::fromImage(qi);
98 | }
99 |
100 | EL_END_NAMESPACE
101 |
--------------------------------------------------------------------------------
/qelement/el_inputnumber.cpp:
--------------------------------------------------------------------------------
1 | #include "el_inputnumber.h"
2 | #include "el_awesome.h"
3 |
4 | #include
5 | #include
6 | #include
7 | #include
8 |
9 | EL_BEGIN_NAMESPACE
10 |
11 | InputNumber::InputNumber(int min, int max, QWidget* parent)
12 | : QLineEdit { parent }
13 | {
14 |
15 | QVariantMap options;
16 | options.insert("color", QColor(0x606266));
17 | options.insert("color-active", QColor(0x7fb8fe));
18 |
19 | _minusBtn = new QPushButton(this);
20 | _minusBtn->setIcon(qAwesome->icon(fa::fa_solid, fa::fa_minus, options));
21 | QString minusStyle;
22 | minusStyle += "QPushButton { background:#f5f7fa; width: 40px; height: 38px;}";
23 | minusStyle += "QPushButton { border-left: none; border-top: none; border-bottom: none; border-right: 1px solid #dcdfe6;}";
24 | minusStyle += "QPushButton { border-top-left-radius: 4px; border-bottom-left-radius: 4px;} ";
25 | _minusBtn->setStyleSheet(minusStyle);
26 | _minusBtn->setFocusProxy(this);
27 | _minusBtn->setMouseTracking(true);
28 |
29 | connect(_minusBtn, &QPushButton::pressed, [this, min] {
30 | int value = text().toInt();
31 | value--;
32 | if (value < min)
33 | return;
34 | setText(QString::number(value));
35 | });
36 |
37 | _plusBtn = new QPushButton(this);
38 | _plusBtn->setIcon(qAwesome->icon(fa::fa_solid, fa::fa_add, options));
39 | QString plusStyle;
40 | plusStyle += "QPushButton { background:#f5f7fa; width: 40px; height: 38px;}";
41 | plusStyle += "QPushButton { border-left: 1px solid #dcdfe6; border-top: none; border-bottom: none; border-right: none;}";
42 | plusStyle += "QPushButton { border-top-right-radius: 4px; border-bottom-right-radius: 4px;} ";
43 | _plusBtn->setStyleSheet(plusStyle);
44 | _plusBtn->setFocusProxy(this);
45 | _plusBtn->setMouseTracking(true);
46 | connect(_plusBtn, &QPushButton::pressed, [this, max] {
47 | int value = text().toInt();
48 | value++;
49 | if (value > max)
50 | return;
51 | setText(QString::number(value));
52 | });
53 |
54 | QString styleSheet;
55 | styleSheet += "QLineEdit { border-radius: 4px; border: 1px solid #dcdfe6; padding-left: 40px; padding-right: 40px;}";
56 | styleSheet += "QLineEdit:focus { border: 1px solid #409eff; }";
57 | styleSheet += "QLineEdit { qproperty-alignment: AlignHCenter;}";
58 | styleSheet += "QLineEdit { font-family: Microsoft YaHei; font-size: 14px; }";
59 | styleSheet += "QLineEdit { color: #606266; min-height: 40px; }";
60 |
61 | setStyleSheet(styleSheet);
62 | setValidator(new QIntValidator(this));
63 | }
64 |
65 | void InputNumber::resizeEvent(QResizeEvent* event)
66 | {
67 | if (auto resizeEvent = dynamic_cast(event)) {
68 | QSize sz = _minusBtn->sizeHint();
69 | int frameWidth = style()->pixelMetric(QStyle::PM_DefaultFrameWidth);
70 | _minusBtn->move(1,
71 | (rect().bottom() - sz.height()) / 2);
72 |
73 | sz = _plusBtn->sizeHint();
74 | _plusBtn->move(rect().right() - frameWidth - sz.width(),
75 | (rect().bottom() - sz.height()) / 2);
76 | }
77 | }
78 |
79 | void InputNumber::mouseMoveEvent(QMouseEvent* event)
80 | {
81 | if (_minusBtn->geometry().contains(event->pos())
82 | || _plusBtn->geometry().contains(event->pos())) {
83 | setCursor(Qt::PointingHandCursor);
84 | } else {
85 | setCursor(Qt::IBeamCursor);
86 | }
87 | }
88 |
89 | EL_END_NAMESPACE
90 |
--------------------------------------------------------------------------------
/qelement/el_slider.h:
--------------------------------------------------------------------------------
1 | #ifndef EL_SLIDER_H
2 | #define EL_SLIDER_H
3 |
4 | #include "el_global.h"
5 | #include
6 |
7 | EL_BEGIN_NAMESPACE
8 |
9 | class OverlayWidget : public QWidget {
10 | Q_OBJECT
11 | public:
12 | explicit OverlayWidget(QWidget* parent = 0);
13 | ~OverlayWidget();
14 |
15 | protected:
16 | bool event(QEvent* event) Q_DECL_OVERRIDE;
17 | bool eventFilter(QObject* obj, QEvent* event) Q_DECL_OVERRIDE;
18 |
19 | virtual QRect overlayGeometry() const;
20 | };
21 |
22 | class Slider;
23 | class SliderThumb : public OverlayWidget {
24 | Q_OBJECT
25 | public:
26 | explicit SliderThumb(Slider* slider);
27 | ~SliderThumb();
28 | void setDiameter(qreal diameter);
29 | qreal diameter() const;
30 |
31 | void setBorderWidth(qreal width);
32 | qreal borderWidth() const;
33 |
34 | void setBorderColor(const QColor& color);
35 | QColor borderColor() const;
36 |
37 | void setFillColor(const QColor& color);
38 | QColor fillColor() const;
39 |
40 | void setHaloSize(qreal size);
41 | qreal haloSize() const;
42 |
43 | void setHaloColor(const QColor& color);
44 | QColor haloColor() const;
45 |
46 | void setOffset(int offset);
47 | int offset() const;
48 |
49 | protected:
50 | bool eventFilter(QObject* obj, QEvent* event) Q_DECL_OVERRIDE;
51 | void paintEvent(QPaintEvent* event) Q_DECL_OVERRIDE;
52 |
53 | private:
54 | const Slider* const _slider;
55 | QColor _borderColor;
56 | QColor _fillColor;
57 | QColor _haloColor;
58 | qreal _diameter;
59 | qreal _borderWidth;
60 | qreal _haloSize;
61 | int _offset;
62 | };
63 |
64 | class SliderTrack : public OverlayWidget {
65 | Q_OBJECT
66 | public:
67 | explicit SliderTrack(SliderThumb* thumb, Slider* slider);
68 | ~SliderTrack();
69 |
70 | void setFillColor(const QColor& color);
71 | QColor fillColor() const;
72 |
73 | void setTrackWidth(int width);
74 | int trackWidth() const;
75 |
76 | protected:
77 | bool eventFilter(QObject* obj, QEvent* event) Q_DECL_OVERRIDE;
78 | void paintEvent(QPaintEvent* event) Q_DECL_OVERRIDE;
79 |
80 | private:
81 | const Slider* const _slider;
82 | SliderThumb* const _thumb;
83 | QColor _fillColor;
84 | int _trackWidth;
85 | };
86 |
87 | // Slider 滑块
88 | class Slider : public QAbstractSlider {
89 | Q_OBJECT
90 | public:
91 | Slider(QWidget* parent = nullptr);
92 |
93 | void setThumbColor(const QColor& color);
94 | QColor thumbColor() const;
95 |
96 | void setTrackColor(const QColor& color);
97 | QColor trackColor() const;
98 |
99 | void setDisabledColor(const QColor& color);
100 | QColor disabledColor() const;
101 |
102 | void setPageStepMode(bool pageStep);
103 | bool pageStepMode() const;
104 |
105 | QSize minimumSizeHint() const Q_DECL_OVERRIDE;
106 | void setInvertedAppearance(bool value);
107 |
108 | protected:
109 | void sliderChange(SliderChange change) Q_DECL_OVERRIDE;
110 | void mouseMoveEvent(QMouseEvent* event) Q_DECL_OVERRIDE;
111 | void mousePressEvent(QMouseEvent* event) Q_DECL_OVERRIDE;
112 | void mouseReleaseEvent(QMouseEvent* event) Q_DECL_OVERRIDE;
113 | void leaveEvent(QEvent* event) Q_DECL_OVERRIDE;
114 |
115 | void updateThumbOffset();
116 |
117 | private:
118 | void init();
119 | QRectF trackBoundingRect() const;
120 | QRectF thumbBoundingRect() const;
121 | int valueFromPosition(const QPoint& pos) const;
122 | void setHovered(bool status);
123 |
124 | private:
125 | SliderThumb* _thumb;
126 | SliderTrack* _track;
127 | QColor _thumbColor;
128 | QColor _trackColor;
129 | QColor _disabledColor;
130 | int _stepTo;
131 | int _oldValue;
132 | int _trackWidth;
133 | bool _hoverTrack;
134 | bool _hoverThumb;
135 | bool _hover;
136 | bool _step;
137 | bool _pageStepMode;
138 | };
139 |
140 | EL_END_NAMESPACE
141 |
142 | #endif // EL_SLIDER_H
143 |
--------------------------------------------------------------------------------
/qelement/el_avatar.cpp:
--------------------------------------------------------------------------------
1 | #include "el_avatar.h"
2 |
3 | #include
4 | #include
5 | #include
6 |
7 | EL_BEGIN_NAMESPACE
8 |
9 | Avatar::Avatar(QWidget* parent)
10 | : QWidget { parent }
11 | {
12 | QSizePolicy policy(QSizePolicy::MinimumExpanding,
13 | QSizePolicy::MinimumExpanding);
14 | setSizePolicy(policy);
15 |
16 | connect(&_provider, &ImageProvider::imageReady, this, &Avatar::onImageReady);
17 | }
18 |
19 | Avatar::Avatar(const QIcon& icon, QWidget* parent)
20 | : Avatar(parent)
21 | {
22 | setIcon(icon);
23 | }
24 |
25 | Avatar::Avatar(const QString& letter, QWidget* parent)
26 | : Avatar(parent)
27 | {
28 | setLetter(letter);
29 | }
30 |
31 | Avatar::Avatar(const QImage& image, QWidget* parent)
32 | : Avatar(parent)
33 | {
34 | setImage(image);
35 | }
36 |
37 | QSize Avatar::sizeHint() const
38 | {
39 | return QSize(_size + 2, _size + 2);
40 | }
41 |
42 | void Avatar::setSize(int size)
43 | {
44 | _size = size;
45 |
46 | if (!_image.isNull()) {
47 | _pixmap = QPixmap::fromImage(_image.scaled(_size, _size,
48 | Qt::IgnoreAspectRatio,
49 | Qt::SmoothTransformation));
50 | }
51 |
52 | update();
53 | }
54 |
55 | int Avatar::size() const
56 | {
57 | return _size;
58 | }
59 |
60 | void Avatar::setLetter(const QString& letter)
61 | {
62 | _letter = letter;
63 | _type = Letter;
64 | update();
65 | }
66 |
67 | void Avatar::setImage(const QImage& image)
68 | {
69 | _image = image;
70 | _type = Image;
71 |
72 | _pixmap = QPixmap::fromImage(image.scaled(_size, _size,
73 | Qt::IgnoreAspectRatio,
74 | Qt::SmoothTransformation));
75 | update();
76 | }
77 |
78 | void Avatar::setIcon(const QIcon& icon)
79 | {
80 | _icon = icon;
81 | _type = Icon;
82 | update();
83 | }
84 |
85 | void Avatar::setUrl(const QString& url)
86 | {
87 | if (url.isEmpty()) {
88 | return;
89 | }
90 | _provider.getNetworkImage(url);
91 | }
92 |
93 | void Avatar::onImageReady(QString url, QString filePath)
94 | {
95 | Q_UNUSED(url)
96 | if (QFile::exists(filePath)) {
97 | setImage(QImage(filePath));
98 | return;
99 | }
100 | }
101 |
102 | Avatar::Type Avatar::type() const
103 | {
104 | return _type;
105 | }
106 |
107 | void Avatar::paintEvent(QPaintEvent* event)
108 | {
109 | Q_UNUSED(event)
110 |
111 | QPainter painter(this);
112 | painter.setRenderHint(QPainter::Antialiasing);
113 |
114 | QRect r = rect();
115 | const qreal hs = _size / 2;
116 |
117 | if (!isEnabled()) {
118 | QBrush brush;
119 | brush.setStyle(Qt::SolidPattern);
120 | brush.setColor(QColor(0xc0c4cc));
121 | painter.setPen(Qt::NoPen);
122 | painter.setBrush(brush);
123 | painter.drawEllipse(QRectF((width() - _size) / 2, (height() - _size) / 2,
124 | _size, _size));
125 | return;
126 | }
127 |
128 | if (Image != _type) {
129 | QBrush brush;
130 | brush.setStyle(Qt::SolidPattern);
131 | brush.setColor(QColor(0xc0c4cc));
132 | painter.setPen(Qt::NoPen);
133 | painter.setBrush(brush);
134 | painter.drawEllipse(QRectF((width() - _size) / 2, (height() - _size) / 2,
135 | _size, _size));
136 | }
137 |
138 | switch (_type) {
139 | case Image: {
140 | QPainterPath path;
141 | path.addEllipse(width() / 2 - hs, height() / 2 - hs, _size, _size);
142 | painter.setClipPath(path);
143 |
144 | painter.drawPixmap(QRect(width() / 2 - hs, height() / 2 - hs, _size, _size), _pixmap);
145 | break;
146 | }
147 | case Icon: {
148 | QRect iconGeometry((width() - hs) / 2, (height() - hs) / 2, hs, hs);
149 | QPixmap pixmap = _icon.pixmap(hs, hs);
150 | QPainter icon(&pixmap);
151 | icon.setCompositionMode(QPainter::CompositionMode_SourceIn);
152 | icon.fillRect(pixmap.rect(), QColor(0xffffff));
153 | painter.drawPixmap(iconGeometry, pixmap);
154 | break;
155 | }
156 | case Letter: {
157 | QFont f("Microsoft YaHei");
158 | f.setPixelSize(18);
159 | painter.setFont(f);
160 | painter.setPen(QColor(0xffffff));
161 | painter.setBrush(Qt::NoBrush);
162 | painter.drawText(r, Qt::AlignCenter, _letter);
163 | break;
164 | }
165 | default:
166 | break;
167 | }
168 | }
169 |
170 | EL_END_NAMESPACE
171 |
--------------------------------------------------------------------------------
/qelement/el_button.cpp:
--------------------------------------------------------------------------------
1 | #include "el_button.h"
2 | #include "el_awesome.h"
3 |
4 | EL_BEGIN_NAMESPACE
5 |
6 | Button::Button(QWidget *parent)
7 | :QPushButton(parent)
8 | {
9 |
10 | }
11 |
12 | Button::Button(const QString& text, ButtonType type, ButtonStyle style, QWidget* parent)
13 | : Button(text, QIcon(), type, style, parent)
14 | {
15 | }
16 |
17 | Button::Button(const QIcon& icon, ButtonType type, ButtonStyle style, QWidget* parent)
18 | : Button(QString(), icon, type, style, parent)
19 | {
20 | }
21 |
22 | Button::Button(const QString& text, const QIcon& icon, ButtonType type, ButtonStyle style, QWidget* parent)
23 | : QPushButton(icon, text, parent)
24 | {
25 | init(type, style);
26 | }
27 |
28 | Button::Button(int character, ButtonType type, ButtonStyle style, QWidget* parent)
29 | : Button(QString(), character, type, style, parent)
30 | {
31 | }
32 |
33 | Button::Button(const QString& text, int character, ButtonType type, ButtonStyle style, QWidget* parent)
34 | : QPushButton(text, parent)
35 | {
36 | init(character, type, style);
37 | }
38 |
39 | void Button::init(ButtonType type, ButtonStyle style)
40 | {
41 |
42 | setCursor(Qt::PointingHandCursor);
43 |
44 | QString styleSheet;
45 | styleSheet += "QPushButton {font-family: Microsoft YaHei; font-size: 14px;}";
46 | styleSheet += getBorderStyle(type, style);
47 | styleSheet += getColorStyle(type);
48 | styleSheet += getBkColorStyle(type);
49 | setStyleSheet(styleSheet);
50 | }
51 |
52 | void Button::init(const QIcon& icon, ButtonType type, ButtonStyle style)
53 | {
54 | init(type, style);
55 | setIcon(icon);
56 | }
57 |
58 | void Button::init(int character, ButtonType type, ButtonStyle style)
59 | {
60 | setCursor(Qt::PointingHandCursor);
61 |
62 | QVariantMap options;
63 | if (type == BT_Default) {
64 | options.insert("color", QColor(0x606266));
65 | options.insert("color-active", QColor(0x409eff));
66 | } else {
67 | options.insert("color", QColor(0xffffff));
68 | options.insert("color-active", QColor(0xffffff));
69 | }
70 |
71 | QIcon icon = qAwesome->icon(fa::fa_solid, character, options);
72 | setIcon(icon);
73 | QString styleSheet;
74 | styleSheet += "QPushButton {font-family: Microsoft YaHei; font-size: 14px;}";
75 | styleSheet += getBorderStyle(type, style);
76 | styleSheet += getColorStyle(type);
77 | styleSheet += getBkColorStyle(type);
78 | setStyleSheet(styleSheet);
79 | if (text().isEmpty()) {
80 | setFixedSize(40, 40);
81 | }
82 | }
83 |
84 | QSize Button::sizeHint() const
85 | {
86 | if (text().isEmpty()) {
87 | return QSize(40, 40);
88 | }
89 | QFont font("Microsoft YaHei");
90 | font.setPixelSize(14);
91 | QFontMetrics metrics(font);
92 | return QSize(metrics.boundingRect(text()).size().width() + 30, 40);
93 | }
94 |
95 | QString Button::getBorderStyle(ButtonType type, ButtonStyle style)
96 | {
97 | QString borderStyle;
98 | // 圆角样式
99 | if (style == BS_Default) {
100 | borderStyle += "QPushButton { border-radius: 4px; }";
101 | } else if (style == BS_Round) {
102 | borderStyle += "QPushButton { border-radius: 20px; }";
103 | } else if (style == BS_Circle) {
104 | borderStyle += "QPushButton { border-radius: 20px; }";
105 | }
106 | // 边框样式
107 | if (type == BT_Default) {
108 | borderStyle += "QPushButton { border: 1px solid #dcdfe6; }";
109 | borderStyle += "QPushButton:pressed { border: 1px solid #c6e2ff; }";
110 | } else {
111 | borderStyle += "QPushButton { border: none; }";
112 | }
113 |
114 | return borderStyle;
115 | }
116 |
117 | QString Button::getColorStyle(ButtonType type)
118 | {
119 | QString colorStyle;
120 | if (type == BT_Default) {
121 | colorStyle += "QPushButton { color: #606266; }";
122 | colorStyle += "QPushButton:hover { color: #409eff; }";
123 | colorStyle += "QPushButton:pressed { color: #409eff; }";
124 | } else {
125 | colorStyle += "QPushButton { color: #ffffff; }";
126 | }
127 | return colorStyle;
128 | }
129 |
130 | QString Button::getBkColorStyle(ButtonType type)
131 | {
132 | QString bkColorStyle;
133 | if (type == BT_Default) {
134 | bkColorStyle += "QPushButton { background: #ffffff; }";
135 | bkColorStyle += "QPushButton:hover { background: #ecf5ff; }";
136 | bkColorStyle += "QPushButton:pressed { background: #ecf5ff; }";
137 | } else if (type == BT_Primary) {
138 | bkColorStyle += "QPushButton { background: #409eff; }";
139 | bkColorStyle += "QPushButton:hover { background: #66b1ff; }";
140 | bkColorStyle += "QPushButton:pressed { background: #3a8ee6; }";
141 | } else if (type == BT_Success) {
142 | bkColorStyle += "QPushButton { background: #67c23a; }";
143 | bkColorStyle += "QPushButton:hover { background: #85ce61; }";
144 | bkColorStyle += "QPushButton:pressed { background: #5daf34; }";
145 | } else if (type == BT_Warning) {
146 | bkColorStyle += "QPushButton { background: #e6a23c; }";
147 | bkColorStyle += "QPushButton:hover { background: #ebb563; }";
148 | bkColorStyle += "QPushButton:pressed { background: #cf9236; }";
149 | } else if (type == BT_Danger) {
150 | bkColorStyle += "QPushButton { background: #f56c6c; }";
151 | bkColorStyle += "QPushButton:hover { background: #f78989; }";
152 | bkColorStyle += "QPushButton:pressed { background: #dd6161; }";
153 | } else if (type == BT_Info) {
154 | bkColorStyle += "QPushButton { background: #909399; }";
155 | bkColorStyle += "QPushButton:hover { background: #a6a9ad; }";
156 | bkColorStyle += "QPushButton:pressed { background: #82848a; }";
157 | }
158 | return bkColorStyle;
159 | }
160 |
161 | EL_END_NAMESPACE
162 |
--------------------------------------------------------------------------------
/qelement/el_messagebox.cpp:
--------------------------------------------------------------------------------
1 | #include "el_messagebox.h"
2 | #include "el_awesome.h"
3 | #include "el_button.h"
4 | #include
5 | #include
6 | #include
7 | #include
8 | #include
9 | #include
10 | #include
11 | #include
12 |
13 | EL_BEGIN_NAMESPACE
14 |
15 | MessageBox::MessageBox(const QIcon& icon, const QString& title, const QString& text, QWidget* parent)
16 | : FramelessWindow(true, parent, true)
17 | {
18 | init(icon, title, text);
19 | }
20 |
21 | int MessageBox::alert(QWidget* parent, const QString& title, const QString& text, const QString& confirmButtonText)
22 | {
23 | return showNewMessageBox(parent, {}, title, text, StandardButton::Ok, StandardButton::Ok, { { StandardButton::Ok, confirmButtonText } });
24 | }
25 |
26 | int MessageBox::confirm(QWidget* parent, const QString& title, const QString& text, const QString& confirmButtonText, const QString& cancelButtonText)
27 | {
28 | QVariantMap options;
29 | options.insert("color", QColor(0xe6a23c));
30 | options.insert("color-active", QColor(0xe6a23c));
31 | QIcon icon = qAwesome->icon(fa::fa_solid, fa::fa_circle_question, options);
32 | return showNewMessageBox(parent, icon, title, text, StandardButton::Cancel | StandardButton::Ok,
33 | StandardButton::Cancel,
34 | { { StandardButton::Cancel, cancelButtonText }, { StandardButton::Ok, confirmButtonText } });
35 | }
36 |
37 | int MessageBox::error(QWidget* parent, const QString& title, const QString& text, const QString& confirmButtonText)
38 | {
39 | QVariantMap options;
40 | options.insert("color", QColor(0xF56C6C));
41 | QIcon icon = qAwesome->icon(fa::fa_solid, fa::fa_xmark_circle, options);
42 | return showNewMessageBox(parent, icon, title, text, StandardButton::Ok,
43 | StandardButton::Ok,
44 | { { StandardButton::Ok, confirmButtonText } });
45 | }
46 |
47 | MessageBox::StandardButton MessageBox::showNewMessageBox(QWidget* parent, const QIcon& icon, const QString& title, const QString& text,
48 | StandardButtons buttons, StandardButton defaultButton, ButtonText buttonText)
49 | {
50 | MessageBox msgBox(icon, title, text, parent);
51 |
52 | uint mask = MessageBox::LastButton;
53 | while (mask >= MessageBox::FirstButton) {
54 | uint sb = buttons & mask;
55 | mask >>= 1;
56 | if (!sb)
57 | continue;
58 | QPushButton* button = msgBox.addButton((StandardButton)sb, buttonText[(StandardButton)sb]);
59 | if (sb == defaultButton) {
60 | msgBox.setDefaultButton(button);
61 | }
62 | }
63 |
64 | return (StandardButton)msgBox.exec();
65 | }
66 |
67 | void MessageBox::setDefaultButton(QPushButton* button)
68 | {
69 | if (button == nullptr)
70 | return;
71 |
72 | button->setDefault(true);
73 | button->setFocus();
74 | }
75 |
76 | QPushButton* MessageBox::addButton(MessageBox::StandardButton button, const QString& buttonText)
77 | {
78 | QPushButton* pushButton = nullptr;
79 | pushButton = new Button(buttonText, Button::BT_Primary, Button::BS_Default, this);
80 | connect(pushButton, &QPushButton::clicked, [this, button] {
81 | done(button);
82 | });
83 | _buttonBox->addWidget(pushButton);
84 | return pushButton;
85 | }
86 |
87 | void MessageBox::init(const QIcon& icon, const QString& title, const QString& text)
88 | {
89 | setStyleSheet("border-radius: 4px;");
90 | _label = new QLabel;
91 | _label->setTextInteractionFlags(Qt::TextInteractionFlags(style()->styleHint(QStyle::SH_MessageBox_TextInteractionFlags, nullptr, this)));
92 | _label->setAlignment(Qt::AlignVCenter | Qt::AlignLeft);
93 | _label->setOpenExternalLinks(true);
94 | _iconLabel = new QLabel(this);
95 | _iconLabel->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
96 |
97 | if (!icon.isNull())
98 | _iconLabel->setPixmap(icon.pixmap(QSize(24, 24)));
99 |
100 | _titleLabel = new QLabel;
101 | _titleLabel->setStyleSheet("QLabel { font-family: Microsoft YaHei; font-size: 18px; color: #303133}");
102 | _titleLabel->setText(title);
103 |
104 | _label->setStyleSheet("QLabel { font-family: Microsoft YaHei; font-size: 14px; color: #606266}");
105 |
106 | setupLayout();
107 |
108 | if (!title.isEmpty() || !text.isEmpty()) {
109 | setWindowTitle(title);
110 | setText(text);
111 | }
112 |
113 | setContentsMargins(14, 14, 14, 14);
114 | setMinimumSize(400, 200);
115 |
116 | setModal(true);
117 | }
118 |
119 | QPushButton* MessageBox::closeButton()
120 | {
121 | QPushButton* closeBtn = new QPushButton();
122 | QVariantMap options;
123 | options.insert("color", QColor(0x909399));
124 | options.insert("color-active", QColor(0x409eff));
125 | QIcon icon = qAwesome->icon(fa::fa_solid, fa::fa_close, options);
126 | closeBtn->setIcon(icon);
127 | closeBtn->setStyleSheet("QPushButton { background-color: transparent; border: 0px }");
128 | connect(closeBtn, &QPushButton::clicked, [this] {
129 | done(MessageBox::Close);
130 | });
131 | return closeBtn;
132 | }
133 |
134 | void MessageBox::setupLayout()
135 | {
136 | QWidget* centralWidget = new QWidget();
137 | QHBoxLayout* bkLayout = new QHBoxLayout();
138 | bkLayout->setContentsMargins(0, 0, 0, 0);
139 | bkLayout->addWidget(centralWidget);
140 | setLayout(bkLayout);
141 |
142 | // 窗口拖动部位
143 | setTitlebar({ centralWidget, _label });
144 |
145 | // 创建窗口阴影效果
146 | QGraphicsDropShadowEffect* shadow = new QGraphicsDropShadowEffect();
147 | shadow->setColor(QColor(0, 0, 0, 64));
148 | shadow->setOffset(0, 2);
149 | shadow->setBlurRadius(14);
150 | centralWidget->setGraphicsEffect(shadow);
151 |
152 | const QPixmap* piamap = _iconLabel->pixmap();
153 | const bool hasIcon = piamap != nullptr && !piamap->isNull();
154 |
155 | QVBoxLayout* mainLayout = new QVBoxLayout();
156 |
157 | QHBoxLayout* titleLeft = new QHBoxLayout();
158 | titleLeft->setAlignment(Qt::AlignLeft);
159 | if (_titleIcon) {
160 | titleLeft->addWidget(_titleIcon);
161 | }
162 | titleLeft->addWidget(_titleLabel);
163 |
164 | // 标题栏部分
165 | QHBoxLayout* titleRight = new QHBoxLayout();
166 | titleRight->setAlignment(Qt::AlignRight);
167 | QPushButton* closeBtn = closeButton();
168 | titleRight->addWidget(closeBtn);
169 |
170 | QHBoxLayout* titleBar = new QHBoxLayout();
171 | titleBar->addLayout(titleLeft);
172 | titleBar->addLayout(titleRight);
173 |
174 | mainLayout->addLayout(titleBar);
175 |
176 | QHBoxLayout* contentLayout = new QHBoxLayout;
177 | contentLayout->setContentsMargins(15, 10, 15, 10);
178 | if (hasIcon)
179 | contentLayout->addWidget(_iconLabel, Qt::AlignCenter);
180 | _iconLabel->setVisible(hasIcon);
181 |
182 | contentLayout->addWidget(_label, Qt::AlignCenter);
183 |
184 | _buttonBox = new QHBoxLayout();
185 | _buttonBox->addStretch(0);
186 |
187 | mainLayout->addLayout(contentLayout);
188 | mainLayout->addLayout(_buttonBox);
189 |
190 | centralWidget->setLayout(mainLayout);
191 | }
192 |
193 | void MessageBox::setText(const QString& text)
194 | {
195 | _label->setText(text);
196 | _label->setWordWrap(_label->textFormat() == Qt::RichText
197 | || (_label->textFormat() == Qt::AutoText && Qt::mightBeRichText(text)));
198 | }
199 |
200 | EL_END_NAMESPACE
201 |
--------------------------------------------------------------------------------
/qelement/el_switch.cpp:
--------------------------------------------------------------------------------
1 | // SwitchButton
2 | // Copyright (c) 2018 Iman Ahmadvand
3 | // Copyright (c) 2021 WANDERSON M.PIMENTA
4 | // Copyright (c) 2023 CM0use
5 |
6 | #include "el_switch.h"
7 |
8 | #include
9 | #include
10 |
11 | QT_BEGIN_NAMESPACE
12 | class QPropertyAnimation;
13 | extern Q_DECL_IMPORT void qt_blurImage(QPainter* p, QImage& blurImage, qreal radius, bool quality, bool alphaOnly, int transposed = 0);
14 | QT_END_NAMESPACE
15 |
16 | QPixmap drawShadowEllipse(const qreal& radius, const qreal& elevation, const QColor& color)
17 | {
18 | QPixmap px { qRound(radius * 2), qRound(radius * 2) };
19 | px.fill(Qt::transparent);
20 |
21 | QPainter p { &px };
22 |
23 | p.setBrush(color);
24 | p.setPen(Qt::NoPen);
25 | p.setRenderHint(QPainter::Antialiasing);
26 | p.drawEllipse(QRectF(0, 0, px.size().width(), px.size().height()).center(),
27 | radius - elevation,
28 | radius - elevation);
29 | p.end();
30 |
31 | QImage tmp { px.size(), QImage::Format_ARGB32_Premultiplied };
32 | tmp.setDevicePixelRatio(px.devicePixelRatioF());
33 | tmp.fill(0);
34 | QImage blurred { tmp };
35 | p.begin(&tmp);
36 | p.setCompositionMode(QPainter::CompositionMode_Source);
37 | p.drawPixmap(QPointF(), px);
38 | p.end();
39 |
40 | p.begin(&blurred);
41 | qt_blurImage(&p, tmp, elevation * 4, true, false);
42 | p.end();
43 |
44 | return QPixmap::fromImage(blurred);
45 | }
46 |
47 | EL_BEGIN_NAMESPACE
48 |
49 | Switch::Switch(QWidget* const parent)
50 | : QAbstractButton { parent }
51 | , CORNER_RADIUS { 14 }
52 | , THUMB_RADIUS { 14 }
53 | , SHADOW_ELEVATION { 2.0 }
54 | , height { 36 }
55 | , indicatorMargin { 8, 4, 8, 4 }
56 | , thumbOnColor { Qt::white }
57 | , thumbOffColor { Qt::white }
58 | , trackOnColor { 0x13ce66 }
59 | , trackOffColor { 0xff4949 }
60 | , trackDisabledColor { Qt::gray }
61 | , thumbDisabledColor { Qt::white }
62 | , trackDisabledOpacity { 0.25 }
63 | , disabledTextOpacity { 0.25 }
64 | ,
65 |
66 | thumbPosAnimation { new QPropertyAnimation(this, "thumbPosition", this) }
67 | , _thumbPosition { isChecked() ? (indicatorMargin.left() + indicatorMargin.right() + 2) : 0 }
68 | , shadowPixmap { drawShadowEllipse(THUMB_RADIUS, SHADOW_ELEVATION, QColor(0, 0, 0, 70)) }
69 | {
70 | setCursor(Qt::PointingHandCursor);
71 | setCheckable(true);
72 |
73 | thumbPosAnimation->setDuration(150);
74 | thumbPosAnimation->setEasingCurve(QEasingCurve::OutQuad);
75 | }
76 |
77 | Switch::Switch(const QString& text, QWidget* const parent)
78 | : Switch { parent }
79 | {
80 | setText(text);
81 | }
82 |
83 | void Switch::setTrackColor(const QColor& trackOnColor, const QColor& trackOffColor)
84 | {
85 | this->trackOnColor = trackOnColor;
86 | this->trackOffColor = trackOffColor;
87 | }
88 |
89 | void Switch::setThumbColor(const QColor& thumbOnColor, const QColor& thumbOffColor)
90 | {
91 | this->thumbOnColor = thumbOnColor;
92 | this->thumbOffColor = thumbOffColor;
93 | }
94 |
95 | void Switch::setHieght(int nHeight)
96 | {
97 | this->height = nHeight;
98 | }
99 |
100 | void Switch::setRadius(qreal corner_radius, qreal thumb_radius)
101 | {
102 | CORNER_RADIUS = corner_radius;
103 | THUMB_RADIUS = thumb_radius;
104 | shadowPixmap = drawShadowEllipse(THUMB_RADIUS, SHADOW_ELEVATION, QColor(0, 0, 0, 70));
105 | }
106 |
107 | QSize Switch::sizeHint() const
108 | {
109 | auto w { indicatorMargin.left()
110 | + height
111 | + indicatorMargin.right()
112 | + fontMetrics().horizontalAdvance(text()) };
113 |
114 | return QSize { w, height };
115 | }
116 |
117 | QRect Switch::indicatorRect()
118 | {
119 | const auto w { indicatorMargin.left()
120 | + height
121 | + indicatorMargin.right() };
122 |
123 | return isLeftToRight() ? QRect(0, 0, w, height) : QRect(width() - w, 0, w, height);
124 | }
125 |
126 | QRect Switch::textRect()
127 | {
128 | const auto w { indicatorMargin.left()
129 | + height
130 | + indicatorMargin.right() };
131 |
132 | return isLeftToRight() ? rect().marginsRemoved(QMargins(w, 0, 0, 0)) : rect().marginsRemoved(QMargins(0, 0, w, 0));
133 | }
134 |
135 | void Switch::paintEvent(QPaintEvent* const)
136 | {
137 | QPainter p { this };
138 | p.setPen(Qt::NoPen);
139 | p.setRenderHints(QPainter::Antialiasing | QPainter::TextAntialiasing);
140 |
141 | QMargins trackMargin { indicatorMargin };
142 | trackMargin.setTop(trackMargin.top() + 2);
143 | trackMargin.setBottom(trackMargin.bottom() + 2);
144 |
145 | QRectF trackRect { indicatorRect().marginsRemoved(trackMargin) };
146 |
147 | if (isEnabled()) {
148 | /* DRAW TRACK */
149 | p.setBrush(isChecked() ? trackOnColor : trackOffColor);
150 | p.drawRoundedRect(trackRect, CORNER_RADIUS, CORNER_RADIUS);
151 |
152 | /* DRAW THUMB */
153 | trackRect.setX(trackRect.x() - trackMargin.left() - trackMargin.right() - 2
154 | + thumbPosAnimation->currentValue().toInt());
155 | if (!shadowPixmap.isNull())
156 | p.drawPixmap(trackRect.center() - QPointF(THUMB_RADIUS, THUMB_RADIUS - 1.0), shadowPixmap);
157 | p.setBrush(isChecked() ? thumbOnColor : thumbOffColor);
158 | p.drawEllipse(trackRect.center(), THUMB_RADIUS - SHADOW_ELEVATION - 1.0, THUMB_RADIUS - SHADOW_ELEVATION - 1.0);
159 |
160 | /* DRAW TEXT */
161 | if (!text().isEmpty()) {
162 | QFont font("Microsoft YaHei");
163 | font.setPixelSize(14);
164 | p.setFont(font);
165 | p.setPen(QColor(0x303133));
166 | p.setPen(palette().color(QPalette::Active, QPalette::ButtonText));
167 | p.drawText(textRect(), Qt::AlignLeft | Qt::AlignVCenter, text());
168 | }
169 | } else {
170 | /* DRAW TRACK */
171 | p.setBrush(trackDisabledColor);
172 | p.setOpacity(trackDisabledOpacity);
173 | p.drawRoundedRect(trackRect, CORNER_RADIUS, CORNER_RADIUS);
174 |
175 | /* DRAW THUMB */
176 | p.setOpacity(1.0);
177 | if (isChecked())
178 | trackRect.setX(trackRect.x() + trackMargin.left() + trackMargin.right() + 2);
179 | else
180 | trackRect.setX(trackRect.x() - trackMargin.left() - trackMargin.right() - 2);
181 | if (!shadowPixmap.isNull())
182 | p.drawPixmap(trackRect.center() - QPointF(THUMB_RADIUS, THUMB_RADIUS - 1.0), shadowPixmap);
183 | p.setBrush(thumbDisabledColor);
184 | p.drawEllipse(trackRect.center(), THUMB_RADIUS - SHADOW_ELEVATION - 1.0, THUMB_RADIUS - SHADOW_ELEVATION - 1.0);
185 |
186 | /* DRAW TEXT */
187 | if (!text().isEmpty()) {
188 | QFont font("Microsoft YaHei");
189 | font.setPixelSize(14);
190 | p.setFont(font);
191 | p.setOpacity(disabledTextOpacity);
192 | p.setPen(palette().color(QPalette::Disabled, QPalette::ButtonText));
193 | p.drawText(textRect(), Qt::AlignLeft | Qt::AlignVCenter, text());
194 | }
195 | }
196 | }
197 |
198 | void Switch::nextCheckState()
199 | {
200 | QAbstractButton::nextCheckState();
201 | checkStateSet();
202 | }
203 |
204 | void Switch::checkStateSet()
205 | {
206 | const Qt::CheckState state { isChecked() ? Qt::Checked : Qt::Unchecked };
207 | toggle(state);
208 | emit stateChanged(state);
209 | }
210 |
211 | void Switch::toggle(const Qt::CheckState& state)
212 | {
213 | thumbPosAnimation->stop();
214 | if (state == Qt::Unchecked)
215 | thumbPosAnimation->setEndValue(0);
216 | else
217 | thumbPosAnimation->setEndValue((indicatorMargin.left() + indicatorMargin.right() + 2) * 2);
218 | thumbPosAnimation->start();
219 | }
220 |
221 | void Switch::setThumbPosition(const int& thumbPosition)
222 | {
223 | this->_thumbPosition = thumbPosition;
224 | update();
225 | emit thumbPositionChanged();
226 | }
227 |
228 | int Switch::thumbPosition()
229 | {
230 | return _thumbPosition;
231 | }
232 |
233 | EL_END_NAMESPACE
234 |
--------------------------------------------------------------------------------
/example/widget.cpp:
--------------------------------------------------------------------------------
1 | #include "widget.h"
2 | #include "QtAwesome.h"
3 | #include "el_avatar.h"
4 | #include "el_button.h"
5 | #include "el_checkbox.h"
6 | #include "el_input.h"
7 | #include "el_link.h"
8 | #include "el_messagebox.h"
9 | #include "el_select.h"
10 | #include "el_switch.h"
11 | #include "el_inputnumber.h"
12 | #include "el_radio.h"
13 | #include "el_card.h"
14 | #include "el_slider.h"
15 | #include "el_lineprogress.h"
16 | #include "el_circleprogress.h"
17 | #include "ui_widget.h"
18 |
19 | #include
20 | #include
21 | #include
22 | #include
23 | #include
24 |
25 | using namespace el;
26 |
27 | Widget::Widget(QWidget* parent)
28 | : QWidget(parent)
29 | , ui(new Ui::Widget)
30 | {
31 | ui->setupUi(this);
32 | setStyleSheet("background-color: white");
33 |
34 | QVBoxLayout* vLayout = new QVBoxLayout();
35 |
36 | QHBoxLayout* hLayout = new QHBoxLayout();
37 | vLayout->addLayout(hLayout);
38 |
39 | // Link 文字链接
40 | Link* link = new Link("默认链接", "https://www.baidu.com", Link::Danger, this);
41 | // link->setDisabled(true);
42 | connect(link, &Link::linkClicked, [](const QString& link) {
43 | qDebug() << "linkClicked" << link;
44 | });
45 |
46 | Link* link2 = new Link("成功链接", "https://www.baidu.com", Link::Success, this);
47 |
48 | hLayout->addWidget(link);
49 | hLayout->addWidget(link2);
50 |
51 | // Input 输入框
52 | QHBoxLayout* hLayout2 = new QHBoxLayout();
53 | vLayout->addLayout(hLayout2);
54 | Input* input = new Input(Input::Clearable, this);
55 | Input* input2 = new Input(Input::ShowPassword, this);
56 | Input* input3 = new Input(Input::Calendar, this);
57 | hLayout2->addWidget(input);
58 | hLayout2->addWidget(input2);
59 | hLayout2->addWidget(input3);
60 |
61 | // Button 按钮
62 | QHBoxLayout* hLayout3 = new QHBoxLayout();
63 | vLayout->addLayout(hLayout3);
64 | Button* btn = new Button("默认按钮");
65 | Button* btn2 = new Button("主要按钮", Button::BT_Primary);
66 | Button* btn3 = new Button("成功按钮", Button::BT_Success);
67 | Button* btn4 = new Button("警告按钮", Button::BT_Warning);
68 | Button* btn5 = new Button("危险按钮", Button::BT_Danger);
69 | Button* btn6 = new Button("信息按钮", Button::BT_Info);
70 |
71 | hLayout3->addWidget(btn);
72 | hLayout3->addWidget(btn2);
73 | hLayout3->addWidget(btn3);
74 | hLayout3->addWidget(btn4);
75 | hLayout3->addWidget(btn5);
76 | hLayout3->addWidget(btn6);
77 |
78 | // 圆角 按钮
79 | QHBoxLayout* hLayout4 = new QHBoxLayout();
80 | vLayout->addLayout(hLayout4);
81 | Button* rbtn2 = new Button("主要按钮", Button::BT_Primary, Button::BS_Round);
82 | Button* rbtn3 = new Button("成功按钮", Button::BT_Success, Button::BS_Round);
83 | Button* rbtn4 = new Button("警告按钮", Button::BT_Warning, Button::BS_Round);
84 | Button* rbtn5 = new Button("危险按钮", Button::BT_Danger, Button::BS_Round);
85 | Button* rbtn6 = new Button("信息按钮", Button::BT_Info, Button::BS_Round);
86 |
87 | hLayout4->addWidget(rbtn2);
88 | hLayout4->addWidget(rbtn3);
89 | hLayout4->addWidget(rbtn4);
90 | hLayout4->addWidget(rbtn5);
91 | hLayout4->addWidget(rbtn6);
92 |
93 | // ICON 按钮
94 | QHBoxLayout* hLayout5 = new QHBoxLayout();
95 | vLayout->addLayout(hLayout5);
96 | Button* ibtn = new Button(fa::fa_add, Button::BT_Default);
97 | Button* ibtn2 = new Button(fa::fa_add, Button::BT_Primary);
98 | Button* ibtn3 = new Button(fa::fa_bookmark, Button::BT_Success);
99 | Button* ibtn4 = new Button(fa::fa_camera, Button::BT_Warning);
100 | Button* ibtn5 = new Button(fa::fa_dashboard, Button::BT_Danger);
101 | Button* ibtn6 = new Button(fa::fa_edit, Button::BT_Info);
102 | Button* ibtn7 = new Button("搜索", fa::fa_search, Button::BT_Primary);
103 |
104 | hLayout5->addWidget(ibtn);
105 | hLayout5->addWidget(ibtn2);
106 | hLayout5->addWidget(ibtn3);
107 | hLayout5->addWidget(ibtn4);
108 | hLayout5->addWidget(ibtn5);
109 | hLayout5->addWidget(ibtn6);
110 | hLayout5->addWidget(ibtn7);
111 |
112 | // Switch 开关
113 | QHBoxLayout* hLayout6 = new QHBoxLayout();
114 | vLayout->addLayout(hLayout6);
115 | Switch* switch1 = new Switch("开关");
116 | Switch* switch2 = new Switch("禁用开关");
117 | switch2->setDisabled(true);
118 | hLayout6->addWidget(switch1);
119 | hLayout6->addWidget(switch2);
120 |
121 | // Checkbox 多选框
122 | Checkbox* cbx1 = new Checkbox("备选项");
123 | Checkbox* cbx2 = new Checkbox("备选项", Checkbox::LP_Left);
124 | Radio* rdo1 = new Radio("单选项1");
125 | Radio* rdo2 = new Radio("单选项2");
126 | QButtonGroup *group = new QButtonGroup(this);
127 | group->addButton(rdo1);
128 | group->addButton(rdo2);
129 | group->setExclusive(true);
130 |
131 | hLayout6->addWidget(cbx1);
132 | hLayout6->addWidget(cbx2);
133 | hLayout6->addWidget(rdo1);
134 | hLayout6->addWidget(rdo2);
135 |
136 | // Avatar 头像
137 | QHBoxLayout* hLayout7 = new QHBoxLayout();
138 | vLayout->addLayout(hLayout7);
139 | Avatar* avatar1 = new Avatar("姓");
140 | Avatar* avatar2 = new Avatar(QImage(":/avatar.png"));
141 | hLayout7->addWidget(avatar1);
142 | hLayout7->addWidget(avatar2);
143 |
144 | // MessageBox 弹框
145 | QHBoxLayout* hLayout8 = new QHBoxLayout();
146 | vLayout->addLayout(hLayout8);
147 | Button* btn7 = new Button("消息提示 Message Box", Button::BT_Default);
148 | connect(btn7, &Button::clicked, [this]() {
149 | int ret = MessageBox::alert(this, "标题名称", "这是一段内容", "确定");
150 | qDebug() << ret;
151 | });
152 | Button* btn8 = new Button("确认消息 Message Box", Button::BT_Default);
153 | connect(btn8, &Button::clicked, [this]() {
154 | int ret = MessageBox::confirm(this, "提示", "此操作将永久删除该文件, 是否继续?", "确定", "取消");
155 | qDebug() << ret;
156 | });
157 | Button* btn9 = new Button("错误消息 Message Box", Button::BT_Default);
158 | connect(btn9, &Button::clicked, [this]() {
159 | int ret = MessageBox::error(this, "错误", "文件不存在!\n请重新选择", "确定");
160 | qDebug() << ret;
161 | });
162 | hLayout8->addWidget(btn7);
163 | hLayout8->addWidget(btn8);
164 | hLayout8->addWidget(btn9);
165 |
166 | // Select 选择器
167 | QHBoxLayout* hLayout9 = new QHBoxLayout();
168 | vLayout->addLayout(hLayout9);
169 | Select* select1 = new Select();
170 | select1->addItems(QStringList() << "黄金糕"
171 | << "双皮奶"
172 | << "蚵仔煎"
173 | << "龙须面");
174 | hLayout9->addWidget(select1);
175 |
176 | QHBoxLayout* hLayout10 = new QHBoxLayout();
177 | vLayout->addLayout(hLayout10);
178 | InputNumber* inputNum1 = new InputNumber(0, 10);
179 | hLayout10->addWidget(inputNum1);
180 |
181 | QHBoxLayout* hLayout11 = new QHBoxLayout();
182 | vLayout->addLayout(hLayout11);
183 | Card* card1 = new Card(QIcon(":/avatar.png"), "卡片名称1", "列表内容 1");
184 | Card* card2 = new Card(QIcon(":/avatar.png"), "卡片名称2", "列表内容 1");
185 | card2->setEnabled(false);
186 | hLayout11->addWidget(card1);
187 | hLayout11->addWidget(card2);
188 |
189 | // 线形进度条
190 | QHBoxLayout* hLayout12 = new QHBoxLayout();
191 | vLayout->addLayout(hLayout12);
192 | LineProgress* lineProgress1 = new LineProgress();
193 | lineProgress1->setValue(50);
194 | LineProgress* lineProgress2 = new LineProgress();
195 | lineProgress2->setValue(70);
196 | lineProgress2->setStatus(LineProgress::Success);
197 | LineProgress* lineProgress3 = new LineProgress();
198 | lineProgress3->setValue(80);
199 | lineProgress3->setStatus(LineProgress::Warning);
200 | hLayout12->addWidget(lineProgress1);
201 | hLayout12->addWidget(lineProgress2);
202 | hLayout12->addWidget(lineProgress3);
203 |
204 | // 环形进度条
205 | QHBoxLayout* hLayout13 = new QHBoxLayout();
206 | vLayout->addLayout(hLayout13);
207 | CircleProgress* circleProgress1 = new CircleProgress();
208 | circleProgress1->setPercent(60);
209 | hLayout13->addWidget(circleProgress1);
210 | CircleProgress* circleProgress2 = new CircleProgress();
211 | circleProgress2->setPercent(80);
212 | circleProgress2->setStatus(CircleProgress::Exception);
213 | hLayout13->addWidget(circleProgress2);
214 |
215 | setLayout(vLayout);
216 | }
217 |
218 | Widget::~Widget()
219 | {
220 | delete ui;
221 | }
222 |
--------------------------------------------------------------------------------
/qelement/el_slider.cpp:
--------------------------------------------------------------------------------
1 | #include "el_slider.h"
2 | #include
3 | #include
4 | #include
5 | #include
6 | #include
7 |
8 | #define QT_MATERIAL_SLIDER_MARGIN 30
9 |
10 | EL_BEGIN_NAMESPACE
11 |
12 | OverlayWidget::OverlayWidget(QWidget* parent)
13 | : QWidget(parent)
14 | {
15 | if (parent) {
16 | parent->installEventFilter(this);
17 | }
18 | }
19 |
20 | OverlayWidget::~OverlayWidget()
21 | {
22 | }
23 |
24 | bool OverlayWidget::event(QEvent* event)
25 | {
26 | if (!parent()) {
27 | return QWidget::event(event);
28 | }
29 | switch (event->type()) {
30 | case QEvent::ParentChange: {
31 | parent()->installEventFilter(this);
32 | setGeometry(overlayGeometry());
33 | break;
34 | }
35 | case QEvent::ParentAboutToChange: {
36 | parent()->removeEventFilter(this);
37 | break;
38 | }
39 | default:
40 | break;
41 | }
42 | return QWidget::event(event);
43 | }
44 |
45 | bool OverlayWidget::eventFilter(QObject* obj, QEvent* event)
46 | {
47 | switch (event->type()) {
48 | case QEvent::Move:
49 | case QEvent::Resize:
50 | setGeometry(overlayGeometry());
51 | break;
52 | default:
53 | break;
54 | }
55 | return QWidget::eventFilter(obj, event);
56 | }
57 |
58 | QRect OverlayWidget::overlayGeometry() const
59 | {
60 | QWidget* widget = parentWidget();
61 | if (!widget) {
62 | return QRect();
63 | }
64 | return widget->rect();
65 | }
66 |
67 | SliderThumb::SliderThumb(Slider* slider)
68 | : OverlayWidget(slider->parentWidget())
69 | , _slider(slider)
70 | , _diameter(16)
71 | , _borderWidth(2)
72 | , _offset(0)
73 | {
74 | slider->installEventFilter(this);
75 | setAttribute(Qt::WA_TransparentForMouseEvents, true);
76 | }
77 |
78 | SliderThumb::~SliderThumb()
79 | {
80 | }
81 |
82 | void SliderThumb::setDiameter(qreal diameter)
83 | {
84 | _diameter = diameter;
85 | update();
86 | }
87 |
88 | qreal SliderThumb::diameter() const
89 | {
90 | return _diameter;
91 | }
92 |
93 | void SliderThumb::setBorderWidth(qreal width)
94 | {
95 | _borderWidth = width;
96 | update();
97 | }
98 |
99 | qreal SliderThumb::borderWidth() const
100 | {
101 | return _borderWidth;
102 | }
103 |
104 | void SliderThumb::setBorderColor(const QColor& color)
105 | {
106 | _borderColor = color;
107 | update();
108 | }
109 |
110 | QColor SliderThumb::borderColor() const
111 | {
112 | return _borderColor;
113 | }
114 |
115 | void SliderThumb::setFillColor(const QColor& color)
116 | {
117 | _fillColor = color;
118 | update();
119 | }
120 |
121 | QColor SliderThumb::fillColor() const
122 | {
123 | return _fillColor;
124 | }
125 |
126 | void SliderThumb::setHaloSize(qreal size)
127 | {
128 | _haloSize = size;
129 | update();
130 | }
131 |
132 | qreal SliderThumb::haloSize() const
133 | {
134 | return _haloSize;
135 | }
136 |
137 | void SliderThumb::setHaloColor(const QColor& color)
138 | {
139 | _haloColor = color;
140 | update();
141 | }
142 |
143 | QColor SliderThumb::haloColor() const
144 | {
145 | return _haloColor;
146 | }
147 |
148 | void SliderThumb::setOffset(int offset)
149 | {
150 | _offset = offset;
151 | update();
152 | }
153 |
154 | int SliderThumb::offset() const
155 | {
156 | return _offset;
157 | }
158 |
159 | bool SliderThumb::eventFilter(QObject* obj, QEvent* event)
160 | {
161 | if (QEvent::ParentChange == event->type()) {
162 | setParent(_slider->parentWidget());
163 | }
164 |
165 | return QWidget::eventFilter(obj, event);
166 | }
167 |
168 | void SliderThumb::paintEvent(QPaintEvent* event)
169 | {
170 | Q_UNUSED(event)
171 |
172 | QPainter painter(this);
173 | painter.setRenderHint(QPainter::Antialiasing);
174 |
175 | // Halo
176 |
177 | QBrush brush;
178 | brush.setStyle(Qt::SolidPattern);
179 | brush.setColor(_haloColor);
180 | painter.setBrush(brush);
181 | painter.setPen(Qt::NoPen);
182 |
183 | QPointF disp = Qt::Horizontal == _slider->orientation()
184 | ? QPointF(QT_MATERIAL_SLIDER_MARGIN + _offset, _slider->height() / 2)
185 | : QPointF(_slider->width() / 2, QT_MATERIAL_SLIDER_MARGIN + _offset);
186 |
187 | QRectF halo((_slider->pos() - QPointF(_haloSize, _haloSize) / 2) + disp,
188 | QSizeF(_haloSize, _haloSize));
189 |
190 | painter.setOpacity(0.15);
191 | painter.drawEllipse(halo);
192 |
193 | // Knob
194 |
195 | const bool isMin = _slider->value() == _slider->minimum();
196 |
197 | brush.setColor(_slider->isEnabled()
198 | ? _fillColor
199 | : _slider->disabledColor());
200 | painter.setBrush(!_slider->isEnabled() && isMin
201 | ? Qt::NoBrush
202 | : brush);
203 |
204 | if (_slider->isEnabled() || isMin) {
205 | QPen pen;
206 | pen.setColor(_borderColor);
207 | pen.setWidthF((isMin && !_slider->isEnabled()) ? 1.7 : _borderWidth);
208 | painter.setPen(pen);
209 | } else {
210 | painter.setPen(Qt::NoPen);
211 | }
212 |
213 | QRectF geometry = Qt::Horizontal == _slider->orientation()
214 | ? QRectF(_offset, _slider->height() / 2 - QT_MATERIAL_SLIDER_MARGIN,
215 | QT_MATERIAL_SLIDER_MARGIN * 2, QT_MATERIAL_SLIDER_MARGIN * 2)
216 | .translated(_slider->pos())
217 | : QRectF(_slider->width() / 2 - QT_MATERIAL_SLIDER_MARGIN, _offset,
218 | QT_MATERIAL_SLIDER_MARGIN * 2, QT_MATERIAL_SLIDER_MARGIN * 2)
219 | .translated(_slider->pos());
220 |
221 | qreal s = _slider->isEnabled() ? _diameter : 7;
222 |
223 | QRectF thumb(0, 0, s, s);
224 |
225 | thumb.moveCenter(geometry.center());
226 |
227 | painter.setOpacity(1);
228 | painter.drawEllipse(thumb);
229 | }
230 |
231 | // SliderTrack
232 | SliderTrack::SliderTrack(SliderThumb* thumb, Slider* slider)
233 | : OverlayWidget(slider->parentWidget())
234 | , _slider(slider)
235 | , _thumb(thumb)
236 | {
237 | slider->installEventFilter(this);
238 |
239 | setAttribute(Qt::WA_TransparentForMouseEvents, true);
240 |
241 | connect(slider, SIGNAL(sliderMoved(int)), this, SLOT(update()));
242 | }
243 |
244 | SliderTrack::~SliderTrack()
245 | {
246 | }
247 |
248 | void SliderTrack::setFillColor(const QColor& color)
249 | {
250 | _fillColor = color;
251 | update();
252 | }
253 |
254 | QColor SliderTrack::fillColor() const
255 | {
256 | return _fillColor;
257 | }
258 |
259 | void SliderTrack::setTrackWidth(int width)
260 | {
261 | _trackWidth = width;
262 | update();
263 | }
264 |
265 | int SliderTrack::trackWidth() const
266 | {
267 | return _trackWidth;
268 | }
269 |
270 | bool SliderTrack::eventFilter(QObject* obj, QEvent* event)
271 | {
272 | if (QEvent::ParentChange == event->type()) {
273 | setParent(_slider->parentWidget());
274 | }
275 |
276 | return QWidget::eventFilter(obj, event);
277 | }
278 |
279 | void SliderTrack::paintEvent(QPaintEvent* event)
280 | {
281 | Q_UNUSED(event)
282 |
283 | QPainter painter(this);
284 | painter.setRenderHint(QPainter::Antialiasing);
285 |
286 | QBrush fg;
287 | fg.setStyle(Qt::SolidPattern);
288 | fg.setColor(_slider->isEnabled() ? _slider->thumbColor()
289 | : _slider->disabledColor());
290 | QBrush bg;
291 | bg.setStyle(Qt::SolidPattern);
292 | bg.setColor(_slider->isEnabled() ? _fillColor
293 | : _slider->disabledColor());
294 |
295 | qreal offset = _thumb->offset();
296 |
297 | if (Qt::Horizontal == _slider->orientation()) {
298 | painter.translate(_slider->x() + QT_MATERIAL_SLIDER_MARGIN,
299 | _slider->y() + _slider->height() / 2
300 | - static_cast(_trackWidth) / 2);
301 | } else {
302 | painter.translate(_slider->x() + _slider->width() / 2
303 | - static_cast(_trackWidth) / 2,
304 | _slider->y() + QT_MATERIAL_SLIDER_MARGIN);
305 | }
306 |
307 | QRectF geometry = Qt::Horizontal == _slider->orientation()
308 | ? QRectF(0, 0, _slider->width() - QT_MATERIAL_SLIDER_MARGIN * 2, _trackWidth)
309 | : QRectF(0, 0, _trackWidth, _slider->height() - QT_MATERIAL_SLIDER_MARGIN * 2);
310 |
311 | QRectF bgRect;
312 | QRectF fgRect;
313 |
314 | if (Qt::Horizontal == _slider->orientation()) {
315 | fgRect = QRectF(0, 0, offset, _trackWidth);
316 | bgRect = QRectF(offset, 0, _slider->width(), _trackWidth).intersected(geometry);
317 | } else {
318 | fgRect = QRectF(0, 0, _trackWidth, offset);
319 | bgRect = QRectF(0, offset, _trackWidth, _slider->height()).intersected(geometry);
320 | }
321 |
322 | if (!_slider->isEnabled()) {
323 | fgRect = fgRect.width() < 9 ? QRectF() : fgRect.adjusted(0, 0, -6, 0);
324 | bgRect = bgRect.width() < 9 ? QRectF() : bgRect.adjusted(6, 0, 0, 0);
325 | }
326 |
327 | if (_slider->invertedAppearance()) {
328 | qSwap(bgRect, fgRect);
329 | }
330 |
331 | painter.fillRect(bgRect, bg);
332 | painter.fillRect(fgRect, fg);
333 | }
334 |
335 | // Slider
336 | Slider::Slider(QWidget* parent)
337 | : QAbstractSlider(parent)
338 | , _thumbColor(0x409eff)
339 | , _trackColor(0xe4e7ed)
340 | , _disabledColor(0xc0c4cc)
341 | {
342 | init();
343 | }
344 |
345 | void Slider::setThumbColor(const QColor& color)
346 | {
347 | _thumbColor = color;
348 | update();
349 | }
350 |
351 | QColor Slider::thumbColor() const
352 | {
353 | return _thumbColor;
354 | }
355 |
356 | void Slider::setTrackColor(const QColor& color)
357 | {
358 | _trackColor = color;
359 | update();
360 | }
361 |
362 | void Slider::setDisabledColor(const QColor& color)
363 | {
364 | _disabledColor = color;
365 | update();
366 | }
367 |
368 | QColor Slider::disabledColor() const
369 | {
370 | return _disabledColor;
371 | }
372 |
373 | void Slider::setPageStepMode(bool pageStep)
374 | {
375 | _pageStepMode = pageStep;
376 | }
377 |
378 | bool Slider::pageStepMode() const
379 | {
380 | return _pageStepMode;
381 | }
382 |
383 | QSize Slider::minimumSizeHint() const
384 | {
385 | return Qt::Horizontal == orientation()
386 | ? QSize(130, 34)
387 | : QSize(34, 130);
388 | }
389 |
390 | void Slider::setInvertedAppearance(bool value)
391 | {
392 | QAbstractSlider::setInvertedAppearance(value);
393 |
394 | updateThumbOffset();
395 | }
396 |
397 | void Slider::sliderChange(SliderChange change)
398 | {
399 | if (SliderOrientationChange == change) {
400 | QSizePolicy sp(QSizePolicy::Expanding, QSizePolicy::Fixed);
401 | if (orientation() == Qt::Vertical) {
402 | sp.transpose();
403 | }
404 | setSizePolicy(sp);
405 | } else if (SliderValueChange == change) {
406 | if (minimum() == value()) {
407 | triggerAction(SliderToMinimum);
408 | // d->stateMachine->postEvent(new QtMaterialStateTransitionEvent(SliderChangedToMinimum));
409 | } else if (maximum() == value()) {
410 | triggerAction(SliderToMaximum);
411 | }
412 | if (minimum() == _oldValue) {
413 | // d->stateMachine->postEvent(new QtMaterialStateTransitionEvent(SliderChangedFromMinimum));
414 | }
415 | _oldValue = value();
416 | }
417 |
418 | updateThumbOffset();
419 |
420 | QAbstractSlider::sliderChange(change);
421 | }
422 |
423 | void Slider::mouseMoveEvent(QMouseEvent* event)
424 | {
425 | if (isSliderDown()) {
426 | setSliderPosition(valueFromPosition(event->pos()));
427 | } else {
428 | QRectF track(trackBoundingRect().adjusted(-2, -2, 2, 2));
429 |
430 | if (track.contains(event->pos()) != _hoverTrack) {
431 | _hoverTrack = !_hoverTrack;
432 | update();
433 | }
434 |
435 | QRectF thumb(0, 0, 16, 16);
436 | thumb.moveCenter(thumbBoundingRect().center());
437 |
438 | if (thumb.contains(event->pos()) != _hoverThumb) {
439 | _hoverThumb = !_hoverThumb;
440 | // QPoint point = mapToGlobal(event->pos());
441 | // QToolTip::showText(point, QString::number(value()));
442 | update();
443 | }
444 |
445 | setHovered(_hoverTrack || _hoverThumb);
446 | }
447 |
448 | QAbstractSlider::mouseMoveEvent(event);
449 | }
450 |
451 | void Slider::mousePressEvent(QMouseEvent* event)
452 | {
453 | const QPoint pos = event->pos();
454 |
455 | QRectF thumb(0, 0, 16, 16);
456 | thumb.moveCenter(thumbBoundingRect().center());
457 |
458 | if (thumb.contains(pos)) {
459 | setSliderDown(true);
460 | return;
461 | }
462 |
463 | if (!_pageStepMode) {
464 | setSliderPosition(valueFromPosition(event->pos()));
465 | _thumb->setHaloSize(0);
466 | setSliderDown(true);
467 | return;
468 | }
469 |
470 | _step = true;
471 | _stepTo = valueFromPosition(pos);
472 |
473 | SliderAction action = _stepTo > sliderPosition()
474 | ? SliderPageStepAdd
475 | : SliderPageStepSub;
476 |
477 | triggerAction(action);
478 | setRepeatAction(action, 400, 8);
479 | }
480 |
481 | void Slider::mouseReleaseEvent(QMouseEvent* event)
482 | {
483 | if (isSliderDown()) {
484 | setSliderDown(false);
485 | } else if (_step) {
486 | _step = false;
487 | setRepeatAction(SliderNoAction, 0);
488 | }
489 |
490 | QAbstractSlider::mouseReleaseEvent(event);
491 | }
492 |
493 | void Slider::leaveEvent(QEvent* event)
494 | {
495 | if (_hoverTrack) {
496 | _hoverTrack = false;
497 | update();
498 | }
499 | if (_hoverThumb) {
500 | _hoverThumb = false;
501 | update();
502 | }
503 |
504 | setHovered(false);
505 |
506 | QAbstractSlider::leaveEvent(event);
507 | }
508 |
509 | void Slider::updateThumbOffset()
510 | {
511 | const int offset = QCommonStyle::sliderPositionFromValue(
512 | minimum(),
513 | maximum(),
514 | sliderPosition(),
515 | Qt::Horizontal == orientation()
516 | ? width() - QT_MATERIAL_SLIDER_MARGIN * 2
517 | : height() - QT_MATERIAL_SLIDER_MARGIN * 2,
518 | invertedAppearance());
519 |
520 | _thumb->setOffset(offset);
521 | }
522 |
523 | void Slider::init()
524 | {
525 | _thumb = new SliderThumb(this);
526 | _track = new SliderTrack(_thumb, this);
527 | _stepTo = 0;
528 | _oldValue = value();
529 | _trackWidth = 6;
530 | _track->setTrackWidth(_trackWidth);
531 |
532 | _hoverTrack = false;
533 | _hoverThumb = false;
534 | _hover = false;
535 | _step = false;
536 | _pageStepMode = true;
537 |
538 | setMouseTracking(true);
539 | setFocusPolicy(Qt::StrongFocus);
540 | setPageStep(1);
541 |
542 | setCursor(Qt::PointingHandCursor);
543 |
544 | QSizePolicy sp(QSizePolicy::Expanding,
545 | QSizePolicy::Fixed);
546 | if (orientation() == Qt::Vertical) {
547 | sp.transpose();
548 | }
549 |
550 | setSizePolicy(sp);
551 | setAttribute(Qt::WA_WState_OwnSizePolicy, false);
552 |
553 | _track->setFillColor(_trackColor);
554 | QColor holeColor = palette().color(QPalette::Base);
555 | if (parentWidget()) {
556 | holeColor = parentWidget()->palette().color(backgroundRole());
557 | }
558 | _thumb->setFillColor(holeColor);
559 | _thumb->setHaloColor(_trackColor);
560 | _thumb->setBorderColor(_thumbColor);
561 | }
562 |
563 | QRectF Slider::trackBoundingRect() const
564 | {
565 | qreal hw = static_cast(_trackWidth) / 2;
566 |
567 | return Qt::Horizontal == orientation()
568 | ? QRectF(QT_MATERIAL_SLIDER_MARGIN, height() / 2 - hw,
569 | width() - QT_MATERIAL_SLIDER_MARGIN * 2, hw * 2)
570 | : QRectF(width() / 2 - hw, QT_MATERIAL_SLIDER_MARGIN, hw * 2,
571 | height() - QT_MATERIAL_SLIDER_MARGIN * 2);
572 | }
573 |
574 | QRectF Slider::thumbBoundingRect() const
575 | {
576 | return Qt::Horizontal == orientation()
577 | ? QRectF(_thumb->offset(), height() / 2 - QT_MATERIAL_SLIDER_MARGIN,
578 | QT_MATERIAL_SLIDER_MARGIN * 2, QT_MATERIAL_SLIDER_MARGIN * 2)
579 | : QRectF(width() / 2 - QT_MATERIAL_SLIDER_MARGIN, _thumb->offset(),
580 | QT_MATERIAL_SLIDER_MARGIN * 2, QT_MATERIAL_SLIDER_MARGIN * 2);
581 | }
582 |
583 | int Slider::valueFromPosition(const QPoint& pos) const
584 | {
585 | const int position = Qt::Horizontal == orientation() ? pos.x() : pos.y();
586 |
587 | const int span = Qt::Horizontal == orientation()
588 | ? width() - QT_MATERIAL_SLIDER_MARGIN * 2
589 | : height() - QT_MATERIAL_SLIDER_MARGIN * 2;
590 |
591 | return QCommonStyle::sliderValueFromPosition(
592 | minimum(),
593 | maximum(),
594 | position - QT_MATERIAL_SLIDER_MARGIN,
595 | span,
596 | invertedAppearance());
597 | }
598 |
599 | void Slider::setHovered(bool status)
600 | {
601 | if (_hover == status) {
602 | return;
603 | }
604 | _hover = status;
605 | update();
606 | }
607 |
608 | EL_END_NAMESPACE
609 |
--------------------------------------------------------------------------------