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"
26 #include "dolphin_generalsettings.h"
27 #include "dolphindebug.h"
28 #include "dolphinplacesmodelsingleton.h"
29 #include "placesitem.h"
30 #include "placesitemsignalhandler.h"
31 #include "views/dolphinview.h"
32 #include "views/viewproperties.h"
35 #include <KLocalizedString>
36 #include <KUrlMimeData>
37 #include <Solid/DeviceNotifier>
38 #include <Solid/OpticalDrive>
46 static QList
<QUrl
> balooURLs
= {
47 QUrl(QStringLiteral("timeline:/today")),
48 QUrl(QStringLiteral("timeline:/yesterday")),
49 QUrl(QStringLiteral("timeline:/thismonth")),
50 QUrl(QStringLiteral("timeline:/lastmonth")),
51 QUrl(QStringLiteral("search:/documents")),
52 QUrl(QStringLiteral("search:/images")),
53 QUrl(QStringLiteral("search:/audio")),
54 QUrl(QStringLiteral("search:/videos"))
58 PlacesItemModel::PlacesItemModel(QObject
* parent
) :
59 KStandardItemModel(parent
),
60 m_hiddenItemsShown(false),
61 m_deviceToTearDown(nullptr),
62 m_storageSetupInProgress(),
63 m_sourceModel(DolphinPlacesModelSingleton::instance().placesModel())
67 initializeDefaultViewProperties();
69 connect(m_sourceModel
, &KFilePlacesModel::rowsInserted
, this, &PlacesItemModel::onSourceModelRowsInserted
);
70 connect(m_sourceModel
, &KFilePlacesModel::rowsAboutToBeRemoved
, this, &PlacesItemModel::onSourceModelRowsAboutToBeRemoved
);
71 connect(m_sourceModel
, &KFilePlacesModel::dataChanged
, this, &PlacesItemModel::onSourceModelDataChanged
);
72 connect(m_sourceModel
, &KFilePlacesModel::rowsAboutToBeMoved
, this, &PlacesItemModel::onSourceModelRowsAboutToBeMoved
);
73 connect(m_sourceModel
, &KFilePlacesModel::rowsMoved
, this, &PlacesItemModel::onSourceModelRowsMoved
);
74 connect(m_sourceModel
, &KFilePlacesModel::groupHiddenChanged
, this, &PlacesItemModel::onSourceModelGroupHiddenChanged
);
77 PlacesItemModel::~PlacesItemModel()
81 void PlacesItemModel::createPlacesItem(const QString
&text
, const QUrl
&url
, const QString
&iconName
, const QString
&appName
)
83 createPlacesItem(text
, url
, iconName
, appName
, -1);
86 void PlacesItemModel::createPlacesItem(const QString
&text
, const QUrl
&url
, const QString
&iconName
, const QString
&appName
, int after
)
88 m_sourceModel
->addPlace(text
, url
, iconName
, appName
, mapToSource(after
));
91 PlacesItem
* PlacesItemModel::placesItem(int index
) const
93 return dynamic_cast<PlacesItem
*>(item(index
));
96 int PlacesItemModel::hiddenCount() const
98 return m_sourceModel
->hiddenCount();
101 void PlacesItemModel::setHiddenItemsShown(bool show
)
103 if (m_hiddenItemsShown
== show
) {
107 m_hiddenItemsShown
= show
;
110 for (int r
= 0, rMax
= m_sourceModel
->rowCount(); r
< rMax
; r
++) {
111 const QModelIndex index
= m_sourceModel
->index(r
, 0);
112 if (!m_sourceModel
->isHidden(index
)) {
115 addItemFromSourceModel(index
);
118 for (int r
= 0, rMax
= m_sourceModel
->rowCount(); r
< rMax
; r
++) {
119 const QModelIndex index
= m_sourceModel
->index(r
, 0);
120 if (m_sourceModel
->isHidden(index
)) {
121 removeItemByIndex(index
);
127 bool PlacesItemModel::hiddenItemsShown() const
129 return m_hiddenItemsShown
;
132 int PlacesItemModel::closestItem(const QUrl
& url
) const
134 return mapFromSource(m_sourceModel
->closestItem(url
));
137 // look for the correct position for the item based on source model
138 void PlacesItemModel::insertSortedItem(PlacesItem
* item
)
144 const KBookmark iBookmark
= item
->bookmark();
145 const QString iBookmarkId
= bookmarkId(iBookmark
);
146 QModelIndex sourceIndex
;
149 for(int r
= 0, rMax
= m_sourceModel
->rowCount(); r
< rMax
; r
++) {
150 sourceIndex
= m_sourceModel
->index(r
, 0);
151 const KBookmark sourceBookmark
= m_sourceModel
->bookmarkForIndex(sourceIndex
);
153 if (bookmarkId(sourceBookmark
) == iBookmarkId
) {
157 if (m_hiddenItemsShown
|| !m_sourceModel
->isHidden(sourceIndex
)) {
162 m_indexMap
.insert(pos
, sourceIndex
);
163 insertItem(pos
, item
);
166 void PlacesItemModel::onItemInserted(int index
)
168 KStandardItemModel::onItemInserted(index
);
171 void PlacesItemModel::onItemRemoved(int index
, KStandardItem
* removedItem
)
173 m_indexMap
.removeAt(index
);
175 KStandardItemModel::onItemRemoved(index
, removedItem
);
178 void PlacesItemModel::onItemChanged(int index
, const QSet
<QByteArray
>& changedRoles
)
180 const QModelIndex sourceIndex
= mapToSource(index
);
181 const PlacesItem
*changedItem
= placesItem(mapFromSource(sourceIndex
));
183 if (!changedItem
|| !sourceIndex
.isValid()) {
184 qWarning() << "invalid item changed signal";
187 if (changedRoles
.contains("isHidden")) {
188 if (m_sourceModel
->isHidden(sourceIndex
) != changedItem
->isHidden()) {
189 m_sourceModel
->setPlaceHidden(sourceIndex
, changedItem
->isHidden());
191 m_sourceModel
->refresh();
194 KStandardItemModel::onItemChanged(index
, changedRoles
);
197 QAction
* PlacesItemModel::ejectAction(int index
) const
199 const PlacesItem
* item
= placesItem(index
);
200 if (item
&& item
->device().is
<Solid::OpticalDisc
>()) {
201 return new QAction(QIcon::fromTheme(QStringLiteral("media-eject")), i18nc("@item", "Eject"), nullptr);
207 QAction
* PlacesItemModel::teardownAction(int index
) const
209 const PlacesItem
* item
= placesItem(index
);
214 Solid::Device device
= item
->device();
215 const bool providesTearDown
= device
.is
<Solid::StorageAccess
>() &&
216 device
.as
<Solid::StorageAccess
>()->isAccessible();
217 if (!providesTearDown
) {
221 Solid::StorageDrive
* drive
= device
.as
<Solid::StorageDrive
>();
223 drive
= device
.parent().as
<Solid::StorageDrive
>();
226 bool hotPluggable
= false;
227 bool removable
= false;
229 hotPluggable
= drive
->isHotpluggable();
230 removable
= drive
->isRemovable();
235 if (device
.is
<Solid::OpticalDisc
>()) {
236 text
= i18nc("@item", "Release");
237 } else if (removable
|| hotPluggable
) {
238 text
= i18nc("@item", "Safely Remove");
239 iconName
= QStringLiteral("media-eject");
241 text
= i18nc("@item", "Unmount");
242 iconName
= QStringLiteral("media-eject");
245 if (iconName
.isEmpty()) {
246 return new QAction(text
, nullptr);
249 return new QAction(QIcon::fromTheme(iconName
), text
, nullptr);
252 void PlacesItemModel::requestEject(int index
)
254 const PlacesItem
* item
= placesItem(index
);
256 Solid::OpticalDrive
* drive
= item
->device().parent().as
<Solid::OpticalDrive
>();
258 connect(drive
, &Solid::OpticalDrive::ejectDone
,
259 this, &PlacesItemModel::slotStorageTearDownDone
);
262 const QString label
= item
->text();
263 const QString message
= i18nc("@info", "The device '%1' is not a disk and cannot be ejected.", label
);
264 emit
errorMessage(message
);
269 void PlacesItemModel::requestTearDown(int index
)
271 const PlacesItem
* item
= placesItem(index
);
273 Solid::StorageAccess
*tmp
= item
->device().as
<Solid::StorageAccess
>();
275 m_deviceToTearDown
= tmp
;
276 // disconnect the Solid::StorageAccess::teardownRequested
277 // to prevent emitting PlacesItemModel::storageTearDownExternallyRequested
278 // after we have emitted PlacesItemModel::storageTearDownRequested
279 disconnect(tmp
, &Solid::StorageAccess::teardownRequested
,
280 item
->signalHandler(), &PlacesItemSignalHandler::onTearDownRequested
);
281 emit
storageTearDownRequested(tmp
->filePath());
286 bool PlacesItemModel::storageSetupNeeded(int index
) const
288 const PlacesItem
* item
= placesItem(index
);
289 return item
? item
->storageSetupNeeded() : false;
292 void PlacesItemModel::requestStorageSetup(int index
)
294 const PlacesItem
* item
= placesItem(index
);
299 Solid::Device device
= item
->device();
300 const bool setup
= device
.is
<Solid::StorageAccess
>()
301 && !m_storageSetupInProgress
.contains(device
.as
<Solid::StorageAccess
>())
302 && !device
.as
<Solid::StorageAccess
>()->isAccessible();
304 Solid::StorageAccess
* access
= device
.as
<Solid::StorageAccess
>();
306 m_storageSetupInProgress
[access
] = index
;
308 connect(access
, &Solid::StorageAccess::setupDone
,
309 this, &PlacesItemModel::slotStorageSetupDone
);
315 QMimeData
* PlacesItemModel::createMimeData(const KItemSet
& indexes
) const
320 QDataStream
stream(&itemData
, QIODevice::WriteOnly
);
322 for (int index
: indexes
) {
323 const QUrl itemUrl
= placesItem(index
)->url();
324 if (itemUrl
.isValid()) {
330 QMimeData
* mimeData
= new QMimeData();
331 if (!urls
.isEmpty()) {
332 mimeData
->setUrls(urls
);
334 // #378954: prevent itemDropEvent() drops if there isn't a source url.
335 mimeData
->setData(blacklistItemDropEventMimeType(), QByteArrayLiteral("true"));
337 mimeData
->setData(internalMimeType(), itemData
);
342 bool PlacesItemModel::supportsDropping(int index
) const
344 return index
>= 0 && index
< count();
347 void PlacesItemModel::dropMimeDataBefore(int index
, const QMimeData
* mimeData
)
349 if (mimeData
->hasFormat(internalMimeType())) {
350 // The item has been moved inside the view
351 QByteArray itemData
= mimeData
->data(internalMimeType());
352 QDataStream
stream(&itemData
, QIODevice::ReadOnly
);
356 m_sourceModel
->movePlace(oldIndex
, index
);
357 } else if (mimeData
->hasFormat(QStringLiteral("text/uri-list"))) {
358 // One or more items must be added to the model
359 const QList
<QUrl
> urls
= KUrlMimeData::urlsFromMimeData(mimeData
);
360 for (int i
= urls
.count() - 1; i
>= 0; --i
) {
361 const QUrl
& url
= urls
[i
];
363 QString text
= url
.fileName();
364 if (text
.isEmpty()) {
368 if ((url
.isLocalFile() && !QFileInfo(url
.toLocalFile()).isDir())
369 || url
.scheme() == QLatin1String("trash")) {
370 // Only directories outside the trash are allowed
374 createPlacesItem(text
, url
, KIO::iconNameForUrl(url
), {}, qMax(0, index
- 1));
377 // will save bookmark alteration and fix sort if that is broken by the drag/drop operation
381 void PlacesItemModel::addItemFromSourceModel(const QModelIndex
&index
)
383 if (!m_hiddenItemsShown
&& m_sourceModel
->isHidden(index
)) {
387 const KBookmark bookmark
= m_sourceModel
->bookmarkForIndex(index
);
388 Q_ASSERT(!bookmark
.isNull());
389 PlacesItem
*item
= new PlacesItem(bookmark
);
390 updateItem(item
, index
);
391 insertSortedItem(item
);
393 if (m_sourceModel
->isDevice(index
)) {
394 connect(item
->signalHandler(), &PlacesItemSignalHandler::tearDownExternallyRequested
,
395 this, &PlacesItemModel::storageTearDownExternallyRequested
);
399 void PlacesItemModel::removeItemByIndex(const QModelIndex
&sourceIndex
)
401 QString id
= bookmarkId(m_sourceModel
->bookmarkForIndex(sourceIndex
));
403 for (int i
= 0, iMax
= count(); i
< iMax
; ++i
) {
404 if (bookmarkId(placesItem(i
)->bookmark()) == id
) {
411 QString
PlacesItemModel::bookmarkId(const KBookmark
&bookmark
) const
413 QString id
= bookmark
.metaDataItem(QStringLiteral("UDI"));
415 id
= bookmark
.metaDataItem(QStringLiteral("ID"));
420 void PlacesItemModel::initializeDefaultViewProperties() const
422 for(int i
= 0, iMax
= m_sourceModel
->rowCount(); i
< iMax
; i
++) {
423 const QModelIndex index
= m_sourceModel
->index(i
, 0);
424 const PlacesItem
*item
= placesItem(mapFromSource(index
));
429 // Create default view-properties for all "Search For" and "Recently Saved" bookmarks
430 // in case the user has not already created custom view-properties for a corresponding
432 const bool createDefaultViewProperties
= item
->isSearchOrTimelineUrl() && !GeneralSettings::self()->globalViewProps();
433 if (createDefaultViewProperties
) {
434 const QUrl itemUrl
= item
->url();
435 ViewProperties
props(KFilePlacesModel::convertedUrl(itemUrl
));
436 if (!props
.exist()) {
437 const QString path
= itemUrl
.path();
438 if (path
== QLatin1String("/documents")) {
439 props
.setViewMode(DolphinView::DetailsView
);
440 props
.setPreviewsShown(false);
441 props
.setVisibleRoles({"text", "path"});
442 } else if (path
== QLatin1String("/images")) {
443 props
.setViewMode(DolphinView::IconsView
);
444 props
.setPreviewsShown(true);
445 props
.setVisibleRoles({"text", "height", "width"});
446 } else if (path
== QLatin1String("/audio")) {
447 props
.setViewMode(DolphinView::DetailsView
);
448 props
.setPreviewsShown(false);
449 props
.setVisibleRoles({"text", "artist", "album"});
450 } else if (path
== QLatin1String("/videos")) {
451 props
.setViewMode(DolphinView::IconsView
);
452 props
.setPreviewsShown(true);
453 props
.setVisibleRoles({"text"});
454 } else if (itemUrl
.scheme() == QLatin1String("timeline")) {
455 props
.setViewMode(DolphinView::DetailsView
);
456 props
.setVisibleRoles({"text", "modificationtime"});
464 void PlacesItemModel::updateItem(PlacesItem
*item
, const QModelIndex
&index
)
466 item
->setGroup(index
.data(KFilePlacesModel::GroupRole
).toString());
467 item
->setIcon(index
.data(KFilePlacesModel::IconNameRole
).toString());
468 item
->setGroupHidden(index
.data(KFilePlacesModel::GroupHiddenRole
).toBool());
471 void PlacesItemModel::slotStorageTearDownDone(Solid::ErrorType error
, const QVariant
& errorData
)
473 if (error
&& errorData
.isValid()) {
474 emit
errorMessage(errorData
.toString());
476 disconnect(m_deviceToTearDown
, &Solid::StorageAccess::teardownDone
,
477 this, &PlacesItemModel::slotStorageTearDownDone
);
478 m_deviceToTearDown
= nullptr;
481 void PlacesItemModel::slotStorageSetupDone(Solid::ErrorType error
,
482 const QVariant
& errorData
,
487 const int index
= m_storageSetupInProgress
.take(sender());
488 const PlacesItem
* item
= placesItem(index
);
493 if (error
!= Solid::NoError
) {
494 if (errorData
.isValid()) {
495 emit
errorMessage(i18nc("@info", "An error occurred while accessing '%1', the system responded: %2",
497 errorData
.toString()));
499 emit
errorMessage(i18nc("@info", "An error occurred while accessing '%1'",
502 emit
storageSetupDone(index
, false);
504 emit
storageSetupDone(index
, true);
508 void PlacesItemModel::onSourceModelRowsInserted(const QModelIndex
&parent
, int first
, int last
)
510 for (int i
= first
; i
<= last
; i
++) {
511 const QModelIndex index
= m_sourceModel
->index(i
, 0, parent
);
512 addItemFromSourceModel(index
);
516 void PlacesItemModel::onSourceModelRowsAboutToBeRemoved(const QModelIndex
&parent
, int first
, int last
)
518 for(int r
= first
; r
<= last
; r
++) {
519 const QModelIndex index
= m_sourceModel
->index(r
, 0, parent
);
520 int oldIndex
= mapFromSource(index
);
521 if (oldIndex
!= -1) {
522 removeItem(oldIndex
);
527 void PlacesItemModel::onSourceModelRowsAboutToBeMoved(const QModelIndex
&parent
, int start
, int end
, const QModelIndex
&destination
, int row
)
529 Q_UNUSED(destination
);
532 for(int r
= start
; r
<= end
; r
++) {
533 const QModelIndex sourceIndex
= m_sourceModel
->index(r
, 0, parent
);
535 removeItem(mapFromSource(sourceIndex
));
539 void PlacesItemModel::onSourceModelRowsMoved(const QModelIndex
&parent
, int start
, int end
, const QModelIndex
&destination
, int row
)
541 Q_UNUSED(destination
);
544 const int blockSize
= (end
- start
) + 1;
546 for (int r
= start
; r
<= end
; r
++) {
547 // insert the moved item in the new position
548 const int targetRow
= row
+ (start
- r
) - (r
< row
? blockSize
: 0);
549 const QModelIndex targetIndex
= m_sourceModel
->index(targetRow
, 0, destination
);
551 addItemFromSourceModel(targetIndex
);
555 void PlacesItemModel::onSourceModelDataChanged(const QModelIndex
&topLeft
, const QModelIndex
&bottomRight
, const QVector
<int> &roles
)
559 for (int r
= topLeft
.row(); r
<= bottomRight
.row(); r
++) {
560 const QModelIndex sourceIndex
= m_sourceModel
->index(r
, 0);
561 const KBookmark bookmark
= m_sourceModel
->bookmarkForIndex(sourceIndex
);
562 PlacesItem
*placeItem
= itemFromBookmark(bookmark
);
564 if (placeItem
&& (!m_hiddenItemsShown
&& m_sourceModel
->isHidden(sourceIndex
))) {
565 //hide item if it became invisible
566 removeItem(index(placeItem
));
570 if (!placeItem
&& (m_hiddenItemsShown
|| !m_sourceModel
->isHidden(sourceIndex
))) {
571 //show item if it became visible
572 addItemFromSourceModel(sourceIndex
);
576 if (placeItem
&& !m_sourceModel
->isDevice(sourceIndex
)) {
577 placeItem
->setText(bookmark
.text());
578 placeItem
->setIcon(sourceIndex
.data(KFilePlacesModel::IconNameRole
).toString());
579 placeItem
->setUrl(m_sourceModel
->url(sourceIndex
));
580 placeItem
->bookmark().setMetaDataItem(QStringLiteral("OnlyInApp"),
581 bookmark
.metaDataItem(QStringLiteral("OnlyInApp")));
582 // must update the bookmark object
583 placeItem
->setBookmark(bookmark
);
588 void PlacesItemModel::onSourceModelGroupHiddenChanged(KFilePlacesModel::GroupType group
, bool hidden
)
590 const auto groupIndexes
= m_sourceModel
->groupIndexes(group
);
591 for (const QModelIndex
&sourceIndex
: groupIndexes
) {
592 PlacesItem
*item
= placesItem(mapFromSource(sourceIndex
));
594 item
->setGroupHidden(hidden
);
599 void PlacesItemModel::cleanupBookmarks()
601 // KIO model now provides support for baloo urls, and because of that we
602 // need to remove old URLs that were visible only in Dolphin to avoid duplication
605 const QModelIndex sourceIndex
= m_sourceModel
->index(row
, 0);
606 const KBookmark bookmark
= m_sourceModel
->bookmarkForIndex(sourceIndex
);
607 const QUrl url
= bookmark
.url();
608 const QString appName
= bookmark
.metaDataItem(QStringLiteral("OnlyInApp"));
610 if ((appName
== KAboutData::applicationData().componentName() ||
611 appName
== KAboutData::applicationData().componentName() + DolphinPlacesModelSingleton::applicationNameSuffix()) && balooURLs
.contains(url
)) {
612 qCDebug(DolphinDebug
) << "Removing old baloo url:" << url
;
613 m_sourceModel
->removePlace(sourceIndex
);
617 } while (row
< m_sourceModel
->rowCount());
620 void PlacesItemModel::loadBookmarks()
622 for(int r
= 0, rMax
= m_sourceModel
->rowCount(); r
< rMax
; r
++) {
623 const QModelIndex sourceIndex
= m_sourceModel
->index(r
, 0);
624 if (m_hiddenItemsShown
|| !m_sourceModel
->isHidden(sourceIndex
)) {
625 addItemFromSourceModel(sourceIndex
);
630 void PlacesItemModel::clear() {
631 KStandardItemModel::clear();
634 void PlacesItemModel::proceedWithTearDown()
636 Q_ASSERT(m_deviceToTearDown
);
638 connect(m_deviceToTearDown
, &Solid::StorageAccess::teardownDone
,
639 this, &PlacesItemModel::slotStorageTearDownDone
);
640 m_deviceToTearDown
->teardown();
643 void PlacesItemModel::deleteItem(int index
)
645 QModelIndex sourceIndex
= mapToSource(index
);
646 Q_ASSERT(sourceIndex
.isValid());
647 m_sourceModel
->removePlace(sourceIndex
);
650 void PlacesItemModel::refresh()
652 m_sourceModel
->refresh();
655 void PlacesItemModel::hideItem(int index
)
657 PlacesItem
* shownItem
= placesItem(index
);
662 shownItem
->setHidden(true);
665 QString
PlacesItemModel::internalMimeType() const
667 return "application/x-dolphinplacesmodel-" +
668 QString::number((qptrdiff
)this);
671 int PlacesItemModel::groupedDropIndex(int index
, const PlacesItem
* item
) const
675 int dropIndex
= index
;
676 const QString group
= item
->group();
678 const int itemCount
= count();
680 dropIndex
= itemCount
;
683 // Search nearest previous item with the same group
684 int previousIndex
= -1;
685 for (int i
= dropIndex
- 1; i
>= 0; --i
) {
686 if (placesItem(i
)->group() == group
) {
692 // Search nearest next item with the same group
694 for (int i
= dropIndex
; i
< count(); ++i
) {
695 if (placesItem(i
)->group() == group
) {
701 // Adjust the drop-index to be inserted to the
702 // nearest item with the same group.
703 if (previousIndex
>= 0 && nextIndex
>= 0) {
704 dropIndex
= (dropIndex
- previousIndex
< nextIndex
- dropIndex
) ?
705 previousIndex
+ 1 : nextIndex
;
706 } else if (previousIndex
>= 0) {
707 dropIndex
= previousIndex
+ 1;
708 } else if (nextIndex
>= 0) {
709 dropIndex
= nextIndex
;
715 bool PlacesItemModel::equalBookmarkIdentifiers(const KBookmark
& b1
, const KBookmark
& b2
)
717 const QString udi1
= b1
.metaDataItem(QStringLiteral("UDI"));
718 const QString udi2
= b2
.metaDataItem(QStringLiteral("UDI"));
719 if (!udi1
.isEmpty() && !udi2
.isEmpty()) {
722 return b1
.metaDataItem(QStringLiteral("ID")) == b2
.metaDataItem(QStringLiteral("ID"));
726 int PlacesItemModel::mapFromSource(const QModelIndex
&index
) const
728 if (!index
.isValid()) {
732 return m_indexMap
.indexOf(index
);
735 bool PlacesItemModel::isDir(int index
) const
741 KFilePlacesModel::GroupType
PlacesItemModel::groupType(int row
) const
743 return m_sourceModel
->groupType(mapToSource(row
));
746 bool PlacesItemModel::isGroupHidden(KFilePlacesModel::GroupType type
) const
748 return m_sourceModel
->isGroupHidden(type
);
751 void PlacesItemModel::setGroupHidden(KFilePlacesModel::GroupType type
, bool hidden
)
753 return m_sourceModel
->setGroupHidden(type
, hidden
);
756 QModelIndex
PlacesItemModel::mapToSource(int row
) const
758 return m_indexMap
.value(row
);
761 PlacesItem
*PlacesItemModel::itemFromBookmark(const KBookmark
&bookmark
) const
763 const QString id
= bookmarkId(bookmark
);
764 for (int i
= 0, iMax
= count(); i
< iMax
; i
++) {
765 PlacesItem
*item
= placesItem(i
);
766 const KBookmark itemBookmark
= item
->bookmark();
767 if (bookmarkId(itemBookmark
) == id
) {