File indexing completed on 2024-05-26 16:01:01

0001 /*
0002  * <one line to give the program's name and a brief idea of what it does.>
0003  * Copyright (C) 2018  Camilo Higuita <email>
0004  *
0005  * This program is free software: you can redistribute it and/or modify
0006  * it under the terms of the GNU General Public License as published by
0007  * the Free Software Foundation, either version 3 of the License, or
0008  * (at your option) any later version.
0009  *
0010  * This program is distributed in the hope that it will be useful,
0011  * but WITHOUT ANY WARRANTY; without even the implied warranty of
0012  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
0013  * GNU General Public License for more details.
0014  *
0015  * You should have received a copy of the GNU General Public License
0016  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
0017  */
0018 
0019 #pragma once
0020 
0021 #include <QObject>
0022 #include <QImage>
0023 
0024 #if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
0025 #include <MauiKit3/Core/mauilist.h>
0026 #else
0027 #include <MauiKit4/Core/mauilist.h>
0028 #endif
0029 
0030 #include "filebrowsing_export.h"
0031 
0032 #include "fmstatic.h"
0033 
0034 class FM;
0035 
0036 /**
0037  * @brief Represents the status of a directory listing, be it non existence location, loading or empty.
0038  * 
0039  * The status object is divided into different properties for convenience, such as error label, message, icon, code, etc.
0040  */
0041 struct PathStatus
0042 {
0043     Q_GADGET
0044     
0045     /**
0046      * The status code. More details are exposed with the other properties.
0047      */
0048     Q_PROPERTY(PathStatus::STATUS_CODE code MEMBER m_code)
0049     
0050     /**
0051      * The status title.
0052      */
0053     Q_PROPERTY(QString title MEMBER m_title)
0054     
0055     /**
0056      * The message details of the status.
0057      */
0058     Q_PROPERTY(QString message MEMBER m_message)
0059     
0060     /**
0061      * An associated icon name for the status.
0062      */
0063     Q_PROPERTY(QString icon MEMBER m_icon)
0064     
0065     /**
0066      * Whether the location is empty and there is nothing for listing.
0067      */
0068     Q_PROPERTY(bool empty MEMBER m_empty)
0069     
0070     /**
0071      * Whether the location can be accessed and exists.
0072      */
0073     Q_PROPERTY(bool exists MEMBER m_exists)    
0074     
0075 public:
0076     /**
0077      * @brief The different status that can occur.
0078      */
0079     enum STATUS_CODE : int 
0080     { 
0081         /**
0082          * The content is still loading its contents
0083          */
0084         LOADING, 
0085         
0086         /**
0087          * The listing of the contents has failed. For knowing the reason check the other properties, such as `title`, `exists`, etc.
0088          */
0089         ERROR,
0090         
0091         /**
0092          * The listing has finished successfully
0093          */
0094         READY 
0095         
0096     }; Q_ENUM(STATUS_CODE)
0097     
0098     STATUS_CODE m_code;
0099     QString m_title;
0100     QString m_message;
0101     QString m_icon;
0102     bool m_empty = false;
0103     bool m_exists = false;
0104 };
0105 Q_DECLARE_METATYPE(PathStatus)
0106 
0107 /**
0108  * @private
0109  */
0110 struct NavHistory {
0111     void appendPath(const QUrl &path)
0112     {
0113         this->prev_history.append(path);
0114     }
0115     
0116     QUrl getPosteriorPath()
0117     {
0118         if (this->post_history.isEmpty())
0119             return QUrl();
0120         
0121         return this->post_history.takeLast();
0122     }
0123     
0124     QUrl getPreviousPath()
0125     {
0126         if (this->prev_history.isEmpty())
0127             return QUrl();
0128         
0129         if (this->prev_history.length() < 2)
0130             return this->prev_history.at(0);
0131         
0132         this->post_history.append(this->prev_history.takeLast());
0133         return this->prev_history.takeLast();
0134     }
0135     
0136 private:
0137     QVector<QUrl> prev_history;
0138     QVector<QUrl> post_history;
0139 };
0140 
0141 /**
0142  * @brief The FMList class
0143  * Model for listing the file system files and directories and perform relevant actions upon it
0144  */
0145 class FILEBROWSING_EXPORT FMList : public MauiList
0146 {
0147     Q_OBJECT
0148     Q_DISABLE_COPY(FMList)
0149     
0150     // writable
0151     
0152     /**
0153      * Whether to auto load the content entries when the path property is modified. Otherwise explicitly call the load method.
0154      * @see search
0155      * @see fill
0156      */
0157     Q_PROPERTY(bool autoLoad READ getAutoLoad WRITE setAutoLoad NOTIFY autoLoadChanged)
0158     
0159     /**
0160      * The URL to location path to proceed listing all of its file entries.
0161      * There is support for multiple type of location depending on the scheme, for example local file system uses `file://`, while you can browser networks using `ftp://` or `fish://`. Support for those locations depends on KIO and its slaves - to know more about it read the KIO slaves documentation.
0162      */
0163     Q_PROPERTY(QString path READ getPath WRITE setPath NOTIFY pathChanged)
0164     
0165     /**
0166      * Whether to list the hidden entries.
0167      * By default this is set to `false`.
0168      */
0169     Q_PROPERTY(bool hidden READ getHidden WRITE setHidden NOTIFY hiddenChanged)
0170     
0171     /**
0172      * Whether only directories should be listed.
0173      * By default this is set to `false`.
0174      */
0175     Q_PROPERTY(bool onlyDirs READ getOnlyDirs WRITE setOnlyDirs NOTIFY onlyDirsChanged)
0176     
0177     /**
0178      * Whether the folders should be sorted first and then the files.
0179      * By default this is set to `true`.
0180      */
0181     Q_PROPERTY(bool foldersFirst READ getFoldersFirst WRITE setFoldersFirst NOTIFY foldersFirstChanged)
0182     
0183     /**
0184      * When the location if a remote cloud directory, this allows to define the depth of the levels for listing the contents.
0185      * By default this is set to `1`, which will only lists the entries in the current location, a bigger depth will start listing sub-directories too.
0186      * @deprecated
0187      */
0188     Q_PROPERTY(int cloudDepth READ getCloudDepth WRITE setCloudDepth NOTIFY cloudDepthChanged)
0189     
0190     /**
0191      * The list of string values to filter the listing. For example to only list PNG and JPG images: `filters: ["*.png", "*.jpg"]`.
0192      * To reset or clear the filters you can set the property to `undefined`
0193      */
0194     Q_PROPERTY(QStringList filters READ getFilters WRITE setFilters NOTIFY filtersChanged RESET resetFilters)
0195     
0196     /**
0197      * A convenient way to filter the location contents by a file type (mimetype). 
0198      * By default this is set to `FILTER_TYPE::NONE`.
0199      */
0200     Q_PROPERTY(FMList::FILTER filterType READ getFilterType WRITE setFilterType NOTIFY filterTypeChanged RESET resetFilterType)
0201     
0202     /**
0203      * The sorting value.
0204      * By default this is set to `SORTBY::MODIFIED`.
0205      */
0206     Q_PROPERTY(FMList::SORTBY sortBy READ getSortBy WRITE setSortBy NOTIFY sortByChanged)
0207     
0208     /**
0209      * Whether destructive actions or modifications can be done to the current location contents, such as deleting, renaming, pasting, adding, etc.
0210      * This only protects the location contents if using this API action methods.
0211      */
0212     Q_PROPERTY(bool readOnly READ readOnly WRITE setReadOnly NOTIFY readOnlyChanged)
0213     
0214     // readonly
0215     /**
0216      * The title name of the current location.
0217      */
0218     Q_PROPERTY(QString pathName READ getPathName NOTIFY pathNameChanged FINAL)
0219     
0220     /**
0221      * The known type of the current location.
0222      */
0223     Q_PROPERTY(FMList::PATHTYPE pathType READ getPathType NOTIFY pathTypeChanged FINAL)
0224     
0225     /**
0226      * The current status of the location contents listing. This is a group of properties.
0227      */
0228     Q_PROPERTY(PathStatus status READ getStatus NOTIFY statusChanged)
0229     
0230     /**
0231      * The location of the parent directory of this current location.
0232      */
0233     Q_PROPERTY(QUrl parentPath READ getParentPath NOTIFY pathChanged)
0234     
0235 public:
0236     /**
0237      * @brief The possible values to sort the location contents
0238      */
0239     enum SORTBY : uint_fast8_t {
0240         /**
0241          * The size of the file entry
0242          */
0243         SIZE = FMH::MODEL_KEY::SIZE,
0244         
0245         /**
0246          * The last modified date of the entry file
0247          */
0248         MODIFIED = FMH::MODEL_KEY::MODIFIED,
0249         
0250         /**
0251          * The creation date of the file entry
0252          */
0253         DATE = FMH::MODEL_KEY::DATE,
0254         
0255         /**
0256          * The name or title of the file entry
0257          */
0258         LABEL = FMH::MODEL_KEY::LABEL,
0259         
0260         /**
0261          * The file type of the entry. Deduced from its file suffix name
0262          */
0263         MIME = FMH::MODEL_KEY::MIME,
0264         
0265         /**
0266          * The date when the file entry was added
0267          */
0268         ADDDATE = FMH::MODEL_KEY::ADDDATE
0269     };
0270     Q_ENUM(SORTBY)
0271     
0272     /**
0273      * @brief The possible values to filter the a location content by a mime-type.
0274      */
0275     enum FILTER : uint_fast8_t {
0276         /**
0277          * Audio file types. Such as MP3, WAV, FLAC, MP4, etc.
0278          */
0279         AUDIO = FMStatic::FILTER_TYPE::AUDIO,
0280         
0281         /**
0282          * Video file types
0283          */
0284         VIDEO = FMStatic::FILTER_TYPE::VIDEO,
0285         
0286         /**
0287          * Plain text file types
0288          */
0289         TEXT = FMStatic::FILTER_TYPE::TEXT,
0290         
0291         /**
0292          * Image file types
0293          */
0294         IMAGE = FMStatic::FILTER_TYPE::IMAGE,
0295         
0296         /**
0297          * PDF, EBooks and comic books file types
0298          */
0299         DOCUMENT = FMStatic::FILTER_TYPE::DOCUMENT,
0300         
0301         /**
0302          * Compressed archives
0303          */
0304         COMPRESSED = FMStatic::FILTER_TYPE::COMPRESSED,
0305         
0306         /**
0307          * Font file types
0308          */
0309         FONT = FMStatic::FILTER_TYPE::FONT,
0310         
0311         /**
0312          * Any file type
0313          */
0314         NONE = FMStatic::FILTER_TYPE::NONE
0315     };
0316     Q_ENUM(FILTER)
0317     
0318     /**
0319      * @brief The different location or places types.
0320      */
0321     enum PATHTYPE : uint_fast8_t {
0322         PLACES_PATH = FMStatic::PATHTYPE_KEY::PLACES_PATH,
0323         FISH_PATH = FMStatic::PATHTYPE_KEY::FISH_PATH,
0324         MTP_PATH = FMStatic::PATHTYPE_KEY::MTP_PATH,
0325         REMOTE_PATH = FMStatic::PATHTYPE_KEY::REMOTE_PATH,
0326         DRIVES_PATH = FMStatic::PATHTYPE_KEY::DRIVES_PATH,
0327         REMOVABLE_PATH = FMStatic::PATHTYPE_KEY::REMOVABLE_PATH,
0328         TAGS_PATH = FMStatic::PATHTYPE_KEY::TAGS_PATH,
0329         BOOKMARKS_PATH = FMStatic::PATHTYPE_KEY::BOOKMARKS_PATH,
0330         APPS_PATH = FMStatic::PATHTYPE_KEY::APPS_PATH,
0331         TRASH_PATH = FMStatic::PATHTYPE_KEY::TRASH_PATH,
0332         CLOUD_PATH = FMStatic::PATHTYPE_KEY::CLOUD_PATH,
0333         QUICK_PATH = FMStatic::PATHTYPE_KEY::QUICK_PATH,
0334         OTHER_PATH = FMStatic::PATHTYPE_KEY::OTHER_PATH
0335         
0336     };
0337     Q_ENUM(PATHTYPE)
0338     
0339     /**
0340      * @brief The possible view types for listing the entries in the FileBrowser visual control.
0341      */
0342     enum VIEW_TYPE : uint_fast8_t {
0343         /**
0344          * Display the file system entries in a grid view.
0345          */
0346         ICON_VIEW,
0347         
0348         /**
0349          * Display the file system entries in a list, with more information details visible.
0350          */
0351         LIST_VIEW
0352     };
0353     Q_ENUM(VIEW_TYPE)
0354     
0355     /**
0356      * @brief FMList
0357      * @param parent
0358      */
0359     FMList(QObject *parent = nullptr);
0360     
0361     /**
0362      * @brief items
0363      * @return
0364      */
0365     const FMH::MODEL_LIST &items() const final override;
0366     
0367     FMList::SORTBY getSortBy() const;
0368     void setSortBy(const FMList::SORTBY &key);
0369     
0370     /**
0371      * @private
0372      */
0373     void componentComplete() override final;
0374     
0375     bool getAutoLoad() const;    
0376     void setAutoLoad(bool value);    
0377     
0378     QString getPath() const;
0379     void setPath(const QString &path);
0380     
0381     QString getPathName() const;
0382     
0383     FMList::PATHTYPE getPathType() const;
0384     
0385     QStringList getFilters() const;
0386     void setFilters(const QStringList &filters);
0387     void resetFilters();    
0388     
0389     FMList::FILTER getFilterType() const;
0390     void setFilterType(const FMList::FILTER &type);    
0391     void resetFilterType();    
0392     
0393     bool getHidden() const;
0394     void setHidden(const bool &state);
0395     
0396     bool getOnlyDirs() const;
0397     void setOnlyDirs(const bool &state);
0398     
0399     const QUrl getParentPath();
0400     
0401     bool getFoldersFirst() const;
0402     void setFoldersFirst(const bool &value);
0403     
0404     int getCloudDepth() const;
0405     void setCloudDepth(const int &value);    
0406     
0407     PathStatus getStatus() const;
0408     
0409     void setReadOnly(bool value);
0410     bool readOnly() const;
0411     
0412 private:
0413     FM *fm;
0414     void clear();
0415     void reset();
0416     void setList();
0417     void assignList(const FMH::MODEL_LIST &list);
0418     void appendToList(const FMH::MODEL_LIST &list);
0419     void sortList();
0420     void filterContent(const QString &query, const QUrl &path);
0421     void setStatus(const PathStatus &status);    
0422     
0423     bool saveImageFile(const QImage &image);
0424     bool saveTextFile(const QString &data, const QString &format);
0425     /**
0426      * @brief Gets a model of the files associated with a tag
0427      * @param tag The lookup tag
0428      * @param filters Filters as regular expression
0429      * @return Model of files associated
0430      */
0431     FMH::MODEL_LIST getTagContent(const QString &tag, const QStringList &filters = {});
0432     
0433     FMH::MODEL_LIST list = {{}};
0434     
0435     bool m_autoLoad = true;
0436     QUrl path;
0437     QString pathName = QString();
0438     QStringList filters = {};
0439     
0440     bool onlyDirs = false;
0441     bool hidden = false;
0442     
0443     bool foldersFirst = false;
0444     int cloudDepth = 1;
0445     
0446     PathStatus m_status;
0447     
0448     FMList::SORTBY sort = FMList::SORTBY::MODIFIED;
0449     FMList::FILTER filterType = FMList::FILTER::NONE;
0450     FMList::PATHTYPE pathType = FMList::PATHTYPE::PLACES_PATH;
0451     
0452     NavHistory m_navHistory;
0453     
0454     bool m_readOnly = false;
0455     
0456 public Q_SLOTS:
0457     
0458     /**
0459      * @brief Refresh the model for new changes. h content listing ill be regenerated.
0460      */
0461     void refresh();
0462     
0463     /**
0464      * @brief Create a new directory within the current directory.
0465      * @param name the name of the directory
0466      */
0467     void createDir(const QString &name);
0468     
0469     /**
0470      * @brief Create a new file.
0471      * @note To create a custom file, please supply with the correct suffix.
0472      * @param name the name of the new file, for example `new.txt`
0473      */
0474     void createFile(const QString &name);
0475     
0476     /**
0477      * @brief Rename a file with from a given URL to the a new name provided
0478      * @param url the file URL to be renamed
0479      * @param newName the new name for the file
0480      */
0481     void renameFile(const QString &url, const QString &newName);
0482     
0483     /**
0484      * @brief Create a symbolic link to the given URL in the current location.
0485      * @param url the file URL to create the link from
0486      */
0487     void createSymlink(const QString &url);
0488     
0489     /**
0490      * @brief Completely remove the set of file URLs provided. This action can not be undone
0491      * @param urls the list of file URLS to be removed
0492      */
0493     void removeFiles(const QStringList &urls);
0494     
0495     /**
0496      * @brief Remove and move to the trash the provided set of file URLs
0497      * @param urls the list of file URLS to be removed
0498      */
0499     void moveToTrash(const QStringList &urls);
0500     
0501     /**
0502      * @brief Whether the clipboard has a supported type of content.
0503      * @return whether the clipboard content is a supported file URL or a text or image raw data.
0504      */
0505     bool clipboardHasContent() const;
0506     
0507     /**
0508      * @brief Copy a list of file URLs into the current directory
0509      * @param urls list of files
0510      */
0511     void copyInto(const QStringList &urls);
0512     
0513     /**
0514      * @brief Cut/move a list of file URLs to the current directory
0515      * @param urls list of files
0516      */
0517     void cutInto(const QStringList &urls);
0518     
0519     /**
0520      * @brief Handle the paste action.
0521      * This allows to quickly paste into the current location any file URL in the clipboard, and raw image data and text snippets into a new file.
0522      */
0523     void paste();
0524     
0525     /**
0526      * @brief Changes the icon of a directory by making use of the directory config file
0527      * @param index the index position of the directory in the model
0528      * @param iconName then name of the new icon
0529      */
0530     void setDirIcon(const int &index, const QString &iconName);
0531     
0532     /**
0533      * @brief Remove an item from the model, this does not remove the file from the file system
0534      * @param index the index position of the file entry
0535      */
0536     void remove(const int &index);
0537     
0538     /**
0539      * @brief Start a search - starting from the current location - for a given name query.
0540      * @param query the search query name
0541      * @param recursive whether the search should be recursive and look into the subsequent sub-directories structure. By default this is set to `false`.
0542      */
0543     void search(const QString &query, bool recursive = true);    
0544     
0545     /**
0546      * @brief The immediate previous path location that was navigated
0547      * @return the path URL location
0548      */
0549     const QUrl previousPath();
0550     
0551     /**
0552      * @brief The immediate posterior path location that was navigated
0553      * @return the path URL location
0554      */
0555     const QUrl posteriorPath();
0556     
0557     /**
0558      * @brief Given a file name query find if it exists in the current location 
0559      * @param index the index of the found file entry otherwise `-1`
0560      */
0561     int indexOfName(const QString &query);
0562     int indexOfFile(const QString &url);
0563     
0564 Q_SIGNALS:
0565     void pathChanged();
0566     void pathNameChanged();
0567     void pathTypeChanged();
0568     void filtersChanged();
0569     void filterTypeChanged();
0570     void hiddenChanged();
0571     void onlyDirsChanged();
0572     void sortByChanged();
0573     void foldersFirstChanged();
0574     void statusChanged();
0575     void cloudDepthChanged();
0576     void autoLoadChanged();    
0577     void readOnlyChanged();
0578     
0579     /**
0580      * @brief Emitted when the listing process has any error message that needs to be notified.
0581      * @param message the warning message text
0582      */
0583     void warning(QString message);
0584     
0585     /**
0586      * @brief Emitted while the file listing is still in progress.
0587      * @param percent the loading progress - it goes from 0 to 100.
0588      */
0589     void progress(int percent);
0590 };
0591