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: