Page MenuHomePhabricator (Chris)

No OneTemporary

Size
72 KB
Referenced Files
None
Subscribers
None
diff --git a/dialogs/areadialog.cpp b/dialogs/areadialog.cpp
index ffe5379..641b1b4 100644
--- a/dialogs/areadialog.cpp
+++ b/dialogs/areadialog.cpp
@@ -1,606 +1,608 @@
/*
* 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>
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::keyPressEvent(QKeyEvent *e)
{
if (e->key() == Qt::Key_Escape) {
cancel();
} else if (e->key() == Qt::Key_Enter || e->key() == Qt::Key_Return) {
grabRect();
} else {
e->ignore();
}
}
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 (!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));
- magPainter.drawLine(QLine(magnified.rect().left(), magnified.rect().width()/2, magnified.rect().right(), magnified.rect().width()/2));
- magPainter.drawLine(QLine(magnified.rect().width()/2, 0, magnified.rect().height()/2, magnified.height()));
+
+ 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/optionsdialog.cpp b/dialogs/optionsdialog.cpp
index 55fd7e7..ab82c57 100644
--- a/dialogs/optionsdialog.cpp
+++ b/dialogs/optionsdialog.cpp
@@ -1,863 +1,861 @@
/*
* 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 <QToolTip>
#include <QCompleter>
#include <QDate>
#include <QDesktopServices>
#include <QDesktopWidget>
#include <QDirModel>
#include <QFileDialog>
#include <QKeyEvent>
#include <QMessageBox>
#include <QProcess>
#include <QSettings>
#include <QTimer>
#include <QUrl>
#include <QInputDialog>
#include <QMenu>
#include <QAction>
#include <QFutureWatcher>
#include <QtConcurrent>
#ifdef Q_OS_WIN
#include <windows.h>
#endif
#include "optionsdialog.h"
#include "namingdialog.h"
#include "historydialog.h"
#include "../tools/os.h"
#include "../tools/screenshot.h"
#include "../tools/screenshotmanager.h"
#include "../tools/uploader/uploader.h"
#include "../updater/updater.h"
OptionsDialog::OptionsDialog(QWidget *parent) :
QDialog(parent)
{
ui.setupUi(this);
setModal(true);
#if defined(Q_OS_LINUX)
// KDE-specific style tweaks.
if (qApp->style()->objectName() == "oxygen") {
ui.browsePushButton->setMaximumWidth(30);
ui.namingOptionsButton->setMaximumWidth(30);
ui.fileGroupBox->setFlat(false);
ui.startupGroupBox->setFlat(false);
ui.capturesGroupBox->setFlat(false);
ui.controlGroupBox->setFlat(false);
ui.interfaceGroupBox->setFlat(false);
ui.screenshotsGroupBox->setFlat(false);
ui.previewGroupBox->setFlat(false);
ui.updaterGroupBox->setFlat(false);
ui.historyGroupBox->setFlat(false);
ui.clipboardGroupBox->setFlat(false);
ui.optionsTab->layout()->setContentsMargins(0, 0, 6, 0);
ui.aboutTab->layout()->setMargin(8);
}
#endif
setEnabled(false); // We disable the widgets to prevent any user interaction until the settings have loaded.
QMetaObject::invokeMethod(this, "init" , Qt::QueuedConnection);
QMetaObject::invokeMethod(this, "loadSettings", Qt::QueuedConnection);
}
void OptionsDialog::accepted()
{
if (hotkeyCollision()) {
QMessageBox::critical(this, tr("Hotkey conflict"), tr("You have assigned the same hotkeys to more than one action."));
return;
}
if (ui.prefixLineEdit->text().contains(QRegExp("[?:\\\\/*\"<>|]"))) {
QMessageBox::critical(this, tr("Filename character error"), tr("The filename can't contain any of the following characters: ? : \\ / * \" < > |"));
return;
}
if (!ui.fileGroupBox->isChecked() && !ui.clipboardCheckBox->isChecked()) {
QMessageBox::critical(this, tr("Final Destination"), tr("You can't take screenshots unless you enable either file saving or the clipboard."));
return;
}
saveSettings();
accept();
}
void OptionsDialog::checkUpdatesNow()
{
Updater updater;
updater.checkWithFeedback();
}
void OptionsDialog::exportSettings()
{
QString exportFileName = QFileDialog::getSaveFileName(this,
tr("Export Settings"),
QStandardPaths::writableLocation(QStandardPaths::DocumentsLocation) + QDir::separator() + "config.ini",
tr("Lightscreen Settings (*.ini)"));
if (exportFileName.isEmpty()) {
return;
}
if (QFile::exists(exportFileName)) {
QFile::remove(exportFileName);
}
QSettings exportedSettings(exportFileName, QSettings::IniFormat);
for (auto key : settings()->allKeys()) {
exportedSettings.setValue(key, settings()->value(key));
}
}
void OptionsDialog::importSettings()
{
QString importFileName = QFileDialog::getOpenFileName(this,
tr("Import Settings"),
QStandardPaths::writableLocation(QStandardPaths::DocumentsLocation),
tr("Lightscreen Settings (*.ini)"));
QSettings importedSettings(importFileName, QSettings::IniFormat);
saveSettings();
for (auto key : importedSettings.allKeys()) {
if (settings()->contains(key)) {
settings()->setValue(key, importedSettings.value(key));
}
}
loadSettings();
}
void OptionsDialog::loadSettings()
{
settings()->sync();
setUpdatesEnabled(false);
if (!settings()->contains("file/format")) {
// If there are no settings, get rid of the cancel button so that the user is forced to save them
ui.buttonBox->clear();
ui.buttonBox->addButton(QDialogButtonBox::Ok);
}
ui.startupCheckBox->toggle();
ui.trayCheckBox->toggle();
ui.previewAutocloseCheckBox->toggle();
QString targetDefault;
if (ScreenshotManager::instance()->portableMode()) {
targetDefault = tr("Screenshots");
} else {
targetDefault = os::getDocumentsPath() + QDir::separator() + tr("Screenshots");
}
settings()->beginGroup("file");
ui.formatComboBox->setCurrentIndex(settings()->value("format", 1).toInt());
ui.prefixLineEdit->setText(settings()->value("prefix", tr("screenshot.")).toString());
ui.namingComboBox->setCurrentIndex(settings()->value("naming", 0).toInt());
ui.targetLineEdit->setText(settings()->value("target", targetDefault).toString());
ui.fileGroupBox->setChecked(settings()->value("enabled", true).toBool());
settings()->endGroup();
settings()->beginGroup("options");
ui.startupCheckBox->setChecked(settings()->value("startup", false).toBool());
ui.startupHideCheckBox->setChecked(settings()->value("startupHide", true).toBool());
ui.hideCheckBox->setChecked(settings()->value("hide", true).toBool());
ui.delaySpinBox->setValue(settings()->value("delay", 0).toInt());
flipToggled(settings()->value("flip", false).toBool());
ui.trayCheckBox->setChecked(settings()->value("tray", true).toBool());
ui.messageCheckBox->setChecked(settings()->value("message", true).toBool());
ui.qualitySlider->setValue(settings()->value("quality", 100).toInt());
ui.playSoundCheckBox->setChecked(settings()->value("playSound", false).toBool());
ui.updaterCheckBox->setChecked(!settings()->value("disableUpdater", false).toBool());
ui.telemetryCheckBox->setChecked(settings()->value("telemetry", false).toBool());
ui.magnifyCheckBox->setChecked(settings()->value("magnify", false).toBool());
ui.cursorCheckBox->setChecked(settings()->value("cursor", true).toBool());
ui.saveAsCheckBox->setChecked(settings()->value("saveAs", false).toBool());
ui.previewGroupBox->setChecked(settings()->value("preview", false).toBool());
ui.previewSizeSpinBox->setValue(settings()->value("previewSize", 300).toInt());
ui.previewPositionComboBox->setCurrentIndex(settings()->value("previewPosition", 3).toInt());
ui.previewAutocloseCheckBox->setChecked(settings()->value("previewAutoclose", false).toBool());
ui.previewAutocloseTimeSpinBox->setValue(settings()->value("previewAutocloseTime", 15).toInt());
ui.previewAutocloseActionComboBox->setCurrentIndex(settings()->value("previewAutocloseAction", 0).toInt());
ui.previewDefaultActionComboBox->setCurrentIndex(settings()->value("previewDefaultAction", 0).toInt());
ui.areaAutocloseCheckBox->setChecked(settings()->value("areaAutoclose", false).toBool());
// History mode is neat for normal operation but I'll keep it disabled by default on portable mode.
ui.historyCheckBox->setChecked(settings()->value("history", (ScreenshotManager::instance()->portableMode()) ? false : true).toBool());
// Advanced
ui.clipboardCheckBox->setChecked(settings()->value("clipboard", true).toBool());
ui.urlClipboardCheckBox->setChecked(settings()->value("urlClipboard", false).toBool());
ui.optiPngCheckBox->setChecked(settings()->value("optimize", false).toBool());
ui.closeHideCheckBox->setChecked(settings()->value("closeHide", true).toBool());
ui.currentMonitorCheckBox->setChecked(settings()->value("currentMonitor", false).toBool());
ui.replaceCheckBox->setChecked(settings()->value("replace", false).toBool());
ui.uploadCheckBox->setChecked(settings()->value("uploadAuto", false).toBool());
#ifdef Q_OS_WIN
if (!QFile::exists(qApp->applicationDirPath() + QDir::separator() + "optipng.exe")) {
ui.optiPngCheckBox->setEnabled(false);
ui.optiPngLabel->setText("optipng.exe not found");
}
#elif defined(Q_OS_LINUX)
if (!QProcess::startDetached("optipng")) {
ui.optiPngCheckBox->setChecked(false);
ui.optiPngCheckBox->setEnabled(false);
ui.optiPngLabel->setText(tr("Install 'OptiPNG'"));
}
//TODO: Sound cue support on Linux
ui.playSoundCheckBox->setVisible(false);
ui.playSoundCheckBox->setChecked(false);
//TODO: Cursor support on X11
ui.cursorCheckBox->setVisible(false);
ui.cursorCheckBox->setChecked(false);
#endif
settings()->endGroup();
settings()->beginGroup("actions");
// This toggle is for the first run
ui.screenCheckBox->toggle();
ui.areaCheckBox->toggle();
ui.windowCheckBox->toggle();
ui.windowPickerCheckBox->toggle();
ui.openCheckBox->toggle();
ui.directoryCheckBox->toggle();
settings()->beginGroup("screen");
ui.screenCheckBox->setChecked(settings()->value("enabled", true).toBool());
ui.screenHotkeyWidget->setHotkey(settings()->value("hotkey", "Print").toString());
settings()->endGroup();
settings()->beginGroup("area");
ui.areaCheckBox->setChecked(settings()->value("enabled").toBool());
ui.areaHotkeyWidget->setHotkey(settings()->value("hotkey", "Ctrl+Print").toString());
settings()->endGroup();
settings()->beginGroup("window");
ui.windowCheckBox->setChecked(settings()->value("enabled").toBool());
ui.windowHotkeyWidget->setHotkey(settings()->value("hotkey", "Alt+Print").toString());
settings()->endGroup();
settings()->beginGroup("windowPicker");
ui.windowPickerCheckBox->setChecked(settings()->value("enabled").toBool());
ui.windowPickerHotkeyWidget->setHotkey(settings()->value("hotkey", "Ctrl+Alt+Print").toString());
settings()->endGroup();
settings()->beginGroup("open");
ui.openCheckBox->setChecked(settings()->value("enabled").toBool());
ui.openHotkeyWidget->setHotkey(settings()->value("hotkey", "Ctrl+PgUp").toString());
settings()->endGroup();
settings()->beginGroup("directory");
ui.directoryCheckBox->setChecked(settings()->value("enabled").toBool());
ui.directoryHotkeyWidget->setHotkey(settings()->value("hotkey", "Ctrl+PgDown").toString());
settings()->endGroup();
settings()->endGroup();
settings()->beginGroup("upload");
ui.uploadServiceComboBox->setCurrentIndex(settings()->value("service").toInt());
settings()->beginGroup("imgur");
ui.imgurOptions->setUser(settings()->value("account_username", "").toString());
settings()->endGroup();
settings()->beginGroup("pomf");
// TODO: Move to pomfuploader in a more generic way.
QString pomf_url = settings()->value("pomf_url", "").toString();
if (!pomf_url.isEmpty()) {
if (ui.pomfOptions->ui.pomfUrlComboBox->findText(pomf_url, Qt::MatchFixedString) == -1) {
ui.pomfOptions->ui.pomfUrlComboBox->addItem(pomf_url);
}
ui.pomfOptions->ui.pomfUrlComboBox->setCurrentText(settings()->value("pomf_url", "").toString());
ui.pomfOptions->ui.verifyButton->setEnabled(!settings()->value("pomf_url", "").toString().isEmpty());
}
settings()->endGroup();
settings()->endGroup();
QTimer::singleShot(0, this, &OptionsDialog::updatePreview);
setEnabled(true);
setUpdatesEnabled(true);
}
void OptionsDialog::openUrl(QString url)
{
if (url == "#aboutqt") {
qApp->aboutQt();
} else {
QDesktopServices::openUrl(QUrl(url));
}
}
void OptionsDialog::saveSettings()
{
settings()->beginGroup("file");
settings()->setValue("format", ui.formatComboBox->currentIndex());
settings()->setValue("prefix", ui.prefixLineEdit->text());
settings()->setValue("naming", ui.namingComboBox->currentIndex());
settings()->setValue("target", ui.targetLineEdit->text());
settings()->setValue("enabled", ui.fileGroupBox->isChecked());
settings()->endGroup();
settings()->beginGroup("options");
settings()->setValue("startup", ui.startupCheckBox->isChecked());
settings()->setValue("startupHide", ui.startupHideCheckBox->isChecked());
settings()->setValue("hide", ui.hideCheckBox->isChecked());
settings()->setValue("delay", ui.delaySpinBox->value());
settings()->setValue("tray", ui.trayCheckBox->isChecked());
settings()->setValue("message", ui.messageCheckBox->isChecked());
settings()->setValue("quality", ui.qualitySlider->value());
settings()->setValue("playSound", ui.playSoundCheckBox->isChecked());
// This settings is inverted because the first iteration of the Updater did not have a settings but instead relied on the messagebox choice of the user.
settings()->setValue("disableUpdater", !ui.updaterCheckBox->isChecked());
settings()->setValue("telemetry", ui.telemetryCheckBox->isChecked());
settings()->setValue("magnify", ui.magnifyCheckBox->isChecked());
settings()->setValue("cursor", ui.cursorCheckBox->isChecked());
settings()->setValue("saveAs", ui.saveAsCheckBox->isChecked());
settings()->setValue("preview", ui.previewGroupBox->isChecked());
settings()->setValue("previewSize", ui.previewSizeSpinBox->value());
settings()->setValue("previewPosition", ui.previewPositionComboBox->currentIndex());
settings()->setValue("previewAutoclose", ui.previewAutocloseCheckBox->isChecked());
settings()->setValue("previewAutocloseTime", ui.previewAutocloseTimeSpinBox->value());
settings()->setValue("previewAutocloseAction", ui.previewAutocloseActionComboBox->currentIndex());
settings()->setValue("previewDefaultAction", ui.previewDefaultActionComboBox->currentIndex());
settings()->setValue("areaAutoclose", ui.areaAutocloseCheckBox->isChecked());
settings()->setValue("history", ui.historyCheckBox->isChecked());
// Advanced
settings()->setValue("closeHide", ui.closeHideCheckBox->isChecked());
settings()->setValue("clipboard", ui.clipboardCheckBox->isChecked());
settings()->setValue("urlClipboard", ui.urlClipboardCheckBox->isChecked());
settings()->setValue("optimize", ui.optiPngCheckBox->isChecked());
settings()->setValue("currentMonitor", ui.currentMonitorCheckBox->isChecked());
settings()->setValue("replace", ui.replaceCheckBox->isChecked());
//Upload
settings()->setValue("uploadAuto", ui.uploadCheckBox->isChecked());
settings()->endGroup();
settings()->beginGroup("actions");
settings()->beginGroup("screen");
settings()->setValue("enabled", ui.screenCheckBox->isChecked());
settings()->setValue("hotkey" , ui.screenHotkeyWidget->hotkey());
settings()->endGroup();
settings()->beginGroup("area");
settings()->setValue("enabled", ui.areaCheckBox->isChecked());
settings()->setValue("hotkey" , ui.areaHotkeyWidget->hotkey());
settings()->endGroup();
settings()->beginGroup("window");
settings()->setValue("enabled", ui.windowCheckBox->isChecked());
settings()->setValue("hotkey" , ui.windowHotkeyWidget->hotkey());
settings()->endGroup();
settings()->beginGroup("windowPicker");
settings()->setValue("enabled", ui.windowPickerCheckBox->isChecked());
settings()->setValue("hotkey" , ui.windowPickerHotkeyWidget->hotkey());
settings()->endGroup();
settings()->beginGroup("open");
settings()->setValue("enabled", ui.openCheckBox->isChecked());
settings()->setValue("hotkey" , ui.openHotkeyWidget->hotkey());
settings()->endGroup();
settings()->beginGroup("directory");
settings()->setValue("enabled", ui.directoryCheckBox->isChecked());
settings()->setValue("hotkey" , ui.directoryHotkeyWidget->hotkey());
settings()->endGroup();
settings()->endGroup();
settings()->beginGroup("upload");
settings()->setValue("service", ui.uploadServiceComboBox->currentIndex());
settings()->beginGroup("imgur");
settings()->setValue("anonymous", settings()->value("account_username").toString().isEmpty());
settings()->setValue("album" , ui.imgurOptions->ui.albumComboBox->property("currentData").toString());
settings()->endGroup();
settings()->beginGroup("pomf");
settings()->setValue("pomf_url", ui.pomfOptions->ui.pomfUrlComboBox->currentText());
settings()->endGroup();
settings()->endGroup();
}
void OptionsDialog::updatePreview()
{
Screenshot::NamingOptions options;
options.naming = (Screenshot::Naming) ui.namingComboBox->currentIndex();
options.flip = settings()->value("options/flip", false).toBool();
options.leadingZeros = settings()->value("options/naming/leadingZeros", 0).toInt();
options.dateFormat = settings()->value("options/naming/dateFormat", "yyyy-MM-dd").toString();
if (ui.fileGroupBox->isChecked()) { // Only change the naming button when file options are enabled.
ui.namingOptionsButton->setDisabled((options.naming == Screenshot::Empty));
}
QString preview = Screenshot::getName(options,
ui.prefixLineEdit->text(),
QDir(ui.targetLineEdit->text()));
preview = QString("%1.%2").arg(preview).arg(ui.formatComboBox->currentText().toLower());
if (preview.length() >= 40) {
preview.truncate(37);
preview.append("...");
}
ui.previewLabel->setText(preview);
ui.qualitySlider->setEnabled(ui.formatComboBox->currentText() != "PNG");
ui.qualityLabel->setEnabled(ui.qualitySlider->isEnabled());
}
void OptionsDialog::viewHistory()
{
HistoryDialog historyDialog(this);
historyDialog.exec();
}
//
bool OptionsDialog::event(QEvent *event)
{
if (event->type() == QEvent::Close || event->type() == QEvent::Hide) {
settings()->setValue("geometry/optionsDialog", saveGeometry());
if (!settings()->contains("file/format")) {
// I'm afraid I can't let you do that, Dave.
event->ignore();
return false;
}
} else if (event->type() == QEvent::Show) {
if (settings()->contains("geometry/optionsDialog")) {
restoreGeometry(settings()->value("geometry/optionsDialog").toByteArray());
} else {
move(QApplication::desktop()->screenGeometry(this).center() - rect().center());
}
}
return QDialog::event(event);
}
#ifdef Q_OS_WIN
// Qt does not send the print screen key as a regular QKeyPress event, so we must use the Windows API
bool OptionsDialog::nativeEvent(const QByteArray &eventType, void *message, long *result)
{
if (eventType == "windows_generic_MSG") {
MSG *m = static_cast<MSG *>(message);
if ((m->message == WM_KEYUP || m->message == WM_SYSKEYUP) && m->wParam == VK_SNAPSHOT) {
qApp->postEvent(qApp->focusWidget(), new QKeyEvent(QEvent::KeyPress, Qt::Key_Print, qApp->queryKeyboardModifiers()));
}
}
return QDialog::nativeEvent(eventType, message, result);
}
#endif
//
void OptionsDialog::browse()
{
QString fileName = QFileDialog::getExistingDirectory(this,
tr("Select where you want to save the screenshots"),
ui.targetLineEdit->text());
if (fileName.isEmpty()) {
return;
}
ui.targetLineEdit->setText(fileName);
updatePreview();
}
void OptionsDialog::dialogButtonClicked(QAbstractButton *button)
{
if (ui.buttonBox->buttonRole(button) == QDialogButtonBox::ResetRole) {
QPushButton *pb = qobject_cast<QPushButton *>(button);
pb->showMenu();
}
}
void OptionsDialog::restoreDefaults()
{
QMessageBox msgBox;
msgBox.setWindowTitle(tr("Lightscreen - Restore Default Options"));
msgBox.setText(tr("Restoring the default options will cause you to lose all of your current configuration."));
msgBox.setIcon(QMessageBox::Warning);
msgBox.addButton(tr("Restore"), QMessageBox::ActionRole);
QPushButton *dontRestoreButton = msgBox.addButton(tr("Don't Restore"), QMessageBox::ActionRole);
msgBox.setDefaultButton(dontRestoreButton);
msgBox.exec();
if (msgBox.clickedButton() == dontRestoreButton) {
return;
}
settings()->clear();
loadSettings();
}
void OptionsDialog::flipToggled(bool checked)
{
setUpdatesEnabled(false);
ui.filenameLayout->removeWidget(ui.prefixLineEdit);
ui.filenameLayout->removeWidget(ui.namingComboBox);
if (checked) {
ui.filenameLayout->addWidget(ui.namingComboBox);
ui.filenameLayout->addWidget(ui.prefixLineEdit);
} else {
ui.filenameLayout->addWidget(ui.prefixLineEdit);
ui.filenameLayout->addWidget(ui.namingComboBox);
}
if (ui.prefixLineEdit->text() == tr("screenshot.")
&& checked) {
ui.prefixLineEdit->setText(tr(".screenshot"));
}
if (ui.prefixLineEdit->text() == tr(".screenshot")
&& !checked) {
ui.prefixLineEdit->setText(tr("screenshot."));
}
setUpdatesEnabled(true); // Avoids flicker
}
void OptionsDialog::init()
{
// Make the scroll area share the Tab Widget background color
- QPalette optionsPalette = ui.optionsScrollArea->palette();
- optionsPalette.setColor(QPalette::Window, ui.tabWidget->palette().color(QPalette::Base));
- ui.optionsScrollArea->setPalette(optionsPalette);
+ ui.optionsScrollArea->setStyleSheet("QScrollArea { background-color: transparent; } #scrollAreaWidgetContents { background-color: transparent; }");
ui.browsePushButton->setIcon(os::icon("folder"));
ui.namingOptionsButton->setIcon(os::icon("configure"));
// Export/Import menu .
QMenu *optionsMenu = new QMenu(tr("Options"));
QAction *exportAction = new QAction(tr("&Export.."), optionsMenu);
connect(exportAction, &QAction::triggered, this, &OptionsDialog::exportSettings);
QAction *importAction = new QAction(tr("&Import.."), optionsMenu);
connect(importAction, &QAction::triggered, this, &OptionsDialog::importSettings);
QAction *restoreAction = new QAction(tr("&Restore Defaults"), optionsMenu);
connect(restoreAction, &QAction::triggered, this, &OptionsDialog::restoreDefaults);
optionsMenu->addAction(exportAction);
optionsMenu->addAction(importAction);
optionsMenu->addSeparator();
optionsMenu->addAction(restoreAction);
QPushButton *optionsButton = new QPushButton(tr("Options"), this);
optionsButton->setMenu(optionsMenu);
ui.buttonBox->addButton(optionsButton, QDialogButtonBox::ResetRole);
// Set up the autocomplete for the directory.
QCompleter *completer = new QCompleter(this);
completer->setModel(new QDirModel(QStringList(), QDir::Dirs, QDir::Name, completer));
ui.targetLineEdit->setCompleter(completer);
// HotkeyWidget icons.
ui.screenHotkeyWidget->setIcon(os::icon("screen"));
ui.windowHotkeyWidget->setIcon(os::icon("window"));
ui.windowPickerHotkeyWidget->setIcon(os::icon("pickWindow"));
ui.areaHotkeyWidget->setIcon(os::icon("area"));
ui.openHotkeyWidget->setIcon(QIcon(":/icons/lightscreen.small"));
ui.directoryHotkeyWidget->setIcon(os::icon("folder"));
// Version
ui.versionLabel->setText(tr("Version %1").arg(qApp->applicationVersion()));
ui.uploadSslWarningLabel->setVisible(false);
// Run the SSL check in another thread (slows down dialog startup considerably).
auto futureWatcher = new QFutureWatcher<bool>(this);
connect(futureWatcher, &QFutureWatcher<bool>::finished, futureWatcher, &QFutureWatcher<bool>::deleteLater);
connect(futureWatcher, &QFutureWatcher<bool>::finished, this, [&, futureWatcher] {
ui.uploadSslWarningLabel->setVisible(!futureWatcher->future().result());
});
futureWatcher->setFuture(QtConcurrent::run([]() -> bool { return QSslSocket::supportsSsl(); }));
//
// Connections
//
connect(ui.buttonBox, &QDialogButtonBox::clicked , this, &OptionsDialog::dialogButtonClicked);
connect(ui.buttonBox, &QDialogButtonBox::accepted , this, &OptionsDialog::accepted);
connect(ui.namingOptionsButton, &QPushButton::clicked, this, &OptionsDialog::namingOptions);
connect(ui.prefixLineEdit, &QLineEdit::textEdited, this, &OptionsDialog::updatePreview);
connect(ui.formatComboBox, QOverload<int>::of(&QComboBox::currentIndexChanged), this, &OptionsDialog::updatePreview);
connect(ui.namingComboBox, QOverload<int>::of(&QComboBox::currentIndexChanged), this, &OptionsDialog::updatePreview);
connect(ui.browsePushButton , &QPushButton::clicked, this, &OptionsDialog::browse);
connect(ui.checkUpdatesPushButton , &QPushButton::clicked, this, &OptionsDialog::checkUpdatesNow);
connect(ui.historyPushButton , &QPushButton::clicked, this, &OptionsDialog::viewHistory);
connect(ui.windowPickerCheckBox, &QCheckBox::toggled, ui.windowPickerHotkeyWidget, &HotkeyWidget::setEnabled);
connect(ui.screenCheckBox , &QCheckBox::toggled, ui.screenHotkeyWidget , &HotkeyWidget::setEnabled);
connect(ui.areaCheckBox , &QCheckBox::toggled, ui.areaHotkeyWidget , &HotkeyWidget::setEnabled);
connect(ui.windowCheckBox , &QCheckBox::toggled, ui.windowHotkeyWidget , &HotkeyWidget::setEnabled);
connect(ui.openCheckBox , &QCheckBox::toggled, ui.openHotkeyWidget , &HotkeyWidget::setEnabled);
connect(ui.directoryCheckBox , &QCheckBox::toggled, ui.directoryHotkeyWidget, &HotkeyWidget::setEnabled);
// "Save as" disables the file target input field.
connect(ui.saveAsCheckBox, &QCheckBox::toggled, [&](bool checked) {
ui.targetLineEdit->setDisabled(checked);
ui.browsePushButton->setDisabled(checked);
ui.directoryLabel->setDisabled(checked);
});
connect(ui.qualitySlider, QOverload<int>::of(&QSlider::valueChanged), ui.qualityValueLabel, QOverload<int>::of(&QLabel::setNum));
connect(ui.startupCheckBox, &QCheckBox::toggled , ui.startupHideCheckBox, &QCheckBox::setEnabled);
connect(ui.trayCheckBox , &QCheckBox::toggled , ui.messageCheckBox , &QCheckBox::setEnabled);
// Auto-upload disables the default action button in the previews.
connect(ui.uploadCheckBox, &QCheckBox::toggled, [&](bool checked) {
ui.previewDefaultActionLabel->setDisabled(checked);
ui.previewDefaultActionComboBox->setDisabled(checked);
ui.directoryHotkeyWidget->setEnabled(checked);
});
auto conflictWarning = [](bool fullConflict, QWidget *w) {
if (fullConflict) {
QToolTip::showText(QCursor::pos(), tr("<font color=\"darkRed\">This setting conflicts with the Screenshot Clipboard setting, which has been disabled.</font>"), w);
} else {
QToolTip::showText(QCursor::pos(), tr("<b>This setting might conflict with the Screenshot Clipboard setting!</b>"), w);
}
};
connect(ui.uploadCheckBox, &QCheckBox::toggled, [&](bool checked) {
if (ui.urlClipboardCheckBox->isChecked() && ui.clipboardCheckBox->isChecked()) {
ui.clipboardGroupBox->setDisabled(checked);
if (checked) {
conflictWarning(true, ui.uploadCheckBox);
}
}
});
connect(ui.urlClipboardCheckBox, &QCheckBox::toggled, [&](bool checked) {
if (ui.uploadCheckBox->isChecked() && ui.clipboardCheckBox->isChecked()) {
ui.clipboardGroupBox->setDisabled(checked);
if (checked) {
conflictWarning(true, ui.urlClipboardCheckBox);
}
} else if (ui.clipboardCheckBox->isChecked()) {
conflictWarning(false, ui.urlClipboardCheckBox);
}
});
connect(ui.mainLabel , &QLabel::linkActivated, this, &OptionsDialog::openUrl);
connect(ui.licenseAboutLabel, &QLabel::linkActivated, this, &OptionsDialog::openUrl);
connect(ui.linksLabel, &QLabel::linkActivated, this, &OptionsDialog::openUrl);
connect(ui.uploadSslWarningLabel,&QLabel::linkActivated, this, &OptionsDialog::openUrl);
connect(ui.tabWidget, &QTabWidget::currentChanged, [&](int index) {
if (index == 2 && ui.uploadServiceStackWidget->currentIndex() == 0 && !ui.imgurOptions->mCurrentUser.isEmpty() && ui.imgurOptions->ui.albumComboBox->count() == 1) {
QTimer::singleShot(20, ui.imgurOptions, &ImgurOptionsWidget::requestAlbumList);
}
});
}
void OptionsDialog::namingOptions()
{
NamingDialog namingDialog((Screenshot::Naming) ui.namingComboBox->currentIndex());
namingDialog.exec();
flipToggled(settings()->value("options/flip").toBool());
updatePreview();
}
//
bool OptionsDialog::hotkeyCollision()
{
// Check for hotkey collision (there's probably a better way to do this...=)
if (ui.screenCheckBox->isChecked()) {
if (ui.screenHotkeyWidget->hotkey() == ui.areaHotkeyWidget->hotkey()
&& ui.areaCheckBox->isChecked()) {
return true;
}
if (ui.screenHotkeyWidget->hotkey() == ui.windowHotkeyWidget->hotkey()
&& ui.windowCheckBox->isChecked()) {
return true;
}
if (ui.screenHotkeyWidget->hotkey() == ui.windowPickerHotkeyWidget->hotkey()
&& ui.windowPickerCheckBox->isChecked()) {
return true;
}
if (ui.screenHotkeyWidget->hotkey() == ui.openHotkeyWidget->hotkey()
&& ui.openCheckBox->isChecked()) {
return true;
}
if (ui.screenHotkeyWidget->hotkey() == ui.directoryHotkeyWidget->hotkey()
&& ui.directoryCheckBox->isChecked()) {
return true;
}
}
if (ui.areaCheckBox->isChecked()) {
if (ui.areaHotkeyWidget->hotkey() == ui.screenHotkeyWidget->hotkey()
&& ui.screenCheckBox->isChecked()) {
return true;
}
if (ui.areaHotkeyWidget->hotkey() == ui.windowHotkeyWidget->hotkey()
&& ui.windowCheckBox->isChecked()) {
return true;
}
if (ui.areaHotkeyWidget->hotkey() == ui.windowPickerHotkeyWidget->hotkey()
&& ui.windowPickerCheckBox->isChecked()) {
return true;
}
if (ui.areaHotkeyWidget->hotkey() == ui.openHotkeyWidget->hotkey()
&& ui.openCheckBox->isChecked()) {
return true;
}
if (ui.areaHotkeyWidget->hotkey() == ui.directoryHotkeyWidget->hotkey()
&& ui.directoryCheckBox->isChecked()) {
return true;
}
}
if (ui.windowCheckBox->isChecked()) {
if (ui.windowHotkeyWidget->hotkey() == ui.screenHotkeyWidget->hotkey()
&& ui.screenCheckBox->isChecked()) {
return true;
}
if (ui.windowHotkeyWidget->hotkey() == ui.areaHotkeyWidget->hotkey()
&& ui.areaCheckBox->isChecked()) {
return true;
}
if (ui.windowHotkeyWidget->hotkey() == ui.windowPickerHotkeyWidget->hotkey()
&& ui.windowPickerCheckBox->isChecked()) {
return true;
}
if (ui.windowHotkeyWidget->hotkey() == ui.openHotkeyWidget->hotkey()
&& ui.openCheckBox->isChecked()) {
return true;
}
if (ui.windowHotkeyWidget->hotkey() == ui.directoryHotkeyWidget->hotkey()
&& ui.directoryCheckBox->isChecked()) {
return true;
}
}
if (ui.openCheckBox->isChecked()) {
if (ui.openHotkeyWidget->hotkey() == ui.screenHotkeyWidget->hotkey()
&& ui.screenCheckBox->isChecked()) {
return true;
}
if (ui.openHotkeyWidget->hotkey() == ui.areaHotkeyWidget->hotkey()
&& ui.areaCheckBox->isChecked()) {
return true;
}
if (ui.openHotkeyWidget->hotkey() == ui.windowPickerHotkeyWidget->hotkey()
&& ui.windowPickerCheckBox->isChecked()) {
return true;
}
if (ui.openHotkeyWidget->hotkey() == ui.windowHotkeyWidget->hotkey()
&& ui.windowCheckBox->isChecked()) {
return true;
}
if (ui.openHotkeyWidget->hotkey() == ui.directoryHotkeyWidget->hotkey()
&& ui.directoryCheckBox->isChecked()) {
return true;
}
}
if (ui.directoryCheckBox->isChecked()) {
if (ui.directoryHotkeyWidget->hotkey() == ui.screenHotkeyWidget->hotkey()
&& ui.screenCheckBox->isChecked()) {
return true;
}
if (ui.directoryHotkeyWidget->hotkey() == ui.areaHotkeyWidget->hotkey()
&& ui.areaCheckBox->isChecked()) {
return true;
}
if (ui.directoryHotkeyWidget->hotkey() == ui.windowPickerHotkeyWidget->hotkey()
&& ui.windowPickerCheckBox->isChecked()) {
return true;
}
if (ui.directoryHotkeyWidget->hotkey() == ui.windowHotkeyWidget->hotkey()
&& ui.windowCheckBox->isChecked()) {
return true;
}
if (ui.directoryHotkeyWidget->hotkey() == ui.openHotkeyWidget->hotkey()
&& ui.openCheckBox->isChecked()) {
return true;
}
}
return false;
}
QSettings *OptionsDialog::settings() const
{
return ScreenshotManager::instance()->settings();
}
diff --git a/tools/uploader/pomfuploader.cpp b/tools/uploader/pomfuploader.cpp
index 838d819..abd3b40 100644
--- a/tools/uploader/pomfuploader.cpp
+++ b/tools/uploader/pomfuploader.cpp
@@ -1,135 +1,140 @@
#include "pomfuploader.h"
#include "../uploader/uploader.h"
#include <QtNetwork>
#include <QJsonDocument>
#include <QJsonObject>
PomfUploader::PomfUploader(QObject *parent) : ImageUploader(parent)
{
mUploaderType = "pomf";
loadSettings();
}
-void PomfUploader::verify(const QString &url, VerificationCallback callback)
+QNetworkReply* PomfUploader::verify(const QString &url, VerificationCallback callback)
{
QNetworkRequest request(QUrl::fromUserInput(QString("%1/upload.php").arg(url)));
if (!request.url().isValid()) {
callback(false);
+ return 0;
}
QNetworkReply *reply = Uploader::network()->get(request);
connect(reply, &QNetworkReply::finished, [reply, callback] {
reply->deleteLater();
const QJsonObject pomfResponse = QJsonDocument::fromJson(reply->readAll()).object();
if (!pomfResponse.isEmpty() && pomfResponse.contains("success")) {
callback(true);
} else {
callback(false);
}
});
- connect(reply, &QNetworkReply::sslErrors, [reply](const QList<QSslError> &errors) {
+ connect(reply, &QNetworkReply::sslErrors, [reply, callback](const QList<QSslError> &errors) {
Q_UNUSED(errors);
if (QSysInfo::WindowsVersion == QSysInfo::WV_XP) {
reply->ignoreSslErrors();
+ } else {
+ callback(false);
}
});
+
+ return reply;
}
void PomfUploader::upload(const QString &fileName)
{
QString pomfUrl = mSettings["pomf_url"].toString();
if (pomfUrl.isEmpty()) {
emit error(ImageUploader::HostError, tr("Invalid pomf uploader URL!"), fileName);
return;
}
QUrl url = QUrl::fromUserInput(pomfUrl + "/upload.php");
QFile *file = new QFile(fileName);
if (!file->open(QIODevice::ReadOnly)) {
emit error(ImageUploader::FileError, tr("Unable to read screenshot file"), fileName);
file->deleteLater();
return;
}
QNetworkRequest request(url);
QHttpMultiPart *multiPart = new QHttpMultiPart(QHttpMultiPart::FormDataType);
QHttpPart imagePart;
imagePart.setHeader(QNetworkRequest::ContentTypeHeader, QMimeDatabase().mimeTypeForFile(fileName, QMimeDatabase::MatchExtension).name());
imagePart.setHeader(QNetworkRequest::ContentDispositionHeader, QString("form-data; name=\"files[]\"; filename=\"%1\"").arg(QFileInfo(fileName).fileName()));
imagePart.setBodyDevice(file);
file->setParent(multiPart);
multiPart->append(imagePart);
QNetworkReply *reply = Uploader::network()->post(request, multiPart);
this->setProperty("fileName", fileName);
multiPart->setParent(reply);
connect(this , &PomfUploader::cancelRequest, reply, &QNetworkReply::abort);
connect(this , &PomfUploader::cancelRequest, reply, &QNetworkReply::deleteLater);
connect(reply, &QNetworkReply::uploadProgress, this, [&](qint64 bytesSent, qint64 bytesTotal) {
float b = (float) bytesSent / bytesTotal;
int p = qRound(b * 100);
setProgress(p);
});
connect(reply, &QNetworkReply::finished, this, [&, reply, fileName] {
const QJsonObject pomfResponse = QJsonDocument::fromJson(reply->readAll()).object();
if (reply->error() != QNetworkReply::NoError && pomfResponse.isEmpty()) {
emit error(ImageUploader::NetworkError, tr("Error reaching uploader"), fileName);
return;
}
if (!pomfResponse.contains("success") || !pomfResponse.contains("files")) {
emit error(ImageUploader::HostError, tr("Invalid response from uploader"), fileName);
return;
}
if (pomfResponse["success"].toBool()) {
emit uploaded(fileName, pomfResponse["files"].toArray().at(0).toObject()["url"].toString(), "");
} else {
QString description;
if (pomfResponse.contains("description")) {
description = pomfResponse["description"].toString();
}
if (description.isEmpty()) {
description = tr("Host error");
}
emit error(ImageUploader::HostError, description, fileName);
}
});
connect(reply, &QNetworkReply::sslErrors, [reply](const QList<QSslError> &errors) {
Q_UNUSED(errors);
if (QSysInfo::WindowsVersion == QSysInfo::WV_XP) {
reply->ignoreSslErrors();
}
});
}
void PomfUploader::retry()
{
upload(property("fileName").toString());
}
void PomfUploader::cancel()
{
emit cancelRequest();
}
diff --git a/tools/uploader/pomfuploader.h b/tools/uploader/pomfuploader.h
index 5b746e1..8563a19 100644
--- a/tools/uploader/pomfuploader.h
+++ b/tools/uploader/pomfuploader.h
@@ -1,27 +1,27 @@
#ifndef POMFUPLOADER_H
#define POMFUPLOADER_H
#include "imageuploader.h"
#include <functional>
class PomfUploader : public ImageUploader
{
Q_OBJECT
public:
PomfUploader(QObject *parent = 0);
typedef std::function<void(bool)> VerificationCallback;
- static void verify(const QString &url, VerificationCallback callback);
+ static QNetworkReply* verify(const QString &url, VerificationCallback callback);
public slots:
void upload(const QString &fileName);
void retry();
void cancel();
signals:
void cancelRequest();
};
#endif // POMFUPLOADER_H
diff --git a/widgets/pomfoptionswidget.cpp b/widgets/pomfoptionswidget.cpp
index 8c0cb0a..fb1a969 100644
--- a/widgets/pomfoptionswidget.cpp
+++ b/widgets/pomfoptionswidget.cpp
@@ -1,114 +1,142 @@
#include <QJsonObject>
#include <QInputDialog>
#include <QNetworkReply>
#include <QDesktopServices>
#include <QMessageBox>
#include <QRegExpValidator>
#include "pomfoptionswidget.h"
#include "../uploader/uploader.h"
#include "../uploader/pomfuploader.h"
#include "../screenshotmanager.h"
#include "../os.h"
PomfOptionsWidget::PomfOptionsWidget(QWidget *parent) : QWidget(parent)
{
ui.setupUi(this);
ui.progressIndicatorBar->setVisible(false);
+ ui.cancelButton->setVisible(false);
connect(ui.verifyButton, &QPushButton::clicked, this, [&]() {
ui.verifyButton->setEnabled(false);
ui.downloadListButton->setEnabled(false);
ui.progressIndicatorBar->setVisible(true);
+ ui.cancelButton->setVisible(true);
+ disconnect(ui.cancelButton);
+ ui.cancelButton->disconnect();
QPointer<QWidget> guard(parentWidget());
- PomfUploader::verify(ui.pomfUrlComboBox->currentText(), [&, guard](bool result) {
+ QPointer<QNetworkReply> reply = PomfUploader::verify(ui.pomfUrlComboBox->currentText(), [&, guard](bool result) {
if (guard.isNull()) return;
ui.verifyButton->setEnabled(true);
ui.downloadListButton->setEnabled(true);
ui.progressIndicatorBar->setVisible(false);
if (result) {
ui.verifyButton->setText(tr("Valid uploader!"));
ui.verifyButton->setStyleSheet("color: green;");
ui.verifyButton->setIcon(os::icon("yes"));
- } else {
+ } else if (ui.cancelButton->isVisible() == true) { // Not cancelled
ui.verifyButton->setStyleSheet("color: red;");
ui.verifyButton->setIcon(os::icon("no"));
ui.verifyButton->setText(tr("Invalid uploader :("));
}
+
+ ui.cancelButton->setVisible(false);
});
+
+ if (reply) {
+ connect(ui.cancelButton, &QPushButton::clicked, [&, reply] {
+ if (reply) {
+ ui.cancelButton->setVisible(false);
+ reply->abort();
+ }
+ });
+ }
});
connect(ui.pomfUrlComboBox, &QComboBox::currentTextChanged, [&](const QString &text) {
bool validUrl = false;
if (!text.isEmpty() && (text.startsWith("http://") || text.startsWith("https://"))) { // TODO: Something a bit more complex
validUrl = true;
}
ui.verifyButton->setEnabled(validUrl);
if (ui.verifyButton->styleSheet().count() > 0) {
ui.verifyButton->setStyleSheet("");
ui.verifyButton->setIcon(QIcon());
ui.verifyButton->setText(tr("Verify"));
}
});
connect(ui.helpLabel, &QLabel::linkActivated, this, [&](const QString &url) {
QDesktopServices::openUrl(url);
});
connect(ui.downloadListButton, &QPushButton::clicked, this, [&]() {
ui.verifyButton->setEnabled(false);
ui.downloadListButton->setEnabled(false);
ui.progressIndicatorBar->setVisible(true);
+ ui.cancelButton->setVisible(true);
+ disconnect(ui.cancelButton);
+ ui.cancelButton->disconnect();
QUrl pomfRepoURL = QUrl(ScreenshotManager::instance()->settings()->value("options/upload/pomfRepo").toString());
if (pomfRepoURL.isEmpty()) {
pomfRepoURL = QUrl("https://lightscreen.com.ar/pomf.json");
}
- auto pomflistReply = Uploader::network()->get(QNetworkRequest(pomfRepoURL));
+ auto pomflistReply = QPointer<QNetworkReply>(Uploader::network()->get(QNetworkRequest(pomfRepoURL)));
QPointer<QWidget> guard(parentWidget());
connect(pomflistReply, &QNetworkReply::finished, [&, guard, pomflistReply] {
if (guard.isNull()) return;
+ if (pomflistReply.isNull()) return;
ui.verifyButton->setEnabled(true);
ui.downloadListButton->setEnabled(true);
ui.progressIndicatorBar->setVisible(false);
+ ui.cancelButton->setVisible(false);
if (pomflistReply->error() != QNetworkReply::NoError) {
QMessageBox::warning(parentWidget(), tr("Connection error"), pomflistReply->errorString());
return;
}
auto pomfListData = QJsonDocument::fromJson(pomflistReply->readAll()).object();
if (pomfListData.contains("url")) {
auto urlList = pomfListData["url"].toArray();
for (auto url : qAsConst(urlList)) {
if (ui.pomfUrlComboBox->findText(url.toString(), Qt::MatchExactly) < 0) {
ui.pomfUrlComboBox->addItem(url.toString());
}
}
ui.pomfUrlComboBox->showPopup();
}
});
connect(pomflistReply, &QNetworkReply::sslErrors, [pomflistReply](const QList<QSslError> &errors) {
Q_UNUSED(errors);
- if (QSysInfo::WindowsVersion == QSysInfo::WV_XP) {
+ if (!pomflistReply.isNull() && QSysInfo::WindowsVersion == QSysInfo::WV_XP) {
pomflistReply->ignoreSslErrors();
}
});
+
+ connect(ui.cancelButton, &QPushButton::clicked, [&, guard, pomflistReply] {
+ if (guard.isNull()) return;
+ if (pomflistReply.isNull()) return;
+
+ pomflistReply->abort();
+ });
+
});
}
diff --git a/widgets/pomfoptionswidget.ui b/widgets/pomfoptionswidget.ui
index ccc471a..4583d0f 100644
--- a/widgets/pomfoptionswidget.ui
+++ b/widgets/pomfoptionswidget.ui
@@ -1,102 +1,115 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>PomfOptions</class>
<widget class="QWidget" name="PomfOptions">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>297</width>
- <height>84</height>
+ <height>106</height>
</rect>
</property>
<property name="windowTitle">
<string>Form</string>
</property>
<layout class="QGridLayout" name="gridLayout">
- <item row="0" column="0" colspan="2">
+ <item row="0" column="0">
<widget class="QComboBox" name="pomfUrlComboBox">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="toolTip">
<string>URL to a pomf.se clone</string>
</property>
<property name="editable">
<bool>true</bool>
</property>
</widget>
</item>
- <item row="4" column="0" colspan="2">
- <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 row="0" column="2">
+ <item row="0" column="1" colspan="2">
<widget class="QPushButton" name="verifyButton">
<property name="enabled">
<bool>false</bool>
</property>
<property name="text">
<string>Verify</string>
</property>
</widget>
</item>
- <item row="1" column="2">
+ <item row="1" column="0">
+ <widget class="QPushButton" name="downloadListButton">
+ <property name="text">
+ <string>Download List</string>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="1">
<widget class="QLabel" name="helpLabel">
<property name="sizePolicy">
<sizepolicy hsizetype="Minimum" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>&lt;a href=&quot;https://lightscreen.com.ar/help#pomf&quot;&gt;View Help&lt;/a&gt;</string>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
</widget>
</item>
- <item row="1" column="0" colspan="2">
- <widget class="QPushButton" name="downloadListButton">
+ <item row="3" column="0">
+ <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 row="2" column="2">
+ <widget class="QPushButton" name="cancelButton">
<property name="text">
- <string>Download List</string>
+ <string/>
+ </property>
+ <property name="icon">
+ <iconset resource="../lightscreen.qrc">
+ <normaloff>:/icons/no</normaloff>:/icons/no</iconset>
</property>
</widget>
</item>
- <item row="2" column="0" colspan="3">
+ <item row="2" column="0" colspan="2">
<widget class="QProgressBar" name="progressIndicatorBar">
<property name="maximumSize">
<size>
<width>16777215</width>
<height>2</height>
</size>
</property>
<property name="maximum">
<number>0</number>
</property>
<property name="value">
<number>0</number>
</property>
<property name="textVisible">
<bool>false</bool>
</property>
</widget>
</item>
</layout>
</widget>
- <resources/>
+ <resources>
+ <include location="../lightscreen.qrc"/>
+ </resources>
<connections/>
</ui>

File Metadata

Mime Type
text/x-diff
Expires
Fri, Sep 12, 10:53 PM (1 d, 14 h)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
42964
Default Alt Text
(72 KB)

Event Timeline