├── HTYDock
├── preview.png
├── launcher.png
├── res.qrc
├── install.sh
├── main.cpp
├── datetimewidget.h
├── HTYDock.pro
├── netspeedwidget.h
├── README.md
├── trashwidget.h
├── appwidget.h
├── mainwindow.h
├── appwidget.cpp
├── trashwidget.cpp
├── netspeedwidget.cpp
├── datetimewidget.cpp
└── mainwindow.cpp
/HTYDock:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sonichy/HTYDock_KWin/HEAD/HTYDock
--------------------------------------------------------------------------------
/preview.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sonichy/HTYDock_KWin/HEAD/preview.png
--------------------------------------------------------------------------------
/launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sonichy/HTYDock_KWin/HEAD/launcher.png
--------------------------------------------------------------------------------
/res.qrc:
--------------------------------------------------------------------------------
1 |
2 |
3 | launcher.png
4 |
5 |
6 |
--------------------------------------------------------------------------------
/install.sh:
--------------------------------------------------------------------------------
1 | s="[Desktop Entry]\nName=海天鹰Dock\nComment=HTY Dock\nExec=`pwd`/HTYDock\nIcon=`pwd`/launcher.png\nPath=`pwd`\nType=Application\nTerminal=false\nCategories=System;"
2 | echo -e $s > HTYDock.desktop
3 | cp `pwd`/HTYDock.desktop ~/.local/share/applications/HTYDock.desktop
--------------------------------------------------------------------------------
/main.cpp:
--------------------------------------------------------------------------------
1 | #include "mainwindow.h"
2 | #include
3 |
4 | int main(int argc, char *argv[])
5 | {
6 | qSetMessagePattern("[ %{file}: %{line} ] %{message}");
7 | QApplication a(argc, argv);
8 | a.setOrganizationName("HTY");
9 | a.setApplicationName("HTYDock");
10 | MainWindow w;
11 | w.show();
12 | return a.exec();
13 | }
--------------------------------------------------------------------------------
/datetimewidget.h:
--------------------------------------------------------------------------------
1 | #ifndef DATETIMEWIDGET_H
2 | #define DATETIMEWIDGET_H
3 |
4 | #include
5 | #include
6 | #include
7 |
8 | class DatetimeWidget : public QWidget
9 | {
10 | Q_OBJECT
11 | public:
12 | explicit DatetimeWidget(QWidget *parent = 0);
13 |
14 | private:
15 | QString clock_type;
16 | bool isMouseOn = false;
17 | QCalendarWidget *calendar;
18 |
19 | protected:
20 | void paintEvent(QPaintEvent *event);
21 | void enterEvent(QEvent *event);
22 | void leaveEvent(QEvent *event);
23 | void mousePressEvent(QMouseEvent *event);
24 |
25 | signals:
26 |
27 | public slots:
28 |
29 | };
30 |
31 | #endif // DATETIMEWIDGET_H
--------------------------------------------------------------------------------
/HTYDock.pro:
--------------------------------------------------------------------------------
1 | #-------------------------------------------------
2 | #
3 | # Project created by QtCreator 2020-03-27T11:29:29
4 | #
5 | #-------------------------------------------------
6 |
7 | QT += core gui KWindowSystem x11extras
8 |
9 | greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
10 |
11 | TARGET = HTYDock
12 | TEMPLATE = app
13 |
14 | CONFIG += c++11
15 |
16 | SOURCES += main.cpp\
17 | mainwindow.cpp \
18 | datetimewidget.cpp \
19 | appwidget.cpp \
20 | netspeedwidget.cpp \
21 | trashwidget.cpp
22 |
23 | HEADERS += mainwindow.h \
24 | datetimewidget.h \
25 | appwidget.h \
26 | netspeedwidget.h \
27 | trashwidget.h
28 |
29 | RESOURCES += \
30 | res.qrc
--------------------------------------------------------------------------------
/netspeedwidget.h:
--------------------------------------------------------------------------------
1 | #ifndef NETSPEEDWIDGET_H
2 | #define NETSPEEDWIDGET_H
3 |
4 | #include
5 | #include
6 |
7 | class NetSpeedWidget : public QWidget
8 | {
9 | Q_OBJECT
10 | public:
11 | explicit NetSpeedWidget(QWidget *parent = 0);
12 |
13 | private:
14 | long int i, db, ub, dbt, ubt, dbt1, ubt1, dbt0, ubt0, tt0, idle0;
15 | QString KB(long k);
16 | QString NB(long b);
17 | QString BS(long b);
18 | QString startup;
19 | bool isMouseOn = false;
20 | QLabel *label;
21 |
22 | protected:
23 | void paintEvent(QPaintEvent *event);
24 | void enterEvent(QEvent *event);
25 | void leaveEvent(QEvent *event);
26 |
27 | signals:
28 |
29 | public slots:
30 |
31 | };
32 |
33 | #endif // NETSPEEDWIDGET_H
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | 基于 Qt 和 KWindowSystem(窗管、背景模糊)的 Dock 程序。
2 | 已编译的 HTYDock 适用 64 位 Linux Qt>5.11。
3 |
4 | 
5 | ### 运行依赖
6 | libkf5windowsystem5
7 |
8 | ### 编译依赖
9 | libkf5windowsystem-dev qmake make libqt5extras5-dev
10 |
11 | ### 参考
12 | https://github.com/linuxdeepin/dde-dock
13 | https://github.com/pandaos/panda-dock
14 | https://github.com/KDE/latte-dock
15 | [非系统程序获取图标](https://github.com/linuxdeepin/deepin-system-monitor/blob/117a3b90cb02ecca4990f2136400147c59801dc5/src/utils.cpp#L379)
16 | [为QWidget创建鼠标点击信号](https://blog.csdn.net/l285345042/article/details/8161320)
17 |
18 | ### KWindowSystem API
19 | https://api.kde.org/frameworks/kwindowsystem/html/index.html
20 |
21 | ### 版本日志
22 | V2.0 (2020-04)
23 | 自定义 QWidget 实现悬浮预览窗。
24 |
25 | V1.0 (2020-03)
26 | 使用 QPushButton 做按钮。
27 |
28 | ### 已知问题
29 | 预览窗截图不对:除了深度文管,其他窗口最小化以后都截屏。
--------------------------------------------------------------------------------
/trashwidget.h:
--------------------------------------------------------------------------------
1 | #ifndef TRASHWIDGET_H
2 | #define TRASHWIDGET_H
3 |
4 | #include
5 | #include
6 |
7 | class TrashWidget : public QWidget
8 | {
9 | Q_OBJECT
10 | public:
11 | explicit TrashWidget(QWidget *parent = 0);
12 | QPixmap pixmap_icon, pixmap;
13 |
14 | private:
15 | bool isMouseOn = false;
16 | QPixmap pixmap_dragEnter;
17 | QPoint point_mouse;
18 | QString dir_trash;
19 |
20 | protected:
21 | void paintEvent(QPaintEvent *event);
22 | void enterEvent(QEvent *event);
23 | void leaveEvent(QEvent *event);
24 | void mousePressEvent(QMouseEvent *event);
25 | void mouseReleaseEvent(QMouseEvent *event);
26 | void dragEnterEvent(QDragEnterEvent *event);
27 | void dragLeaveEvent(QDragLeaveEvent *event);
28 | void dropEvent(QDropEvent *event);
29 |
30 | signals:
31 |
32 | public slots:
33 | void trashChanged(QString path);
34 |
35 | };
36 |
37 | #endif // TRASHWIDGET_H
--------------------------------------------------------------------------------
/appwidget.h:
--------------------------------------------------------------------------------
1 | #ifndef APPWIDGET_H
2 | #define APPWIDGET_H
3 |
4 | #include
5 | #include
6 | #include
7 | #include
8 | #include
9 | #include
10 |
11 | struct Dock : QObjectUserData
12 | {
13 | WId wid;
14 | };
15 |
16 | class AppWidget : public QWidget
17 | {
18 | Q_OBJECT
19 | public:
20 | explicit AppWidget(QWidget *parent = 0);
21 | QList list_wid;
22 | int index=0;
23 | QButtonGroup *buttonGroup;
24 | QString name, className;
25 | QPixmap icon;
26 | bool isActive = false;
27 | void addPreview(WId wid);
28 | void removePreview(WId wid);
29 |
30 | private:
31 | bool isMouseOn = false;
32 | QWidget *widget_preview;
33 | QBoxLayout *boxLayout;
34 | QPoint point_mouse;
35 | QTimer *timer;
36 |
37 | protected:
38 | void paintEvent(QPaintEvent *event);
39 | void enterEvent(QEvent *event);
40 | void leaveEvent(QEvent *event);
41 | void mousePressEvent(QMouseEvent *event);
42 | void mouseReleaseEvent(QMouseEvent *event);
43 |
44 | signals:
45 | void clicked();
46 |
47 | public slots:
48 |
49 | };
50 |
51 | #endif // APPWIDGET_H
--------------------------------------------------------------------------------
/mainwindow.h:
--------------------------------------------------------------------------------
1 | #ifndef MAINWINDOW_H
2 | #define MAINWINDOW_H
3 |
4 | #include "datetimewidget.h"
5 | #include "netspeedwidget.h"
6 | #include "appwidget.h"
7 | #include "trashwidget.h"
8 | #include
9 | #include
10 | #include
11 | #include
12 | #include
13 | #include
14 |
15 | class MainWindow : public QMainWindow
16 | {
17 | Q_OBJECT
18 |
19 | public:
20 | MainWindow(QWidget *parent = 0);
21 | ~MainWindow();
22 |
23 | protected:
24 | void paintEvent(QPaintEvent *event);
25 |
26 | private:
27 | int h, count_plugin=0;
28 | QString qss, mode, position;
29 | QWidget *widget_app;
30 | QPushButton *pushButton_launcher, *pushButton_desktop;
31 | QBoxLayout *boxLayout, *boxLayout_app;
32 | QSize size;
33 | QList list_appWidget;
34 | NET::Properties properties = NET::WMState | NET::XAWMState | NET::WMDesktop | NET::WMVisibleName | NET::WMGeometry | NET::WMWindowType;
35 | NET::Properties2 properties2 = NET::WM2WindowClass | NET::WM2AllowedActions | NET::WM2DesktopFileName;
36 | QSettings settings;
37 | DatetimeWidget *datetimeWidget;
38 | NetSpeedWidget *netSpeedWidget;
39 | TrashWidget *trashWidget;
40 | void addMenus();
41 | void refit();
42 | void resizeIcon(int w);
43 |
44 | private slots:
45 | void buttonClicked(AppWidget *appWidget);
46 | void windowAdded(WId wid);
47 | void windowRemoved(WId wid);
48 | void activeWindowChanged(WId wid);
49 | void windowChanged(WId wid, NET::Properties properties, NET::Properties2 properties2);
50 |
51 | };
52 |
53 | #endif // MAINWINDOW_H
--------------------------------------------------------------------------------
/appwidget.cpp:
--------------------------------------------------------------------------------
1 | #include "appwidget.h"
2 | #include
3 | #include
4 | #include
5 | #include
6 | #include
7 |
8 | AppWidget::AppWidget(QWidget *parent) : QWidget(parent)
9 | {
10 | widget_preview = new QWidget;
11 | boxLayout = new QBoxLayout(QBoxLayout::LeftToRight);
12 | widget_preview->setLayout(boxLayout);
13 | widget_preview->setWindowFlags(Qt::Tool | Qt::FramelessWindowHint);
14 | buttonGroup = new QButtonGroup;
15 | timer = new QTimer(this);
16 | connect(timer, SIGNAL(timeout()), widget_preview, SLOT(show()));
17 | timer->setSingleShot(true);
18 | }
19 |
20 | void AppWidget::enterEvent(QEvent *event)
21 | {
22 | Q_UNUSED(event);
23 | isMouseOn = true;
24 | update();
25 | QScreen *screen = QApplication::primaryScreen();
26 | for (int i=0; ibuttons().count(); i++) {
27 | QAbstractButton *button = buttonGroup->buttons().at(i);
28 | Dock *dock = static_cast(button->userData(Qt::UserRole));
29 | button->setIcon(QIcon(screen->grabWindow(dock->wid,0,0,-1,-1).scaled(widget_preview->size(), Qt::KeepAspectRatio)));
30 | }
31 | QSettings settings(QCoreApplication::organizationName(), QCoreApplication::applicationName());
32 | QString position = settings.value("Position", "Bottom").toString();
33 | int x1=0, y1=0;
34 | if (position == "Bottom") {
35 | x1 = mapToGlobal(QPoint(0,0)).x() + width()/2 - widget_preview->width()/2;
36 | y1 = mapToGlobal(QPoint(0,0)).y() - widget_preview->height();
37 | } else if (position == "Top") {
38 | x1 = mapToGlobal(QPoint(0,0)).x() + width()/2 - widget_preview->width()/2;
39 | y1 = height();
40 | } else if (position == "Left") {
41 | x1 = width();
42 | y1 = mapToGlobal(QPoint(0,0)).y() + height()/2 - widget_preview->height()/2;
43 | } else if (position == "Right") {
44 | x1 = QApplication::desktop()->width() - width() - widget_preview->width();
45 | y1 = mapToGlobal(QPoint(0,0)).y() + height()/2 - widget_preview->height()/2;
46 | }
47 | widget_preview->move(x1, y1);
48 | timer->start(1000);
49 | }
50 |
51 | void AppWidget::leaveEvent(QEvent *event)
52 | {
53 | Q_UNUSED(event);
54 | isMouseOn = false;
55 | update();
56 | if(widget_preview->isHidden())
57 | timer->stop();
58 | else
59 | widget_preview->hide();
60 | }
61 |
62 | void AppWidget::paintEvent(QPaintEvent *event)
63 | {
64 | Q_UNUSED(event);
65 | QPainter painter(this);
66 | painter.setRenderHint(QPainter::Antialiasing, true);
67 | painter.setRenderHint(QPainter::SmoothPixmapTransform, true);
68 | painter.setPen(Qt::NoPen);
69 | if (isActive) {
70 | //渐变色失败
71 | // QRadialGradient radialGradient(width()/2,height()/2,width()/3,width()/2,height()/2);
72 | // radialGradient.setColorAt(0.0,Qt::white);
73 | // radialGradient.setColorAt(1.0,Qt::blue);
74 | // painter.setBrush(QBrush(radialGradient));
75 | //painter.setBrush(QColor(48,140,198,200));//下划线
76 | //painter.drawRect(rect().adjusted(10, height()-2, -10, 0));
77 | painter.setBrush(QColor(255,255,255,30));//蒙板
78 | painter.drawRoundRect(rect(), 50, 50);
79 | }
80 | if (isMouseOn) {
81 | painter.setBrush(QColor(255,255,255,30));
82 | painter.drawRoundRect(rect(), 50, 50);
83 | }
84 | painter.drawPixmap(rect().adjusted(3,3,-3,-3), icon);
85 | if (list_wid.count() > 1) {
86 | painter.setBrush(QColor(255,0,0,100));
87 | painter.drawEllipse(QRect(0,0,11,11));
88 | painter.setPen(Qt::white);
89 | QFont font = this->font();
90 | font.setPointSize(6);
91 | painter.setFont(font);
92 | painter.drawText(QRect(0,0,10,10), Qt::AlignCenter, QString::number(list_wid.count()));
93 | }
94 | }
95 |
96 | void AppWidget::mousePressEvent(QMouseEvent *event)
97 | {
98 | point_mouse = QPoint(event->x(), event->y());
99 | widget_preview->hide();
100 | }
101 |
102 | void AppWidget::mouseReleaseEvent(QMouseEvent *ev)
103 | {
104 | if (point_mouse == QPoint(ev->x(), ev->y()))
105 | emit clicked();
106 | }
107 |
108 | void AppWidget::addPreview(WId wid)
109 | {
110 | QPushButton *button = new QPushButton;
111 | button->setFixedSize(150,100);
112 | button->setIconSize(button->size());
113 | Dock *dock = new Dock;
114 | dock->wid = wid;
115 | button->setUserData(Qt::UserRole, dock);
116 | buttonGroup->addButton(button);
117 | boxLayout->addWidget(button);
118 | }
119 |
120 | void AppWidget::removePreview(WId wid)
121 | {
122 | for (int i=0; ibuttons().count(); i++) {
123 | QAbstractButton *button = buttonGroup->buttons().at(i);
124 | Dock *dock = static_cast(button->userData(Qt::UserRole));
125 | if (dock->wid == wid) {
126 | //qDebug() << dock->wid;
127 | boxLayout->removeWidget(button);
128 | buttonGroup->removeButton(button);
129 | button->deleteLater();
130 | }
131 | }
132 | }
--------------------------------------------------------------------------------
/trashwidget.cpp:
--------------------------------------------------------------------------------
1 | #include "trashwidget.h"
2 | #include
3 | #include
4 | #include
5 | #include
6 | #include
7 | #include
8 | #include
9 | #include
10 | #include
11 | #include
12 | #include
13 |
14 | TrashWidget::TrashWidget(QWidget *parent) : QWidget(parent)
15 | {
16 | pixmap_icon = QIcon::fromTheme("user-trash").pixmap(size());
17 | pixmap = pixmap_icon;
18 | pixmap_dragEnter = QIcon::fromTheme("user-trash-full-opened").pixmap(size());
19 | setAcceptDrops(true);
20 |
21 | QFileSystemWatcher *FSW = new QFileSystemWatcher;
22 | dir_trash = QDir::homePath() + "/.local/share/Trash/files";
23 | FSW->addPath(dir_trash);
24 | connect(FSW, SIGNAL(directoryChanged(QString)), this, SLOT(trashChanged(QString)));
25 | trashChanged("");
26 |
27 | setContextMenuPolicy(Qt::CustomContextMenu);
28 | connect(this, &QWidget::customContextMenuRequested, [=](){
29 | //[&](const QPoint& pos)
30 | QMenu *menu = new QMenu;
31 | menu->setStyleSheet("QMenu { color:white; background: rgba(0,0,0,100);}"
32 | "QMenu::item:selected { background: rgba(48,140,198,255);}");
33 | menu->setAttribute(Qt::WA_TranslucentBackground, true);
34 | menu->setAutoFillBackground(true);
35 | QAction *action_empty_trash = new QAction("清空", this);
36 | connect(action_empty_trash, &QAction::triggered, [](){
37 | QProcess::startDetached("gio", QStringList() << "trash" << "--empty");
38 | });
39 | menu->addAction(action_empty_trash);
40 | menu->adjustSize();//不加会到屏幕中间
41 | //menu->exec(mapToGlobal(pos));
42 | int x1=0, y1=0;
43 | QSettings settings(QApplication::organizationName(), QApplication::applicationName());
44 | QString position = settings.value("Position", "Bottom").toString();
45 | if (position == "Top") {
46 | x1 = QPoint(mapToGlobal(QPoint(0,0))).x() + width()/2 - menu->width()/2;
47 | y1 = height();
48 | } else if (position == "Bottom") {
49 | x1 = QPoint(mapToGlobal(QPoint(0,0))).x() + width()/2 - menu->width()/2;
50 | y1 = QPoint(mapToGlobal(QPoint(0,0))).y() - menu->height();
51 | } else if (position == "Left") {
52 | x1 = width();
53 | y1 = QPoint(mapToGlobal(QPoint(0,0))).y() + height()/2 - menu->height()/2;
54 | } else if (position == "Right") {
55 | x1 = QApplication::desktop()->width() - width() - menu->width();
56 | y1 = QPoint(mapToGlobal(QPoint(0,0))).y() + height()/2 - menu->height()/2;
57 | }
58 | menu->exec(QPoint(x1, y1));
59 | });
60 | }
61 |
62 | void TrashWidget::enterEvent(QEvent *event)
63 | {
64 | Q_UNUSED(event);
65 | isMouseOn = true;
66 | update();
67 | }
68 |
69 | void TrashWidget::leaveEvent(QEvent *event)
70 | {
71 | Q_UNUSED(event);
72 | isMouseOn = false;
73 | update();
74 | }
75 |
76 | void TrashWidget::paintEvent(QPaintEvent *event)
77 | {
78 | Q_UNUSED(event);
79 | QPainter painter(this);
80 | painter.setRenderHint(QPainter::Antialiasing, true);
81 | painter.setRenderHint(QPainter::SmoothPixmapTransform, true);
82 | painter.setPen(Qt::NoPen);
83 | if (isMouseOn) {
84 | painter.setBrush(QColor(255,255,255,30));
85 | painter.drawRoundRect(rect(), 50, 50);
86 | }
87 | painter.drawPixmap(rect().adjusted(3,3,-3,-3), pixmap);
88 | }
89 |
90 | void TrashWidget::dragEnterEvent(QDragEnterEvent *event)
91 | {
92 | qDebug() << event->mimeData();
93 | if(event->mimeData()->hasFormat("text/uri-list")){
94 | pixmap = pixmap_dragEnter;
95 | update();
96 | event->acceptProposedAction();
97 | }
98 | }
99 |
100 | void TrashWidget::dragLeaveEvent(QDragLeaveEvent *event)
101 | {
102 | Q_UNUSED(event);
103 | pixmap = pixmap_icon;
104 | update();
105 | }
106 |
107 | void TrashWidget::dropEvent(QDropEvent *event)
108 | {
109 | QList urls = event->mimeData()->urls();
110 | if (urls.isEmpty())
111 | return ;
112 |
113 | foreach (QUrl u, urls) {
114 | qDebug() << "trash" << u.toString();
115 | QProcess::startDetached("gio", QStringList() << "trash" << u.toString());
116 | }
117 | qDebug() << urls.size();
118 | trashChanged("");
119 | }
120 |
121 | void TrashWidget::mousePressEvent(QMouseEvent *event)
122 | {
123 | point_mouse = QPoint(event->x(), event->y());
124 | }
125 |
126 | void TrashWidget::mouseReleaseEvent(QMouseEvent *event)
127 | {
128 | if (point_mouse == QPoint(event->x(), event->y())) {
129 | QProcess::startDetached("gio", QStringList() << "open" << "trash:///");
130 | }
131 | }
132 |
133 | void TrashWidget::trashChanged(QString path)
134 | {
135 | Q_UNUSED(path);
136 | QDir dir(dir_trash);
137 | int count = dir.entryList(QDir::AllEntries | QDir::Hidden | QDir::NoDotAndDotDot).count();
138 | if (count == 0) {
139 | setToolTip("回收站");
140 | pixmap_icon = QIcon::fromTheme("user-trash").pixmap(size());
141 | } else {
142 | setToolTip("回收站 - " + QString::number(count) + "个文件");
143 | pixmap_icon = QIcon::fromTheme("user-trash-full").pixmap(size());
144 | }
145 | pixmap = pixmap_icon;
146 | update();
147 | }
--------------------------------------------------------------------------------
/netspeedwidget.cpp:
--------------------------------------------------------------------------------
1 | #include "netspeedwidget.h"
2 | #include
3 | #include
4 | #include
5 | #include
6 | #include
7 | #include
8 | #include
9 | #include
10 | #include
11 |
12 | NetSpeedWidget::NetSpeedWidget(QWidget *parent) : QWidget(parent)
13 | {
14 | i=db=ub=dbt=ubt=dbt1=ubt1=dbt0=ubt0=0;
15 |
16 | // Boot time
17 | QProcess *process = new QProcess;
18 | process->start("systemd-analyze");
19 | process->waitForFinished();
20 | QString PO = process->readAllStandardOutput();
21 | QString SD = PO.mid(PO.indexOf("=") + 1, PO.indexOf("\n") - PO.indexOf("=") - 1);
22 | startup = "SUT: " + SD;
23 |
24 | QTimer *timer = new QTimer(this);
25 | connect(timer, SIGNAL(timeout()), this, SLOT(update()));
26 | timer->start(1000);
27 |
28 | label = new QLabel;
29 | label->setMargin(5);
30 | label->setWindowFlags(Qt::Tool | Qt::FramelessWindowHint);
31 | }
32 |
33 | void NetSpeedWidget::enterEvent(QEvent *event)
34 | {
35 | Q_UNUSED(event);
36 | isMouseOn = true;
37 | update();
38 | QSettings settings(QCoreApplication::organizationName(), QCoreApplication::applicationName());
39 | QString position = settings.value("Position", "Bottom").toString();
40 | int x1=0, y1=0;
41 | if (position == "Bottom") {
42 | x1 = mapToGlobal(QPoint(0,0)).x() + width()/2 - label->width()/2;
43 | y1 = mapToGlobal(QPoint(0,0)).y() - label->height();
44 | } else if (position == "Top") {
45 | x1 = mapToGlobal(QPoint(0,0)).x() + width()/2 - label->width()/2;
46 | y1 = height();
47 | } else if (position == "Left") {
48 | x1 = width();
49 | y1 = mapToGlobal(QPoint(0,0)).y() + height()/2 - label->height()/2;
50 | } else if (position == "Right") {
51 | x1 = QApplication::desktop()->width() - width() - label->width();
52 | y1 = mapToGlobal(QPoint(0,0)).y() + height()/2 - label->height()/2;
53 | }
54 | label->move(x1, y1);
55 | label->show();
56 | }
57 |
58 | void NetSpeedWidget::leaveEvent(QEvent *event)
59 | {
60 | Q_UNUSED(event);
61 | isMouseOn = false;
62 | update();
63 | label->hide();
64 | }
65 |
66 | void NetSpeedWidget::paintEvent(QPaintEvent *event)
67 | {
68 | Q_UNUSED(event);
69 | QSettings settings(QCoreApplication::organizationName(), QCoreApplication::applicationName());
70 | bool b = settings.value("isShowNetSpeed", true).toBool();
71 | if (!b)
72 | return;
73 |
74 | // uptime
75 | QFile file("/proc/uptime");
76 | file.open(QIODevice::ReadOnly);
77 | QString l = file.readLine();
78 | file.close();
79 | QTime t(0,0,0);
80 | t = t.addSecs(l.left(l.indexOf(".")).toInt());
81 | QString uptime = "UTM: " + t.toString("hh:mm:ss");
82 |
83 | // memory
84 | file.setFileName("/proc/meminfo");
85 | file.open(QIODevice::ReadOnly);
86 | l = file.readLine();
87 | long mt = l.replace("MemTotal:","").replace("kB","").replace(" ","").toLong();
88 | l = file.readLine();
89 | l = file.readLine();
90 | long ma = l.replace("MemAvailable:","").replace("kB","").replace(" ","").toLong();
91 | l = file.readLine();
92 | l = file.readLine();
93 | file.close();
94 | long mu = mt - ma;
95 | int mp = static_cast(mu*100/mt);
96 | QString mem = "MEM: " + QString("%1 / %2 = %3").arg(KB(mu)).arg(KB(mt)).arg(QString::number(mp) + "%");
97 |
98 | // CPU
99 | file.setFileName("/proc/stat");
100 | file.open(QIODevice::ReadOnly);
101 | l = file.readLine();
102 | QByteArray ba;
103 | ba = l.toLatin1();
104 | const char *ch;
105 | ch = ba.constData();
106 | char cpu[5];
107 | long user,nice,sys,idle,iowait,irq,softirq,tt;
108 | sscanf(ch,"%s%ld%ld%ld%ld%ld%ld%ld",cpu,&user,&nice,&sys,&idle,&iowait,&irq,&softirq);
109 | tt = user + nice + sys + idle + iowait + irq + softirq;
110 | file.close();
111 | QString cusage = "";
112 | int cp = 0;
113 | if (tt != tt0)
114 | cp = static_cast(((tt-tt0)-(idle-idle0))*100/(tt-tt0));
115 | if (i > 0)
116 | cusage = "CPU: " + QString::number(cp) + "%";
117 | idle0 = idle;
118 | tt0 = tt;
119 |
120 | // net
121 | file.setFileName("/proc/net/dev");
122 | file.open(QIODevice::ReadOnly);
123 | l = file.readLine();
124 | l = file.readLine();
125 | dbt1 = ubt1 = 0;
126 | while(!file.atEnd()){
127 | l = file.readLine();
128 | QStringList list = l.split(QRegExp("\\s{1,}"));
129 | db = list.at(1).toLong();
130 | ub = list.at(9).toLong();
131 | dbt1 += db;
132 | ubt1 += ub;
133 | }
134 | file.close();
135 | QString dss = "";
136 | QString uss = "";
137 | if (i > 0) {
138 | long ds = dbt1 - dbt0;
139 | long us = ubt1 - ubt0;
140 | dss = NB(ds) + "/s";
141 | uss = NB(us) + "/s";
142 | dbt0 = dbt1;
143 | ubt0 = ubt1;
144 | }
145 | QString netspeed = "↑" + uss + "\n↓" + dss;
146 | QString net = "UPB: " + BS(ubt1) + " " + uss + "\nDNB: " + BS(dbt1) + " " + dss;
147 |
148 | i++;
149 | if (i>2) i = 2;
150 |
151 | QPainter painter(this);
152 | painter.setRenderHint(QPainter::Antialiasing, true);
153 | //mouseover
154 | if (isMouseOn) {
155 | painter.setPen(Qt::NoPen);
156 | painter.setBrush(QColor(255,255,255,30));
157 | painter.drawRoundRect(rect(), 50, 50);
158 | }
159 | //内存使用率竖条
160 | painter.setPen(Qt::gray);
161 | if (mp < 90) {
162 | painter.setBrush(QColor(0,255,0,150));
163 | } else {
164 | painter.setBrush(QColor(255,0,0,150));
165 | }
166 | painter.drawRect(rect().adjusted(0,height()*(100-mp)/100,-width()/2,0));
167 | //CPU使用率竖条
168 | if (cp < 90) {
169 | painter.setBrush(QColor(0,255,0,150));
170 | } else {
171 | painter.setBrush(QColor(255,0,0,150));
172 | }
173 | painter.drawRect(rect().adjusted(width()/2,height()*(100-cp)/100,0,0));
174 | //netspeed
175 | painter.setPen(Qt::white);
176 | QFont font = this->font();
177 | font.setFamily("Noto Mono");
178 | font.setPointSize(7);
179 | painter.setFont(font);
180 | painter.drawText(rect(), Qt::AlignCenter, netspeed);
181 | //tooltip
182 | label->setText(startup + "\n" + uptime + "\n" + cusage + "\n" + mem + "\n" + net);
183 | }
184 |
185 | QString NetSpeedWidget::KB(long k)
186 | {
187 | QString s = "";
188 | if(k > 999999){
189 | s = QString::number(k/(1024*1024.0),'f',2) + "GB";
190 | }else{
191 | if(k > 999){
192 | s = QString::number(k/1024.0,'f',2) + "MB";
193 | }else{
194 | s = QString::number(k/1.0,'f',2) + "KB";
195 | }
196 | }
197 | return s;
198 | }
199 |
200 | QString NetSpeedWidget::NB(long b)
201 | {
202 | QString s = "";
203 | if (b>999) {
204 | s = QString("%1").arg(b/1024, 5, 'f', 0, QLatin1Char(' ')) + "KB";
205 | } else { // <1K => 0
206 | s = QString("%1").arg(0, 5, 'f', 0, QLatin1Char(' ')) + "KB";
207 | }
208 | return s;
209 | }
210 |
211 | QString NetSpeedWidget::BS(long b)
212 | {
213 | QString s = "";
214 | if (b > 999999999) {
215 | //s = QString("%1").arg(b/(1024*1024*1024.0), 6, 'f', 2, QLatin1Char(' ')) + "GB";
216 | s = QString::number(b/(1024*1024*1024.0), 'f', 2) + "GB";
217 | } else {
218 | if (b > 999999) {
219 | //s = QString("%1").arg(b/(1024*1024.0), 6, 'f', 2, QLatin1Char(' ')) + "MB";
220 | s = QString::number(b/(1024*1024.0), 'f', 2) + "MB";
221 | } else {
222 | if (b > 999) {
223 | //s = QString("%1").arg(b/1024.0, 6, 'f', 2, QLatin1Char(' ')) + "KB";
224 | s = QString::number(b/(1024.0), 'f',2) + "KB";
225 | } else {
226 | s = QString::number(b) + "B";
227 | }
228 | }
229 | }
230 | return s;
231 | }
--------------------------------------------------------------------------------
/datetimewidget.cpp:
--------------------------------------------------------------------------------
1 | #include "datetimewidget.h"
2 | #include
3 | #include
4 | #include
5 | #include
6 | #include
7 | #include
8 | #include
9 | #include
10 | #include
11 | #include
12 |
13 | DatetimeWidget::DatetimeWidget(QWidget *parent) : QWidget(parent)
14 | {
15 | setAttribute(Qt::WA_TranslucentBackground, true);
16 | setStyleSheet("QMenu { color:white; background: rgba(0,0,0,100);}"
17 | "QMenu::item:selected { background: rgba(48,140,198,200);}");
18 |
19 | QTimer *timer = new QTimer(this);
20 | connect(timer, SIGNAL(timeout()), this, SLOT(update()));
21 | timer->start(1000);
22 |
23 | QSettings settings(QApplication::organizationName(), QApplication::applicationName());
24 | clock_type = settings.value("ClockType", "TEXT_CLOCK").toString();
25 |
26 | calendar = new QCalendarWidget;
27 | calendar->setWindowFlags(Qt::Tool | Qt::FramelessWindowHint);
28 |
29 | setContextMenuPolicy(Qt::CustomContextMenu);
30 | connect(this, &QWidget::customContextMenuRequested, [=](){
31 | //[&](const QPoint& pos)
32 | QMenu *menu = new QMenu;
33 | menu->setStyleSheet("QMenu { color:white; background: rgba(0,0,0,100);}"
34 | "QMenu::item:selected { background: rgba(48,140,198,255);}");
35 | menu->setAttribute(Qt::WA_TranslucentBackground, true);
36 | menu->setAutoFillBackground(true);
37 | QAction *action_text = new QAction("文字", this);
38 | connect(action_text, &QAction::triggered, [=](){
39 | clock_type = "TEXT_CLOCK";
40 | QSettings settings(QApplication::organizationName(), QApplication::applicationName());
41 | settings.setValue("ClockType", clock_type);
42 | update();
43 | });
44 | menu->addAction(action_text);
45 | QAction *action_digital = new QAction("数字", this);
46 | connect(action_digital, &QAction::triggered, [=](){
47 | clock_type = "DIGITAL_CLOCK";
48 | QSettings settings(QApplication::organizationName(), QApplication::applicationName());
49 | settings.setValue("ClockType", clock_type);
50 | update();
51 | });
52 | menu->addAction(action_digital);
53 | QAction *action_analog = new QAction("模拟", this);
54 | connect(action_analog, &QAction::triggered, [=](){
55 | clock_type = "ANALOG_CLOCK";
56 | QSettings settings(QApplication::organizationName(), QApplication::applicationName());
57 | settings.setValue("ClockType", clock_type);
58 | update();
59 | });
60 | menu->addAction(action_analog);
61 | menu->adjustSize();//不加会到屏幕中间
62 | //menu->exec(mapToGlobal(pos));
63 | int x1=0, y1=0;
64 | QSettings settings(QApplication::organizationName(), QApplication::applicationName());
65 | QString position = settings.value("Position", "Bottom").toString();
66 | if (position == "Top") {
67 | x1 = QPoint(mapToGlobal(QPoint(0,0))).x() + width()/2 - menu->width()/2;
68 | y1 = height();
69 | } else if (position == "Bottom") {
70 | x1 = QPoint(mapToGlobal(QPoint(0,0))).x() + width()/2 - menu->width()/2;
71 | y1 = QPoint(mapToGlobal(QPoint(0,0))).y() - menu->height();
72 | } else if (position == "Left") {
73 | x1 = width();
74 | y1 = QPoint(mapToGlobal(QPoint(0,0))).y() + height()/2 - menu->height()/2;
75 | } else if (position == "Right") {
76 | x1 = QApplication::desktop()->width() - width() - menu->width();
77 | y1 = QPoint(mapToGlobal(QPoint(0,0))).y() + height()/2 - menu->height()/2;
78 | }
79 | menu->exec(QPoint(x1, y1));
80 | });
81 | }
82 |
83 | void DatetimeWidget::enterEvent(QEvent *event)
84 | {
85 | Q_UNUSED(event);
86 | isMouseOn = true;
87 | update();
88 | }
89 |
90 | void DatetimeWidget::leaveEvent(QEvent *event)
91 | {
92 | Q_UNUSED(event);
93 | isMouseOn = false;
94 | update();
95 | }
96 |
97 | void DatetimeWidget::paintEvent(QPaintEvent *event)
98 | {
99 | Q_UNUSED(event);
100 | QSettings settings(QCoreApplication::organizationName(), QCoreApplication::applicationName());
101 | bool b = settings.value("isShowClock", true).toBool();
102 | if (!b)
103 | return;
104 | QDateTime dateTime = QDateTime::currentDateTime();
105 | setToolTip(dateTime.toString("yyyy/MM/dd HH:mm:ss ddd"));
106 | QPainter painter(this);
107 | if (isMouseOn) {
108 | painter.setPen(Qt::NoPen);
109 | painter.setBrush(QColor(255,255,255,30));
110 | painter.drawRoundRect(rect(), 50, 50);
111 | }
112 | painter.setRenderHint(QPainter::Antialiasing, true);
113 | if (clock_type == "TEXT_CLOCK") {
114 | painter.setPen(Qt::white);
115 | QFont font = this->font();
116 | font.setPointSize(7);
117 | painter.setFont(font);
118 | painter.drawText(rect(), Qt::AlignCenter, dateTime.toString("HH:mm ddd\nyyyy/MM/dd"));
119 | } else if(clock_type == "DIGITAL_CLOCK") {
120 | painter.setPen(Qt::white);
121 | QFont font = this->font();
122 | font.setPointSize(14);
123 | painter.setFont(font);
124 | painter.drawText(rect(), Qt::AlignCenter, dateTime.toString("HH:mm"));
125 | } else if(clock_type == "ANALOG_CLOCK") {
126 | int w = width() - 6;
127 | int h = height() - 6;
128 | QPixmap pixmap(w, h);
129 | pixmap.fill(Qt::transparent);
130 | QPainter painter1(&pixmap);
131 | painter1.setRenderHint(QPainter::Antialiasing, true);
132 | QTime time = QTime::currentTime();
133 | int hour = time.hour();
134 | int m = time.minute();
135 | int s = time.second();
136 | // face
137 | painter1.setPen(QPen(Qt::black, 2));
138 | painter1.setBrush(QBrush(Qt::white));
139 | painter1.drawEllipse(QPoint(w/2,h/2), (int)(w/2*0.9), (int)(h/2*0.9));
140 | painter1.setBrush(QBrush(Qt::black));
141 | painter1.drawEllipse(QPoint(w/2,h/2), (int)(w*0.015), (int)(h*0.015));
142 | qreal da = 2 * M_PI / 60;
143 | // second hand
144 | int x = w * 0.4 * qCos(M_PI/2 - s * da) + w / 2;
145 | int y = - h * 0.4 * qSin(M_PI/2 - s * da) + h / 2;
146 | painter1.setPen(QPen(Qt::black, 1));
147 | painter1.drawLine(QPoint(w/2,h/2), QPoint(x,y));
148 | // minute hand
149 | x = w * 0.35 * qCos(M_PI/2 - m * da - s * da / 60) + w / 2;
150 | y = - h * 0.35 * qSin(M_PI/2 - m * da - s * da / 60) + h / 2;
151 | painter1.setPen(QPen(Qt::black, 2));
152 | painter1.drawLine(QPoint(w/2,h/2), QPoint(x,y));
153 | // hour hand
154 | da = 2 * M_PI / 12;
155 | if(hour >= 12) hour -= 12;
156 | x = w*0.25 * qCos(M_PI/2 - hour * da - m * da / 60) + w/2;
157 | y = - h*0.25 * qSin(M_PI/2 - hour * da - m * da / 60) + h/2;
158 | //qDebug() << "x =" << x << ", y =" << y;
159 | painter1.setPen(QPen(Qt::black, 2));
160 | painter1.drawLine(QPoint(w/2,h/2), QPoint(x,y));
161 | painter.drawPixmap(rect().center() - pixmap.rect().center(), pixmap);
162 | }
163 | }
164 |
165 | void DatetimeWidget::mousePressEvent(QMouseEvent *event)
166 | {
167 | if(event->button() == Qt::LeftButton){
168 | QSettings settings(QCoreApplication::organizationName(), QCoreApplication::applicationName());
169 | QString position = settings.value("Position", "Bottom").toString();
170 | if (calendar->isHidden()) {
171 | int x1, y1;
172 | if (position == "Bottom") {
173 | x1 = mapToGlobal(QPoint(0,0)).x() + width()/2 - calendar->width()/2;
174 | y1 = mapToGlobal(QPoint(0,0)).y() - calendar->height();
175 | } else if (position == "Top") {
176 | x1 = mapToGlobal(QPoint(0,0)).x() + width()/2 - calendar->width()/2;
177 | y1 = height();
178 | } else if (position == "Left") {
179 | x1 = width();
180 | y1 = mapToGlobal(QPoint(0,0)).y() + height()/2 - calendar->height()/2;
181 | } else if (position == "Right") {
182 | x1 = QApplication::desktop()->width() - width() - calendar->width();
183 | y1 = mapToGlobal(QPoint(0,0)).y() + height()/2 - calendar->height()/2;
184 | }
185 | qDebug() << "QCalendarWidget" << x1 << y1;
186 | calendar->move(x1, y1);
187 | calendar->setSelectedDate(QDate::currentDate());
188 | calendar->show();
189 | } else {
190 | calendar->hide();
191 | }
192 | } else {
193 | calendar->hide();
194 | }
195 | }
--------------------------------------------------------------------------------
/mainwindow.cpp:
--------------------------------------------------------------------------------
1 | #include "mainwindow.h"
2 | #include
3 | #include
4 | #include
5 | #include
6 | #include
7 | #include
8 | #include
9 | #include
10 | #include
11 | #include
12 | #include
13 | #include
14 | #include
15 | #include
16 | #include
17 |
18 | MainWindow::MainWindow(QWidget *parent)
19 | : QMainWindow(parent)
20 | ,settings(QApplication::organizationName(), QApplication::applicationName())
21 | {
22 | setStyleSheet("background-color:white;");
23 | int w = settings.value("IconSize", 40).toInt();
24 | mode = settings.value("Mode", "Fashion").toString();
25 | position = settings.value("Position", "Bottom").toString();
26 | size.setWidth(w);
27 | size.setHeight(w);
28 | h = w + 20;
29 | qss = ".CurrentButton { background-color: rgba(48,140,198,0.5); border-radius:10px; }"
30 | ".CurrentButton:hover { background-color: rgba(48,140,198,0.5); }"
31 | "QTooltip { color: white; border: 1px solid white; background-color: white; }"
32 | "QPushButton { border: none; }"
33 | "QPushButton:hover { color: rgba(0, 0, 0, 0.1); background-color: rgba(255,255,255,0.1); border-radius:10px; }";
34 | setStyleSheet(qss);
35 | setWindowFlags(Qt::FramelessWindowHint);
36 | setAttribute(Qt::WA_TranslucentBackground, true);
37 | //setAttribute(Qt::WA_X11NetWmWindowTypeDock, true);
38 | KWindowSystem::setOnDesktop(winId(), NET::OnAllDesktops);
39 | KWindowSystem::setType(winId(), NET::Dock);
40 | setFixedHeight(h);
41 | QWidget *widget = new QWidget;
42 | QBoxLayout::Direction direction = QBoxLayout::LeftToRight;
43 | if (position == "Top" || position == "Bottom") {
44 | direction = QBoxLayout::LeftToRight;
45 | } else if (position == "Left" || position == "Right") {
46 | direction = QBoxLayout::TopToBottom;
47 | }
48 | boxLayout = new QBoxLayout(direction);
49 | boxLayout->setMargin(0);
50 | widget->setLayout(boxLayout);
51 | setCentralWidget(widget);
52 |
53 | pushButton_launcher = new QPushButton(QIcon(":/launcher.png"), nullptr);
54 | pushButton_launcher->setFixedSize(size + QSize(6,6));
55 | pushButton_launcher->setIconSize(size);
56 | pushButton_launcher->setToolTip("启动器");
57 | pushButton_launcher->setFocusPolicy(Qt::NoFocus);
58 | connect(pushButton_launcher, &QPushButton::pressed, [](){
59 | QProcess::startDetached("HTYStartMenu");
60 | });
61 | boxLayout->addWidget(pushButton_launcher);
62 |
63 | widget_app = new QWidget;
64 | boxLayout_app = new QBoxLayout(direction);
65 | boxLayout_app->setMargin(0);
66 | widget_app->setLayout(boxLayout_app);
67 | boxLayout->addWidget(widget_app);
68 |
69 | boxLayout->addStretch();
70 |
71 | trashWidget = new TrashWidget;
72 | trashWidget->setFixedSize(size + QSize(6,6));
73 | boxLayout->addWidget(trashWidget);
74 |
75 | datetimeWidget = new DatetimeWidget;
76 | datetimeWidget->setFixedSize(size + QSize(6,6));
77 | boxLayout->addWidget(datetimeWidget);
78 |
79 | netSpeedWidget = new NetSpeedWidget;
80 | netSpeedWidget->setFixedSize(size + QSize(6,6));
81 | boxLayout->addWidget(netSpeedWidget);
82 |
83 | pushButton_desktop = new QPushButton(QIcon::fromTheme("computer"), nullptr);
84 | pushButton_desktop->setFixedSize(size + QSize(6,6));
85 | pushButton_desktop->setIconSize(size);
86 | pushButton_desktop->setToolTip("显示桌面");
87 | pushButton_desktop->setFocusPolicy(Qt::NoFocus);
88 | connect(pushButton_desktop, &QPushButton::pressed, [](){
89 | KWindowSystem::setShowingDesktop(!KWindowSystem::showingDesktop());
90 | });
91 | boxLayout->addWidget(pushButton_desktop);
92 |
93 | connect(KWindowSystem::self(), &KWindowSystem::windowAdded, this, &MainWindow::windowAdded);
94 | connect(KWindowSystem::self(), &KWindowSystem::windowRemoved, this, &MainWindow::windowRemoved);
95 | //这2个差不多
96 | connect(KWindowSystem::self(), static_cast(&KWindowSystem::windowChanged), this, &MainWindow::windowChanged);
97 | connect(KWindowSystem::self(), &KWindowSystem::activeWindowChanged, this, &MainWindow::activeWindowChanged);
98 |
99 | addMenus();
100 | refit();
101 | }
102 |
103 | MainWindow::~MainWindow()
104 | {
105 |
106 | }
107 |
108 | void MainWindow::addMenus()
109 | {
110 | //右键菜单
111 | QAction *action = new QAction("模式", this);
112 | QMenu *menu = new QMenu;
113 | QAction *action_mode_fashion = new QAction("时尚", menu);
114 | QAction *action_mode_efficient = new QAction("高效", menu);
115 | action_mode_fashion->setCheckable(true);
116 | action_mode_efficient->setCheckable(true);
117 | if (mode == "Fashion")
118 | action_mode_fashion->setChecked(true);
119 | else if (mode == "Efficient")
120 | action_mode_efficient->setChecked(true);
121 | connect(action_mode_fashion, &QAction::triggered, [=](){
122 | mode = "Fashion";
123 | settings.setValue("Mode", mode);
124 | refit();
125 | });
126 | connect(action_mode_efficient, &QAction::triggered, [=](){
127 | mode = "Efficient";
128 | settings.setValue("Mode", mode);
129 | refit();
130 | });
131 | QActionGroup *actionGroup = new QActionGroup(this);
132 | menu->addAction(actionGroup->addAction(action_mode_fashion));
133 | menu->addAction(actionGroup->addAction(action_mode_efficient));
134 | action->setMenu(menu);
135 | addAction(action);
136 |
137 | action = new QAction("位置", this);
138 | menu = new QMenu;
139 | QAction *action_position_top = new QAction("上", menu);
140 | QAction *action_position_bottom = new QAction("下", menu);
141 | QAction *action_position_left = new QAction("左", menu);
142 | QAction *action_position_right = new QAction("右", menu);
143 | action_position_top->setCheckable(true);
144 | action_position_bottom->setCheckable(true);
145 | action_position_left->setCheckable(true);
146 | action_position_right->setCheckable(true);
147 | if (position == "Top")
148 | action_position_top->setChecked(true);
149 | else if (position == "Bottom")
150 | action_position_bottom->setChecked(true);
151 | else if (position == "Left")
152 | action_position_left->setChecked(true);
153 | else if (position == "Right")
154 | action_position_right->setChecked(true);
155 | connect(action_position_top, &QAction::triggered, [=](){
156 | position = "Top";
157 | settings.setValue("Position", position);
158 | refit();
159 | });
160 | connect(action_position_bottom, &QAction::triggered, [=](){
161 | position = "Bottom";
162 | settings.setValue("Position", position);
163 | refit();
164 | });
165 | connect(action_position_left, &QAction::triggered, [=](){
166 | position = "Left";
167 | settings.setValue("Position", position);
168 | refit();
169 | });
170 | connect(action_position_right, &QAction::triggered, [=](){
171 | position = "Right";
172 | settings.setValue("Position", position);
173 | refit();
174 | });
175 | actionGroup = new QActionGroup(this);
176 | menu->addAction(actionGroup->addAction(action_position_top));
177 | menu->addAction(actionGroup->addAction(action_position_bottom));
178 | menu->addAction(actionGroup->addAction(action_position_left));
179 | menu->addAction(actionGroup->addAction(action_position_right));
180 | action->setMenu(menu);
181 | addAction(action);
182 |
183 | action = new QAction("大小", this);
184 | QAction *action_size_big = new QAction("大", menu);
185 | QAction *action_size_medium = new QAction("中", menu);
186 | QAction *action_size_small = new QAction("小", menu);
187 | action_size_big->setCheckable(true);
188 | action_size_medium->setCheckable(true);
189 | action_size_small->setCheckable(true);
190 | int w = settings.value("IconSize", 40).toInt();
191 | if (w == 50) {
192 | action_size_big->setChecked(true);
193 | } else if (w == 40) {
194 | action_size_medium->setChecked(true);
195 | } else if (w == 30) {
196 | action_size_small->setChecked(true);
197 | }
198 | connect(action_size_big, &QAction::triggered, [=](){
199 | resizeIcon(50);
200 | settings.setValue("IconSize", 50);
201 | });
202 | connect(action_size_medium, &QAction::triggered, [=](){
203 | resizeIcon(40);
204 | settings.setValue("IconSize", 40);
205 | });
206 | connect(action_size_small, &QAction::triggered, [=](){
207 | resizeIcon(30);
208 | settings.setValue("IconSize", 30);
209 | });
210 | actionGroup = new QActionGroup(this);
211 | menu = new QMenu;
212 | menu->addAction(actionGroup->addAction(action_size_big));
213 | menu->addAction(actionGroup->addAction(action_size_medium));
214 | menu->addAction(actionGroup->addAction(action_size_small));
215 | action->setMenu(menu);
216 | addAction(action);
217 |
218 | action = new QAction("状态", this);
219 | QAction *action_always_show = new QAction("总是显示", menu);
220 | QAction *action_always_hide = new QAction("总是隐藏", menu);
221 | QAction *action_smart_hide = new QAction("智能隐藏", menu);
222 | action_always_show->setCheckable(true);
223 | action_always_hide->setCheckable(true);
224 | action_smart_hide->setCheckable(true);
225 | actionGroup = new QActionGroup(this);
226 | menu = new QMenu;
227 | menu->addAction(actionGroup->addAction(action_always_show));
228 | menu->addAction(actionGroup->addAction(action_always_hide));
229 | menu->addAction(actionGroup->addAction(action_smart_hide));
230 | action->setMenu(menu);
231 | addAction(action);
232 |
233 | action = new QAction("插件", this);
234 | QAction *action_plugin_trash = new QAction("回收站", menu);
235 | QAction *action_plugin_clock = new QAction("时钟", menu);
236 | QAction *action_plugin_netspeed = new QAction("网速", menu);
237 | action_plugin_trash->setCheckable(true);
238 | action_plugin_clock->setCheckable(true);
239 | action_plugin_netspeed->setCheckable(true);
240 |
241 | connect(action_plugin_trash, &QAction::triggered, [=](bool b){
242 | if (b) {
243 | trashWidget->show();
244 | settings.setValue("isShowTrash", true);
245 | count_plugin++;
246 | } else {
247 | trashWidget->hide();
248 | settings.setValue("isShowTrash", false);
249 | count_plugin--;
250 | }
251 | refit();
252 | });
253 |
254 | connect(action_plugin_clock, &QAction::triggered, [=](bool b){
255 | if (b){
256 | datetimeWidget->show();
257 | settings.setValue("isShowClock", true);
258 | count_plugin++;
259 | } else {
260 | datetimeWidget->hide();
261 | settings.setValue("isShowClock", false);
262 | count_plugin--;
263 | }
264 | refit();
265 | });
266 |
267 | connect(action_plugin_netspeed, &QAction::triggered, [=](bool b){
268 | if (b){
269 | netSpeedWidget->show();
270 | settings.setValue("isShowNetSpeed", true);
271 | count_plugin++;
272 | } else {
273 | netSpeedWidget->hide();
274 | settings.setValue("isShowNetSpeed", false);
275 | count_plugin--;
276 | }
277 | refit();
278 | });
279 |
280 | bool b = settings.value("isShowTrash", true).toBool();
281 | if (b) {
282 | action_plugin_trash->setChecked(true);
283 | count_plugin++;
284 | } else {
285 | trashWidget->hide();
286 | }
287 |
288 | b = settings.value("isShowClock", true).toBool();
289 | if (b) {
290 | action_plugin_clock->setChecked(true);
291 | count_plugin++;
292 | } else {
293 | datetimeWidget->hide();
294 | }
295 |
296 | b = settings.value("isShowNetSpeed", true).toBool();
297 | if (b) {
298 | action_plugin_netspeed->setChecked(true);
299 | count_plugin++;
300 | } else {
301 | netSpeedWidget->hide();
302 | }
303 |
304 | menu = new QMenu;
305 | menu->addAction(action_plugin_trash);
306 | menu->addAction(action_plugin_clock);
307 | menu->addAction(action_plugin_netspeed);
308 | action->setMenu(menu);
309 | addAction(action);
310 |
311 | action = new QAction("系统监视器", this);
312 | connect(action, &QAction::triggered, []{
313 | QProcess::startDetached("deepin-system-monitor");
314 | });
315 | addAction(action);
316 |
317 | setContextMenuPolicy(Qt::ActionsContextMenu);
318 | }
319 |
320 | void MainWindow::resizeIcon(int w)
321 | {
322 | size.setWidth(w);
323 | size.setHeight(w);
324 | if (w == 50)
325 | h = w + 20;
326 | else if (w == 40)
327 | h = w + 10;
328 | else if (w == 30)
329 | h = w + 6;
330 | for (int i=0; isetFixedSize(size + QSize(w/10,w/10));
332 | }
333 | pushButton_launcher->setFixedSize(size + QSize(w/10,w/10));
334 | pushButton_launcher->setIconSize(size);
335 | trashWidget->setFixedSize(size + QSize(w/10,w/10));
336 | pushButton_desktop->setFixedSize(size+ QSize(w/10,w/10));
337 | pushButton_desktop->setIconSize(size);
338 | datetimeWidget->setFixedSize(size);
339 | netSpeedWidget->setFixedSize(size);
340 | refit();
341 | }
342 |
343 | void MainWindow::refit()
344 | {
345 | //qDebug() << count_plugin;
346 | int w=0, x1=0, y1=0;
347 | if (position == "Bottom") {
348 | boxLayout->setDirection(QBoxLayout::LeftToRight);
349 | boxLayout_app->setDirection(QBoxLayout::LeftToRight);
350 | if (mode == "Fashion")
351 | w = (list_appWidget.count() + count_plugin + 3) * size.width();
352 | else if (mode == "Efficient")
353 | w = QApplication::desktop()->width();
354 | int sh = size.height();
355 | if (sh == 50)
356 | h = sh + 20;
357 | else if (sh == 40)
358 | h = sh + 10;
359 | else if (sh == 30)
360 | h = sh + 6;
361 | x1 = QApplication::desktop()->width()/2 - w/2;
362 | y1 = QApplication::desktop()->height() - h;
363 | } else if (position == "Top") {
364 | boxLayout->setDirection(QBoxLayout::LeftToRight);
365 | boxLayout_app->setDirection(QBoxLayout::LeftToRight);
366 | if (mode == "Fashion")
367 | w = (list_appWidget.count() + count_plugin + 3) * size.width();
368 | else if (mode == "Efficient")
369 | w = QApplication::desktop()->width();
370 | h = size.height();
371 | x1 = QApplication::desktop()->width()/2 - w/2;
372 | y1 = 0;
373 | } else if (position == "Left") {
374 | boxLayout->setDirection(QBoxLayout::TopToBottom);
375 | boxLayout_app->setDirection(QBoxLayout::TopToBottom);
376 | w = size.width();
377 | if (mode == "Fashion")
378 | h = (list_appWidget.count() + count_plugin + 3) * size.height();
379 | else if (mode == "Efficient")
380 | h = QApplication::desktop()->height();
381 | x1 = 0;
382 | y1 = QApplication::desktop()->height()/2 - h/2;
383 | } else if (position == "Right") {
384 | boxLayout->setDirection(QBoxLayout::TopToBottom);
385 | boxLayout_app->setDirection(QBoxLayout::TopToBottom);
386 | w = size.width();
387 | if (mode == "Fashion")
388 | h = (list_appWidget.count() + count_plugin + 3) * size.width();
389 | else if (mode == "Efficient")
390 | h = QApplication::desktop()->height();
391 | x1 = QApplication::desktop()->width() - size.width();
392 | y1 = QApplication::desktop()->height()/2 - h/2;
393 | }
394 | resize(w, h);
395 | setFixedSize(w, h);
396 | move(x1, y1);
397 | //qDebug() << position << x1 << y1 << w << h;
398 |
399 | //区域模糊
400 | //QRegion region(rect()); //矩形
401 | //KWindowEffects::enableBlurBehind(winId(), true, region);
402 | int r = qMin(width(), height()) / 3;
403 | QPainterPath PP;
404 | PP.addRoundedRect(rect(), r, r); //圆角矩形
405 | KWindowEffects::enableBlurBehind(winId(), true, PP.toFillPolygon().toPolygon());
406 |
407 | //挤开桌面。为什么只需要3个参数?从各边减去width。
408 | NETExtendedStrut strut;
409 | if (position == "Bottom") {
410 | strut.bottom_width = height();
411 | strut.bottom_start = x();
412 | strut.bottom_end = x() + width();
413 | } else if (position == "Top") {
414 | strut.top_width = height();
415 | strut.top_start = x();
416 | strut.top_end = x() + width();
417 | } else if (position == "Left") {
418 | strut.left_width = width();
419 | strut.left_start = y();
420 | strut.left_end = y() + height();
421 | } else if (position == "Right") {
422 | strut.right_width = width();
423 | strut.right_start = y();
424 | strut.right_end = y() + height();
425 | }
426 | KWindowSystem::setExtendedStrut(winId(),
427 | strut.left_width, strut.left_start, strut.left_end,
428 | strut.right_width, strut.right_start, strut.right_end,
429 | strut.top_width, strut.top_start, strut.top_end,
430 | strut.bottom_width, strut.bottom_start, strut.bottom_end);
431 | }
432 |
433 | void MainWindow::windowAdded(WId wid)
434 | {
435 | KWindowInfo winInfo(wid, NET::WMWindowType | NET::WMVisibleName, NET::WM2WindowClass |NET::WM2DesktopFileName);
436 | //DDE 系列的值是 NET::OverrideMask
437 | if (!NET::typeMatchesMask(winInfo.windowType(NET::AllTypesMask), NET::NormalMask | NET::OverrideMask)) {
438 | //QMetaEnum metaEnum = QMetaEnum::fromType();
439 | //metaEnum.valueToKey(winInfo.windowType(NET::AllTypesMask));
440 | //qDebug() << winInfo.windowClassClass() << winInfo.windowType(NET::AllTypesMask);
441 | return;
442 | }
443 | qDebug() << winInfo.name() << winInfo.windowClassClass();
444 | if (winInfo.windowClassClass() == "")
445 | return;
446 | for(int i=0; iclassName == winInfo.windowClassClass()){
448 | if(!list_appWidget.at(i)->list_wid.contains(wid)){
449 | list_appWidget.at(i)->list_wid.append(wid);
450 | list_appWidget.at(i)->addPreview(wid);
451 | list_appWidget.at(i)->update();
452 | }
453 | return;
454 | }
455 | }
456 |
457 | AppWidget *appWidget = new AppWidget;
458 | appWidget->setFixedSize(size);
459 | appWidget->list_wid.append(wid);
460 | appWidget->name = winInfo.name();
461 | appWidget->className = winInfo.windowClassClass();
462 | appWidget->icon = KWindowSystem::icon(wid);
463 | appWidget->setToolTip(winInfo.name());
464 | appWidget->addPreview(wid);
465 | connect(appWidget, &AppWidget::clicked, [=](){
466 | buttonClicked(appWidget);
467 | });
468 | appWidget->setContextMenuPolicy(Qt::CustomContextMenu);
469 | connect(appWidget, &AppWidget::customContextMenuRequested, [=](){
470 | QMenu *menu = new QMenu;
471 | menu->setStyleSheet("QMenu { color:white; background: rgba(0,0,0,100);}"
472 | "QMenu::item:selected { background: rgba(48,140,198,255);}");
473 | menu->setAttribute(Qt::WA_TranslucentBackground, true);
474 | menu->setAutoFillBackground(true);
475 | QAction *action_close = new QAction("关闭", this);
476 | connect(action_close, &QAction::triggered, [=](){
477 | NETRootInfo(QX11Info::connection(), NET::CloseWindow).closeWindowRequest(static_cast(wid));
478 | });
479 | menu->addAction(action_close);
480 | menu->adjustSize();//不加会到屏幕中间
481 | int x1=0, y1=0;
482 | if (position == "Top") {
483 | x1 = QPoint(appWidget->mapToGlobal(QPoint(0,0))).x() + appWidget->width()/2 - menu->width()/2;
484 | y1 = height();
485 | } else if (position == "Bottom") {
486 | x1 = QPoint(appWidget->mapToGlobal(QPoint(0,0))).x() + appWidget->width()/2 - menu->width()/2;
487 | y1 = y() - menu->height();
488 | } else if (position == "Left") {
489 | x1 = width();
490 | y1 = QPoint(appWidget->mapToGlobal(QPoint(0,0))).y() + appWidget->height()/2 - menu->height()/2;
491 | } else if (position == "Right") {
492 | x1 = QApplication::desktop()->width() - width() - menu->width();
493 | y1 = QPoint(appWidget->mapToGlobal(QPoint(0,0))).y() + appWidget->height()/2 - menu->height()/2;
494 | }
495 | menu->exec(QPoint(x1, y1));
496 | });
497 | boxLayout_app->addWidget(appWidget);
498 | list_appWidget.append(appWidget);
499 | refit();
500 | }
501 |
502 | void MainWindow::windowRemoved(WId wid)
503 | {
504 | for (int i=0; ilist_wid.contains(wid)) {
507 | //qDebug() << dock->wid;
508 | if (appWidget->list_wid.count() > 1) {
509 | appWidget->list_wid.removeOne(wid);
510 | if(appWidget->index > 0)
511 | appWidget->index--;
512 | appWidget->removePreview(wid);
513 | } else {
514 | boxLayout_app->removeWidget(appWidget);
515 | list_appWidget.removeAt(i);
516 | //connect(appWidget, &AppWidget::destroyed, [=](){
517 | // refit();
518 | //});
519 | appWidget->deleteLater();
520 | refit();
521 | }
522 | }
523 | }
524 | }
525 |
526 | void MainWindow::windowChanged(WId wid, NET::Properties properties, NET::Properties2 properties2)
527 | {
528 | KWindowInfo winInfo(wid, properties, properties2);
529 | //qDebug() << wid << winInfo.name() << winInfo.windowClassClass();// wid,空值,空值
530 | }
531 |
532 | void MainWindow::activeWindowChanged(WId wid)
533 | {
534 | for (int i=0; ilist_wid.contains(wid)) {
537 | appWidget->isActive = true;
538 | } else {
539 | appWidget->isActive = false;
540 | }
541 | appWidget->update();
542 | }
543 | }
544 |
545 | void MainWindow::buttonClicked(AppWidget *appWidget)
546 | {
547 | for (int i=0; iisActive = false;
549 | list_appWidget.at(i)->update();
550 | }
551 | appWidget->isActive = true;
552 | appWidget->update();
553 | KWindowInfo winInfo(appWidget->list_wid.at(appWidget->index), NET::WMState | NET::XAWMState | NET::WMDesktop | NET::WMVisibleName);
554 | appWidget->setToolTip(winInfo.name());
555 | if (winInfo.isMinimized()) {
556 | KWindowSystem::unminimizeWindow(appWidget->list_wid.at(appWidget->index));
557 | KWindowSystem::activateWindow(appWidget->list_wid.at(appWidget->index));
558 | } else {
559 | if (KWindowSystem::activeWindow() == appWidget->list_wid.at(appWidget->index)) {
560 | if (appWidget->index < appWidget->list_wid.count() -1) {
561 | appWidget->index++;
562 | KWindowSystem::activateWindow(appWidget->list_wid.at(appWidget->index));
563 | } else {
564 | for(int i=0; ilist_wid.count(); i++){
565 | KWindowSystem::minimizeWindow(appWidget->list_wid.at(i));
566 | }
567 | appWidget->index = 0;
568 | }
569 | } else {
570 | KWindowSystem::activateWindow(appWidget->list_wid.at(appWidget->index));
571 | }
572 | }
573 | }
574 |
575 | void MainWindow::paintEvent(QPaintEvent *event)
576 | {
577 | Q_UNUSED(event);
578 | QPainter painter(this);
579 | painter.setRenderHint(QPainter::Antialiasing);
580 | painter.setPen(Qt::NoPen);
581 | painter.setBrush(QColor(0,0,0,50));
582 | int r = qMin(width(), height()) / 3;
583 | painter.drawRoundedRect(rect(), r, r);
584 | }
--------------------------------------------------------------------------------