mirror of
https://github.com/qTox/qTox.git
synced 2024-03-22 14:00:36 +08:00
261 lines
7.7 KiB
C++
261 lines
7.7 KiB
C++
/*
|
|
Copyright © 2015-2018 by The qTox Project Contributors
|
|
|
|
This file is part of qTox, a Qt-based graphical interface for Tox.
|
|
|
|
qTox is libre software: you can redistribute it and/or modify
|
|
it under the terms of the GNU General Public License as published by
|
|
the Free Software Foundation, either version 3 of the License, or
|
|
(at your option) any later version.
|
|
|
|
qTox 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 General Public License
|
|
along with qTox. If not, see <http://www.gnu.org/licenses/>.
|
|
*/
|
|
|
|
#include "screenshotgrabber.h"
|
|
|
|
#include <QApplication>
|
|
#include <QDebug>
|
|
#include <QDesktopWidget>
|
|
#include <QGraphicsPixmapItem>
|
|
#include <QGraphicsRectItem>
|
|
#include <QGraphicsSceneMouseEvent>
|
|
#include <QGraphicsView>
|
|
#include <QMouseEvent>
|
|
#include <QScreen>
|
|
#include <QTimer>
|
|
|
|
#include "screengrabberchooserrectitem.h"
|
|
#include "screengrabberoverlayitem.h"
|
|
#include "toolboxgraphicsitem.h"
|
|
#include "src/widget/widget.h"
|
|
|
|
ScreenshotGrabber::ScreenshotGrabber()
|
|
: QObject()
|
|
, mKeysBlocked(false)
|
|
, scene(nullptr)
|
|
, mQToxVisible(true)
|
|
{
|
|
window = new QGraphicsView(scene); // Top-level widget
|
|
window->setWindowFlags(Qt::FramelessWindowHint | Qt::BypassWindowManagerHint);
|
|
window->setContentsMargins(0, 0, 0, 0);
|
|
window->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
|
|
window->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
|
|
window->setFrameShape(QFrame::NoFrame);
|
|
window->installEventFilter(this);
|
|
pixRatio = QApplication::primaryScreen()->devicePixelRatio();
|
|
|
|
setupScene();
|
|
}
|
|
|
|
void ScreenshotGrabber::reInit()
|
|
{
|
|
window->resetCachedContent();
|
|
setupScene();
|
|
showGrabber();
|
|
mKeysBlocked = false;
|
|
}
|
|
|
|
ScreenshotGrabber::~ScreenshotGrabber()
|
|
{
|
|
delete scene;
|
|
delete window;
|
|
}
|
|
|
|
bool ScreenshotGrabber::eventFilter(QObject* object, QEvent* event)
|
|
{
|
|
if (event->type() == QEvent::KeyPress)
|
|
return handleKeyPress(static_cast<QKeyEvent*>(event));
|
|
|
|
return QObject::eventFilter(object, event);
|
|
}
|
|
|
|
void ScreenshotGrabber::showGrabber()
|
|
{
|
|
this->screenGrab = grabScreen();
|
|
this->screenGrabDisplay->setPixmap(this->screenGrab);
|
|
this->window->show();
|
|
this->window->setFocus();
|
|
this->window->grabKeyboard();
|
|
|
|
QRect fullGrabbedRect = screenGrab.rect();
|
|
QRect rec = QApplication::primaryScreen()->virtualGeometry();
|
|
|
|
this->window->setGeometry(rec);
|
|
this->scene->setSceneRect(fullGrabbedRect);
|
|
this->overlay->setRect(fullGrabbedRect);
|
|
|
|
adjustTooltipPosition();
|
|
}
|
|
|
|
bool ScreenshotGrabber::handleKeyPress(QKeyEvent* event)
|
|
{
|
|
if (mKeysBlocked)
|
|
return false;
|
|
|
|
if (event->key() == Qt::Key_Escape)
|
|
reject();
|
|
else if (event->key() == Qt::Key_Return || event->key() == Qt::Key_Enter)
|
|
acceptRegion();
|
|
else if (event->key() == Qt::Key_Space) {
|
|
mKeysBlocked = true;
|
|
|
|
if (mQToxVisible)
|
|
hideVisibleWindows();
|
|
else
|
|
restoreHiddenWindows();
|
|
|
|
window->hide();
|
|
QTimer::singleShot(350, this, SLOT(reInit()));
|
|
} else
|
|
return false;
|
|
|
|
return true;
|
|
}
|
|
|
|
void ScreenshotGrabber::acceptRegion()
|
|
{
|
|
QRect rect = this->chooserRect->chosenRect();
|
|
if (rect.width() < 1 || rect.height() < 1)
|
|
return;
|
|
|
|
// Scale the accepted region from DIPs to actual pixels
|
|
rect.setRect(rect.x() * pixRatio, rect.y() * pixRatio, rect.width() * pixRatio,
|
|
rect.height() * pixRatio);
|
|
|
|
emit regionChosen(rect);
|
|
qDebug() << "Screenshot accepted, chosen region" << rect;
|
|
QPixmap pixmap = this->screenGrab.copy(rect);
|
|
restoreHiddenWindows();
|
|
emit screenshotTaken(pixmap);
|
|
|
|
deleteLater();
|
|
}
|
|
|
|
void ScreenshotGrabber::setupScene()
|
|
{
|
|
delete scene;
|
|
scene = new QGraphicsScene;
|
|
window->setScene(scene);
|
|
|
|
this->overlay = new ScreenGrabberOverlayItem(this);
|
|
this->helperToolbox = new ToolBoxGraphicsItem;
|
|
|
|
this->screenGrabDisplay = scene->addPixmap(this->screenGrab);
|
|
this->helperTooltip = scene->addText(QString());
|
|
|
|
scene->addItem(this->overlay);
|
|
this->chooserRect = new ScreenGrabberChooserRectItem(scene);
|
|
scene->addItem(this->helperToolbox);
|
|
|
|
this->helperToolbox->addToGroup(this->helperTooltip);
|
|
this->helperTooltip->setDefaultTextColor(Qt::black);
|
|
useNothingSelectedTooltip();
|
|
|
|
connect(this->chooserRect, &ScreenGrabberChooserRectItem::doubleClicked, this,
|
|
&ScreenshotGrabber::acceptRegion);
|
|
connect(this->chooserRect, &ScreenGrabberChooserRectItem::regionChosen, this,
|
|
&ScreenshotGrabber::chooseHelperTooltipText);
|
|
connect(this->chooserRect, &ScreenGrabberChooserRectItem::regionChosen, this->overlay,
|
|
&ScreenGrabberOverlayItem::setChosenRect);
|
|
}
|
|
|
|
void ScreenshotGrabber::useNothingSelectedTooltip()
|
|
{
|
|
helperTooltip->setHtml(
|
|
tr("Click and drag to select a region. Press %1 to "
|
|
"hide/show qTox window, or %2 to cancel.",
|
|
"Help text shown when no region has been selected yet")
|
|
.arg(QString("<b>%1</b>").arg(tr("Space", "[Space] key on the keyboard")),
|
|
QString("<b>%1</b>").arg(tr("Escape", "[Escape] key on the keyboard"))));
|
|
adjustTooltipPosition();
|
|
}
|
|
|
|
void ScreenshotGrabber::useRegionSelectedTooltip()
|
|
{
|
|
helperTooltip->setHtml(
|
|
tr("Press %1 to send a screenshot of the selection, "
|
|
"%2 to hide/show qTox window, or %3 to cancel.",
|
|
"Help text shown when a region has been selected")
|
|
.arg(QString("<b>%1</b>").arg(tr("Enter", "[Enter] key on the keyboard")),
|
|
QString("<b>%1</b>").arg(tr("Space", "[Space] key on the keyboard")),
|
|
QString("<b>%1</b>").arg(tr("Escape", "[Escape] key on the keyboard"))));
|
|
adjustTooltipPosition();
|
|
}
|
|
|
|
void ScreenshotGrabber::chooseHelperTooltipText(QRect rect)
|
|
{
|
|
if (rect.size().isNull())
|
|
useNothingSelectedTooltip();
|
|
else
|
|
useRegionSelectedTooltip();
|
|
}
|
|
|
|
/**
|
|
* @internal
|
|
* @brief Align the tooltip centered at top of screen with the mouse cursor.
|
|
*/
|
|
void ScreenshotGrabber::adjustTooltipPosition()
|
|
{
|
|
QRect recGL = QGuiApplication::primaryScreen()->virtualGeometry();
|
|
QRect rec = qApp->desktop()->screenGeometry(QCursor::pos());
|
|
const QRectF ttRect = this->helperToolbox->childrenBoundingRect();
|
|
int x = qAbs(recGL.x()) + rec.x() + ((rec.width() - ttRect.width()) / 2);
|
|
int y = qAbs(recGL.y()) + rec.y();
|
|
|
|
helperToolbox->setX(x);
|
|
helperToolbox->setY(y);
|
|
}
|
|
|
|
void ScreenshotGrabber::reject()
|
|
{
|
|
restoreHiddenWindows();
|
|
deleteLater();
|
|
}
|
|
|
|
QPixmap ScreenshotGrabber::grabScreen()
|
|
{
|
|
QScreen* screen = QGuiApplication::primaryScreen();
|
|
QRect rec = screen->virtualGeometry();
|
|
|
|
// Multiply by devicePixelRatio to get actual desktop size
|
|
return screen->grabWindow(QApplication::desktop()->winId(), rec.x() * pixRatio,
|
|
rec.y() * pixRatio, rec.width() * pixRatio, rec.height() * pixRatio);
|
|
}
|
|
|
|
void ScreenshotGrabber::hideVisibleWindows()
|
|
{
|
|
foreach (QWidget* w, qApp->topLevelWidgets()) {
|
|
if (w != window && w->isVisible()) {
|
|
mHiddenWindows << w;
|
|
w->setVisible(false);
|
|
}
|
|
}
|
|
|
|
mQToxVisible = false;
|
|
}
|
|
|
|
void ScreenshotGrabber::restoreHiddenWindows()
|
|
{
|
|
foreach (QWidget* w, mHiddenWindows) {
|
|
if (w)
|
|
w->setVisible(true);
|
|
}
|
|
|
|
mHiddenWindows.clear();
|
|
mQToxVisible = true;
|
|
}
|
|
|
|
void ScreenshotGrabber::beginRectChooser(QGraphicsSceneMouseEvent* event)
|
|
{
|
|
QPointF pos = event->scenePos();
|
|
this->chooserRect->setX(pos.x());
|
|
this->chooserRect->setY(pos.y());
|
|
this->chooserRect->beginResize(event->scenePos());
|
|
}
|