Fix crash if key bindings specified in profile cannot be found. Improve
[personal-kdebase.git] / apps / lib / konq / konq_operations.cpp
blob04c6954152c1101fecf829efb7b5473c201a1b0c
1 /* This file is part of the KDE project
2 Copyright 2000-2007 David Faure <faure@kde.org>
3 Copyright 2003 Waldo Bastian <bastian@kde.org>
4 Copyright 2002 Michael Brade <brade@kde.org>
5 Copyright 2001-2002 Alexander Neundorf <neundorf@kde.org>
6 Copyright 2000-2001 Simon Hausmann <hausmann@kde.org>
8 This library is free software; you can redistribute it and/or
9 modify it under the terms of the GNU Library General Public
10 License as published by the Free Software Foundation; either
11 version 2 of the License, or (at your option) version 3.
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
23 #include "konq_operations.h"
24 #include "konqmimedata.h"
26 #include <ktoolinvocation.h>
27 #include <kautomount.h>
28 #include <kmountpoint.h>
29 #include <kinputdialog.h>
30 #include <klocale.h>
31 #include <kmessagebox.h>
32 #include <knotification.h>
33 #include <krun.h>
34 #include <kshell.h>
35 #include <kprocess.h>
36 #include <kshortcut.h>
37 #include <kprotocolmanager.h>
38 #include <kio/deletejob.h>
39 #include <kio/fileundomanager.h>
40 #include <kio/job.h>
41 #include <kio/jobuidelegate.h>
42 #include <kio/jobclasses.h>
43 #include <kio/copyjob.h>
44 #include <kio/paste.h>
45 #include <kio/renamedialog.h>
46 #include <kdirnotify.h>
47 #include <kuiserverjobtracker.h>
48 #include <kstandarddirs.h>
49 // For doDrop
50 #include <kauthorized.h>
51 #include <kglobal.h>
52 #include <kglobalsettings.h>
53 #include <kdebug.h>
54 #include <kfileitem.h>
55 #include <kdesktopfile.h>
57 //#include <konq_iconviewwidget.h>
58 #include <QtDBus/QtDBus>
59 #include <QMenu>
60 #include <QApplication>
61 #include <QClipboard>
62 #include <QDropEvent>
63 #include <QList>
64 #include <QDir>
66 #include <assert.h>
67 #include <unistd.h>
68 #include <kconfiggroup.h>
70 KonqOperations::KonqOperations( QWidget *parent )
71 : QObject( parent ),
72 m_method( UNKNOWN ), m_info(0), m_pasteInfo(0)
74 setObjectName( "KonqOperations" );
77 KonqOperations::~KonqOperations()
79 delete m_info;
80 delete m_pasteInfo;
83 void KonqOperations::editMimeType( const QString & mimeType, QWidget* parent )
85 QString keditfiletype = QLatin1String("keditfiletype");
86 KRun::runCommand( keditfiletype
87 + " --parent " + QString::number( (long)parent->winId())
88 + ' ' + KShell::quoteArg(mimeType),
89 keditfiletype, keditfiletype /*unused*/, parent );
92 void KonqOperations::del( QWidget * parent, Operation method, const KUrl::List & selectedUrls )
94 kDebug(1203) << "KonqOperations::del " << parent->metaObject()->className();
95 if ( selectedUrls.isEmpty() )
97 kWarning(1203) << "Empty URL list !" ;
98 return;
101 KonqOperations * op = new KonqOperations( parent );
102 ConfirmationType confirmation = DEFAULT_CONFIRMATION;
103 op->_del( method, selectedUrls, confirmation );
106 void KonqOperations::emptyTrash( QWidget* parent )
108 KonqOperations *op = new KonqOperations( parent );
109 op->_del( EMPTYTRASH, KUrl("trash:/"), SKIP_CONFIRMATION );
112 void KonqOperations::restoreTrashedItems( const KUrl::List& urls, QWidget* parent )
114 KonqOperations *op = new KonqOperations( parent );
115 op->_restoreTrashedItems( urls );
118 KIO::SimpleJob* KonqOperations::mkdir( QWidget *parent, const KUrl & url )
120 KIO::SimpleJob * job = KIO::mkdir(url);
121 job->ui()->setWindow(parent);
122 job->ui()->setAutoErrorHandlingEnabled(true);
123 KIO::FileUndoManager::self()->recordJob( KIO::FileUndoManager::Mkdir, KUrl(), url, job );
124 return job;
127 void KonqOperations::doPaste( QWidget * parent, const KUrl & destUrl, const QPoint &pos )
129 // move or not move ?
130 bool move = false;
131 const QMimeData *data = QApplication::clipboard()->mimeData();
132 if ( data->hasFormat( "application/x-kde-cutselection" ) ) {
133 move = KonqMimeData::decodeIsCutSelection( data );
134 kDebug(1203) << "move (from clipboard data) = " << move;
137 KIO::Job *job = KIO::pasteClipboard( destUrl, parent, move );
138 if ( job )
140 KonqOperations * op = new KonqOperations( parent );
141 KIO::CopyJob * copyJob = static_cast<KIO::CopyJob *>(job);
142 KIOPasteInfo * pi = new KIOPasteInfo;
143 pi->mousePos = pos;
144 op->setPasteInfo( pi );
145 op->setOperation( job, move ? MOVE : COPY, copyJob->destUrl() );
146 KIO::FileUndoManager::self()->recordJob( move ? KIO::FileUndoManager::Move : KIO::FileUndoManager::Copy, KUrl::List(), destUrl, job );
150 void KonqOperations::copy( QWidget * parent, Operation method, const KUrl::List & selectedUrls, const KUrl& destUrl )
152 kDebug(1203) << "KonqOperations::copy() " << parent->metaObject()->className();
153 if ((method!=COPY) && (method!=MOVE) && (method!=LINK))
155 kWarning(1203) << "Illegal copy method !" ;
156 return;
158 if ( selectedUrls.isEmpty() )
160 kWarning(1203) << "Empty URL list !" ;
161 return;
164 KonqOperations * op = new KonqOperations( parent );
165 KIO::CopyJob* job;
166 if (method == LINK)
167 job = KIO::link( selectedUrls, destUrl );
168 else if (method == MOVE)
169 job = KIO::move( selectedUrls, destUrl );
170 else
171 job = KIO::copy( selectedUrls, destUrl );
173 op->setOperation( job, method, destUrl );
175 KIO::FileUndoManager::self()->recordCopyJob(job);
178 void KonqOperations::_del( Operation method, const KUrl::List & _selectedUrls, ConfirmationType confirmation )
180 KUrl::List selectedUrls;
181 for (KUrl::List::ConstIterator it = _selectedUrls.begin(); it != _selectedUrls.end(); ++it)
182 if (KProtocolManager::supportsDeleting(*it))
183 selectedUrls.append(*it);
184 if (selectedUrls.isEmpty()) {
185 delete this; // this one is ok, _del is always called directly
186 return;
189 if ( confirmation == SKIP_CONFIRMATION || askDeleteConfirmation( selectedUrls, method, confirmation, parentWidget() ) )
191 //m_srcUrls = selectedUrls;
192 KIO::Job *job;
193 m_method = method;
194 switch( method )
196 case TRASH:
198 job = KIO::trash( selectedUrls );
199 KIO::FileUndoManager::self()->recordJob( KIO::FileUndoManager::Trash, selectedUrls, KUrl("trash:/"), job );
200 break;
202 case EMPTYTRASH:
204 // Same as in ktrash --empty
205 QByteArray packedArgs;
206 QDataStream stream( &packedArgs, QIODevice::WriteOnly );
207 stream << (int)1;
208 job = KIO::special( KUrl("trash:/"), packedArgs );
209 KNotification::event("Trash: emptied", QString() , QPixmap() , 0l, KNotification::DefaultEvent );
210 break;
212 case DEL:
213 job = KIO::del( selectedUrls );
214 break;
215 default:
216 kWarning() << "Unknown operation: " << method ;
217 delete this; // this one is ok, _del is always called directly
218 return;
220 job->ui()->setWindow(parentWidget());
221 connect( job, SIGNAL( result( KJob * ) ),
222 SLOT( slotResult( KJob * ) ) );
223 } else {
224 delete this; // this one is ok, _del is always called directly
228 void KonqOperations::_restoreTrashedItems( const KUrl::List& urls )
230 m_method = RESTORE;
231 KonqMultiRestoreJob* job = new KonqMultiRestoreJob( urls );
232 job->ui()->setWindow(parentWidget());
233 KIO::getJobTracker()->registerJob(job);
234 connect( job, SIGNAL( result( KJob * ) ),
235 SLOT( slotResult( KJob * ) ) );
238 bool KonqOperations::askDeleteConfirmation( const KUrl::List & selectedUrls, int method, ConfirmationType confirmation, QWidget* widget )
240 KIO::JobUiDelegate::DeletionType deletionType = method == DEL ? KIO::JobUiDelegate::Delete : KIO::JobUiDelegate::Trash;
241 KIO::JobUiDelegate::ConfirmationType confirmationType = confirmation == FORCE_CONFIRMATION ? KIO::JobUiDelegate::ForceConfirmation : KIO::JobUiDelegate::DefaultConfirmation;
242 KIO::JobUiDelegate uiDelegate;
243 uiDelegate.setWindow(widget);
244 return uiDelegate.askDeleteConfirmation(selectedUrls, deletionType, confirmationType);
247 void KonqOperations::doDrop( const KFileItem & destItem, const KUrl & dest, QDropEvent * ev, QWidget * parent )
249 kDebug(1203) << "doDrop: dest:" << dest;
250 QMap<QString, QString> metaData;
251 const KUrl::List lst = KUrl::List::fromMimeData(ev->mimeData(), &metaData);
252 if (!lst.isEmpty()) { // Are they urls ?
253 //kDebug(1203) << "metaData:" << metaData.count() << "entries.";
254 //QMap<QString,QString>::ConstIterator mit;
255 //for( mit = metaData.begin(); mit != metaData.end(); ++mit ) {
256 // kDebug(1203) << "metaData: key=" << mit.key() << "value=" << mit.value();
258 // Check if we dropped something on itself
259 KUrl::List::ConstIterator it = lst.begin();
260 for (; it != lst.end() ; it++) {
261 kDebug(1203) << "URL:" << (*it);
262 if (dest.equals(*it, KUrl::CompareWithoutTrailingSlash)) {
263 // The event source may be the view or an item (icon)
264 // Note: ev->source() can be 0L! (in case of kdesktop) (Simon)
265 if ( !ev->source() || ( ev->source() != parent && ev->source()->parent() != parent ) )
266 KMessageBox::sorry( parent, i18n("You cannot drop a folder on to itself") );
267 kDebug(1203) << "Dropped on itself";
268 ev->setAccepted( false );
269 return; // do nothing instead of displaying kfm's annoying error box
273 // Check the state of the modifiers key at the time of the drop
274 Qt::KeyboardModifiers modifiers = QApplication::keyboardModifiers();
276 Qt::DropAction action = ev->dropAction();
277 // Check for the drop of a bookmark -> we want a Link action
278 if ( ev->provides("application/x-xbel") )
280 modifiers |= Qt::ControlModifier | Qt::ShiftModifier;
281 action = Qt::LinkAction;
282 kDebug(1203) << "KonqOperations::doDrop Bookmark -> emulating Link";
285 KonqOperations * op = new KonqOperations(parent);
286 op->setDropInfo( new DropInfo( modifiers, lst, metaData, QCursor::pos(), action ) );
288 // Ok, now we need destItem.
289 if ( !destItem.isNull() )
291 op->asyncDrop( destItem ); // we have it already
293 else
295 // we need to stat to get it.
296 op->_statUrl( dest, op, SLOT( asyncDrop( const KFileItem & ) ) );
298 // In both cases asyncDrop will delete op when done
300 ev->acceptProposedAction();
302 else
304 //kDebug(1203) << "Pasting to " << dest.url();
305 KonqOperations * op = new KonqOperations(parent);
306 KIO::CopyJob* job = KIO::pasteMimeSource( ev->mimeData(), dest,
307 i18n( "File name for dropped contents:" ),
308 parent );
309 if ( job ) // 0 if canceled by user
311 op->setOperation( job, COPY, job->destUrl() );
312 KIO::FileUndoManager::self()->recordJob( KIO::FileUndoManager::Copy, KUrl::List(), dest, job );
314 ev->acceptProposedAction();
318 void KonqOperations::asyncDrop( const KFileItem & destItem )
320 assert(m_info); // setDropInfo should have been called before asyncDrop
321 bool m_destIsLocal = false;
322 m_destUrl = destItem.mostLocalUrl(m_destIsLocal); // #168154
324 //kDebug(1203) << "KonqOperations::asyncDrop destItem->mode=" << destItem->mode() << " url=" << m_destUrl;
325 // Check what the destination is
326 if ( destItem.isDir() )
328 doDropFileCopy();
329 return;
331 if ( !m_destIsLocal )
333 // We dropped onto a remote URL that is not a directory!
334 // (e.g. an HTTP link in the sidebar).
335 // Can't do that, but we can't prevent it before stating the dest....
336 kWarning(1203) << "Cannot drop onto " << m_destUrl ;
337 deleteLater();
338 return;
340 if ( destItem.isDesktopFile() )
342 // Local .desktop file. What type ?
343 KDesktopFile desktopFile( m_destUrl.path() );
344 KConfigGroup desktopGroup = desktopFile.desktopGroup();
345 if ( desktopFile.hasApplicationType() )
347 QString error;
348 const QStringList urlStrList = m_info->urls.toStringList();
349 if ( KToolInvocation::startServiceByDesktopPath( m_destUrl.path(), urlStrList, &error ) > 0 )
350 KMessageBox::error( parentWidget(), error );
352 else
354 // Device or Link -> adjust dest
355 if ( desktopFile.hasDeviceType() && desktopGroup.hasKey("MountPoint") ) {
356 QString point = desktopGroup.readEntry( "MountPoint" );
357 m_destUrl.setPath( point );
358 QString dev = desktopFile.readDevice();
359 KMountPoint::Ptr mp = KMountPoint::currentMountPoints().findByDevice( dev );
360 // Is the device already mounted ?
361 if ( mp ) {
362 doDropFileCopy();
364 #ifndef Q_WS_WIN
365 else
367 const bool ro = desktopGroup.readEntry( "ReadOnly", false );
368 const QByteArray fstype = desktopGroup.readEntry( "FSType" ).toLatin1();
369 KAutoMount* am = new KAutoMount( ro, fstype, dev, point, m_destUrl.path(), false );
370 connect( am, SIGNAL( finished() ), this, SLOT( doDropFileCopy() ) );
372 #endif
373 return;
375 else if ( desktopFile.hasLinkType() && desktopGroup.hasKey("URL") ) {
376 m_destUrl = desktopGroup.readPathEntry("URL", QString());
377 doDropFileCopy();
378 return;
380 // else, well: mimetype, service, servicetype or .directory. Can't really drop anything on those.
383 else
385 // Should be a local executable
386 // (If this fails, there is a bug in KFileItem::acceptsDrops / KDirModel::flags)
387 kDebug(1203) << "KonqOperations::doDrop " << m_destUrl.path() << "should be an executable";
388 Q_ASSERT ( access( QFile::encodeName(m_destUrl.path()), X_OK ) == 0 );
389 // Launch executable for each of the files
390 QStringList args;
391 const KUrl::List lst = m_info->urls;
392 KUrl::List::ConstIterator it = lst.begin();
393 for ( ; it != lst.end() ; it++ )
394 args << (*it).path(); // assume local files
395 kDebug(1203) << "starting " << m_destUrl.path() << " with " << lst.count() << " arguments";
396 KProcess::startDetached( m_destUrl.path(), args );
398 deleteLater();
401 void KonqOperations::doDropFileCopy()
403 assert(m_info); // setDropInfo - and asyncDrop - should have been called before asyncDrop
404 const KUrl::List lst = m_info->urls;
405 Qt::DropAction action = m_info->action;
406 bool isDesktopFile = false;
407 bool itemIsOnDesktop = false;
408 bool allItemsAreFromTrash = true;
409 KUrl::List mlst; // list of items that can be moved
410 for (KUrl::List::ConstIterator it = lst.begin(); it != lst.end(); ++it)
412 bool local = (*it).isLocalFile();
413 if ( KProtocolManager::supportsDeleting( *it ) && (!local || QFileInfo((*it).directory()).isWritable() ))
414 mlst.append(*it);
415 if ( local && KDesktopFile::isDesktopFile((*it).path()))
416 isDesktopFile = true;
417 if ( local && (*it).path().startsWith(KGlobalSettings::desktopPath()))
418 itemIsOnDesktop = true;
419 if ( local || (*it).protocol() != "trash" )
420 allItemsAreFromTrash = false;
423 bool linkOnly = false;
424 if (isDesktopFile && !KAuthorized::authorizeKAction("run_desktop_files") &&
425 (m_destUrl.path( KUrl::AddTrailingSlash ) == KGlobalSettings::desktopPath()) )
427 linkOnly = true;
430 if ( !mlst.isEmpty() && m_destUrl.protocol() == "trash" )
432 if ( itemIsOnDesktop && !KAuthorized::authorizeKAction("editable_desktop_icons") )
434 deleteLater();
435 return;
438 m_method = TRASH;
439 if ( askDeleteConfirmation( mlst, TRASH, DEFAULT_CONFIRMATION, parentWidget() ) )
440 action = Qt::MoveAction;
441 else
443 deleteLater();
444 return;
447 else if ( allItemsAreFromTrash || m_destUrl.protocol() == "trash" ) {
448 // No point in asking copy/move/link when using dnd from or to the trash.
449 action = Qt::MoveAction;
451 else if ( (
452 ((m_info->keyboardModifiers & Qt::ControlModifier) == 0) &&
453 ((m_info->keyboardModifiers & Qt::ShiftModifier) == 0) &&
454 ((m_info->keyboardModifiers & Qt::AltModifier) == 0) ) || linkOnly )
456 // Neither control, shift or alt are pressed => show popup menu
458 // TODO move this code out somehow. Allow user of KonqOperations to add his own actions...
459 #if 0
460 KonqIconViewWidget *iconView = dynamic_cast<KonqIconViewWidget*>(parent());
461 bool bSetWallpaper = false;
462 if ( iconView && iconView->maySetWallpaper() && lst.count() == 1 )
464 KUrl url = lst.first();
465 KMimeType::Ptr mime = KMimeType::findByUrl( url );
466 if ( mime && ( ( KImageIO::isSupported(mime->name(), KImageIO::Reading) ) ||
467 mime->is( "image/svg+xml" ) ) )
469 bSetWallpaper = true;
472 #endif
474 // Check what the source can do
475 const KUrl url = lst.first(); // we'll assume it's the same for all URLs (hack)
476 bool sReading = KProtocolManager::supportsReading( url );
477 bool sDeleting = KProtocolManager::supportsDeleting( url );
478 bool sMoving = KProtocolManager::supportsMoving( url );
479 // Check what the destination can do
480 bool dWriting = KProtocolManager::supportsWriting( m_destUrl );
481 if ( !dWriting )
483 deleteLater();
484 return;
487 // We don't want to offer "move" for temp files. They might come from
488 // kmail using a tempfile for attachments, or ark using a tempdir for
489 // extracting an archive -- in all cases, we can't implement a real move,
490 // it's just a copy of the tempfile [and the source app will delete it later].
491 // https://www.intevation.de/roundup/kolab/issue2026
492 if (url.isLocalFile() && url.path().startsWith(KStandardDirs::locateLocal("tmp", QString()))) {
493 sMoving = false;
494 sDeleting = false;
497 QMenu popup;
498 QString seq = QKeySequence( Qt::ShiftModifier ).toString();
499 seq.chop(1); // chop superfluous '+'
500 QAction* popupMoveAction = new QAction(i18n( "&Move Here" ) + '\t' + seq, this);
501 popupMoveAction->setIcon(KIcon("go-jump"));
502 seq = QKeySequence( Qt::ControlModifier ).toString();
503 seq.chop(1);
504 QAction* popupCopyAction = new QAction(i18n( "&Copy Here" ) + '\t' + seq, this);
505 popupCopyAction->setIcon(KIcon("edit-copy"));
506 seq = QKeySequence( Qt::ControlModifier + Qt::ShiftModifier ).toString();
507 seq.chop(1);
508 QAction* popupLinkAction = new QAction(i18n( "&Link Here" ) + '\t' + seq, this);
509 popupLinkAction->setIcon(KIcon("edit-link"));
510 QAction* popupWallAction = new QAction( i18n( "Set as &Wallpaper" ), this );
511 popupWallAction->setIcon(KIcon("preferences-desktop-wallpaper"));
512 QAction* popupCancelAction = new QAction(i18n( "C&ancel" ) + '\t' + QKeySequence( Qt::Key_Escape ).toString(), this);
513 popupCancelAction->setIcon(KIcon("process-stop"));
515 if (!mlst.isEmpty() && (sMoving || (sReading && sDeleting)) && !linkOnly )
517 bool equalDestination = true;
518 foreach ( const KUrl & src, lst )
520 const bool equalProtocol = ( m_destUrl.protocol() == src.protocol() );
521 if ( !equalProtocol || m_destUrl.path(KUrl::RemoveTrailingSlash) != src.directory() )
523 equalDestination = false;
524 break;
528 if ( !equalDestination )
529 popup.addAction(popupMoveAction);
532 if ( sReading && !linkOnly)
533 popup.addAction(popupCopyAction);
535 popup.addAction(popupLinkAction);
537 #if 0
538 if (bSetWallpaper)
539 popup.addAction(popupWallAction);
540 #endif
542 popup.addSeparator();
543 popup.addAction(popupCancelAction);
545 QAction* result = popup.exec( m_info->mousePos );
547 if(result == popupCopyAction)
548 action = Qt::CopyAction;
549 else if(result == popupMoveAction)
550 action = Qt::MoveAction;
551 else if(result == popupLinkAction)
552 action = Qt::LinkAction;
553 else if(result == popupCancelAction || !result)
555 deleteLater();
556 return;
560 KIO::CopyJob * job = 0;
561 switch ( action ) {
562 case Qt::MoveAction :
563 job = KIO::move( lst, m_destUrl );
564 job->setMetaData( m_info->metaData );
565 setOperation( job, m_method == TRASH ? TRASH : MOVE, m_destUrl );
566 KIO::FileUndoManager::self()->recordJob(
567 m_method == TRASH ? KIO::FileUndoManager::Trash : KIO::FileUndoManager::Move,
568 lst, m_destUrl, job );
569 return; // we still have stuff to do -> don't delete ourselves
570 case Qt::CopyAction :
571 job = KIO::copy( lst, m_destUrl );
572 job->setMetaData( m_info->metaData );
573 setOperation( job, COPY, m_destUrl );
574 KIO::FileUndoManager::self()->recordCopyJob(job);
575 return;
576 case Qt::LinkAction :
577 kDebug(1203) << "KonqOperations::asyncDrop lst.count=" << lst.count();
578 job = KIO::link( lst, m_destUrl );
579 job->setMetaData( m_info->metaData );
580 setOperation( job, LINK, m_destUrl );
581 KIO::FileUndoManager::self()->recordCopyJob(job);
582 return;
583 default : kError(1203) << "Unknown action " << (int)action << endl;
585 deleteLater();
588 void KonqOperations::rename( QWidget * parent, const KUrl & oldurl, const KUrl& newurl )
590 kDebug(1203) << "KonqOperations::rename oldurl=" << oldurl << " newurl=" << newurl;
591 if ( oldurl == newurl )
592 return;
594 KUrl::List lst;
595 lst.append(oldurl);
596 KIO::Job * job = KIO::moveAs( oldurl, newurl, oldurl.isLocalFile() ? KIO::HideProgressInfo : KIO::DefaultFlags );
597 KonqOperations * op = new KonqOperations( parent );
598 op->setOperation( job, MOVE, newurl );
599 KIO::FileUndoManager::self()->recordJob( KIO::FileUndoManager::Rename, lst, newurl, job );
600 // if moving the desktop then update config file and emit
601 if ( oldurl.isLocalFile() && oldurl.path( KUrl::AddTrailingSlash ) == KGlobalSettings::desktopPath() )
603 kDebug(1203) << "That rename was the Desktop path, updating config files";
604 KSharedConfig::Ptr globalConfig = KGlobal::config();
605 KConfigGroup cgs( globalConfig, "Paths" );
606 cgs.writePathEntry("Desktop" , newurl.path(), KConfigBase::Persistent|KConfigBase::Global );
607 cgs.sync();
608 KGlobalSettings::self()->emitChange(KGlobalSettings::SettingsChanged, KGlobalSettings::SETTINGS_PATHS);
612 void KonqOperations::setOperation( KIO::Job * job, Operation method, const KUrl & dest )
614 m_method = method;
615 m_destUrl = dest;
616 if ( job )
618 job->ui()->setWindow(parentWidget());
619 connect( job, SIGNAL( result( KJob * ) ),
620 SLOT( slotResult( KJob * ) ) );
621 #if 0
622 KIO::CopyJob *copyJob = dynamic_cast<KIO::CopyJob*>(job);
623 KonqIconViewWidget *iconView = dynamic_cast<KonqIconViewWidget*>(parent());
624 if (copyJob && iconView)
626 connect(copyJob, SIGNAL(aboutToCreate(KIO::Job *,const QList<KIO::CopyInfo> &)),
627 this, SLOT(slotAboutToCreate(KIO::Job *,const QList<KIO::CopyInfo> &)));
628 // TODO move this connect into the iconview!
629 connect(this, SIGNAL(aboutToCreate(const QPoint &, const QList<KIO::CopyInfo> &)),
630 iconView, SLOT(slotAboutToCreate(const QPoint &, const QList<KIO::CopyInfo> &)));
632 #endif
634 else // for link
635 slotResult( 0L );
638 void KonqOperations::slotAboutToCreate(KIO::Job *, const QList<KIO::CopyInfo> &files)
640 emit aboutToCreate( m_info ? m_info->mousePos : m_pasteInfo ? m_pasteInfo->mousePos : QPoint(), files);
643 void KonqOperations::statUrl( const KUrl & url, const QObject *receiver, const char *member, QWidget* parent )
645 KonqOperations * op = new KonqOperations( parent );
646 op->m_method = STAT;
647 op->_statUrl( url, receiver, member );
650 void KonqOperations::_statUrl( const KUrl & url, const QObject *receiver, const char *member )
652 connect( this, SIGNAL( statFinished( const KFileItem & ) ), receiver, member );
653 KIO::StatJob * job = KIO::stat( url /*, KIO::HideProgressInfo?*/ );
654 job->ui()->setWindow(parentWidget());
655 connect( job, SIGNAL( result( KJob * ) ),
656 SLOT( slotStatResult( KJob * ) ) );
659 void KonqOperations::slotStatResult( KJob * job )
661 if ( job->error())
663 static_cast<KIO::Job*>( job )->ui()->showErrorMessage();
665 else
667 KIO::StatJob * statJob = static_cast<KIO::StatJob*>(job);
668 KFileItem item( statJob->statResult(), statJob->url() );
669 emit statFinished( item );
671 // If we're only here for a stat, we're done. But not if we used _statUrl internally
672 if ( m_method == STAT )
673 deleteLater();
676 void KonqOperations::slotResult( KJob * job )
678 if (job && job->error())
680 static_cast<KIO::Job*>( job )->ui()->showErrorMessage();
682 if ( m_method == EMPTYTRASH ) {
683 // Update konq windows opened on trash:/
684 org::kde::KDirNotify::emitFilesAdded( "trash:/" ); // yeah, files were removed, but we don't know which ones...
686 deleteLater();
689 void KonqOperations::rename( QWidget * parent, const KUrl & oldurl, const QString & name )
691 KUrl newurl( oldurl );
692 newurl.setPath( oldurl.directory( KUrl::AppendTrailingSlash ) + name );
693 kDebug(1203) << "KonqOperations::rename("<<name<<") called. newurl=" << newurl;
694 rename( parent, oldurl, newurl );
697 KIO::SimpleJob* KonqOperations::newDir( QWidget * parent, const KUrl & baseUrl )
699 bool ok;
700 QString name = i18n( "New Folder" );
701 if ( baseUrl.isLocalFile() && QFileInfo( baseUrl.path( KUrl::AddTrailingSlash ) + name ).exists() )
702 name = KIO::RenameDialog::suggestName( baseUrl, i18n( "New Folder" ) );
704 name = KInputDialog::getText ( i18n( "New Folder" ),
705 i18n( "Enter folder name:" ), name, &ok, parent );
706 if ( ok && !name.isEmpty() )
708 KUrl url;
709 if ((name[0] == '/') || (name[0] == '~'))
711 url.setPath(KShell::tildeExpand(name));
713 else
715 name = KIO::encodeFileName( name );
716 url = baseUrl;
717 url.addPath( name );
719 return KonqOperations::mkdir( parent, url );
721 return 0;
724 ////
726 KonqMultiRestoreJob::KonqMultiRestoreJob( const KUrl::List& urls )
727 : KIO::Job(),
728 m_urls( urls ), m_urlsIterator( m_urls.begin() ),
729 m_progress( 0 )
731 QTimer::singleShot(0, this, SLOT(slotStart()));
732 setUiDelegate(new KIO::JobUiDelegate);
735 void KonqMultiRestoreJob::slotStart()
737 if ( m_urlsIterator == m_urls.begin() ) // first time: emit total
738 setTotalAmount( KJob::Files, m_urls.count() );
740 if ( m_urlsIterator != m_urls.end() )
742 const KUrl& url = *m_urlsIterator;
744 KUrl new_url = url;
745 if ( new_url.protocol()=="system"
746 && new_url.path().startsWith("/trash") )
748 QString path = new_url.path();
749 path.remove(0, 6);
750 new_url.setProtocol("trash");
751 new_url.setPath(path);
754 Q_ASSERT( new_url.protocol() == "trash" );
755 QByteArray packedArgs;
756 QDataStream stream( &packedArgs, QIODevice::WriteOnly );
757 stream << (int)3 << new_url;
758 KIO::Job* job = KIO::special( new_url, packedArgs, KIO::HideProgressInfo );
759 addSubjob( job );
760 setProcessedAmount(KJob::Files, processedAmount(KJob::Files) + 1);
762 else // done!
764 org::kde::KDirNotify::emitFilesRemoved(m_urls.toStringList() );
765 emitResult();
769 void KonqMultiRestoreJob::slotResult( KJob *job )
771 if ( job->error() )
773 KIO::Job::slotResult( job ); // will set the error and emit result(this)
774 return;
776 removeSubjob(job);
777 // Move on to next one
778 ++m_urlsIterator;
779 ++m_progress;
780 //emit processedSize( this, m_progress );
781 emitPercent( m_progress, m_urls.count() );
782 slotStart();
785 QWidget* KonqOperations::parentWidget() const
787 return static_cast<QWidget *>( parent() );
790 #include "konq_operations.moc"