From 88c68592846b83cdc4c2de89aaf81412f3f42f3a Mon Sep 17 00:00:00 2001 From: Peter Penz Date: Wed, 16 May 2012 13:46:28 +0200 Subject: [PATCH] Implement bookmark synchronization Whenever the bookmarks are changed by another application, the state must be synchronized within the model. --- src/panels/places/placesitem.cpp | 26 +- src/panels/places/placesitemmodel.cpp | 342 +++++++++++++++++++------- src/panels/places/placesitemmodel.h | 71 +++++- 3 files changed, 327 insertions(+), 112 deletions(-) diff --git a/src/panels/places/placesitem.cpp b/src/panels/places/placesitem.cpp index 436d69668c..9e4cb6846a 100644 --- a/src/panels/places/placesitem.cpp +++ b/src/panels/places/placesitem.cpp @@ -63,7 +63,14 @@ PlacesItem::~PlacesItem() void PlacesItem::setUrl(const KUrl& url) { - setDataValue("url", url); + // The default check in KStandardItem::setDataValue() + // for equal values does not work with a custom value + // like KUrl. Hence do a manual check to prevent that + // setting an equal URL results in an itemsChanged() + // signal. + if (dataValue("url").value() != url) { + setDataValue("url", url); + } } KUrl PlacesItem::url() const @@ -84,9 +91,6 @@ QString PlacesItem::udi() const void PlacesItem::setHidden(bool hidden) { setDataValue("isHidden", hidden); - if (!m_bookmark.isNull()) { - m_bookmark.setMetaDataItem("IsHidden", hidden ? "true" : "false"); - } } bool PlacesItem::isHidden() const @@ -121,9 +125,8 @@ void PlacesItem::setBookmark(const KBookmark& bookmark) const QString udi = bookmark.metaDataItem("UDI"); if (udi.isEmpty()) { setIcon(bookmark.icon()); - setText(bookmark.description()); + setText(bookmark.text()); setUrl(bookmark.url()); - setDataValue("address", bookmark.address()); } else { initializeDevice(udi); } @@ -173,7 +176,7 @@ KBookmark PlacesItem::createBookmark(KBookmarkManager* manager, } KBookmark bookmark = root.addBookmark(text, url, iconName); - bookmark.setDescription(text); + bookmark.setFullText(text); bookmark.setMetaDataItem("ID", generateNewId()); return bookmark; @@ -259,7 +262,7 @@ void PlacesItem::updateBookmarkForRole(const QByteArray& role) if (role == "iconName") { m_bookmark.setIcon(icon()); } else if (role == "text") { - m_bookmark.setDescription(text()); + m_bookmark.setFullText(text()); } else if (role == "url") { m_bookmark.setUrl(url()); } else if (role == "udi)") { @@ -273,6 +276,11 @@ void PlacesItem::updateBookmarkForRole(const QByteArray& role) QString PlacesItem::generateNewId() { + // The ID-generation must be different as done in KFilePlacesItem from kdelibs + // to prevent identical IDs, because 'count' is of course not shared. We append a + // " (V2)" to indicate that the ID has been generated by + // a new version of the places view. static int count = 0; - return QString::number(QDateTime::currentDateTime().toTime_t()) + '/' + QString::number(count++); + return QString::number(QDateTime::currentDateTime().toTime_t()) + + '/' + QString::number(count++) + " (V2)"; } diff --git a/src/panels/places/placesitemmodel.cpp b/src/panels/places/placesitemmodel.cpp index ac7422ca48..4ddd60c0b3 100644 --- a/src/panels/places/placesitemmodel.cpp +++ b/src/panels/places/placesitemmodel.cpp @@ -48,6 +48,17 @@ #include #endif +namespace { + // As long as KFilePlacesView from kdelibs is available in parallel, the + // system-bookmarks for "Recently Accessed" and "Search For" should be + // shown only inside the Places Panel. This is necessary as the stored + // URLs needs to get translated to a Nepomuk-search-URL on-the-fly to + // be independent from changes in the Nepomuk-search-URL-syntax. + // Hence a prefix to the application-name of the stored bookmarks is + // added, which is only read by PlacesItemModel. + const char* AppNamePrefix = "-places-panel"; +} + PlacesItemModel::PlacesItemModel(QObject* parent) : KStandardItemModel(parent), m_nepomukRunning(false), @@ -57,9 +68,10 @@ PlacesItemModel::PlacesItemModel(QObject* parent) : m_bookmarkManager(0), m_systemBookmarks(), m_systemBookmarksIndexes(), - m_hiddenItems(), + m_bookmarkedItems(), m_hiddenItemToRemove(-1), - m_saveBookmarksTimer(0) + m_saveBookmarksTimer(0), + m_updateBookmarksTimer(0) { #ifdef HAVE_NEPOMUK m_nepomukRunning = (Nepomuk::ResourceManager::instance()->initialized()); @@ -71,17 +83,29 @@ PlacesItemModel::PlacesItemModel(QObject* parent) : initializeAvailableDevices(); loadBookmarks(); + const int syncBookmarksTimeout = 1000; + m_saveBookmarksTimer = new QTimer(this); - m_saveBookmarksTimer->setInterval(100); + m_saveBookmarksTimer->setInterval(syncBookmarksTimeout); m_saveBookmarksTimer->setSingleShot(true); connect(m_saveBookmarksTimer, SIGNAL(timeout()), this, SLOT(saveBookmarks())); + + m_updateBookmarksTimer = new QTimer(this); + m_updateBookmarksTimer->setInterval(syncBookmarksTimeout); + m_updateBookmarksTimer->setSingleShot(true); + connect(m_updateBookmarksTimer, SIGNAL(timeout()), this, SLOT(updateBookmarks())); + + connect(m_bookmarkManager, SIGNAL(changed(QString,QString)), + m_updateBookmarksTimer, SLOT(start())); + connect(m_bookmarkManager, SIGNAL(bookmarksChanged(QString)), + m_updateBookmarksTimer, SLOT(start())); } PlacesItemModel::~PlacesItemModel() { saveBookmarks(); - qDeleteAll(m_hiddenItems); - m_hiddenItems.clear(); + qDeleteAll(m_bookmarkedItems); + m_bookmarkedItems.clear(); } PlacesItem* PlacesItemModel::createPlacesItem(const QString& text, @@ -100,19 +124,19 @@ PlacesItem* PlacesItemModel::placesItem(int index) const int PlacesItemModel::hiddenCount() const { int modelIndex = 0; - int itemCount = 0; - foreach (const PlacesItem* hiddenItem, m_hiddenItems) { - if (hiddenItem) { - ++itemCount; + int hiddenItemCount = 0; + foreach (const PlacesItem* item, m_bookmarkedItems) { + if (item) { + ++hiddenItemCount; } else { if (placesItem(modelIndex)->isHidden()) { - ++itemCount; + ++hiddenItemCount; } ++modelIndex; } } - return itemCount; + return hiddenItemCount; } void PlacesItemModel::setHiddenItemsShown(bool show) @@ -124,26 +148,26 @@ void PlacesItemModel::setHiddenItemsShown(bool show) m_hiddenItemsShown = show; if (show) { - // Move all items that are part of m_hiddenItems to the model. + // Move all items that are part of m_bookmarkedItems to the model. int modelIndex = 0; - for (int hiddenIndex = 0; hiddenIndex < m_hiddenItems.count(); ++hiddenIndex) { - if (m_hiddenItems[hiddenIndex]) { - PlacesItem* visibleItem = new PlacesItem(*m_hiddenItems[hiddenIndex]); - delete m_hiddenItems[hiddenIndex]; - m_hiddenItems.removeAt(hiddenIndex); + for (int i = 0; i < m_bookmarkedItems.count(); ++i) { + if (m_bookmarkedItems[i]) { + PlacesItem* visibleItem = new PlacesItem(*m_bookmarkedItems[i]); + delete m_bookmarkedItems[i]; + m_bookmarkedItems.removeAt(i); insertItem(modelIndex, visibleItem); - Q_ASSERT(!m_hiddenItems[hiddenIndex]); + Q_ASSERT(!m_bookmarkedItems[i]); } ++modelIndex; } } else { // Move all items of the model, where the "isHidden" property is true, to - // m_hiddenItems. - Q_ASSERT(m_hiddenItems.count() == count()); + // m_allItems. + Q_ASSERT(m_bookmarkedItems.count() == count()); for (int i = count() - 1; i >= 0; --i) { const PlacesItem* visibleItem = placesItem(i); if (visibleItem->isHidden()) { - removeHiddenItem(i); + hideItem(i); } } } @@ -286,22 +310,22 @@ void PlacesItemModel::onItemInserted(int index) // The item has been appended as last item to the list. In this // case assure that it is also appended after the hidden items and // not before (like done otherwise). - m_hiddenItems.append(0); + m_bookmarkedItems.append(0); return; } int modelIndex = -1; - int hiddenIndex = 0; - while (hiddenIndex < m_hiddenItems.count()) { - if (!m_hiddenItems[hiddenIndex]) { + int bookmarkIndex = 0; + while (bookmarkIndex < m_bookmarkedItems.count()) { + if (!m_bookmarkedItems[bookmarkIndex]) { ++modelIndex; if (modelIndex + 1 == index) { break; } } - ++hiddenIndex; + ++bookmarkIndex; } - m_hiddenItems.insert(hiddenIndex, 0); + m_bookmarkedItems.insert(bookmarkIndex, 0); m_saveBookmarksTimer->start(); @@ -319,9 +343,9 @@ void PlacesItemModel::onItemRemoved(int index, KStandardItem* removedItem) m_bookmarkManager->root().deleteBookmark(bookmark); } - const int removeIndex = hiddenIndex(index); - Q_ASSERT(!m_hiddenItems[removeIndex]); - m_hiddenItems.removeAt(removeIndex); + const int boomarkIndex = bookmarkIndex(index); + Q_ASSERT(!m_bookmarkedItems[boomarkIndex]); + m_bookmarkedItems.removeAt(boomarkIndex); m_saveBookmarksTimer->start(); @@ -353,9 +377,10 @@ void PlacesItemModel::onItemChanged(int index, const QSet& changedRo Q_ASSERT(shownItem); if (!m_hiddenItemsShown && shownItem->isHidden()) { m_hiddenItemToRemove = index; - QTimer::singleShot(0, this, SLOT(removeHiddenItem())); + QTimer::singleShot(0, this, SLOT(hideItem())); } } + m_saveBookmarksTimer->start(); } @@ -375,10 +400,10 @@ void PlacesItemModel::slotDeviceRemoved(const QString& udi) return; } - for (int i = 0; i < m_hiddenItems.count(); ++i) { - PlacesItem* item = m_hiddenItems[i]; + for (int i = 0; i < m_bookmarkedItems.count(); ++i) { + PlacesItem* item = m_bookmarkedItems[i]; if (item && item->udi() == udi) { - m_hiddenItems.removeAt(i); + m_bookmarkedItems.removeAt(i); delete item; return; } @@ -399,17 +424,94 @@ void PlacesItemModel::slotStorageTeardownDone(Solid::ErrorType error, const QVar } } -void PlacesItemModel::removeHiddenItem() +void PlacesItemModel::hideItem() { - removeHiddenItem(m_hiddenItemToRemove); + hideItem(m_hiddenItemToRemove); m_hiddenItemToRemove = -1; } +void PlacesItemModel::updateBookmarks() +{ + // Verify whether new bookmarks have been added or existing + // bookmarks have been changed. + KBookmarkGroup root = m_bookmarkManager->root(); + KBookmark newBookmark = root.first(); + while (!newBookmark.isNull()) { + if (acceptBookmark(newBookmark)) { + bool found = false; + int modelIndex = 0; + for (int i = 0; i < m_bookmarkedItems.count(); ++i) { + PlacesItem* item = m_bookmarkedItems[i]; + if (!item) { + item = placesItem(modelIndex); + ++modelIndex; + } + + const KBookmark oldBookmark = item->bookmark(); + if (equalBookmarkIdentifiers(newBookmark, oldBookmark)) { + // The bookmark has been found in the model or as + // a hidden item. The content of the bookmark might + // have been changed, so an update is done. + found = true; + if (newBookmark.metaDataItem("UDI").isEmpty()) { + item->setBookmark(newBookmark); + } + break; + } + } + + if (!found) { + PlacesItem* item = new PlacesItem(newBookmark); + if (item->isHidden() && !m_hiddenItemsShown) { + m_bookmarkedItems.append(item); + } else { + appendItem(item); + } + } + } + + newBookmark = root.next(newBookmark); + } + + // Remove items that are not part of the bookmark-manager anymore + int modelIndex = 0; + for (int i = m_bookmarkedItems.count() - 1; i >= 0; --i) { + PlacesItem* item = m_bookmarkedItems[i]; + const bool itemIsPartOfModel = (item == 0); + if (itemIsPartOfModel) { + item = placesItem(modelIndex); + } + + bool hasBeenRemoved = true; + const KBookmark oldBookmark = item->bookmark(); + KBookmark newBookmark = root.first(); + while (!newBookmark.isNull()) { + if (equalBookmarkIdentifiers(newBookmark, oldBookmark)) { + hasBeenRemoved = false; + break; + } + newBookmark = root.next(newBookmark); + } + + if (hasBeenRemoved) { + if (m_bookmarkedItems[i]) { + delete m_bookmarkedItems[i]; + m_bookmarkedItems.removeAt(i); + } else { + removeItem(modelIndex); + --modelIndex; + } + } + + if (itemIsPartOfModel) { + ++modelIndex; + } + } +} void PlacesItemModel::saveBookmarks() { - // TODO: Temporary deactivated until 100 % backward compatibility is provided - // m_bookmarkManager->emitChanged(m_bookmarkManager->root()); + m_bookmarkManager->emitChanged(m_bookmarkManager->root()); } void PlacesItemModel::loadBookmarks() @@ -433,20 +535,13 @@ void PlacesItemModel::loadBookmarks() QList devicesItems; while (!bookmark.isNull()) { - const QString udi = bookmark.metaDataItem("UDI"); - const KUrl url = bookmark.url(); - const QString appName = bookmark.metaDataItem("OnlyInApp"); - const bool deviceAvailable = devices.remove(udi); - - const bool allowedHere = (appName.isEmpty() || appName == KGlobal::mainComponent().componentName()) - && (m_nepomukRunning || (url.protocol() != QLatin1String("timeline") && - url.protocol() != QLatin1String("search"))); - - if ((udi.isEmpty() && allowedHere) || deviceAvailable) { + const bool deviceAvailable = devices.remove(bookmark.metaDataItem("UDI")); + if (acceptBookmark(bookmark)) { PlacesItem* item = new PlacesItem(bookmark); if (deviceAvailable) { devicesItems.append(item); } else { + const KUrl url = bookmark.url(); if (missingSystemBookmarks.contains(url)) { missingSystemBookmarks.remove(url); @@ -483,8 +578,10 @@ void PlacesItemModel::loadBookmarks() const QString protocol = data.url.protocol(); if (protocol == QLatin1String("timeline") || protocol == QLatin1String("search")) { // As long as the KFilePlacesView from kdelibs is available, the system-bookmarks - // for timeline and search should be a Dolphin-specific setting. - bookmark.setMetaDataItem("OnlyInApp", KGlobal::mainComponent().componentName()); + // for "Recently Accessed" and "Search For" should be a setting available only + // in the Places Panel (see description of AppNamePrefix for more details). + const QString appName = KGlobal::mainComponent().componentName() + AppNamePrefix; + bookmark.setMetaDataItem("OnlyInApp", appName); } PlacesItem* item = new PlacesItem(bookmark); @@ -501,17 +598,25 @@ void PlacesItemModel::loadBookmarks() } } - addItems(placesItems); - addItems(recentlyAccessedItems); - addItems(searchForItems); - - // Create items for devices that have not stored as bookmark yet + // Create items for devices that have not been stored as bookmark yet foreach (const QString& udi, devices) { const KBookmark bookmark = PlacesItem::createDeviceBookmark(m_bookmarkManager, udi); devicesItems.append(new PlacesItem(bookmark)); } - addItems(devicesItems); + QList items; + items.append(placesItems); + items.append(recentlyAccessedItems); + items.append(searchForItems); + items.append(devicesItems); + + foreach (PlacesItem* item, items) { + if (!m_hiddenItemsShown && item->isHidden()) { + m_bookmarkedItems.append(item); + } else { + appendItem(item); + } + } #ifdef PLACESITEMMODEL_DEBUG kDebug() << "Loaded bookmarks"; @@ -519,15 +624,20 @@ void PlacesItemModel::loadBookmarks() #endif } -void PlacesItemModel::addItems(const QList& items) +bool PlacesItemModel::acceptBookmark(const KBookmark& bookmark) const { - foreach (PlacesItem* item, items) { - if (!m_hiddenItemsShown && item->isHidden()) { - m_hiddenItems.append(item); - } else { - appendItem(item); - } - } + const QString udi = bookmark.metaDataItem("UDI"); + const KUrl url = bookmark.url(); + const QString appName = bookmark.metaDataItem("OnlyInApp"); + const bool deviceAvailable = m_availableDevices.contains(udi); + + const bool allowedHere = (appName.isEmpty() + || appName == KGlobal::mainComponent().componentName() + || appName == KGlobal::mainComponent().componentName() + AppNamePrefix) + && (m_nepomukRunning || (url.protocol() != QLatin1String("timeline") && + url.protocol() != QLatin1String("search"))); + + return (udi.isEmpty() && allowedHere) || deviceAvailable; } void PlacesItemModel::createSystemBookmarks() @@ -605,28 +715,39 @@ void PlacesItemModel::initializeAvailableDevices() } } -int PlacesItemModel::hiddenIndex(int index) const +int PlacesItemModel::bookmarkIndex(int index) const { - int hiddenIndex = 0; - int visibleItemIndex = 0; - while (hiddenIndex < m_hiddenItems.count()) { - if (!m_hiddenItems[hiddenIndex]) { - if (visibleItemIndex == index) { + int bookmarkIndex = 0; + int modelIndex = 0; + while (bookmarkIndex < m_bookmarkedItems.count()) { + if (!m_bookmarkedItems[bookmarkIndex]) { + if (modelIndex == index) { break; } - ++visibleItemIndex; + ++modelIndex; } - ++hiddenIndex; + ++bookmarkIndex; } - return hiddenIndex >= m_hiddenItems.count() ? -1 : hiddenIndex; + return bookmarkIndex >= m_bookmarkedItems.count() ? -1 : bookmarkIndex; } -void PlacesItemModel::removeHiddenItem(int index) +void PlacesItemModel::hideItem(int index) { - const PlacesItem* shownItem = placesItem(index); - const int newIndex = hiddenIndex(index); - if (shownItem && newIndex >= 0) { + PlacesItem* shownItem = placesItem(index); + if (!shownItem) { + return; + } + + shownItem->setHidden(true); + if (m_hiddenItemsShown) { + // Removing items from the model is not allowed if all hidden + // items should be shown. + return; + } + + const int newIndex = bookmarkIndex(index); + if (newIndex >= 0) { PlacesItem* hiddenItem = new PlacesItem(*shownItem); const KBookmark hiddenBookmark = hiddenItem->bookmark(); @@ -636,36 +757,71 @@ void PlacesItemModel::removeHiddenItem(int index) previousBookmark = previousItem->bookmark(); } + const bool updateBookmark = (m_bookmarkManager->root().indexOf(hiddenBookmark) >= 0); removeItem(index); - // removeItem() also removed the bookmark from m_bookmarkManager in - // PlacesItemModel::onItemRemoved(). However for hidden items the - // bookmark should still be remembered, so readd it again: - m_bookmarkManager->root().addBookmark(hiddenBookmark); - m_bookmarkManager->root().moveBookmark(hiddenBookmark, previousBookmark); + if (updateBookmark) { + // removeItem() also removed the bookmark from m_bookmarkManager in + // PlacesItemModel::onItemRemoved(). However for hidden items the + // bookmark should still be remembered, so readd it again: + m_bookmarkManager->root().addBookmark(hiddenBookmark); + m_bookmarkManager->root().moveBookmark(hiddenBookmark, previousBookmark); + m_saveBookmarksTimer->start(); + } - m_hiddenItems.insert(newIndex, hiddenItem); - m_saveBookmarksTimer->start(); + m_bookmarkedItems.insert(newIndex, hiddenItem); + } +} + +bool PlacesItemModel::equalBookmarkIdentifiers(const KBookmark& b1, const KBookmark& b2) +{ + const QString udi1 = b1.metaDataItem("UDI"); + const QString udi2 = b2.metaDataItem("UDI"); + if (!udi1.isEmpty() && !udi2.isEmpty()) { + return udi1 == udi2; + } else { + return b1.metaDataItem("ID") == b2.metaDataItem("ID"); } } #ifdef PLACESITEMMODEL_DEBUG void PlacesItemModel::showModelState() { - kDebug() << "hidden-index model-index text"; - int j = 0; - for (int i = 0; i < m_hiddenItems.count(); ++i) { - if (m_hiddenItems[i]) { - kDebug() << i << "(Hidden) " << " " << m_hiddenItems[i]->dataValue("text").toString(); + kDebug() << "================================="; + kDebug() << "Model:"; + kDebug() << "hidden-index model-index text"; + int modelIndex = 0; + for (int i = 0; i < m_bookmarkedItems.count(); ++i) { + if (m_bookmarkedItems[i]) { + kDebug() << i << "(Hidden) " << " " << m_bookmarkedItems[i]->dataValue("text").toString(); } else { - if (item(j)) { - kDebug() << i << " " << j << " " << item(j)->dataValue("text").toString(); + if (item(modelIndex)) { + kDebug() << i << " " << modelIndex << " " << item(modelIndex)->dataValue("text").toString(); } else { - kDebug() << i << " " << j << " " << "(not available yet)"; + kDebug() << i << " " << modelIndex << " " << "(not available yet)"; } - ++j; + ++modelIndex; } } + + kDebug(); + kDebug() << "Bookmarks:"; + + int bookmarkIndex = 0; + KBookmarkGroup root = m_bookmarkManager->root(); + KBookmark bookmark = root.first(); + while (!bookmark.isNull()) { + const QString udi = bookmark.metaDataItem("UDI"); + const QString text = udi.isEmpty() ? bookmark.text() : udi; + if (bookmark.metaDataItem("IsHidden") == QLatin1String("true")) { + kDebug() << bookmarkIndex << "(Hidden)" << text; + } else { + kDebug() << bookmarkIndex << " " << text; + } + + bookmark = root.next(bookmark); + ++bookmarkIndex; + } } #endif diff --git a/src/panels/places/placesitemmodel.h b/src/panels/places/placesitemmodel.h index b7591f66a1..9444324334 100644 --- a/src/panels/places/placesitemmodel.h +++ b/src/panels/places/placesitemmodel.h @@ -31,6 +31,7 @@ #include #include +class KBookmark; class KBookmarkManager; class PlacesItem; class QAction; @@ -52,15 +53,31 @@ public: explicit PlacesItemModel(QObject* parent = 0); virtual ~PlacesItemModel(); + /** + * @return A new instance of a places item with the given + * attributes. + */ PlacesItem* createPlacesItem(const QString& text, const KUrl& url, const QString& iconName); PlacesItem* placesItem(int index) const; + /** + * If set to true, all items that are marked as hidden + * will be shown in the view. The items will + * stay marked as hidden, which is visually indicated + * by the view by desaturating the icon and the text. + */ void setHiddenItemsShown(bool show); bool hiddenItemsShown() const; + /** + * @return Number of items that are marked as hidden. + * Note that this does not mean that the items + * are really hidden + * (see PlacesItemModel::setHiddenItemsShown()). + */ int hiddenCount() const; /** @@ -90,18 +107,35 @@ private slots: void slotDeviceAdded(const QString& udi); void slotDeviceRemoved(const QString& udi); void slotStorageTeardownDone(Solid::ErrorType error, const QVariant& errorData); - void removeHiddenItem(); + void hideItem(); + + /** + * Updates the bookmarks from the model corresponding to the changed + * bookmarks stored by the bookmark-manager. Is called whenever the bookmarks + * have been changed by another application. + */ + void updateBookmarks(); + + /** + * Saves the bookmarks and indicates to other applications that the + * state of the bookmarks has been changed. Is only called by the + * timeout of m_saveBookmarksTimer to prevent unnecessary savings. + */ void saveBookmarks(); private: - void loadBookmarks(); + /** + * Loads the bookmarks from the bookmark-manager and creates items for + * the model or moves hidden items to m_bookmarkedItems. + */ + void loadBookmarks(); /** - * Helper method for loadBookmarks(): Adds the items - * to the model if the "isHidden"-property is false, - * otherwise the items get added to m_hiddenItems. + * @return True, if the bookmark can be accepted in the context of the + * current application (e.g. bookmarks from other applications + * will be ignored). */ - void addItems(const QList& items); + bool acceptBookmark(const KBookmark& bookmark) const; /** * Creates system bookmarks that are shown per default and can @@ -114,11 +148,22 @@ private: /** * @param index Item index related to the model. - * @return Corresponding item index related to m_hiddenItems. + * @return Corresponding index related to m_bookmarkedItems. */ - int hiddenIndex(int index) const; + int bookmarkIndex(int index) const; - void removeHiddenItem(int index); + /** + * Marks the item with the index \a index as hidden and + * removes it from the model so that it gets invisible. + */ + void hideItem(int index); + + /** + * @return True if the bookmarks have the same identifiers. The identifier + * is the unique "ID"-property in case if no UDI is set, otherwise + * the UDI is used as identifier. + */ + static bool equalBookmarkIdentifiers(const KBookmark& b1, const KBookmark& b2); #ifdef PLACESITEMMODEL_DEBUG void showModelState(); @@ -146,7 +191,12 @@ private: QList m_systemBookmarks; QHash m_systemBookmarksIndexes; - QList m_hiddenItems; + // Contains hidden and unhidden items that are stored as + // bookmark (the model itself only contains items that + // are shown in the view). If an entry is 0, then the + // places-item is part of the model. If an entry is not + // 0, the item is hidden and not part of the model. + QList m_bookmarkedItems; // Index of the hidden item that should be removed in // removeHiddenItem(). The removing must be done @@ -155,6 +205,7 @@ private: int m_hiddenItemToRemove; QTimer* m_saveBookmarksTimer; + QTimer* m_updateBookmarksTimer; }; #endif