Page MenuHomePhabricator (Chris)

No OneTemporary

Size
111 KB
Referenced Files
None
Subscribers
None
diff --git a/dialogs/areadialog.cpp b/dialogs/areadialog.cpp
index 641b1b4..482836b 100644
--- a/dialogs/areadialog.cpp
+++ b/dialogs/areadialog.cpp
@@ -1,608 +1,736 @@
/*
* Copyright (C) 2017 Christian Kaiser
*
* This program is free 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 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 General Public License
* along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
******
*
* Based on KDE's KSnapshot regiongrabber.cpp, revision 796531, Copyright 2007 Luca Gugelmann <lucag@student.ethz.ch>
* released under the GNU LGPL <http://www.gnu.org/licenses/old-licenses/library.txt>
*
*/
#include "areadialog.h"
#include "../tools/os.h"
#include "../tools/screenshot.h"
#include "../tools/screenshotmanager.h"
#include <QApplication>
#include <QDesktopWidget>
#include <QHBoxLayout>
#include <QMouseEvent>
#include <QPainter>
#include <QPushButton>
#include <QSettings>
#include <QTimer>
#include <QToolTip>
+#include <QThread>
AreaDialog::AreaDialog(Screenshot *screenshot) :
QDialog(0), mScreenshot(screenshot), mMouseDown(false), mMouseMagnifier(false),
mNewSelection(false), mHandleSize(10), mMouseOverHandle(0),
mShowHelp(true), mGrabbing(false), mOverlayAlpha(1), mAutoclose(false),
mTLHandle(0, 0, mHandleSize, mHandleSize), mTRHandle(0, 0, mHandleSize, mHandleSize),
mBLHandle(0, 0, mHandleSize, mHandleSize), mBRHandle(0, 0, mHandleSize, mHandleSize),
mLHandle(0, 0, mHandleSize, mHandleSize), mTHandle(0, 0, mHandleSize, mHandleSize),
mRHandle(0, 0, mHandleSize, mHandleSize), mBHandle(0, 0, mHandleSize, mHandleSize)
{
mHandles << &mTLHandle << &mTRHandle << &mBLHandle << &mBRHandle
<< &mLHandle << &mTHandle << &mRHandle << &mBHandle;
mMouseOverHandle = 0;
setMouseTracking(true);
setWindowTitle(tr("Lightscreen Area Mode"));
setWindowFlags(Qt::WindowStaysOnTopHint | Qt::FramelessWindowHint | Qt::X11BypassWindowManagerHint);
setCursor(Qt::CrossCursor);
connect(&mIdleTimer, &QTimer::timeout, this, &AreaDialog::displayHelp);
mIdleTimer.start(2000);
mAutoclose = ScreenshotManager::instance()->settings()->value("options/areaAutoclose").toBool();
if (mAutoclose) {
return; // Avoid creating the accept widget if it's not going to get used.
}
// Creating accept widget:
mAcceptWidget = new QWidget(this);
mAcceptWidget->resize(140, 70);
mAcceptWidget->setWindowOpacity(0.4);
mAcceptWidget->setStyleSheet("QWidget { background: rgba(255, 255, 255, 200); border: 4px solid #232323; padding: 0; } QPushButton { background: transparent; border: none; height: 50px; padding: 5px; } QPushButton:hover { cursor: hand; }");
auto awAcceptButton = new QPushButton(QIcon(":/icons/yes.big"), "", this);
connect(awAcceptButton, &QPushButton::clicked, this, &AreaDialog::grabRect);
awAcceptButton->setCursor(Qt::PointingHandCursor);
awAcceptButton->setIconSize(QSize(48, 48));
auto awRejectButton = new QPushButton(QIcon(":/icons/no.big"), "", this);
connect(awRejectButton, &QPushButton::clicked, this, &AreaDialog::cancel);
awRejectButton->setCursor(Qt::PointingHandCursor);
awRejectButton->setIconSize(QSize(48, 48));
auto awLayout = new QHBoxLayout(this);
awLayout->addWidget(awAcceptButton);
awLayout->addWidget(awRejectButton);
awLayout->setMargin(0);
awLayout->setSpacing(0);
mAcceptWidget->setLayout(awLayout);
mAcceptWidget->setVisible(false);
}
QRect AreaDialog::resultRect() const
{
auto devicePixelRatio = mScreenshot->pixmap().devicePixelRatio();
return QRect(mSelection.left() * devicePixelRatio,
mSelection.top() * devicePixelRatio,
mSelection.width() * devicePixelRatio,
mSelection.height() * devicePixelRatio);
}
void AreaDialog::animationTick(int frame)
{
mOverlayAlpha = frame;
update();
}
void AreaDialog::cancel()
{
reject();
}
void AreaDialog::displayHelp()
{
mShowHelp = true;
update();
}
void AreaDialog::grabRect()
{
QRect r = mSelection.normalized();
if (!r.isNull() && r.isValid()) {
mGrabbing = true;
accept();
}
}
+void AreaDialog::keyboardResize()
+{
+ if (mKeyboardSize.contains("x")) {
+ auto sizeList = mKeyboardSize.split("x");
+
+ if (sizeList.count() == 2) {
+ bool okw = false, okh = false;
+
+ QSize size(sizeList.at(0).toInt(&okw), sizeList.at(1).toInt(&okh));
+
+ if (okw && okh && size.width() > 0 && size.height() > 0) {
+ auto oldSize = mSelection.size();
+
+ mSelection.setSize(size);
+
+ if (rect().contains(mSelection)) {
+ updateHandles();
+ } else {
+ mSelection.setSize(oldSize); // Reverting size
+ }
+ }
+ }
+ }
+
+ mKeyboardSize.clear();
+ update();
+}
+
void AreaDialog::keyPressEvent(QKeyEvent *e)
{
if (e->key() == Qt::Key_Escape) {
- cancel();
+ if (mKeyboardSize.isEmpty()) {
+ cancel();
+ } else {
+ mKeyboardSize.clear();
+ update();
+ }
} else if (e->key() == Qt::Key_Enter || e->key() == Qt::Key_Return) {
- grabRect();
+ if (mKeyboardSize.isEmpty()) {
+ grabRect();
+ } else {
+ keyboardResize();
+ }
+ } else if (e->key() == Qt::Key_Up || e->key() == Qt::Key_Down || e->key() == Qt::Key_Left || e->key() == Qt::Key_Right) {
+ // Keyboard movement
+ int adjustMagnitude = 1;
+
+ if (e->modifiers() & Qt::ShiftModifier)
+ adjustMagnitude += 4;
+
+ if (e->modifiers() & Qt::ControlModifier)
+ adjustMagnitude += 4;
+
+ if (e->modifiers() & Qt::AltModifier)
+ adjustMagnitude += 4;
+
+ int xAdjust = 0;
+ int yAdjust = 0;
+
+ if (e->key() == Qt::Key_Left)
+ xAdjust = -(adjustMagnitude);
+
+ if (e->key() == Qt::Key_Right)
+ xAdjust = adjustMagnitude;
+
+ if (e->key() == Qt::Key_Up)
+ yAdjust = -(adjustMagnitude);
+
+ if (e->key() == Qt::Key_Down)
+ yAdjust = adjustMagnitude;
+
+ auto adjusted = mSelection.adjusted(xAdjust, yAdjust, xAdjust, yAdjust);
+
+ if (rect().contains(adjusted)) {
+ mSelection = adjusted;
+ updateHandles();
+ update();
+ }
+ } else if (e->key() == Qt::Key_F5) {
+ setWindowOpacity(0);
+ QThread::msleep(200); // Give the window system time to catch up
+ mScreenshot->refresh();
+ setWindowOpacity(1);
} else {
- e->ignore();
+ if (e->key() == Qt::Key_Backspace && !mKeyboardSize.isEmpty()) {
+ mKeyboardSize.remove(mKeyboardSize.size()-1, 1);
+ update();
+ return;
+ }
+
+ if (e->key() != Qt::Key_X) {
+ bool ok = false;
+ int number = e->text().toInt(&ok);
+
+ if (!ok || number < 0 || number > qMax<int>(width(), height())) {
+ e->ignore();
+ return;
+ }
+ } else {
+ if (mKeyboardSize.contains("x"))
+ return;
+ }
+
+ mKeyboardSize += e->text();
+ update();
}
}
void AreaDialog::mouseDoubleClickEvent(QMouseEvent *)
{
grabRect();
}
void AreaDialog::mouseMoveEvent(QMouseEvent *e)
{
mMouseMagnifier = false;
if (mMouseDown) {
mMousePos = e->pos();
if (mNewSelection) {
mSelection = QRect(mDragStartPoint, limitPointToRect(mMousePos, rect())).normalized();
} else if (mMouseOverHandle == 0) {
// Moving the whole selection
QRect r = rect().normalized(), s = mSelectionBeforeDrag.normalized();
QPoint p = s.topLeft() + e->pos() - mDragStartPoint;
r.setBottomRight(r.bottomRight() - QPoint(s.width(), s.height()));
if (!r.isNull() && r.isValid()) {
mSelection.moveTo(limitPointToRect(p, r));
}
} else {
// Dragging a handle
QRect r = mSelectionBeforeDrag;
QPoint offset = e->pos() - mDragStartPoint;
bool symmetryMod = qApp->keyboardModifiers() & Qt::ShiftModifier;
bool aspectRatioMod = qApp->keyboardModifiers() & Qt::ControlModifier;
if (mMouseOverHandle == &mTLHandle || mMouseOverHandle == &mTHandle
|| mMouseOverHandle == &mTRHandle) { // dragging one of the top handles
r.setTop(r.top() + offset.y());
if (symmetryMod) {
r.setBottom(r.bottom() - offset.y());
}
}
if (mMouseOverHandle == &mTLHandle || mMouseOverHandle == &mLHandle
|| mMouseOverHandle == &mBLHandle) { // dragging one of the left handles
r.setLeft(r.left() + offset.x());
if (symmetryMod) {
r.setRight(r.right() - offset.x());
}
}
if (mMouseOverHandle == &mBLHandle || mMouseOverHandle == &mBHandle
|| mMouseOverHandle == &mBRHandle) { // dragging one of the bottom handles
r.setBottom(r.bottom() + offset.y());
if (symmetryMod) {
r.setTop(r.top() - offset.y());
}
}
if (mMouseOverHandle == &mTRHandle || mMouseOverHandle == &mRHandle
|| mMouseOverHandle == &mBRHandle) { // dragging one of the right handles
r.setRight(r.right() + offset.x());
if (symmetryMod) {
r.setLeft(r.left() - offset.x());
}
}
r = r.normalized();
r.setTopLeft(limitPointToRect(r.topLeft(), rect()));
r.setBottomRight(limitPointToRect(r.bottomRight(), rect()));
if (aspectRatioMod) {
if (mMouseOverHandle == &mBLHandle || mMouseOverHandle == &mBRHandle || mMouseOverHandle == &mLHandle || mMouseOverHandle == &mRHandle) {
r.setHeight(r.width());
} else {
r.setWidth(r.height());
}
}
mSelection = r;
}
if (mAcceptWidget) {
QPoint acceptPos = e->pos();
QRect acceptRect = QRect(acceptPos, QSize(120, 70));
// Prevent the widget from overlapping the handles
if (acceptRect.intersects(mTLHandle)) {
acceptPos = mTLHandle.bottomRight() + QPoint(2, 2); // Corner case
}
if (acceptRect.intersects(mBRHandle)) {
acceptPos = mBRHandle.bottomRight();
}
if (acceptRect.intersects(mBHandle)) {
acceptPos = mBHandle.bottomRight();
}
if (acceptRect.intersects(mRHandle)) {
acceptPos = mRHandle.topRight();
}
if (acceptRect.intersects(mTHandle)) {
acceptPos = mTHandle.bottomRight();
}
if ((acceptPos.x() + 120) > mScreenshot->pixmap().rect().width()) {
acceptPos.setX(acceptPos.x() - 120);
}
if ((acceptPos.y() + 70) > mScreenshot->pixmap().rect().height()) {
acceptPos.setY(acceptPos.y() - 70);
}
mAcceptWidget->move(acceptPos);
}
update();
} else {
if (mSelection.isNull()) {
mMouseMagnifier = true;
update();
return;
}
bool found = false;
foreach (QRect *r, mHandles) {
if (r->contains(e->pos())) {
mMouseOverHandle = r;
found = true;
break;
}
}
if (!found) {
mMouseOverHandle = 0;
if (mSelection.contains(e->pos())) {
setCursor(Qt::OpenHandCursor);
} else if (mAcceptWidget && QRect(mAcceptWidget->mapToParent(mAcceptWidget->pos()), QSize(100, 60)).contains(e->pos())) {
setCursor(Qt::PointingHandCursor);
} else {
setCursor(Qt::CrossCursor);
}
} else {
if (mMouseOverHandle == &mTLHandle || mMouseOverHandle == &mBRHandle) {
setCursor(Qt::SizeFDiagCursor);
}
if (mMouseOverHandle == &mTRHandle || mMouseOverHandle == &mBLHandle) {
setCursor(Qt::SizeBDiagCursor);
}
if (mMouseOverHandle == &mLHandle || mMouseOverHandle == &mRHandle) {
setCursor(Qt::SizeHorCursor);
}
if (mMouseOverHandle == &mTHandle || mMouseOverHandle == &mBHandle) {
setCursor(Qt::SizeVerCursor);
}
}
}
}
void AreaDialog::mousePressEvent(QMouseEvent *e)
{
mShowHelp = false;
mIdleTimer.stop();
if (mAcceptWidget) {
mAcceptWidget->hide();
}
if (e->button() == Qt::LeftButton) {
mMouseDown = true;
mDragStartPoint = e->pos();
mSelectionBeforeDrag = mSelection;
if (!mSelection.contains(e->pos())) {
mNewSelection = true;
mSelection = QRect();
mShowHelp = true;
setCursor(Qt::CrossCursor);
} else {
setCursor(Qt::ClosedHandCursor);
}
} else if (e->button() == Qt::RightButton
|| e->button() == Qt::MidButton) {
cancel();
}
update();
}
void AreaDialog::mouseReleaseEvent(QMouseEvent *e)
{
if (mAutoclose) {
grabRect();
}
if (!mSelection.isNull() && mAcceptWidget) {
mAcceptWidget->show();
}
mMouseDown = false;
mNewSelection = false;
mIdleTimer.start();
if (mMouseOverHandle == 0 && mSelection.contains(e->pos())) {
setCursor(Qt::OpenHandCursor);
}
update();
}
void AreaDialog::paintEvent(QPaintEvent *e)
{
Q_UNUSED(e);
if (mGrabbing) { // grabWindow() should just get the background
return;
}
QPainter painter(this);
QPalette pal = palette();
QFont font = QToolTip::font();
QColor handleColor(85, 160, 188, 220);
QColor overlayColor(0, 0, 0, mOverlayAlpha);
QColor textColor = pal.color(QPalette::Active, QPalette::Text);
QColor textBackgroundColor = pal.color(QPalette::Active, QPalette::Base);
painter.drawPixmap(0, 0, mScreenshot->pixmap());
painter.setFont(font);
QRect r = mSelection.normalized().adjusted(0, 0, -1, -1);
QRegion grey(rect());
grey = grey.subtracted(r);
painter.setPen(handleColor);
painter.setBrush(overlayColor);
painter.setClipRegion(grey);
painter.drawRect(-1, -1, rect().width() + 1, rect().height() + 1);
painter.setClipRect(rect());
painter.setBrush(Qt::NoBrush);
painter.drawRect(r);
if (mShowHelp) {
//Drawing the explanatory text.
QRect helpRect = qApp->desktop()->screenGeometry(qApp->desktop()->primaryScreen());
QString helpTxt = tr("Lightscreen area mode:\nUse your mouse to draw a rectangle to capture.\nPress any key or right click to exit.");
helpRect.setHeight(qRound((float)(helpRect.height() / 10))); // We get a decently sized rect where the text should be drawn (centered)
// We draw the white contrasting background for the text, using the same text and options to get the boundingRect that the text will have.
painter.setPen(QPen(Qt::white));
painter.setBrush(QBrush(QColor(255, 255, 255, 180), Qt::SolidPattern));
QRectF bRect = painter.boundingRect(helpRect, Qt::AlignCenter, helpTxt);
// These four calls provide padding for the rect
bRect.setWidth(bRect.width() + 12);
bRect.setHeight(bRect.height() + 10);
bRect.setX(bRect.x() - 12);
bRect.setY(bRect.y() - 10);
painter.drawRoundedRect(bRect, 8, 8);
// Draw the text:
painter.setPen(QPen(Qt::black));
painter.drawText(helpRect, Qt::AlignCenter, helpTxt);
}
+ if (!mKeyboardSize.isEmpty()) {
+ QRect keyboardSizeRect = qApp->desktop()->screenGeometry(qApp->desktop()->primaryScreen());
+
+ QFont originalFont = painter.font();
+ QFont font = originalFont;
+ font.setPixelSize(16);
+ font.setBold(true);
+ painter.setFont(font);
+
+ painter.setPen(QPen(Qt::white));
+ painter.setBrush(QBrush(QColor(255, 255, 255, 180), Qt::SolidPattern));
+ QRectF textRect = painter.boundingRect(keyboardSizeRect, Qt::AlignLeft, mKeyboardSize);
+
+ textRect.setX(textRect.x() + 9);
+ textRect.setY(textRect.y() + 10);
+ textRect.setWidth(textRect.width() + 14);
+ textRect.setHeight(textRect.height() + 12);
+
+ painter.drawRect(textRect);
+
+ // Left-Right padding
+ textRect.setX(textRect.x() + 3);
+ textRect.setWidth(textRect.width() - 2);
+
+ painter.setPen(QPen(Qt::black));
+ painter.drawText(textRect, Qt::AlignCenter, mKeyboardSize, &textRect);
+
+ painter.setFont(originalFont); // Reset the font
+ }
+
if (!mSelection.isNull()) {
// The grabbed region is everything which is covered by the drawn
// rectangles (border included). This means that there is no 0px
// selection, since a 0px wide rectangle will always be drawn as a line.
QString txt = QString("%1x%2").arg(mSelection.width() == 0 ? 2 : mSelection.width())
.arg(mSelection.height() == 0 ? 2 : mSelection.height());
QRect textRect = painter.boundingRect(rect(), Qt::AlignLeft, txt);
QRect boundingRect = textRect.adjusted(-4, 0, 0, 0);
if (textRect.width() < r.width() - 2 * mHandleSize &&
textRect.height() < r.height() - 2 * mHandleSize &&
(r.width() > 100 && r.height() > 100)) { // center, unsuitable for small selections
boundingRect.moveCenter(r.center());
textRect.moveCenter(r.center());
} else if (r.y() - 3 > textRect.height() &&
r.x() + textRect.width() < rect().right()) { // on top, left aligned
boundingRect.moveBottomLeft(QPoint(r.x(), r.y() - 3));
textRect.moveBottomLeft(QPoint(r.x() + 2, r.y() - 3));
} else if (r.x() - 3 > textRect.width()) { // left, top aligned
boundingRect.moveTopRight(QPoint(r.x() - 3, r.y()));
textRect.moveTopRight(QPoint(r.x() - 5, r.y()));
} else if (r.bottom() + 3 + textRect.height() < rect().bottom() &&
r.right() > textRect.width()) { // at bottom, right aligned
boundingRect.moveTopRight(QPoint(r.right(), r.bottom() + 3));
textRect.moveTopRight(QPoint(r.right() - 2, r.bottom() + 3));
} else if (r.right() + textRect.width() + 3 < rect().width()) { // right, bottom aligned
boundingRect.moveBottomLeft(QPoint(r.right() + 3, r.bottom()));
textRect.moveBottomLeft(QPoint(r.right() + 5, r.bottom()));
}
// if the above didn't catch it, you are running on a very tiny screen...
painter.setPen(textColor);
painter.setBrush(textBackgroundColor);
painter.drawRect(boundingRect);
painter.drawText(textRect, txt);
if ((r.height() > mHandleSize * 2 && r.width() > mHandleSize * 2)
|| !mMouseDown) {
updateHandles();
painter.setPen(handleColor);
handleColor.setAlpha(80);
painter.setBrush(handleColor);
painter.drawRects(handleMask().rects());
}
}
if (!mScreenshot->options().magnify) {
return;
}
// Drawing the magnified version
QPoint magStart, magEnd, drawPosition;
QRect newRect;
QRect pixmapRect = mScreenshot->pixmap().rect();
if (mMouseMagnifier) {
drawPosition = mMousePos - QPoint(100, 100);
magStart = mMousePos - QPoint(50, 50);
magEnd = mMousePos + QPoint(50, 50);
newRect = QRect(magStart, magEnd);
} else {
// So pretty.. oh so pretty.
if (mMouseOverHandle == &mTLHandle) {
magStart = mSelection.topLeft();
} else if (mMouseOverHandle == &mTRHandle) {
magStart = mSelection.topRight();
} else if (mMouseOverHandle == &mBLHandle) {
magStart = mSelection.bottomLeft();
} else if (mMouseOverHandle == &mBRHandle) {
magStart = mSelection.bottomRight();
} else if (mMouseOverHandle == &mLHandle) {
magStart = QPoint(mSelection.left(), mSelection.center().y());
} else if (mMouseOverHandle == &mTHandle) {
magStart = QPoint(mSelection.center().x(), mSelection.top());
} else if (mMouseOverHandle == &mRHandle) {
magStart = QPoint(mSelection.right(), mSelection.center().y());
} else if (mMouseOverHandle == &mBHandle) {
magStart = QPoint(mSelection.center().x(), mSelection.bottom());
} else if (mMouseOverHandle == 0) {
magStart = mMousePos;
}
magEnd = magStart;
drawPosition = mSelection.bottomRight();
magStart -= QPoint(48, 48);
magEnd += QPoint(48, 48);
newRect = QRect(magStart, magEnd);
if ((drawPosition.x() + newRect.width() * 2) > pixmapRect.width()) {
drawPosition.setX(drawPosition.x() - newRect.width() * 2);
}
if ((drawPosition.y() + newRect.height() * 2) > pixmapRect.height()) {
drawPosition.setY(drawPosition.y() - newRect.height() * 2);
}
if (drawPosition.y() == mSelection.bottomRight().y() - newRect.height() * 2
&& drawPosition.x() == mSelection.bottomRight().x() - newRect.width() * 2) {
painter.setOpacity(0.7);
}
}
if (!pixmapRect.contains(newRect, true) || drawPosition.x() <= 0 || drawPosition.y() <= 0) {
return;
}
QPixmap magnified = mScreenshot->pixmap().copy(newRect).scaled(QSize(newRect.width() * 2, newRect.height() * 2));
QPainter magPainter(&magnified);
magPainter.setPen(QPen(QBrush(QColor(35, 35, 35)), 2)); // Same border pen
magPainter.drawRect(magnified.rect());
if (!mMouseMagnifier) {
magPainter.setCompositionMode(QPainter::CompositionMode_Exclusion);
magPainter.setPen(QPen(QBrush(QColor(255, 255, 255, 180)), 1));
QRect magRect = magnified.rect();
magPainter.drawLine(QLine(magRect.left(), magRect.width()/2, magRect.right(), magRect.width()/2));
magPainter.drawLine(QLine(magRect.width()/2, 0, magRect.height()/2, magnified.height()));
}
painter.drawPixmap(drawPosition, magnified);
}
void AreaDialog::resizeEvent(QResizeEvent *e)
{
Q_UNUSED(e);
if (mSelection.isNull()) {
return;
}
QRect r = mSelection;
r.setTopLeft(limitPointToRect(r.topLeft(), rect()));
r.setBottomRight(limitPointToRect(r.bottomRight(), rect()));
if (r.width() <= 1 || r.height() <= 1) { //this just results in ugly drawing...
r = QRect();
}
mSelection = r;
}
void AreaDialog::showEvent(QShowEvent *e)
{
Q_UNUSED(e)
QRect geometry = qApp->desktop()->geometry();
if (mScreenshot->options().currentMonitor) {
geometry = qApp->desktop()->screenGeometry(qApp->desktop()->screenNumber(QCursor::pos()));
}
resize(geometry.size());
move(geometry.topLeft());
if (mScreenshot->options().animations) {
os::effect(this, SLOT(animationTick(int)), 85, 300);
} else {
animationTick(85);
}
setMouseTracking(true);
}
void AreaDialog::updateHandles()
{
QRect r = mSelection.normalized().adjusted(0, 0, -1, -1);
int s2 = mHandleSize / 2;
mTLHandle.moveTopLeft(r.topLeft());
mTRHandle.moveTopRight(r.topRight());
mBLHandle.moveBottomLeft(r.bottomLeft());
mBRHandle.moveBottomRight(r.bottomRight());
mLHandle.moveTopLeft(QPoint(r.x(), r.y() + r.height() / 2 - s2));
mTHandle.moveTopLeft(QPoint(r.x() + r.width() / 2 - s2, r.y()));
mRHandle.moveTopRight(QPoint(r.right(), r.y() + r.height() / 2 - s2));
mBHandle.moveBottomLeft(QPoint(r.x() + r.width() / 2 - s2, r.bottom()));
}
QRegion AreaDialog::handleMask() const
{
// note: not normalized QRects are bad here, since they will not be drawn
QRegion mask;
foreach(QRect * rect, mHandles) mask += QRegion(*rect);
return mask;
}
QPoint AreaDialog::limitPointToRect(const QPoint &p, const QRect &r) const
{
QPoint q;
q.setX(p.x() < r.x() ? r.x() : p.x() < r.right() ? p.x() : r.right());
q.setY(p.y() < r.y() ? r.y() : p.y() < r.bottom() ? p.y() : r.bottom());
return q;
}
diff --git a/dialogs/areadialog.h b/dialogs/areadialog.h
index 8262259..a7d93fb 100644
--- a/dialogs/areadialog.h
+++ b/dialogs/areadialog.h
@@ -1,99 +1,102 @@
/*
* Copyright (C) 2017 Christian Kaiser
*
* This program is free 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 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 General Public License
* along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
******
*
* Based on KDE's KSnapshot regiongrabber.cpp, revision 796531, Copyright 2007 Luca Gugelmann <lucag@student.ethz.ch>
* released under the GNU LGPL <http://www.gnu.org/licenses/old-licenses/library.txt>
*
*/
#ifndef AREADIALOG_H
#define AREADIALOG_H
#include <QDialog>
#include <QVector>
#include <QPointer>
#include <QTimer>
#include <QRegion>
#include <QRect>
#include <QPoint>
class QPaintEvent;
class QResizeEvent;
class QMouseEvent;
class Screenshot;
class AreaDialog : public QDialog
{
Q_OBJECT
public:
AreaDialog(Screenshot *screenshot);
QRect resultRect() const;
protected slots:
void animationTick(int frame);
void cancel();
void displayHelp();
void grabRect();
+ void keyboardResize();
signals:
void regionGrabbed(const QPixmap &);
protected:
void keyPressEvent(QKeyEvent *e);
void mouseDoubleClickEvent(QMouseEvent *);
void mouseMoveEvent(QMouseEvent *e);
void mousePressEvent(QMouseEvent *e);
void mouseReleaseEvent(QMouseEvent *e);
void paintEvent(QPaintEvent *e);
void resizeEvent(QResizeEvent *e);
void showEvent(QShowEvent *e);
void updateHandles();
QRegion handleMask() const;
QPoint limitPointToRect(const QPoint &p, const QRect &r) const;
Screenshot *mScreenshot;
QPoint mDragStartPoint;
bool mMouseDown;
bool mMouseMagnifier;
bool mNewSelection;
const int mHandleSize;
QRect *mMouseOverHandle;
QPoint mMousePos;
QTimer mIdleTimer;
QRect mSelection;
QRect mSelectionBeforeDrag;
bool mShowHelp;
bool mGrabbing;
int mOverlayAlpha;
bool mAutoclose;
// naming convention for handles
// T top, B bottom, R Right, L left
// 2 letters: a corner
// 1 letter: the handle on the middle of the corresponding side
QRect mTLHandle, mTRHandle, mBLHandle, mBRHandle;
QRect mLHandle, mTHandle, mRHandle, mBHandle;
QVector<QRect *> mHandles;
QPointer<QWidget> mAcceptWidget;
+
+ QString mKeyboardSize;
};
#endif
diff --git a/dialogs/optionsdialog.ui b/dialogs/optionsdialog.ui
index 8648b68..3c8586b 100644
--- a/dialogs/optionsdialog.ui
+++ b/dialogs/optionsdialog.ui
@@ -1,1566 +1,1585 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>OptionsDialog</class>
<widget class="QDialog" name="OptionsDialog">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>401</width>
<height>318</height>
</rect>
</property>
<property name="windowTitle">
<string>Options - Lightscreen</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout_4">
<item>
<widget class="QTabWidget" name="tabWidget">
<property name="currentIndex">
<number>0</number>
</property>
<widget class="QWidget" name="generalTab">
<attribute name="title">
<string>General</string>
</attribute>
<layout class="QVBoxLayout" name="verticalLayout">
<property name="bottomMargin">
<number>6</number>
</property>
<item>
<widget class="QGroupBox" name="fileGroupBox">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="title">
<string>File</string>
</property>
<property name="flat">
<bool>true</bool>
</property>
<property name="checkable">
<bool>true</bool>
</property>
<layout class="QGridLayout" name="fileGroupBoxLayout">
<property name="leftMargin">
<number>6</number>
</property>
<property name="topMargin">
<number>6</number>
</property>
<property name="rightMargin">
<number>6</number>
</property>
<property name="bottomMargin">
<number>6</number>
</property>
<property name="verticalSpacing">
<number>4</number>
</property>
<item row="0" column="0">
<widget class="QLabel" name="directoryLabel">
<property name="text">
<string>&amp;Directory:</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
<property name="buddy">
<cstring>targetLineEdit</cstring>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QLineEdit" name="targetLineEdit">
<property name="styleSheet">
<string notr="true"/>
</property>
</widget>
</item>
<item row="0" column="2">
<widget class="QPushButton" name="browsePushButton">
<property name="maximumSize">
<size>
<width>60</width>
<height>16777215</height>
</size>
</property>
<property name="text">
<string/>
</property>
<property name="autoDefault">
<bool>false</bool>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="filenameLabel">
<property name="toolTip">
<string>The prefix for the screenshot file</string>
</property>
<property name="text">
<string>&amp;Filename:</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
<property name="buddy">
<cstring>prefixLineEdit</cstring>
</property>
</widget>
</item>
<item row="1" column="1">
<layout class="QHBoxLayout" name="filenameLayout">
<property name="spacing">
<number>3</number>
</property>
<item>
<widget class="QLineEdit" name="prefixLineEdit">
<property name="whatsThis">
<string>The prefix will be inserted before the &lt;em&gt;Naming&lt;/em&gt; in the screenshot file and it is usually used to distinguish files. It can be left blank.</string>
</property>
</widget>
</item>
<item>
<widget class="QComboBox" name="namingComboBox">
<property name="whatsThis">
<string>The naming is inserted after the prefix and is what makes each screenshot file unique to avoid overwriting.&lt;br /&gt;
&lt;b&gt;Numeric&lt;/b&gt;: inserts a number in sequence, 1, 2, 3..&lt;br /&gt;
&lt;b&gt;Date&lt;/b&gt;: inserts the current date and time, in the form of dd-MM-yyyy, click the &quot;wrench&quot; button on the right to customize the format.&lt;br /&gt;
&lt;b&gt;Timestamp&lt;/b&gt;: inserts a number, a Unix timestamp, which is the number of seconds passed since 1970-1-1 00:00:00.&lt;br /&gt;
</string>
</property>
<item>
<property name="text">
<string>(number)</string>
</property>
</item>
<item>
<property name="text">
<string>(date)</string>
</property>
</item>
<item>
<property name="text">
<string>(timestamp)</string>
</property>
</item>
<item>
<property name="text">
<string>(none)</string>
</property>
</item>
</widget>
</item>
</layout>
</item>
<item row="1" column="2">
<widget class="QPushButton" name="namingOptionsButton">
<property name="autoDefault">
<bool>false</bool>
</property>
</widget>
</item>
<item row="3" column="0">
<widget class="QLabel" name="formatLabel">
<property name="toolTip">
<string>The file format for the screenshot</string>
</property>
<property name="text">
<string>F&amp;ormat:</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
<property name="buddy">
<cstring>formatComboBox</cstring>
</property>
</widget>
</item>
<item row="3" column="1">
<widget class="QComboBox" name="formatComboBox">
<item>
<property name="text">
<string notr="true">PNG</string>
</property>
</item>
<item>
<property name="text">
<string notr="true">JPG</string>
</property>
</item>
<item>
<property name="text">
<string notr="true">BMP</string>
</property>
</item>
<item>
<property name="text">
<string>WEBP</string>
</property>
</item>
</widget>
</item>
<item row="4" column="0">
<widget class="QLabel" name="qualityLabel">
<property name="text">
<string>&amp;Quality:</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
<property name="buddy">
<cstring>qualitySlider</cstring>
</property>
</widget>
</item>
<item row="4" column="1">
<widget class="QSlider" name="qualitySlider">
<property name="whatsThis">
<string>This slider goes from 0 to 100. 100 being the highest quality and 0 the lowest.&lt;br&gt;
Quality is related to file size and of course to readability and overall quality of the image.</string>
</property>
<property name="maximum">
<number>100</number>
</property>
<property name="pageStep">
<number>5</number>
</property>
<property name="value">
<number>100</number>
</property>
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
</widget>
</item>
<item row="4" column="2">
<layout class="QHBoxLayout" name="qualityLayout">
<property name="spacing">
<number>0</number>
</property>
<property name="sizeConstraint">
<enum>QLayout::SetMinimumSize</enum>
</property>
<item>
<widget class="QLabel" name="qualityValueLabel">
<property name="font">
<font>
<pointsize>8</pointsize>
</font>
</property>
<property name="text">
<string notr="true">100</string>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="qualityPercentLabel">
<property name="font">
<font>
<pointsize>7</pointsize>
</font>
</property>
<property name="text">
<string notr="true">%</string>
</property>
</widget>
</item>
</layout>
</item>
<item row="5" column="0">
<widget class="QLabel" name="previewTextLabel">
<property name="text">
<string>&lt;u&gt;Preview&lt;/u&gt;:</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item row="5" column="1">
<widget class="QLabel" name="previewLabel">
<property name="text">
<string/>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>0</width>
<height>0</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QGroupBox" name="startupGroupBox">
<property name="sizePolicy">
<sizepolicy hsizetype="Minimum" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="title">
<string>System Startup</string>
</property>
<property name="flat">
<bool>true</bool>
</property>
<layout class="QVBoxLayout" name="verticalLayout_3">
<item>
<widget class="QCheckBox" name="startupCheckBox">
<property name="whatsThis">
<string/>
</property>
<property name="text">
<string>&amp;Run Lightscreen at system startup.</string>
</property>
</widget>
</item>
<item>
<layout class="QHBoxLayout" name="startupHideLayout">
<item>
<spacer name="startupHideSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeType">
<enum>QSizePolicy::Fixed</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>13</width>
<height>15</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QCheckBox" name="startupHideCheckBox">
<property name="whatsThis">
<string/>
</property>
<property name="text">
<string>H&amp;ide the main window.</string>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</widget>
</item>
</layout>
</widget>
<widget class="QWidget" name="hotkeyTab">
<attribute name="title">
<string>Hotkeys</string>
</attribute>
<layout class="QVBoxLayout" name="verticalLayout_2">
<item>
<widget class="QGroupBox" name="capturesGroupBox">
<property name="title">
<string>Captures</string>
</property>
<property name="flat">
<bool>true</bool>
</property>
<layout class="QGridLayout" name="gridLayout">
<property name="leftMargin">
<number>6</number>
</property>
<property name="topMargin">
<number>6</number>
</property>
<property name="rightMargin">
<number>6</number>
</property>
<property name="bottomMargin">
<number>6</number>
</property>
<property name="spacing">
<number>4</number>
</property>
<item row="0" column="0">
<widget class="QCheckBox" name="screenCheckBox">
<property name="sizePolicy">
<sizepolicy hsizetype="Maximum" vsizetype="Maximum">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>&amp;Fullscreen</string>
</property>
</widget>
</item>
<item row="0" column="2">
<widget class="HotkeyWidget" name="screenHotkeyWidget">
<property name="sizePolicy">
<sizepolicy hsizetype="Minimum" vsizetype="Maximum">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
</widget>
</item>
<item row="3" column="0">
<widget class="QCheckBox" name="windowPickerCheckBox">
<property name="sizePolicy">
<sizepolicy hsizetype="Maximum" vsizetype="Maximum">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Window &amp;Picker</string>
</property>
</widget>
</item>
<item row="3" column="2">
<widget class="HotkeyWidget" name="windowPickerHotkeyWidget"/>
</item>
<item row="2" column="1">
<spacer name="horizontalSpacer_4">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>0</height>
</size>
</property>
</spacer>
</item>
<item row="2" column="0">
<widget class="QCheckBox" name="windowCheckBox">
<property name="sizePolicy">
<sizepolicy hsizetype="Maximum" vsizetype="Maximum">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Active &amp;Window</string>
</property>
</widget>
</item>
<item row="2" column="2">
<widget class="HotkeyWidget" name="windowHotkeyWidget"/>
</item>
<item row="1" column="0">
<widget class="QCheckBox" name="areaCheckBox">
<property name="sizePolicy">
<sizepolicy hsizetype="Maximum" vsizetype="Maximum">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Screen &amp;Area</string>
</property>
</widget>
</item>
<item row="1" column="2">
<widget class="HotkeyWidget" name="areaHotkeyWidget"/>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QGroupBox" name="controlGroupBox">
<property name="title">
<string>Lightscreen Control</string>
</property>
<property name="flat">
<bool>true</bool>
</property>
<layout class="QGridLayout" name="gridLayout_2">
<property name="leftMargin">
<number>6</number>
</property>
<property name="topMargin">
<number>6</number>
</property>
<property name="rightMargin">
<number>6</number>
</property>
<property name="bottomMargin">
<number>6</number>
</property>
<property name="spacing">
<number>4</number>
</property>
<item row="0" column="0">
<widget class="QCheckBox" name="openCheckBox">
<property name="sizePolicy">
<sizepolicy hsizetype="Maximum" vsizetype="Maximum">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>&amp;Open the program window</string>
</property>
</widget>
</item>
<item row="0" column="2">
<widget class="HotkeyWidget" name="openHotkeyWidget"/>
</item>
<item row="1" column="0">
<widget class="QCheckBox" name="directoryCheckBox">
<property name="sizePolicy">
<sizepolicy hsizetype="Maximum" vsizetype="Maximum">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Open the &amp;directory</string>
</property>
</widget>
</item>
<item row="1" column="2">
<widget class="HotkeyWidget" name="directoryHotkeyWidget"/>
</item>
<item row="0" column="1">
<spacer name="horizontalSpacer_2">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>0</height>
</size>
</property>
</spacer>
</item>
</layout>
</widget>
</item>
</layout>
</widget>
<widget class="QWidget" name="uploadTab">
<attribute name="title">
<string>Upload</string>
</attribute>
<layout class="QVBoxLayout" name="verticalLayout_12">
<item>
<widget class="QLabel" name="uploadSslWarningLabel">
<property name="font">
<font>
<weight>75</weight>
<bold>true</bold>
</font>
</property>
<property name="styleSheet">
<string notr="true">QLabel { padding: 4px; border: 1px solid red; background-color: rgba(248, 182, 182, 60); }</string>
</property>
<property name="text">
<string>WARNING: You have no SSL support, &lt;a href=&quot;http://lightscreen.com.ar/help#SSL&quot;&gt;click here&lt;/a&gt; to learn more.</string>
</property>
</widget>
</item>
<item>
<widget class="QCheckBox" name="uploadCheckBox">
<property name="text">
<string>Upload all my screenshots automatically.</string>
</property>
</widget>
</item>
<item>
<widget class="QCheckBox" name="urlClipboardCheckBox">
+ <property name="whatsThis">
+ <string>After uploading, Lightscreen will put the resulting image URL in your clipboard.
+
+Warning: Cannot be used in tandem with the &quot;Copy screenshot to clipboard&quot; option.</string>
+ </property>
<property name="text">
<string>After uploading, copy the URL to the clipboard.</string>
</property>
</widget>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="QLabel" name="uploadServiceLabel">
<property name="text">
<string>Service:</string>
</property>
</widget>
</item>
<item>
<widget class="QComboBox" name="uploadServiceComboBox">
<item>
<property name="text">
<string>Imgur</string>
</property>
</item>
<item>
<property name="text">
<string>Pomf-clone</string>
</property>
</item>
</widget>
</item>
<item>
<spacer name="horizontalSpacer_7">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
</layout>
</item>
<item>
<widget class="QGroupBox" name="uploadServiceOptionsGroupBox">
<property name="title">
<string>Upload Service Options</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout_11">
<property name="spacing">
<number>2</number>
</property>
<property name="leftMargin">
<number>4</number>
</property>
<property name="topMargin">
<number>4</number>
</property>
<property name="rightMargin">
<number>4</number>
</property>
<property name="bottomMargin">
<number>4</number>
</property>
<item>
<widget class="QStackedWidget" name="uploadServiceStackWidget">
<property name="currentIndex">
<number>0</number>
</property>
<widget class="QWidget" name="page">
<layout class="QVBoxLayout" name="verticalLayout_13">
<property name="spacing">
<number>0</number>
</property>
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<widget class="ImgurOptionsWidget" name="imgurOptions" native="true"/>
</item>
</layout>
</widget>
<widget class="QWidget" name="page_2">
<layout class="QVBoxLayout" name="verticalLayout_14">
<property name="spacing">
<number>0</number>
</property>
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<widget class="PomfOptionsWidget" name="pomfOptions" native="true"/>
</item>
</layout>
</widget>
</widget>
</item>
</layout>
</widget>
</item>
</layout>
</widget>
<widget class="QWidget" name="optionsTab">
<attribute name="title">
<string>Options</string>
</attribute>
<layout class="QVBoxLayout" name="verticalLayout_8">
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<widget class="QScrollArea" name="optionsScrollArea">
<property name="sizePolicy">
<sizepolicy hsizetype="Minimum" vsizetype="Expanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>375</width>
<height>0</height>
</size>
</property>
<property name="frameShape">
<enum>QFrame::NoFrame</enum>
</property>
<property name="horizontalScrollBarPolicy">
<enum>Qt::ScrollBarAlwaysOff</enum>
</property>
<property name="widgetResizable">
<bool>true</bool>
</property>
<widget class="QWidget" name="scrollAreaWidgetContents">
<property name="geometry">
<rect>
<x>0</x>
- <y>0</y>
+ <y>-357</y>
<width>360</width>
<height>729</height>
</rect>
</property>
<layout class="QVBoxLayout" name="verticalLayout_5">
<property name="spacing">
<number>4</number>
</property>
<property name="leftMargin">
<number>6</number>
</property>
<property name="topMargin">
<number>6</number>
</property>
<property name="rightMargin">
<number>6</number>
</property>
<property name="bottomMargin">
<number>6</number>
</property>
<item>
<widget class="QGroupBox" name="interfaceGroupBox">
<property name="title">
<string>Interface</string>
</property>
<property name="flat">
<bool>true</bool>
</property>
<layout class="QVBoxLayout" name="verticalLayout_6">
<item>
<widget class="QCheckBox" name="trayCheckBox">
<property name="whatsThis">
<string/>
</property>
<property name="text">
<string>Sho&amp;w a system tray icon.</string>
</property>
</widget>
</item>
<item>
<widget class="QCheckBox" name="closeHideCheckBox">
<property name="text">
<string>C&amp;losing hides the main window.</string>
</property>
</widget>
</item>
<item>
<widget class="QCheckBox" name="hideCheckBox">
<property name="text">
<string>&amp;Hide Lightscreen while taking a screenshot.</string>
</property>
</widget>
</item>
<item>
<layout class="QGridLayout" name="notifyLayout">
<property name="topMargin">
<number>2</number>
</property>
<property name="bottomMargin">
<number>2</number>
</property>
<item row="1" column="1">
<widget class="QCheckBox" name="messageCheckBox">
<property name="whatsThis">
<string>Shows a completion message once the screenshot is saved, clicking this message takes you to the directory where the screenshot was saved.</string>
</property>
<property name="text">
<string>Tray icon Popup</string>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QCheckBox" name="playSoundCheckBox">
<property name="text">
<string>&amp;Sound cue</string>
</property>
</widget>
</item>
<item row="1" column="0">
<spacer name="horizontalSpacer_9">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeType">
<enum>QSizePolicy::Fixed</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>15</width>
<height>0</height>
</size>
</property>
</spacer>
</item>
<item row="1" column="2">
<spacer name="horizontalSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>0</height>
</size>
</property>
</spacer>
</item>
<item row="0" column="0" colspan="3">
<widget class="QLabel" name="notifyLabel">
<property name="font">
<font>
<weight>75</weight>
<bold>true</bold>
<underline>true</underline>
</font>
</property>
<property name="text">
<string>&amp;Notify with:</string>
</property>
<property name="buddy">
<cstring>messageCheckBox</cstring>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QGroupBox" name="previewGroupBox">
<property name="title">
<string>Screenshot Previews</string>
</property>
<property name="flat">
<bool>true</bool>
</property>
<property name="checkable">
<bool>true</bool>
</property>
<property name="checked">
<bool>true</bool>
</property>
<layout class="QGridLayout" name="gridLayout_3">
<item row="0" column="0">
<widget class="QLabel" name="previewSizeLabel">
<property name="text">
<string>Maximum Size:</string>
</property>
<property name="buddy">
<cstring>previewSizeSpinBox</cstring>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QSpinBox" name="previewSizeSpinBox">
<property name="buttonSymbols">
<enum>QAbstractSpinBox::PlusMinus</enum>
</property>
<property name="accelerated">
<bool>true</bool>
</property>
<property name="correctionMode">
<enum>QAbstractSpinBox::CorrectToNearestValue</enum>
</property>
<property name="suffix">
<string notr="true"> px</string>
</property>
<property name="minimum">
<number>200</number>
</property>
<property name="maximum">
<number>800</number>
</property>
<property name="singleStep">
<number>10</number>
</property>
<property name="value">
<number>300</number>
</property>
</widget>
</item>
<item row="0" column="4" rowspan="4">
<spacer name="horizontalSpacer_5">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item row="1" column="0">
<widget class="QLabel" name="previewPositionLabel">
<property name="text">
<string>Position:</string>
</property>
<property name="buddy">
<cstring>previewPositionComboBox</cstring>
</property>
</widget>
</item>
<item row="1" column="1" colspan="2">
<widget class="QComboBox" name="previewPositionComboBox">
<property name="currentIndex">
<number>3</number>
</property>
<item>
<property name="text">
<string>Top Left</string>
</property>
</item>
<item>
<property name="text">
<string>Top Right</string>
</property>
</item>
<item>
<property name="text">
<string>Bottom Left</string>
</property>
</item>
<item>
<property name="text">
<string>Bottom Right</string>
</property>
</item>
</widget>
</item>
<item row="2" column="0">
<widget class="QCheckBox" name="previewAutocloseCheckBox">
<property name="text">
<string>Auto-close after</string>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QSpinBox" name="previewAutocloseTimeSpinBox">
<property name="suffix">
<string> seconds</string>
</property>
<property name="minimum">
<number>1</number>
</property>
</widget>
</item>
<item row="2" column="2">
<widget class="QLabel" name="andLabel">
<property name="minimumSize">
<size>
<width>20</width>
<height>0</height>
</size>
</property>
<property name="text">
<string> and </string>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
<property name="buddy">
<cstring>previewAutocloseActionComboBox</cstring>
</property>
</widget>
</item>
<item row="2" column="3">
<widget class="QComboBox" name="previewAutocloseActionComboBox">
<property name="currentIndex">
<number>0</number>
</property>
<item>
<property name="text">
<string>save</string>
</property>
</item>
<item>
<property name="text">
<string>upload</string>
</property>
</item>
<item>
<property name="text">
<string>cancel</string>
</property>
</item>
</widget>
</item>
<item row="3" column="0">
<widget class="QLabel" name="previewDefaultActionLabel">
<property name="text">
<string>Default action:</string>
</property>
<property name="buddy">
<cstring>previewDefaultActionComboBox</cstring>
</property>
</widget>
</item>
<item row="3" column="1">
<widget class="QComboBox" name="previewDefaultActionComboBox">
<item>
<property name="text">
<string>save</string>
</property>
</item>
<item>
<property name="text">
<string>upload</string>
</property>
</item>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QGroupBox" name="screenshotsGroupBox">
<property name="title">
<string>Screenshots</string>
</property>
<property name="flat">
<bool>true</bool>
</property>
<layout class="QVBoxLayout" name="verticalLayout_7">
<item>
<widget class="QCheckBox" name="saveAsCheckBox">
<property name="text">
<string>Choose where to save each screenshot (&quot;&amp;Save as&quot;).</string>
</property>
</widget>
</item>
<item>
<widget class="QCheckBox" name="currentMonitorCheckBox">
<property name="text">
<string>&amp;Grab only the active monitor.</string>
</property>
</widget>
</item>
<item>
<widget class="QCheckBox" name="cursorCheckBox">
<property name="text">
<string>Inc&amp;lude the cursor in the screenshot.</string>
</property>
</widget>
</item>
<item>
<widget class="QCheckBox" name="magnifyCheckBox">
<property name="text">
<string>&amp;Magnify around the mouse in Area mode.</string>
</property>
</widget>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_2">
<property name="spacing">
<number>2</number>
</property>
<item>
<widget class="QCheckBox" name="optiPngCheckBox">
<property name="toolTip">
<string>Runs OptiPNG which reduces screenshot file size.</string>
</property>
<property name="text">
<string>O&amp;ptimize PNG screenshots.</string>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="optiPngLabel">
<property name="palette">
<palette>
<active>
<colorrole role="WindowText">
<brush brushstyle="SolidPattern">
<color alpha="255">
<red>128</red>
<green>0</green>
<blue>0</blue>
</color>
</brush>
</colorrole>
</active>
<inactive>
<colorrole role="WindowText">
<brush brushstyle="SolidPattern">
<color alpha="255">
<red>128</red>
<green>0</green>
<blue>0</blue>
</color>
</brush>
</colorrole>
</inactive>
<disabled>
<colorrole role="WindowText">
<brush brushstyle="SolidPattern">
<color alpha="255">
<red>141</red>
<green>138</green>
<blue>136</blue>
</color>
</brush>
</colorrole>
</disabled>
</palette>
</property>
<property name="text">
<string/>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer_10">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>0</height>
</size>
</property>
</spacer>
</item>
</layout>
</item>
<item>
<widget class="QCheckBox" name="replaceCheckBox">
<property name="text">
<string>Replace screenshots when there's an existing file.</string>
</property>
</widget>
</item>
<item>
<widget class="QCheckBox" name="areaAutocloseCheckBox">
<property name="text">
<string>Snap area screenshots automatically (no resizing).</string>
</property>
</widget>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_5">
<item>
<widget class="QLabel" name="delayLabel">
<property name="text">
<string>D&amp;elay:</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
<property name="buddy">
<cstring>delaySpinBox</cstring>
</property>
</widget>
</item>
<item>
<widget class="QSpinBox" name="delaySpinBox">
<property name="whatsThis">
<string>Selecting anything other than 0 in this option will cause the program to &lt;b&gt;wait&lt;/b&gt; that amount of seconds before taking the screenshot.</string>
</property>
<property name="specialValueText">
<string>none</string>
</property>
<property name="accelerated">
<bool>true</bool>
</property>
<property name="correctionMode">
<enum>QAbstractSpinBox::CorrectToNearestValue</enum>
</property>
<property name="suffix">
<string> seconds</string>
</property>
<property name="prefix">
<string/>
</property>
<property name="maximum">
<number>32767</number>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer_8">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>114</width>
<height>0</height>
</size>
</property>
</spacer>
</item>
</layout>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QGroupBox" name="clipboardGroupBox">
<property name="title">
<string>Clipboard</string>
</property>
<property name="flat">
<bool>true</bool>
</property>
<layout class="QVBoxLayout" name="verticalLayout_10">
<item>
<widget class="QCheckBox" name="clipboardCheckBox">
+ <property name="whatsThis">
+ <string>Lightscreen will copy the screenshot image data to your clipboard.
+
+Warning: Cannot be used in tandem with the &quot;After uploading, copy the URL to the clipboard.&quot; option</string>
+ </property>
<property name="text">
<string>&amp;Copy the screenshot to the clipboard.</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QGroupBox" name="historyGroupBox">
<property name="title">
<string>History</string>
</property>
<property name="flat">
<bool>true</bool>
</property>
<layout class="QHBoxLayout" name="historyLayout">
<item>
<widget class="QCheckBox" name="historyCheckBox">
+ <property name="whatsThis">
+ <string>Lightscreen will save a list of all the screenshots you've taken and where you've uploaded them to (and a deletion link to delete this upload [imgur only]).</string>
+ </property>
<property name="text">
<string>Save my screenshot history.</string>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer_6">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>95</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QPushButton" name="historyPushButton">
<property name="text">
<string>View &amp;History</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QGroupBox" name="updaterGroupBox">
<property name="title">
<string>Updater</string>
</property>
<property name="flat">
<bool>true</bool>
</property>
<layout class="QGridLayout" name="gridLayout_4">
<item row="0" column="0">
<widget class="QCheckBox" name="updaterCheckBox">
+ <property name="whatsThis">
+ <string>Every 7 days Lightscreen will ping the update server for a new version and notify you if there's an update to download.</string>
+ </property>
<property name="text">
<string>Check for updates regularly.</string>
</property>
</widget>
</item>
<item row="0" column="1">
<spacer name="horizontalSpacer_3">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>78</width>
<height>13</height>
</size>
</property>
</spacer>
</item>
<item row="0" column="2">
<widget class="QPushButton" name="checkUpdatesPushButton">
<property name="text">
<string>Chec&amp;k Now</string>
</property>
</widget>
</item>
<item row="1" column="0" colspan="3">
<widget class="QCheckBox" name="telemetryCheckBox">
+ <property name="whatsThis">
+ <string>Lightscreen will send anonymous data about which configuration settings you're using, to better understand how to improve this software.</string>
+ </property>
<property name="text">
<string>Send telemetry data when checking for updates.</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
</layout>
</widget>
</widget>
</item>
</layout>
</widget>
<widget class="QWidget" name="aboutTab">
<attribute name="title">
<string>About</string>
</attribute>
<layout class="QVBoxLayout" name="verticalLayout_9">
<item>
<widget class="QLabel" name="mainLabel">
<property name="text">
<string>Lightscreen is a simple tool to take screenshots, designed to be customizable and lightweight.&lt;br&gt;&lt;br&gt;
Created by &lt;a href=&quot;https://ckaiser.com.ar&quot;&gt;Christian Kaiser&lt;/a&gt;, with &lt;a href=&quot;#aboutqt&quot;&gt;Qt&lt;/a&gt;.</string>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
<property name="textInteractionFlags">
<set>Qt::LinksAccessibleByKeyboard|Qt::LinksAccessibleByMouse</set>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="licenseAboutLabel">
<property name="text">
<string>Released under the &lt;a href=&quot;http://www.gnu.org/licenses/gpl-2.0.html&quot;&gt;GNU General Public License&lt;/a&gt;.</string>
</property>
<property name="textInteractionFlags">
<set>Qt::LinksAccessibleByKeyboard|Qt::LinksAccessibleByMouse</set>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="versionLabel">
<property name="font">
<font>
<pointsize>12</pointsize>
<weight>75</weight>
<bold>true</bold>
</font>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="linksLabel">
<property name="text">
<string>&lt;a href=&quot;https://github.com/ckaiser/Lightscreen/&quot;&gt;GitHub page&lt;/a&gt;&lt;br&gt;&lt;br&gt;&lt;a href=&quot;https://lightscreen.com.ar/&quot;&gt;Lightscreen home page&lt;/a&gt;</string>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
<property name="textInteractionFlags">
<set>Qt::LinksAccessibleByKeyboard|Qt::LinksAccessibleByMouse</set>
</property>
</widget>
</item>
</layout>
</widget>
</widget>
</item>
<item>
<widget class="QDialogButtonBox" name="buttonBox">
<property name="standardButtons">
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
</property>
</widget>
</item>
</layout>
</widget>
<customwidgets>
<customwidget>
<class>HotkeyWidget</class>
<extends>QPushButton</extends>
<header location="global">widgets/hotkeywidget.h</header>
</customwidget>
<customwidget>
<class>ImgurOptionsWidget</class>
<extends>QWidget</extends>
<header location="global">widgets/imguroptionswidget.h</header>
<container>1</container>
</customwidget>
<customwidget>
<class>PomfOptionsWidget</class>
<extends>QWidget</extends>
<header location="global">widgets/pomfoptionswidget.h</header>
<container>1</container>
</customwidget>
</customwidgets>
<tabstops>
<tabstop>fileGroupBox</tabstop>
<tabstop>targetLineEdit</tabstop>
<tabstop>browsePushButton</tabstop>
<tabstop>prefixLineEdit</tabstop>
<tabstop>namingComboBox</tabstop>
<tabstop>namingOptionsButton</tabstop>
<tabstop>formatComboBox</tabstop>
<tabstop>qualitySlider</tabstop>
<tabstop>startupCheckBox</tabstop>
<tabstop>startupHideCheckBox</tabstop>
<tabstop>screenCheckBox</tabstop>
<tabstop>screenHotkeyWidget</tabstop>
<tabstop>areaCheckBox</tabstop>
<tabstop>areaHotkeyWidget</tabstop>
<tabstop>windowCheckBox</tabstop>
<tabstop>windowHotkeyWidget</tabstop>
<tabstop>windowPickerCheckBox</tabstop>
<tabstop>windowPickerHotkeyWidget</tabstop>
<tabstop>openCheckBox</tabstop>
<tabstop>openHotkeyWidget</tabstop>
<tabstop>directoryCheckBox</tabstop>
<tabstop>directoryHotkeyWidget</tabstop>
<tabstop>trayCheckBox</tabstop>
<tabstop>hideCheckBox</tabstop>
<tabstop>messageCheckBox</tabstop>
<tabstop>playSoundCheckBox</tabstop>
<tabstop>previewGroupBox</tabstop>
<tabstop>previewSizeSpinBox</tabstop>
<tabstop>previewPositionComboBox</tabstop>
<tabstop>previewAutocloseCheckBox</tabstop>
<tabstop>previewAutocloseTimeSpinBox</tabstop>
<tabstop>previewAutocloseActionComboBox</tabstop>
<tabstop>previewDefaultActionComboBox</tabstop>
<tabstop>saveAsCheckBox</tabstop>
<tabstop>currentMonitorCheckBox</tabstop>
<tabstop>cursorCheckBox</tabstop>
<tabstop>magnifyCheckBox</tabstop>
<tabstop>optiPngCheckBox</tabstop>
<tabstop>replaceCheckBox</tabstop>
<tabstop>areaAutocloseCheckBox</tabstop>
<tabstop>delaySpinBox</tabstop>
<tabstop>historyCheckBox</tabstop>
<tabstop>historyPushButton</tabstop>
<tabstop>updaterCheckBox</tabstop>
<tabstop>checkUpdatesPushButton</tabstop>
<tabstop>buttonBox</tabstop>
</tabstops>
<resources/>
<connections>
<connection>
<sender>buttonBox</sender>
<signal>rejected()</signal>
<receiver>OptionsDialog</receiver>
<slot>reject()</slot>
<hints>
<hint type="sourcelabel">
<x>307</x>
<y>304</y>
</hint>
<hint type="destinationlabel">
<x>286</x>
<y>274</y>
</hint>
</hints>
</connection>
<connection>
<sender>previewAutocloseCheckBox</sender>
<signal>toggled(bool)</signal>
<receiver>previewAutocloseTimeSpinBox</receiver>
<slot>setEnabled(bool)</slot>
<hints>
<hint type="sourcelabel">
<x>118</x>
<y>511</y>
</hint>
<hint type="destinationlabel">
<x>210</x>
<y>529</y>
</hint>
</hints>
</connection>
<connection>
<sender>previewAutocloseCheckBox</sender>
<signal>toggled(bool)</signal>
<receiver>previewAutocloseActionComboBox</receiver>
<slot>setEnabled(bool)</slot>
<hints>
<hint type="sourcelabel">
<x>115</x>
<y>511</y>
</hint>
<hint type="destinationlabel">
<x>302</x>
<y>529</y>
</hint>
</hints>
</connection>
<connection>
<sender>uploadServiceComboBox</sender>
<signal>currentIndexChanged(int)</signal>
<receiver>uploadServiceStackWidget</receiver>
<slot>setCurrentIndex(int)</slot>
<hints>
<hint type="sourcelabel">
<x>92</x>
<y>96</y>
</hint>
<hint type="destinationlabel">
<x>198</x>
<y>196</y>
</hint>
</hints>
</connection>
</connections>
</ui>
diff --git a/main.cpp b/main.cpp
index f294fb0..4d62f96 100644
--- a/main.cpp
+++ b/main.cpp
@@ -1,94 +1,93 @@
/*
* Copyright (C) 2017 Christian Kaiser
*
* This program is free 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 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 General Public License
* along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*/
#include <QApplication>
#include <QDesktopWidget>
#include <QLocale>
#ifdef Q_OS_WIN
#include <QtWinExtras>
#endif
#include "tools/os.h"
#include "tools/SingleApplication/singleapplication.h"
#include "lightscreenwindow.h"
int main(int argc, char *argv[])
{
#ifdef QT_DEBUG
qSetMessagePattern("%{message} @%{line}[%{function}()]");
#endif
QApplication::setOrganizationName("K");
QApplication::setApplicationName("Lightscreen");
QApplication::setApplicationVersion(APP_VERSION);
QApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
SingleApplication application(argc, argv);
application.setQuitOnLastWindowClosed(false);
LightscreenWindow lightscreen;
#ifdef Q_OS_WIN
if (QSysInfo::WindowsVersion >= QSysInfo::WV_WINDOWS7) {
auto jumplist = new QWinJumpList(&lightscreen);
QColor backgroundColor = qApp->palette("QToolTip").color(QPalette::Background);
if (QSysInfo::WindowsVersion == QSysInfo::WV_WINDOWS10) {
// contrast r hard
backgroundColor = Qt::black;
}
auto screenshotCategory = new QWinJumpListCategory(QObject::tr("Screenshot"));
screenshotCategory->setVisible(true);
screenshotCategory->addLink(os::icon("screen", backgroundColor), QObject::tr("Screen") , application.applicationFilePath(), QStringList("--screen"));
screenshotCategory->addLink(os::icon("area", backgroundColor), QObject::tr("Area") , application.applicationFilePath(), QStringList("--area"));
screenshotCategory->addLink(os::icon("pickWindow", backgroundColor), QObject::tr("Pick Window"), application.applicationFilePath(), QStringList("--pickwindow"));
auto uploadCategory = new QWinJumpListCategory(QObject::tr("Upload"));
uploadCategory->setVisible(true);
uploadCategory->addLink(os::icon("imgur", backgroundColor), QObject::tr("Upload Last") , application.applicationFilePath(), QStringList("--uploadlast"));
uploadCategory->addLink(os::icon("view-history", backgroundColor), QObject::tr("View History"), application.applicationFilePath(), QStringList("--viewhistory"));
auto actionsCategory = new QWinJumpListCategory(QObject::tr("Actions"));
actionsCategory->setVisible(true);
actionsCategory->addLink(os::icon("configure", backgroundColor), QObject::tr("Options") , application.applicationFilePath(), QStringList("--options"));
actionsCategory->addLink(os::icon("folder", backgroundColor), QObject::tr("Go to Folder") , application.applicationFilePath(), QStringList("--folder"));
actionsCategory->addLink(os::icon("no.big", backgroundColor), QObject::tr("Quit Lightscreen") , application.applicationFilePath(), QStringList("--quit"));
jumplist->addCategory(screenshotCategory);
jumplist->addCategory(uploadCategory);
jumplist->addCategory(actionsCategory);
}
#endif
if (application.arguments().size() > 1) {
lightscreen.executeArguments(application.arguments());
} else {
lightscreen.show();
}
QObject::connect(&application, &SingleApplication::instanceArguments, &lightscreen, &LightscreenWindow::executeArguments);
QObject::connect(&lightscreen, &LightscreenWindow::finished, &application, &SingleApplication::quit);
- int result = application.exec();
- return result;
+ return application.exec();
}
diff --git a/tools/screenshot.cpp b/tools/screenshot.cpp
index 84a665d..13a4af6 100644
--- a/tools/screenshot.cpp
+++ b/tools/screenshot.cpp
@@ -1,519 +1,524 @@
/*
* Copyright (C) 2017 Christian Kaiser
*
* This program is free 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 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 General Public License
* along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*/
#include <QApplication>
#include <QClipboard>
#include <QDateTime>
#include <QDesktopWidget>
#include <QFileDialog>
#include <QPainter>
#include <QPixmap>
#include <QProcess>
#include <QTextStream>
#include <QScreen>
#include <QStringBuilder>
#include "windowpicker.h"
#include "../dialogs/areadialog.h"
#include "uploader/uploader.h"
#include "screenshot.h"
#include "screenshotmanager.h"
#include "os.h"
#ifdef Q_OS_WIN
#include <windows.h>
#endif
#ifdef Q_OS_LINUX
#include <QX11Info>
#include <X11/X.h>
#include <X11/Xlib.h>
#endif
Screenshot::Screenshot(QObject *parent, Screenshot::Options options):
QObject(parent),
mOptions(options),
mPixmapDelay(false),
mUnloaded(false),
mUnloadFilename()
{
if (mOptions.format == Screenshot::PNG) {
mOptions.quality = 80;
}
}
Screenshot::~Screenshot()
{
if (!mUnloadFilename.isEmpty()) {
QFile::remove(mUnloadFilename);
}
}
QString Screenshot::getName(const NamingOptions &options, const QString &prefix, const QDir &directory)
{
QString naming;
int naming_largest = 0;
if (options.flip) {
naming = "%1" % prefix;
} else {
naming = prefix % "%1";
}
switch (options.naming) {
case Screenshot::Numeric: // Numeric
// Iterating through the folder to find the largest numeric naming.
for (auto file : directory.entryList(QDir::Files)) {
if (file.contains(prefix)) {
file.chop(file.size() - file.lastIndexOf("."));
file.remove(prefix);
if (file.toInt() > naming_largest) {
naming_largest = file.toInt();
}
}
}
if (options.leadingZeros > 0) {
//Pretty, huh?
QString format;
QTextStream(&format) << "%0" << (options.leadingZeros + 1) << "d";
naming = naming.arg(QString().sprintf(format.toLatin1(), naming_largest + 1));
} else {
naming = naming.arg(naming_largest + 1);
}
break;
case Screenshot::Date: // Date
naming = naming.arg(QLocale().toString(QDateTime::currentDateTime(), options.dateFormat));
break;
case Screenshot::Timestamp: // Timestamp
naming = naming.arg(QDateTime::currentDateTime().toTime_t());
break;
case Screenshot::Empty:
naming = naming.arg("");
break;
}
return naming;
}
const QString &Screenshot::unloadedFileName()
{
return mUnloadFilename;
}
const Screenshot::Options &Screenshot::options()
{
return mOptions;
}
QPixmap &Screenshot::pixmap()
{
return mPixmap;
}
//
void Screenshot::confirm(bool result)
{
if (result) {
save();
} else {
mOptions.result = Screenshot::Cancel;
emit finished();
}
emit cleanup();
mPixmap = QPixmap();
}
void Screenshot::confirmation()
{
emit askConfirmation();
if (mOptions.file) {
unloadPixmap();
}
}
void Screenshot::discard()
{
confirm(false);
}
void Screenshot::markUpload()
{
mOptions.upload = true;
}
void Screenshot::optimize()
{
QProcess *process = new QProcess(this);
// Delete the QProcess once it's done.
connect(process, SIGNAL(finished(int, QProcess::ExitStatus)), this , SLOT(optimizationDone()));
connect(process, SIGNAL(finished(int, QProcess::ExitStatus)), process, SLOT(deleteLater()));
QString optiPNG;
#ifdef Q_OS_UNIX
optiPNG = "optipng";
#else
optiPNG = qApp->applicationDirPath() % QDir::separator() % "optipng.exe";
#endif
if (!QFile::exists(optiPNG)) {
emit optimizationDone();
}
process->start(optiPNG, QStringList() << mOptions.fileName);
if (process->state() == QProcess::NotRunning) {
emit optimizationDone();
process->deleteLater();
}
}
void Screenshot::optimizationDone()
{
if (mOptions.upload) {
upload();
} else {
emit finished();
}
}
void Screenshot::save()
{
QString name = "";
QString fileName = "";
Screenshot::Result result = Screenshot::Failure;
if (mOptions.file && !mOptions.saveAs) {
name = newFileName();
} else if (mOptions.file && mOptions.saveAs) {
name = QFileDialog::getSaveFileName(0, tr("Save as.."), newFileName(), "*" % extension());
}
if (!mOptions.replace && QFile::exists(name % extension())) {
// Ugly? You should see my wife!
int count = 0;
int cunt = 0;
QString naming = QFileInfo(name).fileName();
for (auto file : QFileInfo(name % extension()).dir().entryList(QDir::Files)) {
if (file.contains(naming)) {
file.remove(naming);
file.remove(" (");
file.remove(")");
file.remove(extension());
cunt = file.toInt();
if (cunt > count) {
count = cunt;
}
}
}
name = name % " (" % QString::number(count % 1) % ")";
}
if (mOptions.clipboard && !(mOptions.upload && mOptions.urlClipboard)) {
if (mUnloaded) {
mUnloaded = false;
mPixmap = QPixmap(mUnloadFilename);
}
QApplication::clipboard()->setPixmap(mPixmap, QClipboard::Clipboard);
if (!mOptions.file) {
result = Screenshot::Success;
}
}
if (mOptions.file) {
fileName = name % extension();
if (name.isEmpty()) {
result = Screenshot::Cancel;
} else if (mUnloaded) {
result = (QFile::rename(mUnloadFilename, fileName)) ? Screenshot::Success : Screenshot::Failure;
} else if (mPixmap.save(fileName, 0, mOptions.quality)) {
result = Screenshot::Success;
} else {
result = Screenshot::Failure;
}
}
mOptions.fileName = fileName;
mOptions.result = result;
if (!mOptions.result) {
emit finished();
}
if (mOptions.format == Screenshot::PNG && mOptions.optimize && mOptions.file) {
if (!mOptions.upload) {
ScreenshotManager::instance()->saveHistory(mOptions.fileName);
}
optimize();
} else if (mOptions.upload) {
upload();
} else if (mOptions.file) {
ScreenshotManager::instance()->saveHistory(mOptions.fileName);
emit finished();
} else {
emit finished();
}
}
void Screenshot::setPixmap(const QPixmap &pixmap)
{
mPixmap = pixmap;
if (mPixmap.isNull()) {
emit confirm(false);
} else {
confirmation();
}
}
void Screenshot::take()
{
switch (mOptions.mode) {
case Screenshot::WholeScreen:
wholeScreen();
break;
case Screenshot::SelectedArea:
selectedArea();
break;
case Screenshot::ActiveWindow:
activeWindow();
break;
case Screenshot::SelectedWindow:
selectedWindow();
break;
}
if (mPixmapDelay) {
return;
}
if (mPixmap.isNull()) {
confirm(false);
} else {
confirmation();
}
}
void Screenshot::upload()
{
if (mOptions.file) {
Uploader::instance()->upload(mOptions.fileName, mOptions.uploadService);
} else if (unloadPixmap()) {
Uploader::instance()->upload(mUnloadFilename, mOptions.uploadService);
} else {
emit finished();
}
}
void Screenshot::uploadDone(const QString &url)
{
if (mOptions.urlClipboard && !url.isEmpty()) {
QApplication::clipboard()->setText(url, QClipboard::Clipboard);
}
emit finished();
}
+void Screenshot::refresh()
+{
+ grabDesktop();
+}
+
//
void Screenshot::activeWindow()
{
#ifdef Q_OS_WIN
HWND fWindow = GetForegroundWindow();
if (fWindow == NULL) {
return;
}
if (fWindow == GetDesktopWindow()) {
wholeScreen();
return;
}
mPixmap = os::grabWindow((WId)GetForegroundWindow());
#endif
#if defined(Q_OS_LINUX)
Window focus;
int revert;
XGetInputFocus(QX11Info::display(), &focus, &revert);
mPixmap = QPixmap::grabWindow(focus);
#endif
}
const QString Screenshot::extension() const
{
switch (mOptions.format) {
case Screenshot::PNG:
return QStringLiteral(".png");
break;
case Screenshot::BMP:
return QStringLiteral(".bmp");
break;
case Screenshot::WEBP:
return QStringLiteral(".webp");
break;
case Screenshot::JPEG:
return QStringLiteral(".jpg");
break;
}
}
void Screenshot::grabDesktop()
{
QRect geometry;
QPoint cursorPosition = QCursor::pos();
if (mOptions.currentMonitor) {
int currentScreen = qApp->desktop()->screenNumber(cursorPosition);
geometry = qApp->desktop()->screen(currentScreen)->geometry();
cursorPosition = cursorPosition - geometry.topLeft();
} else {
int top = 0;
for (QScreen *screen : QGuiApplication::screens()) {
auto screenRect = screen->geometry();
if (screenRect.top() < 0) {
top += screenRect.top() * -1;
}
if (screenRect.left() < 0) {
cursorPosition.setX(cursorPosition.x() + screenRect.width()); //= localCursorPos + screenRect.normalized().topLeft();
}
geometry = geometry.united(screenRect);
}
cursorPosition.setY(cursorPosition.y() + top);
}
mPixmap = QApplication::primaryScreen()->grabWindow(QApplication::desktop()->winId(), geometry.x(), geometry.y(), geometry.width(), geometry.height());
mPixmap.setDevicePixelRatio(QApplication::desktop()->devicePixelRatio());
if (mOptions.cursor && !mPixmap.isNull()) {
QPainter painter(&mPixmap);
auto cursorInfo = os::cursor();
auto cursorPixmap = cursorInfo.first;
cursorPixmap.setDevicePixelRatio(QApplication::desktop()->devicePixelRatio());
#if 0 // Debug cursor position helper
painter.setBrush(QBrush(Qt::darkRed));
painter.setPen(QPen(QBrush(Qt::red), 5));
QRectF rect;
rect.setSize(QSizeF(100, 100));
rect.moveCenter(cursorPosition);
painter.drawRoundRect(rect, rect.size().height()*2, rect.size().height()*2);
#endif
painter.drawPixmap(cursorPosition-cursorInfo.second, cursorPixmap);
}
}
const QString Screenshot::newFileName() const
{
if (!mOptions.directory.exists()) {
mOptions.directory.mkpath(mOptions.directory.path());
}
QString naming = Screenshot::getName(mOptions.namingOptions, mOptions.prefix, mOptions.directory);
QString path = QDir::toNativeSeparators(mOptions.directory.path());
// Cleanup
if (path.at(path.size() - 1) != QDir::separator() && !path.isEmpty()) {
path.append(QDir::separator());
}
QString fileName;
fileName.append(path);
fileName.append(naming);
return fileName;
}
void Screenshot::selectedArea()
{
grabDesktop();
if (mPixmap.isNull()) {
return;
}
AreaDialog selector(this);
int result = selector.exec();
if (result == QDialog::Accepted) {
mPixmap = mPixmap.copy(selector.resultRect());
} else {
mPixmap = QPixmap();
}
}
void Screenshot::selectedWindow()
{
WindowPicker *windowPicker = new WindowPicker;
mPixmapDelay = true;
connect(windowPicker, SIGNAL(pixmap(QPixmap)), this, SLOT(setPixmap(QPixmap)));
}
bool Screenshot::unloadPixmap()
{
if (mUnloaded) {
return true;
}
// Unloading the pixmap to reduce memory usage during previews
mUnloadFilename = QString("%1/.screenshot.%2%3").arg(mOptions.directory.path()).arg(qrand() * qrand() + QDateTime::currentDateTime().toTime_t()).arg(extension());
mUnloaded = mPixmap.save(mUnloadFilename, 0, mOptions.quality);
if (mUnloaded) {
mPixmap = QPixmap();
}
return mUnloaded;
}
void Screenshot::wholeScreen()
{
grabDesktop();
}
diff --git a/tools/screenshot.h b/tools/screenshot.h
index ac7d4c8..608c14c 100644
--- a/tools/screenshot.h
+++ b/tools/screenshot.h
@@ -1,142 +1,143 @@
/*
* Copyright (C) 2017 Christian Kaiser
*
* This program is free 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 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 General Public License
* along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*/
#ifndef SCREENSHOT_H
#define SCREENSHOT_H
#include <QObject>
#include <QDir>
#include <QPixmap>
class Screenshot : public QObject
{
Q_OBJECT
public:
enum Format {
PNG = 0,
JPEG = 1,
BMP = 2,
WEBP = 3
};
Q_ENUM(Format)
enum Naming {
Numeric = 0,
Date = 1,
Timestamp = 2,
Empty = 3
};
Q_ENUM(Naming)
enum Mode {
None = 0,
WholeScreen = 1,
ActiveWindow = 2,
SelectedArea = 3,
SelectedWindow = 4
};
Q_ENUM(Mode)
enum Result {
Failure = 0,
Success = 1,
Cancel = 2
};
Q_ENUM(Result)
struct NamingOptions {
Naming naming;
bool flip;
int leadingZeros;
QString dateFormat;
};
struct Options {
QString fileName;
Result result;
Format format;
NamingOptions namingOptions;
QDir directory;
QString prefix;
QString uploadService;
int mode;
int quality;
bool animations;
bool clipboard;
bool urlClipboard;
bool currentMonitor;
bool cursor;
bool file;
bool magnify;
bool optimize;
bool preview;
bool replace;
bool saveAs;
bool upload;
};
Screenshot(QObject *parent, Screenshot::Options options);
~Screenshot();
const Screenshot::Options &options();
QPixmap &pixmap();
static QString getName(const NamingOptions &options, const QString &prefix, const QDir &directory);
const QString &unloadedFileName();
public slots:
void confirm(bool result = true);
void confirmation();
void discard();
void markUpload();
void optimize();
void optimizationDone();
void save();
void setPixmap(const QPixmap &pixmap);
void take();
void upload();
void uploadDone(const QString &url);
+ void refresh();
signals:
void askConfirmation();
void cleanup();
void finished();
private:
void activeWindow();
const QString extension() const;
void grabDesktop();
const QString newFileName() const;
void selectedArea();
void selectedWindow();
bool unloadPixmap();
void wholeScreen();
private:
Screenshot::Options mOptions;
QPixmap mPixmap;
bool mPixmapDelay;
bool mUnloaded;
QString mUnloadFilename;
};
#endif // SCREENSHOT_H
diff --git a/updater/updater.cpp b/updater/updater.cpp
index 9534926..d34757d 100644
--- a/updater/updater.cpp
+++ b/updater/updater.cpp
@@ -1,100 +1,98 @@
/*
* Copyright (C) 2017 Christian Kaiser
*
* This program is free 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 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 General Public License
* along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*/
#include <QApplication>
#include <QDate>
#include <QNetworkAccessManager>
#include <QNetworkRequest>
#include <QNetworkReply>
#include <QVersionNumber>
#include <QJsonDocument>
#include <QJsonObject>
#include <QSettings>
#include "updater.h"
#include "../dialogs/updaterdialog.h"
#include "../tools/screenshotmanager.h"
Updater::Updater(QObject *parent) :
QObject(parent)
{
connect(&mNetwork, &QNetworkAccessManager::finished, this, &Updater::finished);
}
void Updater::check()
{
QNetworkRequest request(QUrl("https://lightscreen.com.ar/version_telemetry"));
request.setHeader(QNetworkRequest::ContentTypeHeader, "application/json");
QJsonObject telemetryObject;
telemetryObject.insert("version", qApp->applicationVersion());
telemetryObject.insert("manual_check", property("withFeedback").toBool());
telemetryObject.insert("platform", QJsonObject{
{"product_type", QSysInfo::productType()},
{"product_version", QSysInfo::productVersion()},
{"kernel_type", QSysInfo::kernelType()},
{"kernel_version", QSysInfo::kernelVersion()}
});
auto settings = ScreenshotManager::instance()->settings();
if (settings->value("options/telemetry", false).toBool()) {
QJsonObject settingsObject;
const auto keys = settings->allKeys();
for (const auto& key : qAsConst(keys)) {
if (key.contains("token") ||
key.contains("username") ||
key.contains("album") ||
key.contains("lastScreenshot") ||
key.contains("target") ||
key.contains("geometry")) {
continue; // Privacy/useless stuff
}
settingsObject.insert(key, QJsonValue::fromVariant(settings->value(key)));
}
telemetryObject.insert("settings", settingsObject);
}
- QJsonDocument telemetry(telemetryObject);
-
- mNetwork.post(request, telemetry.toJson());
+ mNetwork.post(request, QJsonDocument(telemetryObject).toJson());
}
void Updater::checkWithFeedback()
{
UpdaterDialog updaterDialog;
connect(this, &Updater::done, &updaterDialog, &UpdaterDialog::updateDone);
setProperty("withFeedback", true);
check();
updaterDialog.exec();
}
void Updater::finished(QNetworkReply *reply)
{
QByteArray data = reply->readAll();
auto currentVersion = QVersionNumber::fromString(qApp->applicationVersion()).normalized();
auto remoteVersion = QVersionNumber::fromString(QString(data)).normalized();
emit done(remoteVersion > currentVersion);
}

File Metadata

Mime Type
text/x-diff
Expires
Fri, Sep 12, 2:28 PM (1 d, 13 h)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
42893
Default Alt Text
(111 KB)

Event Timeline