diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index a083188..d664cbf 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -1,87 +1,88 @@ # common - configure file and version definitions configure_file(Config.h.in ${CMAKE_CURRENT_BINARY_DIR}/Config.h) # target set( SPECTACLE_SRCS_DEFAULT Main.cpp SpectacleCore.cpp SpectacleDBusAdapter.cpp PlatformBackends/ImageGrabber.cpp PlatformBackends/DummyImageGrabber.cpp Gui/KSMainWindow.cpp Gui/KSWidget.cpp Gui/KSImageWidget.cpp Gui/KSSaveConfigDialog.cpp Gui/KSSendToMenu.cpp Gui/ScreenClipper.cpp + Gui/SmartSpinBox.cpp ) if(XCB_FOUND) set( SPECTACLE_SRCS_X11 PlatformBackends/X11ImageGrabber.cpp ) endif() if(KF5Kipi_FOUND) set( SPECTACLE_SRCS_KIPI KipiInterface/KSGKipiInterface.cpp KipiInterface/KSGKipiInfoShared.cpp KipiInterface/KSGKipiImageCollectionShared.cpp KipiInterface/KSGKipiImageCollectionSelector.cpp ) endif() set( SPECTACLE_SRCS_ALL ${SPECTACLE_SRCS_DEFAULT} ${SPECTACLE_SRCS_KIPI} ${SPECTACLE_SRCS_X11} ) add_executable( spectacle ${SPECTACLE_SRCS_ALL} ) # link libraries target_link_libraries( spectacle Qt5::DBus Qt5::PrintSupport KF5::CoreAddons KF5::DBusAddons KF5::WidgetsAddons KF5::Notifications KF5::ConfigCore KF5::I18n KF5::KIOWidgets KF5::WindowSystem KF5::XmlGui ) if(XCB_FOUND) target_link_libraries( spectacle XCB::XFIXES XCB::IMAGE XCB::CURSOR XCB::UTIL Qt5::X11Extras KF5::Screen ) endif() if(KF5Kipi_FOUND) target_link_libraries ( spectacle KF5::Kipi ) endif() install(TARGETS spectacle ${INSTALL_TARGETS_DEFAULT_ARGS}) diff --git a/src/Gui/KSWidget.cpp b/src/Gui/KSWidget.cpp index b153c0b..b3e4915 100644 --- a/src/Gui/KSWidget.cpp +++ b/src/Gui/KSWidget.cpp @@ -1,231 +1,231 @@ /* * Copyright (C) 2015 Boudhayan Gupta * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. */ #include "KSWidget.h" KSWidget::KSWidget(QWidget *parent) : QWidget(parent) { // we'll init the widget that holds the image first mImageWidget = new KSImageWidget(this); mImageWidget->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); connect(mImageWidget, &KSImageWidget::dragInitiated, this, &KSWidget::dragInitiated); // the capture mode options first mCaptureModeLabel = new QLabel(this); mCaptureModeLabel->setText(i18n("Capture Mode")); mCaptureArea = new QComboBox(this); mCaptureArea->insertItem(1, i18n("Full Screen (All Monitors)"), ImageGrabber::FullScreen); mCaptureArea->insertItem(2, i18n("Current Screen"), ImageGrabber::CurrentScreen); mCaptureArea->insertItem(3, i18n("Active Window"), ImageGrabber::ActiveWindow); mCaptureArea->insertItem(4, i18n("Window Under Cursor"), ImageGrabber::WindowUnderCursor); mCaptureArea->insertItem(5, i18n("Rectangular Region"), ImageGrabber::RectangularRegion); mCaptureArea->setMinimumWidth(240); connect(mCaptureArea, static_cast(&QComboBox::currentIndexChanged), this, &KSWidget::captureModeChanged); - mDelayMsec = new QDoubleSpinBox(this); + mDelayMsec = new SmartSpinBox(this); mDelayMsec->setDecimals(1); mDelayMsec->setSingleStep(1.0); mDelayMsec->setMinimum(0.0); mDelayMsec->setMaximum(999.9); mDelayMsec->setSuffix(i18n(" seconds")); mDelayMsec->setMinimumWidth(160); - connect(mDelayMsec, static_cast(&QDoubleSpinBox::valueChanged), this, &KSWidget::captureDelayChanged); + connect(mDelayMsec, static_cast(&SmartSpinBox::valueChanged), this, &KSWidget::captureDelayChanged); mCaptureOnClick = new QCheckBox(this); mCaptureOnClick->setText(i18n("On Click")); mCaptureOnClick->setToolTip(i18n("Wait for a mouse click before capturing the screenshot image")); connect(mCaptureOnClick, &QCheckBox::stateChanged, this, &KSWidget::onClickStateChanged); connect(mCaptureOnClick, &QCheckBox::stateChanged, this, &KSWidget::checkboxStatesChanged); mDelayLayout = new QHBoxLayout; mDelayLayout->addWidget(mDelayMsec); mDelayLayout->addWidget(mCaptureOnClick); mCaptureModeForm = new QFormLayout; mCaptureModeForm->addRow(i18n("Area:"), mCaptureArea); mCaptureModeForm->addRow(i18n("Delay:"), mDelayLayout); mCaptureModeForm->setContentsMargins(24, 0, 0, 0); // the content options (mouse pointer, window decorations) mContentOptionsLabel = new QLabel(this); mContentOptionsLabel->setText(i18n("Content Options")); mMousePointer = new QCheckBox(this); mMousePointer->setText(i18n("Include mouse pointer")); mMousePointer->setToolTip(i18n("Show the mouse cursor in the screeenshot image")); connect(mMousePointer, &QCheckBox::stateChanged, this, &KSWidget::checkboxStatesChanged); mWindowDecorations = new QCheckBox(this); mWindowDecorations->setText(i18n("Include window titlebar and borders")); mWindowDecorations->setToolTip(i18n("Show the window title bar, the minimize/maximize/close buttons, and the window border")); mWindowDecorations->setEnabled(false); connect(mWindowDecorations, &QCheckBox::stateChanged, this, &KSWidget::checkboxStatesChanged); mCaptureTransientOnly = new QCheckBox(this); mCaptureTransientOnly->setText(i18n("Capture the current pop-up only")); mCaptureTransientOnly->setToolTip(i18n("Capture only the current pop-up window (like a menu, tooltip etc). " "If this is not enabled, the pop-up is captured along with the parent window")); mCaptureTransientOnly->setEnabled(false); connect(mCaptureTransientOnly, &QCheckBox::stateChanged, this, &KSWidget::checkboxStatesChanged); mContentOptionsForm = new QVBoxLayout; mContentOptionsForm->addWidget(mMousePointer); mContentOptionsForm->addWidget(mWindowDecorations); mContentOptionsForm->addWidget(mCaptureTransientOnly); mContentOptionsForm->setSpacing(16); mContentOptionsForm->setContentsMargins(24, 0, 0, 0); // the take new screenshot button mTakeScreenshotButton = new QPushButton(this); mTakeScreenshotButton->setText(i18n("Take New Screenshot")); mTakeScreenshotButton->setIcon(QIcon::fromTheme("spectacle")); mTakeScreenshotButton->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed); mTakeScreenshotButton->setFocus(); connect(mTakeScreenshotButton, &QPushButton::clicked, this, &KSWidget::newScreenshotClicked); QShortcut *shortcut = new QShortcut(QKeySequence(QKeySequence::New), mTakeScreenshotButton); auto clickFunc = [&]() { mTakeScreenshotButton->animateClick(100); QTimer::singleShot(100, mTakeScreenshotButton, &QPushButton::click); }; connect(shortcut, &QShortcut::activated, clickFunc); // finally, finish up the layouts 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); mRightLayout->setContentsMargins(20, 0, 0, 10); mMainLayout = new QGridLayout(this); mMainLayout->addWidget(mImageWidget, 0, 0, 1, 1); mMainLayout->addLayout(mRightLayout, 0, 1, 1, 1); mMainLayout->setColumnMinimumWidth(0, 400); mMainLayout->setColumnMinimumWidth(1, 400); // and read in the saved checkbox states and capture mode indices KSharedConfigPtr config = KSharedConfig::openConfig("spectaclerc"); KConfigGroup guiConfig(config, "GuiConfig"); mMousePointer->setChecked(guiConfig.readEntry("includePointer", true)); mWindowDecorations->setChecked(guiConfig.readEntry("includeDecorations", true)); mCaptureOnClick->setChecked(guiConfig.readEntry("waitCaptureOnClick", false)); mCaptureTransientOnly->setChecked(guiConfig.readEntry("transientOnly", false)); mCaptureArea->setCurrentIndex(guiConfig.readEntry("captureModeIndex", 0)); mDelayMsec->setValue(guiConfig.readEntry("captureDelay", (qreal)0)); // done } // public slots void KSWidget::setScreenshotPixmap(const QPixmap &pixmap) { mImageWidget->setScreenshot(pixmap); } void KSWidget::disableOnClick() { mCaptureOnClick->setEnabled(false); mDelayMsec->setEnabled(true); } // private slots void KSWidget::newScreenshotClicked() { int delay = mCaptureOnClick->isChecked() ? -1 : (mDelayMsec->value() * 1000); ImageGrabber::GrabMode mode = static_cast(mCaptureArea->currentData().toInt()); if (mode == ImageGrabber::WindowUnderCursor && !(mCaptureTransientOnly->isChecked())) { mode = ImageGrabber::TransientWithParent; } emit newScreenshotRequest(mode, delay, mMousePointer->isChecked(), mWindowDecorations->isChecked()); } void KSWidget::checkboxStatesChanged(int state) { Q_UNUSED(state); KSharedConfigPtr config = KSharedConfig::openConfig("spectaclerc"); KConfigGroup guiConfig(config, "GuiConfig"); guiConfig.writeEntry("includePointer", mMousePointer->isChecked()); guiConfig.writeEntry("includeDecorations", mWindowDecorations->isChecked()); guiConfig.writeEntry("waitCaptureOnClick", mCaptureOnClick->isChecked()); guiConfig.writeEntry("transientOnly", mCaptureTransientOnly->isChecked()); guiConfig.sync(); } void KSWidget::onClickStateChanged(int state) { if (state == Qt::Checked) { mDelayMsec->setEnabled(false); } else if (state == Qt::Unchecked) { mDelayMsec->setEnabled(true); } } void KSWidget::captureModeChanged(int index) { KSharedConfigPtr config = KSharedConfig::openConfig("spectaclerc"); KConfigGroup guiConfig(config, "GuiConfig"); guiConfig.writeEntry("captureModeIndex", index); guiConfig.sync(); ImageGrabber::GrabMode mode = static_cast(mCaptureArea->itemData(index).toInt()); switch (mode) { case ImageGrabber::WindowUnderCursor: mWindowDecorations->setEnabled(true); mCaptureTransientOnly->setEnabled(true); break; case ImageGrabber::ActiveWindow: mWindowDecorations->setEnabled(true); mCaptureTransientOnly->setEnabled(false); break; default: mWindowDecorations->setEnabled(false); mCaptureTransientOnly->setEnabled(false); } } void KSWidget::captureDelayChanged(qreal value) { KSharedConfigPtr config = KSharedConfig::openConfig("spectaclerc"); KConfigGroup guiConfig(config, "GuiConfig"); guiConfig.writeEntry("captureDelay", value); guiConfig.sync(); } diff --git a/src/Gui/KSWidget.h b/src/Gui/KSWidget.h index db9d4cb..d70a577 100644 --- a/src/Gui/KSWidget.h +++ b/src/Gui/KSWidget.h @@ -1,91 +1,91 @@ /* * Copyright (C) 2015 Boudhayan Gupta * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. */ #ifndef KSWIDGET_H #define KSWIDGET_H #include #include #include #include #include #include #include #include #include #include #include -#include #include #include #include #include #include #include #include "PlatformBackends/ImageGrabber.h" #include "KSImageWidget.h" +#include "SmartSpinBox.h" class KSWidget : public QWidget { Q_OBJECT public: explicit KSWidget(QWidget *parent = 0); signals: void dragInitiated(); void newScreenshotRequest(ImageGrabber::GrabMode mode, int captureDelay, bool capturePointer, bool captureDecorations); public slots: void setScreenshotPixmap(const QPixmap &pixmap); void disableOnClick(); private slots: void newScreenshotClicked(); void checkboxStatesChanged(int state); void onClickStateChanged(int state); void captureModeChanged(int index); void captureDelayChanged(qreal value); private: - QGridLayout *mMainLayout; - QHBoxLayout *mDelayLayout; - QVBoxLayout *mRightLayout; - QFormLayout *mCaptureModeForm; - QVBoxLayout *mContentOptionsForm; - KSImageWidget *mImageWidget; - QPushButton *mTakeScreenshotButton; - QComboBox *mCaptureArea; - QDoubleSpinBox *mDelayMsec; - QCheckBox *mCaptureOnClick; - QCheckBox *mMousePointer; - QCheckBox *mWindowDecorations; - QCheckBox *mCaptureTransientOnly; - QLabel *mCaptureModeLabel; - QLabel *mContentOptionsLabel; + QGridLayout *mMainLayout; + QHBoxLayout *mDelayLayout; + QVBoxLayout *mRightLayout; + QFormLayout *mCaptureModeForm; + QVBoxLayout *mContentOptionsForm; + KSImageWidget *mImageWidget; + QPushButton *mTakeScreenshotButton; + QComboBox *mCaptureArea; + SmartSpinBox *mDelayMsec; + QCheckBox *mCaptureOnClick; + QCheckBox *mMousePointer; + QCheckBox *mWindowDecorations; + QCheckBox *mCaptureTransientOnly; + QLabel *mCaptureModeLabel; + QLabel *mContentOptionsLabel; }; #endif // KSWIDGET_H diff --git a/src/Gui/SmartSpinBox.cpp b/src/Gui/SmartSpinBox.cpp new file mode 100644 index 0000000..eb801aa --- /dev/null +++ b/src/Gui/SmartSpinBox.cpp @@ -0,0 +1,33 @@ +/* + * Copyright (C) 2015 Boudhayan Gupta + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#include +#include "SmartSpinBox.h" + +SmartSpinBox::SmartSpinBox(QWidget *parent) : + QDoubleSpinBox(parent) +{} + +QString SmartSpinBox::textFromValue(double val) const +{ + if ((qFloor(val) == val) && (qCeil(val) == val)) { + return QWidget::locale().toString(qint64(val)); + } + return QWidget::locale().toString(val, 'f', decimals()); +} diff --git a/src/Gui/SmartSpinBox.h b/src/Gui/SmartSpinBox.h new file mode 100644 index 0000000..b75e1cf --- /dev/null +++ b/src/Gui/SmartSpinBox.h @@ -0,0 +1,35 @@ +/* + * Copyright (C) 2015 Boudhayan Gupta + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#ifndef SMARTSPINBOX_H +#define SMARTSPINBOX_H + +#include + +class SmartSpinBox : public QDoubleSpinBox +{ + Q_OBJECT + + public: + + explicit SmartSpinBox(QWidget *parent = 0); + QString textFromValue(double val) const Q_DECL_OVERRIDE; +}; + +#endif // SMARTSPINBOX_H