[rkward/work/remove_khtml] /: WIP: Start actually replacing KHTMLPart with QWebView / QWebPage.

Thomas Friedrichsmeier thomas.friedrichsmeier at ruhr-uni-bochum.de
Mon Feb 23 11:01:26 UTC 2015


Git commit fcc6002a97581d15ee4fbe6842e3a8255e14ae46 by Thomas Friedrichsmeier.
Committed on 21/02/2015 at 19:46.
Pushed by tfry into branch 'work/remove_khtml'.

WIP: Start actually replacing KHTMLPart with QWebView / QWebPage.
This could be considered a first step in porting to KF5.

M  +1    -1    debian/control
M  +2    -2    rkward/CMakeLists.txt
M  +156  -180  rkward/windows/rkhtmlwindow.cpp
M  +64   -34   rkward/windows/rkhtmlwindow.h
M  +1    -0    rkward/windows/rkworkplace.cpp

http://commits.kde.org/rkward/fcc6002a97581d15ee4fbe6842e3a8255e14ae46

diff --git a/debian/control b/debian/control
index 1012eb4..254fc11 100644
--- a/debian/control
+++ b/debian/control
@@ -2,7 +2,7 @@ Source: rkward
 Section: math
 Priority: optional
 Maintainer: Thomas Friedrichsmeier <tfry at users.sourceforge.net>
-Build-Depends: debhelper (>= 6.0.0), kdelibs5-dev, cmake, r-base-dev (>= 2.8.0), libx11-dev
+Build-Depends: debhelper (>= 6.0.0), kdelibs5-dev, cmake, r-base-dev (>= 2.8.0), libx11-dev, libqtwebkit-dev
 Standards-Version: 3.9.6
 Homepage: http://rkward.kde.org
 Vcs-Browser: http://quickgit.kde.org/?p=rkward.git&a=tree&f=debian
diff --git a/rkward/CMakeLists.txt b/rkward/CMakeLists.txt
index 5f77e4b..11112d4 100644
--- a/rkward/CMakeLists.txt
+++ b/rkward/CMakeLists.txt
@@ -32,7 +32,7 @@ ENDIF(WIN32)
 ADD_SUBDIRECTORY( windows )
 ADD_SUBDIRECTORY( syntax )
 
-INCLUDE_DIRECTORIES( ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_BINARY_DIR} ${KDE4_INCLUDE_DIR} ${QT_INCLUDES} ${X11_X11_INCLUDE_PATH} )
+INCLUDE_DIRECTORIES( ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_BINARY_DIR} ${KDE4_INCLUDE_DIR} ${QT_INCLUDES} ${QT_QTWEBKIT_INCLUDE_DIR} ${X11_X11_INCLUDE_PATH} )
 
 SET(RKWard_Sources
 	rkward.cpp
@@ -63,7 +63,7 @@ IF(Q_WS_MAC)
 		@ONLY)
 ENDIF(Q_WS_MAC)
 
-TARGET_LINK_LIBRARIES(rkward.frontend ${KDE4_KDECORE_LIBS} windows ${RKWARD_ADDLIBS} agents dialogs plugin settings dataeditor core scriptbackends rbackend misc ${KDE4_KTEXTEDITOR_LIBS} ${KDE4_KHTML_LIBS} ${KDE4_KFILE_LIBS} ${KDE4_KDEUI_LIBS} ${QT_QTDBUS_LIBRARY} ${QT_QTSCRIPT_LIBRARY} ${QT_QTNETWORK_LIBRARY} ${GETTEXT_LIBRARIES})
+TARGET_LINK_LIBRARIES(rkward.frontend ${KDE4_KDECORE_LIBS} windows ${RKWARD_ADDLIBS} agents dialogs plugin settings dataeditor core scriptbackends rbackend misc ${KDE4_KTEXTEDITOR_LIBS} ${KDE4_KFILE_LIBS} ${KDE4_KDEUI_LIBS} ${QT_QTDBUS_LIBRARY} ${QT_QTSCRIPT_LIBRARY} ${QT_QTNETWORK_LIBRARY} ${QT_QTWEBKIT_LIBRARY} ${GETTEXT_LIBRARIES})
 
 # wrapper executable
 GET_DIRECTORY_PROPERTY(R_EXECUTABLE DIRECTORY rbackend DEFINITION R_EXECUTABLE)
diff --git a/rkward/windows/rkhtmlwindow.cpp b/rkward/windows/rkhtmlwindow.cpp
index cd67904..1316245 100644
--- a/rkward/windows/rkhtmlwindow.cpp
+++ b/rkward/windows/rkhtmlwindow.cpp
@@ -28,6 +28,7 @@
 #include <kmimetype.h>
 #include <kio/job.h>
 #include <kservice.h>
+#include <ktemporaryfile.h>
 
 #include <qfileinfo.h>
 #include <qwidget.h>
@@ -36,6 +37,9 @@
 #include <qdir.h>
 #include <QHBoxLayout>
 #include <QHostInfo>
+#include <QWebView>
+#include <QWebFrame>
+#include <QPrintDialog>
 
 #include "../rkglobals.h"
 #include "../rbackend/rinterface.h"
@@ -59,69 +63,42 @@
 
 RKHTMLWindow::RKHTMLWindow (QWidget *parent, WindowMode mode) : RKMDIWindow (parent, RKMDIWindow::HelpWindow) {
 	RK_TRACE (APP);
-	setComponentData (KGlobal::mainComponent ());
 
-	renderingpart = 0;
-	khtmlpart = 0;
-/*	KService::Ptr service = KService::serviceByDesktopPath ("kwebkitpart.desktop");
-	if (service) renderingpart = service->createInstance<KParts::ReadOnlyPart> (this);
-	if (!renderingpart) { */
-		khtmlpart = new KHTMLPart (this, 0, KHTMLPart::BrowserViewGUI);
-		renderingpart = khtmlpart;
-//	}
-
-	setPart (renderingpart);
-	fixupPartGUI ();
-// WORKAROUND for annoying kdelibs bug in KDE 4.6: https://sourceforge.net/tracker/?func=detail&atid=459007&aid=3310106&group_id=50231
-// NOTE: Fixed in KDE 4.7. See http://git.reviewboard.kde.org/r/101491/
-	QAction *action = renderingpart->action ("findAheadText");
-	if (action) action->setShortcutContext (Qt::WidgetWithChildrenShortcut);
-// WORKAROUND end
+	current_cache_file = 0;
+
+	QVBoxLayout* layout = new QVBoxLayout (this);
+	layout->setContentsMargins (0, 0, 0, 0);
+	view = new QWebView (this);
+	RKWebPage *page = new RKWebPage (this);
+	view->setPage (page);
+	layout->addWidget (view);
+	part = new RKHTMLWindowPart (this);
+	setPart (part);
+	part->initActions ();
+
 	initializeActivationSignals ();
-	RKXMLGUISyncer::self()->registerChangeListener (renderingpart, this, SLOT (fixupPartGUI()));
-	renderingpart->setSelectable (true);
-	setFocusProxy (renderingpart->widget ());
-	renderingpart->widget ()->setFocusPolicy (Qt::StrongFocus);
-	
-	renderingpart->widget ()->setSizePolicy (QSizePolicy::Expanding, QSizePolicy::Expanding);
-	QHBoxLayout *pLayout = new QHBoxLayout (this);
-	pLayout->setContentsMargins (0, 0, 0, 0);
-	pLayout->addWidget (renderingpart->widget ());
+// TODO	renderingpart->setSelectable (true);
+	setFocusProxy (view);
+	view->setFocusPolicy (Qt::StrongFocus);
 
 	// We have to connect this in order to allow browsing.
-	connect (renderingpart->browserExtension (), SIGNAL (openUrlRequestDelayed(KUrl,KParts::OpenUrlArguments,KParts::BrowserArguments)), this, SLOT (slotOpenUrl(KUrl,KParts::OpenUrlArguments,KParts::BrowserArguments)));
-	connect (renderingpart, SIGNAL (completed()), this, SLOT (loadDone()));
-	connect (renderingpart->browserExtension (), SIGNAL (openUrlNotify()), this, SLOT (internalNavigation()));	// to catch internal navigation on a page
+	connect (page, SIGNAL (linkClicked (QUrl)), this, SLOT (slotOpenUrl(KUrl)));
+	connect (page, SIGNAL (pageInternalNavigation (QUrl)), this, SLOT (internalNavigation()));
 
 	current_history_position = -1;
 	url_change_is_from_history = false;
 
-	initActions ();
-	window_mode = Undefined;
 	useMode (mode);
-}
 
-RKHTMLWindow::~RKHTMLWindow () {
-	RK_TRACE (APP);
-
-// WORKAROUND for annoying kdelibs bug (KDE 4.0 up to at least KDE 4.6): Status bar icons added by plugins typically do not get deleted in case the KParts::StatusBarExtension
-// has already been deleted, first. See http://www.mail-archive.com/rkward-devel@lists.sourceforge.net/msg01345.html . Therefore, delete the plugins, explicitely, while the
-// StatusBarExtension is still alive...
-	QList<KParts::Plugin*> plugins = KParts::Plugin::pluginObjects (renderingpart);
-	foreach (KParts::Plugin *plugin, plugins) {
-		delete plugin;
-	}
-// I hope this does not come back to bite us one day... If it does, here's a safer variant, which simply hides the problem (the way it is hidden in konqueror, among others):
-// 	RKWardMainWindow::getMain ()->partManager ()->setActivePart (0);
-// WORKAROUND end
-	delete renderingpart;
+	// needed to enable / disable the run selection action
+	connect (view, SIGNAL (selectionChanged()), this, SLOT (selectionChanged()));
+	selectionChanged ();
 }
 
-void RKHTMLWindow::fixupPartGUI () {
+RKHTMLWindow::~RKHTMLWindow () {
 	RK_TRACE (APP);
 
-	// strip down the khtmlpart's GUI. remove some stuff we definitely don't need.
-	RKCommonFunctions::removeContainers (renderingpart, QString ("tools,security,extraToolBar,saveBackground,saveFrame,printFrame,kget_menu").split (','), true);
+	delete current_cache_file;
 }
 
 KUrl RKHTMLWindow::restorableUrl () {
@@ -135,71 +112,37 @@ bool RKHTMLWindow::isModified () {
 	return false;
 }
 
-void RKHTMLWindow::initActions () {
-	RK_TRACE (APP);
-
-	// common actions
-	actionCollection ()->addAction (KStandardAction::Copy, "copy", renderingpart->browserExtension (), SLOT (copy()));
-
-	print = actionCollection ()->addAction (KStandardAction::Print, "print_html", this, SLOT (slotPrint()));
-
-	run_selection = RKStandardActions::runCurrent (this, this, SLOT (runSelection()));
-
-		// needed to enable / disable the run selection action
-	connect (renderingpart, SIGNAL (selectionChanged()), this, SLOT (selectionChanged()));
-	selectionChanged ();
-
-	// help window actions
-	back = actionCollection ()->addAction (KStandardAction::Back, "help_back", this, SLOT (slotBack()));
-	back->setEnabled (false);
-
-	forward = actionCollection ()->addAction (KStandardAction::Forward, "help_forward", this, SLOT (slotForward()));
-	forward->setEnabled (false);
-
-	// output window actions
-	outputFlush = actionCollection ()->addAction ("output_flush", this, SLOT (flushOutput()));
-	outputFlush->setText (i18n ("&Flush Output"));
-	outputFlush->setIcon (KIcon ("edit-delete"));
-
-	outputRefresh = actionCollection ()->addAction ("output_refresh", this, SLOT (refresh()));
-	outputRefresh->setText (i18n ("&Refresh Output"));
-	outputRefresh->setIcon (KIcon ("view-refresh"));
-}
-
 void RKHTMLWindow::selectionChanged () {
 	RK_TRACE (APP);
 
-	if (!run_selection) {
+	if (!(part && part->run_selection)) {
 		RK_ASSERT (false);
 		return;
 	}
 
-	run_selection->setEnabled (khtmlpart->hasSelection ());
+#if QT_VERSION >= 0x040800
+	part->run_selection->setEnabled (view->hasSelection ());
+#else
+	part->run_selection->setEnabled (!view->selectedText ().isEmpty ());
+#endif
 }
 
 void RKHTMLWindow::runSelection () {
 	RK_TRACE (APP);
 
-	RKConsole::pipeUserCommand (khtmlpart->selectedText ());
-}
-
-void RKHTMLWindow::doGotoAnchor (const QString &anchor_name) {
-	RK_TRACE (APP);
-
-	goto_anchor_name = anchor_name;
-	QTimer::singleShot (0, this, SLOT (doGotoAnchorNow()));
-}
-
-void RKHTMLWindow::doGotoAnchorNow () {
-	RK_TRACE (APP);
-
-	if (khtmlpart) khtmlpart->gotoAnchor (goto_anchor_name);
+	RKConsole::pipeUserCommand (view->selectedText ());
 }
 
 void RKHTMLWindow::slotPrint () {
 	RK_TRACE (APP);
 
-	khtmlpart->view ()->print ();
+	// NOTE: taken from kwebkitpart, with small mods
+	// Make it non-modal, in case a redirection deletes the part
+	QPointer<QPrintDialog> dlg (new QPrintDialog (view));
+	if (dlg->exec () == QPrintDialog::Accepted) {
+		view->print (dlg->printer ());
+	}
+	delete dlg;
 }
 
 void RKHTMLWindow::openLocationFromHistory (VisitedLocation &loc) {
@@ -209,17 +152,17 @@ void RKHTMLWindow::openLocationFromHistory (VisitedLocation &loc) {
 	int history_last = url_history.count () - 1;
 	RK_ASSERT (current_history_position >= 0);
 	RK_ASSERT (current_history_position <= history_last);
-	if (loc.url == renderingpart->url ()) {
-		restoreBrowserState (&(loc.state));
+	if (loc.url == current_url) {
+		restoreBrowserState (&loc);
 	} else {
 		url_change_is_from_history = true;
-		openURL (loc.url);
-		restoreBrowserState (&(loc.state));
+		openURL (loc.url);            // TODO: merge into restoreBrowserState()?
+		restoreBrowserState (&loc);
 		url_change_is_from_history = false;
 	}
 
-	back->setEnabled (current_history_position > 0);
-	forward->setEnabled (current_history_position < history_last);
+	part->back->setEnabled (current_history_position > 0);
+	part->forward->setEnabled (current_history_position < history_last);
 }
 
 void RKHTMLWindow::slotForward () {
@@ -234,7 +177,7 @@ void RKHTMLWindow::slotBack () {
 
 	// if going back from the end of the history, save that position, first.
 	if (current_history_position >= (url_history.count () - 1)) {
-		changeURL (renderingpart->url ());
+		changeURL (current_url);
 		--current_history_position;
 	}
 	--current_history_position;
@@ -249,18 +192,17 @@ void RKHTMLWindow::openRKHPage (const KUrl& url) {
 	bool ok = false;
 	if ((url.host () == "component") || (url.host () == "page")) {
 		useMode (HTMLHelpWindow);
-		QString rendered;
-		RKHelpRenderer render (&rendered);
+
+		delete current_cache_file;
+		current_cache_file = new KTemporaryFile ();
+		current_cache_file->open ();
+		RKHelpRenderer render (current_cache_file);
 		ok = render.renderRKHelp (url);
-		if (khtmlpart) {
-			khtmlpart->begin (url);
-			khtmlpart->write (rendered);
-			khtmlpart->end ();
-		}
-		QString ref = url.ref ();
-		if (!ref.isEmpty ()) {
-			doGotoAnchor (ref);
-		}
+		current_cache_file->close ();
+
+		KUrl cache_url = KUrl::fromLocalFile (current_cache_file->fileName ());
+		cache_url.setFragment (url.fragment ());
+		view->load (cache_url);
 	} else if (url.host ().toUpper () == "RHELPBASE") {	// NOTE: QUrl () may lowercase the host part, internally
 		KUrl fixed_url = KUrl (RKSettingsModuleR::helpBaseUrl ());
 		fixed_url.setPath (url.path ());
@@ -322,7 +264,7 @@ bool RKHTMLWindow::openURL (const KUrl &url) {
 		QFileInfo out_file (url.toLocalFile ());
 		bool ok = out_file.exists();
 		if (ok)  {
-			renderingpart->openUrl (url);
+			view->load (url);
 		} else {
 			fileDoesNotExistMessage ();
 		}
@@ -331,7 +273,7 @@ bool RKHTMLWindow::openURL (const KUrl &url) {
 
 	if (url_change_is_from_history || url.protocol ().toLower ().startsWith ("help")) {	// handle help pages, and any page that we have previously handled (from history)
 		changeURL (url);
-		renderingpart->openUrl (url);
+		view->load (url);
 		return true;
 	}
 
@@ -361,7 +303,7 @@ void RKHTMLWindow::mimeTypeDetermined (KIO::Job* job, const QString& type) {
 	tj->putOnHold ();
 	if (type == "text/html") {
 		changeURL (url);
-		renderingpart->openUrl (url);
+		view->load (url);
 	} else {
 		RKWorkplace::mainWorkplace ()->openAnyUrl (url, type);
 	}
@@ -370,10 +312,20 @@ void RKHTMLWindow::mimeTypeDetermined (KIO::Job* job, const QString& type) {
 void RKHTMLWindow::internalNavigation () {
 	RK_TRACE (APP);
 
-	changeURL (renderingpart->url ());
+	// TODO: handle this type of navigation via openRKHPage (), instead?
+	KUrl real_url = view->url ();
+	if (current_cache_file && real_url.isLocalFile ()) {
+		KUrl cache_url = KUrl::fromLocalFile (current_cache_file->fileName ());
+		QString fragment = real_url.fragment ();
+		real_url = current_url;
+		real_url.setFragment (fragment);
+	}
+
+	changeURL (real_url);
 }
 
 void RKHTMLWindow::changeURL (const KUrl &url) {
+	KUrl prev_url = current_url;
 	current_url = url;
 	updateCaption (url);
 
@@ -383,14 +335,14 @@ void RKHTMLWindow::changeURL (const KUrl &url) {
 				url_history = url_history.mid (0, current_history_position);
 
 				VisitedLocation loc;
-				loc.url = renderingpart->url ();
-				saveBrowserState (&loc.state);
+				loc.url = prev_url;
+				saveBrowserState (&loc);
 				url_history.append (loc);
 			}
 
 			++current_history_position;
- 			back->setEnabled (current_history_position > 0);
-			forward->setEnabled (false);
+ 			part->back->setEnabled (current_history_position > 0);
+			part->forward->setEnabled (false);
 		}
 	}
 }
@@ -402,7 +354,8 @@ void RKHTMLWindow::updateCaption (const KUrl &url) {
 	else setCaption (url.fileName ());
 }
 
-void RKHTMLWindow::slotOpenUrl (const KUrl & url, const KParts::OpenUrlArguments &, const KParts::BrowserArguments &) {
+// TODO: handle request for new window / tab
+void RKHTMLWindow::slotOpenUrl (const KUrl & url) {
 	RK_TRACE (APP);
 
 	openURL (url);
@@ -411,60 +364,37 @@ void RKHTMLWindow::slotOpenUrl (const KUrl & url, const KParts::OpenUrlArguments
 void RKHTMLWindow::refresh () {
 	RK_TRACE (APP);
 
-	KParts::OpenUrlArguments args;
-	args.setReload (true);		// this forces the next openURL to reload all images
-	renderingpart->setArguments (args);
-	saveBrowserState (&saved_state);
-	openURL (current_url);
+// TODO: does this restore scroll position?
+	view->reload ();
 }
 
 void RKHTMLWindow::loadDone () {
 	RK_TRACE (APP);
 
+// TODO: does this work?
 	if (window_mode == HTMLOutputWindow) {	// scroll to bottom
-		khtmlpart->view ()->setContentsPos (0, khtmlpart->view ()->contentsHeight ());
-	} else {	// scroll to previous pos
-		restoreBrowserState (&saved_state);
-		saved_state.clear ();
+		view->page ()->mainFrame ()->setScrollBarValue (Qt::Vertical, view->page ()->mainFrame ()->scrollBarMaximum (Qt::Vertical));
 	}
 }
 
 void RKHTMLWindow::useMode (WindowMode new_mode) {
 	RK_TRACE (APP);
 
-	RK_ASSERT (new_mode != Undefined);
 	if (window_mode == new_mode) return;
 
 	if (new_mode == HTMLOutputWindow) {
 		type = RKMDIWindow::OutputWindow | RKMDIWindow::DocumentWindow;
 		setWindowIcon (RKStandardIcons::getIcon (RKStandardIcons::WindowOutput));
-
-		print->setText (i18n ("Print output"));
-		QAction *action = renderingpart->action ("saveDocument");
-		if (action) action->setText (i18n ("Export page as HTML"));
-		else RK_ASSERT (false);		// we should know about this
-
-		setXMLFile ("rkoutputwindow.rc");
+		part->setOutputWindowSkin ();
 		setMetaInfo (i18n ("Output Window"), "rkward://page/rkward_output", RKSettings::PageOutput);
-		run_selection->setVisible (false);
 	} else {
 		RK_ASSERT (new_mode == HTMLHelpWindow);
 
 		type = RKMDIWindow::HelpWindow | RKMDIWindow::DocumentWindow;
 		setWindowIcon (RKStandardIcons::getIcon (RKStandardIcons::WindowHelp));
-
-		print->setText (i18n ("Print page"));
-		QAction *action = renderingpart->action ("saveDocument");
-		if (action) action->setText (i18n ("Save Output as HTML"));
-		else RK_ASSERT (false);		// we should know about this
-
-		setXMLFile ("rkhelpwindow.rc");
-		run_selection->setVisible (true);
+		part->setHelpWindowSkin ();
 	}
 
-	if (parentClient ()) renderingpart->removeChildClient (this);
-	renderingpart->insertChildClient (this);
-
 	updateCaption (current_url);
 	window_mode = new_mode;
 }
@@ -472,14 +402,19 @@ void RKHTMLWindow::useMode (WindowMode new_mode) {
 void RKHTMLWindow::fileDoesNotExistMessage () {
 	RK_TRACE (APP);
 
-	if (!khtmlpart) return;
-	khtmlpart->begin (KUrl ());
+	delete current_cache_file;
+	current_cache_file = new KTemporaryFile ();
+	current_cache_file->open ();
 	if (window_mode == HTMLOutputWindow) {
-		khtmlpart->write (i18n ("<HTML><BODY><H1>RKWard output file could not be found</H1>\n</BODY></HTML>"));
+		current_cache_file->write (i18n ("<HTML><BODY><H1>RKWard output file could not be found</H1>\n</BODY></HTML>").toUtf8 ());
 	} else {
-		khtmlpart->write ("<html><body><h1>" + i18n ("Page does not exist or is broken") + "</h1></body></html>");
+		current_cache_file->write (QString ("<html><body><h1>" + i18n ("Page does not exist or is broken") + "</h1></body></html>").toUtf8 ());
 	}
-	khtmlpart->end ();
+	
+	current_cache_file->close ();
+
+	KUrl cache_url = KUrl::fromLocalFile (current_cache_file->fileName ());
+	view->load (cache_url);
 }
 
 void RKHTMLWindow::flushOutput () {
@@ -497,30 +432,75 @@ void RKHTMLWindow::flushOutput () {
 	}
 }
 
-void RKHTMLWindow::saveBrowserState (QByteArray* state) {
+void RKHTMLWindow::saveBrowserState (VisitedLocation* state) {
 	RK_TRACE (APP);
 
-	KParts::BrowserExtension *bext = renderingpart->browserExtension ();
-	if (!bext) {
-		RK_ASSERT (bext);
-		return;
+	if (view && view->page () && view->page ()->mainFrame ()) {
+		state->scroll_position = view->page ()->mainFrame ()->scrollPosition ();
+	} else {
+		state->scroll_position = QPoint ();
 	}
-	state->clear ();
-	QDataStream dummy (state, QIODevice::WriteOnly);
-	bext->saveState (dummy);
 }
 
-void RKHTMLWindow::restoreBrowserState (QByteArray* state) {
+void RKHTMLWindow::restoreBrowserState (VisitedLocation* state) {
 	RK_TRACE (APP);
 
-	if (state->isEmpty()) return;
-	KParts::BrowserExtension *bext = renderingpart->browserExtension ();
-	if (!bext) {
-		RK_ASSERT (bext);
-		return;
-	}
-	QDataStream dummy (state, QIODevice::ReadOnly);
-	bext->restoreState (dummy);
+	if (state->scroll_position.isNull ()) return;
+	RK_ASSERT (view && view->page () && view->page ()->mainFrame ());
+	view->page ()->mainFrame ()->setScrollPosition (state->scroll_position);
+}
+
+RKHTMLWindowPart::RKHTMLWindowPart (RKHTMLWindow* window) : KParts::Part (window) {
+	RK_TRACE (APP);
+	setComponentData (KGlobal::mainComponent ());
+	RKHTMLWindowPart::window = window;
+}
+
+void RKHTMLWindowPart::initActions () {
+	RK_TRACE (APP);
+
+	// TODO!!!
+	// common actions
+	actionCollection ()->addAction (KStandardAction::Copy, "copy", this, SLOT (copy()));
+
+	print = actionCollection ()->addAction (KStandardAction::Print, "print_html", this, SLOT (slotPrint()));
+	save_page = actionCollection ()->addAction (KStandardAction::Print, "save_page", this, SLOT (slotPrint()));
+
+	run_selection = RKStandardActions::runCurrent (window, this, SLOT (runSelection()));
+
+	// help window actions
+	back = actionCollection ()->addAction (KStandardAction::Back, "help_back", this, SLOT (slotBack()));
+	back->setEnabled (false);
+
+	forward = actionCollection ()->addAction (KStandardAction::Forward, "help_forward", this, SLOT (slotForward()));
+	forward->setEnabled (false);
+
+	// output window actions
+	outputFlush = actionCollection ()->addAction ("output_flush", this, SLOT (flushOutput()));
+	outputFlush->setText (i18n ("&Flush Output"));
+	outputFlush->setIcon (KIcon ("edit-delete"));
+
+	outputRefresh = actionCollection ()->addAction ("output_refresh", this, SLOT (refresh()));
+	outputRefresh->setText (i18n ("&Refresh Output"));
+	outputRefresh->setIcon (KIcon ("view-refresh"));
+}
+
+void RKHTMLWindowPart::setOutputWindowSkin () {
+	RK_TRACE (APP);
+
+	print->setText (i18n ("Print output"));
+	save_page->setText (i18n ("Export page as HTML"));
+	setXMLFile ("rkoutputwindow.rc");
+	run_selection->setVisible (false);
+}
+
+void RKHTMLWindowPart::setHelpWindowSkin () {
+	RK_TRACE (APP);
+
+	print->setText (i18n ("Print page"));
+	save_page->setText (i18n ("Save Output as HTML"));
+	setXMLFile ("rkhelpwindow.rc");
+	run_selection->setVisible (true);
 }
 
 //////////////////////////////////////////
@@ -834,11 +814,7 @@ QString RKHelpRenderer::startSection (const QString &name, const QString &title,
 void RKHelpRenderer::writeHTML (const QString& string) {
 	RK_TRACE (APP);
 
-	buffer->append (string);
-/*	else {
-		RK_ASSERT (html_write_file);
-		html_write_file->write (string.toUtf8 ());
-	} */
+	device->write (string.toUtf8 ());
 }
 
 /////////////////////////////////////
diff --git a/rkward/windows/rkhtmlwindow.h b/rkward/windows/rkhtmlwindow.h
index c74e6e9..938d281 100644
--- a/rkward/windows/rkhtmlwindow.h
+++ b/rkward/windows/rkhtmlwindow.h
@@ -19,34 +19,47 @@
 #define RKHTMLWINDOW_H
 
 #include <kurl.h>
-#include <kparts/browserextension.h>
-#include <kxmlguiclient.h>
+#include <kparts/part.h>
 #include <kio/jobclasses.h>
 
+#include <QWebPage>
+
 #include "../windows/rkmdiwindow.h"
 
-class KHTMLPart;
 class KActionCollection;
 class KRecentFilesAction;
 class QAction;
 class QDomElement;
 class RKComponentHandle;
 class XMLHelper;
+class RKHTMLWindowPart;
+class QWebView;
+class KTemporaryFile;
+
+class RKWebPage : public QWebPage {
+	Q_OBJECT
+public:
+	RKWebPage (QObject* parent) : QWebPage (parent) {};
+signals:
+	void pageInternalNavigation (const QUrl& url);
+protected:
+/** reimplemented to always emit linkClicked() for pages that need special handling (importantly, rkward://-urls). */
+	bool acceptNavigationRequest (QWebFrame* frame, const QNetworkRequest& request, NavigationType type) { return true; }; // TODO
+};
 
 /**
 	\brief Show html files.
 
-This class wraps a khtml part.
+Provide a window for viewing HTML pages.
 
-It is used as a base for several purposes: Display R-help (in HTML format), display generic HTML, display RKWard output. Do not use this class directly. Use the derived classes instead.
+It is used as a base for several purposes: Display R-help (in HTML format), display RKWard help pages, display generic HTML, display RKWard output.
 
 @author Pierre Ecochard
 */
-class RKHTMLWindow : public RKMDIWindow, public KXMLGUIClient {
+class RKHTMLWindow : public RKMDIWindow {
 	Q_OBJECT
 public:
 	enum WindowMode {
-		Undefined,
 		HTMLHelpWindow,
 		HTMLOutputWindow
 	};
@@ -64,20 +77,17 @@ public:
  */
 	static bool handleRKWardURL (const KUrl &url, RKHTMLWindow *window=0);
 	void openRKHPage (const KUrl &url);
-/** initialize all actions */
-	void initActions ();
 
 	bool isModified ();
 /** Return current url */
 	KUrl url ();
 /** Return current url in a restorable way, i.e. for help pages, abstract the session specific part of the path */
 	KUrl restorableUrl ();
-	void doGotoAnchor (const QString &anchor_name);
 
 	WindowMode mode () { return window_mode; };
 public slots:
 /** this is used for browsing only. Use openURL instead, when calling from outside. */
-	void slotOpenUrl (const KUrl & url, const KParts::OpenUrlArguments &, const KParts::BrowserArguments &);
+	void slotOpenUrl (const KUrl & url);
 	void slotPrint ();
 	void slotForward ();
 	void slotBack ();
@@ -87,35 +97,54 @@ public slots:
 	void flushOutput ();
 /** Reload current page.*/
 	void refresh ();
-/** apply our customizations to the khtmlpart GUI */
-	void fixupPartGUI ();
 private slots:
 /** This slot is called when the new page has finished loading. Sets scroll position to scroll_position */
 	void loadDone ();
-	void doGotoAnchorNow ();
 	void mimeTypeDetermined (KIO::Job*, const QString& type);
 	void internalNavigation ();
-protected:
-/** Here we store the state of the part before refresh. Used to scroll to the same position after a reload */
-	QByteArray saved_state;
-/** the part doing all the real work */
-	KParts::ReadOnlyPart * renderingpart;
+private:
+	QWebView* view;
 /** In case the part is a khtmlpart: A ready-cast pointer to that. 0 otherwise (if a webkit part is in use) */
-	KHTMLPart *khtmlpart;
+	RKHTMLWindowPart *part;
 /** update caption according to given URL */
 	virtual void updateCaption (const KUrl &url);
 /** called from openURL. Takes care of updating caption, and updating back/forward actions, if available */
 	void changeURL (const KUrl &url);
-private:
+
 	struct VisitedLocation {
 		KUrl url;
-		QByteArray state;
+		QPoint scroll_position;
 	};
 	QList<VisitedLocation> url_history;
 	void openLocationFromHistory (VisitedLocation &loc);
 	int current_history_position;
 	bool url_change_is_from_history;	// dirty!!!
 
+	KUrl current_url;
+	KTemporaryFile *current_cache_file;
+
+	WindowMode window_mode;
+	void useMode (WindowMode);
+
+	void fileDoesNotExistMessage ();
+
+	void saveBrowserState (VisitedLocation *state);
+	void restoreBrowserState (VisitedLocation *state);
+};
+
+class RKHTMLWindowPart : public KParts::Part {
+	Q_OBJECT
+public:
+	RKHTMLWindowPart (RKHTMLWindow *window);
+	~RKHTMLWindowPart () {};
+
+	void setOutputWindowSkin ();
+	void setHelpWindowSkin ();
+	void initActions ();
+private:
+	friend class RKHTMLWindow;
+	RKHTMLWindow *window;
+
 	// general actions
 	QAction *run_selection;
 	QAction* print;
@@ -126,16 +155,17 @@ private:
 	QAction *back;
 	QAction *forward;
 
-	QString goto_anchor_name;
-	KUrl current_url;
-
-	WindowMode window_mode;
-	void useMode (WindowMode);
-
-	void fileDoesNotExistMessage ();
-
-	void saveBrowserState (QByteArray *state);
-	void restoreBrowserState (QByteArray *state);
+// TODO: Most of these won't need a pointer. This is sort of a todo-list of actions to implement
+	QAction* zoom_in;
+	QAction* zoom_out;
+	QAction* save_page;
+	QAction* find;
+	QAction* findAhead;      // shortcut '/'
+	QAction* find_next;
+	QAction* find_previous;
+	QAction* copy;
+	QAction* select_all;
+	// needed? QAction* encoding;
 };
 
 /**
@@ -146,7 +176,7 @@ private:
 class RKHelpRenderer {
 public:
 /** ctor */
-	RKHelpRenderer (QString *_buffer) { buffer = _buffer; help_xml = 0; component_xml = 0; };
+	RKHelpRenderer (QIODevice *_device) { device = _device; help_xml = 0; component_xml = 0; };
 /** destructor */
 	~RKHelpRenderer () {};
 
@@ -164,7 +194,7 @@ public:
 	RKComponentHandle *componentPathToHandle (QString path);
 	QString startSection (const QString &name, const QString &title, const QString &shorttitle, QStringList *anchors, QStringList *anchor_names);
 
-	QString *buffer;
+	QIODevice *device;
 	void writeHTML (const QString &string);
 };
 
diff --git a/rkward/windows/rkworkplace.cpp b/rkward/windows/rkworkplace.cpp
index 8530ad3..40f7985 100644
--- a/rkward/windows/rkworkplace.cpp
+++ b/rkward/windows/rkworkplace.cpp
@@ -31,6 +31,7 @@
 
 #include <QFileInfo>
 #include <QCryptographicHash>
+#include <QKeyEvent>
 
 #include "detachedwindowcontainer.h"
 #include "rkcommandeditorwindow.h"



More information about the rkward-tracker mailing list