File indexing completed on 2024-12-01 03:40:53

0001 /*
0002     This file is part of the KDE project
0003     SPDX-FileCopyrightText: 2007 Kevin Ottens <ervin@kde.org>
0004     SPDX-FileCopyrightText: 2007 David Faure <faure@kde.org>
0005     SPDX-FileCopyrightText: 2023 Harald Sitter <sitter@kde.org>
0006 
0007     SPDX-License-Identifier: LGPL-2.0-only
0008 */
0009 
0010 #ifndef KFILEPLACESMODEL_H
0011 #define KFILEPLACESMODEL_H
0012 
0013 #include "kiofilewidgets_export.h"
0014 
0015 #include <KBookmark>
0016 #include <QAbstractItemModel>
0017 #include <QUrl>
0018 
0019 #include <solid/device.h>
0020 #include <solid/solidnamespace.h>
0021 
0022 #include <memory>
0023 
0024 class KFilePlacesModelPrivate;
0025 class KBookmarkManager;
0026 
0027 class QMimeData;
0028 class QAction;
0029 
0030 /**
0031  * @class KFilePlacesModel kfileplacesmodel.h <KFilePlacesModel>
0032  *
0033  * This class is a list view model. Each entry represents a "place"
0034  * where user can access files. Only relevant when
0035  * used with QListView or QTableView.
0036  * @note This class is since 6.0 re-entrant
0037  */
0038 class KIOFILEWIDGETS_EXPORT KFilePlacesModel : public QAbstractItemModel
0039 {
0040     Q_OBJECT
0041 
0042     Q_PROPERTY(QStringList supportedSchemes READ supportedSchemes WRITE setSupportedSchemes NOTIFY supportedSchemesChanged)
0043 
0044 public:
0045     // Note: run   printf "0x%08X\n" $(($RANDOM*$RANDOM))
0046     // to define additional roles.
0047     enum AdditionalRoles {
0048         /** roleName is "url". @see url() */
0049         UrlRole = 0x069CD12B,
0050 
0051         /** roleName is "isHidden". @see isHidden() */
0052         HiddenRole = 0x0741CAAC,
0053 
0054         /** roleName is "isSetupNeeded". @see setupNeeded() */
0055         SetupNeededRole = 0x059A935D,
0056 
0057         /**
0058          * Whether the place is a fixed device (neither hotpluggable nor removable).
0059          * roleName is "isFixedDevice".
0060          */
0061         FixedDeviceRole = 0x332896C1,
0062 
0063         /**
0064          * Whether the place should have its free space displayed in a capacity bar.
0065          * roleName is "isCapacityBarRecommended".
0066          */
0067         CapacityBarRecommendedRole = 0x1548C5C4,
0068 
0069         /**
0070          * The name of the group, for example "Remote" or "Devices". roleName is "group".
0071          * @since 5.40
0072          */
0073         GroupRole = 0x0a5b64ee,
0074 
0075         /**
0076          * roleName is "iconName".
0077          * @see icon()
0078          * @since 5.41
0079          */
0080         IconNameRole = 0x00a45c00,
0081 
0082         /** roleName is "isGroupHidden".
0083          * @see isGroupHidden()
0084          * @since 5.42
0085          */
0086         GroupHiddenRole = 0x21a4b936,
0087 
0088         /** roleName is "isTeardownAllowed".
0089          * @see isTeardownAllowed().
0090          * @since 5.91
0091          */
0092         TeardownAllowedRole = 0x02533364,
0093 
0094         /** roleName is "isEjectAllowed".
0095          * @since 5.94.
0096          */
0097         EjectAllowedRole = 0x0A16AC5B,
0098 
0099         /**
0100          * roleName is "isTeardownOverlayRecommended".
0101          * @see isTeardownOverlayRecommended()
0102          * @since 5.95
0103          */
0104         TeardownOverlayRecommendedRole = 0x032EDCCE,
0105 
0106         /**
0107          * roleName is "deviceAccessibility".
0108          * @see deviceAccessibility()
0109          * @since 5.99
0110          */
0111         DeviceAccessibilityRole = 0x023FFD93,
0112     };
0113 
0114     /**
0115      * Describes the available group types used in this model.
0116      * @since 5.42
0117      */
0118     enum GroupType {
0119         PlacesType, ///< "Places" section
0120         RemoteType, ///< "Remote" section
0121         RecentlySavedType, ///< "Recent" section
0122         SearchForType, ///< "Search for" section
0123         DevicesType, ///< "Devices" section
0124         RemovableDevicesType, ///< "Removable Devices" section
0125         UnknownType, ///< Unknown GroupType
0126         TagsType, ///< "Tags" section. @since 5.54
0127     };
0128     Q_ENUM(GroupType)
0129 
0130     enum DeviceAccessibility { SetupNeeded, SetupInProgress, Accessible, TeardownInProgress };
0131     Q_ENUM(DeviceAccessibility)
0132 
0133     explicit KFilePlacesModel(QObject *parent = nullptr);
0134     ~KFilePlacesModel() override;
0135 
0136     /**
0137      * @return The URL of the place at index @p index.
0138      */
0139     Q_INVOKABLE QUrl url(const QModelIndex &index) const;
0140 
0141     /**
0142      * @return Whether the place at index @p index needs to be mounted before it can be used.
0143      */
0144     Q_INVOKABLE bool setupNeeded(const QModelIndex &index) const;
0145 
0146     /**
0147      * @return Whether the place is a device that can be unmounted, e.g. it is
0148      * mounted but does not point at system Root or the user's Home directory.
0149      *
0150      * It does not indicate whether the teardown can succeed.
0151      * @since 5.91
0152      */
0153     Q_INVOKABLE bool isTeardownAllowed(const QModelIndex &index) const;
0154 
0155     /**
0156      * @return Whether the place is a device that can be ejected, e.g. it is
0157      * a CD, DVD, etc.
0158      *
0159      * It does not indicate whether the eject can succeed.
0160      * @since 5.94
0161      */
0162     Q_INVOKABLE bool isEjectAllowed(const QModelIndex &index) const;
0163 
0164     /**
0165      * @return Whether showing an inline teardown button is recommended,
0166      * e.g. when it is a removable drive.
0167      *
0168      * @since 5.95
0169      **/
0170     Q_INVOKABLE bool isTeardownOverlayRecommended(const QModelIndex &index) const;
0171 
0172     /**
0173      * @return Whether this device is currently accessible or being (un)mounted.
0174      *
0175      * @since 5.99
0176      */
0177     Q_INVOKABLE KFilePlacesModel::DeviceAccessibility deviceAccessibility(const QModelIndex &index) const;
0178 
0179     /**
0180      * @return The icon of the place at index @p index.
0181      */
0182     Q_INVOKABLE QIcon icon(const QModelIndex &index) const;
0183 
0184     /**
0185      * @return The user-visible text of the place at index @p index.
0186      */
0187     Q_INVOKABLE QString text(const QModelIndex &index) const;
0188 
0189     /**
0190      * @return Whether the place at index @p index is hidden or is inside an hidden group.
0191      */
0192     Q_INVOKABLE bool isHidden(const QModelIndex &index) const;
0193 
0194     /**
0195      * @return Whether the group type @p type is hidden.
0196      * @since 5.42
0197      */
0198     Q_INVOKABLE bool isGroupHidden(const GroupType type) const;
0199 
0200     /**
0201      * @return Whether the group of the place at index @p index is hidden.
0202      * @since 5.42
0203      */
0204     Q_INVOKABLE bool isGroupHidden(const QModelIndex &index) const;
0205 
0206     /**
0207      * @return Whether the place at index @p index is a device handled by Solid.
0208      * @see deviceForIndex()
0209      */
0210     Q_INVOKABLE bool isDevice(const QModelIndex &index) const;
0211 
0212     /**
0213      * @return The solid device of the place at index @p index, if it is a device. Otherwise a default Solid::Device() instance is returned.
0214      * @see isDevice()
0215      */
0216     Solid::Device deviceForIndex(const QModelIndex &index) const;
0217 
0218     /**
0219      * @return The KBookmark instance of the place at index @p index.
0220      * If the index is not valid, a default KBookmark instance is returned.
0221      */
0222     KBookmark bookmarkForIndex(const QModelIndex &index) const;
0223 
0224     /**
0225      * @return The KBookmark instance of the place with url @p searchUrl.
0226      * If the bookmark corresponding to searchUrl is not found, a default KBookmark instance is returned.
0227      * @since 5.63
0228      */
0229     KBookmark bookmarkForUrl(const QUrl &searchUrl) const;
0230 
0231     /**
0232      * @return The group type of the place at index @p index.
0233      * @since 5.42
0234      */
0235     Q_INVOKABLE GroupType groupType(const QModelIndex &index) const;
0236 
0237     /**
0238      * @return The list of model indexes that have @ type as their group type.
0239      * @see groupType()
0240      * @since 5.42
0241      */
0242     Q_INVOKABLE QModelIndexList groupIndexes(const GroupType type) const;
0243 
0244     /**
0245      * @return A QAction with a proper translated label that can be used to trigger the requestTeardown()
0246      * method for the place at index @p index.
0247      * @see requestTeardown()
0248      */
0249     Q_INVOKABLE QAction *teardownActionForIndex(const QModelIndex &index) const;
0250 
0251     /**
0252      * @return A QAction with a proper translated label that can be used to trigger the requestEject()
0253      * method for the place at index @p index.
0254      * @see requestEject()
0255      */
0256     Q_INVOKABLE QAction *ejectActionForIndex(const QModelIndex &index) const;
0257 
0258     /**
0259      * @return A QAction with a proper translated label that can be used to open a partitioning menu for the device. nullptr if not a device.
0260      */
0261     Q_INVOKABLE QAction *partitionActionForIndex(const QModelIndex &index) const;
0262 
0263     /**
0264      * Unmounts the place at index @p index by triggering the teardown functionality of its Solid device.
0265      * @see deviceForIndex()
0266      */
0267     Q_INVOKABLE void requestTeardown(const QModelIndex &index);
0268 
0269     /**
0270      * Ejects the place at index @p index by triggering the eject functionality of its Solid device.
0271      * @see deviceForIndex()
0272      */
0273     Q_INVOKABLE void requestEject(const QModelIndex &index);
0274 
0275     /**
0276      * Mounts the place at index @p index by triggering the setup functionality of its Solid device.
0277      * @see deviceForIndex()
0278      */
0279     Q_INVOKABLE void requestSetup(const QModelIndex &index);
0280 
0281     /**
0282      * Adds a new place to the model.
0283      * @param text The user-visible text for the place
0284      * @param url The URL of the place. It will be stored in its QUrl::FullyEncoded string format.
0285      * @param iconName The icon of the place
0286      * @param appName If set as the value of QCoreApplication::applicationName(), will make the place visible only in this application.
0287      */
0288     Q_INVOKABLE void addPlace(const QString &text, const QUrl &url, const QString &iconName = QString(), const QString &appName = QString());
0289 
0290     /**
0291      * Adds a new place to the model.
0292      * @param text The user-visible text for the place
0293      * @param url The URL of the place. It will be stored in its QUrl::FullyEncoded string format.
0294      * @param iconName The icon of the place
0295      * @param appName If set as the value of QCoreApplication::applicationName(), will make the place visible only in this application.
0296      * @param after The index after which the new place will be added.
0297      */
0298     Q_INVOKABLE void addPlace(const QString &text, const QUrl &url, const QString &iconName, const QString &appName, const QModelIndex &after);
0299 
0300     /**
0301      * Edits the place with index @p index.
0302      * @param text The new user-visible text for the place
0303      * @param url The new URL of the place
0304      * @param iconName The new icon of the place
0305      * @param appName The new application-local filter for the place (@see addPlace()).
0306      */
0307     Q_INVOKABLE void
0308     editPlace(const QModelIndex &index, const QString &text, const QUrl &url, const QString &iconName = QString(), const QString &appName = QString());
0309 
0310     /**
0311      * Deletes the place with index @p index from the model.
0312      */
0313     Q_INVOKABLE void removePlace(const QModelIndex &index) const;
0314 
0315     /**
0316      * Changes the visibility of the place with index @p index, but only if the place is not inside an hidden group.
0317      * @param hidden Whether the place should be hidden or visible.
0318      * @see isGroupHidden()
0319      */
0320     Q_INVOKABLE void setPlaceHidden(const QModelIndex &index, bool hidden);
0321 
0322     /**
0323      * Changes the visibility of the group with type @p type.
0324      * @param hidden Whether the group should be hidden or visible.
0325      * @see isGroupHidden()
0326      * @since 5.42
0327      */
0328     Q_INVOKABLE void setGroupHidden(const GroupType type, bool hidden);
0329 
0330     /**
0331      * @brief Move place at @p itemRow to a position before @p row
0332      * @return Whether the place has been moved.
0333      * @since 5.41
0334      */
0335     Q_INVOKABLE bool movePlace(int itemRow, int row);
0336 
0337     /**
0338      * @return The number of hidden places in the model.
0339      * @see isHidden()
0340      */
0341     Q_INVOKABLE int hiddenCount() const;
0342 
0343     /**
0344      * @brief Get a visible data based on Qt role for the given index.
0345      * Return the device information for the give index.
0346      *
0347      * @param index The QModelIndex which contains the row, column to fetch the data.
0348      * @param role The Interview data role(ex: Qt::DisplayRole).
0349      *
0350      * @return the data for the given index and role.
0351      */
0352     QVariant data(const QModelIndex &index, int role) const override;
0353 
0354     /**
0355      * @brief Get the children model index for the given row and column.
0356      */
0357     QModelIndex index(int row, int column, const QModelIndex &parent = QModelIndex()) const override;
0358 
0359     /**
0360      * @brief Get the parent QModelIndex for the given model child.
0361      */
0362     QModelIndex parent(const QModelIndex &child) const override;
0363 
0364     /// Reimplemented from QAbstractItemModel.
0365     /// @see AdditionalRoles
0366     QHash<int, QByteArray> roleNames() const override;
0367 
0368     /**
0369      * @brief Get the number of rows for a model index.
0370      */
0371     int rowCount(const QModelIndex &parent = QModelIndex()) const override;
0372 
0373     /**
0374      * @brief Get the number of columns for a model index.
0375      */
0376     int columnCount(const QModelIndex &parent = QModelIndex()) const override;
0377 
0378     /**
0379      * Returns the closest item for the URL \a url.
0380      * The closest item is defined as item which is equal to
0381      * the URL or at least is a parent URL. If there are more than
0382      * one possible parent URL candidates, the item which covers
0383      * the bigger range of the URL is returned.
0384      *
0385      * Example: the url is '/home/peter/Documents/Music'.
0386      * Available items are:
0387      * - /home/peter
0388      * - /home/peter/Documents
0389      *
0390      * The returned item will the one for '/home/peter/Documents'.
0391      */
0392     QModelIndex closestItem(const QUrl &url) const;
0393 
0394     Qt::DropActions supportedDropActions() const override;
0395     Qt::ItemFlags flags(const QModelIndex &index) const override;
0396     QStringList mimeTypes() const override;
0397     QMimeData *mimeData(const QModelIndexList &indexes) const override;
0398     bool dropMimeData(const QMimeData *data, Qt::DropAction action, int row, int column, const QModelIndex &parent) override;
0399 
0400     /**
0401      * @brief Reload bookmark information
0402      * @since 5.41
0403      */
0404     Q_INVOKABLE void refresh() const;
0405 
0406     /**
0407      * @brief  Converts the URL, which contains "virtual" URLs for system-items like
0408      *         "timeline:/lastmonth" into a Query-URL "timeline:/2017-10"
0409      *         that will be handled by the corresponding KIO worker.
0410      *         Virtual URLs for bookmarks are used to be independent from
0411      *         internal format changes.
0412      * @param an url
0413      * @return the converted URL, which can be handled by a KIO worker
0414      * @since 5.41
0415      */
0416     static QUrl convertedUrl(const QUrl &url);
0417 
0418     /**
0419      * Set the URL schemes that the file widget should allow navigating to.
0420      *
0421      * If the returned list is empty, all schemes are supported. Examples for
0422      * schemes are @c "file" or @c "ftp".
0423      *
0424      * @sa QFileDialog::setSupportedSchemes
0425      * @since 5.43
0426      */
0427     void setSupportedSchemes(const QStringList &schemes);
0428 
0429     /**
0430      * Returns the URL schemes that the file widget should allow navigating to.
0431      *
0432      * If the returned list is empty, all schemes are supported.
0433      *
0434      * @sa QFileDialog::supportedSchemes
0435      * @since 5.43
0436      */
0437     QStringList supportedSchemes() const;
0438 
0439 Q_SIGNALS:
0440     /**
0441      * @p message An error message explaining what went wrong.
0442      */
0443     void errorMessage(const QString &message);
0444 
0445     /**
0446      * Emitted after the Solid setup ends.
0447      * @param success Whether the Solid setup has been successful.
0448      * @see requestSetup()
0449      */
0450     void setupDone(const QModelIndex &index, bool success);
0451 
0452     /**
0453      * Emitted after the teardown of a device ends.
0454      *
0455      * @note In case of an error, the @p errorMessage signal
0456      * will also be emitted with a message describing the error.
0457      *
0458      * @param error Type of error that occurred, if any.
0459      * @param errorData More information about the error, if any.
0460      * @since 5.100
0461      */
0462     void teardownDone(const QModelIndex &index, Solid::ErrorType error, const QVariant &errorData);
0463 
0464     /**
0465      * Emitted whenever the visibility of the group @p group changes.
0466      * @param hidden The new visibility of the group.
0467      * @see setGroupHidden()
0468      * @since 5.42
0469      */
0470     void groupHiddenChanged(KFilePlacesModel::GroupType group, bool hidden);
0471 
0472     /**
0473      * Called once the model has been reloaded
0474      *
0475      * @since 5.71
0476      */
0477     void reloaded();
0478 
0479     /**
0480      * Emitted whenever the list of supported schemes has been changed
0481      *
0482      * @since 5.94
0483      */
0484     void supportedSchemesChanged();
0485 
0486 private:
0487     friend class KFilePlacesModelPrivate;
0488     std::unique_ptr<KFilePlacesModelPrivate> d;
0489 };
0490 
0491 #endif