File indexing completed on 2024-05-19 04:56:04

0001 /**
0002  * \file frametablemodel.h
0003  * Model for table with frames.
0004  *
0005  * \b Project: Kid3
0006  * \author Urs Fleisch
0007  * \date 01 May 2011
0008  *
0009  * Copyright (C) 2011-2024  Urs Fleisch
0010  *
0011  * This file is part of Kid3.
0012  *
0013  * Kid3 is free software; you can redistribute it and/or modify
0014  * it under the terms of the GNU General Public License as published by
0015  * the Free Software Foundation; either version 2 of the License, or
0016  * (at your option) any later version.
0017  *
0018  * Kid3 is distributed in the hope that it will be useful,
0019  * but WITHOUT ANY WARRANTY; without even the implied warranty of
0020  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
0021  * GNU General Public License for more details.
0022  *
0023  * You should have received a copy of the GNU General Public License
0024  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
0025  */
0026 
0027 #pragma once
0028 
0029 #include <QAbstractTableModel>
0030 #include <QVector>
0031 #include <QSet>
0032 #include <QBitArray>
0033 #include "frame.h"
0034 #include "kid3api.h"
0035 
0036 class CoreTaggedFileIconProvider;
0037 
0038 /**
0039  * Model for table with frames.
0040  */
0041 class KID3_CORE_EXPORT FrameTableModel : public QAbstractTableModel {
0042   Q_OBJECT
0043 public:
0044   /** Custom role. */
0045   enum Roles {
0046     FrameTypeRole = Qt::UserRole + 1,
0047     NameRole = Qt::UserRole + 2,
0048     ValueRole =  Qt::UserRole + 3,
0049     ModifiedRole =  Qt::UserRole + 4,
0050     TruncatedRole =  Qt::UserRole + 5,
0051     InternalNameRole =  Qt::UserRole + 6,
0052     FieldIdsRole =  Qt::UserRole + 7,
0053     FieldValuesRole =  Qt::UserRole + 8,
0054     CompletionsRole =  Qt::UserRole + 9,
0055     NoticeRole =  Qt::UserRole + 10,
0056     NoticeWarningRole =  Qt::UserRole + 11
0057   };
0058 
0059   /** Column indices. */
0060   enum ColumnIndex {
0061     CI_Enable,
0062     CI_Value,
0063     CI_NumColumns
0064   };
0065 
0066   /**
0067    * Constructor.
0068    * @param id3v1  true if model for ID3v1 frames
0069    * @param colorProvider colorProvider
0070    * @param parent parent widget
0071    */
0072   FrameTableModel(bool id3v1, CoreTaggedFileIconProvider* colorProvider,
0073                   QObject* parent = nullptr);
0074 
0075   /**
0076    * Destructor.
0077    */
0078   ~FrameTableModel() override = default;
0079 
0080   /**
0081    * Get item flags for index.
0082    * @param index model index
0083    * @return item flags
0084    */
0085   Qt::ItemFlags flags(const QModelIndex& index) const override;
0086 
0087   /**
0088    * Get data for a given role.
0089    * @param index model index
0090    * @param role item data role
0091    * @return data for role
0092    */
0093   QVariant data(const QModelIndex& index,
0094                 int role = Qt::DisplayRole) const override;
0095 
0096   /**
0097    * Set data for a given role.
0098    * @param index model index
0099    * @param value data value
0100    * @param role item data role
0101    * @return true if successful
0102    */
0103   bool setData(const QModelIndex& index, const QVariant& value,
0104                int role = Qt::EditRole) override;
0105 
0106   /**
0107    * Get data for header section.
0108    * @param section column or row
0109    * @param orientation horizontal or vertical
0110    * @param role item data role
0111    * @return header data for role
0112    */
0113   QVariant headerData(int section, Qt::Orientation orientation,
0114                       int role = Qt::DisplayRole) const override;
0115 
0116   /**
0117    * Set data for header section.
0118    * Not supported.
0119    * @return false
0120    */
0121   bool setHeaderData(int, Qt::Orientation, const QVariant&,
0122                      int = Qt::EditRole) override { return false; }
0123 
0124   /**
0125    * Get number of rows.
0126    * @param parent parent model index, invalid for table models
0127    * @return number of rows,
0128    * if parent is valid number of children (0 for table models)
0129    */
0130   int rowCount(const QModelIndex& parent = QModelIndex()) const override;
0131 
0132   /**
0133    * Get number of columns.
0134    * @param parent parent model index, invalid for table models
0135    * @return number of columns,
0136    * if parent is valid number of children (0 for table models)
0137    */
0138   int columnCount(const QModelIndex& parent = QModelIndex()) const override;
0139 
0140   /**
0141    * Remove rows.
0142    * @param row rows are removed starting with this row
0143    * @param count number of rows to remove
0144    * @param parent parent model index, invalid for table models
0145    * @return true if successful
0146    */
0147   bool removeRows(int row, int count,
0148                   const QModelIndex& parent = QModelIndex()) override;
0149 
0150   /**
0151    * Insert rows.
0152    * @param row rows are inserted before this row, if 0 at the begin,
0153    * if rowCount() at the end
0154    * @param count number of rows to insert
0155    * @param parent parent model index, invalid for table models
0156    * @return true if successful
0157    */
0158   bool insertRows(int row, int count,
0159                   const QModelIndex& parent = QModelIndex()) override;
0160 
0161   /**
0162    * Map role identifiers to role property names in scripting languages.
0163    * @return hash mapping role identifiers to names.
0164    */
0165   QHash<int,QByteArray> roleNames() const override;
0166 
0167   /**
0168    * Insert a frame.
0169    * @param frame frame to insert
0170    */
0171   void insertFrame(const Frame& frame);
0172 
0173   /**
0174    * Check if model is for ID3v1 frames.
0175    * @return true if for ID3v1.
0176    */
0177   bool isId3v1() const { return m_id3v1; }
0178 
0179   /**
0180    * Mark rows.
0181    * @param rowMask mask with bits of rows to mark
0182    */
0183   void markRows(quint64 rowMask);
0184 
0185 
0186   /**
0187    * Mark changed frames.
0188    * @param types frame types to mark
0189    */
0190   void markChangedFrames(const QList<Frame::ExtendedType>& types);
0191 
0192   /**
0193    * Get frame for index.
0194    * @param index model index
0195    * @return frame, 0 if no frame.
0196    */
0197   const Frame* getFrameOfIndex(const QModelIndex& index) const;
0198 
0199   /**
0200    * Get row with frame with a specific frame index.
0201    * @param index frame index
0202    * @return row number, -1 if not found.
0203    */
0204   int getRowWithFrameIndex(int index) const;
0205 
0206   /**
0207    * Get row with frame with a specific frame name.
0208    * @param name name of frame
0209    * @return row number, -1 if not found.
0210    */
0211   int getRowWithFrameName(const QString& name) const;
0212 
0213   /**
0214    * Get filter with enabled frames.
0215    *
0216    * @param allDisabledToAllEnabled true to enable all if all are disabled
0217    *
0218    * @return filter with enabled frames.
0219    */
0220   FrameFilter getEnabledFrameFilter(bool allDisabledToAllEnabled = false) const;
0221 
0222   /**
0223    * Set the check state of all frames in the table.
0224    *
0225    * @param checked true to check the frames
0226    */
0227   void setAllCheckStates(bool checked);
0228 
0229   /**
0230    * Get reference to frame collection.
0231    * @return frame collection.
0232    */
0233   const FrameCollection& frames() const { return m_frames; }
0234 
0235   /**
0236    * Get enabled frames.
0237    * @return frame collection with enabled frames.
0238    */
0239   FrameCollection getEnabledFrames() const;
0240 
0241   /**
0242    * Clear frame collection.
0243    */
0244   void clearFrames();
0245 
0246   /**
0247    * Transfer frames to frame collection.
0248    * @param src frames to move into frame collection, will be cleared
0249    */
0250   void transferFrames(FrameCollection& src);
0251 
0252   /**
0253    * Start filtering different values.
0254    */
0255   void beginFilterDifferent();
0256 
0257   /**
0258    * Set values which are different inactive.
0259    *
0260    * @param others frames to compare, will be modified
0261    */
0262   void filterDifferent(FrameCollection& others);
0263 
0264   /**
0265    * End filtering different values.
0266    */
0267   void endFilterDifferent();
0268 
0269   /**
0270    * Get the different values which have been filtered for a frame type.
0271    * @param type frame type
0272    * @return different values.
0273    */
0274   QSet<QString> getCompletionsForType(Frame::ExtendedType type) const;
0275 
0276   /**
0277    * Set if headerData() shall return empty values.
0278    * This can be used to avoid having text fragments visible in the header of
0279    * frame table columns.
0280    * @param empty true to use empty values, default is false
0281    */
0282   void setHeadersEmpty(bool empty) { m_emptyHeaders = empty; }
0283   bool headersEmpty() const { return m_emptyHeaders; }
0284 
0285 public slots:
0286   /**
0287    * Select all frames in the table.
0288    */
0289   void selectAllFrames();
0290 
0291   /**
0292    * Deselect all frames in the table.
0293    */
0294   void deselectAllFrames();
0295 
0296   /**
0297    * Select changed frames in the table.
0298    */
0299   void selectChangedFrames();
0300 
0301   /**
0302    * Set order of frames in frame table.
0303    * @param frameTypes ordered sequence of frame types
0304    * @see TagConfig::quickAccessFrameOrder().
0305    */
0306   void setFrameOrder(const QList<int>& frameTypes);
0307 
0308 private:
0309   /**
0310    * Get the frame at a specific position in the collection.
0311    * @param row position of frame
0312    * @return iterator to frame
0313    */
0314   FrameCollection::iterator frameAt(int row) const;
0315 
0316   /**
0317    * Get the row corresponding to a frame iterator.
0318    * @param frameIt frame iterator
0319    * @return row number, number of rows if not found.
0320    */
0321   int rowOf(FrameCollection::iterator frameIt) const;
0322 
0323   /**
0324    * Resize the bit array with the frame selection to match the frames size.
0325    */
0326   void resizeFrameSelected();
0327 
0328   /**
0329    * Update the frame to row mapping.
0330    */
0331   void updateFrameRowMapping();
0332 
0333   QBitArray m_frameSelected;
0334   quint64 m_markedRows;
0335   quint64 m_changedFrames;
0336   QSet<QString> m_changedOtherFrameNames;
0337   FrameCollection m_frames;
0338   QVector<FrameCollection::iterator> m_frameOfRow;
0339   QHash<Frame::ExtendedType, QSet<QString>> m_differentValues;
0340   QVector<int> m_frameTypeSeqNr;
0341   CoreTaggedFileIconProvider* m_colorProvider;
0342   bool m_id3v1;
0343   bool m_emptyHeaders;
0344 };