22 #include "kfinddialog_p.h"
24 #include <QtGui/QCheckBox>
25 #include <QtGui/QCursor>
26 #include <QtGui/QGroupBox>
27 #include <QtGui/QLabel>
28 #include <QtGui/QLayout>
29 #include <QtGui/QLineEdit>
30 #include <QtGui/QMenu>
31 #include <QtGui/QPushButton>
32 #include <QtCore/QRegExp>
40 #include <kregexpeditorinterface.h>
45 d(new KFindDialogPrivate(this))
51 d->init(replaceDialog, findStrings, hasSelection);
63 if (!d->findExtension)
65 d->findExtension =
new QWidget(d->findGrp);
66 d->findLayout->addWidget(d->findExtension, 3, 0, 1, 2);
69 return d->findExtension;
74 return d->find->historyItems();
77 void KFindDialog::KFindDialogPrivate::init(
bool forReplace,
const QStringList &_findStrings,
bool hasSelection)
79 QVBoxLayout *topLayout;
80 QGridLayout *optionsLayout;
84 q->setMainWidget(page);
86 topLayout =
new QVBoxLayout(page);
87 topLayout->setMargin( 0 );
90 findLayout =
new QGridLayout(findGrp);
94 find->setMaxCount(10);
95 find->setDuplicatesEnabled(
false);
96 regExp =
new QCheckBox(
i18n(
"Regular e&xpression"), findGrp);
98 regExpItem->setEnabled(
false);
100 findLayout->addWidget(findLabel, 0, 0);
101 findLayout->addWidget(
find, 1, 0, 1, 2);
102 findLayout->addWidget(regExp, 2, 0);
103 findLayout->addWidget(regExpItem, 2, 1);
104 topLayout->addWidget(findGrp);
107 replaceLayout =
new QGridLayout(replaceGrp);
112 replace->setDuplicatesEnabled(
false);
113 backRef =
new QCheckBox(
i18n(
"Use p&laceholders"), replaceGrp);
114 backRefItem =
new QPushButton(
i18n(
"Insert Place&holder"), replaceGrp);
115 backRefItem->setEnabled(
false);
117 replaceLayout->addWidget(replaceLabel, 0, 0);
118 replaceLayout->addWidget(
replace, 1, 0, 1, 2);
119 replaceLayout->addWidget(backRef, 2, 0);
120 replaceLayout->addWidget(backRefItem, 2, 1);
121 topLayout->addWidget(replaceGrp);
124 optionsLayout =
new QGridLayout(optionGrp);
126 caseSensitive =
new QCheckBox(
i18n(
"C&ase sensitive"), optionGrp);
127 wholeWordsOnly =
new QCheckBox(
i18n(
"&Whole words only"), optionGrp);
128 fromCursor =
new QCheckBox(
i18n(
"From c&ursor"), optionGrp);
129 findBackwards =
new QCheckBox(
i18n(
"Find &backwards"), optionGrp);
130 selectedText =
new QCheckBox(
i18n(
"&Selected text"), optionGrp);
131 q->setHasSelection( hasSelection );
134 selectedText->setChecked( hasSelection );
135 _k_slotSelectedTextToggled( hasSelection );
137 promptOnReplace =
new QCheckBox(
i18n(
"&Prompt on replace"), optionGrp);
138 promptOnReplace->setChecked(
true );
140 optionsLayout->addWidget(caseSensitive, 0, 0);
141 optionsLayout->addWidget(wholeWordsOnly, 1, 0);
142 optionsLayout->addWidget(fromCursor, 2, 0);
143 optionsLayout->addWidget(findBackwards, 0, 1);
144 optionsLayout->addWidget(selectedText, 1, 1);
145 optionsLayout->addWidget(promptOnReplace, 2, 1);
146 topLayout->addWidget(optionGrp);
153 q->connect(selectedText, SIGNAL(toggled(
bool)), q, SLOT(_k_slotSelectedTextToggled(
bool)));
154 q->connect(regExp, SIGNAL(toggled(
bool)), regExpItem, SLOT(setEnabled(
bool)));
155 q->connect(backRef, SIGNAL(toggled(
bool)), backRefItem, SLOT(setEnabled(
bool)));
156 q->connect(regExpItem, SIGNAL(clicked()), q, SLOT(_k_showPatterns()));
157 q->connect(backRefItem, SIGNAL(clicked()), q, SLOT(_k_showPlaceholders()));
159 q->connect(
find, SIGNAL(editTextChanged(
QString)), q, SLOT(_k_textSearchChanged(
QString)));
161 q->connect(regExp, SIGNAL(toggled(
bool)), q, SIGNAL(optionsChanged()));
162 q->connect(backRef, SIGNAL(toggled(
bool)), q, SIGNAL(optionsChanged()));
163 q->connect(caseSensitive, SIGNAL(toggled(
bool)), q, SIGNAL(optionsChanged()));
164 q->connect(wholeWordsOnly, SIGNAL(toggled(
bool)), q, SIGNAL(optionsChanged()));
165 q->connect(fromCursor, SIGNAL(toggled(
bool)), q, SIGNAL(optionsChanged()));
166 q->connect(findBackwards, SIGNAL(toggled(
bool)), q, SIGNAL(optionsChanged()));
167 q->connect(selectedText, SIGNAL(toggled(
bool)), q, SIGNAL(optionsChanged()));
168 q->connect(promptOnReplace, SIGNAL(toggled(
bool)), q, SIGNAL(optionsChanged()));
171 q->setTabOrder(
find, regExp);
172 q->setTabOrder(regExp, regExpItem);
173 q->setTabOrder(regExpItem,
replace);
174 q->setTabOrder(
replace, backRef);
175 q->setTabOrder(backRef, backRefItem);
176 q->setTabOrder(backRefItem, caseSensitive);
177 q->setTabOrder(caseSensitive, wholeWordsOnly);
178 q->setTabOrder(wholeWordsOnly, fromCursor);
179 q->setTabOrder(fromCursor, findBackwards);
180 q->setTabOrder(findBackwards, selectedText);
181 q->setTabOrder(selectedText, promptOnReplace);
184 findLabel->setBuddy(
find);
185 replaceLabel->setBuddy(
replace);
189 promptOnReplace->hide();
193 findStrings = _findStrings;
195 q->enableButtonOk( !q->pattern().isEmpty() );
199 i18n(
"Start replace"),
200 i18n(
"<qt>If you press the <b>Replace</b> button, the text you entered "
201 "above is searched for within the document and any occurrence is "
202 "replaced with the replacement text.</qt>")));
207 i18n(
"Start searching"),
208 i18n(
"<qt>If you press the <b>Find</b> button, the text you entered "
209 "above is searched for within the document.</qt>")));
214 "Enter a pattern to search for, or select a previous pattern from "
216 regExp->setWhatsThis(
i18n(
217 "If enabled, search for a regular expression.") );
218 regExpItem->setWhatsThis(
i18n(
219 "Click here to edit your regular expression using a graphical editor.") );
221 "Enter a replacement string, or select a previous one from the list.") );
222 backRef->setWhatsThis(
i18n(
223 "<qt>If enabled, any occurrence of <code><b>\\N</b></code>, where "
224 "<code><b>N</b></code> is an integer number, will be replaced with "
225 "the corresponding capture (\"parenthesized substring\") from the "
226 "pattern.<p>To include (a literal <code><b>\\N</b></code> in your "
227 "replacement, put an extra backslash in front of it, like "
228 "<code><b>\\\\N</b></code>.</p></qt>") );
229 backRefItem->setWhatsThis(
i18n(
230 "Click for a menu of available captures.") );
231 wholeWordsOnly->setWhatsThis(
i18n(
232 "Require word boundaries in both ends of a match to succeed.") );
233 fromCursor->setWhatsThis(
i18n(
234 "Start searching at the current cursor location rather than at the top.") );
235 selectedText->setWhatsThis(
i18n(
236 "Only search within the current selection.") );
237 caseSensitive->setWhatsThis(
i18n(
238 "Perform a case sensitive search: entering the pattern "
239 "'Joe' will not match 'joe' or 'JOE', only 'Joe'.") );
240 findBackwards->setWhatsThis(
i18n(
241 "Search backwards.") );
242 promptOnReplace->setWhatsThis(
i18n(
243 "Ask before replacing each match found.") );
245 q->connect(q, SIGNAL(okClicked()), q, SLOT(_k_slotOk()));
246 _k_textSearchChanged(
find->lineEdit()->text());
249 void KFindDialog::KFindDialogPrivate::_k_textSearchChanged(
const QString & text)
251 q->enableButtonOk( !text.isEmpty() );
256 if ( !d->initialShowDone )
258 d->initialShowDone =
true;
259 kDebug() <<
"showEvent\n";
260 if (!d->findStrings.isEmpty())
263 if (!d->pattern.isEmpty()) {
264 d->find->lineEdit()->setText( d->pattern );
265 d->find->lineEdit()->selectAll();
269 if (d->findExtension) {
271 foreach(
QWidget* child, d->findExtension->findChildren<
QWidget*>()) {
272 setTabOrder(prev, child);
275 setTabOrder(prev, d->replace);
278 KDialog::showEvent(e);
285 if (d->caseSensitive->isChecked())
287 if (d->wholeWordsOnly->isChecked())
289 if (d->fromCursor->isChecked())
291 if (d->findBackwards->isChecked())
293 if (d->selectedText->isChecked())
295 if (d->regExp->isChecked())
302 return d->find->currentText();
307 d->find->lineEdit()->setText( pattern );
308 d->find->lineEdit()->selectAll();
315 if (strings.count() > 0)
317 d->find->setHistoryItems(strings,
true);
318 d->find->lineEdit()->setText( strings.first() );
319 d->find->lineEdit()->selectAll();
322 d->find->clearHistory();
328 else d->enabled &= ~
KFind::SelectedText;
329 d->selectedText->setEnabled( hasSelection );
332 d->selectedText->setChecked(
false );
333 d->_k_slotSelectedTextToggled( hasSelection );
337 void KFindDialog::KFindDialogPrivate::_k_slotSelectedTextToggled(
bool selec)
342 fromCursor->setChecked(
false );
348 else d->enabled &= ~
KFind::FromCursor;
349 d->fromCursor->setEnabled( hasCursor );
350 d->fromCursor->setChecked( hasCursor && (
options() & KFind::FromCursor) );
357 else d->enabled &= ~
KFind::FindBackwards;
358 d->findBackwards->setEnabled( supports );
366 else d->enabled &= ~
KFind::CaseSensitive;
367 d->caseSensitive->setEnabled( supports );
375 else d->enabled &= ~
KFind::WholeWordsOnly;
376 d->wholeWordsOnly->setEnabled( supports );
383 else d->enabled &= ~
KFind::RegularExpression;
384 d->regExp->setEnabled( supports );
388 d->regExpItem->hide();
393 d->regExpItem->show();
402 d->fromCursor->setChecked((d->enabled & KFind::FromCursor) && (options & KFind::FromCursor));
410 void KFindDialog::KFindDialogPrivate::_k_showPatterns()
412 if ( !regexpDialogQueryDone )
414 regexpDialog = KServiceTypeTrader::createInstanceFromQuery<QDialog>(
"KRegExpEditor/KRegExpEditor",
QString(), q );
415 regexpDialogQueryDone =
true;
420 KRegExpEditorInterface *iface = qobject_cast<KRegExpEditorInterface*>( regexpDialog );
423 iface->setRegExp( q->pattern() );
424 if ( regexpDialog->exec() == QDialog::Accepted )
425 q->setPattern( iface->regExp() );
431 const char *description;
433 int cursorAdjustment;
435 static const term items[] =
440 {
I18N_NOOP(
"Set of Characters"),
"[]", -1 },
441 {
I18N_NOOP(
"Repeats, Zero or More Times"),
"*", 0 },
442 {
I18N_NOOP(
"Repeats, One or More Times"),
"+", 0 },
447 {
I18N_NOOP(
"Carriage Return"),
"\\r", 0 },
453 class RegExpAction :
public QAction
457 :
QAction( text, parent ), mText( text ), mRegExp( regExp ), mCursor( cursor )
461 QString text()
const {
return mText; }
462 QString regExp()
const {
return mRegExp; }
463 int cursor()
const {
return mCursor; }
476 patterns =
new QMenu(q);
477 for (i = 0; (unsigned)i <
sizeof(items) /
sizeof(items[0]); i++)
479 patterns->addAction(
new RegExpAction(patterns,
i18n(items[i].description),
481 items[i].cursorAdjustment));
486 QAction *action = patterns->exec(regExpItem->mapToGlobal(regExpItem->rect().bottomLeft()));
489 RegExpAction *regExpAction =
static_cast<RegExpAction*
>( action );
490 if ( regExpAction ) {
493 editor->insert(regExpAction->regExp());
494 editor->setCursorPosition(editor->cursorPosition() + regExpAction->cursor());
500 class PlaceHolderAction :
public QAction
504 :
QAction( text, parent ), mText( text ), mId( id )
508 QString text()
const {
return mText; }
509 int id()
const {
return mId; }
518 void KFindDialog::KFindDialogPrivate::_k_showPlaceholders()
523 placeholders =
new QMenu(q);
524 q->connect( placeholders, SIGNAL(aboutToShow()), q, SLOT(_k_slotPlaceholdersAboutToShow()) );
528 QAction *action = placeholders->exec(backRefItem->mapToGlobal(backRefItem->rect().bottomLeft()));
531 PlaceHolderAction *placeHolderAction =
static_cast<PlaceHolderAction*
>(action);
532 if (placeHolderAction) {
534 editor->insert(
QString(
"\\%1").arg( placeHolderAction->id() ) );
539 void KFindDialog::KFindDialogPrivate::_k_slotPlaceholdersAboutToShow()
541 placeholders->clear();
542 placeholders->addAction(
new PlaceHolderAction(placeholders,
i18n(
"Complete Match"), 0));
544 QRegExp r( q->pattern() );
545 uint n = r.numCaptures();
546 for ( uint i=0; i < n; i++ )
547 placeholders->addAction(
new PlaceHolderAction(placeholders,
i18n(
"Captured Text (%1)", i+1 ), i+1 ) );
550 void KFindDialog::KFindDialogPrivate::_k_slotOk()
553 if (q->pattern().isEmpty())
559 if (regExp->isChecked())
562 QRegExp _regExp(q->pattern());
564 if (!_regExp.isValid())
570 find->addToHistory(q->pattern());
571 if ( q->windowModality() != Qt::NonModal )
575 #include "kfinddialog.moc"
QString i18n(const char *text)
void setPattern(const QString &pattern)
Sets the pattern to find.
void setButtonGuiItem(ButtonCode id, const KGuiItem &item)
Sets the KGuiItem directly for the button instead of using 3 methods to set the text, tooltip and whatsthis strings.
void setHasCursor(bool hasCursor)
Hide/show the 'from cursor' option, depending on whether the application implements a cursor...
Show Cancel-button. (this button reject()s the dialog; result set to QDialog::Rejected) ...
void setSupportsRegularExpressionFind(bool supports)
Enable/disable the 'Regular expression' option, depending on whether the application supports it...
KAction * find(const QObject *recvr, const char *slot, QObject *parent)
Initiate a 'find' request in the current document.
KFindDialog(QWidget *parent=0, long options=0, const QStringList &findStrings=QStringList(), bool hasSelection=false, bool replaceDialog=false)
Construct a modal find dialog.
A dialog base class with standard buttons and predefined layouts.
void setSupportsWholeWordsFind(bool supports)
Enable/disable the 'Whole words only' option, depending on whether the application supports it...
static QDebug kDebug(bool cond, int area=KDE_DEFAULT_DEBUG_AREA)
virtual void setCaption(const QString &caption)
Make a KDE compliant caption.
long options() const
Returns the state of the options.
Interpret the pattern as a regular expression.
QString i18nc(const char *ctxt, const char *text)
QString pattern() const
Returns the pattern to find.
A combobox for offering a history and completion.
Start from current cursor position.
void setFindHistory(const QStringList &history)
Provide the list of strings to be displayed as the history of find strings.
An abstract class for GUI data such as ToolTip and Icon.
void setButtons(ButtonCodes buttonMask)
Creates (or recreates) the button box and all the buttons in it.
virtual void showEvent(QShowEvent *)
QWidget * findExtension() const
Returns an empty widget which the user may fill with additional UI elements as required.
Show Ok button. (this button accept()s the dialog; result set to QDialog::Accepted) ...
A generic implementation of the "find" function.
void setDefaultButton(ButtonCode id)
Sets the button that will be activated when the Enter key is pressed.
virtual ~KFindDialog()
Destructor.
void setSupportsBackwardsFind(bool supports)
Enable/disable the 'Find backwards' option, depending on whether the application supports it...
KGuiItem close()
Returns the 'Close' gui item.
Only search selected area.
KAction * replace(const QObject *recvr, const char *slot, QObject *parent)
Find and replace matches.
void setOptions(long options)
Set the options which are checked.
void setHasSelection(bool hasSelection)
Enable/disable the 'search in selection' option, depending on whether there actually is a selection...
Consider case when matching.
void setSupportsCaseSensitiveFind(bool supports)
Enable/disable the 'Case sensitive' option, depending on whether the application supports it...
QStringList findHistory() const
Returns the list of history items.
static void error(QWidget *parent, const QString &text, const QString &caption=QString(), Options options=Notify)
Display an "Error" dialog.