Commit 731f8b16 authored by Antonio Prcela's avatar Antonio Prcela 🏞 Committed by Méven Car
Browse files

Option to launch Spectacle without taking a screenshot or using last used capture mode

FEATURE: 437368

Adds an option to set so one can launch spectacle with either taking a fullscreen screenshot, using last capture mode or not taking a screenshot on launch.
parent e6d64481
......@@ -98,6 +98,14 @@
</doc:doc>
</method>
<method name="OpenWithoutScreenshot">
<doc:doc>
<doc:description>
<doc:para>Launches Spectacle without taking a screenshot.</doc:para>
</doc:description>
</doc:doc>
</method>
<signal name="ScreenshotTaken">
<arg name="fileName" direction="out" type="s">
<doc:doc>
......
......@@ -168,7 +168,7 @@ Icon=spectacle
Type=Application
Terminal=false
StartupNotify=false
Actions=FullScreenScreenShot;CurrentMonitorScreenShot;ActiveWindowScreenShot;RectangularRegionScreenShot;WindowUnderCursorScreenShot;
Actions=FullScreenScreenShot;CurrentMonitorScreenShot;ActiveWindowScreenShot;RectangularRegionScreenShot;WindowUnderCursorScreenShot;OpenWithoutScreenshot;
X-DBUS-StartupType=Unique
X-DBUS-ServiceName=org.kde.Spectacle
X-KDE-Shortcuts=Print
......@@ -402,3 +402,11 @@ Name[x-test]=xxCapture Window Under Cursorxx
Name[zh_CN]=捕获光标所在窗口
Exec=@QtBinariesDir@/qdbus org.kde.Spectacle / WindowUnderCursor true false
X-KDE-Shortcuts=Meta+Ctrl+Print
[Desktop Action OpenWithoutScreenshot]
Name=Launch without taking a screenshot
Name[de]=Ohne Aufnahme starten
Name[en_GB]=Launch without taking a screenshot
Name[sr@ijekavianlatin]=Pokreni bez snimanja
Name[sr@latin]=Pokreni bez snimanja
Exec=@QtBinariesDir@/qdbus org.kde.Spectacle / OpenWithoutScreenshot
Version=5
Version=6
Id=spectacle-new-config
File=spectaclerc
Group=GuiConfig,General
......@@ -12,6 +12,7 @@ Group=GuiConfig,Save
Key=compressionQuality
Key=lastUsedSaveMode
Group=General,Save
Key=onLaunchActionIndex,onLaunchAction
Key=copySaveLocation
Key=lastSaveAsFile,lastSaveAsLocation
Key=lastSaveFile,lastSaveLocation
......
......@@ -118,7 +118,7 @@
<sect1 id="taking-screenshot">
<title>Taking A Screenshot</title>
<para>When you open &spectacle;, it immediately takes a screenshot of the whole screen as a convenience and shows a preview of it in the main window. You can save this screenshot using the buttons on the bottom of the window, or take a new one using the controls to the right of the preview.</para>
<para>When you open &spectacle;, it immediately takes a screenshot, unless otherwise set in the general options, of the whole screen as a convenience and shows a preview of it in the main window. You can save this screenshot using the buttons on the bottom of the window, or take a new one using the controls to the right of the preview.</para>
<para>To discard the current screenshot and take another screenshot, press the <guibutton>Take a New Screenshot</guibutton> (<keycombo action="simul">&Ctrl;<keycap>N</keycap></keycombo>) button.</para>
......@@ -285,6 +285,12 @@
</textobject>
</mediaobject>
<variablelist>
<varlistentry>
<term><guilabel>When launching Spectacle</guilabel></term>
<listitem>
<para>Allows to <guilabel>Take full screen screenshot</guilabel>, use last-used capture mode, or do not take a screenshot automatically. The last-used capture mode is the one set in Capture Mode</para>
</listitem>
</varlistentry>
<varlistentry>
<term><guilabel>After taking a screenshot</guilabel></term>
<listitem>
......
......@@ -82,6 +82,13 @@
</listitem>
</varlistentry>
<varlistentry>
<term><option>-l, --launchonly</option></term>
<listitem>
<para>Launch Spectacle without taking a screenshot.</para>
</listitem>
</varlistentry>
<varlistentry>
<term><option>-g, --gui</option></term>
<listitem>
......
......@@ -39,6 +39,11 @@ void KSImageWidget::setScaledPixmap()
setPixmap(scaledPixmap);
}
bool KSImageWidget::isPixmapSet()
{
return !mPixmap.isNull();
}
// drag handlers
void KSImageWidget::mousePressEvent(QMouseEvent *event)
......
......@@ -23,6 +23,7 @@ class KSImageWidget : public QLabel
public:
explicit KSImageWidget(QWidget *parent = nullptr);
void setScreenshot(const QPixmap &pixmap);
bool isPixmapSet();
Q_SIGNALS:
......
......@@ -18,6 +18,7 @@
#include <QDBusMessage>
#include <QDesktopServices>
#include <QKeyEvent>
#include <QPainter>
#include <QPrintDialog>
#include <QPushButton>
#include <QTimer>
......@@ -539,6 +540,13 @@ void KSMainWindow::screenshotFailed()
KMessageWidget::Warning);
}
void KSMainWindow::setPlaceholderTextOnLaunch()
{
QString placeholderText(i18n("Ready to take a screenshot"));
mKSWidget->showPlaceholderText(placeholderText);
setWindowTitle(placeholderText);
}
void KSMainWindow::showPreferencesDialog()
{
if (KConfigDialog::showDialog(QStringLiteral("settings"))) {
......@@ -595,7 +603,13 @@ void KSMainWindow::restoreWindowTitle()
if (isWindowModified()) {
setWindowTitle(i18nc("@title:window Unsaved Screenshot", "Unsaved[*]"));
} else {
setWindowTitle(Settings::lastSaveLocation().fileName());
// if a screenshot is not visible inside of mKSWidget, it means we have launched spectacle
// with the last mode set to 'rectangular region' and canceled the screenshot
if (mKSWidget->isScreenshotSet()) {
setWindowTitle(Settings::lastSaveLocation().fileName());
} else {
setPlaceholderTextOnLaunch();
}
}
}
......
......@@ -67,6 +67,7 @@ public Q_SLOTS:
void imageSaved(const QUrl &location);
void imageSavedAndCopied(const QUrl &location);
void screenshotFailed();
void setPlaceholderTextOnLaunch();
Q_SIGNALS:
......
......@@ -164,8 +164,23 @@ KSWidget::KSWidget(Platform::GrabModes theGrabModes, QWidget *parent)
mRightLayout->addWidget(mTakeScreenshotButton, 1, Qt::AlignHCenter);
mRightLayout->setContentsMargins(10, 0, 0, 10);
mPlaceholderLabel = new QLabel;
QFont placeholderLabelFont;
// To match the size of a level 2 Heading/KTitleWidget
placeholderLabelFont.setPointSize(qRound(placeholderLabelFont.pointSize() * 1.3));
mPlaceholderLabel->setFont(placeholderLabelFont);
mPlaceholderLabel->setTextInteractionFlags(Qt::NoTextInteraction);
mPlaceholderLabel->setWordWrap(true);
mPlaceholderLabel->setAlignment(Qt::AlignCenter);
// Match opacity of QML placeholder label component
auto *effect = new QGraphicsOpacityEffect(mPlaceholderLabel);
effect->setOpacity(0.5);
mPlaceholderLabel->setGraphicsEffect(effect);
mMainLayout = new QGridLayout();
mMainLayout->addWidget(mPlaceholderLabel, 0, 0, 1, 1);
mMainLayout->addWidget(mImageWidget, 0, 0, 1, 1);
mMainLayout->addLayout(mRightLayout, 0, 1, 1, 1);
mMainLayout->setColumnMinimumWidth(0, 320);
......@@ -202,10 +217,24 @@ int KSWidget::imagePaddingWidth() const
return lPaddingWidth;
}
bool KSWidget::isScreenshotSet()
{
return mImageWidget->isPixmapSet();
}
// public slots
void KSWidget::showPlaceholderText(const QString &label)
{
mPlaceholderLabel->setText(label);
mPlaceholderLabel->show();
}
void KSWidget::setScreenshotPixmap(const QPixmap &thePixmap)
{
if (mPlaceholderLabel->isVisible()) {
mPlaceholderLabel->hide();
}
mImageWidget->setScreenshot(thePixmap);
}
......
......@@ -44,6 +44,7 @@ public:
enum class State { TakeNewScreenshot, Cancel };
int imagePaddingWidth() const;
bool isScreenshotSet();
Q_SIGNALS:
......@@ -53,6 +54,7 @@ Q_SIGNALS:
public Q_SLOTS:
void showPlaceholderText(const QString &label);
void setScreenshotPixmap(const QPixmap &thePixmap);
void lockOnClickDisabled();
void lockOnClickEnabled();
......@@ -87,12 +89,14 @@ private:
QCheckBox *mQuitAfterSaveOrCopy{nullptr};
QLabel *mCaptureModeLabel{nullptr};
QLabel *mContentOptionsLabel{nullptr};
QLabel *mPlaceholderLabel { nullptr };
bool mTransientWithParentAvailable{false};
QAction *mTakeNewScreenshotAction{nullptr};
QAction *mCancelAction{nullptr};
KConfigDialogManager *mConfigManager{nullptr};
QStackedLayout *mStack{nullptr};
QWidget *placeHolder{nullptr};
#ifdef KIMAGEANNOTATOR_FOUND
kImageAnnotator::KImageAnnotator *mAnnotator{nullptr};
#endif
......
......@@ -12,20 +12,46 @@
</property>
<layout class="QFormLayout">
<item row="0" column="0">
<widget class="QLabel" name="onLaunchSpectacleLabel">
<property name="text">
<string>When launching Spectacle:</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QComboBox" name="kcfg_onLaunchAction">
<item>
<property name="text">
<string>Take full screen screenshot</string>
</property>
</item>
<item>
<property name="text">
<string>Use last-used capture mode</string>
</property>
</item>
<item>
<property name="text">
<string>Do not take a screenshot automatically</string>
</property>
</item>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="afterScreenshotLabel">
<property name="text">
<string>After taking a screenshot:</string>
</property>
</widget>
</item>
<item row="0" column="1">
<item row="1" column="1">
<widget class="QCheckBox" name="kcfg_autoSaveImage">
<property name="text">
<string>Autosave file to default folder</string>
</property>
</widget>
</item>
<item row="2" column="0" colspan="2">
<item row="3" column="0" colspan="2">
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
......@@ -41,21 +67,21 @@
</property>
</spacer>
</item>
<item row="3" column="0" colspan="2">
<item row="4" column="0" colspan="2">
<widget class="KTitleWidget" name="runningTitle">
<property name="text">
<string>While Spectacle is running</string>
</property>
</widget>
</item>
<item row="4" column="0">
<item row="5" column="0">
<widget class="QLabel" name="printKeyActionLabel">
<property name="text">
<string>Press screenshot key to:</string>
</property>
</widget>
</item>
<item row="4" column="1">
<item row="5" column="1">
<widget class="QGroupBox" name="kcfg_printKeyActionRunning">
<property name="title">
<string/>
......@@ -94,7 +120,7 @@
</layout>
</widget>
</item>
<item row="5" column="0" colspan="2">
<item row="6" column="0" colspan="2">
<spacer name="verticalSpacer_2">
<property name="orientation">
<enum>Qt::Vertical</enum>
......@@ -110,42 +136,42 @@
</property>
</spacer>
</item>
<item row="6" column="0" colspan="2">
<item row="7" column="0" colspan="2">
<widget class="KTitleWidget" name="regionTitle">
<property name="text">
<string>Rectangular Region</string>
</property>
</widget>
</item>
<item row="7" column="0">
<item row="8" column="0">
<widget class="QLabel" name="generalLabel">
<property name="text">
<string>General:</string>
</property>
</widget>
</item>
<item row="7" column="1">
<item row="8" column="1">
<widget class="QCheckBox" name="kcfg_useLightMaskColour">
<property name="text">
<string>Use light background</string>
</property>
</widget>
</item>
<item row="8" column="1">
<item row="9" column="1">
<widget class="QCheckBox" name="kcfg_showMagnifier">
<property name="text">
<string>Show magnifier</string>
</property>
</widget>
</item>
<item row="9" column="1">
<item row="10" column="1">
<widget class="QCheckBox" name="kcfg_useReleaseToCapture">
<property name="text">
<string>Accept on click-and-release</string>
</property>
</widget>
</item>
<item row="10" column="1">
<item row="11" column="1">
<spacer name="verticalSpacer_3">
<property name="orientation">
<enum>Qt::Vertical</enum>
......@@ -161,16 +187,15 @@
</property>
</spacer>
</item>
<item row="11" column="0">
<item row="12" column="0">
<widget class="QLabel" name="rememberLabel">
<property name="text">
<string>Remember selected area:</string>
</property>
</widget>
</item>
<item row="11" column="1">
<widget class="QRadioButton" name="
">
<item row="12" column="1">
<widget class="QRadioButton" name="">
<property name="text">
<string>Never</string>
</property>
......@@ -182,7 +207,7 @@
</attribute>
</widget>
</item>
<item row="12" column="1">
<item row="13" column="1">
<widget class="QRadioButton" name="kcfg_alwaysRememberRegion">
<property name="text">
<string>Always</string>
......@@ -192,7 +217,7 @@
</attribute>
</widget>
</item>
<item row="13" column="1">
<item row="14" column="1">
<widget class="QRadioButton" name="kcfg_rememberLastRectangularRegion">
<property name="text">
<string>Until Spectacle is closed</string>
......@@ -202,7 +227,7 @@
</attribute>
</widget>
</item>
<item row="1" column="1">
<item row="2" column="1">
<widget class="QGroupBox" name="kcfg_clipboardGroup">
<property name="title">
<string/>
......@@ -210,7 +235,7 @@
<property name="flat">
<bool>true</bool>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<layout class="QVBoxLayout" name="verticalLayout2">
<property name="leftMargin">
<number>0</number>
</property>
......@@ -251,6 +276,8 @@
</customwidget>
</customwidgets>
<tabstops>
<tabstop>defaultOnLaunchButton</tabstop>
<tabstop>kcfg_onLaunchAction</tabstop>
<tabstop>kcfg_autoSaveImage</tabstop>
<tabstop>newScreenshotButton</tabstop>
<tabstop>newWindowButton</tabstop>
......
......@@ -13,6 +13,7 @@
#include <KWindowSystem>
#include <QCheckBox>
#include <QComboBox>
GeneralOptionsPage::GeneralOptionsPage(QWidget *parent)
: QWidget(parent)
......@@ -23,7 +24,7 @@ GeneralOptionsPage::GeneralOptionsPage(QWidget *parent)
m_ui->runningTitle->setLevel(2);
m_ui->regionTitle->setLevel(2);
// On Wayland we can't programmatically raise and focus the window so we have to hide the option
//On Wayland we can't programmatically raise and focus the window so we have to hide the option
if (KWindowSystem::isPlatformWayland() || qstrcmp(qgetenv("XDG_SESSION_TYPE").data(), "wayland") == 0) {
delete m_ui->activateWindowButton;
}
......
......@@ -8,6 +8,15 @@
<include>SpectacleCommon.h</include>
<kcfgfile />
<group name="General">
<entry name="onLaunchAction" type="Enum">
<label>What to do when Spectacle is launched</label>
<choices>
<choice name="TakeFullscreenScreenshot"></choice>
<choice name="UseLastUsedCapturemode"></choice>
<choice name="DoNotTakeScreenshot"></choice>
</choices>
<default>TakeFullscreenScreenshot</default>
</entry>
<entry name="printKeyActionRunning" type="Enum">
<label>What should happen if print key is pressed when Spectacle is already running</label>
<choices>
......
......@@ -27,6 +27,7 @@ ShortcutActions::ShortcutActions()
// CurrentMonitorScreenShot
// RectangularRegionScreenShot
// FullScreenScreenShot
// OpenWithoutScreenshot
// _launch
{
QAction *action = new QAction(i18n("Launch Spectacle"));
......@@ -58,6 +59,11 @@ ShortcutActions::ShortcutActions()
action->setObjectName(QStringLiteral("WindowUnderCursorScreenShot"));
mActions.addAction(action->objectName(), action);
}
{
QAction *action = new QAction(i18n("Launch Spectacle without capturing"));
action->setObjectName(QStringLiteral("OpenWithoutScreenshot"));
mActions.addAction(action->objectName(), action);
}
}
KActionCollection *ShortcutActions::shortcutActions()
......@@ -99,3 +105,8 @@ QAction *ShortcutActions::windowUnderCursorAction() const
{
return mActions.action(5);
}
QAction *ShortcutActions::openWithoutScreenshotAction() const
{
return mActions.action(6);
}
......@@ -24,6 +24,7 @@ public:
QAction *activeWindowAction() const;
QAction *regionAction() const;
QAction *windowUnderCursorAction() const;
QAction *openWithoutScreenshotAction() const;
private:
ShortcutActions();
......
......@@ -85,20 +85,6 @@ void SpectacleCore::onActivateRequested(QStringList arguments, const QString & /
populateCommandLineParser(parser.data());
parser->parse(arguments);
// extract the capture mode
Spectacle::CaptureMode lCaptureMode = Spectacle::CaptureMode::AllScreens;
if (parser->isSet(QStringLiteral("current"))) {
lCaptureMode = Spectacle::CaptureMode::CurrentScreen;
} else if (parser->isSet(QStringLiteral("activewindow"))) {
lCaptureMode = Spectacle::CaptureMode::ActiveWindow;
} else if (parser->isSet(QStringLiteral("region"))) {
lCaptureMode = Spectacle::CaptureMode::RectangularRegion;
} else if (parser->isSet(QStringLiteral("windowundercursor"))) {
lCaptureMode = Spectacle::CaptureMode::TransientWithParent;
} else if (parser->isSet(QStringLiteral("transientonly"))) {
lCaptureMode = Spectacle::CaptureMode::WindowUnderCursor;
}
mStartMode = SpectacleCore::StartMode::Gui;
mNotify = true;
qint64 lDelayMsec = 0;
......@@ -110,6 +96,39 @@ void SpectacleCore::onActivateRequested(QStringList arguments, const QString & /
mStartMode = SpectacleCore::StartMode::DBus;
}
Spectacle::CaptureMode lCaptureMode = Spectacle::CaptureMode::AllScreens;
if (!mIsGuiInited && mStartMode == SpectacleCore::StartMode::Gui) {
if (parser->isSet(QStringLiteral("launchonly")) || Settings::onLaunchAction() == Settings::EnumOnLaunchAction::DoNotTakeScreenshot) {
initGuiNoScreenshot();
return;
} else if (Settings::onLaunchAction() == Settings::EnumOnLaunchAction::UseLastUsedCapturemode) {
lCaptureMode = Settings::captureMode();
} else if (parser->isSet(QStringLiteral("current"))) {
lCaptureMode = Spectacle::CaptureMode::CurrentScreen;
} else if (parser->isSet(QStringLiteral("activewindow"))) {
lCaptureMode = Spectacle::CaptureMode::ActiveWindow;
} else if (parser->isSet(QStringLiteral("region"))) {
lCaptureMode = Spectacle::CaptureMode::RectangularRegion;
} else if (parser->isSet(QStringLiteral("windowundercursor"))) {
lCaptureMode = Spectacle::CaptureMode::TransientWithParent;
} else if (parser->isSet(QStringLiteral("transientonly"))) {
lCaptureMode = Spectacle::CaptureMode::WindowUnderCursor;
}
} else {
// extract the capture mode
if (parser->isSet(QStringLiteral("current"))) {
lCaptureMode = Spectacle::CaptureMode::CurrentScreen;
} else if (parser->isSet(QStringLiteral("activewindow"))) {
lCaptureMode = Spectacle::CaptureMode::ActiveWindow;
} else if (parser->isSet(QStringLiteral("region"))) {
lCaptureMode = Spectacle::CaptureMode::RectangularRegion;
} else if (parser->isSet(QStringLiteral("windowundercursor"))) {
lCaptureMode = Spectacle::CaptureMode::TransientWithParent;
} else if (parser->isSet(QStringLiteral("transientonly"))) {
lCaptureMode = Spectacle::CaptureMode::WindowUnderCursor;
}
}
auto lExportManager = ExportManager::instance();
lExportManager->setCaptureMode(lCaptureMode);
......@@ -233,6 +252,8 @@ void SpectacleCore::setUpShortcuts()
KGlobalAccel::self()->setGlobalShortcut(ShortcutActions::self()->regionAction(), Qt::META | Qt::SHIFT | Qt::Key_Print);
KGlobalAccel::self()->setGlobalShortcut(ShortcutActions::self()->currentScreenAction(), QList<QKeySequence>());
KGlobalAccel::self()->setGlobalShortcut(ShortcutActions::self()->openWithoutScreenshotAction(), QList<QKeySequence>());
}
QString SpectacleCore::filename() const
......@@ -343,6 +364,11 @@ void SpectacleCore::screenshotUpdated(const QPixmap &thePixmap)
}
} break;
case StartMode::Gui:
if (thePixmap.isNull()) {
mMainWindow->setScreenshotAndShow(thePixmap);
mMainWindow->setPlaceholderTextOnLaunch();
return;
}
mMainWindow->setScreenshotAndShow(thePixmap);
bool autoSaveImage = Settings::autoSaveImage();
......@@ -475,6 +501,7 @@ void SpectacleCore::populateCommandLineParser(QCommandLineParser *lCmdLineParser
{{QStringLiteral("u"), QStringLiteral("windowundercursor")}, i18n("Capture the window currently under the cursor, including parents of pop-up menus")},
{{QStringLiteral("t"), QStringLiteral("transientonly")}, i18n("Capture the window currently under the cursor, excluding parents of pop-up menus")},
{{QStringLiteral("r"), QStringLiteral("region")}, i18n("Capture a rectangular region of the screen")},
{{QStringLiteral("l"), QStringLiteral("launchonly")}, i18n("Launch Spectacle without taking a screenshot")},
{{QStringLiteral("g"), QStringLiteral("gui")}, i18n("Start in GUI mode (default)")},
{{QStringLiteral("b"), QStringLiteral("background")}, i18n("Take a screenshot and exit without showing the GUI")},
{{QStringLiteral("s"), QStringLiteral("dbus")}, i18n("Start in DBus-Activation mode")},
......@@ -535,7 +562,7 @@ Platform::GrabMode SpectacleCore::toPlatformGrabMode(Spectacle::CaptureMode theC
return Platform::GrabMode::InvalidChoice;
}
void SpectacleCore::initGui(int theDelay, bool theIncludePointer, bool theIncludeDecorations)
void SpectacleCore::ensureGuiInitiad()
{
if (!mIsGuiInited) {
mMainWindow = std::make_unique<KSMainWindow>(mPlatform->supportedGrabModes(), mPlatform->supportedShutterModes());
......@@ -545,6 +572,17 @@ void SpectacleCore::initGui(int theDelay, bool theIncludePointer, bool theInclud
mIsGuiInited = true;
}
}
void SpectacleCore::initGui(int theDelay, bool theIncludePointer, bool theIncludeDecorations)
{
ensureGuiInitiad();
takeNewScreenshot(ExportManager::instance()->captureMode(), theDelay, theIncludePointer, theIncludeDecorations);
}
void SpectacleCore::initGuiNoScreenshot()
{
ensureGuiInitiad();
screenshotUpdated(QPixmap());
}
......@@ -45,6 +45,7 @@ public:
void setFilename