kutils Library API Documentation

kfinddialog.cpp

00001 /* 00002 Copyright (C) 2001, S.R.Haque <srhaque@iee.org>. 00003 Copyright (C) 2002, David Faure <david@mandrakesoft.com> 00004 This file is part of the KDE project 00005 00006 This library is free software; you can redistribute it and/or 00007 modify it under the terms of the GNU Library General Public 00008 License version 2, as published by the Free Software Foundation. 00009 00010 This library is distributed in the hope that it will be useful, 00011 but WITHOUT ANY WARRANTY; without even the implied warranty of 00012 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00013 Library General Public License for more details. 00014 00015 You should have received a copy of the GNU Library General Public License 00016 along with this library; see the file COPYING.LIB. If not, write to 00017 the Free Software Foundation, Inc., 59 Temple Place - Suite 330, 00018 Boston, MA 02111-1307, USA. 00019 */ 00020 00021 #include "kfinddialog.h" 00022 #include <qcheckbox.h> 00023 #include <qcursor.h> 00024 #include <qgroupbox.h> 00025 #include <qlabel.h> 00026 #include <qlayout.h> 00027 #include <qpopupmenu.h> 00028 #include <qpushbutton.h> 00029 #include <qregexp.h> 00030 #include <kcombobox.h> 00031 #include <kdebug.h> 00032 #include <klocale.h> 00033 #include <kmessagebox.h> 00034 #include <assert.h> 00035 00036 #include <kregexpeditorinterface.h> 00037 #include <kparts/componentfactory.h> 00038 00039 class KFindDialog::KFindDialogPrivate 00040 { 00041 public: 00042 KFindDialogPrivate() : m_regexpDialog(0), 00043 m_regexpDialogQueryDone(false), m_hasCursor(true), m_hasSelection(false), 00044 m_initialShowDone(false) {} 00045 QDialog* m_regexpDialog; 00046 bool m_regexpDialogQueryDone; 00047 bool m_hasCursor; 00048 bool m_hasSelection; 00049 bool m_initialShowDone; 00050 QStringList findStrings; 00051 QString pattern; 00052 }; 00053 00054 KFindDialog::KFindDialog(QWidget *parent, const char *name, long options, const QStringList &findStrings, bool hasSelection) : 00055 KDialogBase(parent, name, true, i18n("Find Text"), Ok | Cancel, Ok), 00056 m_findExtension (0), 00057 m_replaceExtension (0) 00058 { 00059 d = new KFindDialogPrivate; 00060 init(false, findStrings, hasSelection); 00061 setOptions(options); 00062 } 00063 00064 KFindDialog::KFindDialog(bool modal, QWidget *parent, const char *name, long options, const QStringList &findStrings, bool hasSelection) : 00065 KDialogBase(parent, name, modal, i18n("Find Text"), Ok | Cancel, Ok), 00066 m_findExtension (0), 00067 m_replaceExtension (0) 00068 { 00069 d = new KFindDialogPrivate; 00070 init(false, findStrings, hasSelection); 00071 setOptions(options); 00072 } 00073 00074 KFindDialog::KFindDialog(QWidget *parent, const char *name, bool /*forReplace*/) : 00075 KDialogBase(parent, name, true, i18n("Replace Text"), Ok | Cancel, Ok), 00076 m_findExtension (0), 00077 m_replaceExtension (0) 00078 { 00079 d = new KFindDialogPrivate; 00080 } 00081 00082 KFindDialog::~KFindDialog() 00083 { 00084 delete d; 00085 } 00086 00087 QWidget *KFindDialog::findExtension() 00088 { 00089 if (!m_findExtension) 00090 { 00091 m_findExtension = new QWidget(m_findGrp); 00092 m_findLayout->addMultiCellWidget(m_findExtension, 3, 3, 0, 1); 00093 } 00094 00095 return m_findExtension; 00096 } 00097 00098 QStringList KFindDialog::findHistory() const 00099 { 00100 return m_find->historyItems(); 00101 } 00102 00103 void KFindDialog::init(bool forReplace, const QStringList &findStrings, bool hasSelection) 00104 { 00105 QVBoxLayout *topLayout; 00106 QGridLayout *optionsLayout; 00107 00108 // Create common parts of dialog. 00109 QWidget *page = new QWidget(this); 00110 setMainWidget(page); 00111 00112 topLayout = new QVBoxLayout(page); 00113 topLayout->setSpacing( KDialog::spacingHint() ); 00114 topLayout->setMargin( 0 ); 00115 00116 m_findGrp = new QGroupBox(0, Qt::Vertical, i18n("Find"), page); 00117 m_findGrp->layout()->setSpacing( KDialog::spacingHint() ); 00118 // m_findGrp->layout()->setMargin( KDialog::marginHint() ); 00119 m_findLayout = new QGridLayout(m_findGrp->layout()); 00120 m_findLayout->setSpacing( KDialog::spacingHint() ); 00121 // m_findLayout->setMargin( KDialog::marginHint() ); 00122 00123 m_findLabel = new QLabel(i18n("&Text to find:"), m_findGrp); 00124 m_find = new KHistoryCombo(true, m_findGrp); 00125 m_find->setMaxCount(10); 00126 m_find->setDuplicatesEnabled(false); 00127 m_regExp = new QCheckBox(i18n("Regular e&xpression"), m_findGrp); 00128 m_regExpItem = new QPushButton(i18n("&Edit..."), m_findGrp); 00129 m_regExpItem->setEnabled(false); 00130 00131 m_findLayout->addWidget(m_findLabel, 0, 0); 00132 m_findLayout->addMultiCellWidget(m_find, 1, 1, 0, 1); 00133 m_findLayout->addWidget(m_regExp, 2, 0); 00134 m_findLayout->addWidget(m_regExpItem, 2, 1); 00135 topLayout->addWidget(m_findGrp); 00136 00137 m_replaceGrp = new QGroupBox(0, Qt::Vertical, i18n("Replace With"), page); 00138 m_replaceGrp->layout()->setSpacing( KDialog::spacingHint() ); 00139 // m_replaceGrp->layout()->setMargin( KDialog::marginHint() ); 00140 m_replaceLayout = new QGridLayout(m_replaceGrp->layout()); 00141 m_replaceLayout->setSpacing( KDialog::spacingHint() ); 00142 // m_replaceLayout->setMargin( KDialog::marginHint() ); 00143 00144 m_replaceLabel = new QLabel(i18n("Replace&ment text:"), m_replaceGrp); 00145 m_replace = new KHistoryCombo(true, m_replaceGrp); 00146 m_replace->setMaxCount(10); 00147 m_replace->setDuplicatesEnabled(false); 00148 m_backRef = new QCheckBox(i18n("Use p&laceholders"), m_replaceGrp); 00149 m_backRefItem = new QPushButton(i18n("Insert Place&holder"), m_replaceGrp); 00150 m_backRefItem->setEnabled(false); 00151 00152 m_replaceLayout->addWidget(m_replaceLabel, 0, 0); 00153 m_replaceLayout->addMultiCellWidget(m_replace, 1, 1, 0, 1); 00154 m_replaceLayout->addWidget(m_backRef, 2, 0); 00155 m_replaceLayout->addWidget(m_backRefItem, 2, 1); 00156 topLayout->addWidget(m_replaceGrp); 00157 00158 m_optionGrp = new QGroupBox(0, Qt::Vertical, i18n("Options"), page); 00159 m_optionGrp->layout()->setSpacing(KDialog::spacingHint()); 00160 // m_optionGrp->layout()->setMargin(KDialog::marginHint()); 00161 optionsLayout = new QGridLayout(m_optionGrp->layout()); 00162 optionsLayout->setSpacing( KDialog::spacingHint() ); 00163 // optionsLayout->setMargin( KDialog::marginHint() ); 00164 00165 m_caseSensitive = new QCheckBox(i18n("C&ase sensitive"), m_optionGrp); 00166 m_wholeWordsOnly = new QCheckBox(i18n("&Whole words only"), m_optionGrp); 00167 m_fromCursor = new QCheckBox(i18n("From c&ursor"), m_optionGrp); 00168 m_findBackwards = new QCheckBox(i18n("Find &backwards"), m_optionGrp); 00169 m_selectedText = new QCheckBox(i18n("&Selected text"), m_optionGrp); 00170 setHasSelection( hasSelection ); 00171 // If we have a selection, we make 'find in selection' default 00172 // and if we don't, then the option has to be unchecked, obviously. 00173 m_selectedText->setChecked( hasSelection ); 00174 slotSelectedTextToggled( hasSelection ); 00175 00176 m_promptOnReplace = new QCheckBox(i18n("&Prompt on replace"), m_optionGrp); 00177 m_promptOnReplace->setChecked( true ); 00178 00179 optionsLayout->addWidget(m_caseSensitive, 0, 0); 00180 optionsLayout->addWidget(m_wholeWordsOnly, 1, 0); 00181 optionsLayout->addWidget(m_fromCursor, 2, 0); 00182 optionsLayout->addWidget(m_findBackwards, 0, 1); 00183 optionsLayout->addWidget(m_selectedText, 1, 1); 00184 optionsLayout->addWidget(m_promptOnReplace, 2, 1); 00185 topLayout->addWidget(m_optionGrp); 00186 00187 // We delay creation of these until needed. 00188 m_patterns = 0L; 00189 m_placeholders = 0L; 00190 00191 // signals and slots connections 00192 connect(m_selectedText, SIGNAL(toggled(bool)), this, SLOT(slotSelectedTextToggled(bool))); 00193 connect(m_regExp, SIGNAL(toggled(bool)), m_regExpItem, SLOT(setEnabled(bool))); 00194 connect(m_backRef, SIGNAL(toggled(bool)), m_backRefItem, SLOT(setEnabled(bool))); 00195 connect(m_regExpItem, SIGNAL(clicked()), this, SLOT(showPatterns())); 00196 connect(m_backRefItem, SIGNAL(clicked()), this, SLOT(showPlaceholders())); 00197 00198 connect(m_find, SIGNAL(textChanged ( const QString & )),this, SLOT(textSearchChanged( const QString & ))); 00199 00200 // tab order 00201 setTabOrder(m_find, m_regExp); 00202 setTabOrder(m_regExp, m_regExpItem); 00203 setTabOrder(m_regExpItem, m_replace); 00204 setTabOrder(m_replace, m_backRef); 00205 setTabOrder(m_backRef, m_backRefItem); 00206 setTabOrder(m_backRefItem, m_caseSensitive); 00207 setTabOrder(m_caseSensitive, m_wholeWordsOnly); 00208 setTabOrder(m_wholeWordsOnly, m_fromCursor); 00209 setTabOrder(m_fromCursor, m_findBackwards); 00210 setTabOrder(m_findBackwards, m_selectedText); 00211 setTabOrder(m_selectedText, m_promptOnReplace); 00212 00213 // buddies 00214 m_findLabel->setBuddy(m_find); 00215 m_replaceLabel->setBuddy(m_replace); 00216 00217 if (!forReplace) 00218 { 00219 m_promptOnReplace->hide(); 00220 m_replaceGrp->hide(); 00221 } 00222 00223 d->findStrings = findStrings; 00224 m_find->setFocus(); 00225 enableButtonOK( !pattern().isEmpty() ); 00226 if (forReplace) 00227 { 00228 setButtonOKText(i18n("&Replace"), 00229 i18n("Start replace"), 00230 i18n("<qt>If you press the <b>Replace</b> button, the text you entered " 00231 "above is searched for within the document and any occurrence is " 00232 "replaced with the replacement text.</qt>")); 00233 } 00234 else 00235 { 00236 setButtonOK( KGuiItem(i18n("&Find"),"find", 00237 i18n("Start searching"), 00238 i18n("<qt>If you press the <b>Find</b> button, the text you entered " 00239 "above is searched for within the document.</qt>")) ); 00240 } 00241 } 00242 00243 void KFindDialog::textSearchChanged( const QString & text) 00244 { 00245 enableButtonOK( !text.isEmpty() ); 00246 } 00247 00248 void KFindDialog::showEvent( QShowEvent *e ) 00249 { 00250 if ( !d->m_initialShowDone ) 00251 { 00252 d->m_initialShowDone = true; // only once 00253 kdDebug() << "showEvent\n"; 00254 if (!d->findStrings.isEmpty()) 00255 setFindHistory(d->findStrings); 00256 d->findStrings = QStringList(); 00257 if (!d->pattern.isEmpty()) { 00258 m_find->lineEdit()->setText( d->pattern ); 00259 m_find->lineEdit()->selectAll(); 00260 d->pattern = QString::null; 00261 } 00262 } 00263 KDialogBase::showEvent(e); 00264 } 00265 00266 long KFindDialog::options() const 00267 { 00268 long options = 0; 00269 00270 if (m_caseSensitive->isChecked()) 00271 options |= CaseSensitive; 00272 if (m_wholeWordsOnly->isChecked()) 00273 options |= WholeWordsOnly; 00274 if (m_fromCursor->isChecked()) 00275 options |= FromCursor; 00276 if (m_findBackwards->isChecked()) 00277 options |= FindBackwards; 00278 if (m_selectedText->isChecked()) 00279 options |= SelectedText; 00280 if (m_regExp->isChecked()) 00281 options |= RegularExpression; 00282 return options; 00283 } 00284 00285 QString KFindDialog::pattern() const 00286 { 00287 return m_find->currentText(); 00288 } 00289 00290 void KFindDialog::setPattern (const QString &pattern) 00291 { 00292 m_find->lineEdit()->setText( pattern ); 00293 m_find->lineEdit()->selectAll(); 00294 d->pattern = pattern; 00295 kdDebug() << "setPattern " << pattern<<endl; 00296 } 00297 00298 void KFindDialog::setFindHistory(const QStringList &strings) 00299 { 00300 if (strings.count() > 0) 00301 { 00302 m_find->setHistoryItems(strings, true); 00303 m_find->lineEdit()->setText( strings.first() ); 00304 m_find->lineEdit()->selectAll(); 00305 } 00306 else 00307 m_find->clearHistory(); 00308 } 00309 00310 void KFindDialog::setHasSelection(bool hasSelection) 00311 { 00312 d->m_hasSelection = hasSelection; 00313 m_selectedText->setEnabled( hasSelection ); 00314 if ( !hasSelection ) 00315 { 00316 m_selectedText->setChecked( false ); 00317 slotSelectedTextToggled( hasSelection ); 00318 } 00319 } 00320 00321 void KFindDialog::slotSelectedTextToggled(bool selec) 00322 { 00323 // From cursor doesn't make sense if we have a selection 00324 m_fromCursor->setEnabled( !selec && d->m_hasCursor ); 00325 if ( selec ) // uncheck if disabled 00326 m_fromCursor->setChecked( false ); 00327 } 00328 00329 void KFindDialog::setHasCursor(bool hasCursor) 00330 { 00331 d->m_hasCursor = hasCursor; 00332 m_fromCursor->setEnabled( hasCursor ); 00333 m_fromCursor->setChecked( hasCursor && (options() & FromCursor) ); 00334 } 00335 00336 void KFindDialog::setOptions(long options) 00337 { 00338 m_caseSensitive->setChecked(options & CaseSensitive); 00339 m_wholeWordsOnly->setChecked(options & WholeWordsOnly); 00340 m_fromCursor->setChecked(d->m_hasCursor && (options & FromCursor)); 00341 m_findBackwards->setChecked(options & FindBackwards); 00342 m_selectedText->setChecked(d->m_hasSelection && (options & SelectedText)); 00343 m_regExp->setChecked(options & RegularExpression); 00344 } 00345 00346 // Create a popup menu with a list of regular expression terms, to help the user 00347 // compose a regular expression search pattern. 00348 void KFindDialog::showPatterns() 00349 { 00350 if ( !d->m_regexpDialogQueryDone ) 00351 { 00352 d->m_regexpDialog = KParts::ComponentFactory::createInstanceFromQuery<QDialog>( "KRegExpEditor/KRegExpEditor", QString::null, this ); 00353 d->m_regexpDialogQueryDone = true; 00354 } 00355 00356 if ( d->m_regexpDialog ) 00357 { 00358 KRegExpEditorInterface *iface = static_cast<KRegExpEditorInterface *>( d->m_regexpDialog->qt_cast( "KRegExpEditorInterface" ) ); 00359 assert( iface ); 00360 00361 iface->setRegExp( pattern() ); 00362 if ( d->m_regexpDialog->exec() == QDialog::Accepted ) 00363 setPattern( iface->regExp() ); 00364 } 00365 else // No complete regexp-editor available, bring up the old popupmenu 00366 { 00367 typedef struct 00368 { 00369 const char *description; 00370 const char *regExp; 00371 int cursorAdjustment; 00372 } term; 00373 static const term items[] = 00374 { 00375 { I18N_NOOP("Any Character"), ".", 0 }, 00376 { I18N_NOOP("Start of Line"), "^", 0 }, 00377 { I18N_NOOP("End of Line"), "$", 0 }, 00378 { I18N_NOOP("Set of Characters"), "[]", -1 }, 00379 { I18N_NOOP("Repeats, Zero or More Times"), "*", 0 }, 00380 { I18N_NOOP("Repeats, One or More Times"), "+", 0 }, 00381 { I18N_NOOP("Optional"), "?", 0 }, 00382 { I18N_NOOP("Escape"), "\\", 0 }, 00383 { I18N_NOOP("TAB"), "\\t", 0 }, 00384 { I18N_NOOP("Newline"), "\\n", 0 }, 00385 { I18N_NOOP("Carriage Return"), "\\r", 0 }, 00386 { I18N_NOOP("White Space"), "\\s", 0 }, 00387 { I18N_NOOP("Digit"), "\\d", 0 }, 00388 }; 00389 int i; 00390 00391 // Populate the popup menu. 00392 if (!m_patterns) 00393 { 00394 m_patterns = new QPopupMenu(this); 00395 for (i = 0; (unsigned)i < sizeof(items) / sizeof(items[0]); i++) 00396 { 00397 m_patterns->insertItem(i18n(items[i].description), i, i); 00398 } 00399 } 00400 00401 // Insert the selection into the edit control. 00402 i = m_patterns->exec(m_regExpItem->mapToGlobal(m_regExpItem->rect().bottomLeft())); 00403 if (i != -1) 00404 { 00405 QLineEdit *editor = m_find->lineEdit(); 00406 00407 editor->insert(items[i].regExp); 00408 editor->setCursorPosition(editor->cursorPosition() + items[i].cursorAdjustment); 00409 } 00410 } 00411 } 00412 00413 // Create a popup menu with a list of backreference terms, to help the user 00414 // compose a regular expression replacement pattern. 00415 void KFindDialog::showPlaceholders() 00416 { 00417 typedef struct 00418 { 00419 const char *description; 00420 const char *backRef; 00421 } term; 00422 static const term items[] = 00423 { 00424 { I18N_NOOP("Complete text found"), "\\0" }, 00425 }; 00426 int i; 00427 00428 // Populate the popup menu. 00429 if (!m_placeholders) 00430 { 00431 m_placeholders = new QPopupMenu(this); 00432 for (i = 0; (unsigned)i < sizeof(items) / sizeof(items[0]); i++) 00433 { 00434 m_placeholders->insertItem(i18n(items[i].description), i, i); 00435 } 00436 } 00437 00438 // Insert the selection into the edit control. 00439 i = m_placeholders->exec(m_backRefItem->mapToGlobal(m_backRefItem->rect().bottomLeft())); 00440 if (i != -1) 00441 { 00442 QLineEdit *editor = m_replace->lineEdit(); 00443 00444 editor->insert(items[i].backRef); 00445 } 00446 } 00447 00448 void KFindDialog::slotOk() 00449 { 00450 // Nothing to find? 00451 if (pattern().isEmpty()) 00452 { 00453 KMessageBox::error(this, i18n("You must enter some text to search for.")); 00454 return; 00455 } 00456 00457 if (m_regExp->isChecked()) 00458 { 00459 // Check for a valid regular expression. 00460 QRegExp regExp(pattern()); 00461 00462 if (!regExp.isValid()) 00463 { 00464 KMessageBox::error(this, i18n("Invalid regular expression.")); 00465 return; 00466 } 00467 } 00468 m_find->addToHistory(pattern()); 00469 emit okClicked(); 00470 if ( testWFlags( WShowModal ) ) 00471 accept(); 00472 } 00473 00474 #include "kfinddialog.moc"
KDE Logo
This file is part of the documentation for kutils Library Version 3.2.3.
Documentation copyright © 1996-2004 the KDE developers.
Generated on Sat Jun 12 15:09:15 2004 by doxygen 1.3.7 written by Dimitri van Heesch, © 1997-2003