[prev in list] [next in list] [prev in thread] [next in thread]
List: kfm-devel
Subject: [PATCH] Textarea search, and spelling->KStdAction
From: George Staikos <staikos () kde ! org>
Date: 2003-09-25 7:29:24
[Download RAW message or body]
Attached is a patch that does two things:
1) Converts the spell check menu item to a standard action. This way if it
gets an accelerator in the future, it will "just work".
2) Most importantly, I implemented:
http://ask.slashdot.org/article.pl?sid=03/09/24/201231&mode=thread&tid=126&tid=185&tid=95
It isn't *perfect* yet which is why I did not apply this patch. I would
like some testing, and perhaps some help. This patch doesn't support regexps
at all, and I think the "find" is a bit clunky still (there is no "Find Next"
and trying to find again finds the same hit over again). In general it works
though.
Oh if someone has a slashdot account and cares, feel free to post a link to
this patch to show them that 49 (at this point) Slashdotters can talk about a
feature and form a committee in the same time that one person can implement
it. Reminds me of a joke about lightbulbs... :)
--
George Staikos
KDE Developer http://www.kde.org/
Staikos Computing Services Inc. http://www.staikos.net/
["textarea-search.patch" (text/x-diff)]
Index: render_form.cpp
===================================================================
RCS file: /home/kde/kdelibs/khtml/rendering/render_form.cpp,v
retrieving revision 1.235
diff -u -3 -p -r1.235 render_form.cpp
--- render_form.cpp 9 Sep 2003 16:31:55 -0000 1.235
+++ render_form.cpp 25 Sep 2003 07:17:12 -0000
@@ -23,13 +23,17 @@
* $Id: render_form.cpp,v 1.235 2003/09/09 16:31:55 pletourn Exp $
*/
-#include <kdebug.h>
-#include <klocale.h>
-#include <kfiledialog.h>
#include <kcompletionbox.h>
#include <kcursor.h>
-#include <kspell.h>
+#include <kdebug.h>
+#include <kfiledialog.h>
+#include <kfinddialog.h>
#include <kiconloader.h>
+#include <klocale.h>
+#include <kmessagebox.h>
+#include <kreplacedialog.h>
+#include <kspell.h>
+#include <kwin.h>
#include <qstyle.h>
@@ -289,15 +293,22 @@ LineEditWidget::LineEditWidget(DOM::HTML
: KLineEdit(parent), m_input(input), m_view(view), m_spell(0)
{
setMouseTracking(true);
+ KActionCollection *ac = new KActionCollection(this);
+ m_spellAction = KStdAction::spelling( this, SLOT( slotCheckSpelling() ), ac );
}
LineEditWidget::~LineEditWidget()
{
delete m_spell;
+ m_spell = 0L;
}
void LineEditWidget::slotCheckSpelling()
{
+ if ( text().isEmpty() ) {
+ return;
+ }
+
delete m_spell;
m_spell = new KSpell( this, i18n( "Spell Checking" ), this, SLOT( \
slotSpellCheckReady( KSpell *) ), 0, true, true);
@@ -346,29 +357,34 @@ void LineEditWidget::slotSpellCheckDone(
QPopupMenu *LineEditWidget::createPopupMenu()
{
QPopupMenu *popup = KLineEdit::createPopupMenu();
- if ( !popup )
+
+ if ( !popup ) {
return 0L;
+ }
+
connect( popup, SIGNAL( activated( int ) ),
this, SLOT( extendedMenuActivated( int ) ) );
if (m_input->autoComplete()) {
popup->insertSeparator();
int id = popup->insertItem( i18n("Clear &History"), ClearHistory );
- if (!completionObject())
- popup->setItemEnabled( id, false);
+ if (!completionObject()) {
+ popup->setItemEnabled( id, false );
+ }
}
if (echoMode() == QLineEdit::Normal &&
!isReadOnly()) {
popup->insertSeparator();
- int id = popup->insertItem( SmallIcon( "spellcheck" ), i18n( "Check \
Spelling" ), this, SLOT( slotCheckSpelling() ) );
- if( text().isEmpty() )
- popup->setItemEnabled( id, false );
+
+ m_spellAction->plug(popup);
+ m_spellAction->setEnabled( !text().isEmpty() );
}
return popup;
}
+
void LineEditWidget::extendedMenuActivated( int id)
{
switch ( id )
@@ -1248,7 +1264,7 @@ void RenderSelect::updateSelection()
// -------------------------------------------------------------------------
TextAreaWidget::TextAreaWidget(int wrap, QWidget* parent)
- : KTextEdit(parent)
+ : KTextEdit(parent), m_findDlg(0), m_repDlg(0)
{
setCheckSpellingEnabled( true );
@@ -1266,7 +1282,191 @@ TextAreaWidget::TextAreaWidget(int wrap,
setTextFormat(QTextEdit::PlainText);
setAutoMask(true);
setMouseTracking(true);
+
+ KActionCollection *ac = new KActionCollection(this);
+ m_findAction = KStdAction::find( this, SLOT( slotFind() ), ac );
+ m_replaceAction = KStdAction::replace( this, SLOT( slotReplace() ), ac );
+}
+
+
+TextAreaWidget::~TextAreaWidget()
+{
+ delete m_repDlg;
+ m_repDlg = 0L;
+ delete m_findDlg;
+ m_findDlg = 0L;
+}
+
+
+QPopupMenu *TextAreaWidget::createPopupMenu(const QPoint& pos)
+{
+ QPopupMenu *popup = KTextEdit::createPopupMenu(pos);
+
+ if ( !popup ) {
+ return 0L;
+ }
+
+ if (!isReadOnly()) {
+ popup->insertSeparator();
+
+ m_findAction->plug(popup);
+ m_findAction->setEnabled( !text().isEmpty() );
+
+ m_replaceAction->plug(popup);
+ m_replaceAction->setEnabled( !text().isEmpty() );
+ }
+
+ return popup;
+}
+
+
+void TextAreaWidget::slotFindNext()
+{
+ int index = 0, para = 0;
+ bool replace = m_repDlg && sender() == m_repDlg;
+ KFindDialog *dlg = 0L;
+
+ if (replace) {
+ dlg = m_repDlg;
+ } else {
+ dlg = m_findDlg;
+ }
+
+ if (!dlg) {
+ // Should really assert()
+ return;
+ }
+
+ QString pattern = dlg->pattern();
+ long options = dlg->options();
+
+ if (pattern.isEmpty()) {
+ dlg->hide();
+ return;
+ }
+
+ if (options & KFindDialog::FromCursor) {
+ getCursorPosition(¶, &index);
+ if (options & KFindDialog::FindBackwards) {
+ if (index == 0 && para == 0) {
+ dlg->hide();
+ return;
+ } else {
+ moveCursor(MoveBackward, false);
+ }
+ } else {
+ if (para == paragraphs() - 1 && index == paragraphLength(paragraphs() - \
1) - 1) { + dlg->hide();
+ return;
+ } else {
+ moveCursor(MoveForward, false);
+ }
+ }
+ } else if (options & KFindDialog::FindBackwards) {
+ para = paragraphs() - 1;
+ index = paragraphLength(para) - 1;
+ }
+
+ //kdDebug() << "Searching for " << pattern << " at " << para << " "
+ // << index << ", case: "
+ // << bool(options & KFindDialog::CaseSensitive)
+ // << ", whole words: "
+ // << bool(options & KFindDialog::WholeWordsOnly)
+ // << ", backwards: "
+ // << bool(options & KFindDialog::FindBackwards) << endl;
+
+ bool rc = find(pattern,
+ options & KFindDialog::CaseSensitive,
+ options & KFindDialog::WholeWordsOnly,
+ !(options & KFindDialog::FindBackwards),
+ ¶,
+ &index);
+
+ if (rc) {
+ setCursorPosition(para, index);
+ ensureCursorVisible();
+ dlg->setOptions(options | KFindDialog::FromCursor);
+ dlg->hide();
+ if (replace) {
+ bool prompt = m_repDlg->options() & KReplaceDialog::PromptOnReplace;
+ while (rc) {
+ int epara = 0, eindex = 0;
+ int forwardOffset = 0;
+
+ getSelection(¶, &index, &epara, &eindex);
+
+ QString replacement = m_repDlg->replacement();
+ if (prompt) {
+ int rc = KMessageBox::questionYesNo(this, i18n("Replace '%1' \
with '%2'?").arg(pattern).arg(replacement)); + if (rc == \
KMessageBox::Yes) { + removeSelectedText();
+ insertAt(replacement, para, index);
+ forwardOffset = replacement.length();
+ } else {
+ forwardOffset = 1;
+ }
+ } else {
+ removeSelectedText();
+ insertAt(replacement, para, index);
+ forwardOffset = replacement.length();
+ }
+
+ if (options & KFindDialog::FindBackwards) {
+ if (para == 0 && index == 0) {
+ break;
+ }
+ setCursorPosition(para, index);
+ for (int i = 0; i < pattern.length(); ++i) {
+ moveCursor(MoveBackward, false);
+ }
+ } else {
+ setCursorPosition(para, index + forwardOffset);
+ }
+
+ rc = find(pattern,
+ options & KFindDialog::CaseSensitive,
+ options & KFindDialog::WholeWordsOnly,
+ !(options & KFindDialog::FindBackwards),
+ 0, 0);
+ }
+ }
+ } else {
+ dlg->hide();
+ return;
+ }
}
+
+
+void TextAreaWidget::slotFind()
+{
+ if( text().isEmpty() ) // saves having to track the text changes
+ return;
+
+ if ( m_findDlg ) {
+ KWin::setActiveWindow( m_findDlg->winId() );
+ } else {
+ m_findDlg = new KFindDialog(false, this, "KHTML Text Area Find Dialog");
+ connect( m_findDlg, SIGNAL(okClicked()), this, SLOT(slotFindNext()) );
+ }
+ m_findDlg->show();
+}
+
+
+void TextAreaWidget::slotReplace()
+{
+ if( text().isEmpty() ) // saves having to track the text changes
+ return;
+
+ if ( m_repDlg ) {
+ KWin::setActiveWindow( m_repDlg->winId() );
+ } else {
+ m_repDlg = new KReplaceDialog(this, "KHTMLText Area Replace Dialog", 0,
+ QStringList(), QStringList(), false);
+ connect( m_repDlg, SIGNAL(okClicked()), this, SLOT(slotFindNext()) );
+ }
+ m_repDlg->show();
+}
+
bool TextAreaWidget::event( QEvent *e )
{
Index: render_form.h
===================================================================
RCS file: /home/kde/kdelibs/khtml/rendering/render_form.h,v
retrieving revision 1.99
diff -u -3 -p -r1.99 render_form.h
--- render_form.h 7 Sep 2003 20:52:28 -0000 1.99
+++ render_form.h 25 Sep 2003 07:17:13 -0000
@@ -47,6 +47,9 @@ class QListboxItem;
class KHTMLPartBrowserExtension;
class KSpell;
+class KFindDialog;
+class KReplaceDialog;
+class KAction;
namespace DOM {
class HTMLFormElementImpl;
@@ -260,6 +263,7 @@ private:
DOM::HTMLInputElementImpl* m_input;
KHTMLView* m_view;
KSpell *m_spell;
+ KAction *m_spellAction;
};
// -------------------------------------------------------------------------
@@ -397,15 +401,25 @@ protected slots:
};
// -------------------------------------------------------------------------
-
class TextAreaWidget : public KTextEdit
{
Q_OBJECT
public:
TextAreaWidget(int wrap, QWidget* parent);
+ virtual ~TextAreaWidget();
protected:
virtual bool event (QEvent *e );
+ virtual QPopupMenu *createPopupMenu(const QPoint& pos);
+private slots:
+ void slotFind();
+ void slotFindNext();
+ void slotReplace();
+private:
+ KFindDialog *m_findDlg;
+ KReplaceDialog *m_repDlg;
+ KAction *m_findAction;
+ KAction *m_replaceAction;
};
[prev in list] [next in list] [prev in thread] [next in thread]
Configure |
About |
News |
Add a list |
Sponsored by KoreLogic