File indexing completed on 2024-04-28 05:47:43

0001 /*
0002     SPDX-FileCopyrightText: 2007 Henrique Pinto <henrique.pinto@kdemail.net>
0003     SPDX-FileCopyrightText: 2008-2009 Harald Hvaal <haraldhv@stud.ntnu.no>
0004     SPDX-FileCopyrightText: 2016 Vladyslav Batyrenko <mvlabat@gmail.com>
0005 
0006     SPDX-License-Identifier: GPL-2.0-or-later
0007 */
0008 #ifndef ARCHIVEMODEL_H
0009 #define ARCHIVEMODEL_H
0010 
0011 #include "archiveentry.h"
0012 
0013 #include <KMessageWidget>
0014 
0015 #include <QAbstractItemModel>
0016 #include <QScopedPointer>
0017 
0018 using Kerfuffle::Archive;
0019 
0020 namespace Kerfuffle
0021 {
0022 class Query;
0023 }
0024 
0025 /**
0026  * Meta data related to one entry in a compressed archive.
0027  *
0028  * This is used for indexing entry properties as numbers
0029  * and for determining data displaying order in part's view.
0030  */
0031 enum EntryMetaDataType {
0032     DisplayName, /**< The entry's name that will be displayed in the view */
0033     Size, /**< The entry's original size */
0034     CompressedSize, /**< The compressed size for the entry */
0035     Permissions, /**< The entry's permissions */
0036     Owner, /**< The user the entry belongs to */
0037     Group, /**< The user group the entry belongs to */
0038     Ratio, /**< The compression ratio for the entry */
0039     CRC, /**< The entry's CRC */
0040     BLAKE2, /**< The entry's BLAKE2 */
0041     Method, /**< The compression method used on the entry */
0042     Version, /**< The archiver version needed to extract the entry */
0043     Timestamp /**< The timestamp for the current entry */
0044 };
0045 
0046 class ArchiveModel : public QAbstractItemModel
0047 {
0048     Q_OBJECT
0049 public:
0050     explicit ArchiveModel(const QString &dbusPathName, QObject *parent = nullptr);
0051     ~ArchiveModel() override;
0052 
0053     QVariant data(const QModelIndex &index, int role) const override;
0054     Qt::ItemFlags flags(const QModelIndex &index) const override;
0055     QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const override;
0056     QModelIndex index(int row, int column, const QModelIndex &parent = QModelIndex()) const override;
0057     QModelIndex parent(const QModelIndex &index) const override;
0058     int rowCount(const QModelIndex &parent = QModelIndex()) const override;
0059     int columnCount(const QModelIndex &parent = QModelIndex()) const override;
0060 
0061     // drag and drop related
0062     Qt::DropActions supportedDropActions() const override;
0063     QStringList mimeTypes() const override;
0064     QMimeData *mimeData(const QModelIndexList &indexes) const override;
0065     bool dropMimeData(const QMimeData *data, Qt::DropAction action, int row, int column, const QModelIndex &parent) override;
0066 
0067     void reset();
0068     void createEmptyArchive(const QString &path, const QString &mimeType, QObject *parent);
0069     Kerfuffle::LoadJob *loadArchive(const QString &path, const QString &mimeType, QObject *parent);
0070     Kerfuffle::Archive *archive() const;
0071 
0072     QList<int> shownColumns() const;
0073     QMap<int, QByteArray> propertiesMap() const;
0074 
0075     Archive::Entry *entryForIndex(const QModelIndex &index);
0076 
0077     Kerfuffle::ExtractJob *
0078     extractFile(Archive::Entry *file, const QString &destinationDir, Kerfuffle::ExtractionOptions options = Kerfuffle::ExtractionOptions()) const;
0079     Kerfuffle::ExtractJob *extractFiles(const QVector<Archive::Entry *> &files,
0080                                         const QString &destinationDir,
0081                                         Kerfuffle::ExtractionOptions options = Kerfuffle::ExtractionOptions()) const;
0082 
0083     Kerfuffle::PreviewJob *preview(Archive::Entry *file) const;
0084     Kerfuffle::OpenJob *open(Archive::Entry *file) const;
0085     Kerfuffle::OpenWithJob *openWith(Archive::Entry *file) const;
0086 
0087     Kerfuffle::AddJob *addFiles(QVector<Archive::Entry *> &entries,
0088                                 const Archive::Entry *destination,
0089                                 const Kerfuffle::CompressionOptions &options = Kerfuffle::CompressionOptions());
0090     Kerfuffle::MoveJob *
0091     moveFiles(QVector<Archive::Entry *> &entries, Archive::Entry *destination, const Kerfuffle::CompressionOptions &options = Kerfuffle::CompressionOptions());
0092     Kerfuffle::CopyJob *
0093     copyFiles(QVector<Archive::Entry *> &entries, Archive::Entry *destination, const Kerfuffle::CompressionOptions &options = Kerfuffle::CompressionOptions());
0094     Kerfuffle::DeleteJob *deleteFiles(QVector<Archive::Entry *> entries);
0095 
0096     /**
0097      * @param password The password to encrypt the archive with.
0098      * @param encryptHeader Whether to encrypt also the list of files.
0099      */
0100     void encryptArchive(const QString &password, bool encryptHeader);
0101 
0102     void countEntriesAndSize();
0103     qulonglong numberOfFiles() const;
0104     qulonglong numberOfFolders() const;
0105     qulonglong uncompressedSize() const;
0106 
0107     /**
0108      * Constructs a list of conflicting entries.
0109      *
0110      * @param conflictingEntries Reference to the empty mutable entries list, which will be constructed.
0111      * If the method returns false, this list will contain only entries which produce a critical conflict.
0112      * @param entries New entries paths list.
0113      * @param allowMerging Boolean variable indicating whether merging is permitted.
0114      * If true, existing entries won't generate an error.
0115      *
0116      * @return Boolean variable indicating whether conflicts are not critical (true for not critical,
0117      * false for critical). For example, if there are both "some/file" (not a directory) and "some/file/" (a directory)
0118      * entries for both new and existing paths, the method will return false. Also, if merging is not allowed,
0119      * this method will return false for entries with the same path and types.
0120      */
0121     bool conflictingEntries(QList<const Archive::Entry *> &conflictingEntries, const QStringList &entries, bool allowMerging) const;
0122 
0123     static bool hasDuplicatedEntries(const QStringList &entries);
0124 
0125     static QMap<QString, Archive::Entry *> entryMap(const QVector<Archive::Entry *> &entries);
0126 
0127     QMap<QString, Kerfuffle::Archive::Entry *> filesToMove;
0128     QMap<QString, Kerfuffle::Archive::Entry *> filesToCopy;
0129 
0130 Q_SIGNALS:
0131     void loadingStarted();
0132     void loadingFinished(KJob *);
0133     void error(const QString &error, const QString &details);
0134     void droppedFiles(const QStringList &files, const Archive::Entry *);
0135     void messageWidget(KMessageWidget::MessageType type, const QString &msg);
0136 
0137 private Q_SLOTS:
0138     void slotNewEntry(Archive::Entry *entry);
0139     void slotListEntry(Archive::Entry *entry);
0140     void slotLoadingFinished(KJob *job);
0141     void slotEntryRemoved(const QString &path);
0142     void slotUserQuery(Kerfuffle::Query *query);
0143     void slotCleanupEmptyDirs();
0144 
0145 private:
0146     /**
0147      * Strips file names that start with './'.
0148      *
0149      * For more information, see bug 194241.
0150      *
0151      * @param fileName The file name that will be stripped.
0152      *
0153      * @return @p fileName without the leading './'
0154      */
0155     QString cleanFileName(const QString &fileName);
0156 
0157     void initRootEntry();
0158 
0159     enum InsertBehaviour { NotifyViews, DoNotNotifyViews };
0160     Archive::Entry *parentFor(const Kerfuffle::Archive::Entry *entry, InsertBehaviour behaviour = NotifyViews);
0161     QModelIndex indexForEntry(Archive::Entry *entry);
0162     /**
0163      * Insert the node @p node into the model, ensuring all views are notified
0164      * of the change.
0165      */
0166 
0167     void insertEntry(Archive::Entry *entry, InsertBehaviour behaviour = NotifyViews);
0168     void newEntry(Kerfuffle::Archive::Entry *receivedEntry, InsertBehaviour behaviour);
0169 
0170     qulonglong traverseAndComputeDirSizes(Archive::Entry *dir);
0171 
0172     QList<int> m_showColumns;
0173     QScopedPointer<Kerfuffle::Archive> m_archive;
0174     QScopedPointer<Archive::Entry> m_rootEntry;
0175     QHash<QString, QIcon> m_entryIcons;
0176     QMap<int, QByteArray> m_propertiesMap;
0177 
0178     QString m_dbusPathName;
0179 
0180     qulonglong m_numberOfFiles;
0181     qulonglong m_numberOfFolders;
0182 
0183     // Whether a file entry has been listed. Used to ensure all relevant columns are shown,
0184     // since directories might have fewer columns than files.
0185     bool m_fileEntryListed;
0186 };
0187 
0188 #endif // ARCHIVEMODEL_H