adapt linux.

This commit is contained in:
amass 2024-09-05 22:05:05 +08:00
parent 7b40c42407
commit 578a764ec0
9 changed files with 1552 additions and 1189 deletions

View File

@ -2,8 +2,33 @@ cmake_minimum_required(VERSION 3.15)
project(Kylin)
option(INDEPENDENT_BUILD "build self." OFF)
option(UNIT_TEST "do unit test" OFF)
if(INDEPENDENT_BUILD)
set(KYLIN_WITH_FLUENT ON)
if(WIN32)
set(Projects_ROOT E:/Projects)
set(Libraries_ROOT ${Projects_ROOT}/Libraries)
set(BOOST_ROOT ${Libraries_ROOT}/boost_1_86_0_msvc2022_64bit)
set(Boost_INCLUDE_DIR ${BOOST_ROOT}/include/boost-1_86)
add_compile_definitions(
BOOST_USE_WINAPI_VERSION=BOOST_WINAPI_VERSION_WIN10
)
else()
execute_process(
COMMAND sh -c "echo $HOME"
OUTPUT_VARIABLE USER_HOME
OUTPUT_STRIP_TRAILING_WHITESPACE
)
set(Projects_ROOT ${USER_HOME}/Projects)
set(Libraries_ROOT /opt/Libraries)
set(BOOST_ROOT ${Libraries_ROOT}/boost_1_86_0)
set(Boost_INCLUDE_DIR ${BOOST_ROOT}/include)
endif()
add_subdirectory(Examples)
endif()
find_package(Boost REQUIRED COMPONENTS log serialization)
set(OpenSSL_LIBRARY ssl crypto)

View File

@ -1,11 +1,26 @@
import QtQuick
import Fluent as Fluent
Fluent.Window {
Fluent.ApplicationWindow {
width: 640
height: 480
visible: true
title: qsTr("FluentWindow")
appBar {
height: 30
showDark: true
darkClickListener:(button)=>handleDarkChanged(button)
closeClickListener: ()=>{dialog_close.open()}
z:7
}
Fluent.Button {
text: "成功"
property int dd: 0
onClicked: {
showSuccess("This is a success message %1".arg(dd++),2000)
}
}
Fluent.Rectangle {
x:100
@ -15,4 +30,59 @@ Fluent.Window {
color:"red"
radius:[10,0,10,0]
}
Fluent.ContentDialog{
id: dialog_close
title: qsTr("Quit")
message: qsTr("Are you sure you want to exit the program?")
negativeText: qsTr("Minimize")
buttonFlags: Fluent.ContentDialogType.NegativeButton | Fluent.ContentDialogType.NeutralButton | Fluent.ContentDialogType.PositiveButton
onNegativeClicked: {
system_tray.showMessage(qsTr("Friendly Reminder"),qsTr("FluentUI is hidden from the tray, click on the tray to activate the window again"));
timer_window_hide_delay.restart()
}
positiveText: qsTr("Quit")
neutralText: qsTr("Cancel")
onPositiveClicked:{
Fluent.Router.exit(0)
}
}
function changeDark(){
if(Fluent.Theme.dark){
Fluent.Theme.darkMode = Fluent.ThemeType.Light
}else{
Fluent.Theme.darkMode = Fluent.ThemeType.Dark
}
}
function handleDarkChanged(button){
if(Fluent.Utilities.isMacos() || !Fluent.Theme.animationEnabled || !fitsAppBarWindows){
changeDark()
}else{
loader_reveal.sourceComponent = com_reveal
var target = window.containerItem()
var pos = button.mapToItem(target,0,0)
var mouseX = pos.x + button.width / 2
var mouseY = pos.y + button.height / 2
var radius = Math.max(distance(mouseX,mouseY,0,0),distance(mouseX,mouseY,target.width,0),distance(mouseX,mouseY,0,target.height),distance(mouseX,mouseY,target.width,target.height))
var reveal = loader_reveal.item
reveal.start(reveal.width*Screen.devicePixelRatio,reveal.height*Screen.devicePixelRatio,Qt.point(mouseX,mouseY),radius)
}
}
Fluent.FpsItem {
id:fps_item
}
Fluent.Text{
text: "fps %1".arg(fps_item.fps)
opacity: 0.3
anchors{
bottom: parent.bottom
right: parent.right
bottomMargin: 5
rightMargin: 5
}
}
}

View File

@ -1,4 +1,5 @@
#include "Colors.h"
#include <QJSEngine>
Colors *Colors::instance() {
static Colors *self = nullptr;

File diff suppressed because it is too large Load Diff

View File

@ -1,91 +1,180 @@
#ifndef FRAMELESS_H
#define FRAMELESS_H
#include "Utilities.h"
#include <QAbstractNativeEventFilter>
#include <QQuickItem>
class Frameless : public QQuickItem, QAbstractNativeEventFilter {
Q_OBJECT
QML_ELEMENT
Q_PROPERTY_AUTO(QString, effect)
Q_PROPERTY_READONLY_AUTO(bool, effective)
Q_PROPERTY_READONLY_AUTO(QStringList, availableEffects)
Q_PROPERTY(QQuickItem *appBar READ appBar WRITE setAppBar NOTIFY appBarChanged)
Q_PROPERTY(QQuickItem *maximizeButton READ maximizeButton WRITE setMaximizeButton NOTIFY maximizeButtonChanged)
Q_PROPERTY(QQuickItem *minimizedButton READ minimizedButton WRITE setMinimizedButton NOTIFY minimizedButtonChanged)
Q_PROPERTY(QQuickItem *closeButton READ closeButton WRITE setCloseButton NOTIFY closeButtonChanged)
Q_PROPERTY(bool fixSize READ fixSize WRITE setFixSize NOTIFY fixSizeChanged)
Q_PROPERTY(bool topmost READ topmost WRITE setTopmost NOTIFY topmostChanged)
Q_PROPERTY(bool disabled READ disabled WRITE setDisabled NOTIFY disabledChanged)
public:
Frameless(QQuickItem *parent = nullptr);
QQuickItem *appBar() const;
void setAppBar(QQuickItem *appBar);
QQuickItem *maximizeButton() const;
void setMaximizeButton(QQuickItem *button);
QQuickItem *minimizedButton() const;
void setMinimizedButton(QQuickItem *button);
QQuickItem *closeButton() const;
void setCloseButton(QQuickItem *button);
bool fixSize() const;
void setFixSize(bool fix);
bool topmost() const;
void setTopmost(bool topmost);
bool disabled() const;
void setDisabled(bool disabled);
Q_INVOKABLE void showMaximized();
Q_INVOKABLE void showMinimized();
Q_INVOKABLE void showNormal();
Q_INVOKABLE void setHitTestVisible(QQuickItem *item);
Q_INVOKABLE void onDestruction();
void componentComplete() final;
bool nativeEventFilter(const QByteArray &eventType, void *message, qintptr *result) final;
signals:
void appBarChanged();
void maximizeButtonChanged();
void minimizedButtonChanged();
void closeButtonChanged();
void fixSizeChanged();
void topmostChanged();
void disabledChanged();
protected:
bool isFullScreen();
bool isMaximized();
void setMaximizeHovered(bool val);
void setMaximizePressed(bool val);
void setWindowTopmost(bool topmost);
bool hitMaximizeButton();
bool hitAppBar();
void showSystemMenu(QPoint point);
bool eventFilter(QObject *obj, QEvent *event) final;
private:
quint64 m_current = 0;
QQuickItem *m_appBar = nullptr;
QQuickItem *m_maximizeButton = nullptr;
QQuickItem *m_minimizedButton = nullptr;
QQuickItem *m_closeButton = nullptr;
bool m_fixSize = false;
bool m_topmost = false;
bool m_disabled = false;
int m_margins = 8;
QList<QPointer<QQuickItem>> m_hitTestList;
bool m_isWindows11OrGreater = false;
QString m_currentEffect;
};
#endif // FRAMELESS_H
#ifndef __FRAMELESS_H__
#define __FRAMELESS_H__
#include "Utilities.h"
#include <QAbstractNativeEventFilter>
#include <QObject>
#include <QQmlProperty>
#include <QQuickItem>
#ifdef Q_OS_WIN
#pragma comment (lib, "user32.lib")
#pragma comment (lib, "dwmapi.lib")
#include <windows.h>
#include <windowsx.h>
#include <dwmapi.h>
enum _DWM_SYSTEMBACKDROP_TYPE {
_DWMSBT_AUTO, // [Default] Let DWM automatically decide the system-drawn backdrop for this
// window.
_DWMSBT_NONE, // [Disable] Do not draw any system backdrop.
_DWMSBT_MAINWINDOW, // [Mica] Draw the backdrop material effect corresponding to a
// long-lived window.
_DWMSBT_TRANSIENTWINDOW, // [Acrylic] Draw the backdrop material effect corresponding to a
// transient window.
_DWMSBT_TABBEDWINDOW, // [Mica Alt] Draw the backdrop material effect corresponding to a
// window with a tabbed title bar.
};
enum WINDOWCOMPOSITIONATTRIB {
WCA_UNDEFINED = 0,
WCA_NCRENDERING_ENABLED = 1,
WCA_NCRENDERING_POLICY = 2,
WCA_TRANSITIONS_FORCEDISABLED = 3,
WCA_ALLOW_NCPAINT = 4,
WCA_CAPTION_BUTTON_BOUNDS = 5,
WCA_NONCLIENT_RTL_LAYOUT = 6,
WCA_FORCE_ICONIC_REPRESENTATION = 7,
WCA_EXTENDED_FRAME_BOUNDS = 8,
WCA_HAS_ICONIC_BITMAP = 9,
WCA_THEME_ATTRIBUTES = 10,
WCA_NCRENDERING_EXILED = 11,
WCA_NCADORNMENTINFO = 12,
WCA_EXCLUDED_FROM_LIVEPREVIEW = 13,
WCA_VIDEO_OVERLAY_ACTIVE = 14,
WCA_FORCE_ACTIVEWINDOW_APPEARANCE = 15,
WCA_DISALLOW_PEEK = 16,
WCA_CLOAK = 17,
WCA_CLOAKED = 18,
WCA_ACCENT_POLICY = 19,
WCA_FREEZE_REPRESENTATION = 20,
WCA_EVER_UNCLOAKED = 21,
WCA_VISUAL_OWNER = 22,
WCA_HOLOGRAPHIC = 23,
WCA_EXCLUDED_FROM_DDA = 24,
WCA_PASSIVEUPDATEMODE = 25,
WCA_USEDARKMODECOLORS = 26,
WCA_CORNER_STYLE = 27,
WCA_PART_COLOR = 28,
WCA_DISABLE_MOVESIZE_FEEDBACK = 29,
WCA_LAST = 30
};
enum ACCENT_STATE {
ACCENT_DISABLED = 0,
ACCENT_ENABLE_GRADIENT = 1,
ACCENT_ENABLE_TRANSPARENTGRADIENT = 2,
ACCENT_ENABLE_BLURBEHIND = 3, // Traditional DWM blur
ACCENT_ENABLE_ACRYLICBLURBEHIND = 4, // RS4 1803
ACCENT_ENABLE_HOST_BACKDROP = 5, // RS5 1809
ACCENT_INVALID_STATE = 6 // Using this value will remove the window background
};
enum ACCENT_FLAG {
ACCENT_NONE = 0,
ACCENT_ENABLE_ACRYLIC = 1,
ACCENT_ENABLE_ACRYLIC_WITH_LUMINOSITY = 482
};
struct ACCENT_POLICY {
DWORD dwAccentState;
DWORD dwAccentFlags;
DWORD dwGradientColor; // #AABBGGRR
DWORD dwAnimationId;
};
using PACCENT_POLICY = ACCENT_POLICY *;
struct WINDOWCOMPOSITIONATTRIBDATA {
WINDOWCOMPOSITIONATTRIB Attrib;
PVOID pvData;
SIZE_T cbData;
};
using PWINDOWCOMPOSITIONATTRIBDATA = WINDOWCOMPOSITIONATTRIBDATA *;
typedef HRESULT (WINAPI *DwmSetWindowAttributeFunc)(HWND hwnd, DWORD dwAttribute, LPCVOID pvAttribute, DWORD cbAttribute);
typedef HRESULT (WINAPI *DwmExtendFrameIntoClientAreaFunc)(HWND hwnd, const MARGINS *pMarInset);
typedef HRESULT (WINAPI *DwmIsCompositionEnabledFunc)(BOOL *pfEnabled);
typedef HRESULT (WINAPI *DwmEnableBlurBehindWindowFunc)(HWND hWnd, const DWM_BLURBEHIND *pBlurBehind);
typedef BOOL (WINAPI *SetWindowCompositionAttributeFunc)(HWND hwnd, const WINDOWCOMPOSITIONATTRIBDATA *);
#endif
#if (QT_VERSION >= QT_VERSION_CHECK(6, 0, 0))
using QT_NATIVE_EVENT_RESULT_TYPE = qintptr;
using QT_ENTER_EVENT_TYPE = QEnterEvent;
#else
using QT_NATIVE_EVENT_RESULT_TYPE = long;
using QT_ENTER_EVENT_TYPE = QEvent;
#endif
class Frameless : public QQuickItem, QAbstractNativeEventFilter {
Q_OBJECT
QML_ELEMENT
Q_PROPERTY_AUTO_P(QQuickItem *, appBar)
Q_PROPERTY_AUTO_P(QQuickItem *, maximizeButton)
Q_PROPERTY_AUTO_P(QQuickItem *, minimizedButton)
Q_PROPERTY_AUTO_P(QQuickItem *, closeButton)
Q_PROPERTY_AUTO(bool, topmost)
Q_PROPERTY_AUTO(bool, disabled)
Q_PROPERTY_AUTO(bool, fixSize)
Q_PROPERTY_AUTO(QString, effect)
Q_PROPERTY_READONLY_AUTO(bool, effective)
Q_PROPERTY_READONLY_AUTO(QStringList, availableEffects)
Q_PROPERTY_AUTO(bool, isDarkMode)
Q_PROPERTY_AUTO(bool, useSystemEffect)
public:
explicit Frameless(QQuickItem *parent = nullptr);
~Frameless() override;
void componentComplete() override;
[[maybe_unused]] bool nativeEventFilter(const QByteArray &eventType, void *message,
QT_NATIVE_EVENT_RESULT_TYPE *result) override;
[[maybe_unused]] Q_INVOKABLE void showFullScreen();
Q_INVOKABLE void showMaximized();
[[maybe_unused]] Q_INVOKABLE void showMinimized();
Q_INVOKABLE void showNormal();
Q_INVOKABLE void setHitTestVisible(QQuickItem *);
[[maybe_unused]] Q_INVOKABLE void onDestruction();
protected:
bool eventFilter(QObject *obj, QEvent *event) override;
private:
bool _isFullScreen();
bool _isMaximized();
void _updateCursor(int edges);
void _setWindowTopmost(bool topmost);
void _showSystemMenu(QPoint point);
bool _hitAppBar();
bool _hitMaximizeButton();
void _setMaximizePressed(bool val);
void _setMaximizeHovered(bool val);
private:
quint64 m_current = 0;
int m_edges = 0;
int m_margins = 8;
quint64 m_clickTimer = 0;
bool m_isWindows11OrGreater = false;
QList<QPointer<QQuickItem>> m_hitTestList;
QString m_currentEffect;
};
#endif // __FRAMELESS_H__

View File

@ -1,7 +1,9 @@
add_library(QHotkey
qhotkey.h qhotkey.cpp
qhotkey_p.h qhotkey_win.cpp
qhotkey_p.h
$<$<PLATFORM_ID:Windows>:qhotkey_win.cpp>
$<$<PLATFORM_ID:Linux>:qhotkey_x11.cpp>
)
target_include_directories(QHotkey
@ -10,4 +12,5 @@ target_include_directories(QHotkey
target_link_libraries(QHotkey
PUBLIC Qt${QT_VERSION_MAJOR}::Gui
$<$<PLATFORM_ID:Linux>:X11>
)

View File

@ -1,133 +1,335 @@
#include "Utilities.h"
#include <QSettings>
#include <qt_windows.h>
Utilities *Utilities::instance() {
static Utilities *self = nullptr;
if (self == nullptr) {
self = new Utilities();
}
return self;
}
Utilities *Utilities::create(QQmlEngine *, QJSEngine *) {
auto ret = instance();
QJSEngine::setObjectOwnership(ret, QJSEngine::CppOwnership);
return ret;
}
Utilities::Utilities(QObject *parent) : QObject{parent} {
}
bool Utilities::isSoftware() {
return QQuickWindow::sceneGraphBackend() == "software";
}
void Utilities::deleteLater(QObject *p) {
if (p) {
p->deleteLater();
}
}
QColor Utilities::withOpacity(const QColor &color, qreal opacity) {
int alpha = qRound(opacity * 255) & 0xff;
return QColor::fromRgba((alpha << 24) | (color.rgba() & 0xffffff));
}
QRect Utilities::desktopAvailableGeometry(QQuickWindow *window) {
return window->screen()->availableGeometry();
}
QString Utilities::getWallpaperFilePath() {
#if defined(Q_OS_WIN)
wchar_t path[MAX_PATH] = {};
if (::SystemParametersInfoW(SPI_GETDESKWALLPAPER, MAX_PATH, path, FALSE) == FALSE) {
return {};
}
return QString::fromWCharArray(path);
#elif defined(Q_OS_LINUX)
auto type = QSysInfo::productType();
if (type == "uos") {
QProcess process;
QStringList args;
args << "--session";
args << "--type=method_call";
args << "--print-reply";
args << "--dest=com.deepin.wm";
args << "/com/deepin/wm";
args << "com.deepin.wm.GetCurrentWorkspaceBackgroundForMonitor";
args << QString("string:'%1'").arg(currentTimestamp());
process.start("dbus-send", args);
process.waitForFinished();
QByteArray result = process.readAllStandardOutput().trimmed();
int startIndex = result.indexOf("file:///");
if (startIndex != -1) {
auto path = result.mid(startIndex + 7, result.length() - startIndex - 8);
return path;
}
}
#elif defined(Q_OS_MACOS)
QProcess process;
QStringList args;
args << "-e";
args << R"(tell application "Finder" to get POSIX path of (desktop picture as alias))";
process.start("osascript", args);
process.waitForFinished();
QByteArray result = process.readAllStandardOutput().trimmed();
if (result.isEmpty()) {
return "/System/Library/CoreServices/DefaultDesktop.heic";
}
return result;
#else
return {};
#endif
}
QUrl Utilities::getUrlByFilePath(const QString &path) {
return QUrl::fromLocalFile(path);
}
bool Utilities::isMacos() {
#if defined(Q_OS_MACOS)
return true;
#else
return false;
#endif
}
bool Utilities::isWin() {
#if defined(Q_OS_WIN)
return true;
#else
return false;
#endif
}
int Utilities::windowBuildNumber() {
#if defined(Q_OS_WIN)
QSettings regKey{QString::fromUtf8(R"(HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion)"),
QSettings::NativeFormat};
if (regKey.contains(QString::fromUtf8("CurrentBuildNumber"))) {
auto buildNumber = regKey.value(QString::fromUtf8("CurrentBuildNumber")).toInt();
return buildNumber;
}
#endif
return -1;
}
bool Utilities::isWindows11OrGreater() {
static QVariant var;
if (var.isNull()) {
#if defined(Q_OS_WIN)
auto buildNumber = windowBuildNumber();
if (buildNumber >= 22000) {
var = QVariant::fromValue(true);
return true;
}
#endif
var = QVariant::fromValue(false);
return false;
} else {
return var.toBool();
}
}
#include "Utilities.h"
#include <QClipboard>
#include <QColor>
#include <QCryptographicHash>
#include <QCursor>
#include <QDateTime>
#include <QDir>
#include <QFileInfo>
#include <QGuiApplication>
#include <QJSEngine>
#include <QOpenGLContext>
#include <QProcess>
#include <QQuickWindow>
#include <QScreen>
#include <QSettings>
#include <QTextDocument>
#include <QUuid>
#ifdef Q_OS_WIN
# pragma comment(lib, "user32.lib")
# include <windows.h>
# include <windowsx.h>
#endif
Utilities *Utilities::instance() {
static Utilities *self = nullptr;
if (self == nullptr) {
self = new Utilities();
}
return self;
}
Utilities *Utilities::create(QQmlEngine *, QJSEngine *) {
auto ret = instance();
QJSEngine::setObjectOwnership(ret, QJSEngine::CppOwnership);
return ret;
}
Utilities::Utilities(QObject *parent) : QObject{parent} {
}
void Utilities::clipText(const QString &text) {
QGuiApplication::clipboard()->setText(text);
}
QString Utilities::uuid() {
return QUuid::createUuid().toString().remove('-').remove('{').remove('}');
}
QString Utilities::readFile(const QString &fileName) {
QString content;
QFile file(fileName);
if (file.open(QIODevice::ReadOnly)) {
QTextStream stream(&file);
content = stream.readAll();
}
return content;
}
bool Utilities::isMacos() {
#if defined(Q_OS_MACOS)
return true;
#else
return false;
#endif
}
bool Utilities::isLinux() {
#if defined(Q_OS_LINUX)
return true;
#else
return false;
#endif
}
bool Utilities::isWin() {
#if defined(Q_OS_WIN)
return true;
#else
return false;
#endif
}
int Utilities::qtMajor() {
const QString qtVersion = QString::fromLatin1(qVersion());
const QStringList versionParts = qtVersion.split('.');
return versionParts[0].toInt();
}
int Utilities::qtMinor() {
const QString qtVersion = QString::fromLatin1(qVersion());
const QStringList versionParts = qtVersion.split('.');
return versionParts[1].toInt();
}
void Utilities::setQuitOnLastWindowClosed(bool val) {
QGuiApplication::setQuitOnLastWindowClosed(val);
}
void Utilities::setOverrideCursor(Qt::CursorShape shape) {
QGuiApplication::setOverrideCursor(QCursor(shape));
}
void Utilities::restoreOverrideCursor() {
QGuiApplication::restoreOverrideCursor();
}
void Utilities::deleteLater(QObject *p) {
if (p) {
p->deleteLater();
}
}
QString Utilities::toLocalPath(const QUrl &url) {
return url.toLocalFile();
}
QString Utilities::getFileNameByUrl(const QUrl &url) {
return QFileInfo(url.toLocalFile()).fileName();
}
QString Utilities::html2PlantText(const QString &html) {
QTextDocument textDocument;
textDocument.setHtml(html);
return textDocument.toPlainText();
}
QRect Utilities::getVirtualGeometry() {
return QGuiApplication::primaryScreen()->virtualGeometry();
}
QString Utilities::getApplicationDirPath() {
return QGuiApplication::applicationDirPath();
}
QUrl Utilities::getUrlByFilePath(const QString &path) {
return QUrl::fromLocalFile(path);
}
QColor Utilities::withOpacity(const QColor &color, qreal opacity) {
int alpha = qRound(opacity * 255) & 0xff;
return QColor::fromRgba((alpha << 24) | (color.rgba() & 0xffffff));
}
QString Utilities::md5(const QString &text) {
return QCryptographicHash::hash(text.toUtf8(), QCryptographicHash::Md5).toHex();
}
QString Utilities::toBase64(const QString &text) {
return text.toUtf8().toBase64();
}
QString Utilities::fromBase64(const QString &text) {
return QByteArray::fromBase64(text.toUtf8());
}
bool Utilities::removeDir(const QString &dirPath) {
QDir qDir(dirPath);
return qDir.removeRecursively();
}
bool Utilities::removeFile(const QString &filePath) {
QFile file(filePath);
return file.remove();
}
QString Utilities::sha256(const QString &text) {
return QCryptographicHash::hash(text.toUtf8(), QCryptographicHash::Sha256).toHex();
}
void Utilities::showFileInFolder(const QString &path) {
#if defined(Q_OS_WIN)
QProcess::startDetached("explorer.exe", {"/select,", QDir::toNativeSeparators(path)});
#endif
#if defined(Q_OS_LINUX)
QFileInfo fileInfo(path);
auto process = "xdg-open";
auto arguments = {fileInfo.absoluteDir().absolutePath()};
QProcess::startDetached(process, arguments);
#endif
#if defined(Q_OS_MACOS)
QProcess::execute("/usr/bin/osascript",
{"-e", "tell application \"Finder\" to reveal POSIX file \"" + path + "\""});
QProcess::execute("/usr/bin/osascript", {"-e", "tell application \"Finder\" to activate"});
#endif
}
bool Utilities::isSoftware() {
return QQuickWindow::sceneGraphBackend() == "software";
}
QPoint Utilities::cursorPos() {
return QCursor::pos();
}
qint64 Utilities::currentTimestamp() {
return QDateTime::currentMSecsSinceEpoch();
}
QIcon Utilities::windowIcon() {
return QGuiApplication::windowIcon();
}
int Utilities::cursorScreenIndex() {
int screenIndex = 0;
int screenCount = QGuiApplication::screens().count();
if (screenCount > 1) {
QPoint pos = QCursor::pos();
for (int i = 0; i <= screenCount - 1; ++i) {
if (QGuiApplication::screens().at(i)->geometry().contains(pos)) {
screenIndex = i;
break;
}
}
}
return screenIndex;
}
int Utilities::windowBuildNumber() {
#if defined(Q_OS_WIN)
QSettings regKey{
QString::fromUtf8(R"(HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion)"),
QSettings::NativeFormat};
if (regKey.contains(QString::fromUtf8("CurrentBuildNumber"))) {
auto buildNumber = regKey.value(QString::fromUtf8("CurrentBuildNumber")).toInt();
return buildNumber;
}
#endif
return -1;
}
bool Utilities::isWindows11OrGreater() {
static QVariant var;
if (var.isNull()) {
#if defined(Q_OS_WIN)
auto buildNumber = windowBuildNumber();
if (buildNumber >= 22000) {
var = QVariant::fromValue(true);
return true;
}
#endif
var = QVariant::fromValue(false);
return false;
} else {
return var.toBool();
}
}
bool Utilities::isWindows10OrGreater() {
static QVariant var;
if (var.isNull()) {
#if defined(Q_OS_WIN)
auto buildNumber = windowBuildNumber();
if (buildNumber >= 10240) {
var = QVariant::fromValue(true);
return true;
}
#endif
var = QVariant::fromValue(false);
return false;
} else {
return var.toBool();
}
}
QRect Utilities::desktopAvailableGeometry(QQuickWindow *window) {
return window->screen()->availableGeometry();
}
QString Utilities::getWallpaperFilePath() {
#if defined(Q_OS_WIN)
wchar_t path[MAX_PATH] = {};
if (::SystemParametersInfoW(SPI_GETDESKWALLPAPER, MAX_PATH, path, FALSE) == FALSE) {
return {};
}
return QString::fromWCharArray(path);
#elif defined(Q_OS_LINUX)
auto type = QSysInfo::productType();
if (type == "uos") {
QProcess process;
QStringList args;
args << "--session";
args << "--type=method_call";
args << "--print-reply";
args << "--dest=com.deepin.wm";
args << "/com/deepin/wm";
args << "com.deepin.wm.GetCurrentWorkspaceBackgroundForMonitor";
args << QString("string:'%1'").arg(currentTimestamp());
process.start("dbus-send", args);
process.waitForFinished();
QByteArray result = process.readAllStandardOutput().trimmed();
int startIndex = result.indexOf("file:///");
if (startIndex != -1) {
auto path = result.mid(startIndex + 7, result.length() - startIndex - 8);
return path;
}
}
#elif defined(Q_OS_MACOS)
QProcess process;
QStringList args;
args << "-e";
args << R"(tell application "Finder" to get POSIX path of (desktop picture as alias))";
process.start("osascript", args);
process.waitForFinished();
QByteArray result = process.readAllStandardOutput().trimmed();
if (result.isEmpty()) {
return "/System/Library/CoreServices/DefaultDesktop.heic";
}
return result;
#else
return {};
#endif
}
QColor Utilities::imageMainColor(const QImage &image, double bright) {
int step = 20;
int t = 0;
int r = 0, g = 0, b = 0;
for (int i = 0; i < image.width(); i += step) {
for (int j = 0; j < image.height(); j += step) {
if (image.valid(i, j)) {
t++;
QColor c = image.pixel(i, j);
r += c.red();
b += c.blue();
g += c.green();
}
}
}
return QColor(int(bright * r / t) > 255 ? 255 : int(bright * r / t),
int(bright * g / t) > 255 ? 255 : int(bright * g / t),
int(bright * b / t) > 255 ? 255 : int(bright * b / t));
}

View File

@ -1,108 +1,175 @@
#ifndef UTILITIES_H
#define UTILITIES_H
#include <QObject>
#include <QQmlEngine>
#include <QQuickWindow>
#define Q_PROPERTY_AUTO(TYPE, M) \
Q_PROPERTY(TYPE M MEMBER m_##M NOTIFY M##Changed) \
public: \
Q_SIGNAL void M##Changed(); \
void M(const TYPE &in_##M) { \
m_##M = in_##M; \
Q_EMIT M##Changed(); \
} \
TYPE M() { \
return m_##M; \
} \
\
private: \
TYPE m_##M;
#define Q_PROPERTY_READONLY_AUTO(TYPE, M) \
Q_PROPERTY(TYPE M READ M NOTIFY M##Changed FINAL) \
public: \
Q_SIGNAL void M##Changed(); \
void M(const TYPE &in_##M) { \
m_##M = in_##M; \
Q_EMIT M##Changed(); \
} \
TYPE M() { \
return m_##M; \
} \
\
private: \
TYPE m_##M;
#define Q_PROPERTY_AUTO_P(TYPE, M) \
Q_PROPERTY(TYPE M MEMBER m_##M NOTIFY M##Changed) \
public: \
Q_SIGNAL void M##Changed(); \
void M(TYPE in_##M) { \
m_##M = in_##M; \
Q_EMIT M##Changed(); \
} \
TYPE M() { \
return m_##M; \
} \
\
private: \
TYPE m_##M;
namespace WindowType {
Q_NAMESPACE
enum LaunchMode {
Standard = 0x0000,
SingleTask = 0x0001,
SingleInstance = 0x0002,
};
Q_ENUM_NS(LaunchMode)
QML_ELEMENT
} // namespace WindowType
namespace ThemeType {
Q_NAMESPACE
enum DarkMode {
System = 0x0000,
Light = 0x0001,
Dark = 0x0002,
};
Q_ENUM_NS(DarkMode)
QML_ELEMENT
} // namespace ThemeType
namespace ContentDialogType {
Q_NAMESPACE
enum ButtonFlag {
NeutralButton = 0x0001,
NegativeButton = 0x0002,
PositiveButton = 0x0004,
};
Q_ENUM_NS(ButtonFlag)
QML_ELEMENT
} // namespace ContentDialogType
class Utilities : public QObject {
Q_OBJECT
QML_ELEMENT
QML_SINGLETON
public:
static Utilities *instance();
static Utilities *create(QQmlEngine *, QJSEngine *);
Q_INVOKABLE int windowBuildNumber();
Q_INVOKABLE bool isWindows11OrGreater();
Q_INVOKABLE bool isWin();
Q_INVOKABLE bool isMacos();
Q_INVOKABLE QRect desktopAvailableGeometry(QQuickWindow *window);
Q_INVOKABLE QUrl getUrlByFilePath(const QString &path);
Q_INVOKABLE bool isSoftware();
Q_INVOKABLE void deleteLater(QObject *p);
Q_INVOKABLE QColor withOpacity(const QColor &, qreal alpha);
Q_INVOKABLE QString getWallpaperFilePath();
protected:
Utilities(QObject *parent = nullptr);
};
#endif // UTILITIES_H
#ifndef __UTILITIES_H__
#define __UTILITIES_H__
#include <QObject>
#include <QFile>
#include <QColor>
#include <QtQml/qqml.h>
#include <QQuickWindow>
#define Q_PROPERTY_AUTO(TYPE, M) \
Q_PROPERTY(TYPE M MEMBER m_##M NOTIFY M##Changed) \
public: \
Q_SIGNAL void M##Changed(); \
void M(const TYPE &in_##M) { \
m_##M = in_##M; \
Q_EMIT M##Changed(); \
} \
TYPE M() { \
return m_##M; \
} \
\
private: \
TYPE m_##M;
#define Q_PROPERTY_READONLY_AUTO(TYPE, M) \
Q_PROPERTY(TYPE M READ M NOTIFY M##Changed FINAL) \
public: \
Q_SIGNAL void M##Changed(); \
void M(const TYPE &in_##M) { \
m_##M = in_##M; \
Q_EMIT M##Changed(); \
} \
TYPE M() { \
return m_##M; \
} \
\
private: \
TYPE m_##M;
#define Q_PROPERTY_AUTO_P(TYPE, M) \
Q_PROPERTY(TYPE M MEMBER m_##M NOTIFY M##Changed) \
public: \
Q_SIGNAL void M##Changed(); \
void M(TYPE in_##M) { \
m_##M = in_##M; \
Q_EMIT M##Changed(); \
} \
TYPE M() { \
return m_##M; \
} \
\
private: \
TYPE m_##M;
namespace WindowType {
Q_NAMESPACE
enum LaunchMode {
Standard = 0x0000,
SingleTask = 0x0001,
SingleInstance = 0x0002,
};
Q_ENUM_NS(LaunchMode)
QML_ELEMENT
} // namespace WindowType
namespace ThemeType {
Q_NAMESPACE
enum DarkMode {
System = 0x0000,
Light = 0x0001,
Dark = 0x0002,
};
Q_ENUM_NS(DarkMode)
QML_ELEMENT
} // namespace ThemeType
namespace ContentDialogType {
Q_NAMESPACE
enum ButtonFlag {
NeutralButton = 0x0001,
NegativeButton = 0x0002,
PositiveButton = 0x0004,
};
Q_ENUM_NS(ButtonFlag)
QML_ELEMENT
} // namespace ContentDialogType
class Utilities : public QObject {
Q_OBJECT
QML_ELEMENT
QML_SINGLETON
private:
explicit Utilities(QObject *parent = nullptr);
public:
static Utilities *instance();
static Utilities *create(QQmlEngine *, QJSEngine *);
Q_INVOKABLE int qtMajor();
Q_INVOKABLE int qtMinor();
Q_INVOKABLE bool isMacos();
Q_INVOKABLE bool isLinux();
Q_INVOKABLE bool isWin();
Q_INVOKABLE void clipText(const QString &text);
Q_INVOKABLE QString uuid();
Q_INVOKABLE QString readFile(const QString &fileName);
Q_INVOKABLE void setQuitOnLastWindowClosed(bool val);
Q_INVOKABLE void setOverrideCursor(Qt::CursorShape shape);
Q_INVOKABLE void restoreOverrideCursor();
Q_INVOKABLE QString html2PlantText(const QString &html);
Q_INVOKABLE QString toLocalPath(const QUrl &url);
Q_INVOKABLE void deleteLater(QObject *p);
Q_INVOKABLE QString getFileNameByUrl(const QUrl &url);
Q_INVOKABLE QRect getVirtualGeometry();
Q_INVOKABLE QString getApplicationDirPath();
Q_INVOKABLE QUrl getUrlByFilePath(const QString &path);
Q_INVOKABLE QColor withOpacity(const QColor &, qreal alpha);
Q_INVOKABLE QString md5(const QString &text);
Q_INVOKABLE QString sha256(const QString &text);
Q_INVOKABLE QString toBase64(const QString &text);
Q_INVOKABLE QString fromBase64(const QString &text);
Q_INVOKABLE bool removeDir(const QString &dirPath);
Q_INVOKABLE bool removeFile(const QString &filePath);
Q_INVOKABLE void showFileInFolder(const QString &path);
Q_INVOKABLE bool isSoftware();
Q_INVOKABLE qint64 currentTimestamp();
Q_INVOKABLE QPoint cursorPos();
Q_INVOKABLE QIcon windowIcon();
Q_INVOKABLE int cursorScreenIndex();
Q_INVOKABLE int windowBuildNumber();
Q_INVOKABLE bool isWindows11OrGreater();
Q_INVOKABLE bool isWindows10OrGreater();
Q_INVOKABLE QRect desktopAvailableGeometry(QQuickWindow *window);
Q_INVOKABLE QString getWallpaperFilePath();
Q_INVOKABLE QColor imageMainColor(const QImage &image, double bright = 1);
};
#endif // __UTILITIES_H__

View File

@ -316,7 +316,7 @@ Quick.Window {
id:loader_border
anchors.fill: parent
sourceComponent: {
if(window.useSystemAppBar || Utilities.isWin() || window.visibility === Window.Maximized || window.visibility === Window.FullScreen){
if(window.useSystemAppBar || Utilities.isWin() || window.visibility === Quick.Window.Maximized || window.visibility === Quick.Window.FullScreen){
return undefined
}
return com_border