diff --git a/krusader/Panel/panelfunc.cpp b/krusader/Panel/panelfunc.cpp index 2b1e3d95..95c57482 100644 --- a/krusader/Panel/panelfunc.cpp +++ b/krusader/Panel/panelfunc.cpp @@ -1,1263 +1,1262 @@ /*************************************************************************** panelfunc.cpp ------------------- copyright : (C) 2000 by Shie Erlich & Rafi Yanai e-mail : krusader@users.sourceforge.net web site : http://krusader.sourceforge.net --------------------------------------------------------------------------- Description *************************************************************************** A db dD d8888b. db db .d8888. .d8b. d8888b. d88888b d8888b. 88 ,8P' 88 `8D 88 88 88' YP d8' `8b 88 `8D 88' 88 `8D 88,8P 88oobY' 88 88 `8bo. 88ooo88 88 88 88ooooo 88oobY' 88`8b 88`8b 88 88 `Y8b. 88~~~88 88 88 88~~~~~ 88`8b 88 `88. 88 `88. 88b d88 db 8D 88 88 88 .8D 88. 88 `88. YP YD 88 YD ~Y8888P' `8888Y' YP YP Y8888D' Y88888P 88 YD S o u r c e F i l e *************************************************************************** * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #include "panelfunc.h" // QtCore #include #include #include #include #include #include // QtGui #include #include // QtWidgets #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "dirhistoryqueue.h" #include "krcalcspacedialog.h" #include "listpanel.h" #include "krerrordisplay.h" #include "listpanelactions.h" #include "../krglobal.h" #include "../krslots.h" #include "../kractions.h" #include "../defaults.h" #include "../abstractpanelmanager.h" #include "../krservices.h" #include "../VFS/vfile.h" #include "../VFS/virt_vfs.h" #include "../VFS/krarchandler.h" #include "../VFS/krpermhandler.h" #include "../VFS/krvfshandler.h" #include "../VFS/packjob.h" #include "../Dialogs/packgui.h" #include "../Dialogs/krdialogs.h" #include "../Dialogs/krpleasewait.h" #include "../Dialogs/krspwidgets.h" #include "../Dialogs/checksumdlg.h" #include "../KViewer/krviewer.h" #include "../GUI/syncbrowsebutton.h" QPointer ListPanelFunc::copyToClipboardOrigin; ListPanelFunc::ListPanelFunc(ListPanel *parent) : QObject(parent), panel(parent), vfsP(0), urlManuallyEntered(false), _refreshing(false) { history = new DirHistoryQueue(panel); delayTimer.setSingleShot(true); connect(&delayTimer, SIGNAL(timeout()), this, SLOT(doRefresh())); } ListPanelFunc::~ListPanelFunc() { if (vfsP) { if (vfsP->vfs_canDelete()) delete vfsP; else { connect(vfsP, SIGNAL(deleteAllowed()), vfsP, SLOT(deleteLater())); vfsP->vfs_requestDelete(); } } delete history; } void ListPanelFunc::navigatorUrlChanged(const QUrl &url) { if (_refreshing) return; if (!ListPanel::isNavigatorEditModeSet()) { panel->urlNavigator->setUrlEditable(false); } openUrl(KrServices::escapeFileUrl(url), QString(), true); } bool ListPanelFunc::isSyncing(const QUrl &url) { if(otherFunc()->otherFunc() == this && panel->otherPanel()->gui->syncBrowseButton->state() == SYNCBROWSE_CD && !otherFunc()->syncURL.isEmpty() && otherFunc()->syncURL == url) return true; return false; } void ListPanelFunc::openFileNameInternal(const QString &name, bool theFileCanBeExecutedOrOpenedWithOtherSoftware) { if (name == "..") { dirUp(); return ; } vfile *vf = files()->vfs_search(name); if (vf == 0) return ; QUrl url = files()->vfs_getFile(name); if (vf->vfile_isDir()) { panel->view->setNameToMakeCurrent(QString()); openUrl(url); return; } QString mime = vf->vfile_getMime(); QUrl arcPath = browsableArchivePath(name); if (!arcPath.isEmpty()) { bool theArchiveMustBeBrowsedAsADirectory = (KConfigGroup(krConfig, "Archives").readEntry("ArchivesAsDirectories", _ArchivesAsDirectories) && KRarcHandler::arcSupported(mime)) || !theFileCanBeExecutedOrOpenedWithOtherSoftware; if (theArchiveMustBeBrowsedAsADirectory) { openUrl(arcPath); return; } } if (theFileCanBeExecutedOrOpenedWithOtherSoftware) { if (KRun::isExecutableFile(url, mime)) { runCommand(KShell::quoteArg(url.path())); return; } KService::Ptr service = KMimeTypeTrader::self()->preferredService(mime); if(service) { runService(*service, QList() << url); return; } displayOpenWithDialog(QList() << url); } } #if 0 //FIXME: see if this is still needed void ListPanelFunc::popErronousUrl() { QUrl current = urlStack.last(); while (urlStack.count() != 0) { QUrl url = urlStack.takeLast(); if (!current.equals(url)) { immediateOpenUrl(url, true); return; } } immediateOpenUrl(QUrl::fromLocalFile(ROOT_DIR), true); } #endif QUrl ListPanelFunc::cleanPath(const QUrl &urlIn) { QUrl url = urlIn; url.setPath(QDir::cleanPath(url.path())); if (!url.isValid() || url.isRelative()) { if (url.url() == "~") url = QUrl::fromLocalFile(QDir::homePath()); else if (!url.url().startsWith('/')) { // possible relative URL - translate to full URL url = files()->vfs_getOrigin(); url.setPath(url.path() + '/' + urlIn.path()); } } url.setPath(QDir::cleanPath(url.path())); return url; } void ListPanelFunc::openUrl(const QUrl &url, const QString& nameToMakeCurrent, bool manuallyEntered) { if (panel->syncBrowseButton->state() == SYNCBROWSE_CD) { //do sync-browse stuff.... if(syncURL.isEmpty()) syncURL = panel->otherPanel()->virtualPath(); QString relative = QDir(panel->virtualPath().path() + '/').relativeFilePath(url.path()); syncURL.setPath(QDir::cleanPath(syncURL.path() + '/' + relative)); panel->otherPanel()->gui->setLocked(false); otherFunc()->openUrlInternal(syncURL, nameToMakeCurrent, false, false, false); } openUrlInternal(url, nameToMakeCurrent, false, false, manuallyEntered); } void ListPanelFunc::immediateOpenUrl(const QUrl &url, bool disableLock) { openUrlInternal(url, QString(), true, disableLock, false); } void ListPanelFunc::openUrlInternal(const QUrl &url, const QString& nameToMakeCurrent, bool immediately, bool disableLock, bool manuallyEntered) { QUrl cleanUrl = cleanPath(url); if (!disableLock && panel->isLocked() && !files()->vfs_getOrigin().matches(cleanUrl, QUrl::StripTrailingSlash)) { panel->_manager->newTab(url); urlManuallyEntered = false; return; } urlManuallyEntered = manuallyEntered; history->add(cleanUrl, nameToMakeCurrent); if(immediately) doRefresh(); else refresh(); } void ListPanelFunc::refresh() { panel->inlineRefreshCancel(); delayTimer.start(0); // to avoid qApp->processEvents() deadlock situaltion } void ListPanelFunc::doRefresh() { _refreshing = true; delayTimer.stop(); QUrl url = history->currentUrl(); if(!url.isValid()) { //FIXME go back in history here ? panel->slotStartUpdate(); // refresh the panel urlManuallyEntered = false; return ; } panel->inlineRefreshCancel(); // if we are not refreshing to current URL bool isEqualUrl = files()->vfs_getOrigin().matches(url, QUrl::StripTrailingSlash); if (!isEqualUrl) { panel->setCursor(Qt::WaitCursor); panel->view->clearSavedSelection(); } if(panel->vfsError) panel->vfsError->hide(); bool refreshFailed = false; while (true) { QString tmp; if (refreshFailed) { tmp = history->currentUrl().fileName(); history->goForward(); QUrl t = history->currentUrl(); QString protocol = t.scheme(); if (protocol != QStringLiteral("file") && KProtocolInfo::protocolClass(protocol).toLower() == QStringLiteral(":local")) { t.setScheme("file"); history->setCurrentUrl(t); panel->vfsError->hide(); } else { history->goBack(); } } QUrl url = history->currentUrl(); isEqualUrl = files()->vfs_getOrigin().matches(url, QUrl::StripTrailingSlash); vfs* v = KrVfsHandler::instance().getVfs(url, panel, files()); v->setParentWindow(krMainWindow); v->setMountMan(&krMtMan); if (v != vfsP) { panel->view->setFiles(0); // disconnect older signals disconnect(vfsP, 0, panel, 0); if (vfsP->vfs_canDelete()) delete vfsP; else { connect(vfsP, SIGNAL(deleteAllowed()), vfsP, SLOT(deleteLater())); vfsP->vfs_requestDelete(); } vfsP = v; // v != 0 so this is safe } else { if (vfsP->vfs_isBusy()) { delayTimer.start(100); /* if vfs is busy try refreshing later */ return; } } // (re)connect vfs signals disconnect(files(), 0, panel, 0); connect(files(), SIGNAL(startUpdate()), panel, SLOT(slotStartUpdate())); connect(files(), SIGNAL(incrementalRefreshFinished(const QUrl&)), panel, SLOT(slotGetStats(const QUrl&))); connect(files(), SIGNAL(startJob(KIO::Job*)), panel, SLOT(slotJobStarted(KIO::Job*))); connect(files(), SIGNAL(error(QString)), panel, SLOT(slotVfsError(QString))); panel->view->setFiles(files()); if(isSyncing(url)) vfsP->vfs_setQuiet(true); if(!history->currentItem().isEmpty() && isEqualUrl) { // if the url we're refreshing into is the current one, then the // partial refresh will not generate the needed signals to actually allow the // view to use nameToMakeCurrent. do it here instead (patch by Thomas Jarosch) panel->view->setCurrentItem(history->currentItem()); panel->view->makeItemVisible(panel->view->getCurrentKrViewItem()); } if (!tmp.isEmpty()) panel->view->setNameToMakeCurrent(tmp); else panel->view->setNameToMakeCurrent(history->currentItem()); int savedHistoryState = history->state(); if (vfsP->vfs_refresh(url)) { // update the history and address bar, as the actual url might differ from the one requested history->setCurrentUrl(vfsP->vfs_getOrigin()); panel->urlNavigator->setLocationUrl(vfsP->vfs_getOrigin()); break; // we have a valid refreshed URL now } refreshFailed = true; panel->view->setNameToMakeCurrent(QString()); if(history->state() != savedHistoryState) // don't go back if the history was touched break; // prevent repeated error messages if (vfsP->vfs_isDeleting()) break; if(!history->goBack()) { // put the root dir to the beginning of history, if it's not there yet if (!url.matches(QUrl::fromLocalFile(ROOT_DIR), QUrl::StripTrailingSlash)) history->pushBackRoot(); else break; } vfsP->vfs_setQuiet(true); } vfsP->vfs_setQuiet(false); panel->view->setNameToMakeCurrent(QString()); panel->setCursor(Qt::ArrowCursor); // on local file system change the working directory if (files() ->vfs_getType() == vfs::VFS_NORMAL) QDir::setCurrent(KrServices::urlToLocalPath(files()->vfs_getOrigin())); // see if the open url operation failed, and if so, // put the attempted url in the navigator bar and let the user change it if (refreshFailed) { if(isSyncing(url)) panel->otherPanel()->gui->syncBrowseButton->setChecked(false); else if(urlManuallyEntered) { panel->urlNavigator->setLocationUrl(url); if(panel == ACTIVE_PANEL) panel->editLocation(); } } if(otherFunc()->otherFunc() == this) // not true if our tab is not active otherFunc()->syncURL = QUrl(); urlManuallyEntered = false; refreshActions(); _refreshing = false; } void ListPanelFunc::redirectLink() { if (files() ->vfs_getType() != vfs::VFS_NORMAL) { KMessageBox::sorry(krMainWindow, i18n("You can edit links only on local file systems")); return ; } vfile *vf = files() ->vfs_search(panel->getCurrentName()); if (!vf) return ; QString file = files() ->vfs_getFile(vf->vfile_getName()).path(); QString currentLink = vf->vfile_getSymDest(); if (currentLink.isEmpty()) { KMessageBox::sorry(krMainWindow, i18n("The current file is not a link, so it cannot be redirected.")); return ; } // ask the user for a new destination bool ok = false; QString newLink = QInputDialog::getText(krMainWindow, i18n("Link Redirection"), i18n("Please enter the new link destination:"), QLineEdit::Normal, currentLink, &ok); // if the user canceled - quit if (!ok || newLink == currentLink) return ; // delete the current link if (unlink(file.toLocal8Bit()) == -1) { KMessageBox::sorry(krMainWindow, i18n("Cannot remove old link: %1", file)); return ; } // try to create a new symlink if (symlink(newLink.toLocal8Bit(), file.toLocal8Bit()) == -1) { KMessageBox:: /* --=={ Patch by Heiner }==-- */sorry(krMainWindow, i18n("Failed to create a new link: %1", file)); return ; } } void ListPanelFunc::krlink(bool sym) { if (files() ->vfs_getType() != vfs::VFS_NORMAL) { KMessageBox::sorry(krMainWindow, i18n("You can create links only on local file systems")); return ; } QString name = panel->getCurrentName(); // ask the new link name.. bool ok = false; QString linkName = QInputDialog::getText(krMainWindow, i18n("New Link"), i18n("Create a new link to: %1", name), QLineEdit::Normal, name, &ok); // if the user canceled - quit if (!ok || linkName == name) return ; // if the name is already taken - quit if (files() ->vfs_search(linkName) != 0) { KMessageBox::sorry(krMainWindow, i18n("A folder or a file with this name already exists.")); return ; } if (linkName.left(1) != "/") linkName = files() ->vfs_workingDir() + '/' + linkName; if (linkName.contains("/")) name = files() ->vfs_getFile(name).path(); if (sym) { if (symlink(name.toLocal8Bit(), linkName.toLocal8Bit()) == -1) KMessageBox::sorry(krMainWindow, i18n("Failed to create a new symlink '%1' to: '%2'", linkName, name)); } else { if (link(name.toLocal8Bit(), linkName.toLocal8Bit()) == -1) KMessageBox::sorry(krMainWindow, i18n("Failed to create a new link '%1' to '%2'", linkName, name)); } } void ListPanelFunc::view() { QString fileName = panel->getCurrentName(); if (fileName.isNull()) return ; // if we're trying to view a directory, just exit vfile * vf = files() ->vfs_search(fileName); if (!vf || vf->vfile_isDir()) return ; if (!vf->vfile_isReadable()) { KMessageBox::sorry(0, i18n("No permissions to view this file.")); return ; } // call KViewer. KrViewer::view(files() ->vfs_getFile(fileName)); // nothing more to it! } void ListPanelFunc::viewDlg() { // ask the user for a url to view QUrl dest = KChooseDir::getFile(i18n("Enter a URL to view:"), panel->virtualPath(), panel->virtualPath()); if (dest.isEmpty()) return ; // the user canceled KrViewer::view(dest); // view the file } void ListPanelFunc::terminal() { SLOTS->runTerminal(panel->realPath()); } void ListPanelFunc::edit() { KFileItem tmp; if (fileToCreate.isEmpty()) { QString name = panel->getCurrentName(); if (name.isNull()) return; fileToCreate = files()->vfs_getFile(name); } tmp = KFileItem(fileToCreate); if (tmp.isDir()) { KMessageBox::sorry(krMainWindow, i18n("You cannot edit a folder")); fileToCreate = QUrl(); return ; } if (!tmp.isReadable()) { KMessageBox::sorry(0, i18n("No permissions to edit this file.")); fileToCreate = QUrl(); return; } KrViewer::edit(fileToCreate); fileToCreate = QUrl(); } void ListPanelFunc::editNew() { if(!fileToCreate.isEmpty()) return; // ask the user for the filename to edit fileToCreate = KChooseDir::getFile(i18n("Enter the filename to edit:"), panel->virtualPath(), panel->virtualPath()); if(fileToCreate.isEmpty()) return ; // the user canceled // if the file exists, edit it instead of creating a new one QFile f(fileToCreate.toLocalFile()); if(f.exists()) { edit(); } else { QTemporaryFile *tempFile = new QTemporaryFile; tempFile->open(); KIO::CopyJob *job = KIO::copy(QUrl::fromLocalFile(tempFile->fileName()), fileToCreate); job->setUiDelegate(0); job->setDefaultPermissions(true); connect(job, SIGNAL(result(KJob*)), SLOT(slotFileCreated(KJob*))); connect(job, SIGNAL(result(KJob*)), tempFile, SLOT(deleteLater())); } } void ListPanelFunc::slotFileCreated(KJob *job) { if(!job->error() || job->error() == KIO::ERR_FILE_ALREADY_EXIST) { KrViewer::edit(fileToCreate); if(KIO::upUrl(fileToCreate).matches(panel->virtualPath(), QUrl::StripTrailingSlash)) refresh(); else if(KIO::upUrl(fileToCreate).matches(panel->otherPanel()->virtualPath(), QUrl::StripTrailingSlash)) otherFunc()->refresh(); } else KMessageBox::sorry(krMainWindow, job->errorString()); fileToCreate = QUrl(); } void ListPanelFunc::moveFiles() { copyFiles(true); } void ListPanelFunc::copyFiles(bool move) { QStringList fileNames; panel->getSelectedNames(&fileNames); if (fileNames.isEmpty()) return ; // safety QUrl destination = panel->otherPanel()->virtualPath(); KConfigGroup group(krConfig, "Advanced"); bool showDialog = move ? group.readEntry("Confirm Move", _ConfirmMove) : group.readEntry("Confirm Copy", _ConfirmCopy); if (showDialog) { QString operationText; if (move) { operationText = fileNames.count() == 1 ? i18n("Move %1 to:", fileNames.first()) : i18np("Move %1 file to:", "Move %1 files to:", fileNames.count()); } else { operationText = fileNames.count() == 1 ? i18n("Copy %1 to:", fileNames.first()) : i18np("Copy %1 file to:", "Copy %1 files to:", fileNames.count()); } // ask the user for the copy/move dest destination = KChooseDir::getDir(operationText, destination, panel->virtualPath()); if (destination.isEmpty()) return ; // the user canceled } QList fileUrls = files()->vfs_getFiles(fileNames); if (move) { // after the delete return the cursor to the first unmarked file above the current item panel->prepareToDelete(); } // you can rename only *one* file not a batch, so a batch destination must always be a directory if (fileNames.count() > 1) { destination = vfs::ensureTrailingSlash(destination); } KIO::CopyJob::CopyMode mode = move ? KIO::CopyJob::Move : KIO::CopyJob::Copy; KIO::Job* job = KrVfsHandler::instance().createCopyJob(fileUrls, destination, mode); job->ui()->setAutoErrorHandlingEnabled(true); // refresh our panel when done connect(job, SIGNAL(result(KJob*)), this, SLOT(refresh())); // and if needed the other panel as well if (destination.matches(panel->otherPanel()->virtualPath(), QUrl::StripTrailingSlash)) connect(job, SIGNAL(result(KJob*)), panel->otherPanel()->func, SLOT(refresh())); if(KConfigGroup(krConfig, "Look&Feel").readEntry("UnselectBeforeOperation", _UnselectBeforeOperation)) { panel->view->saveSelection(); panel->view->unselectAll(); } } // called from SLOTS to begin the renaming process void ListPanelFunc::rename() { panel->view->renameCurrentItem(); } // called by signal itemRenamed() from the view to complete the renaming process void ListPanelFunc::rename(const QString &oldname, const QString &newname) { if (oldname == newname) return ; // do nothing panel->view->setNameToMakeCurrentIfAdded(newname); // as always - the vfs do the job files() ->vfs_rename(oldname, newname); } void ListPanelFunc::mkdir() { // ask the new dir name.. // suggested name is the complete name for the directories // while filenames are suggested without their extension QString suggestedName = panel->getCurrentName(); if (!suggestedName.isEmpty() && !files()->vfs_search(suggestedName)->vfile_isDir()) suggestedName = QFileInfo(suggestedName).completeBaseName(); QString dirName = QInputDialog::getText(krMainWindow, i18n("New folder"), i18n("Folder's name:"), QLineEdit::Normal, suggestedName); // if the user canceled - quit if (dirName.isEmpty()) return ; QStringList dirTree = dirName.split('/'); for (QStringList::Iterator it = dirTree.begin(); it != dirTree.end(); ++it) { if (*it == ".") continue; if (*it == "..") { immediateOpenUrl(QUrl::fromUserInput(*it, QString(), QUrl::AssumeLocalFile)); continue; } // check if the name is already taken if (files() ->vfs_search(*it)) { // if it is the last dir to be created - quit if (*it == dirTree.last()) { KMessageBox::sorry(krMainWindow, i18n("A folder or a file with this name already exists.")); return ; } // else go into this dir else { immediateOpenUrl(QUrl::fromUserInput(*it, QString(), QUrl::AssumeLocalFile)); continue; } } panel->view->setNameToMakeCurrent(*it); // as always - the vfs do the job files() ->vfs_mkdir(*it); if (dirTree.count() > 1) immediateOpenUrl(QUrl::fromUserInput(*it, QString(), QUrl::AssumeLocalFile)); } // for } void ListPanelFunc::deleteFiles(bool reallyDelete) { // check that the you have write perm if (!files() ->vfs_isWritable()) { KMessageBox::sorry(krMainWindow, i18n("You do not have write permission to this folder")); return ; } // first get the selected file names list QStringList fileNames; panel->getSelectedNames(&fileNames); if (fileNames.isEmpty()) return ; KConfigGroup gg(krConfig, "General"); bool trash = gg.readEntry("Move To Trash", _MoveToTrash); // now ask the user if he want to delete: KConfigGroup group(krConfig, "Advanced"); if (group.readEntry("Confirm Delete", _ConfirmDelete)) { QString s, b; if (!reallyDelete && trash && files() ->vfs_getType() == vfs::VFS_NORMAL) { s = i18np("Do you really want to move this item to the trash?", "Do you really want to move these %1 items to the trash?", fileNames.count()); b = i18n("&Trash"); } else if (files() ->vfs_getType() == vfs::VFS_VIRT && files()->vfs_getOrigin().matches(QUrl("virt:/"), QUrl::StripTrailingSlash)) { s = i18np("Do you really want to delete this virtual item (physical files stay untouched)?", "Do you really want to delete these %1 virtual items (physical files stay untouched)?", fileNames.count()); b = i18n("&Delete"); } else if (files() ->vfs_getType() == vfs::VFS_VIRT) { s = i18np("Do you really want to delete this item physically (not just removing it from the virtual items)?", "Do you really want to delete these %1 items physically (not just removing them from the virtual items)?", fileNames.count()); b = i18n("&Delete"); } else { s = i18np("Do you really want to delete this item?", "Do you really want to delete these %1 items?", fileNames.count()); b = i18n("&Delete"); } // show message // note: i'm using continue and not yes/no because the yes/no has cancel as default button if (KMessageBox::warningContinueCancelList(krMainWindow, s, fileNames, i18n("Warning"), KGuiItem(b)) != KMessageBox::Continue) return ; } //we want to warn the user about non empty dir // and files he don't have permission to delete bool emptyDirVerify = group.readEntry("Confirm Unempty Dir", _ConfirmUnemptyDir); emptyDirVerify = ((emptyDirVerify) && (files() ->vfs_getType() == vfs::VFS_NORMAL)); QDir dir; for (QStringList::Iterator name = fileNames.begin(); name != fileNames.end();) { vfile * vf = files() ->vfs_search(*name); // verify non-empty dirs delete... (only for normal vfs) if (vf && emptyDirVerify && vf->vfile_isDir() && !vf->vfile_isSymLink()) { dir.setPath(panel->virtualPath().path() + '/' + (*name)); if (dir.entryList(QDir::TypeMask | QDir::System | QDir::Hidden).count() > 2) { switch (KMessageBox::warningYesNoCancel(krMainWindow, i18n("

Folder %1 is not empty.

Skip this one or delete all?

", *name), QString(), KGuiItem(i18n("&Skip")), KGuiItem(i18n("&Delete All")))) { case KMessageBox::No : emptyDirVerify = false; break; case KMessageBox::Yes : name = fileNames.erase(name); continue; default : return ; } } } ++name; } if (fileNames.count() == 0) return ; // nothing to delete // after the delete return the cursor to the first unmarked // file above the current item; panel->prepareToDelete(); // let the vfs do the job... files() ->vfs_delFiles(fileNames, reallyDelete); } void ListPanelFunc::goInside(const QString& name) { openFileNameInternal(name, false); } void ListPanelFunc::runCommand(QString cmd) { krOut << "Run command: " << cmd; QString workdir = panel->virtualPath().isLocalFile() ? panel->virtualPath().path() : QDir::homePath(); if(!KRun::runCommand(cmd, krMainWindow, workdir)) KMessageBox::error(0, i18n("Could not start %1", cmd)); } void ListPanelFunc::runService(const KService &service, QList urls) { krOut << "Run service: " << service.name(); KIO::DesktopExecParser parser(service, urls); QStringList args = parser.resultingArguments(); if (!args.isEmpty()) runCommand(KShell::joinArgs(args)); else KMessageBox::error(0, i18n("%1 cannot open %2", service.name(), KrServices::toStringList(urls).join(", "))); } void ListPanelFunc::displayOpenWithDialog(QList urls) { KRun::displayOpenWithDialog(urls, krMainWindow); } QUrl ListPanelFunc::browsableArchivePath(const QString &filename) { vfile *vf = files()->vfs_search(filename); QUrl url = files()->vfs_getFile(filename); QString mime = vf->vfile_getMime(); if(url.isLocalFile()) { QString protocol = KrServices::registeredProtocol(mime); if(!protocol.isEmpty()) { url.setScheme(protocol); return url; } } return QUrl(); } // this is done when you double click on a file void ListPanelFunc::execute(const QString& name) { openFileNameInternal(name, true); } void ListPanelFunc::pack() { QStringList fileNames; panel->getSelectedNames(&fileNames); if (fileNames.isEmpty()) return ; // safety if (fileNames.count() == 0) return ; // nothing to pack // choose the default name QString defaultName = panel->virtualPath().fileName(); if (defaultName.isEmpty()) defaultName = "pack"; if (fileNames.count() == 1) defaultName = fileNames.first(); // ask the user for archive name and packer new PackGUI(defaultName, panel->otherPanel()->virtualPath().toDisplayString(QUrl::PreferLocalFile | QUrl::StripTrailingSlash), fileNames.count(), fileNames.first()); if (PackGUI::type.isEmpty()) { return ; // the user canceled } // check for partial URLs if (!PackGUI::destination.contains(":/") && !PackGUI::destination.startsWith('/')) { PackGUI::destination = panel->virtualPath().toDisplayString() + '/' + PackGUI::destination; } QString destDir = PackGUI::destination; if (!destDir.endsWith('/')) destDir += '/'; bool packToOtherPanel = (destDir == vfs::ensureTrailingSlash(panel->otherPanel()->virtualPath()).toDisplayString(QUrl::PreferLocalFile)); QUrl destURL = QUrl::fromUserInput(destDir + PackGUI::filename + '.' + PackGUI::type, QString(), QUrl::AssumeLocalFile); if (destURL.isLocalFile() && QFile::exists(destURL.path())) { QString msg = i18n("

The archive %1.%2 already exists. Do you want to overwrite it?

All data in the previous archive will be lost.

", PackGUI::filename, PackGUI::type); if (PackGUI::type == "zip") { msg = i18n("

The archive %1.%2 already exists. Do you want to overwrite it?

Zip will replace identically named entries in the zip archive or add entries for new names.

", PackGUI::filename, PackGUI::type); } if (KMessageBox::warningContinueCancel(krMainWindow, msg, QString(), KGuiItem(i18n("&Overwrite"))) == KMessageBox::Cancel) return ; // stop operation } else if (destURL.scheme() == QStringLiteral("virt")) { KMessageBox::error(krMainWindow, i18n("Cannot pack files onto a virtual destination.")); return; } PackJob * job = PackJob::createPacker(files()->vfs_getOrigin(), destURL, fileNames, PackGUI::type, PackGUI::extraProps); job->setUiDelegate(new KIO::JobUiDelegate()); KIO::getJobTracker()->registerJob(job); job->ui()->setAutoErrorHandlingEnabled(true); if (packToOtherPanel) connect(job, SIGNAL(result(KJob*)), panel->otherPanel()->func, SLOT(refresh())); } void ListPanelFunc::testArchive() { QStringList fileNames; panel->getSelectedNames(&fileNames); if (fileNames.isEmpty()) return ; // safety TestArchiveJob * job = TestArchiveJob::testArchives(files()->vfs_getOrigin(), fileNames); job->setUiDelegate(new KIO::JobUiDelegate()); KIO::getJobTracker()->registerJob(job); job->ui()->setAutoErrorHandlingEnabled(true); } void ListPanelFunc::unpack() { QStringList fileNames; panel->getSelectedNames(&fileNames); if (fileNames.isEmpty()) return ; // safety QString s; if (fileNames.count() == 1) s = i18n("Unpack %1 to:", fileNames[0]); else s = i18np("Unpack %1 file to:", "Unpack %1 files to:", fileNames.count()); // ask the user for the copy dest QUrl dest = KChooseDir::getDir(s, panel->otherPanel()->virtualPath(), panel->virtualPath()); if (dest.isEmpty()) return ; // the user canceled bool packToOtherPanel = (dest.matches(panel->otherPanel()->virtualPath(), QUrl::StripTrailingSlash)); UnpackJob * job = UnpackJob::createUnpacker(files()->vfs_getOrigin(), dest, fileNames); job->setUiDelegate(new KIO::JobUiDelegate()); KIO::getJobTracker()->registerJob(job); job->ui()->setAutoErrorHandlingEnabled(true); if (packToOtherPanel) connect(job, SIGNAL(result(KJob*)), panel->otherPanel()->func, SLOT(refresh())); } // a small ugly function, used to prevent duplication of EVERY line of // code (maybe except 3) from createChecksum and matchChecksum static void checksum_wrapper(ListPanel *panel, QStringList& args, bool &folders) { KrViewItemList items; panel->view->getSelectedKrViewItems(&items); if (items.isEmpty()) return ; // nothing to do // determine if we need recursive mode (md5deep) folders = false; for (KrViewItemList::Iterator it = items.begin(); it != items.end(); ++it) { if (panel->func->getVFile(*it)->vfile_isDir()) { folders = true; args << (*it)->name(); } else args << (*it)->name(); } } void ListPanelFunc::createChecksum() { QStringList args; bool folders; checksum_wrapper(panel, args, folders); CreateChecksumDlg dlg(args, folders, panel->realPath()); } void ListPanelFunc::matchChecksum() { QStringList args; bool folders; checksum_wrapper(panel, args, folders); QList checksumFiles = files()->vfs_search( KRQuery(MatchChecksumDlg::checksumTypesFilter) ); MatchChecksumDlg dlg(args, folders, panel->realPath(), (checksumFiles.size() == 1 ? checksumFiles[0]->vfile_getUrl().toDisplayString(QUrl::PreferLocalFile) : QString())); } void ListPanelFunc::calcSpace() { QStringList items; panel->view->getSelectedItems(&items); if (items.isEmpty()) { panel->view->selectAllIncludingDirs(); panel->view->getSelectedItems(&items); if (items.isEmpty()) return ; // nothing to do } QPointer calc = new KrCalcSpaceDialog(krMainWindow, panel, items, false); calc->exec(); panel->slotUpdateTotals(); delete calc; } bool ListPanelFunc::calcSpace(const QStringList & items, KIO::filesize_t & totalSize, unsigned long & totalFiles, unsigned long & totalDirs) { QPointer calc = new KrCalcSpaceDialog(krMainWindow, panel, items, true); calc->exec(); calc->getStats(totalSize, totalFiles, totalDirs); bool calcWasCanceled = calc->wasCanceled(); delete calc; return !calcWasCanceled; } void ListPanelFunc::calcSpace(KrViewItem *item) { // // NOTE: this is buggy incase somewhere down in the folder we're calculating, // there's a folder we can't enter (permissions). in that case, the returned // size will not be correct. // KIO::filesize_t totalSize = 0; unsigned long totalFiles = 0, totalDirs = 0; QStringList items; items.push_back(item->name()); if (calcSpace(items, totalSize, totalFiles, totalDirs)) { // did we succeed to calcSpace? we'll fail if we don't have permissions if (totalSize != 0) { // just mark it, and bail out item->setSize(totalSize); item->redraw(); } } } void ListPanelFunc::FTPDisconnect() { // you can disconnect only if connected ! if (files()->vfs_getType() == vfs::VFS_FTP) { panel->_actions->actFTPDisconnect->setEnabled(false); panel->view->setNameToMakeCurrent(QString()); openUrl(QUrl::fromLocalFile(panel->realPath())); // open the last local URL } } void ListPanelFunc::newFTPconnection() { QUrl url = KRSpWidgets::newFTP(); // if the user canceled - quit if (url.isEmpty()) return ; panel->_actions->actFTPDisconnect->setEnabled(true); openUrl(url); } void ListPanelFunc::properties() { QStringList names; panel->getSelectedNames(&names); if (names.isEmpty()) return ; // no names... KFileItemList fi; for (int i = 0 ; i < names.count() ; ++i) { vfile* vf = files() ->vfs_search(names[ i ]); if (!vf) continue; QUrl url = files()->vfs_getFile(names[i]); fi.push_back(KFileItem(vf->vfile_getEntry(), url)); } if (fi.isEmpty()) return ; // Show the properties dialog KPropertiesDialog *dlg = new KPropertiesDialog(fi, krMainWindow); connect(dlg, SIGNAL(applied()), SLOT(refresh())); dlg->show(); } void ListPanelFunc::refreshActions() { panel->updateButtons(); if(ACTIVE_PANEL != panel) return; vfs::VFS_TYPE vfsType = files() ->vfs_getType(); QString protocol = files()->vfs_getOrigin().scheme(); krRemoteEncoding->setEnabled(protocol == "ftp" || protocol == "sftp" || protocol == "fish" || protocol == "krarc"); //krMultiRename->setEnabled( vfsType == vfs::VFS_NORMAL ); // batch rename //krProperties ->setEnabled( vfsType == vfs::VFS_NORMAL || vfsType == vfs::VFS_FTP ); // file properties /* krUnpack->setEnabled(true); // unpack archive krTest->setEnabled(true); // test archive krSelect->setEnabled(true); // select a group by filter krSelectAll->setEnabled(true); // select all files krUnselect->setEnabled(true); // unselect by filter krUnselectAll->setEnabled( true); // remove all selections krInvert->setEnabled(true); // invert the selection krFTPConnect->setEnabled(true); // connect to an ftp krFTPNew->setEnabled(true); // create a new connection krAllFiles->setEnabled(true); // show all files in list krCustomFiles->setEnabled(true); // show a custom set of files krRoot->setEnabled(true); // go all the way up krExecFiles->setEnabled(true); // show only executables */ panel->_actions->setViewActions[panel->panelType]->setChecked(true); panel->_actions->actFTPDisconnect->setEnabled(vfsType == vfs::VFS_FTP); // disconnect an FTP session panel->_actions->actCreateChecksum->setEnabled(vfsType == vfs::VFS_NORMAL); panel->_actions->actDirUp->setEnabled(!files()->isRoot()); panel->_actions->actRoot->setEnabled(!panel->virtualPath().matches(QUrl::fromLocalFile(ROOT_DIR), QUrl::StripTrailingSlash)); panel->_actions->actHome->setEnabled(!atHome()); panel->_actions->actHistoryBackward->setEnabled(history->canGoBack()); panel->_actions->actHistoryForward->setEnabled(history->canGoForward()); panel->view->op()->emitRefreshActions(); } vfs* ListPanelFunc::files() { if (!vfsP) vfsP = KrVfsHandler::instance().getVfs(QUrl::fromLocalFile("/"), panel); return vfsP; } void ListPanelFunc::clipboardChanged(QClipboard::Mode mode) { if (mode == QClipboard::Clipboard && this == copyToClipboardOrigin) { disconnect(QApplication::clipboard(), 0, this, 0); copyToClipboardOrigin = 0; } } void ListPanelFunc::copyToClipboard(bool move) { QStringList fileNames; panel->getSelectedNames(&fileNames); if (fileNames.isEmpty()) return ; // safety QList fileUrls = files() ->vfs_getFiles(fileNames); QMimeData *mimeData = new QMimeData; mimeData->setData("application/x-kde-cutselection", move ? "1" : "0"); mimeData->setUrls(fileUrls); if (copyToClipboardOrigin) disconnect(QApplication::clipboard(), 0, copyToClipboardOrigin, 0); copyToClipboardOrigin = this; QApplication::clipboard()->setMimeData(mimeData, QClipboard::Clipboard); connect(QApplication::clipboard(), SIGNAL(changed(QClipboard::Mode)), this, SLOT(clipboardChanged(QClipboard::Mode))); } void ListPanelFunc::pasteFromClipboard() { QClipboard * cb = QApplication::clipboard(); ListPanelFunc *origin = 0; if (copyToClipboardOrigin) { disconnect(QApplication::clipboard(), 0, copyToClipboardOrigin, 0); origin = copyToClipboardOrigin; copyToClipboardOrigin = 0; } bool move = false; const QMimeData *data = cb->mimeData(); if (data->hasFormat("application/x-kde-cutselection")) { QByteArray a = data->data("application/x-kde-cutselection"); if (!a.isEmpty()) move = (a.at(0) == '1'); // true if 1 } QList urls = data->urls(); if (urls.isEmpty()) return ; if(origin && KConfigGroup(krConfig, "Look&Feel").readEntry("UnselectBeforeOperation", _UnselectBeforeOperation)) { origin->panel->view->saveSelection(); for(KrViewItem *item = origin->panel->view->getFirst(); item != 0; item = origin->panel->view->getNext(item)) { if (urls.contains(item->getVfile()->vfile_getUrl())) item->setSelected(false); } } - files()->vfs_addFiles(urls, move ? KIO::CopyJob::Move : KIO::CopyJob::Copy, otherFunc()->files(), - "", PM_DEFAULT); + files()->vfs_addFiles(urls, move ? KIO::CopyJob::Move : KIO::CopyJob::Copy, otherFunc()->files()); } ListPanelFunc* ListPanelFunc::otherFunc() { return panel->otherPanel()->func; } void ListPanelFunc::historyGotoPos(int pos) { if(history->gotoPos(pos)) refresh(); } void ListPanelFunc::historyBackward() { if(history->goBack()) refresh(); } void ListPanelFunc::historyForward() { if(history->goForward()) refresh(); } void ListPanelFunc::dirUp() { openUrl(KIO::upUrl(files()->vfs_getOrigin()), files()->vfs_getOrigin().fileName()); } void ListPanelFunc::home() { openUrl(QUrl::fromLocalFile(QDir::homePath())); } void ListPanelFunc::root() { openUrl(QUrl::fromLocalFile(ROOT_DIR)); } void ListPanelFunc::cdToOtherPanel() { openUrl(panel->otherPanel()->virtualPath()); } void ListPanelFunc::syncOtherPanel() { otherFunc()->openUrl(panel->virtualPath()); } bool ListPanelFunc::atHome() { return QUrl::fromLocalFile(QDir::homePath()).matches(panel->virtualPath(), QUrl::StripTrailingSlash); } diff --git a/krusader/VFS/CMakeLists.txt b/krusader/VFS/CMakeLists.txt index 82ac3f8d..1c2b2a1e 100644 --- a/krusader/VFS/CMakeLists.txt +++ b/krusader/VFS/CMakeLists.txt @@ -1,35 +1,34 @@ include_directories(${KF5_INCLUDES_DIRS} ${QT_INCLUDES}) set(VFS_SRCS vfilecontainer.cpp krvfshandler.cpp virt_vfs.cpp vfs.cpp vfile.cpp default_vfs.cpp krpermhandler.cpp krarchandler.cpp - preservingcopyjob.cpp krquery.cpp packjob.cpp abstractthreadedjob.cpp kr7zencryptionchecker.cpp ../../krArc/krarcbasemanager.cpp ../../krArc/krlinecountingprocess.cpp ) add_library(VFS STATIC ${VFS_SRCS}) target_link_libraries(VFS KF5::Archive KF5::I18n KF5::KIOCore KF5::KIOWidgets KF5::Solid KF5::Wallet KF5::WidgetsAddons ) if(ACL_FOUND) target_link_libraries(VFS ${ACL_LIBS}) endif(ACL_FOUND) diff --git a/krusader/VFS/abstractthreadedjob.cpp b/krusader/VFS/abstractthreadedjob.cpp index f3b6c834..073830bc 100644 --- a/krusader/VFS/abstractthreadedjob.cpp +++ b/krusader/VFS/abstractthreadedjob.cpp @@ -1,653 +1,652 @@ /*************************************************************************** packjob.cpp - description ------------------- copyright : (C) 2009 + by Csaba Karai e-mail : krusader@users.sourceforge.net web site : http://krusader.sourceforge.net --------------------------------------------------------------------------- Description *************************************************************************** A db dD d8888b. db db .d8888. .d8b. d8888b. d88888b d8888b. 88 ,8P' 88 `8D 88 88 88' YP d8' `8b 88 `8D 88' 88 `8D 88,8P 88oobY' 88 88 `8bo. 88ooo88 88 88 88ooooo 88oobY' 88`8b 88`8b 88 88 `Y8b. 88~~~88 88 88 88~~~~~ 88`8b 88 `88. 88 `88. 88b d88 db 8D 88 88 88 .8D 88. 88 `88. YP YD 88 YD ~Y8888P' `8888Y' YP YP Y8888D' Y88888P 88 YD S o u r c e F i l e *************************************************************************** * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #include "abstractthreadedjob.h" // QtCore #include #include #include #include #include #include // QtWidgets #include #include #include #include #include "krvfshandler.h" #include "krarchandler.h" #include "vfs.h" -#include "preservingcopyjob.h" #include "../krglobal.h" #include "../krservices.h" extern KRarcHandler arcHandler; AbstractThreadedJob::AbstractThreadedJob() : KIO::Job(), _locker(), _waiter(), _stack(), _maxProgressValue(0), _currentProgress(0), _exiting(false), _jobThread(0) { } void AbstractThreadedJob::startAbstractJobThread(AbstractJobThread * jobThread) { _jobThread = jobThread; _jobThread->setJob(this); _jobThread->moveToThread(_jobThread); _jobThread->start(); } AbstractThreadedJob::~AbstractThreadedJob() { _exiting = true; if (_jobThread) { _jobThread->abort(); _locker.lock(); _waiter.wakeAll(); _locker.unlock(); _jobThread->wait(); delete _jobThread; } } bool AbstractThreadedJob::event(QEvent *e) { if (e->type() == QEvent::User) { UserEvent *event = (UserEvent*) e; switch (event->command()) { case CMD_SUCCESS: { emitResult(); } break; case CMD_ERROR: { int error = event->args()[ 0 ].value(); QString errorText = event->args()[ 1 ].value(); setError(error); setErrorText(errorText); emitResult(); } break; case CMD_INFO: { QString info = event->args()[ 0 ].value(); QString arg1 = event->args()[ 1 ].value(); QString arg2 = event->args()[ 2 ].value(); QString arg3 = event->args()[ 3 ].value(); QString arg4 = event->args()[ 4 ].value(); _title = info; emit description(this, info, qMakePair(arg1, arg2), qMakePair(arg3, arg4)); } break; case CMD_RESET: { QString info = event->args()[ 0 ].value(); QString arg1 = event->args()[ 1 ].value(); QString arg2 = event->args()[ 2 ].value(); QString arg3 = event->args()[ 3 ].value(); QString arg4 = event->args()[ 4 ].value(); _title = info; setProcessedAmount(KJob::Bytes, 0); setTotalAmount(KJob::Bytes, 0); emitSpeed(0); emit description(this, info, qMakePair(arg1, arg2), qMakePair(arg3, arg4)); } break; case CMD_UPLOAD_FILES: case CMD_DOWNLOAD_FILES: { QList sources = KrServices::toUrlList(event->args()[ 0 ].value()); QUrl dest = event->args()[ 1 ].value(); - KIO::Job *job = PreservingCopyJob::createCopyJob(PM_PRESERVE_ATTR, sources, dest, KIO::CopyJob::Copy, false, false); + KIO::Job *job = KIO::copy(sources, dest, KIO::HideProgressInfo); addSubjob(job); job->setUiDelegate(new KIO::JobUiDelegate()); connect(job, SIGNAL(result(KJob*)), this, SLOT(slotDownloadResult(KJob*))); connect(job, SIGNAL(processedAmount(KJob *, KJob::Unit, qulonglong)), this, SLOT(slotProcessedAmount(KJob *, KJob::Unit, qulonglong))); connect(job, SIGNAL(totalAmount(KJob *, KJob::Unit, qulonglong)), this, SLOT(slotTotalAmount(KJob *, KJob::Unit, qulonglong))); connect(job, SIGNAL(speed(KJob *, unsigned long)), this, SLOT(slotSpeed(KJob *, unsigned long))); connect(job, SIGNAL(description(KJob *, const QString &, const QPair &, const QPair &)), this, SLOT(slotDescription(KJob *, const QString &, const QPair &, const QPair &))); } break; case CMD_MAXPROGRESSVALUE: { qulonglong maxValue = event->args()[ 0 ].value(); _maxProgressValue = maxValue; _currentProgress = 0; } break; case CMD_ADD_PROGRESS: { qulonglong progress = event->args()[ 0 ].value(); _currentProgress += progress; if (_maxProgressValue != 0) { setPercent(100 * _currentProgress / _maxProgressValue); int elapsed = _time.isNull() ? 1 : _time.secsTo(QTime::currentTime()); if (elapsed != 0 && event->args().count() > 1) { _time = QTime::currentTime(); QString progressString = (event->args()[ 1 ].value()); emit description(this, _title, qMakePair(progressString, QString("%1/%2").arg(_currentProgress).arg(_maxProgressValue)), qMakePair(QString(), QString()) ); } } } break; case CMD_GET_PASSWORD: { QString path = event->args()[ 0 ].value(); QString password = KRarcHandler::getPassword(path); QList *resultResp = new QList (); (*resultResp) << password; addEventResponse(resultResp); } break; case CMD_MESSAGE: { QString message = event->args()[ 0 ].value(); KIO::JobUiDelegate *ui = static_cast(uiDelegate()); KMessageBox::information(ui ? ui->window() : 0, message); QList *resultResp = new QList (); addEventResponse(resultResp); } break; } return true; } else { return KIO::Job::event(e); } } void AbstractThreadedJob::addEventResponse(QList * obj) { _locker.lock(); _stack.push(obj); _waiter.wakeOne(); _locker.unlock(); } QList * AbstractThreadedJob::getEventResponse(UserEvent * event) { _locker.lock(); QApplication::postEvent(this, event); _waiter.wait(&_locker); if (_exiting) return 0; QList *resp = _stack.pop(); _locker.unlock(); return resp; } void AbstractThreadedJob::sendEvent(UserEvent * event) { QApplication::postEvent(this, event); } void AbstractThreadedJob::slotDownloadResult(KJob* job) { QList *resultResp = new QList (); if (job) { (*resultResp) << QVariant(job->error()); (*resultResp) << QVariant(job->errorText()); } else { (*resultResp) << QVariant(KJob::UserDefinedError); (*resultResp) << QVariant(QString(i18n("Internal error, undefined in result signal"))); } addEventResponse(resultResp); } void AbstractThreadedJob::slotProcessedAmount(KJob *, KJob::Unit unit, qulonglong xu) { setProcessedAmount(unit, xu); } void AbstractThreadedJob::slotTotalAmount(KJob *, KJob::Unit unit, qulonglong xu) { setTotalAmount(unit, xu); } void AbstractThreadedJob::slotSpeed(KJob *, unsigned long spd) { emitSpeed(spd); } void AbstractThreadedJob::slotDescription(KJob *, const QString &title, const QPair &field1, const QPair &field2) { QString mytitle = title; if (!_title.isNull()) mytitle = _title; emit description(this, mytitle, field1, field2); } class AbstractJobObserver : public KRarcObserver { protected: AbstractJobThread * _jobThread; public: AbstractJobObserver(AbstractJobThread * thread): _jobThread(thread) {} virtual ~AbstractJobObserver() {} virtual void processEvents() Q_DECL_OVERRIDE { usleep(1000); qApp->processEvents(); } virtual void subJobStarted(const QString & jobTitle, int count) Q_DECL_OVERRIDE { _jobThread->sendReset(jobTitle); _jobThread->sendMaxProgressValue(count); } virtual void subJobStopped() Q_DECL_OVERRIDE { } virtual bool wasCancelled() Q_DECL_OVERRIDE { return _jobThread->_exited; } virtual void error(const QString & error) Q_DECL_OVERRIDE { _jobThread->sendError(KIO::ERR_NO_CONTENT, error); } virtual void detailedError(const QString & error, const QString & details) Q_DECL_OVERRIDE { _jobThread->sendError(KIO::ERR_NO_CONTENT, error + '\n' + details); } virtual void incrementProgress(int c) Q_DECL_OVERRIDE { _jobThread->sendAddProgress(c, _jobThread->_progressTitle); } }; AbstractJobThread::AbstractJobThread() : _job(0), _downloadTempDir(0), _observer(0), _tempFile(0), _tempDir(0), _exited(false) { } AbstractJobThread::~AbstractJobThread() { if (_downloadTempDir) { delete _downloadTempDir; _downloadTempDir = 0; } if (_observer) { delete _observer; _observer = 0; } if (_tempFile) { delete _tempFile; _tempFile = 0; } } void AbstractJobThread::run() { QTimer::singleShot(0, this, SLOT(slotStart())); QPointer threadLoop = new QEventLoop(this); _loop = threadLoop; threadLoop->exec(); _loop = 0; delete threadLoop; } void AbstractJobThread::terminate() { if (_loop && !_exited) { _loop->quit(); _exited = true; } } void AbstractJobThread::abort() { terminate(); } QList AbstractJobThread::remoteUrls(const QUrl &baseUrl, const QStringList & files) { QList urlList; foreach(const QString &name, files) { QUrl url = baseUrl; url = url.adjusted(QUrl::StripTrailingSlash); url.setPath(url.path() + '/' + (name)); urlList << url; } return urlList; } QUrl AbstractJobThread::downloadIfRemote(const QUrl &baseUrl, const QStringList & files) { // download remote URL-s if necessary if (!baseUrl.isLocalFile()) { sendInfo(i18n("Downloading remote files")); _downloadTempDir = new QTemporaryDir(); QList urlList = remoteUrls(baseUrl, files); QUrl dest(_downloadTempDir->path()); QList args; args << KrServices::toStringList(urlList); args << dest; UserEvent * downloadEvent = new UserEvent(CMD_DOWNLOAD_FILES, args); QList * result = _job->getEventResponse(downloadEvent); if (result == 0) return QUrl(); int errorCode = (*result)[ 0 ].value(); QString errorText = (*result)[ 1 ].value(); delete result; if (errorCode) { sendError(errorCode, errorText); return QUrl(); } else { return dest; } } else { return baseUrl; } } QString AbstractJobThread::tempFileIfRemote(const QUrl &kurl, const QString &type) { if (kurl.isLocalFile()) { return kurl.path(); } _tempFile = new QTemporaryFile(QDir::tempPath() + QLatin1String("/krusader_XXXXXX.") + type); _tempFile->open(); _tempFileName = _tempFile->fileName(); _tempFile->close(); // necessary to create the filename QFile::remove(_tempFileName); _tempFileTarget = kurl; return _tempFileName; } QString AbstractJobThread::tempDirIfRemote(const QUrl &kurl) { if (kurl.isLocalFile()) { return kurl.adjusted(QUrl::StripTrailingSlash).path(); } _tempDir = new QTemporaryDir(); _tempDirTarget = kurl; return _tempDirName = _tempDir->path(); } void AbstractJobThread::sendSuccess() { terminate(); QList args; UserEvent * errorEvent = new UserEvent(CMD_SUCCESS, args); _job->sendEvent(errorEvent); } void AbstractJobThread::sendError(int errorCode, QString message) { terminate(); QList args; args << errorCode; args << message; UserEvent * errorEvent = new UserEvent(CMD_ERROR, args); _job->sendEvent(errorEvent); } void AbstractJobThread::sendInfo(QString message, QString a1, QString a2, QString a3, QString a4) { QList args; args << message; args << a1; args << a2; args << a3; args << a4; UserEvent * infoEvent = new UserEvent(CMD_INFO, args); _job->sendEvent(infoEvent); } void AbstractJobThread::sendReset(QString message, QString a1, QString a2, QString a3, QString a4) { QList args; args << message; args << a1; args << a2; args << a3; args << a4; UserEvent * infoEvent = new UserEvent(CMD_RESET, args); _job->sendEvent(infoEvent); } void AbstractJobThread::sendMaxProgressValue(qulonglong value) { QList args; args << value; UserEvent * infoEvent = new UserEvent(CMD_MAXPROGRESSVALUE, args); _job->sendEvent(infoEvent); } void AbstractJobThread::sendAddProgress(qulonglong value, const QString &progress) { QList args; args << value; if (!progress.isNull()) args << progress; UserEvent * infoEvent = new UserEvent(CMD_ADD_PROGRESS, args); _job->sendEvent(infoEvent); } void AbstractJobThread::calcSpaceLocal(const QUrl &baseUrl, const QStringList & files, KIO::filesize_t &totalSize, unsigned long &totalDirs, unsigned long &totalFiles) { sendReset(i18n("Calculating space")); vfs *calcSpaceVfs = KrVfsHandler::instance().getVfs(baseUrl); KIO::JobUiDelegate *ui = static_cast(_job->uiDelegate()); if(ui) calcSpaceVfs->setParentWindow(ui->window()); calcSpaceVfs->vfs_refresh(baseUrl); for (int i = 0; i != files.count(); i++) { calcSpaceVfs->vfs_calcSpaceLocal(files[ i ], &totalSize, &totalFiles, &totalDirs, &_exited); } delete calcSpaceVfs; } KRarcObserver * AbstractJobThread::observer() { if (_observer) return _observer; _observer = new AbstractJobObserver(this); return _observer; } bool AbstractJobThread::uploadTempFiles() { if (_tempFile != 0 || _tempDir != 0) { sendInfo(i18n("Uploading to remote destination")); if (_tempFile) { QList urlList; urlList << QUrl::fromLocalFile(_tempFileName); QList args; args << KrServices::toStringList(urlList); args << _tempFileTarget; UserEvent * uploadEvent = new UserEvent(CMD_UPLOAD_FILES, args); QList * result = _job->getEventResponse(uploadEvent); if (result == 0) return false; int errorCode = (*result)[ 0 ].value(); QString errorText = (*result)[ 1 ].value(); delete result; if (errorCode) { sendError(errorCode, errorText); return false; } } if (_tempDir) { QList urlList; QDir tempDir(_tempDirName); QStringList list = tempDir.entryList(); foreach(const QString &name, list) { if (name == "." || name == "..") continue; QUrl url = QUrl::fromLocalFile(_tempDirName).adjusted(QUrl::StripTrailingSlash); url.setPath(url.path() + '/' + (name)); urlList << url; } QList args; args << KrServices::toStringList(urlList); args << _tempDirTarget; UserEvent * uploadEvent = new UserEvent(CMD_UPLOAD_FILES, args); QList * result = _job->getEventResponse(uploadEvent); if (result == 0) return false; int errorCode = (*result)[ 0 ].value(); QString errorText = (*result)[ 1 ].value(); delete result; if (errorCode) { sendError(errorCode, errorText); return false; } } } return true; } QString AbstractJobThread::getPassword(const QString &path) { QList args; args << path; UserEvent * getPasswdEvent = new UserEvent(CMD_GET_PASSWORD, args); QList * result = _job->getEventResponse(getPasswdEvent); if (result == 0) return QString(); QString password = (*result)[ 0 ].value(); if (password.isNull()) password = QString(""); delete result; return password; } void AbstractJobThread::sendMessage(const QString &message) { QList args; args << message; UserEvent * getPasswdEvent = new UserEvent(CMD_MESSAGE, args); QList * result = _job->getEventResponse(getPasswdEvent); if (result == 0) return; delete result; } //! Gets some archive information that is needed in several cases. /*! \param path A path to the archive. \param type The type of the archive. \param password The password of the archive. \param arcName The name of the archive. \param sourceFolder A QUrl, which may be remote, of the folder where the archive is. \return If the archive information has been obtained. */ bool AbstractJobThread::getArchiveInformation(QString &path, QString &type, QString &password, QString &arcName, const QUrl &sourceFolder) { // Safety checks (though the user shouldn't have been able to select something named "" or "..") if (arcName.isEmpty()) return false; if (arcName == "..") return false; QUrl url = sourceFolder.adjusted(QUrl::StripTrailingSlash); url.setPath(url.path() + '/' + arcName); path = url.adjusted(QUrl::StripTrailingSlash).path(); QMimeDatabase db; QMimeType mt = db.mimeTypeForUrl(url); QString mime = mt.isValid() ? mt.name() : QString(); bool encrypted = false; type = arcHandler.getType(encrypted, path, mime); // Check that the archive is supported if (!KRarcHandler::arcSupported(type)) { sendError(KIO::ERR_NO_CONTENT, i18nc("%1=archive filename", "%1, unsupported archive type.", arcName)); return false; } password = encrypted ? getPassword(path) : QString(); return true; } diff --git a/krusader/VFS/default_vfs.cpp b/krusader/VFS/default_vfs.cpp index 4035d539..512f0ccf 100644 --- a/krusader/VFS/default_vfs.cpp +++ b/krusader/VFS/default_vfs.cpp @@ -1,345 +1,345 @@ /*************************************************************************** default_vfs.cpp ------------------- copyright : (C) 2000 by Rafi Yanai e-mail : krusader@users.sourceforge.net web site : http://krusader.sourceforge.net --------------------------------------------------------------------------- *************************************************************************** A db dD d8888b. db db .d8888. .d8b. d8888b. d88888b d8888b. 88 ,8P' 88 `8D 88 88 88' YP d8' `8b 88 `8D 88' 88 `8D 88,8P 88oobY' 88 88 `8bo. 88ooo88 88 88 88ooooo 88oobY' 88`8b 88`8b 88 88 `Y8b. 88~~~88 88 88 88~~~~~ 88`8b 88 `88. 88 `88. 88b d88 db 8D 88 88 88 .8D 88. 88 `88. YP YD 88 YD ~Y8888P' `8888Y' YP YP Y8888D' Y88888P 88 YD S o u r c e F i l e *************************************************************************** * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #include "default_vfs.h" // QtCore #include #include #include #include #include #include #include #include #include #include #include "krpermhandler.h" #include "../defaults.h" #include "../krglobal.h" #include "../krservices.h" #include "../MountMan/kmountman.h" default_vfs::default_vfs(QObject* parent): vfs(parent), watcher(0) { vfs_type = VFS_NORMAL; } void default_vfs::vfs_addFiles(const QList &fileUrls, KIO::CopyJob::CopyMode mode, - QObject *toNotify, QString dir, PreserveMode /*pmode*/) + QObject *toNotify, QString dir) { //if (watcher) watcher->stopScan(); QUrl destination(vfs_origin); if (!dir.isEmpty()) { destination.setPath(QDir::cleanPath(destination.path() + '/' + dir)); if (destination.scheme() == "tar" || destination.scheme() == "zip" || destination.scheme() == "krarc") { if (QDir(destination.adjusted(QUrl::StripTrailingSlash).path()).exists()) destination.setScheme("file"); // if we get out from the archive change the protocol } } KIO::Job *job = 0; switch (mode) { case KIO::CopyJob::Copy: job = KIO::copy(fileUrls, destination); break; case KIO::CopyJob::Move: job = KIO::move(fileUrls, destination); break; case KIO::CopyJob::Link: job = KIO::link(fileUrls, destination); break; } connect(job, SIGNAL(result(KJob *)), this, SLOT(slotJobResult(KJob *))); if (toNotify && mode == KIO::CopyJob::Move) { // notify the other panel connect(job, SIGNAL(result(KJob *)), toNotify, SLOT(vfs_refresh(KJob *))); } } void default_vfs::vfs_drop(const QUrl &destination, QDropEvent *event) { //if (watcher) watcher->stopScan(); KIO::DropJob *job = KIO::drop(event, destination); connect(job, SIGNAL(result(KJob*)), this, SLOT(slotJobResult(KJob *))); QObject *dropSource = event->source(); if (dropSource) { // refresh source because files may have been removed connect(job, SIGNAL(result(KJob*)), dropSource, SLOT(vfs_refresh(KJob*))); } } void default_vfs::vfs_delFiles(const QStringList &fileNames, bool reallyDelete) { //if (watcher) watcher->stopScan(); // get absolute URLs for file names QList filesUrls = vfs_getFiles(fileNames); // create job: delete of move to trash ? KIO::Job *job; KConfigGroup group(krConfig, "General"); if (!reallyDelete && group.readEntry("Move To Trash", _MoveToTrash)) { job = KIO::trash(filesUrls); emit trashJobStarted(job); } else { job = KIO::del(filesUrls); } connect(job, SIGNAL(result(KJob*)), this, SLOT(slotJobResult(KJob*))); } QUrl default_vfs::vfs_getFile(const QString& name) { QUrl absoluteUrl(vfs_origin); absoluteUrl.setPath(absoluteUrl.path() + "/" + name); return absoluteUrl; } QList default_vfs::vfs_getFiles(const QStringList &names) { QList urls; foreach (const QString &name, names) { urls.append(vfs_getFile(name)); } return urls; } void default_vfs::vfs_mkdir(const QString& name) { KIO::SimpleJob* job = KIO::mkdir(vfs_getFile(name)); connect(job, SIGNAL(result(KJob*)), this, SLOT(slotJobResult(KJob*))); } void default_vfs::vfs_rename(const QString& oldName, const QString& newName) { QUrl oldUrl = vfs_getFile(oldName); QUrl newUrl = vfs_getFile(newName); KIO::Job *job = KIO::moveAs(oldUrl, newUrl, KIO::HideProgressInfo); connect(job, SIGNAL(result(KJob *)), this, SLOT(slotJobResult(KJob *))); } // ==== protected ==== bool default_vfs::populateVfsList(const QUrl &origin, bool showHidden) { delete watcher; // stop watching the old dir QString errorMsg; if (!origin.isValid()) { errorMsg = i18n("Malformed URL:\n%1", origin.url()); } else if (!KProtocolManager::supportsListing(origin)) { errorMsg = i18n("Protocol not supported by Krusader:\n%1", origin.url()); } if (!errorMsg.isEmpty()) { if (!quietMode) { emit error(errorMsg); } return false; } if (origin.isLocalFile()) { QString path = KrServices::urlToLocalPath(origin); #ifdef Q_WS_WIN if (!path.contains("/")) { // change C: to C:/ path = path + QString("/"); } #endif // check if the new origin exists if (!QDir(path).exists()) { if (!quietMode) emit error(i18n("The folder %1 does not exist.", path)); return false; } KConfigGroup group(krConfig, "Advanced"); if (group.readEntry("AutoMount", _AutoMount) && !mountMan.isNull()) mountMan->autoMount(path); // set the origin... vfs_origin = origin; vfs_origin.setPath(path); vfs_origin.setPath(QDir::cleanPath(vfs_origin.path())); } else { vfs_origin = origin.adjusted(QUrl::StripTrailingSlash); } // start the listing job KIO::ListJob *job = KIO::listDir(vfs_origin, KIO::HideProgressInfo, showHidden); connect(job, SIGNAL(entries(KIO::Job *, const KIO::UDSEntryList &)), this, SLOT(slotAddFiles(KIO::Job *, const KIO::UDSEntryList &))); connect(job, &KIO::ListJob::redirection, [=](KIO::Job *, const QUrl &url) { slotRedirection(url); }); connect(job, &KIO::ListJob::permanentRedirection, [=](KIO::Job *, const QUrl &, const QUrl &url) { slotRedirection(url); }); connect(job, SIGNAL(result(KJob*)), this, SLOT(slotListResult(KJob*))); if(!parentWindow.isNull()) { KIO::JobUiDelegate *ui = static_cast(job->uiDelegate()); ui->setWindow(parentWindow); } if (!quietMode) { emit startJob(job); } listError = false; // ugly: we have to wait here until the list job is finished QEventLoop eventLoop; connect(job, SIGNAL(result(KJob*)), &eventLoop, SLOT(quit())); eventLoop.exec(); // blocking until quit() if (panelConnected && vfs_origin.isLocalFile()) { // start watching the new dir for file changes watcher = new KDirWatch(this); connect(watcher, SIGNAL(dirty(const QString&)), this, SLOT(slotWatcherDirty(const QString&))); connect(watcher, SIGNAL(created(const QString&)), this, SLOT(slotWatcherCreated(const QString&))); connect(watcher, SIGNAL(deleted(const QString&)), this, SLOT(slotWatcherDeleted(const QString&))); watcher->addDir(vfs_getOrigin().toLocalFile(), KDirWatch::WatchFiles); watcher->startScan(false); } return !listError; } // ==== slots ==== void default_vfs::slotJobResult(KJob *job) { if (job->error() && job->uiDelegate()) { job->uiDelegate()->showErrorMessage(); } vfs_refresh(); return; } void default_vfs::slotAddFiles(KIO::Job *, const KIO::UDSEntryList& entries) { int rwx = -1; QString prot = vfs_origin.scheme(); if (prot == "krarc" || prot == "tar" || prot == "zip") rwx = PERM_ALL; // add all files to the vfs for (const KIO::UDSEntry entry : entries) { KFileItem kfi(entry, vfs_origin, true, true); vfile *temp; // get file statistics QString name = kfi.text(); // ignore un-needed entries // TODO do not filter ".." here if (name.isEmpty() || name == "." || name == "..") continue; KIO::filesize_t size = kfi.size(); time_t mtime = kfi.time(KFileItem::ModificationTime).toTime_t(); bool symLink = kfi.isLink(); mode_t mode = kfi.mode() | kfi.permissions(); QString perm = KRpermHandler::mode2QString(mode); // set the mimetype QString mime = kfi.mimetype(); QString symDest = ""; if (symLink) { symDest = kfi.linkDest(); if (kfi.isDir()) perm[0] = 'd'; } // create a new virtual file object if (kfi.user().isEmpty()) temp = new vfile(name, size, perm, mtime, symLink, false, getuid(), getgid(), mime, symDest, mode, rwx); else { QString currentUser = vfs_origin.userName(); if (currentUser.contains("@")) /* remove the FTP proxy tags from the username */ currentUser.truncate(currentUser.indexOf('@')); if (currentUser.isEmpty()) { if (vfs_origin.host().isEmpty()) { currentUser = KRpermHandler::uid2user(getuid()); } else { currentUser = ""; // empty, but not QString() } } temp = new vfile(name, size, perm, mtime, symLink, false, kfi.user(), kfi.group(), currentUser, mime, symDest, mode, rwx, kfi.ACL().asString(), kfi.defaultACL().asString()); } if (!kfi.localPath().isEmpty()) { temp->vfile_setUrl(QUrl::fromLocalFile(kfi.localPath())); } else { temp->vfile_setUrl(kfi.url()); } temp->vfile_setIcon(kfi.iconName()); foundVfile(temp); } } void default_vfs::slotRedirection(const QUrl &url) { // update the origin vfs_origin = url.adjusted(QUrl::StripTrailingSlash); } void default_vfs::slotListResult(KJob *job) { if (job && job->error()) { // we failed to refresh listError = true; // display error message if (!quietMode) { emit error(job->errorString()); } } } void default_vfs::slotWatcherDirty(const QString& path) { // TODO } void default_vfs::slotWatcherCreated(const QString& path) { // TODO } void default_vfs::slotWatcherDeleted(const QString& path) { // TODO } diff --git a/krusader/VFS/default_vfs.h b/krusader/VFS/default_vfs.h index 41d9ef62..996844f1 100644 --- a/krusader/VFS/default_vfs.h +++ b/krusader/VFS/default_vfs.h @@ -1,88 +1,86 @@ /*************************************************************************** default_vfs.h ------------------- begin : Thu May 4 2000 copyright : (C) 2000 by Shie Erlich & Rafi Yanai e-mail : krusader@users.sourceforge.net web site : http://krusader.sourceforge.net *************************************************************************** A db dD d8888b. db db .d8888. .d8b. d8888b. d88888b d8888b. 88 ,8P' 88 `8D 88 88 88' YP d8' `8b 88 `8D 88' 88 `8D 88,8P 88oobY' 88 88 `8bo. 88ooo88 88 88 88ooooo 88oobY' 88`8b 88`8b 88 88 `Y8b. 88~~~88 88 88 88~~~~~ 88`8b 88 `88. 88 `88. 88b d88 db 8D 88 88 88 .8D 88. 88 `88. YP YD 88 YD ~Y8888P' `8888Y' YP YP Y8888D' Y88888P 88 YD H e a d e r F i l e *************************************************************************** * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #ifndef DEFAULT_VFS_H #define DEFAULT_VFS_H #include "vfs.h" #include -#include "preservingcopyjob.h" - /** * @brief Default filesystem implementation supporting all KIO protocols * * This vfs implementation allows file operations and listing of all supported KIO protocls (local, * virtual and remote/network). * */ class default_vfs : public vfs { Q_OBJECT public: default_vfs(QObject *parent); ~default_vfs() {} virtual void vfs_addFiles(const QList &fileUrls, KIO::CopyJob::CopyMode mode, - QObject *toNotify, QString dir = "", PreserveMode pmode = PM_DEFAULT) Q_DECL_OVERRIDE; + QObject *toNotify, QString dir = "") Q_DECL_OVERRIDE; virtual void vfs_drop(const QUrl &destination, QDropEvent *event) Q_DECL_OVERRIDE; virtual void vfs_delFiles(const QStringList &fileNames, bool reallyDelete = false) Q_DECL_OVERRIDE; virtual QList vfs_getFiles(const QStringList &names) Q_DECL_OVERRIDE; virtual QUrl vfs_getFile(const QString &name) Q_DECL_OVERRIDE; virtual void vfs_mkdir(const QString &name) Q_DECL_OVERRIDE; virtual void vfs_rename(const QString &fileName, const QString &newName) Q_DECL_OVERRIDE; virtual QString vfs_workingDir() Q_DECL_OVERRIDE { return vfs_origin.path(); } protected: virtual bool populateVfsList(const QUrl &origin, bool showHidden) Q_DECL_OVERRIDE; protected slots: // handle result after job (except listing job!) finished void slotJobResult(KJob *job); // fill directory file list with new files from the dir lister void slotAddFiles(KIO::Job *job, const KIO::UDSEntryList &entries); // redirection signal from dir lister void slotRedirection(const QUrl &url); // handle result after dir listing job is finished void slotListResult(KJob *job); // react to filesystem changes nofified by watcher void slotWatcherDirty(const QString &path); void slotWatcherCreated(const QString &path); void slotWatcherDeleted(const QString &path); private: KDirWatch *watcher; // dir watcher used to detect changes in the current dir bool listError; // for async operation, return list job result }; #endif diff --git a/krusader/VFS/preservingcopyjob.cpp b/krusader/VFS/preservingcopyjob.cpp deleted file mode 100644 index 2981becf..00000000 --- a/krusader/VFS/preservingcopyjob.cpp +++ /dev/null @@ -1,64 +0,0 @@ -/*************************************************************************** - preservingcopyjob.cpp - description - ------------------- - copyright : (C) 2005 + by Csaba Karai - e-mail : krusader@users.sourceforge.net - web site : http://krusader.sourceforge.net - --------------------------------------------------------------------------- - Description - *************************************************************************** - - A - - db dD d8888b. db db .d8888. .d8b. d8888b. d88888b d8888b. - 88 ,8P' 88 `8D 88 88 88' YP d8' `8b 88 `8D 88' 88 `8D - 88,8P 88oobY' 88 88 `8bo. 88ooo88 88 88 88ooooo 88oobY' - 88`8b 88`8b 88 88 `Y8b. 88~~~88 88 88 88~~~~~ 88`8b - 88 `88. 88 `88. 88b d88 db 8D 88 88 88 .8D 88. 88 `88. - YP YD 88 YD ~Y8888P' `8888Y' YP YP Y8888D' Y88888P 88 YD - - S o u r c e F i l e - - *************************************************************************** - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * - * (at your option) any later version. * - * * - ***************************************************************************/ - -#include "preservingcopyjob.h" -#include "../defaults.h" -#include "../krglobal.h" - -#include -#include - - -KIO::Job * PreservingCopyJob::createCopyJob(PreserveMode pmode, const QList& src, const QUrl &dest, KIO::CopyJob::CopyMode mode, bool /*asMethod*/, bool showProgressInfo) -{ - switch (pmode) { - // KIO always preserves attributes - -// case PM_DEFAULT: { -// KConfigGroup grp(krConfig, "Advanced"); -// bool preserve = grp.readEntry("PreserveAttributes", _PreserveAttributes); -// } -// // case PM_NONE: -// case PM_PRESERVE_ATTR: - default: { - switch (mode) { - case KIO::CopyJob::Copy: - return KIO::copy(src, dest, showProgressInfo ? KIO::DefaultFlags : KIO::HideProgressInfo); - case KIO::CopyJob::Move: - return KIO::move(src, dest, showProgressInfo ? KIO::DefaultFlags : KIO::HideProgressInfo); - case KIO::CopyJob::Link: - return KIO::link(src, dest, showProgressInfo ? KIO::DefaultFlags : KIO::HideProgressInfo); - default: - return 0; - } - } - } -} - diff --git a/krusader/VFS/preservingcopyjob.h b/krusader/VFS/preservingcopyjob.h deleted file mode 100644 index 57f373fa..00000000 --- a/krusader/VFS/preservingcopyjob.h +++ /dev/null @@ -1,54 +0,0 @@ -/*************************************************************************** - preservingcopyjob.h - description - ------------------- - copyright : (C) 2005 + by Csaba Karai - e-mail : krusader@users.sourceforge.net - web site : http://krusader.sourceforge.net - --------------------------------------------------------------------------- - Description - *************************************************************************** - - A - - db dD d8888b. db db .d8888. .d8b. d8888b. d88888b d8888b. - 88 ,8P' 88 `8D 88 88 88' YP d8' `8b 88 `8D 88' 88 `8D - 88,8P 88oobY' 88 88 `8bo. 88ooo88 88 88 88ooooo 88oobY' - 88`8b 88`8b 88 88 `Y8b. 88~~~88 88 88 88~~~~~ 88`8b - 88 `88. 88 `88. 88b d88 db 8D 88 88 88 .8D 88. 88 `88. - YP YD 88 YD ~Y8888P' `8888Y' YP YP Y8888D' Y88888P 88 YD - - H e a d e r F i l e - - *************************************************************************** - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * - * (at your option) any later version. * - * * - ***************************************************************************/ - -#ifndef PRESERVINGCOPYJOB_H -#define PRESERVINGCOPYJOB_H - -// QtCore -#include -#include -#include - -#include - -typedef enum { - PM_NONE = 0, - PM_PRESERVE_ATTR = 1, - PM_DEFAULT = 2 -} PreserveMode; - -class PreservingCopyJob -{ - -public: - static KIO::Job *createCopyJob(PreserveMode pmode, const QList& src, const QUrl &dest, KIO::CopyJob::CopyMode mode, bool /* asMethod */, bool showProgressInfo); -}; - -#endif /* __PRESERVING_COPY_JOB_H__ */ diff --git a/krusader/VFS/vfs.h b/krusader/VFS/vfs.h index 56a305dd..76b6a9e0 100644 --- a/krusader/VFS/vfs.h +++ b/krusader/VFS/vfs.h @@ -1,239 +1,241 @@ /*************************************************************************** vfs.h ------------------- begin : Thu May 4 2000 copyright : (C) 2000 by Shie Erlich & Rafi Yanai e-mail : krusader@users.sourceforge.net web site : http://krusader.sourceforge.net *************************************************************************** A db dD d8888b. db db .d8888. .d8b. d8888b. d88888b d8888b. 88 ,8P' 88 `8D 88 88 88' YP d8' `8b 88 `8D 88' 88 `8D 88,8P 88oobY' 88 88 `8bo. 88ooo88 88 88 88ooooo 88oobY' 88`8b 88`8b 88 88 `Y8b. 88~~~88 88 88 88~~~~~ 88`8b 88 `88. 88 `88. 88b d88 db 8D 88 88 88 .8D 88. 88 `88. YP YD 88 YD ~Y8888P' `8888Y' YP YP Y8888D' Y88888P 88 YD H e a d e r F i l e *************************************************************************** * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #ifndef VFS_H #define VFS_H #include "vfilecontainer.h" // QtCore #include #include #include #include #include #include // QtGui #include // QtWidgets #include +#include + #include "vfile.h" -#include "preservingcopyjob.h" #include "krquery.h" class KMountMan; /** * The vfs class is an extendable class which by itself does (almost) * nothing. other VFSs like the normal_vfs inherits from this class and * make it possible to use a consistent API for all types of VFSs. */ class vfs : public VfileContainer { Q_OBJECT public: typedef QHash vfileDict; enum VFS_TYPE {VFS_ERROR = 0, VFS_NORMAL, VFS_FTP, VFS_VIRT}; /** * Creates a vfs. * @param panel the panel father * @param quiet if true, the VFS will not display error messages */ vfs(QObject* panel, bool quiet = false); virtual ~vfs(); // VfileContainer implementation virtual QList vfiles() { return vfs_filesP->values(); } virtual unsigned long numVfiles() { return vfs_filesP->count(); } virtual bool isRoot(); /// Copy (copy, move or link) files to the vfs (physical). Copy destination is "dir", the /// directory name to copy to relative to the current dir. May implemented async. - virtual void vfs_addFiles(const QList &fileUrls, KIO::CopyJob::CopyMode mode, QObject* toNotify, QString dir = "", PreserveMode pmode = PM_DEFAULT) = 0; + virtual void vfs_addFiles(const QList &fileUrls, KIO::CopyJob::CopyMode mode, + QObject *toNotify, QString dir = "") = 0; /// Handle file dropping in this vfs. Destination is absolute URL. May implemented async. virtual void vfs_drop(const QUrl &destination, QDropEvent *event) = 0; /// Remove a file from the vfs (physical). May implemented async. virtual void vfs_delFiles(const QStringList &fileNames, bool reallyDelete = false) = 0; /// Return a list of URLs for multiple files virtual QList vfs_getFiles(const QStringList &names) = 0; /// Return a URL to a single file, with no trailing slash virtual QUrl vfs_getFile(const QString& name) = 0; /// Create a new directory virtual void vfs_mkdir(const QString& name) = 0; /// Rename file. May implemented async. virtual void vfs_rename(const QString& fileName, const QString& newName) = 0; /// Calculate the amount of space occupied by a file or directory (recursive). virtual void vfs_calcSpace(QString name , KIO::filesize_t *totalSize, unsigned long *totalFiles, unsigned long *totalDirs, bool * stop); /// Calculate the amount of space occupied by a local file or directory (recursive). virtual void vfs_calcSpaceLocal(QString name , KIO::filesize_t *totalSize, unsigned long *totalFiles, unsigned long *totalDirs, bool * stop); /// Return the VFS working dir virtual QString vfs_workingDir() = 0; /// Return true if the VFS url is writable virtual bool vfs_isWritable() { return isWritable; } /// Return vfile* or 0 if not found inline vfile* vfs_search(const QString& name) { return (*vfs_filesP)[name]; } /// Return an empty vfile* list if not found QList vfs_search(const KRQuery& filter); /// The total size of all the files in the VFS, KIO::filesize_t vfs_totalSize(); /// Returns the VFS url. inline QUrl vfs_getOrigin() { return vfs_origin; } /// Return the VFS type. inline VFS_TYPE vfs_getType() { return vfs_type; } /// Returns true if vfs is busy inline bool vfs_isBusy() { return vfs_busy; } /// Returns true if hidden files has to be shown bool vfs_showHidden(); /// Return the first file in the VFS and set the internal iterator to the beginning of the list. inline vfile* vfs_getFirstFile() { vfileIterator = vfs_filesP->begin(); return (vfileIterator == vfs_filesP->end() ? 0 : *vfileIterator); } /// Return the next file in the list and advance the iterator. inline vfile* vfs_getNextFile() { if (vfileIterator == vfs_filesP->end() || ++vfileIterator == vfs_filesP->end()) return 0; else return *vfileIterator; } /// returns true if the vfs can be deleted without crash virtual bool vfs_canDelete() { return deletePossible; } /// process the application events virtual bool vfs_processEvents(); /// process the application events virtual void vfs_requestDelete(); /// process the application events virtual bool vfs_isDeleting() { return deleteRequested; } virtual QString metaInformation() { return QString(); } // set the parent window to be used for dialogs void setParentWindow(QWidget *widget) { parentWindow = widget; } // set the mount manager void setMountMan(KMountMan *mtMan); static QUrl ensureTrailingSlash(const QUrl &url); public slots: /// Re-reads files and stats and fills the vfile list bool vfs_refresh(const QUrl &origin); /// Used to refresh the VFS when a job finishs. it calls the refresh() slot /// or display a error message if the job fails bool vfs_refresh(KJob * job); bool vfs_refresh(); void vfs_setQuiet(bool beQuiet) { quietMode = beQuiet; } bool vfs_enableRefresh(bool enable); void vfs_invalidate() { invalidated = true; } signals: void startJob(KIO::Job* job); void incrementalRefreshFinished(const QUrl&); //< emitted when the incremental refresh was finished void deleteAllowed(); void trashJobStarted(KIO::Job *job); void error(QString msg); protected: /// Feel the vfs dictionary with vfiles, must be implemented for each vfs virtual bool populateVfsList(const QUrl &origin, bool showHidden) = 0; /// Called by populateVfsList for each file void foundVfile(vfile *vf) { vfs_tempFilesP->insert(vf->vfile_getName(), vf); } /// Set the vfile list pointer void setVfsFilesP(vfileDict* dict); /// clear and delete all current vfiles inline void clear(); /// Add a new vfile to the list. inline void addToList(vfile *data) { vfs_filesP->insert(data->vfile_getName(), data); } /// Deletes a vfile from the list. inline void removeFromList(QString name) { vfs_filesP->remove(name); } void calculateURLSize(QUrl url, KIO::filesize_t *totalSize, unsigned long *totalFiles, unsigned long *totalDirs, bool * stop); VFS_TYPE vfs_type; //< the vfs type. QUrl vfs_origin; //< the path or file the VFS originates from. bool vfs_busy; //< true if vfs is busy with refreshing bool quietMode; //< if true the vfs won't display error messages or emit signals bool disableRefresh; //< true if refresh is disabled bool isWritable; //< true if it's writable QUrl postponedRefreshURL; //< true if vfs_refresh() was called when refresh is disabled. bool invalidated; //< the content of the cache is invalidated bool panelConnected; //< indicates that there's a panel connected. Important for disabling the dir watcher QPointer parentWindow; QPointer mountMan; protected slots: /// The slot for the KIO::DirectorySizeJob void slotKdsResult(KJob *job); void slotStatResultArrived(KJob *job); private: vfileDict* vfs_filesP; //< Point to a lists of virtual files (vfile). vfileDict* vfs_tempFilesP;//< Temporary files are stored here QHash::iterator vfileIterator; //< Point to a dictionary of virtual files (vfile). // used in the calcSpace function bool* kds_busy; bool stat_busy; bool deletePossible; bool deleteRequested; KIO::UDSEntry entry; KIO::filesize_t* kds_totalSize; unsigned long* kds_totalFiles; unsigned long* kds_totalDirs; }; #endif diff --git a/krusader/VFS/virt_vfs.cpp b/krusader/VFS/virt_vfs.cpp index 52eababc..86ed222b 100644 --- a/krusader/VFS/virt_vfs.cpp +++ b/krusader/VFS/virt_vfs.cpp @@ -1,383 +1,383 @@ /***************************************************************************** * Copyright (C) 2003 Shie Erlich * * Copyright (C) 2003 Rafi Yanai * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This package 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 General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this package; if not, write to the Free Software * * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * *****************************************************************************/ #include "virt_vfs.h" // QtCore #include #include #include #include #include #include #include #include #include #include "krpermhandler.h" #include "../krglobal.h" #include "../krservices.h" #include "../defaults.h" #define VIRT_VFS_DB "virt_vfs.db" QHash *> virt_vfs::virtVfsDict; QHash virt_vfs::metaInfoDict; KConfig* virt_vfs::virt_vfs_db = 0; virt_vfs::virt_vfs(QObject* panel, bool quiet) : vfs(panel, quiet) { // set the writable attribute isWritable = true; if (virtVfsDict.isEmpty()) { restore(); } vfs_type = VFS_VIRT; } virt_vfs::~virt_vfs() {} bool virt_vfs::populateVfsList(const QUrl &origin, bool /*showHidden*/) { vfs_origin = origin.adjusted(QUrl::StripTrailingSlash); path = origin.adjusted(QUrl::StripTrailingSlash).path().mid(1); if (path.isEmpty()) path = '/'; QList* urlList; if (virtVfsDict.find(path) == virtVfsDict.end()) { urlList = new QList(); virtVfsDict.insert(path, urlList); virtVfsDict[ "/" ] ->append(QUrl("virt:/" + path)); } else { urlList = virtVfsDict[ path ]; metaInfo = metaInfoDict[ path ]; } save(); if (urlList->isEmpty()) return true; QList::iterator it; for (it = urlList->begin() ; it != urlList->end() ; /*++it*/) { QUrl url = *it; // translate url->vfile and remove urls that no longer exist from the list vfile* vf = stat(url); if (!vf) { it = urlList->erase(it); // the iterator is advanced automatically continue; } foundVfile(vf); ++it; } return true; } -void virt_vfs::vfs_addFiles(const QList &fileUrls, KIO::CopyJob::CopyMode /*mode*/, QObject* /*toNotify*/, QString /*dir*/, PreserveMode /*pmode*/) +void virt_vfs::vfs_addFiles(const QList &fileUrls, KIO::CopyJob::CopyMode /*mode*/, QObject* /*toNotify*/, QString /*dir*/) { if (path == "/") { if (!quietMode) KMessageBox::error(parentWindow, i18n("You cannot copy files directly to the 'virt:/' folder.\nYou can create a sub folder and copy your files into it."), i18n("Error")); return ; } if (virtVfsDict.find(path) == virtVfsDict.end()) { QList *urlList = new QList(); virtVfsDict.insert(path, urlList); virtVfsDict[ "/" ] ->append(QUrl("virt:/" + path)); } QList* urlList = virtVfsDict[ path ]; foreach (const QUrl &fileUrl, fileUrls) { if (!urlList->contains(fileUrl)) urlList->push_back(fileUrl); } vfs_refresh(); } // TODO dropping to another directory in this vfs implementation is currently not supported void virt_vfs::vfs_drop(const QUrl &/*destination*/, QDropEvent *event) { QList urls = KUrlMimeData::urlsFromMimeData(event->mimeData()); // dropping on virtual vfs (sic!) is always copy operation vfs_addFiles(urls, KIO::CopyJob::Copy, 0); } void virt_vfs::vfs_delFiles(const QStringList &fileNames, bool reallyDelete) { if (path == "/") { foreach (const QString &filename, fileNames) { virtVfsDict[ "/" ] ->removeAll(QUrl(QStringLiteral("virt:/") + filename)); delete virtVfsDict[ filename ]; virtVfsDict.remove(filename); metaInfoDict.remove(filename); } vfs_refresh(); return ; } // names -> urls QList filesUrls = vfs_getFiles(fileNames); KIO::Job *job; // delete of move to trash ? KConfigGroup group(krConfig, "General"); if (!reallyDelete && group.readEntry("Move To Trash", _MoveToTrash)) { job = KIO::trash(filesUrls); if(parentWindow) emit trashJobStarted(job); } else job = KIO::del(filesUrls); // refresh will remove the deleted files... connect(job, SIGNAL(result(KJob*)), this, SLOT(vfs_refresh(KJob*))); } void virt_vfs::vfs_removeFiles(QStringList *fileNames) { if (path == "/") return; // removing the URLs from the collection for (int i = 0 ; i < fileNames->count(); ++i) { if (virtVfsDict.find(path) != virtVfsDict.end()) { QList* urlList = virtVfsDict[ path ]; urlList->removeAll(vfs_getFile((*fileNames)[ i ])); } } vfs_refresh(); } QList virt_vfs::vfs_getFiles(const QStringList &names) { QUrl url; QList urls; foreach (const QString &name, names) { urls.append(vfs_getFile(name)); } return urls; } QUrl virt_vfs::vfs_getFile(const QString& name) { vfile * vf = vfs_search(name); if (!vf) return QUrl(); // empty return vf->vfile_getUrl(); } void virt_vfs::vfs_mkdir(const QString& name) { if (path != "/") { if (!quietMode) KMessageBox::error(parentWindow, i18n("Creating new folders is allowed only in the 'virt:/' folder."), i18n("Error")); return ; } QList* temp = new QList(); virtVfsDict.insert(name, temp); virtVfsDict[ "/" ] ->append(QUrl(QStringLiteral("virt:/") + name)); vfs_refresh(); } void virt_vfs::vfs_rename(const QString& fileName, const QString& newName) { vfile* vf = vfs_search(fileName); if (!vf) return ; // not found if (path == "/") { virtVfsDict[ "/" ] ->append(QUrl(QStringLiteral("virt:/") + newName)); virtVfsDict[ "/" ] ->removeAll(QUrl(QStringLiteral("virt:/") + fileName)); virtVfsDict.insert(newName, virtVfsDict.take(fileName)); vfs_refresh(); return ; } QUrl url = vf->vfile_getUrl(); QList fileUrls; fileUrls.append(url); QUrl dest = url; // keep same url scheme and host as source. dest.setPath(newName); // add the new url to the list // the list is refreshed only existing files remain - // so we don't have to worry if the job was successful virtVfsDict[ path ] ->append(dest); KIO::Job *job = KIO::move(fileUrls, dest); connect(job, SIGNAL(result(KJob*)), this, SLOT(vfs_refresh(KJob*))); } void virt_vfs::slotStatResult(KJob* job) { if (!job || job->error()) entry = KIO::UDSEntry(); else entry = static_cast(job)->statResult(); busy = false; } vfile* virt_vfs::stat(const QUrl &url) { if (url.scheme() == "virt") { QString path = url.path().mid(1); if (path.isEmpty()) path = '/'; vfile * temp = new vfile(path, 0, "drwxr-xr-x", time(0), false, false, getuid(), getgid(), "inode/directory", "", 0); temp->vfile_setUrl(url); return temp; } KFileItem* kfi; if (url.isLocalFile()) { kfi = new KFileItem(url); kfi->setDelayedMimeTypes(true); } else { busy = true; KIO::StatJob* statJob = KIO::stat(url, KIO::HideProgressInfo); connect(statJob, SIGNAL(result(KJob*)), this, SLOT(slotStatResult(KJob*))); while (busy && vfs_processEvents()); if (entry.count() == 0) return 0; // statJob failed kfi = new KFileItem(entry, url, true); } if (kfi->time(KFileItem::ModificationTime).isNull()) { delete kfi; return 0; // file not found } vfile *temp; // get file statistics QString name; if (url.isLocalFile()) name = url.path(); else name = url.toDisplayString(); KIO::filesize_t size = kfi->size(); time_t mtime = kfi->time(KFileItem::ModificationTime).toTime_t(); bool symLink = kfi->isLink(); mode_t mode = kfi->mode() | kfi->permissions(); QString perm = KRpermHandler::mode2QString(mode); // set the mimetype QString mime; QString symDest; if (symLink) { symDest = kfi->linkDest(); if (kfi->isDir()) perm[ 0 ] = 'd'; } // create a new virtual file object if (kfi->user().isEmpty()) temp = new vfile(name, size, perm, mtime, symLink, false, getuid(), getgid(), mime, symDest, mode); else { QString currentUser = url.userName(); if (currentUser.contains("@")) /* remove the FTP proxy tags from the username */ currentUser.truncate(currentUser.indexOf('@')); if (currentUser.isEmpty()) currentUser = KRpermHandler::uid2user(getuid()); temp = new vfile(name, size, perm, mtime, symLink, false, kfi->user(), kfi->group(), currentUser, mime, symDest, mode); } temp->vfile_setUrl(kfi->url()); delete kfi; return temp; } KConfig* virt_vfs::getVirtDB() { if (!virt_vfs_db) { // virt_vfs_db = new KConfig("data",VIRT_VFS_DB,KConfig::NoGlobals); virt_vfs_db = new KConfig(VIRT_VFS_DB, KConfig:: CascadeConfig, QStandardPaths::DataLocation); } return virt_vfs_db; } bool virt_vfs::save() { KConfig* db = getVirtDB(); db->deleteGroup("virt_db"); KConfigGroup group(db, "virt_db"); QHashIterator< QString, QList *> lit(virtVfsDict); while (lit.hasNext()) { QList * curr = lit.next().value(); QList::iterator url; QStringList entry; for (url = curr->begin() ; url != curr->end() ; ++url) { entry.append((*url).toDisplayString()); } // KDE 4.0 workaround, Item_ is added as KConfig fails on 1 char names (such as /) group.writeEntry("Item_" + lit.key(), entry); group.writeEntry("MetaInfo_" + lit.key(), metaInfoDict[lit.key()]); } db->sync(); return true; } bool virt_vfs::restore() { KConfig* db = getVirtDB(); KConfigGroup dbGrp(db, "virt_db"); QMap map = db->entryMap("virt_db"); QMap::Iterator it; QList* urlList; for (it = map.begin(); it != map.end(); ++it) { if(!it.key().startsWith(QLatin1String("Item_"))) continue; urlList = new QList(KrServices::toUrlList(dbGrp.readEntry(it.key(), QStringList()))); // KDE 4.0 workaround, Item_ is removed (KConfig fails on 1 char names (such as /)) QString key = it.key().mid(5); // remove Item_ virtVfsDict.insert(key, urlList); metaInfoDict.insert(key, dbGrp.readEntry("MetaInfo_" + key, QString())); } if (!virtVfsDict["/" ]) { urlList = new QList(); virtVfsDict.insert("/", urlList); } return true; } void virt_vfs::vfs_calcSpace(QString name , KIO::filesize_t* totalSize, unsigned long* totalFiles, unsigned long* totalDirs, bool* stop) { if (stop && *stop) return ; if (path == "/") { QList* urlList = virtVfsDict[ name ]; if (urlList) for (int i = 0; (i != urlList->size()) && !(*stop); i++) calculateURLSize((*urlList)[ i ], totalSize, totalFiles, totalDirs, stop); return; } return vfs::vfs_calcSpace(name, totalSize, totalFiles, totalDirs, stop); } void virt_vfs::setMetaInformation(QString info) { metaInfo = info; metaInfoDict[path] = metaInfo; vfs_refresh(); } diff --git a/krusader/VFS/virt_vfs.h b/krusader/VFS/virt_vfs.h index 67f7fd4a..4bd0ce49 100644 --- a/krusader/VFS/virt_vfs.h +++ b/krusader/VFS/virt_vfs.h @@ -1,89 +1,90 @@ /***************************************************************************** * Copyright (C) 2003 Shie Erlich * * Copyright (C) 2003 Rafi Yanai * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This package 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 General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this package; if not, write to the Free Software * * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * *****************************************************************************/ #ifndef VIRT_VFS_H #define VIRT_VFS_H // QtCore #include #include #include "vfs.h" class virt_vfs : public vfs { Q_OBJECT public: virt_vfs(QObject* panel, bool quiet = false); ~virt_vfs(); /// Copy a file to the vfs (physical). - void vfs_addFiles(const QList &fileUrls, KIO::CopyJob::CopyMode mode, QObject* toNotify, QString dir = "", PreserveMode pmode = PM_DEFAULT) Q_DECL_OVERRIDE; + void vfs_addFiles(const QList &fileUrls, KIO::CopyJob::CopyMode mode, QObject *toNotify, + QString dir = "") Q_DECL_OVERRIDE; /// Handle file drop virtual void vfs_drop(const QUrl &destination, QDropEvent *event) Q_DECL_OVERRIDE; /// Remove a file from the vfs (physical) void vfs_delFiles(const QStringList &fileNames, bool reallyDelete = true) Q_DECL_OVERRIDE; /// Remove a file from the collection (only its link, not the file) void vfs_removeFiles(QStringList *fileNames); /// Return a list of URLs for multiple files QList vfs_getFiles(const QStringList &names) Q_DECL_OVERRIDE; /// Return a URL to a single file QUrl vfs_getFile(const QString& name) Q_DECL_OVERRIDE; /// Create a new directory void vfs_mkdir(const QString& name) Q_DECL_OVERRIDE; /// Rename file void vfs_rename(const QString& fileName, const QString& newName) Q_DECL_OVERRIDE; /// Calculate the amount of space occupied by a file or directory (recursive). virtual void vfs_calcSpace(QString name , KIO::filesize_t *totalSize, unsigned long *totalFiles, unsigned long *totalDirs, bool * stop) Q_DECL_OVERRIDE; /// Return the VFS working dir QString vfs_workingDir() Q_DECL_OVERRIDE { return QString(); } virtual QString metaInformation() Q_DECL_OVERRIDE { return metaInfo; } void setMetaInformation(QString info); protected slots: void slotStatResult(KJob *job); protected: /// Save the dictionary to file bool save(); /// Restore the dictionary from file bool restore(); /// return the URLs DB KConfig* getVirtDB(); bool populateVfsList(const QUrl &origin, bool showHidden) Q_DECL_OVERRIDE; vfile* stat(const QUrl &url); static QHash *> virtVfsDict; static QHash metaInfoDict; static KConfig* virt_vfs_db; bool busy; QString path; QString metaInfo; KIO::UDSEntry entry; }; #endif