Page MenuHomePhabricator (Chris)

No OneTemporary

Authored By
Unknown
Size
342 KB
Referenced Files
None
Subscribers
None
This file is larger than 256 KB, so syntax highlighting was skipped.
diff --git a/dialogs/areadialog.cpp b/dialogs/areadialog.cpp
index 6e665a8..f502d31 100644
--- a/dialogs/areadialog.cpp
+++ b/dialogs/areadialog.cpp
@@ -1,587 +1,587 @@
-/*
- * 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
- *
- ******
- *
- * Based on KDE's KSnapshot regiongrabber.cpp, revision 796531, Copyright 2007 Luca Gugelmann <lucag@student.ethz.ch>
- * released under the GNU LGPL <http://www.gnu.org/licenses/old-licenses/library.txt>
- *
- */
-#include "areadialog.h"
-#include "../tools/os.h"
-#include "../tools/screenshot.h"
-#include "../tools/screenshotmanager.h"
-
-#include <QApplication>
-#include <QDesktopWidget>
-#include <QHBoxLayout>
-#include <QMouseEvent>
-#include <QPainter>
-#include <QPushButton>
-#include <QSettings>
-#include <QTimer>
-#include <QToolTip>
-
-#include <QDebug>
-
-AreaDialog::AreaDialog(Screenshot *screenshot) :
- QDialog(0), mScreenshot(screenshot), mMouseDown(false), mMouseMagnifier(false),
- mNewSelection(false), mHandleSize(10), mMouseOverHandle(0), mIdleTimer(),
- mShowHelp(true), mGrabbing(false), mOverlayAlpha(1), mAutoclose(false),
- mTLHandle(0, 0, mHandleSize, mHandleSize), mTRHandle(0, 0, mHandleSize, mHandleSize),
- mBLHandle(0, 0, mHandleSize, mHandleSize), mBRHandle(0, 0, mHandleSize, mHandleSize),
- mLHandle(0, 0, mHandleSize, mHandleSize), mTHandle(0, 0, mHandleSize, mHandleSize),
- mRHandle(0, 0, mHandleSize, mHandleSize), mBHandle(0, 0, mHandleSize, mHandleSize)
-{
- mHandles << &mTLHandle << &mTRHandle << &mBLHandle << &mBRHandle
- << &mLHandle << &mTHandle << &mRHandle << &mBHandle;
-
- mMouseOverHandle = 0;
-
- setMouseTracking(true);
- setWindowTitle(tr("Lightscreen Area Mode"));
- setWindowFlags(Qt::WindowStaysOnTopHint | Qt::FramelessWindowHint | Qt::X11BypassWindowManagerHint);
-
- setCursor(Qt::CrossCursor);
-
- connect(&mIdleTimer, SIGNAL(timeout()), this, SLOT(displayHelp()));
- mIdleTimer.start(2000);
-
- mAutoclose = ScreenshotManager::instance()->settings()->value("options/areaAutoclose").toBool();
-
- if (mAutoclose)
- return; // Avoid creating the accept widget if it's not going to get used.
-
- // Creating accept widget:
- mAcceptWidget = new QWidget(this);
- mAcceptWidget->resize(110, 60);
- mAcceptWidget->setWindowOpacity(0.4);
- mAcceptWidget->setGraphicsEffect(os::shadow(QColor(50, 50, 50, 255), 8));
- mAcceptWidget->setStyleSheet("QWidget { background: qlineargradient(spread:pad, x1:0, y1:0, x2:0, y2:1, stop:0 rgba(140, 140, 140, 230), stop:1 rgba(80, 80, 80, 230)); padding: 6px 10px; border: 1px solid rgba(0, 0, 0, 200); border-radius: 8px; } QPushButton { background: transparent; border: none; height: 50px; color: white; padding: 0; } QPushButton:hover { cursor: hand; }");
-
- QPushButton *awAcceptButton = new QPushButton(QIcon(":/icons/yes.big"), "", this);
- connect(awAcceptButton, SIGNAL(clicked()), this, SLOT(grabRect()));
- awAcceptButton->setCursor(Qt::PointingHandCursor);
- awAcceptButton->setIconSize(QSize(48, 48));
- awAcceptButton->setGraphicsEffect(os::shadow(QColor(50, 50, 50, 255)));
-
- QPushButton *awRejectButton = new QPushButton(QIcon(":/icons/no.big"), "", this);
- connect(awRejectButton, SIGNAL(clicked()), this, SLOT(cancel()));
- awRejectButton->setCursor(Qt::PointingHandCursor);
- awRejectButton->setIconSize(QSize(48, 48));
- awRejectButton->setGraphicsEffect(os::shadow(QColor(50, 50, 50, 255)));
-
- QHBoxLayout *awLayout = new QHBoxLayout(this);
- awLayout->addWidget(awAcceptButton);
- awLayout->addWidget(awRejectButton);
- awLayout->setMargin(0);
- awLayout->setSpacing(0);
-
- mAcceptWidget->setLayout(awLayout);
- mAcceptWidget->setVisible(false);
-}
-
-QRect &AreaDialog::resultRect()
-{
- return mSelection;
-}
-
-void AreaDialog::animationTick(int frame)
-{
- mOverlayAlpha = frame;
- update();
-}
-
-void AreaDialog::cancel()
-{
- reject();
-}
-
-void AreaDialog::displayHelp()
-{
- mShowHelp = true;
- update();
-}
-
-void AreaDialog::grabRect()
-{
- QRect r = mSelection.normalized();
- if (!r.isNull() && r.isValid()) {
- mGrabbing = true;
- accept();
- }
-}
-
-void AreaDialog::keyPressEvent(QKeyEvent* e)
-{
- if (e->key() == Qt::Key_Escape) {
- cancel();
- }
- else if (e->key() == Qt::Key_Enter || e->key() == Qt::Key_Return) {
- grabRect();
- }
- else {
- e->ignore();
- }
-}
-
-void AreaDialog::mouseDoubleClickEvent(QMouseEvent*)
-{
- grabRect();
-}
-
-void AreaDialog::mouseMoveEvent(QMouseEvent* e)
-{
- mMouseMagnifier = false;
-
- if (mMouseDown) {
-
- mMousePos = e->pos();
-
- if (mNewSelection) {
- QRect r = rect();
-
- mSelection = QRect(mDragStartPoint, limitPointToRect(mMousePos, r)).normalized();
- }
- else if (mMouseOverHandle == 0) { // moving the whole selection
- QRect r = rect().normalized(), s = mSelectionBeforeDrag.normalized();
- QPoint p = s.topLeft() + e->pos() - mDragStartPoint;
- r.setBottomRight(r.bottomRight() - QPoint(s.width(), s.height()));
-
- if (!r.isNull() && r.isValid())
- mSelection.moveTo(limitPointToRect(p, r));
- }
- else {// dragging a handle
- QRect r = mSelectionBeforeDrag;
- QPoint offset = e->pos() - mDragStartPoint;
-
- if (mMouseOverHandle == &mTLHandle || mMouseOverHandle == &mTHandle
- || mMouseOverHandle == &mTRHandle) // dragging one of the top handles
- {
- r.setTop(r.top() + offset.y());
- }
-
- if (mMouseOverHandle == &mTLHandle || mMouseOverHandle == &mLHandle
- || mMouseOverHandle == &mBLHandle) // dragging one of the left handles
- {
- r.setLeft(r.left() + offset.x());
- }
-
- if (mMouseOverHandle == &mBLHandle || mMouseOverHandle == &mBHandle
- || mMouseOverHandle == &mBRHandle) // dragging one of the bottom handles
- {
- r.setBottom(r.bottom() + offset.y());
- }
-
- if (mMouseOverHandle == &mTRHandle || mMouseOverHandle == &mRHandle
- || mMouseOverHandle == &mBRHandle) // dragging one of the right handles
- {
- r.setRight(r.right() + offset.x());
- }
-
- r = r.normalized();
- r.setTopLeft(limitPointToRect(r.topLeft(), rect()));
- r.setBottomRight(limitPointToRect(r.bottomRight(), rect()));
- mSelection = r;
- }
-
- if (qApp->keyboardModifiers() & Qt::ControlModifier)
- {
- // The lazy 1:1 aspect ratio approach!
- mSelection.setHeight(mSelection.width());
- }
-
- if (mAcceptWidget) {
- QPoint acceptPos = e->pos();
- QRect acceptRect = QRect(acceptPos, QSize(120, 70));
-
- // Prevent the widget from overlapping the handles
- if (acceptRect.intersects(mTLHandle)) {
- acceptPos = mTLHandle.bottomRight() + QPoint(2, 2); // Corner case
- }
-
- if (acceptRect.intersects(mBRHandle)) {
- acceptPos = mBRHandle.bottomRight();
- }
-
- if (acceptRect.intersects(mBHandle)) {
- acceptPos = mBHandle.bottomRight();
- }
-
- if (acceptRect.intersects(mRHandle)) {
- acceptPos = mRHandle.topRight();
- }
-
- if (acceptRect.intersects(mTHandle)) {
- acceptPos = mTHandle.bottomRight();
- }
-
- if ((acceptPos.x()+120) > mScreenshot->pixmap().rect().width())
- acceptPos.setX(acceptPos.x()-120);
-
- if ((acceptPos.y()+70) > mScreenshot->pixmap().rect().height())
- acceptPos.setY(acceptPos.y()-70);
-
- mAcceptWidget->move(acceptPos);
- }
-
- update();
- }
- else
- {
- if (mSelection.isNull()) {
- mMouseMagnifier = true;
- update();
- return;
- }
-
- bool found = false;
- foreach(QRect* r, mHandles) {
- if (r->contains(e->pos())) {
- mMouseOverHandle = r;
- found = true;
- break;
- }
- }
-
- if (!found) {
- mMouseOverHandle = 0;
- if (mSelection.contains(e->pos()))
- setCursor(Qt::OpenHandCursor);
- else if (mAcceptWidget && QRect(mAcceptWidget->mapToParent(mAcceptWidget->pos()), QSize(100, 60)).contains(e->pos()))
- setCursor(Qt::PointingHandCursor);
- else
- setCursor(Qt::CrossCursor);
- }
- else {
- if (mMouseOverHandle == &mTLHandle || mMouseOverHandle == &mBRHandle)
- setCursor(Qt::SizeFDiagCursor);
- if (mMouseOverHandle == &mTRHandle || mMouseOverHandle == &mBLHandle)
- setCursor(Qt::SizeBDiagCursor);
- if (mMouseOverHandle == &mLHandle || mMouseOverHandle == &mRHandle)
- setCursor(Qt::SizeHorCursor);
- if (mMouseOverHandle == &mTHandle || mMouseOverHandle == &mBHandle)
- setCursor(Qt::SizeVerCursor);
- }
- }
-}
-
-void AreaDialog::mousePressEvent(QMouseEvent* e)
-{
- mShowHelp = false;
- mIdleTimer.stop();
-
- if (mAcceptWidget)
- mAcceptWidget->hide();
-
- if (e->button() == Qt::LeftButton) {
- mMouseDown = true;
- mDragStartPoint = e->pos();
- mSelectionBeforeDrag = mSelection;
- if (!mSelection.contains(e->pos())) {
- mNewSelection = true;
- mSelection = QRect();
- mShowHelp = true;
- setCursor(Qt::CrossCursor);
- }
- else {
- setCursor(Qt::ClosedHandCursor);
- }
- }
- else if (e->button() == Qt::RightButton
- || e->button() == Qt::MidButton)
- {
- cancel();
- }
-
- update();
-}
-
-void AreaDialog::mouseReleaseEvent(QMouseEvent* e)
-{
- if (mAutoclose)
- grabRect();
-
- if (!mSelection.isNull() && mAcceptWidget)
- mAcceptWidget->show();
-
- mMouseDown = false;
- mNewSelection = false;
- mIdleTimer.start();
-
- if (mMouseOverHandle == 0 && mSelection.contains(e->pos()))
- setCursor(Qt::OpenHandCursor);
-
- update();
-}
-
-void AreaDialog::paintEvent(QPaintEvent* e)
-{
- Q_UNUSED(e);
-
- if (mGrabbing) // grabWindow() should just get the background
- return;
-
- QPainter painter(this);
-
- QPalette pal = palette();
- QFont font = QToolTip::font();
-
- QColor handleColor(25, 115, 240, 180);
- QColor overlayColor(0, 0, 0, mOverlayAlpha);
- QColor textColor = pal.color(QPalette::Active, QPalette::Text);
- QColor textBackgroundColor = pal.color(QPalette::Active, QPalette::Base);
- painter.drawPixmap(0, 0, mScreenshot->pixmap());
- painter.setFont(font);
-
- QRect r = mSelection.normalized().adjusted(0, 0, -1, -1);
-
- QRegion grey(rect());
- grey = grey.subtracted(r);
- painter.setPen(handleColor);
- painter.setBrush(overlayColor);
- painter.setClipRegion(grey);
- painter.drawRect(-1, -1, rect().width() + 1, rect().height() + 1);
- painter.setClipRect(rect());
- painter.setBrush(Qt::NoBrush);
- painter.drawRect(r);
-
- if (mShowHelp) {
- //Drawing the explanatory text.
- QRect helpRect = qApp->desktop()->screenGeometry(qApp->desktop()->primaryScreen());
- QString helpTxt = tr("Lightscreen area mode:\nUse your mouse to draw a rectangle to capture.\nPress any key or right click to exit.");
-
- helpRect.setHeight(qRound(helpRect.height() / 10)); // We get a decently sized rect where the text should be drawn (centered)
-
- // We draw the white contrasting background for the text, using the same text and options to get the boundingRect that the text will have.
- painter.setPen(QPen(Qt::white));
- painter.setBrush(QBrush(QColor(255, 255, 255, 180), Qt::SolidPattern));
- QRectF bRect = painter.boundingRect(helpRect, Qt::AlignCenter, helpTxt);
-
- // These four calls provide padding for the rect
- bRect.setWidth(bRect.width() + 12);
- bRect.setHeight(bRect.height() + 10);
- bRect.setX(bRect.x() - 12);
- bRect.setY(bRect.y() - 10);
-
- painter.drawRoundedRect(bRect, 8, 8);
-
- // Draw the text:
- painter.setPen(QPen(Qt::black));
- painter.drawText(helpRect, Qt::AlignCenter, helpTxt);
- }
-
- if (!mSelection.isNull()) {
- // The grabbed region is everything which is covered by the drawn
- // rectangles (border included). This means that there is no 0px
- // selection, since a 0px wide rectangle will always be drawn as a line.
- QString txt = QString("%1x%2").arg(mSelection.width() == 0 ? 2 : mSelection.width())
- .arg(mSelection.height() == 0 ? 2 : mSelection.height());
- QRect textRect = painter.boundingRect(rect(), Qt::AlignLeft, txt);
- QRect boundingRect = textRect.adjusted(-4, 0, 0, 0);
-
- if (textRect.width() < r.width() - 2*mHandleSize &&
- textRect.height() < r.height() - 2*mHandleSize &&
- (r.width() > 100 && r.height() > 100)) // center, unsuitable for small selections
- {
- boundingRect.moveCenter(r.center());
- textRect.moveCenter(r.center());
- }
- else if (r.y() - 3 > textRect.height() &&
- r.x() + textRect.width() < rect().right()) // on top, left aligned
- {
- boundingRect.moveBottomLeft(QPoint(r.x(), r.y() - 3));
- textRect.moveBottomLeft(QPoint(r.x() + 2, r.y() - 3));
- }
- else if (r.x() - 3 > textRect.width()) // left, top aligned
- {
- boundingRect.moveTopRight(QPoint(r.x() - 3, r.y()));
- textRect.moveTopRight(QPoint(r.x() - 5, r.y()));
- }
- else if (r.bottom() + 3 + textRect.height() < rect().bottom() &&
- r.right() > textRect.width()) // at bottom, right aligned
- {
- boundingRect.moveTopRight(QPoint(r.right(), r.bottom() + 3));
- textRect.moveTopRight(QPoint(r.right() - 2, r.bottom() + 3));
- }
- else if (r.right() + textRect.width() + 3 < rect().width()) // right, bottom aligned
- {
- boundingRect.moveBottomLeft(QPoint(r.right() + 3, r.bottom()));
- textRect.moveBottomLeft(QPoint(r.right() + 5, r.bottom()));
- }
- // if the above didn't catch it, you are running on a very tiny screen...
- painter.setPen(textColor);
- painter.setBrush(textBackgroundColor);
- painter.drawRect(boundingRect);
- painter.drawText(textRect, txt);
-
- if ((r.height() > mHandleSize*2 && r.width() > mHandleSize*2)
- || !mMouseDown)
- {
- updateHandles();
- painter.setPen(handleColor);
- handleColor.setAlpha(80);
- painter.setBrush(handleColor);
- painter.drawRects(handleMask().rects());
- }
- }
-
- if (!mScreenshot->options().magnify)
- return;
-
- // Drawing the magnified version
- QPoint magStart, magEnd, drawPosition;
- QRect newRect;
-
- QRect pixmapRect = mScreenshot->pixmap().rect();
-
- if (mMouseMagnifier) {
- drawPosition = QCursor::pos() - QPoint(100, 100);
-
- magStart = QCursor::pos() - QPoint(50, 50);
- magEnd = QCursor::pos() + QPoint(50, 50);
-
- newRect = QRect(magStart, magEnd);
- }
- else {
- // So pretty.. oh so pretty.
- if (mMouseOverHandle == &mTLHandle)
- magStart = mSelection.topLeft();
- else if (mMouseOverHandle == &mTRHandle)
- magStart = mSelection.topRight();
- else if (mMouseOverHandle == &mBLHandle)
- magStart = mSelection.bottomLeft();
- else if (mMouseOverHandle == &mBRHandle)
- magStart = mSelection.bottomRight();
- else if (mMouseOverHandle == &mLHandle)
- magStart = QPoint(mSelection.left(), mSelection.center().y());
- else if (mMouseOverHandle == &mTHandle)
- magStart = QPoint(mSelection.center().x(), mSelection.top());
- else if (mMouseOverHandle == &mRHandle)
- magStart = QPoint(mSelection.right(), mSelection.center().y());
- else if (mMouseOverHandle == &mBHandle)
- magStart = QPoint(mSelection.center().x(), mSelection.bottom());
- else if (mMouseOverHandle == 0)
- magStart = QCursor::pos();
-
- magEnd = magStart;
- drawPosition = mSelection.bottomRight();
-
- magStart -= QPoint(50, 50);
- magEnd += QPoint(50, 50);
-
- newRect = QRect(magStart, magEnd);
-
- if ((drawPosition.x()+newRect.width()*2) > pixmapRect.width())
- drawPosition.setX(drawPosition.x()-newRect.width()*2);
-
- if ((drawPosition.y()+newRect.height()*2) > pixmapRect.height())
- drawPosition.setY(drawPosition.y()-newRect.height()*2);
-
- if (drawPosition.y() == mSelection.bottomRight().y()-newRect.height()*2
- && drawPosition.x() == mSelection.bottomRight().x()-newRect.width()*2)
- painter.setOpacity(0.7);
- }
-
- if (!pixmapRect.contains(newRect, true) || drawPosition.x() <= 0 || drawPosition.y() <= 0) {
- return;
- }
-
- QPixmap magnified = mScreenshot->pixmap().copy(newRect).scaled(QSize(newRect.width()*2, newRect.height()*2));
-
- QPainter magPainter(&magnified);
- magPainter.setPen(QPen(QBrush(QColor(25, 115, 240)), 2)); // Same border pen
- magPainter.drawRect(magnified.rect());
-
- if (!mMouseMagnifier) {
- magPainter.drawText(magnified.rect().center()-QPoint(4, -4), "+"); //Center minus the 4 pixels wide and across of the "+" -- TODO: Test alternative DPI settings.
- }
-
- painter.drawPixmap(drawPosition, magnified);
-}
-
-void AreaDialog::resizeEvent(QResizeEvent* e)
-{
- Q_UNUSED(e);
-
- if (mSelection.isNull())
- return;
-
- QRect r = mSelection;
- r.setTopLeft(limitPointToRect(r.topLeft(), rect()));
- r.setBottomRight(limitPointToRect(r.bottomRight(), rect()));
-
- if (r.width() <= 1 || r.height() <= 1) //this just results in ugly drawing...
- r = QRect();
-
- mSelection = r;
-}
-
-void AreaDialog::showEvent(QShowEvent* e)
-{
- Q_UNUSED(e)
-
- QRect geometry = qApp->desktop()->geometry();
-
- if (mScreenshot->options().currentMonitor) {
- geometry = qApp->desktop()->screenGeometry(qApp->desktop()->screenNumber(QCursor::pos()));
- }
-
- resize(geometry.size());
- move(geometry.topLeft());
-
- if (mScreenshot->options().animations) {
- os::effect(this, SLOT(animationTick(int)), 85, 300);
- }
- else {
- animationTick(85);
- }
-
- setMouseTracking(true);
-}
-
-void AreaDialog::updateHandles()
-{
- QRect r = mSelection.normalized().adjusted(0, 0, -1, -1);
- int s2 = mHandleSize / 2;
-
- mTLHandle.moveTopLeft(r.topLeft());
- mTRHandle.moveTopRight(r.topRight());
- mBLHandle.moveBottomLeft(r.bottomLeft());
- mBRHandle.moveBottomRight(r.bottomRight());
-
- mLHandle.moveTopLeft(QPoint(r.x(), r.y() + r.height() / 2 - s2));
- mTHandle.moveTopLeft(QPoint(r.x() + r.width() / 2 - s2, r.y()));
- mRHandle.moveTopRight(QPoint(r.right(), r.y() + r.height() / 2 - s2));
- mBHandle.moveBottomLeft(QPoint(r.x() + r.width() / 2 - s2, r.bottom()));
-}
-
-QRegion AreaDialog::handleMask() const
-{
- // note: not normalized QRects are bad here, since they will not be drawn
- QRegion mask;
- foreach(QRect* rect, mHandles) mask += QRegion(*rect);
- return mask;
-}
-
-QPoint AreaDialog::limitPointToRect(const QPoint &p, const QRect &r) const
-{
- QPoint q;
- q.setX(p.x() < r.x() ? r.x() : p.x() < r.right() ? p.x() : r.right());
- q.setY(p.y() < r.y() ? r.y() : p.y() < r.bottom() ? p.y() : r.bottom());
- return q;
-}
+/*
+ * 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
+ *
+ ******
+ *
+ * Based on KDE's KSnapshot regiongrabber.cpp, revision 796531, Copyright 2007 Luca Gugelmann <lucag@student.ethz.ch>
+ * released under the GNU LGPL <http://www.gnu.org/licenses/old-licenses/library.txt>
+ *
+ */
+#include "areadialog.h"
+#include "../tools/os.h"
+#include "../tools/screenshot.h"
+#include "../tools/screenshotmanager.h"
+
+#include <QApplication>
+#include <QDesktopWidget>
+#include <QHBoxLayout>
+#include <QMouseEvent>
+#include <QPainter>
+#include <QPushButton>
+#include <QSettings>
+#include <QTimer>
+#include <QToolTip>
+
+#include <QDebug>
+
+AreaDialog::AreaDialog(Screenshot *screenshot) :
+ QDialog(0), mScreenshot(screenshot), mMouseDown(false), mMouseMagnifier(false),
+ mNewSelection(false), mHandleSize(10), mMouseOverHandle(0), mIdleTimer(),
+ mShowHelp(true), mGrabbing(false), mOverlayAlpha(1), mAutoclose(false),
+ mTLHandle(0, 0, mHandleSize, mHandleSize), mTRHandle(0, 0, mHandleSize, mHandleSize),
+ mBLHandle(0, 0, mHandleSize, mHandleSize), mBRHandle(0, 0, mHandleSize, mHandleSize),
+ mLHandle(0, 0, mHandleSize, mHandleSize), mTHandle(0, 0, mHandleSize, mHandleSize),
+ mRHandle(0, 0, mHandleSize, mHandleSize), mBHandle(0, 0, mHandleSize, mHandleSize)
+{
+ mHandles << &mTLHandle << &mTRHandle << &mBLHandle << &mBRHandle
+ << &mLHandle << &mTHandle << &mRHandle << &mBHandle;
+
+ mMouseOverHandle = 0;
+
+ setMouseTracking(true);
+ setWindowTitle(tr("Lightscreen Area Mode"));
+ setWindowFlags(Qt::WindowStaysOnTopHint | Qt::FramelessWindowHint | Qt::X11BypassWindowManagerHint);
+
+ setCursor(Qt::CrossCursor);
+
+ connect(&mIdleTimer, SIGNAL(timeout()), this, SLOT(displayHelp()));
+ mIdleTimer.start(2000);
+
+ mAutoclose = ScreenshotManager::instance()->settings()->value("options/areaAutoclose").toBool();
+
+ if (mAutoclose)
+ return; // Avoid creating the accept widget if it's not going to get used.
+
+ // Creating accept widget:
+ mAcceptWidget = new QWidget(this);
+ mAcceptWidget->resize(110, 60);
+ mAcceptWidget->setWindowOpacity(0.4);
+ mAcceptWidget->setGraphicsEffect(os::shadow(QColor(50, 50, 50, 255), 8));
+ mAcceptWidget->setStyleSheet("QWidget { background: qlineargradient(spread:pad, x1:0, y1:0, x2:0, y2:1, stop:0 rgba(140, 140, 140, 230), stop:1 rgba(80, 80, 80, 230)); padding: 6px 10px; border: 1px solid rgba(0, 0, 0, 200); border-radius: 8px; } QPushButton { background: transparent; border: none; height: 50px; color: white; padding: 0; } QPushButton:hover { cursor: hand; }");
+
+ QPushButton *awAcceptButton = new QPushButton(QIcon(":/icons/yes.big"), "", this);
+ connect(awAcceptButton, SIGNAL(clicked()), this, SLOT(grabRect()));
+ awAcceptButton->setCursor(Qt::PointingHandCursor);
+ awAcceptButton->setIconSize(QSize(48, 48));
+ awAcceptButton->setGraphicsEffect(os::shadow(QColor(50, 50, 50, 255)));
+
+ QPushButton *awRejectButton = new QPushButton(QIcon(":/icons/no.big"), "", this);
+ connect(awRejectButton, SIGNAL(clicked()), this, SLOT(cancel()));
+ awRejectButton->setCursor(Qt::PointingHandCursor);
+ awRejectButton->setIconSize(QSize(48, 48));
+ awRejectButton->setGraphicsEffect(os::shadow(QColor(50, 50, 50, 255)));
+
+ QHBoxLayout *awLayout = new QHBoxLayout(this);
+ awLayout->addWidget(awAcceptButton);
+ awLayout->addWidget(awRejectButton);
+ awLayout->setMargin(0);
+ awLayout->setSpacing(0);
+
+ mAcceptWidget->setLayout(awLayout);
+ mAcceptWidget->setVisible(false);
+}
+
+QRect &AreaDialog::resultRect()
+{
+ return mSelection;
+}
+
+void AreaDialog::animationTick(int frame)
+{
+ mOverlayAlpha = frame;
+ update();
+}
+
+void AreaDialog::cancel()
+{
+ reject();
+}
+
+void AreaDialog::displayHelp()
+{
+ mShowHelp = true;
+ update();
+}
+
+void AreaDialog::grabRect()
+{
+ QRect r = mSelection.normalized();
+ if (!r.isNull() && r.isValid()) {
+ mGrabbing = true;
+ accept();
+ }
+}
+
+void AreaDialog::keyPressEvent(QKeyEvent* e)
+{
+ if (e->key() == Qt::Key_Escape) {
+ cancel();
+ }
+ else if (e->key() == Qt::Key_Enter || e->key() == Qt::Key_Return) {
+ grabRect();
+ }
+ else {
+ e->ignore();
+ }
+}
+
+void AreaDialog::mouseDoubleClickEvent(QMouseEvent*)
+{
+ grabRect();
+}
+
+void AreaDialog::mouseMoveEvent(QMouseEvent* e)
+{
+ mMouseMagnifier = false;
+
+ if (mMouseDown) {
+
+ mMousePos = e->pos();
+
+ if (mNewSelection) {
+ QRect r = rect();
+
+ mSelection = QRect(mDragStartPoint, limitPointToRect(mMousePos, r)).normalized();
+ }
+ else if (mMouseOverHandle == 0) { // moving the whole selection
+ QRect r = rect().normalized(), s = mSelectionBeforeDrag.normalized();
+ QPoint p = s.topLeft() + e->pos() - mDragStartPoint;
+ r.setBottomRight(r.bottomRight() - QPoint(s.width(), s.height()));
+
+ if (!r.isNull() && r.isValid())
+ mSelection.moveTo(limitPointToRect(p, r));
+ }
+ else {// dragging a handle
+ QRect r = mSelectionBeforeDrag;
+ QPoint offset = e->pos() - mDragStartPoint;
+
+ if (mMouseOverHandle == &mTLHandle || mMouseOverHandle == &mTHandle
+ || mMouseOverHandle == &mTRHandle) // dragging one of the top handles
+ {
+ r.setTop(r.top() + offset.y());
+ }
+
+ if (mMouseOverHandle == &mTLHandle || mMouseOverHandle == &mLHandle
+ || mMouseOverHandle == &mBLHandle) // dragging one of the left handles
+ {
+ r.setLeft(r.left() + offset.x());
+ }
+
+ if (mMouseOverHandle == &mBLHandle || mMouseOverHandle == &mBHandle
+ || mMouseOverHandle == &mBRHandle) // dragging one of the bottom handles
+ {
+ r.setBottom(r.bottom() + offset.y());
+ }
+
+ if (mMouseOverHandle == &mTRHandle || mMouseOverHandle == &mRHandle
+ || mMouseOverHandle == &mBRHandle) // dragging one of the right handles
+ {
+ r.setRight(r.right() + offset.x());
+ }
+
+ r = r.normalized();
+ r.setTopLeft(limitPointToRect(r.topLeft(), rect()));
+ r.setBottomRight(limitPointToRect(r.bottomRight(), rect()));
+ mSelection = r;
+ }
+
+ if (qApp->keyboardModifiers() & Qt::ControlModifier)
+ {
+ // The lazy 1:1 aspect ratio approach!
+ mSelection.setHeight(mSelection.width());
+ }
+
+ if (mAcceptWidget) {
+ QPoint acceptPos = e->pos();
+ QRect acceptRect = QRect(acceptPos, QSize(120, 70));
+
+ // Prevent the widget from overlapping the handles
+ if (acceptRect.intersects(mTLHandle)) {
+ acceptPos = mTLHandle.bottomRight() + QPoint(2, 2); // Corner case
+ }
+
+ if (acceptRect.intersects(mBRHandle)) {
+ acceptPos = mBRHandle.bottomRight();
+ }
+
+ if (acceptRect.intersects(mBHandle)) {
+ acceptPos = mBHandle.bottomRight();
+ }
+
+ if (acceptRect.intersects(mRHandle)) {
+ acceptPos = mRHandle.topRight();
+ }
+
+ if (acceptRect.intersects(mTHandle)) {
+ acceptPos = mTHandle.bottomRight();
+ }
+
+ if ((acceptPos.x()+120) > mScreenshot->pixmap().rect().width())
+ acceptPos.setX(acceptPos.x()-120);
+
+ if ((acceptPos.y()+70) > mScreenshot->pixmap().rect().height())
+ acceptPos.setY(acceptPos.y()-70);
+
+ mAcceptWidget->move(acceptPos);
+ }
+
+ update();
+ }
+ else
+ {
+ if (mSelection.isNull()) {
+ mMouseMagnifier = true;
+ update();
+ return;
+ }
+
+ bool found = false;
+ foreach(QRect* r, mHandles) {
+ if (r->contains(e->pos())) {
+ mMouseOverHandle = r;
+ found = true;
+ break;
+ }
+ }
+
+ if (!found) {
+ mMouseOverHandle = 0;
+ if (mSelection.contains(e->pos()))
+ setCursor(Qt::OpenHandCursor);
+ else if (mAcceptWidget && QRect(mAcceptWidget->mapToParent(mAcceptWidget->pos()), QSize(100, 60)).contains(e->pos()))
+ setCursor(Qt::PointingHandCursor);
+ else
+ setCursor(Qt::CrossCursor);
+ }
+ else {
+ if (mMouseOverHandle == &mTLHandle || mMouseOverHandle == &mBRHandle)
+ setCursor(Qt::SizeFDiagCursor);
+ if (mMouseOverHandle == &mTRHandle || mMouseOverHandle == &mBLHandle)
+ setCursor(Qt::SizeBDiagCursor);
+ if (mMouseOverHandle == &mLHandle || mMouseOverHandle == &mRHandle)
+ setCursor(Qt::SizeHorCursor);
+ if (mMouseOverHandle == &mTHandle || mMouseOverHandle == &mBHandle)
+ setCursor(Qt::SizeVerCursor);
+ }
+ }
+}
+
+void AreaDialog::mousePressEvent(QMouseEvent* e)
+{
+ mShowHelp = false;
+ mIdleTimer.stop();
+
+ if (mAcceptWidget)
+ mAcceptWidget->hide();
+
+ if (e->button() == Qt::LeftButton) {
+ mMouseDown = true;
+ mDragStartPoint = e->pos();
+ mSelectionBeforeDrag = mSelection;
+ if (!mSelection.contains(e->pos())) {
+ mNewSelection = true;
+ mSelection = QRect();
+ mShowHelp = true;
+ setCursor(Qt::CrossCursor);
+ }
+ else {
+ setCursor(Qt::ClosedHandCursor);
+ }
+ }
+ else if (e->button() == Qt::RightButton
+ || e->button() == Qt::MidButton)
+ {
+ cancel();
+ }
+
+ update();
+}
+
+void AreaDialog::mouseReleaseEvent(QMouseEvent* e)
+{
+ if (mAutoclose)
+ grabRect();
+
+ if (!mSelection.isNull() && mAcceptWidget)
+ mAcceptWidget->show();
+
+ mMouseDown = false;
+ mNewSelection = false;
+ mIdleTimer.start();
+
+ if (mMouseOverHandle == 0 && mSelection.contains(e->pos()))
+ setCursor(Qt::OpenHandCursor);
+
+ update();
+}
+
+void AreaDialog::paintEvent(QPaintEvent* e)
+{
+ Q_UNUSED(e);
+
+ if (mGrabbing) // grabWindow() should just get the background
+ return;
+
+ QPainter painter(this);
+
+ QPalette pal = palette();
+ QFont font = QToolTip::font();
+
+ QColor handleColor(25, 115, 240, 180);
+ QColor overlayColor(0, 0, 0, mOverlayAlpha);
+ QColor textColor = pal.color(QPalette::Active, QPalette::Text);
+ QColor textBackgroundColor = pal.color(QPalette::Active, QPalette::Base);
+ painter.drawPixmap(0, 0, mScreenshot->pixmap());
+ painter.setFont(font);
+
+ QRect r = mSelection.normalized().adjusted(0, 0, -1, -1);
+
+ QRegion grey(rect());
+ grey = grey.subtracted(r);
+ painter.setPen(handleColor);
+ painter.setBrush(overlayColor);
+ painter.setClipRegion(grey);
+ painter.drawRect(-1, -1, rect().width() + 1, rect().height() + 1);
+ painter.setClipRect(rect());
+ painter.setBrush(Qt::NoBrush);
+ painter.drawRect(r);
+
+ if (mShowHelp) {
+ //Drawing the explanatory text.
+ QRect helpRect = qApp->desktop()->screenGeometry(qApp->desktop()->primaryScreen());
+ QString helpTxt = tr("Lightscreen area mode:\nUse your mouse to draw a rectangle to capture.\nPress any key or right click to exit.");
+
+ helpRect.setHeight(qRound((float)(helpRect.height() / 10))); // We get a decently sized rect where the text should be drawn (centered)
+
+ // We draw the white contrasting background for the text, using the same text and options to get the boundingRect that the text will have.
+ painter.setPen(QPen(Qt::white));
+ painter.setBrush(QBrush(QColor(255, 255, 255, 180), Qt::SolidPattern));
+ QRectF bRect = painter.boundingRect(helpRect, Qt::AlignCenter, helpTxt);
+
+ // These four calls provide padding for the rect
+ bRect.setWidth(bRect.width() + 12);
+ bRect.setHeight(bRect.height() + 10);
+ bRect.setX(bRect.x() - 12);
+ bRect.setY(bRect.y() - 10);
+
+ painter.drawRoundedRect(bRect, 8, 8);
+
+ // Draw the text:
+ painter.setPen(QPen(Qt::black));
+ painter.drawText(helpRect, Qt::AlignCenter, helpTxt);
+ }
+
+ if (!mSelection.isNull()) {
+ // The grabbed region is everything which is covered by the drawn
+ // rectangles (border included). This means that there is no 0px
+ // selection, since a 0px wide rectangle will always be drawn as a line.
+ QString txt = QString("%1x%2").arg(mSelection.width() == 0 ? 2 : mSelection.width())
+ .arg(mSelection.height() == 0 ? 2 : mSelection.height());
+ QRect textRect = painter.boundingRect(rect(), Qt::AlignLeft, txt);
+ QRect boundingRect = textRect.adjusted(-4, 0, 0, 0);
+
+ if (textRect.width() < r.width() - 2*mHandleSize &&
+ textRect.height() < r.height() - 2*mHandleSize &&
+ (r.width() > 100 && r.height() > 100)) // center, unsuitable for small selections
+ {
+ boundingRect.moveCenter(r.center());
+ textRect.moveCenter(r.center());
+ }
+ else if (r.y() - 3 > textRect.height() &&
+ r.x() + textRect.width() < rect().right()) // on top, left aligned
+ {
+ boundingRect.moveBottomLeft(QPoint(r.x(), r.y() - 3));
+ textRect.moveBottomLeft(QPoint(r.x() + 2, r.y() - 3));
+ }
+ else if (r.x() - 3 > textRect.width()) // left, top aligned
+ {
+ boundingRect.moveTopRight(QPoint(r.x() - 3, r.y()));
+ textRect.moveTopRight(QPoint(r.x() - 5, r.y()));
+ }
+ else if (r.bottom() + 3 + textRect.height() < rect().bottom() &&
+ r.right() > textRect.width()) // at bottom, right aligned
+ {
+ boundingRect.moveTopRight(QPoint(r.right(), r.bottom() + 3));
+ textRect.moveTopRight(QPoint(r.right() - 2, r.bottom() + 3));
+ }
+ else if (r.right() + textRect.width() + 3 < rect().width()) // right, bottom aligned
+ {
+ boundingRect.moveBottomLeft(QPoint(r.right() + 3, r.bottom()));
+ textRect.moveBottomLeft(QPoint(r.right() + 5, r.bottom()));
+ }
+ // if the above didn't catch it, you are running on a very tiny screen...
+ painter.setPen(textColor);
+ painter.setBrush(textBackgroundColor);
+ painter.drawRect(boundingRect);
+ painter.drawText(textRect, txt);
+
+ if ((r.height() > mHandleSize*2 && r.width() > mHandleSize*2)
+ || !mMouseDown)
+ {
+ updateHandles();
+ painter.setPen(handleColor);
+ handleColor.setAlpha(80);
+ painter.setBrush(handleColor);
+ painter.drawRects(handleMask().rects());
+ }
+ }
+
+ if (!mScreenshot->options().magnify)
+ return;
+
+ // Drawing the magnified version
+ QPoint magStart, magEnd, drawPosition;
+ QRect newRect;
+
+ QRect pixmapRect = mScreenshot->pixmap().rect();
+
+ if (mMouseMagnifier) {
+ drawPosition = QCursor::pos() - QPoint(100, 100);
+
+ magStart = QCursor::pos() - QPoint(50, 50);
+ magEnd = QCursor::pos() + QPoint(50, 50);
+
+ newRect = QRect(magStart, magEnd);
+ }
+ else {
+ // So pretty.. oh so pretty.
+ if (mMouseOverHandle == &mTLHandle)
+ magStart = mSelection.topLeft();
+ else if (mMouseOverHandle == &mTRHandle)
+ magStart = mSelection.topRight();
+ else if (mMouseOverHandle == &mBLHandle)
+ magStart = mSelection.bottomLeft();
+ else if (mMouseOverHandle == &mBRHandle)
+ magStart = mSelection.bottomRight();
+ else if (mMouseOverHandle == &mLHandle)
+ magStart = QPoint(mSelection.left(), mSelection.center().y());
+ else if (mMouseOverHandle == &mTHandle)
+ magStart = QPoint(mSelection.center().x(), mSelection.top());
+ else if (mMouseOverHandle == &mRHandle)
+ magStart = QPoint(mSelection.right(), mSelection.center().y());
+ else if (mMouseOverHandle == &mBHandle)
+ magStart = QPoint(mSelection.center().x(), mSelection.bottom());
+ else if (mMouseOverHandle == 0)
+ magStart = QCursor::pos();
+
+ magEnd = magStart;
+ drawPosition = mSelection.bottomRight();
+
+ magStart -= QPoint(50, 50);
+ magEnd += QPoint(50, 50);
+
+ newRect = QRect(magStart, magEnd);
+
+ if ((drawPosition.x()+newRect.width()*2) > pixmapRect.width())
+ drawPosition.setX(drawPosition.x()-newRect.width()*2);
+
+ if ((drawPosition.y()+newRect.height()*2) > pixmapRect.height())
+ drawPosition.setY(drawPosition.y()-newRect.height()*2);
+
+ if (drawPosition.y() == mSelection.bottomRight().y()-newRect.height()*2
+ && drawPosition.x() == mSelection.bottomRight().x()-newRect.width()*2)
+ painter.setOpacity(0.7);
+ }
+
+ if (!pixmapRect.contains(newRect, true) || drawPosition.x() <= 0 || drawPosition.y() <= 0) {
+ return;
+ }
+
+ QPixmap magnified = mScreenshot->pixmap().copy(newRect).scaled(QSize(newRect.width()*2, newRect.height()*2));
+
+ QPainter magPainter(&magnified);
+ magPainter.setPen(QPen(QBrush(QColor(25, 115, 240)), 2)); // Same border pen
+ magPainter.drawRect(magnified.rect());
+
+ if (!mMouseMagnifier) {
+ magPainter.drawText(magnified.rect().center()-QPoint(4, -4), "+"); //Center minus the 4 pixels wide and across of the "+" -- TODO: Test alternative DPI settings.
+ }
+
+ painter.drawPixmap(drawPosition, magnified);
+}
+
+void AreaDialog::resizeEvent(QResizeEvent* e)
+{
+ Q_UNUSED(e);
+
+ if (mSelection.isNull())
+ return;
+
+ QRect r = mSelection;
+ r.setTopLeft(limitPointToRect(r.topLeft(), rect()));
+ r.setBottomRight(limitPointToRect(r.bottomRight(), rect()));
+
+ if (r.width() <= 1 || r.height() <= 1) //this just results in ugly drawing...
+ r = QRect();
+
+ mSelection = r;
+}
+
+void AreaDialog::showEvent(QShowEvent* e)
+{
+ Q_UNUSED(e)
+
+ QRect geometry = qApp->desktop()->geometry();
+
+ if (mScreenshot->options().currentMonitor) {
+ geometry = qApp->desktop()->screenGeometry(qApp->desktop()->screenNumber(QCursor::pos()));
+ }
+
+ resize(geometry.size());
+ move(geometry.topLeft());
+
+ if (mScreenshot->options().animations) {
+ os::effect(this, SLOT(animationTick(int)), 85, 300);
+ }
+ else {
+ animationTick(85);
+ }
+
+ setMouseTracking(true);
+}
+
+void AreaDialog::updateHandles()
+{
+ QRect r = mSelection.normalized().adjusted(0, 0, -1, -1);
+ int s2 = mHandleSize / 2;
+
+ mTLHandle.moveTopLeft(r.topLeft());
+ mTRHandle.moveTopRight(r.topRight());
+ mBLHandle.moveBottomLeft(r.bottomLeft());
+ mBRHandle.moveBottomRight(r.bottomRight());
+
+ mLHandle.moveTopLeft(QPoint(r.x(), r.y() + r.height() / 2 - s2));
+ mTHandle.moveTopLeft(QPoint(r.x() + r.width() / 2 - s2, r.y()));
+ mRHandle.moveTopRight(QPoint(r.right(), r.y() + r.height() / 2 - s2));
+ mBHandle.moveBottomLeft(QPoint(r.x() + r.width() / 2 - s2, r.bottom()));
+}
+
+QRegion AreaDialog::handleMask() const
+{
+ // note: not normalized QRects are bad here, since they will not be drawn
+ QRegion mask;
+ foreach(QRect* rect, mHandles) mask += QRegion(*rect);
+ return mask;
+}
+
+QPoint AreaDialog::limitPointToRect(const QPoint &p, const QRect &r) const
+{
+ QPoint q;
+ q.setX(p.x() < r.x() ? r.x() : p.x() < r.right() ? p.x() : r.right());
+ q.setY(p.y() < r.y() ? r.y() : p.y() < r.bottom() ? p.y() : r.bottom());
+ return q;
+}
diff --git a/dialogs/areadialog.h b/dialogs/areadialog.h
index da0b17e..adf47ea 100644
--- a/dialogs/areadialog.h
+++ b/dialogs/areadialog.h
@@ -1,99 +1,99 @@
-/*
- * 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
- *
- ******
- *
- * Based on KDE's KSnapshot regiongrabber.cpp, revision 796531, Copyright 2007 Luca Gugelmann <lucag@student.ethz.ch>
- * released under the GNU LGPL <http://www.gnu.org/licenses/old-licenses/library.txt>
- *
- */
-#ifndef AREADIALOG_H
-#define AREADIALOG_H
-
-#include <QDialog>
-#include <QVector>
-#include <QPointer>
-#include <QTimer>
-
-struct QRegion;
-struct QPoint;
-struct QRect;
-class QPaintEvent;
-class QResizeEvent;
-class QMouseEvent;
-class Screenshot;
-
-class AreaDialog : public QDialog
-{
- Q_OBJECT
-
-public:
- AreaDialog(Screenshot* screenshot);
- QRect &resultRect();
-
-protected slots:
- void animationTick(int frame);
- void cancel();
- void displayHelp();
- void grabRect();
-
-signals:
- void regionGrabbed( const QPixmap & );
-
-protected:
- void keyPressEvent( QKeyEvent* e );
- void mouseDoubleClickEvent( QMouseEvent* );
- void mouseMoveEvent( QMouseEvent* e );
- void mousePressEvent( QMouseEvent* e );
- void mouseReleaseEvent( QMouseEvent* e );
- void paintEvent( QPaintEvent* e );
- void resizeEvent( QResizeEvent* e );
- void showEvent( QShowEvent* e );
-
- void updateHandles();
- QRegion handleMask() const;
-
- QPoint limitPointToRect( const QPoint &p, const QRect &r ) const;
-
- bool mAutoclose;
- QPoint mDragStartPoint;
- bool mGrabbing;
- const int mHandleSize;
- QTimer mIdleTimer;
- bool mMouseDown;
- bool mMouseMagnifier;
- QRect *mMouseOverHandle;
- QPoint mMousePos;
- bool mNewSelection;
- int mOverlayAlpha;
- Screenshot *mScreenshot;
- QRect mSelection;
- QRect mSelectionBeforeDrag;
- bool mShowHelp;
-
- // naming convention for handles
- // T top, B bottom, R Right, L left
- // 2 letters: a corner
- // 1 letter: the handle on the middle of the corresponding side
- QRect mTLHandle, mTRHandle, mBLHandle, mBRHandle;
- QRect mLHandle, mTHandle, mRHandle, mBHandle;
-
- QVector<QRect*> mHandles;
- QPointer<QWidget> mAcceptWidget;
-};
-
-#endif
+/*
+ * 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
+ *
+ ******
+ *
+ * Based on KDE's KSnapshot regiongrabber.cpp, revision 796531, Copyright 2007 Luca Gugelmann <lucag@student.ethz.ch>
+ * released under the GNU LGPL <http://www.gnu.org/licenses/old-licenses/library.txt>
+ *
+ */
+#ifndef AREADIALOG_H
+#define AREADIALOG_H
+
+#include <QDialog>
+#include <QVector>
+#include <QPointer>
+#include <QTimer>
+#include <QRegion>
+#include <QRect>
+#include <QPoint>
+
+class QPaintEvent;
+class QResizeEvent;
+class QMouseEvent;
+class Screenshot;
+
+class AreaDialog : public QDialog
+{
+ Q_OBJECT
+
+public:
+ AreaDialog(Screenshot* screenshot);
+ QRect &resultRect();
+
+protected slots:
+ void animationTick(int frame);
+ void cancel();
+ void displayHelp();
+ void grabRect();
+
+signals:
+ void regionGrabbed( const QPixmap & );
+
+protected:
+ void keyPressEvent( QKeyEvent* e );
+ void mouseDoubleClickEvent( QMouseEvent* );
+ void mouseMoveEvent( QMouseEvent* e );
+ void mousePressEvent( QMouseEvent* e );
+ void mouseReleaseEvent( QMouseEvent* e );
+ void paintEvent( QPaintEvent* e );
+ void resizeEvent( QResizeEvent* e );
+ void showEvent( QShowEvent* e );
+
+ void updateHandles();
+ QRegion handleMask() const;
+
+ QPoint limitPointToRect( const QPoint &p, const QRect &r ) const;
+
+ bool mAutoclose;
+ QPoint mDragStartPoint;
+ bool mGrabbing;
+ const int mHandleSize;
+ QTimer mIdleTimer;
+ bool mMouseDown;
+ bool mMouseMagnifier;
+ QRect *mMouseOverHandle;
+ QPoint mMousePos;
+ bool mNewSelection;
+ int mOverlayAlpha;
+ Screenshot *mScreenshot;
+ QRect mSelection;
+ QRect mSelectionBeforeDrag;
+ bool mShowHelp;
+
+ // naming convention for handles
+ // T top, B bottom, R Right, L left
+ // 2 letters: a corner
+ // 1 letter: the handle on the middle of the corresponding side
+ QRect mTLHandle, mTRHandle, mBLHandle, mBRHandle;
+ QRect mLHandle, mTHandle, mRHandle, mBHandle;
+
+ QVector<QRect*> mHandles;
+ QPointer<QWidget> mAcceptWidget;
+};
+
+#endif
diff --git a/dialogs/historydialog.cpp b/dialogs/historydialog.cpp
index 4560ffe..ca31840 100644
--- a/dialogs/historydialog.cpp
+++ b/dialogs/historydialog.cpp
@@ -1,246 +1,282 @@
-#include "historydialog.h"
-#include "ui_historydialog.h"
-
-#include "../tools/os.h"
-#include "../tools/uploader.h"
-#include "../tools/screenshotmanager.h"
-
-#include <QClipboard>
-#include <QDesktopServices>
-#include <QDir>
-#include <QFile>
-#include <QFileInfo>
-#include <QFileSystemWatcher>
-#include <QMenu>
-#include <QMessageBox>
-#include <QSortFilterProxyModel>
-#include <QUrl>
-
-#include <QtSql/QSqlDatabase>
-#include <QtSql/QSqlTableModel>
-
-#include <QDebug>
-
-HistoryDialog::HistoryDialog(QWidget *parent) :
- QDialog(parent),
- ui(new Ui::HistoryDialog)
-{
- ui->setupUi(this);
-
- ui->filterEdit->setText(tr("Filter.."));
- ui->filterEdit->installEventFilter(this);
-
- if (ScreenshotManager::instance()->history().isOpen())
- {
- QSqlTableModel *model = new QSqlTableModel(this, ScreenshotManager::instance()->history());
- model->setTable("history");
- model->setHeaderData(0, Qt::Horizontal, tr("Screenshot"));
- model->setHeaderData(1, Qt::Horizontal, tr("URL"));
- model->select();
-
- mFilterModel = new QSortFilterProxyModel(model);
- mFilterModel->setSourceModel(model);
- mFilterModel->setDynamicSortFilter(true);
- mFilterModel->setSortCaseSensitivity(Qt::CaseInsensitive);
- mFilterModel->setFilterCaseSensitivity(Qt::CaseInsensitive);
- mFilterModel->setFilterKeyColumn(-1);
-
- ui->tableView->setModel(mFilterModel);
-
- ui->tableView->hideColumn(2); // No delete hash.
- ui->tableView->hideColumn(3); // No timestamp.
-
- ui->tableView->horizontalHeader()->setClickable(false);
- ui->tableView->horizontalHeader()->setMovable(false);
-
- ui->tableView->horizontalHeader()->setResizeMode(0, QHeaderView::Stretch);
- ui->tableView->horizontalHeader()->setResizeMode(1, QHeaderView::ResizeToContents);
-
- ui->tableView->verticalHeader()->hide();
-
- ui->tableView->setTextElideMode(Qt::ElideLeft);
- ui->tableView->setEditTriggers(QAbstractItemView::NoEditTriggers);
- ui->tableView->setAlternatingRowColors(true);
- ui->tableView->setSelectionMode(QAbstractItemView::SingleSelection);
- ui->tableView->setContextMenuPolicy(Qt::CustomContextMenu);
- ui->tableView->setSortingEnabled(true);
-
- if (ui->tableView->model()->rowCount() > 0)
- {
- ui->clearButton->setEnabled(true);
- ui->filterEdit->setEnabled(true);
- }
-
- connect(ui->tableView->selectionModel(), SIGNAL(selectionChanged(QItemSelection,QItemSelection)), this, SLOT(selectionChanged(QItemSelection,QItemSelection)));
- connect(ui->tableView, SIGNAL(doubleClicked(QModelIndex)), this, SLOT(open(QModelIndex)));
- connect(ui->tableView, SIGNAL(customContextMenuRequested(QPoint)), this, SLOT(contextMenu(QPoint)));
- }
- else {
- ui->tableView->setEnabled(false);
- ui->clearButton->setEnabled(false);
- }
-
- ui->uploadProgressBar->setValue (Uploader::instance()->progressSent());
-
- if (Uploader::instance()->progressTotal() == 0) {
- ui->uploadProgressBar->setMaximum(1);
- }
- else {
- ui->uploadProgressBar->setMaximum(Uploader::instance()->progressTotal());
- }
-
- connect(Uploader::instance(), SIGNAL(progress(qint64,qint64)), this, SLOT(uploadProgress(qint64, qint64)));
- connect(ui->uploadButton, SIGNAL(clicked()), this, SLOT(upload()));
- connect(ui->clearButton , SIGNAL(clicked()), this, SLOT(clear()));
-}
-
-HistoryDialog::~HistoryDialog()
-{
- delete ui;
-}
-
-void HistoryDialog::clear()
-{
- if (QMessageBox::question(this,
- tr("Clearing the screenshot history"),
- tr("Are you sure you want to clear your entire screenshot history?\nThis cannot be undone."),
- tr("Clear History"),
- tr("Don't Clear")) == 1) {
- return;
- }
-
- ScreenshotManager::instance()->clearHistory();
- close();
-}
-
-void HistoryDialog::contextMenu(QPoint point)
-{
- mContextIndex = ui->tableView->indexAt(point);;
-
- QMenu contextMenu(ui->tableView);
-
- QAction copyAction((mContextIndex.column() == 0) ? tr("Copy Path") : tr("Copy URL"), &contextMenu);
- connect(&copyAction, SIGNAL(triggered()), this, SLOT(copy()));
- contextMenu.addAction(&copyAction);
-
- QAction deleteAction(tr("Delete from imgur.com"), &contextMenu);
- QAction locationAction(tr("Open Location"), &contextMenu);
-
- if (mContextIndex.column() == 0)
- {
- connect(&locationAction, SIGNAL(triggered()), this, SLOT(location()));
- contextMenu.addAction(&locationAction);
- }
- else {
- connect(&deleteAction, SIGNAL(triggered()), this, SLOT(deleteImage()));
- contextMenu.addAction(&deleteAction);
- }
-
- if (mContextIndex.data().toString().isEmpty()) {
- copyAction.setEnabled(false);
- deleteAction.setEnabled(false);
- }
-
- contextMenu.exec(QCursor::pos());
-}
-
-void HistoryDialog::copy()
-{
- qApp->clipboard()->setText(mContextIndex.data().toString());
-}
-
-void HistoryDialog::deleteImage()
-{
- QDesktopServices::openUrl(mContextIndex.sibling(mContextIndex.row(), 2).data().toString());
-}
-
-void HistoryDialog::location()
-{
- QDesktopServices::openUrl("file:///" + QFileInfo(mContextIndex.data().toString()).absolutePath());
-}
-
-void HistoryDialog::open(QModelIndex index)
-{
- if (index.column() == 0) {
- QDesktopServices::openUrl(QUrl("file:///" + index.data().toString()));
- }
- else {
- QDesktopServices::openUrl(index.data().toUrl());
- }
-}
-
-void HistoryDialog::reloadHistory()
-{
- qobject_cast<QSqlTableModel*>(mFilterModel->sourceModel())->select();
-}
-
-void HistoryDialog::selectionChanged(QItemSelection selected, QItemSelection deselected)
-{
- Q_UNUSED(deselected);
-
- QModelIndex index = selected.indexes().at(0);
-
- QString screenshot, url;
-
- if (index.column() == 0) {
- screenshot = index.data().toString();
- url = ui->tableView->model()->index(index.row(), 1).data().toString();
- }
- else {
- screenshot = ui->tableView->model()->index(index.row(), 0).data().toString();
- url = index.data().toString();
- }
-
- mSelectedScreenshot = screenshot;
-
- ui->uploadButton->setEnabled((url.isEmpty() && QFile::exists(screenshot)));
-}
-
-void HistoryDialog::upload()
-{
- Uploader::instance()->upload(mSelectedScreenshot);
- ui->uploadButton->setEnabled(false);
-}
-
-void HistoryDialog::uploadProgress(qint64 sent, qint64 total)
-{
- ui->uploadProgressBar->setEnabled(true);
-
- ui->uploadProgressBar->setMaximum(total);
- ui->uploadProgressBar->setValue(sent);
-}
-
-bool HistoryDialog::eventFilter(QObject *object, QEvent *event)
-{
- if (object == ui->filterEdit) {
- if (event->type() == QEvent::FocusIn)
- {
- if (ui->filterEdit->text() == tr("Filter..")) {
- ui->filterEdit->setStyleSheet("");
- ui->filterEdit->setText("");
- mFilterModel->setFilterWildcard("");
- mFilterModel->sort(3, Qt::DescendingOrder);
- }
- }
- else if (event->type() == QEvent::FocusOut)
- {
- if (ui->filterEdit->text() == "") {
- ui->filterEdit->setStyleSheet("color: palette(mid);");
- ui->filterEdit->setText(tr("Filter.."));
- mFilterModel->sort(3, Qt::DescendingOrder);
- }
- }
- else if (event->type() == QEvent::KeyRelease)
- {
- if (ui->filterEdit->text() != tr("Filter..") && !ui->filterEdit->text().isEmpty()) {
- mFilterModel->setFilterWildcard(ui->filterEdit->text());
- mFilterModel->sort(3, Qt::DescendingOrder);
- }
- else {
- mFilterModel->setFilterWildcard("");
- mFilterModel->sort(3, Qt::DescendingOrder);
- }
- }
- }
- return QDialog::eventFilter(object, event);
-}
+#include "historydialog.h"
+#include "ui_historydialog.h"
+
+#include "../tools/os.h"
+#include "../tools/uploader.h"
+#include "../tools/screenshotmanager.h"
+
+#include <QClipboard>
+#include <QDesktopServices>
+#include <QDir>
+#include <QFile>
+#include <QFileInfo>
+#include <QFileSystemWatcher>
+#include <QMenu>
+#include <QMessageBox>
+#include <QSortFilterProxyModel>
+#include <QUrl>
+#include <QSettings>
+
+#include <QtSql/QSqlDatabase>
+#include <QtSql/QSqlTableModel>
+
+#include <QDebug>
+
+HistoryDialog::HistoryDialog(QWidget *parent) :
+ QDialog(parent),
+ ui(new Ui::HistoryDialog)
+{
+ ui->setupUi(this);
+
+ ui->filterEdit->setText(tr("Filter.."));
+ ui->filterEdit->installEventFilter(this);
+
+ if (ScreenshotManager::instance()->history().isOpen())
+ {
+ mModel = new QSqlTableModel(this, ScreenshotManager::instance()->history());
+ mModel->setTable("history");
+ mModel->setHeaderData(0, Qt::Horizontal, tr("Screenshot"));
+ mModel->setHeaderData(1, Qt::Horizontal, tr("URL"));
+ mModel->select();
+
+ mFilterModel = new QSortFilterProxyModel(mModel);
+ mFilterModel->setSourceModel(mModel);
+ mFilterModel->setDynamicSortFilter(true);
+ mFilterModel->setSortCaseSensitivity(Qt::CaseInsensitive);
+ mFilterModel->setFilterCaseSensitivity(Qt::CaseInsensitive);
+ mFilterModel->setFilterKeyColumn(-1);
+
+ ui->tableView->setModel(mFilterModel);
+
+ ui->tableView->hideColumn(2); // No delete hash.
+ ui->tableView->hideColumn(3); // No timestamp.
+
+ ui->tableView->horizontalHeader()->setClickable(false);
+ ui->tableView->horizontalHeader()->setMovable(false);
+
+ ui->tableView->horizontalHeader()->setResizeMode(0, QHeaderView::Stretch);
+ ui->tableView->horizontalHeader()->setResizeMode(1, QHeaderView::ResizeToContents);
+
+ ui->tableView->verticalHeader()->hide();
+
+ ui->tableView->setTextElideMode(Qt::ElideLeft);
+ ui->tableView->setEditTriggers(QAbstractItemView::NoEditTriggers);
+ ui->tableView->setAlternatingRowColors(true);
+ ui->tableView->setSelectionMode(QAbstractItemView::SingleSelection);
+ ui->tableView->setContextMenuPolicy(Qt::CustomContextMenu);
+ ui->tableView->setSortingEnabled(true);
+
+ if (ui->tableView->model()->rowCount() > 0)
+ {
+ ui->clearButton->setEnabled(true);
+ ui->filterEdit->setEnabled(true);
+ }
+
+ connect(ui->tableView->selectionModel(), SIGNAL(selectionChanged(QItemSelection,QItemSelection)), this, SLOT(selectionChanged(QItemSelection,QItemSelection)));
+ connect(ui->tableView, SIGNAL(doubleClicked(QModelIndex)), this, SLOT(open(QModelIndex)));
+ connect(ui->tableView, SIGNAL(customContextMenuRequested(QPoint)), this, SLOT(contextMenu(QPoint)));
+ }
+ else {
+ ui->tableView->setEnabled(false);
+ ui->clearButton->setEnabled(false);
+ }
+
+ ui->uploadProgressBar->setValue (Uploader::instance()->progressSent());
+
+ if (Uploader::instance()->progressTotal() == 0) {
+ ui->uploadProgressBar->setMaximum(1);
+ }
+ else {
+ ui->uploadProgressBar->setMaximum(Uploader::instance()->progressTotal());
+ }
+
+ connect(Uploader::instance(), SIGNAL(progress(qint64,qint64)), this, SLOT(uploadProgress(qint64, qint64)));
+ connect(ui->uploadButton, SIGNAL(clicked()), this, SLOT(upload()));
+ connect(ui->clearButton , SIGNAL(clicked()), this, SLOT(clear()));
+}
+
+HistoryDialog::~HistoryDialog()
+{
+ delete ui;
+}
+
+void HistoryDialog::clear()
+{
+ if (QMessageBox::question(this,
+ tr("Clearing the screenshot history"),
+ tr("Are you sure you want to clear your entire screenshot history?\nThis cannot be undone."),
+ tr("Clear History"),
+ tr("Don't Clear")) == 1) {
+ return;
+ }
+
+ ScreenshotManager::instance()->clearHistory();
+ close();
+}
+
+void HistoryDialog::contextMenu(QPoint point)
+{
+ mContextIndex = ui->tableView->indexAt(point);;
+
+ QMenu contextMenu(ui->tableView);
+
+ QAction copyAction((mContextIndex.column() == 0) ? tr("Copy Path") : tr("Copy URL"), &contextMenu);
+ connect(&copyAction, SIGNAL(triggered()), this, SLOT(copy()));
+ contextMenu.addAction(&copyAction);
+
+ QAction deleteAction(tr("Delete from imgur.com"), &contextMenu);
+ QAction locationAction(tr("Open Location"), &contextMenu);
+
+ QAction removeAction(tr("Remove history entry"), &contextMenu);
+
+ if (mContextIndex.column() == 0)
+ {
+ connect(&locationAction, SIGNAL(triggered()), this, SLOT(location()));
+ contextMenu.addAction(&locationAction);
+ }
+ else {
+ connect(&deleteAction, SIGNAL(triggered()), this, SLOT(deleteImage()));
+ contextMenu.addAction(&deleteAction);
+ }
+
+ connect(&removeAction, SIGNAL(triggered()), this, SLOT(removeHistoryEntry()));
+
+ if (mContextIndex.data().toString().isEmpty()) {
+ copyAction.setEnabled(false);
+ deleteAction.setEnabled(false);
+ }
+
+ contextMenu.addAction(&removeAction);
+
+ contextMenu.exec(QCursor::pos());
+}
+
+void HistoryDialog::copy()
+{
+ qApp->clipboard()->setText(mContextIndex.data().toString());
+}
+
+void HistoryDialog::deleteImage()
+{
+ QDesktopServices::openUrl(mContextIndex.sibling(mContextIndex.row(), 2).data().toString());
+}
+
+void HistoryDialog::location()
+{
+ QDesktopServices::openUrl("file:///" + QFileInfo(mContextIndex.data().toString()).absolutePath());
+}
+
+void HistoryDialog::removeHistoryEntry()
+{
+ ScreenshotManager::instance()->removeHistory(mContextIndex.data().toString(), mContextIndex.sibling(mContextIndex.row(), 3).data().toLongLong());
+ mModel->select();
+}
+
+void HistoryDialog::open(QModelIndex index)
+{
+ if (index.column() == 0) {
+ QDesktopServices::openUrl(QUrl("file:///" + index.data().toString()));
+ }
+ else {
+ QDesktopServices::openUrl(index.data().toUrl());
+ }
+}
+
+void HistoryDialog::reloadHistory()
+{
+ qobject_cast<QSqlTableModel*>(mFilterModel->sourceModel())->select();
+}
+
+void HistoryDialog::selectionChanged(QItemSelection selected, QItemSelection deselected)
+{
+ Q_UNUSED(deselected);
+
+ if (selected.indexes().count() == 0){
+ return;
+ }
+
+ QModelIndex index = selected.indexes().at(0);
+
+ QString screenshot;
+
+ if (index.column() == 0) {
+ screenshot = index.data().toString();
+ }
+ else {
+ screenshot = ui->tableView->model()->index(index.row(), 0).data().toString();
+ }
+
+ mSelectedScreenshot = screenshot;
+
+ ui->uploadButton->setEnabled(QFile::exists(screenshot));
+}
+
+void HistoryDialog::upload()
+{
+ Uploader::instance()->upload(mSelectedScreenshot);
+ ui->uploadButton->setEnabled(false);
+}
+
+void HistoryDialog::uploadProgress(qint64 sent, qint64 total)
+{
+ ui->uploadProgressBar->setEnabled(true);
+
+ ui->uploadProgressBar->setMaximum(total);
+ ui->uploadProgressBar->setValue(sent);
+
+
+ if (sent == total) {
+ mModel->select();
+ }
+}
+
+bool HistoryDialog::eventFilter(QObject *object, QEvent *event)
+{
+ if (object == ui->filterEdit) {
+ if (event->type() == QEvent::FocusIn)
+ {
+ if (ui->filterEdit->text() == tr("Filter..")) {
+ ui->filterEdit->setStyleSheet("");
+ ui->filterEdit->setText("");
+ mFilterModel->setFilterWildcard("");
+ mFilterModel->sort(3, Qt::DescendingOrder);
+ }
+ }
+ else if (event->type() == QEvent::FocusOut)
+ {
+ if (ui->filterEdit->text() == "") {
+ ui->filterEdit->setStyleSheet("color: palette(mid);");
+ ui->filterEdit->setText(tr("Filter.."));
+ mFilterModel->sort(3, Qt::DescendingOrder);
+ }
+ }
+ else if (event->type() == QEvent::KeyRelease)
+ {
+ if (ui->filterEdit->text() != tr("Filter..") && !ui->filterEdit->text().isEmpty()) {
+ mFilterModel->setFilterWildcard(ui->filterEdit->text());
+ mFilterModel->sort(3, Qt::DescendingOrder);
+ }
+ else {
+ mFilterModel->setFilterWildcard("");
+ mFilterModel->sort(3, Qt::DescendingOrder);
+ }
+ }
+ }
+
+ return QDialog::eventFilter(object, event);
+}
+
+bool HistoryDialog::event(QEvent *event)
+{
+ if (event->type() == QEvent::Show)
+ {
+ restoreGeometry(ScreenshotManager::instance()->settings()->value("geometry/historyDialog").toByteArray());
+ }
+ else if (event->type() == QEvent::Close)
+ {
+ ScreenshotManager::instance()->settings()->setValue("geometry/historyDialog", saveGeometry());
+ }
+
+
+ return QDialog::event(event);
+}
diff --git a/dialogs/historydialog.h b/dialogs/historydialog.h
index 998eaf4..f75df0a 100644
--- a/dialogs/historydialog.h
+++ b/dialogs/historydialog.h
@@ -1,42 +1,46 @@
-#ifndef UPLOADDIALOG_H
-#define UPLOADDIALOG_H
-
-#include <QDialog>
-#include <QItemSelection>
-
-namespace Ui {
- class HistoryDialog;
-}
-
-class QSortFilterProxyModel;
-class HistoryDialog : public QDialog
-{
- Q_OBJECT
-
-public:
- explicit HistoryDialog(QWidget *parent = 0);
- ~HistoryDialog();
-
-private slots:
- void clear();
- void contextMenu(QPoint point);
- void copy();
- void deleteImage();
- void location();
- void open(QModelIndex index);
- void reloadHistory();
- void selectionChanged(QItemSelection selected, QItemSelection deselected);
- void upload();
- void uploadProgress(qint64 sent, qint64 total);
-
-protected:
- bool eventFilter(QObject *object, QEvent *event);
-
-private:
- Ui::HistoryDialog *ui;
- QSortFilterProxyModel *mFilterModel;
- QString mSelectedScreenshot;
- QModelIndex mContextIndex;
-};
-
-#endif // UPLOADDIALOG_H
+#ifndef UPLOADDIALOG_H
+#define UPLOADDIALOG_H
+
+#include <QDialog>
+#include <QItemSelection>
+
+namespace Ui {
+ class HistoryDialog;
+}
+
+class QSqlTableModel;
+class QSortFilterProxyModel;
+class HistoryDialog : public QDialog
+{
+ Q_OBJECT
+
+public:
+ explicit HistoryDialog(QWidget *parent = 0);
+ ~HistoryDialog();
+
+private slots:
+ void clear();
+ void contextMenu(QPoint point);
+ void copy();
+ void deleteImage();
+ void location();
+ void removeHistoryEntry();
+ void open(QModelIndex index);
+ void reloadHistory();
+ void selectionChanged(QItemSelection selected, QItemSelection deselected);
+ void upload();
+ void uploadProgress(qint64 sent, qint64 total);
+
+protected:
+ bool eventFilter(QObject *object, QEvent *event);
+ bool event(QEvent *event);
+
+private:
+ Ui::HistoryDialog *ui;
+ QSqlTableModel *mModel;
+ QSortFilterProxyModel *mFilterModel;
+ QString mSelectedScreenshot;
+ QModelIndex mContextIndex;
+};
+
+#endif // UPLOADDIALOG_H
diff --git a/dialogs/optionsdialog.cpp b/dialogs/optionsdialog.cpp
index 8e6b506..c612045 100644
--- a/dialogs/optionsdialog.cpp
+++ b/dialogs/optionsdialog.cpp
@@ -1,720 +1,727 @@
-/*
- * 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 <QProcess>
-#include <QSettings>
-#include <QTimer>
-#include <QUrl>
-
-#include <QDebug>
-
-#ifdef Q_WS_WIN
- #include <windows.h>
-#endif
-
-#include "optionsdialog.h"
-#include "namingdialog.h"
-#include "historydialog.h"
-#include "../tools/os.h"
-#include "../tools/screenshot.h"
-#include "../tools/screenshotmanager.h"
-#include "../updater/updater.h"
-
-OptionsDialog::OptionsDialog(QWidget *parent) :
- QDialog(parent)
-{
- ui.setupUi(this);
- setModal(true);
-
-#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::accepted()
-{
- if (hotkeyCollision()) {
- QMessageBox::critical(this, tr("Hotkey conflict"), tr("You have assigned the same hotkeys to more than one action."));
- return;
- }
-
- if (ui.prefixLineEdit->text().contains(QRegExp("[?:\\\\/*\"<>|]"))) {
- QMessageBox::critical(this, tr("Filename character error"), tr("The filename can't contain any of the following characters: ? : \\ / * \" < > |"));
- return;
- }
-
- if (!ui.fileGroupBox->isChecked() && !ui.clipboardCheckBox->isChecked()) {
- QMessageBox::critical(this, tr("Final Destination"), tr("You can't take screenshots unless you enable either file saving or the clipboard."));
- return;
- }
-
- saveSettings();
- accept();
-}
-
-void OptionsDialog::checkUpdatesNow()
-{
- Updater::instance()->checkWithFeedback();
-}
-
-void OptionsDialog::languageChange(QString language)
-{
- os::translate(language);
-}
-
-void OptionsDialog::loadSettings()
-{
- settings()->sync();
- os::translate(settings()->value("options/language").toString()); // Why? Don't ask me, I'm just the programmer.
-
- setUpdatesEnabled(false);
-
- if (!settings()->contains("file/format")) {
- // If there are no settings, get rid of the cancel button so that the user is forced to save them
- ui.buttonBox->clear();
- ui.buttonBox->addButton(QDialogButtonBox::Ok);
- }
-
- ui.startupCheckBox->toggle();
- ui.trayCheckBox->toggle();
- ui.previewAutocloseCheckBox->toggle();
-
- QString targetDefault;
-
- if (ScreenshotManager::instance()->portableMode()) {
- targetDefault = tr("Screenshots");
- }
- else {
- targetDefault = os::getDocumentsPath() + QDir::separator() + tr("Screenshots");
- }
-
- settings()->beginGroup("file");
- ui.formatComboBox->setCurrentIndex(settings()->value("format", 1).toInt());
- ui.prefixLineEdit->setText(settings()->value("prefix", tr("screenshot.")).toString());
- ui.namingComboBox->setCurrentIndex(settings()->value("naming", 0).toInt());
- ui.targetLineEdit->setText(settings()->value("target", targetDefault).toString());
- ui.fileGroupBox->setChecked(settings()->value("enabled", true).toBool());
- settings()->endGroup();
-
- settings()->beginGroup("options");
- ui.startupCheckBox->setChecked(settings()->value("startup", false).toBool());
- ui.startupHideCheckBox->setChecked(settings()->value("startupHide", true).toBool());
- ui.hideCheckBox->setChecked(settings()->value("hide", true).toBool());
- ui.delaySpinBox->setValue(settings()->value("delay", 0).toInt());
- flipToggled(settings()->value("flip", false).toBool());
- ui.trayCheckBox->setChecked(settings()->value("tray", true).toBool());
- ui.messageCheckBox->setChecked(settings()->value("message", true).toBool());
- ui.qualitySlider->setValue(settings()->value("quality", 100).toInt());
- ui.playSoundCheckBox->setChecked(settings()->value("playSound", false).toBool());
- ui.updaterCheckBox->setChecked(!settings()->value("disableUpdater", false).toBool());
- ui.magnifyCheckBox->setChecked(settings()->value("magnify", false).toBool());
- ui.cursorCheckBox->setChecked(settings()->value("cursor", false).toBool());
- ui.saveAsCheckBox->setChecked(settings()->value("saveAs", false).toBool());
- ui.previewGroupBox->setChecked(settings()->value("preview", false).toBool());
- ui.previewSizeSpinBox->setValue(settings()->value("previewSize", 300).toInt());
- ui.previewPositionComboBox->setCurrentIndex(settings()->value("previewPosition", 3).toInt());
- ui.previewAutocloseCheckBox->setChecked(settings()->value("previewAutoclose", false).toBool());
- ui.previewAutocloseTimeSpinBox->setValue(settings()->value("previewAutocloseTime", 15).toInt());
- ui.previewAutocloseActionComboBox->setCurrentIndex(settings()->value("previewAutocloseAction", 0).toInt());
- ui.previewDefaultActionComboBox->setCurrentIndex(settings()->value("previewDefaultAction", 0).toInt());
- ui.areaAutocloseCheckBox->setChecked(settings()->value("areaAutoclose", false).toBool());
- ui.historyCheckBox->setChecked(settings()->value("history", true).toBool());
-
- // Advanced
- ui.clipboardCheckBox->setChecked(settings()->value("clipboard", true).toBool());
- ui.imgurClipboardCheckBox->setChecked(settings()->value("imgurClipboard", false).toBool());
- ui.optiPngCheckBox->setChecked(settings()->value("optipng", true).toBool());
- ui.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());
-
-#ifdef Q_WS_WIN
- if (!QFile::exists(qApp->applicationDirPath() + QDir::separator() + "optipng.exe")) {
- ui.optiPngCheckBox->setEnabled(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", "Print").toString());
- settings()->endGroup();
-
- settings()->beginGroup("area");
- ui.areaCheckBox->setChecked(settings()->value("enabled").toBool());
- ui.areaHotkeyWidget->setHotkey(settings()->value("hotkey", "Ctrl+Print").toString());
- settings()->endGroup();
-
- settings()->beginGroup("window");
- ui.windowCheckBox->setChecked(settings()->value("enabled").toBool());
- ui.windowHotkeyWidget->setHotkey(settings()->value("hotkey", "Alt+Print").toString());
- settings()->endGroup();
-
- settings()->beginGroup("windowPicker");
- ui.windowPickerCheckBox->setChecked(settings()->value("enabled").toBool());
- ui.windowPickerHotkeyWidget->setHotkey(settings()->value("hotkey", "Ctrl+Alt+Print").toString());
- settings()->endGroup();
-
- settings()->beginGroup("open");
- ui.openCheckBox->setChecked(settings()->value("enabled").toBool());
- ui.openHotkeyWidget->setHotkey(settings()->value("hotkey", "Ctrl+PgUp").toString());
- settings()->endGroup();
-
- settings()->beginGroup("directory");
- ui.directoryCheckBox->setChecked(settings()->value("enabled").toBool());
- ui.directoryHotkeyWidget->setHotkey(settings()->value("hotkey", "Ctrl+PgDown").toString());
- settings()->endGroup();
-
- settings()->endGroup();
-
- QTimer::singleShot(0, this, SLOT(updatePreview()));
-
- setEnabled(true);
- setUpdatesEnabled(true);
-}
-
-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("previewDefaultAction", ui.previewDefaultActionComboBox->currentIndex());
- settings()->setValue("areaAutoclose", ui.areaAutocloseCheckBox->isChecked());
- settings()->setValue("history", ui.historyCheckBox->isChecked());
-
- // Advanced
- settings()->setValue("disableHideAlert", !ui.warnHideCheckBox->isChecked());
- settings()->setValue("clipboard", ui.clipboardCheckBox->isChecked());
- settings()->setValue("imgurClipboard", ui.imgurClipboardCheckBox->isChecked());
- settings()->setValue("optipng", ui.optiPngCheckBox->isChecked());
- settings()->setValue("currentMonitor", ui.currentMonitorCheckBox->isChecked());
- settings()->setValue("replace", ui.replaceCheckBox->isChecked());
-
- //Upload
- settings()->setValue("uploadAuto", ui.uploadCheckBox->isChecked());
- settings()->endGroup();
-
- settings()->beginGroup("actions");
-
- settings()->beginGroup("screen");
- settings()->setValue("enabled", ui.screenCheckBox->isChecked());
- settings()->setValue("hotkey", ui.screenHotkeyWidget->hotkey());
- settings()->endGroup();
-
- settings()->beginGroup("area");
- settings()->setValue("enabled", ui.areaCheckBox->isChecked());
- settings()->setValue("hotkey", ui.areaHotkeyWidget->hotkey());
- settings()->endGroup();
-
- settings()->beginGroup("window");
- settings()->setValue("enabled", ui.windowCheckBox->isChecked());
- settings()->setValue("hotkey", ui.windowHotkeyWidget->hotkey());
- settings()->endGroup();
-
- settings()->beginGroup("windowPicker");
- settings()->setValue("enabled", ui.windowPickerCheckBox->isChecked());
- settings()->setValue("hotkey", ui.windowPickerHotkeyWidget->hotkey());
- settings()->endGroup();
-
- settings()->beginGroup("open");
- settings()->setValue("enabled", ui.openCheckBox->isChecked());
- settings()->setValue("hotkey", ui.openHotkeyWidget->hotkey());
- settings()->endGroup();
-
- settings()->beginGroup("directory");
- settings()->setValue("enabled", ui.directoryCheckBox->isChecked());
- settings()->setValue("hotkey", ui.directoryHotkeyWidget->hotkey());
- settings()->endGroup();
-
- settings()->endGroup();
-}
-
-void OptionsDialog::updatePreview()
-{
- Screenshot::NamingOptions options;
-
- options.naming = (Screenshot::Naming)ui.namingComboBox->currentIndex();
- options.flip = settings()->value("options/flip", false).toBool();
- options.leadingZeros = settings()->value("options/naming/leadingZeros", 0).toInt();
- options.dateFormat = settings()->value("options/naming/dateFormat", "yyyy-MM-dd").toString();
-
- ui.namingOptionsButton->setDisabled((options.naming == Screenshot::Empty));
-
- QString preview = Screenshot::getName(options,
- ui.prefixLineEdit->text(),
- QDir(ui.targetLineEdit->text()));
-
- preview = QString("%1.%2").arg(preview).arg(ui.formatComboBox->currentText().toLower());
-
- if (preview.length() >= 40) {
- preview.truncate(37);
- preview.append("...");
- }
-
- ui.previewLabel->setText(preview);
-}
-
-void OptionsDialog::viewHistory()
-{
- HistoryDialog historyDialog(this);
- historyDialog.exec();
-}
-
-//
-
-bool OptionsDialog::event(QEvent* event)
-{
- if (event->type() == QEvent::LanguageChange) {
-
- // ComboBoxes revert to the first index when translated:
- int naming = ui.namingComboBox->currentIndex();
- int format = ui.formatComboBox->currentIndex();
- int previewPosition = ui.previewPositionComboBox->currentIndex();
- int previewAutoclose = ui.previewAutocloseActionComboBox->currentIndex();
- int previewDefault = ui.previewDefaultActionComboBox->currentIndex();
-
- ui.retranslateUi(this);
-
- // Restoring comboboxes
- ui.namingComboBox->setCurrentIndex(naming);
- ui.formatComboBox->setCurrentIndex(format);
- ui.previewPositionComboBox->setCurrentIndex(previewPosition);
- ui.previewAutocloseActionComboBox->setCurrentIndex(previewAutoclose);
- ui.previewDefaultActionComboBox->setCurrentIndex(previewDefault);
-
- 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);
-}
-
-#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
-
-//
-
-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::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;
-
- QString language = settings()->value("options/language").toString(); // Only mantain language.
-
- settings()->clear();
- settings()->setValue("options/language", language);
-
- loadSettings();
- }
-}
-
-void OptionsDialog::flipToggled(bool checked)
-{
- setUpdatesEnabled(false);
-
- ui.filenameLayout->removeWidget(ui.prefixLineEdit);
- ui.filenameLayout->removeWidget(ui.namingComboBox);
-
- if (checked) {
- ui.filenameLayout->addWidget(ui.namingComboBox);
- ui.filenameLayout->addWidget(ui.prefixLineEdit);
- }
- else {
- ui.filenameLayout->addWidget(ui.prefixLineEdit);
- ui.filenameLayout->addWidget(ui.namingComboBox);
- }
-
- if (ui.prefixLineEdit->text() == tr("screenshot.")
- && checked)
- ui.prefixLineEdit->setText(tr(".screenshot"));
-
- if (ui.prefixLineEdit->text() == tr(".screenshot")
- && !checked)
- ui.prefixLineEdit->setText(tr("screenshot."));
-
- setUpdatesEnabled(true); // Avoids flicker
-}
-
-void OptionsDialog::init()
-{
- // Make the scroll area share the Tab Widget background color
- QPalette optionsPalette = ui.optionsScrollArea->palette();
- optionsPalette.setColor(QPalette::Window, ui.tabWidget->palette().color(QPalette::Base));
- ui.optionsScrollArea->setPalette(optionsPalette);
-
-
- ui.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.
-
- //
- // 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.historyPushButton , SIGNAL(clicked()) , this , SLOT(viewHistory()));
-
- connect(ui.screenCheckBox , SIGNAL(toggled(bool)), ui.screenHotkeyWidget , SLOT(setEnabled(bool)));
- connect(ui.areaCheckBox , SIGNAL(toggled(bool)), ui.areaHotkeyWidget , SLOT(setEnabled(bool)));
- connect(ui.windowCheckBox , SIGNAL(toggled(bool)), ui.windowHotkeyWidget , SLOT(setEnabled(bool)));
- connect(ui.windowPickerCheckBox, SIGNAL(toggled(bool)), ui.windowPickerHotkeyWidget, SLOT(setEnabled(bool)));
- connect(ui.openCheckBox , SIGNAL(toggled(bool)), ui.openHotkeyWidget , SLOT(setEnabled(bool)));
- connect(ui.directoryCheckBox , SIGNAL(toggled(bool)), ui.directoryHotkeyWidget, SLOT(setEnabled(bool)));
-
- // "Save as" disables the file target input field.
- connect(ui.saveAsCheckBox , SIGNAL(toggled(bool)), ui.targetLineEdit , SLOT(setDisabled(bool)));
- connect(ui.saveAsCheckBox , SIGNAL(toggled(bool)), ui.browsePushButton , SLOT(setDisabled(bool)));
- connect(ui.saveAsCheckBox , SIGNAL(toggled(bool)), ui.directoryLabel , SLOT(setDisabled(bool)));
-
- connect(ui.startupCheckBox , SIGNAL(toggled(bool)), ui.startupHideCheckBox , SLOT(setEnabled(bool)));
- connect(ui.qualitySlider , SIGNAL(valueChanged(int)), ui.qualityValueLabel, SLOT(setNum(int)));
- connect(ui.trayCheckBox , SIGNAL(toggled(bool)), ui.messageCheckBox , SLOT(setEnabled(bool)));
-
- // Auto-upload disables the default action button in the previews.
- connect(ui.uploadCheckBox , SIGNAL(toggled(bool)), ui.previewDefaultActionLabel , SLOT(setDisabled(bool)));
- connect(ui.uploadCheckBox , SIGNAL(toggled(bool)), ui.previewDefaultActionComboBox, SLOT(setDisabled(bool)));
- connect(ui.directoryCheckBox , SIGNAL(toggled(bool)), ui.directoryHotkeyWidget, SLOT(setEnabled(bool)));
-
- connect(ui.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.licenseAboutLabel, 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();
-}
-
-//
-
-bool OptionsDialog::hotkeyCollision()
-{
- // Check for hotkey collision (there's probably a better way to do this...=)
-
- if (ui.screenCheckBox->isChecked()) {
- if (ui.screenHotkeyWidget->hotkey() == ui.areaHotkeyWidget->hotkey()
- && ui.areaCheckBox->isChecked())
- return true;
-
- if (ui.screenHotkeyWidget->hotkey() == ui.windowHotkeyWidget->hotkey()
- && ui.windowCheckBox->isChecked())
- return true;
-
- if (ui.screenHotkeyWidget->hotkey() == ui.windowPickerHotkeyWidget->hotkey()
- && ui.windowPickerCheckBox->isChecked())
- return true;
-
- if (ui.screenHotkeyWidget->hotkey() == ui.openHotkeyWidget->hotkey()
- && ui.openCheckBox->isChecked())
- return true;
-
- if (ui.screenHotkeyWidget->hotkey() == ui.directoryHotkeyWidget->hotkey()
- && ui.directoryCheckBox->isChecked())
- return true;
- }
-
- if (ui.areaCheckBox->isChecked()) {
- if (ui.areaHotkeyWidget->hotkey() == ui.screenHotkeyWidget->hotkey()
- && ui.screenCheckBox->isChecked())
- return true;
-
- if (ui.areaHotkeyWidget->hotkey() == ui.windowHotkeyWidget->hotkey()
- && ui.windowCheckBox->isChecked())
- return true;
-
- if (ui.areaHotkeyWidget->hotkey() == ui.windowPickerHotkeyWidget->hotkey()
- && ui.windowPickerCheckBox->isChecked())
- return true;
-
- if (ui.areaHotkeyWidget->hotkey() == ui.openHotkeyWidget->hotkey()
- && ui.openCheckBox->isChecked())
- return true;
-
- if (ui.areaHotkeyWidget->hotkey() == ui.directoryHotkeyWidget->hotkey()
- && ui.directoryCheckBox->isChecked())
- return true;
- }
-
- if (ui.windowCheckBox->isChecked()) {
- if (ui.windowHotkeyWidget->hotkey() == ui.screenHotkeyWidget->hotkey()
- && ui.screenCheckBox->isChecked())
- return true;
-
- if (ui.windowHotkeyWidget->hotkey() == ui.areaHotkeyWidget->hotkey()
- && ui.areaCheckBox->isChecked())
- return true;
-
- if (ui.windowHotkeyWidget->hotkey() == ui.windowPickerHotkeyWidget->hotkey()
- && ui.windowPickerCheckBox->isChecked())
- return true;
-
- if (ui.windowHotkeyWidget->hotkey() == ui.openHotkeyWidget->hotkey()
- && ui.openCheckBox->isChecked())
- return true;
-
- if (ui.windowHotkeyWidget->hotkey() == ui.directoryHotkeyWidget->hotkey()
- && ui.directoryCheckBox->isChecked())
- return true;
- }
-
- if (ui.openCheckBox->isChecked()) {
- if (ui.openHotkeyWidget->hotkey() == ui.screenHotkeyWidget->hotkey()
- && ui.screenCheckBox->isChecked())
- return true;
-
- if (ui.openHotkeyWidget->hotkey() == ui.areaHotkeyWidget->hotkey()
- && ui.areaCheckBox->isChecked())
- return true;
-
- if (ui.openHotkeyWidget->hotkey() == ui.windowPickerHotkeyWidget->hotkey()
- && ui.windowPickerCheckBox->isChecked())
- return true;
-
- if (ui.openHotkeyWidget->hotkey() == ui.windowHotkeyWidget->hotkey()
- && ui.windowCheckBox->isChecked())
- return true;
-
- if (ui.openHotkeyWidget->hotkey() == ui.directoryHotkeyWidget->hotkey()
- && ui.directoryCheckBox->isChecked())
- return true;
- }
-
- if (ui.directoryCheckBox->isChecked()) {
- if (ui.directoryHotkeyWidget->hotkey() == ui.screenHotkeyWidget->hotkey()
- && ui.screenCheckBox->isChecked())
- return true;
-
- if (ui.directoryHotkeyWidget->hotkey() == ui.areaHotkeyWidget->hotkey()
- && ui.areaCheckBox->isChecked())
- return true;
-
- if (ui.directoryHotkeyWidget->hotkey() == ui.windowPickerHotkeyWidget->hotkey()
- && ui.windowPickerCheckBox->isChecked())
- return true;
-
- if (ui.directoryHotkeyWidget->hotkey() == ui.windowHotkeyWidget->hotkey()
- && ui.windowCheckBox->isChecked())
- return true;
-
- if (ui.directoryHotkeyWidget->hotkey() == ui.openHotkeyWidget->hotkey()
- && ui.openCheckBox->isChecked())
- return true;
- }
-
- return false;
-}
-
-QSettings *OptionsDialog::settings() const
-{
- return ScreenshotManager::instance()->settings();
-}
+/*
+ * 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 <QProcess>
+#include <QSettings>
+#include <QTimer>
+#include <QUrl>
+
+#include <QDebug>
+
+#ifdef Q_WS_WIN
+ #include <windows.h>
+#endif
+
+#include "optionsdialog.h"
+#include "namingdialog.h"
+#include "historydialog.h"
+#include "../tools/os.h"
+#include "../tools/screenshot.h"
+#include "../tools/screenshotmanager.h"
+#include "../updater/updater.h"
+
+OptionsDialog::OptionsDialog(QWidget *parent) :
+ QDialog(parent)
+{
+ ui.setupUi(this);
+ setModal(true);
+
+#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::accepted()
+{
+ if (hotkeyCollision()) {
+ QMessageBox::critical(this, tr("Hotkey conflict"), tr("You have assigned the same hotkeys to more than one action."));
+ return;
+ }
+
+ if (ui.prefixLineEdit->text().contains(QRegExp("[?:\\\\/*\"<>|]"))) {
+ QMessageBox::critical(this, tr("Filename character error"), tr("The filename can't contain any of the following characters: ? : \\ / * \" < > |"));
+ return;
+ }
+
+ if (!ui.fileGroupBox->isChecked() && !ui.clipboardCheckBox->isChecked()) {
+ QMessageBox::critical(this, tr("Final Destination"), tr("You can't take screenshots unless you enable either file saving or the clipboard."));
+ return;
+ }
+
+ saveSettings();
+ accept();
+}
+
+void OptionsDialog::checkUpdatesNow()
+{
+ Updater::instance()->checkWithFeedback();
+}
+
+void OptionsDialog::languageChange(QString language)
+{
+ os::translate(language);
+}
+
+void OptionsDialog::loadSettings()
+{
+ settings()->sync();
+ os::translate(settings()->value("options/language").toString()); // Why? Don't ask me, I'm just the programmer.
+
+ setUpdatesEnabled(false);
+
+ if (!settings()->contains("file/format")) {
+ // If there are no settings, get rid of the cancel button so that the user is forced to save them
+ ui.buttonBox->clear();
+ ui.buttonBox->addButton(QDialogButtonBox::Ok);
+ }
+
+ ui.startupCheckBox->toggle();
+ ui.trayCheckBox->toggle();
+ ui.previewAutocloseCheckBox->toggle();
+
+ QString targetDefault;
+
+ if (ScreenshotManager::instance()->portableMode()) {
+ targetDefault = tr("Screenshots");
+ }
+ else {
+ targetDefault = os::getDocumentsPath() + QDir::separator() + tr("Screenshots");
+ }
+
+ settings()->beginGroup("file");
+ ui.formatComboBox->setCurrentIndex(settings()->value("format", 1).toInt());
+ ui.prefixLineEdit->setText(settings()->value("prefix", tr("screenshot.")).toString());
+ ui.namingComboBox->setCurrentIndex(settings()->value("naming", 0).toInt());
+ ui.targetLineEdit->setText(settings()->value("target", targetDefault).toString());
+ ui.fileGroupBox->setChecked(settings()->value("enabled", true).toBool());
+ settings()->endGroup();
+
+ settings()->beginGroup("options");
+ ui.startupCheckBox->setChecked(settings()->value("startup", false).toBool());
+ ui.startupHideCheckBox->setChecked(settings()->value("startupHide", true).toBool());
+ ui.hideCheckBox->setChecked(settings()->value("hide", true).toBool());
+ ui.delaySpinBox->setValue(settings()->value("delay", 0).toInt());
+ flipToggled(settings()->value("flip", false).toBool());
+ ui.trayCheckBox->setChecked(settings()->value("tray", true).toBool());
+ ui.messageCheckBox->setChecked(settings()->value("message", true).toBool());
+ ui.qualitySlider->setValue(settings()->value("quality", 100).toInt());
+ ui.playSoundCheckBox->setChecked(settings()->value("playSound", false).toBool());
+ ui.updaterCheckBox->setChecked(!settings()->value("disableUpdater", false).toBool());
+ ui.magnifyCheckBox->setChecked(settings()->value("magnify", false).toBool());
+ ui.cursorCheckBox->setChecked(settings()->value("cursor", false).toBool());
+ ui.saveAsCheckBox->setChecked(settings()->value("saveAs", false).toBool());
+ ui.previewGroupBox->setChecked(settings()->value("preview", false).toBool());
+ ui.previewSizeSpinBox->setValue(settings()->value("previewSize", 300).toInt());
+ ui.previewPositionComboBox->setCurrentIndex(settings()->value("previewPosition", 3).toInt());
+ ui.previewAutocloseCheckBox->setChecked(settings()->value("previewAutoclose", false).toBool());
+ ui.previewAutocloseTimeSpinBox->setValue(settings()->value("previewAutocloseTime", 15).toInt());
+ ui.previewAutocloseActionComboBox->setCurrentIndex(settings()->value("previewAutocloseAction", 0).toInt());
+ ui.previewDefaultActionComboBox->setCurrentIndex(settings()->value("previewDefaultAction", 0).toInt());
+ ui.areaAutocloseCheckBox->setChecked(settings()->value("areaAutoclose", false).toBool());
+
+ // History mode is neat for normal operation but I'll keep it disabled by default on portable mode.
+ ui.historyCheckBox->setChecked(settings()->value("history", (ScreenshotManager::instance()->portableMode()) ? false : true).toBool());
+
+ // Advanced
+ ui.clipboardCheckBox->setChecked(settings()->value("clipboard", true).toBool());
+ ui.imgurClipboardCheckBox->setChecked(settings()->value("imgurClipboard", false).toBool());
+ ui.optiPngCheckBox->setChecked(settings()->value("optipng", true).toBool());
+ ui.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());
+
+#ifdef Q_WS_WIN
+ if (!QFile::exists(qApp->applicationDirPath() + QDir::separator() + "optipng.exe")) {
+ ui.optiPngCheckBox->setEnabled(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", "Print").toString());
+ settings()->endGroup();
+
+ settings()->beginGroup("area");
+ ui.areaCheckBox->setChecked(settings()->value("enabled").toBool());
+ ui.areaHotkeyWidget->setHotkey(settings()->value("hotkey", "Ctrl+Print").toString());
+ settings()->endGroup();
+
+ settings()->beginGroup("window");
+ ui.windowCheckBox->setChecked(settings()->value("enabled").toBool());
+ ui.windowHotkeyWidget->setHotkey(settings()->value("hotkey", "Alt+Print").toString());
+ settings()->endGroup();
+
+ settings()->beginGroup("windowPicker");
+ ui.windowPickerCheckBox->setChecked(settings()->value("enabled").toBool());
+ ui.windowPickerHotkeyWidget->setHotkey(settings()->value("hotkey", "Ctrl+Alt+Print").toString());
+ settings()->endGroup();
+
+ settings()->beginGroup("open");
+ ui.openCheckBox->setChecked(settings()->value("enabled").toBool());
+ ui.openHotkeyWidget->setHotkey(settings()->value("hotkey", "Ctrl+PgUp").toString());
+ settings()->endGroup();
+
+ settings()->beginGroup("directory");
+ ui.directoryCheckBox->setChecked(settings()->value("enabled").toBool());
+ ui.directoryHotkeyWidget->setHotkey(settings()->value("hotkey", "Ctrl+PgDown").toString());
+ settings()->endGroup();
+
+ settings()->endGroup();
+
+ QTimer::singleShot(0, this, SLOT(updatePreview()));
+
+ setEnabled(true);
+ setUpdatesEnabled(true);
+}
+
+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("previewDefaultAction", ui.previewDefaultActionComboBox->currentIndex());
+ settings()->setValue("areaAutoclose", ui.areaAutocloseCheckBox->isChecked());
+ settings()->setValue("history", ui.historyCheckBox->isChecked());
+
+ // Advanced
+ settings()->setValue("disableHideAlert", !ui.warnHideCheckBox->isChecked());
+ settings()->setValue("clipboard", ui.clipboardCheckBox->isChecked());
+ settings()->setValue("imgurClipboard", ui.imgurClipboardCheckBox->isChecked());
+ settings()->setValue("optipng", ui.optiPngCheckBox->isChecked());
+ settings()->setValue("currentMonitor", ui.currentMonitorCheckBox->isChecked());
+ settings()->setValue("replace", ui.replaceCheckBox->isChecked());
+
+ //Upload
+ settings()->setValue("uploadAuto", ui.uploadCheckBox->isChecked());
+ settings()->endGroup();
+
+ settings()->beginGroup("actions");
+
+ settings()->beginGroup("screen");
+ settings()->setValue("enabled", ui.screenCheckBox->isChecked());
+ settings()->setValue("hotkey", ui.screenHotkeyWidget->hotkey());
+ settings()->endGroup();
+
+ settings()->beginGroup("area");
+ settings()->setValue("enabled", ui.areaCheckBox->isChecked());
+ settings()->setValue("hotkey", ui.areaHotkeyWidget->hotkey());
+ settings()->endGroup();
+
+ settings()->beginGroup("window");
+ settings()->setValue("enabled", ui.windowCheckBox->isChecked());
+ settings()->setValue("hotkey", ui.windowHotkeyWidget->hotkey());
+ settings()->endGroup();
+
+ settings()->beginGroup("windowPicker");
+ settings()->setValue("enabled", ui.windowPickerCheckBox->isChecked());
+ settings()->setValue("hotkey", ui.windowPickerHotkeyWidget->hotkey());
+ settings()->endGroup();
+
+ settings()->beginGroup("open");
+ settings()->setValue("enabled", ui.openCheckBox->isChecked());
+ settings()->setValue("hotkey", ui.openHotkeyWidget->hotkey());
+ settings()->endGroup();
+
+ settings()->beginGroup("directory");
+ settings()->setValue("enabled", ui.directoryCheckBox->isChecked());
+ settings()->setValue("hotkey", ui.directoryHotkeyWidget->hotkey());
+ settings()->endGroup();
+
+ settings()->endGroup();
+}
+
+void OptionsDialog::updatePreview()
+{
+ Screenshot::NamingOptions options;
+
+ options.naming = (Screenshot::Naming)ui.namingComboBox->currentIndex();
+ options.flip = settings()->value("options/flip", false).toBool();
+ options.leadingZeros = settings()->value("options/naming/leadingZeros", 0).toInt();
+ options.dateFormat = settings()->value("options/naming/dateFormat", "yyyy-MM-dd").toString();
+
+ ui.namingOptionsButton->setDisabled((options.naming == Screenshot::Empty));
+
+ QString preview = Screenshot::getName(options,
+ ui.prefixLineEdit->text(),
+ QDir(ui.targetLineEdit->text()));
+
+ preview = QString("%1.%2").arg(preview).arg(ui.formatComboBox->currentText().toLower());
+
+ if (preview.length() >= 40) {
+ preview.truncate(37);
+ preview.append("...");
+ }
+
+ ui.previewLabel->setText(preview);
+}
+
+void OptionsDialog::viewHistory()
+{
+ HistoryDialog historyDialog(this);
+ historyDialog.exec();
+}
+
+//
+
+bool OptionsDialog::event(QEvent* event)
+{
+ if (event->type() == QEvent::LanguageChange) {
+
+ // ComboBoxes revert to the first index when translated:
+ int naming = ui.namingComboBox->currentIndex();
+ int format = ui.formatComboBox->currentIndex();
+ int previewPosition = ui.previewPositionComboBox->currentIndex();
+ int previewAutoclose = ui.previewAutocloseActionComboBox->currentIndex();
+ int previewDefault = ui.previewDefaultActionComboBox->currentIndex();
+
+ ui.retranslateUi(this);
+
+ // Restoring comboboxes
+ ui.namingComboBox->setCurrentIndex(naming);
+ ui.formatComboBox->setCurrentIndex(format);
+ ui.previewPositionComboBox->setCurrentIndex(previewPosition);
+ ui.previewAutocloseActionComboBox->setCurrentIndex(previewAutoclose);
+ ui.previewDefaultActionComboBox->setCurrentIndex(previewDefault);
+
+ updatePreview();
+ resize(minimumSizeHint());
+ }
+ else if (event->type() == QEvent::Close || event->type() == QEvent::Hide) {
+ settings()->setValue("geometry/optionsDialog", saveGeometry());
+
+ if (!settings()->contains("file/format")) {
+ // I'm afraid I can't let you do that, Dave.
+ event->ignore();
+ return false;
+ }
+ }
+ else if (event->type() == QEvent::Show)
+ {
+ restoreGeometry(settings()->value("geometry/optionsDialog").toByteArray());
+ }
+
+ return QDialog::event(event);
+}
+
+#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
+
+//
+
+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::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;
+
+ QString language = settings()->value("options/language").toString(); // Only mantain language.
+
+ settings()->clear();
+ settings()->setValue("options/language", language);
+
+ loadSettings();
+ }
+}
+
+void OptionsDialog::flipToggled(bool checked)
+{
+ setUpdatesEnabled(false);
+
+ ui.filenameLayout->removeWidget(ui.prefixLineEdit);
+ ui.filenameLayout->removeWidget(ui.namingComboBox);
+
+ if (checked) {
+ ui.filenameLayout->addWidget(ui.namingComboBox);
+ ui.filenameLayout->addWidget(ui.prefixLineEdit);
+ }
+ else {
+ ui.filenameLayout->addWidget(ui.prefixLineEdit);
+ ui.filenameLayout->addWidget(ui.namingComboBox);
+ }
+
+ if (ui.prefixLineEdit->text() == tr("screenshot.")
+ && checked)
+ ui.prefixLineEdit->setText(tr(".screenshot"));
+
+ if (ui.prefixLineEdit->text() == tr(".screenshot")
+ && !checked)
+ ui.prefixLineEdit->setText(tr("screenshot."));
+
+ setUpdatesEnabled(true); // Avoids flicker
+}
+
+void OptionsDialog::init()
+{
+ // Make the scroll area share the Tab Widget background color
+ QPalette optionsPalette = ui.optionsScrollArea->palette();
+ optionsPalette.setColor(QPalette::Window, ui.tabWidget->palette().color(QPalette::Base));
+ ui.optionsScrollArea->setPalette(optionsPalette);
+
+ ui.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.
+
+ //
+ // 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.historyPushButton , SIGNAL(clicked()) , this , SLOT(viewHistory()));
+
+ connect(ui.screenCheckBox , SIGNAL(toggled(bool)), ui.screenHotkeyWidget , SLOT(setEnabled(bool)));
+ connect(ui.areaCheckBox , SIGNAL(toggled(bool)), ui.areaHotkeyWidget , SLOT(setEnabled(bool)));
+ connect(ui.windowCheckBox , SIGNAL(toggled(bool)), ui.windowHotkeyWidget , SLOT(setEnabled(bool)));
+ connect(ui.windowPickerCheckBox, SIGNAL(toggled(bool)), ui.windowPickerHotkeyWidget, SLOT(setEnabled(bool)));
+ connect(ui.openCheckBox , SIGNAL(toggled(bool)), ui.openHotkeyWidget , SLOT(setEnabled(bool)));
+ connect(ui.directoryCheckBox , SIGNAL(toggled(bool)), ui.directoryHotkeyWidget, SLOT(setEnabled(bool)));
+
+ // "Save as" disables the file target input field.
+ connect(ui.saveAsCheckBox , SIGNAL(toggled(bool)), ui.targetLineEdit , SLOT(setDisabled(bool)));
+ connect(ui.saveAsCheckBox , SIGNAL(toggled(bool)), ui.browsePushButton , SLOT(setDisabled(bool)));
+ connect(ui.saveAsCheckBox , SIGNAL(toggled(bool)), ui.directoryLabel , SLOT(setDisabled(bool)));
+
+ connect(ui.startupCheckBox , SIGNAL(toggled(bool)), ui.startupHideCheckBox , SLOT(setEnabled(bool)));
+ connect(ui.qualitySlider , SIGNAL(valueChanged(int)), ui.qualityValueLabel, SLOT(setNum(int)));
+ connect(ui.trayCheckBox , SIGNAL(toggled(bool)), ui.messageCheckBox , SLOT(setEnabled(bool)));
+
+ // Auto-upload disables the default action button in the previews.
+ connect(ui.uploadCheckBox , SIGNAL(toggled(bool)), ui.previewDefaultActionLabel , SLOT(setDisabled(bool)));
+ connect(ui.uploadCheckBox , SIGNAL(toggled(bool)), ui.previewDefaultActionComboBox, SLOT(setDisabled(bool)));
+ connect(ui.directoryCheckBox , SIGNAL(toggled(bool)), ui.directoryHotkeyWidget, SLOT(setEnabled(bool)));
+
+ connect(ui.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.licenseAboutLabel, 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();
+}
+
+//
+
+bool OptionsDialog::hotkeyCollision()
+{
+ // Check for hotkey collision (there's probably a better way to do this...=)
+
+ if (ui.screenCheckBox->isChecked()) {
+ if (ui.screenHotkeyWidget->hotkey() == ui.areaHotkeyWidget->hotkey()
+ && ui.areaCheckBox->isChecked())
+ return true;
+
+ if (ui.screenHotkeyWidget->hotkey() == ui.windowHotkeyWidget->hotkey()
+ && ui.windowCheckBox->isChecked())
+ return true;
+
+ if (ui.screenHotkeyWidget->hotkey() == ui.windowPickerHotkeyWidget->hotkey()
+ && ui.windowPickerCheckBox->isChecked())
+ return true;
+
+ if (ui.screenHotkeyWidget->hotkey() == ui.openHotkeyWidget->hotkey()
+ && ui.openCheckBox->isChecked())
+ return true;
+
+ if (ui.screenHotkeyWidget->hotkey() == ui.directoryHotkeyWidget->hotkey()
+ && ui.directoryCheckBox->isChecked())
+ return true;
+ }
+
+ if (ui.areaCheckBox->isChecked()) {
+ if (ui.areaHotkeyWidget->hotkey() == ui.screenHotkeyWidget->hotkey()
+ && ui.screenCheckBox->isChecked())
+ return true;
+
+ if (ui.areaHotkeyWidget->hotkey() == ui.windowHotkeyWidget->hotkey()
+ && ui.windowCheckBox->isChecked())
+ return true;
+
+ if (ui.areaHotkeyWidget->hotkey() == ui.windowPickerHotkeyWidget->hotkey()
+ && ui.windowPickerCheckBox->isChecked())
+ return true;
+
+ if (ui.areaHotkeyWidget->hotkey() == ui.openHotkeyWidget->hotkey()
+ && ui.openCheckBox->isChecked())
+ return true;
+
+ if (ui.areaHotkeyWidget->hotkey() == ui.directoryHotkeyWidget->hotkey()
+ && ui.directoryCheckBox->isChecked())
+ return true;
+ }
+
+ if (ui.windowCheckBox->isChecked()) {
+ if (ui.windowHotkeyWidget->hotkey() == ui.screenHotkeyWidget->hotkey()
+ && ui.screenCheckBox->isChecked())
+ return true;
+
+ if (ui.windowHotkeyWidget->hotkey() == ui.areaHotkeyWidget->hotkey()
+ && ui.areaCheckBox->isChecked())
+ return true;
+
+ if (ui.windowHotkeyWidget->hotkey() == ui.windowPickerHotkeyWidget->hotkey()
+ && ui.windowPickerCheckBox->isChecked())
+ return true;
+
+ if (ui.windowHotkeyWidget->hotkey() == ui.openHotkeyWidget->hotkey()
+ && ui.openCheckBox->isChecked())
+ return true;
+
+ if (ui.windowHotkeyWidget->hotkey() == ui.directoryHotkeyWidget->hotkey()
+ && ui.directoryCheckBox->isChecked())
+ return true;
+ }
+
+ if (ui.openCheckBox->isChecked()) {
+ if (ui.openHotkeyWidget->hotkey() == ui.screenHotkeyWidget->hotkey()
+ && ui.screenCheckBox->isChecked())
+ return true;
+
+ if (ui.openHotkeyWidget->hotkey() == ui.areaHotkeyWidget->hotkey()
+ && ui.areaCheckBox->isChecked())
+ return true;
+
+ if (ui.openHotkeyWidget->hotkey() == ui.windowPickerHotkeyWidget->hotkey()
+ && ui.windowPickerCheckBox->isChecked())
+ return true;
+
+ if (ui.openHotkeyWidget->hotkey() == ui.windowHotkeyWidget->hotkey()
+ && ui.windowCheckBox->isChecked())
+ return true;
+
+ if (ui.openHotkeyWidget->hotkey() == ui.directoryHotkeyWidget->hotkey()
+ && ui.directoryCheckBox->isChecked())
+ return true;
+ }
+
+ if (ui.directoryCheckBox->isChecked()) {
+ if (ui.directoryHotkeyWidget->hotkey() == ui.screenHotkeyWidget->hotkey()
+ && ui.screenCheckBox->isChecked())
+ return true;
+
+ if (ui.directoryHotkeyWidget->hotkey() == ui.areaHotkeyWidget->hotkey()
+ && ui.areaCheckBox->isChecked())
+ return true;
+
+ if (ui.directoryHotkeyWidget->hotkey() == ui.windowPickerHotkeyWidget->hotkey()
+ && ui.windowPickerCheckBox->isChecked())
+ return true;
+
+ if (ui.directoryHotkeyWidget->hotkey() == ui.windowHotkeyWidget->hotkey()
+ && ui.windowCheckBox->isChecked())
+ return true;
+
+ if (ui.directoryHotkeyWidget->hotkey() == ui.openHotkeyWidget->hotkey()
+ && ui.openCheckBox->isChecked())
+ return true;
+ }
+
+ return false;
+}
+
+QSettings *OptionsDialog::settings() const
+{
+ return ScreenshotManager::instance()->settings();
+}
diff --git a/lightscreen.pro b/lightscreen.pro
index b43fcc7..0b5bbd0 100644
--- a/lightscreen.pro
+++ b/lightscreen.pro
@@ -1,68 +1,75 @@
-TEMPLATE = app
-TARGET = lightscreen
-HEADERS += tools/os.h \
- updater/updater.h \
- dialogs/areadialog.h \
- dialogs/optionsdialog.h \
- widgets/hotkeywidget.h \
- lightscreenwindow.h \
- tools/screenshot.h \
- dialogs/previewdialog.h \
- tools/screenshotmanager.h \
- tools/windowpicker.h \
- tools/uploader.h \
- tools/qtimgur.h \
- dialogs/updaterdialog.h \
- dialogs/screenshotdialog.h \
- dialogs/namingdialog.h \
- dialogs/historydialog.h
-SOURCES += tools/os.cpp \
- updater/updater.cpp \
- dialogs/areadialog.cpp \
- dialogs/optionsdialog.cpp \
- widgets/hotkeywidget.cpp \
- main.cpp \
- lightscreenwindow.cpp \
- tools/screenshot.cpp \
- dialogs/previewdialog.cpp \
- tools/screenshotmanager.cpp \
- tools/windowpicker.cpp \
- tools/uploader.cpp \
- tools/qtimgur.cpp \
- dialogs/updaterdialog.cpp \
- dialogs/screenshotdialog.cpp \
- dialogs/namingdialog.cpp \
- dialogs/historydialog.cpp
-FORMS += dialogs/optionsdialog.ui \
- dialogs/namingdialog.ui \
- dialogs/historydialog.ui \
- lightscreenwindow.ui
-RESOURCES += lightscreen.qrc
-TRANSLATIONS += translations/untranslated.ts \
- translations/spanish.ts \
- translations/russian.ts \
- translations/portuguese.ts \
- translations/polish.ts \
- translations/japanese.ts \
- translations/italian.ts \
- translations/dutch.ts
-RC_FILE += lightscreen.rc
-CODECFORSRC = UTF-8
-QT += network core gui xml sql
-
-include($$PWD/tools/globalshortcut/globalshortcut.pri)
-include($$PWD/tools/qtsingleapplication/qtsingleapplication.pri)
-include($$PWD/tools/qwin7utils/qwin7utils.pri)
-
-win32:LIBS += libgdi32 libgcc libuser32 libole32 libshell32 libshlwapi libcomctl32
-
-QMAKE_CXXFLAGS = -Wextra -Wall -Wpointer-arith
-OTHER_FILES += TODO.txt
-
-
-
-
-
-
-
-
+TEMPLATE = app
+TARGET = lightscreen
+HEADERS += tools/os.h \
+ updater/updater.h \
+ dialogs/areadialog.h \
+ dialogs/optionsdialog.h \
+ widgets/hotkeywidget.h \
+ lightscreenwindow.h \
+ tools/screenshot.h \
+ dialogs/previewdialog.h \
+ tools/screenshotmanager.h \
+ tools/windowpicker.h \
+ tools/uploader.h \
+ tools/qtimgur.h \
+ dialogs/updaterdialog.h \
+ dialogs/screenshotdialog.h \
+ dialogs/namingdialog.h \
+ dialogs/historydialog.h
+SOURCES += tools/os.cpp \
+ updater/updater.cpp \
+ dialogs/areadialog.cpp \
+ dialogs/optionsdialog.cpp \
+ widgets/hotkeywidget.cpp \
+ main.cpp \
+ lightscreenwindow.cpp \
+ tools/screenshot.cpp \
+ dialogs/previewdialog.cpp \
+ tools/screenshotmanager.cpp \
+ tools/windowpicker.cpp \
+ tools/uploader.cpp \
+ tools/qtimgur.cpp \
+ dialogs/updaterdialog.cpp \
+ dialogs/screenshotdialog.cpp \
+ dialogs/namingdialog.cpp \
+ dialogs/historydialog.cpp
+FORMS += dialogs/optionsdialog.ui \
+ dialogs/namingdialog.ui \
+ dialogs/historydialog.ui \
+ lightscreenwindow.ui
+RESOURCES += lightscreen.qrc
+TRANSLATIONS += translations/untranslated.ts \
+ translations/spanish.ts \
+ translations/russian.ts \
+ translations/portuguese.ts \
+ translations/polish.ts \
+ translations/japanese.ts \
+ translations/italian.ts \
+ translations/dutch.ts
+RC_FILE += lightscreen.rc
+CODECFORSRC = UTF-8
+QT += network core gui xml sql
+
+include($$PWD/tools/globalshortcut/globalshortcut.pri)
+include($$PWD/tools/qtsingleapplication/qtsingleapplication.pri)
+include($$PWD/tools/qwin7utils/qwin7utils.pri)
+
+windows{
+ contains(QMAKE_CC, gcc){
+ LIBS += libgdi32 libgcc libuser32 libole32 libshell32 libshlwapi libcomctl32
+ QMAKE_CXXFLAGS = -Wextra -Wall -Wpointer-arith
+ }
+ contains(QMAKE_CC, cl){
+ LIBS += gdi32.lib user32.lib ole32.lib shell32.lib shlwapi.lib comctl32.lib
+ }
+}
+
+OTHER_FILES += TODO.txt
+
+
+
+
+
+
+
+
diff --git a/lightscreenwindow.cpp b/lightscreenwindow.cpp
index a2067de..7868cc8 100644
--- a/lightscreenwindow.cpp
+++ b/lightscreenwindow.cpp
@@ -1,983 +1,983 @@
-/*
- * 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 <QMainWindow>
-#include <QDate>
-#include <QDesktopServices>
-#include <QFileInfo>
-#include <QHttp>
-#include <QKeyEvent>
-#include <QMenu>
-#include <QMessageBox>
-#include <QPointer>
-#include <QProcess>
-#include <QSettings>
-#include <QSound>
-#include <QSystemTrayIcon>
-#include <QTimer>
-#include <QToolTip>
-#include <QUrl>
-
-#include <QDebug>
-
-#ifdef Q_WS_WIN
- #include <windows.h>
- #include "tools/qwin7utils/Taskbar.h"
- #include "tools/qwin7utils/TaskbarButton.h"
- #include "tools/qwin7utils/Utils.h"
- using namespace QW7;
-#endif
-
-/*
- * Lightscreen includes
- */
-#include "lightscreenwindow.h"
-#include "dialogs/optionsdialog.h"
-#include "dialogs/previewdialog.h"
-#include "dialogs/historydialog.h"
-
-#include "tools/globalshortcut/globalshortcutmanager.h"
-#include "tools/os.h"
-#include "tools/screenshot.h"
-#include "tools/screenshotmanager.h"
-
-#include "tools/uploader.h"
-
-#include "updater/updater.h"
-
-LightscreenWindow::LightscreenWindow(QWidget *parent) :
- QMainWindow(parent),
- mDoCache(false),
- mHideTrigger(false),
- mReviveMain(false),
- mWasVisible(true),
- mLastMessage(0),
- mLastMode(-1),
- mLastScreenshot()
-{
- os::translate(settings()->value("options/language", "English").toString());
-
- ui.setupUi(this);
-
-#ifdef Q_WS_WIN
- ExtendFrameIntoClientArea(this);
-#endif
-
- setMaximumSize(size());
- setMinimumSize(size());
-
- setWindowFlags(Qt::Window);
-
-#ifdef Q_WS_WIN
- if (QSysInfo::windowsVersion() >= QSysInfo::WV_WINDOWS7) {
- mTaskbarButton = new TaskbarButton(this);
- }
-#endif
-
- // Actions
- connect(ui.screenPushButton, SIGNAL(clicked()), this, SLOT(screenshotAction()));
- connect(ui.areaPushButton , SIGNAL(clicked()), this, SLOT(areaHotkey()));
- connect(ui.windowPushButton, SIGNAL(clicked()), this, SLOT(windowPickerHotkey()));
-
- connect(ui.optionsPushButton, SIGNAL(clicked()), this, SLOT(showOptions()));
- connect(ui.folderPushButton , SIGNAL(clicked()), this, SLOT(goToFolder()));
-
- connect(ui.imgurPushButton, SIGNAL(clicked()), this, SLOT(showUploadMenu()));
-
- // Uploader
- connect(Uploader::instance(), SIGNAL(progress(qint64, qint64)), this, SLOT(uploadProgress(qint64, qint64)));
- connect(Uploader::instance(), SIGNAL(done(QString, QString, QString)), this, SLOT(showUploaderMessage(QString, QString)));
- connect(Uploader::instance(), SIGNAL(error(QString)), this, SLOT(showUploaderError(QString)));
-
- // Manager
- connect(ScreenshotManager::instance(), SIGNAL(confirm(Screenshot*)), this, SLOT(preview(Screenshot*)));
- connect(ScreenshotManager::instance(), SIGNAL(windowCleanup(Screenshot::Options&)), this, SLOT(cleanup(Screenshot::Options&)));
-
- if (!settings()->contains("file/format")) {
- showOptions(); // There are no options (or the options config is invalid or incomplete)
- }
- else {
- QTimer::singleShot(0 , this, SLOT(applySettings()));
- QTimer::singleShot(5000, this, SLOT(checkForUpdates()));
- }
-}
-
-LightscreenWindow::~LightscreenWindow()
-{
- settings()->setValue("lastScreenshot", mLastScreenshot);
- settings()->sync();
-
- GlobalShortcutManager::instance()->clear();
- delete mTrayIcon;
-}
-
-void LightscreenWindow::action(int mode)
-{
- if (mode == 4) {
- goToFolder();
- }
- else {
- show();
- }
-}
-
-void LightscreenWindow::areaHotkey()
-{
- screenshotAction(2);
-}
-
-void LightscreenWindow::checkForUpdates()
-{
- if (settings()->value("options/disableUpdater", false).toBool())
- return;
-
- if (settings()->value("lastUpdateCheck").toInt() + 7
- > QDate::currentDate().dayOfYear())
- return; // If 7 days have not passed since the last update check.
-
- connect(Updater::instance(), SIGNAL(done(bool)), this, SLOT(updaterDone(bool)));
- Updater::instance()->check();
-}
-
-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 {
-#ifdef Q_WS_WIN
- QSound::play("afakepathtomakewindowsplaythedefaultsoundtheresprobablyabetterwaybuticantbebothered");
-#else
- QSound::play("sound/ls.error.wav");
-#endif
- }
- }
-
- if (options.result != Screenshot::Success)
- return;
-
- mLastScreenshot = options.fileName;
-}
-
-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::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::messageClicked()
-{
- if (mLastMessage == 1) {
- goToFolder();
- }
- else {
- QDesktopServices::openUrl(QUrl(Uploader::instance()->lastUrl()));
- }
-}
-
-void LightscreenWindow::messageReceived(const QString &message)
-{
- if (message.contains(' ')) {
- foreach (QString argument, message.split(' ')) {
- messageReceived(argument);
- }
- }
-
- if (message == "--wake") {
- show();
- qApp->alert(this, 500);
- return;
- }
-
- if (message == "--screen")
- screenshotAction();
- else if (message == "--area")
- screenshotAction(2);
- else if (message == "--activewindow")
- screenshotAction(1);
- else if (message == "--pickwindow")
- screenshotAction(3);
- else if (message == "--folder")
- action(4);
- else if (message == "--uploadlast")
- uploadLast();
- else if (message == "--viewhistory")
- showHistoryDialog();
-}
-
-void LightscreenWindow::notify(const Screenshot::Result &result)
-{
- switch (result)
- {
- case Screenshot::Success:
- mTrayIcon->setIcon(QIcon(":/icons/lightscreen.yes"));
-
-#ifdef Q_WS_WIN
- if (mTaskbarButton)
- 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
- if (mTaskbarButton)
- mTaskbarButton->SetOverlayIcon(QIcon(":/icons/no"), tr("Failed!"));
-#endif
- break;
- case Screenshot::Cancel:
- setWindowTitle(tr("Cancelled!"));
- break;
- }
-
- QTimer::singleShot(2000, this, SLOT(restoreNotification()));
-}
-
-void LightscreenWindow::preview(Screenshot* screenshot)
-{
- if (screenshot->options().preview) {
- if (!mPreviewDialog) {
- mPreviewDialog = new PreviewDialog(this);
- }
-
- mPreviewDialog->add(screenshot);
- }
- else {
- screenshot->confirm(true);
- }
-}
-
-void LightscreenWindow::quit()
-{
- settings()->setValue("position", pos());
-
- int answer = 0;
- QString doing;
-
- if (ScreenshotManager::instance()->activeCount() > 0) {
- doing = tr("processing");
- }
-
- if (Uploader::instance()->uploading() > 0) {
- if (doing.isEmpty()) {
- doing = tr("uploading");
- }
- else {
- doing = tr("processing and uploading");
- }
- }
-
- if (!doing.isEmpty()) {
- answer = QMessageBox::question(this,
- tr("Are you sure you want to quit?"),
- tr("Lightscreen is currently %1 screenshots. Are you sure you want to quit?").arg(doing),
- tr("Quit"),
- tr("Don't Quit"));
- }
-
- if (answer == 0)
- emit finished();
-}
-
-void LightscreenWindow::restoreNotification()
-{
- if (mTrayIcon)
- mTrayIcon->setIcon(QIcon(":/icons/lightscreen.small"));
-
-#ifdef Q_WS_WIN
- if (mTaskbarButton)
- mTaskbarButton->SetOverlayIcon(QIcon(), "");
-#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();
-
- QDir dir(settings()->value("file/target").toString());
- dir.makeAbsolute();
-
- options.directory = dir;
-
- options.quality = settings()->value("options/quality", 100).toInt();
- options.currentMonitor = settings()->value("options/currentMonitor", false).toBool();
- options.clipboard = settings()->value("options/clipboard", true).toBool();
- options.imgurClipboard = settings()->value("options/imgurClipboard", false).toBool();
- options.preview = settings()->value("options/preview", false).toBool();
- options.magnify = settings()->value("options/magnify", false).toBool();
- options.cursor = settings()->value("options/cursor", 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();
- options.optimize = settings()->value("options/optipng", false).toBool();
-
- Screenshot::NamingOptions namingOptions;
- namingOptions.naming = (Screenshot::Naming) settings()->value("file/naming").toInt();
- namingOptions.leadingZeros = settings()->value("options/naming/leadingZeros", 0).toInt();
- namingOptions.flip = settings()->value("options/flip", false).toBool();
- namingOptions.dateFormat = settings()->value("options/naming/dateFormat", "yyyy-MM-dd").toString();
-
- options.namingOptions = namingOptions;
-
- mDoCache = true;
- }
-
- options.mode = mode;
-
- ScreenshotManager::instance()->take(options);
-}
-
-void LightscreenWindow::screenshotActionTriggered(QAction* action)
-{
- screenshotAction(action->data().toInt());
-}
-
-void LightscreenWindow::showHotkeyError(const QStringList &hotkeys)
-{
- static bool dontShow = false;
-
- if (dontShow)
- return;
-
- QString messageText;
-
- messageText = tr("Some hotkeys could not be registered, they might already be in use");
-
- if (hotkeys.count() > 1) {
- messageText += tr("<br>The failed hotkeys are the following:") + "<ul>";
-
- foreach(const QString &hotkey, hotkeys) {
- 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::showHistoryDialog()
-{
- HistoryDialog historyDialog(this);
- historyDialog.exec();
-
- updateUploadStatus();
-}
-
-void LightscreenWindow::showOptions()
-{
- GlobalShortcutManager::clear();
-
- QPointer<OptionsDialog> optionsDialog = new OptionsDialog(this);
-
- optionsDialog->exec();
- optionsDialog->deleteLater();
-
- applySettings();
-}
-
-
-void LightscreenWindow::showUploadMenu()
-{
- QMenu* imgurMenu = new QMenu(tr("Upload"));
-
- QAction *uploadAction = new QAction(QIcon(":/icons/imgur"), tr("&Upload last"), imgurMenu);
- uploadAction->setToolTip(tr("Upload the last screenshot you took to imgur.com"));
- connect(uploadAction, SIGNAL(triggered()), this, SLOT(uploadLast()));
-
- QAction *cancelAction = new QAction(QIcon(":/icons/no"), tr("&Cancel upload"), imgurMenu);
- cancelAction->setToolTip(tr("Cancel the currently uploading screenshots"));
- cancelAction->setEnabled(false);
- connect(this, SIGNAL(uploading(bool)), cancelAction, SLOT(setEnabled(bool)));
- connect(cancelAction, SIGNAL(triggered()), this, SLOT(uploadCancel()));
-
- QAction *historyAction = new QAction(QIcon(":/icons/view-history"), tr("View &History"), imgurMenu);
- connect(historyAction, SIGNAL(triggered()), this, SLOT(showHistoryDialog()));
-
- imgurMenu->addAction(uploadAction);
- imgurMenu->addAction(cancelAction);
- imgurMenu->addAction(historyAction);
- imgurMenu->addSeparator();
-
- ui.imgurPushButton->setMenu(imgurMenu);
- ui.imgurPushButton->showMenu();
-}
-
-
-void LightscreenWindow::showScreenshotMessage(const Screenshot::Result &result, const 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::showUploaderError(const QString &error)
-{
- mLastMessage = -1;
-
- if (mTrayIcon && !error.isEmpty()) {
- mTrayIcon->showMessage(tr("Upload error"), error);
- }
-
- updateUploadStatus();
-}
-
-void LightscreenWindow::showUploaderMessage(QString fileName, QString url)
-{
- if (!mTrayIcon)
- return;
-
- QString screenshot = QFileInfo(fileName).fileName();
-
- if (screenshot.startsWith(".lstemp."))
- screenshot = tr("Screenshot");
-
- mLastMessage = 2;
- mTrayIcon->showMessage(tr("%1 uploaded").arg(screenshot), tr("Click here to go to %1").arg(url));
- updateUploadStatus();
-}
-
-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();
- }
-}
-
-void LightscreenWindow::updateUploadStatus()
-{
- int uploadCount = Uploader::instance()->uploading();
- QString statusString;
-
- if (uploadCount > 0) {
- statusString = tr("%1 uploading - Lightscreen").arg(uploadCount);
- ui.imgurPushButton->setIcon(QIcon(":/icons/imgur.upload"));
- emit uploading(true);
- }
- else {
- statusString = tr("Lightscreen");
- ui.imgurPushButton->setIcon(QIcon(":/icons/imgur"));
- emit uploading(false);
-
-#ifdef Q_WS_WIN
- if (mTaskbarButton) {
- mTaskbarButton->SetProgresValue(0, 0);
- mTaskbarButton->SetState(STATE_NOPROGRESS);
- }
-#endif
- }
-
- if (mTrayIcon) {
- mTrayIcon->setToolTip(statusString);
- }
-
- setWindowTitle(statusString);
-}
-
-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/whatsnew/?from=" + qApp->applicationVersion()));
- }
- else if (msgBox.clickedButton() == turnOffButton) {
- settings()->setValue("options/disableUpdater", true);
- }
-}
-
-void LightscreenWindow::upload(const QString &fileName)
-{
- Uploader::instance()->upload(fileName);
-}
-
-void LightscreenWindow::uploadCancel()
-{
- if (Uploader::instance()->uploading() <= 0) {
- return;
- }
-
- int confirm = QMessageBox::question(this, tr("Upload cancel"), tr("Do you want to cancel all screenshot uploads?"), tr("Cancel"), tr("Don't Cancel"));
-
- if (confirm == 0) {
- Uploader::instance()->cancel();
- updateUploadStatus();
- }
-}
-
-void LightscreenWindow::uploadLast()
-{
- upload(mLastScreenshot);
- updateUploadStatus();
-}
-
-void LightscreenWindow::uploadProgress(qint64 sent, qint64 total)
-{
-#ifdef Q_WS_WIN
- if (mTaskbarButton)
- mTaskbarButton->SetProgresValue(sent, total);
-
- if (isVisible()) {
- int uploadCount = Uploader::instance()->uploading();
- int progress = (sent*100)/total;
-
- if (uploadCount > 1) {
- setWindowTitle(tr("%1% of %2 uploads - Lightscreen").arg(progress).arg(uploadCount));
- }
- else {
- setWindowTitle(tr("%1% - Lightscreen").arg(progress));
- }
- }
-#endif
-}
-
-void LightscreenWindow::windowHotkey()
-{
- screenshotAction(1);
-}
-
-void LightscreenWindow::windowPickerHotkey()
-{
- screenshotAction(3);
-}
-
-//
-
-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::connectHotkeys()
-{
- // Set to true because if the hotkey is disabled it will show an error.
- bool screen = true, area = true, window = true, windowPicker = 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())
- windowPicker = 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 (!windowPicker) failed << "window picker";
- 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 *cancelAction = new QAction(QIcon(":/icons/no"), tr("&Cancel upload"), mTrayIcon);
- cancelAction->setToolTip(tr("Cancel the currently uploading screenshots"));
- cancelAction->setEnabled(false);
- connect(this, SIGNAL(uploading(bool)), cancelAction, SLOT(setEnabled(bool)));
- connect(cancelAction, SIGNAL(triggered()), this, SLOT(uploadCancel()));
-
- QAction *historyAction = new QAction(QIcon(":/icons/view-history"), tr("View History"), mTrayIcon);
- connect(historyAction, SIGNAL(triggered()), this, SLOT(showHistoryDialog()));
- //
-
- 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(tr("Screenshot"));
- screenshotMenu->addAction(screenAction);
- screenshotMenu->addAction(areaAction);
- screenshotMenu->addAction(windowAction);
- screenshotMenu->addAction(windowPickerAction);
-
- // Duplicated for the screenshot button :(
- QMenu* imgurMenu = new QMenu(tr("Upload"));
- imgurMenu->addAction(uploadAction);
- imgurMenu->addAction(cancelAction);
- imgurMenu->addAction(historyAction);
- imgurMenu->addSeparator();
-
- QMenu* trayIconMenu = new QMenu;
- trayIconMenu->addAction(hideAction);
- trayIconMenu->addSeparator();
- trayIconMenu->addMenu(imgurMenu);
- trayIconMenu->addSeparator();
- trayIconMenu->addMenu(screenshotMenu);
- trayIconMenu->addAction(optionsAction);
- trayIconMenu->addAction(goAction);
- trayIconMenu->addSeparator();
- trayIconMenu->addAction(quitAction);
-
- mTrayIcon->setContextMenu(trayIconMenu);
-}
-
-#ifdef Q_WS_WIN
-bool LightscreenWindow::winEvent(MSG *message, long *result)
-{
- Taskbar::GetInstance()->winEvent(message, result);
- return false;
-}
-#endif
-
-QSettings *LightscreenWindow::settings() const
-{
- return ScreenshotManager::instance()->settings();
-}
-
-// 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) {
- 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 QMainWindow::event(event);
-}
+/*
+ * 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 <QMainWindow>
+#include <QDate>
+#include <QDesktopServices>
+#include <QFileInfo>
+#include <QHttp>
+#include <QKeyEvent>
+#include <QMenu>
+#include <QMessageBox>
+#include <QPointer>
+#include <QProcess>
+#include <QSettings>
+#include <QSound>
+#include <QSystemTrayIcon>
+#include <QTimer>
+#include <QToolTip>
+#include <QUrl>
+
+#include <QDebug>
+
+#ifdef Q_WS_WIN
+ #include <windows.h>
+ #include "tools/qwin7utils/Taskbar.h"
+ #include "tools/qwin7utils/TaskbarButton.h"
+ #include "tools/qwin7utils/Utils.h"
+ using namespace QW7;
+#endif
+
+/*
+ * Lightscreen includes
+ */
+#include "lightscreenwindow.h"
+#include "dialogs/optionsdialog.h"
+#include "dialogs/previewdialog.h"
+#include "dialogs/historydialog.h"
+
+#include "tools/globalshortcut/globalshortcutmanager.h"
+#include "tools/os.h"
+#include "tools/screenshot.h"
+#include "tools/screenshotmanager.h"
+
+#include "tools/uploader.h"
+
+#include "updater/updater.h"
+
+LightscreenWindow::LightscreenWindow(QWidget *parent) :
+ QMainWindow(parent),
+ mDoCache(false),
+ mHideTrigger(false),
+ mReviveMain(false),
+ mWasVisible(true),
+ mLastMessage(0),
+ mLastMode(-1),
+ mLastScreenshot()
+{
+ os::translate(settings()->value("options/language", "English").toString());
+
+ ui.setupUi(this);
+
+#ifdef Q_WS_WIN
+ ExtendFrameIntoClientArea(this);
+#endif
+
+ setMaximumSize(size());
+ setMinimumSize(size());
+
+ setWindowFlags(Qt::Window);
+
+#ifdef Q_WS_WIN
+ if (QSysInfo::windowsVersion() >= QSysInfo::WV_WINDOWS7) {
+ mTaskbarButton = new TaskbarButton(this);
+ }
+#endif
+
+ // Actions
+ connect(ui.screenPushButton, SIGNAL(clicked()), this, SLOT(screenshotAction()));
+ connect(ui.areaPushButton , SIGNAL(clicked()), this, SLOT(areaHotkey()));
+ connect(ui.windowPushButton, SIGNAL(clicked()), this, SLOT(windowPickerHotkey()));
+
+ connect(ui.optionsPushButton, SIGNAL(clicked()), this, SLOT(showOptions()));
+ connect(ui.folderPushButton , SIGNAL(clicked()), this, SLOT(goToFolder()));
+
+ connect(ui.imgurPushButton, SIGNAL(clicked()), this, SLOT(showUploadMenu()));
+
+ // Uploader
+ connect(Uploader::instance(), SIGNAL(progress(qint64, qint64)), this, SLOT(uploadProgress(qint64, qint64)));
+ connect(Uploader::instance(), SIGNAL(done(QString, QString, QString)), this, SLOT(showUploaderMessage(QString, QString)));
+ connect(Uploader::instance(), SIGNAL(error(QString)), this, SLOT(showUploaderError(QString)));
+
+ // Manager
+ connect(ScreenshotManager::instance(), SIGNAL(confirm(Screenshot*)), this, SLOT(preview(Screenshot*)));
+ connect(ScreenshotManager::instance(), SIGNAL(windowCleanup(Screenshot::Options&)), this, SLOT(cleanup(Screenshot::Options&)));
+
+ if (!settings()->contains("file/format")) {
+ showOptions(); // There are no options (or the options config is invalid or incomplete)
+ }
+ else {
+ QTimer::singleShot(0 , this, SLOT(applySettings()));
+ QTimer::singleShot(5000, this, SLOT(checkForUpdates()));
+ }
+}
+
+LightscreenWindow::~LightscreenWindow()
+{
+ settings()->setValue("lastScreenshot", mLastScreenshot);
+ settings()->sync();
+
+ GlobalShortcutManager::instance()->clear();
+ delete mTrayIcon;
+}
+
+void LightscreenWindow::action(int mode)
+{
+ if (mode == 4) {
+ goToFolder();
+ }
+ else {
+ show();
+ }
+}
+
+void LightscreenWindow::areaHotkey()
+{
+ screenshotAction(2);
+}
+
+void LightscreenWindow::checkForUpdates()
+{
+ if (settings()->value("options/disableUpdater", false).toBool())
+ return;
+
+ if (settings()->value("lastUpdateCheck").toInt() + 7
+ > QDate::currentDate().dayOfYear())
+ return; // If 7 days have not passed since the last update check.
+
+ connect(Updater::instance(), SIGNAL(done(bool)), this, SLOT(updaterDone(bool)));
+ Updater::instance()->check();
+}
+
+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 {
+#ifdef Q_WS_WIN
+ QSound::play("afakepathtomakewindowsplaythedefaultsoundtheresprobablyabetterwaybuticantbebothered");
+#else
+ QSound::play("sound/ls.error.wav");
+#endif
+ }
+ }
+
+ if (options.result != Screenshot::Success)
+ return;
+
+ mLastScreenshot = options.fileName;
+}
+
+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::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::messageClicked()
+{
+ if (mLastMessage == 1) {
+ goToFolder();
+ }
+ else {
+ QDesktopServices::openUrl(QUrl(Uploader::instance()->lastUrl()));
+ }
+}
+
+void LightscreenWindow::messageReceived(const QString &message)
+{
+ if (message.contains(' ')) {
+ foreach (QString argument, message.split(' ')) {
+ messageReceived(argument);
+ }
+ }
+
+ if (message == "--wake") {
+ show();
+ qApp->alert(this, 500);
+ return;
+ }
+
+ if (message == "--screen")
+ screenshotAction();
+ else if (message == "--area")
+ screenshotAction(2);
+ else if (message == "--activewindow")
+ screenshotAction(1);
+ else if (message == "--pickwindow")
+ screenshotAction(3);
+ else if (message == "--folder")
+ action(4);
+ else if (message == "--uploadlast")
+ uploadLast();
+ else if (message == "--viewhistory")
+ showHistoryDialog();
+}
+
+void LightscreenWindow::notify(const Screenshot::Result &result)
+{
+ switch (result)
+ {
+ case Screenshot::Success:
+ mTrayIcon->setIcon(QIcon(":/icons/lightscreen.yes"));
+
+#ifdef Q_WS_WIN
+ if (mTaskbarButton)
+ 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
+ if (mTaskbarButton)
+ mTaskbarButton->SetOverlayIcon(QIcon(":/icons/no"), tr("Failed!"));
+#endif
+ break;
+ case Screenshot::Cancel:
+ setWindowTitle(tr("Cancelled!"));
+ break;
+ }
+
+ QTimer::singleShot(2000, this, SLOT(restoreNotification()));
+}
+
+void LightscreenWindow::preview(Screenshot* screenshot)
+{
+ if (screenshot->options().preview) {
+ if (!mPreviewDialog) {
+ mPreviewDialog = new PreviewDialog(this);
+ }
+
+ mPreviewDialog->add(screenshot);
+ }
+ else {
+ screenshot->confirm(true);
+ }
+}
+
+void LightscreenWindow::quit()
+{
+ settings()->setValue("position", pos());
+
+ int answer = 0;
+ QString doing;
+
+ if (ScreenshotManager::instance()->activeCount() > 0) {
+ doing = tr("processing");
+ }
+
+ if (Uploader::instance()->uploading() > 0) {
+ if (doing.isEmpty()) {
+ doing = tr("uploading");
+ }
+ else {
+ doing = tr("processing and uploading");
+ }
+ }
+
+ if (!doing.isEmpty()) {
+ answer = QMessageBox::question(this,
+ tr("Are you sure you want to quit?"),
+ tr("Lightscreen is currently %1 screenshots. Are you sure you want to quit?").arg(doing),
+ tr("Quit"),
+ tr("Don't Quit"));
+ }
+
+ if (answer == 0)
+ emit finished();
+}
+
+void LightscreenWindow::restoreNotification()
+{
+ if (mTrayIcon)
+ mTrayIcon->setIcon(QIcon(":/icons/lightscreen.small"));
+
+#ifdef Q_WS_WIN
+ if (mTaskbarButton)
+ mTaskbarButton->SetOverlayIcon(QIcon(), "");
+#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();
+
+ QDir dir(settings()->value("file/target").toString());
+ dir.makeAbsolute();
+
+ options.directory = dir;
+
+ options.quality = settings()->value("options/quality", 100).toInt();
+ options.currentMonitor = settings()->value("options/currentMonitor", false).toBool();
+ options.clipboard = settings()->value("options/clipboard", true).toBool();
+ options.imgurClipboard = settings()->value("options/imgurClipboard", false).toBool();
+ options.preview = settings()->value("options/preview", false).toBool();
+ options.magnify = settings()->value("options/magnify", false).toBool();
+ options.cursor = settings()->value("options/cursor", 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();
+ options.optimize = settings()->value("options/optipng", false).toBool();
+
+ Screenshot::NamingOptions namingOptions;
+ namingOptions.naming = (Screenshot::Naming) settings()->value("file/naming").toInt();
+ namingOptions.leadingZeros = settings()->value("options/naming/leadingZeros", 0).toInt();
+ namingOptions.flip = settings()->value("options/flip", false).toBool();
+ namingOptions.dateFormat = settings()->value("options/naming/dateFormat", "yyyy-MM-dd").toString();
+
+ options.namingOptions = namingOptions;
+
+ mDoCache = true;
+ }
+
+ options.mode = mode;
+
+ ScreenshotManager::instance()->take(options);
+}
+
+void LightscreenWindow::screenshotActionTriggered(QAction* action)
+{
+ screenshotAction(action->data().toInt());
+}
+
+void LightscreenWindow::showHotkeyError(const QStringList &hotkeys)
+{
+ static bool dontShow = false;
+
+ if (dontShow)
+ return;
+
+ QString messageText;
+
+ messageText = tr("Some hotkeys could not be registered, they might already be in use");
+
+ if (hotkeys.count() > 1) {
+ messageText += tr("<br>The failed hotkeys are the following:") + "<ul>";
+
+ foreach(const QString &hotkey, hotkeys) {
+ 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::showHistoryDialog()
+{
+ HistoryDialog historyDialog(this);
+ historyDialog.exec();
+
+ updateUploadStatus();
+}
+
+void LightscreenWindow::showOptions()
+{
+ GlobalShortcutManager::clear();
+
+ QPointer<OptionsDialog> optionsDialog = new OptionsDialog(this);
+
+ optionsDialog->exec();
+ optionsDialog->deleteLater();
+
+ applySettings();
+}
+
+
+void LightscreenWindow::showUploadMenu()
+{
+ QMenu* imgurMenu = new QMenu(tr("Upload"));
+
+ QAction *uploadAction = new QAction(QIcon(":/icons/imgur"), tr("&Upload last"), imgurMenu);
+ uploadAction->setToolTip(tr("Upload the last screenshot you took to imgur.com"));
+ connect(uploadAction, SIGNAL(triggered()), this, SLOT(uploadLast()));
+
+ QAction *cancelAction = new QAction(QIcon(":/icons/no"), tr("&Cancel upload"), imgurMenu);
+ cancelAction->setToolTip(tr("Cancel the currently uploading screenshots"));
+ cancelAction->setEnabled(false);
+ connect(this, SIGNAL(uploading(bool)), cancelAction, SLOT(setEnabled(bool)));
+ connect(cancelAction, SIGNAL(triggered()), this, SLOT(uploadCancel()));
+
+ QAction *historyAction = new QAction(QIcon(":/icons/view-history"), tr("View &History"), imgurMenu);
+ connect(historyAction, SIGNAL(triggered()), this, SLOT(showHistoryDialog()));
+
+ imgurMenu->addAction(uploadAction);
+ imgurMenu->addAction(cancelAction);
+ imgurMenu->addAction(historyAction);
+ imgurMenu->addSeparator();
+
+ ui.imgurPushButton->setMenu(imgurMenu);
+ ui.imgurPushButton->showMenu();
+}
+
+
+void LightscreenWindow::showScreenshotMessage(const Screenshot::Result &result, const 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::showUploaderError(const QString &error)
+{
+ mLastMessage = -1;
+
+ if (mTrayIcon && !error.isEmpty()) {
+ mTrayIcon->showMessage(tr("Upload error"), error);
+ }
+
+ updateUploadStatus();
+}
+
+void LightscreenWindow::showUploaderMessage(QString fileName, QString url)
+{
+ if (!mTrayIcon)
+ return;
+
+ QString screenshot = QFileInfo(fileName).fileName();
+
+ if (screenshot.startsWith(".lstemp."))
+ screenshot = tr("Screenshot");
+
+ mLastMessage = 2;
+ mTrayIcon->showMessage(tr("%1 uploaded").arg(screenshot), tr("Click here to go to %1").arg(url));
+ updateUploadStatus();
+}
+
+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();
+ }
+}
+
+void LightscreenWindow::updateUploadStatus()
+{
+ int uploadCount = Uploader::instance()->uploading();
+ QString statusString;
+
+ if (uploadCount > 0) {
+ statusString = tr("%1 uploading - Lightscreen").arg(uploadCount);
+ ui.imgurPushButton->setIcon(QIcon(":/icons/imgur.upload"));
+ emit uploading(true);
+ }
+ else {
+ statusString = tr("Lightscreen");
+ ui.imgurPushButton->setIcon(QIcon(":/icons/imgur"));
+ emit uploading(false);
+
+#ifdef Q_WS_WIN
+ if (mTaskbarButton) {
+ mTaskbarButton->SetProgresValue(0, 0);
+ mTaskbarButton->SetState(STATE_NOPROGRESS);
+ }
+#endif
+ }
+
+ if (mTrayIcon) {
+ mTrayIcon->setToolTip(statusString);
+ }
+
+ setWindowTitle(statusString);
+}
+
+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/whatsnew/?from=" + qApp->applicationVersion()));
+ }
+ else if (msgBox.clickedButton() == turnOffButton) {
+ settings()->setValue("options/disableUpdater", true);
+ }
+}
+
+void LightscreenWindow::upload(const QString &fileName)
+{
+ Uploader::instance()->upload(fileName);
+}
+
+void LightscreenWindow::uploadCancel()
+{
+ if (Uploader::instance()->uploading() <= 0) {
+ return;
+ }
+
+ int confirm = QMessageBox::question(this, tr("Upload cancel"), tr("Do you want to cancel all screenshot uploads?"), tr("Cancel"), tr("Don't Cancel"));
+
+ if (confirm == 0) {
+ Uploader::instance()->cancel();
+ updateUploadStatus();
+ }
+}
+
+void LightscreenWindow::uploadLast()
+{
+ upload(mLastScreenshot);
+ updateUploadStatus();
+}
+
+void LightscreenWindow::uploadProgress(qint64 sent, qint64 total)
+{
+#ifdef Q_WS_WIN
+ if (mTaskbarButton)
+ mTaskbarButton->SetProgresValue(sent, total);
+
+ if (isVisible()) {
+ int uploadCount = Uploader::instance()->uploading();
+ int progress = (sent*100)/total;
+
+ if (uploadCount > 1) {
+ setWindowTitle(tr("%1% of %2 uploads - Lightscreen").arg(progress).arg(uploadCount));
+ }
+ else {
+ setWindowTitle(tr("%1% - Lightscreen").arg(progress));
+ }
+ }
+#endif
+}
+
+void LightscreenWindow::windowHotkey()
+{
+ screenshotAction(1);
+}
+
+void LightscreenWindow::windowPickerHotkey()
+{
+ screenshotAction(3);
+}
+
+//
+
+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.isEmpty())
+ mLastScreenshot = settings()->value("lastScreenshot").toString();
+
+ os::setStartup(settings()->value("options/startup").toBool(), settings()->value("options/startupHide").toBool());
+}
+
+//
+
+
+void LightscreenWindow::connectHotkeys()
+{
+ // Set to true because if the hotkey is disabled it will show an error.
+ bool screen = true, area = true, window = true, windowPicker = 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())
+ windowPicker = 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 (!windowPicker) failed << "window picker";
+ 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 *cancelAction = new QAction(QIcon(":/icons/no"), tr("&Cancel upload"), mTrayIcon);
+ cancelAction->setToolTip(tr("Cancel the currently uploading screenshots"));
+ cancelAction->setEnabled(false);
+ connect(this, SIGNAL(uploading(bool)), cancelAction, SLOT(setEnabled(bool)));
+ connect(cancelAction, SIGNAL(triggered()), this, SLOT(uploadCancel()));
+
+ QAction *historyAction = new QAction(QIcon(":/icons/view-history"), tr("View History"), mTrayIcon);
+ connect(historyAction, SIGNAL(triggered()), this, SLOT(showHistoryDialog()));
+ //
+
+ 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(tr("Screenshot"));
+ screenshotMenu->addAction(screenAction);
+ screenshotMenu->addAction(areaAction);
+ screenshotMenu->addAction(windowAction);
+ screenshotMenu->addAction(windowPickerAction);
+
+ // Duplicated for the screenshot button :(
+ QMenu* imgurMenu = new QMenu(tr("Upload"));
+ imgurMenu->addAction(uploadAction);
+ imgurMenu->addAction(cancelAction);
+ imgurMenu->addAction(historyAction);
+ imgurMenu->addSeparator();
+
+ QMenu* trayIconMenu = new QMenu;
+ trayIconMenu->addAction(hideAction);
+ trayIconMenu->addSeparator();
+ trayIconMenu->addMenu(imgurMenu);
+ trayIconMenu->addSeparator();
+ trayIconMenu->addMenu(screenshotMenu);
+ trayIconMenu->addAction(optionsAction);
+ trayIconMenu->addAction(goAction);
+ trayIconMenu->addSeparator();
+ trayIconMenu->addAction(quitAction);
+
+ mTrayIcon->setContextMenu(trayIconMenu);
+}
+
+#ifdef Q_WS_WIN
+bool LightscreenWindow::winEvent(MSG *message, long *result)
+{
+ Taskbar::GetInstance()->winEvent(message, result);
+ return false;
+}
+#endif
+
+QSettings *LightscreenWindow::settings() const
+{
+ return ScreenshotManager::instance()->settings();
+}
+
+// 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) {
+ 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 QMainWindow::event(event);
+}
diff --git a/tools/globalshortcut/globalshortcutmanager_win.cpp b/tools/globalshortcut/globalshortcutmanager_win.cpp
index 8086e41..401160b 100644
--- a/tools/globalshortcut/globalshortcutmanager_win.cpp
+++ b/tools/globalshortcut/globalshortcutmanager_win.cpp
@@ -1,213 +1,213 @@
/*
* globalshortcutmanager_win.cpp - Windows implementation of global shortcuts
* Copyright (C) 2003-2006 Justin Karneges, Maciej Niedzielski
*
* 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 "globalshortcutmanager.h"
#include "globalshortcuttrigger.h"
#include <QWidget>
#include <windows.h>
class GlobalShortcutManager::KeyTrigger::Impl : public QWidget
{
public:
/**
* Constructor registers the hotkey.
*/
Impl(GlobalShortcutManager::KeyTrigger* t, const QKeySequence& ks)
: trigger_(t)
, id_(0)
, valid(false)
{
UINT mod = 0, key;
if (convertKeySequence(ks, &mod, &key))
- if (valid = RegisterHotKey(winId(), nextId, mod, key))
+ if (valid = RegisterHotKey((HWND)winId(), nextId, mod, key))
id_ = nextId++;
}
/**
* Destructor unregisters the hotkey.
*/
~Impl()
{
if (id_)
- UnregisterHotKey(winId(), id_);
+ UnregisterHotKey((HWND)winId(), id_);
}
/**
* Triggers activated() signal when the hotkey is activated.
*/
bool winEvent(MSG* m, long* result)
{
if (m->message == WM_HOTKEY && m->wParam == id_) {
emit trigger_->activated();
return true;
}
return QWidget::winEvent(m, result);
}
bool isValid() { return valid; }
private:
KeyTrigger* trigger_;
int id_;
static int nextId;
bool valid;
private:
struct Qt_VK_Keymap
{
int key;
UINT vk;
};
static Qt_VK_Keymap qt_vk_table[];
static bool convertKeySequence(const QKeySequence& ks, UINT* mod_, UINT* key_)
{
int code = ks;
UINT mod = 0;
if (code & Qt::META)
mod |= MOD_WIN;
if (code & Qt::SHIFT)
mod |= MOD_SHIFT;
if (code & Qt::CTRL)
mod |= MOD_CONTROL;
if (code & Qt::ALT)
mod |= MOD_ALT;
UINT key = 0;
code &= ~Qt::KeyboardModifierMask;
if (code >= 0x20 && code <= 0x7f)
key = code;
else {
for (int n = 0; qt_vk_table[n].key != Qt::Key_unknown; ++n) {
if (qt_vk_table[n].key == code) {
key = qt_vk_table[n].vk;
break;
}
}
if (!key)
return false;
}
if (mod)
*mod_ = mod;
if (key)
*key_ = key;
return true;
}
};
GlobalShortcutManager::KeyTrigger::Impl::Qt_VK_Keymap
GlobalShortcutManager::KeyTrigger::Impl::qt_vk_table[] = {
{ Qt::Key_Escape, VK_ESCAPE },
{ Qt::Key_Tab, VK_TAB },
{ Qt::Key_Backtab, 0 },
{ Qt::Key_Backspace, VK_BACK },
{ Qt::Key_Return, VK_RETURN },
{ Qt::Key_Enter, VK_RETURN },
{ Qt::Key_Insert, VK_INSERT },
{ Qt::Key_Delete, VK_DELETE },
{ Qt::Key_Pause, VK_PAUSE },
{ Qt::Key_Print, VK_SNAPSHOT }, // Was changed from VK_PRINT
{ Qt::Key_SysReq, 0 },
{ Qt::Key_Clear, VK_CLEAR },
{ Qt::Key_Home, VK_HOME },
{ Qt::Key_End, VK_END },
{ Qt::Key_Left, VK_LEFT },
{ Qt::Key_Up, VK_UP },
{ Qt::Key_Right, VK_RIGHT },
{ Qt::Key_Down, VK_DOWN },
{ Qt::Key_PageUp, VK_PRIOR },
{ Qt::Key_PageDown, VK_NEXT },
{ Qt::Key_Shift, VK_SHIFT },
{ Qt::Key_Control, VK_CONTROL },
{ Qt::Key_Meta, VK_LWIN },
{ Qt::Key_Alt, VK_MENU },
{ Qt::Key_CapsLock, VK_CAPITAL },
{ Qt::Key_NumLock, VK_NUMLOCK },
{ Qt::Key_ScrollLock, VK_SCROLL },
{ Qt::Key_F1, VK_F1 },
{ Qt::Key_F2, VK_F2 },
{ Qt::Key_F3, VK_F3 },
{ Qt::Key_F4, VK_F4 },
{ Qt::Key_F5, VK_F5 },
{ Qt::Key_F6, VK_F6 },
{ Qt::Key_F7, VK_F7 },
{ Qt::Key_F8, VK_F8 },
{ Qt::Key_F9, VK_F9 },
{ Qt::Key_F10, VK_F10 },
{ Qt::Key_F11, VK_F11 },
{ Qt::Key_F12, VK_F12 },
{ Qt::Key_F13, VK_F13 },
{ Qt::Key_F14, VK_F14 },
{ Qt::Key_F15, VK_F15 },
{ Qt::Key_F16, VK_F16 },
{ Qt::Key_F17, VK_F17 },
{ Qt::Key_F18, VK_F18 },
{ Qt::Key_F19, VK_F19 },
{ Qt::Key_F20, VK_F20 },
{ Qt::Key_F21, VK_F21 },
{ Qt::Key_F22, VK_F22 },
{ Qt::Key_F23, VK_F23 },
{ Qt::Key_F24, VK_F24 },
{ Qt::Key_F25, 0 },
{ Qt::Key_F26, 0 },
{ Qt::Key_F27, 0 },
{ Qt::Key_F28, 0 },
{ Qt::Key_F29, 0 },
{ Qt::Key_F30, 0 },
{ Qt::Key_F31, 0 },
{ Qt::Key_F32, 0 },
{ Qt::Key_F33, 0 },
{ Qt::Key_F34, 0 },
{ Qt::Key_F35, 0 },
{ Qt::Key_Super_L, 0 },
{ Qt::Key_Super_R, 0 },
{ Qt::Key_Menu, 0 },
{ Qt::Key_Hyper_L, 0 },
{ Qt::Key_Hyper_R, 0 },
{ Qt::Key_Help, 0 },
{ Qt::Key_Direction_L, 0 },
{ Qt::Key_Direction_R, 0 },
{ Qt::Key_unknown, 0 },
};
int GlobalShortcutManager::KeyTrigger::Impl::nextId = 1;
GlobalShortcutManager::KeyTrigger::KeyTrigger(const QKeySequence& key)
{
d = new Impl(this, key);
}
bool GlobalShortcutManager::KeyTrigger::isValid() const
{
return d->isValid();
}
GlobalShortcutManager::KeyTrigger::~KeyTrigger()
{
delete d;
d = 0;
}
diff --git a/tools/os.h b/tools/os.h
index 20211ae..1236012 100644
--- a/tools/os.h
+++ b/tools/os.h
@@ -1,72 +1,72 @@
-/*
- * 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 OS_H_
-#define OS_H_
-
-#include <QWidget>
-
-struct QPixmap;
-struct QPoint;
-struct QString;
-struct QUrl;
-class QGraphicsEffect;
-
-#if defined(Q_WS_X11)
- typedef unsigned long XID;
- typedef XID Window;
-#endif
-
-namespace os
-{
- // Adds the filename to the Windows recent document list (useful for Windows 7 jump lists)
- void addToRecentDocuments(QString fileName);
-
- // Returns the cursor pixmap in Windows
- QPixmap cursor();
-
- // A QTimeLine based effect for a slot (TODO: look at the new effect classes)
- void effect(QObject* target, const char* slot, int frames, int duration = 400, const char* cleanup = 0);
-
- // Returns the current users's Documents/My Documents folder
- QString getDocumentsPath();
-
- // Returns the pixmap of the given window id.
- QPixmap grabWindow(WId winId);
-
- // Set the target window as the foreground window (Windows only)
- void setForegroundWindow(QWidget *window);
-
- // Adds lightscreen to the startup list in Windows & Linux (KDE, Gnome and Xfce for now).
- void setStartup(bool startup, bool hide);
-
- // Creates a new QGraphicsDropShadowEffect to apply to widgets.
- QGraphicsEffect* shadow(QColor color = Qt::black, int blurRadius = 6, int offset = 1);
-
- // Translates the ui to the given language name.
- void translate(QString language);
-
- // X11-specific functions for the Window Picker
-#if defined(Q_WS_X11)
- Window findRealWindow(Window w, int depth = 0);
- Window windowUnderCursor(bool includeDecorations = true);
-#endif
-}
-
-
-#endif /*OS_H_*/
+/*
+ * 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 OS_H_
+#define OS_H_
+
+#include <QWidget>
+
+class QPixmap;
+class QPoint;
+class QString;
+class QUrl;
+class QGraphicsEffect;
+
+#if defined(Q_WS_X11)
+ typedef unsigned long XID;
+ typedef XID Window;
+#endif
+
+namespace os
+{
+ // Adds the filename to the Windows recent document list (useful for Windows 7 jump lists)
+ void addToRecentDocuments(QString fileName);
+
+ // Returns the cursor pixmap in Windows
+ QPixmap cursor();
+
+ // A QTimeLine based effect for a slot (TODO: look at the new effect classes)
+ void effect(QObject* target, const char* slot, int frames, int duration = 400, const char* cleanup = 0);
+
+ // Returns the current users's Documents/My Documents folder
+ QString getDocumentsPath();
+
+ // Returns the pixmap of the given window id.
+ QPixmap grabWindow(WId winId);
+
+ // Set the target window as the foreground window (Windows only)
+ void setForegroundWindow(QWidget *window);
+
+ // Adds lightscreen to the startup list in Windows & Linux (KDE, Gnome and Xfce for now).
+ void setStartup(bool startup, bool hide);
+
+ // Creates a new QGraphicsDropShadowEffect to apply to widgets.
+ QGraphicsEffect* shadow(QColor color = Qt::black, int blurRadius = 6, int offset = 1);
+
+ // Translates the ui to the given language name.
+ void translate(QString language);
+
+ // X11-specific functions for the Window Picker
+#if defined(Q_WS_X11)
+ Window findRealWindow(Window w, int depth = 0);
+ Window windowUnderCursor(bool includeDecorations = true);
+#endif
+}
+
+
+#endif /*OS_H_*/
diff --git a/tools/qtsingleapplication/qtlocalpeer.cpp b/tools/qtsingleapplication/qtlocalpeer.cpp
index 382d182..ddd2c74 100644
--- a/tools/qtsingleapplication/qtlocalpeer.cpp
+++ b/tools/qtsingleapplication/qtlocalpeer.cpp
@@ -1,199 +1,199 @@
/****************************************************************************
**
** 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 "qtlocalpeer.h"
-#include <QtCore/QCoreApplication>
-#include <QtCore/QTime>
+#include <QCoreApplication>
+#include <QTime>
#if defined(Q_OS_WIN)
-#include <QtCore/QLibrary>
-#include <QtCore/qt_windows.h>
+#include <QLibrary>
+#include <qt_windows.h>
typedef BOOL(WINAPI*PProcessIdToSessionId)(DWORD,DWORD*);
static PProcessIdToSessionId pProcessIdToSessionId = 0;
#endif
#if defined(Q_OS_UNIX)
#include <time.h>
#endif
namespace QtLP_Private {
#include "qtlockedfile.cpp"
#if defined(Q_OS_WIN)
#include "qtlockedfile_win.cpp"
#else
#include "qtlockedfile_unix.cpp"
#endif
}
const char* QtLocalPeer::ack = "ack";
QtLocalPeer::QtLocalPeer(QObject* parent, const QString &appId)
: QObject(parent), id(appId)
{
QString prefix = id;
if (id.isEmpty()) {
id = QCoreApplication::applicationFilePath();
#if defined(Q_OS_WIN)
id = id.toLower();
#endif
prefix = id.section(QLatin1Char('/'), -1);
}
prefix.remove(QRegExp("[^a-zA-Z]"));
prefix.truncate(6);
QByteArray idc = id.toUtf8();
quint16 idNum = qChecksum(idc.constData(), idc.size());
socketName = QLatin1String("qtsingleapp-") + prefix
+ QLatin1Char('-') + QString::number(idNum, 16);
#if defined(Q_OS_WIN)
if (!pProcessIdToSessionId) {
QLibrary lib("kernel32");
pProcessIdToSessionId = (PProcessIdToSessionId)lib.resolve("ProcessIdToSessionId");
}
if (pProcessIdToSessionId) {
DWORD sessionId = 0;
pProcessIdToSessionId(GetCurrentProcessId(), &sessionId);
socketName += QLatin1Char('-') + QString::number(sessionId, 16);
}
#else
socketName += QLatin1Char('-') + QString::number(::getuid(), 16);
#endif
server = new QLocalServer(this);
QString lockName = QDir(QDir::tempPath()).absolutePath()
+ QLatin1Char('/') + socketName
+ QLatin1String("-lockfile");
lockFile.setFileName(lockName);
lockFile.open(QIODevice::ReadWrite);
}
bool QtLocalPeer::isClient()
{
if (lockFile.isLocked())
return false;
if (!lockFile.lock(QtLP_Private::QtLockedFile::WriteLock, false))
return true;
bool res = server->listen(socketName);
#if defined(Q_OS_UNIX) && (QT_VERSION >= QT_VERSION_CHECK(4,5,0))
// ### Workaround
if (!res && server->serverError() == QAbstractSocket::AddressInUseError) {
QFile::remove(QDir::cleanPath(QDir::tempPath())+QLatin1Char('/')+socketName);
res = server->listen(socketName);
}
#endif
if (!res)
qWarning("QtSingleCoreApplication: listen on local socket failed, %s", qPrintable(server->errorString()));
QObject::connect(server, SIGNAL(newConnection()), SLOT(receiveConnection()));
return false;
}
bool QtLocalPeer::sendMessage(const QString &message, int timeout)
{
if (!isClient())
return false;
QLocalSocket socket;
bool connOk = false;
for(int i = 0; i < 2; i++) {
// Try twice, in case the other instance is just starting up
socket.connectToServer(socketName);
connOk = socket.waitForConnected(timeout/2);
if (connOk || i)
break;
int ms = 250;
#if defined(Q_OS_WIN)
Sleep(DWORD(ms));
#else
struct timespec ts = { ms / 1000, (ms % 1000) * 1000 * 1000 };
nanosleep(&ts, NULL);
#endif
}
if (!connOk)
return false;
QByteArray uMsg(message.toUtf8());
QDataStream ds(&socket);
ds.writeBytes(uMsg.constData(), uMsg.size());
bool res = socket.waitForBytesWritten(timeout);
if (res) {
res &= socket.waitForReadyRead(timeout); // wait for ack
if (res)
res &= (socket.read(qstrlen(ack)) == ack);
}
return res;
}
void QtLocalPeer::receiveConnection()
{
QLocalSocket* socket = server->nextPendingConnection();
if (!socket)
return;
while (socket->bytesAvailable() < (int)sizeof(quint32))
socket->waitForReadyRead();
QDataStream ds(socket);
QByteArray uMsg;
quint32 remaining;
ds >> remaining;
uMsg.resize(remaining);
int got = 0;
char* uMsgBuf = uMsg.data();
do {
got = ds.readRawData(uMsgBuf, remaining);
remaining -= got;
uMsgBuf += got;
} while (remaining && got >= 0 && socket->waitForReadyRead(2000));
if (got < 0) {
qWarning("QtLocalPeer: Message reception failed %s", socket->errorString().toLatin1().constData());
delete socket;
return;
}
QString message(QString::fromUtf8(uMsg));
socket->write(ack, qstrlen(ack));
socket->waitForBytesWritten(1000);
delete socket;
emit messageReceived(message); //### (might take a long time to return)
}
diff --git a/tools/qtsingleapplication/qtlocalpeer.h b/tools/qtsingleapplication/qtlocalpeer.h
index 869af2a..7b3fa81 100644
--- a/tools/qtsingleapplication/qtlocalpeer.h
+++ b/tools/qtsingleapplication/qtlocalpeer.h
@@ -1,72 +1,76 @@
/****************************************************************************
**
** 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."
**
****************************************************************************/
+#ifndef QTLOCALPEER_H
+#define QTLOCALPEER_H
-#include <QtNetwork/QLocalServer>
-#include <QtNetwork/QLocalSocket>
-#include <QtCore/QDir>
+#include <QLocalServer>
+#include <QLocalSocket>
+#include <QDir>
#include "qtlockedfile.h"
class QtLocalPeer : public QObject
{
Q_OBJECT
public:
QtLocalPeer(QObject *parent = 0, const QString &appId = QString());
bool isClient();
bool sendMessage(const QString &message, int timeout);
QString applicationId() const
{ return id; }
Q_SIGNALS:
void messageReceived(const QString &message);
protected Q_SLOTS:
void receiveConnection();
protected:
QString id;
QString socketName;
QLocalServer* server;
QtLP_Private::QtLockedFile lockFile;
private:
static const char* ack;
};
+
+#endif // QTLOCALPEER_H
diff --git a/tools/qtsingleapplication/qtlockedfile.h b/tools/qtsingleapplication/qtlockedfile.h
index 07a42bf..3e41b79 100644
--- a/tools/qtsingleapplication/qtlockedfile.h
+++ b/tools/qtsingleapplication/qtlockedfile.h
@@ -1,96 +1,96 @@
/****************************************************************************
**
** 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."
**
****************************************************************************/
#ifndef QTLOCKEDFILE_H
#define QTLOCKEDFILE_H
#include <QtCore/QFile>
#ifdef Q_OS_WIN
#include <QtCore/QVector>
#endif
-#if defined(Q_WS_WIN)
+#if defined(Q_WS_WIN) || defined(Q_OS_WIN)
# if !defined(QT_QTLOCKEDFILE_EXPORT) && !defined(QT_QTLOCKEDFILE_IMPORT)
# define QT_QTLOCKEDFILE_EXPORT
# elif defined(QT_QTLOCKEDFILE_IMPORT)
# if defined(QT_QTLOCKEDFILE_EXPORT)
# undef QT_QTLOCKEDFILE_EXPORT
# endif
# define QT_QTLOCKEDFILE_EXPORT __declspec(dllimport)
# elif defined(QT_QTLOCKEDFILE_EXPORT)
# undef QT_QTLOCKEDFILE_EXPORT
# define QT_QTLOCKEDFILE_EXPORT __declspec(dllexport)
# endif
#else
# define QT_QTLOCKEDFILE_EXPORT
#endif
namespace QtLP_Private {
class QT_QTLOCKEDFILE_EXPORT QtLockedFile : public QFile
{
public:
enum LockMode { NoLock = 0, ReadLock, WriteLock };
QtLockedFile();
QtLockedFile(const QString &name);
~QtLockedFile();
bool open(OpenMode mode);
bool lock(LockMode mode, bool block = true);
bool unlock();
bool isLocked() const;
LockMode lockMode() const;
private:
#ifdef Q_OS_WIN
Qt::HANDLE wmutex;
Qt::HANDLE rmutex;
QVector<Qt::HANDLE> rmutexes;
QString mutexname;
Qt::HANDLE getMutexHandle(int idx, bool doCreate);
bool waitMutex(Qt::HANDLE mutex, bool doBlock);
#endif
LockMode m_lock_mode;
};
}
#endif
diff --git a/tools/qtsingleapplication/qtlockedfile_win.cpp b/tools/qtsingleapplication/qtlockedfile_win.cpp
index 4cd2003..ed2995f 100644
--- a/tools/qtsingleapplication/qtlockedfile_win.cpp
+++ b/tools/qtsingleapplication/qtlockedfile_win.cpp
@@ -1,206 +1,214 @@
/****************************************************************************
**
** 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 "qtlockedfile.h"
#include <qt_windows.h>
-#include <QtCore/QFileInfo>
+#include <QFileInfo>
#define MUTEX_PREFIX "QtLockedFile mutex "
// Maximum number of concurrent read locks. Must not be greater than MAXIMUM_WAIT_OBJECTS
#define MAX_READERS MAXIMUM_WAIT_OBJECTS
Qt::HANDLE QtLockedFile::getMutexHandle(int idx, bool doCreate)
{
if (mutexname.isEmpty()) {
QFileInfo fi(*this);
mutexname = QString::fromLatin1(MUTEX_PREFIX)
+ fi.absoluteFilePath().toLower();
}
QString mname(mutexname);
if (idx >= 0)
mname += QString::number(idx);
Qt::HANDLE mutex;
if (doCreate) {
+#if (QT_VERSION < 0x050000)
QT_WA( { mutex = CreateMutexW(NULL, FALSE, (TCHAR*)mname.utf16()); },
{ mutex = CreateMutexA(NULL, FALSE, mname.toLocal8Bit().constData()); } );
+#else
+ mutex = CreateMutexW(NULL, FALSE, (TCHAR*)mname.utf16());
+#endif
if (!mutex) {
qErrnoWarning("QtLockedFile::lock(): CreateMutex failed");
return 0;
}
}
else {
+#if (QT_VERSION < 0x050000)
QT_WA( { mutex = OpenMutexW(SYNCHRONIZE | MUTEX_MODIFY_STATE, FALSE, (TCHAR*)mname.utf16()); },
{ mutex = OpenMutexA(SYNCHRONIZE | MUTEX_MODIFY_STATE, FALSE, mname.toLocal8Bit().constData()); } );
+#else
+ mutex = OpenMutexW(SYNCHRONIZE | MUTEX_MODIFY_STATE, FALSE, (TCHAR*)mname.utf16());
+#endif
if (!mutex) {
if (GetLastError() != ERROR_FILE_NOT_FOUND)
qErrnoWarning("QtLockedFile::lock(): OpenMutex failed");
return 0;
}
}
return mutex;
}
bool QtLockedFile::waitMutex(Qt::HANDLE mutex, bool doBlock)
{
Q_ASSERT(mutex);
DWORD res = WaitForSingleObject(mutex, doBlock ? INFINITE : 0);
switch (res) {
case WAIT_OBJECT_0:
case WAIT_ABANDONED:
return true;
break;
case WAIT_TIMEOUT:
break;
default:
qErrnoWarning("QtLockedFile::lock(): WaitForSingleObject failed");
}
return false;
}
bool QtLockedFile::lock(LockMode mode, bool block)
{
if (!isOpen()) {
qWarning("QtLockedFile::lock(): file is not opened");
return false;
}
if (mode == NoLock)
return unlock();
if (mode == m_lock_mode)
return true;
if (m_lock_mode != NoLock)
unlock();
if (!wmutex && !(wmutex = getMutexHandle(-1, true)))
return false;
if (!waitMutex(wmutex, block))
return false;
if (mode == ReadLock) {
int idx = 0;
for (; idx < MAX_READERS; idx++) {
rmutex = getMutexHandle(idx, false);
if (!rmutex || waitMutex(rmutex, false))
break;
CloseHandle(rmutex);
}
bool ok = true;
if (idx >= MAX_READERS) {
qWarning("QtLockedFile::lock(): too many readers");
rmutex = 0;
ok = false;
}
else if (!rmutex) {
rmutex = getMutexHandle(idx, true);
if (!rmutex || !waitMutex(rmutex, false))
ok = false;
}
if (!ok && rmutex) {
CloseHandle(rmutex);
rmutex = 0;
}
ReleaseMutex(wmutex);
if (!ok)
return false;
}
else {
Q_ASSERT(rmutexes.isEmpty());
for (int i = 0; i < MAX_READERS; i++) {
Qt::HANDLE mutex = getMutexHandle(i, false);
if (mutex)
rmutexes.append(mutex);
}
if (rmutexes.size()) {
DWORD res = WaitForMultipleObjects(rmutexes.size(), rmutexes.constData(),
TRUE, block ? INFINITE : 0);
if (res != WAIT_OBJECT_0 && res != WAIT_ABANDONED) {
if (res != WAIT_TIMEOUT)
qErrnoWarning("QtLockedFile::lock(): WaitForMultipleObjects failed");
m_lock_mode = WriteLock; // trick unlock() to clean up - semiyucky
unlock();
return false;
}
}
}
m_lock_mode = mode;
return true;
}
bool QtLockedFile::unlock()
{
if (!isOpen()) {
qWarning("QtLockedFile::unlock(): file is not opened");
return false;
}
if (!isLocked())
return true;
if (m_lock_mode == ReadLock) {
ReleaseMutex(rmutex);
CloseHandle(rmutex);
rmutex = 0;
}
else {
foreach(Qt::HANDLE mutex, rmutexes) {
ReleaseMutex(mutex);
CloseHandle(mutex);
}
rmutexes.clear();
ReleaseMutex(wmutex);
}
m_lock_mode = QtLockedFile::NoLock;
return true;
}
QtLockedFile::~QtLockedFile()
{
if (isOpen())
unlock();
if (wmutex)
CloseHandle(wmutex);
}
diff --git a/tools/qtsingleapplication/qtsingleapplication.cpp b/tools/qtsingleapplication/qtsingleapplication.cpp
index 5a8f1b0..b9a4db7 100644
--- a/tools/qtsingleapplication/qtsingleapplication.cpp
+++ b/tools/qtsingleapplication/qtsingleapplication.cpp
@@ -1,344 +1,343 @@
/****************************************************************************
**
** 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 "qtsingleapplication.h"
#include "qtlocalpeer.h"
-#include <QtGui/QWidget>
-
+#include <QWidget>
/*!
\class QtSingleApplication qtsingleapplication.h
\brief The QtSingleApplication class provides an API to detect and
communicate with running instances of an application.
This class allows you to create applications where only one
instance should be running at a time. I.e., if the user tries to
launch another instance, the already running instance will be
activated instead. Another usecase is a client-server system,
where the first started instance will assume the role of server,
and the later instances will act as clients of that server.
By default, the full path of the executable file is used to
determine whether two processes are instances of the same
application. You can also provide an explicit identifier string
that will be compared instead.
The application should create the QtSingleApplication object early
in the startup phase, and call isRunning() to find out if another
instance of this application is already running. If isRunning()
returns false, it means that no other instance is running, and
this instance has assumed the role as the running instance. In
this case, the application should continue with the initialization
of the application user interface before entering the event loop
with exec(), as normal.
The messageReceived() signal will be emitted when the running
application receives messages from another instance of the same
application. When a message is received it might be helpful to the
user to raise the application so that it becomes visible. To
facilitate this, QtSingleApplication provides the
setActivationWindow() function and the activateWindow() slot.
If isRunning() returns true, another instance is already
running. It may be alerted to the fact that another instance has
started by using the sendMessage() function. Also data such as
startup parameters (e.g. the name of the file the user wanted this
new instance to open) can be passed to the running instance with
this function. Then, the application should terminate (or enter
client mode).
If isRunning() returns true, but sendMessage() fails, that is an
indication that the running instance is frozen.
Here's an example that shows how to convert an existing
application to use QtSingleApplication. It is very simple and does
not make use of all QtSingleApplication's functionality (see the
examples for that).
\code
// Original
int main(int argc, char **argv)
{
QApplication app(argc, argv);
MyMainWidget mmw;
mmw.show();
return app.exec();
}
// Single instance
int main(int argc, char **argv)
{
QtSingleApplication app(argc, argv);
if (app.isRunning())
return !app.sendMessage(someDataString);
MyMainWidget mmw;
app.setActivationWindow(&mmw);
mmw.show();
return app.exec();
}
\endcode
Once this QtSingleApplication instance is destroyed (normally when
the process exits or crashes), when the user next attempts to run the
application this instance will not, of course, be encountered. The
next instance to call isRunning() or sendMessage() will assume the
role as the new running instance.
For console (non-GUI) applications, QtSingleCoreApplication may be
used instead of this class, to avoid the dependency on the QtGui
library.
\sa QtSingleCoreApplication
*/
void QtSingleApplication::sysInit(const QString &appId)
{
actWin = 0;
peer = new QtLocalPeer(this, appId);
connect(peer, SIGNAL(messageReceived(const QString&)), SIGNAL(messageReceived(const QString&)));
}
/*!
Creates a QtSingleApplication object. The application identifier
will be QCoreApplication::applicationFilePath(). \a argc, \a
argv, and \a GUIenabled are passed on to the QAppliation constructor.
If you are creating a console application (i.e. setting \a
GUIenabled to false), you may consider using
QtSingleCoreApplication instead.
*/
QtSingleApplication::QtSingleApplication(int &argc, char **argv, bool GUIenabled)
: QApplication(argc, argv, GUIenabled)
{
sysInit();
}
/*!
Creates a QtSingleApplication object with the application
identifier \a appId. \a argc and \a argv are passed on to the
QAppliation constructor.
*/
QtSingleApplication::QtSingleApplication(const QString &appId, int &argc, char **argv)
: QApplication(argc, argv)
{
sysInit(appId);
}
/*!
Creates a QtSingleApplication object. The application identifier
will be QCoreApplication::applicationFilePath(). \a argc, \a
argv, and \a type are passed on to the QAppliation constructor.
*/
QtSingleApplication::QtSingleApplication(int &argc, char **argv, Type type)
: QApplication(argc, argv, type)
{
sysInit();
}
#if defined(Q_WS_X11)
/*!
Special constructor for X11, ref. the documentation of
QApplication's corresponding constructor. The application identifier
will be QCoreApplication::applicationFilePath(). \a dpy, \a visual,
and \a cmap are passed on to the QApplication constructor.
*/
QtSingleApplication::QtSingleApplication(Display* dpy, Qt::HANDLE visual, Qt::HANDLE cmap)
: QApplication(dpy, visual, cmap)
{
sysInit();
}
/*!
Special constructor for X11, ref. the documentation of
QApplication's corresponding constructor. The application identifier
will be QCoreApplication::applicationFilePath(). \a dpy, \a argc, \a
argv, \a visual, and \a cmap are passed on to the QApplication
constructor.
*/
QtSingleApplication::QtSingleApplication(Display *dpy, int &argc, char **argv, Qt::HANDLE visual, Qt::HANDLE cmap)
: QApplication(dpy, argc, argv, visual, cmap)
{
sysInit();
}
/*!
Special constructor for X11, ref. the documentation of
QApplication's corresponding constructor. The application identifier
will be \a appId. \a dpy, \a argc, \a
argv, \a visual, and \a cmap are passed on to the QApplication
constructor.
*/
QtSingleApplication::QtSingleApplication(Display* dpy, const QString &appId, int argc, char **argv, Qt::HANDLE visual, Qt::HANDLE cmap)
: QApplication(dpy, argc, argv, visual, cmap)
{
sysInit(appId);
}
#endif
/*!
Returns true if another instance of this application is running;
otherwise false.
This function does not find instances of this application that are
being run by a different user (on Windows: that are running in
another session).
\sa sendMessage()
*/
bool QtSingleApplication::isRunning()
{
return peer->isClient();
}
/*!
Tries to send the text \a message to the currently running
instance. The QtSingleApplication object in the running instance
will emit the messageReceived() signal when it receives the
message.
This function returns true if the message has been sent to, and
processed by, the current instance. If there is no instance
currently running, or if the running instance fails to process the
message within \a timeout milliseconds, this function return false.
\sa isRunning(), messageReceived()
*/
bool QtSingleApplication::sendMessage(const QString &message, int timeout)
{
return peer->sendMessage(message, timeout);
}
/*!
Returns the application identifier. Two processes with the same
identifier will be regarded as instances of the same application.
*/
QString QtSingleApplication::id() const
{
return peer->applicationId();
}
/*!
Sets the activation window of this application to \a aw. The
activation window is the widget that will be activated by
activateWindow(). This is typically the application's main window.
If \a activateOnMessage is true (the default), the window will be
activated automatically every time a message is received, just prior
to the messageReceived() signal being emitted.
\sa activateWindow(), messageReceived()
*/
void QtSingleApplication::setActivationWindow(QWidget* aw, bool activateOnMessage)
{
actWin = aw;
if (activateOnMessage)
connect(peer, SIGNAL(messageReceived(const QString&)), this, SLOT(activateWindow()));
else
disconnect(peer, SIGNAL(messageReceived(const QString&)), this, SLOT(activateWindow()));
}
/*!
Returns the applications activation window if one has been set by
calling setActivationWindow(), otherwise returns 0.
\sa setActivationWindow()
*/
QWidget* QtSingleApplication::activationWindow() const
{
return actWin;
}
/*!
De-minimizes, raises, and activates this application's activation window.
This function does nothing if no activation window has been set.
This is a convenience function to show the user that this
application instance has been activated when he has tried to start
another instance.
This function should typically be called in response to the
messageReceived() signal. By default, that will happen
automatically, if an activation window has been set.
\sa setActivationWindow(), messageReceived(), initialize()
*/
void QtSingleApplication::activateWindow()
{
if (actWin) {
actWin->setWindowState(actWin->windowState() & ~Qt::WindowMinimized);
actWin->raise();
actWin->activateWindow();
}
}
/*!
\fn void QtSingleApplication::messageReceived(const QString& message)
This signal is emitted when the current instance receives a \a
message from another instance of this application.
\sa sendMessage(), setActivationWindow(), activateWindow()
*/
/*!
\fn void QtSingleApplication::initialize(bool dummy = true)
\obsolete
*/
diff --git a/tools/qtsingleapplication/qtsingleapplication.h b/tools/qtsingleapplication/qtsingleapplication.h
index 8297aab..60668ad 100644
--- a/tools/qtsingleapplication/qtsingleapplication.h
+++ b/tools/qtsingleapplication/qtsingleapplication.h
@@ -1,98 +1,102 @@
/****************************************************************************
**
** 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."
**
****************************************************************************/
+#ifndef QTSINGLEAPPLICATION_H
+#define QTSINGLEAPPLICATION_H
-#include <QtGui/QApplication>
+#include <QApplication>
class QtLocalPeer;
-#ifdef Q_WS_WIN
+#if defined(Q_WS_WIN) || defined(Q_OS_WIN32)
# 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;
};
+
+#endif // QTSINGLEAPPLICATION_H
diff --git a/tools/qtsingleapplication/qtsingleapplication.pri b/tools/qtsingleapplication/qtsingleapplication.pri
index 02de47e..2a71d43 100644
--- a/tools/qtsingleapplication/qtsingleapplication.pri
+++ b/tools/qtsingleapplication/qtsingleapplication.pri
@@ -1,15 +1,19 @@
INCLUDEPATH += $$PWD
DEPENDPATH += $$PWD
QT *= network
+contains(QT_VERSION, ^5.*) {
+ QT *= widgets
+}
+
qtsingleapplication-uselib:!qtsingleapplication-buildlib {
LIBS += -L$$QTSINGLEAPPLICATION_LIBDIR -l$$QTSINGLEAPPLICATION_LIBNAME
} else {
SOURCES += $$PWD/qtsingleapplication.cpp $$PWD/qtlocalpeer.cpp
HEADERS += $$PWD/qtsingleapplication.h $$PWD/qtlocalpeer.h
}
win32 {
contains(TEMPLATE, lib):contains(CONFIG, shared):DEFINES += QT_QTSINGLEAPPLICATION_EXPORT
else:qtsingleapplication-uselib:DEFINES += QT_QTSINGLEAPPLICATION_IMPORT
}
diff --git a/tools/qtsingleapplication/qtsinglecoreapplication.h b/tools/qtsingleapplication/qtsinglecoreapplication.h
index ef529a8..549d49f 100644
--- a/tools/qtsingleapplication/qtsinglecoreapplication.h
+++ b/tools/qtsingleapplication/qtsinglecoreapplication.h
@@ -1,66 +1,70 @@
/****************************************************************************
**
** 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."
**
****************************************************************************/
+#ifndef QTSINGLECOREAPPLICATION_H
+#define QTSINGLECOREAPPLICATION_H
-#include <QtCore/QCoreApplication>
+#include <QCoreApplication>
class QtLocalPeer;
class QtSingleCoreApplication : public QCoreApplication
{
Q_OBJECT
public:
QtSingleCoreApplication(int &argc, char **argv);
QtSingleCoreApplication(const QString &id, int &argc, char **argv);
bool isRunning();
QString id() const;
public Q_SLOTS:
bool sendMessage(const QString &message, int timeout = 5000);
Q_SIGNALS:
void messageReceived(const QString &message);
private:
QtLocalPeer* peer;
};
+
+#endif // QTSINGLECOREAPPLICATION_H
diff --git a/tools/qwin7utils/JumpList.cpp b/tools/qwin7utils/JumpList.cpp
index 87bca05..4c8bf69 100644
--- a/tools/qwin7utils/JumpList.cpp
+++ b/tools/qwin7utils/JumpList.cpp
@@ -1,381 +1,380 @@
-/***************************************************************************
- * Copyright (C) 2011 by Nicolae Ghimbovschi *
- * nicolae.ghimbovschi@gmail.com *
- * *
- * 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; version 3 of the License. *
- * *
- * 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 program; if not, write to the *
- * Free Software Foundation, Inc., *
- * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
- ***************************************************************************/
-
-#include "JumpList.h"
-
-#ifdef Q_OS_WIN32
-
-#include "win7_include.h"
-#include "JLPrivateData.h"
-
-namespace QW7 {
-
-
- namespace LOCAL_UTILS {
-
- IShellItem* JLItem2ShellItem(const JumpListItem& item) {
- HMODULE shell;
- IShellItem *shell_item = NULL;
- t_SHCreateItemFromParsingName SHCreateItemFromParsingName = NULL;
-
- shell = LoadLibrary(L"shell32.dll");
-
- if (shell) {
- SHCreateItemFromParsingName = reinterpret_cast<t_SHCreateItemFromParsingName>
- (GetProcAddress (shell, "SHCreateItemFromParsingName"));
-
- if (SHCreateItemFromParsingName != NULL) {
- SHCreateItemFromParsingName(item.m_path.toStdWString().c_str(), NULL, IID_IShellItem,
- reinterpret_cast<void**> (&(shell_item)));
- }
-
- FreeLibrary (shell);
- }
-
- return shell_item;
- }
-
- IShellLink* JLItem2ShellLink(const JumpListItem& item) {
- IShellLink* shell_link = NULL;
- IPropertyStore* prop_store = NULL;
- bool is_not_separator = (item.m_path.length() > 0);
-
- HRESULT hr = CoCreateInstance(CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER, IID_IShellLink,
- reinterpret_cast<void**> (&(shell_link)));
-
- if(SUCCEEDED(hr)) {
-
- if (is_not_separator) {
- shell_link->SetPath(item.m_path.toStdWString().c_str());
- shell_link->SetArguments(item.m_arguments.toStdWString().c_str());
- shell_link->SetIconLocation(item.m_icon_path.toStdWString().c_str(), item.m_icon_index);
- shell_link->SetDescription(item.m_description.toStdWString().c_str());
- }
-
- hr = shell_link->QueryInterface(IID_IPropertyStore, reinterpret_cast<void**> (&(prop_store)));
-
- if (SUCCEEDED(hr)) {
- PROPVARIANT pv;
-
- if (is_not_separator) {
- hr = InitPropVariantFromString(item.m_title.toStdWString().c_str(), &pv);
-
- if (SUCCEEDED(hr)) {
- hr = prop_store->SetValue(PKEY_Title, pv);
- }
- } else {
- hr = InitPropVariantFromBoolean(TRUE, &pv);
-
- if (SUCCEEDED(hr)) {
- hr = prop_store->SetValue(PKEY_AppUserModel_IsDestListSeparator, pv);
- }
- }
-
- //Save the changes we made to the property store
- prop_store->Commit();
- prop_store->Release();
-
- PropVariantClear(&pv);
- }
- }
-
- return shell_link;
- }
-
- long List2ObjectCollection(const QList<JumpListItem>& items, IObjectCollection* obj_collection) {
- HRESULT hr = 0;
-
- if (obj_collection == NULL) {
- return -1;
- }
-
- for (int index = 0; index < items.size(); ++index) {
- JumpListItem item = items.at(index);
-
- if (item.m_type == JL_ITEM) {
- IShellItem* s_item = JLItem2ShellItem(item);
-
- if (s_item) {
- hr = obj_collection->AddObject(s_item);
- }
- } else if (item.m_type != JL_OTHER){
- IShellLink* s_link = JLItem2ShellLink(item);
-
- if (s_link) {
- hr = obj_collection->AddObject(s_link);
- }
- }
- }
-
- return hr;
- }
-
- void ObjectArray2List(IObjectArray *object_array, QList<JumpListItem>& items) {
- bool fRet = false;
- UINT cItems;
-
- if (SUCCEEDED(object_array->GetCount(&cItems)))
- {
- IShellItem *shell_item;
- IShellLink *shell_link;
- wchar_t buffer[MAX_PATH];
-
- for (UINT i = 0; !fRet && i < cItems; i++)
- {
- JumpListItem item;
-
- if (SUCCEEDED(object_array->GetAt(i, IID_IShellItem, reinterpret_cast<void**> (&(shell_item)))))
- {
- LPWSTR file_path = NULL;
- HRESULT hr = shell_item->GetDisplayName(SIGDN_FILESYSPATH, &file_path);
-
- if (SUCCEEDED(hr))
- {
- item.m_type = JL_ITEM;
- item.m_path = QString::fromStdWString(file_path);
- items.append(item);
- CoTaskMemFree(file_path);
- }
-
- shell_item->Release();
- } else if (SUCCEEDED(object_array->GetAt(i, IID_IShellLink, reinterpret_cast<void**> (&(shell_link))))) {
- int index = 0;
-
- item.m_type = JL_LINK;
- shell_link->GetDescription(buffer, MAX_PATH);
- item.m_description.fromStdWString(buffer);
-
- shell_link->GetArguments(buffer, MAX_PATH);
- item.m_arguments.fromStdWString(buffer);
-
- shell_link->GetIconLocation(buffer, MAX_PATH, &index);
- item.m_icon_path.fromStdWString(buffer);
- item.m_icon_index = index;
-
- shell_link->GetPath(buffer, MAX_PATH, NULL, SLGP_UNCPRIORITY);
- item.m_path.fromStdWString(buffer);
-
- shell_link->GetWorkingDirectory(buffer, MAX_PATH);
- item.m_working_path.fromStdWString(buffer);
-
- items.append(item);
-
- shell_link->Release();
- }
- }
- }
- }
- }
-
-
- JumpList::JumpList(QString app_id) {
- m_app_id = app_id;
- m_private = new JLPrivateData(app_id);
- }
-
- long JumpList::SetAppID(QString app_id) {
- if (m_private->m_list_is_initialized) {
- return -1;
- }
-
- m_app_id = app_id;
-
- return m_private->ListHandler()->SetAppID(app_id.toStdWString().c_str());
- }
-
- //ICustomDestinationList
- long JumpList::Begin() {
- if (!m_private->m_list_is_initialized) {
- m_private->InitList();
- }
-
- return m_private->m_list_is_initialized ? 0 : -1;
- }
-
- long JumpList::AddRecentCategory() {
- if (!m_private->m_list_is_initialized) {
- return -1;
- }
-
- return m_private->ListHandler()->AppendKnownCategory(KDC_RECENT);
- }
-
- long JumpList::AddFrequentCategory() {
- if (!m_private->m_list_is_initialized) {
- return -1;
- }
-
- return m_private->ListHandler()->AppendKnownCategory(KDC_FREQUENT);
- }
-
- long JumpList::AddCategory(QString title, const QList<JumpListItem>& items) {
- if (!m_private->m_list_is_initialized) {
- return -1;
- }
-
- IObjectCollection* obj_collection;
-
- HRESULT hr = CoCreateInstance(CLSID_EnumerableObjectCollection, NULL,
- CLSCTX_INPROC, IID_IObjectCollection, reinterpret_cast<void**> (&(obj_collection)));
-
- if (SUCCEEDED(hr)) {
- IObjectArray* object_array;
-
- LOCAL_UTILS::List2ObjectCollection(items, obj_collection);
- hr = obj_collection->QueryInterface(IID_IObjectArray,reinterpret_cast<void**> (&(object_array)));
-
- if (SUCCEEDED(hr)) {
- hr = m_private->ListHandler()->AppendCategory(title.toStdWString().c_str(), object_array);
- object_array->Release();
- }
-
- obj_collection->Release();
- }
-
- return hr;
- }
-
- long JumpList::AddUserTasks(const QList<JumpListItem>& items) {
- if (!m_private->m_list_is_initialized) {
- return -1;
- }
-
- IObjectCollection* obj_collection;
-
- HRESULT hr = CoCreateInstance(CLSID_EnumerableObjectCollection, NULL,
- CLSCTX_INPROC, IID_IObjectCollection, reinterpret_cast<void**> (&(obj_collection)));
-
- if (SUCCEEDED(hr)) {
- LOCAL_UTILS::List2ObjectCollection(items, obj_collection);
- hr = m_private->ListHandler()->AddUserTasks(obj_collection);
-
- obj_collection->Release();
- }
-
- return hr;
- }
-
- long JumpList::GetRemovedDestinations(QList<JumpListItem>& items) {
- IObjectArray* object_array = NULL;
-
- HRESULT hr = m_private->ListHandler()->GetRemovedDestinations(IID_IObjectArray,
- reinterpret_cast<void**> (&(object_array)));
-
- if (SUCCEEDED(hr)) {
- LOCAL_UTILS::ObjectArray2List(object_array, items);
- object_array->Release();
- }
-
- return hr;
- }
-
- long JumpList::Clear() {
- return m_private->ListHandler()->DeleteList(m_app_id.isEmpty() ? NULL : m_app_id.toStdWString().c_str());
- }
-
- long JumpList::Commit() {
- if (!m_private->m_list_is_initialized) {
- return -1;
- }
-
- HRESULT hr = m_private->ListHandler()->CommitList();
- m_private->ReleaseList();
-
- return hr;
- }
-
- long JumpList::Abort() {
- if (!m_private->m_list_is_initialized) {
- return -1;
- }
-
- HRESULT hr = m_private->ListHandler()->AbortList();
- m_private->ReleaseList();
-
- return hr;
- }
-
- //IApplicationDocumentLists
- long JumpList::GetKnownList(KnownListType type, QList<JumpListItem>& items) {
- IObjectArray* object_array = NULL;
- IApplicationDocumentLists* app_documents = NULL;
-
- HRESULT hr = CoCreateInstance(CLSID_ApplicationDocumentLists, NULL, CLSCTX_INPROC_SERVER, IID_IApplicationDocumentLists,
- reinterpret_cast<void**> (&(app_documents)));
-
- if (SUCCEEDED(hr)) {
- if (m_app_id.length() > 0) {
- app_documents->SetAppID(m_app_id.toStdWString().c_str());
- }
-
- hr = app_documents->GetList(type == LIST_RECENT ? ADLT_RECENT : ADLT_FREQUENT, 0, IID_IObjectArray,
- reinterpret_cast<void**> (&(object_array)));
-
- if (SUCCEEDED(hr)) {
- LOCAL_UTILS::ObjectArray2List(object_array, items);
- object_array->Release();
- }
-
- app_documents->Release();
- }
-
- return hr;
- }
-
- long JumpList::GetRecentList(QList<JumpListItem>& items) {
- return GetKnownList(LIST_RECENT, items);
- }
-
- long JumpList::GetFrequentList(QList<JumpListItem>& items) {
- return GetKnownList(LIST_FREQUENT, items);
- }
-
- //IApplicationDestinations
- long JumpList::ClearRecentAndFrequentList() {
- IApplicationDestinations* app_destinations = NULL;
-
- HRESULT hr = CoCreateInstance(CLSID_ApplicationDestinations, NULL ,CLSCTX_INPROC_SERVER, IID_IApplicationDestinations,
- reinterpret_cast<void**> (&(app_destinations)));
-
- if (SUCCEEDED(hr)) {
- if (m_app_id.length() > 0) {
- app_destinations->SetAppID(m_app_id.toStdWString().c_str());
- }
-
- hr = app_destinations->RemoveAllDestinations();
-
- app_destinations->Release();
- }
-
- return hr;
- }
-
- void JumpList::AddPathToRecent(QString path) {
- SHAddToRecentDocs(0x00000003, path.toStdWString().c_str());
- }
-
- void JumpList::AddLinkToRecent(const JumpListItem& link) {
- SHAddToRecentDocs(0x00000006, LOCAL_UTILS::JLItem2ShellLink(link));
- }
-
- JumpList::~JumpList() {
- delete m_private;
- }
-}
-#endif //Q_OS_WIN32
+/***************************************************************************
+ * Copyright (C) 2011 by Nicolae Ghimbovschi *
+ * nicolae.ghimbovschi@gmail.com *
+ * *
+ * 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; version 3 of the License. *
+ * *
+ * 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 program; if not, write to the *
+ * Free Software Foundation, Inc., *
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
+ ***************************************************************************/
+
+#include "JumpList.h"
+
+#ifdef Q_OS_WIN32
+
+#include "win7_include.h"
+#include "JLPrivateData.h"
+
+namespace QW7 {
+
+ namespace LOCAL_UTILS {
+
+ IShellItem* JLItem2ShellItem(const JumpListItem& item) {
+ HMODULE shell;
+ IShellItem *shell_item = NULL;
+ t_SHCreateItemFromParsingName SHCreateItemFromParsingName = NULL;
+
+ shell = LoadLibrary(L"shell32.dll");
+
+ if (shell) {
+ SHCreateItemFromParsingName = reinterpret_cast<t_SHCreateItemFromParsingName>
+ (GetProcAddress (shell, "SHCreateItemFromParsingName"));
+
+ if (SHCreateItemFromParsingName != NULL) {
+ SHCreateItemFromParsingName(item.m_path.toStdWString().c_str(), NULL, IID_IShellItem,
+ reinterpret_cast<void**> (&(shell_item)));
+ }
+
+ FreeLibrary (shell);
+ }
+
+ return shell_item;
+ }
+
+ IShellLink* JLItem2ShellLink(const JumpListItem& item) {
+ IShellLink* shell_link = NULL;
+ IPropertyStore* prop_store = NULL;
+ bool is_not_separator = (item.m_path.length() > 0);
+
+ HRESULT hr = CoCreateInstance(CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER, IID_IShellLink,
+ reinterpret_cast<void**> (&(shell_link)));
+
+ if(SUCCEEDED(hr)) {
+
+ if (is_not_separator) {
+ shell_link->SetPath(item.m_path.toStdWString().c_str());
+ shell_link->SetArguments(item.m_arguments.toStdWString().c_str());
+ shell_link->SetIconLocation(item.m_icon_path.toStdWString().c_str(), item.m_icon_index);
+ shell_link->SetDescription(item.m_description.toStdWString().c_str());
+ }
+
+ hr = shell_link->QueryInterface(IID_IPropertyStore, reinterpret_cast<void**> (&(prop_store)));
+
+ if (SUCCEEDED(hr)) {
+ PROPVARIANT pv;
+
+ if (is_not_separator) {
+ hr = InitPropVariantFromString(item.m_title.toStdWString().c_str(), &pv);
+
+ if (SUCCEEDED(hr)) {
+ hr = prop_store->SetValue(PKEY_Title, pv);
+ }
+ } else {
+ hr = InitPropVariantFromBoolean(TRUE, &pv);
+
+ if (SUCCEEDED(hr)) {
+ hr = prop_store->SetValue(PKEY_AppUserModel_IsDestListSeparator, pv);
+ }
+ }
+
+ //Save the changes we made to the property store
+ prop_store->Commit();
+ prop_store->Release();
+
+ PropVariantClear(&pv);
+ }
+ }
+
+ return shell_link;
+ }
+
+ long List2ObjectCollection(const QList<JumpListItem>& items, IObjectCollection* obj_collection) {
+ HRESULT hr = 0;
+
+ if (obj_collection == NULL) {
+ return -1;
+ }
+
+ for (int index = 0; index < items.size(); ++index) {
+ JumpListItem item = items.at(index);
+
+ if (item.m_type == JL_ITEM) {
+ IShellItem* s_item = JLItem2ShellItem(item);
+
+ if (s_item) {
+ hr = obj_collection->AddObject(s_item);
+ }
+ } else if (item.m_type != JL_OTHER){
+ IShellLink* s_link = JLItem2ShellLink(item);
+
+ if (s_link) {
+ hr = obj_collection->AddObject(s_link);
+ }
+ }
+ }
+
+ return hr;
+ }
+
+ void ObjectArray2List(IObjectArray *object_array, QList<JumpListItem>& items) {
+ bool fRet = false;
+ UINT cItems;
+
+ if (SUCCEEDED(object_array->GetCount(&cItems)))
+ {
+ IShellItem *shell_item;
+ IShellLink *shell_link;
+ wchar_t buffer[MAX_PATH];
+
+ for (UINT i = 0; !fRet && i < cItems; i++)
+ {
+ JumpListItem item;
+
+ if (SUCCEEDED(object_array->GetAt(i, IID_IShellItem, reinterpret_cast<void**> (&(shell_item)))))
+ {
+ LPWSTR file_path = NULL;
+ HRESULT hr = shell_item->GetDisplayName(SIGDN_FILESYSPATH, &file_path);
+
+ if (SUCCEEDED(hr))
+ {
+ item.m_type = JL_ITEM;
+ item.m_path = QString::fromStdWString(file_path);
+ items.append(item);
+ CoTaskMemFree(file_path);
+ }
+
+ shell_item->Release();
+ } else if (SUCCEEDED(object_array->GetAt(i, IID_IShellLink, reinterpret_cast<void**> (&(shell_link))))) {
+ int index = 0;
+
+ item.m_type = JL_LINK;
+ shell_link->GetDescription(buffer, MAX_PATH);
+ item.m_description.fromStdWString(buffer);
+
+ shell_link->GetArguments(buffer, MAX_PATH);
+ item.m_arguments.fromStdWString(buffer);
+
+ shell_link->GetIconLocation(buffer, MAX_PATH, &index);
+ item.m_icon_path.fromStdWString(buffer);
+ item.m_icon_index = index;
+
+ shell_link->GetPath(buffer, MAX_PATH, NULL, SLGP_UNCPRIORITY);
+ item.m_path.fromStdWString(buffer);
+
+ shell_link->GetWorkingDirectory(buffer, MAX_PATH);
+ item.m_working_path.fromStdWString(buffer);
+
+ items.append(item);
+
+ shell_link->Release();
+ }
+ }
+ }
+ }
+ }
+
+
+ JumpList::JumpList(QString app_id) {
+ m_app_id = app_id;
+ m_private = new JLPrivateData(app_id);
+ }
+
+ long JumpList::SetAppID(QString app_id) {
+ if (m_private->m_list_is_initialized) {
+ return -1;
+ }
+
+ m_app_id = app_id;
+
+ return m_private->ListHandler()->SetAppID(app_id.toStdWString().c_str());
+ }
+
+ //ICustomDestinationList
+ long JumpList::Begin() {
+ if (!m_private->m_list_is_initialized) {
+ m_private->InitList();
+ }
+
+ return m_private->m_list_is_initialized ? 0 : -1;
+ }
+
+ long JumpList::AddRecentCategory() {
+ if (!m_private->m_list_is_initialized) {
+ return -1;
+ }
+
+ return m_private->ListHandler()->AppendKnownCategory(KDC_RECENT);
+ }
+
+ long JumpList::AddFrequentCategory() {
+ if (!m_private->m_list_is_initialized) {
+ return -1;
+ }
+
+ return m_private->ListHandler()->AppendKnownCategory(KDC_FREQUENT);
+ }
+
+ long JumpList::AddCategory(QString title, const QList<JumpListItem>& items) {
+ if (!m_private->m_list_is_initialized) {
+ return -1;
+ }
+
+ IObjectCollection* obj_collection;
+
+ HRESULT hr = CoCreateInstance(CLSID_EnumerableObjectCollection, NULL,
+ CLSCTX_INPROC, IID_IObjectCollection, reinterpret_cast<void**> (&(obj_collection)));
+
+ if (SUCCEEDED(hr)) {
+ IObjectArray* object_array;
+
+ LOCAL_UTILS::List2ObjectCollection(items, obj_collection);
+ hr = obj_collection->QueryInterface(IID_IObjectArray,reinterpret_cast<void**> (&(object_array)));
+
+ if (SUCCEEDED(hr)) {
+ hr = m_private->ListHandler()->AppendCategory(title.toStdWString().c_str(), object_array);
+ object_array->Release();
+ }
+
+ obj_collection->Release();
+ }
+
+ return hr;
+ }
+
+ long JumpList::AddUserTasks(const QList<JumpListItem>& items) {
+ if (!m_private->m_list_is_initialized) {
+ return -1;
+ }
+
+ IObjectCollection* obj_collection;
+
+ HRESULT hr = CoCreateInstance(CLSID_EnumerableObjectCollection, NULL,
+ CLSCTX_INPROC, IID_IObjectCollection, reinterpret_cast<void**> (&(obj_collection)));
+
+ if (SUCCEEDED(hr)) {
+ LOCAL_UTILS::List2ObjectCollection(items, obj_collection);
+ hr = m_private->ListHandler()->AddUserTasks(obj_collection);
+
+ obj_collection->Release();
+ }
+
+ return hr;
+ }
+
+ long JumpList::GetRemovedDestinations(QList<JumpListItem>& items) {
+ IObjectArray* object_array = NULL;
+
+ HRESULT hr = m_private->ListHandler()->GetRemovedDestinations(IID_IObjectArray,
+ reinterpret_cast<void**> (&(object_array)));
+
+ if (SUCCEEDED(hr)) {
+ LOCAL_UTILS::ObjectArray2List(object_array, items);
+ object_array->Release();
+ }
+
+ return hr;
+ }
+
+ long JumpList::Clear() {
+ return m_private->ListHandler()->DeleteList(m_app_id.isEmpty() ? NULL : m_app_id.toStdWString().c_str());
+ }
+
+ long JumpList::Commit() {
+ if (!m_private->m_list_is_initialized) {
+ return -1;
+ }
+
+ HRESULT hr = m_private->ListHandler()->CommitList();
+ m_private->ReleaseList();
+
+ return hr;
+ }
+
+ long JumpList::Abort() {
+ if (!m_private->m_list_is_initialized) {
+ return -1;
+ }
+
+ HRESULT hr = m_private->ListHandler()->AbortList();
+ m_private->ReleaseList();
+
+ return hr;
+ }
+
+ //IApplicationDocumentLists
+ long JumpList::GetKnownList(KnownListType type, QList<JumpListItem>& items) {
+ IObjectArray* object_array = NULL;
+ IApplicationDocumentLists* app_documents = NULL;
+
+ HRESULT hr = CoCreateInstance(CLSID_ApplicationDocumentLists, NULL, CLSCTX_INPROC_SERVER, IID_IApplicationDocumentLists,
+ reinterpret_cast<void**> (&(app_documents)));
+
+ if (SUCCEEDED(hr)) {
+ if (m_app_id.length() > 0) {
+ app_documents->SetAppID(m_app_id.toStdWString().c_str());
+ }
+
+ hr = app_documents->GetList(type == LIST_RECENT ? ADLT_RECENT : ADLT_FREQUENT, 0, IID_IObjectArray,
+ reinterpret_cast<void**> (&(object_array)));
+
+ if (SUCCEEDED(hr)) {
+ LOCAL_UTILS::ObjectArray2List(object_array, items);
+ object_array->Release();
+ }
+
+ app_documents->Release();
+ }
+
+ return hr;
+ }
+
+ long JumpList::GetRecentList(QList<JumpListItem>& items) {
+ return GetKnownList(LIST_RECENT, items);
+ }
+
+ long JumpList::GetFrequentList(QList<JumpListItem>& items) {
+ return GetKnownList(LIST_FREQUENT, items);
+ }
+
+ //IApplicationDestinations
+ long JumpList::ClearRecentAndFrequentList() {
+ IApplicationDestinations* app_destinations = NULL;
+
+ HRESULT hr = CoCreateInstance(CLSID_ApplicationDestinations, NULL ,CLSCTX_INPROC_SERVER, IID_IApplicationDestinations,
+ reinterpret_cast<void**> (&(app_destinations)));
+
+ if (SUCCEEDED(hr)) {
+ if (m_app_id.length() > 0) {
+ app_destinations->SetAppID(m_app_id.toStdWString().c_str());
+ }
+
+ hr = app_destinations->RemoveAllDestinations();
+
+ app_destinations->Release();
+ }
+
+ return hr;
+ }
+
+ void JumpList::AddPathToRecent(QString path) {
+ SHAddToRecentDocs(0x00000003, path.toStdWString().c_str());
+ }
+
+ void JumpList::AddLinkToRecent(const JumpListItem& link) {
+ SHAddToRecentDocs(0x00000006, LOCAL_UTILS::JLItem2ShellLink(link));
+ }
+
+ JumpList::~JumpList() {
+ delete m_private;
+ }
+}
+#endif //Q_OS_WIN32
diff --git a/tools/qwin7utils/TaskbarButton.cpp b/tools/qwin7utils/TaskbarButton.cpp
index 5c3704f..52468c9 100644
--- a/tools/qwin7utils/TaskbarButton.cpp
+++ b/tools/qwin7utils/TaskbarButton.cpp
@@ -1,72 +1,72 @@
-/***************************************************************************
- * Copyright (C) 2011 by Nicolae Ghimbovschi *
- * nicolae.ghimbovschi@gmail.com *
- * *
- * 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; version 3 of the License. *
- * *
- * 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 program; if not, write to the *
- * Free Software Foundation, Inc., *
- * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
- ***************************************************************************/
-
-#include <QBitmap>
-#include <QPixmap>
-#include <QPainter>
-
-#include "TaskbarButton.h"
-
-#ifdef Q_OS_WIN32
-#include "Taskbar.h"
-#include "TBPrivateData.h"
-
-namespace QW7 {
-
- TaskbarButton::TaskbarButton(QWidget* parent) : QObject(parent) {
- SetWindow(parent);
- }
-
- void TaskbarButton::SetWindow(QWidget* window) {
- m_widget = window;
- }
-
- long TaskbarButton::SetOverlayIcon(const QIcon& icon, QString description) {
- if (Taskbar::GetInstance()->m_private) {
- HICON overlay_icon = icon.isNull() ? NULL : icon.pixmap(48).toWinHICON();
- long result = Taskbar::GetInstance()->m_private->GetHandler()->SetOverlayIcon(m_widget->winId(), overlay_icon, description.toStdWString().c_str());
-
- if (overlay_icon) {
- DestroyIcon(overlay_icon);
- return result;
- }
- }
-
- return -1;
- }
-
- long TaskbarButton::SetState(ProgressBarState state) {
- if (Taskbar::GetInstance()->m_private) {
- return Taskbar::GetInstance()->m_private->GetHandler()->SetProgressState(m_widget->winId(), (TBPFLAG)state);
- }
-
- return -1;
- }
-
- long TaskbarButton::SetProgresValue(unsigned long long done, unsigned long long total) {
- if (Taskbar::GetInstance()->m_private) {
- return Taskbar::GetInstance()->m_private->GetHandler()->SetProgressValue(m_widget->winId(), done, total);
- }
-
- return -1;
- }
-
-}
-
-#endif //Q_OS_WIN32
+/***************************************************************************
+ * Copyright (C) 2011 by Nicolae Ghimbovschi *
+ * nicolae.ghimbovschi@gmail.com *
+ * *
+ * 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; version 3 of the License. *
+ * *
+ * 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 program; if not, write to the *
+ * Free Software Foundation, Inc., *
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
+ ***************************************************************************/
+
+#include <QBitmap>
+#include <QPixmap>
+#include <QPainter>
+
+#include "TaskbarButton.h"
+
+#ifdef Q_OS_WIN32
+#include "Taskbar.h"
+#include "TBPrivateData.h"
+
+namespace QW7 {
+
+ TaskbarButton::TaskbarButton(QWidget* parent) : QObject(parent) {
+ SetWindow(parent);
+ }
+
+ void TaskbarButton::SetWindow(QWidget* window) {
+ m_widget = window;
+ }
+
+ long TaskbarButton::SetOverlayIcon(const QIcon& icon, QString description) {
+ if (Taskbar::GetInstance()->m_private) {
+ HICON overlay_icon = icon.isNull() ? NULL : icon.pixmap(48).toWinHICON();
+ long result = Taskbar::GetInstance()->m_private->GetHandler()->SetOverlayIcon(m_widget->winId(), overlay_icon, description.toStdWString().c_str());
+
+ if (overlay_icon) {
+ DestroyIcon(overlay_icon);
+ return result;
+ }
+ }
+
+ return -1;
+ }
+
+ long TaskbarButton::SetState(ProgressBarState state) {
+ if (Taskbar::GetInstance()->m_private) {
+ return Taskbar::GetInstance()->m_private->GetHandler()->SetProgressState((HWND)m_widget->winId(), (TBPFLAG)state);
+ }
+
+ return -1;
+ }
+
+ long TaskbarButton::SetProgresValue(unsigned long long done, unsigned long long total) {
+ if (Taskbar::GetInstance()->m_private) {
+ return Taskbar::GetInstance()->m_private->GetHandler()->SetProgressValue((HWND)m_widget->winId(), done, total);
+ }
+
+ return -1;
+ }
+
+}
+
+#endif //Q_OS_WIN32
diff --git a/tools/qwin7utils/TaskbarToolbar.cpp b/tools/qwin7utils/TaskbarToolbar.cpp
index b93ba75..d011b92 100644
--- a/tools/qwin7utils/TaskbarToolbar.cpp
+++ b/tools/qwin7utils/TaskbarToolbar.cpp
@@ -1,167 +1,167 @@
-/***************************************************************************
- * Copyright (C) 2011 by Nicolae Ghimbovschi *
- * nicolae.ghimbovschi@gmail.com *
- * *
- * 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; version 3 of the License. *
- * *
- * 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 program; if not, write to the *
- * Free Software Foundation, Inc., *
- * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
- ***************************************************************************/
-
-#include "TaskbarToolbar.h"
-
-#ifdef Q_OS_WIN32
-#include <QBitmap>
-#include <QPixmap>
-
-#include "Taskbar.h"
-#include "TBPrivateData.h"
-
-#define IDTB_FIRST 3000
-
-namespace QW7 {
-
- TaskbarToolbar::TaskbarToolbar(QWidget *parent) :
- QObject(parent)
- {
- m_initialized = false;
- SetWidget(parent);
- }
-
- void TaskbarToolbar::SetWidget(QWidget* widget) {
- m_widget = widget;
- }
-
- void TaskbarToolbar::SetThumbnailClip(QRect rect) {
- RECT wrect;
- wrect.left = rect.left(); wrect.right = rect.right();
- wrect.top = rect.top(); wrect.bottom = rect.bottom();
- Taskbar::GetInstance()->m_private->GetHandler()->SetThumbnailClip(m_widget->winId(), &wrect);
- }
-
- void TaskbarToolbar::SetThumbnailTooltip(QString tooltip) {
- Taskbar::GetInstance()->m_private->GetHandler()->SetThumbnailTooltip(m_widget->winId(), tooltip.toStdWString().c_str());
- }
-
- void TaskbarToolbar::AddAction(QAction* action) {
- if (m_initialized) return;
-
- m_actions.append(action);
-
- connect(action, SIGNAL(changed()), this, SLOT(OnActionChanged()));
- }
-
- void TaskbarToolbar::AddActions(QList<QAction*>& actions) {
- if (m_initialized) return;
-
- RemoveActions();
-
- m_actions.append(actions);
-
- QAction* action;
- foreach(action, m_actions) {
- connect(action, SIGNAL(changed()), this, SLOT(OnActionChanged()));
- }
- }
-
- void TaskbarToolbar::RemoveActions() {
- QAction* action;
-
- foreach(action, m_actions) {
- disconnect(action, SIGNAL(changed()), this, SLOT(OnActionChanged()));
- }
-
- m_actions.clear();
- }
-
- void TaskbarToolbar::OnActionChanged() {
- Show();
- }
-
- void TaskbarToolbar::Show() {
- HIMAGELIST himl = ImageList_Create(20, 20, ILC_COLOR32, m_actions.size(), 0);
-
- THUMBBUTTON* thbButtons = new THUMBBUTTON[m_actions.size()];
-
- if (!himl) return;
- if (!thbButtons) return;
-
- int index = 0;
- QAction* action;
-
- foreach(action, m_actions) {
- QPixmap img = action->icon().pixmap(20);
- QBitmap mask = img.createMaskFromColor(Qt::transparent);
-
- ImageList_Add(himl, img.toWinHBITMAP(QPixmap::PremultipliedAlpha), mask.toWinHBITMAP());
-
- wcscpy(thbButtons[index].szTip, action->text().toStdWString().c_str());
-
- thbButtons[index].iId = IDTB_FIRST + index;
- thbButtons[index].iBitmap = index;
- thbButtons[index].dwMask = (THUMBBUTTONMASK)(THB_BITMAP | THB_FLAGS | THB_TOOLTIP);
- thbButtons[index].dwFlags = (THUMBBUTTONFLAGS)(action->isEnabled() ? THBF_ENABLED : THBF_DISABLED);
-
- if (!action->isVisible()) thbButtons[index].dwFlags = (THUMBBUTTONFLAGS)(thbButtons[index].dwFlags | THBF_HIDDEN);
- if (action->data().toBool()) thbButtons[index].dwFlags = (THUMBBUTTONFLAGS)(thbButtons[index].dwFlags | THBF_DISMISSONCLICK);
-
- ++index;
- }
-
- HRESULT hr = Taskbar::GetInstance()->m_private->GetHandler()->ThumbBarSetImageList(m_widget->winId(), himl);
-
- if (S_OK == hr) {
- if (!m_initialized) {
- Taskbar::GetInstance()->m_private->GetHandler()->ThumbBarAddButtons(m_widget->winId(), m_actions.size(), thbButtons);
- } else {
- Taskbar::GetInstance()->m_private->GetHandler()->ThumbBarUpdateButtons(m_widget->winId(), m_actions.size(), thbButtons);
- }
- }
-
- m_initialized = true;
-
- delete[] thbButtons;
- ImageList_Destroy(himl);
- }
-
- bool TaskbarToolbar::winEvent(MSG* message, long* result) {
-
- switch (message->message)
- {
- case WM_COMMAND:
- {
- int buttonId = LOWORD(message->wParam) - IDTB_FIRST;
-
- if ((buttonId >= 0) && (buttonId < m_actions.size())) {
- QAction* action = m_actions.at(buttonId);
-
- if (action) action->trigger();
- return true;
- }
-
-
- break;
- }
- }
-
- return false;
- }
-
-
- TaskbarToolbar::~TaskbarToolbar() {
- RemoveActions();
- }
-
-
-}
-
-#endif //Q_OS_WIN32
+/***************************************************************************
+ * Copyright (C) 2011 by Nicolae Ghimbovschi *
+ * nicolae.ghimbovschi@gmail.com *
+ * *
+ * 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; version 3 of the License. *
+ * *
+ * 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 program; if not, write to the *
+ * Free Software Foundation, Inc., *
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
+ ***************************************************************************/
+
+#include "TaskbarToolbar.h"
+
+#ifdef Q_OS_WIN32
+#include <QBitmap>
+#include <QPixmap>
+
+#include "Taskbar.h"
+#include "TBPrivateData.h"
+
+#define IDTB_FIRST 3000
+
+namespace QW7 {
+
+ TaskbarToolbar::TaskbarToolbar(QWidget *parent) :
+ QObject(parent)
+ {
+ m_initialized = false;
+ SetWidget(parent);
+ }
+
+ void TaskbarToolbar::SetWidget(QWidget* widget) {
+ m_widget = widget;
+ }
+
+ void TaskbarToolbar::SetThumbnailClip(QRect rect) {
+ RECT wrect;
+ wrect.left = rect.left(); wrect.right = rect.right();
+ wrect.top = rect.top(); wrect.bottom = rect.bottom();
+ Taskbar::GetInstance()->m_private->GetHandler()->SetThumbnailClip((HWND) m_widget->winId(), &wrect);
+ }
+
+ void TaskbarToolbar::SetThumbnailTooltip(QString tooltip) {
+ Taskbar::GetInstance()->m_private->GetHandler()->SetThumbnailTooltip((HWND) m_widget->winId(), tooltip.toStdWString().c_str());
+ }
+
+ void TaskbarToolbar::AddAction(QAction* action) {
+ if (m_initialized) return;
+
+ m_actions.append(action);
+
+ connect(action, SIGNAL(changed()), this, SLOT(OnActionChanged()));
+ }
+
+ void TaskbarToolbar::AddActions(QList<QAction*>& actions) {
+ if (m_initialized) return;
+
+ RemoveActions();
+
+ m_actions.append(actions);
+
+ QAction* action;
+ foreach(action, m_actions) {
+ connect(action, SIGNAL(changed()), this, SLOT(OnActionChanged()));
+ }
+ }
+
+ void TaskbarToolbar::RemoveActions() {
+ QAction* action;
+
+ foreach(action, m_actions) {
+ disconnect(action, SIGNAL(changed()), this, SLOT(OnActionChanged()));
+ }
+
+ m_actions.clear();
+ }
+
+ void TaskbarToolbar::OnActionChanged() {
+ Show();
+ }
+
+ void TaskbarToolbar::Show() {
+ HIMAGELIST himl = ImageList_Create(20, 20, ILC_COLOR32, m_actions.size(), 0);
+
+ THUMBBUTTON* thbButtons = new THUMBBUTTON[m_actions.size()];
+
+ if (!himl) return;
+ if (!thbButtons) return;
+
+ int index = 0;
+ QAction* action;
+
+ foreach(action, m_actions) {
+ QPixmap img = action->icon().pixmap(20);
+ QBitmap mask = img.createMaskFromColor(Qt::transparent);
+
+ ImageList_Add(himl, img.toWinHBITMAP(QPixmap::PremultipliedAlpha), mask.toWinHBITMAP());
+
+ wcscpy(thbButtons[index].szTip, action->text().toStdWString().c_str());
+
+ thbButtons[index].iId = IDTB_FIRST + index;
+ thbButtons[index].iBitmap = index;
+ thbButtons[index].dwMask = (THUMBBUTTONMASK)(THB_BITMAP | THB_FLAGS | THB_TOOLTIP);
+ thbButtons[index].dwFlags = (THUMBBUTTONFLAGS)(action->isEnabled() ? THBF_ENABLED : THBF_DISABLED);
+
+ if (!action->isVisible()) thbButtons[index].dwFlags = (THUMBBUTTONFLAGS)(thbButtons[index].dwFlags | THBF_HIDDEN);
+ if (action->data().toBool()) thbButtons[index].dwFlags = (THUMBBUTTONFLAGS)(thbButtons[index].dwFlags | THBF_DISMISSONCLICK);
+
+ ++index;
+ }
+
+ HRESULT hr = Taskbar::GetInstance()->m_private->GetHandler()->ThumbBarSetImageList((HWND)m_widget->winId(), himl);
+
+ if (S_OK == hr) {
+ if (!m_initialized) {
+ Taskbar::GetInstance()->m_private->GetHandler()->ThumbBarAddButtons((HWND)m_widget->winId(), m_actions.size(), thbButtons);
+ } else {
+ Taskbar::GetInstance()->m_private->GetHandler()->ThumbBarUpdateButtons((HWND)m_widget->winId(), m_actions.size(), thbButtons);
+ }
+ }
+
+ m_initialized = true;
+
+ delete[] thbButtons;
+ ImageList_Destroy(himl);
+ }
+
+ bool TaskbarToolbar::winEvent(MSG* message, long* result) {
+
+ switch (message->message)
+ {
+ case WM_COMMAND:
+ {
+ int buttonId = LOWORD(message->wParam) - IDTB_FIRST;
+
+ if ((buttonId >= 0) && (buttonId < m_actions.size())) {
+ QAction* action = m_actions.at(buttonId);
+
+ if (action) action->trigger();
+ return true;
+ }
+
+
+ break;
+ }
+ }
+
+ return false;
+ }
+
+
+ TaskbarToolbar::~TaskbarToolbar() {
+ RemoveActions();
+ }
+
+
+}
+
+#endif //Q_OS_WIN32
diff --git a/tools/qwin7utils/Utils.cpp b/tools/qwin7utils/Utils.cpp
index 0873144..77a36e6 100644
--- a/tools/qwin7utils/Utils.cpp
+++ b/tools/qwin7utils/Utils.cpp
@@ -1,212 +1,212 @@
-/***************************************************************************
- * Copyright (C) 2011 by Nicolae Ghimbovschi *
- * nicolae.ghimbovschi@gmail.com *
- * *
- * 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; version 3 of the License. *
- * *
- * 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 program; if not, write to the *
- * Free Software Foundation, Inc., *
- * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
- ***************************************************************************/
-
-#include <QtGlobal>
-
-#ifdef Q_OS_WIN32
-
-#include "Utils.h"
-namespace QW7 {
-
-#define DWM_BB_ENABLE 0x00000001 // fEnable has been specified
-
- typedef struct _DWM_BLURBEHIND
- {
- DWORD dwFlags;
- BOOL fEnable;
- HRGN hRgnBlur;
- BOOL fTransitionOnMaximized;
- } DWM_BLURBEHIND, *PDWM_BLURBEHIND;
-
- typedef struct _MARGINS
- {
- int cxLeftWidth; // width of left border that retains its size
- int cxRightWidth; // width of right border that retains its size
- int cyTopHeight; // height of top border that retains its size
- int cyBottomHeight; // height of bottom border that retains its size
- } MARGINS, *PMARGINS;
-
- // Window attributes
- enum DWMWINDOWATTRIBUTE
- {
- DWMWA_NCRENDERING_ENABLED = 1, // [get] Is non-client rendering enabled/disabled
- DWMWA_NCRENDERING_POLICY, // [set] Non-client rendering policy
- DWMWA_TRANSITIONS_FORCEDISABLED, // [set] Potentially enable/forcibly disable transitions
- DWMWA_ALLOW_NCPAINT, // [set] Allow contents rendered in the non-client area to be visible on the DWM-drawn frame.
- DWMWA_CAPTION_BUTTON_BOUNDS, // [get] Bounds of the caption button area in window-relative space.
- DWMWA_NONCLIENT_RTL_LAYOUT, // [set] Is non-client content RTL mirrored
- DWMWA_FORCE_ICONIC_REPRESENTATION, // [set] Force this window to display iconic thumbnails.
- DWMWA_FLIP3D_POLICY, // [set] Designates how Flip3D will treat the window.
- DWMWA_EXTENDED_FRAME_BOUNDS, // [get] Gets the extended frame bounds rectangle in screen space
- DWMWA_HAS_ICONIC_BITMAP, // [set] Indicates an available bitmap when there is no better thumbnail representation.
- DWMWA_DISALLOW_PEEK, // [set] Don't invoke Peek on the window.
- DWMWA_EXCLUDED_FROM_PEEK, // [set] LivePreview exclusion information
- DWMWA_LAST
- };
-
- // Values designating how Flip3D treats a given window.
- enum DWMFLIP3DWINDOWPOLICY
- {
- DWMFLIP3D_DEFAULT, // Hide or include the window in Flip3D based on window style and visibility.
- DWMFLIP3D_EXCLUDEBELOW, // Display the window under Flip3D and disabled.
- DWMFLIP3D_EXCLUDEABOVE, // Display the window above Flip3D and enabled.
- DWMFLIP3D_LAST
- };
-
- typedef enum _DWMNCRENDERINGPOLICY {
- DWMNCRP_USEWINDOWSTYLE,
- DWMNCRP_DISABLED,
- DWMNCRP_ENABLED,
- DWMNCRP_LAST
- } DWMNCRENDERINGPOLICY;
-
- extern "C"
- {
- typedef HRESULT (WINAPI *t_DwmSetIconicThumbnail)(HWND hwnd, HBITMAP hbmp, DWORD dwSITFlags);
- typedef HRESULT (WINAPI *t_DwmSetWindowAttribute)(HWND hwnd, DWORD dwAttribute, LPCVOID pvAttribute, DWORD cbAttribute);
- typedef HRESULT (WINAPI *t_DwmSetIconicLivePreviewBitmap)(HWND hwnd, HBITMAP hbmp, POINT *pptClient, DWORD dwSITFlags);
- typedef HRESULT (WINAPI *t_DwmEnableBlurBehindWindow)(HWND hWnd, const DWM_BLURBEHIND* pBlurBehind);
- typedef HRESULT (WINAPI *t_DwmExtendFrameIntoClientArea)(HWND hwnd, const MARGINS *pMarInset);
- typedef HRESULT (WINAPI *t_DwmInvalidateIconicBitmaps)(HWND hwnd);
- }
-
- void DwmSetIconicThumbnail(HWND hwnd, HBITMAP hbmp, DWORD dwSITFlags) {
- HMODULE shell;
-
- shell = LoadLibrary(L"dwmapi.dll");
- if (shell) {
- t_DwmSetIconicThumbnail set_iconic_thumbnail = reinterpret_cast<t_DwmSetIconicThumbnail>(GetProcAddress (shell, "DwmSetIconicThumbnail"));
- set_iconic_thumbnail(hwnd, hbmp, dwSITFlags);
-
- FreeLibrary (shell);
- }
- }
-
- void DwmSetWindowAttribute(HWND hwnd, DWORD dwAttribute, LPCVOID pvAttribute, DWORD cbAttribute) {
- HMODULE shell;
-
- shell = LoadLibrary(L"dwmapi.dll");
- if (shell) {
- t_DwmSetWindowAttribute set_window_attribute = reinterpret_cast<t_DwmSetWindowAttribute>(GetProcAddress (shell, "DwmSetWindowAttribute"));
- set_window_attribute(hwnd, dwAttribute, pvAttribute, cbAttribute);
-
- FreeLibrary (shell);
- }
- }
-
- void DwmSetIconicLivePreviewBitmap(HWND hwnd, HBITMAP hbmp, POINT *pptClient, DWORD dwSITFlags) {
- HMODULE shell;
-
- shell = LoadLibrary(L"dwmapi.dll");
- if (shell) {
- t_DwmSetIconicLivePreviewBitmap set_live_preview = reinterpret_cast<t_DwmSetIconicLivePreviewBitmap>(GetProcAddress (shell, "DwmSetIconicLivePreviewBitmap"));
- set_live_preview(hwnd, hbmp, pptClient, dwSITFlags);
-
- FreeLibrary (shell);
- }
- }
-
-
- void DwmEnableBlurBehindWindow(HWND hwnd, const DWM_BLURBEHIND* pBlurBehind) {
- HMODULE shell;
-
- shell = LoadLibrary(L"dwmapi.dll");
- if (shell) {
- t_DwmEnableBlurBehindWindow set_window_blur = reinterpret_cast<t_DwmEnableBlurBehindWindow>(GetProcAddress (shell, "DwmEnableBlurBehindWindow"));
- set_window_blur(hwnd, pBlurBehind);
-
- FreeLibrary (shell);
- }
- }
-
- void DwmExtendFrameIntoClientArea(HWND hwnd, const MARGINS *pMarInset) {
- HMODULE shell;
-
- shell = LoadLibrary(L"dwmapi.dll");
- if (shell) {
- t_DwmExtendFrameIntoClientArea set_window_frame_into_client_area = reinterpret_cast<t_DwmExtendFrameIntoClientArea>(GetProcAddress (shell, "DwmExtendFrameIntoClientArea"));
- set_window_frame_into_client_area(hwnd, pMarInset);
-
- FreeLibrary (shell);
- }
-
- }
-
- void DwmInvalidateIconicBitmaps(HWND hwnd) {
- HMODULE shell;
-
- shell = LoadLibrary(L"dwmapi.dll");
- if (shell) {
- t_DwmInvalidateIconicBitmaps invalidate_icon_bitmap = reinterpret_cast<t_DwmInvalidateIconicBitmaps>(GetProcAddress (shell, "DwmInvalidateIconicBitmaps"));
- invalidate_icon_bitmap(hwnd);
-
- FreeLibrary (shell);
- }
-
- }
-
- void ExtendFrameIntoClientArea(QWidget* widget) {
- MARGINS margins = {-1};
-
- DwmExtendFrameIntoClientArea(widget->winId(), &margins);
- }
-
- long EnableBlurBehindWidget(QWidget* widget, bool enable)
- {
- HWND hwnd = widget->winId();
- HRESULT hr = S_OK;
-
- widget->setAttribute(Qt::WA_TranslucentBackground, enable);
- widget->setAttribute(Qt::WA_NoSystemBackground, enable);
-
- // Create and populate the Blur Behind structure
- DWM_BLURBEHIND bb = {0};
-
- bb.dwFlags = DWM_BB_ENABLE;
- bb.fEnable = enable;
- bb.hRgnBlur = NULL;
-
- DwmEnableBlurBehindWindow(hwnd, &bb);
- return hr;
- }
-
- void EnableWidgetIconicPreview(QWidget* widget, bool enable) {
- BOOL _enable = enable ? TRUE : FALSE;
-
- DwmSetWindowAttribute(
- widget->winId(),
- DWMWA_FORCE_ICONIC_REPRESENTATION,
- &_enable,
- sizeof(_enable));
-
- DwmSetWindowAttribute(
- widget->winId(),
- DWMWA_HAS_ICONIC_BITMAP,
- &_enable,
- sizeof(_enable));
-
- }
-
- void InvalidateIconicBitmaps(QWidget* widget) {
- DwmInvalidateIconicBitmaps(widget->winId());
- }
-
-}
-
-#endif //Q_OS_WIN32
+/***************************************************************************
+ * Copyright (C) 2011 by Nicolae Ghimbovschi *
+ * nicolae.ghimbovschi@gmail.com *
+ * *
+ * 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; version 3 of the License. *
+ * *
+ * 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 program; if not, write to the *
+ * Free Software Foundation, Inc., *
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
+ ***************************************************************************/
+
+#include <QtGlobal>
+
+#ifdef Q_OS_WIN32
+
+#include "Utils.h"
+namespace QW7 {
+
+#define DWM_BB_ENABLE 0x00000001 // fEnable has been specified
+
+ typedef struct _DWM_BLURBEHIND
+ {
+ DWORD dwFlags;
+ BOOL fEnable;
+ HRGN hRgnBlur;
+ BOOL fTransitionOnMaximized;
+ } DWM_BLURBEHIND, *PDWM_BLURBEHIND;
+
+ typedef struct _MARGINS
+ {
+ int cxLeftWidth; // width of left border that retains its size
+ int cxRightWidth; // width of right border that retains its size
+ int cyTopHeight; // height of top border that retains its size
+ int cyBottomHeight; // height of bottom border that retains its size
+ } MARGINS, *PMARGINS;
+
+ // Window attributes
+ enum DWMWINDOWATTRIBUTE
+ {
+ DWMWA_NCRENDERING_ENABLED = 1, // [get] Is non-client rendering enabled/disabled
+ DWMWA_NCRENDERING_POLICY, // [set] Non-client rendering policy
+ DWMWA_TRANSITIONS_FORCEDISABLED, // [set] Potentially enable/forcibly disable transitions
+ DWMWA_ALLOW_NCPAINT, // [set] Allow contents rendered in the non-client area to be visible on the DWM-drawn frame.
+ DWMWA_CAPTION_BUTTON_BOUNDS, // [get] Bounds of the caption button area in window-relative space.
+ DWMWA_NONCLIENT_RTL_LAYOUT, // [set] Is non-client content RTL mirrored
+ DWMWA_FORCE_ICONIC_REPRESENTATION, // [set] Force this window to display iconic thumbnails.
+ DWMWA_FLIP3D_POLICY, // [set] Designates how Flip3D will treat the window.
+ DWMWA_EXTENDED_FRAME_BOUNDS, // [get] Gets the extended frame bounds rectangle in screen space
+ DWMWA_HAS_ICONIC_BITMAP, // [set] Indicates an available bitmap when there is no better thumbnail representation.
+ DWMWA_DISALLOW_PEEK, // [set] Don't invoke Peek on the window.
+ DWMWA_EXCLUDED_FROM_PEEK, // [set] LivePreview exclusion information
+ DWMWA_LAST
+ };
+
+ // Values designating how Flip3D treats a given window.
+ enum DWMFLIP3DWINDOWPOLICY
+ {
+ DWMFLIP3D_DEFAULT, // Hide or include the window in Flip3D based on window style and visibility.
+ DWMFLIP3D_EXCLUDEBELOW, // Display the window under Flip3D and disabled.
+ DWMFLIP3D_EXCLUDEABOVE, // Display the window above Flip3D and enabled.
+ DWMFLIP3D_LAST
+ };
+
+ typedef enum _DWMNCRENDERINGPOLICY {
+ DWMNCRP_USEWINDOWSTYLE,
+ DWMNCRP_DISABLED,
+ DWMNCRP_ENABLED,
+ DWMNCRP_LAST
+ } DWMNCRENDERINGPOLICY;
+
+ extern "C"
+ {
+ typedef HRESULT (WINAPI *t_DwmSetIconicThumbnail)(HWND hwnd, HBITMAP hbmp, DWORD dwSITFlags);
+ typedef HRESULT (WINAPI *t_DwmSetWindowAttribute)(HWND hwnd, DWORD dwAttribute, LPCVOID pvAttribute, DWORD cbAttribute);
+ typedef HRESULT (WINAPI *t_DwmSetIconicLivePreviewBitmap)(HWND hwnd, HBITMAP hbmp, POINT *pptClient, DWORD dwSITFlags);
+ typedef HRESULT (WINAPI *t_DwmEnableBlurBehindWindow)(HWND hWnd, const DWM_BLURBEHIND* pBlurBehind);
+ typedef HRESULT (WINAPI *t_DwmExtendFrameIntoClientArea)(HWND hwnd, const MARGINS *pMarInset);
+ typedef HRESULT (WINAPI *t_DwmInvalidateIconicBitmaps)(HWND hwnd);
+ }
+
+ void DwmSetIconicThumbnail(HWND hwnd, HBITMAP hbmp, DWORD dwSITFlags) {
+ HMODULE shell;
+
+ shell = LoadLibrary(L"dwmapi.dll");
+ if (shell) {
+ t_DwmSetIconicThumbnail set_iconic_thumbnail = reinterpret_cast<t_DwmSetIconicThumbnail>(GetProcAddress (shell, "DwmSetIconicThumbnail"));
+ set_iconic_thumbnail(hwnd, hbmp, dwSITFlags);
+
+ FreeLibrary (shell);
+ }
+ }
+
+ void DwmSetWindowAttribute(HWND hwnd, DWORD dwAttribute, LPCVOID pvAttribute, DWORD cbAttribute) {
+ HMODULE shell;
+
+ shell = LoadLibrary(L"dwmapi.dll");
+ if (shell) {
+ t_DwmSetWindowAttribute set_window_attribute = reinterpret_cast<t_DwmSetWindowAttribute>(GetProcAddress (shell, "DwmSetWindowAttribute"));
+ set_window_attribute(hwnd, dwAttribute, pvAttribute, cbAttribute);
+
+ FreeLibrary (shell);
+ }
+ }
+
+ void DwmSetIconicLivePreviewBitmap(HWND hwnd, HBITMAP hbmp, POINT *pptClient, DWORD dwSITFlags) {
+ HMODULE shell;
+
+ shell = LoadLibrary(L"dwmapi.dll");
+ if (shell) {
+ t_DwmSetIconicLivePreviewBitmap set_live_preview = reinterpret_cast<t_DwmSetIconicLivePreviewBitmap>(GetProcAddress (shell, "DwmSetIconicLivePreviewBitmap"));
+ set_live_preview(hwnd, hbmp, pptClient, dwSITFlags);
+
+ FreeLibrary (shell);
+ }
+ }
+
+
+ void DwmEnableBlurBehindWindow(HWND hwnd, const DWM_BLURBEHIND* pBlurBehind) {
+ HMODULE shell;
+
+ shell = LoadLibrary(L"dwmapi.dll");
+ if (shell) {
+ t_DwmEnableBlurBehindWindow set_window_blur = reinterpret_cast<t_DwmEnableBlurBehindWindow>(GetProcAddress (shell, "DwmEnableBlurBehindWindow"));
+ set_window_blur(hwnd, pBlurBehind);
+
+ FreeLibrary (shell);
+ }
+ }
+
+ void DwmExtendFrameIntoClientArea(HWND hwnd, const MARGINS *pMarInset) {
+ HMODULE shell;
+
+ shell = LoadLibrary(L"dwmapi.dll");
+ if (shell) {
+ t_DwmExtendFrameIntoClientArea set_window_frame_into_client_area = reinterpret_cast<t_DwmExtendFrameIntoClientArea>(GetProcAddress (shell, "DwmExtendFrameIntoClientArea"));
+ set_window_frame_into_client_area(hwnd, pMarInset);
+
+ FreeLibrary (shell);
+ }
+
+ }
+
+ void DwmInvalidateIconicBitmaps(HWND hwnd) {
+ HMODULE shell;
+
+ shell = LoadLibrary(L"dwmapi.dll");
+ if (shell) {
+ t_DwmInvalidateIconicBitmaps invalidate_icon_bitmap = reinterpret_cast<t_DwmInvalidateIconicBitmaps>(GetProcAddress (shell, "DwmInvalidateIconicBitmaps"));
+ invalidate_icon_bitmap(hwnd);
+
+ FreeLibrary (shell);
+ }
+
+ }
+
+ void ExtendFrameIntoClientArea(QWidget* widget) {
+ MARGINS margins = {-1};
+
+ DwmExtendFrameIntoClientArea((HWND)widget->winId(), &margins);
+ }
+
+ long EnableBlurBehindWidget(QWidget* widget, bool enable)
+ {
+ HWND hwnd = (HWND) widget->winId();
+ HRESULT hr = S_OK;
+
+ widget->setAttribute(Qt::WA_TranslucentBackground, enable);
+ widget->setAttribute(Qt::WA_NoSystemBackground, enable);
+
+ // Create and populate the Blur Behind structure
+ DWM_BLURBEHIND bb = {0};
+
+ bb.dwFlags = DWM_BB_ENABLE;
+ bb.fEnable = enable;
+ bb.hRgnBlur = NULL;
+
+ DwmEnableBlurBehindWindow(hwnd, &bb);
+ return hr;
+ }
+
+ void EnableWidgetIconicPreview(QWidget* widget, bool enable) {
+ BOOL _enable = enable ? TRUE : FALSE;
+
+ DwmSetWindowAttribute(
+ (HWND)widget->winId(),
+ DWMWA_FORCE_ICONIC_REPRESENTATION,
+ &_enable,
+ sizeof(_enable));
+
+ DwmSetWindowAttribute(
+ (HWND)widget->winId(),
+ DWMWA_HAS_ICONIC_BITMAP,
+ &_enable,
+ sizeof(_enable));
+
+ }
+
+ void InvalidateIconicBitmaps(QWidget* widget) {
+ DwmInvalidateIconicBitmaps((HWND)widget->winId());
+ }
+
+}
+
+#endif //Q_OS_WIN32
diff --git a/tools/qwin7utils/win7_include.h b/tools/qwin7utils/win7_include.h
index ba5747b..77c05b1 100644
--- a/tools/qwin7utils/win7_include.h
+++ b/tools/qwin7utils/win7_include.h
@@ -1,302 +1,42 @@
-#ifndef WIN7UTILS_H
-#define WIN7UTILS_H
-#include <QtGlobal>
-
-#ifdef Q_OS_WIN32
-#include <shlobj.h>
-#include <shlwapi.h>
-#include <initguid.h>
-#include <objidl.h>
-#include <shellapi.h>
-//#include <ShObjIdl.h>
-
-//Definitions for Windows 7 Taskbar and JumpList
-
-#define WM_DWMSENDICONICTHUMBNAIL 0x0323
-#define WM_DWMSENDICONICLIVEPREVIEWBITMAP 0x0326
-
-typedef enum STPFLAG
-{
- STPF_NONE = 0,
- STPF_USEAPPTHUMBNAILALWAYS = 0x1,
- STPF_USEAPPTHUMBNAILWHENACTIVE = 0x2,
- STPF_USEAPPPEEKALWAYS = 0x4,
- STPF_USEAPPPEEKWHENACTIVE = 0x8
-} STPFLAG;
-
-typedef enum THUMBBUTTONMASK
-{
- THB_BITMAP = 0x1,
- THB_ICON = 0x2,
- THB_TOOLTIP = 0x4,
- THB_FLAGS = 0x8
-} THUMBBUTTONMASK;
-
-typedef enum THUMBBUTTONFLAGS
-{
- THBF_ENABLED = 0,
- THBF_DISABLED = 0x1,
- THBF_DISMISSONCLICK = 0x2,
- THBF_NOBACKGROUND = 0x4,
- THBF_HIDDEN = 0x8,
- THBF_NONINTERACTIVE = 0x10
-} THUMBBUTTONFLAGS;
-
-typedef struct THUMBBUTTON
-{
- THUMBBUTTONMASK dwMask;
- UINT iId;
- UINT iBitmap;
- HICON hIcon;
- WCHAR szTip[260];
- THUMBBUTTONFLAGS dwFlags;
-} THUMBBUTTON;
-typedef struct THUMBBUTTON *LPTHUMBBUTTON;
-
-typedef enum TBPFLAG
-{
- TBPF_NOPROGRESS = 0,
- TBPF_INDETERMINATE = 0x1,
- TBPF_NORMAL = 0x2,
- TBPF_ERROR = 0x4,
- TBPF_PAUSED = 0x8
-} TBPFLAG;
-
-typedef enum KNOWNDESTCATEGORY
-{
- KDC_FREQUENT = 1,
- KDC_RECENT = (KDC_FREQUENT + 1)
-} KNOWNDESTCATEGORY;
-
-typedef enum _SIGDN
-{
- SIGDN_NORMALDISPLAY = 0,
- SIGDN_PARENTRELATIVEPARSING = (int) 0x80018001,
- SIGDN_DESKTOPABSOLUTEPARSING = (int) 0x80028000,
- SIGDN_PARENTRELATIVEEDITING = (int) 0x80031001,
- SIGDN_DESKTOPABSOLUTEEDITING = (int) 0x8004c000,
- SIGDN_FILESYSPATH = (int) 0x80058000,
- SIGDN_URL = (int) 0x80068000,
- SIGDN_PARENTRELATIVEFORADDRESSBAR = (int) 0x8007c001,
- SIGDN_PARENTRELATIVE = (int) 0x80080001
-} SIGDN;
-
-enum _SICHINTF
-{
- SICHINT_DISPLAY = 0,
- SICHINT_ALLFIELDS = (int) 0x80000000,
- SICHINT_CANONICAL = 0x10000000,
- SICHINT_TEST_FILESYSPATH_IF_NOT_EQUAL = 0x20000000
-};
-typedef DWORD SICHINTF;
-
-typedef enum APPDOCLISTTYPE
-{
- ADLT_RECENT = 0,
- ADLT_FREQUENT = (ADLT_RECENT + 1)
-} APPDOCLISTTYPE;
-
-typedef struct _tagpropertykey
-{
- GUID fmtid;
- DWORD pid;
-} PROPERTYKEY;
-
-#define REFPROPERTYKEY const PROPERTYKEY &
-
-typedef struct tagPROPVARIANT PROPVARIANT;
-#define REFPROPVARIANT const PROPVARIANT &
-
-
-#define DEFINE_PROPERTYKEY(name, l, w1, w2, b1, b2, b3, b4, b5, b6, b7, b8, pid) const PROPERTYKEY name \
- = { { l, w1, w2, { b1, b2, b3, b4, b5, b6, b7, b8 } }, pid }
-
-#define DEFINE_KNOWN_FOLDER(name, l, w1, w2, b1, b2, b3, b4, b5, b6, b7, b8) \
- extern const GUID DECLSPEC_SELECTANY name \
- = { l, w1, w2, { b1, b2, b3, b4, b5, b6, b7, b8 } }
-
-#define DEFINE_GUID_(n,l,w1,w2,b1,b2,b3,b4,b5,b6,b7,b8) const GUID n GUID_SECT = {l,w1,w2,{b1,b2,b3,b4,b5,b6,b7,b8}}
-
-typedef enum
-{
- KF_FLAG_DEFAULT = 0x00000000,
- KF_FLAG_CREATE = 0x00008000,
- KF_FLAG_DONT_VERIFY = 0x00004000,
- KF_FLAG_DONT_UNEXPAND = 0x00002000,
- KF_FLAG_NO_ALIAS = 0x00001000,
- KF_FLAG_INIT = 0x00000800,
- KF_FLAG_DEFAULT_PATH = 0x00000400,
- KF_FLAG_NOT_PARENT_RELATIVE = 0x00000200,
- KF_FLAG_SIMPLE_IDLIST = 0x00000100,
- KF_FLAG_ALIAS_ONLY = 0x80000000,
-} KNOWN_FOLDER_FLAG;
-
-typedef GUID KNOWNFOLDERID;
-#define REFKNOWNFOLDERID const KNOWNFOLDERID &
-
-//MIDL_INTERFACE("56FDF342-FD6D-11d0-958A-006097C9A090")
-DECLARE_INTERFACE_(ITaskbarList, IUnknown)
-{
- STDMETHOD (HrInit) (THIS) PURE;
- STDMETHOD (AddTab) (THIS_ HWND hwnd) PURE;
- STDMETHOD (DeleteTab) (THIS_ HWND hwnd) PURE;
- STDMETHOD (ActivateTab) (THIS_ HWND hwnd) PURE;
- STDMETHOD (SetActiveAlt) (THIS_ HWND hwnd) PURE;
-};
-typedef ITaskbarList *LPITaskbarList;
-
-//MIDL_INTERFACE("602D4995-B13A-429b-A66E-1935E44F4317")
-DECLARE_INTERFACE_(ITaskbarList2, ITaskbarList)
-{
- STDMETHOD (MarkFullscreenWindow) (THIS_ HWND hwnd, int fFullscreen) PURE;
-};
-typedef ITaskbarList2 *LPITaskbarList2;
-
-//MIDL_INTERFACE("ea1afb91-9e28-4b86-90e9-9e9f8a5eefaf")
-DECLARE_INTERFACE_(ITaskbarList3, ITaskbarList2)
-{
- STDMETHOD (SetProgressValue) (THIS_ HWND hwnd, ULONGLONG ullCompleted, ULONGLONG ullTotal) PURE;
- STDMETHOD (SetProgressState) (THIS_ HWND hwnd, TBPFLAG tbpFlags) PURE;
- STDMETHOD (RegisterTab) (THIS_ HWND hwndTab,HWND hwndMDI) PURE;
- STDMETHOD (UnregisterTab) (THIS_ HWND hwndTab) PURE;
- STDMETHOD (SetTabOrder) (THIS_ HWND hwndTab, HWND hwndInsertBefore) PURE;
- STDMETHOD (SetTabActive) (THIS_ HWND hwndTab, HWND hwndMDI, DWORD dwReserved) PURE;
- STDMETHOD (ThumbBarAddButtons) (THIS_ HWND hwnd, UINT cButtons, LPTHUMBBUTTON pButton) PURE;
- STDMETHOD (ThumbBarUpdateButtons) (THIS_ HWND hwnd, UINT cButtons, LPTHUMBBUTTON pButton) PURE;
- STDMETHOD (ThumbBarSetImageList) (THIS_ HWND hwnd, HIMAGELIST himl) PURE;
- STDMETHOD (SetOverlayIcon) (THIS_ HWND hwnd, HICON hIcon, LPCWSTR pszDescription) PURE;
- STDMETHOD (SetThumbnailTooltip) (THIS_ HWND hwnd, LPCWSTR pszTip) PURE;
- STDMETHOD (SetThumbnailClip) (THIS_ HWND hwnd, RECT *prcClip) PURE;
-};
-typedef ITaskbarList3 *LPITaskbarList3;
-
-//MIDL_INTERFACE("c43dc798-95d1-4bea-9030-bb99e2983a1a")
-DECLARE_INTERFACE_(ITaskbarList4, ITaskbarList3)
-{
- STDMETHOD (SetTabProperties) (HWND hwndTab, STPFLAG stpFlags) PURE;
-};
-typedef ITaskbarList4 *LPITaskbarList4;
-
-//MIDL_INTERFACE("92CA9DCD-5622-4bba-A805-5E9F541BD8C9")
-DECLARE_INTERFACE_(IObjectArray, IUnknown)
-{
- STDMETHOD (GetCount) (UINT *pcObjects) PURE;
- STDMETHOD (GetAt) (UINT uiIndex, REFIID riid, void **ppv) PURE;
-};
-typedef IObjectArray *LPIObjectArray;
-
-//MIDL_INTERFACE("6332debf-87b5-4670-90c0-5e57b408a49e")
-DECLARE_INTERFACE_(ICustomDestinationList, IUnknown)
-{
- STDMETHOD (SetAppID) (LPCWSTR pszAppID);
- STDMETHOD (BeginList) (UINT *pcMinSlots, REFIID riid, void **ppv) PURE;
- STDMETHOD (AppendCategory) (LPCWSTR pszCategory, IObjectArray *poa) PURE;
- STDMETHOD (AppendKnownCategory) (KNOWNDESTCATEGORY category) PURE;
- STDMETHOD (AddUserTasks) (IObjectArray *poa) PURE;
- STDMETHOD (CommitList) (void) PURE;
- STDMETHOD (GetRemovedDestinations) (REFIID riid, void **ppv) PURE;
- STDMETHOD (DeleteList) (LPCWSTR pszAppID) PURE;
- STDMETHOD (AbortList) (void) PURE;
-
-};
-typedef ICustomDestinationList *LPICustomDestinationList;
-
-//MIDL_INTERFACE("5632b1a4-e38a-400a-928a-d4cd63230295")
-DECLARE_INTERFACE_(IObjectCollection, IObjectArray)
-{
- STDMETHOD (AddObject) (IUnknown *punk) PURE;
- STDMETHOD (AddFromArray) (IObjectArray *poaSource)PURE;
- STDMETHOD (RemoveObjectAt) (UINT uiIndex) PURE;
- STDMETHOD (Clear) (void) PURE;
-};
-typedef IObjectCollection *LPIObjectCollection;
-
-//MIDL_INTERFACE("43826d1e-e718-42ee-bc55-a1e261c37bfe")
-DECLARE_INTERFACE_(IShellItem, IUnknown)
-{
- STDMETHOD (BindToHandler) (IBindCtx *pbc, REFGUID bhid, REFIID riid,void **ppv) PURE;
- STDMETHOD (GetParent) (IShellItem **ppsi) PURE;
- STDMETHOD (GetDisplayName) (SIGDN sigdnName, LPWSTR *ppszName) PURE;
- STDMETHOD (GetAttributes) (SFGAOF sfgaoMask, SFGAOF *psfgaoAttribs) PURE;
- STDMETHOD (Compare) (IShellItem *psi, SICHINTF hint, int *piOrder) PURE;
-};
-typedef IShellItem *LPIShellItem;
-
-//MIDL_INTERFACE("886d8eeb-8cf2-4446-8d02-cdba1dbdcf99")
-DECLARE_INTERFACE_(IPropertyStore, IUnknown)
-{
- STDMETHOD (GetCount) (DWORD *cProps) PURE;
- STDMETHOD (GetAt) (DWORD iProp, PROPERTYKEY *pkey) PURE;
- STDMETHOD (GetValue) (REFPROPERTYKEY key, PROPVARIANT *pv) PURE;
- STDMETHOD (SetValue) (REFPROPERTYKEY key, REFPROPVARIANT propvar) PURE;
- STDMETHOD (Commit) (void) PURE;
-};
-typedef IPropertyStore *LPIPropertyStore;
-
-//MIDL_INTERFACE("3c594f9f-9f30-47a1-979a-c9e83d3d0a06")
-DECLARE_INTERFACE_(IApplicationDocumentLists, IUnknown)
-{
- STDMETHOD (SetAppID) (LPCWSTR pszAppID) PURE;
- STDMETHOD (GetList) (APPDOCLISTTYPE listtype, UINT cItemsDesired, REFIID riid, void **ppv) PURE;
-};
-typedef IApplicationDocumentLists *LPIApplicationDocumentLists;
-
-//MIDL_INTERFACE("12337d35-94c6-48a0-bce7-6a9c69d4d600")
-DECLARE_INTERFACE_(IApplicationDestinations, IUnknown)
-{
- STDMETHOD (SetAppID) (LPCWSTR pszAppID) PURE;
- STDMETHOD (RemoveDestination) (IUnknown *punk) PURE;
- STDMETHOD (RemoveAllDestinations) (void) PURE;
-};
-typedef IApplicationDestinations *LPIApplicationDestinations;
-DEFINE_KNOWN_FOLDER(FOLDERID_Documents, 0xFDD39AD0, 0x238F, 0x46AF, 0xAD, 0xB4, 0x6C, 0x85, 0x48, 0x03, 0x69, 0xC7);
-
-DEFINE_PROPERTYKEY(PKEY_Title, 0xF29F85E0, 0x4FF9, 0x1068, 0xAB, 0x91, 0x08, 0x00, 0x2B, 0x27, 0xB3, 0xD9, 2);
-DEFINE_PROPERTYKEY(PKEY_AppUserModel_IsDestListSeparator, 0x9F4C2855, 0x9F79, 0x4B39, 0xA8, 0xD0, 0xE1, 0xD4, 0x2D, 0xE1, 0xD5, 0xF3, 6);
-
-DEFINE_GUID_(CLSID_DestinationList,0x77f10cf0,0x3db5,0x4966,0xb5,0x20,0xb7,0xc5,0x4f,0xd3,0x5e,0xd6);
-DEFINE_GUID_(CLSID_TaskbarList,0x56fdf344,0xfd6d,0x11d0,0x95,0x8a,0x0,0x60,0x97,0xc9,0xa0,0x90);
-DEFINE_GUID_(CLSID_EnumerableObjectCollection,0x2d3468c1,0x36a7,0x43b6,0xac,0x24,0xd3,0xf0,0x2f,0xd9,0x60,0x7a);
-DEFINE_GUID_(CLSID_ShellItem,0x9ac9fbe1,0xe0a2,0x4ad6,0xb4,0xee,0xe2,0x12,0x01,0x3e,0xa9,0x17);
-DEFINE_GUID_(CLSID_ApplicationDocumentLists,0x86bec222,0x30f2,0x47e0,0x9f,0x25,0x60,0xd1,0x1c,0xd7,0x5c,0x28);
-DEFINE_GUID_(CLSID_ApplicationDestinations,0x86c14003,0x4d6b,0x4ef3,0xa7,0xb4,0x05,0x06,0x66,0x3b,0x2e,0x68);
-
-DEFINE_GUID_(IID_ITaskbarList,0x56FDF342,0xFD6D,0x11d0,0x95,0x8A,0x00,0x60,0x97,0xC9,0xA0,0x90);
-DEFINE_GUID_(IID_ITaskbarList2,0x602D4995,0xB13A,0x429b,0xA6,0x6E,0x19,0x35,0xE4,0x4F,0x43,0x17);
-DEFINE_GUID_(IID_ITaskbarList3,0xea1afb91,0x9e28,0x4b86,0x90,0xE9,0x9e,0x9f,0x8a,0x5e,0xef,0xaf);
-DEFINE_GUID_(IID_ITaskbarList4,0xc43dc798,0x95d1,0x4bea,0x90,0x30,0xbb,0x99,0xe2,0x98,0x3a,0x1a);
-DEFINE_GUID_(IID_IObjectArray,0x92ca9dcd,0x5622,0x4bba,0xa8,0x05,0x5e,0x9f,0x54,0x1b,0xd8,0xc9);
-DEFINE_GUID_(IID_ICustomDestinationList,0x6332debf,0x87b5,0x4670,0x90,0xc0,0x5e,0x57,0xb4,0x08,0xa4,0x9e);
-DEFINE_GUID_(IID_IObjectCollection,0x5632b1a4,0xe38a,0x400a,0x92,0x8a,0xd4,0xcd,0x63,0x23,0x02,0x95);
-DEFINE_GUID_(IID_IShellItem,0x43826d1e,0xe718,0x42ee,0xbc,0x55,0xa1,0xe2,0x61,0xc3,0x7b,0xfe);
-DEFINE_GUID_(IID_IPropertyStore,0x886d8eeb,0x8cf2,0x4446,0x8d,0x02,0xcd,0xba,0x1d,0xbd,0xcf,0x99);
-DEFINE_GUID_(IID_IApplicationDocumentLists,0x3c594f9f,0x9f30,0x47a1,0x97,0x9a,0xc9,0xe8,0x3d,0x3d,0x0a,0x06);
-DEFINE_GUID_(IID_IApplicationDestinations,0x12337d35,0x94c6,0x48a0,0xbc,0xe7,0x6a,0x9c,0x69,0xd4,0xd6,0x00);
-
-extern "C"
-{
- typedef HRESULT (WINAPI *t_GetCurrentProcessExplicitAppUserModelID)(PWSTR* AppID);
- typedef HRESULT (WINAPI *t_SetCurrentProcessExplicitAppUserModelID)(PCWSTR AppID);
- typedef HRESULT (WINAPI *t_SHCreateItemInKnownFolder)(REFKNOWNFOLDERID kfid, DWORD dwKFFlags, PCWSTR pszItem, REFIID riid, void **ppv);
- typedef HRESULT (WINAPI *t_SHCreateItemFromParsingName)(PCWSTR pszPath, IBindCtx *pbc, REFIID riid, void **ppv);
-}
-
-WINOLEAPI PropVariantClear(PROPVARIANT* pvar);
-
-inline HRESULT InitPropVariantFromString(PCWSTR psz, PROPVARIANT *ppropvar)
-{
- ppropvar->vt = VT_LPWSTR;
- HRESULT hr = SHStrDupW(psz, &ppropvar->pwszVal);
- return hr;
-}
-
-inline HRESULT InitPropVariantFromBoolean(BOOL fVal, PROPVARIANT *ppropvar)
-{
- ppropvar->vt = VT_BOOL;
- ppropvar->boolVal = fVal ? VARIANT_TRUE : VARIANT_FALSE;
- return S_OK;
-}
-
-#endif //Q_OS_WIN32
-
-#endif // WIN7UTILS_H
+#ifndef WIN7UTILS_H
+#define WIN7UTILS_H
+#include <QtGlobal>
+
+#ifdef Q_OS_WIN32
+#include <shlobj.h>
+#include <shlwapi.h>
+#include <initguid.h>
+#include <objidl.h>
+#include <shellapi.h>
+//#include <ShObjIdl.h>
+
+DEFINE_PROPERTYKEY(PKEY_Title, 0xF29F85E0, 0x4FF9, 0x1068, 0xAB, 0x91, 0x08, 0x00, 0x2B, 0x27, 0xB3, 0xD9, 2);
+DEFINE_PROPERTYKEY(PKEY_AppUserModel_IsDestListSeparator, 0x9F4C2855, 0x9F79, 0x4B39, 0xA8, 0xD0, 0xE1, 0xD4, 0x2D, 0xE1, 0xD5, 0xF3, 6);
+
+extern "C"
+{
+ typedef HRESULT (WINAPI *t_GetCurrentProcessExplicitAppUserModelID)(PWSTR* AppID);
+ typedef HRESULT (WINAPI *t_SetCurrentProcessExplicitAppUserModelID)(PCWSTR AppID);
+ typedef HRESULT (WINAPI *t_SHCreateItemInKnownFolder)(REFKNOWNFOLDERID kfid, DWORD dwKFFlags, PCWSTR pszItem, REFIID riid, void **ppv);
+ typedef HRESULT (WINAPI *t_SHCreateItemFromParsingName)(PCWSTR pszPath, IBindCtx *pbc, REFIID riid, void **ppv);
+}
+
+WINOLEAPI PropVariantClear(PROPVARIANT* pvar);
+
+inline HRESULT InitPropVariantFromString(PCWSTR psz, PROPVARIANT *ppropvar)
+{
+ ppropvar->vt = VT_LPWSTR;
+ HRESULT hr = SHStrDupW(psz, &ppropvar->pwszVal);
+ return hr;
+}
+
+inline HRESULT InitPropVariantFromBoolean(BOOL fVal, PROPVARIANT *ppropvar)
+{
+ ppropvar->vt = VT_BOOL;
+ ppropvar->boolVal = fVal ? VARIANT_TRUE : VARIANT_FALSE;
+ return S_OK;
+}
+
+#endif //Q_OS_WIN32
+
+#endif // WIN7UTILS_H
diff --git a/tools/screenshotmanager.cpp b/tools/screenshotmanager.cpp
index 43786a9..508a972 100644
--- a/tools/screenshotmanager.cpp
+++ b/tools/screenshotmanager.cpp
@@ -1,154 +1,197 @@
-/*
- * 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 "screenshotmanager.h"
-#include "screenshot.h"
-#include "uploader.h"
-
-#include <QApplication>
-#include <QDateTime>
-#include <QDebug>
-#include <QDesktopServices>
-#include <QFile>
-#include <QSettings>
-#include <QtSql/QSqlDatabase>
-#include <QtSql/QSqlQuery>
-
-ScreenshotManager::ScreenshotManager(QObject *parent = 0) : QObject(parent)
-{
- QString historyPath;
-
- if (QFile::exists(qApp->applicationDirPath() + "/config.ini")) {
- mSettings = new QSettings(qApp->applicationDirPath() + QDir::separator() + "config.ini", QSettings::IniFormat);
- mPortableMode = true;
- historyPath = qApp->applicationDirPath() + QDir::separator() + "history.sqlite";
- }
- else {
- mSettings = new QSettings();
- mPortableMode = false;
- historyPath = QDesktopServices::storageLocation(QDesktopServices::DataLocation) + QDir::separator() + "history.sqlite";
- }
-
- // Creating the SQLite database.
- mHistory = QSqlDatabase::addDatabase("QSQLITE");
- mHistory.setDatabaseName(historyPath);
-
- if (mHistory.open()) {
- mHistory.exec("CREATE TABLE IF NOT EXISTS history (fileName text, URL text, deleteURL text, time integer)");
- }
-
- connect(Uploader::instance(), SIGNAL(done(QString, QString, QString)), this, SLOT(uploadDone(QString, QString, QString)));
-}
-
-ScreenshotManager::~ScreenshotManager()
-{
- delete mSettings;
-}
-
-int ScreenshotManager::activeCount() const
-{
- return mScreenshots.count();
-}
-
-bool ScreenshotManager::portableMode()
-{
- return mPortableMode;
-}
-
-void ScreenshotManager::saveHistory(QString fileName, QString url, QString deleteHash)
-{
- if (!mSettings->value("/options/history", true).toBool())
- return;
-
- if (!mHistory.isOpen())
- return;
-
- mHistory.exec(QString("INSERT INTO history (fileName, URL, deleteURL, time) VALUES('%1', '%2', '%3', %4)")
- .arg(fileName)
- .arg(url)
- .arg("http://imgur.com/delete/" + deleteHash)
- .arg(QDateTime::currentMSecsSinceEpoch())
- );
-}
-
-void ScreenshotManager::clearHistory()
-{
- if (mHistory.isOpen())
- mHistory.exec("DROP TABLE history");
-}
-
-//
-
-void ScreenshotManager::askConfirmation()
-{
- Screenshot* s = qobject_cast<Screenshot*>(sender());
- emit confirm(s);
-}
-
-void ScreenshotManager::cleanup()
-{
- Screenshot* screenshot = qobject_cast<Screenshot*>(sender());
- emit windowCleanup(screenshot->options());
-}
-
-void ScreenshotManager::finished()
-{
- Screenshot* screenshot = qobject_cast<Screenshot*>(sender());
- mScreenshots.removeOne(screenshot);
- screenshot->deleteLater();
-}
-
-void ScreenshotManager::take(Screenshot::Options &options)
-{
- Screenshot* newScreenshot = new Screenshot(this, options);
- mScreenshots.append(newScreenshot);
-
- connect(newScreenshot, SIGNAL(askConfirmation()), this, SLOT(askConfirmation()));
- connect(newScreenshot, SIGNAL(cleanup()) , this, SLOT(cleanup()));
- connect(newScreenshot, SIGNAL(finished()) , this, SLOT(finished()));
-
- newScreenshot->take();
-}
-
-void ScreenshotManager::uploadDone(QString fileName, QString url, QString deleteHash)
-{
- foreach (Screenshot* screenshot, mScreenshots) {
- if (screenshot->options().fileName == fileName
- || screenshot->unloadedFileName() == fileName) {
- screenshot->uploadDone(url);
-
- if (screenshot->options().file) {
- saveHistory(fileName, url, deleteHash);
- }
- else {
- saveHistory("", url, deleteHash);
- }
- }
- }
-}
-
-// Singleton
-ScreenshotManager* ScreenshotManager::mInstance = 0;
-
-ScreenshotManager *ScreenshotManager::instance()
-{
- if (!mInstance)
- mInstance = new ScreenshotManager();
-
- return mInstance;
-}
+/*
+ * 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 "screenshotmanager.h"
+#include "screenshot.h"
+#include "uploader.h"
+
+#include <QApplication>
+#include <QDateTime>
+#include <QDebug>
+#include <QDesktopServices>
+#include <QFile>
+#include <QSettings>
+#include <QtSql/QSqlDatabase>
+#include <QtSql/QSqlQuery>
+#include <QtSql/QSqlRecord>
+
+ScreenshotManager::ScreenshotManager(QObject *parent = 0) : QObject(parent)
+{
+ QString historyPath;
+
+ if (QFile::exists(qApp->applicationDirPath() + "/config.ini")) {
+ mSettings = new QSettings(qApp->applicationDirPath() + QDir::separator() + "config.ini", QSettings::IniFormat);
+ mPortableMode = true;
+ historyPath = qApp->applicationDirPath() + QDir::separator();
+ }
+ else {
+ mSettings = new QSettings();
+ mPortableMode = false;
+ historyPath = QDesktopServices::storageLocation(QDesktopServices::DataLocation) + QDir::separator();
+ }
+
+ // Creating the SQLite database.
+ mHistory = QSqlDatabase::addDatabase("QSQLITE");
+
+ QDir hp(historyPath);
+
+ if (!hp.exists())
+ hp.mkpath(historyPath);
+
+ mHistory.setDatabaseName(historyPath + "history.sqlite");
+
+ if (mHistory.open()) {
+ mHistory.exec("CREATE TABLE IF NOT EXISTS history (fileName text, URL text, deleteURL text, time integer)");
+ }
+
+ connect(Uploader::instance(), SIGNAL(done(QString, QString, QString)), this, SLOT(uploadDone(QString, QString, QString)));
+}
+
+ScreenshotManager::~ScreenshotManager()
+{
+ delete mSettings;
+}
+
+int ScreenshotManager::activeCount() const
+{
+ return mScreenshots.count();
+}
+
+bool ScreenshotManager::portableMode()
+{
+ return mPortableMode;
+}
+
+void ScreenshotManager::saveHistory(QString fileName, QString url, QString deleteHash)
+{
+ if (!mSettings->value("/options/history", true).toBool())
+ return;
+
+ if (!mHistory.isOpen())
+ return;
+
+ mHistory.exec(QString("INSERT INTO history (fileName, URL, deleteURL, time) VALUES('%1', '%2', '%3', %4)")
+ .arg(fileName)
+ .arg(url)
+ .arg("http://imgur.com/delete/" + deleteHash)
+ .arg(QDateTime::currentMSecsSinceEpoch())
+ );
+}
+
+void ScreenshotManager::updateHistory(QString fileName, QString url, QString deleteHash)
+{
+ if (!mSettings->value("/options/history", true).toBool())
+ return;
+
+ if (!mHistory.isOpen())
+ return;
+
+ QSqlQuery query = mHistory.exec(QString("SELECT fileName FROM history WHERE URL IS NOT NULL AND fileName = '%1'").arg(fileName));
+
+ if (query.record().count() > 0) {
+ // If we can find another entry for this filename with a valid URL, add another record (so as to not override a delete hash)
+ saveHistory(fileName, url, deleteHash);
+ }
+ else {
+ // Makes sure to only update the latest file, in case something weird happened with the files (deleted screenshots, etc). Though that might still happen in some edge cases that I'm too lazy to account for.
+ mHistory.exec(QString("UPDATE history SET URL = '%1', deleteURL = '%2', time = %3 WHERE fileName = '%4' LIMIT 1 ORDER BY time DESC")
+ .arg(url)
+ .arg("http://imgur.com/delete/" + deleteHash)
+ .arg(QDateTime::currentMSecsSinceEpoch())
+ .arg(fileName)
+ );
+ }
+}
+
+void ScreenshotManager::removeHistory(QString fileName, qint64 time)
+{
+ if (mHistory.isOpen())
+ mHistory.exec(QString("DELETE FROM history WHERE fileName = '%1' AND time = %3").arg(fileName).arg(time));
+}
+
+void ScreenshotManager::clearHistory()
+{
+ if (mHistory.isOpen())
+ mHistory.exec("DROP TABLE history");
+}
+
+//
+
+void ScreenshotManager::askConfirmation()
+{
+ Screenshot* s = qobject_cast<Screenshot*>(sender());
+ emit confirm(s);
+}
+
+void ScreenshotManager::cleanup()
+{
+ Screenshot* screenshot = qobject_cast<Screenshot*>(sender());
+ emit windowCleanup(screenshot->options());
+}
+
+void ScreenshotManager::finished()
+{
+ Screenshot* screenshot = qobject_cast<Screenshot*>(sender());
+ mScreenshots.removeOne(screenshot);
+ screenshot->deleteLater();
+}
+
+void ScreenshotManager::take(Screenshot::Options &options)
+{
+ Screenshot* newScreenshot = new Screenshot(this, options);
+ mScreenshots.append(newScreenshot);
+
+ connect(newScreenshot, SIGNAL(askConfirmation()), this, SLOT(askConfirmation()));
+ connect(newScreenshot, SIGNAL(cleanup()) , this, SLOT(cleanup()));
+ connect(newScreenshot, SIGNAL(finished()) , this, SLOT(finished()));
+
+ newScreenshot->take();
+}
+
+void ScreenshotManager::uploadDone(QString fileName, QString url, QString deleteHash)
+{
+ foreach (Screenshot* screenshot, mScreenshots) {
+ if (screenshot->options().fileName == fileName
+ || screenshot->unloadedFileName() == fileName) {
+ screenshot->uploadDone(url);
+
+ if (screenshot->options().file) {
+ saveHistory(fileName, url, deleteHash);
+ }
+ else {
+ saveHistory("", url, deleteHash);
+ }
+
+ return;
+ }
+ }
+
+ // If we get here, it's because the screenshot upload wasn't on the current screenshot list, which means it's a View History/Upload Later upload.
+ updateHistory(fileName, url, deleteHash);
+}
+
+// Singleton
+ScreenshotManager* ScreenshotManager::mInstance = 0;
+
+ScreenshotManager *ScreenshotManager::instance()
+{
+ if (!mInstance)
+ mInstance = new ScreenshotManager();
+
+ return mInstance;
+}
diff --git a/tools/screenshotmanager.h b/tools/screenshotmanager.h
index 9818416..9a75d9b 100644
--- a/tools/screenshotmanager.h
+++ b/tools/screenshotmanager.h
@@ -1,72 +1,74 @@
-/*
- * 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 SCREENSHOTMANAGER_H
-#define SCREENSHOTMANAGER_H
-
-#include <QObject>
-#include <QList>
-#include <QtSql/QSqlDatabase>
-
-#include "screenshot.h"
-
-class QSettings;
-class ScreenshotManager : public QObject
-{
- Q_OBJECT
-
-public:
- enum State
- {
- Idle = 0,
- Busy = 1,
- Disabled = 2
- };
-
-public:
- ScreenshotManager(QObject *parent);
- ~ScreenshotManager();
- static ScreenshotManager *instance();
-
- int activeCount() const;
- bool portableMode();
- void saveHistory(QString fileName, QString url = "", QString deleteHash = "");
- void clearHistory();
- QSettings *settings() const { return mSettings; }
- QSqlDatabase &history() { return mHistory; }
-
-public slots:
- void askConfirmation();
- void cleanup();
- void finished();
- void take(Screenshot::Options &options);
- void uploadDone(QString fileName, QString url, QString deleteHash);
-
-signals:
- void confirm(Screenshot* screenshot);
- void windowCleanup(Screenshot::Options &options);
-
-private:
- static ScreenshotManager* mInstance;
- QList<Screenshot*> mScreenshots;
- QSettings *mSettings;
- QSqlDatabase mHistory;
- bool mPortableMode;
-};
-
-#endif // SCREENSHOTMANAGER_H
+/*
+ * 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 SCREENSHOTMANAGER_H
+#define SCREENSHOTMANAGER_H
+
+#include <QObject>
+#include <QList>
+#include <QtSql/QSqlDatabase>
+
+#include "screenshot.h"
+
+class QSettings;
+class ScreenshotManager : public QObject
+{
+ Q_OBJECT
+
+public:
+ enum State
+ {
+ Idle = 0,
+ Busy = 1,
+ Disabled = 2
+ };
+
+public:
+ ScreenshotManager(QObject *parent);
+ ~ScreenshotManager();
+ static ScreenshotManager *instance();
+
+ int activeCount() const;
+ bool portableMode();
+ void saveHistory(QString fileName, QString url = "", QString deleteHash = "");
+ void updateHistory(QString fileName, QString url, QString deleteHash);
+ void removeHistory(QString fileName, qint64 time);
+ void clearHistory();
+ QSettings *settings() const { return mSettings; }
+ QSqlDatabase &history() { return mHistory; }
+
+public slots:
+ void askConfirmation();
+ void cleanup();
+ void finished();
+ void take(Screenshot::Options &options);
+ void uploadDone(QString fileName, QString url, QString deleteHash);
+
+signals:
+ void confirm(Screenshot* screenshot);
+ void windowCleanup(Screenshot::Options &options);
+
+private:
+ static ScreenshotManager* mInstance;
+ QList<Screenshot*> mScreenshots;
+ QSettings *mSettings;
+ QSqlDatabase mHistory;
+ bool mPortableMode;
+};
+
+#endif // SCREENSHOTMANAGER_H
diff --git a/tools/windowpicker.cpp b/tools/windowpicker.cpp
index 92fa725..8bfcc43 100644
--- a/tools/windowpicker.cpp
+++ b/tools/windowpicker.cpp
@@ -1,304 +1,304 @@
-/*
- * 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 <QLabel>
-#include <QMouseEvent>
-#include <QPushButton>
-#include <QRubberBand>
-#include <QRubberBand>
-#include <QVBoxLayout>
-#include <QWidget>
-
-#include <QDebug>
-
-#include "windowpicker.h"
-#include "os.h"
-
-#if defined(Q_OS_WIN)
- #include <windows.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
-
-WindowPicker::WindowPicker() : QWidget(0), mCrosshair(":/icons/picker"), mWindowLabel(0), mTaken(false)
-{
-#if defined(Q_OS_WIN)
- setWindowFlags(Qt::SplashScreen | Qt::WindowStaysOnTopHint);
-#elif defined(Q_WS_X11)
- setWindowFlags(Qt::WindowStaysOnTopHint);
-#endif
-
- setWindowTitle(tr("Lightscreen Window Picker"));
- setStyleSheet("QWidget { color: #000; } #frame { padding: 7px 10px; border: 1px solid #898c95; background-color: qlineargradient(spread:pad, x1:1, y1:1, x2:0.988636, y2:0.608, stop:0 rgba(235, 235, 235, 255), stop:1 rgba(255, 255, 255, 255)); border-radius: 8px; }");
-
- QLabel *helpLabel = new QLabel(tr("Grab the window picker by clicking and holding down the mouse button, then drag it to the window of your choice and release it to capture."), this);
- helpLabel->setMinimumWidth(400);
- helpLabel->setMaximumWidth(400);
- helpLabel->setWordWrap(true);
-
- mWindowIcon = new QLabel(this);
- mWindowIcon->setMinimumSize(22, 22);
- mWindowIcon->setMaximumSize(22, 22);
- mWindowIcon->setScaledContents(true);
-
- mWindowLabel = new QLabel(tr(" - Start dragging to select windows"), this);
- mWindowLabel->setStyleSheet("font-weight: bold");
-
- mCrosshairLabel = new QLabel(this);
- mCrosshairLabel->setAlignment(Qt::AlignHCenter);
- mCrosshairLabel->setPixmap(mCrosshair);
-
- QPushButton *closeButton = new QPushButton(tr("Close"));
- connect(closeButton, SIGNAL(clicked()), this, SLOT(close()));
-
- QHBoxLayout *windowLayout = new QHBoxLayout;
- windowLayout->addWidget(mWindowIcon);
- windowLayout->addWidget(mWindowLabel);
- windowLayout->setMargin(0);
-
- QHBoxLayout *buttonLayout = new QHBoxLayout;
- buttonLayout->addStretch(0);
- buttonLayout->addWidget(closeButton);
- buttonLayout->setMargin(0);
-
- QHBoxLayout *crosshairLayout = new QHBoxLayout;
- crosshairLayout->addStretch(0);
- crosshairLayout->addWidget(mCrosshairLabel);
- crosshairLayout->addStretch(0);
- crosshairLayout->setMargin(0);
-
- QVBoxLayout *fl = new QVBoxLayout;
- fl->addWidget(helpLabel);
- fl->addLayout(windowLayout);
- fl->addLayout(crosshairLayout);
- fl->addLayout(buttonLayout);
- fl->setMargin(0);
-
- QFrame *frame = new QFrame(this);
- frame->setObjectName("frame");
- frame->setLayout(fl);
-
- QVBoxLayout *l = new QVBoxLayout;
- l->setMargin(0);
- l->addWidget(frame);
-
- setLayout(l);
-
- resize(sizeHint());
- move(QApplication::desktop()->screenGeometry(QApplication::desktop()->screenNumber(QCursor::pos())).center()-QPoint(width()/2, height()/2));
- show();
-}
-
-WindowPicker::~WindowPicker() {
- qApp->restoreOverrideCursor();
-}
-
-void WindowPicker::cancel() {
- mWindowIcon->setPixmap(QPixmap());
- mCrosshairLabel->setPixmap(mCrosshair);
- qApp->restoreOverrideCursor();
-}
-
-void WindowPicker::closeEvent(QCloseEvent*)
-{
- if (!mTaken)
- emit pixmap(QPixmap());
-
- qApp->restoreOverrideCursor();
- deleteLater();
-}
-
-void WindowPicker::mouseMoveEvent(QMouseEvent *event)
-{
- QString windowName;
-
-#if defined(Q_OS_WIN)
- POINT mousePos;
- mousePos.x = event->globalX();
- mousePos.y = event->globalY();
-
- HWND cWindow = GetAncestor(WindowFromPoint(mousePos), GA_ROOT);
-
- mCurrentWindow = cWindow;
-
- if (mCurrentWindow == winId()) {
- mWindowIcon->setPixmap(QPixmap());
- mWindowLabel->setText("");
- return;
- }
-
- // Text
- WCHAR str[60];
- HICON icon;
-
- ::GetWindowText(mCurrentWindow, str, 60);
- windowName = QString::fromWCharArray(str);
- ///
-
- // Retrieving the application icon
- icon = (HICON)::GetClassLong(mCurrentWindow, GCL_HICON);
-
- if (icon != NULL) {
- mWindowIcon->setPixmap(QPixmap::fromWinHICON(icon));
- }
- else {
- mWindowIcon->setPixmap(QPixmap());
- }
-#elif defined(Q_WS_X11)
- Window cWindow = os::windowUnderCursor(false);
-
- if (cWindow == mCurrentWindow) {
- return;
- }
-
- mCurrentWindow = cWindow;
-
- if (mCurrentWindow == winId()) {
- mWindowIcon->setPixmap(QPixmap());
- mWindowLabel->setText("");
- return;
- }
-
- // Getting the window name property.
- XTextProperty tp;
- char **text;
- int count;
-
- if (XGetTextProperty(QX11Info::display(), cWindow, &tp, XA_WM_NAME) != 0 && tp.value != NULL ) {
- if (tp.encoding == XA_STRING) {
- windowName = QString::fromLocal8Bit((const char*) tp.value);
- }
- else if (XmbTextPropertyToTextList( QX11Info::display(), &tp, &text, &count) == Success &&
- text != NULL && count > 0) {
- windowName = QString::fromLocal8Bit(text[0]);
- XFreeStringList(text);
- }
-
- XFree(tp.value);
- }
-
- // Retrieving the _NET_WM_ICON property.
- Atom type_ret = None;
- unsigned char *data = 0;
- int format = 0;
- unsigned long n = 0;
- unsigned long extra = 0;
- int width = 0;
- int height = 0;
-
- Atom _net_wm_icon = XInternAtom(QX11Info::display(), "_NET_WM_ICON", False);
-
- if (XGetWindowProperty(QX11Info::display(), cWindow, _net_wm_icon, 0, 1, False,
- XA_CARDINAL, &type_ret, &format, &n, &extra, (unsigned char **)&data) == Success && data)
- {
- width = data[0];
- XFree(data);
- }
-
- if (XGetWindowProperty(QX11Info::display(), cWindow, _net_wm_icon, 1, 1, False,
- XA_CARDINAL, &type_ret, &format, &n, &extra, (unsigned char **)&data) == Success && data)
- {
- height = data[0];
- XFree(data);
- }
-
- if (XGetWindowProperty(QX11Info::display(), cWindow, _net_wm_icon, 2, width*height, False,
- XA_CARDINAL, &type_ret, &format, &n, &extra, (unsigned char **)&data) == Success && data)
- {
- QImage img(data, width, height, QImage::Format_ARGB32);
- mWindowIcon->setPixmap(QPixmap::fromImage(img));
- XFree(data);
- }
- else {
- mWindowIcon->setPixmap(QPixmap());
- }
-
-#endif
-
- QString windowText;
-
- if (!mWindowIcon->pixmap()) {
- windowText = QString(" - %1").arg(windowName);
- }
- else {
- windowText = windowName;
- }
-
- if (windowText == " - ") {
- mWindowLabel->setText("");
- return;
- }
-
- if (windowText.length() == 62) {
- mWindowLabel->setText(windowText + "...");
- }
- else {
- mWindowLabel->setText(windowText);
- }
-}
-
-void WindowPicker::mousePressEvent(QMouseEvent *event)
-{
- qApp->setOverrideCursor(QCursor(mCrosshair));
- mCrosshairLabel->setMinimumWidth(mCrosshairLabel->width());
- mCrosshairLabel->setMinimumHeight(mCrosshairLabel->height());
- mCrosshairLabel->setPixmap(QPixmap());
- QWidget::mousePressEvent(event);
-}
-
-void WindowPicker::mouseReleaseEvent(QMouseEvent *event)
-{
- if (event->button() == Qt::LeftButton) {
-#if defined(Q_OS_WIN)
- POINT mousePos;
- mousePos.x = event->globalX();
- mousePos.y = event->globalY();
-
- HWND window = GetAncestor(WindowFromPoint(mousePos), GA_ROOT);
-#elif defined(Q_WS_X11)
- Window window = os::windowUnderCursor(false);
-#endif
-
- if (window == winId()) {
- cancel();
- return;
- }
-
- mTaken = true;
-
- setWindowFlags(windowFlags() ^ Qt::WindowStaysOnTopHint);
- close();
-
-#ifdef Q_WS_X11
- emit pixmap(QPixmap::grabWindow(mCurrentWindow));
-#else
- emit pixmap(os::grabWindow(window));
-#endif
-
- return;
- }
-
- close();
-}
-
+/*
+ * 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 <QLabel>
+#include <QMouseEvent>
+#include <QPushButton>
+#include <QRubberBand>
+#include <QRubberBand>
+#include <QVBoxLayout>
+#include <QWidget>
+
+#include <QDebug>
+
+#include "windowpicker.h"
+#include "os.h"
+
+#if defined(Q_OS_WIN)
+ #include <windows.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
+
+WindowPicker::WindowPicker() : QWidget(0), mCrosshair(":/icons/picker"), mWindowLabel(0), mTaken(false)
+{
+#if defined(Q_OS_WIN)
+ setWindowFlags(Qt::SplashScreen | Qt::WindowStaysOnTopHint);
+#elif defined(Q_WS_X11)
+ setWindowFlags(Qt::WindowStaysOnTopHint);
+#endif
+
+ setWindowTitle(tr("Lightscreen Window Picker"));
+ setStyleSheet("QWidget { color: #000; } #frame { padding: 7px 10px; border: 1px solid #898c95; background-color: qlineargradient(spread:pad, x1:1, y1:1, x2:0.988636, y2:0.608, stop:0 rgba(235, 235, 235, 255), stop:1 rgba(255, 255, 255, 255)); border-radius: 8px; }");
+
+ QLabel *helpLabel = new QLabel(tr("Grab the window picker by clicking and holding down the mouse button, then drag it to the window of your choice and release it to capture."), this);
+ helpLabel->setMinimumWidth(400);
+ helpLabel->setMaximumWidth(400);
+ helpLabel->setWordWrap(true);
+
+ mWindowIcon = new QLabel(this);
+ mWindowIcon->setMinimumSize(22, 22);
+ mWindowIcon->setMaximumSize(22, 22);
+ mWindowIcon->setScaledContents(true);
+
+ mWindowLabel = new QLabel(tr(" - Start dragging to select windows"), this);
+ mWindowLabel->setStyleSheet("font-weight: bold");
+
+ mCrosshairLabel = new QLabel(this);
+ mCrosshairLabel->setAlignment(Qt::AlignHCenter);
+ mCrosshairLabel->setPixmap(mCrosshair);
+
+ QPushButton *closeButton = new QPushButton(tr("Close"));
+ connect(closeButton, SIGNAL(clicked()), this, SLOT(close()));
+
+ QHBoxLayout *windowLayout = new QHBoxLayout;
+ windowLayout->addWidget(mWindowIcon);
+ windowLayout->addWidget(mWindowLabel);
+ windowLayout->setMargin(0);
+
+ QHBoxLayout *buttonLayout = new QHBoxLayout;
+ buttonLayout->addStretch(0);
+ buttonLayout->addWidget(closeButton);
+ buttonLayout->setMargin(0);
+
+ QHBoxLayout *crosshairLayout = new QHBoxLayout;
+ crosshairLayout->addStretch(0);
+ crosshairLayout->addWidget(mCrosshairLabel);
+ crosshairLayout->addStretch(0);
+ crosshairLayout->setMargin(0);
+
+ QVBoxLayout *fl = new QVBoxLayout;
+ fl->addWidget(helpLabel);
+ fl->addLayout(windowLayout);
+ fl->addLayout(crosshairLayout);
+ fl->addLayout(buttonLayout);
+ fl->setMargin(0);
+
+ QFrame *frame = new QFrame(this);
+ frame->setObjectName("frame");
+ frame->setLayout(fl);
+
+ QVBoxLayout *l = new QVBoxLayout;
+ l->setMargin(0);
+ l->addWidget(frame);
+
+ setLayout(l);
+
+ resize(sizeHint());
+ move(QApplication::desktop()->screenGeometry(QApplication::desktop()->screenNumber(QCursor::pos())).center()-QPoint(width()/2, height()/2));
+ show();
+}
+
+WindowPicker::~WindowPicker() {
+ qApp->restoreOverrideCursor();
+}
+
+void WindowPicker::cancel() {
+ mWindowIcon->setPixmap(QPixmap());
+ mCrosshairLabel->setPixmap(mCrosshair);
+ qApp->restoreOverrideCursor();
+}
+
+void WindowPicker::closeEvent(QCloseEvent*)
+{
+ if (!mTaken)
+ emit pixmap(QPixmap());
+
+ qApp->restoreOverrideCursor();
+ deleteLater();
+}
+
+void WindowPicker::mouseMoveEvent(QMouseEvent *event)
+{
+ QString windowName;
+
+#if defined(Q_OS_WIN)
+ POINT mousePos;
+ mousePos.x = event->globalX();
+ mousePos.y = event->globalY();
+
+ HWND cWindow = GetAncestor(WindowFromPoint(mousePos), GA_ROOT);
+
+ mCurrentWindow = (WId) cWindow;
+
+ if (mCurrentWindow == winId()) {
+ mWindowIcon->setPixmap(QPixmap());
+ mWindowLabel->setText("");
+ return;
+ }
+
+ // Text
+ WCHAR str[60];
+ HICON icon;
+
+ ::GetWindowText((HWND)mCurrentWindow, str, 60);
+ windowName = QString::fromWCharArray(str);
+ ///
+
+ // Retrieving the application icon
+ icon = (HICON)::GetClassLong((HWND)mCurrentWindow, GCL_HICON);
+
+ if (icon != NULL) {
+ mWindowIcon->setPixmap(QPixmap::fromWinHICON(icon));
+ }
+ else {
+ mWindowIcon->setPixmap(QPixmap());
+ }
+#elif defined(Q_WS_X11)
+ Window cWindow = os::windowUnderCursor(false);
+
+ if (cWindow == mCurrentWindow) {
+ return;
+ }
+
+ mCurrentWindow = cWindow;
+
+ if (mCurrentWindow == winId()) {
+ mWindowIcon->setPixmap(QPixmap());
+ mWindowLabel->setText("");
+ return;
+ }
+
+ // Getting the window name property.
+ XTextProperty tp;
+ char **text;
+ int count;
+
+ if (XGetTextProperty(QX11Info::display(), cWindow, &tp, XA_WM_NAME) != 0 && tp.value != NULL ) {
+ if (tp.encoding == XA_STRING) {
+ windowName = QString::fromLocal8Bit((const char*) tp.value);
+ }
+ else if (XmbTextPropertyToTextList( QX11Info::display(), &tp, &text, &count) == Success &&
+ text != NULL && count > 0) {
+ windowName = QString::fromLocal8Bit(text[0]);
+ XFreeStringList(text);
+ }
+
+ XFree(tp.value);
+ }
+
+ // Retrieving the _NET_WM_ICON property.
+ Atom type_ret = None;
+ unsigned char *data = 0;
+ int format = 0;
+ unsigned long n = 0;
+ unsigned long extra = 0;
+ int width = 0;
+ int height = 0;
+
+ Atom _net_wm_icon = XInternAtom(QX11Info::display(), "_NET_WM_ICON", False);
+
+ if (XGetWindowProperty(QX11Info::display(), cWindow, _net_wm_icon, 0, 1, False,
+ XA_CARDINAL, &type_ret, &format, &n, &extra, (unsigned char **)&data) == Success && data)
+ {
+ width = data[0];
+ XFree(data);
+ }
+
+ if (XGetWindowProperty(QX11Info::display(), cWindow, _net_wm_icon, 1, 1, False,
+ XA_CARDINAL, &type_ret, &format, &n, &extra, (unsigned char **)&data) == Success && data)
+ {
+ height = data[0];
+ XFree(data);
+ }
+
+ if (XGetWindowProperty(QX11Info::display(), cWindow, _net_wm_icon, 2, width*height, False,
+ XA_CARDINAL, &type_ret, &format, &n, &extra, (unsigned char **)&data) == Success && data)
+ {
+ QImage img(data, width, height, QImage::Format_ARGB32);
+ mWindowIcon->setPixmap(QPixmap::fromImage(img));
+ XFree(data);
+ }
+ else {
+ mWindowIcon->setPixmap(QPixmap());
+ }
+
+#endif
+
+ QString windowText;
+
+ if (!mWindowIcon->pixmap()) {
+ windowText = QString(" - %1").arg(windowName);
+ }
+ else {
+ windowText = windowName;
+ }
+
+ if (windowText == " - ") {
+ mWindowLabel->setText("");
+ return;
+ }
+
+ if (windowText.length() == 62) {
+ mWindowLabel->setText(windowText + "...");
+ }
+ else {
+ mWindowLabel->setText(windowText);
+ }
+}
+
+void WindowPicker::mousePressEvent(QMouseEvent *event)
+{
+ qApp->setOverrideCursor(QCursor(mCrosshair));
+ mCrosshairLabel->setMinimumWidth(mCrosshairLabel->width());
+ mCrosshairLabel->setMinimumHeight(mCrosshairLabel->height());
+ mCrosshairLabel->setPixmap(QPixmap());
+ QWidget::mousePressEvent(event);
+}
+
+void WindowPicker::mouseReleaseEvent(QMouseEvent *event)
+{
+ if (event->button() == Qt::LeftButton) {
+#if defined(Q_OS_WIN)
+ POINT mousePos;
+ mousePos.x = event->globalX();
+ mousePos.y = event->globalY();
+
+ HWND window = GetAncestor(WindowFromPoint(mousePos), GA_ROOT);
+#elif defined(Q_WS_X11)
+ Window window = os::windowUnderCursor(false);
+#endif
+
+ if (window == (HWND)winId()) {
+ cancel();
+ return;
+ }
+
+ mTaken = true;
+
+ setWindowFlags(windowFlags() ^ Qt::WindowStaysOnTopHint);
+ close();
+
+#ifdef Q_WS_X11
+ emit pixmap(QPixmap::grabWindow(mCurrentWindow));
+#else
+ emit pixmap(os::grabWindow((WId)window));
+#endif
+
+ return;
+ }
+
+ close();
+}
+

File Metadata

Mime Type
text/x-diff
Expires
Wed, Jun 17, 9:29 PM (1 w, 5 d ago)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
70192
Default Alt Text
(342 KB)

Event Timeline