Index: kioslave/CMakeLists.txt =================================================================== --- /dev/null +++ kioslave/CMakeLists.txt @@ -0,0 +1,3 @@ +add_subdirectory(applications) +add_subdirectory(desktop) +add_subdirectory(remote) Index: kioslave/applications/CMakeLists.txt =================================================================== --- /dev/null +++ kioslave/applications/CMakeLists.txt @@ -0,0 +1,8 @@ +add_definitions(-DTRANSLATION_DOMAIN=\"kio_applications\") + +add_library(kio_applications MODULE kio_applications.cpp) + +target_link_libraries(kio_applications KF5::KIOCore KF5::I18n) + +install(TARGETS kio_applications DESTINATION ${KDE_INSTALL_PLUGINDIR} ) +install( FILES programs.protocol applications.protocol DESTINATION ${KDE_INSTALL_KSERVICES5DIR} ) Index: kioslave/applications/Messages.sh =================================================================== --- /dev/null +++ kioslave/applications/Messages.sh @@ -0,0 +1,2 @@ +#! /usr/bin/env bash +$XGETTEXT `find . -name "*.cc" -o -name "*.cpp" -o -name "*.h"` -o $podir/kio_applications.pot Index: kioslave/applications/applications.protocol =================================================================== --- /dev/null +++ kioslave/applications/applications.protocol @@ -0,0 +1,15 @@ +[Protocol] +exec=kio_applications +protocol=applications +input=none +output=filesystem +listing=Name,Type,Size,Date,Access,Owner,Group,Link, +reading=true +writing=false +makedir=false +deleting=false +linking=false +moving=false +Icon=start-here-kde +maxInstances=2 +Class=:local Index: kioslave/applications/kio_applications.cpp =================================================================== --- /dev/null +++ kioslave/applications/kio_applications.cpp @@ -0,0 +1,198 @@ +/* This file is part of the KDE project + Copyright (C) 2003 Joseph Wenninger + + 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. +*/ + +#include +#include +#include +#include +#include +#include + +#include +#include + +class ApplicationsProtocol : public KIO::SlaveBase +{ +public: + enum RunMode { ProgramsMode, ApplicationsMode }; + ApplicationsProtocol(const QByteArray &protocol, const QByteArray &pool, const QByteArray &app); + ~ApplicationsProtocol() override; + void get( const QUrl& url ) override; + void stat(const QUrl& url) override; + void listDir(const QUrl& url) override; + +private: + RunMode m_runMode; +}; + +extern "C" { + Q_DECL_EXPORT int kdemain( int argc, char **argv ) + { + QCoreApplication app(argc, argv); + app.setApplicationName( "kio_applications" ); + + ApplicationsProtocol slave(argv[1], argv[2], argv[3]); + slave.dispatchLoop(); + return 0; + } +} + + +static void createFileEntry(KIO::UDSEntry& entry, const KService::Ptr& service, const QUrl& parentUrl) +{ + entry.clear(); + entry.insert(KIO::UDSEntry::UDS_NAME, KIO::encodeFileName(service->name())); + entry.insert(KIO::UDSEntry::UDS_FILE_TYPE, S_IFREG); + const QString fileUrl = parentUrl.url() + '/' + service->desktopEntryName(); + entry.insert(KIO::UDSEntry::UDS_URL, fileUrl); + entry.insert(KIO::UDSEntry::UDS_ACCESS, 0500); + entry.insert(KIO::UDSEntry::UDS_MIME_TYPE, QStringLiteral("application/x-desktop")); + entry.insert(KIO::UDSEntry::UDS_SIZE, 0); + const QString localPath = QStandardPaths::locate(QStandardPaths::ApplicationsLocation, QStringLiteral("%1.desktop").arg(service->desktopEntryName())); + entry.insert(KIO::UDSEntry::UDS_LOCAL_PATH, localPath); + entry.insert(KIO::UDSEntry::UDS_MODIFICATION_TIME, time(0)); + entry.insert(KIO::UDSEntry::UDS_ICON_NAME, service->icon()); +} + +static void createDirEntry(KIO::UDSEntry& entry, const QString& name, const QString& url, const QString& mime, const QString& iconName) +{ + entry.clear(); + entry.insert( KIO::UDSEntry::UDS_NAME, name ); + entry.insert( KIO::UDSEntry::UDS_FILE_TYPE, S_IFDIR ); + entry.insert( KIO::UDSEntry::UDS_ACCESS, 0500 ); + entry.insert( KIO::UDSEntry::UDS_MIME_TYPE, mime ); + if (!url.isEmpty()) + entry.insert( KIO::UDSEntry::UDS_URL, url ); + entry.insert( KIO::UDSEntry::UDS_ICON_NAME, iconName ); +} + +ApplicationsProtocol::ApplicationsProtocol( const QByteArray &protocol, const QByteArray &pool, const QByteArray &app) + : SlaveBase( protocol, pool, app ) +{ + // Adjusts which part of the K Menu to virtualize. + if ( protocol == "programs" ) + m_runMode = ProgramsMode; + else // if (protocol == "applications") + m_runMode = ApplicationsMode; +} + +ApplicationsProtocol::~ApplicationsProtocol() +{ +} + +void ApplicationsProtocol::get( const QUrl & url ) +{ + KService::Ptr service = KService::serviceByDesktopName(url.fileName()); + if (service && service->isValid()) { + const QString localPath = QStandardPaths::locate(QStandardPaths::ApplicationsLocation, QStringLiteral("%1.desktop").arg(service->desktopEntryName())); + QUrl redirUrl(QUrl::fromLocalFile(localPath)); + redirection(redirUrl); + finished(); + } else { + error( KIO::ERR_IS_DIRECTORY, url.toDisplayString() ); + } +} + + +void ApplicationsProtocol::stat(const QUrl& url) +{ + KIO::UDSEntry entry; + + QString servicePath( url.path() ); + if(!servicePath.endsWith('/')) + servicePath.append('/'); + servicePath.remove(0, 1); // remove starting '/' + + KServiceGroup::Ptr grp = KServiceGroup::group(servicePath); + + if (grp && grp->isValid()) { + createDirEntry(entry, ((m_runMode==ApplicationsMode) ? i18n("Applications") : i18n("Programs")), + url.url(), QStringLiteral("inode/directory"), grp->icon() ); + } else { + KService::Ptr service = KService::serviceByDesktopName( url.fileName() ); + if (service && service->isValid()) { + createFileEntry(entry, service, url ); + } else { + error(KIO::ERR_SLAVE_DEFINED, i18n("Unknown application folder")); + return; + } + } + + statEntry(entry); + finished(); +} + + +void ApplicationsProtocol::listDir(const QUrl& url) +{ + QString groupPath = url.path(); + if(!groupPath.endsWith('/')) + groupPath.append('/'); + groupPath.remove(0, 1); // remove starting '/' + + KServiceGroup::Ptr grp = KServiceGroup::group(groupPath); + + if (!grp || !grp->isValid()) { + error(KIO::ERR_DOES_NOT_EXIST, groupPath); + return; + } + + unsigned int count = 0; + KIO::UDSEntry entry; + + foreach (const KSycocaEntry::Ptr &e, grp->entries(true, true)) { + if (e->isType(KST_KServiceGroup)) { + KServiceGroup::Ptr g(static_cast(e.data())); + + //qDebug() << "ADDING SERVICE GROUP WITH PATH " << g->relPath(); + + // Avoid adding empty groups. + KServiceGroup::Ptr subMenuRoot = KServiceGroup::group(g->relPath()); + if (subMenuRoot->childCount() == 0) + continue; + + // Ignore dotfiles. + if (g->name().startsWith('.')) + continue; + + QString relPath = g->relPath(); + QUrl dirUrl = url; // preserve protocol, whether that's programs:/ or applications:/ + dirUrl.setPath('/' + relPath); + dirUrl = dirUrl.adjusted(QUrl::StripTrailingSlash); + //qDebug() << "ApplicationsProtocol: adding entry" << dirUrl; + createDirEntry(entry, g->caption(), dirUrl.url(), QStringLiteral("inode/directory"), g->icon()); + } else { + KService::Ptr service(static_cast(e.data())); + + //qDebug() << "the entry name is" << service->desktopEntryName() + // << "with path" << service->entryPath(); + + if (!service->isApplication()) // how could this happen? + continue; + createFileEntry(entry, service, url); + } + + listEntry(entry); + count++; + } + + totalSize(count); + listEntry(entry); + finished(); +} Index: kioslave/applications/programs.protocol =================================================================== --- /dev/null +++ kioslave/applications/programs.protocol @@ -0,0 +1,15 @@ +[Protocol] +exec=kio_applications +protocol=programs +input=none +output=filesystem +listing=Name,Type,Size,Date,Access,Owner,Group,Link, +reading=true +writing=false +makedir=false +deleting=false +linking=false +moving=false +Icon=start-here-kde +maxInstances=2 +Class=:local Index: kioslave/desktop/CMakeLists.txt =================================================================== --- /dev/null +++ kioslave/desktop/CMakeLists.txt @@ -0,0 +1,24 @@ +add_subdirectory(tests) + +add_library(kio_desktop MODULE kio_desktop.cpp) + +target_link_libraries(kio_desktop Qt5::DBus Qt5::Gui KF5::KIOCore) + +set_target_properties(kio_desktop PROPERTIES OUTPUT_NAME "desktop") + +install(TARGETS kio_desktop DESTINATION ${PLUGIN_INSTALL_DIR}/kf5/kio) + +########### next target ############### + +add_library(desktopnotifier MODULE desktopnotifier.cpp) +kcoreaddons_desktop_to_json(desktopnotifier desktopnotifier.desktop) +target_link_libraries(desktopnotifier KF5::KIOCore KF5::DBusAddons) + +install(TARGETS desktopnotifier DESTINATION ${PLUGIN_INSTALL_DIR}/kf5/kded) + +########### install files ############### + +install( FILES desktop.protocol DESTINATION ${SERVICES_INSTALL_DIR} ) + +install(FILES directory.desktop directory.trash DESTINATION ${DATA_INSTALL_DIR}/kio_desktop) +install(FILES Home.desktop DESTINATION ${DATA_INSTALL_DIR}/kio_desktop/DesktopLinks) Index: kioslave/desktop/ExtraDesktop.sh =================================================================== --- /dev/null +++ kioslave/desktop/ExtraDesktop.sh @@ -0,0 +1,4 @@ +#! /bin/sh +#This file has output in separate line each file with a .desktop syntax +#that needs to be translated but has a non .desktop extension +find -name \*.trash -print Index: kioslave/desktop/Home.desktop =================================================================== --- /dev/null +++ kioslave/desktop/Home.desktop @@ -0,0 +1,85 @@ +[Desktop Entry] +Encoding=UTF-8 +Name=Home +Name[ca]=Inici +Name[ca@valencia]=Inici +Name[cs]=Můj adresář +Name[da]=Hjem +Name[de]=Persönlicher Ordner +Name[el]=Προσωπικός φάκελος +Name[en_GB]=Home +Name[es]=Inicio +Name[et]=Kodu +Name[fi]=Koti +Name[fr]=Dossier personnel +Name[gl]=Cartafol persoal +Name[he]=בית +Name[is]=Heimamappa +Name[it]=Home +Name[ja]=ホーム +Name[ko]=홈 +Name[lt]=Pradžia +Name[nl]=Home +Name[nn]=Heim +Name[pa]=ਘਰ +Name[pl]=Katalog domowy +Name[pt]=Pasta Pessoal +Name[pt_BR]=Pasta Pessoal +Name[ru]=Домашняя папка +Name[se]=Ruoktu +Name[sk]=Domov +Name[sl]=Dom +Name[sr]=Домаће +Name[sr@ijekavian]=Домаће +Name[sr@ijekavianlatin]=Domaće +Name[sr@latin]=Domaće +Name[sv]=Hem +Name[tr]=Başlangıç +Name[uk]=Домівка +Name[x-test]=xxHomexx +Name[zh_CN]=主文件夹 +Name[zh_TW]=家目錄 +GenericName=Personal Files +GenericName[ast]=Ficheros personales +GenericName[ca]=Fitxers personals +GenericName[ca@valencia]=Fitxers personals +GenericName[cs]=Osobní soubory +GenericName[da]=Personlige filer +GenericName[de]=Persönliche Dateien +GenericName[el]=Προσωπικά αρχεία +GenericName[en_GB]=Personal Files +GenericName[es]=Archivos personales +GenericName[et]=Isiklikud failid +GenericName[fi]=Omat tiedostot +GenericName[fr]=Fichiers personnels +GenericName[gl]=Ficheiros persoais +GenericName[he]=קבצים אישיים +GenericName[is]=Einkaskrár +GenericName[it]=File personali +GenericName[ja]=個人のファイル +GenericName[ko]=개인적인 파일 +GenericName[lt]=Asmeniniai failai +GenericName[nl]=Persoonlijke bestanden +GenericName[nn]=Personlege filer +GenericName[pa]=ਨਿੱਜੀ ਫਾਇਲਾਂ +GenericName[pl]=Pliki osobiste +GenericName[pt]=Ficheiros Pessoais +GenericName[pt_BR]=Arquivos pessoais +GenericName[ru]=Личные файлы +GenericName[se]=Iežat fiillat +GenericName[sk]=Osobné súbory +GenericName[sl]=Osebne datoteke +GenericName[sr]=Лични фајлови +GenericName[sr@ijekavian]=Лични фајлови +GenericName[sr@ijekavianlatin]=Lični fajlovi +GenericName[sr@latin]=Lični fajlovi +GenericName[sv]=Personliga filer +GenericName[tr]=Kişisel Dosyalar +GenericName[uk]=Особисті файли +GenericName[x-test]=xxPersonal Filesxx +GenericName[zh_CN]=个人文件 +GenericName[zh_TW]=個人檔案 +URL[$e]=$HOME +Icon=user-home +Type=Link + Index: kioslave/desktop/desktop.protocol =================================================================== --- /dev/null +++ kioslave/desktop/desktop.protocol @@ -0,0 +1,17 @@ +[Protocol] +exec=kf5/kio/desktop +protocol=desktop +Icon=user-desktop +input=none +output=filesystem +listing=Name,Type,Size,Date,AccessDate,Access,Owner,Group,Link +reading=true +writing=true +makedir=true +deleting=true +linking=true +moving=true +opening=true +maxInstances=4 +Class=:local +slaveHandlesNotify=Rename Index: kioslave/desktop/desktopnotifier.h =================================================================== --- /dev/null +++ kioslave/desktop/desktopnotifier.h @@ -0,0 +1,50 @@ +/* This file is part of the KDE Project + Copyright (C) 2008, 2009 Fredrik Höglund + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License version 2 as published by the Free Software Foundation. + + 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 DESKTOPNOTIFIER_H +#define DESKTOPNOTIFIER_H + +#include +#include + +class KDirWatch; + +class DesktopNotifier : public KDEDModule +{ + Q_OBJECT + Q_CLASSINFO("D-Bus Interface", "org.kde.DesktopNotifier") + +public: + DesktopNotifier(QObject* parent, const QList&); + +public slots: + Q_SCRIPTABLE Q_NOREPLY void watchDir(const QString &path); + +private slots: + void created(const QString &path); + void dirty(const QString &path); + +private: + void checkDesktopLocation(); + + KDirWatch *dirWatch; + QUrl m_desktopLocation; +}; + +#endif + Index: kioslave/desktop/desktopnotifier.cpp =================================================================== --- /dev/null +++ kioslave/desktop/desktopnotifier.cpp @@ -0,0 +1,91 @@ +/* This file is part of the KDE Project + Copyright (C) 2008, 2009 Fredrik Höglund + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License version 2 as published by the Free Software Foundation. + + 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. +*/ + +#include "desktopnotifier.h" + +#include +#include +#include + +#include + +#include +#include + +K_PLUGIN_FACTORY_WITH_JSON(DesktopNotifierFactory, + "desktopnotifier.json", + registerPlugin();) + +DesktopNotifier::DesktopNotifier(QObject *parent, const QList &) + : KDEDModule(parent) +{ + m_desktopLocation = QUrl::fromLocalFile(QStandardPaths::writableLocation(QStandardPaths::DesktopLocation)); + + dirWatch = new KDirWatch(this); + dirWatch->addDir(QStandardPaths::writableLocation(QStandardPaths::DesktopLocation)); + dirWatch->addDir(QStandardPaths::writableLocation(QStandardPaths::GenericDataLocation) + '/' + "Trash/files"); + dirWatch->addFile(QStandardPaths::writableLocation(QStandardPaths::ConfigLocation) + QStringLiteral("/user-dirs.dirs")); + + connect(dirWatch, &KDirWatch::created, this, &DesktopNotifier::created); + connect(dirWatch, &KDirWatch::dirty, this, &DesktopNotifier::dirty); +} + +void DesktopNotifier::watchDir(const QString &path) +{ + dirWatch->addDir(path); +} + +void DesktopNotifier::created(const QString &path) +{ + if (path == QStandardPaths::writableLocation(QStandardPaths::ConfigLocation) + QStringLiteral("/user-dirs.dirs")){ + checkDesktopLocation(); + } +} + +void DesktopNotifier::dirty(const QString &path) +{ + Q_UNUSED(path) + + if (path.startsWith(QStandardPaths::writableLocation(QStandardPaths::GenericDataLocation) + '/' + "Trash/files")) { + // Trigger an update of the trash icon + if (QFile::exists(QStandardPaths::writableLocation(QStandardPaths::DesktopLocation) + "/trash.desktop")) + org::kde::KDirNotify::emitFilesChanged(QList() << QUrl(QStringLiteral("desktop:/trash.desktop"))); + } else if (path == QStandardPaths::writableLocation(QStandardPaths::ConfigLocation) + QStringLiteral("/user-dirs.dirs")){ + checkDesktopLocation(); + } else { + // Emitting FilesAdded forces a re-read of the dir + QUrl url; + url.setScheme(QStringLiteral("desktop")); + const auto relativePath = QDir(QStandardPaths::writableLocation(QStandardPaths::DesktopLocation)).relativeFilePath(path); + url.setPath(QStringLiteral("%1/%2").arg(url.path(), relativePath)); + url.setPath(QDir::cleanPath(url.path())); + org::kde::KDirNotify::emitFilesAdded(url); + } +} + +void DesktopNotifier::checkDesktopLocation() +{ + const QUrl ¤tLocation = QUrl::fromLocalFile(QStandardPaths::writableLocation(QStandardPaths::DesktopLocation)); + + if (m_desktopLocation != currentLocation) { + m_desktopLocation = currentLocation; + org::kde::KDirNotify::emitFilesChanged(QList() << QUrl(QStringLiteral("desktop:/"))); + } +} + +#include Index: kioslave/desktop/desktopnotifier.desktop =================================================================== --- /dev/null +++ kioslave/desktop/desktopnotifier.desktop @@ -0,0 +1,87 @@ +[Desktop Entry] +Type=Service +Name=Directory Watcher +Name[ast]=Visor de direutorios +Name[ca]=Vigilant de directori +Name[ca@valencia]=Vigilant de directori +Name[cs]=Sledovač adresářů +Name[da]=Mappeovervåger +Name[de]=Ordnerüberwachung +Name[el]=Επόπτης φακέλων +Name[en_GB]=Directory Watcher +Name[es]=Vigilante de directorios +Name[et]=Kataloogijälgija +Name[fi]=Kansion tarkkailija +Name[fr]=Surveillant de dossier +Name[gl]=Vixilante de cartafoles +Name[he]=צופה תיקיות +Name[is]=Möppuskoðunartól +Name[it]=Guardia delle cartelle +Name[ja]=ディレクトリウォッチャ +Name[ko]=디렉터리 감시기 +Name[lt]=Aplanko stebėtojas +Name[nl]=Mappenbewaker +Name[nn]=Mappeovervaking +Name[pa]=ਡਾਇਰੈਕਟਰੀ ਨਿਗਰਾਨ +Name[pl]=Monitorowanie katalogów +Name[pt]=Monitorização de Pastas +Name[pt_BR]=Monitor de pastas +Name[ru]=Наблюдение за каталогом +Name[sk]=Sledovač adresárov +Name[sl]=Opazovalnik map +Name[sr]=Надзорник фасцикли +Name[sr@ijekavian]=Надзорник фасцикли +Name[sr@ijekavianlatin]=Nadzornik fascikli +Name[sr@latin]=Nadzornik fascikli +Name[sv]=Katalogövervakare +Name[tr]=Dizin İzleyici +Name[uk]=Спостереження за каталогами +Name[x-test]=xxDirectory Watcherxx +Name[zh_CN]=目录监视器 +Name[zh_TW]=目錄監控器 +ServiceTypes=KDEDModule +X-KDE-ServiceTypes=KDEDModule +X-KDE-Library=desktopnotifier +X-KDE-FactoryName=desktopnotifier +X-KDE-DBus-ModuleName=desktopnotifier +X-KDE-Kded-load-on-demand=true +X-KDE-Kded-autoload=false +Comment=Monitors directories for changes +Comment[ast]=Monitoriza por camudancies los direutorios +Comment[ca]=Controla els canvis en els directoris +Comment[ca@valencia]=Controla els canvis en els directoris +Comment[cs]=Monitoruje změny v adresáři +Comment[da]=Overvåger mapper for ændringer +Comment[de]=Überwacht Ordner auf Änderungen +Comment[el]=Επίβλεψη φακέλων για αλλαγές +Comment[en_GB]=Monitors directories for changes +Comment[es]=Monitoriza cambios en directorios +Comment[et]=Kataloogide muutuste jälgimine +Comment[fi]=Tarkkailee muutoksia kansioissa +Comment[fr]=Surveille les changements d'un dossier +Comment[gl]=Vixía os cambios nos cartafoles. +Comment[he]=עקוב אחר שינויים בתיקיות +Comment[is]=Fylgist með breytingum í möppum +Comment[it]=Sorveglia i cambiamenti nelle cartelle +Comment[ja]=ディレクトリの変更を監視します +Comment[ko]=디렉터리 변경 사항을 감시합니다 +Comment[lt]=Stebi aplanko pakeitimus +Comment[nl]=Mappen monitoren op wijzigingen +Comment[nn]=Overvakar mapper for endringar +Comment[pl]=Monitoruje katalogi w poszukiwaniu zmian +Comment[pt]=Vigia as modificações em determinadas pastas +Comment[pt_BR]=Monitora as alterações nas pastas +Comment[ru]=Наблюдение за изменениями в каталоге +Comment[sk]=Sleduje zmeny v adresároch +Comment[sl]=Nadzira mape za spremembami +Comment[sr]=Надгледа измене у фасциклама +Comment[sr@ijekavian]=Надгледа измене у фасциклама +Comment[sr@ijekavianlatin]=Nadgleda izmene u fasciklama +Comment[sr@latin]=Nadgleda izmene u fasciklama +Comment[sv]=Övervakar om kataloger ändras +Comment[tr]=Dizinleri değişiklik için izler +Comment[uk]=Веде спостереження за змінами у каталогах +Comment[x-test]=xxMonitors directories for changesxx +Comment[zh_CN]=监视目录的更改 +Comment[zh_TW]=監控目錄的改變 + Index: kioslave/desktop/directory.desktop =================================================================== --- /dev/null +++ kioslave/desktop/directory.desktop @@ -0,0 +1,5 @@ +[Desktop Entry] +Encoding=UTF-8 +Icon=user-desktop +Type=Directory + Index: kioslave/desktop/directory.trash =================================================================== --- /dev/null +++ kioslave/desktop/directory.trash @@ -0,0 +1,88 @@ +[Desktop Entry] +Encoding=UTF-8 +Name=Trash +Name[ast]=Papelera +Name[ca]=Paperera +Name[ca@valencia]=Paperera +Name[cs]=Koš +Name[da]=Affald +Name[de]=Papierkorb +Name[el]=Απορρίμματα +Name[en_GB]=Wastebin +Name[es]=Papelera +Name[et]=Prügikast +Name[fi]=Roskakori +Name[fr]=Corbeille +Name[gl]=Lixo +Name[he]=אשפה +Name[is]=Rusl +Name[it]=Cestino +Name[ja]=ごみ箱 +Name[ko]=휴지통 +Name[lt]=Šiukšlinė +Name[nl]=Prullenbak +Name[nn]=Papirkorg +Name[pa]=ਰੱਦੀ +Name[pl]=Kosz +Name[pt]=Lixo +Name[pt_BR]=Lixeira +Name[ru]=Корзина +Name[se]=Ruskalihtti +Name[sk]=Smeti +Name[sl]=Smeti +Name[sr]=Смеће +Name[sr@ijekavian]=Смеће +Name[sr@ijekavianlatin]=Smeće +Name[sr@latin]=Smeće +Name[sv]=Papperskorg +Name[tr]=Çöp +Name[uk]=Смітник +Name[x-test]=xxTrashxx +Name[zh_CN]=回收站 +Name[zh_TW]=資源回收筒 +Comment=Contains removed files +Comment[ast]=Contién ficheros desaniciaos +Comment[ca]=Conté els fitxers eliminats +Comment[ca@valencia]=Conté els fitxers eliminats +Comment[cs]=Obsahuje odstraněné soubory +Comment[da]=Indeholder slettede filer +Comment[de]=Enthält gelöschte Dateien +Comment[el]=Περιέχει αρχεία που αφαιρέθηκαν +Comment[en_GB]=Contains removed files +Comment[es]=Contiene archivos eliminados +Comment[et]=Sisaldab eemaldatud faile +Comment[fi]=Sisältää poistetut tiedostot +Comment[fr]=Contient les fichiers supprimés +Comment[gl]=Contén ficheiros eliminados. +Comment[he]=מכיל קבצים שנמחקו +Comment[is]=Inniheldur skrár sem hefur verið eytt +Comment[it]=Contiene i file rimossi +Comment[ja]=削除されたファイルを保管します +Comment[ko]=삭제된 파일 및 폴더가 있습니다 +Comment[lt]=Čia yra ištrinti failai +Comment[nl]=Bevat de verwijderde bestanden +Comment[nn]=Inneheld sletta filer +Comment[pa]=ਹਟਾਈਆਂ ਫਾਇਲਾਂ ਰੱਖਦਾ ਹੈ +Comment[pl]=Zawiera usunięte pliki +Comment[pt]=Contém os ficheiros removidos +Comment[pt_BR]=Contém os arquivos removidos +Comment[ru]=Содержит файлы, которые вы удалили +Comment[se]=Dáppe leat eret váldon fiillat +Comment[sk]=Obsahuje odstránené súbory +Comment[sl]=Vsebujejo odstranjene datoteke +Comment[sr]=Садржи уклоњене фајлове +Comment[sr@ijekavian]=Садржи уклоњене фајлове +Comment[sr@ijekavianlatin]=Sadrži uklonjene fajlove +Comment[sr@latin]=Sadrži uklonjene fajlove +Comment[sv]=Innehåller borttagna filer +Comment[tr]=Silinen dosyaları içerir +Comment[uk]=Містить вилучені файли +Comment[x-test]=xxContains removed filesxx +Comment[zh_CN]=储存已删除的文件 +Comment[zh_TW]=包含已移除的檔案 +Icon=user-trash-full +EmptyIcon=user-trash +Type=Link +URL=trash:/ +OnlyShowIn=KDE; + Index: kioslave/desktop/kio_desktop.h =================================================================== --- /dev/null +++ kioslave/desktop/kio_desktop.h @@ -0,0 +1,41 @@ +/* This file is part of the KDE project + Copyright (C) 2008, 2009 Fredrik Höglund + + 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 KIO_DESKTOP_H +#define KIO_DESKTOP_H + +#include + +class DesktopProtocol : public KIO::ForwardingSlaveBase +{ + Q_OBJECT +public: + DesktopProtocol(const QByteArray& protocol, const QByteArray &pool, const QByteArray &app); + ~DesktopProtocol() override; + +protected: + void checkLocalInstall(); + QString desktopFile(KIO::UDSEntry&) const; + bool rewriteUrl(const QUrl &url, QUrl &newUrl) override; + void listDir(const QUrl &url) override; + void prepareUDSEntry(KIO::UDSEntry &entry, bool listing=false) const override; + void rename(const QUrl &, const QUrl &, KIO::JobFlags flags) override; +}; + +#endif Index: kioslave/desktop/kio_desktop.cpp =================================================================== --- /dev/null +++ kioslave/desktop/kio_desktop.cpp @@ -0,0 +1,220 @@ +/* This file is part of the KDE project + Copyright (C) 2008, 2009 Fredrik Höglund + + 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. +*/ + +#include "kio_desktop.h" + +#include +#include +#include + +#include +#include + +#include +#include +#include +#include +#include +#include + +extern "C" +{ + int Q_DECL_EXPORT kdemain(int argc, char **argv) + { + // necessary to use other kio slaves + QCoreApplication app(argc, argv); + app.setApplicationName("kio_desktop"); + + // start the slave + DesktopProtocol slave(argv[1], argv[2], argv[3]); + slave.dispatchLoop(); + return 0; + } +} + +DesktopProtocol::DesktopProtocol(const QByteArray& protocol, const QByteArray &pool, const QByteArray &app) + : KIO::ForwardingSlaveBase(protocol, pool, app) +{ + checkLocalInstall(); + + QDBusInterface kded(QStringLiteral("org.kde.kded5"), QStringLiteral("/kded"), QStringLiteral("org.kde.kded5")); + kded.call(QStringLiteral("loadModule"), "desktopnotifier"); +} + +DesktopProtocol::~DesktopProtocol() +{ +} + +void DesktopProtocol::checkLocalInstall() +{ +#ifndef Q_WS_WIN + // We can't use QStandardPaths::writableLocation(QStandardPaths::DesktopLocation) here, since it returns the home dir + // if the desktop folder doesn't exist. + QString desktopPath = QDesktopServices::storageLocation(QDesktopServices::DesktopLocation); + if (desktopPath.isEmpty()) + desktopPath = QDir::homePath() + "/Desktop"; + + const QDir desktopDir(desktopPath); + bool desktopIsEmpty; + + // Create the desktop folder if it doesn't exist + if (!desktopDir.exists()) { + ::mkdir(QFile::encodeName(desktopPath), S_IRWXU); + desktopIsEmpty = true; + } else + desktopIsEmpty = desktopDir.entryList(QDir::AllEntries | QDir::Hidden | QDir::NoDotAndDotDot).isEmpty(); + + if (desktopIsEmpty) { + // Copy the .directory file + QFile::copy(QStandardPaths::locate(QStandardPaths::GenericDataLocation, QStringLiteral("kio_desktop/directory.desktop")), + desktopPath + "/.directory"); + + // Copy the trash link + QFile::copy(QStandardPaths::locate(QStandardPaths::GenericDataLocation, QStringLiteral("kio_desktop/directory.trash")), + desktopPath + "/trash.desktop"); + + // Copy the desktop links + QSet links; + const auto dirs = QStandardPaths::locateAll(QStandardPaths::GenericDataLocation, QStringLiteral("kio_desktop/DesktopLinks"), QStandardPaths::LocateDirectory); + for (const auto &dir : dirs) { + const auto fileNames = QDir(dir).entryList({QStringLiteral("*.desktop")}); + for (const auto &file : fileNames) { + links += file; + } + } + + foreach (const QString &link, links) { + const auto fullPath = QStandardPaths::locate(QStandardPaths::GenericDataLocation, QStringLiteral("kio_desktop/DesktopLinks/%1").arg(link)); + KDesktopFile file(fullPath); + if (!file.desktopGroup().readEntry("Hidden", false)) + QFile::copy(fullPath, QStringLiteral("%1/%2").arg(desktopPath, link)); + } + } +#endif +} + +bool DesktopProtocol::rewriteUrl(const QUrl &url, QUrl &newUrl) +{ + newUrl.setScheme(QStringLiteral("file")); + newUrl.setPath(QStandardPaths::writableLocation(QStandardPaths::DesktopLocation) + url.path()); + return true; +} + +void DesktopProtocol::listDir(const QUrl &url) +{ + KIO::ForwardingSlaveBase::listDir(url); + + QUrl actual; + rewriteUrl(url, actual); + + QDBusInterface kded(QStringLiteral("org.kde.kded5"), QStringLiteral("/modules/desktopnotifier"), QStringLiteral("org.kde.DesktopNotifier")); + kded.call(QStringLiteral("watchDir"), actual.path()); +} + +QString DesktopProtocol::desktopFile(KIO::UDSEntry &entry) const +{ + const QString name = entry.stringValue(KIO::UDSEntry::UDS_NAME); + if (name == QLatin1String(".") || name == QLatin1String("..")) + return QString(); + + QUrl url = processedUrl(); + url.setPath(QStringLiteral("%1/%2").arg(url.path(), name)); + + if (entry.isDir()) { + url.setPath(QStringLiteral("%1/.directory").arg(url.path())); + if (!QFileInfo::exists(url.path())) + return QString(); + + return url.path(); + } + + if (KDesktopFile::isDesktopFile(url.path())) + return url.path(); + + return QString(); +} + +void DesktopProtocol::prepareUDSEntry(KIO::UDSEntry &entry, bool listing) const +{ + ForwardingSlaveBase::prepareUDSEntry(entry, listing); + const QString path = desktopFile(entry); + + if (!path.isEmpty()) { + KDesktopFile file(path); + + const QString name = file.readName(); + if (!name.isEmpty()) + entry.insert(KIO::UDSEntry::UDS_DISPLAY_NAME, name); + + if (file.noDisplay() || !file.tryExec()) + entry.insert(KIO::UDSEntry::UDS_HIDDEN, 1); + } + + // Set the target URL to the local path + QUrl localUrl(QUrl::fromLocalFile(entry.stringValue(KIO::UDSEntry::UDS_LOCAL_PATH))); + entry.insert(KIO::UDSEntry::UDS_TARGET_URL, localUrl.toString()); +} + +void DesktopProtocol::rename(const QUrl &_src, const QUrl &_dest, KIO::JobFlags flags) +{ + Q_UNUSED(flags) + + if (_src == _dest) { + finished(); + return; + } + + QUrl src; + rewriteUrl(_src, src); + const QString srcPath = src.toLocalFile(); + + QUrl dest; + rewriteUrl(_dest, dest); + const QString destPath = dest.toLocalFile(); + + if (KDesktopFile::isDesktopFile(srcPath)) { + QString friendlyName; + + if (destPath.endsWith(QLatin1String(".desktop"))) { + const QString fileName = dest.fileName(); + friendlyName = KIO::decodeFileName(fileName.left(fileName.length() - 8)); + } else { + friendlyName = KIO::decodeFileName(dest.fileName()); + } + + // Update the value of the Name field in the file. + KDesktopFile file(src.toLocalFile()); + KConfigGroup cg(file.desktopGroup()); + cg.writeEntry("Name", friendlyName); + cg.writeEntry("Name", friendlyName, KConfigGroup::Persistent | KConfigGroup::Localized); + cg.sync(); + } + + if (QFile(srcPath).rename(destPath)) { +#if KIO_VERSION >= QT_VERSION_CHECK(5, 20, 0) + org::kde::KDirNotify::emitFileRenamedWithLocalPath(_src, _dest, destPath); +#else + org::kde::KDirNotify::emitFileRenamed(_src, _dest); +#endif + finished(); + } else { + error(KIO::ERR_CANNOT_RENAME, srcPath); + } +} + Index: kioslave/desktop/tests/CMakeLists.txt =================================================================== --- /dev/null +++ kioslave/desktop/tests/CMakeLists.txt @@ -0,0 +1,6 @@ +add_executable(testdesktop kio_desktop_test.cpp) +target_link_libraries(testdesktop KF5::KIOWidgets KF5::Solid Qt5::Test) + +ecm_mark_as_test(testdesktop) +add_test(testdesktop testdesktop) + Index: kioslave/desktop/tests/kio_desktop_test.cpp =================================================================== --- /dev/null +++ kioslave/desktop/tests/kio_desktop_test.cpp @@ -0,0 +1,131 @@ +/* This file is part of the KDE project + Copyright (C) 2009 David Faure + + 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. +*/ + +#include +#include +#include +#include +#include +#include +#include + +class TestDesktop : public QObject +{ + Q_OBJECT + +public: + TestDesktop() {} + +private Q_SLOTS: + void initTestCase() + { + setenv( "KDE_FORK_SLAVES", "yes", true ); + + //make KIOs use test mode too + setenv("KIOSLAVE_ENABLE_TESTMODE", "1", 1); + QStandardPaths::setTestModeEnabled(true); + + m_desktopPath = QStandardPaths::writableLocation(QStandardPaths::DesktopLocation); + m_testFileName = QLatin1String("kio_desktop_test_file"); + } + void cleanupTestCase() + { + QFile::remove(m_desktopPath + '/' + m_testFileName); + QFile::remove(m_desktopPath + '/' + m_testFileName + ".part"); + } + + void testCopyToDesktop() + { + QTemporaryFile tempFile; + QVERIFY(tempFile.open()); + tempFile.write( "Hello world\n", 12 ); + QString fileName = tempFile.fileName(); + tempFile.close(); + KIO::Job* job = KIO::file_copy(QUrl::fromLocalFile(fileName), QUrl("desktop:/" + m_testFileName), -1, KIO::HideProgressInfo); + job->setUiDelegate(0); + QVERIFY(job->exec()); + QVERIFY(QFile::exists(m_desktopPath + '/' + m_testFileName)); + } + + void testMostLocalUrl() // relies on testCopyToDesktop being run before + { + const QUrl desktopUrl("desktop:/" + m_testFileName); + const QString filePath(m_desktopPath + '/' + m_testFileName); + KIO::StatJob* job = KIO::mostLocalUrl(desktopUrl, KIO::HideProgressInfo); + QVERIFY(job); + bool ok = job->exec(); + QVERIFY(ok); + QCOMPARE(job->mostLocalUrl().toLocalFile(), filePath); + } + + void testRename_data() + { + QTest::addColumn("withDirListerCache"); + QTest::addColumn("srcFile"); + QTest::addColumn("destFile"); + + const QString orig = "desktop:/" + m_testFileName; + const QString part = orig + ".part"; + QTest::newRow("from orig to .part") << false << orig << part; + QTest::newRow("from .part to orig") << false << part << orig; + // Warnings: all tests without dirlister cache should above this line + // and all tests with it should be below - the cache stays forever once it exists. + QTest::newRow("from orig to .part, with cache") << true << orig << part; + QTest::newRow("from .part to orig, with cache (#218719)") << true << part << orig; + } + + void testRename() // relies on testCopyToDesktop being run before + { + QFETCH(bool, withDirListerCache); + QFETCH(QString, srcFile); + QFETCH(QString, destFile); + + if (withDirListerCache) { + KDirLister lister; + lister.openUrl(QUrl(QStringLiteral("desktop:/"))); + QEventLoop eventLoop; + connect(&lister, static_cast(&KDirLister::completed), &eventLoop, &QEventLoop::quit); + eventLoop.exec(QEventLoop::ExcludeUserInputEvents); + } + + const QUrl srcUrl = QUrl(srcFile); + const QUrl destUrl = QUrl(destFile); + + const QString srcFilePath(m_desktopPath + srcUrl.path()); + QVERIFY(QFile::exists(srcFilePath)); + const QString destFilePath(m_desktopPath + destUrl.path()); + QVERIFY(!QFile::exists(destFilePath)); + + KIO::CopyJob* job = KIO::move(srcUrl, destUrl, KIO::HideProgressInfo); + job->setUiDelegate(0); + QVERIFY(job); + bool ok = job->exec(); + QVERIFY(ok); + QVERIFY(!QFile::exists(srcFilePath)); + QVERIFY(QFile::exists(destFilePath)); + } + +private: + QString m_desktopPath; + QString m_testFileName; +}; + +QTEST_GUILESS_MAIN(TestDesktop) + +#include "kio_desktop_test.moc" Index: kioslave/remote/CMakeLists.txt =================================================================== --- /dev/null +++ kioslave/remote/CMakeLists.txt @@ -0,0 +1,19 @@ +add_definitions(-DTRANSLATION_DOMAIN=\"kio_remote\") + +add_subdirectory( kdedmodule ) + +set(kio_remote_SRCS + kio_remote.cpp + remoteimpl.cpp + ) + +ecm_qt_declare_logging_category(kio_remote_SRCS HEADER debug.h + IDENTIFIER KIOREMOTE_LOG + CATEGORY_NAME log_kioremote + DEFAULT_SEVERITY Info) + +add_library(kio_remote MODULE ${kio_remote_SRCS}) +target_link_libraries(kio_remote KF5::KIOCore KF5::I18n) + +install(TARGETS kio_remote DESTINATION ${KDE_INSTALL_PLUGINDIR} ) +install( FILES remote.protocol DESTINATION ${KDE_INSTALL_KSERVICES5DIR} ) Index: kioslave/remote/Messages.sh =================================================================== --- /dev/null +++ kioslave/remote/Messages.sh @@ -0,0 +1,2 @@ +#! /usr/bin/env bash +$XGETTEXT `find . -name "*.cc" -o -name "*.cpp" -o -name "*.h"` -o $podir/kio_remote.pot Index: kioslave/remote/kdedmodule/CMakeLists.txt =================================================================== --- /dev/null +++ kioslave/remote/kdedmodule/CMakeLists.txt @@ -0,0 +1,6 @@ +add_library(remotedirnotify MODULE remotedirnotify.cpp remotedirnotifymodule.cpp ../debug.cpp) +kcoreaddons_desktop_to_json(remotedirnotify remotedirnotify.desktop) + +target_link_libraries(remotedirnotify KF5::DBusAddons KF5::KIOCore) + +install(TARGETS remotedirnotify DESTINATION ${KDE_INSTALL_PLUGINDIR}/kf5/kded ) Index: kioslave/remote/kdedmodule/remotedirnotify.h =================================================================== --- /dev/null +++ kioslave/remote/kdedmodule/remotedirnotify.h @@ -0,0 +1,43 @@ +/* This file is part of the KDE Project + Copyright (c) 2004 Kévin Ottens + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License version 2 as published by the Free Software Foundation. + + 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 REMOTEDIRNOTIFY_H +#define REMOTEDIRNOTIFY_H + +#include +#include + +class RemoteDirNotify : public QObject +{ +Q_OBJECT + +public: + RemoteDirNotify(); + +private slots: + void FilesAdded (const QString &directory); + void FilesRemoved (const QStringList &fileList); + void FilesChanged (const QStringList &fileList); + +private: + QUrl toRemoteURL(const QUrl &url); + QList toRemoteURLList(const QStringList &list); + QUrl m_baseURL; +}; + +#endif Index: kioslave/remote/kdedmodule/remotedirnotify.cpp =================================================================== --- /dev/null +++ kioslave/remote/kdedmodule/remotedirnotify.cpp @@ -0,0 +1,136 @@ +/* This file is part of the KDE Project + Copyright (c) 2004 Kévin Ottens + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License version 2 as published by the Free Software Foundation. + + 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. +*/ + +#include "remotedirnotify.h" + +#include "../debug.h" +#include +#include +#include + +#include + +RemoteDirNotify::RemoteDirNotify() +{ + const QString path = QStringLiteral("%1/remoteview").arg(QStandardPaths::writableLocation(QStandardPaths::GenericDataLocation)); + m_baseURL.setPath(path); + + QDBusConnection::sessionBus().connect(QString(), QString(), QStringLiteral("org.kde.KDirNotify"), + QStringLiteral("FilesAdded"), this, SLOT(FilesAdded(QString))); + QDBusConnection::sessionBus().connect(QString(), QString(), QStringLiteral("org.kde.KDirNotify"), + QStringLiteral("FilesRemoved"), this, SLOT(FilesRemoved(QStringList))); + QDBusConnection::sessionBus().connect(QString(), QString(), QStringLiteral("org.kde.KDirNotify"), + QStringLiteral("FilesChanged"), this, SLOT(FilesChanged(QStringList))); +} + +QUrl RemoteDirNotify::toRemoteURL(const QUrl &url) +{ + qCDebug(KIOREMOTE_LOG) << "RemoteDirNotify::toRemoteURL(" << url << ")"; + if ( m_baseURL.isParentOf(url) ) + { + QString path = QDir(m_baseURL.path()).relativeFilePath(url.path()); + QUrl result; + result.setScheme(QStringLiteral("remote")); + result.setPath(path); + result.setPath(QDir::cleanPath(result.path())); + qCDebug(KIOREMOTE_LOG) << "result => " << result; + return result; + } + + qCDebug(KIOREMOTE_LOG) << "result => QUrl()"; + return QUrl(); +} + +QList RemoteDirNotify::toRemoteURLList(const QStringList &list) +{ + QList urls; + for (const QString &file : list) { + QUrl url = toRemoteURL(QUrl::fromLocalFile(file)); + if (url.isValid()) { + urls.append(url); + } + } + + return urls; +} + +void RemoteDirNotify::FilesAdded(const QString &directory) +{ + qCDebug(KIOREMOTE_LOG) << "RemoteDirNotify::FilesAdded"; + + QUrl new_dir = toRemoteURL(QUrl::fromLocalFile(directory)); + + if (new_dir.isValid()) + { + org::kde::KDirNotify::emitFilesAdded(new_dir); + } +} + +// This hack is required because of the way we manage .desktop files with +// Forwarding Slaves, their URL is out of the ioslave (most remote:/ files +// have a file:/ based UDS_URL so that they are executed correctly. +// Hence, FilesRemoved and FilesChanged does nothing... We're forced to use +// FilesAdded to re-list the modified directory. +inline void evil_hack(const QList &list) +{ + QList notified; + + QList::const_iterator it = list.begin(); + QList::const_iterator end = list.end(); + + for (; it!=end; ++it) + { + QUrl url = KIO::upUrl(*it); + + if (!notified.contains(url)) + { + org::kde::KDirNotify::emitFilesAdded(url); + notified.append(url); + } + } +} + + +void RemoteDirNotify::FilesRemoved(const QStringList &fileList) +{ + qCDebug(KIOREMOTE_LOG) << "RemoteDirNotify::FilesRemoved"; + + QList new_list = toRemoteURLList(fileList); + + if (!new_list.isEmpty()) + { + //KDirNotify_stub notifier("*", "*"); + //notifier.FilesRemoved( new_list ); + evil_hack(new_list); + } +} + +void RemoteDirNotify::FilesChanged(const QStringList &fileList) +{ + qCDebug(KIOREMOTE_LOG) << "RemoteDirNotify::FilesChanged"; + + QList new_list = toRemoteURLList(fileList); + + if (!new_list.isEmpty()) + { + //KDirNotify_stub notifier("*", "*"); + //notifier.FilesChanged( new_list ); + evil_hack(new_list); + } +} + Index: kioslave/remote/kdedmodule/remotedirnotify.desktop =================================================================== --- /dev/null +++ kioslave/remote/kdedmodule/remotedirnotify.desktop @@ -0,0 +1,103 @@ +[Desktop Entry] +Type=Service +Name=Remote URL Change Notifier +Name[bs]=Udaljeni URL izvještavač o promjenama +Name[ca]=Notificador de canvi d'URL remot +Name[ca@valencia]=Notificador de canvi d'URL remot +Name[cs]=Démon upozorňování na vzdálená URL +Name[da]=Bekendtgørelse af ændring på eksterne URL'er +Name[de]=Überwachung für Dateien auf Fremdrechnern +Name[el]=Εργαλείο ειδοποιήσεων αλλαγής απομακρυσμένου URL +Name[en_GB]=Remote URL Change Notifier +Name[es]=Notificador de cambios en URL remotos +Name[et]=Mujalasuva URL-i muutumise teadustaja +Name[fi]=Etäverkko-osoitteiden muutosten ilmoitin +Name[fr]=Avertisseur de changement d'URL distante +Name[gl]=Notificador de cambios en URL remotas +Name[he]=מעקב אחר שינויים בכתובת מרוחקת +Name[hr]=Glasnik promjena na udaljenom URL-u +Name[hu]=Távoli URL-címváltozás értesítő +Name[ia]=Notificator remote de cambio de URL +Name[id]=Notifikasi Ubah URL Jarak Jauh +Name[is]=Tilkynningar á slóðabreytingum (URL) +Name[it]=Notificatore del cambiamento dell'URL remoto +Name[ja]=リモート URL 変更通知 +Name[ko]=원격 URL 변경 알림이 +Name[lt]=Nutolusio URL pasikeitimo priminimo programa +Name[nb]=Påminner for endringer i eksterne URL-er +Name[nds]=Feern-URL-Ännernbescheed +Name[nl]=Notificatie van wijziging in URL-adres op afstand +Name[nn]=Varsling for endringar på nettadresser +Name[pl]=Powiadamianie o zmianie zdalnego adresu URL +Name[pt]=Notificador da Alteração de URLs Remotos +Name[pt_BR]=Notificador da alteração de URLs remotas +Name[ru]=Слежение за изменениями URL +Name[sk]=Monitor zmien vzdialených URL +Name[sl]=Obvestilnik sprememb oddaljenega URL-ja +Name[sr]=Извештавач о изменама удаљених УРЛ‑ова +Name[sr@ijekavian]=Извјештавач о изменама удаљених УРЛ‑ова +Name[sr@ijekavianlatin]=Izvještavač o izmenama udaljenih URL‑ova +Name[sr@latin]=Izveštavač o izmenama udaljenih URL‑ova +Name[sv]=Underrättelse om ändring av fjärrwebbadresser +Name[tr]=Uzak Adres Değiştirme Bildiricisi +Name[uk]=Сповіщення про зміну віддаленої адреси (URL) +Name[x-test]=xxRemote URL Change Notifierxx +Name[zh_CN]=远程 URL 更改通知器 +Name[zh_TW]=遠端網址變更通知程式 +Comment=Provides change notification for network folders +Comment[bn]=নেটওয়ার্ক ফোল্ডার-এ পরিবর্তনের সূচনা দেয় +Comment[bs]=Ispostavlja obavještenja o izmjenama u mrežnim fasciklama +Comment[ca]=Proporciona notificacions de canvis en carpetes de xarxa +Comment[ca@valencia]=Proporciona notificacions de canvis en carpetes de xarxa +Comment[cs]=Poskytuje oznamování o změnách síťových složek +Comment[da]=Giver bekendtgørelse af ændringer af netværksmapper +Comment[de]=Benachrichtigt den Anwender über Änderungen an Dateien in Netzwerkordnern. +Comment[el]=Παρέχει ειδοποίηση αλλαγών για δικτυακούς φακέλους +Comment[en_GB]=Provides change notification for network folders +Comment[eo]=Ĝi provizas atentigojn pri ŝanĝoj de retaj dosierujoj +Comment[es]=Proporciona notificaciones sobre cambios en carpetas de red +Comment[et]=Võrgukataloogide muutuste märguanded +Comment[fa]=هشدار تغییر را برای پوشه‌های شبکه ارائه میدهد +Comment[fi]=Tarjoaa ilmoituksia verkkokansioiden muutoksista +Comment[fr]=Fournit les notifications de modification pour les dossiers du réseau +Comment[ga]=Cuireann sé in iúl duit nuair a athraíonn fillteán líonra +Comment[gl]=Fornece notificacións dos cambios en cartafoles en rede +Comment[gu]=નેટવર્ક ફોલ્ડરો માટે ફેરફાર નોંધણી પૂરી પાડે છે +Comment[he]=מתריע על שינויים בתיקיות רשת +Comment[hi]=संजाल फ़ोल्डर्स के लिए परिवर्तन अधिसूचना प्रदान करता है +Comment[hr]=Omogućuje obavještavanje o promjenama na mrežnim mapama +Comment[hu]=Értesítést küld a hálózati mappák változásairól +Comment[ia]=Il forni notification de cambio pro dossieres de rete +Comment[id]=Menyediakan notifikasi perubahan untuk folder jaringan +Comment[is]=Tilkynningaforrit fyrir breytingar á fjartengdum netmöppum +Comment[it]=Fornisce notifiche di modifica per le cartelle di rete +Comment[ja]=ネットワークフォルダの変更通知を提供します +Comment[ko]=네트워크 폴더의 변경 사항 알림 +Comment[lt]=Pranešimai naudotojui apie pasikeitimus tinklo aplankuose +Comment[nb]=Gir endringsvarslinger for nettverksmapper +Comment[nds]=Stellt Bescheden över Ännern vun Nettwarkornern praat +Comment[nl]=Levert notificatie voor wijzigingen in netwerkmappen +Comment[nn]=Gjev endringsvarslingar for nettverksmapper +Comment[pa]=ਨੈੱਟਵਰਕ ਫੋਲਡਰਾਂ ਲਈ ਤਬਦੀਲੀ ਨੋਟੀਫਿਕੇਸ਼ਨ ਦਿੰਦਾ ਹੈ +Comment[pl]=Udostępnia powiadomienia o zmianach w katalogach sieciowych +Comment[pt]=Fornece notificações de alterações para as pastas de rede +Comment[pt_BR]=Fornece notificações de alterações para pastas de rede +Comment[ru]=Отслеживание изменений в сетевых папках +Comment[sk]=Poskytuje upozornenia o zmenách sieťových priečinkov +Comment[sl]=Ponuja obvestila o spremembah omrežnih map +Comment[sr]=Даје обавештења о изменама за мрежне фасцикле +Comment[sr@ijekavian]=Даје обавјештења о изменама за мрежне фасцикле +Comment[sr@ijekavianlatin]=Daje obavještenja o izmenama za mrežne fascikle +Comment[sr@latin]=Daje obaveštenja o izmenama za mrežne fascikle +Comment[sv]=Tillhandahåller ändringsunderrättelser för nätverkskataloger +Comment[tr]=Ağ klasörleri için değişiklik bildirimleri sağlar +Comment[uk]=Сповіщення про зміну стану мережевих тек +Comment[vi]=Cung cấp thông báo thay đổi cho các thư mục mạng +Comment[x-test]=xxProvides change notification for network foldersxx +Comment[zh_CN]=为网络文件夹提供更改通知 +Comment[zh_TW]=提供網路資料夾的變更通知 +X-KDE-ServiceTypes=KDEDModule +X-KDE-Library=remotedirnotify +X-KDE-DBus-ModuleName=remotedirnotify +X-KDE-Kded-load-on-demand=true +X-KDE-Kded-autoload=true Index: kioslave/remote/kdedmodule/remotedirnotifymodule.h =================================================================== --- /dev/null +++ kioslave/remote/kdedmodule/remotedirnotifymodule.h @@ -0,0 +1,35 @@ +/* This file is part of the KDE Project + Copyright (c) 2004 Kévin Ottens + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License version 2 as published by the Free Software Foundation. + + 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 REMOTEDIRNOTIFYMODULE_H +#define REMOTEDIRNOTIFYMODULE_H + +#include + +#include "remotedirnotify.h" + +class RemoteDirNotifyModule : public KDEDModule +{ + Q_OBJECT +public: + RemoteDirNotifyModule(QObject* parent, const QList&); +private: + RemoteDirNotify notifier; +}; + +#endif Index: kioslave/remote/kdedmodule/remotedirnotifymodule.cpp =================================================================== --- /dev/null +++ kioslave/remote/kdedmodule/remotedirnotifymodule.cpp @@ -0,0 +1,33 @@ +/* This file is part of the KDE Project + Copyright (c) 2004 Kévin Ottens + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License version 2 as published by the Free Software Foundation. + + 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. +*/ + +#include "remotedirnotifymodule.h" + +#include +//#include + +K_PLUGIN_FACTORY_WITH_JSON(RemoteDirNotifyFactory, + "remotedirnotify.json", + registerPlugin();) + +RemoteDirNotifyModule::RemoteDirNotifyModule(QObject* parent, const QList&) + : KDEDModule(parent) +{ +} + +#include "remotedirnotifymodule.moc" Index: kioslave/remote/kio_remote.h =================================================================== --- /dev/null +++ kioslave/remote/kio_remote.h @@ -0,0 +1,45 @@ +/* This file is part of the KDE project + Copyright (c) 2004 Kevin Ottens + + 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 KIO_REMOTE_H +#define KIO_REMOTE_H + +#include +#include "remoteimpl.h" + +class RemoteProtocol : public KIO::SlaveBase +{ +public: + RemoteProtocol(const QByteArray &protocol, const QByteArray &pool, + const QByteArray &app); + ~RemoteProtocol() override; + void listDir(const QUrl &url) override; + void stat(const QUrl &url) override; + void del(const QUrl &url, bool isFile) override; + void get(const QUrl &url) override; + void rename(const QUrl &src, const QUrl &dest, KIO::JobFlags flags) override; + void symlink(const QString &target, const QUrl &dest, KIO::JobFlags flags) override; + +private: + void listRoot(); + + RemoteImpl m_impl; +}; + +#endif Index: kioslave/remote/kio_remote.cpp =================================================================== --- /dev/null +++ kioslave/remote/kio_remote.cpp @@ -0,0 +1,234 @@ +/* This file is part of the KDE project + Copyright (c) 2004 Kevin Ottens + + 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. +*/ + +#include "kio_remote.h" +#include "debug.h" +#include + +#include + +extern "C" { + int Q_DECL_EXPORT kdemain( int argc, char **argv ) + { + // necessary to use other kio slaves + QCoreApplication app(argc, argv); + app.setApplicationName("kio_remote"); + + // start the slave + RemoteProtocol slave( argv[1], argv[2], argv[3] ); + slave.dispatchLoop(); + return 0; + } +} + + +RemoteProtocol::RemoteProtocol(const QByteArray &protocol, + const QByteArray &pool, const QByteArray &app) + : SlaveBase(protocol, pool, app) +{ +} + +RemoteProtocol::~RemoteProtocol() +{ +} + +void RemoteProtocol::listDir(const QUrl &url) +{ + qCDebug(KIOREMOTE_LOG) << "RemoteProtocol::listDir: " << url; + + if ( url.path().length() <= 1 ) + { + listRoot(); + return; + } + + int second_slash_idx = url.path().indexOf( '/', 1 ); + const QString root_dirname = url.path().mid( 1, second_slash_idx-1 ); + + QUrl target = m_impl.findBaseURL( root_dirname ); + qCDebug(KIOREMOTE_LOG) << "possible redirection target : " << target; + if( target.isValid() ) + { + if ( second_slash_idx < 0 ) { + second_slash_idx = url.path().size(); + } + target = target.adjusted(QUrl::StripTrailingSlash); + target.setPath(target.path() + '/' + ( url.path().remove(0, second_slash_idx) )); + qCDebug(KIOREMOTE_LOG) << "complete redirection target : " << target; + redirection(target); + finished(); + return; + } + + error(KIO::ERR_MALFORMED_URL, url.toDisplayString()); +} + +void RemoteProtocol::listRoot() +{ + KIO::UDSEntry entry; + + KIO::UDSEntryList remote_entries; + m_impl.listRoot(remote_entries); + + totalSize(remote_entries.count()+2); + + m_impl.createTopLevelEntry(entry); + listEntry(entry); + + if(m_impl.createWizardEntry(entry)) + listEntry(entry); + + KIO::UDSEntryList::ConstIterator it = remote_entries.constBegin(); + const KIO::UDSEntryList::ConstIterator end = remote_entries.constEnd(); + for(; it!=end; ++it) + { + listEntry(*it); + } + + entry.clear(); + finished(); +} + +void RemoteProtocol::stat(const QUrl &url) +{ + qCDebug(KIOREMOTE_LOG) << "RemoteProtocol::stat: " << url; + + QString path = url.path(); + if ( path.isEmpty() || path == QLatin1String("/") ) + { + // The root is "virtual" - it's not a single physical directory + KIO::UDSEntry entry; + m_impl.createTopLevelEntry( entry ); + statEntry( entry ); + finished(); + return; + } + + if (m_impl.isWizardURL(url)) + { + KIO::UDSEntry entry; + if (m_impl.createWizardEntry(entry)) + { + statEntry(entry); + finished(); + } + else + { + error(KIO::ERR_DOES_NOT_EXIST, url.toDisplayString()); + } + return; + } + + int second_slash_idx = url.path().indexOf( '/', 1 ); + const QString root_dirname = url.path().mid( 1, second_slash_idx-1 ); + + if ( second_slash_idx==-1 || ( (int)url.path().length() )==second_slash_idx+1 ) + { + KIO::UDSEntry entry; + if (m_impl.statNetworkFolder(entry, root_dirname)) + { + statEntry(entry); + finished(); + return; + } + } + else + { + QUrl target = m_impl.findBaseURL( root_dirname ); + qCDebug(KIOREMOTE_LOG) << "possible redirection target : " << target; + if ( target.isValid() ) + { + if ( second_slash_idx < 0 ) { + second_slash_idx = url.path().size(); + } + qCDebug(KIOREMOTE_LOG) << "complete redirection target : " << target; + target = target.adjusted(QUrl::StripTrailingSlash); + target.setPath(target.path() + '/' + ( url.path().remove( 0, second_slash_idx ) )); + redirection( target ); + finished(); + return; + } + } + + error(KIO::ERR_MALFORMED_URL, url.toDisplayString()); +} + +void RemoteProtocol::del(const QUrl &url, bool /*isFile*/) +{ + qCDebug(KIOREMOTE_LOG) << "RemoteProtocol::del: " << url; + + if (!m_impl.isWizardURL(url) + && m_impl.deleteNetworkFolder(url.fileName())) + { + finished(); + return; + } + + error(KIO::ERR_CANNOT_DELETE, url.toDisplayString()); +} + +void RemoteProtocol::get(const QUrl &url) +{ + qCDebug(KIOREMOTE_LOG) << "RemoteProtocol::get: " << url; + + const QString file = m_impl.findDesktopFile( url.fileName() ); + qCDebug(KIOREMOTE_LOG) << "desktop file : " << file; + + if (!file.isEmpty()) + { + QUrl desktop; + desktop.setPath(file); + + redirection(desktop); + finished(); + return; + } + + error(KIO::ERR_MALFORMED_URL, url.toDisplayString()); +} + +void RemoteProtocol::rename(const QUrl &src, const QUrl &dest, + KIO::JobFlags flags) +{ + if (src.scheme()!=QLatin1String("remote") || dest.scheme()!=QLatin1String("remote") + || m_impl.isWizardURL(src) || m_impl.isWizardURL(dest)) + { + error(KIO::ERR_UNSUPPORTED_ACTION, src.toDisplayString()); + return; + } + + if (m_impl.renameFolders(src.fileName(), dest.fileName(), flags & KIO::Overwrite)) + { + finished(); + return; + } + + error(KIO::ERR_CANNOT_RENAME, src.toDisplayString()); +} + +void RemoteProtocol::symlink(const QString &target, const QUrl &dest, KIO::JobFlags flags) +{ + if (m_impl.changeFolderTarget(dest.fileName(), target, flags & KIO::Overwrite)) + { + finished(); + return; + } + + error(KIO::ERR_CANNOT_SYMLINK, dest.toDisplayString()); +} Index: kioslave/remote/remote.protocol =================================================================== --- /dev/null +++ kioslave/remote/remote.protocol @@ -0,0 +1,17 @@ +[Protocol] +exec=kio_remote +protocol=remote +input=none +output=filesystem +listing=Name,Type,Size,Date,AccessDate,Access,Owner,Group,Link +reading=true +writing=false +makedir=false +deleting=true +linking=true +moving=true +Icon=folder-remote +maxInstances=4 +#TODO DocPath=kioslave/file.html +Class=:local +deleteRecursive=true Index: kioslave/remote/remoteimpl.h =================================================================== --- /dev/null +++ kioslave/remote/remoteimpl.h @@ -0,0 +1,56 @@ +/* This file is part of the KDE project + Copyright (c) 2004 Kevin Ottens + + 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 REMOTEIMPL_H +#define REMOTEIMPL_H + +#include +#include +#include + + + +class RemoteImpl +{ +public: + RemoteImpl(); + + void createTopLevelEntry(KIO::UDSEntry &entry) const; + bool createWizardEntry(KIO::UDSEntry &entry) const; + bool isWizardURL(const QUrl &url) const; + bool statNetworkFolder(KIO::UDSEntry &entry, const QString &filename) const; + + void listRoot(KIO::UDSEntryList& list) const; + + QUrl findBaseURL(const QString &filename) const; + QString findDesktopFile(const QString &filename) const; + + bool deleteNetworkFolder(const QString &filename) const; + bool renameFolders(const QString &src, const QString &dest, + bool overwrite) const; + bool changeFolderTarget(const QString &src, const QString &target, + bool overwrite) const; + +private: + bool findDirectory(const QString &filename, QString &directory) const; + void createEntry(KIO::UDSEntry& entry, const QString &directory, + const QString &file) const; +}; + +#endif Index: kioslave/remote/remoteimpl.cpp =================================================================== --- /dev/null +++ kioslave/remote/remoteimpl.cpp @@ -0,0 +1,311 @@ +/* This file is part of the KDE project + Copyright (c) 2004 Kevin Ottens + + 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. +*/ + +#include "remoteimpl.h" + +#include "debug.h" +#include +#include +#include +#include + +#include +#include + +#include + +#define WIZARD_URL "remote:/x-wizard_service.desktop" +#define WIZARD_SERVICE "org.kde.knetattach" + +RemoteImpl::RemoteImpl() +{ + const QString path = QStringLiteral("%1/remoteview").arg(QStandardPaths::writableLocation(QStandardPaths::GenericDataLocation)); + + QDir dir = path; + if (!dir.exists()) + { + dir.cdUp(); + dir.mkdir(QStringLiteral("remoteview")); + } +} + +void RemoteImpl::listRoot(KIO::UDSEntryList &list) const +{ + qCDebug(KIOREMOTE_LOG) << "RemoteImpl::listRoot"; + + QStringList names_found; + const QStringList dirList = QStandardPaths::locateAll(QStandardPaths::GenericDataLocation, QStringLiteral("remoteview"), QStandardPaths::LocateDirectory); + + QStringList::ConstIterator dirpath = dirList.constBegin(); + const QStringList::ConstIterator end = dirList.constEnd(); + for(; dirpath!=end; ++dirpath) + { + QDir dir = *dirpath; + if (!dir.exists()) continue; + + const QStringList filenames + = dir.entryList( QDir::Files | QDir::Readable ); + + + KIO::UDSEntry entry; + + QStringList::ConstIterator name = filenames.constBegin(); + QStringList::ConstIterator endf = filenames.constEnd(); + + for(; name!=endf; ++name) + { + if (!names_found.contains(*name)) + { + entry.clear(); + createEntry(entry, *dirpath, *name); + list.append(entry); + names_found.append(*name); + } + } + } +} + +bool RemoteImpl::findDirectory(const QString &filename, QString &directory) const +{ + qCDebug(KIOREMOTE_LOG) << "RemoteImpl::findDirectory"; + + const QStringList dirList = QStandardPaths::locateAll(QStandardPaths::GenericDataLocation, QStringLiteral("remoteview"), QStandardPaths::LocateDirectory); + + QStringList::ConstIterator dirpath = dirList.constBegin(); + const QStringList::ConstIterator end = dirList.constEnd(); + for(; dirpath!=end; ++dirpath) + { + QDir dir = *dirpath; + if (!dir.exists()) continue; + + QStringList filenames + = dir.entryList( QDir::Files | QDir::Readable ); + + + KIO::UDSEntry entry; + + QStringList::ConstIterator name = filenames.constBegin(); + QStringList::ConstIterator endf = filenames.constEnd(); + + for(; name!=endf; ++name) + { + if (*name==filename) + { + directory = *dirpath; + return true; + } + } + } + + return false; +} + +QString RemoteImpl::findDesktopFile(const QString &filename) const +{ + qCDebug(KIOREMOTE_LOG) << "RemoteImpl::findDesktopFile"; + + QString directory; + if (findDirectory(filename+".desktop", directory)) + { + return directory+filename+".desktop"; + } + + return QString(); +} + +QUrl RemoteImpl::findBaseURL(const QString &filename) const +{ + qCDebug(KIOREMOTE_LOG) << "RemoteImpl::findBaseURL"; + + const QString file = findDesktopFile(filename); + if (!file.isEmpty()) + { + KDesktopFile desktop( file ); + return QUrl::fromLocalFile(desktop.readUrl()); + } + + return QUrl(); +} + + +void RemoteImpl::createTopLevelEntry(KIO::UDSEntry &entry) const +{ + entry.clear(); + entry.insert( KIO::UDSEntry::UDS_NAME, QString::fromLatin1(".")); + entry.insert( KIO::UDSEntry::UDS_FILE_TYPE, S_IFDIR); + entry.insert( KIO::UDSEntry::UDS_ACCESS, 0777); + entry.insert( KIO::UDSEntry::UDS_MIME_TYPE, QString::fromLatin1("inode/directory")); + entry.insert( KIO::UDSEntry::UDS_ICON_NAME, QString::fromLatin1("folder-remote")); + entry.insert( KIO::UDSEntry::UDS_USER, QString::fromLatin1("root")); + entry.insert( KIO::UDSEntry::UDS_GROUP, QString::fromLatin1("root")); +} + +static QUrl findWizardRealURL() +{ + QUrl url; + KService::Ptr service = KService::serviceByDesktopName(WIZARD_SERVICE); + + if (service && service->isValid()) + { + url.setPath(QStandardPaths::locate(QStandardPaths::ApplicationsLocation, + QStringLiteral("%1.desktop").arg(WIZARD_SERVICE))); + } + + return url; +} + +bool RemoteImpl::createWizardEntry(KIO::UDSEntry &entry) const +{ + entry.clear(); + + QUrl url = findWizardRealURL(); + + if (!url.isValid()) + { + return false; + } + + entry.insert( KIO::UDSEntry::UDS_NAME, i18n("Add Network Folder")); + entry.insert( KIO::UDSEntry::UDS_FILE_TYPE, S_IFREG); + entry.insert( KIO::UDSEntry::UDS_URL, QString::fromLatin1(WIZARD_URL) ); + entry.insert( KIO::UDSEntry::UDS_LOCAL_PATH, url.path()); + entry.insert( KIO::UDSEntry::UDS_ACCESS, 0500); + entry.insert( KIO::UDSEntry::UDS_MIME_TYPE, QString::fromLatin1("application/x-desktop")); + entry.insert( KIO::UDSEntry::UDS_ICON_NAME, QString::fromLatin1("folder-new")); + + return true; +} + +bool RemoteImpl::isWizardURL(const QUrl &url) const +{ + return url==QUrl(WIZARD_URL); +} + + +void RemoteImpl::createEntry(KIO::UDSEntry &entry, + const QString &directory, + const QString &file) const +{ + qCDebug(KIOREMOTE_LOG) << "RemoteImpl::createEntry"; + + QString dir = directory; + if (!dir.endsWith(QLatin1Char('/'))) { + dir += QLatin1Char('/'); + } + KDesktopFile desktop(dir + file); + + qCDebug(KIOREMOTE_LOG) << "path = " << directory << file; + + entry.clear(); + + QString new_filename = file; + new_filename.truncate( file.length()-8); + + entry.insert( KIO::UDSEntry::UDS_NAME, desktop.readName()); + entry.insert( KIO::UDSEntry::UDS_URL, "remote:/"+new_filename); + + entry.insert( KIO::UDSEntry::UDS_FILE_TYPE, S_IFDIR); + entry.insert( KIO::UDSEntry::UDS_ACCESS, 0500); + entry.insert( KIO::UDSEntry::UDS_MIME_TYPE, QString::fromLatin1("inode/directory")); + + const QString icon = desktop.readIcon(); + entry.insert( KIO::UDSEntry::UDS_ICON_NAME, icon); + entry.insert( KIO::UDSEntry::UDS_LINK_DEST, desktop.readUrl()); + entry.insert( KIO::UDSEntry::UDS_TARGET_URL, desktop.readUrl()); +} + +bool RemoteImpl::statNetworkFolder(KIO::UDSEntry &entry, const QString &filename) const +{ + qCDebug(KIOREMOTE_LOG) << "RemoteImpl::statNetworkFolder: " << filename; + + QString directory; + if (findDirectory(filename+".desktop", directory)) + { + createEntry(entry, directory, filename+".desktop"); + return true; + } + + return false; +} + +bool RemoteImpl::deleteNetworkFolder(const QString &filename) const +{ + qCDebug(KIOREMOTE_LOG) << "RemoteImpl::deleteNetworkFolder: " << filename; + + QString directory; + if (findDirectory(filename+".desktop", directory)) + { + qCDebug(KIOREMOTE_LOG) << "Removing " << directory << filename << ".desktop"; + return QFile::remove(directory+filename+".desktop"); + } + + return false; +} + +bool RemoteImpl::renameFolders(const QString &src, const QString &dest, + bool overwrite) const +{ + qCDebug(KIOREMOTE_LOG) << "RemoteImpl::renameFolders: " + << src << ", " << dest << endl; + + QString directory; + if (findDirectory(src+".desktop", directory)) + { + if (!overwrite && QFile::exists(directory+dest+".desktop")) + { + return false; + } + + qCDebug(KIOREMOTE_LOG) << "Renaming " << directory << src << ".desktop"; + QDir dir(directory); + bool res = dir.rename(src+".desktop", dest+".desktop"); + if (res) + { + KDesktopFile desktop(directory+dest+".desktop"); + desktop.desktopGroup().writeEntry("Name", dest); + } + return res; + } + + return false; +} + +bool RemoteImpl::changeFolderTarget(const QString &src, const QString &target, + bool overwrite) const +{ + qCDebug(KIOREMOTE_LOG) << "RemoteImpl::changeFolderTarget: " + << src << ", " << target << endl; + + QString directory; + if (findDirectory(src+".desktop", directory)) + { + if (!overwrite || !QFile::exists(directory+src+".desktop")) + { + return false; + } + + qCDebug(KIOREMOTE_LOG) << "Changing target " << directory << src << ".desktop"; + KDesktopFile desktop(directory+src+".desktop"); + desktop.desktopGroup().writeEntry("URL", target); + return true; + } + + return false; +} +