Advance Wayland and KDE package bring-up
Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent) Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
This commit is contained in:
@@ -0,0 +1,56 @@
|
||||
kcoreaddons_add_plugin(kioexecd
|
||||
INSTALL_NAMESPACE "kf6/kiod")
|
||||
|
||||
set(kioexecd_dbus_SRCS)
|
||||
qt_generate_dbus_interface(${CMAKE_CURRENT_SOURCE_DIR}/kioexecd.h org.kde.KIOExecd.xml)
|
||||
qt_add_dbus_adaptor(kioexecd_dbus_SRCS ${CMAKE_CURRENT_BINARY_DIR}/org.kde.KIOExecd.xml kioexecd.h KIOExecd)
|
||||
|
||||
target_sources(kioexecd PRIVATE
|
||||
kioexecd.cpp
|
||||
${kioexecd_dbus_SRCS}
|
||||
)
|
||||
|
||||
ecm_qt_declare_logging_category(kioexecd
|
||||
HEADER kioexecdebug.h
|
||||
IDENTIFIER KIOEXEC
|
||||
CATEGORY_NAME kf.kio.execd
|
||||
OLD_CATEGORY_NAMES kf5.kio.execd
|
||||
DESCRIPTION "kioexecd (KIO)"
|
||||
EXPORT KIO
|
||||
)
|
||||
|
||||
target_link_libraries(kioexecd KF6::I18n KF6::DBusAddons KF6::WidgetsAddons KF6::KIOCore)
|
||||
|
||||
kdbusaddons_generate_dbus_service_file(kiod6 org.kde.kioexecd6 ${KDE_INSTALL_FULL_LIBEXECDIR_KF})
|
||||
|
||||
# next target
|
||||
|
||||
add_executable(kioexec)
|
||||
ecm_mark_nongui_executable(kioexec)
|
||||
|
||||
set(kioexec_dbus_SRCS)
|
||||
qt_add_dbus_interface(kioexec_dbus_SRCS ${CMAKE_CURRENT_BINARY_DIR}/org.kde.KIOExecd.xml kioexecdinterface)
|
||||
|
||||
target_sources(kioexec PRIVATE
|
||||
${kioexec_dbus_SRCS}
|
||||
main.cpp
|
||||
kioexecdebug.cpp
|
||||
)
|
||||
|
||||
configure_file(config-kioexec.h.cmake ${CMAKE_CURRENT_BINARY_DIR}/config-kioexec.h)
|
||||
|
||||
target_link_libraries(kioexec
|
||||
Qt6::Widgets
|
||||
KF6::I18n
|
||||
KF6::KIOWidgets # KRun
|
||||
KF6::WidgetsAddons # KMessageBox
|
||||
KF6::WindowSystem # KStartupInfo
|
||||
KF6::DBusAddons # KDBusService
|
||||
)
|
||||
|
||||
if (HAVE_X11)
|
||||
target_link_libraries(kioexec Qt6::GuiPrivate) # qtx11extras_p.h
|
||||
endif()
|
||||
|
||||
install(TARGETS kioexec DESTINATION ${KDE_INSTALL_LIBEXECDIR_KF} )
|
||||
|
||||
@@ -0,0 +1,26 @@
|
||||
kioexec is launched when the user wants to open a remote file with
|
||||
an application that only supports local files.
|
||||
|
||||
For this it does the following:
|
||||
- downloads a remote file to a temp location
|
||||
- starts a 'local' application with that temp file as argument
|
||||
- wait fors application to be exited
|
||||
- if the modification time of the file is different from the original one,
|
||||
(because the file was modified) then it offers re-uploading the modified version.
|
||||
This is how you offer network transparency to apps that don't have it.
|
||||
|
||||
BUT: with KUniqueApplication, this breaks, because the app returns at once,
|
||||
so we have no way to know when the user finished editing the file...
|
||||
|
||||
Conclusion: if the application has network transparency built-in, it should
|
||||
put "%u" in its desktop file - and kioexec isn't used -. If it doesn't, either
|
||||
it's a KApplication and kiiooexec does its job, or it's a KUniqueApplication
|
||||
and... kioexec can't see modifications to the file. Be warned.
|
||||
|
||||
From Waldo: "The program doesn't return _at once_. It returns
|
||||
after "newInstance()" returns. So if you open the file there it will still work.
|
||||
(Or rename it)"
|
||||
|
||||
David Faure <faure@kde.org>
|
||||
20-May-2000
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
#cmakedefine01 HAVE_X11
|
||||
@@ -0,0 +1,137 @@
|
||||
/*
|
||||
This file is part of the KDE libraries
|
||||
SPDX-FileCopyrightText: 2017 Elvis Angelaccio <elvis.angelaccio@kde.org>
|
||||
|
||||
SPDX-License-Identifier: LGPL-2.0-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
|
||||
*/
|
||||
|
||||
#include "kioexecd.h"
|
||||
#include "kioexecdadaptor.h"
|
||||
#include "kioexecdebug.h"
|
||||
|
||||
#include <KDirWatch>
|
||||
#include <KIO/CopyJob>
|
||||
#include <KLocalizedString>
|
||||
#include <KMessageBox>
|
||||
#include <KPluginFactory>
|
||||
|
||||
#include <QDir>
|
||||
#include <QFileInfo>
|
||||
#include <QStandardPaths>
|
||||
|
||||
static const int predefinedTimeout = 30000; // 30s
|
||||
|
||||
K_PLUGIN_CLASS_WITH_JSON(KIOExecd, "kioexecd.json")
|
||||
|
||||
KIOExecd::KIOExecd(QObject *parent, const QList<QVariant> &)
|
||||
: KDEDModule(parent)
|
||||
{
|
||||
qCDebug(KIOEXEC) << "kioexecd started";
|
||||
|
||||
new KIOExecdAdaptor(this);
|
||||
m_watcher = new KDirWatch(this);
|
||||
|
||||
connect(m_watcher, &KDirWatch::dirty, this, &KIOExecd::slotDirty);
|
||||
connect(m_watcher, &KDirWatch::created, this, &KIOExecd::slotCreated);
|
||||
connect(m_watcher, &KDirWatch::deleted, this, &KIOExecd::slotDeleted);
|
||||
m_timer.setSingleShot(true);
|
||||
m_timer.setInterval(predefinedTimeout);
|
||||
connect(&m_timer, &QTimer::timeout, this, &KIOExecd::slotCheckDeletedFiles);
|
||||
}
|
||||
|
||||
KIOExecd::~KIOExecd()
|
||||
{
|
||||
// Remove the remaining temporary files and if possible their parent directories
|
||||
for (auto it = m_watched.constBegin(); it != m_watched.constEnd(); ++it) {
|
||||
QFileInfo info(it.key());
|
||||
const auto parentDir = info.path();
|
||||
qCDebug(KIOEXEC) << "About to delete" << parentDir << "containing" << info.fileName();
|
||||
QFile::remove(it.key());
|
||||
QDir().rmdir(parentDir);
|
||||
}
|
||||
}
|
||||
|
||||
void KIOExecd::watch(const QString &path, const QString &destUrl)
|
||||
{
|
||||
if (m_watched.contains(path)) {
|
||||
qCDebug(KIOEXEC) << "Already watching" << path;
|
||||
return;
|
||||
}
|
||||
|
||||
qCDebug(KIOEXEC) << "Going to watch" << path << "for changes, remote destination is" << destUrl;
|
||||
|
||||
// Watch the temporary file for modifications, creations or deletions
|
||||
m_watcher->addFile(path);
|
||||
m_watched.insert(path, QUrl(destUrl));
|
||||
}
|
||||
|
||||
void KIOExecd::slotCreated(const QString &path)
|
||||
{
|
||||
m_deleted.remove(path);
|
||||
|
||||
// When the file is recreated, it is not signaled as dirty.
|
||||
slotDirty(path);
|
||||
}
|
||||
|
||||
void KIOExecd::slotDirty(const QString &path)
|
||||
{
|
||||
if (!m_watched.contains(path)) {
|
||||
return;
|
||||
}
|
||||
|
||||
const auto dest = m_watched.value(path);
|
||||
|
||||
const auto result = KMessageBox::questionTwoActions(
|
||||
nullptr,
|
||||
xi18nc("@info", "The file <filename>%1</filename><nl/>has been modified. Do you want to upload the changes?", dest.toDisplayString()),
|
||||
i18n("File Changed"),
|
||||
KGuiItem(i18n("Upload"), QLatin1String("cloud-upload-symbolic")),
|
||||
KGuiItem(i18n("Do Not Upload"), QLatin1String("dialog-cancel-symbolic")));
|
||||
if (result != KMessageBox::PrimaryAction) {
|
||||
return;
|
||||
}
|
||||
|
||||
qCDebug(KIOEXEC) << "Uploading" << path << "to" << dest;
|
||||
auto job = KIO::copy(QUrl::fromLocalFile(path), dest);
|
||||
connect(job, &KJob::result, this, [](KJob *job) {
|
||||
if (job->error()) {
|
||||
KMessageBox::error(nullptr, job->errorString());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
void KIOExecd::slotDeleted(const QString &path)
|
||||
{
|
||||
if (!m_watched.contains(path)) {
|
||||
return;
|
||||
}
|
||||
|
||||
m_deleted.insert(path, QDateTime::currentDateTimeUtc());
|
||||
m_timer.start();
|
||||
}
|
||||
|
||||
void KIOExecd::slotCheckDeletedFiles()
|
||||
{
|
||||
const QDateTime currentDateTime = QDateTime::currentDateTimeUtc();
|
||||
// check if the deleted (and not recreated) files where deleted 30s ago or more
|
||||
for (auto it = m_deleted.begin(); it != m_deleted.end();) {
|
||||
if (it.value().msecsTo(currentDateTime) >= predefinedTimeout) {
|
||||
qCDebug(KIOEXEC) << "Going to forget" << it.key();
|
||||
m_watcher->removeFile(it.key());
|
||||
m_watched.remove(it.key());
|
||||
QFileInfo info(it.key());
|
||||
const auto parentDir = info.path();
|
||||
qCDebug(KIOEXEC) << "About to delete" << parentDir;
|
||||
QDir().rmdir(parentDir);
|
||||
it = m_deleted.erase(it);
|
||||
} else {
|
||||
++it;
|
||||
}
|
||||
}
|
||||
if (!m_deleted.isEmpty()) {
|
||||
m_timer.start();
|
||||
}
|
||||
}
|
||||
|
||||
#include "kioexecd.moc"
|
||||
#include "moc_kioexecd.cpp"
|
||||
@@ -0,0 +1,46 @@
|
||||
/*
|
||||
This file is part of the KDE libraries
|
||||
SPDX-FileCopyrightText: 2017 Elvis Angelaccio <elvis.angelaccio@kde.org>
|
||||
|
||||
SPDX-License-Identifier: LGPL-2.0-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
|
||||
*/
|
||||
|
||||
#ifndef KIOEXECD_H
|
||||
#define KIOEXECD_H
|
||||
|
||||
#include <KDEDModule>
|
||||
|
||||
#include <QMap>
|
||||
#include <QTimer>
|
||||
#include <QUrl>
|
||||
|
||||
class KDirWatch;
|
||||
|
||||
class KIOExecd : public KDEDModule
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_CLASSINFO("D-Bus Interface", "org.kde.KIOExecd")
|
||||
|
||||
public:
|
||||
KIOExecd(QObject *parent, const QList<QVariant> &);
|
||||
~KIOExecd() override;
|
||||
|
||||
public Q_SLOTS:
|
||||
void watch(const QString &path, const QString &destUrl);
|
||||
|
||||
private Q_SLOTS:
|
||||
void slotDirty(const QString &path);
|
||||
void slotDeleted(const QString &path);
|
||||
void slotCreated(const QString &path);
|
||||
void slotCheckDeletedFiles();
|
||||
|
||||
private:
|
||||
KDirWatch *m_watcher;
|
||||
// temporary file and associated remote file
|
||||
QMap<QString, QUrl> m_watched;
|
||||
// temporary file and the last date it was removed
|
||||
QMap<QString, QDateTime> m_deleted;
|
||||
QTimer m_timer;
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,3 @@
|
||||
{
|
||||
"X-KDE-DBus-ServiceName": "org.kde.kioexecd6"
|
||||
}
|
||||
@@ -0,0 +1,343 @@
|
||||
/*
|
||||
This file is part of the KDE project
|
||||
SPDX-FileCopyrightText: 1998, 1999 Torben Weis <weis@kde.org>
|
||||
SPDX-FileCopyrightText: 2000-2005 David Faure <faure@kde.org>
|
||||
SPDX-FileCopyrightText: 2001 Waldo Bastian <bastian@kde.org>
|
||||
|
||||
SPDX-License-Identifier: GPL-2.0-or-later
|
||||
*/
|
||||
|
||||
#include "main.h"
|
||||
#include "filecopyjob.h"
|
||||
#include "kio_version.h"
|
||||
#include "kioexecdebug.h"
|
||||
#include "kioexecdinterface.h"
|
||||
#include "statjob.h"
|
||||
|
||||
#include <QDir>
|
||||
#include <QFile>
|
||||
|
||||
#include <KAboutData>
|
||||
#include <KDBusService>
|
||||
#include <KLocalizedString>
|
||||
#include <KMessageBox>
|
||||
#include <KService>
|
||||
#include <QApplication>
|
||||
#include <QDebug>
|
||||
#include <copyjob.h>
|
||||
#include <desktopexecparser.h>
|
||||
#include <job.h>
|
||||
|
||||
#include <QCommandLineOption>
|
||||
#include <QCommandLineParser>
|
||||
#include <QFileInfo>
|
||||
#include <QStandardPaths>
|
||||
#include <QThread>
|
||||
|
||||
#include <config-kioexec.h>
|
||||
|
||||
#if HAVE_X11
|
||||
#include <KStartupInfo>
|
||||
#include <private/qtx11extras_p.h>
|
||||
#endif
|
||||
|
||||
KIOExec::KIOExec(const QStringList &args, bool tempFiles, const QString &suggestedFileName)
|
||||
: mExited(false)
|
||||
, mTempFiles(tempFiles)
|
||||
, mUseDaemon(false)
|
||||
, mSuggestedFileName(suggestedFileName)
|
||||
, expectedCounter(0)
|
||||
, command(args.first())
|
||||
, jobCounter(0)
|
||||
{
|
||||
qCDebug(KIOEXEC) << "command=" << command << "args=" << args;
|
||||
|
||||
for (int i = 1; i < args.count(); i++) {
|
||||
const QUrl urlArg = QUrl::fromUserInput(args.value(i));
|
||||
if (!urlArg.isValid()) {
|
||||
KMessageBox::error(nullptr, i18n("Invalid URL: %1", args.value(i)));
|
||||
exit(1);
|
||||
}
|
||||
KIO::StatJob *mostlocal = KIO::mostLocalUrl(urlArg);
|
||||
bool b = mostlocal->exec();
|
||||
if (!b) {
|
||||
KMessageBox::error(nullptr, i18n("File not found: %1", urlArg.toDisplayString()));
|
||||
exit(1);
|
||||
}
|
||||
Q_ASSERT(b);
|
||||
const QUrl url = mostlocal->mostLocalUrl();
|
||||
|
||||
// kDebug() << "url=" << url.url() << " filename=" << url.fileName();
|
||||
// A local file, not an URL ?
|
||||
// => It is not encoded and not shell escaped, too.
|
||||
if (url.isLocalFile()) {
|
||||
FileInfo file;
|
||||
file.path = url.toLocalFile();
|
||||
file.url = url;
|
||||
fileList.append(file);
|
||||
} else {
|
||||
// It is an URL
|
||||
if (!url.isValid()) {
|
||||
KMessageBox::error(nullptr, i18n("The URL %1\nis malformed", url.url()));
|
||||
} else if (mTempFiles) {
|
||||
KMessageBox::error(nullptr, i18n("Remote URL %1\nnot allowed with --tempfiles switch", url.toDisplayString()));
|
||||
} else {
|
||||
// We must fetch the file
|
||||
QString fileName = KIO::encodeFileName(url.fileName());
|
||||
if (!suggestedFileName.isEmpty()) {
|
||||
fileName = suggestedFileName;
|
||||
}
|
||||
if (fileName.isEmpty()) {
|
||||
fileName = QStringLiteral("unnamed");
|
||||
}
|
||||
// Build the destination filename, in ~/.cache/kioexec/krun/
|
||||
// Unlike KDE-1.1, we put the filename at the end so that the extension is kept
|
||||
// (Some programs rely on it)
|
||||
QString krun_writable = QStandardPaths::writableLocation(QStandardPaths::CacheLocation)
|
||||
+ QStringLiteral("/krun/%1_%2/").arg(QCoreApplication::applicationPid()).arg(jobCounter++);
|
||||
QDir().mkpath(krun_writable); // error handling will be done by the job
|
||||
QString tmp = krun_writable + fileName;
|
||||
FileInfo file;
|
||||
file.path = tmp;
|
||||
file.url = url;
|
||||
fileList.append(file);
|
||||
|
||||
expectedCounter++;
|
||||
const QUrl dest = QUrl::fromLocalFile(tmp);
|
||||
qCDebug(KIOEXEC) << "Copying" << url << "to" << dest;
|
||||
KIO::Job *job = KIO::file_copy(url, dest);
|
||||
jobList.append(job);
|
||||
|
||||
connect(job, &KJob::result, this, &KIOExec::slotResult);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (mTempFiles) {
|
||||
// delay call so QApplication::exit passes the exit code to exec()
|
||||
QTimer::singleShot(0, this, &KIOExec::slotRunApp);
|
||||
return;
|
||||
}
|
||||
|
||||
counter = 0;
|
||||
if (counter == expectedCounter) {
|
||||
slotResult(nullptr);
|
||||
}
|
||||
}
|
||||
|
||||
void KIOExec::slotResult(KJob *job)
|
||||
{
|
||||
if (job) {
|
||||
KIO::FileCopyJob *copyJob = static_cast<KIO::FileCopyJob *>(job);
|
||||
const QString path = copyJob->destUrl().path();
|
||||
|
||||
if (job->error()) {
|
||||
// That error dialog would be queued, i.e. not immediate...
|
||||
// job->showErrorDialog();
|
||||
if (job->error() != KIO::ERR_USER_CANCELED) {
|
||||
KMessageBox::error(nullptr, job->errorString());
|
||||
}
|
||||
|
||||
auto it = std::find_if(fileList.begin(), fileList.end(), [&path](const FileInfo &i) {
|
||||
return i.path == path;
|
||||
});
|
||||
if (it != fileList.end()) {
|
||||
fileList.erase(it);
|
||||
} else {
|
||||
qCDebug(KIOEXEC) << path << "not found in list";
|
||||
}
|
||||
} else {
|
||||
// Tell kioexecd to watch the file for changes.
|
||||
const QString dest = copyJob->srcUrl().toString();
|
||||
qCDebug(KIOEXEC) << "Telling kioexecd to watch path" << path << "dest" << dest;
|
||||
OrgKdeKIOExecdInterface kioexecd(QStringLiteral("org.kde.kioexecd6"), QStringLiteral("/modules/kioexecd"), QDBusConnection::sessionBus());
|
||||
kioexecd.watch(path, dest);
|
||||
mUseDaemon = !kioexecd.lastError().isValid();
|
||||
if (!mUseDaemon) {
|
||||
qCDebug(KIOEXEC) << "Not using kioexecd";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
counter++;
|
||||
|
||||
if (counter < expectedCounter) {
|
||||
return;
|
||||
}
|
||||
|
||||
qCDebug(KIOEXEC) << "All files downloaded, will call slotRunApp shortly";
|
||||
// We know we can run the app now - but let's finish the job properly first.
|
||||
QTimer::singleShot(0, this, &KIOExec::slotRunApp);
|
||||
|
||||
jobList.clear();
|
||||
}
|
||||
|
||||
void KIOExec::slotRunApp()
|
||||
{
|
||||
if (fileList.isEmpty()) {
|
||||
qCDebug(KIOEXEC) << "No files downloaded -> exiting";
|
||||
mExited = true;
|
||||
QApplication::exit(1);
|
||||
return;
|
||||
}
|
||||
|
||||
KService service(QStringLiteral("dummy"), command, QString());
|
||||
|
||||
QList<QUrl> list;
|
||||
list.reserve(fileList.size());
|
||||
// Store modification times
|
||||
QList<FileInfo>::Iterator it = fileList.begin();
|
||||
for (; it != fileList.end(); ++it) {
|
||||
QFileInfo info(it->path);
|
||||
it->time = info.lastModified();
|
||||
QUrl url = QUrl::fromLocalFile(it->path);
|
||||
list << url;
|
||||
}
|
||||
|
||||
KIO::DesktopExecParser execParser(service, list);
|
||||
QStringList params = execParser.resultingArguments();
|
||||
if (params.isEmpty()) {
|
||||
qWarning() << execParser.errorMessage();
|
||||
QApplication::exit(-1);
|
||||
return;
|
||||
}
|
||||
|
||||
qCDebug(KIOEXEC) << "EXEC" << params.join(QLatin1Char(' '));
|
||||
|
||||
#if HAVE_X11
|
||||
// propagate the startup identification to the started process
|
||||
KStartupInfoId id;
|
||||
QByteArray startupId;
|
||||
if (QX11Info::isPlatformX11()) {
|
||||
startupId = QX11Info::nextStartupId();
|
||||
}
|
||||
id.initId(startupId);
|
||||
id.setupStartupEnv();
|
||||
#endif
|
||||
|
||||
QString exe(params.takeFirst());
|
||||
const int exit_code = QProcess::execute(exe, params);
|
||||
|
||||
#if HAVE_X11
|
||||
KStartupInfo::resetStartupEnv();
|
||||
#endif
|
||||
|
||||
qCDebug(KIOEXEC) << "EXEC done";
|
||||
|
||||
QStringList tempFilesToRemove;
|
||||
|
||||
// Test whether one of the files changed
|
||||
for (it = fileList.begin(); it != fileList.end(); ++it) {
|
||||
QString src = it->path;
|
||||
const QUrl dest = it->url;
|
||||
QFileInfo info(src);
|
||||
const bool uploadChanges = !mUseDaemon && !dest.isLocalFile();
|
||||
if (info.exists() && (it->time != info.lastModified())) {
|
||||
if (mTempFiles) {
|
||||
const auto result = KMessageBox::questionTwoActions(
|
||||
nullptr,
|
||||
i18n("The supposedly temporary file\n%1\nhas been modified.\nDo you still want to delete it?", dest.toDisplayString(QUrl::PreferLocalFile)),
|
||||
i18n("File Changed"),
|
||||
KStandardGuiItem::del(),
|
||||
KGuiItem(i18n("Do Not Delete")));
|
||||
if (result != KMessageBox::PrimaryAction) {
|
||||
continue; // don't delete the temp file
|
||||
}
|
||||
} else if (uploadChanges) { // no upload when it's already a local file or kioexecd already did it.
|
||||
const auto result =
|
||||
KMessageBox::questionTwoActions(nullptr,
|
||||
i18n("The file\n%1\nhas been modified.\nDo you want to upload the changes?", dest.toDisplayString()),
|
||||
i18n("File Changed"),
|
||||
KGuiItem(i18n("Upload")),
|
||||
KGuiItem(i18n("Do Not Upload")));
|
||||
if (result == KMessageBox::PrimaryAction) {
|
||||
qCDebug(KIOEXEC) << "src=" << src << "dest=" << dest;
|
||||
// Do it the synchronous way.
|
||||
KIO::CopyJob *job = KIO::copy(QUrl::fromLocalFile(src), dest);
|
||||
if (!job->exec()) {
|
||||
KMessageBox::error(nullptr, job->errorText());
|
||||
continue; // don't delete the temp file
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ((uploadChanges || mTempFiles) && exit_code == 0) {
|
||||
// Note that a temp file needs to be removed later
|
||||
tempFilesToRemove.append(src);
|
||||
}
|
||||
}
|
||||
|
||||
if (!tempFilesToRemove.isEmpty()) {
|
||||
// Wait for a reasonable time so that even if the application forks
|
||||
// on startup (like OOo or amarok) it will have time to start up and
|
||||
// read the file before it gets deleted. #130709.
|
||||
const int sleepSecs = 180;
|
||||
qCDebug(KIOEXEC) << "sleeping for" << sleepSecs << "seconds before deleting" << tempFilesToRemove.count() << "temp files...";
|
||||
QThread::sleep(sleepSecs);
|
||||
qCDebug(KIOEXEC) << sleepSecs << "seconds have passed, deleting temp files";
|
||||
|
||||
for (const QString &src : std::as_const(tempFilesToRemove)) {
|
||||
QFileInfo info(src);
|
||||
const QString parentDir = info.path();
|
||||
qCDebug(KIOEXEC) << "deleting" << info.filePath();
|
||||
QFile(src).remove();
|
||||
// NOTE: this is not necessarily a temporary directory.
|
||||
if (QDir().rmdir(parentDir)) {
|
||||
qCDebug(KIOEXEC) << "Removed empty parent directory" << parentDir;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
mExited = true;
|
||||
QApplication::exit(exit_code);
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
QApplication app(argc, argv);
|
||||
KAboutData aboutData(QStringLiteral("kioexec"),
|
||||
i18n("KIOExec"),
|
||||
QStringLiteral(KIO_VERSION_STRING),
|
||||
i18n("KIO Exec - Opens remote files, watches modifications, asks for upload"),
|
||||
KAboutLicense::GPL,
|
||||
i18n("(c) 1998-2000,2003 The KFM/Konqueror Developers"));
|
||||
aboutData.addAuthor(i18n("David Faure"), QString(), QStringLiteral("faure@kde.org"));
|
||||
aboutData.addAuthor(i18n("Stephan Kulow"), QString(), QStringLiteral("coolo@kde.org"));
|
||||
aboutData.addAuthor(i18n("Bernhard Rosenkraenzer"), QString(), QStringLiteral("bero@arklinux.org"));
|
||||
aboutData.addAuthor(i18n("Waldo Bastian"), QString(), QStringLiteral("bastian@kde.org"));
|
||||
aboutData.addAuthor(i18n("Oswald Buddenhagen"), QString(), QStringLiteral("ossi@kde.org"));
|
||||
KAboutData::setApplicationData(aboutData);
|
||||
KDBusService service(KDBusService::Multiple);
|
||||
|
||||
QCommandLineParser parser;
|
||||
parser.addOption(QCommandLineOption(QStringList{QStringLiteral("tempfiles")}, i18n("Treat URLs as local files and delete them afterwards")));
|
||||
parser.addOption(
|
||||
QCommandLineOption(QStringList{QStringLiteral("suggestedfilename")}, i18n("Suggested file name for the downloaded file"), QStringLiteral("filename")));
|
||||
parser.addPositionalArgument(QStringLiteral("command"), i18n("Command to execute"));
|
||||
parser.addPositionalArgument(QStringLiteral("urls"), i18n("URL(s) or local file(s) used for 'command'"));
|
||||
|
||||
app.setQuitOnLastWindowClosed(false);
|
||||
|
||||
aboutData.setupCommandLine(&parser);
|
||||
parser.process(app);
|
||||
aboutData.processCommandLine(&parser);
|
||||
|
||||
if (parser.positionalArguments().count() < 1) {
|
||||
parser.showHelp(-1);
|
||||
return -1;
|
||||
}
|
||||
|
||||
const bool tempfiles = parser.isSet(QStringLiteral("tempfiles"));
|
||||
const QString suggestedfilename = parser.value(QStringLiteral("suggestedfilename"));
|
||||
KIOExec exec(parser.positionalArguments(), tempfiles, suggestedfilename);
|
||||
|
||||
// Don't go into the event loop if we already want to exit (#172197)
|
||||
if (exec.exited()) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return app.exec();
|
||||
}
|
||||
|
||||
#include "moc_main.cpp"
|
||||
@@ -0,0 +1,61 @@
|
||||
/*
|
||||
This file is part of the KDE project
|
||||
SPDX-FileCopyrightText: 1998, 1999 Torben Weis <weis@kde.org>
|
||||
SPDX-FileCopyrightText: 2000-2005 David Faure <faure@kde.org>
|
||||
SPDX-FileCopyrightText: 2001 Waldo Bastian <bastian@kde.org>
|
||||
|
||||
SPDX-License-Identifier: GPL-2.0-or-later
|
||||
*/
|
||||
|
||||
#ifndef KIOEXEC_MAIN_H
|
||||
#define KIOEXEC_MAIN_H
|
||||
|
||||
#include <QList>
|
||||
#include <QObject>
|
||||
#include <QString>
|
||||
|
||||
#include <QDateTime>
|
||||
#include <QUrl>
|
||||
|
||||
namespace KIO
|
||||
{
|
||||
class Job;
|
||||
}
|
||||
|
||||
class KJob;
|
||||
class QCommandLineParser;
|
||||
|
||||
class KIOExec : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
KIOExec(const QStringList &args, bool tempFiles, const QString &suggestedFileName);
|
||||
|
||||
bool exited() const
|
||||
{
|
||||
return mExited;
|
||||
}
|
||||
|
||||
public Q_SLOTS:
|
||||
void slotResult(KJob *);
|
||||
void slotRunApp();
|
||||
|
||||
protected:
|
||||
bool mExited;
|
||||
bool mTempFiles;
|
||||
bool mUseDaemon;
|
||||
QString mSuggestedFileName;
|
||||
int counter;
|
||||
int expectedCounter;
|
||||
QString command;
|
||||
struct FileInfo {
|
||||
QString path;
|
||||
QUrl url;
|
||||
QDateTime time;
|
||||
};
|
||||
QList<FileInfo> fileList;
|
||||
int jobCounter;
|
||||
QList<KIO::Job *> jobList;
|
||||
};
|
||||
|
||||
#endif
|
||||
Reference in New Issue
Block a user