File indexing completed on 2024-05-19 04:56:08
0001 /** 0002 * \file taggedfileselection.h 0003 * Information about selected tagged files. 0004 * 0005 * \b Project: Kid3 0006 * \author Urs Fleisch 0007 * \date 19 Jun 2014 0008 * 0009 * Copyright (C) 2014-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 <QObject> 0030 #include "frame.h" 0031 #include "kid3api.h" 0032 0033 class FrameTableModel; 0034 class TaggedFile; 0035 class TaggedFileSelectionTagContext; 0036 0037 /** 0038 * Information about selected tagged files. 0039 */ 0040 class KID3_CORE_EXPORT TaggedFileSelection : public QObject { 0041 Q_OBJECT 0042 /** true if no tagged file is selected. */ 0043 Q_PROPERTY(bool empty READ isEmpty NOTIFY emptyChanged) 0044 /** true if exactly one file is selected. */ 0045 Q_PROPERTY(bool singleFileSelected READ isSingleFileSelected 0046 NOTIFY singleFileSelectedChanged) 0047 /** true if single file selected and filename was changed. */ 0048 Q_PROPERTY(bool fileNameChanged READ isFilenameChanged 0049 NOTIFY singleFileChanged) 0050 /** File name if single file selected, else null string. */ 0051 Q_PROPERTY(QString fileName READ getFilename WRITE setFilename 0052 NOTIFY singleFileChanged) 0053 /** Absolute file path if single file selected, else null string. */ 0054 Q_PROPERTY(QString filePath READ getFilePath NOTIFY singleFileChanged) 0055 /** Detail information if single file selected, else null string. */ 0056 Q_PROPERTY(QString detailInfo READ getDetailInfo NOTIFY singleFileChanged) 0057 /** 0058 * Format of tag 1 if single file selected, else null string. 0059 * @deprecated For compatibility with old scripts, 0060 * use tag(Frame.Tag_1).tagFormat instead. 0061 */ 0062 Q_PROPERTY(QString tagFormatV1 READ getTagFormatV1 NOTIFY singleFileChanged) 0063 /** 0064 * Format of tag 2 if single file selected, else null string. 0065 * @deprecated For compatibility with old scripts, 0066 * use tag(Frame.Tag_2).tagFormat instead. 0067 */ 0068 Q_PROPERTY(QString tagFormatV2 READ getTagFormatV2 NOTIFY singleFileChanged) 0069 /** Picture data, empty if not available.*/ 0070 Q_PROPERTY(QByteArray picture READ getPicture NOTIFY singleFileChanged) 0071 public: 0072 /** 0073 * Constructor. 0074 * @param framesModel frame table models for all tags, Frame::Tag_NumValues 0075 * elements 0076 * @param parent parent object 0077 */ 0078 TaggedFileSelection(FrameTableModel* framesModel[], QObject* parent = nullptr); 0079 0080 /** 0081 * Destructor. 0082 */ 0083 ~TaggedFileSelection() override = default; 0084 0085 /** 0086 * Start adding tagged files to selection. 0087 * Has to be called before adding the first file using addTaggedFile(). 0088 */ 0089 void beginAddTaggedFiles(); 0090 0091 /** 0092 * End adding tagged files to selection. 0093 * Has to be called after adding the last file using addTaggedFile(). 0094 */ 0095 void endAddTaggedFiles(); 0096 0097 /** 0098 * Add a tagged file to the selection. 0099 * @param taggedFile tagged file 0100 */ 0101 void addTaggedFile(TaggedFile* taggedFile); 0102 0103 /** 0104 * Check if a single file is selected. 0105 * @return if a single file is selected, this tagged file, else 0. 0106 */ 0107 TaggedFile* singleFile() const { return m_state.singleFile(); } 0108 0109 /** 0110 * Check if selection is empty. 0111 * @return true if no tagged file is selected. 0112 */ 0113 bool isEmpty() const { return m_state.isEmpty(); } 0114 0115 /** 0116 * Check if any of the selected files has a tag. 0117 * @param tagNr tag number 0118 * @return true if any of the selected files has a tag. 0119 */ 0120 bool hasTag(Frame::TagNumber tagNr) const { return m_state.hasTag(tagNr); } 0121 0122 /** 0123 * Check if a single file is selected. 0124 * @return true if exactly one file is selected. 0125 */ 0126 bool isSingleFileSelected() const { return m_state.isSingleFileSelected(); } 0127 0128 /** 0129 * Check if tag is used. 0130 * @param tagNr tag number 0131 * @return true if any selected file supports tag. 0132 */ 0133 bool isTagUsed(Frame::TagNumber tagNr) const { return m_state.isTagUsed(tagNr); } 0134 0135 /** 0136 * Get file name. 0137 * @return file name if single file selected, else null string. 0138 */ 0139 QString getFilename() const; 0140 0141 /** 0142 * Set file name if single file selected. 0143 * @param fn file name 0144 */ 0145 void setFilename(const QString& fn); 0146 0147 /** 0148 * Get file path. 0149 * @return absolute file path if single file selected, else null string. 0150 */ 0151 QString getFilePath() const; 0152 0153 /** 0154 * Get string representation of detail information. 0155 * @return information summary as string if single file else null string. 0156 */ 0157 QString getDetailInfo() const; 0158 0159 /** 0160 * Get the format of tag. 0161 * @param tagNr tag number 0162 * @return string describing format of tag 2 if single file selected, 0163 * else null string. 0164 */ 0165 QString getTagFormat(Frame::TagNumber tagNr) const; 0166 0167 /** 0168 * Get context for tag. 0169 * @param tagNr tag number 0170 * @return tag context. 0171 */ 0172 Q_INVOKABLE TaggedFileSelectionTagContext* tag(Frame::TagNumber tagNr) const { 0173 return m_tagContext[tagNr]; 0174 } 0175 0176 /** 0177 * Check if filename is changed. 0178 * @return true if single file selected and filename was changed. 0179 */ 0180 bool isFilenameChanged() const; 0181 0182 /** 0183 * Get data from a picture frame. 0184 * @return picture data, empty if not available. 0185 */ 0186 QByteArray getPicture() const; 0187 0188 /** 0189 * Replace codes in format string with information from the tags. 0190 * @param tagVersion tag version 0191 * @param fmt format string 0192 * @return string with format codes replaced. 0193 */ 0194 Q_INVOKABLE QString formatString(Frame::TagVersion tagVersion, 0195 const QString& fmt) const; 0196 0197 /** 0198 * Select changed frames in the tables if multiple files are selected. 0199 */ 0200 void selectChangedFrames(); 0201 0202 /** 0203 * Clear frame collection in frame models not used by current selection. 0204 */ 0205 void clearUnusedFrames(); 0206 0207 signals: 0208 /** 0209 * Emitted when empty changed. 0210 */ 0211 void emptyChanged(bool empty); 0212 0213 /** 0214 * Emitted when singleFileSelected changed. 0215 */ 0216 void singleFileSelectedChanged(bool single); 0217 0218 /** 0219 * Emitted when the single file may have changed. 0220 * This is not accurate, because the file itself may change without notice. 0221 * Therefore this signal is emitted at the end of endAddTaggedFiles() unless 0222 * no single file exists in the current and the last state. 0223 */ 0224 void singleFileChanged(); 0225 0226 /** 0227 * Emitted when the file name is modified. 0228 */ 0229 void fileNameModified(); 0230 0231 private: 0232 struct State { 0233 State() : m_singleFile(nullptr), m_fileCount(0) { 0234 FOR_ALL_TAGS(tagNr) { 0235 m_tagSupportedCount[tagNr] = 0; 0236 m_hasTag[tagNr] = false; 0237 } 0238 } 0239 0240 TaggedFile* singleFile() const { return m_singleFile; } 0241 bool isEmpty() const { return m_fileCount == 0; } 0242 bool hasTag(Frame::TagNumber tagNr) const { return m_hasTag[tagNr]; } 0243 bool isSingleFileSelected() const { return m_singleFile != nullptr; } 0244 bool isTagUsed(Frame::TagNumber tagNr) const { return m_tagSupportedCount[tagNr] > 0; } 0245 0246 /** If a single file is selected, this tagged file, else 0 */ 0247 TaggedFile* m_singleFile; 0248 /** Number of selected files */ 0249 int m_fileCount; 0250 /** Number of selected files which support tag 1 */ 0251 int m_tagSupportedCount[Frame::Tag_NumValues]; 0252 /** true if any of the selected files has a tag */ 0253 bool m_hasTag[Frame::Tag_NumValues]; 0254 }; 0255 0256 QString getTagFormatV1() const; 0257 QString getTagFormatV2() const; 0258 0259 FrameTableModel* m_framesModel[Frame::Tag_NumValues]; 0260 TaggedFileSelectionTagContext* m_tagContext[Frame::Tag_NumValues]; 0261 State m_state; 0262 State m_lastState; 0263 }; 0264 0265 /** 0266 * Facade to have a uniform interface for different tags. 0267 */ 0268 class KID3_CORE_EXPORT TaggedFileSelectionTagContext : public QObject { 0269 Q_OBJECT 0270 /** true if any of the selected files has a tag. */ 0271 Q_PROPERTY(bool hasTag READ hasTag NOTIFY hasTagChanged) 0272 /** true if any selected file supports the tag. */ 0273 Q_PROPERTY(bool tagUsed READ isTagUsed NOTIFY tagUsedChanged) 0274 /** Format of tag if single file selected, else null string. */ 0275 Q_PROPERTY(QString tagFormat READ tagFormat NOTIFY tagFormatChanged) 0276 public: 0277 /** 0278 * Constructor. 0279 * @param selection tagged file selection 0280 * @param tagNr tag number 0281 */ 0282 TaggedFileSelectionTagContext(TaggedFileSelection* selection, 0283 Frame::TagNumber tagNr) 0284 : QObject(selection), m_selection(selection), m_tagNr(tagNr), 0285 m_tagVersion(Frame::tagVersionFromNumber(tagNr)) { 0286 } 0287 0288 signals: 0289 /** 0290 * Emitted when hasTag changed. 0291 */ 0292 void hasTagChanged(bool hasTag); 0293 0294 /** 0295 * Emitted when tagUsed changed. 0296 */ 0297 void tagUsedChanged(bool used); 0298 0299 /** 0300 * Emitted when tagFormat may have changed. 0301 */ 0302 void tagFormatChanged(); 0303 0304 private: 0305 friend class TaggedFileSelection; 0306 0307 bool hasTag() const { return m_selection->hasTag(m_tagNr); } 0308 bool isTagUsed() const { return m_selection->isTagUsed(m_tagNr); } 0309 QString tagFormat() const { return m_selection->getTagFormat(m_tagNr); } 0310 0311 TaggedFileSelection* m_selection; 0312 const Frame::TagNumber m_tagNr; 0313 const Frame::TagVersion m_tagVersion; 0314 };