File indexing completed on 2023-05-30 11:30:53
0001 /** 0002 * Copyright (C) 2004, 2017 Michael Pyne <mpyne@kde.org> 0003 * 0004 * This program is free software; you can redistribute it and/or modify it under 0005 * the terms of the GNU General Public License as published by the Free Software 0006 * Foundation; either version 2 of the License, or (at your option) any later 0007 * version. 0008 * 0009 * This program is distributed in the hope that it will be useful, but WITHOUT ANY 0010 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A 0011 * PARTICULAR PURPOSE. See the GNU General Public License for more details. 0012 * 0013 * You should have received a copy of the GNU General Public License along with 0014 * this program. If not, see <http://www.gnu.org/licenses/>. 0015 */ 0016 0017 #ifndef TAGTRANSACTIONMANAGER_H 0018 #define TAGTRANSACTIONMANAGER_H 0019 0020 #include <QObject> 0021 0022 #include <memory> 0023 #include <vector> 0024 0025 #include "juktag.h" 0026 0027 class PlaylistItem; 0028 class QWidget; 0029 class QFileInfo; 0030 0031 using std::unique_ptr; 0032 0033 /** 0034 * Class to encapsulate a change to the tag, and optionally the file name, of 0035 * a PlaylistItem. 0036 * 0037 * @author Michael Pyne <mpyne@kde.org> 0038 * @see TagTransactionManager 0039 */ 0040 struct TagTransactionAtom 0041 { 0042 public: 0043 /** 0044 * Creates an atom detailing a change made by \p tag to \p item. 0045 * 0046 * @param item The PlaylistItem to change. 0047 * @param tag Contains the new tag to apply to item. 0048 */ 0049 TagTransactionAtom(PlaylistItem *item, Tag *tag); 0050 0051 PlaylistItem *item() const { return m_item; } 0052 const Tag *tag() const { return m_tag.get(); } 0053 0054 PlaylistItem *m_item; 0055 unique_ptr<Tag> m_tag; 0056 }; 0057 0058 // Qt's containers don't play well with std::unique_ptr, but being able to use 0059 // unique_ptr avoids a bunch of custom code on my part. 0060 using TagAlterationList = std::vector<TagTransactionAtom>; 0061 0062 /** 0063 * This class manages alterations of a group of PlaylistItem's FileHandles. What this 0064 * means in practice is that you will use this class to change the tags and/or 0065 * filename of a PlaylistItem. 0066 * 0067 * This class supports a limited transactional interface. Once you commit a 0068 * group of changes, you can call the undo() method to revert back to the way 0069 * things were (except possibly for file renames). You can call forget() to 0070 * forget a series of changes as well. 0071 * 0072 * @author Michael Pyne <mpyne@kde.org> 0073 */ 0074 class TagTransactionManager : public QObject 0075 { 0076 Q_OBJECT 0077 0078 public: 0079 /** 0080 * Returns the global TagTransactionManager instance. 0081 * 0082 * @return The global TagTransactionManager. 0083 */ 0084 static TagTransactionManager *instance(); 0085 0086 /** 0087 * Adds a change to the list of changes to apply. Internally this 0088 * function extracts the CollectionListItem of @p item, and uses that 0089 * instead, so there is no need to do so yourself. 0090 * 0091 * @param item The PlaylistItem to change. 0092 * @param newTag The Tag containing the changed data. 0093 */ 0094 void changeTagOnItem(PlaylistItem *item, Tag *newTag); 0095 0096 /** 0097 * Convenience function to duplicate a Tag object, since the Tag 0098 * object doesn't have a decent copy constructor. 0099 * 0100 * @param tag The Tag to duplicate. 0101 * @param fileName The filename to assign to the tag. If an empty QString 0102 * (the default) is passed, the filename of the existing tag is 0103 * used. 0104 * @bug Tag should have a correct copy ctor and assignment operator. 0105 * @return The duplicate Tag. 0106 */ 0107 static Tag *duplicateTag(const Tag *tag, const QString &fileName = QString()); 0108 0109 /** 0110 * Commits the changes to the PlaylistItems. It is important that the 0111 * PlaylistItems still exist when you call this function, although this 0112 * shouldn't be a problem in practice. After altering the tags, and 0113 * renaming the files if necessary, you can call undo() to back out the 0114 * changes. 0115 * 0116 * If any errors have occurred, the user will be notified with a dialog 0117 * box, and those files which were unabled to be altered will be excluded 0118 * from the undo set. 0119 * 0120 * @return true if no errors occurred, false otherwise. 0121 */ 0122 bool commit(); 0123 0124 /** 0125 * Clears the current update list. The current undo list is unaffected. 0126 */ 0127 void forget(); 0128 0129 /** 0130 * Undoes the changes caused by commit(). Like commit(), if any errors 0131 * occur changing the state back (for example, it may be impossible to 0132 * rename a file back to its original name), the user will be shown notified 0133 * via a dialog box. 0134 * 0135 * After performing the undo operation, it is impossible to call undo() 0136 * again on the same set of files. Namely, you can't repeatedly call 0137 * undo() to switch between two different file states. 0138 * 0139 * @return true if no errors occurred, false otherwise. 0140 */ 0141 bool undo(); 0142 0143 signals: 0144 void signalAboutToModifyTags(); 0145 void signalDoneModifyingTags(); 0146 0147 private: 0148 /** 0149 * Renames the file identified by @p from to have the name given by @p to, 0150 * prompting the user to confirm if necessary. 0151 * 0152 * @param from QFileInfo with the filename of the original file. 0153 * @param to QFileInfo with the new filename. 0154 * @return true if no errors occurred, false otherwise. 0155 */ 0156 bool renameFile(const QFileInfo &from, const QFileInfo &to) const; 0157 0158 /** 0159 * Used internally by commit() and undo(). Performs the work of updating 0160 * the PlaylistItems and then updating the various GUI elements that need 0161 * to be updated. 0162 * 0163 * @param undo true if operating in undo mode, false otherwise. 0164 */ 0165 bool processChangeList(bool undo = false); 0166 0167 TagAlterationList m_list; ///< holds a list of changes to commit 0168 TagAlterationList m_undoList; ///< holds a list of changes to undo 0169 }; 0170 0171 #endif /* TAGTRANSACTIONMANAGER_H */ 0172 0173 // vim: set et sw=4 tw=0 sta: