[spectacle] /: (3/3) add option to quit after save or copy operations

Nathaniel Graham null at kde.org
Sun Feb 11 21:35:07 UTC 2018


Git commit 2b1c8bec0fd1ff6b929eca638264d0649270af5f by Nathaniel Graham.
Committed on 11/02/2018 at 21:25.
Pushed by ngraham into branch 'master'.

(3/3) add option to quit after save or copy operations

Summary:
Part 3 of 3 for {T7841}

FEATURE: 389773
FIXED-IN: KDE Applications 18.04

We add a checkbox visible on the main UI to quit Spectacle after save or copy operations. This yields the following benefits:
- We can remove the "Save & Exit" item from the split button
- Users gain the ability to have spectacle quit after copying the image to the clipboard

I tried to make the feature apply to Export operations as well, but that proved to be much more complicated and I decided to abandon that for now and do it later in a subsequent patch.

Test Plan:
{F5691970}

Tested in KDE Neon:
- With "Quit after Copy or Save" unchecked:
-- Save: image is saved
-- Save As: file save dialog shown, image is saved
-- Copy to Clipboard: message is shown, image is copied to clipboard

- With "Quit after Copy or Save" checked:
-- Save: notification shown, Spectacle quits, image is saved
-- Save As: file save dialog shown, notification shown, Spectacle quits, image is saved
-- Copy to Clipboard: image is copied to clipboard (if Klipper is set up to accept images), Spectacle quits

Reviewers: #spectacle, rkflx

Reviewed By: rkflx

Subscribers: rkflx

Differential Revision: https://phabricator.kde.org/D10301

M  +11   -8    doc/index.docbook
M  +7    -1    src/ExportManager.cpp
M  +1    -1    src/ExportManager.h
M  +28   -20   src/Gui/KSMainWindow.cpp
M  +0    -1    src/Gui/KSMainWindow.h
M  +8    -5    src/Gui/KSWidget.cpp
M  +1    -0    src/Gui/KSWidget.h
M  +13   -0    src/SpectacleConfig.cpp
M  +3    -0    src/SpectacleConfig.h

https://commits.kde.org/spectacle/2b1c8bec0fd1ff6b929eca638264d0649270af5f

diff --git a/doc/index.docbook b/doc/index.docbook
index 946485f..f0630c3 100644
--- a/doc/index.docbook
+++ b/doc/index.docbook
@@ -115,7 +115,7 @@
 
 		<para>To save a screenshot to the default location, click on the arrow portion of the <guibutton>Save As...</guibutton> button and press the <guimenuitem>Save </guimenuitem> (<keycombo action="simul">&Ctrl;<keycap>S</keycap></keycombo>) button. The new save mode will be remembered for next time; this behavior can be configured in Spectacle's settings. The default save location and filename can also be configured there, as described later.</para>
 
-		<para>To quickly save the image and quit &spectacle;, click on the arrow portion of the <guibutton>Save As...</guibutton> button and press the <guimenuitem>Save & Exit</guimenuitem> (<keycombo action="simul">&Ctrl;<keycap>Q</keycap></keycombo>) item. This saves the image as a PNG file in your default Pictures folder, and exits the application immediately. As above, this new save mode will be remembered.</para>
+		<para>To quickly save the image and quit &spectacle;, click on the checkbox beside <guilabel>Quit after Save or Copy</guilabel>, then click the arrow portion of the <guibutton>Save As...</guibutton> button and press the <guimenuitem>Save</guimenuitem> (<keycombo action="simul">&Ctrl;<keycap>S</keycap></keycombo>) item. This saves the image as a PNG file in your default Pictures folder, and exits the application immediately. As above, this new save mode will be remembered.</para>
 
 		<sect1 id="taking-screenshot">
 			<title>Taking A Screenshot</title>
@@ -146,7 +146,7 @@
 					<listitem>
 						<para>The <guilabel>Window Under Cursor</guilabel> option takes a screenshot of the window that is under the mouse cursor. If the cursor is on top of a popup menu, &spectacle; tries to take a screenshot of the menu as well as its parent window.</para>
 
-						<para>While this works most of the time, in certain cases it may fail to obtain information about the parent window. In this case, &spectacle; falls back to old way of capturing the image automatically, and captures an image of only the popup menu. You can also force the old way of capturing the image by checking the <guilabel>Capture the current pop-up only</guilabel> checkbox under <guilabel>Content Options</guilabel></para>
+						<para>While this works most of the time, in certain cases it may fail to obtain information about the parent window. In this case, &spectacle; falls back to old way of capturing the image automatically, and captures an image of only the popup menu. You can also force the old way of capturing the image by checking the <guilabel>Capture the current pop-up only</guilabel> checkbox under <guilabel>Options</guilabel></para>
 					</listitem>
 					<listitem>
 						<para>The <guilabel>Rectangular Region</guilabel> option allows you to select a rectangular region of your desktop with your mouse. This region may be spread across different outputs.</para>
@@ -161,9 +161,9 @@
 			</sect2>
 
 			<sect2>
-				<title>Content Options</title>
+				<title>Options</title>
 
-				<para>The content options settings allow you to select whether the mouse cursor should be included in the screenshots, and whether to capture window decorations along with the image of a single application window. In <guilabel>Window Under Cursor</guilabel> mode, it also allows you to select if &spectacle; shall only capture the image of the current popup menu under the cursor, or also include the parent window.</para>
+				<para>The Options settings allow you to select whether the mouse cursor should be included in the screenshots, and whether to capture window decorations along with the image of a single application window. In <guilabel>Window Under Cursor</guilabel> mode, it also allows you to select if &spectacle; shall only capture the image of the current popup menu under the cursor, or also include the parent window. Finally, <guilabel>Quit after Save or Copy</guilabel> will quit Spectacle after any save or copy operations.</para>
 
 				<itemizedlist>
 					<listitem>
@@ -175,6 +175,9 @@
 					<listitem>
 						<para>The <guilabel>Capture the current pop-up only</guilabel> option is only enabled when the <guilabel>Window Under Cursor</guilabel> mode is selected in the <guilabel>Area</guilabel> combo-box. Checking this option captures only the popup menu under the cursor, without its parent window.</para>
 					</listitem>
+					<listitem>
+						<para>The <guilabel>Quit after Save or Copy</guilabel> option will quit Spectacle after any saving or copying operations. Note that a copied screenshot will only be retained if you are running a clipboard manager that accepts images. KDE Klipper can be configured in this manner by right-clicking on its icon, selecting <guilabel>Configure Clipboard...</guilabel>, and unchecking <guilabel>Ignore images</guilabel>.</para>
+					</listitem>
 				</itemizedlist>
 			</sect2>
 		</sect1>
@@ -222,9 +225,9 @@
 					</listitem>
 				</varlistentry>
 				<varlistentry>
-					<term><guibutton>Save & Exit</guibutton></term>
+					<term><guibutton>Save As</guibutton></term>
 					<listitem>
-						<para>Clicking this button saves the screenshot as a PNG image in your default Pictures folder and immediately exits the application.</para>
+						<para>Clicking this button saves the screenshot as a PNG image to a location of your choosing. Clicking on the arrow on the side will expose the other save mode, <guimenuitem>Save</guimenuitem>, which will save the screenshot as a PNG image to the standard location (which defaults to your Pictures folder). By default, the last-used save mode is remembered for next time.</para>
 					</listitem>
 				</varlistentry>
 			</variablelist>
@@ -274,7 +277,7 @@
 			</sect2>
 			<sect2>
 			<title>Save</title>
-			<para>When you use the <guilabel>Save & Exit</guilabel> or the <guilabel>Save</guilabel> functions, &spectacle; saves the image with a default filename, in your Pictures folder under your home folder. The default filename includes the date and time when the image was taken.</para>
+			<para>When you use the <guilabel>Save</guilabel> function, &spectacle; saves the image with a default filename, in your Pictures folder (which is inside your home folder). The default filename includes the date and time when the image was taken.</para>
 
 			<para>The <guilabel>Save</guilabel> page allows you to set the default save location and filename. Clicking this option brings up a dialog box like the following:
 				<mediaobject>
@@ -290,7 +293,7 @@
 				<varlistentry>
 					<term><guilabel>Default Save Location</guilabel></term>
 					<listitem>
-                    <para>In the <guilabel>Location</guilabel> text box set the folder where you'd like to save your screenshots when you press <guibutton>Save</guibutton> or <guibutton>Save & Exit</guibutton>.</para>
+                    <para>In the <guilabel>Location</guilabel> text box set the folder where you'd like to save your screenshots when you press <guibutton>Save</guibutton>.</para>
 					</listitem>
 				</varlistentry>
 				<varlistentry>
diff --git a/src/ExportManager.cpp b/src/ExportManager.cpp
index 16ac3dc..8f36a4a 100644
--- a/src/ExportManager.cpp
+++ b/src/ExportManager.cpp
@@ -326,7 +326,7 @@ void ExportManager::doSave(const QUrl &url, bool notify)
     }
 }
 
-void ExportManager::doSaveAs(QWidget *parentWindow)
+bool ExportManager::doSaveAs(QWidget *parentWindow, bool notify)
 {
     QStringList supportedFilters;
     SpectacleConfig *config = SpectacleConfig::instance();
@@ -353,9 +353,15 @@ void ExportManager::doSaveAs(QWidget *parentWindow)
             if (save(saveUrl)) {
                 emit imageSaved(saveUrl);
                 config->setLastSaveAsLocation(saveUrl.adjusted(QUrl::RemoveFilename));
+
+                if (notify) {
+                    emit forceNotify(saveUrl);
+                }
+                return true;
             }
         }
     }
+    return false;
 }
 
 // misc helpers
diff --git a/src/ExportManager.h b/src/ExportManager.h
index 33e7f13..5b45070 100644
--- a/src/ExportManager.h
+++ b/src/ExportManager.h
@@ -73,7 +73,7 @@ class ExportManager : public QObject
     QUrl tempSave(const QString &mimetype = QStringLiteral("png"));
 
     void doSave(const QUrl &url = QUrl(), bool notify = false);
-    void doSaveAs(QWidget *parentWindow = 0);
+    bool doSaveAs(QWidget *parentWindow = 0, bool notify = false);
     void doCopyToClipboard();
     void doPrint(QPrinter *printer);
 
diff --git a/src/Gui/KSMainWindow.cpp b/src/Gui/KSMainWindow.cpp
index e491cb4..5b3bd1f 100644
--- a/src/Gui/KSMainWindow.cpp
+++ b/src/Gui/KSMainWindow.cpp
@@ -192,6 +192,10 @@ void KSMainWindow::init()
     }
     resize(QSize(DEFAULT_WINDOW_WIDTH, DEFAULT_WINDOW_HEIGHT).expandedTo(minimumSize()));
 
+    // Allow Ctrl+Q to quit the app
+    QAction *actionQuit = KStandardAction::quit(qApp, &QApplication::quit, this);
+    actionQuit->setShortcut(QKeySequence::Quit);
+    addAction(actionQuit);
 
     // done with the init
 }
@@ -220,10 +224,6 @@ void KSMainWindow::buildSaveMenu()
     // get our actions in order
     QAction *actionSave = KStandardAction::save(this, &KSMainWindow::save, this);
     QAction *actionSaveAs = KStandardAction::saveAs(this, &KSMainWindow::saveAs, this);
-    QAction *actionSaveExit = new QAction(QIcon::fromTheme(QStringLiteral("document-save")), i18n("Save &&& Exit"), this);
-    actionSaveExit->setToolTip(i18n("Save screenshot in your Pictures directory and exit"));
-    actionSaveExit->setShortcut(QKeySequence(QKeySequence::Quit));
-    connect(actionSaveExit, &QAction::triggered, this, &KSMainWindow::saveAndExit);
 
     // static or dynamic
     SpectacleConfig *cfgManager = SpectacleConfig::instance();
@@ -234,17 +234,10 @@ void KSMainWindow::buildSaveMenu()
     case 0:
     default:
         mSaveButton->setDefaultAction(actionSaveAs);
-        mSaveMenu->addAction(actionSaveExit);
         mSaveMenu->addAction(actionSave);
         break;
     case 1:
         mSaveButton->setDefaultAction(actionSave);
-        mSaveMenu->addAction(actionSaveExit);
-        mSaveMenu->addAction(actionSaveAs);
-        break;
-    case 2:
-        mSaveButton->setDefaultAction(actionSaveExit);
-        mSaveMenu->addAction(actionSave);
         mSaveMenu->addAction(actionSaveAs);
         break;
     }
@@ -318,6 +311,12 @@ void KSMainWindow::sendToClipboard()
 {
     ExportManager::instance()->doCopyToClipboard();
 
+    if (SpectacleConfig::instance()->quitAfterSaveOrCopyChecked()) {
+        qApp->setQuitOnLastWindowClosed(false);
+        hide();
+        QTimer::singleShot(250, qApp, &QApplication::quit);
+    }
+
     mMessageWidget->setMessageType(KMessageWidget::Information);
     mMessageWidget->setText(i18n("The screenshot has been copied to the clipboard."));
     mMessageWidget->setIcon(QIcon::fromTheme(QStringLiteral("dialog-information")));
@@ -342,20 +341,29 @@ void KSMainWindow::save()
 {
     SpectacleConfig::instance()->setLastUsedSaveMode(1);
     buildSaveMenu();
-    ExportManager::instance()->doSave();
+
+    if (SpectacleConfig::instance()->quitAfterSaveOrCopyChecked()) {
+        ExportManager::instance()->doSave(QUrl(), true);
+        qApp->setQuitOnLastWindowClosed(false);
+        hide();
+    }
+    else {
+        ExportManager::instance()->doSave();
+    }
 }
 
 void KSMainWindow::saveAs()
 {
     SpectacleConfig::instance()->setLastUsedSaveMode(0);
     buildSaveMenu();
-    ExportManager::instance()->doSaveAs(this);
-}
 
-void KSMainWindow::saveAndExit()
-{
-    SpectacleConfig::instance()->setLastUsedSaveMode(2);
-    qApp->setQuitOnLastWindowClosed(false);
-    ExportManager::instance()->doSave(QUrl(), true);
-    hide();
+    if (SpectacleConfig::instance()->quitAfterSaveOrCopyChecked()) {
+        if (ExportManager::instance()->doSaveAs(this, true)) {
+            qApp->setQuitOnLastWindowClosed(false);
+            hide();
+        }
+    }
+    else {
+        ExportManager::instance()->doSaveAs(this, false);
+    }
 }
diff --git a/src/Gui/KSMainWindow.h b/src/Gui/KSMainWindow.h
index ab78f31..b51c9a9 100644
--- a/src/Gui/KSMainWindow.h
+++ b/src/Gui/KSMainWindow.h
@@ -52,7 +52,6 @@ class KSMainWindow : public QDialog
     void buildSaveMenu();
     void save();
     void saveAs();
-    void saveAndExit();
     int windowWidth(const QPixmap &pixmap) const;
 
     public slots:
diff --git a/src/Gui/KSWidget.cpp b/src/Gui/KSWidget.cpp
index 28612ec..81382c8 100644
--- a/src/Gui/KSWidget.cpp
+++ b/src/Gui/KSWidget.cpp
@@ -87,10 +87,10 @@ KSWidget::KSWidget(QWidget *parent) :
     mCaptureModeForm->addRow(i18n("Delay:"), mDelayLayout);
     mCaptureModeForm->setContentsMargins(24, 0, 0, 0);
 
-    // the content options (mouse pointer, window decorations)
+    // options (mouse pointer, window decorations, quit after saving or copying)
 
     mContentOptionsLabel = new QLabel(this);
-    mContentOptionsLabel->setText(i18n("<b>Content Options</b>"));
+    mContentOptionsLabel->setText(i18n("<b>Options</b>"));
 
     mMousePointer = new QCheckBox(i18n("Include mouse pointer"), this);
     mMousePointer->setToolTip(i18n("Show the mouse cursor in the screenshot image"));
@@ -107,11 +107,15 @@ KSWidget::KSWidget(QWidget *parent) :
     mCaptureTransientOnly->setEnabled(false);
     connect(mCaptureTransientOnly, &QCheckBox::clicked, configManager, &SpectacleConfig::setCaptureTransientWindowOnlyChecked);
 
+    mQuitAfterSaveOrCopy = new QCheckBox(i18n("Quit after Save or Copy"), this);
+    mQuitAfterSaveOrCopy->setToolTip(i18n("Quit Spectacle after saving or copying the image"));
+    connect(mQuitAfterSaveOrCopy, &QCheckBox::clicked, configManager, &SpectacleConfig::setQuitAfterSaveOrCopyChecked);
+
     mContentOptionsForm = new QVBoxLayout;
     mContentOptionsForm->addWidget(mMousePointer);
     mContentOptionsForm->addWidget(mWindowDecorations);
     mContentOptionsForm->addWidget(mCaptureTransientOnly);
-    mContentOptionsForm->setSpacing(16);
+    mContentOptionsForm->addWidget(mQuitAfterSaveOrCopy);
     mContentOptionsForm->setContentsMargins(24, 0, 0, 0);
 
     // the take a new screenshot button
@@ -134,11 +138,9 @@ KSWidget::KSWidget(QWidget *parent) :
     mRightLayout = new QVBoxLayout;
     mRightLayout->addStretch(1);
     mRightLayout->addWidget(mCaptureModeLabel);
-    mRightLayout->addSpacing(10);
     mRightLayout->addLayout(mCaptureModeForm);
     mRightLayout->addStretch(1);
     mRightLayout->addWidget(mContentOptionsLabel);
-    mRightLayout->addSpacing(10);
     mRightLayout->addLayout(mContentOptionsForm);
     mRightLayout->addStretch(10);
     mRightLayout->addWidget(mTakeScreenshotButton, 1, Qt::AlignHCenter);
@@ -156,6 +158,7 @@ KSWidget::KSWidget(QWidget *parent) :
     mWindowDecorations->setChecked    (configManager->includeDecorationsChecked());
     mCaptureOnClick->setChecked       (configManager->onClickChecked());
     mCaptureTransientOnly->setChecked (configManager->captureTransientWindowOnlyChecked());
+    mQuitAfterSaveOrCopy->setChecked  (configManager->quitAfterSaveOrCopyChecked());
     mCaptureArea->setCurrentIndex     (configManager->captureMode());
     mDelayMsec->setValue              (configManager->captureDelay());
 
diff --git a/src/Gui/KSWidget.h b/src/Gui/KSWidget.h
index 11998af..733c87a 100644
--- a/src/Gui/KSWidget.h
+++ b/src/Gui/KSWidget.h
@@ -78,6 +78,7 @@ class KSWidget : public QWidget
     QCheckBox     *mMousePointer;
     QCheckBox     *mWindowDecorations;
     QCheckBox     *mCaptureTransientOnly;
+    QCheckBox     *mQuitAfterSaveOrCopy;
     QLabel        *mCaptureModeLabel;
     QLabel        *mContentOptionsLabel;
 };
diff --git a/src/SpectacleConfig.cpp b/src/SpectacleConfig.cpp
index 89be2f6..e3b82b0 100644
--- a/src/SpectacleConfig.cpp
+++ b/src/SpectacleConfig.cpp
@@ -117,6 +117,19 @@ void SpectacleConfig::setCaptureTransientWindowOnlyChecked(bool enabled)
     mGuiConfig.sync();
 }
 
+// quit after saving, copying, or exporting the image
+
+bool SpectacleConfig::quitAfterSaveOrCopyChecked() const
+{
+    return mGuiConfig.readEntry(QStringLiteral("quitAfterSaveCopyExport"), false);
+}
+
+void SpectacleConfig::setQuitAfterSaveOrCopyChecked(bool enabled)
+{
+    mGuiConfig.writeEntry(QStringLiteral("quitAfterSaveCopyExport"), enabled);
+    mGuiConfig.sync();
+}
+
 // capture delay
 
 qreal SpectacleConfig::captureDelay() const
diff --git a/src/SpectacleConfig.h b/src/SpectacleConfig.h
index 2a3bfb7..d033005 100644
--- a/src/SpectacleConfig.h
+++ b/src/SpectacleConfig.h
@@ -67,6 +67,9 @@ class SpectacleConfig : public QObject
     bool captureTransientWindowOnlyChecked() const;
     void setCaptureTransientWindowOnlyChecked(bool enabled);
 
+    bool quitAfterSaveOrCopyChecked() const;
+    void setQuitAfterSaveOrCopyChecked(bool enabled);
+
     qreal captureDelay() const;
     void setCaptureDelay(qreal delay);
 


More information about the kde-doc-english mailing list