1
0
mirror of https://invent.kde.org/system/dolphin synced 2024-07-04 17:30:55 +00:00

Replaced Dolphins UndoManager and DolphinCommand by KonqUndoManager and KonqOperations. There are still some minor open issues left (renaming of multiple selected files, no undo support for KonqOperations::mkdir(), redo, ...), but all in all it absolutely makes sense to use a shared code for those operations.

svn path=/trunk/playground/utils/dolphin/; revision=624760
This commit is contained in:
Peter Penz 2007-01-18 06:32:21 +00:00
parent 4db903c670
commit 76866f783c
6 changed files with 134 additions and 871 deletions

View File

@ -39,7 +39,6 @@ set(dolphin_SRCS
sidebarpage.cpp
statusbarspaceinfo.cpp
statusbarmessagelabel.cpp
undomanager.cpp
urlbutton.cpp
urlnavigator.cpp
urlnavigatorbutton.cpp

View File

@ -23,58 +23,53 @@
#include <assert.h>
#include <kactioncollection.h>
#include <ktoggleaction.h>
#include <kbookmarkmanager.h>
#include <kglobal.h>
#include <kpropertiesdialog.h>
#include <kicon.h>
#include <kiconloader.h>
#include <kdeversion.h>
#include <kstatusbar.h>
#include <kio/netaccess.h>
#include <kfiledialog.h>
#include <kconfig.h>
#include <kurl.h>
#include <kaction.h>
#include <kstandardaction.h>
#include <kmenu.h>
#include <kio/renamedialog.h>
#include <kinputdialog.h>
#include <kshell.h>
#include <kdesktopfile.h>
#include <kstandarddirs.h>
#include <kprotocolinfo.h>
#include <kmessagebox.h>
#include <kservice.h>
#include <kstandarddirs.h>
#include <krun.h>
#include <klocale.h>
#include <konqmimedata.h>
#include <qclipboard.h>
#include <q3dragobject.h>
//Added by qt3to4:
#include <Q3ValueList>
#include <QCloseEvent>
#include <QSplitter>
#include <QDockWidget>
#include "urlnavigator.h"
#include "viewpropertiesdialog.h"
#include "viewproperties.h"
#include "dolphinapplication.h"
#include "dolphinsettings.h"
#include "dolphinsettingsdialog.h"
#include "dolphinstatusbar.h"
#include "dolphinapplication.h"
#include "undomanager.h"
#include "urlnavigator.h"
#include "progressindicator.h"
#include "dolphinsettings.h"
#include "bookmarkssidebarpage.h"
#include "infosidebarpage.h"
#include "generalsettings.h"
#include "dolphinapplication.h"
#include "viewpropertiesdialog.h"
#include "viewproperties.h"
#include <kaction.h>
#include <kactioncollection.h>
#include <kbookmarkmanager.h>
#include <kconfig.h>
#include <kdesktopfile.h>
#include <kdeversion.h>
#include <kfiledialog.h>
#include <kglobal.h>
#include <kicon.h>
#include <kiconloader.h>
#include <kio/netaccess.h>
#include <kio/renamedialog.h>
#include <kinputdialog.h>
#include <klocale.h>
#include <kmenu.h>
#include <kmessagebox.h>
#include <konqmimedata.h>
#include <konq_undo.h>
#include <kpropertiesdialog.h>
#include <kprotocolinfo.h>
#include <ktoggleaction.h>
#include <krun.h>
#include <kshell.h>
#include <kstandarddirs.h>
#include <kstatusbar.h>
#include <kstandardaction.h>
#include <kurl.h>
#include <Q3ValueList> // TODO
#include <QCloseEvent>
#include <QClipboard>
#include <QSplitter>
#include <QDockWidget>
DolphinMainWindow::DolphinMainWindow() :
KMainWindow(0),
@ -84,10 +79,19 @@ DolphinMainWindow::DolphinMainWindow() :
setObjectName("Dolphin");
m_view[PrimaryIdx] = 0;
m_view[SecondaryIdx] = 0;
KonqUndoManager::incRef();
connect(KonqUndoManager::self(), SIGNAL(undoAvailable(bool)),
this, SLOT(slotUndoAvailable(bool)));
connect(KonqUndoManager::self(), SIGNAL(undoTextChanged(const QString&)),
this, SLOT(slotUndoTextChanged(const QString&)));
}
DolphinMainWindow::~DolphinMainWindow()
{
KonqUndoManager::decRef();
qDeleteAll(m_fileGroupActions);
m_fileGroupActions.clear();
@ -274,16 +278,6 @@ void DolphinMainWindow::updateFilterBarAction(bool show)
showFilterBarAction->setChecked(show);
}
void DolphinMainWindow::redo()
{
UndoManager::instance().redo(this);
}
void DolphinMainWindow::undo()
{
UndoManager::instance().undo(this);
}
void DolphinMainWindow::openNewMainWindow()
{
DolphinApplication::app()->createMainWindow()->show();
@ -301,8 +295,8 @@ void DolphinMainWindow::copyDroppedItems()
void DolphinMainWindow::linkDroppedItems()
{
KIO::Job* job = KIO::link(m_droppedUrls, m_dropDestination);
addPendingUndoJob(job, DolphinCommand::Link, m_droppedUrls, m_dropDestination);
KonqOperations::copy(this, KonqOperations::LINK, m_droppedUrls, m_dropDestination);
m_undoOperations.append(KonqOperations::LINK);
}
void DolphinMainWindow::closeEvent(QCloseEvent* event)
@ -401,29 +395,26 @@ void DolphinMainWindow::createFolder()
url = baseUrl;
url.addPath(name);
}
ok = KIO::NetAccess::mkdir(url, this);
// TODO: provide message type hint
if (ok) {
KonqOperations::mkdir(this, url);
// TODO: is there a possability to check whether the mkdir operation
// has been successful?
//if (ok) {
statusBar->setMessage(i18n("Created folder %1.",url.path()),
DolphinStatusBar::OperationCompleted);
DolphinCommand command(DolphinCommand::CreateFolder, KUrl::List(), url);
UndoManager::instance().addCommand(command);
}
else {
// Creating of the folder has been failed. Check whether the creating
// has been failed because a folder with the same name exists...
if (KIO::NetAccess::exists(url, true, this)) {
statusBar->setMessage(i18n("A folder named %1 already exists.",url.path()),
DolphinStatusBar::Error);
}
else {
statusBar->setMessage(i18n("Creating of folder %1 failed.",url.path()),
DolphinStatusBar::Error);
}
}
//}
//else {
// // Creating of the folder has been failed. Check whether the creating
// // has been failed because a folder with the same name exists...
// if (KIO::NetAccess::exists(url, true, this)) {
// statusBar->setMessage(i18n("A folder named %1 already exists.",url.path()),
// DolphinStatusBar::Error);
// }
// else {
// statusBar->setMessage(i18n("Creating of folder %1 failed.",url.path()),
// DolphinStatusBar::Error);
// }
}
void DolphinMainWindow::createFile()
@ -515,8 +506,10 @@ void DolphinMainWindow::createFile()
KUrl::List list;
list.append(sourceUrl);
DolphinCommand command(DolphinCommand::CreateFile, list, destUrl);
UndoManager::instance().addCommand(command);
// TODO: use the KonqUndoManager/KonqOperations instead.
//DolphinCommand command(DolphinCommand::CreateFile, list, destUrl);
//UndoManager::instance().addCommand(command);
}
else {
@ -534,9 +527,12 @@ void DolphinMainWindow::rename()
void DolphinMainWindow::moveToTrash()
{
clearStatusBar();
KUrl::List selectedUrls = m_activeView->selectedUrls();
KIO::Job* job = KIO::trash(selectedUrls);
addPendingUndoJob(job, DolphinCommand::Trash, selectedUrls, m_activeView->url());
const KUrl::List selectedUrls = m_activeView->selectedUrls();
// TODO: per default a message box is opened which asks whether the item
// should really be moved to the trash. This does not make sense, as the
// action can be undone anyway by the user.
KonqOperations::del(this, KonqOperations::TRASH, selectedUrls);
m_undoOperations.append(KonqOperations::TRASH);
}
void DolphinMainWindow::deleteItems()
@ -609,6 +605,32 @@ void DolphinMainWindow::slotUndoAvailable(bool available)
if (undoAction != 0) {
undoAction->setEnabled(available);
}
if (available && (m_undoOperations.count() > 0)) {
const KonqOperations::Operation op = m_undoOperations.takeFirst();
DolphinStatusBar* statusBar = m_activeView->statusBar();
switch (op) {
case KonqOperations::COPY:
statusBar->setMessage(i18n("Copy operation completed."),
DolphinStatusBar::OperationCompleted);
break;
case KonqOperations::MOVE:
statusBar->setMessage(i18n("Move operation completed."),
DolphinStatusBar::OperationCompleted);
break;
case KonqOperations::LINK:
statusBar->setMessage(i18n("Link operation completed."),
DolphinStatusBar::OperationCompleted);
break;
case KonqOperations::TRASH:
statusBar->setMessage(i18n("Move to trash operation completed."),
DolphinStatusBar::OperationCompleted);
break;
default:
break;
}
}
}
void DolphinMainWindow::slotUndoTextChanged(const QString& text)
@ -619,22 +641,6 @@ void DolphinMainWindow::slotUndoTextChanged(const QString& text)
}
}
void DolphinMainWindow::slotRedoAvailable(bool available)
{
QAction* redoAction = actionCollection()->action(KStandardAction::stdName(KStandardAction::Redo));
if (redoAction != 0) {
redoAction->setEnabled(available);
}
}
void DolphinMainWindow::slotRedoTextChanged(const QString& text)
{
QAction* redoAction = actionCollection()->action(KStandardAction::stdName(KStandardAction::Redo));
if (redoAction != 0) {
redoAction->setText(text);
}
}
void DolphinMainWindow::cut()
{
QMimeData* mimeData = new QMimeData();
@ -995,80 +1001,6 @@ void DolphinMainWindow::editSettings()
dlg.exec();
}
void DolphinMainWindow::addUndoOperation(KJob* job)
{
if (job->error() != 0) {
slotHandleJobError(job);
}
else {
const int id = job->progressId();
// set iterator to the executed command with the current id...
Q3ValueList<UndoInfo>::Iterator it = m_pendingUndoJobs.begin();
const Q3ValueList<UndoInfo>::Iterator end = m_pendingUndoJobs.end();
bool found = false;
while (!found && (it != end)) {
if ((*it).id == id) {
found = true;
}
else {
++it;
}
}
if (found) {
DolphinCommand command = (*it).command;
if (command.type() == DolphinCommand::Trash) {
// To be able to perform an undo for the 'Move to Trash' operation
// all source Urls must be updated with the trash Url. E. g. when moving
// a file "test.txt" and a second file "test.txt" to the trash,
// then the filenames in the trash are "0-test.txt" and "1-test.txt".
QMap<QString, QString> metaData;
KIO::Job *kiojob = qobject_cast<KIO::Job*>( job );
if ( kiojob )
{
metaData = kiojob->metaData();
}
KUrl::List newSourceUrls;
KUrl::List sourceUrls = command.source();
KUrl::List::Iterator sourceIt = sourceUrls.begin();
const KUrl::List::Iterator sourceEnd = sourceUrls.end();
while (sourceIt != sourceEnd) {
QMap<QString, QString>::ConstIterator metaIt = metaData.find("trashUrl-" + (*sourceIt).path());
if (metaIt != metaData.end()) {
newSourceUrls.append(KUrl(metaIt.value()));
}
++sourceIt;
}
command.setSource(newSourceUrls);
}
UndoManager::instance().addCommand(command);
m_pendingUndoJobs.erase(it);
DolphinStatusBar* statusBar = m_activeView->statusBar();
switch (command.type()) {
case DolphinCommand::Copy:
statusBar->setMessage(i18n("Copy operation completed."),
DolphinStatusBar::OperationCompleted);
break;
case DolphinCommand::Move:
statusBar->setMessage(i18n("Move operation completed."),
DolphinStatusBar::OperationCompleted);
break;
case DolphinCommand::Trash:
statusBar->setMessage(i18n("Move to trash operation completed."),
DolphinStatusBar::OperationCompleted);
break;
default:
break;
}
}
}
}
void DolphinMainWindow::init()
{
// Check whether Dolphin runs the first time. If yes then
@ -1197,22 +1129,9 @@ void DolphinMainWindow::setupActions()
KStandardAction::quit(this, SLOT(quit()), actionCollection());
// setup 'Edit' menu
UndoManager& undoManager = UndoManager::instance();
KStandardAction::undo(this,
SLOT(undo()),
actionCollection());
connect(&undoManager, SIGNAL(undoAvailable(bool)),
this, SLOT(slotUndoAvailable(bool)));
connect(&undoManager, SIGNAL(undoTextChanged(const QString&)),
this, SLOT(slotUndoTextChanged(const QString&)));
KStandardAction::redo(this,
SLOT(redo()),
actionCollection());
connect(&undoManager, SIGNAL(redoAvailable(bool)),
this, SLOT(slotRedoAvailable(bool)));
connect(&undoManager, SIGNAL(redoTextChanged(const QString&)),
this, SLOT(slotRedoTextChanged(const QString&)));
KStandardAction::undo(KonqUndoManager::self(),
SLOT(undo()),
actionCollection());
KStandardAction::cut(this, SLOT(cut()), actionCollection());
KStandardAction::copy(this, SLOT(copy()), actionCollection());
@ -1579,28 +1498,14 @@ void DolphinMainWindow::updateGoActions()
void DolphinMainWindow::copyUrls(const KUrl::List& source, const KUrl& dest)
{
KIO::Job* job = KIO::copy(source, dest);
addPendingUndoJob(job, DolphinCommand::Copy, source, dest);
KonqOperations::copy(this, KonqOperations::COPY, source, dest);
m_undoOperations.append(KonqOperations::COPY);
}
void DolphinMainWindow::moveUrls(const KUrl::List& source, const KUrl& dest)
{
KIO::Job* job = KIO::move(source, dest);
addPendingUndoJob(job, DolphinCommand::Move, source, dest);
}
void DolphinMainWindow::addPendingUndoJob(KIO::Job* job,
DolphinCommand::Type commandType,
const KUrl::List& source,
const KUrl& dest)
{
connect(job, SIGNAL(result(KJob*)),
this, SLOT(addUndoOperation(KJob*)));
UndoInfo undoInfo;
undoInfo.id = job->progressId();
undoInfo.command = DolphinCommand(commandType, source, dest);
m_pendingUndoJobs.append(undoInfo);
KonqOperations::copy(this, KonqOperations::MOVE, source, dest);
m_undoOperations.append(KonqOperations::MOVE);
}
void DolphinMainWindow::clearStatusBar()

View File

@ -22,13 +22,13 @@
#ifndef _DOLPHIN_MAINWINDOW_H_
#define _DOLPHIN_MAINWINDOW_H_
#include "dolphinview.h"
#include <kmainwindow.h>
#include <ksortablelist.h>
#include <konq_operations.h>
#include <q3valuelist.h>
#include "dolphinview.h"
#include "undomanager.h" // for DolphinCommand::Type
#include <QList>
class KPrinter;
class KUrl;
@ -173,15 +173,6 @@ private slots:
/** Sets the text of the 'Undo' menu action to \a text. */
void slotUndoTextChanged(const QString& text);
/**
* Updates the state of the 'Redo' menu action dependent
* from the parameter \a available.
*/
void slotRedoAvailable(bool available);
/** Sets the text of the 'Redo' menu action to \a text. */
void slotRedoTextChanged(const QString& text);
/**
* Copies all selected items to the clipboard and marks
* the items as cutted.
@ -303,12 +294,6 @@ private slots:
/** Opens the settings dialog for Dolphin. */
void editSettings();
/**
* Adds the undo operation given by \a job
* to the UndoManager.
*/
void addUndoOperation(KJob* job);
/** Updates the state of all 'View' menu actions. */
void slotViewModeChanged();
@ -339,12 +324,6 @@ private slots:
/** Updates the state of the 'Show filter bar' menu action. */
void updateFilterBarAction(bool show);
/** Executes the redo operation (see UndoManager::Redo ()). */
void redo();
/** Executes the undo operation (see UndoManager::Undo()). */
void undo();
/** Open a new main window. */
void openNewMainWindow();
@ -381,10 +360,6 @@ private:
void updateGoActions();
void copyUrls(const KUrl::List& source, const KUrl& dest);
void moveUrls(const KUrl::List& source, const KUrl& dest);
void addPendingUndoJob(KIO::Job* job,
DolphinCommand::Type commandType,
const KUrl::List& source,
const KUrl& dest);
void clearStatusBar();
/**
@ -413,21 +388,8 @@ private:
};
DolphinView* m_view[SecondaryIdx + 1];
/**
* Asynchronous operations like 'Move' and 'Copy' may only be added as undo
* operation after they have been finished successfully. When an asynchronous
* operation is started, it is added to a pending undo jobs list in the meantime.
* As soon as the job has been finished, the operation is added to the undo mangager.
* @see UndoManager
* @see DolphinMainWindow::addPendingUndoJob
* @see DolphinMainWindow::addUndoOperation
*/
struct UndoInfo
{
int id;
DolphinCommand command;
};
Q3ValueList<UndoInfo> m_pendingUndoJobs;
/// remember pending undo operations until they are finished
QList<KonqOperations::Operation> m_undoOperations;
/** Contains meta information for creating files. */
struct CreateFileEntry

View File

@ -20,34 +20,35 @@
#include "dolphinview.h"
#include <assert.h>
#include <QItemSelectionModel>
#include <Q3ValueList>
#include <Q3ValueList> // TODO
#include <QDropEvent>
#include <QMouseEvent>
#include <QVBoxLayout>
#include <kdirmodel.h>
#include <kfileitemdelegate.h>
#include <kurl.h>
#include <klocale.h>
#include <kio/netaccess.h>
#include <kio/renamedialog.h>
#include <kmimetyperesolver.h>
#include <assert.h>
#include <konq_operations.h>
#include <kurl.h>
#include "urlnavigator.h"
#include "dolphinstatusbar.h"
#include "dolphinmainwindow.h"
#include "dolphindirlister.h"
#include "dolphinsortfilterproxymodel.h"
#include "viewproperties.h"
#include "dolphindetailsview.h"
#include "dolphiniconsview.h"
#include "dolphincontextmenu.h"
#include "undomanager.h"
#include "renamedialog.h"
#include "progressindicator.h"
#include "filterbar.h"
#include "progressindicator.h"
#include "renamedialog.h"
#include "urlnavigator.h"
#include "viewproperties.h"
DolphinView::DolphinView(DolphinMainWindow *mainWindow,
QWidget *parent,
@ -233,8 +234,10 @@ void DolphinView::renameSelectedItems()
DolphinStatusBar::Error);
}
else {
UndoManager& undoMan = UndoManager::instance();
undoMan.beginMacro();
// TODO: check how this can be integrated into KonqUndoManager/KonqOperations
//UndoManager& undoMan = UndoManager::instance();
//undoMan.beginMacro();
assert(newName.contains('#'));
@ -268,8 +271,8 @@ void DolphinView::renameSelectedItems()
else if (KIO::NetAccess::file_move(source, dest)) {
// TODO: From the users point of view he executed one 'rename n files' operation,
// but internally we store it as n 'rename 1 file' operations for the undo mechanism.
DolphinCommand command(DolphinCommand::Rename, source, dest);
undoMan.addCommand(command);
//DolphinCommand command(DolphinCommand::Rename, source, dest);
//undoMan.addCommand(command);
}
}
@ -278,7 +281,7 @@ void DolphinView::renameSelectedItems()
delete progressIndicator;
progressIndicator = 0;
undoMan.endMacro();
//undoMan.endMacro();
}
}
else {
@ -566,15 +569,15 @@ void DolphinView::rename(const KUrl& source, const QString& newName)
ok = KIO::NetAccess::file_move(source, dest);
}
const QString destFileName = dest.fileName();
if (ok) {
m_statusBar->setMessage(i18n("Renamed file '%1' to '%2'.",source.fileName(), dest.fileName()),
m_statusBar->setMessage(i18n("Renamed file '%1' to '%2'.",source.fileName(), destFileName),
DolphinStatusBar::OperationCompleted);
DolphinCommand command(DolphinCommand::Rename, source, dest);
UndoManager::instance().addCommand(command);
KonqOperations::rename(this, source, destFileName);
}
else {
m_statusBar->setMessage(i18n("Renaming of file '%1' to '%2' failed.",source.fileName(), dest.fileName()),
m_statusBar->setMessage(i18n("Renaming of file '%1' to '%2' failed.",source.fileName(), destFileName),
DolphinStatusBar::Error);
reload();
}

View File

@ -1,405 +0,0 @@
/***************************************************************************
* Copyright (C) 2006 by Peter Penz *
* peter.penz@gmx.at *
* *
* 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, Boston, MA 02110-1301 USA *
***************************************************************************/
#include "undomanager.h"
#include <klocale.h>
#include <kio/netaccess.h>
#include <qtimer.h>
#include <assert.h>
#include "dolphinmainwindow.h"
#include "dolphinstatusbar.h"
#include "progressindicator.h"
DolphinCommand::DolphinCommand() :
m_type(Copy),
m_macroIndex(-1)
{
// Implementation note: DolphinCommands are stored in a QValueList, whereas
// QValueList requires a default constructor of the added class.
// Instead of expressing this implementation detail to the interface by adding a
// Type::Undefined just Type::Copy is used to assure that all members have
// a defined state.
//
// KDE4TODO: QList doesn't require a default constructor iirc - so remove this
}
DolphinCommand::DolphinCommand(Type type,
const KUrl::List& source,
const KUrl& dest) :
m_type(type),
m_macroIndex(-1),
m_source(source),
m_dest(dest)
{
}
DolphinCommand::~DolphinCommand()
{
}
DolphinCommand& DolphinCommand::operator = (const DolphinCommand& command)
{
m_type = command.m_type;
m_source = command.m_source;
m_dest = command.m_dest;
return *this;
}
UndoManager& UndoManager::instance()
{
static UndoManager* instance = 0;
if (instance == 0) {
instance = new UndoManager();
}
return *instance;
}
void UndoManager::addCommand(const DolphinCommand& command)
{
++m_historyIndex;
QList<DolphinCommand>::iterator it = m_history.begin();
it += m_historyIndex;
if (m_recordMacro) {
DolphinCommand macroCommand = command;
macroCommand.m_macroIndex = m_macroCounter;
m_history.insert(it, macroCommand);
}
else {
m_history.insert(it, command);
}
emit undoAvailable(true);
emit undoTextChanged(i18n("Undo: %1",commandText(command)));
// prevent an endless growing of the Undo history
if (m_historyIndex > 10000) {
m_history.erase(m_history.begin());
--m_historyIndex;
}
}
void UndoManager::beginMacro()
{
assert(!m_recordMacro);
m_recordMacro = true;
++m_macroCounter;
}
void UndoManager::endMacro()
{
assert(m_recordMacro);
m_recordMacro = false;
}
// KDE4 TODO: consider switching to KCommandHistory (kdeui) for the command history, and to
// KonqCommandRecorder etc. from libkonq/konq_undo.*
void UndoManager::undo(DolphinMainWindow* mainWindow)
{
if (m_recordMacro) {
endMacro();
}
if (m_historyIndex < 0) {
return;
}
int progressCount = 0;
int macroCount = 1;
calcStepsCount(macroCount, progressCount);
/*
* KDE4, ### TODO Only here to avoid possible crash
*/
ProgressIndicator progressIndicator(mainWindow, i18n("Executing undo operation..."),
i18n("Executed undo operation."),
progressCount);
for (int i = 0; i < macroCount; ++i) {
const DolphinCommand command = m_history[m_historyIndex];
--m_historyIndex;
if (m_historyIndex < 0) {
emit undoAvailable(false);
emit undoTextChanged(i18n("Undo"));
}
else {
emit undoTextChanged(i18n("Undo: %1",commandText(m_history[m_historyIndex])));
}
if (m_historyIndex < static_cast<int>(m_history.count()) - 1) {
emit redoAvailable(true);
emit redoTextChanged(i18n("Redo: %1",commandText(command)));
}
else {
emit redoAvailable(false);
emit redoTextChanged(i18n("Redo"));
}
KUrl::List sourceUrls = command.source();
KUrl::List::Iterator it = sourceUrls.begin();
const KUrl::List::Iterator end = sourceUrls.end();
const QString destUrl(command.destination().prettyUrl(KUrl::AddTrailingSlash));
KIO::Job* job = 0;
switch (command.type()) {
case DolphinCommand::Link:
case DolphinCommand::Copy: {
KUrl::List list;
while (it != end) {
const KUrl deleteUrl(destUrl + (*it).fileName());
list.append(deleteUrl);
++it;
}
job = KIO::del(list, false, false);
break;
}
case DolphinCommand::Move: {
KUrl::List list;
const KUrl newDestUrl((*it).directory());
while (it != end) {
const KUrl newSourceUrl(destUrl + (*it).fileName());
list.append(newSourceUrl);
++it;
}
job = KIO::move(list, newDestUrl, false);
break;
}
case DolphinCommand::Rename: {
assert(sourceUrls.count() == 1);
KIO::NetAccess::move(command.destination(), (*it));
break;
}
case DolphinCommand::Trash: {
while (it != end) {
// TODO: use KIO::special for accessing the trash protocol. See
// also Dolphin::slotJobResult() for further details.
const QString originalFileName((*it).fileName().section('-', 1));
KUrl newDestUrl(destUrl + originalFileName);
KIO::NetAccess::move(*it, newDestUrl);
++it;
progressIndicator.execOperation();
}
break;
}
case DolphinCommand::CreateFolder:
case DolphinCommand::CreateFile: {
KIO::NetAccess::del(command.destination(), mainWindow);
break;
}
}
if (job != 0) {
// Execute the jobs in a synchronous manner and forward the progress
// information to the Dolphin statusbar.
connect(job, SIGNAL(percent(KJob*, unsigned long)),
this, SLOT(slotPercent(KJob*, unsigned long)));
KIO::NetAccess::synchronousRun(job, mainWindow);
}
progressIndicator.execOperation();
}
}
void UndoManager::redo(DolphinMainWindow *mainWindow)
{
if (m_recordMacro) {
endMacro();
}
const int maxHistoryIndex = m_history.count() - 1;
if (m_historyIndex >= maxHistoryIndex) {
return;
}
++m_historyIndex;
int progressCount = 0;
int macroCount = 1;
calcStepsCount(macroCount, progressCount);
ProgressIndicator progressIndicator(mainWindow, i18n("Executing redo operation..."),
i18n("Executed redo operation."),
progressCount);
for (int i = 0; i < macroCount; ++i) {
const DolphinCommand command = m_history[m_historyIndex];
if (m_historyIndex >= maxHistoryIndex) {
emit redoAvailable(false);
emit redoTextChanged(i18n("Redo"));
}
else {
emit redoTextChanged(i18n("Redo: %1",commandText(m_history[m_historyIndex + 1])));
}
emit undoAvailable(true);
emit undoTextChanged(i18n("Undo: %1",commandText(command)));
KUrl::List sourceUrls = command.source();
KUrl::List::Iterator it = sourceUrls.begin();
const KUrl::List::Iterator end = sourceUrls.end();
KIO::Job* job = 0;
switch (command.type()) {
case DolphinCommand::Link: {
job = KIO::link(sourceUrls, command.destination(), false);
break;
}
case DolphinCommand::Copy: {
job = KIO::copy(sourceUrls, command.destination(), false);
break;
}
case DolphinCommand::Rename:
case DolphinCommand::Move: {
job = KIO::move(sourceUrls, command.destination(), false);
break;
}
case DolphinCommand::Trash: {
const QString destUrl(command.destination().prettyUrl());
while (it != end) {
// TODO: use KIO::special for accessing the trash protocol. See
// also Dolphin::slotJobResult() for further details.
const QString originalFileName((*it).fileName().section('-', 1));
KUrl originalSourceUrl(destUrl + "/" + originalFileName);
KIO::Job* moveToTrashJob = KIO::trash(originalSourceUrl);
KIO::NetAccess::synchronousRun(moveToTrashJob, mainWindow);
++it;
progressIndicator.execOperation();
}
break;
}
case DolphinCommand::CreateFolder: {
KIO::NetAccess::mkdir(command.destination(), mainWindow);
break;
}
case DolphinCommand::CreateFile: {
progressIndicator.execOperation();
KUrl::List::Iterator it = sourceUrls.begin();
assert(sourceUrls.count() == 1);
KIO::CopyJob* copyJob = KIO::copyAs(*it, command.destination(), false);
copyJob->setDefaultPermissions(true);
job = copyJob;
break;
}
}
if (job != 0) {
// Execute the jobs in a synchronous manner and forward the progress
// information to the Dolphin statusbar.
connect(job, SIGNAL(percent(KJob*, unsigned long)),
this, SLOT(slotPercent(KJob*, unsigned long)));
KIO::NetAccess::synchronousRun(job, mainWindow);
}
++m_historyIndex;
progressIndicator.execOperation();
}
--m_historyIndex;
}
UndoManager::UndoManager() :
m_recordMacro(false),
m_historyIndex(-1),
m_macroCounter(0)
{
}
UndoManager::~UndoManager()
{
}
QString UndoManager::commandText(const DolphinCommand& command) const
{
QString text;
switch (command.type()) {
case DolphinCommand::Copy: text = i18n("Copy"); break;
case DolphinCommand::Move: text = i18n("Move"); break;
case DolphinCommand::Link: text = i18n("Link"); break;
case DolphinCommand::Rename: text = i18n("Rename"); break;
case DolphinCommand::Trash: text = i18n("Move to Trash"); break;
case DolphinCommand::CreateFolder: text = i18n("Create New Folder"); break;
case DolphinCommand::CreateFile: text = i18n("Create New File"); break;
default: break;
}
return text;
}
void UndoManager::slotPercent(KJob* /* job */, unsigned long /* percent */)
{
// It is not allowed to update the progress indicator in the context
// of this slot, hence do an asynchronous triggering.
QTimer::singleShot(0, this, SLOT(updateProgress()));
}
void UndoManager::updateProgress()
{
/*
* ### XXX, TODO, KDE4 make this work when switchting to KonqUndoManager
*/
//m_progressIndicator->execOperation();
}
void UndoManager::calcStepsCount(int& macroCount, int& progressCount)
{
progressCount = 0;
macroCount = 0;
const int macroIndex = m_history[m_historyIndex].m_macroIndex;
if (macroIndex < 0) {
// default use case: no macro has been recorded
macroCount = 1;
progressCount = m_history[m_historyIndex].source().count();
return;
}
// iterate backward for undo...
int i = m_historyIndex;
while ((i >= 0) && (m_history[i].m_macroIndex == macroIndex)) {
++macroCount;
progressCount += m_history[i].source().count();
--i;
}
// iterate forward for redo...
const int max = m_history.count() - 1;
i = m_historyIndex + 1;
while ((i <= max) && (m_history[i].m_macroIndex == macroIndex)) {
++macroCount;
progressCount += m_history[i].source().count();
++i;
}
}
#include "undomanager.moc"

View File

@ -1,201 +0,0 @@
/***************************************************************************
* Copyright (C) 2006 by Peter Penz *
* peter.penz@gmx.at *
* *
* 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, Boston, MA 02110-1301 USA *
***************************************************************************/
#ifndef UNDOMANAGER_H
#define UNDOMANAGER_H
#include <QObject>
#include <QPointer>
#include <QList>
#include <kurl.h>
#include <kio/jobclasses.h>
class DolphinMainWindow;
/**
* @short Represents a file manager command which can be undone and redone.
*
* A command is specified by a type, a list of source Urls and a
* destination Url.
*
* Due to the fixed set of commands a file manager offers this class is
* a very simplified version of the classic command pattern.
*
* @see UndoManager
* @author Peter Penz <peter.penz@gmx.at>
*/
class DolphinCommand
{
public:
enum Type {
Copy,
Move,
Link,
Rename,
Trash,
CreateFolder,
CreateFile
};
DolphinCommand();
DolphinCommand(Type type, const KUrl::List& source, const KUrl& dest);
~DolphinCommand(); // non-virtual
DolphinCommand& operator = (const DolphinCommand& command);
Type type() const { return m_type; }
void setSource(const KUrl::List source) { m_source = source; }
const KUrl::List& source() const { return m_source; }
const KUrl& destination() const { return m_dest; }
private:
Type m_type;
int m_macroIndex;
KUrl::List m_source;
KUrl m_dest;
friend class UndoManager; // allow to modify m_macroIndex
};
/**
* @short Stores all file manager commands which can be undone and redone.
*
* During the undo and redo operations a progress information is
* shown in the status bar.
*
* @author Peter Penz <peter.penz@gmx.at>
*/
class UndoManager : public QObject // TODO switch to KonqUndoManager (multi-process, async, more robust on complex operations, no redo though)
{
Q_OBJECT
public:
static UndoManager& instance();
/**
* Adds the command \a command to the undo list. The command
* can be undone by invoking UndoManager::undo().
*/
void addCommand(const DolphinCommand& command);
/**
* Allows to summarize several commands into one macro, which
* can be undo in one stop by UndoManager::undo(). Example
* \code
* UndoManager& undoMan = UndoManager.instance();
* undoMan.beginMacro();
* undoMan.addCommand(...);
* undoMan.addCommand(...);
* undoMan.addCommand(...);
* undoMan.endMacro();
* \endcode
* It is not allowed to do nested macro recordings.
*/
void beginMacro();
/**
* Marks the end of a macro command. See UndoManager::beginMacro()
* for sample code.
*/
void endMacro();
public slots:
/**
* Performs an undo operation on the last command which has
* been added by UndoManager::addCommand().
*
* @param mainwindow The mainwindow where to show progress
*/
void undo(DolphinMainWindow* mainwindow);
/**
* Performs a redo operation on the last command where an undo
* operation has been applied.
*
* @param mainwindow The mainwindow where to show progress
*/
void redo(DolphinMainWindow* mainwindow);
signals:
/**
* Is emitted if whenever the availability state
* of the current undo operation changes.
*/
void undoAvailable(bool available);
/**
* Is emitted whenever the text of the current
* undo operation changes
* (e. g. from 'Undo: Delete' to 'Undo: Copy')
*/
void undoTextChanged(const QString& text);
/**
* Is emitted if whenever the availability state
* of the current redo operation changes.
*/
void redoAvailable(bool available);
/**
* Is emitted whenever the text of the current
* redo operation changes
* (e. g. from 'Redo: Delete' to 'Redo: Copy')
*/
void redoTextChanged(const QString& text);
protected:
UndoManager();
virtual ~UndoManager();
QString commandText(const DolphinCommand& command) const;
private slots:
/**
* Slot for the percent information of the I/O slaves.
* Delegates the updating of the progress information
* to UndoManager::updateProgress().
*/
void slotPercent(KJob* job, unsigned long percent);
/**
* Updates the progress information of the statusbar
* by accessing the progress indicator information.
*/
void updateProgress();
private:
bool m_recordMacro;
int m_historyIndex;
int m_macroCounter;
QList<DolphinCommand> m_history;
/**
* Dependent from the current history index \a m_historyIndex
* the number of macro commands is written to the output
* parameter \a macroCount. The number of steps for all macro
* commands is written to the output parameter \a progressCount.
*
* Per default \a macroCount is 1 and \a progressCount represents
* the number of operations for one command.
*/
void calcStepsCount(int& macroCount,
int& progressCount);
};
#endif