X-Git-Url: https://cloud.milkyroute.net/gitweb/dolphin.git/blobdiff_plain/89158c6b3d29b9c01fe9dcc4c2b477dbc80abbdb..b4e80645e8e39ef7fcc1545136bad06ab3dd5f3e:/src/kitemviews/kfileitemmodel.h diff --git a/src/kitemviews/kfileitemmodel.h b/src/kitemviews/kfileitemmodel.h index 3266a49f9..13554d8c7 100644 --- a/src/kitemviews/kfileitemmodel.h +++ b/src/kitemviews/kfileitemmodel.h @@ -1,21 +1,8 @@ -/*************************************************************************** - * Copyright (C) 2011 by Peter Penz * - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * - * (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License for more details. * - * * - * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * - ***************************************************************************/ +/* + * SPDX-FileCopyrightText: 2011 Peter Penz + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ #ifndef KFILEITEMMODEL_H #define KFILEITEMMODEL_H @@ -25,6 +12,7 @@ #include "kitemviews/private/kfileitemmodelfilter.h" #include +#include #include #include @@ -33,9 +21,15 @@ #include -class KFileItemModelDirLister; +class KDirLister; + class QTimer; +namespace KIO +{ +class Job; +} + /** * @brief KItemModelBase implementation for KFileItems. * @@ -51,7 +45,7 @@ class DOLPHIN_EXPORT KFileItemModel : public KItemModelBase Q_OBJECT public: - explicit KFileItemModel(QObject* parent = nullptr); + explicit KFileItemModel(QObject *parent = nullptr); ~KFileItemModel() override; /** @@ -60,13 +54,13 @@ public: * indicate the current state of the loading process. The items * of the directory are added after the loading has been completed. */ - void loadDirectory(const QUrl& url); + void loadDirectory(const QUrl &url); /** * Throws away all currently loaded items and refreshes the directory * by reloading all items again. */ - void refreshDirectory(const QUrl& url); + void refreshDirectory(const QUrl &url); /** * @return Parent directory of the items that are shown. In case @@ -84,7 +78,7 @@ public: int count() const override; QHash data(int index) const override; - bool setData(int index, const QHash& values) override; + bool setData(int index, const QHash &values) override; /** * Sets a separate sorting with directories first (true) or a mixed @@ -93,6 +87,12 @@ public: void setSortDirectoriesFirst(bool dirsFirst); bool sortDirectoriesFirst() const; + /** + * Sets a separate sorting with hidden files and folders last (true) or not (false). + */ + void setSortHiddenLast(bool hiddenLast); + bool sortHiddenLast() const; + void setShowHiddenFiles(bool show); bool showHiddenFiles() const; @@ -103,15 +103,17 @@ public: void setShowDirectoriesOnly(bool enabled); bool showDirectoriesOnly() const; - QMimeData* createMimeData(const KItemSet& indexes) const override; + QMimeData *createMimeData(const KItemSet &indexes) const override; - int indexForKeyboardSearch(const QString& text, int startFromIndex = 0) const override; + int indexForKeyboardSearch(const QString &text, int startFromIndex = 0) const override; bool supportsDropping(int index) const override; - QString roleDescription(const QByteArray& role) const override; + bool canEnterOnHover(int index) const override; - QList > groups() const override; + QString roleDescription(const QByteArray &role) const override; + + QList> groups() const override; /** * @return The file-item for the index \a index. If the index is in a valid @@ -125,14 +127,14 @@ public: * URL is found KFileItem::isNull() will be true for the returned * file-item. The runtime complexity of this call is O(1). */ - KFileItem fileItem(const QUrl& url) const; + KFileItem fileItem(const QUrl &url) const; /** * @return The index for the file-item \a item. -1 is returned if no file-item * is found or if the file-item is null. The amortized runtime * complexity of this call is O(1). */ - int index(const KFileItem& item) const; + int index(const KFileItem &item) const; /** * @return The index for the URL \a url. -1 is returned if no file-item @@ -154,7 +156,7 @@ public: /** * Sets the roles that should be shown for each item. */ - void setRoles(const QSet& roles); + void setRoles(const QSet &roles); QSet roles() const; bool setExpanded(int index, bool expanded) override; @@ -169,27 +171,38 @@ public: * After calling loadDirectory() or refreshDirectory() the marked sub-directories * will be expanded step-by-step. */ - void restoreExpandedDirectories(const QSet& urls); + void restoreExpandedDirectories(const QSet &urls); /** * Expands all parent-directories of the item \a url. */ - void expandParentDirectories(const QUrl& url); + void expandParentDirectories(const QUrl &url); - void setNameFilter(const QString& nameFilter); + void setNameFilter(const QString &nameFilter); QString nameFilter() const; - void setMimeTypeFilters(const QStringList& filters); + void setMimeTypeFilters(const QStringList &filters); QStringList mimeTypeFilters() const; - struct RoleInfo - { QByteArray role; + void setExcludeMimeTypeFilter(const QStringList &filters); + QStringList excludeMimeTypeFilter() const; + + struct RoleInfo { + QByteArray role; QString translation; QString group; + QString tooltip; bool requiresBaloo; bool requiresIndexer; }; + /** + * @return Provides static information for a role that is supported + * by KFileItemModel. Some roles can only be determined if + * Baloo is enabled and/or the Baloo indexing is enabled. + */ + static RoleInfo roleInformation(const QByteArray &role); + /** * @return Provides static information for all available roles that * are supported by KFileItemModel. Some roles can only be @@ -198,7 +211,17 @@ public: */ static QList rolesInformation(); -signals: + /** + * @return Provides static information for all available grouping + * behaviors supported by KFileItemModel but not directly + * mapped to roles of KFileItemModel. + */ + static QList extraGroupingInformation(); + + /** set to true to hide application/x-trash files */ + void setShowTrashMime(bool show); + +Q_SIGNALS: /** * Is emitted if the loading of a directory has been started. It is * assured that a signal directoryLoadingCompleted() will be send after @@ -216,6 +239,11 @@ signals: */ void directoryLoadingCompleted(); + /** + * Is emitted when the model is being refreshed (F5 key press) + */ + void directoryRefreshing(); + /** * Is emitted after the loading of a directory has been canceled. */ @@ -238,77 +266,134 @@ signals: * Is emitted if an information message (e.g. "Connecting to host...") * should be shown. */ - void infoMessage(const QString& message); + void infoMessage(const QString &message); /** * Is emitted if an error message (e.g. "Unknown location") * should be shown. */ - void errorMessage(const QString& message); + void errorMessage(const QString &message, const int kioErrorCode); /** * Is emitted if a redirection from the current URL \a oldUrl * to the new URL \a newUrl has been done. */ - void directoryRedirection(const QUrl& oldUrl, const QUrl& newUrl); + void directoryRedirection(const QUrl &oldUrl, const QUrl &newUrl); /** * Is emitted when the URL passed by KFileItemModel::setUrl() represents a file. * In this case no signal errorMessage() will be emitted. */ - void urlIsFileError(const QUrl& url); + void urlIsFileError(const QUrl &url); + + /** + * It is emitted for files when they change and + * for dirs when files are added or removed. + */ + void fileItemsChanged(const KFileItemList &changedFileItems); + + /** + * It is emitted when the parent directory was removed. + */ + void currentDirectoryRemoved(); protected: void onGroupedSortingChanged(bool current) override; - void onSortRoleChanged(const QByteArray& current, const QByteArray& previous, bool resortItems = true) override; + void onSortRoleChanged(const QByteArray ¤t, const QByteArray &previous, bool resortItems = true) override; void onSortOrderChanged(Qt::SortOrder current, Qt::SortOrder previous) override; + void onGroupRoleChanged(const QByteArray ¤t, const QByteArray &previous, bool resortItems = true) override; + void onGroupOrderChanged(Qt::SortOrder current, Qt::SortOrder previous) override; -private slots: +private Q_SLOTS: /** - * Resorts all items dependent on the set sortRole(), sortOrder() - * and foldersFirst() settings. + * Resorts all items dependent on the set sortRole(), sortOrder(), + * groupRole(), groupOrder() and foldersFirst() settings. */ void resortAllItems(); void slotCompleted(); void slotCanceled(); - void slotItemsAdded(const QUrl& directoryUrl, const KFileItemList& items); - void slotItemsDeleted(const KFileItemList& items); - void slotRefreshItems(const QList >& items); + void slotItemsAdded(const QUrl &directoryUrl, const KFileItemList &items); + void slotItemsDeleted(const KFileItemList &items); + void slotRefreshItems(const QList> &items); void slotClear(); void slotSortingChoiceChanged(); + void slotListerError(KIO::Job *job); void dispatchPendingItemsToInsert(); private: enum RoleType { // User visible roles: - NoRole, NameRole, SizeRole, ModificationTimeRole, CreationTimeRole, AccessTimeRole, PermissionsRole, OwnerRole, - GroupRole, TypeRole, DestinationRole, PathRole, DeletionTimeRole, + NoRole, + NameRole, + SizeRole, + ModificationTimeRole, + CreationTimeRole, + AccessTimeRole, + PermissionsRole, + OwnerRole, + GroupRole, + TypeRole, + ExtensionRole, + DestinationRole, + PathRole, + DeletionTimeRole, // User visible roles available with Baloo: - CommentRole, TagsRole, RatingRole, WidthRole, HeightRole, ImageDateTimeRole, OrientationRole, - WordCountRole, TitleRole, LineCountRole, ArtistRole, GenreRole, AlbumRole, DurationRole, TrackRole, ReleaseYearRole, - BitrateRole, OriginUrlRole, + CommentRole, + TagsRole, + RatingRole, + DimensionsRole, + WidthRole, + HeightRole, + ImageDateTimeRole, + OrientationRole, + PublisherRole, + PageCountRole, + WordCountRole, + TitleRole, + AuthorRole, + LineCountRole, + ArtistRole, + GenreRole, + AlbumRole, + DurationRole, + TrackRole, + ReleaseYearRole, + BitrateRole, + OriginUrlRole, + AspectRatioRole, + FrameRateRole, // Non-visible roles: - IsDirRole, IsLinkRole, IsHiddenRole, IsExpandedRole, IsExpandableRole, ExpandedParentsCountRole, + IsDirRole, + IsLinkRole, + IsHiddenRole, + IsExpandedRole, + IsExpandableRole, + ExpandedParentsCountRole, // Mandatory last entry: RolesCount }; - struct ItemData - { + struct ItemData { KFileItem item; QHash values; - ItemData* parent; + ItemData *parent; }; - - enum RemoveItemsBehavior { - KeepItemData, - DeleteItemData + + struct ItemGroupInfo { + int comparable; + QString text; + + bool operator==(const ItemGroupInfo &other) const; + bool operator!=(const ItemGroupInfo &other) const; + bool operator<(const ItemGroupInfo &other) const; }; - void insertItems(QList& items); - void removeItems(const KItemRangeList& itemRanges, RemoveItemsBehavior behavior); + enum RemoveItemsBehavior { KeepItemData, DeleteItemData, DeleteItemDataIfUnfiltered }; + + void insertItems(QList &items); + void removeItems(const KItemRangeList &itemRanges, RemoveItemsBehavior behavior); /** * Helper method for insertItems() and removeItems(): Creates @@ -316,16 +401,22 @@ private: * Note that the ItemData instances are created dynamically and * must be deleted by the caller. */ - QList createItemDataList(const QUrl& parentUrl, const KFileItemList& items) const; + QList createItemDataList(const QUrl &parentUrl, const KFileItemList &items) const; + + /** + * Helper method for prepareItemsForSorting(). + * For a set role, fills 'values' of ItemData non-lazily. + */ + void prepareItemsWithRole(QList &itemDataList, RoleType roleType); /** * Prepares the items for sorting. Normally, the hash 'values' in ItemData is filled * lazily to save time and memory, but for some sort roles, it is expected that the * sort role data is stored in 'values'. */ - void prepareItemsForSorting(QList& itemDataList); + void prepareItemsForSorting(QList &itemDataList); - static int expandedParentsCount(const ItemData* data); + static int expandedParentsCount(const ItemData *data); void removeExpandedItems(); @@ -334,7 +425,7 @@ private: * the itemsChanged() signal, checks if the sort order is still correct, * and starts m_resortAllItemsTimer if that is not the case. */ - void emitItemsChangedAndTriggerResorting(const KItemRangeList& itemRanges, const QSet& changedRoles); + void emitItemsChangedAndTriggerResorting(const KItemRangeList &itemRanges, const QSet &changedRoles); /** * Resets all values from m_requestRole to false. @@ -345,7 +436,7 @@ private: * @return Role-type for the given role. * Runtime complexity is O(1). */ - RoleType typeForRole(const QByteArray& role) const; + RoleType typeForRole(const QByteArray &role) const; /** * @return Role-byte-array for the given role-type. @@ -353,43 +444,62 @@ private: */ QByteArray roleForType(RoleType roleType) const; - QHash retrieveData(const KFileItem& item, const ItemData* parent) const; + QHash retrieveData(const KFileItem &item, const ItemData *parent) const; + + /** + * @return True if role values benefit from natural or case insensitive sorting. + */ + static bool isRoleValueNatural(const RoleType roleType); /** * @return True if \a a has a KFileItem whose text is 'less than' the one * of \a b according to QString::operator<(const QString&). */ - static bool nameLessThan(const ItemData* a, const ItemData* b); + static bool nameLessThan(const ItemData *a, const ItemData *b); /** * @return True if the item-data \a a should be ordered before the item-data * \b. The item-data may have different parent-items. */ - bool lessThan(const ItemData* a, const ItemData* b, const QCollator& collator) const; + bool lessThan(const ItemData *a, const ItemData *b, const QCollator &collator) const; /** * Sorts the items between \a begin and \a end using the comparison * function lessThan(). */ - void sort(QList::iterator begin, QList::iterator end) const; + void sort(const QList::iterator &begin, const QList::iterator &end) const; /** * Helper method for lessThan() and expandedParentsCountCompare(): Compares * the passed item-data using m_sortRole as criteria. Both items must * have the same parent item, otherwise the comparison will be wrong. */ - int sortRoleCompare(const ItemData* a, const ItemData* b, const QCollator& collator) const; + int sortRoleCompare(const ItemData *a, const ItemData *b, const QCollator &collator) const; + + /** + * Helper method for lessThan() and expandedParentsCountCompare(): Compares + * the passed item-data using m_groupRole as criteria. Both items must + * have the same parent item, otherwise the comparison will be wrong. + */ + int groupRoleCompare(const ItemData *a, const ItemData *b, const QCollator &collator) const; - int stringCompare(const QString& a, const QString& b, const QCollator& collator) const; + int stringCompare(const QString &a, const QString &b, const QCollator &collator) const; - bool useMaximumUpdateInterval() const; + ItemGroupInfo nameRoleGroup(const ItemData *itemData, bool withString = true) const; + ItemGroupInfo sizeRoleGroup(const ItemData *itemData, bool withString = true) const; + ItemGroupInfo timeRoleGroup(const std::function &fileTimeCb, const ItemData *itemData, bool withString = true) const; + ItemGroupInfo permissionRoleGroup(const ItemData *itemData, bool withString = true) const; + ItemGroupInfo ratingRoleGroup(const ItemData *itemData, bool withString = true) const; + ItemGroupInfo typeRoleGroup(const ItemData *itemData) const; + ItemGroupInfo genericStringRoleGroup(const QByteArray &role, const ItemData *itemData) const; - QList > nameRoleGroups() const; - QList > sizeRoleGroups() const; - QList > timeRoleGroups(std::function fileTimeCb) const; - QList > permissionRoleGroups() const; - QList > ratingRoleGroups() const; - QList > genericStringRoleGroups(const QByteArray& typeForRole) const; + QList> nameRoleGroups() const; + QList> sizeRoleGroups() const; + QList> timeRoleGroups(const std::function &fileTimeCb) const; + QList> permissionRoleGroups() const; + QList> ratingRoleGroups() const; + QList> typeRoleGroups() const; + QList> genericStringRoleGroups(const QByteArray &typeForRole) const; /** * Helper method for all xxxRoleGroups() methods to check whether the @@ -401,6 +511,8 @@ private: */ bool isChildItem(int index) const; + void scheduleResortAllItems(); + /** * Is invoked by KFileItemModelRolesUpdater and results in emitting the * sortProgress signal with a percent-value of the progress. @@ -416,7 +528,7 @@ private: * Removes filtered items whose expanded parents have been deleted * or collapsed via setExpanded(parentIndex, false). */ - void removeFilteredChildren(const KItemRangeList& parents); + void removeFilteredChildren(const KItemRangeList &parents); /** * Loads the selected choice of sorting method from Dolphin General Settings @@ -427,14 +539,12 @@ private: * Maps the QByteArray-roles to RoleTypes and provides translation- and * group-contexts. */ - struct RoleInfoMap - { - const char* const role; + struct RoleInfoMap { + const char *const role; const RoleType roleType; - const char* const roleTranslationContext; - const char* const roleTranslation; - const char* const groupTranslationContext; - const char* const groupTranslation; + const KLazyLocalizedString roleTranslation; + const KLazyLocalizedString groupTranslation; + const KLazyLocalizedString tooltipTranslation; const bool requiresBaloo; const bool requiresIndexer; }; @@ -442,37 +552,51 @@ private: /** * @return Map of user visible roles that are accessible by KFileItemModel::rolesInformation(). */ - static const RoleInfoMap* rolesInfoMap(int& count); + static const RoleInfoMap *rolesInfoMap(int &count); /** * Determines the MIME-types of all items that can be done within * the given timeout. */ - static void determineMimeTypes(const KFileItemList& items, int timeout); + static void determineMimeTypes(const KFileItemList &items, int timeout); /** * @return Returns a copy of \a value that is implicitly shared * with other users to save memory. */ - static QByteArray sharedValue(const QByteArray& value); + static QByteArray sharedValue(const QByteArray &value); /** * Checks if the model's internal data structures are consistent. */ bool isConsistent() const; + /** + * Filters out the expanded folders that don't pass the filter themselves and don't have any filter-passing children. + * Will update the removedItemRanges arguments to include the parents that have been filtered. + * @returns the number of parents that have been filtered. + * @param removedItemRanges The ranges of items being deleted/filtered, will get updated + * @param parentsToEnsureVisible Parents that must be visible no matter what due to being ancestors of newly visible items + */ + int filterChildlessParents(KItemRangeList &removedItemRanges, const QSet &parentsToEnsureVisible = QSet()); + private: - KFileItemModelDirLister* m_dirLister; + KDirLister *m_dirLister = nullptr; QCollator m_collator; bool m_naturalSorting; bool m_sortDirsFirst; + bool m_sortHiddenLast; RoleType m_sortRole; + RoleType m_groupRole; + QByteArray m_sortExtraInfo; + QByteArray m_groupExtraInfo; + int m_sortingProgressPercent; // Value of directorySortingProgress() signal QSet m_roles; - QList m_itemData; + QList m_itemData; // m_items is a cache for the method index(const QUrl&). If it contains N // entries, it is guaranteed that these correspond to the first N items in @@ -481,16 +605,16 @@ private: mutable QHash m_items; KFileItemModelFilter m_filter; - QHash m_filteredItems; // Items that got hidden by KFileItemModel::setNameFilter() + QHash m_filteredItems; // Items that got hidden by KFileItemModel::setNameFilter() bool m_requestRole[RolesCount]; - QTimer* m_maximumUpdateIntervalTimer; - QTimer* m_resortAllItemsTimer; - QList m_pendingItemsToInsert; + QTimer *m_maximumUpdateIntervalTimer; + QTimer *m_resortAllItemsTimer; + QList m_pendingItemsToInsert; // Cache for KFileItemModel::groups() - mutable QList > m_groups; + mutable QList> m_groups; // Stores the URLs (key: target url, value: url) of the expanded directories. QHash m_expandedDirs; @@ -499,18 +623,26 @@ private: // and done step after step in slotCompleted(). QSet m_urlsToExpand; - friend class KFileItemModelRolesUpdater; // Accesses emitSortProgress() method - friend class KFileItemModelTest; // For unit testing - friend class KFileItemModelBenchmark; // For unit testing - friend class KFileItemListViewTest; // For unit testing - friend class DolphinPart; // Accesses m_dirLister + friend class KFileItemModelRolesUpdater; // Accesses emitSortProgress() method + friend class KFileItemModelTest; // For unit testing + friend class KFileItemModelBenchmark; // For unit testing + friend class KFileItemListViewTest; // For unit testing + friend class DolphinPart; // Accesses m_dirLister }; -inline bool KFileItemModel::nameLessThan(const ItemData* a, const ItemData* b) +inline bool KFileItemModel::isRoleValueNatural(RoleType roleType) { - return a->item.text() < b->item.text(); + return (roleType == TypeRole || roleType == ExtensionRole || roleType == TagsRole || roleType == CommentRole || roleType == TitleRole + || roleType == ArtistRole || roleType == GenreRole || roleType == AlbumRole || roleType == PathRole || roleType == DestinationRole + || roleType == OriginUrlRole || roleType == OwnerRole || roleType == GroupRole); } +inline bool KFileItemModel::nameLessThan(const ItemData *a, const ItemData *b) +{ + // Split extension, taking into account it can be empty + constexpr QString::SectionFlags flags = QString::SectionSkipEmpty | QString::SectionIncludeLeadingSep; + return a->item.text().section('.', 0, 0, flags) < b->item.text().section('.', 0, 0, flags); +} inline bool KFileItemModel::isChildItem(int index) const { @@ -521,6 +653,14 @@ inline bool KFileItemModel::isChildItem(int index) const } } -#endif +inline bool KFileItemModel::ItemGroupInfo::operator==(const ItemGroupInfo &other) const +{ + return comparable == other.comparable && text == other.text; +} +inline bool KFileItemModel::ItemGroupInfo::operator!=(const ItemGroupInfo &other) const +{ + return comparable != other.comparable || text != other.text; +} +#endif