Compare commits

..

526 Commits

Author SHA1 Message Date
58f590560e !166 4.0 代号:Flamescion
Merge pull request !166 from shenmo/dev
2022-12-19 11:04:38 +00:00
f636b82f02 4.0Flamescion 2022-12-19 18:54:36 +08:00
877c3aafd1 正式版 2022-12-19 18:52:37 +08:00
zty199
65c26f035b fix: ISSUE #I66334 安装结束后仍显示 Installing
DownloadItem::install 中 finished 信号发送时间错误:安装操作被放入 QtConcurrent::run 中异步执行,发送信号在主线程中,安装未结束就发送了信号

Log: 调整信号发送位置至子线程中;AppIntoPage::isDownloading 中,若安装任务正在执行,需要 return,否则会出现安装后卸载再重新安装时,直接显示卸载按钮的问题
2022-12-19 17:38:41 +08:00
zty199
ba331cb3fb fix: ISSUE #I66N4Y 关闭动画播放时快速按Alt+F4可反复关闭动画而关不掉商店
动画执行标志位仅在动画结束后被置为不再执行,需要提前

Log: 修改 BaseWidgetOpacity::closeEvent,动画开始执行就修改标志位
2022-12-19 10:55:03 +08:00
zty199
27c95991c5 fix: 修复窗口关闭时崩溃问题
DownloadListWidget 析构时未对 downloadController 指针判空,直接调用 downloadController->stopDownload() 空指针导致崩溃

Log: DownloadListWidget 析构时对 downloadController 指针添加判断
2022-12-19 10:49:53 +08:00
ffd31445b9 !165 4.0.0.3
Merge pull request !165 from shenmo/Framescion
2022-12-19 02:11:26 +00:00
02fd887116 cmake-patch: 更新补丁用于支持 BaseWidgetOpacity 基础类的构建内容
此补丁包含以下内容:
 .gitignore                           |   34 ++++
 CMakeLists.txt                       |   93 ++++++++++
 Makefile                             |   60 ++++++
 assets/spark.png                     |  Bin
 cmake/DebPackageConfig.cmake         |  327 ++++++++++++++++++++++++++++++++++
 cmake/SparkAppimageConfig.cmake      |  133 ++++++++++++++
 cmake/SparkBuildGraphviz.cmake       |    8 +
 cmake/SparkDesktopMacros.cmake       |   35 ++++
 cmake/SparkEnvConfig.cmake           |    8 +
 cmake/SparkFindDtkConfig.cmake       |   11 +
 cmake/SparkFindLibraries.cmake       |    7 +
 cmake/SparkFindQt5Config.cmake       |  154 ++++++++++++++++
 cmake/SparkFindQt6Config.cmake       |   24 ++
 cmake/SparkInstallMacrosConfig.cmake |  132 ++++++++++++++
 cmake/SparkMacrosConfig.cmake        |  129 +++++++++++++
 cmake/SparkMacrosExtendConfig.cmake  |  197 ++++++++++++++++++++
 cmake/SparkTranslatorConfig.cmake    |   27 +++
 cmake/linuxdeployqt-help             |   48 +++++
 cmake/package-deb.descript           |   45 +++++
 cmake/spark-appimage.desktop.in      |    9 +
 cmake/spark-desktop.desktop.in       |   11 +
 Makefile                             |   16 ++
 cmake/DebPackageConfig.cmake         |    8 -
 DOCS/spark-cmake-build-system.md     |  301 +++++++++++++++++++++++++++++++
 CMakeLists.txt                       |    1
 cmake/SparkFindQt5Config.cmake       |    4
 CMakeLists.txt                       |    4
 27 files changed, 1818 insertions(+), 8 deletions(-)
2022-12-19 03:00:25 +08:00
fd3df91017 docs: 添加有关 src 下内容的改进,与"描述主体结构预览"文档的编写规范说明 2022-12-19 02:49:36 +08:00
c9d0c8b751 repo: 添加 BaseWidgetOpacity 基础类来实现继承者的淡出动画来代替主窗口的实现
BaseWidgetOpacity 是一个提供了淡出/淡入动画的基础类

1. closeEvent 窗口关闭时进行淡出动画
    此前在 MainWindow 中实现的淡出动画将由 BaseWidgetOpacity 来实现。

    此前 MainWindow 原有的 DBlurEffectWidget 父类将移交至 BaseWidgetOpacity 继承。

注意:
    如果 MainWindow 在未来重写 closeEvent 事件时将可能丢失 BaseWidgetOpacity 中的淡出效果
2022-12-19 02:47:38 +08:00
adf9032897 fix:商店点击刷新线路之后未默认选中首位 2022-12-18 13:46:55 +08:00
2c1679d0af fix:商店点击刷新线路之后未默认选中首位 2022-12-18 13:03:54 +08:00
95f9806c1c update .workflow/dtk-build-commit-20220425.yml.
Signed-off-by: shenmo <jifengshenmo@outlook.com>
2022-12-17 01:24:39 +00:00
252d2f491d 更新链接 2022-12-16 21:28:33 +08:00
e2f6d97f94 改为使用全新Web接口 2022-12-16 14:01:12 +08:00
48fd79e9be fix:商店更换线路的选项无效,点击刷新线路之后未默认选中首位 2022-12-15 22:31:00 +08:00
07eb9493cb cmake-patch: 更新补丁用于支持 Qt5 Svg 依赖的构建内容
此补丁包含以下内容:
 .gitignore                           |   34 ++++
 CMakeLists.txt                       |   93 ++++++++++
 Makefile                             |   60 ++++++
 assets/spark.png                     |  Bin
 cmake/DebPackageConfig.cmake         |  327 ++++++++++++++++++++++++++++++++++
 cmake/SparkAppimageConfig.cmake      |  133 ++++++++++++++
 cmake/SparkBuildGraphviz.cmake       |    8 +
 cmake/SparkDesktopMacros.cmake       |   35 ++++
 cmake/SparkEnvConfig.cmake           |    8 +
 cmake/SparkFindDtkConfig.cmake       |   11 +
 cmake/SparkFindLibraries.cmake       |    7 +
 cmake/SparkFindQt5Config.cmake       |  154 ++++++++++++++++
 cmake/SparkFindQt6Config.cmake       |   24 ++
 cmake/SparkInstallMacrosConfig.cmake |  132 ++++++++++++++
 cmake/SparkMacrosConfig.cmake        |  129 +++++++++++++
 cmake/SparkMacrosExtendConfig.cmake  |  197 ++++++++++++++++++++
 cmake/SparkTranslatorConfig.cmake    |   27 +++
 cmake/linuxdeployqt-help             |   48 +++++
 cmake/package-deb.descript           |   45 +++++
 cmake/spark-appimage.desktop.in      |    9 +
 cmake/spark-desktop.desktop.in       |   11 +
 Makefile                             |   16 ++
 cmake/DebPackageConfig.cmake         |    8 -
 DOCS/spark-cmake-build-system.md     |  301 +++++++++++++++++++++++++++++++
 CMakeLists.txt                       |    1
 cmake/SparkFindQt5Config.cmake       |    4
 26 files changed, 1815 insertions(+), 7 deletions(-)
2022-12-15 20:10:34 +08:00
217b299a67 update tool/ssinstall.
Signed-off-by: shenmo <jifengshenmo@outlook.com>
2022-12-15 12:04:37 +00:00
9738c41bb9 patch: 为星火商店提交一个基础的 cmake 构建补丁
此补丁包含以下内容:
 .gitignore                           |   34 ++++
 CMakeLists.txt                       |   93 ++++++++++
 Makefile                             |   60 ++++++
 assets/spark.png                     |  Bin
 cmake/DebPackageConfig.cmake         |  327 ++++++++++++++++++++++++++++++++++
 cmake/SparkAppimageConfig.cmake      |  133 ++++++++++++++
 cmake/SparkBuildGraphviz.cmake       |    8 +
 cmake/SparkDesktopMacros.cmake       |   35 ++++
 cmake/SparkEnvConfig.cmake           |    8 +
 cmake/SparkFindDtkConfig.cmake       |   11 +
 cmake/SparkFindLibraries.cmake       |    7 +
 cmake/SparkFindQt5Config.cmake       |  154 ++++++++++++++++
 cmake/SparkFindQt6Config.cmake       |   24 ++
 cmake/SparkInstallMacrosConfig.cmake |  132 ++++++++++++++
 cmake/SparkMacrosConfig.cmake        |  129 +++++++++++++
 cmake/SparkMacrosExtendConfig.cmake  |  197 ++++++++++++++++++++
 cmake/SparkTranslatorConfig.cmake    |   27 +++
 cmake/linuxdeployqt-help             |   48 +++++
 cmake/package-deb.descript           |   45 +++++
 cmake/spark-appimage.desktop.in      |    9 +
 cmake/spark-desktop.desktop.in       |   11 +
 Makefile                             |   16 ++
 cmake/DebPackageConfig.cmake         |    8 -
 DOCS/spark-cmake-build-system.md     |  301 +++++++++++++++++++++++++++++++
 24 files changed, 1812 insertions(+), 5 deletions(-)
2022-12-15 15:35:19 +08:00
e17c50d396 fix:安装结束后仍显示Installing 2022-12-15 14:55:46 +08:00
795c3308d3 修改翻译 2022-12-15 14:47:56 +08:00
f026844dba 更新部分翻译 2022-12-14 08:56:25 +08:00
1a05ad05aa update dtk-build-release-tag-20220425.yml 2022-12-13 14:21:46 +00:00
9c91d0a5a0 400t2 公测准备 2022-12-13 21:47:09 +08:00
a27c8b9ace fix:下载取消后下载进度仍然在widget中显示 2022-12-13 21:37:40 +08:00
68d91f71ba 应用详情页添加版本号 2022-12-13 21:30:30 +08:00
fca2086d9f 修复取消下载导致闪退 2022-12-13 21:17:51 +08:00
83ee212484 重写下载按钮逻辑 2022-12-13 20:32:39 +08:00
922cb6a34f fix:应用商店退出时,aria2c仍然在运行 2022-12-13 19:37:46 +08:00
eb00159691 fix:Appinfo界面信息无法复制 2022-12-13 19:25:52 +08:00
3b18fc94b5 将下载按钮更新为自绘按钮 2022-12-13 19:00:36 +08:00
375243503f Merge remote-tracking branch 'refs/remotes/origin/dev' into dev 2022-12-13 18:28:48 +08:00
9b31040efd ssinstall支持相对路径 2022-12-13 18:28:24 +08:00
ac5d86db92 update README.md.
Signed-off-by: shenmo <jifengshenmo@outlook.com>
2022-12-13 09:53:50 +00:00
86f270eca9 修复进度条过长 2022-12-13 17:23:34 +08:00
f5bb95da12 修复左侧边栏样式错误 2022-12-13 17:18:10 +08:00
eadc8dd875 修改: translations/spark-store_zh_CN.ts 2022-12-13 17:13:25 +08:00
91b628e7a6 installation complete 翻译
现在使用AppName来提示
2022-12-13 17:12:41 +08:00
6bd8fc7a1e 修改限制单例运行,再次启动时拉起现有实例 2022-12-13 14:54:59 +08:00
c2e665ecb6 修复英文状态下左侧边栏文字不对齐 2022-12-13 14:52:07 +08:00
50cf537e1d 安装完成通知加上应用名 2022-12-13 14:40:55 +08:00
0f0a5795af Merge remote-tracking branch 'upstream/dev' into dev 2022-12-13 12:53:15 +08:00
09f96d596a fix: 超时时间错误 2022-12-13 12:52:45 +08:00
a2cb7ef112 需求:在安装结束后将安装状态发送系统通知 2022-12-13 12:43:58 +08:00
2ed2512d6c fix:设置界面点击链接仍无效,邮箱文案附近出现未被解析的html标签 2022-12-13 12:40:20 +08:00
d720d0670d fix:下载的进度条仍然过长 2022-12-13 12:36:28 +08:00
da2c019da0 fix:点击取消下载 仍然会有系统通知提示下载完毕 2022-12-13 12:34:48 +08:00
ce8c058265 更新翻译 2022-12-13 10:23:37 +08:00
7f3eadf3a7 更新文案 2022-12-12 21:47:52 +08:00
44ea6755f9 fix:4.0 bug 在设置界面意义不明的文案 2022-12-12 21:37:29 +08:00
9df0e3a3b3 去除安装按钮的子菜单 2022-12-12 21:33:41 +08:00
13550ebbec 修复由于翻译不正确引起的关于页面bug 2022-12-12 21:30:40 +08:00
077034b1d6 fix:4.0 开始自动安装时安装按钮仍然存在 2022-12-12 21:13:28 +08:00
ac21f67030 fix:4.0 安装结束后的Info按钮的中文翻译应当为:详情,而不是信息 2022-12-12 21:10:55 +08:00
292d4aa5c9 fix: 清除网页缓存未生效 2022-12-12 17:36:12 +08:00
fb4d78ce1d 修复下载量统计超时 2022-12-12 16:23:41 +08:00
ad25606ef9 新增文案提示用户发生了什么 2022-12-12 16:20:01 +08:00
6ace772a09 修改发送邮件的等待时间 2022-12-12 16:08:30 +08:00
bfc68fbf6f 修复下载按钮状态未重置 2022-12-12 15:49:41 +08:00
e2c9f1100d 修改: debian/spark-store.postinst 2022-12-12 15:43:23 +08:00
77c2e2ebc8 changelog-400t1 2022-12-12 15:30:03 +08:00
eb06f33269 修复 2022-12-12 15:28:12 +08:00
e2c8eb79a0 添加下载完成后自动安装 2022-12-12 15:26:15 +08:00
c825e4b39c 修改文案 2022-12-12 15:23:48 +08:00
79d12f2409 安全的免密码安装 2022-12-12 15:11:48 +08:00
382b2de5ca 更新翻译 2022-12-12 14:36:33 +08:00
0fea4c13ef 添加多个通知,修复下载进度条过长问题 2022-12-12 14:34:29 +08:00
ff84576aab 更改文案 2022-12-12 12:19:38 +08:00
2b2ebc111e 更新翻译 2022-12-12 12:15:55 +08:00
20fc6f5a77 update src/main.cpp.
Signed-off-by: shenmo <jifengshenmo@outlook.com>
2022-12-12 04:00:46 +00:00
83bfb8dfd5 解决依赖没有删除完全导致构建失败问题 2022-12-12 11:52:46 +08:00
db5b85db7d 去除无用依赖 2022-12-11 20:53:35 +08:00
271a7e33f4 添加chatGPT帮忙写的通知推送 2022-12-11 20:40:01 +08:00
478db77d36 点击侧边栏按钮时清空搜索框 2022-12-11 19:28:25 +08:00
a787745752 设置中添加QQ群号,链接改为可点击,搜索后关键词不清空 2022-12-11 19:21:45 +08:00
758b752d6e 修复重新安装按钮文案错误 2022-12-11 18:54:00 +08:00
60ed4c5aff 添加重新安装按钮 2022-12-11 18:41:19 +08:00
2d3366990a feat: 增加主程序退出动画 2022-12-11 18:25:30 +08:00
b63ae13a3e fix shebang 2022-12-11 18:13:03 +08:00
6ff58adffa 左侧边栏加入更新按钮 2022-12-11 18:10:36 +08:00
f948c8905a 添加浏览器GPU支持,编译时间获取,关于窗口修改,启动时窗口居中显示 2022-12-11 17:55:27 +08:00
a31f724b65 修复翻译异常与应用详细页文字过长时显示不完整的问题 2022-12-11 17:47:31 +08:00
8c9c2fcf11 修复非DDE环境下透明度过高的问题 2022-12-11 17:31:10 +08:00
e251616129 update .workflow/dtk-build-commit-20220425.yml.
Signed-off-by: shenmo <jifengshenmo@outlook.com>
2022-12-11 09:27:16 +00:00
6655e14b6c 构建同步到master
Signed-off-by: shenmo <jifengshenmo@outlook.com>
2022-12-11 09:26:37 +00:00
柚子
b3aa2036f8 删除文件 Makefile 2022-12-11 09:22:45 +00:00
8ad1156e3c 修复返回键出现错误问题 2022-12-11 12:02:26 +08:00
b5495fa66e !4 make: 添加快速构建脚本,对 VSCode 用户友好
Merge pull request !4 from zinface/makefile-script
2022-12-11 02:11:09 +00:00
333a1168d4 添加应用详情页下载量显示 2022-12-11 02:05:34 +08:00
8a54dd92a3 添加dbus功能 2022-12-11 01:19:59 +08:00
ae1c50893d 菜单中添加投稿器,更新等 2022-12-11 01:06:52 +08:00
dd0605d0ba 应用详情页添加分享和请求更新按钮,设置页面添加更新客户端和清理缓存、读取缓存大小功能 2022-12-11 01:03:13 +08:00
0817901a59 添加下载列表为空时的提示 2022-12-11 00:29:51 +08:00
e171904a34 抽象出控件动画类 2022-12-11 00:17:09 +08:00
abd0e47c69 make: 添加快速构建脚本,对 VSCode 用户友好
此部分对 VSCode 用户友好,并提供一些可扩展的操作
1. make 时将创建 build 目录并使用 qmake 构建(核心数为机器最大核心数)
2. make run 时将运行此程序(程序构建位置将在: build/src/spark-store)
3. make package 用来提供产出包功能?
2022-12-10 23:16:22 +08:00
1c24079406 添加按下下载按钮时标题栏下载列表按钮抖动 2022-12-10 19:18:23 +08:00
67c0cbf27b fix: 修复一些bug 2022-12-10 13:22:54 +08:00
5cc34e7e3d 修复页面索引错位bug 2022-12-09 22:19:20 +08:00
98cf333386 添加服务器url配置功能 2022-12-09 21:27:01 +08:00
562b582f72 添加设置页面 2022-12-09 19:07:22 +08:00
73917eeeb1 fix: 打包依赖增加g++ 2022-12-09 15:29:17 +08:00
c5913b4198 !1 feat: 增加主程序进入动画
* !1 update src/mainwindow-dtk.cpp.
* update src/mainwindow-dtk.cpp.
* feat: 增加主程序进入动画
2022-12-09 07:26:55 +00:00
c0e9815d9d 修复深色模式下顶栏的按钮未更新的bug 2022-12-09 15:15:48 +08:00
050fe964dd 深色主題寫好啦! 2022-12-09 15:13:41 +08:00
6981a4f476 更改应用详情页UI细节 2022-12-09 14:38:08 +08:00
e72d123a40 更新中文翻译 2022-12-09 13:49:28 +08:00
a10390a6e3 update changelog 2022-12-09 12:01:26 +08:00
3fecd41c4f 下载完成后自动更改按钮文案 2022-12-09 11:59:19 +08:00
f0604afcfc 同步3.5版本的更改 2022-12-09 11:59:04 +08:00
2ec4b1f4d4 4.0 2022-12-09 11:16:11 +08:00
fbffe12501 feat:搜索从网页加载 2022-12-08 22:44:34 +08:00
df7b49dbe2 fix: aria2指定dns,指定最大并发下载数 2022-12-08 17:51:18 +08:00
9d93966124 Merge remote-tracking branch 'upstream/dev' into dev 2022-12-08 17:46:20 +08:00
977b2ebdc9 update src/main.cpp.
Signed-off-by: shenmo <jifengshenmo@outlook.com>
2022-12-04 07:09:26 +00:00
28ed452bb0 * feat: aptss不再尝试安装apt-fast,转而自带
* chore:  删除password-check模块
2022-12-04 15:07:44 +08:00
512d86feac update: 更新aria2下载参数 2022-11-27 12:21:15 +08:00
8e1e0cea7a fix: minor updates 2022-11-26 19:33:20 +08:00
d2214114fb Merge remote-tracking branch 'upstream/dev' into dev 2022-11-26 19:27:41 +08:00
c90232022e update src/main.cpp.
Signed-off-by: shenmo <jifengshenmo@outlook.com>
2022-11-26 09:27:43 +00:00
84a1554b4b !149 333 feat feat: 首页链接调用浏览器打开
Merge pull request !149 from shenmo/master
2022-11-26 09:27:04 +00:00
71dbf9b958 update debian/changelog.
Signed-off-by: shenmo <jifengshenmo@outlook.com>
2022-11-26 09:22:56 +00:00
9d12086f09 !148 feat: 首页链接调用浏览器打开
Merge pull request !148 from zty199/auto-7392693-master-b04b4cba
2022-11-26 09:20:37 +00:00
zty199
54a55e15a9 feat: 首页链接调用浏览器打开
首页链接调用浏览器打开

Log: 使用自定义 WebEngineView 和 WebEnginePage 替代 QWebEngineView,重写 createWindow 方法,当页面存在新建窗口或标签页动作时调用浏览器打开网址;修改 Widget UI 布局,在 page1 添加 QVBoxLayout,保证 WebEngineView 自动撑满布局,去除 webFoot 填充控件;更新翻译文件,添加“请勿频繁搜索”翻译文案,去除残留翻译
2022-11-26 17:14:48 +08:00
5385e2d1b1 update debian/changelog.
Signed-off-by: shenmo <jifengshenmo@outlook.com>
2022-11-26 08:50:41 +00:00
1e468ba774 fix: 邮件超时 2022-11-26 14:30:00 +08:00
25efce0017 !147 dev--->master:流水线准备优化,先行同步
Merge pull request !147 from shenmo/dev
2022-11-26 02:07:44 +00:00
707a2b5e4c !146 修正一些问题
Merge pull request !146 from Pluto/dev
2022-11-26 02:06:19 +00:00
b9121c13ab feat: 改进搜索动画 2022-11-26 02:20:17 +08:00
9c80179493 feat: 版本号新增编译时间 2022-11-25 22:29:23 +08:00
2a89135d1a fix: 指针未释放 2022-11-25 22:05:29 +08:00
b91e0142f4 bigimage: 对应用信息下的截图预览优化(#I62F4X) 2022-11-22 11:58:09 +08:00
55897e3cb9 update: 更新介绍 2022-11-20 20:23:45 +08:00
f17fcdfe85 feat: 跳转到反馈器 2022-11-20 20:00:14 +08:00
9046a3a965 fix: 只允许一个更新进程 2022-11-18 01:11:20 +08:00
1e72fcb7f2 !145 文案:修复换行
Merge pull request !145 from shenmo/dev
2022-11-17 14:48:33 +00:00
9007bdf3d3 update README.md.
Signed-off-by: shenmo <jifengshenmo@outlook.com>
2022-11-17 14:48:13 +00:00
afd926ae4a update README.zh.md.
Signed-off-by: shenmo <jifengshenmo@outlook.com>
2022-11-17 14:47:46 +00:00
4949d67852 !144 文案:添加RC入口
Merge pull request !144 from shenmo/dev
2022-11-17 14:46:44 +00:00
5f5d71fbd0 update README.md.
Signed-off-by: shenmo <jifengshenmo@outlook.com>
2022-11-17 14:46:16 +00:00
9fd8f64195 update README.zh.md.
Signed-off-by: shenmo <jifengshenmo@outlook.com>
2022-11-17 14:45:25 +00:00
c32ffb7cd2 update .workflow/dtk-build-release-tag-20220425.yml.
Signed-off-by: shenmo <jifengshenmo@outlook.com>
2022-11-10 11:34:28 +00:00
af9217b1dc !143 333t4
Merge pull request !143 from shenmo/dev
2022-11-10 11:30:47 +00:00
93e218dd53 update README.zh.md.
Signed-off-by: shenmo <jifengshenmo@outlook.com>
2022-11-10 11:28:20 +00:00
4de32fa8a6 update README.md.
Signed-off-by: shenmo <jifengshenmo@outlook.com>
2022-11-10 11:27:19 +00:00
2d59a61796 修改: debian/changelog
修改:     debian/spark-store.postinst
	修改:     src/main.cpp
2022-11-09 20:06:50 +08:00
7abdd90215 文案修改 update tool/update-upgrade/ss-do-upgrade.sh.
Signed-off-by: shenmo <jifengshenmo@outlook.com>
2022-11-08 13:45:24 +00:00
cbd594e217 !142 333t3
Merge pull request !142 from shenmo/dev
2022-10-28 13:45:08 +00:00
42b6a20c97 fix 菜单中进入更新列表失效 2022-10-28 21:43:57 +08:00
110adc995d 文案修改 2022-10-28 10:20:23 +08:00
cd6d0ac133 cmmit 2022-10-28 10:19:17 +08:00
568e73de07 文案修改 2022-10-28 09:58:17 +08:00
62c8841c50 aptss的download也使用ss-apt-fast 2022-10-28 09:55:48 +08:00
6fd611919b Now use ss-apt-fast as aptss backend 2022-10-28 09:08:21 +08:00
77a84785de !141 333t2
Merge pull request !141 from shenmo/dev
2022-10-27 16:58:38 +00:00
9969f4f2fc just in case有些用户没有找到QQ群.... 2022-10-28 00:57:02 +08:00
833a8ec14b version 2022-10-28 00:52:25 +08:00
dd679f3f26 333t2推仓库 2022-10-28 00:50:31 +08:00
5411a832dc fix:更新和检查更新出错时不报错 2022-10-28 00:48:53 +08:00
0aeadb5526 update debian/changelog.
Signed-off-by: shenmo <jifengshenmo@outlook.com>
2022-10-27 13:14:10 +00:00
91fd97b878 修改文案:检查更新 2022-10-27 10:37:51 +08:00
f2cf344f62 polkit文件 2022-10-26 16:01:55 +08:00
8d84e433a6 zenity 不再以root启动 2022-10-26 15:43:43 +08:00
a6e9dac2f9 没啥用,又加回来了 2022-10-24 09:22:07 +08:00
495ef3292e 更新提示超时时间增加到15 2022-10-24 09:15:04 +08:00
5900b3cdf3 feat:安装时不再需要网络
modify: 为了CI的构建速度,在构建依赖中不再依赖语言工具
2022-10-24 09:12:37 +08:00
e644214263 !140 3304 策略调整 选中的应用作为整体更新,降低服务器压力
Merge pull request !140 from shenmo/dev
2022-10-23 15:52:04 +00:00
2b76f5e202 3304 2022-10-23 23:50:16 +08:00
6fe06667eb !139 3303-real
Merge pull request !139 from shenmo/dev
2022-10-23 06:06:22 +00:00
f61e3a6ede 引号故障 2022-10-23 14:04:58 +08:00
bddbbcc2e8 !138 3303 暂时关闭实时输出,未找到禁止取消或关闭的方法
Merge pull request !138 from shenmo/dev
2022-10-23 05:58:42 +00:00
8310a59df8 微调样式 2022-10-23 13:58:32 +08:00
05cfdbb318 支持分应用显示正在更新 2022-10-23 13:42:32 +08:00
b5488b6c32 3303 2022-10-23 13:27:14 +08:00
6cec12be9d 3302 修复pkexec未执行 2022-10-23 13:06:03 +08:00
53f9746ebf 3301 推送 2022-10-23 10:21:59 +08:00
b68ef5aab1 !137 3301 sudo去除
Merge pull request !137 from shenmo/dev
2022-10-23 02:20:29 +00:00
c6daf5159c 去除sudo 2022-10-23 10:19:49 +08:00
b0453c7a8a !136 3101重大事故:更新系统修复
Merge pull request !136 from shenmo/dev
2022-10-23 02:15:44 +00:00
c7ee32a452 pkexec 修复 2022-10-23 10:10:55 +08:00
e1d25e401f update debian/spark-store.preinst.
Signed-off-by: shenmo <jifengshenmo@outlook.com>
2022-10-22 08:19:33 +00:00
6b78dce87e !135 体验优化:更新时添加进度条
Merge pull request !135 from shenmo/dev
2022-10-21 09:47:49 +00:00
e5a198e1d8 添加升级应用时的进度条 2022-10-21 17:46:20 +08:00
1780110e33 !134 330
Merge pull request !134 from shenmo/dev
2022-10-21 09:28:29 +00:00
19901b0d7d update debian/changelog.
Signed-off-by: shenmo <jifengshenmo@outlook.com>
2022-10-21 09:28:06 +00:00
d24af0461b update src/main.cpp.
Signed-off-by: shenmo <jifengshenmo@outlook.com>
2022-10-21 09:27:05 +00:00
31a574ec8b !133 feat: 侧边栏更新管理器
Merge pull request !133 from Pluto/dev
2022-10-21 09:26:27 +00:00
3feae61b1b feat: 更新管理器
change: 翻译
2022-10-21 17:20:57 +08:00
eaf65a326c update tool/update-upgrade/ss-do-upgrade.sh.
Signed-off-by: shenmo <jifengshenmo@outlook.com>
2022-10-21 08:49:18 +00:00
13da2bc441 update tool/update-upgrade/ss-do-upgrade.sh.
Signed-off-by: shenmo <jifengshenmo@outlook.com>
2022-10-21 08:47:41 +00:00
5420bad0ee 默认免密码查看可更新应用 2022-10-21 14:56:31 +08:00
8465c9ad2d 全部改为zenity 2022-10-21 14:43:15 +08:00
5562e2b5d1 fix:不正确地跳过unhold 2022-10-21 13:59:43 +08:00
a09425f361 符号错误修正 2022-10-21 13:46:23 +08:00
18db530c0d zenity依赖加入 2022-10-21 13:30:21 +08:00
03263edf8c 更新系统zenity,适配apt-mark hold 2022-10-21 13:28:34 +08:00
cd13a1ce08 !132 merge and start develop zenity
Merge pull request !132 from shenmo/dev
2022-10-21 03:03:18 +00:00
1c5f31da6f fix: 左侧菜单字体大小变化 2022-10-20 21:13:59 +08:00
cafb4d1dfe !131 版本号 GUI
Merge pull request !131 from shenmo/dev
2022-10-19 15:15:00 +00:00
828f1a0f05 update src/main.cpp.
版本号

Signed-off-by: shenmo <jifengshenmo@outlook.com>
2022-10-19 15:14:38 +00:00
b03795e364 !130 324正式
Merge pull request !130 from shenmo/dev
2022-10-19 14:54:19 +00:00
c54c13d822 modified: debian/changelog 2022-10-17 18:33:49 +08:00
fdc9550100 tag相关文案修改 2022-10-17 18:31:46 +08:00
458cc49302 update debian/changelog.
Signed-off-by: shenmo <jifengshenmo@outlook.com>
2022-10-15 14:26:04 +00:00
e11afad89b !129 反向同步进度
Merge pull request !129 from shenmo/master
2022-10-15 14:25:37 +00:00
43ae031131 !128 增加dbus
Merge pull request !128 from depend/dev
2022-10-15 12:03:18 +00:00
dd6780d636 增加dbus文件,再次启动的时候会唤起第一个进程
并且处理spark打开
2022-10-15 19:55:19 +08:00
42368a0245 !127 转扁平化为正常合入,添加依赖libssl-dev
Merge pull request !127 from shenmo/dev
2022-10-13 16:04:52 +00:00
8ca0035107 根据 https://www.deepinos.org/d/1076-ubuntu2204/3 修改
Signed-off-by: shenmo <jifengshenmo@outlook.com>
2022-10-13 16:03:40 +00:00
10332c59e0 !126 324t3发版
* 3.2.4~test3
* 	修改:     debian/changelog
* !125 fix: 对oss进行URL转译
* Merge remote-tracking branch 'upstream/dev' into dev
* fix: 对oss进行URL转译
* !124 fix: 安装时可能出现的超时错误
* update debian/changelog.
* update src/widget.cpp.
* Merge remote-tracking branch 'upstream/dev' into dev
* update debian/changelog.
* Merge remote-tracking branch 'upstream/dev' into dev
* fix: 超时错误
* update README.zh.md.
* update README.md.
* update README.zh.md.
* update debian/changelog.
* !123 feat: 投稿器
* feat: 投稿器
* !122 fix:gpu 参数
* fix: chrome GPU 参数
* Merge remote-tracking branch 'upstream/dev' into dev
* 修复错误的配置文件
* 改为读取/etc
* update debian/changelog.
* UOS 走普通的aptss,aptss支持UOS源
* 更新时不再清除免密码安装设置
* !121 反向同步
* fix
* Merge remote-tracking branch 'upstream/dev' into dev
* fix: high CPU usage because futex is still waiting for queue after illegal exit
* Merge remote-tracking branch 'upstream/master' into dev
* Merge remote-tracking branch 'upstream/dev' into dev
* feat: enable GPU
* Merge remote-tracking branch 'upstream/dev' into dev
* Merge branch 'dev' of gitee.com:uniartisan2018/spark-store into dev
* feat: 清除网页缓存
* 文案修改
* update src/widget.ui.
* feat: 星火应用商店检测更新
2022-10-12 14:08:21 +00:00
09a1c9f710 3.2.4~test3 2022-10-12 22:08:08 +08:00
ba29c4171c 修改: debian/changelog
修改:     translations/spark-store_en.ts
	修改:     translations/spark-store_fr.ts
	修改:     translations/spark-store_zh_CN.ts
2022-10-12 22:06:30 +08:00
3b9dde23e7 !125 fix: 对oss进行URL转译
Merge pull request !125 from Pluto/dev
2022-10-12 10:59:23 +00:00
746e9bd3d6 Merge remote-tracking branch 'upstream/dev' into dev 2022-10-12 09:31:38 +08:00
d7f0ee983b fix: 对oss进行URL转译 2022-10-12 09:31:23 +08:00
3feec88f7b !124 fix: 安装时可能出现的超时错误
Merge pull request !124 from Pluto/dev
2022-10-09 11:11:25 +00:00
c0ffb64a86 update debian/changelog.
Signed-off-by: shenmo <jifengshenmo@outlook.com>
2022-10-09 11:01:55 +00:00
8c08b7e995 update src/widget.cpp.
Signed-off-by: shenmo <jifengshenmo@outlook.com>
2022-10-09 10:41:48 +00:00
4d7e766d75 Merge remote-tracking branch 'upstream/dev' into dev 2022-10-09 18:37:01 +08:00
09115c3961 update debian/changelog.
Signed-off-by: shenmo <jifengshenmo@outlook.com>
2022-10-09 10:36:31 +00:00
63998bbce4 Merge remote-tracking branch 'upstream/dev' into dev 2022-10-09 18:36:31 +08:00
967f62f825 fix: 超时错误 2022-10-09 18:36:22 +08:00
e8ae0325e0 update README.zh.md.
Signed-off-by: shenmo <jifengshenmo@outlook.com>
2022-10-08 16:13:33 +00:00
66a4563b51 update README.md.
Signed-off-by: shenmo <jifengshenmo@outlook.com>
2022-10-08 16:12:59 +00:00
330ae3eeb8 update README.zh.md.
Signed-off-by: shenmo <jifengshenmo@outlook.com>
2022-10-08 16:12:00 +00:00
0534c39ee5 update debian/changelog.
Signed-off-by: shenmo <jifengshenmo@outlook.com>
2022-10-08 15:45:37 +00:00
04047c1e44 !123 feat: 投稿器
* feat: 投稿器
2022-10-08 15:38:55 +00:00
5e501b9d17 feat: 投稿器 2022-10-08 23:27:35 +08:00
5a434a9b7d !122 fix:gpu 参数
Merge pull request !122 from Pluto/dev
2022-10-08 14:41:43 +00:00
e554aec98d fix: chrome GPU 参数 2022-10-08 22:24:16 +08:00
ab0f5e6613 Merge remote-tracking branch 'upstream/dev' into dev 2022-10-08 22:20:46 +08:00
59607f6b34 修复错误的配置文件
Signed-off-by: shenmo <jifengshenmo@outlook.com>
2022-10-08 14:08:30 +00:00
a13f0ddcb7 改为读取/etc
Signed-off-by: shenmo <jifengshenmo@outlook.com>
2022-10-08 13:47:00 +00:00
fec604b481 update debian/changelog.
Signed-off-by: shenmo <jifengshenmo@outlook.com>
2022-10-08 03:22:12 +00:00
085eddd66f UOS 走普通的aptss,aptss支持UOS源 2022-10-07 22:31:24 +08:00
30860802dd 更新时不再清除免密码安装设置 2022-09-30 11:27:22 +08:00
30f36ff35d !121 反向同步
Merge pull request !121 from shenmo/master
2022-09-27 12:15:32 +00:00
lisuke
81993625ba !120 添加编译依赖 fakeroot
* 添加 fakeroot 依赖
2022-09-27 12:14:48 +00:00
87b68aca1e !119 323版本 降低dtk版本
Merge pull request !119 from shenmo/dev
2022-09-27 01:53:24 +00:00
10125c5816 update src/main.cpp.
Signed-off-by: shenmo <jifengshenmo@outlook.com>
2022-09-27 01:49:01 +00:00
21d33ec347 update debian/changelog.
Signed-off-by: shenmo <jifengshenmo@outlook.com>
2022-09-27 01:48:34 +00:00
ad57aa26ff 降低dtk需求版本
Signed-off-by: shenmo <jifengshenmo@outlook.com>
2022-09-27 01:34:48 +00:00
8902c81b9e !118 fix: high CPU usage because futex is still waiting for queue after illegal exit
* fix
* Merge remote-tracking branch 'upstream/dev' into dev
* fix: high CPU usage because futex is still waiting for queue after illegal exit
* Merge remote-tracking branch 'upstream/master' into dev
* Merge remote-tracking branch 'upstream/dev' into dev
* feat: enable GPU
* !113 3.2.1 merge
* !112 Now stop use mail to collect info
* Merge remote-tracking branch 'upstream/dev' into dev
* Merge branch 'dev' of gitee.com:uniartisan2018/spark-store into dev
* feat: 清除网页缓存
* 文案修改
* update src/widget.ui.
* feat: 星火应用商店检测更新
2022-09-27 01:34:18 +00:00
0ad4b6c82c fix 2022-09-26 23:53:28 +08:00
189a0b4939 Merge remote-tracking branch 'upstream/dev' into dev 2022-09-26 23:46:34 +08:00
c65d7b86df fix: high CPU usage because futex is still waiting for queue after illegal exit 2022-09-26 23:46:25 +08:00
e269e6ca57 !116 3.2.2 合并
Merge pull request !116 from shenmo/dev
2022-09-21 18:37:02 +00:00
aff593eba8 !115 3.2.2 启动
* update debian/changelog.
* download可无root运行,相应的,不会自动到最新
* !114 feat: GPU enable
* aptss will now refresh the system source before doing install, downloa…
2022-09-20 04:12:29 +00:00
beaeac60a3 update debian/changelog.
Signed-off-by: shenmo <jifengshenmo@outlook.com>
2022-09-20 04:11:58 +00:00
11d68fb4b5 download可无root运行,相应的,不会自动到最新
Signed-off-by: shenmo <jifengshenmo@outlook.com>
2022-09-20 04:05:25 +00:00
e7680fe2a0 !114 feat: GPU enable
* Merge remote-tracking branch 'upstream/master' into dev
* Merge remote-tracking branch 'upstream/dev' into dev
* feat: enable GPU
* !113 3.2.1 merge
* !112 Now stop use mail to collect info
* Merge remote-tracking branch 'upstream/dev' into dev
* Merge branch 'dev' of gitee.com:uniartisan2018/spark-store into dev
* feat: 清除网页缓存
* 文案修改
* update src/widget.ui.
* feat: 星火应用商店检测更新
2022-09-20 04:03:09 +00:00
19dff7fb56 Merge remote-tracking branch 'upstream/master' into dev 2022-09-20 11:55:54 +08:00
67b314d0d2 Merge remote-tracking branch 'upstream/dev' into dev 2022-09-20 11:55:40 +08:00
63b28adaf8 feat: enable GPU 2022-09-20 11:55:36 +08:00
8741973cca aptss will now refresh the system source before doing install, download, policy....etc 2022-09-19 17:58:00 +08:00
8e3787ab07 !113 3.2.1 merge
Merge pull request !113 from shenmo/dev
2022-09-18 13:17:11 +00:00
f7d07e0bf9 !112 Now stop use mail to collect info
* Now abandon mail info collect method and delete the outdated info
2022-09-11 12:24:26 +00:00
9e4df5c5c2 !111 feat: 清除QtWebCore的缓存
* Merge remote-tracking branch 'upstream/dev' into dev
* Merge branch 'dev' of gitee.com:uniartisan2018/spark-store into dev
* feat: 清除网页缓存
* 文案修改
* update src/widget.ui.
* feat: 星火应用商店检测更新
2022-09-03 09:25:19 +00:00
829a08d40a Merge remote-tracking branch 'upstream/dev' into dev 2022-09-02 19:28:05 +08:00
411bbe5935 Merge branch 'dev' of gitee.com:uniartisan2018/spark-store into dev 2022-09-02 19:25:27 +08:00
5d5fbfbad4 feat: 清除网页缓存 2022-09-02 19:24:45 +08:00
af89e64478 !110 检测更新
* 文案修改
* update src/widget.ui.
* feat: 星火应用商店检测更新
2022-08-31 17:50:24 +00:00
c93c221cf1 文案修改 2022-09-01 01:47:38 +08:00
afee0966c8 update src/widget.ui.
Signed-off-by: shenmo <jifengshenmo@outlook.com>
2022-08-31 17:44:46 +00:00
2df5363c2c feat: 星火应用商店检测更新 2022-09-01 01:39:09 +08:00
971a5dcc63 安装时删除已有的源 2022-09-01 00:40:16 +08:00
a252e7b724 3.2.1 更新源服务器改为aptss 2022-09-01 00:29:37 +08:00
d3987a20ec !108 在检测更新时临时降低优先级到100,防止系统中有且版本一致的包被反复来回更新
* changelog更新
* 修复界面中显示的更新检测服务是否启动不正确
* 在检测更新时临时降低优先级到100,防止系统中有且版本一致的包被反复来回更新
2022-08-29 17:58:39 +00:00
932e754b88 !107 修改: debian/changelog
* 	修改:     debian/changelog
* ssupdate不再更新cache,防止ssinstall出错率
2022-08-29 17:32:05 +00:00
72a771b0f1 !106 界面细节修改,提升下载量的瞩目 补充changelog 准备发320测试
Merge pull request !106 from shenmo/auto-4915358-master-984782a5
2022-08-29 17:01:12 +00:00
b75fbe5674 界面细节修改,提升下载量的瞩目
补充changelog
准备发320测试
2022-08-30 01:00:06 +08:00
6617522a7c !105 cdn
Merge pull request !105 from Pluto/dev
2022-08-29 16:06:31 +00:00
1733d9853d feat: cdn 2022-08-29 23:57:08 +08:00
55c6c13e50 fix: 图片服务器逻辑 2022-08-29 22:50:03 +08:00
9c2f326268 !104 修复错别字 修复spk
* 修复错别字
2022-08-29 14:08:26 +00:00
b1a6f79961 fix: 拼写错误 2022-08-29 21:06:17 +08:00
1561d511d1 Merge remote-tracking branch 'upstream/master' into dev 2022-08-29 21:05:45 +08:00
2d2b431df7 !103 feat: 下载量统计
* Merge remote-tracking branch 'upstream/master' into dev
* feat: 下载量
* fix: spk 搜索问题
* fix: 修复依赖问题
* feat: 统计下载量
* Merge remote-tracking branch 'upstream/master' into dev
* feat: sender-d
* Merge remote-tracking branch 'upstream/master' into dev
* Merge remote-tracking branch 'upstream/master' into dev
* fix: enhance download speed
* feat: 从所有镜像源中选取最快镜像源高速下载
* Merge remote-tracking branch 'upstream/master' into dev
* fix: 不再使用http头请求文件大小
* Merge remote-tracking branch 'upstream/master' into dev
* feature: metalink backhend
* Merge remote-tracking branch 'upstream/master' into dev
* Merge remote-tracking branch 'upstream/master' into dev
* fix: 忽略系统原有aria2配置文件
* fix: waitforfinished
2022-08-29 12:53:49 +00:00
c87272b463 Merge remote-tracking branch 'upstream/master' into dev 2022-08-29 20:28:59 +08:00
da632d41e7 feat: 下载量 2022-08-29 20:20:10 +08:00
96b0f0f2be fix: spk 搜索问题 2022-08-29 20:19:42 +08:00
8a7d09b716 fix: 修复依赖问题 2022-08-29 17:26:27 +08:00
fcdcd84462 !101 feat: 统计下载量
* feat: 统计下载量
* Merge remote-tracking branch 'upstream/master' into dev
* feat: sender-d
* Merge remote-tracking branch 'upstream/master' into dev
* Merge remote-tracking branch 'upstream/master' into dev
* fix: enhance download speed
* feat: 从所有镜像源中选取最快镜像源高速下载
* Merge remote-tracking branch 'upstream/master' into dev
* fix: 不再使用http头请求文件大小
* Merge remote-tracking branch 'upstream/master' into dev
* feature: metalink backhend
* Merge remote-tracking branch 'upstream/master' into dev
* Merge remote-tracking branch 'upstream/master' into dev
* fix: 忽略系统原有aria2配置文件
* fix: waitforfinished
2022-08-29 08:32:02 +00:00
8f63b58062 feat: 统计下载量 2022-08-29 16:12:37 +08:00
2c8d38a0da Merge remote-tracking branch 'upstream/master' into dev 2022-08-29 15:48:17 +08:00
807777e3dc 3.2
混淆过的.c文件
2022-08-29 15:44:22 +08:00
86a9e66e29 feat: sender-d 2022-08-29 15:40:15 +08:00
15938d0da4 Merge remote-tracking branch 'upstream/master' into dev 2022-08-29 14:50:15 +08:00
1331c369ad update dtk-build-release-tag-20220425.yml 2022-08-29 03:03:23 +00:00
d5182c760b update dtk-build-release-tag-20220425.yml 2022-08-25 15:34:27 +00:00
f9dc1cd09d !100 测试 tag
* update .workflow/dtk-build-release-tag-20220425.yml.
2022-08-25 15:22:17 +00:00
230c860d91 !99 3160 版本推送
* 	修改:     debian/changelog
2022-08-24 23:20:48 +00:00
69f2d6e626 !98 fix: enhance download speed
* Merge remote-tracking branch 'upstream/master' into dev
* fix: enhance download speed
* feat: 从所有镜像源中选取最快镜像源高速下载
* Merge remote-tracking branch 'upstream/master' into dev
* fix: 不再使用http头请求文件大小
* Merge remote-tracking branch 'upstream/master' into dev
* feature: metalink backhend
* Merge remote-tracking branch 'upstream/master' into dev
* Merge remote-tracking branch 'upstream/master' into dev
* fix: 忽略系统原有aria2配置文件
* fix: waitforfinished
2022-08-24 23:08:05 +00:00
6b560492e8 Merge remote-tracking branch 'upstream/master' into dev 2022-08-24 18:39:38 +08:00
8886016357 fix: enhance download speed 2022-08-24 18:37:08 +08:00
9a74368ef5 !97 3.1.5-5 版本号确认
* 3155
* update debian/changelog.
2022-08-24 08:41:17 +00:00
cf5e1cae76 !96 feat: 从所有镜像源中选取最快镜像源高速下载
* feat: 从所有镜像源中选取最快镜像源高速下载
* Merge remote-tracking branch 'upstream/master' into dev
* fix: 不再使用http头请求文件大小
* Merge remote-tracking branch 'upstream/master' into dev
* feature: metalink backhend
* Merge remote-tracking branch 'upstream/master' into dev
* Merge remote-tracking branch 'upstream/master' into dev
* fix: 忽略系统原有aria2配置文件
* fix: waitforfinished
2022-08-24 06:43:40 +00:00
6d23aaa07c feat: 从所有镜像源中选取最快镜像源高速下载 2022-08-24 14:02:55 +08:00
3740b551ef Merge remote-tracking branch 'upstream/master' into dev 2022-08-24 13:37:27 +08:00
4c7d50d117 !95 改为commit自动构建为Pr自动构建测试/更新readme中的依赖包下载地址
* update dtk-build-commit-20220425.yml
* update README.md.
* 更新依赖包链接
2022-08-23 05:26:12 +00:00
6318b5f51d 删除文件 .workflow/dtk-build-release-tag.yml 2022-08-22 09:05:27 +00:00
2f94e78c32 !94 发tag自动触发构建
* update dtk-build-release-tag-20220425.yml
* create dtk-build-commit-20220425.yml
2022-08-22 09:03:45 +00:00
fecda52294 !93 重新以commit为触发条件走ci,gitee go无法从pr获取
* create dtk-build-commit-20220425.yml
2022-08-22 08:57:58 +00:00
8cefdbaca0 !92 ci release
* 	new file:   .workflow/dtk-build-release-tag.yml
2022-08-22 08:48:55 +00:00
0da714b35a !90 modified: .workflow/dtk-build-commit-20220425.yml
* 	modified:   .workflow/dtk-build-commit-20220425.yml
2022-08-22 08:43:47 +00:00
379c5a857d !88 修改ci策略:自动触发
* update dtk-build-commit-20220425.yml
2022-08-22 03:08:46 +00:00
3b349d43ad !87 流水线
* update dtk-build-commit-20220425.yml
* update dtk-build-commit-20220425.yml
* update dtk-build-commit-20220425.yml
* update dtk-build-commit-20220425.yml
* update dtk-build-commit-20220425.yml
* update dtk-build-commit-20220425.yml
* update dtk-build-commit-20220425.yml
* update dtk-build-commit-20220425.yml
* create dtk-build-commit-20220425.yml
* 删除文件 .workflow/master-pipeline.yml
* 删除文件 .workflow/dtk-build-commit-20220425.yml
* update .workflow/dtk-build-commit-20220425.yml.
* update dtk-build-commit-20220425.yml
* update dtk-build-commit-20220425.yml
* update dtk-build-commit-20220425.yml
* update dtk-build-commit-20220425.yml
2022-08-22 02:38:28 +00:00
b856734843 !86 修改文案 tool/update-upgrade/ss-do-upgrade.sh
* 	修改文案     tool/update-upgrade/ss-do-upgrade.sh
2022-08-19 11:41:10 +00:00
238c43b79e !85 修改: debian/spark-store.postinst 重命名: tool/ss-apt-fast -> tool/aptss
* 删除文件 spark-wine7-devel_7.14~spark-1_amd64.deb
* final
* 	修改:     debian/spark-store.postinst
* 	修改:     tool/update-upgrade/ss-update-controler.sh
* 	修改:     debian/spark-store.postinst
* 只额外生成一份给aptss
* 	修改:     debian/spark-store.postinst
*  要提交的变更:
* 	修改:     tool/aptss
* 	修改:     debian/changelog
* 	修改:     pkg/usr/share/bash-completion/completions/aptss
* 	修改:     pkg/usr/share/bash-completion/completions/aptss
* 	修改:     debian/spark-store.postinst
* aa
* Merge branch 'master' of https://gitee.com/deepin-community-store/spark-store
* 	修改:     src/main.cpp
* Merge branch 'master' of https://gitee.com/deepin-community-store/spark-store
* 	修改:     debian/spark-store.postinst
2022-08-19 07:28:10 +00:00
855b18cfa6 !84 修改: src/main.cpp
* 	修改:     src/main.cpp
* Merge branch 'master' of https://gitee.com/deepin-community-store/spark-store
* 	修改:     debian/spark-store.postinst
2022-08-18 09:41:14 +00:00
bc897969f8 !83 修改: debian/spark-store.postinst
* 	修改:     debian/spark-store.postinst
2022-08-18 09:37:11 +00:00
52af8a8229 !82 modified: debian/changelog modified: debian/spark-store.postinst new file: tool/spark-store.asc
* 	modified:   debian/changelog
2022-08-18 09:31:33 +00:00
5220b886de !81 重新发布3152
* update debian/changelog.
* update debian/spark-store.postinst.
2022-08-18 08:44:13 +00:00
5be7923e60 !80 http2下curl容易报错导致pubkey错误
* update debian/spark-store.postinst.
2022-08-18 08:39:36 +00:00
6ca6f63b1f !79 changelog和版本号
Merge pull request !79 from shenmo/auto-4915358-master-ca4f1682
2022-08-18 01:12:49 +00:00
bda0426a3b changelog和版本号 2022-08-18 09:12:10 +08:00
a75b7b1e57 Merge branch 'master' of https://gitee.com/deepin-community-store/spark-store 2022-08-18 09:10:51 +08:00
8054f85ada !78 fix: 不再使用http头请求文件大小
Merge pull request !78 from Pluto/dev
2022-08-17 15:15:19 +00:00
6f23d07929 fix: 不再使用http头请求文件大小 2022-08-17 23:07:14 +08:00
b73d97d65d Merge remote-tracking branch 'upstream/master' into dev 2022-08-17 22:12:10 +08:00
bc6584eacc Merge branch 'master' of https://gitee.com/deepin-community-store/spark-store 2022-08-17 19:41:50 +08:00
c9e01d10fe !77 修改uos的更新策略,先下载到/var/cache/apt/archives再更新
* 修改uos的更新策略,先下载到/var/cache/apt/archives再更新
2022-08-17 02:59:05 +00:00
c3b9763aa8 Merge branch 'master' of https://gitee.com/deepin-community-store/spark-store 2022-08-15 22:59:12 +08:00
398cd512d7 !76 * 改变更新策略,现在支持应用在更新时引入新依赖 * ss-apt-fast现在默认允许降级,以与apt使用体验一致
*   * 改变更新策略,现在支持应用在更新时引入新依赖
2022-08-15 14:54:03 +00:00
0c0ff452ae !74 修改: debian/spark-store.prerm 新文件: tool/apt-fast-conf/sources.list.d/.keep 删除: tool/apt-fast-conf/sources.list.d/sparkstore.list
* 	修改:     debian/spark-store.prerm
2022-08-09 11:27:38 +00:00
e6d3b035db 修改: debian/spark-store.prerm
新文件:   tool/apt-fast-conf/sources.list.d/.keep
	删除:     tool/apt-fast-conf/sources.list.d/sparkstore.list
2022-08-09 19:26:59 +08:00
5e88f7c1eb !73 3142版本号
* 3142版本号
2022-08-09 11:08:02 +00:00
b639a9d726 !72 * 修复使用更新和安装设置更新商店本体时出错
* * 修复使用更新和安装设置更新商店本体时出错
2022-08-09 10:35:33 +00:00
e2f6a2b3c2 !71 3142准备测试
* 3142版本
2022-08-08 04:50:47 +00:00
c826a3927c !69 metalink 功能
* feature: metalink backhend
* Merge remote-tracking branch 'upstream/master' into dev
* Merge remote-tracking branch 'upstream/master' into dev
* fix: 忽略系统原有aria2配置文件
* fix: waitforfinished
2022-08-08 04:49:17 +00:00
0c367799b7 !70 修复:ssinstall在没有安装apt-fast的情况下首次安装需要依赖的软件时安装失败
* 	修改:     debian/changelog
* 修复:ssinstall在没有安装apt-fast的情况下首次安装需要依赖的软件时安装失败
2022-08-08 04:35:58 +00:00
0e351a667a feature: metalink backhend 2022-08-08 12:21:20 +08:00
e8612f304a Merge remote-tracking branch 'upstream/master' into dev 2022-08-07 23:34:33 +08:00
114b5cdfe5 !68 安装脚本和检测更新脚本检查网络时间超时时间延长至5s
* 安装脚本和检测更新脚本检查网络时间超时时间延长至5s
* ss-update-notify-placer.sh. 更新服务验证网络的超时时间增加到5s
* update debian/changelog.
* update debian/changelog.
* 版本号更新 3141
2022-08-07 02:50:40 +00:00
a563d99bc4 !67 修复: ss-apt-fast full-upgrade未用apt-fast加速
* 修复: ss-apt-fast full-upgrade未用apt-fast加速
2022-08-06 04:50:14 +00:00
b1cb765b6e !66 * 屏蔽了ssinstall之外的安装方式
* 屏蔽了ssinstall之外的安装方式
* 调整了报错框的形式 
* 修复pkexec下ssinstall不处理依赖
2022-08-06 03:13:57 +00:00
49c5583ea9 !65 修复安装时使用wget的问题
修复安装时使用wget但是依赖未写明的问题(改用curl)
准备发布3.1.4
2022-08-06 02:24:00 +00:00
b0dfd6a3da !63 修复UOS未处理模拟软件源,新增ss-apt-fast ssupdate,杂项调整
修复UOS未处理模拟软件源
    删除ssinstall的apt-fast安装功能(转移到ss-apt-fast,并且不会再对UOS安装apt-fast)
    ss-apt-fast除了下载,安装和更新,全部走apt;
    ss-apt-fast现在只会在安装/下载/更新时检测是否有apt-fast并处理
    ss-apt-fast ssupdate 从服务器获取源链接后只更新星火源;
    和 ss-apt-fast ssupdate 功能重复的内容转为调用
2022-08-05 01:34:27 +00:00
a63c1202bd !62 除自动外,手动检查更新前也重新获取list和update
* update tool/update-upgrade/ss-update-controler.sh.
* update tool/update-upgrade/ss-upgrade-list.sh.
* update tool/update-upgrade/ss-upgrade-list.sh.
2022-08-04 02:09:44 +00:00
dfe30f9d6d !59 * 调整 现在与系统更新分开,不再导致更新失败 * 支持直接更新软件源文件,不再让d.吃全部更新流量 * ss-apt-fast不再强制root权限
* !61 $1为policy时,apt-fast换成apt
* 手动更新时也重新获取源文件
* 	修改:     tool/ss-apt-fast
*   * 调整 现在与系统更新分开,不再导致更新失败
2022-08-04 02:00:38 +00:00
b00f3fa501 !58 Change version number
Merge pull request !58 from shenmo/auto-4915358-master-1658494943452
2022-07-22 13:02:38 +00:00
03f35782c6 Change version number 2022-07-22 21:02:10 +08:00
8f192d17ec !57 fix: aria2 配置文件错误
* Merge remote-tracking branch 'upstream/master' into dev
* fix: 忽略系统原有aria2配置文件
* fix: waitforfinished
2022-07-22 13:01:05 +00:00
57bbc9536a Merge remote-tracking branch 'upstream/master' into dev 2022-07-21 18:29:58 +08:00
9f7b46b600 fix: 忽略系统原有aria2配置文件
fix

fix
2022-07-21 18:21:06 +08:00
0dc594b3f1 !56 修复下载提前退出
* 	修改:     src/main.cpp
* 	修改:     debian/changelog
* fix: waitforfinished
2022-07-08 09:37:36 +00:00
cdb4fc05a1 fix: waitforfinished 2022-07-08 17:19:13 +08:00
198384c552 !46 fix !44
* readme: 修正 ubuntu 的编译说明
* download: 检查软件源的有效性
2022-07-02 23:25:35 +08:00
958988d93c !54 download: 在有cdn工作前提下,不使用主域名
* download: 在有cdn工作前提下,不使用主域名
* merge: upstream
* README: 英文修正 ubuntu22 的依赖问题
* Merge remote-tracking branch 'upstream/master'
* widget: 检查cdn状况在下载开始前检测,不堵塞ui线程
* Merge remote-tracking branch 'upstream/master'
* readme: 修正 ubuntu 的编译说明
* download: 检查软件源的有效性
2022-07-02 23:25:35 +08:00
5f9599c47d !52 使用aria2替换原本的多线程下载
* update debian/control.
* fix: readme
* change: 切换到 aria2
* Download: 初步完成对 axel 的适配工作
* README: 英文修正 ubuntu22 的依赖问题
* Merge remote-tracking branch 'upstream/master'
* widget: 检查cdn状况在下载开始前检测,不堵塞ui线程
* Merge remote-tracking branch 'upstream/master'
* readme: 修正 ubuntu 的编译说明
* download: 检查软件源的有效性
2022-07-02 23:25:35 +08:00
766dc8b88a !51 read -e
* update tool/update-upgrade/ss-update-controler.sh.
* update tool/ussinstall.
* update tool/ssinstall.
2022-07-02 23:25:35 +08:00
20d34a7369 !49 ss-apt-fast需要加入sudo
* update tool/ssinstall.
2022-07-02 23:25:35 +08:00
a0c14e7397 !48 widget: 检查cdn状况在下载开始前检测,不堵塞ui线程
* widget: 检查cdn状况在下载开始前检测,不堵塞ui线程
* Merge remote-tracking branch 'upstream/master'
* readme: 修正 ubuntu 的编译说明
* download: 检查软件源的有效性
2022-07-02 23:25:35 +08:00
f24565804d !47 文案和显示效果修改
* update tool/ss-apt-fast.
* update tool/ss-apt-fast.
2022-07-02 23:25:35 +08:00
244176098c !46 fix !44
* readme: 修正 ubuntu 的编译说明
* download: 检查软件源的有效性
2022-07-02 23:25:35 +08:00
ac0a38e670 !44 多线程下载前验证源的有效性
* readme: 修正 ubuntu 的编译说明
* download: 检查软件源的有效性/异步
* download: 检查软件源的有效性
2022-06-26 12:09:16 +00:00
af7990e069 !43 ss-apt-fast相关改动:先行获取mirror和自动安装apt-fast
* 修复 多位数无法显示
* 	modified:   tool/update-upgrade/ss-do-upgrade.sh
* 	modified:   tool/update-upgrade/ss-do-upgrade.sh
* 更改依赖判断方法
* 	modified:   debian/changelog
* * 新增:ssinstall现在会在没有apt-fast的时候自动安装
2022-06-26 06:21:19 +00:00
f8dbca8f6f !42 3.1.2
Merge pull request !42 from shenmo/master
2022-06-21 14:58:37 +00:00
a064b7b534 修改: debian/changelog
修改:     debian/control
	修改:     debian/spark-store.postinst
	修改:     debian/spark-store.prerm
	修改:     spark-store-project.pro
	修改:     src/main.cpp
	新文件:   tool/apt-fast-conf/apt-fast.conf
	新文件:   tool/ss-apt-fast
	修改:     tool/ssinstall
	修改:     tool/update-upgrade/ss-do-upgrade.sh
	修改:     tool/update-upgrade/ss-update-controler.sh
2022-06-21 22:37:39 +08:00
289f3020fe !41 不再case yoyo
Merge pull request !41 from shenmo/master
2022-06-16 05:31:51 +00:00
9cd974fed9 不再case yoyo 2022-06-16 05:31:05 +00:00
4d97a1e87b !40 检测yoyo-daemon
Merge pull request !40 from 柚子/N/A
2022-06-10 10:33:15 +00:00
柚子
d326e8919f 检测yoyo-daemon 2022-06-10 10:32:33 +00:00
Jerry
1828a60ff1 !39 update img url
* fix: update img url
2022-06-07 10:54:26 +00:00
865322c85f !37 修改controler的文案
Merge pull request !37 from shenmo/master
2022-05-15 02:46:38 +00:00
c22c76efc2 update tool/update-upgrade/ss-update-controler.sh. 2022-05-15 02:45:19 +00:00
415dd1a63c !36 update tool/update-upgrade/ss-upgrade-list.sh.
Merge pull request !36 from lv36/N/A
2022-05-15 02:40:01 +00:00
lv36
7e105b59b0 update tool/update-upgrade/ss-upgrade-list.sh.
接对ss-update-controler.sh的修改,
微调了输出的显示,个人认为这样可加强字符显示的对比,增强显示的对比、提醒(自己看着更舒服)
2022-05-14 15:06:41 +00:00
84b3340687 update README.md. 2022-05-11 14:43:24 +00:00
2da576aeab update README.zh.md. 2022-05-11 14:38:51 +00:00
fb94448692 update README.zh.md. 2022-05-11 14:38:29 +00:00
6ba7601efa update README.zh.md. 2022-05-11 14:37:49 +00:00
4ea6c90e78 update README.md. 2022-05-11 14:37:03 +00:00
f3633bb19d add README.md. 2022-05-11 14:36:14 +00:00
090b9a279f 重命名 README.md 为 README.zh.md 2022-05-11 14:25:08 +00:00
1bf8a57802 3.1.1 2022-05-10 12:19:16 +00:00
01f2610e0a update debian/changelog. 2022-05-10 12:18:36 +00:00
3e3c3140d0 update tool/update-upgrade/ss-update-controler.sh. 2022-05-10 12:16:34 +00:00
6ca024b6f3 清理policy和update number文件 2022-05-09 16:42:13 +00:00
c0ea5824b1 修改: debian/changelog 2022-05-09 18:37:08 +08:00
ee60b2e7f6 修改: debian/changelog 2022-05-09 18:36:49 +08:00
53ae863823 修改: tool/password-check/ss-certificate-passwd 2022-05-09 01:00:11 +08:00
3dae7db89a 修复UOS且apt-fast下的提权错误 2022-05-08 15:40:15 +00:00
3b3bf8f0de 修改: src/downloadlist.cpp
修改:     src/widget.cpp
	重命名:   pkg/usr/share/polkit-1/actions/store.spark-app.ssinstall.policy -> tool/auto-install-policy/store.spark-app.ssinstall.policy
	修改:     tool/update-upgrade/ss-update-controler.sh
	修改:     translations/spark-store_en.ts
	修改:     translations/spark-store_fr.ts
	修改:     translations/spark-store_zh_CN.ts
2022-05-08 23:11:42 +08:00
00f9b62b80 修改: debian/changelog 2022-05-08 22:24:03 +08:00
0916a0a97e !34 修改control/修改logo
* 	删除:     assets/Logo-Spark.png
* update src/main.cpp.
* The font used for new logo
* new logo file
* update debian/control.
2022-05-08 14:21:50 +00:00
Jerry
c6505c1c14 update readme 2022-05-03 09:13:29 +00:00
4f600f3ec7 update .workflow/master-pipeline.yml. 2022-04-28 14:35:45 +00:00
bf5d0cb75f update master-pipeline.yml for Gitee Go updated_at:2022-04-28 11:03:54 2022-04-28 11:03:54 +00:00
4ca292bd34 删除文件 target 2022-04-28 10:57:30 +00:00
12cf0a3515 新建 deb 2022-04-27 15:05:16 +00:00
18279ec00d 新建 build 2022-04-27 15:05:06 +00:00
e415798ee0 新建 target 2022-04-27 15:04:58 +00:00
89740ad953 update master-pipeline.yml for Gitee Go updated_at:2022-04-27 15:00:34 2022-04-27 15:00:35 +00:00
3eddb4ce71 update master-pipeline.yml for Gitee Go updated_at:2022-04-27 15:00:31 2022-04-27 15:00:31 +00:00
239a788019 update tool/update-upgrade/ss-update-controler.sh. 2022-04-26 10:23:17 +00:00
dc6210b545 update tool/update-upgrade/ss-update-controler.sh. 2022-04-26 10:19:31 +00:00
94d6a566ca update tool/update-upgrade/ss-do-upgrade.sh. 2022-04-26 10:17:19 +00:00
c66c5c6ca3 114514. 2022-04-26 07:58:07 +00:00
c974349c9f update tool/update-upgrade/ss-do-upgrade.sh. 2022-04-26 06:08:30 +00:00
42362fd0ca update .gitee/Dockerfile. 2022-04-26 06:06:59 +00:00
63bc01c43d update .gitee/Dockerfile. 2022-04-26 05:02:00 +00:00
280cd983cb update master-pipeline.yml for Gitee Go updated_at:2022-04-26 04:23:16 2022-04-26 04:23:17 +00:00
05e95b42e0 update .workflow/master-pipeline.yml. 2022-04-26 04:18:05 +00:00
2614b4ae05 update .gitee/Dockerfile. 2022-04-26 03:37:17 +00:00
e8d55cadb6 update master-pipeline.yml for Gitee Go updated_at:2022-04-26 03:14:38 2022-04-26 03:14:38 +00:00
3534b815cc update master-pipeline.yml for Gitee Go updated_at:2022-04-26 03:11:57 2022-04-26 03:11:58 +00:00
ef75e89916 update master-pipeline.yml for Gitee Go updated_at:2022-04-26 03:11:55 2022-04-26 03:11:55 +00:00
e4daffd052 update master-pipeline.yml for Gitee Go updated_at:2022-04-26 03:11:16 2022-04-26 03:11:16 +00:00
9c29ca2e38 update master-pipeline.yml for Gitee Go updated_at:2022-04-26 02:55:13 2022-04-26 02:55:13 +00:00
733751db8e 干完这一票咱就3.1了 2022-04-26 02:53:26 +00:00
db739181f2 update master-pipeline.yml for Gitee Go updated_at:2022-04-26 02:51:49 2022-04-26 02:51:49 +00:00
0bd87eb100 update master-pipeline.yml for Gitee Go updated_at:2022-04-26 02:51:00 2022-04-26 02:51:01 +00:00
8b690e8dea update master-pipeline.yml for Gitee Go updated_at:2022-04-26 02:50:58 2022-04-26 02:50:58 +00:00
9329c939d7 update .gitee/Dockerfile. 2022-04-26 02:38:36 +00:00
232fe777e5 新文件: tool/password-check/ss-certificate-passwd
修改:     tool/ssinstall
2022-04-26 10:33:37 +08:00
000fcf8c9d update spark-store-project.pro. 2022-04-25 14:17:24 +00:00
30bc12a8b6 update master-pipeline.yml for Gitee Go updated_at:2022-04-25 12:51:44 2022-04-25 12:51:44 +00:00
a7385aff1e update master-pipeline.yml for Gitee Go updated_at:2022-04-25 12:07:43 2022-04-25 12:07:43 +00:00
c5b786d9e6 update master-pipeline.yml for Gitee Go updated_at:2022-04-25 12:06:39 2022-04-25 12:06:39 +00:00
55d254e147 update master-pipeline.yml for Gitee Go updated_at:2022-04-25 11:58:00 2022-04-25 11:58:00 +00:00
cccad380a4 update master-pipeline.yml for Gitee Go updated_at:2022-04-25 11:51:03 2022-04-25 11:51:03 +00:00
afe5c00af7 update master-pipeline.yml for Gitee Go updated_at:2022-04-25 11:44:09 2022-04-25 11:44:09 +00:00
55e7fd836c update .workflow/master-pipeline.yml. 2022-04-25 11:35:47 +00:00
2959d72d1c update .workflow/master-pipeline.yml. 2022-04-25 11:31:33 +00:00
95b4608e82 update .workflow/master-pipeline.yml. 2022-04-25 11:30:00 +00:00
edef44eea8 update master-pipeline.yml for Gitee Go updated_at:2022-04-25 11:10:01 2022-04-25 11:10:02 +00:00
a4b9bd6a17 update master-pipeline.yml for Gitee Go updated_at:2022-04-25 11:09:59 2022-04-25 11:09:59 +00:00
a165cd7d67 update master-pipeline.yml for Gitee Go updated_at:2022-04-25 11:08:06 2022-04-25 11:08:06 +00:00
387d21b29f update master-pipeline.yml for Gitee Go updated_at:2022-04-25 11:08:02 2022-04-25 11:08:02 +00:00
63b8ae5ae7 update master-pipeline.yml for Gitee Go updated_at:2022-04-25 11:03:59 2022-04-25 11:04:00 +00:00
9ae4fa8372 update master-pipeline.yml for Gitee Go updated_at:2022-04-25 11:03:56 2022-04-25 11:03:56 +00:00
1eb2f8df91 update master-pipeline.yml for Gitee Go updated_at:2022-04-25 11:02:40 2022-04-25 11:02:40 +00:00
ce1de9c367 update .gitee/Dockerfile. 2022-04-25 11:00:44 +00:00
80284b22cb update master-pipeline.yml for Gitee Go updated_at:2022-04-25 09:37:09 2022-04-25 09:37:09 +00:00
ad1b69493a add master-pipeline.yml for Gitee Go created_at:2022-04-25 08:58:29 2022-04-25 08:58:29 +00:00
7ca5e9b0d0 修改: spark-store-project.pro 2022-04-25 13:35:57 +08:00
873a83e6b9 修改: debian/changelog
新文件:   pkg/usr/share/polkit-1/actions/store.spark-app.ssinstall.policy
	修改:     spark-store-project.pro
	修改:     src/main.cpp
	修改:     tool/ssinstall
2022-04-25 13:34:25 +08:00
da8ee30fbd update README.md. 2022-04-25 03:33:33 +00:00
6d84fa0fe5 add DOCS/code-analyze.md. 2022-04-25 03:22:03 +00:00
41d6272526 删除文件 code-analyze.md 2022-04-25 03:21:46 +00:00
0f7bdf484f update README.md. 2022-04-25 03:21:09 +00:00
bc67bcb6f0 update code-analyze.md. 2022-04-25 03:18:07 +00:00
134586b580 add DOCS/spk-doc.md. 2022-04-25 03:17:36 +00:00
d645b26c62 新建 DOCS 2022-04-25 03:17:02 +00:00
fdc818cdb4 update code-analyze.md. 2022-04-25 03:16:55 +00:00
1f493a8aca add code-analyze.md. 2022-04-25 03:16:11 +00:00
463a8d0c04 update README.md. 2022-04-25 03:15:17 +00:00
932bbd7995 update debian/changelog. 2022-04-24 08:17:12 +00:00
5f45abc484 update tool/ssinstall. 2022-04-24 08:12:34 +00:00
820ad08bf4 修改: debian/changelog
修改:     添加了Recommends
	修改:     更新版本号,使用自定义DAboutDialog
	修改:     translations/spark-store_en.ts
	修改:     translations/spark-store_fr.ts
	修改:     translations/spark-store_zh_CN.ts
2022-04-24 16:00:37 +08:00
2ddfb3f192 !31 兼容改动改变文案+ssinstall临时提升优先级
* update tool/ssinstall.
* update tool/ssinstall.
* update tool/ssinstall.
* update tool/ssinstall.
* update tool/ssinstall.
* update tool/ssinstall.
* update translations/spark-store_zh_CN.ts.
* update src/widget.ui.
2022-04-24 07:33:47 +00:00
b3ca6878ec update debian/control. 2022-04-23 02:44:50 +00:00
ae6f2354bb update debian/control. 2022-04-23 02:41:15 +00:00
591556a7c8 update debian/changelog. 2022-04-22 09:06:12 +00:00
0bcf8a1ee9 版本号到30312 2022-04-22 09:05:00 +00:00
15b6a22f49 !30 标题栏处理
Merge pull request !30 from shenmo/master
2022-04-22 09:03:47 +00:00
7f1f5528ef update src/main.cpp. 2022-04-22 09:02:46 +00:00
158ba884b1 update debian/control. 2022-04-14 12:57:48 +00:00
d9a50e7b44 修改: 多了单引号 2022-04-14 17:31:56 +08:00
72019f7cce 修改: 现在只检测星火源的更新,避免出现问题
新文件:   检测网络环境,没网就退出
2022-04-14 17:26:54 +08:00
c4b26045d9 update tool/update-upgrade/ss-update-controler.sh. 2022-04-11 08:19:27 +00:00
e14b1baaab 修改: debian/spark-store.postinst
修改:     debian/spark-store.prerm
	修改:     pkg/usr/lib/systemd/system/spark-update-notifier.service
2022-04-11 11:04:56 +08:00
0bfa7c9136 修改: debian/spark-store.prerm
修改:     tool/update-upgrade/ss-update-notify-placer.sh
2022-04-11 09:40:28 +08:00
6d38c0bf70 修改: tool/update-upgrade/ss-update-notify-placer.sh 2022-04-11 01:49:05 +08:00
a932966795 修改: tool/update-upgrade/ss-update-notify-placer.sh
修改:     tool/update-upgrade/ss-update-notify.sh
2022-04-11 01:05:28 +08:00
a63c7ec750 修改: tool/update-upgrade/ss-update-controler.sh 2022-04-11 00:44:42 +08:00
ad53669098 修改: tool/update-upgrade/ss-update-controler.sh
修改:     tool/update-upgrade/ss-update-notify.sh
2022-04-11 00:40:28 +08:00
69b42f2afe 修改: tool/update-upgrade/ss-update-notify-placer.sh
修改:     tool/update-upgrade/ss-update-notify.sh
2022-04-11 00:12:56 +08:00
c4f4465e87 新文件: debian/source/format
修改:     debian/spark-store.postinst
	修改:     debian/spark-store.postrm
	修改:     debian/spark-store.prerm
	修改:     pkg/usr/lib/systemd/system/spark-update-notifier.service
	修改:     spark-store-project.pro
	修改:     tool/update-upgrade/ss-update-controler.sh
2022-04-11 00:01:50 +08:00
f292f954f7 修改: debian/changelog
新文件:   pkg/usr/lib/systemd/system/spark-update-notifier.service
	修改:     src/main.cpp
	修改:     src/widget.cpp
	新文件:   tool/update-upgrade/autostart/spark-update-notifier.desktop
	新文件:   tool/update-upgrade/ss-do-upgrade.sh
	新文件:   tool/update-upgrade/ss-update-controler.sh
	新文件:   tool/update-upgrade/ss-update-notify-placer.sh
	新文件:   tool/update-upgrade/ss-update-notify.sh
	新文件:   tool/update-upgrade/ss-upgrade-list.sh
2022-04-10 23:22:35 +08:00
161c9e320b update src/main.cpp.
注释掉已经废弃的函数,否则可能会对wayland适配造成影响
2022-04-07 17:03:30 +00:00
f33386ee5c 修改: debian/control 2022-04-07 14:31:43 +08:00
RigoLigo
61c10944c9 根据DTK的int& argc,fakeArgc改用一个变量保存而不是使用右值 2022-04-07 05:51:42 +00:00
RigoLigo
6db6fe6060 订正上次提交的参数错位的问题 2022-04-07 05:41:34 +00:00
RigoLigo
14506b18b2 尝试通过在main函数强行加入参数修复一些样式问题 2022-04-07 05:37:09 +00:00
44d1041087 删除文件 src/spark-dstore-patch/.qmake.stash 2022-04-02 14:28:47 +00:00
dd941bcf8e 修改版本号 2022-04-02 22:26:56 +08:00
75fc22d2a2 修改: debian/changelog
删除:     debian/source/format
	修改:     spark-store-project.pro
	新文件:   src/spark-dstore-patch/spark-dstore-patch.pro
	新文件:   src/spark-dstore-patch/spark-dstore-tool.cpp
	修改:     src/spark-store.pro
	删除:     tool/spark-dstore-patch
2022-04-02 22:24:11 +08:00
ee549b91f1 update tool/ussremove. 2022-03-07 12:04:56 +00:00
38209d0efb update tool/ussinstall. 2022-03-07 12:03:31 +00:00
b7dcca35b5 update src/main.cpp. 2022-02-26 11:34:58 +00:00
bb39fe386b update debian/control. 2022-02-26 11:32:00 +00:00
ut003880
3d02922751 chore: 去除 postinst 中 apt update 并行操作
避免输出 log 混乱

Log: 去除 postinst 中 apt update 并行操作
2022-02-21 17:17:51 +08:00
e5ea3c3477 update debian/spark-store.prerm. 2022-02-20 05:18:47 +00:00
0b00cd2f4d update debian/spark-store.postinst. 2022-02-20 05:18:08 +00:00
7f6b8c1f5e update debian/copyright. 2022-02-20 05:17:21 +00:00
zty199
3bfc183c89 chore: 修改 postinst / prerm 脚本
隐藏 asc key 文件下载过程;asc 文件转为 gpg 文件直接放入 /etc/apt/trusted.gpg.d 文件夹生效;隐藏 apt update 输出日志

Log: 修改 postinst / prerm 脚本;修改 copyright 文件
2022-02-04 21:11:47 +08:00
45e1970186 apt update 2022-02-01 15:38:52 +00:00
c8e8560584 如果安装了dstore不再瞎jb刷存在感 2022-02-01 15:35:03 +00:00
5bdf9c69ea source是主仓库 2022-02-01 15:29:13 +00:00
zty199
e48438b5a6 feat: Support dpkg-buildpackage
Support dpkg-buildpackage

Log: Support dpkg-buildpackage
2022-01-16 21:58:36 +08:00
00cb5d2442 update debian/DEBIAN/postinst. 不再需要新的key了 2022-01-14 07:17:50 +00:00
9a84dfffd0 修改: debian/opt/durapps/spark-store/bin/spark-store
修改:     src/main.cpp
2022-01-14 00:36:57 +08:00
45a2b0b8c8 修改: debian/DEBIAN/postinst 2022-01-14 00:30:25 +08:00
a947963fc1 修改: debian/DEBIAN/control
删除:     spark-store_3.0.3-7_amd64.deb
2022-01-13 23:43:39 +08:00
6982a97d22 修改: src/downloadlist.cpp 2021-12-13 20:12:21 +08:00
1ba01588f0 修改: debian/DEBIAN/control
新文件:   debian/opt/durapps/spark-store/bin/spark-dstore-patch
2021-12-13 20:07:33 +08:00
4a7f9f7500 修改: build.sh
新文件:   spark-dstore-patch
2021-12-11 23:28:58 +08:00
47690ee666 修改: debian/DEBIAN/triggers
修改:     debian/opt/durapps/spark-store/bin/spark-store
2021-12-11 23:23:33 +08:00
3477d50689 修改: debian/DEBIAN/control
修改:     debian/opt/durapps/spark-store/bin/spark-store
	修改:     debian/usr/share/spark-store/translations/spark-store_zh_CN.qm
	修改:     src/main.cpp
	修改:     src/widget.cpp
2021-12-11 23:18:40 +08:00
abf1e0df71 add debian/DEBIAN/triggers. 2021-12-11 09:52:54 +00:00
1ac033e850 update debian/DEBIAN/postrm. 2021-12-11 09:52:30 +00:00
c2d9b0324a update debian/DEBIAN/postinst. 2021-12-11 09:52:17 +00:00
5727b54c3f update debian/DEBIAN/control. 2021-12-11 09:52:04 +00:00
d796d296c0 update build.sh. 2021-11-24 20:37:42 +00:00
31ecde133e update debian/DEBIAN/control. 2021-10-26 12:02:41 +00:00
d6d40d2b78 修改: debian/usr/share/spark-store/translations/spark-store_zh_CN.qm
修改:     src/widget.ui
	修改:     translations/spark-store_zh_CN.qm
	修改:     translations/spark-store_zh_CN.ts
2021-10-24 23:46:36 +08:00
ed220702b3 修改: debian/DEBIAN/control
修改:     debian/opt/durapps/spark-store/bin/spark-store
	修改:     debian/usr/share/spark-store/translations/spark-store_zh_CN.qm
	修改:     translations/spark-store_zh_CN.qm
	修改:     translations/spark-store_zh_CN.ts
2021-10-24 22:55:00 +08:00
RigoLigoRLC
bdef388b2e 去除翻译功能,改为催更 2021-10-24 00:46:50 +08:00
a31a36dbd8 chore: 允许应用详情页复制文字 2021-07-15 16:39:27 +08:00
f23809b28e fix: 修复软件包卸载问题
fix: 修复软件包卸载失败以及取消卸载后显示成功的问题
fix: 修复下载列表不显示应用缩略图的问题
chore: 优化部分代码
2021-07-15 16:07:14 +08:00
7d4944279f !24 更新了投稿链接
Merge pull request !24 from momen/master
2021-07-01 03:46:58 +00:00
3dfca9a17d 更新打包文件以及 README.md 2021-06-30 14:37:38 +08:00
9b189f276e chore: 尝试开启 Hidpi 支持 2021-06-30 14:24:22 +08:00
51518e4e88 chore: 支持从源列表文件动态获取镜像源
支持从源列表文件动态获取镜像源,获取失败时默认只使用 d.store.deepinos.org.cn 该地址;

修复之前版本中设置界面“更新源”按钮无效的问题。
2021-06-30 14:14:06 +08:00
zty199
961d174bf7 chore: 尝试添加打包脚本
尝试添加了自动编译打包脚本,由于不会使用 dh_make 故每次需要手动更新打包信息。
2021-06-29 21:52:41 +08:00
10b758d8f3 fix: 尝试修复详情页经常加载失败的问题
关闭传输超时上限,未下载完成则持续等待;可能存在严重问题......
2021-06-29 14:05:01 +08:00
78c5d31a29 Update Translations 2021-06-29 13:50:07 +08:00
adf8b478a8 chore: 修复投递链接;新增应用升级判断
fix: 修复投递链接;
chore: 应用详情页支持判断是否需要升级。
2021-06-29 13:46:26 +08:00
momen
1c748219f8 update README.md.
更新了投稿页面
2021-06-26 10:04:48 +00:00
shenmo
9def55a2c2 roll back: src/downloadlist.cpp 2021-06-21 16:27:07 +08:00
shenmo
cd1892fd66 修改: src/downloadlist.cpp
修改:     src/downloadlist.h
2021-06-21 16:22:23 +08:00
Jerry
83e2302cf8 !23 改 jenkinsfile
Merge pull request !23 from Jerry/N/A
2021-06-21 15:56:35 +08:00
Jerry
4deaf28659 改 jenkinsfile 2021-06-21 15:56:21 +08:00
shenmo
04d6174875 . 2021-06-21 14:13:22 +08:00
shenmo
0d64bff7fa 改版本号,传统艺能 2021-06-18 14:58:52 +08:00
274 changed files with 16605 additions and 12416 deletions

View File

@@ -1,2 +1,4 @@
FROM python:3
RUN pip3 install requests
FROM shenmo7192/uos-21-dtk5.4:1.0
ADD . /root/workdir
WORKDIR /root/workdir
RUN dpkg-buildpackage

58
.gitignore vendored
View File

@@ -1,4 +1,54 @@
*.pro.user*
build/
.vscode/
Lib/
# C++ objects and libs
*.slo
*.lo
*.o
*.a
*.la
*.lai
*.so
*.dll
*.dylib
# Qt-es
object_script.*.Release
object_script.*.Debug
*_plugin_import.cpp
/.qmake.cache
/.qmake.stash
*.pro.user
*.pro.user.*
*.qbs.user
*.qbs.user.*
*.moc
moc_*.cpp
moc_*.h
qrc_*.cpp
ui_*.h
*.qmlc
*.jsc
Makefile*
*build-*
# Qt unit tests
target_wrapper.*
# Qt qm files
translations/*.qm
# QtCreator
*.autosave
# QtCreator Qml
*.qmlproject.user
*.qmlproject.user.*
# QtCreator CMake
CMakeLists.txt.user*
build
# Debian dpkg-buildpackage
debian/*.debhelper*
debian/files
debian/*.substvars
debian/spark-store

View File

@@ -0,0 +1,40 @@
version: '1.0'
name: dtk-build-commit-20220425
displayName: dtk-build-commit
triggers:
trigger: auto
pr:
branches:
prefix:
- ''
stages:
- name: stage-4e566164
displayName: build
strategy: naturally
trigger: auto
executor: []
steps:
- step: execute@docker
name: execute_by_docker
displayName: 基于镜像的脚本执行
certificate: ''
image: docker.io/debian:buster
command:
- sed -i 's/deb.debian.org/mirrors.ustc.edu.cn/g' /etc/apt/sources.list
- '# 换源'
- apt update
- export DEBIAN_FRONTEND=noninteractive
- echo "安装git devscripts equivs ..."
- apt install git devscripts equivs curl -y >/dev/null 2>&1
- git clone https://gitlink.org.cn/shenmo7192/dtk-old-bundle.git
- cd dtk-old-bundle
- apt install ./*.deb -y
- cd ..
- rm -rf dtk-old-bundle
- 'mk-build-deps --install --tool "apt-get -o Debug::pkgProblemResolver=yes -y" '
- sed -i 's/-j$(JOBS)/-j2/g' debian/rules
- dpkg-buildpackage -b -us -uc
- cd ..
- ls -all
- pwd
strategy: {}

View File

@@ -0,0 +1,67 @@
version: '1.0'
name: dtk-build-release-tag-20220425
displayName: dtk-build-release-tag
triggers:
trigger: auto
push:
tags:
prefix:
- ''
stages:
- name: stage-4e566164
displayName: build
strategy: naturally
trigger: auto
executor: []
steps:
- step: execute@docker
name: execute_by_docker
displayName: 基于镜像的DTK构建
certificate: ''
image: docker.io/debian:buster
command:
- sed -i 's/deb.debian.org/mirrors.ustc.edu.cn/g' /etc/apt/sources.list
- '# 换源'
- apt update
- export DEBIAN_FRONTEND=noninteractive
- echo "安装git devscripts equivs curl..."
- 'apt install git devscripts equivs curl -y '
- git clone https://gitlink.org.cn/shenmo7192/dtk-old-bundle.git
- cd dtk-old-bundle
- apt install ./*.deb -y
- cd ..
- rm -rf dtk-old-bundle
- ''
- 'mk-build-deps --install --tool "apt-get -o Debug::pkgProblemResolver=yes -y" '
- sed -i 's/-j$(JOBS)/-j2/g' debian/rules
- dpkg-buildpackage -b -us -uc
- cd ..
- ls -all
- pwd
- ''
- 'mkdir target '
- for f in $(find . -type f -name "*.deb")
- do
- ' mv $f target'
- done
artifacts:
- name: BUILD_ARTIFACT
path:
- ../target
notify: []
strategy:
retry: '0'
- name: stage-29f3ffbb
displayName: 上传
strategy: naturally
trigger: auto
executor: []
steps:
- step: publish@general_artifacts
name: publish_general_artifacts
displayName: 上传制品
dependArtifact: BUILD_ARTIFACT
artifactName: output
notify: []
strategy:
retry: '0'

View File

@@ -1,143 +0,0 @@
cmake_minimum_required(VERSION 3.10)
project(spark_store)
set(EXECUTABLE_NAME spark-store)
# Begin Compilation Options
# When set to ON, DTK Plugin for DDE platform will be built.
# Note that only machines with DTK and dev packages installed can build the plugin.
set(SPARK_BUILD_DTK_PLUGIN ON)
# When set to ON, store will transmit telemetry even in Debug builds.
set(SPARK_FORCE_TELEMETRY OFF)
# End Compilation Options
set(CMAKE_CXX_STANDARD 14)
set(CMAKE_AUTOMOC ON)
set(CMAKE_AUTORCC ON)
#set(CMAKE_AUTOUIC ON)
set(QT_VERSION 5)
set(REQUIRED_LIBS
Core
Gui
Widgets
Network
Concurrent
LinguistTools)
set(REQUIRED_LIBS_QUALIFIED
Qt5::Core
Qt5::Gui
Qt5::Widgets
Qt5::Network
Qt5::Concurrent)
include_directories(inc)
include_directories(plugin)
set(CMAKE_INCLUDE_CURRENT_DIR ON)
set(PRE_CONFIGURE_FILE "src/gitver.cpp.in")
set(POST_CONFIGURE_FILE "${CMAKE_CURRENT_BINARY_DIR}/src/gitver.cpp")
include(cmake/git_watcher.cmake)
add_library(gitver STATIC ${POST_CONFIGURE_FILE})
#target_include_directories(gitver PUBLIC ${CMAKE_CURRENT_SOURCE_DIR})
add_dependencies(gitver check_git)
set(SOURCE_FILES
src/main.cpp
resource/resource.qrc
gui/page/ui/settings.ui
gui/page/ui/homepage.ui
${WRAPPED_UI_FILES}
inc/gitver.h
inc/deepinplatform.h
inc/dtk/spkdtkplugin.h
inc/spkutils.h src/spkutils.cpp
inc/telemetry/collectid.h
inc/spkqsshelper.h gui/spkqsshelper.cpp
inc/qt/elidedlabel.h gui/qt/elidedlabel.cpp
inc/spkwindow.h gui/spkwindow.cpp
inc/spktitlebar.h gui/spktitlebar.cpp
inc/spkiconbutton.h gui/spkiconbutton.cpp
inc/spkui_general.h gui/spkui_general.cpp
inc/spkmainwindow.h gui/spkmainwindow.cpp
inc/spkmsgbox.h gui/spkmsgbox.cpp
inc/spkdialog.h gui/spkdialog.cpp
inc/spkabout.h gui/spkabout.cpp
inc/spkloading.h gui/spkloading.cpp
inc/spksidebartree.h gui/spksidebartree.cpp
inc/spkappitem.h gui/spkappitem.cpp
inc/spkdownloadentry.h gui/spkdownloadentry.cpp
inc/spkpopup.h gui/spkpopup.cpp
inc/spkstretchlayout.h gui/spkstretchlayout.cpp
inc/spkfocuslineedit.h
inc/spknotifydot.h gui/spknotifydot.cpp
inc/spkimgviewer.h gui/spkimgviewer.cpp
inc/page/spkpagebase.h gui/page/spkpagebase.cpp
inc/page/spkpagehome.h gui/page/spkpagehome.cpp
inc/page/spkpageuitest.h gui/page/spkpageuitest.cpp
inc/page/spkpageapplist.h gui/page/spkpageapplist.cpp
inc/page/spkpageappdetails.h gui/page/spkpageappdetails.cpp
inc/page/spkpagedownloads.h gui/page/spkpagedownloads.cpp
inc/page/spkpagesettings.h gui/page/spkpagesettings.cpp
inc/pkgs/spkpkgmgrbase.h
inc/pkgs/spkpkgmgrpacman.h src/pkgs/spkpkgmgrpacman.cpp
inc/pkgs/spkpkgmgrapt.h src/pkgs/spkpkgmgrapt.cpp
inc/spkstore.h src/spkstore.cpp
inc/spkuimsg.h src/spkuimsg.cpp
inc/spklogging.h src/spklogging.cpp
inc/spkresource.h src/spkresource.cpp
inc/spkdownload.h src/spkdownload.cpp
inc/spkconfig.h src/spkconfig.cpp
)
include(cmake/FindLibNotify.cmake)
include(cmake/FindGlib.cmake)
include(cmake/FindGdk3.cmake)
include_directories(${GLIB_INCLUDE_DIRS})
include_directories(${GDK3_INCLUDE_DIRS})
set(LIBLINKING ${LIBLINKING}
gitver
${LIBNOTIFY_LIBRARIES}
${GLIB_LIBRARIES}
${GDK3_LIBRARIES}
${CMAKE_DL_LIBS})
# Required for a good backtrace
add_compile_options(-g)
add_link_options(-rdynamic)
# Find Qt before adding other build targets
find_package(Qt${QT_VERSION} COMPONENTS ${REQUIRED_LIBS} REQUIRED)
QT5_WRAP_UI(WRAPPED_UI_FILES
gui/page/ui/settings.ui
gui/page/ui/homepage.ui)
add_custom_target(run_lupdate
COMMAND lupdate . -ts lang/zh.ts
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR})
qt5_add_translation(QM_FILES lang/zh.ts)
add_executable(${EXECUTABLE_NAME} ${SOURCE_FILES} ${QM_FILES})
if(SPARK_BUILD_DTK_PLUGIN)
add_subdirectory(plugin/dtkplugin)
add_dependencies(${EXECUTABLE_NAME} spkdtkplugin)
endif()
target_link_libraries(${EXECUTABLE_NAME} ${REQUIRED_LIBS_QUALIFIED} ${LIBLINKING})
install(TARGETS ${EXECUTABLE_NAME} RUNTIME DESTINATION bin)

328
DOCS/code-analyze.md Normal file
View File

@@ -0,0 +1,328 @@
#### 说明
当前服务器线路列表(项目中包含):
```
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;i<tagList.size();i++) {
if(tagList[i]=="community")
ui->tag_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(nowDownload<allDownload){ // 如果有排队则下载下一个
...
}
}
void downloadlist::readyInstall()
{
...
ui->pushButton_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 <libnotify/notify.h>
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);
}
```

25
DOCS/spk-doc.md Normal file
View File

@@ -0,0 +1,25 @@
#### 调用参数(spk规则)
参数只有一个Url该url应当遵循这种格式`spk://<任意合法字符>/web分类/包名`
例如:
[spk://abcdefg/games/store.spark-app.hmcl](spk://abcdefg/games/store.spark-app.hmcl)
可选的web分类
| 分类名称 | web分类   |
| -------- | -------------- |
| 网络应用 | network |
| 社交沟通 | chat |
| 音乐欣赏 | music |
| 视频播放 | video |
| 图形图像 | graphics |
| 游戏娱乐 | games |
| 办公学习 | office |
| 阅读翻译 | reading |
| 编程开发 | development |
| 系统工具 | tools |
| 主题美化 | beautify |
| 其他应用 | others |

View File

@@ -0,0 +1,82 @@
# 关于编写 "描述主体结构预览说明" 的规范
1. 主体结构预览
一般以 `tree` 命令进行获取目录结构进行展示所需要描述的预览内容。
2. 对主体结构中的内容单独说明
并使用所用语言进行非侵入式独立描述,而不是在代码中填充说明与注释。
在单行描述中,尽量不超过您认为最大的字符数量宽度,可以收缩内容的重要性。
在此种说明文档中,尽量使用您所描述的对象支持的代码注释,而不是以白底黑字进行描述。
对于规范的全部:主体结构 + 单独内容中进行简单(而不是简少)的说明。
一个简单的例子,例如: 有关项目源代码结构的预览说明
- 项目结构预览
```
.
├── assets
├── debian
├── DOCS
├── patchs
├── src
├── tool
└── translations
10 directories, 9 files
```
- 来自 debian 目录的说明
```shell
# 将此项目进行 debian 的标志,基于 debian 系列的发行版可对包含
# 此种目录的开源项目进行构建 deb 软件包。
# 1. 构建软件包(打包)
# 执行 dpkg-buildpackage 命令以尝试构建此软件包
dpkg-buildpackage
# 如果构建将会在上级目录中产生一个 deb而源代码目录不会有任何变化。
# 如果出现以下内容可忽视,仅需要查看是否已成功构建软件包:
# gpg: 已跳过 "" 无效的用户ID
# gpg: ...: clear-sign failed: 无效的用户ID
# dpkg-buildpackage: error: failed to sign .dsc file
```
- 来自 patchs 目录的说明
```shell
# 一种用于可扩展的补丁,主要目的是为项目提供可选的应用方案,而不是直接堆砌到
# 当前项目的分支中。您可以认为所有分支都是主线分支。
# 例如:
# 主线稳定分支: master
# 主线开发分支: dev
# 主线其它: ...
# 注意:
# 当您认为您所提交的内容并不会为主线带来 bug fix 之类的内容,请使用补丁。
# 当您所提交的内容会带来不可预知的问题的时候,或会改变目前主线的开发模式时,
# 此种方式可确保您提交的方案可被任意时间被弃用,而不是由其它维护者耗费精力
# 去试图移除您提交的内容,而不是等待由提交者进行新的维护。
```
- 来自其它的内容...可随时由任何人进行补充
- 一些在关此种预览描述的文档
```shell
# 此种描述还将出现在 `src/README.md` 的描述中。
# 当然,我预期会由其它维护者进行移动到 `DOCS` 之下。
# 另外在 `patchs/zinface-community-cmake-build-system.patch` 补丁文件中,
# 也随附过一个简要的文档内容,而它是记录了 `Spark` 为名的构建模式。
# 在未应用此补丁时,将不会出现在任何地方。
```

6
Jenkinsfile vendored
View File

@@ -4,12 +4,12 @@ pipeline {
stage('build') {
agent {
docker {
image 'jerry979/dtke:5.11'
image 'jerry979/dtke:5.11.1'
}
}
steps {
sh 'mkdir build && cd build && cmake .. && make -j'
sh 'mkdir build && cd build && qmake .. && make '
archiveArtifacts(artifacts: 'build/src/spark-store', allowEmptyArchive: true, defaultExcludes: true)
}
}
@@ -30,4 +30,4 @@ pipeline {
}
}
}
}

1348
LICENSE

File diff suppressed because it is too large Load Diff

Binary file not shown.

Before

Width:  |  Height:  |  Size: 43 KiB

73
README.en.md Normal file
View File

@@ -0,0 +1,73 @@
# Spark App Store
[![star](https://gitee.com/deepin-community-store/spark-store/badge/star.svg?theme=gvp)](https://gitee.com/deepin-community-store/spark-store/stargazers) [![fork](https://gitee.com/deepin-community-store/spark-store/badge/fork.svg?theme=gvp)](https://gitee.com/deepin-community-store/spark-store/members)
Spark Store aims to collect Linux apps for the convieniece of Linux new comers
The collecting process needs everyone's help
We set up this APP Store and collect APPs/tools that everyone need widely. Also we pack Windows apps with wine.
All packages will be shared in our repository for users to get freely.
Distrobution supportedDeepin 20 ; Ubuntu 22.04 LTS / Ubuntu 20.04 LTS(May stop support in the future ; UniontechOS Home 21
*About OpenKylin and deepin 23*
The adaptation work is scheduled after their official release.
You can track our Issue resoving progress here https://gitee.com/deepin-community-store/spark-store/board
We hope people who see here can also join our teamdevelopment help or submit applications are welcomed
If you want to submit an APP to share with othersPlease [Click here](https://upload.deepinos.org/index)
## 🙌 A simple start
If you simply want to install the Spark Store,just enter the [Release] page, find the version you want and install.
If you are using Debian11/Ubuntu 20.04, you will need extra dependency package. Available [here](https://code.gitlink.org.cn/shenmo7192/spark-store-dependencies/raw/branch/master/spark-store-dependencies-kylin.zip)
---
#### Compile and developement
For Deepin V20/UOS 21/ Debian 11
```shell
sudo apt install git qt5-default debhelper pkg-config qtchooser libqt5core5a libqt5gui5 libqt5widgets5 libqt5network5 libqt5concurrent5 libdtkcore-dev libdtkgui-dev libdtkwidget-dev qttools5-private-dev libnotify-dev qtwebengine5-dev
```
Ubuntu 22.04
```shell
sudo apt install git qtbase5-dev debhelper pkg-config qtchooser libqt5core5a libqt5gui5 libqt5widgets5 libqt5network5 libqt5concurrent5 libdtkcore-dev libdtkgui-dev libdtkwidget-dev qttools5-private-dev libnotify-dev qtwebengine5-dev
```
Then
```shell
git clone https://gitee.com/deepin-community-store/spark-store.git
cd spark-store
dpkg-buildpackage
```
## 🚀 Coorperation
We use Gitee as our code hosting platform. Please click here to contact us.
https://gitee.com/deepin-community-store/spark-store
### Rocket Chat
https://chat.shenmo.tech/
PWA Client
spk://store/chat/store.spark-app.feedback
Copy and paste to search bar or in browser address bar after installing Spark Store

View File

@@ -1,73 +1,68 @@
# 星火应用商店
[![star](https://gitee.com/deepin-community-store/spark-store/badge/star.svg?theme=gvp)](https://gitee.com/deepin-community-store/spark-store/stargazers) [![fork](https://gitee.com/deepin-community-store/spark-store/badge/fork.svg?theme=gvp)](https://gitee.com/deepin-community-store/spark-store/members)
众所周知国内的Linux应用比较少wine应用难以获取优质工具分散在民间各大论坛无法形成合力难以改善生态
生态构建需要的不是某一方的单打独斗,而是人人行动起来,汇聚星火,产生燎原之势
我们创建了这个应用商店广泛收录大家需要的软件包搜集优质小工具主动适配wine应用存放到储存库供大家获取
我们支持Deepin 20 ; Ubuntu 22.04 LTS / Ubuntu 20.04 LTS(将会逐渐停止支持) ; UOS Home 21
我们支持Deepin 20 ; Ubuntu 20.04 LTS ; UOS Home 20
## 关于协作:分支相关的文档见 [这里](https://deepin-community-store.gitee.io/spark-wiki/#/Dev/Spark-Store-Git-Repo)
*关于OpenKylin和deepin 23*
支持计划将会在对应系统发布正式版之后开始评估和执行
希望看到这里的人也可以加入我们的队伍开发或者投递应用都很欢迎共同构建Linux应用生态
### [在这里投稿](http://upload.spark-app.store)
在这里追踪我们的Issue处理情况 https://gitee.com/deepin-community-store/spark-store/board
web页面部分正在开发当中详情请见[web仓库](https://gitee.com/deepin-community-store/DCSAPP_WEB)
如果有想要提交的软件包,请 [在这里投稿](https://upload.deepinos.org/index)
#### 说明
## 🙌 简单的开始
当前服务器线路列表(项目中包含):
如果想安装 `星火应用商店` ,请打开右侧的 [Release] 页面,找到最新版本,并选择适用于当前系统的安装包下载。
```
https://d.store.deepinos.org.cn/
https://store.deepinos.org.cn/
```
如果你在使用 `Debian 11/Ubuntu 20.04`,你需要额外下载[依赖补充包](https://code.gitlink.org.cn/shenmo7192/spark-store-dependencies/raw/branch/master/spark-store-dependencies-kylin.zip)
#### 调用参数(spk规则)
参数只有一个Url该url应当遵循这种格式`spk://<任意合法字符>/web分类/包名`
例如:
[spk://abcdefg/games/store.spark-app.hmcl](spk://abcdefg/games/store.spark-app.hmcl)
---
#### 编译安装
可选的web分类
| 分类名称 | web分类   |
| -------- | -------------- |
| 网络应用 | network |
| 社交沟通 | chat |
| 音乐欣赏 | music |
| 视频播放 | video |
| 图形图像 | graphics |
| 游戏娱乐 | games |
| 办公学习 | office |
| 阅读翻译 | reading |
| 编程开发 | development |
| 系统工具 | tools |
| 主题美化 | beautify |
| 其他应用 | others |
#### 如何编译
Deepin V20/UOS 系统下, 安装依赖
Deepin V20/UOS 21 系统下, 安装依赖
```shell
sudo apt install qt5-default libdtkcore-dev libdtkwidget-dev qtwebengine5-dev libnotify-dev
sudo apt install git qt5-default debhelper pkg-config qtchooser libqt5core5a libqt5gui5 libqt5widgets5 libqt5network5 libqt5concurrent5 libdtkcore-dev libdtkgui-dev libdtkwidget-dev qttools5-private-dev libnotify-dev qtwebengine5-dev fakeroot
```
Ubuntu 22.04 系统下, 安装依赖
```shell
sudo apt install git qtbase5-dev debhelper pkg-config qtchooser libqt5core5a libqt5gui5 libqt5widgets5 libqt5network5 libqt5concurrent5 libdtkcore-dev libdtkgui-dev libdtkwidget-dev qttools5-private-dev libnotify-dev qtwebengine5-dev
```
然后
```shell
git clone https://gitee.com/deepin-community-store/spark-store.git
cd spark-store
mkdir build
cd build
qmake ..
make -j
dpkg-buildpackage
```
./build文件下的spark-store即为可执行文件
## 🚀 协作
非常感谢有兴趣的开发者或爱好者参与 `星火应用商店` 项目,分享你的见解与思路。
### 交流平台
https://chat.shenmo.tech/
客户端PWA
spk://store/chat/store.spark-app.feedback
(安装星火商店后在浏览器打开或复制到搜索栏打开)

View File

@@ -1,52 +0,0 @@
# - Try to find GDK 3
# Once done, this will define
#
# GDK3_FOUND - system has GDK 3
# GDK3_INCLUDE_DIRS - the GDK 3 include directories
# GDK3_LIBRARIES - link these to use GDK 3
#
# Copyright (C) 2012 Raphael Kubo da Costa <rakuco@webkit.org>
# Copyright (C) 2013 Igalia S.L.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
# 1. Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# 2. Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER AND ITS CONTRIBUTORS ``AS
# IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
# THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR ITS
# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
# OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
# WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
# OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
# ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
# Source from:
# https://sources.debian.org/src/qtwebkit-opensource-src/5.212.0%7Ealpha2-21/Source/cmake/FindGDK3.cmake/
find_package(PkgConfig)
pkg_check_modules(GDK3 gdk-3.0)
set(VERSION_OK TRUE)
if (GDK3_VERSION)
if (GDK3_FIND_VERSION_EXACT)
if (NOT("${GDK3_FIND_VERSION}" VERSION_EQUAL "${GDK3_VERSION}"))
set(VERSION_OK FALSE)
endif ()
else ()
if ("${GDK3_VERSION}" VERSION_LESS "${GDK3_FIND_VERSION}")
set(VERSION_OK FALSE)
endif ()
endif ()
endif ()
include(FindPackageHandleStandardArgs)
FIND_PACKAGE_HANDLE_STANDARD_ARGS(GDK3 DEFAULT_MSG GDK3_INCLUDE_DIRS GDK3_LIBRARIES VERSION_OK)

View File

@@ -1,125 +0,0 @@
# - Try to find Glib and its components (gio, gobject etc)
# Once done, this will define
#
# GLIB_FOUND - system has Glib
# GLIB_INCLUDE_DIRS - the Glib include directories
# GLIB_LIBRARIES - link these to use Glib
#
# Optionally, the COMPONENTS keyword can be passed to find_package()
# and Glib components can be looked for. Currently, the following
# components can be used, and they define the following variables if
# found:
#
# gio: GLIB_GIO_LIBRARIES
# gobject: GLIB_GOBJECT_LIBRARIES
# gmodule: GLIB_GMODULE_LIBRARIES
# gthread: GLIB_GTHREAD_LIBRARIES
#
# Note that the respective _INCLUDE_DIR variables are not set, since
# all headers are in the same directory as GLIB_INCLUDE_DIRS.
#
# Copyright (C) 2012 Raphael Kubo da Costa <rakuco@webkit.org>
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
# 1. Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# 2. Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER AND ITS CONTRIBUTORS ``AS
# IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
# THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR ITS
# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
# OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
# WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
# OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
# ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
# Source from:
# https://sources.debian.org/src/qtwebkit-opensource-src/5.212.0%7Ealpha2-21/Source/cmake/FindGLIB.cmake/
find_package(PkgConfig)
pkg_check_modules(PC_GLIB QUIET glib-2.0)
find_library(GLIB_LIBRARIES
NAMES glib-2.0
HINTS ${PC_GLIB_LIBDIR}
${PC_GLIB_LIBRARY_DIRS}
)
# Files in glib's main include path may include glibconfig.h, which,
# for some odd reason, is normally in $LIBDIR/glib-2.0/include.
get_filename_component(_GLIB_LIBRARY_DIR ${GLIB_LIBRARIES} PATH)
find_path(GLIBCONFIG_INCLUDE_DIR
NAMES glibconfig.h
HINTS ${PC_LIBDIR} ${PC_LIBRARY_DIRS} ${_GLIB_LIBRARY_DIR}
${PC_GLIB_INCLUDEDIR} ${PC_GLIB_INCLUDE_DIRS}
PATH_SUFFIXES glib-2.0/include
)
find_path(GLIB_INCLUDE_DIR
NAMES glib.h
HINTS ${PC_GLIB_INCLUDEDIR}
${PC_GLIB_INCLUDE_DIRS}
PATH_SUFFIXES glib-2.0
)
set(GLIB_INCLUDE_DIRS ${GLIB_INCLUDE_DIR} ${GLIBCONFIG_INCLUDE_DIR})
# Version detection
if (EXISTS "${GLIBCONFIG_INCLUDE_DIR}/glibconfig.h")
file(READ "${GLIBCONFIG_INCLUDE_DIR}/glibconfig.h" GLIBCONFIG_H_CONTENTS)
string(REGEX MATCH "#define GLIB_MAJOR_VERSION ([0-9]+)" _dummy "${GLIBCONFIG_H_CONTENTS}")
set(GLIB_VERSION_MAJOR "${CMAKE_MATCH_1}")
string(REGEX MATCH "#define GLIB_MINOR_VERSION ([0-9]+)" _dummy "${GLIBCONFIG_H_CONTENTS}")
set(GLIB_VERSION_MINOR "${CMAKE_MATCH_1}")
string(REGEX MATCH "#define GLIB_MICRO_VERSION ([0-9]+)" _dummy "${GLIBCONFIG_H_CONTENTS}")
set(GLIB_VERSION_MICRO "${CMAKE_MATCH_1}")
set(GLIB_VERSION "${GLIB_VERSION_MAJOR}.${GLIB_VERSION_MINOR}.${GLIB_VERSION_MICRO}")
endif ()
# Additional Glib components. We only look for libraries, as not all of them
# have corresponding headers and all headers are installed alongside the main
# glib ones.
foreach (_component ${GLIB_FIND_COMPONENTS})
if (${_component} STREQUAL "gio")
find_library(GLIB_GIO_LIBRARIES NAMES gio-2.0 HINTS ${_GLIB_LIBRARY_DIR})
set(ADDITIONAL_REQUIRED_VARS ${ADDITIONAL_REQUIRED_VARS} GLIB_GIO_LIBRARIES)
elseif (${_component} STREQUAL "gobject")
find_library(GLIB_GOBJECT_LIBRARIES NAMES gobject-2.0 HINTS ${_GLIB_LIBRARY_DIR})
set(ADDITIONAL_REQUIRED_VARS ${ADDITIONAL_REQUIRED_VARS} GLIB_GOBJECT_LIBRARIES)
elseif (${_component} STREQUAL "gmodule")
find_library(GLIB_GMODULE_LIBRARIES NAMES gmodule-2.0 HINTS ${_GLIB_LIBRARY_DIR})
set(ADDITIONAL_REQUIRED_VARS ${ADDITIONAL_REQUIRED_VARS} GLIB_GMODULE_LIBRARIES)
elseif (${_component} STREQUAL "gthread")
find_library(GLIB_GTHREAD_LIBRARIES NAMES gthread-2.0 HINTS ${_GLIB_LIBRARY_DIR})
set(ADDITIONAL_REQUIRED_VARS ${ADDITIONAL_REQUIRED_VARS} GLIB_GTHREAD_LIBRARIES)
elseif (${_component} STREQUAL "gio-unix")
# gio-unix is compiled as part of the gio library, but the include paths
# are separate from the shared glib ones. Since this is currently only used
# by WebKitGTK+ we don't go to extraordinary measures beyond pkg-config.
pkg_check_modules(GIO_UNIX QUIET gio-unix-2.0)
endif ()
endforeach ()
include(FindPackageHandleStandardArgs)
FIND_PACKAGE_HANDLE_STANDARD_ARGS(GLIB REQUIRED_VARS GLIB_INCLUDE_DIRS GLIB_LIBRARIES ${ADDITIONAL_REQUIRED_VARS}
VERSION_VAR GLIB_VERSION)
mark_as_advanced(
GLIBCONFIG_INCLUDE_DIR
GLIB_GIO_LIBRARIES
GLIB_GIO_UNIX_LIBRARIES
GLIB_GMODULE_LIBRARIES
GLIB_GOBJECT_LIBRARIES
GLIB_GTHREAD_LIBRARIES
GLIB_INCLUDE_DIR
GLIB_INCLUDE_DIRS
GLIB_LIBRARIES
)

View File

@@ -1,58 +0,0 @@
# - Try to find LibNotify
# This module defines the following variables:
#
# LIBNOTIFY_FOUND - LibNotify was found
# LIBNOTIFY_INCLUDE_DIRS - the LibNotify include directories
# LIBNOTIFY_LIBRARIES - link these to use LibNotify
#
# Copyright (C) 2012 Raphael Kubo da Costa <rakuco@webkit.org>
# Copyright (C) 2014 Collabora Ltd.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
# 1. Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# 2. Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER AND ITS CONTRIBUTORS ``AS
# IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
# THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR ITS
# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
# OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
# WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
# OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
# ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
# Source from:
# https://sources.debian.org/src/qtwebkit-opensource-src/5.212.0~alpha2-21/Source/cmake/FindLibNotify.cmake/
find_package(PkgConfig)
pkg_check_modules(LIBNOTIFY QUIET libnotify)
find_path(LIBNOTIFY_INCLUDE_DIRS
NAMES notify.h
HINTS ${LIBNOTIFY_INCLUDEDIR}
${LIBNOTIFY_INCLUDE_DIRS}
PATH_SUFFIXES libnotify
)
find_library(LIBNOTIFY_LIBRARIES
NAMES notify
HINTS ${LIBNOTIFY_LIBDIR}
${LIBNOTIFY_LIBRARY_DIRS}
)
include(FindPackageHandleStandardArgs)
FIND_PACKAGE_HANDLE_STANDARD_ARGS(LibNotify REQUIRED_VARS LIBNOTIFY_INCLUDE_DIRS LIBNOTIFY_LIBRARIES
VERSION_VAR LIBNOTIFY_VERSION)
mark_as_advanced(
LIBNOTIFY_INCLUDE_DIRS
LIBNOTIFY_LIBRARIES
)

View File

@@ -1,51 +0,0 @@
# - FindXCB
#
# Copyright 2015 Valve Coporation
find_package(PkgConfig)
if(NOT XCB_FIND_COMPONENTS)
set(XCB_FIND_COMPONENTS xcb)
endif()
include(FindPackageHandleStandardArgs)
set(XCB_FOUND true)
set(XCB_INCLUDE_DIRS "")
set(XCB_LIBRARIES "")
foreach(comp ${XCB_FIND_COMPONENTS})
# component name
string(TOUPPER ${comp} compname)
string(REPLACE "-" "_" compname ${compname})
# header name
string(REPLACE "xcb-" "" headername xcb/${comp}.h)
# library name
set(libname ${comp})
pkg_check_modules(PC_${comp} QUIET ${comp})
find_path(${compname}_INCLUDE_DIR NAMES ${headername}
HINTS
${PC_${comp}_INCLUDEDIR}
${PC_${comp}_INCLUDE_DIRS}
)
find_library(${compname}_LIBRARY NAMES ${libname}
HINTS
${PC_${comp}_LIBDIR}
${PC_${comp}_LIBRARY_DIRS}
)
find_package_handle_standard_args(${comp}
FOUND_VAR ${comp}_FOUND
REQUIRED_VARS ${compname}_INCLUDE_DIR ${compname}_LIBRARY)
mark_as_advanced(${compname}_INCLUDE_DIR ${compname}_LIBRARY)
list(APPEND XCB_INCLUDE_DIRS ${${compname}_INCLUDE_DIR})
list(APPEND XCB_LIBRARIES ${${compname}_LIBRARY})
if(NOT ${comp}_FOUND)
set(XCB_FOUND false)
endif()
endforeach()
list(REMOVE_DUPLICATES XCB_INCLUDE_DIRS)

View File

@@ -1,335 +0,0 @@
# git_watcher.cmake
# https://raw.githubusercontent.com/andrew-hardin/cmake-git-version-tracking/master/git_watcher.cmake
#
# Released under the MIT License.
# https://raw.githubusercontent.com/andrew-hardin/cmake-git-version-tracking/master/LICENSE
# This file defines a target that monitors the state of a git repo.
# If the state changes (e.g. a commit is made), then a file gets reconfigured.
# Here are the primary variables that control script behavior:
#
# PRE_CONFIGURE_FILE (REQUIRED)
# -- The path to the file that'll be configured.
#
# POST_CONFIGURE_FILE (REQUIRED)
# -- The path to the configured PRE_CONFIGURE_FILE.
#
# GIT_STATE_FILE (OPTIONAL)
# -- The path to the file used to store the previous build's git state.
# Defaults to the current binary directory.
#
# GIT_WORKING_DIR (OPTIONAL)
# -- The directory from which git commands will be run.
# Defaults to the directory with the top level CMakeLists.txt.
#
# GIT_EXECUTABLE (OPTIONAL)
# -- The path to the git executable. It'll automatically be set if the
# user doesn't supply a path.
#
# GIT_FAIL_IF_NONZERO_EXIT (optional)
# -- Raise a FATAL_ERROR if any of the git commands return a non-zero
# exit code. This is set to TRUE by default. You can set this to FALSE
# if you'd like the build to continue even if a git command fails.
#
# DESIGN
# - This script was designed similar to a Python application
# with a Main() function. I wanted to keep it compact to
# simplify "copy + paste" usage.
#
# - This script is invoked under two CMake contexts:
# 1. Configure time (when build files are created).
# 2. Build time (called via CMake -P).
# The first invocation is what registers the script to
# be executed at build time.
#
# MODIFICATIONS
# You may wish to track other git properties like when the last
# commit was made. There are two sections you need to modify,
# and they're tagged with a ">>>" header.
# Short hand for converting paths to absolute.
macro(PATH_TO_ABSOLUTE var_name)
get_filename_component(${var_name} "${${var_name}}" ABSOLUTE)
endmacro()
# Check that a required variable is set.
macro(CHECK_REQUIRED_VARIABLE var_name)
if(NOT DEFINED ${var_name})
message(FATAL_ERROR "The \"${var_name}\" variable must be defined.")
endif()
PATH_TO_ABSOLUTE(${var_name})
endmacro()
# Check that an optional variable is set, or, set it to a default value.
macro(CHECK_OPTIONAL_VARIABLE_NOPATH var_name default_value)
if(NOT DEFINED ${var_name})
set(${var_name} ${default_value})
endif()
endmacro()
# Check that an optional variable is set, or, set it to a default value.
# Also converts that path to an abspath.
macro(CHECK_OPTIONAL_VARIABLE var_name default_value)
CHECK_OPTIONAL_VARIABLE_NOPATH(${var_name} ${default_value})
PATH_TO_ABSOLUTE(${var_name})
endmacro()
CHECK_REQUIRED_VARIABLE(PRE_CONFIGURE_FILE)
CHECK_REQUIRED_VARIABLE(POST_CONFIGURE_FILE)
CHECK_OPTIONAL_VARIABLE(GIT_STATE_FILE "${CMAKE_BINARY_DIR}/git-state-hash")
CHECK_OPTIONAL_VARIABLE(GIT_WORKING_DIR "${CMAKE_SOURCE_DIR}")
CHECK_OPTIONAL_VARIABLE_NOPATH(GIT_FAIL_IF_NONZERO_EXIT TRUE)
# Check the optional git variable.
# If it's not set, we'll try to find it using the CMake packaging system.
if(NOT DEFINED GIT_EXECUTABLE)
find_package(Git QUIET REQUIRED)
endif()
CHECK_REQUIRED_VARIABLE(GIT_EXECUTABLE)
set(_state_variable_names
GIT_RETRIEVED_STATE
GIT_HEAD_SHA1
GIT_IS_DIRTY
GIT_AUTHOR_NAME
GIT_AUTHOR_EMAIL
GIT_COMMIT_DATE_ISO8601
GIT_COMMIT_SUBJECT
GIT_COMMIT_BODY
GIT_DESCRIBE
# >>>
# 1. Add the name of the additional git variable you're interested in monitoring
# to this list.
)
# Macro: RunGitCommand
# Description: short-hand macro for calling a git function. Outputs are the
# "exit_code" and "output" variables.
macro(RunGitCommand)
execute_process(COMMAND
"${GIT_EXECUTABLE}" ${ARGV}
WORKING_DIRECTORY "${_working_dir}"
RESULT_VARIABLE exit_code
OUTPUT_VARIABLE output
ERROR_VARIABLE stderr
OUTPUT_STRIP_TRAILING_WHITESPACE)
if(NOT exit_code EQUAL 0)
set(ENV{GIT_RETRIEVED_STATE} "false")
# Issue 26: git info not properly set
#
# Check if we should fail if any of the exit codes are non-zero.
if(GIT_FAIL_IF_NONZERO_EXIT)
string(REPLACE ";" " " args_with_spaces "${ARGV}")
message(FATAL_ERROR "${stderr} (${GIT_EXECUTABLE} ${args_with_spaces})")
endif()
endif()
endmacro()
# Function: GetGitState
# Description: gets the current state of the git repo.
# Args:
# _working_dir (in) string; the directory from which git commands will be executed.
function(GetGitState _working_dir)
# This is an error code that'll be set to FALSE if the
# RunGitCommand ever returns a non-zero exit code.
set(ENV{GIT_RETRIEVED_STATE} "true")
# Get whether or not the working tree is dirty.
RunGitCommand(status --porcelain)
if(NOT exit_code EQUAL 0)
set(ENV{GIT_IS_DIRTY} "false")
else()
if(NOT "${output}" STREQUAL "")
set(ENV{GIT_IS_DIRTY} "true")
else()
set(ENV{GIT_IS_DIRTY} "false")
endif()
endif()
# There's a long list of attributes grabbed from git show.
set(object HEAD)
RunGitCommand(show -s "--format=%H" ${object})
if(exit_code EQUAL 0)
set(ENV{GIT_HEAD_SHA1} ${output})
endif()
RunGitCommand(show -s "--format=%an" ${object})
if(exit_code EQUAL 0)
set(ENV{GIT_AUTHOR_NAME} "${output}")
endif()
RunGitCommand(show -s "--format=%ae" ${object})
if(exit_code EQUAL 0)
set(ENV{GIT_AUTHOR_EMAIL} "${output}")
endif()
RunGitCommand(show -s "--format=%ci" ${object})
if(exit_code EQUAL 0)
set(ENV{GIT_COMMIT_DATE_ISO8601} "${output}")
endif()
RunGitCommand(show -s "--format=%s" ${object})
if(exit_code EQUAL 0)
# Escape quotes
string(REPLACE "\"" "\\\"" output "${output}")
set(ENV{GIT_COMMIT_SUBJECT} "${output}")
endif()
RunGitCommand(show -s "--format=%b" ${object})
if(exit_code EQUAL 0)
if(output)
# Escape quotes
string(REPLACE "\"" "\\\"" output "${output}")
# Escape line breaks in the commit message.
string(REPLACE "\r\n" "\\r\\n\\\r\n" safe "${output}")
if(safe STREQUAL output)
# Didn't have windows lines - try unix lines.
string(REPLACE "\n" "\\n\\\n" safe "${output}")
endif()
else()
# There was no commit body - set the safe string to empty.
set(safe "")
endif()
set(ENV{GIT_COMMIT_BODY} "\"${safe}\"")
else()
set(ENV{GIT_COMMIT_BODY} "\"\"") # empty string.
endif()
# Get output of git describe
RunGitCommand(describe --tags ${object})
if(NOT exit_code EQUAL 0)
set(ENV{GIT_DESCRIBE} "unknown")
else()
set(ENV{GIT_DESCRIBE} "${output}")
endif()
# >>>
# 2. Additional git properties can be added here via the
# "execute_process()" command. Be sure to set them in
# the environment using the same variable name you added
# to the "_state_variable_names" list.
endfunction()
# Function: GitStateChangedAction
# Description: this function is executed when the state of the git
# repository changes (e.g. a commit is made).
function(GitStateChangedAction)
foreach(var_name ${_state_variable_names})
set(${var_name} $ENV{${var_name}})
endforeach()
configure_file("${PRE_CONFIGURE_FILE}" "${POST_CONFIGURE_FILE}" @ONLY)
endfunction()
# Function: HashGitState
# Description: loop through the git state variables and compute a unique hash.
# Args:
# _state (out) string; a hash computed from the current git state.
function(HashGitState _state)
set(ans "")
foreach(var_name ${_state_variable_names})
string(SHA256 ans "${ans}$ENV{${var_name}}")
endforeach()
set(${_state} ${ans} PARENT_SCOPE)
endfunction()
# Function: CheckGit
# Description: check if the git repo has changed. If so, update the state file.
# Args:
# _working_dir (in) string; the directory from which git commands will be ran.
# _state_changed (out) bool; whether or no the state of the repo has changed.
function(CheckGit _working_dir _state_changed)
# Get the current state of the repo.
GetGitState("${_working_dir}")
# Convert that state into a hash that we can compare against
# the hash stored on-disk.
HashGitState(state)
# Issue 14: post-configure file isn't being regenerated.
#
# Update the state to include the SHA256 for the pre-configure file.
# This forces the post-configure file to be regenerated if the
# pre-configure file has changed.
file(SHA256 ${PRE_CONFIGURE_FILE} preconfig_hash)
string(SHA256 state "${preconfig_hash}${state}")
# Check if the state has changed compared to the backup on disk.
if(EXISTS "${GIT_STATE_FILE}")
file(READ "${GIT_STATE_FILE}" OLD_HEAD_CONTENTS)
if(OLD_HEAD_CONTENTS STREQUAL "${state}")
# State didn't change.
set(${_state_changed} "false" PARENT_SCOPE)
return()
endif()
endif()
# The state has changed.
# We need to update the state file on disk.
# Future builds will compare their state to this file.
file(WRITE "${GIT_STATE_FILE}" "${state}")
set(${_state_changed} "true" PARENT_SCOPE)
endfunction()
# Function: SetupGitMonitoring
# Description: this function sets up custom commands that make the build system
# check the state of git before every build. If the state has
# changed, then a file is configured.
function(SetupGitMonitoring)
add_custom_target(check_git
ALL
DEPENDS ${PRE_CONFIGURE_FILE}
BYPRODUCTS
${POST_CONFIGURE_FILE}
${GIT_STATE_FILE}
COMMENT "Checking the git repository for changes..."
COMMAND
${CMAKE_COMMAND}
-D_BUILD_TIME_CHECK_GIT=TRUE
-DGIT_WORKING_DIR=${GIT_WORKING_DIR}
-DGIT_EXECUTABLE=${GIT_EXECUTABLE}
-DGIT_STATE_FILE=${GIT_STATE_FILE}
-DPRE_CONFIGURE_FILE=${PRE_CONFIGURE_FILE}
-DPOST_CONFIGURE_FILE=${POST_CONFIGURE_FILE}
-DGIT_FAIL_IF_NONZERO_EXIT=${GIT_FAIL_IF_NONZERO_EXIT}
-P "${CMAKE_CURRENT_LIST_FILE}")
endfunction()
# Function: Main
# Description: primary entry-point to the script. Functions are selected based
# on whether it's configure or build time.
function(Main)
if(_BUILD_TIME_CHECK_GIT)
# Check if the repo has changed.
# If so, run the change action.
CheckGit("${GIT_WORKING_DIR}" changed)
if(changed OR NOT EXISTS "${POST_CONFIGURE_FILE}")
GitStateChangedAction()
endif()
else()
# >> Executes at configure time.
SetupGitMonitoring()
endif()
endfunction()
# And off we go...
Main()

387
debian/changelog vendored Normal file
View File

@@ -0,0 +1,387 @@
spark-store (4.0.0) stable; urgency=medium
* feat: 修复了成吨的bug后开始正式版
-- shenmo <shenmo@spark-app.store> Fri, 30 Jan 2022 00:00:00 +0800
spark-store (4.0.0~test2) stable; urgency=medium
* feat: 修复了成吨的bug后开始公测
-- shenmo <shenmo@spark-app.store> Fri, 30 Jan 2022 00:00:00 +0800
spark-store (4.0.0~test1) stable; urgency=medium
* feat: 柚子过来补充一下啦
-- shenmo <shenmo@spark-app.store> Fri, 30 Jan 2022 00:00:00 +0800
spark-store (3.4~test1) stable; urgency=medium
* feat: aptss不再尝试安装apt-fast转而自带
* chore: 删除password-check模块
-- shenmo <shenmo@spark-app.store> Fri, 30 Jan 2022 00:00:00 +0800
spark-store (3.3.3) stable; urgency=medium
* feat: 首页链接调用浏览器打开
-- shenmo <shenmo@spark-app.store> Fri, 30 Jan 2022 00:00:00 +0800
0spark-store (3.3.3~test5) stable; urgency=medium
* 修复可能的内存泄漏问题
* 修复应用搜索为空但仍显示上一次搜索结果的问题
* 修复动画加载延后的问题
* 修复统计下载量卡主渲染线程的问题
-- shenmo <shenmo@spark-app.store> Fri, 30 Jan 2022 00:00:00 +0800
spark-store (3.3.3~test4) stable; urgency=medium
* Enable i386 arch support by default
-- shenmo <shenmo@spark-app.store> Fri, 30 Jan 2022 00:00:00 +0800
spark-store (3.3.3~test3) stable; urgency=medium
* Now use ss-apt-fast instead of apt-fast
* 修复:右上角 更新和安装设置 菜单中进入更新列表失效
-- shenmo <shenmo@spark-app.store> Fri, 30 Jan 2022 00:00:00 +0800
spark-store (3.3.3~test2) stable; urgency=medium
* bug fix: 更新和检查更新出错时不报错.此更新需要一个推送
-- shenmo <shenmo@spark-app.store> Fri, 30 Jan 2022 00:00:00 +0800
spark-store (3.3.3~test1) stable; urgency=medium
* 3.3.3将会是修复大部分bug后的最终版本
* 图形环境中所有root权限的组件剥离到cli(可用于deepin 23 daily只保证商店本体正常运作不处理安装依赖不满足)
* 文案更改:更新检查-->检查更新
-- shenmo <shenmo@spark-app.store> Fri, 30 Jan 2022 00:00:00 +0800
spark-store (3.3.1~test1) stable; urgency=medium
* 安装时不再需要联网
-- shenmo <shenmo@spark-app.store> Fri, 30 Jan 2022 00:00:00 +0800
spark-store (3.3.0.4) stable; urgency=medium
* 为减轻服务器压力,不再单独更新某一个应用,而是作为整体更新
-- shenmo <shenmo@spark-app.store> Fri, 30 Jan 2022 00:00:00 +0800
spark-store (3.3.0.3) stable; urgency=medium
* 回滚 更新中行为到进度条而不是实时输出
* 更新应用时显示正在更新哪个应用
-- shenmo <shenmo@spark-app.store> Fri, 30 Jan 2022 00:00:00 +0800
spark-store (3.3.0.2) stable; urgency=medium
* 修复 pkexec未执行
-- shenmo <shenmo@spark-app.store> Fri, 30 Jan 2022 00:00:00 +0800
spark-store (3.3.0.1) stable; urgency=medium
* 修复 检查更新的更新进程未实际运行
-- shenmo <shenmo@spark-app.store> Fri, 30 Jan 2022 00:00:00 +0800
spark-store (3.3) stable; urgency=medium
* 修复 检查更新 未刷新软件源
* 把检查更新单独拿出作为左列
-- shenmo <shenmo@spark-app.store> Fri, 30 Jan 2022 00:00:00 +0800
spark-store (3.3~test3) stable; urgency=medium
* 把检查更新加入免密码
-- shenmo <shenmo@spark-app.store> Fri, 30 Jan 2022 00:00:00 +0800
spark-store (3.3~test2) stable; urgency=medium
* 更新检测功能全部更改到zenity
-- shenmo <shenmo@spark-app.store> Fri, 30 Jan 2022 00:00:00 +0800
spark-store (3.3~test1) stable; urgency=medium
* zenity选择可更新应用
* 自动更新检测现在会跳过hold
-- shenmo <shenmo@spark-app.store> Fri, 30 Jan 2022 00:00:00 +0800
spark-store (3.2.4) stable; urgency=medium
* 修改tag相关的文案内容wine相关环境已可自动配置了
* 准备发版
-- shenmo <shenmo@spark-app.store> Fri, 30 Jan 2022 00:00:00 +0800
spark-store (3.2.4~test4) stable; urgency=medium
* 现在在商店启动后点击spk链接仍会正常启动 https://gitee.com/deepin-community-store/spark-store/commit/dd6780d636042bf12d77414e6f1552cc7d1ed24c
-- shenmo <shenmo@spark-app.store> Fri, 30 Jan 2022 00:00:00 +0800
spark-store (3.2.4~test3) stable; urgency=medium
* 发版合入到master
* 翻译完毕
* 合入先前的各项改动客户端集成投稿器入口和支持修复安装依赖时间较长时错误地返回“安装完毕”结果现在客户端版本更新时不关闭免密码登录UOS安装进程合并正常aptss中
-- shenmo <shenmo@spark-app.store> Fri, 30 Jan 2022 00:00:00 +0800
spark-store (3.2.4~test2) stable; urgency=medium
* 客户端集成投稿器入口和支持
* 修复:安装依赖时间较长时错误地返回“安装完毕”结果
-- shenmo <shenmo@spark-app.store> Fri, 30 Jan 2022 00:00:00 +0800
spark-store (3.2.4~test1) stable; urgency=medium
* 客户端更新时不关闭免密码登录
* UOS合并正常aptss中
-- shenmo <shenmo@spark-app.store> Fri, 30 Jan 2022 00:00:00 +0800
spark-store (3.2.3) stable; urgency=medium
* 客户端异常退出时仍然占用资源问题修复
* 降低dtk依赖版本Debian 11 stable可直接安装
-- shenmo <shenmo@spark-app.store> Fri, 30 Jan 2022 00:00:00 +0800
spark-store (3.2.2) stable; urgency=medium
* aptss will now refresh the system source before doing install, policy....etc
* 启动客户端GPU加速支持
-- shenmo <shenmo@spark-app.store> Fri, 30 Jan 2022 00:00:00 +0800
spark-store (3.2.1) stable; urgency=medium
* 更改刷新系统源的功能
-- shenmo <shenmo@spark-app.store> Fri, 30 Jan 2022 00:00:00 +0800
spark-store (3.2) stable; urgency=medium
* 新增 下载量统计功能
* 新增 显示下载量
* 修复 spk链接生成错误
* 调整 启动时检测商店applist源
* 新增 applist cdn加速
* 调整 ssupdate不再更新/etc/aptss下的cache如要如此请使用aptss update
* 修复 在更新检测设置中的是否开启自动更新检测设置项的显示不随开启或关闭状态改变
* 修复 在检测更新时临时降低优先级到100防止系统中有且版本一致的包被反复来回更新
-- shenmo <shenmo@spark-app.store> Fri, 30 Jan 2022 00:00:00 +0800
spark-store (3.1.6) stable; urgency=medium
* 修复部分情况下无法选中正确的镜像源的问题
* 合入3.1.5以来的各项修改
-- shenmo <shenmo@spark-app.store> Fri, 30 Jan 2022 00:00:00 +0800
spark-store (3.1.5-5) stable; urgency=medium
* 从所有镜像源中选取最快镜像源高速下载
-- shenmo <shenmo@spark-app.store> Fri, 30 Jan 2022 00:00:00 +0800
spark-store (3.1.5-4) stable; urgency=medium
* 更改ss-apt-fast策略现在只会在updatessupdate和没有检测到配置文件的时候更新配置文件
* 新增ss-apt-fast别名aptss
* 更新检测服务优化:从分体改为一体
* aptss 支持自动补全
-- shenmo <shenmo@spark-app.store> Fri, 30 Jan 2022 00:00:00 +0800
spark-store (3.1.5-3) stable; urgency=medium
* 包内自带密钥
-- shenmo <shenmo@spark-app.store> Fri, 30 Jan 2022 00:00:00 +0800
spark-store (3.1.5-2) stable; urgency=medium
* 下载软件时跳过获取大小,修复部分软件无法下载的问题
* 修复 获取key时出错指定使用http1.1
-- shenmo <shenmo@spark-app.store> Fri, 30 Jan 2022 00:00:00 +0800
spark-store (3.1.5-1) stable; urgency=medium
* 改变更新策略UOS也下载加速但是安装不加速
-- shenmo <shenmo@spark-app.store> Fri, 30 Jan 2022 00:00:00 +0800
spark-store (3.1.5) stable; urgency=medium
* 改变更新策略,现在支持应用在更新时引入新依赖
* ss-apt-fast现在默认允许降级以与apt使用体验一致
-- shenmo <shenmo@spark-app.store> Fri, 30 Jan 2022 00:00:00 +0800
spark-store (3.1.4-2) stable; urgency=medium
* 客户端下载使用metalink来支持bt下载加速
* 修复使用更新和安装设置更新商店本体时出错
-- shenmo <shenmo@spark-app.store> Fri, 30 Jan 2022 00:00:00 +0800
spark-store (3.1.4-1) stable; urgency=medium
* 安装脚本和检测更新脚本检查网络时间超时时间延长至5s
* 修复ssinstall在没有安装apt-fast的情况下首次安装需要依赖的软件时安装失败
-- shenmo <shenmo@spark-app.store> Fri, 30 Jan 2022 00:00:00 +0800
spark-store (3.1.4) stable; urgency=medium
* 发布正式版,同步到官网
* 修复安装时使用wget的问题
* 合并3.1.3-1和3.1.3-2的更改
* 屏蔽了ssinstall之外的安装方式
* 调整了报错框的形式
* 修复pkexec下ssinstall不处理依赖
-- shenmo <shenmo@spark-app.store> Fri, 30 Jan 2022 00:00:00 +0800
spark-store (3.1.3-2) stable; urgency=medium
* 调整 现在与系统更新分开,不再导致更新失败
* 支持直接更新软件源文件不再让d.吃全部更新流量
* ss-apt-fast不再强制root权限
* 修改ss-apt-fast的策略现在除了安装下载和更新都改用apt
* ssinstall 现在也会在不适用ss-apt-fast的时候模拟源了针对UOS
-- shenmo <shenmo@spark-app.store> Fri, 30 Jan 2022 00:00:00 +0800
spark-store (3.1.3-1) stable; urgency=medium
* 修复 下载提前退出
* 移除 下载量显示
-- shenmo <shenmo@spark-app.store> Fri, 30 Jan 2022 00:00:00 +0800
spark-store (3.1.3) stable; urgency=medium
* Now uses aria2 to download softwares form all mirrors
* 新增ssinstall现在会在没有apt-fast的时候自动安装
* 新增ss-apt-fast现在会在没有apt-fast的时候自动安装
* 修改删除ssinstall中无用的 || dpkg -P $1
* 新增ss-apt-fast会先下载云上的conf以确保mirror是最新的
* 修复去除wget指令
-- shenmo <shenmo@spark-app.store> Fri, 30 Jan 2022 00:00:00 +0800
spark-store (3.1.2) stable; urgency=medium
* Now let apt-fast method support all mirrors
* Now will download dependencies and upgrade with all mirrors
-- shenmo <shenmo@spark-app.store> Mon, 17 Jan 2022 00:00:00 +0800
spark-store (3.1.1) stable; urgency=medium
* Now will delete the link of policy file after uninstall or upgrade
* Now ss-update-controler will create symbol link instead of hard link
-- shenmo <shenmo@spark-app.store> Mon, 17 Jan 2022 00:00:00 +0800
spark-store (3.1.0) stable; urgency=medium
* Add pkexec policy: ssinstall. Only will be enabled after permitted.
* Modify ssinistall script: Now will ask for password when not run as root
-- shenmo <shenmo@spark-app.store> Mon, 17 Jan 2022 00:00:00 +0800
spark-store (3.0.3-13) stable; urgency=medium
* Update the ssinstall script. Now support apt-fast and will temporarily increase the spark store source priority to 500 to make depends install correctly
* Change the style of About Dialog
* Modified depends to avoid Deb installers can not handle "Provides"
-- shenmo <shenmo@spark-app.store> Mon, 17 Jan 2022 00:00:00 +0800
spark-store (3.0.3-12) stable; urgency=medium
* Rollback to use DApplication::loadDXcbPlugin() to make titlebar behave normally in ubuntu
* Now can run on Debian 11
* Now can run on Ubuntu 22.04
-- shenmo <shenmo@spark-app.store> Mon, 17 Jan 2022 00:00:00 +0800
spark-store (3.0.3-11) stable; urgency=medium
* Now support autoupdate
-- shenmo <shenmo@spark-app.store> Mon, 17 Jan 2022 00:00:00 +0800
spark-store (3.0.3-10) stable; urgency=medium
* Now also compile dstore patch
-- shenmo <shenmo@spark-app.store> Mon, 17 Jan 2022 00:00:00 +0800
spark-store (3.0.3-9) stable; urgency=medium
* Support dpkg-buildpackage
-- shenmo <shenmo@spark-app.store> Mon, 17 Jan 2022 00:00:00 +0800

1
debian/compat vendored Normal file
View File

@@ -0,0 +1 @@
11

45
debian/control vendored Normal file
View File

@@ -0,0 +1,45 @@
Source: spark-store
Maintainer: shenmo <shenmo@spark-app.store>
Section: utils
Priority: optional
Build-Depends:
debhelper (>= 9),
pkg-config,
qtchooser (>= 55-gc9562a1-1~),
libqt5core5a,
libqt5gui5,
libqt5widgets5,
libqt5network5,
libqt5concurrent5,
libdtkcore-dev(>=5.0),
libdtkgui-dev(>=5.0),
libdtkwidget-dev(>=5.0),
qttools5-private-dev,
qtwebengine5-dev
Standards-Version: 3.0
Homepage: https://www.spark-app.store/
Package: spark-store
Architecture: any
Depends:${shlibs:Depends}, ${misc:Depends},
libqt5core5a,
libqt5gui5,
libqt5widgets5,
libqt5network5,
libqt5concurrent5,
libdtkcore5,
libdtkgui5,
libdtkwidget5,
curl,
openssl,
libssl-dev,
dde-qt5integration,
bubblewrap,
aria2,
gcc,
g++,
zenity
Description: Spark Store
A community powered app store, based on DTK.
Recommends: apt-fast

22
debian/copyright vendored Normal file
View File

@@ -0,0 +1,22 @@
Format: https://www.debian.org/doc/packaging-manuals/copyright-format/1.0/
Upstream-Name: spark-store
Source: https://gitee.com/deepin-community-store/spark-store
Files: *
Copyright: The Spark Project Developers
License: GPL-3+
This package is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
.
This package is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>
.
On Debian systems, the complete text of the GNU General

37
debian/rules vendored Executable file
View File

@@ -0,0 +1,37 @@
#!/usr/bin/make -f
export QT_SELECT=5
include /usr/share/dpkg/default.mk
DEB_BUILD_ARCH ?= $(shell dpkg-architecture -qDEB_BUILD_ARCH)
DH_AUTO_ARGS = --parallel --buildsystem=qmake
# Uncomment this to turn on verbose mode.
#export DH_VERBOSE=1
%:
dh $@ --parallel
override_dh_auto_clean:
rm -rf $(CURDIR)/build
override_dh_auto_configure:
mkdir -p $(CURDIR)/build
dh_auto_configure MAKEFLAGS=-j$(JOBS) -- spark-store-project.pro \
-spec linux-g++ CONFIG+=qtquickcompiler \
-o $(CURDIR)/build/
override_dh_auto_build:
make -C $(CURDIR)/build -j$(JOBS)
override_dh_auto_install:
make -C $(CURDIR)/build install \
INSTALL_ROOT=$(CURDIR)/debian/spark-store
# Ignore the dpkg-shlibdeps: warning (it uses none of the library's symbols)
# Qt Mutidedia lib will ref to network libraray.
override_dh_shlibdeps:
dh_shlibdeps --dpkg-shlibdeps-params=--warnings=0

1
debian/source/format vendored Normal file
View File

@@ -0,0 +1 @@
1.0

88
debian/spark-store.postinst vendored Executable file
View File

@@ -0,0 +1,88 @@
#!/bin/sh
case "$1" in
configure)
# Enable i386 arch
echo "Enable i386 arch..."
dpkg --add-architecture i386
# config for aptss
mkdir -p /etc/aptss/sources.list.d
ln -s -f /etc/apt/sources.list /etc/aptss/sources.list
# Remove the sources.list file
if [ -e /etc/apt/sources.list.d/sparkstore.list ];then
rm /etc/apt/sources.list.d/sparkstore.list
fi
# Check if /usr/local/bin existed
mkdir -p /usr/local/bin
# Create symbol links for binary files
ln -s -f /opt/durapps/spark-store/bin/ussinstall /usr/local/bin/ussinstall
ln -s -f /opt/durapps/spark-store/bin/ussremove /usr/local/bin/ussremove
ln -s -f /opt/durapps/spark-store/bin/spark-store /usr/local/bin/spark-store
ln -s -f /opt/durapps/spark-store/bin/ssinstall /usr/local/bin/ssinstall
ln -s -f /opt/durapps/spark-store/bin/spark-dstore-patch /usr/local/bin/spark-dstore-patch
ln -s -f /opt/durapps/spark-store/bin/aptss /usr/local/bin/ss-apt-fast
ln -s -f /opt/durapps/spark-store/bin/aptss /usr/bin/aptss
# Create symbol links for SSINSTALL
ln -s -f /opt/durapps/spark-store/bin/auto-install-policy/store.spark-app.ssinstall.policy /usr/share/polkit-1/actions/store.spark-app.ssinstall.policy
echo "Compiling the Sender module..."
gcc /opt/durapps/spark-store/bin/ss-feedback/sender-d.sh.c -o /opt/durapps/spark-store/bin/ss-feedback/sender-d
# Install key
mkdir -p /tmp/spark-store-install/
cp -f /opt/durapps/spark-store/bin/spark-store.asc /tmp/spark-store-install/spark-store.asc
gpg --dearmor /tmp/spark-store-install/spark-store.asc
cp -f /tmp/spark-store-install/spark-store.asc.gpg /etc/apt/trusted.gpg.d/spark-store.gpg
# Run apt update to avoid users being fucked up by the non-exist dependency problem
# Now abandoned as aptss now run ssupdate everytime
#aptss ssupdate
# Start upgrade detect service
systemctl enable spark-update-notifier
service spark-update-notifier start
# Update certain caches
update-icon-caches /usr/share/icons/hicolor || true
update-desktop-database /usr/share/applications || true
xdg-mime default spark-store.desktop x-scheme-handler/spk
update-mime-database /usr/share/mime || true
# Send email for statistics
# /tmp/spark-store-install/feedback.sh
# Remove temp dir
rm -rf /tmp/spark-store-install
;;
triggered)
# Quit if deepin-app-store-tool existed
if [ -x "/usr/bin/deepin-app-store-tool" ] ; then
exit 0
fi
# Trigger for UOS debs installation
echo '--------检测到Uniontech标准软件包运行补丁以修正安装--------'
if [ -x "/usr/local/bin/spark-dstore-patch" ] ; then
/usr/local/bin/spark-dstore-patch
echo '-----------spark-dstore-patch补丁工具已运行完毕-----------'
else
echo '------------spark-dstore-patch补丁工具运行失败------------'
fi
;;
esac

6
debian/spark-store.postrm vendored Normal file
View File

@@ -0,0 +1,6 @@
#!/bin/sh
# Update certain caches
update-icon-caches /usr/share/icons/hicolor || true
update-desktop-database /usr/share/applications || true
update-mime-database /usr/share/mime || true

28
debian/spark-store.preinst vendored Executable file
View File

@@ -0,0 +1,28 @@
#!/bin/bash
#检测网络链接畅通
function network-check()
{
#超时时间
local timeout=15
#目标网站
local target=www.baidu.com
#获取响应状态码
local ret_code=`curl -I -s --connect-timeout ${timeout} ${target} -w %{http_code} | tail -n1`
if [ "x$ret_code" = "x200" ]; then
echo "Network Checked successful ! Continue..."
echo "网络通畅,继续安装"
else
#网络不畅通
echo "Network failed ! Cancel the installation"
echo "网络不畅,终止安装"
exit -1
fi
}
#network-check
echo "不再检测网络"

47
debian/spark-store.prerm vendored Executable file
View File

@@ -0,0 +1,47 @@
#!/bin/sh
if [ "$1" = "remove" ] || [ "$1" = "purge" ];then
# Remove residual symbol links
rm /usr/local/bin/spark-store
rm /usr/local/bin/ssinstall
rm /usr/local/bin/spark-dstore-patch
rm /usr/local/bin/ussinstall
rm /usr/local/bin/ussremove
rm /usr/local/bin/ss-apt-fast
rm /usr/bin/aptss
rm -rf /etc/aptss/
# Remove Sender module
rm /opt/durapps/spark-store/bin/ss-feedback/sender-d
# Remove residual symbol links to stop upgrade detect if exist
if [ -e /etc/xdg/autostart/spark-update-notifier.desktop ];then
rm /etc/xdg/autostart/spark-update-notifier.desktop
fi
# Shutdown services
service spark-update-notifier stop
# Stop update detect service
systemctl disable spark-update-notifier
# Clean the auto install polkit file if exist
if [ -f "/usr/share/polkit-1/actions/store.spark-app.ssinstall.policy" ] ; then
rm /usr/share/polkit-1/actions/store.spark-app.ssinstall.policy
fi
# Remove gpg key file
if [ -f "/etc/apt/trusted.gpg.d/spark-store.gpg" ] ; then
rm /etc/apt/trusted.gpg.d/spark-store.gpg
fi
apt-key del '9D9A A859 F750 24B1 A1EC E16E 0E41 D354 A29A 440C'
else
echo "非卸载操作,不进行配置清理"
fi

1
debian/spark-store.triggers vendored Normal file
View File

@@ -0,0 +1 @@
interest-noawait /opt/apps

View File

@@ -1,52 +0,0 @@
# 项目结构和命名规范
## 文件夹结构
### cmake
主要用于 CMake 配置时需要用到的 CMake 模块脚本。
### gui
主要用于显示界面的 C++ 代码文件(即包含 Qt Widgets 代码),无论包含多少与其他组件的联系,都在这个目录内。
这包括 SpkUi 的自定义界面组件、商店主界面自身的 Page 类等等。
### inc
项目中所有以 `#include "xxx.h"` 方式包含到代码中的标头文件,全部放入此目录。
标头文件并不强求目录结构明确,文件用途或来源特殊的除外。
### src
商店主体逻辑。包含基础的 `SpkStore` 类、`main.cpp` 等核心逻辑。
新加入的逻辑如单个功能多于一个cpp文件则必须分装到一个目录内。
### plugin
适配 Deepin 以及其他平台的平台相关插件。
## 命名规范
### 通用规范
类名、成员、方法名一律采用大驼峰形式。例如,`SpkTitleBar::SetTitle` 方法。
C++ 规范要求的和第三方库有较大差异的除外。例如,`SpkUiMessage::_notify`成员。
临时变量采用小驼峰形式或全小写。
名称要对功能要有基础的描述,例如,`SpkUi::SpkCategorySelector` 类。抽象核心逻辑除外。
### 类名
如非第三方代码,一般以 `Spk` 前缀标明。
实现 UI 的类都应归于 `SpkUi` 命名空间。
## 类定义
### 一般规则
Qt 类的 `Q_OBJECT` 应置于类定义最顶端。
`public` `protected``private` 等标签中只应该包含一类成员,
如单个 `public` 标签内只能包含方法,或成员。
信号、槽等不得与普通方法混合。
<!--TODO-->

View File

@@ -1,6 +0,0 @@
# 翻译
由于CMake和Qt的稀烂集成我们不能使用CMake自动lupdate更新翻译。
如果需要更新翻译,请使用`make run_lupdate`目标进行。qm文件的编译无需其他操作只需build即可。

View File

@@ -1,314 +0,0 @@
// SPDX-License-Identifier: GPL-3.0-only
#include "page/spkpageappdetails.h"
#include "spkutils.h"
#include "spkappitem.h"
namespace SpkUi
{
constexpr QSize SpkPageAppDetails::IconSize;
void SpkPageAppDetails::LoadAppResources(QString aPkgName, QString aIcon, QStringList aScreenshots,
QStringList aTags)
{
QPixmap pic;
// Load icon
auto res = RES->RequestResource(0, aPkgName, SpkResource::ResourceType::AppIcon, aIcon);
if(res.status == SpkResource::ResourceStatus::Ready)
{
if(pic.loadFromData(res.data))
mAppIcon->setPixmap(pic.scaled(IconSize,
Qt::IgnoreAspectRatio,
Qt::SmoothTransformation));
else
{
mAppIcon->setPixmap(mBrokenImg);
RES->PurgeCachedResource(aPkgName, SpkResource::ResourceType::AppIcon, 0);
}
}
// Load screenshots. Screenshots have id starting with 1.
if(aScreenshots.isEmpty())
return;
else
{
auto count = aScreenshots.size();
mImgViewer->SetImageTotal(count);
if(count > mScreenshotPreviews.size())
{
auto from = mScreenshotPreviews.size(), to = count - mScreenshotPreviews.size();
for(int i = 0; i <= to; i++)
{
auto wid = new SpkClickLabel;
wid->setProperty("shotId", from + i + 1);
wid->setFixedHeight(200);
wid->setCursor(Qt::PointingHandCursor);
connect(wid, &SpkClickLabel::Pressed, this, &SpkPageAppDetails::ImageClicked);
mScreenshotPreviews.append(wid);
mScreenshotLay->addWidget(wid);
}
}
}
int shotId = 0;
for(auto &i : aScreenshots)
{
shotId++;
res = RES->RequestResource(shotId, aPkgName, SpkResource::ResourceType::AppScreenshot, i,
shotId);
auto preview = mScreenshotPreviews[shotId - 1];
preview->setVisible(true);
if(res.status == SpkResource::ResourceStatus::Ready)
{
if(pic.loadFromData(res.data))
{
mAppImages[shotId] = pic;
mImgViewer->SetPixmap(shotId, &mAppImages[shotId]);
preview->setPixmap(pic.scaledToHeight(200, Qt::SmoothTransformation));
}
else
{
mAppImages[shotId] = mBrokenImg;
RES->PurgeCachedResource(aPkgName, SpkResource::ResourceType::AppScreenshot, 0);
}
}
else
{
preview->setPixmap(mIconLoading);
}
}
// TODO: tags
}
void SpkPageAppDetails::SetWebsiteLink(QString url)
{
mWebsite->setText(QString("<a href=\"%1\">%2</a>").arg(url, tr("Website link")));
}
void SpkPageAppDetails::SetPackagePath(QString url)
{
mPkgPath = url;
}
SpkPageAppDetails::SpkPageAppDetails(QWidget *parent) : SpkPageBase(parent),
mBrokenImg(QIcon(":/icons/broken-icon.svg").pixmap(SpkAppItem::IconSize_)),
mIconLoading(QIcon(":/icons/loading-icon.svg").pixmap(SpkAppItem::IconSize_))
{
mMainArea = new QScrollArea;
mMainArea->setWidgetResizable(true);
mMainArea->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
mMainLay = new QVBoxLayout(this);
mMainLay->addWidget(mMainArea);
mBottomBar = new QWidget;
mMainLay->addWidget(mBottomBar);
mDetailsLay = new QVBoxLayout(mMainArea);
mDetailsLay->setSizeConstraint(QLayout::SetMinAndMaxSize);
mAppIcon = new QLabel;
mAppTitle = new QLabel;
mAppTitle->setObjectName("styDetTitle");
mAppTitle->setWordWrap(true);
mAppDescription = new QLabel;
mAppDescription->setObjectName("styDetDesc");
mAppDescription->setWordWrap(true);
mAppShortDesc = new QLabel;
mAppShortDesc->setObjectName("styDetDesc");
mAppShortDesc->setWordWrap(true);
// NOTE: Seems Qt have trouble dealing with wrapped text here. Removing the following operations
// to mAppShortDesc will result in broken layout. Very possible that it's a Qt bug.
mAppShortDesc->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::Preferred);
mAppShortDesc->setMinimumWidth(100);
mVersion = new QLabel;
mVersion->setWordWrap(true);
mWebsite = new QLabel;
mPkgName = new QLabel;
mPkgName->setObjectName("styDetPkg");
mPkgName->setWordWrap(true);
mTitleLay = new QVBoxLayout;
mTitleLay->setAlignment(Qt::AlignTop);
mTitleLay->addWidget(mAppTitle);
mTitleLay->addWidget(mVersion);
mTitleLay->addWidget(mAppShortDesc);
mTitleLay->addWidget(mPkgName);
mTitleLay->addWidget(mWebsite);
mTitleLay->setSpacing(0);
mIconTitleLay = new QHBoxLayout;
mIconTitleLay->setAlignment(Qt::AlignLeft);
mIconTitleLay->addWidget(mAppIcon);
mIconTitleLay->addSpacing(15);
mIconTitleLay->addLayout(mTitleLay);
mIconTitleWidget = new QWidget;
mIconTitleWidget->setLayout(mIconTitleLay);
mAuthor = new SpkDetailEntry;
mAuthor->SetTitle(tr("Author"));
mContributor = new SpkDetailEntry;
mContributor->SetTitle(tr("Contributor"));
// mSite = new SpkDetailEntry;
// mSite->SetTitle(tr("Website"));
mArch = new SpkDetailEntry;
mArch->SetTitle(tr("Architecture"));
mSize = new SpkDetailEntry;
mSize->SetTitle(tr("Size"));
mDetailLay = new SpkStretchLayout;
mDetailLay->setSpacing(12);
mDetailLay->addWidget(mAuthor);
mDetailLay->addWidget(mContributor);
mDetailLay->addWidget(mSize);
mDetailLay->addWidget(mArch);
// mDetailLay->addWidget(mSite);
// mDetailWidget = new QWidget;
// mDetailWidget->setLayout(mDetailLay);
// mDetailWidget->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Expanding);
mDetailsLay->setAlignment(Qt::AlignTop);
mDetailsLay->addWidget(mIconTitleWidget);
mDetailsLay->addLayout(mDetailLay);
mDetailsLay->addWidget(mAppDescription);
// mMainLay->addStretch();
mScreenshotLay = new QHBoxLayout;
mScreenshotArea = new QScrollArea;
mWid4ShotArea = new QWidget;
mWid4ShotArea->setLayout(mScreenshotLay);
mScreenshotArea->setWidget(mWid4ShotArea);
mScreenshotArea->setWidgetResizable(true);
mScreenshotArea->setFixedHeight(230);
mScreenshotArea->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Fixed);
mDetailsLay->addWidget(mScreenshotArea);
mWid4MainArea = new QWidget;
mWid4MainArea->setLayout(mDetailsLay);
mMainArea->setWidget(mWid4MainArea);
mWebsite->setTextFormat(Qt::RichText);
mWebsite->setOpenExternalLinks(true);
// Bottom bar buttons
mBottomBarLay = new QHBoxLayout;
mBottomBar->setLayout(mBottomBarLay);
mBtnDownload = new QPushButton;
mBtnDownload->setText(tr("Download"));
// mBtnInstall = new QPushButton;
// mBtnInstall->setText(tr("Install"));
mBtnUninstall = new QPushButton;
mBtnUninstall->setText(tr("Uninstall"));
mBtnRequestUpdate = new QPushButton;
mBtnRequestUpdate->setText(tr("Request Update"));
mBtnReport = new QPushButton;
mBtnReport->setText(tr("Report"));
mBottomBarLay->addStretch();
mBottomBarLay->addWidget(mBtnDownload);
// mBottomBarLay->addWidget(mBtnInstall);
mBottomBarLay->addWidget(mBtnUninstall);
mBottomBarLay->addWidget(mBtnRequestUpdate);
mBottomBarLay->addWidget(mBtnReport);
mImgViewer = new SpkImgViewer;
mImgViewer->setVisible(false);
connect(mBtnDownload, &QPushButton::clicked,
[=](){ emit RequestDownload(mAppTitle->text(), mPkgName->text(),
"/store/reading/youdao-dict/youdao-dict_6.0.0-0~ubuntu_amd64.deb");
});
}
SpkPageAppDetails::~SpkPageAppDetails()
{
delete mImgViewer;
}
void SpkPageAppDetails::ResourceAcquisitionFinished(int id, ResourceResult result)
{
QPixmap img;
// qDebug() << "PageAppDetails: Resource" << id << "acquired";
if(!id)
{
// id == 0, icon
if(result.status == SpkResource::ResourceStatus::Ready)
{
if(img.loadFromData(result.data))
mAppIcon->setPixmap(img.scaled(SpkAppItem::IconSize_,
Qt::IgnoreAspectRatio,
Qt::SmoothTransformation));
else
mAppIcon->setPixmap(mBrokenImg);
}
else if(result.status == SpkResource::ResourceStatus::Failed)
{
mAppIcon->setPixmap(mBrokenImg);
RES->PurgeCachedResource(mPkgName->text(), SpkResource::ResourceType::AppIcon, 0);
}
}
else
{
auto preview = mScreenshotPreviews[id - 1];
preview->setVisible(true);
if(result.status == SpkResource::ResourceStatus::Ready)
{
if(img.loadFromData(result.data))
{
mAppImages[id] = img;
mImgViewer->SetPixmap(id, &mAppImages[id]);
mScreenshotPreviews[id - 1]->setPixmap(img.scaledToHeight(200, Qt::SmoothTransformation));
}
else
{
mImgViewer->SetPixmap(id, &mBrokenImg);
mScreenshotPreviews[id - 1]->setPixmap(mBrokenImg);
}
}
else if(result.status == SpkResource::ResourceStatus::Failed)
{
mImgViewer->SetPixmap(id, &mBrokenImg);
mScreenshotPreviews[id - 1]->setPixmap(mBrokenImg);
RES->PurgeCachedResource(mPkgName->text(), SpkResource::ResourceType::AppIcon, 0);
}
}
}
void SpkPageAppDetails::Activated()
{
RES->Acquire(this, false);
for(auto &i : mScreenshotPreviews)
i->setVisible(false);
mImgViewer->Clear();
}
void SpkPageAppDetails::ImageClicked()
{
mImgViewer->ShowWithImage(sender()->property("shotId").toInt());
}
SpkDetailEntry::SpkDetailEntry(QWidget *parent) : QWidget(parent)
{
setLayout(&mLay);
mLay.addWidget(&mTitle);
mLay.addWidget(&mField);
mTitle.setAlignment(Qt::AlignLeft);
mField.setAlignment(Qt::AlignRight);
setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
setMinimumWidth(300);
setAutoFillBackground(true);
}
}

View File

@@ -1,181 +0,0 @@
#include "page/spkpageapplist.h"
#include "spkutils.h"
#include "spkuimsg.h"
namespace SpkUi
{
SpkPageAppList::SpkPageAppList(QWidget *parent) : SpkPageBase(parent)
{
mLoadingIcon = new QPixmap(QIcon(":/icons/loading-icon.svg").pixmap(SpkAppItem::IconSize_));
mBrokenIcon = new QPixmap(QIcon(":/icons/broken-icon.svg").pixmap(SpkAppItem::IconSize_));
mAppsWidget = new QWidget;
mAppsArea = new QScrollArea(this);
mMainLay = new QVBoxLayout(this);
mItemLay = new SpkStretchLayout(mAppsWidget);
mPageSwitchWidget = new QWidget;
mPageSwitchLay = new QHBoxLayout(mPageSwitchWidget);
mBtnPgUp = new QPushButton;
mBtnPgDown = new QPushButton;
mBtnGotoPage = new QPushButton;
mPageInput = new QLineEdit;
mPageValidator = new QIntValidator(mPageInput);
mPageIndicator = new QLabel;
mPageValidator->setRange(1, 99);
mPageInput->setFixedWidth(50);
mPageInput->setValidator(mPageValidator);
mBtnGotoPage->setText(tr("Goto"));
mBtnPgUp->setText(tr("Previous"));
mBtnPgDown->setText(tr("Next"));
mBtnGotoPage->setFocusPolicy(Qt::NoFocus);
mBtnPgDown->setFocusPolicy(Qt::NoFocus);
mBtnPgUp->setFocusPolicy(Qt::NoFocus);
mPageSwitchLay->addWidget(mPageIndicator);
mPageSwitchLay->addStretch();
mPageSwitchLay->addWidget(mPageInput);
mPageSwitchLay->addWidget(mBtnGotoPage);
mPageSwitchLay->addWidget(mBtnPgUp);
mPageSwitchLay->addWidget(mBtnPgDown);
mAppsArea->setWidget(mAppsWidget);
mAppsArea->setWidgetResizable(true);
mMainLay->addWidget(mAppsArea);
mMainLay->addWidget(mPageSwitchWidget);
setLayout(mMainLay);
connect(mBtnPgUp, &QPushButton::clicked, this, &SpkPageAppList::PageUp);
connect(mBtnPgDown, &QPushButton::clicked, this, &SpkPageAppList::PageDown);
connect(mBtnGotoPage, &QPushButton::clicked, this, &SpkPageAppList::GotoPage);
}
void SpkPageAppList::AddApplicationEntry(QString name, QString pkgName, QString description,
QString iconUrl, int appId)
{
auto item = new SpkAppItem(appId, this);
auto id = mAppItemList.size();
connect(item, &SpkAppItem::clicked, this, &SpkPageAppList::ApplicationClicked);
item->SetTitle(name);
item->SetDescription(description);
item->setProperty("pkg_name", pkgName);
auto iconRes = RES->RequestResource(id, pkgName, SpkResource::ResourceType::AppIcon,
iconUrl, 0);
QPixmap icon;
if(iconRes.status == SpkResource::ResourceStatus::Ready)
{
if(icon.loadFromData(iconRes.data))
item->SetIcon(icon.scaled(SpkAppItem::IconSize_,
Qt::IgnoreAspectRatio,
Qt::SmoothTransformation));
else
{
item->SetIcon(*mBrokenIcon);
RES->PurgeCachedResource(pkgName, SpkResource::ResourceType::AppIcon, 0);
}
}
else
item->SetIcon(*mLoadingIcon);
mAppItemList.append(item);
mItemLay->addWidget(item);
}
void SpkPageAppList::ClearAll()
{
QWidget *itm;
QLayoutItem *layitm;
while((layitm = mItemLay->takeAt(0)))
{
itm = layitm->widget();
itm->hide();
itm->deleteLater();
}
mAppItemList.clear();
mAppsArea->verticalScrollBar()->setValue(0);
}
void SpkPageAppList::ResourceAcquisitionFinished(int id, ResourceResult result)
{
QPixmap icon;
// qDebug() << "PageAppList: Resource" << id << "acquired";
auto item = mAppItemList[id];
if(result.status == SpkResource::ResourceStatus::Ready)
{
if(icon.loadFromData(result.data))
item->SetIcon(icon.scaled(SpkAppItem::IconSize_,
Qt::IgnoreAspectRatio,
Qt::SmoothTransformation));
else
item->SetIcon(*mBrokenIcon);
}
else if(result.status == SpkResource::ResourceStatus::Failed)
{
item->SetIcon(*mBrokenIcon);
RES->PurgeCachedResource(item->property("pkg_name").toString(),
SpkResource::ResourceType::AppIcon, 0);
}
}
void SpkPageAppList::SetPageStatus(int total, int current, int itemCount, QString &keyword)
{
mCurrentPage = current;
mKeyword = keyword;
mPageIndicator->setText(tr("Page %1 / %2, %3 apps in total")
.arg(current).arg(total).arg(itemCount));
mBtnPgUp->setDisabled(current == 1);
mBtnPgDown->setDisabled(total == current || total == 1);
mBtnGotoPage->setDisabled(total == 1);
mPageValidator->setTop(total);
}
void SpkPageAppList::DisablePageSwitchers()
{
mBtnPgDown->setDisabled(true);
mBtnPgUp->setDisabled(true);
mBtnGotoPage->setDisabled(true);
}
void SpkPageAppList::PageUp()
{
DisablePageSwitchers();
if(mKeyword.isEmpty())
emit SwitchListPage(mCategoryId, mCurrentPage - 1);
else
emit SwitchSearchPage(mKeyword, mCurrentPage - 1);
}
void SpkPageAppList::PageDown()
{
DisablePageSwitchers();
if(mKeyword.isEmpty())
emit SwitchListPage(mCategoryId, mCurrentPage + 1);
else
emit SwitchSearchPage(mKeyword, mCurrentPage + 1);
}
void SpkPageAppList::GotoPage()
{
if(mPageInput->text().isEmpty())
return SpkUiMessage::SendStoreNotification(tr("Please enter page number to go to!"));
int page = mPageInput->text().toInt();
if(page > mPageValidator->top())
return SpkUiMessage::SendStoreNotification(tr("Page %1 is not a valid page number!")
.arg(page));
DisablePageSwitchers();
if(mKeyword.isEmpty())
emit SwitchListPage(mCategoryId, page);
else
emit SwitchSearchPage(mKeyword, page);
}
void SpkPageAppList::Activated()
{
RES->Acquire(this, false);
}
}

View File

@@ -1,41 +0,0 @@
#include "page/spkpagebase.h"
/*
* Documentation on
* How to Add a New Page to Main Window Side Bar
*
* 1. Derive your page widget class from SpkPageBase (reference implementation
* in SpkPageSettings) and add them to CMakeLists
*
* 2. Add the ID for the page in enum SpkUi::SpkStackedPages (in spkmainwindow.h)
* and add it as a resource context if needed
*
* 3. Include the page's header file in spkmainwindow.h and add a pointer to it in
* SpkUi::SpkMainWidget
*
* 4. Add a tree item or icon button for the corresponding page inside
* SpkUi::SpkMainWidget, and initialize it in SpkUi::SpkMainWidget::SpkMainWidget.
* Take references of existing entries, and write similar code close to each other
* to make the source look nice. Don't forget to add the item to the UI.
*
* 5. Make the linkage between the page and the sidebar item at the end of
* SpkUi::SpkMainWidget::SpkMainWidget().
*
*/
SpkPageBase::SpkPageBase(QWidget *parent) : QWidget(parent)
{
}
void SpkPageBase::ResourceAcquisitionFinished(int id, ResourceResult result)
{
Q_UNUSED(id);
Q_UNUSED(result);
}
void SpkPageBase::Activated()
{
; // Do nothing
}

View File

@@ -1,214 +0,0 @@
#include "page/spkpagedownloads.h"
#include "pkgs/spkpkgmgrbase.h"
#include "spkuimsg.h"
#include "spkutils.h"
SpkUi::SpkPageDownloads::SpkPageDownloads(QWidget *parent) :
SpkPageBase(parent)
{
mMainLay = new QVBoxLayout(this);
mLayEntries = new QVBoxLayout;
mScrollWidget = new QWidget;
mScrollArea = new QScrollArea(this);
mLayEntries->setAlignment(Qt::AlignTop);
mScrollWidget->setLayout(mLayEntries);
mScrollArea->setWidget(mScrollWidget);
mScrollArea->setWidgetResizable(true);
mMainLay->addWidget(mScrollArea);
setLayout(mMainLay);
mDownloadMgr = new SpkDownloadMgr(this);
connect(mDownloadMgr, &SpkDownloadMgr::DownloadProgressed,
this, &SpkPageDownloads::DownloadProgress);
mNextDownloadId = 0;
mCurrentStatus = Idle;
connect(mDownloadMgr, &SpkDownloadMgr::DownloadStopped,
this, &SpkPageDownloads::DownloadStopped, Qt::QueuedConnection);
connect(PKG, &SpkPkgMgrBase::ReportInstallResult,
this, &SpkPageDownloads::InstallationEnded);
}
SpkUi::SpkPageDownloads::~SpkPageDownloads()
{
// TODO
}
void SpkUi::SpkPageDownloads::DownloadProgress(qint64 downloadedBytes, qint64 totalBytes, int id)
{
if(!totalBytes)
return;
if(mCurrentStatus == Waiting && totalBytes)
{
mCurrentStatus = Downloading;
mEntries[id]->SetTotalBytes(totalBytes);
mEntries[id]->SetStatus(SpkDownloadEntry::Downloading);
}
mEntries[id]->Progress(downloadedBytes);
}
void SpkUi::SpkPageDownloads::AddDownloadTask(QString name, QString pkgName, QString path)
{
// Add a new download entry into the UI
auto entry = new SpkDownloadEntry;
auto iconData = RES->CacheLookup(pkgName, SpkResource::ResourceType::AppIcon, 0);
auto id = mNextDownloadId;
QPixmap icon;
if(iconData.status != SpkResource::ResourceStatus::Ready || !icon.loadFromData(iconData.data))
icon.load(":/icons/broken-icon.svg");
entry->SetBasicInfo(name, icon, mDownloadMgr->GetDestFilePath(path));
entry->SetStatus(SpkDownloadEntry::Waiting);
entry->setProperty("entryId", id);
entry->setProperty("path", path);
mNextDownloadId++;
mEntries[id] = entry;
mLayEntries->addWidget(entry);
connect(entry, &SpkDownloadEntry::Action,
this, &SpkPageDownloads::EntryAction);
NewDownloadTask(id, path);
}
void SpkUi::SpkPageDownloads::DownloadStopped(SpkDownloadMgr::TaskResult status, int id)
{
switch(status)
{
case SpkDownloadMgr::Success:
mEntries[id]->SetStatus(SpkDownloadEntry::ToBeInstalled);
break;
case SpkDownloadMgr::FailCannotCreateFile:
mEntries[id]->SetStatus(SpkDownloadEntry::DownloadFailed,
tr("Cannot create download file. Download failed."));
break;
case SpkDownloadMgr::FailNoVaibleServer:
mEntries[id]->SetStatus(SpkDownloadEntry::DownloadFailed,
tr("Connection unstable or server failure. Download failed."));
break;
case SpkDownloadMgr::FailCancel:
mEntries[id]->SetStatus(SpkDownloadEntry::DownloadFailed,
tr("This download was cancelled."));
break;
case SpkDownloadMgr::Fail:
mEntries[id]->SetStatus(SpkDownloadEntry::DownloadFailed,
tr("Unknown error. Download failed."));
break;
}
if(status == SpkDownloadMgr::Success)
SpkUiMessage::SendDesktopNotification(
tr("App \"%1\" downloaded, and ready to install.").arg(mEntries[id]->GetTaskName()));
else if(status != SpkDownloadMgr::FailCancel)
SpkUiMessage::SendDesktopNotification(
tr("Error occurred downloading \"%1\".").arg(mEntries[id]->GetTaskName()));
// Continue next download task
if(!mWaitingDownloads.isEmpty())
{
auto nextTask = mWaitingDownloads.dequeue();
auto nextEntry = mEntries[nextTask.first];
nextEntry->SetStatus(SpkDownloadEntry::Starting);
mDownloadMgr->StartNewDownload(nextTask.second, nextTask.first);
mCurrentStatus = Waiting;
}
else
{
mCurrentStatus = Idle;
}
}
void SpkUi::SpkPageDownloads::EntryAction(SpkDownloadEntry::EntryAction act)
{
SpkDownloadEntry *entry = static_cast<SpkDownloadEntry*>(sender());
auto id = entry->property("entryId").toInt();
switch(act)
{
case SpkDownloadEntry::AbortDownload:
mDownloadMgr->CancelCurrentDownload(); // Only one task at a time so simply abort download
break;
case SpkDownloadEntry::RetryDownload:
mLayEntries->removeWidget(entry); // Move to list tail
mLayEntries->addWidget(entry);
NewDownloadTask(id, entry->property("path").toString());
entry->SetStatus(SpkDownloadEntry::Waiting);
break;
case SpkDownloadEntry::StartInstall:
switch(PKG->ExecuteInstallation(entry->GetFilePath(), id))
{
case SpkPkgMgrBase::Succeeded:
entry->SetStatus(SpkDownloadEntry::Installing);
break;
case SpkPkgMgrBase::Failed:
entry->SetStatus(SpkDownloadEntry::InstallFailed,
tr("Failed to start installation."));
break;
default: break;
}
break;
case SpkDownloadEntry::RemoveEntry:
mLayEntries->removeWidget(entry);
mEntries.remove(id);
for(auto i = mWaitingDownloads.begin(); i != mWaitingDownloads.end(); i++)
{
if(i->first == id)
{
mWaitingDownloads.erase(i);
break;
}
}
entry->setVisible(false);
entry->deleteLater();
break;
}
}
void SpkUi::SpkPageDownloads::InstallationEnded(int id,
SpkPkgMgrBase::PkgInstallResult result,
int exitCode)
{
if(result == SpkPkgMgrBase::Succeeded)
{
mEntries[id]->SetStatus(SpkDownloadEntry::Installed);
}
else
{
mEntries[id]->SetStatus(SpkDownloadEntry::InstallFailed,
tr("Install failed, exit code: %1.").arg(exitCode));
}
}
void SpkUi::SpkPageDownloads::NewDownloadTask(int id, QString downloadPath)
{
if(mCurrentStatus != Idle)
mWaitingDownloads.enqueue({ id, downloadPath }); // Queue download task for future
else
{
auto nextEntry = mEntries[id];
nextEntry->SetStatus(SpkDownloadEntry::Starting);
mCurrentStatus = Waiting;
if(!mDownloadMgr->StartNewDownload(downloadPath, id)) // Initiate a download task when idle
{
// If fails to start then try next one. Emitting this signal causes
// SpkPageDownloads::DownloadStopped to be activated and thus tries next item in queue
emit mDownloadMgr->DownloadStopped(SpkDownloadMgr::FailNoVaibleServer, id);
}
}
}

View File

@@ -1,50 +0,0 @@
#include <QDesktopServices>
#include "page/spkpagehome.h"
#include "spkabout.h"
#include "gitver.h"
SpkUi::SpkPageHome::SpkPageHome(QWidget *parent) :
SpkPageBase(parent)
{
ui = new Ui::SpkHomepage;
ui->setupUi(this);
SetupUi();
}
void SpkUi::SpkPageHome::LinkActivated(QString s)
{
QDesktopServices::openUrl(QUrl(s));
}
void SpkUi::SpkPageHome::SetupUi()
{
ui->lblIcon->setPixmap(QIcon(":/icons/spark-store.svg").pixmap(QSize(128, 128)));
ui->hlayTitle->setAlignment(Qt::AlignHCenter);
ui->lblVersion->setText(ui->lblVersion->text().arg(GitVer::DescribeTags()));
ui->lblNewAnnouncement->setVisible(false);
// Click event will propagate to the main window and cause the window to move when
// mouse enters the zoom & move detection area. Disable mouse event propagation.
ui->lblAuthor->setAttribute(Qt::WA_NoMousePropagation, true);
ui->widReloadCategory->setVisible(false);
ui->widReloadCategory->setAttribute(Qt::WA_StyledBackground);
ui->lblCategoryErrIcon->setPixmap(QIcon::fromTheme("dialog-error").pixmap(QSize(32, 32)));
connect(ui->lblAuthor, &QLabel::linkActivated,
this, &SpkPageHome::LinkActivated);
connect(ui->btnSubmit, &QPushButton::clicked,
[&](){ LinkActivated("https://upload.deepinos.org"); });
connect(ui->btnFeedback, &QPushButton::clicked,
[&](){ LinkActivated("https://www.deepinos.org/t/spark-feedback"); });
connect(ui->btnDonation, &QPushButton::clicked,
[&](){ LinkActivated("https://spark.deepinos.org.cn/"); });
connect(ui->btnAbout, &QPushButton::clicked,
[&](){ SpkAbout::Show(); });
}

View File

@@ -1,225 +0,0 @@
#include <QtConcurrent/QtConcurrentRun>
#include <QMutexLocker>
#include <QFutureWatcher>
#include "spkutils.h"
#include "page/spkpagesettings.h"
#include "spkmsgbox.h"
namespace SpkUi
{
SpkPageSettings::SpkPageSettings(QWidget *parent) :
SpkPageBase(parent)
{
mMainArea = new QScrollArea();
mMainLay = new QVBoxLayout(this);
mSettingsWidget = new QWidget(this);
ui = new Ui::SpkUiSettings;
ui->setupUi(mSettingsWidget);
mMainLay->addWidget(mMainArea);
mMainArea->setWidget(mSettingsWidget);
mMainArea->setWidgetResizable(true);
CFG->BindField("url/repo", &this->mRepoListUrl,
"https://d.store.deepinos.org.cn/store/server.list");
mBytesDownloads = mBytesResource = -1;
connect(&mFwResourceClean, &QFutureWatcher<void>::finished,
this, &SpkPageSettings::CleanedResource);
connect(&mFwResourceCount, &QFutureWatcher<void>::finished,
this, &SpkPageSettings::CountFinishResource);
connect(&mFwDownloadClean, &QFutureWatcher<void>::finished,
this, &SpkPageSettings::CleanedDownload);
connect(&mFwDownloadCount, &QFutureWatcher<void>::finished,
this, &SpkPageSettings::CountFinishDownload);
connect(ui->btnViewDownloadedContent, &QPushButton::clicked,
this, &SpkPageSettings::on_btnViewDownloadedContent_clicked);
connect(ui->btnViewResourceCache, &QPushButton::clicked,
this, &SpkPageSettings::on_btnViewResourceCache_clicked);
connect(ui->btnCleanDownloadedContent, &QPushButton::clicked,
this, &SpkPageSettings::on_btnCleanDownloadedContent_clicked);
connect(ui->btnCleanResourceCache, &QPushButton::clicked,
this, &SpkPageSettings::on_btnCleanResourceCache_clicked);
SetupUi();
}
SpkPageSettings::~SpkPageSettings()
{
delete mSettingsWidget;
}
void SpkPageSettings::SetupUi()
{
ui->lblSettingsTitle->setObjectName("styConfTitle");
ui->lblCleanup->setObjectName("styConfTitle");
ui->lblAdvanced->setObjectName("styConfTitle");
connect(ui->btnSave, &QPushButton::clicked,
this, &SpkPageSettings::SaveConfiguration);
}
void SpkPageSettings::ReadConfiguration()
{
ui->spnConcurrentResDownloads->setValue(CFG->ReadField("resource/concurrent", 5).toInt());
ui->edtApiUrl->setText(CFG->ReadField("url/api", "").toString());
ui->edtResourceUrl->setText(CFG->ReadField("url/res", "").toString());
ui->edtResourceCachePath->setText(CFG->ReadField("dirs/cache", "").toString());
ui->edtDownloadPath->setText(CFG->ReadField("dirs/download", "").toString());
ui->edtDownloadServers->setPlainText(CFG->ReadField("download/servers", "").toString());
ui->edtQssPath->setText(CFG->ReadField("internal/qss_path", "").toString());
ui->edtRepoListUrl->setText(CFG->ReadField("url/repo", "").toString());
ui->cmbLightDarkTheme->setCurrentIndex(CFG->ReadField("ui/theme", 0).toInt());
}
void SpkPageSettings::SaveConfiguration()
{
CFG->SetSettings("resource/concurrent", ui->spnConcurrentResDownloads->value());
CFG->SetField("url/api", ui->edtApiUrl->text());
CFG->SetField("url/res", ui->edtResourceUrl->text());
CFG->SetSettings("dirs/cache", ui->edtResourceCachePath->text());
CFG->SetField("dirs/download", ui->edtDownloadPath->text());
CFG->SetSettings("internal/qss_path", ui->edtQssPath->text());
CFG->SetField("url/repo", ui->edtRepoListUrl->text());
if(!CFG->SetField("download/servers", ui->edtDownloadServers->toPlainText()))
SpkMsgBox::StaticExec(tr("Cannot change distribution servers.\n"
"There's probably still downloads going on."),
tr("Cannot set distribution server"),
QMessageBox::Warning);
if(!CFG->SetField("ui/theme", ui->cmbLightDarkTheme->currentIndex()))
SpkMsgBox::StaticExec(tr("Auto mode can only be used when DDE plugin is loaded.\n"
"Option change is not applied."),
tr("Cannot set theme mode"),
QMessageBox::Warning);
}
void SpkPageSettings::CountCleaning()
{
ui->lblSizeDownloadedContent->setText(tr("Counting..."));
ui->lblSizeResourceCache->setText(tr("Counting..."));
auto futureDownload = QtConcurrent::run([&]()
{
QDirIterator itr(ui->edtDownloadPath->text().replace('*', QDir::homePath()),
QDirIterator::Subdirectories);
if(mMutDownload.tryLock(0))
{
int64_t size = 0;
while(itr.hasNext())
{
QFile f(itr.next());
size += f.size();
}
mBytesDownloads = size;
mMutDownload.unlock();
}
});
auto futureResource = QtConcurrent::run([&]()
{
QDirIterator itr(ui->edtResourceCachePath->text().replace('*', QDir::homePath()),
QDirIterator::Subdirectories);
if(mMutResource.tryLock((0)))
{
int64_t size = 0;
while(itr.hasNext())
{
QFile f(itr.next());
size += f.size();
}
mBytesResource = size;
mMutResource.unlock();
}
});
mFwDownloadCount.setFuture(futureDownload);
mFwResourceCount.setFuture(futureResource);
}
void SpkPageSettings::CleanedResource()
{
ui->lblSizeResourceCache->setText(tr("Cleaned"));
}
void SpkPageSettings::CleanedDownload()
{
ui->lblSizeDownloadedContent->setText(tr("Cleaned"));
}
void SpkPageSettings::Activated()
{
ReadConfiguration();
CountCleaning();
}
void SpkPageSettings::CountFinishResource()
{
if(mBytesResource >= 0)
ui->lblSizeResourceCache->setText(SpkUtils::BytesToSize(mBytesResource));
}
void SpkPageSettings::CountFinishDownload()
{
if(mBytesDownloads >= 0)
ui->lblSizeDownloadedContent->setText(SpkUtils::BytesToSize(mBytesDownloads));
}
void SpkPageSettings::on_btnViewResourceCache_clicked()
{
QDesktopServices::openUrl(ui->edtResourceCachePath->text().replace('*', QDir::homePath()));
}
void SpkPageSettings::on_btnViewDownloadedContent_clicked()
{
QDesktopServices::openUrl(ui->edtDownloadPath->text().replace('*', QDir::homePath()));
}
void SpkPageSettings::on_btnCleanResourceCache_clicked()
{
ui->lblSizeResourceCache->setText(tr("Cleaning..."));
auto future = QtConcurrent::run([&]()
{
QDirIterator itr(ui->edtResourceCachePath->text().replace('*', QDir::homePath()),
QDirIterator::Subdirectories);
if(mMutDownload.tryLock(0))
{
int64_t size = 0;
while(itr.hasNext())
{
QFile f(itr.next());
f.remove();
}
mBytesDownloads = size;
mMutDownload.unlock();
}
});
mFwResourceClean.setFuture(future);
}
void SpkPageSettings::on_btnCleanDownloadedContent_clicked()
{
ui->lblSizeDownloadedContent->setText(tr("Cleaning..."));
auto futureDownload = QtConcurrent::run([&]()
{
QDirIterator itr(ui->edtDownloadPath->text().replace('*', QDir::homePath()),
QDirIterator::Subdirectories);
if(mMutDownload.tryLock(0))
{
int64_t size = 0;
while(itr.hasNext())
{
QFile f(itr.next());
f.remove();
}
mBytesDownloads = size;
mMutDownload.unlock();
}
});
mFwDownloadClean.setFuture(futureDownload);
}
}

View File

@@ -1,165 +0,0 @@
#include <QApplication>
#include "spkabout.h"
#include "inc/page/spkpageuitest.h"
#include "spkpopup.h"
#include "spkui_general.h"
#include "pkgs/spkpkgmgrbase.h"
SpkUi::SpkPageUiTest::SpkPageUiTest(QWidget *parent) : QSplitter(parent)
{
setObjectName("spk_pg_qsstest");
TextStylesheet = new QTextEdit(this);
TextStylesheet->setObjectName("spk_pg_qsstest_qsstext");
TextStylesheet->setPlainText(SpkUi::CurrentStylesheet);
BtnApply = new QPushButton(this);
BtnApply->setObjectName("spk_pg_qsstest_btnapply");
BtnApply->setText("Apply");
connect(BtnApply, &QPushButton::pressed, this, &SpkPageUiTest::SetStylesheet);
BtnFetch = new QPushButton(this);
BtnFetch->setObjectName("spk_pg_qsstest_btnfetch");
BtnFetch->setText("Fetch Stylesheet");
connect(BtnFetch, &QPushButton::pressed, this, &SpkPageUiTest::FetchStylesheet);
HLayInputBtns = new QHBoxLayout;
HLayInputBtns->setObjectName("spk_pg_qsstest_hlay_inputbtns");
HLayInputBtns->addWidget(BtnFetch);
HLayInputBtns->addWidget(BtnApply);
Btn = new QPushButton(this);
Btn->setObjectName("spk_pg_qsstest_button");
Btn->setText("TestButton");
Chk = new QCheckBox(this);
Chk->setObjectName("spk_pg_qsstest_checkbox");
Chk->setText("CheckBox");
Rad = new QRadioButton(this);
Rad->setObjectName("spk_pg_qsstest_radiobtn");
Rad->setText("RadioButton");
Loading = new SpkLoading(this);
Loading->setObjectName("spk_pg_qsstest_loading");
Loading->start();
Prog = new QProgressBar(this);
Prog->setObjectName("spk_pg_qsstest_prog");
Prog->setValue(65);
Prog->setRange(0, 100);
AppItem = new SpkAppItem(0, this);
AppItem->setObjectName("spk_pg_qsstest_appitem");
AppItem->SetTitle("Lorem ipsum dolor sit amet, consectetur adipiscing elit.");
AppItem->SetDescription("Nam vehicula lacus vitae leo fermentum efficitur. "
"Phasellus finibus risus id aliquam pulvinar.");
AppItem->SetIcon(QIcon::fromTheme("dialog-information").pixmap(72, 72));
Detail1 = new SpkDetailEntry; Detail1->SetTitle("Foo"); Detail1->SetValue("1");
Detail2 = new SpkDetailEntry; Detail2->SetTitle("Foo"); Detail2->SetValue("1");
Detail3 = new SpkDetailEntry; Detail3->SetTitle("Foo"); Detail3->SetValue("1");
DetailsLay = new SpkStretchLayout;
DetailsLay->addWidget(Detail1);
DetailsLay->addWidget(Detail2);
DetailsLay->addWidget(Detail3);
DetailsWidget = new QWidget;
DetailsWidget->setLayout(DetailsLay);
PopupText = new QLineEdit(this);
PopupText->setObjectName("spk_pg_qsstest_poptext");
PopupText->setText("Hello, world");
ShowPopup = new QPushButton(this);
ShowPopup->setText("Show Popup");
connect(ShowPopup, &QPushButton::clicked, this, &SpkPageUiTest::ShowPopupSlot);
ShowAbout = new QPushButton(this);
ShowAbout->setText("Show About Dialog");
connect(ShowAbout, &QPushButton::clicked, [](){ SpkAbout::Show(); });
ShowPkgmgr = new QPushButton(this);
ShowPkgmgr->setText("Show Install Menu");
connect(ShowPkgmgr, &QPushButton::clicked, [=](){ SpkPkgMgrBase::Instance()->ExecuteInstallation(PopupText->text(), 0); });
SlideV = new QSlider(this);
SlideV->setObjectName("spk_pg_qsstest_slider_v");
SlideV->setOrientation(Qt::Vertical);
SlideV->setMaximum(1000);
SlideV->setMinimum(0);
SlideH = new QSlider(this);
SlideH->setObjectName("spk_pg_qsstest_slider_h");
SlideH->setOrientation(Qt::Horizontal);
SlideH->setMaximum(1000);
SlideH->setMinimum(0);
IconBtn = new SpkIconButton(this);
IconBtn->setObjectName("spk_pg_qsstest_iconbtn");
IconBtn->SetIcon(QIcon(":/icons/settings.svg"), QSize{ 16, 16 });
VLayTestWidgets = new QVBoxLayout;
VLayTestWidgets->setObjectName("spk_pg_qsstest_vlay_btn");
VLayTestWidgets->addWidget(Btn);
VLayTestWidgets->addWidget(Chk);
VLayTestWidgets->addWidget(Rad);
VLayTestWidgets->addWidget(IconBtn);
VLayTestWidgets->addWidget(Loading);
VLayTestWidgets->addWidget(PopupText);
VLayTestWidgets->addWidget(ShowPopup);
VLayTestWidgets->addWidget(ShowAbout);
VLayTestWidgets->addWidget(ShowPkgmgr);
VLayTestWidgets->addWidget(AppItem);
VLayTestWidgets->addWidget(DetailsWidget);
Group = new QGroupBox(this);
Group->setObjectName("spk_pg_qsstest_groupbox");
Group->setTitle("GroupBox");
Group->setLayout(VLayTestWidgets);
VLayInput = new QVBoxLayout;
VLayInput->setObjectName("spk_pg_qsstest_inputlay");
VLayInput->addWidget(TextStylesheet);
VLayInput->addLayout(HLayInputBtns);
VLayWidgets = new QVBoxLayout;
VLayWidgets->setObjectName("spk_pg_qsstest_widgetlay");
VLayWidgets->addWidget(Group);
VLayWidgets->addWidget(SlideH);
VLayWidgets->addWidget(Prog);
HLay4Slider = new QHBoxLayout;
HLay4Slider->setObjectName("spk_pg_qsstest_hlay_for_slider");
HLay4Slider->addLayout(VLayWidgets);
HLay4Slider->addWidget(SlideV);
WidL = new QWidget(this);
WidL->setObjectName("spk_pg_qsstest_widleft");
WidL->setLayout(HLay4Slider);
WidL->setSizePolicy(QSizePolicy::Maximum, QSizePolicy::Preferred);
WidR = new QWidget(this);
WidR->setObjectName("spk_pg_qsstest_widright");
WidR->setLayout(VLayInput);
addWidget(WidL);
addWidget(WidR);
}
void SpkUi::SpkPageUiTest::SetStylesheet()
{
qApp->setStyleSheet(TextStylesheet->toPlainText());
}
void SpkUi::SpkPageUiTest::FetchStylesheet()
{
TextStylesheet->setPlainText(SpkUi::CurrentStylesheet);
}
void SpkUi::SpkPageUiTest::ShowPopupSlot()
{
SpkUi::Popup->Show(PopupText->text());
}

View File

@@ -1,361 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>SpkHomepage</class>
<widget class="QWidget" name="SpkHomepage">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>648</width>
<height>554</height>
</rect>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Maximum">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="windowTitle">
<string>Form</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeType">
<enum>QSizePolicy::Fixed</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
<item>
<layout class="QHBoxLayout" name="hlayTitle">
<item>
<widget class="QLabel" name="lblIcon">
<property name="sizePolicy">
<sizepolicy hsizetype="Maximum" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>{spark-store-icon}</string>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="lblTitle">
<property name="sizePolicy">
<sizepolicy hsizetype="Maximum" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="font">
<font>
<pointsize>40</pointsize>
</font>
</property>
<property name="text">
<string>Spark Store</string>
</property>
</widget>
</item>
</layout>
</item>
<item>
<widget class="QLabel" name="lblAuthor">
<property name="text">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Brought to you by &lt;a href=&quot;https://spark-app.store&quot;&gt;&lt;span style=&quot; text-decoration: underline; color:#007af4;&quot;&gt;Spark Project&lt;/span&gt;&lt;/a&gt;, an open source software project.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
</widget>
</item>
<item>
<spacer name="verticalSpacer_3">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeType">
<enum>QSizePolicy::Fixed</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>50</height>
</size>
</property>
</spacer>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_2">
<item>
<layout class="QGridLayout" name="vlayBtns">
<item row="1" column="1">
<widget class="SpkNotifyDot" name="lblNewAnnouncement">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>20</width>
<height>20</height>
</size>
</property>
<property name="text">
<string>0</string>
</property>
</widget>
</item>
<item row="0" column="0">
<widget class="QLabel" name="lblAboutProject">
<property name="text">
<string>About this project...</string>
</property>
</widget>
</item>
<item row="3" column="0">
<widget class="QPushButton" name="btnFeedback">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>150</width>
<height>0</height>
</size>
</property>
<property name="text">
<string>Feedback</string>
</property>
</widget>
</item>
<item row="4" column="0">
<widget class="QPushButton" name="btnDonation">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>150</width>
<height>0</height>
</size>
</property>
<property name="text">
<string>Donation</string>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QPushButton" name="btnAnnouncements">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>150</width>
<height>0</height>
</size>
</property>
<property name="text">
<string>Announcements</string>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QPushButton" name="btnSubmit">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>150</width>
<height>0</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>16777215</width>
<height>16777215</height>
</size>
</property>
<property name="text">
<string>Submit Software</string>
</property>
</widget>
</item>
</layout>
</item>
<item>
<spacer name="horizontalSpacer_3">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeType">
<enum>QSizePolicy::Expanding</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
</layout>
</item>
<item>
<spacer name="verticalSpacer_2">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeType">
<enum>QSizePolicy::Expanding</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QWidget" name="widReloadCategory" native="true">
<layout class="QHBoxLayout" name="horizontalLayout_3">
<item>
<widget class="QLabel" name="lblCategoryErrIcon">
<property name="text">
<string>{error-icon}</string>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer_4">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QLabel" name="lblCategoryErr">
<property name="sizePolicy">
<sizepolicy hsizetype="Maximum" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Category failed to load. Click the button to retry.</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="btnReloadCategory">
<property name="sizePolicy">
<sizepolicy hsizetype="Maximum" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Reload</string>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer_2">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
</layout>
</widget>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="QLabel" name="lblVersion">
<property name="text">
<string>Version %1</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="btnAbout">
<property name="sizePolicy">
<sizepolicy hsizetype="Maximum" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>About</string>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
</layout>
</item>
</layout>
</widget>
<customwidgets>
<customwidget>
<class>SpkNotifyDot</class>
<extends>QLabel</extends>
<header>spknotifydot.h</header>
</customwidget>
</customwidgets>
<resources/>
<connections/>
</ui>

View File

@@ -1,472 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>SpkUiSettings</class>
<widget class="QWidget" name="SpkUiSettings">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>581</width>
<height>896</height>
</rect>
</property>
<property name="windowTitle">
<string>Form</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<layout class="QHBoxLayout" name="layTitle">
<item>
<widget class="QLabel" name="lblSettingsTitle">
<property name="text">
<string>Spark Store Settings</string>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QPushButton" name="btnSave">
<property name="text">
<string>Apply</string>
</property>
</widget>
</item>
</layout>
</item>
<item>
<widget class="Line" name="lineTitle">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="lblRestartHint">
<property name="text">
<string>Configuration entries marked &quot;*&quot; will only take effect after restarting Spark Store.</string>
</property>
</widget>
</item>
<item>
<layout class="QGridLayout" name="laySettings">
<item row="5" column="0">
<widget class="QLabel" name="lblApiUrl">
<property name="text">
<string>Store API URL</string>
</property>
</widget>
</item>
<item row="6" column="0">
<widget class="QLabel" name="lblResourceUrl">
<property name="text">
<string>Store resource URL</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QLineEdit" name="edtDownloadPath">
<property name="spkcfg_key" stdset="0">
<string notr="true">dirs/download</string>
</property>
</widget>
</item>
<item row="4" column="0">
<widget class="QLabel" name="lblResourceCachePath">
<property name="text">
<string>Resource cache path*</string>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QLabel" name="lblAptRepo">
<property name="text">
<string>APT Repository</string>
</property>
</widget>
</item>
<item row="6" column="1">
<widget class="QLineEdit" name="edtResourceUrl">
<property name="spkcfg_key" stdset="0">
<string>url/res</string>
</property>
</widget>
</item>
<item row="2" column="1">
<layout class="QHBoxLayout" name="layAptRepo">
<property name="spacing">
<number>4</number>
</property>
<item>
<widget class="QComboBox" name="cmbAptRepo">
<property name="sizePolicy">
<sizepolicy hsizetype="Minimum" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="spkcfg_key" stdset="0">
<string notr="true">pkgmgr/apt_repo</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="btnFetchAptRepo">
<property name="sizePolicy">
<sizepolicy hsizetype="Maximum" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Fetch all</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="btnApplyAptRepo">
<property name="sizePolicy">
<sizepolicy hsizetype="Maximum" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Apply</string>
</property>
</widget>
</item>
</layout>
</item>
<item row="0" column="0">
<widget class="QLabel" name="lblLightDarkTheme">
<property name="text">
<string>Light/dark theme</string>
</property>
</widget>
</item>
<item row="4" column="1">
<widget class="QLineEdit" name="edtResourceCachePath">
<property name="spkcfg_key" stdset="0">
<string>dirs/cache</string>
</property>
</widget>
</item>
<item row="3" column="1">
<widget class="QPlainTextEdit" name="edtDownloadServers">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Maximum">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>0</width>
<height>80</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>16777215</width>
<height>150</height>
</size>
</property>
<property name="baseSize">
<size>
<width>100</width>
<height>100</height>
</size>
</property>
<property name="spkcfg_key" stdset="0">
<string notr="true">download/servers</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QComboBox" name="cmbLightDarkTheme">
<property name="currentIndex">
<number>3</number>
</property>
<property name="frame">
<bool>true</bool>
</property>
<property name="spkcfg_key" stdset="0">
<string notr="true">gui/theme</string>
</property>
<item>
<property name="text">
<string>Auto (DDE only)</string>
</property>
</item>
<item>
<property name="text">
<string>Always Light</string>
</property>
</item>
<item>
<property name="text">
<string>Always Dark</string>
</property>
</item>
<item>
<property name="text">
<string>Manual</string>
</property>
</item>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="lblDownloadPath">
<property name="toolTip">
<string/>
</property>
<property name="toolTipDuration">
<number>-1</number>
</property>
<property name="text">
<string>Download path*</string>
</property>
</widget>
</item>
<item row="3" column="0">
<widget class="QLabel" name="lblDownloadServers">
<property name="toolTip">
<string>Server addresses are separated with two semicolons (;;).</string>
</property>
<property name="toolTipDuration">
<number>1</number>
</property>
<property name="text">
<string>Download servers</string>
</property>
<property name="alignment">
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set>
</property>
</widget>
</item>
<item row="5" column="1">
<widget class="QLineEdit" name="edtApiUrl">
<property name="spkcfg_key" stdset="0">
<string>url/api</string>
</property>
</widget>
</item>
<item row="7" column="0">
<widget class="QLabel" name="lblRepoListUrl">
<property name="text">
<string>APT Repository Source</string>
</property>
</widget>
</item>
<item row="7" column="1">
<widget class="QLineEdit" name="edtRepoListUrl"/>
</item>
</layout>
</item>
<item>
<widget class="QLabel" name="lblHomeNotice">
<property name="text">
<string>Note: character &quot;*&quot; in paths are replaced with the current user's home path.</string>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="lblCleanup">
<property name="text">
<string>Cache and Downloads cleanup</string>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="lblCleanupDescription">
<property name="text">
<string>Spark Store caches resources such as app icons and screenshots locally. If you want to free up space, you can clear them here or delete them manually.</string>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<layout class="QGridLayout" name="layCleanup">
<item row="1" column="3">
<widget class="QPushButton" name="btnCleanDownloadedContent">
<property name="sizePolicy">
<sizepolicy hsizetype="Maximum" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Clear</string>
</property>
</widget>
</item>
<item row="0" column="2">
<widget class="QPushButton" name="btnViewResourceCache">
<property name="sizePolicy">
<sizepolicy hsizetype="Maximum" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>View</string>
</property>
</widget>
</item>
<item row="1" column="2">
<widget class="QPushButton" name="btnViewDownloadedContent">
<property name="sizePolicy">
<sizepolicy hsizetype="Maximum" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>View</string>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="lblDownloadedContent">
<property name="text">
<string>Downloaded content</string>
</property>
</widget>
</item>
<item row="0" column="0">
<widget class="QLabel" name="lblResourceCache">
<property name="text">
<string>Resource cache</string>
</property>
</widget>
</item>
<item row="0" column="3">
<widget class="QPushButton" name="btnCleanResourceCache">
<property name="sizePolicy">
<sizepolicy hsizetype="Maximum" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Clear</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QLabel" name="lblSizeResourceCache">
<property name="sizePolicy">
<sizepolicy hsizetype="Maximum" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string/>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QLabel" name="lblSizeDownloadedContent">
<property name="sizePolicy">
<sizepolicy hsizetype="Maximum" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string/>
</property>
</widget>
</item>
</layout>
</item>
<item>
<widget class="QLabel" name="lblAdvanced">
<property name="text">
<string>Advanced</string>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="lblAdvancedDescription">
<property name="text">
<string>Advanced settings are low-level configurations that can affect usability and are not meant to be modified by average users.</string>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<layout class="QGridLayout" name="layAdvanced">
<item row="0" column="0">
<widget class="QLabel" name="lblConcurrentResDownloads">
<property name="text">
<string>Concurrent resource downloads*</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QSpinBox" name="spnConcurrentResDownloads">
<property name="sizePolicy">
<sizepolicy hsizetype="Maximum" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>50</width>
<height>0</height>
</size>
</property>
<property name="minimum">
<number>1</number>
</property>
<property name="maximum">
<number>6</number>
</property>
<property name="value">
<number>5</number>
</property>
<property name="spkcfg_key" stdset="0">
<string>resource/concurrent</string>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="lblQssPath">
<property name="text">
<string>Default Qt Style Sheet template*</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QLineEdit" name="edtQssPath">
<property name="spkcfg_key" stdset="0">
<string>internal/qss_path</string>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</widget>
<resources/>
<connections/>
</ui>

View File

@@ -1,133 +0,0 @@
/****************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the QtCore module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:BSD$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** BSD License Usage
** Alternatively, you may use this file under the terms of the BSD license
** as follows:
**
** "Redistribution and use in source and binary forms, with or without
** modification, are permitted provided that the following conditions are
** met:
** * Redistributions of source code must retain the above copyright
** notice, this list of conditions and the following disclaimer.
** * Redistributions in binary form must reproduce the above copyright
** notice, this list of conditions and the following disclaimer in
** the documentation and/or other materials provided with the
** distribution.
** * Neither the name of The Qt Company Ltd nor the names of its
** contributors may be used to endorse or promote products derived
** from this software without specific prior written permission.
**
**
** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
**
** $QT_END_LICENSE$
**
****************************************************************************/
/*
* Slight modifications has been done to the code to make it fit into the project.
*/
#include "qt/elidedlabel.h"
#include <QPainter>
#include <QSizePolicy>
#include <QTextLayout>
//! [0]
ElidedLabel::ElidedLabel(const QString &text, QWidget *parent)
: QFrame(parent)
, elided(false)
, content(text)
{
setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred);
}
//! [0]
//! [1]
void ElidedLabel::setText(const QString &newText)
{
content = newText;
update();
}
//! [1]
//! [2]
void ElidedLabel::paintEvent(QPaintEvent *event)
{
QFrame::paintEvent(event);
QPainter painter(this);
QFontMetrics fontMetrics = painter.fontMetrics();
bool didElide = false;
int lineSpacing = fontMetrics.lineSpacing();
int y = 0;
QTextLayout textLayout(content, painter.font());
textLayout.beginLayout();
forever {
QTextLine line = textLayout.createLine();
if (!line.isValid())
break;
line.setLineWidth(width());
int nextLineY = y + lineSpacing;
if (height() >= nextLineY + lineSpacing) {
line.draw(&painter, QPoint(0, y));
y = nextLineY;
//! [2]
//! [3]
} else {
QString lastLine = content.mid(line.textStart());
QString elidedLastLine = fontMetrics.elidedText(lastLine, Qt::ElideRight, width());
painter.drawText(QPoint(0, y + fontMetrics.ascent()), elidedLastLine);
line = textLayout.createLine();
didElide = line.isValid();
break;
}
}
textLayout.endLayout();
//! [3]
//! [4]
if (didElide != elided) {
elided = didElide;
emit elisionChanged(didElide);
}
}
ElidedLabel::ElidedLabel(QWidget *parent)
: QFrame(parent)
, elided(false)
, content("")
{
setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred);
}
//! [4]

View File

@@ -1,73 +0,0 @@
#include <QDesktopServices>
#include "spkabout.h"
#include "gitver.h"
SpkAbout::SpkAbout(QWidget *parent) : SpkDialog(parent)
{
setWindowModality(Qt::ApplicationModal);
// mDialogWidget->setMaximumWidth(600);
mDialogWidget->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
setFixedSize(550, 450);
SetResizable(false); // Do you like the dilemma of using self created widget?
mIconLay = new QHBoxLayout;
mSpkVersion = new QLabel;
mSpkVersion->setText(tr("<h1>Spark Store</h1>"
"<h3>Version <a href=\"https://www.spark-app.store\">%1</a></h3>"
"<t>Built on %2 %3</t>")
.arg(GitVer::DescribeTags(),
__DATE__, __TIME__));
connect(mSpkVersion, &QLabel::linkActivated,
[](const QString &link){ QDesktopServices::openUrl(link); });
mSpkIcon = new QLabel;
mSpkIcon->setPixmap(QIcon(":/icons/spark-store.svg").pixmap(QSize(128, 128)));
auto description = tr(
"Spark Store was started when Chinese home-grown Linux operating systems "
"had initially hit the market. Because the Linux desktop ecosystem is not "
"good enough at the time being, volunteers built this small App Store in "
"the hope that users can get useful applications faster.\n\n"
"Right now we are not just a Chinese group. We are discovering our way into "
"more Debian-based Linux OSes, and build a real community software repository "
"for users around the world.");
mDescriptionText = new QLabel;
mDescriptionText->setObjectName("spk_about_desc");
mDescriptionText->setWordWrap(true);
mDescriptionText->setText(description);
mIconLay->addStretch(3);
mIconLay->addWidget(mSpkIcon);
mIconLay->addStretch(1);
mIconLay->addWidget(mSpkVersion);
mIconLay->addStretch(3);
mIconLay->setAlignment(Qt::AlignVCenter | Qt::AlignHCenter);
AddStretch();
AddLayout(mIconLay);
AddSpacing(18);
AddWidget(mDescriptionText);
AddStretch();
SetMargin(18, 0, 18, 18);
GetTitleBar()->SetOperationButton(SpkTitleBar::OperationButton::Close);
GetTitleBar()->SetTitle(tr("About Spark Store"));
}
SpkAbout::~SpkAbout()
{
// delete mIconLay;
// delete mDescriptionText;
}
void SpkAbout::Show()
{
SpkAbout *b = new SpkAbout;
b->Exec();
delete b;
}

View File

@@ -1,63 +0,0 @@
#include <QPainter>
#include <QStyleOption>
#include "spkappitem.h"
#include "qt/elidedlabel.h"
const QSize SpkAppItem::IconSize_;
SpkAppItem::SpkAppItem(int appId, QWidget *parent) : QWidget(parent)
{
mAppId = appId;
mMainLay = new QHBoxLayout(this);
mLayText = new QVBoxLayout;
mIcon = new QLabel;
mIcon->setFixedSize(IconSize, IconSize);
mIcon->setAutoFillBackground(false);
// NOTE: Make mTitle ElidedTitle too?
mTitle = new QLabel;
mTitle->setWordWrap(false);
mTitle->setObjectName("styAppItmTitle");
mTitle->setAutoFillBackground(true);
mDescription = new ElidedLabel;
// mDescription->setWordWrap(true); // Commented out since ElidedLabel lacks of these methods
mDescription->setObjectName("styAppItmDesc");
mDescription->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
// mDescription->setAlignment(Qt::AlignTop | Qt::AlignLeft);
// mDescription->setAutoFillBackground(true);
mLayText->addWidget(mTitle);
mLayText->addWidget(mDescription);
mLayText->setAlignment(Qt::AlignTop);
mMainLay->setMargin(5);
mMainLay->addWidget(mIcon);
mMainLay->addLayout(mLayText);
setMinimumHeight(82);
setMaximumHeight(82);
setMinimumWidth(300);
}
void SpkAppItem::paintEvent(QPaintEvent *e)
{
Q_UNUSED(e)
QStyleOption opt;
opt.init(this);
QPainter p(this);
style()->drawPrimitive(QStyle::PE_Widget, &opt, &p, this);
}
void SpkAppItem::mousePressEvent(QMouseEvent *e)
{
mPressCond = true;
}
void SpkAppItem::mouseReleaseEvent(QMouseEvent *e)
{
if(mPressCond)
emit clicked(mAppId);
mPressCond = false;
}

View File

@@ -1,61 +0,0 @@
#include "spkmainwindow.h"
namespace SpkUi
{
SpkCategorySelector::SpkCategorySelector(QWidget *parent) : QWidget(parent)
{
mBtnLayout = new QVBoxLayout(this);
mGroup = new QButtonGroup(this);
}
void SpkCategorySelector::AddButton(QString aBtnText, int aCategoryId, QPixmap *aBtnIcon)
{
auto btn = new SpkCategoryButton(this);
btn->SetText(aBtnText);
if(aBtnIcon)
btn->SetIcon(*aBtnIcon);
mBtnList.append(btn);
mGroup->addButton(btn, aCategoryId ? aCategoryId : -1);
mBtnLayout->addWidget(btn);
}
void SpkCategorySelector::DeleteAllButtons() // TODO: UNTESTED
{
foreach (auto i, mBtnList)
{
mBtnLayout->removeWidget(i);
mGroup->removeButton(i);
i->deleteLater();
}
mBtnList.clear();
}
SpkCategoryButton::SpkCategoryButton(QWidget *parent) : QPushButton(parent)
{
mIcon = new QLabel(this);
mIcon->setObjectName("spk_categorybtn_label");
mText = new QLabel(this);
mText->setObjectName("spk_categorybtn_text");
mLayout = new QHBoxLayout;
mLayout->setObjectName("spk_categorybtn_lay");
mLayout->addSpacing(Spacing);
mLayout->addWidget(mIcon);
mLayout->addSpacing(Spacing);
mLayout->addStretch();
mLayout->addWidget(mText);
mLayout->addStretch();
mLayout->addSpacing(Spacing);
setLayout(mLayout);
}
void SpkCategoryButton::SetIcon(QPixmap aImage)
{
mIcon->setPixmap(aImage);
}
void SpkCategoryButton::SetText(QString aText)
{
mText->setText(aText);
}
}

View File

@@ -1,115 +0,0 @@
#include "spkdialog.h"
#include <QEventLoop>
SpkDialog::SpkDialog(QWidget *parent) : SpkWindow(parent)
{
mDialogWidget = new QWidget;
mMainVLay = new QVBoxLayout;
mWidgetsVLay = new QVBoxLayout();
mBtnLay = new QHBoxLayout();
mBtnGroup = new QButtonGroup(this);
mMainVLay->addLayout(mWidgetsVLay);
mMainVLay->addLayout(mBtnLay);
mBtnLay->setAlignment(Qt::AlignCenter);
SetCentralWidget(mDialogWidget);
mDialogWidget->setLayout(mMainVLay);
// idClicked is not available on platforms we support, shouldn't change it
connect(mBtnGroup, QOverload<int>::of(&QButtonGroup::buttonClicked),
this, &SpkDialog::ButtonPressed);
connect(this, &SpkWindow::Closed, this, &SpkDialog::ForceClose);
}
SpkDialog::~SpkDialog()
{
auto itp = mParentsList.begin();
for(auto itw = mWidgetsList.begin(); itw != mWidgetsList.end(); itw++)
{
(*itw)->setParent(*(itp++));// We shall never take the ownership of these widgets
}
delete mDialogWidget;
}
void SpkDialog::AddButton(QString text, SpkUi::SpkButtonStyle style)
{
auto b = new QPushButton();
b->setText(text);
b->setMinimumWidth(100);
b->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred);
switch(style)
{
case SpkUi::SpkButtonStyle::Recommend:
b->setObjectName("sty_recommendbtn");
break;
case SpkUi::SpkButtonStyle::Warn:
b->setObjectName("sty_warnbtn");
break;
default:
break;
}
mBtnLay->addWidget(b);
mBtnGroup->addButton(b);
}
void SpkDialog::AddWidget(QWidget *w)
{
// Adding a widget does not take the ownership.
mWidgetsVLay->addWidget(w);
mWidgetsList << w;
mParentsList << w->parentWidget();
}
void SpkDialog::AddLayout(QLayout *w)
{
mWidgetsVLay->addLayout(w);
mWidgetsList << w;
mParentsList << w->parentWidget();
}
void SpkDialog::AddSpacing(int a)
{
mWidgetsVLay->addSpacing(a);
}
void SpkDialog::AddStretch(int a)
{
mWidgetsVLay->addStretch(a);
}
void SpkDialog::SetMargin(int a)
{
mWidgetsVLay->setMargin(a);
}
int SpkDialog::Exec()
{
QEventLoop loop;
connect(this, &SpkDialog::ExitEventLoop, &loop, &QEventLoop::exit);
connect(this, &SpkDialog::CloseWindow, this, &QMainWindow::close);
show();
return loop.exec();
}
void SpkDialog::ButtonPressed(int aBtnId)
{
disconnect(this, &SpkWindow::Closed, this, &SpkDialog::ForceClose);
emit ExitEventLoop(-aBtnId - 2);
emit CloseWindow();
}
void SpkDialog::ForceClose()
{
disconnect(this, &SpkDialog::CloseWindow, this, &QMainWindow::close);
emit ExitEventLoop(-1);
}
void SpkDialog::SetMargin(int left, int top, int right, int bottom)
{
mWidgetsVLay->setContentsMargins(left, top, right, bottom);
}

View File

@@ -1,201 +0,0 @@

#include "spkdownloadentry.h"
#include "spklogging.h"
#include "spkutils.h"
#include <QDebug>
constexpr QSize SpkDownloadEntry::IconSize;
SpkDownloadEntry::SpkDownloadEntry(QWidget *parent)
{
mIcon = new QLabel;
mAppName = new ElidedLabel;
mMessage = new QLabel;
mProgress = new QProgressBar;
mLoading = new SpkLoading;
mBtnDelete = new QPushButton;
mBtnActions = new QPushButton;
mLayInfo = new QVBoxLayout;
mLayMsgs = new QHBoxLayout;
mLayMain = new QHBoxLayout;
mLoading->setVisible(false);
mIcon->setFixedSize(IconSize);
mProgress->setRange(0, 1000);
mLayMsgs->addWidget(mAppName);
mLayMsgs->addStretch();
mLayMsgs->addWidget(mMessage);
mLayInfo->addLayout(mLayMsgs);
mLayInfo->addWidget(mProgress);
mLayInfo->setAlignment(Qt::AlignVCenter);
mLayMain->addWidget(mIcon);
mLayMain->addLayout(mLayInfo);
mLayMain->addWidget(mLoading);
mLayMain->addWidget(mBtnActions);
mLayMain->addWidget(mBtnDelete);
setLayout(mLayMain);
connect(mBtnActions, &QPushButton::clicked, this, &SpkDownloadEntry::ActionButton);
connect(mBtnDelete, &QPushButton::clicked, this, &SpkDownloadEntry::DeleteButton);
mStatus = Invalid;
mLastReportTime = QTime::currentTime();
}
SpkDownloadEntry::~SpkDownloadEntry()
{
// TODO
}
void SpkDownloadEntry::SetTotalBytes(qint64 total)
{
mTotalBytes = total;
mReadableTotalSize = SpkUtils::BytesToSize(total);
mLastReportTime = QTime::currentTime();
}
void SpkDownloadEntry::SetBasicInfo(QString name, QPixmap icon, QString filePath)
{
mAppName->setText(name);
mIcon->setPixmap(icon.scaled(IconSize, Qt::IgnoreAspectRatio, Qt::SmoothTransformation));
mFilePath = filePath;
}
void SpkDownloadEntry::SetStatus(DownloadEntryStatus status, QString msg)
{
mStatus = status;
switch(status)
{
case Waiting:
mMessage->setText(tr("Waiting for download"));
mProgress->setVisible(false);
mBtnActions->setVisible(false);
mBtnDelete->setVisible(true);
mBtnDelete->setText(tr("Cancel"));
break;
case Starting:
mMessage->setText(tr("Starting download"));
mBtnDelete->setVisible(false);
break;
case Downloading:
mMessage->setText(tr(""));
mProgress->setVisible(true);
mBtnActions->setVisible(false);
mBtnDelete->setVisible(true);
break;
case DownloadFailed:
mMessage->setText(msg);
mProgress->setVisible(false);
mBtnActions->setVisible(true);
mBtnActions->setText(tr("Retry"));
break;
case ToBeInstalled:
mMessage->setText(tr("Download Finished"));
mProgress->setVisible(false);
mBtnActions->setVisible(true);
mBtnDelete->setVisible(false);
mBtnActions->setText(tr("Install"));
break;
case Installing:
mMessage->setText("");
mProgress->setVisible(false);
mBtnActions->setVisible(false);
mBtnDelete->setVisible(false);
mLoading->setVisible(true);
mLoading->Begin();
break;
case Installed:
mMessage->setText(tr("Installed"));
mLoading->End();
mLoading->setVisible(false);
mBtnDelete->setVisible(true);
mBtnDelete->setText(tr("Delete"));
break;
case InstallFailed:
mMessage->setText(msg.isEmpty() ? tr("Install Failed") : msg);
mLoading->End();
mLoading->setVisible(false);
mBtnActions->setVisible(true);
mBtnActions->setText(tr("Install"));
mBtnDelete->setVisible(true);
mBtnDelete->setText(tr("Cancel"));
break;
case Invalid:
break;
}
}
void SpkDownloadEntry::Progress(qint64 bytes)
{
auto now = QTime::currentTime();
auto msecDiff = mLastReportTime.msecsTo(now);
if(msecDiff != 0)
{
auto bytesPerSec = (bytes - mDownloadedBytes) / (msecDiff / 1000.0);
qDebug() << "Bytes" << bytes - mDownloadedBytes
<< "MsDiff" << msecDiff / 1000.0
<< "Bytes-Per-Seg" << bytesPerSec;
auto speedSize = SpkUtils::BytesToSize(static_cast<size_t>(bytesPerSec));
mMessage->setText(QString("%1/%2(%3/s)")
.arg(SpkUtils::BytesToSize(bytes), mReadableTotalSize, speedSize));
}
mDownloadedBytes = bytes;
mProgress->setValue(static_cast<int>(((double)bytes) / mTotalBytes * 1000));
mLastReportTime = now;
}
void SpkDownloadEntry::ActionButton()
{
switch(mStatus)
{
case DownloadFailed:
emit Action(RetryDownload);
break;
case ToBeInstalled:
case InstallFailed:
emit Action(StartInstall);
break;
default:
break;
}
}
void SpkDownloadEntry::DeleteButton()
{
switch(mStatus)
{
case Waiting:
case DownloadFailed:
case Installed:
case InstallFailed:
case ToBeInstalled:
emit Action(RemoveEntry);
break;
case Downloading:
emit Action(AbortDownload);
break;
default:
break;
}
}

View File

@@ -1,56 +0,0 @@
#include <QMargins>
#include <QPainter>
#include <QVariant>
#include <QDebug>
#include "spkiconbutton.h"
SpkIconButton::SpkIconButton(QWidget *parent) :
QPushButton(parent)
{
setFocusPolicy(Qt::NoFocus);
}
void SpkIconButton::SetIcon(QIcon i, QSize s)
{
mPmapPaintedIcon = i.pixmap(s);
setFixedSize((mPmapSize = s.grownBy(QMargins(IconMargin, IconMargin, IconMargin, IconMargin))));
}
void SpkIconButton::SetIcon(QPixmap m)
{
mPmapPaintedIcon = m;
setFixedSize((mPmapSize = m.size().grownBy(QMargins(IconMargin, IconMargin,
IconMargin, IconMargin))));
}
void SpkIconButton::SetIconSize(QSize s)
{
setFixedSize((mPmapSize = s.grownBy(QMargins(IconMargin, IconMargin, IconMargin, IconMargin))));
}
void SpkIconButton::paintEvent(QPaintEvent *e)
{
QPushButton::paintEvent(e);
// Paint the icon mask
QPainter p(this), p1(&mPmapPaintedIcon);
QBrush b(Qt::SolidPattern);
p.drawPixmap(IconMargin, IconMargin, mPmapPaintedIcon);
if(isDown() || isChecked())
{
b.setColor(SpkUi::ColorBtnMaskSelected);
}
else
{
b.setColor(SpkUi::ColorBtnMaskUnselected);
}
p1.setCompositionMode(QPainter::CompositionMode_SourceIn);
p1.fillRect(0, 0, mPmapSize.width(), mPmapSize.height(), b);
p1.end();
p.drawPixmap(IconMargin, IconMargin, mPmapPaintedIcon);
p.end();
}

View File

@@ -1,120 +0,0 @@
#include "spktitlebar.h"
#include "spkimgviewer.h"
#include "spkui_general.h"
#include <QDebug>
#include <QFocusEvent>
#include <QGuiApplication>
#include <QScreen>
SpkImgViewer::SpkImgViewer(QWidget *parent) :
SpkWindow(parent),
mIconLoading(QIcon(":/icons/loading-icon.svg").pixmap({ 72, 72 }))
{
mImgIndict = new QLabel;
mImgIndict->setText("%1/%2");
mBtnPrev = new QPushButton;
mBtnPrev->setText("<");
mBtnNext = new QPushButton;
mBtnNext->setText(">");
auto titleBar = GetTitleBar();
titleBar->SetUseIcon(false);
titleBar->SetTitle(tr("Image Preview"));
titleBar->SetOperationButton(SpkTitleBar::OperationButton::Close);
auto lay = titleBar->GetUserSpace();
lay->setAlignment(Qt::AlignVCenter);
lay->addStretch();
lay->addWidget(mBtnPrev);
lay->addWidget(mImgIndict);
lay->addWidget(mBtnNext);
lay->addStretch();
mImgArea = new QScrollArea;
mImgArea->setWidgetResizable(true);
mImgArea->setContentsMargins(10, 10, 10, 10);
mImgShow = new ImgView;
mImgArea->setWidget(mImgShow);
auto w = new QWidget;
auto l = new QHBoxLayout;
l->setContentsMargins(10, 10, 10, 10);
l->addWidget(mImgArea);
w->setLayout(l);
SetCentralWidget(w);
connect(mBtnPrev, &QPushButton::clicked,
[&](){ if(mCurrentImg > 0) { SwitchToImage(--mCurrentImg); } });
connect(mBtnNext, &QPushButton::clicked,
[&](){ if(mCurrentImg < mTotalImg) { SwitchToImage(++mCurrentImg); } });
}
void SpkImgViewer::ShowWithImage(int idx)
{
SwitchToImage(idx);
show();
}
void SpkImgViewer::Clear()
{
mImgMap.clear();
mImgShow->SetPixmap(nullptr);
mCurrentImg = 1;
}
void SpkImgViewer::SetPixmap(int idx, QPixmap *img)
{
mImgMap[idx] = img;
if(mCurrentImg == idx)
{
mImgShow->SetPixmap(img);
}
ResizeToFitImageSize(img->size());
}
void SpkImgViewer::SwitchToImage(int idx)
{
auto img = mImgMap.value(idx, nullptr);
mCurrentImg = idx;
mImgShow->SetPixmap(img ? img : &mIconLoading);
if(img)
ResizeToFitImageSize(img->size());
if(idx == 1)
{
mBtnPrev->setEnabled(false);
mBtnNext->setEnabled(true);
}
else if(idx == mTotalImg)
{
mBtnPrev->setEnabled(true);
mBtnNext->setEnabled(false);
}
else
{
mBtnPrev->setEnabled(true);
mBtnNext->setEnabled(true);
}
mImgIndict->setText(QString("%1/%2").arg(mCurrentImg).arg(mTotalImg));
}
bool SpkImgViewer::event(QEvent *e)
{
if(e->type() == QEvent::WindowDeactivate)
close();
return SpkWindow::event(e);
}
void SpkImgViewer::ResizeToFitImageSize(QSize s)
{
auto targetSize = s;
targetSize.rheight() += SpkTitleBar::Height;
targetSize = s.grownBy(QMargins(10, 10, 10, 10));
targetSize = targetSize.boundedTo(SpkUi::PrimaryScreenSize * 0.8);
resize(targetSize);
targetSize /= 2;
auto targetPos = SpkUi::PrimaryScreenSize / 2 - targetSize;
move(targetPos.width(), targetPos.height());
}

View File

@@ -1,79 +0,0 @@
#include <QPaintEvent>
#include <QPainter>
#include "spkloading.h"
#include "spkui_general.h"
SpkLoading::SpkLoading(QWidget *parent) : QFrame(parent)
{
setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Minimum);
mAnimTimer = new QTimeLine(400, this);
mAnimTimer->setFrameRange(10, 30);
mAnimTimer->setEasingCurve(QEasingCurve::InCubic);
for(int i = 0; i < 5; i++)
mSizeList.append(20);
connect(mAnimTimer, &QTimeLine::frameChanged, this, &SpkLoading::timer);
connect(mAnimTimer, &QTimeLine::finished, this, &SpkLoading::loop);
}
void SpkLoading::paintEvent(QPaintEvent *e)
{
QPainter p(this);
QPen pen(Qt::NoPen);
QBrush b(SpkUi::CurrentColorSet[SpkUi::Qss::AccentColor], Qt::SolidPattern);
p.setBrush(b);
p.setPen(pen);
p.setRenderHint(QPainter::Antialiasing);
dx = width() / 2 - dh * 2;
dy = height() / 2;
double r;
for(int i = 0; i < 5; i++)
{
r = dh * mSizeList[i] / 80;
p.drawEllipse({ dx, dy }, r, r);
dx += dh;
}
e->accept();
}
void SpkLoading::resizeEvent(QResizeEvent *e)
{
// Calculate size of drawing space
if(mUserHeight != 0 && mUserHeight * 5 <= e->size().width())
{
dw = 5 * mUserHeight;
dh = mUserHeight;
return;
}
dh = e->size().height();
if(width() < dh * 5)
{
dw = e->size().width();
dh = dw / 5;
}
else
dw = dh * 5;
}
void SpkLoading::timer(int s)
{
for(int i = 4; i > 0; i--)
mSizeList[i] = mSizeList[i - 1];
mSizeList[0] = s;
update();
}
void SpkLoading::loop()
{
mAnimTimer->setDirection(mAnimTimer->direction() == QTimeLine::Forward ?
QTimeLine::Backward : QTimeLine::Forward);
mAnimTimer->start();
}
void SpkLoading::reset()
{
for(int i = 0; i < 5; i++)
mSizeList[i] = 20;
update();
}

View File

@@ -1,570 +0,0 @@
#include <QGuiApplication>
#include <QScreen>
#include <QJsonArray>
#include "spkmsgbox.h"
#include "spkmainwindow.h"
#include "spklogging.h"
#include "spkutils.h"
#include "spkuimsg.h"
SpkMainWindow::SpkMainWindow(QWidget *parent) : SpkWindow(parent)
{
ui = new SpkUi::SpkMainWidget(this);
Initialize();
SetCentralWidget(ui);
RefreshCategoryData();
GetTitleBar()->SetTitle("");
GetTitleBar()->SetUseIcon(true);
GetTitleBar()->SetIcon(QIcon(":/icons/spark-store.svg").pixmap({ 40, 40 }));
GetTitleBar()->setObjectName("spk_mw_titlebar");
GetTitleBar()->setAttribute(Qt::WA_StyledBackground);
auto size = QGuiApplication::primaryScreen()->size() * 0.5;
size = size.expandedTo(QSize(900, 600));
resize(size);
auto pos = QGuiApplication::primaryScreen()->size() * 0.5 - size * 0.5;
move(pos.width(), pos.height());
}
void SpkMainWindow::SwitchDayNightTheme()
{
if(SpkUi::CurrentStyle == SpkUi::Dark)
SpkUi::SetGlobalStyle(SpkUi::Light, true);
else
SpkUi::SetGlobalStyle(SpkUi::Dark, true);
ReloadThemedUiIcons();
}
void SpkMainWindow::SwitchToPage(SpkUi::SpkStackedPages page)
{
if(mCurrentPage != page)
{
ui->Pager->setCurrentIndex(int(page));
mCurrentPage = page;
// If the page is a SpkPageBase (with a resource context), activate it for resource acquisition
auto tryActivate = qobject_cast<SpkPageBase *>(ui->Pager->currentWidget());
if(tryActivate)
tryActivate->Activated();
ui->BtnBack->setVisible(page == SpkUi::SpkStackedPages::PgAppDetails);
ui->BtnBack->setEnabled(true);
}
}
void SpkMainWindow::PopulateCategories(QJsonArray aCategoryData)
{
using SpkUi::SpkSidebarSelector;
QTreeWidgetItem *catg;
if(ui->CategoryParentItem->childCount()) // Clear all existing children if there is any
foreach(auto &i, ui->CategoryParentItem->takeChildren())
delete i;
foreach(auto i, aCategoryData)
{
if(i.isObject())
{
auto j = i.toObject();
double typeId;
QString typeName;
if(j.contains("type_id") && j.value("type_id").isDouble())
typeId = j.value("type_id").toDouble();
else goto WRONG_CATEGORY;
if(j.contains("type_name") && j.value("type_name").isString())
typeName = j.value("type_name").toString();
else goto WRONG_CATEGORY;
catg = new QTreeWidgetItem(ui->CategoryParentItem, QStringList(typeName));
catg->setData(0, SpkSidebarSelector::RoleItemIsCategory, true);
catg->setData(0, SpkSidebarSelector::RoleItemCategoryPageId, typeId);
continue;
WRONG_CATEGORY:;
}
ui->CategoryParentItem->setExpanded(true);
}
}
void SpkMainWindow::RefreshCategoryData()
{
// Asynchronously call category API
using namespace SpkUtils;
VerifySingleRequest(mCategoryGetReply);
mCategoryGetReply = STORE->SendApiRequest("type/get_type_list");
DeleteReplyLater(mCategoryGetReply);
connect(mCategoryGetReply, &QNetworkReply::finished, this, &SpkMainWindow::CategoryDataReceived);
}
void SpkMainWindow::CategoryDataReceived()
{
QJsonValue retval;
auto verify = SpkUtils::VerifyReplyJson(mCategoryGetReply, retval);
if(verify || !retval.isArray())
{
sErr(tr("Failed to load categories! Type=%1 Code=%2").arg(retval.type()).arg(verify));
sNotify(tr("Cannot load categories! Type: %1 Code: %2").arg(retval.type()).arg(verify));
ui->PageHome->ui->widReloadCategory->setVisible(true);
return;
}
ui->PageHome->ui->widReloadCategory->setVisible(false);
PopulateCategories(retval.toArray());
}
void SpkMainWindow::EnterCategoryList(int aCategoryId, int aPage)
{
// Asynchronously call category API
using namespace SpkUtils;
VerifySingleRequest(mCategoryAppListGetReply);
QJsonObject reqData;
QJsonDocument reqDoc;
reqData.insert("type_id", QJsonValue(aCategoryId));
reqData.insert("page", QJsonValue(aPage));
reqDoc.setObject(reqData);
mCategoryAppListGetReply = STORE->SendApiRequest("application/get_application_list", reqDoc);
DeleteReplyLater(mCategoryAppListGetReply);
connect(mCategoryAppListGetReply, &QNetworkReply::finished,
this, &SpkMainWindow::CategoryListDataReceived);
setCursor(Qt::BusyCursor);
ui->PageAppList->SetCurrentCategory(aCategoryId); // AppList needs to remember current category
}
void SpkMainWindow::CategoryListDataReceived()
{
QJsonValue retval;
setCursor(Qt::ArrowCursor);
int verify = SpkUtils::VerifyReplyJson(mCategoryAppListGetReply, retval);
if(verify || !retval.isObject())
{
sErr(tr("Failed to load app list of category! Type=%1 Code=%2").arg(retval.type()).arg(verify));
sNotify(tr("Failed to load app list of category! Type: %1 Code: %2").arg(retval.type()).arg(verify));
return;
}
SwitchToPage(SpkUi::PgAppList);
PopulateAppList(retval.toObject(), "");
}
void SpkMainWindow::SearchKeyword(QString aKeyword, int aPage)
{
using namespace SpkUtils;
VerifySingleRequest(mCategoryAppListGetReply);
QJsonObject reqData;
QJsonDocument reqDoc;
reqData.insert("application_name", QJsonValue(aKeyword));
reqData.insert("page", QJsonValue(aPage));
reqDoc.setObject(reqData);
mCategoryAppListGetReply = STORE->SendApiRequest("application/get_application_list", reqDoc);
mCategoryAppListGetReply->setProperty("keyword", aKeyword);
DeleteReplyLater(mCategoryAppListGetReply);
connect(mCategoryAppListGetReply, &QNetworkReply::finished,
this, &SpkMainWindow::SearchDataReceived);
setCursor(Qt::BusyCursor);
}
void SpkMainWindow::SearchDataReceived()
{
QJsonValue retval;
setCursor(Qt::ArrowCursor);
auto verify = SpkUtils::VerifyReplyJson(mCategoryAppListGetReply, retval);
if(verify || !retval.isObject())
{
sErr(tr("Failed to search keyword! Type=%1 Code=%2").arg(retval.type()).arg(verify));
sNotify(tr("Failed to search keyword! Type: %1 Code: %2").arg(retval.type()).arg(verify));
return;
}
SwitchToPage(SpkUi::PgAppList);
PopulateAppList(retval.toObject(), mCategoryAppListGetReply->property("keyword").toString());
}
void SpkMainWindow::PopulateAppList(QJsonObject appData, QString &&keyword)
{
auto w = ui->PageAppList;
w->ClearAll();
static auto err =
[](){
sErr("Received invalid application list data!");
SpkUiMessage::SendStoreNotification(tr("Received an invalid response. Please try again!"));
return;
};
int pgCurrent, pgTotal, totalApps;
if(appData.contains("currentPage") && appData.value("currentPage").isDouble())
pgCurrent = appData.value("currentPage").toInt();
else return err();
if(appData.contains("totalPages") && appData.value("totalPages").isDouble())
pgTotal = appData.value("totalPages").toInt();
else return err();
if(appData.contains("count") && appData.value("count").isDouble())
totalApps = appData.value("count").toInt();
else return err();
w->SetPageStatus(pgTotal, pgCurrent, totalApps, keyword);
if(!appData.contains("data") || !appData.value("data").isArray())
return err();
auto apps = appData.value("data").toArray();
for(auto &&i : apps)
{
if(i.isObject())
{
auto j = i.toObject();
QString pkgName, displayName, description, iconPath;
int appid;
if(j.contains("package") && j.value("package").isString())
pkgName = j.value("package").toString();
else continue;
if(j.contains("application_name_zh") && j.value("application_name_zh").isString())
displayName = j.value("application_name_zh").toString();
else continue;
if(j.contains("description") && j.value("description").isString())
description = j.value("description").toString();
else continue;
if(j.contains("application_id") && j.value("application_id").isDouble())
appid = j.value("application_id").toInt();
else continue;
if(j.contains("icons") && j.value("icons").isString())
iconPath = j.value("icons").toString();
else continue;
w->AddApplicationEntry(displayName, pkgName, description, iconPath, appid);
}
}
}
void SpkMainWindow::EnterAppDetails(int aAppId)
{
using namespace SpkUtils;
VerifySingleRequest(mAppDetailsGetReply);
QJsonObject reqData;
QJsonDocument reqDoc;
reqData.insert("application_id", QJsonValue(aAppId));
reqDoc.setObject(reqData);
mAppDetailsGetReply = STORE->SendApiRequest("application/get_application_detail", reqDoc);
DeleteReplyLater(mAppDetailsGetReply);
connect(mAppDetailsGetReply, &QNetworkReply::finished,
this, &SpkMainWindow::AppDetailsDataReceived);
setCursor(Qt::BusyCursor);
}
void SpkMainWindow::AppDetailsDataReceived()
{
QJsonValue retval;
setCursor(Qt::ArrowCursor);
auto verify = SpkUtils::VerifyReplyJson(mAppDetailsGetReply, retval);
if(verify || !retval.isObject())
{
sErr(tr("Failed to open app details page! Type=%1 Code=%2").arg(retval.type()).arg(verify));
sNotify(tr("Failed to open app details page! Type: %1 Code: %2").arg(retval.type()).arg(verify));
return;
}
SwitchToPage(SpkUi::PgAppList);
PopulateAppDetails(retval.toObject());
}
void SpkMainWindow::PopulateAppDetails(QJsonObject appDetails)
{
QString pkgName, author, contributor, site, iconPath, arch, version, details, shortDesc, name,
pkgPath;
QStringList screenshots, tags;
int packageSize;
static auto err =
[](){
sErr("Received invalid application details!");
SpkUiMessage::SendStoreNotification(tr("Received an invalid response. Please try again!"));
return;
};
if(appDetails.contains("package") && appDetails.value("package").isString())
pkgName = appDetails.value("package").toString();
else return err();
if(appDetails.contains("application_name_zh") && appDetails.value("application_name_zh").isString())
name = appDetails.value("application_name_zh").toString();
else name = pkgName;
if(appDetails.contains("version") && appDetails.value("version").isString())
version = appDetails.value("version").toString();
else return err();
if(appDetails.contains("icons") && appDetails.value("icons").isString())
iconPath= appDetails.value("icons").toString();
if(appDetails.contains("author") && appDetails.value("author").isString())
author = appDetails.value("author").toString();
if(appDetails.contains("contributor") && appDetails.value("contributor").isString())
contributor = appDetails.value("contributor").toString();
if(appDetails.contains("website") && appDetails.value("website").isString())
site = appDetails.value("website").toString();
if(appDetails.contains("description") && appDetails.value("description").isString())
shortDesc = appDetails.value("description").toString();
if(appDetails.contains("more") && appDetails.value("more").isString())
details = appDetails.value("more").toString();
if(appDetails.contains("arch") && appDetails.value("arch").isString())
arch = appDetails.value("arch").toString();
if(appDetails.contains("size") && appDetails.value("size").isDouble())
packageSize = appDetails.value("size").toInt();
if(appDetails.contains("deb_url") && appDetails.value("deb_url").isString())
pkgPath = appDetails.value("deb_url").toString();
QJsonArray imgs;
if(appDetails.contains("img_urls") && appDetails.value("img_urls").isArray())
imgs = appDetails.value("img_urls").toArray();
if(!imgs.isEmpty())
for(auto &&i : imgs)
if(i.isString()) screenshots << i.toString();
QJsonArray tags_j;
if(appDetails.contains("tags") && appDetails.value("tags").isArray())
imgs = appDetails.value("tags").toArray();
if(!tags_j.isEmpty())
for(auto &&i : tags_j)
if(i.isString()) tags << i.toString();
// Details string has a strangely appended LF. IDK but still should remove it.
shortDesc = shortDesc.trimmed();
auto w = ui->PageAppDetails;
w->mPkgName->setText(pkgName);
w->mAppTitle->setText(name);
w->mAppShortDesc->setText(shortDesc);
w->mAppDescription->setText(details);
w->mAuthor->SetValue(author);
w->mContributor->SetValue(contributor);
// w->mSite->SetValue(site); // Doesn't look good, I disabled it temporarily. Better solution?
w->SetWebsiteLink(site);
w->mArch->SetValue(arch);
w->mSize->SetValue(SpkUtils::BytesToSize(packageSize));
w->mVersion->setText(version);
w->SetPackagePath(pkgPath);
SwitchToPage(SpkUi::PgAppDetails);
ui->AppDetailsItem->setHidden(false);
ui->CategoryWidget->setCurrentItem(ui->AppDetailsItem);
w->LoadAppResources(pkgName, iconPath, screenshots, tags);
}
void SpkMainWindow::ReloadThemedUiIcons()
{
for(auto &i : mThemedUiIconReferences)
i.first->SetIcon(SpkUi::GetThemedIcon(i.second), QSize { 20, 20 });
}
// ==================== Main Window Initialization ====================
void SpkMainWindow::Initialize()
{
connect(ui->SidebarMgr, &SpkUi::SpkSidebarSelector::SwitchToPage,
this, &SpkMainWindow::SwitchToPage);
connect(ui->SidebarMgr, &SpkUi::SpkSidebarSelector::SwitchToCategory,
this, &SpkMainWindow::EnterCategoryList);
connect(ui->PageAppList, &SpkUi::SpkPageAppList::SwitchListPage,
this, &SpkMainWindow::EnterCategoryList);
connect(ui->PageAppList, &SpkUi::SpkPageAppList::SwitchSearchPage,
this, &SpkMainWindow::SearchKeyword);
connect(ui->SearchEdit, &QLineEdit::returnPressed,
[=](){ emit SearchKeyword(ui->SearchEdit->text(), 1); });
connect(ui->PageAppList, &SpkUi::SpkPageAppList::ApplicationClicked,
this, &SpkMainWindow::EnterAppDetails);
connect(ui->BtnDayNight, &QPushButton::clicked,
this, &SpkMainWindow::SwitchDayNightTheme);
if(SpkUi::States::IsUsingDtkPlugin)
{
connect(SpkUi::DtkPlugin, &SpkDtkPlugin::DarkLightThemeChanged,
this, &SpkMainWindow::ReloadThemedUiIcons);
}
connect(ui->PageAppDetails, &SpkUi::SpkPageAppDetails::RequestDownload,
ui->PageDownloads, &SpkUi::SpkPageDownloads::AddDownloadTask);
connect(ui->PageHome->ui->btnReloadCategory, &QPushButton::clicked,
this, &SpkMainWindow::RefreshCategoryData);
connect(&SpkUi::SpkUiMetaObject, &SpkUi::UiMetaObject::SetThemeButtonVisible,
[=](bool visible)
{
ui->BtnDayNight->setVisible(visible);
ReloadThemedUiIcons();
});
// Register themed button icons
// mThemedUiIconReferences.append({ ui->BtnSettings, "settings" });
mThemedUiIconReferences.append({ ui->BtnDayNight, "daynight" });
ReloadThemedUiIcons();
}
// ==================== Main Widget Initialization ====================
SpkUi::SpkMainWidget::SpkMainWidget(QWidget *parent) : QFrame(parent)
{
setObjectName("spk_mainwidget");
Pager = new QStackedWidget(this);
Pager->setObjectName("spk_mw_pager");
Pager->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
SidebarMgr = new SpkSidebarSelector(this);
SidebarMgr->setObjectName("spk_mw_sidebar_mgr");
BtnSettings = new SpkIconButton(this);
BtnSettings->setObjectName("styPlainChkBtn");
BtnSettings->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
BtnSettings->setCheckable(true);
BtnSettings->setFixedSize({ 40, 40 });
BtnSettings->SetIcon(QIcon(":/icons/settings.svg"), QSize(20, 20));
BtnSettings->setProperty("spk_pageno", PgSettings);
SidebarMgr->BindPageSwitcherButton(BtnSettings);
BtnDayNight = new SpkIconButton(this);
BtnDayNight->setObjectName("styPlainChkBtn");
BtnDayNight->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
BtnDayNight->setFixedSize({ 40, 40 });
BtnDayNight->SetIcon(QIcon(":/icons/daynight.svg"), QSize(20, 20));
BtnBack = new SpkIconButton(this);
BtnBack->setFixedSize({ 40, 40 });
BtnBack->SetIcon(QIcon(":/icons/back.svg"), QSize(20, 20));
BtnBack->setVisible(false);
using SpkUi::SpkSidebarSelector;
CategoryWidget = new SpkSidebarTree(this);
CategoryWidget->setObjectName("styMwCateg");
CategoryWidget->setAutoFillBackground(true);
CategoryWidget->setColumnCount(1);
CategoryWidget->setHeaderHidden(true);
CategoryWidget->setSelectionMode(QAbstractItemView::SelectionMode::SingleSelection);
CategoryWidget->setFixedWidth(200);
//============ Sidebar entries BEGIN ============
HomepageItem = new QTreeWidgetItem(QStringList(tr("Home")));
HomepageItem->setData(0, SpkSidebarSelector::RoleItemIsCategory, false);
HomepageItem->setData(0, SpkSidebarSelector::RoleItemCategoryPageId, SpkStackedPages::PgHomepage);
AppDetailsItem = new QTreeWidgetItem(QStringList(tr("App Details")));
AppDetailsItem->setData(0, SpkSidebarSelector::RoleItemIsCategory, false);
AppDetailsItem->setData(0, SpkSidebarSelector::RoleItemCategoryPageId, SpkStackedPages::PgAppDetails);
CategoryParentItem = new QTreeWidgetItem(QStringList(tr("Categories")));
CategoryParentItem->setFlags(CategoryParentItem->flags().setFlag(Qt::ItemIsSelectable, false));
DownloadsItem = new QTreeWidgetItem(QStringList(tr("Downloads")));
DownloadsItem->setData(0, SpkSidebarSelector::RoleItemIsCategory, false);
DownloadsItem->setData(0, SpkSidebarSelector::RoleItemCategoryPageId, SpkStackedPages::PgDownloads);
#ifndef NDEBUG
UiTestItem = new QTreeWidgetItem(QStringList(tr("UI TEST")));
UiTestItem->setData(0, SpkSidebarSelector::RoleItemIsCategory, false);
UiTestItem->setData(0, SpkSidebarSelector::RoleItemCategoryPageId, SpkStackedPages::PgQssTest);
#endif
//============ Sidebar entries END ============
CategoryWidget->addTopLevelItem(HomepageItem);
SidebarMgr->AddUnusableItem(CategoryParentItem);
CategoryWidget->addTopLevelItem(AppDetailsItem);
CategoryWidget->addTopLevelItem(CategoryParentItem);
CategoryWidget->addTopLevelItem(DownloadsItem);
CategoryWidget->addTopLevelItem(UiTestItem);
CategoryWidget->setFocusPolicy(Qt::NoFocus);
// Must be done after added into a view.
AppDetailsItem->setHidden(true); // Hide until we actually open up a Details page
CategoryParentItem->setExpanded(true);
// FIXMEIFPOSSIBLE: Fusion adds extra gradient.
// Details: https://forum.qt.io/topic/128190/fusion-style-kept-adding-an-extra-
// layer-of-gradient-to-my-selected-item-of-qtreewidget-even-with-qss
if(SpkUi::OldSystemStyle)
CategoryWidget->setStyle(SpkUi::OldSystemStyle);
SidebarMgr->BindCategoryWidget(CategoryWidget);
HorizontalDivide = new QHBoxLayout;
HorizontalDivide->setObjectName("spk_mw_divide_hlay");
HorizontalDivide->setSpacing(0);
HorizontalDivide->setContentsMargins(0, 0, 0, 0);
HorizontalDivide->setAlignment(Qt::AlignLeft);
if(!SpkUi::States::IsUsingDtkPlugin)
HorizontalDivide->addSpacing(SpkWindow::BorderWidth);
HorizontalDivide->addWidget(CategoryWidget);
HorizontalDivide->addWidget(Pager);
//============ Search Bar ============
SearchEdit = new SpkFocusLineEdit(this);
SearchEdit->setPlaceholderText(tr("Press Enter to search"));
SearchEdit->setFixedWidth(30);
SearchEdit->setFixedHeight(30);
SearchBarAnim = new QTimeLine(300, this);
SearchBarAnim->setDuration(300);
SearchBarAnim->setEasingCurve(QEasingCurve::OutExpo);
SearchBarAnim->setUpdateInterval(20);
ActClearSearchBar = SearchEdit->addAction(QIcon(":/icons/clear-input.svg"),
QLineEdit::TrailingPosition);
ActClearSearchBar->setVisible(false); // Invisible by default
ActSearchIcon = SearchEdit->addAction(QIcon(":/icons/search-mini.svg"), QLineEdit::LeadingPosition);
connect(SearchEdit, &SpkFocusLineEdit::focusGained,
[=](){
ActClearSearchBar->setVisible(true);
SearchBarAnim->setDirection(QTimeLine::Forward);
SearchBarAnim->start();
});
connect(SearchEdit, &SpkFocusLineEdit::focusLost,
[=](){
ActClearSearchBar->setVisible(false);
SearchBarAnim->setDirection(QTimeLine::Backward);
SearchBarAnim->start();
});
connect(SearchBarAnim, &QTimeLine::valueChanged,
[=](qreal v){
SearchEdit->setFixedWidth(static_cast<int>(250 * v) + 30);
});
connect(ActClearSearchBar, &QAction::triggered, [=](){ SearchEdit->clear(); });
connect(BtnBack, &QPushButton::clicked,
[=](){
SidebarMgr->GoBack();
BtnBack->setEnabled(false);
});
auto space = static_cast<SpkWindow*>(parent)->GetTitleBar()->GetUserSpace();
space->addSpacing(50);
space->addWidget(BtnDayNight);
space->addWidget(BtnSettings);
space->addWidget(BtnBack);
space->addWidget(SearchEdit);
space->addStretch();
//============ Pages =============
// Red-Black tree based map will be able to sort things. Just for convenience of ordering pages.
QMap<SpkStackedPages, QWidget*> sorter;
// Initialize pages
PageAppList = new SpkUi::SpkPageAppList(this);
PageAppList->setProperty("spk_pageid", SpkStackedPages::PgAppList);
sorter[PgAppList] = PageAppList;
PageAppDetails = new SpkUi::SpkPageAppDetails(this);
PageAppDetails->setProperty("spk_pageid", SpkStackedPages::PgAppDetails);
sorter[PgAppDetails] = PageAppDetails;
PageDownloads = new SpkUi::SpkPageDownloads(this);
PageDownloads->setProperty("spk_pageid", SpkStackedPages::PgDownloads);
sorter[PgDownloads] = PageDownloads;
PageSettings = new SpkUi::SpkPageSettings(this);
PageSettings->setProperty("spk_pageid", SpkStackedPages::PgSettings);
sorter[PgSettings] = PageSettings;
PageHome = new SpkUi::SpkPageHome(this);
PageSettings->setProperty("spk_pageid", SpkStackedPages::PgHomepage);
sorter[PgHomepage] = PageHome;
#ifndef NDEBUG // If only in debug mode should we initialize QSS test page
PageQssTest = new SpkUi::SpkPageUiTest(this);
PageQssTest->setProperty("spk_pageid", SpkStackedPages::PgQssTest);
sorter[PgQssTest] = PageQssTest;
#endif
for(auto i : sorter)
Pager->addWidget(i);
// Default page selection : homepage
HomepageItem->setSelected(true);
// Manually "activate" the default page item to make the sidebar tree know about default item
emit CategoryWidget->itemPressed(HomepageItem, 0);
setLayout(HorizontalDivide);
}

View File

@@ -1,139 +0,0 @@
#include <QScrollArea>
#include <QDebug>
#include <QGuiApplication>
#include <QScreen>
#include "spkui_general.h"
#include "spkmainwindow.h"
#include "spkmsgbox.h"
#include "spkstore.h"
// Suppress unwanted Clazy check warnings
// clazy:excludeall=connect-3arg-lambda,lambda-in-connect
const QSize SpkMsgBox::IconSize; // I don't know why I need it, compiler wants that
SpkMsgBox::SpkMsgBox(QWidget *parent)
{
Q_UNUSED(parent);
setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::Minimum);
}
int SpkMsgBox::StaticExec(QString msg, QString title, QMessageBox::Icon icon,
QMessageBox::StandardButtons buttons, QString extra, bool expanded)
{
SpkMsgBox *b = new SpkMsgBox(SpkStore::Instance->GetRootWindow());
QWidget *wMsgWidget = new QWidget;
QHBoxLayout *wMsg = new QHBoxLayout(wMsgWidget);
QPushButton *wExpandBtn;
QScrollArea *wExtraArea;
QLabel *wMsgText = new QLabel,
*wExtraInfo,
*wIcon;
int InitialHeight;
bool hasextra = extra.length() != 0;
if(icon)
{
wIcon = new QLabel;
QIcon icon_;
switch(icon)
{
case QMessageBox::Critical:
icon_ = QIcon::fromTheme("dialog-error");
break;
case QMessageBox::Warning:
icon_ = QIcon::fromTheme("dialog-warning");
break;
case QMessageBox::Information:
icon_ = QIcon::fromTheme("dialog-information");
break;
case QMessageBox::Question:
icon_ = QIcon::fromTheme("dialog-question");
break;
case QMessageBox::NoIcon:
break;
}
if(icon)
wIcon->setPixmap(icon_.pixmap(IconSize));
wMsg->addWidget(wIcon);
}
wMsgText->setText(msg);
wMsgText->setAlignment(Qt::AlignLeft);
wMsg->addWidget(wMsgText);
wMsg->setSpacing(10);
wMsgWidget->setLayout(wMsg);
b->AddWidget(wMsgWidget);
b->GetTitleBar()->SetTitle(title);
b->GetTitleBar()->SetOperationButton(SpkTitleBar::OperationButton::Close);
b->SetResizable(false);
b->SetCentralMargin(Margin, Margin, Margin, Margin);
b->setMaximumSize(SpkUi::PrimaryScreenSize * 0.6);
if(hasextra)
{
wExpandBtn = new QPushButton;
wExtraInfo = new QLabel;
wExtraArea = new QScrollArea;
wExtraInfo->setText(extra);
wExtraArea->setWidget(wExtraInfo);
wExtraArea->setVisible(false);
wExtraArea->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
wExpandBtn->setText(tr("Details"));
wExpandBtn->setMaximumWidth(100);
wExpandBtn->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred);
wExpandBtn->setCheckable(true);
wExpandBtn->setObjectName("styChkBtn");
connect(wExpandBtn, &QPushButton::clicked,
[&](){ // FIXME: hint doesn't change when visibility changes, this is a quirky hack
wExtraArea->setVisible(wExpandBtn->isChecked());
if(wExpandBtn->isChecked())
b->setFixedHeight(b->sizeHint().height());
else
b->setFixedHeight(InitialHeight);
});
b->mBtnLay->addWidget(wExpandBtn);
b->mBtnLay->addStretch();
b->AddWidget(wExtraArea);
}
b->AddSpacing(3);
AddButtons(b, buttons);
if(hasextra)
{
b->mBtnLay->addStretch(); // Keep conventional buttons centered
if(expanded)
emit wExpandBtn->clicked();
}
InitialHeight = b->minimumSizeHint().height();
auto pos = (SpkUi::PrimaryScreenSize - b->sizeHint()) / 2;
b->move(pos.width(), pos.height());
b->setWindowModality(Qt::ApplicationModal);
b->setFixedSize(b->sizeHint());
auto r = b->Exec();
if(r != -1)
r = b->mButtonList[r]; // Retrieve the correct button
delete b;
return r;
}
void SpkMsgBox::AddButtons(SpkMsgBox *me, QMessageBox::StandardButtons b)
{
// If anyone can do it better, please let me know, I wrote this on the airplane
using btn = QMessageBox::StandardButton;
if(!b) return;
if(b.testFlag(btn::Ok)) { me->AddButton(tr("OK")); me->mButtonList << btn::Ok; };
if(b.testFlag(btn::Cancel)) { me->AddButton(tr("Cancel")); me->mButtonList << btn::Cancel; };
if(b.testFlag(btn::Yes)) { me->AddButton(tr("Yes")); me->mButtonList << btn::Yes; };
if(b.testFlag(btn::No)) { me->AddButton(tr("No")); me->mButtonList << btn::No; };
if(b.testFlag(btn::Apply)) { me->AddButton(tr("Apply")); me->mButtonList << btn::Apply; };
if(b.testFlag(btn::Reset)) { me->AddButton(tr("Reset")); me->mButtonList << btn::Reset; };
if(b.testFlag(btn::Abort)) { me->AddButton(tr("Abort")); me->mButtonList << btn::Abort; };
if(b.testFlag(btn::Retry)) { me->AddButton(tr("Retry")); me->mButtonList << btn::Retry; };
if(b.testFlag(btn::Ignore)) { me->AddButton(tr("Ignore")); me->mButtonList << btn::Ignore; };
if(b.testFlag(btn::Reset)) { me->AddButton(tr("Reset")); me->mButtonList << btn::Reset; };
if(b.testFlag(btn::Close)) { me->AddButton(tr("Close")); me->mButtonList << btn::Close; };
if(b.testFlag(btn::Open)) { me->AddButton(tr("Open")); me->mButtonList << btn::Open; };
}

View File

@@ -1,35 +0,0 @@
#include <QPaintEvent>
#include <QPainter>
#include <QBrush>
#include "spknotifydot.h"
#include "spkstore.h"
/*
* The font size and the actual geometry of this widget is hard coded
* If you want to use this widget code please consider improving it
*/
SpkNotifyDot::SpkNotifyDot(QWidget *parent) :
QLabel(parent)
{
}
void SpkNotifyDot::paintEvent(QPaintEvent *e)
{
QPainter p(this);
int h = height();
p.setRenderHint(QPainter::Antialiasing);
p.setBrush(QBrush(QColor(255, 70, 50)));
p.setPen(Qt::transparent);
p.drawEllipse(0, 0, h, h);
p.setBrush(QBrush(QColor(Qt::white)));
p.setPen(Qt::white);
p.setFont(QFont("sansserif", 10, 1000));
p.drawText(QRect(0, 0, h, h), Qt::AlignHCenter | Qt::AlignVCenter, text());
p.end();
}

View File

@@ -1,82 +0,0 @@
#include "spkpopup.h"
#include <QDebug>
namespace SpkUi
{
SpkPopup::SpkPopup(QWidget *parent, int aMillis) : QWidget(parent)
{
setAttribute(Qt::WA_TransparentForMouseEvents);
setAttribute(Qt::WA_TranslucentBackground);
setWindowFlags(Qt::FramelessWindowHint);
mText = new QLabel();
mText->setStyleSheet("border-radius: 11px;"
"background-color: rgba(0,0,0,150);"
"color: white;"
"padding: 5px;");
mText->setText(tr("(No Text)"));
mBox = new QHBoxLayout(this);
mBox->addWidget(mText);
mBox->setContentsMargins(0, 0, 0, 0);
// The reason why we contain it in a widget is that, if we want a QLabel have rounded corners,
// then it must be able to be displayed with a translucent background. However, setting
// Qt::WA_TranslucentBackground will cause the entire background of QLabel transparent.
// Therefore we need a container (SpkPopup) with a transparent background as the canvas layer
// of the actual displayed text.
mAnim = new QSequentialAnimationGroup(this);
// Disabled as translucency doesn't work well on every platform :(
// mAnimFadeIn = new QPropertyAnimation(this, "windowOpacity");
// mAnimFadeOut = new QPropertyAnimation(this, "windowOpacity");
// mAnimFadeIn->setStartValue(0.0);
// mAnimFadeIn->setEndValue(1.0);
// mAnimFadeOut->setStartValue(1.0);
// mAnimFadeOut->setEndValue(0.0);
// Using moving animation instead
mAnimFadeIn = new QPropertyAnimation(this, "pos");
mAnimFadeOut = new QPropertyAnimation(this, "pos");
mAnimFadeIn->setDuration(250);
mAnimFadeOut->setDuration(250);
mAnimFadeIn->setEasingCurve(QEasingCurve::InQuad);
mAnimFadeOut->setEasingCurve(QEasingCurve::InQuad);
mAnim->addAnimation(mAnimFadeIn);
mAnim->addPause(aMillis);
mAnim->addAnimation(mAnimFadeOut);
setVisible(false);
connect(mAnim, &QAnimationGroup::stateChanged,
[=](QAbstractAnimation::State newState, QAbstractAnimation::State oldState)
{
// qDebug() << "OldState" << oldState << "NewState" << newState;
if(newState == QAbstractAnimation::Stopped)
setVisible(false);
});
}
void SpkPopup::Show(QString aText)
{
if(mAnim->state() == QSequentialAnimationGroup::Running)
mAnim->stop();
QSize parentSize = parentWidget()->size();
mText->setText(aText);
adjustSize();
move(QPoint((parentSize.width() - width()) / 2, parentSize.height() - height() - 30)/* +
parentWidget()->pos()*/);
setMaximumWidth(parentSize.width() - 200);
setWindowOpacity(1);
show();
mAnimFadeIn->setStartValue(QPoint((parentSize.width() - width()) / 2,
parentSize.height() + height()));
mAnimFadeIn->setEndValue(QPoint((parentSize.width() - width()) / 2,
parentSize.height() - height() - 80));
mAnimFadeOut->setStartValue(QPoint((parentSize.width() - width()) / 2,
parentSize.height() - height() - 80));
mAnimFadeOut->setEndValue(QPoint((parentSize.width() - width()) / 2,
parentSize.height() + height()));
qDebug() << "Popup size " << size() << "position" << pos() << "parent size" << parentWidget()->size();
mAnim->start();
}
}

View File

@@ -1,93 +0,0 @@
#include "spkqsshelper.h"
const std::list<SpkUi::Qss::ColorSetIndex> SpkUi::Qss::AccentColorExceptions
{
AccentColor,
AccentColorHighlighted,
TextOnAccentColor,
};
const std::map<SpkUi::Qss::ColorSetIndex, const char *> SpkUi::Qss::ColorSet2Token
{
{ GlobalBgnd, "GBG_" },
{ ControlsBgnd, "CBG_" },
{ ControlsBgndHighlighted, "CBGH" },
{ SelectionBgnd, "ACC_" },
{ SelectionBgndHighlighted, "ACCH" },
{ LightCtrlsGradLight, "LCTL1" },
{ LightCtrlsGradDark, "LCTL2" },
{ LightCtrlsGradDarker, "LCTL3" },
{ LightCtrlsDisabledBackground, "LCTLD" },
{ DarkCtrlsGradLight, "DCTL1" },
{ DarkCtrlsGradDark, "DCTL2" },
{ DarkCtrlsGradDarker, "DCTL3" },
{ DarkCtrlsDisabledBackground, "DCTLD" },
{ TextOnSelection, "TXACC" },
{ TextOnGlobalBgnd, "TXGBG" },
{ TextOnControlsBgnd, "TXCBG" },
{ TextLighter, "TXL1" },
{ TextEvenLighter, "TXL2" },
{ TextDisabled, "TXD" },
{ GlossyEdge, "GLS" },
{ ShadesEdge, "SHD" },
{ ScrollBarNorm, "SCBN" },
{ ScrollBarHover, "SCBH" },
{ DivideLine, "DVL" },
};
const std::map<SpkUi::Qss::ColorSetIndex, QColor> SpkUi::Qss::DarkColorSet
{
{ GlobalBgnd, 0x282828 },
{ ControlsBgnd, 0x323232 },
{ ControlsBgndHighlighted, 0xff0000 },
{ SelectionBgnd, 0x0070ff },
{ SelectionBgndHighlighted, QColor(0x0070ff).lighter(120) },
{ LightCtrlsGradLight, 0x6b6b6b },
{ LightCtrlsGradDark, 0x656565 },
{ LightCtrlsGradDarker, 0x606060 },
{ LightCtrlsDisabledBackground, 0x808080 },
{ DarkCtrlsGradLight, 0x404040 },
{ DarkCtrlsGradDark, 0x383838 },
{ DarkCtrlsGradDarker, 0x323232 },
{ DarkCtrlsDisabledBackground, 0x525252 },
{ TextOnSelection, ColorTextOnBackground(0x0070ff) },
{ TextOnGlobalBgnd, ColorTextOnBackground(0x282828) },
{ TextOnControlsBgnd, ColorTextOnBackground(0x282828) },
{ TextLighter, 0xd5d5d5 },
{ TextEvenLighter, 0x505050 },
{ TextDisabled, 0xbebebe },
{ GlossyEdge, 0x656565 },
{ ShadesEdge, 0x7b7b7b },
{ ScrollBarNorm, 0x404040 },
{ ScrollBarHover, 0x656565 },
{ DivideLine, 0x424242 },
};
const std::map<SpkUi::Qss::ColorSetIndex, QColor> SpkUi::Qss::LightColorSet
{
{ GlobalBgnd, 0xf8f8f8 },
{ ControlsBgnd, 0xf8f8f8 },
{ ControlsBgndHighlighted, 0xff0000 },
{ SelectionBgnd, 0x0070ff },
{ SelectionBgndHighlighted, QColor(0x0070ff).lighter(120) },
{ LightCtrlsGradLight, 0xfbfbfb },
{ LightCtrlsGradDark, 0xf2f2f2 },
{ LightCtrlsGradDarker, 0xebebeb },
{ LightCtrlsDisabledBackground, 0xe0e0e0 },
{ DarkCtrlsGradLight, 0xe4e4e4 },
{ DarkCtrlsGradDark, 0xcecece },
{ DarkCtrlsGradDarker, 0xb8b8b8 },
{ DarkCtrlsDisabledBackground, 0xababab },
{ TextOnSelection, ColorTextOnBackground(0x0070ff) },
{ TextOnGlobalBgnd, ColorTextOnBackground(0xf8f8f8) },
{ TextOnControlsBgnd, ColorTextOnBackground(0xf8f8f8) },
{ TextLighter, 0x2a2a2a },
{ TextEvenLighter, 0xa0a0a0 },
{ TextDisabled, 0x8a8a8a },
{ GlossyEdge, 0x9d9d9d },
{ ShadesEdge, 0xc5c5c5 },
{ ScrollBarNorm, 0xa0a0a0 },
{ ScrollBarHover, 0x858585 },
{ DivideLine, 0xd5d5d5 },
};

View File

@@ -1,31 +0,0 @@
#include <QMouseEvent>
#include "spksidebartree.h"
SpkUi::SpkSidebarTree::SpkSidebarTree(QWidget *parent) :
QTreeWidget(parent)
{
}
void SpkUi::SpkSidebarTree::mouseMoveEvent(QMouseEvent *e)
{
// This is solely for forcibly disabling the view to change selection when dragging on the view
// and probably the only reason why this class began its existence
if((e->buttons() & Qt::LeftButton))
setState(NoState);
else
QTreeWidget::mouseMoveEvent(e);
}
void SpkUi::SpkSidebarTree::mousePressEvent(QMouseEvent *e)
{
// Prevent anything being deselected
if(e->modifiers().testFlag(Qt::ControlModifier) && e->buttons().testFlag(Qt::LeftButton))
{
auto i = itemAt(e->pos());
if(i && i->isSelected())
return;
}
QTreeWidget::mousePressEvent(e);
}

View File

@@ -1,92 +0,0 @@
#include "spkstretchlayout.h"
SpkStretchLayout::SpkStretchLayout(QWidget *parent) : QLayout(parent)
{
}
SpkStretchLayout::~SpkStretchLayout()
{
QLayoutItem *item;
while((item = takeAt(0)))
delete item;
}
void SpkStretchLayout::addItem(QLayoutItem *item)
{
mItems.append(item);
}
QSize SpkStretchLayout::sizeHint() const
{
if(mItems.isEmpty())
return { 300, 300 };
auto w = geometry().width() - spacing();
auto it = mItems.first();
int countPerLine = w / (it->minimumSize().width() + spacing());
int lines = ceil((double)mItems.size() / countPerLine);
auto h = static_cast<int>(it->minimumSize().height() * lines + spacing() * lines);
return { w, h };
}
QSize SpkStretchLayout::minimumSize() const
{
// It works this way, but I honestly have no idea WHY IT WORKS
auto r = sizeHint();
r.setWidth(300);
return r;
}
int SpkStretchLayout::count() const
{
return mItems.size();
}
QLayoutItem *SpkStretchLayout::itemAt(int i) const
{
return mItems.value(i);
}
QLayoutItem *SpkStretchLayout::takeAt(int i)
{
return i >= 0 && i < mItems.size() ? mItems.takeAt(i) : nullptr;
}
void SpkStretchLayout::setGeometry(const QRect &rect)
{
QLayout::setGeometry(rect);
if(mItems.isEmpty())
return;
int spc = spacing(), w = rect.width() - spc;
QSize size;
auto itm = mItems.first();
// All items are considered the same, so we only calculate with the first item.
// Figure out how many at most can we squeeze into one line
int countPerLine = w / (itm->minimumSize().width() + spacing());
if(countPerLine < 1)
countPerLine = 1;
if(countPerLine >= mItems.size()) // All items fit in one line
size = itm->minimumSize();
// Won't fit in one line.
else // Stretch items.
size = QSize {(w / countPerLine - spc), itm->maximumSize().height() };
auto origin = geometry().topLeft();
QLayoutItem *o;
for(int i = 0; i < mItems.size(); i++)
{
o = mItems.at(i);
QRect geo;
geo.setSize(size);
geo.moveTo((i % countPerLine) * (size.width() + spc) + spc + origin.x(),
(i / countPerLine) * (size.height() + spacing()) + spc + origin.y());
o->setGeometry(geo);
}
// qDebug() << rect;
}

View File

@@ -1,149 +0,0 @@
#include <QEvent>
#include <QMouseEvent>
#include "spkwindow.h"
#include "spkui_general.h"
#include "spktitlebar.h"
SpkTitleBar::SpkTitleBar(QWidget *parent) : QFrame(parent)
{
mLinkedWindow = nullptr;
setFixedHeight(Height);
setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
mIcon = new QLabel(this);
mTitle = new QLabel(this);
mIcon->setFixedSize(40, 40);
mMainLayout = new QHBoxLayout(this);
mUserSpace = new QHBoxLayout();
mBtnGroup = new QHBoxLayout();
mBtnMin = new SpkTitleBarDefaultButton(this);
mBtnMaxRestore = new SpkTitleBarDefaultButton(this);
mBtnClose= new SpkTitleBarDefaultButton(this);
mMainLayout->setSpacing(8);
mBtnGroup->setSpacing(0);
mMainLayout->addSpacing(12);
mMainLayout->addWidget(mIcon);
mMainLayout->addWidget(mTitle);
mMainLayout->addLayout(mUserSpace);
mMainLayout->addLayout(mBtnGroup);
mBtnGroup->addWidget(mBtnMin);
mBtnGroup->addWidget(mBtnMaxRestore);
mBtnGroup->addWidget(mBtnClose);
mBtnMin->SetRole(OperationButton::Minimize);
mBtnMaxRestore->SetRole(OperationButton::MaximizeRestore);
mBtnClose->SetRole(OperationButton::Close);
mMainLayout->setContentsMargins(0, 0, 0, 1);
setLayout(mMainLayout);
connect(mBtnClose, &QPushButton::clicked, this, &SpkTitleBar::CloseWindow);
connect(mBtnMin, &QPushButton::clicked, this, &SpkTitleBar::MinimizeWindow);
connect(mBtnMaxRestore, &QPushButton::clicked, this, &SpkTitleBar::MaximizeRestoreWindow);
}
SpkTitleBar::~SpkTitleBar()
{
//qDebug() << "Freed title bar!";
}
void SpkTitleBar::SetOperationButton(OperationButton type)
{
mBtnClose->setVisible(type & OperationButton::Close);
mBtnMaxRestore->setVisible(type & OperationButton::MaximizeRestore);
mBtnMin->setVisible(type & OperationButton::Minimize);
}
bool SpkTitleBar::event(QEvent *evt)
{
switch(evt->type())
{
case QEvent::MouseButtonDblClick:
{
if(static_cast<QMouseEvent*>(evt)->button())
emit mBtnMaxRestore->clicked();
break;
}
default:;
}
return QWidget::event(evt);
}
void SpkTitleBar::CloseWindow()
{
if(mLinkedWindow)
mLinkedWindow->close();
}
void SpkTitleBar::MinimizeWindow()
{
if(mLinkedWindow)
mLinkedWindow->setWindowState(Qt::WindowMinimized);
}
void SpkTitleBar::MaximizeRestoreWindow()
{
if(mLinkedWindow)
{
if(mLinkedWindow->windowState().testFlag(Qt::WindowMaximized))
mLinkedWindow->setWindowState(mLinkedWindow->windowState() & ~Qt::WindowMaximized);
else
mLinkedWindow->setWindowState(Qt::WindowMaximized);
}
}
SpkTitleBarDefaultButton::SpkTitleBarDefaultButton(QWidget* parent) : QPushButton(parent)
{
setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Expanding);
setMaximumWidth(ButtonWidth);
setMinimumWidth(ButtonWidth);
setFocusPolicy(Qt::NoFocus);
}
void SpkTitleBarDefaultButton::paintEvent(QPaintEvent *e)
{
QPushButton::paintEvent(e);
QPainter painter;
painter.begin(this);
PaintSymbol(painter);
painter.end();
}
void SpkTitleBarDefaultButton::PaintSymbol(QPainter &p)
{
QPen pen(SpkUi::ColorLine);
p.setPen(pen);
auto mh = height() / 2, mw = width() / 2, h = height(), w = width();
constexpr int fr = 10;
switch(Role)
{
case Minimize:
p.drawLine(mw - w / fr, mh, mw + w / fr, mh);
break;
case MaximizeRestore:
p.drawRect(mw - w / fr, mh - h / fr,
w / fr * 2, h / fr * 2);
break;
case Restore:
p.drawRect(mw - w / fr - 2, mh - w / fr + 2, w / fr * 2, h / fr * 2);
p.drawLine(mw - w / fr, mh - h / fr - 2, mw + w / fr, mh - h / fr - 2);
p.drawLine(mw + w / fr, mh - h / fr - 2, mw + w / fr, mh + h / fr - 2);
break;
case Close:
p.drawLine(mw - h / fr * 1.3, mh - h / fr * 1.3,
mw + h / fr * 1.3, mh + h / fr * 1.3);
p.drawLine(mw - h / fr * 1.3, mh + h / fr * 1.3,
mw + h / fr * 1.3, mh - h / fr * 1.3);
break;
}
}
void SpkTitleBarDefaultButton::SetRole(OperationButton role)
{
Role = role;
}

View File

@@ -1,332 +0,0 @@
//
// Created by rigoligo on 2021/5/8.
//
#include <QApplication>
#include <QFile>
#include <QTextStream>
#include <QLibrary>
#include <QDir>
#include <QMessageBox>
#include <QDateTime>
#include <QDebug>
#include <QScreen>
#include <QPluginLoader>
#include <QStyleFactory>
#include <csignal>
#include <execinfo.h>
#include "spkui_general.h"
#include "spkmsgbox.h"
#include "spkpopup.h"
#include "spklogging.h"
#include "spkstore.h"
#include "spkutils.h"
namespace SpkUi
{
UiMetaObject SpkUiMetaObject;
SpkUiStyle CurrentStyle;
QString StylesheetBase, CurrentStylesheet;
QColor ColorLine, ColorBack, ColorBtnMaskSelected, ColorBtnMaskUnselected;
QSize PrimaryScreenSize;
SpkDtkPlugin *DtkPlugin = nullptr;
QStyle *OldSystemStyle = nullptr;
std::map<Qss::ColorSetIndex, QColor> CurrentColorSet;
SpkPopup *Popup;
namespace States
{
bool IsDDE = false, IsUsingDtkPlugin = false;
bool DoRespondAutoTheme = false;
int LightDarkMode = 3; // Default to Manual
bool ThemeConfigCallback()
{
switch(LightDarkMode)
{
case 0:
if(!DtkPlugin) return false;
SpkUiMetaObject.SetDarkLightTheme(DtkPlugin->GetIsDarkTheme());
break;
case 1:
SetGlobalStyle(Light, true);
SpkUiMetaObject.SetThemeButtonVisible(false);
break;
case 2:
SetGlobalStyle(Dark, true);
SpkUiMetaObject.SetThemeButtonVisible(false);
break;
case 3:
SpkUiMetaObject.SetThemeButtonVisible(true);
break;
}
return true;
}
}
namespace Priv
{
bool CrashHandlerActivated;
}
// ======================= Static Linkage Private Functions ========================
static void SetBtnMaskColor()
{
ColorBtnMaskUnselected = ColorTextOnBackground(CurrentColorSet[Qss::ControlsBgnd]);
ColorBtnMaskSelected = ColorTextOnBackground(CurrentColorSet[Qss::AccentColor]);
}
// ======================== Public Functions =========================
void Initialize()
{
// Obtain global stylesheets
QFile ObtainStylesheet;
ObtainStylesheet.setFileName(CFG->ReadField("internal/qss_path",
":/stylesheet/stylesheet/default.css")
.toString());
ObtainStylesheet.open(QIODevice::ReadOnly);
StylesheetBase = ObtainStylesheet.readAll();
ObtainStylesheet.close();
CurrentStyle = SpkUiStyle::Invalid;
#ifdef NDEBUG
SetGlobalStyle(Light, false);
#else
SetGlobalStyle(qEnvironmentVariableIntValue("SPK_FORCE_DARK") ? Dark : Light, false);
#endif
// Initalize crash handler
signal(SIGSEGV, SpkUi::CrashSignalHandler);
signal(SIGABRT, SpkUi::CrashSignalHandler);
signal(SIGFPE, SpkUi::CrashSignalHandler);
// Prepare theme following for DDE
if((States::IsDDE = CheckIsDeepinDesktop()))
PrepareForDeepinDesktop();
// Misc data initialization
PrimaryScreenSize = QGuiApplication::primaryScreen()->size();
CFG->BindField("ui/theme", &States::LightDarkMode, 3, States::ThemeConfigCallback);
}
void GuessAppropriateTheme()
{
// FIXME: Too difficult, not implementing it
}
bool CheckIsDeepinDesktop()
{
QString Desktop(getenv("XDG_CURRENT_DESKTOP"));
// This method of checking is from DTK source code.
if(Desktop.contains("deepin", Qt::CaseInsensitive) ||
Desktop.contains("tablet", Qt::CaseInsensitive))
return true;
else
return false;
}
void PrepareForDeepinDesktop()
{
#ifndef NDEBUG
qApp->addLibraryPath(qApp->applicationDirPath() + "/plugin/dtkplugin");
#else
// You must `make install' before these work in release mode
qApp->addLibraryPath("/usr/local/lib");
qApp->addLibraryPath("/usr/lib");
#endif
if(!qEnvironmentVariableIntValue("SPARK_NO_DTK_PLUGIN"))
{
QPluginLoader p("libspkdtkplugin");
if(p.load())
{
auto i = qobject_cast<SpkDtkPlugin*>(p.instance());
if(i)
{
DtkPlugin = i;
States::IsUsingDtkPlugin = true;
i->Initialize();
SpkUiMetaObject.SetAccentColor(i->GetAccentColor()); // Match OS accent color
SpkUiMetaObject.SetDarkLightTheme(i->GetIsDarkTheme()); // Match OS dark theme type
QObject::connect(i, &SpkDtkPlugin::AccentColorChanged,
&SpkUiMetaObject, &UiMetaObject::SetAccentColor);
QObject::connect(i, &SpkDtkPlugin::DarkLightThemeChanged,
&SpkUiMetaObject, &UiMetaObject::SetDarkLightTheme);
}
}
}
// NOTE: Chameleon style kept adding unwanted blue focus indication border
// to widgets that shouldn't have borders.
// We need to eliminate this irritating problem.
if(qEnvironmentVariableIntValue("SPARK_NO_QSTYLE_CHANGE"))
return;
OldSystemStyle = QStyleFactory::create("chameleon"); // TreeWidget doesn't work well with Fusion
auto styles = QStyleFactory::keys();
styles.removeAll("chameleon");
if(styles.contains("Fusion"))
{
auto style = QStyleFactory::create("Fusion");
qApp->setStyle(style);
}
else if(styles.size()) // What? This shouldn't happen.
qApp->setStyle(QStyleFactory::create(styles[0]));
else // Duh...
sWarn(QObject::tr("Cannot find styles other than 'chameleon'! You may see widgets "
"with unwanted blue borders."));
}
void SetGlobalStyle(const SpkUiStyle aStyle, const bool aPreserveAccentColor)
{
if(aStyle == CurrentStyle) // Don't waste precious CPU time parsing new style sheet!
return;
CurrentStyle = aStyle;
Qss::ColorSet tempset;
switch(aStyle)
{
case Invalid:
case Light:
tempset = Qss::LightColorSet;
ColorLine = Qt::black;
break;
case Dark:
tempset = Qss::DarkColorSet;
ColorLine = Qt::white;
break;
}
if(aPreserveAccentColor)
{
for(auto i : Qss::AccentColorExceptions)
tempset[i] = CurrentColorSet[i];
}
CurrentColorSet = tempset;
CurrentStylesheet = StylesheetFromColors(CurrentColorSet);
SetBtnMaskColor();
qApp->setStyleSheet(CurrentStylesheet);
}
QString WriteStackTrace(const QString &aStackTrace)
{
QString path = QDir::homePath() + "/.local/share/spark-store/crash/";
QFile StackTraceFile;
if(!QDir().exists(path))
if(!QDir().mkpath(path))
return QObject::tr("Stack trace directory %1 cannot be created. "
"Stack trace wasn't saved.").arg(path);
path += QString::number(QDateTime::currentDateTimeUtc().toSecsSinceEpoch());
while(QFile::exists(path))
path += "_";
StackTraceFile.setFileName(path);
StackTraceFile.open(QIODevice::WriteOnly);
if(StackTraceFile.isOpen() && StackTraceFile.isWritable())
{
QTextStream StackTraceWriter;
StackTraceWriter.setDevice(&StackTraceFile);
StackTraceWriter << QDateTime::currentDateTime().toLocalTime().toString() << "\n\n";
StackTraceWriter << aStackTrace;
StackTraceFile.close();
return QObject::tr("Stack trace written to \"%1\".").arg(path);
}
return QObject::tr("Stack trace file %1 cannot be opened. "
"Stack trace wasn't saved.").arg(path);
}
void CrashSignalHandler(int sig)
{
QString msg(QObject::tr("Program has received signal %1 during normal execution.\n\n")),
trace;
switch(sig)
{
case SIGSEGV:
msg = msg.arg(QObject::tr("\"SIGSEGV\" (Segmentation fault)"));
goto CRASH;
case SIGFPE:
msg = msg.arg(QObject::tr("\"SIGFPE\" (Arithmetic exception)"));
goto CRASH;
case SIGABRT:
msg = msg.arg(QObject::tr("\"SIGABRT\" (Abort)"));
CRASH:
{
if(Priv::CrashHandlerActivated) // If error occured in the handler...
{
signal(SIGABRT, SIG_DFL); // Return control flow to OS and give up
raise(SIGABRT);
exit(2);
}
Priv::CrashHandlerActivated = true;
void* TraceStack[StackTraceArraySize];
int StackTraceSize = backtrace(TraceStack, StackTraceArraySize);
auto TraceTextArray = backtrace_symbols(TraceStack, StackTraceArraySize);
trace = QString(QObject::tr("Stack trace:\n"));
for(int i = 0; i < StackTraceSize; i++)
trace += QString::number(i) + "> " + QString(TraceTextArray[i]) + '\n';
msg += QObject::tr("Spark Store cannot continue.\n\n");
msg += WriteStackTrace(trace);
SpkMsgBox::StaticExec(msg, QObject::tr("Spark Store Crashed"), QMessageBox::Critical,
QMessageBox::Ok, trace);
exit(2);
}
default:
sErrPop(QObject::tr("Unknown signal %1 received in crash handler. "
"Program internals may be corrupted. Please decide if you want "
"to continue execution.").arg(sig));
}
}
QIcon GetThemedIcon(QString name)
{
if(CurrentStyle == SpkUiStyle::Dark)
name += "-dark";
return QIcon(":/icons/" + name + ".svg");
}
QString StylesheetFromColors(Qss::ColorSet aColors)
{
QString ret = StylesheetBase;
foreach(auto &i, aColors)
ret = ret.replace(Qss::ColorSet2Token.at(i.first), i.second.name());
return ret;
}
QColor ColorTextOnBackground(QColor c)
{
// From https://github.com/feiyangqingyun/qtkaifajingyan
double gray = (0.299 * c.red() + 0.587 * c.green() + 0.114 * c.blue()) / 255;
return gray > 0.5 ? Qt::black : Qt::white;
}
// =================== UiMetaObject =======================
// UiMetaObject is the signal-slot receiver for DDE plugin, receiving the DDE system level
// notifications of UI theme changes
// Communications with UI widgets are also done here
void UiMetaObject::SetAccentColor(QColor aColor)
{
if(!SpkUi::States::DoRespondAutoTheme)
return;
CurrentColorSet[Qss::AccentColor] = aColor.lighter(90);
CurrentColorSet[Qss::AccentColorHighlighted] = aColor.lighter(105);
CurrentColorSet[Qss::TextOnAccentColor] = ColorTextOnBackground(aColor);
SetBtnMaskColor();
qApp->setStyleSheet(StylesheetFromColors(CurrentColorSet));
}
void UiMetaObject::SetDarkLightTheme(bool isDark)
{
if(!SpkUi::States::DoRespondAutoTheme)
return;
if(isDark)
SetGlobalStyle(Dark, true);
else
SetGlobalStyle(Light, true);
}
}

View File

@@ -1,326 +0,0 @@
#include <QVBoxLayout>
#include <QApplication>
#include <QStyleHints>
#include <QPainterPath>
#include <QFile>
#include <QPushButton>
#include <QMouseEvent>
#include "spklogging.h"
#include "spkwindow.h"
#include "spkui_general.h"
#include "spktitlebar.h"
#include <QDebug>
SpkWindow::SpkWindow(QWidget *parent) : QWidget(parent)
{
mUseCustomEvents = SpkUi::DtkPlugin == nullptr; // Put to the front, to prevent warnings
if(SpkUi::DtkPlugin && !qEnvironmentVariableIntValue("SPARK_NO_DXCB"))
SpkUi::DtkPlugin->addWindow(this, parent); // Register window to DXcb so we got Deepin
else
setWindowFlags(Qt::FramelessWindowHint); // Remove default title bar
setAttribute(Qt::WA_Hover);
mCornerRadius = 5;
mUserCentralWidget = nullptr;
mResizable = true;
mMoving = mResizing = false;
mCloseHook = nullptr;
mMaximized = windowState().testFlag(Qt::WindowMaximized);
setMouseTracking(true);
PopulateUi();
}
SpkWindow::~SpkWindow()
{
}
bool SpkWindow::event(QEvent *evt)
{
// These custom events weren't useful for Deepin platform
if(!mUseCustomEvents)
return QWidget::event(evt);
switch(evt->type())
{
case QEvent::WindowStateChange:
{
mMaximized = windowState().testFlag(Qt::WindowMaximized);
if(mMaximized)
mTitleBarComponent->mBtnMaxRestore->SetRole(SpkTitleBarDefaultButton::Restore);
else
mTitleBarComponent->mBtnMaxRestore->SetRole(SpkTitleBarDefaultButton::MaximizeRestore);
break;
}
case QEvent::MouseButtonPress:
{
// if(!mResizable) break;
auto e = static_cast<QMouseEvent*>(evt);
if(e->button() != Qt::LeftButton) break;
auto edge = DetectEdgeOnThis(e->pos());
if(edge)
{
mResizing = true;
mEdgesBeingResized = edge;
return true;
}
else
{
if(!QWidget::event(evt) || 1) // Movable property is not implemented, let move anywhere
{
mMoveOffset = e->globalPos() - pos();
mMoving = true;
mResizing = false;
}
return true;
}
break;
}
case QEvent::MouseButtonRelease:
{
// if(!mResizable) break;
auto e = static_cast<QMouseEvent*>(evt);
if(e->button() != Qt::LeftButton) break;
mResizing = false;
mMoving = false;
unsetCursor();
return true;
break;
}
case QEvent::HoverMove:
{
if((mResizing || !mResizable) && !mMoving) break;
if(mMaximized)
{
unsetCursor();
break;
}
if(mResizable && !mMoving)
{
auto e = static_cast<QHoverEvent*>(evt);
auto edge = DetectEdgeOnThis(e->pos());
SetMouseCursor(edge);
}
break;
}
case QEvent::MouseMove:
{
if(mMaximized) break;
auto e = static_cast<QMouseEvent*>(evt);
if(mResizing && mResizable)
{
ResizeWindowByCursor(e->globalPos());
return true; // Intercept resize movements
}
else if(mMoving)
{
move(e->globalPos() - mMoveOffset);
}
break;
}
default:
;
}
return QWidget::event(evt);
}
Qt::Edges SpkWindow::DetectEdgeOnThis(QPoint p)
{
Qt::Edges edge;
if(p.x() < BorderWidth) edge |= Qt::LeftEdge;
if(p.x() > width() - BorderWidth) edge |= Qt::RightEdge;
if(p.y() < BorderWidth) edge |= Qt::TopEdge;
if(p.y() > height() - BorderWidth) edge |= Qt::BottomEdge;
return edge;
}
void SpkWindow::SetMouseCursor(Qt::Edges e)
{
switch(e)
{
case Qt::TopEdge:
case Qt::BottomEdge:
setCursor(Qt::SizeVerCursor);
break;
case Qt::LeftEdge:
case Qt::RightEdge:
setCursor(Qt::SizeHorCursor);
break;
case Qt::TopEdge | Qt::LeftEdge:
case Qt::BottomEdge | Qt::RightEdge:
setCursor(Qt::SizeFDiagCursor);
break;
case Qt::TopEdge | Qt::RightEdge:
case Qt::BottomEdge | Qt::LeftEdge:
setCursor(Qt::SizeBDiagCursor);
break;
default:
unsetCursor();
}
}
void SpkWindow::ResizeWindowByCursor(QPoint p)
{
auto r_ = geometry(), r = r_;
switch(mEdgesBeingResized)
{
case Qt::TopEdge | Qt::LeftEdge:
r.setLeft(p.x());
if(r.width() < minimumWidth()) // If smaller than minimum the window moves, so we stop it
r.setLeft(r_.left());
case Qt::TopEdge:
r.setTop(p.y());
if(r.height() < minimumHeight()) // Same
r.setTop(r_.top());
break;
case Qt::BottomEdge | Qt::LeftEdge:
r.setLeft(p.x());
if(r.width() < minimumWidth())
r.setLeft(r_.left());
case Qt::BottomEdge:
r.setBottom(p.y());
if(r.height() < minimumHeight())
r.setBottom(r_.bottom());
break;
case Qt::TopEdge | Qt::RightEdge:
r.setTop(p.y());
r.setRight(p.x());
if(r.height() < minimumHeight())
r.setTop(r_.top());
if(r.width() < minimumWidth())
r.setRight(r_.right());
break;
case Qt::BottomEdge | Qt::RightEdge:
r.setBottom(p.y());
if(r.height() < minimumHeight())
r.setBottom(r_.bottom());
case Qt::RightEdge:
r.setRight(p.x());
if(r.width() < minimumWidth())
r.setRight(r_.right());
break;
case Qt::LeftEdge:
r.setLeft(p.x());
if(r.width() < minimumWidth())
r.setLeft(r_.left());
break;
default:
return;
}
setGeometry(r);
}
void SpkWindow::closeEvent(QCloseEvent *e)
{
if(mCloseHook)
{
if(mCloseHook())
e->accept();
else
e->ignore();
emit Closed();
return;
}
e->accept();
emit Closed();
}
void SpkWindow::paintEvent(QPaintEvent *e)
{
QWidget::paintEvent(e);
if(!mUseCustomEvents)
return;
QPainter painter(this);
painter.setBrush(QBrush(Qt::NoBrush));
painter.setPen(QPen(SpkUi::ColorLine));
QRect rect = this->rect();
rect.adjust(0, 0, -1, -1);
painter.drawRect(rect);
}
void SpkWindow::SetCornerRadius(int radius)
{
mCornerRadius = radius;
}
void SpkWindow::PopulateUi()
{
mMainVLayout = new QVBoxLayout;
mTitleBarComponent = new SpkTitleBar(this);
setLayout(mMainVLayout);
mMainVLayout->addWidget(mTitleBarComponent);
mMainVLayout->setAlignment(Qt::AlignTop);
if(mUseCustomEvents)
mMainVLayout->setContentsMargins(1, 1, 1, 1);
else
mMainVLayout->setContentsMargins(0, 0, 0, 0);
mMainVLayout->setSpacing(0);
mTitleBarComponent->SetTitle(qAppName());
mTitleBarComponent->SetUseIcon(false);
mTitleBarComponent->SetLinkedWindow(this);
setWindowFlag(Qt::NoDropShadowWindowHint, false);
}
void SpkWindow::SetCentralWidget(QWidget *widget)
{
if(mUserCentralWidget)
mMainVLayout->removeWidget(mUserCentralWidget);
mUserCentralWidget = widget;
mMainVLayout->addWidget(widget);
}
void SpkWindow::SetUseTitleBar(bool x)
{
mTitleBarComponent->setVisible(x);
}
void SpkWindow::SetCentralMargin(int a, int b, int c, int d)
{
if(mUserCentralWidget)
mUserCentralWidget->setContentsMargins(a, b, c, d);
}
void SpkWindow::SetCloseHook(bool (*f)())
{
mCloseHook = f;
}
void SpkWindow::ClearCloseHook()
{
mCloseHook = nullptr;
}
void SpkWindow::RecalculateSize()
{
mMainVLayout->activate();
}
bool SpkWindow::GetUseTitleBar()
{
return mTitleBarComponent->isVisible();
}
SpkTitleBar *SpkWindow::GetTitleBar()
{
return mTitleBarComponent;
}
SpkTitleBar *SpkWindow::SetTitleBar(SpkTitleBar *bar, bool replace)
{
if(!bar)
return nullptr;
auto ret = mTitleBarComponent;
mMainVLayout->removeWidget(mTitleBarComponent);
if(replace)
mMainVLayout->insertWidget(0, bar);
mTitleBarComponent = bar;
bar->SetLinkedWindow(this);
return ret;
}

View File

@@ -1,9 +0,0 @@
//
// Created by rigoligo on 2021/5/8.
//
#pragma once
// Stub
#endif //_DEEPINPLATFORM_H_

View File

@@ -1,22 +0,0 @@
#pragma once
#include <QWidget>
class SpkDtkPlugin : public QObject
{
Q_OBJECT
public:
virtual ~SpkDtkPlugin() = default;
virtual void Initialize() = 0;
virtual void addWindow(QWidget* w, QObject* parent) = 0;
virtual QColor GetAccentColor() = 0;
virtual bool GetIsDarkTheme() = 0;
signals:
void AccentColorChanged(QColor);
void DarkLightThemeChanged(bool isDark);
};
QT_BEGIN_NAMESPACE
Q_DECLARE_INTERFACE(SpkDtkPlugin, "org.spark-store.client.dtkplugin")
QT_END_NAMESPACE

View File

@@ -1,8 +0,0 @@
#pragma once
namespace GitVer
{
const char *DescribeTags();
const char *CommitDate();
}

View File

@@ -1,86 +0,0 @@
// SPDX-License-Identifier: GPL-3.0-only
#pragma once
#include <QLabel>
#include <QScrollArea>
#include <QVBoxLayout>
#include <QFormLayout>
#include "page/spkpagebase.h"
#include "spkstretchlayout.h"
#include "spkimgviewer.h"
namespace SpkUi
{
class SpkDetailEntry;
class SpkClickLabel : public QLabel
{
Q_OBJECT
protected:
virtual void mousePressEvent(QMouseEvent *e) override { emit Pressed(); }
signals:
void Pressed();
};
class SpkPageAppDetails : public SpkPageBase
{
Q_OBJECT
public:
SpkPageAppDetails(QWidget *parent = nullptr);
~SpkPageAppDetails();
void LoadAppResources(QString pkgName, QString icon, QStringList screenshots, QStringList tags);
void SetWebsiteLink(QString url);
void SetPackagePath(QString url);
private:
QString mPkgPath;
QPixmap mBrokenImg, mIconLoading;
public slots:
void ResourceAcquisitionFinished(int id, ResourceResult result);
void Activated();
public:
static constexpr QSize IconSize { 144, 144 };
// Main Area
QScrollArea *mMainArea, *mScreenshotArea;
QWidget *mDetailWidget, *mIconTitleWidget, *mWid4MainArea, *mWid4ShotArea;
QLabel *mAppTitle, *mAppIcon, *mAppDescription, *mAppShortDesc, *mPkgName, *mVersion,
*mWebsite;
SpkDetailEntry *mAuthor, *mContributor, *mSite, *mArch, *mSize;
SpkStretchLayout *mDetailLay;
QVBoxLayout *mDetailsLay, *mTitleLay, *mMainLay;
QHBoxLayout *mIconTitleLay, *mScreenshotLay;
QList<SpkClickLabel*> mScreenshotPreviews;
QMap<int, QPixmap> mAppImages;
SpkImgViewer *mImgViewer;
// Bottom bar
QWidget *mBottomBar;
QPushButton *mBtnInstall, *mBtnDownload, *mBtnUninstall, *mBtnRequestUpdate, *mBtnReport;
QHBoxLayout *mBottomBarLay;
signals:
void RequestDownload(QString name, QString pkgName, QString path);
private slots:
void ImageClicked();
};
class SpkDetailEntry : public QWidget
{
Q_OBJECT
public:
SpkDetailEntry(QWidget *parent = nullptr);
void SetTitle(const QString &s) { mTitle.setText(s); }
void SetValue(const QString &s) { mField.setText(s); }
private:
QLabel mTitle, mField;
QHBoxLayout mLay;
};
}

View File

@@ -1,63 +0,0 @@
#pragma once
#include <QtWidgets>
#include "spkresource.h"
#include "spkappitem.h"
#include "page/spkpagebase.h"
#include "spkstretchlayout.h"
namespace SpkUi
{
class SpkPageAppList : public SpkPageBase
{
Q_OBJECT
public:
SpkPageAppList(QWidget *parent = nullptr);
void AddApplicationEntry(QString name, QString pkgName, QString description, QString iconUrl,
int appId);
void ClearAll();
void SetPageStatus(int total, int current, int itemCount, QString &keyword);
void SetCurrentCategory(int categoryId) { mCategoryId = categoryId; }
private:
void DisablePageSwitchers();
public:
private:
QVBoxLayout *mMainLay;
QHBoxLayout *mPageSwitchLay;
QPushButton *mBtnPgUp, *mBtnPgDown, *mBtnGotoPage;
QLineEdit *mPageInput;
QScrollArea *mAppsArea;
QLabel *mPageIndicator;
QWidget *mAppsWidget, *mPageSwitchWidget;
SpkStretchLayout *mItemLay;
QList<SpkAppItem *> mAppItemList;
// Cached icons
QPixmap *mLoadingIcon,
*mBrokenIcon;
QIntValidator *mPageValidator;
int mCategoryId, mCurrentPage;
QString mKeyword;
signals:
void ApplicationClicked(int appId);
void SwitchListPage(int categoryId, int page);
void SwitchSearchPage(QString keyword, int page);
public slots:
void ResourceAcquisitionFinished(int id, ResourceResult result);
void Activated();
private slots:
void PageUp();
void PageDown();
void GotoPage();
};
}

View File

@@ -1,27 +0,0 @@
#pragma once
#include <QtWidgets>
#include <spkresource.h>
class SpkPageBase : public QWidget
{
Q_OBJECT
public:
SpkPageBase(QWidget *parent = nullptr);
public slots:
/**
* @brief This signal is emitted by resource manager when a resource acquisition requested
* has finished.
* @param id The request ID
* @param result The data retrieved
*/
virtual void ResourceAcquisitionFinished(int id, ResourceResult result);
/**
* @brief This is an optional signal for Resource Context objects, mainly used for notifying the
* context that it is now activated (therefore it needs to acquire the resource manager).
*/
virtual void Activated();
};

View File

@@ -1,45 +0,0 @@
#ifndef SPKPAGEDOWNLOADS_H
#define SPKPAGEDOWNLOADS_H
#include "spkdownload.h"
#include "spkdownloadentry.h"
#include "page/spkpagebase.h"
#include "pkgs/spkpkgmgrbase.h"
namespace SpkUi
{
class SpkPageDownloads : public SpkPageBase
{
Q_OBJECT
public:
SpkPageDownloads(QWidget *parent = nullptr);
~SpkPageDownloads();
public slots:
void AddDownloadTask(QString name, QString pkgName, QString path);
private:
// Logic
SpkDownloadMgr *mDownloadMgr;
QMap<uint, SpkDownloadEntry*> mEntries;
uint mNextDownloadId;
QQueue<QPair<int, QString>> mWaitingDownloads;
enum { Idle, Waiting, Downloading } mCurrentStatus;
// UI
QVBoxLayout *mLayEntries, *mMainLay;
QWidget *mScrollWidget;
QScrollArea *mScrollArea;
private slots:
void DownloadProgress(qint64 downloadedBytes, qint64 totalBytes, int id);
void DownloadStopped(SpkDownloadMgr::TaskResult status, int id);
void EntryAction(SpkDownloadEntry::EntryAction);
void InstallationEnded(int id, SpkPkgMgrBase::PkgInstallResult, int exitCode);
private:
void NewDownloadTask(int id, QString downloadPath);
};
}
#endif // SPKPAGEDOWNLOADS_H

View File

@@ -1,25 +0,0 @@
#pragma once
#include <QVBoxLayout>
#include "page/spkpagebase.h"
#include "ui_homepage.h"
namespace SpkUi
{
class SpkPageHome : public SpkPageBase
{
Q_OBJECT
public:
SpkPageHome(QWidget *parent = nullptr);
~SpkPageHome() { }
Ui::SpkHomepage *ui;
private slots:
void LinkActivated(QString);
private:
void SetupUi();
};
}

View File

@@ -1,56 +0,0 @@
#pragma once
#include <QScrollArea>
#include <QVBoxLayout>
#include <QFutureWatcher>
#include <QMutex>
#include "page/spkpagebase.h"
#include "ui_settings.h"
namespace SpkUi
{
class SpkPageSettings : public SpkPageBase
{
Q_OBJECT
public:
SpkPageSettings(QWidget *parent = nullptr);
~SpkPageSettings();
void SetupUi();
void ReadConfiguration();
void SaveConfiguration();
void CountCleaning();
virtual void Activated() override;
private slots:
void on_btnCleanDownloadedContent_clicked();
void on_btnCleanResourceCache_clicked();
void on_btnViewDownloadedContent_clicked();
void on_btnViewResourceCache_clicked();
void CountFinishResource();
void CountFinishDownload();
void CleanedResource();
void CleanedDownload();
private:
QScrollArea *mMainArea;
QVBoxLayout *mMainLay;
QWidget *mSettingsWidget;
Ui::SpkUiSettings *ui;
QString mRepoListUrl;
QFutureWatcher<void> mFwResourceCount,
mFwDownloadCount,
mFwResourceClean,
mFwDownloadClean;
QMutex mMutResource, mMutDownload;
int64_t mBytesResource, mBytesDownloads;
};
}

View File

@@ -1,63 +0,0 @@
#pragma once
#include <QWidget>
#include <QSplitter>
#include <QPushButton>
#include <QRadioButton>
#include <QCheckBox>
#include <QGroupBox>
#include <QTextEdit>
#include <QLineEdit>
#include <QVBoxLayout>
#include <QHBoxLayout>
#include <QSlider>
#include <QProgressBar>
#include "spkappitem.h"
#include "spkstretchlayout.h"
#include "page/spkpageappdetails.h"
#include "spkiconbutton.h"
#include "spkloading.h"
namespace SpkUi
{
class SpkPageUiTest : public QSplitter
{
Q_OBJECT
public:
SpkPageUiTest(QWidget *parent = nullptr);
QWidget *WidL, *WidR;
QVBoxLayout *VLayWidgets,
*VLayTestWidgets,
*VLayInput;
QHBoxLayout *HLay4Slider,
*HLayInputBtns;
QTextEdit *TextStylesheet;
QPushButton *BtnApply;
QPushButton *BtnFetch;
QPushButton *Btn;
QCheckBox *Chk;
QRadioButton *Rad;
QGroupBox *Group;
QSlider *SlideH;
QSlider *SlideV;
SpkIconButton *IconBtn;
QProgressBar *Prog;
SpkLoading *Loading;
SpkAppItem *AppItem;
SpkStretchLayout *DetailsLay;
SpkDetailEntry *Detail1, *Detail2, *Detail3;
QWidget *DetailsWidget;
QLineEdit *PopupText;
QPushButton *ShowPopup,
*ShowAbout,
*ShowPkgmgr;
public slots:
void SetStylesheet();
void FetchStylesheet();
void ShowPopupSlot();
};
}

View File

@@ -1,36 +0,0 @@
#pragma once
#include "spkpkgmgrbase.h"
#include <QProcess>
class SpkPkgMgrApt final : public SpkPkgMgrBase
{
Q_OBJECT
public:
SpkPkgMgrApt(QObject *parent = nullptr);
static bool DetectRequirements();
virtual PkgInstallResult ExecuteInstallation(QString pkgPath,
int entryId) override;
// APT backend specific
bool ChangeServerRepository(QString content);
private:
void CheckInstallerAvailability();
private slots:
void InstallerExited(int, QProcess::ExitStatus);
private:
QAction *mActAptitudeTerm,
*mActAptTerm,
*mActGdebi,
*mActDeepinPkgInst;
QProcess mInstaller;
};

View File

@@ -1,91 +0,0 @@
#pragma once
#include <QObject>
#include <QMenu>
#include <QAction>
#include <QCursor>
#include <QUrl>
#include <QDesktopServices>
#include "spkutils.h"
class SpkPkgMgrBase : public QObject
{
Q_OBJECT
public:
SpkPkgMgrBase(QObject *parent = nullptr) : QObject(parent)
{
Q_ASSERT(mInstance == nullptr);
mInstance = this;
mActOpen = new QAction(tr("Open package"), this);
mActOpenDir = new QAction(tr("Open containing directory"), this);
mMenu = new QMenu(tr("Package Actions"));
mMenu->addAction(mActOpen);
mMenu->addAction(mActOpenDir);
mMenu->setAttribute(Qt::WA_TranslucentBackground);
mMenu->setWindowFlags(Qt::Popup | Qt::FramelessWindowHint);
}
enum PkgInstallResult
{
Failed,
Succeeded,
Ignored ///< No installation action is taken, no messages be displayed
};
/**
* @brief Detects if this system qualified to use this kind of packaging
*/
static bool DetectRequirements() { return true; }
/**
* @brief Popup a menu at cursor to select installation methods
* and do installation accordingly
* @param pkgPath Path to the package file
* @param entryId ID of the download entry
*/
virtual PkgInstallResult ExecuteInstallation(QString pkgPath, int entryId)
{
Q_UNUSED(entryId);
auto item = mMenu->exec(QCursor::pos());
if(item == mActOpenDir)
QDesktopServices::openUrl(QUrl(SpkUtils::CutPath(pkgPath)));
else if(item == mActOpen)
QDesktopServices::openUrl(QUrl(pkgPath));
return Ignored;
}
/**
* @brief Called when Spark Store installs a software when it's running
* in CLI mode
* @param pkgPath Path to the package file
*/
virtual PkgInstallResult CliInstall(QString pkgPath)
{
qInfo() << tr("Spark Store cannot install your package because no supported "
"packaging system has been found. You shall decide what you "
"want to do with the downloaded package.\n\n"
"File path:")
<< pkgPath;
return Ignored;
}
public:
static SpkPkgMgrBase *Instance() { return mInstance; }
protected:
QAction *mActOpenDir, *mActOpen, *mActDesc;
QMenu *mMenu;
int mCurrentItemId; ///< ID of currently installing download item
private:
static SpkPkgMgrBase *mInstance;
signals:
void ReportInstallResult(int entryId,
SpkPkgMgrBase::PkgInstallResult result,
int exitCode);
};

View File

@@ -1,20 +0,0 @@
#pragma once
#include "spkpkgmgrbase.h"
class SpkPkgMgrPacman final : public SpkPkgMgrBase
{
Q_OBJECT
public:
SpkPkgMgrPacman(QObject *parent = nullptr);
static bool DetectRequirements();
virtual PkgInstallResult ExecuteInstallation(QString pkgPath,
int entryId) override;
};

View File

@@ -1,87 +0,0 @@
#pragma once
/****************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the QtCore module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:BSD$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** BSD License Usage
** Alternatively, you may use this file under the terms of the BSD license
** as follows:
**
** "Redistribution and use in source and binary forms, with or without
** modification, are permitted provided that the following conditions are
** met:
** * Redistributions of source code must retain the above copyright
** notice, this list of conditions and the following disclaimer.
** * Redistributions in binary form must reproduce the above copyright
** notice, this list of conditions and the following disclaimer in
** the documentation and/or other materials provided with the
** distribution.
** * Neither the name of The Qt Company Ltd nor the names of its
** contributors may be used to endorse or promote products derived
** from this software without specific prior written permission.
**
**
** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
**
** $QT_END_LICENSE$
**
****************************************************************************/
/*
* Slight modifications has been done to the code to make it fit into the project.
*/
#include <QFrame>
#include <QString>
//! [0]
class ElidedLabel : public QFrame
{
Q_OBJECT
Q_PROPERTY(QString text READ text WRITE setText)
Q_PROPERTY(bool isElided READ isElided)
public:
explicit ElidedLabel(const QString &text, QWidget *parent = nullptr);
explicit ElidedLabel(QWidget *parent = nullptr);
void setText(const QString &text);
const QString & text() const { return content; }
bool isElided() const { return elided; }
protected:
void paintEvent(QPaintEvent *event) override;
signals:
void elisionChanged(bool elided);
private:
bool elided;
QString content;
};
//! [0]

View File

@@ -1,23 +0,0 @@
#pragma once
#include <QLabel>
#include <QPushButton>
#include <QHBoxLayout>
#include "spkdialog.h"
class SpkAbout : public SpkDialog
{
Q_OBJECT
public:
SpkAbout(QWidget* parent = nullptr);
~SpkAbout();
static void Show();
private:
QHBoxLayout *mIconLay;
QLabel *mSpkIcon;
QLabel *mSpkVersion;
QLabel *mDescriptionText;
};

View File

@@ -1,41 +0,0 @@
#pragma once
#include <QLabel>
#include <QVBoxLayout>
#include <QHBoxLayout>
#include "qt/elidedlabel.h"
class SpkAppItem : public QWidget
{
Q_OBJECT
public:
SpkAppItem(int appId, QWidget *parent = nullptr);
void SetIcon(QPixmap p) { mIcon->setPixmap(p); }
void SetTitle(QString s) { mTitle->setText(s); }
void SetDescription(QString s) { mDescription->setText(s); }
protected:
void paintEvent(QPaintEvent *e);
void mousePressEvent(QMouseEvent *e);
void mouseReleaseEvent(QMouseEvent *e);
public:
static constexpr int IconSize = 72;
static constexpr QSize IconSize_ = { IconSize, IconSize };
private:
QLabel *mIcon;
QLabel *mTitle;
ElidedLabel *mDescription;
int mAppId;
bool mPressCond;
QVBoxLayout *mLayText;
QHBoxLayout *mMainLay;
signals:
void clicked(int);
};

View File

@@ -1,51 +0,0 @@
#ifndef SPKCONFIG_H
#define SPKCONFIG_H
#include <QSettings>
#include <QHash>
#include <QPair>
#include <functional>
class SpkConfig : public QObject
{
Q_OBJECT
public:
SpkConfig(QObject *parent, QString configPath);
~SpkConfig();
/**
* @brief BindField If a variable is bound to the specified key, then future chanegs via SetField
* will modify the provided variable. A callback can also be specified to make
* sure the chanegs are acceptable.
* @param key
* @param value A pointer to the variable to be bound
* @param defaultValue
* @param callback When SetField is called to modify this specific key associated with a callback,
* the callback is called. If the callback returned false then the original value
* is restored to the value target, and changes won't be saved in mSettings, and
* SetField will return false too. It is used to ensure if the target can accept
* the changes.
* @return false when the key is already bound.
*/
bool BindField(QString key, QString* value, QString defaultValue, std::function<bool(void)> callback = nullptr);
bool BindField(QString key, int* value, int defaultValue, std::function<bool(void)> callback = nullptr);
bool SetField(QString key, QString value);
bool SetField(QString key, int value);
// Wrapper of QSettings::value, used for "read once on startup" configurations
QVariant ReadField(QString key, QVariant defaultValue);
// Wrapper of QSettings::setValue, used for "set and restart to take effect" configurations
void SetSettings(QString key, QVariant value);
// Wrapper of QSettings::sync
void Sync();
private:
QSettings mSettings;
QHash<QString, QPair<QString*, std::function<bool(void)>>> mStringBindMap;
QHash<QString, QPair<int*,std::function<bool(void)>>> mIntBindMap;
};
#endif // SPKCONFIG_H

View File

@@ -1,40 +0,0 @@
#pragma once
#include <QList>
#include <QButtonGroup>
#include "spkui_general.h"
#include "spktitlebar.h"
#include "spkwindow.h"
class SpkDialog : public SpkWindow
{
Q_OBJECT
friend class SpkMsgBox;
public:
SpkDialog(QWidget *parent = nullptr);
~SpkDialog();
void AddButton(QString text, SpkUi::SpkButtonStyle style = SpkUi::SpkButtonStyle::Normal);
void AddWidget(QWidget*);
void AddLayout(QLayout*);
void AddSpacing(int);
void AddStretch(int a = 0);
void SetMargin(int);
void SetMargin(int, int, int, int);
int Exec();
private slots:
void ButtonPressed(int);
void ForceClose();
signals:
void ExitEventLoop(int);
void CloseWindow();
protected:
QWidget *mDialogWidget;
private:
QVBoxLayout *mMainVLay, *mWidgetsVLay;
QHBoxLayout *mBtnLay;
QButtonGroup *mBtnGroup;
QList<QObject*> mWidgetsList, mParentsList;
};

View File

@@ -1,125 +0,0 @@
#pragma once
#include "spkstore.h"
#include <QTimer>
/**
* @note SpkDownloadMgr does NOT do download scheduling and other things; it's only a multithreaded
* downloader; it manages the threads that are downloading stuff from the Internet.
*
* Because of this, SpkDownloadMgr does not support complex download queues, cannot handle
* pauses, and can only work on a sequential list of tasks.
*/
class SpkDownloadMgr : public QObject
{
Q_OBJECT
public:
SpkDownloadMgr(QObject *parent = nullptr);
~SpkDownloadMgr();
static constexpr int MaximumThreadRetryCount = 3;
enum TaskResult
{
Success = 0,
FailCannotCreateFile, ///< Failed because destination file cannot be created
FailNoVaibleServer, ///< Failed because no server provides file size or download stalled on
///< all of them
FailCancel, ///< User has cancelled the task
Fail
};
/**
* @brief DownloadWorker is not a real worker but more of a worker-like structure. It holds
* information about one download thread, such as offset, total bytes and received bytes.
* Workers' scheduling is still done by SpkDownloadMgr synchronously, avoiding
* unnecessary race conditions and data safety problems.
* DownloadWorker is also used in mFailureRetryQueue to indicate the blocks that needed
* to be retried on other servers.
*
* Each worker has a watch dog value, incremented each time the download speed is
* updated, and zeroed each time the worker has data ready. If the value exceeds a
* preset maximum, then this worker is considered timed out and killed.
*/
struct DownloadWorker
{
QNetworkReply *Reply; ///< Reply from the network
int Watchdog; ///< Watch dog value watching for a timed out worker
qint64 BeginOffset; ///< Where should a worker start downloading
qint64 BytesNeeded; ///< How many bytes a worker should fetch in total
qint64 BytesRecvd; ///< How many bytes a worker has received till now
};
constexpr static int WatchDogMaximum = 7;
struct RemoteFileInfo
{
qint64 Size = -1;
bool SupportPartialDownload = false; ///< Whether this file can be downloaded multithreaded
QByteArray Md5;
};
void SetNewServers(QList<QString> servers);
/**
* @note This function uses BLOCKING IO!
*/
static RemoteFileInfo GetRemoteFileInfo(QUrl url);
QString GetDestFilePath(QString downloadPath);
private:
QList<QString> mServers; ///< Multithreaded download
QList<DownloadWorker> mScheduledWorkers;
// If one scheduled task fails a few times in a row, we must give it up on that server and put
// its responsible block onto this queue so we can try downloading the block from other servers
QQueue<DownloadWorker> mFailureRetryQueue;
QFile mDestFile;
QString mDestFolder, mCurrentRemotePath;
RemoteFileInfo mCurrentRemoteFileInfo;
QTimer mProgressEmitterTimer;
qint64 mDownloadedBytes;
int mCurrentDownloadId; ///< Indicates download status. -1 means no download going on.
int mActiveWorkerCount;
QString mBulkServerPaths; ///< Config string, modification are taken care of by callback.
public slots:
void SetDestinationFolder(QString path);
/**
* @brief StartNewDownload try to start new download task.
* @param path File path. Domain name excluded. No leading slashes.
* @param downloadId Emitted with progress, finish and error so the UI know whose status it is.
* @return true for success and false for failure.
*/
bool StartNewDownload(QString path, int downloadId);
bool PauseCurrentDownload();
bool CancelCurrentDownload();
private slots:
void WorkerFinish();
void WorkerDownloadProgress(); ///< Be connected to ***QNetworkReply::readyRead***
void WorkerError(QNetworkReply::NetworkError);
void ProgressTimer();
private:
void ProcessWorkerError(DownloadWorker &, int id);
void LinkReplyWithMe(QNetworkReply*);
void TryScheduleFailureRetries();
void TryScheduleFailureRetries(int i); ///< Try schedule on a specific task slot.
bool ServerAddressesChangedCallback(); ///< Called by SpkConfig upon address changing
signals:
void DownloadProgressed(qint64 bytes, qint64 total, int id);
void DownloadStopped(TaskResult status, int id);
};

View File

@@ -1,78 +0,0 @@
#pragma once
#include <QWidget>
#include <QPushButton>
#include <QLabel>
#include "qt/elidedlabel.h"
#include "spkloading.h"
#include <QProgressBar>
#include <QHBoxLayout>
#include <QVBoxLayout>
#include <QTime>
class SpkDownloadEntry : public QWidget
{
Q_OBJECT
public:
explicit SpkDownloadEntry(QWidget* parent = nullptr);
~SpkDownloadEntry();
static constexpr QSize IconSize { 64, 64 };
enum DownloadEntryStatus
{
Invalid = -1,
Waiting,
Starting,
Downloading,
DownloadFailed,
ToBeInstalled,
Installing,
Installed,
InstallFailed
};
void SetTotalBytes(qint64 total);
void SetBasicInfo(QString name, QPixmap icon, QString filePath);
void SetStatus(DownloadEntryStatus status, QString msg = "");
void Progress(qint64 bytes);
QString GetTaskName() { return mAppName->text(); }
QString GetFilePath() { return mFilePath; }
enum EntryAction
{
AbortDownload,
RetryDownload,
StartInstall,
RemoveEntry
};
private slots:
void ActionButton();
void DeleteButton();
private:
QLabel *mIcon, *mMessage;
ElidedLabel *mAppName;
QProgressBar *mProgress;
QPushButton *mBtnDelete,
*mBtnActions; // Actions include Retry Pause Install etc, one status at a time
SpkLoading *mLoading;
QHBoxLayout *mLayMsgs, *mLayMain;
QVBoxLayout *mLayInfo;
// Download status data
qint64 mTotalBytes, mDownloadedBytes;
QTime mLastReportTime;
QString mReadableTotalSize;
QString mFilePath;
DownloadEntryStatus mStatus;
signals:
void Action(EntryAction);
};

View File

@@ -1,4 +0,0 @@
#ifndef SPKFILLWIDGET_H
#define SPKFILLWIDGET_H
#endif // SPKFILLWIDGET_H

View File

@@ -1,19 +0,0 @@
#pragma once
#include <QtWidgets/QLineEdit>
class SpkFocusLineEdit final : public QLineEdit
{
Q_OBJECT
public:
explicit SpkFocusLineEdit(QWidget *parent = nullptr) : QLineEdit(parent) {}
protected:
void focusInEvent(QFocusEvent *e) override { emit focusGained(); }
void focusOutEvent(QFocusEvent *e) override { emit focusLost(); }
signals:
void focusGained();
void focusLost();
};

View File

@@ -1,30 +0,0 @@
#ifndef SPKICONBUTTON_H
#define SPKICONBUTTON_H
#include <QPushButton>
#include "spkui_general.h"
class SpkIconButton : public QPushButton
{
Q_OBJECT
public:
SpkIconButton(QWidget *parent = nullptr);
~SpkIconButton() {};
void SetIcon(QIcon, QSize);
void SetIcon(QPixmap);
void SetIconSize(QSize);
protected:
void paintEvent(QPaintEvent *) override;
private:
static enum { Dark, Light } sCurrentTheme;
QPixmap mPmapPaintedIcon;
QSize mPmapSize;
static constexpr int IconMargin = 8; // shall we make it changable?
};
#endif // SPKICONBUTTON_H

View File

@@ -1,61 +0,0 @@
#pragma once
#include <QPainter>
#include <QScrollArea>
#include "spkwindow.h"
class ImgView : public QWidget
{
Q_OBJECT
public:
ImgView(QWidget *parent = nullptr) : QWidget(parent) { mPixmap = nullptr; }
void SetPixmap(QPixmap *p) { mPixmap = p; if(p) setFixedSize(p->size()); update(); }
protected:
void paintEvent(QPaintEvent *e)
{
QPainter p(this);
if(mPixmap)
p.drawPixmap(0, 0, *mPixmap);
p.end();
e->accept();
}
private:
QPixmap *mPixmap;
};
class SpkImgViewer : public SpkWindow
{
Q_OBJECT
public:
SpkImgViewer(QWidget *parent = nullptr);
void ShowWithImage(int idx);
void SetImageTotal(int a) { mTotalImg = a; }
public slots:
void Clear();
void SetPixmap(int idx, QPixmap *img);
private slots:
void SwitchToImage(int idx);
protected:
bool event(QEvent*) override;
private:
void ResizeToFitImageSize(QSize);
private:
QPushButton *mBtnPrev, *mBtnNext;
QScrollArea *mImgArea;
QLabel *mImgIndict;
QMap<int, QPixmap*> mImgMap;
int mCurrentImg, mTotalImg;
QPixmap mIconLoading;
ImgView *mImgShow;
};

View File

@@ -1,25 +0,0 @@
#ifndef SPKJSONAPICONSUMER_H
#define SPKJSONAPICONSUMER_H
#include <QJsonDocument>
#include <QJsonObject>
#include <QJsonArray>
#include <QtNetwork/QNetworkAccessManager>
class SpkJsonApiConsumer: public QObject
{
Q_OBJECT
public:
SpkJsonApiConsumer();
private:
QNetworkAccessManager mNet;
public slots:
void RequestUrl(QUrl);
signals:
void RequestFinish(QJsonDocument, int);
};
#endif // SPKJSONAPICONSUMER_H

View File

@@ -1,34 +0,0 @@
#pragma once
#include <QFrame>
#include <QTimeLine>
class SpkLoading : public QFrame
{
Q_OBJECT
public:
explicit SpkLoading(QWidget *parent = nullptr);
virtual void paintEvent(QPaintEvent *e) override;
virtual void resizeEvent(QResizeEvent *e) override;
private:
QTimeLine *mAnimTimer;
QList<int> mSizeList;
int mUserHeight = 0;
int dw, dh;
double dx, dy;
public slots:
void start() { mAnimTimer->start(); }
void stop() { mAnimTimer->stop(); }
void Begin() { start(); setVisible(true); }
void End() { stop(); setVisible(false); }
void setHeight(int h) { mUserHeight = h; }
void reset();
private slots:
void timer(int s);
void loop();
};

View File

@@ -1,44 +0,0 @@
/**
* @brief Simple logging for Spark Store
*/
#pragma once
#pragma push_macro("signals")
#undef signals
#include <libnotify/notify.h>
#define signals DUMMY
#pragma pop_macro("signals")
#include <QString>
#include <QStringListModel>
#include <QTextStream>
#include <QFile>
class SpkLogger
{
QStringListModel mLogData;
QString mLogPath;
QFile mLogFile;
QTextStream mLogWriter;
static SpkLogger *Instance;
void Initialize(QString suggestPath = "");
bool NotifyViable = false;
public:
SpkLogger(QString suggestPath = "");
~SpkLogger();
static SpkLogger *GetInstance() { return Instance; };
void Log(QString message);
void Warning(QString message);
void Error(QString message, bool pop = false);
void Critical(QString message);
void Notify(QString);
};
#define sLog(X) SpkLogger::GetInstance()->Log(X)
#define sWarn(X) SpkLogger::GetInstance()->Warning(X)
#define sErr(X) SpkLogger::GetInstance()->Error(X)
#define sErrPop(X) SpkLogger::GetInstance()->Error(X,true)
#define sCritical(X) SpkLogger::GetInstance()->Critical(X)
#define sNotify(X) SpkLogger::GetInstance()->Notify(X)

View File

@@ -1,236 +0,0 @@
//
// Created by rigoligo on 2021/5/9.
//
#pragma once
#include "spkwindow.h"
#include <vector>
#include <QTextEdit>
#include <QStackedWidget>
#include <QButtonGroup>
#include <QJsonObject>
#include "spksidebartree.h" // In place of #include <QTreeWidget>
#include <QPointer>
#include <QTimeLine>
#include <QQueue>
#include "spkfocuslineedit.h"
#include "spkiconbutton.h"
#include "page/spkpageuitest.h"
#include "page/spkpagehome.h"
#include "page/spkpageapplist.h"
#include "page/spkpageappdetails.h"
#include "page/spkpagedownloads.h"
#include "page/spkpagesettings.h"
class QNetworkReply;
namespace SpkUi
{
enum SpkStackedPages
{
PgInvalid = -1,
PgHomepage,
PgAppList,
PgAppDetails,
PgDownloads,
PgSettings,
PgQssTest // Must be at last
};
const std::vector<SpkStackedPages> ResourceContexts
{
PgAppList
};
class SpkSidebarSelector : public QObject
{
Q_OBJECT
private:
QPushButton *mLastCheckedBtn;
QTreeWidgetItem *mLastSelectedItem;
QTreeWidget *mCategoryWidget;
QVector<QTreeWidgetItem *> mUnusableItems; // Unselectable top level items; never changes
QTreeWidgetItem* mLastCategoryItem;
int mLastCategoryPage;
public:
SpkSidebarSelector(QObject *parent = nullptr) : QObject(parent)
{
mLastCheckedBtn = nullptr;
mLastSelectedItem = nullptr;
}
// Tree item can either represent a page or a category, data of special roles
// help identify them; Buttons instead can only represent a page
constexpr static int RoleItemIsCategory = Qt::UserRole + 1;
constexpr static int RoleItemCategoryPageId= Qt::UserRole + 2;
void BindPageSwitcherButton(QAbstractButton* w)
{
connect(w, &QAbstractButton::toggled,
this, &SpkSidebarSelector::ButtonToggled);
connect(w, &QAbstractButton::pressed,
this, &SpkSidebarSelector::ButtonPressed);
}
void BindCategoryWidget(QTreeWidget* w)
{
mCategoryWidget = w;
connect(w, &QTreeWidget::itemPressed, this,
&SpkSidebarSelector::TreeItemSelected);
}
void AddUnusableItem(QTreeWidgetItem *i) { mUnusableItems.append(i); }
void GoBack()
{
emit SwitchToCategory(mLastCategoryPage, 0);
mCategoryWidget->currentItem()->setSelected(false);
mLastCategoryItem->setSelected(true);
}
private slots:
// We assume the objects in interest all have the correct properties
void ButtonToggled(bool aBtnState)
{
auto b = qobject_cast<QPushButton*>(sender());
if(mLastCheckedBtn)
{
if(mLastCheckedBtn != b)
{
mLastCheckedBtn->setChecked(false);
mLastCheckedBtn = nullptr;
}
}
else if(mLastSelectedItem)
{
mLastSelectedItem->setSelected(false);
mLastSelectedItem = nullptr;
}
mLastCheckedBtn = b;
auto id = b->property("spk_pageno").toInt();
emit SwitchToPage(static_cast<SpkStackedPages>(id));
}
void ButtonPressed()
{ // Prevent a selected button from being deselected by clicking on it
auto b = qobject_cast<QPushButton*>(sender());
if(mLastCheckedBtn == b)
b->setChecked(false);
}
void TreeItemSelected(QTreeWidgetItem *item, int column)
{
if(mUnusableItems.contains(item))
{
UnusableItemSelected(item); return;
}
if(mLastCheckedBtn)
{
mLastCheckedBtn->setChecked(false);
mLastCheckedBtn = nullptr;
}
mLastSelectedItem = item;
auto id = item->data(column, RoleItemCategoryPageId).toInt();
if(item->data(column, RoleItemIsCategory).toBool())
emit SwitchToCategory(id, 0), mLastCategoryPage = id, mLastCategoryItem = item;
else
emit SwitchToPage(static_cast<SpkStackedPages>(id));
}
void UnusableItemSelected(QTreeWidgetItem *i)
{
i->setSelected(false);
if(mLastSelectedItem)
{
mLastSelectedItem->setSelected(true);
}
else if(mLastCheckedBtn)
{
mLastCheckedBtn->setChecked(true);
}
}
signals:
void SwitchToCategory(int aCategoryId, int aPage);
void SwitchToPage(SpkStackedPages aPageId);
};
class SpkMainWidget : public QFrame
{
Q_OBJECT
public:
SpkMainWidget(QWidget *parent = nullptr);
QHBoxLayout *HorizontalDivide;
QStackedWidget *Pager;
// Category widget is for switching pages
SpkIconButton *BtnSettings, *BtnFeedback, *BtnLogs, *BtnDayNight, *BtnBack;
SpkSidebarTree *CategoryWidget;
QMap<int, QTreeWidgetItem> *CategoryItemMap;
SpkSidebarSelector *SidebarMgr;
QTreeWidgetItem *HomepageItem,
*CategoryParentItem,
*AppDetailsItem,
*DownloadsItem,
*UiTestItem;
// Title bar search bar
SpkFocusLineEdit *SearchEdit;
QAction *ActClearSearchBar, *ActSearchIcon;
QTimeLine *SearchBarAnim;
//Pages
SpkPageUiTest *PageQssTest;
SpkPageHome *PageHome;
SpkPageAppList *PageAppList;
SpkPageAppDetails *PageAppDetails;
SpkPageDownloads *PageDownloads;
SpkPageSettings *PageSettings;
};
}
class SpkMainWindow : public SpkWindow
{
Q_OBJECT
private:
SpkUi::SpkMainWidget *ui;
public:
SpkMainWindow(QWidget *parent = nullptr);
void PopulateCategories(QJsonArray);
private:
void Initialize();
private:
QPointer<QNetworkReply> mCategoryGetReply,
mCategoryAppListGetReply,
mAppDetailsGetReply;
SpkUi::SpkStackedPages mCurrentPage = SpkUi::PgInvalid;
QList<QPair<SpkIconButton*, QString>> mThemedUiIconReferences;
public slots:
void ReloadThemedUiIcons();
void RefreshCategoryData();
private slots:
void SwitchDayNightTheme();
void SwitchToPage(SpkUi::SpkStackedPages page);
void CategoryDataReceived();
// Enter a category (and switch pages)
void EnterCategoryList(int aCategoryId, int aPage);
void CategoryListDataReceived();
// Search a keyword (and switch pages)
void SearchKeyword(QString aKeyword, int aPage);
void SearchDataReceived();
// Enter the details page of an application (and switch pages)
void EnterAppDetails(int aAppId);
void AppDetailsDataReceived();
private:
void PopulateAppList(QJsonObject appData, QString &&keyword);
void PopulateAppDetails(QJsonObject appDetails);
};

View File

@@ -1,20 +0,0 @@
#pragma once
#include <QStyle>
#include <QMessageBox>
#include "spkdialog.h"
class SpkMsgBox : public SpkDialog
{
Q_OBJECT
public:
SpkMsgBox(QWidget *parent = nullptr);
static int StaticExec(QString msg, QString title, QMessageBox::Icon = QMessageBox::NoIcon,
QMessageBox::StandardButtons = QMessageBox::Ok, QString extra = "",
bool expanded = false);
private:
static void AddButtons(SpkMsgBox *me, QMessageBox::StandardButtons b);
QList<QMessageBox::StandardButton> mButtonList;
static constexpr QSize IconSize {48, 48};
static constexpr int Margin = 10;
};

View File

@@ -1,17 +0,0 @@
#pragma once
#include <QLabel>
class SpkNotifyDot : public QLabel
{
Q_OBJECT
public:
SpkNotifyDot(QWidget *parent = nullptr);
~SpkNotifyDot() {}
protected:
virtual void paintEvent(QPaintEvent *) override;
// virtual int widthForHeight(int h) override;
};

View File

@@ -1,30 +0,0 @@
#pragma once
#include <QLabel>
#include <QWidget>
#include <QHBoxLayout>
#include <QPropertyAnimation>
#include <QSequentialAnimationGroup>
class SpkMainWindow;
namespace SpkUi
{
class SpkPopup : public QWidget
{
Q_OBJECT
public:
SpkPopup(QWidget *parent, int aMillis = 3000);
public slots:
void Show(QString aText);
private:
QPoint MoveOffset;
QLabel *mText;
QHBoxLayout *mBox;
QPropertyAnimation *mAnimFadeIn, *mAnimFadeOut;
QSequentialAnimationGroup *mAnim;
};
}

View File

@@ -1,51 +0,0 @@
#pragma once
#include <map>
#include <list>
#include <QColor>
namespace SpkUi
{
QColor ColorTextOnBackground(QColor);
namespace Qss
{
enum ColorSetIndex
{
GlobalBgnd = 0,
ControlsBgnd,
ControlsBgndHighlighted,
SelectionBgnd, AccentColor = SelectionBgnd,
SelectionBgndHighlighted, AccentColorHighlighted = SelectionBgndHighlighted,
LightCtrlsGradLight,
LightCtrlsGradDark,
LightCtrlsGradDarker,
LightCtrlsDisabledBackground,
DarkCtrlsGradLight,
DarkCtrlsGradDark,
DarkCtrlsGradDarker,
DarkCtrlsDisabledBackground,
TextOnSelection, TextOnAccentColor = TextOnSelection,
TextOnGlobalBgnd,
TextOnControlsBgnd,
TextLighter,
TextEvenLighter,
TextDisabled,
GlossyEdge,
ShadesEdge,
ScrollBarNorm,
ScrollBarHover,
DivideLine,
};
extern const std::list<ColorSetIndex> AccentColorExceptions;
extern const std::map<ColorSetIndex, const char *> ColorSet2Token;
extern const std::map<ColorSetIndex, QColor>
DarkColorSet, LightColorSet;
using ColorSet = std::map<Qss::ColorSetIndex, QColor>;
}
}

View File

@@ -1,101 +0,0 @@
#pragma once
#include <QObject>
#include <QQueue>
#include <QSemaphore>
#include <QMap>
#include <QNetworkReply>
#include <QVariant>
struct ResourceResult;
class SpkResourceContext;
class SpkPageBase;
class SpkResource : public QObject
{
Q_OBJECT
public:
enum class ResourceType { HomeImage, AppIcon, TagIcon, AppScreenshot, };
enum class ResourceStatus
{
Ready, ///< The resource is ready to be read now and the file link is included
Deferred, ///< The resource is not in cache or outdated, and is being downloaded
Failed, ///< The requested resource can not be downloaded and thus can not be loaded.
};
private:
struct ResourceTask
{
QString pkgName, path;
ResourceType type;
QVariant info;
int id;
};
static const QMap<ResourceType, QString> ResourceName;
public:
SpkResource(QObject *parent = nullptr);
ResourceResult
RequestResource(const int aId, const QString &aPkgName, ResourceType aType, const QString &aPath,
const QVariant &aInfo = 0);
void PurgeCachedResource(const QString &aPkgName, SpkResource::ResourceType aType,
const QVariant &aInfo);
inline QString GetCachePath(const ResourceTask &task);
ResourceResult CacheLookup(QString pkgName, ResourceType type, QVariant info);
/**
* @brief When the resource context was changed, the new context needs to acquire the resource
* manager, so the resource manager can download resource for the new context.
*
* A resource context, in Spark Store, is likely to be a "page" of the UI. AppList is
* a page, Homepage is a page, AppDetails is a page. But each category is not a separated
* context; they're all from AppList page.
* @param dest Pass a SpkResourceContext as the resource acquisition destination. Signals will
* be connected in this function internally. When a resource was downloaded, this
* object will be notified.
* @param clearQueue determines if the awaiting tasks needs to be cleared.
* @param stopOngoing determines if ongoing tasks needs to be terminated.
*/
void Acquire(SpkPageBase *dest, bool stopOngoing, bool clearQueue = true);
public:
static SpkResource* Instance;
const int mMaximumConcurrent; ///< Maximum number of concurrent resource downloads
const QString mCacheDirectory;///< Where caches were stored
private slots:
void ResourceDownloaded();
void TryBeginAwaitingTasks();
private:
ResourceResult LocateCachedResource(const ResourceTask &task);
signals:
void AcquisitionFinish(int id, ResourceResult result);
private:
// Operations to mAwaitingRequests and mWorkingRequests must be all made synchronously.
// When connecting signal/slot pairs regarding operations to them, use QueuedConnection.
QQueue<ResourceTask> mAwaitingRequests;
QSemaphore *mRequestSemaphore;
QMap<QNetworkReply*, int> mWorkingRequests;
};
struct ResourceResult
{
SpkResource::ResourceStatus status;
QByteArray data;
};
Q_DECLARE_METATYPE(ResourceResult);
/**
* @brief SpkResourceContext is meant to be used by connecting signals from it. An object inheriting
* it would be theoretically a resource context. A resource context can acquire a SpkResource
* management object for downloading resources. More details at SpkResource::Acquire.
*/

View File

@@ -1,17 +0,0 @@
#pragma once
#include <QTreeWidget>
namespace SpkUi
{
class SpkSidebarTree : public QTreeWidget
{
Q_OBJECT
public:
SpkSidebarTree(QWidget* parent = nullptr);
protected:
void mouseMoveEvent(QMouseEvent *) override;
void mousePressEvent(QMouseEvent *) override;
};
}

View File

@@ -1,51 +0,0 @@
#pragma once
#include <QJsonDocument>
#include <QString>
#include <QSettings>
#include <QtNetwork/QNetworkReply>
#include <QtNetwork/QNetworkAccessManager>
#include "spklogging.h"
#include "spkresource.h"
#include "spkconfig.h"
class SpkMainWindow;
/**
* @brief SpkStore class is the core of the store client side program, it is constructed first and
* handling all processing after the launch. All client side data should be held by it,
* including preferences class, category names, request URLs, downloads status, packaging
* backend interfaces and so on.
*/
class SpkStore : public QObject
{
Q_OBJECT
public:
static SpkStore *Instance;
SpkConfig *mCfg;
SpkStore(bool aCli, QString &aLogPath);
~SpkStore();
SpkMainWindow* GetRootWindow() { return mMainWindow; }
void SetApiRequestUrl(QString aUrlStr) { mApiRequestUrl = aUrlStr; }
QString GetApiRequestUrl() { return mApiRequestUrl; }
QNetworkReply *SendApiRequest(QString path, QJsonDocument param = QJsonDocument());
QNetworkReply *SendResourceRequest(QString path); ///< WARNING: Only intended for SpkResource!
QNetworkReply *SendDownloadRequest(QUrl file, qint64 fromByte = -1, qint64 toByte = -1);
QNetworkReply *SendCustomHeadRequest(QNetworkRequest);
private:
SpkLogger *mLogger;
SpkMainWindow *mMainWindow = nullptr;
SpkResource *mResMgr = nullptr;
QNetworkAccessManager *mNetMgr = nullptr;
QString mDistroName,
mApiRequestUrl,
mResourceRequestUrl,
mUserAgentStr,
mConfigPath;
};

View File

@@ -1,27 +0,0 @@
#pragma once
#include <QtWidgets>
#include <QVector>
/**
* @brief SpkStretchLayout is meant solely for use with app list, where each layout item is
* considered the same size.
*/
class SpkStretchLayout : public QLayout
{
public:
SpkStretchLayout(QWidget *parent = nullptr);
~SpkStretchLayout();
void addItem(QLayoutItem *item) override;
QSize sizeHint() const override;
QSize minimumSize() const override;
int count() const override;
QLayoutItem* itemAt(int) const override;
QLayoutItem* takeAt(int) override;
void setGeometry(const QRect &rect) override;
private:
QVector<QLayoutItem*> mItems;
};

View File

@@ -1,71 +0,0 @@
//
// Created by rigoligo on 2021/5/8.
//
#pragma once
#include <QHBoxLayout>
#include <QLabel>
#include <QPixmap>
#include <QPainter>
#include <QBrush>
#include <QPushButton>
#include <QMainWindow>
namespace SpkUi
{
}
class SpkWindow;
class SpkTitleBarDefaultButton : public QPushButton
{
Q_OBJECT
public:
SpkTitleBarDefaultButton(QWidget* parent = nullptr);
enum OperationButton { Minimize = 1, MaximizeRestore = 2, Close = 4, Restore = 3 };
void SetRole(OperationButton);
constexpr static int ButtonWidth = 60;
protected:
void paintEvent(QPaintEvent *e) override;
private:
OperationButton Role;
void PaintSymbol(QPainter &);
};
class SpkTitleBar : public QFrame
{
Q_OBJECT
friend class SpkWindow;
public:
SpkTitleBar(QWidget *parent = nullptr);
~SpkTitleBar();
static constexpr int Height = 48;
using OperationButton = SpkTitleBarDefaultButton::OperationButton;
void SetOperationButton(OperationButton);
void SetIcon(QPixmap p) { mIcon->setPixmap(p); }
void SetTitle(QString t) { mTitle->setText(t); }
QString GetTitle() { return mTitle->text(); }
void SetUseIcon(bool t) { mIcon->setVisible(t); }
void SetLinkedWindow(SpkWindow *w) { mLinkedWindow = w; }
QHBoxLayout *GetUserSpace() { return mUserSpace; }
protected:
bool event(QEvent*) override;
private:
QLabel *mIcon;
QLabel *mTitle;
SpkWindow *mLinkedWindow;
QHBoxLayout *mMainLayout, *mUserSpace, *mBtnGroup;
SpkTitleBarDefaultButton *mBtnMin, *mBtnMaxRestore, *mBtnClose;
private slots:
void CloseWindow();
void MinimizeWindow();
void MaximizeRestoreWindow();
};

View File

@@ -1,81 +0,0 @@
//
// Created by rigoligo on 2021/5/8.
//
#pragma once
#include <QWidget>
#include <QString>
#include <QSize>
#include <QColor>
#include <map>
#include "spkqsshelper.h"
#include "dtk/spkdtkplugin.h"
namespace SpkUi
{
enum SpkUiStyle { Invalid, Light, Dark };
enum SpkButtonStyle { Normal = 0, Recommend, Warn };
class SpkPopup;
constexpr int StackTraceArraySize = 64;
constexpr const char * const StoreIconName = "spark-store";
class UiMetaObject : public QObject
{
Q_OBJECT
private:
static UiMetaObject *sGlobalInstance;
public:
UiMetaObject() {}
public slots:
void SetAccentColor(QColor);
void SetDarkLightTheme(bool isDark);
signals:
void SetThemeButtonVisible(bool);
};
extern UiMetaObject SpkUiMetaObject;
extern SpkUiStyle CurrentStyle;
extern QString StylesheetBase, CurrentStylesheet;
extern QColor ColorLine, ColorBack,
ColorBtnMaskUnselected, ///< SpkIconButton icon mask colors, unselected & selected
ColorBtnMaskSelected;
extern QSize PrimaryScreenSize;
extern SpkDtkPlugin *DtkPlugin;
extern QStyle *OldSystemStyle;
extern std::map<Qss::ColorSetIndex, QColor> CurrentColorSet;
extern SpkPopup *Popup;
namespace States
{
extern bool IsDDE, IsUsingDtkPlugin;
extern bool DoRespondAutoTheme;
extern int LightDarkMode; ///< Tied to settings UI value
bool ThemeConfigCallback();
}
namespace Priv
{
extern bool CrashHandlerActivated;
using namespace SpkUi::Qss;
}
void Initialize();
void GuessAppropriateTheme();
void PrepareForDeepinDesktop();
bool CheckIsDeepinDesktop();
QString StylesheetFromColors(Qss::ColorSet);
QIcon GetThemedIcon(QString);
void CrashSignalHandler(int);
void SetGlobalStyle(const SpkUiStyle, const bool aPreserveAccentColor);
};

View File

@@ -1,32 +0,0 @@
//
// Created by rigoligo on 2021/5/9.
//
#pragma once
#pragma push_macro("signals")
#undef signals
#include <libnotify/notify.h>
#define signals DUMMY
#pragma pop_macro("signals")
#include <QString>
#include <QObject>
#include "spkui_general.h"
class SpkUiMessage : public QObject
{
Q_OBJECT
public:
static void SendDesktopNotification(QString aMsg,
const char * const aIcon = SpkUi::StoreIconName);
static void SendStoreNotification(QString);
static void SetDesktopNotifyTimeout(int ms);
private:
static NotifyNotification *_notify;
static int mTimeoutDesktop;
signals:
};

View File

@@ -1,36 +0,0 @@
#pragma once
#include <QPointer>
#include <QString>
#include <QSettings>
#include <QFile>
#include <QtNetwork/QNetworkReply>
#include "spkstore.h"
#include "spklogging.h"
#define STORE (SpkStore::Instance)
#define CFG (SpkStore::Instance->mCfg)
#define RES (SpkResource::Instance)
#define PKG (SpkPkgMgrBase::Instance())
namespace SpkUtils
{
QString GetDistroName();
void VerifySingleRequest(QPointer<QNetworkReply> aReply);
void DeleteReplyLater(QNetworkReply *aReply);
int VerifyReplyJson(QNetworkReply *aReply, QJsonValue& aRetDoc);
QString CutFileName(QString);
QString CutPath(QString);
QString BytesToSize(size_t s, int prec = 2);
bool EnsureDirExists(QString path);
bool FindViableTerminal();
extern QPair<QString, QString> AvailableTerminal;
}

Some files were not shown because too many files have changed in this diff Show More