RabbitCommon v2.3.3
Loading...
Searching...
No Matches
RabbitCommonTools.cpp
1// Copyright Copyright (c) Kang Lin studio, All Rights Reserved
2// Author Kang Lin <kl222@126.com>
3
4#include <QLocale>
5#include <QDir>
6#include <QLibraryInfo>
7#include <QStandardPaths>
8#include <QSslSocket>
9#include <QThread>
10#include <QSettings>
11#include <QMimeData>
12
13#if defined(Q_OS_ANDROID)
14#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
15#include <QtCore/private/qandroidextras_p.h>
16#endif
17#endif
18
19#ifdef HAVE_RABBITCOMMON_GUI
20 #include <QIcon>
21 #include <QMainWindow>
22 #include <QMessageBox>
23 #include <QPushButton>
24 #include <QApplication>
25 #include <QDesktopServices>
26 #include <QClipboard>
27 #include "Style.h"
28#ifdef HAVE_ABOUT
29 #include "Information.h"
30#endif
31#else
32 #include <QCoreApplication>
33#endif
34
35#include "RabbitCommonTools.h"
36#include "RabbitCommonDir.h"
37#ifdef HAVE_ADMINAUTHORISER
38#include "AdminAuthoriser/adminauthoriser.h"
39#endif
40#include "RabbitCommonRegister.h"
41#include "Log/Log.h"
42
43#if defined(HAVE_OPENSSL)
44 #include "openssl/opensslv.h"
45 #include "openssl/crypto.h"
46 #include "openssl/ssl.h"
47#endif
48
49#if defined(Q_OS_WIN)
50 #include <windows.h>
51 #include <tchar.h>
52// #include <stdio.h>
53 //#include "lm.h"
54 //#pragma comment(lib,"netapi32.lib")
55#else
56 #include <pwd.h>
57 #include <unistd.h>
58 #include <signal.h>
59#endif
60
61#if defined(Q_OS_WIN)
62 #include "CoreDump/MiniDumper.h"
63#endif
64#include "CoreDump/StackTrace.h"
65
66#ifdef HAVE_RABBITCOMMON_GUI
67 #include "Log/DockDebugLog.h"
68 #include "Log/DlgFilter.h"
69 extern CDockDebugLog* g_pDcokDebugLog;
70#endif
71
72inline void g_RabbitCommon_InitResource()
73{
74 Q_INIT_RESOURCE(ResourceRabbitCommon);
75
76#ifdef BUILD_QUIWidget
77 Q_INIT_RESOURCE(QUIWidget);
78#endif
79#if DEBUG
80 // Must set cmake parameters: -DCMAKE_BUILD_TYPE=Debug
81 //Q_INIT_RESOURCE(translations_RabbitCommon);
82#ifdef BUILD_QUIWidget
83 Q_INIT_RESOURCE(QUIWidgetQss);
84#endif
85#endif
86}
87
88inline void g_RabbitCommon_CleanResource()
89{
90 Q_CLEANUP_RESOURCE(ResourceRabbitCommon);
91#ifdef BUILD_QUIWidget
92 Q_CLEANUP_RESOURCE(QUIWidget);
93#endif
94#if DEBUG
95 //Q_CLEANUP_RESOURCE(translations_RabbitCommon);
96#ifdef BUILD_QUIWidget
97 Q_CLEANUP_RESOURCE(QUIWidgetQss);
98#endif
99#endif
100}
101
102namespace RabbitCommon {
103
104static Q_LOGGING_CATEGORY(log, "RabbitCommon.Tools")
105static Q_LOGGING_CATEGORY(logTranslation, "RabbitCommon.Tools.Translation")
106
107static CCallTrace* g_pCallStack = nullptr;
108
109CTools::CTools() : QObject()
110 , m_Initialized(false)
111#if defined(Q_OS_ANDROID)
112 , m_bShowMaxWindow(true)
113#else
114 , m_bShowMaxWindow(false)
115#endif
116{}
117
118CTools::~CTools()
119{
120 qDebug(log) << "CTools::~CTools()";
121#if HAVE_RABBITCOMMON_GUI
122 if(g_pDcokDebugLog)
123 delete g_pDcokDebugLog;
124#endif
125}
126
127CTools* CTools::Instance()
128{
129 static CTools* pTools = nullptr;
130 if(nullptr == pTools)
131 pTools = new CTools();
132 return pTools;
133}
134
135int CTools::SetLanguage(const QString szLanguage)
136{
137 m_szLanguage = szLanguage;
138 return 0;
139}
140
141QString CTools::GetLanguage()
142{
143 if(m_szLanguage.isEmpty())
144 return QLocale::system().name();
145 return m_szLanguage;
146}
147
149{
150 QString szReturn;
151 QString szVersion(RabbitCommon_VERSION);
152 QString szRevision(RabbitCommon_REVISION);
153 if(szRevision.isEmpty()) {
154 szReturn = QObject::tr("Version: ") + szVersion;
155 } else {
156 szReturn = QObject::tr("Version: ") + szVersion + QObject::tr(" (From revision: ");
157#if (defined(HAVE_CMARK) || defined(HAVE_CMARK_GFM))
158 szReturn += "[" + szRevision + "](http://github.com/KangLin/RabbitCommon/tree/" + szRevision + ")";
159#else
160 szReturn += szRevision;
161#endif
162 szReturn += ") ";
163 }
164 return szReturn;
165}
166
168{
169 QString szInfo;
170 szInfo = QObject::tr("- Functions:") + "\n";
171#if defined(HAVE_RABBITCOMMON_GUI)
172 szInfo += QObject::tr(" - Have GUI") + "\n";
173#endif
174#if defined(HAVE_ABOUT)
175 szInfo += QObject::tr(" - Have about diaglog") + "\n";
176#ifdef HAVE_CMARK_GFM
177 szInfo += QObject::tr(" - Use cmark-gfm") + "\n";
178#elif HAVE_CMARK
179 szInfo += QObject::tr(" - Use cmark") + "\n";
180#endif
181#endif
182#if defined(HAVE_UPDATE)
183 szInfo += QObject::tr(" - Have update") + "\n";
184#endif
185 szInfo += QObject::tr(" - The cursom title bar for QWidget") + "\n";
186 szInfo += QObject::tr(" - Dock Folder browser") + "\n";
187 szInfo += QObject::tr(" - Recent menu") + "\n";
188 szInfo += QObject::tr(" - Style") + "\n";
189 szInfo += QObject::tr(" - Log") + "\n";
190 szInfo += QObject::tr(" - Core dump") + "\n";
191#if defined(HAVE_OPENSSL)
192 szInfo += QObject::tr(" - Have encrypt(OPENSSL)") + "\n";
193#endif
194#if defined(BUILD_QUIWidget)
195 szInfo += QObject::tr(" - Have QUIWidget") + "\n";
196#endif
197 szInfo += QObject::tr(" - Applicatoin paths and files: ") + "\n";
198 szInfo += QObject::tr(" - Install root path: ") + RabbitCommon::CDir::Instance()->GetDirApplicationInstallRoot() + "\n";
199 szInfo += QObject::tr(" - Application path: ") + RabbitCommon::CDir::Instance()->GetDirApplication() + "\n";
200 szInfo += QObject::tr(" - Configure path: ") + RabbitCommon::CDir::Instance()->GetDirConfig() + "\n";
201 szInfo += QObject::tr(" - Configure file: ") + RabbitCommon::CDir::Instance()->GetFileApplicationConfigure() + "\n";
202 szInfo += QObject::tr(" - Translations path: ") + RabbitCommon::CDir::Instance()->GetDirTranslations() + "\n";
203 szInfo += QObject::tr(" - Log path: ") + RabbitCommon::CDir::Instance()->GetDirLog() + "\n";
204 szInfo += QObject::tr(" - Data path: ") + RabbitCommon::CDir::Instance()->GetDirData() + "\n";
205 szInfo += QObject::tr(" - Icons path: ") + RabbitCommon::CDir::Instance()->GetDirIcons() + "\n";
206 szInfo += QObject::tr(" - Database path: ") + RabbitCommon::CDir::Instance()->GetDirDatabase() + "\n";
207 szInfo += QObject::tr(" - Database file: ") + RabbitCommon::CDir::Instance()->GetDirDatabaseFile() + "\n";
208 szInfo += QObject::tr(" - Plugins path: ") + RabbitCommon::CDir::Instance()->GetDirPlugins() + "\n";
209 szInfo += QObject::tr(" - User folders and files: ") + "\n";
210 szInfo += QObject::tr(" - Documents path: ") + RabbitCommon::CDir::Instance()->GetDirUserDocument() + "\n";
211 szInfo += QObject::tr(" - Configure path: ") + RabbitCommon::CDir::Instance()->GetDirUserConfig() + "\n";
212 szInfo += QObject::tr(" - Configure file: ") + RabbitCommon::CDir::Instance()->GetFileUserConfigure() + "\n";
213 szInfo += QObject::tr(" - Data path: ") + RabbitCommon::CDir::Instance()->GetDirUserData() + "\n";
214 szInfo += QObject::tr(" - Image path: ") + RabbitCommon::CDir::Instance()->GetDirUserImage() + "\n";
215 szInfo += QObject::tr(" - Database path: ") + RabbitCommon::CDir::Instance()->GetDirUserDatabase() + "\n";
216 szInfo += QObject::tr(" - Database file: ") + RabbitCommon::CDir::Instance()->GetDirUserDatabaseFile() + "\n";
217
218 szInfo += QObject::tr("- Dependent libraries:") + "\n";
219 szInfo += QObject::tr(" - OpenSSL:") + "\n";
220#if defined(HAVE_OPENSSL)
221 szInfo += " - " + QObject::tr("Build Version: ") + OPENSSL_VERSION_TEXT + "\n";
222 szInfo += " - " + QObject::tr("Runtime Version: ") + OpenSSL_version(OPENSSL_VERSION) + "\n";
223#endif
224 if(QSslSocket::supportsSsl())
225 {
226#if (QT_VERSION >= QT_VERSION_CHECK(5, 4, 3))
227 szInfo += " - Qt " + QObject::tr("Build Version: ") + QSslSocket::sslLibraryBuildVersionString() + "\n";
228#endif
229 szInfo += " - Qt " + QObject::tr("Installed Version: ") + QSslSocket::sslLibraryVersionString() + "\n";
230 } else {
231#if (QT_VERSION >= QT_VERSION_CHECK(5, 4, 3))
232 szInfo += " - Qt " + QObject::tr("Build Version: ") + QSslSocket::sslLibraryBuildVersionString() + "\n";
233#endif
234 szInfo += " - Qt " + QObject::tr("Don't install OPENSSL dynamic library. Please install it") + "\n";
235 }
236#if HAVE_StackWalker
237 szInfo += QObject::tr(" - StackWalker") + "\n";
238#endif
239#ifdef HAVE_CMARK_GFM
240 szInfo += QObject::tr(" - cmark-gfm") + "\n";
241#elif HAVE_CMARK
242 szInfo += QObject::tr(" - cmark") + "\n";
243#endif
244 return szInfo;
245}
246
247int CTools::AndroidRequestPermission(const QString &permission)
248{
249#if defined (Q_OS_ANDROID)
250 #if QT_VERSION > QT_VERSION_CHECK(6, 0, 0)
251 // get android storage permission
252 // 该接口也可以直接使用字符串,可自行跳转到头文件自行查看
253
254 if (QtAndroidPrivate::checkPermission(permission).result()
255 == QtAndroidPrivate::Denied)
256 {
257 QtAndroidPrivate::requestPermission(permission).waitForFinished();
258 }
259 qInfo(log) << "android permission" << permission << ";status:"
260 << QtAndroidPrivate::checkPermission(permission).result();
261 #endif
262#endif
263
264 return 0;
265}
266
267int CTools::AndroidRequestPermission(const QStringList &permissions)
268{
269 foreach (auto p, permissions) {
270 AndroidRequestPermission(p);
271 }
272 return 0;
273}
274
275void CTools::Init(int argc, char *argv[], QString szApplicationName)
276{
277 if(1 > argc || !argv) {
278 qCritical(log) << "The parameters is error";
279 return;
280 }
281
282 QString szName;
283 QString szPath;
284 QFileInfo fi(argv[0]);
285 if(szApplicationName.isEmpty())
286 szName = fi.baseName();
287 else
288 szName = szApplicationName;
289 szPath = fi.absolutePath();
290 Init(szName, szPath, szPath + QDir::separator() + "..");
291}
292
293void CTools::Init(QString szApplicationName,
294 QString szApplicationDirPath,
295 QString szApplicationInstallRoot,
296 const QString szLanguage)
297{
298 if(m_Initialized) {
299 qWarning(log) << "CTools is already initialized";
300 Q_ASSERT(false);
301 return;
302 }
303
304 if(QCoreApplication::applicationName().isEmpty())
305 {
306 QCoreApplication::setApplicationName(szApplicationName);
307 CDir::Instance()->SetDirUserDocument();
308 }
309 if(QCoreApplication::applicationDirPath().isEmpty()
310 && CDir::Instance()->GetDirApplication().isEmpty())
311 CDir::Instance()->SetDirApplication(szApplicationDirPath);
312 if(CDir::Instance()->GetDirApplicationInstallRoot().isEmpty())
313 CDir::Instance()->SetDirApplicationInstallRoot(szApplicationInstallRoot);
314 if(QCoreApplication::applicationName().isEmpty()
315 || CDir::Instance()->GetDirApplication().isEmpty()
316 || CDir::Instance()->GetDirApplicationInstallRoot().isEmpty())
317 {
318 qCritical(log)
319 << "CTools::Instance()->Init() is called after QApplication a(argc, argv);"
320 "Or call this function with the parameters"
321 "szApplicationName, "
322 "szApplicationDirPath, "
323 "and szApplicationInstallRoot";
324 Q_ASSERT(false);
325 return;
326 }
327
328 QStringList permissions;
329 permissions << "android.permission.WRITE_EXTERNAL_STORAGE"
330 << "android.permission.INTERNET"
331 << "android.permission.ACCESS_NETWORK_STATE"
332 << "android.permission.CHANGE_WIFI_STATE"
333 << "android.permission.ACCESS_WIFI_STATE"
334 << "android.permission.ACCESS_NETWORK_STATE"
335 << "android.permission.CHANGE_NETWORK_STATE";
336 AndroidRequestPermission(permissions);
338 RabbitCommon::CLog::Instance();
339 SetLanguage(szLanguage);
340 qInfo(logTranslation) << "Language:" << szLanguage;
341 InitResource();
342 InstallTranslator("RabbitCommon", TranslationType::Library, szLanguage);
343 //Init qt translation
344 QString szQtTranslationPath;
345#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
346 szQtTranslationPath = QLibraryInfo::location(QLibraryInfo::TranslationsPath);
347#else
348 szQtTranslationPath = QLibraryInfo::path(QLibraryInfo::TranslationsPath);
349#endif
350 QStringList qtTranslations;
351 qtTranslations << "qt" << "qtbase" << "qtmultimedia"
352 << "qtlocation";
353 foreach(auto f, qtTranslations) {
354 QString szFile = szQtTranslationPath + QDir::separator()
355 + f + "_" + szLanguage + ".qm";
356 QFile file(szFile);
357 if(file.exists())
358 InstallTranslatorFile(szFile);
359 else
360 qWarning(logTranslation) << "The file isn't exists:" << szFile;
361 }
362
363#ifdef HAVE_RABBITCOMMON_GUI
364 QSettings set(RabbitCommon::CDir::Instance()->GetFileUserConfigure(),
365 QSettings::IniFormat);
366 m_bShowMaxWindow = set.value("Tools/Window/ShowMax", m_bShowMaxWindow).toBool();
367
368 CStyle::Instance()->LoadStyle();
369#ifdef HAVE_ABOUT
370 CInformation info("RabbitCommon, Qt and System information:", "");
371#endif
372#else
373 qDebug(log) << "RabbitCommon:" << "\n" << Information();
374#endif //HAVE_RABBITCOMMON_GUI
375}
376
378{
379 foreach(auto t, m_Translator) {
380 QCoreApplication::removeTranslator(t.data());
381 }
382 m_Translator.clear();
383 CleanResource();
384 delete RabbitCommon::CLog::Instance();
385}
386
387QSharedPointer<QTranslator> CTools::InstallTranslatorFile(const QString szFile)
388{
389 QSharedPointer<QTranslator> translator
390 = QSharedPointer<QTranslator>(new QTranslator());
391 if(!translator) {
392 qCritical(logTranslation) << "new QTranslator fail";
393 return translator;
394 }
395 bool bRet = translator->load(szFile);
396 if(bRet)
397 {
398 bRet = QCoreApplication::installTranslator(translator.data());
399 if(bRet)
400 {
401 m_Translator.push_back(translator);
402 qDebug(logTranslation) << "Install translator:" << szFile;
403 return translator;
404 }
405 else {
406 qCritical(logTranslation) << "Install translator fail:" << szFile;
407 }
408 } else
409 qCritical(logTranslation) << "Load translator file fail:" << szFile;
410 return QSharedPointer<QTranslator>();
411}
412
413QSharedPointer<QTranslator> CTools::InstallTranslator(
414 const QString szName,
415 TranslationType type,
416 const QString szPluginDir,
417 const QString szLanguage)
418{
419 QString szTranslationName = szName;
420
421 QString szSuffix;
422 QString szPath;
423 szSuffix = QDir::separator() + szTranslationName + "_" + szLanguage + ".qm";
424 switch(type) {
425 case TranslationType::Application:
426 szPath = CDir::Instance()->GetDirTranslations();
427 if(szTranslationName.isEmpty()) {
428 szTranslationName = QCoreApplication::applicationName();
429 szSuffix = QDir::separator() + szTranslationName + "_" + szLanguage + ".qm";
430 }
431 break;
432 case TranslationType::Library: {
433 szPath = CDir::Instance()->GetDirTranslations();
434 if(szTranslationName.isEmpty()) {
435 qCritical(logTranslation) << "Please set translation name";
436 Q_ASSERT(false);
437 }
438#if defined(Q_OS_LINUX)
439 QFile file(szPath + szSuffix);
440 if(!file.exists()) {
441 szPath = CDir::Instance()->GetDirTranslations("/usr/share");
442 file.setFileName(szPath + szSuffix);
443 if(!file.exists()) {
444 szPath = CDir::Instance()->GetDirTranslations(
445 "/usr/local/share");
446 }
447 }
448#endif
449 break;
450 }
451 case TranslationType::Plugin:
452 szPath = CDir::Instance()->GetDirPluginsTranslation(szPluginDir);
453 if(szTranslationName.isEmpty()) {
454 qCritical(logTranslation) << "Please set translation name";
455 Q_ASSERT(false);
456 }
457 break;
458 }
459
460 QString szFile = szPath + szSuffix;
461 QFile file(szFile);
462 if(!file.exists())
463 {
464 qCritical(logTranslation) << "File isn't exit:" << szFile;
465 return QSharedPointer<QTranslator>();
466 }
467
468 return InstallTranslatorFile(szFile);
469}
470
471int CTools::RemoveTranslator(QSharedPointer<QTranslator> translator)
472{
473 foreach(auto t, m_Translator) {
474 if(t == translator) {
475 QCoreApplication::removeTranslator(t.data());
476 m_Translator.removeAll(t);
477 return 0;
478 }
479 }
480 return -1;
481}
482
483void CTools::InitResource()
484{
485 g_RabbitCommon_InitResource();
486}
487
488void CTools::CleanResource()
489{
490 g_RabbitCommon_CleanResource();
491}
492
493#if defined(Q_OS_UNIX)
494void SigHandler(int sig)
495{
496 switch(sig)
497 {
498 case SIGSEGV: // 试图访问未分配给自己的内存, 或试图往没有写权限的内存地址写数据.
499 case SIGBUS: // 非法地址, 包括内存地址对齐(alignment)出错。比如访问一个四个字长的整数, 但其地址不是4的倍数。它与SIGSEGV的区别在于后者是由于对合法存储地址的非法访问触发的(如访问不属于自己存储空间或只读存储空间)。
500 case SIGILL: // illeage,非法的。执行了非法指令, 通常是因为可执行文件本身出现错误, 或者试图执行数据段. 堆栈溢出也有可能产生这个信号。
501 qCritical(log) << "Receive exception signal:" << sig << "\n"
502 << g_pCallStack->GetStack(3).toStdString().c_str();
503 break;
504 default:
505 qDebug(log) << "Receive signal:" << sig;
506 return;
507 };
508 exit(sig);
509}
510#endif
511
512bool CTools::EnableCoreDump(bool bPrompt)
513{
514 Q_UNUSED(bPrompt);
515 g_pCallStack = new CCallTrace();
516
517#ifdef Q_OS_WIN
518 //static RabbitCommon::CMiniDumper dumper(bPrompt);
519 RabbitCommon::EnableMiniDumper();
520#else
521 //SIGSEGV: 试图访问未分配给自己的内存, 或试图往没有写权限的内存地址写数据.
522 signal(SIGSEGV, SigHandler);
523 // 非法地址, 包括内存地址对齐(alignment)出错。比如访问一个四个字长的整数, 但其地址不是4的倍数。它与SIGSEGV的区别在于后者是由于对合法存储地址的非法访问触发的(如访问不属于自己存储空间或只读存储空间)。
524 signal(SIGBUS, SigHandler);
525 // illeage,非法的。执行了非法指令, 通常是因为可执行文件本身出现错误, 或者试图执行数据段. 堆栈溢出也有可能产生这个信号。
526 signal(SIGILL, SigHandler);
527#endif
528 return true;
529}
530
532{
533#ifdef HAVE_ADMINAUTHORISER
534 return CAdminAuthoriser::Instance()->hasAdminRights();
535#else
536 return false;
537#endif
538}
539
540bool CTools::ExecuteWithAdministratorPrivilege(const QString &program, const QStringList &arguments)
541{
542#ifdef HAVE_ADMINAUTHORISER
543 return CAdminAuthoriser::Instance()->execute(program, arguments);
544#else
545 return false;
546#endif
547}
548
549bool CTools::executeByRoot(const QString &program, const QStringList &arguments)
550{
551 return ExecuteWithAdministratorPrivilege(program, arguments);
552}
553
554bool CTools::StartWithAdministratorPrivilege(bool bQuitOld)
555{
556 bool bRet = true;
558 auto para = QApplication::arguments();
559 QString szApp = QApplication::applicationFilePath();
560 QString szAppImage;
561#if QT_VERSION > QT_VERSION_CHECK(6, 0, 0) && defined(Q_OS_WIN)
562 szAppImage = qEnvironmentVariable("APPIMAGE");
563#else
564 szAppImage = QString::fromLocal8Bit(qgetenv("APPIMAGE"));
565#endif
566 qDebug(log) << "App:" << szApp << szAppImage;
567 if(!szAppImage.isEmpty())
568 szApp = szAppImage;
569 if(!para.isEmpty())
570 para.removeFirst();
571 if(para.isEmpty())
572 bRet = ExecuteWithAdministratorPrivilege(szApp);
573 else
574 bRet = ExecuteWithAdministratorPrivilege(szApp,
575 para);
576 if(bRet) {
577 if(bQuitOld)
578 QApplication::quit();
579 }
580 else
581 qCritical(log) << "Start by root fail:" << QApplication::applicationFilePath()
582 << para;
583 }
584 return bRet;
585}
586
587int CTools::InstallStartRun(const QString &szName, const QString &szPath, bool bAllUser)
588{
589 Q_UNUSED(szName)
590 Q_UNUSED(szPath)
591 Q_UNUSED(bAllUser)
592
593 QString appPath;
594 appPath = QCoreApplication::applicationFilePath();
595
596 if(!szPath.isEmpty())
597 appPath = szPath;
598 if(appPath.isEmpty())
599 {
600 qCCritical(log) << "szPath is empty";
601 return -1;
602 }
603 if(bAllUser)
604 return RabbitCommon::CRegister::InstallStartRun();
605 return RabbitCommon::CRegister::InstallStartRunCurrentUser();
606 //See: debian/postinst and Install/install.sh
607 //Ubuntu use gnome-session-properties
608 // - Current user: ~/.config/autostart
609 // - All user: /etc/xdg/autostart/
610 //https://blog.csdn.net/DinnerHowe/article/details/79025282
611 QString szLink = CRegister::GetDesktopFileLink(szName, bAllUser);
612 if(QFile::exists(szLink))
613 if(RemoveStartRun(szName, bAllUser))
614 {
615 qCCritical(log) << "RemoveStartRun" << szName << "fail";
616 return -1;
617 }
618
619 appPath = CRegister::GetDesktopFileName(szPath, szName);
620 QFile f(appPath);
621 if(!f.exists())
622 {
623 qCCritical(log) << "The desktop file is not exist." << appPath;
624 return -2;
625 }
626 bool ret = f.link(szLink);
627 if(!ret)
628 {
629 QString szCmd = "ln -s " + appPath + " " + szLink;
630 if(!executeByRoot(szCmd))
631 qCritical(log) << "CTools::InstallStartRun: file link"
632 << f.fileName() << " to " << szLink << f.error();
633 return -1;
634 }
635 return 0;
636
637}
638
639int CTools::RemoveStartRun(const QString &szName, bool bAllUser)
640{
641 Q_UNUSED(szName);
642 QString appName = QCoreApplication::applicationName();
643 if(!szName.isEmpty())
644 appName = szName;
645 if(bAllUser)
646 return RabbitCommon::CRegister::RemoveStartRun();
647 return RabbitCommon::CRegister::RemoveStartRunCurrentUser();
648
649 QString szLink = CRegister::GetDesktopFileLink(szName, bAllUser);
650 if(!QFile::exists(szLink)) return 0;
651
652 QDir d;
653 if(d.remove(szLink)) return 0;
654
655 QString szCmd = "rm " + szLink;
656 if(executeByRoot(szCmd)) return 0;
657 qCritical(log) << "execute" << szCmd << "fail";
658 return -1;
659
660}
661
662bool CTools::IsStartRun(const QString &szName, bool bAllUser)
663{
664 Q_UNUSED(szName);
665
666 if(bAllUser)
667 return RabbitCommon::CRegister::IsStartRun();
668 return RabbitCommon::CRegister::IsStartRunCurrentUser();
669
670 QString szLink = CRegister::GetDesktopFileLink(szName, bAllUser);
671 if(QFile::exists(szLink))
672 return true;
673 return false;
674}
675
676int CTools::GenerateDesktopFile(const QString &szPath,
677 const QString &szName)
678{
679 int nRet = 0;
680
681 QString szFile = CRegister::GetDesktopFileName(szPath, szName);
682
683 QString szContent;
684 szContent = "[Desktop Entry]\n";
685 szContent += "Name=" + QCoreApplication::applicationName() + "\n";
686 szContent += "Comment=" + QCoreApplication::applicationName() + "\n";
687#ifdef HAVE_RABBITCOMMON_GUI
688 szContent += "Name[" + QLocale::system().name() + "]=" + QApplication::applicationDisplayName() + "\n";
689 szContent += "Comment[" + QLocale::system().name() + "]=" + QApplication::applicationDisplayName() + "\n";
690#else
691 szContent += "Name[" + QLocale::system().name() + "]=" + QCoreApplication::applicationName() + "\n";
692 szContent += "Comment[" + QLocale::system().name() + "]=" + QCoreApplication::applicationName() + "\n";
693#endif
694 szContent += "Icon=" + QCoreApplication::applicationName() + "\n";
695 szContent += "Exec=" + QCoreApplication::applicationFilePath() + "\n";
696 szContent += "Categories=Application;Development;\n";
697 szContent += "Terminal=false\n";
698 szContent += "StartupNotify=true\n";
699
700 QFile f(szFile);
701 if(!f.open(QFile::WriteOnly))
702 {
703 return f.error();
704 }
705 f.write(szContent.toStdString().c_str());
706 f.close();
707 return nRet;
708}
709
710QString CTools::GetCurrentUser()
711{
712#ifdef UNIX
713 struct passwd *pwd;
714 pwd = getpwuid(getuid());
715 return pwd->pw_name;
716#elif WINDOWS
717 CHAR szUserName[MAX_PATH] = {0};
718 DWORD dwSize=MAX_PATH;
719 ::GetUserNameA(szUserName, &dwSize);
720 return szUserName;
721 //return QString::fromWCharArray(szUserName, dwSize);
722#else
723 return QDir::home().dirName();
724#endif
725}
726
727QString CTools::GetHostName()
728{
729 char buf[255];
730 gethostname(buf, sizeof(buf));
731 return buf;
732}
733
734#ifdef HAVE_RABBITCOMMON_GUI
735QAction* CTools::AddStyleMenu(QMenu *pMenu, QWidget *parent)
736{
737 return pMenu->addAction(QIcon::fromTheme("style"),
738 QObject::tr("Style"),
739 [=](){
740 CFrmStyle* s = new CFrmStyle(parent);
741 if(s)
742 s->show();
743 });
744}
745
746void CTools::InsertStyleMenu(QMenu *pMenu, QAction *before, QWidget *parent)
747{
748 QAction* pAction = new QAction(QIcon::fromTheme("style"),
749 QObject::tr("Style"), parent);
750 if(!pAction)
751 return;
752 pAction->setStatusTip(QObject::tr("Style"));
753 QObject::connect(pAction, &QAction::triggered, [=](){
754 CFrmStyle* s = new CFrmStyle(parent);
755 if(s)
756 s->show();
757 });
758 pMenu->insertAction(before, pAction);
759}
760
761QMenu* CTools::GetLogMenu(QWidget *parentMainWindow)
762{
763 QMenu* pMenu = new QMenu(QObject::tr("Log"), parentMainWindow);
764 if(!pMenu) return pMenu;
765 pMenu->setStatusTip(QObject::tr("Log"));
766 pMenu->setIcon(QIcon::fromTheme("folder-open"));
767 QAction* pAction = pMenu->addAction(QIcon::fromTheme("emblem-system"),
768 QObject::tr("Settings"),
769 [](){
770 CDlgFilter dlg;
771 QString szInclude, szExclude;
772 CLog::Instance()->GetFilter(szInclude, szExclude);
773 dlg.SetFilter(szInclude, szExclude);
774 if(QDialog::Accepted == RC_SHOW_WINDOW(&dlg))
775 {
776 dlg.GetFilter(szInclude, szExclude);
777 CLog::Instance()->SetFilter(szInclude, szExclude);
778 }
779 });
780 pAction->setStatusTip(QObject::tr("Settings"));
781 pAction = pMenu->addAction(QIcon::fromTheme("document-open"),
782 QObject::tr("Open Log configure file"),
783 [](){RabbitCommon::OpenLogConfigureFile();});
784 pAction->setStatusTip(QObject::tr("Open Log configure file"));
785 pAction = pMenu->addAction(QIcon::fromTheme("document-open"),
786 QObject::tr("Open Log file"),
787 [](){RabbitCommon::OpenLogFile();});
788 pAction->setStatusTip(QObject::tr("Open Log file"));
789 pAction = pMenu->addAction(QIcon::fromTheme("folder-open"),
790 QObject::tr("Open log folder"),
791 [](){RabbitCommon::OpenLogFolder();});
792 pAction->setStatusTip(QObject::tr("Open Log folder"));
793 QMainWindow* pMainWindow = qobject_cast<QMainWindow*>(parentMainWindow);
794 if(pMainWindow) {
795 if(!g_pDcokDebugLog)
796 g_pDcokDebugLog = new CDockDebugLog(pMainWindow);
797 pMainWindow->addDockWidget(Qt::DockWidgetArea::BottomDockWidgetArea,
798 g_pDcokDebugLog);
799 // Must set ObjectName then restore it. See: saveState help document
800 g_pDcokDebugLog->setObjectName("dockDebugLog");
801 QAction* pDock = g_pDcokDebugLog->toggleViewAction();
802 pMenu->addAction(pDock);
803 pDock->setText(QObject::tr("Log dock"));
804 pDock->setIcon(QIcon::fromTheme("floating"));
805 pDock->setStatusTip(QObject::tr("Log dock"));
806 } else {
807 qWarning(log) << "CTools::GetLogMenu: Don't use dock debug log."
808 << "The parent suggest is MainWindow pointer";
809 }
810
811 return pMenu;
812}
813
814int CTools::RestoreWidget(QWidget *pWidget)
815{
816 int nRet = 0;
817 Q_ASSERT(pWidget);
818 if(!pWidget) return -1;
819 QSettings set(RabbitCommon::CDir::Instance()->GetFileUserConfigure(),
820 QSettings::IniFormat);
821 QByteArray geometry
822 = set.value("MainWindow/Status/Geometry").toByteArray();
823 if(!geometry.isEmpty()) {
824 if(!pWidget->restoreGeometry(geometry))
825 qWarning(log) << "Restore geometry fail";
826 }
827 QMainWindow* pMainWindow = qobject_cast<QMainWindow*>(pWidget);
828 if(pMainWindow) {
829 QByteArray state = set.value("MainWindow/Status/State").toByteArray();
830 if(!state.isEmpty()) {
831 if(!pMainWindow->restoreState(state))
832 qWarning(log) << "Restore state fail";
833 }
834 }
835 return nRet;
836}
837
838int CTools::SaveWidget(QWidget *pWidget)
839{
840 int nRet = 0;
841 Q_ASSERT(pWidget);
842 if(!pWidget) return -1;
843 QSettings set(RabbitCommon::CDir::Instance()->GetFileUserConfigure(),
844 QSettings::IniFormat);
845 set.setValue("MainWindow/Status/Geometry", pWidget->saveGeometry());
846 QMainWindow* pMainWindow = qobject_cast<QMainWindow*>(pWidget);
847 if(pMainWindow) {
848 set.setValue("MainWindow/Status/State", pMainWindow->saveState());
849 }
850 return nRet;
851}
852
853int CTools::ShowWidget(QWidget *pWin)
854{
855 if(!pWin) {
856 qCritical(log) << Q_FUNC_INFO << "The parameter is nullptr";
857 Q_ASSERT(pWin);
858 return -1;
859 }
860
861 QDialog* pDlg = qobject_cast<QDialog*>(pWin);
862 if(pDlg) {
863 if(m_bShowMaxWindow) {
864 pDlg->showMaximized();
865 }
866 return pDlg->exec();
867 } else {
868 if(m_bShowMaxWindow) {
869 pWin->showMaximized();
870 } else
871 pWin->show();
872 }
873 return 0;
874}
875
876void CTools::ShowCoreDialog(QString szTitle, QString szContent, QString szDetail, QString szCoreDumpFile)
877{
878 g_pCallStack->ShowCoreDialog(szTitle, szContent, szDetail, szCoreDumpFile);
879}
880
881#endif // #ifdef HAVE_RABBITCOMMON_GUI
882
883} //namespace RabbitCommon
Set filter dialog.
Definition DlgFilter.h:18
The CDockDebugLog class.
Set style and icon theme form.
Definition FrmStyle.h:89
Get call stack.
Definition StackTrace.h:17
QString GetDirData(bool bReadOnly=false)
Get data directory.
QString GetDirTranslations(QString szPrefix=QString())
static QString GetDesktopFileLink(const QString &szName=QString(), bool bAllUser=false)
GetDesktopFileLink.
static QString GetDesktopFileName(const QString &szPath=QString(), const QString &szName=QString())
Generate the name of desktop file.
static bool EnableCoreDump(bool bPrompt=true)
Enable core dump.
QSharedPointer< QTranslator > InstallTranslator(const QString szName=QString(), TranslationType type=TranslationType::Application, const QString szPluginDir="plugins", const QString szLanguage=QLocale::system().name())
Install translation.
static int GenerateDesktopFile(const QString &szPath=QString(), const QString &szName=QString())
GenerateDesktopFile: Generate desktop file.
static bool HasAdministratorPrivilege()
Has administrator privilege.
static QString Information()
RabbitCommon information.
static bool executeByRoot(const QString &program, const QStringList &arguments=QStringList())
executeByRoot: Run with administrator privileges
void Init(QString szApplicationName=QCoreApplication::applicationName(), QString szApplicationDirPath=QCoreApplication::applicationDirPath(), QString szApplicationInstallRoot=QString(), const QString szLanguage=QLocale::system().name())
Initialize the resource, which is called only once at the beginning of the program,...
static int InstallStartRun(const QString &szName=QString(), const QString &szPath=QString(), bool bAllUser=false)
InstallStartRun: auto run when startup.
static QString Version()
RabbitCommon version.