File indexing completed on 2024-04-28 15:26:42

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 
0006     SPDX-License-Identifier: LGPL-2.0-only
0007 */
0008 
0009 #ifndef KFILEPLACESMODEL_H
0010 #define KFILEPLACESMODEL_H
0011 
0012 #include "kiofilewidgets_export.h"
0013 
0014 #include <KBookmark>
0015 #include <QAbstractItemModel>
0016 #include <QUrl>
0017 
0018 #include <solid/device.h>
0019 #include <solid/solidnamespace.h>
0020 
0021 #include <memory>
0022 
0023 class KFilePlacesModelPrivate;
0024 
0025 class QMimeData;
0026 class QAction;
0027 
0028 /**
0029  * @class KFilePlacesModel kfileplacesmodel.h <KFilePlacesModel>
0030  *
0031  * This class is a list view model. Each entry represents a "place"
0032  * where user can access files. Only relevant when
0033  * used with QListView or QTableView.
0034  */
0035 class KIOFILEWIDGETS_EXPORT KFilePlacesModel : public QAbstractItemModel
0036 {
0037     Q_OBJECT
0038 
0039     Q_PROPERTY(QStringList supportedSchemes READ supportedSchemes WRITE setSupportedSchemes NOTIFY supportedSchemesChanged)
0040 
0041 public:
0042     // Note: run   printf "0x%08X\n" $(($RANDOM*$RANDOM))
0043     // to define additional roles.
0044     enum AdditionalRoles {
0045         /** roleName is "url". @see url() */
0046         UrlRole = 0x069CD12B,
0047 
0048         /** roleName is "isHidden". @see isHidden() */
0049         HiddenRole = 0x0741CAAC,
0050 
0051         /** roleName is "isSetupNeeded". @see setupNeeded() */
0052         SetupNeededRole = 0x059A935D,
0053 
0054         /**
0055          * Whether the place is a fixed device (neither hotpluggable nor removable).
0056          * roleName is "isFixedDevice".
0057          */
0058         FixedDeviceRole = 0x332896C1,
0059 
0060         /**
0061          * Whether the place should have its free space displayed in a capacity bar.
0062          * roleName is "isCapacityBarRecommended".
0063          */
0064         CapacityBarRecommendedRole = 0x1548C5C4,
0065 
0066         /**
0067          * The name of the group, for example "Remote" or "Devices". roleName is "group".
0068          * @since 5.40
0069          */
0070         GroupRole = 0x0a5b64ee,
0071 
0072         /**
0073          * roleName is "iconName".
0074          * @see icon()
0075          * @since 5.41
0076          */
0077         IconNameRole = 0x00a45c00,
0078 
0079         /** roleName is "isGroupHidden".
0080          * @see isGroupHidden()
0081          * @since 5.42
0082          */
0083         GroupHiddenRole = 0x21a4b936,
0084 
0085         /** roleName is "isTeardownAllowed".
0086          * @see isTeardownAllowed().
0087          * @since 5.91
0088          */
0089         TeardownAllowedRole = 0x02533364,
0090 
0091         /** roleName is "isEjectAllowed".
0092          * @since 5.94.
0093          */
0094         EjectAllowedRole = 0x0A16AC5B,
0095 
0096         /**
0097          * roleName is "isTeardownOverlayRecommended".
0098          * @see isTeardownOverlayRecommended()
0099          * @since 5.95
0100          */
0101         TeardownOverlayRecommendedRole = 0x032EDCCE,
0102 
0103         /**
0104          * roleName is "deviceAccessibility".
0105          * @see deviceAccessibility()
0106          * @since 5.99
0107          */
0108         DeviceAccessibilityRole = 0x023FFD93,
0109     };
0110 
0111     /**
0112      * Describes the available group types used in this model.
0113      * @since 5.42
0114      */
0115     enum GroupType {
0116         PlacesType, ///< "Places" section
0117         RemoteType, ///< "Remote" section
0118         RecentlySavedType, ///< "Recent" section
0119         SearchForType, ///< "Search for" section
0120         DevicesType, ///< "Devices" section
0121         RemovableDevicesType, ///< "Removable Devices" section
0122         UnknownType, ///< Unknown GroupType
0123         TagsType, ///< "Tags" section. @since 5.54
0124     };
0125     Q_ENUM(GroupType)
0126 
0127     enum DeviceAccessibility { SetupNeeded, SetupInProgress, Accessible, TeardownInProgress };
0128     Q_ENUM(DeviceAccessibility)
0129 
0130     explicit KFilePlacesModel(QObject *parent = nullptr);
0131     /**
0132      * @brief Construct a new KFilePlacesModel with an alternativeApplicationName
0133      * @param alternativeApplicationName This value will be used to filter bookmarks in addition to the actual application name
0134      * @param parent Parent object
0135      * @since 5.43
0136      */
0137     // TODO KF6: merge constructors
0138     KFilePlacesModel(const QString &alternativeApplicationName, QObject *parent = nullptr);
0139     ~KFilePlacesModel() override;
0140 
0141     /**
0142      * @return The URL of the place at index @p index.
0143      */
0144     Q_INVOKABLE QUrl url(const QModelIndex &index) const;
0145 
0146     /**
0147      * @return Whether the place at index @p index needs to be mounted before it can be used.
0148      */
0149     Q_INVOKABLE bool setupNeeded(const QModelIndex &index) const;
0150 
0151     /**
0152      * @return Whether the place is a device that can be unmounted, e.g. it is
0153      * mounted but does not point at system Root or the user's Home directory.
0154      *
0155      * It does not indicate whether the teardown can succeed.
0156      * @since 5.91
0157      */
0158     Q_INVOKABLE bool isTeardownAllowed(const QModelIndex &index) const;
0159 
0160     /**
0161      * @return Whether the place is a device that can be ejected, e.g. it is
0162      * a CD, DVD, etc.
0163      *
0164      * It does not indicate whether the eject can succeed.
0165      * @since 5.94
0166      */
0167     Q_INVOKABLE bool isEjectAllowed(const QModelIndex &index) const;
0168 
0169     /**
0170      * @return Whether showing an inline teardown button is recommended,
0171      * e.g. when it is a removable drive.
0172      *
0173      * @since 5.95
0174      **/
0175     Q_INVOKABLE bool isTeardownOverlayRecommended(const QModelIndex &index) const;
0176 
0177     /**
0178      * @return Whether this device is currently accessible or being (un)mounted.
0179      *
0180      * @since 5.99
0181      */
0182     Q_INVOKABLE KFilePlacesModel::DeviceAccessibility deviceAccessibility(const QModelIndex &index) const;
0183 
0184     /**
0185      * @return The icon of the place at index @p index.
0186      */
0187     Q_INVOKABLE QIcon icon(const QModelIndex &index) const;
0188 
0189     /**
0190      * @return The user-visible text of the place at index @p index.
0191      */
0192     Q_INVOKABLE QString text(const QModelIndex &index) const;
0193 
0194     /**
0195      * @return Whether the place at index @p index is hidden or is inside an hidden group.
0196      */
0197     Q_INVOKABLE bool isHidden(const QModelIndex &index) const;
0198 
0199     /**
0200      * @return Whether the group type @p type is hidden.
0201      * @since 5.42
0202      */
0203     Q_INVOKABLE bool isGroupHidden(const GroupType type) const;
0204 
0205     /**
0206      * @return Whether the group of the place at index @p index is hidden.
0207      * @since 5.42
0208      */
0209     Q_INVOKABLE bool isGroupHidden(const QModelIndex &index) const;
0210 
0211     /**
0212      * @return Whether the place at index @p index is a device handled by Solid.
0213      * @see deviceForIndex()
0214      */
0215     Q_INVOKABLE bool isDevice(const QModelIndex &index) const;
0216 
0217     /**
0218      * @return The solid device of the place at index @p index, if it is a device. Otherwise a default Solid::Device() instance is returned.
0219      * @see isDevice()
0220      */
0221     Solid::Device deviceForIndex(const QModelIndex &index) const;
0222 
0223     /**
0224      * @return The KBookmark instance of the place at index @p index.
0225      * If the index is not valid, a default KBookmark instance is returned.
0226      */
0227     KBookmark bookmarkForIndex(const QModelIndex &index) const;
0228 
0229     /**
0230      * @return The KBookmark instance of the place with url @p searchUrl.
0231      * If the bookmark corresponding to searchUrl is not found, a default KBookmark instance is returned.
0232      * @since 5.63
0233      */
0234     KBookmark bookmarkForUrl(const QUrl &searchUrl) const;
0235 
0236     /**
0237      * @return The group type of the place at index @p index.
0238      * @since 5.42
0239      */
0240     Q_INVOKABLE GroupType groupType(const QModelIndex &index) const;
0241 
0242     /**
0243      * @return The list of model indexes that have @ type as their group type.
0244      * @see groupType()
0245      * @since 5.42
0246      */
0247     Q_INVOKABLE QModelIndexList groupIndexes(const GroupType type) const;
0248 
0249     /**
0250      * @return A QAction with a proper translated label that can be used to trigger the requestTeardown()
0251      * method for the place at index @p index.
0252      * @see requestTeardown()
0253      */
0254     Q_INVOKABLE QAction *teardownActionForIndex(const QModelIndex &index) const;
0255 
0256     /**
0257      * @return A QAction with a proper translated label that can be used to trigger the requestEject()
0258      * method for the place at index @p index.
0259      * @see requestEject()
0260      */
0261     Q_INVOKABLE QAction *ejectActionForIndex(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