Changeset View
Changeset View
Standalone View
Standalone View
src/SpectacleCore.cpp
Show All 38 Lines | |||||
39 | #include <QClipboard> | 39 | #include <QClipboard> | ||
40 | #include <QDir> | 40 | #include <QDir> | ||
41 | #include <QDrag> | 41 | #include <QDrag> | ||
42 | #include <QKeySequence> | 42 | #include <QKeySequence> | ||
43 | #include <QMimeData> | 43 | #include <QMimeData> | ||
44 | #include <QProcess> | 44 | #include <QProcess> | ||
45 | #include <QTimer> | 45 | #include <QTimer> | ||
46 | 46 | | |||
47 | SpectacleCore::SpectacleCore(StartMode theStartMode, | 47 | SpectacleCore::SpectacleCore(QObject *parent): | ||
48 | Spectacle::CaptureMode theCaptureMode, | | |||
49 | QString &theSaveFileName, | | |||
50 | qint64 theDelayMsec, | | |||
51 | bool theNotifyOnGrab, | | |||
52 | bool theCopyToClipboard, | | |||
53 | QObject *parent) : | | |||
54 | QObject(parent), | 48 | QObject(parent), | ||
55 | mStartMode(theStartMode), | | |||
56 | mNotify(theNotifyOnGrab), | | |||
57 | mPlatform(loadPlatform()), | | |||
58 | mMainWindow(nullptr), | 49 | mMainWindow(nullptr), | ||
59 | mIsGuiInited(false), | 50 | mIsGuiInited(false), | ||
60 | mCopyToClipboard(theCopyToClipboard), | | |||
61 | mWaylandPlasmashell(nullptr) | 51 | mWaylandPlasmashell(nullptr) | ||
62 | { | 52 | { | ||
davidre: Can you do
```
{
}
```
| |||||
63 | if (!(theSaveFileName.isEmpty() || theSaveFileName.isNull())) { | | |||
64 | if (QDir::isRelativePath(theSaveFileName)) { | | |||
65 | theSaveFileName = QDir::current().absoluteFilePath(theSaveFileName); | | |||
66 | } | | |||
67 | setFilename(theSaveFileName); | | |||
68 | } | 53 | } | ||
69 | 54 | | |||
55 | void SpectacleCore::init() | ||||
56 | { | ||||
57 | mPlatform = loadPlatform(); | ||||
58 | | ||||
70 | // essential connections | 59 | // essential connections | ||
71 | connect(this, &SpectacleCore::errorMessage, this, &SpectacleCore::showErrorMessage); | 60 | connect(this, &SpectacleCore::errorMessage, this, &SpectacleCore::showErrorMessage); | ||
72 | connect(mPlatform.get(), &Platform::newScreenshotTaken, this, &SpectacleCore::screenshotUpdated); | 61 | connect(mPlatform.get(), &Platform::newScreenshotTaken, this, &SpectacleCore::screenshotUpdated); | ||
73 | connect(mPlatform.get(), &Platform::newScreenshotFailed, this, &SpectacleCore::screenshotFailed); | 62 | connect(mPlatform.get(), &Platform::newScreenshotFailed, this, &SpectacleCore::screenshotFailed); | ||
74 | 63 | | |||
75 | auto lImmediateAvailable = mPlatform->supportedShutterModes().testFlag(Platform::ShutterMode::Immediate); | | |||
76 | auto lOnClickAvailable = mPlatform->supportedShutterModes().testFlag(Platform::ShutterMode::OnClick); | | |||
77 | if ((!lOnClickAvailable) && (theDelayMsec < 0)) { | | |||
78 | theDelayMsec = 0; | | |||
79 | } | | |||
80 | | ||||
81 | // reset last region if it should not be remembered across restarts | | |||
82 | if(!Settings::alwaysRememberRegion()) { | | |||
83 | Settings::setCropRegion({0, 0, 0, 0}); | | |||
84 | } | | |||
85 | | ||||
86 | // set up the export manager | 64 | // set up the export manager | ||
87 | auto lExportManager = ExportManager::instance(); | 65 | auto lExportManager = ExportManager::instance(); | ||
88 | lExportManager->setCaptureMode(theCaptureMode); | | |||
89 | connect(lExportManager, &ExportManager::errorMessage, this, &SpectacleCore::showErrorMessage); | 66 | connect(lExportManager, &ExportManager::errorMessage, this, &SpectacleCore::showErrorMessage); | ||
90 | connect(lExportManager, &ExportManager::imageSaved, this, &SpectacleCore::doCopyPath); | 67 | connect(lExportManager, &ExportManager::imageSaved, this, &SpectacleCore::doCopyPath); | ||
91 | connect(lExportManager, &ExportManager::forceNotify, this, &SpectacleCore::doNotify); | 68 | connect(lExportManager, &ExportManager::forceNotify, this, &SpectacleCore::doNotify); | ||
92 | connect(mPlatform.get(), &Platform::windowTitleChanged, lExportManager, &ExportManager::setWindowTitle); | 69 | connect(mPlatform.get(), &Platform::windowTitleChanged, lExportManager, &ExportManager::setWindowTitle); | ||
93 | 70 | | |||
94 | // Needed so the QuickEditor can go fullscreen on wayland | 71 | // Needed so the QuickEditor can go fullscreen on wayland | ||
95 | if (KWindowSystem::isPlatformWayland()) { | 72 | if (KWindowSystem::isPlatformWayland()) { | ||
96 | using namespace KWayland::Client; | 73 | using namespace KWayland::Client; | ||
97 | ConnectionThread *connection = ConnectionThread::fromApplication(this); | 74 | ConnectionThread *connection = ConnectionThread::fromApplication(this); | ||
98 | if (!connection) { | 75 | if (!connection) { | ||
99 | return; | 76 | return; | ||
100 | } | 77 | } | ||
101 | Registry *registry = new Registry(this); | 78 | Registry *registry = new Registry(this); | ||
102 | registry->create(connection); | 79 | registry->create(connection); | ||
103 | connect(registry, &Registry::plasmaShellAnnounced, this, | 80 | connect(registry, &Registry::plasmaShellAnnounced, this, | ||
104 | [this, registry] (quint32 name, quint32 version) { | 81 | [this, registry] (quint32 name, quint32 version) { | ||
105 | mWaylandPlasmashell = registry->createPlasmaShell(name, version, this); | 82 | mWaylandPlasmashell = registry->createPlasmaShell(name, version, this); | ||
106 | } | 83 | } | ||
107 | ); | 84 | ); | ||
108 | registry->setup(); | 85 | registry->setup(); | ||
109 | connection->roundtrip(); | 86 | connection->roundtrip(); | ||
110 | } | 87 | } | ||
88 | setUpShortcuts(); | ||||
89 | } | ||||
111 | 90 | | |||
112 | switch (theStartMode) { | 91 | void SpectacleCore::onActivateRequested(QStringList arguments, const QString& /*workingDirectory */) | ||
113 | case StartMode::DBus: | 92 | { | ||
114 | break; | 93 | // QCommandLineParser expects the first argument to be the executable name | ||
115 | case StartMode::Background: { | 94 | // In the current version it just strips it away | ||
116 | auto lMsec = (KWindowSystem::compositingActive() ? 200 : 50) + theDelayMsec; | 95 | arguments.prepend(qApp->applicationFilePath()); | ||
117 | auto lShutterMode = lImmediateAvailable ? Platform::ShutterMode::Immediate : Platform::ShutterMode::OnClick; | 96 | | ||
118 | auto lIncludePointer = Settings::includePointer(); | 97 | // We can't re-use QCommandLineParser instances, it preserves earlier parsed values | ||
119 | auto lIncludeDecorations = Settings::includeDecorations(); | 98 | auto parser = new QCommandLineParser; | ||
broulik: This leaks | |||||
120 | const Platform::GrabMode lCaptureMode = toPlatformGrabMode(theCaptureMode); | 99 | populateCommandLineParser(parser); | ||
121 | QTimer::singleShot(lMsec, this, [ this, lCaptureMode, lShutterMode, lIncludePointer, lIncludeDecorations ]() { | 100 | parser->parse(arguments); | ||
122 | mPlatform->doGrab(lShutterMode, lCaptureMode, lIncludePointer, lIncludeDecorations); | 101 | | ||
123 | }); | 102 | // extract the capture mode | ||
103 | Spectacle::CaptureMode lCaptureMode = Spectacle::CaptureMode::AllScreens; | ||||
104 | if (parser->isSet(QStringLiteral("current"))) { | ||||
105 | lCaptureMode = Spectacle::CaptureMode::CurrentScreen; | ||||
106 | } else if (parser->isSet(QStringLiteral("activewindow"))) { | ||||
107 | lCaptureMode = Spectacle::CaptureMode::ActiveWindow; | ||||
108 | } else if (parser->isSet(QStringLiteral("region"))) { | ||||
109 | lCaptureMode = Spectacle::CaptureMode::RectangularRegion; | ||||
110 | } else if (parser->isSet(QStringLiteral("windowundercursor"))) { | ||||
111 | lCaptureMode = Spectacle::CaptureMode::TransientWithParent; | ||||
112 | } else if (parser->isSet(QStringLiteral("transientonly"))) { | ||||
113 | lCaptureMode = Spectacle::CaptureMode::WindowUnderCursor; | ||||
114 | } | ||||
115 | | ||||
116 | mStartMode = SpectacleCore::StartMode::Gui; | ||||
117 | mNotify = true; | ||||
118 | mCopyToClipboard = Settings::copyImageToClipboard(); | ||||
119 | qint64 lDelayMsec = 0; | ||||
120 | QString lFileName = QString(); | ||||
121 | | ||||
122 | // are we ask to run in background or dbus mode? | ||||
123 | if (parser->isSet(QStringLiteral("background"))) { | ||||
124 | mStartMode = SpectacleCore::StartMode::Background; | ||||
125 | } else if (parser->isSet(QStringLiteral("dbus"))) { | ||||
126 | mStartMode = SpectacleCore::StartMode::DBus; | ||||
124 | } | 127 | } | ||
125 | break; | 128 | | ||
126 | case StartMode::Gui: | 129 | auto lExportManager = ExportManager::instance(); | ||
127 | initGui(Settings::includePointer(), Settings::includeDecorations()); | 130 | lExportManager->setCaptureMode(lCaptureMode); | ||
128 | break; | 131 | | ||
132 | auto lOnClickAvailable = mPlatform->supportedShutterModes().testFlag(Platform::ShutterMode::OnClick); | ||||
133 | if ((!lOnClickAvailable) && (lDelayMsec < 0)) { | ||||
134 | lDelayMsec = 0; | ||||
129 | } | 135 | } | ||
130 | setUpShortcuts(); | 136 | | ||
137 | if (!(lFileName.isEmpty() || lFileName.isNull())) { | ||||
138 | if (QDir::isRelativePath(lFileName)) { | ||||
139 | lFileName = QDir::current().absoluteFilePath(lFileName); | ||||
140 | } | ||||
141 | setFilename(lFileName); | ||||
131 | } | 142 | } | ||
132 | 143 | | |||
133 | void SpectacleCore::setUpShortcuts() | 144 | // reset last region if it should not be remembered across restarts | ||
134 | { | 145 | if(!Settings::alwaysRememberRegion()) { | ||
135 | KGlobalAccel::self()->setGlobalShortcut(ShortcutActions::self()->openAction(), Qt::Key_Print); | 146 | Settings::setCropRegion({0, 0, 0, 0}); | ||
147 | } | ||||
136 | 148 | | |||
137 | KGlobalAccel::self()->setGlobalShortcut(ShortcutActions::self()->fullScreenAction(), Qt::SHIFT + Qt::Key_Print); | 149 | switch (mStartMode) { | ||
138 | 150 | | |||
139 | KGlobalAccel::self()->setGlobalShortcut(ShortcutActions::self()->activeWindowAction(), Qt::META + Qt::Key_Print); | 151 | case StartMode::DBus: | ||
152 | qApp->setQuitOnLastWindowClosed(false); | ||||
153 | break; | ||||
140 | 154 | | |||
141 | KGlobalAccel::self()->setGlobalShortcut(ShortcutActions::self()->regionAction(), Qt::META + Qt::SHIFT + Qt::Key_Print); | 155 | case StartMode::Background: { | ||
156 | if (parser->isSet(QStringLiteral("nonotify"))) { | ||||
157 | mNotify = false; | ||||
158 | } | ||||
142 | 159 | | |||
143 | KGlobalAccel::self()->setGlobalShortcut(ShortcutActions::self()->currentScreenAction(), QList<QKeySequence>()); | 160 | if (parser->isSet(QStringLiteral("output"))) { | ||
161 | lFileName = parser->value(QStringLiteral("output")); | ||||
144 | } | 162 | } | ||
145 | 163 | | |||
146 | QString SpectacleCore::filename() const | 164 | if (parser->isSet(QStringLiteral("delay"))) { | ||
147 | { | 165 | bool lParseOk = false; | ||
148 | return mFileNameString; | 166 | qint64 lDelayValue = parser->value(QStringLiteral("delay")).toLongLong(&lParseOk); | ||
167 | if (lParseOk) { | ||||
168 | lDelayMsec = lDelayValue; | ||||
169 | } | ||||
149 | } | 170 | } | ||
150 | 171 | | |||
151 | void SpectacleCore::setFilename(const QString &filename) | 172 | if (parser->isSet(QStringLiteral("onclick"))) { | ||
152 | { | 173 | lDelayMsec = -1; | ||
153 | mFileNameString = filename; | | |||
154 | mFileNameUrl = QUrl::fromUserInput(filename); | | |||
155 | } | 174 | } | ||
156 | 175 | | |||
157 | // Slots | 176 | if (parser->isSet(QStringLiteral("clipboard"))) { | ||
177 | mCopyToClipboard = true; | ||||
178 | } | ||||
158 | 179 | | |||
159 | void SpectacleCore::dbusStartAgent() | 180 | if (!mIsGuiInited) { | ||
160 | { | 181 | static_cast<QGuiApplication *>(qApp->instance())->setQuitOnLastWindowClosed(false); | ||
161 | qApp->setQuitOnLastWindowClosed(true); | 182 | } | ||
162 | 183 | | |||
163 | auto lConfig = KSharedConfig::openConfig(QStringLiteral("spectaclerc")); | 184 | auto lIncludePointer = Settings::includePointer(); | ||
164 | KConfigGroup lGuiConfig(lConfig, "GuiConfig"); | 185 | auto lIncludeDecorations = Settings::includeDecorations(); | ||
165 | auto lIncludePointer = lGuiConfig.readEntry("includePointer", true); | 186 | takeNewScreenshot(lCaptureMode, lDelayMsec, lIncludePointer, lIncludeDecorations); | ||
166 | auto lIncludeDecorations = lGuiConfig.readEntry("includeDecorations", true); | 187 | } | ||
188 | break; | ||||
167 | 189 | | |||
168 | if (!(mStartMode == StartMode::Gui)) { | 190 | case StartMode::Gui: | ||
169 | mStartMode = StartMode::Gui; | 191 | if (!mIsGuiInited) { | ||
170 | initGui(lIncludePointer, lIncludeDecorations); | 192 | initGui(lDelayMsec, Settings::includePointer(), Settings::includeDecorations()); | ||
171 | } else { | 193 | } else { | ||
172 | using Actions = Settings::EnumPrintKeyActionRunning; | 194 | using Actions = Settings::EnumPrintKeyActionRunning; | ||
173 | switch (Settings::printKeyActionRunning()) { | 195 | switch (Settings::printKeyActionRunning()) { | ||
174 | case Actions::TakeNewScreenshot: { | 196 | case Actions::TakeNewScreenshot: { | ||
175 | // 0 means Immediate, -1 onClick | 197 | // 0 means Immediate, -1 onClick | ||
176 | int timeout = mPlatform->supportedShutterModes().testFlag(Platform::ShutterMode::Immediate) ? 0 : -1; | 198 | int timeout = mPlatform->supportedShutterModes().testFlag(Platform::ShutterMode::Immediate) ? 0 : -1; | ||
177 | takeNewScreenshot(Settings::captureMode(), timeout, Settings::includePointer(), Settings::includeDecorations()); | 199 | takeNewScreenshot(Settings::captureMode(), timeout, Settings::includePointer(), Settings::includeDecorations()); | ||
178 | break; | 200 | break; | ||
179 | } | 201 | } | ||
180 | case Actions::FocusWindow: | 202 | case Actions::FocusWindow: | ||
181 | if (mMainWindow->isMinimized()) { | 203 | if (mMainWindow->isMinimized()) { | ||
182 | mMainWindow->setWindowState(mMainWindow->windowState() & ~Qt::WindowMinimized); | 204 | mMainWindow->setWindowState(mMainWindow->windowState() & ~Qt::WindowMinimized); | ||
183 | } | 205 | } | ||
184 | mMainWindow->activateWindow(); | 206 | mMainWindow->activateWindow(); | ||
185 | break; | 207 | break; | ||
186 | case Actions::StartNewInstance: | 208 | case Actions::StartNewInstance: | ||
187 | QProcess newInstance; | 209 | QProcess newInstance; | ||
188 | newInstance.setProgram(QStringLiteral("spectacle")); | 210 | newInstance.setProgram(QStringLiteral("spectacle")); | ||
211 | newInstance.setArguments({QStringLiteral("--new-instance")}); | ||||
189 | newInstance.startDetached(); | 212 | newInstance.startDetached(); | ||
190 | break; | 213 | break; | ||
191 | } | 214 | } | ||
192 | } | 215 | } | ||
216 | | ||||
217 | break; | ||||
218 | } | ||||
219 | } | ||||
220 | | ||||
221 | void SpectacleCore::setUpShortcuts() | ||||
222 | { | ||||
223 | KGlobalAccel::self()->setGlobalShortcut(ShortcutActions::self()->openAction(), Qt::Key_Print); | ||||
224 | | ||||
225 | KGlobalAccel::self()->setGlobalShortcut(ShortcutActions::self()->fullScreenAction(), Qt::SHIFT + Qt::Key_Print); | ||||
226 | | ||||
227 | KGlobalAccel::self()->setGlobalShortcut(ShortcutActions::self()->activeWindowAction(), Qt::META + Qt::Key_Print); | ||||
228 | | ||||
229 | KGlobalAccel::self()->setGlobalShortcut(ShortcutActions::self()->regionAction(), Qt::META + Qt::SHIFT + Qt::Key_Print); | ||||
230 | | ||||
231 | KGlobalAccel::self()->setGlobalShortcut(ShortcutActions::self()->currentScreenAction(), QList<QKeySequence>()); | ||||
232 | } | ||||
233 | | ||||
234 | QString SpectacleCore::filename() const | ||||
235 | { | ||||
236 | return mFileNameString; | ||||
237 | } | ||||
238 | | ||||
239 | void SpectacleCore::setFilename(const QString &filename) | ||||
240 | { | ||||
241 | mFileNameString = filename; | ||||
242 | mFileNameUrl = QUrl::fromUserInput(filename); | ||||
193 | } | 243 | } | ||
194 | 244 | | |||
195 | void SpectacleCore::takeNewScreenshot(Spectacle::CaptureMode theCaptureMode, | 245 | void SpectacleCore::takeNewScreenshot(Spectacle::CaptureMode theCaptureMode, | ||
196 | int theTimeout, | 246 | int theTimeout, | ||
197 | bool theIncludePointer, | 247 | bool theIncludePointer, | ||
198 | bool theIncludeDecorations) | 248 | bool theIncludeDecorations) | ||
199 | { | 249 | { | ||
200 | ExportManager::instance()->setCaptureMode(theCaptureMode); | 250 | ExportManager::instance()->setCaptureMode(theCaptureMode); | ||
201 | auto lGrabMode = toPlatformGrabMode(theCaptureMode); | 251 | auto lGrabMode = toPlatformGrabMode(theCaptureMode); | ||
202 | 252 | | |||
203 | if (theTimeout < 0) { | 253 | if (theTimeout < 0 || !mPlatform->supportedShutterModes().testFlag(Platform::ShutterMode::Immediate)) { | ||
204 | mPlatform->doGrab(Platform::ShutterMode::OnClick, lGrabMode, theIncludePointer, theIncludeDecorations); | 254 | mPlatform->doGrab(Platform::ShutterMode::OnClick, lGrabMode, theIncludePointer, theIncludeDecorations); | ||
205 | return; | 255 | return; | ||
206 | } | 256 | } | ||
207 | 257 | | |||
208 | // when compositing is enabled, we need to give it enough time for the window | 258 | // when compositing is enabled, we need to give it enough time for the window | ||
209 | // to disappear and all the effects are complete before we take the shot. there's | 259 | // to disappear and all the effects are complete before we take the shot. there's | ||
210 | // no way of knowing how long the disappearing effects take, but as per default | 260 | // no way of knowing how long the disappearing effects take, but as per default | ||
211 | // settings (and unless the user has set an extremely slow effect), 200 | 261 | // settings (and unless the user has set an extremely slow effect), 200 | ||
Show All 36 Lines | 280 | { | |||
248 | 298 | | |||
249 | lExportManager->setPixmap(thePixmap); | 299 | lExportManager->setPixmap(thePixmap); | ||
250 | lExportManager->updatePixmapTimestamp(); | 300 | lExportManager->updatePixmapTimestamp(); | ||
251 | 301 | | |||
252 | switch (mStartMode) { | 302 | switch (mStartMode) { | ||
253 | case StartMode::Background: | 303 | case StartMode::Background: | ||
254 | case StartMode::DBus: | 304 | case StartMode::DBus: | ||
255 | { | 305 | { | ||
256 | if (mNotify) { | | |||
257 | connect(lExportManager, &ExportManager::imageSaved, this, &SpectacleCore::doNotify); | | |||
258 | } | | |||
259 | | ||||
260 | if (mCopyToClipboard) { | 306 | if (mCopyToClipboard) { | ||
261 | lExportManager->doCopyToClipboard(mNotify); | 307 | lExportManager->doCopyToClipboard(mNotify); | ||
262 | } else { | 308 | } else { | ||
263 | QUrl lSavePath = (mStartMode == StartMode::Background && mFileNameUrl.isValid() && mFileNameUrl.isLocalFile()) ? | 309 | QUrl lSavePath = (mStartMode == StartMode::Background && mFileNameUrl.isValid() && mFileNameUrl.isLocalFile()) ? | ||
264 | mFileNameUrl : QUrl(); | 310 | mFileNameUrl : QUrl(); | ||
265 | lExportManager->doSave(lSavePath); | 311 | lExportManager->doSave(lSavePath, mNotify); | ||
266 | } | 312 | } | ||
267 | 313 | | |||
314 | // if we don't have a Gui already opened, emit allDone | ||||
315 | if (!this->mIsGuiInited) { | ||||
268 | // if we notify, we emit allDone only if the user either dismissed the notification or pressed | 316 | // if we notify, we emit allDone only if the user either dismissed the notification or pressed | ||
269 | // the "Open" button, otherwise the app closes before it can react to it. | 317 | // the "Open" button, otherwise the app closes before it can react to it. | ||
270 | if (!mNotify && mCopyToClipboard) { | 318 | if (!mNotify && mCopyToClipboard) { | ||
271 | // Allow some time for clipboard content to transfer if '--nonotify' is used, see Bug #411263 | 319 | // Allow some time for clipboard content to transfer if '--nonotify' is used, see Bug #411263 | ||
272 | // TODO: Find better solution | 320 | // TODO: Find better solution | ||
273 | QTimer::singleShot(250, this, &SpectacleCore::allDone); | 321 | QTimer::singleShot(250, this, &SpectacleCore::allDone); | ||
274 | } else if (!mNotify) { | 322 | } else if (!mNotify) { | ||
275 | emit allDone(); | 323 | emit allDone(); | ||
276 | } | 324 | } | ||
277 | } | 325 | } | ||
326 | } | ||||
278 | break; | 327 | break; | ||
279 | case StartMode::Gui: | 328 | case StartMode::Gui: | ||
280 | mMainWindow->setScreenshotAndShow(thePixmap); | 329 | mMainWindow->setScreenshotAndShow(thePixmap); | ||
281 | 330 | | |||
282 | bool autoSaveImage = Settings::autoSaveImage(); | 331 | bool autoSaveImage = Settings::autoSaveImage(); | ||
283 | bool copyImageToClipboard = Settings::copyImageToClipboard(); | 332 | bool mCopyImageToClipboard = Settings::copyImageToClipboard(); | ||
284 | 333 | | |||
285 | if (autoSaveImage && copyImageToClipboard) { | 334 | if (autoSaveImage && mCopyImageToClipboard) { | ||
286 | lExportManager->doSaveAndCopy(); | 335 | lExportManager->doSaveAndCopy(); | ||
287 | } else if (autoSaveImage) { | 336 | } else if (autoSaveImage) { | ||
288 | lExportManager->doSave(); | 337 | lExportManager->doSave(); | ||
289 | } else if (copyImageToClipboard) { | 338 | } else if (mCopyImageToClipboard) { | ||
290 | lExportManager->doCopyToClipboard(false); | 339 | lExportManager->doCopyToClipboard(false); | ||
291 | } | 340 | } | ||
292 | } | 341 | } | ||
293 | } | 342 | } | ||
294 | 343 | | |||
295 | void SpectacleCore::screenshotFailed() | 344 | void SpectacleCore::screenshotFailed() | ||
296 | { | 345 | { | ||
297 | if (ExportManager::instance()->captureMode() == Spectacle::CaptureMode::RectangularRegion && mQuickEditor) { | 346 | if (ExportManager::instance()->captureMode() == Spectacle::CaptureMode::RectangularRegion && mQuickEditor) { | ||
▲ Show 20 Lines • Show All 52 Lines • ▼ Show 20 Line(s) | 366 | { | |||
350 | 399 | | |||
351 | if (!mCopyToClipboard) { | 400 | if (!mCopyToClipboard) { | ||
352 | lNotify->setUrls({theSavedAt}); | 401 | lNotify->setUrls({theSavedAt}); | ||
353 | lNotify->setDefaultAction(i18nc("Open the screenshot we just saved", "Open")); | 402 | lNotify->setDefaultAction(i18nc("Open the screenshot we just saved", "Open")); | ||
354 | connect(lNotify, QOverload<uint>::of(&KNotification::activated), this, [this, theSavedAt](uint index) { | 403 | connect(lNotify, QOverload<uint>::of(&KNotification::activated), this, [this, theSavedAt](uint index) { | ||
355 | if (index == 0) { | 404 | if (index == 0) { | ||
356 | new KRun(theSavedAt, nullptr); | 405 | new KRun(theSavedAt, nullptr); | ||
357 | QTimer::singleShot(250, this, [this] { | 406 | QTimer::singleShot(250, this, [this] { | ||
358 | if (mStartMode != StartMode::Gui || Settings::quitAfterSaveCopyExport()) { | 407 | if (!mIsGuiInited || Settings::quitAfterSaveCopyExport()) { | ||
359 | emit allDone(); | 408 | emit allDone(); | ||
360 | } | 409 | } | ||
361 | }); | 410 | }); | ||
362 | } | 411 | } | ||
363 | }); | 412 | }); | ||
364 | } | 413 | } | ||
365 | 414 | | |||
366 | connect(lNotify, &QObject::destroyed, this, [this] { | 415 | connect(lNotify, &QObject::destroyed, this, [this] { | ||
367 | if (mStartMode != StartMode::Gui || Settings::quitAfterSaveCopyExport()) { | 416 | if (!mIsGuiInited || Settings::quitAfterSaveCopyExport()) { | ||
368 | emit allDone(); | 417 | emit allDone(); | ||
369 | } | 418 | } | ||
370 | }); | 419 | }); | ||
371 | 420 | | |||
372 | lNotify->sendEvent(); | 421 | lNotify->sendEvent(); | ||
373 | } | 422 | } | ||
374 | 423 | | |||
375 | void SpectacleCore::doCopyPath(const QUrl &savedAt) | 424 | void SpectacleCore::doCopyPath(const QUrl &savedAt) | ||
376 | { | 425 | { | ||
377 | if (Settings::copySaveLocation()) { | 426 | if (Settings::copySaveLocation()) { | ||
378 | qApp->clipboard()->setText(savedAt.toLocalFile()); | 427 | qApp->clipboard()->setText(savedAt.toLocalFile()); | ||
379 | } | 428 | } | ||
380 | } | 429 | } | ||
381 | 430 | | |||
431 | void SpectacleCore::populateCommandLineParser(QCommandLineParser *lCmdLineParser) | ||||
432 | { | ||||
433 | lCmdLineParser->addOptions({ | ||||
434 | {{QStringLiteral("f"), QStringLiteral("fullscreen")}, i18n("Capture the entire desktop (default)")}, | ||||
435 | {{QStringLiteral("m"), QStringLiteral("current")}, i18n("Capture the current monitor")}, | ||||
436 | {{QStringLiteral("a"), QStringLiteral("activewindow")}, i18n("Capture the active window")}, | ||||
437 | {{QStringLiteral("u"), QStringLiteral("windowundercursor")}, i18n("Capture the window currently under the cursor, including parents of pop-up menus")}, | ||||
438 | {{QStringLiteral("t"), QStringLiteral("transientonly")}, i18n("Capture the window currently under the cursor, excluding parents of pop-up menus")}, | ||||
439 | {{QStringLiteral("r"), QStringLiteral("region")}, i18n("Capture a rectangular region of the screen")}, | ||||
440 | {{QStringLiteral("g"), QStringLiteral("gui")}, i18n("Start in GUI mode (default)")}, | ||||
441 | {{QStringLiteral("b"), QStringLiteral("background")}, i18n("Take a screenshot and exit without showing the GUI")}, | ||||
442 | {{QStringLiteral("s"), QStringLiteral("dbus")}, i18n("Start in DBus-Activation mode")}, | ||||
443 | {{QStringLiteral("n"), QStringLiteral("nonotify")}, i18n("In background mode, do not pop up a notification when the screenshot is taken")}, | ||||
444 | {{QStringLiteral("o"), QStringLiteral("output")}, i18n("In background mode, save image to specified file"), QStringLiteral("fileName")}, | ||||
445 | {{QStringLiteral("d"), QStringLiteral("delay")}, i18n("In background mode, delay before taking the shot (in milliseconds)"), QStringLiteral("delayMsec")}, | ||||
446 | {{QStringLiteral("c"), QStringLiteral("clipboard")}, i18n("In background mode, copy screenshot to clipboard")}, | ||||
447 | {{QStringLiteral("w"), QStringLiteral("onclick")}, i18n("Wait for a click before taking screenshot. Invalidates delay")}, | ||||
448 | {{QStringLiteral("i"), QStringLiteral("new-instance")}, i18n("Starts a new GUI instance of spectacle without registering to DBus")} | ||||
449 | }); | ||||
450 | } | ||||
451 | | ||||
382 | void SpectacleCore::doStartDragAndDrop() | 452 | void SpectacleCore::doStartDragAndDrop() | ||
383 | { | 453 | { | ||
384 | auto lExportManager = ExportManager::instance(); | 454 | auto lExportManager = ExportManager::instance(); | ||
385 | QUrl lTempFile = lExportManager->tempSave(); | 455 | QUrl lTempFile = lExportManager->tempSave(); | ||
386 | if (!lTempFile.isValid()) { | 456 | if (!lTempFile.isValid()) { | ||
387 | return; | 457 | return; | ||
388 | } | 458 | } | ||
389 | 459 | | |||
Show All 24 Lines | 473 | { | |||
414 | case Spectacle::CaptureMode::ActiveWindow: | 484 | case Spectacle::CaptureMode::ActiveWindow: | ||
415 | return Platform::GrabMode::ActiveWindow; | 485 | return Platform::GrabMode::ActiveWindow; | ||
416 | case Spectacle::CaptureMode::WindowUnderCursor: | 486 | case Spectacle::CaptureMode::WindowUnderCursor: | ||
417 | return Platform::GrabMode::WindowUnderCursor; | 487 | return Platform::GrabMode::WindowUnderCursor; | ||
418 | } | 488 | } | ||
419 | return Platform::GrabMode::InvalidChoice; | 489 | return Platform::GrabMode::InvalidChoice; | ||
420 | } | 490 | } | ||
421 | 491 | | |||
422 | void SpectacleCore::initGui(bool theIncludePointer, bool theIncludeDecorations) | 492 | void SpectacleCore::initGui(int theDelay, bool theIncludePointer, bool theIncludeDecorations) | ||
423 | { | 493 | { | ||
424 | if (!mIsGuiInited) { | 494 | if (!mIsGuiInited) { | ||
425 | mMainWindow = std::make_unique<KSMainWindow>(mPlatform->supportedGrabModes(), mPlatform->supportedShutterModes()); | 495 | mMainWindow = std::make_unique<KSMainWindow>(mPlatform->supportedGrabModes(), mPlatform->supportedShutterModes()); | ||
426 | 496 | | |||
427 | connect(mMainWindow.get(), &KSMainWindow::newScreenshotRequest, this, &SpectacleCore::takeNewScreenshot); | 497 | connect(mMainWindow.get(), &KSMainWindow::newScreenshotRequest, this, &SpectacleCore::takeNewScreenshot); | ||
428 | connect(mMainWindow.get(), &KSMainWindow::dragAndDropRequest, this, &SpectacleCore::doStartDragAndDrop); | 498 | connect(mMainWindow.get(), &KSMainWindow::dragAndDropRequest, this, &SpectacleCore::doStartDragAndDrop); | ||
429 | 499 | | |||
430 | mIsGuiInited = true; | 500 | mIsGuiInited = true; | ||
431 | | ||||
432 | auto lShutterMode = mPlatform->supportedShutterModes().testFlag(Platform::ShutterMode::Immediate) ? Platform::ShutterMode::Immediate : Platform::ShutterMode::OnClick; | | |||
433 | auto lGrabMode = toPlatformGrabMode(ExportManager::instance()->captureMode()); | | |||
434 | | ||||
435 | QTimer::singleShot(0, this, [this, lShutterMode, lGrabMode, theIncludePointer, theIncludeDecorations]() { | | |||
436 | mPlatform->doGrab(lShutterMode, lGrabMode, theIncludePointer, theIncludeDecorations); | | |||
437 | }); | | |||
438 | } | 501 | } | ||
502 | | ||||
503 | takeNewScreenshot(ExportManager::instance()->captureMode(), theDelay, theIncludePointer, theIncludeDecorations); | ||||
439 | } | 504 | } |
Can you do