diff --git a/CMakeLists.txt b/CMakeLists.txt index 6804b9e..4705418 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,81 +1,80 @@ cmake_minimum_required(VERSION 2.8.12) project(kompare) # search packages used by KDE include(FeatureSummary) find_package(Qt5 REQUIRED COMPONENTS Core PrintSupport Widgets) find_package(ECM 0.0.9 NO_MODULE REQUIRED) set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${ECM_MODULE_PATH} ${ECM_KDE_MODULE_DIR}) include(KDEInstallDirs) include(KDECMakeSettings) include(KDECompilerSettings NO_POLICY_SCOPE) include(ECMInstallIcons) include(GenerateExportHeader) find_package(KF5 REQUIRED COMPONENTS CoreAddons Codecs DocTools IconThemes JobWidgets Config Parts TextEditor WidgetsAddons ) -find_package(LibKompareDiff2 REQUIRED) -include_directories (${LIBKOMPAREDIFF2_INCLUDE_DIR}) +find_package(LibKompareDiff2 5.1 REQUIRED) include_directories (${CMAKE_SOURCE_DIR} ${CMAKE_BINARY_DIR}) set(KOMPARE_LIB_VERSION 5) set(KOMPARE_LIB_SOVERSION 5) add_subdirectory( doc ) add_subdirectory( interfaces ) add_subdirectory( libdialogpages ) add_subdirectory( komparenavtreepart ) add_subdirectory( komparepart ) add_subdirectory( pics ) include_directories( ${CMAKE_CURRENT_SOURCE_DIR}/komparepart ${CMAKE_CURRENT_SOURCE_DIR}/libdialogpages ${CMAKE_CURRENT_SOURCE_DIR}/interfaces ${CMAKE_CURRENT_SOURCE_DIR}/komparenavtreepart ${CMAKE_CURRENT_SOURCE_DIR}/komparepart) ########### next target ############### set(kompare_SRCS main.cpp kompare_shell.cpp kompareurldialog.cpp ) # kde4_add_app_icon(kompare_SRCS "${CMAKE_CURRENT_SOURCE_DIR}/pics/hi*-app-kompare.png") add_executable(kompare ${kompare_SRCS}) target_link_libraries(kompare kompareinterface - ${LIBKOMPAREDIFF2_LIBRARIES} komparedialogpages + KompareDiff2 KF5::TextEditor KF5::WidgetsAddons Qt5::Widgets ) install(TARGETS kompare ${INSTALL_TARGETS_DEFAULT_ARGS} ) ########### install files ############### install( PROGRAMS org.kde.kompare.desktop DESTINATION ${XDG_APPS_INSTALL_DIR} ) install( FILES kompareui.rc DESTINATION ${KXMLGUI_INSTALL_DIR}/kompare ) install( FILES komparenavigationpart.desktop kompareviewpart.desktop DESTINATION ${SERVICETYPES_INSTALL_DIR} ) install( FILES org.kde.kompare.appdata.xml DESTINATION ${KDE_INSTALL_METAINFODIR} ) feature_summary(WHAT ALL INCLUDE_QUIET_PACKAGES FATAL_ON_MISSING_REQUIRED_PACKAGES) diff --git a/kompare_shell.h b/kompare_shell.h index 4d82ff8..2eafbc3 100644 --- a/kompare_shell.h +++ b/kompare_shell.h @@ -1,158 +1,158 @@ /*************************************************************************** kompare_shell.h ---------------- begin : Sun Mar 4 2001 Copyright 2001-2003 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. ** ***************************************************************************/ #ifndef KOMPARESHELL_H #define KOMPARESHELL_H #include -#include +#include #include Q_DECLARE_LOGGING_CATEGORY(KOMPARESHELL) class KompareInterface; namespace KParts { class ReadOnlyPart; class ReadWritePart; } class KToggleAction; class KSqueezedTextLabel; class KomparePart; class KompareNavTreePart; class QLabel; class QEventLoopLocker; namespace KTextEditor { class Document; class EditInterface; class View; } /** * This is the application "Shell". It has a menubar, toolbar, and * statusbar but relies on the "Part" to do all the real work. * * Adapted the shell a bit so it now handles separate view and navigation parts * * @short Application Shell * @author John Firebaugh * @author Otto Bruggeman * @version 3.2.90 */ class KompareShell : public KParts::MainWindow { Q_OBJECT public: /** * Default Constructor */ KompareShell(); /** * Default Destructor */ virtual ~KompareShell(); /** * Use this method to load whatever file/URL you have */ void openDiff( const QUrl& url ); /** * Use this method to load the diff from stdin */ void openStdin(); /** * Use this method to compare 2 URLs (files or directories) */ void compare( const QUrl& source, const QUrl& destination ); /** * Use this method to blend diff into url1 (file or directory) */ void blend( const QUrl& url1, const QUrl& diff ); public slots: void slotUpdateStatusBar( int modelIndex, int differenceIndex, int modelCount, int differenceCount, int appliedCount ); KompareInterface* viewPart() const; protected: virtual bool queryClose(); /** * This method is called when it is time for the app to save its * properties for session management purposes. */ void saveProperties(KConfigGroup &); /** * This method is called when this app is restored. The KConfig * object points to the session management config file that was saved * with @ref saveProperties */ void readProperties(const KConfigGroup &); private slots: void slotSetStatusBarText( const QString& text ); void slotFileOpen(); void slotFileCompareFiles(); void slotFileBlendURLAndDiff(); void slotShowTextView(); void slotFileClose(); void optionsConfigureKeys(); void optionsConfigureToolbars(); void slotSetDiffString( const QString& diffString ); void newToolbarConfig(); void slotVisibilityChanged( bool visible ); private: void setupAccel(); void setupActions(); void setupStatusBar(); private: QUrl m_sourceURL; QUrl m_destinationURL; QUrl m_diffURL; KParts::ReadWritePart* m_viewPart; KParts::ReadOnlyPart* m_navTreePart; KTextEditor::Document* m_textViewPart; KTextEditor::View* m_textView; // KTextEditor::EditInterface* m_textEditIface; QDockWidget* m_textViewWidget; QDockWidget* m_navTreeDock; KToggleAction* m_showTextView; enum Kompare::Mode m_mode; // This is the statusbarwidget for displaying the general stuff KSqueezedTextLabel* m_generalLabel; QString m_diffString; QLabel* m_filesLabel; QLabel* m_differencesLabel; QEventLoopLocker* m_eventLoopLocker; }; #endif // KOMPARE_H diff --git a/komparenavtreepart/CMakeLists.txt b/komparenavtreepart/CMakeLists.txt index 798a3d4..964e391 100644 --- a/komparenavtreepart/CMakeLists.txt +++ b/komparenavtreepart/CMakeLists.txt @@ -1,27 +1,27 @@ include_directories( ${CMAKE_CURRENT_SOURCE_DIR}/../komparepart) ########### next target ############### set(komparenavtreepart_PART_SRCS komparenavtreepart.cpp ) add_library(komparenavtreepart MODULE ${komparenavtreepart_PART_SRCS}) target_link_libraries(komparenavtreepart Qt5::Widgets KF5::Parts KF5::IconThemes - ${LIBKOMPAREDIFF2_LIBRARIES} + KompareDiff2 ) install(TARGETS komparenavtreepart DESTINATION ${PLUGIN_INSTALL_DIR} ) ########### install files ############### install( FILES komparenavtreepart.desktop DESTINATION ${SERVICES_INSTALL_DIR} ) diff --git a/komparenavtreepart/komparenavtreepart.cpp b/komparenavtreepart/komparenavtreepart.cpp index 8f641b5..115d7e8 100644 --- a/komparenavtreepart/komparenavtreepart.cpp +++ b/komparenavtreepart/komparenavtreepart.cpp @@ -1,779 +1,779 @@ /*************************************************************************** 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 +#include +#include +#include +#include #define COL_SOURCE 0 #define COL_DESTINATION 1 #define COL_DIFFERENCE 2 using namespace Diff2; Q_LOGGING_CATEGORY(KOMPARENAVVIEW, "komparenavview") KompareNavTreePart::KompareNavTreePart( QWidget* parentWidget, QObject* parent, const QVariantList& ) : KParts::ReadOnlyPart( parent ), m_splitter( 0 ), m_modelList( 0 ), m_srcDirTree( 0 ), m_destDirTree( 0 ), m_fileList( 0 ), m_changesList( 0 ), m_srcRootItem( 0 ), m_destRootItem( 0 ), m_selectedModel( 0 ), m_selectedDifference( 0 ), m_source( "" ), m_destination( "" ), m_info( 0 ) { m_splitter = new QSplitter( Qt::Horizontal, parentWidget ); setWidget( m_splitter ); m_srcDirTree = new QTreeWidget( m_splitter ); m_srcDirTree->setHeaderLabel( i18n("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( i18n("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() << i18n("Source File") << i18n("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() << i18n("Source Line") << i18n("Destination Line") << i18n("Difference") ); m_changesList->setAllColumnsShowFocus( true ); m_changesList->setRootIsDecorated( false ); m_changesList->setSortingEnabled( true ); m_changesList->sortByColumn( 0, Qt::AscendingOrder ); connect( m_srcDirTree, SIGNAL(currentItemChanged( QTreeWidgetItem*, QTreeWidgetItem* )), this, SLOT(slotSrcDirTreeSelectionChanged( QTreeWidgetItem* )) ); connect( m_destDirTree, SIGNAL(currentItemChanged( QTreeWidgetItem*, QTreeWidgetItem* )), this, SLOT(slotDestDirTreeSelectionChanged( QTreeWidgetItem* )) ); connect( m_fileList, SIGNAL(currentItemChanged( QTreeWidgetItem*, QTreeWidgetItem* )), this, SLOT(slotFileListSelectionChanged( QTreeWidgetItem* )) ); connect( m_changesList, SIGNAL(currentItemChanged( QTreeWidgetItem*, QTreeWidgetItem* )), this, SLOT(slotChangesListSelectionChanged( QTreeWidgetItem* )) ); } KompareNavTreePart::~KompareNavTreePart() { m_modelList = 0; m_selectedModel = 0; m_selectedDifference = 0; } 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 == 0 ) { qCDebug(KOMPARENAVVIEW) << "No Info... weird shit..." ; return; } QString srcBase; QString destBase; DiffModel* model; model = m_modelList->first(); m_selectedModel = 0L; 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] != '/' ) srcBase = ""; if ( destBase[0] != '/' ) destBase = ""; break; case Kompare::ComparingFiles: srcBase = model->sourcePath(); destBase = model->destinationPath(); break; case Kompare::ComparingDirs: srcBase = m_info->localSource; if ( !srcBase.endsWith( '/' ) ) srcBase += '/'; destBase = m_info->localDestination; if ( !destBase.endsWith( '/' ) ) destBase += '/'; 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( '/' ) ) 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 ); } 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 ); } 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 = ""; } 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, SmallIcon( getIcon( src ) ) ); setIcon( 1, SmallIcon( getIcon( dst ) ) ); } bool KFileLVI::hasExtension(const QString& extensions, const QString& fileName) { QStringList extList = extensions.split(' '); foreach (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( ".h .hpp", fileName ) ) { return "text-x-c++hdr"; } if ( hasExtension( ".cpp", fileName ) ) { return "text-x-c++src"; } if ( hasExtension( ".c", fileName ) ) { return "text-x-csrc"; } // Python if ( hasExtension( ".py .pyw", fileName ) ) { return "text-x-python"; } // C# if ( hasExtension( ".cs", fileName ) ) { return "text-x-csharp"; } // Objective-C if ( hasExtension( ".m", fileName ) ) { return "text-x-objcsrc"; } // Java if ( hasExtension( ".java", fileName ) ) { return "text-x-java"; } // Script if ( hasExtension( ".sh", fileName ) ) { return "text-x-script"; } // Makefile if ( hasExtension( ".cmake Makefile", fileName ) ) { return "text-x-makefile"; } // Ada if ( hasExtension( ".ada .ads .adb", fileName ) ) { return "text-x-adasrc"; } // Pascal if ( hasExtension( ".pas", fileName ) ) { return "text-x-pascal"; } // Patch if ( hasExtension( ".diff", fileName ) ) { return "text-x-patch"; } // Tcl if ( hasExtension( ".tcl", fileName ) ) { return "text-x-tcl"; } // Text if ( hasExtension( ".txt", fileName ) ) { return "text-plain"; } // Xml if ( hasExtension( ".xml", fileName ) ) { return "text-xml"; } // unknown or no file extension return "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, QString& dir ) : QTreeWidgetItem( parent ) { // qCDebug(KOMPARENAVVIEW) << "KDirLVI (QTreeWidget) constructor called with dir = " << dir ; m_rootItem = true; m_dirName = dir; setIcon( 0, SmallIcon( "folder" ) ); setExpanded( true ); if ( m_dirName.isEmpty() ) setText( 0, i18n( "Unknown" ) ); else setText( 0, m_dirName ); } KDirLVI::KDirLVI( KDirLVI* parent, QString& dir ) : QTreeWidgetItem( parent ) { // qCDebug(KOMPARENAVVIEW) << "KDirLVI (KDirLVI) constructor called with dir = " << dir ; m_rootItem = false; m_dirName = dir; setIcon( 0, SmallIcon( "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( "/", 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( QString dir ) { // qCDebug(KOMPARENAVVIEW) << "KDirLVI::findChild called with dir = " << dir ; KDirLVI* child; if ( ( child = static_cast(this->child(0)) ) != 0L ) { // 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 0L; } 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( QString 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 0L; QTreeWidgetItemIterator it(child); while (*it) { child = static_cast(*it); if ( dir.startsWith( child->dirName() ) ) return child->setSelected( dir ); ++it; } return 0L; } KDirLVI::~KDirLVI() { m_modelList.clear(); } static KAboutData aboutData() { KAboutData about("komparenavtreepart", i18n("KompareNavTreePart"), "1.2"); about.addAuthor(i18n("John Firebaugh"), i18n("Author"), "jfirebaugh@kde.org"); about.addAuthor(i18n("Otto Bruggeman"), i18n("Author"), "bruggie@gmail.com" ); return about; } K_PLUGIN_FACTORY(KompareNavTreePartFactory, registerPlugin(); ) #include "komparenavtreepart.moc" diff --git a/komparenavtreepart/komparenavtreepart.h b/komparenavtreepart/komparenavtreepart.h index e517c4c..cf0816e 100644 --- a/komparenavtreepart/komparenavtreepart.h +++ b/komparenavtreepart/komparenavtreepart.h @@ -1,171 +1,171 @@ /*************************************************************************** komparenavtreepart.h -------------------- begin : Mon Feb 26 2002 Copyright 2001-2004 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. ** ***************************************************************************/ #ifndef KOMPARENAVTREEPART_H #define KOMPARENAVTREEPART_H #include #include #include #include #include #include -#include -#include +#include +#include Q_DECLARE_LOGGING_CATEGORY(KOMPARENAVVIEW) namespace Diff2 { class DiffModel; class Difference; } class KDirLVI; class KFileLVI; class KChangeLVI; class KompareNavTreePart : public KParts::ReadOnlyPart { Q_OBJECT public: explicit KompareNavTreePart( QWidget* parentWidget, QObject* parent, const QVariantList& args ); virtual ~KompareNavTreePart(); public: virtual bool openFile() { return false; }; public slots: void slotSetSelection( const Diff2::DiffModel* model, const Diff2::Difference* diff ); void slotSetSelection( const Diff2::Difference* diff ); void slotModelsChanged( const Diff2::DiffModelList* modelList ); void slotKompareInfo( Kompare::Info* info ); signals: void selectionChanged( const Diff2::DiffModel* model, const Diff2::Difference* diff ); void selectionChanged( const Diff2::Difference* diff ); private slots: void slotSrcDirTreeSelectionChanged ( QTreeWidgetItem* item ); void slotDestDirTreeSelectionChanged( QTreeWidgetItem* item ); void slotFileListSelectionChanged ( QTreeWidgetItem* item ); void slotChangesListSelectionChanged( QTreeWidgetItem* item ); void slotApplyDifference( bool apply ); void slotApplyAllDifferences( bool apply ); void slotApplyDifference( const Diff2::Difference* diff, bool apply ); void buildTreeInMemory(); private: void setSelectedDir( const Diff2::DiffModel* model ); void setSelectedFile( const Diff2::DiffModel* model ); void setSelectedDifference( const Diff2::Difference* diff ); void buildDirectoryTree(); QString compareFromEndAndReturnSame( const QString& string1, const QString& string2 ); void addDirToTreeView( enum Kompare::Target, const QString& filename ); QTreeWidgetItem* findDirInDirTree( const QTreeWidgetItem* parent, const QString& dir ); private: QSplitter* m_splitter; const Diff2::DiffModelList* m_modelList; QHash m_diffToChangeItemDict; QHash m_modelToFileItemDict; QHash m_modelToSrcDirItemDict; QHash m_modelToDestDirItemDict; QTreeWidget* m_srcDirTree; QTreeWidget* m_destDirTree; QTreeWidget* m_fileList; QTreeWidget* m_changesList; KDirLVI* m_srcRootItem; KDirLVI* m_destRootItem; const Diff2::DiffModel* m_selectedModel; const Diff2::Difference* m_selectedDifference; QString m_source; QString m_destination; struct Kompare::Info* m_info; }; // These 3 classes are need to store the models into a tree so it is easier // to extract the info we need for the navigation widgets class KChangeLVI : public QTreeWidgetItem { public: KChangeLVI( QTreeWidget* parent, Diff2::Difference* diff ); ~KChangeLVI(); public: Diff2::Difference* difference() { return m_difference; }; virtual bool operator<( const QTreeWidgetItem& item ) const; void setDifferenceText(); private: Diff2::Difference* m_difference; }; class KFileLVI : public QTreeWidgetItem { public: KFileLVI( QTreeWidget* parent, Diff2::DiffModel* model ); ~KFileLVI(); public: Diff2::DiffModel* model() { return m_model; }; void fillChangesList( QTreeWidget* changesList, QHash* diffToChangeItemDict ); private: bool hasExtension(const QString& extensions, const QString& fileName); const QString getIcon(const QString& fileName); private: Diff2::DiffModel* m_model; }; class KDirLVI : public QTreeWidgetItem { public: KDirLVI( KDirLVI* parent, QString& dir ); KDirLVI( QTreeWidget* parent, QString& dir ); ~KDirLVI(); public: void addModel( QString& dir, Diff2::DiffModel* model, QHash* modelToDirItemDict ); QString& dirName() { return m_dirName; }; QString fullPath( QString& path ); KDirLVI* setSelected( QString dir ); void setSelected( bool selected ) { QTreeWidgetItem::setSelected( selected ); } void fillFileList( QTreeWidget* fileList, QHash* modelToFileItemDict ); bool isRootItem() { return m_rootItem; }; private: KDirLVI* findChild( QString dir ); private: Diff2::DiffModelList m_modelList; QString m_dirName; bool m_rootItem; }; #endif diff --git a/komparepart/CMakeLists.txt b/komparepart/CMakeLists.txt index ef6ad6f..9878fda 100644 --- a/komparepart/CMakeLists.txt +++ b/komparepart/CMakeLists.txt @@ -1,94 +1,94 @@ #define TRANSLATION_DOMAIN "kompare" include_directories( ${CMAKE_CURRENT_SOURCE_DIR}/../libdialogpages ${CMAKE_CURRENT_SOURCE_DIR}/../interfaces ) ########### next target ############### set( komparepart_PART_SRCS kompare_part.cpp kompareconnectwidget.cpp komparesplitter.cpp komparelistview.cpp kompareprefdlg.cpp komparesaveoptionsbase.cpp komparesaveoptionswidget.cpp kompareview.cpp ) ki18n_wrap_ui(komparepart_PART_SRCS komparesaveoptionsbase.ui ) add_library(komparepart MODULE ${komparepart_PART_SRCS}) target_link_libraries(komparepart komparedialogpages - ${LIBKOMPAREDIFF2_LIBRARIES} kompareinterface + KompareDiff2 KF5::ConfigWidgets KF5::CoreAddons KF5::JobWidgets Qt5::PrintSupport ) install(TARGETS komparepart DESTINATION ${PLUGIN_INSTALL_DIR} ) ########### install files ############### install( FILES komparepart.desktop DESTINATION ${SERVICES_INSTALL_DIR} ) install( FILES komparepartui.rc DESTINATION ${KXMLGUI_INSTALL_DIR}/kompare ) #original Makefile.am contents follow: ########################################################################## ## KPART SECTION ########################################################################## # #INCLUDES = \ # -I$(top_srcdir)/kompare/libdialogpages \ # -I$(top_srcdir)/kompare/interfaces \ # $(all_includes) # #noinst_HEADERS = \ # kompare_part.h \ # komparesplitter.h \ # kompareprefdlg.h \ # komparelistview.h \ # kompareconnectwidget.h \ # komparesaveoptionsbase.h \ # komparesaveoptionswidget.h \ # kompare_qsplitter.h # ## let automoc handle all of the meta source files (moc) #METASOURCES = AUTO # #kde_module_LTLIBRARIES = libkomparepart.la # ## the Part's source, library search path, and link libraries #libkomparepart_la_SOURCES = \ # kompare_part.cpp \ # kompareconnectwidget.cpp \ # komparesplitter.cpp \ # komparelistview.cpp \ # kompareprefdlg.cpp \ # komparesaveoptionsbase.ui \ # komparesaveoptionswidget.cpp # #libkomparepart_la_LDFLAGS = $(KDE_PLUGIN) $(all_libraries) #libkomparepart_la_LIBADD = $(LIB_KPARTS) $(LIB_KFILE) \ # ../libdialogpages/libdialogpages.la \ # ../interfaces/libkompareinterface.la # ## this is where the desktop file will go #partdesktopdir = $(kde_servicesdir) #partdesktop_DATA = komparepart.desktop # ## this is where the part's XML-GUI resource file goes #partrcdir = $(kde_datadir)/kompare #partrc_DATA = komparepartui.rc # diff --git a/komparepart/kompare_part.cpp b/komparepart/kompare_part.cpp index 5aa98ed..6a58403 100644 --- a/komparepart/kompare_part.cpp +++ b/komparepart/kompare_part.cpp @@ -1,970 +1,971 @@ /*************************************************************************** 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 "komparelistview.h" #include "kompareconnectwidget.h" -#include #include "viewsettings.h" #include "kompareprefdlg.h" #include "komparesaveoptionswidget.h" #include "komparesplitter.h" #include "kompareview.h" Q_LOGGING_CATEGORY(KOMPAREPART, "komparepart") K_PLUGIN_FACTORY( KomparePartFactory, registerPlugin(); ) ViewSettings* KomparePart::m_viewSettings = 0L; DiffSettings* KomparePart::m_diffSettings = 0L; KomparePart::KomparePart( QWidget *parentWidget, QObject *parent, const QVariantList & /*args*/ ) : KParts::ReadWritePart(parent), m_info() { if( !m_viewSettings ) { m_viewSettings = new ViewSettings( 0 ); } if( !m_diffSettings ) { m_diffSettings = new DiffSettings( 0 ); } readProperties( KSharedConfig::openConfig().data() ); m_view = new KompareView ( m_viewSettings, parentWidget ); 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" , KParts::ReadWritePart::isReadWrite()); Q_FOREACH(QAction* action, m_modelList->actionCollection()->actions()) { actionCollection()->addAction(action->objectName(), action); } connect( m_modelList, SIGNAL(status( Kompare::Status )), this, SLOT(slotSetStatus( Kompare::Status )) ); connect( m_modelList, SIGNAL(setStatusBarModelInfo( int, int, int, int, int )), this, SIGNAL(setStatusBarModelInfo( int, int, int, int, int )) ); connect( m_modelList, SIGNAL(error( QString )), this, SLOT(slotShowError( QString )) ); connect( m_modelList, SIGNAL(applyAllDifferences( bool )), this, SLOT(updateActions()) ); connect( m_modelList, SIGNAL(applyDifference( bool )), this, SLOT(updateActions()) ); connect( m_modelList, SIGNAL(applyAllDifferences( bool )), this, SIGNAL(appliedChanged()) ); connect( m_modelList, SIGNAL(applyDifference( bool )), this, SIGNAL(appliedChanged()) ); connect( m_modelList, SIGNAL(updateActions()), this, SLOT(updateActions()) ); // This is the stuff to connect the "interface" of the kompare part to the model inside connect( m_modelList, SIGNAL(modelsChanged(const Diff2::DiffModelList*)), this, SIGNAL(modelsChanged(const Diff2::DiffModelList*)) ); connect( m_modelList, SIGNAL(setSelection(const Diff2::DiffModel*, const Diff2::Difference*)), this, SIGNAL(setSelection(const Diff2::DiffModel*, const Diff2::Difference*)) ); connect( this, SIGNAL(selectionChanged(const Diff2::DiffModel*, const Diff2::Difference*)), m_modelList, SLOT(slotSelectionChanged(const Diff2::DiffModel*, const Diff2::Difference*)) ); connect( m_modelList, SIGNAL(setSelection(const Diff2::Difference*)), this, SIGNAL(setSelection(const Diff2::Difference*)) ); connect( this, SIGNAL(selectionChanged(const Diff2::Difference*)), m_modelList, SLOT(slotSelectionChanged(const Diff2::Difference*)) ); connect( m_modelList, SIGNAL(applyDifference(bool)), this, SIGNAL(applyDifference(bool)) ); connect( m_modelList, SIGNAL(applyAllDifferences(bool)), this, SIGNAL(applyAllDifferences(bool)) ); connect( m_modelList, SIGNAL(applyDifference(const Diff2::Difference*, bool)), this, SIGNAL(applyDifference(const Diff2::Difference*, bool)) ); connect( m_modelList, SIGNAL(diffString(const QString&)), this, SIGNAL(diffString(const QString&)) ); connect( this, SIGNAL(kompareInfo(Kompare::Info*)), m_modelList, SLOT(slotKompareInfo(Kompare::Info*)) ); // Here we connect the splitter to the modellist connect( m_modelList, SIGNAL(setSelection(const Diff2::DiffModel*, const Diff2::Difference*)), m_splitter, SLOT(slotSetSelection(const Diff2::DiffModel*, const Diff2::Difference*)) ); // connect( m_splitter, SIGNAL(selectionChanged(const Diff2::Difference*, const Diff2::Difference*)), // m_modelList, SLOT(slotSelectionChanged(const Diff2::Difference*, const Diff2::Difference*)) ); connect( m_modelList, SIGNAL(setSelection(const Diff2::Difference*)), m_splitter, SLOT(slotSetSelection(const Diff2::Difference*)) ); connect( m_splitter, SIGNAL(selectionChanged(const Diff2::Difference*)), m_modelList, SLOT(slotSelectionChanged(const Diff2::Difference*)) ); connect( m_modelList, SIGNAL(applyDifference(bool)), m_splitter, SLOT(slotApplyDifference(bool)) ); connect( m_modelList, SIGNAL(applyAllDifferences(bool)), m_splitter, SLOT(slotApplyAllDifferences(bool)) ); connect( m_modelList, SIGNAL(applyDifference(const Diff2::Difference*, bool)), m_splitter, SLOT(slotApplyDifference(const Diff2::Difference*, bool)) ); connect( this, SIGNAL(configChanged()), m_splitter, SIGNAL(configChanged()) ); setupActions(); // set our XML-UI resource file setXMLFile( "komparepartui.rc" ); // 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( true ); // 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() { // create our actions m_saveAll = actionCollection()->addAction("file_save_all", this, SLOT(saveAll())); m_saveAll->setIcon(QIcon::fromTheme("document-save-all")); m_saveAll->setText(i18n("Save &All")); m_saveDiff = actionCollection()->addAction("file_save_diff", this, SLOT(saveDiff())); m_saveDiff->setText(i18n("Save &Diff...")); m_swap = actionCollection()->addAction("file_swap", this, SLOT(slotSwap())); m_swap->setText(i18n("Swap Source with Destination")); m_diffStats = actionCollection()->addAction("file_diffstats", this, SLOT(slotShowDiffstats())); m_diffStats->setText(i18n("Show Statistics")); m_diffRefresh = actionCollection()->addAction("file_refreshdiff", this, SLOT(slotRefreshDiff())); m_diffRefresh->setIcon(QIcon::fromTheme("view-refresh")); m_diffRefresh->setText(i18n("Refresh Diff")); actionCollection()->setDefaultShortcuts(m_diffRefresh, KStandardShortcut::reload()); m_print = actionCollection()->addAction(KStandardAction::Print, this, SLOT( slotFilePrint() )); m_printPreview = actionCollection()->addAction(KStandardAction::PrintPreview, this, SLOT( slotFilePrintPreview() )); KStandardAction::preferences(this, SLOT(optionsPreferences()), actionCollection()); } void KomparePart::updateActions() { m_saveAll->setEnabled ( m_modelList->hasUnsavedChanges() ); m_saveDiff->setEnabled ( m_modelList->mode() == Kompare::ComparingFiles || m_modelList->mode() == Kompare::ComparingDirs ); 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 ); 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 ); 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::exists( const QString& url ) { QFileInfo fi( url ); return fi.exists(); } 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 = 0; 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() + "/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 = ""; // Not sure if download has already touched this tempFileName when there is an error result = false; } } else { tmpDir = new QTemporaryDir(QDir::tempPath() + "/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 = 0; 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( '/' ) ) tempFileName += '/'; tempFileName += entries.at( 0 ); tempFileName += '/'; } else { qCDebug(KOMPAREPART) << "Yikes, nothing downloaded?"; delete tmpDir; tmpDir = 0; tempFileName = ""; result = false; } } } } } else { // is Local already, check if exists if ( 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 != 0 ) { delete m_info.sourceQTempDir; m_info.sourceQTempDir = 0; } m_info.localSource = ""; } if ( !m_info.localDestination.isEmpty() ) { if ( m_info.destinationQTempDir != 0 ) { delete m_info.destinationQTempDir; m_info.destinationQTempDir = 0; } m_info.localDestination = ""; } } 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 dont diff fetchURL( source, true ); fetchURL( destination, false ); 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 ); 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 ); 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 dont diff fetchURL( sourceFile, true ); fetchURL( destinationFile, false ); 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 ); 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 ); 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 ); 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( "save_options" ); dlg.setModal( true ); dlg.setWindowTitle( i18n("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(), i18n( "Save .diff" ), m_info.destination.url(), i18n("Patch Files (*.diff *.dif *.patch)") ); if ( QFile::exists( url.toLocalFile() ) ) { int result = KMessageBox::warningYesNoCancel( widget(), i18n("The file exists or is write-protected; do you want to overwrite it?"), i18n("File Exists"), KStandardGuiItem::overwrite(), KGuiItem(i18n("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, 0 ); 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, SIGNAL(paintRequested(QPrinter*)), this, SLOT(slotPaintRequested(QPrinter*)) ); 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..."; } KAboutData* KomparePart::createAboutData() { KAboutData *about = new KAboutData("kompare", i18n("KomparePart"), "4.0"); about->addAuthor(i18n("John Firebaugh"), i18n("Author"), "jfirebaugh@kde.org"); about->addAuthor(i18n("Otto Bruggeman"), i18n("Author"), "bruggie@gmail.com" ); about->addAuthor(i18n("Kevin Kofler"), i18n("Author"), "kevin.kofler@chello.at" ); return about; } void KomparePart::slotSetStatus( enum Kompare::Status status ) { updateActions(); switch( status ) { case Kompare::RunningDiff: emit setStatusBarText( i18n( "Running diff..." ) ); break; case Kompare::Parsing: emit setStatusBarText( i18n( "Parsing diff output..." ) ); break; case Kompare::FinishedParsing: updateStatus(); break; case Kompare::FinishedWritingDiff: updateStatus(); emit diffURLChanged(); break; default: break; } } 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 + " -- " + destination; // no need to translate this " -- " break; case Kompare::ShowingDiff : text = source; break; default: break; } 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 = i18n( "Comparing file %1 with file %2" , source , destination ); break; case Kompare::ComparingDirs : text = i18n( "Comparing files in %1 with files in %2" , source , destination ); break; case Kompare::ShowingDiff : text = i18n( "Viewing diff output from %1", source ); break; case Kompare::BlendingFile : text = i18n( "Blending diff output from %1 into file %2" , source , destination ); break; case Kompare::BlendingDir : text = i18n( "Blending diff output from %1 into folder %2" , m_info.source.toDisplayString() , m_info.destination.toDisplayString() ); break; default: break; } 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( 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?" ), i18n( "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?" ), i18n( "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( void ) { // 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 = i18n( "Unified" ); break; case Kompare::Context : diffFormat = i18n( "Context" ); break; case Kompare::RCS : diffFormat = i18n( "RCS" ); break; case Kompare::Ed : diffFormat = i18n( "Ed" ); break; case Kompare::Normal : diffFormat = i18n( "Normal" ); break; case Kompare::UnknownFormat : default: diffFormat = i18n( "Unknown" ); break; } } else { diffFormat = ""; } 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( 0L, i18n( "No diff file, or no 2 files have been diffed. " "Therefore no stats are available."), i18n("Diff Statistics"), QString(), 0 ); } else if ( m_modelList->modelCount() == 1 ) { // 1 file in diff, or 2 files compared KMessageBox::information( 0L, 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), i18n("Diff Statistics"), QString(), 0 ); } else { // more than 1 file in diff, or 2 directories compared KMessageBox::information( 0L, 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(), i18n("Diff Statistics"), QString(), 0 ); } } 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?" ), i18n( "Save Changes?" ), KStandardGuiItem::save(), KStandardGuiItem::discard() ); if( query == KMessageBox::Cancel ) return false; if( query == KMessageBox::Yes ) return m_modelList->saveAll(); return true; } int KomparePart::readProperties( KConfig *config ) { m_viewSettings->loadSettings( config ); m_diffSettings->loadSettings( config ); 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, SIGNAL(configChanged()), this, SIGNAL(configChanged()) ); if ( pref.exec() ) emit configChanged(); } #include "kompare_part.moc" diff --git a/komparepart/kompare_part.h b/komparepart/kompare_part.h index 640534a..1466ff5 100644 --- a/komparepart/kompare_part.h +++ b/komparepart/kompare_part.h @@ -1,236 +1,236 @@ /*************************************************************************** kompare_part.h -------------- 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 ****************************************************************************/ /*************************************************************************** ** ** 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. ** ***************************************************************************/ #ifndef KOMPAREPART_H #define KOMPAREPART_H #include #include #include -#include +#include #include "kompareinterface.h" class QAction; class QPrinter; class QUrl; class QWidget; class KAboutData; namespace Diff2 { class Difference; class DiffModel; class DiffModelList; class KompareModelList; } class DiffSettings; class ViewSettings; class KompareSplitter; class KompareView; Q_DECLARE_LOGGING_CATEGORY(KOMPAREPART) /** * This is a "Part". It does all the real work in a KPart * application. * * @short Main Part * @author John Firebaugh * @author Otto Bruggeman * @version 0.3 */ class KomparePart : public KParts::ReadWritePart, public KompareInterface { Q_OBJECT Q_INTERFACES(KompareInterface) public: /** * Default constructor */ KomparePart( QWidget *parentWidget, QObject *parent, const QVariantList & /*args*/); /** * Destructor */ virtual ~KomparePart(); // Sessionmanagement stuff, added to the kompare iface // because they are not in the Part class where they belong // Should be added when bic changes are allowed again (kde 4.0) virtual int readProperties( KConfig *config ); virtual int saveProperties( KConfig *config ); // this one is called when the shell_app is about to close. // we need it now to save the properties of the part when apps don't (can't) // use the readProperties and saveProperties methods virtual bool queryClose(); // Do we really want to expose this ??? const Diff2::KompareModelList* model() const { return m_modelList; }; static KAboutData *createAboutData(); public: // Reimplemented from the KompareInterface /** * Open and parse the diff file at diffUrl. */ virtual bool openDiff( const QUrl& diffUrl ); /** Added on request of Harald Fernengel */ virtual bool openDiff( const QString& diffOutput ); /** Open and parse the diff3 file at diff3Url */ virtual bool openDiff3( const QUrl& diff3URL ); /** Open and parse the file diff3Output with the output of diff3 */ virtual bool openDiff3( const QString& diff3Output ); /** Compare, with diff, source with destination */ virtual void compare( const QUrl& sourceFile, const QUrl& destinationFile ); /** Compare a Source file to a custom Destination string */ virtual void compareFileString( const QUrl & sourceFile, const QString & destination); /** Compare a custom Source string to a Destination file */ virtual void compareStringFile( const QString & source, const QUrl & destinationFile); /** Compare, with diff, source with destination */ virtual void compareFiles( const QUrl& sourceFile, const QUrl& destinationFile ); /** Compare, with diff, source with destination */ virtual void compareDirs ( const QUrl& sourceDir, const QUrl& destinationDir ); /** Compare, with diff3, originalFile with changedFile1 and changedFile2 */ virtual void compare3Files( const QUrl& originalFile, const QUrl& changedFile1, const QUrl& changedFile2 ); /** This will show the file and the file with the diff applied */ virtual void openFileAndDiff( const QUrl& file, const QUrl& diffFile ); /** This will show the directory and the directory with the diff applied */ virtual void openDirAndDiff ( const QUrl& dir, const QUrl& diffFile ); /** Reimplementing this because this one knows more about the real part then the interface */ virtual void setEncoding( const QString& encoding ); // This is the interpart interface, it is signal and slot based so no "real" interface here // All you have to do is connect the parts from your application. // These just point to their counterpart in the KompareModelList or get called from their // counterpart in KompareModelList. signals: void modelsChanged( const Diff2::DiffModelList* models ); void setSelection( const Diff2::DiffModel* model, const Diff2::Difference* diff ); void setSelection( const Diff2::Difference* diff ); void selectionChanged( const Diff2::DiffModel* model, const Diff2::Difference* diff ); void selectionChanged( const Diff2::Difference* diff ); void applyDifference( bool apply ); void applyAllDifferences( bool apply ); void applyDifference( const Diff2::Difference*, bool apply ); void configChanged(); /* ** This is emitted when a difference is clicked in the kompare view. You can connect to ** it so you can use it to jump to this particular line in the editor in your app. */ void differenceClicked( int lineNumber ); // Stuff that can probably be removed by putting it in the part where it belongs in my opinion public slots: /** Save all destinations. */ bool saveAll(); /** Save the results of a comparison as a diff file. */ void saveDiff(); /** To enable printing, the part has the only interesting printable content so putting it here */ void slotFilePrint(); void slotFilePrintPreview(); signals: void appliedChanged(); void diffURLChanged(); void kompareInfo( Kompare::Info* info ); void setStatusBarModelInfo( int modelIndex, int differenceIndex, int modelCount, int differenceCount, int appliedCount ); // void setStatusBarText( const QString& text ); void diffString(const QString&); protected: /** * This is the method that gets called when the file is opened, * when using openURL( const QUrl& ) or in our case also openDiff( const QUrl& ); * return true when everything went ok, false if there were problems */ virtual bool openFile(); // ... Uhm we return true without saving ??? virtual bool saveFile() { return true; }; protected slots: void slotSetStatus( Kompare::Status status ); void slotShowError( QString error ); void slotSwap(); void slotShowDiffstats(); void slotRefreshDiff(); void optionsPreferences(); void updateActions(); void updateCaption(); void updateStatus(); void compareAndUpdateAll(); void slotPaintRequested( QPrinter* ); private: void cleanUpTemporaryFiles(); void setupActions(); bool exists( const QString& url ); bool isDirectory( const QUrl& url ); // FIXME (like in cpp file not urgent) Replace with enum, cant find a proper // name now but it is private anyway so can not be used from outside bool fetchURL( const QUrl& url, bool isSource ); private: // Uhm why were these static again ??? // Ah yes, so multiple instances of kompare use the // same settings after one of them changes them static ViewSettings* m_viewSettings; static DiffSettings* m_diffSettings; Diff2::KompareModelList* m_modelList; KompareView* m_view; KompareSplitter* m_splitter; QAction* m_saveAll; QAction* m_saveDiff; QAction* m_swap; QAction* m_diffStats; QAction* m_diffRefresh; QAction* m_print; QAction* m_printPreview; struct Kompare::Info m_info; }; #endif // KOMPAREPART_H diff --git a/komparepart/kompareconnectwidget.h b/komparepart/kompareconnectwidget.h index 60f0d75..77ded6d 100644 --- a/komparepart/kompareconnectwidget.h +++ b/komparepart/kompareconnectwidget.h @@ -1,93 +1,93 @@ /*************************************************************************** kompareconnectwidget.h ---------------------- begin : Tue Jun 26 2001 Copyright 2001-2003 John Firebaugh Copyright 2001-2004 Otto Bruggeman Copyright 2004 Jeff Snyder 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. * * * ***************************************************************************/ #ifndef KOMPARECONNECTWIDGET_H #define KOMPARECONNECTWIDGET_H #include #include #include #include #include #include -#include +#include namespace Diff2 { class DiffModel; } class ViewSettings; class KompareSplitter; class KompareConnectWidget : public QWidget { Q_OBJECT public: KompareConnectWidget( ViewSettings* settings, QWidget* parent, const char* name = 0 ); ~KompareConnectWidget(); public slots: void slotSetSelection( const Diff2::DiffModel* model, const Diff2::Difference* diff ); void slotSetSelection( const Diff2::Difference* diff ); void slotDelayedRepaint(); signals: void selectionChanged(const Diff2::Difference* diff); protected: void paintEvent( QPaintEvent* e ); QPainterPath makeBezier( int l, int r ) const; private: ViewSettings* m_settings; const Diff2::DiffModel* m_selectedModel; const Diff2::Difference* m_selectedDifference; }; class KompareConnectWidgetFrame : public QSplitterHandle { Q_OBJECT public: KompareConnectWidgetFrame( ViewSettings* settings, KompareSplitter* parent, const char* name = 0 ); ~KompareConnectWidgetFrame(); QSize sizeHint() const; KompareConnectWidget* wid() { return &m_wid; } protected: // stop the parent QSplitterHandle painting void paintEvent( QPaintEvent* /* e */ ) { } #if 0 void mouseMoveEvent( QMouseEvent * ); void mousePressEvent( QMouseEvent * ); void mouseReleaseEvent( QMouseEvent * ); #endif private: KompareConnectWidget m_wid; QLabel m_label; QVBoxLayout m_layout; }; #endif diff --git a/komparepart/komparelistview.cpp b/komparepart/komparelistview.cpp index b6cb104..978afb8 100644 --- a/komparepart/komparelistview.cpp +++ b/komparepart/komparelistview.cpp @@ -1,973 +1,974 @@ /*************************************************************************** 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 +#include +#include + #include "viewsettings.h" -#include #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; Q_DECLARE_LOGGING_CATEGORY(KOMPAREPART) KompareListViewFrame::KompareListViewFrame( bool isSource, ViewSettings* settings, KompareSplitter* parent, const char* name ): QFrame ( parent ), m_view ( isSource, settings, this, name ), m_label ( isSource?"Source":"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.setMargin(0); m_layout.addWidget(&m_label); m_layout.addWidget(bottomLine); m_layout.addWidget(&m_view); connect( &m_view, SIGNAL(differenceClicked(const Diff2::Difference*)), parent, SLOT(slotDifferenceClicked(const Diff2::Difference*)) ); connect( parent, SIGNAL(scrollViewsToId(int)), &m_view, SLOT(scrollToId(int)) ); connect( parent, SIGNAL(setXOffset(int)), &m_view, SLOT(setXOffset(int)) ); connect( &m_view, SIGNAL(resized()), parent, SLOT(slotUpdateScrollBars()) ); } void KompareListViewFrame::slotSetModel( const DiffModel* model ) { if( model ) { if( view()->isSource() ) { if( !model->sourceRevision().isEmpty() ) m_label.setText( model->sourceFile() + " (" + model->sourceRevision() + ')' ); else m_label.setText( model->sourceFile() ); } else { if( !model->destinationRevision().isEmpty() ) m_label.setText( model->destinationFile() + " (" + model->destinationRevision() + ')' ); else m_label.setText( model->destinationFile() ); } } else { m_label.setText( QString::null ); //krazy:exclude=nullstrassign for old broken gcc } } KompareListView::KompareListView( bool isSource, ViewSettings* settings, QWidget* parent, const char* name ) : QTreeWidget( parent ), m_isSource( isSource ), m_settings( settings ), m_scrollId( -1 ), m_selectedModel( 0 ), m_selectedDifference( 0 ) { setObjectName( 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 = 0; m_selectedModel = 0; m_selectedDifference = 0; } KompareListViewItem* KompareListView::itemAtIndex( int i ) { return m_items[ i ]; } int KompareListView::firstVisibleDifference() { QTreeWidgetItem* item = itemAt( QPoint( 0, 0 ) ); if( item == 0 ) { 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 == 0 ) { 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; ichild( 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 = 0; if( n ) { int i = 1; for( ; iscrollId() > 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 = 0; 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 0; switch( item->type() ) { case KompareListViewItem::Hunk: if( item->paintHeight() ) return 0; // 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 0; } } void KompareListView::mousePressEvent( QMouseEvent* e ) { QPoint vp = e->pos(); KompareListViewDiffItem* diffItem = diffItemAt( vp ); if( diffItem && diffItem->difference()->type() != Difference::Unchanged ) { 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() ); } } void KompareListView::renumberLines( void ) { // 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(); } 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( 0L ), m_destItem( 0L ) { init(); } KompareListViewDiffItem::KompareListViewDiffItem( KompareListView* parent, KompareListViewItem* after, Difference* difference ) : KompareListViewItem( parent, after, Diff ), m_difference( difference ), m_sourceItem( 0L ), m_destItem( 0L ) { init(); } KompareListViewDiffItem::~KompareListViewDiffItem() { m_difference = 0; } 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( 0 ), 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 = 0; } 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.dark(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; } chunkWidth = p->fontMetrics().width( textChunk ); 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 ); chunkWidth = p->fontMetrics().width( textChunk ); 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),' ')); } 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 = 0; } 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/komparesaveoptionswidget.cpp b/komparepart/komparesaveoptionswidget.cpp index e39eec8..a279280 100644 --- a/komparepart/komparesaveoptionswidget.cpp +++ b/komparepart/komparesaveoptionswidget.cpp @@ -1,223 +1,223 @@ /*************************************************************************** komparesaveoptionswidget.cpp ---------------------------- begin : Sun Mar 4 2001 Copyright 2001-2003 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 "komparesaveoptionswidget.h" #include #include #include #include #include #include -#include +#include KompareSaveOptionsWidget::KompareSaveOptionsWidget( QString source, QString destination, DiffSettings * settings, QWidget * parent ) : KompareSaveOptionsBase( parent ) , m_source( source ) , m_destination( destination ) , m_FormatBG( new QButtonGroup(this) ) { setObjectName("save options"); m_settings = settings; m_directoryRequester->setMode( KFile::ExistingOnly | KFile::Directory | KFile::LocalOnly ); QUrl sourceURL; QUrl destinationURL; sourceURL.setPath( source ); destinationURL.setPath( destination ); // Find a common root. QUrl root( sourceURL ); while( root.isValid() && !root.isParentOf( destinationURL ) && root != KIO::upUrl(root) ) { root = KIO::upUrl(root); } // If we found a common root, change to that directory and // strip the common part from source and destination. if( root.isValid() && root != KIO::upUrl(root) ) { m_directoryRequester->setUrl( root.url() ); } connect( m_SmallerChangesCB, SIGNAL(toggled(bool)), SLOT(updateCommandLine()) ); connect( m_LargeFilesCB, SIGNAL(toggled(bool)), SLOT(updateCommandLine()) ); connect( m_IgnoreCaseCB, SIGNAL(toggled(bool)), SLOT(updateCommandLine()) ); connect( m_ExpandTabsCB, SIGNAL(toggled(bool)), SLOT(updateCommandLine()) ); connect( m_IgnoreEmptyLinesCB, SIGNAL(toggled(bool)), SLOT(updateCommandLine()) ); connect( m_IgnoreWhiteSpaceCB, SIGNAL(toggled(bool)), SLOT(updateCommandLine()) ); connect( m_FunctionNamesCB, SIGNAL(toggled(bool)), SLOT(updateCommandLine()) ); connect( m_RecursiveCB, SIGNAL(toggled(bool)), SLOT(updateCommandLine()) ); connect( m_NewFilesCB, SIGNAL(toggled(bool)), SLOT(updateCommandLine()) ); connect( m_ContextRB, SIGNAL(toggled(bool)), SLOT(updateCommandLine()) ); connect( m_EdRB, SIGNAL(toggled(bool)), SLOT(updateCommandLine()) ); connect( m_NormalRB, SIGNAL(toggled(bool)), SLOT(updateCommandLine()) ); connect( m_RCSRB, SIGNAL(toggled(bool)), SLOT(updateCommandLine()) ); connect( m_UnifiedRB, SIGNAL(toggled(bool)), SLOT(updateCommandLine()) ); connect( m_SideBySideRB, SIGNAL(toggled(bool)), SLOT(updateCommandLine()) ); connect( m_ContextLinesSB, SIGNAL(valueChanged(int)), SLOT(updateCommandLine()) ); connect( m_directoryRequester, SIGNAL(textChanged(const QString&)), SLOT(updateCommandLine()) ); m_FormatBG->setExclusive(true); m_FormatBG->addButton(m_ContextRB, Kompare::Context); m_FormatBG->addButton(m_EdRB, Kompare::Ed); m_FormatBG->addButton(m_NormalRB, Kompare::Normal); m_FormatBG->addButton(m_UnifiedRB, Kompare::Unified); m_FormatBG->addButton(m_RCSRB, Kompare::RCS); m_FormatBG->addButton(m_SideBySideRB, Kompare::SideBySide); loadOptions(); } KompareSaveOptionsWidget::~KompareSaveOptionsWidget() { } QString KompareSaveOptionsWidget::directory() const { return QUrl( m_directoryRequester->url() ).toLocalFile(); } void KompareSaveOptionsWidget::updateCommandLine() { QString cmdLine = "diff"; QString options = ""; switch( static_cast( m_FormatBG->checkedId() ) ) { case Kompare::Unified : cmdLine += " -U " + QString::number( m_ContextLinesSB->value() ); break; case Kompare::Context : cmdLine += " -C " + QString::number( m_ContextLinesSB->value() ); break; case Kompare::RCS : options += 'n'; break; case Kompare::Ed : options += 'e'; break; case Kompare::SideBySide: options += 'y'; break; case Kompare::Normal : case Kompare::UnknownFormat : default: break; } if ( m_SmallerChangesCB->isChecked() ) { options += 'd'; } if ( m_LargeFilesCB->isChecked() ) { options += 'H'; } if ( m_IgnoreCaseCB->isChecked() ){ options += 'i'; } if ( m_ExpandTabsCB->isChecked() ) { options += 't'; } if ( m_IgnoreEmptyLinesCB->isChecked() ) { options += 'B'; } if ( m_IgnoreWhiteSpaceCB->isChecked() ) { options += 'b'; } if ( m_FunctionNamesCB->isChecked() ) { options += 'p'; } // if ( ) { // cmdLine += " -w"; // } if ( m_RecursiveCB->isChecked() ) { options += 'r'; } if( m_NewFilesCB->isChecked() ) { options += 'N'; } // if( m_AllTextCB->isChecked() ) { // options += 'a'; // } if( options.length() > 0 ) { cmdLine += " -" + options; } QDir dir( directory() ); cmdLine += " -- "; cmdLine += dir.relativeFilePath( m_source ); cmdLine += ' '; cmdLine += dir.relativeFilePath( m_destination ); m_CommandLineLabel->setText( cmdLine ); } void KompareSaveOptionsWidget::loadOptions() { m_SmallerChangesCB->setChecked ( m_settings->m_createSmallerDiff ); m_LargeFilesCB->setChecked ( m_settings->m_largeFiles ); m_IgnoreCaseCB->setChecked ( m_settings->m_ignoreChangesInCase ); m_ExpandTabsCB->setChecked ( m_settings->m_convertTabsToSpaces ); m_IgnoreEmptyLinesCB->setChecked( m_settings->m_ignoreEmptyLines ); m_IgnoreWhiteSpaceCB->setChecked( m_settings->m_ignoreWhiteSpace ); m_FunctionNamesCB->setChecked ( m_settings->m_showCFunctionChange ); m_RecursiveCB->setChecked ( m_settings->m_recursive ); m_NewFilesCB->setChecked ( m_settings->m_newFiles ); // m_AllTextCB->setChecked ( m_settings->m_allText ); m_ContextLinesSB->setValue ( m_settings->m_linesOfContext ); m_FormatBG->button(m_settings->m_format)->setChecked(true); updateCommandLine(); } void KompareSaveOptionsWidget::saveOptions() { m_settings->m_createSmallerDiff = m_SmallerChangesCB->isChecked(); m_settings->m_largeFiles = m_LargeFilesCB->isChecked(); m_settings->m_ignoreChangesInCase = m_IgnoreCaseCB->isChecked(); m_settings->m_convertTabsToSpaces = m_ExpandTabsCB->isChecked(); m_settings->m_ignoreEmptyLines = m_IgnoreEmptyLinesCB->isChecked(); m_settings->m_ignoreWhiteSpace = m_IgnoreWhiteSpaceCB->isChecked(); m_settings->m_showCFunctionChange = m_FunctionNamesCB->isChecked(); m_settings->m_recursive = m_RecursiveCB->isChecked(); m_settings->m_newFiles = m_NewFilesCB->isChecked(); // m_settings->m_allText = m_AllTextCB->isChecked(); m_settings->m_linesOfContext = m_ContextLinesSB->value(); m_settings->m_format = static_cast( m_FormatBG->checkedId() ); } diff --git a/komparepart/komparesaveoptionswidget.h b/komparepart/komparesaveoptionswidget.h index e84fc9a..0c4ba53 100644 --- a/komparepart/komparesaveoptionswidget.h +++ b/komparepart/komparesaveoptionswidget.h @@ -1,50 +1,50 @@ /*************************************************************************** komparesaveoptionswidget.h -------------------------- begin : Sun Mar 4 2001 Copyright 2001-2003 Otto Bruggeman Copyright 2001-2003 John Firebaugh ****************************************************************************/ /*************************************************************************** ** ** 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. ** ***************************************************************************/ #ifndef KOMPARESAVEOPTIONSWIDGET_H #define KOMPARESAVEOPTIONSWIDGET_H -#include +#include #include "komparesaveoptionsbase.h" class DiffSettings; class QButtonGroup; class KompareSaveOptionsWidget : public KompareSaveOptionsBase { Q_OBJECT public: KompareSaveOptionsWidget( QString source, QString destination, DiffSettings* settings, QWidget* parent ); ~KompareSaveOptionsWidget(); void saveOptions(); QString directory() const; protected slots: void updateCommandLine(); private: void loadOptions(); DiffSettings* m_settings; QString m_source; QString m_destination; QButtonGroup* m_FormatBG; }; #endif diff --git a/komparepart/komparesplitter.cpp b/komparepart/komparesplitter.cpp index 86257a7..0556dd2 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 +#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, SIGNAL(configChanged()), SLOT(slotConfigChanged()) ); connect( this, SIGNAL(configChanged()), SLOT(slotDelayedRepaintHandles()) ); connect( this, SIGNAL(configChanged()), SLOT(slotDelayedUpdateScrollBars()) ); // scrolling connect( m_vScroll, SIGNAL(valueChanged(int)), SLOT(slotScrollToId(int)) ); connect( m_vScroll, SIGNAL(sliderMoved(int)), SLOT(slotScrollToId(int)) ); connect( m_hScroll, SIGNAL(valueChanged(int)), SIGNAL(setXOffset(int)) ); connect( m_hScroll, SIGNAL(sliderMoved(int)), SIGNAL(setXOffset(int)) ); m_scrollTimer=new QTimer(this); m_restartTimer = false; connect (m_scrollTimer, SIGNAL(timeout()), SLOT(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, SLOT(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 ); 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 ); slotRepaintHandles(); m_vScroll->setValue( id ); m_scrollTimer->start( 30 ); } } void KompareSplitter::slotDelayedUpdateScrollBars() { QTimer::singleShot( 0, this, SLOT( 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, SLOT( 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->orientation() == Qt::Vertical ) { if ( e->modifiers() & Qt::ControlModifier ) { if ( e->delta() < 0 ) // scroll down one page m_vScroll->triggerAction( QAbstractSlider::SliderPageStepAdd ); else // scroll up one page m_vScroll->triggerAction( QAbstractSlider::SliderPageStepSub ); } else { if ( e->delta() < 0 ) // scroll down m_vScroll->triggerAction( QAbstractSlider::SliderSingleStepAdd ); else // scroll up m_vScroll->triggerAction( QAbstractSlider::SliderSingleStepSub ); } } else { if ( e->modifiers() & Qt::ControlModifier ) { if ( e->delta() < 0 ) // scroll right one page m_hScroll->triggerAction( QAbstractSlider::SliderPageStepAdd ); else // scroll left one page m_hScroll->triggerAction( QAbstractSlider::SliderPageStepSub ); } else { if ( e->delta() < 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 ); } 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/komparepart/komparesplitter.h b/komparepart/komparesplitter.h index 2d4c316..812e679 100644 --- a/komparepart/komparesplitter.h +++ b/komparepart/komparesplitter.h @@ -1,121 +1,121 @@ /*************************************************************************** komparesplitter.h ----------------- begin : Wed Jan 14 2004 Copyright 2004 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. ** ***************************************************************************/ #ifndef _KOMPARESPLITTER_H_ #define _KOMPARESPLITTER_H_ #include -#include +#include class QSplitterHandle; class QTimer; class QScrollBar; class QWheelEvent; class QKeyEvent; namespace Diff2 { class DiffModel; class Difference; } class ViewSettings; class KompareListView; class KompareConnectWidget; class KompareSplitter : public QSplitter { Q_OBJECT public: KompareSplitter(ViewSettings *settings, QWidget *parent); ~KompareSplitter(); signals: void configChanged(); void scrollViewsToId( int id ); void setXOffset( int x ); void selectionChanged( const Diff2::Difference* diff ); public slots: void slotScrollToId( int id ); void slotDelayedUpdateScrollBars(); void slotUpdateScrollBars(); void slotDelayedUpdateVScrollValue(); void slotUpdateVScrollValue(); void keyPressEvent( QKeyEvent* e ); void slotApplyDifference( bool apply ); void slotApplyAllDifferences( bool apply ); void slotApplyDifference( const Diff2::Difference* diff, bool apply ); void slotSetSelection( const Diff2::DiffModel* model, const Diff2::Difference* diff ); void slotSetSelection( const Diff2::Difference* diff ); void slotDifferenceClicked( const Diff2::Difference* diff ); void slotConfigChanged(); protected: void wheelEvent( QWheelEvent* e ); ViewSettings* settings() const { return m_settings; } protected slots: void slotDelayedRepaintHandles(); void slotRepaintHandles(); void timerTimeout(); private: // override from QSplitter QSplitterHandle* createHandle(); void setCursor( int id, const QCursor& cursor ); void unsetCursor( int id ); protected: KompareListView* listView( int index ); KompareConnectWidget* connectWidget( int index ); private: // Scrollbars. all this just for the goddamn scrollbars. i hate them. int scrollId(); int lineHeight(); int pageSize(); bool needVScrollBar(); int minVScrollId(); int maxVScrollId(); bool needHScrollBar(); int minHScrollId(); int maxHScrollId(); int maxContentsX(); int minVisibleWidth(); QTimer* m_scrollTimer; bool m_restartTimer; int m_scrollTo; ViewSettings* m_settings; QScrollBar* m_vScroll; QScrollBar* m_hScroll; friend class KompareConnectWidgetFrame; }; #endif //_KOMPARESPLITTER_H_ diff --git a/komparepart/kompareview.h b/komparepart/kompareview.h index 0f26f4b..f02f3ef 100644 --- a/komparepart/kompareview.h +++ b/komparepart/kompareview.h @@ -1,39 +1,39 @@ /************************************************************************** ** kompareview.h ** ------------- ** begin : Thu Nov 3 2011 ** Copyright 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. ** ***************************************************************************/ #ifndef _KOMPAREVIEW_H_ #define _KOMPAREVIEW_H_ #include -#include +#include class ViewSettings; class KompareSplitter; class KompareView : public QFrame { Q_OBJECT public: KompareView(ViewSettings *settings, QWidget *parent); ~KompareView() {} KompareSplitter *splitter() { return m_splitter; } private: KompareSplitter *m_splitter; }; #endif //_KOMPARESPLITTER_H_ diff --git a/kompareurldialog.cpp b/kompareurldialog.cpp index 46857f0..2813f36 100644 --- a/kompareurldialog.cpp +++ b/kompareurldialog.cpp @@ -1,186 +1,187 @@ /*************************************************************************** kompareurldialog.cpp -------------------- begin : Sun Mar 4 2001 Copyright 2001-2005,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 "kompareurldialog.h" #include #include #include #include #include #include #include +#include + #include "diffpage.h" -#include #include "filespage.h" #include "filessettings.h" #include "viewpage.h" #include "viewsettings.h" Q_DECLARE_LOGGING_CATEGORY(KOMPARESHELL) KompareURLDialog::KompareURLDialog( QWidget *parent, Qt::WindowFlags flags ) : KPageDialog( parent, flags ) { setFaceType( List ); KSharedConfig::Ptr cfg = KSharedConfig::openConfig(); m_filesPage = new FilesPage(); KPageWidgetItem *filesItem = addPage( m_filesPage, i18n( "Files" ) ); filesItem->setIcon( QIcon::fromTheme( "text-plain" ) ); filesItem->setHeader( i18n( "Here you can enter the files you want to compare." ) ); m_filesSettings = new FilesSettings( this ); m_filesSettings->loadSettings( cfg.data() ); m_filesPage->setSettings( m_filesSettings ); m_diffPage = new DiffPage(); KPageWidgetItem *diffItem = addPage( m_diffPage, i18n( "Diff" ) ); diffItem->setIcon( QIcon::fromTheme( "text-x-patch" ) ); diffItem->setHeader( i18n( "Here you can change the options for comparing the files." ) ); m_diffSettings = new DiffSettings( this ); m_diffSettings->loadSettings( cfg.data() ); m_diffPage->setSettings( m_diffSettings ); m_viewPage = new ViewPage(); KPageWidgetItem *viewItem = addPage( m_viewPage, i18n( "Appearance" ) ); viewItem->setIcon( QIcon::fromTheme( "preferences-desktop-theme" ) ); viewItem->setHeader( i18n( "Here you can change the options for the view." ) ); m_viewSettings = new ViewSettings( this ); m_viewSettings->loadSettings( cfg.data() ); m_viewPage->setSettings( m_viewSettings ); adjustSize(); connect( m_filesPage->firstURLRequester(), SIGNAL( textChanged( const QString& ) ), this, SLOT( slotEnableOk() ) ); connect( m_filesPage->secondURLRequester(), SIGNAL( textChanged( const QString& ) ), this, SLOT( slotEnableOk() ) ); } KompareURLDialog::~KompareURLDialog() { } void KompareURLDialog::showEvent ( QShowEvent * event ) { if ( !event->spontaneous () ) { slotEnableOk(); } } void KompareURLDialog::slotButtonClicked( int button ) { if ( button == QDialogButtonBox::Cancel ) { reject(); return; } // BUG: 124121 File with filenames to be excluded does not exist so diff complains and no diffs are generated qCDebug(KOMPARESHELL) << "Test to see if the file is an actual file that is given in the file with filenames to exclude field" ; if ( m_diffPage->m_excludeFileNameGroupBox->isChecked() ) { qCDebug(KOMPARESHELL) << "Ok the checkbox is active..." ; if ( QFileInfo( m_diffPage->m_excludeFileURLComboBox->currentText() ).isDir() ) { qCDebug(KOMPARESHELL) << "Don't enter directory names where filenames are expected..." ; KMessageBox::sorry( this, i18n( "File used for excluding files cannot be found, please specify another file." ) ); reject(); return; } } // Room for more checks for invalid input m_filesPage->setURLsInComboBoxes(); KSharedConfig::Ptr cfg = KSharedConfig::openConfig(); m_filesPage->apply(); m_diffPage->apply(); m_viewPage->apply(); m_filesSettings->saveSettings( cfg.data() ); m_diffSettings->saveSettings( cfg.data() ); m_viewSettings->saveSettings( cfg.data() ); cfg->sync(); accept(); } void KompareURLDialog::slotEnableOk() { button(QDialogButtonBox::Ok)->setEnabled( !m_filesPage->firstURLRequester()->url().isEmpty() && !m_filesPage->secondURLRequester()->url().isEmpty() ); } /** * Returns the first URL, which was entered. * @return first URL */ QUrl KompareURLDialog::getFirstURL() const { return m_filesPage->firstURLRequester()->url(); } /** * Returns the second URL, which was entered. * @return second URL */ QUrl KompareURLDialog::getSecondURL() const { return m_filesPage->secondURLRequester()->url(); } /** * Returns the encoding. * @return encoding */ QString KompareURLDialog::encoding() const { return m_filesPage->encoding(); } void KompareURLDialog::setFirstGroupBoxTitle( const QString& title ) { m_filesPage->setFirstGroupBoxTitle( title ); } void KompareURLDialog::setSecondGroupBoxTitle( const QString& title ) { m_filesPage->setSecondGroupBoxTitle( title ); } void KompareURLDialog::setGroup( const QString& groupName ) { m_filesSettings->setGroup( groupName ); m_filesSettings->loadSettings( KSharedConfig::openConfig().data() ); m_filesPage->setSettings( m_filesSettings ); } void KompareURLDialog::setFirstURLRequesterMode( unsigned int mode ) { m_filesPage->setFirstURLRequesterMode( mode ); } void KompareURLDialog::setSecondURLRequesterMode( unsigned int mode ) { m_filesPage->setSecondURLRequesterMode( mode ); } diff --git a/libdialogpages/CMakeLists.txt b/libdialogpages/CMakeLists.txt index 0e49421..b76846b 100644 --- a/libdialogpages/CMakeLists.txt +++ b/libdialogpages/CMakeLists.txt @@ -1,29 +1,27 @@ ########### next target ############### set(dialogpages_PART_SRCS filessettings.cpp viewsettings.cpp diffpage.cpp filespage.cpp viewpage.cpp ) add_library(komparedialogpages SHARED ${dialogpages_PART_SRCS}) -include_directories(${LIBKOMPAREDIFF2_INCLUDE_DIR}) - generate_export_header(komparedialogpages BASE_NAME DIALOGPAGES) target_link_libraries(komparedialogpages + KompareDiff2 KF5::Codecs KF5::Parts KF5::WidgetsAddons - ${LIBKOMPAREDIFF2_LIBRARIES} ) set_target_properties(komparedialogpages PROPERTIES VERSION ${KOMPARE_LIB_VERSION} SOVERSION ${KOMPARE_LIB_SOVERSION} ) install(TARGETS komparedialogpages ${INSTALL_TARGETS_DEFAULT_ARGS} LIBRARY NAMELINK_SKIP) diff --git a/libdialogpages/diffpage.cpp b/libdialogpages/diffpage.cpp index 7fd45fc..15c83a7 100644 --- a/libdialogpages/diffpage.cpp +++ b/libdialogpages/diffpage.cpp @@ -1,401 +1,401 @@ /*************************************************************************** diffprefs.cpp ------------- begin : Sun Mar 4 2001 Copyright 2001-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 "diffpage.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include -#include +#include QUrl urlFromArg(const QString& arg) { #if QT_VERSION >= 0x050400 return QUrl::fromUserInput(arg, QDir::currentPath(), QUrl::AssumeLocalFile); #else // Logic from QUrl::fromUserInput(QString, QString, UserInputResolutionOptions) return (QUrl(arg, QUrl::TolerantMode).isRelative() && !QDir::isAbsolutePath(arg)) ? QUrl::fromLocalFile(QDir::current().absoluteFilePath(arg)) : QUrl::fromUserInput(arg); #endif } DiffPage::DiffPage() : QFrame(), m_ignoreRegExpDialog( 0 ) { QVBoxLayout *layout = new QVBoxLayout( this ); m_tabWidget = new QTabWidget( this ); addDiffTab(); addFormatTab(); addOptionsTab(); addExcludeTab(); layout->addWidget( m_tabWidget ); } DiffPage::~DiffPage() { m_settings = 0; } void DiffPage::setSettings( DiffSettings* setts ) { m_settings = setts; m_diffURLRequester->setUrl( m_settings->m_diffProgram ); m_newFilesCheckBox->setChecked ( m_settings->m_newFiles ); m_smallerCheckBox->setChecked ( m_settings->m_createSmallerDiff ); m_largerCheckBox->setChecked ( m_settings->m_largeFiles ); m_tabsCheckBox->setChecked ( m_settings->m_convertTabsToSpaces ); m_caseCheckBox->setChecked ( m_settings->m_ignoreChangesInCase ); m_linesCheckBox->setChecked ( m_settings->m_ignoreEmptyLines ); m_whitespaceCheckBox->setChecked ( m_settings->m_ignoreWhiteSpace ); m_allWhitespaceCheckBox->setChecked ( m_settings->m_ignoreAllWhiteSpace ); m_ignoreTabExpansionCheckBox->setChecked( m_settings->m_ignoreChangesDueToTabExpansion ); m_ignoreRegExpCheckBox->setChecked ( m_settings->m_ignoreRegExp ); m_ignoreRegExpEdit->setCompletedItems( m_settings->m_ignoreRegExpTextHistory ); m_ignoreRegExpEdit->setText ( m_settings->m_ignoreRegExpText ); m_locSpinBox->setValue( m_settings->m_linesOfContext ); m_modeButtonGroup->button( m_settings->m_format )->setChecked( true ); m_excludeFilePatternGroupBox->setChecked ( m_settings->m_excludeFilePattern ); slotExcludeFilePatternToggled ( m_settings->m_excludeFilePattern ); m_excludeFilePatternEditListBox->insertStringList( m_settings->m_excludeFilePatternList ); m_excludeFileNameGroupBox->setChecked( m_settings->m_excludeFilesFile ); slotExcludeFileToggled ( m_settings->m_excludeFilesFile ); m_excludeFileURLComboBox->setUrls( m_settings->m_excludeFilesFileHistoryList ); m_excludeFileURLComboBox->setUrl ( urlFromArg( m_settings->m_excludeFilesFileURL ) ); } DiffSettings* DiffPage::settings( void ) { return m_settings; } void DiffPage::restore() { // this shouldn't do a thing... } void DiffPage::apply() { m_settings->m_diffProgram = m_diffURLRequester->url().toLocalFile(); m_settings->m_newFiles = m_newFilesCheckBox->isChecked(); m_settings->m_largeFiles = m_largerCheckBox->isChecked(); m_settings->m_createSmallerDiff = m_smallerCheckBox->isChecked(); m_settings->m_convertTabsToSpaces = m_tabsCheckBox->isChecked(); m_settings->m_ignoreChangesInCase = m_caseCheckBox->isChecked(); m_settings->m_ignoreEmptyLines = m_linesCheckBox->isChecked(); m_settings->m_ignoreWhiteSpace = m_whitespaceCheckBox->isChecked(); m_settings->m_ignoreAllWhiteSpace = m_allWhitespaceCheckBox->isChecked(); m_settings->m_ignoreChangesDueToTabExpansion = m_ignoreTabExpansionCheckBox->isChecked(); m_settings->m_ignoreRegExp = m_ignoreRegExpCheckBox->isChecked(); m_settings->m_ignoreRegExpText = m_ignoreRegExpEdit->text(); m_settings->m_ignoreRegExpTextHistory = m_ignoreRegExpEdit->completionObject()->items(); m_settings->m_linesOfContext = m_locSpinBox->value(); m_settings->m_format = static_cast( m_modeButtonGroup->checkedId() ); m_settings->m_excludeFilePattern = m_excludeFilePatternGroupBox->isChecked(); m_settings->m_excludeFilePatternList = m_excludeFilePatternEditListBox->items(); m_settings->m_excludeFilesFile = m_excludeFileNameGroupBox->isChecked(); m_settings->m_excludeFilesFileURL = m_excludeFileURLComboBox->currentText(); m_settings->m_excludeFilesFileHistoryList = m_excludeFileURLComboBox->urls(); m_settings->saveSettings( KSharedConfig::openConfig().data() ); } void DiffPage::setDefaults() { m_diffURLRequester->setUrl( QUrl( "diff" ) ); m_newFilesCheckBox->setChecked( true ); m_smallerCheckBox->setChecked( true ); m_largerCheckBox->setChecked( true ); m_tabsCheckBox->setChecked( false ); m_caseCheckBox->setChecked( false ); m_linesCheckBox->setChecked( false ); m_whitespaceCheckBox->setChecked( false ); m_allWhitespaceCheckBox->setChecked( false ); m_ignoreTabExpansionCheckBox->setChecked( false ); m_ignoreRegExpCheckBox->setChecked( false ); m_ignoreRegExpEdit->setText( QString() ); m_locSpinBox->setValue( 3 ); m_modeButtonGroup->button( Kompare::Unified )->setChecked( true ); m_excludeFilePatternGroupBox->setChecked( false ); m_excludeFileNameGroupBox->setChecked( false ); } void DiffPage::slotShowRegExpEditor() { if ( ! m_ignoreRegExpDialog ) m_ignoreRegExpDialog = KServiceTypeTrader::createInstanceFromQuery( "KRegExpEditor/KRegExpEditor", QString(), this ); KRegExpEditorInterface *iface = qobject_cast( m_ignoreRegExpDialog ); if ( !iface ) return; iface->setRegExp( m_ignoreRegExpEdit->text() ); bool ok = m_ignoreRegExpDialog->exec(); if ( ok ) m_ignoreRegExpEdit->setText( iface->regExp() ); } void DiffPage::slotExcludeFilePatternToggled( bool on ) { m_excludeFilePatternEditListBox->setEnabled( on ); } void DiffPage::slotExcludeFileToggled( bool on ) { m_excludeFileURLComboBox->setEnabled( on ); m_excludeFileURLRequester->setEnabled( on ); } void DiffPage::addDiffTab() { QWidget* page = new QWidget( this ); QVBoxLayout* layout = new QVBoxLayout( page ); // add diff program selector m_diffProgramGroup = new QGroupBox( page ); layout->addWidget( m_diffProgramGroup ); QVBoxLayout* bgLayout = new QVBoxLayout( m_diffProgramGroup ); m_diffProgramGroup->setTitle( i18n( "Diff Program" ) ); m_diffURLRequester = new KUrlRequester( m_diffProgramGroup); m_diffURLRequester->setObjectName("diffURLRequester" ); m_diffURLRequester->setWhatsThis( i18n( "You can select a different diff program here. On Solaris the standard diff program does not support all the options that the GNU version does. This way you can select that version." ) ); bgLayout->addWidget( m_diffURLRequester ); layout->addStretch( 1 ); m_tabWidget->addTab( page, i18n( "Diff" ) ); } void DiffPage::addFormatTab() { QWidget* page = new QWidget( this ); QVBoxLayout* layout = new QVBoxLayout( page ); // add diff modes m_modeButtonGroup = new QButtonGroup( page ); QGroupBox *box = new QGroupBox( page ); box->setWhatsThis( i18n( "Select the format of the output generated by diff. Unified is the one that is used most frequently because it is very readable. The KDE developers like this format the best so use it for sending patches." ) ); layout->addWidget( box ); QVBoxLayout* bgLayout = new QVBoxLayout( box ); box->setTitle( i18n( "Output Format" ) ); QRadioButton *radioButton = new QRadioButton( i18n( "Context" ), box ); m_modeButtonGroup->addButton( radioButton, Kompare::Context); bgLayout->addWidget( radioButton ); radioButton = new QRadioButton( i18n( "Normal" ), box ); m_modeButtonGroup->addButton( radioButton, Kompare::Normal); bgLayout->addWidget( radioButton ); radioButton = new QRadioButton( i18n( "Unified" ), box ); m_modeButtonGroup->addButton( radioButton, Kompare::Unified); bgLayout->addWidget( radioButton ); // #lines of context (loc) QGroupBox* groupBox = new QGroupBox( page ); QHBoxLayout *groupLayout = new QHBoxLayout; groupBox->setLayout( groupLayout ); layout->addWidget( groupBox ); groupBox->setTitle( i18n( "Lines of Context" ) ); groupBox->setWhatsThis( i18n( "The number of context lines is normally 2 or 3. This makes the diff readable and applicable in most cases. More than 3 lines will only bloat the diff unnecessarily." ) ); QLabel* label = new QLabel( i18n( "Number of context lines:" )); groupLayout->addWidget( label ); label->setWhatsThis( i18n( "The number of context lines is normally 2 or 3. This makes the diff readable and applicable in most cases. More than 3 lines will only bloat the diff unnecessarily." ) ); m_locSpinBox = new QSpinBox( groupBox ); m_locSpinBox->setRange( 0, 100 ); groupLayout->addWidget( m_locSpinBox ); m_locSpinBox->setWhatsThis( i18n( "The number of context lines is normally 2 or 3. This makes the diff readable and applicable in most cases. More than 3 lines will only bloat the diff unnecessarily." ) ); label->setBuddy( m_locSpinBox ); layout->addStretch( 1 ); m_tabWidget->addTab( page, i18n( "Format" ) ); } void DiffPage::addOptionsTab() { QWidget* page = new QWidget( this ); QVBoxLayout* layout = new QVBoxLayout( page ); // add diff options QGroupBox* optionButtonGroup = new QGroupBox( page ); layout->addWidget( optionButtonGroup ); QVBoxLayout* bgLayout = new QVBoxLayout( optionButtonGroup ); optionButtonGroup->setTitle( i18n( "General" ) ); m_newFilesCheckBox = new QCheckBox( i18n( "&Treat new files as empty" ), optionButtonGroup ); m_newFilesCheckBox->setToolTip( i18n( "This option corresponds to the -N diff option." ) ); m_newFilesCheckBox->setWhatsThis( i18n( "With this option enabled diff will treat a file that only exists in one of the directories as empty in the other directory. This means that the file is compared with an empty file and because of this will appear as one big insertion or deletion." ) ); bgLayout->addWidget( m_newFilesCheckBox ); m_smallerCheckBox = new QCheckBox( i18n( "&Look for smaller changes" ), optionButtonGroup ); m_smallerCheckBox->setToolTip( i18n( "This corresponds to the -d diff option." ) ); m_smallerCheckBox->setWhatsThis( i18n( "With this option enabled diff will try a little harder (at the cost of more memory) to find fewer changes." ) ); bgLayout->addWidget( m_smallerCheckBox ); m_largerCheckBox = new QCheckBox( i18n( "O&ptimize for large files" ), optionButtonGroup ); m_largerCheckBox->setToolTip( i18n( "This corresponds to the -H diff option." ) ); m_largerCheckBox->setWhatsThis( i18n( "This option lets diff makes better diffs when using large files. The definition of large is nowhere to be found though." ) ); bgLayout->addWidget( m_largerCheckBox ); m_caseCheckBox = new QCheckBox( i18n( "&Ignore changes in case" ), optionButtonGroup ); m_caseCheckBox->setToolTip( i18n( "This corresponds to the -i diff option." ) ); m_caseCheckBox->setWhatsThis( i18n( "With this option to ignore changes in case enabled, diff will not indicate a difference when something in one file is changed into SoMEthing in the other file." ) ); bgLayout->addWidget( m_caseCheckBox ); QHBoxLayout* groupLayout = new QHBoxLayout(); layout->addLayout( groupLayout ); groupLayout->setObjectName( "regexp_horizontal_layout" ); groupLayout->setSpacing( -1 ); m_ignoreRegExpCheckBox = new QCheckBox( i18n( "Ignore regexp:" ), page ); m_ignoreRegExpCheckBox->setToolTip( i18n( "This option corresponds to the -I diff option." ) ); m_ignoreRegExpCheckBox->setWhatsThis( i18n( "When this checkbox is enabled, an option to diff is given that will make diff ignore lines that match the regular expression." ) ); groupLayout->addWidget( m_ignoreRegExpCheckBox ); m_ignoreRegExpEdit = new KLineEdit( QString::null, page); //krazy:exclude=nullstrassign for old broken gcc m_ignoreRegExpEdit->setObjectName("regexplineedit" ); m_ignoreRegExpEdit->setToolTip( i18n( "Add the regular expression here that you want to use\nto ignore lines that match it." ) ); groupLayout->addWidget( m_ignoreRegExpEdit ); if ( !KServiceTypeTrader::self()->query("KRegExpEditor/KRegExpEditor").isEmpty() ) { // Ok editor is available, use it QPushButton* ignoreRegExpEditButton = new QPushButton( i18n( "&Edit..." ), page); ignoreRegExpEditButton->setObjectName( "regexp_editor_button" ); ignoreRegExpEditButton->setToolTip( i18n( "Clicking this will open a regular expression dialog where\nyou can graphically create regular expressions." ) ); groupLayout->addWidget( ignoreRegExpEditButton ); connect( ignoreRegExpEditButton, SIGNAL( clicked() ), this, SLOT( slotShowRegExpEditor() ) ); } QGroupBox* moreOptionButtonGroup = new QGroupBox( page ); layout->addWidget( moreOptionButtonGroup ); bgLayout = new QVBoxLayout( moreOptionButtonGroup ); moreOptionButtonGroup->setTitle( i18n( "Whitespace" ) ); m_tabsCheckBox = new QCheckBox( i18n( "E&xpand tabs to spaces in output" ), moreOptionButtonGroup ); m_tabsCheckBox->setToolTip( i18n( "This option corresponds to the -t diff option." ) ); m_tabsCheckBox->setWhatsThis( i18n( "This option does not always produce the right result. Due to this expansion Kompare may have problems applying the change to the destination file." ) ); bgLayout->addWidget( m_tabsCheckBox ); m_linesCheckBox = new QCheckBox( i18n( "I&gnore added or removed empty lines" ), moreOptionButtonGroup ); m_linesCheckBox->setToolTip( i18n( "This option corresponds to the -B diff option." ) ); m_linesCheckBox->setWhatsThis( i18n( "This can be very useful in situations where code has been reorganized and empty lines have been added or removed to improve legibility." ) ); bgLayout->addWidget( m_linesCheckBox ); m_whitespaceCheckBox = new QCheckBox( i18n( "Ig&nore changes in the amount of whitespace" ), moreOptionButtonGroup ); m_whitespaceCheckBox->setToolTip( i18n( "This option corresponds to the -b diff option." ) ); m_whitespaceCheckBox->setWhatsThis( i18n( "If you are uninterested in differences arising due to, for example, changes in indentation, then use this option." ) ); bgLayout->addWidget( m_whitespaceCheckBox ); m_allWhitespaceCheckBox = new QCheckBox( i18n( "Ign&ore all whitespace" ), moreOptionButtonGroup ); m_allWhitespaceCheckBox->setToolTip( i18n( "This option corresponds to the -w diff option." ) ); m_allWhitespaceCheckBox->setWhatsThis( i18n( "This is useful for seeing the significant changes without being overwhelmed by all the white space changes." ) ); bgLayout->addWidget( m_allWhitespaceCheckBox ); m_ignoreTabExpansionCheckBox = new QCheckBox( i18n( "Igno&re changes due to tab expansion" ), moreOptionButtonGroup ); m_ignoreTabExpansionCheckBox->setToolTip( i18n( "This option corresponds to the -E diff option." ) ); m_ignoreTabExpansionCheckBox->setWhatsThis( i18n( "If there is a change because tabs have been expanded into spaces in the other file, then this option will make sure that these do not show up. Kompare currently has some problems applying such changes so be careful when you use this option." ) ); bgLayout->addWidget( m_ignoreTabExpansionCheckBox ); layout->addStretch( 1 ); m_tabWidget->addTab( page, i18n( "Options" ) ); } void DiffPage::addExcludeTab() { QWidget* page = new QWidget( this ); QVBoxLayout* layout = new QVBoxLayout( page ); m_excludeFilePatternGroupBox = new QGroupBox( page ); m_excludeFilePatternGroupBox->setCheckable(true); QHBoxLayout *excludeFileLayout = new QHBoxLayout; m_excludeFilePatternGroupBox->setLayout( excludeFileLayout ); m_excludeFilePatternGroupBox->setTitle( i18n( "File Pattern to Exclude" ) ); m_excludeFilePatternGroupBox->setToolTip( i18n( "If this is checked you can enter a shell pattern in the text box on the right or select entries from the list." ) ); m_excludeFilePatternEditListBox = new KEditListWidget; excludeFileLayout->addWidget( m_excludeFilePatternEditListBox ); m_excludeFilePatternEditListBox->setObjectName( "exclude_file_pattern_editlistbox" ); m_excludeFilePatternEditListBox->setButtons( KEditListWidget::Add|KEditListWidget::Remove ); m_excludeFilePatternEditListBox->setCheckAtEntering( false ); m_excludeFilePatternEditListBox->setToolTip( i18n( "Here you can enter or remove a shell pattern or select one or more entries from the list." ) ); layout->addWidget( m_excludeFilePatternGroupBox ); connect( m_excludeFilePatternGroupBox, SIGNAL(toggled(bool)), this, SLOT(slotExcludeFilePatternToggled(bool))); m_excludeFileNameGroupBox = new QGroupBox( page ); m_excludeFileNameGroupBox->setCheckable( true ); excludeFileLayout = new QHBoxLayout; m_excludeFileNameGroupBox->setLayout( excludeFileLayout ); m_excludeFileNameGroupBox->setTitle( i18n( "File with Filenames to Exclude" ) ); m_excludeFileNameGroupBox->setToolTip( i18n( "If this is checked you can enter a filename in the combo box below." ) ); m_excludeFileURLComboBox = new KUrlComboBox( KUrlComboBox::Files, true ); excludeFileLayout->addWidget( m_excludeFileURLComboBox ); m_excludeFileURLComboBox->setObjectName( "exclude_file_urlcombo" ); m_excludeFileURLComboBox->setToolTip( i18n( "Here you can enter the URL of a file with shell patterns to ignore during the comparison of the folders." ) ); m_excludeFileURLRequester = new KUrlRequester( m_excludeFileURLComboBox,m_excludeFileNameGroupBox ); excludeFileLayout->addWidget( m_excludeFileURLRequester ); m_excludeFileURLRequester->setObjectName("exclude_file_name_urlrequester" ); m_excludeFileURLRequester->setToolTip( i18n( "Any file you select in the dialog that pops up when you click it will be put in the dialog to the left of this button." ) ); layout->addWidget( m_excludeFileNameGroupBox ); connect( m_excludeFileNameGroupBox, SIGNAL(toggled(bool)), this, SLOT(slotExcludeFileToggled(bool))); layout->addStretch( 1 ); m_tabWidget->addTab( page, i18n( "Exclude" ) ); } //kate: replace-tabs 0; indent-width 4; tab-width 4; diff --git a/libdialogpages/filessettings.h b/libdialogpages/filessettings.h index ba4481c..85b099c 100644 --- a/libdialogpages/filessettings.h +++ b/libdialogpages/filessettings.h @@ -1,54 +1,54 @@ /*************************************************************************** filessettings.h --------------- begin : Sun Apr 18 2004 Copyright 2004 Otto Bruggeman ****************************************************************************/ /*************************************************************************** ** ** 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. ** ****************************************************************************/ #ifndef FILESSETTINGS_H #define FILESSETTINGS_H #include #include -#include +#include #include "dialogpages_export.h" class KConfig; class DIALOGPAGES_EXPORT FilesSettings : public SettingsBase { Q_OBJECT public: FilesSettings( QWidget* parent ); virtual ~FilesSettings(); public: // some virtual functions that will be overloaded from the base class virtual void loadSettings( KConfig* config ); virtual void saveSettings( KConfig* config ); void setGroup( const QString& groupName ); public: QString m_configGroupName; QStringList m_recentSources; QString m_lastChosenSourceURL; QStringList m_recentDestinations; QString m_lastChosenDestinationURL; QString m_encoding; }; #endif // FILESSETTINGS_H diff --git a/libdialogpages/viewsettings.h b/libdialogpages/viewsettings.h index 2ea3d16..5d265ec 100644 --- a/libdialogpages/viewsettings.h +++ b/libdialogpages/viewsettings.h @@ -1,61 +1,61 @@ /*************************************************************************** generalsettings.h ----------------- begin : Sun Mar 4 2001 Copyright 2001-2003 Otto Bruggeman Copyright 2001-2003 John Firebaugh ****************************************************************************/ /*************************************************************************** ** ** 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. ** ***************************************************************************/ #ifndef VIEWSETTINGS_H #define VIEWSETTINGS_H #include #include -#include -#include +#include +#include #include "dialogpages_export.h" class DIALOGPAGES_EXPORT ViewSettings : public SettingsBase { Q_OBJECT public: static const QColor default_removeColor; static const QColor default_changeColor; static const QColor default_addColor; static const QColor default_appliedColor; ViewSettings( QWidget* parent ); ~ViewSettings(); public: // some virtual functions that will be overloaded from the base class virtual void loadSettings( KConfig* config ); virtual void saveSettings( KConfig* config ); QColor colorForDifferenceType( int type, bool selected = false, bool applied = false ); public: QColor m_removeColor; QColor m_changeColor; QColor m_addColor; QColor m_appliedColor; QColor m_selectedRemoveColor; QColor m_selectedChangeColor; QColor m_selectedAddColor; QColor m_selectedAppliedColor; int m_scrollNoOfLines; int m_tabToNumberOfSpaces; QFont m_font; }; #endif // VIEWSETTINGS_H