diff --git a/CMakeLists.txt b/CMakeLists.txt index b9dd2fd..1479e9c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,106 +1,106 @@ cmake_minimum_required(VERSION 3.0) project(kompare) set(QT_MIN_VERSION "5.9.0") set(KF5_MIN_VERSION "5.53.0") find_package(ECM ${KF5_MIN_VERSION} NO_MODULE REQUIRED) set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${ECM_MODULE_PATH}) include(FeatureSummary) include(KDEInstallDirs) include(KDECMakeSettings) include(KDECompilerSettings NO_POLICY_SCOPE) include(ECMInstallIcons) include(GenerateExportHeader) include(ECMAddAppIcon) include(ECMQtDeclareLoggingCategory) find_package(Qt5 ${QT_MIN_VERSION} REQUIRED COMPONENTS Core PrintSupport Widgets ) find_package(KF5 ${KF5_MIN_VERSION} REQUIRED COMPONENTS CoreAddons Codecs DocTools IconThemes JobWidgets Config Parts TextEditor WidgetsAddons ) find_package(LibKompareDiff2 5.2 CONFIG) set_package_properties(LibKompareDiff2 PROPERTIES TYPE REQUIRED ) set(KOMPARE_LIB_VERSION 5) set(KOMPARE_LIB_SOVERSION 5) add_definitions( -DQT_DEPRECATED_WARNINGS - -DQT_NO_SIGNALS_SLOTS_KEYWORDS + -DQT_NO_KEYWORDS -DQT_STRICT_ITERATORS -DQT_USE_QSTRINGBUILDER -DQT_NO_CAST_TO_ASCII -DQT_NO_CAST_FROM_ASCII -DQT_NO_CAST_FROM_BYTEARRAY # -DQT_NO_URL_CAST_FROM_STRING -DQT_NO_FOREACH ) add_subdirectory( doc ) add_subdirectory( interfaces ) add_subdirectory( libdialogpages ) add_subdirectory( komparenavtreepart ) add_subdirectory( komparepart ) add_subdirectory( pics ) add_subdirectory( servicemenus ) set(kompare_SRCS main.cpp kompare_shell.cpp kompareurldialog.cpp ) ecm_qt_declare_logging_category(kompare_SRCS HEADER kompareshelldebug.h IDENTIFIER KOMPARESHELL CATEGORY_NAME "kompareshell" ) qt5_add_resources(kompare_SRCS kompare_shell.qrc ) ecm_add_app_icon(kompare_SRCS ICONS pics/16-apps-kompare.png pics/22-apps-kompare.png pics/32-apps-kompare.png pics/48-apps-kompare.png pics/128-apps-kompare.png ) add_executable(kompare ${kompare_SRCS}) target_link_libraries(kompare kompareinterface komparedialogpages KompareDiff2 KF5::TextEditor KF5::WidgetsAddons Qt5::Widgets ) install(TARGETS kompare ${KDE_INSTALL_TARGETS_DEFAULT_ARGS}) install(PROGRAMS org.kde.kompare.desktop DESTINATION ${KDE_INSTALL_APPDIR}) install(FILES org.kde.kompare.appdata.xml DESTINATION ${KDE_INSTALL_METAINFODIR}) install(FILES komparenavigationpart.desktop kompareviewpart.desktop DESTINATION ${KDE_INSTALL_KSERVICETYPES5DIR}) feature_summary(WHAT ALL INCLUDE_QUIET_PACKAGES FATAL_ON_MISSING_REQUIRED_PACKAGES) diff --git a/komparenavtreepart/komparenavtreepart.cpp b/komparenavtreepart/komparenavtreepart.cpp index a151ef0..ec03fc5 100644 --- a/komparenavtreepart/komparenavtreepart.cpp +++ b/komparenavtreepart/komparenavtreepart.cpp @@ -1,785 +1,785 @@ /*************************************************************************** KompareNavTreePart.cpp ---------------------- begin : Sun Mar 4 2001 Copyright 2001-2005,2009 Otto Bruggeman Copyright 2001-2003 John Firebaugh Copyright 2007-2011 Kevin Kofler ****************************************************************************/ /*************************************************************************** ** ** This program is free software; you can redistribute it and/or modify ** it under the terms of the GNU General Public License as published by ** the Free Software Foundation; either version 2 of the License, or ** (at your option) any later version. ** ***************************************************************************/ #include "komparenavtreepart.h" #include #include #include #include #include #include #include #include #include #include #define COL_SOURCE 0 #define COL_DESTINATION 1 #define COL_DIFFERENCE 2 using namespace Diff2; KompareNavTreePart::KompareNavTreePart(QWidget* parentWidget, QObject* parent, const QVariantList&) : KParts::ReadOnlyPart(parent), m_splitter(nullptr), m_modelList(nullptr), m_srcDirTree(nullptr), m_destDirTree(nullptr), m_fileList(nullptr), m_changesList(nullptr), m_srcRootItem(nullptr), m_destRootItem(nullptr), m_selectedModel(nullptr), m_selectedDifference(nullptr), m_source(), m_destination(), m_info(nullptr) { m_splitter = new QSplitter(Qt::Horizontal, parentWidget); setWidget(m_splitter); m_srcDirTree = new QTreeWidget(m_splitter); m_srcDirTree->setHeaderLabel(i18nc("@title:column", "Source Folder")); m_srcDirTree->setRootIsDecorated(false); m_srcDirTree->setSortingEnabled(true); m_srcDirTree->sortByColumn(0, Qt::AscendingOrder); m_destDirTree = new QTreeWidget(m_splitter); m_destDirTree->setHeaderLabel(i18nc("@title:column", "Destination Folder")); m_destDirTree->setRootIsDecorated(false); m_destDirTree->setSortingEnabled(true); m_destDirTree->sortByColumn(0, Qt::AscendingOrder); m_fileList = new QTreeWidget(m_splitter); m_fileList->setHeaderLabels(QStringList { i18nc("@title:column", "Source File"), i18nc("@title:column", "Destination File") } ); m_fileList->setAllColumnsShowFocus(true); m_fileList->setRootIsDecorated(false); m_fileList->setSortingEnabled(true); m_fileList->sortByColumn(0, Qt::AscendingOrder); m_changesList = new QTreeWidget(m_splitter); m_changesList->setHeaderLabels(QStringList { i18nc("@title:column", "Source Line"), i18nc("@title:column", "Destination Line"), i18nc("@title:column", "Difference"), } ); m_changesList->setAllColumnsShowFocus(true); m_changesList->setRootIsDecorated(false); m_changesList->setSortingEnabled(true); m_changesList->sortByColumn(0, Qt::AscendingOrder); connect(m_srcDirTree, &QTreeWidget::currentItemChanged, this, &KompareNavTreePart::slotSrcDirTreeSelectionChanged); connect(m_destDirTree, &QTreeWidget::currentItemChanged, this, &KompareNavTreePart::slotDestDirTreeSelectionChanged); connect(m_fileList, &QTreeWidget::currentItemChanged, this, &KompareNavTreePart::slotFileListSelectionChanged); connect(m_changesList, &QTreeWidget::currentItemChanged, this, &KompareNavTreePart::slotChangesListSelectionChanged); } KompareNavTreePart::~KompareNavTreePart() { m_modelList = nullptr; m_selectedModel = nullptr; m_selectedDifference = nullptr; } void KompareNavTreePart::slotKompareInfo(struct Kompare::Info* info) { m_info = info; } void KompareNavTreePart::slotModelsChanged(const DiffModelList* modelList) { qCDebug(KOMPARENAVVIEW) << "Models (" << modelList << ") have changed... scanning the models... " ; if (modelList) { m_modelList = modelList; m_srcDirTree->clear(); m_destDirTree->clear(); m_fileList->clear(); m_changesList->clear(); buildTreeInMemory(); } else { m_modelList = modelList; m_srcDirTree->clear(); m_destDirTree->clear(); m_fileList->clear(); m_changesList->clear(); } } void KompareNavTreePart::buildTreeInMemory() { qCDebug(KOMPARENAVVIEW) << "BuildTreeInMemory called" ; if (m_modelList->count() == 0) { qCDebug(KOMPARENAVVIEW) << "No models... weird shit..." ; return; // avoids a crash on clear() } if (!m_info) { qCDebug(KOMPARENAVVIEW) << "No Info... weird shit..." ; return; } QString srcBase; QString destBase; DiffModel* model; model = m_modelList->first(); m_selectedModel = nullptr; switch (m_info->mode) { case Kompare::ShowingDiff: // BUG: 107489 No common root because it is a multi directory relative path diff // We need to detect this and create a different rootitem / or so or should we always add this? // Trouble we run into is that the directories do not start with a / // so we have an unknown top root dir // Thinking some more about it i guess it is best to use "" as base and simply show some string // like Unknown filesystem path as root text but only in the case of dirs starting without a / srcBase = model->sourcePath(); destBase = model->destinationPath(); // FIXME: these tests will not work on windows, we need something else if (srcBase[0] != QLatin1Char('/')) srcBase.clear(); if (destBase[0] != QLatin1Char('/')) destBase.clear(); break; case Kompare::ComparingFiles: srcBase = model->sourcePath(); destBase = model->destinationPath(); break; case Kompare::ComparingDirs: srcBase = m_info->localSource; if (!srcBase.endsWith(QLatin1Char('/'))) srcBase += QLatin1Char('/'); destBase = m_info->localDestination; if (!destBase.endsWith(QLatin1Char('/'))) destBase += QLatin1Char('/'); break; case Kompare::BlendingFile: case Kompare::BlendingDir: default: qCDebug(KOMPARENAVVIEW) << "Oops needs to implement this..." ; } // qCDebug(KOMPARENAVVIEW) << "srcBase = " << srcBase ; // qCDebug(KOMPARENAVVIEW) << "destBase = " << destBase ; m_srcRootItem = new KDirLVI(m_srcDirTree, srcBase); m_destRootItem = new KDirLVI(m_destDirTree, destBase); QString srcPath; QString destPath; // Create the tree from the models DiffModelListConstIterator modelIt = m_modelList->begin(); DiffModelListConstIterator mEnd = m_modelList->end(); for (; modelIt != mEnd; ++modelIt) { model = *modelIt; srcPath = model->sourcePath(); destPath = model->destinationPath(); qCDebug(KOMPARENAVVIEW) << "srcPath = " << srcPath ; qCDebug(KOMPARENAVVIEW) << "destPath = " << destPath ; m_srcRootItem->addModel(srcPath, model, &m_modelToSrcDirItemDict); m_destRootItem->addModel(destPath, model, &m_modelToDestDirItemDict); } // m_srcDirTree->setSelected( m_srcDirTree->firstChild(), true ); } void KompareNavTreePart::buildDirectoryTree() { // FIXME: afaict this can be deleted // qCDebug(KOMPARENAVVIEW) << "BuildDirTree called" ; } QString KompareNavTreePart::compareFromEndAndReturnSame( const QString& string1, const QString& string2) { QString result; int srcLen = string1.length(); int destLen = string2.length(); while (srcLen != 0 && destLen != 0) { if (string1[--srcLen] == string2[--destLen]) result.prepend(string1[srcLen]); else break; } if (srcLen != 0 && destLen != 0 && result.startsWith(QLatin1Char('/'))) result = result.remove(0, 1); // strip leading /, we need it later return result; } void KompareNavTreePart::slotSetSelection(const DiffModel* model, const Difference* diff) { qCDebug(KOMPARENAVVIEW) << "KompareNavTreePart::slotSetSelection model = " << model << ", diff = " << diff ; if (model == m_selectedModel) { // model is the same, so no need to update that... if (diff != m_selectedDifference) { m_selectedDifference = diff; setSelectedDifference(diff); } return; } // model is different so we need to find the right dirs, file and changeitems to select // if m_selectedModel == NULL then everything needs to be done as well if (!m_selectedModel || model->sourcePath() != m_selectedModel->sourcePath()) { // dirs are different, so we need to update the dirviews as well m_selectedModel = model; m_selectedDifference = diff; setSelectedDir(model); setSelectedFile(model); setSelectedDifference(diff); return; } if (!m_selectedModel || model->sourceFile() != m_selectedModel->sourceFile()) { m_selectedModel = model; setSelectedFile(model); m_selectedDifference = diff; setSelectedDifference(diff); } } void KompareNavTreePart::setSelectedDir(const DiffModel* model) { KDirLVI* currentDir; currentDir = m_modelToSrcDirItemDict[ model ]; qCDebug(KOMPARENAVVIEW) << "Manually setting selection in srcdirtree with currentDir = " << currentDir ; m_srcDirTree->blockSignals(true); m_srcDirTree->setCurrentItem(currentDir); m_srcDirTree->scrollToItem(currentDir); m_srcDirTree->blockSignals(false); currentDir = m_modelToDestDirItemDict[ model ]; qCDebug(KOMPARENAVVIEW) << "Manually setting selection in destdirtree with currentDir = " << currentDir ; m_destDirTree->blockSignals(true); m_destDirTree->setCurrentItem(currentDir); m_destDirTree->scrollToItem(currentDir); m_destDirTree->blockSignals(false); m_fileList->blockSignals(true); currentDir->fillFileList(m_fileList, &m_modelToFileItemDict); m_fileList->blockSignals(false); } void KompareNavTreePart::setSelectedFile(const DiffModel* model) { KFileLVI* currentFile; currentFile = m_modelToFileItemDict[ model ]; qCDebug(KOMPARENAVVIEW) << "Manually setting selection in filelist" ; m_fileList->blockSignals(true); m_fileList->setCurrentItem(currentFile); m_fileList->scrollToItem(currentFile); m_fileList->blockSignals(false); m_changesList->blockSignals(true); currentFile->fillChangesList(m_changesList, &m_diffToChangeItemDict); m_changesList->blockSignals(false); } void KompareNavTreePart::setSelectedDifference(const Difference* diff) { KChangeLVI* currentDiff; currentDiff = m_diffToChangeItemDict[ diff ]; qCDebug(KOMPARENAVVIEW) << "Manually setting selection in changeslist to " << currentDiff ; m_changesList->blockSignals(true); m_changesList->setCurrentItem(currentDiff); m_changesList->scrollToItem(currentDiff); m_changesList->blockSignals(false); } void KompareNavTreePart::slotSetSelection(const Difference* diff) { // qCDebug(KOMPARENAVVIEW) << "Scotty i need more power !!" ; if (m_selectedDifference != diff) { // qCDebug(KOMPARENAVVIEW) << "But sir, i am giving you all she's got" ; m_selectedDifference = diff; setSelectedDifference(diff); } } void KompareNavTreePart::slotSrcDirTreeSelectionChanged(QTreeWidgetItem* item) { if (!item) return; qCDebug(KOMPARENAVVIEW) << "Sent by the sourceDirectoryTree with item = " << item ; m_srcDirTree->scrollToItem(item); KDirLVI* dir = static_cast(item); // order the dest tree view to set its selected item to the same as here QString path; // We start with an empty path and after the call path contains the full path path = dir->fullPath(path); KDirLVI* selItem = m_destRootItem->setSelected(path); m_destDirTree->blockSignals(true); m_destDirTree->setCurrentItem(selItem); m_destDirTree->scrollToItem(selItem); m_destDirTree->blockSignals(false); // fill the changes list dir->fillFileList(m_fileList, &m_modelToFileItemDict); } void KompareNavTreePart::slotDestDirTreeSelectionChanged(QTreeWidgetItem* item) { if (!item) return; qCDebug(KOMPARENAVVIEW) << "Sent by the destinationDirectoryTree with item = " << item ; m_destDirTree->scrollToItem(item); KDirLVI* dir = static_cast(item); // order the src tree view to set its selected item to the same as here QString path; // We start with an empty path and after the call path contains the full path path = dir->fullPath(path); KDirLVI* selItem = m_srcRootItem->setSelected(path); m_srcDirTree->blockSignals(true); m_srcDirTree->setCurrentItem(selItem); m_srcDirTree->scrollToItem(selItem); m_srcDirTree->blockSignals(false); // fill the changes list dir->fillFileList(m_fileList, &m_modelToFileItemDict); } void KompareNavTreePart::slotFileListSelectionChanged(QTreeWidgetItem* item) { if (!item) return; qCDebug(KOMPARENAVVIEW) << "Sent by the fileList with item = " << item ; KFileLVI* file = static_cast(item); m_selectedModel = file->model(); m_changesList->blockSignals(true); file->fillChangesList(m_changesList, &m_diffToChangeItemDict); m_changesList->blockSignals(false); if (m_changesList->currentItem()) { // FIXME: This is ugly... m_selectedDifference = (static_cast(m_changesList->currentItem()))->difference(); } - emit selectionChanged(m_selectedModel, m_selectedDifference); + Q_EMIT selectionChanged(m_selectedModel, m_selectedDifference); } void KompareNavTreePart::slotChangesListSelectionChanged(QTreeWidgetItem* item) { if (!item) return; qCDebug(KOMPARENAVVIEW) << "Sent by the changesList" ; KChangeLVI* change = static_cast(item); m_selectedDifference = change->difference(); - emit selectionChanged(m_selectedDifference); + Q_EMIT selectionChanged(m_selectedDifference); } void KompareNavTreePart::slotApplyDifference(bool /*apply*/) { KChangeLVI* clvi = m_diffToChangeItemDict[m_selectedDifference]; if (clvi) clvi->setDifferenceText(); } void KompareNavTreePart::slotApplyAllDifferences(bool /*apply*/) { QHash::ConstIterator it = m_diffToChangeItemDict.constBegin(); QHash::ConstIterator end = m_diffToChangeItemDict.constEnd(); qCDebug(KOMPARENAVVIEW) << "m_diffToChangeItemDict.count() = " << m_diffToChangeItemDict.count() ; for (; it != end ; ++it) { it.value()->setDifferenceText(); } } void KompareNavTreePart::slotApplyDifference(const Difference* diff, bool /*apply*/) { // this applies to the currently selected difference KChangeLVI* clvi = m_diffToChangeItemDict[diff]; if (clvi) clvi->setDifferenceText(); } void KChangeLVI::setDifferenceText() { QString text; switch (m_difference->type()) { case Difference::Change: // Shouldn't this simply be diff->sourceLineCount() ? // because you change the _number of lines_ lines in source, not in dest if (m_difference->applied()) text = i18np("Applied: Changes made to %1 line undone", "Applied: Changes made to %1 lines undone", m_difference->sourceLineCount()); else text = i18np("Changed %1 line", "Changed %1 lines", m_difference->sourceLineCount()); break; case Difference::Insert: if (m_difference->applied()) text = i18np("Applied: Insertion of %1 line undone", "Applied: Insertion of %1 lines undone", m_difference->destinationLineCount()); else text = i18np("Inserted %1 line", "Inserted %1 lines", m_difference->destinationLineCount()); break; case Difference::Delete: if (m_difference->applied()) text = i18np("Applied: Deletion of %1 line undone", "Applied: Deletion of %1 lines undone", m_difference->sourceLineCount()); else text = i18np("Deleted %1 line", "Deleted %1 lines", m_difference->sourceLineCount()); break; default: qCDebug(KOMPARENAVVIEW) << "Unknown or Unchanged enum value when checking for diff->type() in KChangeLVI's constructor" ; text.clear(); } setText(2, text); } KChangeLVI::KChangeLVI(QTreeWidget* parent, Difference* diff) : QTreeWidgetItem(parent) { m_difference = diff; setText(0, QString::number(diff->sourceLineNumber())); setText(1, QString::number(diff->destinationLineNumber())); setDifferenceText(); } bool KChangeLVI::operator<(const QTreeWidgetItem& item) const { int column = treeWidget()->sortColumn(); QString text1 = text(column); QString text2 = item.text(column); // Compare the numbers. if (column < 2 && text1.length() != text2.length()) return text1.length() < text2.length(); return text1 < text2; } KChangeLVI::~KChangeLVI() { } KFileLVI::KFileLVI(QTreeWidget* parent, DiffModel* model) : QTreeWidgetItem(parent) { m_model = model; QString src = model->sourceFile(); QString dst = model->destinationFile(); setText(0, src); setText(1, dst); setIcon(0, QIcon::fromTheme(getIcon(src))); setIcon(1, QIcon::fromTheme(getIcon(dst))); } bool KFileLVI::hasExtension(const QString& extensions, const QString& fileName) { const QStringList extList = extensions.split(QLatin1Char(' ')); for (const QString& ext : extList) { if (fileName.endsWith(ext, Qt::CaseInsensitive)) { return true; } } return false; } const QString KFileLVI::getIcon(const QString& fileName) { // C++, C if (hasExtension(QStringLiteral(".h .hpp"), fileName)) { return QStringLiteral("text-x-c++hdr"); } if (hasExtension(QStringLiteral(".cpp"), fileName)) { return QStringLiteral("text-x-c++src"); } if (hasExtension(QStringLiteral(".c"), fileName)) { return QStringLiteral("text-x-csrc"); } // Python if (hasExtension(QStringLiteral(".py .pyw"), fileName)) { return QStringLiteral("text-x-python"); } // C# if (hasExtension(QStringLiteral(".cs"), fileName)) { return QStringLiteral("text-x-csharp"); } // Objective-C if (hasExtension(QStringLiteral(".m"), fileName)) { return QStringLiteral("text-x-objcsrc"); } // Java if (hasExtension(QStringLiteral(".java"), fileName)) { return QStringLiteral("text-x-java"); } // Script if (hasExtension(QStringLiteral(".sh"), fileName)) { return QStringLiteral("text-x-script"); } // Makefile if (hasExtension(QStringLiteral(".cmake Makefile"), fileName)) { return QStringLiteral("text-x-makefile"); } // Ada if (hasExtension(QStringLiteral(".ada .ads .adb"), fileName)) { return QStringLiteral("text-x-adasrc"); } // Pascal if (hasExtension(QStringLiteral(".pas"), fileName)) { return QStringLiteral("text-x-pascal"); } // Patch if (hasExtension(QStringLiteral(".diff"), fileName)) { return QStringLiteral("text-x-patch"); } // Tcl if (hasExtension(QStringLiteral(".tcl"), fileName)) { return QStringLiteral("text-x-tcl"); } // Text if (hasExtension(QStringLiteral(".txt"), fileName)) { return QStringLiteral("text-plain"); } // Xml if (hasExtension(QStringLiteral(".xml"), fileName)) { return QStringLiteral("text-xml"); } // unknown or no file extension return QStringLiteral("text-plain"); } void KFileLVI::fillChangesList(QTreeWidget* changesList, QHash* diffToChangeItemDict) { changesList->clear(); diffToChangeItemDict->clear(); DifferenceListConstIterator diffIt = m_model->differences()->constBegin(); DifferenceListConstIterator dEnd = m_model->differences()->constEnd(); for (; diffIt != dEnd; ++diffIt) { KChangeLVI* change = new KChangeLVI(changesList, *diffIt); diffToChangeItemDict->insert(*diffIt, change); } changesList->setCurrentItem(changesList->topLevelItem(0)); } KFileLVI::~KFileLVI() { } KDirLVI::KDirLVI(QTreeWidget* parent, const QString& dir) : QTreeWidgetItem(parent) { // qCDebug(KOMPARENAVVIEW) << "KDirLVI (QTreeWidget) constructor called with dir = " << dir ; m_rootItem = true; m_dirName = dir; setIcon(0, QIcon::fromTheme(QStringLiteral("folder"))); setExpanded(true); if (m_dirName.isEmpty()) setText(0, i18nc("@item directory name not known", "Unknown")); else setText(0, m_dirName); } KDirLVI::KDirLVI(KDirLVI* parent, const QString& dir) : QTreeWidgetItem(parent) { // qCDebug(KOMPARENAVVIEW) << "KDirLVI (KDirLVI) constructor called with dir = " << dir ; m_rootItem = false; m_dirName = dir; setIcon(0, QIcon::fromTheme(QStringLiteral("folder"))); setExpanded(true); setText(0, m_dirName); } // addModel always removes it own path from the beginning void KDirLVI::addModel(QString& path, DiffModel* model, QHash* modelToDirItemDict) { // qCDebug(KOMPARENAVVIEW) << "KDirLVI::addModel called with path = " << path << " from KDirLVI with m_dirName = " << m_dirName ; if (!m_dirName.isEmpty()) { if (path.indexOf(m_dirName) > -1) path = path.remove(path.indexOf(m_dirName), m_dirName.length()); } // qCDebug(KOMPARENAVVIEW) << "Path after removal of own dir (\"" << m_dirName << "\") = " << path ; if (path.isEmpty()) { m_modelList.append(model); modelToDirItemDict->insert(model, this); return; } KDirLVI* child; QString dir = path.mid(0, path.indexOf(QLatin1Char('/'), 0) + 1); child = findChild(dir); if (!child) { // does not exist yet so make it // qCDebug(KOMPARENAVVIEW) << "KDirLVI::addModel creating new KDirLVI because not found" ; child = new KDirLVI(this, dir); } child->addModel(path, model, modelToDirItemDict); } KDirLVI* KDirLVI::findChild(const QString& dir) { // qCDebug(KOMPARENAVVIEW) << "KDirLVI::findChild called with dir = " << dir ; KDirLVI* child; if ((child = static_cast(this->child(0))) != nullptr) { // has children, check if dir already exists, if so addModel QTreeWidgetItemIterator it(child); while (*it) { child = static_cast(*it); if (dir == child->dirName()) return child; ++it; } } return nullptr; } void KDirLVI::fillFileList(QTreeWidget* fileList, QHash* modelToFileItemDict) { fileList->clear(); DiffModelListIterator modelIt = m_modelList.begin(); DiffModelListIterator mEnd = m_modelList.end(); for (; modelIt != mEnd; ++modelIt) { KFileLVI* file = new KFileLVI(fileList, *modelIt); modelToFileItemDict->insert(*modelIt, file); } fileList->setCurrentItem(fileList->topLevelItem(0)); } QString KDirLVI::fullPath(QString& path) { // if (!path.isEmpty()) // qCDebug(KOMPARENAVVIEW) << "KDirLVI::fullPath called with path = " << path ; // else // qCDebug(KOMPARENAVVIEW) << "KDirLVI::fullPath called with empty path..." ; if (m_rootItem) // don't bother adding rootItem's dir... return path; path = path.prepend(m_dirName); KDirLVI* lviParent = dynamic_cast(parent()); if (lviParent) { path = lviParent->fullPath(path); } return path; } KDirLVI* KDirLVI::setSelected(const QString& _dir) { QString dir(_dir); // qCDebug(KOMPARENAVVIEW) << "KDirLVI::setSelected called with dir = " << dir ; // root item's dirName is never taken into account... remember that if (!m_rootItem) { dir = dir.remove(0, m_dirName.length()); } if (dir.isEmpty()) { return this; } KDirLVI* child = static_cast(this->child(0)); if (!child) return nullptr; QTreeWidgetItemIterator it(child); while (*it) { child = static_cast(*it); if (dir.startsWith(child->dirName())) return child->setSelected(dir); ++it; } return nullptr; } KDirLVI::~KDirLVI() { m_modelList.clear(); } static KAboutData aboutData() { KAboutData about(QStringLiteral("komparenavtreepart"), i18n("KompareNavTreePart"), QStringLiteral("1.2")); about.addAuthor(i18n("John Firebaugh"), i18n("Author"), QStringLiteral("jfirebaugh@kde.org")); about.addAuthor(i18n("Otto Bruggeman"), i18n("Author"), QStringLiteral("bruggie@gmail.com")); return about; } K_PLUGIN_FACTORY_WITH_JSON(KompareNavTreePartFactory, "komparenavtreepart.json", registerPlugin();) #include "komparenavtreepart.moc" diff --git a/komparepart/kompare_part.cpp b/komparepart/kompare_part.cpp index 3dd9974..42d3120 100644 --- a/komparepart/kompare_part.cpp +++ b/komparepart/kompare_part.cpp @@ -1,982 +1,982 @@ /*************************************************************************** kompare_part.cpp ---------------- begin : Sun Mar 4 2001 Copyright 2001-2005,2009 Otto Bruggeman Copyright 2001-2003 John Firebaugh Copyright 2004 Jeff Snyder Copyright 2007-2011 Kevin Kofler Copyright 2012 Jean-Nicolas Artaud ****************************************************************************/ /*************************************************************************** ** ** This program is free software; you can redistribute it and/or modify ** it under the terms of the GNU General Public License as published by ** the Free Software Foundation; either version 2 of the License, or ** (at your option) any later version. ** ***************************************************************************/ #include "kompare_part.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "komparelistview.h" #include "kompareconnectwidget.h" #include "viewsettings.h" #include "kompareprefdlg.h" #include "komparesaveoptionswidget.h" #include "komparesplitter.h" #include "kompareview.h" using namespace Diff2; ViewSettings* KomparePart::m_viewSettings = nullptr; DiffSettings* KomparePart::m_diffSettings = nullptr; KomparePart::KomparePart(QWidget* parentWidget, QObject* parent, const KAboutData& aboutData, Modus modus) : KParts::ReadWritePart(parent), m_info() { setComponentData(aboutData); // set our XML-UI resource file setXMLFile(QStringLiteral("komparepartui.rc")); if (!m_viewSettings) { m_viewSettings = new ViewSettings(nullptr); } if (!m_diffSettings) { m_diffSettings = new DiffSettings(nullptr); } readProperties(KSharedConfig::openConfig().data()); m_view = new KompareView(m_viewSettings, parentWidget); m_view->setContextMenuPolicy(Qt::CustomContextMenu); connect(m_view, &QWidget::customContextMenuRequested, this, &KomparePart::onContextMenuRequested); setWidget(m_view); m_splitter = m_view->splitter(); // This creates the "Model creator" and connects the signals and slots m_modelList = new Diff2::KompareModelList(m_diffSettings, m_splitter, this, "komparemodellist" , (modus == ReadWriteModus)); const auto modelListActions = m_modelList->actionCollection()->actions(); for (QAction* action : modelListActions) { actionCollection()->addAction(action->objectName(), action); } connect(m_modelList, &KompareModelList::status, this, &KomparePart::slotSetStatus); connect(m_modelList, &KompareModelList::setStatusBarModelInfo, this, &KomparePart::setStatusBarModelInfo); connect(m_modelList, &KompareModelList::error, this, &KomparePart::slotShowError); connect(m_modelList, &KompareModelList::applyAllDifferences, this, &KomparePart::updateActions); connect(m_modelList, static_cast(&KompareModelList::applyDifference), this, &KomparePart::updateActions); connect(m_modelList, &KompareModelList::applyAllDifferences, this, &KomparePart::appliedChanged); connect(m_modelList, static_cast(&KompareModelList::applyDifference), this, &KomparePart::appliedChanged); connect(m_modelList, &KompareModelList::updateActions, this, &KomparePart::updateActions); // This is the stuff to connect the "interface" of the kompare part to the model inside connect(m_modelList, &KompareModelList::modelsChanged, this, &KomparePart::modelsChanged); typedef void(KompareModelList::*void_KompareModelList_argModelDiff)(const DiffModel*, const Difference*); typedef void(KompareModelList::*void_KompareModelList_argDiffBool)(const Difference*, bool); typedef void(KompareSplitter::*void_KompareSplitter_argModelDiff)(const DiffModel*, const Difference*); typedef void(KompareSplitter::*void_KompareSplitter_argDiffBool)(const Difference*, bool); typedef void(KomparePart::*void_KomparePart_argModelDiff)(const DiffModel*, const Difference*); typedef void(KomparePart::*void_KomparePart_argDiffBool)(const Difference*, bool); connect(m_modelList, static_cast(&KompareModelList::setSelection), this, static_cast(&KomparePart::setSelection)); connect(this, static_cast(&KomparePart::selectionChanged), m_modelList, static_cast(&KompareModelList::slotSelectionChanged)); connect(m_modelList, static_cast(&KompareModelList::setSelection), this, static_cast(&KomparePart::setSelection)); connect(this, static_cast(&KomparePart::selectionChanged), m_modelList, static_cast(&KompareModelList::slotSelectionChanged)); connect(m_modelList, static_cast(&KompareModelList::applyDifference), this, static_cast(&KomparePart::applyDifference)); connect(m_modelList, &KompareModelList::applyAllDifferences, this, &KomparePart::applyAllDifferences); connect(m_modelList, static_cast(&KompareModelList::applyDifference), this, static_cast(&KomparePart::applyDifference)); connect(m_modelList, &KompareModelList::diffString, this, &KomparePart::diffString); connect(this, &KomparePart::kompareInfo, m_modelList, &KompareModelList::slotKompareInfo); // Here we connect the splitter to the modellist connect(m_modelList, static_cast(&KompareModelList::setSelection), m_splitter, static_cast(&KompareSplitter::slotSetSelection)); // connect(m_splitter, SIGNAL(selectionChanged(const Diff2::Difference*,const Diff2::Difference*)), // m_modelList, SLOT(slotSelectionChanged(const Diff2::Difference*,const Diff2::Difference*))); connect(m_modelList, static_cast(&KompareModelList::setSelection), m_splitter, static_cast(&KompareSplitter::slotSetSelection)); connect(m_splitter, static_cast(&KompareSplitter::selectionChanged), m_modelList, static_cast(&KompareModelList::slotSelectionChanged)); connect(m_modelList, static_cast(&KompareModelList::applyDifference), m_splitter, static_cast(&KompareSplitter::slotApplyDifference)); connect(m_modelList, &KompareModelList::applyAllDifferences, m_splitter, &KompareSplitter::slotApplyAllDifferences); connect(m_modelList, static_cast(&KompareModelList::applyDifference), m_splitter, static_cast(&KompareSplitter::slotApplyDifference)); connect(this, &KomparePart::configChanged, m_splitter, &KompareSplitter::configChanged); setupActions(modus); // we are read-write by default -> uhm what if we are opened by lets say konq in RO mode ? // Then we should not be doing this... setReadWrite((modus == ReadWriteModus)); // we are not modified since we haven't done anything yet setModified(false); } KomparePart::~KomparePart() { // This is the only place allowed to call cleanUpTemporaryFiles // because before there might still be a use for them (when swapping) cleanUpTemporaryFiles(); } void KomparePart::setupActions(Modus modus) { // create our actions if (modus == ReadWriteModus) { m_saveAll = actionCollection()->addAction(QStringLiteral("file_save_all"), this, &KomparePart::saveAll); m_saveAll->setIcon(QIcon::fromTheme(QStringLiteral("document-save-all"))); m_saveAll->setText(i18nc("@action", "Save &All")); m_saveDiff = actionCollection()->addAction(QStringLiteral("file_save_diff"), this, &KomparePart::saveDiff); m_saveDiff->setText(i18nc("@action", "Save &Diff...")); m_swap = actionCollection()->addAction(QStringLiteral("file_swap"), this, &KomparePart::slotSwap); m_swap->setText(i18nc("@action", "Swap Source with Destination")); } else { m_saveAll = nullptr; m_saveDiff = nullptr; m_swap = nullptr; } m_diffStats = actionCollection()->addAction(QStringLiteral("file_diffstats"), this, &KomparePart::slotShowDiffstats); m_diffStats->setText(i18nc("@action", "Show Statistics")); m_diffRefresh = actionCollection()->addAction(QStringLiteral("file_refreshdiff"), this, &KomparePart::slotRefreshDiff); m_diffRefresh->setIcon(QIcon::fromTheme(QStringLiteral("view-refresh"))); m_diffRefresh->setText(i18nc("@action", "Refresh Diff")); actionCollection()->setDefaultShortcuts(m_diffRefresh, KStandardShortcut::reload()); m_print = KStandardAction::print(this, &KomparePart::slotFilePrint, actionCollection()); m_printPreview = KStandardAction::printPreview(this, &KomparePart::slotFilePrintPreview, actionCollection()); KStandardAction::preferences(this, &KomparePart::optionsPreferences, actionCollection()); } void KomparePart::updateActions() { if (m_saveAll) m_saveAll->setEnabled(m_modelList->hasUnsavedChanges()); if (m_saveDiff) m_saveDiff->setEnabled(m_modelList->mode() == Kompare::ComparingFiles || m_modelList->mode() == Kompare::ComparingDirs); if (m_swap) m_swap->setEnabled(m_modelList->mode() == Kompare::ComparingFiles || m_modelList->mode() == Kompare::ComparingDirs); m_diffRefresh->setEnabled(m_modelList->mode() == Kompare::ComparingFiles || m_modelList->mode() == Kompare::ComparingDirs); m_diffStats->setEnabled(m_modelList->modelCount() > 0); m_print->setEnabled(m_modelList->modelCount() > 0); // If modellist has models then we have something to print, it's that simple. m_printPreview->setEnabled(m_modelList); } void KomparePart::setEncoding(const QString& encoding) { qCDebug(KOMPAREPART) << "Encoding: " << encoding; m_modelList->setEncoding(encoding); } bool KomparePart::openDiff(const QUrl& url) { qCDebug(KOMPAREPART) << "Url = " << url.url(); m_info.mode = Kompare::ShowingDiff; m_info.source = url; bool result = false; fetchURL(url, true); - emit kompareInfo(&m_info); + Q_EMIT kompareInfo(&m_info); if (!m_info.localSource.isEmpty()) { qCDebug(KOMPAREPART) << "Download succeeded "; result = m_modelList->openDiff(m_info.localSource); updateActions(); updateCaption(); updateStatus(); } else { qCDebug(KOMPAREPART) << "Download failed !"; } return result; } bool KomparePart::openDiff(const QString& diffOutput) { bool value = false; m_info.mode = Kompare::ShowingDiff; - emit kompareInfo(&m_info); + Q_EMIT kompareInfo(&m_info); if (m_modelList->parseAndOpenDiff(diffOutput) == 0) { value = true; updateActions(); updateCaption(); updateStatus(); } return value; } bool KomparePart::openDiff3(const QUrl& diff3Url) { // FIXME: Implement this !!! qCDebug(KOMPAREPART) << "Not implemented yet. Filename is: " << diff3Url; return false; } bool KomparePart::openDiff3(const QString& diff3Output) { // FIXME: Implement this !!! qCDebug(KOMPAREPART) << "Not implemented yet. diff3 output is: "; qCDebug(KOMPAREPART) << diff3Output; return false; } bool KomparePart::fetchURL(const QUrl& url, bool addToSource) { // Default value if there is an error is "", we rely on it! QString tempFileName; // Only in case of error do we set result to false, don't forget!! bool result = true; QTemporaryDir* tmpDir = nullptr; if (!url.isLocalFile()) { KIO::StatJob* statJob = KIO::stat(url); KJobWidgets::setWindow(statJob, widget()); if (statJob->exec()) { KIO::UDSEntry node; node = statJob->statResult(); if (!node.isDir()) { tmpDir = new QTemporaryDir(QDir::tempPath() + QLatin1String("/kompare")); tmpDir->setAutoRemove(true); tempFileName = tmpDir->path() + QLatin1Char('/') + url.fileName(); KIO::FileCopyJob* copyJob = KIO::file_copy(url, QUrl::fromLocalFile(tempFileName)); KJobWidgets::setWindow(copyJob, widget()); if (! copyJob->exec()) { qDebug() << "download error " << copyJob->errorString(); slotShowError(i18n("The URL %1 cannot be downloaded.", url.toDisplayString())); tempFileName.clear(); // Not sure if download has already touched this tempFileName when there is an error result = false; } } else { tmpDir = new QTemporaryDir(QDir::tempPath() + QLatin1String("/kompare")); tmpDir->setAutoRemove(true); // Yes this is the default but just to make sure KIO::CopyJob* copyJob = KIO::copy(url, QUrl::fromLocalFile(tmpDir->path())); KJobWidgets::setWindow(copyJob, widget()); if (! copyJob->exec()) { slotShowError(i18n("The URL %1 cannot be downloaded.", url.toDisplayString())); delete tmpDir; tmpDir = nullptr; result = false; } else { tempFileName = tmpDir->path(); qCDebug(KOMPAREPART) << "tempFileName = " << tempFileName; // If a directory is copied into QTemporaryDir then the directory in // here is what I need to add to tempFileName QDir dir(tempFileName); QStringList entries = dir.entryList(QDir::Dirs | QDir::NoDotAndDotDot); if (entries.size() == 1) // More than 1 entry in here means big problems!!! { if (!tempFileName.endsWith(QLatin1Char('/'))) tempFileName += QLatin1Char('/'); tempFileName += entries.at(0); tempFileName += QLatin1Char('/'); } else { qCDebug(KOMPAREPART) << "Yikes, nothing downloaded?"; delete tmpDir; tmpDir = nullptr; tempFileName.clear(); result = false; } } } } } else { // is Local already, check if exists if (QFile::exists(url.toLocalFile())) { tempFileName = url.toLocalFile(); } else { slotShowError(i18n("The URL %1 does not exist on your system.", url.toDisplayString())); result = false; } } if (addToSource) { m_info.localSource = tempFileName; m_info.sourceQTempDir = tmpDir; } else { m_info.localDestination = tempFileName; m_info.destinationQTempDir = tmpDir; } return result; } void KomparePart::cleanUpTemporaryFiles() { qCDebug(KOMPAREPART) << "Cleaning temporary files."; if (!m_info.localSource.isEmpty()) { if (m_info.sourceQTempDir) { delete m_info.sourceQTempDir; m_info.sourceQTempDir = nullptr; } m_info.localSource.clear(); } if (!m_info.localDestination.isEmpty()) { if (!m_info.destinationQTempDir) { delete m_info.destinationQTempDir; m_info.destinationQTempDir = nullptr; } m_info.localDestination.clear(); } } void KomparePart::compare(const QUrl& source, const QUrl& destination) { // FIXME: This is silly, i can use NetAccess::stat to figure out what it is and not // wait until i am in the modellist to determine the mode we're supposed to be in. // That should make the code more readable // I should store the QTemporaryDir(s)/File(s) in the Info struct as well and delete it at the right time m_info.source = source; m_info.destination = destination; // FIXME: (Not urgent) But turn this into an enum, for now i cant find a nice name for the enum that has Source and Destination as values // For now we do not do error checking, user has already been notified and if the localString is empty then we do not diff fetchURL(source, true); fetchURL(destination, false); - emit kompareInfo(&m_info); + Q_EMIT kompareInfo(&m_info); compareAndUpdateAll(); } void KomparePart::compareFileString(const QUrl& sourceFile, const QString& destination) { //Set the modeto specify that the source is a file, and the destination is a string m_info.mode = Kompare::ComparingFileString; m_info.source = sourceFile; m_info.localDestination = destination; fetchURL(sourceFile, true); - emit kompareInfo(&m_info); + Q_EMIT kompareInfo(&m_info); compareAndUpdateAll(); } void KomparePart::compareStringFile(const QString& source, const QUrl& destinationFile) { //Set the modeto specify that the source is a file, and the destination is a string m_info.mode = Kompare::ComparingStringFile; m_info.localSource = source; m_info.destination = destinationFile; fetchURL(destinationFile, false); - emit kompareInfo(&m_info); + Q_EMIT kompareInfo(&m_info); compareAndUpdateAll(); } void KomparePart::compareFiles(const QUrl& sourceFile, const QUrl& destinationFile) { m_info.mode = Kompare::ComparingFiles; m_info.source = sourceFile; m_info.destination = destinationFile; // FIXME: (Not urgent) But turn this into an enum, for now i cant find a nice name for the enum that has Source and Destination as values // For now we do not do error checking, user has already been notified and if the localString is empty then we do not diff fetchURL(sourceFile, true); fetchURL(destinationFile, false); - emit kompareInfo(&m_info); + Q_EMIT kompareInfo(&m_info); compareAndUpdateAll(); } void KomparePart::compareDirs(const QUrl& sourceDirectory, const QUrl& destinationDirectory) { m_info.mode = Kompare::ComparingDirs; m_info.source = sourceDirectory; m_info.destination = destinationDirectory; fetchURL(sourceDirectory, true); fetchURL(destinationDirectory, false); - emit kompareInfo(&m_info); + Q_EMIT kompareInfo(&m_info); compareAndUpdateAll(); } void KomparePart::compare3Files(const QUrl& /*originalFile*/, const QUrl& /*changedFile1*/, const QUrl& /*changedFile2*/) { // FIXME: actually implement this some day :) updateActions(); updateCaption(); updateStatus(); } void KomparePart::openFileAndDiff(const QUrl& file, const QUrl& diffFile) { m_info.source = file; m_info.destination = diffFile; fetchURL(file, true); fetchURL(diffFile, false); m_info.mode = Kompare::BlendingFile; - emit kompareInfo(&m_info); + Q_EMIT kompareInfo(&m_info); compareAndUpdateAll(); } void KomparePart::openDirAndDiff(const QUrl& dir, const QUrl& diffFile) { m_info.source = dir; m_info.destination = diffFile; fetchURL(dir, true); fetchURL(diffFile, false); m_info.mode = Kompare::BlendingDir; - emit kompareInfo(&m_info); + Q_EMIT kompareInfo(&m_info); if (!m_info.localSource.isEmpty() && !m_info.localDestination.isEmpty()) { m_modelList->openDirAndDiff(); //Must this be in here? couldn't we use compareAndUpdateAll as well? updateActions(); updateCaption(); updateStatus(); } } bool KomparePart::openFile() { // This is called from openURL // This is a little inefficient but i will do it anyway openDiff(url()); return true; } bool KomparePart::saveAll() { bool result = m_modelList->saveAll(); updateActions(); updateCaption(); updateStatus(); return result; } void KomparePart::saveDiff() { QDialog dlg(widget()); dlg.setObjectName(QStringLiteral("save_options")); dlg.setModal(true); dlg.setWindowTitle(i18nc("@title:window", "Diff Options")); QDialogButtonBox* buttons = new QDialogButtonBox(QDialogButtonBox::Save | QDialogButtonBox::Cancel, &dlg); connect(buttons, &QDialogButtonBox::accepted, &dlg, &QDialog::accept); connect(buttons, &QDialogButtonBox::rejected, &dlg, &QDialog::reject); KompareSaveOptionsWidget* w = new KompareSaveOptionsWidget( m_info.localSource, m_info.localDestination, m_diffSettings, &dlg); QVBoxLayout* layout = new QVBoxLayout(&dlg); layout->addWidget(w); layout->addWidget(buttons); dlg.setLayout(layout); if (dlg.exec()) { w->saveOptions(); KSharedConfig::Ptr config = KSharedConfig::openConfig(); saveProperties(config.data()); config->sync(); while (1) { QUrl url = QFileDialog::getSaveFileUrl(widget(), i18nc("@title:window", "Save .diff"), m_info.destination, i18n("Patch Files (*.diff *.dif *.patch)")); if (url.isLocalFile() && QFile::exists(url.toLocalFile())) { int result = KMessageBox::warningYesNoCancel(widget(), i18n("The file exists or is write-protected; do you want to overwrite it?"), i18nc("@window:title", "File Exists"), KStandardGuiItem::overwrite(), KGuiItem(i18nc("@action:button", "Do Not Overwrite"))); if (result == KMessageBox::Cancel) { break; } else if (result == KMessageBox::No) { continue; } else { qCDebug(KOMPAREPART) << "URL = " << url.toDisplayString(); qCDebug(KOMPAREPART) << "Directory = " << w->directory(); qCDebug(KOMPAREPART) << "DiffSettings = " << m_diffSettings; m_modelList->saveDiff(url.url(), w->directory(), m_diffSettings); break; } } else { qCDebug(KOMPAREPART) << "URL = " << url.toDisplayString(); qCDebug(KOMPAREPART) << "Directory = " << w->directory(); qCDebug(KOMPAREPART) << "DiffSettings = " << m_diffSettings; m_modelList->saveDiff(url.url(), w->directory(), m_diffSettings); break; } } } } void KomparePart::slotFilePrint() { QPrinter printer; printer.setOrientation(QPrinter::Landscape); QPrintDialog* dlg = new QPrintDialog(&printer, nullptr); if (dlg->exec() == QDialog::Accepted) { // do some printing in qprinter slotPaintRequested(&printer); } delete dlg; } void KomparePart::slotFilePrintPreview() { QPrinter printer; printer.setOrientation(QPrinter::Landscape); QPrintPreviewDialog dlg(&printer); connect(&dlg, &QPrintPreviewDialog::paintRequested, this, &KomparePart::slotPaintRequested); dlg.exec(); } void KomparePart::slotPaintRequested(QPrinter* printer) { qCDebug(KOMPAREPART) << "Now paint something..."; QPainter p; p.begin(printer); QSize widgetWidth = m_view->size(); qCDebug(KOMPAREPART) << "printer.width() = " << printer->width(); qCDebug(KOMPAREPART) << "widgetWidth.width() = " << widgetWidth.width(); qreal factor = ((qreal)printer->width()) / ((qreal)widgetWidth.width()); qCDebug(KOMPAREPART) << "factor = " << factor; p.scale(factor, factor); m_view->render(&p); p.end(); qCDebug(KOMPAREPART) << "Done painting something..."; } void KomparePart::slotSetStatus(enum Kompare::Status status) { updateActions(); switch (status) { case Kompare::RunningDiff: - emit setStatusBarText(i18nc("@info:status", "Running diff...")); + Q_EMIT setStatusBarText(i18nc("@info:status", "Running diff...")); break; case Kompare::Parsing: - emit setStatusBarText(i18nc("@info:status", "Parsing diff output...")); + Q_EMIT setStatusBarText(i18nc("@info:status", "Parsing diff output...")); break; case Kompare::FinishedParsing: updateStatus(); break; case Kompare::FinishedWritingDiff: updateStatus(); - emit diffURLChanged(); + Q_EMIT diffURLChanged(); break; default: break; } } void KomparePart::onContextMenuRequested(const QPoint& pos) { QMenu* popup = static_cast(factory()->container(QStringLiteral("mainPopUp"), this)); if (popup) popup->exec(m_view->mapToGlobal(pos)); } void KomparePart::updateCaption() { QString source = m_info.source.toDisplayString(); QString destination = m_info.destination.toDisplayString(); QString text; switch (m_info.mode) { case Kompare::ComparingFiles : case Kompare::ComparingDirs : case Kompare::BlendingFile : case Kompare::BlendingDir : text = source + QLatin1String(" -- ") + destination; // no need to translate this " -- " break; case Kompare::ShowingDiff : text = source; break; default: break; } - emit setWindowCaption(text); + Q_EMIT setWindowCaption(text); } void KomparePart::updateStatus() { QString source = m_info.source.toDisplayString(); QString destination = m_info.destination.toDisplayString(); QString text; switch (m_info.mode) { case Kompare::ComparingFiles : text = i18nc("@info:status", "Comparing file %1 with file %2" , source, destination); break; case Kompare::ComparingDirs : text = i18nc("@info:status", "Comparing files in %1 with files in %2" , source, destination); break; case Kompare::ShowingDiff : text = i18nc("@info:status", "Viewing diff output from %1", source); break; case Kompare::BlendingFile : text = i18nc("@info:status", "Blending diff output from %1 into file %2" , source, destination); break; case Kompare::BlendingDir : text = i18nc("@info:status", "Blending diff output from %1 into folder %2" , m_info.source.toDisplayString(), m_info.destination.toDisplayString()); break; default: break; } - emit setStatusBarText(text); + Q_EMIT setStatusBarText(text); } void KomparePart::compareAndUpdateAll() { if (!m_info.localSource.isEmpty() && !m_info.localDestination.isEmpty()) { switch (m_info.mode) { default: case Kompare::UnknownMode: m_modelList->compare(); break; case Kompare::ComparingStringFile: case Kompare::ComparingFileString: case Kompare::ComparingFiles: case Kompare::ComparingDirs: m_modelList->compare(m_info.mode); break; case Kompare::BlendingFile: m_modelList->openFileAndDiff(); break; } updateCaption(); updateStatus(); } updateActions(); } void KomparePart::slotShowError(const QString& error) { KMessageBox::error(widget(), error); } void KomparePart::slotSwap() { if (m_modelList->hasUnsavedChanges()) { int query = KMessageBox::warningYesNoCancel ( widget(), i18n("You have made changes to the destination file(s).\n" "Would you like to save them?"), i18nc("@title:window", "Save Changes?"), KStandardGuiItem::save(), KStandardGuiItem::discard() ); if (query == KMessageBox::Yes) m_modelList->saveAll(); if (query == KMessageBox::Cancel) return; // Abort prematurely so no swapping } // Swap the info in the Kompare::Info struct m_info.swapSourceWithDestination(); // Update window caption and statusbar text updateCaption(); updateStatus(); m_modelList->swap(); } void KomparePart::slotRefreshDiff() { if (m_modelList->hasUnsavedChanges()) { int query = KMessageBox::warningYesNoCancel ( widget(), i18n("You have made changes to the destination file(s).\n" "Would you like to save them?"), i18nc("@title:window", "Save Changes?"), KStandardGuiItem::save(), KStandardGuiItem::discard() ); if (query == KMessageBox::Cancel) return; // Abort prematurely so no refreshing if (query == KMessageBox::Yes) m_modelList->saveAll(); } // For this to work properly you have to refetch the files from their (remote) locations cleanUpTemporaryFiles(); fetchURL(m_info.source, true); fetchURL(m_info.destination, false); m_modelList->refresh(); } void KomparePart::slotShowDiffstats() { // Fetch all the args needed for komparestatsmessagebox // oldfile, newfile, diffformat, noofhunks, noofdiffs QString oldFile; QString newFile; QString diffFormat; int filesInDiff; int noOfHunks; int noOfDiffs; oldFile = m_modelList->selectedModel() ? m_modelList->selectedModel()->sourceFile() : QString(); newFile = m_modelList->selectedModel() ? m_modelList->selectedModel()->destinationFile() : QString(); if (m_modelList->selectedModel()) { switch (m_info.format) { case Kompare::Unified : diffFormat = i18nc("@item diff format", "Unified"); break; case Kompare::Context : diffFormat = i18nc("@item diff format", "Context"); break; case Kompare::RCS : diffFormat = i18nc("@item diff format", "RCS"); break; case Kompare::Ed : diffFormat = i18nc("@item diff format", "Ed"); break; case Kompare::Normal : diffFormat = i18nc("@item diff format", "Normal"); break; case Kompare::UnknownFormat : default: diffFormat = i18nc("@item diff format", "Unknown"); break; } } else { diffFormat.clear(); } filesInDiff = m_modelList->modelCount(); noOfHunks = m_modelList->selectedModel() ? m_modelList->selectedModel()->hunkCount() : 0; noOfDiffs = m_modelList->selectedModel() ? m_modelList->selectedModel()->differenceCount() : 0; if (m_modelList->modelCount() == 0) { // no diff loaded yet KMessageBox::information(nullptr, i18n( "No diff file, or no 2 files have been diffed. " "Therefore no stats are available."), i18nc("@title:window", "Diff Statistics"), QString(), KMessageBox::Options()); } else if (m_modelList->modelCount() == 1) { // 1 file in diff, or 2 files compared KMessageBox::information(nullptr, i18n( "Statistics:\n" "\n" "Old file: %1\n" "New file: %2\n" "\n" "Format: %3\n" "Number of hunks: %4\n" "Number of differences: %5", oldFile, newFile, diffFormat, noOfHunks, noOfDiffs), i18nc("@title:window", "Diff Statistics"), QString(), KMessageBox::Options()); } else { // more than 1 file in diff, or 2 directories compared KMessageBox::information(nullptr, ki18n( "Statistics:\n" "\n" "Number of files in diff file: %1\n" "Format: %2\n" "\n" "Current old file: %3\n" "Current new file: %4\n" "\n" "Number of hunks: %5\n" "Number of differences: %6") .subs(filesInDiff).subs(diffFormat).subs(oldFile) .subs(newFile).subs(noOfHunks).subs(noOfDiffs) .toString(), i18nc("@title:window", "Diff Statistics"), QString(), KMessageBox::Options()); } } bool KomparePart::queryClose() { if (!m_modelList->hasUnsavedChanges()) return true; int query = KMessageBox::warningYesNoCancel ( widget(), i18n("You have made changes to the destination file(s).\n" "Would you like to save them?"), i18nc("@title:window", "Save Changes?"), KStandardGuiItem::save(), KStandardGuiItem::discard() ); if (query == KMessageBox::Cancel) return false; if (query == KMessageBox::Yes) return m_modelList->saveAll(); return true; } void KomparePart::setReadWrite(bool readWrite) { m_modelList->setReadWrite(readWrite); KParts::ReadWritePart::setReadWrite(readWrite); } int KomparePart::readProperties(KConfig* config) { m_viewSettings->loadSettings(config); m_diffSettings->loadSettings(config); - emit configChanged(); + Q_EMIT configChanged(); return 0; } int KomparePart::saveProperties(KConfig* config) { m_viewSettings->saveSettings(config); m_diffSettings->saveSettings(config); return 0; } void KomparePart::optionsPreferences() { // show preferences KomparePrefDlg pref(m_viewSettings, m_diffSettings); connect(&pref, &KomparePrefDlg::configChanged, this, &KomparePart::configChanged); if (pref.exec()) - emit configChanged(); + Q_EMIT configChanged(); } diff --git a/komparepart/komparelistview.cpp b/komparepart/komparelistview.cpp index ff20739..e47aaaf 100644 --- a/komparepart/komparelistview.cpp +++ b/komparepart/komparelistview.cpp @@ -1,980 +1,980 @@ /*************************************************************************** komparelistview.h ----------------- begin : Sun Mar 4 2001 Copyright 2001-2009 Otto Bruggeman Copyright 2001-2003 John Firebaugh Copyright 2004 Jeff Snyder Copyright 2007-2012 Kevin Kofler ****************************************************************************/ /*************************************************************************** ** ** This program is free software; you can redistribute it and/or modify ** it under the terms of the GNU General Public License as published by ** the Free Software Foundation; either version 2 of the License, or ** (at your option) any later version. ** ***************************************************************************/ #include "komparelistview.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "viewsettings.h" #include "komparesplitter.h" #define COL_LINE_NO 0 #define COL_MAIN 1 #define BLANK_LINE_HEIGHT 3 #define HUNK_LINE_HEIGHT 5 #define ITEM_MARGIN 3 using namespace Diff2; KompareListViewFrame::KompareListViewFrame(bool isSource, ViewSettings* settings, KompareSplitter* parent, const char* name): QFrame(parent), m_view(isSource, settings, this, name), m_label(isSource ? QStringLiteral("Source") : QStringLiteral("Dest"), this), m_layout(this) { setSizePolicy(QSizePolicy(QSizePolicy::Ignored, QSizePolicy::Ignored)); m_label.setSizePolicy(QSizePolicy(QSizePolicy::Ignored, QSizePolicy::Fixed)); QFrame* bottomLine = new QFrame(this); bottomLine->setFrameShape(QFrame::HLine); bottomLine->setFrameShadow(QFrame::Plain); bottomLine->setSizePolicy(QSizePolicy(QSizePolicy::Ignored, QSizePolicy::Fixed)); bottomLine->setFixedHeight(1); m_label.setMargin(3); m_layout.setSpacing(0); m_layout.setContentsMargins(0, 0, 0, 0); m_layout.addWidget(&m_label); m_layout.addWidget(bottomLine); m_layout.addWidget(&m_view); connect(&m_view, &KompareListView::differenceClicked, parent, &KompareSplitter::slotDifferenceClicked); connect(parent, &KompareSplitter::scrollViewsToId, &m_view, &KompareListView::scrollToId); connect(parent, &KompareSplitter::setXOffset, &m_view, &KompareListView::setXOffset); connect(&m_view, &KompareListView::resized, parent, &KompareSplitter::slotUpdateScrollBars); } void KompareListViewFrame::slotSetModel(const DiffModel* model) { if (model) { if (view()->isSource()) { if (!model->sourceRevision().isEmpty()) m_label.setText(model->sourceFile() + QLatin1String(" (") + model->sourceRevision() + QLatin1Char(')')); else m_label.setText(model->sourceFile()); } else { if (!model->destinationRevision().isEmpty()) m_label.setText(model->destinationFile() + QLatin1String(" (") + model->destinationRevision() + QLatin1Char(')')); else m_label.setText(model->destinationFile()); } } else { m_label.setText(QString()); } } KompareListView::KompareListView(bool isSource, ViewSettings* settings, QWidget* parent, const char* name) : QTreeWidget(parent), m_isSource(isSource), m_settings(settings), m_scrollId(-1), m_selectedModel(nullptr), m_selectedDifference(nullptr) { setObjectName(QLatin1String(name)); setItemDelegate(new KompareListViewItemDelegate(this)); setHeaderHidden(true); setColumnCount(3); // Line Number, Main, Blank setAllColumnsShowFocus(true); setRootIsDecorated(false); setIndentation(0); setFrameStyle(QFrame::NoFrame); setVerticalScrollMode(QAbstractItemView::ScrollPerPixel); setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff); setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); setFocusPolicy(Qt::NoFocus); setFont(m_settings->m_font); setFocusProxy(parent->parentWidget()); } KompareListView::~KompareListView() { m_settings = nullptr; m_selectedModel = nullptr; m_selectedDifference = nullptr; } KompareListViewItem* KompareListView::itemAtIndex(int i) { return m_items[ i ]; } int KompareListView::firstVisibleDifference() { QTreeWidgetItem* item = itemAt(QPoint(0, 0)); if (item == nullptr) { qCDebug(KOMPAREPART) << "no item at viewport coordinates (0,0)" ; } while (item) { KompareListViewLineItem* lineItem = dynamic_cast(item); if (lineItem && lineItem->diffItemParent()->difference()->type() != Difference::Unchanged) break; item = itemBelow(item); } if (item) return m_items.indexOf(((KompareListViewLineItem*)item)->diffItemParent()); return -1; } int KompareListView::lastVisibleDifference() { QTreeWidgetItem* item = itemAt(QPoint(0, visibleHeight() - 1)); if (item == nullptr) { qCDebug(KOMPAREPART) << "no item at viewport coordinates (0," << visibleHeight() - 1 << ")" ; // find last item item = itemAt(QPoint(0, 0)); if (item) { QTreeWidgetItem* nextItem = item; do { item = nextItem; nextItem = itemBelow(item); } while (nextItem); } } while (item) { KompareListViewLineItem* lineItem = dynamic_cast(item); if (lineItem && lineItem->diffItemParent()->difference()->type() != Difference::Unchanged) break; item = itemAbove(item); } if (item) return m_items.indexOf(((KompareListViewLineItem*)item)->diffItemParent()); return -1; } QRect KompareListView::totalVisualItemRect(QTreeWidgetItem* item) { QRect total = visualItemRect(item); int n = item->childCount(); for (int i = 0; i < n; ++i) { QTreeWidgetItem* child = item->child(i); if (!child->isHidden()) total = total.united(totalVisualItemRect(child)); } return total; } QRect KompareListView::itemRect(int i) { QTreeWidgetItem* item = itemAtIndex(i); return totalVisualItemRect(item); } int KompareListView::minScrollId() { return visibleHeight() / 2; } int KompareListView::maxScrollId() { int n = topLevelItemCount(); if (!n) return 0; KompareListViewItem* item = (KompareListViewItem*)topLevelItem(n - 1); int maxId = item->scrollId() + item->maxHeight() - minScrollId(); qCDebug(KOMPAREPART) << "Max ID = " << maxId ; return maxId; } int KompareListView::contentsHeight() { return verticalScrollBar()->maximum() + viewport()->height() - style()->pixelMetric(QStyle::PM_ScrollBarExtent); } int KompareListView::contentsWidth() { return (columnWidth(COL_LINE_NO) + columnWidth(COL_MAIN)); } int KompareListView::visibleHeight() { return viewport()->height(); } int KompareListView::visibleWidth() { return viewport()->width(); } int KompareListView::contentsX() { return horizontalOffset(); } int KompareListView::contentsY() { return verticalOffset(); } int KompareListView::nextPaintOffset() const { return m_nextPaintOffset; } void KompareListView::setNextPaintOffset(int offset) { m_nextPaintOffset = offset; } void KompareListView::setXOffset(int x) { qCDebug(KOMPAREPART) << "SetXOffset : Scroll to x position: " << x ; horizontalScrollBar()->setValue(x); } void KompareListView::scrollToId(int id) { // qCDebug(KOMPAREPART) << "ScrollToID : Scroll to id : " << id ; int n = topLevelItemCount(); KompareListViewItem* item = nullptr; if (n) { int i = 1; for (; i < n; ++i) { if (((KompareListViewItem*)topLevelItem(i))->scrollId() > id) break; } item = (KompareListViewItem*)topLevelItem(i - 1); } if (item) { QRect rect = totalVisualItemRect(item); int pos = rect.top() + verticalOffset(); int itemId = item->scrollId(); int height = rect.height(); double r = (double)(id - itemId) / (double)item->maxHeight(); int y = pos + (int)(r * (double)height) - minScrollId(); // qCDebug(KOMPAREPART) << "scrollToID: " ; // qCDebug(KOMPAREPART) << " id = " << id ; // qCDebug(KOMPAREPART) << " pos = " << pos ; // qCDebug(KOMPAREPART) << " itemId = " << itemId ; // qCDebug(KOMPAREPART) << " r = " << r ; // qCDebug(KOMPAREPART) << " height = " << height ; // qCDebug(KOMPAREPART) << " minID = " << minScrollId() ; // qCDebug(KOMPAREPART) << " y = " << y ; // qCDebug(KOMPAREPART) << "contentsHeight = " << contentsHeight() ; // qCDebug(KOMPAREPART) << " c - y = " << contentsHeight() - y ; verticalScrollBar()->setValue(y); } m_scrollId = id; } int KompareListView::scrollId() { if (m_scrollId < 0) m_scrollId = minScrollId(); return m_scrollId; } void KompareListView::setSelectedDifference(const Difference* diff, bool scroll) { qCDebug(KOMPAREPART) << "KompareListView::setSelectedDifference(" << diff << ", " << scroll << ")" ; // When something other than a click causes this function to be called, // it'll only get called once, and all is simple. // // When the user clicks on a diff, this function will get called once when // komparesplitter::slotDifferenceClicked runs, and again when the // setSelection signal from the modelcontroller arrives. // // the first call (which will always be from the splitter) will have // scroll==false, and the second call will bail out here. // Which is why clicking on a difference does not cause the listviews to // scroll. if (m_selectedDifference == diff) return; m_selectedDifference = diff; KompareListViewItem* item = m_itemDict[ diff ]; if (!item) { qCDebug(KOMPAREPART) << "KompareListView::slotSetSelection(): couldn't find our selection!" ; return; } // why does this not happen when the user clicks on a diff? see the comment above. if (scroll) scrollToId(item->scrollId()); setUpdatesEnabled(false); int x = horizontalScrollBar()->value(); int y = verticalScrollBar()->value(); setCurrentItem(item); horizontalScrollBar()->setValue(x); verticalScrollBar()->setValue(y); setUpdatesEnabled(true); } void KompareListView::slotSetSelection(const Difference* diff) { qCDebug(KOMPAREPART) << "KompareListView::slotSetSelection( const Difference* diff )" ; setSelectedDifference(diff, true); } void KompareListView::slotSetSelection(const DiffModel* model, const Difference* diff) { qCDebug(KOMPAREPART) << "KompareListView::slotSetSelection( const DiffModel* model, const Difference* diff )" ; if (m_selectedModel && m_selectedModel == model) { slotSetSelection(diff); return; } clear(); m_items.clear(); m_itemDict.clear(); m_selectedModel = model; DiffHunkListConstIterator hunkIt = model->hunks()->begin(); DiffHunkListConstIterator hEnd = model->hunks()->end(); KompareListViewItem* item = nullptr; m_nextPaintOffset = 0; for (; hunkIt != hEnd; ++hunkIt) { if (item) item = new KompareListViewHunkItem(this, item, *hunkIt, model->isBlended()); else item = new KompareListViewHunkItem(this, *hunkIt, model->isBlended()); DifferenceListConstIterator diffIt = (*hunkIt)->differences().begin(); DifferenceListConstIterator dEnd = (*hunkIt)->differences().end(); for (; diffIt != dEnd; ++diffIt) { item = new KompareListViewDiffItem(this, item, *diffIt); int type = (*diffIt)->type(); if (type != Difference::Unchanged) { m_items.append((KompareListViewDiffItem*)item); m_itemDict.insert(*diffIt, (KompareListViewDiffItem*)item); } } } resizeColumnToContents(COL_LINE_NO); resizeColumnToContents(COL_MAIN); slotSetSelection(diff); } KompareListViewDiffItem* KompareListView::diffItemAt(const QPoint& pos) { KompareListViewItem* item = static_cast(itemAt(pos)); if (!item) return nullptr; switch (item->type()) { case KompareListViewItem::Hunk: if (item->paintHeight()) return nullptr; // no diff item here // zero height (fake 1 pixel height), so a diff item shines through return static_cast(itemBelow(item)); case KompareListViewItem::Line: case KompareListViewItem::Blank: return static_cast(item)->diffItemParent(); case KompareListViewItem::Container: return static_cast(item)->diffItemParent(); case KompareListViewItem::Diff: return static_cast(item); default: return nullptr; } } void KompareListView::mousePressEvent(QMouseEvent* e) { QPoint vp = e->pos(); KompareListViewDiffItem* diffItem = diffItemAt(vp); if (diffItem && diffItem->difference()->type() != Difference::Unchanged) { - emit differenceClicked(diffItem->difference()); + Q_EMIT differenceClicked(diffItem->difference()); } } void KompareListView::mouseDoubleClickEvent(QMouseEvent* e) { QPoint vp = e->pos(); KompareListViewDiffItem* diffItem = diffItemAt(vp); if (diffItem && diffItem->difference()->type() != Difference::Unchanged) { // FIXME: make a new signal that does both - emit differenceClicked(diffItem->difference()); - emit applyDifference(!diffItem->difference()->applied()); + Q_EMIT differenceClicked(diffItem->difference()); + Q_EMIT applyDifference(!diffItem->difference()->applied()); } } void KompareListView::renumberLines() { // qCDebug(KOMPAREPART) << "Begin" ; unsigned int newLineNo = 1; if (!topLevelItemCount()) return; KompareListViewItem* item = (KompareListViewItem*)topLevelItem(0); while (item) { // qCDebug(KOMPAREPART) << "type: " << item->type() ; if (item->type() != KompareListViewItem::Container && item->type() != KompareListViewItem::Blank && item->type() != KompareListViewItem::Hunk) { // qCDebug(KOMPAREPART) << QString::number( newLineNo ) ; item->setText(COL_LINE_NO, QString::number(newLineNo++)); } item = (KompareListViewItem*)itemBelow(item); } } void KompareListView::slotApplyDifference(bool apply) { m_itemDict[ m_selectedDifference ]->applyDifference(apply); // now renumber the line column if this is the destination if (!m_isSource) renumberLines(); } void KompareListView::slotApplyAllDifferences(bool apply) { QHash::ConstIterator it = m_itemDict.constBegin(); QHash::ConstIterator end = m_itemDict.constEnd(); for (; it != end; ++it) it.value()->applyDifference(apply); // now renumber the line column if this is the destination if (!m_isSource) renumberLines(); update(); } void KompareListView::slotApplyDifference(const Difference* diff, bool apply) { m_itemDict[ diff ]->applyDifference(apply); // now renumber the line column if this is the destination if (!m_isSource) renumberLines(); } void KompareListView::wheelEvent(QWheelEvent* e) { e->ignore(); // we want the parent to catch wheel events } void KompareListView::resizeEvent(QResizeEvent* e) { QTreeWidget::resizeEvent(e); - emit resized(); + Q_EMIT resized(); } KompareListViewItemDelegate::KompareListViewItemDelegate(QObject* parent) : QStyledItemDelegate(parent) { } KompareListViewItemDelegate::~KompareListViewItemDelegate() { } void KompareListViewItemDelegate::paint(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index) const { int column = index.column(); QStyleOptionViewItem changedOption = option; if (column == COL_LINE_NO) changedOption.displayAlignment = Qt::AlignRight; KompareListViewItem* item = static_cast(static_cast(parent())->itemFromIndex(index)); item->paintCell(painter, changedOption, column); } QSize KompareListViewItemDelegate::sizeHint(const QStyleOptionViewItem& option, const QModelIndex& index) const { KompareListViewItem* item = static_cast(static_cast(parent())->itemFromIndex(index)); QSize hint = QStyledItemDelegate::sizeHint(option, index); return QSize(hint.width() + ITEM_MARGIN, item->height()); } KompareListViewItem::KompareListViewItem(KompareListView* parent, int type) : QTreeWidgetItem(parent, type), m_scrollId(0), m_height(0), m_paintHeight(0), m_paintOffset(parent->nextPaintOffset()) { // qCDebug(KOMPAREPART) << "Created KompareListViewItem with scroll id " << m_scrollId ; } KompareListViewItem::KompareListViewItem(KompareListView* parent, KompareListViewItem* after, int type) : QTreeWidgetItem(parent, after, type), m_scrollId(after->scrollId() + after->maxHeight()), m_height(0), m_paintHeight(0), m_paintOffset(parent->nextPaintOffset()) { // qCDebug(KOMPAREPART) << "Created KompareListViewItem with scroll id " << m_scrollId ; } KompareListViewItem::KompareListViewItem(KompareListViewItem* parent, int type) : QTreeWidgetItem(parent, type), m_scrollId(0), m_height(0), m_paintHeight(0), m_paintOffset(parent->kompareListView()->nextPaintOffset()) { } KompareListViewItem::KompareListViewItem(KompareListViewItem* parent, KompareListViewItem* /*after*/, int type) : QTreeWidgetItem(parent, type), m_scrollId(0), m_height(0), m_paintHeight(0), m_paintOffset(parent->kompareListView()->nextPaintOffset()) { } int KompareListViewItem::height() const { return m_height; } void KompareListViewItem::setHeight(int h) { m_height = m_paintHeight = h; // QTreeWidget doesn't like zero height, fudge around it. m_height -= m_paintOffset; if (m_height <= 0) { kompareListView()->setNextPaintOffset(1 - m_height); m_height = 1; } else kompareListView()->setNextPaintOffset(0); } int KompareListViewItem::paintHeight() const { return m_paintHeight; } int KompareListViewItem::paintOffset() const { return m_paintOffset; } bool KompareListViewItem::isCurrent() const { return treeWidget()->currentItem() == this; } KompareListView* KompareListViewItem::kompareListView() const { return (KompareListView*)treeWidget(); } void KompareListViewItem::paintCell(QPainter* p, const QStyleOptionViewItem& option, int column) { // Default implementation for zero-height items. // We have to paint the item which shines through or we'll end up with glitches. KompareListViewItem* nextItem = (KompareListViewItem*)kompareListView()->itemBelow(this); if (nextItem) { QStyleOptionViewItem changedOption = option; changedOption.rect.translate(0, height()); nextItem->paintCell(p, changedOption, column); } } KompareListViewDiffItem::KompareListViewDiffItem(KompareListView* parent, Difference* difference) : KompareListViewItem(parent, Diff), m_difference(difference), m_sourceItem(nullptr), m_destItem(nullptr) { init(); } KompareListViewDiffItem::KompareListViewDiffItem(KompareListView* parent, KompareListViewItem* after, Difference* difference) : KompareListViewItem(parent, after, Diff), m_difference(difference), m_sourceItem(nullptr), m_destItem(nullptr) { init(); } KompareListViewDiffItem::~KompareListViewDiffItem() { m_difference = nullptr; } void KompareListViewDiffItem::init() { setHeight(0); setExpanded(true); int nextPaintOffset = kompareListView()->nextPaintOffset(); m_destItem = new KompareListViewLineContainerItem(this, false); kompareListView()->setNextPaintOffset(nextPaintOffset); m_sourceItem = new KompareListViewLineContainerItem(this, true); setVisibility(); } void KompareListViewDiffItem::setVisibility() { m_sourceItem->setHidden(!(kompareListView()->isSource() || m_difference->applied())); m_destItem->setHidden(!m_sourceItem->isHidden()); } void KompareListViewDiffItem::applyDifference(bool apply) { qCDebug(KOMPAREPART) << "KompareListViewDiffItem::applyDifference( " << apply << " )" ; setVisibility(); } int KompareListViewDiffItem::maxHeight() { int lines = qMax(m_difference->sourceLineCount(), m_difference->destinationLineCount()); if (lines == 0) return BLANK_LINE_HEIGHT; else return lines * treeWidget()->fontMetrics().height(); } KompareListViewLineContainerItem::KompareListViewLineContainerItem(KompareListViewDiffItem* parent, bool isSource) : KompareListViewItem(parent, Container), m_blankLineItem(nullptr), m_isSource(isSource) { // qCDebug(KOMPAREPART) << "isSource ? " << (isSource ? " Yes!" : " No!") ; setHeight(0); setExpanded(true); int lines = lineCount(); int line = lineNumber(); // qCDebug(KOMPAREPART) << "LineNumber : " << lineNumber() ; if (lines == 0) { m_blankLineItem = new KompareListViewBlankLineItem(this); return; } for (int i = 0; i < lines; ++i, ++line) { new KompareListViewLineItem(this, line, lineAt(i)); } } KompareListViewLineContainerItem::~KompareListViewLineContainerItem() { } KompareListViewDiffItem* KompareListViewLineContainerItem::diffItemParent() const { return (KompareListViewDiffItem*)parent(); } int KompareListViewLineContainerItem::lineCount() const { return m_isSource ? diffItemParent()->difference()->sourceLineCount() : diffItemParent()->difference()->destinationLineCount(); } int KompareListViewLineContainerItem::lineNumber() const { return m_isSource ? diffItemParent()->difference()->sourceLineNumber() : diffItemParent()->difference()->destinationLineNumber(); } DifferenceString* KompareListViewLineContainerItem::lineAt(int i) const { return m_isSource ? diffItemParent()->difference()->sourceLineAt(i) : diffItemParent()->difference()->destinationLineAt(i); } KompareListViewLineItem::KompareListViewLineItem(KompareListViewLineContainerItem* parent, int line, DifferenceString* text) : KompareListViewItem(parent, Line) { init(line, text); } KompareListViewLineItem::KompareListViewLineItem(KompareListViewLineContainerItem* parent, int line, DifferenceString* text, int type) : KompareListViewItem(parent, type) { init(line, text); } KompareListViewLineItem::~KompareListViewLineItem() { m_text = nullptr; } void KompareListViewLineItem::init(int line, DifferenceString* text) { setHeight(treeWidget()->fontMetrics().height()); setText(COL_LINE_NO, QString::number(line)); setText(COL_MAIN, text->string()); m_text = text; } void KompareListViewLineItem::paintCell(QPainter* p, const QStyleOptionViewItem& option, int column) { int width = option.rect.width(); Qt::Alignment align = option.displayAlignment; p->setRenderHint(QPainter::Antialiasing); p->translate(option.rect.topLeft()); p->translate(0, -paintOffset()); QColor bg(Qt::white); // Always make the background white when it is not a real difference if (diffItemParent()->difference()->type() == Difference::Unchanged) { if (column == COL_LINE_NO) { bg = QColor(Qt::lightGray); } } else { bg = kompareListView()->settings()->colorForDifferenceType( diffItemParent()->difference()->type(), diffItemParent()->isCurrent(), diffItemParent()->difference()->applied()); } // Paint background p->fillRect(0, 0, width, paintHeight(), bg); // Paint foreground if (diffItemParent()->difference()->type() == Difference::Unchanged) p->setPen(QColor(Qt::darkGray)); // always make normal text gray else p->setPen(QColor(Qt::black)); // make text with changes black paintText(p, bg, column, width, align); // Paint darker lines around selected item if (diffItemParent()->isCurrent()) { p->translate(0.5, 0.5); p->setPen(bg.darker(135)); QTreeWidgetItem* parentItem = parent(); if (this == parentItem->child(0)) p->drawLine(0, 0, width, 0); if (this == parentItem->child(parentItem->childCount() - 1)) p->drawLine(0, paintHeight() - 1, width, paintHeight() - 1); } p->resetTransform(); } void KompareListViewLineItem::paintText(QPainter* p, const QColor& bg, int column, int width, int align) { if (column == COL_MAIN) { QString textChunk; int offset = ITEM_MARGIN; int prevValue = 0; int charsDrawn = 0; int chunkWidth; QBrush changeBrush(bg, Qt::Dense3Pattern); QBrush normalBrush(bg, Qt::SolidPattern); QBrush brush; if (m_text->string().isEmpty()) { p->fillRect(0, 0, width, paintHeight(), normalBrush); return; } p->fillRect(0, 0, offset, paintHeight(), normalBrush); if (!m_text->markerList().isEmpty()) { MarkerListConstIterator markerIt = m_text->markerList().begin(); MarkerListConstIterator mEnd = m_text->markerList().end(); Marker* m = *markerIt; for (; markerIt != mEnd; ++markerIt) { m = *markerIt; textChunk = m_text->string().mid(prevValue, m->offset() - prevValue); // qCDebug(KOMPAREPART) << "TextChunk = \"" << textChunk << "\"" ; // qCDebug(KOMPAREPART) << "c->offset() = " << c->offset() ; // qCDebug(KOMPAREPART) << "prevValue = " << prevValue ; expandTabs(textChunk, kompareListView()->settings()->m_tabToNumberOfSpaces, charsDrawn); charsDrawn += textChunk.length(); prevValue = m->offset(); if (m->type() == Marker::End) { QFont font(p->font()); font.setBold(true); p->setFont(font); // p->setPen( Qt::blue ); brush = changeBrush; } else { QFont font(p->font()); font.setBold(false); p->setFont(font); // p->setPen( Qt::black ); brush = normalBrush; } #if QT_VERSION >= QT_VERSION_CHECK(5, 11, 0) chunkWidth = p->fontMetrics().horizontalAdvance(textChunk); #else chunkWidth = p->fontMetrics().width(textChunk); #endif p->fillRect(offset, 0, chunkWidth, paintHeight(), brush); p->drawText(offset, 0, chunkWidth, paintHeight(), align, textChunk); offset += chunkWidth; } } if (prevValue < m_text->string().length()) { // Still have to draw some string without changes textChunk = m_text->string().mid(prevValue, qMax(1, m_text->string().length() - prevValue)); expandTabs(textChunk, kompareListView()->settings()->m_tabToNumberOfSpaces, charsDrawn); // qCDebug(KOMPAREPART) << "TextChunk = \"" << textChunk << "\"" ; QFont font(p->font()); font.setBold(false); p->setFont(font); #if QT_VERSION >= QT_VERSION_CHECK(5, 11, 0) chunkWidth = p->fontMetrics().horizontalAdvance(textChunk); #else chunkWidth = p->fontMetrics().width(textChunk); #endif p->fillRect(offset, 0, chunkWidth, paintHeight(), normalBrush); p->drawText(offset, 0, chunkWidth, paintHeight(), align, textChunk); offset += chunkWidth; } p->fillRect(offset, 0, width - offset, paintHeight(), normalBrush); } else { p->fillRect(0, 0, width, paintHeight(), bg); p->drawText(ITEM_MARGIN, 0, width - ITEM_MARGIN, paintHeight(), align, text(column)); } } void KompareListViewLineItem::expandTabs(QString& text, int tabstop, int startPos) const { int index; while ((index = text.indexOf(QChar(9))) != -1) text.replace(index, 1, QString(tabstop - ((startPos + index) % tabstop), QLatin1Char(' '))); } KompareListViewDiffItem* KompareListViewLineItem::diffItemParent() const { KompareListViewLineContainerItem* p = (KompareListViewLineContainerItem*)parent(); return p->diffItemParent(); } KompareListViewBlankLineItem::KompareListViewBlankLineItem(KompareListViewLineContainerItem* parent) : KompareListViewLineItem(parent, 0, new DifferenceString(), Blank) { setHeight(BLANK_LINE_HEIGHT); } void KompareListViewBlankLineItem::paintText(QPainter* p, const QColor& bg, int column, int width, int /* align */) { if (column == COL_MAIN) { QBrush normalBrush(bg, Qt::SolidPattern); p->fillRect(0, 0, width, paintHeight(), normalBrush); } } KompareListViewHunkItem::KompareListViewHunkItem(KompareListView* parent, DiffHunk* hunk, bool zeroHeight) : KompareListViewItem(parent, Hunk), m_zeroHeight(zeroHeight), m_hunk(hunk) { setHeight(maxHeight()); setFlags(flags() & ~Qt::ItemIsSelectable); } KompareListViewHunkItem::KompareListViewHunkItem(KompareListView* parent, KompareListViewItem* after, DiffHunk* hunk, bool zeroHeight) : KompareListViewItem(parent, after, Hunk), m_zeroHeight(zeroHeight), m_hunk(hunk) { setHeight(maxHeight()); setFlags(flags() & ~Qt::ItemIsSelectable); } KompareListViewHunkItem::~KompareListViewHunkItem() { m_hunk = nullptr; } int KompareListViewHunkItem::maxHeight() { if (m_zeroHeight) { return 0; } else if (m_hunk->function().isEmpty()) { return HUNK_LINE_HEIGHT; } else { return treeWidget()->fontMetrics().height(); } } void KompareListViewHunkItem::paintCell(QPainter* p, const QStyleOptionViewItem& option, int column) { if (m_zeroHeight) { KompareListViewItem::paintCell(p, option, column); } else { int x = option.rect.left(); int y = option.rect.top() - paintOffset(); int width = option.rect.width(); Qt::Alignment align = option.displayAlignment; p->fillRect(x, y, width, paintHeight(), QColor(Qt::lightGray)); // Hunk headers should be lightgray p->setPen(QColor(Qt::black)); // Text color in hunk should be black if (column == COL_MAIN) { p->drawText(x + ITEM_MARGIN, y, width - ITEM_MARGIN, paintHeight(), align, m_hunk->function()); } } } diff --git a/komparepart/kompareprefdlg.cpp b/komparepart/kompareprefdlg.cpp index 9aef6de..f20512f 100644 --- a/komparepart/kompareprefdlg.cpp +++ b/komparepart/kompareprefdlg.cpp @@ -1,156 +1,156 @@ /*************************************************************************** kompareprefdlg.cpp ------------------ begin : Sun Mar 4 2001 Copyright 2001-2009 Otto Bruggeman Copyright 2001-2003 John Firebaugh Copyright 2007 Kevin Kofler ****************************************************************************/ /*************************************************************************** ** ** This program is free software; you can redistribute it and/or modify ** it under the terms of the GNU General Public License as published by ** the Free Software Foundation; either version 2 of the License, or ** (at your option) any later version. ** ***************************************************************************/ #include "kompareprefdlg.h" #include #include #include #include #include #include "diffpage.h" #include "viewpage.h" // implementation KomparePrefDlg::KomparePrefDlg(ViewSettings* viewSets, DiffSettings* diffSets) : KPageDialog(nullptr) { setFaceType(KPageDialog::List); setWindowTitle(i18nc("@title:window", "Preferences")); setStandardButtons(QDialogButtonBox::Help | QDialogButtonBox::Reset | QDialogButtonBox::Ok | QDialogButtonBox::Apply | QDialogButtonBox::Cancel); setModal(true); KGuiItem::assign(button(QDialogButtonBox::Reset), KStandardGuiItem::defaults()); // ok i need some stuff in that pref dlg... //setIconListAllVisible(true); m_viewPage = new ViewPage(); KPageWidgetItem* item = addPage(m_viewPage, i18nc("@title:tab", "View")); item->setIcon(QIcon::fromTheme(QStringLiteral("preferences-desktop-theme"))); item->setHeader(i18nc("@title", "View Settings")); m_viewPage->setSettings(viewSets); m_diffPage = new DiffPage(); item = addPage(m_diffPage, i18nc("@title:tab", "Diff")); item->setIcon(QIcon::fromTheme(QStringLiteral("text-x-patch"))); item->setHeader(i18nc("@title", "Diff Settings")); m_diffPage->setSettings(diffSets); // frame = addVBoxPage(i18n(""), i18n(""), UserIcon("")); connect(button(QDialogButtonBox::Reset), &QPushButton::clicked, this, &KomparePrefDlg::slotDefault); connect(button(QDialogButtonBox::Help), &QPushButton::clicked, this, &KomparePrefDlg::slotHelp); connect(button(QDialogButtonBox::Apply), &QPushButton::clicked, this, &KomparePrefDlg::slotApply); connect(button(QDialogButtonBox::Ok), &QPushButton::clicked, this, &KomparePrefDlg::slotOk); connect(button(QDialogButtonBox::Cancel), &QPushButton::clicked, this, &KomparePrefDlg::slotCancel); adjustSize(); } KomparePrefDlg::~KomparePrefDlg() { } /** No descriptions */ void KomparePrefDlg::slotDefault() { // restore all defaults in the options... m_viewPage->setDefaults(); m_diffPage->setDefaults(); } /** No descriptions */ void KomparePrefDlg::slotHelp() { // figure out the current active page QWidget* currentpage = currentPage()->widget(); if (dynamic_cast(currentpage)) { // figure out the active tab int currentTab = static_cast(currentpage)->m_tabWidget->currentIndex(); switch (currentTab) { case 0: KHelpClient::invokeHelp(QStringLiteral("appearance")); break; case 1: KHelpClient::invokeHelp(QStringLiteral("fonts")); break; default: KHelpClient::invokeHelp(QStringLiteral("view-settings")); } } else if (dynamic_cast(currentpage)) { // figure out the active tab int currentTab = static_cast(currentpage)->m_tabWidget->currentIndex(); switch (currentTab) { case 0: KHelpClient::invokeHelp(QStringLiteral("diff")); break; case 1: KHelpClient::invokeHelp(QStringLiteral("diff-format")); break; case 2: KHelpClient::invokeHelp(QStringLiteral("options")); break; case 3: KHelpClient::invokeHelp(QStringLiteral("exclude")); break; default: KHelpClient::invokeHelp(QStringLiteral("diff-settings")); } } else // Fallback since we had not added the code for the page/tab or forgotten about it KHelpClient::invokeHelp(QStringLiteral("configure-preferences")); } /** No descriptions */ void KomparePrefDlg::slotApply() { // well apply the settings that are currently selected m_viewPage->apply(); m_diffPage->apply(); - emit configChanged(); + Q_EMIT configChanged(); } /** No descriptions */ void KomparePrefDlg::slotOk() { // Apply the settings that are currently selected m_viewPage->apply(); m_diffPage->apply(); //accept(); } /** No descriptions */ void KomparePrefDlg::slotCancel() { // discard the current settings and use the present ones m_viewPage->restore(); m_diffPage->restore(); //reject(); } diff --git a/komparepart/komparesplitter.cpp b/komparepart/komparesplitter.cpp index 7f89801..03c7ff8 100644 --- a/komparepart/komparesplitter.cpp +++ b/komparepart/komparesplitter.cpp @@ -1,488 +1,488 @@ /************************************************************************** ** komparesplitter.cpp ** ------------------- ** begin : Wed Jan 14 2004 ** Copyright 2004-2005 Jeff Snyder ** Copyright 2007-2011 Kevin Kofler ***************************************************************************/ /************************************************************************** ** ** This program is free software; you can redistribute it and/or modify ** it under the terms of the GNU General Public License as published by ** the Free Software Foundation; either version 2 of the License, or ** (at your option) any later version. ** ***************************************************************************/ // associated header #include "komparesplitter.h" // qt #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include // kde // kompare #include "komparelistview.h" #include "viewsettings.h" #include "kompareconnectwidget.h" #include #include using namespace Diff2; KompareSplitter::KompareSplitter(ViewSettings* settings, QWidget* parent) : QSplitter(Qt::Horizontal, parent), m_settings(settings) { QFrame* scrollFrame = static_cast(parent); // Set up the scrollFrame scrollFrame->setFrameStyle(QFrame::NoFrame | QFrame::Plain); scrollFrame->setLineWidth(scrollFrame->style()->pixelMetric(QStyle::PM_DefaultFrameWidth)); QGridLayout* pairlayout = new QGridLayout(scrollFrame); pairlayout->setSpacing(0); pairlayout->setContentsMargins(0, 0, 0, 0); m_vScroll = new QScrollBar(Qt::Vertical, scrollFrame); pairlayout->addWidget(m_vScroll, 0, 1); m_hScroll = new QScrollBar(Qt::Horizontal, scrollFrame); pairlayout->addWidget(m_hScroll, 1, 0); new KompareListViewFrame(true, m_settings, this, "source"); new KompareListViewFrame(false, m_settings, this, "destination"); pairlayout->addWidget(this, 0, 0); // set up our looks setLineWidth(style()->pixelMetric(QStyle::PM_DefaultFrameWidth)); setHandleWidth(50); setChildrenCollapsible(false); setFrameStyle(QFrame::NoFrame); setSizePolicy(QSizePolicy(QSizePolicy::Ignored, QSizePolicy::Ignored)); setOpaqueResize(true); setFocusPolicy(Qt::WheelFocus); connect(this, &KompareSplitter::configChanged, this, &KompareSplitter::slotConfigChanged); connect(this, &KompareSplitter::configChanged, this, &KompareSplitter::slotDelayedRepaintHandles); connect(this, &KompareSplitter::configChanged, this, &KompareSplitter::slotDelayedUpdateScrollBars); // scrolling connect(m_vScroll, &QScrollBar::valueChanged, this, &KompareSplitter::slotScrollToId); connect(m_vScroll, &QScrollBar::sliderMoved, this, &KompareSplitter::slotScrollToId); connect(m_hScroll, &QScrollBar::valueChanged, this, &KompareSplitter::setXOffset); connect(m_hScroll, &QScrollBar::sliderMoved, this, &KompareSplitter::setXOffset); m_scrollTimer = new QTimer(this); m_restartTimer = false; connect(m_scrollTimer, &QTimer::timeout, this, &KompareSplitter::timerTimeout); // we need to receive childEvents now so that d->list is ready for when // slotSetSelection(...) arrives qApp->sendPostedEvents(this, QEvent::ChildAdded); // init stuff slotUpdateScrollBars(); } KompareSplitter::~KompareSplitter() { } QSplitterHandle* KompareSplitter::createHandle() { return new KompareConnectWidgetFrame(m_settings, this); } void KompareSplitter::slotDelayedRepaintHandles() { QTimer::singleShot(0, this, &KompareSplitter::slotRepaintHandles); } void KompareSplitter::slotRepaintHandles() { const int end = count(); for (int i = 1; i < end; ++i) handle(i)->update(); } void KompareSplitter::timerTimeout() { if (m_restartTimer) m_restartTimer = false; else m_scrollTimer->stop(); slotDelayedRepaintHandles(); - emit scrollViewsToId(m_scrollTo); + Q_EMIT scrollViewsToId(m_scrollTo); slotRepaintHandles(); m_vScroll->setValue(m_scrollTo); } void KompareSplitter::slotScrollToId(int id) { m_scrollTo = id; if (m_restartTimer) return; if (m_scrollTimer->isActive()) { m_restartTimer = true; } else { - emit scrollViewsToId(id); + Q_EMIT scrollViewsToId(id); slotRepaintHandles(); m_vScroll->setValue(id); m_scrollTimer->start(30); } } void KompareSplitter::slotDelayedUpdateScrollBars() { QTimer::singleShot(0, this, &KompareSplitter::slotUpdateScrollBars); } void KompareSplitter::slotUpdateScrollBars() { const int end = count(); for (int i = 0; i < end; ++i) { KompareListView* lv = listView(i); int minHScroll = minHScrollId(); if (lv->contentsX() < minHScroll) { lv->setXOffset(minHScroll); } } int m_scrollDistance = m_settings->m_scrollNoOfLines * lineHeight(); int m_pageSize = pageSize(); if (needVScrollBar()) { m_vScroll->show(); m_vScroll->blockSignals(true); m_vScroll->setRange(minVScrollId(), maxVScrollId()); m_vScroll->setValue(scrollId()); m_vScroll->setSingleStep(m_scrollDistance); m_vScroll->setPageStep(m_pageSize); m_vScroll->blockSignals(false); } else { m_vScroll->hide(); } if (needHScrollBar()) { m_hScroll->show(); m_hScroll->blockSignals(true); m_hScroll->setRange(minHScrollId(), maxHScrollId()); m_hScroll->setValue(maxContentsX()); m_hScroll->setSingleStep(10); m_hScroll->setPageStep(minVisibleWidth() - 10); m_hScroll->blockSignals(false); } else { m_hScroll->hide(); } } void KompareSplitter::slotDelayedUpdateVScrollValue() { QTimer::singleShot(0, this, &KompareSplitter::slotUpdateVScrollValue); } void KompareSplitter::slotUpdateVScrollValue() { m_vScroll->setValue(scrollId()); } void KompareSplitter::keyPressEvent(QKeyEvent* e) { //keyboard scrolling switch (e->key()) { case Qt::Key_Right: case Qt::Key_L: m_hScroll->triggerAction(QAbstractSlider::SliderSingleStepAdd); break; case Qt::Key_Left: case Qt::Key_H: m_hScroll->triggerAction(QAbstractSlider::SliderSingleStepSub); break; case Qt::Key_Up: case Qt::Key_K: m_vScroll->triggerAction(QAbstractSlider::SliderSingleStepSub); break; case Qt::Key_Down: case Qt::Key_J: m_vScroll->triggerAction(QAbstractSlider::SliderSingleStepAdd); break; case Qt::Key_PageDown: m_vScroll->triggerAction(QAbstractSlider::SliderPageStepAdd); break; case Qt::Key_PageUp: m_vScroll->triggerAction(QAbstractSlider::SliderPageStepSub); break; } e->accept(); slotRepaintHandles(); } void KompareSplitter::wheelEvent(QWheelEvent* e) { if (e->angleDelta().y() != 0) { if (e->modifiers() & Qt::ControlModifier) { if (e->angleDelta().y() < 0) // scroll down one page m_vScroll->triggerAction(QAbstractSlider::SliderPageStepAdd); else // scroll up one page m_vScroll->triggerAction(QAbstractSlider::SliderPageStepSub); } else { if (e->angleDelta().y() < 0) // scroll down m_vScroll->triggerAction(QAbstractSlider::SliderSingleStepAdd); else // scroll up m_vScroll->triggerAction(QAbstractSlider::SliderSingleStepSub); } } else { if (e->modifiers() & Qt::ControlModifier) { if (e->angleDelta().y() < 0) // scroll right one page m_hScroll->triggerAction(QAbstractSlider::SliderPageStepAdd); else // scroll left one page m_hScroll->triggerAction(QAbstractSlider::SliderPageStepSub); } else { if (e->angleDelta().y() < 0) // scroll to the right m_hScroll->triggerAction(QAbstractSlider::SliderSingleStepAdd); else // scroll to the left m_hScroll->triggerAction(QAbstractSlider::SliderSingleStepSub); } } e->accept(); slotDelayedRepaintHandles(); } /* FIXME: this should return/the scrollId() from the listview containing the * /base/ of the diff. but there's bigger issues with that atm. */ int KompareSplitter::scrollId() { if (widget(0)) return listView(0)->scrollId(); return minVScrollId(); } int KompareSplitter::lineHeight() { if (widget(0)) return listView(0)->fontMetrics().height(); return 1; } int KompareSplitter::pageSize() { if (widget(0)) { KompareListView* view = listView(0); return view->visibleHeight() - view->style()->pixelMetric(QStyle::PM_ScrollBarExtent); } return 1; } bool KompareSplitter::needVScrollBar() { int pagesize = pageSize(); const int end = count(); for (int i = 0; i < end; ++i) { KompareListView* view = listView(i); if (view ->contentsHeight() > pagesize) return true; } return false; } int KompareSplitter::minVScrollId() { int min = -1; int mSId; const int end = count(); for (int i = 0; i < end; ++i) { mSId = listView(i)->minScrollId(); if (mSId < min || min == -1) min = mSId; } return (min == -1) ? 0 : min; } int KompareSplitter::maxVScrollId() { int max = 0; int mSId; const int end = count(); for (int i = 0; i < end; ++i) { mSId = listView(i)->maxScrollId(); if (mSId > max) max = mSId; } return max; } bool KompareSplitter::needHScrollBar() { const int end = count(); for (int i = 0; i < end; ++i) { KompareListView* view = listView(i); if (view->contentsWidth() > view->visibleWidth()) return true; } return false; } int KompareSplitter::minHScrollId() { // hardcode an offset to hide the tree controls return 6; } int KompareSplitter::maxHScrollId() { int max = 0; int mHSId; const int end = count(); for (int i = 0; i < end; ++i) { KompareListView* view = listView(i); mHSId = view->contentsWidth() - view->visibleWidth(); if (mHSId > max) max = mHSId; } return max; } int KompareSplitter::maxContentsX() { int max = 0; int mCX; const int end = count(); for (int i = 0; i < end; ++i) { mCX = listView(i)->contentsX(); if (mCX > max) max = mCX; } return max; } int KompareSplitter::minVisibleWidth() { // Why the hell do we want to know this? // ah yes, it is because we use it to set the "page size" for horiz. scrolling. // despite the fact that *none* has a pgright and pgleft key :P // But we do have mousewheels with horizontal scrolling functionality, // pressing shift and scrolling then goes left and right one page at the time int min = -1; int vW; const int end = count(); for (int i = 0; i < end; ++i) { vW = listView(i)->visibleWidth(); if (vW < min || min == -1) min = vW; } return (min == -1) ? 0 : min; } KompareListView* KompareSplitter::listView(int index) { return static_cast(widget(index))->view(); } KompareConnectWidget* KompareSplitter::connectWidget(int index) { return static_cast(handle(index))->wid(); } void KompareSplitter::slotSetSelection(const DiffModel* model, const Difference* diff) { const int end = count(); for (int i = 0; i < end; ++i) { connectWidget(i)->slotSetSelection(model, diff); listView(i)->slotSetSelection(model, diff); static_cast(widget(i))->slotSetModel(model); } slotDelayedRepaintHandles(); slotDelayedUpdateScrollBars(); } void KompareSplitter::slotSetSelection(const Difference* diff) { const int end = count(); for (int i = 0; i < end; ++i) { connectWidget(i)->slotSetSelection(diff); listView(i)->slotSetSelection(diff); } slotDelayedRepaintHandles(); slotDelayedUpdateScrollBars(); } void KompareSplitter::slotApplyDifference(bool apply) { const int end = count(); for (int i = 0; i < end; ++i) listView(i)->slotApplyDifference(apply); slotDelayedRepaintHandles(); } void KompareSplitter::slotApplyAllDifferences(bool apply) { const int end = count(); for (int i = 0; i < end; ++i) listView(i)->slotApplyAllDifferences(apply); slotDelayedRepaintHandles(); slotScrollToId(m_scrollTo); // FIXME! } void KompareSplitter::slotApplyDifference(const Difference* diff, bool apply) { const int end = count(); for (int i = 0; i < end; ++i) listView(i)->slotApplyDifference(diff, apply); slotDelayedRepaintHandles(); } void KompareSplitter::slotDifferenceClicked(const Difference* diff) { const int end = count(); for (int i = 0; i < end; ++i) listView(i)->setSelectedDifference(diff, false); - emit selectionChanged(diff); + Q_EMIT selectionChanged(diff); } void KompareSplitter::slotConfigChanged() { const int end = count(); for (int i = 0; i < end; ++i) { KompareListView* view = listView(i); view->setFont(m_settings->m_font); view->update(); } } diff --git a/libdialogpages/filespage.cpp b/libdialogpages/filespage.cpp index 53a3d0b..a8668bb 100644 --- a/libdialogpages/filespage.cpp +++ b/libdialogpages/filespage.cpp @@ -1,241 +1,241 @@ /*************************************************************************** filespage.cpp ------------- begin : Sun Apr 18 2004 Copyright 2004 Otto Bruggeman Copyright 2007-2011 Kevin Kofler ****************************************************************************/ /*************************************************************************** ** ** This program is free software; you can redistribute it and/or modify ** it under the terms of the GNU General Public License as published by ** the Free Software Foundation; either version 2 of the License, or ** (at your option) any later version. ** ***************************************************************************/ #include "filespage.h" #include #include #include #include #include #include #include #include #include #include "filessettings.h" FilesPage::FilesPage() : QFrame() { QVBoxLayout* layout = new QVBoxLayout(this); m_firstGB = new QGroupBox(QStringLiteral("You have to set this moron :)"), this); // whut? layout->addWidget(m_firstGB); QHBoxLayout* gb1Layout = new QHBoxLayout(m_firstGB); m_firstURLComboBox = new KUrlComboBox(KUrlComboBox::Both, true, m_firstGB); m_firstURLComboBox->setMaxItems(10); m_firstURLComboBox->setObjectName(QStringLiteral("SourceURLComboBox")); m_firstURLRequester = new KUrlRequester(m_firstURLComboBox, nullptr); gb1Layout->addWidget(m_firstURLComboBox); m_firstURLComboBox->setFocus(); QPushButton* button = new QPushButton(this); button->setIcon(QIcon::fromTheme(QStringLiteral("document-open"))); button->setToolTip(i18nc("@info:tooltip", "Select file")); button->setProperty("combobox", QStringLiteral("SourceURLComboBox")); button->setProperty("folder", false); connect(button, &QPushButton::clicked, this, &FilesPage::open); gb1Layout->addWidget(button); button = new QPushButton(this); button->setIcon(QIcon::fromTheme(QStringLiteral("folder-open"))); QSizePolicy sp = button->sizePolicy(); sp.setRetainSizeWhenHidden(true); button->setSizePolicy(sp); button->setObjectName(QStringLiteral("firstURLOpenFolder")); button->setToolTip(i18nc("@info:tooltip", "Select folder")); button->setProperty("combobox", QStringLiteral("SourceURLComboBox")); button->setProperty("folder", true); connect(button, &QPushButton::clicked, this, &FilesPage::open); gb1Layout->addWidget(button); m_secondGB = new QGroupBox(QStringLiteral("This too moron !"), this); // whut again? layout->addWidget(m_secondGB); QHBoxLayout* gb2Layout = new QHBoxLayout(m_secondGB); m_secondURLComboBox = new KUrlComboBox(KUrlComboBox::Both, true, m_secondGB); m_secondURLComboBox->setMaxItems(10); m_secondURLComboBox->setObjectName(QStringLiteral("DestURLComboBox")); m_secondURLRequester = new KUrlRequester(m_secondURLComboBox, nullptr); gb2Layout->addWidget(m_secondURLComboBox); button = new QPushButton(this); button->setIcon(QIcon::fromTheme(QStringLiteral("document-open"))); button->setToolTip(i18nc("@info:tooltip", "Select file")); button->setProperty("combobox", QStringLiteral("DestURLComboBox")); button->setProperty("folder", false); connect(button, &QPushButton::clicked, this, &FilesPage::open); gb2Layout->addWidget(button); button = new QPushButton(this); button->setIcon(QIcon::fromTheme(QStringLiteral("folder-open"))); button->setObjectName(QStringLiteral("secondURLOpenFolder")); sp = button->sizePolicy(); sp.setRetainSizeWhenHidden(true); button->setSizePolicy(sp); button->setToolTip(i18nc("@info:tooltip", "Select folder")); button->setProperty("combobox", QStringLiteral("DestURLComboBox")); button->setProperty("folder", true); connect(button, &QPushButton::clicked, this, &FilesPage::open); gb2Layout->addWidget(button); m_thirdGB = new QGroupBox(i18nc("@title:group", "Encoding"), this); layout->addWidget(m_thirdGB); QHBoxLayout* gb3Layout = new QHBoxLayout(m_thirdGB); m_encodingComboBox = new KComboBox(false, m_thirdGB); m_encodingComboBox->setObjectName(QStringLiteral("encoding_combobox")); m_encodingComboBox->insertItem(0, i18nc("@item:inlistbox encoding", "Default")); m_encodingComboBox->insertItems(1, KCharsets::charsets()->availableEncodingNames()); gb3Layout->addWidget(m_encodingComboBox); layout->addWidget(m_firstGB); layout->addWidget(m_secondGB); layout->addWidget(m_thirdGB); layout->addStretch(1); } FilesPage::~FilesPage() { delete m_firstURLRequester; m_firstURLRequester = nullptr; delete m_secondURLRequester; m_secondURLRequester = nullptr; m_settings = nullptr; } void FilesPage::open() { QPushButton* button = (QPushButton*) sender(); bool selectFolders = button->property("folder").toBool(); KUrlComboBox* urlComboBox = findChild(button->property("combobox").toString()); doOpen(urlComboBox, selectFolders); } void FilesPage::doOpen(KUrlComboBox* urlComboBox, bool selectFolders) { QUrl currentUrl = QUrl::fromUserInput(urlComboBox->currentText()); QUrl newUrl = selectFolders ? QFileDialog::getExistingDirectoryUrl(this, i18nc("@title:window", "Select Folder"), currentUrl, QFileDialog::ReadOnly) : QFileDialog::getOpenFileUrl(this, i18nc("@title:window", "Select File"), currentUrl); if (!newUrl.isEmpty()) { // remove newUrl if already exists and add it as the first item urlComboBox->setUrl(newUrl); - emit urlChanged(); + Q_EMIT urlChanged(); } } KUrlRequester* FilesPage::firstURLRequester() const { return m_firstURLRequester; } KUrlRequester* FilesPage::secondURLRequester() const { return m_secondURLRequester; } QString FilesPage::encoding() const { return m_encodingComboBox->currentText(); } void FilesPage::setFirstGroupBoxTitle(const QString& title) { m_firstGB->setTitle(title); } void FilesPage::setSecondGroupBoxTitle(const QString& title) { m_secondGB->setTitle(title); } void FilesPage::setURLsInComboBoxes() { // qDebug() << "first : " << m_firstURLComboBox->currentText() ; // qDebug() << "second: " << m_secondURLComboBox->currentText() ; m_firstURLComboBox->setUrl(QUrl::fromUserInput(m_firstURLComboBox->currentText(), QDir::currentPath(), QUrl::AssumeLocalFile)); m_secondURLComboBox->setUrl(QUrl::fromUserInput(m_secondURLComboBox->currentText(), QDir::currentPath(), QUrl::AssumeLocalFile)); } void FilesPage::setFirstURLRequesterMode(unsigned int mode) { m_firstURLRequester->setMode((KFile::Mode) mode); if ((mode & KFile::Directory) == 0) { QPushButton* button = findChild(QStringLiteral("firstURLOpenFolder")); button->setVisible(false); } } void FilesPage::setSecondURLRequesterMode(unsigned int mode) { m_secondURLRequester->setMode((KFile::Mode) mode); if ((mode & KFile::Directory) == 0) { QPushButton* button = findChild(QStringLiteral("secondURLOpenFolder")); button->setVisible(false); } } void FilesPage::setSettings(FilesSettings* settings) { m_settings = settings; m_firstURLComboBox->setUrls(m_settings->m_recentSources); m_firstURLComboBox->setUrl(QUrl::fromUserInput(m_settings->m_lastChosenSourceURL, QDir::currentPath(), QUrl::AssumeLocalFile)); m_secondURLComboBox->setUrls(m_settings->m_recentDestinations); m_secondURLComboBox->setUrl(QUrl::fromUserInput(m_settings->m_lastChosenDestinationURL, QDir::currentPath(), QUrl::AssumeLocalFile)); m_encodingComboBox->setCurrentIndex(m_encodingComboBox->findText(m_settings->m_encoding, Qt::MatchFixedString)); } void FilesPage::restore() { // this shouldn't do a thing... } void FilesPage::apply() { // set the current items as the first ones m_firstURLComboBox->insertUrl(0, QUrl(m_firstURLComboBox->currentText())); m_secondURLComboBox->insertUrl(0, QUrl(m_secondURLComboBox->currentText())); m_settings->m_recentSources = m_firstURLComboBox->urls(); m_settings->m_lastChosenSourceURL = m_firstURLComboBox->currentText(); m_settings->m_recentDestinations = m_secondURLComboBox->urls(); m_settings->m_lastChosenDestinationURL = m_secondURLComboBox->currentText(); m_settings->m_encoding = m_encodingComboBox->currentText(); } void FilesPage::setDefaults() { m_firstURLComboBox->setUrls(QStringList()); m_firstURLComboBox->setUrl(QUrl()); m_secondURLComboBox->setUrls(QStringList()); m_secondURLComboBox->setUrl(QUrl()); m_encodingComboBox->setCurrentIndex(0); // "Default" }