diff options
author | J-P Nurmi <jpnurmi@digia.com> | 2013-09-13 18:47:29 +0200 |
---|---|---|
committer | The Qt Project <gerrit-noreply@qt-project.org> | 2013-09-20 10:12:21 +0200 |
commit | 0eade30f37980c38b14d5cfa475837d15b69a8c5 (patch) | |
tree | 1c4f4232086ede3cb3ad62bed1eca053c2977b52 /src | |
parent | 6e81cfd302e48e7ae4ecab44b377eeffaa45cd73 (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.cpp | 18 | ||||
-rw-r--r-- | src/imports/winextras/qquickjumplist_p.h | 1 | ||||
-rw-r--r-- | src/winextras/qwinjumplist.cpp | 876 | ||||
-rw-r--r-- | src/winextras/qwinjumplist.h | 37 | ||||
-rw-r--r-- | src/winextras/qwinjumplist_p.h | 97 | ||||
-rw-r--r-- | src/winextras/qwinjumplistcategory.cpp | 319 | ||||
-rw-r--r-- | src/winextras/qwinjumplistcategory.h | 98 | ||||
-rw-r--r-- | src/winextras/qwinjumplistcategory_p.h | 78 | ||||
-rw-r--r-- | src/winextras/qwinjumplistitem.cpp | 70 | ||||
-rw-r--r-- | src/winextras/qwinjumplistitem.h | 4 | ||||
-rw-r--r-- | src/winextras/qwinjumplistitem_p.h | 74 | ||||
-rw-r--r-- | src/winextras/windowsguidsdefs.cpp | 4 | ||||
-rw-r--r-- | src/winextras/winextras.pro | 7 | ||||
-rw-r--r-- | src/winextras/winshobjidl_p.h | 35 |
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 |