libkonq Library API Documentation

konq_operations.cc

00001 /*  This file is part of the KDE project
00002     Copyright (C) 2000  David Faure <faure@kde.org>
00003 
00004     This program is free software; you can redistribute it and/or modify
00005     it under the terms of the GNU General Public License as published by
00006     the Free Software Foundation; either version 2 of the License, or
00007     (at your option) any later version.
00008 
00009     This program is distributed in the hope that it will be useful,
00010     but WITHOUT ANY WARRANTY; without even the implied warranty of
00011     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012     GNU General Public License for more details.
00013 
00014     You should have received a copy of the GNU General Public License
00015     along with this program; if not, write to the Free Software
00016     Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
00017 */
00018 
00019 #include <qclipboard.h>
00020 #include "konq_operations.h"
00021 
00022 #include <kautomount.h>
00023 #include <kinputdialog.h>
00024 #include <klocale.h>
00025 #include <kmessagebox.h>
00026 #include <krun.h>
00027 #include <kshell.h>
00028 
00029 #include <kdirnotify_stub.h>
00030 
00031 #include <dcopclient.h>
00032 #include "konq_undo.h"
00033 #include "konq_defaults.h"
00034 #include "konqbookmarkmanager.h"
00035 
00036 // For doDrop
00037 #include <qdir.h>//first
00038 #include <assert.h>
00039 #include <kapplication.h>
00040 #include <kipc.h>
00041 #include <kdebug.h>
00042 #include <kfileitem.h>
00043 #include <kdesktopfile.h>
00044 #include <kurldrag.h>
00045 #include <kglobalsettings.h>
00046 #include <kimageio.h>
00047 #include <kio/job.h>
00048 #include <kio/jobclasses.h>
00049 #include <kio/paste.h>
00050 #include <konq_drag.h>
00051 #include <konq_iconviewwidget.h>
00052 #include <kprotocolinfo.h>
00053 #include <kprocess.h>
00054 #include <kstringhandler.h>
00055 #include <qpopupmenu.h>
00056 #include <unistd.h>
00057 #include <X11/Xlib.h>
00058 
00059 KBookmarkManager * KonqBookmarkManager::s_bookmarkManager;
00060 
00061 KonqOperations::KonqOperations( QWidget *parent )
00062     : QObject( parent, "KonqOperations" ), m_info(0L), m_pasteInfo(0L)
00063 {
00064 }
00065 
00066 KonqOperations::~KonqOperations()
00067 {
00068     delete m_info;
00069     delete m_pasteInfo;
00070 }
00071 
00072 void KonqOperations::editMimeType( const QString & mimeType )
00073 {
00074   QString keditfiletype = QString::fromLatin1("keditfiletype");
00075   KRun::runCommand( keditfiletype + " " + KProcess::quote(mimeType),
00076                     keditfiletype, keditfiletype /*unused*/);
00077 }
00078 
00079 void KonqOperations::del( QWidget * parent, int method, const KURL::List & selectedURLs )
00080 {
00081   kdDebug(1203) << "KonqOperations::del " << parent->className() << endl;
00082   if ( selectedURLs.isEmpty() )
00083   {
00084     kdWarning(1203) << "Empty URL list !" << endl;
00085     return;
00086   }
00087   // We have to check the trash itself isn't part of the selected
00088   // URLs.
00089   bool bTrashIncluded = false;
00090   KURL::List::ConstIterator it = selectedURLs.begin();
00091   for ( ; it != selectedURLs.end() && !bTrashIncluded; ++it )
00092       if ( (*it).isLocalFile() && (*it).path(1) == KGlobalSettings::trashPath() )
00093           bTrashIncluded = true;
00094   int confirmation = DEFAULT_CONFIRMATION;
00095   if ( bTrashIncluded )
00096   {
00097       switch ( method ) {
00098           case TRASH:
00099               KMessageBox::sorry(0, i18n("You can't trash the trash bin."));
00100               return;
00101           case DEL:
00102           case SHRED:
00103               confirmation = FORCE_CONFIRMATION;
00104               break;
00105       }
00106   }
00107   KonqOperations * op = new KonqOperations( parent );
00108   op->_del( method, selectedURLs, confirmation );
00109 }
00110 
00111 void KonqOperations::emptyTrash()
00112 {
00113   KonqOperations *op = new KonqOperations( 0L );
00114 
00115   QDir trashDir( KGlobalSettings::trashPath() );
00116   QStringList files = trashDir.entryList( QDir::All | QDir::Hidden | QDir::System );
00117   files.remove(QString("."));
00118   files.remove(QString(".."));
00119   files.remove(QString(".directory"));
00120 
00121   QStringList::Iterator it(files.begin());
00122   for (; it != files.end(); ++it )
00123     (*it).prepend( KGlobalSettings::trashPath() );
00124 
00125   KURL::List urls;
00126   it = files.begin();
00127   for (; it != files.end(); ++it )
00128   {
00129     KURL u;
00130     u.setPath( *it );
00131     urls.append( u );
00132   }
00133 
00134   if ( urls.count() > 0 )
00135     op->_del( EMPTYTRASH, urls, SKIP_CONFIRMATION );
00136 
00137 }
00138 
00139 void KonqOperations::mkdir( QWidget *parent, const KURL & url )
00140 {
00141     KIO::Job * job = KIO::mkdir( url );
00142     KonqOperations * op = new KonqOperations( parent );
00143     op->setOperation( job, MKDIR, KURL::List(), url );
00144     (void) new KonqCommandRecorder( KonqCommand::MKDIR, KURL(), url, job ); // no support yet, apparently
00145 }
00146 
00147 void KonqOperations::doPaste( QWidget * parent, const KURL & destURL )
00148 {
00149    doPaste(parent, destURL, QPoint());
00150 }
00151 
00152 void KonqOperations::doPaste( QWidget * parent, const KURL & destURL, const QPoint &pos )
00153 {
00154     // move or not move ?
00155     bool move = false;
00156     QMimeSource *data = QApplication::clipboard()->data();
00157     if ( data->provides( "application/x-kde-cutselection" ) ) {
00158       move = KonqDrag::decodeIsCutSelection( data );
00159       kdDebug(1203) << "move (from clipboard data) = " << move << endl;
00160     }
00161 
00162     KIO::Job *job = KIO::pasteClipboard( destURL, move );
00163     if ( job )
00164     {
00165         KonqOperations * op = new KonqOperations( parent );
00166         KIO::CopyJob * copyJob = static_cast<KIO::CopyJob *>(job);
00167         KIOPasteInfo * pi = new KIOPasteInfo;
00168         pi->destURL = destURL;
00169         pi->mousePos = pos;
00170         op->setPasteInfo( pi );
00171         op->setOperation( job, move ? MOVE : COPY, copyJob->srcURLs(), copyJob->destURL() );
00172         (void) new KonqCommandRecorder( move ? KonqCommand::MOVE : KonqCommand::COPY, KURL::List(), destURL, job );
00173     }
00174 }
00175 
00176 void KonqOperations::copy( QWidget * parent, int method, const KURL::List & selectedURLs, const KURL& destUrl )
00177 {
00178   kdDebug(1203) << "KonqOperations::copy() " << parent->className() << endl;
00179   if ((method!=COPY) && (method!=MOVE) && (method!=LINK))
00180   {
00181     kdWarning(1203) << "Illegal copy method !" << endl;
00182     return;
00183   }
00184   if ( selectedURLs.isEmpty() )
00185   {
00186     kdWarning(1203) << "Empty URL list !" << endl;
00187     return;
00188   }
00189 
00190   KonqOperations * op = new KonqOperations( parent );
00191   KIO::Job* job(0);
00192   if (method==LINK)
00193      job= KIO::link( selectedURLs, destUrl);
00194   else if (method==MOVE)
00195      job= KIO::move( selectedURLs, destUrl);
00196   else
00197      job= KIO::copy( selectedURLs, destUrl);
00198 
00199   op->setOperation( job, method, selectedURLs, destUrl );
00200 
00201   if (method==COPY)
00202      (void) new KonqCommandRecorder( KonqCommand::COPY, selectedURLs, destUrl, job );
00203   else
00204      (void) new KonqCommandRecorder( method==MOVE?KonqCommand::MOVE:KonqCommand::LINK, selectedURLs, destUrl, job );
00205 }
00206 
00207 void KonqOperations::_del( int method, const KURL::List & _selectedURLs, int confirmation )
00208 {
00209     KURL::List selectedURLs;
00210     for (KURL::List::ConstIterator it = _selectedURLs.begin(); it != _selectedURLs.end(); ++it)
00211         if (KProtocolInfo::supportsDeleting(*it))
00212             selectedURLs.append(*it);
00213     if (selectedURLs.isEmpty()) {
00214         delete this;
00215         return;
00216     }
00217 
00218   m_method = method;
00219   if ( confirmation == SKIP_CONFIRMATION || askDeleteConfirmation( selectedURLs, confirmation ) )
00220   {
00221     //m_srcURLs = selectedURLs;
00222     KIO::Job *job;
00223     switch( method )
00224     {
00225       case TRASH:
00226       {
00227         // Make sure the trash exists. Usually the case, but not when starting
00228         // konq standalone.
00229         QString trashPath = KGlobalSettings::trashPath();
00230         if ( !QFile::exists( trashPath ) )
00231             KStandardDirs::makeDir( QFile::encodeName( trashPath ) );
00232         KURL u;
00233         u.setPath( trashPath );
00234         job = KIO::move( selectedURLs, u );
00235         (void) new KonqCommandRecorder( KonqCommand::MOVE, selectedURLs, u, job );
00236          break;
00237       }
00238       case EMPTYTRASH:
00239       case DEL:
00240         job = KIO::del( selectedURLs );
00241         break;
00242       case SHRED:
00243         job = KIO::del( selectedURLs, true );
00244         break;
00245       default:
00246         Q_ASSERT(0);
00247         delete this;
00248         return;
00249     }
00250     connect( job, SIGNAL( result( KIO::Job * ) ),
00251              SLOT( slotResult( KIO::Job * ) ) );
00252   } else
00253     delete this;
00254 }
00255 
00256 bool KonqOperations::askDeleteConfirmation( const KURL::List & selectedURLs, int confirmation )
00257 {
00258     QString keyName;
00259     bool ask = ( confirmation == FORCE_CONFIRMATION );
00260     if ( !ask )
00261     {
00262         KConfig config("konquerorrc", true, false);
00263         config.setGroup( "Trash" );
00264         keyName = ( m_method == DEL ? "ConfirmDelete" : m_method == SHRED ? "ConfirmShred" : "ConfirmTrash" );
00265         bool defaultValue = ( m_method == DEL ? DEFAULT_CONFIRMDELETE : m_method == SHRED ? DEFAULT_CONFIRMSHRED : DEFAULT_CONFIRMTRASH );
00266         ask = config.readBoolEntry( keyName, defaultValue );
00267     }
00268     if ( ask )
00269     {
00270       KURL::List::ConstIterator it = selectedURLs.begin();
00271       QStringList prettyList;
00272       for ( ; it != selectedURLs.end(); ++it )
00273         prettyList.append( (*it).prettyURL() );
00274 
00275       int result;
00276       switch(m_method)
00277       {
00278       case DEL:
00279           result = KMessageBox::warningContinueCancelList( 0,
00280                 i18n( "Do you really want to delete this item?", "Do you really want to delete these %n items?", prettyList.count()),
00281                 prettyList,
00282         i18n( "Delete Files" ),
00283         KGuiItem( i18n( "Delete" ), "editdelete" ),
00284         keyName, KMessageBox::Dangerous);
00285      break;
00286 
00287       case SHRED:
00288           result = KMessageBox::warningContinueCancelList( 0,
00289                 i18n( "Do you really want to shred this item?", "Do you really want to shred these %n items?", prettyList.count()),
00290                 prettyList,
00291                 i18n( "Shred Files" ),
00292         KGuiItem( i18n( "Shred" ), "editshred" ),
00293         keyName, KMessageBox::Dangerous);
00294         break;
00295 
00296       case MOVE:
00297       default:
00298           result = KMessageBox::warningContinueCancelList( 0,
00299                 i18n( "Do you really want to move this item to the trash?", "Do you really want to move these %n items to the trash?", prettyList.count()),
00300                 prettyList,
00301         i18n( "Move to Trash" ),
00302         KGuiItem( i18n( "Verb", "Trash" ), "edittrash"),
00303         keyName, KMessageBox::Dangerous);
00304       }
00305       if (!keyName.isEmpty())
00306       {
00307          // Check kmessagebox setting... erase & copy to konquerorrc.
00308          KConfig *config = kapp->config();
00309          KConfigGroupSaver saver(config, "Notification Messages");
00310          if (!config->readBoolEntry(keyName, true))
00311          {
00312             config->writeEntry(keyName, true);
00313             config->sync();
00314             KConfig konq_config("konquerorrc", false);
00315             konq_config.setGroup( "Trash" );
00316             konq_config.writeEntry( keyName, false );
00317          }
00318       }
00319       return (result == KMessageBox::Continue);
00320     }
00321     return true;
00322 }
00323 
00324 void KonqOperations::doDrop( const KFileItem * destItem, const KURL & dest, QDropEvent * ev, QWidget * parent )
00325 {
00326     kdDebug(1203) << "doDrop: dest : " << dest.url() << endl;
00327     KURL::List lst;
00328     QMap<QString, QString> metaData;
00329     if ( KURLDrag::decode( ev, lst, metaData ) ) // Are they urls ?
00330     {
00331         if( lst.count() == 0 )
00332         {
00333             kdWarning(1203) << "Oooops, no data ...." << endl;
00334             ev->accept(false);
00335             return;
00336         }
00337         kdDebug(1203) << "KonqOperations::doDrop metaData: " << metaData.count() << " entries." << endl;
00338         QMap<QString,QString>::ConstIterator mit;
00339         for( mit = metaData.begin(); mit != metaData.end(); ++mit )
00340         {
00341             kdDebug(1203) << "metaData: key=" << mit.key() << " value=" << mit.data() << endl;
00342         }
00343         // Check if we dropped something on itself
00344         KURL::List::Iterator it = lst.begin();
00345         for ( ; it != lst.end() ; it++ )
00346         {
00347             kdDebug(1203) << "URL : " << (*it).url() << endl;
00348             if ( dest.equals( *it, true /*ignore trailing slashes*/ ) )
00349             {
00350                 // The event source may be the view or an item (icon)
00351                 // Note: ev->source() can be 0L! (in case of kdesktop) (Simon)
00352                 if ( !ev->source() || ev->source() != parent && ev->source()->parent() != parent )
00353                     KMessageBox::sorry( parent, i18n("You cannot drop a folder on to itself") );
00354                 kdDebug(1203) << "Dropped on itself" << endl;
00355                 ev->accept(false);
00356                 return; // do nothing instead of displaying kfm's annoying error box
00357             }
00358         }
00359 
00360         // Check the state of the modifiers key at the time of the drop
00361         Window root;
00362         Window child;
00363         int root_x, root_y, win_x, win_y;
00364         uint keybstate;
00365         XQueryPointer( qt_xdisplay(), qt_xrootwin(), &root, &child,
00366                        &root_x, &root_y, &win_x, &win_y, &keybstate );
00367 
00368         QDropEvent::Action action = ev->action();
00369         // Check for the drop of a bookmark -> we want a Link action
00370         if ( ev->provides("application/x-xbel") )
00371         {
00372             keybstate |= ControlMask | ShiftMask;
00373             action = QDropEvent::Link;
00374             kdDebug(1203) << "KonqOperations::doDrop Bookmark -> emulating Link" << endl;
00375         }
00376 
00377         KonqOperations * op = new KonqOperations(parent);
00378         op->setDropInfo( new DropInfo( keybstate, lst, metaData, win_x, win_y, action ) );
00379 
00380         // Ok, now we need destItem.
00381         if ( destItem )
00382         {
00383             op->asyncDrop( destItem ); // we have it already
00384         }
00385         else
00386         {
00387             // we need to stat to get it.
00388             op->_statURL( dest, op, SLOT( asyncDrop( const KFileItem * ) ) );
00389         }
00390         // In both cases asyncDrop will delete op when done
00391 
00392         ev->acceptAction();
00393     }
00394     else
00395     {
00396         QStrList formats;
00397 
00398         for ( int i = 0; ev->format( i ); i++ )
00399             if ( *( ev->format( i ) ) )
00400                 formats.append( ev->format( i ) );
00401         if ( formats.count() >= 1 )
00402         {
00403             //kdDebug(1203) << "Pasting to " << dest.url() << endl;
00404 
00405             QByteArray data;
00406 
00407             QString text;
00408             if ( QTextDrag::canDecode( ev ) && QTextDrag::decode( ev, text ) )
00409             {
00410                 QTextStream txtStream( data, IO_WriteOnly );
00411                 txtStream << text;
00412             }
00413             else
00414                 data = ev->data( formats.first() );
00415 
00416             // Delay the call to KIO::pasteData so that the event filters can return. See #38688.
00417             KonqOperations * op = new KonqOperations(parent);
00418             KIOPasteInfo * pi = new KIOPasteInfo;
00419             pi->data = data;
00420             pi->destURL = dest;
00421             pi->mousePos = ev->pos();
00422             op->setPasteInfo( pi );
00423             QTimer::singleShot( 0, op, SLOT( slotKIOPaste() ) );
00424         }
00425         ev->acceptAction();
00426     }
00427 }
00428 
00429 void KonqOperations::slotKIOPaste()
00430 {
00431     assert(m_pasteInfo); // setPasteInfo should have been called before
00432     KIO::CopyJob *job = KIO::pasteDataAsync( m_pasteInfo->destURL, m_pasteInfo->data );
00433     if ( job )
00434     {
00435         setOperation( job, COPY, KURL::List(), job->destURL() );
00436         (void) new KonqCommandRecorder( KonqCommand::COPY, KURL::List(), m_destURL, job );
00437     }
00438     else
00439     {
00440         delete this;
00441     }
00442 }
00443 
00444 void KonqOperations::asyncDrop( const KFileItem * destItem )
00445 {
00446     assert(m_info); // setDropInfo should have been called before asyncDrop
00447     m_destURL = destItem->url();
00448 
00449     //kdDebug(1203) << "KonqOperations::asyncDrop destItem->mode=" << destItem->mode() << " url=" << m_destURL << endl;
00450     // Check what the destination is
00451     if ( destItem->isDir() )
00452     {
00453         doFileCopy();
00454         return;
00455     }
00456     if ( !m_destURL.isLocalFile() )
00457     {
00458         // We dropped onto a remote URL that is not a directory!
00459         // (e.g. an HTTP link in the sidebar).
00460         // Can't do that, but we can't prevent it before stating the dest....
00461         kdWarning(1203) << "Cannot drop onto " << m_destURL << endl;
00462         delete this;
00463         return;
00464     }
00465     if ( destItem->mimetype() == "application/x-desktop")
00466     {
00467         // Local .desktop file. What type ?
00468         KDesktopFile desktopFile( m_destURL.path() );
00469         if ( desktopFile.hasApplicationType() )
00470         {
00471             QString error;
00472             QStringList stringList;
00473             KURL::List lst = m_info->lst;
00474             KURL::List::Iterator it = lst.begin();
00475             for ( ; it != lst.end() ; it++ )
00476             {
00477                 stringList.append((*it).url());
00478             }
00479             if ( KApplication::startServiceByDesktopPath( m_destURL.path(), stringList, &error ) > 0 )
00480                 KMessageBox::error( 0L, error );
00481         }
00482         else
00483         {
00484             // Device or Link -> adjust dest
00485             if ( desktopFile.hasDeviceType() && desktopFile.hasKey("MountPoint") ) {
00486                 QString point = desktopFile.readEntry( "MountPoint" );
00487                 m_destURL.setPath( point );
00488                 QString dev = desktopFile.readDevice();
00489                 QString mp = KIO::findDeviceMountPoint( dev );
00490                 // Is the device already mounted ?
00491                 if ( !mp.isNull() )
00492                     doFileCopy();
00493                 else
00494                 {
00495                     bool ro = desktopFile.readBoolEntry( "ReadOnly", false );
00496                     QString fstype = desktopFile.readEntry( "FSType" );
00497                     KAutoMount* am = new KAutoMount( ro, fstype, dev, point, m_destURL.path(), false );
00498                     connect( am, SIGNAL( finished() ), this, SLOT( doFileCopy() ) );
00499                 }
00500                 return;
00501             }
00502             else if ( desktopFile.hasLinkType() && desktopFile.hasKey("URL") ) {
00503                 m_destURL = desktopFile.readPathEntry("URL");
00504                 doFileCopy();
00505                 return;
00506             }
00507             // else, well: mimetype, service, servicetype or .directory. Can't really drop anything on those.
00508         }
00509     }
00510     else
00511     {
00512         // Should be a local executable
00513         // (If this fails, there is a bug in KFileItem::acceptsDrops)
00514         kdDebug(1203) << "KonqOperations::doDrop " << m_destURL.path() << "should be an executable" << endl;
00515         Q_ASSERT ( access( QFile::encodeName(m_destURL.path()), X_OK ) == 0 );
00516         KProcess proc;
00517         proc << m_destURL.path() ;
00518         // Launch executable for each of the files
00519         KURL::List lst = m_info->lst;
00520         KURL::List::Iterator it = lst.begin();
00521         for ( ; it != lst.end() ; it++ )
00522             proc << (*it).path(); // assume local files
00523         kdDebug(1203) << "starting " << m_destURL.path() << " with " << lst.count() << " arguments" << endl;
00524         proc.start( KProcess::DontCare );
00525     }
00526     delete this;
00527 }
00528 
00529 void KonqOperations::doFileCopy()
00530 {
00531     assert(m_info); // setDropInfo - and asyncDrop - should have been called before asyncDrop
00532     KURL::List lst = m_info->lst;
00533     QDropEvent::Action action = m_info->action;
00534     QString newTrashPath;
00535     bool isDesktopFile = false;
00536     bool itemIsOnDesktop = false;
00537     KURL::List mlst;
00538     for (KURL::List::ConstIterator it = lst.begin(); it != lst.end(); ++it)
00539     {
00540         bool local = (*it).isLocalFile();
00541         if ( local && ((*it).path(1) == KGlobalSettings::trashPath()))
00542             newTrashPath=m_destURL.path()+(*it).path().right((*it).path().length()-(*it).directory().length());
00543         if ( KProtocolInfo::supportsDeleting( *it ) && (!local || QFileInfo((*it).directory()).isWritable() ))
00544             mlst.append(*it);
00545         if ( local && KDesktopFile::isDesktopFile((*it).path()))
00546             isDesktopFile = true;
00547         if ( local && (*it).path().startsWith(KGlobalSettings::desktopPath()))
00548             itemIsOnDesktop = true;
00549     }
00550 
00551     bool linkOnly = false;
00552     if (isDesktopFile && !kapp->authorize("run_desktop_files") &&
00553         (m_destURL.path(1) == KGlobalSettings::desktopPath()) )
00554     {
00555        linkOnly = true;
00556     }
00557 
00558     if ( !mlst.isEmpty() && m_destURL.path( 1 ) == KGlobalSettings::trashPath() )
00559     {
00560         if ( itemIsOnDesktop && !kapp->authorize("editable_desktop_icons") )
00561         {
00562             delete this;
00563             return;
00564         }
00565 
00566         if ( askDeleteConfirmation( mlst, DEFAULT_CONFIRMATION ) )
00567             action = QDropEvent::Move;
00568         else
00569         {
00570             delete this;
00571             return;
00572         }
00573     }
00574     else if ( (((m_info->keybstate & ControlMask) == 0) && ((m_info->keybstate & ShiftMask) == 0)) ||
00575               linkOnly )
00576     {
00577         KonqIconViewWidget *iconView = dynamic_cast<KonqIconViewWidget*>(parent());
00578         bool bSetWallpaper = false;
00579         if (iconView && iconView->maySetWallpaper() &&
00580             (lst.count() == 1) &&
00581             ((!KImageIO::type(lst.first().path()).isEmpty()) ||
00582              (KImageIO::isSupported(KMimeType::findByURL(lst.first())->name(),
00583                                     KImageIO::Reading))))
00584         {
00585             bSetWallpaper = true;
00586         }
00587 
00588         // Check what the source can do
00589         KURL url = lst.first(); // we'll assume it's the same for all URLs (hack)
00590         bool sReading = KProtocolInfo::supportsReading( url );
00591         bool sDeleting = KProtocolInfo::supportsDeleting( url );
00592         bool sMoving = KProtocolInfo::supportsMoving( url );
00593         // Check what the destination can do
00594         bool dWriting = KProtocolInfo::supportsWriting( m_destURL );
00595         if ( !dWriting )
00596         {
00597             delete this;
00598             return;
00599         }
00600         //bool sTrash = url.path(1) == KGlobalSettings::trashPath();
00601         // Nor control nor shift are pressed => show popup menu
00602 
00603         QPopupMenu popup;
00604         if (!mlst.isEmpty() && (sMoving || (sReading && sDeleting)) && !linkOnly )
00605             popup.insertItem( i18n( "&Move Here" ), 2 );
00606         if ( sReading && !linkOnly)
00607             popup.insertItem(SmallIconSet("editcopy"), i18n( "&Copy Here" ), 1 );
00608         popup.insertItem(SmallIconSet("www"), i18n( "&Link Here" ), 3 );
00609         if (bSetWallpaper)
00610             popup.insertItem(SmallIconSet("background"), i18n( "Set as &Wallpaper" ), 4 );
00611         popup.insertSeparator();
00612         popup.insertItem(SmallIconSet("cancel"), i18n( "C&ancel" ), 5);
00613 
00614         int result = popup.exec( m_info->mousePos );
00615 
00616         switch (result) {
00617         case 1 : action = QDropEvent::Copy; break;
00618         case 2 : action = QDropEvent::Move; break;
00619         case 3 : action = QDropEvent::Link; break;
00620         case 4 :
00621         {
00622             kdDebug(1203) << "setWallpaper iconView=" << iconView << " url=" << lst.first().url() << endl;
00623             if (iconView && iconView->isDesktop() ) iconView->setWallpaper(lst.first());
00624             delete this;
00625             return;
00626         }
00627         case 5 :
00628         default : delete this; return;
00629         }
00630     }
00631 
00632     KIO::Job * job = 0;
00633     switch ( action ) {
00634     case QDropEvent::Move :
00635         job = KIO::move( lst, m_destURL );
00636         job->setMetaData( m_info->metaData );
00637         setOperation( job, MOVE, lst, m_destURL );
00638         if ( !newTrashPath.isEmpty() )
00639         {
00640 
00641             kdDebug(1203) << "Update trash path" <<newTrashPath<< endl;
00642             KConfig *globalConfig = KGlobal::config();
00643             KConfigGroupSaver cgs( globalConfig, "Paths" );
00644             globalConfig->writePathEntry("Trash" , newTrashPath, true, true );
00645             globalConfig->sync();
00646             KIPC::sendMessageAll(KIPC::SettingsChanged, KApplication::SETTINGS_PATHS);
00647         }
00648 
00649         (void) new KonqCommandRecorder( KonqCommand::MOVE, lst, m_destURL, job );
00650         return; // we still have stuff to do -> don't delete ourselves
00651     case QDropEvent::Copy :
00652         job = KIO::copy( lst, m_destURL );
00653         job->setMetaData( m_info->metaData );
00654         setOperation( job, COPY, lst, m_destURL );
00655         (void) new KonqCommandRecorder( KonqCommand::COPY, lst, m_destURL, job );
00656         return;
00657     case QDropEvent::Link :
00658         kdDebug(1203) << "KonqOperations::asyncDrop lst.count=" << lst.count() << endl;
00659         job = KIO::link( lst, m_destURL );
00660         job->setMetaData( m_info->metaData );
00661         setOperation( job, LINK, lst, m_destURL );
00662         (void) new KonqCommandRecorder( KonqCommand::LINK, lst, m_destURL, job );
00663         return;
00664     default : kdError(1203) << "Unknown action " << (int)action << endl;
00665     }
00666     delete this;
00667 }
00668 
00669 void KonqOperations::rename( QWidget * parent, const KURL & oldurl, const KURL& newurl )
00670 {
00671     kdDebug(1203) << "KonqOperations::rename oldurl=" << oldurl.prettyURL() << " newurl=" << newurl.prettyURL() << endl;
00672     if ( oldurl == newurl )
00673         return;
00674 
00675     KURL::List lst;
00676     lst.append(oldurl);
00677     KIO::Job * job = KIO::moveAs( oldurl, newurl, !oldurl.isLocalFile() );
00678     KonqOperations * op = new KonqOperations( parent );
00679     op->setOperation( job, MOVE, lst, newurl );
00680     (void) new KonqCommandRecorder( KonqCommand::MOVE, lst, newurl, job );
00681     // if old trash then update config file and emit
00682     if(oldurl.isLocalFile() )
00683     {
00684         if (  oldurl.path(1) == KGlobalSettings::trashPath() ) {
00685             kdDebug(1203) << "That rename was the Trashcan, updating config files" << endl;
00686             KConfig *globalConfig = KGlobal::config();
00687             KConfigGroupSaver cgs( globalConfig, "Paths" );
00688             globalConfig->writePathEntry("Trash" , newurl.path(), true, true );
00689             globalConfig->sync();
00690             KIPC::sendMessageAll(KIPC::SettingsChanged, KApplication::SETTINGS_PATHS);
00691         }
00692         // if old trash then update config file and emit
00693         if(oldurl.path(1) == KGlobalSettings::desktopPath() )
00694         {
00695             kdDebug(1203) << "That rename was the Desktop path, updating config files" << endl;
00696             KConfig *globalConfig = KGlobal::config();
00697             KConfigGroupSaver cgs( globalConfig, "Paths" );
00698             globalConfig->writePathEntry("Desktop" , newurl.path(), true, true );
00699             if ( KGlobalSettings::trashPath().startsWith(oldurl.path(1) ))
00700             {
00701                 QString newTrashPath = newurl.path()+KGlobalSettings::trashPath().right(KGlobalSettings::trashPath().length()-KURL(KGlobalSettings::trashPath()).directory().length());
00702 
00703                 globalConfig->writePathEntry("Trash" , newTrashPath, true, true );
00704             }
00705             globalConfig->sync();
00706             KIPC::sendMessageAll(KIPC::SettingsChanged, KApplication::SETTINGS_PATHS);
00707         }
00708     }
00709 
00710 }
00711 
00712 void KonqOperations::setOperation( KIO::Job * job, int method, const KURL::List & /*src*/, const KURL & dest )
00713 {
00714     m_method = method;
00715     //m_srcURLs = src;
00716     m_destURL = dest;
00717     if ( job )
00718     {
00719         connect( job, SIGNAL( result( KIO::Job * ) ),
00720                  SLOT( slotResult( KIO::Job * ) ) );
00721     }
00722     else // for link
00723         slotResult( 0L );
00724 
00725     KIO::CopyJob *copyJob = dynamic_cast<KIO::CopyJob*>(job);
00726     KonqIconViewWidget *iconView = dynamic_cast<KonqIconViewWidget*>(parent());
00727     if (copyJob && iconView)
00728     {
00729         connect(copyJob, SIGNAL(aboutToCreate(KIO::Job *,const QValueList<KIO::CopyInfo> &)),
00730              this, SLOT(slotAboutToCreate(KIO::Job *,const QValueList<KIO::CopyInfo> &)));
00731         connect(this, SIGNAL(aboutToCreate(const QPoint &, const QValueList<KIO::CopyInfo> &)),
00732              iconView, SLOT(slotAboutToCreate(const QPoint &, const QValueList<KIO::CopyInfo> &)));
00733     }
00734 }
00735 
00736 void KonqOperations::slotAboutToCreate(KIO::Job *, const QValueList<KIO::CopyInfo> &files)
00737 {
00738     emit aboutToCreate( m_info ? m_info->mousePos : m_pasteInfo ? m_pasteInfo->mousePos : QPoint(), files);
00739 }
00740 
00741 void KonqOperations::statURL( const KURL & url, const QObject *receiver, const char *member )
00742 {
00743     KonqOperations * op = new KonqOperations( 0L );
00744     op->_statURL( url, receiver, member );
00745     op->m_method = STAT;
00746 }
00747 
00748 void KonqOperations::_statURL( const KURL & url, const QObject *receiver, const char *member )
00749 {
00750     connect( this, SIGNAL( statFinished( const KFileItem * ) ), receiver, member );
00751     KIO::StatJob * job = KIO::stat( url /*, false?*/ );
00752     connect( job, SIGNAL( result( KIO::Job * ) ),
00753              SLOT( slotStatResult( KIO::Job * ) ) );
00754 }
00755 
00756 void KonqOperations::slotStatResult( KIO::Job * job )
00757 {
00758     if ( job->error())
00759         job->showErrorDialog( (QWidget*)parent() );
00760     else
00761     {
00762         KIO::StatJob * statJob = static_cast<KIO::StatJob*>(job);
00763         KFileItem * item = new KFileItem( statJob->statResult(), statJob->url() );
00764         emit statFinished( item );
00765         delete item;
00766     }
00767     // If we're only here for a stat, we're done. But not if we used _statURL internally
00768     if ( m_method == STAT )
00769         delete this;
00770 }
00771 
00772 void KonqOperations::slotResult( KIO::Job * job )
00773 {
00774     if (job && job->error())
00775         job->showErrorDialog( (QWidget*)parent() );
00776 
00777     // Update trash bin icon if trashing files or emptying trash
00778     bool bUpdateTrash = m_method == TRASH || m_method == EMPTYTRASH;
00779     // ... or if creating a new file in the trash
00780     if ( m_method == MOVE || m_method == COPY || m_method == LINK )
00781     {
00782         KURL trash;
00783         trash.setPath( KGlobalSettings::trashPath() );
00784         if ( m_destURL.equals( trash, true /*ignore trailing slash*/ ) )
00785             bUpdateTrash = true;
00786     }
00787     if (bUpdateTrash)
00788     {
00789         // Update trash bin icon
00790         KURL trash;
00791         trash.setPath( KGlobalSettings::trashPath() );
00792         KURL::List lst;
00793         lst.append(trash);
00794         KDirNotify_stub allDirNotify("*", "KDirNotify*");
00795         allDirNotify.FilesChanged( lst );
00796     }
00797     delete this;
00798 }
00799 
00800 void KonqOperations::rename( QWidget * parent, const KURL & oldurl, const QString & name )
00801 {
00802     KURL newurl( oldurl );
00803     newurl.setPath( oldurl.directory(false, true) + name );
00804     kdDebug(1203) << "KonqOperations::rename("<<name<<") called. newurl=" << newurl.prettyURL() << endl;
00805     rename( parent, oldurl, newurl );
00806 }
00807 
00808 void KonqOperations::newDir( QWidget * parent, const KURL & baseURL )
00809 {
00810     bool ok;
00811     QString name = i18n( "New Folder" );
00812     if (baseURL.isLocalFile())
00813     {
00814        QString base = name;
00815        int n = 2;
00816        while(true)
00817        {
00818           KURL url=baseURL;
00819           url.addPath( name );
00820 
00821           if (access(QFile::encodeName(url.path()), F_OK) == -1)
00822              break;
00823 
00824           name = base + QString("_%1").arg(n++);
00825        }
00826     }
00827 
00828     name = KInputDialog::getText ( i18n( "New Folder" ),
00829         i18n( "Enter folder name:" ), name, &ok, parent );
00830     if ( ok && !name.isEmpty() )
00831     {
00832         KURL url;
00833         if ((name[0] == '/') || (name[0] == '~'))
00834         {
00835            url.setPath(KShell::tildeExpand(name));
00836         }
00837         else
00838         {
00839            name = KIO::encodeFileName( name );
00840            url = baseURL;
00841            url.addPath( name );
00842         }
00843         KonqOperations::mkdir( 0L, url );
00844     }
00845 }
00846 
00847 #include "konq_operations.moc"
KDE Logo
This file is part of the documentation for libkonq Library Version 3.2.2.
Documentation copyright © 1996-2004 the KDE developers.
Generated on Sun Apr 11 13:44:47 2004 by doxygen 1.3.6-20040222 written by Dimitri van Heesch, © 1997-2003