File indexing completed on 2024-05-12 16:45:39
0001 /*************************************************************************** 0002 Copyright (C) 2006-2009 Robby Stephenson <robby@periapsis.org> 0003 0004 ***************************************************************************/ 0005 0006 /*************************************************************************** 0007 * * 0008 * This program is free software; you can redistribute it and/or * 0009 * modify it under the terms of the GNU General Public License as * 0010 * published by the Free Software Foundation; either version 2 of * 0011 * the License or (at your option) version 3 or any later version * 0012 * accepted by the membership of KDE e.V. (or its successor approved * 0013 * by the membership of KDE e.V.), which shall act as a proxy * 0014 * defined in Section 14 of version 3 of the license. * 0015 * * 0016 * This program is distributed in the hope that it will be useful, * 0017 * but WITHOUT ANY WARRANTY; without even the implied warranty of * 0018 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * 0019 * GNU General Public License for more details. * 0020 * * 0021 * You should have received a copy of the GNU General Public License * 0022 * along with this program. If not, see <http://www.gnu.org/licenses/>. * 0023 * * 0024 ***************************************************************************/ 0025 0026 #include "collectioncommand.h" 0027 #include "../collection.h" 0028 #include "../collections/bibtexcollection.h" 0029 #include "../document.h" 0030 #include "../controller.h" 0031 #include "../tellico_debug.h" 0032 0033 #include <KLocalizedString> 0034 0035 #include <algorithm> 0036 0037 using Tellico::Command::CollectionCommand; 0038 0039 CollectionCommand::CollectionCommand(Mode mode_, Tellico::Data::CollPtr origColl_, Tellico::Data::CollPtr newColl_) 0040 : QUndoCommand() 0041 , m_mode(mode_) 0042 , m_origColl(origColl_) 0043 , m_newColl(newColl_) 0044 , m_cleanup(DoNothing) 0045 { 0046 #ifndef NDEBUG 0047 // just some sanity checking 0048 if(!m_origColl || !m_newColl) { 0049 myDebug() << "CommandTest: null collection pointer"; 0050 } 0051 if(m_origColl != Data::Document::self()->collection()) { 0052 myWarning() << "CollectionCommand: original collection is different than the current document"; 0053 } 0054 #endif 0055 switch(m_mode) { 0056 case Append: 0057 setText(i18n("Append Collection")); 0058 break; 0059 case Merge: 0060 setText(i18n("Merge Collection")); 0061 break; 0062 case Replace: 0063 setText(i18n("Replace Collection")); 0064 break; 0065 } 0066 } 0067 0068 CollectionCommand::~CollectionCommand() { 0069 switch(m_cleanup) { 0070 case ClearOriginal: 0071 m_origColl->clear(); 0072 break; 0073 case ClearNew: 0074 m_newColl->clear(); 0075 break; 0076 default: 0077 break; 0078 } 0079 } 0080 0081 void CollectionCommand::redo() { 0082 if(!m_origColl || !m_newColl) { 0083 return; 0084 } 0085 0086 m_structuralChange = false; 0087 switch(m_mode) { 0088 case Append: 0089 copyFields(); 0090 copyMacros(); 0091 { 0092 auto existingEntries = m_origColl->entryIdList(); 0093 Data::Document::self()->appendCollection(m_newColl, &m_structuralChange); 0094 auto allEntries = m_origColl->entryIdList(); 0095 0096 // keep track of which entries were added by the append operation 0097 // by taking difference of the entry id lists 0098 m_addedEntries.clear(); 0099 std::sort(existingEntries.begin(), existingEntries.end()); 0100 std::sort(allEntries.begin(), allEntries.end()); 0101 std::set_difference(allEntries.begin(), allEntries.end(), 0102 existingEntries.begin(), existingEntries.end(), 0103 std::back_inserter(m_addedEntries)); 0104 } 0105 Controller::self()->slotCollectionModified(m_origColl, m_structuralChange); 0106 break; 0107 0108 case Merge: 0109 copyFields(); 0110 copyMacros(); 0111 m_mergePair = Data::Document::self()->mergeCollection(m_newColl, &m_structuralChange); 0112 Controller::self()->slotCollectionModified(m_origColl, m_structuralChange); 0113 break; 0114 0115 case Replace: 0116 // replaceCollection() makes the URL = "Unknown" 0117 m_origURL = Data::Document::self()->URL(); 0118 Data::Document::self()->replaceCollection(m_newColl); 0119 Controller::self()->slotCollectionDeleted(m_origColl); 0120 Controller::self()->slotCollectionAdded(m_newColl); 0121 m_cleanup = ClearOriginal; 0122 break; 0123 } 0124 } 0125 0126 void CollectionCommand::undo() { 0127 if(!m_origColl || !m_newColl) { 0128 return; 0129 } 0130 0131 switch(m_mode) { 0132 case Append: 0133 unCopyMacros(); 0134 Data::Document::self()->unAppendCollection(m_origFields, m_addedEntries); 0135 Controller::self()->slotCollectionModified(m_origColl, m_structuralChange); 0136 break; 0137 0138 case Merge: 0139 unCopyMacros(); 0140 Data::Document::self()->unMergeCollection(m_origFields, m_mergePair); 0141 Controller::self()->slotCollectionModified(m_origColl, m_structuralChange); 0142 break; 0143 0144 case Replace: 0145 Data::Document::self()->replaceCollection(m_origColl); 0146 Data::Document::self()->setURL(m_origURL); 0147 Controller::self()->slotCollectionDeleted(m_newColl); 0148 Controller::self()->slotCollectionAdded(m_origColl); 0149 m_cleanup = ClearNew; 0150 break; 0151 } 0152 } 0153 0154 void CollectionCommand::copyFields() { 0155 m_origFields.clear(); 0156 foreach(Data::FieldPtr field, m_origColl->fields()) { 0157 m_origFields.append(Data::FieldPtr(new Data::Field(*field))); 0158 } 0159 } 0160 0161 void CollectionCommand::copyMacros() { 0162 // only applies to bibliographies 0163 if(m_origColl->type() != Data::Collection::Bibtex || 0164 m_newColl->type() != Data::Collection::Bibtex) { 0165 return; 0166 } 0167 m_addedMacros.clear(); 0168 // iterate over all macros in the new collection, check if they exist in the orig, add them if not 0169 // do not over write them 0170 // TODO: what to do if they clash? 0171 auto origColl = static_cast<Data::BibtexCollection*>(m_origColl.data()); 0172 const QMap<QString, QString> origMacros = origColl->macroList(); 0173 const QMap<QString, QString> newMacros = static_cast<Data::BibtexCollection*>(m_newColl.data())->macroList(); 0174 0175 auto i = newMacros.constBegin(); 0176 while(i != newMacros.constEnd()) { 0177 if(!origMacros.contains(i.key())) { 0178 origColl->addMacro(i.key(), i.value()); 0179 m_addedMacros.insert(i.key(), i.value()); 0180 } 0181 ++i; 0182 } 0183 0184 m_origPreamble = origColl->preamble(); 0185 if(m_origPreamble.isEmpty()) { 0186 origColl->setPreamble(static_cast<Data::BibtexCollection*>(m_newColl.data())->preamble()); 0187 } 0188 } 0189 0190 void CollectionCommand::unCopyMacros() { 0191 // only applies to bibliographies 0192 if(m_origColl->type() != Data::Collection::Bibtex) { 0193 return; 0194 } 0195 auto origColl = static_cast<Data::BibtexCollection*>(m_origColl.data()); 0196 // remove the macros added by the append/merge 0197 auto i = m_addedMacros.constBegin(); 0198 while(i != m_addedMacros.constEnd()) { 0199 origColl->removeMacro(i.key()); 0200 ++i; 0201 } 0202 origColl->setPreamble(m_origPreamble); 0203 }