Page MenuHomePhabricator (Chris)

No OneTemporary

Authored By
Unknown
Size
160 KB
Referenced Files
None
Subscribers
None
diff --git a/dialogs/optionsdialog.cpp b/dialogs/optionsdialog.cpp
index 5e33b66..f7a7ef5 100644
--- a/dialogs/optionsdialog.cpp
+++ b/dialogs/optionsdialog.cpp
@@ -1,926 +1,789 @@
/*
* 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);
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();
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;
- }
-
- 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;
-
- 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.urlClipboardCheckBox->setChecked(settings()->value("urlClipboard", 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());
+ ui.uploadServiceComboBox->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());
+ ui.imgurOptions->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);
+ ui.imgurOptions->ui.imgurAuthUserLabel->setText(tr("<i>none</i>"));
+ ui.imgurOptions->ui.imgurAlbumComboBox->setEnabled(false);
+ ui.imgurOptions->ui.imgurRefreshAlbumButton->setEnabled(false);
} else {
- ui.imgurAuthButton->setText(tr("Deauthorize"));
- ui.imgurAuthUserLabel->setText("<b>" + ui.imgurAuthUserLabel->text() + "</b>");
- ui.imgurRefreshAlbumButton->setEnabled(true);
+ ui.imgurOptions->ui.imgurAuthButton->setText(tr("Deauthorize"));
+ ui.imgurOptions->ui.imgurAuthUserLabel->setText("<b>" + ui.imgurOptions->ui.imgurAuthUserLabel->text() + "</b>");
+ ui.imgurOptions->ui.imgurRefreshAlbumButton->setEnabled(true);
}
settings()->endGroup();
settings()->endGroup();
QMetaObject::invokeMethod(this, "updatePreview", Qt::QueuedConnection);
- QMetaObject::invokeMethod(this, "imgurRequestAlbumList", Qt::QueuedConnection);
+ QMetaObject::invokeMethod(ui.imgurOptions, "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("urlClipboard", ui.urlClipboardCheckBox->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()->setValue("service", ui.uploadServiceComboBox->currentIndex());
settings()->beginGroup("imgur");
- settings()->setValue("anonymous", !ui.imgurAuthGroupBox->isChecked());
- settings()->setValue("album" , ui.imgurAlbumComboBox->property("currentData").toString());
+ settings()->setValue("anonymous", settings()->value("account_username").toString().isEmpty());
+ settings()->setValue("album" , ui.imgurOptions->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.h b/dialogs/optionsdialog.h
index 2c5c39e..3a09510 100644
--- a/dialogs/optionsdialog.h
+++ b/dialogs/optionsdialog.h
@@ -1,73 +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 OPTIONSDIALOG_H
#define OPTIONSDIALOG_H
#include <QDialog>
#include "../updater/updater.h"
#include "ui_optionsdialog.h"
class QSettings;
class QAbstractButton;
class OptionsDialog : public QDialog
{
Q_OBJECT
public:
OptionsDialog(QWidget *parent = 0);
public slots:
void accepted();
void checkUpdatesNow();
void exportSettings();
- void imgurAlbumList();
- void imgurAuthorize();
- void imgurRequestAlbumList();
- void imgurToken();
void importSettings();
void loadSettings();
void openUrl(QString url);
void restoreDefaults();
void saveSettings();
void updatePreview();
void viewHistory();
protected:
bool event(QEvent *event);
#ifdef Q_OS_WIN
bool nativeEvent(const QByteArray &eventType, void *message, long *result);
#endif
private slots:
void browse();
void dialogButtonClicked(QAbstractButton *button);
void flipToggled(bool checked);
void init();
void namingOptions();
private:
bool hotkeyCollision();
QSettings *settings() const;
private:
Ui::OptionsDialog ui;
};
#endif // OPTIONSDIALOG_H
diff --git a/dialogs/optionsdialog.ui b/dialogs/optionsdialog.ui
index f418d53..3bf8bba 100644
--- a/dialogs/optionsdialog.ui
+++ b/dialogs/optionsdialog.ui
@@ -1,1491 +1,1463 @@
<?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">
+ <layout class="QVBoxLayout" name="verticalLayout_12">
<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">
+ <widget class="QCheckBox" name="urlClipboardCheckBox">
<property name="text">
- <string>After uploading, copy the imgur URL to the clipboard.</string>
+ <string>After uploading, copy the 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">
+ <layout class="QHBoxLayout" name="horizontalLayout">
+ <item>
+ <widget class="QLabel" name="uploadServiceLabel">
+ <property name="text">
+ <string>Service:</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QComboBox" name="uploadServiceComboBox">
+ <item>
<property name="text">
- <string>&lt;i&gt;none</string>
+ <string>Imgur</string>
</property>
- </widget>
- </item>
- </layout>
- </widget>
+ </item>
+ </widget>
+ </item>
+ <item>
+ <spacer name="horizontalSpacer_7">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>40</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ </layout>
</item>
<item>
- <widget class="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>
+ <widget class="QGroupBox" name="uploadServiceOptionsGroupBox">
+ <property name="title">
+ <string>Upload Service Options</string>
</property>
+ <layout class="QVBoxLayout" name="verticalLayout_11">
+ <property name="spacing">
+ <number>2</number>
+ </property>
+ <property name="leftMargin">
+ <number>4</number>
+ </property>
+ <property name="topMargin">
+ <number>4</number>
+ </property>
+ <property name="rightMargin">
+ <number>4</number>
+ </property>
+ <property name="bottomMargin">
+ <number>4</number>
+ </property>
+ <item>
+ <widget class="ImgurOptions" name="imgurOptions" native="true"/>
+ </item>
+ </layout>
</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>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;, with &lt;a href=&quot;#aboutqt&quot;&gt;Qt&lt;/a&gt;.</string>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
<property name="textInteractionFlags">
<set>Qt::LinksAccessibleByKeyboard|Qt::LinksAccessibleByMouse</set>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="licenseAboutLabel">
<property name="text">
<string>Released under the &lt;a href=&quot;http://www.gnu.org/licenses/gpl-2.0.html&quot;&gt;GNU General Public License&lt;/a&gt;.</string>
</property>
<property name="textInteractionFlags">
<set>Qt::LinksAccessibleByKeyboard|Qt::LinksAccessibleByMouse</set>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="versionLabel">
<property name="font">
<font>
<pointsize>12</pointsize>
<weight>75</weight>
<bold>true</bold>
</font>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="linksLabel">
<property name="text">
<string>&lt;a href=&quot;https://github.com/ckaiser/Lightscreen/&quot;&gt;GitHub page&lt;/a&gt;&lt;br&gt;&lt;br&gt;&lt;a href=&quot;https://lightscreen.com.ar/&quot;&gt;Lightscreen home page&lt;/a&gt;</string>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
<property name="textInteractionFlags">
<set>Qt::LinksAccessibleByKeyboard|Qt::LinksAccessibleByMouse</set>
</property>
</widget>
</item>
</layout>
</widget>
</widget>
</item>
<item>
<widget class="QDialogButtonBox" name="buttonBox">
<property name="standardButtons">
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
</property>
</widget>
</item>
</layout>
</widget>
<customwidgets>
<customwidget>
<class>HotkeyWidget</class>
<extends>QPushButton</extends>
<header location="global">widgets/hotkeywidget.h</header>
</customwidget>
+ <customwidget>
+ <class>ImgurOptions</class>
+ <extends>QWidget</extends>
+ <header location="global">widgets/imguroptions.h</header>
+ <container>1</container>
+ </customwidget>
</customwidgets>
<tabstops>
<tabstop>fileGroupBox</tabstop>
<tabstop>targetLineEdit</tabstop>
<tabstop>browsePushButton</tabstop>
<tabstop>prefixLineEdit</tabstop>
<tabstop>namingComboBox</tabstop>
<tabstop>namingOptionsButton</tabstop>
<tabstop>formatComboBox</tabstop>
<tabstop>qualitySlider</tabstop>
<tabstop>startupCheckBox</tabstop>
<tabstop>startupHideCheckBox</tabstop>
<tabstop>screenCheckBox</tabstop>
<tabstop>screenHotkeyWidget</tabstop>
<tabstop>areaCheckBox</tabstop>
<tabstop>areaHotkeyWidget</tabstop>
<tabstop>windowCheckBox</tabstop>
<tabstop>windowHotkeyWidget</tabstop>
<tabstop>windowPickerCheckBox</tabstop>
<tabstop>windowPickerHotkeyWidget</tabstop>
<tabstop>openCheckBox</tabstop>
<tabstop>openHotkeyWidget</tabstop>
<tabstop>directoryCheckBox</tabstop>
<tabstop>directoryHotkeyWidget</tabstop>
<tabstop>trayCheckBox</tabstop>
<tabstop>hideCheckBox</tabstop>
<tabstop>messageCheckBox</tabstop>
<tabstop>playSoundCheckBox</tabstop>
<tabstop>previewGroupBox</tabstop>
<tabstop>previewSizeSpinBox</tabstop>
<tabstop>previewPositionComboBox</tabstop>
<tabstop>previewAutocloseCheckBox</tabstop>
<tabstop>previewAutocloseTimeSpinBox</tabstop>
<tabstop>previewAutocloseActionComboBox</tabstop>
<tabstop>previewDefaultActionComboBox</tabstop>
<tabstop>saveAsCheckBox</tabstop>
<tabstop>currentMonitorCheckBox</tabstop>
<tabstop>cursorCheckBox</tabstop>
<tabstop>magnifyCheckBox</tabstop>
<tabstop>optiPngCheckBox</tabstop>
<tabstop>replaceCheckBox</tabstop>
<tabstop>areaAutocloseCheckBox</tabstop>
<tabstop>delaySpinBox</tabstop>
<tabstop>historyCheckBox</tabstop>
<tabstop>historyPushButton</tabstop>
<tabstop>updaterCheckBox</tabstop>
<tabstop>checkUpdatesPushButton</tabstop>
<tabstop>buttonBox</tabstop>
</tabstops>
<resources/>
<connections>
<connection>
<sender>buttonBox</sender>
<signal>rejected()</signal>
<receiver>OptionsDialog</receiver>
<slot>reject()</slot>
<hints>
<hint type="sourcelabel">
<x>307</x>
<y>304</y>
</hint>
<hint type="destinationlabel">
<x>286</x>
<y>274</y>
</hint>
</hints>
</connection>
<connection>
<sender>previewAutocloseCheckBox</sender>
<signal>toggled(bool)</signal>
<receiver>previewAutocloseTimeSpinBox</receiver>
<slot>setEnabled(bool)</slot>
<hints>
<hint type="sourcelabel">
<x>118</x>
<y>511</y>
</hint>
<hint type="destinationlabel">
<x>210</x>
<y>529</y>
</hint>
</hints>
</connection>
<connection>
<sender>previewAutocloseCheckBox</sender>
<signal>toggled(bool)</signal>
<receiver>previewAutocloseActionComboBox</receiver>
<slot>setEnabled(bool)</slot>
<hints>
<hint type="sourcelabel">
<x>115</x>
<y>511</y>
</hint>
<hint type="destinationlabel">
<x>302</x>
<y>529</y>
</hint>
</hints>
</connection>
</connections>
</ui>
diff --git a/lightscreen.pro b/lightscreen.pro
index f9ed505..1e310e7 100644
--- a/lightscreen.pro
+++ b/lightscreen.pro
@@ -1,92 +1,95 @@
TEMPLATE = app
TARGET = lightscreen
HEADERS += dialogs/areadialog.h \
dialogs/historydialog.h \
dialogs/namingdialog.h \
dialogs/optionsdialog.h \
dialogs/previewdialog.h \
dialogs/updaterdialog.h \
lightscreenwindow.h \
tools/os.h \
tools/screenshot.h \
tools/screenshotmanager.h \
tools/windowpicker.h \
updater/updater.h \
widgets/hotkeywidget.h \
tools/uploader/imageuploader.h \
tools/uploader/imguruploader.h \
- tools/uploader/uploader.h
+ tools/uploader/uploader.h \
+ widgets/imguroptions.h
SOURCES += dialogs/areadialog.cpp \
dialogs/historydialog.cpp \
dialogs/namingdialog.cpp \
dialogs/optionsdialog.cpp \
dialogs/previewdialog.cpp \
dialogs/updaterdialog.cpp \
lightscreenwindow.cpp \
main.cpp \
tools/os.cpp \
tools/screenshot.cpp \
tools/screenshotmanager.cpp \
tools/windowpicker.cpp \
updater/updater.cpp \
widgets/hotkeywidget.cpp \
tools/uploader/imageuploader.cpp \
tools/uploader/imguruploader.cpp \
- tools/uploader/uploader.cpp
+ tools/uploader/uploader.cpp \
+ widgets/imguroptions.cpp
FORMS += dialogs/historydialog.ui \
dialogs/namingdialog.ui \
dialogs/optionsdialog.ui \
- lightscreenwindow.ui
+ lightscreenwindow.ui \
+ widgets/imguroptions.ui
RESOURCES += lightscreen.qrc
CODECFORSRC = UTF-8
QT += core gui widgets network sql multimedia
include($$PWD/tools/SingleApplication/singleapplication.pri)
include($$PWD/tools/UGlobalHotkey/uglobalhotkey.pri)
windows {
QT += winextras
RC_ICONS += images/LS.ico
# MinGW
contains(QMAKE_CC, gcc){
LIBS += libgdi32 libgcc libuser32 libole32 libshell32 libshlwapi libcomctl32
QMAKE_CXXFLAGS = -Wextra -Wall -Wpointer-arith
}
# MSVC
contains(QMAKE_CC, cl){
LIBS += gdi32.lib user32.lib ole32.lib shell32.lib shlwapi.lib comctl32.lib
DEFINES += _ATL_XP_TARGETING
QMAKE_CFLAGS += /D _USING_V110_SDK71
QMAKE_CXXFLAGS += /D _USING_V110_SDK71
QMAKE_LFLAGS_WINDOWS += /SUBSYSTEM:WINDOWS,5.01
QMAKE_LFLAGS_WINDOWS += /MANIFESTUAC:level=\'asInvoker\'
QMAKE_LFLAGS_CONSOLE = /SUBSYSTEM:CONSOLE,5.01
}
CONFIG += embed_manifest_exe
#QMAKE_CXXFLAGS_DEBUG += /analyze /W3 /wd6326
}
unix:LIBS += -lX11
unix:QT += x11extras
include (version.pri)
OTHER_FILES += TODO.txt
diff --git a/lightscreenwindow.cpp b/lightscreenwindow.cpp
index 1530d19..488bd21 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() << "Unknown 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())); // TODO: Benchmark me
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;
}
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.urlClipboard = settings()->value("options/urlClipboard", 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>";
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) {
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)
{
mUpdater->deleteLater();
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);
}
}
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;
size_t i = 0;
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/screenshot.cpp b/tools/screenshot.cpp
index 9a9fda2..580bbd7 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.
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();
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 (mOptions.clipboard && !(mOptions.upload && mOptions.urlClipboard)) {
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()) {
+ if (mOptions.urlClipboard && !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 {
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/screenshot.h b/tools/screenshot.h
index cb097cc..ef5db3b 100644
--- a/tools/screenshot.h
+++ b/tools/screenshot.h
@@ -1,140 +1,140 @@
/*
* 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 SCREENSHOT_H
#define SCREENSHOT_H
#include <QObject>
#include <QDir>
#include <QPixmap>
class Screenshot : public QObject
{
Q_OBJECT
public:
enum Format {
PNG = 0,
JPEG = 1,
BMP = 2,
TIFF = 3
};
Q_ENUM(Format)
enum Naming {
Numeric = 0,
Date = 1,
Timestamp = 2,
Empty = 3
};
Q_ENUM(Naming)
enum Mode {
WholeScreen = 0,
ActiveWindow = 1,
SelectedArea = 2,
SelectedWindow = 3
};
Q_ENUM(Mode)
enum Result {
Fail = 0,
Success = 1,
Cancel = 2
};
Q_ENUM(Result)
struct NamingOptions {
Naming naming;
bool flip;
int leadingZeros;
QString dateFormat;
};
struct Options {
QString fileName;
Result result;
Format format;
NamingOptions namingOptions;
QDir directory;
QString prefix;
int mode;
int quality;
bool animations;
bool clipboard;
- bool imgurClipboard;
+ bool urlClipboard;
bool currentMonitor;
bool cursor;
bool file;
bool magnify;
bool optimize;
bool preview;
bool replace;
bool saveAs;
bool upload;
};
Screenshot(QObject *parent, Screenshot::Options options);
~Screenshot();
Screenshot::Options &options();
QPixmap &pixmap();
static QString getName(const NamingOptions &options, const QString &prefix, const QDir &directory);
QString &unloadedFileName();
public slots:
void confirm(bool result = true);
void confirmation();
void discard();
void markUpload();
void optimize();
void optimizationDone();
void save();
void setPixmap(const QPixmap &pixmap);
void take();
void upload();
void uploadDone(const QString &url);
signals:
void askConfirmation();
void cleanup();
void finished();
private:
void activeWindow();
QString extension() const;
void grabDesktop();
QString newFileName() const;
void selectedArea();
void selectedWindow();
bool unloadPixmap();
void wholeScreen();
private:
Screenshot::Options mOptions;
QPixmap mPixmap;
bool mPixmapDelay;
bool mUnloaded;
QString mUnloadFilename;
};
#endif // SCREENSHOT_H
diff --git a/tools/uploader/imageuploader.h b/tools/uploader/imageuploader.h
index 3c1dbba..1b125f8 100644
--- a/tools/uploader/imageuploader.h
+++ b/tools/uploader/imageuploader.h
@@ -1,46 +1,46 @@
#ifndef IMAGEUPLOADER_H
#define IMAGEUPLOADER_H
#include <QHash>
#include <QVariant>
class QNetworkReply;
class ImageUploader : public QObject
{
Q_OBJECT
public:
static ImageUploader *getNewUploader(const QString &name, const QVariantHash &options = QVariantHash());
enum Error {
FileError,
NetworkError,
HostError,
CancelError,
OtherError
};
Q_ENUM(Error)
public:
inline ImageUploader(const QVariantHash &options) : QObject(0), mOptions(options), mProgress(0) {}
- QVariantHash &options() { return mOptions; }
+ QVariantHash options() const { return mOptions; }
public slots:
virtual void upload(const QString &fileName) = 0;
virtual void cancel() = 0;
virtual void retry() = 0;
int progress() const { return mProgress; }
void setProgress(int progress) { mProgress = progress; }
signals:
void uploaded(QString, QString, QString);
void error(Error, QString, QString);
void progressChange(int);
protected:
QVariantHash mOptions;
int mProgress;
};
#endif // IMAGEUPLOADER_H
diff --git a/widgets/imguroptions.cpp b/widgets/imguroptions.cpp
new file mode 100644
index 0000000..a81b384
--- /dev/null
+++ b/widgets/imguroptions.cpp
@@ -0,0 +1,160 @@
+#include <QJsonObject>
+#include <QInputDialog>
+#include <QNetworkReply>
+#include <QDesktopServices>
+#include <QMessageBox>
+
+#include "imguroptions.h"
+#include "../uploader/uploader.h"
+#include "../screenshotmanager.h"
+
+ImgurOptions::ImgurOptions(QWidget *parent) : QWidget(parent)
+{
+ ui.setupUi(this);
+ connect(Uploader::instance(), &Uploader::imgurAuthRefreshed, this, &ImgurOptions::imgurRequestAlbumList);
+ connect(ui.imgurAuthButton , SIGNAL(clicked()), this , SLOT(imgurAuthorize()));
+ connect(ui.imgurRefreshAlbumButton, SIGNAL(clicked()), this , SLOT(imgurRequestAlbumList()));
+}
+
+QSettings *ImgurOptions::settings()
+{
+ return ScreenshotManager::instance()->settings();
+}
+
+void ImgurOptions::imgurAuthorize()
+{
+ 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;
+ }
+
+ QDesktopServices::openUrl(QUrl("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 ImgurOptions::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, &ImgurOptions::imgurRequestAlbumList);
+}
+
+void ImgurOptions::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 ImgurOptions::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;
+ }
+
+ 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;
+
+ for (auto albumValue : albumList) {
+ const QJsonObject album = albumValue.toObject();
+
+ QString albumVisibleTitle = album["title"].toString();
+
+ if (albumVisibleTitle.isEmpty()) {
+ albumVisibleTitle = tr("untitled");
+ }
+
+ ui.imgurAlbumComboBox->addItem(albumVisibleTitle, album["id"].toString());
+
+ if (album["id"].toString() == settings()->value("upload/imgur/album").toString()) {
+ settingsIndex = ui.imgurAlbumComboBox->count() - 1;
+ }
+ }
+
+ ui.imgurAlbumComboBox->setCurrentIndex(settingsIndex);
+}
diff --git a/widgets/imguroptions.h b/widgets/imguroptions.h
new file mode 100644
index 0000000..4984908
--- /dev/null
+++ b/widgets/imguroptions.h
@@ -0,0 +1,27 @@
+#ifndef IMGUROPTIONS_H
+#define IMGUROPTIONS_H
+
+#include <QWidget>
+#include "ui_imguroptions.h"
+
+class QSettings;
+class ImgurOptions : public QWidget
+{
+ Q_OBJECT
+public:
+ explicit ImgurOptions(QWidget *parent = 0);
+
+ QSettings *settings();
+
+private slots:
+ void imgurAlbumList();
+ void imgurAuthorize();
+ void imgurRequestAlbumList();
+ void imgurToken();
+
+private:
+ Ui::ImgurOptions ui;
+ friend class OptionsDialog;
+};
+
+#endif // IMGUROPTIONS_H
diff --git a/widgets/imguroptions.ui b/widgets/imguroptions.ui
new file mode 100644
index 0000000..1230cfe
--- /dev/null
+++ b/widgets/imguroptions.ui
@@ -0,0 +1,99 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>ImgurOptions</class>
+ <widget class="QWidget" name="ImgurOptions">
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>298</width>
+ <height>121</height>
+ </rect>
+ </property>
+ <property name="windowTitle">
+ <string>Form</string>
+ </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="QLabel" name="imgurUserLabel">
+ <property name="text">
+ <string>User:</string>
+ </property>
+ <property name="buddy">
+ <cstring>imgurAuthButton</cstring>
+ </property>
+ </widget>
+ </item>
+ <item row="0" column="1">
+ <widget class="QLabel" name="imgurAuthUserLabel">
+ <property name="text">
+ <string>&lt;i&gt;none</string>
+ </property>
+ </widget>
+ </item>
+ <item row="0" column="2">
+ <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="1">
+ <widget class="QComboBox" name="imgurAlbumComboBox">
+ <item>
+ <property name="text">
+ <string>- None -</string>
+ </property>
+ </item>
+ </widget>
+ </item>
+ <item row="1" column="2">
+ <widget class="QPushButton" name="imgurRefreshAlbumButton">
+ <property name="enabled">
+ <bool>false</bool>
+ </property>
+ <property name="text">
+ <string>Refresh</string>
+ </property>
+ </widget>
+ </item>
+ <item row="2" column="0" colspan="3">
+ <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>
+ </layout>
+ </widget>
+ <resources/>
+ <connections/>
+</ui>

File Metadata

Mime Type
text/x-diff
Expires
Tue, Jun 16, 12:21 AM (2 w, 1 d ago)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
70778
Default Alt Text
(160 KB)

Event Timeline