diff --git a/src/Gui/KSMainWindow.cpp b/src/Gui/KSMainWindow.cpp index c2b3ac1..6c7f37d 100644 --- a/src/Gui/KSMainWindow.cpp +++ b/src/Gui/KSMainWindow.cpp @@ -1,370 +1,367 @@ /* * 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 "KSMainWindow.h" #include "Config.h" #include #include #include #include #include #include #include #ifdef XCB_FOUND #include #include #endif #include #include #include #include #include #include #include #include "SettingsDialog/SettingsDialog.h" #include "ExportMenu.h" #include "ExportManager.h" #include "SpectacleConfig.h" static const int DEFAULT_WINDOW_HEIGHT = 420; static const int DEFAULT_WINDOW_WIDTH = 840; static const int MAXIMUM_WINDOW_WIDTH = 1000; KSMainWindow::KSMainWindow(bool onClickAvailable, QWidget *parent) : QDialog(parent), mKSWidget(new KSWidget), mDivider(new QFrame), mDialogButtonBox(new QDialogButtonBox), mConfigureButton(new QToolButton), mToolsButton(new QPushButton), mSendToButton(new QPushButton), mClipboardButton(new QToolButton), mSaveButton(new QToolButton), mSaveMenu(new QMenu), + mSaveAsAction(new QAction), + mSaveAction(new QAction), mMessageWidget(new KMessageWidget), mToolsMenu(new QMenu), mExportMenu(new ExportMenu(this)), mOnClickAvailable(onClickAvailable) { // before we do anything, we need to set a window property // that skips the close/hide window animation on kwin. this // fixes a ghost image of the spectacle window that appears // on subsequent screenshots taken with the take new screenshot // button // // credits for this goes to Thomas Lübking #ifdef XCB_FOUND if (KWindowSystem::isPlatformX11()) { // create a window if we haven't already. note that the QWidget constructor // should already have done this if (winId() == 0) { create(0, true, true); } // do the xcb shenanigans xcb_connection_t *xcbConn = QX11Info::connection(); const QByteArray effectName = QByteArrayLiteral("_KDE_NET_WM_SKIP_CLOSE_ANIMATION"); xcb_intern_atom_cookie_t atomCookie = xcb_intern_atom_unchecked(xcbConn, false, effectName.length(), effectName.constData()); QScopedPointer atom(xcb_intern_atom_reply(xcbConn, atomCookie, nullptr)); if (atom.isNull()) { goto done; } uint32_t value = 1; xcb_change_property(xcbConn, XCB_PROP_MODE_REPLACE, winId(), atom->atom, XCB_ATOM_CARDINAL, 32, 1, &value); } #endif done: QMetaObject::invokeMethod(this, "init", Qt::QueuedConnection); } KSMainWindow::~KSMainWindow() {} SaveMode KSMainWindow::saveButtonMode() const { const SpectacleConfig *cfgManager = SpectacleConfig::instance(); return cfgManager->useDynamicSaveButton() ? cfgManager->lastUsedSaveMode() : SaveMode::SaveAs; } // GUI init void KSMainWindow::init() { KSharedConfigPtr config = KSharedConfig::openConfig(QStringLiteral("spectaclerc")); KConfigGroup guiConfig(config, "GuiConfig"); // window properties setWindowFlags(windowFlags() & ~Qt::WindowContextHelpButtonHint); QPoint location = guiConfig.readEntry("window-position", QPoint(50, 50)); move(location); // change window title on save connect(ExportManager::instance(), &ExportManager::imageSaved, this, &KSMainWindow::setScreenshotWindowTitle); // the KSGWidget connect(mKSWidget, &KSWidget::newScreenshotRequest, this, &KSMainWindow::captureScreenshot); connect(mKSWidget, &KSWidget::dragInitiated, this, &KSMainWindow::dragAndDropRequest); // the Button Bar mDialogButtonBox->setStandardButtons(QDialogButtonBox::Help); mConfigureButton->setDefaultAction(KStandardAction::preferences(this, SLOT(showPreferencesDialog()), this)); mConfigureButton->setText(i18n("Configure...")); mConfigureButton->setToolTip(i18n("Change Spectacle's settings.")); mConfigureButton->setToolButtonStyle(Qt::ToolButtonTextBesideIcon); mDialogButtonBox->addButton(mConfigureButton, QDialogButtonBox::ResetRole); KGuiItem::assign(mToolsButton, KGuiItem(i18n("Tools"))); mToolsButton->setIcon(QIcon::fromTheme(QStringLiteral("application-menu"))); mDialogButtonBox->addButton(mToolsButton, QDialogButtonBox::ActionRole); mToolsMenu->addAction(KStandardAction::print(this, SLOT(showPrintDialog()), this)); mToolsButton->setMenu(mToolsMenu); KGuiItem::assign(mSendToButton, KGuiItem(i18n("Export"))); mSendToButton->setIcon(QIcon::fromTheme(QStringLiteral("document-share"))); mDialogButtonBox->addButton(mSendToButton, QDialogButtonBox::ActionRole); mClipboardButton->setDefaultAction(KStandardAction::copy(this, SLOT(sendToClipboard()), this)); mClipboardButton->setText(i18n("Copy To Clipboard")); mClipboardButton->setToolTip(i18n("Copy the current screenshot image to the clipboard.")); mClipboardButton->setToolButtonStyle(Qt::ToolButtonTextBesideIcon); mDialogButtonBox->addButton(mClipboardButton, QDialogButtonBox::ActionRole); mSaveButton->setToolButtonStyle(Qt::ToolButtonTextBesideIcon); mSaveButton->setMenu(mSaveMenu); mSaveButton->setPopupMode(QToolButton::MenuButtonPopup); - buildSaveMenu(); mDialogButtonBox->addButton(mSaveButton, QDialogButtonBox::ActionRole); // the help menu - KHelpMenu *helpMenu = new KHelpMenu(this, KAboutData::applicationData(), true); mDialogButtonBox->button(QDialogButtonBox::Help)->setMenu(helpMenu->menu()); + // the save menu + mSaveAsAction = KStandardAction::saveAs(this, &KSMainWindow::saveAs, this); + mSaveAction = KStandardAction::save(this, &KSMainWindow::save, this); + mSaveMenu->addAction(mSaveAsAction); + mSaveMenu->addAction(mSaveAction); + setDefaultSaveAction(); + // message widget connect(mMessageWidget, &KMessageWidget::linkActivated, this, [](const QString &str) { QDesktopServices::openUrl(QUrl(str)); } ); // layouts mDivider->setFrameShape(QFrame::HLine); mDivider->setLineWidth(2); QVBoxLayout *layout = new QVBoxLayout(this); layout->addWidget(mKSWidget); layout->addWidget(mMessageWidget); layout->addWidget(mDivider); layout->addWidget(mDialogButtonBox); mMessageWidget->hide(); // populate our send-to actions mSendToButton->setMenu(mExportMenu); connect(mExportMenu, &ExportMenu::imageShared, this, &KSMainWindow::showImageSharedFeedback); // disable onClick mode if not available on the platform if (!mOnClickAvailable) { mKSWidget->disableOnClick(); } 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 } int KSMainWindow::windowWidth(const QPixmap &pixmap) const { // Calculates what the width of the window should be for the captured image to perfectly fit // the area reserved for the image, with the height already set. const float pixmapAspectRatio = (float)pixmap.width() / pixmap.height(); const int imageHeight = mKSWidget->height() - 2 * layout()->spacing(); const int imageWidth = pixmapAspectRatio * imageHeight; int alignedWindowWidth = qMin(mKSWidget->imagePaddingWidth() + imageWidth, MAXIMUM_WINDOW_WIDTH); alignedWindowWidth += layout()->contentsMargins().left() + layout()->contentsMargins().right(); alignedWindowWidth += 2; // margins is removing 1 - 1 pixel for some reason return alignedWindowWidth; } -void KSMainWindow::buildSaveMenu() +void KSMainWindow::setDefaultSaveAction() { - // first clear the menu - mSaveMenu->clear(); - - // get our actions in order - QAction *actionSave = KStandardAction::save(this, &KSMainWindow::save, this); - QAction *actionSaveAs = KStandardAction::saveAs(this, &KSMainWindow::saveAs, this); - mSaveMenu->addAction(actionSaveAs); - mSaveMenu->addAction(actionSave); - - // put the actions in order switch (saveButtonMode()) { case SaveMode::SaveAs: - mSaveButton->setDefaultAction(actionSaveAs); + mSaveButton->setDefaultAction(mSaveAsAction); break; case SaveMode::Save: - mSaveButton->setDefaultAction(actionSave); + mSaveButton->setDefaultAction(mSaveAction); break; } } // overrides void KSMainWindow::moveEvent(QMoveEvent *event) { Q_UNUSED(event); KSharedConfigPtr config = KSharedConfig::openConfig(QStringLiteral("spectaclerc")); KConfigGroup guiConfig(config, "GuiConfig"); guiConfig.writeEntry("window-position", pos()); guiConfig.sync(); } // slots void KSMainWindow::captureScreenshot(ImageGrabber::GrabMode mode, int timeout, bool includePointer, bool includeDecorations) { hide(); emit newScreenshotRequest(mode, timeout, includePointer, includeDecorations); } void KSMainWindow::setScreenshotAndShow(const QPixmap &pixmap) { mKSWidget->setScreenshotPixmap(pixmap); mExportMenu->imageUpdated(); setWindowTitle(i18nc("Unsaved Screenshot", "Unsaved[*]")); setWindowModified(true); show(); resize(QSize(windowWidth(pixmap), DEFAULT_WINDOW_HEIGHT)); } void KSMainWindow::showPrintDialog() { QPrinter *printer = new QPrinter(QPrinter::HighResolution); QPrintDialog printDialog(printer, this); if (printDialog.exec() == QDialog::Accepted) { ExportManager::instance()->doPrint(printer); return; } delete printer; } void KSMainWindow::showImageSharedFeedback(bool error, const QString &message) { if (error) { mMessageWidget->setMessageType(KMessageWidget::Error); mMessageWidget->setText(i18n("There was a problem sharing the image: %1", message)); mMessageWidget->setIcon(QIcon::fromTheme(QStringLiteral("dialog-error"))); } else { mMessageWidget->setMessageType(KMessageWidget::Positive); if (message.isEmpty()) mMessageWidget->setText(i18n("Image shared")); else mMessageWidget->setText(i18n("You can find the shared image at: %1", message)); mMessageWidget->setIcon(QIcon::fromTheme(QStringLiteral("dialog-ok-apply"))); } mMessageWidget->animatedShow(); QTimer::singleShot(20000, mMessageWidget, &KMessageWidget::animatedHide); } 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"))); mMessageWidget->animatedShow(); QTimer::singleShot(10000, mMessageWidget, &KMessageWidget::animatedHide); } void KSMainWindow::showPreferencesDialog() { SettingsDialog prefDialog(this); prefDialog.exec(); } void KSMainWindow::setScreenshotWindowTitle(QUrl location) { setWindowTitle(location.fileName()); setWindowModified(false); } void KSMainWindow::save() { SpectacleConfig::instance()->setLastUsedSaveMode(SaveMode::Save); - buildSaveMenu(); + setDefaultSaveAction(); if (SpectacleConfig::instance()->quitAfterSaveOrCopyChecked()) { ExportManager::instance()->doSave(QUrl(), true); qApp->setQuitOnLastWindowClosed(false); hide(); } else { ExportManager::instance()->doSave(); } } void KSMainWindow::saveAs() { SpectacleConfig::instance()->setLastUsedSaveMode(SaveMode::SaveAs); - buildSaveMenu(); + setDefaultSaveAction(); 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 fc3cb99..3d8d421 100644 --- a/src/Gui/KSMainWindow.h +++ b/src/Gui/KSMainWindow.h @@ -1,93 +1,95 @@ /* * 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 KSMAINWINDOW_H #define KSMAINWINDOW_H #include #include #include #include #include #include #include "PlatformBackends/ImageGrabber.h" #include "ExportMenu.h" #include "KSWidget.h" #include "SpectacleConfig.h" class KSMainWindow : public QDialog { Q_OBJECT public: explicit KSMainWindow(bool onClickAvailable, QWidget *parent = 0); ~KSMainWindow(); private: SaveMode saveButtonMode() const; private slots: void captureScreenshot(ImageGrabber::GrabMode mode, int timeout, bool includePointer, bool includeDecorations); void showPrintDialog(); void showPreferencesDialog(); void showImageSharedFeedback(bool error, const QString &message); void sendToClipboard(); void init(); - void buildSaveMenu(); + void setDefaultSaveAction(); void save(); void saveAs(); int windowWidth(const QPixmap &pixmap) const; public slots: void setScreenshotAndShow(const QPixmap &pixmap); void setScreenshotWindowTitle(QUrl location); signals: void newScreenshotRequest(ImageGrabber::GrabMode mode, int timeout, bool includePointer, bool includeDecorations); void dragAndDropRequest(); protected: void moveEvent(QMoveEvent *event) Q_DECL_OVERRIDE; private: KSWidget *mKSWidget; QFrame *mDivider; QDialogButtonBox *mDialogButtonBox; QToolButton *mConfigureButton; QPushButton *mToolsButton; QPushButton *mSendToButton; QToolButton *mClipboardButton; QToolButton *mSaveButton; QMenu *mSaveMenu; + QAction *mSaveAsAction; + QAction *mSaveAction; KMessageWidget *mMessageWidget; QMenu *mToolsMenu; ExportMenu *mExportMenu; bool mOnClickAvailable; }; #endif // KSMAINWINDOW_H