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);