From 41d6272526098f8be303434b888947bf311fb477 Mon Sep 17 00:00:00 2001 From: shenmo Date: Mon, 25 Apr 2022 03:21:46 +0000 Subject: [PATCH] =?UTF-8?q?=E5=88=A0=E9=99=A4=E6=96=87=E4=BB=B6=20code-ana?= =?UTF-8?q?lyze.md?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- code-analyze.md | 328 ------------------------------------------------ 1 file changed, 328 deletions(-) delete mode 100644 code-analyze.md diff --git a/code-analyze.md b/code-analyze.md deleted file mode 100644 index 4bad78a..0000000 --- a/code-analyze.md +++ /dev/null @@ -1,328 +0,0 @@ - -#### 说明 - -当前服务器线路列表(项目中包含): - -``` -https://d.store.deepinos.org.cn/ -https://store.deepinos.org.cn/ -``` - - - - - - -# 星火应用商店文档 - -# 目录结构 -几个目录结构 -``` -/ -/icons 图标文件夹 -/tags 首页图标 -/tras 多语言翻译 -``` - -主要的文件分析 -```js -spark-store.pro Qt工程配置文件 -ssinstall 调用包安装器的脚本 -icons.qrc 图标资源文件 -main.cpp 入口文件 -widget.h widget.cpp widget.ui 主要窗口控件 -downloadlist.h downloadlist.cpp downloadlist.ui 单个软件的下载安装展示控件 -progressload.h progressload.cpp 网页加载显示? 得在deepin上编译运行才能搞清楚 -workerthreads.h workerthreads.cpp 应用信息加载线程 -image_show.h image_show.cpp 应用页面截图预览控件 -big_image.h big_image.cpp 大图查看控件 -``` - -# 使用的开源库及第三方工具 -* GDebi 一个 Ubuntu 软件中心的轻量级替代品 https://linux.cn/article-4982-1.html -* libnotify 系统通知 https://developer.gnome.org/libnotify/unstable/ - - -# 源码分析 -## 应用的组成部分 -左侧应用分类菜单 -主窗口的下拉菜单 -应用列表页面 -应用详情页面 -应用首页,有几个链接跳转 -商店设置页面 -下载列表页面 - -## 应用初始化,及主控件加载 -初始化 `DApplication` 进入事件循环。 -设置关于我们弹窗 `DAboutDialog`。 -主控件 Widget 根据不同屏幕大小自适应。 -首页打开webview页面,如果传入了`spk://`参数,会打开应用详情页。 -```cpp -// main.cpp -QString arg1=argv[1]; -if(arg1.left(6)=="spk://"){ - w.openUrl(QUrl(argv[1])); -} - -// widget.cpp -void Widget::openUrl(QUrl u) -{ - QString app=serverUrl + "store"+u.path()+"/app.json"; - ui->webEngineView->setUrl(app); // 会触发 webEngineView 的 -} - -``` -## Tags处理方式 - -**Tags处理方式** -```cpp -// widget.cpp -QString tags=json["Tags"].toString(); //Read the Tags - QStringList tagList=tags.split(";"); - for (int i=0;itag_community->show();//Tags icon shows like this - if(tagList[i]=="ubuntu") - ui->tag_ubuntu->show(); - if(tagList[i]=="deepin") - ui->tag_deepin->show(); - if(tagList[i]=="uos") - ui->tag_uos->show(); - if(tagList[i]=="dtk5") - ui->tag_dtk5->show(); - if(tagList[i]=="dwine2") - ui->tag_dwine2->show(); - if(tagList[i]=="dwine5") - ui->tag_dwine5->show(); - if(tagList[i]=="a2d") - ui->tag_a2d->show(); - } -``` - -**Widget 初始化** -```cpp -void Widget::initConfig() -{ - ... - // 读取服务器URL并初始化菜单项的链接 - QSettings readConfig(QDir::homePath()+"/.config/spark-store/config.ini",QSettings::IniFormat); - if(readConfig.value("server/choose").toString()!=""){ - ui->comboBox_server->setCurrentText(readConfig.value("server/choose").toString()); - appinfoLoadThread.setServer(serverUrl=readConfig.value("server/choose").toString()); - }else { - appinfoLoadThread.setServer(serverUrl="http://sucdn.jerrywang.top/"); // 默认URL - } - configCanSave=true; // 防止触发保存配置信号 - menuUrl[0]=serverUrl + "store/#/"; // 首页 - // 下面是各个应用分类页面,直接加载的webview的 - // 每个连接对应一个左侧的菜单项,在构造函数用连接到 chooseLeftMenu 槽函数 - menuUrl[1]=serverUrl + "store/#/network"; - ... - menuUrl[12]=serverUrl + "store/#/others"; - ... - ui->webfoot->hide(); - - //初始化首页 - ui->webEngineView->setUrl(menuUrl[0]); -} -/** - * 菜单切换逻辑 - * - */ -void Widget::chooseLeftMenu(int index) -{ - nowMenu=index; - updateUI(); - left_list[index]->setStyleSheet("color:#FFFFFF;background-color:"+main_color.name()+";border-radius:8;border:0px"); - // index <=12 加载某个分类的应用列表的webviejw - // index == 13 加载下载列表页面 - if(index<=12){ - if(themeIsDark){ - darkurl = 夜间模式的URL - ui->webEngineView->setUrl(darkurl); - }else { - ui->webEngineView->setUrl(menuUrl[index]); - } - ui->stackedWidget->setCurrentIndex(0); - }else if (index==13) { - ui->stackedWidget->setCurrentIndex(1); - } -} -``` - -## 应用下载安装卸载分析 -**应用详情页面加载** -```cpp -/** - * 加载单个应用的信息 - */ -void Widget::on_webEngineView_urlChanged(const QUrl &arg1) -{ - //分析出服务器中的分类名称 - ... - //如果是app.json就打开详情页 - if(arg1.path().right(8)=="app.json"){ - ... - // 读取相应的应用信息 - appinfoLoadThread.requestInterruption(); - appinfoLoadThread.wait(100); - appinfoLoadThread.setUrl(arg1); - appinfoLoadThread.start(); - } -} -// 设置详情页的APP信息 -SpkAppInfoLoaderThread::requestSetAppInformation() -> Widget::sltAppinfoDetails() -// 设置详情页的APP图标 -SpkAppInfoLoaderThread::finishedIconLoad() -> Widget::sltAppinfoIcon() -// 设置详情页的APP截图 -SpkAppInfoLoaderThread::finishedScreenshotLoad() -> Widget::sltAppinfoScreenshot() - -// 下载APP详情信息线程 -void SpkAppInfoLoaderThread::run() -{ - QProcess get_json; - get_json.start("curl -o app.json " + targetUrl.toString()); - QFile app_json("app.json"); - 读取 app.json 里的信息,提取应用名、描述、图标、截图 - 处理完毕后发射相应的信号 -} -``` - - -**应用下载** -Widget::on_pushButton_download_clicked() 是点击下载的安装方法。 -最终使用的是 `QNetwrokAccessManager` 进行GET请求获取数据写入文件。 -```cpp -void Widget::on_pushButton_download_clicked() -{ - if(!isBusy){ - file = new QFile(fileName); - ... - nowDownload+=1; - startRequest(urList.at(nowDownload-1)); // 进行链接请求 - } -} -void Widget::startRequest(QUrl url) -{ - reply = manager->get(QNetworkRequest(url)); - // 请求响应完成,关闭文件,清理下载队列 - connect(reply,SIGNAL(finished()),this,SLOT(httpFinished())); - // 接收应用下载数据 - connect(reply,SIGNAL(readyRead()),this,SLOT(httpReadyRead())); - // 更新应用下载进度 - connect(reply,SIGNAL(downloadProgress(qint64,qint64)),this,SLOT(updateDataReadProgress(qint64,qint64))); -} -``` - -使用 QSettings 来读取配置,更换服务源 -```cpp -void Widget::on_comboBox_server_currentIndexChanged(const QString &arg1) -{ - appinfoLoadThread.setServer(arg1); // 服务器信息更新 - if(configCanSave){ - ui->label_setting1->show(); - QSettings *setConfig=new QSettings(QDir::homePath()+"/.config/spark-store/config.ini",QSettings::IniFormat); - setConfig->setValue("server/choose",arg1); - } -} -``` -使用 `QProcess` 来调用各种小文件下载、包安装卸载的命令。 - -**应用安装** -```cpp -void Widget::httpFinished() // 完成下载 -{ - ...清理资源 - download_list[nowDownload-1].readyInstall(); - download_list[nowDownload-1].free=true; - if(nowDownloadpushButton_install->setEnabled(true); - ui->pushButton_install->show(); - ui->pushButton_2->hide(); - Widget::sendNotification(tr("Finished downloading %1, awaiting to install").arg(ui->label->text()), 5000, - "/tmp/spark-store/icon_"+QString::number(num).toUtf8()+".png"); -} -void downloadlist::on_pushButton_install_clicked() -{ - //弹出菜单 - menu_install->exec(cursor().pos()); -} -在 downloadlist 构造函数里将三种安装方式的按钮按条件放入了 menu_install 菜单里 -用户点击时,downloadlist::install() 方法 -三种安装方式为: gdebi, dpkg, deepin-deb-installer -void downloadlist::install(int t) -{ - QtConcurrent::run([=](){ - QProcess installer; - installer.start("pkexec gdebi -n /tmp/spark-store/"+ui->label_filename->text().toUtf8()); - installer.start("pkexec ssinstall /tmp/spark-store/"+ui->label_filename->text().toUtf8()); - installer.start("deepin-deb-installer /tmp/spark-store/"+ui->label_filename->text().toUtf8()); - }); -} -``` - -**应用卸载** -```cpp -void Widget::on_pushButton_uninstall_clicked() -{ - QtConcurrent::run([=](){ - uninstall.start("pkexec apt purge -y "+pkgName); - }); -} -``` - -**仓库源更新** -```cpp -// 更新源列表 -void Widget::on_pushButton_updateServer_clicked() -{ - QtConcurrent::run([=](){ - ... - QFile::remove(QDir::homePath().toUtf8()+"/.config/spark-store/server.list"); - system("curl -o "+QDir::homePath().toUtf8()+"/.config/spark-store/server.list http://dcstore.shenmo.tech/store/server.list"); - server.open(QDir::homePath().toUtf8()+"/.config/spark-store/server.list",std::ios::in); - ... - while (getline(server,lineTmp)) { - ui->comboBox_server->addItem(QString::fromStdString(lineTmp)); - } - }); -} -// 更新星火商店apt源 -void Widget::on_pushButton_updateApt_clicked() -{ - QtConcurrent::run([=](){ - 读取 comboBox_server 的内容,写入 /tmp/spark-store/sparkstore.list 文件 - 创建bash脚本,内容为将 sparkstore.list 移动到 /etc/apt/sources.list.d/ 目录下 - 使用QProcess 执行命令 pkexec update.sh - }): -} -``` - -## 发送系统通知 -```cpp -#include - -static NotifyNotification *_notify = nullptr; // 初始化 -notify_init(tr("Spark\\ Store").toLocal8Bit()); // 构造函数初始化 -notify_uninit(); // 析构函数调用 - -void Widget::sendNotification(const QString &message, const int msTimeout, const QString &icon) -{ - if(_notify == nullptr) - { - _notify = notify_notification_new(tr("Spark\\ Store").toLocal8Bit(), message.toLocal8Bit(), icon.toLocal8Bit()); - notify_notification_set_timeout(_notify, msTimeout); - } - else - notify_notification_update(_notify, tr("Spark\\ Store").toLocal8Bit(), message.toLocal8Bit(), icon.toLocal8Bit()); - - notify_notification_show(_notify, nullptr); -} -```