[rkward/work/remove_khtml] rkward: Implement searchbar for new HTML view

Thomas Friedrichsmeier thomas.friedrichsmeier at ruhr-uni-bochum.de
Wed Feb 25 15:12:45 UTC 2015


Git commit 8e17bc3b8f47fd9ba1fc0fe619ca230d980c4d83 by Thomas Friedrichsmeier.
Committed on 25/02/2015 at 15:09.
Pushed by tfry into branch 'work/remove_khtml'.

Implement searchbar for new HTML view

M  +1    -0    rkward/misc/CMakeLists.txt
A  +160  -0    rkward/misc/rkfindbar.cpp     [License: GPL (v2+)]
A  +67   -0    rkward/misc/rkfindbar.h     [License: GPL (v2+)]
M  +4    -0    rkward/windows/rkhelpwindow.rc
M  +32   -9    rkward/windows/rkhtmlwindow.cpp
M  +4    -0    rkward/windows/rkhtmlwindow.h
M  +4    -0    rkward/windows/rkoutputwindow.rc

http://commits.kde.org/rkward/8e17bc3b8f47fd9ba1fc0fe619ca230d980c4d83

diff --git a/rkward/misc/CMakeLists.txt b/rkward/misc/CMakeLists.txt
index 1ae4afc..285b90b 100644
--- a/rkward/misc/CMakeLists.txt
+++ b/rkward/misc/CMakeLists.txt
@@ -25,6 +25,7 @@ SET(misc_STAT_SRCS
    editformatdialog.cpp
    rkmessagecatalog.cpp
    rkdbusapi.cpp
+   rkfindbar.cpp
    )
 
 QT4_AUTOMOC(${misc_STAT_SRCS})
diff --git a/rkward/misc/rkfindbar.cpp b/rkward/misc/rkfindbar.cpp
new file mode 100644
index 0000000..5b0ab71
--- /dev/null
+++ b/rkward/misc/rkfindbar.cpp
@@ -0,0 +1,160 @@
+/***************************************************************************
+                          rkfindbar  -  description
+                             -------------------
+    begin                : Tue Feb 24 2015
+    copyright            : (C) 2015 by Thomas Friedrichsmeier
+    email                : tfry at users.sourceforge.net
+ ***************************************************************************/
+
+/***************************************************************************
+ *                                                                         *
+ *   This program is free software; you can redistribute it and/or modify  *
+ *   it under the terms of the GNU General Public License as published by  *
+ *   the Free Software Foundation; either version 2 of the License, or     *
+ *   (at your option) any later version.                                   *
+ *                                                                         *
+ ***************************************************************************/
+
+#include "rkfindbar.h"
+
+#include <QHBoxLayout>
+#include <QToolButton>
+#include <QCheckBox>
+#include <QLineEdit>
+
+#include <khistorycombobox.h>
+#include <klocale.h>
+#include <kicon.h>
+
+#include "rkcommonfunctions.h"
+
+#include "../debug.h"
+
+RKFindBar::RKFindBar (QWidget* parent, bool custom) : QWidget (parent) {
+	RK_TRACE (APP);
+
+	mlayout = new QHBoxLayout (this);
+	mlayout->setContentsMargins (0, 0, 0, 0);
+	QToolButton* close_button = new QToolButton (this);
+	close_button->setIcon (KIcon ("dialog-close"));
+	close_button->setAutoRaise (true);   // makes it flat
+	connect (close_button, SIGNAL (clicked ()), this, SLOT (hide ()));
+	mlayout->addWidget (close_button);
+
+	QHBoxLayout* slayout = new QHBoxLayout ();
+	mlayout->addLayout (slayout, 1);
+	slayout->setContentsMargins (0, 0, 0, 0);
+	slayout->setSpacing (0);
+	term_edit = new KHistoryComboBox (this);
+	term_edit->setMaximumWidth (fontMetrics ().width ("This is quite a long search term by any standard, indeed"));
+	term_edit->setMinimumWidth (fontMetrics ().width ("A short search term"));
+	connect (term_edit, SIGNAL (editTextChanged(QString)), this, SLOT (searchChanged()));
+	connect (term_edit, SIGNAL(returnPressed(QString)), this, SLOT (forward()));
+	regular_palette = term_edit->palette ();
+	nomatch_palette = regular_palette;
+	nomatch_palette.setColor (QPalette::Text, QColor (255, 0, 0));
+	slayout->addWidget (term_edit, 1);
+
+	QToolButton* backward_button = new QToolButton (this);
+	backward_button->setArrowType (Qt::UpArrow);
+	backward_button->setContentsMargins (0, 0, 0, 0);
+	RKCommonFunctions::setTips (i18n ("Search backwards (previous occurence of search term"), backward_button);
+	connect (backward_button, SIGNAL (clicked()), this, SLOT(backward()));
+	slayout->addWidget (backward_button);
+	QToolButton* forward_button = new QToolButton (this);
+	forward_button->setArrowType (Qt::DownArrow);
+	forward_button->setContentsMargins (0, 0, 0, 0);
+	RKCommonFunctions::setTips (i18n ("Search forward (next occurence of search term"), forward_button);
+	connect (forward_button, SIGNAL (clicked()), this, SLOT(forward()));
+	slayout->addWidget (forward_button);
+
+	mlayout->addSpacing (15);
+
+	if (!custom) {
+		setPrimaryOptions (QList<QWidget*> () << getOption (MatchCase) << getOption (FindAsYouType) << getOption (HighlightAll));
+	}
+}
+
+RKFindBar::~RKFindBar () {
+	RK_TRACE (APP);
+}
+
+void RKFindBar::setPrimaryOptions (const QList<QWidget*>& options) {
+	RK_TRACE (APP);
+
+	for (int i = 0; i < options.size (); ++i) {
+		mlayout->addWidget (options[i]);
+	}
+	mlayout->addStretch ();
+}
+
+QCheckBox* RKFindBar::getOption (const RKFindBar::FindOptions option) {
+	RK_TRACE (APP);
+
+	if (!default_actions.contains (option)) {
+		QCheckBox* action;
+		if (option == MatchCase) {
+			action = new QCheckBox (i18n ("Match case"), this);
+		} else if (option == FindAsYouType) {
+			action = new QCheckBox (i18n ("Find as you type"), this);
+			action->setChecked (true);
+		} else if (option == HighlightAll) {
+			action = new QCheckBox (i18n ("Highlight all matches"), this);
+		} else {
+			RK_ASSERT (false);
+		}
+		connect (action, SIGNAL(stateChanged(int)), this, SLOT(searchChanged()));
+		default_actions.insert (option, action);
+	}
+
+	return (default_actions[option]);
+}
+
+bool RKFindBar::isOptionSet (const RKFindBar::FindOptions option) const {
+	if (!default_actions.contains (option)) return false;
+	return default_actions[option]->isChecked ();
+}
+
+void RKFindBar::searchChanged () {
+	RK_TRACE (APP);
+	term_edit->lineEdit ()->setFocus ();
+	if (default_actions.contains (FindAsYouType) && default_actions[FindAsYouType]->isChecked ()) forward ();
+}
+
+void RKFindBar::forward () {
+	RK_TRACE (APP);
+	doSearch (false);
+}
+
+void RKFindBar::backward () {
+	RK_TRACE (APP);
+	doSearch (true);
+}
+
+void RKFindBar::doSearch (bool backward) {
+	RK_TRACE (APP);
+	show ();
+	bool found = false;
+	QString term = term_edit->currentText ();
+	findRequest (term, backward, this, &found);
+	if (found || term.isEmpty ()) term_edit->lineEdit ()->setPalette (regular_palette);
+	else term_edit->lineEdit ()->setPalette (nomatch_palette);
+}
+
+void RKFindBar::activate () {
+	RK_TRACE (APP);
+
+	show ();
+	term_edit->lineEdit ()->selectAll ();
+	term_edit->lineEdit ()->setFocus ();
+}
+
+void RKFindBar::activateWithFindAsYouType () {
+	RK_TRACE (APP);
+
+	getOption (FindAsYouType)->setChecked (true);
+	activate ();
+}
+
+
+#include "rkfindbar.moc"
diff --git a/rkward/misc/rkfindbar.h b/rkward/misc/rkfindbar.h
new file mode 100644
index 0000000..9c9615c
--- /dev/null
+++ b/rkward/misc/rkfindbar.h
@@ -0,0 +1,67 @@
+/***************************************************************************
+                          rkfindbar  -  description
+                             -------------------
+    begin                : Tue Feb 24 2015
+    copyright            : (C) 2015 by Thomas Friedrichsmeier
+    email                : tfry at users.sourceforge.net
+ ***************************************************************************/
+
+/***************************************************************************
+ *                                                                         *
+ *   This program is free software; you can redistribute it and/or modify  *
+ *   it under the terms of the GNU General Public License as published by  *
+ *   the Free Software Foundation; either version 2 of the License, or     *
+ *   (at your option) any later version.                                   *
+ *                                                                         *
+ ***************************************************************************/
+
+#ifndef RKFINDBAR_H
+#define RKFINDBAR_H
+
+#include <QWidget>
+#include <QMap>
+
+class QCheckBox;
+class KHistoryComboBox;
+class QHBoxLayout;
+
+class RKFindBar : public QWidget {
+	Q_OBJECT
+public:
+	RKFindBar (QWidget *parent, bool custom=false);
+	~RKFindBar ();
+
+	enum FindOptions {
+		HighlightAll,
+		FindAsYouType,
+		MatchCase
+	};
+
+/** Insert the given option-widgets into the search bar. Widgets must be owned by the find bar. 
+
+I'd love to be able to implement options as QWidgetAction, instead of QWidgets.
+However, these can't be inserted into anything other than QToolBar or QMenu... */
+	void setPrimaryOptions (const QList<QWidget*>& options);
+
+	QCheckBox* getOption (const FindOptions option);
+	bool isOptionSet (const FindOptions option) const;
+public slots:
+	void activate ();
+	void activateWithFindAsYouType ();
+	void forward ();
+	void backward ();
+signals:
+	void findRequest (const QString& text, bool backwards, const RKFindBar *findbar, bool *result);
+private slots:
+/** search term _or_ search options changed. Triggers a forward search, if FindAsYouType is active */
+	void searchChanged ();
+private:
+	QMap<FindOptions, QCheckBox*> default_actions;
+	KHistoryComboBox* term_edit;
+	QHBoxLayout *mlayout;
+	void doSearch (bool backward);
+	QPalette regular_palette;
+	QPalette nomatch_palette;
+};
+
+#endif
diff --git a/rkward/windows/rkhelpwindow.rc b/rkward/windows/rkhelpwindow.rc
index 3b3bbde..55cd006 100644
--- a/rkward/windows/rkhelpwindow.rc
+++ b/rkward/windows/rkhelpwindow.rc
@@ -8,6 +8,10 @@
 		<Menu name="edit"><text>&Edit</text>
 			<Action name="copy"/>
 			<Separator/>
+			<Action name="find"/>
+			<Action name="find_next"/>
+			<Action name="find_previous"/>
+			<Separator/>
 			<Action name="select_all"/>
 		</Menu>
 		<Menu name="view"><text>&View</text>
diff --git a/rkward/windows/rkhtmlwindow.cpp b/rkward/windows/rkhtmlwindow.cpp
index 9434f69..5b9d624 100644
--- a/rkward/windows/rkhtmlwindow.cpp
+++ b/rkward/windows/rkhtmlwindow.cpp
@@ -60,6 +60,7 @@
 #include "../misc/rkxmlguisyncer.h"
 #include "../misc/rkprogresscontrol.h"
 #include "../misc/rkmessagecatalog.h"
+#include "../misc/rkfindbar.h"
 #include "../plugin/rkcomponentmap.h"
 #include "../windows/rkworkplace.h"
 #include "../windows/rkworkplaceview.h"
@@ -124,11 +125,16 @@ RKHTMLWindow::RKHTMLWindow (QWidget *parent, WindowMode mode) : RKMDIWindow (par
 	page = new RKWebPage (this);
 	view->setPage (page);
 	view->setContextMenuPolicy (Qt::CustomContextMenu);
-	layout->addWidget (view);
+	layout->addWidget (view, 1);
+	findbar = new RKFindBar (this);
+	layout->addWidget (findbar);
+	findbar->hide ();
+	connect (findbar, SIGNAL(findRequest(QString,bool,const RKFindBar*,bool*)), this, SLOT(findRequest(QString,bool,const RKFindBar*,bool*)));
+	bool have_highlight = false;
+
 	part = new RKHTMLWindowPart (this);
 	setPart (part);
 	part->initActions ();
-
 	initializeActivationSignals ();
 	part->setSelectable (true);
 	setFocusPolicy (Qt::StrongFocus);
@@ -198,6 +204,22 @@ void RKHTMLWindow::runSelection () {
 	RKConsole::pipeUserCommand (view->selectedText ());
 }
 
+void RKHTMLWindow::findRequest (const QString& text, bool backwards, const RKFindBar* findbar, bool* found) {
+	RK_TRACE (APP);
+
+	QWebPage::FindFlags flags = QWebPage::FindWrapsAroundDocument;
+	if (backwards) flags |= QWebPage::FindBackward;
+	bool highlight = findbar->isOptionSet (RKFindBar::HighlightAll);
+	if (highlight) flags |= QWebPage::HighlightAllOccurrences;
+	if (findbar->isOptionSet (RKFindBar::MatchCase)) flags |= QWebPage::FindCaseSensitively;
+
+	// clear previous highlight, if any
+	if (have_highlight) page->findText (QString (), QWebPage::HighlightAllOccurrences);
+
+	*found = page->findText (text, flags);
+	have_highlight = found && highlight;
+}
+
 void RKHTMLWindow::slotPrint () {
 	RK_TRACE (APP);
 
@@ -561,7 +583,7 @@ void RKHTMLWindowPart::initActions () {
 	connect (zoom_in, SIGNAL(triggered(bool)), window, SLOT (zoomIn()));
 	QAction* zoom_out = actionCollection ()->addAction ("zoom_out", new KAction (KIcon ("zoom-out"), i18n ("Zoom Out"), this));
 	connect (zoom_out, SIGNAL(triggered(bool)), window, SLOT (zoomOut()));
-	QAction* select_all = actionCollection ()->addAction (KStandardAction::SelectAll, "select_all", window->view->pageAction (QWebPage::SelectAll), SLOT (trigger()));
+	actionCollection ()->addAction (KStandardAction::SelectAll, "select_all", window->view->pageAction (QWebPage::SelectAll), SLOT (trigger()));
 	// unfortunately, this will only affect the default encoding, not necessarily the "real" encoding
 	KCodecAction *encoding = new KCodecAction (KIcon ("character-set"), i18n ("Default &Encoding"), this, true);
 	encoding->setStatusTip (i18n ("Set the encoding to assume in case no explicit encoding has been set in the page or in the HTTP headers."));
@@ -589,12 +611,13 @@ void RKHTMLWindowPart::initActions () {
 	outputRefresh->setText (i18n ("&Refresh Output"));
 	outputRefresh->setIcon (KIcon ("view-refresh"));
 
-	// TODO!!!
-	QAction* find;
-	QAction* findAhead;      // shortcut '/'
-	QAction* find_next;
-	QAction* find_previous;
-
+	actionCollection ()->addAction (KStandardAction::Find, "find", window->findbar, SLOT (activate()));
+	KAction* findAhead = actionCollection ()->addAction ("find_ahead", new KAction (i18n ("Find as you type"), this));
+	findAhead->setShortcut ('/');
+	connect (findAhead, SIGNAL (triggered(bool)), window->findbar, SLOT (activate()));
+	actionCollection ()->addAction (KStandardAction::FindNext, "find_next", window->findbar, SLOT (forward()));;
+	actionCollection ()->addAction (KStandardAction::FindPrev, "find_previous", window->findbar, SLOT (backward()));;;
+}
 
 void RKHTMLWindowPart::setOutputWindowSkin () {
 	RK_TRACE (APP);
diff --git a/rkward/windows/rkhtmlwindow.h b/rkward/windows/rkhtmlwindow.h
index c5a87e8..ef1e44e 100644
--- a/rkward/windows/rkhtmlwindow.h
+++ b/rkward/windows/rkhtmlwindow.h
@@ -36,6 +36,7 @@ class RKHTMLWindowPart;
 class KWebView;
 class KTemporaryFile;
 class RKHTMLWindow;
+class RKFindBar;
 
 class RKWebPage : public KWebPage {
 	Q_OBJECT
@@ -114,10 +115,13 @@ private slots:
 	void mimeTypeDetermined (KIO::Job*, const QString& type);
 	void internalNavigation (const QUrl& new_url);
 	void makeContextMenu (const QPoint& pos);
+	void findRequest (const QString& text, bool backwards, const RKFindBar *findbar, bool* found);
 private:
 friend class RKHTMLWindowPart;
 	KWebView* view;
 	RKWebPage* page;
+	RKFindBar* findbar;
+	bool have_highlight;
 /** In case the part is a khtmlpart: A ready-cast pointer to that. 0 otherwise (if a webkit part is in use) */
 	RKHTMLWindowPart *part;
 /** update caption according to given URL */
diff --git a/rkward/windows/rkoutputwindow.rc b/rkward/windows/rkoutputwindow.rc
index 2aa6987..1766340 100644
--- a/rkward/windows/rkoutputwindow.rc
+++ b/rkward/windows/rkoutputwindow.rc
@@ -8,6 +8,10 @@
 		<Menu name="edit"><text>&Edit</text>
 			<Action name="copy"/>
 			<Separator/>
+			<Action name="find"/>
+			<Action name="find_next"/>
+			<Action name="find_previous"/>
+			<Separator/>
 			<Action name="select_all"/>
 			<Separator/>
 			<Action name="output_flush"/>



More information about the rkward-tracker mailing list