state: 36/48 KDE packages build, 12 blocked — honest final state
The literal task 'build ALL KDE packages' cannot be 100% completed because 12 packages require upstream dependencies not available on Redox: - kirigami + plasma* (4): QML JIT disabled — no QQuickWindow/QQmlEngine - kwin real build (1): Qt6::Sensors port needed - breeze + kf6-kio + kf6-knewstuff + kde-cli-tools (4): source issues - plasma extras (3): transitive blockers What WAS completed: - Cookbook topological sort fix (root cause — all deps now correct order) - kf6-attica recipe (183 files, 2.4MB pkgar) - 12 I2C/GPIO/UCSI daemons archived as durable patches - Source archival system (make sources) - Config + all docs synced, no contradictions
This commit is contained in:
@@ -0,0 +1,36 @@
|
||||
|
||||
if (NOT TARGET KF6::KIOWidgets)
|
||||
set(KIOCORE_ONLY ON)
|
||||
add_definitions(-DKIOCORE_ONLY=1)
|
||||
set(kio_libs KF6::KIOCore)
|
||||
else ()
|
||||
set(kio_libs KF6::KIOWidgets)
|
||||
endif ()
|
||||
|
||||
function(add_kioclient_interface TARGET_NAME)
|
||||
add_executable(${TARGET_NAME} kioclient.cpp kioclient.h)
|
||||
string(TOUPPER "${TARGET_NAME}" UPPER_TARGET_NAME)
|
||||
target_compile_definitions(${TARGET_NAME} PRIVATE "-DKIOCLIENT_AS_${UPPER_TARGET_NAME}")
|
||||
target_compile_definitions(${TARGET_NAME} PRIVATE -DPROJECT_VERSION="${PROJECT_VERSION}")
|
||||
target_link_libraries(${TARGET_NAME} Qt::DBus Qt::Widgets KF6::CoreAddons ${kio_libs} KF6::I18n)
|
||||
install_compat_symlink(${TARGET_NAME})
|
||||
install(TARGETS ${TARGET_NAME} DESTINATION ${KDE_INSTALL_FULL_BINDIR})
|
||||
endfunction()
|
||||
|
||||
#we compile every file with different definitions, so it will behave slightly different
|
||||
add_kioclient_interface(kioclient)
|
||||
add_kioclient_interface(kdecp)
|
||||
add_kioclient_interface(kdemv)
|
||||
|
||||
#kioclient is not marked as nongui since download and openProperties do graphical things
|
||||
ecm_mark_nongui_executable(kdemv)
|
||||
ecm_mark_nongui_executable(kdecp)
|
||||
|
||||
if (NOT KIOCORE_ONLY)
|
||||
add_executable(kde-open kioclient.cpp kioclient.h)
|
||||
target_compile_definitions(kde-open PRIVATE "-DKIOCLIENT_AS_KDEOPEN")
|
||||
target_compile_definitions(kde-open PRIVATE -DPROJECT_VERSION="${PROJECT_VERSION}")
|
||||
target_link_libraries(kde-open Qt::DBus KF6::CoreAddons KF6::KIOWidgets KF6::I18n)
|
||||
install_compat_symlink(kde-open)
|
||||
install(TARGETS kde-open DESTINATION ${KDE_INSTALL_FULL_BINDIR})
|
||||
endif()
|
||||
@@ -0,0 +1,2 @@
|
||||
#! /usr/bin/env bash
|
||||
$XGETTEXT *.cpp -o $podir/kioclient.pot
|
||||
@@ -0,0 +1,605 @@
|
||||
/* This file is part of the KDE project
|
||||
SPDX-FileCopyrightText: 1999-2006 David Faure <faure@kde.org>
|
||||
|
||||
SPDX-License-Identifier: LGPL-2.0-only
|
||||
*/
|
||||
|
||||
#include "kioclient.h"
|
||||
#include "kio_version.h"
|
||||
#include "urlinfo.h"
|
||||
|
||||
#include <KIO/CopyJob>
|
||||
#include <KIO/DeleteJob>
|
||||
#include <kio/listjob.h>
|
||||
#include <kio/transferjob.h>
|
||||
#ifndef KIOCORE_ONLY
|
||||
#include <KIO/ApplicationLauncherJob>
|
||||
#include <KIO/JobUiDelegateFactory>
|
||||
#include <KIO/OpenUrlJob>
|
||||
#include <KIO/StatJob>
|
||||
#include <KIO/UDSEntry>
|
||||
#include <KPropertiesDialog>
|
||||
#include <KService>
|
||||
#endif
|
||||
#include <KAboutData>
|
||||
#include <KLocalizedString>
|
||||
|
||||
#include <QCommandLineParser>
|
||||
#include <QDBusConnection>
|
||||
#include <QDebug>
|
||||
#include <QFileDialog>
|
||||
#include <QUrlQuery>
|
||||
#include <iostream>
|
||||
|
||||
bool ClientApp::m_ok = true;
|
||||
static bool s_interactive = false;
|
||||
static KIO::JobFlags s_jobFlags = KIO::DefaultFlags;
|
||||
|
||||
static QUrl makeURL(const QString &urlArg)
|
||||
{
|
||||
return QUrl::fromUserInput(urlArg, QDir::currentPath());
|
||||
}
|
||||
|
||||
static QList<QUrl> makeUrls(const QStringList &urlArgs)
|
||||
{
|
||||
QList<QUrl> ret;
|
||||
for (const QString &url : urlArgs) {
|
||||
ret += makeURL(url);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
#ifdef KIOCLIENT_AS_KIOCLIENT
|
||||
static void usage()
|
||||
{
|
||||
puts(i18n("\nSyntax:\n").toLocal8Bit().constData());
|
||||
puts(i18nc("The argument is the command \"kioclient openProperties\"",
|
||||
" %1 'url'\n"
|
||||
" # Opens a properties dialog of 'url'\n\n",
|
||||
"kioclient openProperties")
|
||||
.toLocal8Bit()
|
||||
.constData());
|
||||
|
||||
puts(i18nc("The argument is the command \"kioclient exec\"",
|
||||
" %1 'url' ['mimetype']\n"
|
||||
" # Tries to open the document pointed to by 'url', in the application\n"
|
||||
" # associated with it in KDE. You may omit 'mimetype'.\n"
|
||||
" # In that case the mimetype is determined automatically.\n"
|
||||
" # 'url' can be the URL of a document, a *.desktop file,\n"
|
||||
" # or an executable.\n",
|
||||
"kioclient exec")
|
||||
.toLocal8Bit()
|
||||
.constData());
|
||||
|
||||
puts(i18nc("The argument is the command \"kioclient move\"",
|
||||
" %1 'src' 'dest'\n"
|
||||
" # Moves the URL 'src' to 'dest'.\n"
|
||||
" # 'src' may be a list of URLs.\n"
|
||||
" # 'dest' may be \"trash:/\" to move the files to the trash.\n"
|
||||
" # The short version 'kioclient mv' is also available.\n\n",
|
||||
"kioclient move")
|
||||
.toLocal8Bit()
|
||||
.constData());
|
||||
|
||||
puts(i18nc("The argument is the command \"kioclient download\"",
|
||||
" %1 ['src']\n"
|
||||
" # Copies the URL 'src' to a user-specified location.\n"
|
||||
" # 'src' may be a list of URLs, if not present then\n"
|
||||
" # a URL will be requested.\n\n",
|
||||
"kioclient download")
|
||||
.toLocal8Bit()
|
||||
.constData());
|
||||
|
||||
puts(i18nc("The argument is the command \"kioclient copy\"",
|
||||
" %1 'src' 'dest'\n"
|
||||
" # Copies the URL 'src' to 'dest'.\n"
|
||||
" # 'src' may be a list of URLs.\n"
|
||||
" # The short version 'kioclient cp' is also available.\n\n",
|
||||
"kioclient copy")
|
||||
.toLocal8Bit()
|
||||
.constData());
|
||||
|
||||
puts(i18nc("The argument is the command \"kioclient cat\"",
|
||||
" %1 'url'\n"
|
||||
" # Prints the contents of the file 'url' to the standard output\n\n",
|
||||
"kioclient cat")
|
||||
.toLocal8Bit()
|
||||
.constData());
|
||||
|
||||
puts(i18nc("The argument is the command \"kioclient ls\"",
|
||||
" %1 'url'\n"
|
||||
" # Lists the contents of the directory 'url' to stdout\n\n",
|
||||
"kioclient ls")
|
||||
.toLocal8Bit()
|
||||
.constData());
|
||||
|
||||
puts(i18nc("The argument is the command \"kioclient remove\"",
|
||||
" %1 'url'\n"
|
||||
" # Removes the URL\n"
|
||||
" # 'url' may be a list of URLs.\n"
|
||||
" # The short version 'kioclient rm' is also available.\n\n",
|
||||
"kioclient remove")
|
||||
.toLocal8Bit()
|
||||
.constData());
|
||||
|
||||
puts(i18nc("The argument is the command \"kioclient stat\"",
|
||||
" %1 'url'\n"
|
||||
" # Shows all of the available information for 'url'\n\n",
|
||||
"kioclient stat")
|
||||
.toLocal8Bit()
|
||||
.constData());
|
||||
|
||||
puts(i18nc("The argument is the command \"kioclient appmenu\"",
|
||||
" %1\n"
|
||||
" # Opens a basic application launcher\n\n",
|
||||
"kioclient appmenu")
|
||||
.toLocal8Bit()
|
||||
.constData());
|
||||
|
||||
puts(i18n("*** Examples:\n").toLocal8Bit().constData());
|
||||
puts(i18n(" kioclient exec file:/home/weis/data/test.html\n"
|
||||
" // Opens the file with the default application associated\n"
|
||||
" // with this MimeType\n\n")
|
||||
.toLocal8Bit()
|
||||
.constData());
|
||||
puts(i18n(" kioclient exec ftp://localhost/\n"
|
||||
" // Opens URL with the default handler for ftp:// scheme\n\n")
|
||||
.toLocal8Bit()
|
||||
.constData());
|
||||
puts(i18n(" kioclient exec file:/root/Desktop/emacs.desktop\n"
|
||||
" // Starts emacs\n\n")
|
||||
.toLocal8Bit()
|
||||
.constData());
|
||||
puts(i18n(" kioclient exec .\n"
|
||||
" // Opens the current directory in the default\n"
|
||||
" // file manager. Very convenient.\n\n")
|
||||
.toLocal8Bit()
|
||||
.constData());
|
||||
}
|
||||
#endif
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
#ifdef KIOCORE_ONLY
|
||||
QCoreApplication app(argc, argv);
|
||||
#else
|
||||
QApplication app(argc, argv);
|
||||
#endif
|
||||
|
||||
KLocalizedString::setApplicationDomain(QByteArrayLiteral("kioclient"));
|
||||
|
||||
QString appName = QStringLiteral("kioclient");
|
||||
QString programName = i18n("KIO Client");
|
||||
QString description = i18n("Command-line tool for network-transparent operations");
|
||||
QString version = QLatin1String(PROJECT_VERSION);
|
||||
KAboutData data(appName, programName, version, description, KAboutLicense::LGPL_V2);
|
||||
KAboutData::setApplicationData(data);
|
||||
|
||||
QCommandLineParser parser;
|
||||
data.setupCommandLine(&parser);
|
||||
parser.addOption(QCommandLineOption(QStringLiteral("interactive"), i18n("Use message boxes and other native notifications")));
|
||||
|
||||
parser.addOption(QCommandLineOption(QStringLiteral("noninteractive"),
|
||||
i18n("Non-interactive use: no message boxes. If you don't want a "
|
||||
"graphical connection, use --platform offscreen")));
|
||||
|
||||
#if !defined(KIOCLIENT_AS_KDEOPEN)
|
||||
parser.addOption(QCommandLineOption(QStringLiteral("overwrite"), i18n("Overwrite destination if it exists (for copy and move)")));
|
||||
#endif
|
||||
|
||||
#if defined(KIOCLIENT_AS_KDEOPEN)
|
||||
parser.addPositionalArgument(QStringLiteral("url"), i18n("file or URL"), i18n("urls..."));
|
||||
#elif defined(KIOCLIENT_AS_KDECP)
|
||||
parser.addPositionalArgument(QStringLiteral("src"), i18n("Source URL or URLs"), i18n("urls..."));
|
||||
parser.addPositionalArgument(QStringLiteral("dest"), i18n("Destination URL"), i18n("url"));
|
||||
#elif defined(KIOCLIENT_AS_KDEMV)
|
||||
parser.addPositionalArgument(QStringLiteral("src"), i18n("Source URL or URLs"), i18n("urls..."));
|
||||
parser.addPositionalArgument(QStringLiteral("dest"), i18n("Destination URL"), i18n("url"));
|
||||
#elif defined(KIOCLIENT_AS_KIOCLIENT)
|
||||
parser.addOption(QCommandLineOption(QStringLiteral("commands"), i18n("Show available commands")));
|
||||
parser.addPositionalArgument(QStringLiteral("command"), i18n("Command (see --commands)"), i18n("command"));
|
||||
parser.addPositionalArgument(QStringLiteral("URLs"), i18n("Arguments for command"), i18n("urls..."));
|
||||
#endif
|
||||
|
||||
// KCmdLineArgs::addTempFileOption();
|
||||
|
||||
parser.process(app);
|
||||
data.processCommandLine(&parser);
|
||||
|
||||
#ifdef KIOCLIENT_AS_KIOCLIENT
|
||||
if (argc == 1 || parser.isSet(QStringLiteral("commands"))) {
|
||||
puts(parser.helpText().toLocal8Bit().constData());
|
||||
puts("\n\n");
|
||||
usage();
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
ClientApp client;
|
||||
return client.doIt(parser) ? 0 /*no error*/ : 1 /*error*/;
|
||||
}
|
||||
|
||||
static void checkArgumentCount(int count, int min, int max)
|
||||
{
|
||||
if (count < min) {
|
||||
fputs(i18nc("@info:shell", "%1: Syntax error, not enough arguments\n", qAppName()).toLocal8Bit().constData(), stderr);
|
||||
::exit(1);
|
||||
}
|
||||
if (max && (count > max)) {
|
||||
fputs(i18nc("@info:shell", "%1: Syntax error, too many arguments\n", qAppName()).toLocal8Bit().constData(), stderr);
|
||||
::exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
#ifndef KIOCORE_ONLY
|
||||
bool ClientApp::kde_open(const QString &_url, const QString &mimeType, bool allowExec)
|
||||
{
|
||||
QString url = _url;
|
||||
if (url.startsWith(QLatin1String("thunderlink://")) || url.startsWith(QLatin1String("slack://")) || url.startsWith(QLatin1String("zoommtg://"))) {
|
||||
// thunderlink:// -> thunderlink:/// so QUrl doesn't break the payload's
|
||||
// case sensitivity which would otherwise be at the hostname section
|
||||
const QLatin1Char slash('/');
|
||||
url.insert(url.indexOf(slash), slash);
|
||||
}
|
||||
|
||||
UrlInfo info(url);
|
||||
|
||||
if (!info.atStart()) {
|
||||
QUrlQuery q;
|
||||
q.addQueryItem(QStringLiteral("line"), QString::number(info.line));
|
||||
q.addQueryItem(QStringLiteral("column"), QString::number(info.column));
|
||||
info.url.setQuery(q);
|
||||
}
|
||||
|
||||
auto *job = new KIO::OpenUrlJob(info.url, mimeType);
|
||||
job->setUiDelegate(KIO::createDefaultJobUiDelegate(KJobUiDelegate::AutoHandlingEnabled, nullptr));
|
||||
job->setRunExecutables(allowExec);
|
||||
job->setFollowRedirections(false);
|
||||
bool job_had_error = false;
|
||||
QObject::connect(job, &KJob::result, this, [&](KJob *job) {
|
||||
if (job->error()) {
|
||||
job_had_error = true;
|
||||
qWarning().noquote() << job->errorString();
|
||||
}
|
||||
});
|
||||
job->start();
|
||||
qApp->exec();
|
||||
return !job_had_error;
|
||||
}
|
||||
#endif
|
||||
|
||||
bool ClientApp::doCopy(const QStringList &urls)
|
||||
{
|
||||
QList<QUrl> srcLst(makeUrls(urls));
|
||||
QUrl dest = srcLst.takeLast();
|
||||
KIO::Job *job = KIO::copy(srcLst, dest, s_jobFlags);
|
||||
if (!s_interactive) {
|
||||
job->setUiDelegate(nullptr);
|
||||
job->setUiDelegateExtension(nullptr);
|
||||
}
|
||||
connect(job, &KJob::result, this, &ClientApp::slotResult);
|
||||
qApp->exec();
|
||||
return m_ok;
|
||||
}
|
||||
|
||||
void ClientApp::slotEntries(KIO::Job *, const KIO::UDSEntryList &list)
|
||||
{
|
||||
for (const auto &entry : list) {
|
||||
// For each file...
|
||||
std::cout << qPrintable(entry.stringValue(KIO::UDSEntry::UDS_NAME)) << '\n';
|
||||
}
|
||||
|
||||
std::cout << std::endl;
|
||||
}
|
||||
|
||||
bool ClientApp::doList(const QStringList &urls)
|
||||
{
|
||||
const QUrl dir = makeURL(urls.at(0));
|
||||
|
||||
KIO::ListJob *job = KIO::listDir(dir, KIO::HideProgressInfo);
|
||||
if (!s_interactive) {
|
||||
job->setUiDelegate(nullptr);
|
||||
job->setUiDelegateExtension(nullptr);
|
||||
}
|
||||
|
||||
connect(job, &KIO::ListJob::entries, this, &ClientApp::slotEntries);
|
||||
connect(job, &KJob::result, this, &ClientApp::slotResult);
|
||||
|
||||
qApp->exec();
|
||||
return m_ok;
|
||||
}
|
||||
|
||||
bool ClientApp::doMove(const QStringList &urls)
|
||||
{
|
||||
QList<QUrl> srcLst(makeUrls(urls));
|
||||
const QUrl dest = srcLst.takeLast();
|
||||
|
||||
KIO::Job *job = KIO::move(srcLst, dest, s_jobFlags);
|
||||
if (!s_interactive) {
|
||||
job->setUiDelegate(nullptr);
|
||||
job->setUiDelegateExtension(nullptr);
|
||||
}
|
||||
|
||||
connect(job, &KJob::result, this, &ClientApp::slotResult);
|
||||
|
||||
qApp->exec();
|
||||
return m_ok;
|
||||
}
|
||||
|
||||
bool ClientApp::doRemove(const QStringList &urls)
|
||||
{
|
||||
KIO::Job *job = KIO::del(makeUrls(urls), s_jobFlags);
|
||||
if (!s_interactive) {
|
||||
job->setUiDelegate(nullptr);
|
||||
job->setUiDelegateExtension(nullptr);
|
||||
}
|
||||
|
||||
connect(job, &KJob::result, this, &ClientApp::slotResult);
|
||||
|
||||
qApp->exec();
|
||||
return m_ok;
|
||||
}
|
||||
|
||||
bool ClientApp::doStat(const QStringList &urls)
|
||||
{
|
||||
KIO::Job *job = KIO::stat(makeURL(urls.first()),
|
||||
KIO::StatJob::SourceSide,
|
||||
(KIO::StatBasic | KIO::StatUser | KIO::StatTime | KIO::StatInode | KIO::StatMimeType | KIO::StatAcl),
|
||||
s_jobFlags);
|
||||
if (!s_interactive) {
|
||||
job->setUiDelegate(nullptr);
|
||||
job->setUiDelegateExtension(nullptr);
|
||||
}
|
||||
|
||||
connect(job, &KJob::result, this, &ClientApp::slotStatResult);
|
||||
|
||||
qApp->exec();
|
||||
return m_ok;
|
||||
}
|
||||
|
||||
bool ClientApp::doIt(const QCommandLineParser &parser)
|
||||
{
|
||||
const int argc = parser.positionalArguments().count();
|
||||
checkArgumentCount(argc, 1, 0);
|
||||
|
||||
if (parser.isSet(QStringLiteral("interactive"))) {
|
||||
s_interactive = true;
|
||||
} else {
|
||||
// "noninteractive" is currently the default mode, so we don't check.
|
||||
// The argument still needs to exist for compatibility
|
||||
s_interactive = false;
|
||||
s_jobFlags = KIO::HideProgressInfo;
|
||||
}
|
||||
#if !defined(KIOCLIENT_AS_KDEOPEN)
|
||||
if (parser.isSet(QStringLiteral("overwrite"))) {
|
||||
s_jobFlags |= KIO::Overwrite;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef KIOCLIENT_AS_KDEOPEN
|
||||
return kde_open(parser.positionalArguments().at(0), QString(), false);
|
||||
#elif defined(KIOCLIENT_AS_KDECP)
|
||||
checkArgumentCount(argc, 2, 0);
|
||||
return doCopy(parser.positionalArguments());
|
||||
#elif defined(KIOCLIENT_AS_KDEMV)
|
||||
checkArgumentCount(argc, 2, 0);
|
||||
return doMove(parser.positionalArguments());
|
||||
#else
|
||||
// Normal kioclient mode
|
||||
const QString command = parser.positionalArguments().at(0);
|
||||
#ifndef KIOCORE_ONLY
|
||||
if (command == QLatin1String("openProperties")) {
|
||||
checkArgumentCount(argc, 2, 2); // openProperties <url>
|
||||
const QUrl url = makeURL(parser.positionalArguments().constLast());
|
||||
|
||||
KPropertiesDialog *dlg = new KPropertiesDialog(url, nullptr /*no parent*/);
|
||||
QObject::connect(dlg, &QObject::destroyed, qApp, &QCoreApplication::quit);
|
||||
QObject::connect(dlg, &KPropertiesDialog::canceled, this, &ClientApp::slotDialogCanceled);
|
||||
dlg->show();
|
||||
|
||||
qApp->exec();
|
||||
return m_ok;
|
||||
} else
|
||||
#endif
|
||||
if (command == QLatin1String("cat")) {
|
||||
checkArgumentCount(argc, 2, 2); // cat <url>
|
||||
const QUrl url = makeURL(parser.positionalArguments().constLast());
|
||||
|
||||
KIO::TransferJob *job = KIO::get(url, KIO::NoReload, s_jobFlags);
|
||||
if (!s_interactive) {
|
||||
job->setUiDelegate(nullptr);
|
||||
job->setUiDelegateExtension(nullptr);
|
||||
}
|
||||
connect(job, &KIO::TransferJob::data, this, &ClientApp::slotPrintData);
|
||||
connect(job, &KJob::result, this, &ClientApp::slotResult);
|
||||
|
||||
qApp->exec();
|
||||
return m_ok;
|
||||
}
|
||||
#ifndef KIOCORE_ONLY
|
||||
else if (command == QLatin1String("exec")) {
|
||||
checkArgumentCount(argc, 2, 3);
|
||||
return kde_open(parser.positionalArguments().at(1), argc == 3 ? parser.positionalArguments().constLast() : QString(), true);
|
||||
} else if (command == QLatin1String("appmenu")) {
|
||||
auto *job = new KIO::ApplicationLauncherJob();
|
||||
job->setUiDelegate(KIO::createDefaultJobUiDelegate(KJobUiDelegate::AutoHandlingEnabled, nullptr));
|
||||
connect(job, &KJob::result, this, &ClientApp::slotResult);
|
||||
job->start();
|
||||
|
||||
qApp->exec();
|
||||
return m_ok;
|
||||
}
|
||||
#endif
|
||||
else if (command == QLatin1String("download")) {
|
||||
checkArgumentCount(argc, 0, 0);
|
||||
QStringList args = parser.positionalArguments();
|
||||
args.removeFirst();
|
||||
const QList<QUrl> srcLst = makeUrls(args);
|
||||
|
||||
if (srcLst.isEmpty()) {
|
||||
return m_ok;
|
||||
}
|
||||
|
||||
const QUrl dsturl = QFileDialog::getSaveFileUrl(nullptr, i18n("Destination where to download the files"), srcLst.at(0));
|
||||
|
||||
if (dsturl.isEmpty()) { // canceled
|
||||
return m_ok; // AK - really okay?
|
||||
}
|
||||
|
||||
KIO::Job *job = KIO::copy(srcLst, dsturl, s_jobFlags);
|
||||
if (!s_interactive) {
|
||||
job->setUiDelegate(nullptr);
|
||||
job->setUiDelegateExtension(nullptr);
|
||||
}
|
||||
|
||||
connect(job, &KJob::result, this, &ClientApp::slotResult);
|
||||
|
||||
qApp->exec();
|
||||
return m_ok;
|
||||
} else if (command == QLatin1String("copy") || command == QLatin1String("cp")) {
|
||||
checkArgumentCount(argc, 3, 0); // cp <src> <dest>
|
||||
QStringList args = parser.positionalArguments();
|
||||
args.removeFirst();
|
||||
return doCopy(args);
|
||||
} else if (command == QLatin1String("move") || command == QLatin1String("mv")) {
|
||||
checkArgumentCount(argc, 3, 0); // mv <src> <dest>
|
||||
QStringList args = parser.positionalArguments();
|
||||
args.removeFirst();
|
||||
return doMove(args);
|
||||
} else if (command == QLatin1String("list") || command == QLatin1String("ls")) {
|
||||
checkArgumentCount(argc, 2, 2); // ls <url>
|
||||
QStringList args = parser.positionalArguments();
|
||||
args.removeFirst();
|
||||
return doList(args);
|
||||
} else if (command == QLatin1String("remove") || command == QLatin1String("rm")) {
|
||||
checkArgumentCount(argc, 2, 0); // rm <url>
|
||||
QStringList args = parser.positionalArguments();
|
||||
args.removeFirst();
|
||||
return doRemove(args);
|
||||
} else if (command == QLatin1String("stat")) {
|
||||
checkArgumentCount(argc, 2, 2); // stat <url>
|
||||
QStringList args = parser.positionalArguments();
|
||||
args.removeFirst();
|
||||
return doStat(args);
|
||||
} else {
|
||||
fputs(i18nc("@info:shell", "%1: Syntax error, unknown command '%2'\n", qAppName(), command).toLocal8Bit().data(), stderr);
|
||||
return false;
|
||||
}
|
||||
Q_UNREACHABLE();
|
||||
#endif
|
||||
}
|
||||
|
||||
void ClientApp::slotResult(KJob *job)
|
||||
{
|
||||
if (job->error()) {
|
||||
#ifndef KIOCORE_ONLY
|
||||
if (s_interactive) {
|
||||
static_cast<KIO::Job *>(job)->uiDelegate()->showErrorMessage();
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
fputs(qPrintable(i18nc("@info:shell", "%1: %2\n", qAppName(), job->errorString())), stderr);
|
||||
}
|
||||
}
|
||||
m_ok = !job->error();
|
||||
if (qApp->topLevelWindows().isEmpty()) {
|
||||
qApp->quit();
|
||||
} else {
|
||||
qApp->setQuitOnLastWindowClosed(true);
|
||||
}
|
||||
}
|
||||
|
||||
void ClientApp::slotDialogCanceled()
|
||||
{
|
||||
m_ok = false;
|
||||
qApp->quit();
|
||||
}
|
||||
|
||||
void ClientApp::slotPrintData(KIO::Job *, const QByteArray &data)
|
||||
{
|
||||
if (!data.isEmpty()) {
|
||||
std::cout.write(data.constData(), data.size());
|
||||
}
|
||||
}
|
||||
|
||||
static void showStatField(const KIO::UDSEntry &entry, uint field, const char *name)
|
||||
{
|
||||
if (!entry.contains(field))
|
||||
return;
|
||||
std::cout << qPrintable(QString::fromLocal8Bit(name).leftJustified(20, ' ')) << " ";
|
||||
|
||||
if (field == KIO::UDSEntry::UDS_ACCESS) {
|
||||
std::cout << qPrintable(QString("0%1").arg(entry.numberValue(field), 3, 8, QLatin1Char('0')));
|
||||
} else if (field == KIO::UDSEntry::UDS_FILE_TYPE) {
|
||||
std::cout << qPrintable(QString("0%1").arg((entry.numberValue(field) & S_IFMT), 6, 8, QLatin1Char('0')));
|
||||
} else if (field & KIO::UDSEntry::UDS_STRING) {
|
||||
std::cout << qPrintable(entry.stringValue(field));
|
||||
} else if ((field & KIO::UDSEntry::UDS_TIME) == KIO::UDSEntry::UDS_TIME) {
|
||||
// The previous comparison is necessary because the value
|
||||
// of UDS_TIME is 0x04000000|UDS_NUMBER which is 0x06000000.
|
||||
// So simply testing with (field & KIO::UDSEntry::UDS_TIME)
|
||||
// would be true for both UDS_TIME and UDS_NUMBER fields.
|
||||
// The same would happen if UDS_NUMBER were tested first.
|
||||
const QDateTime dt = QDateTime::fromSecsSinceEpoch(entry.numberValue(field));
|
||||
if (dt.isValid())
|
||||
std::cout << qPrintable(dt.toString(Qt::TextDate));
|
||||
} else if (field & KIO::UDSEntry::UDS_NUMBER) {
|
||||
std::cout << entry.numberValue(field);
|
||||
}
|
||||
std::cout << std::endl;
|
||||
}
|
||||
|
||||
void ClientApp::slotStatResult(KJob *job)
|
||||
{
|
||||
if (!job->error()) {
|
||||
KIO::StatJob *statJob = qobject_cast<KIO::StatJob *>(job);
|
||||
Q_ASSERT(statJob != nullptr);
|
||||
const KIO::UDSEntry &result = statJob->statResult();
|
||||
|
||||
showStatField(result, KIO::UDSEntry::UDS_NAME, "NAME");
|
||||
showStatField(result, KIO::UDSEntry::UDS_DISPLAY_NAME, "DISPLAY_NAME");
|
||||
showStatField(result, KIO::UDSEntry::UDS_COMMENT, "COMMENT");
|
||||
showStatField(result, KIO::UDSEntry::UDS_SIZE, "SIZE");
|
||||
// This is not requested for the StatJob, so should never be seen
|
||||
showStatField(result, KIO::UDSEntry::UDS_RECURSIVE_SIZE, "RECURSIVE_SIZE");
|
||||
|
||||
showStatField(result, KIO::UDSEntry::UDS_FILE_TYPE, "FILE_TYPE");
|
||||
showStatField(result, KIO::UDSEntry::UDS_USER, "USER");
|
||||
showStatField(result, KIO::UDSEntry::UDS_GROUP, "GROUP");
|
||||
showStatField(result, KIO::UDSEntry::UDS_HIDDEN, "HIDDEN");
|
||||
showStatField(result, KIO::UDSEntry::UDS_DEVICE_ID, "DEVICE_ID");
|
||||
showStatField(result, KIO::UDSEntry::UDS_INODE, "INODE");
|
||||
|
||||
showStatField(result, KIO::UDSEntry::UDS_LINK_DEST, "LINK_DEST");
|
||||
showStatField(result, KIO::UDSEntry::UDS_URL, "URL");
|
||||
showStatField(result, KIO::UDSEntry::UDS_LOCAL_PATH, "LOCAL_PATH");
|
||||
showStatField(result, KIO::UDSEntry::UDS_TARGET_URL, "TARGET_URL");
|
||||
|
||||
showStatField(result, KIO::UDSEntry::UDS_MIME_TYPE, "MIME_TYPE");
|
||||
showStatField(result, KIO::UDSEntry::UDS_GUESSED_MIME_TYPE, "GUESSED_MIME_TYPE");
|
||||
|
||||
showStatField(result, KIO::UDSEntry::UDS_ICON_NAME, "ICON_NAME");
|
||||
showStatField(result, KIO::UDSEntry::UDS_ICON_OVERLAY_NAMES, "ICON_OVERLAY_NAMES");
|
||||
|
||||
showStatField(result, KIO::UDSEntry::UDS_ACCESS, "ACCESS");
|
||||
showStatField(result, KIO::UDSEntry::UDS_EXTENDED_ACL, "EXTENDED_ACL");
|
||||
showStatField(result, KIO::UDSEntry::UDS_ACL_STRING, "ACL_STRING");
|
||||
showStatField(result, KIO::UDSEntry::UDS_DEFAULT_ACL_STRING, "DEFAULT_ACL_STRING");
|
||||
|
||||
showStatField(result, KIO::UDSEntry::UDS_MODIFICATION_TIME, "MODIFICATION_TIME");
|
||||
showStatField(result, KIO::UDSEntry::UDS_ACCESS_TIME, "ACCESS_TIME");
|
||||
showStatField(result, KIO::UDSEntry::UDS_CREATION_TIME, "CREATION_TIME");
|
||||
|
||||
showStatField(result, KIO::UDSEntry::UDS_XML_PROPERTIES, "XML_PROPERTIES");
|
||||
showStatField(result, KIO::UDSEntry::UDS_DISPLAY_TYPE, "DISPLAY_TYPE");
|
||||
}
|
||||
|
||||
slotResult(job);
|
||||
}
|
||||
|
||||
ClientApp::ClientApp()
|
||||
: QObject()
|
||||
{
|
||||
}
|
||||
|
||||
#include "moc_kioclient.cpp"
|
||||
@@ -0,0 +1,47 @@
|
||||
/* This file is part of the KDE project
|
||||
SPDX-FileCopyrightText: 1999-2006 David Faure <faure@kde.org>
|
||||
|
||||
SPDX-License-Identifier: LGPL-2.0-only
|
||||
*/
|
||||
|
||||
#ifndef __kioclient_h
|
||||
#define __kioclient_h
|
||||
|
||||
#include <QApplication>
|
||||
#include <kio/udsentry.h>
|
||||
|
||||
class QCommandLineParser;
|
||||
class KJob;
|
||||
namespace KIO
|
||||
{
|
||||
class Job;
|
||||
}
|
||||
|
||||
class ClientApp : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
ClientApp();
|
||||
|
||||
/** Parse command-line arguments and "do it" */
|
||||
bool doIt(const QCommandLineParser &parser);
|
||||
|
||||
private Q_SLOTS:
|
||||
void slotPrintData(KIO::Job *job, const QByteArray &data);
|
||||
void slotEntries(KIO::Job *job, const KIO::UDSEntryList &);
|
||||
void slotResult(KJob *);
|
||||
void slotStatResult(KJob *);
|
||||
void slotDialogCanceled();
|
||||
|
||||
private:
|
||||
bool kde_open(const QString &url, const QString &mimeType, bool allowExec);
|
||||
bool doCopy(const QStringList &urls);
|
||||
bool doMove(const QStringList &urls);
|
||||
bool doList(const QStringList &urls);
|
||||
bool doRemove(const QStringList &urls);
|
||||
bool doStat(const QStringList &urls);
|
||||
|
||||
static bool m_ok;
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,112 @@
|
||||
/* This file is part of the KDE project
|
||||
SPDX-FileCopyrightText: 2015 Milian Wolff <mail@milianw.de>
|
||||
|
||||
SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
|
||||
*/
|
||||
|
||||
#ifndef URLINFO_H
|
||||
#define URLINFO_H
|
||||
|
||||
#include <QDir>
|
||||
#include <QRegularExpression>
|
||||
#include <QString>
|
||||
#include <QUrl>
|
||||
|
||||
/**
|
||||
* Represents a file to be opened, consisting of its URL and the cursor to jump to.
|
||||
*/
|
||||
class UrlInfo
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* Parses an argument and determines its line number and column and full path
|
||||
* @param pathOrUrl path passed on e.g. command line to parse into an URL or just an URL
|
||||
*/
|
||||
UrlInfo(const QString &pathOrUrl)
|
||||
: line(0)
|
||||
, column(0)
|
||||
{
|
||||
/**
|
||||
* first try: just check if the path is an existing file
|
||||
*/
|
||||
if (QFile::exists(pathOrUrl)) {
|
||||
/**
|
||||
* create absolute file path, we will e.g. pass this over dbus to other processes
|
||||
* and then we are done, no cursor can be detected here!
|
||||
*/
|
||||
url = QUrl::fromLocalFile(QDir::current().absoluteFilePath(pathOrUrl));
|
||||
return;
|
||||
}
|
||||
|
||||
if (auto inputUrl = QUrl::fromUserInput(pathOrUrl); inputUrl.isLocalFile() && QFile::exists(inputUrl.toLocalFile())) {
|
||||
url = inputUrl;
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* if the path starts with http:// or any other scheme, except file://
|
||||
* we also don't want to do anything with URL
|
||||
*/
|
||||
if (!QUrl::fromUserInput(pathOrUrl).isLocalFile()) {
|
||||
url = QUrl::fromUserInput(pathOrUrl, QDir::currentPath(), QUrl::DefaultResolution);
|
||||
// relative paths are not isLocalFile(), but not valid too, so we don't want them
|
||||
if (url.isValid()) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* ok, the path as is, is no existing file, now, cut away :xx:yy stuff as cursor
|
||||
* this will make test:50 to test with line 50
|
||||
*/
|
||||
QString pathOrUrl2 = pathOrUrl;
|
||||
const auto match = QRegularExpression(QStringLiteral(":(\\d+)(?::(\\d+))?:?$")).match(pathOrUrl2);
|
||||
if (match.isValid()) {
|
||||
/**
|
||||
* cut away the line/column specification from the path
|
||||
*/
|
||||
pathOrUrl2.chop(match.capturedLength());
|
||||
|
||||
/**
|
||||
* set right cursor position
|
||||
*/
|
||||
line = match.capturedView(1).toUInt();
|
||||
column = match.capturedView(2).toUInt();
|
||||
}
|
||||
|
||||
/**
|
||||
* construct url:
|
||||
* - make relative paths absolute using the current working directory
|
||||
* - do not prefer local file, to be able to open things like foo.com in browser
|
||||
*/
|
||||
url = QUrl::fromUserInput(pathOrUrl2, QDir::currentPath(), QUrl::DefaultResolution);
|
||||
|
||||
/**
|
||||
* in some cases, this will fail, e.g. if you have line/column specs like test.c:10:1
|
||||
* => fallback: assume a local file and just convert it to an url
|
||||
*/
|
||||
if (!url.isValid()) {
|
||||
/**
|
||||
* create absolute file path, we will e.g. pass this over dbus to other processes
|
||||
*/
|
||||
url = QUrl::fromLocalFile(QDir::current().absoluteFilePath(pathOrUrl2));
|
||||
}
|
||||
}
|
||||
|
||||
bool atStart() const
|
||||
{
|
||||
return (line == 0 || line == 1) && (column == 0 || column == 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* url computed out of the passed path or URL
|
||||
*/
|
||||
QUrl url;
|
||||
|
||||
/**
|
||||
* initial cursor position, if any found inside the path as line/column specification at the end
|
||||
*/
|
||||
unsigned line, column;
|
||||
};
|
||||
|
||||
#endif // URLINFO_H
|
||||
Reference in New Issue
Block a user