diff --git a/src/smalldialogs.cpp b/src/smalldialogs.cpp index a37ac59..c9a495b 100644 --- a/src/smalldialogs.cpp +++ b/src/smalldialogs.cpp @@ -1,625 +1,625 @@ /*************************************************************************** * Copyright (C) 2005-2007 by 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 Street, Fifth Floor, Boston, MA 02110-1301, USA. * ***************************************************************************/ #include "smalldialogs.h" #include "diff.h" #include "options.h" #include "kdiff3.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include // OpenDialog ************************************************************** OpenDialog::OpenDialog( KDiff3App* pParent, const QString& n1, const QString& n2, const QString& n3, bool bMerge, const QString& outputName, Options* pOptions) : QDialog(pParent) { setObjectName("OpenDialog"); setModal(true); m_pOptions = pOptions; QVBoxLayout* v = new QVBoxLayout(this); v->setMargin(5); QGridLayout* h = new QGridLayout(); v->addLayout(h); h->setSpacing(5); h->setColumnStretch(1, 10); QLabel* label = new QLabel(i18n("A (Base):"), this); m_pLineA = new QComboBox(); m_pLineA->setEditable(true); m_pLineA->insertItems(0, m_pOptions->m_recentAFiles); m_pLineA->setEditText(QUrl(n1).toDisplayString()); m_pLineA->setMinimumWidth(200); QPushButton* button = new QPushButton(QIcon::fromTheme("document-new"), i18n("File..."), this); connect(button, &QPushButton::clicked, this, &OpenDialog::selectFileA); QPushButton* button2 = new QPushButton(QIcon::fromTheme("document-open-folder"), i18n("Dir..."), this); connect(button2, &QPushButton::clicked, this, &OpenDialog::selectDirA); connect(m_pLineA, &QComboBox::editTextChanged, this, &OpenDialog::inputFilenameChanged); h->addWidget(label, 0, 0); h->addWidget(m_pLineA, 0, 1); h->addWidget(button, 0, 2); h->addWidget(button2, 0, 3); label = new QLabel("B:", this); m_pLineB = new QComboBox(); m_pLineB->setEditable(true); m_pLineB->insertItems(0, m_pOptions->m_recentBFiles); m_pLineB->setEditText(QUrl(n2).toDisplayString()); m_pLineB->setMinimumWidth(200); button = new QPushButton(QIcon::fromTheme("document-new"), i18n("File..."), this); connect(button, &QPushButton::clicked, this, &OpenDialog::selectFileB); button2 = new QPushButton(QIcon::fromTheme("document-open-folder"), i18n("Dir..."), this); connect(button2, &QPushButton::clicked, this, &OpenDialog::selectDirB); connect(m_pLineB, &QComboBox::editTextChanged, this, &OpenDialog::inputFilenameChanged); h->addWidget(label, 1, 0); h->addWidget(m_pLineB, 1, 1); h->addWidget(button, 1, 2); h->addWidget(button2, 1, 3); label = new QLabel(i18n("C (Optional):"), this); m_pLineC = new QComboBox(); m_pLineC->setEditable(true); m_pLineC->insertItems(0, m_pOptions->m_recentCFiles); m_pLineC->setEditText(QUrl(n3).toDisplayString()); m_pLineC->setMinimumWidth(200); button = new QPushButton(QIcon::fromTheme("document-new"), i18n("File..."), this); connect(button, &QPushButton::clicked, this, &OpenDialog::selectFileC); button2 = new QPushButton(QIcon::fromTheme("document-open-folder"), i18n("Dir..."), this); connect(button2, &QPushButton::clicked, this, &OpenDialog::selectDirC); connect(m_pLineC, &QComboBox::editTextChanged, this, &OpenDialog::inputFilenameChanged); h->addWidget(label, 2, 0); h->addWidget(m_pLineC, 2, 1); h->addWidget(button, 2, 2); h->addWidget(button2, 2, 3); m_pMerge = new QCheckBox(i18n("Merge"), this); h->addWidget(m_pMerge, 3, 0); QHBoxLayout* hl = new QHBoxLayout(); h->addLayout(hl, 3, 1); hl->addStretch(2); button = new QPushButton(i18n("Swap/Copy Names..."), this); //button->setToggleButton(false); hl->addWidget(button); QMenu* m = new QMenu(this); m->addAction(i18n("Swap %1<->%2", i18n("A"), i18n("B"))); m->addAction(i18n("Swap %1<->%2", i18n("B"), i18n("C"))); m->addAction(i18n("Swap %1<->%2", i18n("C"), i18n("A"))); m->addAction(i18n("Copy %1->Output", i18n("A"))); m->addAction(i18n("Copy %1->Output", i18n("B"))); m->addAction(i18n("Copy %1->Output", i18n("C"))); m->addAction(i18n("Swap %1<->Output", i18n("A"))); m->addAction(i18n("Swap %1<->Output", i18n("B"))); m->addAction(i18n("Swap %1<->Output", i18n("C"))); connect(m, &QMenu::triggered, this, &OpenDialog::slotSwapCopyNames); button->setMenu(m); hl->addStretch(2); label = new QLabel(i18n("Output (optional):"), this); m_pLineOut = new QComboBox(); m_pLineOut->setEditable(true); m_pLineOut->insertItems(0, m_pOptions->m_recentOutputFiles); m_pLineOut->setEditText(QUrl(outputName).toDisplayString()); m_pLineOut->setMinimumWidth(200); button = new QPushButton(QIcon::fromTheme("document-new"), i18n("File..."), this); connect(button, &QPushButton::clicked, this, &OpenDialog::selectOutputName); button2 = new QPushButton(QIcon::fromTheme("document-open-folder"), i18n("Dir..."), this); connect(button2, &QPushButton::clicked, this, &OpenDialog::selectOutputDir); connect(m_pMerge, &QCheckBox::stateChanged, this, &OpenDialog::internalSlot); connect(this, &OpenDialog::internalSignal, m_pLineOut, &QComboBox::setEnabled); connect(this, &OpenDialog::internalSignal, button, &QPushButton::setEnabled); connect(this, &OpenDialog::internalSignal, button2, &QPushButton::setEnabled); m_pMerge->setChecked(!bMerge); m_pMerge->setChecked(bMerge); // m_pLineOutput->setEnabled( bMerge ); // button->setEnabled( bMerge ); h->addWidget(label, 4, 0); h->addWidget(m_pLineOut, 4, 1); h->addWidget(button, 4, 2); h->addWidget(button2, 4, 3); h->addItem(new QSpacerItem(200, 0), 0, 1); QDialogButtonBox *box = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel, this); v->addWidget(box); button = box->addButton(i18n("Configure..."), QDialogButtonBox::ActionRole); button->setIcon(QIcon::fromTheme("configure")); connect(button, &QPushButton::clicked, pParent, &KDiff3App::slotConfigure); connect(box, &QDialogButtonBox::accepted, this, &OpenDialog::accept); connect(box, &QDialogButtonBox::rejected, this, &OpenDialog::reject); QSize sh = sizeHint(); setFixedHeight(sh.height()); m_bInputFileNameChanged = false; #ifdef Q_OS_WIN m_pLineA->lineEdit()->installEventFilter(this); m_pLineB->lineEdit()->installEventFilter(this); m_pLineC->lineEdit()->installEventFilter(this); m_pLineOut->lineEdit()->installEventFilter(this); #endif } // Eventfilter: Only needed under Windows. // Without this, files dropped in the line edit have URL-encoding. // This eventfilter decodes the filenames as needed by KDiff3. bool OpenDialog::eventFilter(QObject* o, QEvent* e) { if(e->type() == QEvent::DragEnter) { QDragEnterEvent* d = static_cast(e); d->setAccepted(d->mimeData()->hasUrls()); return true; } if(e->type() == QEvent::Drop) { QDropEvent* d = static_cast(e); if(!d->mimeData()->hasUrls()) return false; QList lst = d->mimeData()->urls(); if(lst.count() > 0) { static_cast(o)->setText(QDir::toNativeSeparators(lst[0].toLocalFile())); static_cast(o)->setFocus(); } return true; } return false; } void OpenDialog::selectURL(QComboBox* pLine, bool bDir, int i, bool bSave) { QString current = pLine->currentText(); QUrl currentUrl; if(current.isEmpty() && i > 3) { current = m_pLineC->currentText(); } if(current.isEmpty()) { current = m_pLineB->currentText(); } if(current.isEmpty()) { current = m_pLineA->currentText(); } currentUrl = QUrl::fromUserInput(current, QString(), QUrl::AssumeLocalFile); QUrl newURL = bDir ? QFileDialog::getExistingDirectoryUrl(this, i18n("Open Directory"), currentUrl) - : bSave ? QFileDialog::getSaveFileUrl(this, i18n("Select Output File"), currentUrl, QLatin1Literal("all/allfiles")) - : QFileDialog::getOpenFileUrl(this, i18n("Open File"), currentUrl, QLatin1Literal("all/allfiles")); + : bSave ? QFileDialog::getSaveFileUrl(this, i18n("Select Output File"), currentUrl, QLatin1Literal("all/allfiles (*)")) + : QFileDialog::getOpenFileUrl(this, i18n("Open File"), currentUrl, QLatin1Literal("all/allfiles (*)")); if(!newURL.isEmpty()) { /* Since we are selecting a directory open in the parent directory not the one selected. */ //QFileDialog::setStartDir( KIO::upUrl( newURL ) ); pLine->setEditText(newURL.url()); } // newURL won't be modified if nothing was selected. } void OpenDialog::selectFileA() { selectURL(m_pLineA, false, 1, false); } void OpenDialog::selectFileB() { selectURL(m_pLineB, false, 2, false); } void OpenDialog::selectFileC() { selectURL(m_pLineC, false, 3, false); } void OpenDialog::selectOutputName() { selectURL(m_pLineOut, false, 4, true); } void OpenDialog::selectDirA() { selectURL(m_pLineA, true, 1, false); } void OpenDialog::selectDirB() { selectURL(m_pLineB, true, 2, false); } void OpenDialog::selectDirC() { selectURL(m_pLineC, true, 3, false); } void OpenDialog::selectOutputDir() { selectURL(m_pLineOut, true, 4, true); } void OpenDialog::internalSlot(int i) { emit internalSignal(i != 0); } // Clear the output-filename when any input-filename changed, // because users forgot to change the output and accidentally overwrote it with // wrong data during a merge. void OpenDialog::inputFilenameChanged() { if(!m_bInputFileNameChanged) { m_bInputFileNameChanged = true; m_pLineOut->clearEditText(); } } static void fixCurrentText(QComboBox* pCB) { QString s = pCB->currentText(); int pos = s.indexOf('\n'); if(pos >= 0) s = s.left(pos); pos = s.indexOf('\r'); if(pos >= 0) s = s.left(pos); pCB->setEditText(s); } void OpenDialog::accept() { int maxNofRecentFiles = 10; fixCurrentText(m_pLineA); QString s = m_pLineA->currentText(); s = QUrl::fromUserInput(s, QString(), QUrl::AssumeLocalFile).toLocalFile(); QStringList* sl = &m_pOptions->m_recentAFiles; // If an item exist, remove it from the list and reinsert it at the beginning. sl->removeAll(s); if(!s.isEmpty()) sl->prepend(s); if(sl->count() > maxNofRecentFiles) sl->erase(sl->begin() + maxNofRecentFiles, sl->end()); fixCurrentText(m_pLineB); s = m_pLineB->currentText(); s = QUrl::fromUserInput(s, QString(), QUrl::AssumeLocalFile).toLocalFile(); sl = &m_pOptions->m_recentBFiles; sl->removeAll(s); if(!s.isEmpty()) sl->prepend(s); if(sl->count() > maxNofRecentFiles) sl->erase(sl->begin() + maxNofRecentFiles, sl->end()); fixCurrentText(m_pLineC); s = m_pLineC->currentText(); s = QUrl::fromUserInput(s, QString(), QUrl::AssumeLocalFile).toLocalFile(); sl = &m_pOptions->m_recentCFiles; sl->removeAll(s); if(!s.isEmpty()) sl->prepend(s); if(sl->count() > maxNofRecentFiles) sl->erase(sl->begin() + maxNofRecentFiles, sl->end()); fixCurrentText(m_pLineOut); s = m_pLineOut->currentText(); s = QUrl::fromUserInput(s, QString(), QUrl::AssumeLocalFile).toLocalFile(); sl = &m_pOptions->m_recentOutputFiles; sl->removeAll(s); if(!s.isEmpty()) sl->prepend(s); if(sl->count() > maxNofRecentFiles) sl->erase(sl->begin() + maxNofRecentFiles, sl->end()); QDialog::accept(); } void OpenDialog::slotSwapCopyNames(QAction* pAction) // id selected in the popup menu { int id = pAction->parentWidget()->actions().indexOf(pAction); QComboBox* cb1 = nullptr; QComboBox* cb2 = nullptr; switch(id) { case 0: cb1 = m_pLineA; cb2 = m_pLineB; break; case 1: cb1 = m_pLineB; cb2 = m_pLineC; break; case 2: cb1 = m_pLineC; cb2 = m_pLineA; break; case 3: cb1 = m_pLineA; cb2 = m_pLineOut; break; case 4: cb1 = m_pLineB; cb2 = m_pLineOut; break; case 5: cb1 = m_pLineC; cb2 = m_pLineOut; break; case 6: cb1 = m_pLineA; cb2 = m_pLineOut; break; case 7: cb1 = m_pLineB; cb2 = m_pLineOut; break; case 8: cb1 = m_pLineC; cb2 = m_pLineOut; break; } if(cb1 && cb2) { QString t1 = cb1->currentText(); QString t2 = cb2->currentText(); cb2->setEditText(t1); if(id <= 2 || id >= 6) { cb1->setEditText(t2); } } } // FindDialog ********************************************* FindDialog::FindDialog(QWidget* pParent) : QDialog(pParent) { QGridLayout* layout = new QGridLayout(this); layout->setMargin(5); layout->setSpacing(5); int line = 0; layout->addWidget(new QLabel(i18n("Search text:"), this), line, 0, 1, 2); ++line; m_pSearchString = new QLineEdit(this); layout->addWidget(m_pSearchString, line, 0, 1, 2); ++line; m_pCaseSensitive = new QCheckBox(i18n("Case sensitive"), this); layout->addWidget(m_pCaseSensitive, line, 1); m_pSearchInA = new QCheckBox(i18n("Search A"), this); layout->addWidget(m_pSearchInA, line, 0); m_pSearchInA->setChecked(true); ++line; m_pSearchInB = new QCheckBox(i18n("Search B"), this); layout->addWidget(m_pSearchInB, line, 0); m_pSearchInB->setChecked(true); ++line; m_pSearchInC = new QCheckBox(i18n("Search C"), this); layout->addWidget(m_pSearchInC, line, 0); m_pSearchInC->setChecked(true); ++line; m_pSearchInOutput = new QCheckBox(i18n("Search output"), this); layout->addWidget(m_pSearchInOutput, line, 0); m_pSearchInOutput->setChecked(true); ++line; QDialogButtonBox *box = new QDialogButtonBox(QDialogButtonBox::Cancel, this); layout->addWidget(box, line, 0, 1, 2); box->addButton(i18n("&Search"), QDialogButtonBox::AcceptRole); connect(box, &QDialogButtonBox::accepted, this, &FindDialog::accept); connect(box, &QDialogButtonBox::rejected, this, &FindDialog::reject); hide(); } void FindDialog::setVisible(bool bVisible) { QDialog::setVisible(bVisible); m_pSearchString->selectAll(); m_pSearchString->setFocus(); } RegExpTester::RegExpTester(QWidget* pParent, const QString& autoMergeRegExpToolTip, const QString& historyStartRegExpToolTip, const QString& historyEntryStartRegExpToolTip, const QString& historySortKeyOrderToolTip) : QDialog(pParent) { int line = 0; setWindowTitle(i18n("Regular Expression Tester")); QGridLayout* pGrid = new QGridLayout(this); pGrid->setSpacing(5); pGrid->setMargin(5); QLabel* l = new QLabel(i18n("Auto merge regular expression:"), this); pGrid->addWidget(l, line, 0); l->setToolTip(autoMergeRegExpToolTip); m_pAutoMergeRegExpEdit = new QLineEdit(this); pGrid->addWidget(m_pAutoMergeRegExpEdit, line, 1); connect(m_pAutoMergeRegExpEdit, &QLineEdit::textChanged, this, &RegExpTester::slotRecalc); ++line; l = new QLabel(i18n("Example auto merge line:"), this); pGrid->addWidget(l, line, 0); l->setToolTip(i18n("To test auto merge, copy a line as used in your files.")); m_pAutoMergeExampleEdit = new QLineEdit(this); pGrid->addWidget(m_pAutoMergeExampleEdit, line, 1); connect(m_pAutoMergeExampleEdit, &QLineEdit::textChanged, this, &RegExpTester::slotRecalc); ++line; l = new QLabel(i18n("Match result:"), this); pGrid->addWidget(l, line, 0); m_pAutoMergeMatchResult = new QLineEdit(this); m_pAutoMergeMatchResult->setReadOnly(true); pGrid->addWidget(m_pAutoMergeMatchResult, line, 1); ++line; pGrid->addItem(new QSpacerItem(100, 20), line, 0); pGrid->setRowStretch(line, 5); ++line; l = new QLabel(i18n("History start regular expression:"), this); pGrid->addWidget(l, line, 0); l->setToolTip(historyStartRegExpToolTip); m_pHistoryStartRegExpEdit = new QLineEdit(this); pGrid->addWidget(m_pHistoryStartRegExpEdit, line, 1); connect(m_pHistoryStartRegExpEdit, &QLineEdit::textChanged, this, &RegExpTester::slotRecalc); ++line; l = new QLabel(i18n("Example history start line (with leading comment):"), this); pGrid->addWidget(l, line, 0); l->setToolTip(i18n("Copy a history start line as used in your files,\n" "including the leading comment.")); m_pHistoryStartExampleEdit = new QLineEdit(this); pGrid->addWidget(m_pHistoryStartExampleEdit, line, 1); connect(m_pHistoryStartExampleEdit, &QLineEdit::textChanged, this, &RegExpTester::slotRecalc); ++line; l = new QLabel(i18n("Match result:"), this); pGrid->addWidget(l, line, 0); m_pHistoryStartMatchResult = new QLineEdit(this); m_pHistoryStartMatchResult->setReadOnly(true); pGrid->addWidget(m_pHistoryStartMatchResult, line, 1); ++line; pGrid->addItem(new QSpacerItem(100, 20), line, 0); pGrid->setRowStretch(line, 5); ++line; l = new QLabel(i18n("History entry start regular expression:"), this); pGrid->addWidget(l, line, 0); l->setToolTip(historyEntryStartRegExpToolTip); m_pHistoryEntryStartRegExpEdit = new QLineEdit(this); pGrid->addWidget(m_pHistoryEntryStartRegExpEdit, line, 1); connect(m_pHistoryEntryStartRegExpEdit, &QLineEdit::textChanged, this, &RegExpTester::slotRecalc); ++line; l = new QLabel(i18n("History sort key order:"), this); pGrid->addWidget(l, line, 0); l->setToolTip(historySortKeyOrderToolTip); m_pHistorySortKeyOrderEdit = new QLineEdit(this); pGrid->addWidget(m_pHistorySortKeyOrderEdit, line, 1); connect(m_pHistorySortKeyOrderEdit, &QLineEdit::textChanged, this, &RegExpTester::slotRecalc); ++line; l = new QLabel(i18n("Example history entry start line (without leading comment):"), this); pGrid->addWidget(l, line, 0); l->setToolTip(i18n("Copy a history entry start line as used in your files,\n" "but omit the leading comment.")); m_pHistoryEntryStartExampleEdit = new QLineEdit(this); pGrid->addWidget(m_pHistoryEntryStartExampleEdit, line, 1); connect(m_pHistoryEntryStartExampleEdit, &QLineEdit::textChanged, this, &RegExpTester::slotRecalc); ++line; l = new QLabel(i18n("Match result:"), this); pGrid->addWidget(l, line, 0); m_pHistoryEntryStartMatchResult = new QLineEdit(this); m_pHistoryEntryStartMatchResult->setReadOnly(true); pGrid->addWidget(m_pHistoryEntryStartMatchResult, line, 1); ++line; l = new QLabel(i18n("Sort key result:"), this); pGrid->addWidget(l, line, 0); m_pHistorySortKeyResult = new QLineEdit(this); m_pHistorySortKeyResult->setReadOnly(true); pGrid->addWidget(m_pHistorySortKeyResult, line, 1); ++line; QDialogButtonBox *box = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel, this); pGrid->addWidget(box, line, 0, 1, 2); connect(box, &QDialogButtonBox::accepted, this, &RegExpTester::accept); connect(box, &QDialogButtonBox::rejected, this, &RegExpTester::reject); resize(800, sizeHint().height()); } void RegExpTester::init(const QString& autoMergeRegExp, const QString& historyStartRegExp, const QString& historyEntryStartRegExp, const QString& historySortKeyOrder) { m_pAutoMergeRegExpEdit->setText(autoMergeRegExp); m_pHistoryStartRegExpEdit->setText(historyStartRegExp); m_pHistoryEntryStartRegExpEdit->setText(historyEntryStartRegExp); m_pHistorySortKeyOrderEdit->setText(historySortKeyOrder); } QString RegExpTester::autoMergeRegExp() { return m_pAutoMergeRegExpEdit->text(); } QString RegExpTester::historyStartRegExp() { return m_pHistoryStartRegExpEdit->text(); } QString RegExpTester::historyEntryStartRegExp() { return m_pHistoryEntryStartRegExpEdit->text(); } QString RegExpTester::historySortKeyOrder() { return m_pHistorySortKeyOrderEdit->text(); } void RegExpTester::slotRecalc() { QRegExp autoMergeRegExp(m_pAutoMergeRegExpEdit->text()); if(autoMergeRegExp.exactMatch(m_pAutoMergeExampleEdit->text())) { m_pAutoMergeMatchResult->setText(i18n("Match success.")); } else { m_pAutoMergeMatchResult->setText(i18n("Match failed.")); } QRegExp historyStartRegExp(m_pHistoryStartRegExpEdit->text()); if(historyStartRegExp.exactMatch(m_pHistoryStartExampleEdit->text())) { m_pHistoryStartMatchResult->setText(i18n("Match success.")); } else { m_pHistoryStartMatchResult->setText(i18n("Match failed.")); } QStringList parenthesesGroups; bool bSuccess = findParenthesesGroups(m_pHistoryEntryStartRegExpEdit->text(), parenthesesGroups); if(!bSuccess) { m_pHistoryEntryStartMatchResult->setText(i18n("Opening and closing parentheses do not match in regular expression.")); m_pHistorySortKeyResult->setText(""); return; } QRegExp historyEntryStartRegExp(m_pHistoryEntryStartRegExpEdit->text()); QString s = m_pHistoryEntryStartExampleEdit->text(); if(historyEntryStartRegExp.exactMatch(s)) { m_pHistoryEntryStartMatchResult->setText(i18n("Match success.")); QString key = calcHistorySortKey(m_pHistorySortKeyOrderEdit->text(), historyEntryStartRegExp, parenthesesGroups); m_pHistorySortKeyResult->setText(key); } else { m_pHistoryEntryStartMatchResult->setText(i18n("Match failed.")); m_pHistorySortKeyResult->setText(""); } } //#include "smalldialogs.moc"