diff --git a/example/AboutPage.qml b/example/AboutPage.qml index 4f14f20..28c453c 100644 --- a/example/AboutPage.qml +++ b/example/AboutPage.qml @@ -6,6 +6,8 @@ FluWindow { width: 500 height: 600 + minimumWidth: 300 + minimumHeight: 400 title:"关于" FluAppBar{ diff --git a/example/App.qml b/example/App.qml index 4ac129c..15a236d 100644 --- a/example/App.qml +++ b/example/App.qml @@ -9,11 +9,9 @@ Window { id:app color: "#00000000" Component.onCompleted: { - - FluApp.setContextProperty("installHelper",installHelper) - + FluApp.init(app,properties) + console.debug(properties.installHelper.applicationFilePath()) FluApp.isDark = false - FluApp.setAppWindow(app) FluApp.routes = { "/":"qrc:/MainPage.qml", "/Setting":"qrc:/SettingPage.qml", @@ -24,7 +22,11 @@ Window { if(installHelper.isNavigateUninstall()){ FluApp.initialRoute = "/Uninstall" }else{ - FluApp.initialRoute = "/Installer" + if(installHelper.isNavigateInstall()){ + FluApp.initialRoute = "/Installer" + }else{ + FluApp.initialRoute = "/" + } } FluApp.run() } diff --git a/example/InstallHelper.cpp b/example/InstallHelper.cpp index ef83a0c..7710b03 100644 --- a/example/InstallHelper.cpp +++ b/example/InstallHelper.cpp @@ -11,10 +11,22 @@ #pragma comment(lib, "User32.lib") #pragma comment(lib, "Ole32.lib") +extern Q_CORE_EXPORT int qt_ntfs_permission_lookup; using CopyProgressCallback = std::function; +QString linkName = "FluentUI.lnk"; +QString uninstallLinkName = "Uninstall FluentUI.lnk"; +QString fileName = "FluentUI"; + +InstallHelper* InstallHelper::m_instance = nullptr; + +static QString getInstallConfigPath(){ + return QStandardPaths::writableLocation(QStandardPaths::ConfigLocation)+"/install"; +} + + static void copyDir(const QString& srcPath, const QString& dstPath, CopyProgressCallback callback) { QDir srcDir(srcPath); @@ -44,50 +56,76 @@ static void copyDir(const QString& srcPath, const QString& dstPath, CopyProgress } } -static void createHome(const QString& exePath,const QString& linkName){ - //创建桌面快捷方式 - QFile::link(exePath, QStandardPaths::writableLocation(QStandardPaths::DesktopLocation).append("/").append(linkName)); -} - -static void createUninstallLink(QString exePath, QString path, QString uninstallLinkName){ -#ifdef Q_OS_WIN - QString dst = path.append("\\").append(uninstallLinkName); - IShellLink *pShellLink; - QString args = "--uninstall"; - HRESULT hres = CoCreateInstance(CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER, - IID_IShellLink, (LPVOID *)&pShellLink); - if (SUCCEEDED(hres)) - { - // 设置快捷方式的目标路径和参数 - pShellLink->SetPath(exePath.toStdWString().c_str()); - pShellLink->SetArguments(args.toStdWString().c_str()); - - // 设置快捷方式的描述 - pShellLink->SetDescription(L"Fluent Uninstall"); - - // 获取IPersistFile接口 - IPersistFile *pPersistFile; - hres = pShellLink->QueryInterface(IID_IPersistFile, (LPVOID *)&pPersistFile); - - if (SUCCEEDED(hres)) - { - // 保存快捷方式到文件 - hres = pPersistFile->Save(dst.toStdWString().c_str(), TRUE); - pPersistFile->Release(); - } - pShellLink->Release(); +static QString generateBatFile() +{ + QDir pathDir(getInstallConfigPath()); + if(!pathDir.exists()){ + pathDir.mkdir(getInstallConfigPath()); } - CoUninitialize(); - - // std::string dst = path.append("\\").append(uninstallLinkName).toStdString(); - - // QFile::link(exePath,QString::fromStdString(dst + " --uninstall")); -#endif + QString filePath = getInstallConfigPath()+"/uninstall.bat"; + QFile batFile(filePath); + if (!batFile.open(QIODevice::WriteOnly | QIODevice::Text)) { + qWarning() << "Failed to create bat file: " << batFile.errorString(); + return ""; + } + QTextStream out(&batFile); + out << "@echo off\n"; + out << "set PID=%1" << "\n"; + out << "tasklist /FI \"PID eq %PID%\" | find /i \"%PID%\"\n"; + out << "if \"%ERRORLEVEL%\"==\"0\" (\n"; + out << " taskkill /pid %PID%\n"; + out << " timeout /t 2 /nobreak >nul\n"; + out << " echo The process with PID %PID% has been terminated.\n"; + out << ") else (\n"; + out << " echo The process with PID %PID% does not exist.\n"; + out << ")\n"; + out << "rd /s /q %2" <<"\n"; + batFile.close(); + return filePath; } -static void createStartMenu(const QString& exePath,const QString& fileName,const QString& linkName){ - //创建开始菜单快捷方式 - QString startMenuPath=QStandardPaths::writableLocation(QStandardPaths::ApplicationsLocation).append("/").append(fileName); +static bool registerUninstallProgram(const QString& displayName, const QString& installPath, const QString& version) +{ + const QString instalIniPath = getInstallConfigPath()+"/install.ini"; + QSettings settings(instalIniPath,QSettings::IniFormat); + settings.setValue("DisplayName", displayName); + settings.setValue("InstallLocation", installPath); + settings.setValue("DisplayVersion", version); + QString uninstallCommand = QString("\"%1\" --uninstall").arg(QCoreApplication::applicationFilePath()); + settings.setValue("UninstallString", uninstallCommand); + settings.sync(); + return true; +} + +static bool unRegisterUninstallProgram(){ + const QString instalIniPath = getInstallConfigPath()+"/install.ini"; + QFile instalIniFile(instalIniPath); + if(instalIniFile.exists()){ + instalIniFile.remove(); + } + return true; +} + +static void createHome(const QString& exePath){ + //创建桌面快捷方式 + QFile::link(exePath,QStandardPaths::writableLocation(QStandardPaths::DesktopLocation).append("/").append(linkName)); +} + +static void removeLink(){ + QString linkPath = QStandardPaths::writableLocation(QStandardPaths::DesktopLocation).append("/").append(linkName); + QFile linkHome(linkPath); + if(linkHome.exists()){ + linkHome.remove(); + } + linkPath = QStandardPaths::writableLocation(QStandardPaths::ApplicationsLocation).append("/").append(fileName); + QFile linkStartMenu(linkPath); + if(linkStartMenu.exists()){ + linkStartMenu.remove(); + } +} + +static void createStartMenu(const QString& exePath){ + QString startMenuPath = QStandardPaths::writableLocation(QStandardPaths::ApplicationsLocation).append("/").append(fileName); QDir dir(startMenuPath); if(!dir.exists()) { @@ -100,39 +138,101 @@ static void createStartMenu(const QString& exePath,const QString& fileName,const } + +static void createUninstallLink(QString exePath, QString path){ +#ifdef Q_OS_WIN + QString dst = path.append("\\").append(uninstallLinkName); + IShellLink *pShellLink; + QString args = "--uninstall"; + HRESULT hres = CoCreateInstance(CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER,IID_IShellLink, (LPVOID *)&pShellLink); + if (SUCCEEDED(hres)) + { + pShellLink->SetPath(exePath.toStdWString().c_str()); + pShellLink->SetArguments(args.toStdWString().c_str()); + pShellLink->SetDescription(L"Fluent Uninstall"); + IPersistFile *pPersistFile; + hres = pShellLink->QueryInterface(IID_IPersistFile, (LPVOID *)&pPersistFile); + if (SUCCEEDED(hres)) + { + hres = pPersistFile->Save(dst.toStdWString().c_str(), TRUE); + pPersistFile->Release(); + } + pShellLink->Release(); + } + CoUninitialize(); +#endif +} + +InstallHelper *InstallHelper::getInstance() +{ + if(InstallHelper::m_instance == nullptr){ + InstallHelper::m_instance = new InstallHelper; + } + return InstallHelper::m_instance; +} + InstallHelper::InstallHelper(QObject *parent) : QObject{parent} { installing(false); + uninstallSuccess(false); + errorInfo(""); +} + +bool InstallHelper::isNavigateInstall(){ + const QString instalIniPath = getInstallConfigPath()+"/install.ini"; + QFile installIniFle(instalIniPath); + if(installIniFle.exists()){ + return false; + } + return true; } void InstallHelper::install(const QString& path,bool isHome,bool isStartMenu){ + qt_ntfs_permission_lookup ++; + QFileInfo folder(path.chopped(8)); + bool isWritable = folder.isWritable(); + qt_ntfs_permission_lookup --; + qDebug()< future = QtConcurrent::run(copyDir,QCoreApplication::applicationDirPath(),path,[=](int currentFile, int totalFiles){ if(currentFile==totalFiles){ - QString exePath = path+"\\"+"example.exe"; - QString fileName = "FluentUI"; - QString linkName = "FluentUI.lnk"; - QString uninstallLinkName = "Uninstall FluentUI.lnk"; if(isHome){ - createHome(exePath,linkName); + createHome(exePath); } if(isStartMenu){ - createStartMenu(exePath,fileName,linkName); + createStartMenu(exePath); } - createUninstallLink(exePath,path,uninstallLinkName); + createUninstallLink(exePath,path); + registerUninstallProgram("FluentUI",path,"1.0.0.0"); } }); future.waitForFinished(); - qDebug()< #include #include +#include +#include #include "InstallHelper.h" +QMap properties(){ + QMap map; + map["installHelper"] = QVariant::fromValue(QVariant::fromValue(InstallHelper::getInstance())); + return map; +} + int main(int argc, char *argv[]) { QCoreApplication::setOrganizationName("ZhuZiChu"); @@ -11,8 +19,14 @@ int main(int argc, char *argv[]) QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling); QGuiApplication app(argc, argv); QQmlApplicationEngine engine; - qDebug()<<"setContextProperty------->1"; - engine.rootContext()->setContextProperty("installHelper",new InstallHelper()); + QMapIterator iterator(properties()); + while (iterator.hasNext()) { + iterator.next(); + QString key = iterator.key(); + QVariant value = iterator.value(); + engine.rootContext()->setContextProperty(key,value); + } + engine.rootContext()->setContextProperty("properties",properties()); const QUrl url(QStringLiteral("qrc:/App.qml")); QObject::connect(&engine, &QQmlApplicationEngine::objectCreated, &app, [url](QObject *obj, const QUrl &objUrl) { diff --git a/example/stdafx.h b/example/stdafx.h index 8919941..375822e 100644 --- a/example/stdafx.h +++ b/example/stdafx.h @@ -1,4 +1,8 @@ -#ifndef STDAFX_H +#if defined(_MSC_VER) && (_MSC_VER >= 1600) +#pragma execution_character_set("utf-8") +#endif + +#ifndef STDAFX_H #define STDAFX_H #define Q_PROPERTY_AUTO(TYPE, M) \ diff --git a/src/FluApp.cpp b/src/FluApp.cpp index 0bb4450..bdaf2cd 100644 --- a/src/FluApp.cpp +++ b/src/FluApp.cpp @@ -25,8 +25,9 @@ FluApp::FluApp(QObject *parent) isDark(false); } -void FluApp::setAppWindow(QWindow *window){ - appWindow = window; +void FluApp::init(QWindow *window,QMap properties){ + this->appWindow = window; + this->properties = properties; } void FluApp::run(){ @@ -40,6 +41,14 @@ void FluApp::navigate(const QString& route){ } bool isAppWindow = route == initialRoute(); FramelessView *view = new FramelessView(); + + QMapIterator iterator(properties); + while (iterator.hasNext()) { + iterator.next(); + QString key = iterator.key(); + QVariant value = iterator.value(); + view->engine()->rootContext()->setContextProperty(key,value); + } view->setColor(QColor(Qt::transparent)); QObject::connect(view, &QQuickView::statusChanged, view, [&](QQuickView::Status status) { if (status == QQuickView::Status::Ready) { diff --git a/src/FluApp.h b/src/FluApp.h index 08009e4..5939904 100644 --- a/src/FluApp.h +++ b/src/FluApp.h @@ -27,7 +27,7 @@ public: Q_INVOKABLE void navigate(const QString& route); - Q_INVOKABLE void setAppWindow(QWindow *window); + Q_INVOKABLE void init(QWindow *window,QMap properties); Q_SIGNAL void windowReady(FramelessView *view); @@ -37,20 +37,10 @@ public: Q_INVOKABLE void clipText(const QString& text); - Q_INVOKABLE void setContextProperty(const QString &name, QObject *data){ - if(engine){ - engine->rootContext()->setContextProperty(name,data); - } - } - - void setEngine(QQmlEngine *engine){ - this->engine = engine; - } - private: static FluApp* m_instance; - QQmlEngine *engine; + QMap properties; QWindow *appWindow; }; diff --git a/src/Fluent.cpp b/src/Fluent.cpp index ccb7bc6..f3473cf 100644 --- a/src/Fluent.cpp +++ b/src/Fluent.cpp @@ -72,6 +72,5 @@ void Fluent::initializeEngine(QQmlEngine *engine, const char *uri) QGuiApplication::setFont(font); QFontDatabase::addApplicationFont(":/com.zhuzichu/res/font/fontawesome-webfont.ttf"); FluApp* app = FluApp::getInstance(); - app->setEngine(engine); engine->rootContext()->setContextProperty("FluApp",app); } diff --git a/src/Fluent.h b/src/Fluent.h index f330871..a245a15 100644 --- a/src/Fluent.h +++ b/src/Fluent.h @@ -8,13 +8,10 @@ class Fluent: public QObject { Q_OBJECT public: - static Fluent *getInstance(); - Q_INVOKABLE QString version() const; - void registerTypes(const char *uri); - void initializeEngine(QQmlEngine *engine, const char *uri); + static Fluent *getInstance(); private: static Fluent* m_instance; }; diff --git a/src/controls/FluButton.qml b/src/controls/FluButton.qml index 2c42f3c..f3c6c5f 100644 --- a/src/controls/FluButton.qml +++ b/src/controls/FluButton.qml @@ -13,6 +13,7 @@ Rectangle { property color primaryColor : "#0064B0" signal clicked radius: 4 + color:{ if(FluApp.isDark){ if(disabled){ diff --git a/src/controls/FluWindowResize.qml b/src/controls/FluWindowResize.qml index 3d07f29..aa6067e 100644 --- a/src/controls/FluWindowResize.qml +++ b/src/controls/FluWindowResize.qml @@ -20,11 +20,6 @@ MouseArea { propagateComposedEvents: true z: -65535 - onReleased: { - Window.window.width = Window.window.width+1 - Window.window.width = Window.window.width-1 - } - onPressed : (mouse)=> { if (fixedSize) {