File indexing completed on 2024-04-21 05:43:03
0001 /* 0002 SPDX-FileCopyrightText: 2001-2005, 2009 Otto Bruggeman <bruggie@gmail.com> 0003 SPDX-FileCopyrightText: 2001-2003 John Firebaugh <jfirebaugh@kde.org> 0004 SPDX-FileCopyrightText: 2007-2011 Kevin Kofler <kevin.kofler@chello.at> 0005 0006 SPDX-License-Identifier: GPL-2.0-or-later 0007 */ 0008 0009 #include "komparenavtreepart.h" 0010 0011 #include <QDebug> 0012 #include <QTreeWidgetItemIterator> 0013 0014 #include <KLocalizedString> 0015 #include <KPluginMetaData> 0016 #include <KPluginFactory> 0017 0018 #include <KompareDiff2/Difference> 0019 #include <KompareDiff2/DiffModel> 0020 #include <KompareDiff2/DiffModelList> 0021 #include <KompareDiff2/ModelList> 0022 0023 #include <komparenavviewdebug.h> 0024 0025 #define COL_SOURCE 0 0026 #define COL_DESTINATION 1 0027 #define COL_DIFFERENCE 2 0028 0029 using namespace KompareDiff2; 0030 0031 KompareNavTreePart::KompareNavTreePart(QWidget* parentWidget, QObject* parent, 0032 const KPluginMetaData& metaData, const QVariantList&) 0033 : KParts::ReadOnlyPart(parent, metaData), 0034 m_splitter(nullptr), 0035 m_modelList(nullptr), 0036 m_srcDirTree(nullptr), 0037 m_destDirTree(nullptr), 0038 m_fileList(nullptr), 0039 m_changesList(nullptr), 0040 m_srcRootItem(nullptr), 0041 m_destRootItem(nullptr), 0042 m_selectedModel(nullptr), 0043 m_selectedDifference(nullptr), 0044 m_source(), 0045 m_destination(), 0046 m_info(nullptr) 0047 { 0048 m_splitter = new QSplitter(Qt::Horizontal, parentWidget); 0049 0050 setWidget(m_splitter); 0051 0052 m_srcDirTree = new QTreeWidget(m_splitter); 0053 m_srcDirTree->setHeaderLabel(i18nc("@title:column", "Source Folder")); 0054 m_srcDirTree->setRootIsDecorated(false); 0055 m_srcDirTree->setSortingEnabled(true); 0056 m_srcDirTree->sortByColumn(0, Qt::AscendingOrder); 0057 0058 m_destDirTree = new QTreeWidget(m_splitter); 0059 m_destDirTree->setHeaderLabel(i18nc("@title:column", "Destination Folder")); 0060 m_destDirTree->setRootIsDecorated(false); 0061 m_destDirTree->setSortingEnabled(true); 0062 m_destDirTree->sortByColumn(0, Qt::AscendingOrder); 0063 0064 m_fileList = new QTreeWidget(m_splitter); 0065 m_fileList->setHeaderLabels(QStringList { 0066 i18nc("@title:column", "Source File"), 0067 i18nc("@title:column", "Destination File") 0068 } ); 0069 m_fileList->setAllColumnsShowFocus(true); 0070 m_fileList->setRootIsDecorated(false); 0071 m_fileList->setSortingEnabled(true); 0072 m_fileList->sortByColumn(0, Qt::AscendingOrder); 0073 0074 m_changesList = new QTreeWidget(m_splitter); 0075 m_changesList->setHeaderLabels(QStringList { 0076 i18nc("@title:column", "Source Line"), 0077 i18nc("@title:column", "Destination Line"), 0078 i18nc("@title:column", "Difference"), 0079 } ); 0080 m_changesList->setAllColumnsShowFocus(true); 0081 m_changesList->setRootIsDecorated(false); 0082 m_changesList->setSortingEnabled(true); 0083 m_changesList->sortByColumn(0, Qt::AscendingOrder); 0084 0085 connect(m_srcDirTree, &QTreeWidget::currentItemChanged, 0086 this, &KompareNavTreePart::slotSrcDirTreeSelectionChanged); 0087 connect(m_destDirTree, &QTreeWidget::currentItemChanged, 0088 this, &KompareNavTreePart::slotDestDirTreeSelectionChanged); 0089 connect(m_fileList, &QTreeWidget::currentItemChanged, 0090 this, &KompareNavTreePart::slotFileListSelectionChanged); 0091 connect(m_changesList, &QTreeWidget::currentItemChanged, 0092 this, &KompareNavTreePart::slotChangesListSelectionChanged); 0093 } 0094 0095 KompareNavTreePart::~KompareNavTreePart() 0096 { 0097 m_modelList = nullptr; 0098 m_selectedModel = nullptr; 0099 m_selectedDifference = nullptr; 0100 } 0101 0102 void KompareNavTreePart::slotKompareInfo(KompareDiff2::Info* info) 0103 { 0104 m_info = info; 0105 } 0106 0107 void KompareNavTreePart::slotModelsChanged(const DiffModelList* modelList) 0108 { 0109 qCDebug(KOMPARENAVVIEW) << "Models (" << modelList << ") have changed... scanning the models... " ; 0110 0111 if (modelList) 0112 { 0113 m_modelList = modelList; 0114 m_srcDirTree->clear(); 0115 m_destDirTree->clear(); 0116 m_fileList->clear(); 0117 m_changesList->clear(); 0118 buildTreeInMemory(); 0119 } 0120 else 0121 { 0122 m_modelList = modelList; 0123 m_srcDirTree->clear(); 0124 m_destDirTree->clear(); 0125 m_fileList->clear(); 0126 m_changesList->clear(); 0127 } 0128 } 0129 0130 void KompareNavTreePart::buildTreeInMemory() 0131 { 0132 qCDebug(KOMPARENAVVIEW) << "BuildTreeInMemory called" ; 0133 0134 if (m_modelList->count() == 0) 0135 { 0136 qCDebug(KOMPARENAVVIEW) << "No models... weird shit..." ; 0137 return; // avoids a crash on clear() 0138 } 0139 0140 if (!m_info) 0141 { 0142 qCDebug(KOMPARENAVVIEW) << "No Info... weird shit..." ; 0143 return; 0144 } 0145 0146 QString srcBase; 0147 QString destBase; 0148 0149 DiffModel* model; 0150 model = m_modelList->first(); 0151 m_selectedModel = nullptr; 0152 0153 switch (m_info->mode) 0154 { 0155 case KompareDiff2::ShowingDiff: 0156 // BUG: 107489 No common root because it is a multi directory relative path diff 0157 // We need to detect this and create a different rootitem / or so or should we always add this? 0158 // Trouble we run into is that the directories do not start with a / 0159 // so we have an unknown top root dir 0160 // Thinking some more about it i guess it is best to use "" as base and simply show some string 0161 // like Unknown filesystem path as root text but only in the case of dirs starting without a / 0162 srcBase = model->sourcePath(); 0163 destBase = model->destinationPath(); 0164 // FIXME: these tests will not work on windows, we need something else 0165 if (srcBase[0] != QLatin1Char('/')) 0166 srcBase.clear(); 0167 if (destBase[0] != QLatin1Char('/')) 0168 destBase.clear(); 0169 break; 0170 case KompareDiff2::ComparingFiles: 0171 srcBase = model->sourcePath(); 0172 destBase = model->destinationPath(); 0173 break; 0174 case KompareDiff2::ComparingDirs: 0175 srcBase = m_info->localSource; 0176 if (!srcBase.endsWith(QLatin1Char('/'))) 0177 srcBase += QLatin1Char('/'); 0178 destBase = m_info->localDestination; 0179 if (!destBase.endsWith(QLatin1Char('/'))) 0180 destBase += QLatin1Char('/'); 0181 break; 0182 case KompareDiff2::BlendingFile: 0183 case KompareDiff2::BlendingDir: 0184 default: 0185 qCDebug(KOMPARENAVVIEW) << "Oops needs to implement this..." ; 0186 } 0187 0188 // qCDebug(KOMPARENAVVIEW) << "srcBase = " << srcBase ; 0189 // qCDebug(KOMPARENAVVIEW) << "destBase = " << destBase ; 0190 0191 m_srcRootItem = new KDirLVI(m_srcDirTree, srcBase); 0192 m_destRootItem = new KDirLVI(m_destDirTree, destBase); 0193 0194 QString srcPath; 0195 QString destPath; 0196 0197 // Create the tree from the models 0198 DiffModelListConstIterator modelIt = m_modelList->begin(); 0199 DiffModelListConstIterator mEnd = m_modelList->end(); 0200 0201 for (; modelIt != mEnd; ++modelIt) 0202 { 0203 model = *modelIt; 0204 srcPath = model->sourcePath(); 0205 destPath = model->destinationPath(); 0206 0207 qCDebug(KOMPARENAVVIEW) << "srcPath = " << srcPath ; 0208 qCDebug(KOMPARENAVVIEW) << "destPath = " << destPath ; 0209 m_srcRootItem->addModel(srcPath, model, &m_modelToSrcDirItemDict); 0210 m_destRootItem->addModel(destPath, model, &m_modelToDestDirItemDict); 0211 } 0212 // m_srcDirTree->setSelected( m_srcDirTree->firstChild(), true ); 0213 } 0214 0215 void KompareNavTreePart::buildDirectoryTree() 0216 { 0217 // FIXME: afaict this can be deleted 0218 // qCDebug(KOMPARENAVVIEW) << "BuildDirTree called" ; 0219 } 0220 0221 QString KompareNavTreePart::compareFromEndAndReturnSame( 0222 const QString& string1, 0223 const QString& string2) 0224 { 0225 QString result; 0226 0227 int srcLen = string1.length(); 0228 int destLen = string2.length(); 0229 0230 while (srcLen != 0 && destLen != 0) 0231 { 0232 if (string1[--srcLen] == string2[--destLen]) 0233 result.prepend(string1[srcLen]); 0234 else 0235 break; 0236 } 0237 0238 if (srcLen != 0 && destLen != 0 && result.startsWith(QLatin1Char('/'))) 0239 result = result.remove(0, 1); // strip leading /, we need it later 0240 0241 return result; 0242 } 0243 0244 void KompareNavTreePart::slotSetSelection(const DiffModel* model, const Difference* diff) 0245 { 0246 qCDebug(KOMPARENAVVIEW) << "KompareNavTreePart::slotSetSelection model = " << model << ", diff = " << diff ; 0247 if (model == m_selectedModel) 0248 { 0249 // model is the same, so no need to update that... 0250 if (diff != m_selectedDifference) 0251 { 0252 m_selectedDifference = diff; 0253 setSelectedDifference(diff); 0254 } 0255 return; 0256 } 0257 0258 // model is different so we need to find the right dirs, file and changeitems to select 0259 // if m_selectedModel == NULL then everything needs to be done as well 0260 if (!m_selectedModel || model->sourcePath() != m_selectedModel->sourcePath()) 0261 { // dirs are different, so we need to update the dirviews as well 0262 m_selectedModel = model; 0263 m_selectedDifference = diff; 0264 0265 setSelectedDir(model); 0266 setSelectedFile(model); 0267 setSelectedDifference(diff); 0268 return; 0269 } 0270 0271 if (!m_selectedModel || model->sourceFile() != m_selectedModel->sourceFile()) 0272 { 0273 m_selectedModel = model; 0274 setSelectedFile(model); 0275 0276 m_selectedDifference = diff; 0277 setSelectedDifference(diff); 0278 } 0279 } 0280 0281 void KompareNavTreePart::setSelectedDir(const DiffModel* model) 0282 { 0283 KDirLVI* currentDir; 0284 currentDir = m_modelToSrcDirItemDict[ model ]; 0285 qCDebug(KOMPARENAVVIEW) << "Manually setting selection in srcdirtree with currentDir = " << currentDir ; 0286 m_srcDirTree->blockSignals(true); 0287 m_srcDirTree->setCurrentItem(currentDir); 0288 m_srcDirTree->scrollToItem(currentDir); 0289 m_srcDirTree->blockSignals(false); 0290 0291 currentDir = m_modelToDestDirItemDict[ model ]; 0292 qCDebug(KOMPARENAVVIEW) << "Manually setting selection in destdirtree with currentDir = " << currentDir ; 0293 m_destDirTree->blockSignals(true); 0294 m_destDirTree->setCurrentItem(currentDir); 0295 m_destDirTree->scrollToItem(currentDir); 0296 m_destDirTree->blockSignals(false); 0297 0298 m_fileList->blockSignals(true); 0299 currentDir->fillFileList(m_fileList, &m_modelToFileItemDict); 0300 m_fileList->blockSignals(false); 0301 } 0302 0303 void KompareNavTreePart::setSelectedFile(const DiffModel* model) 0304 { 0305 KFileLVI* currentFile; 0306 currentFile = m_modelToFileItemDict[ model ]; 0307 qCDebug(KOMPARENAVVIEW) << "Manually setting selection in filelist" ; 0308 m_fileList->blockSignals(true); 0309 m_fileList->setCurrentItem(currentFile); 0310 m_fileList->scrollToItem(currentFile); 0311 m_fileList->blockSignals(false); 0312 0313 m_changesList->blockSignals(true); 0314 currentFile->fillChangesList(m_changesList, &m_diffToChangeItemDict); 0315 m_changesList->blockSignals(false); 0316 } 0317 0318 void KompareNavTreePart::setSelectedDifference(const Difference* diff) 0319 { 0320 KChangeLVI* currentDiff; 0321 currentDiff = m_diffToChangeItemDict[ diff ]; 0322 qCDebug(KOMPARENAVVIEW) << "Manually setting selection in changeslist to " << currentDiff ; 0323 m_changesList->blockSignals(true); 0324 m_changesList->setCurrentItem(currentDiff); 0325 m_changesList->scrollToItem(currentDiff); 0326 m_changesList->blockSignals(false); 0327 } 0328 0329 void KompareNavTreePart::slotSetSelection(const Difference* diff) 0330 { 0331 // qCDebug(KOMPARENAVVIEW) << "Scotty i need more power !!" ; 0332 if (m_selectedDifference != diff) 0333 { 0334 // qCDebug(KOMPARENAVVIEW) << "But sir, i am giving you all she's got" ; 0335 m_selectedDifference = diff; 0336 setSelectedDifference(diff); 0337 } 0338 } 0339 0340 void KompareNavTreePart::slotSrcDirTreeSelectionChanged(QTreeWidgetItem* item) 0341 { 0342 if (!item) 0343 return; 0344 0345 qCDebug(KOMPARENAVVIEW) << "Sent by the sourceDirectoryTree with item = " << item ; 0346 m_srcDirTree->scrollToItem(item); 0347 KDirLVI* dir = static_cast<KDirLVI*>(item); 0348 // order the dest tree view to set its selected item to the same as here 0349 QString path; 0350 // We start with an empty path and after the call path contains the full path 0351 path = dir->fullPath(path); 0352 KDirLVI* selItem = m_destRootItem->setSelected(path); 0353 m_destDirTree->blockSignals(true); 0354 m_destDirTree->setCurrentItem(selItem); 0355 m_destDirTree->scrollToItem(selItem); 0356 m_destDirTree->blockSignals(false); 0357 // fill the changes list 0358 dir->fillFileList(m_fileList, &m_modelToFileItemDict); 0359 } 0360 0361 void KompareNavTreePart::slotDestDirTreeSelectionChanged(QTreeWidgetItem* item) 0362 { 0363 if (!item) 0364 return; 0365 0366 qCDebug(KOMPARENAVVIEW) << "Sent by the destinationDirectoryTree with item = " << item ; 0367 m_destDirTree->scrollToItem(item); 0368 KDirLVI* dir = static_cast<KDirLVI*>(item); 0369 // order the src tree view to set its selected item to the same as here 0370 QString path; 0371 // We start with an empty path and after the call path contains the full path 0372 path = dir->fullPath(path); 0373 KDirLVI* selItem = m_srcRootItem->setSelected(path); 0374 m_srcDirTree->blockSignals(true); 0375 m_srcDirTree->setCurrentItem(selItem); 0376 m_srcDirTree->scrollToItem(selItem); 0377 m_srcDirTree->blockSignals(false); 0378 // fill the changes list 0379 dir->fillFileList(m_fileList, &m_modelToFileItemDict); 0380 } 0381 0382 void KompareNavTreePart::slotFileListSelectionChanged(QTreeWidgetItem* item) 0383 { 0384 if (!item) 0385 return; 0386 0387 qCDebug(KOMPARENAVVIEW) << "Sent by the fileList with item = " << item ; 0388 0389 KFileLVI* file = static_cast<KFileLVI*>(item); 0390 m_selectedModel = file->model(); 0391 m_changesList->blockSignals(true); 0392 file->fillChangesList(m_changesList, &m_diffToChangeItemDict); 0393 m_changesList->blockSignals(false); 0394 0395 if (m_changesList->currentItem()) 0396 { 0397 // FIXME: This is ugly... 0398 m_selectedDifference = (static_cast<KChangeLVI*>(m_changesList->currentItem()))->difference(); 0399 } 0400 0401 Q_EMIT selectionChanged(m_selectedModel, m_selectedDifference); 0402 } 0403 0404 void KompareNavTreePart::slotChangesListSelectionChanged(QTreeWidgetItem* item) 0405 { 0406 if (!item) 0407 return; 0408 0409 qCDebug(KOMPARENAVVIEW) << "Sent by the changesList" ; 0410 0411 KChangeLVI* change = static_cast<KChangeLVI*>(item); 0412 m_selectedDifference = change->difference(); 0413 0414 Q_EMIT selectionChanged(m_selectedDifference); 0415 } 0416 0417 void KompareNavTreePart::slotApplyDifference(bool /*apply*/) 0418 { 0419 KChangeLVI* clvi = m_diffToChangeItemDict[m_selectedDifference]; 0420 if (clvi) 0421 clvi->setDifferenceText(); 0422 } 0423 0424 void KompareNavTreePart::slotApplyAllDifferences(bool /*apply*/) 0425 { 0426 QHash<const KompareDiff2::Difference*, KChangeLVI*>::ConstIterator it = m_diffToChangeItemDict.constBegin(); 0427 QHash<const KompareDiff2::Difference*, KChangeLVI*>::ConstIterator end = m_diffToChangeItemDict.constEnd(); 0428 0429 qCDebug(KOMPARENAVVIEW) << "m_diffToChangeItemDict.count() = " << m_diffToChangeItemDict.count() ; 0430 0431 for (; it != end ; ++it) 0432 { 0433 it.value()->setDifferenceText(); 0434 } 0435 } 0436 0437 void KompareNavTreePart::slotApplyDifference(const Difference* diff, bool /*apply*/) 0438 { 0439 // this applies to the currently selected difference 0440 KChangeLVI* clvi = m_diffToChangeItemDict[diff]; 0441 if (clvi) 0442 clvi->setDifferenceText(); 0443 } 0444 0445 void KChangeLVI::setDifferenceText() 0446 { 0447 QString text; 0448 switch (m_difference->type()) { 0449 case Difference::Change: 0450 // Shouldn't this simply be diff->sourceLineCount() ? 0451 // because you change the _number of lines_ lines in source, not in dest 0452 if (m_difference->applied()) 0453 text = i18np("Applied: Changes made to %1 line undone", "Applied: Changes made to %1 lines undone", 0454 m_difference->sourceLineCount()); 0455 else 0456 text = i18np("Changed %1 line", "Changed %1 lines", 0457 m_difference->sourceLineCount()); 0458 break; 0459 case Difference::Insert: 0460 if (m_difference->applied()) 0461 text = i18np("Applied: Insertion of %1 line undone", "Applied: Insertion of %1 lines undone", 0462 m_difference->destinationLineCount()); 0463 else 0464 text = i18np("Inserted %1 line", "Inserted %1 lines", 0465 m_difference->destinationLineCount()); 0466 break; 0467 case Difference::Delete: 0468 if (m_difference->applied()) 0469 text = i18np("Applied: Deletion of %1 line undone", "Applied: Deletion of %1 lines undone", 0470 m_difference->sourceLineCount()); 0471 else 0472 text = i18np("Deleted %1 line", "Deleted %1 lines", 0473 m_difference->sourceLineCount()); 0474 break; 0475 default: 0476 qCDebug(KOMPARENAVVIEW) << "Unknown or Unchanged enum value when checking for diff->type() in KChangeLVI's constructor" ; 0477 text.clear(); 0478 } 0479 0480 setText(2, text); 0481 } 0482 0483 KChangeLVI::KChangeLVI(QTreeWidget* parent, Difference* diff) : QTreeWidgetItem(parent) 0484 { 0485 m_difference = diff; 0486 0487 setText(0, QString::number(diff->sourceLineNumber())); 0488 setText(1, QString::number(diff->destinationLineNumber())); 0489 0490 setDifferenceText(); 0491 } 0492 0493 bool KChangeLVI::operator<(const QTreeWidgetItem& item) const 0494 { 0495 int column = treeWidget()->sortColumn(); 0496 QString text1 = text(column); 0497 QString text2 = item.text(column); 0498 0499 // Compare the numbers. 0500 if (column < 2 && text1.length() != text2.length()) 0501 return text1.length() < text2.length(); 0502 return text1 < text2; 0503 } 0504 0505 KChangeLVI::~KChangeLVI() 0506 { 0507 } 0508 0509 KFileLVI::KFileLVI(QTreeWidget* parent, DiffModel* model) : QTreeWidgetItem(parent) 0510 { 0511 m_model = model; 0512 0513 QString src = model->sourceFile(); 0514 QString dst = model->destinationFile(); 0515 0516 setText(0, src); 0517 setText(1, dst); 0518 setIcon(0, QIcon::fromTheme(getIcon(src))); 0519 setIcon(1, QIcon::fromTheme(getIcon(dst))); 0520 } 0521 0522 bool KFileLVI::hasExtension(const QString& extensions, const QString& fileName) 0523 { 0524 const QStringList extList = extensions.split(QLatin1Char(' ')); 0525 for (const QString& ext : extList) { 0526 if (fileName.endsWith(ext, Qt::CaseInsensitive)) { 0527 return true; 0528 } 0529 } 0530 return false; 0531 } 0532 0533 const QString KFileLVI::getIcon(const QString& fileName) 0534 { 0535 // C++, C 0536 if (hasExtension(QStringLiteral(".h .hpp"), fileName)) { 0537 return QStringLiteral("text-x-c++hdr"); 0538 } 0539 if (hasExtension(QStringLiteral(".cpp"), fileName)) { 0540 return QStringLiteral("text-x-c++src"); 0541 } 0542 if (hasExtension(QStringLiteral(".c"), fileName)) { 0543 return QStringLiteral("text-x-csrc"); 0544 } 0545 // Python 0546 if (hasExtension(QStringLiteral(".py .pyw"), fileName)) { 0547 return QStringLiteral("text-x-python"); 0548 } 0549 // C# 0550 if (hasExtension(QStringLiteral(".cs"), fileName)) { 0551 return QStringLiteral("text-x-csharp"); 0552 } 0553 // Objective-C 0554 if (hasExtension(QStringLiteral(".m"), fileName)) { 0555 return QStringLiteral("text-x-objcsrc"); 0556 } 0557 // Java 0558 if (hasExtension(QStringLiteral(".java"), fileName)) { 0559 return QStringLiteral("text-x-java"); 0560 } 0561 // Script 0562 if (hasExtension(QStringLiteral(".sh"), fileName)) { 0563 return QStringLiteral("text-x-script"); 0564 } 0565 // Makefile 0566 if (hasExtension(QStringLiteral(".cmake Makefile"), fileName)) { 0567 return QStringLiteral("text-x-makefile"); 0568 } 0569 // Ada 0570 if (hasExtension(QStringLiteral(".ada .ads .adb"), fileName)) { 0571 return QStringLiteral("text-x-adasrc"); 0572 } 0573 // Pascal 0574 if (hasExtension(QStringLiteral(".pas"), fileName)) { 0575 return QStringLiteral("text-x-pascal"); 0576 } 0577 // Patch 0578 if (hasExtension(QStringLiteral(".diff"), fileName)) { 0579 return QStringLiteral("text-x-patch"); 0580 } 0581 // Tcl 0582 if (hasExtension(QStringLiteral(".tcl"), fileName)) { 0583 return QStringLiteral("text-x-tcl"); 0584 } 0585 // Text 0586 if (hasExtension(QStringLiteral(".txt"), fileName)) { 0587 return QStringLiteral("text-plain"); 0588 } 0589 // Xml 0590 if (hasExtension(QStringLiteral(".xml"), fileName)) { 0591 return QStringLiteral("text-xml"); 0592 } 0593 // unknown or no file extension 0594 return QStringLiteral("text-plain"); 0595 } 0596 0597 void KFileLVI::fillChangesList(QTreeWidget* changesList, QHash<const KompareDiff2::Difference*, KChangeLVI*>* diffToChangeItemDict) 0598 { 0599 changesList->clear(); 0600 diffToChangeItemDict->clear(); 0601 0602 const DifferenceList* differences = m_model->differences(); 0603 DifferenceListConstIterator diffIt = differences->constBegin(); 0604 DifferenceListConstIterator dEnd = differences->constEnd(); 0605 0606 for (; diffIt != dEnd; ++diffIt) 0607 { 0608 KChangeLVI* change = new KChangeLVI(changesList, *diffIt); 0609 diffToChangeItemDict->insert(*diffIt, change); 0610 } 0611 0612 changesList->setCurrentItem(changesList->topLevelItem(0)); 0613 } 0614 0615 KFileLVI::~KFileLVI() 0616 { 0617 } 0618 0619 KDirLVI::KDirLVI(QTreeWidget* parent, const QString& dir) : QTreeWidgetItem(parent) 0620 { 0621 // qCDebug(KOMPARENAVVIEW) << "KDirLVI (QTreeWidget) constructor called with dir = " << dir ; 0622 m_rootItem = true; 0623 m_dirName = dir; 0624 setIcon(0, QIcon::fromTheme(QStringLiteral("folder"))); 0625 setExpanded(true); 0626 if (m_dirName.isEmpty()) 0627 setText(0, i18nc("@item directory name not known", "Unknown")); 0628 else 0629 setText(0, m_dirName); 0630 } 0631 0632 KDirLVI::KDirLVI(KDirLVI* parent, const QString& dir) : QTreeWidgetItem(parent) 0633 { 0634 // qCDebug(KOMPARENAVVIEW) << "KDirLVI (KDirLVI) constructor called with dir = " << dir ; 0635 m_rootItem = false; 0636 m_dirName = dir; 0637 setIcon(0, QIcon::fromTheme(QStringLiteral("folder"))); 0638 setExpanded(true); 0639 setText(0, m_dirName); 0640 } 0641 0642 // addModel always removes it own path from the beginning 0643 void KDirLVI::addModel(QString& path, DiffModel* model, QHash<const KompareDiff2::DiffModel*, KDirLVI*>* modelToDirItemDict) 0644 { 0645 // qCDebug(KOMPARENAVVIEW) << "KDirLVI::addModel called with path = " << path << " from KDirLVI with m_dirName = " << m_dirName ; 0646 0647 if (!m_dirName.isEmpty()) 0648 { 0649 if (path.indexOf(m_dirName) > -1) 0650 path = path.remove(path.indexOf(m_dirName), m_dirName.length()); 0651 } 0652 0653 // qCDebug(KOMPARENAVVIEW) << "Path after removal of own dir (\"" << m_dirName << "\") = " << path ; 0654 0655 if (path.isEmpty()) { 0656 m_modelList.append(model); 0657 modelToDirItemDict->insert(model, this); 0658 return; 0659 } 0660 0661 KDirLVI* child; 0662 0663 QString dir = path.mid(0, path.indexOf(QLatin1Char('/'), 0) + 1); 0664 child = findChild(dir); 0665 if (!child) 0666 { 0667 // does not exist yet so make it 0668 // qCDebug(KOMPARENAVVIEW) << "KDirLVI::addModel creating new KDirLVI because not found" ; 0669 child = new KDirLVI(this, dir); 0670 } 0671 0672 child->addModel(path, model, modelToDirItemDict); 0673 } 0674 0675 KDirLVI* KDirLVI::findChild(const QString& dir) 0676 { 0677 // qCDebug(KOMPARENAVVIEW) << "KDirLVI::findChild called with dir = " << dir ; 0678 KDirLVI* child; 0679 if ((child = static_cast<KDirLVI*>(this->child(0))) != nullptr) 0680 { // has children, check if dir already exists, if so addModel 0681 QTreeWidgetItemIterator it(child); 0682 while (*it) { 0683 child = static_cast<KDirLVI*>(*it); 0684 0685 if (dir == child->dirName()) 0686 return child; 0687 ++it; 0688 } 0689 } 0690 0691 return nullptr; 0692 } 0693 0694 void KDirLVI::fillFileList(QTreeWidget* fileList, QHash<const KompareDiff2::DiffModel*, KFileLVI*>* modelToFileItemDict) 0695 { 0696 fileList->clear(); 0697 0698 DiffModelListIterator modelIt = m_modelList.begin(); 0699 DiffModelListIterator mEnd = m_modelList.end(); 0700 for (; modelIt != mEnd; ++modelIt) 0701 { 0702 KFileLVI* file = new KFileLVI(fileList, *modelIt); 0703 modelToFileItemDict->insert(*modelIt, file); 0704 } 0705 0706 fileList->setCurrentItem(fileList->topLevelItem(0)); 0707 } 0708 0709 QString KDirLVI::fullPath(QString& path) 0710 { 0711 // if (!path.isEmpty()) 0712 // qCDebug(KOMPARENAVVIEW) << "KDirLVI::fullPath called with path = " << path ; 0713 // else 0714 // qCDebug(KOMPARENAVVIEW) << "KDirLVI::fullPath called with empty path..." ; 0715 0716 if (m_rootItem) // don't bother adding rootItem's dir... 0717 return path; 0718 0719 path = path.prepend(m_dirName); 0720 0721 KDirLVI* lviParent = dynamic_cast<KDirLVI*>(parent()); 0722 if (lviParent) 0723 { 0724 path = lviParent->fullPath(path); 0725 } 0726 0727 return path; 0728 } 0729 0730 KDirLVI* KDirLVI::setSelected(const QString& _dir) 0731 { 0732 QString dir(_dir); 0733 // qCDebug(KOMPARENAVVIEW) << "KDirLVI::setSelected called with dir = " << dir ; 0734 0735 // root item's dirName is never taken into account... remember that 0736 if (!m_rootItem) 0737 { 0738 dir = dir.remove(0, m_dirName.length()); 0739 } 0740 0741 if (dir.isEmpty()) 0742 { 0743 return this; 0744 } 0745 KDirLVI* child = static_cast<KDirLVI*>(this->child(0)); 0746 if (!child) 0747 return nullptr; 0748 0749 QTreeWidgetItemIterator it(child); 0750 while (*it) { 0751 child = static_cast<KDirLVI*>(*it); 0752 0753 if (dir.startsWith(child->dirName())) 0754 return child->setSelected(dir); 0755 ++it; 0756 } 0757 0758 return nullptr; 0759 } 0760 0761 KDirLVI::~KDirLVI() 0762 { 0763 m_modelList.clear(); 0764 } 0765 0766 K_PLUGIN_FACTORY_WITH_JSON(KompareNavTreePartFactory, "komparenavtreepart.json", 0767 registerPlugin<KompareNavTreePart>();) 0768 0769 #include "komparenavtreepart.moc" 0770 #include "moc_komparenavtreepart.cpp"