Changeset View
Changeset View
Standalone View
Standalone View
src/Main.cpp
Show All 30 Lines | |||||
31 | #include <KAboutData> | 31 | #include <KAboutData> | ||
32 | #include <KDBusService> | 32 | #include <KDBusService> | ||
33 | #include <KLocalizedString> | 33 | #include <KLocalizedString> | ||
34 | 34 | | |||
35 | int main(int argc, char **argv) | 35 | int main(int argc, char **argv) | ||
36 | { | 36 | { | ||
37 | // set up the application | 37 | // set up the application | ||
38 | 38 | | |||
39 | QApplication lApp(argc, argv); | 39 | QApplication app(argc, argv); | ||
40 | 40 | | |||
41 | lApp.setAttribute(Qt::AA_DontCreateNativeWidgetSiblings, true); | 41 | app.setAttribute(Qt::AA_DontCreateNativeWidgetSiblings, true); | ||
anthonyfieroni: `s_needToDeleteQApplication` is not needed any more. | |||||
42 | lApp.setAttribute(Qt::AA_UseHighDpiPixmaps, true); | 42 | app.setAttribute(Qt::AA_UseHighDpiPixmaps, true); | ||
anthonyfieroni: Deleting application allocated on stack is UB. Keep app on heap. | |||||
43 | 43 | | |||
44 | KLocalizedString::setApplicationDomain("spectacle"); | 44 | KLocalizedString::setApplicationDomain("spectacle"); | ||
45 | QCoreApplication::setOrganizationDomain(QStringLiteral("org.kde")); | ||||
45 | 46 | | |||
46 | KAboutData aboutData(QStringLiteral("spectacle"), | 47 | KAboutData aboutData(QStringLiteral("spectacle"), | ||
47 | i18n("Spectacle"), | 48 | i18n("Spectacle"), | ||
48 | QStringLiteral(SPECTACLE_VERSION), | 49 | QStringLiteral(SPECTACLE_VERSION), | ||
49 | i18n("KDE Screenshot Utility"), | 50 | i18n("KDE Screenshot Utility"), | ||
50 | KAboutLicense::GPL_V2, | 51 | KAboutLicense::GPL_V2, | ||
51 | i18n("(C) 2015 Boudhayan Gupta")); | 52 | i18n("(C) 2015 Boudhayan Gupta")); | ||
52 | aboutData.addAuthor(QStringLiteral("Boudhayan Gupta"), QString(), QStringLiteral("bgupta@kde.org")); | 53 | aboutData.addAuthor(QStringLiteral("Boudhayan Gupta"), QString(), QStringLiteral("bgupta@kde.org")); | ||
53 | aboutData.addAuthor(QStringLiteral("David Redondo"), QString(), QStringLiteral("kde@david-redondo.de")); | 54 | aboutData.addAuthor(QStringLiteral("David Redondo"), QString(), QStringLiteral("kde@david-redondo.de")); | ||
54 | aboutData.setTranslator(i18nc("NAME OF TRANSLATORS", "Your names"), i18nc("EMAIL OF TRANSLATORS", "Your emails")); | 55 | aboutData.setTranslator(i18nc("NAME OF TRANSLATORS", "Your names"), i18nc("EMAIL OF TRANSLATORS", "Your emails")); | ||
55 | KAboutData::setApplicationData(aboutData); | 56 | KAboutData::setApplicationData(aboutData); | ||
56 | lApp.setWindowIcon(QIcon::fromTheme(QStringLiteral("spectacle"))); | 57 | app.setWindowIcon(QIcon::fromTheme(QStringLiteral("spectacle"))); | ||
57 | 58 | | |||
58 | // set up the command line options parser | 59 | SpectacleCore lCore; | ||
59 | 60 | | |||
60 | QCommandLineParser lCmdLineParser; | 61 | QCommandLineParser lCmdLineParser; | ||
61 | aboutData.setupCommandLine(&lCmdLineParser); | 62 | aboutData.setupCommandLine(&lCmdLineParser); | ||
63 | lCore.populateCommandLineParser(&lCmdLineParser); | ||||
62 | 64 | | |||
63 | lCmdLineParser.addOptions({ | 65 | // first parsing for help-about | ||
64 | {{QStringLiteral("f"), QStringLiteral("fullscreen")}, i18n("Capture the entire desktop (default)")}, | 66 | lCmdLineParser.process(app.arguments()); | ||
65 | {{QStringLiteral("m"), QStringLiteral("current")}, i18n("Capture the current monitor")}, | | |||
66 | {{QStringLiteral("a"), QStringLiteral("activewindow")}, i18n("Capture the active window")}, | | |||
67 | {{QStringLiteral("u"), QStringLiteral("windowundercursor")}, i18n("Capture the window currently under the cursor, including parents of pop-up menus")}, | | |||
68 | {{QStringLiteral("t"), QStringLiteral("transientonly")}, i18n("Capture the window currently under the cursor, excluding parents of pop-up menus")}, | | |||
69 | {{QStringLiteral("r"), QStringLiteral("region")}, i18n("Capture a rectangular region of the screen")}, | | |||
70 | {{QStringLiteral("g"), QStringLiteral("gui")}, i18n("Start in GUI mode (default)")}, | | |||
71 | {{QStringLiteral("b"), QStringLiteral("background")}, i18n("Take a screenshot and exit without showing the GUI")}, | | |||
72 | {{QStringLiteral("s"), QStringLiteral("dbus")}, i18n("Start in DBus-Activation mode")}, | | |||
73 | {{QStringLiteral("n"), QStringLiteral("nonotify")}, i18n("In background mode, do not pop up a notification when the screenshot is taken")}, | | |||
74 | {{QStringLiteral("o"), QStringLiteral("output")}, i18n("In background mode, save image to specified file"), QStringLiteral("fileName")}, | | |||
75 | {{QStringLiteral("d"), QStringLiteral("delay")}, i18n("In background mode, delay before taking the shot (in milliseconds)"), QStringLiteral("delayMsec")}, | | |||
76 | {{QStringLiteral("c"), QStringLiteral("clipboard")}, i18n("In background mode, copy screenshot to clipboard")}, | | |||
77 | {{QStringLiteral("w"), QStringLiteral("onclick")}, i18n("Wait for a click before taking screenshot. Invalidates delay")} | | |||
78 | }); | | |||
79 | | ||||
80 | lCmdLineParser.process(lApp); | | |||
81 | aboutData.processCommandLine(&lCmdLineParser); | 67 | aboutData.processCommandLine(&lCmdLineParser); | ||
82 | 68 | | |||
83 | // extract the capture mode | 69 | // and new-instance | ||
70 | if (lCmdLineParser.isSet(QStringLiteral("new-instance"))){ | ||||
71 | lCore.init(); | ||||
84 | 72 | | |||
85 | Spectacle::CaptureMode lCaptureMode = Spectacle::CaptureMode::AllScreens; | 73 | QObject::connect(&lCore, &SpectacleCore::allDone, &app, &QCoreApplication::quit, Qt::QueuedConnection); | ||
86 | if (lCmdLineParser.isSet(QStringLiteral("current"))) { | | |||
87 | lCaptureMode = Spectacle::CaptureMode::CurrentScreen; | | |||
88 | } else if (lCmdLineParser.isSet(QStringLiteral("activewindow"))) { | | |||
89 | lCaptureMode = Spectacle::CaptureMode::ActiveWindow; | | |||
90 | } else if (lCmdLineParser.isSet(QStringLiteral("region"))) { | | |||
91 | lCaptureMode = Spectacle::CaptureMode::RectangularRegion; | | |||
92 | } else if (lCmdLineParser.isSet(QStringLiteral("windowundercursor"))) { | | |||
93 | lCaptureMode = Spectacle::CaptureMode::TransientWithParent; | | |||
94 | } else if (lCmdLineParser.isSet(QStringLiteral("transientonly"))) { | | |||
95 | lCaptureMode = Spectacle::CaptureMode::WindowUnderCursor; | | |||
96 | } | | |||
97 | 74 | | |||
98 | // are we running in background or dbus mode? | 75 | // fire it up | ||
99 | 76 | lCore.onActivateRequested(app.arguments(), QStringLiteral()); | |||
100 | SpectacleCore::StartMode lStartMode = SpectacleCore::StartMode::Gui; | | |||
101 | bool lNotify = true; | | |||
102 | bool lCopyToClipboard = false; | | |||
103 | qint64 lDelayMsec = 0; | | |||
104 | QString lFileName = QString(); | | |||
105 | | ||||
106 | if (lCmdLineParser.isSet(QStringLiteral("background"))) { | | |||
107 | lStartMode = SpectacleCore::StartMode::Background; | | |||
108 | } else if (lCmdLineParser.isSet(QStringLiteral("dbus"))) { | | |||
109 | lStartMode = SpectacleCore::StartMode::DBus; | | |||
110 | } | | |||
111 | | ||||
112 | switch(lStartMode) { | | |||
113 | case SpectacleCore::StartMode::Background: | | |||
114 | if (lCmdLineParser.isSet(QStringLiteral("nonotify"))) { | | |||
115 | lNotify = false; | | |||
116 | } | | |||
117 | | ||||
118 | if (lCmdLineParser.isSet(QStringLiteral("output"))) { | | |||
119 | lFileName = lCmdLineParser.value(QStringLiteral("output")); | | |||
120 | } | | |||
121 | | ||||
122 | if (lCmdLineParser.isSet(QStringLiteral("delay"))) { | | |||
123 | bool lParseOk = false; | | |||
124 | qint64 lDelayValue = lCmdLineParser.value(QStringLiteral("delay")).toLongLong(&lParseOk); | | |||
125 | if (lParseOk) { | | |||
126 | lDelayMsec = lDelayValue; | | |||
127 | } | | |||
128 | } | | |||
129 | | ||||
130 | if (lCmdLineParser.isSet(QStringLiteral("onclick"))) { | | |||
131 | lDelayMsec = -1; | | |||
132 | } | | |||
133 | 77 | | |||
134 | if (lCmdLineParser.isSet(QStringLiteral("clipboard"))) { | 78 | return app.exec(); | ||
135 | lCopyToClipboard = true; | | |||
136 | } | 79 | } | ||
137 | 80 | | |||
138 | lApp.setQuitOnLastWindowClosed(false); | 81 | // Ensure that we only launch a new instance if we need to | ||
139 | break; | 82 | // If there is already an instance running, we will quit here | ||
140 | case SpectacleCore::StartMode::DBus: | 83 | // and activateRequested signal is triggered | ||
141 | lApp.setQuitOnLastWindowClosed(false); | 84 | // For some reason this does not work properly if behind an if | ||
142 | break; | 85 | KDBusService service(KDBusService::Unique, &lCore); | ||
davidre: whitespace | |||||
143 | case SpectacleCore::StartMode::Gui: | | |||
144 | break; | | |||
145 | } | | |||
146 | 86 | | |||
Just use second function atexit(deleteQApplication); KDBusService service(KDBusService::Unique, lCore); // it does not need to be heap allocation atexit(noopfunc); anthonyfieroni: Just use second function
```
atexit(deleteQApplication);
KDBusService service(KDBusService… | |||||
147 | // release the kraken | 87 | // Delay initialisation after we now we are in the single instance or new-instance was passed, to avoid doing it each time spectacle executable is called | ||
88 | lCore.init(); | ||||
148 | 89 | | |||
149 | SpectacleCore lCore(lStartMode, lCaptureMode, lFileName, lDelayMsec, lNotify, lCopyToClipboard); | 90 | // set up the KDBusService activateRequested slot | ||
150 | QObject::connect(&lCore, &SpectacleCore::allDone, qApp, &QApplication::quit); | 91 | QObject::connect(&service, &KDBusService::activateRequested, &lCore, &SpectacleCore::onActivateRequested); | ||
92 | QObject::connect(&lCore, &SpectacleCore::allDone, &app, &QCoreApplication::quit, Qt::QueuedConnection); | ||||
151 | QObject::connect(qApp, &QApplication::aboutToQuit, Settings::self(), &Settings::save); | 93 | QObject::connect(qApp, &QApplication::aboutToQuit, Settings::self(), &Settings::save); | ||
152 | 94 | | |||
153 | // create the dbus connections | 95 | // create the dbus connections | ||
154 | | ||||
155 | new KDBusService(KDBusService::Multiple, &lCore); | | |||
156 | SpectacleDBusAdapter *lDBusAdapter = new SpectacleDBusAdapter(&lCore); | 96 | SpectacleDBusAdapter *lDBusAdapter = new SpectacleDBusAdapter(&lCore); | ||
157 | QObject::connect(&lCore, &SpectacleCore::grabFailed, lDBusAdapter, &SpectacleDBusAdapter::ScreenshotFailed); | 97 | QObject::connect(&lCore, &SpectacleCore::grabFailed, lDBusAdapter, &SpectacleDBusAdapter::ScreenshotFailed); | ||
158 | QObject::connect(ExportManager::instance(), &ExportManager::imageSaved, &lCore, [&](const QUrl &savedAt) { | 98 | QObject::connect(ExportManager::instance(), &ExportManager::imageSaved, &lCore, [&](const QUrl &savedAt) { | ||
159 | emit lDBusAdapter->ScreenshotTaken(savedAt.toLocalFile()); | 99 | lDBusAdapter->ScreenshotTaken(savedAt.toLocalFile()); | ||
160 | }); | 100 | }); | ||
161 | QDBusConnection::sessionBus().registerObject(QStringLiteral("/"), &lCore); | 101 | QDBusConnection::sessionBus().registerObject(QStringLiteral("/"), &lCore); | ||
162 | QDBusConnection::sessionBus().registerService(QStringLiteral("org.kde.Spectacle")); | 102 | QDBusConnection::sessionBus().registerService(QStringLiteral("org.kde.Spectacle")); | ||
163 | 103 | | |||
164 | // fire it up | 104 | // fire it up | ||
105 | lCore.onActivateRequested(app.arguments(), QStringLiteral()); | ||||
165 | 106 | | |||
166 | return lApp.exec(); | 107 | return app.exec(); | ||
167 | } | 108 | } |
s_needToDeleteQApplication is not needed any more.