Page MenuHomePhabricator (Chris)

No OneTemporary

Size
68 KB
Referenced Files
None
Subscribers
None
diff --git a/dialogs/previewdialog.cpp b/dialogs/previewdialog.cpp
index 83a2cca..5ce51fa 100644
--- a/dialogs/previewdialog.cpp
+++ b/dialogs/previewdialog.cpp
@@ -1,365 +1,365 @@
/*
* 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 "previewdialog.h"
#include "screenshotdialog.h"
#include "../tools/screenshot.h"
#include "../tools/screenshotmanager.h"
#include "../tools/os.h"
#include <QApplication>
#include <QObject>
#include <QList>
#include <QHBoxLayout>
#include <QIcon>
#include <QPushButton>
#include <QPalette>
#include <QDesktopWidget>
#include <QGraphicsDropShadowEffect>
#include <QLabel>
#include <QStackedLayout>
#include <QSettings>
#include <QToolButton>
#include <QMenu>
#include <QDebug>
PreviewDialog::PreviewDialog(QWidget *parent) :
QDialog(parent), mAutoclose(0)
{
setWindowFlags(Qt::Tool | Qt::WindowStaysOnTopHint);
os::aeroGlass(this);
setWindowTitle("Screenshot Preview");
QSettings *settings = ScreenshotManager::instance()->settings();
mSize = settings->value("options/previewSize", 300).toInt();
mPosition = settings->value("options/previewPosition", 3).toInt();
if (settings->value("options/previewAutoclose", false).toBool()) {
mAutoclose = settings->value("options/previewAutocloseTime").toInt();
mAutocloseReset = mAutoclose;
mAutocloseAction = settings->value("options/previewAutocloseAction").toInt();
}
QHBoxLayout *l = new QHBoxLayout;
mStack = new QStackedLayout;
connect(mStack, SIGNAL(currentChanged(int)), this, SLOT(indexChanged(int)));
mPrevButton = new QPushButton(QIcon(":/icons/arrow-left"), "", this);
connect(mPrevButton, SIGNAL(clicked()), this, SLOT(previous()));
mNextButton = new QPushButton(QIcon(":/icons/arrow-right"), "", this);
connect(mNextButton, SIGNAL(clicked()), this, SLOT(next()));
mPrevButton->setCursor(Qt::PointingHandCursor);
mPrevButton->setFlat(true);
mPrevButton->setGraphicsEffect(os::shadow());
mPrevButton->setIconSize(QSize(24, 24));
mPrevButton->setVisible(false);
mNextButton->setCursor(Qt::PointingHandCursor);
mNextButton->setFlat(true);
mNextButton->setGraphicsEffect(os::shadow());
mNextButton->setIconSize(QSize(24, 24));
mNextButton->setVisible(false);
l->addWidget(mPrevButton);
l->addLayout(mStack);
l->addWidget(mNextButton);
l->setMargin(0);
l->setContentsMargins(6, 6, 6, 6);
mStack->setMargin(0);
setMaximumHeight(mSize);
setLayout(l);
if (mAutoclose) {
startTimer(1000);
}
}
void PreviewDialog::add(Screenshot *screenshot)
{
if (!isVisible()) {
show();
}
if (mAutoclose) {
mAutoclose = mAutocloseReset;
}
QLabel *label = new QLabel(this);
label->setGraphicsEffect(os::shadow());
bool small = false;
connect(label, SIGNAL(destroyed()), screenshot, SLOT(discard()));
QSize size = screenshot->pixmap().size();
if (size.width() > mSize || size.height() > mSize) {
size.scale(mSize, mSize, Qt::KeepAspectRatio);
}
else {
small = true;
}
QPixmap thumbnail = screenshot->pixmap().scaled(size, Qt::KeepAspectRatio, Qt::SmoothTransformation);
label->setPixmap(thumbnail);
thumbnail = QPixmap();
label->setAlignment(Qt::AlignCenter);
if (size.height() < 120) {
label->setMinimumHeight(120);
}
if (size.width() < 140) {
label->setMinimumWidth(140);
}
label->resize(size);
QToolButton *confirmPushButton = new QToolButton(label);
QPushButton *discardPushButton = new QPushButton(QIcon(":/icons/no") , "", label);
QPushButton *enlargePushButton = new QPushButton(QIcon(":/icons/zoom.in"), "", label);
confirmPushButton->setIcon(QIcon(":/icons/yes"));
confirmPushButton->setIconSize(QSize(24, 24));
confirmPushButton->setCursor(Qt::PointingHandCursor);
confirmPushButton->setGraphicsEffect(os::shadow());
if (!ScreenshotManager::instance()->settings()->value("options/uploadAuto").toBool()) {
QMenu *confirmMenu = new QMenu(confirmPushButton);
confirmMenu->setObjectName("confirmMenu");
QAction *uploadAction = new QAction(QIcon(":/icons/imgur"), tr("Upload"), confirmPushButton);
+ connect(uploadAction, SIGNAL(triggered()), screenshot, SLOT(markUpload()));
connect(uploadAction, SIGNAL(triggered()), screenshot, SLOT(confirm()));
- connect(uploadAction, SIGNAL(triggered()), parent(), SLOT(uploadLast()));
connect(uploadAction, SIGNAL(triggered()), this, SLOT(closePreview()));
confirmMenu->addAction(uploadAction);
confirmPushButton->setMenu(confirmMenu);
confirmPushButton->setPopupMode(QToolButton::MenuButtonPopup);
}
confirmPushButton->setAutoRaise(true);
confirmPushButton->setVisible(false);
discardPushButton->setIconSize(QSize(24, 24));
discardPushButton->setCursor(Qt::PointingHandCursor);
discardPushButton->setGraphicsEffect(os::shadow());
discardPushButton->setFlat(true);
discardPushButton->setVisible(false);
enlargePushButton->setIconSize(QSize(22, 22));
enlargePushButton->setCursor(Qt::PointingHandCursor);
enlargePushButton->setGraphicsEffect(os::shadow());
enlargePushButton->setFlat(true);
enlargePushButton->setVisible(false);
enlargePushButton->setDisabled(small);
connect(this, SIGNAL(acceptAll()), confirmPushButton, SLOT(click()));
connect(this, SIGNAL(rejectAll()), discardPushButton, SLOT(click()));
connect(confirmPushButton, SIGNAL(clicked()), screenshot, SLOT(confirm()));
connect(confirmPushButton, SIGNAL(clicked()), this, SLOT(closePreview()));
connect(discardPushButton, SIGNAL(clicked()), screenshot, SLOT(discard()));
connect(discardPushButton, SIGNAL(clicked()), this, SLOT(closePreview()));
connect(enlargePushButton, SIGNAL(clicked()), this, SLOT(enlargePreview()));
QHBoxLayout *wlayout = new QHBoxLayout;
wlayout->addWidget(confirmPushButton);
wlayout->addStretch();
wlayout->addWidget(enlargePushButton);
wlayout->addStretch();
wlayout->addWidget(discardPushButton);
wlayout->setMargin(0);
QVBoxLayout *wl = new QVBoxLayout;
wl->addStretch();
wl->addLayout(wlayout);
wl->setMargin(0);
label->setLayout(wl);
mStack->addWidget(label);
mStack->setCurrentIndex(mStack->count()-1);
mNextButton->setEnabled(false);
if (mStack->count() >= 2 && !mNextButton->isVisible()) {
mNextButton->setVisible(true);
mPrevButton->setVisible(true);
}
relocate();
}
int PreviewDialog::count() const
{
return mStack->count();
}
void PreviewDialog::relocate()
{
updateGeometry();
resize(minimumSizeHint());
QApplication::sendEvent(this, new QEvent(QEvent::Enter)); // Ensures the buttons are visible.
QPoint where;
switch (mPosition)
{
case 0:
where = QApplication::desktop()->availableGeometry(this).topLeft();
break;
case 1:
where = QApplication::desktop()->availableGeometry(this).topRight();
where.setX(where.x() - frameGeometry().width());
break;
case 2:
where = QApplication::desktop()->availableGeometry(this).bottomLeft();
where.setY(where.y() - frameGeometry().height());
break;
case 3:
default:
where = QApplication::desktop()->availableGeometry(this).bottomRight();
where.setX(where.x() - frameGeometry().width());
where.setY(where.y() - frameGeometry().height());
break;
}
move(where);
}
void PreviewDialog::closePreview()
{
QWidget *widget = mStack->currentWidget();
mStack->removeWidget(widget);
widget->deleteLater();
if (mStack->count() == 0) {
close();
}
else {
relocate();
}
}
void PreviewDialog::indexChanged(int i)
{
if (i == mStack->count()-1) {
mNextButton->setEnabled(false);
mPrevButton->setEnabled(true);
}
if (i == 0 && mStack->count() > 1) {
mNextButton->setEnabled(true);
mPrevButton->setEnabled(false);
}
if (i != 0 && i != mStack->count()-1) {
mNextButton->setEnabled(true);
mPrevButton->setEnabled(true);
}
if (mStack->count() < 2) {
mNextButton->setEnabled(false);
mPrevButton->setEnabled(false);
}
if (mStack->widget(i)) {
mStack->widget(i)->setFocus();
}
}
void PreviewDialog::previous()
{
mStack->setCurrentIndex(mStack->currentIndex()-1);
relocate();
}
void PreviewDialog::next()
{
mStack->setCurrentIndex(mStack->currentIndex()+1);
relocate();
}
void PreviewDialog::enlargePreview()
{
Screenshot *screenshot = qobject_cast<Screenshot*>(ScreenshotManager::instance()->children().at(mStack->currentIndex()));
if (screenshot) {
new ScreenshotDialog(screenshot, this);
}
}
bool PreviewDialog::event(QEvent *event)
{
if ((event->type() == QEvent::Enter || event->type() == QEvent::Leave)
&& mStack->currentWidget())
{
foreach (QObject *child, mStack->currentWidget()->children()) {
QWidget *widget = qobject_cast<QWidget*>(child);
if (widget) {
// Lets avoid disappearing buttons and bail if the menu is open.
QMenu *confirmMenu = widget->findChild<QMenu*>("confirmMenu");
if (confirmMenu && confirmMenu->isVisible())
return false;
widget->setVisible((event->type() == QEvent::Enter));
}
}
}
else if (event->type() == QEvent::Close) {
deleteLater();
}
else if (event->type() == QEvent::MouseButtonDblClick) {
enlargePreview();
}
return QDialog::event(event);
}
void PreviewDialog::timerEvent(QTimerEvent *event)
{
if (mAutoclose == 0) {
if (mAutocloseAction == 0) {
emit acceptAll();
}
else {
emit rejectAll();
}
}
else if (mAutoclose < 0) {
killTimer(event->timerId());
}
else {
setWindowTitle(tr("Preview: Closing in %1").arg(mAutoclose));
mAutoclose--;
}
}
diff --git a/lightscreenwindow.cpp b/lightscreenwindow.cpp
index 653f47f..937a5df 100644
--- a/lightscreenwindow.cpp
+++ b/lightscreenwindow.cpp
@@ -1,1034 +1,1034 @@
/*
* 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>
#ifdef Q_WS_WIN
#include <windows.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(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);
+ optiPNG(options.fileName, options.upload);
}
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();
+ options.upload = settings()->value("options/uploadAuto", 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);
+
+ if (mTrayIcon && !error.isEmpty()) {
+ 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(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)
+void LightscreenWindow::optiPNG(QString fileName, bool upload)
{
-#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
+ if (upload) {
+ // If the user has chosen to upload the 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);
+#if defined(Q_OS_UNIX)
+ QProcess::startDetached("optipng " + fileName + " -quiet");
+#else
}
#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());
+ action->setWhatsThis(iterator.peekPrevious().first);
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);
}
#ifdef Q_WS_WIN
bool LightscreenWindow::winEvent(MSG *message, long *result)
{
Taskbar::GetInstance()->winEvent(message, result);
}
#endif
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()
+ int confirm = QMessageBox::question(this, tr("Upload cancel"), tr("Do you want to cancel the upload of %1").arg(upload->toolTip()), tr("Cancel"), tr("Don't Cancel"));
+
+ if (confirm == 0) {
+ Uploader::instance()->cancel(upload->whatsThis()); // Full path stored in the whatsThis
+ }
}
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");
#ifdef Q_WS_WIN
mTaskbarButton->SetProgresValue(0, 0);
+ mTaskbarButton->SetState(STATE_NOPROGRESS);
#endif
}
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 737146d..7b576ff 100644
--- a/lightscreenwindow.h
+++ b/lightscreenwindow.h
@@ -1,116 +1,116 @@
/*
* 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 optiPNG(QString fileName, bool upload);
void connectHotkeys();
void createTrayIcon();
bool eventFilter(QObject *object, QEvent *event);
#ifdef Q_WS_WIN
bool winEvent(MSG *message, long *result);
#endif
// 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/tools/qtimgur.cpp b/tools/qtimgur.cpp
index 8112f88..dc5f599 100644
--- a/tools/qtimgur.cpp
+++ b/tools/qtimgur.cpp
@@ -1,113 +1,127 @@
/*
* 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, SLOT(progress(qint64, qint64)));
mFiles.insert(reply, fileName);
}
+void QtImgur::cancel(const QString &fileName)
+{
+ QNetworkReply *reply = mFiles.key(fileName);
+
+ if (!reply) {
+ return;
+ }
+
+ reply->abort();
+ mFiles.remove(reply);
+ reply->deleteLater();
+}
+
void QtImgur::reply(QNetworkReply *reply)
{
reply->deleteLater();
QString fileName = mFiles[reply];
mFiles.remove(reply);
+ reply->deleteLater();
if (reply->error() != QNetworkReply::NoError) {
- emit error(fileName, QtImgur::ErrorNetwork);
+ emit error(fileName, QtImgur::ErrorCancel);
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 3cdc886..b18016a 100644
--- a/tools/qtimgur.h
+++ b/tools/qtimgur.h
@@ -1,59 +1,61 @@
/*
* 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 QtImgur: public QObject {
Q_OBJECT
public:
enum Error {
ErrorFile,
ErrorNetwork,
ErrorCredits,
- ErrorUpload
+ ErrorUpload,
+ ErrorCancel
};
QtImgur(const QString &APIKey, QObject *parent);
public slots:
void upload(const QString &fileName);
+ void cancel(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/screenshot.cpp b/tools/screenshot.cpp
index 601fb3f..deae1df 100644
--- a/tools/screenshot.cpp
+++ b/tools/screenshot.cpp
@@ -1,395 +1,400 @@
/*
* 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()
{
#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;
}
+void Screenshot::markUpload()
+{
+ mOptions.upload = true;
+}
+
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/screenshot.h b/tools/screenshot.h
index 5eae27c..56f2e98 100644
--- a/tools/screenshot.h
+++ b/tools/screenshot.h
@@ -1,130 +1,132 @@
/*
* 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 SCREENSHOT_H
#define SCREENSHOT_H
#include <QObject>
#include <QDir>
#include <QPixmap>
class Screenshot : public QObject
{
Q_OBJECT
public:
enum Format
{
PNG = 0,
JPEG = 1,
BMP = 2,
TIFF = 3
};
enum Naming
{
Numeric = 0,
Date = 1,
Timestamp = 2,
Empty = 3
};
enum Mode
{
WholeScreen = 0,
ActiveWindow = 1,
SelectedArea = 2,
SelectedWindow = 3
};
enum Result
{
Fail = 0,
Success = 1,
Cancel = 2
};
struct NamingOptions
{
Naming naming;
bool flip;
int leadingZeros;
QString dateFormat;
};
struct Options
{
QString fileName;
Result result;
Format format;
QString prefix;
NamingOptions namingOptions;
QDir directory;
int mode;
int quality;
bool currentMonitor;
bool clipboard;
bool file;
bool preview;
bool magnify;
bool cursor;
bool saveAs;
bool animations;
bool replace;
+ bool upload;
};
Screenshot(QObject *parent, Screenshot::Options options);
~Screenshot();
Screenshot::Options &options();
QPixmap &pixmap();
static QString getName(NamingOptions options, QString prefix, QDir directory);
public slots:
void take();
void confirm(bool result = true);
void discard();
void save();
void setPixmap(QPixmap pixmap);
void confirmation();
+ void markUpload();
signals:
void askConfirmation();
void finished();
private:
void activeWindow();
QString newFileName() const;
QString extension() const;
void selectedArea();
void selectedWindow();
void wholeScreen();
void grabDesktop();
private:
Screenshot::Options mOptions;
QPixmap mPixmap;
bool mPixmapDelay;
bool mUnloaded;
QString mUnloadFilename;
};
#endif // SCREENSHOT_H
diff --git a/tools/uploader.cpp b/tools/uploader.cpp
index c20e6b6..8b47fac 100644
--- a/tools/uploader.cpp
+++ b/tools/uploader.cpp
@@ -1,145 +1,150 @@
/*
* 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);
}
+void Uploader::cancel(const QString &fileName)
+{
+ mImgur->cancel(fileName);
+}
+
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 f3c8ab9..e1ea66a 100644
--- a/tools/uploader.h
+++ b/tools/uploader.h
@@ -1,60 +1,61 @@
/*
* 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);
+ void cancel(const QString &fileName);
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
Fri, Jan 30, 3:15 PM (5 d, 9 h ago)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
55444
Default Alt Text
(68 KB)

Event Timeline