24#include <tdeio/uiserver_stub.h> 
   25#include "konq_operations.h" 
   29#include <dcopclient.h> 
   32#include <tdeapplication.h> 
   33#include <kdatastream.h> 
   36#include <tdeglobalsettings.h> 
   41#include <kdirnotify_stub.h> 
   43inline const char *dcopTypeName( 
const KonqCommand & ) { 
return "KonqCommand"; }
 
   44inline const char *dcopTypeName( 
const KonqCommand::Stack & ) { 
return "KonqCommand::Stack"; }
 
   66class KonqUndoJob : 
public TDEIO::Job
 
   69    KonqUndoJob() : TDEIO::Job( true ) { KonqUndoManager::incRef(); };
 
   70    virtual ~KonqUndoJob() { KonqUndoManager::decRef(); }
 
   72    virtual void kill( 
bool q) { KonqUndoManager::self()->stopUndo( 
true ); TDEIO::Job::kill( q ); }
 
   75class KonqCommandRecorder::KonqCommandRecorderPrivate
 
   78  KonqCommandRecorderPrivate()
 
   81  ~KonqCommandRecorderPrivate()
 
   88KonqCommandRecorder::KonqCommandRecorder( KonqCommand::Type op, 
const KURL::List &src, 
const KURL &dst, TDEIO::Job *job )
 
   89  : TQObject( job, 
"konqcmdrecorder" )
 
   91  d = 
new KonqCommandRecorderPrivate;
 
   93  d->m_cmd.m_valid = 
true;
 
   96  connect( job, TQ_SIGNAL( result( TDEIO::Job * ) ),
 
   97           this, TQ_SLOT( slotResult( TDEIO::Job * ) ) );
 
   99  if ( op != KonqCommand::MKDIR ) {
 
  100      connect( job, TQ_SIGNAL( copyingDone( TDEIO::Job *, 
const KURL &, 
const KURL &, 
bool, 
bool ) ),
 
  101               this, TQ_SLOT( slotCopyingDone( TDEIO::Job *, 
const KURL &, 
const KURL &, 
bool, 
bool ) ) );
 
  102      connect( job, TQ_SIGNAL( copyingLinkDone( TDEIO::Job *, 
const KURL &, 
const TQString &, 
const KURL & ) ),
 
  103               this, TQ_SLOT( slotCopyingLinkDone( TDEIO::Job *, 
const KURL &, 
const TQString &, 
const KURL & ) ) );
 
  106  KonqUndoManager::incRef();
 
  109KonqCommandRecorder::~KonqCommandRecorder()
 
  111  KonqUndoManager::decRef();
 
  115void KonqCommandRecorder::slotResult( TDEIO::Job *job )
 
  120  KonqUndoManager::self()->addCommand( d->m_cmd );
 
  123void KonqCommandRecorder::slotCopyingDone( TDEIO::Job *job, 
const KURL &from, 
const KURL &to, 
bool directory, 
bool renamed )
 
  125  KonqBasicOperation op;
 
  127  op.m_directory = directory;
 
  128  op.m_renamed = renamed;
 
  133  if ( d->m_cmd.m_type == KonqCommand::TRASH )
 
  135      Q_ASSERT( from.isLocalFile() );
 
  136      Q_ASSERT( to.protocol() == 
"trash" );
 
  137      TQMap<TQString, TQString> metaData = job->metaData();
 
  138      TQMap<TQString, TQString>::ConstIterator it = metaData.find( 
"trashURL-" + from.path() );
 
  139      if ( it != metaData.end() ) {
 
  141          op.m_dst = it.data();
 
  145  d->m_cmd.m_opStack.prepend( op );
 
  148void KonqCommandRecorder::slotCopyingLinkDone( TDEIO::Job *, 
const KURL &from, 
const TQString &target, 
const KURL &to )
 
  150  KonqBasicOperation op;
 
  152  op.m_directory = 
false;
 
  153  op.m_renamed = 
false;
 
  155  op.m_target = target;
 
  158  d->m_cmd.m_opStack.prepend( op );
 
  161KonqUndoManager *KonqUndoManager::s_self = 0;
 
  162unsigned long KonqUndoManager::s_refCnt = 0;
 
  164class KonqUndoManager::KonqUndoManagerPrivate
 
  167  KonqUndoManagerPrivate()
 
  169      m_uiserver = 
new UIServer_stub( 
"tdeio_uiserver", 
"UIServer" );
 
  172  ~KonqUndoManagerPrivate()
 
  179  KonqCommand::Stack m_commands;
 
  181  KonqCommand m_current;
 
  182  TDEIO::Job *m_currentJob;
 
  183  UndoState m_undoState;
 
  184  TQValueStack<KURL> m_dirStack;
 
  185  TQValueStack<KURL> m_dirCleanupStack;
 
  186  TQValueStack<KURL> m_fileCleanupStack;
 
  187  TQValueList<KURL> m_dirsToUpdate;
 
  191  UIServer_stub *m_uiserver;
 
  194  KonqUndoJob *m_undoJob;
 
  197KonqUndoManager::KonqUndoManager()
 
  198: DCOPObject( 
"KonqUndoManager" )
 
  200  if ( !tdeApp->dcopClient()->isAttached() )
 
  201      tdeApp->dcopClient()->attach();
 
  203  d = 
new KonqUndoManagerPrivate;
 
  204  d->m_syncronized = initializeFromKDesky();
 
  209KonqUndoManager::~KonqUndoManager()
 
  214void KonqUndoManager::incRef()
 
  219void KonqUndoManager::decRef()
 
  222  if ( s_refCnt == 0 && s_self )
 
  229KonqUndoManager *KonqUndoManager::self()
 
  235    s_self = 
new KonqUndoManager;
 
  240void KonqUndoManager::addCommand( 
const KonqCommand &cmd )
 
  242  broadcastPush( cmd );
 
  245bool KonqUndoManager::undoAvailable()
 const 
  247  return ( d->m_commands.count() > 0 ) && !d->m_lock;
 
  250TQString KonqUndoManager::undoText()
 const 
  252  if ( d->m_commands.count() == 0 )
 
  253    return i18n( 
"Und&o" );
 
  255  KonqCommand::Type t = d->m_commands.top().m_type;
 
  256  if ( t == KonqCommand::COPY )
 
  257    return i18n( 
"Und&o: Copy" );
 
  258  else if ( t == KonqCommand::LINK )
 
  259    return i18n( 
"Und&o: Link" );
 
  260  else if ( t == KonqCommand::MOVE )
 
  261    return i18n( 
"Und&o: Move" );
 
  262  else if ( t == KonqCommand::TRASH )
 
  263    return i18n( 
"Und&o: Trash" );
 
  264  else if ( t == KonqCommand::MKDIR )
 
  265    return i18n( 
"Und&o: Create Folder" );
 
  269  return TQString::null;
 
  272void KonqUndoManager::undo()
 
  274  KonqCommand cmd = d->m_commands.top();
 
  275  assert( cmd.m_valid );
 
  279  TQValueList<KonqBasicOperation>& opStack = d->m_current.m_opStack;
 
  282  KURL::List fileCleanupStack;
 
  283  TQValueList<KonqBasicOperation>::Iterator it = opStack.begin();
 
  284  for ( ; it != opStack.end() ; ++it ) {
 
  285      if ( !(*it).m_directory && !(*it).m_link && d->m_current.m_type == KonqCommand::COPY ) {
 
  286          fileCleanupStack.append( (*it).m_dst );
 
  289  if ( !fileCleanupStack.isEmpty() ) {
 
  292                                                   KonqOperations::FORCE_CONFIRMATION,
 
  297  d->m_dirCleanupStack.clear();
 
  298  d->m_dirStack.clear();
 
  299  d->m_dirsToUpdate.clear();
 
  301  d->m_undoState = MOVINGFILES;
 
  306  it = opStack.begin();
 
  307  TQValueList<KonqBasicOperation>::Iterator end = opStack.end();
 
  310    if ( (*it).m_directory && !(*it).m_renamed )
 
  312      d->m_dirStack.push( (*it).m_src );
 
  313      d->m_dirCleanupStack.prepend( (*it).m_dst );
 
  314      it = d->m_current.m_opStack.remove( it );
 
  315      d->m_undoState = MAKINGDIRS;
 
  316      kdDebug(1203) << 
"KonqUndoManager::undo MAKINGDIRS" << endl;
 
  318    else if ( (*it).m_link )
 
  320      if ( !d->m_fileCleanupStack.contains( (*it).m_dst ) )
 
  321        d->m_fileCleanupStack.prepend( (*it).m_dst );
 
  323      if ( d->m_current.m_type != KonqCommand::MOVE )
 
  324        it = d->m_current.m_opStack.remove( it );
 
  347  if ( d->m_current.m_type != KonqCommand::MOVE )
 
  348    d->m_dirStack.clear();
 
  350  d->m_undoJob = 
new KonqUndoJob;
 
  351  d->m_uiserverJobId = d->m_undoJob->progressId();
 
  355void KonqUndoManager::stopUndo( 
bool step )
 
  357    d->m_current.m_opStack.clear();
 
  358    d->m_dirCleanupStack.clear();
 
  359    d->m_fileCleanupStack.clear();
 
  360    d->m_undoState = REMOVINGDIRS;
 
  363    if ( d->m_currentJob )
 
  364        d->m_currentJob->kill( 
true );
 
  372void KonqUndoManager::slotResult( TDEIO::Job *job )
 
  374  d->m_uiserver->jobFinished( d->m_uiserverJobId );
 
  377    job->showErrorDialog( 0L );
 
  391void KonqUndoManager::addDirToUpdate( 
const KURL& url )
 
  393  if ( d->m_dirsToUpdate.find( url ) == d->m_dirsToUpdate.end() )
 
  394    d->m_dirsToUpdate.prepend( url );
 
  397void KonqUndoManager::undoStep()
 
  401  if ( d->m_undoState == MAKINGDIRS )
 
  402      undoMakingDirectories();
 
  404  if ( d->m_undoState == MOVINGFILES )
 
  407  if ( d->m_undoState == REMOVINGFILES )
 
  410  if ( d->m_undoState == REMOVINGDIRS )
 
  411      undoRemovingDirectories();
 
  413  if ( d->m_currentJob )
 
  414    connect( d->m_currentJob, TQ_SIGNAL( result( TDEIO::Job * ) ),
 
  415             this, TQ_SLOT( slotResult( TDEIO::Job * ) ) );
 
  418void KonqUndoManager::undoMakingDirectories()
 
  420    if ( !d->m_dirStack.isEmpty() ) {
 
  421      KURL dir = d->m_dirStack.pop();
 
  422      kdDebug(1203) << 
"KonqUndoManager::undoStep creatingDir " << dir.prettyURL() << endl;
 
  423      d->m_currentJob = TDEIO::mkdir( dir );
 
  424      d->m_uiserver->creatingDir( d->m_uiserverJobId, dir );
 
  427      d->m_undoState = MOVINGFILES;
 
  430void KonqUndoManager::undoMovingFiles()
 
  432    if ( !d->m_current.m_opStack.isEmpty() )
 
  434      KonqBasicOperation op = d->m_current.m_opStack.pop();
 
  436      assert( op.m_valid );
 
  437      if ( op.m_directory )
 
  441          kdDebug(1203) << 
"KonqUndoManager::undoStep rename " << op.m_dst.prettyURL() << 
" " << op.m_src.prettyURL() << endl;
 
  442          d->m_currentJob = TDEIO::rename( op.m_dst, op.m_src, 
false );
 
  443          d->m_uiserver->moving( d->m_uiserverJobId, op.m_dst, op.m_src );
 
  448      else if ( op.m_link )
 
  450        kdDebug(1203) << 
"KonqUndoManager::undoStep symlink " << op.m_target << 
" " << op.m_src.prettyURL() << endl;
 
  451        d->m_currentJob = TDEIO::symlink( op.m_target, op.m_src, 
true, 
false );
 
  453      else if ( d->m_current.m_type == KonqCommand::COPY )
 
  455        kdDebug(1203) << 
"KonqUndoManager::undoStep file_delete " << op.m_dst.prettyURL() << endl;
 
  456        d->m_currentJob = TDEIO::file_delete( op.m_dst );
 
  457        d->m_uiserver->deleting( d->m_uiserverJobId, op.m_dst );
 
  459      else if ( d->m_current.m_type == KonqCommand::MOVE
 
  460                || d->m_current.m_type == KonqCommand::TRASH )
 
  462        kdDebug(1203) << 
"KonqUndoManager::undoStep file_move " << op.m_dst.prettyURL() << 
" " << op.m_src.prettyURL() << endl;
 
  463        d->m_currentJob = TDEIO::file_move( op.m_dst, op.m_src, -1, 
true );
 
  464        d->m_uiserver->moving( d->m_uiserverJobId, op.m_dst, op.m_src );
 
  469      KURL url( op.m_dst );
 
  470      url.setPath( url.directory() );
 
  471      addDirToUpdate( url );
 
  474      url.setPath( url.directory() );
 
  475      addDirToUpdate( url );
 
  478      d->m_undoState = REMOVINGFILES;
 
  481void KonqUndoManager::undoRemovingFiles()
 
  483    kdDebug(1203) << 
"KonqUndoManager::undoStep REMOVINGFILES" << endl;
 
  484    if ( !d->m_fileCleanupStack.isEmpty() )
 
  486      KURL file = d->m_fileCleanupStack.pop();
 
  487      kdDebug(1203) << 
"KonqUndoManager::undoStep file_delete " << file.prettyURL() << endl;
 
  488      d->m_currentJob = TDEIO::file_delete( file );
 
  489      d->m_uiserver->deleting( d->m_uiserverJobId, file );
 
  492      url.setPath( url.directory() );
 
  493      addDirToUpdate( url );
 
  497      d->m_undoState = REMOVINGDIRS;
 
  499      if ( d->m_dirCleanupStack.isEmpty() && d->m_current.m_type == KonqCommand::MKDIR )
 
  500        d->m_dirCleanupStack << d->m_current.m_dst;
 
  504void KonqUndoManager::undoRemovingDirectories()
 
  506    if ( !d->m_dirCleanupStack.isEmpty() )
 
  508      KURL dir = d->m_dirCleanupStack.pop();
 
  509      kdDebug(1203) << 
"KonqUndoManager::undoStep rmdir " << dir.prettyURL() << endl;
 
  510      d->m_currentJob = TDEIO::rmdir( dir );
 
  511      d->m_uiserver->deleting( d->m_uiserverJobId, dir );
 
  512      addDirToUpdate( dir );
 
  516      d->m_current.m_valid = 
false;
 
  520          kdDebug(1203) << 
"KonqUndoManager::undoStep deleting undojob" << endl;
 
  521          d->m_uiserver->jobFinished( d->m_uiserverJobId );
 
  525      KDirNotify_stub allDirNotify( 
"*", 
"KDirNotify*" );
 
  526      TQValueList<KURL>::ConstIterator it = d->m_dirsToUpdate.begin();
 
  527      for( ; it != d->m_dirsToUpdate.end(); ++it ) {
 
  528          kdDebug() << 
"Notifying FilesAdded for " << *it << endl;
 
  529          allDirNotify.FilesAdded( *it );
 
  535void KonqUndoManager::push( 
const KonqCommand &cmd )
 
  537  d->m_commands.push( cmd );
 
  538  emit undoAvailable( 
true );
 
  539  emit undoTextChanged( undoText() );
 
  542void KonqUndoManager::pop()
 
  545  emit undoAvailable( undoAvailable() );
 
  546  emit undoTextChanged( undoText() );
 
  549void KonqUndoManager::lock()
 
  553  emit undoAvailable( undoAvailable() );
 
  556void KonqUndoManager::unlock()
 
  560  emit undoAvailable( undoAvailable() );
 
  563KonqCommand::Stack KonqUndoManager::get()
 const 
  565  return d->m_commands;
 
  568void KonqUndoManager::broadcastPush( 
const KonqCommand &cmd )
 
  570  if ( !d->m_syncronized )
 
  576  DCOPRef( 
"kdesktop", 
"KonqUndoManager" ).send( 
"push", cmd );
 
  577  DCOPRef( 
"konqueror*", 
"KonqUndoManager" ).send( 
"push", cmd );
 
  580void KonqUndoManager::broadcastPop()
 
  582  if ( !d->m_syncronized )
 
  587  DCOPRef( 
"kdesktop", 
"KonqUndoManager" ).send( 
"pop" );
 
  588  DCOPRef( 
"konqueror*", 
"KonqUndoManager" ).send( 
"pop" );
 
  591void KonqUndoManager::broadcastLock()
 
  595  if ( !d->m_syncronized )
 
  600  DCOPRef( 
"kdesktop", 
"KonqUndoManager" ).send( 
"lock" );
 
  601  DCOPRef( 
"konqueror*", 
"KonqUndoManager" ).send( 
"lock" );
 
  604void KonqUndoManager::broadcastUnlock()
 
  608  if ( !d->m_syncronized )
 
  613  DCOPRef( 
"kdesktop", 
"KonqUndoManager" ).send( 
"unlock" );
 
  614  DCOPRef( 
"konqueror*", 
"KonqUndoManager" ).send( 
"unlock" );
 
  617bool KonqUndoManager::initializeFromKDesky()
 
  628  DCOPClient *client = tdeApp->dcopClient();
 
  630  if ( client->appId() == 
"kdesktop" ) 
 
  633  if ( !client->isApplicationRegistered( 
"kdesktop" ) )
 
  636  d->m_commands = DCOPRef( 
"kdesktop", 
"KonqUndoManager" ).call( 
"get" );
 
  640TQDataStream &operator<<( TQDataStream &stream, 
const KonqBasicOperation &op )
 
  642    stream << op.m_valid << op.m_directory << op.m_renamed << op.m_link
 
  643           << op.m_src << op.m_dst << op.m_target;
 
  646TQDataStream &operator>>( TQDataStream &stream, KonqBasicOperation &op )
 
  648  stream >> op.m_valid >> op.m_directory >> op.m_renamed >> op.m_link
 
  649         >> op.m_src >> op.m_dst >> op.m_target;
 
  653TQDataStream &operator<<( TQDataStream &stream, 
const KonqCommand &cmd )
 
  655  stream << cmd.m_valid << (TQ_INT8)cmd.m_type << cmd.m_opStack << cmd.m_src << cmd.m_dst;
 
  659TQDataStream &operator>>( TQDataStream &stream, KonqCommand &cmd )
 
  662  stream >> cmd.m_valid >> type >> cmd.m_opStack >> cmd.m_src >> cmd.m_dst;
 
  663  cmd.m_type = 
static_cast<KonqCommand::Type
>( type );
 
  667#include "konq_undo.moc" 
static bool askDeleteConfirmation(const KURL::List &selectedURLs, int method, ConfirmationType confirmation, TQWidget *widget)
Ask for confirmation before deleting/trashing selectedURLs.