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>
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();
77void 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);
111 replace->setMaxCount(10);
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());
249void 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())
262 d->findStrings = QStringList();
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();
309 d->pattern = pattern;
310 kDebug() <<
"setPattern " << pattern;
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 );
337void KFindDialog::KFindDialogPrivate::_k_slotSelectedTextToggled(
bool selec)
342 fromCursor->setChecked(
false );
348 else d->enabled &=
~KFind::FromCursor;
349 d->fromCursor->setEnabled( hasCursor );
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();
410void 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
456 RegExpAction(
QObject *parent,
const QString &text,
const QString ®Exp,
int cursor )
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());
500class PlaceHolderAction :
public QAction
503 PlaceHolderAction(
QObject *parent,
const QString &text,
int id )
504 :
QAction( text, parent ), mText( text ), mId( id )
508 QString text()
const {
return mText; }
509 int id()
const {
return mId; }
518void 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() ) );
539void 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 ) );
550void 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"
A dialog base class with standard buttons and predefined layouts.
void setButtonGuiItem(ButtonCode id, const KGuiItem &item)
Sets the KGuiItem directly for the button instead of using 3 methods to set the text,...
void setButtons(ButtonCodes buttonMask)
Creates (or recreates) the button box and all the buttons in it.
@ Ok
Show Ok button. (this button accept()s the dialog; result set to QDialog::Accepted)
@ Cancel
Show Cancel-button. (this button reject()s the dialog; result set to QDialog::Rejected)
void setDefaultButton(ButtonCode id)
Sets the button that will be activated when the Enter key is pressed.
virtual void setCaption(const QString &caption)
Make a KDE compliant caption.
virtual void showEvent(QShowEvent *)
virtual ~KFindDialog()
Destructor.
void setSupportsBackwardsFind(bool supports)
Enable/disable the 'Find backwards' option, depending on whether the application supports it.
void setHasCursor(bool hasCursor)
Hide/show the 'from cursor' option, depending on whether the application implements a cursor.
void setSupportsWholeWordsFind(bool supports)
Enable/disable the 'Whole words only' option, depending on whether the application supports it.
KFindDialog(QWidget *parent=0, long options=0, const QStringList &findStrings=QStringList(), bool hasSelection=false, bool replaceDialog=false)
Construct a modal find dialog.
void setSupportsCaseSensitiveFind(bool supports)
Enable/disable the 'Case sensitive' option, depending on whether the application supports it.
void setFindHistory(const QStringList &history)
Provide the list of strings to be displayed as the history of find strings.
QStringList findHistory() const
Returns the list of history items.
QString pattern() const
Returns the pattern to find.
void setSupportsRegularExpressionFind(bool supports)
Enable/disable the 'Regular expression' option, depending on whether the application supports it.
long options() const
Returns the state of the options.
void setHasSelection(bool hasSelection)
Enable/disable the 'search in selection' option, depending on whether there actually is a selection.
void setOptions(long options)
Set the options which are checked.
void setPattern(const QString &pattern)
Sets the pattern to find.
QWidget * findExtension() const
Returns an empty widget which the user may fill with additional UI elements as required.
A generic implementation of the "find" function.
@ CaseSensitive
Consider case when matching.
@ SelectedText
Only search selected area.
@ RegularExpression
Interpret the pattern as a regular expression.
@ FromCursor
Start from current cursor position.
@ FindBackwards
Go backwards.
@ WholeWordsOnly
Match whole words only.
An abstract class for GUI data such as ToolTip and Icon.
A combobox for offering a history and completion.
static void error(QWidget *parent, const QString &text, const QString &caption=QString(), Options options=Notify)
Display an "Error" dialog.
QString i18n(const char *text)
QString i18nc(const char *ctxt, const char *text)
KAction * replace(const QObject *recvr, const char *slot, QObject *parent)
Find and replace matches.
KAction * find(const QObject *recvr, const char *slot, QObject *parent)
Initiate a 'find' request in the current document.
KGuiItem close()
Returns the 'Close' gui item.