19 #include <tqclipboard.h>
20 #include "konq_operations.h"
22 #include <kautomount.h>
23 #include <kinputdialog.h>
25 #include <kmessagebox.h>
26 #include <knotifyclient.h>
29 #include <kshortcut.h>
31 #include <kdirnotify_stub.h>
33 #include <dcopclient.h>
34 #include "konq_undo.h"
35 #include "konq_defaults.h"
36 #include "konqbookmarkmanager.h"
41 #include <kapplication.h>
44 #include <kfileitem.h>
45 #include <kdesktopfile.h>
47 #include <kglobalsettings.h>
50 #include <kio/jobclasses.h>
51 #include <kio/paste.h>
52 #include <kio/netaccess.h>
53 #include <kio/renamedlg.h>
54 #include <konq_drag.h>
55 #include <konq_iconviewwidget.h>
56 #include <kprotocolinfo.h>
58 #include <kstringhandler.h>
59 #include <tqpopupmenu.h>
63 KBookmarkManager * KonqBookmarkManager::s_bookmarkManager;
65 KonqOperations::KonqOperations( TQWidget *parent )
66 : TQObject( parent,
"KonqOperations" ),
67 m_method( UNKNOWN ), m_info(0L), m_pasteInfo(0L)
71 KonqOperations::~KonqOperations()
79 TQString keditfiletype = TQString::fromLatin1(
"keditfiletype");
80 KRun::runCommand( keditfiletype +
" " + KProcess::quote(mimeType),
81 keditfiletype, keditfiletype );
86 kdDebug(1203) <<
"KonqOperations::del " << parent->className() << endl;
87 if ( selectedURLs.isEmpty() )
89 kdWarning(1203) <<
"Empty URL list !" << endl;
94 ConfirmationType confirmation = DEFAULT_CONFIRMATION;
95 op->_del( method, selectedURLs, confirmation );
98 void KonqOperations::emptyTrash()
101 op->_del( EMPTYTRASH, KURL(
"trash:/"), SKIP_CONFIRMATION );
104 void KonqOperations::restoreTrashedItems(
const KURL::List& urls )
107 op->_restoreTrashedItems( urls );
114 op->setOperation( job, MKDIR, KURL::List(), url );
115 (void)
new KonqCommandRecorder( KonqCommand::MKDIR, KURL(), url, job );
120 doPaste(parent, destURL, TQPoint());
127 TQMimeSource *data = TQApplication::clipboard()->data();
128 if ( data->provides(
"application/x-kde-cutselection" ) ) {
129 move = KonqDrag::decodeIsCutSelection( data );
130 kdDebug(1203) <<
"move (from clipboard data) = " << move << endl;
133 KIO::Job *job = KIO::pasteClipboard( destURL, move );
137 KIO::CopyJob * copyJob =
static_cast<KIO::CopyJob *
>(job);
138 KIOPasteInfo * pi =
new KIOPasteInfo;
140 op->setPasteInfo( pi );
141 op->setOperation( job, move ? MOVE : COPY, copyJob->srcURLs(), copyJob->destURL() );
142 (void)
new KonqCommandRecorder( move ? KonqCommand::MOVE : KonqCommand::COPY, KURL::List(), destURL, job );
146 void KonqOperations::copy( TQWidget * parent,
int method,
const KURL::List & selectedURLs,
const KURL& destUrl )
148 kdDebug(1203) <<
"KonqOperations::copy() " << parent->className() << endl;
149 if ((method!=COPY) && (method!=MOVE) && (method!=LINK))
151 kdWarning(1203) <<
"Illegal copy method !" << endl;
154 if ( selectedURLs.isEmpty() )
156 kdWarning(1203) <<
"Empty URL list !" << endl;
163 job= KIO::link( selectedURLs, destUrl);
164 else if (method==MOVE)
165 job= KIO::move( selectedURLs, destUrl);
169 op->setOperation( job, method, selectedURLs, destUrl );
172 (void)
new KonqCommandRecorder( KonqCommand::COPY, selectedURLs, destUrl, job );
174 (
void)
new KonqCommandRecorder( method==MOVE?KonqCommand::MOVE:KonqCommand::LINK, selectedURLs, destUrl, job );
177 void KonqOperations::_del(
int method,
const KURL::List & _selectedURLs, ConfirmationType confirmation )
179 KURL::List selectedURLs;
180 for (KURL::List::ConstIterator it = _selectedURLs.begin(); it != _selectedURLs.end(); ++it)
181 if (KProtocolInfo::supportsDeleting(*it))
182 selectedURLs.append(*it);
183 if (selectedURLs.isEmpty()) {
197 job = KIO::trash( selectedURLs );
198 (void)
new KonqCommandRecorder( KonqCommand::TRASH, selectedURLs,
"trash:/", job );
204 TQByteArray packedArgs;
205 TQDataStream stream( packedArgs, IO_WriteOnly );
207 job = KIO::special(
"trash:/", packedArgs );
208 KNotifyClient::event(0,
"Trash: emptied");
215 job =
KIO::del( selectedURLs,
true );
218 kdWarning() <<
"Unknown operation: " << method << endl;
222 connect( job, TQT_SIGNAL( result( KIO::Job * ) ),
223 TQT_SLOT( slotResult( KIO::Job * ) ) );
228 void KonqOperations::_restoreTrashedItems(
const KURL::List& urls )
232 connect( job, TQT_SIGNAL( result( KIO::Job * ) ),
233 TQT_SLOT( slotResult( KIO::Job * ) ) );
238 if ( confirmation == SKIP_CONFIRMATION )
241 bool ask = ( confirmation == FORCE_CONFIRMATION );
244 KConfig config(
"konquerorrc",
true,
false);
245 config.setGroup(
"Trash" );
246 keyName = ( method == DEL ?
"ConfirmDelete" : method == SHRED ?
"ConfirmShred" :
"ConfirmTrash" );
247 bool defaultValue = ( method == DEL ? DEFAULT_CONFIRMDELETE : method == SHRED ? DEFAULT_CONFIRMSHRED : DEFAULT_CONFIRMTRASH );
248 ask = config.readBoolEntry( keyName, defaultValue );
252 KURL::List::ConstIterator it = selectedURLs.begin();
253 TQStringList prettyList;
254 for ( ; it != selectedURLs.end(); ++it ) {
255 if ( (*it).protocol() ==
"trash" ) {
256 TQString path = (*it).path();
259 prettyList.append( path.remove(TQRegExp(
"^/[0-9]*-")) );
261 prettyList.append( (*it).pathOrURL() );
268 result = KMessageBox::warningContinueCancelList( widget,
269 i18n(
"Do you really want to delete this item?",
"Do you really want to delete these %n items?", prettyList.count()),
271 i18n(
"Delete Files" ),
273 keyName, KMessageBox::Dangerous);
277 result = KMessageBox::warningContinueCancelList( widget,
278 i18n(
"Do you really want to shred this item?",
"Do you really want to shred these %n items?", prettyList.count()),
280 i18n(
"Shred Files" ),
281 KGuiItem( i18n(
"Shred" ),
"editshred" ),
282 keyName, KMessageBox::Dangerous);
287 result = KMessageBox::warningContinueCancelList( widget,
288 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()),
290 i18n(
"Move to Trash" ),
291 KGuiItem( i18n(
"Verb",
"&Trash" ),
"edittrash"),
292 keyName, KMessageBox::Dangerous);
294 if (!keyName.isEmpty())
297 KConfig *config = kapp->config();
298 KConfigGroupSaver saver(config,
"Notification Messages");
299 if (!config->readBoolEntry(keyName,
true))
301 config->writeEntry(keyName,
true);
303 KConfig konq_config(
"konquerorrc",
false);
304 konq_config.setGroup(
"Trash" );
305 konq_config.writeEntry( keyName,
false );
308 return (result == KMessageBox::Continue);
315 kdDebug(1203) <<
"doDrop: dest : " << dest.url() << endl;
317 TQMap<TQString, TQString> metaData;
318 if ( KURLDrag::decode( ev, lst, metaData ) )
320 if( lst.count() == 0 )
322 kdWarning(1203) <<
"Oooops, no data ...." << endl;
326 kdDebug(1203) <<
"KonqOperations::doDrop metaData: " << metaData.count() <<
" entries." << endl;
327 TQMap<TQString,TQString>::ConstIterator mit;
328 for( mit = metaData.begin(); mit != metaData.end(); ++mit )
330 kdDebug(1203) <<
"metaData: key=" << mit.key() <<
" value=" << mit.data() << endl;
333 KURL::List::Iterator it = lst.begin();
334 for ( ; it != lst.end() ; it++ )
336 kdDebug(1203) <<
"URL : " << (*it).url() << endl;
337 if ( dest.equals( *it,
true ) )
341 if ( !ev->source() || ev->source() != parent && ev->source()->parent() != parent )
342 KMessageBox::sorry( parent, i18n(
"You cannot drop a folder on to itself") );
343 kdDebug(1203) <<
"Dropped on itself" << endl;
352 int root_x, root_y, win_x, win_y;
354 XQueryPointer( qt_xdisplay(), qt_xrootwin(), &root, &child,
355 &root_x, &root_y, &win_x, &win_y, &keybstate );
357 TQDropEvent::Action action = ev->action();
359 if ( ev->provides(
"application/x-xbel") )
361 keybstate |= ControlMask | ShiftMask;
362 action = TQDropEvent::Link;
363 kdDebug(1203) <<
"KonqOperations::doDrop Bookmark -> emulating Link" << endl;
367 op->setDropInfo(
new DropInfo( keybstate, lst, metaData, win_x, win_y, action ) );
372 op->asyncDrop( destItem );
377 op->_statURL( dest, op, TQT_SLOT( asyncDrop(
const KFileItem * ) ) );
387 KIO::CopyJob* job = KIO::pasteMimeSource( ev, dest,
388 i18n(
"File name for dropped contents:" ),
392 op->setOperation( job, COPY, KURL::List(), job->destURL() );
393 (void)
new KonqCommandRecorder( KonqCommand::COPY, KURL::List(), dest, job );
399 void KonqOperations::asyncDrop(
const KFileItem * destItem )
402 m_destURL = destItem->url();
406 if ( destItem->isDir() )
411 if ( !m_destURL.isLocalFile() )
416 kdWarning(1203) <<
"Cannot drop onto " << m_destURL << endl;
420 if ( (destItem->mimetype() ==
"application/x-desktop")
421 || (destItem->mimetype() ==
"media/builtin-mydocuments")
422 || (destItem->mimetype() ==
"media/builtin-mycomputer")
423 || (destItem->mimetype() ==
"media/builtin-mynetworkplaces")
424 || (destItem->mimetype() ==
"media/builtin-printers")
425 || (destItem->mimetype() ==
"media/builtin-trash")
426 || (destItem->mimetype() ==
"media/builtin-webbrowser") )
429 KDesktopFile desktopFile( m_destURL.path() );
430 if ( desktopFile.hasApplicationType() )
433 TQStringList stringList;
434 KURL::List lst = m_info->lst;
435 KURL::List::Iterator it = lst.begin();
436 for ( ; it != lst.end() ; it++ )
438 stringList.append((*it).url());
440 if ( KApplication::startServiceByDesktopPath( m_destURL.path(), stringList, &error ) > 0 )
441 KMessageBox::error( 0L, error );
446 if ( desktopFile.hasDeviceType() && desktopFile.hasKey(
"MountPoint") ) {
447 TQString point = desktopFile.readEntry(
"MountPoint" );
448 m_destURL.setPath( point );
449 TQString dev = desktopFile.readDevice();
450 TQString mp = KIO::findDeviceMountPoint( dev );
456 bool ro = desktopFile.readBoolEntry(
"ReadOnly",
false );
457 TQString fstype = desktopFile.readEntry(
"FSType" );
458 KAutoMount* am =
new KAutoMount( ro, fstype, dev, point, m_destURL.path(), false );
459 connect( am, TQT_SIGNAL( finished() ),
this, TQT_SLOT( doFileCopy() ) );
463 else if ( desktopFile.hasLinkType() && desktopFile.hasKey(
"URL") ) {
464 m_destURL = desktopFile.readPathEntry(
"URL");
475 kdDebug(1203) <<
"KonqOperations::doDrop " << m_destURL.path() <<
"should be an executable" << endl;
476 Q_ASSERT ( access( TQFile::encodeName(m_destURL.path()), X_OK ) == 0 );
478 proc << m_destURL.path() ;
480 KURL::List lst = m_info->lst;
481 KURL::List::Iterator it = lst.begin();
482 for ( ; it != lst.end() ; it++ )
483 proc << (*it).path();
484 kdDebug(1203) <<
"starting " << m_destURL.path() <<
" with " << lst.count() <<
" arguments" << endl;
485 proc.start( KProcess::DontCare );
490 void KonqOperations::doFileCopy()
493 KURL::List lst = m_info->lst;
494 TQDropEvent::Action action = m_info->action;
495 bool isDesktopFile =
false;
496 bool itemIsOnDesktop =
false;
497 bool allItemsAreFromTrash =
true;
499 for (KURL::List::ConstIterator it = lst.begin(); it != lst.end(); ++it)
501 bool local = (*it).isLocalFile();
502 if ( KProtocolInfo::supportsDeleting( *it ) && (!local || TQFileInfo((*it).directory()).isWritable() ))
504 if ( local && KDesktopFile::isDesktopFile((*it).path()))
505 isDesktopFile =
true;
506 if ( local && (*it).path().startsWith(KGlobalSettings::desktopPath()))
507 itemIsOnDesktop =
true;
508 if ( local || (*it).protocol() !=
"trash" )
509 allItemsAreFromTrash =
false;
512 bool linkOnly =
false;
513 if (isDesktopFile && !kapp->authorize(
"run_desktop_files") &&
514 (m_destURL.path(1) == KGlobalSettings::desktopPath()) )
519 if ( !mlst.isEmpty() && m_destURL.protocol() ==
"trash" )
521 if ( itemIsOnDesktop && !kapp->authorize(
"editable_desktop_icons") )
529 action = TQDropEvent::Move;
536 else if ( allItemsAreFromTrash || m_destURL.protocol() ==
"trash" ) {
538 action = TQDropEvent::Move;
540 else if ( (((m_info->keybstate & ControlMask) == 0) && ((m_info->keybstate & ShiftMask) == 0)) ||
545 bool bSetWallpaper =
false;
546 if ( iconView && iconView->maySetWallpaper() && lst.count() == 1 )
548 KURL url = lst.first();
549 KMimeType::Ptr mime = KMimeType::findByURL( url );
550 if ( ( !KImageIO::type(url.path()).isEmpty() ) ||
551 ( KImageIO::isSupported(mime->name(), KImageIO::Reading) ) ||
552 mime->is(
"image/svg+xml" ) )
554 bSetWallpaper =
true;
559 KURL url = lst.first();
560 bool sReading = KProtocolInfo::supportsReading( url );
561 bool sDeleting = KProtocolInfo::supportsDeleting( url );
562 bool sMoving = KProtocolInfo::supportsMoving( url );
564 bool dWriting = KProtocolInfo::supportsWriting( m_destURL );
572 if (!mlst.isEmpty() && (sMoving || (sReading && sDeleting)) && !linkOnly )
573 popup.insertItem(SmallIconSet(
"goto"), i18n(
"&Move Here" ) +
"\t" + KKey::modFlagLabel( KKey::SHIFT ), 2 );
574 if ( sReading && !linkOnly)
575 popup.insertItem(SmallIconSet(
"editcopy"), i18n(
"&Copy Here" ) +
"\t" + KKey::modFlagLabel( KKey::CTRL ), 1 );
576 popup.insertItem(SmallIconSet(
"www"), i18n(
"&Link Here" ) +
"\t" + KKey::modFlagLabel( (KKey::ModFlag)( KKey::CTRL|KKey::SHIFT ) ), 3 );
578 popup.insertItem(SmallIconSet(
"background"), i18n(
"Set as &Wallpaper" ), 4 );
579 popup.insertSeparator();
580 popup.insertItem(SmallIconSet(
"cancel"), i18n(
"C&ancel" ) +
"\t" + KKey( Qt::Key_Escape ).toString(), 5);
582 int result = popup.exec( m_info->mousePos );
585 case 1 : action = TQDropEvent::Copy;
break;
586 case 2 : action = TQDropEvent::Move;
break;
587 case 3 : action = TQDropEvent::Link;
break;
590 kdDebug(1203) <<
"setWallpaper iconView=" << iconView <<
" url=" << lst.first().url() << endl;
591 if (iconView && iconView->isDesktop() ) iconView->
setWallpaper(lst.first());
596 default :
delete this;
return;
602 case TQDropEvent::Move :
603 job = KIO::move( lst, m_destURL );
604 job->setMetaData( m_info->metaData );
605 setOperation( job, m_method == TRASH ? TRASH : MOVE, lst, m_destURL );
606 (void)
new KonqCommandRecorder(
607 m_method == TRASH ? KonqCommand::TRASH : KonqCommand::MOVE,
608 lst, m_destURL, job );
610 case TQDropEvent::Copy :
612 job->setMetaData( m_info->metaData );
613 setOperation( job, COPY, lst, m_destURL );
614 (void)
new KonqCommandRecorder( KonqCommand::COPY, lst, m_destURL, job );
616 case TQDropEvent::Link :
617 kdDebug(1203) <<
"KonqOperations::asyncDrop lst.count=" << lst.count() << endl;
618 job = KIO::link( lst, m_destURL );
619 job->setMetaData( m_info->metaData );
620 setOperation( job, LINK, lst, m_destURL );
621 (void)
new KonqCommandRecorder( KonqCommand::LINK, lst, m_destURL, job );
623 default : kdError(1203) <<
"Unknown action " << (int)action << endl;
630 kdDebug(1203) <<
"KonqOperations::rename oldurl=" << oldurl <<
" newurl=" << newurl << endl;
631 if ( oldurl == newurl )
636 KIO::Job * job = KIO::moveAs( oldurl, newurl, !oldurl.isLocalFile() );
638 op->setOperation( job, MOVE, lst, newurl );
639 (void)
new KonqCommandRecorder( KonqCommand::MOVE, lst, newurl, job );
641 if ( oldurl.isLocalFile() && oldurl.path(1) == KGlobalSettings::desktopPath() )
643 kdDebug(1203) <<
"That rename was the Desktop path, updating config files" << endl;
644 KConfig *globalConfig = KGlobal::config();
645 KConfigGroupSaver cgs( globalConfig,
"Paths" );
646 globalConfig->writePathEntry(
"Desktop" , newurl.path(),
true, true );
647 globalConfig->sync();
648 KIPC::sendMessageAll(KIPC::SettingsChanged, KApplication::SETTINGS_PATHS);
652 void KonqOperations::setOperation( KIO::Job * job,
int method,
const KURL::List & ,
const KURL & dest )
659 connect( job, TQT_SIGNAL( result( KIO::Job * ) ),
660 TQT_SLOT( slotResult( KIO::Job * ) ) );
661 KIO::CopyJob *copyJob = tqt_dynamic_cast<KIO::CopyJob*>(job);
663 if (copyJob && iconView)
665 connect(copyJob, TQT_SIGNAL(aboutToCreate(KIO::Job *,
const TQValueList<KIO::CopyInfo> &)),
666 this, TQT_SLOT(slotAboutToCreate(KIO::Job *,
const TQValueList<KIO::CopyInfo> &)));
667 connect(
this, TQT_SIGNAL(aboutToCreate(
const TQPoint &,
const TQValueList<KIO::CopyInfo> &)),
668 iconView, TQT_SLOT(slotAboutToCreate(
const TQPoint &,
const TQValueList<KIO::CopyInfo> &)));
675 void KonqOperations::slotAboutToCreate(KIO::Job *,
const TQValueList<KIO::CopyInfo> &files)
677 emit aboutToCreate( m_info ? m_info->mousePos : m_pasteInfo ? m_pasteInfo->mousePos : TQPoint(), files);
683 op->_statURL( url, receiver, member );
687 void KonqOperations::_statURL(
const KURL & url,
const TQObject *receiver,
const char *member )
689 connect(
this, TQT_SIGNAL( statFinished(
const KFileItem * ) ), receiver, member );
690 KIO::StatJob * job = KIO::stat( url );
691 connect( job, TQT_SIGNAL( result( KIO::Job * ) ),
692 TQT_SLOT( slotStatResult( KIO::Job * ) ) );
695 void KonqOperations::slotStatResult( KIO::Job * job )
698 job->showErrorDialog( (TQWidget*)parent() );
701 KIO::StatJob * statJob =
static_cast<KIO::StatJob*
>(job);
702 KFileItem * item =
new KFileItem( statJob->statResult(), statJob->url() );
703 emit statFinished( item );
707 if ( m_method == STAT )
711 void KonqOperations::slotResult( KIO::Job * job )
713 if (job && job->error())
714 job->showErrorDialog( (TQWidget*)parent() );
715 if ( m_method == EMPTYTRASH ) {
717 KDirNotify_stub allDirNotify(
"*",
"KDirNotify*");
718 allDirNotify.FilesAdded(
"trash:/" );
725 KURL newurl( oldurl );
726 newurl.setPath( oldurl.directory(
false,
true) + name );
727 kdDebug(1203) <<
"KonqOperations::rename("<<name<<
") called. newurl=" << newurl << endl;
728 rename( parent, oldurl, newurl );
734 TQString name = i18n(
"New Folder" );
735 if ( baseURL.isLocalFile() && TQFileInfo( baseURL.path(+1) + name ).exists() )
736 name = KIO::RenameDlg::suggestName( baseURL, i18n(
"New Folder" ) );
738 name = KInputDialog::getText ( i18n(
"New Folder" ),
739 i18n(
"Enter folder name:" ), name, &ok, parent );
740 if ( ok && !name.isEmpty() )
743 if ((name[0] ==
'/') || (name[0] ==
'~'))
745 url.setPath(KShell::tildeExpand(name));
749 name = KIO::encodeFileName( name );
759 KonqMultiRestoreJob::KonqMultiRestoreJob(
const KURL::List& urls,
bool showProgressInfo )
760 : KIO::Job( showProgressInfo ),
761 m_urls( urls ), m_urlsIterator( m_urls.begin() ),
764 TQTimer::singleShot(0,
this, TQT_SLOT(slotStart()));
767 void KonqMultiRestoreJob::slotStart()
773 if ( m_urlsIterator != m_urls.end() )
775 const KURL& url = *m_urlsIterator;
778 if ( new_url.protocol()==
"system"
779 && new_url.path().startsWith(
"/trash") )
781 TQString path = new_url.path();
783 new_url.setProtocol(
"trash");
784 new_url.setPath(path);
787 Q_ASSERT( new_url.protocol() ==
"trash" );
788 TQByteArray packedArgs;
789 TQDataStream stream( packedArgs, IO_WriteOnly );
790 stream << (int)3 << new_url;
791 KIO::Job* job = KIO::special( new_url, packedArgs );
796 KDirNotify_stub allDirNotify(
"*",
"KDirNotify*");
797 allDirNotify.FilesRemoved( m_urls );
802 void KonqMultiRestoreJob::slotResult( KIO::Job *job )
806 KIO::Job::slotResult( job );
809 subjobs.remove( job );
814 emitPercent( m_progress, m_urls.count() );
818 TQWidget* KonqOperations::parentWidget()
const
820 return static_cast<TQWidget *
>( parent() );
823 #include "konq_operations.moc"