00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #include "fileundomanager.h"
00022 #include "fileundomanager_p.h"
00023 #include "fileundomanager_adaptor.h"
00024
00025 #include <kdatetime.h>
00026 #include <kdebug.h>
00027 #include <kdirnotify.h>
00028 #include <kglobal.h>
00029 #include <kio/copyjob.h>
00030 #include <kio/job.h>
00031 #include <kio/jobuidelegate.h>
00032 #include <klocale.h>
00033 #include <kmessagebox.h>
00034 #include <kuiserverjobtracker.h>
00035
00036 #include <QtDBus/QtDBus>
00037
00038 #include <assert.h>
00039
00040 using namespace KIO;
00041
00042 static const char* undoStateToString(UndoState state) {
00043 static const char* s_undoStateToString[] = { "MAKINGDIRS", "MOVINGFILES", "STATINGFILE", "REMOVINGDIRS", "REMOVINGLINKS" };
00044 return s_undoStateToString[state];
00045 }
00046
00047 static QDataStream &operator<<(QDataStream &stream, const KIO::BasicOperation &op)
00048 {
00049 stream << op.m_valid << (qint8)op.m_type << op.m_renamed
00050 << op.m_src << op.m_dst << op.m_target << (qint64)op.m_mtime;
00051 return stream;
00052 }
00053 static QDataStream &operator>>(QDataStream &stream, BasicOperation &op)
00054 {
00055 qint8 type;
00056 qint64 mtime;
00057 stream >> op.m_valid >> type >> op.m_renamed
00058 >> op.m_src >> op.m_dst >> op.m_target >> mtime;
00059 op.m_type = static_cast<BasicOperation::Type>(type);
00060 op.m_mtime = mtime;
00061 return stream;
00062 }
00063
00064 static QDataStream &operator<<(QDataStream &stream, const UndoCommand &cmd)
00065 {
00066 stream << cmd.m_valid << (qint8)cmd.m_type << cmd.m_opStack << cmd.m_src << cmd.m_dst;
00067 return stream;
00068 }
00069
00070 static QDataStream &operator>>(QDataStream &stream, UndoCommand &cmd)
00071 {
00072 qint8 type;
00073 stream >> cmd.m_valid >> type >> cmd.m_opStack >> cmd.m_src >> cmd.m_dst;
00074 cmd.m_type = static_cast<FileUndoManager::CommandType>(type);
00075 return stream;
00076 }
00077
00101 class KIO::UndoJob : public KIO::Job
00102 {
00103 public:
00104 UndoJob(bool showProgressInfo) : KIO::Job() {
00105 if (showProgressInfo)
00106 KIO::getJobTracker()->registerJob(this);
00107 }
00108 virtual ~UndoJob() {}
00109
00110 virtual void kill(bool) {
00111 FileUndoManager::self()->d->stopUndo(true);
00112 KIO::Job::doKill();
00113 }
00114
00115 void emitCreatingDir(const KUrl &dir)
00116 { emit description(this, i18n("Creating directory"),
00117 qMakePair(i18n("Directory"), dir.prettyUrl())); }
00118 void emitMoving(const KUrl &src, const KUrl &dest)
00119 { emit description(this, i18n("Moving"),
00120 qMakePair(i18nc("The source of a file operation", "Source"), src.prettyUrl()),
00121 qMakePair(i18nc("The destination of a file operation", "Destination"), dest.prettyUrl())); }
00122 void emitDeleting(const KUrl &url)
00123 { emit description(this, i18n("Deleting"),
00124 qMakePair(i18n("File"), url.prettyUrl())); }
00125 void emitResult() { KIO::Job::emitResult(); }
00126 };
00127
00128 CommandRecorder::CommandRecorder(FileUndoManager::CommandType op, const KUrl::List &src, const KUrl &dst, KIO::Job *job)
00129 : QObject(job)
00130 {
00131 m_cmd.m_type = op;
00132 m_cmd.m_valid = true;
00133 m_cmd.m_serialNumber = FileUndoManager::self()->newCommandSerialNumber();
00134 m_cmd.m_src = src;
00135 m_cmd.m_dst = dst;
00136 connect(job, SIGNAL(result(KJob*)),
00137 this, SLOT(slotResult(KJob*)));
00138
00139 if (op != FileUndoManager::Mkdir) {
00140 connect(job, SIGNAL(copyingDone(KIO::Job*,KUrl,KUrl,time_t,bool,bool)),
00141 this, SLOT(slotCopyingDone(KIO::Job*,KUrl,KUrl,time_t,bool,bool)));
00142 connect(job, SIGNAL(copyingLinkDone(KIO::Job *,KUrl,QString,KUrl)),
00143 this, SLOT(slotCopyingLinkDone(KIO::Job *,KUrl,QString,KUrl)));
00144 }
00145 }
00146
00147 CommandRecorder::~CommandRecorder()
00148 {
00149 }
00150
00151 void CommandRecorder::slotResult(KJob *job)
00152 {
00153 if (job->error())
00154 return;
00155
00156 FileUndoManager::self()->d->addCommand(m_cmd);
00157 }
00158
00159 void CommandRecorder::slotCopyingDone(KIO::Job *job, const KUrl &from, const KUrl &to, time_t mtime, bool directory, bool renamed)
00160 {
00161 BasicOperation op;
00162 op.m_valid = true;
00163 op.m_type = directory ? BasicOperation::Directory : BasicOperation::File;
00164 op.m_renamed = renamed;
00165 op.m_src = from;
00166 op.m_dst = to;
00167 op.m_mtime = mtime;
00168
00169 if (m_cmd.m_type == FileUndoManager::Trash)
00170 {
00171 Q_ASSERT(to.protocol() == "trash");
00172 const QMap<QString, QString> metaData = job->metaData();
00173 QMap<QString, QString>::ConstIterator it = metaData.find("trashURL-" + from.path());
00174 if (it != metaData.constEnd()) {
00175
00176 op.m_dst = it.value();
00177 }
00178 }
00179
00180 m_cmd.m_opStack.prepend(op);
00181 }
00182
00183
00184 void CommandRecorder::slotCopyingLinkDone(KIO::Job *, const KUrl &from, const QString &target, const KUrl &to)
00185 {
00186 BasicOperation op;
00187 op.m_valid = true;
00188 op.m_type = BasicOperation::Link;
00189 op.m_renamed = false;
00190 op.m_src = from;
00191 op.m_target = target;
00192 op.m_dst = to;
00193 op.m_mtime = -1;
00194 m_cmd.m_opStack.prepend(op);
00195 }
00196
00198
00199 class KIO::FileUndoManagerSingleton
00200 {
00201 public:
00202 FileUndoManager self;
00203 };
00204 K_GLOBAL_STATIC(KIO::FileUndoManagerSingleton, globalFileUndoManager)
00205
00206 FileUndoManager *FileUndoManager::self()
00207 {
00208 return &globalFileUndoManager->self;
00209 }
00210
00211
00212
00213
00214
00215
00216 FileUndoManagerPrivate::FileUndoManagerPrivate(FileUndoManager* qq)
00217 : m_uiInterface(new FileUndoManager::UiInterface()),
00218 m_undoJob(0), m_nextCommandIndex(1000), q(qq)
00219 {
00220 m_syncronized = initializeFromKDesky();
00221 (void) new KIOFileUndoManagerAdaptor(this);
00222 const QString dbusPath = "/FileUndoManager";
00223 const QString dbusInterface = "org.kde.kio.FileUndoManager";
00224
00225 QDBusConnection dbus = QDBusConnection::sessionBus();
00226 dbus.registerObject(dbusPath, this);
00227 dbus.connect(QString(), dbusPath, dbusInterface, "lock", this, SLOT(slotLock()));
00228 dbus.connect(QString(), dbusPath, dbusInterface, "pop", this, SLOT(slotPop()));
00229 dbus.connect(QString(), dbusPath, dbusInterface, "push", this, SLOT(slotPush(QByteArray)));
00230 dbus.connect(QString(), dbusPath, dbusInterface, "unlock", this, SLOT(slotUnlock()));
00231 }
00232
00233 FileUndoManager::FileUndoManager()
00234 {
00235 d = new FileUndoManagerPrivate(this);
00236 d->m_lock = false;
00237 d->m_currentJob = 0;
00238 }
00239
00240 FileUndoManager::~FileUndoManager()
00241 {
00242 delete d;
00243 }
00244
00245 void FileUndoManager::recordJob(CommandType op, const KUrl::List &src, const KUrl &dst, KIO::Job *job)
00246 {
00247
00248 (void) new CommandRecorder(op, src, dst, job);
00249 emit jobRecordingStarted(op);
00250 }
00251
00252 void FileUndoManager::recordCopyJob(KIO::CopyJob* copyJob)
00253 {
00254 CommandType commandType;
00255 switch (copyJob->operationMode()) {
00256 case CopyJob::Copy:
00257 commandType = Copy;
00258 break;
00259 case CopyJob::Move:
00260 commandType = Move;
00261 break;
00262 case CopyJob::Link:
00263 default:
00264 commandType = Link;
00265 break;
00266 }
00267 recordJob(commandType, copyJob->srcUrls(), copyJob->destUrl(), copyJob);
00268 }
00269
00270 void FileUndoManagerPrivate::addCommand(const UndoCommand &cmd)
00271 {
00272 broadcastPush(cmd);
00273 emit q->jobRecordingFinished(cmd.m_type);
00274 }
00275
00276 bool FileUndoManager::undoAvailable() const
00277 {
00278 return (d->m_commands.count() > 0) && !d->m_lock;
00279 }
00280
00281 QString FileUndoManager::undoText() const
00282 {
00283 if (d->m_commands.isEmpty())
00284 return i18n("Und&o");
00285
00286 FileUndoManager::CommandType t = d->m_commands.top().m_type;
00287 if (t == FileUndoManager::Copy)
00288 return i18n("Und&o: Copy");
00289 else if (t == FileUndoManager::Link)
00290 return i18n("Und&o: Link");
00291 else if (t == FileUndoManager::Move)
00292 return i18n("Und&o: Move");
00293 else if (t == FileUndoManager::Rename)
00294 return i18n("Und&o: Rename");
00295 else if (t == FileUndoManager::Trash)
00296 return i18n("Und&o: Trash");
00297 else if (t == FileUndoManager::Mkdir)
00298 return i18n("Und&o: Create Folder");
00299 else
00300 assert(false);
00301
00302 return QString();
00303 }
00304
00305 quint64 FileUndoManager::newCommandSerialNumber()
00306 {
00307 return ++(d->m_nextCommandIndex);
00308 }
00309
00310 quint64 FileUndoManager::currentCommandSerialNumber() const
00311 {
00312 if(!d->m_commands.isEmpty())
00313 {
00314 const UndoCommand& cmd = d->m_commands.top();
00315 assert(cmd.m_valid);
00316 return cmd.m_serialNumber;
00317 } else
00318 return 0;
00319 }
00320
00321 void FileUndoManager::undo()
00322 {
00323
00324 UndoCommand cmd = d->m_commands.top();
00325 assert(cmd.m_valid);
00326 d->m_current = cmd;
00327
00328 BasicOperation::Stack& opStack = d->m_current.m_opStack;
00329
00330
00331
00332 KUrl::List fileCleanupStack;
00333 QStack<BasicOperation>::Iterator it = opStack.begin();
00334 for (; it != opStack.end() ; ++it) {
00335 BasicOperation::Type type = (*it).m_type;
00336 if (type == BasicOperation::File && d->m_current.m_type == FileUndoManager::Copy) {
00337 fileCleanupStack.append((*it).m_dst);
00338 }
00339 }
00340 if (d->m_current.m_type == FileUndoManager::Mkdir) {
00341 fileCleanupStack.append(d->m_current.m_dst);
00342 }
00343 if (!fileCleanupStack.isEmpty()) {
00344 if (!d->m_uiInterface->confirmDeletion(fileCleanupStack)) {
00345 return;
00346 }
00347 }
00348
00349 d->broadcastPop();
00350 d->broadcastLock();
00351
00352 d->m_dirCleanupStack.clear();
00353 d->m_dirStack.clear();
00354 d->m_dirsToUpdate.clear();
00355
00356 d->m_undoState = MOVINGFILES;
00357
00358
00359
00360
00361 it = opStack.begin();
00362 while (it != opStack.end())
00363 {
00364 bool removeBasicOperation = false;
00365 BasicOperation::Type type = (*it).m_type;
00366 if (type == BasicOperation::Directory && !(*it).m_renamed)
00367 {
00368
00369 d->m_undoState = MAKINGDIRS;
00370
00371 if (d->m_current.isMoveCommand())
00372 d->m_dirStack.push((*it).m_src);
00373
00374
00375 d->m_dirCleanupStack.prepend((*it).m_dst);
00376 removeBasicOperation = true;
00377 }
00378 else if (type == BasicOperation::Link)
00379 {
00380 d->m_linkCleanupStack.prepend((*it).m_dst);
00381
00382 removeBasicOperation = !d->m_current.isMoveCommand();
00383 }
00384
00385 if (removeBasicOperation)
00386 it = opStack.erase(it);
00387 else
00388 ++it;
00389 }
00390
00391 kDebug(1203) << "starting with" << undoStateToString(d->m_undoState);
00392 d->m_undoJob = new UndoJob(d->m_uiInterface->showProgressInfo());
00393 d->undoStep();
00394 }
00395
00396 void FileUndoManagerPrivate::stopUndo(bool step)
00397 {
00398 m_current.m_opStack.clear();
00399 m_dirCleanupStack.clear();
00400 m_linkCleanupStack.clear();
00401 m_undoState = REMOVINGDIRS;
00402 m_undoJob = 0;
00403
00404 if (m_currentJob)
00405 m_currentJob->kill();
00406
00407 m_currentJob = 0;
00408
00409 if (step)
00410 undoStep();
00411 }
00412
00413 void FileUndoManagerPrivate::slotResult(KJob *job)
00414 {
00415 m_currentJob = 0;
00416 if (job->error())
00417 {
00418 m_uiInterface->jobError(static_cast<KIO::Job*>(job));
00419 delete m_undoJob;
00420 stopUndo(false);
00421 }
00422 else if (m_undoState == STATINGFILE)
00423 {
00424 BasicOperation op = m_current.m_opStack.top();
00425
00426 KIO::StatJob* statJob = static_cast<KIO::StatJob*>(job);
00427 time_t mtime = statJob->statResult().numberValue(KIO::UDSEntry::UDS_MODIFICATION_TIME, -1);
00428 if (mtime != op.m_mtime) {
00429 kDebug(1203) << op.m_dst << " was modified after being copied!";
00430 KDateTime srcTime; srcTime.setTime_t(op.m_mtime); srcTime = srcTime.toLocalZone();
00431 KDateTime destTime; destTime.setTime_t(mtime); destTime = destTime.toLocalZone();
00432 if (!m_uiInterface->copiedFileWasModified(op.m_src, op.m_dst, srcTime, destTime)) {
00433 stopUndo(false);
00434 }
00435 }
00436 }
00437
00438 undoStep();
00439 }
00440
00441
00442 void FileUndoManagerPrivate::addDirToUpdate(const KUrl& url)
00443 {
00444 if (!m_dirsToUpdate.contains(url))
00445 m_dirsToUpdate.prepend(url);
00446 }
00447
00448 void FileUndoManagerPrivate::undoStep()
00449 {
00450 m_currentJob = 0;
00451
00452 if (m_undoState == MAKINGDIRS)
00453 stepMakingDirectories();
00454
00455 if (m_undoState == MOVINGFILES || m_undoState == STATINGFILE)
00456 stepMovingFiles();
00457
00458 if (m_undoState == REMOVINGLINKS)
00459 stepRemovingLinks();
00460
00461 if (m_undoState == REMOVINGDIRS)
00462 stepRemovingDirectories();
00463
00464 if (m_currentJob) {
00465 if (m_uiInterface)
00466 m_currentJob->ui()->setWindow(m_uiInterface->parentWidget());
00467 QObject::connect(m_currentJob, SIGNAL(result(KJob*)),
00468 this, SLOT(slotResult(KJob*)));
00469 }
00470 }
00471
00472 void FileUndoManagerPrivate::stepMakingDirectories()
00473 {
00474 if (!m_dirStack.isEmpty()) {
00475 KUrl dir = m_dirStack.pop();
00476 kDebug(1203) << "creatingDir" << dir;
00477 m_currentJob = KIO::mkdir(dir);
00478 m_undoJob->emitCreatingDir(dir);
00479 }
00480 else
00481 m_undoState = MOVINGFILES;
00482 }
00483
00484
00485
00486
00487 void FileUndoManagerPrivate::stepMovingFiles()
00488 {
00489 if (!m_current.m_opStack.isEmpty())
00490 {
00491 BasicOperation op = m_current.m_opStack.top();
00492 BasicOperation::Type type = op.m_type;
00493
00494 assert(op.m_valid);
00495 if (type == BasicOperation::Directory)
00496 {
00497 if (op.m_renamed)
00498 {
00499 kDebug(1203) << "rename" << op.m_dst << op.m_src;
00500 m_currentJob = KIO::rename(op.m_dst, op.m_src, KIO::HideProgressInfo);
00501 m_undoJob->emitMoving(op.m_dst, op.m_src);
00502 }
00503 else
00504 assert(0);
00505 }
00506 else if (type == BasicOperation::Link)
00507 {
00508 kDebug(1203) << "symlink" << op.m_target << op.m_src;
00509 m_currentJob = KIO::symlink(op.m_target, op.m_src, KIO::Overwrite | KIO::HideProgressInfo);
00510 }
00511 else if (m_current.m_type == FileUndoManager::Copy)
00512 {
00513 if (m_undoState == MOVINGFILES)
00514 {
00515
00516 kDebug(1203) << "stat" << op.m_dst;
00517 m_currentJob = KIO::stat(op.m_dst, KIO::HideProgressInfo);
00518 m_undoState = STATINGFILE;
00519 return;
00520 }
00521 else
00522 {
00523 m_currentJob = KIO::file_delete(op.m_dst, KIO::HideProgressInfo);
00524 m_undoJob->emitDeleting(op.m_dst);
00525 m_undoState = MOVINGFILES;
00526 }
00527 }
00528 else if (m_current.isMoveCommand()
00529 || m_current.m_type == FileUndoManager::Trash)
00530 {
00531 kDebug(1203) << "file_move" << op.m_dst << op.m_src;
00532 m_currentJob = KIO::file_move(op.m_dst, op.m_src, -1, KIO::Overwrite | KIO::HideProgressInfo);
00533 m_undoJob->emitMoving(op.m_dst, op.m_src);
00534 }
00535
00536 m_current.m_opStack.pop();
00537
00538
00539 KUrl url(op.m_dst);
00540 url.setPath(url.directory());
00541 addDirToUpdate(url);
00542
00543 url = op.m_src;
00544 url.setPath(url.directory());
00545 addDirToUpdate(url);
00546 }
00547 else
00548 m_undoState = REMOVINGLINKS;
00549 }
00550
00551 void FileUndoManagerPrivate::stepRemovingLinks()
00552 {
00553 kDebug(1203) << "REMOVINGLINKS";
00554 if (!m_linkCleanupStack.isEmpty())
00555 {
00556 KUrl file = m_linkCleanupStack.pop();
00557 kDebug(1203) << "file_delete" << file;
00558 m_currentJob = KIO::file_delete(file, KIO::HideProgressInfo);
00559 m_undoJob->emitDeleting(file);
00560
00561 KUrl url(file);
00562 url.setPath(url.directory());
00563 addDirToUpdate(url);
00564 }
00565 else
00566 {
00567 m_undoState = REMOVINGDIRS;
00568
00569 if (m_dirCleanupStack.isEmpty() && m_current.m_type == FileUndoManager::Mkdir)
00570 m_dirCleanupStack << m_current.m_dst;
00571 }
00572 }
00573
00574 void FileUndoManagerPrivate::stepRemovingDirectories()
00575 {
00576 if (!m_dirCleanupStack.isEmpty())
00577 {
00578 KUrl dir = m_dirCleanupStack.pop();
00579 kDebug(1203) << "rmdir" << dir;
00580 m_currentJob = KIO::rmdir(dir);
00581 m_undoJob->emitDeleting(dir);
00582 addDirToUpdate(dir);
00583 }
00584 else
00585 {
00586 m_current.m_valid = false;
00587 m_currentJob = 0;
00588 if (m_undoJob)
00589 {
00590 kDebug(1203) << "deleting undojob";
00591 m_undoJob->emitResult();
00592 m_undoJob = 0;
00593 }
00594 QList<KUrl>::ConstIterator it = m_dirsToUpdate.constBegin();
00595 for(; it != m_dirsToUpdate.constEnd(); ++it) {
00596 kDebug() << "Notifying FilesAdded for " << *it;
00597 org::kde::KDirNotify::emitFilesAdded((*it).url());
00598 }
00599 emit q->undoJobFinished();
00600 broadcastUnlock();
00601 }
00602 }
00603
00604
00605 void FileUndoManagerPrivate::slotPush(QByteArray data)
00606 {
00607 QDataStream strm(&data, QIODevice::ReadOnly);
00608 UndoCommand cmd;
00609 strm >> cmd;
00610 pushCommand(cmd);
00611 }
00612
00613 void FileUndoManagerPrivate::pushCommand(const UndoCommand& cmd)
00614 {
00615 m_commands.push(cmd);
00616 emit q->undoAvailable(true);
00617 emit q->undoTextChanged(q->undoText());
00618 }
00619
00620 void FileUndoManagerPrivate::slotPop()
00621 {
00622 m_commands.pop();
00623 emit q->undoAvailable(q->undoAvailable());
00624 emit q->undoTextChanged(q->undoText());
00625 }
00626
00627 void FileUndoManagerPrivate::slotLock()
00628 {
00629
00630 m_lock = true;
00631 emit q->undoAvailable(q->undoAvailable());
00632 }
00633
00634 void FileUndoManagerPrivate::slotUnlock()
00635 {
00636
00637 m_lock = false;
00638 emit q->undoAvailable(q->undoAvailable());
00639 }
00640
00641 QByteArray FileUndoManagerPrivate::get() const
00642 {
00643 QByteArray data;
00644 QDataStream stream(&data, QIODevice::WriteOnly);
00645 stream << m_commands;
00646 return data;
00647 }
00648
00649 void FileUndoManagerPrivate::broadcastPush(const UndoCommand &cmd)
00650 {
00651 if (!m_syncronized) {
00652 pushCommand(cmd);
00653 return;
00654 }
00655
00656 QByteArray data;
00657 QDataStream stream(&data, QIODevice::WriteOnly);
00658 stream << cmd;
00659 emit push(data);
00660 }
00661
00662 void FileUndoManagerPrivate::broadcastPop()
00663 {
00664 if (!m_syncronized) {
00665 slotPop();
00666 return;
00667 }
00668
00669 emit pop();
00670 }
00671
00672 void FileUndoManagerPrivate::broadcastLock()
00673 {
00674
00675
00676 if (!m_syncronized) {
00677 slotLock();
00678 return;
00679 }
00680 emit lock();
00681 }
00682
00683 void FileUndoManagerPrivate::broadcastUnlock()
00684 {
00685
00686
00687 if (!m_syncronized) {
00688 slotUnlock();
00689 return;
00690 }
00691 emit unlock();
00692 }
00693
00694 bool FileUndoManagerPrivate::initializeFromKDesky()
00695 {
00696
00697
00698
00699
00700
00701
00702
00703
00704 return false;
00705 #if 0
00706 DCOPClient *client = kapp->dcopClient();
00707
00708 if (client->appId() == "kdesktop")
00709 return true;
00710
00711 if (!client->isApplicationRegistered("kdesktop"))
00712 return false;
00713
00714 d->m_commands = DCOPRef("kdesktop", "FileUndoManager").call("get");
00715 return true;
00716 #endif
00717 }
00718
00719 void FileUndoManager::setUiInterface(UiInterface* ui)
00720 {
00721 delete d->m_uiInterface;
00722 d->m_uiInterface = ui;
00723 }
00724
00725 FileUndoManager::UiInterface* FileUndoManager::uiInterface() const
00726 {
00727 return d->m_uiInterface;
00728 }
00729
00731
00732 class FileUndoManager::UiInterface::UiInterfacePrivate
00733 {
00734 public:
00735 UiInterfacePrivate()
00736 : m_parentWidget(0), m_showProgressInfo(true)
00737 {}
00738 QWidget* m_parentWidget;
00739 bool m_showProgressInfo;
00740 };
00741
00742 FileUndoManager::UiInterface::UiInterface()
00743 : d(new UiInterfacePrivate)
00744 {
00745 }
00746
00747 FileUndoManager::UiInterface::~UiInterface()
00748 {
00749 delete d;
00750 }
00751
00752 void FileUndoManager::UiInterface::jobError(KIO::Job* job)
00753 {
00754 job->ui()->showErrorMessage();
00755 }
00756
00757 bool FileUndoManager::UiInterface::copiedFileWasModified(const KUrl& src, const KUrl& dest, const KDateTime& srcTime, const KDateTime& destTime)
00758 {
00759 Q_UNUSED(srcTime);
00760
00761 const QString timeStr = KGlobal::locale()->formatDateTime(destTime, KLocale::ShortDate);
00762 return KMessageBox::warningContinueCancel(
00763 d->m_parentWidget,
00764 i18n("The file %1 was copied from %2, but since then it has apparently been modified at %3.\n"
00765 "Undoing the copy will delete the file, and all modifications will be lost.\n"
00766 "Are you sure you want to delete %4?", dest.pathOrUrl(), src.pathOrUrl(), timeStr, dest.pathOrUrl()),
00767 i18n("Undo File Copy Confirmation"),
00768 KStandardGuiItem::cont(),
00769 KStandardGuiItem::cancel(),
00770 QString(),
00771 KMessageBox::Notify | KMessageBox::Dangerous) == KMessageBox::Continue;
00772 }
00773
00774 bool FileUndoManager::UiInterface::confirmDeletion(const KUrl::List& files)
00775 {
00776 KIO::JobUiDelegate uiDelegate;
00777 uiDelegate.setWindow(d->m_parentWidget);
00778
00779 return uiDelegate.askDeleteConfirmation(files, KIO::JobUiDelegate::Delete, KIO::JobUiDelegate::ForceConfirmation);
00780 }
00781
00782 QWidget* FileUndoManager::UiInterface::parentWidget() const
00783 {
00784 return d->m_parentWidget;
00785 }
00786
00787 void FileUndoManager::UiInterface::setParentWidget(QWidget* parentWidget)
00788 {
00789 d->m_parentWidget = parentWidget;
00790 }
00791
00792 void FileUndoManager::UiInterface::setShowProgressInfo(bool b)
00793 {
00794 d->m_showProgressInfo = b;
00795 }
00796
00797 bool FileUndoManager::UiInterface::showProgressInfo() const
00798 {
00799 return d->m_showProgressInfo;
00800 }
00801
00802 void FileUndoManager::UiInterface::virtual_hook(int, void*)
00803 {
00804 }
00805
00806 #include "fileundomanager_p.moc"
00807 #include "fileundomanager.moc"