From 6bc5c612d6e202a585f772399d929ad750a745c3 Mon Sep 17 00:00:00 2001 From: ivaquero Date: Fri, 10 Apr 2026 17:45:34 +0800 Subject: [PATCH] update config --- .vscode/c_cpp_properties.json | 2 +- .vscode/launch.json | 2 +- .vscode/tasks.json | 4 +- CMakeLists.txt | 2 +- FloatingClock.h | 78 +++++ Info.plist.in | 26 ++ flock.pro | 6 +- main.cpp | 624 +--------------------------------- 8 files changed, 115 insertions(+), 629 deletions(-) create mode 100644 FloatingClock.h create mode 100644 Info.plist.in diff --git a/.vscode/c_cpp_properties.json b/.vscode/c_cpp_properties.json index d094de3..e9fb10b 100644 --- a/.vscode/c_cpp_properties.json +++ b/.vscode/c_cpp_properties.json @@ -4,7 +4,7 @@ "name": "macos-conda-qt", "includePath": [ "${workspaceFolder}/**", - "${env:HOMEBREW_CELLAR}/qt/6.11.0/include/**", + "/opt/homebrew/opt/qt/include" ], "defines": [], "compilerPath": "/usr/bin/clang++", diff --git a/.vscode/launch.json b/.vscode/launch.json index 74acc45..a90ed95 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -14,7 +14,7 @@ "environment": [ { "name": "DYLD_LIBRARY_PATH", - "value": "${env:HOMEBREW_CELLAR}/qt/6.11.0/lib" + "value": "/opt/homebrew/opt/qt/lib" } ], "MIMode": "lldb", diff --git a/.vscode/tasks.json b/.vscode/tasks.json index af766c4..6449c26 100644 --- a/.vscode/tasks.json +++ b/.vscode/tasks.json @@ -11,9 +11,9 @@ "-o", "${fileDirname}/${fileBasenameNoExtension}", "-I", - "${env:HOMEBREW_CELLAR}/qtbase/6.11.0/include", + "/opt/homebrew/opt/qt/include", "-L", - "${env:HOMEBREW_CELLAR}/qtbase/6.11.0/lib", + "/opt/homebrew/opt/qt/lib", "-lQt6Core", "-lQt6Gui", "-lQt6Widgets" diff --git a/CMakeLists.txt b/CMakeLists.txt index e3ad736..512a72c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -39,7 +39,7 @@ set_target_properties(${CMAKE_PROJECT_NAME} PROPERTIES MACOSX_BUNDLE TRUE ) -target_link_libraries(${CMAKE_PROJECT_NAME} PRIVATE Qt6 Qt6::Core +target_link_libraries(${CMAKE_PROJECT_NAME} PRIVATE Qt6::Core Qt6::Gui Qt6::Widgets Qt6::Xml diff --git a/FloatingClock.h b/FloatingClock.h new file mode 100644 index 0000000..789ece8 --- /dev/null +++ b/FloatingClock.h @@ -0,0 +1,78 @@ +#ifndef FLOATINGCLOCK_H +#define FLOATINGCLOCK_H + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +class FloatingClock : public QWidget +{ + Q_OBJECT + +public: + explicit FloatingClock(QWidget *parent = nullptr); + ~FloatingClock(); + +protected: + void mousePressEvent(QMouseEvent *event) override; + void mouseMoveEvent(QMouseEvent *event) override; + void mouseReleaseEvent(QMouseEvent *event) override; + void paintEvent(QPaintEvent *) override; + +private slots: + void updateTime(); + void changeFontSize(); + void changeFontColor(); + void changeBgColor(); + void resetSettings(); + void quitApp(); + +private: + void showContextMenu(const QPoint &pos); + void updateStyle(); + void moveToCenter(); + void loadXmlConfig(); + void createDefaultXml(const QString &path); + void setDefaultValues(); + void applyXmlValues(const QMap &values); + bool parseBool(const QString &str); + void loadUserSettings(); + void saveUserSettings(); + QColor parseColor(const QString &str); + + QLabel *timeLabel; + + 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; +}; + +#endif diff --git a/Info.plist.in b/Info.plist.in new file mode 100644 index 0000000..81ce9d5 --- /dev/null +++ b/Info.plist.in @@ -0,0 +1,26 @@ + + + + + CFBundleExecutable + ${MACOSX_BUNDLE_EXECUTABLE_NAME} + CFBundleIdentifier + com.example.FloatingClock + CFBundleName + FloatingClock + CFBundleVersion + 1.0 + CFBundleShortVersionString + 1.0 + CFBundleInfoDictionaryVersion + 6.0 + CFBundlePackageType + APPL + CFBundleSignature + ???? + LSMinimumSystemVersion + 10.12 + NSHighResolutionCapable + + + diff --git a/flock.pro b/flock.pro index c3360f2..f43210e 100644 --- a/flock.pro +++ b/flock.pro @@ -5,15 +5,11 @@ QT = core gui widgets -HEADERS = \ - $$PWD/flock.h - SOURCES = \ - $$PWD/flock.cpp \ $$PWD/main.cpp INCLUDEPATH = \ $$PWD/. -#DEFINES = +#DEFINES = diff --git a/main.cpp b/main.cpp index b23f80f..2bb6039 100644 --- a/main.cpp +++ b/main.cpp @@ -1,626 +1,12 @@ #include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -class FloatingClock : public QWidget -{ - Q_OBJECT - -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" +#include "FloatingClock.h" int main(int argc, char *argv[]) { - QApplication app(argc, argv); + QApplication app(argc, argv); - // 高分屏适配 - app.setAttribute(Qt::AA_EnableHighDpiScaling, true); - app.setAttribute(Qt::AA_UseHighDpiPixmaps, true); + FloatingClock clock; + clock.show(); - FloatingClock clock; - clock.show(); - - return app.exec(); + return app.exec(); }