Page MenuHomePhabricator (Chris)

No OneTemporary

Authored By
Unknown
Size
100 KB
Referenced Files
None
Subscribers
None
This document is not UTF8. It was detected as JIS and converted to UTF8 for display.
diff --git a/dialogs/optionsdialog.cpp b/dialogs/optionsdialog.cpp
index 21449af..bc6d751 100644
--- a/dialogs/optionsdialog.cpp
+++ b/dialogs/optionsdialog.cpp
@@ -1,675 +1,675 @@
/*
* Copyright (C) 2011 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 <QSettings>
#include <QUrl>
#include <QTimer>
#include <QProcess>
#include <QDebug>
-#if defined(Q_WS_WIN)
+#ifdef Q_WS_WIN
#include <windows.h>
#endif
#include "optionsdialog.h"
#include "namingdialog.h"
#include "../tools/os.h"
#include "../tools/screenshot.h"
#include "../tools/screenshotmanager.h"
#include "../updater/updater.h"
OptionsDialog::OptionsDialog(QWidget *parent) :
QDialog(parent)
{
ui.setupUi(this);
setModal(true);
if (os::aeroGlass(this)) {
layout()->setMargin(2);
resize(minimumSizeHint());
}
#if defined(Q_WS_X11)
// 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.optionsTab->layout()->setContentsMargins(0, 0, 6, 0);
ui.aboutTab->layout()->setMargin(8);
}
#endif
QTimer::singleShot(0, this, SLOT(init()));
QTimer::singleShot(1, this, SLOT(loadSettings()));
}
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.buttonBox->addButton(new QPushButton(" " + tr("Restore Defaults") + " ", this), 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 (QIcon(":/icons/screen"));
ui.windowHotkeyWidget->setIcon (QIcon(":/icons/window"));
ui.windowPickerHotkeyWidget->setIcon(QIcon(":/icons/picker"));
ui.areaHotkeyWidget->setIcon (QIcon(":/icons/area"));
ui.openHotkeyWidget->setIcon (QIcon(":/icons/lightscreen.small"));
ui.directoryHotkeyWidget->setIcon (QIcon(":/icons/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.
setUpdatesEnabled(false);
//
// Connections
//
connect(ui.buttonBox , SIGNAL(clicked(QAbstractButton*)), this , SLOT(dialogButtonClicked(QAbstractButton*)));
connect(ui.buttonBox , SIGNAL(accepted()) , this , SLOT(accepted()));
connect(ui.buttonBox , SIGNAL(rejected()) , this , SLOT(rejected()));
connect(ui.namingOptionsButton , SIGNAL(clicked()) , this , SLOT(namingOptions()));
connect(ui.prefixLineEdit , SIGNAL(textChanged(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.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)));
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)));
connect(ui.moreInformationLabel, SIGNAL(linkActivated(QString)) , this, SLOT(openUrl(QString)));
connect(ui.languageComboBox , SIGNAL(currentIndexChanged(QString)), this, SLOT(languageChange(QString)));
connect(ui.mainLabel , SIGNAL(linkActivated(QString)), this, SLOT(openUrl(QString)));
connect(ui.linksLabel, SIGNAL(linkActivated(QString)), this, SLOT(openUrl(QString)));
//
// Languages
//
QDir languages(":/translations");
ui.languageComboBox->addItem("English");
foreach (QString language, languages.entryList()) {
ui.languageComboBox->addItem(language);
}
}
void OptionsDialog::namingOptions()
{
NamingDialog namingDialog((Screenshot::Naming) ui.namingComboBox->currentIndex());
namingDialog.exec();
flipToggled(settings()->value("options/flip").toBool());
updatePreview();
}
QSettings *OptionsDialog::settings() const
{
return ScreenshotManager::instance()->settings();
}
/*
* Slots
*/
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::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);
}
void OptionsDialog::checkUpdatesNow()
{
Updater::instance()->checkWithFeedback();
}
void OptionsDialog::dialogButtonClicked(QAbstractButton *button)
{
if (ui.buttonBox->buttonRole(button) == QDialogButtonBox::ResetRole) {
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);
QPushButton *restoreButton = msgBox.addButton(tr("Restore"), QMessageBox::ActionRole);
QPushButton *dontRestoreButton = msgBox.addButton(tr("Don't Restore"), QMessageBox::ActionRole);
msgBox.setDefaultButton(dontRestoreButton);
msgBox.exec();
Q_UNUSED(restoreButton)
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() == "screenshot."
&& checked)
ui.prefixLineEdit->setText(".screenshot");
if (ui.prefixLineEdit->text() == ".screenshot"
&& !checked)
ui.prefixLineEdit->setText("screenshot.");
setUpdatesEnabled(true); // Avoids flicker
}
void OptionsDialog::languageChange(QString language)
{
os::translate(language);
}
void OptionsDialog::openUrl(QString url)
{
if (url == "#aboutqt") {
qApp->aboutQt();
}
else {
QDesktopServices::openUrl(QUrl(url));
}
}
void OptionsDialog::rejected()
{
languageChange(settings()->value("options/language").toString()); // Revert language to default.
}
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());
// We save the explicit string because addition/removal of language files can cause it to change
settings()->setValue("language", ui.languageComboBox->currentText());
// 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("areaAutoclose", ui.areaAutocloseCheckBox->isChecked());
// Advanced
settings()->setValue("disableHideAlert", !ui.warnHideCheckBox->isChecked());
settings()->setValue("clipboard", ui.clipboardCheckBox->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();
}
/*
* Private
*/
void OptionsDialog::loadSettings()
{
settings()->sync();
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);
// Move the first option window to the center of the screen, since Windows usually positions it in a random location since it has no visible parent.
if (!(static_cast<QWidget*>(parent())->isVisible()))
move(qApp->desktop()->screen(qApp->desktop()->primaryScreen())->rect().center()-QPoint(height()/2, width()/2));
}
ui.startupCheckBox->toggle();
ui.trayCheckBox->toggle();
ui.previewAutocloseCheckBox->toggle();
settings()->beginGroup("file");
ui.formatComboBox->setCurrentIndex(settings()->value("format", 1).toInt());
ui.prefixLineEdit->setText(settings()->value("prefix", "screenshot.").toString());
ui.namingComboBox->setCurrentIndex(settings()->value("naming", 0).toInt());
ui.targetLineEdit->setText(settings()->value("target", os::getDocumentsPath() + QDir::separator() + "Screenshots").toString()); // Defaults to $HOME$/screenshots
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", true).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.areaAutocloseCheckBox->setChecked(settings()->value("areaAutoclose", false).toBool());
// Advanced
ui.clipboardCheckBox->setChecked(settings()->value("clipboard", true).toBool());
ui.optiPngCheckBox->setChecked(settings()->value("optipng", true).toBool());
ui.warnHideCheckBox->setChecked(!settings()->value("disableHideAlert", false).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());
-#if defined(Q_WS_WIN)
+#ifdef Q_WS_WIN
if (!QFile::exists("optipng.exe")) {
ui.optiPngCheckBox->setEnabled(false);
ui.optiPngCheckBox->setChecked(false);
ui.optiPngLabel->setText("optipng.exe not found");
}
#elif defined(Q_WS_X11)
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
//TODO: Must replace with not-stupid system
QString lang = settings()->value("language").toString();
int index = ui.languageComboBox->findText(lang);
if (index == -1)
index = ui.languageComboBox->findText("English");
ui.languageComboBox->setCurrentIndex(index);
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", QKeySequence(Qt::Key_Print)).value<QKeySequence> ());
settings()->endGroup();
settings()->beginGroup("area");
ui.areaCheckBox->setChecked(settings()->value("enabled").toBool());
ui.areaHotkeyWidget->setHotkey(settings()->value("hotkey", QKeySequence(Qt::CTRL + Qt::Key_Print)).value<QKeySequence> ());
settings()->endGroup();
settings()->beginGroup("window");
ui.windowCheckBox->setChecked(settings()->value("enabled").toBool());
ui.windowHotkeyWidget->setHotkey(settings()->value("hotkey", QKeySequence(Qt::ALT + Qt::Key_Print)).value<QKeySequence> ());
settings()->endGroup();
settings()->beginGroup("windowPicker");
ui.windowPickerCheckBox->setChecked(settings()->value("enabled").toBool());
ui.windowPickerHotkeyWidget->setHotkey(settings()->value("hotkey", QKeySequence(Qt::CTRL + Qt::ALT + Qt::Key_Print)).value<QKeySequence> ());
settings()->endGroup();
settings()->beginGroup("open");
ui.openCheckBox->setChecked(settings()->value("enabled").toBool());
ui.openHotkeyWidget->setHotkey(settings()->value("hotkey", QKeySequence(Qt::CTRL + Qt::Key_PageUp)).value<QKeySequence> ());
settings()->endGroup();
settings()->beginGroup("directory");
ui.directoryCheckBox->setChecked(settings()->value("enabled").toBool());
ui.directoryHotkeyWidget->setHotkey(settings()->value("hotkey", QKeySequence(Qt::SHIFT + Qt::Key_PageUp)).value<QKeySequence> ());
settings()->endGroup();
settings()->endGroup();
QTimer::singleShot(0, this, SLOT(updatePreview()));
setEnabled(true);
setUpdatesEnabled(true);
}
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;
}
void OptionsDialog::updatePreview()
{
Screenshot::NamingOptions options;
options.naming = (Screenshot::Naming)ui.namingComboBox->currentIndex();
options.flip = settings()->value("options/flip").toBool();
options.leadingZeros = settings()->value("options/naming/leadingZeros").toInt();
options.dateFormat = settings()->value("options/naming/dateFormat").toString();
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);
}
bool OptionsDialog::event(QEvent* event)
{
if (event->type() == QEvent::LanguageChange) {
ui.retranslateUi(this);
updatePreview();
resize(minimumSizeHint());
}
else if (event->type() == QEvent::Close) {
if (!settings()->contains("file/format")) {
// I'm afraid I can't let you do that, Dave.
event->ignore();
return false;
}
}
return QDialog::event(event);
}
-#if defined(Q_WS_WIN)
+#ifdef Q_WS_WIN
// Qt does not send the print screen key as a regular QKeyPress event, so we must use the Windows API
bool OptionsDialog::winEvent(MSG *message, long *result)
{
if ((message->message == WM_KEYUP || message->message == WM_SYSKEYUP)
&& message->wParam == VK_SNAPSHOT) {
qApp->postEvent(qApp->focusWidget(), new QKeyEvent(QEvent::KeyPress, Qt::Key_Print, qApp->keyboardModifiers()));
}
return QDialog::winEvent(message, result);
}
#endif
diff --git a/dialogs/optionsdialog.h b/dialogs/optionsdialog.h
index 7b31045..d1f13db 100644
--- a/dialogs/optionsdialog.h
+++ b/dialogs/optionsdialog.h
@@ -1,67 +1,67 @@
/*
* Copyright (C) 2011 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 <QtGui/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 languageChange(QString language);
void openUrl(QString url);
void rejected();
void saveSettings();
void updatePreview();
void loadSettings();
protected:
bool event(QEvent *event);
-#if defined(Q_WS_WIN)
+#ifdef Q_WS_WIN
bool winEvent(MSG *message, long *result);
#endif
private slots:
void namingOptions();
void flipToggled(bool checked);
void dialogButtonClicked(QAbstractButton *button);
void browse();
void init();
private:
bool hotkeyCollision();
QSettings *settings() const;
private:
Ui::OptionsDialog ui;
};
#endif // OPTIONSDIALOG_H
diff --git a/lightscreen.rc b/lightscreen.rc
index b636d5c..bf3798c 100644
--- a/lightscreen.rc
+++ b/lightscreen.rc
@@ -1,2 +1 @@
-IDI_ICON1 ICON DISCARDABLE "images/LS.ico"
-IDI_ICON2 ICON DISCARDABLE "images/test.ico"
+IDI_ICON1 ICON DISCARDABLE "images/LS.ico"
\ No newline at end of file
diff --git a/lightscreenwindow.cpp b/lightscreenwindow.cpp
index 4ddc766..4a9bbbe 100644
--- a/lightscreenwindow.cpp
+++ b/lightscreenwindow.cpp
@@ -1,995 +1,1030 @@
/*
* Copyright (C) 2011 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 <QFileInfo>
#include <QHttp>
#include <QMenu>
#include <QMessageBox>
#include <QPointer>
#include <QProcess>
#include <QSettings>
#include <QSound>
#include <QSystemTrayIcon>
#include <QTimer>
#include <QUrl>
#include <QKeyEvent>
#include <QToolTip>
#include <QDebug>
-#if defined(Q_WS_WIN)
+#ifdef Q_WS_WIN
#include <windows.h>
- #include "tools/qwin7utils/JumpList.h"
+ #include "tools/qwin7utils/Taskbar.h"
+ #include "tools/qwin7utils/TaskbarButton.h"
using namespace QW7;
#endif
/*
* Lightscreen includes
*/
#include "lightscreenwindow.h"
#include "dialogs/optionsdialog.h"
#include "dialogs/previewdialog.h"
#include "tools/globalshortcut/globalshortcutmanager.h"
#include "tools/os.h"
#include "tools/screenshot.h"
#include "tools/screenshotmanager.h"
#include "tools/qtwin.h"
#include "tools/uploader.h"
#include "updater/updater.h"
LightscreenWindow::LightscreenWindow(QWidget *parent) :
QDialog(parent),
mDoCache(false),
mHideTrigger(false),
mReviveMain(false),
mWasVisible(true),
mOptimizeCount(0),
mLastMode(-1),
mLastMessage(0),
mLastScreenshot()
{
os::translate(settings()->value("options/language").toString());
ui.setupUi(this);
if (QtWin::isCompositionEnabled()) {
layout()->setMargin(0);
resize(minimumSizeHint());
}
setMaximumSize(size());
setMinimumSize(size());
setWindowFlags(windowFlags() ^ Qt::WindowContextHelpButtonHint); // Remove the what's this button, no real use in the main window.
+#ifdef Q_WS_WIN
+ mTaskbarButton = new TaskbarButton(this);
+#endif
+
// Actions
connect(ui.optionsPushButton , SIGNAL(clicked()), this, SLOT(showOptions()));
connect(ui.hidePushButton , SIGNAL(clicked()), this, SLOT(toggleVisibility()));
connect(ui.screenshotPushButton, SIGNAL(clicked()), this, SLOT(showScreenshotMenu()));
connect(ui.quitPushButton , SIGNAL(clicked()), this, SLOT(quit()));
// Uploader
- connect(Uploader::instance(), SIGNAL(done(QString, QString)), this, SLOT(showUploaderMessage(QString, QString)));
- connect(Uploader::instance(), SIGNAL(error(QString)) , this, SLOT(showUploaderError(QString)));
+ connect(Uploader::instance(), SIGNAL(progress(qint64,qint64)), this, SLOT(uploadProgress(qint64, qint64)));
+ connect(Uploader::instance(), SIGNAL(done(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&)));
if (!settings()->contains("file/format")) {
showOptions(); // There are no options (or the options config is invalid or incomplete)
}
else {
QTimer::singleShot(0 , this, SLOT(applySettings()));
QTimer::singleShot(5000, this, SLOT(checkForUpdates()));
}
}
LightscreenWindow::~LightscreenWindow()
{
settings()->setValue("lastScreenshot", mLastScreenshot);
GlobalShortcutManager::instance()->clear();
delete mTrayIcon;
}
/*
* Slots
*/
void LightscreenWindow::action(int mode)
{
if (mode == 4) {
goToFolder();
}
else {
show();
}
}
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 false;
}
else if (msgBox.clickedButton() == enableAndDenotifyButton) {
settings()->setValue("options/disableHideAlert", true);
applySettings();
return false;
}
else if (msgBox.clickedButton() == enableButton) {
settings()->setValue("options/tray", true);
applySettings();
return false;
}
return true; // Cancel
}
void LightscreenWindow::cleanup(Screenshot::Options &options)
{
// Reversing settings
if (settings()->value("options/hide").toBool()) {
#ifndef Q_WS_X11 // 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) {
showScreenshotMessage(options.result, options.fileName);
}
}
if (settings()->value("options/playSound", false).toBool()) {
if (options.result == Screenshot::Success) {
QSound::play("sounds/ls.screenshot.wav");
}
else {
QSound::play("afakepathtomakewindowsplaythedefaultsoundtheresprobablyabetterwaybuticantbebothered");
}
}
if (options.result == Screenshot::Success
&& settings()->value("options/optipng").toBool()
&& options.format == Screenshot::PNG)
{
compressPng(options.fileName);
}
else if (settings()->value("options/uploadAuto").toBool()) {
upload(options.fileName);
}
if (options.result == Screenshot::Success && options.file) {
mLastScreenshot = options.fileName;
}
}
void LightscreenWindow::goToFolder()
{
#ifdef Q_WS_WIN
if (!mLastScreenshot.isEmpty()) {
QProcess::startDetached("explorer /select, \"" + mLastScreenshot +"\"");
}
else {
#endif
QString folder = settings()->value("file/target").toString();
if (folder.isEmpty())
folder = qApp->applicationDirPath();
if (QDir::toNativeSeparators(folder.at(folder.size()-1)) != QDir::separator())
folder.append(QDir::separator());
QDesktopServices::openUrl("file:///"+folder);
#ifdef Q_WS_WIN
}
#endif
}
void LightscreenWindow::messageReceived(const QString message)
{
if (message == "-wake") {
show();
qApp->alert(this, 500);
return;
}
if (message == "-screen")
screenshotAction();
if (message == "-area")
screenshotAction(2);
if (message == "-activewindow")
screenshotAction(1);
if (message == "-pickwindow")
screenshotAction(3);
if (message == "-folder")
action(4);
}
void LightscreenWindow::messageClicked()
{
if (mLastMessage == 1) {
goToFolder();
}
else {
QDesktopServices::openUrl(QUrl(Uploader::instance()->lastUrl()));
}
}
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());
QString doing;
int answer = 0;
if (Uploader::instance()->uploading() > 0) {
doing = tr("uploading one or more screenshots");
}
if (mOptimizeCount > 0) {
if (!doing.isNull()) {
doing = tr("optimizing and uploading screenshots");
}
else {
doing = tr("optimizing one or more screenshots");
}
}
if (!doing.isNull()) {
answer = QMessageBox::question(this,
tr("Are you sure you want to quit?"),
tr("Lightscreen is currently %1, this will finish momentarily, are you sure you want to quit?").arg(doing),
tr("Quit"),
tr("Don't quit"));
}
if (answer == 0)
accept();
}
void LightscreenWindow::restoreNotification()
{
if (mTrayIcon)
mTrayIcon->setIcon(QIcon(":/icons/lightscreen.small"));
+#ifdef Q_WS_WIN
+ mTaskbarButton->SetOverlayIcon(QIcon(), "");
+ mTaskbarButton->SetState(STATE_NORMAL);
+#endif
+
updateUploadStatus();
}
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_WS_X11 // 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();
options.directory = QDir(settings()->value("file/target").toString());
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.preview = settings()->value("options/preview", false).toBool();
options.magnify = settings()->value("options/magnify", false).toBool();
options.cursor = settings()->value("options/cursor" , false).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();
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::showOptions()
{
GlobalShortcutManager::clear();
QPointer<OptionsDialog> optionsDialog = new OptionsDialog(this);
optionsDialog->exec();
optionsDialog->deleteLater();
applySettings();
}
void LightscreenWindow::showScreenshotMessage(Screenshot::Result result, QString fileName)
{
if (result == Screenshot::Cancel
|| mPreviewDialog)
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::showUploaderMessage(QString fileName, QString url)
{
if (!mTrayIcon)
return;
QString screenshot = QFileInfo(fileName).fileName();
mLastMessage = 2;
mTrayIcon->showMessage(tr("%1 uploaded").arg(screenshot), tr("Click here to go to %1").arg(url));
updateUploadStatus();
}
void LightscreenWindow::showUploaderError(QString error)
{
if (!mTrayIcon)
return;
mLastMessage = -1;
mTrayIcon->showMessage(tr("Upload error"), error);
updateUploadStatus();
}
void LightscreenWindow::showScreenshotMenu()
{
// This slot is called only on the first click
QMenu *buttonMenu = new QMenu;
QAction *screenAction = new QAction(QIcon(":/icons/screen"), tr("&Screen"), buttonMenu);
screenAction->setData(QVariant(0));
QAction *windowAction = new QAction(QIcon(":/icons/window"),tr("Active &Window"), buttonMenu);
windowAction->setData(QVariant(1));
QAction *windowPickerAction = new QAction(QIcon(":/icons/picker"), tr("&Pick Window"), buttonMenu);
windowPickerAction->setData(QVariant(3));
QAction *areaAction = new QAction(QIcon(":/icons/area"), tr("&Area"), buttonMenu);
areaAction->setData(QVariant(2));
QAction *uploadAction = new QAction(QIcon(":/icons/imgur"), tr("&Upload last"), buttonMenu);
uploadAction->setToolTip(tr("Upload the last screenshot you took to imgur.com"));
connect(uploadAction, SIGNAL(triggered()), this, SLOT(uploadLast()));
QAction *goAction = new QAction(QIcon(":/icons/folder"), tr("&Go to Folder"), buttonMenu);
connect(goAction, SIGNAL(triggered()), this, SLOT(goToFolder()));
QActionGroup *screenshotGroup = new QActionGroup(buttonMenu);
screenshotGroup->addAction(screenAction);
screenshotGroup->addAction(windowAction);
screenshotGroup->addAction(windowPickerAction);
screenshotGroup->addAction(areaAction);
QMenu* imgurMenu = new QMenu("Upload");
imgurMenu->installEventFilter(this);
imgurMenu->addAction(uploadAction);
imgurMenu->addSeparator();
connect(screenshotGroup, SIGNAL(triggered(QAction*)), this, SLOT(screenshotActionTriggered(QAction*)));
buttonMenu->addAction(screenAction);
buttonMenu->addAction(areaAction);
buttonMenu->addAction(windowAction);
buttonMenu->addAction(windowPickerAction);
buttonMenu->addSeparator();
buttonMenu->addMenu(imgurMenu);
buttonMenu->addSeparator();
buttonMenu->addAction(goAction);
ui.screenshotPushButton->setMenu(buttonMenu);
ui.screenshotPushButton->showMenu();
}
void LightscreenWindow::notify(Screenshot::Result result)
{
switch (result)
{
case Screenshot::Success:
mTrayIcon->setIcon(QIcon(":/icons/lightscreen.yes"));
+#ifdef Q_WS_WIN
+ mTaskbarButton->SetOverlayIcon(QIcon(":/icons/yes"), tr("Success!"));
+#endif
setWindowTitle(tr("Success!"));
break;
case Screenshot::Fail:
mTrayIcon->setIcon(QIcon(":/icons/lightscreen.no"));
setWindowTitle(tr("Failed!"));
+#ifdef Q_WS_WIN
+ mTaskbarButton->SetOverlayIcon(QIcon(":/icons/no"), tr("Failed!"));
+ mTaskbarButton->SetState(STATE_ERROR);
+#endif
break;
case Screenshot::Cancel:
setWindowTitle(tr("Cancelled!"));
+#ifdef Q_WS_WIN
+ mTaskbarButton->SetState(STATE_NOPROGRESS);
+#endif
break;
}
- QTimer::singleShot(1500, this, SLOT(restoreNotification()));
+ QTimer::singleShot(2000, this, SLOT(restoreNotification()));
}
void LightscreenWindow::optimizationDone()
{
// A mouthful :D
mOptimizeCount--;
QString screenshot = (qobject_cast<QProcess*>(sender()))->property("screenshot").toString();
upload(screenshot);
}
void LightscreenWindow::showHotkeyError(QStringList hotkeys)
{
static bool dontShow = false;
if (dontShow)
return;
QString messageText;
messageText = tr("Some hotkeys could not be registered, they might already be in use");
if (hotkeys.count() > 1) {
messageText += tr("<br>The failed hotkeys are the following:") + "<ul>";
foreach(const QString &hotkey, hotkeys) {
messageText += QString("%1%2%3").arg("<li><b>").arg(hotkey).arg("</b></li>");
}
messageText += "</ul>";
}
else {
messageText += tr("<br>The failed hotkey is <b>%1</b>").arg(hotkeys[0]);
}
messageText += tr("<br><i>What do you want to do?</i>");
QMessageBox msgBox(this);
msgBox.setWindowTitle(tr("Lightscreen"));
msgBox.setText(messageText);
QPushButton *changeButton = msgBox.addButton(tr("Change") , QMessageBox::ActionRole);
QPushButton *disableButton = msgBox.addButton(tr("Disable"), QMessageBox::ActionRole);
QPushButton *exitButton = msgBox.addButton(tr("Quit") , QMessageBox::ActionRole);
msgBox.exec();
if (msgBox.clickedButton() == exitButton) {
dontShow = true;
QTimer::singleShot(10, this, SLOT(quit()));
}
else if (msgBox.clickedButton() == changeButton) {
showOptions();
}
else if (msgBox.clickedButton() == disableButton) {
foreach(const QString &hotkey, hotkeys) {
settings()->setValue(QString("actions/%1/enabled").arg(hotkey), false);
}
}
}
void LightscreenWindow::toggleVisibility(QSystemTrayIcon::ActivationReason reason)
{
if (reason != QSystemTrayIcon::DoubleClick)
return;
if (isVisible()) {
if (settings()->value("options/tray").toBool() == false
&& closingWithoutTray())
return;
hide();
}
else {
show();
}
}
// Aliases
void LightscreenWindow::windowHotkey() { screenshotAction(1); }
void LightscreenWindow::windowPickerHotkey() { screenshotAction(3); }
void LightscreenWindow::areaHotkey() { screenshotAction(2); }
/*
* Private
*/
void LightscreenWindow::applySettings()
{
bool tray = settings()->value("options/tray").toBool();
if (tray && !mTrayIcon) {
createTrayIcon();
mTrayIcon->show();
}
else if (!tray && mTrayIcon) {
mTrayIcon->deleteLater();
}
connectHotkeys();
mDoCache = false;
if (settings()->value("lastScreenshot").isValid())
mLastScreenshot = settings()->value("lastScreenshot").toString();
os::setStartup(settings()->value("options/startup").toBool(), settings()->value("options/startupHide").toBool());
}
void LightscreenWindow::compressPng(QString fileName)
{
#if defined(Q_OS_UNIX)
QProcess::startDetached("optipng " + fileName + " -quiet");
#else
if (settings()->value("options/uploadAuto").toBool()) {
// If the user has chosen to automatically upload screenshots we have to track the progress of the optimization, so we use QProcess
QProcess* optipng = new QProcess(this);
// To be read by optimizationDone() (for uploading)
optipng->setProperty("screenshot", fileName);
// Delete the QProcess once it's done.
connect(optipng, SIGNAL(finished(int, QProcess::ExitStatus)), this, SLOT(optimizationDone()));
connect(optipng, SIGNAL(finished(int, QProcess::ExitStatus)), optipng, SLOT(deleteLater()));
optipng->start("optipng", QStringList() << fileName);
mOptimizeCount++;
}
else {
// Otherwise start it detached from this process.
ShellExecuteW(NULL, NULL, (LPCWSTR)QString("optipng.exe").toStdWString().data(), (LPCWSTR)fileName.toStdWString().data(), NULL, SW_HIDE);
}
#endif
}
void LightscreenWindow::connectHotkeys()
{
// Set to true because if the hotkey is disabled it will show an error.
bool screen = true, area = true, window = true, open = true, directory = true;
if (settings()->value("actions/screen/enabled").toBool())
screen = GlobalShortcutManager::instance()->connect(settings()->value(
"actions/screen/hotkey").value<QKeySequence> (), this, SLOT(screenshotAction()));
if (settings()->value("actions/area/enabled").toBool())
area = GlobalShortcutManager::instance()->connect(settings()->value(
"actions/area/hotkey").value<QKeySequence> (), this, SLOT(areaHotkey()));
if (settings()->value("actions/window/enabled").toBool())
window = GlobalShortcutManager::instance()->connect(settings()->value(
"actions/window/hotkey").value<QKeySequence> (), this, SLOT(windowHotkey()));
if (settings()->value("actions/windowPicker/enabled").toBool())
window = GlobalShortcutManager::instance()->connect(settings()->value(
"actions/windowPicker/hotkey").value<QKeySequence> (), this, SLOT(windowPickerHotkey()));
if (settings()->value("actions/open/enabled").toBool())
open = GlobalShortcutManager::instance()->connect(settings()->value(
"actions/open/hotkey").value<QKeySequence> (), this, SLOT(show()));
if (settings()->value("actions/directory/enabled").toBool())
directory = GlobalShortcutManager::instance()->connect(settings()->value(
"actions/directory/hotkey").value<QKeySequence> (), this, SLOT(goToFolder()));
QStringList failed;
if (!screen) failed << "screen";
if (!area) failed << "area";
if (!window) failed << "window";
if (!open) failed << "open";
if (!directory) failed << "directory";
if (!failed.isEmpty())
showHotkeyError(failed);
}
void LightscreenWindow::createTrayIcon()
{
mTrayIcon = new QSystemTrayIcon(QIcon(":/icons/lightscreen.small"), this);
updateUploadStatus();
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(QIcon(":/icons/screen"), tr("&Screen"), mTrayIcon);
screenAction->setData(QVariant(0));
QAction *windowAction = new QAction(QIcon(":/icons/window"), tr("Active &Window"), this);
windowAction->setData(QVariant(1));
QAction *windowPickerAction = new QAction(QIcon(":/icons/picker"), tr("&Pick Window"), this);
windowPickerAction->setData(QVariant(3));
QAction *areaAction = new QAction(QIcon(":/icons/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(QIcon(":/icons/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 *optionsAction = new QAction(QIcon(":/icons/configure"), tr("View &Options"), mTrayIcon);
connect(optionsAction, SIGNAL(triggered()), this, SLOT(showOptions()));
QAction *goAction = new QAction(QIcon(":/icons/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("Screenshot");
screenshotMenu->addAction(screenAction);
screenshotMenu->addAction(areaAction);
screenshotMenu->addAction(windowAction);
screenshotMenu->addAction(windowPickerAction);
// Duplicated for the screenshot button :(
QMenu* imgurMenu = new QMenu("Upload");
imgurMenu->installEventFilter(this);
imgurMenu->addAction(uploadAction);
imgurMenu->addSeparator();
mUploadHistoryActions = new QActionGroup(imgurMenu);
connect(mUploadHistoryActions, SIGNAL(triggered(QAction*)), this, SLOT(uploadAction(QAction*)));
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);
}
bool LightscreenWindow::eventFilter(QObject *object, QEvent *event)
{
// Filtering upload menu(s) for show events to populate them with links to imgur.
if (event->type() == QEvent::Show) {
QMenu* menu = qobject_cast<QMenu*>(object);
QAction* uploadAction = menu->actions().at(0);
uploadAction->setEnabled(true); // Later in the loop we check to see if the last screenshot is already uploaded and disable this.
if (Uploader::instance()->screenshots().count() > 0) {
QAction* action = 0;
foreach (action, mUploadHistoryActions->actions()) {
mUploadHistoryActions->removeAction(action);
menu->removeAction(action);
delete action;
}
// Iterating back to front for the first 10 screenshots in the uploader history.
QListIterator< QPair<QString, QString> > iterator(Uploader::instance()->screenshots());
iterator.toBack();
int limit = 0;
while (iterator.hasPrevious()) {
if (limit >= 10) {
break;
}
action = new QAction(iterator.peekPrevious().second, menu);
action->setToolTip(QFileInfo(iterator.peekPrevious().first).fileName());
if (iterator.previous().first == mLastScreenshot) {
uploadAction->setEnabled(false);
}
mUploadHistoryActions->addAction(action);
menu->addAction(action);
limit++;
}
}
}
else if (event->type() == QEvent::ToolTip) {
QHelpEvent* helpEvent = dynamic_cast<QHelpEvent*>(event);
QMenu* menu = qobject_cast<QMenu*>(object);
QAction* action = menu->actionAt(helpEvent->pos());
if (action) {
QToolTip::showText(helpEvent->globalPos(), action->toolTip(), this);
}
}
return QDialog::eventFilter(object, event);
}
+bool LightscreenWindow::winEvent(MSG *message, long *result)
+{
+ Taskbar::GetInstance()->winEvent(message, result);
+}
+
QSettings *LightscreenWindow::settings() const
{
return ScreenshotManager::instance()->settings();
}
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.
connect(Updater::instance(), SIGNAL(done(bool)), this, SLOT(updaterDone(bool)));
Updater::instance()->check();
}
void LightscreenWindow::updaterDone(bool result)
{
settings()->setValue("lastUpdateCheck", QDate::currentDate().dayOfYear());
if (!result)
return;
QMessageBox msgBox;
msgBox.setWindowTitle(tr("Lightscreen"));
msgBox.setText(tr("There's a new version of Lightscreen available.<br>Would you like to see more information?<br>(<em>You can turn this notification off</em>)"));
msgBox.setIcon(QMessageBox::Information);
QPushButton *yesButton = msgBox.addButton(QMessageBox::Yes);
QPushButton *turnOffButton = msgBox.addButton(tr("Turn Off"), QMessageBox::ActionRole);
QPushButton *remindButton = msgBox.addButton(tr("Remind Me Later"), QMessageBox::RejectRole);
Q_UNUSED(remindButton);
msgBox.exec();
if (msgBox.clickedButton() == yesButton) {
QDesktopServices::openUrl(QUrl("http://lightscreen.sourceforge.net/new-version"));
}
else if (msgBox.clickedButton() == turnOffButton) {
settings()->setValue("disableUpdater", true);
}
}
void LightscreenWindow::upload(QString fileName)
{
Uploader::instance()->upload(fileName);
}
void LightscreenWindow::uploadAction(QAction *upload)
{
QString url = upload->text();
if (url == tr("Uploading...")) {
//int confirm = QMessageBox::question()
}
else {
QDesktopServices::openUrl(QUrl(url));
}
}
+void LightscreenWindow::uploadProgress(qint64 sent, qint64 total)
+{
+#ifdef Q_WS_WIN
+ mTaskbarButton->SetProgresValue(sent, total);
+#endif
+ //TODO: Update mTrayIcon & windowTitle()
+}
+
void LightscreenWindow::uploadLast()
{
upload(mLastScreenshot);
updateUploadStatus();
}
void LightscreenWindow::updateUploadStatus()
{
int uploading = Uploader::instance()->uploading();
QString statusString;
if (uploading > 0) {
statusString = tr("Uploading %1 screenshot(s)").arg(uploading);
}
else {
statusString = tr("Lightscreen");
+ mTaskbarButton->SetProgresValue(0, 0);
}
if (mTrayIcon) {
mTrayIcon->setToolTip(statusString);
}
setWindowTitle(statusString);
}
// Event handling
bool LightscreenWindow::event(QEvent *event)
{
if (event->type() == QEvent::Hide) {
settings()->setValue("position", pos());
}
else if (event->type() == QEvent::Close) {
quit();
}
else if (event->type() == QEvent::Show) {
os::aeroGlass(this);
if (!settings()->value("position").toPoint().isNull())
move(settings()->value("position").toPoint());
}
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 QDialog::event(event);
}
diff --git a/lightscreenwindow.h b/lightscreenwindow.h
index 50e7d4f..0e084c8 100644
--- a/lightscreenwindow.h
+++ b/lightscreenwindow.h
@@ -1,106 +1,115 @@
/*
* Copyright (C) 2011 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 LIGHTSCREENWINDOW_H
#define LIGHTSCREENWINDOW_H
#include <QtGui/QDialog>
#include <QPointer>
#include <QSystemTrayIcon>
#include "updater/updater.h"
#include "tools/screenshot.h"
#include "dialogs/previewdialog.h"
#include "ui_lightscreenwindow.h"
+#ifdef Q_WS_WIN
+ #include "tools/qwin7utils/TaskbarButton.h"
+#endif
+
class QHttp;
class Updater;
class QSettings;
class LightscreenWindow : public QDialog
{
Q_OBJECT
public:
LightscreenWindow(QWidget *parent = 0);
~LightscreenWindow();
public slots:
void action(int mode = 3);
void areaHotkey();
void checkForUpdates();
void cleanup(Screenshot::Options &options);
bool closingWithoutTray();
void goToFolder();
void messageClicked();
void messageReceived(const QString message);
void notify(Screenshot::Result result);
void optimizationDone();
void preview(Screenshot* screenshot);
void quit();
void restoreNotification();
void screenshotAction(int mode = 0);
void screenshotActionTriggered(QAction* action);
void showHotkeyError(QStringList hotkeys);
void showOptions();
void showScreenshotMenu();
void showScreenshotMessage(Screenshot::Result result, QString fileName);
void showUploaderError(QString error);
void showUploaderMessage(QString fileName, QString url);
void toggleVisibility(QSystemTrayIcon::ActivationReason reason = QSystemTrayIcon::DoubleClick);
void updateUploadStatus();
void updaterDone(bool result);
void upload(QString fileName);
void uploadAction(QAction* upload);
+ void uploadProgress(qint64 sent, qint64 total);
void uploadLast();
void windowHotkey();
void windowPickerHotkey();
private slots:
void applySettings();
private:
void compressPng(QString fileName);
void connectHotkeys();
void createTrayIcon();
bool eventFilter(QObject *object, QEvent *event);
+ bool winEvent(MSG *message, long *result);
// Convenience function
QSettings *settings() const;
protected:
bool event(QEvent *event);
private:
bool mDoCache;
bool mHideTrigger;
bool mReviveMain;
bool mWasVisible;
int mOptimizeCount;
int mLastMode;
int mLastMessage;
QActionGroup* mUploadHistoryActions;
QString mLastScreenshot;
QPointer<QSystemTrayIcon> mTrayIcon;
QPointer<PreviewDialog> mPreviewDialog;
Ui::LightscreenWindowClass ui;
+#ifdef Q_WS_WIN
+ QW7::TaskbarButton *mTaskbarButton;
+#endif
};
#endif // LIGHTSCREENWINDOW_H
diff --git a/main.cpp b/main.cpp
index 778d61c..b6e003c 100644
--- a/main.cpp
+++ b/main.cpp
@@ -1,87 +1,94 @@
/*
* Copyright (C) 2011 Christian Kaiser
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*/
#include <QApplication>
#include <QDesktopWidget>
#include <QLocale>
#include <QDebug>
-#if defined(Q_WS_WIN)
+#ifdef Q_WS_WIN
#include "tools/qwin7utils/AppUserModel.h"
#include "tools/qwin7utils/JumpList.h"
+ #include "tools/qwin7utils/Taskbar.h"
using namespace QW7;
#endif
#include "tools/os.h"
#include <QtSingleApplication>
#include "lightscreenwindow.h"
int main(int argc, char *argv[])
{
QtSingleApplication application(argc, argv);
application.setOrganizationName("K");
application.setApplicationName ("Lightscreen");
application.setApplicationVersion("2.0");
application.setQuitOnLastWindowClosed(false);
if (application.isRunning()) {
if (application.arguments().size() > 1) {
QStringList arguments = application.arguments();
arguments.removeFirst();
application.sendMessage(arguments.join(" "));
}
else {
application.sendMessage("-wake");
}
return 0;
}
LightscreenWindow lightscreen;
-#if defined(Q_WS_WIN)
+#ifdef Q_WS_WIN
// Windows 7 jumplists.
AppUserModel::SetCurrentProcessExplicitAppUserModelID("Lightscreen");
JumpList jumpList("Lightscreen");
QList<JumpListItem> tasks;
tasks.append(JumpListItem(application.applicationFilePath(), "-screen" , lightscreen.tr("Screen"), "", "", 0, application.applicationDirPath()));
tasks.append(JumpListItem(application.applicationFilePath(), "-area" , lightscreen.tr("Area") , "", "", 0, application.applicationDirPath()));
tasks.append(JumpListItem(application.applicationFilePath(), "-activewindow", lightscreen.tr("Active Window"), "", "", 0, application.applicationDirPath()));
tasks.append(JumpListItem(application.applicationFilePath(), "-pickwindow" , lightscreen.tr("Pick Window"), "", "", 0, application.applicationDirPath()));
tasks.append(JumpListItem());
tasks.append(JumpListItem(application.applicationFilePath(), "-folder" , lightscreen.tr("Go to Folder"), "", "", 0, application.applicationDirPath()));
jumpList.Begin();
jumpList.AddUserTasks(tasks);
jumpList.Commit();
#endif
if (application.arguments().size() > 1) {
lightscreen.messageReceived(application.arguments().at(1));
}
else {
lightscreen.show();
}
QObject::connect(&application, SIGNAL(messageReceived(const QString&)), &lightscreen, SLOT(messageReceived(const QString&)));
QObject::connect(&lightscreen, SIGNAL(finished(int)), &application, SLOT(quit()));
- return application.exec();
+ int result = application.exec();
+
+#ifdef Q_WS_WIN
+ Taskbar::ReleaseInstance();
+#endif
+
+ return result;
}
diff --git a/tools/os.cpp b/tools/os.cpp
index 6f1e66e..4c77272 100644
--- a/tools/os.cpp
+++ b/tools/os.cpp
@@ -1,402 +1,402 @@
/*
* Copyright (C) 2011 Christian Kaiser
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*/
#include <QApplication>
#include <QBitmap>
#include <QDesktopWidget>
#include <QDialog>
#include <QDir>
#include <QSettings>
#include <QLibrary>
#include <QPixmap>
#include <QTextEdit>
#include <QTranslator>
#include <QTimer>
#include <QTimeLine>
#include <QWidget>
#include <QGraphicsDropShadowEffect>
#include <string>
#include <QDesktopServices>
#include <QPointer>
#include <QProcess>
#include <QUrl>
#include <QDebug>
#include <QMessageBox>
#include "qtwin.h"
-#if defined(Q_WS_WIN)
+#ifdef Q_WS_WIN
#include <qt_windows.h>
#include <shlobj.h>
#elif defined(Q_WS_X11)
#include <QX11Info>
#include <X11/X.h>
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <X11/Xatom.h>
#endif
#include "os.h"
void os::addToRecentDocuments(QString fileName)
{
#ifdef Q_WS_WIN
QT_WA ( {
SHAddToRecentDocs (0x00000003, QDir::toNativeSeparators(fileName).utf16());
} , {
SHAddToRecentDocs (0x00000002, QDir::toNativeSeparators(fileName).toLocal8Bit().data());
} ); // QT_WA
#else
Q_UNUSED(fileName)
#endif
}
bool os::aeroGlass(QWidget* target)
{
if (QtWin::isCompositionEnabled()) {
QtWin::extendFrameIntoClientArea(target);
return true;
}
return false;
}
void os::setStartup(bool startup, bool hide)
{
QString lightscreen = QDir::toNativeSeparators(qApp->applicationFilePath());
if (hide)
lightscreen.append(" -h");
#ifdef Q_WS_WIN
// Windows startup settings
QSettings init("Microsoft", "Windows");
init.beginGroup("CurrentVersion");
init.beginGroup("Run");
if (startup) {
init.setValue("Lightscreen", lightscreen);
}
else {
init.remove("Lightscreen");
}
init.endGroup();
init.endGroup();
#endif
#if defined(Q_WS_X11)
QFile desktopFile(QDir::homePath() + "/.config/autostart/lightscreen.desktop");
desktopFile.remove();
if (startup) {
desktopFile.open(QIODevice::WriteOnly);
desktopFile.write(QString("[Desktop Entry]\nExec=%1\nType=Application").arg(lightscreen).toAscii());
}
#endif
}
QString os::getDocumentsPath()
{
#ifdef Q_WS_WIN
TCHAR szPath[MAX_PATH];
if (SUCCEEDED(SHGetFolderPath(NULL,
CSIDL_PERSONAL|CSIDL_FLAG_CREATE,
NULL,
0,
szPath)))
{
std::wstring path(szPath);
return QString::fromWCharArray(path.c_str());
}
return QDir::homePath() + QDir::separator() + "My Documents";
#else
return QDir::homePath() + QDir::separator() + "Documents";
#endif
}
QPixmap os::grabWindow(WId winId)
{
#ifdef Q_WS_WIN
RECT rcWindow;
GetWindowRect(winId, &rcWindow);
if (IsZoomed(winId)) {
if (QSysInfo::WindowsVersion >= QSysInfo::WV_VISTA) {
// TODO: WTF!
rcWindow.right -= 8;
rcWindow.left += 8;
rcWindow.top += 8;
rcWindow.bottom -= 8;
}
else {
rcWindow.right += 4;
rcWindow.left -= 4;
rcWindow.top += 4;
rcWindow.bottom -= 4;
}
}
int width, height;
width = rcWindow.right - rcWindow.left;
height = rcWindow.bottom - rcWindow.top;
RECT rcScreen;
GetWindowRect(GetDesktopWindow(), &rcScreen);
RECT rcResult;
UnionRect(&rcResult, &rcWindow, &rcScreen);
QPixmap pixmap;
// Comparing the rects to determine if the window is outside the boundaries of the screen,
// the window DC method has the disadvantage that it does not show Aero glass transparency,
// so we'll avoid it for the screenshots that don't need it.
if (EqualRect(&rcScreen, &rcResult)) {
// Grabbing the window from the Screen DC.
HDC hdcScreen = GetDC(NULL);
BringWindowToTop(winId);
HDC hdcMem = CreateCompatibleDC(hdcScreen);
HBITMAP hbmCapture = CreateCompatibleBitmap(hdcScreen, width, height);
SelectObject(hdcMem, hbmCapture);
BitBlt(hdcMem, 0, 0, width, height, hdcScreen, rcWindow.left, rcWindow.top, SRCCOPY);
ReleaseDC(winId, hdcMem);
DeleteDC(hdcMem);
pixmap = QPixmap::fromWinHBITMAP(hbmCapture);
DeleteObject(hbmCapture);
}
else {
// Grabbing the window by its own DC
HDC hdcWindow = GetWindowDC(winId);
HDC hdcMem = CreateCompatibleDC(hdcWindow);
HBITMAP hbmCapture = CreateCompatibleBitmap(hdcWindow, width, height);
SelectObject(hdcMem, hbmCapture);
BitBlt(hdcMem, 0, 0, width, height, hdcWindow, 0, 0, SRCCOPY);
ReleaseDC(winId, hdcMem);
DeleteDC(hdcMem);
pixmap = QPixmap::fromWinHBITMAP(hbmCapture);
DeleteObject(hbmCapture);
}
return pixmap;
#else
return QPixmap::grabWindow(winId);
#endif
}
void os::setForegroundWindow(QWidget *window)
{
#ifdef Q_WS_WIN
ShowWindow(window->winId(), SW_RESTORE);
SetForegroundWindow(window->winId());
#else
Q_UNUSED(window)
#endif
}
QPixmap os::cursor()
{
#ifdef Q_WS_WIN
/*
* Taken from: git://github.com/arrai/mumble-record.git ? src ? mumble ? Overlay.cpp
* BSD License.
*/
QPixmap pm;
CURSORINFO cursorInfo;
cursorInfo.cbSize = sizeof(cursorInfo);
::GetCursorInfo(&cursorInfo);
HICON c = cursorInfo.hCursor;
ICONINFO info;
ZeroMemory(&info, sizeof(info));
if (::GetIconInfo(c, &info)) {
if (info.hbmColor) {
pm = QPixmap::fromWinHBITMAP(info.hbmColor);
pm.setMask(QBitmap(QPixmap::fromWinHBITMAP(info.hbmMask)));
}
else {
QBitmap orig(QPixmap::fromWinHBITMAP(info.hbmMask));
QImage img = orig.toImage();
int h = img.height() / 2;
int w = img.bytesPerLine() / sizeof(quint32);
QImage out(img.width(), h, QImage::Format_MonoLSB);
QImage outmask(img.width(), h, QImage::Format_MonoLSB);
for (int i=0;i<h; ++i) {
const quint32 *srcimg = reinterpret_cast<const quint32 *>(img.scanLine(i + h));
const quint32 *srcmask = reinterpret_cast<const quint32 *>(img.scanLine(i));
quint32 *dstimg = reinterpret_cast<quint32 *>(out.scanLine(i));
quint32 *dstmask = reinterpret_cast<quint32 *>(outmask.scanLine(i));
for (int j=0;j<w;++j) {
dstmask[j] = srcmask[j];
dstimg[j] = srcimg[j];
}
}
pm = QBitmap::fromImage(out);
}
if (info.hbmMask)
::DeleteObject(info.hbmMask);
if (info.hbmColor)
::DeleteObject(info.hbmColor);
}
return pm;
#else
return QPixmap();
#endif
}
void os::translate(QString language)
{
static QTranslator *translator = 0;
if ((language.compare("English", Qt::CaseInsensitive) == 0
|| language.isEmpty()) && translator) {
qApp->removeTranslator(translator);
return;
}
if (translator)
delete translator;
translator = new QTranslator(qApp);
if (translator->load(language, ":/translations"))
qApp->installTranslator(translator);
}
void os::effect(QObject* target, const char *slot, int frames, int duration, const char* cleanup)
{
QTimeLine* timeLine = new QTimeLine(duration);
timeLine->setFrameRange(0, frames);
timeLine->connect(timeLine, SIGNAL(frameChanged(int)), target, slot);
if (cleanup != 0)
timeLine->connect(timeLine, SIGNAL(finished()), target, SLOT(cleanup()));
timeLine->connect(timeLine, SIGNAL(finished()), timeLine, SLOT(deleteLater()));
timeLine->start();
}
QGraphicsEffect* os::shadow(QColor color, int blurRadius, int offset) {
QGraphicsDropShadowEffect* shadowEffect = new QGraphicsDropShadowEffect;
shadowEffect->setBlurRadius(blurRadius);
shadowEffect->setOffset(offset);
shadowEffect->setColor(color);
return shadowEffect;
}
#ifdef Q_WS_X11
// Taken from KSnapshot. Oh KDE, what would I do whithout you :D
Window os::findRealWindow(Window w, int depth)
{
if( depth > 5 ) {
return None;
}
static Atom wm_state = XInternAtom( QX11Info::display(), "WM_STATE", False );
Atom type;
int format;
unsigned long nitems, after;
unsigned char* prop;
if( XGetWindowProperty( QX11Info::display(), w, wm_state, 0, 0, False, AnyPropertyType,
&type, &format, &nitems, &after, &prop ) == Success ) {
if( prop != NULL ) {
XFree( prop );
}
if( type != None ) {
return w;
}
}
Window root, parent;
Window* children;
unsigned int nchildren;
Window ret = None;
if( XQueryTree( QX11Info::display(), w, &root, &parent, &children, &nchildren ) != 0 ) {
for( unsigned int i = 0;
i < nchildren && ret == None;
++i ) {
ret = os::findRealWindow( children[ i ], depth + 1 );
}
if( children != NULL ) {
XFree( children );
}
}
return ret;
}
Window os::windowUnderCursor(bool includeDecorations)
{
Window root;
Window child;
uint mask;
int rootX, rootY, winX, winY;
XQueryPointer( QX11Info::display(), QX11Info::appRootWindow(), &root, &child,
&rootX, &rootY, &winX, &winY, &mask );
if( child == None ) {
child = QX11Info::appRootWindow();
}
if( !includeDecorations ) {
Window real_child = os::findRealWindow( child );
if( real_child != None ) { // test just in case
child = real_child;
}
}
return child;
}
#endif
diff --git a/tools/qtimgur.cpp b/tools/qtimgur.cpp
index ab9b7a1..8112f88 100644
--- a/tools/qtimgur.cpp
+++ b/tools/qtimgur.cpp
@@ -1,93 +1,113 @@
/*
* Copyright (C) 2011 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 "qtimgur.h"
#include <QNetworkAccessManager>
#include <QNetworkReply>
#include <QNetworkRequest>
#include <QFile>
#include <QXmlStreamReader>
#include <QDebug>
QtImgur::QtImgur(const QString &APIKey, QObject *parent) : QObject(parent), mAPIKey(APIKey)
{
mNetworkManager = new QNetworkAccessManager(this);
connect(mNetworkManager, SIGNAL(finished(QNetworkReply*)), this, SLOT(reply(QNetworkReply*)));
}
void QtImgur::upload(const QString &fileName)
{
QFile file(fileName);
if (!file.open(QIODevice::ReadOnly)) {
emit error(fileName, QtImgur::ErrorFile);
return;
}
QByteArray image = file.readAll().toBase64();
file.close();
QByteArray data;
data.append(QString("key=").toUtf8());
data.append(QUrl::toPercentEncoding(mAPIKey));
data.append(QString("&image=").toUtf8());
data.append(QUrl::toPercentEncoding(image));
QNetworkReply *reply = mNetworkManager->post(QNetworkRequest(QUrl("http://api.imgur.com/2/upload.xml")), data);
- connect(reply, SIGNAL(uploadProgress(qint64, qint64)), this, SIGNAL(uploadProgress(qint64, qint64)));
+ connect(reply, SIGNAL(uploadProgress(qint64, qint64)), this, SLOT(progress(qint64, qint64)));
mFiles.insert(reply, fileName);
}
void QtImgur::reply(QNetworkReply *reply)
{
reply->deleteLater();
QString fileName = mFiles[reply];
mFiles.remove(reply);
if (reply->error() != QNetworkReply::NoError) {
emit error(fileName, QtImgur::ErrorNetwork);
return;
}
if (reply->rawHeader("X-RateLimit-Remaining") == "0") {
emit error(fileName, QtImgur::ErrorCredits);
return;
}
QXmlStreamReader reader(reply->readAll());
while (!reader.atEnd()) {
reader.readNext();
if (reader.isStartElement()) {
if (reader.name() == "error") {
emit error(fileName, QtImgur::ErrorUpload);
}
if (reader.name() == "imgur_page") {
emit uploaded(fileName, reader.readElementText());
}
}
}
+}
+
+void QtImgur::progress(qint64 bytesSent, qint64 bytesTotal)
+{
+ qint64 totalSent, totalTotal;
+
+ QNetworkReply *senderReply = qobject_cast<QNetworkReply*>(sender());
+ senderReply->setProperty("bytesSent", bytesSent);
+ senderReply->setProperty("bytesTotal", bytesTotal);
+
+ totalSent = bytesSent;
+ totalTotal = bytesTotal;
+
+ foreach (QNetworkReply *reply, mFiles.keys()) {
+ if (reply != senderReply) {
+ totalSent += reply->property("bytesSent").toLongLong();
+ totalTotal += reply->property("bytesTotal").toLongLong();
+ }
+ }
+ emit uploadProgress(totalSent, totalTotal);
}
diff --git a/tools/qtimgur.h b/tools/qtimgur.h
index b1af73b..3cdc886 100644
--- a/tools/qtimgur.h
+++ b/tools/qtimgur.h
@@ -1,59 +1,59 @@
/*
* Copyright (C) 2011 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 QTIMGUR_H
#define QTIMGUR_H
#include <QObject>
#include <QHash>
+#include <QNetworkReply>
class QNetworkAccessManager;
-class QNetworkReply;
class QtImgur: public QObject {
Q_OBJECT
public:
enum Error {
ErrorFile,
ErrorNetwork,
ErrorCredits,
ErrorUpload
};
QtImgur(const QString &APIKey, QObject *parent);
public slots:
void upload(const QString &fileName);
protected slots:
void reply(QNetworkReply* reply);
+ void progress(qint64, qint64);
signals:
void uploaded(QString file, QString url);
void error(QString, QtImgur::Error);
void uploadProgress(qint64, qint64);
private:
QString mAPIKey;
QNetworkAccessManager *mNetworkManager;
QHash<QNetworkReply*, QString> mFiles;
-
};
#endif // QTIMGUR_H
diff --git a/tools/qtsingleapplication/qtsingleapplication.h b/tools/qtsingleapplication/qtsingleapplication.h
index 7bf6837..8297aab 100644
--- a/tools/qtsingleapplication/qtsingleapplication.h
+++ b/tools/qtsingleapplication/qtsingleapplication.h
@@ -1,98 +1,98 @@
/****************************************************************************
**
** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
**
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of a Qt Solutions component.
**
** You may use this file under the terms of the BSD license as follows:
**
** "Redistribution and use in source and binary forms, with or without
** modification, are permitted provided that the following conditions are
** met:
** * Redistributions of source code must retain the above copyright
** notice, this list of conditions and the following disclaimer.
** * Redistributions in binary form must reproduce the above copyright
** notice, this list of conditions and the following disclaimer in
** the documentation and/or other materials provided with the
** distribution.
** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor
** the names of its contributors may be used to endorse or promote
** products derived from this software without specific prior written
** permission.
**
** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
**
****************************************************************************/
#include <QtGui/QApplication>
class QtLocalPeer;
-#if defined(Q_WS_WIN)
+#ifdef Q_WS_WIN
# if !defined(QT_QTSINGLEAPPLICATION_EXPORT) && !defined(QT_QTSINGLEAPPLICATION_IMPORT)
# define QT_QTSINGLEAPPLICATION_EXPORT
# elif defined(QT_QTSINGLEAPPLICATION_IMPORT)
# if defined(QT_QTSINGLEAPPLICATION_EXPORT)
# undef QT_QTSINGLEAPPLICATION_EXPORT
# endif
# define QT_QTSINGLEAPPLICATION_EXPORT __declspec(dllimport)
# elif defined(QT_QTSINGLEAPPLICATION_EXPORT)
# undef QT_QTSINGLEAPPLICATION_EXPORT
# define QT_QTSINGLEAPPLICATION_EXPORT __declspec(dllexport)
# endif
#else
# define QT_QTSINGLEAPPLICATION_EXPORT
#endif
class QT_QTSINGLEAPPLICATION_EXPORT QtSingleApplication : public QApplication
{
Q_OBJECT
public:
QtSingleApplication(int &argc, char **argv, bool GUIenabled = true);
QtSingleApplication(const QString &id, int &argc, char **argv);
QtSingleApplication(int &argc, char **argv, Type type);
#if defined(Q_WS_X11)
QtSingleApplication(Display* dpy, Qt::HANDLE visual = 0, Qt::HANDLE colormap = 0);
QtSingleApplication(Display *dpy, int &argc, char **argv, Qt::HANDLE visual = 0, Qt::HANDLE cmap= 0);
QtSingleApplication(Display* dpy, const QString &appId, int argc, char **argv, Qt::HANDLE visual = 0, Qt::HANDLE colormap = 0);
#endif
bool isRunning();
QString id() const;
void setActivationWindow(QWidget* aw, bool activateOnMessage = true);
QWidget* activationWindow() const;
// Obsolete:
void initialize(bool dummy = true)
{ isRunning(); Q_UNUSED(dummy) }
public Q_SLOTS:
bool sendMessage(const QString &message, int timeout = 5000);
void activateWindow();
Q_SIGNALS:
void messageReceived(const QString &message);
private:
void sysInit(const QString &appId = QString());
QtLocalPeer *peer;
QWidget *actWin;
};
diff --git a/tools/screenshot.cpp b/tools/screenshot.cpp
index 0df2986..601fb3f 100644
--- a/tools/screenshot.cpp
+++ b/tools/screenshot.cpp
@@ -1,395 +1,395 @@
/*
* Copyright (C) 2011 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 <QDebug>
#include "windowpicker.h"
#include "../dialogs/areadialog.h"
#include "screenshot.h"
#include "os.h"
#ifdef Q_WS_WIN
#include <windows.h>
#endif
#ifdef Q_WS_X11
#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 (mUnloaded) {
QFile::remove(mUnloadFilename);
}
}
Screenshot::Options &Screenshot::options()
{
return mOptions;
}
QPixmap &Screenshot::pixmap()
{
if (mUnloaded) {
// A local reference.. what could go wrong? Nothing! Right guys? Guys?
QPixmap p;
p.load(mUnloadFilename);
return p;
}
return mPixmap;
}
void Screenshot::activeWindow()
{
-#if defined(Q_WS_WIN)
+#ifdef Q_WS_WIN
HWND fWindow = GetForegroundWindow();
if (fWindow == NULL)
return;
if (fWindow == GetDesktopWindow()) {
wholeScreen();
return;
}
mPixmap = os::grabWindow(GetForegroundWindow());
#endif
#if defined(Q_WS_X11)
Window focus;
int revert;
XGetInputFocus(QX11Info::display(), &focus, &revert);
mPixmap = QPixmap::grabWindow(focus);
#endif
}
QString Screenshot::getName(NamingOptions options, QString prefix, QDir directory)
{
QString naming;
int naming_largest = 0;
if (options.flip) {
naming = "%1" + prefix;
}
else {
naming = prefix + "%1";
}
switch (options.naming)
{
case Screenshot::Numeric: // Numeric
// Iterating through the folder to find the largest numeric naming.
foreach(QString file, directory.entryList(QDir::Files))
{
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.toAscii(), naming_largest + 1));
}
else {
naming = naming.arg(naming_largest + 1);
}
break;
case Screenshot::Date: // Date
naming = naming.arg(QDateTime::currentDateTime().toString(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::newFileName() const
{
if (!mOptions.directory.exists())
mOptions.directory.mkpath(mOptions.directory.path());
QString naming = Screenshot::getName(mOptions.namingOptions, mOptions.prefix, mOptions.directory);
QString fileName;
QString path = QDir::toNativeSeparators(mOptions.directory.path());
// Cleanup
if (path.at(path.size()-1) != QDir::separator() && !path.isEmpty())
path.append(QDir::separator());
fileName.append(path);
fileName.append(naming);
return fileName;
}
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::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)));
}
void Screenshot::wholeScreen()
{
grabDesktop();
}
void Screenshot::grabDesktop()
{
QRect geometry;
if (mOptions.currentMonitor) {
geometry = qApp->desktop()->screenGeometry(QCursor::pos());
}
else {
geometry = qApp->desktop()->geometry();
}
mPixmap = QPixmap::grabWindow(qApp->desktop()->winId(), geometry.x(), geometry.y(), geometry.width(), geometry.height());
if (mOptions.cursor && !mPixmap.isNull()) {
QPainter painter(&mPixmap);
painter.drawPixmap(QCursor::pos(), os::cursor());
}
}
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::confirm(bool result)
{
if (result) {
save();
}
else {
mOptions.result = Screenshot::Cancel;
}
mPixmap = QPixmap(); // Cleanup just in case.
emit finished();
}
void Screenshot::discard()
{
confirm(false);
}
void Screenshot::save()
{
QString name = "";
QString fileName = "";
Screenshot::Result result = Screenshot::Fail;
if (mOptions.file && !mOptions.saveAs) {
name = newFileName();
}
else if (mOptions.file && mOptions.saveAs) {
name = QFileDialog::getSaveFileName(0, tr("Save as.."), newFileName(), "*" + extension());
}
if (!mOptions.replace && QFile::exists(name+extension())) {
// Ugly? You should see my wife!
int count = 0;
int cunt = 0;
QString naming = QFileInfo(name).fileName();
foreach(QString file, QFileInfo(name+extension()).dir().entryList(QDir::Files)) {
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) + ")";
}
fileName = name + extension();
// 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) {
if (fileName.isEmpty()) {
result = Screenshot::Fail;
}
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;
}
os::addToRecentDocuments(fileName);
}
if (mOptions.clipboard) {
QApplication::clipboard()->setPixmap(mPixmap, QClipboard::Clipboard);
if (!mOptions.file) {
result = (Screenshot::Result)1;
}
}
mPixmap = QPixmap();
mOptions.fileName = fileName;
mOptions.result = result;
}
void Screenshot::setPixmap(QPixmap pixmap)
{
mPixmap = pixmap;
if (mPixmap.isNull()) {
emit confirm(false);
}
else {
confirmation();
}
}
void Screenshot::confirmation()
{
emit askConfirmation();
if (!mOptions.file) {
return;
}
// 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();
}
}
diff --git a/tools/uploader.cpp b/tools/uploader.cpp
index e75d3dd..c20e6b6 100644
--- a/tools/uploader.cpp
+++ b/tools/uploader.cpp
@@ -1,144 +1,145 @@
/*
* Copyright (C) 2011 Christian Kaiser
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*/
#include "uploader.h"
#include "qtimgur.h"
#include <QList>
#include <QPair>
#include <QDebug>
Uploader::Uploader(QObject *parent) : QObject(parent), mUploading(0)
{
mImgur = new QtImgur("6920a141451d125b3e1357ce0e432409", this);
connect(mImgur, SIGNAL(uploaded(QString, QString)), this, SLOT(uploaded(QString, QString)));
connect(mImgur, SIGNAL(error(QString, QtImgur::Error)), this, SLOT(imgurError(QString, QtImgur::Error)));
+ connect(mImgur, SIGNAL(uploadProgress(qint64,qint64)), this, SIGNAL(progress(qint64,qint64)));
}
void Uploader::upload(const QString &fileName)
{
if (fileName.isEmpty()) {
return;
}
// Cancel on duplicate
for (int i = 0; i < mScreenshots.size(); ++i) {
if (mScreenshots.at(i).first == fileName) {
return;
}
}
mImgur->upload(fileName);
QPair<QString, QString> screenshot;
screenshot.first = fileName;
screenshot.second = tr("Uploading...");
mScreenshots.append(screenshot);
mUploading++;
}
void Uploader::uploaded(const QString &file, const QString &url)
{
// Modifying uploaded list, adding url.
for (int i = 0; i < mScreenshots.size(); ++i) {
if (mScreenshots.at(i).first == file) {
mScreenshots[i].second = url;
break;
}
}
mUploading--;
emit done(file, url);
}
int Uploader::uploading()
{
return mUploading;
}
void Uploader::imgurError(const QString &file, const QtImgur::Error e)
{
qDebug() << "Uploader::imgurError(" << file << ", " << e << ")";
mUploading--;
// Removing the screenshot.
for (int i = 0; i < mScreenshots.size(); ++i) {
if (mScreenshots.at(i).first == file) {
mScreenshots.removeAt(i);
break;
}
}
if (e == mLastError) {
// Fail silently? Really? FINE
return;
}
QString errorString;
switch (e) {
case QtImgur::ErrorFile:
errorString = tr("Screenshot file not found.");
break;
case QtImgur::ErrorNetwork:
errorString = tr("Could not reach imgur.com");
break;
case QtImgur::ErrorCredits:
errorString = tr("You have exceeded your upload quota.");
break;
case QtImgur::ErrorUpload:
errorString = tr("Upload failed.");
break;
}
mLastError = e;
emit error(errorString);
}
QString Uploader::lastUrl() const
{
QListIterator< QPair<QString, QString> > i(mScreenshots);
i.toBack();
QString url;
while (i.hasPrevious()) {
url = i.previous().second;
if (!url.contains(tr("Uploading..."))) {
return url;
}
}
return url;
}
// Singleton
Uploader* Uploader::mInstance = 0;
Uploader *Uploader::instance()
{
if (!mInstance)
mInstance = new Uploader();
return mInstance;
}
diff --git a/tools/uploader.h b/tools/uploader.h
index 30caa70..f3c8ab9 100644
--- a/tools/uploader.h
+++ b/tools/uploader.h
@@ -1,59 +1,60 @@
/*
* Copyright (C) 2011 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 UPLOADER_H
#define UPLOADER_H
#include <QObject>
#include <QList>
#include <QPair>
#include "qtimgur.h"
class Uploader : public QObject
{
Q_OBJECT
public:
Uploader(QObject *parent = 0);
static Uploader* instance();
QString lastUrl() const;
QList< QPair<QString, QString> > &screenshots() { return mScreenshots; }
public slots:
void upload(const QString &fileName);
void uploaded(const QString &fileName, const QString &url);
int uploading();
void imgurError(const QString &file, const QtImgur::Error e);
signals:
void done(QString, QString);
void error(QString);
+ void progress(qint64, qint64);
private:
static Uploader* mInstance;
// Filename, url
QList< QPair<QString, QString> > mScreenshots;
QtImgur *mImgur;
QtImgur::Error mLastError;
int mUploading;
};
#endif // UPLOADER_H

File Metadata

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

Event Timeline