diff --git a/src/kdiff3.cpp b/src/kdiff3.cpp index 82d20d7..31e7f8a 100644 --- a/src/kdiff3.cpp +++ b/src/kdiff3.cpp @@ -1,1097 +1,1098 @@ /*************************************************************************** kdiff3.cpp - description ------------------- begin : Don Jul 11 12:31:29 CEST 2002 copyright : (C) 2002-2007 by Joachim Eibl email : joachim.eibl at gmx.de ***************************************************************************/ /*************************************************************************** * * * 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 "difftextwindow.h" #include "mergeresultwindow.h" #include // include files for QT #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include // include files for KDE #include #include #include #include //#include #include #include #include #include // application specific includes #include "directorymergewindow.h" #include "fileaccess.h" #include "guiutils.h" // namespace KDiff3 #include "kdiff3.h" #include "kdiff3_part.h" #include "kdiff3_shell.h" #include "optiondialog.h" #include "progress.h" #include "smalldialogs.h" #define ID_STATUS_MSG 1 #define MAIN_TOOLBAR_NAME "mainToolBar" KActionCollection* KDiff3App::actionCollection() { if(m_pKDiff3Shell == nullptr) return m_pKDiff3Part->actionCollection(); else return m_pKDiff3Shell->actionCollection(); } QStatusBar* KDiff3App::statusBar() { if(m_pKDiff3Shell == nullptr) return nullptr; else return m_pKDiff3Shell->statusBar(); } KToolBar* KDiff3App::toolBar(const char* toolBarId) { if(m_pKDiff3Shell == nullptr) return nullptr; else return m_pKDiff3Shell->toolBar(toolBarId); //return m_pKDiff3Shell->toolBar(); } bool KDiff3App::isPart() { return m_pKDiff3Shell == nullptr; } bool KDiff3App::isFileSaved() { return m_bFileSaved; } bool KDiff3App::isDirComparison() { return m_bDirCompare; } KDiff3App::KDiff3App(QWidget* pParent, const QString /*name*/, KDiff3Part* pKDiff3Part) : QSplitter(pParent) //previously KMainWindow { setObjectName("KDiff3App"); m_pKDiff3Part = pKDiff3Part; m_pKDiff3Shell = qobject_cast(pParent); setWindowTitle("KDiff3"); setOpaqueResize(false); // faster resizing setUpdatesEnabled(false); // set Disabled to same color as enabled to prevent flicker in DirectoryMergeWindow QPalette pal; pal.setBrush(QPalette::Base, pal.brush(QPalette::Active, QPalette::Base)); pal.setColor(QPalette::Text, pal.color(QPalette::Active, QPalette::Text)); setPalette(pal); m_pMainSplitter = nullptr; m_pDirectoryMergeSplitter = nullptr; m_pDirectoryMergeWindow = nullptr; m_pCornerWidget = nullptr; m_pMainWidget = nullptr; m_pDiffTextWindow1 = nullptr; m_pDiffTextWindow2 = nullptr; m_pDiffTextWindow3 = nullptr; m_pDiffTextWindowFrame1 = nullptr; m_pDiffTextWindowFrame2 = nullptr; m_pDiffTextWindowFrame3 = nullptr; m_pDiffWindowSplitter = nullptr; m_pOverview = nullptr; m_bTripleDiff = false; m_pMergeResultWindow = nullptr; m_pMergeWindowFrame = nullptr; m_bOutputModified = false; m_bFileSaved = false; m_bTimerBlock = false; m_pHScrollBar = nullptr; m_pDiffVScrollBar = nullptr; m_pMergeVScrollBar = nullptr; viewToolBar = nullptr; m_bRecalcWordWrapPosted = false; m_bFinishMainInit = false; m_pEventLoopForPrinting = nullptr; m_bLoadFiles = false; // Needed before any file operations via FileAccess happen. if(!g_pProgressDialog) { g_pProgressDialog = new ProgressDialog(this, statusBar()); g_pProgressDialog->setStayHidden(true); } // All default values must be set before calling readOptions(). m_pOptionDialog = new OptionDialog(m_pKDiff3Shell != nullptr, this); connect(m_pOptionDialog, &OptionDialog::applyDone, this, &KDiff3App::slotRefresh); // This is just a convenience variable to make code that accesses options more readable m_pOptions = &m_pOptionDialog->m_options; m_pOptionDialog->readOptions(KSharedConfig::openConfig()); // Option handling: Only when pParent==0 (no parent) int argCount = KDiff3Shell::getParser()->optionNames().count() + KDiff3Shell::getParser()->positionalArguments().count(); bool hasArgs = !isPart() && argCount > 0; if(hasArgs) { QString s; QString title; if(KDiff3Shell::getParser()->isSet("confighelp")) { s = m_pOptionDialog->calcOptionHelp(); title = i18n("Current Configuration:"); } else { s = m_pOptionDialog->parseOptions(KDiff3Shell::getParser()->values("cs")); title = i18n("Config Option Error:"); } if(!s.isEmpty()) { //KMessageBox::information(0, s,i18n("KDiff3-Usage")); QDialog* pDialog = new QDialog(this); pDialog->setAttribute(Qt::WA_DeleteOnClose); pDialog->setModal(true); pDialog->setWindowTitle(title); QVBoxLayout* pVBoxLayout = new QVBoxLayout(pDialog); QTextEdit* pTextEdit = new QTextEdit(pDialog); pTextEdit->setText(s); pTextEdit->setReadOnly(true); pTextEdit->setWordWrapMode(QTextOption::NoWrap); pVBoxLayout->addWidget(pTextEdit); pDialog->resize(600, 400); pDialog->exec(); #if !defined(Q_OS_WIN) // A windows program has no console printf("%s\n", title.toLatin1().constData()); printf("%s\n", s.toLatin1().constData()); #endif exit(1); } } m_sd1.setOptions(m_pOptions); m_sd2.setOptions(m_pOptions); m_sd3.setOptions(m_pOptions); m_bAutoFlag = false; //disable --auto option git hard codes this unwanted flag. m_bAutoMode = m_bAutoFlag || m_pOptions->m_bAutoSaveAndQuitOnMergeWithoutConflicts; if(hasArgs) { m_outputFilename = KDiff3Shell::getParser()->value("output"); if(m_outputFilename.isEmpty()) m_outputFilename = KDiff3Shell::getParser()->value("out"); if(!m_outputFilename.isEmpty()) m_outputFilename = FileAccess(m_outputFilename, true).absoluteFilePath(); if(m_bAutoMode && m_outputFilename.isEmpty()) { if(m_bAutoFlag) { //KMessageBox::information(this, i18n("Option --auto used, but no output file specified.")); fprintf(stderr, "%s\n", (const char*)i18n("Option --auto used, but no output file specified.").toLatin1()); } m_bAutoMode = false; } if(m_outputFilename.isEmpty() && KDiff3Shell::getParser()->isSet("merge")) { m_outputFilename = "unnamed.txt"; m_bDefaultFilename = true; } else { m_bDefaultFilename = false; } g_bAutoSolve = !KDiff3Shell::getParser()->isSet("qall"); // Note that this is effective only once. QStringList args = KDiff3Shell::getParser()->positionalArguments(); m_sd1.setFilename(KDiff3Shell::getParser()->value("base")); if(m_sd1.isEmpty()) { if(args.count() > 0) m_sd1.setFilename(args[0]); // args->arg(0) if(args.count() > 1) m_sd2.setFilename(args[1]); if(args.count() > 2) m_sd3.setFilename(args[2]); } else { if(args.count() > 0) m_sd2.setFilename(args[0]); if(args.count() > 1) m_sd3.setFilename(args[1]); } //never properly defined and redundant QStringList aliasList; //KDiff3Shell::getParser()->values( "fname" ); QStringList::Iterator ali = aliasList.begin(); QString an1 = KDiff3Shell::getParser()->value("L1"); if(!an1.isEmpty()) { m_sd1.setAliasName(an1); } else if(ali != aliasList.end()) { m_sd1.setAliasName(*ali); ++ali; } QString an2 = KDiff3Shell::getParser()->value("L2"); if(!an2.isEmpty()) { m_sd2.setAliasName(an2); } else if(ali != aliasList.end()) { m_sd2.setAliasName(*ali); ++ali; } QString an3 = KDiff3Shell::getParser()->value("L3"); if(!an3.isEmpty()) { m_sd3.setAliasName(an3); } else if(ali != aliasList.end()) { m_sd3.setAliasName(*ali); ++ali; } } else { m_bDefaultFilename = false; g_bAutoSolve = false; } g_pProgressDialog->setStayHidden(m_bAutoMode); /////////////////////////////////////////////////////////////////// // call inits to invoke all other construction parts initActions(actionCollection()); initStatusBar(); m_pFindDialog = new FindDialog(this); connect(m_pFindDialog, &FindDialog::findNext, this, &KDiff3App::slotEditFindNext); autoAdvance->setChecked(m_pOptions->m_bAutoAdvance); showWhiteSpaceCharacters->setChecked(m_pOptions->m_bShowWhiteSpaceCharacters); showWhiteSpace->setChecked(m_pOptions->m_bShowWhiteSpace); showWhiteSpaceCharacters->setEnabled(m_pOptions->m_bShowWhiteSpace); showLineNumbers->setChecked(m_pOptions->m_bShowLineNumbers); wordWrap->setChecked(m_pOptions->m_bWordWrap); if(!isPart()) { // TODO // viewToolBar->setChecked( m_pOptions->m_bShowToolBar ); // slotViewToolBar(); viewStatusBar->setChecked(m_pOptions->m_bShowStatusBar); slotViewStatusBar(); - /* - vrusu - commented out as new KToolBar does not hase setParPos - TODO figure out how to restore bar position - if( toolBar(MAIN_TOOLBAR_NAME)!=0 ) - toolBar(MAIN_TOOLBAR_NAME)->setBarPos( (KToolBar::BarPosition) m_pOptions->m_toolBarPos );*/ + + KToolBar *mainToolBar = toolBar(MAIN_TOOLBAR_NAME); + if(mainToolBar != nullptr){ + mainToolBar->mainWindow()->addToolBar(m_pOptions->m_toolBarPos, mainToolBar); + } + // TODO restore window size/pos? /* QSize size = m_pOptions->m_geometry; QPoint pos = m_pOptions->m_position; if(!size.isEmpty()) { m_pKDiff3Shell->resize( size ); QRect visibleRect = QRect( pos, size ) & QApplication::desktop()->rect(); if ( visibleRect.width()>100 && visibleRect.height()>100 ) m_pKDiff3Shell->move( pos ); }*/ } slotRefresh(); m_pMainSplitter = this; //new QSplitter(this); m_pMainSplitter->setOrientation(Qt::Vertical); // setCentralWidget( m_pMainSplitter ); m_pDirectoryMergeSplitter = new QSplitter(m_pMainSplitter); m_pDirectoryMergeSplitter->setObjectName("DirectoryMergeSplitter"); m_pMainSplitter->addWidget(m_pDirectoryMergeSplitter); m_pDirectoryMergeSplitter->setOrientation(Qt::Horizontal); m_pDirectoryMergeWindow = new DirectoryMergeWindow(m_pDirectoryMergeSplitter, m_pOptions, KIconLoader::global()); m_pDirectoryMergeSplitter->addWidget(m_pDirectoryMergeWindow); m_pDirectoryMergeInfo = new DirectoryMergeInfo(m_pDirectoryMergeSplitter); m_pDirectoryMergeWindow->setDirectoryMergeInfo(m_pDirectoryMergeInfo); m_pDirectoryMergeSplitter->addWidget(m_pDirectoryMergeInfo); connect(m_pDirectoryMergeWindow, &DirectoryMergeWindow::startDiffMerge, this, &KDiff3App::slotFileOpen2); connect(m_pDirectoryMergeWindow->selectionModel(), &QItemSelectionModel::selectionChanged, this, &KDiff3App::slotUpdateAvailabilities); connect(m_pDirectoryMergeWindow->selectionModel(), &QItemSelectionModel::currentChanged, this, &KDiff3App::slotUpdateAvailabilities); connect(m_pDirectoryMergeWindow, &DirectoryMergeWindow::checkIfCanContinue, this, &KDiff3App::slotCheckIfCanContinue); connect(m_pDirectoryMergeWindow, SIGNAL(updateAvailabilities()), this, SLOT(slotUpdateAvailabilities())); connect(m_pDirectoryMergeWindow, &DirectoryMergeWindow::statusBarMessage, this, &KDiff3App::slotStatusMsg); connect(QApplication::clipboard(), &QClipboard::dataChanged, this, &KDiff3App::slotClipboardChanged); m_pDirectoryMergeWindow->initDirectoryMergeActions(this, actionCollection()); delete KDiff3Shell::getParser(); //if( args != 0 ) args->clear(); // Free up some memory. if(m_pKDiff3Shell == nullptr) { completeInit(); } } void KDiff3App::completeInit(const QString& fn1, const QString& fn2, const QString& fn3) { if(m_pKDiff3Shell != nullptr) { QSize size = m_pOptions->m_geometry; QPoint pos = m_pOptions->m_position; if(!size.isEmpty()) { m_pKDiff3Shell->resize(size); QRect visibleRect = QRect(pos, size) & QApplication::desktop()->rect(); if(visibleRect.width() > 100 && visibleRect.height() > 100) m_pKDiff3Shell->move(pos); if(!m_bAutoMode) { if(m_pOptions->m_bMaximised) m_pKDiff3Shell->showMaximized(); else m_pKDiff3Shell->show(); } } } if(!fn1.isEmpty()) { m_sd1.setFilename(fn1); } if(!fn2.isEmpty()) { m_sd2.setFilename(fn2); } if(!fn3.isEmpty()) { m_sd3.setFilename(fn3); } bool bSuccess = improveFilenames(false); if(m_bAutoFlag && m_bAutoMode && m_bDirCompare) { fprintf(stderr, "%s\n", (const char*)i18n("Option --auto ignored for directory comparison.").toLatin1()); m_bAutoMode = false; } if(!m_bDirCompare) { m_pDirectoryMergeSplitter->hide(); mainInit(); if(m_bAutoMode) { SourceData* pSD = nullptr; if(m_sd3.isEmpty()) { if(m_totalDiffStatus.bBinaryAEqB) { pSD = &m_sd1; } } else { if(m_totalDiffStatus.bBinaryBEqC) { pSD = &m_sd3; // B==C (assume A is old) } else if(m_totalDiffStatus.bBinaryAEqB) { pSD = &m_sd3; // assuming C has changed } else if(m_totalDiffStatus.bBinaryAEqC) { pSD = &m_sd2; // assuming B has changed } } if(pSD != nullptr) { // Save this file directly, not via the merge result window. bool bSuccess = false; FileAccess fa(m_outputFilename); if(m_pOptions->m_bDmCreateBakFiles && fa.exists()) { QString newName = m_outputFilename + ".orig"; if(FileAccess::exists(newName)) FileAccess::removeFile(newName); if(!FileAccess::exists(newName)) fa.rename(newName); } bSuccess = pSD->saveNormalDataAs(m_outputFilename); if(bSuccess) ::exit(0); else KMessageBox::error(this, i18n("Saving failed.")); } else if(m_pMergeResultWindow->getNrOfUnsolvedConflicts() == 0) { bool bSuccess = m_pMergeResultWindow->saveDocument(m_pMergeResultWindowTitle->getFileName(), m_pMergeResultWindowTitle->getEncoding(), m_pMergeResultWindowTitle->getLineEndStyle()); if(bSuccess) ::exit(0); } } } m_bAutoMode = false; if(m_pKDiff3Shell) { if(m_pOptions->m_bMaximised) m_pKDiff3Shell->showMaximized(); else m_pKDiff3Shell->show(); } g_pProgressDialog->setStayHidden(false); if(statusBar() != nullptr) statusBar()->setSizeGripEnabled(true); slotClipboardChanged(); // For initialisation. slotUpdateAvailabilities(); if(!m_bDirCompare && m_pKDiff3Shell != nullptr) { bool bFileOpenError = false; if((!m_sd1.isEmpty() && !m_sd1.hasData()) || (!m_sd2.isEmpty() && !m_sd2.hasData()) || (!m_sd3.isEmpty() && !m_sd3.hasData())) { QString text(i18n("Opening of these files failed:")); text += "\n\n"; if(!m_sd1.isEmpty() && !m_sd1.hasData()) text += " - " + m_sd1.getAliasName() + "\n"; if(!m_sd2.isEmpty() && !m_sd2.hasData()) text += " - " + m_sd2.getAliasName() + "\n"; if(!m_sd3.isEmpty() && !m_sd3.hasData()) text += " - " + m_sd3.getAliasName() + "\n"; KMessageBox::sorry(this, text, i18n("File Open Error")); bFileOpenError = true; } if(m_sd1.isEmpty() || m_sd2.isEmpty() || bFileOpenError) slotFileOpen(); } else if(!bSuccess) // Directory open failed { slotFileOpen(); } } KDiff3App::~KDiff3App() { } /** * Helper function used to create actions into the ac collection */ void KDiff3App::initActions(KActionCollection* ac) { if(ac == nullptr){ KMessageBox::error(nullptr, "actionCollection==0"); exit(-1);//we cann't recover from this. } fileOpen = KStandardAction::open(this, SLOT(slotFileOpen()), ac); fileOpen->setStatusTip(i18n("Opens documents for comparison...")); fileReload = KDiff3::createAction(i18n("Reload"), QKeySequence(QKeySequence::Refresh), this, SLOT(slotReload()), ac, "file_reload"); fileSave = KStandardAction::save(this, SLOT(slotFileSave()), ac); fileSave->setStatusTip(i18n("Saves the merge result. All conflicts must be solved!")); fileSaveAs = KStandardAction::saveAs(this, SLOT(slotFileSaveAs()), ac); fileSaveAs->setStatusTip(i18n("Saves the current document as...")); #ifndef QT_NO_PRINTER filePrint = KStandardAction::print(this, SLOT(slotFilePrint()), ac); filePrint->setStatusTip(i18n("Print the differences")); #endif fileQuit = KStandardAction::quit(this, SLOT(slotFileQuit()), ac); fileQuit->setStatusTip(i18n("Quits the application")); editCut = KStandardAction::cut(this, SLOT(slotEditCut()), ac); editCut->setStatusTip(i18n("Cuts the selected section and puts it to the clipboard")); editCopy = KStandardAction::copy(this, SLOT(slotEditCopy()), ac); editCopy->setStatusTip(i18n("Copies the selected section to the clipboard")); editPaste = KStandardAction::paste(this, SLOT(slotEditPaste()), ac); editPaste->setStatusTip(i18n("Pastes the clipboard contents to current position")); editSelectAll = KStandardAction::selectAll(this, SLOT(slotEditSelectAll()), ac); editSelectAll->setStatusTip(i18n("Select everything in current window")); editFind = KStandardAction::find(this, SLOT(slotEditFind()), ac); editFind->setStatusTip(i18n("Search for a string")); editFindNext = KStandardAction::findNext(this, SLOT(slotEditFindNext()), ac); editFindNext->setStatusTip(i18n("Search again for the string")); /* FIXME figure out how to implement this action viewToolBar = KStandardAction::showToolbar(this, SLOT(slotViewToolBar()), ac); viewToolBar->setStatusTip(i18n("Enables/disables the toolbar")); */ viewStatusBar = KStandardAction::showStatusbar(this, SLOT(slotViewStatusBar()), ac); viewStatusBar->setStatusTip(i18n("Enables/disables the statusbar")); KStandardAction::keyBindings(this, SLOT(slotConfigureKeys()), ac); QAction* pAction = KStandardAction::preferences(this, SLOT(slotConfigure()), ac); if(isPart()) pAction->setText(i18n("Configure KDiff3...")); #include "xpm/autoadvance.xpm" #include "xpm/currentpos.xpm" #include "xpm/down1arrow.xpm" #include "xpm/down2arrow.xpm" #include "xpm/downend.xpm" #include "xpm/iconA.xpm" #include "xpm/iconB.xpm" #include "xpm/iconC.xpm" #include "xpm/nextunsolved.xpm" #include "xpm/prevunsolved.xpm" #include "xpm/showlinenumbers.xpm" #include "xpm/showwhitespace.xpm" #include "xpm/showwhitespacechars.xpm" #include "xpm/up1arrow.xpm" #include "xpm/up2arrow.xpm" #include "xpm/upend.xpm" //#include "reload.xpm" goCurrent = KDiff3::createAction(i18n("Go to Current Delta"), QIcon(QPixmap(currentpos)), i18n("Current\nDelta"), QKeySequence(Qt::CTRL + Qt::Key_Space), this, SLOT(slotGoCurrent()), ac, "go_current"); goTop = KDiff3::createAction(i18n("Go to First Delta"), QIcon(QPixmap(upend)), i18n("First\nDelta"), this, SLOT(slotGoTop()), ac, "go_top"); goBottom = KDiff3::createAction(i18n("Go to Last Delta"), QIcon(QPixmap(downend)), i18n("Last\nDelta"), this, SLOT(slotGoBottom()), ac, "go_bottom"); QString omitsWhitespace = ".\n" + i18n("(Skips white space differences when \"Show White Space\" is disabled.)"); QString includeWhitespace = ".\n" + i18n("(Does not skip white space differences even when \"Show White Space\" is disabled.)"); goPrevDelta = KDiff3::createAction(i18n("Go to Previous Delta"), QIcon(QPixmap(up1arrow)), i18n("Prev\nDelta"), QKeySequence(Qt::CTRL + Qt::Key_Up), this, SLOT(slotGoPrevDelta()), ac, "go_prev_delta"); goPrevDelta->setToolTip(goPrevDelta->text() + omitsWhitespace); goNextDelta = KDiff3::createAction(i18n("Go to Next Delta"), QIcon(QPixmap(down1arrow)), i18n("Next\nDelta"), QKeySequence(Qt::CTRL + Qt::Key_Down), this, SLOT(slotGoNextDelta()), ac, "go_next_delta"); goNextDelta->setToolTip(goNextDelta->text() + omitsWhitespace); goPrevConflict = KDiff3::createAction(i18n("Go to Previous Conflict"), QIcon(QPixmap(up2arrow)), i18n("Prev\nConflict"), QKeySequence(Qt::CTRL + Qt::Key_PageUp), this, SLOT(slotGoPrevConflict()), ac, "go_prev_conflict"); goPrevConflict->setToolTip(goPrevConflict->text() + omitsWhitespace); goNextConflict = KDiff3::createAction(i18n("Go to Next Conflict"), QIcon(QPixmap(down2arrow)), i18n("Next\nConflict"), QKeySequence(Qt::CTRL + Qt::Key_PageDown), this, SLOT(slotGoNextConflict()), ac, "go_next_conflict"); goNextConflict->setToolTip(goNextConflict->text() + omitsWhitespace); goPrevUnsolvedConflict = KDiff3::createAction(i18n("Go to Previous Unsolved Conflict"), QIcon(QPixmap(prevunsolved)), i18n("Prev\nUnsolved"), this, SLOT(slotGoPrevUnsolvedConflict()), ac, "go_prev_unsolved_conflict"); goPrevUnsolvedConflict->setToolTip(goPrevUnsolvedConflict->text() + includeWhitespace); goNextUnsolvedConflict = KDiff3::createAction(i18n("Go to Next Unsolved Conflict"), QIcon(QPixmap(nextunsolved)), i18n("Next\nUnsolved"), this, SLOT(slotGoNextUnsolvedConflict()), ac, "go_next_unsolved_conflict"); goNextUnsolvedConflict->setToolTip(goNextUnsolvedConflict->text() + includeWhitespace); chooseA = KDiff3::createAction(i18n("Select Line(s) From A"), QIcon(QPixmap(iconA)), i18n("Choose\nA"), QKeySequence(Qt::CTRL + Qt::Key_1), this, SLOT(slotChooseA()), ac, "merge_choose_a"); chooseB = KDiff3::createAction(i18n("Select Line(s) From B"), QIcon(QPixmap(iconB)), i18n("Choose\nB"), QKeySequence(Qt::CTRL + Qt::Key_2), this, SLOT(slotChooseB()), ac, "merge_choose_b"); chooseC = KDiff3::createAction(i18n("Select Line(s) From C"), QIcon(QPixmap(iconC)), i18n("Choose\nC"), QKeySequence(Qt::CTRL + Qt::Key_3), this, SLOT(slotChooseC()), ac, "merge_choose_c"); autoAdvance = KDiff3::createAction(i18n("Automatically Go to Next Unsolved Conflict After Source Selection"), QIcon(QPixmap(autoadvance)), i18n("Auto\nNext"), this, SLOT(slotAutoAdvanceToggled()), ac, "merge_autoadvance"); showWhiteSpaceCharacters = KDiff3::createAction(i18n("Show Space && Tabulator Characters"), QIcon(QPixmap(showwhitespacechars)), i18n("White\nCharacters"), this, SLOT(slotShowWhiteSpaceToggled()), ac, "diff_show_whitespace_characters"); showWhiteSpace = KDiff3::createAction(i18n("Show White Space"), QIcon(QPixmap(showwhitespace)), i18n("White\nDeltas"), this, SLOT(slotShowWhiteSpaceToggled()), ac, "diff_show_whitespace"); showLineNumbers = KDiff3::createAction(i18n("Show Line Numbers"), QIcon(QPixmap(showlinenumbers)), i18n("Line\nNumbers"), this, SLOT(slotShowLineNumbersToggled()), ac, "diff_showlinenumbers"); chooseAEverywhere = KDiff3::createAction(i18n("Choose A Everywhere"), QKeySequence(Qt::CTRL + Qt::SHIFT + Qt::Key_1), this, SLOT(slotChooseAEverywhere()), ac, "merge_choose_a_everywhere"); chooseBEverywhere = KDiff3::createAction(i18n("Choose B Everywhere"), QKeySequence(Qt::CTRL + Qt::SHIFT + Qt::Key_2), this, SLOT(slotChooseBEverywhere()), ac, "merge_choose_b_everywhere"); chooseCEverywhere = KDiff3::createAction(i18n("Choose C Everywhere"), QKeySequence(Qt::CTRL + Qt::SHIFT + Qt::Key_3), this, SLOT(slotChooseCEverywhere()), ac, "merge_choose_c_everywhere"); chooseAForUnsolvedConflicts = KDiff3::createAction(i18n("Choose A for All Unsolved Conflicts"), this, SLOT(slotChooseAForUnsolvedConflicts()), ac, "merge_choose_a_for_unsolved_conflicts"); chooseBForUnsolvedConflicts = KDiff3::createAction(i18n("Choose B for All Unsolved Conflicts"), this, SLOT(slotChooseBForUnsolvedConflicts()), ac, "merge_choose_b_for_unsolved_conflicts"); chooseCForUnsolvedConflicts = KDiff3::createAction(i18n("Choose C for All Unsolved Conflicts"), this, SLOT(slotChooseCForUnsolvedConflicts()), ac, "merge_choose_c_for_unsolved_conflicts"); chooseAForUnsolvedWhiteSpaceConflicts = KDiff3::createAction(i18n("Choose A for All Unsolved Whitespace Conflicts"), this, SLOT(slotChooseAForUnsolvedWhiteSpaceConflicts()), ac, "merge_choose_a_for_unsolved_whitespace_conflicts"); chooseBForUnsolvedWhiteSpaceConflicts = KDiff3::createAction(i18n("Choose B for All Unsolved Whitespace Conflicts"), this, SLOT(slotChooseBForUnsolvedWhiteSpaceConflicts()), ac, "merge_choose_b_for_unsolved_whitespace_conflicts"); chooseCForUnsolvedWhiteSpaceConflicts = KDiff3::createAction(i18n("Choose C for All Unsolved Whitespace Conflicts"), this, SLOT(slotChooseCForUnsolvedWhiteSpaceConflicts()), ac, "merge_choose_c_for_unsolved_whitespace_conflicts"); autoSolve = KDiff3::createAction(i18n("Automatically Solve Simple Conflicts"), this, SLOT(slotAutoSolve()), ac, "merge_autosolve"); unsolve = KDiff3::createAction(i18n("Set Deltas to Conflicts"), this, SLOT(slotUnsolve()), ac, "merge_autounsolve"); mergeRegExp = KDiff3::createAction(i18n("Run Regular Expression Auto Merge"), this, SLOT(slotRegExpAutoMerge()), ac, "merge_regexp_automerge"); mergeHistory = KDiff3::createAction(i18n("Automatically Solve History Conflicts"), this, SLOT(slotMergeHistory()), ac, "merge_versioncontrol_history"); splitDiff = KDiff3::createAction(i18n("Split Diff At Selection"), this, SLOT(slotSplitDiff()), ac, "merge_splitdiff"); joinDiffs = KDiff3::createAction(i18n("Join Selected Diffs"), this, SLOT(slotJoinDiffs()), ac, "merge_joindiffs"); showWindowA = KDiff3::createAction(i18n("Show Window A"), this, SLOT(slotShowWindowAToggled()), ac, "win_show_a"); showWindowB = KDiff3::createAction(i18n("Show Window B"), this, SLOT(slotShowWindowBToggled()), ac, "win_show_b"); showWindowC = KDiff3::createAction(i18n("Show Window C"), this, SLOT(slotShowWindowCToggled()), ac, "win_show_c"); overviewModeNormal = KDiff3::createAction(i18n("Normal Overview"), this, SLOT(slotOverviewNormal()), ac, "diff_overview_normal"); overviewModeAB = KDiff3::createAction(i18n("A vs. B Overview"), this, SLOT(slotOverviewAB()), ac, "diff_overview_ab"); overviewModeAC = KDiff3::createAction(i18n("A vs. C Overview"), this, SLOT(slotOverviewAC()), ac, "diff_overview_ac"); overviewModeBC = KDiff3::createAction(i18n("B vs. C Overview"), this, SLOT(slotOverviewBC()), ac, "diff_overview_bc"); wordWrap = KDiff3::createAction(i18n("Word Wrap Diff Windows"), this, SLOT(slotWordWrapToggled()), ac, "diff_wordwrap"); addManualDiffHelp = KDiff3::createAction(i18n("Add Manual Diff Alignment"), QKeySequence(Qt::CTRL + Qt::Key_Y), this, SLOT(slotAddManualDiffHelp()), ac, "diff_add_manual_diff_help"); clearManualDiffHelpList = KDiff3::createAction(i18n("Clear All Manual Diff Alignments"), QKeySequence(Qt::CTRL + Qt::SHIFT + Qt::Key_Y), this, SLOT(slotClearManualDiffHelpList()), ac, "diff_clear_manual_diff_help_list"); winFocusNext = KDiff3::createAction(i18n("Focus Next Window"), QKeySequence(Qt::ALT + Qt::Key_Right), this, SLOT(slotWinFocusNext()), ac, "win_focus_next"); winFocusPrev = KDiff3::createAction(i18n("Focus Prev Window"), QKeySequence(Qt::ALT + Qt::Key_Left), this, SLOT(slotWinFocusPrev()), ac, "win_focus_prev"); winToggleSplitOrientation = KDiff3::createAction(i18n("Toggle Split Orientation"), this, SLOT(slotWinToggleSplitterOrientation()), ac, "win_toggle_split_orientation"); dirShowBoth = KDiff3::createAction(i18n("Dir && Text Split Screen View"), this, SLOT(slotDirShowBoth()), ac, "win_dir_show_both"); dirShowBoth->setChecked(true); dirViewToggle = KDiff3::createAction(i18n("Toggle Between Dir && Text View"), this, SLOT(slotDirViewToggle()), ac, "win_dir_view_toggle"); m_pMergeEditorPopupMenu = new QMenu(this); /* chooseA->plug( m_pMergeEditorPopupMenu ); chooseB->plug( m_pMergeEditorPopupMenu ); chooseC->plug( m_pMergeEditorPopupMenu );*/ m_pMergeEditorPopupMenu->addAction(chooseA); m_pMergeEditorPopupMenu->addAction(chooseB); m_pMergeEditorPopupMenu->addAction(chooseC); } void KDiff3App::showPopupMenu(const QPoint& point) { m_pMergeEditorPopupMenu->popup(point); } void KDiff3App::initStatusBar() { /////////////////////////////////////////////////////////////////// // STATUSBAR if(statusBar() != nullptr) statusBar()->showMessage(i18n("Ready.")); } void KDiff3App::saveOptions(KSharedConfigPtr config) { if(!m_bAutoMode) { if(!isPart()) { m_pOptions->m_bMaximised = m_pKDiff3Shell->isMaximized(); if(!m_pKDiff3Shell->isMaximized() && m_pKDiff3Shell->isVisible()) { m_pOptions->m_geometry = m_pKDiff3Shell->size(); m_pOptions->m_position = m_pKDiff3Shell->pos(); } /* TODO change this option as now KToolbar uses QToolbar positioning style if ( toolBar(MAIN_TOOLBAR_NAME)!=0 ) m_pOptionDialog->m_toolBarPos = (int) toolBar(MAIN_TOOLBAR_NAME)->allowedAreas();*/ } m_pOptionDialog->saveOptions(config); } } bool KDiff3App::queryClose() { saveOptions(KSharedConfig::openConfig()); if(m_bOutputModified) { int result = KMessageBox::warningYesNoCancel(this, i18n("The merge result has not been saved."), i18n("Warning"), KGuiItem(i18n("Save && Quit")), KGuiItem(i18n("Quit Without Saving"))); if(result == KMessageBox::Cancel) return false; else if(result == KMessageBox::Yes) { slotFileSave(); if(m_bOutputModified) { KMessageBox::sorry(this, i18n("Saving the merge result failed."), i18n("Warning")); return false; } } } m_bOutputModified = false; if(m_pDirectoryMergeWindow->isDirectoryMergeInProgress()) { int result = KMessageBox::warningYesNo(this, i18n("You are currently doing a directory merge. Are you sure, you want to abort?"), i18n("Warning"), KStandardGuiItem::quit(), KStandardGuiItem::cont() /* i18n("Continue Merging") */); if(result != KMessageBox::Yes) return false; } return true; } ///////////////////////////////////////////////////////////////////// // SLOT IMPLEMENTATION ///////////////////////////////////////////////////////////////////// void KDiff3App::slotFileSave() { if(m_bDefaultFilename) { slotFileSaveAs(); } else { slotStatusMsg(i18n("Saving file...")); bool bSuccess = m_pMergeResultWindow->saveDocument(m_outputFilename, m_pMergeResultWindowTitle->getEncoding(), m_pMergeResultWindowTitle->getLineEndStyle()); if(bSuccess) { m_bFileSaved = true; m_bOutputModified = false; if(m_bDirCompare) m_pDirectoryMergeWindow->mergeResultSaved(m_outputFilename); } slotStatusMsg(i18n("Ready.")); } } void KDiff3App::slotFileSaveAs() { slotStatusMsg(i18n("Saving file with a new filename...")); QString s = QFileDialog::getSaveFileUrl(this, i18n("Save As..."), QUrl::fromLocalFile(QDir::currentPath()), nullptr).url(QUrl::PreferLocalFile); if(!s.isEmpty()) { m_outputFilename = s; m_pMergeResultWindowTitle->setFileName(m_outputFilename); bool bSuccess = m_pMergeResultWindow->saveDocument(m_outputFilename, m_pMergeResultWindowTitle->getEncoding(), m_pMergeResultWindowTitle->getLineEndStyle()); if(bSuccess) { m_bOutputModified = false; if(m_bDirCompare) m_pDirectoryMergeWindow->mergeResultSaved(m_outputFilename); } //setWindowTitle(url.fileName(),doc->isModified()); m_bDefaultFilename = false; } slotStatusMsg(i18n("Ready.")); } void printDiffTextWindow(MyPainter& painter, const QRect& view, const QString& headerText, DiffTextWindow* pDiffTextWindow, int line, int linesPerPage, QColor fgColor) { QRect clipRect = view; clipRect.setTop(0); painter.setClipRect(clipRect); painter.translate(view.left(), 0); QFontMetrics fm = painter.fontMetrics(); //if ( fm.width(headerText) > view.width() ) { // A simple wrapline algorithm int l = 0; for(int p = 0; p < headerText.length();) { QString s = headerText.mid(p); int i; for(i = 2; i < s.length(); ++i) if(fm.width(s, i) > view.width()) { --i; break; } //QString s2 = s.left(i); painter.drawText(0, l * fm.height() + fm.ascent(), s.left(i)); p += i; ++l; } painter.setPen(fgColor); painter.drawLine(0, view.top() - 2, view.width(), view.top() - 2); } painter.translate(0, view.top()); pDiffTextWindow->print(painter, view, line, linesPerPage); painter.resetMatrix(); } void KDiff3App::slotFilePrint() { if(m_pDiffTextWindow1 == nullptr) return; #ifdef QT_NO_PRINTER slotStatusMsg(i18n("Printing not implemented.")); #endif #ifndef QT_NO_PRINTER QPrinter printer; QPrintDialog printDialog(&printer, this); LineRef firstSelectionD3LIdx = -1; LineRef lastSelectionD3LIdx = -1; m_pDiffTextWindow1->getSelectionRange(&firstSelectionD3LIdx, &lastSelectionD3LIdx, eD3LLineCoords); if(firstSelectionD3LIdx < 0 && m_pDiffTextWindow2) { m_pDiffTextWindow2->getSelectionRange(&firstSelectionD3LIdx, &lastSelectionD3LIdx, eD3LLineCoords); } if(firstSelectionD3LIdx < 0 && m_pDiffTextWindow3) { m_pDiffTextWindow3->getSelectionRange(&firstSelectionD3LIdx, &lastSelectionD3LIdx, eD3LLineCoords); } if(firstSelectionD3LIdx >= 0) { printDialog.addEnabledOption(QPrintDialog::PrintSelection); //printer.setOptionEnabled(QPrinter::PrintSelection,true); printDialog.setPrintRange(QAbstractPrintDialog::Selection); } if(firstSelectionD3LIdx == -1) printDialog.setPrintRange(QAbstractPrintDialog::AllPages); //printDialog.setMinMax(0,0); printDialog.setFromTo(0, 0); int currentFirstLine = m_pDiffTextWindow1->getFirstLine(); int currentFirstD3LIdx = m_pDiffTextWindow1->convertLineToDiff3LineIdx(currentFirstLine); // do some printer initialization printer.setFullPage(false); // initialize the printer using the print dialog if(printDialog.exec() == QDialog::Accepted) { slotStatusMsg(i18n("Printing...")); // create a painter to paint on the printer object MyPainter painter(&printer, m_pOptions->m_bRightToLeftLanguage, width(), fontMetrics().width('W')); QPaintDevice* pPaintDevice = painter.device(); int dpiy = pPaintDevice->logicalDpiY(); int columnDistance = (int)((0.5 / 2.54) * dpiy); // 0.5 cm between the columns int columns = m_bTripleDiff ? 3 : 2; int columnWidth = (pPaintDevice->width() - (columns - 1) * columnDistance) / columns; QFont f = m_pOptions->m_font; f.setPointSizeF(f.pointSizeF() - 1); // Print with slightly smaller font. painter.setFont(f); QFontMetrics fm = painter.fontMetrics(); QString topLineText = i18n("Top line"); //int headerWidth = fm.width( m_sd1.getAliasName() + ", "+topLineText+": 01234567" ); int headerLines = fm.width(m_sd1.getAliasName() + ", " + topLineText + ": 01234567") / columnWidth + 1; int headerMargin = headerLines * fm.height() + 3; // Text + one horizontal line int footerMargin = fm.height() + 3; QRect view(0, headerMargin, pPaintDevice->width(), pPaintDevice->height() - (headerMargin + footerMargin)); QRect view1(0 * (columnWidth + columnDistance), view.top(), columnWidth, view.height()); QRect view2(1 * (columnWidth + columnDistance), view.top(), columnWidth, view.height()); QRect view3(2 * (columnWidth + columnDistance), view.top(), columnWidth, view.height()); int linesPerPage = view.height() / fm.lineSpacing(); QEventLoop eventLoopForPrinting; m_pEventLoopForPrinting = &eventLoopForPrinting; if(m_pOptions->m_bWordWrap) { // For printing the lines are wrapped differently (this invalidates the first line) recalcWordWrap(columnWidth); m_pEventLoopForPrinting->exec(); } LineRef totalNofLines = max2(m_pDiffTextWindow1->getNofLines(), m_pDiffTextWindow2->getNofLines()); if(m_bTripleDiff && m_pDiffTextWindow3) totalNofLines = max2(totalNofLines, m_pDiffTextWindow3->getNofLines()); QList pageList; // = printer.pageList(); bool bPrintCurrentPage = false; bool bFirstPrintedPage = false; bool bPrintSelection = false; int totalNofPages = (totalNofLines + linesPerPage - 1) / linesPerPage; LineRef line = -1; LineRef selectionEndLine = -1; if(printer.printRange() == QPrinter::AllPages) { pageList.clear(); for(int i = 0; i < totalNofPages; ++i) { pageList.push_back(i + 1); } } else if(printer.printRange() == QPrinter::PageRange) { pageList.clear(); for(int i = printer.fromPage(); i <= printer.toPage(); ++i) { pageList.push_back(i); } } if(printer.printRange() == QPrinter::Selection) { bPrintSelection = true; if(firstSelectionD3LIdx >= 0) { line = m_pDiffTextWindow1->convertDiff3LineIdxToLine(firstSelectionD3LIdx); selectionEndLine = m_pDiffTextWindow1->convertDiff3LineIdxToLine(lastSelectionD3LIdx + 1); totalNofPages = (selectionEndLine - line + linesPerPage - 1) / linesPerPage; } } int page = 1; ProgressProxy pp; pp.setMaxNofSteps(totalNofPages); QList::iterator pageListIt = pageList.begin(); for(;;) { pp.setInformation(i18n("Printing page %1 of %2", page, totalNofPages), false); pp.setCurrent(page - 1); if(pp.wasCancelled()) { printer.abort(); break; } if(!bPrintSelection) { if(pageListIt == pageList.end()) break; page = *pageListIt; line = (page - 1) * linesPerPage; if(page == 10000) { // This means "Print the current page" bPrintCurrentPage = true; // Detect the first visible line in the window. line = m_pDiffTextWindow1->convertDiff3LineIdxToLine(currentFirstD3LIdx); } } else { if(line >= selectionEndLine) { break; } else { if(selectionEndLine - line < linesPerPage) linesPerPage = selectionEndLine - line; } } if(line >= 0 && line < totalNofLines) { if(bFirstPrintedPage) printer.newPage(); painter.setClipping(true); painter.setPen(m_pOptions->m_colorA); QString headerText1 = m_sd1.getAliasName() + ", " + topLineText + ": " + QString::number(m_pDiffTextWindow1->calcTopLineInFile(line) + 1); printDiffTextWindow(painter, view1, headerText1, m_pDiffTextWindow1, line, linesPerPage, m_pOptions->m_fgColor); painter.setPen(m_pOptions->m_colorB); QString headerText2 = m_sd2.getAliasName() + ", " + topLineText + ": " + QString::number(m_pDiffTextWindow2->calcTopLineInFile(line) + 1); printDiffTextWindow(painter, view2, headerText2, m_pDiffTextWindow2, line, linesPerPage, m_pOptions->m_fgColor); if(m_bTripleDiff && m_pDiffTextWindow3) { painter.setPen(m_pOptions->m_colorC); QString headerText3 = m_sd3.getAliasName() + ", " + topLineText + ": " + QString::number(m_pDiffTextWindow3->calcTopLineInFile(line) + 1); printDiffTextWindow(painter, view3, headerText3, m_pDiffTextWindow3, line, linesPerPage, m_pOptions->m_fgColor); } painter.setClipping(false); painter.setPen(m_pOptions->m_fgColor); painter.drawLine(0, view.bottom() + 3, view.width(), view.bottom() + 3); QString s = bPrintCurrentPage ? QString("") : QString::number(page) + "/" + QString::number(totalNofPages); if(bPrintSelection) s += i18n(" (Selection)"); painter.drawText((view.right() - painter.fontMetrics().width(s)) / 2, view.bottom() + painter.fontMetrics().ascent() + 5, s); bFirstPrintedPage = true; } if(bPrintSelection) { line += linesPerPage; ++page; } else { ++pageListIt; } } painter.end(); if(m_pOptions->m_bWordWrap) { recalcWordWrap(); m_pEventLoopForPrinting->exec(); m_pDiffVScrollBar->setValue(m_pDiffTextWindow1->convertDiff3LineIdxToLine(currentFirstD3LIdx)); } slotStatusMsg(i18n("Printing completed.")); } else { slotStatusMsg(i18n("Printing aborted.")); } #endif } void KDiff3App::slotFileQuit() { slotStatusMsg(i18n("Exiting...")); if(!queryClose()) return; // Don't quit QApplication::exit(isFileSaved() || isDirComparison() ? 0 : 1); } void KDiff3App::slotViewToolBar() { Q_ASSERT(viewToolBar != nullptr); slotStatusMsg(i18n("Toggling toolbar...")); m_pOptions->m_bShowToolBar = viewToolBar->isChecked(); /////////////////////////////////////////////////////////////////// // turn Toolbar on or off if(toolBar(MAIN_TOOLBAR_NAME) != nullptr) { if(!m_pOptions->m_bShowToolBar) { toolBar(MAIN_TOOLBAR_NAME)->hide(); } else { toolBar(MAIN_TOOLBAR_NAME)->show(); } } slotStatusMsg(i18n("Ready.")); } void KDiff3App::slotViewStatusBar() { slotStatusMsg(i18n("Toggle the statusbar...")); m_pOptions->m_bShowStatusBar = viewStatusBar->isChecked(); /////////////////////////////////////////////////////////////////// //turn Statusbar on or off if(statusBar() != nullptr) { if(!viewStatusBar->isChecked()) { statusBar()->hide(); } else { statusBar()->show(); } } slotStatusMsg(i18n("Ready.")); } void KDiff3App::slotStatusMsg(const QString& text) { /////////////////////////////////////////////////////////////////// // change status message permanently if(statusBar() != nullptr) { statusBar()->clearMessage(); statusBar()->showMessage(text); } } //#include "kdiff3.moc" diff --git a/src/optiondialog.cpp b/src/optiondialog.cpp index 906f42b..43011a2 100644 --- a/src/optiondialog.cpp +++ b/src/optiondialog.cpp @@ -1,1903 +1,1904 @@ /* * kdiff3 - Text Diff And Merge Tool * Copyright (C) 2002-2009 Joachim Eibl, joachim.eibl at gmx.de * * 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. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Steet, Fifth Floor, Boston, MA 02110-1301, USA. * */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "diff.h" #include "optiondialog.h" #include "smalldialogs.h" #define KDIFF3_CONFIG_GROUP "KDiff3 Options" QString s_historyEntryStartRegExpToolTip; QString s_historyEntryStartSortKeyOrderToolTip; QString s_autoMergeRegExpToolTip; QString s_historyStartRegExpToolTip; void OptionDialog::addOptionItem(OptionItem* p) { m_optionItemList.push_back(p); } class OptionItem { public: OptionItem(OptionDialog* pOptionDialog, const QString& saveName) { Q_ASSERT(pOptionDialog != nullptr); pOptionDialog->addOptionItem(this); m_saveName = saveName; m_bPreserved = false; } virtual ~OptionItem() {} virtual void setToDefault() = 0; virtual void setToCurrent() = 0; virtual void apply() = 0; virtual void write(ValueMap*) = 0; virtual void read(ValueMap*) = 0; void doPreserve() { if(!m_bPreserved) { m_bPreserved = true; preserve(); } } void doUnpreserve() { if(m_bPreserved) { unpreserve(); } } QString getSaveName() { return m_saveName; } protected: virtual void preserve() = 0; virtual void unpreserve() = 0; bool m_bPreserved; QString m_saveName; }; template class OptionItemT : public OptionItem { public: OptionItemT(OptionDialog* pOptionDialog, const QString& saveName) : OptionItem(pOptionDialog, saveName) { } protected: void preserve() override { m_preservedVal = *m_pVar; } void unpreserve() override { *m_pVar = m_preservedVal; } T* m_pVar; T m_preservedVal; T m_defaultVal; }; class OptionCheckBox : public QCheckBox, public OptionItemT { public: OptionCheckBox(QString text, bool bDefaultVal, const QString& saveName, bool* pbVar, QWidget* pParent, OptionDialog* pOD) : QCheckBox(text, pParent), OptionItemT(pOD, saveName) { m_pVar = pbVar; m_defaultVal = bDefaultVal; } void setToDefault() override { setChecked(m_defaultVal); } void setToCurrent() override { setChecked(*m_pVar); } void apply() override { *m_pVar = isChecked(); } void write(ValueMap* config) override { config->writeEntry(m_saveName, *m_pVar); } void read(ValueMap* config) override { *m_pVar = config->readBoolEntry(m_saveName, *m_pVar); } private: OptionCheckBox(const OptionCheckBox&); // private copy constructor without implementation }; class OptionRadioButton : public QRadioButton, public OptionItemT { public: OptionRadioButton(QString text, bool bDefaultVal, const QString& saveName, bool* pbVar, QWidget* pParent, OptionDialog* pOD) : QRadioButton(text, pParent), OptionItemT(pOD, saveName) { m_pVar = pbVar; m_defaultVal = bDefaultVal; } void setToDefault() override { setChecked(m_defaultVal); } void setToCurrent() override { setChecked(*m_pVar); } void apply() override { *m_pVar = isChecked(); } void write(ValueMap* config) override { config->writeEntry(m_saveName, *m_pVar); } void read(ValueMap* config) override { *m_pVar = config->readBoolEntry(m_saveName, *m_pVar); } private: OptionRadioButton(const OptionRadioButton&); // private copy constructor without implementation }; template class OptionT : public OptionItemT { public: OptionT(const T& defaultVal, const QString& saveName, T* pVar, OptionDialog* pOD) : OptionItemT(pOD, saveName) { this->m_pVar = pVar; *this->m_pVar = defaultVal; } OptionT(const QString& saveName, T* pVar, OptionDialog* pOD) : OptionItemT(pOD, saveName) { this->m_pVar = pVar; } void setToDefault() override {} void setToCurrent() override {} void apply() override {} void write(ValueMap* vm) override { writeEntry(vm, this->m_saveName, *this->m_pVar); } void read(ValueMap* vm) override { *this->m_pVar = vm->readEntry(this->m_saveName, *this->m_pVar); } private: OptionT(const OptionT&); // private copy constructor without implementation }; template void writeEntry(ValueMap* vm, const QString& saveName, const T& v) { vm->writeEntry(saveName, v); } static void writeEntry(ValueMap* vm, const QString& saveName, const QStringList& v) { vm->writeEntry(saveName, v); } //static void readEntry(ValueMap* vm, const QString& saveName, bool& v ) { v = vm->readBoolEntry( saveName, v ); } //static void readEntry(ValueMap* vm, const QString& saveName, int& v ) { v = vm->readNumEntry( saveName, v ); } //static void readEntry(ValueMap* vm, const QString& saveName, QSize& v ) { v = vm->readSizeEntry( saveName, &v ); } //static void readEntry(ValueMap* vm, const QString& saveName, QPoint& v ) { v = vm->readPointEntry( saveName, &v ); } //static void readEntry(ValueMap* vm, const QString& saveName, QStringList& v ){ v = vm->readListEntry( saveName, QStringList(), '|' ); } typedef OptionT OptionToggleAction; typedef OptionT OptionNum; typedef OptionT OptionPoint; typedef OptionT OptionSize; typedef OptionT OptionStringList; FontChooser::FontChooser(QWidget* pParent) : QGroupBox(pParent) { QVBoxLayout* pLayout = new QVBoxLayout(this); m_pLabel = new QLabel(QString(), this); pLayout->addWidget(m_pLabel); QChar visualTab(0x2192); QChar visualSpace((ushort)0xb7); m_pExampleTextEdit = new QPlainTextEdit(QString("The quick brown fox jumps over the river\n" "but the little red hen escapes with a shiver.\n" ":-)") + visualTab + visualSpace, this); m_pExampleTextEdit->setFont(m_font); m_pExampleTextEdit->setReadOnly(true); pLayout->addWidget(m_pExampleTextEdit); m_pSelectFont = new QPushButton(i18n("Change Font"), this); m_pSelectFont->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed); connect(m_pSelectFont, SIGNAL(clicked()), this, SLOT(slotSelectFont())); pLayout->addWidget(m_pSelectFont); pLayout->setAlignment(m_pSelectFont, Qt::AlignRight); } QFont FontChooser::font() { return m_font; //QFont("courier",10); } void FontChooser::setFont(const QFont& font, bool) { m_font = font; m_pExampleTextEdit->setFont(m_font); m_pLabel->setText(i18n("Font: %1, %2, %3\n\nExample:", m_font.family(), m_font.styleName(), m_font.pointSize())); //update(); } void FontChooser::slotSelectFont() { bool bOk; m_font = QFontDialog::getFont(&bOk, m_font); m_pExampleTextEdit->setFont(m_font); m_pLabel->setText(i18n("Font: %1, %2, %3\n\nExample:", m_font.family(), m_font.styleName(), m_font.pointSize())); } class OptionFontChooser : public FontChooser, public OptionItemT { public: OptionFontChooser(const QFont& defaultVal, const QString& saveName, QFont* pVar, QWidget* pParent, OptionDialog* pOD) : FontChooser(pParent), OptionItemT(pOD, saveName) { m_pVar = pVar; *m_pVar = defaultVal; m_defaultVal = defaultVal; } void setToDefault() override { setFont(m_defaultVal, false); } void setToCurrent() override { setFont(*m_pVar, false); } void apply() override { *m_pVar = font(); } void write(ValueMap* config) override { config->writeEntry(m_saveName, *m_pVar); } void read(ValueMap* config) override { *m_pVar = config->readFontEntry(m_saveName, m_pVar); } private: OptionFontChooser(const OptionToggleAction&); // private copy constructor without implementation }; class OptionColorButton : public KColorButton, public OptionItemT { public: OptionColorButton(QColor defaultVal, const QString& saveName, QColor* pVar, QWidget* pParent, OptionDialog* pOD) : KColorButton(pParent), OptionItemT(pOD, saveName) { m_pVar = pVar; m_defaultVal = defaultVal; } void setToDefault() override { setColor(m_defaultVal); } void setToCurrent() override { setColor(*m_pVar); } void apply() override { *m_pVar = color(); } void write(ValueMap* config) override { config->writeEntry(m_saveName, *m_pVar); } void read(ValueMap* config) override { *m_pVar = config->readColorEntry(m_saveName, m_pVar); } private: OptionColorButton(const OptionColorButton&); // private copy constructor without implementation }; class OptionLineEdit : public QComboBox, public OptionItemT { public: OptionLineEdit(const QString& defaultVal, const QString& saveName, QString* pVar, QWidget* pParent, OptionDialog* pOD) : QComboBox(pParent), OptionItemT(pOD, saveName) { setMinimumWidth(50); setEditable(true); m_pVar = pVar; m_defaultVal = defaultVal; m_list.push_back(defaultVal); insertText(); } void setToDefault() override { setEditText(m_defaultVal); } void setToCurrent() override { setEditText(*m_pVar); } void apply() override { *m_pVar = currentText(); insertText(); } void write(ValueMap* config) override { config->writeEntry(m_saveName, m_list); } void read(ValueMap* config) override { m_list = config->readListEntry(m_saveName, QStringList(m_defaultVal)); if(!m_list.empty()) *m_pVar = m_list.front(); clear(); insertItems(0, m_list); } private: void insertText() { // Check if the text exists. If yes remove it and push it in as first element QString current = currentText(); m_list.removeAll(current); m_list.push_front(current); clear(); if(m_list.size() > 10) m_list.erase(m_list.begin() + 10, m_list.end()); insertItems(0, m_list); } OptionLineEdit(const OptionLineEdit&); // private copy constructor without implementation QStringList m_list; }; #if defined QT_NO_VALIDATOR #error No validator #endif class OptionIntEdit : public QLineEdit, public OptionItemT { public: OptionIntEdit(int defaultVal, const QString& saveName, int* pVar, int rangeMin, int rangeMax, QWidget* pParent, OptionDialog* pOD) : QLineEdit(pParent), OptionItemT(pOD, saveName) { m_pVar = pVar; m_defaultVal = defaultVal; QIntValidator* v = new QIntValidator(this); v->setRange(rangeMin, rangeMax); setValidator(v); } void setToDefault() override { QString s; s.setNum(m_defaultVal); setText(s); } void setToCurrent() override { QString s; s.setNum(*m_pVar); setText(s); } void apply() override { const QIntValidator* v = static_cast(validator()); *m_pVar = minMaxLimiter(text().toInt(), v->bottom(), v->top()); setText(QString::number(*m_pVar)); } void write(ValueMap* config) override { config->writeEntry(m_saveName, *m_pVar); } void read(ValueMap* config) override { *m_pVar = config->readNumEntry(m_saveName, *m_pVar); } private: OptionIntEdit(const OptionIntEdit&); // private copy constructor without implementation }; class OptionComboBox : public QComboBox, public OptionItem { public: OptionComboBox(int defaultVal, const QString& saveName, int* pVarNum, QWidget* pParent, OptionDialog* pOD) : QComboBox(pParent), OptionItem(pOD, saveName) { setMinimumWidth(50); m_pVarNum = pVarNum; m_pVarStr = nullptr; m_defaultVal = defaultVal; setEditable(false); } OptionComboBox(int defaultVal, const QString& saveName, QString* pVarStr, QWidget* pParent, OptionDialog* pOD) : QComboBox(pParent), OptionItem(pOD, saveName) { m_pVarNum = nullptr; m_pVarStr = pVarStr; m_defaultVal = defaultVal; setEditable(false); } void setToDefault() override { setCurrentIndex(m_defaultVal); if(m_pVarStr != nullptr) { *m_pVarStr = currentText(); } } void setToCurrent() override { if(m_pVarNum != nullptr) setCurrentIndex(*m_pVarNum); else setText(*m_pVarStr); } void apply() override { if(m_pVarNum != nullptr) { *m_pVarNum = currentIndex(); } else { *m_pVarStr = currentText(); } } void write(ValueMap* config) override { if(m_pVarStr != nullptr) config->writeEntry(m_saveName, *m_pVarStr); else config->writeEntry(m_saveName, *m_pVarNum); } void read(ValueMap* config) override { if(m_pVarStr != nullptr) setText(config->readEntry(m_saveName, currentText())); else *m_pVarNum = config->readNumEntry(m_saveName, *m_pVarNum); } void preserve() override { if(m_pVarStr != nullptr) { m_preservedStrVal = *m_pVarStr; } else { m_preservedNumVal = *m_pVarNum; } } void unpreserve() override { if(m_pVarStr != nullptr) { *m_pVarStr = m_preservedStrVal; } else { *m_pVarNum = m_preservedNumVal; } } private: OptionComboBox(const OptionIntEdit&); // private copy constructor without implementation int* m_pVarNum; int m_preservedNumVal = 0; QString* m_pVarStr; QString m_preservedStrVal; int m_defaultVal; void setText(const QString& s) { // Find the string in the combobox-list, don't change the value if nothing fits. for(int i = 0; i < count(); ++i) { if(itemText(i) == s) { if(m_pVarNum != nullptr) *m_pVarNum = i; if(m_pVarStr != nullptr) *m_pVarStr = s; setCurrentIndex(i); return; } } } }; class OptionEncodingComboBox : public QComboBox, public OptionItem { Q_OBJECT QVector m_codecVec; QTextCodec** m_ppVarCodec; public: OptionEncodingComboBox(const QString& saveName, QTextCodec** ppVarCodec, QWidget* pParent, OptionDialog* pOD) : QComboBox(pParent), OptionItem(pOD, saveName) { m_ppVarCodec = ppVarCodec; insertCodec(i18n("Unicode, 8 bit"), QTextCodec::codecForName("UTF-8")); insertCodec(i18n("Unicode"), QTextCodec::codecForName("iso-10646-UCS-2")); insertCodec(i18n("Latin1"), QTextCodec::codecForName("iso 8859-1")); // First sort codec names: std::map names; QList mibs = QTextCodec::availableMibs(); foreach(int i, mibs) { QTextCodec* c = QTextCodec::codecForMib(i); if(c != nullptr) names[QString(c->name()).toUpper()] = c; } std::map::iterator it; for(it = names.begin(); it != names.end(); ++it) { insertCodec("", it->second); } this->setToolTip(i18n( "Change this if non-ASCII characters are not displayed correctly.")); } void insertCodec(const QString& visibleCodecName, QTextCodec* c) { if(c != nullptr) { for(int i = 0; i < m_codecVec.size(); ++i) { if(c == m_codecVec[i]) return; // don't insert any codec twice } addItem(visibleCodecName.isEmpty() ? QString(c->name()) : visibleCodecName + " (" + c->name() + ")", (int)m_codecVec.size()); m_codecVec.push_back(c); } } void setToDefault() override { QString defaultName = QTextCodec::codecForLocale()->name(); for(int i = 0; i < count(); ++i) { if(defaultName == itemText(i) && m_codecVec[i] == QTextCodec::codecForLocale()) { setCurrentIndex(i); if(m_ppVarCodec != nullptr) { *m_ppVarCodec = m_codecVec[i]; } return; } } setCurrentIndex(0); if(m_ppVarCodec != nullptr) { *m_ppVarCodec = m_codecVec[0]; } } void setToCurrent() override { if(m_ppVarCodec != nullptr) { for(int i = 0; i < m_codecVec.size(); ++i) { if(*m_ppVarCodec == m_codecVec[i]) { setCurrentIndex(i); break; } } } } void apply() override { if(m_ppVarCodec != nullptr) { *m_ppVarCodec = m_codecVec[currentIndex()]; } } void write(ValueMap* config) override { if(m_ppVarCodec != nullptr) config->writeEntry(m_saveName, QString((*m_ppVarCodec)->name())); } void read(ValueMap* config) override { QString codecName = config->readEntry(m_saveName, QString(m_codecVec[currentIndex()]->name())); for(int i = 0; i < m_codecVec.size(); ++i) { if(codecName == m_codecVec[i]->name()) { setCurrentIndex(i); if(m_ppVarCodec != nullptr) *m_ppVarCodec = m_codecVec[i]; break; } } } protected: void preserve() override { m_preservedVal = currentIndex(); } void unpreserve() override { setCurrentIndex(m_preservedVal); } int m_preservedVal; }; OptionDialog::OptionDialog(bool bShowDirMergeSettings, QWidget* parent, char* name) : // KPageDialog( IconList, i18n("Configure"), Help|Default|Apply|Ok|Cancel, // Ok, parent, name, true /*modal*/, true ) KPageDialog(parent) { setFaceType(List); setWindowTitle(i18n("Configure")); setStandardButtons(QDialogButtonBox::Help | QDialogButtonBox::RestoreDefaults | QDialogButtonBox::Apply | QDialogButtonBox::Ok | QDialogButtonBox::Cancel); // TODO KF5 necessary? setDefaultButton( Ok ); setObjectName(name); setModal(true); //showButtonSeparator( true ); //setHelp( "kdiff3/index.html", QString::null ); setupFontPage(); setupColorPage(); setupEditPage(); setupDiffPage(); setupMergePage(); setupOtherOptions(); if(bShowDirMergeSettings) setupDirectoryMergePage(); setupRegionalPage(); setupIntegrationPage(); //setupKeysPage(); // Initialize all values in the dialog resetToDefaults(); slotApply(); connect(button(QDialogButtonBox::Apply), &QPushButton::clicked, this, &OptionDialog::slotApply); connect(button(QDialogButtonBox::Ok), &QPushButton::clicked, this, &OptionDialog::slotOk); connect(button(QDialogButtonBox::RestoreDefaults), &QPushButton::clicked, this, &OptionDialog::slotDefault); connect(button(QDialogButtonBox::Cancel), &QPushButton::clicked, this, &QDialog::reject); connect(button(QDialogButtonBox::Help), &QPushButton::clicked, this, &OptionDialog::helpRequested); //connect(this, &OptionDialog::applyClicked, this, &OptionDialog::slotApply); //helpClicked() is connected in KDiff3App::KDiff3App -- Really where? //connect(this, &OptionDialog::defaultClicked, this, &OptionDialog::slotDefault); } void OptionDialog::helpRequested() { KHelpClient::invokeHelp(QStringLiteral("kdiff3/index.html"), QString()); } OptionDialog::~OptionDialog(void) { } void OptionDialog::setupOtherOptions() { + //TODO move to Options class new OptionToggleAction(false, "AutoAdvance", &m_options.m_bAutoAdvance, this); new OptionToggleAction(true, "ShowWhiteSpaceCharacters", &m_options.m_bShowWhiteSpaceCharacters, this); new OptionToggleAction(true, "ShowWhiteSpace", &m_options.m_bShowWhiteSpace, this); new OptionToggleAction(false, "ShowLineNumbers", &m_options.m_bShowLineNumbers, this); new OptionToggleAction(true, "HorizDiffWindowSplitting", &m_options.m_bHorizDiffWindowSplitting, this); new OptionToggleAction(false, "WordWrap", &m_options.m_bWordWrap, this); new OptionToggleAction(true, "ShowIdenticalFiles", &m_options.m_bDmShowIdenticalFiles, this); new OptionToggleAction(true, "Show Toolbar", &m_options.m_bShowToolBar, this); new OptionToggleAction(true, "Show Statusbar", &m_options.m_bShowStatusBar, this); /* TODO manage toolbar positioning - new OptionNum( (int)KToolBar::Top, "ToolBarPos", &m_toolBarPos, this ); -*/ + */ + new OptionNum( Qt::TopToolBarArea, "ToolBarPos", (int*)&m_options.m_toolBarPos, this ); new OptionSize(QSize(600, 400), "Geometry", &m_options.m_geometry, this); new OptionPoint(QPoint(0, 22), "Position", &m_options.m_position, this); new OptionToggleAction(false, "WindowStateMaximised", &m_options.m_bMaximised, this); new OptionStringList("RecentAFiles", &m_options.m_recentAFiles, this); new OptionStringList("RecentBFiles", &m_options.m_recentBFiles, this); new OptionStringList("RecentCFiles", &m_options.m_recentCFiles, this); new OptionStringList("RecentOutputFiles", &m_options.m_recentOutputFiles, this); new OptionStringList("RecentEncodings", &m_options.m_recentEncodings, this); } void OptionDialog::setupFontPage(void) { QFrame* page = new QFrame(); KPageWidgetItem* pageItem = new KPageWidgetItem(page, i18n("Font")); pageItem->setHeader(i18n("Editor & Diff Output Font")); //not all themes have this icon if(QIcon::hasThemeIcon(QStringLiteral("font-select-symbolic"))) pageItem->setIcon(QIcon::fromTheme(QStringLiteral("font-select-symbolic"))); else pageItem->setIcon(QIcon::fromTheme(QStringLiteral("preferences-desktop-font"))); addPage(pageItem); QVBoxLayout* topLayout = new QVBoxLayout(page); topLayout->setMargin(5); //requires QT 5.2 or later. static const QFont defaultFont = QFontDatabase::systemFont(QFontDatabase::FixedFont); ; static QFont defaultAppFont = QApplication::font(); OptionFontChooser* pAppFontChooser = new OptionFontChooser(defaultAppFont, "ApplicationFont", &m_options.m_appFont, page, this); topLayout->addWidget(pAppFontChooser); pAppFontChooser->setTitle(i18n("Application font")); OptionFontChooser* pFontChooser = new OptionFontChooser(defaultFont, "Font", &m_options.m_font, page, this); topLayout->addWidget(pFontChooser); pFontChooser->setTitle(i18n("File view font")); QGridLayout* gbox = new QGridLayout(); topLayout->addLayout(gbox); //int line=0; // This currently does not work (see rendering in class DiffTextWindow) //OptionCheckBox* pItalicDeltas = new OptionCheckBox( i18n("Italic font for deltas"), false, "ItalicForDeltas", &m_options.m_bItalicForDeltas, page, this ); //gbox->addWidget( pItalicDeltas, line, 0, 1, 2 ); //pItalicDeltas->setToolTip( i18n( // "Selects the italic version of the font for differences.\n" // "If the font doesn't support italic characters, then this does nothing.") // ); } void OptionDialog::setupColorPage(void) { QFrame* page = new QFrame(); KPageWidgetItem* pageItem = new KPageWidgetItem(page, i18n("Color")); pageItem->setHeader(i18n("Colors Settings")); pageItem->setIcon(QIcon::fromTheme(QStringLiteral("colormanagement"))); addPage(pageItem); QVBoxLayout* topLayout = new QVBoxLayout(page); topLayout->setMargin(5); QGridLayout* gbox = new QGridLayout(); gbox->setColumnStretch(1, 5); topLayout->addLayout(gbox); QLabel* label; int line = 0; int depth = QPixmap::defaultDepth(); bool bLowColor = depth <= 8; label = new QLabel(i18n("Editor and Diff Views:"), page); gbox->addWidget(label, line, 0); QFont f(label->font()); f.setBold(true); label->setFont(f); ++line; OptionColorButton* pFgColor = new OptionColorButton(Qt::black, "FgColor", &m_options.m_fgColor, page, this); label = new QLabel(i18n("Foreground color:"), page); label->setBuddy(pFgColor); gbox->addWidget(label, line, 0); gbox->addWidget(pFgColor, line, 1); ++line; OptionColorButton* pBgColor = new OptionColorButton(Qt::white, "BgColor", &m_options.m_bgColor, page, this); label = new QLabel(i18n("Background color:"), page); label->setBuddy(pBgColor); gbox->addWidget(label, line, 0); gbox->addWidget(pBgColor, line, 1); ++line; OptionColorButton* pDiffBgColor = new OptionColorButton( bLowColor ? QColor(Qt::lightGray) : qRgb(224, 224, 224), "DiffBgColor", &m_options.m_diffBgColor, page, this); label = new QLabel(i18n("Diff background color:"), page); label->setBuddy(pDiffBgColor); gbox->addWidget(label, line, 0); gbox->addWidget(pDiffBgColor, line, 1); ++line; OptionColorButton* pColorA = new OptionColorButton( bLowColor ? qRgb(0, 0, 255) : qRgb(0, 0, 200) /*blue*/, "ColorA", &m_options.m_colorA, page, this); label = new QLabel(i18n("Color A:"), page); label->setBuddy(pColorA); gbox->addWidget(label, line, 0); gbox->addWidget(pColorA, line, 1); ++line; OptionColorButton* pColorB = new OptionColorButton( bLowColor ? qRgb(0, 128, 0) : qRgb(0, 150, 0) /*green*/, "ColorB", &m_options.m_colorB, page, this); label = new QLabel(i18n("Color B:"), page); label->setBuddy(pColorB); gbox->addWidget(label, line, 0); gbox->addWidget(pColorB, line, 1); ++line; OptionColorButton* pColorC = new OptionColorButton( bLowColor ? qRgb(128, 0, 128) : qRgb(150, 0, 150) /*magenta*/, "ColorC", &m_options.m_colorC, page, this); label = new QLabel(i18n("Color C:"), page); label->setBuddy(pColorC); gbox->addWidget(label, line, 0); gbox->addWidget(pColorC, line, 1); ++line; OptionColorButton* pColorForConflict = new OptionColorButton(Qt::red, "ColorForConflict", &m_options.m_colorForConflict, page, this); label = new QLabel(i18n("Conflict color:"), page); label->setBuddy(pColorForConflict); gbox->addWidget(label, line, 0); gbox->addWidget(pColorForConflict, line, 1); ++line; OptionColorButton* pColor = new OptionColorButton( bLowColor ? qRgb(192, 192, 192) : qRgb(220, 220, 100), "CurrentRangeBgColor", &m_options.m_currentRangeBgColor, page, this); label = new QLabel(i18n("Current range background color:"), page); label->setBuddy(pColor); gbox->addWidget(label, line, 0); gbox->addWidget(pColor, line, 1); ++line; pColor = new OptionColorButton( bLowColor ? qRgb(255, 255, 0) : qRgb(255, 255, 150), "CurrentRangeDiffBgColor", &m_options.m_currentRangeDiffBgColor, page, this); label = new QLabel(i18n("Current range diff background color:"), page); label->setBuddy(pColor); gbox->addWidget(label, line, 0); gbox->addWidget(pColor, line, 1); ++line; pColor = new OptionColorButton(qRgb(0xff, 0xd0, 0x80), "ManualAlignmentRangeColor", &m_options.m_manualHelpRangeColor, page, this); label = new QLabel(i18n("Color for manually aligned difference ranges:"), page); label->setBuddy(pColor); gbox->addWidget(label, line, 0); gbox->addWidget(pColor, line, 1); ++line; label = new QLabel(i18n("Directory Comparison View:"), page); gbox->addWidget(label, line, 0); label->setFont(f); ++line; pColor = new OptionColorButton(qRgb(0, 0xd0, 0), "NewestFileColor", &m_options.m_newestFileColor, page, this); label = new QLabel(i18n("Newest file color:"), page); label->setBuddy(pColor); gbox->addWidget(label, line, 0); gbox->addWidget(pColor, line, 1); QString dirColorTip = i18n("Changing this color will only be effective when starting the next directory comparison."); label->setToolTip(dirColorTip); ++line; pColor = new OptionColorButton(qRgb(0xf0, 0, 0), "OldestFileColor", &m_options.m_oldestFileColor, page, this); label = new QLabel(i18n("Oldest file color:"), page); label->setBuddy(pColor); gbox->addWidget(label, line, 0); gbox->addWidget(pColor, line, 1); label->setToolTip(dirColorTip); ++line; pColor = new OptionColorButton(qRgb(0xc0, 0xc0, 0), "MidAgeFileColor", &m_options.m_midAgeFileColor, page, this); label = new QLabel(i18n("Middle age file color:"), page); label->setBuddy(pColor); gbox->addWidget(label, line, 0); gbox->addWidget(pColor, line, 1); label->setToolTip(dirColorTip); ++line; pColor = new OptionColorButton(qRgb(0, 0, 0), "MissingFileColor", &m_options.m_missingFileColor, page, this); label = new QLabel(i18n("Color for missing files:"), page); label->setBuddy(pColor); gbox->addWidget(label, line, 0); gbox->addWidget(pColor, line, 1); label->setToolTip(dirColorTip); ++line; topLayout->addStretch(10); } void OptionDialog::setupEditPage(void) { QFrame* page = new QFrame(); KPageWidgetItem* pageItem = new KPageWidgetItem(page, i18n("Editor")); pageItem->setHeader(i18n("Editor Behavior")); pageItem->setIcon(QIcon::fromTheme(QStringLiteral("accessories-text-editor"))); addPage(pageItem); QVBoxLayout* topLayout = new QVBoxLayout(page); topLayout->setMargin(5); QGridLayout* gbox = new QGridLayout(); gbox->setColumnStretch(1, 5); topLayout->addLayout(gbox); QLabel* label; int line = 0; OptionCheckBox* pReplaceTabs = new OptionCheckBox(i18n("Tab inserts spaces"), false, "ReplaceTabs", &m_options.m_bReplaceTabs, page, this); gbox->addWidget(pReplaceTabs, line, 0, 1, 2); pReplaceTabs->setToolTip(i18n( "On: Pressing tab generates the appropriate number of spaces.\n" "Off: A tab character will be inserted.")); ++line; OptionIntEdit* pTabSize = new OptionIntEdit(8, "TabSize", &m_options.m_tabSize, 1, 100, page, this); label = new QLabel(i18n("Tab size:"), page); label->setBuddy(pTabSize); gbox->addWidget(label, line, 0); gbox->addWidget(pTabSize, line, 1); ++line; OptionCheckBox* pAutoIndentation = new OptionCheckBox(i18n("Auto indentation"), true, "AutoIndentation", &m_options.m_bAutoIndentation, page, this); gbox->addWidget(pAutoIndentation, line, 0, 1, 2); pAutoIndentation->setToolTip(i18n( "On: The indentation of the previous line is used for a new line.\n")); ++line; OptionCheckBox* pAutoCopySelection = new OptionCheckBox(i18n("Auto copy selection"), false, "AutoCopySelection", &m_options.m_bAutoCopySelection, page, this); gbox->addWidget(pAutoCopySelection, line, 0, 1, 2); pAutoCopySelection->setToolTip(i18n( "On: Any selection is immediately written to the clipboard.\n" "Off: You must explicitely copy e.g. via Ctrl-C.")); ++line; label = new QLabel(i18n("Line end style:"), page); gbox->addWidget(label, line, 0); OptionComboBox* pLineEndStyle = new OptionComboBox(eLineEndStyleAutoDetect, "LineEndStyle", &m_options.m_lineEndStyle, page, this); gbox->addWidget(pLineEndStyle, line, 1); pLineEndStyle->insertItem(eLineEndStyleUnix, "Unix"); pLineEndStyle->insertItem(eLineEndStyleDos, "Dos/Windows"); pLineEndStyle->insertItem(eLineEndStyleAutoDetect, "Autodetect"); label->setToolTip(i18n( "Sets the line endings for when an edited file is saved.\n" "DOS/Windows: CR+LF; UNIX: LF; with CR=0D, LF=0A")); ++line; topLayout->addStretch(10); } void OptionDialog::setupDiffPage(void) { QFrame* page = new QFrame(); KPageWidgetItem* pageItem = new KPageWidgetItem(page, i18n("Diff")); pageItem->setHeader(i18n("Diff Settings")); pageItem->setIcon(QIcon::fromTheme(QStringLiteral("text-x-patch"))); addPage(pageItem); QVBoxLayout* topLayout = new QVBoxLayout(page); topLayout->setMargin(5); QGridLayout* gbox = new QGridLayout(); gbox->setColumnStretch(1, 5); topLayout->addLayout(gbox); int line = 0; QLabel* label = nullptr; m_options.m_bPreserveCarriageReturn = false; /* OptionCheckBox* pPreserveCarriageReturn = new OptionCheckBox( i18n("Preserve carriage return"), false, "PreserveCarriageReturn", &m_options.m_bPreserveCarriageReturn, page, this ); gbox->addWidget( pPreserveCarriageReturn, line, 0, 1, 2 ); pPreserveCarriageReturn->setToolTip( i18n( "Show carriage return characters '\\r' if they exist.\n" "Helps to compare files that were modified under different operating systems.") ); ++line; */ OptionCheckBox* pIgnoreNumbers = new OptionCheckBox(i18n("Ignore numbers (treat as white space)"), false, "IgnoreNumbers", &m_options.m_bIgnoreNumbers, page, this); gbox->addWidget(pIgnoreNumbers, line, 0, 1, 2); pIgnoreNumbers->setToolTip(i18n( "Ignore number characters during line matching phase. (Similar to Ignore white space.)\n" "Might help to compare files with numeric data.")); ++line; OptionCheckBox* pIgnoreComments = new OptionCheckBox(i18n("Ignore C/C++ comments (treat as white space)"), false, "IgnoreComments", &m_options.m_bIgnoreComments, page, this); gbox->addWidget(pIgnoreComments, line, 0, 1, 2); pIgnoreComments->setToolTip(i18n("Treat C/C++ comments like white space.")); ++line; OptionCheckBox* pIgnoreCase = new OptionCheckBox(i18n("Ignore case (treat as white space)"), false, "IgnoreCase", &m_options.m_bIgnoreCase, page, this); gbox->addWidget(pIgnoreCase, line, 0, 1, 2); pIgnoreCase->setToolTip(i18n( "Treat case differences like white space changes. ('a'<=>'A')")); ++line; label = new QLabel(i18n("Preprocessor command:"), page); gbox->addWidget(label, line, 0); OptionLineEdit* pLE = new OptionLineEdit("", "PreProcessorCmd", &m_options.m_PreProcessorCmd, page, this); gbox->addWidget(pLE, line, 1); label->setToolTip(i18n("User defined pre-processing. (See the docs for details.)")); ++line; label = new QLabel(i18n("Line-matching preprocessor command:"), page); gbox->addWidget(label, line, 0); pLE = new OptionLineEdit("", "LineMatchingPreProcessorCmd", &m_options.m_LineMatchingPreProcessorCmd, page, this); gbox->addWidget(pLE, line, 1); label->setToolTip(i18n("This pre-processor is only used during line matching.\n(See the docs for details.)")); ++line; OptionCheckBox* pTryHard = new OptionCheckBox(i18n("Try hard (slower)"), true, "TryHard", &m_options.m_bTryHard, page, this); gbox->addWidget(pTryHard, line, 0, 1, 2); pTryHard->setToolTip(i18n( "Enables the --minimal option for the external diff.\n" "The analysis of big files will be much slower.")); ++line; OptionCheckBox* pDiff3AlignBC = new OptionCheckBox(i18n("Align B and C for 3 input files"), false, "Diff3AlignBC", &m_options.m_bDiff3AlignBC, page, this); gbox->addWidget(pDiff3AlignBC, line, 0, 1, 2); pDiff3AlignBC->setToolTip(i18n( "Try to align B and C when comparing or merging three input files.\n" "Not recommended for merging because merge might get more complicated.\n" "(Default is off.)")); ++line; topLayout->addStretch(10); } void OptionDialog::setupMergePage(void) { QFrame* page = new QFrame(); KPageWidgetItem* pageItem = new KPageWidgetItem(page, i18n("Merge")); pageItem->setHeader(i18n("Merge Settings")); pageItem->setIcon(QIcon::fromTheme(QStringLiteral("merge"))); addPage(pageItem); QVBoxLayout* topLayout = new QVBoxLayout(page); topLayout->setMargin(5); QGridLayout* gbox = new QGridLayout(); gbox->setColumnStretch(1, 5); topLayout->addLayout(gbox); int line = 0; QLabel* label = nullptr; label = new QLabel(i18n("Auto advance delay (ms):"), page); gbox->addWidget(label, line, 0); OptionIntEdit* pAutoAdvanceDelay = new OptionIntEdit(500, "AutoAdvanceDelay", &m_options.m_autoAdvanceDelay, 0, 2000, page, this); gbox->addWidget(pAutoAdvanceDelay, line, 1); label->setToolTip(i18n( "When in Auto-Advance mode the result of the current selection is shown \n" "for the specified time, before jumping to the next conflict. Range: 0-2000 ms")); ++line; OptionCheckBox* pShowInfoDialogs = new OptionCheckBox(i18n("Show info dialogs"), true, "ShowInfoDialogs", &m_options.m_bShowInfoDialogs, page, this); gbox->addWidget(pShowInfoDialogs, line, 0, 1, 2); pShowInfoDialogs->setToolTip(i18n("Show a dialog with information about the number of conflicts.")); ++line; label = new QLabel(i18n("White space 2-file merge default:"), page); gbox->addWidget(label, line, 0); OptionComboBox* pWhiteSpace2FileMergeDefault = new OptionComboBox(0, "WhiteSpace2FileMergeDefault", &m_options.m_whiteSpace2FileMergeDefault, page, this); gbox->addWidget(pWhiteSpace2FileMergeDefault, line, 1); pWhiteSpace2FileMergeDefault->insertItem(0, i18n("Manual Choice")); pWhiteSpace2FileMergeDefault->insertItem(1, "A"); pWhiteSpace2FileMergeDefault->insertItem(2, "B"); label->setToolTip(i18n( "Allow the merge algorithm to automatically select an input for " "white-space-only changes.")); ++line; label = new QLabel(i18n("White space 3-file merge default:"), page); gbox->addWidget(label, line, 0); OptionComboBox* pWhiteSpace3FileMergeDefault = new OptionComboBox(0, "WhiteSpace3FileMergeDefault", &m_options.m_whiteSpace3FileMergeDefault, page, this); gbox->addWidget(pWhiteSpace3FileMergeDefault, line, 1); pWhiteSpace3FileMergeDefault->insertItem(0, i18n("Manual Choice")); pWhiteSpace3FileMergeDefault->insertItem(1, "A"); pWhiteSpace3FileMergeDefault->insertItem(2, "B"); pWhiteSpace3FileMergeDefault->insertItem(3, "C"); label->setToolTip(i18n( "Allow the merge algorithm to automatically select an input for " "white-space-only changes.")); ++line; QGroupBox* pGroupBox = new QGroupBox(i18n("Automatic Merge Regular Expression")); gbox->addWidget(pGroupBox, line, 0, 1, 2); ++line; { QGridLayout* gbox = new QGridLayout(pGroupBox); gbox->setColumnStretch(1, 10); int line = 0; label = new QLabel(i18n("Auto merge regular expression:"), page); gbox->addWidget(label, line, 0); m_pAutoMergeRegExpLineEdit = new OptionLineEdit(".*\\$(Version|Header|Date|Author).*\\$.*", "AutoMergeRegExp", &m_options.m_autoMergeRegExp, page, this); gbox->addWidget(m_pAutoMergeRegExpLineEdit, line, 1); s_autoMergeRegExpToolTip = i18n("Regular expression for lines where KDiff3 should automatically choose one source.\n" "When a line with a conflict matches the regular expression then\n" "- if available - C, otherwise B will be chosen."); label->setToolTip(s_autoMergeRegExpToolTip); ++line; OptionCheckBox* pAutoMergeRegExp = new OptionCheckBox(i18n("Run regular expression auto merge on merge start"), false, "RunRegExpAutoMergeOnMergeStart", &m_options.m_bRunRegExpAutoMergeOnMergeStart, page, this); gbox->addWidget(pAutoMergeRegExp, line, 0, 1, 2); pAutoMergeRegExp->setToolTip(i18n("Run the merge for auto merge regular expressions\n" "immediately when a merge starts.\n")); ++line; } pGroupBox = new QGroupBox(i18n("Version Control History Merging")); gbox->addWidget(pGroupBox, line, 0, 1, 2); ++line; { QGridLayout* gbox = new QGridLayout(pGroupBox); gbox->setColumnStretch(1, 10); int line = 0; label = new QLabel(i18n("History start regular expression:"), page); gbox->addWidget(label, line, 0); m_pHistoryStartRegExpLineEdit = new OptionLineEdit(".*\\$Log.*\\$.*", "HistoryStartRegExp", &m_options.m_historyStartRegExp, page, this); gbox->addWidget(m_pHistoryStartRegExpLineEdit, line, 1); s_historyStartRegExpToolTip = i18n("Regular expression for the start of the version control history entry.\n" "Usually this line contains the \"$Log$\" keyword.\n" "Default value: \".*\\$Log.*\\$.*\""); label->setToolTip(s_historyStartRegExpToolTip); ++line; label = new QLabel(i18n("History entry start regular expression:"), page); gbox->addWidget(label, line, 0); // Example line: "** \main\rolle_fsp_dev_008\1 17 Aug 2001 10:45:44 rolle" QString historyEntryStartDefault = "\\s*\\\\main\\\\(\\S+)\\s+" // Start with "\main\" "([0-9]+) " // day "(Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec) " //month "([0-9][0-9][0-9][0-9]) " // year "([0-9][0-9]:[0-9][0-9]:[0-9][0-9])\\s+(.*)"; // time, name m_pHistoryEntryStartRegExpLineEdit = new OptionLineEdit(historyEntryStartDefault, "HistoryEntryStartRegExp", &m_options.m_historyEntryStartRegExp, page, this); gbox->addWidget(m_pHistoryEntryStartRegExpLineEdit, line, 1); s_historyEntryStartRegExpToolTip = i18n("A version control history entry consists of several lines.\n" "Specify the regular expression to detect the first line (without the leading comment).\n" "Use parentheses to group the keys you want to use for sorting.\n" "If left empty, then KDiff3 assumes that empty lines separate history entries.\n" "See the documentation for details."); label->setToolTip(s_historyEntryStartRegExpToolTip); ++line; m_pHistoryMergeSorting = new OptionCheckBox(i18n("History merge sorting"), false, "HistoryMergeSorting", &m_options.m_bHistoryMergeSorting, page, this); gbox->addWidget(m_pHistoryMergeSorting, line, 0, 1, 2); m_pHistoryMergeSorting->setToolTip(i18n("Sort version control history by a key.")); ++line; //QString branch = newHistoryEntry.cap(1); //int day = newHistoryEntry.cap(2).toInt(); //int month = QString("Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec").find(newHistoryEntry.cap(3))/4 + 1; //int year = newHistoryEntry.cap(4).toInt(); //QString time = newHistoryEntry.cap(5); //QString name = newHistoryEntry.cap(6); QString defaultSortKeyOrder = "4,3,2,5,1,6"; //QDate(year,month,day).toString(Qt::ISODate) +" "+ time + " " + branch + " " + name; label = new QLabel(i18n("History entry start sort key order:"), page); gbox->addWidget(label, line, 0); m_pHistorySortKeyOrderLineEdit = new OptionLineEdit(defaultSortKeyOrder, "HistoryEntryStartSortKeyOrder", &m_options.m_historyEntryStartSortKeyOrder, page, this); gbox->addWidget(m_pHistorySortKeyOrderLineEdit, line, 1); s_historyEntryStartSortKeyOrderToolTip = i18n("Each pair of parentheses used in the regular expression for the history start entry\n" "groups a key that can be used for sorting.\n" "Specify the list of keys (that are numbered in order of occurrence\n" "starting with 1) using ',' as separator (e.g. \"4,5,6,1,2,3,7\").\n" "If left empty, then no sorting will be done.\n" "See the documentation for details."); label->setToolTip(s_historyEntryStartSortKeyOrderToolTip); m_pHistorySortKeyOrderLineEdit->setEnabled(false); connect(m_pHistoryMergeSorting, &OptionCheckBox::toggled, m_pHistorySortKeyOrderLineEdit, &OptionLineEdit::setEnabled); ++line; m_pHistoryAutoMerge = new OptionCheckBox(i18n("Merge version control history on merge start"), false, "RunHistoryAutoMergeOnMergeStart", &m_options.m_bRunHistoryAutoMergeOnMergeStart, page, this); gbox->addWidget(m_pHistoryAutoMerge, line, 0, 1, 2); m_pHistoryAutoMerge->setToolTip(i18n("Run version control history automerge on merge start.")); ++line; OptionIntEdit* pMaxNofHistoryEntries = new OptionIntEdit(-1, "MaxNofHistoryEntries", &m_options.m_maxNofHistoryEntries, -1, 1000, page, this); label = new QLabel(i18n("Max number of history entries:"), page); gbox->addWidget(label, line, 0); gbox->addWidget(pMaxNofHistoryEntries, line, 1); pMaxNofHistoryEntries->setToolTip(i18n("Cut off after specified number. Use -1 for infinite number of entries.")); ++line; } QPushButton* pButton = new QPushButton(i18n("Test your regular expressions"), page); gbox->addWidget(pButton, line, 0); connect(pButton, &QPushButton::clicked, this, &OptionDialog::slotHistoryMergeRegExpTester); ++line; label = new QLabel(i18n("Irrelevant merge command:"), page); gbox->addWidget(label, line, 0); OptionLineEdit* pLE = new OptionLineEdit("", "IrrelevantMergeCmd", &m_options.m_IrrelevantMergeCmd, page, this); gbox->addWidget(pLE, line, 1); label->setToolTip(i18n("If specified this script is run after automerge\n" "when no other relevant changes were detected.\n" "Called with the parameters: filename1 filename2 filename3")); ++line; OptionCheckBox* pAutoSaveAndQuit = new OptionCheckBox(i18n("Auto save and quit on merge without conflicts"), false, "AutoSaveAndQuitOnMergeWithoutConflicts", &m_options.m_bAutoSaveAndQuitOnMergeWithoutConflicts, page, this); gbox->addWidget(pAutoSaveAndQuit, line, 0, 1, 2); pAutoSaveAndQuit->setToolTip(i18n("If KDiff3 was started for a file-merge from the command line and all\n" "conflicts are solvable without user interaction then automatically save and quit.\n" "(Similar to command line option \"--auto\".)")); ++line; topLayout->addStretch(10); } void OptionDialog::setupDirectoryMergePage(void) { QFrame* page = new QFrame(); KPageWidgetItem* pageItem = new KPageWidgetItem(page, i18n("Directory")); pageItem->setHeader(i18n("Directory")); pageItem->setIcon(QIcon::fromTheme(QStringLiteral("inode-directory"))); addPage(pageItem); QVBoxLayout* topLayout = new QVBoxLayout(page); topLayout->setMargin(5); QGridLayout* gbox = new QGridLayout(); gbox->setColumnStretch(1, 5); topLayout->addLayout(gbox); int line = 0; OptionCheckBox* pRecursiveDirs = new OptionCheckBox(i18n("Recursive directories"), true, "RecursiveDirs", &m_options.m_bDmRecursiveDirs, page, this); gbox->addWidget(pRecursiveDirs, line, 0, 1, 2); pRecursiveDirs->setToolTip(i18n("Whether to analyze subdirectories or not.")); ++line; QLabel* label = new QLabel(i18n("File pattern(s):"), page); gbox->addWidget(label, line, 0); OptionLineEdit* pFilePattern = new OptionLineEdit("*", "FilePattern", &m_options.m_DmFilePattern, page, this); gbox->addWidget(pFilePattern, line, 1); label->setToolTip(i18n( "Pattern(s) of files to be analyzed. \n" "Wildcards: '*' and '?'\n" "Several Patterns can be specified by using the separator: ';'")); ++line; label = new QLabel(i18n("File-anti-pattern(s):"), page); gbox->addWidget(label, line, 0); OptionLineEdit* pFileAntiPattern = new OptionLineEdit("*.orig;*.o;*.obj;*.rej;*.bak", "FileAntiPattern", &m_options.m_DmFileAntiPattern, page, this); gbox->addWidget(pFileAntiPattern, line, 1); label->setToolTip(i18n( "Pattern(s) of files to be excluded from analysis. \n" "Wildcards: '*' and '?'\n" "Several Patterns can be specified by using the separator: ';'")); ++line; label = new QLabel(i18n("Dir-anti-pattern(s):"), page); gbox->addWidget(label, line, 0); OptionLineEdit* pDirAntiPattern = new OptionLineEdit("CVS;.deps;.svn;.hg;.git", "DirAntiPattern", &m_options.m_DmDirAntiPattern, page, this); gbox->addWidget(pDirAntiPattern, line, 1); label->setToolTip(i18n( "Pattern(s) of directories to be excluded from analysis. \n" "Wildcards: '*' and '?'\n" "Several Patterns can be specified by using the separator: ';'")); ++line; OptionCheckBox* pUseCvsIgnore = new OptionCheckBox(i18n("Use .cvsignore"), false, "UseCvsIgnore", &m_options.m_bDmUseCvsIgnore, page, this); gbox->addWidget(pUseCvsIgnore, line, 0, 1, 2); pUseCvsIgnore->setToolTip(i18n( "Extends the antipattern to anything that would be ignored by CVS.\n" "Via local \".cvsignore\" files this can be directory specific.")); ++line; OptionCheckBox* pFindHidden = new OptionCheckBox(i18n("Find hidden files and directories"), true, "FindHidden", &m_options.m_bDmFindHidden, page, this); gbox->addWidget(pFindHidden, line, 0, 1, 2); #if defined(Q_OS_WIN) pFindHidden->setToolTip(i18n("Finds files and directories with the hidden attribute.")); #else pFindHidden->setToolTip(i18n("Finds files and directories starting with '.'.")); #endif ++line; OptionCheckBox* pFollowFileLinks = new OptionCheckBox(i18n("Follow file links"), false, "FollowFileLinks", &m_options.m_bDmFollowFileLinks, page, this); gbox->addWidget(pFollowFileLinks, line, 0, 1, 2); pFollowFileLinks->setToolTip(i18n( "On: Compare the file the link points to.\n" "Off: Compare the links.")); ++line; OptionCheckBox* pFollowDirLinks = new OptionCheckBox(i18n("Follow directory links"), false, "FollowDirLinks", &m_options.m_bDmFollowDirLinks, page, this); gbox->addWidget(pFollowDirLinks, line, 0, 1, 2); pFollowDirLinks->setToolTip(i18n( "On: Compare the directory the link points to.\n" "Off: Compare the links.")); ++line; //OptionCheckBox* pShowOnlyDeltas = new OptionCheckBox( i18n("List only deltas"),false,"ListOnlyDeltas", &m_options.m_bDmShowOnlyDeltas, page, this ); //gbox->addWidget( pShowOnlyDeltas, line, 0, 1, 2 ); //pShowOnlyDeltas->setToolTip( i18n( // "Files and directories without change will not appear in the list.")); //++line; #if defined(Q_OS_WIN) bool bCaseSensitiveFilenameComparison = false; #else bool bCaseSensitiveFilenameComparison = true; #endif OptionCheckBox* pCaseSensitiveFileNames = new OptionCheckBox(i18n("Case sensitive filename comparison"), bCaseSensitiveFilenameComparison, "CaseSensitiveFilenameComparison", &m_options.m_bDmCaseSensitiveFilenameComparison, page, this); gbox->addWidget(pCaseSensitiveFileNames, line, 0, 1, 2); pCaseSensitiveFileNames->setToolTip(i18n( "The directory comparison will compare files or directories when their names match.\n" "Set this option if the case of the names must match. (Default for Windows is off, otherwise on.)")); ++line; OptionCheckBox* pUnfoldSubdirs = new OptionCheckBox(i18n("Unfold all subdirectories on load"), false, "UnfoldSubdirs", &m_options.m_bDmUnfoldSubdirs, page, this); gbox->addWidget(pUnfoldSubdirs, line, 0, 1, 2); pUnfoldSubdirs->setToolTip(i18n( "On: Unfold all subdirectories when starting a directory diff.\n" "Off: Leave subdirectories folded.")); ++line; OptionCheckBox* pSkipDirStatus = new OptionCheckBox(i18n("Skip directory status report"), false, "SkipDirStatus", &m_options.m_bDmSkipDirStatus, page, this); gbox->addWidget(pSkipDirStatus, line, 0, 1, 2); pSkipDirStatus->setToolTip(i18n( "On: Do not show the Directory Comparison Status.\n" "Off: Show the status dialog on start.")); ++line; QGroupBox* pBG = new QGroupBox(i18n("File Comparison Mode")); gbox->addWidget(pBG, line, 0, 1, 2); QVBoxLayout* pBGLayout = new QVBoxLayout(pBG); OptionRadioButton* pBinaryComparison = new OptionRadioButton(i18n("Binary comparison"), true, "BinaryComparison", &m_options.m_bDmBinaryComparison, pBG, this); pBinaryComparison->setToolTip(i18n("Binary comparison of each file. (Default)")); pBGLayout->addWidget(pBinaryComparison); OptionRadioButton* pFullAnalysis = new OptionRadioButton(i18n("Full analysis"), false, "FullAnalysis", &m_options.m_bDmFullAnalysis, pBG, this); pFullAnalysis->setToolTip(i18n("Do a full analysis and show statistics information in extra columns.\n" "(Slower than a binary comparison, much slower for binary files.)")); pBGLayout->addWidget(pFullAnalysis); OptionRadioButton* pTrustDate = new OptionRadioButton(i18n("Trust the size and modification date (unsafe)"), false, "TrustDate", &m_options.m_bDmTrustDate, pBG, this); pTrustDate->setToolTip(i18n("Assume that files are equal if the modification date and file length are equal.\n" "Files with equal contents but different modification dates will appear as different.\n" "Useful for big directories or slow networks.")); pBGLayout->addWidget(pTrustDate); OptionRadioButton* pTrustDateFallbackToBinary = new OptionRadioButton(i18n("Trust the size and date, but use binary comparison if date does not match (unsafe)"), false, "TrustDateFallbackToBinary", &m_options.m_bDmTrustDateFallbackToBinary, pBG, this); pTrustDateFallbackToBinary->setToolTip(i18n("Assume that files are equal if the modification date and file length are equal.\n" "If the dates are not equal but the sizes are, use binary comparison.\n" "Useful for big directories or slow networks.")); pBGLayout->addWidget(pTrustDateFallbackToBinary); OptionRadioButton* pTrustSize = new OptionRadioButton(i18n("Trust the size (unsafe)"), false, "TrustSize", &m_options.m_bDmTrustSize, pBG, this); pTrustSize->setToolTip(i18n("Assume that files are equal if their file lengths are equal.\n" "Useful for big directories or slow networks when the date is modified during download.")); pBGLayout->addWidget(pTrustSize); ++line; // Some two Dir-options: Affects only the default actions. OptionCheckBox* pSyncMode = new OptionCheckBox(i18n("Synchronize directories"), false, "SyncMode", &m_options.m_bDmSyncMode, page, this); gbox->addWidget(pSyncMode, line, 0, 1, 2); pSyncMode->setToolTip(i18n( "Offers to store files in both directories so that\n" "both directories are the same afterwards.\n" "Works only when comparing two directories without specifying a destination.")); ++line; // Allow white-space only differences to be considered equal OptionCheckBox* pWhiteSpaceDiffsEqual = new OptionCheckBox(i18n("White space differences considered equal"), true, "WhiteSpaceEqual", &m_options.m_bDmWhiteSpaceEqual, page, this); gbox->addWidget(pWhiteSpaceDiffsEqual, line, 0, 1, 2); pWhiteSpaceDiffsEqual->setToolTip(i18n( "If files differ only by white space consider them equal.\n" "This is only active when full analysis is chosen.")); connect(pFullAnalysis, &OptionRadioButton::toggled, pWhiteSpaceDiffsEqual, &OptionCheckBox::setEnabled); pWhiteSpaceDiffsEqual->setEnabled(false); ++line; OptionCheckBox* pCopyNewer = new OptionCheckBox(i18n("Copy newer instead of merging (unsafe)"), false, "CopyNewer", &m_options.m_bDmCopyNewer, page, this); gbox->addWidget(pCopyNewer, line, 0, 1, 2); pCopyNewer->setToolTip(i18n( "Do not look inside, just take the newer file.\n" "(Use this only if you know what you are doing!)\n" "Only effective when comparing two directories.")); ++line; OptionCheckBox* pCreateBakFiles = new OptionCheckBox(i18n("Backup files (.orig)"), true, "CreateBakFiles", &m_options.m_bDmCreateBakFiles, page, this); gbox->addWidget(pCreateBakFiles, line, 0, 1, 2); pCreateBakFiles->setToolTip(i18n( "If a file would be saved over an old file, then the old file\n" "will be renamed with a '.orig' extension instead of being deleted.")); ++line; topLayout->addStretch(10); } /* static void insertCodecs(OptionComboBox* p) { std::multimap m; // Using the multimap for case-insensitive sorting. int i; for(i=0;;++i) { QTextCodec* pCodec = QTextCodec::codecForIndex ( i ); if ( pCodec != 0 ) m.insert( std::make_pair( QString(pCodec->mimeName()).toUpper(), pCodec->mimeName()) ); else break; } p->insertItem( i18n("Auto"), 0 ); std::multimap::iterator mi; for(mi=m.begin(), i=0; mi!=m.end(); ++mi, ++i) p->insertItem(mi->second, i+1); } */ /* // UTF8-Codec that saves a BOM // UTF8-Codec that saves a BOM class Utf8BOMCodec : public QTextCodec { QTextCodec* m_pUtf8Codec; class PublicTextCodec : public QTextCodec { public: QString publicConvertToUnicode ( const char * p, int len, ConverterState* pState ) const { return convertToUnicode( p, len, pState ); } QByteArray publicConvertFromUnicode ( const QChar * input, int number, ConverterState * pState ) const { return convertFromUnicode( input, number, pState ); } }; public: Utf8BOMCodec() { m_pUtf8Codec = QTextCodec::codecForName("UTF-8"); } QByteArray name () const { return "UTF-8-BOM"; } int mibEnum () const { return 2123; } QByteArray convertFromUnicode ( const QChar * input, int number, ConverterState * pState ) const { QByteArray r; if ( pState && pState->state_data[2]==0) // state_data[2] not used by QUtf8::convertFromUnicode (see qutfcodec.cpp) { r += "\xEF\xBB\xBF"; pState->state_data[2]=1; pState->flags |= QTextCodec::IgnoreHeader; } r += ((PublicTextCodec*)m_pUtf8Codec)->publicConvertFromUnicode( input, number, pState ); return r; } QString convertToUnicode ( const char * p, int len, ConverterState* pState ) const { return ((PublicTextCodec*)m_pUtf8Codec)->publicConvertToUnicode( p, len, pState ); } }; */ void OptionDialog::setupRegionalPage(void) { /* TODO: What is this line supposed to do besides leak memmory? Intruduced as is in .91 no explaination new Utf8BOMCodec(); */ QFrame* page = new QFrame(); KPageWidgetItem* pageItem = new KPageWidgetItem(page, i18n("Regional Settings")); pageItem->setHeader(i18n("Regional Settings")); pageItem->setIcon(QIcon::fromTheme(QStringLiteral("preferences-desktop-locale"))); addPage(pageItem); QVBoxLayout* topLayout = new QVBoxLayout(page); topLayout->setMargin(5); QGridLayout* gbox = new QGridLayout(); gbox->setColumnStretch(1, 5); topLayout->addLayout(gbox); int line = 0; QLabel* label; m_pSameEncoding = new OptionCheckBox(i18n("Use the same encoding for everything:"), true, "SameEncoding", &m_options.m_bSameEncoding, page, this); gbox->addWidget(m_pSameEncoding, line, 0, 1, 2); m_pSameEncoding->setToolTip(i18n( "Enable this allows to change all encodings by changing the first only.\n" "Disable this if different individual settings are needed.")); ++line; label = new QLabel(i18n("Note: Local Encoding is \"%1\"", QLatin1String(QTextCodec::codecForLocale()->name())), page); gbox->addWidget(label, line, 0); ++line; label = new QLabel(i18n("File Encoding for A:"), page); gbox->addWidget(label, line, 0); m_pEncodingAComboBox = new OptionEncodingComboBox("EncodingForA", &m_options.m_pEncodingA, page, this); gbox->addWidget(m_pEncodingAComboBox, line, 1); QString autoDetectToolTip = i18n( "If enabled then Unicode (UTF-16 or UTF-8) encoding will be detected.\n" "If the file is not Unicode then the selected encoding will be used as fallback.\n" "(Unicode detection depends on the first bytes of a file.)"); m_pAutoDetectUnicodeA = new OptionCheckBox(i18n("Auto Detect Unicode"), true, "AutoDetectUnicodeA", &m_options.m_bAutoDetectUnicodeA, page, this); gbox->addWidget(m_pAutoDetectUnicodeA, line, 2); m_pAutoDetectUnicodeA->setToolTip(autoDetectToolTip); ++line; label = new QLabel(i18n("File Encoding for B:"), page); gbox->addWidget(label, line, 0); m_pEncodingBComboBox = new OptionEncodingComboBox("EncodingForB", &m_options.m_pEncodingB, page, this); gbox->addWidget(m_pEncodingBComboBox, line, 1); m_pAutoDetectUnicodeB = new OptionCheckBox(i18n("Auto Detect Unicode"), true, "AutoDetectUnicodeB", &m_options.m_bAutoDetectUnicodeB, page, this); gbox->addWidget(m_pAutoDetectUnicodeB, line, 2); m_pAutoDetectUnicodeB->setToolTip(autoDetectToolTip); ++line; label = new QLabel(i18n("File Encoding for C:"), page); gbox->addWidget(label, line, 0); m_pEncodingCComboBox = new OptionEncodingComboBox("EncodingForC", &m_options.m_pEncodingC, page, this); gbox->addWidget(m_pEncodingCComboBox, line, 1); m_pAutoDetectUnicodeC = new OptionCheckBox(i18n("Auto Detect Unicode"), true, "AutoDetectUnicodeC", &m_options.m_bAutoDetectUnicodeC, page, this); gbox->addWidget(m_pAutoDetectUnicodeC, line, 2); m_pAutoDetectUnicodeC->setToolTip(autoDetectToolTip); ++line; label = new QLabel(i18n("File Encoding for Merge Output and Saving:"), page); gbox->addWidget(label, line, 0); m_pEncodingOutComboBox = new OptionEncodingComboBox("EncodingForOutput", &m_options.m_pEncodingOut, page, this); gbox->addWidget(m_pEncodingOutComboBox, line, 1); m_pAutoSelectOutEncoding = new OptionCheckBox(i18n("Auto Select"), true, "AutoSelectOutEncoding", &m_options.m_bAutoSelectOutEncoding, page, this); gbox->addWidget(m_pAutoSelectOutEncoding, line, 2); m_pAutoSelectOutEncoding->setToolTip(i18n( "If enabled then the encoding from the input files is used.\n" "In ambiguous cases a dialog will ask the user to choose the encoding for saving.")); ++line; label = new QLabel(i18n("File Encoding for Preprocessor Files:"), page); gbox->addWidget(label, line, 0); m_pEncodingPPComboBox = new OptionEncodingComboBox("EncodingForPP", &m_options.m_pEncodingPP, page, this); gbox->addWidget(m_pEncodingPPComboBox, line, 1); ++line; connect(m_pSameEncoding, &OptionCheckBox::toggled, this, &OptionDialog::slotEncodingChanged); connect(m_pEncodingAComboBox, static_cast(&OptionEncodingComboBox::activated), this, &OptionDialog::slotEncodingChanged); connect(m_pAutoDetectUnicodeA, &OptionCheckBox::toggled, this, &OptionDialog::slotEncodingChanged); connect(m_pAutoSelectOutEncoding, &OptionCheckBox::toggled, this, &OptionDialog::slotEncodingChanged); OptionCheckBox* pRightToLeftLanguage = new OptionCheckBox(i18n("Right To Left Language"), false, "RightToLeftLanguage", &m_options.m_bRightToLeftLanguage, page, this); gbox->addWidget(pRightToLeftLanguage, line, 0, 1, 2); pRightToLeftLanguage->setToolTip(i18n( "Some languages are read from right to left.\n" "This setting will change the viewer and editor accordingly.")); ++line; topLayout->addStretch(10); } // TODO: Integrate this properly in the build system. // Currently breaks compilation on Windows b/c of: // src\ccInstHelper.cpp(15): fatal error C1083: Cannot open include file: 'C:/Programme/NSIS/Contrib/ExDll/exdll.h': No such file or directory #define ENABLE_CC_INTEGRATION 0 #if ENABLE_CC_INTEGRATION #include "ccInstHelper.cpp" #endif void OptionDialog::setupIntegrationPage(void) { QFrame* page = new QFrame(); KPageWidgetItem* pageItem = new KPageWidgetItem(page, i18n("Integration")); pageItem->setHeader(i18n("Integration Settings")); pageItem->setIcon(QIcon::fromTheme(QStringLiteral("utilities-terminal"))); addPage(pageItem); QVBoxLayout* topLayout = new QVBoxLayout(page); topLayout->setMargin(5); QGridLayout* gbox = new QGridLayout(); gbox->setColumnStretch(2, 5); topLayout->addLayout(gbox); int line = 0; QLabel* label; label = new QLabel(i18n("Command line options to ignore:"), page); gbox->addWidget(label, line, 0); OptionLineEdit* pIgnorableCmdLineOptions = new OptionLineEdit("-u;-query;-html;-abort", "IgnorableCmdLineOptions", &m_options.m_ignorableCmdLineOptions, page, this); gbox->addWidget(pIgnorableCmdLineOptions, line, 1, 1, 2); label->setToolTip(i18n( "List of command line options that should be ignored when KDiff3 is used by other tools.\n" "Several values can be specified if separated via ';'\n" "This will suppress the \"Unknown option\" error.")); ++line; OptionCheckBox* pEscapeKeyQuits = new OptionCheckBox(i18n("Quit also via Escape key"), false, "EscapeKeyQuits", &m_options.m_bEscapeKeyQuits, page, this); gbox->addWidget(pEscapeKeyQuits, line, 0, 1, 2); pEscapeKeyQuits->setToolTip(i18n( "Fast method to exit.\n" "For those who are used to using the Escape key.")); ++line; #if ENABLE_CC_INTEGRATION QPushButton* pIntegrateWithClearCase = new QPushButton(i18n("Integrate with ClearCase"), page); gbox->addWidget(pIntegrateWithClearCase, line, 0); pIntegrateWithClearCase->setToolTip(i18n( "Integrate with Rational ClearCase from IBM.\n" "Modifies the \"map\" file in ClearCase subdir \"lib/mgrs\"\n" "(Only enabled when ClearCase \"bin\" directory is in the path.)")); connect(pIntegrateWithClearCase, &QPushButton::clicked, this, &OptionDialog::slotIntegrateWithClearCase); pIntegrateWithClearCase->setEnabled(integrateWithClearCase("existsClearCase", "") != 0); QPushButton* pRemoveClearCaseIntegration = new QPushButton(i18n("Remove ClearCase Integration"), page); gbox->addWidget(pRemoveClearCaseIntegration, line, 1); pRemoveClearCaseIntegration->setToolTip(i18n( "Restore the old \"map\" file from before doing the ClearCase integration.")); connect(pRemoveClearCaseIntegration, &QPushButton::clicked, this, &OptionDialog::slotRemoveClearCaseIntegration); pRemoveClearCaseIntegration->setEnabled(integrateWithClearCase("existsClearCase", "") != 0); ++line; #endif topLayout->addStretch(10); } void OptionDialog::slotIntegrateWithClearCase() { #if ENABLE_CC_INTEGRATION char kdiff3CommandPath[1000]; GetModuleFileNameA(0, kdiff3CommandPath, sizeof(kdiff3CommandPath) - 1); integrateWithClearCase("install", kdiff3CommandPath); #endif } void OptionDialog::slotRemoveClearCaseIntegration() { #if ENABLE_CC_INTEGRATION char kdiff3CommandPath[1000]; GetModuleFileNameA(0, kdiff3CommandPath, sizeof(kdiff3CommandPath) - 1); integrateWithClearCase("uninstall", kdiff3CommandPath); #endif } void OptionDialog::slotEncodingChanged() { if(m_pSameEncoding->isChecked()) { m_pEncodingBComboBox->setEnabled(false); m_pEncodingBComboBox->setCurrentIndex(m_pEncodingAComboBox->currentIndex()); m_pEncodingCComboBox->setEnabled(false); m_pEncodingCComboBox->setCurrentIndex(m_pEncodingAComboBox->currentIndex()); m_pEncodingOutComboBox->setEnabled(false); m_pEncodingOutComboBox->setCurrentIndex(m_pEncodingAComboBox->currentIndex()); m_pEncodingPPComboBox->setEnabled(false); m_pEncodingPPComboBox->setCurrentIndex(m_pEncodingAComboBox->currentIndex()); m_pAutoDetectUnicodeB->setEnabled(false); m_pAutoDetectUnicodeB->setCheckState(m_pAutoDetectUnicodeA->checkState()); m_pAutoDetectUnicodeC->setEnabled(false); m_pAutoDetectUnicodeC->setCheckState(m_pAutoDetectUnicodeA->checkState()); m_pAutoSelectOutEncoding->setEnabled(false); m_pAutoSelectOutEncoding->setCheckState(m_pAutoDetectUnicodeA->checkState()); } else { m_pEncodingBComboBox->setEnabled(true); m_pEncodingCComboBox->setEnabled(true); m_pEncodingOutComboBox->setEnabled(true); m_pEncodingPPComboBox->setEnabled(true); m_pAutoDetectUnicodeB->setEnabled(true); m_pAutoDetectUnicodeC->setEnabled(true); m_pAutoSelectOutEncoding->setEnabled(true); m_pEncodingOutComboBox->setEnabled(m_pAutoSelectOutEncoding->checkState() == Qt::Unchecked); } } void OptionDialog::setupKeysPage(void) { //QVBox *page = addVBoxPage( i18n("Keys"), i18n("KeyDialog" ), // BarIcon("fonts", KIconLoader::SizeMedium ) ); //QVBoxLayout *topLayout = new QVBoxLayout( page, 0, spacingHint() ); // new KFontChooser( page,"font",false/*onlyFixed*/,QStringList(),false,6 ); //m_pKeyDialog=new KKeyDialog( false, 0 ); //topLayout->addWidget( m_pKeyDialog ); } void OptionDialog::slotOk(void) { slotApply(); accept(); } /** Copy the values from the widgets to the public variables.*/ void OptionDialog::slotApply(void) { std::list::iterator i; for(i = m_optionItemList.begin(); i != m_optionItemList.end(); ++i) { (*i)->apply(); } emit applyDone(); #ifdef Q_OS_WIN QString locale = m_options.m_language; if(locale == "Auto" || locale.isEmpty()) locale = QLocale::system().name().left(2); int spacePos = locale.indexOf(' '); if(spacePos > 0) locale = locale.left(spacePos); QSettings settings("HKEY_CURRENT_USER\\Software\\KDiff3\\diff-ext", QSettings::NativeFormat); settings.setValue("Language", locale); #endif } /** Set the default values in the widgets only, while the public variables remain unchanged. */ void OptionDialog::slotDefault() { int result = KMessageBox::warningContinueCancel(this, i18n("This resets all options. Not only those of the current topic.")); if(result == KMessageBox::Cancel) return; else resetToDefaults(); } void OptionDialog::resetToDefaults() { std::list::iterator i; for(i = m_optionItemList.begin(); i != m_optionItemList.end(); ++i) { (*i)->setToDefault(); } slotEncodingChanged(); } /** Initialise the widgets using the values in the public varibles. */ void OptionDialog::setState() { std::list::iterator i; for(i = m_optionItemList.begin(); i != m_optionItemList.end(); ++i) { (*i)->setToCurrent(); } slotEncodingChanged(); } class ConfigValueMap : public ValueMap { private: KConfigGroup m_config; public: explicit ConfigValueMap(const KConfigGroup& config) : m_config(config) {} void writeEntry(const QString& s, const QFont& v) override { m_config.writeEntry(s, v); } void writeEntry(const QString& s, const QColor& v) override { m_config.writeEntry(s, v); } void writeEntry(const QString& s, const QSize& v) override { m_config.writeEntry(s, v); } void writeEntry(const QString& s, const QPoint& v) override { m_config.writeEntry(s, v); } void writeEntry(const QString& s, int v) override { m_config.writeEntry(s, v); } void writeEntry(const QString& s, bool v) override { m_config.writeEntry(s, v); } void writeEntry(const QString& s, const QString& v) override { m_config.writeEntry(s, v); } void writeEntry(const QString& s, const char* v) override { m_config.writeEntry(s, v); } QFont readFontEntry(const QString& s, const QFont* defaultVal) override { return m_config.readEntry(s, *defaultVal); } QColor readColorEntry(const QString& s, const QColor* defaultVal) override { return m_config.readEntry(s, *defaultVal); } QSize readSizeEntry(const QString& s, const QSize* defaultVal) override { return m_config.readEntry(s, *defaultVal); } QPoint readPointEntry(const QString& s, const QPoint* defaultVal) override { return m_config.readEntry(s, *defaultVal); } bool readBoolEntry(const QString& s, bool defaultVal) override { return m_config.readEntry(s, defaultVal); } int readNumEntry(const QString& s, int defaultVal) override { return m_config.readEntry(s, defaultVal); } QString readStringEntry(const QString& s, const QString& defaultVal) override { return m_config.readEntry(s, defaultVal); } void writeEntry(const QString& s, const QStringList& v) override { m_config.writeEntry(s, v); } QStringList readListEntry(const QString& s, const QStringList& def) override { return m_config.readEntry(s, def); } }; void OptionDialog::saveOptions(KSharedConfigPtr config) { // No i18n()-Translations here! ConfigValueMap cvm(config->group(KDIFF3_CONFIG_GROUP)); std::list::iterator i; for(i = m_optionItemList.begin(); i != m_optionItemList.end(); ++i) { (*i)->doUnpreserve(); (*i)->write(&cvm); } } void OptionDialog::readOptions(KSharedConfigPtr config) { // No i18n()-Translations here! ConfigValueMap cvm(config->group(KDIFF3_CONFIG_GROUP)); std::list::iterator i; for(i = m_optionItemList.begin(); i != m_optionItemList.end(); ++i) { (*i)->read(&cvm); } setState(); } QString OptionDialog::parseOptions(const QStringList& optionList) { QString result; QStringList::const_iterator i; for(i = optionList.begin(); i != optionList.end(); ++i) { QString s = *i; int pos = s.indexOf('='); if(pos > 0) // seems not to have a tag { QString key = s.left(pos); QString val = s.mid(pos + 1); std::list::iterator j; bool bFound = false; for(j = m_optionItemList.begin(); j != m_optionItemList.end(); ++j) { if((*j)->getSaveName() == key) { (*j)->doPreserve(); ValueMap config; config.writeEntry(key, val); // Write the value as a string and (*j)->read(&config); // use the internal conversion from string to the needed value. bFound = true; break; } } if(!bFound) { result += "No config item named \"" + key + "\"\n"; } } else { result += "No '=' found in \"" + s + "\"\n"; } } return result; } QString OptionDialog::calcOptionHelp() { ValueMap config; std::list::iterator j; for(j = m_optionItemList.begin(); j != m_optionItemList.end(); ++j) { (*j)->write(&config); } return config.getAsString(); } void OptionDialog::slotHistoryMergeRegExpTester() { RegExpTester dlg(this, s_autoMergeRegExpToolTip, s_historyStartRegExpToolTip, s_historyEntryStartRegExpToolTip, s_historyEntryStartSortKeyOrderToolTip); dlg.init(m_pAutoMergeRegExpLineEdit->currentText(), m_pHistoryStartRegExpLineEdit->currentText(), m_pHistoryEntryStartRegExpLineEdit->currentText(), m_pHistorySortKeyOrderLineEdit->currentText()); if(dlg.exec()) { m_pAutoMergeRegExpLineEdit->setEditText(dlg.autoMergeRegExp()); m_pHistoryStartRegExpLineEdit->setEditText(dlg.historyStartRegExp()); m_pHistoryEntryStartRegExpLineEdit->setEditText(dlg.historyEntryStartRegExp()); m_pHistorySortKeyOrderLineEdit->setEditText(dlg.historySortKeyOrder()); } } #include "optiondialog.moc" diff --git a/src/options.h b/src/options.h index 95295ff..7af94bb 100644 --- a/src/options.h +++ b/src/options.h @@ -1,157 +1,157 @@ /* * kdiff3 - Text Diff And Merge Tool * Copyright (C) 2002-2007 Joachim Eibl, joachim.eibl at gmx.de * * 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. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Steet, Fifth Floor, Boston, MA 02110-1301, USA. * */ #ifndef OPTIONS_H #define OPTIONS_H - +//#include #include #include enum e_LineEndStyle { eLineEndStyleUnix=0, eLineEndStyleDos, eLineEndStyleAutoDetect, eLineEndStyleUndefined, // only one line exists eLineEndStyleConflict // User must resolve manually }; class Options { public: // Some settings are not available in the option dialog: QSize m_geometry; QPoint m_position; bool m_bMaximised; bool m_bShowToolBar; bool m_bShowStatusBar; - int m_toolBarPos; + Qt::ToolBarArea m_toolBarPos; // These are the results of the option dialog. QFont m_font; //bool m_bItalicForDeltas; QFont m_appFont; QColor m_fgColor; QColor m_bgColor; QColor m_diffBgColor; QColor m_colorA; QColor m_colorB; QColor m_colorC; QColor m_colorForConflict; QColor m_currentRangeBgColor; QColor m_currentRangeDiffBgColor; QColor m_oldestFileColor; QColor m_midAgeFileColor; QColor m_newestFileColor; QColor m_missingFileColor; QColor m_manualHelpRangeColor; bool m_bWordWrap; bool m_bReplaceTabs; bool m_bAutoIndentation; int m_tabSize; bool m_bAutoCopySelection; bool m_bSameEncoding; QTextCodec* m_pEncodingA; bool m_bAutoDetectUnicodeA; QTextCodec* m_pEncodingB; bool m_bAutoDetectUnicodeB; QTextCodec* m_pEncodingC; bool m_bAutoDetectUnicodeC; QTextCodec* m_pEncodingOut; bool m_bAutoSelectOutEncoding; QTextCodec* m_pEncodingPP; int m_lineEndStyle; bool m_bPreserveCarriageReturn; bool m_bTryHard; bool m_bShowWhiteSpaceCharacters; bool m_bShowWhiteSpace; bool m_bShowLineNumbers; bool m_bHorizDiffWindowSplitting; bool m_bShowInfoDialogs; bool m_bDiff3AlignBC; int m_whiteSpace2FileMergeDefault; int m_whiteSpace3FileMergeDefault; bool m_bIgnoreCase; bool m_bIgnoreNumbers; bool m_bIgnoreComments; QString m_PreProcessorCmd; QString m_LineMatchingPreProcessorCmd; bool m_bRunRegExpAutoMergeOnMergeStart; QString m_autoMergeRegExp; bool m_bRunHistoryAutoMergeOnMergeStart; QString m_historyStartRegExp; QString m_historyEntryStartRegExp; bool m_bHistoryMergeSorting; QString m_historyEntryStartSortKeyOrder; int m_maxNofHistoryEntries; QString m_IrrelevantMergeCmd; bool m_bAutoSaveAndQuitOnMergeWithoutConflicts; bool m_bAutoAdvance; int m_autoAdvanceDelay; QStringList m_recentAFiles; QStringList m_recentBFiles; QStringList m_recentCFiles; QStringList m_recentEncodings; QStringList m_recentOutputFiles; // Directory Merge options bool m_bDmSyncMode; bool m_bDmRecursiveDirs; bool m_bDmFollowFileLinks; bool m_bDmFollowDirLinks; bool m_bDmFindHidden; bool m_bDmCreateBakFiles; bool m_bDmBinaryComparison; bool m_bDmFullAnalysis; bool m_bDmTrustDate; bool m_bDmTrustDateFallbackToBinary; bool m_bDmTrustSize; bool m_bDmCopyNewer; //bool m_bDmShowOnlyDeltas; bool m_bDmShowIdenticalFiles; bool m_bDmUseCvsIgnore; bool m_bDmWhiteSpaceEqual; bool m_bDmCaseSensitiveFilenameComparison; bool m_bDmUnfoldSubdirs; bool m_bDmSkipDirStatus; QString m_DmFilePattern; QString m_DmFileAntiPattern; QString m_DmDirAntiPattern; QString m_language; bool m_bRightToLeftLanguage; QString m_ignorableCmdLineOptions; bool m_bIntegrateWithClearCase; bool m_bEscapeKeyQuits; }; #endif