kio Library API Documentation

renamedlg.cpp

00001 /* This file is part of the KDE libraries 00002 Copyright (C) 2000 Stephan Kulow <coolo@kde.org> 00003 David Faure <faure@kde.org> 00004 2001 Holger Freyther <freyther@kde.org> 00005 00006 This library is free software; you can redistribute it and/or 00007 modify it under the terms of the GNU Library General Public 00008 License as published by the Free Software Foundation; either 00009 version 2 of the License, or (at your option) any later version. 00010 00011 This library is distributed in the hope that it will be useful, 00012 but WITHOUT ANY WARRANTY; without even the implied warranty of 00013 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00014 Library General Public License for more details. 00015 00016 You should have received a copy of the GNU Library General Public License 00017 along with this library; see the file COPYING.LIB. If not, write to 00018 the Free Software Foundation, Inc., 59 Temple Place - Suite 330, 00019 Boston, MA 02111-1307, USA. 00020 */ 00021 00022 #include "kio/renamedlg.h" 00023 #include "kio/renamedlgplugin.h" 00024 #include <stdio.h> 00025 #include <assert.h> 00026 00027 #include <qfileinfo.h> 00028 #include <qlabel.h> 00029 #include <qlayout.h> 00030 #include <qlineedit.h> 00031 #include <qdir.h> 00032 00033 #include <kmessagebox.h> 00034 #include <kpushbutton.h> 00035 #include <kapplication.h> 00036 #include <kio/global.h> 00037 #include <ktrader.h> 00038 #include <klibloader.h> 00039 #include <kdialog.h> 00040 #include <klocale.h> 00041 #include <kglobal.h> 00042 #include <kdebug.h> 00043 #include <kurl.h> 00044 #include <kmimetype.h> 00045 #include <kwin.h> 00046 #include <kseparator.h> 00047 #include <kstringhandler.h> 00048 #include <kstdguiitem.h> 00049 #include <kguiitem.h> 00050 #include <ksqueezedtextlabel.h> 00051 00052 using namespace KIO; 00053 00054 class RenameDlg::RenameDlgPrivate 00055 { 00056 public: 00057 RenameDlgPrivate(){ 00058 bCancel = 0; 00059 bRename = bSkip = bAutoSkip = bOverwrite = bOverwriteAll = 0; 00060 bResume = bResumeAll = bSuggestNewName = 0; 00061 m_pLineEdit = 0; 00062 } 00063 KPushButton *bCancel; 00064 QPushButton *bRename; 00065 QPushButton *bSkip; 00066 QPushButton *bAutoSkip; 00067 QPushButton *bOverwrite; 00068 QPushButton *bOverwriteAll; 00069 QPushButton *bResume; 00070 QPushButton *bResumeAll; 00071 QPushButton *bSuggestNewName; 00072 QLineEdit* m_pLineEdit; 00073 KURL src; 00074 KURL dest; 00075 QString mimeSrc; 00076 QString mimeDest; 00077 bool modal; 00078 bool plugin; 00079 }; 00080 00081 RenameDlg::RenameDlg(QWidget *parent, const QString & _caption, 00082 const QString &_src, const QString &_dest, 00083 RenameDlg_Mode _mode, 00084 KIO::filesize_t sizeSrc, 00085 KIO::filesize_t sizeDest, 00086 time_t ctimeSrc, 00087 time_t ctimeDest, 00088 time_t mtimeSrc, 00089 time_t mtimeDest, 00090 bool _modal) 00091 : QDialog ( parent, "KIO::RenameDialog" , _modal ) 00092 { 00093 d = new RenameDlgPrivate( ); 00094 d->modal = _modal; 00095 #if 0 00096 // Set "StaysOnTop", because this dialog is typically used in kio_uiserver, 00097 // i.e. in a separate process. 00098 // ####### This isn't the case anymore - remove? 00099 #ifndef Q_WS_QWS //FIXME(E): Implement for QT Embedded 00100 if (d->modal) 00101 KWin::setState( winId(), NET::StaysOnTop ); 00102 #endif 00103 #endif 00104 00105 d->src = _src; 00106 d->dest = _dest; 00107 d->plugin = false; 00108 00109 00110 setCaption( _caption ); 00111 00112 d->bCancel = new KPushButton( KStdGuiItem::cancel(), this ); 00113 connect(d->bCancel, SIGNAL(clicked()), this, SLOT(b0Pressed())); 00114 00115 if ( ! (_mode & M_NORENAME ) ) { 00116 d->bRename = new QPushButton( i18n( "&Rename" ), this ); 00117 d->bRename->setEnabled(false); 00118 d->bSuggestNewName = new QPushButton( i18n( "Suggest New &Name" ), this ); 00119 connect(d->bSuggestNewName, SIGNAL(clicked()), this, SLOT(b8Pressed())); 00120 connect(d->bRename, SIGNAL(clicked()), this, SLOT(b1Pressed())); 00121 } 00122 00123 if ( ( _mode & M_MULTI ) && ( _mode & M_SKIP ) ) { 00124 d->bSkip = new QPushButton( i18n( "&Skip" ), this ); 00125 connect(d->bSkip, SIGNAL(clicked()), this, SLOT(b2Pressed())); 00126 00127 d->bAutoSkip = new QPushButton( i18n( "&Auto Skip" ), this ); 00128 connect(d->bAutoSkip, SIGNAL(clicked()), this, SLOT(b3Pressed())); 00129 } 00130 00131 if ( _mode & M_OVERWRITE ) { 00132 d->bOverwrite = new QPushButton( i18n( "&Overwrite" ), this ); 00133 connect(d->bOverwrite, SIGNAL(clicked()), this, SLOT(b4Pressed())); 00134 00135 if ( _mode & M_MULTI ) { 00136 d->bOverwriteAll = new QPushButton( i18n( "O&verwrite All" ), this ); 00137 connect(d->bOverwriteAll, SIGNAL(clicked()), this, SLOT(b5Pressed())); 00138 } 00139 } 00140 00141 if ( _mode & M_RESUME ) { 00142 d->bResume = new QPushButton( i18n( "&Resume" ), this ); 00143 connect(d->bResume, SIGNAL(clicked()), this, SLOT(b6Pressed())); 00144 00145 if ( _mode & M_MULTI ) 00146 { 00147 d->bResumeAll = new QPushButton( i18n( "R&esume All" ), this ); 00148 connect(d->bResumeAll, SIGNAL(clicked()), this, SLOT(b7Pressed())); 00149 } 00150 } 00151 00152 QVBoxLayout* pLayout = new QVBoxLayout( this, KDialog::marginHint(), 00153 KDialog::spacingHint() ); 00154 pLayout->addStrut( 360 ); // makes dlg at least that wide 00155 00156 // User tries to overwrite a file with itself ? 00157 if ( _mode & M_OVERWRITE_ITSELF ) { 00158 QLabel *lb = new QLabel( i18n( "This action would overwrite '%1' with itself.\n" 00159 "Please enter a new file name:" ).arg( KStringHandler::csqueeze( d->src.prettyURL(),100 ) ), this ); 00160 d->bRename->setText(i18n("C&ontinue")); 00161 pLayout->addWidget( lb ); 00162 } 00163 else if ( _mode & M_OVERWRITE ) { 00164 00165 // Figure out the mimetype and load one plugin 00166 // (This is the only mode that is handled by plugins) 00167 pluginHandling(); 00168 KTrader::OfferList plugin_offers; 00169 if( d->mimeSrc != KMimeType::defaultMimeType() ){ 00170 plugin_offers = KTrader::self()->query(d->mimeSrc, "'RenameDlg/Plugin' in ServiceTypes"); 00171 00172 }else if(d->mimeDest != KMimeType::defaultMimeType() ) { 00173 plugin_offers = KTrader::self()->query(d->mimeDest, "'RenameDlg/Plugin' in ServiceTypes"); 00174 } 00175 if(!plugin_offers.isEmpty() ){ 00176 kdDebug(7024) << "Offers" << endl; 00177 KTrader::OfferList::ConstIterator it = plugin_offers.begin(); 00178 KTrader::OfferList::ConstIterator end = plugin_offers.end(); 00179 for( ; it != end; ++it ){ 00180 QString libName = (*it)->library(); 00181 if( libName.isEmpty() ){ 00182 kdDebug(7024) << "lib is empty" << endl; 00183 continue; 00184 } 00185 KLibrary *lib = KLibLoader::self()->library(libName.local8Bit() ); 00186 if(!lib) { 00187 continue; 00188 } 00189 KLibFactory *factory = lib->factory(); 00190 if(!factory){ 00191 lib->unload(); 00192 continue; 00193 } 00194 QObject *obj = factory->create( this, (*it)->name().latin1() ); 00195 if(!obj) { 00196 lib->unload(); 00197 continue; 00198 } 00199 RenameDlgPlugin *plugin = static_cast<RenameDlgPlugin *>(obj); 00200 if(!plugin ){ 00201 delete obj; 00202 continue; 00203 } 00204 if( plugin->initialize( _mode, _src, _dest, d->mimeSrc, 00205 d->mimeDest, sizeSrc, sizeDest, 00206 ctimeSrc, ctimeDest, 00207 mtimeSrc, mtimeDest ) ) { 00208 d->plugin = true; 00209 pLayout->addWidget(plugin ); 00210 kdDebug(7024) << "RenameDlgPlugin" << endl; 00211 break; 00212 } else { 00213 delete obj; 00214 } 00215 } 00216 00217 } 00218 00219 if( !d->plugin ){ 00220 // No plugin found, build default dialog 00221 QGridLayout * gridLayout = new QGridLayout( 0L, 9, 2, KDialog::marginHint(), 00222 KDialog::spacingHint() ); 00223 pLayout->addLayout(gridLayout); 00224 gridLayout->setColStretch(0,0); 00225 gridLayout->setColStretch(1,10); 00226 00227 QString sentence1; 00228 if (mtimeDest < mtimeSrc) 00229 sentence1 = i18n("An older item named '%1' already exists."); 00230 else if (mtimeDest == mtimeSrc) 00231 sentence1 = i18n("A similar file named '%1' already exists."); 00232 else 00233 sentence1 = i18n("A newer item named '%1' already exists."); 00234 00235 QLabel * lb1 = new KSqueezedTextLabel( sentence1.arg(d->dest.prettyURL()), this ); 00236 gridLayout->addMultiCellWidget( lb1, 0, 0, 0, 1 ); // takes the complete first line 00237 00238 lb1 = new QLabel( this ); 00239 lb1->setPixmap( KMimeType::pixmapForURL( d->dest ) ); 00240 gridLayout->addMultiCellWidget( lb1, 1, 3, 0, 0 ); // takes the first column on rows 1-3 00241 00242 int row = 1; 00243 if ( sizeDest != (KIO::filesize_t)-1 ) 00244 { 00245 QLabel * lb = new QLabel( i18n("size %1").arg( KIO::convertSize(sizeDest) ), this ); 00246 gridLayout->addWidget( lb, row, 1 ); 00247 row++; 00248 00249 } 00250 if ( ctimeDest != (time_t)-1 ) 00251 { 00252 QDateTime dctime; dctime.setTime_t( ctimeDest ); 00253 QLabel * lb = new QLabel( i18n("created on %1").arg( KGlobal::locale()->formatDateTime(dctime) ), this ); 00254 gridLayout->addWidget( lb, row, 1 ); 00255 row++; 00256 } 00257 if ( mtimeDest != (time_t)-1 ) 00258 { 00259 QDateTime dmtime; dmtime.setTime_t( mtimeDest ); 00260 QLabel * lb = new QLabel( i18n("modified on %1").arg( KGlobal::locale()->formatDateTime(dmtime) ), this ); 00261 gridLayout->addWidget( lb, row, 1 ); 00262 row++; 00263 } 00264 00265 if ( !d->src.isEmpty() ) 00266 { 00267 // rows 1 to 3 are the details (size/ctime/mtime), row 4 is empty 00268 gridLayout->addRowSpacing( 4, 20 ); 00269 00270 QLabel * lb2 = new KSqueezedTextLabel( i18n("The source file is '%1'").arg(d->src.prettyURL()), this ); 00271 gridLayout->addMultiCellWidget( lb2, 5, 5, 0, 1 ); // takes the complete first line 00272 00273 lb2 = new QLabel( this ); 00274 lb2->setPixmap( KMimeType::pixmapForURL( d->src ) ); 00275 gridLayout->addMultiCellWidget( lb2, 6, 8, 0, 0 ); // takes the first column on rows 6-8 00276 00277 row = 6; 00278 00279 if ( sizeSrc != (KIO::filesize_t)-1 ) 00280 { 00281 QLabel * lb = new QLabel( i18n("size %1").arg( KIO::convertSize(sizeSrc) ), this ); 00282 gridLayout->addWidget( lb, row, 1 ); 00283 row++; 00284 } 00285 if ( ctimeSrc != (time_t)-1 ) 00286 { 00287 QDateTime dctime; dctime.setTime_t( ctimeSrc ); 00288 QLabel * lb = new QLabel( i18n("created on %1").arg( KGlobal::locale()->formatDateTime(dctime) ), this ); 00289 gridLayout->addWidget( lb, row, 1 ); 00290 row++; 00291 } 00292 if ( mtimeSrc != (time_t)-1 ) 00293 { 00294 QDateTime dmtime; dmtime.setTime_t( mtimeSrc ); 00295 QLabel * lb = new QLabel( i18n("modified on %1").arg( KGlobal::locale()->formatDateTime(dmtime) ), this ); 00296 gridLayout->addWidget( lb, row, 1 ); 00297 row++; 00298 } 00299 } 00300 } 00301 } 00302 else 00303 { 00304 // This is the case where we don't want to allow overwriting, the existing 00305 // file must be preserved (e.g. when renaming). 00306 QString sentence1; 00307 if (mtimeDest < mtimeSrc) 00308 sentence1 = i18n("An older item named '%1' already exists."); 00309 else if (mtimeDest == mtimeSrc) 00310 sentence1 = i18n("A similar file named '%1' already exists."); 00311 else 00312 sentence1 = i18n("A newer item named '%1' already exists."); 00313 00314 QLabel *lb = new KSqueezedTextLabel ( sentence1.arg(d->dest.url()), this ); 00315 pLayout->addWidget(lb); 00316 } 00317 QHBoxLayout* layout2 = new QHBoxLayout(); 00318 pLayout->addLayout( layout2 ); 00319 00320 d->m_pLineEdit = new QLineEdit( this ); 00321 layout2->addWidget( d->m_pLineEdit ); 00322 QString fileName = d->dest.fileName(); 00323 d->m_pLineEdit->setText( KIO::decodeFileName( fileName ) ); 00324 if ( d->bRename || d->bOverwrite ) 00325 connect(d->m_pLineEdit, SIGNAL(textChanged(const QString &)), 00326 SLOT(enableRenameButton(const QString &))); 00327 if ( d->bSuggestNewName ) 00328 { 00329 layout2->addWidget( d->bSuggestNewName ); 00330 setTabOrder( d->m_pLineEdit, d->bSuggestNewName ); 00331 } 00332 00333 KSeparator* separator = new KSeparator( this ); 00334 pLayout->addWidget( separator ); 00335 00336 QHBoxLayout* layout = new QHBoxLayout(); 00337 pLayout->addLayout( layout ); 00338 00339 layout->addStretch(1); 00340 00341 if ( d->bRename ) 00342 { 00343 layout->addWidget( d->bRename ); 00344 setTabOrder( d->bRename, d->bCancel ); 00345 } 00346 if ( d->bSkip ) 00347 { 00348 layout->addWidget( d->bSkip ); 00349 setTabOrder( d->bSkip, d->bCancel ); 00350 } 00351 if ( d->bAutoSkip ) 00352 { 00353 layout->addWidget( d->bAutoSkip ); 00354 setTabOrder( d->bAutoSkip, d->bCancel ); 00355 } 00356 if ( d->bOverwrite ) 00357 { 00358 layout->addWidget( d->bOverwrite ); 00359 setTabOrder( d->bOverwrite, d->bCancel ); 00360 } 00361 if ( d->bOverwriteAll ) 00362 { 00363 layout->addWidget( d->bOverwriteAll ); 00364 setTabOrder( d->bOverwriteAll, d->bCancel ); 00365 } 00366 if ( d->bResume ) 00367 { 00368 layout->addWidget( d->bResume ); 00369 setTabOrder( d->bResume, d->bCancel ); 00370 } 00371 if ( d->bResumeAll ) 00372 { 00373 layout->addWidget( d->bResumeAll ); 00374 setTabOrder( d->bResumeAll, d->bCancel ); 00375 } 00376 00377 d->bCancel->setDefault( true ); 00378 layout->addWidget( d->bCancel ); 00379 00380 resize( sizeHint() ); 00381 } 00382 00383 RenameDlg::~RenameDlg() 00384 { 00385 delete d; 00386 // no need to delete Pushbuttons,... qt will do this 00387 } 00388 00389 void RenameDlg::enableRenameButton(const QString &newDest) 00390 { 00391 if ( newDest != KIO::decodeFileName( d->dest.fileName() ) && !newDest.isEmpty() ) 00392 { 00393 d->bRename->setEnabled( true ); 00394 d->bRename->setDefault( true ); 00395 if ( d->bOverwrite ) 00396 d->bOverwrite->setEnabled( false ); // prevent confusion (#83114) 00397 } 00398 else 00399 { 00400 d->bRename->setEnabled( false ); 00401 if ( d->bOverwrite ) 00402 d->bOverwrite->setEnabled( true ); 00403 } 00404 } 00405 00406 KURL RenameDlg::newDestURL() 00407 { 00408 KURL newDest( d->dest ); 00409 QString fileName = d->m_pLineEdit->text(); 00410 newDest.setFileName( KIO::encodeFileName( fileName ) ); 00411 return newDest; 00412 } 00413 00414 void RenameDlg::b0Pressed() 00415 { 00416 done( 0 ); 00417 } 00418 00419 // Rename 00420 void RenameDlg::b1Pressed() 00421 { 00422 if ( d->m_pLineEdit->text().isEmpty() ) 00423 return; 00424 00425 KURL u = newDestURL(); 00426 if ( !u.isValid() ) 00427 { 00428 KMessageBox::error( this, i18n( "Malformed URL\n%1" ).arg( u.prettyURL() ) ); 00429 return; 00430 } 00431 00432 done( 1 ); 00433 } 00434 00435 static QString suggestName(const KURL& baseURL, const QString& oldName) 00436 { 00437 QString dotSuffix, suggestedName; 00438 QString basename = oldName; 00439 00440 int index = basename.find( '.' ); 00441 if ( index != -1 ) { 00442 dotSuffix = basename.mid( index ); 00443 basename.truncate( index ); 00444 } 00445 00446 int pos = basename.findRev( '_' ); 00447 if(pos != -1 ){ 00448 QString tmp = basename.mid( pos+1 ); 00449 bool ok; 00450 int number = tmp.toInt( &ok ); 00451 if ( !ok ) {// ok there is no number 00452 suggestedName = basename + "1" + dotSuffix; 00453 } 00454 else { 00455 // yes there's already a number behind the _ so increment it by one 00456 basename.replace( pos+1, tmp.length(), QString::number(number+1) ); 00457 suggestedName = basename + dotSuffix; 00458 } 00459 } 00460 else // no underscore yet 00461 suggestedName = basename + "_1" + dotSuffix ; 00462 00463 // Check if suggested name already exists 00464 bool exists = false; 00465 // TODO: network transparency. However, using NetAccess from a modal dialog 00466 // could be a problem, no? (given that it uses a modal widget itself....) 00467 if ( baseURL.isLocalFile() ) 00468 exists = QFileInfo( baseURL.path(+1) + suggestedName ).exists(); 00469 00470 if ( !exists ) 00471 return suggestedName; 00472 else // already exists -> recurse 00473 return suggestName( baseURL, suggestedName ); 00474 } 00475 00476 // Propose button clicked 00477 void RenameDlg::b8Pressed() 00478 { 00479 /* no name to play with */ 00480 if ( d->m_pLineEdit->text().isEmpty() ) 00481 return; 00482 00483 KURL destDirectory( d->dest ); 00484 destDirectory.setPath( destDirectory.directory() ); 00485 d->m_pLineEdit->setText( suggestName( destDirectory, d->m_pLineEdit->text() ) ); 00486 return; 00487 } 00488 00489 void RenameDlg::b2Pressed() 00490 { 00491 done( 2 ); 00492 } 00493 00494 void RenameDlg::b3Pressed() 00495 { 00496 done( 3 ); 00497 } 00498 00499 void RenameDlg::b4Pressed() 00500 { 00501 done( 4 ); 00502 } 00503 00504 void RenameDlg::b5Pressed() 00505 { 00506 done( 5 ); 00507 } 00508 00509 void RenameDlg::b6Pressed() 00510 { 00511 done( 6 ); 00512 } 00513 00514 void RenameDlg::b7Pressed() 00515 { 00516 done( 7 ); 00517 } 00518 00519 static QString mime( const KURL& src ) 00520 { 00521 KMimeType::Ptr type = KMimeType::findByURL( src ); 00522 //if( type->name() == KMimeType::defaultMimeType() ){ // ok no mimetype 00523 // QString ty = KIO::NetAccess::mimetype(d->src ); 00524 // return ty; 00525 return type->name(); 00526 } 00527 00534 void RenameDlg::pluginHandling() 00535 { 00536 d->mimeSrc = mime( d->src ); 00537 d->mimeDest = mime(d->dest ); 00538 00539 kdDebug(7024) << "Source Mimetype: "<< d->mimeSrc << endl; 00540 kdDebug(7024) << "Dest Mimetype: "<< d->mimeDest << endl; 00541 } 00542 00543 00544 RenameDlg_Result KIO::open_RenameDlg( const QString & _caption, 00545 const QString & _src, const QString & _dest, 00546 RenameDlg_Mode _mode, 00547 QString& _new, 00548 KIO::filesize_t sizeSrc, 00549 KIO::filesize_t sizeDest, 00550 time_t ctimeSrc, 00551 time_t ctimeDest, 00552 time_t mtimeSrc, 00553 time_t mtimeDest) 00554 { 00555 Q_ASSERT(kapp); 00556 00557 RenameDlg dlg( 0L, _caption, _src, _dest, _mode, 00558 sizeSrc, sizeDest, ctimeSrc, ctimeDest, mtimeSrc, mtimeDest, 00559 true /*modal*/ ); 00560 int i = dlg.exec(); 00561 _new = dlg.newDestURL().path(); 00562 00563 return (RenameDlg_Result)i; 00564 } 00565 00566 #include "renamedlg.moc" 00567 00568 00569 00570 00571
KDE Logo
This file is part of the documentation for kio Library Version 3.3.0.
Documentation copyright © 1996-2004 the KDE developers.
Generated on Wed Sep 29 09:43:55 2004 by doxygen 1.3.8 written by Dimitri van Heesch, © 1997-2003