[rkward/frameworks] rkward: Assorted KF5 porting

Thomas Friedrichsmeier thomas.friedrichsmeier at ruhr-uni-bochum.de
Thu Nov 19 20:51:13 UTC 2015


Git commit 12e355eaf1e5ae6448efada2b1751aec6c02947e by Thomas Friedrichsmeier.
Committed on 19/11/2015 at 20:50.
Pushed by tfry into branch 'frameworks'.

Assorted KF5 porting

Hooray! It compiles! (Of course, it does not run, yet, but...)

M  +1    -1    rkward/CMakeLists.txt
M  +1    -1    rkward/core/CMakeLists.txt
M  +58   -50   rkward/main.cpp
M  +0    -2    rkward/misc/rkaccordiontable.cpp
M  +0    -3    rkward/misc/rkdynamicsearchline.cpp
M  +2    -2    rkward/misc/rkmessagecatalog.cpp
M  +1    -0    rkward/rbackend/rkwarddevice/CMakeLists.txt
M  +2    -1    rkward/rkconsole.cpp
M  +17   -19   rkward/rkward.cpp
M  +33   -131  rkward/rkwardapplication.cpp
M  +13   -11   rkward/rkwardapplication.h

http://commits.kde.org/rkward/12e355eaf1e5ae6448efada2b1751aec6c02947e

diff --git a/rkward/CMakeLists.txt b/rkward/CMakeLists.txt
index ca23081..9c24f3c 100644
--- a/rkward/CMakeLists.txt
+++ b/rkward/CMakeLists.txt
@@ -60,7 +60,7 @@ IF(Q_WS_MAC)
 		@ONLY)
 ENDIF(Q_WS_MAC)
 
-TARGET_LINK_LIBRARIES(rkward.frontend  windows ${RKWARD_ADDLIBS} agents dialogs plugin settings dataeditor core scriptbackends rbackend misc KF5::TextEditor   ${KDE4_KDEWEBKIT_LIBS} Qt5::DBus Qt5::Script Qt5::Network ${GETTEXT_LIBRARIES})
+TARGET_LINK_LIBRARIES(rkward.frontend  windows ${RKWARD_ADDLIBS} agents dialogs plugin settings dataeditor core scriptbackends rbackend misc KF5::KDELibs4Support KF5::WindowSystem Qt5::Widgets KF5::XmlGui ${GETTEXT_LIBRARIES})
 
 # wrapper executable
 GET_DIRECTORY_PROPERTY(R_EXECUTABLE DIRECTORY rbackend DEFINITION R_EXECUTABLE)
diff --git a/rkward/core/CMakeLists.txt b/rkward/core/CMakeLists.txt
index b63e7c1..c366ead 100644
--- a/rkward/core/CMakeLists.txt
+++ b/rkward/core/CMakeLists.txt
@@ -16,7 +16,7 @@ SET(core_STAT_SRCS
    )
 
 ADD_LIBRARY(core STATIC ${core_STAT_SRCS})
-
+TARGET_LINK_LIBRARIES(core Qt5::Core KF5::KDELibs4Support)
 
 ########### install files ###############
 
diff --git a/rkward/main.cpp b/rkward/main.cpp
index 0694d64..26e01f4 100644
--- a/rkward/main.cpp
+++ b/rkward/main.cpp
@@ -50,10 +50,11 @@
 **
 */
 
-#include <kcmdlineargs.h>
+
 #include <kaboutdata.h>
 #include <klocale.h>
 #include <kstandarddirs.h>
+#include <kglobal.h>
 
 #include <qstring.h>
 #include <QMutex>
@@ -63,6 +64,7 @@
 
 #include <stdio.h>
 #include <stdlib.h>
+#include <QCommandLineParser>
 
 #include "rkward.h"
 #include "rkglobals.h"
@@ -84,8 +86,6 @@ int RK_Debug_Flags = DEBUG_ALL;
 int RK_Debug_CommandStep = 0;
 QMutex RK_Debug_Mutex;
 
-static KCmdLineOptions options;
-
 void RKDebugMessageOutput (QtMsgType type, const char *msg) {
 	RK_Debug_Mutex.lock ();
 	if (type == QtFatalMsg) {
@@ -119,37 +119,7 @@ QString decodeArgument (const QString &input) {
 	return (QUrl::fromPercentEncoding (input.toUtf8()));
 }
 
-int main(int argc, char *argv[]) {
-	options.add ("evaluate <Rcode>", ki18n ("After starting (and after loading the specified workspace, if applicable), evaluate the given R code."), 0);
-	options.add ("debug-level <level>", ki18n ("Verbosity of debug messages (0-5)"), "2");
-	options.add ("debug-flags <flags>", ki18n ("Mask for components to debug (see debug.h)"), QString::number (DEBUG_ALL).toLocal8Bit ());
-	options.add ("debugger <command and arguments>", ki18n ("Debugger for the frontend. Specify last, or add '--' after all debugger arguments"), "");
-	options.add ("backend-debugger <command>", ki18n ("Debugger for the backend. (Enclose any debugger arguments in single quotes ('') together with the command. Make sure to re-direct stdout!)"), "");
-	options.add ("r-executable <command>", ki18n ("Use specified R installation, instead of the one configured at compile time (note: rkward R library must be installed to that installation of R)"), "");
-	options.add ("reuse", ki18n ("Reuse a running RKWard instance (if available). If a running instance is reused, only the file arguments will be interpreted, all other options will be ignored."), 0);
-	options.add ("+[Files]", ki18n ("File or files to open, typically a workspace, or an R script file. When loading several things, you should specify the workspace, first."), 0);
-
-	KAboutData aboutData("rkward", QByteArray (), ki18n ("RKWard"), RKWARD_VERSION, ki18n ("Frontend to the R statistics language"), KAboutData::License_GPL, ki18n ("(c) 2002, 2004 - 2014"), KLocalizedString (), "http://rkward.kde.org", "submit at bugs.kde.org");
-	aboutData.addAuthor (ki18n ("Thomas Friedrichsmeier"), ki18n ("Project leader / main developer"));
-	aboutData.addAuthor (ki18n ("Pierre Ecochard"), ki18n ("C++ developer between 2004 and 2007"));
-	aboutData.addAuthor (ki18n ("Prasenjit Kapat"), ki18n ("Many plugins, suggestions, plot history feature"));
-	aboutData.addAuthor (ki18n ("Meik Michalke"), ki18n ("Many plugins, suggestions, rkwarddev package"));
-	aboutData.addAuthor (ki18n ("Stefan Roediger"), ki18n ("Many plugins, suggestions, marketing, translations"));
-	aboutData.addCredit (ki18n ("Contributors in alphabetical order"));
-	aboutData.addCredit (ki18n ("Philippe Grosjean"), ki18n ("Several helpful comments and discussions"));
-	aboutData.addCredit (ki18n ("Adrien d'Hardemare"), ki18n ("Plugins and patches"));
-	aboutData.addCredit (ki18n ("Yves Jacolin"), ki18n ("New website"));
-	aboutData.addCredit (ki18n ("Germán Márquez Mejía"), ki18n ("HP filter plugin, spanish translation"), 0);
-	aboutData.addCredit (ki18n ("Marco Martin"), ki18n ("A cool icon"));
-	aboutData.addCredit (ki18n ("Daniele Medri"), ki18n ("RKWard logo, many suggestions, help on wording"));
-	aboutData.addCredit (ki18n ("David Sibai"), ki18n ("Several valuable comments, hints and patches"));
-	aboutData.addCredit (ki18n ("Ilias Soumpasis"), ki18n ("Translation, Suggestions, plugins"));
-	aboutData.addCredit (ki18n ("Ralf Tautenhahn"), ki18n ("Many comments, useful suggestions, and bug reports"));
-	aboutData.addCredit (ki18n ("Jannis Vajen"), ki18n ("German Translation, bug reports"));
-	aboutData.addCredit (ki18n ("Roland Vollgraf"), ki18n ("Some patches"));
-	aboutData.addCredit (ki18n ("Roy Qu"), ki18n ("patches and helpful comments"));
-	aboutData.addCredit (ki18n ("Many more people on rkward-devel at kde.org"), ki18n ("Sorry, if we forgot to list you. Please contact us to get added"));
-
+int main (int argc, char *argv[]) {
 	// before initializing the commandline args, remove the ".bin" from "rkward.bin".
 	// This is so it prints "Usage rkward..." instead of "Usage rkward.bin...", etc.
 	// it seems safest to keep a copy, since the shell still owns argv
@@ -158,30 +128,68 @@ int main(int argc, char *argv[]) {
 	for (int i = 1; i < argc; ++i) {
 		argv_copy[i] = argv[i];
 	}
-	KCmdLineArgs::init (argc, argv_copy, &aboutData);
-	KCmdLineArgs::addCmdLineOptions( options ); // Add our own options.
 
-	KCmdLineArgs *args = KCmdLineArgs::parsedArgs();
-	RK_Debug_Level = DL_FATAL - QString (args->getOption ("debug-level")).toInt ();
-	RK_Debug_Flags = QString (args->getOption ("debug-flags")).toInt ();
-	if (!args->getOption ("debugger").isEmpty ()) {
+	RKWardApplication app (argc, argv_copy);
+
+	KAboutData aboutData ("rkward", i18n ("RKWard"), RKWARD_VERSION, i18n ("Frontend to the R statistics language"), KAboutLicense::GPL, i18n ("(c) 2002, 2004 - 2015"), QString (), "http://rkward.kde.org");
+	aboutData.addAuthor (i18n ("Thomas Friedrichsmeier"), i18n ("Project leader / main developer"));
+	aboutData.addAuthor (i18n ("Pierre Ecochard"), i18n ("C++ developer between 2004 and 2007"));
+	aboutData.addAuthor (i18n ("Prasenjit Kapat"), i18n ("Many plugins, suggestions, plot history feature"));
+	aboutData.addAuthor (i18n ("Meik Michalke"), i18n ("Many plugins, suggestions, rkwarddev package"));
+	aboutData.addAuthor (i18n ("Stefan Roediger"), i18n ("Many plugins, suggestions, marketing, translations"));
+	aboutData.addCredit (i18n ("Contributors in alphabetical order"));
+	aboutData.addCredit (i18n ("Philippe Grosjean"), i18n ("Several helpful comments and discussions"));
+	aboutData.addCredit (i18n ("Adrien d'Hardemare"), i18n ("Plugins and patches"));
+	aboutData.addCredit (i18n ("Yves Jacolin"), i18n ("New website"));
+	aboutData.addCredit (i18n ("Germán Márquez Mejía"), i18n ("HP filter plugin, spanish translation"), 0);
+	aboutData.addCredit (i18n ("Marco Martin"), i18n ("A cool icon"));
+	aboutData.addCredit (i18n ("Daniele Medri"), i18n ("RKWard logo, many suggestions, help on wording"));
+	aboutData.addCredit (i18n ("David Sibai"), i18n ("Several valuable comments, hints and patches"));
+	aboutData.addCredit (i18n ("Ilias Soumpasis"), i18n ("Translation, Suggestions, plugins"));
+	aboutData.addCredit (i18n ("Ralf Tautenhahn"), i18n ("Many comments, useful suggestions, and bug reports"));
+	aboutData.addCredit (i18n ("Jannis Vajen"), i18n ("German Translation, bug reports"));
+	aboutData.addCredit (i18n ("Roland Vollgraf"), i18n ("Some patches"));
+	aboutData.addCredit (i18n ("Roy Qu"), i18n ("patches and helpful comments"));
+	aboutData.addCredit (i18n ("Many more people on rkward-devel at kde.org"), i18n ("Sorry, if we forgot to list you. Please contact us to get added"));
+	KAboutData::setApplicationData (aboutData);
+
+	QCommandLineParser parser;
+	parser.addVersionOption ();
+	parser.addHelpOption ();
+	parser.addOption (QCommandLineOption ("evaluate", i18n ("After starting (and after loading the specified workspace, if applicable), evaluate the given R code."), "Rcode", QString ()));
+	parser.addOption (QCommandLineOption ("debug-level", i18n ("Verbosity of debug messages (0-5)"), "level", "2"));
+	parser.addOption (QCommandLineOption ("debug-flags", i18n ("Mask for components to debug (see debug.h)"), "flags", QString::number (DEBUG_ALL)));
+	parser.addOption (QCommandLineOption ("debugger", i18n ("Debugger for the frontend. Specify last, or add '--' after all debugger arguments"), "command and arguments", QString ()));
+	parser.addOption (QCommandLineOption ("backend-debugger", i18n ("Debugger for the backend. (Enclose any debugger arguments in single quotes ('') together with the command. Make sure to re-direct stdout!)"), "command", QString ()));
+	parser.addOption (QCommandLineOption ("r-executable", i18n ("Use specified R installation, instead of the one configured at compile time (note: rkward R library must be installed to that installation of R)"), "command", QString ()));
+	parser.addOption (QCommandLineOption ("reuse", i18n ("Reuse a running RKWard instance (if available). If a running instance is reused, only the file arguments will be interpreted, all other options will be ignored.")));
+	parser.addPositionalArgument ("files", i18n ("File or files to open, typically a workspace, or an R script file. When loading several things, you should specify the workspace, first."), "[Files...]");
+
+	aboutData.setupCommandLine (&parser);
+	parser.process (app);
+	aboutData.processCommandLine (&parser);
+
+	RK_Debug_Level = DL_FATAL - QString (parser.value ("debug-level")).toInt ();
+	RK_Debug_Flags = QString (parser.value ("debug-flags")).toInt ();
+	if (!parser.value ("debugger").isEmpty ()) {
 		RK_DEBUG (DEBUG_ALL, DL_ERROR, "--debugger option should have been handled by wrapper script. Ignoring.");
 	}
 
-	if (args->count ()) {
+	QStringList url_args = parser.positionalArguments ();
+	if (!url_args.isEmpty ()) {
 		QVariantList urls_to_open;
-		for (int i = 0; i < args->count (); ++i) {
-			urls_to_open.append (QUrl (KCmdLineArgs::makeURL (decodeArgument (args->arg (i)).toUtf8 ())));
+		for (int i = 0; i < url_args.count (); ++i) {
+			urls_to_open.append (QUrl::fromUserInput (url_args[i], QDir::currentPath(), QUrl::AssumeLocalFile));
 		}
 		RKGlobals::startup_options["initial_urls"] = urls_to_open;
 	}
-	RKGlobals::startup_options["evaluate"] = decodeArgument (args->getOption ("evaluate"));
-	RKGlobals::startup_options["backend-debugger"] = decodeArgument (args->getOption ("backend-debugger"));
+	RKGlobals::startup_options["evaluate"] = decodeArgument (parser.value ("evaluate"));
+	RKGlobals::startup_options["backend-debugger"] = decodeArgument (parser.value ("backend-debugger"));
 
-	RKWardApplication app;
 	// No, I do not really understand the point of separating KDE_LANG from LANGUAGE. We do honor it in so far as not
 	// forcing LANGUAGE on the backend, though. Having language as LANGUAGE makes code in RKMessageCatalog much easier compared to KCatalog.
-	qputenv ("LANGUAGE", QFile::encodeName (KGlobal::locale ()->language ()));
+	// KF5 TODO: is this still needed at all? Does KDE_LANG still exist?
+	qputenv ("LANGUAGE", QLocale ().bcp47Name ().section ('-', 0, 0).toAscii ());
 	// install message handler *after* the componentData has been initialized
 	RKSettingsModuleDebug::debug_file = new QTemporaryFile (QDir::tempPath () + "/rkward.frontend");
 	RKSettingsModuleDebug::debug_file->setAutoRemove (false);
@@ -195,12 +203,12 @@ int main(int argc, char *argv[]) {
 	} else {
 		new RKWardMainWindow ();
 	}
-	args->clear();
+	
 
 	// Usually, KDE always adds the current directory to the list of prefixes.
 	// However, since RKWard 0.5.6, the main binary is in KDE's libexec dir, which defies this mechanism. Therefore, RKWARD_ENSURE_PREFIX is set from the wrapper script.
-	char *add_path = getenv ("RKWARD_ENSURE_PREFIX");
-	if (add_path) KGlobal::dirs ()->addPrefix (QString::fromLocal8Bit (add_path));
+	QByteArray add_path = qgetenv ("RKWARD_ENSURE_PREFIX");
+	if (!add_path.isEmpty ()) KGlobal::dirs ()->addPrefix (QString::fromLocal8Bit (add_path));
 
 	// do it!
 	int status = app.exec ();
diff --git a/rkward/misc/rkaccordiontable.cpp b/rkward/misc/rkaccordiontable.cpp
index d374451..f0cbeeb 100644
--- a/rkward/misc/rkaccordiontable.cpp
+++ b/rkward/misc/rkaccordiontable.cpp
@@ -512,6 +512,4 @@ void RKAccordionTable::setModel (QAbstractItemModel* model) {
 	updateGeometry ();   // TODO: Not so clean to call this, here. But at this point we know the display_widget has been constructed, too
 }
 
-// KF5 TODO: remove:
 #include "rkaccordiontable.moc"
-#include "rkaccordiontablemodel_moc.cpp"
diff --git a/rkward/misc/rkdynamicsearchline.cpp b/rkward/misc/rkdynamicsearchline.cpp
index 0bcbe04..23c13f1 100644
--- a/rkward/misc/rkdynamicsearchline.cpp
+++ b/rkward/misc/rkdynamicsearchline.cpp
@@ -62,6 +62,3 @@ void RKDynamicSearchLine::delayedSearch () {
 	if (model) model->setFilterRegExp (filter);
 	emit (searchChanged (filter));
 }
-
-// KF5 TODO: remove
-#include "rkdynamicsearchline.moc"
diff --git a/rkward/misc/rkmessagecatalog.cpp b/rkward/misc/rkmessagecatalog.cpp
index aff7628..de6dc57 100644
--- a/rkward/misc/rkmessagecatalog.cpp
+++ b/rkward/misc/rkmessagecatalog.cpp
@@ -116,8 +116,8 @@ void RKMessageCatalog::switchLanguage (const QString &new_language_code) {
 	RK_TRACE (MISC);
 
 	qputenv ("LANGUAGE", new_language_code.toAscii ().data ());
-	KLocale *l = new KLocale ("rkward", new_language_code);
-	KGlobal::setLocale (l);
+	// KF5 TODO: correct?
+	QLocale::setDefault (QLocale (new_language_code));
 	// magic to make gettext discard cache
 #ifndef _MSC_VER
 	extern int _nl_msg_cat_cntr;
diff --git a/rkward/rbackend/rkwarddevice/CMakeLists.txt b/rkward/rbackend/rkwarddevice/CMakeLists.txt
index 081a0d4..e3099f9 100644
--- a/rkward/rbackend/rkwarddevice/CMakeLists.txt
+++ b/rkward/rbackend/rkwarddevice/CMakeLists.txt
@@ -17,3 +17,4 @@ ADD_LIBRARY(rkgraphicsdevice.frontend STATIC ${rkgraphicsdevice_frontend_SRCS})
 TARGET_LINK_LIBRARIES(rkgraphicsdevice.frontend Qt5::Widgets Qt5::Core Qt5::Network KF5::WidgetsAddons KF5::KDELibs4Support)
 
 ADD_LIBRARY(rkgraphicsdevice.backend STATIC ${rkgraphicsdevice_backend_SRCS})
+TARGET_LINK_LIBRARIES(rkgraphicsdevice.backend Qt5::Core Qt5::Network)
\ No newline at end of file
diff --git a/rkward/rkconsole.cpp b/rkward/rkconsole.cpp
index 04cd042..eebd52d 100644
--- a/rkward/rkconsole.cpp
+++ b/rkward/rkconsole.cpp
@@ -69,7 +69,8 @@ RKConsole::RKConsole (QWidget *parent, bool tool_window, const char *name) : RKM
 	layout->setContentsMargins (0, 0, 0, 0);
 
 	// create a Kate-part as command-editor
-	KTextEditor::Editor* editor = KTextEditor::editor ("katepart");
+	// KF5 TODO: (How) can we make sure we are getting a katepart, here, not some other implementation. Or can we take that for granted?
+	KTextEditor::Editor* editor = KTextEditor::Editor::instance ();
 	if (!editor) {
 		RK_ASSERT (false);
 		KMessageBox::error (this, i18n ("The 'katepart' component could not be loaded. RKWard cannot run without katepart, and will exit, now. Please install katepart, and try again."), i18n ("'katepart' component could not be found"));
diff --git a/rkward/rkward.cpp b/rkward/rkward.cpp
index f3b5e93..f79ba56 100644
--- a/rkward/rkward.cpp
+++ b/rkward/rkward.cpp
@@ -19,6 +19,7 @@
 #include <qtimer.h>
 #include <QDesktopWidget>
 #include <QCloseEvent>
+#include <QPointer>
 
 // include files for KDE
 #include <kmessagebox.h>
@@ -40,6 +41,8 @@
 #include <khbox.h>
 #include <ktoolbar.h>
 #include <kactionmenu.h>
+#include <kicon.h>
+#include <KSharedConfig>
 
 // application specific includes
 #include "rkward.h"
@@ -662,18 +665,19 @@ void RKWardMainWindow::openWorkspace (const KUrl &url) {
 
 void RKWardMainWindow::saveOptions () {
 	RK_TRACE (APP);
-	KConfig *config = KGlobal::config ().data ();
+	KSharedConfig::Ptr config = KSharedConfig::openConfig ();
 
-	saveMainWindowSettings (config->group ("main window options"));
+	KConfigGroup cg = config->group ("main window options");
+	saveMainWindowSettings (cg);
 
-	KConfigGroup cg = config->group ("General Options");
+	cg = config->group ("General Options");
 // TODO: WORKAROUND. See corresponding line in readOptions ()
 	cg.writeEntry("Geometry", size ());
 
 	fileOpenRecentWorkspace->saveEntries (config->group ("Recent Files"));
 	fileOpenRecent->saveEntries (config->group ("Recent Command Files"));
 
-	RKSettings::saveSettings (config);
+	RKSettings::saveSettings (config.data ());
 
 	config->sync ();
 }
@@ -681,19 +685,14 @@ void RKWardMainWindow::saveOptions () {
 
 void RKWardMainWindow::readOptions () {
 	RK_TRACE (APP);
-	// first make sure to give the global defaults a chance, if needed.
-	// TODO: Why don't the toolbars honor the global style automatically?
-	QList<KToolBar*> tool_bars = toolBars ();
-	for (int i=0; i < tool_bars.size (); ++i) {
-		tool_bars[i]->setToolButtonStyle (KToolBar::toolButtonStyleSetting ());
-	}
 
-	KConfig *config = KGlobal::config ().data ();
+	KSharedConfig::Ptr config = KSharedConfig::openConfig ();
 
-	applyMainWindowSettings (config->group ("main window options"), true);
+	applyMainWindowSettings (config->group ("main window options"));
 
 // TODO: WORKAROUND: Actually applyMainWindowSettings could/should do this, but apparently this just does not work for maximized windows. Therefore we use our own version instead.
 // KDE4: still needed?
+// KF5 TODO: still needed?
 	KConfigGroup cg = config->group ("General Options");
 	QSize size = cg.readEntry ("Geometry", QSize ());
 	if (size.isEmpty ()) {
@@ -701,8 +700,7 @@ void RKWardMainWindow::readOptions () {
 	}
 	resize (size);
 
-	RKSettings::loadSettings (config);
-	RK_ASSERT (config == KGlobal::config ().data ());	// not messing with config groups
+	RKSettings::loadSettings (config.data ());
 
 	// initialize the recent file list
 	fileOpenRecentWorkspace->loadEntries (config->group ("Recent Files"));
@@ -710,6 +708,7 @@ void RKWardMainWindow::readOptions () {
 	fileOpenRecent->loadEntries (config->group ("Recent Command Files"));
 }
 
+
 bool RKWardMainWindow::doQueryQuit () {
 	RK_TRACE (APP);
 
@@ -910,19 +909,18 @@ void RKWardMainWindow::slotOpenCommandEditor (const KUrl &url, const QString &en
 void RKWardMainWindow::slotOpenCommandEditor () {
 	RK_TRACE (APP);
 	KEncodingFileDialog::Result res;
-	KUrl::List::const_iterator it;
 
 #ifdef Q_WS_WIN
 	// getOpenUrls(KUrl("kfiledialog:///<rfiles>"), ...) causes a hang on windows (KDElibs 4.2.3).
 #	ifdef __GNUC__
 #		warning Track this bug down and/or report it
 #	endif
-	res = KEncodingFileDialog::getOpenUrlsAndEncoding (QString (), QString (), QString ("%1|R Script Files (%1)\n*|All Files (*)").arg (RKSettingsModuleCommandEditor::scriptFileFilter ()), this, i18n ("Open script file(s)"));
+	res = KEncodingFileDialog::getOpenUrlsAndEncoding (QString (), QUrl (), QString ("%1|R Script Files (%1)\n*|All Files (*)").arg (RKSettingsModuleCommandEditor::scriptFileFilter ()), this, i18n ("Open script file(s)"));
 #else
-	res = KEncodingFileDialog::getOpenUrlsAndEncoding (QString (), "kfiledialog:///<rfiles>", QString ("%1|R Script Files (%1)\n*|All Files (*)").arg (RKSettingsModuleCommandEditor::scriptFileFilter ()), this, i18n ("Open script file(s)"));
+	res = KEncodingFileDialog::getOpenUrlsAndEncoding (QString (), QUrl ("kfiledialog:///<rfiles>"), QString ("%1|R Script Files (%1)\n*|All Files (*)").arg (RKSettingsModuleCommandEditor::scriptFileFilter ()), this, i18n ("Open script file(s)"));
 #endif
-	for (it = res.URLs.begin() ; it != res.URLs.end() ; ++it) {
-		slotOpenCommandEditor (*it, res.encoding);
+	for (int i = 0; i < res.URLs.size (); ++i) {
+		slotOpenCommandEditor (res.URLs[i], res.encoding);
 	}
 };
 
diff --git a/rkward/rkwardapplication.cpp b/rkward/rkwardapplication.cpp
index d3d4102..ebf3687 100644
--- a/rkward/rkwardapplication.cpp
+++ b/rkward/rkwardapplication.cpp
@@ -19,68 +19,26 @@
 
 #include "windows/rkmdiwindow.h"
 
-#ifdef Q_WS_WIN
-#	include <windows.h>
-#elif defined Q_WS_MAC
-#	ifdef __GNUC__
-#		warning "Graph window capturing is not supported on Mac OS native, yet. Consider using X11."
-#	endif
-#else
-#	include <X11/X.h>
-#	include <X11/Xlib.h>
-
-#	include <QX11Info>
-
-#	include <kwindowinfo.h>
-#	include <netwm_def.h>
-//static
-Atom wm_name_property;
-#endif	//Q_WS_WIN
-
-#include <kauthorized.h>
+#include <KWindowInfo>
+#include <KWindowSystem>
+#include <KUrlAuthorized>
+#include <kurl.h>
 
 #include "debug.h"
 
-#ifdef __GNUC__
-#	warning TODO: We could really use the detection logic from windows for x11, too. It seems much easier.
-#endif
-#ifdef Q_WS_WIN
-#include <stdio.h>
-namespace RKWardApplicationPrivate {
-	QList<WId> toplevel_windows;
-
-	BOOL CALLBACK EnumWindowsCallback (HWND hwnd, LPARAM) {
-		toplevel_windows.append (hwnd);
-		return true;
-	}
-
-	void updateToplevelWindowList () {
-		RK_TRACE (APP);
-
-		toplevel_windows.clear ();
-		EnumWindows (EnumWindowsCallback, 0);
-	};
-}
-#endif	//Q_WS_WIN
-
 //static
 RKWardApplication *RKWardApplication::rkapp = 0;
 
-RKWardApplication::RKWardApplication () : KApplication () {
+RKWardApplication::RKWardApplication (int argc, char *argv[]) : QApplication (argc, argv) {
 	//RK_TRACE (APP);	// would be called before initialization of debug-level
 	RK_ASSERT (!rkapp);
 
 	// Don't complain when linking rkward://-pages from Rd pages
-	KAuthorized::allowUrlAction ("redirect", KUrl ("http://"), KUrl ("rkward://"));
+	KUrlAuthorized::allowUrlAction ("redirect", KUrl ("http://"), KUrl ("rkward://"));
 	// Don't complain when trying to open help pages
-	KAuthorized::allowUrlAction ("redirect", KUrl ("rkward://"), KUrl ("help:"));
+	KUrlAuthorized::allowUrlAction ("redirect", KUrl ("rkward://"), KUrl ("help:"));
 
 	rkapp = this;
-	detect_x11_creations = false;
-
-#ifdef Q_WS_X11
-	wm_name_property = XInternAtom (QX11Info::display (), "WM_NAME", true);
-#endif	//Q_WS_X11
 }
 
 RKWardApplication::~RKWardApplication () {
@@ -89,80 +47,53 @@ RKWardApplication::~RKWardApplication () {
 
 RKWardApplication *RKWardApplication::getApp () {
 	RK_TRACE (APP);
-	RK_ASSERT (rkapp == KApplication::kApplication ());
+	RK_ASSERT (rkapp == QApplication::instance ());
 	return rkapp;
 }
 
 void RKWardApplication::startWindowCreationDetection () {
 	RK_TRACE (APP);
-	RK_ASSERT (!detect_x11_creations);
 
 	created_window = 0;
-	detect_x11_creations = true;
-
-#ifdef Q_WS_WIN
-	RKWardApplicationPrivate::updateToplevelWindowList ();
-#elif defined Q_WS_X11
-	XSelectInput (QX11Info::display (), QX11Info::appRootWindow (), SubstructureNotifyMask);
-	syncX ();	// this is to make sure we don't miss out on the window creation (if it happens very early). Testing shows, we really need this.
-#endif
+
+	connect (KWindowSystem::self (), SIGNAL (windowAdded(WId)), this, SLOT (windowAdded(WId)));
 }
 
 WId RKWardApplication::endWindowCreationDetection () {
 	RK_TRACE (APP);
-	RK_ASSERT (detect_x11_creations);
-
-#ifdef Q_WS_WIN
-	QList<WId> old_windows = RKWardApplicationPrivate::toplevel_windows;
-	RKWardApplicationPrivate::updateToplevelWindowList ();
-	QList<WId> candidate_windows = RKWardApplicationPrivate::toplevel_windows;
-
-	detect_x11_creations = false;
-
-	// remove all windows that existed before the call to startWindowCreationDetection
-	for (int i = 0; i < old_windows.size (); ++i) {
-		candidate_windows.removeAll (old_windows[i]);
-	}
-	// ideally we have a single candidate remaining, now, but sometimes, additional
-	// invisible windows are created somehow (probably by R's graphapp)
-	for (int i = 0; i < candidate_windows.size (); ++i) {
-		HWND hwnd = candidate_windows[i];
-		if ((!IsWindow(hwnd)) || (!IsWindowVisible(hwnd))) {
-			 candidate_windows.removeAt (i);
-			 --i;
-		}
-	}
-
-	// we could do some more checking, e.g. based on whether the window belongs to our
-	// own process, and whether it appears to be of a sane size, but for now, we keep
-	// things simple.
 
-	if (candidate_windows.size ()) {
-		RK_ASSERT (candidate_windows.size () < 2);
-		return candidate_windows[0];
-	}
-	return 0;
-#elif defined Q_WS_X11
 	if (!created_window) {
 		// we did not see the window, yet? Maybe the event simply hasn't been processed, yet.
-		syncX ();
 		processEvents ();
 	}
-
-	detect_x11_creations = false;
-	XSelectInput (QX11Info::display (), QX11Info::appRootWindow (), NoEventMask);
+	disconnect (KWindowSystem::self (), SIGNAL (windowAdded(WId)), this, SLOT (windowAdded(WId)));
 	return created_window;
-#else
-	return 0;
-#endif
 }
 
-#ifdef Q_WS_X11
+void RKWardApplication::windowAdded (WId id) {
+	RK_TRACE (APP);
+
+	// KF5 TODO: Note: Previously, on windows we checked for IsWindow (hwnd) and IsWindowVisible (hwnd), as sometimes invisible ghost windows
+	// would be created in addition to the real device window. Is this still needed?
+	created_window = id;
+}
+
+void RKWardApplication::windowChanged (WId id, NET::Properties properties, NET::Properties2 properties2) {
+	Q_UNUSED (properties2);
+	if (!(properties & NET::WMName)) return;
+	RK_TRACE (APP);
+	RKMDIWindow *watcher = name_watchers_list.value (id);
+	if (!watcher) return;
+	watcher->setCaption (KWindowInfo (id, NET::WMName).name ());
+}
+
 void RKWardApplication::registerNameWatcher (WId watched, RKMDIWindow *watcher) {
 	RK_TRACE (APP);
 	RK_ASSERT (!name_watchers_list.contains (watched));
 
-	XSelectInput (QX11Info::display (), watched, PropertyChangeMask);
+	if (name_watchers_list.isEmpty ()) {
+		connect (KWindowSystem::self (), SIGNAL (windowChanged(WId,NET::Properties,NET::Properties2)), this, SLOT (windowChanged(WId,NET::Properties,NET::Properties2)));
+	}
 	name_watchers_list.insert (watched, watcher);
 }
 
@@ -170,37 +101,8 @@ void RKWardApplication::unregisterNameWatcher (WId watched) {
 	RK_TRACE (APP);
 	RK_ASSERT (name_watchers_list.contains (watched));
 
-	XSelectInput (QX11Info::display (), watched, NoEventMask);
 	name_watchers_list.remove (watched);
-}
-
-bool RKWardApplication::x11EventFilter (XEvent *e) {
-	if (detect_x11_creations) {
-		if (e->type == CreateNotify) {
-			if (e->xcreatewindow.parent == QX11Info::appRootWindow ()) {
-				KWindowInfo info = KWindowInfo (e->xcreatewindow.window, NET::WMName | NET::WMWindowType);
-				// at this point, we used to check, whether this window has some name or another. This heuristic allowed to sieve out helper windows of the window manager. However, since R 2.8.0, sometimes the window is mapped, before it has been given a name.
-				// Now we rely on the fact (we hope it *is* a fact), that the device window is always the first one created.
-				if ((info.windowType (0xFFFF) != 0) && (!created_window)) {
-					created_window = e->xcreatewindow.window;
-					return true;
-				}
-			} else {
-				RK_ASSERT (false);
-			}
-		}
+	if (name_watchers_list.isEmpty ()) {
+		disconnect (KWindowSystem::self (), SIGNAL (windowChanged(WId,NET::Properties,NET::Properties2)), this, SLOT (windowChanged(WId,NET::Properties,NET::Properties2)));
 	}
-
-	if (e->type == PropertyNotify) {
-		if (e->xproperty.atom == wm_name_property) {
-			if (name_watchers_list.contains (e->xproperty.window)) {
-				KWindowInfo wininfo = KWindowInfo (e->xproperty.window, NET::WMName);
-				name_watchers_list[e->xproperty.window]->setCaption (wininfo.name ());
-				return true;
-			}
-		}
-	}
-
-	return KApplication::x11EventFilter (e);
 }
-#endif	// Q_WS_X11
diff --git a/rkward/rkwardapplication.h b/rkward/rkwardapplication.h
index f1d38f4..14d09b5 100644
--- a/rkward/rkwardapplication.h
+++ b/rkward/rkwardapplication.h
@@ -18,17 +18,22 @@
 #ifndef RKWARDAPPLICATION_H
 #define RKWARDAPPLICATION_H
 
-#include <kapplication.h>
+#include <QApplication>
+#include <netwm_def.h>
 
 #include <qmap.h>
 
 class RKMDIWindow;
 
-/** The purpose of subclassing KApplication as RKWardApplication, is to obtain raw access to X11 events. This is needed to detect the creation of new toplevel windows (R X11 windows), and changed in the caption of those windows. */
+/** The purpose of subclassing KApplication as RKWardApplication, is to obtain raw access to X11 events. This is needed to detect the creation of new toplevel windows (R X11 windows), and changed in the caption of those windows.
+ * 
+ * KF5 TODO: This class should no longer be needed, but should be moved to window catcher (if the code that is in it now, works)
+*/
 
-class RKWardApplication : public KApplication {
+class RKWardApplication : public QApplication {
+	Q_OBJECT
 public:
-	RKWardApplication ();
+	RKWardApplication (int argc, char *argv[]);
 	~RKWardApplication ();
 
 	/** like KApplication::kApplication () (and actually, this should always return the same pointer), but without the need to cast */
@@ -40,18 +45,15 @@ public:
 	@returns the window id of the last top-level window created after the last call to startWindowCreation, hoping it was only one. 0 if no window was created/detected. */
 	WId endWindowCreationDetection ();
 
-#ifdef Q_WS_X11
-	/** watch the given window for changes in its WM_NAME property (i.e. changes in caption). When a change is detected, the caption will be set on watcher. WARNING: Do not use to watch windows managed by Qt! Will override the event mask for this window (within qt_xdisplay ()). WARNING: Remember to call unregisterNameWatcher, when watcher is deleted! */
+	/** watch the given window for changes in its WM_NAME property (i.e. changes in caption). When a change is detected, the caption will be set on watcher. WARNING: Do not use to watch windows managed by Qt! WARNING: Remember to call unregisterNameWatcher, when watcher is deleted! */
 	void registerNameWatcher (WId watched, RKMDIWindow *watcher);
 	/** remove a watch created with registerNameWatcher */
 	void unregisterNameWatcher (WId watched);
-
-	/** reimplemented from KApplication to look for CreateNotify and PropertyNotify events */
-	bool x11EventFilter (XEvent *e);
-#endif
+public slots:
+	void windowAdded (WId id);
+	void windowChanged (WId id, NET::Properties properties, NET::Properties2 properties2);
 private:
 	static RKWardApplication *rkapp;
-	bool detect_x11_creations;
 	WId created_window;
 
 	QMap<WId, RKMDIWindow*> name_watchers_list;



More information about the rkward-tracker mailing list