// SPDX-License-Identifier: GPL-3.0-or-later // SPDX-FileCopyrightText: 2017-2018 Alejandro Sirgo Rica & Contributors #include "capturelauncher.h" #include "src/core/controller.h" #include "src/utils/globalvalues.h" #include "src/utils/screengrabber.h" #include "src/utils/screenshotsaver.h" #include "src/widgets/imagelabel.h" #include #include #include #include #include #include #include #include // https://github.com/KDE/spectacle/blob/941c1a517be82bed25d1254ebd735c29b0d2951c/src/Gui/KSWidget.cpp // https://github.com/KDE/spectacle/blob/941c1a517be82bed25d1254ebd735c29b0d2951c/src/Gui/KSMainWindow.cpp CaptureLauncher::CaptureLauncher(QDialog* parent) : QDialog(parent) { qApp->installEventFilter(this); // see eventFilter() setAttribute(Qt::WA_DeleteOnClose); setWindowIcon(QIcon(GlobalValues::iconPath())); m_imageLabel = new ImageLabel(this); bool ok; m_imageLabel->setScreenshot(ScreenGrabber().grabEntireDesktop(ok)); if (!ok) { } m_imageLabel->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); connect(m_imageLabel, &ImageLabel::dragInitiated, this, &CaptureLauncher::startDrag); QGridLayout* layout = new QGridLayout(this); layout->addWidget(m_imageLabel, 0, 0); m_CaptureModeLabel = new QLabel(tr("Capture Mode")); m_captureType = new QComboBox(); m_captureType->setMinimumWidth(240); // TODO remember number m_captureType->insertItem( 1, tr("Rectangular Region"), CaptureRequest::GRAPHICAL_MODE); #if defined(Q_OS_MACOS) // Following to MacOS philosophy (one application cannot be displayed on // more than one display) m_captureType->insertItem( 2, tr("Full Screen (Current Display)"), CaptureRequest::FULLSCREEN_MODE); #else m_captureType->insertItem( 2, tr("Full Screen (All Monitors)"), CaptureRequest::FULLSCREEN_MODE); #endif // m_captureType->insertItem(3, tr("Single Screen"), // CaptureRequest::SCREEN_MODE); m_delaySpinBox = new QSpinBox(); m_delaySpinBox->setSingleStep(1.0); m_delaySpinBox->setMinimum(0.0); m_delaySpinBox->setMaximum(999.0); m_delaySpinBox->setSpecialValueText(tr("No Delay")); m_delaySpinBox->setMinimumWidth(160); // with QT 5.7 qOverload(&QSpinBox::valueChanged), connect(m_delaySpinBox, static_cast(&QSpinBox::valueChanged), this, [this](int val) { QString sufix = val == 1 ? tr(" second") : tr(" seconds"); this->m_delaySpinBox->setSuffix(sufix); }); m_launchButton = new QPushButton(tr("Take new screenshot")); m_launchButton->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed); connect(m_launchButton, &QPushButton::clicked, this, &CaptureLauncher::startCapture); m_launchButton->setFocus(); QFormLayout* captureModeForm = new QFormLayout; captureModeForm->addRow(tr("Area:"), m_captureType); captureModeForm->addRow(tr("Delay:"), m_delaySpinBox); captureModeForm->setContentsMargins(24, 0, 0, 0); m_mainLayout = new QVBoxLayout(); m_mainLayout->addStretch(1); m_mainLayout->addWidget(m_CaptureModeLabel); m_mainLayout->addLayout(captureModeForm); m_mainLayout->addStretch(10); m_mainLayout->addWidget(m_launchButton, 1, Qt::AlignCenter); m_mainLayout->setContentsMargins(10, 0, 0, 10); layout->addLayout(m_mainLayout, 0, 1); layout->setColumnMinimumWidth(0, 320); layout->setColumnMinimumWidth(1, 320); } // HACK: // https://github.com/KDE/spectacle/blob/fa1e780b8bf3df3ac36c410b9ece4ace041f401b/src/Gui/KSMainWindow.cpp#L70 void CaptureLauncher::startCapture() { m_launchButton->setEnabled(false); hide(); auto mode = static_cast( m_captureType->currentData().toInt()); CaptureRequest req(mode, 600 + m_delaySpinBox->value() * 1000); connectCaptureSlots(); Controller::getInstance()->requestCapture(req); } void CaptureLauncher::startDrag() { QDrag* dragHandler = new QDrag(this); QMimeData* mimeData = new QMimeData; #if (QT_VERSION >= QT_VERSION_CHECK(5, 15, 0)) mimeData->setImageData(m_imageLabel->pixmap(Qt::ReturnByValue)); #else mimeData->setImageData(m_imageLabel->pixmap()); #endif dragHandler->setMimeData(mimeData); #if (QT_VERSION >= QT_VERSION_CHECK(5, 15, 0)) dragHandler->setPixmap( m_imageLabel->pixmap(Qt::ReturnByValue) .scaled( 256, 256, Qt::KeepAspectRatioByExpanding, Qt::SmoothTransformation)); dragHandler->exec(); #else dragHandler->setPixmap(m_imageLabel->pixmap()->scaled( 256, 256, Qt::KeepAspectRatioByExpanding, Qt::SmoothTransformation)); dragHandler->exec(); #endif } void CaptureLauncher::connectCaptureSlots() { connect(Controller::getInstance(), &Controller::captureTaken, this, &CaptureLauncher::captureTaken); connect(Controller::getInstance(), &Controller::captureFailed, this, &CaptureLauncher::captureFailed); } void CaptureLauncher::disconnectCaptureSlots() { // Hack for MacOS // for some strange reasons MacOS sends multiple "captureTaken" signals // (random number, usually from 1 up to 20). // So no it enables signal on "Capture new screenshot" button and disables // on first success of fail. disconnect(Controller::getInstance(), &Controller::captureTaken, this, &CaptureLauncher::captureTaken); disconnect(Controller::getInstance(), &Controller::captureFailed, this, &CaptureLauncher::captureFailed); } void CaptureLauncher::captureTaken(QPixmap p, const QRect&) { // MacOS specific, more details in the function disconnectCaptureSlots() disconnectCaptureSlots(); m_imageLabel->setScreenshot(p); show(); auto mode = static_cast( m_captureType->currentData().toInt()); if (mode == CaptureRequest::FULLSCREEN_MODE) { ScreenshotSaver().saveToFilesystemGUI(p); } m_launchButton->setEnabled(true); } void CaptureLauncher::captureFailed() { // MacOS specific, more details in the function disconnectCaptureSlots() disconnectCaptureSlots(); show(); m_launchButton->setEnabled(true); }