diff -Nru kylin-os-manager-2.0.0/debian/changelog kylin-os-manager-2.0.0/debian/changelog --- kylin-os-manager-2.0.0/debian/changelog 2025-03-12 16:03:41.000000000 +0800 +++ kylin-os-manager-2.0.0/debian/changelog 2025-03-13 00:00:00.000000000 +0800 @@ -1,3 +1,15 @@ +kylin-os-manager (2.0.0-62) nile; urgency=medium + + * BUG: + #IBIXWO【控制面板】选项菜单中存在"Help"及"Feedback"英文选项(该选项点击无反应) + #IBPRBJ【主要】【控制面板】控制面板-选项中‘意见反馈’控件,点击后无反应 + #IBIVS2【闹钟】选项菜单中存在"Feedback"英文选项,点击无反应 + * 需求:无 + * 其他改动说明:无 + * 其他改动影响域:无 + + -- jishengjie <jishengjie@kylinos.cn> Thu, 13 Mar 2025 00:00:00 +0800 + kylin-os-manager (2.0.0-61) nile; urgency=medium * BUG: diff -Nru kylin-os-manager-2.0.0/debian/kylin-os-manager.postinst kylin-os-manager-2.0.0/debian/kylin-os-manager.postinst --- kylin-os-manager-2.0.0/debian/kylin-os-manager.postinst 2025-03-12 16:03:41.000000000 +0800 +++ kylin-os-manager-2.0.0/debian/kylin-os-manager.postinst 2025-03-13 00:00:00.000000000 +0800 @@ -19,10 +19,10 @@ # 设置 kylin-core-dump-trailblazer.service、kylin-core-dump-monitor.service 开机自启 # systemctl enable kylin-core-dump-trailblazer.service -systemctl enable kylin-core-dump-monitor.service +# systemctl enable kylin-core-dump-monitor.service # 安装完包后启动 kylin-core-dump-monitor.service -systemctl restart kylin-core-dump-monitor.service +# systemctl restart kylin-core-dump-monitor.service # 替换掉旧版的服务与支持 old_service_bin="/usr/bin/kylin-service-support" diff -Nru kylin-os-manager-2.0.0/debian/patches/0135-106-release-2.0.0-62.patch kylin-os-manager-2.0.0/debian/patches/0135-106-release-2.0.0-62.patch --- kylin-os-manager-2.0.0/debian/patches/0135-106-release-2.0.0-62.patch 1970-01-01 08:00:00.000000000 +0800 +++ kylin-os-manager-2.0.0/debian/patches/0135-106-release-2.0.0-62.patch 2025-03-13 00:00:00.000000000 +0800 @@ -0,0 +1,3243 @@ +From: snowsi <348240162@qq.com> +Date: Thu, 13 Mar 2025 09:37:43 +0000 +Subject: !106 release 2.0.0-62 Merge pull request !106 from + snowsi/openkylin/nile + +--- + plugins/service-support/CMakeLists.txt | 2 + + .../service-support-mini/CMakeLists.txt | 74 +++ + .../service-support/service-support-mini/main.cpp | 179 ++++++ + .../service-support/service-support-mini/res.qrc | 11 + + .../service-support-mini/res/dialog-warning.png | Bin 0 -> 1729 bytes + .../service-support-mini/res/star-d.png | Bin 0 -> 596 bytes + .../service-support-mini/res/star-l.png | Bin 0 -> 522 bytes + .../service-support-mini/src/blacklist.cpp | 157 +++++ + .../service-support-mini/src/blacklist.h | 17 + + .../service-support-mini/src/feedbackcommon.cpp | 170 +++++ + .../service-support-mini/src/feedbackcommon.h | 36 ++ + .../service-support-mini/src/passivitywidget.cpp | 230 +++++++ + .../service-support-mini/src/passivitywidget.h | 28 + + .../service-support-mini/src/voluntarilywidget.cpp | 696 +++++++++++++++++++++ + .../service-support-mini/src/voluntarilywidget.h | 100 +++ + .../translations/kom-service-support-mini_bo_CN.ts | 188 ++++++ + .../translations/kom-service-support-mini_kk.ts | 188 ++++++ + .../translations/kom-service-support-mini_ky.ts | 188 ++++++ + .../translations/kom-service-support-mini_mn.ts | 188 ++++++ + .../translations/kom-service-support-mini_ug.ts | 188 ++++++ + .../translations/kom-service-support-mini_zh_CN.ts | 188 ++++++ + .../translations/kom-service-support-mini_zh_HK.ts | 188 ++++++ + .../translations/update-translations.sh | 15 + + 23 files changed, 3031 insertions(+) + create mode 100644 plugins/service-support/service-support-mini/CMakeLists.txt + create mode 100644 plugins/service-support/service-support-mini/main.cpp + create mode 100644 plugins/service-support/service-support-mini/res.qrc + create mode 100644 plugins/service-support/service-support-mini/res/dialog-warning.png + create mode 100644 plugins/service-support/service-support-mini/res/star-d.png + create mode 100644 plugins/service-support/service-support-mini/res/star-l.png + create mode 100644 plugins/service-support/service-support-mini/src/blacklist.cpp + create mode 100644 plugins/service-support/service-support-mini/src/blacklist.h + create mode 100644 plugins/service-support/service-support-mini/src/feedbackcommon.cpp + create mode 100644 plugins/service-support/service-support-mini/src/feedbackcommon.h + create mode 100644 plugins/service-support/service-support-mini/src/passivitywidget.cpp + create mode 100644 plugins/service-support/service-support-mini/src/passivitywidget.h + create mode 100644 plugins/service-support/service-support-mini/src/voluntarilywidget.cpp + create mode 100644 plugins/service-support/service-support-mini/src/voluntarilywidget.h + create mode 100644 plugins/service-support/service-support-mini/translations/kom-service-support-mini_bo_CN.ts + create mode 100644 plugins/service-support/service-support-mini/translations/kom-service-support-mini_kk.ts + create mode 100644 plugins/service-support/service-support-mini/translations/kom-service-support-mini_ky.ts + create mode 100644 plugins/service-support/service-support-mini/translations/kom-service-support-mini_mn.ts + create mode 100644 plugins/service-support/service-support-mini/translations/kom-service-support-mini_ug.ts + create mode 100644 plugins/service-support/service-support-mini/translations/kom-service-support-mini_zh_CN.ts + create mode 100644 plugins/service-support/service-support-mini/translations/kom-service-support-mini_zh_HK.ts + create mode 100755 plugins/service-support/service-support-mini/translations/update-translations.sh + +diff --git a/plugins/service-support/CMakeLists.txt b/plugins/service-support/CMakeLists.txt +index 52ad064..6db4892 100644 +--- a/plugins/service-support/CMakeLists.txt ++++ b/plugins/service-support/CMakeLists.txt +@@ -90,3 +90,5 @@ install(FILES ${SERVICE_SUPPORT_TOP_DIR}/script/architecture.py DESTINATION /usr + install(FILES ${SERVICE_SUPPORT_TOP_DIR}/script/machine.py DESTINATION /usr/share/kylin-os-manager/script) + install(FILES ${SERVICE_SUPPORT_TOP_DIR}/script/node.py DESTINATION /usr/share/kylin-os-manager/script) + install(FILES ${SERVICE_SUPPORT_TOP_DIR}/script/release.py DESTINATION /usr/share/kylin-os-manager/script) ++ ++add_subdirectory(service-support-mini) +diff --git a/plugins/service-support/service-support-mini/CMakeLists.txt b/plugins/service-support/service-support-mini/CMakeLists.txt +new file mode 100644 +index 0000000..e221659 +--- /dev/null ++++ b/plugins/service-support/service-support-mini/CMakeLists.txt +@@ -0,0 +1,74 @@ ++cmake_minimum_required(VERSION 3.16) ++ ++project(service-support-mini) ++ ++set(TOP_DIR ${CMAKE_CURRENT_LIST_DIR}/../../../) ++set(SERVICE_SUPPORT_MINI_TOP_DIR ${CMAKE_CURRENT_LIST_DIR}) ++set(CMAKE_AUTOMOC ON) ++set(CMAKE_AUTORCC ON) ++set(CMAKE_AUTOUIC ON) ++ ++set(SRCS ++ "${SERVICE_SUPPORT_MINI_TOP_DIR}/main.cpp" ++ "${SERVICE_SUPPORT_MINI_TOP_DIR}/src/voluntarilywidget.cpp" ++ "${SERVICE_SUPPORT_MINI_TOP_DIR}/src/passivitywidget.cpp" ++ "${SERVICE_SUPPORT_MINI_TOP_DIR}/src/feedbackcommon.cpp" ++ "${SERVICE_SUPPORT_MINI_TOP_DIR}/src/blacklist.cpp" ++ "${SERVICE_SUPPORT_MINI_TOP_DIR}/res.qrc" ++) ++ ++set(TRANSLATIONS ++ "${SERVICE_SUPPORT_MINI_TOP_DIR}/translations/kom-service-support-mini_zh_CN.ts" ++ "${SERVICE_SUPPORT_MINI_TOP_DIR}/translations/kom-service-support-mini_zh_HK.ts" ++ "${SERVICE_SUPPORT_MINI_TOP_DIR}/translations/kom-service-support-mini_bo_CN.ts" ++ "${SERVICE_SUPPORT_MINI_TOP_DIR}/translations/kom-service-support-mini_mn.ts" ++ "${SERVICE_SUPPORT_MINI_TOP_DIR}/translations/kom-service-support-mini_ug.ts" ++ "${SERVICE_SUPPORT_MINI_TOP_DIR}/translations/kom-service-support-mini_kk.ts" ++ "${SERVICE_SUPPORT_MINI_TOP_DIR}/translations/kom-service-support-mini_ky.ts" ++) ++set_source_files_properties(${TRANSLATIONS} PROPERTIES OUTPUT_LOCATION "${CMAKE_CURRENT_BINARY_DIR}/translations") ++qt5_add_translation(QM_FILE ${TRANSLATIONS}) ++ ++add_executable(${PROJECT_NAME} ${SRCS} ${QM_FILE}) ++ ++pkg_check_modules(GLIB_2.0 REQUIRED glib-2.0) ++include_directories(${GLIB_2.0_INCLUDE_DIRS}) ++link_directories(${GLIB_2.0_LIBRARY_DIRS}) ++target_link_libraries(${PROJECT_NAME} PRIVATE ${GLIB_2.0_LIBRARIES}) ++ ++pkg_check_modules(KYSDK_MODULE kysdk-qtwidgets kysdk-kabase kysdk-diagnostics kysdk-ukenv) ++if (${KYSDK_MODULE_FOUND}) ++ target_include_directories(${PROJECT_NAME} PRIVATE ${KYSDK_MODULE_INCLUDE_DIRS}) ++ target_link_directories(${PROJECT_NAME} PRIVATE ${KYSDK_MODULE_LIBRARY_DIRS}) ++ target_link_libraries(${PROJECT_NAME} PRIVATE ${KYSDK_MODULE_LIBRARIES}) ++else() ++ message("========================= Use Compatibility: ${PROJECT_NAME} =========================") ++ set(COMPATIBILITY_NAME compatibility) ++ set(COMPATIBILITY_DIR ${TOP_DIR}/${COMPATIBILITY_NAME}) ++ target_include_directories(${PROJECT_NAME} PRIVATE ${COMPATIBILITY_DIR}/kysdk-qtwidgets/) ++ target_include_directories(${PROJECT_NAME} PRIVATE ${COMPATIBILITY_DIR}/kysdk-kabase/) ++ target_include_directories(${PROJECT_NAME} PRIVATE ${COMPATIBILITY_DIR}/kysdk-ukenv/) ++ target_include_directories(${PROJECT_NAME} PRIVATE ${COMPATIBILITY_DIR}/kysdk-diagnostics/) ++ target_link_libraries(${PROJECT_NAME} PRIVATE ${COMPATIBILITY_NAME}) ++endif() ++ ++find_package(PkgConfig) ++pkg_check_modules(QGSETTINGS REQUIRED IMPORTED_TARGET gsettings-qt) ++include_directories(${GSETTINGS_INCLUDE_DIRS}) ++target_link_libraries(${PROJECT_NAME} PRIVATE PkgConfig::QGSETTINGS) ++ ++find_package(Qt5 COMPONENTS Widgets REQUIRED) ++target_link_libraries(${PROJECT_NAME} PRIVATE Qt5::Widgets) ++ ++find_package(KF5WindowSystem) ++target_link_libraries(${PROJECT_NAME} PRIVATE KF5::WindowSystem) ++ ++target_include_directories(${PROJECT_NAME} PRIVATE ${SERVICE_SUPPORT_MINI_TOP_DIR}) ++target_include_directories(${PROJECT_NAME} PRIVATE ${SERVICE_SUPPORT_MINI_TOP_DIR}/src) ++ ++target_include_directories(${PROJECT_NAME} PRIVATE ${SERVICE_SUPPORT_MINI_TOP_DIR}/../${SERVICE_SUPPORT_BACKEND}) ++target_link_libraries(${PROJECT_NAME} PRIVATE ${SERVICE_SUPPORT_BACKEND}) ++ ++install(TARGETS ${PROJECT_NAME} DESTINATION /usr/lib/kylin-os-manager/bin/) ++install(FILES ${QM_FILE} DESTINATION /usr/share/kylin-os-manager/translations/) ++ +diff --git a/plugins/service-support/service-support-mini/main.cpp b/plugins/service-support/service-support-mini/main.cpp +new file mode 100644 +index 0000000..0c6f9e6 +--- /dev/null ++++ b/plugins/service-support/service-support-mini/main.cpp +@@ -0,0 +1,179 @@ ++#include <QApplication> ++#include <QTranslator> ++#include <QDir> ++#include <QDebug> ++#include <QFileInfo> ++#include <QLibraryInfo> ++#include <QScreen> ++#include "log.hpp" ++#include "voluntarilywidget.h" ++#include "passivitywidget.h" ++#include "blacklist.h" ++ ++void singleton(const QString &exec) { ++ QProcess process; ++ process.setProgram("bash"); ++ process.setArguments({"-c", "ps -eo pid,args | grep service-support-mini | grep -v grep"}); ++ process.start(); ++ process.waitForFinished(); ++ ++ const auto output = QString::fromUtf8(process.readAllStandardOutput()).trimmed(); ++ const auto lines = output.split('\n'); ++ for (const auto &line: lines) { ++ auto elements = line.split(' '); ++ elements.removeAll(""); ++ ++ if (elements.size() != 4) { ++ continue; ++ } ++ if (elements.at(1) != "/opt/kylin-os-manager/tools/service-support-mini" || ++ !elements.at(2).contains("-mode") || ++ !elements.at(3).contains("-exe")) ++ { ++ continue; ++ } ++ ++ auto current_pid = elements.at(0).trimmed(); ++ auto current_mode = elements.at(2); ++ current_mode = current_mode.remove("-mode="); ++ auto current_exec = elements.at(3); ++ current_exec = current_exec.remove("-exe="); ++ ++ if (current_pid.toInt() == QCoreApplication::applicationPid()) { ++ // 过滤掉自己 ++ continue; ++ } ++ ++ if (current_mode == "1" && current_exec == exec) { ++ // 主动反馈弹窗已运行, 置顶弹窗 ++ QProcess p; ++ p.setProgram("bash"); ++ auto top_up_command = QString("wmctrl -i -a $(wmctrl -p -G -l | grep %1 | head -1 | awk '{print $1}')").arg(current_pid); ++ p.setArguments({"-c", top_up_command}); ++ p.startDetached(); ++ ++ qInfo() << "Global feedback [" << exec << "] already running, current process exit."; ++ ++ exit(0); ++ } ++ } ++} ++ ++int main(int argc, char *argv[]) { ++#ifndef DEBUG_MODE ++ qInstallMessageHandler(kdk::kabase::Log::logOutput); ++#endif ++ ++#if (QT_VERSION >= QT_VERSION_CHECK(5, 6, 0)) ++ QApplication::setAttribute(Qt::AA_EnableHighDpiScaling); ++ QApplication::setAttribute(Qt::AA_UseHighDpiPixmaps); ++#endif ++ ++#if (QT_VERSION >= QT_VERSION_CHECK(5, 14, 0)) ++ QApplication::setHighDpiScaleFactorRoundingPolicy(Qt::HighDpiScaleFactorRoundingPolicy::PassThrough); ++#endif ++ ++ QApplication app(argc, argv); ++ ++ // 加载应用翻译文件 ++ QString kylinFileCrush = "/usr/share/kylin-os-manager/translations"; ++ QTranslator trans_global; ++ if (!trans_global.load(QLocale(), "kom-service-support-mini", "_", kylinFileCrush)) { ++ qWarning() << "main Load global translations file" << QLocale() << "failed!"; ++ } else { ++ app.installTranslator(&trans_global); ++ } ++ // 加载service-support-backend翻译文件 ++ QTranslator trans_global_2; ++ if (!trans_global_2.load(QLocale(), "kom-service-support", "_", kylinFileCrush)) { ++ qWarning() << "main Load global2 translations file" << QLocale() << "failed!"; ++ } else { ++ app.installTranslator(&trans_global_2); ++ } ++ // 加载 Qt 翻译文件 ++ QTranslator trans_qt; ++ QString qtTransPath = QLibraryInfo::location(QLibraryInfo::TranslationsPath); ++ if (!trans_qt.load(QLocale(), "qt", "_", qtTransPath)) { ++ qWarning() << "main Load qt translations file" << QLocale() << "failed!"; ++ } else { ++ app.installTranslator(&trans_qt); ++ } ++ // 加载 sdk 的翻译 ++ QString locale = QLocale::system().name(); ++ QTranslator sdk_trans; ++ if (!sdk_trans.load(":/translations/gui_" + locale + ".qm")) { ++ qDebug() << "Load sdk translation file failed!"; ++ } else { ++ app.installTranslator(&sdk_trans); ++ } ++ ++ //参数解析 ++ QStringList args = app.arguments(); ++ args.removeFirst(); ++#ifdef DEBUG_MODE ++ if (args.isEmpty()) { ++ // /opt/kylin-os-manager/tools/service-support-mini -mode=2 -exe=kylin-printer -path=/home/yyf/sensors -restart=2f7573722f62696e2f6b796c696e2d7072696e746572 ++ args = QStringList()<< "-mode=3" << "-path=/home/yyf/sensors" << "-exe=kylin-printer" << "-restart=2f7573722f62696e2f6b796c696e2d7072696e746572"; ++ } ++#endif ++ QString mode; ++ QString path; ++ QString exe; ++ QString restart; ++ QString code; ++ for (QString arg: args) { ++ if (!arg.contains("=")) { ++ continue; ++ } ++ if (arg.startsWith("-mode")) { ++ mode = arg.mid(arg.indexOf("=") +1); ++ } else if (arg.startsWith("-path")) { ++ path = arg.mid(arg.indexOf("=") +1); ++ } else if (arg.startsWith("-exe")) { ++ exe = arg.mid(arg.indexOf("=") +1); ++ } else if (arg.startsWith("-restart")) { ++ restart = QByteArray::fromHex(arg.mid(arg.indexOf("=") +1).toLocal8Bit()); ++ }else if (arg.startsWith("-code")) { ++ code = arg.mid(arg.indexOf("=") +1); ++ } ++ } ++ if (exe.isEmpty()){ ++ qDebug()<<"exe为空"; ++ exit(-1); ++ } ++ QFileInfo fi(path); ++ if ((mode == "2" || mode == "3") && (!fi.exists())){ ++ qDebug()<<"path不存在 "<<path; ++ exit(-1); ++ } ++ ++ // 单例运行 ++ singleton(exe); ++ ++ VoluntarilyWidget voluntarily; ++ voluntarily.setArgs(path, exe, restart, mode, code); ++ PassivityWidget passivity; ++ passivity.setArgs(path, exe, restart, mode, code); ++ if (mode == "1") { ++ voluntarily.run(); ++ const auto primary_screen = QGuiApplication::screenAt(QCursor::pos())->geometry(); ++ const auto x = primary_screen.width() / 2 - voluntarily.width() / 2; ++ const auto y = primary_screen.height() / 2 - voluntarily.height() / 2; ++ voluntarily.move(x, y); ++ voluntarily.show(); ++ } else if (mode == "2") { ++ // 判断可执行文件是否在 7 天不在弹出的黑名单里 ++ if (Blacklist::Contain(exe)) { ++ exit(-1); ++ } ++ passivity.run(); ++ } else if (mode == "3") { ++ passivity.run(); ++ } else { ++ qDebug()<<"mode值不合规 "<<mode; ++ exit(-1); ++ } ++ qDebug()<<"解析参数完成"; ++ ++ return app.exec(); ++} +diff --git a/plugins/service-support/service-support-mini/res.qrc b/plugins/service-support/service-support-mini/res.qrc +new file mode 100644 +index 0000000..2dbd6dd +--- /dev/null ++++ b/plugins/service-support/service-support-mini/res.qrc +@@ -0,0 +1,11 @@ ++<RCC> ++ <qresource prefix="/"> ++ <file>../res/qcpic.png</file> ++ <file>../res/file-item-close.png</file> ++ <file>../res/damaged_img.png</file> ++ <file>../res/fail.png</file> ++ <file>res/star-l.png</file> ++ <file>res/star-d.png</file> ++ <file>res/dialog-warning.png</file> ++ </qresource> ++</RCC> +diff --git a/plugins/service-support/service-support-mini/res/dialog-warning.png b/plugins/service-support/service-support-mini/res/dialog-warning.png +new file mode 100644 +index 0000000..ce73b59 +--- /dev/null ++++ b/plugins/service-support/service-support-mini/res/dialog-warning.png +@@ -0,0 +1,7 @@ ++�PNG ++ ++��� IHDR���,���,����Z���sRGB�������sBIT|d���kIDATX���_���?g~���Y1٠��>�-Q4����/�R}Ѣ��>�c�PJ�- $)}h�)i| ��<֧���P�P�Zhc0�)�jv�;��>ܙ���������3�����s���A�ё)�Xއ�>�̦�l/��q�[`��ɀ��K����kS:��9;�{�Gy�.0�Q�""�����@v��ܥsk�v��FB ���A��Ug�����gE��ڦC+�vㇻ ������ ���Sy��G�#u}p�]hVķ �MZ:P�������F��=?;Ύ/`��&�����e�-�i"��7|<�ky�zmW���|i�ώ�k)���%�������'V:��m���[�hᶀ�Y�-��/ W�ځc�V��$!oѬ������d?��o�VT1���]���<�Z�H�-�}?Â�������l ���L}�T=7�k������m�ƞ�]gV ����A,��1��깉�Ȍo����I�b���L<���;X���B��5w���ߒ��������m�̊�y�$N��'��x��Ll��<`��EB6jL����� �^�Ӊ�Ή]:0E�|��UW.6b�ΰG�M��/��_B>�;�i�M��"��ΐե}�娭�@'7jh���`��w��# �@��K�ǟdui_�j+FgݵT)RlU�90�%��<$�Gu{vBZ�;3�X?�ٞV`S�V��[��s� ��BO�e,�K�V�U���'Dm�J���Z��a1`TS����$�kW�i��!f�;�3�D�A��`O��٭��]T��l�(�#���-j ++�옧 ++��(��F�m �:��������[1�Yf�R���le�Rt��9Du��%�P2H�ϼO��ְ�ױ�-'E��f�I%�f�,�(wA����*��2V4-, ����5�����W�c�6����$�����%� ��xh�_ ++T����������j��~�L�/�k8Z�' ��k�?Y)h��|�d�h�-��!f�������-|�~��7��-��;�ˢ��ߜBÛ�M��`���p+����0���GH���G�E�hg ߛG��َ����zB/�[O�ر����{���{�V=�����u;RmR���� ��7�!�V�f���$g��Mo���S��$)�x4d ������~������X�"��SV7� �59:X��r�5�k�}�fX�0�6o��ݞ�e;�I��S��l�?�ڍ\�[1�S�b��ݻ�ݻ��O!�:��ߤ_���\�jr^}�������UG�H��u��AO|��I�%:g�� ���� #��e��E�S�|�tت\g��&1G �%��(UQ?Z��SY��M�^{�/�*�i:�[Z��7�-�����pF�]=\��v}��+�=��t�8S���jJȖ�k���r?�R��7 #uS�${}z������\1�=�U[22�j��ZV��6-���������"��t ++�:6R�pJN��WMB����w��x�|��:��Cn ��\�XX`�{�X��"?�� G�U���cNN��ҦC��h'��yx�v�>k�c�A�?�9Y�V�h]�l�kS8ه��6 ����,�݅��[a@�.ɉ�����ޕT�ڑ&\����IEND�B`� +\ No newline at end of file +diff --git a/plugins/service-support/service-support-mini/res/star-d.png b/plugins/service-support/service-support-mini/res/star-d.png +new file mode 100644 +index 0000000..b24a74d +--- /dev/null ++++ b/plugins/service-support/service-support-mini/res/star-d.png +@@ -0,0 +1,5 @@ ++�PNG ++ ++��� IHDR��� ������M ++)���sRGB�������sBIT|d����IDATH��W�q�0܅>�^�T�;�;H*HXA� ++u W`��t`���03�$?�~�<Dy2$h�d����@��!��1��(�~X����������3��֕�F���J������s9�������dN�V���_DJ�ԍ�V�f`�V'�IWLcL����ׄ��f�%.+�ۙ��(&��n�选�b</���U@Et $y%"�װ�x!%ɘdb��[}LJ-"����$�� ��Z�3MӯJ��&?��Y��`��K a�er!r��2\]��H..�N2R��HFI,"%�Ͼ�'��@���$������"rA�n�s���7�{�1Ƽ�ADB�nR 3�NL�6�����4��1�jJV$�SPJ]��������#a��6�0��(�Fe5�y~{r��f� ;���R{c0tg`8��6cL4�N=�5�1��ϸN��"�搉1&�Zς x:4A𤵞�%DD��������MDB��������o�쫩�Sk����f����l����IEND�B`� +\ No newline at end of file +diff --git a/plugins/service-support/service-support-mini/res/star-l.png b/plugins/service-support/service-support-mini/res/star-l.png +new file mode 100644 +index 0000000..70dbf2c +--- /dev/null ++++ b/plugins/service-support/service-support-mini/res/star-l.png +@@ -0,0 +1,4 @@ ++�PNG ++ ++��� IHDR��� ������M ++)���sRGB�������sBIT|d����IDATH�ŗ�A�0��8�nP&����N�L�L�l����� �t������ X���k�rMr/� �1z(�����%���%'�G��x땡�N���PT�9�b"^B�r����@If]0�c�90��!T=j6����W(�����@��j�:�#k�/�>�c�b)�����:PEi�^�!�R���"�䤋_$�:����Ҥ+����E�W"���@�*��N�+�!���.�#r�W�Ӊ$aLA����`�ρ�����IHa�$��� �VDLĴƒ���;ad��L�Е��4�����Prгȅ���q���_@�;o�uDe�S��ݝ�#@�i�@�qT@ �.!�x8�luJ�A�H�[i!�غ3�s�6��rA\�&��o��K��!λ�ޮضj�@���L|����hwS��!M��?P慪XW�����IEND�B`� +\ No newline at end of file +diff --git a/plugins/service-support/service-support-mini/src/blacklist.cpp b/plugins/service-support/service-support-mini/src/blacklist.cpp +new file mode 100644 +index 0000000..b1c66b7 +--- /dev/null ++++ b/plugins/service-support/service-support-mini/src/blacklist.cpp +@@ -0,0 +1,157 @@ ++#include "blacklist.h" ++#include <QStandardPaths> ++#include <QFile> ++#include <QJsonDocument> ++#include <QJsonObject> ++#include <QDateTime> ++#include <QDebug> ++ ++void Blacklist::Add(QString exec_name) { ++ QByteArray marshall_data; ++ ++ QFile file(Path()); ++ if (file.exists()) { ++ do { ++ if (!file.open(QIODevice::ReadOnly)) { ++ qCritical() << "Add blacklist open(read) file fail"; ++ break; ++ } ++ auto unmarshall_data = file.readAll(); ++ file.close(); ++ ++ QJsonParseError error; ++ auto doc = QJsonDocument::fromJson(unmarshall_data, &error); ++ if (doc.isNull()) { ++ qCritical() << "Parse blacklist fail: " << error.errorString(); ++ break; ++ } ++ if (!doc.isObject()) { ++ qCritical() << "Blacklist format error"; ++ break; ++ } ++ ++ auto object = doc.object(); ++ object[exec_name] = CurrentDataTime(); ++ ++ QJsonDocument marshall_doc(object); ++ marshall_data = marshall_doc.toJson(); ++ } while (0); ++ } ++ ++ if (marshall_data.isEmpty()) { ++ // 文件不存在或者文件内容错误的情况 ++ QJsonObject object; ++ object.insert(exec_name, CurrentDataTime()); ++ ++ QJsonDocument marshall_doc(object); ++ marshall_data = marshall_doc.toJson(); ++ } ++ ++ if (!file.open(QIODevice::WriteOnly)) { ++ qCritical() << "Add blacklist open(write) file fail"; ++ return; ++ } ++ ++ auto size = file.write(marshall_data); ++ if (size != marshall_data.size()) { ++ qCritical() << "Add blacklist write file fail"; ++ } ++ file.close(); ++} ++ ++void Blacklist::Remove(QString exec_name) { ++ QFile file(Path()); ++ if (!file.exists()) { ++ return; ++ } ++ ++ if (!file.open(QIODevice::ReadOnly)) { ++ qCritical() << "Remove blacklist open file fail"; ++ return; ++ } ++ auto unmarshall_data = file.readAll(); ++ file.close(); ++ ++ QJsonParseError error; ++ auto doc = QJsonDocument::fromJson(unmarshall_data, &error); ++ if (doc.isEmpty()) { ++ qCritical() << "Remove blacklist parse fail: " << error.errorString(); ++ return; ++ } ++ if (!doc.isObject()) { ++ qCritical() << "Remove blacklist format error"; ++ return; ++ } ++ ++ auto object = doc.object(); ++ auto iter = object.find(exec_name); ++ if (iter == object.end()) { ++ return; ++ } ++ object.erase(iter); ++ ++ QJsonDocument marshall_doc(object); ++ auto marshall_data = marshall_doc.toJson(); ++ ++ if (!file.open(QIODevice::WriteOnly)) { ++ qCritical() << "Remove blacklist open(write) file fail"; ++ return; ++ } ++ ++ auto size = file.write(marshall_data); ++ if (size != marshall_data.size()) { ++ qCritical() << "Remove blacklist write file fail"; ++ } ++ file.close(); ++} ++ ++bool Blacklist::Contain(QString exec_name) { ++ QFile file(Path()); ++ if (!file.exists()) { ++ return false; ++ } ++ ++ if (!file.open(QIODevice::ReadOnly)) { ++ qCritical() << "Contain blacklist open file fail"; ++ return false; ++ } ++ auto unmarshall_data = file.readAll(); ++ file.close(); ++ ++ QJsonParseError error; ++ auto doc = QJsonDocument::fromJson(unmarshall_data); ++ if (doc.isNull()) { ++ qCritical() << "Contain blacklist parse fail: " << error.errorString(); ++ return false; ++ } ++ if (!doc.isObject()) { ++ qCritical() << "Contain blacklist format error"; ++ return false; ++ } ++ ++ auto object = doc.object(); ++ auto iter = object.find(exec_name); ++ if (iter == object.end()) { ++ return false; ++ } ++ ++ // 判断是否超过 7 天 ++ auto date = iter.value().toString(); ++ auto record_date = QDateTime::fromString(date, "yyyy-MM-dd HH:mm:ss"); ++ auto current_date = QDateTime::currentDateTime(); ++ if (record_date.secsTo(current_date) > 7 * 24 * 60 * 60) { ++ // 超过 7 天 ++ return false; ++ } ++ ++ return true; ++} ++ ++QString Blacklist::Path() { ++ return QString("%1/.kylin-os-manager/global_feedback_blacklist.json") ++ .arg(QStandardPaths::writableLocation(QStandardPaths::StandardLocation::HomeLocation)); ++} ++ ++QString Blacklist::CurrentDataTime() { ++ return QDateTime::currentDateTime().toString("yyyy-MM-dd HH:mm:ss"); ++} +diff --git a/plugins/service-support/service-support-mini/src/blacklist.h b/plugins/service-support/service-support-mini/src/blacklist.h +new file mode 100644 +index 0000000..3567273 +--- /dev/null ++++ b/plugins/service-support/service-support-mini/src/blacklist.h +@@ -0,0 +1,17 @@ ++#ifndef KYLIN_OS_MANAGER_PLUGINS_SERVICE_SUPPORT_SERVICE_SUPPORT_MINI_BLACKLIST_H ++#define KYLIN_OS_MANAGER_PLUGINS_SERVICE_SUPPORT_SERVICE_SUPPORT_MINI_BLACKLIST_H ++ ++#include <QString> ++ ++class Blacklist { ++public: ++ static void Add(QString exec_name); ++ static void Remove(QString exec_name); ++ static bool Contain(QString exec_name); ++ ++private: ++ static QString Path(); ++ static QString CurrentDataTime(); ++}; ++ ++#endif +diff --git a/plugins/service-support/service-support-mini/src/feedbackcommon.cpp b/plugins/service-support/service-support-mini/src/feedbackcommon.cpp +new file mode 100644 +index 0000000..0276bb2 +--- /dev/null ++++ b/plugins/service-support/service-support-mini/src/feedbackcommon.cpp +@@ -0,0 +1,170 @@ ++#include "feedbackcommon.h" ++#include <pwd.h> ++#include <unistd.h> ++#include <glib.h> ++#include <QDebug> ++#include <QStandardPaths> ++#include <QFile> ++#include <QFileInfo> ++#include "kom-configure.h" ++#include "src/settings.h" ++ ++FeedBackCommon::FeedBackCommon() ++ : annex_size_max_limit_(10 * 1024 * 1024), // 10M ++ m_internalMode(InternalMode::OpenKylin) ++{ ++ exec_desktop_map_ = { ++ {"kybackup", "yhkylin-backup-tools"}, ++ {"kylin-log-viewer", "logview"} ++ }; ++} ++ ++void FeedBackCommon::setArgs(QString path, QString exe, QString restart, QString mode, QString code) ++{ ++ m_path = path; ++ m_exe = exe; ++ m_resart = restart; ++ m_mode = mode; ++ m_code = code; ++ m_datetime = QString::number(QDateTime::currentDateTime().toSecsSinceEpoch()); ++} ++ ++void FeedBackCommon::startCollecting(bool agree, QString text, QString phoneNumber, int score) { ++ kom::Configure conf; ++ // 配置采集内容 ++ InformationClassItemList classList = FeedbackManager::getInstance()->getLogFileItems(); ++ for (InformationClassItem *item : classList) { ++ if (agree) { ++ item->setSelect(true); ++ } else { ++ item->setSelect(false); ++ } ++ } ++ ++ // 设置提交内容 ++ InformationUserStruct info; ++ // 模式 ++ info.module = m_internalMode; ++ // 手机号 ++ if (phoneNumber.isEmpty()) { ++ phoneNumber = conf.value(CONFIG_PLUGIN_PROBLEM_FEEDBACK, CONFIG_PLUGIN_PROBLEM_FEEDBACK_CONTACT).toString(); ++ } else { ++ conf.setValue(CONFIG_PLUGIN_PROBLEM_FEEDBACK, CONFIG_PLUGIN_PROBLEM_FEEDBACK_CONTACT, phoneNumber); ++ } ++ if (phoneNumber.isEmpty()) { ++ phoneNumber = "11111111111"; ++ } ++ info.phoneNumber = phoneNumber; ++ ++ // 称谓 ++ info.name = conf.value(CONFIG_PLUGIN_PROBLEM_FEEDBACK, CONFIG_PLUGIN_PROBLEM_FEEDBACK_NAME_ADDRESS).toString(); ++ if (info.name.isEmpty()) { ++ info.name = "匿名"; ++ } ++ ++ // 因工单系统显示的是内容而不是标题,所以往内容的头部插入一行文本来充当标题 ++ QString content_header; ++ QString title = "【管家反馈】"; ++ if (m_mode == "1") { ++ // 主动反馈 ++ info.priviteType = "3-0"; ++ title += "应用软件"; ++ title += "|" + m_exe + "|" + QString::number(score) + "星"; ++ if (!text.isEmpty()) { ++ title += "|" + text.split("\n").first().mid(0, 20); ++ } ++ content_header = QString("【主动反馈】【应用软件】【%1】").arg(m_exe); ++ } else if (m_mode == "2") { ++ // 被动反馈 ++ info.priviteType = "1-3"; ++ title += "系统崩溃|" + m_exe; ++ content_header = QString("【被动反馈】【系统崩溃】【%1】").arg(m_exe); ++ } else if (m_mode == "3") { ++ // 管家故障诊断调用 ++ info.priviteType = "1-2"; ++ title += "故障修复|"+m_exe; ++ if (!m_code.isEmpty()) { ++ title+="|"+ m_code; ++ } ++ content_header = QString("【故障诊断】【故障修复】【%1】【%2】").arg(m_exe, m_code); ++ } ++ info.title = title; ++ if (text.isEmpty()) { ++ text = "未填写任何内容"; ++ } ++ info.details = QString("%1\n%2").arg(content_header, text); ++ ++ FeedbackManager::getInstance()->setUserData(info); ++ FeedbackManager::getInstance()->setSavePath("/tmp"); ++ ++ //开始提交 ++ FeedbackManager::getInstance()->startCollecting(); ++} ++ ++QString FeedBackCommon::getAppLogFile() { ++ QString getLogFile = m_exe; ++ if (getLogFile.contains("/")) { ++ getLogFile = getLogFile.split("/").last(); ++ } ++ getLogFile = QStandardPaths::writableLocation(QStandardPaths::HomeLocation) + "/.log/" + getLogFile + ".log"; ++ ++ // 判断日志文件是否超出了最大限制 ++ QFileInfo file_info(getLogFile); ++ if (!file_info.exists() || ++ file_info.size() > annex_size_max_limit_) ++ { ++ qWarning() << "Component log does not exist or exceeds size"; ++ return ""; ++ } ++ ++ qInfo() << "Add component log: " << getLogFile; ++ ++ return getLogFile; ++} ++ ++QString FeedBackCommon::GetDesktopPath() const { ++ QString desktop; ++ const auto iter = exec_desktop_map_.find(m_exe); ++ if (iter != exec_desktop_map_.end()) { ++ desktop = QString("/usr/share/applications/%1.desktop").arg(iter.value()); ++ } else { ++ desktop = QString("/usr/share/applications/%1.desktop").arg(m_exe); ++ } ++ return desktop; ++} ++ ++QString FeedBackCommon::ExecName() const { ++ const auto desktop_path = GetDesktopPath().toStdString(); ++ ++ g_autoptr(GKeyFile) key_file = g_key_file_new(); ++ g_autoptr(GError) error = NULL; ++ if (!g_key_file_load_from_file(key_file, desktop_path.c_str(), G_KEY_FILE_KEEP_TRANSLATIONS, &error)) { ++ qCritical() << "Get exec name fail: load key file fail, " << error->message; ++ return m_exe; ++ } ++ ++ g_autofree gchar *name = g_key_file_get_locale_string(key_file, "Desktop Entry", "Name", NULL, &error); ++ if (name != NULL) { ++ return QString(name); ++ } ++ ++ return m_exe; ++} ++ ++QString FeedBackCommon::ExecIcon() const { ++ const auto desktop_path = GetDesktopPath().toStdString(); ++ ++ g_autoptr(GKeyFile) key_file = g_key_file_new(); ++ g_autoptr(GError) error = NULL; ++ if (!g_key_file_load_from_file(key_file, desktop_path.c_str(), G_KEY_FILE_NONE, &error)) { ++ qCritical() << "Get exec icon fail: load key file fail, " << error->message; ++ return ""; ++ } ++ ++ g_autofree gchar *icon = g_key_file_get_string(key_file, "Desktop Entry", "Icon", &error); ++ if (icon != NULL) { ++ return QString(icon); ++ } ++ ++ return ""; ++} +diff --git a/plugins/service-support/service-support-mini/src/feedbackcommon.h b/plugins/service-support/service-support-mini/src/feedbackcommon.h +new file mode 100644 +index 0000000..3a8a804 +--- /dev/null ++++ b/plugins/service-support/service-support-mini/src/feedbackcommon.h +@@ -0,0 +1,36 @@ ++#ifndef FEEDBACK_COMMOM_H ++#define FEEDBACK_COMMOM_H ++ ++#include <QString> ++#include "feedbackmanager.h" ++ ++class FeedBackCommon { ++public: ++ FeedBackCommon(); ++ void setArgs(QString path , QString exe , QString restart, QString mode, QString code); ++ QString ExecName() const; ++ QString ExecIcon() const; ++ virtual void run() = 0; ++ ++protected: ++ void startCollecting(bool agree = false, QString text = "", QString phoneNumber = "", int score = 0); ++ QString getAppLogFile(); ++ QString GetDesktopPath() const; ++ ++ QString m_path; ++ QString m_exe; ++ QString m_resart; ++ QString m_mode; ++ QString m_code; ++ QString m_datetime; ++ bool m_isInit = false; ++ InternalMode m_internalMode; ++ /** ++ * @brief 部分 desktop 的名字与二进制的名字不一致,此处对这部分二进制做一下映射。 ++ * @note <二进制名, desktop 名> ++ */ ++ QHash<QString, QString> exec_desktop_map_; ++ quint64 annex_size_max_limit_; // 附件最大大小限制 ++}; ++ ++#endif +diff --git a/plugins/service-support/service-support-mini/src/passivitywidget.cpp b/plugins/service-support/service-support-mini/src/passivitywidget.cpp +new file mode 100644 +index 0000000..0d9bdec +--- /dev/null ++++ b/plugins/service-support/service-support-mini/src/passivitywidget.cpp +@@ -0,0 +1,230 @@ ++#include "passivitywidget.h" ++#include <glib.h> ++#include <QIcon> ++#include <QLabel> ++#include <QBoxLayout> ++#include <QDebug> ++#include <QFile> ++#include <QTimer> ++#include <QApplication> ++#include <QTextEdit> ++#include <QScreen> ++#include <QScrollArea> ++#include <kwindowinfo.h> ++#include <kwindowsystem.h> ++#include <gsettingmonitor.h> ++#include "kom-label.h" ++#include "kom_buriedpoint.h" ++#include "blacklist.h" ++ ++#define CALL_400 "400-089-1870" ++#define MAIL_400 "support@kylinos.cn" ++ ++PassivityWidget::PassivityWidget(QWidget *parent) ++ : kdk::KWidget(parent) ++{ ++ exec_desktop_map_ = { ++ {"kybackup", "yhkylin-backup-tools"}, ++ {"kylin-log-viewer", "logview"} ++ }; ++} ++ ++void PassivityWidget::run() { ++ if (m_isInit) { ++ return; ++ } ++ m_isInit = true; ++ ++ if (m_mode == "2") { ++ /* ++ * 带界面应用崩溃后的业务逻辑: ++ * 1. 先进行上报 ++ * 2. 上报结束后,弹出界面(不论上报成功还是失败) ++ */ ++ connect(FeedbackManager::getInstance(),&FeedbackManager::creatFinish,this,&PassivityWidget::creatFinish, Qt::ConnectionType::UniqueConnection); ++ } else if (m_mode == "3") { ++ connect(FeedbackManager::getInstance(),&FeedbackManager::creatFinish,this,&PassivityWidget::creatFinishNoUI, Qt::ConnectionType::UniqueConnection); ++ } ++ ++ // 上报 ++ startCollecting(true); ++} ++ ++void PassivityWidget::creatFinish(FeedBackFinishType type, QString str) { ++ switch (type) { ++ case Success: ++ qInfo() << "Received a crash from " << m_exe << ", problem reported successfully"; ++ break; ++ case Oversize: ++ qCritical() << "Received a crash from " << m_exe << ", problem reporting failed because the annex is too large"; ++ break; ++ case UploadFail: ++ qCritical() << "Received a crash from " << m_exe << ", problem reporting failed"; ++ break; ++ default: ++ qCritical() << "Received a crash from " << m_exe << ", don't know the ending type"; ++ break; ++ } ++ ++ // 如果 restart 参数为空,上报完成后则不弹出界面,直接退出 ++ if (m_resart.isEmpty()) { ++ qWarning() << "Received a crash from " << m_exe << ", the interface does not display without a restart command"; ++ // 不会立刻退出,需进入事件循环后才会退出,所以仍需要 return 关键字 ++ qApp->quit(); ++ return; ++ } ++ ++ // 上报完成,显示界面 ++ initUI(); ++} ++ ++void PassivityWidget::creatFinishNoUI(FeedBackFinishType type, QString str) ++{ ++ switch (type) { ++ case Success: { ++ QMap<QString, QString> custom_property = { ++ {"applicationName", m_exe}, ++ {"errorCode", m_code}, ++ {"submitTime", QDateTime::currentDateTime().toString("yyyy-MM-dd HH:mm:ss")}, ++ {"taskNumber", str} ++ }; ++ kom::BuriedPoint::uploadMessage(kom::BuriedPoint::BuriedPointPage::kServiceSupportMini, ++ kom::BuriedPoint::EventCode::kFaultDiagnosisReport, ++ custom_property); ++ ++ qDebug() << "提交成功"; ++ exit(0); ++ break; ++ } ++ case Oversize: ++ qDebug() << "压缩包总大小超过限制"; ++ exit(-2); ++ break; ++ case UploadFail: ++ qDebug() << "提交失败"; ++ exit(-3); ++ break; ++ default: ++ break; ++ } ++} ++ ++void PassivityWidget::initUI() { ++ setFixedSize(452, 257); ++ setAttribute(Qt::WA_AlwaysShowToolTips); ++ setWindowIcon(QIcon::fromTheme("kylin-os-manager")); ++ setWindowTitle(tr("Kylin Os Manager")); ++ setIcon(QIcon(":/res/dialog-warning.png")); ++ setWidgetName(tr("Unexpected exit reminder")); ++ ++ windowButtonBar()->menuButton()->hide(); ++ windowButtonBar()->minimumButton()->hide(); ++ windowButtonBar()->maximumButton()->hide(); ++ ++ // 隐藏任务栏图标 ++ const KWindowInfo window_info(winId(), NET::WMState); ++ if (!window_info.hasState(NET::SkipTaskbar) || !window_info.hasState(NET::SkipPager)) { ++ KWindowSystem::setState(winId(), NET::SkipTaskbar | NET::SkipPager); ++ } ++ ++ // 标题 ++ auto *title_label = new kom::KomLabel(this); ++ title_label->setBold(true); ++ title_label->setText(tr("\"%1\" unexpected exit").arg(ExecName())); ++ ++ // 描述 ++ auto *text_edit = new QTextEdit(this); ++ text_edit->setReadOnly(true); ++ text_edit->setFrameShape(QFrame::Shape::NoFrame); ++ text_edit->setText(tr("Click \"Reopen\" to reopen the application, and this report will be automatically sent to kylin operations personnel.")); ++ // 在驱动阶段调整 QTextEdit 的高度与文本高度一致,只有在界面完全显示结束进入事件循环后,才能获取到正确的 QTextDocument 的大小 ++ auto adjust_text_edit_heigth = [this, text_edit]() { ++ QTimer::singleShot(0, this, [text_edit]() { ++ auto height = text_edit->document()->size().toSize().height(); ++ text_edit->setFixedHeight(height); ++ }); ++ }; ++ QTimer::singleShot(0, this, adjust_text_edit_heigth); ++ connect(kdk::GsettingMonitor::getInstance(), &kdk::GsettingMonitor::systemFontSizeChange, this, adjust_text_edit_heigth); ++ ++ // 7 天内该程序崩溃不再弹出此窗口 ++ auto *prohibit_popup_check_box = new QCheckBox(this); ++ prohibit_popup_check_box->setChecked(true); ++ auto *prohibit_popup_label = new kom::KomLabel(this); ++ prohibit_popup_label->setText(tr("%1 unexpectedly exited within 7 days and no longer pops up").arg(ExecName())); ++ auto *prohibit_popup_hbox_layout = new QHBoxLayout; ++ prohibit_popup_hbox_layout->setContentsMargins(0, 0, 0, 0); ++ prohibit_popup_hbox_layout->setSpacing(0); ++ prohibit_popup_hbox_layout->addWidget(prohibit_popup_check_box); ++ prohibit_popup_hbox_layout->addWidget(prohibit_popup_label); ++ prohibit_popup_hbox_layout->addStretch(); ++ connect(prohibit_popup_check_box, &QCheckBox::toggled, this, &PassivityWidget::on_UpdateBlacklist); ++ ++ // 默认 7 天内不再弹出 ++ on_UpdateBlacklist(true); ++ ++ // 按钮 ++ auto *cancel_btn = new QPushButton(this); ++ cancel_btn->setText(tr("Cancel")); ++ connect(cancel_btn, &QPushButton::clicked, this, []{ ++ qApp->quit(); ++ }); ++ ++ auto *reopen_btn = new QPushButton(this); ++ reopen_btn->setText(tr("Reopen")); ++ reopen_btn->setProperty("isImportant", true); ++ connect(reopen_btn, &QPushButton::clicked, this, [this]() { ++ QProcess::startDetached(m_resart); ++ qApp->quit(); ++ }); ++ ++ auto *btn_hbox_layout = new QHBoxLayout; ++ btn_hbox_layout->setContentsMargins(0, 0, 0, 0); ++ btn_hbox_layout->setSpacing(0); ++ btn_hbox_layout->addStretch(); ++ btn_hbox_layout->addWidget(cancel_btn); ++ btn_hbox_layout->addSpacing(8); ++ btn_hbox_layout->addWidget(reopen_btn); ++ ++ // 整体布局 ++ auto *vbox_layout = new QVBoxLayout; ++ vbox_layout->setContentsMargins(24, 16, 24, 24); ++ vbox_layout->setSpacing(0); ++ vbox_layout->addWidget(title_label); ++ vbox_layout->addWidget(text_edit); ++ vbox_layout->addSpacing(8); ++ vbox_layout->addLayout(prohibit_popup_hbox_layout); ++ vbox_layout->addStretch(); ++ vbox_layout->addLayout(btn_hbox_layout); ++ ++ // 将布局放入滚动区域 ++ auto *scroll_widget = new QWidget(this); ++ scroll_widget->setFixedWidth(width()); ++ scroll_widget->setLayout(vbox_layout); ++ auto *scroll_area = new QScrollArea(this); ++ scroll_area->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); ++ scroll_area->setFrameShape(QScrollArea::NoFrame); ++ scroll_area->setWidget(scroll_widget); ++ ++ auto *hbox_layout = new QHBoxLayout; ++ hbox_layout->setContentsMargins(0, 0, 0, 0); ++ hbox_layout->setSpacing(0); ++ hbox_layout->addWidget(scroll_area); ++ baseBar()->setLayout(hbox_layout); ++ ++ scroll_area->setWidgetResizable(true); ++ ++ const auto primary_screen = QGuiApplication::screenAt(QCursor::pos())->geometry(); ++ const auto x = primary_screen.width() / 2 - width() / 2; ++ const auto y = primary_screen.height() / 2 - height() / 2; ++ move(x, y); ++ show(); ++} ++ ++void PassivityWidget::on_UpdateBlacklist(bool ok) { ++ if (ok) { ++ Blacklist::Add(m_exe); ++ } else { ++ Blacklist::Remove(m_exe); ++ } ++} +diff --git a/plugins/service-support/service-support-mini/src/passivitywidget.h b/plugins/service-support/service-support-mini/src/passivitywidget.h +new file mode 100644 +index 0000000..e4173d8 +--- /dev/null ++++ b/plugins/service-support/service-support-mini/src/passivitywidget.h +@@ -0,0 +1,28 @@ ++#ifndef PASSIVITY_WIDGET_H ++#define PASSIVITY_WIDGET_H ++ ++#include <QWidget> ++#include <QCheckBox> ++#include <QPushButton> ++#include <QProcess> ++#include <kwidget.h> ++#include <kballontip.h> ++#include <kdialog.h> ++#include "feedbackcommon.h" ++ ++class PassivityWidget: public kdk::KWidget, public FeedBackCommon { ++ Q_OBJECT ++public: ++ PassivityWidget(QWidget *parent = nullptr); ++ void run(); ++ ++private Q_SLOTS: ++ void creatFinish(FeedBackFinishType type, QString str); ++ void creatFinishNoUI(FeedBackFinishType type, QString str); ++ void on_UpdateBlacklist(bool ok); ++ ++private: ++ void initUI(); ++}; ++ ++#endif +diff --git a/plugins/service-support/service-support-mini/src/voluntarilywidget.cpp b/plugins/service-support/service-support-mini/src/voluntarilywidget.cpp +new file mode 100644 +index 0000000..1a3ccb7 +--- /dev/null ++++ b/plugins/service-support/service-support-mini/src/voluntarilywidget.cpp +@@ -0,0 +1,696 @@ ++#include "voluntarilywidget.h" ++#include <QBoxLayout> ++#include <QIcon> ++#include <QApplication> ++#include <QTimer> ++#include <QDebug> ++#include <QDir> ++#include <QClipboard> ++#include <QMimeData> ++#include <QDateTime> ++#include <QFileDialog> ++#include <QLineEdit> ++#include <QStandardPaths> ++#include <QSettings> ++#include <QGSettings> ++#include <QStyleOptionButton> ++#include <kwindowinfo.h> ++#include <kwindowsystem.h> ++#include <kpressbutton.h> ++#include <gsettingmonitor.h> ++#include "kom-label.h" ++#include "kom-configure.h" ++ ++#define DETAIL_HEIGHT 150 ++#define NOMAL_SPACING 16 ++#define SMALL_SPACING 8 ++#define WINDOW_WIDTH 452 ++#define WINDOW_HEIGHT 686 ++#define HIGH_SCALE_WIDTH 452 ++#define HIGH_SCALE_HEIGHT 600 ++#define WINDOW_HEIGHT_BIG 770 ++ ++#define UPLOAD_SUPPORT_SUFFIX "*.jpg *.png *.zip *.rar *.7z *.mp4 *.mkv" ++#define UPLOAD_SUPPORT_SUFFIX_PLUS " *.mkv *.flv" ++#define SCREEN_SHOT_GSETTING_PATH "org.ukui.screenshot" ++#define SCREEN_SHOT_TMP_PATH "/tmp/kylin-os-manager/service-support/" ++#define SCREEN_RECORD_EXE "/usr/bin/vokoscreen" ++ ++VoluntarilyWidget::VoluntarilyWidget(QWidget *parent) ++ :kdk::KWidget(parent) ++{ ++ ++} ++ ++void VoluntarilyWidget::run() ++{ ++ if (m_isInit) { ++ return; ++ } ++ m_isInit = true; ++ ++ initUI(); ++ ++ m_videoConfigPath = QStandardPaths::writableLocation(QStandardPaths::ConfigLocation) + "/vokoscreen/vokoscreen.conf"; ++ connect(&m_fileWatcher,&QFileSystemWatcher::fileChanged,this,&VoluntarilyWidget::videoFileChanged); ++ connect(&m_fileWatcher,&QFileSystemWatcher::directoryChanged,this,&VoluntarilyWidget::videoFileChanged); ++ m_fileWatcher.addPaths(QStringList()<<m_videoConfigPath<<getVideoSavePath()); ++ connect(FeedbackManager::getInstance(),&FeedbackManager::creatFinish,this,&VoluntarilyWidget::creatFinish); ++ ++ addLogFile(); ++} ++ ++void VoluntarilyWidget::onButtonClick() ++{ ++ m_submit->setEnabled(false); ++ m_submit->setText(tr("Submitting")); ++ if (m_submit->text() == tr("Retry")) { ++ //FeedbackManager::getInstance()->retryUpload(); ++ return; ++ } ++ QString phoneNumber; ++ if (m_phoneNumberErrMsg->text().isEmpty()) { ++ phoneNumber = m_phoneNumberEdit->text(); ++ } ++ startCollecting(m_agreeAll->isChecked(),m_detailsEdit->toPlainText(),phoneNumber,m_scoreWidget->getScore()); ++} ++ ++void VoluntarilyWidget::creatFinish(FeedBackFinishType type, QString str) ++{ ++ QString failed = tr("Submission failed"); ++ switch (type) { ++ case Success: ++ qDebug()<<"提交成功"; ++ showMessageBox(tr("Submitted successfully"), kdk::Normal); ++ m_submit->setText(tr("Submitted")); ++ break; ++ case Oversize: ++ qDebug()<<"压缩包总大小超过限制"; ++ errorMessage(failed); ++ m_submit->setEnabled(true); ++ m_submit->setText(tr("Retry")); ++ break; ++ case UploadFail: ++ qDebug()<<"提交失败"; ++ errorMessage(failed); ++ m_submit->setEnabled(true); ++ m_submit->setText(tr("Retry")); ++ break; ++ default: ++ break; ++ } ++} ++ ++ ++void VoluntarilyWidget::initUI() { ++ if (GetSystemScale() > 1.3) { ++ setFixedSize(HIGH_SCALE_WIDTH, HIGH_SCALE_HEIGHT); ++ } else { ++ setFixedSize(WINDOW_WIDTH,WINDOW_HEIGHT); ++ } ++ ++ setAttribute(Qt::WA_AlwaysShowToolTips); ++ setIcon(QIcon::fromTheme(ExecIcon())); ++ setWindowIcon(QIcon::fromTheme(ExecIcon())); ++ setWidgetName(ExecName()); ++ setWindowTitle(ExecName()); ++ windowButtonBar()->menuButton()->hide(); ++ windowButtonBar()->minimumButton()->hide(); ++ windowButtonBar()->maximumButton()->hide(); ++ ++ // 隐藏任务栏图标 ++ const KWindowInfo window_info(winId(), NET::WMState); ++ if (!window_info.hasState(NET::SkipTaskbar) || !window_info.hasState(NET::SkipPager)) { ++ KWindowSystem::setState(winId(), NET::SkipTaskbar | NET::SkipPager); ++ } ++ ++ // 标题 ++ kom::KomLabel *label1 = new kom::KomLabel(this); ++ label1->setFontSize(16); ++ label1->setBold(true); ++ label1->setText(tr("FeedBack")); ++ ++ // 问题描述 ++ QLabel *label2 = new QLabel(this); ++ label2->setText(tr("Problem description")); ++ ++ m_cardBase = new kdk::KPressButton(this); ++ m_cardBase->setCheckable(false); ++ m_cardBase->setBorderRadius(6); ++ m_cardBase->setFixedHeight(DETAIL_HEIGHT); ++ ++ QString dateEditText = tr("Please describe the problem in detail and you can upload a photo or file by clicking the button below."); ++ QString detailsEditNumberText = tr("Up to %1 characters").arg(500); ++ m_detailsEdit = new QTextEdit(this); ++ m_detailsEdit->setAcceptRichText(false); ++ m_detailsEdit->setFrameShape(QTextEdit::NoFrame); ++ m_detailsEdit->setPlaceholderText(dateEditText); ++ auto details_edit_palette = m_detailsEdit->palette(); ++ details_edit_palette.setColor(QPalette::ColorRole::Base, m_cardBase->palette().color(QPalette::Button)); ++ m_detailsEdit->setPalette(details_edit_palette); ++ ++ m_detailsEditNumber = new QLabel(m_detailsEdit); ++ m_detailsEditNumber->hide(); ++ m_detailsEditNumber->setAlignment(Qt::AlignRight | Qt::AlignBottom); ++ m_detailsEditNumber->setText(detailsEditNumberText); ++ QString detailsEditNumberTextFirst = tr("Remaining"); ++ QString detailsEditNumberTextLast = tr("character"); ++ connect(m_detailsEdit, &QTextEdit::textChanged, this, [=] { ++ int maxTextNum = 500; ++ QString text = m_detailsEdit->toPlainText(); ++ m_detailsEditNumber->setText(detailsEditNumberTextFirst + " " + QString::number(maxTextNum - text.length()) ++ + " " + detailsEditNumberTextLast); ++ QPalette palet = qApp->palette(); ++ if (text.length() >= maxTextNum) { ++ palet.setColor(QPalette::Foreground, QColor(Qt::red)); ++ m_detailsEditNumber->setPalette(palet); ++ } else { ++ palet.setColor(QPalette::Foreground, QColor(Qt::darkGray)); ++ m_detailsEditNumber->setPalette(palet); ++ } ++ if (text.length() > maxTextNum) { ++ if (m_tmpDetailsEditText.length() < maxTextNum) { ++ m_tmpDetailsEditText = text.mid(0, maxTextNum); ++ } ++ m_detailsEdit->setText(m_tmpDetailsEditText); ++ QTextCursor cursor = m_detailsEdit->textCursor(); ++ cursor.setPosition(maxTextNum); ++ m_detailsEdit->setTextCursor(cursor); ++ return; ++ } ++ m_tmpDetailsEditText = text; ++ }); ++ ++ QVBoxLayout *vlEdit = new QVBoxLayout; ++ vlEdit->setContentsMargins(6, 6, 6, 32); ++ vlEdit->addWidget(m_detailsEdit); ++ m_cardBase->setLayout(vlEdit); ++ ++ // 上传附件 ++ QLabel *label3 = new QLabel(this); ++ label3->setText(tr("Files")); ++ ++ // 截图 ++ m_screenCut = new QPushButton(this); ++ m_screenCut->setText(tr("ScreenShot")); ++ connect(m_screenCut, &QPushButton::clicked, this, &VoluntarilyWidget::onScreenCutClicked); ++ if (QGSettings::isSchemaInstalled(SCREEN_SHOT_GSETTING_PATH)) { ++ m_screenShotSetting = new QGSettings(SCREEN_SHOT_GSETTING_PATH); ++ connect(m_screenShotSetting, &QGSettings::changed, this, [=]() { ++ if (m_startShot && (m_screenShotSetting->get("isrunning").toString() == "false")) { ++ m_startShot = false; ++ getShotImage(); ++ } ++ }); ++ } ++ ++ // 录屏 ++ m_video = new QPushButton(this); ++ m_video->setText(tr("Screen recording")); ++ if (!QFile(SCREEN_RECORD_EXE).exists()) { ++ m_video->hide(); ++ } ++ connect(m_video, &QPushButton::clicked, this, &VoluntarilyWidget::onscreenRecordClicked); ++ ++ // 添加文件 ++ m_addFile = new QPushButton(this); ++ m_addFile->setText(tr("Add file")); ++ connect(m_addFile, &QPushButton::clicked, this, &VoluntarilyWidget::onAddFileClicked); ++ ++ QHBoxLayout *filesButtonHL = new QHBoxLayout; ++ filesButtonHL->setSpacing(SMALL_SPACING); ++ filesButtonHL->addWidget(m_screenCut); ++ filesButtonHL->addWidget(m_video); ++ filesButtonHL->addWidget(m_addFile); ++ filesButtonHL->addStretch(); ++ ++ // 说明文案 ++ kom::KomLabel *uploadText1 = new kom::KomLabel(this); ++ uploadText1->setFixedWidth(380); ++ uploadText1->setFontSize(12); ++ uploadText1->setTransparency(0.35); ++ uploadText1->setText(tr("No more than 5 files and total capacity not exceed %1MB").arg(m_addFileMax)); ++ kom::KomLabel *uploadText2 = new kom::KomLabel(this); ++ uploadText2->setFixedWidth(380); ++ uploadText2->setFontSize(12); ++ uploadText2->setTransparency(0.35); ++ uploadText2->setText(tr("Supported formats: ") + QString(UPLOAD_SUPPORT_SUFFIX)); ++ ++ // 添加文件列表 ++ m_fileListWidget = new QListWidget(this); ++ m_fileListWidget->setFixedHeight(74); ++ m_fileListWidget->setFlow(QListWidget::LeftToRight); ++ m_fileListWidget->setFrameShape(QListWidget::NoFrame); ++ m_fileListWidget->hide(); ++ ++ // 评分 ++ QLabel *label4 = new QLabel(this); ++ label4->setText(tr("My score")); ++ m_scoreWidget= new kom::ScoreWidget(this); ++ m_scoreWidget->setStarPix(QImage(":/res/star-l.png"),QImage(":/res/star-d.png")); ++ ++ // 联系方式 ++ QLabel *label5 = new QLabel(this); ++ label5->setText(tr("Contact")); ++ m_phoneNumberEdit = new QLineEdit(this); ++ m_phoneNumberEdit->setPlaceholderText(tr("Please enter your phone number")); ++ kom::Configure conf; ++ m_phoneNumberEdit->setText(conf.value(CONFIG_PLUGIN_PROBLEM_FEEDBACK, CONFIG_PLUGIN_PROBLEM_FEEDBACK_CONTACT).toString()); ++ ++ // 手机号错误提示 ++ m_phoneNumberErrMsg = new QLabel(this); ++ QPalette errMsgPalet = m_phoneNumberErrMsg->palette(); ++ errMsgPalet.setColor(QPalette::Text, Qt::red); ++ m_phoneNumberErrMsg->setPalette(errMsgPalet); ++ connect(m_phoneNumberEdit, &QLineEdit::textChanged, this, [=] { ++ QRegExp exp("^1[0-9]{10}$"); ++ if (m_phoneNumberEdit->text().isEmpty()) { ++ m_phoneNumberErrMsg->setText(""); ++ return; ++ } ++ if (!exp.exactMatch(m_phoneNumberEdit->text())) { ++ m_phoneNumberErrMsg->setText(tr("The phone number format is incorrect")); ++ return; ++ } ++ m_phoneNumberErrMsg->setText(""); ++ }); ++ ++ // 同意获取系统信息 ++ m_agreeAll = new QCheckBox(tr("Agree to take mine "), this); ++ m_agreeAll->setChecked(true); ++ system_information_label_ = new QLabel(tr("System information"), this); ++ QPalette pal = system_information_label_->palette(); ++ pal.setColor(QPalette::Text, qApp->palette().color(QPalette::Highlight)); ++ system_information_label_->setPalette(pal); ++ ++ QString tooltip; ++ auto categories = FeedbackManager::getInstance()->getLogFileItems(); ++ for (const auto c: categories) { ++ const auto name = c->getItemNameShow(); ++ tooltip.push_back(name); ++ tooltip.push_back("、"); ++ } ++ // 移除最后一个多余的 "、"符号 ++ if (!tooltip.isEmpty()) { ++ tooltip.chop(1); ++ } ++ system_information_label_->setToolTip(tooltip); ++ ++ QHBoxLayout *hlSubmit = new QHBoxLayout; ++ hlSubmit->setMargin(0); ++ hlSubmit->setSpacing(0); ++ hlSubmit->addWidget(m_agreeAll); ++ hlSubmit->addWidget(system_information_label_); ++ hlSubmit->addStretch(); ++ ++ // 提交 ++ QPushButton *cancelBtn = new QPushButton(this); ++ cancelBtn->setText(tr("Cancel")); ++ connect(cancelBtn,&QPushButton::clicked,this,[=]{ ++ FeedbackManager::getInstance()->cancel(); ++ exit(0); ++ }); ++ m_submit = new QPushButton(this); ++ m_submit->setText(tr("Submit")); ++ m_submit->setProperty("isImportant", true); ++ connect(m_submit, &QPushButton::clicked, this, &VoluntarilyWidget::onButtonClick); ++ ++ QHBoxLayout *hlSubmit2 = new QHBoxLayout; ++ hlSubmit2->setMargin(0); ++ hlSubmit2->setSpacing(SMALL_SPACING); ++ hlSubmit2->addStretch(); ++ hlSubmit2->addWidget(cancelBtn); ++ hlSubmit2->addWidget(m_submit); ++ ++ // 总布局 ++ QVBoxLayout *vbox_layout = new QVBoxLayout; ++ vbox_layout->setSpacing(0); ++ vbox_layout->setContentsMargins(24, 0, 24, 24); ++ vbox_layout->addSpacing(NOMAL_SPACING); ++ vbox_layout->addWidget(label1); ++ vbox_layout->addSpacing(NOMAL_SPACING); ++ vbox_layout->addWidget(label2); ++ vbox_layout->addSpacing(SMALL_SPACING); ++ vbox_layout->addWidget(m_cardBase); ++ vbox_layout->addSpacing(NOMAL_SPACING); ++ vbox_layout->addWidget(label3); ++ vbox_layout->addSpacing(SMALL_SPACING); ++ vbox_layout->addLayout(filesButtonHL); ++ vbox_layout->addSpacing(SMALL_SPACING); ++ vbox_layout->addWidget(uploadText1); ++ vbox_layout->addWidget(uploadText2); ++ vbox_layout->addSpacing(SMALL_SPACING); ++ vbox_layout->addWidget(m_fileListWidget); ++ vbox_layout->addSpacing(SMALL_SPACING); ++ vbox_layout->addWidget(label4); ++ vbox_layout->addSpacing(SMALL_SPACING); ++ vbox_layout->addWidget(m_scoreWidget); ++ vbox_layout->addSpacing(NOMAL_SPACING); ++ vbox_layout->addWidget(label5); ++ vbox_layout->addSpacing(SMALL_SPACING); ++ vbox_layout->addWidget(m_phoneNumberEdit); ++ vbox_layout->addWidget(m_phoneNumberErrMsg); ++ vbox_layout->addLayout(hlSubmit); ++ vbox_layout->addStretch(); ++ vbox_layout->addLayout(hlSubmit2); ++ ++ // 将总布局放入滚动区域中 ++ QWidget *widget = new QWidget(this); ++ widget->setLayout(vbox_layout); ++ m_baseScroll = new QScrollArea(this); ++ m_baseScroll->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); ++ m_baseScroll->setFrameShape(QScrollArea::NoFrame); ++ m_baseScroll->setWidget(widget); ++ ++ auto *hbox_layout = new QHBoxLayout; ++ hbox_layout->setContentsMargins(0, 0, 0, 0); ++ hbox_layout->setSpacing(0); ++ hbox_layout->addWidget(m_baseScroll); ++ baseBar()->setLayout(hbox_layout); ++ ++ m_baseScroll->setWidgetResizable(true); ++ ++ auto *theme_gsettings = new QGSettings("org.ukui.style", "", this); ++ connect(theme_gsettings, &QGSettings::changed, this, [this](QString key) { ++ QStyleOptionButton option; ++ if (key == "style-name" || key == "styleName") { ++ auto details_edit_palette = m_detailsEdit->palette(); ++ details_edit_palette.setColor(QPalette::Base, option.palette.color(QPalette::Button)); ++ m_detailsEdit->setPalette(details_edit_palette); ++ } ++ if (key == "theme-color" || key == "themeColor") { ++ // 高亮色改变 ++ auto palette = system_information_label_->palette(); ++ palette.setColor(QPalette::Text, option.palette.color(QPalette::Highlight)); ++ system_information_label_->setPalette(palette); ++ } ++ }); ++} ++ ++void VoluntarilyWidget::onScreenCutClicked() ++{ ++ // 开始截图前,如果剪切板中存在图片的话,则清空剪切板 ++ // 避免本次启动截图而点叉关掉并没有进行实际截图时,读取到之前缓存的图片数据 ++ QClipboard *clipboard = QApplication::clipboard(); ++ if (clipboard->mimeData()->hasImage()) { ++ clipboard->clear(); ++ } ++ QProcess::execute("/usr/bin/kylin-screenshot osmanager"); ++ m_startShot = true; ++} ++ ++void VoluntarilyWidget::getShotImage() { ++ const QMimeData *newData = QApplication::clipboard()->mimeData(); ++ if (!newData->hasImage()) { ++ qWarning() << "剪贴板中不存在图片数据"; ++ return; ++ } ++ ++ // 创建缓存目录 ++ const auto cache_dir = QString("/tmp/problem_feedback_%1").arg(QString(getenv("USER"))); ++ const QDir dir(cache_dir); ++ if (!dir.exists()) { ++ if (!dir.mkdir(cache_dir)) { ++ qCritical() << "Collect screenshot annex create cache directory fail."; ++ return; ++ } ++ } ++ ++ const auto screenshot = QString("%1/%2.jpg").arg(cache_dir, QDateTime::currentDateTime().toString("yyyy-MM-dd_hh-mm-ss")); ++ const QImage img = qvariant_cast<QImage>(newData->imageData()); ++ if (m_lastMimeImage == img) { ++ qWarning() << "重复截图,跳过"; ++ return; ++ } ++ if (!img.save(screenshot)) { ++ qCritical() << "保存截图失败" << img << screenshot; ++ return; ++ } ++ m_lastMimeImage = img; ++ addUploadFile(screenshot); ++} ++ ++void VoluntarilyWidget::addUploadFile(const QString &filename) ++{ ++ if (m_uploadFileNameList.contains(filename)) { ++ errorMessage(tr("Repeat addition")); ++ return; ++ } ++ if (filename.contains("&")) { ++ errorMessage(tr("The file name contains special characters")); ++ return; ++ } ++ ++ // 计算所有文件的总大小 ++ qint64 fileSize = 0; ++ QFileInfo info; ++ if (!m_uploadFileNameList.isEmpty()) { ++ for (QString &file : m_uploadFileNameList) { ++ info.setFile(file); ++ fileSize += info.size(); ++ } ++ } ++ info.setFile(filename); ++ fileSize += info.size(); ++ ++ if (fileSize > annex_size_max_limit_) { ++ qDebug() << "附件大小超出限制" << fileSize; ++ errorMessage(tr("Attachment size out of limit")); ++ return; ++ } ++ ++ m_uploadFileNameList.append(filename); ++ addUploadFileItem(filename); ++} ++ ++void VoluntarilyWidget::addUploadFileItem(const QString &filename) ++{ ++ UploadFileItem *itemWidget = new UploadFileItem(filename); ++ connect(itemWidget, &UploadFileItem::removeUploadFile, this, &VoluntarilyWidget::removeUploadFile); ++ m_fileListWidget->addItem(itemWidget->getWidgetItem()); ++ m_fileListWidget->setItemWidget(itemWidget->getWidgetItem(), itemWidget); ++ if (m_fileListWidget->isHidden()) { ++ m_fileListWidget->show(); ++ if (GetSystemScale() < 1.3) { ++ setFixedHeight(WINDOW_HEIGHT_BIG); ++ } ++ } ++ if (m_uploadFileNameList.length() > 4) { ++ m_screenCut->setEnabled(false); ++ m_addFile->setEnabled(false); ++ } ++} ++ ++void VoluntarilyWidget::onAddFileClicked() ++{ ++ QString suffix = QString(UPLOAD_SUPPORT_SUFFIX); ++// if (m_internalMode == InZentao) { ++// suffix += QString(UPLOAD_SUPPORT_SUFFIX_PLUS); ++// } ++ QString file = QFileDialog::getOpenFileName(this, tr("Add file"), ++ QStandardPaths::writableLocation(QStandardPaths::DesktopLocation), ++ "(" + suffix + ")"); ++ if (file.isEmpty()) { ++ return; ++ } ++ addUploadFile(file); ++} ++ ++void VoluntarilyWidget::onscreenRecordClicked() ++{ ++ if (m_screenRecord != nullptr) { ++ m_screenRecord->deleteLater(); ++ m_screenRecord = nullptr; ++ } ++ m_video->setEnabled(false); ++ m_screenRecord = new QProcess(this); ++ connect(m_screenRecord,SIGNAL(finished(int)),this,SLOT(onScreenRecordFinish(int))); ++ isWatcher = true; ++ m_historyVideoFileList = QDir(getVideoSavePath()).entryList(QDir::NoDotAndDotDot | QDir::Files , QDir::Time); ++ m_screenRecord->start(SCREEN_RECORD_EXE); ++} ++ ++void VoluntarilyWidget::onScreenRecordFinish(int exit) ++{ ++ isWatcher = false; ++ m_video->setEnabled(true); ++ qDebug()<< "录屏进程结束"<<exit; ++} ++ ++void VoluntarilyWidget::videoFileChanged(const QString &filename) ++{ ++ if (filename == m_videoConfigPath) { ++ m_fileWatcher.addPaths(QStringList()<<m_videoConfigPath<<getVideoSavePath()); ++ return; ++ } ++ if (!isWatcher) { ++ return; ++ } ++ QStringList nowVideoList = QDir(getVideoSavePath()).entryList(QDir::NoDotAndDotDot | QDir::Files , QDir::Time); ++ QString newFile = nowVideoList.first(); ++ if (!m_historyVideoFileList.contains(newFile)) { ++ if (newFile.startsWith("vokoscreen")) { ++ qDebug()<<"自动添加录屏文件"<<newFile; ++ addUploadFile(newFile); ++ } ++ } ++ m_historyVideoFileList = nowVideoList; ++} ++ ++QString VoluntarilyWidget::getVideoSavePath() ++{ ++ QSettings setting(m_videoConfigPath , QSettings::IniFormat); ++ setting.beginGroup("Miscellaneous"); ++ QString filePath = setting.value("VideoPath").toString(); ++ setting.endGroup(); ++ if (filePath.isEmpty()) { ++ filePath = QStandardPaths::writableLocation(QStandardPaths::MoviesLocation); ++ } ++ return filePath; ++} ++ ++void VoluntarilyWidget::showMessageBox(const QString &msg, kdk::TipType type) { ++ auto *ballonTip = new kdk::KBallonTip; ++ ballonTip->setWindowFlag(Qt::FramelessWindowHint); ++ ballonTip->setAttribute(Qt::WA_TranslucentBackground); ++ ballonTip->setAttribute(Qt::WA_DeleteOnClose); ++ ballonTip->setText(msg); ++ ballonTip->setTipType(type); ++ ballonTip->showInfo(); ++ ++ // 移动到界面中间 ++ const auto p = pos(); ++ const auto x = p.x() + width() / 2 - ballonTip->width() / 2; ++ const auto y = p.y() + height() / 2 - ballonTip->height() / 2; ++ ballonTip->move(x, y); ++} ++ ++void VoluntarilyWidget::errorMessage(const QString &msg) ++{ ++ showMessageBox(msg, kdk::Error); ++} ++ ++void VoluntarilyWidget::removeUploadFile(const QString &fileName) ++{ ++ m_uploadFileNameList.removeAll(fileName); ++ m_fileListWidget->clear(); ++ if (m_uploadFileNameList.isEmpty()) { ++ m_fileListWidget->hide(); ++ if (GetSystemScale() < 1.3) { ++ setFixedHeight(WINDOW_HEIGHT); ++ } ++ } ++ ++ for (const QString &file : m_uploadFileNameList) { ++ addUploadFileItem(file); ++ } ++ if (!(m_uploadFileNameList.length() > 4)) { ++ m_screenCut->setEnabled(true); ++ m_addFile->setEnabled(true); ++ } ++} ++ ++void VoluntarilyWidget::addLogFile() ++{ ++ QString logFile = getAppLogFile(); ++ if (!logFile.isEmpty()) { ++ addUploadFile(logFile); ++ } ++} ++ ++double VoluntarilyWidget::GetSystemScale() { ++ if (QGSettings::isSchemaInstalled("org.ukui.SettingsDaemon.plugins.xsettings")) { ++ const QGSettings gsettings("org.ukui.SettingsDaemon.plugins.xsettings"); ++ const auto keys = gsettings.keys(); ++ if (keys.contains("scaling-factor") || keys.contains("scalingFactor")) { ++ return gsettings.get("scalingFactor").toDouble(); ++ } ++ } ++ return 0; ++} ++ ++UploadFileItem::UploadFileItem(const QString &filename) : m_filename(filename) ++{ ++ getType(); ++ setFixedSize(74, 74); ++ m_widgetItem = new QListWidgetItem; ++ m_widgetItem->setFlags(Qt::NoItemFlags); ++ m_widgetItem->setToolTip(m_filename); ++ m_widgetItem->setSizeHint(size()); ++ m_item = new QLabel(this); ++ m_item->setFixedSize(64, 64); ++ m_item->move(0, height() - m_item->height()); ++ m_closeBtn = new QPushButton(this); ++ m_closeBtn->hide(); ++ m_closeBtn->setFixedSize(16, 16); ++ m_closeBtn->setIcon(QIcon(":/res/file-item-close.png")); ++ m_closeBtn->move(width() - m_closeBtn->width(), 0); ++ connect(m_closeBtn, &QPushButton::clicked, this, [=] { ++ emit removeUploadFile(m_filename); ++ }); ++ if (m_fileType == Image) { ++ QPixmap pix(m_filename); ++ if (pix.isNull()) { ++ pix.load(":/res/damaged_img.png"); ++ } ++ m_item->setPixmap(pix.scaled(m_item->width(), m_item->height())); ++ return; ++ } ++ m_icon = new QLabel(m_item); ++ m_icon->setFixedSize(32, 32); ++ if (m_fileType == Video) { ++ m_icon->setPixmap(QIcon::fromTheme("video").pixmap(m_icon->size())); ++ } else if (m_fileType == Package) { ++ m_icon->setPixmap(QIcon::fromTheme("application-archive").pixmap(m_icon->size())); ++ } else { ++ m_icon->setPixmap(QIcon::fromTheme("application-octet-stream").pixmap(m_icon->size())); ++ } ++ ++ m_icon->move(m_item->width() / 2 - m_icon->width() / 2, 0); ++ m_name = new QLabel(m_item); ++ connect(kdk::GsettingMonitor::getInstance(), &kdk::GsettingMonitor::systemFontSizeChange, this, ++ &UploadFileItem::textUpdate); ++ m_name->move(0, m_item->height() - m_name->height()); ++ m_name->setFixedWidth(m_item->width()); ++ textUpdate(); ++} ++ ++void UploadFileItem::textUpdate() ++{ ++ QString showText = QFileInfo(m_filename).fileName(); ++ QString tmp = showText; ++ QFont ft = m_name->font(); ++ ft.setPointSizeF(kdk::GsettingMonitor::getSystemFontSize().toDouble()); ++ while (QFontMetrics(ft).width(showText) > m_name->width()) { ++ tmp.chop(1); ++ showText = tmp + "..."; ++ } ++ m_name->setText(showText); ++} ++ ++QListWidgetItem *UploadFileItem::getWidgetItem() ++{ ++ return m_widgetItem; ++} ++ ++bool UploadFileItem::event(QEvent *event) ++{ ++ if (event->type() == QEvent::Enter) { ++ m_closeBtn->show(); ++ } else if (event->type() == QEvent::Leave) { ++ m_closeBtn->hide(); ++ } ++ return QWidget::event(event); ++} ++ ++void UploadFileItem::getType() ++{ ++ QString suffix = QFileInfo(m_filename).suffix().toLower(); ++ if (suffix == "jpg" || suffix == "png") { ++ m_fileType = Image; ++ } else if (suffix == "mp4") { ++ m_fileType = Video; ++ } else if (suffix == "zip" || suffix == "7z" || suffix == "tar.gz") { ++ m_fileType = Package; ++ } ++} +diff --git a/plugins/service-support/service-support-mini/src/voluntarilywidget.h b/plugins/service-support/service-support-mini/src/voluntarilywidget.h +new file mode 100644 +index 0000000..f14f206 +--- /dev/null ++++ b/plugins/service-support/service-support-mini/src/voluntarilywidget.h +@@ -0,0 +1,100 @@ ++#ifndef VOLUNTARILY_WIDGET_H ++#define VOLUNTARILY_WIDGET_H ++ ++#include <QWidget> ++#include <QTextEdit> ++#include <QLabel> ++#include <QPushButton> ++#include <QGSettings> ++#include <QListWidget> ++#include <QCheckBox> ++#include <QProcess> ++#include <QScrollArea> ++#include <QFileSystemWatcher> ++#include <kballontip.h> ++#include <kwidget.h> ++#include <kpressbutton.h> ++#include "feedbackcommon.h" ++#include "kom-scorewidget.h" ++ ++class UploadFileItem : public QWidget ++{ ++ Q_OBJECT ++signals: ++ void removeUploadFile(const QString &); ++ ++public: ++ UploadFileItem(const QString &filename); ++ QListWidgetItem *getWidgetItem(); ++ ++protected: ++ bool event(QEvent *event); ++ ++private: ++ void getType(); ++ void textUpdate(); ++ enum FileType { Unknow = 0, Image, Video, Package } m_fileType = Unknow; ++ QString m_filename; ++ QLabel *m_item = nullptr; ++ QPushButton *m_closeBtn = nullptr; ++ QLabel *m_icon = nullptr; ++ QLabel *m_name = nullptr; ++ QListWidgetItem *m_widgetItem = nullptr; ++}; ++ ++class VoluntarilyWidget: public kdk::KWidget, public FeedBackCommon { ++ Q_OBJECT ++public: ++ VoluntarilyWidget( QWidget *parent = nullptr); ++ void run(); ++ ++private slots: ++ void onScreenRecordFinish(int exit); ++ void creatFinish(FeedBackFinishType type, QString str); ++ ++private: ++ void initUI(); ++ void onButtonClick(); ++ void errorMessage(const QString &msg); ++ void onScreenCutClicked(); ++ void getShotImage(); ++ void addUploadFile(const QString &filename); ++ void addUploadFileItem(const QString &filename); ++ void onAddFileClicked(); ++ void onscreenRecordClicked(); ++ void videoFileChanged(const QString &filename); ++ QString getVideoSavePath(); ++ void showMessageBox(const QString &msg, kdk::TipType type); ++ void removeUploadFile(const QString &fileName); ++ void addLogFile(); ++ static double GetSystemScale(); ++ ++ kdk::KPressButton *m_cardBase; ++ QTextEdit *m_detailsEdit = nullptr; ++ QLabel *m_detailsEditNumber = nullptr; ++ QString m_tmpDetailsEditText; ++ QGSettings *m_screenShotSetting = nullptr; ++ QFileSystemWatcher m_fileWatcher; ++ QStringList m_historyVideoFileList; ++ bool isWatcher = false; ++ bool m_startShot = false; ++ QImage m_lastMimeImage; ++ int m_addFileMax = 10; ++ QString m_videoConfigPath; ++ QProcess *m_screenRecord = nullptr; ++ QPushButton *m_screenCut = nullptr; ++ QPushButton *m_video = nullptr; ++ QPushButton *m_addFile = nullptr; ++ QPushButton *m_submit = nullptr; ++ QListWidget *m_fileListWidget = nullptr; ++ QStringList m_uploadFileNameList; ++ QLineEdit *m_phoneNumberEdit = nullptr; ++ QLabel *m_phoneNumberErrMsg = nullptr; ++ QCheckBox *m_agreeAll = nullptr; ++ QLabel *system_information_label_; ++ kom::ScoreWidget *m_scoreWidget = nullptr; ++ QScrollArea *m_baseScroll = nullptr; ++ ++}; ++ ++#endif // VOLUNTARILY_WIDGET_H +diff --git a/plugins/service-support/service-support-mini/translations/kom-service-support-mini_bo_CN.ts b/plugins/service-support/service-support-mini/translations/kom-service-support-mini_bo_CN.ts +new file mode 100644 +index 0000000..c92d85e +--- /dev/null ++++ b/plugins/service-support/service-support-mini/translations/kom-service-support-mini_bo_CN.ts +@@ -0,0 +1,188 @@ ++<?xml version="1.0" encoding="utf-8"?> ++<!DOCTYPE TS> ++<TS version="2.1" language="bo_CN"> ++<context> ++ <name>PassivityWidget</name> ++ <message> ++ <location filename="../src/passivitywidget.cpp" line="116"/> ++ <source>Kylin Os Manager</source> ++ <translation>གཉེར་པ་</translation> ++ </message> ++ <message> ++ <location filename="../src/passivitywidget.cpp" line="118"/> ++ <source>Unexpected exit reminder</source> ++ <translation>བསམ་ཡུལ་ལས་འདས་པ་ཞིག་ལ་དྲན་སྐུལ་བཏང་།</translation> ++ </message> ++ <message> ++ <location filename="../src/passivitywidget.cpp" line="133"/> ++ <source>"%1" unexpected exit</source> ++ <translation>"%1"བསམ་ཡུལ་ལས་འདས་པ་ནས་ཕྱིར་འཐེན་བྱས་པ་རེད།</translation> ++ </message> ++ <message> ++ <location filename="../src/passivitywidget.cpp" line="139"/> ++ <source>Click "Reopen" to reopen the application, and this report will be automatically sent to kylin operations personnel.</source> ++ <translation>"ཡང་བསྐྱར་ཁ་ཕྱེ་ནས་ཡང་བསྐྱར་བཀོལ་སྤྱོད་བྱས་པ་དང་སྙན་ཞུ་དེ་རང་འགུལ་གྱིས་Kylinལ་སྐྱེལ་འདྲེན་བྱེད་མཁན་ལ་སྐྱེལ་དགོས།.</translation> ++ </message> ++ <message> ++ <location filename="../src/passivitywidget.cpp" line="154"/> ++ <source>%1 unexpectedly exited within 7 days and no longer pops up</source> ++ <translation>%1ཉིན་7གྱི་ནང་དུ་བསམ་ཡུལ་ལས་འདས་པ་ཞིག་ནས་ཕྱིར་འཐེན་མི་བྱེད་པ་རེད།</translation> ++ </message> ++ <message> ++ <location filename="../src/passivitywidget.cpp" line="174"/> ++ <source>Reopen</source> ++ <translation>སླར་ཡང་ཁ་ཕྱེ་བ་རེད།</translation> ++ </message> ++ <message> ++ <location filename="../src/passivitywidget.cpp" line="168"/> ++ <source>Cancel</source> ++ <translation>མེད་པར་བཟོ་དགོས།</translation> ++ </message> ++</context> ++<context> ++ <name>VoluntarilyWidget</name> ++ <message> ++ <location filename="../src/voluntarilywidget.cpp" line="66"/> ++ <source>Submitting</source> ++ <translation>འབུལ་སྤྲོད་བྱེད་རིང་།</translation> ++ </message> ++ <message> ++ <location filename="../src/voluntarilywidget.cpp" line="67"/> ++ <location filename="../src/voluntarilywidget.cpp" line="91"/> ++ <location filename="../src/voluntarilywidget.cpp" line="97"/> ++ <source>Retry</source> ++ <translation>བསྐྱར་དུ་ཚོད་ལྟ་བྱེད་པ</translation> ++ </message> ++ <message> ++ <location filename="../src/voluntarilywidget.cpp" line="80"/> ++ <source>Submission failed</source> ++ <translation>ཕམ་ཉེས་བྱུང་བར་འབུལ་དགོས།</translation> ++ </message> ++ <message> ++ <location filename="../src/voluntarilywidget.cpp" line="84"/> ++ <source>Submitted successfully</source> ++ <translation>ལེགས་འགྲུབ་ཡོང་བར་འབུལ་དགོས།</translation> ++ </message> ++ <message> ++ <location filename="../src/voluntarilywidget.cpp" line="85"/> ++ <source>Submitted</source> ++ <translation>ལེགས་འགྲུབ་བྱ་རྒྱུར་འབུལ་དགོས།</translation> ++ </message> ++ <message> ++ <location filename="../src/voluntarilywidget.cpp" line="131"/> ++ <source>FeedBack</source> ++ <translation>བསམ་འཆར་ལྡོག་འདྲེན་བྱེད་པ།</translation> ++ </message> ++ <message> ++ <location filename="../src/voluntarilywidget.cpp" line="135"/> ++ <source>Problem description</source> ++ <translation>གནད་དོན་ཞིབ་བརྗོད་</translation> ++ </message> ++ <message> ++ <location filename="../src/voluntarilywidget.cpp" line="142"/> ++ <source>Please describe the problem in detail and you can upload a photo or file by clicking the button below.</source> ++ <translation>ཁྱེད་རང་ལ་འཕྲད་པའི་གནད་དོན་ཞིབ་མོར་བཤད་རོགས། ཁྱེད་ཀྱིས་ཀྱང་མར་མནན་ནས་སྒྲོག་པའི་པར་རིས་སམ་ཡིག་ཆ་བཏོན་ནས་ང་ཚོས་མགྱོགས་མྱུར་ངང་གནད་དོན་ཐག་གཅོད་བྱེད་བདེ་པོ་ཡོང་བ་བྱས་ཆོག.</translation> ++ </message> ++ <message> ++ <location filename="../src/voluntarilywidget.cpp" line="143"/> ++ <source>Up to %1 characters</source> ++ <translation>ཆེས་མང་ན་ཡིག་རྟགས་%1ནང་འཇུག་བྱེད་པ་ཡིན།</translation> ++ </message> ++ <message> ++ <location filename="../src/voluntarilywidget.cpp" line="156"/> ++ <source>Remaining</source> ++ <translation>ལྷག་མ།</translation> ++ </message> ++ <message> ++ <location filename="../src/voluntarilywidget.cpp" line="157"/> ++ <source>character</source> ++ <translation>ཡི་གེ་གཅིག་གི་རྟགས།</translation> ++ </message> ++ <message> ++ <location filename="../src/voluntarilywidget.cpp" line="191"/> ++ <source>Files</source> ++ <translation>ཞར་བྱུང་ཡིག་ཆ་གོང་ལ་བརྒྱུད་བསྒྲགས</translation> ++ </message> ++ <message> ++ <location filename="../src/voluntarilywidget.cpp" line="195"/> ++ <source>ScreenShot</source> ++ <translation>དཔེ་རིས་བཅད་པ།</translation> ++ </message> ++ <message> ++ <location filename="../src/voluntarilywidget.cpp" line="209"/> ++ <source>Screen recording</source> ++ <translation>བརྙན་ཕབ།</translation> ++ </message> ++ <message> ++ <location filename="../src/voluntarilywidget.cpp" line="217"/> ++ <location filename="../src/voluntarilywidget.cpp" line="489"/> ++ <source>Add file</source> ++ <translation>ཡིག་ཆ་ཁ་སྣོན་རྒྱག་དགོས།</translation> ++ </message> ++ <message> ++ <location filename="../src/voluntarilywidget.cpp" line="232"/> ++ <source>No more than 5 files and total capacity not exceed %1MB</source> ++ <translation>ཟུར་བཀོད་ཡིག་ཆ་མང་ཤོས་ལ་ཡིག་ཆ་5མང་བ་ཡོད་པ་དང་། སྤྱིའི་ཆེ་ཆུང་ནི་བརྒྱ་ཆ་%1MBལས་བརྒལ་མི་ཆོག</translation> ++ </message> ++ <message> ++ <location filename="../src/voluntarilywidget.cpp" line="237"/> ++ <source>Supported formats: </source> ++ <translation>རྣམ་གཞག་ལ་རྒྱབ་སྐྱོར་བྱ་རྒྱུ་: </translation> ++ </message> ++ <message> ++ <location filename="../src/voluntarilywidget.cpp" line="248"/> ++ <source>My score</source> ++ <translation>ངའི་སྐར་གྲངས་</translation> ++ </message> ++ <message> ++ <location filename="../src/voluntarilywidget.cpp" line="254"/> ++ <source>Contact</source> ++ <translation>འབྲེལ་གཏུག་བྱེད་སྟངས།</translation> ++ </message> ++ <message> ++ <location filename="../src/voluntarilywidget.cpp" line="272"/> ++ <source>The phone number format is incorrect</source> ++ <translation>ལག་ཁྱེར་ཁ་པར་གྱི་ཨང་གྲངས་ནོར་བ།</translation> ++ </message> ++ <message> ++ <location filename="../src/voluntarilywidget.cpp" line="256"/> ++ <source>Please enter your phone number</source> ++ <translation>ཁྱེད་ཀྱི་ལག་ཁྱེར་ཁ་པར་ཨང་གྲངས་ནང་འཇུག་གནང་རོགས།</translation> ++ </message> ++ <message> ++ <location filename="../src/voluntarilywidget.cpp" line="279"/> ++ <source>Agree to take mine </source> ++ <translation>ང་རང་ཐོབ་པར་འཐད་པ་བྱུང་། </translation> ++ </message> ++ <message> ++ <location filename="../src/voluntarilywidget.cpp" line="281"/> ++ <source>System information</source> ++ <translation>མ་ལག་ཆ་འཕྲིན།</translation> ++ </message> ++ <message> ++ <location filename="../src/voluntarilywidget.cpp" line="307"/> ++ <source>Cancel</source> ++ <translation>མེད་པར་བཟོ་དགོས།</translation> ++ </message> ++ <message> ++ <location filename="../src/voluntarilywidget.cpp" line="313"/> ++ <source>Submit</source> ++ <translation>སྤྲོད་དགོས།</translation> ++ </message> ++ <message> ++ <location filename="../src/voluntarilywidget.cpp" line="435"/> ++ <source>Repeat addition</source> ++ <translation>ཟུར་བཀོད་ཡིག་རིགས་ཀྱི་མིང་བསྐྱར་ཟློས་བྱུང་བ།</translation> ++ </message> ++ <message> ++ <location filename="../src/voluntarilywidget.cpp" line="439"/> ++ <source>The file name contains special characters</source> ++ <translation>ཡིག་ཆའི་མིང་ལ་དམིགས་བསལ་གྱི་ཡི་གེ་འདུས་ཡོད།</translation> ++ </message> ++ <message> ++ <location filename="../src/voluntarilywidget.cpp" line="457"/> ++ <source>Attachment size out of limit</source> ++ <translation>ཟུར་བཀོད་ཡིག་ཆའི་ཆེ་ཆུང་ཚོད་འཛིན་ལས་བརྒལ་བ།</translation> ++ </message> ++</context> ++</TS> +diff --git a/plugins/service-support/service-support-mini/translations/kom-service-support-mini_kk.ts b/plugins/service-support/service-support-mini/translations/kom-service-support-mini_kk.ts +new file mode 100644 +index 0000000..02a6537 +--- /dev/null ++++ b/plugins/service-support/service-support-mini/translations/kom-service-support-mini_kk.ts +@@ -0,0 +1,188 @@ ++<?xml version="1.0" encoding="utf-8"?> ++<!DOCTYPE TS> ++<TS version="2.1" language="kk_KZ"> ++<context> ++ <name>PassivityWidget</name> ++ <message> ++ <location filename="../src/passivitywidget.cpp" line="116"/> ++ <source>Kylin Os Manager</source> ++ <translation type="unfinished"></translation> ++ </message> ++ <message> ++ <location filename="../src/passivitywidget.cpp" line="118"/> ++ <source>Unexpected exit reminder</source> ++ <translation type="unfinished"></translation> ++ </message> ++ <message> ++ <location filename="../src/passivitywidget.cpp" line="133"/> ++ <source>"%1" unexpected exit</source> ++ <translation type="unfinished"></translation> ++ </message> ++ <message> ++ <location filename="../src/passivitywidget.cpp" line="139"/> ++ <source>Click "Reopen" to reopen the application, and this report will be automatically sent to kylin operations personnel.</source> ++ <translation type="unfinished"></translation> ++ </message> ++ <message> ++ <location filename="../src/passivitywidget.cpp" line="154"/> ++ <source>%1 unexpectedly exited within 7 days and no longer pops up</source> ++ <translation type="unfinished"></translation> ++ </message> ++ <message> ++ <location filename="../src/passivitywidget.cpp" line="174"/> ++ <source>Reopen</source> ++ <translation type="unfinished"></translation> ++ </message> ++ <message> ++ <location filename="../src/passivitywidget.cpp" line="168"/> ++ <source>Cancel</source> ++ <translation type="unfinished"></translation> ++ </message> ++</context> ++<context> ++ <name>VoluntarilyWidget</name> ++ <message> ++ <location filename="../src/voluntarilywidget.cpp" line="66"/> ++ <source>Submitting</source> ++ <translation type="unfinished"></translation> ++ </message> ++ <message> ++ <location filename="../src/voluntarilywidget.cpp" line="67"/> ++ <location filename="../src/voluntarilywidget.cpp" line="91"/> ++ <location filename="../src/voluntarilywidget.cpp" line="97"/> ++ <source>Retry</source> ++ <translation type="unfinished"></translation> ++ </message> ++ <message> ++ <location filename="../src/voluntarilywidget.cpp" line="80"/> ++ <source>Submission failed</source> ++ <translation type="unfinished"></translation> ++ </message> ++ <message> ++ <location filename="../src/voluntarilywidget.cpp" line="84"/> ++ <source>Submitted successfully</source> ++ <translation type="unfinished"></translation> ++ </message> ++ <message> ++ <location filename="../src/voluntarilywidget.cpp" line="85"/> ++ <source>Submitted</source> ++ <translation type="unfinished"></translation> ++ </message> ++ <message> ++ <location filename="../src/voluntarilywidget.cpp" line="131"/> ++ <source>FeedBack</source> ++ <translation type="unfinished"></translation> ++ </message> ++ <message> ++ <location filename="../src/voluntarilywidget.cpp" line="135"/> ++ <source>Problem description</source> ++ <translation type="unfinished"></translation> ++ </message> ++ <message> ++ <location filename="../src/voluntarilywidget.cpp" line="142"/> ++ <source>Please describe the problem in detail and you can upload a photo or file by clicking the button below.</source> ++ <translation type="unfinished"></translation> ++ </message> ++ <message> ++ <location filename="../src/voluntarilywidget.cpp" line="143"/> ++ <source>Up to %1 characters</source> ++ <translation type="unfinished"></translation> ++ </message> ++ <message> ++ <location filename="../src/voluntarilywidget.cpp" line="156"/> ++ <source>Remaining</source> ++ <translation type="unfinished"></translation> ++ </message> ++ <message> ++ <location filename="../src/voluntarilywidget.cpp" line="157"/> ++ <source>character</source> ++ <translation type="unfinished"></translation> ++ </message> ++ <message> ++ <location filename="../src/voluntarilywidget.cpp" line="191"/> ++ <source>Files</source> ++ <translation type="unfinished"></translation> ++ </message> ++ <message> ++ <location filename="../src/voluntarilywidget.cpp" line="195"/> ++ <source>ScreenShot</source> ++ <translation type="unfinished"></translation> ++ </message> ++ <message> ++ <location filename="../src/voluntarilywidget.cpp" line="209"/> ++ <source>Screen recording</source> ++ <translation type="unfinished"></translation> ++ </message> ++ <message> ++ <location filename="../src/voluntarilywidget.cpp" line="217"/> ++ <location filename="../src/voluntarilywidget.cpp" line="489"/> ++ <source>Add file</source> ++ <translation type="unfinished"></translation> ++ </message> ++ <message> ++ <location filename="../src/voluntarilywidget.cpp" line="232"/> ++ <source>No more than 5 files and total capacity not exceed %1MB</source> ++ <translation type="unfinished"></translation> ++ </message> ++ <message> ++ <location filename="../src/voluntarilywidget.cpp" line="237"/> ++ <source>Supported formats: </source> ++ <translation type="unfinished"></translation> ++ </message> ++ <message> ++ <location filename="../src/voluntarilywidget.cpp" line="248"/> ++ <source>My score</source> ++ <translation type="unfinished"></translation> ++ </message> ++ <message> ++ <location filename="../src/voluntarilywidget.cpp" line="254"/> ++ <source>Contact</source> ++ <translation type="unfinished"></translation> ++ </message> ++ <message> ++ <location filename="../src/voluntarilywidget.cpp" line="272"/> ++ <source>The phone number format is incorrect</source> ++ <translation type="unfinished"></translation> ++ </message> ++ <message> ++ <location filename="../src/voluntarilywidget.cpp" line="256"/> ++ <source>Please enter your phone number</source> ++ <translation type="unfinished"></translation> ++ </message> ++ <message> ++ <location filename="../src/voluntarilywidget.cpp" line="279"/> ++ <source>Agree to take mine </source> ++ <translation type="unfinished"></translation> ++ </message> ++ <message> ++ <location filename="../src/voluntarilywidget.cpp" line="281"/> ++ <source>System information</source> ++ <translation type="unfinished"></translation> ++ </message> ++ <message> ++ <location filename="../src/voluntarilywidget.cpp" line="307"/> ++ <source>Cancel</source> ++ <translation type="unfinished"></translation> ++ </message> ++ <message> ++ <location filename="../src/voluntarilywidget.cpp" line="313"/> ++ <source>Submit</source> ++ <translation type="unfinished"></translation> ++ </message> ++ <message> ++ <location filename="../src/voluntarilywidget.cpp" line="435"/> ++ <source>Repeat addition</source> ++ <translation type="unfinished"></translation> ++ </message> ++ <message> ++ <location filename="../src/voluntarilywidget.cpp" line="439"/> ++ <source>The file name contains special characters</source> ++ <translation type="unfinished"></translation> ++ </message> ++ <message> ++ <location filename="../src/voluntarilywidget.cpp" line="457"/> ++ <source>Attachment size out of limit</source> ++ <translation type="unfinished"></translation> ++ </message> ++</context> ++</TS> +diff --git a/plugins/service-support/service-support-mini/translations/kom-service-support-mini_ky.ts b/plugins/service-support/service-support-mini/translations/kom-service-support-mini_ky.ts +new file mode 100644 +index 0000000..1e11e40 +--- /dev/null ++++ b/plugins/service-support/service-support-mini/translations/kom-service-support-mini_ky.ts +@@ -0,0 +1,188 @@ ++<?xml version="1.0" encoding="utf-8"?> ++<!DOCTYPE TS> ++<TS version="2.1" language="ky_KG"> ++<context> ++ <name>PassivityWidget</name> ++ <message> ++ <location filename="../src/passivitywidget.cpp" line="116"/> ++ <source>Kylin Os Manager</source> ++ <translation type="unfinished"></translation> ++ </message> ++ <message> ++ <location filename="../src/passivitywidget.cpp" line="118"/> ++ <source>Unexpected exit reminder</source> ++ <translation type="unfinished"></translation> ++ </message> ++ <message> ++ <location filename="../src/passivitywidget.cpp" line="133"/> ++ <source>"%1" unexpected exit</source> ++ <translation type="unfinished"></translation> ++ </message> ++ <message> ++ <location filename="../src/passivitywidget.cpp" line="139"/> ++ <source>Click "Reopen" to reopen the application, and this report will be automatically sent to kylin operations personnel.</source> ++ <translation type="unfinished"></translation> ++ </message> ++ <message> ++ <location filename="../src/passivitywidget.cpp" line="154"/> ++ <source>%1 unexpectedly exited within 7 days and no longer pops up</source> ++ <translation type="unfinished"></translation> ++ </message> ++ <message> ++ <location filename="../src/passivitywidget.cpp" line="174"/> ++ <source>Reopen</source> ++ <translation type="unfinished"></translation> ++ </message> ++ <message> ++ <location filename="../src/passivitywidget.cpp" line="168"/> ++ <source>Cancel</source> ++ <translation type="unfinished"></translation> ++ </message> ++</context> ++<context> ++ <name>VoluntarilyWidget</name> ++ <message> ++ <location filename="../src/voluntarilywidget.cpp" line="66"/> ++ <source>Submitting</source> ++ <translation type="unfinished"></translation> ++ </message> ++ <message> ++ <location filename="../src/voluntarilywidget.cpp" line="67"/> ++ <location filename="../src/voluntarilywidget.cpp" line="91"/> ++ <location filename="../src/voluntarilywidget.cpp" line="97"/> ++ <source>Retry</source> ++ <translation type="unfinished"></translation> ++ </message> ++ <message> ++ <location filename="../src/voluntarilywidget.cpp" line="80"/> ++ <source>Submission failed</source> ++ <translation type="unfinished"></translation> ++ </message> ++ <message> ++ <location filename="../src/voluntarilywidget.cpp" line="84"/> ++ <source>Submitted successfully</source> ++ <translation type="unfinished"></translation> ++ </message> ++ <message> ++ <location filename="../src/voluntarilywidget.cpp" line="85"/> ++ <source>Submitted</source> ++ <translation type="unfinished"></translation> ++ </message> ++ <message> ++ <location filename="../src/voluntarilywidget.cpp" line="131"/> ++ <source>FeedBack</source> ++ <translation type="unfinished"></translation> ++ </message> ++ <message> ++ <location filename="../src/voluntarilywidget.cpp" line="135"/> ++ <source>Problem description</source> ++ <translation type="unfinished"></translation> ++ </message> ++ <message> ++ <location filename="../src/voluntarilywidget.cpp" line="142"/> ++ <source>Please describe the problem in detail and you can upload a photo or file by clicking the button below.</source> ++ <translation type="unfinished"></translation> ++ </message> ++ <message> ++ <location filename="../src/voluntarilywidget.cpp" line="143"/> ++ <source>Up to %1 characters</source> ++ <translation type="unfinished"></translation> ++ </message> ++ <message> ++ <location filename="../src/voluntarilywidget.cpp" line="156"/> ++ <source>Remaining</source> ++ <translation type="unfinished"></translation> ++ </message> ++ <message> ++ <location filename="../src/voluntarilywidget.cpp" line="157"/> ++ <source>character</source> ++ <translation type="unfinished"></translation> ++ </message> ++ <message> ++ <location filename="../src/voluntarilywidget.cpp" line="191"/> ++ <source>Files</source> ++ <translation type="unfinished"></translation> ++ </message> ++ <message> ++ <location filename="../src/voluntarilywidget.cpp" line="195"/> ++ <source>ScreenShot</source> ++ <translation type="unfinished"></translation> ++ </message> ++ <message> ++ <location filename="../src/voluntarilywidget.cpp" line="209"/> ++ <source>Screen recording</source> ++ <translation type="unfinished"></translation> ++ </message> ++ <message> ++ <location filename="../src/voluntarilywidget.cpp" line="217"/> ++ <location filename="../src/voluntarilywidget.cpp" line="489"/> ++ <source>Add file</source> ++ <translation type="unfinished"></translation> ++ </message> ++ <message> ++ <location filename="../src/voluntarilywidget.cpp" line="232"/> ++ <source>No more than 5 files and total capacity not exceed %1MB</source> ++ <translation type="unfinished"></translation> ++ </message> ++ <message> ++ <location filename="../src/voluntarilywidget.cpp" line="237"/> ++ <source>Supported formats: </source> ++ <translation type="unfinished"></translation> ++ </message> ++ <message> ++ <location filename="../src/voluntarilywidget.cpp" line="248"/> ++ <source>My score</source> ++ <translation type="unfinished"></translation> ++ </message> ++ <message> ++ <location filename="../src/voluntarilywidget.cpp" line="254"/> ++ <source>Contact</source> ++ <translation type="unfinished"></translation> ++ </message> ++ <message> ++ <location filename="../src/voluntarilywidget.cpp" line="272"/> ++ <source>The phone number format is incorrect</source> ++ <translation type="unfinished"></translation> ++ </message> ++ <message> ++ <location filename="../src/voluntarilywidget.cpp" line="256"/> ++ <source>Please enter your phone number</source> ++ <translation type="unfinished"></translation> ++ </message> ++ <message> ++ <location filename="../src/voluntarilywidget.cpp" line="279"/> ++ <source>Agree to take mine </source> ++ <translation type="unfinished"></translation> ++ </message> ++ <message> ++ <location filename="../src/voluntarilywidget.cpp" line="281"/> ++ <source>System information</source> ++ <translation type="unfinished"></translation> ++ </message> ++ <message> ++ <location filename="../src/voluntarilywidget.cpp" line="307"/> ++ <source>Cancel</source> ++ <translation type="unfinished"></translation> ++ </message> ++ <message> ++ <location filename="../src/voluntarilywidget.cpp" line="313"/> ++ <source>Submit</source> ++ <translation type="unfinished"></translation> ++ </message> ++ <message> ++ <location filename="../src/voluntarilywidget.cpp" line="435"/> ++ <source>Repeat addition</source> ++ <translation type="unfinished"></translation> ++ </message> ++ <message> ++ <location filename="../src/voluntarilywidget.cpp" line="439"/> ++ <source>The file name contains special characters</source> ++ <translation type="unfinished"></translation> ++ </message> ++ <message> ++ <location filename="../src/voluntarilywidget.cpp" line="457"/> ++ <source>Attachment size out of limit</source> ++ <translation type="unfinished"></translation> ++ </message> ++</context> ++</TS> +diff --git a/plugins/service-support/service-support-mini/translations/kom-service-support-mini_mn.ts b/plugins/service-support/service-support-mini/translations/kom-service-support-mini_mn.ts +new file mode 100644 +index 0000000..1098cf6 +--- /dev/null ++++ b/plugins/service-support/service-support-mini/translations/kom-service-support-mini_mn.ts +@@ -0,0 +1,188 @@ ++<?xml version="1.0" encoding="utf-8"?> ++<!DOCTYPE TS> ++<TS version="2.1" language="mn_MN"> ++<context> ++ <name>PassivityWidget</name> ++ <message> ++ <location filename="../src/passivitywidget.cpp" line="116"/> ++ <source>Kylin Os Manager</source> ++ <translation>ᠵᠢᠨ ᠯᠢᠨ ᠬᠠᠮᠢᠶᠠᠷᠤᠭᠴᠢ ᠃</translation> ++ </message> ++ <message> ++ <location filename="../src/passivitywidget.cpp" line="118"/> ++ <source>Unexpected exit reminder</source> ++ <translation>ᠰᠠᠨᠠᠭᠠᠨ ᠠᠴᠠ ᠭᠠᠳᠠᠭᠤᠷ ᠤᠬᠤᠷᠢᠵᠤ ᠰᠠᠨᠠᠭᠤᠯᠵᠠᠢ ᠃</translation> ++ </message> ++ <message> ++ <location filename="../src/passivitywidget.cpp" line="133"/> ++ <source>"%1" unexpected exit</source> ++ <translation>"%1" ᠰᠠᠨᠠᠭᠠᠨ ᠠᠴᠠ ᠭᠠᠳᠠᠭᠤᠷ ᠤᠬᠤᠷᠢᠵᠤ ᠭᠠᠷᠪᠠ᠃</translation> ++ </message> ++ <message> ++ <location filename="../src/passivitywidget.cpp" line="139"/> ++ <source>Click "Reopen" to reopen the application, and this report will be automatically sent to kylin operations personnel.</source> ++ <translation>ᠳᠠᠬᠢᠨ ᠨᠡᠭᠡᠭᠡᠵᠦ ᠳᠠᠬᠢᠨ ᠨᠡᠭᠡᠭᠡᠵᠦ ᠬᠡᠷᠡᠭᠯᠡᠵᠡᠢ ᠂ ᠡᠨᠡ ᠮᠡᠳᠡᠭᠦᠯᠦᠯᠲᠡ ᠶᠢ ᠺᠣᠯᠧᠨ ᠳᠦ ᠬᠦᠷᠭᠡᠨᠡ ᠃.</translation> ++ </message> ++ <message> ++ <location filename="../src/passivitywidget.cpp" line="154"/> ++ <source>%1 unexpectedly exited within 7 days and no longer pops up</source> ++ <translation>7 ᠡᠳᠦᠷ ᠦᠨ ᠳᠣᠲᠣᠷᠠ %1 ᠰᠠᠨᠠᠭᠠᠨ ᠠᠴᠠ ᠭᠠᠳᠠᠭᠤᠷ ᠤᠬᠤᠷᠢᠵᠤ ᠭᠠᠷᠬᠤ ᠪᠠᠨ ᠪᠣᠯᠢᠪᠠ ᠃</translation> ++ </message> ++ <message> ++ <location filename="../src/passivitywidget.cpp" line="174"/> ++ <source>Reopen</source> ++ <translation>ᠳᠠᠬᠢᠨ ᠨᠡᠭᠡᠭᠡᠨᠡ ᠃</translation> ++ </message> ++ <message> ++ <location filename="../src/passivitywidget.cpp" line="168"/> ++ <source>Cancel</source> ++ <translation>ᠬᠦᠴᠦᠨ ᠦᠭᠡᠶ ᠪᠣᠯᠭᠠᠨᠠ᠃</translation> ++ </message> ++</context> ++<context> ++ <name>VoluntarilyWidget</name> ++ <message> ++ <location filename="../src/voluntarilywidget.cpp" line="66"/> ++ <source>Submitting</source> ++ <translation>ᠲᠤᠰᠢᠶᠠᠬᠤ ᠶᠠᠪᠤᠴᠠ ᠳᠤ ᠃</translation> ++ </message> ++ <message> ++ <location filename="../src/voluntarilywidget.cpp" line="67"/> ++ <location filename="../src/voluntarilywidget.cpp" line="91"/> ++ <location filename="../src/voluntarilywidget.cpp" line="97"/> ++ <source>Retry</source> ++ <translation>ᠳᠠᠬᠢᠨ ᠰᠢᠯᠭᠠᠨᠠ ᠃</translation> ++ </message> ++ <message> ++ <location filename="../src/voluntarilywidget.cpp" line="80"/> ++ <source>Submission failed</source> ++ <translation>ᠢᠯᠠᠭᠳᠠᠯ ᠢᠶᠠᠨ ᠲᠤᠰᠢᠶᠠᠨᠠ ᠃</translation> ++ </message> ++ <message> ++ <location filename="../src/voluntarilywidget.cpp" line="84"/> ++ <source>Submitted successfully</source> ++ <translation>ᠠᠮᠵᠢᠯᠲᠠ ᠣᠯᠣᠭᠰᠠᠨ</translation> ++ </message> ++ <message> ++ <location filename="../src/voluntarilywidget.cpp" line="85"/> ++ <source>Submitted</source> ++ <translation>ᠲᠤᠰᠢᠶᠠᠵᠤ ᠳᠠᠭᠤᠰᠬᠠᠬᠤ ᠬᠡᠷᠡᠭᠲᠡᠶ᠃</translation> ++ </message> ++ <message> ++ <location filename="../src/voluntarilywidget.cpp" line="131"/> ++ <source>FeedBack</source> ++ <translation>ᠰᠠᠨᠠᠯ ᠬᠠᠷᠢᠭᠤ ᠲᠤᠰᠬᠠᠪᠠ ᠃</translation> ++ </message> ++ <message> ++ <location filename="../src/voluntarilywidget.cpp" line="135"/> ++ <source>Problem description</source> ++ <translation>ᠠᠰᠠᠭᠤᠳᠠᠯ ᠤᠨ ᠳᠦᠷᠰᠦᠯᠡᠯ</translation> ++ </message> ++ <message> ++ <location filename="../src/voluntarilywidget.cpp" line="142"/> ++ <source>Please describe the problem in detail and you can upload a photo or file by clicking the button below.</source> ++ <translation>ᠲᠠᠨ ᠤ ᠲᠤᠯᠭᠠᠷᠠᠭᠰᠠᠨ ᠠᠰᠠᠭᠤᠳᠠᠯ ᠢ ᠨᠠᠷᠢᠨ ᠲᠣᠳᠣᠷᠬᠠᠢ ᠲᠣᠭᠠᠴᠢᠭᠠᠷᠠᠢ ᠂ ᠲᠠ ᠪᠠᠰᠠ ᠳᠣᠣᠷᠠᠳᠤ ᠲᠠᠯᠠ ᠶᠢᠨ ᠳᠠᠷᠤᠭᠤᠯ ᠢ ᠳᠠᠷᠤᠵᠤ ᠵᠢᠷᠤᠭ ᠪᠤᠶᠤ ᠪᠢᠴᠢᠭ᠌ ᠮᠠᠲ᠋ᠧᠷᠢᠶᠠᠯ ᠢ ᠳᠠᠷᠤᠵᠤ ᠪᠢᠳᠡᠨ ᠦ ᠠᠰᠠᠭᠤᠳᠠᠯ ᠢ ᠲᠦᠷᠭᠡᠨ ᠰᠢᠢᠳᠪᠦᠷᠢᠯᠡᠬᠦ ᠳᠦ ᠳᠥᠭᠥᠮ ᠦᠵᠡᠭᠦᠯᠵᠦ ᠪᠣᠯᠣᠨᠠ ᠃.</translation> ++ </message> ++ <message> ++ <location filename="../src/voluntarilywidget.cpp" line="143"/> ++ <source>Up to %1 characters</source> ++ <translation>ᠬᠠᠮᠤᠭ ᠠᠷᠪᠢᠨ ᠳᠠᠭᠠᠨ %1 ᠦᠰᠦᠭ ᠦᠨ ᠲᠡᠮᠲᠡᠭ ᠢ ᠣᠷᠣᠭᠤᠯᠵᠤ ᠣᠷᠣᠭᠤᠯᠤᠨᠠ ᠃</translation> ++ </message> ++ <message> ++ <location filename="../src/voluntarilywidget.cpp" line="156"/> ++ <source>Remaining</source> ++ <translation>ᠦᠯᠡᠳᠡᠭᠰᠡᠨ᠃</translation> ++ </message> ++ <message> ++ <location filename="../src/voluntarilywidget.cpp" line="157"/> ++ <source>character</source> ++ <translation>ᠦᠰᠦᠭ ᠨᠢ ᠲᠡᠮᠲᠡᠭ ᠃</translation> ++ </message> ++ <message> ++ <location filename="../src/voluntarilywidget.cpp" line="191"/> ++ <source>Files</source> ++ <translation>ᠳᠠᠭᠠᠯᠳᠤᠭᠤᠯᠤᠯ ᠢ ᠳᠡᠭᠡᠭ᠍ᠰᠢ ᠳᠠᠮᠵᠢᠭᠤᠯᠬᠤ</translation> ++ </message> ++ <message> ++ <location filename="../src/voluntarilywidget.cpp" line="195"/> ++ <source>ScreenShot</source> ++ <translation>ᠵᠢᠷᠤᠭ ᠵᠢᠷᠤᠭ᠃</translation> ++ </message> ++ <message> ++ <location filename="../src/voluntarilywidget.cpp" line="209"/> ++ <source>Screen recording</source> ++ <translation>ᠳᠡᠯᠬᠡᠴᠡ᠃</translation> ++ </message> ++ <message> ++ <location filename="../src/voluntarilywidget.cpp" line="217"/> ++ <location filename="../src/voluntarilywidget.cpp" line="489"/> ++ <source>Add file</source> ++ <translation>ᠪᠢᠴᠢᠭ᠌ ᠮᠠᠲ᠋ᠧᠷᠢᠶᠠᠯ ᠨᠡᠮᠡᠬᠦ</translation> ++ </message> ++ <message> ++ <location filename="../src/voluntarilywidget.cpp" line="232"/> ++ <source>No more than 5 files and total capacity not exceed %1MB</source> ++ <translation>ᠳᠠᠭᠠᠯᠳᠤᠭᠤᠯᠤᠯ ᠬᠠᠮᠤᠭ ᠠᠷᠪᠢᠨ ᠳᠠᠭᠠᠨ 5 ᠪᠢᠴᠢᠭ ᠮᠠᠲ᠋ᠧᠷᠢᠶᠠᠯ ᠳᠠᠮᠵᠢᠭᠤᠯᠵᠤ᠂ ᠶᠡᠷᠦᠩᠬᠡᠶ ᠪᠠᠭᠠ ᠨᠢ %1 MB ᠡᠴᠡ ᠬᠡᠲᠦᠷᠡᠭᠦᠯᠵᠦ ᠪᠣᠯᠬᠤ ᠦᠭᠡᠶ᠃</translation> ++ </message> ++ <message> ++ <location filename="../src/voluntarilywidget.cpp" line="237"/> ++ <source>Supported formats: </source> ++ <translation>ᠬᠡᠪ ᠵᠠᠭᠪᠤᠷ ᠢ ᠳᠡᠮᠵᠢᠨᠡ : </translation> ++ </message> ++ <message> ++ <location filename="../src/voluntarilywidget.cpp" line="248"/> ++ <source>My score</source> ++ <translation>ᠮᠢᠨᠦ ᠬᠤᠪᠢ ᠃</translation> ++ </message> ++ <message> ++ <location filename="../src/voluntarilywidget.cpp" line="254"/> ++ <source>Contact</source> ++ <translation>ᠬᠠᠷᠢᠯᠴᠠᠬᠤ ᠠᠷᠭᠠ ᠮᠠᠶᠢᠭ ᠃</translation> ++ </message> ++ <message> ++ <location filename="../src/voluntarilywidget.cpp" line="272"/> ++ <source>The phone number format is incorrect</source> ++ <translation>ᠭᠠᠷ ᠤᠲᠠᠰᠤᠨ ᠤ ᠨᠣᠮᠧᠷ ᠤᠨ ᠬᠡᠯᠪᠡᠷᠢ ᠨᠢ ᠪᠤᠷᠤᠭᠤ ᠃</translation> ++ </message> ++ <message> ++ <location filename="../src/voluntarilywidget.cpp" line="256"/> ++ <source>Please enter your phone number</source> ++ <translation>ᠲᠠᠨ ᠤ ᠭᠠᠷ ᠤᠲᠠᠰᠤᠨ ᠤ ᠨᠣᠮᠧᠷ ᠢ ᠣᠷᠣᠭᠤᠯᠵᠤ ᠢᠷᠡᠭᠡᠷᠡᠢ ᠃</translation> ++ </message> ++ <message> ++ <location filename="../src/voluntarilywidget.cpp" line="279"/> ++ <source>Agree to take mine </source> ++ <translation>ᠮᠢᠨᠦ ᠬᠢ ᠶᠢ ᠣᠯᠬᠤ ᠶᠢ ᠵᠥᠪᠰᠢᠶᠡᠷᠡᠨᠡ ᠃ </translation> ++ </message> ++ <message> ++ <location filename="../src/voluntarilywidget.cpp" line="281"/> ++ <source>System information</source> ++ <translation>ᠰᠢᠰᠲ᠋ᠧᠮ ᠦᠨ ᠮᠡᠳᠡᠭᠡ ᠵᠠᠩᠭᠢ᠃</translation> ++ </message> ++ <message> ++ <location filename="../src/voluntarilywidget.cpp" line="307"/> ++ <source>Cancel</source> ++ <translation>ᠬᠦᠴᠦᠨ ᠦᠭᠡᠶ ᠪᠣᠯᠭᠠᠨᠠ᠃</translation> ++ </message> ++ <message> ++ <location filename="../src/voluntarilywidget.cpp" line="313"/> ++ <source>Submit</source> ++ <translation>ᠲᠤᠰᠢᠶᠠᠨᠠ ᠃</translation> ++ </message> ++ <message> ++ <location filename="../src/voluntarilywidget.cpp" line="435"/> ++ <source>Repeat addition</source> ++ <translation>ᠳᠠᠭᠠᠯᠳᠤᠭᠤᠯᠤᠯ ᠤᠨ ᠨᠡᠷᠡ ᠳᠠᠪᠬᠤᠷᠳᠠᠵᠠᠢ ᠃</translation> ++ </message> ++ <message> ++ <location filename="../src/voluntarilywidget.cpp" line="439"/> ++ <source>The file name contains special characters</source> ++ <translation>ᠪᠢᠴᠢᠭ᠌ ᠮᠠᠲ᠋ᠧᠷᠢᠶᠠᠯ ᠤᠨ ᠨᠡᠷᠡ ᠳᠦ ᠣᠨᠴᠠᠭᠠᠢ ᠦᠰᠦᠭ᠍ ᠦᠨ ᠲᠡᠮᠲᠡᠭ ᠪᠠᠭᠲᠠᠨᠠ ᠃</translation> ++ </message> ++ <message> ++ <location filename="../src/voluntarilywidget.cpp" line="457"/> ++ <source>Attachment size out of limit</source> ++ <translation>ᠳᠠᠭᠠᠯᠳᠤᠭᠤᠯᠤᠯ ᠤᠨ ᠶᠡᠬᠡ ᠪᠠᠭᠠ ᠨᠢ ᠬᠢᠵᠠᠭᠠᠷᠯᠠᠯ ᠠᠴᠠ ᠬᠡᠲᠦᠷᠡᠵᠡᠢ ᠃</translation> ++ </message> ++</context> ++</TS> +diff --git a/plugins/service-support/service-support-mini/translations/kom-service-support-mini_ug.ts b/plugins/service-support/service-support-mini/translations/kom-service-support-mini_ug.ts +new file mode 100644 +index 0000000..c701c54 +--- /dev/null ++++ b/plugins/service-support/service-support-mini/translations/kom-service-support-mini_ug.ts +@@ -0,0 +1,188 @@ ++<?xml version="1.0" encoding="utf-8"?> ++<!DOCTYPE TS> ++<TS version="2.1" language="ug_CN"> ++<context> ++ <name>PassivityWidget</name> ++ <message> ++ <location filename="../src/passivitywidget.cpp" line="116"/> ++ <source>Kylin Os Manager</source> ++ <translation type="unfinished"></translation> ++ </message> ++ <message> ++ <location filename="../src/passivitywidget.cpp" line="118"/> ++ <source>Unexpected exit reminder</source> ++ <translation type="unfinished"></translation> ++ </message> ++ <message> ++ <location filename="../src/passivitywidget.cpp" line="133"/> ++ <source>"%1" unexpected exit</source> ++ <translation type="unfinished"></translation> ++ </message> ++ <message> ++ <location filename="../src/passivitywidget.cpp" line="139"/> ++ <source>Click "Reopen" to reopen the application, and this report will be automatically sent to kylin operations personnel.</source> ++ <translation type="unfinished"></translation> ++ </message> ++ <message> ++ <location filename="../src/passivitywidget.cpp" line="154"/> ++ <source>%1 unexpectedly exited within 7 days and no longer pops up</source> ++ <translation type="unfinished"></translation> ++ </message> ++ <message> ++ <location filename="../src/passivitywidget.cpp" line="174"/> ++ <source>Reopen</source> ++ <translation type="unfinished"></translation> ++ </message> ++ <message> ++ <location filename="../src/passivitywidget.cpp" line="168"/> ++ <source>Cancel</source> ++ <translation type="unfinished"></translation> ++ </message> ++</context> ++<context> ++ <name>VoluntarilyWidget</name> ++ <message> ++ <location filename="../src/voluntarilywidget.cpp" line="66"/> ++ <source>Submitting</source> ++ <translation type="unfinished"></translation> ++ </message> ++ <message> ++ <location filename="../src/voluntarilywidget.cpp" line="67"/> ++ <location filename="../src/voluntarilywidget.cpp" line="91"/> ++ <location filename="../src/voluntarilywidget.cpp" line="97"/> ++ <source>Retry</source> ++ <translation type="unfinished"></translation> ++ </message> ++ <message> ++ <location filename="../src/voluntarilywidget.cpp" line="80"/> ++ <source>Submission failed</source> ++ <translation type="unfinished"></translation> ++ </message> ++ <message> ++ <location filename="../src/voluntarilywidget.cpp" line="84"/> ++ <source>Submitted successfully</source> ++ <translation type="unfinished"></translation> ++ </message> ++ <message> ++ <location filename="../src/voluntarilywidget.cpp" line="85"/> ++ <source>Submitted</source> ++ <translation type="unfinished"></translation> ++ </message> ++ <message> ++ <location filename="../src/voluntarilywidget.cpp" line="131"/> ++ <source>FeedBack</source> ++ <translation type="unfinished"></translation> ++ </message> ++ <message> ++ <location filename="../src/voluntarilywidget.cpp" line="135"/> ++ <source>Problem description</source> ++ <translation type="unfinished"></translation> ++ </message> ++ <message> ++ <location filename="../src/voluntarilywidget.cpp" line="142"/> ++ <source>Please describe the problem in detail and you can upload a photo or file by clicking the button below.</source> ++ <translation type="unfinished"></translation> ++ </message> ++ <message> ++ <location filename="../src/voluntarilywidget.cpp" line="143"/> ++ <source>Up to %1 characters</source> ++ <translation type="unfinished"></translation> ++ </message> ++ <message> ++ <location filename="../src/voluntarilywidget.cpp" line="156"/> ++ <source>Remaining</source> ++ <translation type="unfinished"></translation> ++ </message> ++ <message> ++ <location filename="../src/voluntarilywidget.cpp" line="157"/> ++ <source>character</source> ++ <translation type="unfinished"></translation> ++ </message> ++ <message> ++ <location filename="../src/voluntarilywidget.cpp" line="191"/> ++ <source>Files</source> ++ <translation type="unfinished"></translation> ++ </message> ++ <message> ++ <location filename="../src/voluntarilywidget.cpp" line="195"/> ++ <source>ScreenShot</source> ++ <translation type="unfinished"></translation> ++ </message> ++ <message> ++ <location filename="../src/voluntarilywidget.cpp" line="209"/> ++ <source>Screen recording</source> ++ <translation type="unfinished"></translation> ++ </message> ++ <message> ++ <location filename="../src/voluntarilywidget.cpp" line="217"/> ++ <location filename="../src/voluntarilywidget.cpp" line="489"/> ++ <source>Add file</source> ++ <translation type="unfinished"></translation> ++ </message> ++ <message> ++ <location filename="../src/voluntarilywidget.cpp" line="232"/> ++ <source>No more than 5 files and total capacity not exceed %1MB</source> ++ <translation type="unfinished"></translation> ++ </message> ++ <message> ++ <location filename="../src/voluntarilywidget.cpp" line="237"/> ++ <source>Supported formats: </source> ++ <translation type="unfinished"></translation> ++ </message> ++ <message> ++ <location filename="../src/voluntarilywidget.cpp" line="248"/> ++ <source>My score</source> ++ <translation type="unfinished"></translation> ++ </message> ++ <message> ++ <location filename="../src/voluntarilywidget.cpp" line="254"/> ++ <source>Contact</source> ++ <translation type="unfinished"></translation> ++ </message> ++ <message> ++ <location filename="../src/voluntarilywidget.cpp" line="272"/> ++ <source>The phone number format is incorrect</source> ++ <translation type="unfinished"></translation> ++ </message> ++ <message> ++ <location filename="../src/voluntarilywidget.cpp" line="256"/> ++ <source>Please enter your phone number</source> ++ <translation type="unfinished"></translation> ++ </message> ++ <message> ++ <location filename="../src/voluntarilywidget.cpp" line="279"/> ++ <source>Agree to take mine </source> ++ <translation type="unfinished"></translation> ++ </message> ++ <message> ++ <location filename="../src/voluntarilywidget.cpp" line="281"/> ++ <source>System information</source> ++ <translation type="unfinished"></translation> ++ </message> ++ <message> ++ <location filename="../src/voluntarilywidget.cpp" line="307"/> ++ <source>Cancel</source> ++ <translation type="unfinished"></translation> ++ </message> ++ <message> ++ <location filename="../src/voluntarilywidget.cpp" line="313"/> ++ <source>Submit</source> ++ <translation type="unfinished"></translation> ++ </message> ++ <message> ++ <location filename="../src/voluntarilywidget.cpp" line="435"/> ++ <source>Repeat addition</source> ++ <translation type="unfinished"></translation> ++ </message> ++ <message> ++ <location filename="../src/voluntarilywidget.cpp" line="439"/> ++ <source>The file name contains special characters</source> ++ <translation type="unfinished"></translation> ++ </message> ++ <message> ++ <location filename="../src/voluntarilywidget.cpp" line="457"/> ++ <source>Attachment size out of limit</source> ++ <translation type="unfinished"></translation> ++ </message> ++</context> ++</TS> +diff --git a/plugins/service-support/service-support-mini/translations/kom-service-support-mini_zh_CN.ts b/plugins/service-support/service-support-mini/translations/kom-service-support-mini_zh_CN.ts +new file mode 100644 +index 0000000..51f6242 +--- /dev/null ++++ b/plugins/service-support/service-support-mini/translations/kom-service-support-mini_zh_CN.ts +@@ -0,0 +1,188 @@ ++<?xml version="1.0" encoding="utf-8"?> ++<!DOCTYPE TS> ++<TS version="2.1" language="zh_CN"> ++<context> ++ <name>PassivityWidget</name> ++ <message> ++ <location filename="../src/passivitywidget.cpp" line="116"/> ++ <source>Kylin Os Manager</source> ++ <translation>麒麟管家</translation> ++ </message> ++ <message> ++ <location filename="../src/passivitywidget.cpp" line="118"/> ++ <source>Unexpected exit reminder</source> ++ <translation>意外退出提醒</translation> ++ </message> ++ <message> ++ <location filename="../src/passivitywidget.cpp" line="133"/> ++ <source>"%1" unexpected exit</source> ++ <translation>“%1”意外退出</translation> ++ </message> ++ <message> ++ <location filename="../src/passivitywidget.cpp" line="139"/> ++ <source>Click "Reopen" to reopen the application, and this report will be automatically sent to kylin operations personnel.</source> ++ <translation>点击“重新打开”以再次打开应用,此报告将自动发送至Kylin运维人员。</translation> ++ </message> ++ <message> ++ <location filename="../src/passivitywidget.cpp" line="154"/> ++ <source>%1 unexpectedly exited within 7 days and no longer pops up</source> ++ <translation>7天内%1意外退出不再弹出</translation> ++ </message> ++ <message> ++ <location filename="../src/passivitywidget.cpp" line="174"/> ++ <source>Reopen</source> ++ <translation>重新打开</translation> ++ </message> ++ <message> ++ <location filename="../src/passivitywidget.cpp" line="168"/> ++ <source>Cancel</source> ++ <translation>取消</translation> ++ </message> ++</context> ++<context> ++ <name>VoluntarilyWidget</name> ++ <message> ++ <location filename="../src/voluntarilywidget.cpp" line="66"/> ++ <source>Submitting</source> ++ <translation>提交中</translation> ++ </message> ++ <message> ++ <location filename="../src/voluntarilywidget.cpp" line="67"/> ++ <location filename="../src/voluntarilywidget.cpp" line="91"/> ++ <location filename="../src/voluntarilywidget.cpp" line="97"/> ++ <source>Retry</source> ++ <translation>重试</translation> ++ </message> ++ <message> ++ <location filename="../src/voluntarilywidget.cpp" line="80"/> ++ <source>Submission failed</source> ++ <translation>提交失败</translation> ++ </message> ++ <message> ++ <location filename="../src/voluntarilywidget.cpp" line="84"/> ++ <source>Submitted successfully</source> ++ <translation>提交成功</translation> ++ </message> ++ <message> ++ <location filename="../src/voluntarilywidget.cpp" line="85"/> ++ <source>Submitted</source> ++ <translation>提交完成</translation> ++ </message> ++ <message> ++ <location filename="../src/voluntarilywidget.cpp" line="131"/> ++ <source>FeedBack</source> ++ <translation>意见反馈</translation> ++ </message> ++ <message> ++ <location filename="../src/voluntarilywidget.cpp" line="135"/> ++ <source>Problem description</source> ++ <translation>问题描述</translation> ++ </message> ++ <message> ++ <location filename="../src/voluntarilywidget.cpp" line="142"/> ++ <source>Please describe the problem in detail and you can upload a photo or file by clicking the button below.</source> ++ <translation>请详细描述您遇到的问题,您也可以点击下方按钮上传图片或文件以便我们快速解决问题。</translation> ++ </message> ++ <message> ++ <location filename="../src/voluntarilywidget.cpp" line="143"/> ++ <source>Up to %1 characters</source> ++ <translation>最多输入 %1 个字符</translation> ++ </message> ++ <message> ++ <location filename="../src/voluntarilywidget.cpp" line="156"/> ++ <source>Remaining</source> ++ <translation>剩余</translation> ++ </message> ++ <message> ++ <location filename="../src/voluntarilywidget.cpp" line="157"/> ++ <source>character</source> ++ <translation>个字符</translation> ++ </message> ++ <message> ++ <location filename="../src/voluntarilywidget.cpp" line="191"/> ++ <source>Files</source> ++ <translation>上传附件</translation> ++ </message> ++ <message> ++ <location filename="../src/voluntarilywidget.cpp" line="195"/> ++ <source>ScreenShot</source> ++ <translation>截图</translation> ++ </message> ++ <message> ++ <location filename="../src/voluntarilywidget.cpp" line="209"/> ++ <source>Screen recording</source> ++ <translation>录屏</translation> ++ </message> ++ <message> ++ <location filename="../src/voluntarilywidget.cpp" line="217"/> ++ <location filename="../src/voluntarilywidget.cpp" line="489"/> ++ <source>Add file</source> ++ <translation>添加文件</translation> ++ </message> ++ <message> ++ <location filename="../src/voluntarilywidget.cpp" line="232"/> ++ <source>No more than 5 files and total capacity not exceed %1MB</source> ++ <translation>附件最多上传 5 个文件,总大小不超过 %1 MB</translation> ++ </message> ++ <message> ++ <location filename="../src/voluntarilywidget.cpp" line="237"/> ++ <source>Supported formats: </source> ++ <translation>支持格式: </translation> ++ </message> ++ <message> ++ <location filename="../src/voluntarilywidget.cpp" line="248"/> ++ <source>My score</source> ++ <translation>我的评分</translation> ++ </message> ++ <message> ++ <location filename="../src/voluntarilywidget.cpp" line="254"/> ++ <source>Contact</source> ++ <translation>联系方式</translation> ++ </message> ++ <message> ++ <location filename="../src/voluntarilywidget.cpp" line="272"/> ++ <source>The phone number format is incorrect</source> ++ <translation>手机号格式错误</translation> ++ </message> ++ <message> ++ <location filename="../src/voluntarilywidget.cpp" line="256"/> ++ <source>Please enter your phone number</source> ++ <translation>请输入您的手机号</translation> ++ </message> ++ <message> ++ <location filename="../src/voluntarilywidget.cpp" line="279"/> ++ <source>Agree to take mine </source> ++ <translation>同意获取我的 </translation> ++ </message> ++ <message> ++ <location filename="../src/voluntarilywidget.cpp" line="281"/> ++ <source>System information</source> ++ <translation>系统信息</translation> ++ </message> ++ <message> ++ <location filename="../src/voluntarilywidget.cpp" line="307"/> ++ <source>Cancel</source> ++ <translation>取消</translation> ++ </message> ++ <message> ++ <location filename="../src/voluntarilywidget.cpp" line="313"/> ++ <source>Submit</source> ++ <translation>提交</translation> ++ </message> ++ <message> ++ <location filename="../src/voluntarilywidget.cpp" line="435"/> ++ <source>Repeat addition</source> ++ <translation>附件名重复</translation> ++ </message> ++ <message> ++ <location filename="../src/voluntarilywidget.cpp" line="439"/> ++ <source>The file name contains special characters</source> ++ <translation>文件名包含特殊字符</translation> ++ </message> ++ <message> ++ <location filename="../src/voluntarilywidget.cpp" line="457"/> ++ <source>Attachment size out of limit</source> ++ <translation>附件大小超过限制</translation> ++ </message> ++</context> ++</TS> +diff --git a/plugins/service-support/service-support-mini/translations/kom-service-support-mini_zh_HK.ts b/plugins/service-support/service-support-mini/translations/kom-service-support-mini_zh_HK.ts +new file mode 100644 +index 0000000..c4d31a5 +--- /dev/null ++++ b/plugins/service-support/service-support-mini/translations/kom-service-support-mini_zh_HK.ts +@@ -0,0 +1,188 @@ ++<?xml version="1.0" encoding="utf-8"?> ++<!DOCTYPE TS> ++<TS version="2.1" language="zh_HK"> ++<context> ++ <name>PassivityWidget</name> ++ <message> ++ <location filename="../src/passivitywidget.cpp" line="116"/> ++ <source>Kylin Os Manager</source> ++ <translation>麒麟管家</translation> ++ </message> ++ <message> ++ <location filename="../src/passivitywidget.cpp" line="118"/> ++ <source>Unexpected exit reminder</source> ++ <translation>意外退出提醒</translation> ++ </message> ++ <message> ++ <location filename="../src/passivitywidget.cpp" line="133"/> ++ <source>"%1" unexpected exit</source> ++ <translation>“%1”意外退出</translation> ++ </message> ++ <message> ++ <location filename="../src/passivitywidget.cpp" line="139"/> ++ <source>Click "Reopen" to reopen the application, and this report will be automatically sent to kylin operations personnel.</source> ++ <translation>點擊“重新打開”以再次打開應用,此報告將自動發送至Kylin運維人員。</translation> ++ </message> ++ <message> ++ <location filename="../src/passivitywidget.cpp" line="154"/> ++ <source>%1 unexpectedly exited within 7 days and no longer pops up</source> ++ <translation>7天內%1意外退出不再彈出</translation> ++ </message> ++ <message> ++ <location filename="../src/passivitywidget.cpp" line="174"/> ++ <source>Reopen</source> ++ <translation>重新打開</translation> ++ </message> ++ <message> ++ <location filename="../src/passivitywidget.cpp" line="168"/> ++ <source>Cancel</source> ++ <translation>取消</translation> ++ </message> ++</context> ++<context> ++ <name>VoluntarilyWidget</name> ++ <message> ++ <location filename="../src/voluntarilywidget.cpp" line="66"/> ++ <source>Submitting</source> ++ <translation>提交中</translation> ++ </message> ++ <message> ++ <location filename="../src/voluntarilywidget.cpp" line="67"/> ++ <location filename="../src/voluntarilywidget.cpp" line="91"/> ++ <location filename="../src/voluntarilywidget.cpp" line="97"/> ++ <source>Retry</source> ++ <translation>重試</translation> ++ </message> ++ <message> ++ <location filename="../src/voluntarilywidget.cpp" line="80"/> ++ <source>Submission failed</source> ++ <translation>提交失敗</translation> ++ </message> ++ <message> ++ <location filename="../src/voluntarilywidget.cpp" line="84"/> ++ <source>Submitted successfully</source> ++ <translation>提交成功</translation> ++ </message> ++ <message> ++ <location filename="../src/voluntarilywidget.cpp" line="85"/> ++ <source>Submitted</source> ++ <translation>提交完成</translation> ++ </message> ++ <message> ++ <location filename="../src/voluntarilywidget.cpp" line="131"/> ++ <source>FeedBack</source> ++ <translation>意見反饋</translation> ++ </message> ++ <message> ++ <location filename="../src/voluntarilywidget.cpp" line="135"/> ++ <source>Problem description</source> ++ <translation>問題描述</translation> ++ </message> ++ <message> ++ <location filename="../src/voluntarilywidget.cpp" line="142"/> ++ <source>Please describe the problem in detail and you can upload a photo or file by clicking the button below.</source> ++ <translation>請詳細描述您遇到的問題,您也可以點擊下方按鈕上傳圖片或檔以便我們快速解決問題。</translation> ++ </message> ++ <message> ++ <location filename="../src/voluntarilywidget.cpp" line="143"/> ++ <source>Up to %1 characters</source> ++ <translation>最多輸入 %1 個字元</translation> ++ </message> ++ <message> ++ <location filename="../src/voluntarilywidget.cpp" line="156"/> ++ <source>Remaining</source> ++ <translation>剩餘</translation> ++ </message> ++ <message> ++ <location filename="../src/voluntarilywidget.cpp" line="157"/> ++ <source>character</source> ++ <translation>個字元</translation> ++ </message> ++ <message> ++ <location filename="../src/voluntarilywidget.cpp" line="191"/> ++ <source>Files</source> ++ <translation>上傳附件</translation> ++ </message> ++ <message> ++ <location filename="../src/voluntarilywidget.cpp" line="195"/> ++ <source>ScreenShot</source> ++ <translation>截圖</translation> ++ </message> ++ <message> ++ <location filename="../src/voluntarilywidget.cpp" line="209"/> ++ <source>Screen recording</source> ++ <translation>錄屏</translation> ++ </message> ++ <message> ++ <location filename="../src/voluntarilywidget.cpp" line="217"/> ++ <location filename="../src/voluntarilywidget.cpp" line="489"/> ++ <source>Add file</source> ++ <translation>添加檔</translation> ++ </message> ++ <message> ++ <location filename="../src/voluntarilywidget.cpp" line="232"/> ++ <source>No more than 5 files and total capacity not exceed %1MB</source> ++ <translation>附件最多上傳 5 個檔,總大小不超過 %1 MB</translation> ++ </message> ++ <message> ++ <location filename="../src/voluntarilywidget.cpp" line="237"/> ++ <source>Supported formats: </source> ++ <translation>支援格式: </translation> ++ </message> ++ <message> ++ <location filename="../src/voluntarilywidget.cpp" line="248"/> ++ <source>My score</source> ++ <translation>我的評分</translation> ++ </message> ++ <message> ++ <location filename="../src/voluntarilywidget.cpp" line="254"/> ++ <source>Contact</source> ++ <translation>聯繫方式</translation> ++ </message> ++ <message> ++ <location filename="../src/voluntarilywidget.cpp" line="272"/> ++ <source>The phone number format is incorrect</source> ++ <translation>手機號格式錯誤</translation> ++ </message> ++ <message> ++ <location filename="../src/voluntarilywidget.cpp" line="256"/> ++ <source>Please enter your phone number</source> ++ <translation>請輸入您的手機號</translation> ++ </message> ++ <message> ++ <location filename="../src/voluntarilywidget.cpp" line="279"/> ++ <source>Agree to take mine </source> ++ <translation>同意獲取我的 </translation> ++ </message> ++ <message> ++ <location filename="../src/voluntarilywidget.cpp" line="281"/> ++ <source>System information</source> ++ <translation>系統資訊</translation> ++ </message> ++ <message> ++ <location filename="../src/voluntarilywidget.cpp" line="307"/> ++ <source>Cancel</source> ++ <translation>取消</translation> ++ </message> ++ <message> ++ <location filename="../src/voluntarilywidget.cpp" line="313"/> ++ <source>Submit</source> ++ <translation>提交</translation> ++ </message> ++ <message> ++ <location filename="../src/voluntarilywidget.cpp" line="435"/> ++ <source>Repeat addition</source> ++ <translation>附件名重複</translation> ++ </message> ++ <message> ++ <location filename="../src/voluntarilywidget.cpp" line="439"/> ++ <source>The file name contains special characters</source> ++ <translation>檔名包含特殊字元</translation> ++ </message> ++ <message> ++ <location filename="../src/voluntarilywidget.cpp" line="457"/> ++ <source>Attachment size out of limit</source> ++ <translation>附件大小超過限制</translation> ++ </message> ++</context> ++</TS> +diff --git a/plugins/service-support/service-support-mini/translations/update-translations.sh b/plugins/service-support/service-support-mini/translations/update-translations.sh +new file mode 100755 +index 0000000..3af1cef +--- /dev/null ++++ b/plugins/service-support/service-support-mini/translations/update-translations.sh +@@ -0,0 +1,15 @@ ++#!/bin/bash ++ ++lupdate=`which lupdate 2> /dev/null` ++if [ -z "${lupdate}" ]; then ++ echo "lupdate not fount" ++fi ++ ++echo "using ${lupdate}" ++"$lupdate" `find ../ -name \*.cpp` -no-obsolete -ts kom-service-support-mini_zh_CN.ts \ ++ kom-service-support-mini_zh_HK.ts \ ++ kom-service-support-mini_bo_CN.ts \ ++ kom-service-support-mini_mn.ts \ ++ kom-service-support-mini_kk.ts \ ++ kom-service-support-mini_ky.ts \ ++ kom-service-support-mini_ug.ts \ diff -Nru kylin-os-manager-2.0.0/debian/patches/series kylin-os-manager-2.0.0/debian/patches/series --- kylin-os-manager-2.0.0/debian/patches/series 2025-03-12 16:03:41.000000000 +0800 +++ kylin-os-manager-2.0.0/debian/patches/series 2025-03-13 00:00:00.000000000 +0800 @@ -132,3 +132,4 @@ 0132-102-fix.patch 0133-104-release-2.0.0-60.patch 0134-105-release-2.0.0-61.patch +0135-106-release-2.0.0-62.patch