File indexing completed on 2024-05-19 05:41:55

0001 // desktopapp.m.cpp                                                  -*-C++-*-
0002 
0003 /*
0004 // Copyright 2023 Codethink Ltd <codethink@codethink.co.uk>
0005 // SPDX-License-Identifier: Apache-2.0
0006 //
0007 // Licensed under the Apache License, Version 2.0 (the "License");
0008 // you may not use this file except in compliance with the License.
0009 // You may obtain a copy of the License at
0010 //
0011 //     http://www.apache.org/licenses/LICENSE-2.0
0012 //
0013 // Unless required by applicable law or agreed to in writing, software
0014 // distributed under the License is distributed on an "AS IS" BASIS,
0015 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
0016 // See the License for the specific language governing permissions and
0017 // limitations under the License.
0018 */
0019 
0020 #include <QApplication>
0021 #include <QByteArray>
0022 #include <QCommandLineOption>
0023 #include <QCommandLineParser>
0024 #include <QDateTime>
0025 #include <QStandardPaths>
0026 #include <QStyle>
0027 #include <QStyleFactory>
0028 
0029 #include <KAboutData>
0030 #include <KCrash>
0031 #include <KLocalizedString>
0032 
0033 #include <mainwindow.h>
0034 
0035 #include <cstdlib>
0036 #include <filesystem>
0037 #include <iostream>
0038 
0039 #include <QDebug>
0040 
0041 #include <codevis_dbus_interface.h>
0042 #include <ct_lvtldr_nodestorage.h>
0043 #include <ct_lvtmdl_debugmodel.h>
0044 #include <ct_lvtplg_pluginmanager.h>
0045 #include <ct_lvtqtc_undo_manager.h>
0046 
0047 #include <preferences.h>
0048 
0049 int main(int argc, char *argv[])
0050 {
0051     // This should be called before the creation of the QApplication
0052     QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
0053 
0054 #if (QT_VERSION <= QT_VERSION_CHECK(6, 0, 0))
0055     QCoreApplication::setAttribute(Qt::AA_DisableWindowContextHelpButton);
0056 #endif
0057 
0058     QApplication app(argc, argv);
0059     KCrash::initialize();
0060 
0061     // setup translation string domain for the i18n calls
0062     KLocalizedString::setApplicationDomain("codevis");
0063     // create a KAboutData object to use for setting the application metadata
0064     KAboutData aboutData("codevis",
0065                          i18n("Codevis"),
0066                          "0.1",
0067                          i18n("Visualize and extract information from Large Codebases"),
0068                          KAboutLicense::BSDL, // Apache, but KAboutLicense lacks that.
0069                          i18n("Copyright 2023 KDE"),
0070                          QString(),
0071                          "https://invent.kde.org/sdk/codevis");
0072 
0073     // overwrite default-generated values of organizationDomain & desktopFileName
0074     aboutData.setOrganizationDomain("kde.org");
0075     aboutData.setDesktopFileName("org.kde.codevis");
0076 
0077     aboutData.addAuthor(i18n("Tomaz Canabrava"), i18n("Developer"), QStringLiteral("tcanabrava@kde.org"));
0078     aboutData.addAuthor(i18n("Tarcisio Fischer"),
0079                         i18n("Developer"),
0080                         QStringLiteral("tarcisio.fischer@codethink.co.uk"));
0081     aboutData.addAuthor(i18n("Richard Dale"), i18n("Developer"), QStringLiteral("richard.dale@codethink.co.uk"));
0082     aboutData.addAuthor(i18n("Tom Eccles"), i18n("Developer"));
0083     aboutData.addAuthor(i18n("Poppy Singleton"), i18n("Developer"));
0084 
0085     // set the application metadata
0086     KAboutData::setApplicationData(aboutData);
0087 
0088     MainWindow::initializeResource();
0089 
0090     // in GUI apps set the window icon manually, not covered by KAboutData
0091     // needed for environments where the icon name is not extracted from
0092     // the information in the application's desktop file
0093     QApplication::setWindowIcon(QIcon::fromTheme(QStringLiteral("codevis")));
0094 
0095     const QString folderPath = QStandardPaths::writableLocation(QStandardPaths::DocumentsLocation) + QDir::separator()
0096         + qApp->applicationName() // Folder
0097         + QDir::separator();
0098 
0099     QDir dir(folderPath);
0100     if (!dir.exists()) {
0101         bool created = dir.mkpath(folderPath);
0102         if (!created) {
0103             qDebug() << "Could not create the folder for crash dumps.";
0104         }
0105     }
0106 
0107     // Ensure standard number formatting is used for float and string conversions
0108     if (setlocale(LC_NUMERIC, "C") == nullptr) {
0109         std::cerr << "Failed to set locale" << std::endl;
0110         return EXIT_FAILURE;
0111     }
0112 
0113     QCommandLineParser parser;
0114     aboutData.setupCommandLine(&parser);
0115 
0116     QCommandLineOption inputFile(QStringList({"project-file"}),
0117                                  QObject::tr("[file path] a .lks file"),
0118                                  QObject::tr("file"));
0119 
0120     QCommandLineOption crashInfo(QStringList({"crash-info"}), QObject::tr("show the saved backtraces and exits."));
0121 
0122     QCommandLineOption resetSettings(
0123         QStringList({"reset-settings"}),
0124         QObject::tr("Reset the internal settings to vendor defaults and opens a fresh instance."));
0125 
0126     QCommandLineOption resetProject(
0127         QStringList({"reset-last-project"}),
0128         QObject::tr("Resets the last project, this can be used if the project makes the application crash."));
0129 
0130     parser.addOption(inputFile);
0131     parser.addOption(crashInfo);
0132     parser.addOption(resetSettings);
0133     parser.addOption(resetProject);
0134 
0135     parser.process(app);
0136     aboutData.processCommandLine(&parser);
0137 
0138     if (parser.isSet(crashInfo)) {
0139         qInfo() << "Current Crash Dumps on folder:" << dir.absolutePath();
0140         const auto files = dir.entryList(QDir::Filter::NoDotAndDotDot);
0141         for (const QString& file : std::as_const(files)) {
0142             qInfo() << file;
0143         }
0144         return 0;
0145     }
0146 
0147     if (parser.isSet(resetSettings)) {
0148         Preferences::self()->setDefaults();
0149     }
0150 
0151     if (parser.isSet(resetProject)) {
0152         Preferences::setLastDocument("");
0153     }
0154 
0155     Q_INIT_RESOURCE(resources);
0156 
0157     // We need the debug model early to catch every possible debug message.
0158     Codethink::lvtmdl::DebugModel debugModel;
0159     qInstallMessageHandler(Codethink::lvtmdl::DebugModel::debugMessageHandler);
0160 
0161     auto pluginSearchPaths = Preferences::pluginSearchPaths();
0162 
0163     // Path of plugins installed by GetNewStuff.
0164     pluginSearchPaths.append(QStandardPaths::writableLocation(QStandardPaths::AppLocalDataLocation) + "/plugins");
0165 
0166     auto pluginManager = Codethink::lvtplg::PluginManager{};
0167     pluginManager.loadPlugins(pluginSearchPaths);
0168     pluginManager.callHooksSetupPlugin();
0169 
0170     auto sharedNodeStorage = Codethink::lvtldr::NodeStorage{};
0171     auto undoManager = Codethink::lvtqtc::UndoManager{};
0172     auto *mWindow = new MainWindow(sharedNodeStorage, &pluginManager, &undoManager, &debugModel);
0173 
0174     CodeVisDBusInterface dbusInterface(*mWindow); // cppcheck-suppress unreadVariable
0175 
0176     if (parser.isSet(inputFile)) {
0177         const bool isOpen = mWindow->openProjectFromPath(parser.value(inputFile));
0178         (void) isOpen; // NOLINT
0179     } else {
0180         const QString lastProject = Preferences::lastDocument();
0181         if (lastProject.size()) {
0182             const bool isOpen = mWindow->openProjectFromPath(lastProject);
0183             (void) isOpen; // NOLINT
0184         }
0185     }
0186 
0187     mWindow->show();
0188 
0189     int retValue = QApplication::exec();
0190 
0191     Preferences::self()->save();
0192     pluginManager.callHooksTeardownPlugin();
0193     return retValue;
0194 }