update
parent
891270e6d1
commit
b459b9dda6
|
@ -6,6 +6,8 @@ FluWindow {
|
|||
|
||||
width: 500
|
||||
height: 600
|
||||
minimumWidth: 300
|
||||
minimumHeight: 400
|
||||
title:"关于"
|
||||
|
||||
FluAppBar{
|
||||
|
|
|
@ -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{
|
||||
if(installHelper.isNavigateInstall()){
|
||||
FluApp.initialRoute = "/Installer"
|
||||
}else{
|
||||
FluApp.initialRoute = "/"
|
||||
}
|
||||
}
|
||||
FluApp.run()
|
||||
}
|
||||
|
|
|
@ -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<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)
|
||||
{
|
||||
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){
|
||||
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){
|
||||
#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();
|
||||
static void removeLink(){
|
||||
QString linkPath = QStandardPaths::writableLocation(QStandardPaths::DesktopLocation).append("/").append(linkName);
|
||||
QFile linkHome(linkPath);
|
||||
if(linkHome.exists()){
|
||||
linkHome.remove();
|
||||
}
|
||||
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){
|
||||
//创建开始菜单快捷方式
|
||||
QString startMenuPath=QStandardPaths::writableLocation(QStandardPaths::ApplicationsLocation).append("/").append(fileName);
|
||||
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){
|
||||
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);
|
||||
QString exePath = path+"\\"+"example.exe";
|
||||
QtConcurrent::run([=](){
|
||||
QFuture<void> 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()<<QCoreApplication::applicationDirPath();
|
||||
qDebug()<<path;
|
||||
installing(false);
|
||||
QStringList args;
|
||||
args<<"/c";
|
||||
args<<exePath;
|
||||
QProcess::startDetached("cmd.exe",args,"C:/",nullptr);
|
||||
QCoreApplication::exit();
|
||||
});
|
||||
}
|
||||
|
||||
void InstallHelper::uninstall(){
|
||||
QString currentDir = QCoreApplication::applicationDirPath();
|
||||
QDir dir(currentDir);
|
||||
dir.removeRecursively();
|
||||
QString batFile = generateBatFile();
|
||||
qint64 pid = QCoreApplication::applicationPid();
|
||||
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);
|
||||
}
|
||||
|
|
|
@ -13,6 +13,8 @@ class InstallHelper : public QObject
|
|||
|
||||
Q_OBJECT
|
||||
Q_PROPERTY_AUTO(bool,installing)
|
||||
Q_PROPERTY_AUTO(bool,uninstallSuccess)
|
||||
Q_PROPERTY_AUTO(QString,errorInfo)
|
||||
public:
|
||||
explicit InstallHelper(QObject *parent = nullptr);
|
||||
|
||||
|
@ -23,12 +25,20 @@ public:
|
|||
}
|
||||
|
||||
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();
|
||||
|
||||
static InstallHelper *getInstance();
|
||||
private:
|
||||
static InstallHelper* m_instance;
|
||||
};
|
||||
|
||||
#endif // INSTALLHELPER_H
|
||||
|
|
|
@ -34,6 +34,14 @@ FluWindow {
|
|||
installPath = String(fileDialog.fileUrls[0]).replace("file:///","").replace(RegExp("/",'g'),"\\")
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Connections{
|
||||
target: installHelper
|
||||
function onErrorInfoChanged(){
|
||||
showError(installHelper.errorInfo)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -68,8 +76,7 @@ FluWindow {
|
|||
text:"更改路径"
|
||||
Layout.rightMargin: 30
|
||||
onClicked: {
|
||||
showInfo(installHelper.applicationFilePath())
|
||||
// fileDialog.open()
|
||||
fileDialog.open()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -109,6 +109,7 @@ FluWindow {
|
|||
topMargin: 20
|
||||
bottomMargin: 52
|
||||
}
|
||||
boundsBehavior: Flickable.StopAtBounds
|
||||
clip: true
|
||||
width: 160
|
||||
model: nav_items
|
||||
|
@ -116,6 +117,7 @@ FluWindow {
|
|||
height: 38
|
||||
width: nav_list.width
|
||||
|
||||
|
||||
Rectangle{
|
||||
color: {
|
||||
if(FluApp.isDark){
|
||||
|
@ -147,7 +149,7 @@ FluWindow {
|
|||
leftMargin: 6
|
||||
rightMargin: 6
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
MouseArea{
|
||||
id:item_mouse
|
||||
|
@ -165,6 +167,9 @@ FluWindow {
|
|||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
Rectangle{
|
||||
|
|
|
@ -30,9 +30,16 @@ FluWindow {
|
|||
topMargin: 20
|
||||
}
|
||||
|
||||
|
||||
|
||||
Item{
|
||||
width: 1
|
||||
Layout.preferredWidth : parent.width
|
||||
Layout.fillHeight: true
|
||||
FluText{
|
||||
text:"青山不改,绿水长流,有缘再见"
|
||||
anchors.centerIn: parent
|
||||
fontStyle:FluText.TitleLarge
|
||||
}
|
||||
}
|
||||
|
||||
Rectangle{
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
QT += quick concurrent
|
||||
CONFIG += c++11
|
||||
CONFIG += c++11 qtquickcompiler utf8_source
|
||||
|
||||
DEFINES += QT_DEPRECATED_WARNINGS QT_NO_WARNING_OUTPUT
|
||||
|
||||
|
|
|
@ -1,8 +1,16 @@
|
|||
#include <QGuiApplication>
|
||||
#include <QQmlApplicationEngine>
|
||||
#include <QQmlContext>
|
||||
#include <QDir>
|
||||
#include <QProcess>
|
||||
#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[])
|
||||
{
|
||||
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<QString, QVariant> 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) {
|
||||
|
|
|
@ -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) \
|
||||
|
|
|
@ -25,8 +25,9 @@ FluApp::FluApp(QObject *parent)
|
|||
isDark(false);
|
||||
}
|
||||
|
||||
void FluApp::setAppWindow(QWindow *window){
|
||||
appWindow = window;
|
||||
void FluApp::init(QWindow *window,QMap<QString, QVariant> 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<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));
|
||||
QObject::connect(view, &QQuickView::statusChanged, view, [&](QQuickView::Status status) {
|
||||
if (status == QQuickView::Status::Ready) {
|
||||
|
|
14
src/FluApp.h
14
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<QString, QVariant> 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<QString, QVariant> properties;
|
||||
QWindow *appWindow;
|
||||
|
||||
};
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
|
|
|
@ -13,6 +13,7 @@ Rectangle {
|
|||
property color primaryColor : "#0064B0"
|
||||
signal clicked
|
||||
radius: 4
|
||||
|
||||
color:{
|
||||
if(FluApp.isDark){
|
||||
if(disabled){
|
||||
|
|
|
@ -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) {
|
||||
|
|
Loading…
Reference in New Issue