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