Page MenuHomePhabricator (Chris)

No OneTemporary

Authored By
Unknown
Size
198 KB
Referenced Files
None
Subscribers
None
diff --git a/dialogs/historydialog.cpp b/dialogs/historydialog.cpp
index a438b59..3b3685e 100644
--- a/dialogs/historydialog.cpp
+++ b/dialogs/historydialog.cpp
@@ -1,271 +1,283 @@
#include "historydialog.h"
#include "ui_historydialog.h"
#include "../tools/os.h"
#include "../tools/uploader/uploader.h"
#include "../tools/screenshotmanager.h"
#include <QClipboard>
#include <QDesktopServices>
#include <QDir>
#include <QFile>
#include <QFileInfo>
#include <QFileSystemWatcher>
#include <QMenu>
#include <QMessageBox>
#include <QSettings>
#include <QSortFilterProxyModel>
#include <QtSql/QSqlDatabase>
#include <QtSql/QSqlTableModel>
#include <QUrl>
HistoryDialog::HistoryDialog(QWidget *parent) :
QDialog(parent),
ui(new Ui::HistoryDialog),
mModel(Q_NULLPTR),
mFilterModel(Q_NULLPTR)
{
ui->setupUi(this);
ui->filterEdit->setText(tr("Filter.."));
ui->filterEdit->installEventFilter(this);
- if (QSqlDatabase::database().isOpen()) {
- mModel = new QSqlTableModel(this);
- mModel->setTable("history");
- mModel->setHeaderData(0, Qt::Horizontal, tr("Screenshot"));
- mModel->setHeaderData(1, Qt::Horizontal, tr("URL"));
- mModel->select();
-
- mFilterModel = new QSortFilterProxyModel(mModel);
- mFilterModel->setSourceModel(mModel);
- mFilterModel->setDynamicSortFilter(true);
- mFilterModel->setSortCaseSensitivity(Qt::CaseInsensitive);
- mFilterModel->setFilterCaseSensitivity(Qt::CaseInsensitive);
- mFilterModel->setFilterKeyColumn(-1);
-
- while (mModel->canFetchMore()) {
- mModel->fetchMore();
- }
-
- ui->tableView->setWordWrap(false);
- ui->tableView->setModel(mFilterModel);
-
- ui->tableView->hideColumn(2); // No delete hash.
- ui->tableView->hideColumn(3); // No timestamp.
-
- ui->tableView->horizontalHeader()->setSectionsClickable(false);
- ui->tableView->horizontalHeader()->setSectionsMovable(false);
-
- ui->tableView->horizontalHeader()->setSectionResizeMode(0, QHeaderView::Stretch);
- ui->tableView->horizontalHeader()->setSectionResizeMode(1, QHeaderView::ResizeToContents);
-
- ui->tableView->verticalHeader()->hide();
-
- ui->tableView->setTextElideMode(Qt::ElideLeft);
- ui->tableView->setEditTriggers(QAbstractItemView::NoEditTriggers);
- ui->tableView->setAlternatingRowColors(true);
- ui->tableView->setSelectionMode(QAbstractItemView::SingleSelection);
- ui->tableView->setContextMenuPolicy(Qt::CustomContextMenu);
- ui->tableView->setSortingEnabled(true);
-
- if (ui->tableView->model()->rowCount() > 0) {
- ui->clearButton->setEnabled(true);
- ui->filterEdit->setEnabled(true);
- }
-
- connect(ui->tableView->selectionModel(), SIGNAL(selectionChanged(QItemSelection, QItemSelection)), this, SLOT(selectionChanged(QItemSelection, QItemSelection)));
- connect(ui->tableView, SIGNAL(doubleClicked(QModelIndex)), this, SLOT(open(QModelIndex)));
- connect(ui->tableView, SIGNAL(customContextMenuRequested(QPoint)), this, SLOT(contextMenu(QPoint)));
- } else {
- ui->tableView->setEnabled(false);
- ui->clearButton->setEnabled(false);
- }
-
- if (Uploader::instance()->progress() > 0) {
- ui->uploadProgressBar->setValue(Uploader::instance()->progress());
- } else {
- ui->uploadProgressWidget->setVisible(false);
- }
-
ui->cancelUploadButton->setIcon(os::icon("no"));
+ ui->tableView->setEnabled(false);
+ ui->clearButton->setEnabled(false);
connect(Uploader::instance(), SIGNAL(progress(int)), this, SLOT(uploadProgress(int)));
connect(Uploader::instance(), SIGNAL(done(QString, QString, QString)), this, SLOT(refresh()));
connect(ui->uploadButton , SIGNAL(clicked()), this , SLOT(upload()));
connect(ui->cancelUploadButton, SIGNAL(clicked()), Uploader::instance() , SLOT(cancel()));
connect(ui->cancelUploadButton, SIGNAL(clicked()), ui->uploadProgressWidget, SLOT(hide()));
connect(ui->clearButton , SIGNAL(clicked()), this , SLOT(clear()));
+
+ QTimer::singleShot(0, this, &HistoryDialog::init);
}
HistoryDialog::~HistoryDialog()
{
delete ui;
}
void HistoryDialog::clear()
{
if (QMessageBox::question(this,
tr("Clearing the screenshot history"),
tr("Are you sure you want to clear your entire screenshot history?\nThis cannot be undone."),
tr("Clear History"),
tr("Don't Clear")) == 1) {
return;
}
ScreenshotManager::instance()->clearHistory();
- close();
+ mModel->select();
+ ui->filterEdit->setEnabled(false);
+ ui->tableView->setEnabled(false);
+ ui->clearButton->setEnabled(false);
}
void HistoryDialog::contextMenu(const QPoint &point)
{
mContextIndex = ui->tableView->indexAt(point);;
QMenu contextMenu(ui->tableView);
QAction copyAction((mContextIndex.column() == 0) ? tr("Copy Path") : tr("Copy URL"), &contextMenu);
connect(&copyAction, SIGNAL(triggered()), this, SLOT(copy()));
contextMenu.addAction(&copyAction);
QAction deleteAction(tr("Delete from imgur.com"), &contextMenu);
QAction locationAction(tr("Open Location"), &contextMenu);
QAction removeAction(tr("Remove history entry"), &contextMenu);
if (mContextIndex.data().toString().isEmpty()) {
copyAction.setEnabled(false);
deleteAction.setEnabled(false);
}
if (mContextIndex.column() == 0) {
connect(&locationAction, SIGNAL(triggered()), this, SLOT(location()));
contextMenu.addAction(&locationAction);
} else {
connect(&deleteAction, SIGNAL(triggered()), this, SLOT(deleteImage()));
contextMenu.addAction(&deleteAction);
}
connect(&removeAction, SIGNAL(triggered()), this, SLOT(removeHistoryEntry()));
contextMenu.addAction(&removeAction);
contextMenu.exec(QCursor::pos());
}
void HistoryDialog::copy()
{
qApp->clipboard()->setText(mContextIndex.data().toString());
}
void HistoryDialog::deleteImage()
{
QDesktopServices::openUrl(mContextIndex.sibling(mContextIndex.row(), 2).data().toString());
}
void HistoryDialog::location()
{
QDesktopServices::openUrl("file:///" + QFileInfo(mContextIndex.data().toString()).absolutePath());
}
void HistoryDialog::removeHistoryEntry()
{
if (mContextIndex.column() == 0) {
// File got right clicked:
ScreenshotManager::instance()->removeHistory(mContextIndex.data().toString(), mContextIndex.sibling(mContextIndex.row(), 3).data().toLongLong());
} else {
// Screenshot URL got right clicked:
ScreenshotManager::instance()->removeHistory(mContextIndex.sibling(mContextIndex.row(), 0).data().toString(), mContextIndex.sibling(mContextIndex.row(), 3).data().toLongLong());
}
refresh();
}
void HistoryDialog::refresh()
{
mModel->select();
}
-void HistoryDialog::open(const QModelIndex &index)
+void HistoryDialog::openUrl(const QModelIndex &index)
{
if (index.column() == 0) {
QDesktopServices::openUrl(QUrl("file:///" + index.data().toString()));
} else {
QDesktopServices::openUrl(index.data().toUrl());
}
}
void HistoryDialog::selectionChanged(const QItemSelection &selected, const QItemSelection &deselected)
{
Q_UNUSED(deselected);
if (selected.indexes().count() == 0) {
return;
}
QModelIndex index = selected.indexes().at(0);
QString screenshot;
if (index.column() == 0) {
screenshot = index.data().toString();
} else {
screenshot = ui->tableView->model()->index(index.row(), 0).data().toString();
}
mSelectedScreenshot = screenshot;
ui->uploadButton->setEnabled(QFile::exists(screenshot));
}
void HistoryDialog::upload()
{
Uploader::instance()->upload(mSelectedScreenshot);
ui->uploadProgressWidget->setVisible(true);
}
void HistoryDialog::uploadProgress(int progress)
{
ui->uploadProgressWidget->setVisible(true);
ui->uploadProgressBar->setValue(progress);
}
+void HistoryDialog::init()
+{
+ ScreenshotManager::instance()->initHistory();
+
+ if (QSqlDatabase::database().isOpen()) {
+ mModel = new QSqlTableModel(this);
+ mModel->setTable("history");
+ mModel->setHeaderData(0, Qt::Horizontal, tr("Screenshot"));
+ mModel->setHeaderData(1, Qt::Horizontal, tr("URL"));
+ mModel->select();
+
+ mFilterModel = new QSortFilterProxyModel(mModel);
+ mFilterModel->setSourceModel(mModel);
+ mFilterModel->setDynamicSortFilter(true);
+ mFilterModel->setSortCaseSensitivity(Qt::CaseInsensitive);
+ mFilterModel->setFilterCaseSensitivity(Qt::CaseInsensitive);
+ mFilterModel->setFilterKeyColumn(-1);
+
+ while (mModel->canFetchMore()) {
+ mModel->fetchMore();
+ }
+
+ ui->tableView->setWordWrap(false);
+ ui->tableView->setModel(mFilterModel);
+
+ ui->tableView->hideColumn(2); // No delete hash.
+ ui->tableView->hideColumn(3); // No timestamp.
+
+ ui->tableView->horizontalHeader()->setSectionsClickable(false);
+ ui->tableView->horizontalHeader()->setSectionsMovable(false);
+
+ ui->tableView->horizontalHeader()->setSectionResizeMode(0, QHeaderView::Stretch);
+ ui->tableView->horizontalHeader()->setSectionResizeMode(1, QHeaderView::ResizeToContents);
+
+ ui->tableView->verticalHeader()->hide();
+
+ ui->tableView->setTextElideMode(Qt::ElideLeft);
+ ui->tableView->setEditTriggers(QAbstractItemView::NoEditTriggers);
+ ui->tableView->setAlternatingRowColors(true);
+ ui->tableView->setSelectionMode(QAbstractItemView::SingleSelection);
+ ui->tableView->setContextMenuPolicy(Qt::CustomContextMenu);
+ ui->tableView->setSortingEnabled(true);
+
+ if (ui->tableView->model()->rowCount() > 0) {
+ ui->tableView->setEnabled(true);
+ ui->clearButton->setEnabled(true);
+ ui->filterEdit->setEnabled(true);
+ }
+
+ connect(ui->tableView->selectionModel(), SIGNAL(selectionChanged(QItemSelection, QItemSelection)), this, SLOT(selectionChanged(QItemSelection, QItemSelection)));
+ connect(ui->tableView, SIGNAL(doubleClicked(QModelIndex)), this, SLOT(openUrl(QModelIndex)));
+ connect(ui->tableView, SIGNAL(customContextMenuRequested(QPoint)), this, SLOT(contextMenu(QPoint)));
+ }
+
+ if (Uploader::instance()->progress() > 0) {
+ ui->uploadProgressBar->setValue(Uploader::instance()->progress());
+ } else {
+ ui->uploadProgressWidget->setVisible(false);
+ }
+
+ ui->closeButton->setFocus();
+}
+
bool HistoryDialog::eventFilter(QObject *object, QEvent *event)
{
if (object == ui->filterEdit && mFilterModel) {
if (event->type() == QEvent::FocusIn) {
if (ui->filterEdit->text() == tr("Filter..")) {
ui->filterEdit->setStyleSheet("");
ui->filterEdit->setText("");
mFilterModel->setFilterWildcard("");
mFilterModel->sort(3, Qt::DescendingOrder);
}
} else if (event->type() == QEvent::FocusOut) {
if (ui->filterEdit->text().isEmpty()) {
ui->filterEdit->setStyleSheet("color: palette(mid);");
ui->filterEdit->setText(tr("Filter.."));
mFilterModel->sort(3, Qt::DescendingOrder);
}
} else if (event->type() == QEvent::KeyRelease) {
if (ui->filterEdit->text() != tr("Filter..") && !ui->filterEdit->text().isEmpty()) {
mFilterModel->setFilterWildcard(ui->filterEdit->text());
mFilterModel->sort(3, Qt::DescendingOrder);
} else {
mFilterModel->setFilterWildcard("");
mFilterModel->sort(3, Qt::DescendingOrder);
}
}
}
return QDialog::eventFilter(object, event);
}
bool HistoryDialog::event(QEvent *event)
{
if (event->type() == QEvent::Show) {
restoreGeometry(ScreenshotManager::instance()->settings()->value("geometry/historyDialog").toByteArray());
} else if (event->type() == QEvent::Close) {
ScreenshotManager::instance()->settings()->setValue("geometry/historyDialog", saveGeometry());
}
return QDialog::event(event);
}
diff --git a/dialogs/historydialog.h b/dialogs/historydialog.h
index 01ffe19..c6fd5f0 100644
--- a/dialogs/historydialog.h
+++ b/dialogs/historydialog.h
@@ -1,46 +1,47 @@
#ifndef UPLOADDIALOG_H
#define UPLOADDIALOG_H
#include <QDialog>
#include <QItemSelection>
namespace Ui {
class HistoryDialog;
}
class QSqlTableModel;
class QSortFilterProxyModel;
class HistoryDialog : public QDialog
{
Q_OBJECT
public:
explicit HistoryDialog(QWidget *parent = 0);
~HistoryDialog();
private slots:
void clear();
void contextMenu(const QPoint &point);
void copy();
void deleteImage();
void location();
void removeHistoryEntry();
void refresh();
- void open(const QModelIndex &index);
+ void openUrl(const QModelIndex &index);
void selectionChanged(const QItemSelection &selected, const QItemSelection &deselected);
void upload();
void uploadProgress(int progress);
+ void init();
protected:
bool eventFilter(QObject *object, QEvent *event);
bool event(QEvent *event);
private:
Ui::HistoryDialog *ui;
QSqlTableModel *mModel;
QSortFilterProxyModel *mFilterModel;
QString mSelectedScreenshot;
QModelIndex mContextIndex;
};
#endif // UPLOADDIALOG_H
diff --git a/dialogs/optionsdialog.cpp b/dialogs/optionsdialog.cpp
index 6b43934..5e33b66 100644
--- a/dialogs/optionsdialog.cpp
+++ b/dialogs/optionsdialog.cpp
@@ -1,926 +1,926 @@
/*
* Copyright (C) 2016 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 <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>
#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
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);
- foreach (const QString &key, settings()->allKeys()) {
+ for (auto key : settings()->allKeys()) {
exportedSettings.setValue(key, settings()->value(key));
}
}
void OptionsDialog::imgurAuthorize()
{
// TODO: Tuck this into Uploader
if (ui.imgurAuthButton->text() == tr("Deauthorize")) {
ui.imgurAuthUserLabel->setText(tr("<i>none</i>"));
ui.imgurAuthButton->setText(tr("Authorize"));
ui.imgurRefreshAlbumButton->setEnabled(false);
ui.imgurAlbumComboBox->setEnabled(false);
ui.imgurAlbumComboBox->clear();
ui.imgurAlbumComboBox->addItem(tr("- None -"));
settings()->setValue("upload/imgur/access_token", "");
settings()->setValue("upload/imgur/refresh_token", "");
settings()->setValue("upload/imgur/account_username", "");
settings()->setValue("upload/imgur/expires_in", 0);
return;
}
openUrl("https://api.imgur.com/oauth2/authorize?client_id=3ebe94c791445c1&response_type=pin"); //TODO: get the client-id from somewhere?
bool ok;
QString pin = QInputDialog::getText(this, tr("Imgur Authorization"),
tr("PIN:"), QLineEdit::Normal,
"", &ok);
if (ok) {
QByteArray parameters;
parameters.append(QString("client_id=").toUtf8());
parameters.append(QUrl::toPercentEncoding("3ebe94c791445c1"));
parameters.append(QString("&client_secret=").toUtf8());
parameters.append(QUrl::toPercentEncoding("0546b05d6a80b2092dcea86c57b792c9c9faebf0")); // TODO: TA.png
parameters.append(QString("&grant_type=pin").toUtf8());
parameters.append(QString("&pin=").toUtf8());
parameters.append(QUrl::toPercentEncoding(pin));
QNetworkRequest request(QUrl("https://api.imgur.com/oauth2/token"));
request.setHeader(QNetworkRequest::ContentTypeHeader, "application/x-www-form-urlencoded");
QNetworkReply *reply = Uploader::instance()->nam()->post(request, parameters);
connect(reply, SIGNAL(finished()), this, SLOT(imgurToken()));
ui.imgurAuthButton->setText(tr("Authorizing.."));
ui.imgurAuthButton->setEnabled(false);
}
}
void OptionsDialog::imgurToken()
{
QNetworkReply *reply = qobject_cast<QNetworkReply *>(sender());
ui.imgurAuthButton->setEnabled(true);
if (reply->error() != QNetworkReply::NoError) {
QMessageBox::critical(this, tr("Imgur Authorization Error"), tr("There's been an error authorizing your account with Imgur, please try again."));
ui.imgurAuthButton->setText(tr("Authorize"));
return;
}
QJsonObject imgurResponse = QJsonDocument::fromJson(reply->readAll()).object();
settings()->setValue("upload/imgur/access_token" , imgurResponse.value("access_token").toString());
settings()->setValue("upload/imgur/refresh_token" , imgurResponse.value("refresh_token").toString());
settings()->setValue("upload/imgur/account_username", imgurResponse.value("account_username").toString());
settings()->setValue("upload/imgur/expires_in" , imgurResponse.value("expires_in").toInt());
settings()->sync();
ui.imgurAuthUserLabel->setText("<b>" + imgurResponse.value("account_username").toString() + "</b>");
ui.imgurAuthButton->setText(tr("Deauthorize"));
QTimer::singleShot(0, this, &OptionsDialog::imgurRequestAlbumList);
}
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();
- foreach (const QString &key, importedSettings.allKeys()) {
+ for (auto key : importedSettings.allKeys()) {
if (settings()->contains(key)) {
settings()->setValue(key, importedSettings.value(key));
}
}
loadSettings();
}
void OptionsDialog::imgurRequestAlbumList()
{
QString username = settings()->value("upload/imgur/account_username").toString();
if (username.isEmpty()) {
return;
}
ui.imgurRefreshAlbumButton->setEnabled(true);
ui.imgurAlbumComboBox->clear();
ui.imgurAlbumComboBox->setEnabled(false);
ui.imgurAlbumComboBox->addItem(tr("Loading album data..."));
QNetworkRequest request(QUrl("https://api.imgur.com/3/account/" + username + "/albums/"));
request.setRawHeader("Authorization", QByteArray("Bearer ") + settings()->value("upload/imgur/access_token").toByteArray());
QNetworkReply *reply = Uploader::instance()->nam()->get(request);
connect(reply, SIGNAL(finished()), this, SLOT(imgurAlbumList()));
}
void OptionsDialog::imgurAlbumList()
{
QNetworkReply *reply = qobject_cast<QNetworkReply *>(sender());
if (reply->error() != QNetworkReply::NoError) {
if (reply->error() == QNetworkReply::ContentOperationNotPermittedError ||
reply->error() == QNetworkReply::AuthenticationRequiredError) {
Uploader::instance()->imgurAuthRefresh();
}
ui.imgurAlbumComboBox->addItem(tr("Loading failed :("));
return;
}
QJsonObject imgurResponse = QJsonDocument::fromJson(reply->readAll()).object();
if (imgurResponse["success"].toBool() != true || imgurResponse["status"].toInt() != 200) {
return;
}
- QJsonArray albumList = imgurResponse["data"].toArray();
+ const QJsonArray albumList = imgurResponse["data"].toArray();
ui.imgurAlbumComboBox->clear();
ui.imgurAlbumComboBox->setEnabled(true);
ui.imgurAlbumComboBox->addItem(tr("- None -"), "");
ui.imgurRefreshAlbumButton->setEnabled(true);
int settingsIndex = 0;
- foreach (const QJsonValue &albumValue, albumList) {
+ for (auto albumValue : albumList) {
QJsonObject album = albumValue.toObject();
ui.imgurAlbumComboBox->addItem(album["title"].toString(), album["id"].toString());
if (album["id"].toString() == settings()->value("upload/imgur/album").toString()) {
settingsIndex = ui.imgurAlbumComboBox->count() - 1;
}
}
ui.imgurAlbumComboBox->setCurrentIndex(settingsIndex);
}
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.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.imgurClipboardCheckBox->setChecked(settings()->value("imgurClipboard", false).toBool());
ui.optiPngCheckBox->setChecked(settings()->value("optipng", true).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.serviceComboBox->setCurrentIndex(settings()->value("service").toInt());
settings()->beginGroup("imgur");
ui.imgurAuthGroupBox->setChecked(!settings()->value("anonymous", true).toBool());
ui.imgurAuthUserLabel->setText(settings()->value("account_username", tr("<i>none</i>")).toString());
if (settings()->value("account_username").toString().isEmpty()) {
ui.imgurAuthUserLabel->setText(tr("<i>none</i>"));
ui.imgurAlbumComboBox->setEnabled(false);
ui.imgurRefreshAlbumButton->setEnabled(false);
} else {
ui.imgurAuthButton->setText(tr("Deauthorize"));
ui.imgurAuthUserLabel->setText("<b>" + ui.imgurAuthUserLabel->text() + "</b>");
ui.imgurRefreshAlbumButton->setEnabled(true);
}
settings()->endGroup();
settings()->endGroup();
QMetaObject::invokeMethod(this, "updatePreview", Qt::QueuedConnection);
QMetaObject::invokeMethod(this, "imgurRequestAlbumList", Qt::QueuedConnection);
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("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("imgurClipboard", ui.imgurClipboardCheckBox->isChecked());
settings()->setValue("optipng", 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.serviceComboBox->currentIndex());
settings()->beginGroup("imgur");
settings()->setValue("anonymous", !ui.imgurAuthGroupBox->isChecked());
settings()->setValue("album" , ui.imgurAlbumComboBox->property("currentData").toString());
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);
}
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 && settings()->contains("geometry/optionsDialog")) {
restoreGeometry(settings()->value("geometry/optionsDialog").toByteArray());
}
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.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, SIGNAL(triggered()), this, SLOT(exportSettings()));
QAction *importAction = new QAction(tr("&Import.."), optionsMenu);
connect(importAction, SIGNAL(triggered()), this, SLOT(importSettings()));
QAction *restoreAction = new QAction(tr("&Restore Defaults"), optionsMenu);
connect(restoreAction, SIGNAL(triggered()), this, SLOT(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()));
setEnabled(false); // We disable the widgets to prevent any user interaction until the settings have loaded.
//
// Connections
//
connect(Uploader::instance(), &Uploader::imgurAuthRefreshed, this, &OptionsDialog::imgurRequestAlbumList);
connect(ui.buttonBox , SIGNAL(clicked(QAbstractButton *)), this , SLOT(dialogButtonClicked(QAbstractButton *)));
connect(ui.buttonBox , SIGNAL(accepted()) , this , SLOT(accepted()));
connect(ui.namingOptionsButton , SIGNAL(clicked()) , this , SLOT(namingOptions()));
connect(ui.prefixLineEdit , SIGNAL(textEdited(QString)) , this , SLOT(updatePreview()));
connect(ui.formatComboBox , SIGNAL(currentIndexChanged(int)) , this , SLOT(updatePreview()));
connect(ui.namingComboBox , SIGNAL(currentIndexChanged(int)) , this , SLOT(updatePreview()));
connect(ui.browsePushButton , SIGNAL(clicked()) , this , SLOT(browse()));
connect(ui.checkUpdatesPushButton , SIGNAL(clicked()) , this , SLOT(checkUpdatesNow()));
connect(ui.historyPushButton , SIGNAL(clicked()) , this , SLOT(viewHistory()));
connect(ui.imgurAuthButton , SIGNAL(clicked()) , this , SLOT(imgurAuthorize()));
connect(ui.imgurRefreshAlbumButton, SIGNAL(clicked()) , this , SLOT(imgurRequestAlbumList()));
connect(ui.screenCheckBox , SIGNAL(toggled(bool)), ui.screenHotkeyWidget , SLOT(setEnabled(bool)));
connect(ui.areaCheckBox , SIGNAL(toggled(bool)), ui.areaHotkeyWidget , SLOT(setEnabled(bool)));
connect(ui.windowCheckBox , SIGNAL(toggled(bool)), ui.windowHotkeyWidget , SLOT(setEnabled(bool)));
connect(ui.windowPickerCheckBox, SIGNAL(toggled(bool)), ui.windowPickerHotkeyWidget, SLOT(setEnabled(bool)));
connect(ui.openCheckBox , SIGNAL(toggled(bool)), ui.openHotkeyWidget , SLOT(setEnabled(bool)));
connect(ui.directoryCheckBox , SIGNAL(toggled(bool)), ui.directoryHotkeyWidget, SLOT(setEnabled(bool)));
// "Save as" disables the file target input field.
connect(ui.saveAsCheckBox , SIGNAL(toggled(bool)), ui.targetLineEdit , SLOT(setDisabled(bool)));
connect(ui.saveAsCheckBox , SIGNAL(toggled(bool)), ui.browsePushButton , SLOT(setDisabled(bool)));
connect(ui.saveAsCheckBox , SIGNAL(toggled(bool)), ui.directoryLabel , SLOT(setDisabled(bool)));
connect(ui.startupCheckBox , SIGNAL(toggled(bool)), ui.startupHideCheckBox , SLOT(setEnabled(bool)));
connect(ui.qualitySlider , SIGNAL(valueChanged(int)), ui.qualityValueLabel, SLOT(setNum(int)));
connect(ui.trayCheckBox , SIGNAL(toggled(bool)), ui.messageCheckBox , SLOT(setEnabled(bool)));
// Auto-upload disables the default action button in the previews.
connect(ui.uploadCheckBox , SIGNAL(toggled(bool)), ui.previewDefaultActionLabel , SLOT(setDisabled(bool)));
connect(ui.uploadCheckBox , SIGNAL(toggled(bool)), ui.previewDefaultActionComboBox, SLOT(setDisabled(bool)));
connect(ui.directoryCheckBox , SIGNAL(toggled(bool)), ui.directoryHotkeyWidget, SLOT(setEnabled(bool)));
connect(ui.mainLabel , SIGNAL(linkActivated(QString)), this, SLOT(openUrl(QString)));
connect(ui.licenseAboutLabel, SIGNAL(linkActivated(QString)), this, SLOT(openUrl(QString)));
connect(ui.linksLabel, SIGNAL(linkActivated(QString)), this, SLOT(openUrl(QString)));
}
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/dialogs/optionsdialog.ui b/dialogs/optionsdialog.ui
index e5591c0..f418d53 100644
--- a/dialogs/optionsdialog.ui
+++ b/dialogs/optionsdialog.ui
@@ -1,1491 +1,1491 @@
<?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>399</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>
</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_11">
<item>
<widget class="QCheckBox" name="uploadCheckBox">
<property name="text">
<string>Upload all my screenshots automatically.</string>
</property>
</widget>
</item>
<item>
<widget class="QCheckBox" name="imgurClipboardCheckBox">
<property name="text">
<string>After uploading, copy the imgur URL to the clipboard.</string>
</property>
</widget>
</item>
<item>
<widget class="QGroupBox" name="imgurAuthGroupBox">
<property name="title">
<string>User Account</string>
</property>
<property name="flat">
<bool>true</bool>
</property>
<property name="checkable">
<bool>true</bool>
</property>
<property name="checked">
<bool>false</bool>
</property>
<layout class="QGridLayout" name="gridLayout_4">
<item row="0" column="0">
<widget class="QLabel" name="imgurUserLabel">
<property name="text">
<string>User:</string>
</property>
<property name="buddy">
<cstring>imgurAuthButton</cstring>
</property>
</widget>
</item>
<item row="0" column="3">
<widget class="QPushButton" name="imgurAuthButton">
<property name="text">
<string>Authorize</string>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="imgurAlbumLabel">
<property name="text">
<string>Upload to album:</string>
</property>
<property name="buddy">
<cstring>imgurAlbumComboBox</cstring>
</property>
</widget>
</item>
<item row="1" column="3">
<widget class="QPushButton" name="imgurRefreshAlbumButton">
<property name="enabled">
<bool>false</bool>
</property>
<property name="text">
<string>Refresh</string>
</property>
</widget>
</item>
<item row="1" column="1" colspan="2">
<widget class="QComboBox" name="imgurAlbumComboBox">
<item>
<property name="text">
<string>- None -</string>
</property>
</item>
</widget>
</item>
<item row="0" column="1" colspan="2">
<widget class="QLabel" name="imgurAuthUserLabel">
<property name="text">
<string>&lt;i&gt;none</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QLabel" name="imgurHelpLabel">
<property name="text">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;&lt;span style=&quot; text-decoration: underline;&quot;&gt;Note&lt;/span&gt;: Clicking on the &amp;quot;Authorize&amp;quot; button will open the Imgur website, where you will need to log in with the account you wish to use. They will provide an authentication PIN that you must input into Lightscreen.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<spacer name="verticalSpacer_2">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</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>
- <width>312</width>
+ <width>358</width>
<height>706</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="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="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="QHBoxLayout" name="updaterLayout">
<item>
<widget class="QCheckBox" name="updaterCheckBox">
<property name="text">
<string>Check for updates regularly.</string>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer_3">
<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>
<widget class="QPushButton" name="checkUpdatesPushButton">
<property name="text">
<string>Chec&amp;k Now</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;, using the &lt;a href=&quot;#aboutqt&quot;&gt;Qt toolkit&lt;/a&gt; for the graphical user interface.</string>
+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>
</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>
</connections>
</ui>
diff --git a/dialogs/previewdialog.cpp b/dialogs/previewdialog.cpp
index 11395e0..f2f3c6c 100644
--- a/dialogs/previewdialog.cpp
+++ b/dialogs/previewdialog.cpp
@@ -1,398 +1,398 @@
/*
* Copyright (C) 2016 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 "previewdialog.h"
#include "../tools/screenshot.h"
#include "../tools/screenshotmanager.h"
#include "../tools/os.h"
#include <QApplication>
#include <QDesktopServices>
#include <QDesktopWidget>
#include <QGraphicsDropShadowEffect>
#include <QHBoxLayout>
#include <QIcon>
#include <QLabel>
#include <QList>
#include <QMenu>
#include <QObject>
#include <QPalette>
#include <QPushButton>
#include <QSettings>
#include <QStackedLayout>
#include <QToolButton>
#include <QUrl>
PreviewDialog::PreviewDialog(QWidget *parent) :
QDialog(parent), mAutoclose(0), mAutocloseAction(0), mAutocloseReset(0), mPosition(0), mSize(0)
{
setWindowFlags(Qt::Tool | Qt::WindowStaysOnTopHint);
setWindowTitle(tr("Screenshot Preview"));
QSettings *settings = ScreenshotManager::instance()->settings();
mSize = settings->value("options/previewSize", 300).toInt();
mPosition = settings->value("options/previewPosition", 3).toInt();
if (settings->value("options/previewAutoclose", false).toBool()) {
mAutoclose = settings->value("options/previewAutocloseTime").toInt();
mAutocloseReset = mAutoclose;
mAutocloseAction = settings->value("options/previewAutocloseAction").toInt();
}
QHBoxLayout *l = new QHBoxLayout;
mStack = new QStackedLayout;
connect(mStack, SIGNAL(currentChanged(int)), this, SLOT(indexChanged(int)));
mPrevButton = new QPushButton(os::icon("arrow-left"), "", this);
connect(mPrevButton, SIGNAL(clicked()), this, SLOT(previous()));
mNextButton = new QPushButton(os::icon("arrow-right"), "", this);
connect(mNextButton, SIGNAL(clicked()), this, SLOT(next()));
mPrevButton->setCursor(Qt::PointingHandCursor);
mPrevButton->setFlat(true);
mPrevButton->setGraphicsEffect(os::shadow(Qt::white));
mPrevButton->setIconSize(QSize(24, 24));
mPrevButton->setVisible(false);
mNextButton->setCursor(Qt::PointingHandCursor);
mNextButton->setFlat(true);
mNextButton->setGraphicsEffect(os::shadow(Qt::white));
mNextButton->setIconSize(QSize(24, 24));
mNextButton->setVisible(false);
l->addWidget(mPrevButton);
l->addLayout(mStack);
l->addWidget(mNextButton);
l->setMargin(0);
l->setContentsMargins(6, 6, 6, 6);
mStack->setMargin(0);
setMaximumHeight(mSize);
setLayout(l);
if (mAutoclose) {
startTimer(1000);
}
}
void PreviewDialog::add(Screenshot *screenshot)
{
if (!isVisible()) {
show();
}
if (mAutoclose) {
mAutoclose = mAutocloseReset;
}
QLabel *label = new QLabel(this);
label->setGraphicsEffect(os::shadow());
bool small = false;
QSize size = screenshot->pixmap().size();
if (size.width() > mSize || size.height() > mSize) {
size.scale(mSize, mSize, Qt::KeepAspectRatio);
} else {
small = true;
}
QPixmap thumbnail = screenshot->pixmap().scaled(size, Qt::KeepAspectRatio, Qt::SmoothTransformation);
label->setPixmap(thumbnail);
thumbnail = QPixmap();
label->setAlignment(Qt::AlignCenter);
if (size.height() < 120) {
label->setMinimumHeight(120);
}
if (size.width() < 140) {
label->setMinimumWidth(140);
}
label->resize(size);
QPushButton *discardPushButton = new QPushButton(os::icon("no") , "", label);
QPushButton *enlargePushButton = new QPushButton(os::icon("preview"), "", label);
QToolButton *confirmPushButton = new QToolButton(label);
confirmPushButton->setIconSize(QSize(24, 24));
confirmPushButton->setCursor(Qt::PointingHandCursor);
confirmPushButton->setGraphicsEffect(os::shadow(Qt::white));
if (ScreenshotManager::instance()->settings()->value("options/previewDefaultAction", 0).toInt() == 0
|| ScreenshotManager::instance()->settings()->value("options/uploadAuto").toBool()) {
// Default button, confirm & upload.
confirmPushButton->setIcon(os::icon("yes"));
if (!ScreenshotManager::instance()->settings()->value("options/uploadAuto").toBool()) {
QMenu *confirmMenu = new QMenu(confirmPushButton);
confirmMenu->setObjectName("confirmMenu");
QAction *uploadAction = new QAction(os::icon("imgur"), tr("Upload"), confirmPushButton);
connect(uploadAction, SIGNAL(triggered()), screenshot, SLOT(markUpload()));
connect(uploadAction, SIGNAL(triggered()), screenshot, SLOT(confirm()));
connect(uploadAction, SIGNAL(triggered()), this, SLOT(closePreview()));
connect(this, SIGNAL(uploadAll()), uploadAction, SLOT(trigger()));
confirmMenu->addAction(uploadAction);
confirmPushButton->setMenu(confirmMenu);
confirmPushButton->setPopupMode(QToolButton::MenuButtonPopup);
}
connect(this, SIGNAL(acceptAll()), confirmPushButton, SLOT(click()));
connect(confirmPushButton, SIGNAL(clicked()), screenshot, SLOT(confirm()));
connect(confirmPushButton, SIGNAL(clicked()), this, SLOT(closePreview()));
} else {
// Reversed button, upload & confirm.
confirmPushButton->setIcon(os::icon("imgur"));
QMenu *confirmMenu = new QMenu(confirmPushButton);
confirmMenu->setObjectName("confirmMenu");
QAction *confirmAction = new QAction(os::icon("yes"), tr("Save"), confirmPushButton);
connect(this, SIGNAL(acceptAll()), confirmAction, SLOT(trigger()));
connect(confirmAction, SIGNAL(triggered()), screenshot, SLOT(confirm()));
connect(confirmAction, SIGNAL(triggered()), this, SLOT(closePreview()));
connect(confirmPushButton, SIGNAL(clicked()), screenshot, SLOT(markUpload()));
connect(confirmPushButton, SIGNAL(clicked()), screenshot, SLOT(confirm()));
connect(confirmPushButton, SIGNAL(clicked()), this, SLOT(closePreview()));
connect(this, SIGNAL(uploadAll()), confirmPushButton, SLOT(click()));
confirmMenu->addAction(confirmAction);
confirmPushButton->setMenu(confirmMenu);
confirmPushButton->setPopupMode(QToolButton::MenuButtonPopup);
}
confirmPushButton->setAutoRaise(true);
confirmPushButton->setVisible(false);
discardPushButton->setIconSize(QSize(24, 24));
discardPushButton->setCursor(Qt::PointingHandCursor);
discardPushButton->setGraphicsEffect(os::shadow(Qt::white));
discardPushButton->setFlat(true);
discardPushButton->setVisible(false);
enlargePushButton->setIconSize(QSize(22, 22));
enlargePushButton->setCursor(Qt::PointingHandCursor);
enlargePushButton->setGraphicsEffect(os::shadow(Qt::white));
enlargePushButton->setFlat(true);
enlargePushButton->setVisible(false);
enlargePushButton->setDisabled(small);
connect(this, SIGNAL(rejectAll()), discardPushButton, SLOT(click()));
connect(discardPushButton, SIGNAL(clicked()), screenshot, SLOT(discard()));
connect(discardPushButton, SIGNAL(clicked()), this, SLOT(closePreview()));
connect(enlargePushButton, SIGNAL(clicked()), this, SLOT(enlargePreview()));
QHBoxLayout *wlayout = new QHBoxLayout;
wlayout->addWidget(confirmPushButton);
wlayout->addStretch();
wlayout->addWidget(enlargePushButton);
wlayout->addStretch();
wlayout->addWidget(discardPushButton);
wlayout->setMargin(0);
QVBoxLayout *wl = new QVBoxLayout;
wl->addStretch();
wl->addLayout(wlayout);
wl->setMargin(0);
label->setLayout(wl);
mStack->addWidget(label);
mStack->setCurrentIndex(mStack->count() - 1);
mNextButton->setEnabled(false);
if (mStack->count() >= 2 && !mNextButton->isVisible()) {
mNextButton->setVisible(true);
mPrevButton->setVisible(true);
}
relocate();
}
int PreviewDialog::count() const
{
return mStack->count();
}
//
void PreviewDialog::closePreview()
{
QWidget *widget = mStack->currentWidget();
mStack->removeWidget(widget);
widget->deleteLater();
if (mStack->count() == 0) {
close();
} else {
relocate();
}
}
void PreviewDialog::enlargePreview()
{
Screenshot *screenshot = qobject_cast<Screenshot *>(ScreenshotManager::instance()->children().at(mStack->currentIndex()));
if (screenshot) {
QFileInfo info(screenshot->unloadedFileName());
QDesktopServices::openUrl(QUrl(info.absoluteFilePath()));
}
}
void PreviewDialog::indexChanged(int i)
{
if (i == mStack->count() - 1) {
mNextButton->setEnabled(false);
mPrevButton->setEnabled(true);
}
if (i == 0 && mStack->count() > 1) {
mNextButton->setEnabled(true);
mPrevButton->setEnabled(false);
}
if (i != 0 && i != mStack->count() - 1) {
mNextButton->setEnabled(true);
mPrevButton->setEnabled(true);
}
if (mStack->count() < 2) {
mNextButton->setEnabled(false);
mPrevButton->setEnabled(false);
}
if (mStack->widget(i)) {
mStack->widget(i)->setFocus();
}
if (mStack->count() > 1) {
setWindowTitle(tr("Screenshot Preview (%1 of %2)").arg(mStack->currentIndex() + 1).arg(mStack->count()));
} else {
setWindowTitle(tr("Screenshot Preview"));
}
}
void PreviewDialog::next()
{
mStack->setCurrentIndex(mStack->currentIndex() + 1);
relocate();
}
void PreviewDialog::previous()
{
mStack->setCurrentIndex(mStack->currentIndex() - 1);
relocate();
}
void PreviewDialog::relocate()
{
updateGeometry();
resize(minimumSizeHint());
QApplication::sendEvent(this, new QEvent(QEvent::Enter)); // Ensures the buttons are visible.
QPoint where;
switch (mPosition) {
case 0:
where = QApplication::desktop()->availableGeometry(this).topLeft();
break;
case 1:
where = QApplication::desktop()->availableGeometry(this).topRight();
where.setX(where.x() - frameGeometry().width());
break;
case 2:
where = QApplication::desktop()->availableGeometry(this).bottomLeft();
where.setY(where.y() - frameGeometry().height());
break;
case 3:
default:
where = QApplication::desktop()->availableGeometry(this).bottomRight();
where.setX(where.x() - frameGeometry().width());
where.setY(where.y() - frameGeometry().height());
break;
}
move(where);
}
//
bool PreviewDialog::event(QEvent *event)
{
if ((event->type() == QEvent::Enter || event->type() == QEvent::Leave)
&& mStack->currentWidget()) {
- foreach (QObject *child, mStack->currentWidget()->children()) {
+ for (QObject *child : mStack->currentWidget()->children()) {
QWidget *widget = qobject_cast<QWidget *>(child);
if (widget) {
// Lets avoid disappearing buttons and bail if the menu is open.
QMenu *confirmMenu = widget->findChild<QMenu *>("confirmMenu");
if (confirmMenu && confirmMenu->isVisible()) {
return false;
}
widget->setVisible((event->type() == QEvent::Enter));
}
}
} else if (event->type() == QEvent::Close) {
if (mStack->count() != 0) {
emit rejectAll();
}
deleteLater();
} else if (event->type() == QEvent::MouseButtonDblClick) {
enlargePreview();
}
return QDialog::event(event);
}
void PreviewDialog::timerEvent(QTimerEvent *event)
{
if (mAutoclose == 0) {
if (mAutocloseAction == 0) {
emit acceptAll();
} else if (mAutocloseAction == 1) {
emit uploadAll();
} else {
emit rejectAll();
}
} else if (mAutoclose < 0) {
killTimer(event->timerId());
} else {
setWindowTitle(tr("Preview: Closing in %1").arg(mAutoclose));
mAutoclose--;
}
}
diff --git a/lightscreenwindow.cpp b/lightscreenwindow.cpp
index 426da49..b10a98b 100644
--- a/lightscreenwindow.cpp
+++ b/lightscreenwindow.cpp
@@ -1,1038 +1,1038 @@
/*
* Copyright (C) 2016 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 <QDate>
#include <QDesktopServices>
#include <QDesktopWidget>
#include <QFileInfo>
#include <QKeyEvent>
#include <QMainWindow>
#include <QMenu>
#include <QMessageBox>
#include <QPointer>
#include <QProcess>
#include <QSettings>
#include <QSystemTrayIcon>
#include <QTimer>
#include <QToolTip>
#include <QUrl>
#include <QSound>
#include <QKeyEvent>
#ifdef Q_OS_WIN
#include <windows.h>
#include <QtWinExtras>
#endif
//
//Lightscreen includes
//
#include "lightscreenwindow.h"
#include "dialogs/optionsdialog.h"
#include "dialogs/previewdialog.h"
#include "dialogs/historydialog.h"
#include "tools/os.h"
#include "tools/screenshot.h"
#include "tools/screenshotmanager.h"
#include "tools/UGlobalHotkey/uglobalhotkeys.h"
#include "tools/uploader/uploader.h"
#include "updater/updater.h"
LightscreenWindow::LightscreenWindow(QWidget *parent) :
QMainWindow(parent),
mDoCache(false),
mHideTrigger(false),
mReviveMain(false),
mWasVisible(true),
mLastMessage(0),
mLastMode(-1),
mLastScreenshot(),
mHasTaskbarButton(false)
{
ui.setupUi(this);
ui.screenPushButton->setIcon(os::icon("screen.big"));
ui.areaPushButton->setIcon(os::icon("area.big"));
ui.windowPushButton->setIcon(os::icon("pickWindow.big"));
ui.optionsPushButton->setIcon(os::icon("configure"));
ui.folderPushButton->setIcon(os::icon("folder"));
ui.imgurPushButton->setIcon(os::icon("imgur"));
createUploadMenu();
#ifdef Q_OS_WIN
if (QSysInfo::WindowsVersion >= QSysInfo::WV_WINDOWS7) {
mTaskbarButton = new QWinTaskbarButton(this);
mHasTaskbarButton = true;
if (QtWin::isCompositionEnabled()) {
setAttribute(Qt::WA_NoSystemBackground);
QtWin::enableBlurBehindWindow(this);
QtWin::extendFrameIntoClientArea(this, QMargins(-1, -1, -1, -1));
}
}
if (QSysInfo::WindowsVersion < QSysInfo::WV_WINDOWS7) {
ui.centralWidget->setStyleSheet("QPushButton { padding: 2px; border: 1px solid #acacac; background: qlineargradient(spread:pad, x1:0, y1:0, x2:0, y2:1, stop:0 #eaeaea, stop:1 #e5e5e5);} QPushButton:hover { border: 1px solid #7eb4ea; background-color: #e4f0fc; }");
}
#endif
setMaximumSize(size());
setMinimumSize(size());
setWindowFlags(windowFlags() ^ Qt::WindowMaximizeButtonHint);
// Actions
connect(ui.screenPushButton, SIGNAL(clicked()), this, SLOT(screenshotAction()));
connect(ui.areaPushButton , SIGNAL(clicked()), this, SLOT(areaHotkey()));
connect(ui.windowPushButton, SIGNAL(clicked()), this, SLOT(windowPickerHotkey()));
connect(ui.optionsPushButton, SIGNAL(clicked()), this, SLOT(showOptions()));
connect(ui.folderPushButton , SIGNAL(clicked()), this, SLOT(goToFolder()));
// Shortcuts
mGlobalHotkeys = new UGlobalHotkeys(this);
connect(mGlobalHotkeys, &UGlobalHotkeys::activated, [&](size_t id) {
if (id <= 3) {
screenshotAction(id);
} else if (id == 4) {
show();
} else if (id == 5) {
goToFolder();
} else {
qWarning() << "Uknown hotkey ID: " << id;
}
});
// Uploader
connect(Uploader::instance(), SIGNAL(progress(int)), this, SLOT(uploadProgress(int)));
connect(Uploader::instance(), SIGNAL(done(QString, QString, QString)), this, SLOT(showUploaderMessage(QString, QString)));
connect(Uploader::instance(), SIGNAL(error(QString)), this, SLOT(showUploaderError(QString)));
// Manager
connect(ScreenshotManager::instance(), SIGNAL(confirm(Screenshot *)), this, SLOT(preview(Screenshot *)));
connect(ScreenshotManager::instance(), SIGNAL(windowCleanup(Screenshot::Options &)), this, SLOT(cleanup(Screenshot::Options &)));
connect(ScreenshotManager::instance(), SIGNAL(activeCountChange()), this, SLOT(updateStatus()));
if (!settings()->contains("file/format")) {
showOptions(); // There are no options (or the options config is invalid or incomplete)
} else {
QTimer::singleShot(0 , this, SLOT(applySettings()));
QTimer::singleShot(5000, this, SLOT(checkForUpdates()));
}
}
LightscreenWindow::~LightscreenWindow()
{
settings()->setValue("lastScreenshot", mLastScreenshot);
settings()->sync();
mGlobalHotkeys->unregisterAllHotkeys();
}
void LightscreenWindow::action(int mode)
{
if (mode == 4) {
goToFolder();
} else {
show();
}
}
void LightscreenWindow::areaHotkey()
{
screenshotAction(2);
}
void LightscreenWindow::checkForUpdates()
{
if (settings()->value("options/disableUpdater", false).toBool()) {
return;
}
if (settings()->value("lastUpdateCheck").toInt() + 7
> QDate::currentDate().dayOfYear()) {
return; // If 7 days have not passed since the last update check.
}
mUpdater = new Updater(this);
connect(mUpdater, SIGNAL(done(bool)), this, SLOT(updaterDone(bool)));
mUpdater->check();
}
void LightscreenWindow::cleanup(Screenshot::Options &options)
{
// Reversing settings
if (settings()->value("options/hide").toBool()) {
#ifndef Q_OS_LINUX // X is not quick enough and the notification ends up everywhere but in the icon
if (settings()->value("options/tray").toBool() && mTrayIcon) {
mTrayIcon->show();
}
#endif
if (mPreviewDialog) {
if (mPreviewDialog->count() <= 1 && mWasVisible) {
show();
}
mPreviewDialog->show();
} else if (mWasVisible) {
show();
}
mHideTrigger = false;
}
if (settings()->value("options/tray").toBool() && mTrayIcon) {
notify(options.result);
if (settings()->value("options/message").toBool() && options.file && !options.upload) {
// This message wll get shown only when messages are enabled and the file won't get another upload pop-up soon.
showScreenshotMessage(options.result, options.fileName);
}
}
if (settings()->value("options/playSound", false).toBool()) {
if (options.result == Screenshot::Success) {
QSound::play("sounds/ls.screenshot.wav");
} else {
#ifdef Q_OS_WIN
QSound::play("afakepathtomakewindowsplaythedefaultsoundtheresprobablyabetterwaybuticantbebothered");
#else
QSound::play("sound/ls.error.wav");
#endif
}
}
updateStatus();
if (options.result != Screenshot::Success) {
return;
}
mLastScreenshot = options.fileName;
}
void LightscreenWindow::closeToTrayWarning()
{
if (!settings()->value("options/closeToTrayWarning", true).toBool()) {
return;
}
mLastMessage = 3;
mTrayIcon->showMessage(tr("Closed to tray"), tr("Lightscreen will keep running, you can disable this in the options menu."));
settings()->setValue("options/closeToTrayWarning", false);
}
bool LightscreenWindow::closingWithoutTray()
{
if (settings()->value("options/disableHideAlert", false).toBool()) {
return false;
}
QMessageBox msgBox;
msgBox.setWindowTitle(tr("Lightscreen"));
msgBox.setText(tr("You have chosen to hide Lightscreen when there's no system tray icon, so you will not be able to access the program <b>unless you have selected a hotkey to do so</b>.<br>What do you want to do?"));
msgBox.setIcon(QMessageBox::Warning);
msgBox.setStyleSheet("QPushButton { padding: 4px 8px; }");
QPushButton *enableButton = msgBox.addButton(tr("Hide but enable tray"),
QMessageBox::ActionRole);
QPushButton *enableAndDenotifyButton = msgBox.addButton(tr("Hide and don't warn"),
QMessageBox::ActionRole);
QPushButton *hideButton = msgBox.addButton(tr("Just hide"),
QMessageBox::ActionRole);
QPushButton *abortButton = msgBox.addButton(QMessageBox::Cancel);
Q_UNUSED(abortButton);
msgBox.exec();
if (msgBox.clickedButton() == hideButton) {
return true;
} else if (msgBox.clickedButton() == enableAndDenotifyButton) {
settings()->setValue("options/disableHideAlert", true);
applySettings();
return true;
} else if (msgBox.clickedButton() == enableButton) {
settings()->setValue("options/tray", true);
applySettings();
return true;
}
return false; // Cancel.
}
void LightscreenWindow::createUploadMenu()
{
QMenu *imgurMenu = new QMenu(tr("Upload"));
QAction *uploadAction = new QAction(os::icon("imgur"), tr("&Upload last"), imgurMenu);
uploadAction->setToolTip(tr("Upload the last screenshot you took to imgur.com"));
connect(uploadAction, SIGNAL(triggered()), this, SLOT(uploadLast()));
QAction *cancelAction = new QAction(os::icon("no"), tr("&Cancel upload"), imgurMenu);
cancelAction->setToolTip(tr("Cancel the currently uploading screenshots"));
cancelAction->setEnabled(false);
connect(this, SIGNAL(uploading(bool)), cancelAction, SLOT(setEnabled(bool)));
connect(cancelAction, SIGNAL(triggered()), this, SLOT(uploadCancel()));
QAction *historyAction = new QAction(os::icon("view-history"), tr("View &History"), imgurMenu);
connect(historyAction, SIGNAL(triggered()), this, SLOT(showHistoryDialog()));
imgurMenu->addAction(uploadAction);
imgurMenu->addAction(cancelAction);
imgurMenu->addAction(historyAction);
imgurMenu->addSeparator();
connect(imgurMenu, SIGNAL(aboutToShow()), this, SLOT(uploadMenuShown()));
ui.imgurPushButton->setMenu(imgurMenu);
}
void LightscreenWindow::goToFolder()
{
#ifdef Q_OS_WIN
if (!mLastScreenshot.isEmpty() && QFile::exists(mLastScreenshot)) {
QProcess::startDetached("explorer /select, \"" + mLastScreenshot + "\"");
} else {
#endif
QDir path(settings()->value("file/target").toString());
// We might want to go to the folder without it having been created by taking a screenshot yet.
if (!path.exists()) {
path.mkpath(path.absolutePath());
}
QDesktopServices::openUrl(QUrl::fromLocalFile(path.absolutePath() + QDir::separator()));
#ifdef Q_OS_WIN
}
#endif
}
void LightscreenWindow::messageClicked()
{
if (mLastMessage == 1) {
goToFolder();
} else if (mLastMessage == 3) {
QTimer::singleShot(0, this, SLOT(showOptions()));
} else {
QDesktopServices::openUrl(QUrl(Uploader::instance()->lastUrl()));
}
}
void LightscreenWindow::executeArgument(const QString &message)
{
if (message == "--wake") {
show();
os::setForegroundWindow(this);
qApp->alert(this, 2000);
} else if (message == "--screen") {
screenshotAction();
} else if (message == "--area") {
screenshotAction(2);
} else if (message == "--activewindow") {
screenshotAction(1);
} else if (message == "--pickwindow") {
screenshotAction(3);
} else if (message == "--folder") {
action(4);
} else if (message == "--uploadlast") {
uploadLast();
} else if (message == "--viewhistory") {
showHistoryDialog();
} else if (message == "--options") {
showOptions();
} else if (message == "--quit") {
qApp->quit();
}
}
void LightscreenWindow::executeArguments(const QStringList &arguments)
{
// If we just have the default argument, call "--wake"
if (arguments.count() == 1 && (arguments.at(0) == qApp->arguments().at(0) || arguments.at(0).contains(QFileInfo(qApp->applicationFilePath()).fileName()))) {
executeArgument("--wake");
return;
}
- foreach (const QString &argument, arguments) {
+ for (auto argument : arguments) {
executeArgument(argument);
}
}
void LightscreenWindow::notify(const Screenshot::Result &result)
{
switch (result) {
case Screenshot::Success:
mTrayIcon->setIcon(QIcon(":/icons/lightscreen.yes"));
if (mHasTaskbarButton) {
mTaskbarButton->setOverlayIcon(os::icon("yes"));
}
setWindowTitle(tr("Success!"));
break;
case Screenshot::Fail:
mTrayIcon->setIcon(QIcon(":/icons/lightscreen.no"));
setWindowTitle(tr("Failed!"));
if (mHasTaskbarButton) {
mTaskbarButton->setOverlayIcon(os::icon("no"));
}
break;
case Screenshot::Cancel:
setWindowTitle(tr("Cancelled!"));
break;
}
QTimer::singleShot(2000, this, SLOT(restoreNotification()));
}
void LightscreenWindow::preview(Screenshot *screenshot)
{
if (screenshot->options().preview) {
if (!mPreviewDialog) {
mPreviewDialog = new PreviewDialog(this);
}
mPreviewDialog->add(screenshot);
} else {
screenshot->confirm(true);
}
}
void LightscreenWindow::quit()
{
settings()->setValue("position", pos());
int answer = 0;
QString doing;
if (ScreenshotManager::instance()->activeCount() > 0) {
doing = tr("processing");
}
if (Uploader::instance()->uploading() > 0) {
if (doing.isEmpty()) {
doing = tr("uploading");
} else {
doing = tr("processing and uploading");
}
}
if (!doing.isEmpty()) {
answer = QMessageBox::question(this,
tr("Are you sure you want to quit?"),
tr("Lightscreen is currently %1 screenshots. Are you sure you want to quit?").arg(doing),
tr("Quit"),
tr("Don't Quit"));
}
if (answer == 0) {
emit finished();
}
}
void LightscreenWindow::restoreNotification()
{
if (mTrayIcon) {
mTrayIcon->setIcon(QIcon(":/icons/lightscreen.small"));
}
if (mHasTaskbarButton) {
mTaskbarButton->clearOverlayIcon();
mTaskbarButton->progress()->setVisible(false);
mTaskbarButton->progress()->stop();
mTaskbarButton->progress()->reset();
}
updateStatus();
}
void LightscreenWindow::screenshotAction(int mode)
{
int delayms = -1;
bool optionsHide = settings()->value("options/hide").toBool(); // Option cache, used a couple of times.
if (!mHideTrigger) {
mWasVisible = isVisible();
mHideTrigger = true;
}
// Applying pre-screenshot settings
if (optionsHide) {
hide();
#ifndef Q_OS_LINUX // X is not quick enough and the notification ends up everywhere but in the icon
if (mTrayIcon) {
mTrayIcon->hide();
}
#endif
}
// Screenshot delay
delayms = settings()->value("options/delay", 0).toInt();
delayms = delayms * 1000; // Converting the delay to milliseconds.
delayms += 400;
if (optionsHide && mPreviewDialog) {
if (mPreviewDialog->count() >= 1) {
mPreviewDialog->hide();
}
}
// The delayed functions works using the static variable lastMode
// which keeps the argument so a QTimer can call this function again.
if (delayms > 0) {
if (mLastMode < 0) {
mLastMode = mode;
QTimer::singleShot(delayms, this, SLOT(screenshotAction()));
return;
} else {
mode = mLastMode;
mLastMode = -1;
}
}
static Screenshot::Options options;
if (!mDoCache) {
// Populating the option object that will then be passed to the screenshot engine (sounds fancy huh?)
options.file = settings()->value("file/enabled").toBool();
options.format = (Screenshot::Format) settings()->value("file/format").toInt();
options.prefix = settings()->value("file/prefix").toString();
QDir dir(settings()->value("file/target").toString());
dir.makeAbsolute();
options.directory = dir;
options.quality = settings()->value("options/quality", 100).toInt();
options.currentMonitor = settings()->value("options/currentMonitor", false).toBool();
options.clipboard = settings()->value("options/clipboard", true).toBool();
options.imgurClipboard = settings()->value("options/imgurClipboard", false).toBool();
options.preview = settings()->value("options/preview", false).toBool();
options.magnify = settings()->value("options/magnify", false).toBool();
options.cursor = settings()->value("options/cursor", true).toBool();
options.saveAs = settings()->value("options/saveAs", false).toBool();
options.animations = settings()->value("options/animations", true).toBool();
options.replace = settings()->value("options/replace", false).toBool();
options.upload = settings()->value("options/uploadAuto", false).toBool();
options.optimize = settings()->value("options/optipng", false).toBool();
Screenshot::NamingOptions namingOptions;
namingOptions.naming = (Screenshot::Naming) settings()->value("file/naming").toInt();
namingOptions.leadingZeros = settings()->value("options/naming/leadingZeros", 0).toInt();
namingOptions.flip = settings()->value("options/flip", false).toBool();
namingOptions.dateFormat = settings()->value("options/naming/dateFormat", "yyyy-MM-dd").toString();
options.namingOptions = namingOptions;
mDoCache = true;
}
options.mode = mode;
ScreenshotManager::instance()->take(options);
}
void LightscreenWindow::screenshotActionTriggered(QAction *action)
{
screenshotAction(action->data().toInt());
}
void LightscreenWindow::screenHotkey()
{
screenshotAction(0);
}
void LightscreenWindow::showHotkeyError(const QStringList &hotkeys)
{
static bool dontShow = false;
if (dontShow) {
return;
}
QString messageText;
messageText = tr("Some hotkeys could not be registered, they might already be in use");
if (hotkeys.count() > 1) {
messageText += tr("<br>The failed hotkeys are the following:") + "<ul>";
- foreach (const QString &hotkey, hotkeys) {
+ for (auto hotkey : hotkeys) {
messageText += QString("%1%2%3").arg("<li><b>").arg(hotkey).arg("</b></li>");
}
messageText += "</ul>";
} else {
messageText += tr("<br>The failed hotkey is <b>%1</b>").arg(hotkeys[0]);
}
messageText += tr("<br><i>What do you want to do?</i>");
QMessageBox msgBox(this);
msgBox.setWindowTitle(tr("Lightscreen"));
msgBox.setText(messageText);
QPushButton *changeButton = msgBox.addButton(tr("Change") , QMessageBox::ActionRole);
QPushButton *disableButton = msgBox.addButton(tr("Disable"), QMessageBox::ActionRole);
QPushButton *exitButton = msgBox.addButton(tr("Quit") , QMessageBox::ActionRole);
msgBox.exec();
if (msgBox.clickedButton() == exitButton) {
dontShow = true;
QTimer::singleShot(10, this, SLOT(quit()));
} else if (msgBox.clickedButton() == changeButton) {
showOptions();
} else if (msgBox.clickedButton() == disableButton) {
- foreach (const QString &hotkey, hotkeys) {
+ for (auto hotkey : hotkeys) {
settings()->setValue(QString("actions/%1/enabled").arg(hotkey), false);
}
}
}
void LightscreenWindow::showHistoryDialog()
{
HistoryDialog historyDialog(this);
historyDialog.exec();
updateStatus();
}
void LightscreenWindow::showOptions()
{
mGlobalHotkeys->unregisterAllHotkeys();
QPointer<OptionsDialog> optionsDialog = new OptionsDialog(this);
optionsDialog->exec();
optionsDialog->deleteLater();
applySettings();
}
void LightscreenWindow::showScreenshotMessage(const Screenshot::Result &result, const QString &fileName)
{
if (result == Screenshot::Cancel) {
return;
}
// Showing message.
QString title;
QString message;
if (result == Screenshot::Success) {
title = QFileInfo(fileName).fileName();
if (settings()->value("file/target").toString().isEmpty()) {
message = QDir::toNativeSeparators(QCoreApplication::applicationDirPath());
} else {
message = tr("Saved to \"%1\"").arg(settings()->value("file/target").toString());
}
} else {
title = tr("The screenshot was not taken");
message = tr("An error occurred.");
}
mLastMessage = 1;
mTrayIcon->showMessage(title, message);
}
void LightscreenWindow::showUploaderError(const QString &error)
{
mLastMessage = -1;
updateStatus();
if (mTrayIcon && !error.isEmpty() && settings()->value("options/message").toBool()) {
mTrayIcon->showMessage(tr("Upload error"), error);
}
notify(Screenshot::Fail);
}
void LightscreenWindow::showUploaderMessage(const QString &fileName, const QString &url)
{
if (mTrayIcon && settings()->value("options/message").toBool() && !url.isEmpty()) {
QString screenshot = QFileInfo(fileName).fileName();
if (screenshot.startsWith(".lstemp.")) {
screenshot = tr("Screenshot");
}
mLastMessage = 2;
mTrayIcon->showMessage(tr("%1 uploaded").arg(screenshot), tr("Click here to go to %1").arg(url));
}
updateStatus();
}
void LightscreenWindow::toggleVisibility(QSystemTrayIcon::ActivationReason reason)
{
if (reason != QSystemTrayIcon::DoubleClick) {
return;
}
if (isVisible()) {
hide();
} else {
show();
os::setForegroundWindow(this);
}
}
void LightscreenWindow::updateStatus()
{
int uploadCount = Uploader::instance()->uploading();
int activeCount = ScreenshotManager::instance()->activeCount();
if (mHasTaskbarButton) {
mTaskbarButton->progress()->setPaused(true);
mTaskbarButton->progress()->setVisible(true);
}
if (uploadCount > 0) {
setStatus(tr("%1 uploading").arg(uploadCount));
if (mHasTaskbarButton) {
mTaskbarButton->progress()->setRange(0, 100);
mTaskbarButton->progress()->resume();
}
emit uploading(true);
} else {
if (activeCount > 1) {
setStatus(tr("%1 processing").arg(activeCount));
} else if (activeCount == 1) {
setStatus(tr("processing"));
} else {
setStatus();
if (mHasTaskbarButton) {
mTaskbarButton->progress()->setVisible(false);
}
}
emit uploading(false);
}
}
void LightscreenWindow::updaterDone(bool result)
{
settings()->setValue("lastUpdateCheck", QDate::currentDate().dayOfYear());
if (!result) {
return;
}
QMessageBox msgBox;
msgBox.setWindowTitle(tr("Lightscreen"));
msgBox.setText(tr("There's a new version of Lightscreen available.<br>Would you like to see more information?<br>(<em>You can turn this notification off</em>)"));
msgBox.setIcon(QMessageBox::Information);
QPushButton *yesButton = msgBox.addButton(QMessageBox::Yes);
QPushButton *turnOffButton = msgBox.addButton(tr("Turn Off"), QMessageBox::ActionRole);
QPushButton *remindButton = msgBox.addButton(tr("Remind Me Later"), QMessageBox::RejectRole);
Q_UNUSED(remindButton);
msgBox.exec();
if (msgBox.clickedButton() == yesButton) {
QDesktopServices::openUrl(QUrl("https://lightscreen.com.ar/whatsnew?from=" + qApp->applicationVersion()));
} else if (msgBox.clickedButton() == turnOffButton) {
settings()->setValue("options/disableUpdater", true);
}
mUpdater->deleteLater();
}
void LightscreenWindow::upload(const QString &fileName)
{
Uploader::instance()->upload(fileName);
}
void LightscreenWindow::uploadCancel()
{
if (Uploader::instance()->uploading() <= 0) {
return;
}
int confirm = QMessageBox::question(this, tr("Upload cancel"), tr("Do you want to cancel all screenshot uploads?"), tr("Cancel"), tr("Don't Cancel"));
if (confirm == 0) {
Uploader::instance()->cancel();
updateStatus();
}
}
void LightscreenWindow::uploadLast()
{
upload(mLastScreenshot);
updateStatus();
}
void LightscreenWindow::uploadProgress(int progress)
{
if (mHasTaskbarButton) {
mTaskbarButton->progress()->setVisible(true);
mTaskbarButton->progress()->setValue(progress);
}
if (isVisible() && progress > 0) {
int uploadCount = Uploader::instance()->uploading();
if (uploadCount > 1) {
setWindowTitle(tr("%1% of %2 uploads - Lightscreen").arg(progress).arg(uploadCount));
} else {
setWindowTitle(tr("%1% - Lightscreen").arg(progress));
}
}
}
void LightscreenWindow::uploadMenuShown()
{
QMenu *imgurMenu = qobject_cast<QMenu *>(sender());
imgurMenu->actions().at(0)->setEnabled(!mLastScreenshot.isEmpty());
}
void LightscreenWindow::windowHotkey()
{
screenshotAction(1);
}
void LightscreenWindow::windowPickerHotkey()
{
screenshotAction(3);
}
void LightscreenWindow::applySettings()
{
bool tray = settings()->value("options/tray", true).toBool();
if (tray && !mTrayIcon) {
createTrayIcon();
mTrayIcon->setVisible(true);
} else if (!tray && mTrayIcon) {
mTrayIcon->setVisible(false);
}
connectHotkeys();
mDoCache = false;
if (settings()->value("lastScreenshot").isValid() && mLastScreenshot.isEmpty()) {
mLastScreenshot = settings()->value("lastScreenshot").toString();
}
os::setStartup(settings()->value("options/startup").toBool(), settings()->value("options/startupHide").toBool());
}
void LightscreenWindow::connectHotkeys()
{
+ const QStringList actions = {"screen", "window", "area", "windowPicker", "open", "directory"};
QStringList failed;
- QStringList actions = {"screen", "window", "area", "windowPicker", "open", "directory"};
size_t i = 0;
- foreach (const QString &action, actions) {
+ for (auto action : actions) {
if (settings()->value("actions/" + action + "/enabled").toBool()) {
if (!mGlobalHotkeys->registerHotkey(settings()->value("actions/" + action + "/hotkey").toString(), i)) {
failed << action;
}
}
i++;
}
if (!failed.isEmpty()) {
showHotkeyError(failed);
}
}
void LightscreenWindow::createTrayIcon()
{
mTrayIcon = new QSystemTrayIcon(QIcon(":/icons/lightscreen.small"), this);
updateStatus();
connect(mTrayIcon, SIGNAL(activated(QSystemTrayIcon::ActivationReason)), this, SLOT(toggleVisibility(QSystemTrayIcon::ActivationReason)));
connect(mTrayIcon, SIGNAL(messageClicked()), this, SLOT(messageClicked()));
QAction *hideAction = new QAction(QIcon(":/icons/lightscreen.small"), tr("Show&/Hide"), mTrayIcon);
connect(hideAction, SIGNAL(triggered()), this, SLOT(toggleVisibility()));
QAction *screenAction = new QAction(os::icon("screen"), tr("&Screen"), mTrayIcon);
screenAction->setData(QVariant(0));
QAction *windowAction = new QAction(os::icon("window"), tr("Active &Window"), this);
windowAction->setData(QVariant(1));
QAction *windowPickerAction = new QAction(os::icon("pickWindow"), tr("&Pick Window"), this);
windowPickerAction->setData(QVariant(3));
QAction *areaAction = new QAction(os::icon("area"), tr("&Area"), mTrayIcon);
areaAction->setData(QVariant(2));
QActionGroup *screenshotGroup = new QActionGroup(mTrayIcon);
screenshotGroup->addAction(screenAction);
screenshotGroup->addAction(areaAction);
screenshotGroup->addAction(windowAction);
screenshotGroup->addAction(windowPickerAction);
connect(screenshotGroup, SIGNAL(triggered(QAction *)), this, SLOT(screenshotActionTriggered(QAction *)));
// Duplicated for the screenshot button :(
QAction *uploadAction = new QAction(os::icon("imgur"), tr("&Upload last"), mTrayIcon);
uploadAction->setToolTip(tr("Upload the last screenshot you took to imgur.com"));
connect(uploadAction, SIGNAL(triggered()), this, SLOT(uploadLast()));
QAction *cancelAction = new QAction(os::icon("no"), tr("&Cancel upload"), mTrayIcon);
cancelAction->setToolTip(tr("Cancel the currently uploading screenshots"));
cancelAction->setEnabled(false);
connect(this, SIGNAL(uploading(bool)), cancelAction, SLOT(setEnabled(bool)));
connect(cancelAction, SIGNAL(triggered()), this, SLOT(uploadCancel()));
QAction *historyAction = new QAction(os::icon("view-history"), tr("View History"), mTrayIcon);
connect(historyAction, SIGNAL(triggered()), this, SLOT(showHistoryDialog()));
//
QAction *optionsAction = new QAction(os::icon("configure"), tr("View &Options"), mTrayIcon);
connect(optionsAction, SIGNAL(triggered()), this, SLOT(showOptions()));
QAction *goAction = new QAction(os::icon("folder"), tr("&Go to Folder"), mTrayIcon);
connect(goAction, SIGNAL(triggered()), this, SLOT(goToFolder()));
QAction *quitAction = new QAction(tr("&Quit"), mTrayIcon);
connect(quitAction, SIGNAL(triggered()), this, SLOT(quit()));
QMenu *screenshotMenu = new QMenu(tr("Screenshot"));
screenshotMenu->addAction(screenAction);
screenshotMenu->addAction(areaAction);
screenshotMenu->addAction(windowAction);
screenshotMenu->addAction(windowPickerAction);
// Duplicated for the screenshot button :(
QMenu *imgurMenu = new QMenu(tr("Upload"));
imgurMenu->addAction(uploadAction);
imgurMenu->addAction(cancelAction);
imgurMenu->addAction(historyAction);
imgurMenu->addSeparator();
QMenu *trayIconMenu = new QMenu;
trayIconMenu->addAction(hideAction);
trayIconMenu->addSeparator();
trayIconMenu->addMenu(imgurMenu);
trayIconMenu->addSeparator();
trayIconMenu->addMenu(screenshotMenu);
trayIconMenu->addAction(optionsAction);
trayIconMenu->addAction(goAction);
trayIconMenu->addSeparator();
trayIconMenu->addAction(quitAction);
mTrayIcon->setContextMenu(trayIconMenu);
}
void LightscreenWindow::setStatus(QString status)
{
if (status.isEmpty()) {
status = tr("Lightscreen");
} else {
status += tr(" - Lightscreen");
}
if (mTrayIcon) {
mTrayIcon->setToolTip(status);
}
setWindowTitle(status);
}
QSettings *LightscreenWindow::settings() const
{
return ScreenshotManager::instance()->settings();
}
// Event handling
bool LightscreenWindow::event(QEvent *event)
{
if (event->type() == QEvent::Show) {
QPoint savedPosition = settings()->value("position").toPoint();
if (!savedPosition.isNull() && qApp->desktop()->availableGeometry().contains(QRect(savedPosition, size()))) {
move(savedPosition);
}
if (mHasTaskbarButton) {
mTaskbarButton->setWindow(windowHandle());
}
} else if (event->type() == QEvent::Hide) {
settings()->setValue("position", pos());
} else if (event->type() == QEvent::Close) {
if (settings()->value("options/tray").toBool() && settings()->value("options/closeHide").toBool()) {
closeToTrayWarning();
hide();
} else if (settings()->value("options/closeHide").toBool()) {
if (closingWithoutTray()) {
hide();
}
} else {
quit();
}
} else if (event->type() == QEvent::KeyPress) {
QKeyEvent *keyEvent = static_cast<QKeyEvent *>(event);
#ifdef Q_WS_MAC
if (keyEvent->modifiers() == Qt::ControlModifier && e->key() == Qt::Key_Period) {
keyEvent->ignore();
if (isVisible()) {
toggleVisibility();
}
return false;
} else
#endif
if (!keyEvent->modifiers() && keyEvent->key() == Qt::Key_Escape) {
keyEvent->ignore();
if (isVisible()) {
toggleVisibility();
}
return false;
}
} else if (event->type() == QEvent::LanguageChange) {
ui.retranslateUi(this);
resize(minimumSizeHint());
}
return QMainWindow::event(event);
}
diff --git a/tools/SingleApplication b/tools/SingleApplication
index bc0ffb5..c6378ee 160000
--- a/tools/SingleApplication
+++ b/tools/SingleApplication
@@ -1 +1 @@
-Subproject commit bc0ffb564ae541556815bb0371e362a638b81914
+Subproject commit c6378eec45a5fdf699b4d27fb4be22a190b2a184
diff --git a/tools/os.cpp b/tools/os.cpp
index a0cdce9..e7cfd48 100644
--- a/tools/os.cpp
+++ b/tools/os.cpp
@@ -1,381 +1,380 @@
/*
* Copyright (C) 2016 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 <QBitmap>
#include <QDesktopServices>
#include <QDesktopWidget>
#include <QDialog>
#include <QDir>
#include <QGraphicsDropShadowEffect>
#include <QIcon>
#include <QLibrary>
#include <QLocale>
#include <QMessageBox>
#include <QPixmap>
#include <QPointer>
#include <QProcess>
#include <QSettings>
#include <QTextEdit>
#include <QTimeLine>
#include <QTimer>
#include <QUrl>
#include <QWidget>
#include <string>
#include <QMessageBox>
#include <QPainter>
#ifdef Q_OS_WIN
#include <QtWin>
#include <qt_windows.h>
#include <shlobj.h>
// Define for MinGW
#ifndef SM_CXPADDEDBORDER
#define SM_CXPADDEDBORDER 92
#endif
#elif defined(Q_OS_LINUX)
#include <QX11Info>
#include <X11/X.h>
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <X11/Xatom.h>
#endif
#include "os.h"
QPixmap os::cursor()
{
#ifdef Q_OS_WIN
/*
* Taken from: git://github.com/arrai/mumble-record.git > src > mumble > Overlay.cpp
* BSD License.
*/
QPixmap pixmap;
CURSORINFO cursorInfo;
cursorInfo.cbSize = sizeof(cursorInfo);
::GetCursorInfo(&cursorInfo);
HICON cursor = cursorInfo.hCursor;
ICONINFO iconInfo;
::GetIconInfo(cursor, &iconInfo);
ICONINFO info;
ZeroMemory(&info, sizeof(info));
if (::GetIconInfo(cursor, &info)) {
if (info.hbmColor) {
pixmap = QtWin::fromHBITMAP(info.hbmColor, QtWin::HBitmapAlpha);
} else {
QBitmap orig(QtWin::fromHBITMAP(info.hbmMask));
QImage img = orig.toImage();
int h = img.height() / 2;
int w = img.bytesPerLine() / sizeof(quint32);
QImage out(img.width(), h, QImage::Format_MonoLSB);
QImage outmask(img.width(), h, QImage::Format_MonoLSB);
for (int i = 0; i < h; ++i) {
const quint32 *srcimg = reinterpret_cast<const quint32 *>(img.scanLine(i + h));
const quint32 *srcmask = reinterpret_cast<const quint32 *>(img.scanLine(i));
quint32 *dstimg = reinterpret_cast<quint32 *>(out.scanLine(i));
quint32 *dstmask = reinterpret_cast<quint32 *>(outmask.scanLine(i));
for (int j = 0; j < w; ++j) {
dstmask[j] = srcmask[j];
dstimg[j] = srcimg[j];
}
}
pixmap = QBitmap::fromImage(out, Qt::ColorOnly);
}
if (info.hbmMask) {
::DeleteObject(info.hbmMask);
}
if (info.hbmColor) {
::DeleteObject(info.hbmColor);
}
}
return pixmap;
#else
return QPixmap();
#endif
}
void os::effect(QObject *target, const char *slot, int frames, int duration, const char *cleanup)
{
QTimeLine *timeLine = new QTimeLine(duration);
timeLine->setFrameRange(0, frames);
timeLine->connect(timeLine, SIGNAL(frameChanged(int)), target, slot);
if (cleanup != 0) {
timeLine->connect(timeLine, SIGNAL(finished()), target, SLOT(cleanup()));
}
timeLine->connect(timeLine, SIGNAL(finished()), timeLine, SLOT(deleteLater()));
timeLine->start();
}
QString os::getDocumentsPath()
{
#ifdef Q_OS_WIN
TCHAR szPath[MAX_PATH];
if (SUCCEEDED(SHGetFolderPath(NULL,
CSIDL_PERSONAL | CSIDL_FLAG_CREATE,
NULL,
0,
szPath))) {
std::wstring path(szPath);
return QString::fromWCharArray(path.c_str());
}
return QDir::homePath() + QDir::separator() + "My Documents";
#else
return QDir::homePath() + QDir::separator() + "Documents";
#endif
}
QPixmap os::grabWindow(WId winId)
{
#ifdef Q_OS_WIN
RECT rcWindow;
HWND hwndId = (HWND)winId;
GetWindowRect(hwndId, &rcWindow);
int margin = GetSystemMetrics(SM_CXSIZEFRAME) + GetSystemMetrics(SM_CXPADDEDBORDER) / 2;
rcWindow.right -= margin;
rcWindow.left += margin;
if (IsZoomed(hwndId)) {
rcWindow.top += margin;
} else {
rcWindow.top += GetSystemMetrics(SM_CXPADDEDBORDER);
}
rcWindow.bottom -= margin;
int width, height;
width = rcWindow.right - rcWindow.left;
height = rcWindow.bottom - rcWindow.top;
RECT rcScreen;
GetWindowRect(GetDesktopWindow(), &rcScreen);
RECT rcResult;
UnionRect(&rcResult, &rcWindow, &rcScreen);
QPixmap pixmap;
// Comparing the rects to determine if the window is outside the boundaries of the screen,
// the window DC method has the disadvantage that it does not show Aero glass transparency,
// so we'll avoid it for the screenshots that don't need it.
HDC hdcMem;
HBITMAP hbmCapture;
if (EqualRect(&rcScreen, &rcResult)) {
// Grabbing the window from the Screen DC.
HDC hdcScreen = GetDC(NULL);
BringWindowToTop(hwndId);
hdcMem = CreateCompatibleDC(hdcScreen);
hbmCapture = CreateCompatibleBitmap(hdcScreen, width, height);
SelectObject(hdcMem, hbmCapture);
BitBlt(hdcMem, 0, 0, width, height, hdcScreen, rcWindow.left, rcWindow.top, SRCCOPY);
} else {
// Grabbing the window by its own DC
HDC hdcWindow = GetWindowDC(hwndId);
hdcMem = CreateCompatibleDC(hdcWindow);
hbmCapture = CreateCompatibleBitmap(hdcWindow, width, height);
SelectObject(hdcMem, hbmCapture);
BitBlt(hdcMem, 0, 0, width, height, hdcWindow, 0, 0, SRCCOPY);
}
ReleaseDC(hwndId, hdcMem);
DeleteDC(hdcMem);
pixmap = QtWin::fromHBITMAP(hbmCapture);
DeleteObject(hbmCapture);
return pixmap;
-
#else
return QPixmap::grabWindow(winId);
#endif
}
void os::setForegroundWindow(QWidget *window)
{
#ifdef Q_OS_WIN
ShowWindow((HWND)window->winId(), SW_RESTORE);
SetForegroundWindow((HWND)window->winId());
#else
Q_UNUSED(window)
#endif
}
void os::setStartup(bool startup, bool hide)
{
QString lightscreen = QDir::toNativeSeparators(qApp->applicationFilePath());
if (hide) {
lightscreen.append(" -h");
}
#ifdef Q_OS_WIN
// Windows startup settings
QSettings init("Microsoft", "Windows");
init.beginGroup("CurrentVersion");
init.beginGroup("Run");
if (startup) {
init.setValue("Lightscreen", lightscreen);
} else {
init.remove("Lightscreen");
}
init.endGroup();
init.endGroup();
#endif
#if defined(Q_OS_LINUX)
QFile desktopFile(QDir::homePath() + "/.config/autostart/lightscreen.desktop");
desktopFile.remove();
if (startup) {
desktopFile.open(QIODevice::WriteOnly);
desktopFile.write(QString("[Desktop Entry]\nExec=%1\nType=Application").arg(lightscreen).toLatin1());
}
#endif
}
-QGraphicsEffect *os::shadow(QColor color, int blurRadius, int offset)
+QGraphicsEffect *os::shadow(const QColor &color, int blurRadius, int offset)
{
QGraphicsDropShadowEffect *shadowEffect = new QGraphicsDropShadowEffect;
shadowEffect->setBlurRadius(blurRadius);
shadowEffect->setOffset(offset);
shadowEffect->setColor(color);
return shadowEffect;
}
QIcon os::icon(const QString &name, QColor backgroundColor)
{
if (!backgroundColor.isValid()) {
backgroundColor = qApp->palette().color(QPalette::Button);
}
if (backgroundColor.value() > 125) {
return QIcon(":/icons/" + name);
} else {
return QIcon(":/icons/inv/" + name);
}
}
#ifdef Q_OS_LINUX
// Taken from KSnapshot. Oh KDE, what would I do without you :D
Window os::findRealWindow(Window w, int depth)
{
if (depth > 5) {
return None;
}
static Atom wm_state = XInternAtom(QX11Info::display(), "WM_STATE", False);
Atom type;
int format;
unsigned long nitems, after;
unsigned char *prop;
if (XGetWindowProperty(QX11Info::display(), w, wm_state, 0, 0, False, AnyPropertyType,
&type, &format, &nitems, &after, &prop) == Success) {
if (prop != NULL) {
XFree(prop);
}
if (type != None) {
return w;
}
}
Window root, parent;
Window *children;
unsigned int nchildren;
Window ret = None;
if (XQueryTree(QX11Info::display(), w, &root, &parent, &children, &nchildren) != 0) {
for (unsigned int i = 0;
i < nchildren && ret == None;
++i) {
ret = os::findRealWindow(children[ i ], depth + 1);
}
if (children != NULL) {
XFree(children);
}
}
return ret;
}
Window os::windowUnderCursor(bool includeDecorations)
{
Window root;
Window child;
uint mask;
int rootX, rootY, winX, winY;
XQueryPointer(QX11Info::display(), QX11Info::appRootWindow(), &root, &child,
&rootX, &rootY, &winX, &winY, &mask);
if (child == None) {
child = QX11Info::appRootWindow();
}
if (!includeDecorations) {
Window real_child = os::findRealWindow(child);
if (real_child != None) { // test just in case
child = real_child;
}
}
return child;
}
#endif
diff --git a/tools/os.h b/tools/os.h
index ce90d95..afc653a 100644
--- a/tools/os.h
+++ b/tools/os.h
@@ -1,69 +1,69 @@
/*
* Copyright (C) 2016 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 OS_H_
#define OS_H_
#include <QWidget>
class QPixmap;
class QPoint;
class QString;
class QUrl;
class QGraphicsEffect;
class QIcon;
#if defined(Q_OS_LINUX)
typedef unsigned long XID;
typedef XID Window;
#endif
namespace os {
// Returns the cursor pixmap in Windows
QPixmap cursor();
// A QTimeLine based effect for a slot (TODO: look at the new effect classes)
void effect(QObject *target, const char *slot, int frames, int duration = 400, const char *cleanup = 0);
// Returns the current users's Documents/My Documents folder
QString getDocumentsPath();
// Returns the pixmap of the given window id.
QPixmap grabWindow(WId winId);
// Set the target window as the foreground window (Windows only)
void setForegroundWindow(QWidget *window);
// Adds lightscreen to the startup list in Windows & Linux (KDE, Gnome and Xfce for now).
void setStartup(bool startup, bool hide);
// Creates a new QGraphicsDropShadowEffect to apply to widgets.
-QGraphicsEffect *shadow(QColor color = Qt::black, int blurRadius = 6, int offset = 1);
+QGraphicsEffect *shadow(const QColor &color = Qt::black, int blurRadius = 6, int offset = 1);
// Returns a QIcon for the given icon name (taking into account color schemes and whatnot).
QIcon icon(const QString &name, QColor backgroundColor = QColor());
// X11-specific functions for the Window Picker
#if defined(Q_OS_LINUX)
Window findRealWindow(Window w, int depth = 0);
Window windowUnderCursor(bool includeDecorations = true);
#endif
}
#endif /*OS_H_*/
diff --git a/tools/screenshot.cpp b/tools/screenshot.cpp
index 096bac3..9a9fda2 100644
--- a/tools/screenshot.cpp
+++ b/tools/screenshot.cpp
@@ -1,487 +1,487 @@
/*
* Copyright (C) 2016 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 "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()
{
// Here be crickets
}
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.
- foreach (QString file, directory.entryList(QDir::Files)) {
+ 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;
}
QString &Screenshot::unloadedFileName()
{
return mUnloadFilename;
}
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::Fail;
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();
- foreach (QString file, QFileInfo(name + extension()).dir().entryList(QDir::Files)) {
+ 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.imgurClipboard)) {
if (mUnloaded) {
mUnloaded = false;
mPixmap = QPixmap(mUnloadFilename);
}
QApplication::clipboard()->setPixmap(mPixmap, QClipboard::Clipboard);
if (!mOptions.file) {
result = (Screenshot::Result)1;
}
}
// In the following code I use (Screenshot::Result)1 instead of Screenshot::Success because of some weird issue with the X11 headers. //TODO
if (mOptions.file) {
fileName = name + extension();
if (name.isEmpty()) {
result = Screenshot::Cancel;
} else if (mUnloaded) {
result = (QFile::rename(mUnloadFilename, fileName)) ? (Screenshot::Result)1 : Screenshot::Fail;
} else if (mPixmap.save(fileName, 0, mOptions.quality)) {
result = (Screenshot::Result)1;
} else {
result = Screenshot::Fail;
}
}
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);
} else if (unloadPixmap()) {
Uploader::instance()->upload(mUnloadFilename);
} else {
emit finished();
}
}
void Screenshot::uploadDone(const QString &url)
{
if (mOptions.imgurClipboard && !url.isEmpty()) {
QApplication::clipboard()->setText(url, QClipboard::Clipboard);
}
emit finished();
}
//
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
}
QString Screenshot::extension() const
{
switch (mOptions.format) {
case Screenshot::PNG:
return ".png";
break;
case Screenshot::BMP:
return ".bmp";
break;
case Screenshot::JPEG:
default:
return ".jpg";
break;
}
}
void Screenshot::grabDesktop()
{
QRect geometry;
if (mOptions.currentMonitor) {
geometry = QApplication::primaryScreen()->geometry();
} else {
- foreach (QScreen *screen, QGuiApplication::screens()) {
+ for (QScreen *screen : QGuiApplication::screens()) {
geometry = geometry.united(screen->geometry());
}
}
mPixmap = QApplication::primaryScreen()->grabWindow(QApplication::desktop()->winId(), geometry.x(), geometry.y(), geometry.width(), geometry.height());
if (mOptions.cursor && !mPixmap.isNull()) {
QPainter painter(&mPixmap);
painter.drawPixmap(QCursor::pos(), os::cursor());
}
mPixmap.setDevicePixelRatio(QApplication::desktop()->devicePixelRatio());
}
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 = mOptions.directory.path() + QDir::separator() + QString(".lstemp.%1%2").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/screenshotmanager.cpp b/tools/screenshotmanager.cpp
index 770c896..713e4f6 100644
--- a/tools/screenshotmanager.cpp
+++ b/tools/screenshotmanager.cpp
@@ -1,215 +1,230 @@
/*
* Copyright (C) 2016 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 "screenshotmanager.h"
#include "screenshot.h"
#include "uploader/uploader.h"
#include <QApplication>
#include <QDateTime>
#include <QStandardPaths>
#include <QFile>
#include <QSettings>
#include <QtSql/QSqlDatabase>
#include <QtSql/QSqlError>
#include <QtSql/QSqlQuery>
#include <QtSql/QSqlRecord>
-ScreenshotManager::ScreenshotManager(QObject *parent) : QObject(parent)
+ScreenshotManager::ScreenshotManager(QObject *parent) : QObject(parent), mHistoryInitialized(false)
{
if (QFile::exists(qApp->applicationDirPath() + QDir::separator() + "config.ini")) {
- mSettings = new QSettings(qApp->applicationDirPath() + QDir::separator() + "config.ini", QSettings::IniFormat);
+ mSettings = new QSettings(qApp->applicationDirPath() + QDir::separator() + "config.ini", QSettings::IniFormat, this);
mPortableMode = true;
mHistoryPath = qApp->applicationDirPath() + QDir::separator();
} else {
- mSettings = new QSettings();
+ mSettings = new QSettings(this);
mPortableMode = false;
mHistoryPath = QStandardPaths::writableLocation(QStandardPaths::DataLocation) + QDir::separator();
}
- initHistory();
-
connect(Uploader::instance(), SIGNAL(done(QString, QString, QString)), this, SLOT(uploadDone(QString, QString, QString)));
}
-ScreenshotManager::~ScreenshotManager()
-{
- delete mSettings;
-}
-
void ScreenshotManager::initHistory()
{
+ if (mHistoryInitialized) {
+ return;
+ }
+
// Creating the SQLite database.
QSqlDatabase history = QSqlDatabase::addDatabase("QSQLITE");
QDir hp(mHistoryPath);
if (!hp.exists()) {
hp.mkpath(mHistoryPath);
}
history.setHostName("localhost");
history.setDatabaseName(mHistoryPath + "history.sqlite");
if (history.open()) {
history.exec("CREATE TABLE IF NOT EXISTS history (fileName text, URL text, deleteURL text, time integer)");
+ mHistoryInitialized = true;
} else {
qCritical() << "Could not open SQLite DB.";
}
}
int ScreenshotManager::activeCount() const
{
return mScreenshots.count();
}
bool ScreenshotManager::portableMode()
{
return mPortableMode;
}
void ScreenshotManager::saveHistory(const QString &fileName, const QString &url, const QString &deleteHash)
{
if (!mSettings->value("/options/history", true).toBool()) {
return;
}
+ if (!mHistoryInitialized) {
+ initHistory();
+ }
+
QString deleteUrl;
if (!deleteHash.isEmpty()) {
deleteUrl = "https://imgur.com/delete/" + deleteHash;
}
QSqlQuery query;
query.prepare("INSERT INTO history (fileName, URL, deleteURL, time) VALUES(?, ?, ?, ?)");
query.addBindValue(fileName);
query.addBindValue(url);
query.addBindValue(deleteUrl);
query.addBindValue(QDateTime::currentMSecsSinceEpoch());
query.exec();
}
void ScreenshotManager::updateHistory(const QString &fileName, const QString &url, const QString &deleteHash)
{
if (!mSettings->value("/options/history", true).toBool() || url.isEmpty()) {
return;
}
+ if (!mHistoryInitialized) {
+ initHistory();
+ }
+
QSqlQuery query;
query.prepare("SELECT fileName FROM history WHERE URL IS NOT EMPTY AND fileName = ?");
query.addBindValue(fileName);
query.exec();
if (query.record().count() > 0) {
QSqlQuery updateQuery;
updateQuery.prepare("UPDATE history SET URL = ?, deleteURL = ?, time = ? WHERE fileName = ?");
updateQuery.addBindValue(url);
updateQuery.addBindValue("https://imgur.com/delete/" + deleteHash);
updateQuery.addBindValue(QDateTime::currentMSecsSinceEpoch());
updateQuery.addBindValue(fileName);
updateQuery.exec();
} else {
saveHistory(fileName, url, deleteHash);
}
}
void ScreenshotManager::removeHistory(const QString &fileName, qint64 time)
{
+ if (!mHistoryInitialized) {
+ initHistory();
+ }
+
QSqlQuery removeQuery;
removeQuery.prepare("DELETE FROM history WHERE fileName = ? AND time = ?");
removeQuery.addBindValue(fileName);
removeQuery.addBindValue(time);
removeQuery.exec();
}
void ScreenshotManager::clearHistory()
{
- QSqlQuery clearQuery("DROP TABLE history");
- clearQuery.exec();
+ if (!mHistoryInitialized) {
+ initHistory();
+ }
+
+ QSqlQuery deleteQuery("DELETE FROM history");
+ deleteQuery.exec();
- initHistory();
+ QSqlQuery vacQuery("VACUUM");
+ vacQuery.exec();
}
//
void ScreenshotManager::askConfirmation()
{
Screenshot *s = qobject_cast<Screenshot *>(sender());
emit confirm(s);
}
void ScreenshotManager::cleanup()
{
Screenshot *screenshot = qobject_cast<Screenshot *>(sender());
emit windowCleanup(screenshot->options());
}
void ScreenshotManager::finished()
{
Screenshot *screenshot = qobject_cast<Screenshot *>(sender());
mScreenshots.removeOne(screenshot);
emit activeCountChange();
screenshot->deleteLater();
}
void ScreenshotManager::take(Screenshot::Options &options)
{
Screenshot *newScreenshot = new Screenshot(this, options);
mScreenshots.append(newScreenshot);
connect(newScreenshot, SIGNAL(askConfirmation()), this, SLOT(askConfirmation()));
connect(newScreenshot, SIGNAL(cleanup()) , this, SLOT(cleanup()));
connect(newScreenshot, SIGNAL(finished()) , this, SLOT(finished()));
newScreenshot->take();
}
void ScreenshotManager::uploadDone(const QString &fileName, const QString &url, const QString &deleteHash)
{
- foreach (Screenshot *screenshot, mScreenshots) {
+ for (Screenshot *screenshot : qAsConst(mScreenshots)) {
if (screenshot->options().fileName == fileName
|| screenshot->unloadedFileName() == fileName) {
screenshot->uploadDone(url);
if (screenshot->options().file) {
updateHistory(fileName, url, deleteHash);
} else {
saveHistory("", url, deleteHash);
}
return;
}
}
// If we get here, it's because the screenshot upload wasn't on the current screenshot list, which means it's a View History/Upload Later upload.
updateHistory(fileName, url, deleteHash);
}
// Singleton
ScreenshotManager *ScreenshotManager::mInstance = 0;
ScreenshotManager *ScreenshotManager::instance()
{
if (!mInstance) {
mInstance = new ScreenshotManager();
}
return mInstance;
}
diff --git a/tools/screenshotmanager.h b/tools/screenshotmanager.h
index e071020..f31c53b 100644
--- a/tools/screenshotmanager.h
+++ b/tools/screenshotmanager.h
@@ -1,73 +1,73 @@
/*
* Copyright (C) 2016 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 SCREENSHOTMANAGER_H
#define SCREENSHOTMANAGER_H
#include <QObject>
#include <QList>
#include "screenshot.h"
class QSettings;
class ScreenshotManager : public QObject
{
Q_OBJECT
public:
enum State {
Idle = 0,
Busy = 1,
Disabled = 2
};
public:
ScreenshotManager(QObject *parent = 0);
- ~ScreenshotManager();
static ScreenshotManager *instance();
void initHistory();
int activeCount() const;
bool portableMode();
void saveHistory(const QString &fileName, const QString &url = "", const QString &deleteHash = "");
void updateHistory(const QString &fileName, const QString &url, const QString &deleteHash);
void removeHistory(const QString &fileName, qint64 time);
void clearHistory();
QSettings *settings() const { return mSettings; }
public slots:
void askConfirmation();
void cleanup();
void finished();
void take(Screenshot::Options &options);
void uploadDone(const QString &fileName, const QString &url, const QString &deleteHash);
signals:
void confirm(Screenshot *screenshot);
void windowCleanup(Screenshot::Options &options);
void activeCountChange();
private:
static ScreenshotManager *mInstance;
QList<Screenshot*> mScreenshots;
QSettings *mSettings;
QString mHistoryPath;
bool mPortableMode;
+ bool mHistoryInitialized;
};
#endif // SCREENSHOTMANAGER_H
diff --git a/tools/uploader/uploader.cpp b/tools/uploader/uploader.cpp
index 508d663..25ec90e 100644
--- a/tools/uploader/uploader.cpp
+++ b/tools/uploader/uploader.cpp
@@ -1,204 +1,204 @@
/*
* Copyright (C) 2016 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 "uploader.h"
#include "../screenshotmanager.h"
#include "imguruploader.h"
#include <QtNetwork>
#include <QSettings>
Uploader *Uploader::mInstance = 0;
Uploader::Uploader(QObject *parent) : QObject(parent), mProgress(0)
{
mNetworkAccessManager = new QNetworkAccessManager(this);
}
Uploader *Uploader::instance()
{
if (!mInstance) {
mInstance = new Uploader();
}
return mInstance;
}
int Uploader::progress() const
{
return mProgress;
}
QNetworkAccessManager *Uploader::nam()
{
return mNetworkAccessManager;
}
QString Uploader::lastUrl() const
{
return mLastUrl;
}
void Uploader::cancel()
{
mUploaders.clear();
mProgress = 0;
emit cancelAll();
}
void Uploader::upload(const QString &fileName)
{
if (fileName.isEmpty()) {
return;
}
QVariantHash options;
QSettings *s = ScreenshotManager::instance()->settings();
options["type"] = "imgur";
options["networkManager"].setValue(mNetworkAccessManager);
options["anonymous"] = s->value("upload/imgur/anonymous", true).toBool();
options["album"] = s->value("upload/imgur/album", "").toString();
options["access_token"] = s->value("upload/imgur/access_token", "").toString();
options["refresh_token"] = s->value("upload/imgur/refresh_token", "").toString();
if (options["access_token"].toString().isEmpty() || options["refresh_token"].toString().isEmpty()) {
options["anonymous"] = true;
}
ImgurUploader *uploader = new ImgurUploader(options);
connect(uploader, &ImgurUploader::uploaded , this, &Uploader::uploaded);
connect(uploader, &ImgurUploader::error , this, &Uploader::uploaderError);
connect(uploader, &ImgurUploader::progressChange , this, &Uploader::progressChange);
connect(uploader, &ImgurUploader::needAuthRefresh, this, &Uploader::imgurAuthRefresh);
connect(this , SIGNAL(cancelAll()), uploader, SLOT(cancel()));
uploader->upload(fileName);
mUploaders.append(uploader);
}
void Uploader::uploaded(const QString &file, const QString &url, const QString &deleteHash)
{
mLastUrl = url;
mUploaders.removeAll(qobject_cast<ImageUploader *>(sender()));
if (mUploaders.isEmpty()) {
mProgress = 0;
}
sender()->deleteLater();
emit done(file, url, deleteHash);
}
void Uploader::imgurAuthRefresh()
{
for (int i = 0; i < mUploaders.size(); ++i) {
if (mUploaders[i]->options().value("type") == "imgur") {
mUploaders[i]->cancel();
}
}
QByteArray parameters;
parameters.append(QString("refresh_token=").toUtf8());
parameters.append(QUrl::toPercentEncoding(ScreenshotManager::instance()->settings()->value("upload/imgur/refresh_token").toString()));
parameters.append(QString("&client_id=").toUtf8());
parameters.append(QUrl::toPercentEncoding("3ebe94c791445c1"));
parameters.append(QString("&client_secret=").toUtf8());
parameters.append(QUrl::toPercentEncoding("0546b05d6a80b2092dcea86c57b792c9c9faebf0")); // TODO: TA.png
parameters.append(QString("&grant_type=refresh_token").toUtf8());
QNetworkRequest request(QUrl("https://api.imgur.com/oauth2/token"));
request.setHeader(QNetworkRequest::ContentTypeHeader, "application/x-www-form-urlencoded");
QNetworkReply *reply = Uploader::instance()->nam()->post(request, parameters);
connect(reply, SIGNAL(finished()), this, SLOT(imgurToken()));
}
void Uploader::imgurToken()
{
QNetworkReply *reply = qobject_cast<QNetworkReply *>(sender());
if (reply->error() != QNetworkReply::NoError) {
emit error(reply->errorString());
return;
}
QJsonObject imgurResponse = QJsonDocument::fromJson(reply->readAll()).object();
QSettings *s = ScreenshotManager::instance()->settings();
s->setValue("upload/imgur/access_token" , imgurResponse["access_token"].toString());
s->setValue("upload/imgur/refresh_token" , imgurResponse["refresh_token"].toString());
s->setValue("upload/imgur/account_username", imgurResponse["account_username"].toString());
s->setValue("upload/imgur/expires_in" , imgurResponse["expires_in"].toString());
- foreach (ImageUploader *uploader, mUploaders) {
+ for (ImageUploader *uploader : qAsConst(mUploaders)) {
if (uploader->options().value("type") == "imgur") {
uploader->options().remove("access_token");
uploader->options().remove("refresh_token");
uploader->options().insert("access_token" , imgurResponse["access_token"].toString());
uploader->options().insert("refresh_token", imgurResponse["refresh_token"].toString());
uploader->retry();
}
}
emit imgurAuthRefreshed();
}
void Uploader::uploaderError(ImageUploader::Error code, QString errorString, QString fileName)
{
mUploaders.removeAll(qobject_cast<ImageUploader *>(sender()));
sender()->deleteLater();
mProgress = 0;
if (code != ImageUploader::CancelError) {
if (errorString.isEmpty()) {
emit error(tr("Upload Error ") + code);
} else {
emit error(errorString);
}
}
emit done(fileName, "", "");
}
int Uploader::uploading()
{
return mUploaders.count();
}
void Uploader::progressChange(int p)
{
if (mUploaders.size() <= 0) {
mProgress = p;
emit progress(p);
return;
}
int totalProgress = 0;
for (int i = 0; i < mUploaders.size(); ++i) {
totalProgress += mUploaders[i]->progress();
}
mProgress = totalProgress / mUploaders.size();
emit progress(mProgress);
}
diff --git a/updater/updater.cpp b/updater/updater.cpp
index d0d7693..4a4142d 100644
--- a/updater/updater.cpp
+++ b/updater/updater.cpp
@@ -1,64 +1,62 @@
/*
* Copyright (C) 2016 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 "updater.h"
#include "../dialogs/updaterdialog.cpp"
Updater::Updater(QObject *parent) :
QObject(parent)
{
connect(&mNetwork, SIGNAL(finished(QNetworkReply *)), this, SLOT(finished(QNetworkReply *)));
}
void Updater::check()
{
- QString platform = "unknown";
-
#ifdef Q_OS_WIN
- platform = QString("Windows_%1").arg(QSysInfo::WindowsVersion);
+ QString platform = QString("Windows_%1").arg(QSysInfo::WindowsVersion);
#else
- platform = "Linux";
+ QString platform = QSysInfo::productType();
#endif
- QNetworkRequest request(QUrl("https://lightscreen.com.ar/version?from=" + qApp->applicationVersion() + "&platform=" + platform));
+ QNetworkRequest request(QUrl::fromUserInput("https://lightscreen.com.ar/version?from=" + qApp->applicationVersion() + "&platform=" + platform));
mNetwork.get(request);
}
void Updater::checkWithFeedback()
{
UpdaterDialog updaterDialog;
connect(this, SIGNAL(done(bool)), &updaterDialog, SLOT(updateDone(bool)));
check();
updaterDialog.exec();
}
void Updater::finished(QNetworkReply *reply)
{
QByteArray data = reply->readAll();
double version = QString(data).toDouble();
emit done((version > qApp->applicationVersion().toDouble()));
}

File Metadata

Mime Type
text/x-diff
Expires
Tue, Jun 16, 1:44 AM (2 w, 13 h ago)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
71555
Default Alt Text
(198 KB)

Event Timeline