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