Robert Bieber | e6fd3d0 | 2010-07-23 07:31:53 +0000 | [diff] [blame] | 1 | /* |
| 2 | * Copyright (C) 2009 Lorenzo Bettini <http://www.lorenzobettini.it> |
| 3 | * See COPYING file that comes with this distribution |
| 4 | */ |
| 5 | |
| 6 | #include <QtGui> |
| 7 | #include <QTextEdit> |
| 8 | #include <QRegExp> |
| 9 | #include <QSettings> |
| 10 | |
| 11 | #include "varianteditor.h" |
| 12 | #include "findreplaceform.h" |
| 13 | #include "ui_findreplaceform.h" |
| 14 | |
| 15 | #define TEXT_TO_FIND "textToFind" |
| 16 | #define TEXT_TO_REPLACE "textToReplace" |
| 17 | #define DOWN_RADIO "downRadio" |
| 18 | #define UP_RADIO "upRadio" |
| 19 | #define CASE_CHECK "caseCheck" |
| 20 | #define WHOLE_CHECK "wholeCheck" |
| 21 | #define REGEXP_CHECK "regexpCheck" |
| 22 | |
| 23 | FindReplaceForm::FindReplaceForm(QWidget *parent) : |
| 24 | QWidget(parent), |
| 25 | ui(new Ui::FindReplaceForm), textEdit(0) |
| 26 | { |
| 27 | ui->setupUi(this); |
| 28 | |
| 29 | ui->errorLabel->setText(""); |
| 30 | |
| 31 | connect(ui->textToFind, SIGNAL(textChanged(QString)), this, SLOT(textToFindChanged())); |
| 32 | connect(ui->textToFind, SIGNAL(textChanged(QString)), this, SLOT(validateRegExp(QString))); |
| 33 | |
| 34 | connect(ui->regexCheckBox, SIGNAL(toggled(bool)), this, SLOT(regexpSelected(bool))); |
| 35 | |
| 36 | connect(ui->findButton, SIGNAL(clicked()), this, SLOT(find())); |
| 37 | connect(ui->closeButton, SIGNAL(clicked()), parent, SLOT(close())); |
| 38 | |
| 39 | connect(ui->replaceButton, SIGNAL(clicked()), this, SLOT(replace())); |
| 40 | connect(ui->replaceAllButton, SIGNAL(clicked()), this, SLOT(replaceAll())); |
| 41 | } |
| 42 | |
| 43 | FindReplaceForm::~FindReplaceForm() |
| 44 | { |
| 45 | delete ui; |
| 46 | if(textEdit) |
| 47 | delete textEdit; |
| 48 | } |
| 49 | |
| 50 | void FindReplaceForm::hideReplaceWidgets() { |
| 51 | ui->replaceLabel->setVisible(false); |
| 52 | ui->textToReplace->setVisible(false); |
| 53 | ui->replaceButton->setVisible(false); |
| 54 | ui->replaceAllButton->setVisible(false); |
| 55 | } |
| 56 | |
| 57 | void FindReplaceForm::setTextEdit(QTextEdit *textEdit_) { |
| 58 | textEdit = new VariantEditor(textEdit_); |
| 59 | textEdit->connectToSetEnabled(ui->replaceButton); |
| 60 | textEdit->connectToSetEnabled(ui->replaceAllButton); |
| 61 | } |
| 62 | |
| 63 | void FindReplaceForm::setTextEdit(QPlainTextEdit *textEdit_) |
| 64 | { |
| 65 | textEdit = new VariantEditor(textEdit_); |
| 66 | textEdit->connectToSetEnabled(ui->replaceButton); |
| 67 | textEdit->connectToSetEnabled(ui->replaceAllButton); |
| 68 | } |
| 69 | |
| 70 | void FindReplaceForm::changeEvent(QEvent *e) |
| 71 | { |
| 72 | QWidget::changeEvent(e); |
| 73 | switch (e->type()) { |
| 74 | case QEvent::LanguageChange: |
| 75 | ui->retranslateUi(this); |
| 76 | break; |
| 77 | default: |
| 78 | break; |
| 79 | } |
| 80 | } |
| 81 | |
| 82 | void FindReplaceForm::textToFindChanged() { |
| 83 | ui->findButton->setEnabled(ui->textToFind->text().size() > 0); |
| 84 | } |
| 85 | |
| 86 | void FindReplaceForm::regexpSelected(bool sel) { |
| 87 | if (sel) |
| 88 | validateRegExp(ui->textToFind->text()); |
| 89 | else |
| 90 | validateRegExp(""); |
| 91 | } |
| 92 | |
| 93 | void FindReplaceForm::validateRegExp(const QString &text) { |
| 94 | if (!ui->regexCheckBox->isChecked() || text.size() == 0) { |
| 95 | ui->errorLabel->setText(""); |
| 96 | return; // nothing to validate |
| 97 | } |
| 98 | |
| 99 | QRegExp reg(text, |
| 100 | (ui->caseCheckBox->isChecked() ? Qt::CaseSensitive : Qt::CaseInsensitive)); |
| 101 | |
| 102 | if (reg.isValid()) { |
| 103 | showError(""); |
| 104 | } else { |
| 105 | showError(reg.errorString()); |
| 106 | } |
| 107 | } |
| 108 | |
| 109 | void FindReplaceForm::showError(const QString &error) { |
| 110 | if (error == "") { |
| 111 | ui->errorLabel->setText(""); |
| 112 | } else { |
| 113 | ui->errorLabel->setText("<span style=\" font-weight:600; color:#ff0000;\">" + |
| 114 | error + |
| 115 | "</span>"); |
| 116 | } |
| 117 | } |
| 118 | |
| 119 | void FindReplaceForm::showMessage(const QString &message) { |
| 120 | if (message == "") { |
| 121 | ui->errorLabel->setText(""); |
| 122 | } else { |
| 123 | ui->errorLabel->setText("<span style=\" font-weight:600; color:green;\">" + |
| 124 | message + |
| 125 | "</span>"); |
| 126 | } |
| 127 | } |
| 128 | |
| 129 | void FindReplaceForm::find() { |
| 130 | find(ui->downRadioButton->isChecked()); |
| 131 | } |
| 132 | |
| 133 | void FindReplaceForm::find(bool next) { |
| 134 | if (!textEdit) |
| 135 | return; // TODO: show some warning? |
| 136 | |
| 137 | // backward search |
| 138 | bool back = !next; |
| 139 | |
| 140 | const QString &toSearch = ui->textToFind->text(); |
| 141 | |
| 142 | bool result = false; |
| 143 | |
| 144 | QTextDocument::FindFlags flags; |
| 145 | |
| 146 | if (back) |
| 147 | flags |= QTextDocument::FindBackward; |
| 148 | if (ui->caseCheckBox->isChecked()) |
| 149 | flags |= QTextDocument::FindCaseSensitively; |
| 150 | if (ui->wholeCheckBox->isChecked()) |
| 151 | flags |= QTextDocument::FindWholeWords; |
| 152 | |
| 153 | if (ui->regexCheckBox->isChecked()) { |
| 154 | QRegExp reg(toSearch, |
| 155 | (ui->caseCheckBox->isChecked() ? Qt::CaseSensitive : Qt::CaseInsensitive)); |
| 156 | |
| 157 | qDebug() << "searching for regexp: " << reg.pattern(); |
| 158 | |
| 159 | textCursor = textEdit->document()->find(reg, textCursor, flags); |
| 160 | textEdit->setTextCursor(textCursor); |
| 161 | result = (!textCursor.isNull()); |
| 162 | } else { |
| 163 | qDebug() << "searching for: " << toSearch; |
| 164 | |
| 165 | result = textEdit->find(toSearch, flags); |
| 166 | } |
| 167 | |
| 168 | if (result) { |
| 169 | showError(""); |
| 170 | } else { |
| 171 | showError(tr("no match found")); |
| 172 | // move to the beginning of the document for the next find |
| 173 | textEdit->setTextCursor(QTextCursor(textEdit->document()->begin())); |
| 174 | } |
| 175 | } |
| 176 | |
| 177 | void FindReplaceForm::replace() { |
| 178 | if (!textEdit->textCursor().hasSelection()) { |
| 179 | find(); |
| 180 | } else { |
| 181 | textEdit->textCursor().insertText(ui->textToReplace->text()); |
| 182 | find(); |
| 183 | } |
| 184 | } |
| 185 | |
| 186 | void FindReplaceForm::replaceAll() { |
| 187 | int i=0; |
| 188 | while (textEdit->textCursor().hasSelection()){ |
| 189 | textEdit->textCursor().insertText(ui->textToReplace->text()); |
| 190 | find(); |
| 191 | i++; |
| 192 | } |
| 193 | showMessage(tr("Replaced %1 occurrence(s)").arg(i)); |
| 194 | } |
| 195 | |
| 196 | void FindReplaceForm::writeSettings(QSettings &settings, const QString &prefix) { |
| 197 | settings.beginGroup(prefix); |
| 198 | settings.setValue(TEXT_TO_FIND, ui->textToFind->text()); |
| 199 | settings.setValue(TEXT_TO_REPLACE, ui->textToReplace->text()); |
| 200 | settings.setValue(DOWN_RADIO, ui->downRadioButton->isChecked()); |
| 201 | settings.setValue(UP_RADIO, ui->upRadioButton->isChecked()); |
| 202 | settings.setValue(CASE_CHECK, ui->caseCheckBox->isChecked()); |
| 203 | settings.setValue(WHOLE_CHECK, ui->wholeCheckBox->isChecked()); |
| 204 | settings.setValue(REGEXP_CHECK, ui->regexCheckBox->isChecked()); |
| 205 | settings.endGroup(); |
| 206 | } |
| 207 | |
| 208 | void FindReplaceForm::readSettings(QSettings &settings, const QString &prefix) { |
| 209 | settings.beginGroup(prefix); |
| 210 | ui->textToFind->setText(settings.value(TEXT_TO_FIND, "").toString()); |
| 211 | ui->textToReplace->setText(settings.value(TEXT_TO_REPLACE, "").toString()); |
| 212 | ui->downRadioButton->setChecked(settings.value(DOWN_RADIO, true).toBool()); |
| 213 | ui->upRadioButton->setChecked(settings.value(UP_RADIO, false).toBool()); |
| 214 | ui->caseCheckBox->setChecked(settings.value(CASE_CHECK, false).toBool()); |
| 215 | ui->wholeCheckBox->setChecked(settings.value(WHOLE_CHECK, false).toBool()); |
| 216 | ui->regexCheckBox->setChecked(settings.value(REGEXP_CHECK, false).toBool()); |
| 217 | settings.endGroup(); |
| 218 | } |