File indexing completed on 2024-05-19 05:44:23
0001 /* 0002 SPDX-FileCopyrightText: 2015-2017 Milian Wolff <mail@milianw.de> 0003 0004 SPDX-License-Identifier: LGPL-2.1-or-later 0005 */ 0006 0007 #include <QApplication> 0008 #include <QCommandLineParser> 0009 0010 #include <KAboutData> 0011 #include <KLocalizedString> 0012 #include <kcoreaddons_version.h> 0013 0014 #include "analyze/suppressions.h" 0015 #include "util/config.h" 0016 0017 #include "gui_config.h" 0018 #include "mainwindow.h" 0019 #include "proxystyle.h" 0020 0021 #include <KIconTheme> 0022 #include <QFile> 0023 #include <QResource> 0024 0025 // FIXME: patch KIconTheme so that this isn't needed here 0026 void Q_DECL_UNUSED initRCCIconTheme() 0027 { 0028 const QString iconThemeRcc = qApp->applicationDirPath() + QStringLiteral("/../share/icons/breeze/breeze-icons.rcc"); 0029 if (!QFile::exists(iconThemeRcc)) { 0030 qWarning("cannot find icons rcc: %ls", qUtf16Printable(iconThemeRcc)); 0031 return; 0032 } 0033 0034 const QString iconThemeName = QStringLiteral("kf5_rcc_theme"); 0035 const QString iconSubdir = QStringLiteral("/icons/") + iconThemeName; 0036 if (!QResource::registerResource(iconThemeRcc, iconSubdir)) { 0037 qWarning("Invalid rcc file: %ls", qUtf16Printable(iconThemeRcc)); 0038 } 0039 0040 if (!QFile::exists(QLatin1Char(':') + iconSubdir + QStringLiteral("/index.theme"))) { 0041 qWarning("No index.theme found in %ls", qUtf16Printable(iconThemeRcc)); 0042 QResource::unregisterResource(iconThemeRcc, iconSubdir); 0043 } 0044 0045 // Tell Qt about the theme 0046 // Note that since qtbase commit a8621a3f8, this means the QPA (i.e. KIconLoader) will NOT be used. 0047 QIcon::setThemeName(iconThemeName); // Qt looks under :/icons automatically 0048 // Tell KIconTheme about the theme, in case KIconLoader is used directly 0049 KIconTheme::forceThemeForTests(iconThemeName); 0050 } 0051 0052 int main(int argc, char** argv) 0053 { 0054 #if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) 0055 QApplication::setAttribute(Qt::AA_UseHighDpiPixmaps); 0056 #endif 0057 0058 QApplication app(argc, argv); 0059 app.setStyle(new ProxyStyle); 0060 0061 #if APPIMAGE_BUILD 0062 initRCCIconTheme(); 0063 #endif 0064 0065 KLocalizedString::setApplicationDomain("heaptrack"); 0066 0067 KAboutData aboutData(QStringLiteral("heaptrack_gui"), i18n("Heaptrack GUI"), 0068 QStringLiteral(HEAPTRACK_VERSION_STRING), i18n("A visualizer for heaptrack data files."), 0069 KAboutLicense::LGPL, i18n("Copyright 2015, Milian Wolff <mail@milianw.de>"), QString(), 0070 QStringLiteral("mail@milianw.de")); 0071 0072 aboutData.addAuthor(i18n("Milian Wolff"), i18n("Original author, maintainer"), QStringLiteral("mail@milianw.de"), 0073 QStringLiteral("http://milianw.de")); 0074 0075 aboutData.setOrganizationDomain("kde.org"); 0076 #if KCOREADDONS_VERSION >= QT_VERSION_CHECK(5, 16, 0) 0077 aboutData.setDesktopFileName(QStringLiteral("org.kde.heaptrack")); 0078 #endif 0079 KAboutData::setApplicationData(aboutData); 0080 app.setWindowIcon(QIcon(QStringLiteral(":/512-heaptrack_app_icon.png"))); 0081 0082 QCommandLineParser parser; 0083 aboutData.setupCommandLine(&parser); 0084 0085 QCommandLineOption diffOption {{QStringLiteral("d"), QStringLiteral("diff")}, 0086 i18n("Base profile data to compare other files to."), 0087 QStringLiteral("<file>")}; 0088 parser.addOption(diffOption); 0089 QCommandLineOption suppressionsOption { 0090 {QStringLiteral("s"), QStringLiteral("suppressions")}, 0091 i18n("Load list of leak suppressions from the specified file. Specify one suppression per line, and start each " 0092 "line with 'leak:', i.e. use the LSAN suppression file format."), 0093 QStringLiteral("<file>")}; 0094 parser.addOption(suppressionsOption); 0095 QCommandLineOption disableEmbeddedSuppressionsOption { 0096 {QStringLiteral("disable-embedded-suppressions")}, 0097 i18n("Ignore suppression definitions that are embedded into the heaptrack data file. By default, heaptrack " 0098 "will copy the suppressions optionally defined via a `const char *__lsan_default_suppressions()` symbol " 0099 "in the debuggee application. These are then always applied when analyzing the data, unless this feature " 0100 "is explicitly disabled using this command line option.")}; 0101 parser.addOption(disableEmbeddedSuppressionsOption); 0102 QCommandLineOption disableBuiltinSuppressionsOption { 0103 {QStringLiteral("disable-builtin-suppressions")}, 0104 i18n( 0105 "Ignore suppression definitions that are built into heaptrack. By default, heaptrack will suppress certain " 0106 "known leaks in common system libraries.")}; 0107 parser.addOption(disableBuiltinSuppressionsOption); 0108 parser.addPositionalArgument(QStringLiteral("files"), i18n("Files to load"), i18n("[FILE...]")); 0109 0110 parser.process(app); 0111 aboutData.processCommandLine(&parser); 0112 0113 bool parsedOk = false; 0114 const auto suppressions = parseSuppressions(parser.value(suppressionsOption).toStdString(), &parsedOk); 0115 if (!parsedOk) { 0116 return 1; 0117 } 0118 0119 auto createWindow = [&]() -> MainWindow* { 0120 auto window = new MainWindow; 0121 window->setAttribute(Qt::WA_DeleteOnClose); 0122 window->setSuppressions(suppressions); 0123 window->setDisableEmbeddedSuppressions(parser.isSet(disableEmbeddedSuppressionsOption)); 0124 window->setDisableBuiltinSuppressions(parser.isSet(disableBuiltinSuppressionsOption)); 0125 window->show(); 0126 return window; 0127 }; 0128 0129 const auto files = parser.positionalArguments(); 0130 for (const auto& file : files) { 0131 createWindow()->loadFile(file, parser.value(diffOption)); 0132 } 0133 0134 if (files.isEmpty()) { 0135 createWindow(); 0136 } 0137 0138 #if APPIMAGE_BUILD 0139 // cleanup the environment when we are running from within the AppImage 0140 // to allow launching system applications using Qt without them loading 0141 // the bundled Qt we ship in the AppImage 0142 auto LD_LIBRARY_PATH = qgetenv("LD_LIBRARY_PATH"); 0143 LD_LIBRARY_PATH.remove(0, LD_LIBRARY_PATH.indexOf(':') + 1); 0144 qputenv("LD_LIBRARY_PATH", LD_LIBRARY_PATH); 0145 #endif 0146 0147 return app.exec(); 0148 }