1 /*
2  * KDiff3 - Text Diff And Merge Tool
3  *
4  * SPDX-FileCopyrightText: 2002-2011 Joachim Eibl, joachim.eibl at gmx.de
5  * SPDX-License-Identifier: GPL-2.0-or-later
6 */
7 
8 
9 #include "smalldialogs.h"
10 
11 #include "diff.h"
12 #include "FileNameLineEdit.h"
13 #include "options.h"
14 #include "kdiff3.h"
15 #include "TypeUtils.h"
16 #include "ui_opendialog.h"
17 
18 #include <QCheckBox>
19 #include <QComboBox>
20 #include <QDialogButtonBox>
21 #include <QDir>
22 #include <QDropEvent>
23 #include <QFileDialog>
24 #include <QLabel>
25 #include <QLayout>
26 #include <QLineEdit>
27 #include <QMenu>
28 #include <QMimeData>
29 #include <QPushButton>
30 #include <QToolTip>
31 #include <QUrl>
32 
33 #include <KLocalizedString>
34 
35 // OpenDialog **************************************************************
36 
OpenDialog(KDiff3App * pParent,const QString & n1,const QString & n2,const QString & n3,bool bMerge,const QString & outputName,const QSharedPointer<Options> & pOptions)37 OpenDialog::OpenDialog(
38     KDiff3App* pParent, const QString& n1, const QString& n2, const QString& n3,
39     bool bMerge, const QString& outputName,  const QSharedPointer<Options> &pOptions)
40     : QDialog(pParent)
41 {
42     dialogUi.setupUi(this);
43     setModal(true);
44     m_pOptions = pOptions;
45     //Abort if verticalLayout is not the immediate child of the dialog. This interferes with re-sizing.
46     Q_ASSERT(dialogUi.virticalLayout->parent() == this);
47 
48     dialogUi.lineA->insertItems(0, m_pOptions->m_recentAFiles);
49     dialogUi.lineA->setEditText(n1);
50 
51     QPushButton* button = dialogUi.fileSelectA;
52     chk_connect_a(button, &QPushButton::clicked, this, &OpenDialog::selectFileA);
53     QPushButton* button2 = dialogUi.folderSelectA;
54     chk_connect_a(button2, &QPushButton::clicked, this, &OpenDialog::selectDirA);
55     chk_connect_a(dialogUi.lineA, &QComboBox::editTextChanged, this, &OpenDialog::inputFilenameChanged);
56 
57     dialogUi.lineB->setEditable(true);
58     dialogUi.lineB->insertItems(0, m_pOptions->m_recentBFiles);
59     dialogUi.lineB->setEditText(n2);
60 
61     dialogUi.lineB->setMinimumWidth(200);
62     button = dialogUi.fileSelectB;
63     chk_connect_a(button, &QPushButton::clicked, this, &OpenDialog::selectFileB);
64     button2 = dialogUi.folderSelectB;
65     chk_connect_a(button2, &QPushButton::clicked, this, &OpenDialog::selectDirB);
66     chk_connect_a(dialogUi.lineB, &QComboBox::editTextChanged, this, &OpenDialog::inputFilenameChanged);
67 
68     dialogUi.lineC->setEditable(true);
69     dialogUi.lineC->insertItems(0, m_pOptions->m_recentCFiles);
70     dialogUi.lineC->setEditText(n3);
71     dialogUi.lineC->setMinimumWidth(200);
72     button = dialogUi.fileSelectC;
73     chk_connect_a(button, &QPushButton::clicked, this, &OpenDialog::selectFileC);
74     button2 = dialogUi.folderSelectC;
75     chk_connect_a(button2, &QPushButton::clicked, this, &OpenDialog::selectDirC);
76     chk_connect_a(dialogUi.lineC, &QComboBox::editTextChanged, this, &OpenDialog::inputFilenameChanged);
77 
78     button = dialogUi.swapCopy;
79 
80     QMenu* m = new QMenu(this);
81     m->addAction(i18n("Swap %1<->%2", i18n("A"), i18n("B")));
82     m->addAction(i18n("Swap %1<->%2", i18n("B"), i18n("C")));
83     m->addAction(i18n("Swap %1<->%2", i18n("C"), i18n("A")));
84     m->addAction(i18n("Copy %1->Output", i18n("A")));
85     m->addAction(i18n("Copy %1->Output", i18n("B")));
86     m->addAction(i18n("Copy %1->Output", i18n("C")));
87     m->addAction(i18n("Swap %1<->Output", i18n("A")));
88     m->addAction(i18n("Swap %1<->Output", i18n("B")));
89     m->addAction(i18n("Swap %1<->Output", i18n("C")));
90     chk_connect_a(m, &QMenu::triggered, this, &OpenDialog::slotSwapCopyNames);
91     button->setMenu(m);
92 
93     dialogUi.lineOut->insertItems(0, m_pOptions->m_recentOutputFiles);
94     dialogUi.lineOut->setEditText(outputName);
95 
96     button = dialogUi.selectOutputFile;
97     chk_connect_a(button, &QPushButton::clicked, this, &OpenDialog::selectOutputName);
98     button2 = dialogUi.selectOutputFolder;
99     chk_connect_a(button2, &QPushButton::clicked, this, &OpenDialog::selectOutputDir);
100     chk_connect_a(dialogUi.mergeCheckBox, &QCheckBox::stateChanged, this, &OpenDialog::internalSlot);
101     chk_connect_a(this, &OpenDialog::internalSignal, dialogUi.lineOut, &QComboBox::setEnabled);
102     chk_connect_a(this, &OpenDialog::internalSignal, button, &QPushButton::setEnabled);
103     chk_connect_a(this, &OpenDialog::internalSignal, button2, &QPushButton::setEnabled);
104 
105     dialogUi.mergeCheckBox->setChecked(bMerge);
106 
107     QDialogButtonBox *box = dialogUi.buttonBox;
108     button = box->addButton(i18n("Configure..."), QDialogButtonBox::ActionRole);
109     button->setIcon(QIcon::fromTheme("configure"));
110     chk_connect_a(button, &QPushButton::clicked, pParent, &KDiff3App::slotConfigure);
111     chk_connect_a(box, &QDialogButtonBox::accepted, this, &OpenDialog::accept);
112     chk_connect_a(box, &QDialogButtonBox::rejected, this, &OpenDialog::reject);
113 
114     QSize sh = sizeHint();
115     if(sh.height() > 10)
116         setFixedHeight(sh.height());
117     else
118     {
119         //This is likely a bug. It is also a recoverable condition. Assert for it in debug builds.
120         Q_ASSERT(sh.isValid() && sh.height() > 10);
121         setFixedHeight(262);
122     }
123     m_bInputFileNameChanged = false;
124 
125     /*
126         QComboBox's default handling of Drag and Drop fails to clear existing text on drop.
127         On some systems it may fail to do anything at all.
128 
129         This is not what we want. So manually replace the each QLineEdit object with a FileNameLineEdit.
130         This makes behavior consitant with the main window.
131 
132         On windows this step also needed to bypasses Qt's quirky behavior when converting from QUrl
133         to QString. Specifically % encoding is by handled differently on windows. This is explicitly documented
134         as platform specific unspecified behavior. Not what we need.
135     */
136     dialogUi.lineA->setLineEdit(new FileNameLineEdit(dialogUi.lineA));
137     dialogUi.lineB->setLineEdit(new FileNameLineEdit(dialogUi.lineB));
138     dialogUi.lineC->setLineEdit(new FileNameLineEdit(dialogUi.lineC));
139     dialogUi.lineOut->setLineEdit(new FileNameLineEdit(dialogUi.lineOut));
140 }
141 
selectURL(QComboBox * pLine,bool bDir,int i,bool bSave)142 void OpenDialog::selectURL(QComboBox* pLine, bool bDir, int i, bool bSave)
143 {
144     QString current = pLine->currentText();
145     QUrl currentUrl;
146 
147     if(current.isEmpty() && i > 3)
148     {
149         current = dialogUi.lineC->currentText();
150     }
151     if(current.isEmpty())
152     {
153         current = dialogUi.lineB->currentText();
154     }
155     if(current.isEmpty())
156     {
157         current = dialogUi.lineA->currentText();
158     }
159 
160     currentUrl = QUrl::fromUserInput(current, QString(), QUrl::AssumeLocalFile);
161     QUrl newURL = bDir ? QFileDialog::getExistingDirectoryUrl(this, i18n("Open Folder"), currentUrl)
162                        : bSave ? QFileDialog::getSaveFileUrl(this, i18n("Select Output File"), currentUrl, i18n("all/allfiles (*)"))
163                                : QFileDialog::getOpenFileUrl(this, i18n("Open File"), currentUrl, i18n("all/allfiles (*)"));
164     if(!newURL.isEmpty())
165     {
166         /*
167             Since we are selecting a directory open in the parent directory
168             not the one selected.
169         */
170         //QFileDialog::setStartDir( KIO::upUrl( newURL ) );
171         pLine->setEditText(newURL.url());
172     }
173     // newURL won't be modified if nothing was selected.
174 }
175 
selectFileA()176 void OpenDialog::selectFileA() { selectURL(dialogUi.lineA, false, 1, false); }
selectFileB()177 void OpenDialog::selectFileB() { selectURL(dialogUi.lineB, false, 2, false); }
selectFileC()178 void OpenDialog::selectFileC() { selectURL(dialogUi.lineC, false, 3, false); }
selectOutputName()179 void OpenDialog::selectOutputName() { selectURL(dialogUi.lineOut, false, 4, true); }
selectDirA()180 void OpenDialog::selectDirA() { selectURL(dialogUi.lineA, true, 1, false); }
selectDirB()181 void OpenDialog::selectDirB() { selectURL(dialogUi.lineB, true, 2, false); }
selectDirC()182 void OpenDialog::selectDirC() { selectURL(dialogUi.lineC, true, 3, false); }
selectOutputDir()183 void OpenDialog::selectOutputDir() { selectURL(dialogUi.lineOut, true, 4, true); }
184 
internalSlot(int i)185 void OpenDialog::internalSlot(int i)
186 {
187     Q_EMIT internalSignal(i != 0);
188 }
189 
190 // Clear the output-filename when any input-filename changed,
191 // because users forgot to change the output and accidentally overwrote it with
192 // wrong data during a merge.
inputFilenameChanged()193 void OpenDialog::inputFilenameChanged()
194 {
195     if(!m_bInputFileNameChanged)
196     {
197         m_bInputFileNameChanged = true;
198         dialogUi.lineOut->clearEditText();
199     }
200 }
201 
fixCurrentText(QComboBox * pCB)202 void OpenDialog::fixCurrentText(QComboBox* pCB)
203 {
204     QString s = pCB->currentText();
205     QtNumberType pos = s.indexOf('\n');
206 
207     if(pos >= 0)
208         s = s.left(pos);
209     pos = s.indexOf('\r');
210     if(pos >= 0)
211         s = s.left(pos);
212 
213     pCB->setEditText(s);
214 }
215 
accept()216 void OpenDialog::accept()
217 {
218     int maxNofRecentFiles = 10;
219     fixCurrentText(dialogUi.lineA);
220 
221     QString s = dialogUi.lineA->currentText();
222     s = FileAccess::prettyAbsPath(QUrl::fromUserInput(s, QString(), QUrl::AssumeLocalFile));
223     QStringList* sl = &m_pOptions->m_recentAFiles;
224     // If an item exist, remove it from the list and reinsert it at the beginning.
225     sl->removeAll(s);
226     if(!s.isEmpty()) sl->prepend(s);
227     if(sl->count() > maxNofRecentFiles) sl->erase(sl->begin() + maxNofRecentFiles, sl->end());
228 
229     fixCurrentText(dialogUi.lineB);
230     s = dialogUi.lineB->currentText();
231     s = FileAccess::prettyAbsPath(QUrl::fromUserInput(s, QString(), QUrl::AssumeLocalFile));
232     sl = &m_pOptions->m_recentBFiles;
233     sl->removeAll(s);
234     if(!s.isEmpty()) sl->prepend(s);
235     if(sl->count() > maxNofRecentFiles) sl->erase(sl->begin() + maxNofRecentFiles, sl->end());
236 
237     fixCurrentText(dialogUi.lineC);
238     s = dialogUi.lineC->currentText();
239     s = FileAccess::prettyAbsPath(QUrl::fromUserInput(s, QString(), QUrl::AssumeLocalFile));
240     sl = &m_pOptions->m_recentCFiles;
241     sl->removeAll(s);
242     if(!s.isEmpty()) sl->prepend(s);
243     if(sl->count() > maxNofRecentFiles) sl->erase(sl->begin() + maxNofRecentFiles, sl->end());
244 
245     fixCurrentText(dialogUi.lineOut);
246     s = dialogUi.lineOut->currentText();
247     s = FileAccess::prettyAbsPath(QUrl::fromUserInput(s, QString(), QUrl::AssumeLocalFile));
248     sl = &m_pOptions->m_recentOutputFiles;
249     sl->removeAll(s);
250     if(!s.isEmpty()) sl->prepend(s);
251     if(sl->count() > maxNofRecentFiles) sl->erase(sl->begin() + maxNofRecentFiles, sl->end());
252 
253     QDialog::accept();
254 }
255 
slotSwapCopyNames(QAction * pAction) const256 void OpenDialog::slotSwapCopyNames(QAction* pAction) const // id selected in the popup menu
257 {
258     QtNumberType id = pAction->parentWidget()->actions().indexOf(pAction);
259     QComboBox* cb1 = nullptr;
260     QComboBox* cb2 = nullptr;
261 
262     switch(id)
263     {
264         case 0:
265             cb1 = dialogUi.lineA;
266             cb2 = dialogUi.lineB;
267             break;
268         case 1:
269             cb1 = dialogUi.lineB;
270             cb2 = dialogUi.lineC;
271             break;
272         case 2:
273             cb1 = dialogUi.lineC;
274             cb2 = dialogUi.lineA;
275             break;
276         case 3:
277             cb1 = dialogUi.lineA;
278             cb2 = dialogUi.lineOut;
279             break;
280         case 4:
281             cb1 = dialogUi.lineB;
282             cb2 = dialogUi.lineOut;
283             break;
284         case 5:
285             cb1 = dialogUi.lineC;
286             cb2 = dialogUi.lineOut;
287             break;
288         case 6:
289             cb1 = dialogUi.lineA;
290             cb2 = dialogUi.lineOut;
291             break;
292         case 7:
293             cb1 = dialogUi.lineB;
294             cb2 = dialogUi.lineOut;
295             break;
296         case 8:
297             cb1 = dialogUi.lineC;
298             cb2 = dialogUi.lineOut;
299             break;
300     }
301 
302     if(cb1 && cb2)
303     {
304         QString t1 = cb1->currentText();
305         QString t2 = cb2->currentText();
306         cb2->setEditText(t1);
307         if(id <= 2 || id >= 6)
308         {
309             cb1->setEditText(t2);
310         }
311     }
312 }
313 
314 // FindDialog *********************************************
315 
FindDialog(QWidget * pParent)316 FindDialog::FindDialog(QWidget* pParent)
317     : QDialog(pParent)
318 {
319     QGridLayout* layout = new QGridLayout(this);
320     layout->setContentsMargins(5, 5, 5, 5);
321     layout->setSpacing(5);
322 
323     int line = 0;
324     layout->addWidget(new QLabel(i18n("Search text:"), this), line, 0, 1, 2);
325     ++line;
326 
327     m_pSearchString = new QLineEdit(this);
328     layout->addWidget(m_pSearchString, line, 0, 1, 2);
329     ++line;
330 
331     m_pCaseSensitive = new QCheckBox(i18n("Case sensitive"), this);
332     layout->addWidget(m_pCaseSensitive, line, 1);
333 
334     m_pSearchInA = new QCheckBox(i18n("Search A"), this);
335     layout->addWidget(m_pSearchInA, line, 0);
336     m_pSearchInA->setChecked(true);
337     ++line;
338 
339     m_pSearchInB = new QCheckBox(i18n("Search B"), this);
340     layout->addWidget(m_pSearchInB, line, 0);
341     m_pSearchInB->setChecked(true);
342     ++line;
343 
344     m_pSearchInC = new QCheckBox(i18n("Search C"), this);
345     layout->addWidget(m_pSearchInC, line, 0);
346     m_pSearchInC->setChecked(true);
347     ++line;
348 
349     m_pSearchInOutput = new QCheckBox(i18n("Search output"), this);
350     layout->addWidget(m_pSearchInOutput, line, 0);
351     m_pSearchInOutput->setChecked(true);
352     ++line;
353 
354     QDialogButtonBox *box = new QDialogButtonBox(QDialogButtonBox::Cancel, this);
355     layout->addWidget(box, line, 0, 1, 2);
356     box->addButton(i18n("&Search"), QDialogButtonBox::AcceptRole);
357     chk_connect(box, &QDialogButtonBox::accepted, this, &FindDialog::accept);
358     chk_connect(box, &QDialogButtonBox::rejected, this, &FindDialog::reject);
359 
360     hide();
361 }
362 
restartFind()363 void FindDialog::restartFind()
364 {
365     currentLine = 0;
366     currentPos = 0;
367     currentWindow = eWindowIndex::A;
368 }
369 
setVisible(bool bVisible)370 void FindDialog::setVisible(bool bVisible)
371 {
372     QDialog::setVisible(bVisible);
373     m_pSearchString->selectAll();
374     m_pSearchString->setFocus();
375 }
376 
RegExpTester(QWidget * pParent,const QString & autoMergeRegExpToolTip,const QString & historyStartRegExpToolTip,const QString & historyEntryStartRegExpToolTip,const QString & historySortKeyOrderToolTip)377 RegExpTester::RegExpTester(QWidget* pParent, const QString& autoMergeRegExpToolTip,
378                            const QString& historyStartRegExpToolTip, const QString& historyEntryStartRegExpToolTip, const QString& historySortKeyOrderToolTip)
379     : QDialog(pParent)
380 {
381     int line = 0;
382     setWindowTitle(i18n("Regular Expression Tester"));
383     QGridLayout* pGrid = new QGridLayout(this);
384     pGrid->setSpacing(5);
385     pGrid->setContentsMargins(5, 5, 5, 5);
386 
387     QLabel* l = new QLabel(i18n("Auto merge regular expression:"), this);
388     pGrid->addWidget(l, line, 0);
389     l->setToolTip(autoMergeRegExpToolTip);
390     m_pAutoMergeRegExpEdit = new QLineEdit(this);
391     pGrid->addWidget(m_pAutoMergeRegExpEdit, line, 1);
392     chk_connect(m_pAutoMergeRegExpEdit, &QLineEdit::textChanged, this, &RegExpTester::slotRecalc);
393     ++line;
394 
395     l = new QLabel(i18n("Example auto merge line:"), this);
396     pGrid->addWidget(l, line, 0);
397     l->setToolTip(i18n("To test auto merge, copy a line as used in your files."));
398     m_pAutoMergeExampleEdit = new QLineEdit(this);
399     pGrid->addWidget(m_pAutoMergeExampleEdit, line, 1);
400     chk_connect(m_pAutoMergeExampleEdit, &QLineEdit::textChanged, this, &RegExpTester::slotRecalc);
401     ++line;
402 
403     l = new QLabel(i18n("Match result:"), this);
404     pGrid->addWidget(l, line, 0);
405     m_pAutoMergeMatchResult = new QLineEdit(this);
406     m_pAutoMergeMatchResult->setReadOnly(true);
407     pGrid->addWidget(m_pAutoMergeMatchResult, line, 1);
408     ++line;
409 
410     pGrid->addItem(new QSpacerItem(100, 20), line, 0);
411     pGrid->setRowStretch(line, 5);
412     ++line;
413 
414     l = new QLabel(i18n("History start regular expression:"), this);
415     pGrid->addWidget(l, line, 0);
416     l->setToolTip(historyStartRegExpToolTip);
417     m_pHistoryStartRegExpEdit = new QLineEdit(this);
418     pGrid->addWidget(m_pHistoryStartRegExpEdit, line, 1);
419     chk_connect(m_pHistoryStartRegExpEdit, &QLineEdit::textChanged, this, &RegExpTester::slotRecalc);
420     ++line;
421 
422     l = new QLabel(i18n("Example history start line (with leading comment):"), this);
423     pGrid->addWidget(l, line, 0);
424     l->setToolTip(i18n("Copy a history start line as used in your files,\n"
425                        "including the leading comment."));
426     m_pHistoryStartExampleEdit = new QLineEdit(this);
427     pGrid->addWidget(m_pHistoryStartExampleEdit, line, 1);
428     chk_connect(m_pHistoryStartExampleEdit, &QLineEdit::textChanged, this, &RegExpTester::slotRecalc);
429     ++line;
430 
431     l = new QLabel(i18n("Match result:"), this);
432     pGrid->addWidget(l, line, 0);
433     m_pHistoryStartMatchResult = new QLineEdit(this);
434     m_pHistoryStartMatchResult->setReadOnly(true);
435     pGrid->addWidget(m_pHistoryStartMatchResult, line, 1);
436     ++line;
437 
438     pGrid->addItem(new QSpacerItem(100, 20), line, 0);
439     pGrid->setRowStretch(line, 5);
440     ++line;
441 
442     l = new QLabel(i18n("History entry start regular expression:"), this);
443     pGrid->addWidget(l, line, 0);
444     l->setToolTip(historyEntryStartRegExpToolTip);
445     m_pHistoryEntryStartRegExpEdit = new QLineEdit(this);
446     pGrid->addWidget(m_pHistoryEntryStartRegExpEdit, line, 1);
447     chk_connect(m_pHistoryEntryStartRegExpEdit, &QLineEdit::textChanged, this, &RegExpTester::slotRecalc);
448     ++line;
449 
450     l = new QLabel(i18n("History sort key order:"), this);
451     pGrid->addWidget(l, line, 0);
452     l->setToolTip(historySortKeyOrderToolTip);
453     m_pHistorySortKeyOrderEdit = new QLineEdit(this);
454     pGrid->addWidget(m_pHistorySortKeyOrderEdit, line, 1);
455     chk_connect(m_pHistorySortKeyOrderEdit, &QLineEdit::textChanged, this, &RegExpTester::slotRecalc);
456     ++line;
457 
458     l = new QLabel(i18n("Example history entry start line (without leading comment):"), this);
459     pGrid->addWidget(l, line, 0);
460     l->setToolTip(i18n("Copy a history entry start line as used in your files,\n"
461                        "but omit the leading comment."));
462     m_pHistoryEntryStartExampleEdit = new QLineEdit(this);
463     pGrid->addWidget(m_pHistoryEntryStartExampleEdit, line, 1);
464     chk_connect(m_pHistoryEntryStartExampleEdit, &QLineEdit::textChanged, this, &RegExpTester::slotRecalc);
465     ++line;
466 
467     l = new QLabel(i18n("Match result:"), this);
468     pGrid->addWidget(l, line, 0);
469     m_pHistoryEntryStartMatchResult = new QLineEdit(this);
470     m_pHistoryEntryStartMatchResult->setReadOnly(true);
471     pGrid->addWidget(m_pHistoryEntryStartMatchResult, line, 1);
472     ++line;
473 
474     l = new QLabel(i18n("Sort key result:"), this);
475     pGrid->addWidget(l, line, 0);
476     m_pHistorySortKeyResult = new QLineEdit(this);
477     m_pHistorySortKeyResult->setReadOnly(true);
478     pGrid->addWidget(m_pHistorySortKeyResult, line, 1);
479     ++line;
480 
481     QDialogButtonBox *box = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel, this);
482     pGrid->addWidget(box, line, 0, 1, 2);
483     chk_connect(box, &QDialogButtonBox::accepted, this, &RegExpTester::accept);
484     chk_connect(box, &QDialogButtonBox::rejected, this, &RegExpTester::reject);
485 
486     resize(800, sizeHint().height());
487 }
488 
init(const QString & autoMergeRegExp,const QString & historyStartRegExp,const QString & historyEntryStartRegExp,const QString & historySortKeyOrder)489 void RegExpTester::init(const QString& autoMergeRegExp, const QString& historyStartRegExp, const QString& historyEntryStartRegExp, const QString& historySortKeyOrder)
490 {
491     m_pAutoMergeRegExpEdit->setText(autoMergeRegExp);
492     m_pHistoryStartRegExpEdit->setText(historyStartRegExp);
493     m_pHistoryEntryStartRegExpEdit->setText(historyEntryStartRegExp);
494     m_pHistorySortKeyOrderEdit->setText(historySortKeyOrder);
495 }
496 
autoMergeRegExp()497 QString RegExpTester::autoMergeRegExp()
498 {
499     return m_pAutoMergeRegExpEdit->text();
500 }
501 
historyStartRegExp()502 QString RegExpTester::historyStartRegExp()
503 {
504     return m_pHistoryStartRegExpEdit->text();
505 }
506 
historyEntryStartRegExp()507 QString RegExpTester::historyEntryStartRegExp()
508 {
509     return m_pHistoryEntryStartRegExpEdit->text();
510 }
511 
historySortKeyOrder()512 QString RegExpTester::historySortKeyOrder()
513 {
514     return m_pHistorySortKeyOrderEdit->text();
515 }
516 
slotRecalc()517 void RegExpTester::slotRecalc()
518 {
519     QRegExp autoMergeRegExp(m_pAutoMergeRegExpEdit->text());
520     if(autoMergeRegExp.exactMatch(m_pAutoMergeExampleEdit->text()))
521     {
522         m_pAutoMergeMatchResult->setText(i18n("Match success."));
523     }
524     else
525     {
526         m_pAutoMergeMatchResult->setText(i18n("Match failed."));
527     }
528 
529     QRegExp historyStartRegExp(m_pHistoryStartRegExpEdit->text());
530     if(historyStartRegExp.exactMatch(m_pHistoryStartExampleEdit->text()))
531     {
532         m_pHistoryStartMatchResult->setText(i18n("Match success."));
533     }
534     else
535     {
536         m_pHistoryStartMatchResult->setText(i18n("Match failed."));
537     }
538 
539     QStringList parenthesesGroups;
540     bool bSuccess = findParenthesesGroups(m_pHistoryEntryStartRegExpEdit->text(), parenthesesGroups);
541     if(!bSuccess)
542     {
543         m_pHistoryEntryStartMatchResult->setText(i18n("Opening and closing parentheses do not match in regular expression."));
544         m_pHistorySortKeyResult->setText("");
545         return;
546     }
547     QRegExp historyEntryStartRegExp(m_pHistoryEntryStartRegExpEdit->text());
548     QString s = m_pHistoryEntryStartExampleEdit->text();
549 
550     if(historyEntryStartRegExp.exactMatch(s))
551     {
552         m_pHistoryEntryStartMatchResult->setText(i18n("Match success."));
553         QString key = calcHistorySortKey(m_pHistorySortKeyOrderEdit->text(), historyEntryStartRegExp, parenthesesGroups);
554         m_pHistorySortKeyResult->setText(key);
555     }
556     else
557     {
558         m_pHistoryEntryStartMatchResult->setText(i18n("Match failed."));
559         m_pHistorySortKeyResult->setText("");
560     }
561 }
562 
563 //#include "smalldialogs.moc"
564