File indexing completed on 2021-12-21 13:28:02
0001 /** 0002 * Copyright (C) 2004 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 #include "tagtransactionmanager.h" 0018 0019 #include <KMessageBox> 0020 #include <KLocalizedString> 0021 0022 #include <QAction> 0023 #include <QApplication> 0024 #include <QFileInfo> 0025 #include <QDir> 0026 #include <QGlobalStatic> 0027 0028 #include "playlistitem.h" 0029 #include "collectionlist.h" 0030 #include "juktag.h" 0031 #include "actioncollection.h" 0032 #include "juk_debug.h" 0033 0034 using ActionCollection::action; 0035 0036 Q_GLOBAL_STATIC(TagTransactionManager, g_tagManager) 0037 0038 TagTransactionManager *TagTransactionManager::instance() 0039 { 0040 return g_tagManager; 0041 } 0042 0043 TagTransactionAtom::TagTransactionAtom(PlaylistItem *item, Tag *tag) 0044 : m_item(item) 0045 , m_tag(tag) 0046 { 0047 } 0048 0049 void TagTransactionManager::changeTagOnItem(PlaylistItem *item, Tag *newTag) 0050 { 0051 if(!item) { 0052 qCWarning(JUK_LOG) << "Trying to change tag on null PlaylistItem.\n"; 0053 return; 0054 } 0055 0056 // Save the CollectionListItem, as it is the most likely to survive long 0057 // enough for the commit(). I should probably intercept the item deleted 0058 // signals from CollectionList to ensure that the commit list and the 0059 // playlists stay in sync. 0060 0061 m_list.emplace_back(item->collectionItem(), newTag); 0062 } 0063 0064 Tag *TagTransactionManager::duplicateTag(const Tag *tag, const QString &fileName) 0065 { 0066 Q_ASSERT(tag); 0067 0068 QString name = fileName.isEmpty() ? tag->fileName() : fileName; 0069 Tag *newTag = new Tag(*tag); 0070 0071 newTag->setFileName(name); 0072 return newTag; 0073 } 0074 0075 bool TagTransactionManager::commit() 0076 { 0077 m_undoList.clear(); 0078 bool result = processChangeList(); 0079 0080 m_list.clear(); 0081 return result; 0082 } 0083 0084 void TagTransactionManager::forget() 0085 { 0086 m_list.clear(); 0087 } 0088 0089 bool TagTransactionManager::undo() 0090 { 0091 qCDebug(JUK_LOG) << "Undoing " << m_undoList.size() << " changes.\n"; 0092 0093 forget(); // Scrap our old changes (although the list should be empty 0094 // anyways. 0095 0096 bool result = processChangeList(true); 0097 0098 m_undoList.clear(); 0099 action("edit_undo")->setEnabled(false); 0100 0101 return result; 0102 } 0103 0104 bool TagTransactionManager::renameFile(const QFileInfo &from, const QFileInfo &to) const 0105 { 0106 if(!QFileInfo(to.path()).isWritable() || !from.exists()) 0107 return false; 0108 0109 if(!to.exists() || 0110 KMessageBox::warningContinueCancel( 0111 static_cast<QWidget *>(parent()), 0112 i18n("This file already exists.\nDo you want to replace it?"), 0113 i18n("File Exists"),KGuiItem(i18n("Replace"))) == KMessageBox::Continue) 0114 { 0115 qCDebug(JUK_LOG) << "Renaming " << from.absoluteFilePath() << " to " << to.absoluteFilePath(); 0116 QDir currentDir; 0117 return currentDir.rename(from.absoluteFilePath(), to.absoluteFilePath()); 0118 } 0119 0120 return false; 0121 } 0122 0123 bool TagTransactionManager::processChangeList(bool undo) 0124 { 0125 TagAlterationList::const_iterator it, end; 0126 QStringList errorItems; 0127 0128 it = undo ? m_undoList.cbegin() : m_list.cbegin(); 0129 end = undo ? m_undoList.cend() : m_list.cend(); 0130 0131 emit signalAboutToModifyTags(); 0132 0133 for(; it != end; ++it) { 0134 PlaylistItem *item = (*it).item(); 0135 const Tag *tag = (*it).tag(); 0136 0137 QFileInfo newFile(tag->fileName()); 0138 0139 if(item->file().fileInfo().fileName() != newFile.fileName()) { 0140 if(!renameFile(item->file().fileInfo(), newFile)) { 0141 errorItems.append(item->text(1) + QString(" - ") + item->text(0)); 0142 continue; 0143 } 0144 } 0145 0146 if(tag->save()) { 0147 if(!undo) 0148 m_undoList.emplace_back(item, duplicateTag(item->file().tag())); 0149 0150 item->setFile(tag->fileName()); 0151 item->refreshFromDisk(); 0152 //FIXME repaint 0153 //item->repaint(); 0154 item->playlist()->playlistItemsChanged(); 0155 item->playlist()->update(); 0156 } 0157 else { 0158 Tag *errorTag = item->file().tag(); 0159 QString str = errorTag->artist() + " - " + errorTag->title(); 0160 0161 if(errorTag->artist().isEmpty()) 0162 str = errorTag->title(); 0163 0164 errorItems.append(str); 0165 } 0166 0167 qApp->processEvents(); 0168 } 0169 0170 undo ? m_undoList.clear() : m_list.clear(); 0171 if(!undo && !m_undoList.empty()) 0172 action("edit_undo")->setEnabled(true); 0173 else 0174 action("edit_undo")->setEnabled(false); 0175 0176 if(!errorItems.isEmpty()) 0177 KMessageBox::errorList(static_cast<QWidget *>(parent()), 0178 i18n("The following files were unable to be changed."), 0179 errorItems, 0180 i18n("Error")); 0181 0182 emit signalDoneModifyingTags(); 0183 return errorItems.isEmpty(); 0184 } 0185 0186 // vim: set et sw=4 tw=0 sta: