diff --git a/.clangd b/.clangd
deleted file mode 100644
index cb4c484..0000000
--- a/.clangd
+++ /dev/null
@@ -1,26 +0,0 @@
-CompileFlags:
- Add:
- [
- -Wno-documentation,
- -Wno-missing-prototypes,
- -std=c++17,
- --include-directory=/opt/homebrew/include,
- --include-directory=/opt/homebrew/include/QtGui,
- --include-directory=/opt/homebrew/include/QtCore,
- --include-directory=/opt/homebrew/include/QtWidgets,
- ]
-
-Diagnostics:
- ClangTidy:
- Add:
- [
- performance-*,
- bugprone-*,
- modernize-*,
- clang-analyzer-*,
- readability-identifier*,
- ]
- CheckOptions:
- readability-identifier-naming.VariableCase: camelCase
-
- Suppress: [-Wdeprecated-declarations]
diff --git a/.vscode/c_cpp_properties.json b/.vscode/c_cpp_properties.json
index 808d45e..d094de3 100644
--- a/.vscode/c_cpp_properties.json
+++ b/.vscode/c_cpp_properties.json
@@ -1,6 +1,36 @@
{
- "includePath": "/opt/homebrew/include",
- "compilerPath": "/usr/bin/clang++",
- "cStandard": "c11",
- "cppStandard": "c++17"
+ "configurations": [
+ {
+ "name": "macos-conda-qt",
+ "includePath": [
+ "${workspaceFolder}/**",
+ "${env:HOMEBREW_CELLAR}/qt/6.11.0/include/**",
+ ],
+ "defines": [],
+ "compilerPath": "/usr/bin/clang++",
+ "cStandard": "c17",
+ "cppStandard": "c++17",
+ "intelliSenseMode": "macos-clang-arm64",
+ "configurationProvider": "kylinideteam.cmake-intellisence"
+ },
+ {
+ "name": "win-conda-qt",
+ "includePath": [
+ "${workspaceFolder}/**",
+ "${env:SCOOP}\\apps\\msys2-cn\\current\\ucrt64\\include",
+ "${env:SCOOP}\\apps\\msys2-cn\\current\\ucrt64\\include\\qt"
+ ],
+ "defines": [
+ "_DEBUG",
+ "UNICODE",
+ "_UNICODE"
+ ],
+ "compilerPath": "${env:SCOOP}\\apps\\msys2-cn\\current\\ucrt64\\bin\\g++.exe",
+ "cStandard": "c17",
+ "cppStandard": "c++17",
+ "intelliSenseMode": "windows-gcc-x64",
+ "configurationProvider": "kylinideteam.cmake-intellisence"
+ }
+ ],
+ "version": 4
}
diff --git a/.vscode/launch.json b/.vscode/launch.json
new file mode 100644
index 0000000..74acc45
--- /dev/null
+++ b/.vscode/launch.json
@@ -0,0 +1,58 @@
+{
+ "version": "0.2.0",
+ "configurations": [
+ {
+ "name": "Debug Qt6",
+ "type": "cppdbg",
+ "request": "launch",
+ "targetArchitecture": "arm64",
+ "program": "${fileDirname}/${fileBasenameNoExtension}",
+ "args": [],
+ "stopAtEntry": false,
+ "externalConsole": false,
+ "cwd": "${fileDirname}",
+ "environment": [
+ {
+ "name": "DYLD_LIBRARY_PATH",
+ "value": "${env:HOMEBREW_CELLAR}/qt/6.11.0/lib"
+ }
+ ],
+ "MIMode": "lldb",
+ "internalConsoleOptions": "openOnSessionStart"
+ },
+ {
+ "name": "Debug Qt6 on Windows",
+ "type": "cppdbg",
+ "request": "launch",
+ "targetArchitecture": "x86_64",
+ "program": "${fileDirname}/${fileBasenameNoExtension}.exe",
+ "args": [],
+ "stopAtEntry": false,
+ "externalConsole": false,
+ "cwd": "${fileDirname}",
+ "MIMode": "gdb",
+ "miDebuggerPath": "${env:SCOOP}\\apps\\msys2-cn\\current\\ucrt64\\bin\\gdb.exe",
+ "internalConsoleOptions": "openOnSessionStart",
+ "setupCommands": [
+ {
+ "description": "Enable pretty-printing for gdb",
+ "text": "-enable-pretty-printing",
+ "ignoreFailures": false
+ }
+ ]
+ },
+ {
+ "name": "C/C++: clang++ build and debug active file",
+ "type": "cppdbg",
+ "request": "launch",
+ "program": "${fileDirname}/${fileBasenameNoExtension}",
+ "args": [],
+ "stopAtEntry": false,
+ "cwd": "${fileDirname}",
+ "environment": [],
+ "externalConsole": false,
+ "MIMode": "lldb",
+ "preLaunchTask": "Build Qt6"
+ }
+ ]
+}
diff --git a/.vscode/tasks.json b/.vscode/tasks.json
new file mode 100644
index 0000000..af766c4
--- /dev/null
+++ b/.vscode/tasks.json
@@ -0,0 +1,78 @@
+{
+ "version": "2.0.0",
+ "tasks": [
+ {
+ "type": "cppbuild",
+ "label": "Build Qt6",
+ "command": "/usr/bin/clang++",
+ "args": [
+ "-g",
+ "${file}",
+ "-o",
+ "${fileDirname}/${fileBasenameNoExtension}",
+ "-I",
+ "${env:HOMEBREW_CELLAR}/qtbase/6.11.0/include",
+ "-L",
+ "${env:HOMEBREW_CELLAR}/qtbase/6.11.0/lib",
+ "-lQt6Core",
+ "-lQt6Gui",
+ "-lQt6Widgets"
+ ],
+ "options": {
+ "cwd": "${fileDirname}"
+ },
+ "problemMatcher": [
+ "$gcc"
+ ],
+ "group": "build"
+ },
+ {
+ "type": "cppbuild",
+ "label": "Build Qt6 on Windows",
+ "command": "${env:SCOOP}\\apps\\msys2-cn\\current\\ucrt64\\bin\\g++.exe",
+ "args": [
+ "-fdiagnostics-color=always",
+ "-g",
+ "${file}",
+ "-o",
+ "${fileDirname}/${fileBasenameNoExtension}.exe",
+ "-I",
+ "${env:SCOOP}\\apps\\msys2-cn\\current\\ucrt64\\include",
+ "-I",
+ "${env:SCOOP}\\apps\\msys2-cn\\current\\ucrt64\\include\\qt6",
+ "-L",
+ "${env:SCOOP}\\apps\\msys2-cn\\current\\ucrt64\\lib",
+ "-lQt6Core",
+ "-lQt6Gui",
+ "-lQt6Widgets"
+ ],
+ "options": {
+ "cwd": "${env:SCOOP}\\apps\\msys2-cn\\current\\ucrt64\\bin"
+ },
+ "problemMatcher": [
+ "$gcc"
+ ],
+ "group": "build"
+ },
+ {
+ "type": "cppbuild",
+ "label": "C/C++: g++.exe build active file",
+ "command": "${env:SCOOP}\\apps\\msys2-cn\\current\\ucrt64\\bin\\g++.exe",
+ "args": [
+ "-fdiagnostics-color=always",
+ "-g",
+ "${file}",
+ "-o",
+ "${fileDirname}\\${fileBasenameNoExtension}.exe"
+ ],
+ "options": {
+ "cwd": "${env:SCOOP}\\apps\\msys2-cn\\current\\ucrt64\\bin"
+ },
+ "problemMatcher": [
+ "$gcc"
+ ],
+ "group": "build",
+ "detail": "Task generated by Debugger."
+ }
+ ]
+}
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 907e569..e3ad736 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -4,7 +4,10 @@ if(${CMAKE_VERSION} VERSION_LESS 3.12)
cmake_policy(VERSION ${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION})
endif()
-project(clock)
+project(FloatingClock)
+
+set(CMAKE_CXX_STANDARD 17)
+set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_AUTOUIC ON)
set(CMAKE_AUTOMOC ON)
@@ -13,18 +16,45 @@ set(CMAKE_CXX_STANDARD 17 CACHE STRING "v")
set(CMAKE_CXX_STANDARD_REQUIRED True)
set(CMAKE_CXX_EXTENSIONS OFF)
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
-set(CMAKE_PREFIX_PATH "/opt/homebrew/opt/qt")
-find_package(Qt6 COMPONENTS Core Gui Widgets REQUIRED)
+# Homebrew Qt6 路径 (自动检测或手动设置)
+if(CMAKE_SYSTEM_NAME STREQUAL "Darwin")
+ # 检测架构
+ if(CMAKE_SYSTEM_PROCESSOR STREQUAL "arm64")
+ set(QT6_PATH "/opt/homebrew/opt/qt" CACHE PATH "Qt6 installation path")
+ else()
+ set(QT6_PATH "/usr/local/opt/qt" CACHE PATH "Qt6 installation path")
+ endif()
-include_directories(.)
+ # 添加到 CMake 搜索路径
+ list(APPEND CMAKE_PREFIX_PATH "${QT6_PATH}/lib/cmake")
+endif()
-set (SRCS
- flock.cpp
- flock.h
- main.cpp
+find_package(Qt6 REQUIRED COMPONENTS Core Gui Widgets Xml)
+
+add_executable(${CMAKE_PROJECT_NAME} WIN32 MACOSX_BUNDLE main.cpp)
+
+set_target_properties(${CMAKE_PROJECT_NAME} PROPERTIES
+ WIN32_EXECUTABLE TRUE
+ MACOSX_BUNDLE TRUE
)
-add_executable(${CMAKE_PROJECT_NAME} ${SRCS})
+target_link_libraries(${CMAKE_PROJECT_NAME} PRIVATE Qt6 Qt6::Core
+ Qt6::Gui
+ Qt6::Widgets
+ Qt6::Xml
+)
-target_link_libraries(${CMAKE_PROJECT_NAME} PRIVATE Qt6::Core Qt6::Gui Qt6::Widgets)
+# macOS 特定设置
+if(APPLE)
+ set_target_properties(FloatingClock PROPERTIES
+ MACOSX_BUNDLE TRUE
+ MACOSX_BUNDLE_INFO_PLIST ${CMAKE_SOURCE_DIR}/Info.plist.in
+ )
+
+ # 修复运行时库路径
+ set_target_properties(FloatingClock PROPERTIES
+ INSTALL_RPATH "${QT6_PATH}/lib"
+ BUILD_WITH_INSTALL_RPATH TRUE
+ )
+endif()
diff --git a/clock.py b/clock.py
deleted file mode 100644
index 25babd6..0000000
--- a/clock.py
+++ /dev/null
@@ -1,166 +0,0 @@
-import sys
-
-from PySide6.QtCore import QPoint, QSettings, Qt, QTime, QTimer
-from PySide6.QtGui import QAction, QFont, QMouseEvent
-from PySide6.QtWidgets import QApplication, QLabel, QMenu, QVBoxLayout, QWidget
-
-
-class Clock(QWidget):
- def __init__(self, parent=None) -> None:
- super().__init__(parent)
-
- # geometry of Mmin window (x, y, width, height)
- self.setGeometry(1100, 800, 180, 60)
-
- # hide frame
- self.setWindowFlag(Qt.WindowStaysOnTopHint, True)
- self.setWindowFlag(Qt.FramelessWindowHint, True)
- self.setAttribute(Qt.WA_TranslucentBackground)
-
- # mouse & menu
- self.pressed = False
- self.oldPos = QPoint(0, 0)
- self.setContextMenuPolicy(Qt.CustomContextMenu)
- self.customContextMenuRequested.connect(self.mouseRightMenu)
-
- # clock object
- clock = QTimer(self)
- clock.timeout.connect(self.showTime)
- clock.start(1000) # update the clock per second
- self.show()
-
- self.settings = QSettings(f"{sys.argv[0]}/../config.ini", QSettings.IniFormat)
- font = QFont()
- font.setFamily(self.settings.value("USER/FONT_FAMILY"))
- font.setPointSize(int(self.settings.value("USER/FONT_SIZE")))
-
- # load settings
- self.settings = QSettings(f"{sys.argv[0]}/../config.ini", QSettings.IniFormat)
-
- # # font object
- self.font = QFont()
- self.font.setFamily(self.settings.value("DEFAULT/FONT_FAMILY"))
- self.font_size_step = int(self.settings.value("USER/FONT_SIZE_STEP"))
-
- # label object
- self.label = QLabel()
- self.label.setAlignment(Qt.AlignCenter)
-
- # layout
- layout = QVBoxLayout(self, spacing=0)
- layout.addWidget(self.label)
- self.setLayout(layout)
-
- self.reloadUI()
-
- def reloadUI(self):
- self.font_size = int(self.settings.value("USER/FONT_SIZE"))
- self.font.setPointSize(self.font_size)
- self.label.setFont(self.font)
- self.label.setStyleSheet(
- f"color: {self.settings.value('USER/FONT_COLOR')}; "
- f"background-color: {self.settings.value('USER/BG_COLOR')}"
- )
-
- def resetUI(self):
- default_bg_color = self.settings.value("DEFAULT/BG_COLOR")
- default_font_color = self.settings.value("DEFAULT/FONT_COLOR")
- default_font_size = self.settings.value("DEFAULT/FONT_SIZE")
-
- self.settings.setValue("USER/BG_COLOR", default_bg_color)
- self.settings.setValue("USER/FONT_COLOR", default_font_color)
- self.settings.setValue("USER/FONT_SIZE", default_font_size)
-
- self.reloadUI()
-
- def increaseFontSize(self):
- self.font_size += self.font_size_step
- self.changeFontSize()
-
- def decreaseFontSize(self):
- self.font_size -= self.font_size_step
- self.changeFontSize()
-
- def changeFontSize(self):
- font = self.label.font()
- font.setPointSize(self.font_size)
- self.label.setFont(font)
-
- def setFontColor(self, color: str) -> None:
- self.settings.setValue("USER/FONT_COLOR", color)
- self.reloadUI()
-
- def setBackgroundColor(self, color: str) -> None:
- self.settings.setValue("USER/BG_COLOR", color)
- self.reloadUI()
-
- def mousePressEvent(self, event: QMouseEvent) -> None:
- self.pressed = True
- self.oldPos = event.pos()
- super().mousePressEvent(event)
-
- def mouseMoveEvent(self, event: QMouseEvent) -> None:
- if self.pressed:
- self.move(self.pos() + (event.pos() - self.oldPos))
- super().mouseMoveEvent(event)
-
- def mouseReleaseEvent(self, event: QMouseEvent) -> None:
- self.pressed = False
- self.oldPos = event.pos()
- super().mouseReleaseEvent(event)
-
- def mouseRightMenu(self, pos) -> None:
- menu = QMenu(self)
-
- # font size
- font_size_menu = menu.addMenu("font size")
- larger_action = QAction("larger", self)
- smaller_action = QAction("smaller", self)
-
- larger_action.triggered.connect(self.increaseFontSize)
- smaller_action.triggered.connect(self.decreaseFontSize)
-
- font_size_menu.addAction(larger_action)
- font_size_menu.addAction(smaller_action)
-
- ft_colors = ["none", "blue", "orange", "green", "red", "yellow", "white"]
- bg_colors = ["none", "blue", "orange", "green", "red", "yellow", "white"]
-
- # font color
- font_color_menu = menu.addMenu("font color")
- font_color_actions = [
- QAction(color, self, triggered=lambda c=color: self.setFontColor(c))
- for color in ft_colors
- ]
- font_color_menu.addActions(font_color_actions)
-
- # background color
- bg_color_menu = menu.addMenu("bg color")
- bg_color_actions = [
- QAction(color, self, triggered=lambda c=color: self.setBackgroundColor(c))
- for color in bg_colors
- ]
- bg_color_menu.addActions(bg_color_actions)
-
- # reset
- reset_action = QAction("reset", self)
- reset_action.triggered.connect(self.resetUI)
- menu.addAction(reset_action)
-
- # quit
- quit_action = QAction("quit", self)
- quit_action.triggered.connect(self.close)
- menu.addAction(quit_action)
-
- menu.exec(self.mapToGlobal(pos))
-
- def showTime(self):
- current_time = QTime.currentTime().toString("hh:mm")
- self.label.setText(current_time)
-
-
-if __name__ == "__main__":
- app = QApplication(sys.argv)
- clock = Clock()
- clock.show() # show all the widgets
- app.exit(app.exec()) # start the app
diff --git a/config.ini b/config.ini
deleted file mode 100644
index 2cf1b50..0000000
--- a/config.ini
+++ /dev/null
@@ -1,13 +0,0 @@
-[DEFAULT]
-BG_COLOR=NONE
-FONT_COLOR=blue
-FONT_FAMILY=Arial
-FONT_SIZE=50
-FONT_SIZE_STEP=10
-
-[USER]
-BG_COLOR=NONE
-FONT_COLOR=blue
-FONT_FAMILY=Arial
-FONT_SIZE=50
-FONT_SIZE_STEP=10
diff --git a/config.xml b/config.xml
new file mode 100644
index 0000000..ff103a3
--- /dev/null
+++ b/config.xml
@@ -0,0 +1,41 @@
+
+
+
+
+
+ 350
+ 180
+ -1
+ -1
+ 20
+ 2
+ #333333
+
+
+
+
+ 96
+ Arial
+ true
+ false
+ #ff6600
+
+
+
+
+ #1a000000
+
+
+
+
+
+
+
+ 30
+ 4
+ 4
+ #80000000
+
+
diff --git a/flock.cpp b/flock.cpp
deleted file mode 100644
index dfb5a97..0000000
--- a/flock.cpp
+++ /dev/null
@@ -1,176 +0,0 @@
-#include "flock.h"
-
-Clock::Clock(QWidget *parent) : QWidget{parent}, pressed(false) {
- // geometry of Main Window (x, y, width, height)
- setGeometry(1100, 800, 180, 60);
-
- // hide frame
- setWindowFlag(Qt::WindowStaysOnTopHint, true);
- setWindowFlag(Qt::FramelessWindowHint, true);
- setAttribute(Qt::WA_TranslucentBackground);
-
- // setFixedSize(this->width(), this->height());
- setWindowFlags(windowFlags() & ~Qt::WindowMaximizeButtonHint &
- ~Qt::WindowMinimizeButtonHint);
-
- // clock object
- QTimer *clock = new QTimer(this);
- connect(clock, &QTimer::timeout, this, &Clock::showTime);
- clock->start(1000); // update the clock per second
- show();
-
- settings = new QSettings(
- QString("%1/config.ini").arg(QCoreApplication::applicationDirPath()),
- QSettings::IniFormat);
-
- font = QFont();
- font.setFamily(settings->value("USER/FONT_FAMILY").toString());
- font.setPointSize(settings->value("USER/FONT_SIZE").toInt());
-
- // load settings
- settings = new QSettings(QString("%1/../floating-clock/config.ini")
- .arg(QCoreApplication::applicationDirPath()),
- QSettings::IniFormat);
-
- // font object
- font = QFont();
- font.setFamily(settings->value("DEFAULT/FONT_FAMILY").toString());
- font_size_step = settings->value("USER/FONT_SIZE_STEP").toInt();
-
- // label object
- label = new QLabel();
- label->setAlignment(Qt::AlignCenter);
-
- // layout
- QVBoxLayout *layout = new QVBoxLayout(this);
- layout->addWidget(label);
- setLayout(layout);
-
- reloadUI();
-}
-
-void Clock::showTime() {
- QString current_time = QTime::currentTime().toString("hh:mm");
- label->setText(current_time);
-}
-
-void Clock::reloadUI() {
- font_size = settings->value("USER/FONT_SIZE").toInt();
- font.setPointSize(font_size);
- label->setFont(font);
- label->setStyleSheet(QString("color: %1; background-color: %2")
- .arg(settings->value("USER/FONT_COLOR").toString(),
- settings->value("USER/BG_COLOR").toString()));
-}
-
-void Clock::resetUI() {
- QString default_bg_color = settings->value("DEFAULT/BG_COLOR").toString();
- QString default_font_color = settings->value("DEFAULT/FONT_COLOR").toString();
- QString default_font_size = settings->value("DEFAULT/FONT_SIZE").toString();
-
- settings->setValue("USER/BG_COLOR", default_bg_color);
- settings->setValue("USER/FONT_COLOR", default_font_color);
- settings->setValue("USER/FONT_SIZE", default_font_size);
-
- reloadUI();
-}
-
-void Clock::increaseFontSize() {
- font_size += font_size_step;
- changeFontSize();
-}
-
-void Clock::decreaseFontSize() {
- font_size -= font_size_step;
- changeFontSize();
-}
-
-void Clock::changeFontSize() {
- font.setPointSize(font_size);
- label->setFont(font);
-}
-
-void Clock::setFontColor(const QString &color) {
- settings->setValue("USER/FONT_COLOR", color);
- reloadUI();
-}
-
-void Clock::setBackgroundColor(const QString &color) {
- settings->setValue("USER/BG_COLOR", color);
- reloadUI();
-}
-
-void Clock::mousePressEvent(QMouseEvent *event) {
- pressed = true;
- oldPos = event->pos();
- QWidget::mousePressEvent(event);
-}
-
-void Clock::mouseMoveEvent(QMouseEvent *event) {
- if (pressed) {
- move(pos() + (event->pos() - oldPos));
- }
- QWidget::mouseMoveEvent(event);
-}
-
-void Clock::mouseReleaseEvent(QMouseEvent *event) {
- pressed = false;
- oldPos = event->pos();
- QWidget::mouseReleaseEvent(event);
-}
-
-void Clock::contextMenuEvent(QContextMenuEvent *event) {
- QMenu *menu = new QMenu();
-
- // menu->setFixedWidth(100);
-
- // font size
- QMenu *font_size_menu = menu->addMenu("font size");
- QAction *larger_action = new QAction("larger", this);
- QAction *smaller_action = new QAction("smaller", this);
-
- connect(larger_action, &QAction::triggered, this, &Clock::increaseFontSize);
- connect(smaller_action, &QAction::triggered, this, &Clock::decreaseFontSize);
-
- font_size_menu->addAction(larger_action);
- font_size_menu->addAction(smaller_action);
-
- QStringList ft_colors = {"none", "blue", "orange", "green",
- "red", "yellow", "white"};
- QStringList bg_colors = {"none", "blue", "orange", "green",
- "red", "yellow", "white"};
-
- // font color
- QMenu *font_color_menu = menu->addMenu("font color");
- QList font_color_actions;
- for (const QString &color : ft_colors) {
- QAction *action = new QAction(color, this);
- connect(action, &QAction::triggered, [=]() { setFontColor(color); });
- font_color_actions.append(action);
- }
- font_color_menu->addActions(font_color_actions);
-
- // background color
- QMenu *bg_color_menu = menu->addMenu("bg color");
- QList bg_color_actions;
- for (const QString &color : bg_colors) {
- QAction *action = new QAction(color, this);
- connect(action, &QAction::triggered, [=]() { setBackgroundColor(color); });
- bg_color_actions.append(action);
- }
- bg_color_menu->addActions(bg_color_actions);
-
- // reset
- QAction *reset_action = new QAction("reset", this);
- connect(reset_action, &QAction::triggered, this, &Clock::resetUI);
- menu->addAction(reset_action);
-
- // quit
- QAction *quit_action = new QAction("quit", this);
- connect(quit_action, &QAction::triggered, this, &Clock::close);
- menu->addAction(quit_action);
-
- // menu.exec(mapToGlobal(pos));
- menu->exec(event->globalPos());
- delete menu;
-}
diff --git a/flock.h b/flock.h
deleted file mode 100644
index 79240f5..0000000
--- a/flock.h
+++ /dev/null
@@ -1,52 +0,0 @@
-#ifndef CLOCK_H
-#define CLOCK_H
-
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-
-class Clock : public QWidget {
- Q_OBJECT
-public:
- explicit Clock(QWidget *parent = nullptr);
- void reloadUI();
- void resetUI();
- void increaseFontSize();
- void decreaseFontSize();
- void changeFontSize();
- void setFontColor(const class QString &color);
- void setBackgroundColor(const class QString &color);
-
-protected:
- void mousePressEvent(QMouseEvent *event) override;
- void mouseMoveEvent(QMouseEvent *event) override;
- void mouseReleaseEvent(QMouseEvent *event) override;
- void mouseRightMenu(const QPoint &pos);
-
-signals:
-
-public slots:
- void showTime();
-
-private:
- bool pressed;
- QPoint oldPos;
- QSettings *settings;
- QFont font;
- int font_size_step;
- int font_size;
- QLabel *label;
-
- void contextMenuEvent(QContextMenuEvent *e) override;
-};
-
-#endif // CLOCK_H
diff --git a/main.cpp b/main.cpp
index 6a18f6b..b23f80f 100644
--- a/main.cpp
+++ b/main.cpp
@@ -1,10 +1,626 @@
#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
-#include "flock.h"
+class FloatingClock : public QWidget
+{
+ Q_OBJECT
-auto main(int argc, char *argv[]) -> int {
+public:
+ FloatingClock(QWidget *parent = nullptr) : QWidget(parent)
+ {
+ // 先加载XML配置(在创建UI之前)
+ loadXmlConfig();
+
+ // 无边框、置顶、透明背景
+ setWindowFlags(Qt::FramelessWindowHint |
+ Qt::WindowStaysOnTopHint |
+ Qt::Tool |
+ Qt::WindowDoesNotAcceptFocus);
+ setAttribute(Qt::WA_TranslucentBackground);
+
+ // 创建时间标签
+ timeLabel = new QLabel(this);
+ timeLabel->setAlignment(Qt::AlignCenter);
+
+ updateStyle();
+
+ // 布局
+ QVBoxLayout *layout = new QVBoxLayout(this);
+ layout->addWidget(timeLabel);
+ layout->setContentsMargins(20, 20, 20, 20);
+ setLayout(layout);
+
+ // 添加阴影效果
+ QGraphicsDropShadowEffect *shadow = new QGraphicsDropShadowEffect(this);
+ shadow->setBlurRadius(shadowBlurRadius);
+ shadow->setColor(shadowColor);
+ shadow->setOffset(shadowOffsetX, shadowOffsetY);
+ timeLabel->setGraphicsEffect(shadow);
+
+ // 定时器更新
+ QTimer *timer = new QTimer(this);
+ connect(timer, &QTimer::timeout, this, &FloatingClock::updateTime);
+ timer->start(1000);
+ updateTime();
+
+ // 加载用户设置(覆盖XML默认值)
+ loadUserSettings();
+
+ // 调整大小
+ resize(windowWidth, windowHeight);
+
+ // 如果位置未设置,居中显示
+ if (windowPosX < 0 || windowPosY < 0)
+ {
+ moveToCenter();
+ }
+ else
+ {
+ move(windowPosX, windowPosY);
+ }
+ }
+
+protected:
+ void mousePressEvent(QMouseEvent *event) override
+ {
+ if (event->button() == Qt::LeftButton)
+ {
+ dragging = true;
+ dragPos = event->globalPosition().toPoint() - frameGeometry().topLeft();
+ event->accept();
+ }
+ else if (event->button() == Qt::RightButton)
+ {
+ showContextMenu(event->globalPosition().toPoint());
+ }
+ }
+
+ void mouseMoveEvent(QMouseEvent *event) override
+ {
+ if (dragging && (event->buttons() & Qt::LeftButton))
+ {
+ move(event->globalPosition().toPoint() - dragPos);
+ event->accept();
+ }
+ }
+
+ void mouseReleaseEvent(QMouseEvent *event) override
+ {
+ if (event->button() == Qt::LeftButton)
+ {
+ dragging = false;
+ saveUserSettings();
+ }
+ }
+
+ void paintEvent(QPaintEvent *) override
+ {
+ QPainter painter(this);
+ painter.setRenderHint(QPainter::Antialiasing);
+
+ // 绘制半透明背景
+ if (bgColor.alpha() > 0)
+ {
+ QPainterPath path;
+ path.addRoundedRect(rect(), borderRadius, borderRadius);
+ painter.fillPath(path, bgColor);
+
+ // 绘制边框
+ if (borderWidth > 0)
+ {
+ QPen pen(borderColor);
+ pen.setWidth(borderWidth);
+ painter.setPen(pen);
+ painter.drawPath(path);
+ }
+ }
+ }
+
+private slots:
+ void updateTime()
+ {
+ QTime time = QTime::currentTime();
+ QString text = time.toString(timeFormat);
+ timeLabel->setText(text);
+ }
+
+ void changeFontSize()
+ {
+ bool ok;
+ int size = QInputDialog::getInt(this, "字体大小", "请输入字体大小:",
+ fontSize, 6, 300, 1, &ok);
+ if (ok)
+ {
+ fontSize = size;
+ updateStyle();
+ saveUserSettings();
+ }
+ }
+
+ void changeFontColor()
+ {
+ QColor color = QColorDialog::getColor(fontColor, this, "选择字体颜色",
+ QColorDialog::ShowAlphaChannel);
+ if (color.isValid())
+ {
+ fontColor = color;
+ updateStyle();
+ saveUserSettings();
+ }
+ }
+
+ void changeBgColor()
+ {
+ QColor color = QColorDialog::getColor(bgColor, this, "选择背景颜色",
+ QColorDialog::ShowAlphaChannel);
+ if (color.isValid())
+ {
+ bgColor = color;
+ update();
+ saveUserSettings();
+ }
+ }
+
+ void resetSettings()
+ {
+ // 重新加载XML默认配置
+ loadXmlConfig();
+ updateStyle();
+ update();
+ moveToCenter();
+ saveUserSettings();
+ }
+
+ void quitApp()
+ {
+ qApp->quit();
+ }
+
+private:
+ void showContextMenu(const QPoint &pos)
+ {
+ QMenu menu(this);
+ menu.setStyleSheet(R"(
+ QMenu {
+ background-color: #f0f0f0;
+ border: 1px solid #cccccc;
+ border-radius: 8px;
+ padding: 5px;
+ }
+ QMenu::item {
+ padding: 8px 25px;
+ border-radius: 4px;
+ }
+ QMenu::item:selected {
+ background-color: #e0e0e0;
+ }
+ QMenu::item::right-arrow {
+ image: none;
+ width: 10px;
+ height: 10px;
+ border-left: 6px solid #333;
+ border-top: 5px solid transparent;
+ border-bottom: 5px solid transparent;
+ margin-right: 5px;
+ }
+ )");
+
+ QMenu *fontMenu = menu.addMenu("▶ 字体大小");
+ for (int size : {36, 48, 64, 72, 96, 120})
+ {
+ QAction *action = fontMenu->addAction(QString::number(size));
+ connect(action, &QAction::triggered, this, [this, size]()
+ {
+ fontSize = size;
+ updateStyle();
+ saveUserSettings(); });
+ }
+ fontMenu->addSeparator();
+ QAction *customSize = fontMenu->addAction("自定义...");
+ connect(customSize, &QAction::triggered, this, &FloatingClock::changeFontSize);
+
+ QMenu *colorMenu = menu.addMenu("▶ 字体颜色");
+ QList> colors = {
+ {"蓝色", QColor(0, 0, 255)},
+ {"红色", QColor(255, 0, 0)},
+ {"绿色", QColor(0, 128, 0)},
+ {"黑色", QColor(0, 0, 0)},
+ {"白色", QColor(255, 255, 255)},
+ {"橙色", QColor(255, 165, 0)},
+ {"紫色", QColor(128, 0, 128)}};
+ for (auto &c : colors)
+ {
+ QPixmap pixmap(16, 16);
+ pixmap.fill(c.second);
+ QAction *action = colorMenu->addAction(QIcon(pixmap), c.first);
+ connect(action, &QAction::triggered, this, [this, color = c.second]() mutable
+ {
+ fontColor = color;
+ updateStyle();
+ saveUserSettings(); });
+ }
+ colorMenu->addSeparator();
+ QAction *customColor = colorMenu->addAction("自定义...");
+ connect(customColor, &QAction::triggered, this, &FloatingClock::changeFontColor);
+
+ QMenu *bgMenu = menu.addMenu("▶ 背景颜色");
+ QList> bgColors = {
+ {"透明", QColor(255, 255, 255, 0)},
+ {"白色半透明", QColor(255, 255, 255, 180)},
+ {"黑色半透明", QColor(0, 0, 0, 180)},
+ {"灰色半透明", QColor(128, 128, 128, 180)},
+ {"蓝色半透明", QColor(0, 100, 200, 180)},
+ {"自定义...", QColor()}};
+ for (auto &c : bgColors)
+ {
+ if (c.first == "自定义...")
+ {
+ QAction *action = bgMenu->addAction(c.first);
+ connect(action, &QAction::triggered, this, &FloatingClock::changeBgColor);
+ }
+ else
+ {
+ QPixmap pixmap(16, 16);
+ pixmap.fill(c.second);
+ QAction *action = bgMenu->addAction(QIcon(pixmap), c.first);
+ connect(action, &QAction::triggered, this, [this, color = c.second]() mutable
+ {
+ bgColor = color;
+ update();
+ saveUserSettings(); });
+ }
+ }
+
+ menu.addSeparator();
+ QAction *resetAction = menu.addAction("重置");
+ connect(resetAction, &QAction::triggered, this, &FloatingClock::resetSettings);
+
+ menu.addSeparator();
+ QAction *quitAction = menu.addAction("退出");
+ connect(quitAction, &QAction::triggered, this, &FloatingClock::quitApp);
+
+ menu.exec(pos);
+ }
+
+ void updateStyle()
+ {
+ QFont font(fontFamily, fontSize, fontWeight ? QFont::Bold : QFont::Normal);
+ if (fontItalic)
+ font.setItalic(true);
+ timeLabel->setFont(font);
+
+ QString style = QString("color: %1;").arg(fontColor.name());
+ timeLabel->setStyleSheet(style);
+ }
+
+ void moveToCenter()
+ {
+ QScreen *screen = QApplication::primaryScreen();
+ QRect geo = screen->geometry();
+ move((geo.width() - width()) / 2, (geo.height() - height()) / 2);
+ }
+
+ // 加载XML配置文件
+ void loadXmlConfig()
+ {
+ QString xmlPath = QApplication::applicationDirPath() + "/clock.xml";
+
+ // 如果XML不存在,创建默认配置
+ if (!QFile::exists(xmlPath))
+ {
+ createDefaultXml(xmlPath);
+ }
+
+ QFile file(xmlPath);
+ if (!file.open(QIODevice::ReadOnly | QIODevice::Text))
+ {
+ setDefaultValues();
+ return;
+ }
+
+ QDomDocument doc;
+ QString errorMsg;
+ int errorLine, errorColumn;
+
+ if (!doc.setContent(&file, &errorMsg, &errorLine, &errorColumn))
+ {
+ qWarning() << "XML解析错误:" << errorMsg << "行:" << errorLine << "列:" << errorColumn;
+ setDefaultValues();
+ file.close();
+ return;
+ }
+ file.close();
+
+ QDomElement root = doc.documentElement();
+ if (root.tagName() != "ClockConfig")
+ {
+ qWarning() << "XML根节点错误";
+ setDefaultValues();
+ return;
+ }
+
+ // 解析Window节点
+ QDomElement window = root.firstChildElement("Window");
+ if (!window.isNull())
+ {
+ windowWidth = getXmlInt(window, "Width", 300);
+ windowHeight = getXmlInt(window, "Height", 150);
+ windowPosX = getXmlInt(window, "PosX", -1);
+ windowPosY = getXmlInt(window, "PosY", -1);
+ borderRadius = getXmlInt(window, "BorderRadius", 15);
+ borderWidth = getXmlInt(window, "BorderWidth", 0);
+ borderColor = parseColor(getXmlString(window, "BorderColor", "#cccccc"));
+ }
+
+ // 解析Font节点
+ QDomElement font = root.firstChildElement("Font");
+ if (!font.isNull())
+ {
+ fontSize = getXmlInt(font, "Size", 72);
+ fontFamily = getXmlString(font, "Family", "Microsoft YaHei");
+ fontWeight = getXmlBool(font, "Bold", true);
+ fontItalic = getXmlBool(font, "Italic", false);
+ fontColor = parseColor(getXmlString(font, "Color", "#0000ff"));
+ }
+
+ // 解析Background节点
+ QDomElement background = root.firstChildElement("Background");
+ if (!background.isNull())
+ {
+ bgColor = parseColor(getXmlString(background, "Color", "#00ffffff"));
+ }
+
+ // 解析Time节点
+ QDomElement time = root.firstChildElement("Time");
+ if (!time.isNull())
+ {
+ timeFormat = getXmlString(time, "Format", "HH:mm");
+ }
+
+ // 解析Shadow节点
+ QDomElement shadow = root.firstChildElement("Shadow");
+ if (!shadow.isNull())
+ {
+ shadowBlurRadius = getXmlInt(shadow, "BlurRadius", 20);
+ shadowOffsetX = getXmlInt(shadow, "OffsetX", 2);
+ shadowOffsetY = getXmlInt(shadow, "OffsetY", 2);
+ shadowColor = parseColor(getXmlString(shadow, "Color", "#64000000"));
+ }
+ }
+
+ // 创建默认XML文件
+ void createDefaultXml(const QString &path)
+ {
+ QFile file(path);
+ if (!file.open(QIODevice::WriteOnly | QIODevice::Text))
+ {
+ setDefaultValues();
+ return;
+ }
+
+ QTextStream stream(&file);
+ stream.setEncoding(QStringConverter::Utf8);
+
+ stream << "\n"
+ << "\n"
+ << "\n"
+ << " \n"
+ << " \n"
+ << " 300\n"
+ << " 150\n"
+ << " -1 \n"
+ << " -1\n"
+ << " 15\n"
+ << " 0 \n"
+ << " #cccccc\n"
+ << " \n"
+ << "\n"
+ << " \n"
+ << " \n"
+ << " 72\n"
+ << " Microsoft YaHei\n"
+ << " true\n"
+ << " false\n"
+ << " #0000ff \n"
+ << " \n"
+ << "\n"
+ << " \n"
+ << " \n"
+ << " #00ffffff \n"
+ << " \n"
+ << "\n"
+ << " \n"
+ << " \n"
+ << "\n"
+ << " \n"
+ << " \n"
+ << " 20\n"
+ << " 2\n"
+ << " 2\n"
+ << " #64000000 \n"
+ << " \n"
+ << "\n";
+
+ file.close();
+ }
+
+ // 设置默认值
+ void setDefaultValues()
+ {
+ windowWidth = 300;
+ windowHeight = 150;
+ windowPosX = -1;
+ windowPosY = -1;
+ borderRadius = 15;
+ borderWidth = 0;
+ borderColor = QColor("#cccccc");
+
+ fontSize = 72;
+ fontFamily = "Microsoft YaHei";
+ fontWeight = true;
+ fontItalic = false;
+ fontColor = QColor("#0000ff");
+
+ bgColor = QColor("#00ffffff");
+ timeFormat = "HH:mm";
+
+ shadowBlurRadius = 20;
+ shadowOffsetX = 2;
+ shadowOffsetY = 2;
+ shadowColor = QColor("#64000000");
+ }
+
+ // XML辅助函数
+ int getXmlInt(const QDomElement &parent, const QString &tagName, int defaultValue)
+ {
+ QDomElement elem = parent.firstChildElement(tagName);
+ if (elem.isNull())
+ return defaultValue;
+ return elem.text().toInt();
+ }
+
+ bool getXmlBool(const QDomElement &parent, const QString &tagName, bool defaultValue)
+ {
+ QDomElement elem = parent.firstChildElement(tagName);
+ if (elem.isNull())
+ return defaultValue;
+ QString text = elem.text().toLower();
+ return text == "true" || text == "1" || text == "yes";
+ }
+
+ QString getXmlString(const QDomElement &parent, const QString &tagName, const QString &defaultValue)
+ {
+ QDomElement elem = parent.firstChildElement(tagName);
+ if (elem.isNull())
+ return defaultValue;
+ return elem.text();
+ }
+
+ // 加载用户设置(覆盖XML默认值)
+ void loadUserSettings()
+ {
+ QSettings settings("FloatingClock", "Settings");
+ if (settings.contains("fontSize"))
+ {
+ fontSize = settings.value("fontSize").toInt();
+ }
+ if (settings.contains("fontColor"))
+ {
+ fontColor = settings.value("fontColor").value();
+ }
+ if (settings.contains("bgColor"))
+ {
+ bgColor = settings.value("bgColor").value();
+ }
+ if (settings.contains("pos"))
+ {
+ QPoint pos = settings.value("pos").toPoint();
+ if (!pos.isNull())
+ move(pos);
+ }
+ }
+
+ // 保存用户设置
+ void saveUserSettings()
+ {
+ QSettings settings("FloatingClock", "Settings");
+ settings.setValue("fontSize", fontSize);
+ settings.setValue("fontColor", fontColor);
+ settings.setValue("bgColor", bgColor);
+ settings.setValue("pos", pos());
+ }
+
+ // 解析颜色字符串 (#RGB, #RRGGBB, #ARGB, #AARRGGBB)
+ QColor parseColor(const QString &str)
+ {
+ QString s = str.trimmed();
+ if (s.startsWith("#"))
+ s = s.mid(1);
+
+ bool ok;
+ uint val = s.toUInt(&ok, 16);
+ if (!ok)
+ return QColor();
+
+ switch (s.length())
+ {
+ case 3: // #RGB
+ return QColor(
+ ((val >> 8) & 0xF) * 17,
+ ((val >> 4) & 0xF) * 17,
+ (val & 0xF) * 17);
+ case 6: // #RRGGBB
+ return QColor((val >> 16) & 0xFF, (val >> 8) & 0xFF, val & 0xFF);
+ case 8: // #AARRGGBB
+ return QColor(
+ (val >> 16) & 0xFF,
+ (val >> 8) & 0xFF,
+ val & 0xFF,
+ (val >> 24) & 0xFF);
+ default:
+ return QColor();
+ }
+ }
+
+ QLabel *timeLabel;
+
+ // XML配置项
+ int windowWidth, windowHeight;
+ int windowPosX, windowPosY;
+ int borderRadius;
+ int borderWidth;
+ QColor borderColor;
+
+ int fontSize;
+ QString fontFamily;
+ bool fontWeight;
+ bool fontItalic;
+ QColor fontColor;
+
+ QColor bgColor;
+ QString timeFormat;
+
+ int shadowBlurRadius;
+ int shadowOffsetX, shadowOffsetY;
+ QColor shadowColor;
+
+ bool dragging = false;
+ QPoint dragPos;
+};
+
+#include "main.moc"
+
+int main(int argc, char *argv[])
+{
QApplication app(argc, argv);
- Clock clock;
+ // 高分屏适配
+ app.setAttribute(Qt::AA_EnableHighDpiScaling, true);
+ app.setAttribute(Qt::AA_UseHighDpiPixmaps, true);
+
+ FloatingClock clock;
+ clock.show();
+
return app.exec();
}
diff --git a/requirements.txt b/requirements.txt
deleted file mode 100644
index 9137a62..0000000
--- a/requirements.txt
+++ /dev/null
@@ -1 +0,0 @@
-pyside6