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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 00017 */ 00018 00019 #include <tqclipboard.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 <knotifyclient.h> 00027 #include <krun.h> 00028 #include <kshell.h> 00029 #include <kshortcut.h> 00030 00031 #include <kdirnotify_stub.h> 00032 00033 #include <dcopclient.h> 00034 #include "konq_undo.h" 00035 #include "konq_defaults.h" 00036 #include "konqbookmarkmanager.h" 00037 00038 // For doDrop 00039 #include <tqdir.h>//first 00040 #include <assert.h> 00041 #include <kapplication.h> 00042 #include <kipc.h> 00043 #include <kdebug.h> 00044 #include <kfileitem.h> 00045 #include <kdesktopfile.h> 00046 #include <kurldrag.h> 00047 #include <kglobalsettings.h> 00048 #include <kimageio.h> 00049 #include <kio/job.h> 00050 #include <kio/jobclasses.h> 00051 #include <kio/paste.h> 00052 #include <kio/netaccess.h> 00053 #include <kio/renamedlg.h> 00054 #include <konq_drag.h> 00055 #include <konq_iconviewwidget.h> 00056 #include <kprotocolinfo.h> 00057 #include <kprocess.h> 00058 #include <kstringhandler.h> 00059 #include <tqpopupmenu.h> 00060 #include <unistd.h> 00061 #include <X11/Xlib.h> 00062 00063 KBookmarkManager * KonqBookmarkManager::s_bookmarkManager; 00064 00065 KonqOperations::KonqOperations( TQWidget *parent ) 00066 : TQObject( parent, "KonqOperations" ), 00067 m_method( UNKNOWN ), m_info(0L), m_pasteInfo(0L) 00068 { 00069 } 00070 00071 KonqOperations::~KonqOperations() 00072 { 00073 delete m_info; 00074 delete m_pasteInfo; 00075 } 00076 00077 void KonqOperations::editMimeType( const TQString & mimeType ) 00078 { 00079 TQString keditfiletype = TQString::fromLatin1("keditfiletype"); 00080 KRun::runCommand( keditfiletype + " " + KProcess::quote(mimeType), 00081 keditfiletype, keditfiletype /*unused*/); 00082 } 00083 00084 void KonqOperations::del( TQWidget * parent, int method, const KURL::List & selectedURLs ) 00085 { 00086 kdDebug(1203) << "KonqOperations::del " << parent->className() << endl; 00087 if ( selectedURLs.isEmpty() ) 00088 { 00089 kdWarning(1203) << "Empty URL list !" << endl; 00090 return; 00091 } 00092 00093 KonqOperations * op = new KonqOperations( parent ); 00094 ConfirmationType confirmation = DEFAULT_CONFIRMATION; 00095 op->_del( method, selectedURLs, confirmation ); 00096 } 00097 00098 void KonqOperations::emptyTrash() 00099 { 00100 KonqOperations *op = new KonqOperations( 0L ); 00101 op->_del( EMPTYTRASH, KURL("trash:/"), SKIP_CONFIRMATION ); 00102 } 00103 00104 void KonqOperations::restoreTrashedItems( const KURL::List& urls ) 00105 { 00106 KonqOperations *op = new KonqOperations( 0L ); 00107 op->_restoreTrashedItems( urls ); 00108 } 00109 00110 void KonqOperations::mkdir( TQWidget *parent, const KURL & url ) 00111 { 00112 KIO::Job * job = KIO::mkdir( url ); 00113 KonqOperations * op = new KonqOperations( parent ); 00114 op->setOperation( job, MKDIR, KURL::List(), url ); 00115 (void) new KonqCommandRecorder( KonqCommand::MKDIR, KURL(), url, job ); // no support yet, apparently 00116 } 00117 00118 void KonqOperations::doPaste( TQWidget * parent, const KURL & destURL ) 00119 { 00120 doPaste(parent, destURL, TQPoint()); 00121 } 00122 00123 void KonqOperations::doPaste( TQWidget * parent, const KURL & destURL, const TQPoint &pos ) 00124 { 00125 // move or not move ? 00126 bool move = false; 00127 TQMimeSource *data = TQApplication::clipboard()->data(); 00128 if ( data->provides( "application/x-kde-cutselection" ) ) { 00129 move = KonqDrag::decodeIsCutSelection( data ); 00130 kdDebug(1203) << "move (from clipboard data) = " << move << endl; 00131 } 00132 00133 KIO::Job *job = KIO::pasteClipboard( destURL, move ); 00134 if ( job ) 00135 { 00136 KonqOperations * op = new KonqOperations( parent ); 00137 KIO::CopyJob * copyJob = static_cast<KIO::CopyJob *>(job); 00138 KIOPasteInfo * pi = new KIOPasteInfo; 00139 pi->mousePos = pos; 00140 op->setPasteInfo( pi ); 00141 op->setOperation( job, move ? MOVE : COPY, copyJob->srcURLs(), copyJob->destURL() ); 00142 (void) new KonqCommandRecorder( move ? KonqCommand::MOVE : KonqCommand::COPY, KURL::List(), destURL, job ); 00143 } 00144 } 00145 00146 void KonqOperations::copy( TQWidget * parent, int method, const KURL::List & selectedURLs, const KURL& destUrl ) 00147 { 00148 kdDebug(1203) << "KonqOperations::copy() " << parent->className() << endl; 00149 if ((method!=COPY) && (method!=MOVE) && (method!=LINK)) 00150 { 00151 kdWarning(1203) << "Illegal copy method !" << endl; 00152 return; 00153 } 00154 if ( selectedURLs.isEmpty() ) 00155 { 00156 kdWarning(1203) << "Empty URL list !" << endl; 00157 return; 00158 } 00159 00160 KonqOperations * op = new KonqOperations( parent ); 00161 KIO::Job* job(0); 00162 if (method==LINK) 00163 job= KIO::link( selectedURLs, destUrl); 00164 else if (method==MOVE) 00165 job= KIO::move( selectedURLs, destUrl); 00166 else 00167 job= KIO::copy( selectedURLs, destUrl); 00168 00169 op->setOperation( job, method, selectedURLs, destUrl ); 00170 00171 if (method==COPY) 00172 (void) new KonqCommandRecorder( KonqCommand::COPY, selectedURLs, destUrl, job ); 00173 else 00174 (void) new KonqCommandRecorder( method==MOVE?KonqCommand::MOVE:KonqCommand::LINK, selectedURLs, destUrl, job ); 00175 } 00176 00177 void KonqOperations::_del( int method, const KURL::List & _selectedURLs, ConfirmationType confirmation ) 00178 { 00179 KURL::List selectedURLs; 00180 for (KURL::List::ConstIterator it = _selectedURLs.begin(); it != _selectedURLs.end(); ++it) 00181 if (KProtocolInfo::supportsDeleting(*it)) 00182 selectedURLs.append(*it); 00183 if (selectedURLs.isEmpty()) { 00184 delete this; 00185 return; 00186 } 00187 00188 if ( askDeleteConfirmation( selectedURLs, method, confirmation, parentWidget() ) ) 00189 { 00190 //m_srcURLs = selectedURLs; 00191 KIO::Job *job; 00192 m_method = method; 00193 switch( method ) 00194 { 00195 case TRASH: 00196 { 00197 job = KIO::trash( selectedURLs ); 00198 (void) new KonqCommandRecorder( KonqCommand::TRASH, selectedURLs, "trash:/", job ); 00199 break; 00200 } 00201 case EMPTYTRASH: 00202 { 00203 // Same as in ktrash --empty 00204 TQByteArray packedArgs; 00205 TQDataStream stream( packedArgs, IO_WriteOnly ); 00206 stream << (int)1; 00207 job = KIO::special( "trash:/", packedArgs ); 00208 KNotifyClient::event(0, "Trash: emptied"); 00209 break; 00210 } 00211 case DEL: 00212 job = KIO::del( selectedURLs ); 00213 break; 00214 case SHRED: 00215 job = KIO::del( selectedURLs, true ); 00216 break; 00217 default: 00218 kdWarning() << "Unknown operation: " << method << endl; 00219 delete this; 00220 return; 00221 } 00222 connect( job, TQT_SIGNAL( result( KIO::Job * ) ), 00223 TQT_SLOT( slotResult( KIO::Job * ) ) ); 00224 } else 00225 delete this; 00226 } 00227 00228 void KonqOperations::_restoreTrashedItems( const KURL::List& urls ) 00229 { 00230 m_method = RESTORE; 00231 KonqMultiRestoreJob* job = new KonqMultiRestoreJob( urls, true ); 00232 connect( job, TQT_SIGNAL( result( KIO::Job * ) ), 00233 TQT_SLOT( slotResult( KIO::Job * ) ) ); 00234 } 00235 00236 bool KonqOperations::askDeleteConfirmation( const KURL::List & selectedURLs, int method, ConfirmationType confirmation, TQWidget* widget ) 00237 { 00238 if ( confirmation == SKIP_CONFIRMATION ) 00239 return true; 00240 TQString keyName; 00241 bool ask = ( confirmation == FORCE_CONFIRMATION ); 00242 if ( !ask ) 00243 { 00244 KConfig config("konquerorrc", true, false); 00245 config.setGroup( "Trash" ); 00246 keyName = ( method == DEL ? "ConfirmDelete" : method == SHRED ? "ConfirmShred" : "ConfirmTrash" ); 00247 bool defaultValue = ( method == DEL ? DEFAULT_CONFIRMDELETE : method == SHRED ? DEFAULT_CONFIRMSHRED : DEFAULT_CONFIRMTRASH ); 00248 ask = config.readBoolEntry( keyName, defaultValue ); 00249 } 00250 if ( ask ) 00251 { 00252 KURL::List::ConstIterator it = selectedURLs.begin(); 00253 TQStringList prettyList; 00254 for ( ; it != selectedURLs.end(); ++it ) { 00255 if ( (*it).protocol() == "trash" ) { 00256 TQString path = (*it).path(); 00257 // HACK (#98983): remove "0-foo". Note that it works better than 00258 // displaying KFileItem::name(), for files under a subdir. 00259 prettyList.append( path.remove(TQRegExp("^/[0-9]*-")) ); 00260 } else 00261 prettyList.append( (*it).pathOrURL() ); 00262 } 00263 00264 int result; 00265 switch(method) 00266 { 00267 case DEL: 00268 result = KMessageBox::warningContinueCancelList( widget, 00269 i18n( "Do you really want to delete this item?", "Do you really want to delete these %n items?", prettyList.count()), 00270 prettyList, 00271 i18n( "Delete Files" ), 00272 KStdGuiItem::del(), 00273 keyName, KMessageBox::Dangerous); 00274 break; 00275 00276 case SHRED: 00277 result = KMessageBox::warningContinueCancelList( widget, 00278 i18n( "Do you really want to shred this item?", "Do you really want to shred these %n items?", prettyList.count()), 00279 prettyList, 00280 i18n( "Shred Files" ), 00281 KGuiItem( i18n( "Shred" ), "editshred" ), 00282 keyName, KMessageBox::Dangerous); 00283 break; 00284 00285 case MOVE: 00286 default: 00287 result = KMessageBox::warningContinueCancelList( widget, 00288 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()), 00289 prettyList, 00290 i18n( "Move to Trash" ), 00291 KGuiItem( i18n( "Verb", "&Trash" ), "edittrash"), 00292 keyName, KMessageBox::Dangerous); 00293 } 00294 if (!keyName.isEmpty()) 00295 { 00296 // Check kmessagebox setting... erase & copy to konquerorrc. 00297 KConfig *config = kapp->config(); 00298 KConfigGroupSaver saver(config, "Notification Messages"); 00299 if (!config->readBoolEntry(keyName, true)) 00300 { 00301 config->writeEntry(keyName, true); 00302 config->sync(); 00303 KConfig konq_config("konquerorrc", false); 00304 konq_config.setGroup( "Trash" ); 00305 konq_config.writeEntry( keyName, false ); 00306 } 00307 } 00308 return (result == KMessageBox::Continue); 00309 } 00310 return true; 00311 } 00312 00313 void KonqOperations::doDrop( const KFileItem * destItem, const KURL & dest, TQDropEvent * ev, TQWidget * parent ) 00314 { 00315 kdDebug(1203) << "doDrop: dest : " << dest.url() << endl; 00316 KURL::List lst; 00317 TQMap<TQString, TQString> metaData; 00318 if ( KURLDrag::decode( ev, lst, metaData ) ) // Are they urls ? 00319 { 00320 if( lst.count() == 0 ) 00321 { 00322 kdWarning(1203) << "Oooops, no data ...." << endl; 00323 ev->accept(false); 00324 return; 00325 } 00326 kdDebug(1203) << "KonqOperations::doDrop metaData: " << metaData.count() << " entries." << endl; 00327 TQMap<TQString,TQString>::ConstIterator mit; 00328 for( mit = metaData.begin(); mit != metaData.end(); ++mit ) 00329 { 00330 kdDebug(1203) << "metaData: key=" << mit.key() << " value=" << mit.data() << endl; 00331 } 00332 // Check if we dropped something on itself 00333 KURL::List::Iterator it = lst.begin(); 00334 for ( ; it != lst.end() ; it++ ) 00335 { 00336 kdDebug(1203) << "URL : " << (*it).url() << endl; 00337 if ( dest.equals( *it, true /*ignore trailing slashes*/ ) ) 00338 { 00339 // The event source may be the view or an item (icon) 00340 // Note: ev->source() can be 0L! (in case of kdesktop) (Simon) 00341 if ( !ev->source() || ev->source() != parent && ev->source()->parent() != parent ) 00342 KMessageBox::sorry( parent, i18n("You cannot drop a folder on to itself") ); 00343 kdDebug(1203) << "Dropped on itself" << endl; 00344 ev->accept(false); 00345 return; // do nothing instead of displaying kfm's annoying error box 00346 } 00347 } 00348 00349 // Check the state of the modifiers key at the time of the drop 00350 Window root; 00351 Window child; 00352 int root_x, root_y, win_x, win_y; 00353 uint keybstate; 00354 XQueryPointer( qt_xdisplay(), qt_xrootwin(), &root, &child, 00355 &root_x, &root_y, &win_x, &win_y, &keybstate ); 00356 00357 TQDropEvent::Action action = ev->action(); 00358 // Check for the drop of a bookmark -> we want a Link action 00359 if ( ev->provides("application/x-xbel") ) 00360 { 00361 keybstate |= ControlMask | ShiftMask; 00362 action = TQDropEvent::Link; 00363 kdDebug(1203) << "KonqOperations::doDrop Bookmark -> emulating Link" << endl; 00364 } 00365 00366 KonqOperations * op = new KonqOperations(parent); 00367 op->setDropInfo( new DropInfo( keybstate, lst, metaData, win_x, win_y, action ) ); 00368 00369 // Ok, now we need destItem. 00370 if ( destItem ) 00371 { 00372 op->asyncDrop( destItem ); // we have it already 00373 } 00374 else 00375 { 00376 // we need to stat to get it. 00377 op->_statURL( dest, op, TQT_SLOT( asyncDrop( const KFileItem * ) ) ); 00378 } 00379 // In both cases asyncDrop will delete op when done 00380 00381 ev->acceptAction(); 00382 } 00383 else 00384 { 00385 //kdDebug(1203) << "Pasting to " << dest.url() << endl; 00386 KonqOperations * op = new KonqOperations(parent); 00387 KIO::CopyJob* job = KIO::pasteMimeSource( ev, dest, 00388 i18n( "File name for dropped contents:" ), 00389 parent ); 00390 if ( job ) // 0 if canceled by user 00391 { 00392 op->setOperation( job, COPY, KURL::List(), job->destURL() ); 00393 (void) new KonqCommandRecorder( KonqCommand::COPY, KURL::List(), dest, job ); 00394 } 00395 ev->acceptAction(); 00396 } 00397 } 00398 00399 void KonqOperations::asyncDrop( const KFileItem * destItem ) 00400 { 00401 assert(m_info); // setDropInfo should have been called before asyncDrop 00402 m_destURL = destItem->url(); 00403 00404 //kdDebug(1203) << "KonqOperations::asyncDrop destItem->mode=" << destItem->mode() << " url=" << m_destURL << endl; 00405 // Check what the destination is 00406 if ( destItem->isDir() ) 00407 { 00408 doFileCopy(); 00409 return; 00410 } 00411 if ( !m_destURL.isLocalFile() ) 00412 { 00413 // We dropped onto a remote URL that is not a directory! 00414 // (e.g. an HTTP link in the sidebar). 00415 // Can't do that, but we can't prevent it before stating the dest.... 00416 kdWarning(1203) << "Cannot drop onto " << m_destURL << endl; 00417 delete this; 00418 return; 00419 } 00420 if ( (destItem->mimetype() == "application/x-desktop") 00421 || (destItem->mimetype() == "media/builtin-mydocuments") 00422 || (destItem->mimetype() == "media/builtin-mycomputer") 00423 || (destItem->mimetype() == "media/builtin-mynetworkplaces") 00424 || (destItem->mimetype() == "media/builtin-printers") 00425 || (destItem->mimetype() == "media/builtin-trash") 00426 || (destItem->mimetype() == "media/builtin-webbrowser") ) 00427 { 00428 // Local .desktop file. What type ? 00429 KDesktopFile desktopFile( m_destURL.path() ); 00430 if ( desktopFile.hasApplicationType() ) 00431 { 00432 TQString error; 00433 TQStringList stringList; 00434 KURL::List lst = m_info->lst; 00435 KURL::List::Iterator it = lst.begin(); 00436 for ( ; it != lst.end() ; it++ ) 00437 { 00438 stringList.append((*it).url()); 00439 } 00440 if ( KApplication::startServiceByDesktopPath( m_destURL.path(), stringList, &error ) > 0 ) 00441 KMessageBox::error( 0L, error ); 00442 } 00443 else 00444 { 00445 // Device or Link -> adjust dest 00446 if ( desktopFile.hasDeviceType() && desktopFile.hasKey("MountPoint") ) { 00447 TQString point = desktopFile.readEntry( "MountPoint" ); 00448 m_destURL.setPath( point ); 00449 TQString dev = desktopFile.readDevice(); 00450 TQString mp = KIO::findDeviceMountPoint( dev ); 00451 // Is the device already mounted ? 00452 if ( !mp.isNull() ) 00453 doFileCopy(); 00454 else 00455 { 00456 bool ro = desktopFile.readBoolEntry( "ReadOnly", false ); 00457 TQString fstype = desktopFile.readEntry( "FSType" ); 00458 KAutoMount* am = new KAutoMount( ro, fstype, dev, point, m_destURL.path(), false ); 00459 connect( am, TQT_SIGNAL( finished() ), this, TQT_SLOT( doFileCopy() ) ); 00460 } 00461 return; 00462 } 00463 else if ( desktopFile.hasLinkType() && desktopFile.hasKey("URL") ) { 00464 m_destURL = desktopFile.readPathEntry("URL"); 00465 doFileCopy(); 00466 return; 00467 } 00468 // else, well: mimetype, service, servicetype or .directory. Can't really drop anything on those. 00469 } 00470 } 00471 else 00472 { 00473 // Should be a local executable 00474 // (If this fails, there is a bug in KFileItem::acceptsDrops) 00475 kdDebug(1203) << "KonqOperations::doDrop " << m_destURL.path() << "should be an executable" << endl; 00476 Q_ASSERT ( access( TQFile::encodeName(m_destURL.path()), X_OK ) == 0 ); 00477 KProcess proc; 00478 proc << m_destURL.path() ; 00479 // Launch executable for each of the files 00480 KURL::List lst = m_info->lst; 00481 KURL::List::Iterator it = lst.begin(); 00482 for ( ; it != lst.end() ; it++ ) 00483 proc << (*it).path(); // assume local files 00484 kdDebug(1203) << "starting " << m_destURL.path() << " with " << lst.count() << " arguments" << endl; 00485 proc.start( KProcess::DontCare ); 00486 } 00487 delete this; 00488 } 00489 00490 void KonqOperations::doFileCopy() 00491 { 00492 assert(m_info); // setDropInfo - and asyncDrop - should have been called before asyncDrop 00493 KURL::List lst = m_info->lst; 00494 TQDropEvent::Action action = m_info->action; 00495 bool isDesktopFile = false; 00496 bool itemIsOnDesktop = false; 00497 bool allItemsAreFromTrash = true; 00498 KURL::List mlst; // list of items that can be moved 00499 for (KURL::List::ConstIterator it = lst.begin(); it != lst.end(); ++it) 00500 { 00501 bool local = (*it).isLocalFile(); 00502 if ( KProtocolInfo::supportsDeleting( *it ) && (!local || TQFileInfo((*it).directory()).isWritable() )) 00503 mlst.append(*it); 00504 if ( local && KDesktopFile::isDesktopFile((*it).path())) 00505 isDesktopFile = true; 00506 if ( local && (*it).path().startsWith(KGlobalSettings::desktopPath())) 00507 itemIsOnDesktop = true; 00508 if ( local || (*it).protocol() != "trash" ) 00509 allItemsAreFromTrash = false; 00510 } 00511 00512 bool linkOnly = false; 00513 if (isDesktopFile && !kapp->authorize("run_desktop_files") && 00514 (m_destURL.path(1) == KGlobalSettings::desktopPath()) ) 00515 { 00516 linkOnly = true; 00517 } 00518 00519 if ( !mlst.isEmpty() && m_destURL.protocol() == "trash" ) 00520 { 00521 if ( itemIsOnDesktop && !kapp->authorize("editable_desktop_icons") ) 00522 { 00523 delete this; 00524 return; 00525 } 00526 00527 m_method = TRASH; 00528 if ( askDeleteConfirmation( mlst, TRASH, DEFAULT_CONFIRMATION, parentWidget() ) ) 00529 action = TQDropEvent::Move; 00530 else 00531 { 00532 delete this; 00533 return; 00534 } 00535 } 00536 else if ( allItemsAreFromTrash || m_destURL.protocol() == "trash" ) { 00537 // No point in asking copy/move/link when using dnd from or to the trash. 00538 action = TQDropEvent::Move; 00539 } 00540 else if ( (((m_info->keybstate & ControlMask) == 0) && ((m_info->keybstate & ShiftMask) == 0)) || 00541 linkOnly ) 00542 { 00543 // Neither control nor shift are pressed => show popup menu 00544 KonqIconViewWidget *iconView = tqt_dynamic_cast<KonqIconViewWidget*>(parent()); 00545 bool bSetWallpaper = false; 00546 if ( iconView && iconView->maySetWallpaper() && lst.count() == 1 ) 00547 { 00548 KURL url = lst.first(); 00549 KMimeType::Ptr mime = KMimeType::findByURL( url ); 00550 if ( ( !KImageIO::type(url.path()).isEmpty() ) || 00551 ( KImageIO::isSupported(mime->name(), KImageIO::Reading) ) || 00552 mime->is( "image/svg+xml" ) ) 00553 { 00554 bSetWallpaper = true; 00555 } 00556 } 00557 00558 // Check what the source can do 00559 KURL url = lst.first(); // we'll assume it's the same for all URLs (hack) 00560 bool sReading = KProtocolInfo::supportsReading( url ); 00561 bool sDeleting = KProtocolInfo::supportsDeleting( url ); 00562 bool sMoving = KProtocolInfo::supportsMoving( url ); 00563 // Check what the destination can do 00564 bool dWriting = KProtocolInfo::supportsWriting( m_destURL ); 00565 if ( !dWriting ) 00566 { 00567 delete this; 00568 return; 00569 } 00570 00571 TQPopupMenu popup; 00572 if (!mlst.isEmpty() && (sMoving || (sReading && sDeleting)) && !linkOnly ) 00573 popup.insertItem(SmallIconSet("goto"), i18n( "&Move Here" ) + "\t" + KKey::modFlagLabel( KKey::SHIFT ), 2 ); 00574 if ( sReading && !linkOnly) 00575 popup.insertItem(SmallIconSet("editcopy"), i18n( "&Copy Here" ) + "\t" + KKey::modFlagLabel( KKey::CTRL ), 1 ); 00576 popup.insertItem(SmallIconSet("www"), i18n( "&Link Here" ) + "\t" + KKey::modFlagLabel( (KKey::ModFlag)( KKey::CTRL|KKey::SHIFT ) ), 3 ); 00577 if (bSetWallpaper) 00578 popup.insertItem(SmallIconSet("background"), i18n( "Set as &Wallpaper" ), 4 ); 00579 popup.insertSeparator(); 00580 popup.insertItem(SmallIconSet("cancel"), i18n( "C&ancel" ) + "\t" + KKey( Qt::Key_Escape ).toString(), 5); 00581 00582 int result = popup.exec( m_info->mousePos ); 00583 00584 switch (result) { 00585 case 1 : action = TQDropEvent::Copy; break; 00586 case 2 : action = TQDropEvent::Move; break; 00587 case 3 : action = TQDropEvent::Link; break; 00588 case 4 : 00589 { 00590 kdDebug(1203) << "setWallpaper iconView=" << iconView << " url=" << lst.first().url() << endl; 00591 if (iconView && iconView->isDesktop() ) iconView->setWallpaper(lst.first()); 00592 delete this; 00593 return; 00594 } 00595 case 5 : 00596 default : delete this; return; 00597 } 00598 } 00599 00600 KIO::Job * job = 0; 00601 switch ( action ) { 00602 case TQDropEvent::Move : 00603 job = KIO::move( lst, m_destURL ); 00604 job->setMetaData( m_info->metaData ); 00605 setOperation( job, m_method == TRASH ? TRASH : MOVE, lst, m_destURL ); 00606 (void) new KonqCommandRecorder( 00607 m_method == TRASH ? KonqCommand::TRASH : KonqCommand::MOVE, 00608 lst, m_destURL, job ); 00609 return; // we still have stuff to do -> don't delete ourselves 00610 case TQDropEvent::Copy : 00611 job = KIO::copy( lst, m_destURL ); 00612 job->setMetaData( m_info->metaData ); 00613 setOperation( job, COPY, lst, m_destURL ); 00614 (void) new KonqCommandRecorder( KonqCommand::COPY, lst, m_destURL, job ); 00615 return; 00616 case TQDropEvent::Link : 00617 kdDebug(1203) << "KonqOperations::asyncDrop lst.count=" << lst.count() << endl; 00618 job = KIO::link( lst, m_destURL ); 00619 job->setMetaData( m_info->metaData ); 00620 setOperation( job, LINK, lst, m_destURL ); 00621 (void) new KonqCommandRecorder( KonqCommand::LINK, lst, m_destURL, job ); 00622 return; 00623 default : kdError(1203) << "Unknown action " << (int)action << endl; 00624 } 00625 delete this; 00626 } 00627 00628 void KonqOperations::rename( TQWidget * parent, const KURL & oldurl, const KURL& newurl ) 00629 { 00630 kdDebug(1203) << "KonqOperations::rename oldurl=" << oldurl << " newurl=" << newurl << endl; 00631 if ( oldurl == newurl ) 00632 return; 00633 00634 KURL::List lst; 00635 lst.append(oldurl); 00636 KIO::Job * job = KIO::moveAs( oldurl, newurl, !oldurl.isLocalFile() ); 00637 KonqOperations * op = new KonqOperations( parent ); 00638 op->setOperation( job, MOVE, lst, newurl ); 00639 (void) new KonqCommandRecorder( KonqCommand::MOVE, lst, newurl, job ); 00640 // if moving the desktop then update config file and emit 00641 if ( oldurl.isLocalFile() && oldurl.path(1) == KGlobalSettings::desktopPath() ) 00642 { 00643 kdDebug(1203) << "That rename was the Desktop path, updating config files" << endl; 00644 KConfig *globalConfig = KGlobal::config(); 00645 KConfigGroupSaver cgs( globalConfig, "Paths" ); 00646 globalConfig->writePathEntry("Desktop" , newurl.path(), true, true ); 00647 globalConfig->sync(); 00648 KIPC::sendMessageAll(KIPC::SettingsChanged, KApplication::SETTINGS_PATHS); 00649 } 00650 } 00651 00652 void KonqOperations::setOperation( KIO::Job * job, int method, const KURL::List & /*src*/, const KURL & dest ) 00653 { 00654 m_method = method; 00655 //m_srcURLs = src; 00656 m_destURL = dest; 00657 if ( job ) 00658 { 00659 connect( job, TQT_SIGNAL( result( KIO::Job * ) ), 00660 TQT_SLOT( slotResult( KIO::Job * ) ) ); 00661 KIO::CopyJob *copyJob = tqt_dynamic_cast<KIO::CopyJob*>(job); 00662 KonqIconViewWidget *iconView = tqt_dynamic_cast<KonqIconViewWidget*>(parent()); 00663 if (copyJob && iconView) 00664 { 00665 connect(copyJob, TQT_SIGNAL(aboutToCreate(KIO::Job *,const TQValueList<KIO::CopyInfo> &)), 00666 this, TQT_SLOT(slotAboutToCreate(KIO::Job *,const TQValueList<KIO::CopyInfo> &))); 00667 connect(this, TQT_SIGNAL(aboutToCreate(const TQPoint &, const TQValueList<KIO::CopyInfo> &)), 00668 iconView, TQT_SLOT(slotAboutToCreate(const TQPoint &, const TQValueList<KIO::CopyInfo> &))); 00669 } 00670 } 00671 else // for link 00672 slotResult( 0L ); 00673 } 00674 00675 void KonqOperations::slotAboutToCreate(KIO::Job *, const TQValueList<KIO::CopyInfo> &files) 00676 { 00677 emit aboutToCreate( m_info ? m_info->mousePos : m_pasteInfo ? m_pasteInfo->mousePos : TQPoint(), files); 00678 } 00679 00680 void KonqOperations::statURL( const KURL & url, const TQObject *receiver, const char *member ) 00681 { 00682 KonqOperations * op = new KonqOperations( 0L ); 00683 op->_statURL( url, receiver, member ); 00684 op->m_method = STAT; 00685 } 00686 00687 void KonqOperations::_statURL( const KURL & url, const TQObject *receiver, const char *member ) 00688 { 00689 connect( this, TQT_SIGNAL( statFinished( const KFileItem * ) ), receiver, member ); 00690 KIO::StatJob * job = KIO::stat( url /*, false?*/ ); 00691 connect( job, TQT_SIGNAL( result( KIO::Job * ) ), 00692 TQT_SLOT( slotStatResult( KIO::Job * ) ) ); 00693 } 00694 00695 void KonqOperations::slotStatResult( KIO::Job * job ) 00696 { 00697 if ( job->error()) 00698 job->showErrorDialog( (TQWidget*)parent() ); 00699 else 00700 { 00701 KIO::StatJob * statJob = static_cast<KIO::StatJob*>(job); 00702 KFileItem * item = new KFileItem( statJob->statResult(), statJob->url() ); 00703 emit statFinished( item ); 00704 delete item; 00705 } 00706 // If we're only here for a stat, we're done. But not if we used _statURL internally 00707 if ( m_method == STAT ) 00708 delete this; 00709 } 00710 00711 void KonqOperations::slotResult( KIO::Job * job ) 00712 { 00713 if (job && job->error()) 00714 job->showErrorDialog( (TQWidget*)parent() ); 00715 if ( m_method == EMPTYTRASH ) { 00716 // Update konq windows opened on trash:/ 00717 KDirNotify_stub allDirNotify("*", "KDirNotify*"); 00718 allDirNotify.FilesAdded( "trash:/" ); // yeah, files were removed, but we don't know which ones... 00719 } 00720 delete this; 00721 } 00722 00723 void KonqOperations::rename( TQWidget * parent, const KURL & oldurl, const TQString & name ) 00724 { 00725 KURL newurl( oldurl ); 00726 newurl.setPath( oldurl.directory(false, true) + name ); 00727 kdDebug(1203) << "KonqOperations::rename("<<name<<") called. newurl=" << newurl << endl; 00728 rename( parent, oldurl, newurl ); 00729 } 00730 00731 void KonqOperations::newDir( TQWidget * parent, const KURL & baseURL ) 00732 { 00733 bool ok; 00734 TQString name = i18n( "New Folder" ); 00735 if ( baseURL.isLocalFile() && TQFileInfo( baseURL.path(+1) + name ).exists() ) 00736 name = KIO::RenameDlg::suggestName( baseURL, i18n( "New Folder" ) ); 00737 00738 name = KInputDialog::getText ( i18n( "New Folder" ), 00739 i18n( "Enter folder name:" ), name, &ok, parent ); 00740 if ( ok && !name.isEmpty() ) 00741 { 00742 KURL url; 00743 if ((name[0] == '/') || (name[0] == '~')) 00744 { 00745 url.setPath(KShell::tildeExpand(name)); 00746 } 00747 else 00748 { 00749 name = KIO::encodeFileName( name ); 00750 url = baseURL; 00751 url.addPath( name ); 00752 } 00753 KonqOperations::mkdir( 0L, url ); 00754 } 00755 } 00756 00758 00759 KonqMultiRestoreJob::KonqMultiRestoreJob( const KURL::List& urls, bool showProgressInfo ) 00760 : KIO::Job( showProgressInfo ), 00761 m_urls( urls ), m_urlsIterator( m_urls.begin() ), 00762 m_progress( 0 ) 00763 { 00764 TQTimer::singleShot(0, this, TQT_SLOT(slotStart())); 00765 } 00766 00767 void KonqMultiRestoreJob::slotStart() 00768 { 00769 // Well, it's not a total in bytes, so this would look weird 00770 //if ( m_urlsIterator == m_urls.begin() ) // first time: emit total 00771 // emit totalSize( m_urls.count() ); 00772 00773 if ( m_urlsIterator != m_urls.end() ) 00774 { 00775 const KURL& url = *m_urlsIterator; 00776 00777 KURL new_url = url; 00778 if ( new_url.protocol()=="system" 00779 && new_url.path().startsWith("/trash") ) 00780 { 00781 TQString path = new_url.path(); 00782 path.remove(0, 6); 00783 new_url.setProtocol("trash"); 00784 new_url.setPath(path); 00785 } 00786 00787 Q_ASSERT( new_url.protocol() == "trash" ); 00788 TQByteArray packedArgs; 00789 TQDataStream stream( packedArgs, IO_WriteOnly ); 00790 stream << (int)3 << new_url; 00791 KIO::Job* job = KIO::special( new_url, packedArgs ); 00792 addSubjob( job ); 00793 } 00794 else // done! 00795 { 00796 KDirNotify_stub allDirNotify("*", "KDirNotify*"); 00797 allDirNotify.FilesRemoved( m_urls ); 00798 emitResult(); 00799 } 00800 } 00801 00802 void KonqMultiRestoreJob::slotResult( KIO::Job *job ) 00803 { 00804 if ( job->error() ) 00805 { 00806 KIO::Job::slotResult( job ); // will set the error and emit result(this) 00807 return; 00808 } 00809 subjobs.remove( job ); 00810 // Move on to next one 00811 ++m_urlsIterator; 00812 ++m_progress; 00813 //emit processedSize( this, m_progress ); 00814 emitPercent( m_progress, m_urls.count() ); 00815 slotStart(); 00816 } 00817 00818 TQWidget* KonqOperations::parentWidget() const 00819 { 00820 return static_cast<TQWidget *>( parent() ); 00821 } 00822 00823 #include "konq_operations.moc"