File indexing completed on 2024-04-21 16:33:19
0001 /* 0002 SPDX-FileCopyrightText: 2000 Shie Erlich <krusader@users.sourceforge.net> 0003 SPDX-FileCopyrightText: 2000 Rafi Yanai <krusader@users.sourceforge.net> 0004 SPDX-FileCopyrightText: 2004-2022 Krusader Krew <https://krusader.org> 0005 0006 SPDX-License-Identifier: GPL-2.0-or-later 0007 */ 0008 0009 #include <csignal> 0010 #include <unistd.h> 0011 0012 // QtCore 0013 #include <QAbstractEventDispatcher> 0014 #include <QCommandLineOption> 0015 #include <QCommandLineParser> 0016 #include <QDebug> 0017 #include <QDir> 0018 #include <QEventLoop> 0019 #include <QStandardPaths> 0020 // QtGui 0021 #include <QPixmap> 0022 // QtDBus 0023 #include <QDBusConnectionInterface> 0024 #include <QDBusInterface> 0025 // QtWidgets 0026 #include <QApplication> 0027 #include <QSplashScreen> 0028 0029 #include <KConfigCore/KSharedConfig> 0030 #include <KCoreAddons/KAboutData> 0031 #include <KI18n/KLocalizedString> 0032 #include <KWidgetsAddons/KActionMenu> 0033 #include <KWindowSystem/KStartupInfo> 0034 0035 #include "../Archive/krarchandler.h" 0036 0037 #include "defaults.h" 0038 #include "icon.h" 0039 #include "krservices.h" 0040 #include "krslots.h" 0041 #include "krusader.h" 0042 #include "krusaderversion.h" 0043 #include "krusaderview.h" 0044 #include "panelmanager.h" 0045 0046 static const char *description = I18N_NOOP("Krusader\nTwin-Panel File Manager by KDE"); 0047 0048 static void sigterm_handler(int i) 0049 { 0050 fprintf(stderr, "Signal: %d\n", i); 0051 0052 QAbstractEventDispatcher *instance = QAbstractEventDispatcher::instance(); 0053 if (instance) 0054 instance->wakeUp(); 0055 QApplication::exit(-15); 0056 } 0057 0058 void openTabsRemote(QStringList tabs, bool left, const QString &appName) 0059 { 0060 // make sure left or right are not relative paths 0061 for (int i = 0; i != tabs.count(); i++) { 0062 tabs[i] = tabs[i].trimmed(); 0063 if (!tabs[i].startsWith('/') && tabs[i].indexOf(":/") < 0) 0064 tabs[i] = QDir::currentPath() + '/' + tabs[i]; 0065 } 0066 0067 QDBusInterface remoteApp("org.krusader", 0068 "/Instances/" + appName + (left ? "/left_manager" : "/right_manager"), 0069 "org.krusader.PanelManager", 0070 QDBusConnection::sessionBus()); 0071 QDBusReply<void> reply; 0072 if (remoteApp.isValid()) 0073 reply = remoteApp.call("newTabs", tabs); 0074 0075 if (!reply.isValid()) 0076 fprintf(stderr, "DBus Error: %s, %s\n", reply.error().name().toLocal8Bit().constData(), reply.error().message().toLocal8Bit().constData()); 0077 } 0078 0079 int main(int argc, char *argv[]) 0080 { 0081 // set global log message format 0082 qSetMessagePattern(KrServices::GLOBAL_MESSAGE_PATTERN); 0083 0084 // enable high dpi support 0085 QCoreApplication::setAttribute(Qt::AA_UseHighDpiPixmaps, true); 0086 QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling, true); 0087 0088 // prevent qt5-webengine crashing 0089 QApplication::setAttribute(Qt::AA_ShareOpenGLContexts); 0090 0091 // create the application and set application domain so that calls to i18n get strings from right place. 0092 QApplication app(argc, argv); 0093 KLocalizedString::setApplicationDomain("krusader"); 0094 0095 // init icon theme 0096 qDebug() << "System icon theme:" << QIcon::themeName(); 0097 // [WORKAROUND] setThemeName sets user theme in QIconLoader and allows to avoid Qt issues with invalid icon caching later 0098 // IMPORTANT: this must be done before the first QIcon::fromTheme / QIcon::hasThemeIcon call 0099 QIcon::setThemeName(QIcon::themeName()); 0100 0101 // ABOUT data information 0102 #ifdef RELEASE_NAME 0103 QString versionName = QStringLiteral("%1 \"%2\"").arg(VERSION, RELEASE_NAME); 0104 #else 0105 QString versionName = VERSION; 0106 #endif 0107 0108 #ifdef GIT_REVISION 0109 versionName += QString(" (gitrev: %1)").arg(GIT_REVISION); 0110 #endif 0111 0112 KAboutData aboutData(QStringLiteral("krusader"), 0113 (geteuid() ? i18n("Krusader") : i18n("Krusader - ROOT PRIVILEGES")), 0114 versionName, 0115 i18n(description), 0116 KAboutLicense::GPL_V2, 0117 i18n("© 2000-2003 Shie Erlich, Rafi Yanai\n© 2004-2022 Krusader Krew"), 0118 i18n("Feedback:\nhttps://forum.kde.org/viewforum.php?f=225"), 0119 QStringLiteral("https://krusader.org")); 0120 0121 aboutData.setOrganizationDomain(QByteArray("kde.org")); 0122 aboutData.setDesktopFileName(QStringLiteral("org.kde.krusader")); 0123 0124 aboutData.addAuthor(i18n("Davide Gianforte"), i18n("Developer"), QStringLiteral("davide@gengisdave.org"), nullptr); 0125 aboutData.addAuthor(i18n("Toni Asensi Esteve"), i18n("Developer"), QStringLiteral("toni.asensi@kdemail.net"), nullptr); 0126 aboutData.addAuthor(i18n("Nikita Melnichenko"), i18n("Developer"), QStringLiteral("nikita+kde@melnichenko.name"), nullptr); 0127 aboutData.addAuthor(i18n("Yuri Chornoivan"), i18n("Documentation"), QStringLiteral("yurchor@ukr.net"), nullptr); 0128 aboutData.addAuthor(i18n("Rafi Yanai"), i18n("Author (retired)"), QStringLiteral("yanai@users.sourceforge.net")); 0129 aboutData.addAuthor(i18n("Shie Erlich"), i18n("Author (retired)"), QStringLiteral("erlich@users.sourceforge.net")); 0130 aboutData.addAuthor(i18n("Csaba Karai"), i18n("Developer (retired)"), QStringLiteral("ckarai@users.sourceforge.net"), nullptr); 0131 aboutData.addAuthor(i18n("Heiner Eichmann"), i18n("Developer (retired)"), QStringLiteral("h.eichmann@gmx.de"), nullptr); 0132 aboutData.addAuthor(i18n("Jonas Bähr"), i18n("Developer (retired)"), QStringLiteral("jonas.baehr@web.de"), nullptr); 0133 aboutData.addAuthor(i18n("Václav Jůza"), i18n("Developer (retired)"), QStringLiteral("vaclavjuza@gmail.com"), nullptr); 0134 aboutData.addAuthor(i18n("Jan Lepper"), i18n("Developer (retired)"), QStringLiteral("jan_lepper@gmx.de"), nullptr); 0135 aboutData.addAuthor(i18n("Andrey Matveyakin"), i18n("Developer (retired)"), QStringLiteral("a.matveyakin@gmail.com"), nullptr); 0136 aboutData.addAuthor(i18n("Simon Persson"), i18n("Developer (retired)"), QStringLiteral("simon.persson@mykolab.com"), nullptr); 0137 aboutData.addAuthor(i18n("Alexander Bikadorov"), i18n("Developer (retired)"), QStringLiteral("alex.bikadorov@kdemail.net"), nullptr); 0138 aboutData.addAuthor(i18n("Martin Kostolný"), i18n("Developer (retired)"), QStringLiteral("clearmartin@gmail.com"), nullptr); 0139 aboutData.addAuthor(i18n("Dirk Eschler"), i18n("Webmaster (retired)"), QStringLiteral("deschler@users.sourceforge.net"), nullptr); 0140 aboutData.addAuthor(i18n("Frank Schoolmeesters"), 0141 i18n("Documentation and marketing coordinator (retired)"), 0142 QStringLiteral("frank_schoolmeesters@yahoo.com"), 0143 nullptr); 0144 aboutData.addAuthor(i18n("Richard Holt"), i18n("Documentation & Proofing (retired)"), QStringLiteral("richard.holt@gmail.com"), nullptr); 0145 aboutData.addAuthor(i18n("Matej Urbancic"), i18n("Marketing & Product Research (retired)"), QStringLiteral("matej.urban@gmail.com"), nullptr); 0146 aboutData.addCredit(i18n("kde.org"), i18n("Everyone involved in KDE"), nullptr, nullptr); 0147 aboutData.addCredit(i18n("l10n.kde.org"), i18n("KDE Translation Teams"), nullptr, nullptr); 0148 aboutData.addCredit(i18n("Jiří Paleček"), i18n("QA, bug-hunting, patches and general help"), QStringLiteral("jpalecek@web.de"), nullptr); 0149 aboutData.addCredit(i18n("Jiří Klement"), i18n("Important help in KDE 4 porting"), nullptr, nullptr); 0150 aboutData.addCredit(i18n("Andrew Neupokoev"), i18n("Killer Logo and Icons for Krusader (contest winner)"), QStringLiteral("doom-blue@yandex.ru"), nullptr); 0151 aboutData.addCredit(i18n("The UsefulArts Organization"), i18n("Icon for Krusader"), QStringLiteral("mail@usefularts.org"), nullptr); 0152 aboutData.addCredit(i18n("Gábor Lehel"), i18n("Viewer module for 3rd Hand"), QStringLiteral("illissius@gmail.com"), nullptr); 0153 aboutData.addCredit(i18n("Mark Eatough"), i18n("Handbook Proof-Reader"), QStringLiteral("markeatough@yahoo.com"), nullptr); 0154 aboutData.addCredit(i18n("Jan Halasa"), i18n("The old Bookmark Module"), QStringLiteral("xhalasa@fi.muni.cz"), nullptr); 0155 aboutData.addCredit(i18n("Hans Löffler"), i18n("Dir history button"), nullptr, nullptr); 0156 aboutData.addCredit(i18n("Szombathelyi György"), i18n("ISO KIO slave"), nullptr, nullptr); 0157 aboutData.addCredit(i18n("Jan Willem van de Meent (Adios)"), i18n("Icons for Krusader"), QStringLiteral("janwillem@lorentz.leidenuniv.nl"), nullptr); 0158 aboutData.addCredit(i18n("Mikolaj Machowski"), i18n("Usability and QA"), QStringLiteral("<mikmach@wp.pl>"), nullptr); 0159 aboutData.addCredit(i18n("Cristi Dumitrescu"), i18n("QA, bug-hunting, patches and general help"), QStringLiteral("cristid@chip.ro"), nullptr); 0160 aboutData.addCredit(i18n("Aurelien Gateau"), i18n("patch for KViewer"), QStringLiteral("aurelien.gateau@free.fr"), nullptr); 0161 aboutData.addCredit(i18n("Milan Brabec"), i18n("the first patch ever!"), QStringLiteral("mbrabec@volny.cz"), nullptr); 0162 aboutData.addCredit(i18n("Asim Husanovic"), i18n("Bosnian translation"), QStringLiteral("asim@megatel.ba"), nullptr); 0163 aboutData.addCredit(i18n("Doutor Zero"), i18n("Brazilian Portuguese translation"), QStringLiteral("doutor.zero@gmail.com"), nullptr); 0164 aboutData.addCredit(i18n("Milen Ivanov"), i18n("Bulgarian translation"), QStringLiteral("milen.ivanov@abv.bg"), nullptr); 0165 aboutData.addCredit(i18n("Quim Perez"), i18n("Catalan translation"), QStringLiteral("noguer@osona.com"), nullptr); 0166 aboutData.addCredit(i18n("Jinghua Luo"), i18n("Chinese Simplified translation"), QStringLiteral("luojinghua@msn.com"), nullptr); 0167 aboutData.addCredit(i18n("Mitek"), i18n("Old Czech translation"), QStringLiteral("mitek@email.cz"), nullptr); 0168 aboutData.addCredit(i18n("Martin Sixta"), i18n("Old Czech translation"), QStringLiteral("lukumo84@seznam.cz"), nullptr); 0169 aboutData.addCredit(i18n("Vaclav Jůza"), i18n("Czech translation"), QStringLiteral("VaclavJuza@gmail.com"), nullptr); 0170 aboutData.addCredit(i18n("Anders Bruun Olsen"), i18n("Old Danish translation"), QStringLiteral("anders@bruun-olsen.net"), nullptr); 0171 aboutData.addCredit(i18n("Peter H. Sorensen"), i18n("Danish translation"), QStringLiteral("peters@skydebanen.net"), nullptr); 0172 aboutData.addCredit(i18n("Frank Schoolmeesters"), i18n("Dutch translation"), QStringLiteral("frank_schoolmeesters@yahoo.com"), nullptr); 0173 aboutData.addCredit(i18n("Rene-Pierre Lehmann"), i18n("Old French translation"), QStringLiteral("ripi@lepi.org"), nullptr); 0174 aboutData.addCredit(i18n("David Guillerm"), i18n("French translation"), QStringLiteral("dguillerm@gmail.com"), nullptr); 0175 aboutData.addCredit(i18n("Christoph Thielecke"), i18n("Old German translation"), QStringLiteral("crissi99@gmx.de"), nullptr); 0176 aboutData.addCredit(i18n("Dirk Eschler"), i18n("German translation"), QStringLiteral("deschler@users.sourceforge.net"), nullptr); 0177 aboutData.addCredit(i18n("Spiros Georgaras"), i18n("Greek translation"), QStringLiteral("sngeorgaras@gmail.com"), nullptr); 0178 aboutData.addCredit(i18n("Kukk Zoltan"), i18n("Old Hungarian translation"), QStringLiteral("kukkzoli@freemail.hu"), nullptr); 0179 aboutData.addCredit(i18n("Arpad Biro"), i18n("Hungarian translation"), QStringLiteral("biro_arpad@yahoo.com"), nullptr); 0180 aboutData.addCredit(i18n("Giuseppe Bordoni"), i18n("Italian translation"), QStringLiteral("geppo@geppozone.com"), nullptr); 0181 aboutData.addCredit(i18n("Hideki Kimura"), i18n("Japanese translation"), QStringLiteral("hangyo1973@gmail.com"), nullptr); 0182 aboutData.addCredit(i18n("UTUMI Hirosi"), i18n("Old Japanese translation"), QStringLiteral("utuhiro@mx12.freecom.ne.jp"), nullptr); 0183 aboutData.addCredit(i18n("Dovydas Sankauskas"), i18n("Lithuanian translation"), QStringLiteral("laisve@gmail.com"), nullptr); 0184 aboutData.addCredit(i18n("Bruno Queiros"), i18n("Portuguese translation"), QStringLiteral("brunoqueiros@portugalmail.com"), nullptr); 0185 aboutData.addCredit(i18n("Lukasz Janyst"), i18n("Old Polish translation"), QStringLiteral("ljan@wp.pl"), nullptr); 0186 aboutData.addCredit(i18n("Pawel Salawa"), i18n("Polish translation"), QStringLiteral("boogie@myslenice.one.pl"), nullptr); 0187 aboutData.addCredit(i18n("Tomek Grzejszczyk"), i18n("Polish translation"), QStringLiteral("tgrzej@onet.eu"), nullptr); 0188 aboutData.addCredit(i18n("Dmitry A. Bugay"), i18n("Russian translation"), QStringLiteral("sam@vhnet.ru"), nullptr); 0189 aboutData.addCredit(i18n("Dmitry Chernyak"), i18n("Old Russian translation"), QStringLiteral("chernyak@mail.ru"), nullptr); 0190 aboutData.addCredit(i18n("Sasa Tomic"), i18n("Serbian translation"), QStringLiteral("stomic@gmx.net"), nullptr); 0191 aboutData.addCredit(i18n("Zdenko Podobný and Ondrej Pačay (Yogi)"), i18n("Slovak translation"), QStringLiteral("zdenop@gmail.com"), nullptr); 0192 aboutData.addCredit(i18n("Matej Urbancic"), i18n("Slovenian translation"), QStringLiteral("matej.urban@gmail.com"), nullptr); 0193 aboutData.addCredit(i18n("Rafael Munoz"), i18n("Old Spanish translation"), QStringLiteral("muror@hotpop.com"), nullptr); 0194 aboutData.addCredit(i18n("Alejandro Araiza Alvarado"), i18n("Spanish translation"), QStringLiteral("mebrelith@gmail.com"), nullptr); 0195 aboutData.addCredit(i18n("Erik Johanssen"), i18n("Old Swedish translation"), QStringLiteral("erre@telia.com"), nullptr); 0196 aboutData.addCredit(i18n("Anders Linden"), i18n("Old Swedish translation"), QStringLiteral("connyosis@gmx.net"), nullptr); 0197 aboutData.addCredit(i18n("Peter Landgren"), i18n("Swedish translation"), QStringLiteral("peter.talken@telia.com"), nullptr); 0198 aboutData.addCredit(i18n("Bekir Sonat"), i18n("Turkish translation"), QStringLiteral("bekirsonat@kde.org.tr"), nullptr); 0199 aboutData.addCredit(i18n("Ivan Petrouchtchak"), i18n("Ukrainian translation"), QStringLiteral("connyosis@gmx.net"), nullptr); 0200 aboutData.addCredit(i18n("Seongnam Jee"), i18n("Korean translation"), QStringLiteral("snjee@intellicam.com"), nullptr); 0201 0202 // This will call QCoreApplication::setApplicationName, etc for us by using info in the KAboutData instance. 0203 // The only thing not called for us is setWindowIcon(), which is why we do it ourselves here. 0204 KAboutData::setApplicationData(aboutData); 0205 app.setWindowIcon(Icon(Krusader::appIconName())); 0206 0207 // Command line arguments ... 0208 QCommandLineParser parser; 0209 aboutData.setupCommandLine(&parser); 0210 parser.addOption(QCommandLineOption(QStringList() << QLatin1String("left"), i18n("Start left panel at <path>"), QLatin1String("path"))); 0211 parser.addOption(QCommandLineOption(QStringList() << QLatin1String("right"), i18n("Start right panel at <path>"), QLatin1String("path"))); 0212 parser.addOption(QCommandLineOption(QStringList() << QLatin1String("profile"), i18n("Load this profile on startup"), QLatin1String("panel-profile"))); 0213 parser.addOption(QCommandLineOption(QStringList() << "d" << QLatin1String("debug"), i18n("Enable debug output"))); 0214 parser.addPositionalArgument(QLatin1String("url"), i18n("URL to open")); 0215 0216 // check for command line arguments 0217 parser.process(app); 0218 aboutData.processCommandLine(&parser); 0219 0220 // set global message handler 0221 KrServices::setGlobalKrMessageHandler(parser.isSet("debug")); 0222 0223 KConfigGroup cfg(KSharedConfig::openConfig(), QStringLiteral("Look&Feel")); 0224 bool singleInstanceMode = cfg.readEntry("Single Instance Mode", _SingleInstanceMode); 0225 0226 QString url; 0227 if (!parser.positionalArguments().isEmpty()) { 0228 url = parser.positionalArguments().first(); 0229 } 0230 0231 QString appName = "krusader"; 0232 if (!singleInstanceMode) 0233 appName += QString("%1").arg(getpid()); 0234 0235 if (!QDBusConnection::sessionBus().isConnected()) { 0236 fprintf(stderr, 0237 "Cannot connect to the D-BUS session bus.\n" 0238 "To start it, run:\n" 0239 "\teval `dbus-launch --auto-syntax`\n"); 0240 } 0241 0242 if (singleInstanceMode) { 0243 QDBusInterface remoteApp("org.krusader", "/Instances/" + appName, "org.krusader.Instance", QDBusConnection::sessionBus()); 0244 QDBusReply<bool> reply; 0245 if (remoteApp.isValid()) 0246 reply = remoteApp.call("isRunning"); 0247 0248 if (!reply.isValid() && reply.error().type() != QDBusError::ServiceUnknown && reply.error().type() != QDBusError::UnknownObject) 0249 fprintf(stderr, "DBus Error: %s, %s\n", reply.error().name().toLocal8Bit().constData(), reply.error().message().toLocal8Bit().constData()); 0250 0251 if (reply.isValid() && (bool)reply) { 0252 KStartupInfo::appStarted(); 0253 if (parser.isSet("left")) 0254 openTabsRemote(parser.value("left").split(','), true, appName); 0255 if (parser.isSet("right")) 0256 openTabsRemote(parser.value("right").split(','), false, appName); 0257 if (!url.isEmpty()) { 0258 reply = remoteApp.call("openUrl", url); 0259 if (!reply.isValid()) 0260 fprintf(stderr, "DBus Error: %s, %s\n", reply.error().name().toLocal8Bit().constData(), reply.error().message().toLocal8Bit().constData()); 0261 } 0262 return 0; 0263 } 0264 } 0265 0266 // splash screen - if the user wants one 0267 QSplashScreen *splash = nullptr; 0268 { // don't remove bracket 0269 KConfigGroup cfg(KSharedConfig::openConfig(), QStringLiteral("Look&Feel")); 0270 if (cfg.readEntry("Show splashscreen", _ShowSplashScreen)) { 0271 QString splashFilename = QStandardPaths::locate(QStandardPaths::DataLocation, QStringLiteral("splash.png")); 0272 QPixmap pixmap(splashFilename); 0273 if (!pixmap.isNull()) { 0274 splash = new QSplashScreen(pixmap); 0275 splash->show(); 0276 } 0277 } 0278 } // don't remove bracket 0279 0280 Krusader::AppName = appName; 0281 auto *krusader = new Krusader(parser); 0282 0283 if (!url.isEmpty()) 0284 krusader->openUrl(url); 0285 0286 QDBusConnection dbus = QDBusConnection::sessionBus(); 0287 if (!dbus.interface()->isServiceRegistered("org.krusader") && !dbus.registerService("org.krusader")) { 0288 fprintf(stderr, "DBus Error: %s, %s\n", dbus.lastError().name().toLocal8Bit().constData(), dbus.lastError().message().toLocal8Bit().constData()); 0289 } 0290 if (!dbus.registerObject("/Instances/" + appName, krusader, QDBusConnection::ExportScriptableSlots)) { 0291 fprintf(stderr, "DBus Error: %s, %s\n", dbus.lastError().name().toLocal8Bit().constData(), dbus.lastError().message().toLocal8Bit().constData()); 0292 } 0293 if (!dbus.registerObject("/Instances/" + appName + "/left_manager", LEFT_MNG, QDBusConnection::ExportScriptableSlots)) { 0294 fprintf(stderr, "DBus Error: %s, %s\n", dbus.lastError().name().toLocal8Bit().constData(), dbus.lastError().message().toLocal8Bit().constData()); 0295 } 0296 if (!dbus.registerObject("/Instances/" + appName + "/right_manager", RIGHT_MNG, QDBusConnection::ExportScriptableSlots)) { 0297 fprintf(stderr, "DBus Error: %s, %s\n", dbus.lastError().name().toLocal8Bit().constData(), dbus.lastError().message().toLocal8Bit().constData()); 0298 } 0299 0300 // catching SIGTERM, SIGHUP, SIGQUIT 0301 signal(SIGTERM, sigterm_handler); 0302 signal(SIGPIPE, sigterm_handler); 0303 signal(SIGHUP, sigterm_handler); 0304 0305 QObject::connect(&app, &QGuiApplication::applicationStateChanged, SLOTS, &KrSlots::applicationStateChanged); 0306 0307 // hide splashscreen 0308 if (splash) { 0309 splash->finish(krusader); 0310 delete splash; 0311 } 0312 // let's go. 0313 return app.exec(); 0314 }