251 lines
8.3 KiB
C++
251 lines
8.3 KiB
C++
|
// vim: set tabstop=4 shiftwidth=4 expandtab:
|
||
|
/*
|
||
|
Gwenview: an image viewer
|
||
|
Copyright 2007 Aurélien Gâteau <agateau@kde.org>
|
||
|
|
||
|
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 program 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 program; if not, write to the Free Software
|
||
|
Foundation, Inc., 51 Franklin Street, Fifth Floor, Cambridge, MA 02110-1301, USA.
|
||
|
|
||
|
*/
|
||
|
// Self
|
||
|
#include "fileoperations.h"
|
||
|
|
||
|
// Qt
|
||
|
#include <QFileDialog>
|
||
|
#include <QMenu>
|
||
|
#include <QPushButton>
|
||
|
|
||
|
// KF
|
||
|
#include "kio_version.h"
|
||
|
#include <KIO/CopyJob>
|
||
|
#include <KIO/DeleteJob>
|
||
|
#include <KIO/DeleteOrTrashJob>
|
||
|
#include <KIO/JobUiDelegate>
|
||
|
#include <KIO/SimpleJob>
|
||
|
#include <KJobWidgets>
|
||
|
#include <KLocalizedString>
|
||
|
|
||
|
// Local
|
||
|
#include "gwenview_app_debug.h"
|
||
|
#include "renamedialog.h"
|
||
|
#include <lib/contextmanager.h>
|
||
|
#include <lib/document/documentfactory.h>
|
||
|
#include <lib/thumbnailprovider/thumbnailprovider.h>
|
||
|
|
||
|
namespace Gwenview
|
||
|
{
|
||
|
namespace FileOperations
|
||
|
{
|
||
|
static void copyMoveOrLink(Operation operation, const QList<QUrl> &urlList, QWidget *parent, ContextManager *contextManager)
|
||
|
{
|
||
|
Q_ASSERT(!urlList.isEmpty());
|
||
|
const int numberOfImages = urlList.count();
|
||
|
|
||
|
auto dialog = new QFileDialog(parent->nativeParentWidget(), QString());
|
||
|
dialog->setAcceptMode(QFileDialog::AcceptSave);
|
||
|
dialog->setAttribute(Qt::WA_DeleteOnClose);
|
||
|
dialog->setModal(true);
|
||
|
|
||
|
// Figure out what the window title and buttons should say,
|
||
|
// depending on the operation and how many images are selected
|
||
|
switch (operation) {
|
||
|
case COPY:
|
||
|
if (numberOfImages == 1) {
|
||
|
dialog->setWindowTitle(i18nc("@title:window %1 file name", "Copy %1", urlList.constFirst().fileName()));
|
||
|
} else {
|
||
|
dialog->setWindowTitle(i18ncp("@title:window %1 number of images", "Copy %1 image", "Copy %1 images", numberOfImages));
|
||
|
}
|
||
|
dialog->setLabelText(QFileDialog::DialogLabel::Accept, i18nc("@action:button", "Copy"));
|
||
|
break;
|
||
|
case MOVE:
|
||
|
if (numberOfImages == 1) {
|
||
|
dialog->setWindowTitle(i18nc("@title:window %1 file name", "Move %1", urlList.constFirst().fileName()));
|
||
|
} else {
|
||
|
dialog->setWindowTitle(i18ncp("@title:window %1 number of images", "Move %1 image", "Move %1 images", numberOfImages));
|
||
|
}
|
||
|
dialog->setLabelText(QFileDialog::DialogLabel::Accept, i18nc("@action:button", "Move"));
|
||
|
break;
|
||
|
case LINK:
|
||
|
if (numberOfImages == 1) {
|
||
|
dialog->setWindowTitle(i18nc("@title:window %1 file name", "Link %1", urlList.constFirst().fileName()));
|
||
|
} else {
|
||
|
dialog->setWindowTitle(i18ncp("@title:window %1 number of images", "Link %1 image", "Link %1 images", numberOfImages));
|
||
|
}
|
||
|
dialog->setLabelText(QFileDialog::DialogLabel::Accept, i18nc("@action:button", "Link"));
|
||
|
break;
|
||
|
default:
|
||
|
Q_ASSERT(0);
|
||
|
}
|
||
|
|
||
|
if (numberOfImages == 1) {
|
||
|
dialog->setFileMode(QFileDialog::AnyFile);
|
||
|
dialog->selectUrl(urlList.constFirst());
|
||
|
} else {
|
||
|
dialog->setFileMode(QFileDialog::Directory);
|
||
|
dialog->setOption(QFileDialog::ShowDirsOnly, true);
|
||
|
}
|
||
|
|
||
|
QUrl dirUrl = contextManager->targetDirUrl();
|
||
|
if (!dirUrl.isValid()) {
|
||
|
dirUrl = urlList.constFirst().adjusted(QUrl::RemoveFilename | QUrl::StripTrailingSlash);
|
||
|
}
|
||
|
dialog->setDirectoryUrl(dirUrl);
|
||
|
|
||
|
QObject::connect(dialog, &QDialog::accepted, parent, [=]() {
|
||
|
QUrl destUrl = dialog->selectedUrls().at(0);
|
||
|
|
||
|
KIO::CopyJob *job = nullptr;
|
||
|
switch (operation) {
|
||
|
case COPY:
|
||
|
job = KIO::copy(urlList, destUrl);
|
||
|
break;
|
||
|
case MOVE:
|
||
|
job = KIO::move(urlList, destUrl);
|
||
|
break;
|
||
|
case LINK:
|
||
|
job = KIO::link(urlList, destUrl);
|
||
|
break;
|
||
|
default:
|
||
|
Q_ASSERT(0);
|
||
|
}
|
||
|
KJobWidgets::setWindow(job, parent);
|
||
|
job->uiDelegate()->setAutoErrorHandlingEnabled(true);
|
||
|
|
||
|
if (numberOfImages == 1) {
|
||
|
destUrl = destUrl.adjusted(QUrl::RemoveFilename | QUrl::StripTrailingSlash);
|
||
|
}
|
||
|
contextManager->setTargetDirUrl(destUrl);
|
||
|
});
|
||
|
|
||
|
dialog->show();
|
||
|
}
|
||
|
|
||
|
static void delOrTrash(KIO::JobUiDelegate::DeletionType deletionType, const QList<QUrl> &urlList, QWidget *parent)
|
||
|
{
|
||
|
Q_ASSERT(urlList.count() > 0);
|
||
|
|
||
|
KJob *job = nullptr;
|
||
|
switch (deletionType) {
|
||
|
case KIO::JobUiDelegate::Trash:
|
||
|
job = new KIO::DeleteOrTrashJob(urlList, KIO::AskUserActionInterface::Trash, KIO::AskUserActionInterface::DefaultConfirmation, parent);
|
||
|
break;
|
||
|
case KIO::JobUiDelegate::Delete:
|
||
|
job = new KIO::DeleteOrTrashJob(urlList, KIO::AskUserActionInterface::Delete, KIO::AskUserActionInterface::DefaultConfirmation, parent);
|
||
|
break;
|
||
|
default: // e.g. EmptyTrash
|
||
|
return;
|
||
|
}
|
||
|
Q_ASSERT(job);
|
||
|
KJobWidgets::setWindow(job, parent);
|
||
|
job->start();
|
||
|
|
||
|
for (const QUrl &url : urlList) {
|
||
|
DocumentFactory::instance()->forget(url);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void copyTo(const QList<QUrl> &urlList, QWidget *parent, ContextManager *contextManager)
|
||
|
{
|
||
|
copyMoveOrLink(COPY, urlList, parent, contextManager);
|
||
|
}
|
||
|
|
||
|
void moveTo(const QList<QUrl> &urlList, QWidget *parent, ContextManager *contextManager)
|
||
|
{
|
||
|
copyMoveOrLink(MOVE, urlList, parent, contextManager);
|
||
|
}
|
||
|
|
||
|
void linkTo(const QList<QUrl> &urlList, QWidget *parent, ContextManager *contextManager)
|
||
|
{
|
||
|
copyMoveOrLink(LINK, urlList, parent, contextManager);
|
||
|
}
|
||
|
|
||
|
void trash(const QList<QUrl> &urlList, QWidget *parent)
|
||
|
{
|
||
|
delOrTrash(KIO::JobUiDelegate::Trash, urlList, parent);
|
||
|
}
|
||
|
|
||
|
void del(const QList<QUrl> &urlList, QWidget *parent)
|
||
|
{
|
||
|
delOrTrash(KIO::JobUiDelegate::Delete, urlList, parent);
|
||
|
}
|
||
|
|
||
|
void showMenuForDroppedUrls(QWidget *parent, const QList<QUrl> &urlList, const QUrl &destUrl)
|
||
|
{
|
||
|
if (urlList.isEmpty()) {
|
||
|
qCWarning(GWENVIEW_APP_LOG) << "urlList is empty!";
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
if (!destUrl.isValid()) {
|
||
|
qCWarning(GWENVIEW_APP_LOG) << "destUrl is not valid!";
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
QMenu menu(parent);
|
||
|
QAction *moveAction = menu.addAction(QIcon::fromTheme(QStringLiteral("edit-move"), QIcon::fromTheme(QStringLiteral("go-jump"))), i18n("Move Here"));
|
||
|
QAction *copyAction = menu.addAction(QIcon::fromTheme(QStringLiteral("edit-copy")), i18n("Copy Here"));
|
||
|
QAction *linkAction = menu.addAction(QIcon::fromTheme(QStringLiteral("edit-link")), i18n("Link Here"));
|
||
|
menu.addSeparator();
|
||
|
menu.addAction(QIcon::fromTheme(QStringLiteral("process-stop")), i18n("Cancel"));
|
||
|
|
||
|
QAction *action = menu.exec(QCursor::pos());
|
||
|
|
||
|
KIO::Job *job = nullptr;
|
||
|
if (action == moveAction) {
|
||
|
job = KIO::move(urlList, destUrl);
|
||
|
} else if (action == copyAction) {
|
||
|
job = KIO::copy(urlList, destUrl);
|
||
|
} else if (action == linkAction) {
|
||
|
job = KIO::link(urlList, destUrl);
|
||
|
} else {
|
||
|
return;
|
||
|
}
|
||
|
Q_ASSERT(job);
|
||
|
KJobWidgets::setWindow(job, parent);
|
||
|
}
|
||
|
|
||
|
void rename(const QUrl &oldUrl, QWidget *parent, ContextManager *contextManager)
|
||
|
{
|
||
|
auto dialog = new RenameDialog(parent);
|
||
|
dialog->setFilename(oldUrl.fileName());
|
||
|
dialog->setAttribute(Qt::WA_DeleteOnClose);
|
||
|
dialog->setModal(true);
|
||
|
|
||
|
QObject::connect(dialog, &QDialog::accepted, parent, [=]() {
|
||
|
const QString name = dialog->filename();
|
||
|
if (name.isEmpty() || name == oldUrl.fileName()) {
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
QUrl newUrl = oldUrl;
|
||
|
newUrl = newUrl.adjusted(QUrl::RemoveFilename);
|
||
|
newUrl.setPath(newUrl.path() + name);
|
||
|
KIO::SimpleJob *job = KIO::rename(oldUrl, newUrl, KIO::HideProgressInfo);
|
||
|
KJobWidgets::setWindow(job, parent);
|
||
|
job->uiDelegate()->setAutoErrorHandlingEnabled(true);
|
||
|
QObject::connect(job, &KJob::result, parent, [contextManager, job, oldUrl, newUrl]() {
|
||
|
if (!job->error()) {
|
||
|
contextManager->setCurrentUrl(newUrl);
|
||
|
ThumbnailProvider::moveThumbnail(oldUrl, newUrl);
|
||
|
}
|
||
|
});
|
||
|
});
|
||
|
|
||
|
dialog->show();
|
||
|
}
|
||
|
|
||
|
} // namespace
|
||
|
|
||
|
} // namespace
|