aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorJ-P Nurmi <jpnurmi@digia.com>2013-09-13 18:47:29 +0200
committerThe Qt Project <gerrit-noreply@qt-project.org>2013-09-20 10:12:21 +0200
commit0eade30f37980c38b14d5cfa475837d15b69a8c5 (patch)
tree1c4f4232086ede3cb3ad62bed1eca053c2977b52 /src
parent6e81cfd302e48e7ae4ecab44b377eeffaa45cd73 (diff)
Jump Lists: introduce "categories" & hide COM
QWinJumpList now has three built-in categories: Recent, Frequent and Tasks. In addition to that, user can add custom categories. A new type, QWinJumpListCategory, represents all these categories, providing access to items in the category. The former COM-like begin(), append(), commit(), abort() API has been replaced by a more property/ attribute-based API. The jump list automatically invalidates and lazily rebuilds itself behind the scenes. Furthermore, the API has been minimalized for now - restoring the application identifier as a full-fledged property is in the works. Change-Id: I623a658b4b1fcfc881006f67e2300acadb483c97 Reviewed-by: Ivan Vizir <define-true-false@yandex.com> Reviewed-by: Jan Arve Sæther <jan-arve.saether@digia.com>
Diffstat (limited to 'src')
-rw-r--r--src/imports/winextras/qquickjumplist.cpp18
-rw-r--r--src/imports/winextras/qquickjumplist_p.h1
-rw-r--r--src/winextras/qwinjumplist.cpp876
-rw-r--r--src/winextras/qwinjumplist.h37
-rw-r--r--src/winextras/qwinjumplist_p.h97
-rw-r--r--src/winextras/qwinjumplistcategory.cpp319
-rw-r--r--src/winextras/qwinjumplistcategory.h98
-rw-r--r--src/winextras/qwinjumplistcategory_p.h78
-rw-r--r--src/winextras/qwinjumplistitem.cpp70
-rw-r--r--src/winextras/qwinjumplistitem.h4
-rw-r--r--src/winextras/qwinjumplistitem_p.h74
-rw-r--r--src/winextras/windowsguidsdefs.cpp4
-rw-r--r--src/winextras/winextras.pro7
-rw-r--r--src/winextras/winshobjidl_p.h35
14 files changed, 1129 insertions, 589 deletions
diff --git a/src/imports/winextras/qquickjumplist.cpp b/src/imports/winextras/qquickjumplist.cpp
index 8ff70c2..b49be6d 100644
--- a/src/imports/winextras/qquickjumplist.cpp
+++ b/src/imports/winextras/qquickjumplist.cpp
@@ -124,24 +124,19 @@ void QQuickJumpList::componentComplete()
{
QQuickItem::componentComplete();
QWinJumpList jumplist;
- jumplist.begin();
- jumplist.setFrequentCategoryShown(frequentCategoryShown);
- jumplist.setRecentCategoryShown(recentCategoryShown);
+ jumplist.frequent()->setVisible(frequentCategoryShown);
+ jumplist.recent()->setVisible(recentCategoryShown);
if (!taskList.isEmpty()) {
- jumplist.beginTasks();
Q_FOREACH (QQuickJumpListItem *item, taskList)
- jumplist.addItem(item->toJumpListItem());
+ jumplist.tasks()->addItem(item->toJumpListItem());
taskList.clear();
}
if (!categoryList.isEmpty()) {
Q_FOREACH (QQuickJumpListCategory *category, categoryList) {
- jumplist.beginCategory(category->title());
QList<QWinJumpListItem *> items = category->toItemList();
- Q_FOREACH (QWinJumpListItem *item, items)
- jumplist.addItem(item);
+ jumplist.addCategory(category->title(), items);
}
}
- jumplist.commit();
}
void QQuickJumpList::appendTaskItem(QQmlListProperty<QQuickJumpListItem> *property, QQuickJumpListItem *value)
@@ -242,11 +237,8 @@ int QQuickJumpListItem::type() const
QWinJumpListItem *QQuickJumpListItem::toJumpListItem() const
{
- QWinJumpListItem *item = new QWinJumpListItem();
+ QWinJumpListItem *item = new QWinJumpListItem(QWinJumpListItem::Separator);
switch (m_type) {
- case ItemTypeSeparator :
- item->setType(QWinJumpListItem::Separator);
- break;
case ItemTypeDestination :
item->setType(QWinJumpListItem::Destination);
item->setFilePath(property("filePath").toString());
diff --git a/src/imports/winextras/qquickjumplist_p.h b/src/imports/winextras/qquickjumplist_p.h
index b64b1d5..0bb33a1 100644
--- a/src/imports/winextras/qquickjumplist_p.h
+++ b/src/imports/winextras/qquickjumplist_p.h
@@ -48,6 +48,7 @@
#include <QIcon>
#include <QWinJumpList>
#include <QWinJumpListItem>
+#include <QWinJumpListCategory>
QT_BEGIN_NAMESPACE
diff --git a/src/winextras/qwinjumplist.cpp b/src/winextras/qwinjumplist.cpp
index 498dbda..6fd61c9 100644
--- a/src/winextras/qwinjumplist.cpp
+++ b/src/winextras/qwinjumplist.cpp
@@ -1,6 +1,7 @@
/****************************************************************************
**
** Copyright (C) 2013 Ivan Vizir <define-true-false@yandex.com>
+ ** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of the QtWinExtras module of the Qt Toolkit.
@@ -40,7 +41,10 @@
****************************************************************************/
#include "qwinjumplist.h"
+#include "qwinjumplist_p.h"
#include "qwinjumplistitem.h"
+#include "qwinjumplistcategory.h"
+#include "qwinjumplistcategory_p.h"
#include <QDir>
#include <QCoreApplication>
@@ -49,7 +53,6 @@
#include "qwinfunctions.h"
#include "qwinfunctions_p.h"
-#include "winshobjidl_p.h"
#include "winpropkey_p.h"
QT_BEGIN_NAMESPACE
@@ -66,647 +69,466 @@ QT_BEGIN_NAMESPACE
files or to display shortcuts to tasks or commands.
*/
-/*!
- \enum QWinJumpListItem::Type
-
- This enum specifies QWinJumpListItem type, changing its meaning for QWinJumpList.
-
- \value Unknown
- Invalid item type.
- \value Destination
- Item acts as a link to a file that the application can open.
- \value Link
- Item represents a link to some application.
- \value Separator
- Item becomes a separator. This value is used only for task lists.
- */
-
-class QWinJumpListPrivate
+// partial copy of qprocess_win.cpp:qt_create_commandline()
+static QString createArguments(const QStringList &arguments)
{
-public:
- QWinJumpListPrivate() :
- pDestList(0), isListBegan(false), showFrequentCategory(false), showRecentCategory(false),
- categoryBegan(false), tasksBegan(false), listSize(0)
- {
+ QString args;
+ for (int i=0; i<arguments.size(); ++i) {
+ QString tmp = arguments.at(i);
+ // Quotes are escaped and their preceding backslashes are doubled.
+ tmp.replace(QRegExp(QLatin1String("(\\\\*)\"")), QLatin1String("\\1\\1\\\""));
+ if (tmp.isEmpty() || tmp.contains(QLatin1Char(' ')) || tmp.contains(QLatin1Char('\t'))) {
+ // The argument must not end with a \ since this would be interpreted
+ // as escaping the quote -- rather put the \ behind the quote: e.g.
+ // rather use "foo"\ than "foo\"
+ int i = tmp.length();
+ while (i > 0 && tmp.at(i - 1) == QLatin1Char('\\'))
+ --i;
+ tmp.insert(i, QLatin1Char('"'));
+ tmp.prepend(QLatin1Char('"'));
+ }
+ args += QLatin1Char(' ') + tmp;
}
+ return args;
+}
- static void warning(const char *function, HRESULT hresult)
- {
- const QString err = QtWin::errorStringFromHresult(hresult);
- qWarning("QWinJumpList: %s() failed: %#010x, %s.", function, (unsigned)hresult, qPrintable(err));
- }
+QWinJumpListPrivate::QWinJumpListPrivate() :
+ pDestList(0), recent(0), frequent(0), tasks(0), dirty(false)
+{
+}
- static QString iconsDirPath()
- {
- QString iconDirPath = QDir::tempPath() + QLatin1Char('/') + QCoreApplication::instance()->applicationName() + QLatin1String("/qt-jl-icons/");
- QDir().mkpath(iconDirPath);
- return iconDirPath;
- }
+void QWinJumpListPrivate::warning(const char *function, HRESULT hresult)
+{
+ const QString err = QtWin::errorStringFromHresult(hresult);
+ qWarning("QWinJumpList: %s() failed: %#010x, %s.", function, (unsigned)hresult, qPrintable(err));
+}
- bool appendKnownCategory(KNOWNDESTCATEGORY category)
- {
- if (!pDestList)
- return false;
+QString QWinJumpListPrivate::iconsDirPath()
+{
+ QString iconDirPath = QDir::tempPath() + QLatin1Char('/') + QCoreApplication::instance()->applicationName() + QLatin1String("/qt-jl-icons/");
+ QDir().mkpath(iconDirPath);
+ return iconDirPath;
+}
- HRESULT hresult = pDestList->AppendKnownCategory(category);
- if (FAILED(hresult))
- warning("AppendKnownCategory", hresult);
+void QWinJumpListPrivate::invalidate()
+{
+ Q_Q(QWinJumpList);
+ if (!pDestList)
+ return;
- return SUCCEEDED(hresult);
+ if (!dirty) {
+ dirty = true;
+ QMetaObject::invokeMethod(q, "_q_rebuild", Qt::QueuedConnection);
}
+}
- void appendCategory()
- {
- IObjectCollection *collection = toComCollection(jumpListItems);
- if (collection) {
- wchar_t *title = qt_qstringToNullTerminated(currentlyBuiltCategoryTitle);
- pDestList->AppendCategory(title, collection);
- delete[] title;
- collection->Release();
+void QWinJumpListPrivate::_q_rebuild()
+{
+ if (beginList()) {
+ if (recent && recent->isVisible())
+ appendKnownCategory(KDC_RECENT);
+ if (frequent && frequent->isVisible())
+ appendKnownCategory(KDC_FREQUENT);
+ foreach (QWinJumpListCategory *category, categories) {
+ if (category->isVisible())
+ appendCustomCategory(category);
}
+ if (tasks && tasks->isVisible())
+ appendTasks(tasks->items());
+ commitList();
}
+ dirty = false;
+}
- void appendTasks()
- {
- IObjectCollection *collection = toComCollection(jumpListItems);
- if (collection) {
- pDestList->AddUserTasks(collection);
- collection->Release();
- }
+void QWinJumpListPrivate::destroy(bool clear)
+{
+ if (recent) {
+ if (clear)
+ recent->clear();
+ delete recent;
+ recent = 0;
}
-
- inline void clearItems()
- {
- isListBegan = false;
- qDeleteAll(jumpListItems);
- jumpListItems.clear();
+ if (frequent) {
+ if (clear)
+ frequent->clear();
+ delete frequent;
+ frequent = 0;
}
-
- static QList<QWinJumpListItem *> fromComCollection(IObjectArray *array)
- {
- QList<QWinJumpListItem *> list;
- UINT count = 0;
- array->GetCount(&count);
- for (unsigned i = 0; i < count; i++) {
- IUnknown *collectionItem = 0;
- HRESULT hresult = array->GetAt(i, IID_IUnknown, reinterpret_cast<void **>(collectionItem));
- if (FAILED(hresult))
- continue;
- IShellItem2 *shellItem = 0;
- IShellLinkW *shellLink = 0;
- QWinJumpListItem *jumplistItem = 0;
- if (SUCCEEDED(collectionItem->QueryInterface(IID_IShellItem2, reinterpret_cast<void **>(shellItem)))) {
- jumplistItem = fromIShellItem(shellItem);
- shellItem->Release();
- } else if (SUCCEEDED(collectionItem->QueryInterface(IID_IShellLinkW, reinterpret_cast<void **>(shellLink)))) {
- jumplistItem = fromIShellLink(shellLink);
- shellLink->Release();
- } else {
- qWarning("QWinJumpList: object of unexpected class found");
- }
- collectionItem->Release();
- if (jumplistItem)
- list.append(jumplistItem);
- }
- return list;
+ if (tasks) {
+ if (clear)
+ tasks->clear();
+ delete tasks;
+ tasks = 0;
}
-
- static IObjectCollection *toComCollection(const QList<QWinJumpListItem *> &list)
- {
- if (list.isEmpty())
- return 0;
- IObjectCollection *collection = 0;
- HRESULT hresult = CoCreateInstance(CLSID_EnumerableObjectCollection, 0, CLSCTX_INPROC_SERVER, IID_IObjectCollection, reinterpret_cast<void **>(&collection));
- if (FAILED(hresult)) {
- const QString err = QtWin::errorStringFromHresult(hresult);
- qWarning("QWinJumpList: failed to instantiate IObjectCollection: %#010x, %s.", (unsigned)hresult, qPrintable(err));
- return 0;
- }
- Q_FOREACH (QWinJumpListItem *item, list) {
- IUnknown *iitem = toICustomDestinationListItem(item);
- if (iitem) {
- collection->AddObject(iitem);
- iitem->Release();
- }
- }
- return collection;
+ foreach (QWinJumpListCategory *category, categories) {
+ if (clear)
+ category->clear();
+ delete category;
}
+ categories.clear();
+ invalidate();
+}
- static QWinJumpListItem *fromIShellLink(IShellLinkW *link)
- {
- QWinJumpListItem *item = new QWinJumpListItem(QWinJumpListItem::Link);
-
- IPropertyStore *linkProps;
- link->QueryInterface(IID_IPropertyStore, reinterpret_cast<void **>(&linkProps));
- PROPVARIANT var;
- linkProps->GetValue(PKEY_Link_Arguments, &var);
- item->setArguments(QStringList(QString::fromWCharArray(var.pwszVal)));
- PropVariantClear(&var);
- linkProps->Release();
-
- const int buffersize = 2048;
- wchar_t buffer[buffersize] = {0};
-
- link->GetDescription(buffer, INFOTIPSIZE);
- item->setDescription(QString::fromWCharArray(buffer));
+bool QWinJumpListPrivate::beginList()
+{
+ UINT maxSlots;
+ IUnknown *array = 0;
+ HRESULT hresult = pDestList->BeginList(&maxSlots, IID_IUnknown, reinterpret_cast<void **>(&array));
+ if (FAILED(hresult))
+ QWinJumpListPrivate::warning("BeginList", hresult);
+ if (array)
+ array->Release();
+ return SUCCEEDED(hresult);
+}
- memset(buffer, 0, buffersize * sizeof(wchar_t));
- int dummyindex;
- link->GetIconLocation(buffer, buffersize-1, &dummyindex);
- item->setIcon(QIcon(QString::fromWCharArray(buffer)));
+bool QWinJumpListPrivate::commitList()
+{
+ HRESULT hresult = pDestList->CommitList();
+ if (FAILED(hresult))
+ QWinJumpListPrivate::warning("CommitList", hresult);
+ return SUCCEEDED(hresult);
+}
- memset(buffer, 0, buffersize * sizeof(wchar_t));
- link->GetPath(buffer, buffersize-1, 0, 0);
- item->setFilePath(QString::fromWCharArray(buffer));
+void QWinJumpListPrivate::appendKnownCategory(KNOWNDESTCATEGORY category)
+{
+ HRESULT hresult = pDestList->AppendKnownCategory(category);
+ if (FAILED(hresult))
+ QWinJumpListPrivate::warning("AppendKnownCategory", hresult);
+}
- return item;
+void QWinJumpListPrivate::appendCustomCategory(QWinJumpListCategory *category)
+{
+ IObjectCollection *collection = toComCollection(category->items());
+ if (collection) {
+ wchar_t *title = qt_qstringToNullTerminated(category->title());
+ HRESULT hresult = pDestList->AppendCategory(title, collection);
+ if (FAILED(hresult))
+ QWinJumpListPrivate::warning("AppendCategory", hresult);
+ delete[] title;
+ collection->Release();
}
+}
- static QWinJumpListItem *fromIShellItem(IShellItem2 *shellitem)
- {
- QWinJumpListItem *item = new QWinJumpListItem(QWinJumpListItem::Destination);
- wchar_t *strPtr;
- shellitem->GetDisplayName(SIGDN_FILESYSPATH, &strPtr);
- item->setFilePath(QString::fromWCharArray(strPtr));
- CoTaskMemFree(strPtr);
- return item;
+void QWinJumpListPrivate::appendTasks(const QList<QWinJumpListItem *> &items)
+{
+ IObjectCollection *collection = toComCollection(items);
+ if (collection) {
+ HRESULT hresult = pDestList->AddUserTasks(collection);
+ if (FAILED(hresult))
+ QWinJumpListPrivate::warning("AddUserTasks", hresult);
+ collection->Release();
}
+}
- // partial copy of qprocess_win.cpp:qt_create_commandline()
- static QString createArguments(const QStringList &arguments)
- {
- QString args;
- for (int i=0; i<arguments.size(); ++i) {
- QString tmp = arguments.at(i);
- // Quotes are escaped and their preceding backslashes are doubled.
- tmp.replace(QRegExp(QLatin1String("(\\\\*)\"")), QLatin1String("\\1\\1\\\""));
- if (tmp.isEmpty() || tmp.contains(QLatin1Char(' ')) || tmp.contains(QLatin1Char('\t'))) {
- // The argument must not end with a \ since this would be interpreted
- // as escaping the quote -- rather put the \ behind the quote: e.g.
- // rather use "foo"\ than "foo\"
- int i = tmp.length();
- while (i > 0 && tmp.at(i - 1) == QLatin1Char('\\'))
- --i;
- tmp.insert(i, QLatin1Char('"'));
- tmp.prepend(QLatin1Char('"'));
- }
- args += QLatin1Char(' ') + tmp;
+QList<QWinJumpListItem *> QWinJumpListPrivate::fromComCollection(IObjectArray *array)
+{
+ QList<QWinJumpListItem *> list;
+ UINT count = 0;
+ array->GetCount(&count);
+ for (UINT i = 0; i < count; ++i) {
+ IUnknown *collectionItem = 0;
+ HRESULT hresult = array->GetAt(i, IID_IUnknown, reinterpret_cast<void **>(&collectionItem));
+ if (FAILED(hresult)) {
+ QWinJumpListPrivate::warning("GetAt", hresult);
+ continue;
+ }
+ IShellItem2 *shellItem = 0;
+ IShellLinkW *shellLink = 0;
+ QWinJumpListItem *jumplistItem = 0;
+ if (SUCCEEDED(collectionItem->QueryInterface(IID_IShellItem2, reinterpret_cast<void **>(&shellItem)))) {
+ jumplistItem = fromIShellItem(shellItem);
+ shellItem->Release();
+ } else if (SUCCEEDED(collectionItem->QueryInterface(IID_IShellLinkW, reinterpret_cast<void **>(&shellLink)))) {
+ jumplistItem = fromIShellLink(shellLink);
+ shellLink->Release();
+ } else {
+ qWarning("QWinJumpList: object of unexpected class found");
}
- return args;
+ collectionItem->Release();
+ if (jumplistItem)
+ list.append(jumplistItem);
}
+ return list;
+}
- static IUnknown *toICustomDestinationListItem(const QWinJumpListItem *item)
- {
- switch (item->type()) {
- case QWinJumpListItem::Destination :
- return toIShellItem(item);
- case QWinJumpListItem::Link :
- return toIShellLink(item);
- case QWinJumpListItem::Separator :
- return makeSeparatorShellItem();
- default:
- return 0;
+IObjectCollection *QWinJumpListPrivate::toComCollection(const QList<QWinJumpListItem *> &list)
+{
+ if (list.isEmpty())
+ return 0;
+ IObjectCollection *collection = 0;
+ HRESULT hresult = CoCreateInstance(CLSID_EnumerableObjectCollection, 0, CLSCTX_INPROC_SERVER, IID_IObjectCollection, reinterpret_cast<void **>(&collection));
+ if (FAILED(hresult)) {
+ QWinJumpListPrivate::warning("QWinJumpList: failed to instantiate IObjectCollection", hresult);
+ return 0;
+ }
+ Q_FOREACH (QWinJumpListItem *item, list) {
+ IUnknown *iitem = toICustomDestinationListItem(item);
+ if (iitem) {
+ collection->AddObject(iitem);
+ iitem->Release();
}
}
+ return collection;
+}
- static IShellLinkW *toIShellLink(const QWinJumpListItem *item)
- {
- IShellLinkW *link = 0;
- HRESULT hresult = CoCreateInstance(CLSID_ShellLink, 0, CLSCTX_INPROC_SERVER, IID_IShellLinkW, reinterpret_cast<void **>(&link));
- if (FAILED(hresult)) {
- const QString err = QtWin::errorStringFromHresult(hresult);
- qWarning("QWinJumpList: failed to instantiate IShellLinkW: %#010x, %s.", (unsigned)hresult, qPrintable(err));
- return 0;
- }
+QWinJumpListItem *QWinJumpListPrivate::fromIShellLink(IShellLinkW *link)
+{
+ QWinJumpListItem *item = new QWinJumpListItem(QWinJumpListItem::Link);
- const int iconPathSize = QWinJumpListPrivate::iconsDirPath().size() + sizeof(void *)*2 + 4; // path + ptr-name-in-hex + .ico
- const int bufferSize = qMax(item->workingDirectory().size(), qMax(item->description().size(), qMax(item->title().size(), qMax(item->filePath().size(), iconPathSize)))) + 1;
- wchar_t *buffer = new wchar_t[bufferSize];
+ IPropertyStore *linkProps;
+ link->QueryInterface(IID_IPropertyStore, reinterpret_cast<void **>(&linkProps));
+ PROPVARIANT var;
+ linkProps->GetValue(PKEY_Link_Arguments, &var);
+ item->setArguments(QStringList(QString::fromWCharArray(var.pwszVal)));
+ PropVariantClear(&var);
+ linkProps->Release();
- if (!item->description().isEmpty()) {
- qt_qstringToNullTerminated(item->description(), buffer);
- link->SetDescription(buffer);
- }
+ const int buffersize = 2048;
+ wchar_t buffer[buffersize];
- qt_qstringToNullTerminated(item->filePath(), buffer);
- link->SetPath(buffer);
+ link->GetDescription(buffer, INFOTIPSIZE);
+ item->setDescription(QString::fromWCharArray(buffer));
- if (!item->workingDirectory().isEmpty()) {
- qt_qstringToNullTerminated(item->workingDirectory(), buffer);
- link->SetWorkingDirectory(buffer);
- }
+ int dummyindex;
+ link->GetIconLocation(buffer, buffersize-1, &dummyindex);
+ item->setIcon(QIcon(QString::fromWCharArray(buffer)));
- QString args = createArguments(item->arguments());
+ link->GetPath(buffer, buffersize-1, 0, 0);
+ item->setFilePath(QString::fromWCharArray(buffer));
- qt_qstringToNullTerminated(args, buffer);
- link->SetArguments(buffer);
+ return item;
+}
- if (!item->icon().isNull()) {
- QString iconPath = QWinJumpListPrivate::iconsDirPath() + QString::number(reinterpret_cast<quintptr>(item), 16) + QLatin1String(".ico");
- bool iconSaved = item->icon().pixmap(GetSystemMetrics(SM_CXICON)).save(iconPath, "ico");
- if (iconSaved) {
- qt_qstringToNullTerminated(iconPath, buffer);
- link->SetIconLocation(buffer, 0);
- }
- }
+QWinJumpListItem *QWinJumpListPrivate::fromIShellItem(IShellItem2 *shellitem)
+{
+ QWinJumpListItem *item = new QWinJumpListItem(QWinJumpListItem::Destination);
+ wchar_t *strPtr;
+ shellitem->GetDisplayName(SIGDN_FILESYSPATH, &strPtr);
+ item->setFilePath(QString::fromWCharArray(strPtr));
+ CoTaskMemFree(strPtr);
+ return item;
+}
- IPropertyStore *properties;
- PROPVARIANT titlepv;
- hresult = link->QueryInterface(IID_IPropertyStore, reinterpret_cast<void **>(&properties));
- if (FAILED(hresult)) {
- link->Release();
- return 0;
- }
+IUnknown *QWinJumpListPrivate::toICustomDestinationListItem(const QWinJumpListItem *item)
+{
+ switch (item->type()) {
+ case QWinJumpListItem::Destination :
+ return toIShellItem(item);
+ case QWinJumpListItem::Link :
+ return toIShellLink(item);
+ case QWinJumpListItem::Separator :
+ return makeSeparatorShellItem();
+ default:
+ return 0;
+ }
+}
- qt_qstringToNullTerminated(item->title(), buffer);
- InitPropVariantFromString(buffer, &titlepv);
- properties->SetValue(PKEY_Title, titlepv);
- properties->Commit();
- properties->Release();
- PropVariantClear(&titlepv);
+IShellLinkW *QWinJumpListPrivate::toIShellLink(const QWinJumpListItem *item)
+{
+ IShellLinkW *link = 0;
+ HRESULT hresult = CoCreateInstance(CLSID_ShellLink, 0, CLSCTX_INPROC_SERVER, IID_IShellLinkW, reinterpret_cast<void **>(&link));
+ if (FAILED(hresult)) {
+ QWinJumpListPrivate::warning("QWinJumpList: failed to instantiate IShellLinkW", hresult);
+ return 0;
+ }
- delete[] buffer;
- return link;
+ const QString args = createArguments(item->arguments());
+ const int iconPathSize = QWinJumpListPrivate::iconsDirPath().size() + sizeof(void *)*2 + 4; // path + ptr-name-in-hex + .ico
+ const int bufferSize = qMax(args.size(), qMax(item->workingDirectory().size(), qMax(item->description().size(), qMax(item->title().size(), qMax(item->filePath().size(), iconPathSize))))) + 1;
+ wchar_t *buffer = new wchar_t[bufferSize];
+
+ if (!item->description().isEmpty()) {
+ qt_qstringToNullTerminated(item->description(), buffer);
+ link->SetDescription(buffer);
}
- static IShellItem2 *toIShellItem(const QWinJumpListItem *item)
- {
- IShellItem2 *shellitem = 0;
- wchar_t *buffer = new wchar_t[item->filePath().length() + 1];
- qt_qstringToNullTerminated(item->filePath(), buffer);
- qt_SHCreateItemFromParsingName(buffer, 0, IID_IShellItem2, reinterpret_cast<void **>(&shellitem));
- delete[] buffer;
- return shellitem;
+ qt_qstringToNullTerminated(item->filePath(), buffer);
+ link->SetPath(buffer);
+
+ if (!item->workingDirectory().isEmpty()) {
+ qt_qstringToNullTerminated(item->workingDirectory(), buffer);
+ link->SetWorkingDirectory(buffer);
}
- static IShellLinkW *makeSeparatorShellItem()
- {
- IShellLinkW *separator;
- HRESULT res = CoCreateInstance(CLSID_ShellLink, 0, CLSCTX_INPROC_SERVER, IID_IShellLinkW, reinterpret_cast<void **>(&separator));
- if (FAILED(res))
- return 0;
-
- IPropertyStore *properties;
- res = separator->QueryInterface(IID_IPropertyStore, reinterpret_cast<void **>(&properties));
- if (FAILED(res)) {
- separator->Release();
- return 0;
- }
+ qt_qstringToNullTerminated(args, buffer);
+ link->SetArguments(buffer);
- PROPVARIANT isSeparator;
- InitPropVariantFromBoolean(TRUE, &isSeparator);
- properties->SetValue(PKEY_AppUserModel_IsDestListSeparator, isSeparator);
- properties->Commit();
- properties->Release();
- PropVariantClear(&isSeparator);
+ if (!item->icon().isNull()) {
+ QString iconPath = QWinJumpListPrivate::iconsDirPath() + QString::number(reinterpret_cast<quintptr>(item), 16) + QLatin1String(".ico");
+ bool iconSaved = item->icon().pixmap(GetSystemMetrics(SM_CXICON)).save(iconPath, "ico");
+ if (iconSaved) {
+ qt_qstringToNullTerminated(iconPath, buffer);
+ link->SetIconLocation(buffer, 0);
+ }
+ }
- return separator;
+ IPropertyStore *properties;
+ PROPVARIANT titlepv;
+ hresult = link->QueryInterface(IID_IPropertyStore, reinterpret_cast<void **>(&properties));
+ if (FAILED(hresult)) {
+ link->Release();
+ return 0;
}
- ICustomDestinationList *pDestList;
- bool isListBegan;
- bool showFrequentCategory;
- bool showRecentCategory;
- QString currentlyBuiltCategoryTitle;
- bool categoryBegan;
- bool tasksBegan;
- QList<QWinJumpListItem *> jumpListItems;
- UINT listSize;
-};
+ qt_qstringToNullTerminated(item->title(), buffer);
+ InitPropVariantFromString(buffer, &titlepv);
+ properties->SetValue(PKEY_Title, titlepv);
+ properties->Commit();
+ properties->Release();
+ PropVariantClear(&titlepv);
-/*!
- Constructs a QWinJumpList with the parent object \a parent.
- */
-QWinJumpList::QWinJumpList(QObject *parent) :
- QObject(parent), d_ptr(new QWinJumpListPrivate)
-{
- HRESULT hresult = CoCreateInstance(CLSID_DestinationList, 0, CLSCTX_INPROC_SERVER, IID_ICustomDestinationList, reinterpret_cast<void **>(&d_ptr->pDestList));
- if (FAILED(hresult))
- QWinJumpListPrivate::warning("CoCreateInstance", hresult);
+ delete[] buffer;
+ return link;
}
-/*!
- Destroys the QWinJumpList. If commit() or abort() were not called for the
- corresponding begin() call, building the Jump List is aborted.
- */
-QWinJumpList::~QWinJumpList()
+IShellItem2 *QWinJumpListPrivate::toIShellItem(const QWinJumpListItem *item)
{
- Q_D(QWinJumpList);
- if (d->isListBegan)
- abort();
- if (d->pDestList)
- d->pDestList->Release();
+ IShellItem2 *shellitem = 0;
+ wchar_t *buffer = qt_qstringToNullTerminated(item->filePath());
+ qt_SHCreateItemFromParsingName(buffer, 0, IID_IShellItem2, reinterpret_cast<void **>(&shellitem));
+ delete[] buffer;
+ return shellitem;
}
-/*!
- Initiates Jump List building.
- This method must be called before adding Jump List items.
- Returns true if successful; otherwise returns false.
- */
-bool QWinJumpList::begin()
+IShellLinkW *QWinJumpListPrivate::makeSeparatorShellItem()
{
- Q_D(QWinJumpList);
- if (!d->pDestList)
- return false;
+ IShellLinkW *separator;
+ HRESULT res = CoCreateInstance(CLSID_ShellLink, 0, CLSCTX_INPROC_SERVER, IID_IShellLinkW, reinterpret_cast<void **>(&separator));
+ if (FAILED(res))
+ return 0;
- UINT maxSlots;
- IUnknown *array;
- HRESULT hresult = d->pDestList->BeginList(&maxSlots, IID_IUnknown, reinterpret_cast<void **>(&array));
- if (SUCCEEDED(hresult)) {
- array->Release();
- d->isListBegan = true;
- } else {
- QWinJumpListPrivate::warning("BeginList", hresult);
+ IPropertyStore *properties;
+ res = separator->QueryInterface(IID_IPropertyStore, reinterpret_cast<void **>(&properties));
+ if (FAILED(res)) {
+ separator->Release();
+ return 0;
}
- return SUCCEEDED(hresult);
-}
-/*!
- Completes Jump List building, initiated by begin(), and displays it.
- Returns true if successful; otherwise returns false.
- */
-bool QWinJumpList::commit()
-{
- Q_D(QWinJumpList);
- if (!d->pDestList || !d->isListBegan)
- return false;
-
- if (d->showFrequentCategory)
- d->appendKnownCategory(KDC_FREQUENT);
- if (d->showRecentCategory)
- d->appendKnownCategory(KDC_RECENT);
-
- if (d->tasksBegan) {
- d->appendTasks();
- } else if (d->categoryBegan) {
- d->appendCategory();
- }
+ PROPVARIANT isSeparator;
+ InitPropVariantFromBoolean(TRUE, &isSeparator);
+ properties->SetValue(PKEY_AppUserModel_IsDestListSeparator, isSeparator);
+ properties->Commit();
+ properties->Release();
+ PropVariantClear(&isSeparator);
- d->clearItems();
- HRESULT hresult = d->pDestList->CommitList();
- if (FAILED(hresult))
- QWinJumpListPrivate::warning("CommitList", hresult);
- return SUCCEEDED(hresult);
+ return separator;
}
/*!
- Aborts Jump List building initiated by begin() and leaves the currently
- active Jump List unchanged.
- Returns true if successful; otherwise returns false.
+ Constructs a QWinJumpList with the parent object \a parent.
*/
-bool QWinJumpList::abort()
+QWinJumpList::QWinJumpList(QObject *parent) :
+ QObject(parent), d_ptr(new QWinJumpListPrivate)
{
Q_D(QWinJumpList);
- if (!d->pDestList)
- return false;
-
- d->clearItems();
- HRESULT hresult = d->pDestList->AbortList();
+ d->q_ptr = this;
+ HRESULT hresult = CoCreateInstance(CLSID_DestinationList, 0, CLSCTX_INPROC_SERVER, IID_ICustomDestinationList, reinterpret_cast<void **>(&d_ptr->pDestList));
if (FAILED(hresult))
- QWinJumpListPrivate::warning("AbortList", hresult);
- return SUCCEEDED(hresult);
+ QWinJumpListPrivate::warning("CoCreateInstance", hresult);
+ d->invalidate();
}
/*!
- Clears the application Jump List.
- Returns true if successful; otherwise returns false.
+ Destroys the QWinJumpList.
*/
-bool QWinJumpList::clear()
+QWinJumpList::~QWinJumpList()
{
Q_D(QWinJumpList);
- if (!d->pDestList)
- return false;
-
- bool result;
- if (!d->isListBegan) {
- begin();
- result = commit();
- } else {
- result = abort() && clear() && begin();
+ if (d->dirty)
+ d->_q_rebuild();
+ if (d->pDestList) {
+ d->pDestList->Release();
+ d->pDestList = 0;
}
- return result;
-}
-/*!
- Specifies a unique AppUserModelID \a appId for the application whose custom
- Jump List will be built using this object.
- This is optional.
- This method must be called before begin().
- Returns true if successful; otherwise returns false.
-*/
-bool QWinJumpList::setApplicationId(const QString &appId)
-{
- Q_D(QWinJumpList);
- if (!d->pDestList)
- return false;
-
- wchar_t *wcAppId = qt_qstringToNullTerminated(appId);
- HRESULT hresult = d->pDestList->SetAppID(wcAppId);
- delete[] wcAppId;
- if (FAILED(hresult))
- QWinJumpListPrivate::warning("SetAppID", hresult);
- return SUCCEEDED(hresult);
+ const bool clear = false;
+ d->destroy(clear);
}
/*!
- Retrieves destinations that were removed by the user and must not be added
- again.
- Adding a group with removed destinations will fail.
+ Returns the recent items category in the jump list.
*/
-QList<QWinJumpListItem *> QWinJumpList::removedDestinations() const
+QWinJumpListCategory *QWinJumpList::recent() const
{
Q_D(const QWinJumpList);
- IObjectArray *array = 0;
- d->pDestList->GetRemovedDestinations(IID_IObjectArray, reinterpret_cast<void **>(&array));
- QList<QWinJumpListItem *> list = QWinJumpListPrivate::fromComCollection(array);
- array->Release();
- return list;
+ if (!d->recent) {
+ QWinJumpList *that = const_cast<QWinJumpList *>(this);
+ that->d_func()->recent = QWinJumpListCategoryPrivate::create(QWinJumpListCategory::Recent, that);
+ }
+ return d->recent;
}
/*!
- Returns the number of items that the Jump List will display. This is
- configured by the user.
+ Returns the frequent items category in the jump list.
*/
-int QWinJumpList::capacity() const
-{
- Q_D(const QWinJumpList);
- return d->listSize;
-}
-
-/*!
- \property QWinJumpList::recentCategoryShown
- \brief whether to show the known Recent category
-
- The default value of this property is false.
- Changes to this property are applied only after commit() is called.
-*/
-void QWinJumpList::setRecentCategoryShown(bool show)
-{
- Q_D(QWinJumpList);
- d->showRecentCategory = show;
-}
-
-bool QWinJumpList::isRecentCategoryShown() const
+QWinJumpListCategory *QWinJumpList::frequent() const
{
Q_D(const QWinJumpList);
- return d->showRecentCategory;
-}
-
-/*!
- \property QWinJumpList::frequentCategoryShown
- \brief whether to show the known Frequent category
-
- The default value of this property is false.
- Changes to this property are applied only after commit() is called.
-*/
-void QWinJumpList::setFrequentCategoryShown(bool show)
-{
- Q_D(QWinJumpList);
- d->showFrequentCategory = show;
-}
-
-bool QWinJumpList::isFrequentCategoryShown() const
-{
- Q_D(const QWinJumpList);
- return d->showFrequentCategory;
-}
-
-/*!
- Declares the building of a custom category with the specified \a title.
-
- begin() must be called before calling this method.
- */
-void QWinJumpList::beginCategory(const QString &title)
-{
- Q_D(QWinJumpList);
- if (!d->pDestList)
- return;
-
- if (d->categoryBegan) {
- d->appendCategory();
- } else if (d->tasksBegan) {
- d->appendTasks();
+ if (!d->frequent) {
+ QWinJumpList *that = const_cast<QWinJumpList *>(this);
+ that->d_func()->frequent = QWinJumpListCategoryPrivate::create(QWinJumpListCategory::Frequent, that);
}
- d->currentlyBuiltCategoryTitle = title;
+ return d->frequent;
}
/*!
- Declares the building of a task list.
-
- begin() must be called before calling this method.
+ Returns the tasks category in the jump list.
*/
-void QWinJumpList::beginTasks()
+QWinJumpListCategory *QWinJumpList::tasks() const
{
- Q_D(QWinJumpList);
- if (!d->pDestList)
- return;
-
- if (d->categoryBegan) {
- d->appendCategory();
+ Q_D(const QWinJumpList);
+ if (!d->tasks) {
+ QWinJumpList *that = const_cast<QWinJumpList *>(this);
+ that->d_func()->tasks = QWinJumpListCategoryPrivate::create(QWinJumpListCategory::Tasks, that);
}
- d->tasksBegan = true;
+ return d->tasks;
}
/*!
- Adds an \a item to the Jump List.
-
- beginCategory() or beginTasks() should be called before calling this method.
- Returns true if successful; otherwise returns false.
-
- \warning The \a item pointer becomes invalid after calling any of the following
- methods: beginCategory(), beginTasks(), commit(), abort(), or clear().
+ Returns the custom categories in the jump list.
*/
-bool QWinJumpList::addItem(QWinJumpListItem *item)
+QList<QWinJumpListCategory *> QWinJumpList::categories() const
{
- Q_D(QWinJumpList);
- if (!d->pDestList || (!d->categoryBegan && !d->tasksBegan)) {
- return false;
- }
-
- d->jumpListItems.append(item);
- return true;
+ Q_D(const QWinJumpList);
+ return d->categories;
}
/*!
- Adds a destination to the Jump List pointing to \a filePath.
-
- beginCategory() or beginTasks() should be called before calling this method.
- Returns the item if successful; otherwise returns 0.
-
- \warning The returned pointer becomes invalid after calling any of the following
- methods: beginCategory(), beginTasks(), commit(), abort(), or clear().
+ Adds a custom \a category to the jump list.
*/
-QWinJumpListItem *QWinJumpList::addDestination(const QString &filePath)
+void QWinJumpList::addCategory(QWinJumpListCategory *category)
{
Q_D(QWinJumpList);
- if (!d->pDestList || (!d->categoryBegan && !d->tasksBegan))
- return 0;
-
- QWinJumpListItem *item = new QWinJumpListItem(QWinJumpListItem::Destination);
- item->setFilePath(filePath);
- d->jumpListItems.append(item);
- return item;
+ QWinJumpListCategoryPrivate::get(category)->jumpList = this;
+ d->categories.append(category);
+ d->invalidate();
}
/*!
- Adds a link to the Jump List using \a title, \a executablePath, and
- optionally \a arguments.
-
- beginCategory() or beginTasks() should be called before calling this method.
- Returns the item if successful; otherwise returns 0.
-
- \warning The returned pointer becomes invalid after calling any of the following
- methods: beginCategory(), beginTasks(), commit(), abort(), or clear().
+ \overload addCategory()
+ Creates a custom category with provided \a title and optional \a items,
+ and adds it to the jump list.
*/
-QWinJumpListItem *QWinJumpList::addLink(const QString &title, const QString &executablePath, const QStringList &arguments)
+QWinJumpListCategory *QWinJumpList::addCategory(const QString &title, const QList<QWinJumpListItem *> items)
{
- return addLink(QIcon(), title, executablePath, arguments);
+ QWinJumpListCategory *category = new QWinJumpListCategory(title);
+ foreach (QWinJumpListItem *item, items)
+ category->addItem(item);
+ addCategory(category);
+ return category;
}
/*!
- \overload addLink()
+ Clears the jump list.
- Adds a link to the Jump List using \a icon, \a title, \a executablePath,
- and optionally \a arguments.
-
- beginCategory() or beginTasks() should be called before calling this method.
- Returns the item if successful; otherwise returns 0.
-
- \warning The returned pointer becomes invalid after calling any of the following
- methods: beginCategory(), beginTasks(), commit(), abort(), or clear().
+ \sa QWinJumpListCategory::clear()
*/
-QWinJumpListItem *QWinJumpList::addLink(const QIcon &icon, const QString &title, const QString &executablePath, const QStringList &arguments)
+void QWinJumpList::clear()
{
Q_D(QWinJumpList);
- if (!d->pDestList || (!d->categoryBegan && !d->tasksBegan))
- return 0;
-
- QWinJumpListItem *item = new QWinJumpListItem(QWinJumpListItem::Link);
- item->setFilePath(executablePath);
- item->setTitle(title);
- item->setArguments(arguments);
- item->setIcon(icon);
- d->jumpListItems.append(item);
- return item;
-}
-
-/*!
- Adds a separator to the Jump List.
-
- beginTasks() should be called before calling this method.
- Returns the item if successful; otherwise returns 0.
-
- \warning The returned pointer becomes invalid after calling any of the following
- methods: beginCategory(), beginTasks(), commit(), abort(), or clear().
- */
-QWinJumpListItem *QWinJumpList::addSeparator()
-{
- Q_D(QWinJumpList);
- if (!d->pDestList || (!d->categoryBegan && !d->tasksBegan))
- return 0;
-
- QWinJumpListItem *item = new QWinJumpListItem(QWinJumpListItem::Separator);
- d->jumpListItems.append(item);
- return item;
+ const bool clear = true;
+ d->destroy(clear);
}
QT_END_NAMESPACE
+
+#include "moc_qwinjumplist.cpp"
diff --git a/src/winextras/qwinjumplist.h b/src/winextras/qwinjumplist.h
index 18ce2ea..bc4f431 100644
--- a/src/winextras/qwinjumplist.h
+++ b/src/winextras/qwinjumplist.h
@@ -1,6 +1,7 @@
/****************************************************************************
**
** Copyright (C) 2013 Ivan Vizir <define-true-false@yandex.com>
+ ** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of the QtWinExtras module of the Qt Toolkit.
@@ -49,49 +50,35 @@
QT_BEGIN_NAMESPACE
-class QIcon;
class QWinJumpListItem;
class QWinJumpListPrivate;
+class QWinJumpListCategory;
class Q_WINEXTRAS_EXPORT QWinJumpList : public QObject
{
Q_OBJECT
- Q_PROPERTY(bool recentCategoryShown READ isRecentCategoryShown WRITE setRecentCategoryShown)
- Q_PROPERTY(bool frequentCategoryShown READ isFrequentCategoryShown WRITE setFrequentCategoryShown)
public:
explicit QWinJumpList(QObject *parent = 0);
~QWinJumpList();
-public Q_SLOTS:
- bool begin();
- bool commit();
- bool abort();
- bool clear();
-
-public:
- bool setApplicationId(const QString &);
- QList<QWinJumpListItem *> removedDestinations() const;
- int capacity() const;
+ QWinJumpListCategory *recent() const;
+ QWinJumpListCategory *frequent() const;
+ QWinJumpListCategory *tasks() const;
- void setRecentCategoryShown(bool);
- bool isRecentCategoryShown() const;
- void setFrequentCategoryShown(bool);
- bool isFrequentCategoryShown() const;
+ QList<QWinJumpListCategory *> categories() const;
+ void addCategory(QWinJumpListCategory *category);
+ QWinJumpListCategory *addCategory(const QString &title, const QList<QWinJumpListItem *> items = QList<QWinJumpListItem *>());
- void beginCategory(const QString &title);
- void beginTasks();
-
- bool addItem(QWinJumpListItem *item);
- QWinJumpListItem *addDestination(const QString &filePath);
- QWinJumpListItem *addLink(const QString &title, const QString &executablePath, const QStringList &arguments = QStringList());
- QWinJumpListItem *addLink(const QIcon &icon, const QString &title, const QString &executablePath, const QStringList &arguments = QStringList());
- QWinJumpListItem *addSeparator();
+public Q_SLOTS:
+ void clear();
private:
Q_DISABLE_COPY(QWinJumpList)
Q_DECLARE_PRIVATE(QWinJumpList)
QScopedPointer<QWinJumpListPrivate> d_ptr;
+
+ Q_PRIVATE_SLOT(d_func(), void _q_rebuild())
};
QT_END_NAMESPACE
diff --git a/src/winextras/qwinjumplist_p.h b/src/winextras/qwinjumplist_p.h
new file mode 100644
index 0000000..c30d64b
--- /dev/null
+++ b/src/winextras/qwinjumplist_p.h
@@ -0,0 +1,97 @@
+/****************************************************************************
+ **
+ ** Copyright (C) 2013 Ivan Vizir <define-true-false@yandex.com>
+ ** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+ ** Contact: http://www.qt-project.org/legal
+ **
+ ** This file is part of the QtWinExtras module of the Qt Toolkit.
+ **
+ ** $QT_BEGIN_LICENSE:LGPL$
+ ** Commercial License Usage
+ ** Licensees holding valid commercial Qt licenses may use this file in
+ ** accordance with the commercial license agreement provided with the
+ ** Software or, alternatively, in accordance with the terms contained in
+ ** a written agreement between you and Digia. For licensing terms and
+ ** conditions see http://qt.digia.com/licensing. For further information
+ ** use the contact form at http://qt.digia.com/contact-us.
+ **
+ ** GNU Lesser General Public License Usage
+ ** Alternatively, this file may be used under the terms of the GNU Lesser
+ ** General Public License version 2.1 as published by the Free Software
+ ** Foundation and appearing in the file LICENSE.LGPL included in the
+ ** packaging of this file. Please review the following information to
+ ** ensure the GNU Lesser General Public License version 2.1 requirements
+ ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+ **
+ ** In addition, as a special exception, Digia gives you certain additional
+ ** rights. These rights are described in the Digia Qt LGPL Exception
+ ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+ **
+ ** GNU General Public License Usage
+ ** Alternatively, this file may be used under the terms of the GNU
+ ** General Public License version 3.0 as published by the Free Software
+ ** Foundation and appearing in the file LICENSE.GPL included in the
+ ** packaging of this file. Please review the following information to
+ ** ensure the GNU General Public License version 3.0 requirements will be
+ ** met: http://www.gnu.org/copyleft/gpl.html.
+ **
+ **
+ ** $QT_END_LICENSE$
+ **
+ ****************************************************************************/
+
+#ifndef QWINJUMPLIST_P_H
+#define QWINJUMPLIST_P_H
+
+#include "qwinjumplist.h"
+#include "winshobjidl_p.h"
+
+QT_BEGIN_NAMESPACE
+
+class QWinJumpListPrivate
+{
+ Q_DECLARE_PUBLIC(QWinJumpList)
+
+public:
+ QWinJumpListPrivate();
+
+ static QWinJumpListPrivate *get(QWinJumpList *list)
+ {
+ return list->d_func();
+ }
+
+ static void warning(const char *function, HRESULT hresult);
+ static QString iconsDirPath();
+
+ void invalidate();
+ void _q_rebuild();
+ void destroy(bool clear);
+
+ bool beginList();
+ bool commitList();
+
+ void appendKnownCategory(KNOWNDESTCATEGORY category);
+ void appendCustomCategory(QWinJumpListCategory *category);
+ void appendTasks(const QList<QWinJumpListItem *> &items);
+
+ static QList<QWinJumpListItem *> fromComCollection(IObjectArray *array);
+ static IObjectCollection *toComCollection(const QList<QWinJumpListItem *> &list);
+ static QWinJumpListItem *fromIShellLink(IShellLinkW *link);
+ static QWinJumpListItem *fromIShellItem(IShellItem2 *shellitem);
+ static IUnknown *toICustomDestinationListItem(const QWinJumpListItem *item);
+ static IShellLinkW *toIShellLink(const QWinJumpListItem *item);
+ static IShellItem2 *toIShellItem(const QWinJumpListItem *item);
+ static IShellLinkW *makeSeparatorShellItem();
+
+ QWinJumpList *q_ptr;
+ ICustomDestinationList *pDestList;
+ QWinJumpListCategory *recent;
+ QWinJumpListCategory *frequent;
+ QWinJumpListCategory *tasks;
+ QList<QWinJumpListCategory *> categories;
+ bool dirty;
+};
+
+QT_END_NAMESPACE
+
+#endif // QWINJUMPLIST_P_H
diff --git a/src/winextras/qwinjumplistcategory.cpp b/src/winextras/qwinjumplistcategory.cpp
new file mode 100644
index 0000000..424f1e4
--- /dev/null
+++ b/src/winextras/qwinjumplistcategory.cpp
@@ -0,0 +1,319 @@
+/****************************************************************************
+ **
+ ** Copyright (C) 2013 Ivan Vizir <define-true-false@yandex.com>
+ ** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+ ** Contact: http://www.qt-project.org/legal
+ **
+ ** This file is part of the QtWinExtras module of the Qt Toolkit.
+ **
+ ** $QT_BEGIN_LICENSE:LGPL$
+ ** Commercial License Usage
+ ** Licensees holding valid commercial Qt licenses may use this file in
+ ** accordance with the commercial license agreement provided with the
+ ** Software or, alternatively, in accordance with the terms contained in
+ ** a written agreement between you and Digia. For licensing terms and
+ ** conditions see http://qt.digia.com/licensing. For further information
+ ** use the contact form at http://qt.digia.com/contact-us.
+ **
+ ** GNU Lesser General Public License Usage
+ ** Alternatively, this file may be used under the terms of the GNU Lesser
+ ** General Public License version 2.1 as published by the Free Software
+ ** Foundation and appearing in the file LICENSE.LGPL included in the
+ ** packaging of this file. Please review the following information to
+ ** ensure the GNU Lesser General Public License version 2.1 requirements
+ ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+ **
+ ** In addition, as a special exception, Digia gives you certain additional
+ ** rights. These rights are described in the Digia Qt LGPL Exception
+ ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+ **
+ ** GNU General Public License Usage
+ ** Alternatively, this file may be used under the terms of the GNU
+ ** General Public License version 3.0 as published by the Free Software
+ ** Foundation and appearing in the file LICENSE.GPL included in the
+ ** packaging of this file. Please review the following information to
+ ** ensure the GNU General Public License version 3.0 requirements will be
+ ** met: http://www.gnu.org/copyleft/gpl.html.
+ **
+ **
+ ** $QT_END_LICENSE$
+ **
+ ****************************************************************************/
+
+#include "qwinjumplistcategory.h"
+#include "qwinjumplistcategory_p.h"
+#include "qwinjumplistitem_p.h"
+#include "qwinfunctions_p.h"
+#include "qwinjumplist_p.h"
+
+#include <shlobj.h>
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \class QWinJumpListCategory
+ \inmodule QtWinExtras
+ \since 5.2
+ \brief The QWinJumpListCategory class represents a jump list category.
+ */
+
+/*!
+ \enum QWinJumpListCategory::Type
+
+ This enum describes the available QWinJumpListCategory types.
+
+ \value Custom
+ A custom jump list category.
+ \value Recent
+ A jump list category of "recent" items.
+ \value Frequent
+ A jump list category of "frequent" items.
+ \value Tasks
+ A jump list category of tasks.
+ */
+
+QWinJumpListCategory *QWinJumpListCategoryPrivate::create(QWinJumpListCategory::Type type, QWinJumpList *jumpList)
+{
+ QWinJumpListCategory *category = new QWinJumpListCategory;
+ category->d_func()->type = type;
+ category->d_func()->jumpList = jumpList;
+ if (type == QWinJumpListCategory::Recent || type == QWinJumpListCategory::Frequent)
+ category->d_func()->loadRecents();
+ return category;
+}
+
+void QWinJumpListCategoryPrivate::invalidate()
+{
+ if (jumpList)
+ QWinJumpListPrivate::get(jumpList)->invalidate();
+}
+
+void QWinJumpListCategoryPrivate::loadRecents()
+{
+ HRESULT hresult = CoCreateInstance(CLSID_ApplicationDocumentLists, 0, CLSCTX_INPROC_SERVER, IID_IApplicationDocumentLists, reinterpret_cast<void **>(&pDocList));
+ if (SUCCEEDED(hresult)) {
+ IObjectArray *array = 0;
+ hresult = pDocList->GetList(type == QWinJumpListCategory::Recent ? ADLT_RECENT : ADLT_FREQUENT,
+ 0, IID_IObjectArray, reinterpret_cast<void **>(&array));
+ if (SUCCEEDED(hresult)) {
+ items = QWinJumpListPrivate::fromComCollection(array);
+ array->Release();
+ }
+ }
+ if (FAILED(hresult))
+ QWinJumpListPrivate::warning("loadRecents", hresult);
+}
+
+void QWinJumpListCategoryPrivate::addRecent(QWinJumpListItem *item)
+{
+ if (item->type() == QWinJumpListItem::Link)
+ SHAddToRecentDocs(SHARD_LINK, QWinJumpListPrivate::toIShellLink(item));
+ else if (item->type() == QWinJumpListItem::Destination)
+ SHAddToRecentDocs(SHARD_SHELLITEM, QWinJumpListPrivate::toIShellItem(item));
+}
+
+void QWinJumpListCategoryPrivate::clearRecents()
+{
+ IApplicationDestinations *pDest = 0;
+ HRESULT hresult = CoCreateInstance(CLSID_ApplicationDestinations, 0, CLSCTX_INPROC_SERVER, IID_IApplicationDestinations, reinterpret_cast<void **>(&pDest));
+ if (SUCCEEDED(hresult)) {
+ hresult = pDest->RemoveAllDestinations();
+ pDest->Release();
+ }
+ if (FAILED(hresult))
+ QWinJumpListPrivate::warning("clearRecents", hresult);
+}
+
+/*!
+ Constructs a custom QWinJumpListCategory with the specified \a title.
+ */
+QWinJumpListCategory::QWinJumpListCategory(const QString &title) :
+ d_ptr(new QWinJumpListCategoryPrivate)
+{
+ d_ptr->pDocList = 0;
+ d_ptr->type = Custom;
+ d_ptr->visible = false;
+ d_ptr->title = title;
+}
+
+/*!
+ Destroys the QWinJumpListCategory.
+ */
+QWinJumpListCategory::~QWinJumpListCategory()
+{
+ Q_D(QWinJumpListCategory);
+ if (d->pDocList) {
+ d->pDocList->Release();
+ d->pDocList = 0;
+ }
+ qDeleteAll(d->items);
+ d->items.clear();
+}
+
+/*!
+ Returns the category type.
+ */
+QWinJumpListCategory::Type QWinJumpListCategory::type() const
+{
+ Q_D(const QWinJumpListCategory);
+ return d->type;
+}
+
+/*!
+ Returns whether the category is visible.
+ */
+bool QWinJumpListCategory::isVisible() const
+{
+ Q_D(const QWinJumpListCategory);
+ return d->visible;
+}
+
+/*!
+ Sets the category \a visible.
+ */
+void QWinJumpListCategory::setVisible(bool visible)
+{
+ Q_D(QWinJumpListCategory);
+ if (d->visible != visible) {
+ d->visible = visible;
+ d->invalidate();
+ }
+}
+
+/*!
+ Returns the category title.
+ */
+QString QWinJumpListCategory::title() const
+{
+ Q_D(const QWinJumpListCategory);
+ return d->title;
+}
+
+/*!
+ Sets the category \a title.
+ */
+void QWinJumpListCategory::setTitle(const QString &title)
+{
+ Q_D(QWinJumpListCategory);
+ if (d->title != title) {
+ d->title = title;
+ d->invalidate();
+ }
+}
+
+/*!
+ Returns the amount of items in the category.
+ */
+int QWinJumpListCategory::count() const
+{
+ Q_D(const QWinJumpListCategory);
+ return d->items.count();
+}
+
+/*!
+ Returns whether the category is empty.
+ */
+bool QWinJumpListCategory::isEmpty() const
+{
+ Q_D(const QWinJumpListCategory);
+ return d->items.isEmpty();
+}
+
+/*!
+ Returns the list of items in the category.
+ */
+QList<QWinJumpListItem *> QWinJumpListCategory::items() const
+{
+ Q_D(const QWinJumpListCategory);
+ return d->items;
+}
+
+/*!
+ Adds an \a item to the category.
+ */
+void QWinJumpListCategory::addItem(QWinJumpListItem *item)
+{
+ Q_D(QWinJumpListCategory);
+ if (!item)
+ return;
+
+ QWinJumpListItemPrivate *p = QWinJumpListItemPrivate::get(item);
+ if (p->category != this) {
+ p->category = this;
+ d->items.append(item);
+ if (d->type == QWinJumpListCategory::Recent || d->type == QWinJumpListCategory::Frequent)
+ d->addRecent(item);
+ d->invalidate();
+ }
+}
+
+/*!
+ Adds a destination to the category pointing to \a filePath.
+ */
+QWinJumpListItem *QWinJumpListCategory::addDestination(const QString &filePath)
+{
+ QWinJumpListItem *item = new QWinJumpListItem(QWinJumpListItem::Destination);
+ item->setFilePath(filePath);
+ addItem(item);
+ return item;
+}
+
+/*!
+ Adds a link to the category using \a title, \a executablePath, and
+ optionally \a arguments.
+ */
+QWinJumpListItem *QWinJumpListCategory::addLink(const QString &title, const QString &executablePath, const QStringList &arguments)
+{
+ return addLink(QIcon(), title, executablePath, arguments);
+}
+
+/*!
+ \overload addLink()
+
+ Adds a link to the category using \a icon, \a title, \a executablePath,
+ and optionally \a arguments.
+ */
+QWinJumpListItem *QWinJumpListCategory::addLink(const QIcon &icon, const QString &title, const QString &executablePath, const QStringList &arguments)
+{
+ QWinJumpListItem *item = new QWinJumpListItem(QWinJumpListItem::Link);
+ item->setFilePath(executablePath);
+ item->setTitle(title);
+ item->setArguments(arguments);
+ item->setIcon(icon);
+ addItem(item);
+ return item;
+}
+
+/*!
+ Adds a separator to the category.
+
+ \note Only tasks category supports separators.
+ */
+QWinJumpListItem *QWinJumpListCategory::addSeparator()
+{
+ Q_D(QWinJumpListCategory);
+ if (d->type != Tasks) {
+ qWarning("QWinJumpListCategory::addSeparator(): only tasks category supports separators.");
+ return 0;
+ }
+ QWinJumpListItem *item = new QWinJumpListItem(QWinJumpListItem::Separator);
+ addItem(item);
+ return item;
+}
+
+/*!
+ Clears the category.
+ */
+void QWinJumpListCategory::clear()
+{
+ Q_D(QWinJumpListCategory);
+ if (!d->items.isEmpty()) {
+ qDeleteAll(d->items);
+ d->items.clear();
+ if (d->type == QWinJumpListCategory::Recent || d->type == QWinJumpListCategory::Frequent)
+ d->clearRecents();
+ d->invalidate();
+ }
+}
+
+QT_END_NAMESPACE
diff --git a/src/winextras/qwinjumplistcategory.h b/src/winextras/qwinjumplistcategory.h
new file mode 100644
index 0000000..d572c68
--- /dev/null
+++ b/src/winextras/qwinjumplistcategory.h
@@ -0,0 +1,98 @@
+/****************************************************************************
+ **
+ ** Copyright (C) 2013 Ivan Vizir <define-true-false@yandex.com>
+ ** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+ ** Contact: http://www.qt-project.org/legal
+ **
+ ** This file is part of the QtWinExtras module of the Qt Toolkit.
+ **
+ ** $QT_BEGIN_LICENSE:LGPL$
+ ** Commercial License Usage
+ ** Licensees holding valid commercial Qt licenses may use this file in
+ ** accordance with the commercial license agreement provided with the
+ ** Software or, alternatively, in accordance with the terms contained in
+ ** a written agreement between you and Digia. For licensing terms and
+ ** conditions see http://qt.digia.com/licensing. For further information
+ ** use the contact form at http://qt.digia.com/contact-us.
+ **
+ ** GNU Lesser General Public License Usage
+ ** Alternatively, this file may be used under the terms of the GNU Lesser
+ ** General Public License version 2.1 as published by the Free Software
+ ** Foundation and appearing in the file LICENSE.LGPL included in the
+ ** packaging of this file. Please review the following information to
+ ** ensure the GNU Lesser General Public License version 2.1 requirements
+ ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+ **
+ ** In addition, as a special exception, Digia gives you certain additional
+ ** rights. These rights are described in the Digia Qt LGPL Exception
+ ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+ **
+ ** GNU General Public License Usage
+ ** Alternatively, this file may be used under the terms of the GNU
+ ** General Public License version 3.0 as published by the Free Software
+ ** Foundation and appearing in the file LICENSE.GPL included in the
+ ** packaging of this file. Please review the following information to
+ ** ensure the GNU General Public License version 3.0 requirements will be
+ ** met: http://www.gnu.org/copyleft/gpl.html.
+ **
+ **
+ ** $QT_END_LICENSE$
+ **
+ ****************************************************************************/
+
+#ifndef QWINJUMPLISTCATEGORY_H
+#define QWINJUMPLISTCATEGORY_H
+
+#include <QtGui/qicon.h>
+#include <QtCore/qstring.h>
+#include <QtCore/qstringlist.h>
+#include <QtCore/qscopedpointer.h>
+#include <QtWinExtras/qwinextrasglobal.h>
+
+QT_BEGIN_NAMESPACE
+
+class QWinJumpListItem;
+class QWinJumpListCategoryPrivate;
+
+class Q_WINEXTRAS_EXPORT QWinJumpListCategory
+{
+public:
+ enum Type {
+ Custom,
+ Recent,
+ Frequent,
+ Tasks
+ };
+
+ explicit QWinJumpListCategory(const QString &title = QString());
+ ~QWinJumpListCategory();
+
+ Type type() const;
+
+ bool isVisible() const;
+ void setVisible(bool visible);
+
+ QString title() const;
+ void setTitle(const QString &title);
+
+ int count() const;
+ bool isEmpty() const;
+ QList<QWinJumpListItem *> items() const;
+
+ void addItem(QWinJumpListItem *item);
+ QWinJumpListItem *addDestination(const QString &filePath);
+ QWinJumpListItem *addLink(const QString &title, const QString &executablePath, const QStringList &arguments = QStringList());
+ QWinJumpListItem *addLink(const QIcon &icon, const QString &title, const QString &executablePath, const QStringList &arguments = QStringList());
+ QWinJumpListItem *addSeparator();
+
+ void clear();
+
+private:
+ Q_DISABLE_COPY(QWinJumpListCategory)
+ Q_DECLARE_PRIVATE(QWinJumpListCategory)
+ QScopedPointer<QWinJumpListCategoryPrivate> d_ptr;
+};
+
+QT_END_NAMESPACE
+
+#endif // QWINJUMPLISTCATEGORY_H
diff --git a/src/winextras/qwinjumplistcategory_p.h b/src/winextras/qwinjumplistcategory_p.h
new file mode 100644
index 0000000..6aa23ba
--- /dev/null
+++ b/src/winextras/qwinjumplistcategory_p.h
@@ -0,0 +1,78 @@
+/****************************************************************************
+ **
+ ** Copyright (C) 2013 Ivan Vizir <define-true-false@yandex.com>
+ ** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+ ** Contact: http://www.qt-project.org/legal
+ **
+ ** This file is part of the QtWinExtras module of the Qt Toolkit.
+ **
+ ** $QT_BEGIN_LICENSE:LGPL$
+ ** Commercial License Usage
+ ** Licensees holding valid commercial Qt licenses may use this file in
+ ** accordance with the commercial license agreement provided with the
+ ** Software or, alternatively, in accordance with the terms contained in
+ ** a written agreement between you and Digia. For licensing terms and
+ ** conditions see http://qt.digia.com/licensing. For further information
+ ** use the contact form at http://qt.digia.com/contact-us.
+ **
+ ** GNU Lesser General Public License Usage
+ ** Alternatively, this file may be used under the terms of the GNU Lesser
+ ** General Public License version 2.1 as published by the Free Software
+ ** Foundation and appearing in the file LICENSE.LGPL included in the
+ ** packaging of this file. Please review the following information to
+ ** ensure the GNU Lesser General Public License version 2.1 requirements
+ ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+ **
+ ** In addition, as a special exception, Digia gives you certain additional
+ ** rights. These rights are described in the Digia Qt LGPL Exception
+ ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+ **
+ ** GNU General Public License Usage
+ ** Alternatively, this file may be used under the terms of the GNU
+ ** General Public License version 3.0 as published by the Free Software
+ ** Foundation and appearing in the file LICENSE.GPL included in the
+ ** packaging of this file. Please review the following information to
+ ** ensure the GNU General Public License version 3.0 requirements will be
+ ** met: http://www.gnu.org/copyleft/gpl.html.
+ **
+ **
+ ** $QT_END_LICENSE$
+ **
+ ****************************************************************************/
+
+#ifndef QWINJUMPLISTCATEGORY_P_H
+#define QWINJUMPLISTCATEGORY_P_H
+
+#include "qwinjumplistcategory.h"
+#include "winshobjidl_p.h"
+
+QT_BEGIN_NAMESPACE
+
+class QWinJumpList;
+
+class QWinJumpListCategoryPrivate
+{
+public:
+ static QWinJumpListCategoryPrivate *get(QWinJumpListCategory *category)
+ {
+ return category->d_func();
+ }
+
+ static QWinJumpListCategory *create(QWinJumpListCategory::Type type, QWinJumpList *jumpList);
+
+ void invalidate();
+ void loadRecents();
+ void addRecent(QWinJumpListItem *item);
+ void clearRecents();
+
+ bool visible;
+ QString title;
+ QWinJumpList *jumpList;
+ QWinJumpListCategory::Type type;
+ QList<QWinJumpListItem *> items;
+ IApplicationDocumentLists *pDocList;
+};
+
+QT_END_NAMESPACE
+
+#endif // QWINJUMPLISTCATEGORY_P_H
diff --git a/src/winextras/qwinjumplistitem.cpp b/src/winextras/qwinjumplistitem.cpp
index a73aa99..1eaea85 100644
--- a/src/winextras/qwinjumplistitem.cpp
+++ b/src/winextras/qwinjumplistitem.cpp
@@ -1,6 +1,7 @@
/****************************************************************************
**
** Copyright (C) 2013 Ivan Vizir <define-true-false@yandex.com>
+ ** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of the QtWinExtras module of the Qt Toolkit.
@@ -40,6 +41,8 @@
****************************************************************************/
#include "qwinjumplistitem.h"
+#include "qwinjumplistitem_p.h"
+#include "qwinjumplistcategory_p.h"
QT_BEGIN_NAMESPACE
@@ -47,24 +50,27 @@ QT_BEGIN_NAMESPACE
\class QWinJumpListItem
\inmodule QtWinExtras
\since 5.2
- \inheaderfile QWinJumpList
- \brief The QWinJumpListItem class represents a Jump List destination or link.
+ \brief The QWinJumpListItem class represents a jump list item.
+ */
+
+/*!
+ \enum QWinJumpListItem::Type
- Objects of this class are returned by QWinJumpList::removedDestinations()
- and can also be used to add items to a Jump List.
+ This enum describes the available QWinJumpListItem types.
+
+ \value Destination
+ Item acts as a link to a file that the application can open.
+ \value Link
+ Item represents a link to an application.
+ \value Separator
+ Item is a separator. Only tasks category supports separators.
*/
-class QWinJumpListItemPrivate
+void QWinJumpListItemPrivate::invalidate()
{
-public:
- QString filePath;
- QString workingDirectory;
- QString title;
- QString description;
- QIcon icon;
- QStringList arguments;
- QWinJumpListItem::Type type;
-};
+ if (category)
+ QWinJumpListCategoryPrivate::get(category)->invalidate();
+}
/*!
Constructs a QWinJumpListItem with the specified \a type.
@@ -73,6 +79,7 @@ QWinJumpListItem::QWinJumpListItem(QWinJumpListItem::Type type) :
d_ptr(new QWinJumpListItemPrivate)
{
d_ptr->type = type;
+ d_ptr->category = 0;
}
/*!
@@ -88,7 +95,10 @@ QWinJumpListItem::~QWinJumpListItem()
void QWinJumpListItem::setType(QWinJumpListItem::Type type)
{
Q_D(QWinJumpListItem);
- d->type = type;
+ if (d->type != type) {
+ d->type = type;
+ d->invalidate();
+ }
}
/*!
@@ -120,7 +130,10 @@ QWinJumpListItem::Type QWinJumpListItem::type() const
void QWinJumpListItem::setFilePath(const QString &filePath)
{
Q_D(QWinJumpListItem);
- d->filePath = filePath;
+ if (d->filePath != filePath) {
+ d->filePath = filePath;
+ d->invalidate();
+ }
}
/*!
@@ -142,7 +155,10 @@ QString QWinJumpListItem::filePath() const
void QWinJumpListItem::setWorkingDirectory(const QString &workingDirectory)
{
Q_D(QWinJumpListItem);
- d->workingDirectory = workingDirectory;
+ if (d->workingDirectory != workingDirectory) {
+ d->workingDirectory = workingDirectory;
+ d->invalidate();
+ }
}
/*!
@@ -162,7 +178,10 @@ QString QWinJumpListItem::workingDirectory() const
void QWinJumpListItem::setIcon(const QIcon &icon)
{
Q_D(QWinJumpListItem);
- d->icon = icon;
+ if (d->icon.cacheKey() != icon.cacheKey()) {
+ d->icon = icon;
+ d->invalidate();
+ }
}
/*!
@@ -182,7 +201,10 @@ QIcon QWinJumpListItem::icon() const
void QWinJumpListItem::setTitle(const QString &title)
{
Q_D(QWinJumpListItem);
- d->title = title;
+ if (d->title != title) {
+ d->title = title;
+ d->invalidate();
+ }
}
/*!
@@ -202,7 +224,10 @@ QString QWinJumpListItem::title() const
void QWinJumpListItem::setDescription(const QString &description)
{
Q_D(QWinJumpListItem);
- d->description = description;
+ if (d->description != description) {
+ d->description = description;
+ d->invalidate();
+ }
}
/*!
@@ -224,7 +249,10 @@ QString QWinJumpListItem::description() const
void QWinJumpListItem::setArguments(const QStringList &arguments)
{
Q_D(QWinJumpListItem);
- d->arguments = arguments;
+ if (d->arguments != arguments) {
+ d->arguments = arguments;
+ d->invalidate();
+ }
}
/*!
diff --git a/src/winextras/qwinjumplistitem.h b/src/winextras/qwinjumplistitem.h
index 824cf8f..7691431 100644
--- a/src/winextras/qwinjumplistitem.h
+++ b/src/winextras/qwinjumplistitem.h
@@ -1,6 +1,7 @@
/****************************************************************************
**
** Copyright (C) 2013 Ivan Vizir <define-true-false@yandex.com>
+ ** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of the QtWinExtras module of the Qt Toolkit.
@@ -56,13 +57,12 @@ class Q_WINEXTRAS_EXPORT QWinJumpListItem
{
public:
enum Type {
- Unknown,
Destination,
Link,
Separator
};
- explicit QWinJumpListItem(Type type = Unknown);
+ explicit QWinJumpListItem(Type type);
~QWinJumpListItem();
void setType(Type type);
diff --git a/src/winextras/qwinjumplistitem_p.h b/src/winextras/qwinjumplistitem_p.h
new file mode 100644
index 0000000..1cf7c79
--- /dev/null
+++ b/src/winextras/qwinjumplistitem_p.h
@@ -0,0 +1,74 @@
+/****************************************************************************
+ **
+ ** Copyright (C) 2013 Ivan Vizir <define-true-false@yandex.com>
+ ** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+ ** Contact: http://www.qt-project.org/legal
+ **
+ ** This file is part of the QtWinExtras module of the Qt Toolkit.
+ **
+ ** $QT_BEGIN_LICENSE:LGPL$
+ ** Commercial License Usage
+ ** Licensees holding valid commercial Qt licenses may use this file in
+ ** accordance with the commercial license agreement provided with the
+ ** Software or, alternatively, in accordance with the terms contained in
+ ** a written agreement between you and Digia. For licensing terms and
+ ** conditions see http://qt.digia.com/licensing. For further information
+ ** use the contact form at http://qt.digia.com/contact-us.
+ **
+ ** GNU Lesser General Public License Usage
+ ** Alternatively, this file may be used under the terms of the GNU Lesser
+ ** General Public License version 2.1 as published by the Free Software
+ ** Foundation and appearing in the file LICENSE.LGPL included in the
+ ** packaging of this file. Please review the following information to
+ ** ensure the GNU Lesser General Public License version 2.1 requirements
+ ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+ **
+ ** In addition, as a special exception, Digia gives you certain additional
+ ** rights. These rights are described in the Digia Qt LGPL Exception
+ ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+ **
+ ** GNU General Public License Usage
+ ** Alternatively, this file may be used under the terms of the GNU
+ ** General Public License version 3.0 as published by the Free Software
+ ** Foundation and appearing in the file LICENSE.GPL included in the
+ ** packaging of this file. Please review the following information to
+ ** ensure the GNU General Public License version 3.0 requirements will be
+ ** met: http://www.gnu.org/copyleft/gpl.html.
+ **
+ **
+ ** $QT_END_LICENSE$
+ **
+ ****************************************************************************/
+
+#ifndef QWINJUMPLISTITEM_P_H
+#define QWINJUMPLISTITEM_P_H
+
+#include "qwinjumplistitem.h"
+
+QT_BEGIN_NAMESPACE
+
+class QWinJumpListCategory;
+
+class QWinJumpListItemPrivate
+{
+public:
+ static QWinJumpListItemPrivate *get(QWinJumpListItem *item)
+ {
+ return item->d_func();
+ }
+
+ void invalidate();
+
+ QString filePath;
+ QString workingDirectory;
+ QString title;
+ QString description;
+ QIcon icon;
+ QStringList arguments;
+ QWinJumpListItem::Type type;
+ QWinJumpListCategory *category;
+};
+
+QT_END_NAMESPACE
+
+#endif // QWINJUMPLISTITEM_P_H
diff --git a/src/winextras/windowsguidsdefs.cpp b/src/winextras/windowsguidsdefs.cpp
index d376c5f..740cb84 100644
--- a/src/winextras/windowsguidsdefs.cpp
+++ b/src/winextras/windowsguidsdefs.cpp
@@ -50,6 +50,10 @@
const GUID CLSID_DestinationList = {0x77f10cf0, 0x3db5, 0x4966, {0xb5,0x20,0xb7,0xc5,0x4f,0xd3,0x5e,0xd6}};
const GUID CLSID_EnumerableObjectCollection = {0x2d3468c1, 0x36a7, 0x43b6, {0xac,0x24,0xd3,0xf0,0x2f,0xd9,0x60,0x7a}};
const GUID IID_ICustomDestinationList = {0x6332debf, 0x87b5, 0x4670, {0x90,0xc0,0x5e,0x57,0xb4,0x08,0xa4,0x9e}};
+const GUID IID_IApplicationDestinations = {0x12337d35, 0x94c6, 0x48a0, {0xbc,0xe7,0x6a,0x9c,0x69,0xd4,0xd6,0x00}};
+const GUID CLSID_ApplicationDestinations = {0x86c14003, 0x4d6b, 0x4ef3, {0xa7,0xb4,0x05,0x06,0x66,0x3b,0x2e,0x68}};
+const GUID IID_IApplicationDocumentLists = {0x3c594f9f, 0x9f30, 0x47a1, {0x97,0x9a,0xc9,0xe8,0x3d,0x3d,0x0a,0x06}};
+const GUID CLSID_ApplicationDocumentLists = {0x86bec222, 0x30f2, 0x47e0, {0x9f,0x25,0x60,0xd1,0x1c,0xd7,0x5c,0x28}};
const GUID IID_IObjectArray = {0x92ca9dcd, 0x5622, 0x4bba, {0xa8,0x05,0x5e,0x9f,0x54,0x1b,0xd8,0xc9}};
const GUID IID_IObjectCollection = {0x5632b1a4, 0xe38a, 0x400a, {0x92,0x8a,0xd4,0xcd,0x63,0x23,0x02,0x95}};
const GUID IID_IPropertyStore = {0x886d8eeb, 0x8cf2, 0x4446, {0x8d,0x02,0xcd,0xba,0x1d,0xbd,0xcf,0x99}};
diff --git a/src/winextras/winextras.pro b/src/winextras/winextras.pro
index fdf96a9..aea3b5d 100644
--- a/src/winextras/winextras.pro
+++ b/src/winextras/winextras.pro
@@ -9,6 +9,7 @@ SOURCES += \
qwintaskbarprogress.cpp \
windowsguidsdefs.cpp \
qwinjumplist.cpp \
+ qwinjumplistcategory.cpp \
qwinjumplistitem.cpp \
qwineventfilter.cpp \
qwinthumbnailtoolbar.cpp \
@@ -23,7 +24,11 @@ HEADERS += \
qwintaskbarbutton.h \
qwintaskbarprogress.h \
qwinjumplist.h \
+ qwinjumplist_p.h \
+ qwinjumplistcategory.h \
+ qwinjumplistcategory_p.h \
qwinjumplistitem.h \
+ qwinjumplistitem_p.h \
winshobjidl_p.h \
winpropkey_p.h \
qwineventfilter_p.h \
@@ -35,7 +40,7 @@ HEADERS += \
QMAKE_DOCS = $$PWD/doc/qtwinextras.qdocconf
-LIBS += -lole32 -lshlwapi
+LIBS += -lole32 -lshlwapi -lshell32
LIBS -= -luuid
OTHER_FILES += \
diff --git a/src/winextras/winshobjidl_p.h b/src/winextras/winshobjidl_p.h
index cd564d7..f0f8857 100644
--- a/src/winextras/winshobjidl_p.h
+++ b/src/winextras/winshobjidl_p.h
@@ -207,4 +207,39 @@ public:
#endif
+#ifndef __IApplicationDocumentLists_INTERFACE_DEFINED__
+#define __IApplicationDocumentLists_INTERFACE_DEFINED__
+
+enum APPDOCLISTTYPE {
+ ADLT_RECENT = 0,
+ ADLT_FREQUENT
+};
+
+extern const GUID IID_IApplicationDocumentLists;
+extern const GUID CLSID_ApplicationDocumentLists;
+
+struct IApplicationDocumentLists : public IUnknown
+{
+public:
+ virtual HRESULT STDMETHODCALLTYPE SetAppID(LPCWSTR pszAppID) = 0;
+ virtual HRESULT STDMETHODCALLTYPE GetList(APPDOCLISTTYPE listtype, UINT cItemsDesired, REFIID riid, void **ppv) = 0;
+};
+#endif
+
+#ifndef __IApplicationDestinations_INTERFACE_DEFINED__
+#define __IApplicationDestinations_INTERFACE_DEFINED__
+
+extern const GUID IID_IApplicationDestinations;
+extern const GUID CLSID_ApplicationDestinations;
+
+struct IApplicationDestinations : public IUnknown
+{
+public:
+ virtual HRESULT STDMETHODCALLTYPE SetAppID(LPCWSTR pszAppID) = 0;
+ virtual HRESULT STDMETHODCALLTYPE RemoveDestination(IUnknown *punk) = 0;
+ virtual HRESULT STDMETHODCALLTYPE RemoveAllDestinations( void) = 0;
+};
+
+#endif
+
#endif // ITASKBARLIST_H