1 /***************************************************************************
2 * Copyright (C) 2012 by Peter Penz <peter.penz19@gmail.com> *
4 * Based on KFilePlacesModel from kdelibs: *
5 * Copyright (C) 2007 Kevin Ottens <ervin@kde.org> *
6 * Copyright (C) 2007 David Faure <faure@kde.org> *
8 * This program is free software; you can redistribute it and/or modify *
9 * it under the terms of the GNU General Public License as published by *
10 * the Free Software Foundation; either version 2 of the License, or *
11 * (at your option) any later version. *
13 * This program is distributed in the hope that it will be useful, *
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
16 * GNU General Public License for more details. *
18 * You should have received a copy of the GNU General Public License *
19 * along with this program; if not, write to the *
20 * Free Software Foundation, Inc., *
21 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA *
22 ***************************************************************************/
24 #include "placesitemmodel.h"
27 #include <KBookmarkGroup>
28 #include <KBookmarkManager>
29 #include <KComponentData>
33 #include <KStandardDirs>
35 #include "placesitem.h"
40 #include <Solid/Device>
41 #include <Solid/DeviceNotifier>
42 #include <Solid/OpticalDisc>
43 #include <Solid/OpticalDrive>
44 #include <Solid/StorageAccess>
45 #include <Solid/StorageDrive>
48 #include <Nepomuk/ResourceManager>
52 // As long as KFilePlacesView from kdelibs is available in parallel, the
53 // system-bookmarks for "Recently Accessed" and "Search For" should be
54 // shown only inside the Places Panel. This is necessary as the stored
55 // URLs needs to get translated to a Nepomuk-search-URL on-the-fly to
56 // be independent from changes in the Nepomuk-search-URL-syntax.
57 // Hence a prefix to the application-name of the stored bookmarks is
58 // added, which is only read by PlacesItemModel.
59 const char* AppNamePrefix
= "-places-panel";
62 PlacesItemModel::PlacesItemModel(QObject
* parent
) :
63 KStandardItemModel(parent
),
64 m_nepomukRunning(false),
65 m_hiddenItemsShown(false),
70 m_systemBookmarksIndexes(),
72 m_hiddenItemToRemove(-1),
73 m_saveBookmarksTimer(0),
74 m_updateBookmarksTimer(0)
77 m_nepomukRunning
= (Nepomuk::ResourceManager::instance()->initialized());
79 const QString file
= KStandardDirs::locateLocal("data", "kfileplaces/bookmarks.xml");
80 m_bookmarkManager
= KBookmarkManager::managerForFile(file
, "kfilePlaces");
82 createSystemBookmarks();
83 initializeAvailableDevices();
86 const int syncBookmarksTimeout
= 1000;
88 m_saveBookmarksTimer
= new QTimer(this);
89 m_saveBookmarksTimer
->setInterval(syncBookmarksTimeout
);
90 m_saveBookmarksTimer
->setSingleShot(true);
91 connect(m_saveBookmarksTimer
, SIGNAL(timeout()), this, SLOT(saveBookmarks()));
93 m_updateBookmarksTimer
= new QTimer(this);
94 m_updateBookmarksTimer
->setInterval(syncBookmarksTimeout
);
95 m_updateBookmarksTimer
->setSingleShot(true);
96 connect(m_updateBookmarksTimer
, SIGNAL(timeout()), this, SLOT(updateBookmarks()));
98 connect(m_bookmarkManager
, SIGNAL(changed(QString
,QString
)),
99 m_updateBookmarksTimer
, SLOT(start()));
100 connect(m_bookmarkManager
, SIGNAL(bookmarksChanged(QString
)),
101 m_updateBookmarksTimer
, SLOT(start()));
104 PlacesItemModel::~PlacesItemModel()
107 qDeleteAll(m_bookmarkedItems
);
108 m_bookmarkedItems
.clear();
111 PlacesItem
* PlacesItemModel::createPlacesItem(const QString
& text
,
113 const QString
& iconName
)
115 const KBookmark bookmark
= PlacesItem::createBookmark(m_bookmarkManager
, text
, url
, iconName
);
116 return new PlacesItem(bookmark
);
119 PlacesItem
* PlacesItemModel::placesItem(int index
) const
121 return dynamic_cast<PlacesItem
*>(item(index
));
124 int PlacesItemModel::hiddenCount() const
127 int hiddenItemCount
= 0;
128 foreach (const PlacesItem
* item
, m_bookmarkedItems
) {
132 if (placesItem(modelIndex
)->isHidden()) {
139 return hiddenItemCount
;
142 void PlacesItemModel::setHiddenItemsShown(bool show
)
144 if (m_hiddenItemsShown
== show
) {
148 m_hiddenItemsShown
= show
;
151 // Move all items that are part of m_bookmarkedItems to the model.
152 QList
<PlacesItem
*> itemsToInsert
;
153 QList
<int> insertPos
;
155 for (int i
= 0; i
< m_bookmarkedItems
.count(); ++i
) {
156 if (m_bookmarkedItems
[i
]) {
157 itemsToInsert
.append(m_bookmarkedItems
[i
]);
158 m_bookmarkedItems
[i
] = 0;
159 insertPos
.append(modelIndex
);
164 // Inserting the items will automatically insert an item
165 // to m_bookmarkedItems in PlacesItemModel::onItemsInserted().
166 // The items are temporary saved in itemsToInsert, so
167 // m_bookmarkedItems can be shrinked now.
168 m_bookmarkedItems
.erase(m_bookmarkedItems
.begin(),
169 m_bookmarkedItems
.begin() + itemsToInsert
.count());
171 for (int i
= 0; i
< itemsToInsert
.count(); ++i
) {
172 insertItem(insertPos
[i
], itemsToInsert
[i
]);
175 Q_ASSERT(m_bookmarkedItems
.count() == count());
177 // Move all items of the model, where the "isHidden" property is true, to
178 // m_bookmarkedItems.
179 Q_ASSERT(m_bookmarkedItems
.count() == count());
180 for (int i
= count() - 1; i
>= 0; --i
) {
181 if (placesItem(i
)->isHidden()) {
187 #ifdef PLACESITEMMODEL_DEBUG
188 kDebug() << "Changed visibility of hidden items";
193 bool PlacesItemModel::hiddenItemsShown() const
195 return m_hiddenItemsShown
;
198 int PlacesItemModel::closestItem(const KUrl
& url
) const
203 for (int i
= 0; i
< count(); ++i
) {
204 const KUrl itemUrl
= placesItem(i
)->url();
205 if (itemUrl
.isParentOf(url
)) {
206 const int length
= itemUrl
.prettyUrl().length();
207 if (length
> maxLength
) {
217 QAction
* PlacesItemModel::ejectAction(int index
) const
219 const PlacesItem
* item
= placesItem(index
);
220 if (item
&& item
->device().is
<Solid::OpticalDisc
>()) {
221 return new QAction(KIcon("media-eject"), i18nc("@item", "Eject '%1'", item
->text()), 0);
227 QAction
* PlacesItemModel::teardownAction(int index
) const
229 const PlacesItem
* item
= placesItem(index
);
234 Solid::Device device
= item
->device();
235 const bool providesTearDown
= device
.is
<Solid::StorageAccess
>() &&
236 device
.as
<Solid::StorageAccess
>()->isAccessible();
237 if (!providesTearDown
) {
241 Solid::StorageDrive
* drive
= device
.as
<Solid::StorageDrive
>();
243 drive
= device
.parent().as
<Solid::StorageDrive
>();
246 bool hotPluggable
= false;
247 bool removable
= false;
249 hotPluggable
= drive
->isHotpluggable();
250 removable
= drive
->isRemovable();
255 const QString label
= item
->text();
256 if (device
.is
<Solid::OpticalDisc
>()) {
257 text
= i18nc("@item", "Release '%1'", label
);
258 } else if (removable
|| hotPluggable
) {
259 text
= i18nc("@item", "Safely Remove '%1'", label
);
260 iconName
= "media-eject";
262 text
= i18nc("@item", "Unmount '%1'", label
);
263 iconName
= "media-eject";
266 if (iconName
.isEmpty()) {
267 return new QAction(text
, 0);
270 return new QAction(KIcon(iconName
), text
, 0);
273 void PlacesItemModel::requestEject(int index
)
275 const PlacesItem
* item
= placesItem(index
);
277 Solid::OpticalDrive
* drive
= item
->device().parent().as
<Solid::OpticalDrive
>();
279 connect(drive
, SIGNAL(ejectDone(Solid::ErrorType
,QVariant
,QString
)),
280 this, SLOT(slotStorageTeardownDone(Solid::ErrorType
,QVariant
)));
288 void PlacesItemModel::requestTeardown(int index
)
290 const PlacesItem
* item
= placesItem(index
);
292 Solid::StorageAccess
* access
= item
->device().as
<Solid::StorageAccess
>();
294 connect(access
, SIGNAL(teardownDone(Solid::ErrorType
,QVariant
,QString
)),
295 this, SLOT(slotStorageTeardownDone(Solid::ErrorType
,QVariant
)));
298 const QString label
= item
->text();
299 const QString message
= i18nc("@info", "The device '%1' is not a disk and cannot be ejected.", label
);
300 emit
errorMessage(message
);
305 void PlacesItemModel::onItemInserted(int index
)
307 const PlacesItem
* insertedItem
= placesItem(index
);
309 // Take care to apply the PlacesItemModel-order of the inserted item
310 // also to the bookmark-manager.
311 const KBookmark insertedBookmark
= insertedItem
->bookmark();
313 const PlacesItem
* previousItem
= placesItem(index
- 1);
314 KBookmark previousBookmark
;
316 previousBookmark
= previousItem
->bookmark();
319 m_bookmarkManager
->root().moveBookmark(insertedBookmark
, previousBookmark
);
322 if (index
== count() - 1) {
323 // The item has been appended as last item to the list. In this
324 // case assure that it is also appended after the hidden items and
325 // not before (like done otherwise).
326 m_bookmarkedItems
.append(0);
330 int bookmarkIndex
= 0;
331 while (bookmarkIndex
< m_bookmarkedItems
.count()) {
332 if (!m_bookmarkedItems
[bookmarkIndex
]) {
334 if (modelIndex
+ 1 == index
) {
340 m_bookmarkedItems
.insert(bookmarkIndex
, 0);
343 triggerBookmarksSaving();
345 #ifdef PLACESITEMMODEL_DEBUG
346 kDebug() << "Inserted item" << index
;
351 void PlacesItemModel::onItemRemoved(int index
, KStandardItem
* removedItem
)
353 PlacesItem
* placesItem
= dynamic_cast<PlacesItem
*>(removedItem
);
355 const KBookmark bookmark
= placesItem
->bookmark();
356 m_bookmarkManager
->root().deleteBookmark(bookmark
);
359 const int boomarkIndex
= bookmarkIndex(index
);
360 Q_ASSERT(!m_bookmarkedItems
[boomarkIndex
]);
361 m_bookmarkedItems
.removeAt(boomarkIndex
);
363 triggerBookmarksSaving();
365 #ifdef PLACESITEMMODEL_DEBUG
366 kDebug() << "Removed item" << index
;
371 void PlacesItemModel::onItemChanged(int index
, const QSet
<QByteArray
>& changedRoles
)
373 const PlacesItem
* changedItem
= placesItem(index
);
375 // Take care to apply the PlacesItemModel-order of the inserted item
376 // also to the bookmark-manager.
377 const KBookmark insertedBookmark
= changedItem
->bookmark();
379 const PlacesItem
* previousItem
= placesItem(index
- 1);
380 KBookmark previousBookmark
;
382 previousBookmark
= previousItem
->bookmark();
385 m_bookmarkManager
->root().moveBookmark(insertedBookmark
, previousBookmark
);
388 if (changedRoles
.contains("isHidden")) {
389 const PlacesItem
* shownItem
= placesItem(index
);
391 if (!m_hiddenItemsShown
&& shownItem
->isHidden()) {
392 m_hiddenItemToRemove
= index
;
393 QTimer::singleShot(0, this, SLOT(hideItem()));
397 triggerBookmarksSaving();
400 void PlacesItemModel::slotDeviceAdded(const QString
& udi
)
402 const Solid::Device
device(udi
);
403 if (m_predicate
.matches(device
)) {
404 m_availableDevices
<< udi
;
405 const KBookmark bookmark
= PlacesItem::createDeviceBookmark(m_bookmarkManager
, udi
);
406 appendItem(new PlacesItem(bookmark
));
410 void PlacesItemModel::slotDeviceRemoved(const QString
& udi
)
412 if (!m_availableDevices
.contains(udi
)) {
416 for (int i
= 0; i
< m_bookmarkedItems
.count(); ++i
) {
417 PlacesItem
* item
= m_bookmarkedItems
[i
];
418 if (item
&& item
->udi() == udi
) {
419 m_bookmarkedItems
.removeAt(i
);
425 for (int i
= 0; i
< count(); ++i
) {
426 if (placesItem(i
)->udi() == udi
) {
433 void PlacesItemModel::slotStorageTeardownDone(Solid::ErrorType error
, const QVariant
& errorData
)
435 if (error
&& errorData
.isValid()) {
436 emit
errorMessage(errorData
.toString());
440 void PlacesItemModel::hideItem()
442 hideItem(m_hiddenItemToRemove
);
443 m_hiddenItemToRemove
= -1;
446 void PlacesItemModel::updateBookmarks()
448 // Verify whether new bookmarks have been added or existing
449 // bookmarks have been changed.
450 KBookmarkGroup root
= m_bookmarkManager
->root();
451 KBookmark newBookmark
= root
.first();
452 while (!newBookmark
.isNull()) {
453 if (acceptBookmark(newBookmark
)) {
456 for (int i
= 0; i
< m_bookmarkedItems
.count(); ++i
) {
457 PlacesItem
* item
= m_bookmarkedItems
[i
];
459 item
= placesItem(modelIndex
);
463 const KBookmark oldBookmark
= item
->bookmark();
464 if (equalBookmarkIdentifiers(newBookmark
, oldBookmark
)) {
465 // The bookmark has been found in the model or as
466 // a hidden item. The content of the bookmark might
467 // have been changed, so an update is done.
469 if (newBookmark
.metaDataItem("UDI").isEmpty()) {
470 item
->setBookmark(newBookmark
);
477 PlacesItem
* item
= new PlacesItem(newBookmark
);
478 if (item
->isHidden() && !m_hiddenItemsShown
) {
479 m_bookmarkedItems
.append(item
);
486 newBookmark
= root
.next(newBookmark
);
489 // Remove items that are not part of the bookmark-manager anymore
491 for (int i
= m_bookmarkedItems
.count() - 1; i
>= 0; --i
) {
492 PlacesItem
* item
= m_bookmarkedItems
[i
];
493 const bool itemIsPartOfModel
= (item
== 0);
494 if (itemIsPartOfModel
) {
495 item
= placesItem(modelIndex
);
498 bool hasBeenRemoved
= true;
499 const KBookmark oldBookmark
= item
->bookmark();
500 KBookmark newBookmark
= root
.first();
501 while (!newBookmark
.isNull()) {
502 if (equalBookmarkIdentifiers(newBookmark
, oldBookmark
)) {
503 hasBeenRemoved
= false;
506 newBookmark
= root
.next(newBookmark
);
509 if (hasBeenRemoved
) {
510 if (m_bookmarkedItems
[i
]) {
511 delete m_bookmarkedItems
[i
];
512 m_bookmarkedItems
.removeAt(i
);
514 removeItem(modelIndex
);
519 if (itemIsPartOfModel
) {
525 void PlacesItemModel::saveBookmarks()
527 m_bookmarkManager
->emitChanged(m_bookmarkManager
->root());
530 void PlacesItemModel::loadBookmarks()
532 KBookmarkGroup root
= m_bookmarkManager
->root();
533 KBookmark bookmark
= root
.first();
534 QSet
<QString
> devices
= m_availableDevices
;
536 QSet
<KUrl
> missingSystemBookmarks
;
537 foreach (const SystemBookmarkData
& data
, m_systemBookmarks
) {
538 missingSystemBookmarks
.insert(data
.url
);
541 // The bookmarks might have a mixed order of places, devices and search-groups due
542 // to the compatibility with the KFilePlacesPanel. In Dolphin's places panel the
543 // items should always be collected in one group so the items are collected first
544 // in separate lists before inserting them.
545 QList
<PlacesItem
*> placesItems
;
546 QList
<PlacesItem
*> recentlyAccessedItems
;
547 QList
<PlacesItem
*> searchForItems
;
548 QList
<PlacesItem
*> devicesItems
;
550 while (!bookmark
.isNull()) {
551 const bool deviceAvailable
= devices
.remove(bookmark
.metaDataItem("UDI"));
552 if (acceptBookmark(bookmark
)) {
553 PlacesItem
* item
= new PlacesItem(bookmark
);
554 if (deviceAvailable
) {
555 devicesItems
.append(item
);
557 const KUrl url
= bookmark
.url();
558 if (missingSystemBookmarks
.contains(url
)) {
559 missingSystemBookmarks
.remove(url
);
561 // Apply the translated text to the system bookmarks, otherwise an outdated
562 // translation might be shown.
563 const int index
= m_systemBookmarksIndexes
.value(url
);
564 item
->setText(m_systemBookmarks
[index
].text
);
565 item
->setSystemItem(true);
568 switch (item
->groupType()) {
569 case PlacesItem::PlacesType
: placesItems
.append(item
); break;
570 case PlacesItem::RecentlyAccessedType
: recentlyAccessedItems
.append(item
); break;
571 case PlacesItem::SearchForType
: searchForItems
.append(item
); break;
572 case PlacesItem::DevicesType
:
573 default: Q_ASSERT(false); break;
578 bookmark
= root
.next(bookmark
);
581 if (!missingSystemBookmarks
.isEmpty()) {
582 // The current bookmarks don't contain all system-bookmarks. Add the missing
584 foreach (const SystemBookmarkData
& data
, m_systemBookmarks
) {
585 if (missingSystemBookmarks
.contains(data
.url
)) {
586 KBookmark bookmark
= PlacesItem::createBookmark(m_bookmarkManager
,
591 const QString protocol
= data
.url
.protocol();
592 if (protocol
== QLatin1String("timeline") || protocol
== QLatin1String("search")) {
593 // As long as the KFilePlacesView from kdelibs is available, the system-bookmarks
594 // for "Recently Accessed" and "Search For" should be a setting available only
595 // in the Places Panel (see description of AppNamePrefix for more details).
596 const QString appName
= KGlobal::mainComponent().componentName() + AppNamePrefix
;
597 bookmark
.setMetaDataItem("OnlyInApp", appName
);
600 PlacesItem
* item
= new PlacesItem(bookmark
);
601 item
->setSystemItem(true);
603 switch (item
->groupType()) {
604 case PlacesItem::PlacesType
: placesItems
.append(item
); break;
605 case PlacesItem::RecentlyAccessedType
: recentlyAccessedItems
.append(item
); break;
606 case PlacesItem::SearchForType
: searchForItems
.append(item
); break;
607 case PlacesItem::DevicesType
:
608 default: Q_ASSERT(false); break;
614 // Create items for devices that have not been stored as bookmark yet
615 foreach (const QString
& udi
, devices
) {
616 const KBookmark bookmark
= PlacesItem::createDeviceBookmark(m_bookmarkManager
, udi
);
617 devicesItems
.append(new PlacesItem(bookmark
));
620 QList
<PlacesItem
*> items
;
621 items
.append(placesItems
);
622 items
.append(recentlyAccessedItems
);
623 items
.append(searchForItems
);
624 items
.append(devicesItems
);
626 foreach (PlacesItem
* item
, items
) {
627 if (!m_hiddenItemsShown
&& item
->isHidden()) {
628 m_bookmarkedItems
.append(item
);
634 #ifdef PLACESITEMMODEL_DEBUG
635 kDebug() << "Loaded bookmarks";
640 bool PlacesItemModel::acceptBookmark(const KBookmark
& bookmark
) const
642 const QString udi
= bookmark
.metaDataItem("UDI");
643 const KUrl url
= bookmark
.url();
644 const QString appName
= bookmark
.metaDataItem("OnlyInApp");
645 const bool deviceAvailable
= m_availableDevices
.contains(udi
);
647 const bool allowedHere
= (appName
.isEmpty()
648 || appName
== KGlobal::mainComponent().componentName()
649 || appName
== KGlobal::mainComponent().componentName() + AppNamePrefix
)
650 && (m_nepomukRunning
|| (url
.protocol() != QLatin1String("timeline") &&
651 url
.protocol() != QLatin1String("search")));
653 return (udi
.isEmpty() && allowedHere
) || deviceAvailable
;
656 void PlacesItemModel::createSystemBookmarks()
658 Q_ASSERT(m_systemBookmarks
.isEmpty());
659 Q_ASSERT(m_systemBookmarksIndexes
.isEmpty());
661 const QString timeLineIcon
= "package_utility_time"; // TODO: Ask the Oxygen team to create
662 // a custom icon for the timeline-protocol
664 m_systemBookmarks
.append(SystemBookmarkData(KUrl(KUser().homeDir()),
666 i18nc("@item", "Home")));
667 m_systemBookmarks
.append(SystemBookmarkData(KUrl("remote:/"),
669 i18nc("@item", "Network")));
670 m_systemBookmarks
.append(SystemBookmarkData(KUrl("/"),
672 i18nc("@item", "Root")));
673 m_systemBookmarks
.append(SystemBookmarkData(KUrl("trash:/"),
675 i18nc("@item", "Trash")));
677 if (m_nepomukRunning
) {
678 m_systemBookmarks
.append(SystemBookmarkData(KUrl("timeline:/today"),
680 i18nc("@item Recently Accessed", "Today")));
681 m_systemBookmarks
.append(SystemBookmarkData(KUrl("timeline:/yesterday"),
683 i18nc("@item Recently Accessed", "Yesterday")));
684 m_systemBookmarks
.append(SystemBookmarkData(KUrl("timeline:/thismonth"),
686 i18nc("@item Recently Accessed", "This Month")));
687 m_systemBookmarks
.append(SystemBookmarkData(KUrl("timeline:/lastmonth"),
689 i18nc("@item Recently Accessed", "Last Month")));
690 m_systemBookmarks
.append(SystemBookmarkData(KUrl("search:/documents"),
692 i18nc("@item Commonly Accessed", "Documents")));
693 m_systemBookmarks
.append(SystemBookmarkData(KUrl("search:/images"),
695 i18nc("@item Commonly Accessed", "Images")));
696 m_systemBookmarks
.append(SystemBookmarkData(KUrl("search:/audio"),
698 i18nc("@item Commonly Accessed", "Audio Files")));
699 m_systemBookmarks
.append(SystemBookmarkData(KUrl("search:/videos"),
701 i18nc("@item Commonly Accessed", "Videos")));
704 for (int i
= 0; i
< m_systemBookmarks
.count(); ++i
) {
705 m_systemBookmarksIndexes
.insert(m_systemBookmarks
[i
].url
, i
);
709 void PlacesItemModel::initializeAvailableDevices()
711 m_predicate
= Solid::Predicate::fromString(
712 "[[[[ StorageVolume.ignored == false AND [ StorageVolume.usage == 'FileSystem' OR StorageVolume.usage == 'Encrypted' ]]"
714 "[ IS StorageAccess AND StorageDrive.driveType == 'Floppy' ]]"
716 "OpticalDisc.availableContent & 'Audio' ]"
718 "StorageAccess.ignored == false ]");
719 Q_ASSERT(m_predicate
.isValid());
721 Solid::DeviceNotifier
* notifier
= Solid::DeviceNotifier::instance();
722 connect(notifier
, SIGNAL(deviceAdded(QString
)), this, SLOT(slotDeviceAdded(QString
)));
723 connect(notifier
, SIGNAL(deviceRemoved(QString
)), this, SLOT(slotDeviceRemoved(QString
)));
725 const QList
<Solid::Device
>& deviceList
= Solid::Device::listFromQuery(m_predicate
);
726 foreach(const Solid::Device
& device
, deviceList
) {
727 m_availableDevices
<< device
.udi();
731 int PlacesItemModel::bookmarkIndex(int index
) const
733 int bookmarkIndex
= 0;
735 while (bookmarkIndex
< m_bookmarkedItems
.count()) {
736 if (!m_bookmarkedItems
[bookmarkIndex
]) {
737 if (modelIndex
== index
) {
745 return bookmarkIndex
>= m_bookmarkedItems
.count() ? -1 : bookmarkIndex
;
748 void PlacesItemModel::hideItem(int index
)
750 PlacesItem
* shownItem
= placesItem(index
);
755 shownItem
->setHidden(true);
756 if (m_hiddenItemsShown
) {
757 // Removing items from the model is not allowed if all hidden
758 // items should be shown.
762 const int newIndex
= bookmarkIndex(index
);
764 PlacesItem
* hiddenItem
= new PlacesItem(*shownItem
);
765 const KBookmark hiddenBookmark
= hiddenItem
->bookmark();
767 const PlacesItem
* previousItem
= placesItem(index
- 1);
768 KBookmark previousBookmark
;
770 previousBookmark
= previousItem
->bookmark();
773 const bool updateBookmark
= (m_bookmarkManager
->root().indexOf(hiddenBookmark
) >= 0);
776 if (updateBookmark
) {
777 // removeItem() also removed the bookmark from m_bookmarkManager in
778 // PlacesItemModel::onItemRemoved(). However for hidden items the
779 // bookmark should still be remembered, so readd it again:
780 m_bookmarkManager
->root().addBookmark(hiddenBookmark
);
781 m_bookmarkManager
->root().moveBookmark(hiddenBookmark
, previousBookmark
);
782 triggerBookmarksSaving();
785 m_bookmarkedItems
.insert(newIndex
, hiddenItem
);
789 void PlacesItemModel::triggerBookmarksSaving()
791 if (m_saveBookmarksTimer
) {
792 m_saveBookmarksTimer
->start();
796 bool PlacesItemModel::equalBookmarkIdentifiers(const KBookmark
& b1
, const KBookmark
& b2
)
798 const QString udi1
= b1
.metaDataItem("UDI");
799 const QString udi2
= b2
.metaDataItem("UDI");
800 if (!udi1
.isEmpty() && !udi2
.isEmpty()) {
803 return b1
.metaDataItem("ID") == b2
.metaDataItem("ID");
807 #ifdef PLACESITEMMODEL_DEBUG
808 void PlacesItemModel::showModelState()
810 kDebug() << "=================================";
811 kDebug() << "Model:";
812 kDebug() << "hidden-index model-index text";
814 for (int i
= 0; i
< m_bookmarkedItems
.count(); ++i
) {
815 if (m_bookmarkedItems
[i
]) {
816 kDebug() << i
<< "(Hidden) " << " " << m_bookmarkedItems
[i
]->dataValue("text").toString();
818 if (item(modelIndex
)) {
819 kDebug() << i
<< " " << modelIndex
<< " " << item(modelIndex
)->dataValue("text").toString();
821 kDebug() << i
<< " " << modelIndex
<< " " << "(not available yet)";
828 kDebug() << "Bookmarks:";
830 int bookmarkIndex
= 0;
831 KBookmarkGroup root
= m_bookmarkManager
->root();
832 KBookmark bookmark
= root
.first();
833 while (!bookmark
.isNull()) {
834 const QString udi
= bookmark
.metaDataItem("UDI");
835 const QString text
= udi
.isEmpty() ? bookmark
.text() : udi
;
836 if (bookmark
.metaDataItem("IsHidden") == QLatin1String("true")) {
837 kDebug() << bookmarkIndex
<< "(Hidden)" << text
;
839 kDebug() << bookmarkIndex
<< " " << text
;
842 bookmark
= root
.next(bookmark
);
848 #include "placesitemmodel.moc"