This commit is contained in:
朱子楚\zhuzi 2023-03-05 23:39:13 +08:00
parent 891270e6d1
commit b459b9dda6
16 changed files with 248 additions and 106 deletions

View File

@ -6,6 +6,8 @@ FluWindow {
width: 500 width: 500
height: 600 height: 600
minimumWidth: 300
minimumHeight: 400
title:"关于" title:"关于"
FluAppBar{ FluAppBar{

View File

@ -9,11 +9,9 @@ Window {
id:app id:app
color: "#00000000" color: "#00000000"
Component.onCompleted: { Component.onCompleted: {
FluApp.init(app,properties)
FluApp.setContextProperty("installHelper",installHelper) console.debug(properties.installHelper.applicationFilePath())
FluApp.isDark = false FluApp.isDark = false
FluApp.setAppWindow(app)
FluApp.routes = { FluApp.routes = {
"/":"qrc:/MainPage.qml", "/":"qrc:/MainPage.qml",
"/Setting":"qrc:/SettingPage.qml", "/Setting":"qrc:/SettingPage.qml",
@ -24,7 +22,11 @@ Window {
if(installHelper.isNavigateUninstall()){ if(installHelper.isNavigateUninstall()){
FluApp.initialRoute = "/Uninstall" FluApp.initialRoute = "/Uninstall"
}else{ }else{
if(installHelper.isNavigateInstall()){
FluApp.initialRoute = "/Installer" FluApp.initialRoute = "/Installer"
}else{
FluApp.initialRoute = "/"
}
} }
FluApp.run() FluApp.run()
} }

View File

@ -11,10 +11,22 @@
#pragma comment(lib, "User32.lib") #pragma comment(lib, "User32.lib")
#pragma comment(lib, "Ole32.lib") #pragma comment(lib, "Ole32.lib")
extern Q_CORE_EXPORT int qt_ntfs_permission_lookup;
using CopyProgressCallback = std::function<void(int currentFile, int totalFiles)>; using CopyProgressCallback = std::function<void(int currentFile, int totalFiles)>;
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) static void copyDir(const QString& srcPath, const QString& dstPath, CopyProgressCallback callback)
{ {
QDir srcDir(srcPath); QDir srcDir(srcPath);
@ -44,49 +56,75 @@ static void copyDir(const QString& srcPath, const QString& dstPath, CopyProgress
} }
} }
static void createHome(const QString& exePath,const QString& linkName){ static QString generateBatFile()
{
QDir pathDir(getInstallConfigPath());
if(!pathDir.exists()){
pathDir.mkdir(getInstallConfigPath());
}
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 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)); QFile::link(exePath,QStandardPaths::writableLocation(QStandardPaths::DesktopLocation).append("/").append(linkName));
} }
static void createUninstallLink(QString exePath, QString path, QString uninstallLinkName){ static void removeLink(){
#ifdef Q_OS_WIN QString linkPath = QStandardPaths::writableLocation(QStandardPaths::DesktopLocation).append("/").append(linkName);
QString dst = path.append("\\").append(uninstallLinkName); QFile linkHome(linkPath);
IShellLink *pShellLink; if(linkHome.exists()){
QString args = "--uninstall"; linkHome.remove();
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(); linkPath = QStandardPaths::writableLocation(QStandardPaths::ApplicationsLocation).append("/").append(fileName);
QFile linkStartMenu(linkPath);
if(linkStartMenu.exists()){
linkStartMenu.remove();
} }
CoUninitialize();
// std::string dst = path.append("\\").append(uninstallLinkName).toStdString();
// QFile::link(exePath,QString::fromStdString(dst + " --uninstall"));
#endif
} }
static void createStartMenu(const QString& exePath,const QString& fileName,const QString& linkName){ static void createStartMenu(const QString& exePath){
//创建开始菜单快捷方式
QString startMenuPath = QStandardPaths::writableLocation(QStandardPaths::ApplicationsLocation).append("/").append(fileName); QString startMenuPath = QStandardPaths::writableLocation(QStandardPaths::ApplicationsLocation).append("/").append(fileName);
QDir dir(startMenuPath); QDir dir(startMenuPath);
if(!dir.exists()) 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) InstallHelper::InstallHelper(QObject *parent)
: QObject{parent} : QObject{parent}
{ {
installing(false); 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){ void InstallHelper::install(const QString& path,bool isHome,bool isStartMenu){
QtConcurrent::run([=](){ qt_ntfs_permission_lookup ++;
QFileInfo folder(path.chopped(8));
bool isWritable = folder.isWritable();
qt_ntfs_permission_lookup --;
qDebug()<<folder.path();
if (!isWritable)
{
errorInfo(QString("无写入权限,请用管理员运行或者更新安装文件夹地址"));
return;
}
installing(true); installing(true);
QString exePath = path+"\\"+"example.exe";
QtConcurrent::run([=](){
QFuture<void> future = QtConcurrent::run(copyDir,QCoreApplication::applicationDirPath(),path,[=](int currentFile, int totalFiles){ QFuture<void> future = QtConcurrent::run(copyDir,QCoreApplication::applicationDirPath(),path,[=](int currentFile, int totalFiles){
if(currentFile==totalFiles){ if(currentFile==totalFiles){
QString exePath = path+"\\"+"example.exe";
QString fileName = "FluentUI";
QString linkName = "FluentUI.lnk";
QString uninstallLinkName = "Uninstall FluentUI.lnk";
if(isHome){ if(isHome){
createHome(exePath,linkName); createHome(exePath);
} }
if(isStartMenu){ if(isStartMenu){
createStartMenu(exePath,fileName,linkName); createStartMenu(exePath);
} }
createUninstallLink(exePath,path,uninstallLinkName); createUninstallLink(exePath,path);
registerUninstallProgram("FluentUI",path,"1.0.0.0");
} }
}); });
future.waitForFinished(); future.waitForFinished();
qDebug()<<QCoreApplication::applicationDirPath(); QStringList args;
qDebug()<<path; args<<"/c";
installing(false); args<<exePath;
QProcess::startDetached("cmd.exe",args,"C:/",nullptr);
QCoreApplication::exit();
}); });
} }
void InstallHelper::uninstall(){ void InstallHelper::uninstall(){
QString currentDir = QCoreApplication::applicationDirPath(); QString batFile = generateBatFile();
QDir dir(currentDir); qint64 pid = QCoreApplication::applicationPid();
dir.removeRecursively(); QString currentDir = QCoreApplication::applicationDirPath().replace("/","\\");
QStringList args;
args<<"/c";
args<<batFile;
args<<QString::number(pid);
args<<currentDir;
removeLink();
unRegisterUninstallProgram();
QProcess::startDetached("cmd.exe",args,"C:/",nullptr);
} }

View File

@ -13,6 +13,8 @@ class InstallHelper : public QObject
Q_OBJECT Q_OBJECT
Q_PROPERTY_AUTO(bool,installing) Q_PROPERTY_AUTO(bool,installing)
Q_PROPERTY_AUTO(bool,uninstallSuccess)
Q_PROPERTY_AUTO(QString,errorInfo)
public: public:
explicit InstallHelper(QObject *parent = nullptr); explicit InstallHelper(QObject *parent = nullptr);
@ -23,12 +25,20 @@ public:
} }
Q_INVOKABLE bool isNavigateUninstall(){ Q_INVOKABLE bool isNavigateUninstall(){
return true; return QGuiApplication::arguments().contains("--uninstall");
// return QGuiApplication::arguments().contains("--uninstall"); // return true;
}
Q_INVOKABLE bool isNavigateInstall();
Q_INVOKABLE QString pid(){
return QString::number(QCoreApplication::applicationPid());
} }
Q_INVOKABLE void uninstall(); Q_INVOKABLE void uninstall();
static InstallHelper *getInstance();
private:
static InstallHelper* m_instance;
}; };
#endif // INSTALLHELPER_H #endif // INSTALLHELPER_H

View File

@ -34,6 +34,14 @@ FluWindow {
installPath = String(fileDialog.fileUrls[0]).replace("file:///","").replace(RegExp("/",'g'),"\\") installPath = String(fileDialog.fileUrls[0]).replace("file:///","").replace(RegExp("/",'g'),"\\")
} }
} }
Connections{
target: installHelper
function onErrorInfoChanged(){
showError(installHelper.errorInfo)
}
}
} }
@ -68,8 +76,7 @@ FluWindow {
text:"更改路径" text:"更改路径"
Layout.rightMargin: 30 Layout.rightMargin: 30
onClicked: { onClicked: {
showInfo(installHelper.applicationFilePath()) fileDialog.open()
// fileDialog.open()
} }
} }
} }

View File

@ -109,6 +109,7 @@ FluWindow {
topMargin: 20 topMargin: 20
bottomMargin: 52 bottomMargin: 52
} }
boundsBehavior: Flickable.StopAtBounds
clip: true clip: true
width: 160 width: 160
model: nav_items model: nav_items
@ -116,6 +117,7 @@ FluWindow {
height: 38 height: 38
width: nav_list.width width: nav_list.width
Rectangle{ Rectangle{
color: { color: {
if(FluApp.isDark){ if(FluApp.isDark){
@ -147,7 +149,7 @@ FluWindow {
leftMargin: 6 leftMargin: 6
rightMargin: 6 rightMargin: 6
} }
}
MouseArea{ MouseArea{
id:item_mouse id:item_mouse
@ -165,6 +167,9 @@ FluWindow {
} }
} }
}
} }
Rectangle{ Rectangle{

View File

@ -30,9 +30,16 @@ FluWindow {
topMargin: 20 topMargin: 20
} }
Item{ Item{
width: 1 Layout.preferredWidth : parent.width
Layout.fillHeight: true Layout.fillHeight: true
FluText{
text:"青山不改,绿水长流,有缘再见"
anchors.centerIn: parent
fontStyle:FluText.TitleLarge
}
} }
Rectangle{ Rectangle{

View File

@ -1,5 +1,5 @@
QT += quick concurrent QT += quick concurrent
CONFIG += c++11 CONFIG += c++11 qtquickcompiler utf8_source
DEFINES += QT_DEPRECATED_WARNINGS QT_NO_WARNING_OUTPUT DEFINES += QT_DEPRECATED_WARNINGS QT_NO_WARNING_OUTPUT

View File

@ -1,8 +1,16 @@
#include <QGuiApplication> #include <QGuiApplication>
#include <QQmlApplicationEngine> #include <QQmlApplicationEngine>
#include <QQmlContext> #include <QQmlContext>
#include <QDir>
#include <QProcess>
#include "InstallHelper.h" #include "InstallHelper.h"
QMap<QString, QVariant> properties(){
QMap<QString, QVariant> map;
map["installHelper"] = QVariant::fromValue(QVariant::fromValue(InstallHelper::getInstance()));
return map;
}
int main(int argc, char *argv[]) int main(int argc, char *argv[])
{ {
QCoreApplication::setOrganizationName("ZhuZiChu"); QCoreApplication::setOrganizationName("ZhuZiChu");
@ -11,8 +19,14 @@ int main(int argc, char *argv[])
QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling); QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
QGuiApplication app(argc, argv); QGuiApplication app(argc, argv);
QQmlApplicationEngine engine; QQmlApplicationEngine engine;
qDebug()<<"setContextProperty------->1"; QMapIterator<QString, QVariant> iterator(properties());
engine.rootContext()->setContextProperty("installHelper",new InstallHelper()); 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")); const QUrl url(QStringLiteral("qrc:/App.qml"));
QObject::connect(&engine, &QQmlApplicationEngine::objectCreated, QObject::connect(&engine, &QQmlApplicationEngine::objectCreated,
&app, [url](QObject *obj, const QUrl &objUrl) { &app, [url](QObject *obj, const QUrl &objUrl) {

View File

@ -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 STDAFX_H
#define Q_PROPERTY_AUTO(TYPE, M) \ #define Q_PROPERTY_AUTO(TYPE, M) \

View File

@ -25,8 +25,9 @@ FluApp::FluApp(QObject *parent)
isDark(false); isDark(false);
} }
void FluApp::setAppWindow(QWindow *window){ void FluApp::init(QWindow *window,QMap<QString, QVariant> properties){
appWindow = window; this->appWindow = window;
this->properties = properties;
} }
void FluApp::run(){ void FluApp::run(){
@ -40,6 +41,14 @@ void FluApp::navigate(const QString& route){
} }
bool isAppWindow = route == initialRoute(); bool isAppWindow = route == initialRoute();
FramelessView *view = new FramelessView(); FramelessView *view = new FramelessView();
QMapIterator<QString, QVariant> 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)); view->setColor(QColor(Qt::transparent));
QObject::connect(view, &QQuickView::statusChanged, view, [&](QQuickView::Status status) { QObject::connect(view, &QQuickView::statusChanged, view, [&](QQuickView::Status status) {
if (status == QQuickView::Status::Ready) { if (status == QQuickView::Status::Ready) {

View File

@ -27,7 +27,7 @@ public:
Q_INVOKABLE void navigate(const QString& route); Q_INVOKABLE void navigate(const QString& route);
Q_INVOKABLE void setAppWindow(QWindow *window); Q_INVOKABLE void init(QWindow *window,QMap<QString, QVariant> properties);
Q_SIGNAL void windowReady(FramelessView *view); Q_SIGNAL void windowReady(FramelessView *view);
@ -37,20 +37,10 @@ public:
Q_INVOKABLE void clipText(const QString& text); 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: private:
static FluApp* m_instance; static FluApp* m_instance;
QQmlEngine *engine; QMap<QString, QVariant> properties;
QWindow *appWindow; QWindow *appWindow;
}; };

View File

@ -72,6 +72,5 @@ void Fluent::initializeEngine(QQmlEngine *engine, const char *uri)
QGuiApplication::setFont(font); QGuiApplication::setFont(font);
QFontDatabase::addApplicationFont(":/com.zhuzichu/res/font/fontawesome-webfont.ttf"); QFontDatabase::addApplicationFont(":/com.zhuzichu/res/font/fontawesome-webfont.ttf");
FluApp* app = FluApp::getInstance(); FluApp* app = FluApp::getInstance();
app->setEngine(engine);
engine->rootContext()->setContextProperty("FluApp",app); engine->rootContext()->setContextProperty("FluApp",app);
} }

View File

@ -8,13 +8,10 @@ class Fluent: public QObject
{ {
Q_OBJECT Q_OBJECT
public: public:
static Fluent *getInstance();
Q_INVOKABLE QString version() const; Q_INVOKABLE QString version() const;
void registerTypes(const char *uri); void registerTypes(const char *uri);
void initializeEngine(QQmlEngine *engine, const char *uri); void initializeEngine(QQmlEngine *engine, const char *uri);
static Fluent *getInstance();
private: private:
static Fluent* m_instance; static Fluent* m_instance;
}; };

View File

@ -13,6 +13,7 @@ Rectangle {
property color primaryColor : "#0064B0" property color primaryColor : "#0064B0"
signal clicked signal clicked
radius: 4 radius: 4
color:{ color:{
if(FluApp.isDark){ if(FluApp.isDark){
if(disabled){ if(disabled){

View File

@ -20,11 +20,6 @@ MouseArea {
propagateComposedEvents: true propagateComposedEvents: true
z: -65535 z: -65535
onReleased: {
Window.window.width = Window.window.width+1
Window.window.width = Window.window.width-1
}
onPressed : onPressed :
(mouse)=> { (mouse)=> {
if (fixedSize) { if (fixedSize) {