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     QDialog* m_regexpDialog;
00045     bool m_regexpDialogQueryDone;
00046     bool m_hasCursor;
00047     bool m_hasSelection;
00048     QStringList findStrings;
00049     QString pattern;
00050 };
00051 
00052 KFindDialog::KFindDialog(QWidget *parent, const char *name, long options, const QStringList &findStrings, bool hasSelection) :
00053     KDialogBase(parent, name, true, i18n("Find Text"), Ok | Cancel, Ok),
00054     m_findExtension (0),
00055     m_replaceExtension (0)
00056 {
00057     d = new KFindDialogPrivate;
00058     init(false, findStrings, hasSelection);
00059     setOptions(options);
00060 }
00061 
00062 KFindDialog::KFindDialog(QWidget *parent, const char *name, bool /*forReplace*/) :
00063     KDialogBase(parent, name, true, i18n("Replace Text"), Ok | Cancel, Ok),
00064     m_findExtension (0),
00065     m_replaceExtension (0)
00066 {
00067     d = new KFindDialogPrivate;
00068 }
00069 
00070 KFindDialog::~KFindDialog()
00071 {
00072     delete d;
00073 }
00074 
00075 QWidget *KFindDialog::findExtension()
00076 {
00077     if (!m_findExtension)
00078     {
00079       m_findExtension = new QWidget(m_findGrp);
00080       m_findLayout->addMultiCellWidget(m_findExtension, 3, 3, 0, 1);
00081     }
00082 
00083     return m_findExtension;
00084 }
00085 
00086 QStringList KFindDialog::findHistory() const
00087 {
00088     return m_find->historyItems();
00089 }
00090 
00091 void KFindDialog::init(bool forReplace, const QStringList &findStrings, bool hasSelection)
00092 {
00093     QVBoxLayout *topLayout;
00094     QGridLayout *optionsLayout;
00095 
00096     // Create common parts of dialog.
00097     QWidget *page = new QWidget(this);
00098     setMainWidget(page);
00099 
00100     topLayout = new QVBoxLayout(page);
00101     topLayout->setSpacing( KDialog::spacingHint() );
00102     topLayout->setMargin( KDialog::marginHint() );
00103 
00104     m_findGrp = new QGroupBox(0, Qt::Vertical, i18n("Find"), page);
00105     m_findGrp->layout()->setSpacing( KDialog::spacingHint() );
00106    // m_findGrp->layout()->setMargin( KDialog::marginHint() );
00107     m_findLayout = new QGridLayout(m_findGrp->layout());
00108     m_findLayout->setSpacing( KDialog::spacingHint() );
00109    // m_findLayout->setMargin( KDialog::marginHint() );
00110 
00111     m_findLabel = new QLabel(i18n("&Text to find:"), m_findGrp);
00112     m_find = new KHistoryCombo(true, m_findGrp);
00113     m_find->setMaxCount(10);
00114     m_find->setDuplicatesEnabled(false);
00115     m_regExp = new QCheckBox(i18n("&Regular expression"), m_findGrp);
00116     m_regExpItem = new QPushButton(i18n("&Edit..."), m_findGrp);
00117     m_regExpItem->setEnabled(false);
00118 
00119     m_findLayout->addWidget(m_findLabel, 0, 0);
00120     m_findLayout->addMultiCellWidget(m_find, 1, 1, 0, 1);
00121     m_findLayout->addWidget(m_regExp, 2, 0);
00122     m_findLayout->addWidget(m_regExpItem, 2, 1);
00123     topLayout->addWidget(m_findGrp);
00124 
00125     m_replaceGrp = new QGroupBox(0, Qt::Vertical, i18n("Replace With"), page);
00126     m_replaceGrp->layout()->setSpacing( KDialog::spacingHint() );
00127   //  m_replaceGrp->layout()->setMargin( KDialog::marginHint() );
00128     m_replaceLayout = new QGridLayout(m_replaceGrp->layout());
00129     m_replaceLayout->setSpacing( KDialog::spacingHint() );
00130 //    m_replaceLayout->setMargin( KDialog::marginHint() );
00131 
00132     m_replaceLabel = new QLabel(i18n("&Replacement text:"), m_replaceGrp);
00133     m_replace = new KHistoryCombo(true, m_replaceGrp);
00134     m_replace->setMaxCount(10);
00135     m_replace->setDuplicatesEnabled(false);
00136     m_backRef = new QCheckBox(i18n("Us&e placeholders"), m_replaceGrp);
00137     m_backRefItem = new QPushButton(i18n("Insert Place&holder"), m_replaceGrp);
00138     m_backRefItem->setEnabled(false);
00139 
00140     m_replaceLayout->addWidget(m_replaceLabel, 0, 0);
00141     m_replaceLayout->addMultiCellWidget(m_replace, 1, 1, 0, 1);
00142     m_replaceLayout->addWidget(m_backRef, 2, 0);
00143     m_replaceLayout->addWidget(m_backRefItem, 2, 1);
00144     topLayout->addWidget(m_replaceGrp);
00145 
00146     m_optionGrp = new QGroupBox(0, Qt::Vertical, i18n("Options"), page);
00147     m_optionGrp->layout()->setSpacing(KDialog::spacingHint());
00148   //  m_optionGrp->layout()->setMargin(KDialog::marginHint());
00149     optionsLayout = new QGridLayout(m_optionGrp->layout());
00150     optionsLayout->setSpacing( KDialog::spacingHint() );
00151    // optionsLayout->setMargin( KDialog::marginHint() );
00152 
00153     m_caseSensitive = new QCheckBox(i18n("C&ase sensitive"), m_optionGrp);
00154     m_wholeWordsOnly = new QCheckBox(i18n("&Whole words only"), m_optionGrp);
00155     m_fromCursor = new QCheckBox(i18n("&From cursor"), m_optionGrp);
00156     m_findBackwards = new QCheckBox(i18n("Find &backwards"), m_optionGrp);
00157     m_selectedText = new QCheckBox(i18n("&Selected text"), m_optionGrp);
00158     setHasSelection( hasSelection );
00159     m_promptOnReplace = new QCheckBox(i18n("&Prompt on replace"), m_optionGrp);
00160     m_promptOnReplace->setChecked( true );
00161 
00162     optionsLayout->addWidget(m_caseSensitive, 0, 0);
00163     optionsLayout->addWidget(m_wholeWordsOnly, 1, 0);
00164     optionsLayout->addWidget(m_fromCursor, 2, 0);
00165     optionsLayout->addWidget(m_findBackwards, 0, 1);
00166     optionsLayout->addWidget(m_selectedText, 1, 1);
00167     optionsLayout->addWidget(m_promptOnReplace, 2, 1);
00168     topLayout->addWidget(m_optionGrp);
00169 
00170     // We delay creation of these until needed.
00171     m_patterns = 0L;
00172     m_placeholders = 0L;
00173 
00174     // signals and slots connections
00175     connect(m_selectedText, SIGNAL(toggled(bool)), this, SLOT(slotSelectedTextToggled(bool)));
00176     connect(m_regExp, SIGNAL(toggled(bool)), m_regExpItem, SLOT(setEnabled(bool)));
00177     connect(m_backRef, SIGNAL(toggled(bool)), m_backRefItem, SLOT(setEnabled(bool)));
00178     connect(m_regExpItem, SIGNAL(pressed()), this, SLOT(showPatterns()));
00179     connect(m_backRefItem, SIGNAL(pressed()), this, SLOT(showPlaceholders()));
00180 
00181     connect(m_find, SIGNAL(textChanged ( const QString & )),this, SLOT(textSearchChanged( const QString & )));
00182 
00183     // tab order
00184     setTabOrder(m_find, m_regExp);
00185     setTabOrder(m_regExp, m_regExpItem);
00186     setTabOrder(m_regExpItem, m_replace);
00187     setTabOrder(m_replace, m_backRef);
00188     setTabOrder(m_backRef, m_backRefItem);
00189     setTabOrder(m_backRefItem, m_caseSensitive);
00190     setTabOrder(m_caseSensitive, m_wholeWordsOnly);
00191     setTabOrder(m_wholeWordsOnly, m_fromCursor);
00192     setTabOrder(m_fromCursor, m_findBackwards);
00193     setTabOrder(m_findBackwards, m_selectedText);
00194     setTabOrder(m_selectedText, m_promptOnReplace);
00195 
00196     // buddies
00197     m_findLabel->setBuddy(m_find);
00198     m_replaceLabel->setBuddy(m_replace);
00199 
00200     if (!forReplace)
00201     {
00202         m_promptOnReplace->hide();
00203         m_replaceGrp->hide();
00204     }
00205 
00206     d->findStrings = findStrings;
00207     m_find->setFocus();
00208     enableButtonOK( !pattern().isEmpty() );
00209 }
00210 
00211 void KFindDialog::textSearchChanged( const QString & text)
00212 {
00213     enableButtonOK( !text.isEmpty() );
00214 }
00215 
00216 void KFindDialog::showEvent( QShowEvent *e )
00217 {
00218     kdDebug() << "showEvent\n";
00219     if (!d->findStrings.isEmpty())
00220         setFindHistory(d->findStrings);
00221     d->findStrings = QStringList();
00222     if (!d->pattern.isEmpty()) {
00223         m_find->lineEdit()->setText( d->pattern );
00224         m_find->lineEdit()->selectAll();
00225         d->pattern = QString::null;
00226     }
00227     KDialogBase::showEvent(e);
00228 }
00229 
00230 long KFindDialog::options() const
00231 {
00232     long options = 0;
00233 
00234     if (m_caseSensitive->isChecked())
00235         options |= CaseSensitive;
00236     if (m_wholeWordsOnly->isChecked())
00237         options |= WholeWordsOnly;
00238     if (m_fromCursor->isChecked())
00239         options |= FromCursor;
00240     if (m_findBackwards->isChecked())
00241         options |= FindBackwards;
00242     if (m_selectedText->isChecked())
00243         options |= SelectedText;
00244     if (m_regExp->isChecked())
00245         options |= RegularExpression;
00246     return options;
00247 }
00248 
00249 QString KFindDialog::pattern() const
00250 {
00251     return m_find->currentText();
00252 }
00253 
00254 void KFindDialog::setPattern (const QString &pattern)
00255 {
00256     m_find->lineEdit()->setText( pattern );
00257     m_find->lineEdit()->selectAll();
00258     d->pattern = pattern;
00259     kdDebug() << "setPattern " << pattern<<endl;
00260 }
00261 
00262 void KFindDialog::setFindHistory(const QStringList &strings)
00263 {
00264     if (strings.count() > 0)
00265     {
00266         m_find->setHistoryItems(strings, true);
00267         m_find->lineEdit()->setText( strings.first() );
00268         m_find->lineEdit()->selectAll();
00269     }
00270     else
00271         m_find->clearHistory();
00272 }
00273 
00274 void KFindDialog::setHasSelection(bool hasSelection)
00275 {
00276     d->m_hasSelection = hasSelection;
00277     m_selectedText->setEnabled( hasSelection );
00278     // If we have a selection, we make 'find in selection' default
00279     // and if we don't, then the option has to be unchecked, obviously.
00280     m_selectedText->setChecked( hasSelection );
00281     slotSelectedTextToggled( hasSelection );
00282 }
00283 
00284 void KFindDialog::slotSelectedTextToggled(bool selec)
00285 {
00286     // From cursor doesn't make sense if we have a selection
00287     m_fromCursor->setEnabled( !selec && d->m_hasCursor );
00288     if ( selec ) // uncheck if disabled
00289         m_fromCursor->setChecked( false );
00290 }
00291 
00292 void KFindDialog::setHasCursor(bool hasCursor)
00293 {
00294     d->m_hasCursor = hasCursor;
00295     m_fromCursor->setEnabled( hasCursor );
00296     m_fromCursor->setChecked( hasCursor && (options() & FromCursor) );
00297 }
00298 
00299 void KFindDialog::setOptions(long options)
00300 {
00301     m_caseSensitive->setChecked(options & CaseSensitive);
00302     m_wholeWordsOnly->setChecked(options & WholeWordsOnly);
00303     m_fromCursor->setChecked(d->m_hasCursor && (options & FromCursor));
00304     m_findBackwards->setChecked(options & FindBackwards);
00305     m_selectedText->setChecked(d->m_hasSelection && (options & SelectedText));
00306     m_regExp->setChecked(options & RegularExpression);
00307 }
00308 
00309 // Create a popup menu with a list of regular expression terms, to help the user
00310 // compose a regular expression search pattern.
00311 void KFindDialog::showPatterns()
00312 {
00313     if ( !d->m_regexpDialogQueryDone )
00314     {
00315         d->m_regexpDialog = KParts::ComponentFactory::createInstanceFromQuery<QDialog>( "KRegExpEditor/KRegExpEditor", QString::null, this );
00316         d->m_regexpDialogQueryDone = true;
00317     }
00318 
00319     if ( d->m_regexpDialog )
00320     {
00321         KRegExpEditorInterface *iface = static_cast<KRegExpEditorInterface *>( d->m_regexpDialog->qt_cast( "KRegExpEditorInterface" ) );
00322         assert( iface );
00323 
00324         iface->setRegExp( pattern() );
00325         if ( d->m_regexpDialog->exec() == QDialog::Accepted )
00326             setPattern( iface->regExp() );
00327     }
00328     else // No complete regexp-editor available, bring up the old popupmenu
00329     {
00330         typedef struct
00331         {
00332             const char *description;
00333             const char *regExp;
00334             int cursorAdjustment;
00335         } term;
00336         static const term items[] =
00337             {
00338                 { I18N_NOOP("Any Character"),                 ".",        0 },
00339                 { I18N_NOOP("Start of Line"),                 "^",        0 },
00340                 { I18N_NOOP("End of Line"),                   "$",        0 },
00341                 { I18N_NOOP("Set of Characters"),             "[]",       -1 },
00342                 { I18N_NOOP("Repeats, Zero or More Times"),   "*",        0 },
00343                 { I18N_NOOP("Repeats, One or More Times"),    "+",        0 },
00344                 { I18N_NOOP("Optional"),                      "?",        0 },
00345                 { I18N_NOOP("Escape"),                        "\\",       0 },
00346                 { I18N_NOOP("TAB"),                           "\\t",      0 },
00347                 { I18N_NOOP("Newline"),                       "\\n",      0 },
00348                 { I18N_NOOP("Carriage Return"),               "\\r",      0 },
00349                 { I18N_NOOP("White Space"),                   "\\s",      0 },
00350                 { I18N_NOOP("Digit"),                         "\\d",      0 },
00351             };
00352         int i;
00353 
00354         // Populate the popup menu.
00355         if (!m_patterns)
00356         {
00357             m_patterns = new QPopupMenu(this);
00358             for (i = 0; (unsigned)i < sizeof(items) / sizeof(items[0]); i++)
00359             {
00360                 m_patterns->insertItem(i18n(items[i].description), i, i);
00361             }
00362         }
00363 
00364         // Insert the selection into the edit control.
00365         i = m_patterns->exec(QCursor::pos());
00366         if (i != -1)
00367         {
00368             QLineEdit *editor = m_find->lineEdit();
00369 
00370             editor->insert(items[i].regExp);
00371             editor->setCursorPosition(editor->cursorPosition() + items[i].cursorAdjustment);
00372         }
00373     }
00374 }
00375 
00376 // Create a popup menu with a list of backreference terms, to help the user
00377 // compose a regular expression replacement pattern.
00378 void KFindDialog::showPlaceholders()
00379 {
00380     typedef struct
00381     {
00382         const char *description;
00383         const char *backRef;
00384     } term;
00385     static const term items[] =
00386     {
00387         { I18N_NOOP("Complete text found"),             "\\0" },
00388     };
00389     int i;
00390 
00391     // Populate the popup menu.
00392     if (!m_placeholders)
00393     {
00394         m_placeholders = new QPopupMenu(this);
00395         for (i = 0; (unsigned)i < sizeof(items) / sizeof(items[0]); i++)
00396         {
00397             m_placeholders->insertItem(i18n(items[i].description), i, i);
00398         }
00399     }
00400 
00401     // Insert the selection into the edit control.
00402     i = m_placeholders->exec(QCursor::pos());
00403     if (i != -1)
00404     {
00405         QLineEdit *editor = m_replace->lineEdit();
00406 
00407         editor->insert(items[i].backRef);
00408     }
00409 }
00410 
00411 void KFindDialog::slotOk()
00412 {
00413     // Nothing to find?
00414     if (pattern().isEmpty())
00415     {
00416         KMessageBox::error(this, i18n("You must enter some text to search for."));
00417         return;
00418     }
00419 
00420     if (m_regExp->isChecked())
00421     {
00422         // Check for a valid regular expression.
00423         QRegExp regExp(pattern());
00424 
00425         if (!regExp.isValid())
00426         {
00427             KMessageBox::error(this, i18n("Invalid regular expression."));
00428             return;
00429         }
00430     }
00431     m_find->addToHistory(pattern());
00432     emit okClicked();
00433     accept();
00434 }
00435 
00436 #include "kfinddialog.moc"
KDE Logo
This file is part of the documentation for kdelibs Version 3.1.4.
Documentation copyright © 1996-2002 the KDE developers.
Generated on Sun Feb 27 22:15:55 2005 by doxygen 1.3.4 written by Dimitri van Heesch, © 1997-2001