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.2.
Documentation copyright © 1996-2004 the KDE developers.
Generated on Sun May 16 22:04:33 2004 by doxygen 1.2.15 written by Dimitri van Heesch, © 1997-2003