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"
25 #include "placesitemsignalhandler.h"
27 #include "dolphin_generalsettings.h"
30 #include <KBookmarkManager>
31 #include "dolphindebug.h"
33 #include <KProtocolInfo>
34 #include <KLocalizedString>
35 #include <QStandardPaths>
37 #include "placesitem.h"
42 #include <KUrlMimeData>
43 #include <KFilePlacesModel>
45 #include <Solid/Device>
46 #include <Solid/DeviceNotifier>
47 #include <Solid/OpticalDisc>
48 #include <Solid/OpticalDrive>
49 #include <Solid/StorageAccess>
50 #include <Solid/StorageDrive>
52 #include <views/dolphinview.h>
53 #include <views/viewproperties.h>
56 // Hence a prefix to the application-name of the stored bookmarks is
57 // added, which is only read by PlacesItemModel.
58 const char AppNamePrefix
[] = "-places-panel";
60 static QList
<QUrl
> balooURLs
= {
61 QUrl(QStringLiteral("timeline:/today")),
62 QUrl(QStringLiteral("timeline:/yesterday")),
63 QUrl(QStringLiteral("timeline:/thismonth")),
64 QUrl(QStringLiteral("timeline:/lastmonth")),
65 QUrl(QStringLiteral("search:/documents")),
66 QUrl(QStringLiteral("search:/images")),
67 QUrl(QStringLiteral("search:/audio")),
68 QUrl(QStringLiteral("search:/videos"))
72 PlacesItemModel::PlacesItemModel(QObject
* parent
) :
73 KStandardItemModel(parent
),
74 m_hiddenItemsShown(false),
75 m_deviceToTearDown(nullptr),
76 m_storageSetupInProgress(),
77 m_sourceModel(new KFilePlacesModel(this))
80 initializeDefaultViewProperties();
82 connect(m_sourceModel
.data(), &KFilePlacesModel::rowsInserted
, this, &PlacesItemModel::onSourceModelRowsInserted
);
83 connect(m_sourceModel
.data(), &KFilePlacesModel::rowsAboutToBeRemoved
, this, &PlacesItemModel::onSourceModelRowsAboutToBeRemoved
);
84 connect(m_sourceModel
.data(), &KFilePlacesModel::dataChanged
, this, &PlacesItemModel::onSourceModelDataChanged
);
85 connect(m_sourceModel
.data(), &KFilePlacesModel::rowsAboutToBeMoved
, this, &PlacesItemModel::onSourceModelRowsAboutToBeMoved
);
86 connect(m_sourceModel
.data(), &KFilePlacesModel::rowsMoved
, this, &PlacesItemModel::onSourceModelRowsMoved
);
87 connect(m_sourceModel
.data(), &KFilePlacesModel::groupHiddenChanged
, this, &PlacesItemModel::onSourceModelGroupHiddenChanged
);
90 PlacesItemModel::~PlacesItemModel()
94 void PlacesItemModel::createPlacesItem(const QString
& text
,
96 const QString
& iconName
,
99 m_sourceModel
->addPlace(text
, url
, iconName
, {}, mapToSource(after
));
102 PlacesItem
* PlacesItemModel::placesItem(int index
) const
104 return dynamic_cast<PlacesItem
*>(item(index
));
107 int PlacesItemModel::hiddenCount() const
109 return m_sourceModel
->hiddenCount();
112 void PlacesItemModel::setHiddenItemsShown(bool show
)
114 if (m_hiddenItemsShown
== show
) {
118 m_hiddenItemsShown
= show
;
121 for (int r
= 0, rMax
= m_sourceModel
->rowCount(); r
< rMax
; r
++) {
122 const QModelIndex index
= m_sourceModel
->index(r
, 0);
123 if (!m_sourceModel
->isHidden(index
)) {
126 addItemFromSourceModel(index
);
129 for (int r
= 0, rMax
= m_sourceModel
->rowCount(); r
< rMax
; r
++) {
130 const QModelIndex index
= m_sourceModel
->index(r
, 0);
131 if (m_sourceModel
->isHidden(index
)) {
132 removeItemByIndex(index
);
137 #ifdef PLACESITEMMODEL_DEBUG
138 qCDebug(DolphinDebug
) << "Changed visibility of hidden items";
143 bool PlacesItemModel::hiddenItemsShown() const
145 return m_hiddenItemsShown
;
148 int PlacesItemModel::closestItem(const QUrl
& url
) const
150 return mapFromSource(m_sourceModel
->closestItem(url
));
153 // look for the correct position for the item based on source model
154 void PlacesItemModel::insertSortedItem(PlacesItem
* item
)
160 const KBookmark iBookmark
= item
->bookmark();
161 const QString iBookmarkId
= bookmarkId(iBookmark
);
162 QModelIndex sourceIndex
;
165 for(int r
= 0, rMax
= m_sourceModel
->rowCount(); r
< rMax
; r
++) {
166 sourceIndex
= m_sourceModel
->index(r
, 0);
168 if (bookmarkId(m_sourceModel
->bookmarkForIndex(sourceIndex
)) == iBookmarkId
) {
172 if (!m_sourceModel
->isHidden(sourceIndex
)) {
177 m_indexMap
.insert(pos
, sourceIndex
);
178 insertItem(pos
, item
);
181 void PlacesItemModel::onItemInserted(int index
)
183 KStandardItemModel::onItemInserted(index
);
184 #ifdef PLACESITEMMODEL_DEBUG
185 qCDebug(DolphinDebug
) << "Inserted item" << index
;
190 void PlacesItemModel::onItemRemoved(int index
, KStandardItem
* removedItem
)
192 m_indexMap
.removeAt(index
);
194 KStandardItemModel::onItemRemoved(index
, removedItem
);
195 #ifdef PLACESITEMMODEL_DEBUG
196 qCDebug(DolphinDebug
) << "Removed item" << index
;
201 void PlacesItemModel::onItemChanged(int index
, const QSet
<QByteArray
>& changedRoles
)
203 const QModelIndex sourceIndex
= mapToSource(index
);
204 const PlacesItem
*changedItem
= placesItem(mapFromSource(sourceIndex
));
206 if (!changedItem
|| !sourceIndex
.isValid()) {
207 qWarning() << "invalid item changed signal";
210 if (changedRoles
.contains("isHidden")) {
211 if (m_sourceModel
->isHidden(sourceIndex
) != changedItem
->isHidden()) {
212 m_sourceModel
->setPlaceHidden(sourceIndex
, changedItem
->isHidden());
214 m_sourceModel
->refresh();
217 KStandardItemModel::onItemChanged(index
, changedRoles
);
220 QAction
* PlacesItemModel::ejectAction(int index
) const
222 const PlacesItem
* item
= placesItem(index
);
223 if (item
&& item
->device().is
<Solid::OpticalDisc
>()) {
224 return new QAction(QIcon::fromTheme(QStringLiteral("media-eject")), i18nc("@item", "Eject"), nullptr);
230 QAction
* PlacesItemModel::teardownAction(int index
) const
232 const PlacesItem
* item
= placesItem(index
);
237 Solid::Device device
= item
->device();
238 const bool providesTearDown
= device
.is
<Solid::StorageAccess
>() &&
239 device
.as
<Solid::StorageAccess
>()->isAccessible();
240 if (!providesTearDown
) {
244 Solid::StorageDrive
* drive
= device
.as
<Solid::StorageDrive
>();
246 drive
= device
.parent().as
<Solid::StorageDrive
>();
249 bool hotPluggable
= false;
250 bool removable
= false;
252 hotPluggable
= drive
->isHotpluggable();
253 removable
= drive
->isRemovable();
258 if (device
.is
<Solid::OpticalDisc
>()) {
259 text
= i18nc("@item", "Release");
260 } else if (removable
|| hotPluggable
) {
261 text
= i18nc("@item", "Safely Remove");
262 iconName
= QStringLiteral("media-eject");
264 text
= i18nc("@item", "Unmount");
265 iconName
= QStringLiteral("media-eject");
268 if (iconName
.isEmpty()) {
269 return new QAction(text
, nullptr);
272 return new QAction(QIcon::fromTheme(iconName
), text
, nullptr);
275 void PlacesItemModel::requestEject(int index
)
277 const PlacesItem
* item
= placesItem(index
);
279 Solid::OpticalDrive
* drive
= item
->device().parent().as
<Solid::OpticalDrive
>();
281 connect(drive
, &Solid::OpticalDrive::ejectDone
,
282 this, &PlacesItemModel::slotStorageTearDownDone
);
285 const QString label
= item
->text();
286 const QString message
= i18nc("@info", "The device '%1' is not a disk and cannot be ejected.", label
);
287 emit
errorMessage(message
);
292 void PlacesItemModel::requestTearDown(int index
)
294 const PlacesItem
* item
= placesItem(index
);
296 Solid::StorageAccess
*tmp
= item
->device().as
<Solid::StorageAccess
>();
298 m_deviceToTearDown
= tmp
;
299 // disconnect the Solid::StorageAccess::teardownRequested
300 // to prevent emitting PlacesItemModel::storageTearDownExternallyRequested
301 // after we have emitted PlacesItemModel::storageTearDownRequested
302 disconnect(tmp
, &Solid::StorageAccess::teardownRequested
,
303 item
->signalHandler(), &PlacesItemSignalHandler::onTearDownRequested
);
304 emit
storageTearDownRequested(tmp
->filePath());
309 bool PlacesItemModel::storageSetupNeeded(int index
) const
311 const PlacesItem
* item
= placesItem(index
);
312 return item
? item
->storageSetupNeeded() : false;
315 void PlacesItemModel::requestStorageSetup(int index
)
317 const PlacesItem
* item
= placesItem(index
);
322 Solid::Device device
= item
->device();
323 const bool setup
= device
.is
<Solid::StorageAccess
>()
324 && !m_storageSetupInProgress
.contains(device
.as
<Solid::StorageAccess
>())
325 && !device
.as
<Solid::StorageAccess
>()->isAccessible();
327 Solid::StorageAccess
* access
= device
.as
<Solid::StorageAccess
>();
329 m_storageSetupInProgress
[access
] = index
;
331 connect(access
, &Solid::StorageAccess::setupDone
,
332 this, &PlacesItemModel::slotStorageSetupDone
);
338 QMimeData
* PlacesItemModel::createMimeData(const KItemSet
& indexes
) const
343 QDataStream
stream(&itemData
, QIODevice::WriteOnly
);
345 for (int index
: indexes
) {
346 const QUrl itemUrl
= placesItem(index
)->url();
347 if (itemUrl
.isValid()) {
353 QMimeData
* mimeData
= new QMimeData();
354 if (!urls
.isEmpty()) {
355 mimeData
->setUrls(urls
);
357 // #378954: prevent itemDropEvent() drops if there isn't a source url.
358 mimeData
->setData(blacklistItemDropEventMimeType(), QByteArrayLiteral("true"));
360 mimeData
->setData(internalMimeType(), itemData
);
365 bool PlacesItemModel::supportsDropping(int index
) const
367 return index
>= 0 && index
< count();
370 void PlacesItemModel::dropMimeDataBefore(int index
, const QMimeData
* mimeData
)
372 if (mimeData
->hasFormat(internalMimeType())) {
373 // The item has been moved inside the view
374 QByteArray itemData
= mimeData
->data(internalMimeType());
375 QDataStream
stream(&itemData
, QIODevice::ReadOnly
);
379 m_sourceModel
->movePlace(oldIndex
, index
);
380 } else if (mimeData
->hasFormat(QStringLiteral("text/uri-list"))) {
381 // One or more items must be added to the model
382 const QList
<QUrl
> urls
= KUrlMimeData::urlsFromMimeData(mimeData
);
383 for (int i
= urls
.count() - 1; i
>= 0; --i
) {
384 const QUrl
& url
= urls
[i
];
386 QString text
= url
.fileName();
387 if (text
.isEmpty()) {
391 if ((url
.isLocalFile() && !QFileInfo(url
.toLocalFile()).isDir())
392 || url
.scheme() == QLatin1String("trash")) {
393 // Only directories outside the trash are allowed
397 createPlacesItem(text
, url
, KIO::iconNameForUrl(url
), qMax(0, index
- 1));
400 // will save bookmark alteration and fix sort if that is broken by the drag/drop operation
404 void PlacesItemModel::addItemFromSourceModel(const QModelIndex
&index
)
406 if (!m_hiddenItemsShown
&& m_sourceModel
->isHidden(index
)) {
410 const KBookmark bookmark
= m_sourceModel
->bookmarkForIndex(index
);
411 Q_ASSERT(!bookmark
.isNull());
412 PlacesItem
*item
= new PlacesItem(bookmark
);
413 updateItem(item
, index
);
414 insertSortedItem(item
);
416 if (m_sourceModel
->isDevice(index
)) {
417 connect(item
->signalHandler(), &PlacesItemSignalHandler::tearDownExternallyRequested
,
418 this, &PlacesItemModel::storageTearDownExternallyRequested
);
422 void PlacesItemModel::removeItemByIndex(const QModelIndex
&sourceIndex
)
424 QString id
= bookmarkId(m_sourceModel
->bookmarkForIndex(sourceIndex
));
426 for (int i
= 0, iMax
= count(); i
< iMax
; ++i
) {
427 if (bookmarkId(placesItem(i
)->bookmark()) == id
) {
434 QString
PlacesItemModel::bookmarkId(const KBookmark
&bookmark
) const
436 QString id
= bookmark
.metaDataItem(QStringLiteral("UDI"));
438 id
= bookmark
.metaDataItem(QStringLiteral("ID"));
443 void PlacesItemModel::initializeDefaultViewProperties() const
445 for(int i
= 0, iMax
= m_sourceModel
->rowCount(); i
< iMax
; i
++) {
446 const QModelIndex index
= m_sourceModel
->index(i
, 0);
447 const PlacesItem
*item
= placesItem(mapFromSource(index
));
452 // Create default view-properties for all "Search For" and "Recently Saved" bookmarks
453 // in case the user has not already created custom view-properties for a corresponding
455 const bool createDefaultViewProperties
= item
->isSearchOrTimelineUrl() && !GeneralSettings::self()->globalViewProps();
456 if (createDefaultViewProperties
) {
457 const QUrl itemUrl
= item
->url();
458 ViewProperties
props(KFilePlacesModel::convertedUrl(itemUrl
));
459 if (!props
.exist()) {
460 const QString path
= itemUrl
.path();
461 if (path
== QLatin1String("/documents")) {
462 props
.setViewMode(DolphinView::DetailsView
);
463 props
.setPreviewsShown(false);
464 props
.setVisibleRoles({"text", "path"});
465 } else if (path
== QLatin1String("/images")) {
466 props
.setViewMode(DolphinView::IconsView
);
467 props
.setPreviewsShown(true);
468 props
.setVisibleRoles({"text", "imageSize"});
469 } else if (path
== QLatin1String("/audio")) {
470 props
.setViewMode(DolphinView::DetailsView
);
471 props
.setPreviewsShown(false);
472 props
.setVisibleRoles({"text", "artist", "album"});
473 } else if (path
== QLatin1String("/videos")) {
474 props
.setViewMode(DolphinView::IconsView
);
475 props
.setPreviewsShown(true);
476 props
.setVisibleRoles({"text"});
477 } else if (itemUrl
.scheme() == QLatin1String("timeline")) {
478 props
.setViewMode(DolphinView::DetailsView
);
479 props
.setVisibleRoles({"text", "modificationtime"});
487 void PlacesItemModel::updateItem(PlacesItem
*item
, const QModelIndex
&index
)
489 item
->setGroup(index
.data(KFilePlacesModel::GroupRole
).toString());
490 item
->setIcon(index
.data(KFilePlacesModel::IconNameRole
).toString());
491 item
->setGroupHidden(index
.data(KFilePlacesModel::GroupHiddenRole
).toBool());
494 void PlacesItemModel::slotStorageTearDownDone(Solid::ErrorType error
, const QVariant
& errorData
)
496 if (error
&& errorData
.isValid()) {
497 emit
errorMessage(errorData
.toString());
499 m_deviceToTearDown
->disconnect();
500 m_deviceToTearDown
= nullptr;
503 void PlacesItemModel::slotStorageSetupDone(Solid::ErrorType error
,
504 const QVariant
& errorData
,
509 const int index
= m_storageSetupInProgress
.take(sender());
510 const PlacesItem
* item
= placesItem(index
);
515 if (error
!= Solid::NoError
) {
516 if (errorData
.isValid()) {
517 emit
errorMessage(i18nc("@info", "An error occurred while accessing '%1', the system responded: %2",
519 errorData
.toString()));
521 emit
errorMessage(i18nc("@info", "An error occurred while accessing '%1'",
524 emit
storageSetupDone(index
, false);
526 emit
storageSetupDone(index
, true);
530 void PlacesItemModel::onSourceModelRowsInserted(const QModelIndex
&parent
, int first
, int last
)
532 for (int i
= first
; i
<= last
; i
++) {
533 const QModelIndex index
= m_sourceModel
->index(i
, 0, parent
);
534 addItemFromSourceModel(index
);
538 void PlacesItemModel::onSourceModelRowsAboutToBeRemoved(const QModelIndex
&parent
, int first
, int last
)
540 for(int r
= first
; r
<= last
; r
++) {
541 const QModelIndex index
= m_sourceModel
->index(r
, 0, parent
);
542 int oldIndex
= mapFromSource(index
);
543 if (oldIndex
!= -1) {
544 removeItem(oldIndex
);
549 void PlacesItemModel::onSourceModelRowsAboutToBeMoved(const QModelIndex
&parent
, int start
, int end
, const QModelIndex
&destination
, int row
)
551 Q_UNUSED(destination
);
554 for(int r
= start
; r
<= end
; r
++) {
555 const QModelIndex sourceIndex
= m_sourceModel
->index(r
, 0, parent
);
557 removeItem(mapFromSource(sourceIndex
));
561 void PlacesItemModel::onSourceModelRowsMoved(const QModelIndex
&parent
, int start
, int end
, const QModelIndex
&destination
, int row
)
563 Q_UNUSED(destination
);
566 const int blockSize
= (end
- start
) + 1;
568 for (int r
= start
; r
<= end
; r
++) {
569 // insert the moved item in the new position
570 const int targetRow
= row
+ (start
- r
) - (r
< row
? blockSize
: 0);
571 const QModelIndex targetIndex
= m_sourceModel
->index(targetRow
, 0, destination
);
573 const KBookmark bookmark
= m_sourceModel
->bookmarkForIndex(targetIndex
);
574 PlacesItem
*item
= new PlacesItem(bookmark
);
575 updateItem(item
, targetIndex
);
577 insertSortedItem(item
);
581 void PlacesItemModel::onSourceModelDataChanged(const QModelIndex
&topLeft
, const QModelIndex
&bottomRight
, const QVector
<int> &roles
)
585 for (int r
= topLeft
.row(); r
<= bottomRight
.row(); r
++) {
586 const QModelIndex sourceIndex
= m_sourceModel
->index(r
, 0);
587 const KBookmark bookmark
= m_sourceModel
->bookmarkForIndex(sourceIndex
);
588 PlacesItem
*placeItem
= itemFromBookmark(bookmark
);
590 if (placeItem
&& (!m_hiddenItemsShown
&& m_sourceModel
->isHidden(sourceIndex
))) {
591 //hide item if it became invisible
592 removeItem(index(placeItem
));
596 if (!placeItem
&& (m_hiddenItemsShown
|| !m_sourceModel
->isHidden(sourceIndex
))) {
597 //show item if it became visible
598 addItemFromSourceModel(sourceIndex
);
602 if (placeItem
&& !m_sourceModel
->isDevice(sourceIndex
)) {
603 placeItem
->setText(bookmark
.text());
604 placeItem
->setIcon(sourceIndex
.data(KFilePlacesModel::IconNameRole
).toString());
605 placeItem
->setUrl(m_sourceModel
->url(sourceIndex
));
606 placeItem
->bookmark().setMetaDataItem(QStringLiteral("OnlyInApp"),
607 bookmark
.metaDataItem(QStringLiteral("OnlyInApp")));
612 void PlacesItemModel::onSourceModelGroupHiddenChanged(KFilePlacesModel::GroupType group
, bool hidden
)
614 for(const QModelIndex
&sourceIndex
: m_sourceModel
->groupIndexes(group
)) {
615 PlacesItem
*item
= placesItem(mapFromSource(sourceIndex
));
617 item
->setGroupHidden(hidden
);
622 void PlacesItemModel::loadBookmarks()
624 for(int r
= 0, rMax
= m_sourceModel
->rowCount(); r
< rMax
; r
++) {
625 const QModelIndex sourceIndex
= m_sourceModel
->index(r
, 0);
626 KBookmark bookmark
= m_sourceModel
->bookmarkForIndex(sourceIndex
);
627 if (acceptBookmark(bookmark
) &&
628 (m_hiddenItemsShown
|| !m_sourceModel
->isHidden(sourceIndex
))) {
629 addItemFromSourceModel(sourceIndex
);
633 #ifdef PLACESITEMMODEL_DEBUG
634 qCDebug(DolphinDebug
) << "Loaded bookmarks";
639 bool PlacesItemModel::acceptBookmark(const KBookmark
& bookmark
) const
641 const QString udi
= bookmark
.metaDataItem(QStringLiteral("UDI"));
642 const QUrl url
= bookmark
.url();
643 const QString appName
= bookmark
.metaDataItem(QStringLiteral("OnlyInApp"));
645 if (balooURLs
.contains(url
) && appName
.isEmpty()) {
646 // Does not accept baloo URLS with empty appName, this came from new KIO model and will cause duplications
647 qCWarning(DolphinDebug
) << "Ignore KIO url:" << url
;
650 const bool allowedHere
= (appName
.isEmpty()
651 || appName
== KAboutData::applicationData().componentName()
652 || appName
== KAboutData::applicationData().componentName() + AppNamePrefix
);
654 return (udi
.isEmpty() && allowedHere
);
657 void PlacesItemModel::clear() {
658 KStandardItemModel::clear();
661 void PlacesItemModel::proceedWithTearDown()
663 Q_ASSERT(m_deviceToTearDown
);
665 connect(m_deviceToTearDown
, &Solid::StorageAccess::teardownDone
,
666 this, &PlacesItemModel::slotStorageTearDownDone
);
667 m_deviceToTearDown
->teardown();
670 void PlacesItemModel::deleteItem(int index
)
672 QModelIndex sourceIndex
= mapToSource(index
);
673 Q_ASSERT(sourceIndex
.isValid());
674 m_sourceModel
->removePlace(sourceIndex
);
677 void PlacesItemModel::refresh()
679 m_sourceModel
->refresh();
682 void PlacesItemModel::hideItem(int index
)
684 PlacesItem
* shownItem
= placesItem(index
);
689 shownItem
->setHidden(true);
692 QString
PlacesItemModel::internalMimeType() const
694 return "application/x-dolphinplacesmodel-" +
695 QString::number((qptrdiff
)this);
698 int PlacesItemModel::groupedDropIndex(int index
, const PlacesItem
* item
) const
702 int dropIndex
= index
;
703 const QString group
= item
->group();
705 const int itemCount
= count();
707 dropIndex
= itemCount
;
710 // Search nearest previous item with the same group
711 int previousIndex
= -1;
712 for (int i
= dropIndex
- 1; i
>= 0; --i
) {
713 if (placesItem(i
)->group() == group
) {
719 // Search nearest next item with the same group
721 for (int i
= dropIndex
; i
< count(); ++i
) {
722 if (placesItem(i
)->group() == group
) {
728 // Adjust the drop-index to be inserted to the
729 // nearest item with the same group.
730 if (previousIndex
>= 0 && nextIndex
>= 0) {
731 dropIndex
= (dropIndex
- previousIndex
< nextIndex
- dropIndex
) ?
732 previousIndex
+ 1 : nextIndex
;
733 } else if (previousIndex
>= 0) {
734 dropIndex
= previousIndex
+ 1;
735 } else if (nextIndex
>= 0) {
736 dropIndex
= nextIndex
;
742 bool PlacesItemModel::equalBookmarkIdentifiers(const KBookmark
& b1
, const KBookmark
& b2
)
744 const QString udi1
= b1
.metaDataItem(QStringLiteral("UDI"));
745 const QString udi2
= b2
.metaDataItem(QStringLiteral("UDI"));
746 if (!udi1
.isEmpty() && !udi2
.isEmpty()) {
749 return b1
.metaDataItem(QStringLiteral("ID")) == b2
.metaDataItem(QStringLiteral("ID"));
753 int PlacesItemModel::mapFromSource(const QModelIndex
&index
) const
755 if (!index
.isValid()) {
759 return m_indexMap
.indexOf(index
);
762 bool PlacesItemModel::isDir(int index
) const
768 KFilePlacesModel::GroupType
PlacesItemModel::groupType(int row
) const
770 return m_sourceModel
->groupType(mapToSource(row
));
773 bool PlacesItemModel::isGroupHidden(KFilePlacesModel::GroupType type
) const
775 return m_sourceModel
->isGroupHidden(type
);
778 void PlacesItemModel::setGroupHidden(KFilePlacesModel::GroupType type
, bool hidden
)
780 return m_sourceModel
->setGroupHidden(type
, hidden
);
783 QModelIndex
PlacesItemModel::mapToSource(int row
) const
785 return m_indexMap
.value(row
);
788 PlacesItem
*PlacesItemModel::itemFromBookmark(const KBookmark
&bookmark
) const
790 const QString id
= bookmarkId(bookmark
);
791 for (int i
= 0, iMax
= count(); i
< iMax
; i
++) {
792 PlacesItem
*item
= placesItem(i
);
793 const KBookmark itemBookmark
= item
->bookmark();
794 if (bookmarkId(itemBookmark
) == id
) {
801 #ifdef PLACESITEMMODEL_DEBUG
802 void PlacesItemModel::showModelState()
804 qCDebug(DolphinDebug
) << "=================================";
805 qCDebug(DolphinDebug
) << "Model:";
806 qCDebug(DolphinDebug
) << "hidden-index model-index text";
808 for (int i
= 0; i
< m_bookmarkedItems
.count(); ++i
) {
809 if (m_bookmarkedItems
[i
]) {
810 qCDebug(DolphinDebug
) << i
<< "(Hidden) " << " " << m_bookmarkedItems
[i
]->dataValue("text").toString();
812 if (item(modelIndex
)) {
813 qCDebug(DolphinDebug
) << i
<< " " << modelIndex
<< " " << item(modelIndex
)->dataValue("text").toString();
815 qCDebug(DolphinDebug
) << i
<< " " << modelIndex
<< " " << "(not available yet)";
821 qCDebug(DolphinDebug
);
822 qCDebug(DolphinDebug
) << "Bookmarks:";
824 int bookmarkIndex
= 0;
825 KBookmarkGroup root
= m_bookmarkManager
->root();
826 KBookmark bookmark
= root
.first();
827 while (!bookmark
.isNull()) {
828 const QString udi
= bookmark
.metaDataItem("UDI");
829 const QString text
= udi
.isEmpty() ? bookmark
.text() : udi
;
830 if (bookmark
.metaDataItem("IsHidden") == QLatin1String("true")) {
831 qCDebug(DolphinDebug
) << bookmarkIndex
<< "(Hidden)" << text
;
833 qCDebug(DolphinDebug
) << bookmarkIndex
<< " " << text
;
836 bookmark
= root
.next(bookmark
);