Page MenuHomePhabricator (Chris)

No OneTemporary

Authored By
Unknown
Size
144 KB
Referenced Files
None
Subscribers
None
diff --git a/dialogs/previewdialog.cpp b/dialogs/previewdialog.cpp
index 9bf0ef0..83a2cca 100644
--- a/dialogs/previewdialog.cpp
+++ b/dialogs/previewdialog.cpp
@@ -1,366 +1,365 @@
/*
* Copyright (C) 2011 Christian Kaiser
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*/
#include "previewdialog.h"
#include "screenshotdialog.h"
#include "../tools/screenshot.h"
#include "../tools/screenshotmanager.h"
#include "../tools/os.h"
#include <QApplication>
#include <QObject>
#include <QList>
#include <QHBoxLayout>
#include <QIcon>
#include <QPushButton>
#include <QPalette>
#include <QDesktopWidget>
#include <QGraphicsDropShadowEffect>
#include <QLabel>
#include <QStackedLayout>
#include <QSettings>
#include <QToolButton>
#include <QMenu>
#include <QDebug>
PreviewDialog::PreviewDialog(QWidget *parent) :
QDialog(parent), mAutoclose(0)
{
setWindowFlags(Qt::Tool | Qt::WindowStaysOnTopHint);
os::aeroGlass(this);
setWindowTitle("Screenshot Preview");
QSettings *settings = ScreenshotManager::instance()->settings();
mSize = settings->value("options/previewSize", 300).toInt();
mPosition = settings->value("options/previewPosition", 3).toInt();
if (settings->value("options/previewAutoclose", false).toBool()) {
mAutoclose = settings->value("options/previewAutocloseTime").toInt();
mAutocloseReset = mAutoclose;
mAutocloseAction = settings->value("options/previewAutocloseAction").toInt();
}
QHBoxLayout *l = new QHBoxLayout;
mStack = new QStackedLayout;
connect(mStack, SIGNAL(currentChanged(int)), this, SLOT(indexChanged(int)));
mPrevButton = new QPushButton(QIcon(":/icons/arrow-left"), "", this);
connect(mPrevButton, SIGNAL(clicked()), this, SLOT(previous()));
mNextButton = new QPushButton(QIcon(":/icons/arrow-right"), "", this);
connect(mNextButton, SIGNAL(clicked()), this, SLOT(next()));
mPrevButton->setCursor(Qt::PointingHandCursor);
mPrevButton->setFlat(true);
mPrevButton->setGraphicsEffect(os::shadow());
mPrevButton->setIconSize(QSize(24, 24));
mPrevButton->setVisible(false);
mNextButton->setCursor(Qt::PointingHandCursor);
mNextButton->setFlat(true);
mNextButton->setGraphicsEffect(os::shadow());
mNextButton->setIconSize(QSize(24, 24));
mNextButton->setVisible(false);
l->addWidget(mPrevButton);
l->addLayout(mStack);
l->addWidget(mNextButton);
l->setMargin(0);
l->setContentsMargins(6, 6, 6, 6);
mStack->setMargin(0);
setMaximumHeight(mSize);
setLayout(l);
if (mAutoclose) {
startTimer(1000);
}
}
void PreviewDialog::add(Screenshot *screenshot)
{
if (!isVisible()) {
show();
}
if (mAutoclose) {
mAutoclose = mAutocloseReset;
}
QLabel *label = new QLabel(this);
label->setGraphicsEffect(os::shadow());
bool small = false;
connect(label, SIGNAL(destroyed()), screenshot, SLOT(discard()));
QSize size = screenshot->pixmap().size();
if (size.width() > mSize || size.height() > mSize) {
size.scale(mSize, mSize, Qt::KeepAspectRatio);
}
else {
small = true;
}
QPixmap thumbnail = screenshot->pixmap().scaled(size, Qt::KeepAspectRatio, Qt::SmoothTransformation);
label->setPixmap(thumbnail);
thumbnail = QPixmap();
label->setAlignment(Qt::AlignCenter);
if (size.height() < 120) {
label->setMinimumHeight(120);
}
if (size.width() < 140) {
label->setMinimumWidth(140);
}
label->resize(size);
QToolButton *confirmPushButton = new QToolButton(label);
QPushButton *discardPushButton = new QPushButton(QIcon(":/icons/no") , "", label);
QPushButton *enlargePushButton = new QPushButton(QIcon(":/icons/zoom.in"), "", label);
confirmPushButton->setIcon(QIcon(":/icons/yes"));
confirmPushButton->setIconSize(QSize(24, 24));
confirmPushButton->setCursor(Qt::PointingHandCursor);
confirmPushButton->setGraphicsEffect(os::shadow());
if (!ScreenshotManager::instance()->settings()->value("options/uploadAuto").toBool()) {
QMenu *confirmMenu = new QMenu(confirmPushButton);
confirmMenu->setObjectName("confirmMenu");
QAction *uploadAction = new QAction(QIcon(":/icons/imgur"), tr("Upload"), confirmPushButton);
connect(uploadAction, SIGNAL(triggered()), screenshot, SLOT(confirm()));
connect(uploadAction, SIGNAL(triggered()), parent(), SLOT(uploadLast()));
connect(uploadAction, SIGNAL(triggered()), this, SLOT(closePreview()));
confirmMenu->addAction(uploadAction);
confirmPushButton->setMenu(confirmMenu);
confirmPushButton->setPopupMode(QToolButton::MenuButtonPopup);
}
confirmPushButton->setAutoRaise(true);
confirmPushButton->setVisible(false);
discardPushButton->setIconSize(QSize(24, 24));
discardPushButton->setCursor(Qt::PointingHandCursor);
discardPushButton->setGraphicsEffect(os::shadow());
discardPushButton->setFlat(true);
discardPushButton->setVisible(false);
enlargePushButton->setIconSize(QSize(22, 22));
enlargePushButton->setCursor(Qt::PointingHandCursor);
enlargePushButton->setGraphicsEffect(os::shadow());
enlargePushButton->setFlat(true);
enlargePushButton->setVisible(false);
enlargePushButton->setDisabled(small);
connect(this, SIGNAL(acceptAll()), confirmPushButton, SLOT(click()));
connect(this, SIGNAL(rejectAll()), discardPushButton, SLOT(click()));
connect(confirmPushButton, SIGNAL(clicked()), screenshot, SLOT(confirm()));
connect(confirmPushButton, SIGNAL(clicked()), this, SLOT(closePreview()));
connect(discardPushButton, SIGNAL(clicked()), screenshot, SLOT(discard()));
connect(discardPushButton, SIGNAL(clicked()), this, SLOT(closePreview()));
connect(enlargePushButton, SIGNAL(clicked()), this, SLOT(enlargePreview()));
QHBoxLayout *wlayout = new QHBoxLayout;
wlayout->addWidget(confirmPushButton);
wlayout->addStretch();
wlayout->addWidget(enlargePushButton);
wlayout->addStretch();
wlayout->addWidget(discardPushButton);
wlayout->setMargin(0);
QVBoxLayout *wl = new QVBoxLayout;
wl->addStretch();
wl->addLayout(wlayout);
wl->setMargin(0);
label->setLayout(wl);
mStack->addWidget(label);
mStack->setCurrentIndex(mStack->count()-1);
mNextButton->setEnabled(false);
if (mStack->count() >= 2 && !mNextButton->isVisible()) {
mNextButton->setVisible(true);
mPrevButton->setVisible(true);
}
relocate();
}
int PreviewDialog::count() const
{
return mStack->count();
}
void PreviewDialog::relocate()
{
updateGeometry();
resize(minimumSizeHint());
+ QApplication::sendEvent(this, new QEvent(QEvent::Enter)); // Ensures the buttons are visible.
QPoint where;
switch (mPosition)
{
case 0:
where = QApplication::desktop()->availableGeometry(this).topLeft();
break;
case 1:
where = QApplication::desktop()->availableGeometry(this).topRight();
where.setX(where.x() - frameGeometry().width());
break;
case 2:
where = QApplication::desktop()->availableGeometry(this).bottomLeft();
where.setY(where.y() - frameGeometry().height());
break;
case 3:
default:
where = QApplication::desktop()->availableGeometry(this).bottomRight();
where.setX(where.x() - frameGeometry().width());
where.setY(where.y() - frameGeometry().height());
break;
}
move(where);
}
void PreviewDialog::closePreview()
{
QWidget *widget = mStack->currentWidget();
mStack->removeWidget(widget);
widget->deleteLater();
if (mStack->count() == 0) {
close();
}
else {
relocate();
}
}
void PreviewDialog::indexChanged(int i)
{
if (i == mStack->count()-1) {
mNextButton->setEnabled(false);
mPrevButton->setEnabled(true);
}
if (i == 0 && mStack->count() > 1) {
mNextButton->setEnabled(true);
mPrevButton->setEnabled(false);
}
if (i != 0 && i != mStack->count()-1) {
mNextButton->setEnabled(true);
mPrevButton->setEnabled(true);
}
if (mStack->count() < 2) {
mNextButton->setEnabled(false);
mPrevButton->setEnabled(false);
}
if (mStack->widget(i)) {
mStack->widget(i)->setFocus();
}
}
void PreviewDialog::previous()
{
mStack->setCurrentIndex(mStack->currentIndex()-1);
relocate();
- QApplication::sendEvent(this, new QEvent(QEvent::Enter)); // Ensures the buttons are visible.
}
void PreviewDialog::next()
{
mStack->setCurrentIndex(mStack->currentIndex()+1);
relocate();
- QApplication::sendEvent(this, new QEvent(QEvent::Enter));
}
void PreviewDialog::enlargePreview()
{
Screenshot *screenshot = qobject_cast<Screenshot*>(ScreenshotManager::instance()->children().at(mStack->currentIndex()));
if (screenshot) {
new ScreenshotDialog(screenshot, this);
}
}
bool PreviewDialog::event(QEvent *event)
{
if ((event->type() == QEvent::Enter || event->type() == QEvent::Leave)
&& mStack->currentWidget())
{
foreach (QObject *child, mStack->currentWidget()->children()) {
QWidget *widget = qobject_cast<QWidget*>(child);
if (widget) {
// Lets avoid disappearing buttons and bail if the menu is open.
QMenu *confirmMenu = widget->findChild<QMenu*>("confirmMenu");
if (confirmMenu && confirmMenu->isVisible())
return false;
widget->setVisible((event->type() == QEvent::Enter));
}
}
}
else if (event->type() == QEvent::Close) {
deleteLater();
}
else if (event->type() == QEvent::MouseButtonDblClick) {
enlargePreview();
}
return QDialog::event(event);
}
void PreviewDialog::timerEvent(QTimerEvent *event)
{
if (mAutoclose == 0) {
if (mAutocloseAction == 0) {
emit acceptAll();
}
else {
emit rejectAll();
}
}
else if (mAutoclose < 0) {
killTimer(event->timerId());
}
else {
setWindowTitle(tr("Preview: Closing in %1").arg(mAutoclose));
mAutoclose--;
}
}
diff --git a/lightscreen.pro b/lightscreen.pro
index 8cffa67..0c6c134 100644
--- a/lightscreen.pro
+++ b/lightscreen.pro
@@ -1,60 +1,59 @@
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/qtwin.h \
+ tools/uploader.h \
+ tools/qtimgur.h \
dialogs/updaterdialog.h \
dialogs/screenshotdialog.h \
- dialogs/namingdialog.h \
- tools/qtimgur.h \
- tools/uploader.h
+ dialogs/namingdialog.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/qtwin.cpp \
+ tools/uploader.cpp \
+ tools/qtimgur.cpp \
dialogs/updaterdialog.cpp \
dialogs/screenshotdialog.cpp \
- dialogs/namingdialog.cpp \
- tools/qtimgur.cpp \
- tools/uploader.cpp
+ dialogs/namingdialog.cpp
FORMS += dialogs/optionsdialog.ui \
lightscreenwindow.ui \
dialogs/namingdialog.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
-win32:LIBS += libgdi32 libgcc
+
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
-
-
-
-
diff --git a/lightscreen.rc b/lightscreen.rc
index 02eadda..b636d5c 100644
--- a/lightscreen.rc
+++ b/lightscreen.rc
@@ -1 +1,2 @@
IDI_ICON1 ICON DISCARDABLE "images/LS.ico"
+IDI_ICON2 ICON DISCARDABLE "images/test.ico"
diff --git a/lightscreenwindow.cpp b/lightscreenwindow.cpp
index cb8cdc0..4ddc766 100644
--- a/lightscreenwindow.cpp
+++ b/lightscreenwindow.cpp
@@ -1,993 +1,995 @@
/*
* Copyright (C) 2011 Christian Kaiser
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*/
#include <QDate>
#include <QDesktopServices>
#include <QFileInfo>
#include <QHttp>
#include <QMenu>
#include <QMessageBox>
#include <QPointer>
#include <QProcess>
#include <QSettings>
#include <QSound>
#include <QSystemTrayIcon>
#include <QTimer>
#include <QUrl>
#include <QKeyEvent>
#include <QToolTip>
#include <QDebug>
#if defined(Q_WS_WIN)
#include <windows.h>
+ #include "tools/qwin7utils/JumpList.h"
+ using namespace QW7;
#endif
/*
* Lightscreen includes
*/
#include "lightscreenwindow.h"
#include "dialogs/optionsdialog.h"
#include "dialogs/previewdialog.h"
#include "tools/globalshortcut/globalshortcutmanager.h"
#include "tools/os.h"
#include "tools/screenshot.h"
#include "tools/screenshotmanager.h"
#include "tools/qtwin.h"
#include "tools/uploader.h"
#include "updater/updater.h"
LightscreenWindow::LightscreenWindow(QWidget *parent) :
QDialog(parent),
mDoCache(false),
mHideTrigger(false),
mReviveMain(false),
mWasVisible(true),
mOptimizeCount(0),
mLastMode(-1),
mLastMessage(0),
mLastScreenshot()
{
os::translate(settings()->value("options/language").toString());
ui.setupUi(this);
if (QtWin::isCompositionEnabled()) {
layout()->setMargin(0);
resize(minimumSizeHint());
}
setMaximumSize(size());
setMinimumSize(size());
setWindowFlags(windowFlags() ^ Qt::WindowContextHelpButtonHint); // Remove the what's this button, no real use in the main window.
// Actions
connect(ui.optionsPushButton , SIGNAL(clicked()), this, SLOT(showOptions()));
connect(ui.hidePushButton , SIGNAL(clicked()), this, SLOT(toggleVisibility()));
connect(ui.screenshotPushButton, SIGNAL(clicked()), this, SLOT(showScreenshotMenu()));
connect(ui.quitPushButton , SIGNAL(clicked()), this, SLOT(quit()));
// Uploader
connect(Uploader::instance(), SIGNAL(done(QString, QString)), this, SLOT(showUploaderMessage(QString, QString)));
connect(Uploader::instance(), SIGNAL(error(QString)) , this, SLOT(showUploaderError(QString)));
// Manager
connect(ScreenshotManager::instance(), SIGNAL(confirm(Screenshot*)), this, SLOT(preview(Screenshot*)));
connect(ScreenshotManager::instance(), SIGNAL(windowCleanup(Screenshot::Options&)), this, SLOT(cleanup(Screenshot::Options&)));
if (!settings()->contains("file/format")) {
showOptions(); // There are no options (or the options config is invalid or incomplete)
}
else {
QTimer::singleShot(0 , this, SLOT(applySettings()));
QTimer::singleShot(5000, this, SLOT(checkForUpdates()));
}
}
LightscreenWindow::~LightscreenWindow()
{
settings()->setValue("lastScreenshot", mLastScreenshot);
GlobalShortcutManager::instance()->clear();
delete mTrayIcon;
}
/*
* Slots
*/
void LightscreenWindow::action(int mode)
{
if (mode == 4) {
goToFolder();
}
else {
show();
}
}
bool LightscreenWindow::closingWithoutTray()
{
if (settings()->value("options/disableHideAlert", false).toBool())
return false;
QMessageBox msgBox;
msgBox.setWindowTitle(tr("Lightscreen"));
msgBox.setText(tr("You have chosen to hide Lightscreen when there's no system tray icon, so you will not be able to access the program <b>unless you have selected a hotkey to do so</b>.<br>What do you want to do?"));
msgBox.setIcon(QMessageBox::Warning);
msgBox.setStyleSheet("QPushButton { padding: 4px 8px; }");
QPushButton *enableButton = msgBox.addButton(tr("Hide but enable tray"),
QMessageBox::ActionRole);
QPushButton *enableAndDenotifyButton = msgBox.addButton(tr("Hide and don't warn"),
QMessageBox::ActionRole);
QPushButton *hideButton = msgBox.addButton(tr("Just hide"),
QMessageBox::ActionRole);
QPushButton *abortButton = msgBox.addButton(QMessageBox::Cancel);
Q_UNUSED(abortButton);
msgBox.exec();
if (msgBox.clickedButton() == hideButton) {
return false;
}
else if (msgBox.clickedButton() == enableAndDenotifyButton) {
settings()->setValue("options/disableHideAlert", true);
applySettings();
return false;
}
else if (msgBox.clickedButton() == enableButton) {
settings()->setValue("options/tray", true);
applySettings();
return false;
}
return true; // Cancel
}
void LightscreenWindow::cleanup(Screenshot::Options &options)
{
// Reversing settings
if (settings()->value("options/hide").toBool()) {
#ifndef Q_WS_X11 // X is not quick enough and the notification ends up everywhere but in the icon
if (settings()->value("options/tray").toBool() && mTrayIcon) {
mTrayIcon->show();
}
#endif
if (mPreviewDialog) {
if (mPreviewDialog->count() <= 1 && mWasVisible) {
show();
}
mPreviewDialog->show();
}
else if (mWasVisible) {
show();
}
mHideTrigger = false;
}
if (settings()->value("options/tray").toBool() && mTrayIcon) {
notify(options.result);
if (settings()->value("options/message").toBool() && options.file) {
showScreenshotMessage(options.result, options.fileName);
}
}
if (settings()->value("options/playSound", false).toBool()) {
if (options.result == Screenshot::Success) {
QSound::play("sounds/ls.screenshot.wav");
}
else {
QSound::play("afakepathtomakewindowsplaythedefaultsoundtheresprobablyabetterwaybuticantbebothered");
}
}
if (options.result == Screenshot::Success
&& settings()->value("options/optipng").toBool()
&& options.format == Screenshot::PNG)
{
compressPng(options.fileName);
}
else if (settings()->value("options/uploadAuto").toBool()) {
upload(options.fileName);
}
if (options.result == Screenshot::Success && options.file) {
mLastScreenshot = options.fileName;
}
}
void LightscreenWindow::goToFolder()
{
#ifdef Q_WS_WIN
if (!mLastScreenshot.isEmpty()) {
QProcess::startDetached("explorer /select, \"" + mLastScreenshot +"\"");
}
else {
#endif
QString folder = settings()->value("file/target").toString();
if (folder.isEmpty())
folder = qApp->applicationDirPath();
if (QDir::toNativeSeparators(folder.at(folder.size()-1)) != QDir::separator())
folder.append(QDir::separator());
QDesktopServices::openUrl("file:///"+folder);
#ifdef Q_WS_WIN
}
#endif
}
void LightscreenWindow::messageReceived(const QString message)
{
if (message == "-wake") {
show();
qApp->alert(this, 500);
return;
}
if (message == "-screen")
screenshotAction();
if (message == "-area")
screenshotAction(2);
if (message == "-activewindow")
screenshotAction(1);
if (message == "-pickwindow")
screenshotAction(3);
if (message == "-folder")
action(4);
}
void LightscreenWindow::messageClicked()
{
if (mLastMessage == 1) {
goToFolder();
}
else {
QDesktopServices::openUrl(QUrl(Uploader::instance()->lastUrl()));
}
}
void LightscreenWindow::preview(Screenshot* screenshot)
{
if (screenshot->options().preview) {
if (!mPreviewDialog) {
mPreviewDialog = new PreviewDialog(this);
}
mPreviewDialog->add(screenshot);
}
else {
screenshot->confirm(true);
}
}
void LightscreenWindow::quit()
{
settings()->setValue("position", pos());
QString doing;
int answer = 0;
if (Uploader::instance()->uploading() > 0) {
doing = tr("uploading one or more screenshots");
}
if (mOptimizeCount > 0) {
if (!doing.isNull()) {
doing = tr("optimizing and uploading screenshots");
}
else {
doing = tr("optimizing one or more screenshots");
}
}
if (!doing.isNull()) {
answer = QMessageBox::question(this,
tr("Are you sure you want to quit?"),
tr("Lightscreen is currently %1, this will finish momentarily, are you sure you want to quit?").arg(doing),
tr("Quit"),
tr("Don't quit"));
}
if (answer == 0)
accept();
}
void LightscreenWindow::restoreNotification()
{
if (mTrayIcon)
mTrayIcon->setIcon(QIcon(":/icons/lightscreen.small"));
updateUploadStatus();
}
void LightscreenWindow::screenshotAction(int mode)
{
int delayms = -1;
bool optionsHide = settings()->value("options/hide").toBool(); // Option cache, used a couple of times.
if (!mHideTrigger) {
mWasVisible = isVisible();
mHideTrigger = true;
}
// Applying pre-screenshot settings
if (optionsHide) {
hide();
#ifndef Q_WS_X11 // X is not quick enough and the notification ends up everywhere but in the icon
if (mTrayIcon)
mTrayIcon->hide();
#endif
}
// Screenshot delay
delayms = settings()->value("options/delay", 0).toInt();
delayms = delayms * 1000; // Converting the delay to milliseconds.
delayms += 400;
if (optionsHide && mPreviewDialog) {
if (mPreviewDialog->count() >= 1) {
mPreviewDialog->hide();
}
}
// The delayed functions works using the static variable lastMode
// which keeps the argument so a QTimer can call this function again.
if (delayms > 0) {
if (mLastMode < 0) {
mLastMode = mode;
QTimer::singleShot(delayms, this, SLOT(screenshotAction()));
return;
}
else {
mode = mLastMode;
mLastMode = -1;
}
}
static Screenshot::Options options;
if (!mDoCache) {
// Populating the option object that will then be passed to the screenshot engine (sounds fancy huh?)
options.file = settings()->value("file/enabled").toBool();
options.format = (Screenshot::Format) settings()->value("file/format").toInt();
options.prefix = settings()->value("file/prefix").toString();
options.directory = QDir(settings()->value("file/target").toString());
options.quality = settings()->value("options/quality", 100).toInt();
options.currentMonitor = settings()->value("options/currentMonitor", false).toBool();
options.clipboard = settings()->value("options/clipboard", true).toBool();
options.preview = settings()->value("options/preview", false).toBool();
options.magnify = settings()->value("options/magnify", false).toBool();
options.cursor = settings()->value("options/cursor" , false).toBool();
options.saveAs = settings()->value("options/saveAs" , false).toBool();
options.animations = settings()->value("options/animations" , true).toBool();
options.replace = settings()->value("options/replace", false).toBool();
Screenshot::NamingOptions namingOptions;
namingOptions.naming = (Screenshot::Naming) settings()->value("file/naming").toInt();
namingOptions.leadingZeros = settings()->value("options/naming/leadingZeros", 0).toInt();
namingOptions.flip = settings()->value("options/flip", false).toBool();
namingOptions.dateFormat = settings()->value("options/naming/dateFormat", "yyyy-MM-dd").toString();
options.namingOptions = namingOptions;
mDoCache = true;
}
options.mode = mode;
ScreenshotManager::instance()->take(options);
}
void LightscreenWindow::screenshotActionTriggered(QAction* action)
{
screenshotAction(action->data().toInt());
}
void LightscreenWindow::showOptions()
{
GlobalShortcutManager::clear();
QPointer<OptionsDialog> optionsDialog = new OptionsDialog(this);
optionsDialog->exec();
optionsDialog->deleteLater();
applySettings();
}
void LightscreenWindow::showScreenshotMessage(Screenshot::Result result, QString fileName)
{
if (result == Screenshot::Cancel
|| mPreviewDialog)
return;
// Showing message.
QString title;
QString message;
if (result == Screenshot::Success) {
title = QFileInfo(fileName).fileName();
if (settings()->value("file/target").toString().isEmpty()) {
message = QDir::toNativeSeparators(QCoreApplication::applicationDirPath());
}
else {
message = tr("Saved to \"%1\"").arg(settings()->value("file/target").toString());
}
}
else {
title = tr("The screenshot was not taken");
message = tr("An error occurred.");
}
mLastMessage = 1;
mTrayIcon->showMessage(title, message);
}
void LightscreenWindow::showUploaderMessage(QString fileName, QString url)
{
if (!mTrayIcon)
return;
QString screenshot = QFileInfo(fileName).fileName();
mLastMessage = 2;
mTrayIcon->showMessage(tr("%1 uploaded").arg(screenshot), tr("Click here to go to %1").arg(url));
updateUploadStatus();
}
void LightscreenWindow::showUploaderError(QString error)
{
if (!mTrayIcon)
return;
mLastMessage = -1;
mTrayIcon->showMessage(tr("Upload error"), error);
updateUploadStatus();
}
void LightscreenWindow::showScreenshotMenu()
{
// This slot is called only on the first click
QMenu *buttonMenu = new QMenu;
QAction *screenAction = new QAction(QIcon(":/icons/screen"), tr("&Screen"), buttonMenu);
screenAction->setData(QVariant(0));
QAction *windowAction = new QAction(QIcon(":/icons/window"),tr("Active &Window"), buttonMenu);
windowAction->setData(QVariant(1));
QAction *windowPickerAction = new QAction(QIcon(":/icons/picker"), tr("&Pick Window"), buttonMenu);
windowPickerAction->setData(QVariant(3));
QAction *areaAction = new QAction(QIcon(":/icons/area"), tr("&Area"), buttonMenu);
areaAction->setData(QVariant(2));
QAction *uploadAction = new QAction(QIcon(":/icons/imgur"), tr("&Upload last"), buttonMenu);
uploadAction->setToolTip(tr("Upload the last screenshot you took to imgur.com"));
connect(uploadAction, SIGNAL(triggered()), this, SLOT(uploadLast()));
QAction *goAction = new QAction(QIcon(":/icons/folder"), tr("&Go to Folder"), buttonMenu);
connect(goAction, SIGNAL(triggered()), this, SLOT(goToFolder()));
QActionGroup *screenshotGroup = new QActionGroup(buttonMenu);
screenshotGroup->addAction(screenAction);
screenshotGroup->addAction(windowAction);
screenshotGroup->addAction(windowPickerAction);
screenshotGroup->addAction(areaAction);
QMenu* imgurMenu = new QMenu("Upload");
imgurMenu->installEventFilter(this);
imgurMenu->addAction(uploadAction);
imgurMenu->addSeparator();
connect(screenshotGroup, SIGNAL(triggered(QAction*)), this, SLOT(screenshotActionTriggered(QAction*)));
buttonMenu->addAction(screenAction);
buttonMenu->addAction(areaAction);
buttonMenu->addAction(windowAction);
buttonMenu->addAction(windowPickerAction);
buttonMenu->addSeparator();
buttonMenu->addMenu(imgurMenu);
buttonMenu->addSeparator();
buttonMenu->addAction(goAction);
ui.screenshotPushButton->setMenu(buttonMenu);
ui.screenshotPushButton->showMenu();
}
void LightscreenWindow::notify(Screenshot::Result result)
{
switch (result)
{
case Screenshot::Success:
mTrayIcon->setIcon(QIcon(":/icons/lightscreen.yes"));
setWindowTitle(tr("Success!"));
break;
case Screenshot::Fail:
mTrayIcon->setIcon(QIcon(":/icons/lightscreen.no"));
setWindowTitle(tr("Failed!"));
break;
case Screenshot::Cancel:
setWindowTitle(tr("Cancelled!"));
break;
}
QTimer::singleShot(1500, this, SLOT(restoreNotification()));
}
void LightscreenWindow::optimizationDone()
{
// A mouthful :D
mOptimizeCount--;
QString screenshot = (qobject_cast<QProcess*>(sender()))->property("screenshot").toString();
upload(screenshot);
}
void LightscreenWindow::showHotkeyError(QStringList hotkeys)
{
static bool dontShow = false;
if (dontShow)
return;
QString messageText;
messageText = tr("Some hotkeys could not be registered, they might already be in use");
if (hotkeys.count() > 1) {
messageText += tr("<br>The failed hotkeys are the following:") + "<ul>";
foreach(const QString &hotkey, hotkeys) {
messageText += QString("%1%2%3").arg("<li><b>").arg(hotkey).arg("</b></li>");
}
messageText += "</ul>";
}
else {
messageText += tr("<br>The failed hotkey is <b>%1</b>").arg(hotkeys[0]);
}
messageText += tr("<br><i>What do you want to do?</i>");
QMessageBox msgBox(this);
msgBox.setWindowTitle(tr("Lightscreen"));
msgBox.setText(messageText);
QPushButton *changeButton = msgBox.addButton(tr("Change") , QMessageBox::ActionRole);
QPushButton *disableButton = msgBox.addButton(tr("Disable"), QMessageBox::ActionRole);
QPushButton *exitButton = msgBox.addButton(tr("Quit") , QMessageBox::ActionRole);
msgBox.exec();
if (msgBox.clickedButton() == exitButton) {
dontShow = true;
QTimer::singleShot(10, this, SLOT(quit()));
}
else if (msgBox.clickedButton() == changeButton) {
showOptions();
}
else if (msgBox.clickedButton() == disableButton) {
foreach(const QString &hotkey, hotkeys) {
settings()->setValue(QString("actions/%1/enabled").arg(hotkey), false);
}
}
}
void LightscreenWindow::toggleVisibility(QSystemTrayIcon::ActivationReason reason)
{
if (reason != QSystemTrayIcon::DoubleClick)
return;
if (isVisible()) {
if (settings()->value("options/tray").toBool() == false
&& closingWithoutTray())
return;
hide();
}
else {
show();
}
}
// Aliases
void LightscreenWindow::windowHotkey() { screenshotAction(1); }
void LightscreenWindow::windowPickerHotkey() { screenshotAction(3); }
void LightscreenWindow::areaHotkey() { screenshotAction(2); }
/*
* Private
*/
void LightscreenWindow::applySettings()
{
bool tray = settings()->value("options/tray").toBool();
if (tray && !mTrayIcon) {
createTrayIcon();
mTrayIcon->show();
}
else if (!tray && mTrayIcon) {
mTrayIcon->deleteLater();
}
connectHotkeys();
mDoCache = false;
if (settings()->value("lastScreenshot").isValid())
mLastScreenshot = settings()->value("lastScreenshot").toString();
os::setStartup(settings()->value("options/startup").toBool(), settings()->value("options/startupHide").toBool());
}
void LightscreenWindow::compressPng(QString fileName)
{
#if defined(Q_OS_UNIX)
QProcess::startDetached("optipng " + fileName + " -quiet");
#else
if (settings()->value("options/uploadAuto").toBool()) {
// If the user has chosen to automatically upload screenshots we have to track the progress of the optimization, so we use QProcess
QProcess* optipng = new QProcess(this);
// To be read by optimizationDone() (for uploading)
optipng->setProperty("screenshot", fileName);
// Delete the QProcess once it's done.
connect(optipng, SIGNAL(finished(int, QProcess::ExitStatus)), this, SLOT(optimizationDone()));
connect(optipng, SIGNAL(finished(int, QProcess::ExitStatus)), optipng, SLOT(deleteLater()));
optipng->start("optipng", QStringList() << fileName);
mOptimizeCount++;
}
else {
// Otherwise start it detached from this process.
ShellExecuteW(NULL, NULL, (LPCWSTR)QString("optipng.exe").toStdWString().data(), (LPCWSTR)fileName.toStdWString().data(), NULL, SW_HIDE);
}
#endif
}
void LightscreenWindow::connectHotkeys()
{
// Set to true because if the hotkey is disabled it will show an error.
bool screen = true, area = true, window = true, open = true, directory = true;
if (settings()->value("actions/screen/enabled").toBool())
screen = GlobalShortcutManager::instance()->connect(settings()->value(
"actions/screen/hotkey").value<QKeySequence> (), this, SLOT(screenshotAction()));
if (settings()->value("actions/area/enabled").toBool())
area = GlobalShortcutManager::instance()->connect(settings()->value(
"actions/area/hotkey").value<QKeySequence> (), this, SLOT(areaHotkey()));
if (settings()->value("actions/window/enabled").toBool())
window = GlobalShortcutManager::instance()->connect(settings()->value(
"actions/window/hotkey").value<QKeySequence> (), this, SLOT(windowHotkey()));
if (settings()->value("actions/windowPicker/enabled").toBool())
window = GlobalShortcutManager::instance()->connect(settings()->value(
"actions/windowPicker/hotkey").value<QKeySequence> (), this, SLOT(windowPickerHotkey()));
if (settings()->value("actions/open/enabled").toBool())
open = GlobalShortcutManager::instance()->connect(settings()->value(
"actions/open/hotkey").value<QKeySequence> (), this, SLOT(show()));
if (settings()->value("actions/directory/enabled").toBool())
directory = GlobalShortcutManager::instance()->connect(settings()->value(
"actions/directory/hotkey").value<QKeySequence> (), this, SLOT(goToFolder()));
QStringList failed;
if (!screen) failed << "screen";
if (!area) failed << "area";
if (!window) failed << "window";
if (!open) failed << "open";
if (!directory) failed << "directory";
if (!failed.isEmpty())
showHotkeyError(failed);
}
void LightscreenWindow::createTrayIcon()
{
mTrayIcon = new QSystemTrayIcon(QIcon(":/icons/lightscreen.small"), this);
updateUploadStatus();
connect(mTrayIcon, SIGNAL(activated(QSystemTrayIcon::ActivationReason)), this, SLOT(toggleVisibility(QSystemTrayIcon::ActivationReason)));
connect(mTrayIcon, SIGNAL(messageClicked()), this, SLOT(messageClicked()));
QAction *hideAction = new QAction(QIcon(":/icons/lightscreen.small"), tr("Show&/Hide"), mTrayIcon);
connect(hideAction, SIGNAL(triggered()), this, SLOT(toggleVisibility()));
QAction *screenAction = new QAction(QIcon(":/icons/screen"), tr("&Screen"), mTrayIcon);
screenAction->setData(QVariant(0));
QAction *windowAction = new QAction(QIcon(":/icons/window"), tr("Active &Window"), this);
windowAction->setData(QVariant(1));
QAction *windowPickerAction = new QAction(QIcon(":/icons/picker"), tr("&Pick Window"), this);
windowPickerAction->setData(QVariant(3));
QAction *areaAction = new QAction(QIcon(":/icons/area"), tr("&Area"), mTrayIcon);
areaAction->setData(QVariant(2));
QActionGroup *screenshotGroup = new QActionGroup(mTrayIcon);
screenshotGroup->addAction(screenAction);
screenshotGroup->addAction(areaAction);
screenshotGroup->addAction(windowAction);
screenshotGroup->addAction(windowPickerAction);
connect(screenshotGroup, SIGNAL(triggered(QAction*)), this, SLOT(screenshotActionTriggered(QAction*)));
// Duplicated for the screenshot button :(
QAction *uploadAction = new QAction(QIcon(":/icons/imgur"), tr("&Upload last"), mTrayIcon);
uploadAction->setToolTip(tr("Upload the last screenshot you took to imgur.com"));
connect(uploadAction, SIGNAL(triggered()), this, SLOT(uploadLast()));
QAction *optionsAction = new QAction(QIcon(":/icons/configure"), tr("View &Options"), mTrayIcon);
connect(optionsAction, SIGNAL(triggered()), this, SLOT(showOptions()));
QAction *goAction = new QAction(QIcon(":/icons/folder"), tr("&Go to Folder"), mTrayIcon);
connect(goAction, SIGNAL(triggered()), this, SLOT(goToFolder()));
QAction *quitAction = new QAction(tr("&Quit"), mTrayIcon);
connect(quitAction, SIGNAL(triggered()), this, SLOT(quit()));
QMenu* screenshotMenu = new QMenu("Screenshot");
screenshotMenu->addAction(screenAction);
screenshotMenu->addAction(areaAction);
screenshotMenu->addAction(windowAction);
screenshotMenu->addAction(windowPickerAction);
// Duplicated for the screenshot button :(
QMenu* imgurMenu = new QMenu("Upload");
imgurMenu->installEventFilter(this);
imgurMenu->addAction(uploadAction);
imgurMenu->addSeparator();
mUploadHistoryActions = new QActionGroup(imgurMenu);
connect(mUploadHistoryActions, SIGNAL(triggered(QAction*)), this, SLOT(uploadAction(QAction*)));
QMenu* trayIconMenu = new QMenu;
trayIconMenu->addAction(hideAction);
trayIconMenu->addSeparator();
trayIconMenu->addMenu(imgurMenu);
trayIconMenu->addSeparator();
trayIconMenu->addMenu(screenshotMenu);
trayIconMenu->addAction(optionsAction);
trayIconMenu->addAction(goAction);
trayIconMenu->addSeparator();
trayIconMenu->addAction(quitAction);
mTrayIcon->setContextMenu(trayIconMenu);
}
bool LightscreenWindow::eventFilter(QObject *object, QEvent *event)
{
// Filtering upload menu(s) for show events to populate them with links to imgur.
if (event->type() == QEvent::Show) {
QMenu* menu = qobject_cast<QMenu*>(object);
QAction* uploadAction = menu->actions().at(0);
uploadAction->setEnabled(true); // Later in the loop we check to see if the last screenshot is already uploaded and disable this.
if (Uploader::instance()->screenshots().count() > 0) {
QAction* action = 0;
foreach (action, mUploadHistoryActions->actions()) {
mUploadHistoryActions->removeAction(action);
menu->removeAction(action);
delete action;
}
// Iterating back to front for the first 10 screenshots in the uploader history.
QListIterator< QPair<QString, QString> > iterator(Uploader::instance()->screenshots());
iterator.toBack();
int limit = 0;
while (iterator.hasPrevious()) {
if (limit >= 10) {
break;
}
action = new QAction(iterator.peekPrevious().second, menu);
action->setToolTip(QFileInfo(iterator.peekPrevious().first).fileName());
if (iterator.previous().first == mLastScreenshot) {
uploadAction->setEnabled(false);
}
mUploadHistoryActions->addAction(action);
menu->addAction(action);
limit++;
}
}
}
else if (event->type() == QEvent::ToolTip) {
QHelpEvent* helpEvent = dynamic_cast<QHelpEvent*>(event);
QMenu* menu = qobject_cast<QMenu*>(object);
QAction* action = menu->actionAt(helpEvent->pos());
if (action) {
QToolTip::showText(helpEvent->globalPos(), action->toolTip(), this);
}
}
return QDialog::eventFilter(object, event);
}
QSettings *LightscreenWindow::settings() const
{
return ScreenshotManager::instance()->settings();
}
void LightscreenWindow::checkForUpdates()
{
if (settings()->value("options/disableUpdater", false).toBool())
return;
if (settings()->value("lastUpdateCheck").toInt() + 7
> QDate::currentDate().dayOfYear())
return; // If 7 days have not passed since the last update check.
connect(Updater::instance(), SIGNAL(done(bool)), this, SLOT(updaterDone(bool)));
Updater::instance()->check();
}
void LightscreenWindow::updaterDone(bool result)
{
settings()->setValue("lastUpdateCheck", QDate::currentDate().dayOfYear());
if (!result)
return;
QMessageBox msgBox;
msgBox.setWindowTitle(tr("Lightscreen"));
msgBox.setText(tr("There's a new version of Lightscreen available.<br>Would you like to see more information?<br>(<em>You can turn this notification off</em>)"));
msgBox.setIcon(QMessageBox::Information);
QPushButton *yesButton = msgBox.addButton(QMessageBox::Yes);
QPushButton *turnOffButton = msgBox.addButton(tr("Turn Off"), QMessageBox::ActionRole);
QPushButton *remindButton = msgBox.addButton(tr("Remind Me Later"), QMessageBox::RejectRole);
Q_UNUSED(remindButton);
msgBox.exec();
if (msgBox.clickedButton() == yesButton) {
QDesktopServices::openUrl(QUrl("http://lightscreen.sourceforge.net/new-version"));
}
else if (msgBox.clickedButton() == turnOffButton) {
settings()->setValue("disableUpdater", true);
}
}
void LightscreenWindow::upload(QString fileName)
{
Uploader::instance()->upload(fileName);
}
void LightscreenWindow::uploadAction(QAction *upload)
{
QString url = upload->text();
if (url == tr("Uploading...")) {
//int confirm = QMessageBox::question()
}
else {
QDesktopServices::openUrl(QUrl(url));
}
}
void LightscreenWindow::uploadLast()
{
upload(mLastScreenshot);
updateUploadStatus();
}
void LightscreenWindow::updateUploadStatus()
{
int uploading = Uploader::instance()->uploading();
QString statusString;
if (uploading > 0) {
statusString = tr("Uploading %1 screenshot(s)").arg(uploading);
}
else {
statusString = tr("Lightscreen");
}
if (mTrayIcon) {
mTrayIcon->setToolTip(statusString);
}
setWindowTitle(statusString);
}
// Event handling
bool LightscreenWindow::event(QEvent *event)
{
if (event->type() == QEvent::Hide) {
settings()->setValue("position", pos());
}
else if (event->type() == QEvent::Close) {
quit();
}
else if (event->type() == QEvent::Show) {
os::aeroGlass(this);
if (!settings()->value("position").toPoint().isNull())
move(settings()->value("position").toPoint());
}
else if (event->type() == QEvent::KeyPress) {
QKeyEvent *keyEvent = static_cast<QKeyEvent*>(event);
#ifdef Q_WS_MAC
if (keyEvent->modifiers() == Qt::ControlModifier && e->key() == Qt::Key_Period) {
keyEvent->ignore();
if(isVisible())
toggleVisibility();
return false;
}
else
#endif
if (!keyEvent->modifiers() && keyEvent->key() == Qt::Key_Escape) {
keyEvent->ignore();
if(isVisible())
toggleVisibility();
return false;
}
}
else if (event->type() == QEvent::LanguageChange) {
ui.retranslateUi(this);
resize(minimumSizeHint());
}
return QDialog::event(event);
}
diff --git a/main.cpp b/main.cpp
index f8edb96..778d61c 100644
--- a/main.cpp
+++ b/main.cpp
@@ -1,53 +1,87 @@
/*
* Copyright (C) 2011 Christian Kaiser
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*/
#include <QApplication>
#include <QDesktopWidget>
#include <QLocale>
+#include <QDebug>
+
+#if defined(Q_WS_WIN)
+ #include "tools/qwin7utils/AppUserModel.h"
+ #include "tools/qwin7utils/JumpList.h"
+ using namespace QW7;
+#endif
#include "tools/os.h"
#include <QtSingleApplication>
#include "lightscreenwindow.h"
int main(int argc, char *argv[])
{
QtSingleApplication application(argc, argv);
application.setOrganizationName("K");
application.setApplicationName ("Lightscreen");
application.setApplicationVersion("2.0");
application.setQuitOnLastWindowClosed(false);
if (application.isRunning()) {
- application.sendMessage("-wake");
+ if (application.arguments().size() > 1) {
+ QStringList arguments = application.arguments();
+ arguments.removeFirst();
+ application.sendMessage(arguments.join(" "));
+ }
+ else {
+ application.sendMessage("-wake");
+ }
+
return 0;
}
LightscreenWindow lightscreen;
+#if defined(Q_WS_WIN)
+ // Windows 7 jumplists.
+ AppUserModel::SetCurrentProcessExplicitAppUserModelID("Lightscreen");
+
+ JumpList jumpList("Lightscreen");
+
+ QList<JumpListItem> tasks;
+ tasks.append(JumpListItem(application.applicationFilePath(), "-screen" , lightscreen.tr("Screen"), "", "", 0, application.applicationDirPath()));
+ tasks.append(JumpListItem(application.applicationFilePath(), "-area" , lightscreen.tr("Area") , "", "", 0, application.applicationDirPath()));
+ tasks.append(JumpListItem(application.applicationFilePath(), "-activewindow", lightscreen.tr("Active Window"), "", "", 0, application.applicationDirPath()));
+ tasks.append(JumpListItem(application.applicationFilePath(), "-pickwindow" , lightscreen.tr("Pick Window"), "", "", 0, application.applicationDirPath()));
+ tasks.append(JumpListItem());
+ tasks.append(JumpListItem(application.applicationFilePath(), "-folder" , lightscreen.tr("Go to Folder"), "", "", 0, application.applicationDirPath()));
+
+ jumpList.Begin();
+ jumpList.AddUserTasks(tasks);
+ jumpList.Commit();
+#endif
+
if (application.arguments().size() > 1) {
lightscreen.messageReceived(application.arguments().at(1));
}
else {
lightscreen.show();
}
QObject::connect(&application, SIGNAL(messageReceived(const QString&)), &lightscreen, SLOT(messageReceived(const QString&)));
QObject::connect(&lightscreen, SIGNAL(finished(int)), &application, SLOT(quit()));
return application.exec();
}
diff --git a/tools/qwin7utils/AppUserModel.cpp b/tools/qwin7utils/AppUserModel.cpp
new file mode 100644
index 0000000..4c4fae6
--- /dev/null
+++ b/tools/qwin7utils/AppUserModel.cpp
@@ -0,0 +1,57 @@
+/***************************************************************************
+ * 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 "AppUserModel.h"
+
+#ifdef Q_OS_WIN32
+#include "win7_include.h"
+
+namespace QW7 {
+ void AppUserModel::SetCurrentProcessExplicitAppUserModelID(QString app_id) {
+ HMODULE shell;
+
+ shell = LoadLibrary(L"shell32.dll");
+ if (shell) {
+ t_SetCurrentProcessExplicitAppUserModelID set_user_model = reinterpret_cast<t_SetCurrentProcessExplicitAppUserModelID>(GetProcAddress (shell, "SetCurrentProcessExplicitAppUserModelID"));
+ set_user_model(app_id.toStdWString().c_str());
+
+ FreeLibrary (shell);
+ }
+
+ }
+
+ QString AppUserModel::GetCurrentProcessExplicitAppUserModelID() {
+ HMODULE shell;
+ QString appid;
+
+ shell = LoadLibrary(L"shell32.dll");
+ if (shell) {
+ t_GetCurrentProcessExplicitAppUserModelID get_user_model = reinterpret_cast<t_GetCurrentProcessExplicitAppUserModelID>(GetProcAddress (shell, "GetCurrentProcessExplicitAppUserModelID"));
+ wchar_t* _app_id = NULL;
+ if (SUCCEEDED(get_user_model(&_app_id))) {
+ appid.fromStdWString(_app_id);
+ }
+
+ FreeLibrary (shell);
+ }
+ return appid;
+ }
+}
+
+#endif //Q_OS_WIN32
diff --git a/tools/qwin7utils/AppUserModel.h b/tools/qwin7utils/AppUserModel.h
new file mode 100644
index 0000000..11d0d89
--- /dev/null
+++ b/tools/qwin7utils/AppUserModel.h
@@ -0,0 +1,34 @@
+/***************************************************************************
+ * 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. *
+ ***************************************************************************/
+
+#ifndef APPUSERMODEL_H
+#define APPUSERMODEL_H
+#include <QString>
+
+#ifdef Q_OS_WIN32
+namespace QW7 {
+ class AppUserModel
+ {
+ public:
+ static void SetCurrentProcessExplicitAppUserModelID(QString app_id);
+ static QString GetCurrentProcessExplicitAppUserModelID();
+ };
+}
+#endif //Q_OS_WIN32
+#endif // APPUSERMODEL_H
diff --git a/tools/qwin7utils/JLPrivateData.h b/tools/qwin7utils/JLPrivateData.h
new file mode 100644
index 0000000..7e366c3
--- /dev/null
+++ b/tools/qwin7utils/JLPrivateData.h
@@ -0,0 +1,81 @@
+/***************************************************************************
+ * 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. *
+ ***************************************************************************/
+
+#ifndef JLPRIVATEDATA_H
+#define JLPRIVATEDATA_H
+
+#include <QtGlobal>
+
+#ifdef Q_OS_WIN32
+#include "win7_include.h"
+
+namespace QW7 {
+
+ struct JLPrivateData {
+ bool m_list_is_initialized;
+ UINT m_max_count;
+ IObjectArray* m_array;
+ ICustomDestinationList* m_handler;
+
+ JLPrivateData(QString app_id) {
+ m_handler = NULL;
+ m_array = NULL;
+ m_list_is_initialized = false;
+
+ HRESULT hr = CoCreateInstance(CLSID_DestinationList, NULL, CLSCTX_INPROC_SERVER, IID_ICustomDestinationList,
+ reinterpret_cast<void**> (&(m_handler)));
+
+ if (SUCCEEDED(hr)){
+ if(app_id.length() > 0) {
+ m_handler->SetAppID(app_id.toStdWString().c_str());
+ }
+ }
+ }
+
+ inline ICustomDestinationList* ListHandler() { return m_handler;}
+
+ void InitList() {
+ ReleaseList();
+
+ m_max_count = 0;
+ m_list_is_initialized = SUCCEEDED(m_handler->BeginList(&m_max_count, IID_IObjectArray, reinterpret_cast<void**> (&(m_array))));
+ }
+
+ void ReleaseList() {
+ if (m_array) {
+ m_array->Release();
+ m_array = NULL;
+ m_list_is_initialized = false;
+ }
+ }
+
+ ~JLPrivateData() {
+ if (m_handler) {
+ m_handler->Release();
+ }
+
+ ReleaseList();
+ }
+ };
+
+}
+
+#endif // Q_OS_WIN32
+
+#endif // JLPRIVATEDATA_H
diff --git a/tools/qwin7utils/JumpList.cpp b/tools/qwin7utils/JumpList.cpp
new file mode 100644
index 0000000..87bca05
--- /dev/null
+++ b/tools/qwin7utils/JumpList.cpp
@@ -0,0 +1,381 @@
+/***************************************************************************
+ * 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/JumpList.h b/tools/qwin7utils/JumpList.h
new file mode 100644
index 0000000..f6a172d
--- /dev/null
+++ b/tools/qwin7utils/JumpList.h
@@ -0,0 +1,125 @@
+/***************************************************************************
+ * 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. *
+ ***************************************************************************/
+
+#ifndef JUMPLIST_H
+#define JUMPLIST_H
+
+#include <QList>
+#include <QString>
+
+#ifdef Q_OS_WIN32
+namespace QW7 {
+
+ enum JLITEMTYPE {
+ JL_ITEM = 0,
+ JL_LINK = 1,
+ JL_SEPARATOR = 2,
+ JL_OTHER = 3
+ };
+
+ struct JumpListItem {
+ QString m_path;
+ QString m_arguments;
+ QString m_description;
+ QString m_title;
+ QString m_icon_path;
+ int m_icon_index;
+ QString m_working_path;
+ JLITEMTYPE m_type;
+
+ JumpListItem() {Reset(); m_type = JL_SEPARATOR;}
+
+ JumpListItem(QString path): m_path(path), m_type(JL_ITEM) {}
+
+ JumpListItem(QString path, QString arguments, QString title, QString description, \
+ QString icon_path, int icon_index, QString working_path = "") : \
+ m_path(path), m_arguments(arguments), m_description(description), \
+ m_title(title), m_icon_path(icon_path), m_icon_index(icon_index), \
+ m_working_path(working_path), m_type(JL_LINK) {}
+
+ inline void Reset() {
+ m_path.clear(); m_arguments.clear(); m_description.clear();
+ m_title.clear(); m_icon_path.clear(); m_icon_index = 0;
+ m_working_path.clear(); m_type = JL_OTHER;
+ }
+
+ inline bool operator==(const JumpListItem& second) const
+ {
+ if (m_type == second.m_type) {
+
+ if (m_type == JL_ITEM) {
+ return m_path == second.m_path;
+ } else if (m_type == JL_LINK) {
+ return (m_path == second.m_path && m_arguments == second.m_arguments);
+ }
+ }
+
+ return false;
+ }
+
+ };
+
+ typedef enum KnownListType {
+ LIST_RECENT = 0,
+ LIST_FREQUENT = 1
+ } KnownListType;
+
+ struct JLPrivateData;
+
+ class JumpList
+ {
+ private:
+
+ QString m_app_id;
+ JLPrivateData* m_private;
+
+ long GetKnownList(KnownListType type, QList<JumpListItem>& items);
+
+ public:
+ JumpList(QString app_id = "");
+ ~JumpList();
+
+ long SetAppID(QString app_id);
+
+ //ICustomDestinationList
+ long Begin();
+ long AddRecentCategory();
+ long AddFrequentCategory();
+ long AddUserTasks(const QList<JumpListItem>& items);
+ long AddCategory(QString title, const QList<JumpListItem>& items);
+ long GetRemovedDestinations(QList<JumpListItem>& items);
+ long Clear();
+ long Abort();
+ long Commit();
+
+ //IApplicationDocumentLists
+ long GetRecentList(QList<JumpListItem>& items);
+ long GetFrequentList(QList<JumpListItem>& items);
+
+ //IApplicationDestinations
+ long ClearRecentAndFrequentList();
+
+ //Utils
+ static void AddPathToRecent(QString path);
+ static void AddLinkToRecent(const JumpListItem& link);
+ };
+}
+#endif //Q_OS_WIN32
+
+#endif // JUMPLIST_H
diff --git a/tools/qwin7utils/TBPrivateData.h b/tools/qwin7utils/TBPrivateData.h
new file mode 100644
index 0000000..210e4b5
--- /dev/null
+++ b/tools/qwin7utils/TBPrivateData.h
@@ -0,0 +1,61 @@
+/***************************************************************************
+ * 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. *
+ ***************************************************************************/
+
+#ifndef TBPRIVATEDATA_H
+#define TBPRIVATEDATA_H
+#include <QtGlobal>
+
+#ifdef Q_OS_WIN32
+#include "win7_include.h"
+
+namespace QW7 {
+
+ struct TBPrivateData {
+ ITaskbarList4* m_handler;
+
+ TBPrivateData() {
+ m_handler = NULL;
+
+ HRESULT hr = CoCreateInstance(CLSID_TaskbarList, NULL, CLSCTX_INPROC_SERVER, IID_ITaskbarList4,
+ reinterpret_cast<void**> (&(m_handler)));
+
+ if (SUCCEEDED(hr)){
+
+ hr = m_handler->HrInit();
+
+ if (FAILED(hr)) {
+ m_handler->Release();
+ m_handler = NULL;
+ }
+ }
+ }
+
+ ITaskbarList4* GetHandler() { return m_handler;}
+
+ ~TBPrivateData() {
+ if (m_handler) {
+ m_handler->Release();
+ }
+ }
+ };
+
+}
+
+#endif // Q_OS_WIN32
+#endif // TBPRIVATEDATA_H
diff --git a/tools/qwin7utils/Taskbar.cpp b/tools/qwin7utils/Taskbar.cpp
new file mode 100644
index 0000000..5f59616
--- /dev/null
+++ b/tools/qwin7utils/Taskbar.cpp
@@ -0,0 +1,96 @@
+/***************************************************************************
+ * 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 "Taskbar.h"
+
+#ifdef Q_OS_WIN32
+#include <QMutexLocker>
+#include "TBPrivateData.h"
+
+namespace QW7 {
+
+ QMutex Taskbar::m_mutex;
+ QMutex Taskbar::m_mutex_winevent;
+
+ Taskbar* Taskbar::m_instance = NULL;
+
+
+ Taskbar::Taskbar(QObject* parent) : QObject(parent) {
+ m_private = NULL;
+ m_taskBarCreatedId = WM_NULL;
+ }
+
+ Taskbar* Taskbar::GetInstance() {
+ QMutexLocker locker(&m_mutex);
+
+ if (m_instance == NULL) {
+ m_instance = new Taskbar();
+ }
+
+ return m_instance;
+ }
+
+ Taskbar::~Taskbar() {
+ if (m_private) {
+ delete m_private;
+ m_private = NULL;
+ }
+ }
+
+ void Taskbar::ReleaseInstance() {
+ QMutexLocker locker(&m_mutex);
+
+ if (m_instance != NULL) {
+ delete m_instance;
+ }
+ }
+
+
+ bool Taskbar::isInitialized() {
+ if (m_private != NULL) {
+ return (m_private->GetHandler() != NULL);
+ } else {
+ return false;
+ }
+ }
+
+ bool Taskbar::winEvent(MSG* message, long* result) {
+ if (m_taskBarCreatedId == WM_NULL) {
+ m_taskBarCreatedId = RegisterWindowMessage(L"TaskbarButtonCreated");
+ }
+
+ if (message->message == m_taskBarCreatedId) {
+ QMutexLocker locker(&m_mutex_winevent);
+
+ if (!m_private) {
+ m_private = new TBPrivateData();
+
+ if (m_private) {
+ emit isReady();
+ return true;
+ }
+ }
+
+ }
+
+ return false;
+ }
+}
+
+#endif //Q_OS_WIN32
diff --git a/tools/qwin7utils/Taskbar.h b/tools/qwin7utils/Taskbar.h
new file mode 100644
index 0000000..22cacfb
--- /dev/null
+++ b/tools/qwin7utils/Taskbar.h
@@ -0,0 +1,64 @@
+/***************************************************************************
+ * 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. *
+ ***************************************************************************/
+
+#ifndef TASKBAR_H
+#define TASKBAR_H
+
+#include <QMutex>
+#include <QObject>
+#include <QCoreApplication>
+
+#ifdef Q_OS_WIN32
+namespace QW7 {
+
+ struct TBPrivateData;
+
+ class Taskbar : public QObject {
+
+ Q_OBJECT
+
+ private:
+ TBPrivateData* m_private;
+ unsigned int m_taskBarCreatedId;
+
+ static QMutex m_mutex;
+ static QMutex m_mutex_winevent;
+ static Taskbar* m_instance;
+
+ Taskbar(QObject* parent = NULL);
+ ~Taskbar();
+
+ public:
+
+ static Taskbar* GetInstance();
+ static void ReleaseInstance();
+
+ bool isInitialized();
+ bool winEvent(MSG* message, long* result);
+
+ signals:
+ void isReady();
+
+ friend class TaskbarTabs;
+ friend class TaskbarButton;
+ friend class TaskbarToolbar;
+ };
+}
+#endif // Q_OS_WIN32
+#endif // TASKBAR_H
diff --git a/tools/qwin7utils/TaskbarButton.cpp b/tools/qwin7utils/TaskbarButton.cpp
new file mode 100644
index 0000000..5c3704f
--- /dev/null
+++ b/tools/qwin7utils/TaskbarButton.cpp
@@ -0,0 +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
diff --git a/tools/qwin7utils/TaskbarButton.h b/tools/qwin7utils/TaskbarButton.h
new file mode 100644
index 0000000..fa24990
--- /dev/null
+++ b/tools/qwin7utils/TaskbarButton.h
@@ -0,0 +1,61 @@
+/***************************************************************************
+ * 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. *
+ ***************************************************************************/
+
+#ifndef TASKBARBUTTON_H
+#define TASKBARBUTTON_H
+
+#include <QList>
+#include <QIcon>
+#include <QString>
+#include <QWidget>
+#include <QPixmap>
+#include <QWidget>
+
+#ifdef Q_OS_WIN32
+namespace QW7 {
+
+ typedef enum ProgressBarState {
+ STATE_NOPROGRESS = 0x0,
+ STATE_INDETERMINATE = 0x1,
+ STATE_NORMAL = 0x2,
+ STATE_ERROR = 0x4,
+ STATE_PAUSED = 0x8
+ } ProgressBarState;
+
+ struct TBPrivateData;
+
+ class TaskbarButton : public QObject {
+
+ Q_OBJECT
+ private:
+ QWidget* m_widget;
+
+ public:
+ explicit TaskbarButton(QWidget* parent);
+
+ public slots:
+ void SetWindow(QWidget* window);
+ long SetOverlayIcon(const QIcon& icon, QString description);
+
+ long SetState(ProgressBarState state);
+ long SetProgresValue(unsigned long long done, unsigned long long total);
+ };
+}
+#endif // Q_OS_WIN32
+#endif // TASKBARBUTTON_H
diff --git a/tools/qwin7utils/TaskbarTabs.cpp b/tools/qwin7utils/TaskbarTabs.cpp
new file mode 100644
index 0000000..430df01
--- /dev/null
+++ b/tools/qwin7utils/TaskbarTabs.cpp
@@ -0,0 +1,251 @@
+/***************************************************************************
+ * 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 "TaskbarTabs.h"
+
+#ifdef Q_OS_WIN32
+#include "Utils.h"
+#include "Taskbar.h"
+#include "TBPrivateData.h"
+
+namespace QW7 {
+
+ TaskbarTabs* TaskbarTabs::m_instance = NULL;
+ QCoreApplication::EventFilter TaskbarTabs::m_oldEventFilter = NULL;
+
+ TaskbarTabs::TaskbarTabs(){
+ }
+
+ TaskbarTabs::~TaskbarTabs() {
+ TaskbarTab* tab;
+ foreach(tab, m_tabs) {
+ m_tabs.removeOne(tab);
+
+ delete tab->m_tab_widget;
+ delete tab;
+ }
+
+ if (m_oldEventFilter) {
+ qApp->setEventFilter(m_oldEventFilter);
+ }
+ }
+
+ TaskbarTabs* TaskbarTabs::GetInstance() {
+
+ if (m_instance == NULL) {
+ m_instance = new TaskbarTabs();
+ m_oldEventFilter = qApp->setEventFilter(&TaskbarTabs::eventFilter);
+ }
+
+ return m_instance;
+ }
+
+ void TaskbarTabs::ReleaseInstance() {
+ if (m_instance != NULL) {
+ delete m_instance;
+ }
+ }
+
+ void TaskbarTabs::SetParentWidget(QWidget* widget) {
+ m_parentWidget = widget;
+ }
+
+ void TaskbarTabs::AddTab(QWidget* widget, QString title) {
+ AddTab(widget, title, QIcon(), QPixmap());
+ }
+
+ void TaskbarTabs::AddTab(QWidget* widget, QString title, QIcon icon) {
+ AddTab(widget, title, icon, QPixmap());
+ }
+
+ void TaskbarTabs::AddTab(QWidget* widget, QString title, QPixmap pixmap) {
+ AddTab(widget, title, QIcon(), pixmap);
+ }
+
+ void TaskbarTabs::AddTab(QWidget* widget, QString title, QIcon icon, QPixmap pixmap) {
+ TaskbarTab* tab = new TaskbarTab();
+
+ tab->m_widget = widget;
+ tab->m_tab_widget = new QWidget();
+ tab->m_tab_widget->setWindowTitle(title);
+ tab->m_tab_widget->setWindowIcon(icon.isNull() ? widget->windowIcon() : icon);
+ tab->m_thumbnail = pixmap;
+
+ m_tabs.append(tab);
+ EnableWidgetIconicPreview(tab->m_tab_widget, true);
+
+ Taskbar::GetInstance()->m_private->GetHandler()->RegisterTab(tab->m_tab_widget->winId(), m_parentWidget->winId());
+ Taskbar::GetInstance()->m_private->GetHandler()->SetTabOrder(tab->m_tab_widget->winId(), NULL);
+ Taskbar::GetInstance()->m_private->GetHandler()->SetTabActive(NULL, m_tabs.back()->m_tab_widget->winId(), 0);
+ }
+
+ void TaskbarTabs::UpdateTab(QWidget* widget, QString title) {
+ UpdateTab(widget, title, QIcon(), QPixmap());
+ }
+
+ void TaskbarTabs::UpdateTab(QWidget* widget, QString title, QIcon icon) {
+ UpdateTab(widget, title, icon, QPixmap());
+ }
+
+ void TaskbarTabs::UpdateTab(QWidget* widget, QString title, QPixmap pixmap) {
+ UpdateTab(widget, title, QIcon(), pixmap);
+ }
+
+ void TaskbarTabs::UpdateTab(QWidget* widget, QString title, QIcon icon, QPixmap pixmap) {
+ TaskbarTab* tab = FindTabByWId(widget->winId(), true);
+
+ if (tab == NULL) return;
+
+ tab->m_thumbnail = pixmap;
+ tab->m_tab_widget->setWindowIcon(icon);
+ tab->m_tab_widget->setWindowTitle(title);
+
+ InvalidateIconicBitmaps(tab->m_tab_widget);
+ }
+
+
+ void TaskbarTabs::SetActiveTab(QWidget* widget) {
+ TaskbarTab* tab = FindTabByWId(widget->winId(), true);
+
+ if (tab == NULL) return;
+
+ Taskbar::GetInstance()->m_private->GetHandler()->SetTabActive(tab->m_tab_widget->winId(), m_parentWidget->winId(), 0);
+ }
+
+ void TaskbarTabs::RemoveTab(QWidget* widget) {
+ TaskbarTab* tab = FindTabByWId(widget->winId(), true);
+
+ if (tab == NULL) return;
+
+ Taskbar::GetInstance()->m_private->GetHandler()->UnregisterTab(tab->m_tab_widget->winId());
+
+ m_tabs.removeOne(tab);
+ delete tab->m_tab_widget;
+ delete tab;
+ }
+
+ void TaskbarTabs::SetTabOrder(QWidget* widget, QWidget* after_widget) {
+ TaskbarTab* tab1 = FindTabByWId(widget->winId(), true);
+ TaskbarTab* tab2 = FindTabByWId(after_widget->winId(), true);
+
+ if (tab1 == NULL || tab2 == NULL) return;
+
+ Taskbar::GetInstance()->m_private->GetHandler()->SetTabOrder(tab1->m_tab_widget->winId(), tab2->m_tab_widget->winId());
+ }
+
+ void TaskbarTabs::InvalidateTabThumbnail(QWidget* widget) {
+ TaskbarTab* tab = FindTabByWId(widget->winId());
+
+ if (tab == NULL) return;
+
+ InvalidateIconicBitmaps(tab->m_tab_widget);
+ }
+
+ TaskbarTabs::TaskbarTab* TaskbarTabs::FindTabByWId(WId id, bool inserted) {
+ bool found = false;
+
+ WId tabWId = NULL;
+ TaskbarTab* tab;
+ foreach(tab, m_tabs) {
+
+ tabWId = inserted ? tab->m_widget->winId() : tab->m_tab_widget->winId();
+ if (tabWId == id) {
+ found = true;
+ break;
+ }
+ }
+
+ return found ? tab : NULL;
+ }
+
+ void TaskbarTabs::TabAction(WId id, TABEVENT action) {
+ TaskbarTab* tab = FindTabByWId(id);
+
+ if (tab != NULL) {
+ switch (action) {
+ case TAB_CLICK :
+ emit OnTabClicked(tab->m_widget);
+ break;
+
+ case TAB_CLOSE:
+ emit OnTabClose(tab->m_widget);
+ break;
+
+ case TAB_HOVER:
+ emit OnTabHover(tab->m_widget);
+ break;
+ }
+ }
+ }
+
+ void TaskbarTabs::SetPeekBitmap(WId id, QSize size, bool isLive) {
+ TaskbarTab* tab = FindTabByWId(id);
+
+ if (tab == NULL) return;
+
+ QPixmap thumbnail = (!tab->m_thumbnail.isNull() && !isLive) ? tab->m_thumbnail :
+ QPixmap::grabWidget(isLive ? m_parentWidget : tab->m_widget).scaled(size, Qt::KeepAspectRatio);
+
+ HBITMAP hbitmap = thumbnail.toWinHBITMAP(isLive ? QPixmap::NoAlpha : QPixmap::Alpha);
+
+ isLive ? DwmSetIconicLivePreviewBitmap(id, hbitmap, 0, 0) : DwmSetIconicThumbnail(id, hbitmap, 0);
+
+ if (hbitmap) DeleteObject(hbitmap);
+ }
+
+ bool TaskbarTabs::eventFilter(void *message_, long *result)
+ {
+ MSG* message = static_cast<MSG*>(message_);
+
+ switch(message->message)
+ {
+ case WM_DWMSENDICONICTHUMBNAIL : {
+ if (message->hwnd == TaskbarTabs::GetInstance()->m_parentWidget->winId()) return false;
+
+ TaskbarTabs::GetInstance()->SetPeekBitmap(message->hwnd, QSize(HIWORD(message->lParam), LOWORD(message->lParam)));
+ return true;
+ }
+ case WM_DWMSENDICONICLIVEPREVIEWBITMAP : {
+ TaskbarTabs::GetInstance()->TabAction(message->hwnd, TAB_HOVER);
+
+ if (message->hwnd == TaskbarTabs::GetInstance()->m_parentWidget->winId()) return false;
+
+ TaskbarTabs::GetInstance()->SetPeekBitmap(message->hwnd, TaskbarTabs::GetInstance()->m_parentWidget->size(), true);
+ return true;
+ }
+ case WM_ACTIVATE : {
+ if (LOWORD(message->wParam) == WA_ACTIVE) {
+ TaskbarTabs::GetInstance()->TabAction(message->hwnd, TAB_CLICK);
+ }
+ return false;
+ }
+ case WM_CLOSE : {
+ TaskbarTabs::GetInstance()->TabAction(message->hwnd, TAB_CLOSE);
+ return false;
+ }
+ }
+
+ if (TaskbarTabs::m_oldEventFilter)
+ return TaskbarTabs::m_oldEventFilter(message_, result);
+ else
+ return false;
+ }
+}
+
+#endif //Q_OS_WIN32
diff --git a/tools/qwin7utils/TaskbarTabs.h b/tools/qwin7utils/TaskbarTabs.h
new file mode 100644
index 0000000..adfb2e5
--- /dev/null
+++ b/tools/qwin7utils/TaskbarTabs.h
@@ -0,0 +1,95 @@
+/***************************************************************************
+ * 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. *
+ ***************************************************************************/
+
+#ifndef TASKBARTABS_H
+#define TASKBARTABS_H
+
+#include <QList>
+#include <QIcon>
+#include <QString>
+#include <QPixmap>
+#include <QWidget>
+#include <QCoreApplication>
+
+#ifdef Q_OS_WIN32
+
+namespace QW7 {
+
+ class TaskbarTabs : public QObject
+ {
+ Q_OBJECT
+ public:
+
+ static TaskbarTabs* GetInstance();
+ static void ReleaseInstance();
+ static bool eventFilter(void *message_, long *result);
+
+ void SetParentWidget(QWidget* widget);
+
+ void AddTab(QWidget* widget, QString title = "");
+ void AddTab(QWidget* widget, QString title, QIcon icon);
+ void AddTab(QWidget* widget, QString title, QPixmap pixmap);
+ void AddTab(QWidget* widget, QString title, QIcon icon, QPixmap pixmap);
+ void SetActiveTab(QWidget* widget);
+ void RemoveTab(QWidget* widget);
+ void SetTabOrder(QWidget* widget, QWidget* after_widget);
+
+ void UpdateTab(QWidget* widget, QString title = "");
+ void UpdateTab(QWidget* widget, QString title, QIcon icon);
+ void UpdateTab(QWidget* widget, QString title, QPixmap pixmap);
+ void UpdateTab(QWidget* widget, QString title, QIcon icon, QPixmap pixmap);
+ void InvalidateTabThumbnail(QWidget* widget);
+
+ private:
+ struct TaskbarTab {
+ TaskbarTab() : m_widget(NULL), m_tab_widget(NULL) {}
+
+ QPixmap m_thumbnail;
+ QWidget* m_widget;
+ QWidget* m_tab_widget;
+ };
+
+ enum TABEVENT {
+ TAB_CLICK = 0,
+ TAB_CLOSE = 1,
+ TAB_HOVER = 2
+ };
+
+ QWidget* m_parentWidget;
+ QList<TaskbarTab*> m_tabs;
+
+ static TaskbarTabs* m_instance;
+ static QCoreApplication::EventFilter m_oldEventFilter;
+
+ TaskbarTabs();
+ ~TaskbarTabs();
+
+ void TabAction(WId id, TABEVENT action);
+ TaskbarTab* FindTabByWId(WId id, bool inserted = false);
+ void SetPeekBitmap(WId id, QSize size, bool isLive = false);
+
+ signals:
+ void OnTabClicked(QWidget* widget);
+ void OnTabClose(QWidget* widget);
+ void OnTabHover(QWidget* widget);
+ };
+
+}
+#endif // Q_OS_WIN32
+#endif // TASKBARTABS_H
diff --git a/tools/qwin7utils/TaskbarThumbnail.cpp b/tools/qwin7utils/TaskbarThumbnail.cpp
new file mode 100644
index 0000000..4c551c5
--- /dev/null
+++ b/tools/qwin7utils/TaskbarThumbnail.cpp
@@ -0,0 +1,85 @@
+/***************************************************************************
+ * 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 "taskbarthumbnail.h"
+
+#ifdef Q_OS_WIN32
+#include <QWidget>
+
+#include "utils.h"
+#include "win7_include.h"
+#include "tbprivatedata.h"
+#include "taskbar.h"
+
+namespace QW7 {
+
+ TaskbarThumbnail::TaskbarThumbnail(QObject *parent) : QObject(parent) {
+ SetWindow(parent);
+ }
+
+ void TaskbarThumbnail::SetWindow(QObject* window) {
+ m_widget = dynamic_cast<QWidget*>(window);
+ }
+
+ void TaskbarThumbnail::EnableIconicPreview(bool enable) {
+ EnableWidgetIconicPreview(m_widget, enable);
+ }
+
+ void TaskbarThumbnail::SetThumbnail(QPixmap thumbnail) {
+ m_thumbnail = thumbnail;
+ }
+
+ void TaskbarThumbnail::SetThumbnailTooltip(QString tooltip) {
+ if (Taskbar::GetInstance()->m_private) {
+ Taskbar::GetInstance()->m_private->GetHandler()->SetThumbnailTooltip(m_widget->winId(), tooltip.toStdWString().c_str());
+ }
+ }
+
+ bool TaskbarThumbnail::winEvent(MSG* message, long* result) {
+
+ switch (message->message)
+ {
+ case WM_DWMSENDICONICTHUMBNAIL: {
+ HBITMAP hbitmap = m_thumbnail.toWinHBITMAP(QPixmap::Alpha);
+ DwmSetIconicThumbnail(m_widget->winId(), hbitmap, 0);
+
+ if (hbitmap) DeleteObject(hbitmap);
+ return true;
+ }
+ break;
+
+
+ case WM_DWMSENDICONICLIVEPREVIEWBITMAP: {
+ HBITMAP hbitmap = QPixmap::grabWidget(m_widget).scaled(m_widget->size(), Qt::KeepAspectRatio).toWinHBITMAP();
+
+ DwmSetIconicLivePreviewBitmap(m_widget->winId(), hbitmap, 0, 0);
+ if (hbitmap) DeleteObject(hbitmap);
+ return true;
+ }
+ break;
+
+ }
+
+ return false;//Taskbar::winEvent(message, result);
+ }
+
+
+}
+
+#endif //Q_OS_WIN32
diff --git a/tools/qwin7utils/TaskbarThumbnail.h b/tools/qwin7utils/TaskbarThumbnail.h
new file mode 100644
index 0000000..fbf8ce1
--- /dev/null
+++ b/tools/qwin7utils/TaskbarThumbnail.h
@@ -0,0 +1,53 @@
+/***************************************************************************
+ * 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. *
+ ***************************************************************************/
+
+#ifndef TASKBARTHUMBNAIL_H
+#define TASKBARTHUMBNAIL_H
+
+#include <QObject>
+#include <QPixmap>
+#include <QString>
+#include <QWidget>
+
+#ifdef Q_OS_WIN32
+#include "taskbar.h"
+
+namespace QW7 {
+
+ class TaskbarThumbnail : public QObject
+ {
+ Q_OBJECT
+ public:
+ explicit TaskbarThumbnail(QObject *parent = 0);
+ bool winEvent(MSG* message, long* result);
+
+ public slots:
+ void SetWindow(QObject* window);
+ void SetThumbnail(QPixmap thumbnail);
+ void SetThumbnailTooltip(QString tooltip);
+ void EnableIconicPreview(bool enable);
+
+ private:
+ QWidget* m_widget;
+ QPixmap m_thumbnail;
+
+ };
+}
+#endif //Q_OS_WIN32
+#endif // TASKBARTHUMBNAIL_H
diff --git a/tools/qwin7utils/TaskbarToolbar.cpp b/tools/qwin7utils/TaskbarToolbar.cpp
new file mode 100644
index 0000000..b93ba75
--- /dev/null
+++ b/tools/qwin7utils/TaskbarToolbar.cpp
@@ -0,0 +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
diff --git a/tools/qwin7utils/TaskbarToolbar.h b/tools/qwin7utils/TaskbarToolbar.h
new file mode 100644
index 0000000..091400b
--- /dev/null
+++ b/tools/qwin7utils/TaskbarToolbar.h
@@ -0,0 +1,63 @@
+/***************************************************************************
+ * 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. *
+ ***************************************************************************/
+
+#ifndef TASKBARTOOLBAR_H
+#define TASKBARTOOLBAR_H
+
+#include <QRect>
+#include <QList>
+#include <QAction>
+#include <QObject>
+#include <QString>
+#include <QWidget>
+#include <QCoreApplication>
+
+#ifdef Q_OS_WIN32
+
+namespace QW7 {
+
+ class TaskbarToolbar : public QObject
+ {
+ Q_OBJECT
+ public:
+ explicit TaskbarToolbar(QWidget *parent = 0);
+ void AddAction(QAction* action);
+ void AddActions(QList<QAction*>& actions);
+ void Show();
+ bool winEvent(MSG* message, long* result);
+ void SetWidget(QWidget* widget);
+ void SetThumbnailClip(QRect rect);
+ void SetThumbnailTooltip(QString tooltip);
+
+ ~TaskbarToolbar();
+
+ private:
+ bool m_initialized;
+ QWidget* m_widget;
+ QList<QAction*> m_actions;
+ void RemoveActions();
+
+ private slots:
+ void OnActionChanged();
+
+ };
+}
+#endif // Q_OS_WIN32
+
+#endif // TASKBARTOOLBAR_H
diff --git a/tools/qwin7utils/Utils.cpp b/tools/qwin7utils/Utils.cpp
new file mode 100644
index 0000000..0873144
--- /dev/null
+++ b/tools/qwin7utils/Utils.cpp
@@ -0,0 +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
diff --git a/tools/qwin7utils/Utils.h b/tools/qwin7utils/Utils.h
new file mode 100644
index 0000000..5c7a905
--- /dev/null
+++ b/tools/qwin7utils/Utils.h
@@ -0,0 +1,41 @@
+/***************************************************************************
+ * 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. *
+ ***************************************************************************/
+
+#ifndef UTILS_H
+#define UTILS_H
+
+#include <QWidget>
+
+#ifdef Q_OS_WIN32
+#include <windows.h>
+
+namespace QW7 {
+
+ void DwmSetIconicThumbnail(HWND hwnd, HBITMAP hbmp, DWORD dwSITFlags);
+ void DwmSetIconicLivePreviewBitmap(HWND hwnd, HBITMAP hbmp, POINT *pptClient, DWORD dwSITFlags);
+
+ void InvalidateIconicBitmaps(QWidget* widget);
+ void ExtendFrameIntoClientArea(QWidget* widget);
+ void EnableWidgetIconicPreview(QWidget* widget, bool enable);
+ long EnableBlurBehindWidget(QWidget* widget, bool enable);
+}
+
+#endif //Q_OS_WIN32
+
+#endif // UTILS_H
diff --git a/tools/qwin7utils/qwin7utils.pri b/tools/qwin7utils/qwin7utils.pri
new file mode 100644
index 0000000..1edb09b
--- /dev/null
+++ b/tools/qwin7utils/qwin7utils.pri
@@ -0,0 +1,23 @@
+INCLUDEPATH += $$PWD
+DEPENDPATH += $$PWD
+
+SOURCES += $$PWD/AppUserModel.cpp \
+ $$PWD/JumpList.cpp \
+ $$PWD/TaskbarButton.cpp \
+ $$PWD/Taskbar.cpp \
+ $$PWD/TaskbarToolbar.cpp \
+ $$PWD/Utils.cpp \
+ $$PWD/TaskbarTabs.cpp
+
+HEADERS += $$PWD/AppUserModel.h \
+ $$PWD/JumpList.h \
+ $$PWD/win7_include.h \
+ $$PWD/TaskbarButton.h \
+ $$PWD/Taskbar.h \
+ $$PWD/TaskbarToolbar.h \
+ $$PWD/TBPrivateData.h \
+ $$PWD/JLPrivateData.h \
+ $$PWD/Utils.h \
+ $$PWD/TaskbarTabs.h
+
+#LIBS += libuser32 libole32 libshell32 libshlwapi
diff --git a/tools/qwin7utils/win7_include.h b/tools/qwin7utils/win7_include.h
new file mode 100644
index 0000000..ba5747b
--- /dev/null
+++ b/tools/qwin7utils/win7_include.h
@@ -0,0 +1,302 @@
+#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
diff --git a/tools/screenshot.cpp b/tools/screenshot.cpp
index 10f8c17..0df2986 100644
--- a/tools/screenshot.cpp
+++ b/tools/screenshot.cpp
@@ -1,395 +1,395 @@
/*
* Copyright (C) 2011 Christian Kaiser
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*/
#include <QApplication>
#include <QClipboard>
#include <QDateTime>
#include <QDesktopWidget>
#include <QFileDialog>
#include <QPainter>
#include <QPixmap>
#include <QDebug>
#include "windowpicker.h"
#include "../dialogs/areadialog.h"
#include "screenshot.h"
#include "os.h"
#ifdef Q_WS_WIN
#include <windows.h>
#endif
#ifdef Q_WS_X11
#include <QX11Info>
#include <X11/X.h>
#include <X11/Xlib.h>
#endif
Screenshot::Screenshot(QObject *parent, Screenshot::Options options):
QObject(parent),
mOptions(options),
mPixmapDelay(false),
mUnloaded(false),
mUnloadFilename()
{
// Here be crickets
}
Screenshot::~Screenshot()
{
if (mUnloaded) {
QFile::remove(mUnloadFilename);
}
}
Screenshot::Options &Screenshot::options()
{
return mOptions;
}
QPixmap &Screenshot::pixmap()
{
if (mUnloaded) {
// A local reference.. what could go wrong? Nothing! Right guys? Guys?
QPixmap p;
p.load(mUnloadFilename);
return p;
}
return mPixmap;
}
void Screenshot::activeWindow()
{
#if defined(Q_WS_WIN)
HWND fWindow = GetForegroundWindow();
if (fWindow == NULL)
return;
if (fWindow == GetDesktopWindow()) {
wholeScreen();
return;
}
mPixmap = os::grabWindow(GetForegroundWindow());
#endif
#if defined(Q_WS_X11)
Window focus;
int revert;
XGetInputFocus(QX11Info::display(), &focus, &revert);
mPixmap = QPixmap::grabWindow(focus);
#endif
}
QString Screenshot::getName(NamingOptions options, QString prefix, QDir directory)
{
QString naming;
int naming_largest = 0;
if (options.flip) {
naming = "%1" + prefix;
}
else {
naming = prefix + "%1";
}
switch (options.naming)
{
case Screenshot::Numeric: // Numeric
// Iterating through the folder to find the largest numeric naming.
foreach(QString file, directory.entryList(QDir::Files))
{
if (file.contains(prefix)) {
file.chop(file.size() - file.lastIndexOf("."));
file.remove(prefix);
if (file.toInt()> naming_largest) {
naming_largest = file.toInt();
}
}
}
if (options.leadingZeros > 0) {
//Pretty, huh?
QString format;
QTextStream (&format) << "%0" << (options.leadingZeros+1) << "d";
naming = naming.arg(QString().sprintf(format.toAscii(), naming_largest + 1));
}
else {
naming = naming.arg(naming_largest + 1);
}
break;
case Screenshot::Date: // Date
naming = naming.arg(QDateTime::currentDateTime().toString(options.dateFormat));
break;
case Screenshot::Timestamp: // Timestamp
naming = naming.arg(QDateTime::currentDateTime().toTime_t());
break;
case Screenshot::Empty:
naming = naming.arg("");
break;
}
return naming;
}
QString Screenshot::newFileName() const
{
if (!mOptions.directory.exists())
mOptions.directory.mkpath(mOptions.directory.path());
QString naming = Screenshot::getName(mOptions.namingOptions, mOptions.prefix, mOptions.directory);
QString fileName;
QString path = QDir::toNativeSeparators(mOptions.directory.path());
// Cleanup
if (path.at(path.size()-1) != QDir::separator() && !path.isEmpty())
path.append(QDir::separator());
fileName.append(path);
fileName.append(naming);
return fileName;
}
QString Screenshot::extension() const
{
switch (mOptions.format) {
case Screenshot::PNG:
return ".png";
break;
case Screenshot::BMP:
return ".bmp";
break;
case Screenshot::JPEG:
default:
return ".jpg";
break;
}
}
void Screenshot::selectedArea()
{
grabDesktop();
if (mPixmap.isNull())
return;
AreaDialog selector(this);
int result = selector.exec();
if (result == QDialog::Accepted) {
mPixmap = mPixmap.copy(selector.resultRect());
}
else {
mPixmap = QPixmap();
}
}
void Screenshot::selectedWindow()
{
WindowPicker* windowPicker = new WindowPicker;
mPixmapDelay = true;
connect(windowPicker, SIGNAL(pixmap(QPixmap)), this, SLOT(setPixmap(QPixmap)));
}
void Screenshot::wholeScreen()
{
grabDesktop();
}
void Screenshot::grabDesktop()
{
QRect geometry;
if (mOptions.currentMonitor) {
geometry = qApp->desktop()->screenGeometry(QCursor::pos());
}
else {
geometry = qApp->desktop()->geometry();
}
mPixmap = QPixmap::grabWindow(qApp->desktop()->winId(), geometry.x(), geometry.y(), geometry.width(), geometry.height());
if (mOptions.cursor && !mPixmap.isNull()) {
QPainter painter(&mPixmap);
painter.drawPixmap(QCursor::pos(), os::cursor());
}
}
void Screenshot::take()
{
switch (mOptions.mode)
{
case Screenshot::WholeScreen:
wholeScreen();
break;
case Screenshot::SelectedArea:
selectedArea();
break;
case Screenshot::ActiveWindow:
activeWindow();
break;
case Screenshot::SelectedWindow:
selectedWindow();
break;
}
if (mPixmapDelay)
return;
if (mPixmap.isNull()) {
confirm(false);
}
else {
confirmation();
}
}
void Screenshot::confirm(bool result)
{
if (result) {
save();
}
else {
mOptions.result = Screenshot::Cancel;
}
mPixmap = QPixmap(); // Cleanup just in case.
emit finished();
}
void Screenshot::discard()
{
confirm(false);
}
void Screenshot::save()
{
QString name = "";
QString fileName = "";
Screenshot::Result result = Screenshot::Fail;
if (mOptions.file && !mOptions.saveAs) {
name = newFileName();
}
else if (mOptions.file && mOptions.saveAs) {
name = QFileDialog::getSaveFileName(0, tr("Save as.."), newFileName(), "*" + extension());
}
if (!mOptions.replace && QFile::exists(name+extension())) {
// Ugly? You should see my wife!
int count = 0;
int cunt = 0;
QString naming = QFileInfo(name).fileName();
foreach(QString file, QFileInfo(name+extension()).dir().entryList(QDir::Files)) {
if (file.contains(naming)) {
file.remove(naming);
file.remove(" (");
file.remove(")");
file.remove(extension());
cunt = file.toInt();
if (cunt > count) {
count = cunt;
}
}
}
name = name + " (" + QString::number(count+1) + ")";
}
fileName = name + extension();
// In the following code I use (Screenshot::Result)1 instead of Screenshot::Success because of some weird issue with the X11 headers. //TODO
if (mOptions.file) {
if (fileName.isEmpty()) {
result = Screenshot::Fail;
}
else if (mUnloaded) {
result = (QFile::rename(mUnloadFilename, fileName)) ? (Screenshot::Result)1: Screenshot::Fail;
}
else if (mPixmap.save(fileName, 0, mOptions.quality)) {
result = (Screenshot::Result)1;
}
else {
result = Screenshot::Fail;
}
os::addToRecentDocuments(fileName);
}
if (mOptions.clipboard) {
QApplication::clipboard()->setPixmap(mPixmap, QClipboard::Clipboard);
if (!mOptions.file) {
result = (Screenshot::Result)1;
}
}
mPixmap = QPixmap();
mOptions.fileName = fileName;
mOptions.result = result;
}
void Screenshot::setPixmap(QPixmap pixmap)
{
mPixmap = pixmap;
if (mPixmap.isNull()) {
emit confirm(false);
}
else {
confirmation();
}
}
void Screenshot::confirmation()
{
emit askConfirmation();
if (!mOptions.file) {
return;
}
// Unloading the pixmap to reduce memory usage during previews
- mUnloadFilename = mOptions.directory.path() + QDir::separator() + QString("lstemp.%1%2").arg(qrand() * qrand() + QDateTime::currentDateTime().toTime_t()).arg(extension());
+ mUnloadFilename = mOptions.directory.path() + QDir::separator() + QString(".lstemp.%1%2").arg(qrand() * qrand() + QDateTime::currentDateTime().toTime_t()).arg(extension());
mUnloaded = mPixmap.save(mUnloadFilename, 0, mOptions.quality);
if (mUnloaded) {
mPixmap = QPixmap();
}
}

File Metadata

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

Event Timeline