diff options
Diffstat (limited to 'kompare/komparepart')
-rw-r--r-- | kompare/komparepart/Makefile.am | 49 | ||||
-rw-r--r-- | kompare/komparepart/kompare_part.cpp | 759 | ||||
-rw-r--r-- | kompare/komparepart/kompare_part.h | 223 | ||||
-rw-r--r-- | kompare/komparepart/kompare_qsplitter.h | 213 | ||||
-rw-r--r-- | kompare/komparepart/kompareconnectwidget.cpp | 285 | ||||
-rw-r--r-- | kompare/komparepart/kompareconnectwidget.h | 95 | ||||
-rw-r--r-- | kompare/komparepart/komparelistview.cpp | 783 | ||||
-rw-r--r-- | kompare/komparepart/komparelistview.h | 225 | ||||
-rw-r--r-- | kompare/komparepart/komparepart.desktop | 24 | ||||
-rw-r--r-- | kompare/komparepart/komparepartui.rc | 44 | ||||
-rw-r--r-- | kompare/komparepart/kompareprefdlg.cpp | 106 | ||||
-rw-r--r-- | kompare/komparepart/kompareprefdlg.h | 54 | ||||
-rw-r--r-- | kompare/komparepart/komparesaveoptionsbase.ui | 336 | ||||
-rw-r--r-- | kompare/komparepart/komparesaveoptionswidget.cpp | 215 | ||||
-rw-r--r-- | kompare/komparepart/komparesaveoptionswidget.h | 51 | ||||
-rw-r--r-- | kompare/komparepart/komparesplitter.cpp | 712 | ||||
-rw-r--r-- | kompare/komparepart/komparesplitter.h | 115 |
17 files changed, 4289 insertions, 0 deletions
diff --git a/kompare/komparepart/Makefile.am b/kompare/komparepart/Makefile.am new file mode 100644 index 00000000..f076448b --- /dev/null +++ b/kompare/komparepart/Makefile.am @@ -0,0 +1,49 @@ +######################################################################### +# KPART SECTION +######################################################################### + +INCLUDES = \ + -I$(top_srcdir)/kompare/libdialogpages \ + -I$(top_srcdir)/kompare/libdiff2 \ + -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 \ + ../libdiff2/libdiff2.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/kompare/komparepart/kompare_part.cpp b/kompare/komparepart/kompare_part.cpp new file mode 100644 index 00000000..d74945e6 --- /dev/null +++ b/kompare/komparepart/kompare_part.cpp @@ -0,0 +1,759 @@ +/*************************************************************************** + kompare_part.cpp - description + ------------------- + begin : Sun Mar 4 2001 + copyright : (C) 2001-2004 Otto Bruggeman + (C) 2001-2003 John Firebaugh + (C) 2004 Jeff Snyder + email : otto.bruggeman@home.nl + jfirebaugh@kde.org + jeff@caffeinated.me.uk +****************************************************************************/ + +/*************************************************************************** +** +** 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_qsplitter.h" // make sure we get there first + +#include <qlayout.h> +#include <qwidget.h> + +#include <kaction.h> +#include <kapplication.h> +#include <kdebug.h> +#include <kfiletreeview.h> +#include <kfiledialog.h> +#include <klocale.h> +#include <kmessagebox.h> +#include <kstdaction.h> +#include <kinstance.h> +#include <ktempfile.h> +#include <kparts/genericfactory.h> +//#include <ktempdir.h> + +#include <kio/netaccess.h> + +#include "diffmodel.h" +#include "komparelistview.h" +#include "kompareconnectwidget.h" +#include "diffsettings.h" +#include "viewsettings.h" +#include "kompareprefdlg.h" +#include "komparesaveoptionswidget.h" +#include "komparesplitter.h" + +#include "kompare_part.h" + +typedef KParts::GenericFactory<KomparePart> KomparePartFactory; +K_EXPORT_COMPONENT_FACTORY( libkomparepart, KomparePartFactory ) + +ViewSettings* KomparePart::m_viewSettings = 0L; +DiffSettings* KomparePart::m_diffSettings = 0L; + +KomparePart::KomparePart( QWidget *parentWidget, const char *widgetName, + QObject *parent, const char *name, const QStringList & /*args*/ ) : + KParts::ReadWritePart(parent, name), + m_tempDiff( 0 ), + m_info() +{ + // we need an instance + setInstance( KomparePartFactory::instance() ); + + if( !m_viewSettings ) { + m_viewSettings = new ViewSettings( 0 ); + } + if( !m_diffSettings ) { + m_diffSettings = new DiffSettings( 0 ); + } + + readProperties( kapp->config() ); + + // This creates the "Model creator" and connects the signals and slots + m_modelList = new Diff2::KompareModelList( m_diffSettings, m_info, this, "komparemodellist" ); + 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( setModified( bool ) ), + this, SLOT( slotSetModified( bool ) ) ); + + // 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)) ); + + // This creates the splitterwidget and connects the signals and slots + m_splitter = new KompareSplitter ( m_viewSettings, parentWidget, widgetName ); + + 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()) ); + + // notify the part that this is our internal widget + setWidget( m_splitter->parentWidget() ); + + 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 = new KAction( i18n("Save &All"), "save_all", 0, + this, SLOT(saveAll()), + actionCollection(), "file_save_all" ); + m_saveDiff = new KAction( i18n("Save .&diff..."), 0, + this, SLOT(saveDiff()), + actionCollection(), "file_save_diff" ); + m_swap = new KAction( i18n( "Swap Source with Destination" ), 0, + this, SLOT(slotSwap()), + actionCollection(), "file_swap" ); + m_diffStats = new KAction( i18n( "Show Statistics" ), 0, + this, SLOT(slotShowDiffstats()), + actionCollection(), "file_diffstats" ); + + KStdAction::preferences(this, SLOT(optionsPreferences()), actionCollection()); +} + +void KomparePart::updateActions() +{ + m_saveAll->setEnabled ( m_modelList->isModified() ); + 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_diffStats->setEnabled( m_modelList->modelCount() > 0 ); +} + +void KomparePart::setEncoding( const QString& encoding ) +{ + kdDebug() << "Encoding: " << encoding << endl; + m_modelList->setEncoding( encoding ); +} + +bool KomparePart::openDiff( const KURL& url ) +{ + kdDebug(8103) << "Url = " << url.url() << endl; + + emit kompareInfo( &m_info ); + + m_info.mode = Kompare::ShowingDiff; + m_info.source = url; + bool result = false; + m_info.localSource = fetchURL( url ); + if ( !m_info.localSource.isEmpty() ) + { + kdDebug(8103) << "Download succeeded " << endl; + result = m_modelList->openDiff( m_info.localSource ); + updateActions(); + updateCaption(); + updateStatus(); + } + else + { + kdDebug(8103) << "Download failed !" << endl; + } + + return result; +} + +bool KomparePart::openDiff( const QString& diffOutput ) +{ + bool value = false; + + emit kompareInfo( &m_info ); + + m_info.mode = Kompare::ShowingDiff; + + if ( m_modelList->parseDiffOutput( diffOutput ) == 0 ) + { + value = true; + m_modelList->show(); + updateActions(); + updateCaption(); + updateStatus(); + } + + return value; +} + +bool KomparePart::openDiff3( const KURL& diff3Url ) +{ + // FIXME: Implement this !!! + kdDebug(8103) << "Not implemented yet. Filename is: " << diff3Url.url() << endl; + return false; +} + +bool KomparePart::openDiff3( const QString& diff3Output ) +{ + // FIXME: Implement this !!! + kdDebug(8103) << "Not implemented yet. diff3 output is: " << endl; + kdDebug(8103) << diff3Output << endl; + return false; +} + +bool KomparePart::exists( const QString& url ) +{ + QFileInfo fi( url ); + return fi.exists(); +} + +const QString KomparePart::fetchURL( const KURL& url ) +{ + QString tempFileName( "" ); + if ( !url.isLocalFile() ) + { + if ( ! KIO::NetAccess::download( url, tempFileName, widget() ) ) + { + slotShowError( i18n( "<qt>The URL <b>%1</b> cannot be downloaded.</qt>" ).arg( url.prettyURL() ) ); + tempFileName = ""; + } + return tempFileName; + } + else + { + // is Local already, check if exists + if ( exists( url.path() ) ) + return url.path(); + else + { + slotShowError( i18n( "<qt>The URL <b>%1</b> does not exist on your system.</qt>" ).arg( url.prettyURL() ) ); + return tempFileName; + } + } +} + +void KomparePart::cleanUpTemporaryFiles() +{ + // i hope a local file will not be removed if it was not downloaded... + if ( !m_info.localSource.isEmpty() ) + KIO::NetAccess::removeTempFile( m_info.localSource ); + if ( !m_info.localDestination.isEmpty() ) + KIO::NetAccess::removeTempFile( m_info.localDestination ); +} + +void KomparePart::compare( const KURL& source, const KURL& destination ) +{ + m_info.source = source; + m_info.destination = destination; + + m_info.localSource = fetchURL( source ); + m_info.localDestination = fetchURL( destination ); + + emit kompareInfo( &m_info ); + + if ( !m_info.localSource.isEmpty() && !m_info.localDestination.isEmpty() ) + { + m_modelList->compare( m_info.localSource, m_info.localDestination ); + updateActions(); + updateCaption(); + updateStatus(); + } +} + +void KomparePart::compareFiles( const KURL& sourceFile, const KURL& destinationFile ) +{ + emit kompareInfo( &m_info ); + + m_info.mode = Kompare::ComparingFiles; + + m_info.source = sourceFile; + m_info.destination = destinationFile; + + m_info.localSource = fetchURL( sourceFile ); + m_info.localDestination = fetchURL( destinationFile ); + + if ( !m_info.localSource.isEmpty() && !m_info.localDestination.isEmpty() ) + { + m_modelList->compareFiles( m_info.localSource, m_info.localDestination ); + updateActions(); + updateCaption(); + updateStatus(); + } +} + +void KomparePart::compareDirs( const KURL& sourceDirectory, const KURL& destinationDirectory ) +{ + emit kompareInfo( &m_info ); + + m_info.mode = Kompare::ComparingDirs; + + m_info.source = sourceDirectory; + m_info.destination = destinationDirectory; + + m_info.localSource = fetchURL( sourceDirectory ); + m_info.localDestination = fetchURL( destinationDirectory ); + + if ( !m_info.localSource.isEmpty() && !m_info.localDestination.isEmpty() ) + { + m_modelList->compareDirs( m_info.localSource, m_info.localDestination ); + updateActions(); + updateCaption(); + updateStatus(); + } +} + +void KomparePart::compare3Files( const KURL& /*originalFile*/, const KURL& /*changedFile1*/, const KURL& /*changedFile2*/ ) +{ + // FIXME: actually implement this some day :) + updateActions(); + updateCaption(); + updateStatus(); +} + +void KomparePart::openFileAndDiff( const KURL& file, const KURL& diffFile ) +{ + emit kompareInfo( &m_info ); + + m_info.source = file; + m_info.destination = diffFile; + + m_info.localSource = fetchURL( file ); + m_info.localDestination = fetchURL( diffFile ); + m_info.mode = Kompare::BlendingFile; + + if ( !m_info.localSource.isEmpty() && !m_info.localDestination.isEmpty() ) + { + m_modelList->openFileAndDiff( m_info.localSource, m_info.localDestination ); + updateActions(); + updateCaption(); + updateStatus(); + } +} + +void KomparePart::openDirAndDiff ( const KURL& dir, const KURL& diffFile ) +{ + emit kompareInfo( &m_info ); + + m_info.source = dir; + m_info.destination = diffFile; + + m_info.localSource = fetchURL( dir ); + m_info.localDestination = fetchURL( diffFile ); + m_info.mode = Kompare::BlendingDir; + + if ( !m_info.localSource.isEmpty() && !m_info.localDestination.isEmpty() ) + { + m_modelList->openDirAndDiff( m_info.localSource, m_info.localDestination ); + updateActions(); + updateCaption(); + updateStatus(); + } +} + +bool KomparePart::openFile() +{ + // This is called from openURL + // This is a little inefficient but i will do it anyway + openDiff( m_url ); + return true; +} + +bool KomparePart::saveAll() +{ + bool result = m_modelList->saveAll(); + updateActions(); + updateCaption(); + updateStatus(); + return result; +} + +void KomparePart::saveDiff() +{ + KDialogBase* dlg = new KDialogBase( widget(), "save_options", + true /* modal */, i18n("Diff Options"), + KDialogBase::Ok|KDialogBase::Cancel ); + KompareSaveOptionsWidget* w = new KompareSaveOptionsWidget( + m_info.localSource, + m_info.localDestination, + m_diffSettings, dlg ); + dlg->setMainWidget( w ); + dlg->setButtonOK( KStdGuiItem::save() ); + + if( dlg->exec() ) { + w->saveOptions(); + KConfig* config = instance()->config(); + saveProperties( config ); + config->sync(); + + while ( 1 ) + { + KURL url = KFileDialog::getSaveURL( m_info.destination.url(), + i18n("*.diff *.dif *.patch|Patch Files"), widget(), i18n( "Save .diff" ) ); + if ( KIO::NetAccess::exists( url, false, widget() ) ) + { + int result = KMessageBox::warningYesNoCancel( widget(), i18n("The file exists or is write-protected; do you want to overwrite it?"), i18n("File Exists"), i18n("Overwrite"), i18n("Do Not Overwrite") ); + if ( result == KMessageBox::Cancel ) + { + break; + } + else if ( result == KMessageBox::No ) + { + continue; + } + else + { + kdDebug(8103) << "URL = " << url.prettyURL() << endl; + kdDebug(8103) << "Directory = " << w->directory() << endl; + kdDebug(8103) << "DiffSettings = " << m_diffSettings << endl; + + m_modelList->saveDiff( url.url(), w->directory(), m_diffSettings ); + break; + } + } + else + { + kdDebug(8103) << "URL = " << url.prettyURL() << endl; + kdDebug(8103) << "Directory = " << w->directory() << endl; + kdDebug(8103) << "DiffSettings = " << m_diffSettings << endl; + + m_modelList->saveDiff( url.url(), w->directory(), m_diffSettings ); + break; + } + } + } + delete dlg; +} + +KAboutData *KomparePart::createAboutData() +{ + KAboutData *about = new KAboutData("kompare", I18N_NOOP("KomparePart"), "3.2"); + about->addAuthor("John Firebaugh", "Author", "jfirebaugh@kde.org"); + about->addAuthor("Otto Bruggeman", "Author", "otto.bruggeman@home.nl" ); + 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.prettyURL(); + QString destination = m_info.destination.prettyURL(); + + QString text; + + switch ( m_info.mode ) + { + case Kompare::ComparingFiles : + case Kompare::ComparingDirs : + case Kompare::BlendingFile : + case Kompare::BlendingDir : + text = source + ":" + destination; + break; + case Kompare::ShowingDiff : + text = source; + break; + default: + break; + } + + emit setWindowCaption( text ); +} + +void KomparePart::updateStatus() +{ + QString source = m_info.source.prettyURL(); + QString destination = m_info.destination.prettyURL(); + + QString text; + + switch ( m_info.mode ) + { + case Kompare::ComparingFiles : + text = i18n( "Comparing file %1 with file %2" ) + .arg( source ) + .arg( destination ); + break; + case Kompare::ComparingDirs : + text = i18n( "Comparing files in %1 with files in %2" ) + .arg( source ) + .arg( destination ); + break; + case Kompare::ShowingDiff : + text = i18n( "Viewing diff output from %1" ).arg( source ); + break; + case Kompare::BlendingFile : + text = i18n( "Blending diff output from %1 into file %2" ) + .arg( source ) + .arg( destination ); + break; + case Kompare::BlendingDir : + text = i18n( "Blending diff output from %1 into folder %2" ) + .arg( m_info.source.prettyURL() ) + .arg( m_info.destination.prettyURL() ); + break; + default: + break; + } + + emit setStatusBarText( text ); +} + +void KomparePart::slotShowError( QString error ) +{ + KMessageBox::error( widget(), error ); +} + +void KomparePart::slotSwap() +{ + if ( isModified() ) + { + 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?" ), + KStdGuiItem::save(), + KStdGuiItem::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 + KURL url = m_info.source; + m_info.source = m_info.destination; + m_info.destination = url; + + QString string = m_info.localSource; + m_info.localSource = m_info.localDestination; + m_info.localDestination = string; + + // Update window caption and statusbar text + updateCaption(); + updateStatus(); + + m_modelList->swap(); +} + +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::null, false ); + } + 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") + .arg(oldFile).arg(newFile).arg(diffFormat) + .arg(noOfHunks).arg(noOfDiffs), + i18n("Diff Statistics"), QString::null, false ); + } else { // more than 1 file in diff, or 2 directories compared + KMessageBox::information( 0L, i18n( + "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") + .arg(filesInDiff).arg(diffFormat).arg(oldFile) + .arg(newFile).arg(noOfHunks).arg(noOfDiffs), + i18n("Diff Statistics"), QString::null, false ); + } +} + +bool KomparePart::queryClose() +{ + if( !isModified() ) 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?" ), + KStdGuiItem::save(), + KStdGuiItem::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 = new KomparePrefDlg( m_viewSettings, m_diffSettings ); + + connect( pref, SIGNAL(applyClicked()), this, SIGNAL(configChanged()) ); + + if ( pref->exec() ) + emit configChanged(); +} + +void KomparePart::slotSetModified( bool modified ) +{ + kdDebug() << "KomparePart::slotSetModified( " << modified << " );" << endl; + setModified( modified ); + updateActions(); + updateCaption(); +} + +#include "kompare_part.moc" diff --git a/kompare/komparepart/kompare_part.h b/kompare/komparepart/kompare_part.h new file mode 100644 index 00000000..0a9716c3 --- /dev/null +++ b/kompare/komparepart/kompare_part.h @@ -0,0 +1,223 @@ +/*************************************************************************** + kompare_part.h - description + ------------------- + begin : Sun Mar 4 2001 + copyright : (C) 2001-2004 Otto Bruggeman + (C) 2001-2003 John Firebaugh + (C) 2004 Jeff Snyder + email : otto.bruggeman@home.nl + jfirebaugh@kde.org + jeff@caffeinated.me.uk +****************************************************************************/ + +/*************************************************************************** +** +** 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 <kparts/factory.h> +#include <kparts/part.h> + +#include "kompare.h" + +#include "kompareinterface.h" + +class QWidget; + +class KTempFile; +class KToggleAction; +class KURL; + +namespace Diff2 { +class Difference; +class DiffModel; +class DiffModelList; +class KompareModelList; +} +class DiffSettings; +class ViewSettings; +class KFileTreeView; +class KompareSplitter; +class KompareProcess; + +/** + * This is a "Part". It does all the real work in a KPart + * application. + * + * @short Main Part + * @author John Firebaugh <jfirebaugh@kde.org> + * @author Otto Bruggeman <bruggie@home.nl> + * @version 0.3 + */ +class KomparePart : public KParts::ReadWritePart, + public KompareInterface +{ + Q_OBJECT +public: + /** + * Default constructor + */ + KomparePart( QWidget *parentWidget, const char *widgetName, + QObject *parent, const char *name, const QStringList & /*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 dont (can't) + // use the readProperties and saveProperties methods + virtual bool queryClose(); + + // bool isModified() const { return m_modelList->isModified(); } + // 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 KURL& 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 KURL& 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 KURL& sourceFile, const KURL& destinationFile ); + + /** Compare, with diff, source with destination */ + virtual void compareFiles( const KURL& sourceFile, const KURL& destinationFile ); + + /** Compare, with diff, source with destination */ + virtual void compareDirs ( const KURL& sourceDir, const KURL& destinationDir ); + + /** Compare, with diff3, originalFile with changedFile1 and changedFile2 */ + virtual void compare3Files( const KURL& originalFile, const KURL& changedFile1, const KURL& changedFile2 ); + + /** This will show the file and the file with the diff applied */ + virtual void openFileAndDiff( const KURL& file, const KURL& diffFile ); + + /** This will show the directory and the directory with the diff applied */ + virtual void openDirAndDiff ( const KURL& dir, const KURL& 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(); + + /** This slot is connected to the setModifed( bool ) signal from the KompareModelList */ + void slotSetModified( bool modified ); + +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 ); + +protected: + /** + * This is the method that gets called when the file is opened, + * when using openURL( const KURL& ) or in our case also openDiff( const KURL& ); + * return true when everything went ok, false if there were problems + */ + virtual bool openFile(); + virtual bool saveFile() { return true; }; + + // patchFile + bool patchFile(KURL&); + bool patchDir(); + +protected slots: + void slotSetStatus( Kompare::Status status ); + void slotShowError( QString error ); + + void slotSwap(); + void slotShowDiffstats(); + void optionsPreferences(); + void updateActions(); + void updateCaption(); + void updateStatus(); + +private: + void cleanUpTemporaryFiles(); + void setupActions(); + bool exists( const QString& url ); + bool isDirectory( const KURL& url ); + const QString fetchURL( const KURL& url ); + +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; + + KompareSplitter* m_splitter; + + KAction* m_saveAll; + KAction* m_saveDiff; + KAction* m_swap; + KAction* m_diffStats; + + KTempFile* m_tempDiff; + + struct Kompare::Info m_info; +}; + +#endif // KOMPAREPART_H diff --git a/kompare/komparepart/kompare_qsplitter.h b/kompare/komparepart/kompare_qsplitter.h new file mode 100644 index 00000000..1f1be49d --- /dev/null +++ b/kompare/komparepart/kompare_qsplitter.h @@ -0,0 +1,213 @@ +/**************************************************************************** +** +** +** Definition of QSplitter class +** +** Created : 980105 +** +** Copyright (C) 1992-2000 Trolltech AS. All rights reserved. +** +** This file is part of the widgets module of the Qt GUI Toolkit. +** +** This file may be distributed and/or modified under the terms of the +** GNU General Public License version 2 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +** See http://www.trolltech.com/gpl/ for GPL licensing information. +** +**********************************************************************/ + +#ifndef QSPLITTER_H +#define QSPLITTER_H + +#ifndef QT_H +#include "qframe.h" +#include "qvaluelist.h" +#endif // QT_H + +#ifndef QT_NO_SPLITTER + + +//class QSplitterHandle; +class QSplitterLayoutStruct; +class QTextStream; + +class QSplitterPrivate +{ +public: + QSplitterPrivate() + : opaque( FALSE ), firstShow( TRUE ), childrenCollapsible( TRUE ), + handleWidth( 0 ) { } + + QPtrList<QSplitterLayoutStruct> list; + bool opaque : 8; + bool firstShow : 8; + bool childrenCollapsible : 8; + int handleWidth; +}; + +class Q_EXPORT QSplitter : public QFrame +{ + Q_OBJECT + Q_PROPERTY( Orientation orientation READ orientation WRITE setOrientation ) + Q_PROPERTY( bool opaqueResize READ opaqueResize WRITE setOpaqueResize ) + Q_PROPERTY( int handleWidth READ handleWidth WRITE setHandleWidth ) + Q_PROPERTY( bool childrenCollapsible READ childrenCollapsible WRITE setChildrenCollapsible ) + +public: + // ### Qt 4.0: remove Auto from public API + enum ResizeMode { Stretch, KeepSize, FollowSizeHint, Auto }; + + QSplitter( QWidget* parent = 0, const char* name = 0 ); + QSplitter( Orientation, QWidget* parent = 0, const char* name = 0 ); + ~QSplitter(); + + virtual void setOrientation( Orientation ); + Orientation orientation() const { return orient; } + + // ### Qt 4.0: make setChildrenCollapsible() and setCollapsible() virtual + + void setChildrenCollapsible( bool ); + bool childrenCollapsible() const; + + void setCollapsible( QWidget *w, bool ); + virtual void setResizeMode( QWidget *w, ResizeMode ); + virtual void setOpaqueResize( bool = TRUE ); + bool opaqueResize() const; + + void moveToFirst( QWidget * ); + void moveToLast( QWidget * ); + + void refresh() { recalc( TRUE ); } + QSize sizeHint() const; + QSize minimumSizeHint() const; + + QValueList<int> sizes() const; + void setSizes( QValueList<int> ); + + int handleWidth() const; + void setHandleWidth( int ); + +protected: + void childEvent( QChildEvent * ); + + bool event( QEvent * ); + void resizeEvent( QResizeEvent * ); + + int idAfter( QWidget* ) const; + + void moveSplitter( QCOORD pos, int id ); + virtual void drawSplitter( QPainter*, QCOORD x, QCOORD y, + QCOORD w, QCOORD h ); + void styleChange( QStyle& ); + int adjustPos( int, int ); + virtual void setRubberband( int ); + void getRange( int id, int *, int * ); + +public: // private (: + enum { DefaultResizeMode = 3 }; + + void init(); + void recalc( bool update = FALSE ); + void doResize(); + void storeSizes(); + void getRange( int id, int *, int *, int *, int * ); + void addContribution( int, int *, int *, bool ); + int adjustPos( int, int, int *, int *, int *, int * ); + bool collapsible( QSplitterLayoutStruct * ); + void processChildEvents(); + QSplitterLayoutStruct *findWidget( QWidget * ); + QSplitterLayoutStruct *addWidget( QWidget *, bool prepend = FALSE ); + void recalcId(); + void doMove( bool backwards, int pos, int id, int delta, bool upLeft, + bool mayCollapse ); + void setGeo( QWidget *w, int pos, int size, bool splitterMoved ); + int findWidgetJustBeforeOrJustAfter( int id, int delta, int &collapsibleSize ); + void updateHandles(); + + inline QCOORD pick( const QPoint &p ) const + { return orient == Horizontal ? p.x() : p.y(); } + inline QCOORD pick( const QSize &s ) const + { return orient == Horizontal ? s.width() : s.height(); } + + inline QCOORD trans( const QPoint &p ) const + { return orient == Vertical ? p.x() : p.y(); } + inline QCOORD trans( const QSize &s ) const + { return orient == Vertical ? s.width() : s.height(); } + + QSplitterPrivate *d; + + Orientation orient; + friend class QSplitterHandle; + +#ifndef QT_NO_TEXTSTREAM +// moc doesn't like these. +// friend Q_EXPORT QTextStream& operator<<( QTextStream&, const QSplitter& ); +// friend Q_EXPORT QTextStream& operator>>( QTextStream&, QSplitter& ); +#endif + +public: +#if defined(Q_DISABLE_COPY) + QSplitter( const QSplitter & ); + QSplitter& operator=( const QSplitter & ); +#endif +}; + +#ifndef QT_NO_TEXTSTREAM +Q_EXPORT QTextStream& operator<<( QTextStream&, const QSplitter& ); +Q_EXPORT QTextStream& operator>>( QTextStream&, QSplitter& ); +#endif + +class QSplitterHandle : public QWidget +{ + Q_OBJECT +public: + QSplitterHandle( Orientation o, + QSplitter *parent, const char* name=0 ); + void setOrientation( Orientation o ); + Orientation orientation() const { return orient; } + + bool opaque() const { return s->opaqueResize(); } + + QSize sizeHint() const; + + int id() const { return myId; } // d->list.at(id())->wid == this + void setId( int i ) { myId = i; } + +protected: + void paintEvent( QPaintEvent * ); + void mouseMoveEvent( QMouseEvent * ); + void mousePressEvent( QMouseEvent * ); + void mouseReleaseEvent( QMouseEvent * ); + +public: // private (: + Orientation orient; + bool opaq; + int myId; + + QSplitter *s; +}; + +const uint Default = 2; + +class QSplitterLayoutStruct : public Qt +{ +public: + QCOORD sizer; + uint isHandle : 1; + uint collapsible : 2; + uint resizeMode : 2; + QWidget *wid; + + QSplitterLayoutStruct() + : sizer( -1 ), collapsible( Default ) { } + QCOORD getSizer( Orientation orient ); +}; + +#endif // QT_NO_SPLITTER + +#endif // QSPLITTER_H diff --git a/kompare/komparepart/kompareconnectwidget.cpp b/kompare/komparepart/kompareconnectwidget.cpp new file mode 100644 index 00000000..eed8e99c --- /dev/null +++ b/kompare/komparepart/kompareconnectwidget.cpp @@ -0,0 +1,285 @@ +/*************************************************************************** + kompareconnectwidget.cpp - description + ------------------- + begin : Tue Jun 26 2001 + copyright : (C) 2001-2003 John Firebaugh + (C) 2001-2004 Otto Bruggeman + (C) 2004 Jeff Snyder + email : jfirebaugh@kde.org + otto.bruggeman@home.nl + jeff@caffeinated.me.uk + ***************************************************************************/ + +/*************************************************************************** + * * + * 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 <qapplication.h> +#include <qpainter.h> +#include <qpixmap.h> +#include <qstyle.h> +#include <qtimer.h> + +#include <kdebug.h> + +#include "viewsettings.h" +#include "komparemodellist.h" +#include "komparelistview.h" +#include "komparesplitter.h" + +#include "kompareconnectwidget.h" + +using namespace Diff2; + +KompareConnectWidgetFrame::KompareConnectWidgetFrame( KompareListView* left, + KompareListView* right, + ViewSettings* settings, + KompareSplitter* parent, + const char* name ) : + QSplitterHandle(Horizontal, (QSplitter *)parent, name), + m_wid ( left, right, settings, this, name ), + m_label ( "", this ), + m_layout ( this ) +{ + setSizePolicy ( QSizePolicy(QSizePolicy::Fixed, QSizePolicy::Ignored) ); + m_wid.setSizePolicy ( QSizePolicy(QSizePolicy::Ignored, QSizePolicy::Ignored) ); + m_label.setSizePolicy ( QSizePolicy(QSizePolicy::Ignored, QSizePolicy::Fixed) ); + m_label.setMargin(3); + QFrame* bottomLine = new QFrame(this); + bottomLine->setFrameShape(QFrame::HLine); + bottomLine->setFrameShadow ( QFrame::Plain ); + bottomLine->setSizePolicy ( QSizePolicy(QSizePolicy::Ignored, QSizePolicy::Fixed) ); + bottomLine->setFixedHeight(1); + m_layout.setSpacing(0); + m_layout.setMargin(0); + m_layout.addWidget(&m_label); + m_layout.addWidget(bottomLine); + m_layout.addWidget(&m_wid); +} + +KompareConnectWidgetFrame::~KompareConnectWidgetFrame() +{ +} + +QSize KompareConnectWidgetFrame::sizeHint() const +{ + return QSize(50, style().pixelMetric( QStyle::PM_ScrollBarExtent ) ); +} + +static int kMouseOffset; + +void KompareConnectWidgetFrame::mouseMoveEvent( QMouseEvent *e ) +{ + if ( !(e->state()&LeftButton) ) + return; + + QCOORD pos = s->pick( parentWidget()->mapFromGlobal(e->globalPos()) ) + - kMouseOffset; + + ((KompareSplitter*)s)->moveSplitter( pos, id() ); +} + +void KompareConnectWidgetFrame::mousePressEvent( QMouseEvent *e ) +{ + if ( e->button() == LeftButton ) + kMouseOffset = s->pick( e->pos() ); + QSplitterHandle::mousePressEvent(e); +} + +void KompareConnectWidgetFrame::mouseReleaseEvent( QMouseEvent *e ) +{ + if ( !opaque() && e->button() == LeftButton ) { + QCOORD pos = s->pick( parentWidget()->mapFromGlobal(e->globalPos()) ) + - kMouseOffset; + ((KompareSplitter*)s)->moveSplitter( pos, id() ); + } +} + +KompareConnectWidget::KompareConnectWidget( KompareListView* left, KompareListView* right, + ViewSettings* settings, QWidget* parent, const char* name ) + : QWidget(parent, name), + m_settings( settings ), + m_leftView( left ), + m_rightView( right ), + m_selectedModel( 0 ), + m_selectedDifference( 0 ) +{ +// connect( m_settings, SIGNAL( settingsChanged() ), this, SLOT( slotDelayedRepaint() ) ); + setBackgroundMode( NoBackground ); + setSizePolicy( QSizePolicy( QSizePolicy::Fixed, QSizePolicy::Minimum ) ); + setFocusProxy( parent->parentWidget() ); +} + +KompareConnectWidget::~KompareConnectWidget() +{ +} + +void KompareConnectWidget::slotSetSelection( const DiffModel* model, const Difference* diff ) +{ + if( m_selectedModel == model && m_selectedDifference == diff ) + return; + + if ( m_selectedModel == model && m_selectedDifference != diff ) + { + m_selectedDifference = diff; + slotDelayedRepaint(); + return; + } + + m_selectedModel = model; + m_selectedDifference = diff; + + slotDelayedRepaint(); +} + +void KompareConnectWidget::slotDelayedRepaint() +{ + QTimer::singleShot( 0, this, SLOT( repaint() ) ); +} + +void KompareConnectWidget::slotSetSelection( const Difference* diff ) +{ + if ( m_selectedDifference == diff ) + return; + + m_selectedDifference = diff; + + slotDelayedRepaint(); +} + +void KompareConnectWidget::paintEvent( QPaintEvent* /* e */ ) +{ +// kdDebug(8106) << "KompareConnectWidget::paintEvent()" << endl; + + QPixmap pixbuf(size()); + QPainter paint(&pixbuf, this); + QPainter* p = &paint; + + p->fillRect( 0, 0, pixbuf.width(), pixbuf.height(), white.dark(110) ); + + if ( m_selectedModel ) + { + int firstL = m_leftView->firstVisibleDifference(); + int firstR = m_rightView->firstVisibleDifference(); + int lastL = m_leftView->lastVisibleDifference(); + int lastR = m_rightView->lastVisibleDifference(); + + int first = firstL < 0 ? firstR : QMIN( firstL, firstR ); + int last = lastL < 0 ? lastR : QMAX( lastL, lastR ); + +// kdDebug(8106) << " left: " << firstL << " - " << lastL << endl; +// kdDebug(8106) << " right: " << firstR << " - " << lastR << endl; +// kdDebug(8106) << " drawing: " << first << " - " << last << endl; + if ( first >= 0 && last >= 0 && first <= last ) + { + const DifferenceList* differences = const_cast<DiffModel*>(m_selectedModel)->differences(); + DifferenceListConstIterator diffIt = differences->at( first ); + DifferenceListConstIterator dEnd = differences->at( last + 1 ); + + QRect leftRect, rightRect; + + for ( int i = first; i <= last; ++diffIt, ++i ) + { + Difference* diff = *diffIt; + bool selected = ( diff == m_selectedDifference ); + + if ( QApplication::reverseLayout() ) + { + leftRect = m_rightView->itemRect( i ); + rightRect = m_leftView->itemRect( i ); + } + else + { + leftRect = m_leftView->itemRect( i ); + rightRect = m_rightView->itemRect( i ); + } + + int tl = leftRect.top(); + int tr = rightRect.top(); + int bl = leftRect.bottom(); + int br = rightRect.bottom(); + + // Bah, stupid 16-bit signed shorts in that crappy X stuff... + tl = tl >= -32768 ? tl : -32768; + tr = tr >= -32768 ? tr : -32768; + bl = bl <= 32767 ? bl : 32767; + br = br <= 32767 ? br : 32767; + +// kdDebug(8106) << "drawing: " << tl << " " << tr << " " << bl << " " << br << endl; + QPointArray topBezier = makeTopBezier( tl, tr ); + QPointArray bottomBezier = makeBottomBezier( bl, br ); + + QColor color = m_settings->colorForDifferenceType( diff->type(), selected, diff->applied() ).dark(110); + p->setPen( color ); + p->setBrush( color ); + p->drawPolygon ( makeConnectPoly( topBezier, bottomBezier ) ); + + if ( selected ) + { + p->setPen( color.dark(135) ); + p->drawPolyline( topBezier ); + p->drawPolyline( bottomBezier ); + } + } + } + } + + p->flush(); + bitBlt(this, 0, 0, &pixbuf); +} + +QPointArray KompareConnectWidget::makeTopBezier( int tl, int tr ) +{ + int l = 0; + int r = width(); + int o = (int)((double)r*0.4); // 40% of width + QPointArray controlPoints; + + if ( tl != tr ) + { + controlPoints.setPoints( 4, l,tl, o,tl, r-o,tr, r,tr ); + return controlPoints.cubicBezier(); + } + else + { + controlPoints.setPoints( 2, l,tl, r,tr ); + return controlPoints; + } +} + +QPointArray KompareConnectWidget::makeBottomBezier( int bl, int br ) +{ + int l = 0; + int r = width(); + int o = (int)((double)r*0.4); // 40% of width + QPointArray controlPoints; + + if ( bl != br ) + { + controlPoints.setPoints( 4, r,br, r-o,br, o,bl, l,bl ); + return controlPoints.cubicBezier(); + } + else + { + controlPoints.setPoints( 2, r,br, l,bl ); + return controlPoints; + } +} + +QPointArray KompareConnectWidget::makeConnectPoly( const QPointArray& topBezier, const QPointArray& bottomBezier ) +{ + QPointArray poly( topBezier.size() + bottomBezier.size() ); + for( uint i = 0; i < topBezier.size(); i++ ) + poly.setPoint( i, topBezier.point( i ) ); + for( uint i = 0; i < bottomBezier.size(); i++ ) + poly.setPoint( i + topBezier.size(), bottomBezier.point( i ) ); + + return poly; +} + +#include "kompareconnectwidget.moc" diff --git a/kompare/komparepart/kompareconnectwidget.h b/kompare/komparepart/kompareconnectwidget.h new file mode 100644 index 00000000..96160c97 --- /dev/null +++ b/kompare/komparepart/kompareconnectwidget.h @@ -0,0 +1,95 @@ +/*************************************************************************** + kompareconnectwidget.h - description + ------------------- + begin : Tue Jun 26 2001 + copyright : (C) 2001-2003 John Firebaugh + (C) 2001-2004 Otto Bruggeman + (C) 2004 Jeff Snyder + email : jfirebaugh@kde.org + otto.bruggeman@home.nl + jeff@caffeinated.me.uk + ***************************************************************************/ + +/*************************************************************************** + * * + * 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 "kompare_qsplitter.h" +#include <qwidget.h> + +namespace Diff2 { +class DiffModel; +} +class ViewSettings; +class KompareListView; +class KompareSplitter; + +class KompareConnectWidget : public QWidget +{ + Q_OBJECT + +public: + KompareConnectWidget( KompareListView* left, KompareListView* right, + 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 ); + QPointArray makeTopBezier( int tl, int tr ); + QPointArray makeBottomBezier( int bl, int br ); + QPointArray makeConnectPoly( const QPointArray& topBezier, const QPointArray& bottomBezier ); + +private: + ViewSettings* m_settings; + + KompareListView* m_leftView; + KompareListView* m_rightView; + + const Diff2::DiffModel* m_selectedModel; + const Diff2::Difference* m_selectedDifference; +}; + +class KompareConnectWidgetFrame : public QSplitterHandle +{ + Q_OBJECT +public: + KompareConnectWidgetFrame( KompareListView* left, KompareListView* right, + 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 */ ) { } + + void mouseMoveEvent( QMouseEvent * ); + void mousePressEvent( QMouseEvent * ); + void mouseReleaseEvent( QMouseEvent * ); + +private: + KompareConnectWidget m_wid; + QLabel m_label; + QVBoxLayout m_layout; +}; + +#endif diff --git a/kompare/komparepart/komparelistview.cpp b/kompare/komparepart/komparelistview.cpp new file mode 100644 index 00000000..b86bdef9 --- /dev/null +++ b/kompare/komparepart/komparelistview.cpp @@ -0,0 +1,783 @@ +/*************************************************************************** + komparelistview.h - description + ------------------- + begin : Sun Mar 4 2001 + copyright : (C) 2001-2004 Otto Bruggeman + (C) 2001-2003 John Firebaugh + (C) 2004 Jeff Snyder + email : otto.bruggeman@home.nl + jfirebaugh@kde.org + jeff@caffeinated.me.uk +****************************************************************************/ + +/*************************************************************************** +** +** 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 <qheader.h> +#include <qpainter.h> +#include <qregexp.h> +#include <qtimer.h> + +#include <kdebug.h> +#include <kglobal.h> +#include <kglobalsettings.h> + +#include "diffmodel.h" +#include "diffhunk.h" +#include "difference.h" +#include "viewsettings.h" +#include "komparemodellist.h" +#include "komparesplitter.h" + +#include "komparelistview.h" + +#define COL_LINE_NO 0 +#define COL_MAIN 1 + +#define BLANK_LINE_HEIGHT 3 +#define HUNK_LINE_HEIGHT 5 + +using namespace Diff2; + +KompareListViewFrame::KompareListViewFrame( bool isSource, + ViewSettings* settings, + KompareSplitter* parent, + const char* name ): + QFrame ( parent, name ), + 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 ); + } +} + +KompareListView::KompareListView( bool isSource, + ViewSettings* settings, + QWidget* parent, const char* name ) : + KListView( parent, name ), + m_isSource( isSource ), + m_settings( settings ), + m_scrollId( -1 ), + m_selectedModel( 0 ), + m_selectedDifference( 0 ) +{ + header()->hide(); + addColumn( "Line Number", 0 ); + addColumn( "Main" ); + addColumn( "Blank" ); + setColumnAlignment( COL_LINE_NO, AlignRight ); + setAllColumnsShowFocus( true ); + setRootIsDecorated( false ); + setSorting( -1 ); + setItemMargin( 3 ); + setTreeStepSize( 0 ); + setColumnWidthMode( COL_LINE_NO, Maximum ); + setColumnWidthMode( COL_MAIN, Maximum ); + setResizeMode( LastColumn ); + setFrameStyle( QFrame::NoFrame ); + setVScrollBarMode( QScrollView::AlwaysOff ); + setHScrollBarMode( QScrollView::AlwaysOff ); + setFocusPolicy( QWidget::NoFocus ); + setFont( m_settings->m_font ); + setSpaces( m_settings->m_tabToNumberOfSpaces ); + setFocusProxy( parent->parentWidget() ); +} + +KompareListView::~KompareListView() +{ +} + +KompareListViewItem* KompareListView::itemAtIndex( int i ) +{ + return m_items[ i ]; +} + +int KompareListView::firstVisibleDifference() +{ + QListViewItem* item = itemAt( QPoint( 0, 0 ) ); + + if( item == 0 ) + { + kdDebug(8104) << "no item at viewport coordinates (0,0)" << endl; + } + + while( item ) { + KompareListViewLineItem* lineItem = dynamic_cast<KompareListViewLineItem*>(item); + if( lineItem && lineItem->diffItemParent()->difference()->type() != Difference::Unchanged ) + break; + item = item->itemBelow(); + } + + if( item ) + return m_items.findIndex( ((KompareListViewLineItem*)item)->diffItemParent() ); + + return -1; +} + +int KompareListView::lastVisibleDifference() +{ + QListViewItem* item = itemAt( QPoint( 0, visibleHeight() - 1 ) ); + + if( item == 0 ) + { + kdDebug(8104) << "no item at viewport coordinates (0," << visibleHeight() - 1 << ")" << endl; + item = lastItem(); + } + + while( item ) { + KompareListViewLineItem* lineItem = dynamic_cast<KompareListViewLineItem*>(item); + if( lineItem && lineItem->diffItemParent()->difference()->type() != Difference::Unchanged ) + break; + item = item->itemAbove(); + } + + if( item ) + return m_items.findIndex( ((KompareListViewLineItem*)item)->diffItemParent() ); + + return -1; +} + +QRect KompareListView::itemRect( int i ) +{ + QListViewItem* item = itemAtIndex( i ); + int x = 0; + int y = itemPos( item ); + int vx, vy; + contentsToViewport( x, y, vx, vy ); + return QRect( vx, vy, 0, item->totalHeight() ); +} + +int KompareListView::minScrollId() +{ + return visibleHeight() / 2; +} + +int KompareListView::maxScrollId() +{ + KompareListViewItem* item = (KompareListViewItem*)firstChild(); + if(!item) return 0; + while( item && item->nextSibling() ) { + item = (KompareListViewItem*)item->nextSibling(); + } + int maxId = item->scrollId() + item->maxHeight() - minScrollId(); + kdDebug(8104) << "Max ID = " << maxId << endl; + return maxId; +} + +int KompareListView::contentsWidth() +{ + return ( columnWidth(COL_LINE_NO) + columnWidth(COL_MAIN) ); +} + +void KompareListView::setXOffset( int x ) +{ + kdDebug(8104) << "SetXOffset : Scroll to x position: " << x << endl; + setContentsPos( x, contentsY() ); +} + +void KompareListView::scrollToId( int id ) +{ +// kdDebug(8104) << "ScrollToID : Scroll to id : " << id << endl; + KompareListViewItem* item = (KompareListViewItem*)firstChild(); + while( item && item->nextSibling() ) { + if( ((KompareListViewItem*)item->nextSibling())->scrollId() > id ) + break; + item = (KompareListViewItem*)item->nextSibling(); + } + + if( item ) { + int pos = item->itemPos(); + int itemId = item->scrollId(); + int height = item->totalHeight(); + double r = (double)( id - itemId ) / (double)item->maxHeight(); + int y = pos + (int)( r * (double)height ) - minScrollId(); +// kdDebug(8104) << "scrollToID: " << endl; +// kdDebug(8104) << " id = " << id << endl; +// kdDebug(8104) << " id after = " << ( item->nextSibling() ? QString::number( ((KompareListViewItem*)item->nextSibling())->scrollId() ) : "no such sibling..." ) << endl; +// kdDebug(8104) << " pos = " << pos << endl; +// kdDebug(8104) << " itemId = " << itemId << endl; +// kdDebug(8104) << " r = " << r << endl; +// kdDebug(8104) << " height = " << height << endl; +// kdDebug(8104) << " minID = " << minScrollId() << endl; +// kdDebug(8104) << " y = " << y << endl; +// kdDebug(8104) << "contentsHeight = " << contentsHeight() << endl; +// kdDebug(8104) << " c - y = " << contentsHeight() - y << endl; + setContentsPos( contentsX(), 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 ) +{ + kdDebug(8104) << "KompareListView::setSelectedDifference(" << diff << ", " << scroll << ")" << endl; + + // 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 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[ (void*)diff ]; + if( !item ) { + kdDebug(8104) << "KompareListView::slotSetSelection(): couldn't find our selection!" << endl; + return; + } + + // why does this not happen when the user clicks on a diff? see the comment above. + if( scroll ) + scrollToId(item->scrollId()); + setSelected( item, true ); +} + +void KompareListView::slotSetSelection( const Difference* diff ) +{ + kdDebug(8104) << "KompareListView::slotSetSelection( const Difference* diff )" << endl; + + setSelectedDifference( diff, true ); +} + +void KompareListView::slotSetSelection( const DiffModel* model, const Difference* diff ) +{ + kdDebug(8104) << "KompareListView::slotSetSelection( const DiffModel* model, const Difference* diff )" << endl; + + if( m_selectedModel && m_selectedModel == model ) { + slotSetSelection( diff ); + return; + } + + clear(); + m_items.clear(); + m_itemDict.clear(); + m_selectedModel = model; + + m_itemDict.resize(model->differenceCount()); + + DiffHunkListConstIterator hunkIt = model->hunks()->begin(); + DiffHunkListConstIterator hEnd = model->hunks()->end(); + + KompareListViewItem* item = 0; + Difference* tmpdiff = 0; + DiffHunk* hunk = 0; + + + for ( ; hunkIt != hEnd; ++hunkIt ) + { + hunk = *hunkIt; + + if( item ) + item = new KompareListViewHunkItem( this, item, hunk, model->isBlended() ); + else + item = new KompareListViewHunkItem( this, hunk, model->isBlended() ); + + DifferenceListConstIterator diffIt = hunk->differences().begin(); + DifferenceListConstIterator dEnd = hunk->differences().end(); + + for ( ; diffIt != dEnd; ++diffIt ) + { + tmpdiff = *diffIt; + + item = new KompareListViewDiffItem( this, item, tmpdiff ); + + int type = tmpdiff->type(); + + if ( type != Difference::Unchanged ) + { + m_items.append( (KompareListViewDiffItem*)item ); + m_itemDict.insert( tmpdiff, (KompareListViewDiffItem*)item ); + } + } + } + + slotSetSelection( diff ); +} + +void KompareListView::contentsMousePressEvent( QMouseEvent* e ) +{ + QPoint vp = contentsToViewport( e->pos() ); + KompareListViewLineItem* lineItem = dynamic_cast<KompareListViewLineItem*>( itemAt( vp ) ); + if( !lineItem ) + return; + KompareListViewDiffItem* diffItem = lineItem->diffItemParent(); + if( diffItem->difference()->type() != Difference::Unchanged ) { + emit differenceClicked( diffItem->difference() ); + } +} + +void KompareListView::contentsMouseDoubleClickEvent( QMouseEvent* e ) +{ + QPoint vp = contentsToViewport( e->pos() ); + KompareListViewLineItem* lineItem = dynamic_cast<KompareListViewLineItem*>( itemAt( vp ) ); + if ( !lineItem ) + return; + KompareListViewDiffItem* diffItem = lineItem->diffItemParent(); + if ( diffItem->difference()->type() != Difference::Unchanged ) { + // FIXME: make a new signal that does both + emit differenceClicked( diffItem->difference() ); + emit applyDifference( !diffItem->difference()->applied() ); + } +} + +void KompareListView::slotApplyDifference( bool apply ) +{ + m_itemDict[ (void*)m_selectedDifference ]->applyDifference( apply ); +} + +void KompareListView::slotApplyAllDifferences( bool apply ) +{ + QPtrDictIterator<KompareListViewDiffItem> it ( m_itemDict ); + for( ; it.current(); ++it ) + it.current()->applyDifference( apply ); + repaint(); +} + +void KompareListView::slotApplyDifference( const Difference* diff, bool apply ) +{ + m_itemDict[ (void*)diff ]->applyDifference( apply ); +} + +void KompareListView::setSpaces( int spaces ) +{ + m_spaces.truncate( 0 ); + kdDebug( 8104 ) << "tabToNumberOfSpaces: " << spaces << endl; + for ( int i = 0; i < spaces; i++ ) + m_spaces += " "; + + triggerUpdate(); +} + +void KompareListView::wheelEvent( QWheelEvent* e ) +{ + e->ignore(); // we want the parent to catch wheel events +} + +void KompareListView::resizeEvent( QResizeEvent* e ) +{ + KListView::resizeEvent(e); + emit resized(); + kdDebug() << "resizeEvent " << endl; +} + +KompareListViewItem::KompareListViewItem( KompareListView* parent ) + : QListViewItem( parent ), + m_scrollId( 0 ) +{ +// kdDebug(8104) << "Created KompareListViewItem with scroll id " << m_scrollId << endl; +} + +KompareListViewItem::KompareListViewItem( KompareListView* parent, KompareListViewItem* after ) + : QListViewItem( parent, after ), + m_scrollId( after->scrollId() + after->maxHeight() ) +{ +// kdDebug(8104) << "Created KompareListViewItem with scroll id " << m_scrollId << endl; +} + +KompareListViewItem::KompareListViewItem( KompareListViewItem* parent ) + : QListViewItem( parent ), + m_scrollId( 0 ) +{ +} + +KompareListViewItem::KompareListViewItem( KompareListViewItem* parent, KompareListViewItem* /*after*/ ) + : QListViewItem( parent ), + m_scrollId( 0 ) +{ +} + +KompareListView* KompareListViewItem::kompareListView() const +{ + return (KompareListView*)listView(); +} + +void KompareListViewItem::paintFocus( QPainter* /* p */, const QColorGroup& /* cg */, const QRect& /* r */ ) +{ + // Don't paint anything +} + +KompareListViewDiffItem::KompareListViewDiffItem( KompareListView* parent, Difference* difference ) + : KompareListViewItem( parent ), + m_difference( difference ), + m_sourceItem( 0L ), + m_destItem( 0L ) +{ + init(); +} + +KompareListViewDiffItem::KompareListViewDiffItem( KompareListView* parent, KompareListViewItem* after, Difference* difference ) + : KompareListViewItem( parent, after ), + m_difference( difference ), + m_sourceItem( 0L ), + m_destItem( 0L ) +{ + init(); +} + +void KompareListViewDiffItem::init() +{ + setExpandable( true ); + setOpen( true ); + m_destItem = new KompareListViewLineContainerItem( this, false ); + m_sourceItem = new KompareListViewLineContainerItem( this, true ); + setVisibility(); +} + +void KompareListViewDiffItem::setup() +{ + KompareListViewItem::setup(); + setHeight( 0 ); +} + +void KompareListViewDiffItem::setVisibility() +{ + m_sourceItem->setVisible( kompareListView()->isSource() || m_difference->applied() ); + m_destItem->setVisible( !m_sourceItem->isVisible() ); +} + +void KompareListViewDiffItem::applyDifference( bool apply ) +{ + kdDebug(8104) << "KompareListViewDiffItem::applyDifference( " << apply << " )" << endl; + setVisibility(); + setup(); + repaint(); +} + +int KompareListViewDiffItem::maxHeight() +{ + int lines = QMAX( m_difference->sourceLineCount(), m_difference->destinationLineCount() ); + if( lines == 0 ) + return BLANK_LINE_HEIGHT; + else + return lines * listView()->fontMetrics().lineSpacing(); +} + +void KompareListViewDiffItem::setSelected( bool b ) +{ + kdDebug(8104) << "KompareListViewDiffItem::setSelected( " << b << " )" << endl; + KompareListViewItem::setSelected( b ); + QListViewItem* item = m_sourceItem->isVisible() ? + m_sourceItem->firstChild() : + m_destItem->firstChild(); + while( item && item->isVisible() ) { + item->repaint(); + item = item->nextSibling(); + } +} + +KompareListViewLineContainerItem::KompareListViewLineContainerItem( KompareListViewDiffItem* parent, bool isSource ) + : KompareListViewItem( parent ), + m_isSource( isSource ) +{ +// kdDebug(8104) << "isSource ? " << (isSource ? " Yes!" : " No!") << endl; + setExpandable( true ); + setOpen( true ); + + int lines = lineCount(); + int line = lineNumber() + lines - 1; +// kdDebug(8104) << "LineNumber : " << lineNumber() << endl; + if( lines == 0 ) { + new KompareListViewBlankLineItem( this ); + return; + } + + for( int i = lines - 1; i >= 0; i--, line-- ) { + new KompareListViewLineItem( this, line, lineAt( i ) ); + } +} + +void KompareListViewLineContainerItem::setup() +{ + KompareListViewItem::setup(); + setHeight( 0 ); +} + +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 ) +{ + setText( COL_LINE_NO, QString::number( line ) ); + setText( COL_MAIN, text->string() ); + m_text = text; +} + +void KompareListViewLineItem::setup() +{ + KompareListViewItem::setup(); + setHeight( listView()->fontMetrics().lineSpacing() ); +} + +void KompareListViewLineItem::paintCell( QPainter * p, const QColorGroup & cg, int column, int width, int align ) +{ + QColor bg = cg.base(); + p->fillRect( 0, 0, width, height(), bg ); + if ( diffItemParent()->difference()->type() == Difference::Unchanged ) + { + if ( column == COL_LINE_NO ) + { + bg = cg.background(); + p->fillRect( 0, 0, width, height(), bg ); + } + } + else + { + bg = kompareListView()->settings()->colorForDifferenceType( + diffItemParent()->difference()->type(), + diffItemParent()->isSelected(), + diffItemParent()->difference()->applied() ); + if ( column != COL_MAIN ) + p->fillRect( 0, 0, width, height(), bg ); + } + + p->setPen( cg.foreground() ); + + paintText( p, bg, column, width, align ); + + if ( diffItemParent()->isSelected() ) + { + p->setPen( bg.dark(135) ); + if ( this == parent()->firstChild() ) + p->drawLine( 0, 0, width, 0 ); + if ( nextSibling() == 0 ) + p->drawLine( 0, height() - 1, width, height() - 1 ); + } +} + +void KompareListViewLineItem::paintText( QPainter* p, const QColor& bg, int column, int width, int align ) +{ + if ( column == COL_MAIN ) + { + QString textChunk; + int offset = listView()->itemMargin(); + unsigned int prevValue = 0; + int chunkWidth; + QBrush changeBrush( bg, Dense3Pattern ); + QBrush normalBrush( bg, SolidPattern ); + QBrush brush; + + if ( m_text->string().isEmpty() ) + { + p->fillRect( 0, 0, width, height(), normalBrush ); + return; + } + + p->fillRect( 0, 0, offset, height(), 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 ); +// kdDebug(8104) << "TextChunk = \"" << textChunk << "\"" << endl; +// kdDebug(8104) << "c->offset() = " << c->offset() << endl; +// kdDebug(8104) << "prevValue = " << prevValue << endl; + textChunk.replace( QChar('\t'), kompareListView()->spaces() ); + 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, height(), brush ); + p->drawText( offset, 0, + chunkWidth, height(), + align, textChunk ); + offset += chunkWidth; + } + } + if ( prevValue < m_text->string().length() ) + { + // Still have to draw some string without changes + textChunk = m_text->string().mid( prevValue, kMax( ( unsigned int )1, m_text->string().length() - prevValue ) ); + textChunk.replace( QChar('\t'), kompareListView()->spaces() ); +// kdDebug(8104) << "TextChunk = \"" << textChunk << "\"" << endl; + QFont font( p->font() ); + font.setBold( false ); + p->setFont( font ); + chunkWidth = p->fontMetrics().width( textChunk ); + p->fillRect( offset, 0, chunkWidth, height(), normalBrush ); + p->drawText( offset, 0, + chunkWidth, height(), + align, textChunk ); + offset += chunkWidth; + } + p->fillRect( offset, 0, width - offset, height(), normalBrush ); + } + else + { + p->fillRect( 0, 0, width, height(), bg ); + p->drawText( listView()->itemMargin(), 0, + width - listView()->itemMargin(), height(), + align, text( column ) ); + } +} + +KompareListViewDiffItem* KompareListViewLineItem::diffItemParent() const +{ + KompareListViewLineContainerItem* p = (KompareListViewLineContainerItem*)parent(); + return p->diffItemParent(); +} + +KompareListViewBlankLineItem::KompareListViewBlankLineItem( KompareListViewLineContainerItem* parent ) + : KompareListViewLineItem( parent, 0, new DifferenceString() ) +{ +} + +void KompareListViewBlankLineItem::setup() +{ + KompareListViewLineItem::setup(); + setHeight( BLANK_LINE_HEIGHT ); +} + +void KompareListViewBlankLineItem::paintText( QPainter* p, const QColor& bg, int column, int width, int ) +{ + if ( column == COL_MAIN ) + { + QBrush normalBrush( bg, SolidPattern ); + p->fillRect( 0, 0, width, height(), normalBrush ); + } +} + +KompareListViewHunkItem::KompareListViewHunkItem( KompareListView* parent, DiffHunk* hunk, bool zeroHeight ) + : KompareListViewItem( parent ), + m_zeroHeight( zeroHeight ), + m_hunk( hunk ) +{ + setSelectable( false ); +} + +KompareListViewHunkItem::KompareListViewHunkItem( KompareListView* parent, KompareListViewItem* after, DiffHunk* hunk, bool zeroHeight ) + : KompareListViewItem( parent, after ), + m_zeroHeight( zeroHeight ), + m_hunk( hunk ) +{ + setSelectable( false ); +} + +int KompareListViewHunkItem::maxHeight() +{ + if( m_zeroHeight ) { + return 0; + } else if( m_hunk->function().isEmpty() ) { + return HUNK_LINE_HEIGHT; + } else { + return listView()->fontMetrics().lineSpacing(); + } +} + +void KompareListViewHunkItem::setup() +{ + KompareListViewItem::setup(); + + setHeight( maxHeight() ); +} + +void KompareListViewHunkItem::paintCell( QPainter * p, const QColorGroup & cg, int column, int width, int align ) +{ + p->fillRect( 0, 0, width, height(), cg.mid() ); + if( column == COL_MAIN ) { + p->drawText( listView()->itemMargin(), 0, width - listView()->itemMargin(), height(), + align, m_hunk->function() ); + } +} + +#include "komparelistview.moc" diff --git a/kompare/komparepart/komparelistview.h b/kompare/komparepart/komparelistview.h new file mode 100644 index 00000000..26a6dacb --- /dev/null +++ b/kompare/komparepart/komparelistview.h @@ -0,0 +1,225 @@ +/*************************************************************************** + komparelistview.h - description + ------------------- + begin : Sun Mar 4 2001 + copyright : (C) 2001-2004 Otto Bruggeman + (C) 2001-2003 John Firebaugh + (C) 2004 Jeff Snyder + email : otto.bruggeman@home.nl + jfirebaugh@kde.org + jeff@caffeinated.me.uk +****************************************************************************/ + +/*************************************************************************** +** +** 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 KOMPARELISTVIEW_H +#define KOMPARELISTVIEW_H + +#include <qptrlist.h> +#include <qptrdict.h> +#include <qlabel.h> +#include <qlayout.h> + +#include <klistview.h> + +namespace Diff2 { +class DiffModel; +class DiffHunk; +class Difference; +class DifferenceString; +class KompareModelList; +} +class ViewSettings; +class KompareSplitter; +class KompareListView; +class KompareListViewItem; +class KompareListViewDiffItem; +class KompareListViewLineContainerItem; + +class KompareListView : public KListView +{ + Q_OBJECT + +public: + KompareListView( bool isSource, ViewSettings* settings, QWidget* parent, const char* name = 0 ); + virtual ~KompareListView(); + + KompareListViewItem* itemAtIndex( int i ); + int firstVisibleDifference(); + int lastVisibleDifference(); + QRect itemRect( int i ); + int minScrollId(); + int maxScrollId(); + int contentsWidth(); + + bool isSource() const { return m_isSource; }; + ViewSettings* settings() const { return m_settings; }; + + void setSelectedDifference( const Diff2::Difference* diff, bool scroll ); + + const QString& spaces() const { return m_spaces; }; + void setSpaces( int spaces ); + +public slots: + void slotSetSelection( const Diff2::DiffModel* model, const Diff2::Difference* diff ); + void slotSetSelection( const Diff2::Difference* diff ); + void setXOffset( int x ); + void scrollToId( int id ); + int scrollId(); + void slotApplyDifference( bool apply ); + void slotApplyAllDifferences( bool apply ); + void slotApplyDifference( const Diff2::Difference* diff, bool apply ); + +signals: + void differenceClicked( const Diff2::Difference* diff ); + void applyDifference( bool apply ); + void resized(); + +protected: + void wheelEvent( QWheelEvent* e ); + void resizeEvent( QResizeEvent* e ); + void contentsMousePressEvent ( QMouseEvent * e ); + void contentsMouseDoubleClickEvent ( QMouseEvent* ); + void contentsMouseReleaseEvent ( QMouseEvent * ) {}; + void contentsMouseMoveEvent ( QMouseEvent * ) {}; + +private: + QValueList<KompareListViewDiffItem*> m_items; + QPtrDict<KompareListViewDiffItem> m_itemDict; + bool m_isSource; + ViewSettings* m_settings; + int m_scrollId; + int m_maxMainWidth; + const Diff2::DiffModel* m_selectedModel; + const Diff2::Difference* m_selectedDifference; + QString m_spaces; +}; + +class KompareListViewFrame : public QFrame +{ + Q_OBJECT + +public: + KompareListViewFrame( bool isSource, ViewSettings* settings, KompareSplitter* parent, const char* name = 0 ); + virtual ~KompareListViewFrame() {}; + KompareListView* view() { return &m_view; }; + +public slots: + void slotSetModel( const Diff2::DiffModel* model ); + +private: + KompareListView m_view; + QLabel m_label; + QVBoxLayout m_layout; +}; + +class KompareListViewItem : public QListViewItem +{ +public: + KompareListViewItem( KompareListView* parent ); + KompareListViewItem( KompareListView* parent, KompareListViewItem* after ); + KompareListViewItem( KompareListViewItem* parent ); + KompareListViewItem( KompareListViewItem* parent, KompareListViewItem* after ); + + void paintFocus( QPainter* p, const QColorGroup& cg, const QRect& r ); + int scrollId() { return m_scrollId; }; + + virtual int maxHeight() = 0; + + KompareListView* kompareListView() const; + +private: + int m_scrollId; +}; + +class KompareListViewDiffItem : public KompareListViewItem +{ +public: + KompareListViewDiffItem( KompareListView* parent, Diff2::Difference* difference ); + KompareListViewDiffItem( KompareListView* parent, KompareListViewItem* after, Diff2::Difference* difference ); + + void setup(); + void setSelected( bool b ); + void applyDifference( bool apply ); + + Diff2::Difference* difference() { return m_difference; }; + + int maxHeight(); + +private: + void init(); + void setVisibility(); + + Diff2::Difference* m_difference; + KompareListViewLineContainerItem* m_sourceItem; + KompareListViewLineContainerItem* m_destItem; +}; + +class KompareListViewLineContainerItem : public KompareListViewItem +{ +public: + KompareListViewLineContainerItem( KompareListViewDiffItem* parent, bool isSource ); + + void setup(); + int maxHeight() { return 0; } + KompareListViewDiffItem* diffItemParent() const; + +private: + int lineCount() const; + int lineNumber() const; + Diff2::DifferenceString* lineAt( int i ) const; + + bool m_isSource; +}; + +class KompareListViewLineItem : public KompareListViewItem +{ +public: + KompareListViewLineItem( KompareListViewLineContainerItem* parent, int line, Diff2::DifferenceString* text ); + + virtual void setup(); + int maxHeight() { return 0; } + + virtual void paintCell( QPainter* p, const QColorGroup& cg, int column, int width, int align ); + virtual void paintText( QPainter* p, const QColor& bg, int column, int width, int align ); + + KompareListViewDiffItem* diffItemParent() const; + +private: + Diff2::DifferenceString* m_text; +}; + +class KompareListViewBlankLineItem : public KompareListViewLineItem +{ +public: + KompareListViewBlankLineItem( KompareListViewLineContainerItem* parent ); + + void setup(); + + void paintText( QPainter* p, const QColor& bg, int column, int width, int align ); +}; + +class KompareListViewHunkItem : public KompareListViewItem +{ +public: + KompareListViewHunkItem( KompareListView* parent, Diff2::DiffHunk* hunk, bool zeroHeight = false ); + KompareListViewHunkItem( KompareListView* parent, KompareListViewItem* after, Diff2::DiffHunk* hunk, bool zeroHeight= false ); + + void setup(); + void paintCell( QPainter* p, const QColorGroup& cg, int column, int width, int align ); + + int maxHeight(); + +private: + bool m_zeroHeight; + Diff2::DiffHunk* m_hunk; +}; + +#endif diff --git a/kompare/komparepart/komparepart.desktop b/kompare/komparepart/komparepart.desktop new file mode 100644 index 00000000..3d075d62 --- /dev/null +++ b/kompare/komparepart/komparepart.desktop @@ -0,0 +1,24 @@ +[Desktop Entry] +GenericComment=A part to graphically show the difference between 2 files +Name=KomparePart +Name[af]=K-vergelyk-deel +Name[de]=Einbettungsfähige Komponente von Kompare +Name[eo]=Komparo-parto +Name[he]=רכיב Kompare +Name[hi]=काम्पेयर-पार्ट +Name[lv]=SalīdzinātDaļu +Name[pl]=Moduł Kompare +Name[pt_BR]=Parte do Kompare +Name[ro]=Componentă Kompare +Name[ru]=Компонент утилиты сравнения файлов +Name[sv]=Kompare-del +Name[ta]=கோம்பெர் உறுப்பு +Name[tg]=Қисмати утилитҳои баробаркунии файлҳо +Name[th]=ส่วนเปรียบเทียบ +Name[zu]=Ingxenye yeKompare +MimeType=text/x-diff +ServiceTypes=Kompare/ViewPart,KParts/ReadWritePart,KParts/ReadOnlyPart +X-KDE-Library=libkomparepart +Type=Service +Icon=kompare +InitialPreference=10 diff --git a/kompare/komparepart/komparepartui.rc b/kompare/komparepart/komparepartui.rc new file mode 100644 index 00000000..c7140325 --- /dev/null +++ b/kompare/komparepart/komparepartui.rc @@ -0,0 +1,44 @@ +<!DOCTYPE kpartgui SYSTEM "kpartgui.dtd"> +<kpartgui name="kompare_part" version="5"> +<MenuBar> + <Menu name="file"><text>&File</text> + <Action name="file_save"/> + <Action name="file_save_all"/> + <Action name="file_save_as"/> + <Action name="file_save_diff"/> + <Separator/> + <Action name="file_swap"/> + <Action name="file_diffstats"/> + </Menu> + <Menu name="difference"><text>&Difference</text> + <Action name="difference_unapplyall"/> + <Action name="difference_unapply"/> + <Action name="difference_apply"/> + <Action name="difference_applyall"/> + <Separator/> + <Action name="difference_previousfile"/> + <Action name="difference_nextfile"/> + <Separator/> + <Action name="difference_previous"/> + <Action name="difference_next"/> + </Menu> + <Menu name="settings"><text>&Settings</text> + <Action name="options_configure"/> + </Menu> +</MenuBar> +<ToolBar name="mainToolBar"> + <Action name="file_save"/> + <Action name="file_save_all"/> + <Separator/> + <Action name="difference_previousfile"/> + <Action name="difference_nextfile"/> + <Separator/> + <Action name="difference_previous"/> + <Action name="difference_next"/> + <Separator/> + <Action name="difference_unapplyall"/> + <Action name="difference_unapply"/> + <Action name="difference_apply"/> + <Action name="difference_applyall"/> +</ToolBar> +</kpartgui> diff --git a/kompare/komparepart/kompareprefdlg.cpp b/kompare/komparepart/kompareprefdlg.cpp new file mode 100644 index 00000000..2d731af3 --- /dev/null +++ b/kompare/komparepart/kompareprefdlg.cpp @@ -0,0 +1,106 @@ +/*************************************************************************** + kompareprefdlg.cpp - description + ------------------- + begin : Sun Mar 4 2001 + copyright : (C) 2001-2003 by Otto Bruggeman + and John Firebaugh + email : otto.bruggeman@home.nl + jfirebaugh@kde.org +****************************************************************************/ + +/*************************************************************************** +** +** 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 <qvbox.h> + +#include <kdebug.h> +#include <kiconloader.h> +#include <klocale.h> + +#include "diffpage.h" +#include "viewpage.h" + +#include "kompareprefdlg.h" + +// implementation + +KomparePrefDlg::KomparePrefDlg( ViewSettings* viewSets, DiffSettings* diffSets ) : KDialogBase( IconList, i18n( "Preferences" ), Help|Default|Ok|Apply|Cancel, Ok, 0, 0, true, true ) +{ + // ok i need some stuff in that pref dlg... + setIconListAllVisible(true); + + QVBox* frame; + frame = addVBoxPage( i18n( "View" ), i18n( "View Settings" ), UserIcon( "diff_view" ) ); + m_viewPage = new ViewPage( frame ); + m_viewPage->setSettings( viewSets ); + + frame = addVBoxPage( i18n( "Diff" ), i18n( "Diff Settings" ), UserIcon( "diff_specific" ) ); + m_diffPage = new DiffPage( frame ); + m_diffPage->setSettings( diffSets ); + +// frame = addVBoxPage( i18n( "" ), i18n( "" ), UserIcon( "" ) ); + + adjustSize(); +} + +KomparePrefDlg::~KomparePrefDlg() +{ + +} + +/** No descriptions */ +void KomparePrefDlg::slotDefault() +{ + kdDebug(8103) << "SlotDefault called -> Settings should be restored to defaults..." << endl; + // restore all defaults in the options... + m_viewPage->setDefaults(); + m_diffPage->setDefaults(); +} + +/** No descriptions */ +void KomparePrefDlg::slotHelp() +{ + // show some help... + // figure out the current active page + // and give help for that page +} + +/** No descriptions */ +void KomparePrefDlg::slotApply() +{ + kdDebug(8103) << "SlotApply called -> Settings should be applied..." << endl; + // well apply the settings that are currently selected + m_viewPage->apply(); + m_diffPage->apply(); + + emit applyClicked(); +} + +/** No descriptions */ +void KomparePrefDlg::slotOk() +{ + kdDebug(8103) << "SlotOk called -> Settings should be applied..." << endl; + // Apply the settings that are currently selected + m_viewPage->apply(); + m_diffPage->apply(); + + KDialogBase::slotOk(); +} + +/** No descriptions */ +void KomparePrefDlg::slotCancel() +{ + // discard the current settings and use the present ones + m_viewPage->restore(); + m_diffPage->restore(); + + KDialogBase::slotCancel(); +} + +#include "kompareprefdlg.moc" diff --git a/kompare/komparepart/kompareprefdlg.h b/kompare/komparepart/kompareprefdlg.h new file mode 100644 index 00000000..e81da90c --- /dev/null +++ b/kompare/komparepart/kompareprefdlg.h @@ -0,0 +1,54 @@ +/*************************************************************************** + kompareprefdlg.h - description + ------------------- + begin : Sun Mar 4 2001 + copyright : (C) 2001-2003 by Otto Bruggeman + and John Firebaugh + email : otto.bruggeman@home.nl + jfirebaugh@kde.org +****************************************************************************/ + +/*************************************************************************** +** +** 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 KOMPAREPREFDLG_H +#define KOMPAREPREFDLG_H + +#include <kdialogbase.h> + +class DiffPage; +class DiffSettings; +class ViewPage; +class ViewSettings; + +class KomparePrefDlg : public KDialogBase +{ +Q_OBJECT +public: + KomparePrefDlg( ViewSettings*, DiffSettings* ); + ~KomparePrefDlg(); + +protected slots: + /** No descriptions */ + virtual void slotOk(); + /** No descriptions */ + virtual void slotApply(); + /** No descriptions */ + virtual void slotHelp(); + /** No descriptions */ + virtual void slotDefault(); + /** No descriptions */ + virtual void slotCancel(); + +private: + ViewPage* m_viewPage; + DiffPage* m_diffPage; +}; + +#endif diff --git a/kompare/komparepart/komparesaveoptionsbase.ui b/kompare/komparepart/komparesaveoptionsbase.ui new file mode 100644 index 00000000..4c49b018 --- /dev/null +++ b/kompare/komparepart/komparesaveoptionsbase.ui @@ -0,0 +1,336 @@ +<!DOCTYPE UI><UI version="3.0" stdsetdef="1"> +<class>KompareSaveOptionsBase</class> +<widget class="QWidget"> + <property name="name"> + <cstring>KompareSaveOptionsBase</cstring> + </property> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>558</width> + <height>399</height> + </rect> + </property> + <grid> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <property name="margin"> + <number>0</number> + </property> + <property name="spacing"> + <number>6</number> + </property> + <widget class="QGroupBox" row="1" column="0" rowspan="1" colspan="2"> + <property name="name"> + <cstring>GroupBox2</cstring> + </property> + <property name="sizePolicy"> + <sizepolicy> + <hsizetype>1</hsizetype> + <vsizetype>1</vsizetype> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="frameShape"> + <enum>Panel</enum> + </property> + <property name="title"> + <string>Run Diff In</string> + </property> + <hbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <property name="margin"> + <number>11</number> + </property> + <property name="spacing"> + <number>6</number> + </property> + <widget class="KURLRequester"> + <property name="name"> + <cstring>m_directoryRequester</cstring> + </property> + <property name="sizePolicy"> + <sizepolicy> + <hsizetype>7</hsizetype> + <vsizetype>5</vsizetype> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + </widget> + </hbox> + </widget> + <widget class="QGroupBox" row="2" column="0" rowspan="1" colspan="2"> + <property name="name"> + <cstring>m_CommandLineGB</cstring> + </property> + <property name="sizePolicy"> + <sizepolicy> + <hsizetype>3</hsizetype> + <vsizetype>3</vsizetype> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="frameShape"> + <enum>Panel</enum> + </property> + <property name="title"> + <string>Command Line</string> + </property> + <property name="alignment"> + <set>AlignVCenter|AlignLeft</set> + </property> + <property name="hAlign" stdset="0"> + </property> + <property name="vAlign" stdset="0"> + </property> + <hbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <property name="margin"> + <number>11</number> + </property> + <property name="spacing"> + <number>6</number> + </property> + <widget class="QLabel"> + <property name="name"> + <cstring>m_CommandLineLabel</cstring> + </property> + <property name="text"> + <string>cd dir && diff -udHprNa -- source destination</string> + </property> + </widget> + </hbox> + </widget> + <widget class="QButtonGroup" row="0" column="1"> + <property name="name"> + <cstring>m_OptionsGB</cstring> + </property> + <property name="title"> + <string>Options</string> + </property> + <vbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <property name="margin"> + <number>11</number> + </property> + <property name="spacing"> + <number>6</number> + </property> + <widget class="QCheckBox"> + <property name="name"> + <cstring>m_SmallerChangesCB</cstring> + </property> + <property name="text"> + <string>Look for smaller changes</string> + </property> + <property name="checked"> + <bool>true</bool> + </property> + </widget> + <widget class="QCheckBox"> + <property name="name"> + <cstring>m_LargeFilesCB</cstring> + </property> + <property name="text"> + <string>Optimize for large files</string> + </property> + <property name="checked"> + <bool>true</bool> + </property> + </widget> + <widget class="QCheckBox"> + <property name="name"> + <cstring>m_IgnoreCaseCB</cstring> + </property> + <property name="text"> + <string>Ignore changes in case</string> + </property> + </widget> + <widget class="QCheckBox"> + <property name="name"> + <cstring>m_ExpandTabsCB</cstring> + </property> + <property name="text"> + <string>Expand tabs to spaces</string> + </property> + </widget> + <widget class="QCheckBox"> + <property name="name"> + <cstring>m_IgnoreEmptyLinesCB</cstring> + </property> + <property name="text"> + <string>Ignore added or removed empty lines</string> + </property> + </widget> + <widget class="QCheckBox"> + <property name="name"> + <cstring>m_IgnoreWhiteSpaceCB</cstring> + </property> + <property name="text"> + <string>Ignore changes in whitespace</string> + </property> + </widget> + <widget class="QCheckBox"> + <property name="name"> + <cstring>m_FunctionNamesCB</cstring> + </property> + <property name="text"> + <string>Show function names</string> + </property> + <property name="checked"> + <bool>true</bool> + </property> + </widget> + <widget class="QCheckBox"> + <property name="name"> + <cstring>m_RecursiveCB</cstring> + </property> + <property name="text"> + <string>Compare folders recursively</string> + </property> + <property name="checked"> + <bool>true</bool> + </property> + </widget> + <widget class="QCheckBox"> + <property name="name"> + <cstring>m_NewFilesCB</cstring> + </property> + <property name="text"> + <string>Treat new files as empty</string> + </property> + <property name="checked"> + <bool>true</bool> + </property> + <property name="tristate"> + <bool>false</bool> + </property> + </widget> + </vbox> + </widget> + <widget class="QButtonGroup" row="0" column="0"> + <property name="name"> + <cstring>m_FormatBG</cstring> + </property> + <property name="title"> + <string>Format</string> + </property> + <vbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <property name="margin"> + <number>11</number> + </property> + <property name="spacing"> + <number>6</number> + </property> + <widget class="QRadioButton"> + <property name="name"> + <cstring>m_ContextRB</cstring> + </property> + <property name="text"> + <string>Context</string> + </property> + </widget> + <widget class="QRadioButton"> + <property name="name"> + <cstring>m_EdRB</cstring> + </property> + <property name="text"> + <string>Ed</string> + </property> + </widget> + <widget class="QRadioButton"> + <property name="name"> + <cstring>m_NormalRB</cstring> + </property> + <property name="text"> + <string>Normal</string> + </property> + </widget> + <widget class="QRadioButton"> + <property name="name"> + <cstring>m_RCSRB</cstring> + </property> + <property name="text"> + <string>RCS</string> + </property> + </widget> + <widget class="QRadioButton"> + <property name="name"> + <cstring>m_UnifiedRB</cstring> + </property> + <property name="text"> + <string>Unified</string> + </property> + <property name="checked"> + <bool>true</bool> + </property> + </widget> + <widget class="QRadioButton"> + <property name="name"> + <cstring>m_SideBySideRB</cstring> + </property> + <property name="text"> + <string>Side-by-side</string> + </property> + <property name="checked"> + <bool>false</bool> + </property> + </widget> + <widget class="QLayoutWidget"> + <property name="name"> + <cstring>m_ContextLinesLayout</cstring> + </property> + <hbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <property name="margin"> + <number>0</number> + </property> + <property name="spacing"> + <number>6</number> + </property> + <widget class="QLabel"> + <property name="name"> + <cstring>m_ContextLinesLabel</cstring> + </property> + <property name="text"> + <string>Number of context lines:</string> + </property> + </widget> + <widget class="QSpinBox"> + <property name="name"> + <cstring>m_ContextLinesSB</cstring> + </property> + <property name="enabled"> + <bool>true</bool> + </property> + <property name="maxValue"> + <number>65535</number> + </property> + <property name="value"> + <number>3</number> + </property> + </widget> + </hbox> + </widget> + </vbox> + </widget> + </grid> +</widget> +<layoutdefaults spacing="6" margin="11"/> +</UI> diff --git a/kompare/komparepart/komparesaveoptionswidget.cpp b/kompare/komparepart/komparesaveoptionswidget.cpp new file mode 100644 index 00000000..866ecc0d --- /dev/null +++ b/kompare/komparepart/komparesaveoptionswidget.cpp @@ -0,0 +1,215 @@ +/*************************************************************************** + komparesaveoptionswidget.cpp - description + ------------------- + begin : Sun Mar 4 2001 + copyright : (C) 2001-2003 by Otto Bruggeman + and John Firebaugh + email : otto.bruggeman@home.nl + jfirebaugh@kde.org +****************************************************************************/ + +/*************************************************************************** +** +** 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 <qbuttongroup.h> +#include <qcheckbox.h> +#include <qlabel.h> +#include <qradiobutton.h> +#include <qspinbox.h> + +#include <kdebug.h> +#include <kfiledialog.h> +#include <kurlrequester.h> + +#include "diffsettings.h" +#include "komparesaveoptionswidget.h" + +KompareSaveOptionsWidget::KompareSaveOptionsWidget( QString source, QString destination, + DiffSettings * settings, QWidget * parent ) + : KompareSaveOptionsBase( parent, "save options" ) + , m_source( source ) + , m_destination( destination ) +{ + m_settings = settings; + + m_directoryRequester->setMode( static_cast<KFile::Mode>( + KFile::ExistingOnly | KFile::Directory | KFile::LocalOnly ) ); + + KURL sourceURL; + KURL destinationURL; + sourceURL.setPath( source ); + destinationURL.setPath( destination ); + + // Find a common root. + KURL root( sourceURL ); + while( root.isValid() && !root.isParentOf( destinationURL ) ) { + root = root.upURL(); + } + + // If we found a common root, change to that directory and + // strip the common part from source and destination. + if( root.isValid() ) { + 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()) ); + + loadOptions(); +} + +KompareSaveOptionsWidget::~KompareSaveOptionsWidget() +{ + +} + +QString KompareSaveOptionsWidget::directory() const +{ + return KURL( m_directoryRequester->url() ).path(); +} + +void KompareSaveOptionsWidget::updateCommandLine() +{ + QString cmdLine = "diff"; + + QString options = ""; + + switch( static_cast<Kompare::Format>( m_FormatBG->id( m_FormatBG->selected() ) ) ) { + 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; + } + + cmdLine += " -- "; + cmdLine += constructRelativePath( m_directoryRequester->url(), m_source ); + cmdLine += " "; + cmdLine += constructRelativePath( m_directoryRequester->url(), 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->setButton ( m_settings->m_format ); + + 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<Kompare::Format>( m_FormatBG->id( m_FormatBG->selected() ) ); + +} + +#include "komparesaveoptionswidget.moc" diff --git a/kompare/komparepart/komparesaveoptionswidget.h b/kompare/komparepart/komparesaveoptionswidget.h new file mode 100644 index 00000000..6361ca77 --- /dev/null +++ b/kompare/komparepart/komparesaveoptionswidget.h @@ -0,0 +1,51 @@ +/*************************************************************************** + komparesaveoptionswidget.h - description + ------------------- + begin : Sun Mar 4 2001 + copyright : (C) 2001-2003 by Otto Bruggeman + and John Firebaugh + email : otto.bruggeman@home.nl + jfirebaugh@kde.org +****************************************************************************/ + +/*************************************************************************** +** +** 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 <kurl.h> + +#include "komparesaveoptionsbase.h" +#include "kompare.h" + +class DiffSettings; + +class KompareSaveOptionsWidget : public KompareSaveOptionsBase, public KompareFunctions +{ +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; +}; + +#endif diff --git a/kompare/komparepart/komparesplitter.cpp b/kompare/komparepart/komparesplitter.cpp new file mode 100644 index 00000000..fcf014cb --- /dev/null +++ b/kompare/komparepart/komparesplitter.cpp @@ -0,0 +1,712 @@ +/*************************************************************************** + komparesplitter.cpp - description + ------------------- + begin : Wed Jan 14 2004 + copyright : (C) 2004 by Jeff Snyder + email : jeff@caffeinated.me.uk +****************************************************************************/ + +/*************************************************************************** +** +** 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 "komparesplitter.h" + +#include <qstyle.h> +#include <qstring.h> +#include <qtimer.h> + +#include <kdebug.h> +#include <kapplication.h> +#include <kglobalsettings.h> + +#include "diffmodel.h" +#include "difference.h" +#include "viewsettings.h" +#include "kompare_part.h" +#include "komparelistview.h" +#include "kompareconnectwidget.h" + +using namespace Diff2; + +KompareSplitter::KompareSplitter( ViewSettings *settings, QWidget * parent, + const char *name) : + QSplitter( Horizontal, parent, name ), + m_settings( settings ) +{ + QFrame *scrollFrame = new QFrame( parent, "scrollFrame" ); + reparent( scrollFrame, *(new QPoint()), false ); + + // Set up the scrollFrame + scrollFrame->setFrameStyle( QFrame::NoFrame | QFrame::Plain ); + scrollFrame->setLineWidth(scrollFrame->style().pixelMetric(QStyle::PM_DefaultFrameWidth)); + QGridLayout *pairlayout = new QGridLayout(scrollFrame, 2, 2, 0); + m_vScroll = new QScrollBar( QScrollBar::Vertical, scrollFrame ); + pairlayout->addWidget( m_vScroll, 0, 1 ); + m_hScroll = new QScrollBar( QScrollBar::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 + setFrameStyle( QFrame::StyledPanel | QFrame::Sunken ); + setLineWidth( style().pixelMetric( QStyle::PM_DefaultFrameWidth ) ); + + setHandleWidth(50); + setChildrenCollapsible( false ); + setFrameStyle( QFrame::NoFrame ); + setSizePolicy( QSizePolicy (QSizePolicy::Ignored, QSizePolicy::Ignored )); + setOpaqueResize( true ); + setFocusPolicy( QWidget::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(scrollToId(int)) ); + connect( m_vScroll, SIGNAL(sliderMoved(int)), SLOT(scrollToId(int)) ); + connect( m_hScroll, SIGNAL(valueChanged(int)), SIGNAL(setXOffset(int)) ); + connect( m_hScroll, SIGNAL(sliderMoved(int)), SIGNAL(setXOffset(int)) ); + + m_scrollTimer=new QTimer(); + 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 + kapp->sendPostedEvents(this, QEvent::ChildInserted); + + // init stuff + slotUpdateScrollBars(); +} + +KompareSplitter::~KompareSplitter(){} + +/* + Inserts the widget \a w at the end (or at the beginning if \a + prepend is TRUE) of the splitter's list of widgets. + + It is the responsibility of the caller to make sure that \a w is + not already in the splitter and to call recalcId() if needed. (If + \a prepend is TRUE, then recalcId() is very probably needed.) +*/ + +QSplitterLayoutStruct *KompareSplitter::addWidget( KompareListViewFrame *w, bool prepend ) +{ + /* This function is *not* a good place to make connections to and from + * the KompareListView. Make them in the KompareListViewFrame constructor + * instad - that way the connections get made upon creation, not upon the + * next processing of the event queue. */ + + QSplitterLayoutStruct *s; + KompareConnectWidgetFrame *newHandle = 0; + if ( d->list.count() > 0 ) { + s = new QSplitterLayoutStruct; + s->resizeMode = KeepSize; + QString tmp = "qt_splithandle_"; + tmp += w->name(); + KompareListView *lw = + ((KompareListViewFrame*)(prepend?w:d->list.last()->wid))->view(); + KompareListView *rw = + ((KompareListViewFrame*)(prepend?d->list.first()->wid:w))->view(); + newHandle = new KompareConnectWidgetFrame(lw, rw, m_settings, this, tmp.latin1()); + s->wid = newHandle; + newHandle->setId( d->list.count() ); + s->isHandle = TRUE; + s->sizer = pick( newHandle->sizeHint() ); + if ( prepend ) + d->list.prepend( s ); + else + d->list.append( s ); + } + s = new QSplitterLayoutStruct; + s->resizeMode = DefaultResizeMode; + s->wid = w; + s->isHandle = FALSE; + if ( prepend ) d->list.prepend( s ); + else d->list.append( s ); + if ( newHandle && isVisible() ) + newHandle->show(); // will trigger sending of post events + return s; +} + + +/*! + Tells the splitter that the child widget described by \a c has + been inserted or removed. +*/ + +void KompareSplitter::childEvent( QChildEvent *c ) +{ + if ( c->type() == QEvent::ChildInserted ) { + if ( !c->child()->isWidgetType() ) + return; + + if ( ((QWidget*)c->child())->testWFlags( WType_TopLevel ) ) + return; + + QSplitterLayoutStruct *s = d->list.first(); + while ( s ) { + if ( s->wid == c->child() ) + return; + s = d->list.next(); + } + addWidget( (KompareListViewFrame*)c->child() ); + recalc( isVisible() ); + } else if ( c->type() == QEvent::ChildRemoved ) { + QSplitterLayoutStruct *prev = 0; + if ( d->list.count() > 1 ) + prev = d->list.at( 1 ); // yes, this is correct + QSplitterLayoutStruct *curr = d->list.first(); + while ( curr ) { + if ( curr->wid == c->child() ) { + d->list.removeRef( curr ); + if ( prev && prev->isHandle ) { + QWidget *w = prev->wid; + d->list.removeRef( prev ); + delete w; // will call childEvent() + } + recalcId(); + doResize(); + return; + } + prev = curr; + curr = d->list.next(); + } + } +} + +// This is from a private qt header (kernel/qlayoutengine_p.h). sorry. +QSize qSmartMinSize( QWidget *w ); + +static QPoint toggle( QWidget *w, QPoint pos ) +{ + QSize minS = qSmartMinSize( w ); + return -pos - QPoint( minS.width(), minS.height() ); +} + +static bool isCollapsed( QWidget *w ) +{ + return w->x() < 0 || w->y() < 0; +} + +static QPoint topLeft( QWidget *w ) +{ + if ( isCollapsed(w) ) { + return toggle( w, w->pos() ); + } else { + return w->pos(); + } +} + +static QPoint bottomRight( QWidget *w ) +{ + if ( isCollapsed(w) ) { + return toggle( w, w->pos() ) - QPoint( 1, 1 ); + } else { + return w->geometry().bottomRight(); + } +} + +void KompareSplitter::moveSplitter( QCOORD p, int id ) +{ + QSplitterLayoutStruct *s = d->list.at( id ); + int farMin; + int min; + int max; + int farMax; + p = adjustPos( p, id, &farMin, &min, &max, &farMax ); + int oldP = pick( s->wid->pos() ); + int* poss = new int[d->list.count()]; + int* ws = new int[d->list.count()]; + QWidget *w = 0; + bool upLeft; + if ( QApplication::reverseLayout() && orient == Horizontal ) { + int q = p + s->wid->width(); + doMove( FALSE, q, id - 1, -1, (p > max), poss, ws ); + doMove( TRUE, q, id, -1, (p < min), poss, ws ); + upLeft = (q > oldP); + } else { + doMove( FALSE, p, id, +1, (p > max), poss, ws ); + doMove( TRUE, p, id - 1, +1, (p < min), poss, ws ); + upLeft = (p < oldP); + } + if ( upLeft ) { + int count = d->list.count(); + for ( int id = 0; id < count; ++id ) { + w = d->list.at( id )->wid; + if( !w->isHidden() ) + setGeo( w, poss[id], ws[id], TRUE ); + } + } else { + for ( int id = d->list.count() - 1; id >= 0; --id ) { + w = d->list.at( id )->wid; + if( !w->isHidden() ) + setGeo( w, poss[id], ws[id], TRUE ); + } + } + storeSizes(); +} + +void KompareSplitter::doMove( bool backwards, int pos, int id, int delta, + bool mayCollapse, int* positions, int* widths ) +{ + QSplitterLayoutStruct *s; + QWidget *w; + for ( ; id >= 0 && id < (int)d->list.count(); + id = backwards ? id - delta : id + delta ) { + s = d->list.at( id ); + w = s->wid; + if ( w->isHidden() ) { + mayCollapse = TRUE; + } else { + if ( s->isHandle ) { + int dd = s->getSizer( orient ); + int nextPos = backwards ? pos - dd : pos + dd; + positions[id] = pos; + widths[id] = dd; + pos = nextPos; + } else { + int dd = backwards ? pos - pick( topLeft(w) ) + : pick( bottomRight(w) ) - pos + 1; + if ( dd > 0 || (!isCollapsed(w) && !mayCollapse) ) { + dd = QMAX( pick(qSmartMinSize(w)), + QMIN(dd, pick(w->maximumSize())) ); + } else { + dd = 0; + } + positions[id] = backwards ? pos - dd : pos; + widths[id] = dd; + pos = backwards ? pos - dd : pos + dd; + mayCollapse = TRUE; + } + } + } +} + +void KompareSplitter::slotSetSelection( const DiffModel* model, const Difference* diff ) +{ + QSplitterLayoutStruct *curr; + for ( curr = d->list.first(); curr; curr = d->list.next() ) + { + if ( curr->isHandle ) + ((KompareConnectWidgetFrame*) + curr->wid)->wid()->slotSetSelection( model, diff ); + else + { + ((KompareListViewFrame*) + curr->wid)->view()->slotSetSelection( model, diff ); + ((KompareListViewFrame*) + curr->wid)->slotSetModel( model ); + } + } + slotDelayedRepaintHandles(); + slotDelayedUpdateScrollBars(); +} + +void KompareSplitter::slotSetSelection( const Difference* diff ) +{ + QSplitterLayoutStruct *curr; + for ( curr = d->list.first(); curr; curr = d->list.next() ) + if ( curr->isHandle ) + ((KompareConnectWidgetFrame*) + curr->wid)->wid()->slotSetSelection( diff ); + else + ((KompareListViewFrame*) + curr->wid)->view()->slotSetSelection( diff ); + slotDelayedRepaintHandles(); + slotDelayedUpdateScrollBars(); +} + +void KompareSplitter::slotApplyDifference( bool apply ) +{ + QSplitterLayoutStruct *curr; + for ( curr = d->list.first(); curr; curr = d->list.next() ) + if ( !curr->isHandle ) + ((KompareListViewFrame*) + curr->wid)->view()->slotApplyDifference( apply ); + slotDelayedRepaintHandles(); +} + +void KompareSplitter::slotApplyAllDifferences( bool apply ) +{ + QSplitterLayoutStruct *curr; + for ( curr = d->list.first(); curr; curr = d->list.next() ) + if ( !curr->isHandle ) + ((KompareListViewFrame*) + curr->wid)->view()->slotApplyAllDifferences( apply ); + slotDelayedRepaintHandles(); + scrollToId( scrollTo ); // FIXME! +} + +void KompareSplitter::slotApplyDifference( const Difference* diff, bool apply ) +{ + QSplitterLayoutStruct *curr; + for ( curr = d->list.first(); curr; curr = d->list.next() ) + if ( !curr->isHandle ) + ((KompareListViewFrame*) + curr->wid)->view()->slotApplyDifference( diff, apply ); + slotDelayedRepaintHandles(); +} + +void KompareSplitter::slotDifferenceClicked( const Difference* diff ) +{ + QSplitterLayoutStruct *curr; + for ( curr = d->list.first(); curr; curr = d->list.next() ) + if ( !curr->isHandle ) + ((KompareListViewFrame*) + curr->wid)->view()->setSelectedDifference( diff, false ); + emit selectionChanged( diff ); +} + +void KompareSplitter::slotConfigChanged() +{ + QSplitterLayoutStruct *curr; + for ( curr = d->list.first(); curr; curr = d->list.next() ) { + if ( !curr->isHandle ) + { + ((KompareListViewFrame*) + curr->wid)->view()->setSpaces( m_settings->m_tabToNumberOfSpaces ); + ((KompareListViewFrame*) + curr->wid)->view()->setFont( m_settings->m_font ); + ((KompareListViewFrame*) + curr->wid)->view()->update(); + } + } +} + +void KompareSplitter::slotDelayedRepaintHandles() +{ + QSplitterLayoutStruct *curr; + for ( curr = d->list.first(); curr; curr = d->list.next() ) + if ( curr->isHandle ) + ((KompareConnectWidgetFrame*)curr->wid)->wid()->slotDelayedRepaint(); +} + +void KompareSplitter::repaintHandles() +{ + QSplitterLayoutStruct *curr; + for ( curr = d->list.first(); curr; curr = d->list.next() ) + if ( curr->isHandle ) + ((KompareConnectWidgetFrame*)curr->wid)->wid()->repaint(); +} + +// Scrolling stuff +/* + * limit updating to once every 50 msec with a qtimer + * FIXME: i'm a nasty hack + */ + +void KompareSplitter::wheelEvent( QWheelEvent* e ) +{ + // scroll lines... + if ( e->orientation() == Qt::Vertical ) + { + if ( e->state() & Qt::ControlButton ) + if ( e->delta() < 0 ) // scroll down one page + m_vScroll->addPage(); + else // scroll up one page + m_vScroll->subtractPage(); + else + if ( e->delta() < 0 ) // scroll down + m_vScroll->addLine(); + else // scroll up + m_vScroll->subtractLine(); + } + else + { + if ( e->state() & Qt::ControlButton ) + if ( e->delta() < 0 ) // scroll right one page + m_hScroll->addPage(); + else // scroll left one page + m_hScroll->subtractPage(); + else + if ( e->delta() < 0 ) // scroll to the right + m_hScroll->addLine(); + else // scroll to the left + m_hScroll->subtractLine(); + } + e->accept(); + repaintHandles(); +} + +void KompareSplitter::keyPressEvent( QKeyEvent* e ) +{ + //keyboard scrolling + switch ( e->key() ) { + case Key_Right: + case Key_L: + m_hScroll->addLine(); + break; + case Key_Left: + case Key_H: + m_hScroll->subtractLine(); + break; + case Key_Up: + case Key_K: + m_vScroll->subtractLine(); + break; + case Key_Down: + case Key_J: + m_vScroll->addLine(); + break; + case Key_PageDown: + m_vScroll->addPage(); + break; + case Key_PageUp: + m_vScroll->subtractPage(); + break; + } + e->accept(); + repaintHandles(); +} + +void KompareSplitter::timerTimeout() +{ + if ( restartTimer ) + restartTimer = false; + else + m_scrollTimer->stop(); + + slotDelayedRepaintHandles(); + + emit scrollViewsToId( scrollTo ); +} + +void KompareSplitter::scrollToId( int id ) +{ + scrollTo = id; + + if( restartTimer ) + return; + + if( m_scrollTimer->isActive() ) + { + restartTimer = true; + } + else + { + emit scrollViewsToId( id ); + slotDelayedRepaintHandles(); + m_scrollTimer->start(30, false); + } +} + +void KompareSplitter::slotDelayedUpdateScrollBars() +{ + QTimer::singleShot( 0, this, SLOT( slotUpdateScrollBars() ) ); +} + +void KompareSplitter::slotUpdateScrollBars() +{ + int m_scrollDistance = m_settings->m_scrollNoOfLines * lineSpacing(); + int m_pageSize = pageSize(); + + if( needVScrollBar() ) + { + m_vScroll->show(); + + m_vScroll->blockSignals( true ); + m_vScroll->setRange( minVScrollId(), + maxVScrollId() ); + m_vScroll->setValue( scrollId() ); + m_vScroll->setSteps( m_scrollDistance, m_pageSize ); + m_vScroll->blockSignals( false ); + } + else + { + m_vScroll->hide(); + } + + if( needHScrollBar() ) + { + m_hScroll->show(); + m_hScroll->blockSignals( true ); + m_hScroll->setRange( 0, maxHScrollId() ); + m_hScroll->setValue( maxContentsX() ); + m_hScroll->setSteps( 10, 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() ); +} + +/* 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() +{ + QSplitterLayoutStruct *curr = d->list.first(); + for ( curr = d->list.first(); curr; curr = d->list.next() ) + if ( !curr->isHandle ) + return ((KompareListViewFrame*) curr->wid)->view()->scrollId(); + return minVScrollId(); +} + +int KompareSplitter::lineSpacing() +{ + QSplitterLayoutStruct *curr = d->list.first(); + for ( curr = d->list.first(); curr; curr = d->list.next() ) + if ( !curr->isHandle ) + return ((KompareListViewFrame*) + curr->wid)->view()->fontMetrics().lineSpacing(); + return 1; +} + +int KompareSplitter::pageSize() +{ + QSplitterLayoutStruct *curr; + for ( curr = d->list.first(); curr; curr = d->list.next() ) + { + if ( !curr->isHandle ) + { + KompareListView *view = ((KompareListViewFrame*) curr->wid)->view(); + return view->visibleHeight() - QStyle::PM_ScrollBarExtent; + } + } + return 1; +} + +bool KompareSplitter::needVScrollBar() +{ + QSplitterLayoutStruct *curr; + int pagesize = pageSize(); + for ( curr = d->list.first(); curr; curr = d->list.next() ) + { + if( !curr->isHandle ) + { + KompareListView *view = ((KompareListViewFrame*) curr->wid)->view(); + if( view ->contentsHeight() > pagesize) + return true; + } + } + return false; +} + +int KompareSplitter::minVScrollId() +{ + + QSplitterLayoutStruct *curr; + int min = -1; + int mSId; + for ( curr = d->list.first(); curr; curr = d->list.next() ) + { + if(!curr->isHandle) { + KompareListView* view = ((KompareListViewFrame*)curr->wid)->view(); + mSId = view->minScrollId(); + if (mSId < min || min == -1) min = mSId; + } + } + return ( min == -1 ) ? 0 : min; +} + +int KompareSplitter::maxVScrollId() +{ + QSplitterLayoutStruct *curr; + int max = 0; + int mSId; + for ( curr = d->list.first(); curr; curr = d->list.next() ) + { + if ( !curr->isHandle ) + { + mSId = ((KompareListViewFrame*)curr->wid)->view()->maxScrollId(); + if ( mSId > max ) + max = mSId; + } + } + return max; +} + +bool KompareSplitter::needHScrollBar() +{ + QSplitterLayoutStruct *curr; + for ( curr = d->list.first(); curr; curr = d->list.next() ) + { + if( !curr->isHandle ) + { + KompareListView *view = ((KompareListViewFrame*) curr->wid)->view(); + if ( view->contentsWidth() > view->visibleWidth() ) + return true; + } + } + return false; +} + +int KompareSplitter::maxHScrollId() +{ + QSplitterLayoutStruct *curr; + int max = 0; + int mHSId; + for ( curr = d->list.first(); curr; curr = d->list.next() ) + { + if( !curr->isHandle ) + { + KompareListView *view = ((KompareListViewFrame*) curr->wid)->view(); + mHSId = view->contentsWidth() - view->visibleWidth(); + if ( mHSId > max ) + max = mHSId; + } + } + return max; +} + +int KompareSplitter::maxContentsX() +{ + QSplitterLayoutStruct *curr; + int max = 0; + int mCX; + for ( curr = d->list.first(); curr; curr = d->list.next() ) + { + if ( !curr->isHandle ) + { + mCX = ((KompareListViewFrame*) curr->wid)->view()->contentsX(); + if ( mCX > max ) + max = mCX; + } + } + return max; +} + +int KompareSplitter::minVisibleWidth() +{ + // Why the hell do we want to know this? + // ah yes, its because we use it to set the "page size" for horiz. scrolling. + // despite the fact that *noone* 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 + QSplitterLayoutStruct *curr; + int min = -1; + int vW; + for( curr = d->list.first(); curr; curr = d->list.next() ) + { + if ( !curr->isHandle ) { + vW = ((KompareListViewFrame*)curr->wid)->view()->visibleWidth(); + if ( vW < min || min == -1 ) + min = vW; + } + } + return ( min == -1 ) ? 0 : min; +} + +#include "komparesplitter.moc" diff --git a/kompare/komparepart/komparesplitter.h b/kompare/komparepart/komparesplitter.h new file mode 100644 index 00000000..47eee6bf --- /dev/null +++ b/kompare/komparepart/komparesplitter.h @@ -0,0 +1,115 @@ +/*************************************************************************** + kompareview.cpp - description + ------------------- + begin : Wed Jan 14 2004 + copyright : (C) 2004 by Jeff Snyder + email : jeff@caffeinated.me.uk +****************************************************************************/ + +/*************************************************************************** +** +** 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 "kompare_qsplitter.h" + +#include <qtimer.h> + +#include "komparelistview.h" +#include "komparemodellist.h" + +class QSplitterLayoutStruct; +class QTextStream; +class QSplitterHandle; + +namespace Diff2 { +class DiffModel; +class Difference; +} +class ViewSettings; + +class KompareSplitter : public QSplitter +{ + Q_OBJECT + +public: + KompareSplitter(ViewSettings *settings, QWidget *parent=0, const char *name = 0); + ~KompareSplitter(); + +signals: + void selectionChanged( const Diff2::Difference* diff ); + + void configChanged(); + + void scrollViewsToId( int id ); + void setXOffset( int x ); + +public slots: + void slotApplyDifference( bool apply ); + void slotApplyAllDifferences( bool apply ); + void slotApplyDifference( const Diff2::Difference* diff, bool apply ); + + // to update the list views + void slotSetSelection( const Diff2::DiffModel* model, const Diff2::Difference* diff ); + void slotSetSelection( const Diff2::Difference* diff ); + + void slotDifferenceClicked( const Diff2::Difference* diff ); + + void slotConfigChanged(); + + void scrollToId( int id ); + void slotDelayedUpdateScrollBars(); + void slotUpdateScrollBars(); + void slotDelayedUpdateVScrollValue(); + void slotUpdateVScrollValue(); + +protected: + void childEvent( QChildEvent * ); + void wheelEvent( QWheelEvent* e ); + void keyPressEvent( QKeyEvent* e ); + + void moveSplitter( QCOORD pos, int id ); + +private slots: + void slotDelayedRepaintHandles(); + void timerTimeout(); + +private: + QSplitterLayoutStruct *addWidget(KompareListViewFrame *w, + bool prepend = FALSE ); + + void doMove( bool backwards, int pos, int id, int delta, + bool mayCollapse, int* positions, int* widths ); + + void repaintHandles(); + + QTimer* m_scrollTimer; + bool restartTimer; + int scrollTo; + + // Scrollbars. all this just for the goddamn scrollbars. i hate them. + int scrollId(); + int lineSpacing(); + int pageSize(); + bool needVScrollBar(); + int minVScrollId(); + int maxVScrollId(); + bool needHScrollBar(); + int maxHScrollId(); + int maxContentsX(); + int minVisibleWidth(); + + ViewSettings* m_settings; + QScrollBar* m_vScroll; + QScrollBar* m_hScroll; + + friend class KompareConnectWidgetFrame; +}; +#endif //_KOMPARESPLITTER_H_ |