File indexing completed on 2024-05-12 05:09:24
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 "../tellico_debug.h" 0031 0032 #include <KLocalizedString> 0033 0034 #include <algorithm> 0035 0036 using Tellico::Command::CollectionCommand; 0037 0038 CollectionCommand::CollectionCommand(Mode mode_, Tellico::Data::CollPtr origColl_, Tellico::Data::CollPtr newColl_) 0039 : QUndoCommand() 0040 , m_mode(mode_) 0041 , m_origColl(origColl_) 0042 , m_newColl(newColl_) 0043 , m_cleanup(DoNothing) 0044 { 0045 // just some sanity checking 0046 if(!m_origColl || !m_newColl) { 0047 myDebug() << "CommandTest: null collection pointer"; 0048 } 0049 if(m_origColl != Data::Document::self()->collection()) { 0050 myWarning() << "CollectionCommand: original collection is different than the current document"; 0051 } 0052 switch(m_mode) { 0053 case Append: 0054 setText(i18n("Append Collection")); 0055 break; 0056 case Merge: 0057 setText(i18n("Merge Collection")); 0058 break; 0059 case Replace: 0060 setText(i18n("Replace Collection")); 0061 break; 0062 } 0063 } 0064 0065 CollectionCommand::~CollectionCommand() { 0066 switch(m_cleanup) { 0067 case ClearOriginal: 0068 m_origColl->clear(); 0069 break; 0070 case ClearNew: 0071 m_newColl->clear(); 0072 break; 0073 default: 0074 break; 0075 } 0076 } 0077 0078 void CollectionCommand::redo() { 0079 if(!m_origColl || !m_newColl) { 0080 return; 0081 } 0082 0083 switch(m_mode) { 0084 case Append: 0085 copyFields(); 0086 copyMacros(); 0087 { 0088 auto existingEntries = m_origColl->entryIdList(); 0089 Data::Document::self()->appendCollection(m_newColl); 0090 auto allEntries = m_origColl->entryIdList(); 0091 0092 // keep track of which entries were added by the append operation 0093 // by taking difference of the entry id lists 0094 m_addedEntries.clear(); 0095 std::sort(existingEntries.begin(), existingEntries.end()); 0096 std::sort(allEntries.begin(), allEntries.end()); 0097 std::set_difference(allEntries.begin(), allEntries.end(), 0098 existingEntries.begin(), existingEntries.end(), 0099 std::back_inserter(m_addedEntries)); 0100 } 0101 break; 0102 0103 case Merge: 0104 copyFields(); 0105 copyMacros(); 0106 m_mergePair = Data::Document::self()->mergeCollection(m_newColl); 0107 break; 0108 0109 case Replace: 0110 // replaceCollection() makes the URL = "Unknown" 0111 m_origURL = Data::Document::self()->URL(); 0112 Data::Document::self()->replaceCollection(m_newColl); 0113 m_cleanup = ClearOriginal; 0114 break; 0115 } 0116 } 0117 0118 void CollectionCommand::undo() { 0119 if(!m_origColl || !m_newColl) { 0120 return; 0121 } 0122 0123 switch(m_mode) { 0124 case Append: 0125 unCopyMacros(); 0126 Data::Document::self()->unAppendCollection(m_origFields, m_addedEntries); 0127 break; 0128 0129 case Merge: 0130 unCopyMacros(); 0131 Data::Document::self()->unMergeCollection(m_origFields, m_mergePair); 0132 break; 0133 0134 case Replace: 0135 Data::Document::self()->replaceCollection(m_origColl); 0136 Data::Document::self()->setURL(m_origURL); 0137 m_cleanup = ClearNew; 0138 break; 0139 } 0140 } 0141 0142 void CollectionCommand::copyFields() { 0143 m_origFields.clear(); 0144 foreach(Data::FieldPtr field, m_origColl->fields()) { 0145 m_origFields.append(Data::FieldPtr(new Data::Field(*field))); 0146 } 0147 } 0148 0149 void CollectionCommand::copyMacros() { 0150 // only applies to bibliographies 0151 if(m_origColl->type() != Data::Collection::Bibtex || 0152 m_newColl->type() != Data::Collection::Bibtex) { 0153 return; 0154 } 0155 m_addedMacros.clear(); 0156 // iterate over all macros in the new collection, check if they exist in the orig, add them if not 0157 // do not over write them 0158 // TODO: what to do if they clash? 0159 auto origColl = static_cast<Data::BibtexCollection*>(m_origColl.data()); 0160 const QMap<QString, QString> origMacros = origColl->macroList(); 0161 const QMap<QString, QString> newMacros = static_cast<Data::BibtexCollection*>(m_newColl.data())->macroList(); 0162 0163 auto i = newMacros.constBegin(); 0164 while(i != newMacros.constEnd()) { 0165 if(!origMacros.contains(i.key())) { 0166 origColl->addMacro(i.key(), i.value()); 0167 m_addedMacros.insert(i.key(), i.value()); 0168 } 0169 ++i; 0170 } 0171 0172 m_origPreamble = origColl->preamble(); 0173 if(m_origPreamble.isEmpty()) { 0174 origColl->setPreamble(static_cast<Data::BibtexCollection*>(m_newColl.data())->preamble()); 0175 } 0176 } 0177 0178 void CollectionCommand::unCopyMacros() { 0179 // only applies to bibliographies 0180 if(m_origColl->type() != Data::Collection::Bibtex) { 0181 return; 0182 } 0183 auto origColl = static_cast<Data::BibtexCollection*>(m_origColl.data()); 0184 // remove the macros added by the append/merge 0185 auto i = m_addedMacros.constBegin(); 0186 while(i != m_addedMacros.constEnd()) { 0187 origColl->removeMacro(i.key()); 0188 ++i; 0189 } 0190 origColl->setPreamble(m_origPreamble); 0191 }