update qt
This commit is contained in:
@@ -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]
|
|
||||||
Vendored
+33
-3
@@ -1,6 +1,36 @@
|
|||||||
{
|
{
|
||||||
"includePath": "/opt/homebrew/include",
|
"configurations": [
|
||||||
|
{
|
||||||
|
"name": "macos-conda-qt",
|
||||||
|
"includePath": [
|
||||||
|
"${workspaceFolder}/**",
|
||||||
|
"${env:HOMEBREW_CELLAR}/qt/6.11.0/include/**",
|
||||||
|
],
|
||||||
|
"defines": [],
|
||||||
"compilerPath": "/usr/bin/clang++",
|
"compilerPath": "/usr/bin/clang++",
|
||||||
"cStandard": "c11",
|
"cStandard": "c17",
|
||||||
"cppStandard": "c++17"
|
"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
|
||||||
}
|
}
|
||||||
|
|||||||
Vendored
+58
@@ -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"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
Vendored
+78
@@ -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."
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
+40
-10
@@ -4,7 +4,10 @@ if(${CMAKE_VERSION} VERSION_LESS 3.12)
|
|||||||
cmake_policy(VERSION ${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION})
|
cmake_policy(VERSION ${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION})
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
project(clock)
|
project(FloatingClock)
|
||||||
|
|
||||||
|
set(CMAKE_CXX_STANDARD 17)
|
||||||
|
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||||
|
|
||||||
set(CMAKE_AUTOUIC ON)
|
set(CMAKE_AUTOUIC ON)
|
||||||
set(CMAKE_AUTOMOC 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_STANDARD_REQUIRED True)
|
||||||
set(CMAKE_CXX_EXTENSIONS OFF)
|
set(CMAKE_CXX_EXTENSIONS OFF)
|
||||||
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
|
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
|
find_package(Qt6 REQUIRED COMPONENTS Core Gui Widgets Xml)
|
||||||
flock.cpp
|
|
||||||
flock.h
|
add_executable(${CMAKE_PROJECT_NAME} WIN32 MACOSX_BUNDLE main.cpp)
|
||||||
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()
|
||||||
|
|||||||
@@ -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
|
|
||||||
-13
@@ -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
|
|
||||||
+41
@@ -0,0 +1,41 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!-- 浮动时钟配置文件 -->
|
||||||
|
<ClockConfig>
|
||||||
|
<!-- 窗口设置 -->
|
||||||
|
<Window>
|
||||||
|
<Width>350</Width>
|
||||||
|
<Height>180</Height>
|
||||||
|
<PosX>-1</PosX> <!-- -1表示屏幕居中 -->
|
||||||
|
<PosY>-1</PosY>
|
||||||
|
<BorderRadius>20</BorderRadius>
|
||||||
|
<BorderWidth>2</BorderWidth>
|
||||||
|
<BorderColor>#333333</BorderColor>
|
||||||
|
</Window>
|
||||||
|
|
||||||
|
<!-- 字体设置 -->
|
||||||
|
<Font>
|
||||||
|
<Size>96</Size>
|
||||||
|
<Family>Arial</Family>
|
||||||
|
<Bold>true</Bold>
|
||||||
|
<Italic>false</Italic>
|
||||||
|
<Color>#ff6600</Color>
|
||||||
|
</Font>
|
||||||
|
|
||||||
|
<!-- 背景设置 -->
|
||||||
|
<Background>
|
||||||
|
<Color>#1a000000</Color> <!-- 半透明黑色背景 -->
|
||||||
|
</Background>
|
||||||
|
|
||||||
|
<!-- 时间格式 -->
|
||||||
|
<Time>
|
||||||
|
<Format>HH:mm:ss</Format>
|
||||||
|
</Time>
|
||||||
|
|
||||||
|
<!-- 阴影效果 -->
|
||||||
|
<Shadow>
|
||||||
|
<BlurRadius>30</BlurRadius>
|
||||||
|
<OffsetX>4</OffsetX>
|
||||||
|
<OffsetY>4</OffsetY>
|
||||||
|
<Color>#80000000</Color>
|
||||||
|
</Shadow>
|
||||||
|
</ClockConfig>
|
||||||
@@ -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<QAction *> 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<QAction *> 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;
|
|
||||||
}
|
|
||||||
@@ -1,52 +0,0 @@
|
|||||||
#ifndef CLOCK_H
|
|
||||||
#define CLOCK_H
|
|
||||||
|
|
||||||
#include <QApplication>
|
|
||||||
#include <QLabel>
|
|
||||||
#include <QLocale>
|
|
||||||
#include <QMenu>
|
|
||||||
#include <QMouseEvent>
|
|
||||||
#include <QPoint>
|
|
||||||
#include <QSettings>
|
|
||||||
#include <QTime>
|
|
||||||
#include <QTimer>
|
|
||||||
#include <QTranslator>
|
|
||||||
#include <QVBoxLayout>
|
|
||||||
#include <QWidget>
|
|
||||||
|
|
||||||
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
|
|
||||||
@@ -1,10 +1,626 @@
|
|||||||
#include <QApplication>
|
#include <QApplication>
|
||||||
|
#include <QWidget>
|
||||||
|
#include <QLabel>
|
||||||
|
#include <QVBoxLayout>
|
||||||
|
#include <QTimer>
|
||||||
|
#include <QTime>
|
||||||
|
#include <QMouseEvent>
|
||||||
|
#include <QMenu>
|
||||||
|
#include <QFontDialog>
|
||||||
|
#include <QColorDialog>
|
||||||
|
#include <QSettings>
|
||||||
|
#include <QGraphicsDropShadowEffect>
|
||||||
|
#include <QScreen>
|
||||||
|
#include <QPainter>
|
||||||
|
#include <QPainterPath>
|
||||||
|
#include <QInputDialog>
|
||||||
|
#include <QFile>
|
||||||
|
#include <QTextStream>
|
||||||
|
#include <QDir>
|
||||||
|
#include <QDomDocument>
|
||||||
|
#include <QMessageBox>
|
||||||
|
|
||||||
#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<QPair<QString, QColor>> 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<QPair<QString, QColor>> 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 << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
|
||||||
|
<< "<!-- 浮动时钟配置文件 -->\n"
|
||||||
|
<< "<ClockConfig>\n"
|
||||||
|
<< " <!-- 窗口设置 -->\n"
|
||||||
|
<< " <Window>\n"
|
||||||
|
<< " <Width>300</Width>\n"
|
||||||
|
<< " <Height>150</Height>\n"
|
||||||
|
<< " <PosX>-1</PosX> <!-- -1表示屏幕居中 -->\n"
|
||||||
|
<< " <PosY>-1</PosY>\n"
|
||||||
|
<< " <BorderRadius>15</BorderRadius>\n"
|
||||||
|
<< " <BorderWidth>0</BorderWidth> <!-- 0表示无边框 -->\n"
|
||||||
|
<< " <BorderColor>#cccccc</BorderColor>\n"
|
||||||
|
<< " </Window>\n"
|
||||||
|
<< "\n"
|
||||||
|
<< " <!-- 字体设置 -->\n"
|
||||||
|
<< " <Font>\n"
|
||||||
|
<< " <Size>72</Size>\n"
|
||||||
|
<< " <Family>Microsoft YaHei</Family>\n"
|
||||||
|
<< " <Bold>true</Bold>\n"
|
||||||
|
<< " <Italic>false</Italic>\n"
|
||||||
|
<< " <Color>#0000ff</Color> <!-- 蓝色 -->\n"
|
||||||
|
<< " </Font>\n"
|
||||||
|
<< "\n"
|
||||||
|
<< " <!-- 背景设置 -->\n"
|
||||||
|
<< " <Background>\n"
|
||||||
|
<< " <Color>#00ffffff</Color> <!-- ARGB格式,00表示完全透明 -->\n"
|
||||||
|
<< " </Background>\n"
|
||||||
|
<< "\n"
|
||||||
|
<< " <!-- 时间格式 -->\n"
|
||||||
|
<< " <Time>\n"
|
||||||
|
<< " <Format>HH:mm</Format> <!-- 可选: HH:mm:ss, h:mm AP 等 -->\n"
|
||||||
|
<< " </Time>\n"
|
||||||
|
<< "\n"
|
||||||
|
<< " <!-- 阴影效果 -->\n"
|
||||||
|
<< " <Shadow>\n"
|
||||||
|
<< " <BlurRadius>20</BlurRadius>\n"
|
||||||
|
<< " <OffsetX>2</OffsetX>\n"
|
||||||
|
<< " <OffsetY>2</OffsetY>\n"
|
||||||
|
<< " <Color>#64000000</Color> <!-- 半透明黑色阴影 -->\n"
|
||||||
|
<< " </Shadow>\n"
|
||||||
|
<< "</ClockConfig>\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<QColor>();
|
||||||
|
}
|
||||||
|
if (settings.contains("bgColor"))
|
||||||
|
{
|
||||||
|
bgColor = settings.value("bgColor").value<QColor>();
|
||||||
|
}
|
||||||
|
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);
|
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();
|
return app.exec();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1 +0,0 @@
|
|||||||
pyside6
|
|
||||||
Reference in New Issue
Block a user