Commit 997541a6 authored by David Faure's avatar David Faure

Move code that talks to a running konq (or starts one) into a separate class.

The intention was to put that in libkonq and use it in konqueror,
but after all, KDBusService::Unique is better suited for that.

Still, making things modular isn't bad, so I'm keeping this separate class,
just here in kfmclient.
parent 0c367ad0
......@@ -2,12 +2,14 @@
include(ECMMarkNonGuiExecutable)
find_package(KF5 REQUIRED Init)
set(kfmclient_SRCS kfmclient.cpp )
set(kfmclient_SRCS
kfmclient.cpp
konqclientrequest.cpp
)
qt5_add_dbus_interface( kfmclient_SRCS ../src/org.kde.Konqueror.Main.xml konq_main_interface )
qt5_add_dbus_interface( kfmclient_SRCS ../src/org.kde.Konqueror.MainWindow.xml konq_mainwindow_interface )
add_definitions(-DQT_NO_CAST_ASCII)
set(kfmclient_LIBS
......
......@@ -19,6 +19,8 @@
#include "kfmclient.h"
#include <konqclientrequest.h>
#include <ktoolinvocation.h>
#include <kio/job.h>
#include <kio/jobuidelegate.h>
......@@ -42,16 +44,16 @@
#include <kcoreaddons_version.h>
#include <konq_mainwindow_interface.h>
#include <konq_main_interface.h>
#include <QApplication>
#include <QDebug>
#include <QDBusConnection>
#include <QDir>
#include <QMimeDatabase>
#include <QUrl>
#include <QStandardPaths>
#include <QCommandLineParser>
#include <QCommandLineOption>
#include <QTimer>
#if KONQ_HAVE_X11
#include <QX11Info>
......@@ -148,9 +150,6 @@ static void needDBus()
}
}
// keep in sync with konqpreloadinghandler.cpp
static const char s_preloadDBusName[] = "org.kde.konqueror.preloaded";
static QUrl filteredUrl(const QString &url)
{
KUriFilterData data;
......@@ -168,20 +167,6 @@ ClientApp::ClientApp()
{
}
void ClientApp::sendASNChange()
{
#if KONQ_HAVE_X11
if (KWindowSystem::platform() == KWindowSystem::Platform::X11) {
KStartupInfoId id;
id.initId(startup_id_str);
KStartupInfoData data;
data.addPid(0); // say there's another process for this ASN with unknown PID
data.setHostname(); // ( no need to bother to get this konqy's PID )
KStartupInfo::sendChangeXcb(QX11Info::connection(), QX11Info::appScreen(), id, data);
}
#endif
}
bool ClientApp::createNewWindow(const QUrl &url, bool newTab, bool tempFile, const QString &mimetype)
{
qDebug() << url << "mimetype=" << mimetype;
......@@ -205,71 +190,13 @@ bool ClientApp::createNewWindow(const QUrl &url, bool newTab, bool tempFile, con
}
needDBus();
QDBusConnection dbus = QDBusConnection::sessionBus();
KConfig cfg(QStringLiteral("konquerorrc"));
KConfigGroup fmSettings = cfg.group("FMSettings");
if (newTab || fmSettings.readEntry("KonquerorTabforExternalURL", false)) {
QString foundApp;
QDBusObjectPath foundObj;
QDBusReply<QStringList> reply = dbus.interface()->registeredServiceNames();
if (reply.isValid()) {
const QStringList allServices = reply;
for (QStringList::const_iterator it = allServices.begin(), end = allServices.end(); it != end; ++it) {
const QString service = *it;
if (service.startsWith(QLatin1String("org.kde.konqueror"))) {
org::kde::Konqueror::Main konq(service, QStringLiteral("/KonqMain"), dbus);
QDBusReply<QDBusObjectPath> windowReply = konq.windowForTab();
if (windowReply.isValid()) {
QDBusObjectPath path = windowReply;
// "/" is the indicator for "no object found", since we can't use an empty path
if (path.path() != QLatin1String("/")) {
foundApp = service;
foundObj = path;
}
}
}
}
}
if (!foundApp.isEmpty()) {
org::kde::Konqueror::MainWindow konqWindow(foundApp, foundObj.path(), dbus);
QDBusReply<void> newTabReply = konqWindow.newTabASNWithMimeType(url.url(), mimetype, startup_id_str, tempFile);
if (newTabReply.isValid()) {
sendASNChange();
return true;
}
}
}
const QString appId = QString::fromLatin1(s_preloadDBusName);
org::kde::Konqueror::Main konq(appId, QStringLiteral("/KonqMain"), dbus);
QDBusReply<QDBusObjectPath> reply = konq.createNewWindow(url.url(), mimetype, startup_id_str, tempFile);
if (reply.isValid()) {
sendASNChange();
} else {
// pass kfmclient's startup id to konqueror using kshell
KStartupInfoId id;
id.initId(startup_id_str);
id.setupStartupEnv();
QStringList args;
args << QStringLiteral("konqueror");
if (!mimetype.isEmpty()) {
args << QStringLiteral("--mimetype") << mimetype;
}
if (tempFile) {
args << QStringLiteral("-tempfile");
}
args << url.url();
#ifdef Q_OS_WIN
const int pid = KProcess::startDetached(QLatin1String("kwrapper5"), args);
#else
const int pid = KProcess::startDetached(QStringLiteral("kshell5"), args);
#endif
KStartupInfo::resetStartupEnv();
qDebug() << "ClientApp::createNewWindow KProcess started, pid=" << pid;
}
return true;
KonqClientRequest req;
req.setUrl(url);
req.setNewTab(newTab);
req.setTempFile(tempFile);
req.setMimeType(mimetype);
return req.openUrl();
}
bool ClientApp::openProfile(const QString &profileName, const QUrl &url, const QString &mimetype)
......@@ -308,9 +235,6 @@ bool ClientApp::doIt(const QCommandLineParser &parser)
}
QString command = args.at(0);
// read ASN env. variable
startup_id_str = KStartupInfo::currentStartupIdEnv().id();
if (command == QLatin1String("openURL") || command == QLatin1String("newTab")) {
checkArgumentCount(argc, 1, 3);
const bool tempFile = parser.isSet("tempfile");
......@@ -354,7 +278,7 @@ void ClientApp::slotResult(KJob *job)
{
if (job->error() && m_interactive) {
KJobWidgets::setWindow(job, 0);
static_cast<KIO::Job *>(job)->ui()->showErrorMessage();
job->uiDelegate()->showErrorMessage();
}
const bool ok = !job->error();
qApp->exit(ok ? 0 : 1);
......
......@@ -46,9 +46,6 @@ private Q_SLOTS:
void delayedQuit();
private:
void sendASNChange();
QByteArray startup_id_str;
bool m_interactive = true;
};
......
#include "konqclientrequest.h"
#include <config-konqueror.h> // KONQ_HAVE_X11
#include <konq_main_interface.h>
#include <konq_mainwindow_interface.h>
#include <QDBusConnection>
#include <QDBusConnectionInterface>
#include <QDBusObjectPath>
#include <QDBusReply>
#include <QProcess>
#include <QUrl>
#if KONQ_HAVE_X11
#include <QX11Info>
#endif
#include <KConfig>
#include <KConfigGroup>
#include <KStartupInfo>
#include <KWindowSystem>
// keep in sync with konqpreloadinghandler.cpp
static const char s_preloadDBusName[] = "org.kde.konqueror.preloaded";
class KonqClientRequestPrivate
{
public:
void sendASNChange();
QUrl url;
bool newTab = false;
bool tempFile = false;
QString mimeType;
QByteArray startup_id_str;
};
KonqClientRequest::KonqClientRequest()
: d(new KonqClientRequestPrivate)
{
// read ASN env. variable
d->startup_id_str = KStartupInfo::currentStartupIdEnv().id();
}
KonqClientRequest::~KonqClientRequest()
{
}
void KonqClientRequest::setUrl(const QUrl& url)
{
d->url = url;
}
void KonqClientRequest::setNewTab(bool newTab)
{
d->newTab = newTab;
}
void KonqClientRequest::setTempFile(bool tempFile)
{
d->tempFile = tempFile;
}
void KonqClientRequest::setMimeType(const QString &mimeType)
{
d->mimeType = mimeType;
}
void KonqClientRequestPrivate::sendASNChange()
{
#if KONQ_HAVE_X11
if (KWindowSystem::platform() == KWindowSystem::Platform::X11) {
KStartupInfoId id;
id.initId(startup_id_str);
KStartupInfoData data;
data.addPid(0); // say there's another process for this ASN with unknown PID
data.setHostname(); // ( no need to bother to get this konqy's PID )
KStartupInfo::sendChangeXcb(QX11Info::connection(), QX11Info::appScreen(), id, data);
}
#endif
}
bool KonqClientRequest::openUrl()
{
QDBusConnection dbus = QDBusConnection::sessionBus();
KConfig cfg(QStringLiteral("konquerorrc"));
KConfigGroup fmSettings = cfg.group("FMSettings");
if (d->newTab || fmSettings.readEntry("KonquerorTabforExternalURL", false)) {
QString foundApp;
QDBusObjectPath foundObj;
QDBusReply<QStringList> reply = dbus.interface()->registeredServiceNames();
if (reply.isValid()) {
const QStringList allServices = reply;
for (QStringList::const_iterator it = allServices.begin(), end = allServices.end(); it != end; ++it) {
const QString service = *it;
if (service.startsWith(QLatin1String("org.kde.konqueror"))) {
org::kde::Konqueror::Main konq(service, QStringLiteral("/KonqMain"), dbus);
QDBusReply<QDBusObjectPath> windowReply = konq.windowForTab();
if (windowReply.isValid()) {
QDBusObjectPath path = windowReply;
// "/" is the indicator for "no object found", since we can't use an empty path
if (path.path() != QLatin1String("/")) {
foundApp = service;
foundObj = path;
}
}
}
}
}
if (!foundApp.isEmpty()) {
org::kde::Konqueror::MainWindow konqWindow(foundApp, foundObj.path(), dbus);
QDBusReply<void> newTabReply = konqWindow.newTabASNWithMimeType(d->url.toString(), d->mimeType, d->startup_id_str, d->tempFile);
if (newTabReply.isValid()) {
d->sendASNChange();
return true;
}
}
}
const QString appId = QString::fromLatin1(s_preloadDBusName);
org::kde::Konqueror::Main konq(appId, QStringLiteral("/KonqMain"), dbus);
QDBusReply<QDBusObjectPath> reply = konq.createNewWindow(d->url.toString(), d->mimeType, d->startup_id_str, d->tempFile);
if (reply.isValid()) {
d->sendASNChange();
return true;
} else {
// pass kfmclient's startup id to konqueror using kshell
KStartupInfoId id;
id.initId(d->startup_id_str);
id.setupStartupEnv();
QStringList args;
args << QStringLiteral("konqueror");
if (!d->mimeType.isEmpty()) {
args << QStringLiteral("--mimetype") << d->mimeType;
}
if (d->tempFile) {
args << QStringLiteral("-tempfile");
}
args << d->url.toEncoded();
qint64 pid;
#ifdef Q_OS_WIN
const bool ok = QProcess::startDetached(QStringLiteral("kwrapper5"), args, QString(), &pid);
#else
const bool ok = QProcess::startDetached(QStringLiteral("kshell5"), args, QString(), &pid);
#endif
KStartupInfo::resetStartupEnv();
if (ok) {
qDebug() << "Konqueror started, pid=" << pid;
} else {
qWarning() << "Error starting konqueror";
}
return ok;
}
}
/* This file is part of the KDE project
Copyright (C) 2017 David Faure <faure@kde.org>
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public
License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Library General Public License for more details.
You should have received a copy of the GNU Library General Public License
along with this library; see the file COPYING.LIB. If not, write to
the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
Boston, MA 02110-1301, USA.
*/
#ifndef KONQ_CLIENT_REQUEST_H
#define KONQ_CLIENT_REQUEST_H
#include <QScopedPointer>
class KonqClientRequestPrivate;
class QUrl;
/**
* KonqClientRequest talks to a running Konqueror process, or starts a new one,
* in order to create a new window or tab for a URL.
*
* Usage: each instance of KonqClientRequest is a separate request.
*/
class KonqClientRequest
{
public:
/**
* Creates a KonqClientRequest instance
*/
KonqClientRequest();
/**
* Destroys this KonqClientRequest instance
*/
~KonqClientRequest();
/**
* Sets the URL to open (mandatory)
*/
void setUrl(const QUrl& url);
/**
* Sets whether to open the URL in a new tab (optional, defaults to false)
*/
void setNewTab(bool newTab);
/**
* Sets whether the URL is a temp file that should be deleted after usage (optional, defaults to false)
*/
void setTempFile(bool tempFile);
/**
* Sets the MIME type of the URL (optional)
*/
void setMimeType(const QString &mimeType);
/**
* This is the main method, call it to trigger the opening of the URL,
* once you have called all the relevant setters.
*/
bool openUrl();
private:
Q_DISABLE_COPY(KonqClientRequest)
QScopedPointer<KonqClientRequestPrivate> d;
};
#endif
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment