00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044 #include <config.h>
00045 extern "C" {
00046 #include <pwd.h>
00047 #include <grp.h>
00048 #include <time.h>
00049 }
00050 #include <unistd.h>
00051 #include <errno.h>
00052 #include <assert.h>
00053
00054 #include <qfile.h>
00055 #include <qdir.h>
00056 #include <qlabel.h>
00057 #include <qpushbutton.h>
00058 #include <qcheckbox.h>
00059 #include <qstrlist.h>
00060 #include <qstringlist.h>
00061 #include <qtextstream.h>
00062 #include <qpainter.h>
00063 #include <qlayout.h>
00064 #include <qcombobox.h>
00065 #include <qgroupbox.h>
00066 #include <qwhatsthis.h>
00067 #include <qtooltip.h>
00068 #include <qstyle.h>
00069
00070 #include <kapplication.h>
00071 #include <kdialog.h>
00072 #include <kdirsize.h>
00073 #include <kdirwatch.h>
00074 #include <kdirnotify_stub.h>
00075 #include <kdiskfreesp.h>
00076 #include <kdebug.h>
00077 #include <kdesktopfile.h>
00078 #include <kicondialog.h>
00079 #include <kurl.h>
00080 #include <kurlrequester.h>
00081 #include <klocale.h>
00082 #include <kglobal.h>
00083 #include <kglobalsettings.h>
00084 #include <kstandarddirs.h>
00085 #include <kio/job.h>
00086 #include <kio/chmodjob.h>
00087 #include <kio/renamedlg.h>
00088 #include <kio/netaccess.h>
00089 #include <kfiledialog.h>
00090 #include <kmimetype.h>
00091 #include <kmountpoint.h>
00092 #include <kiconloader.h>
00093 #include <kmessagebox.h>
00094 #include <kservice.h>
00095 #include <kcompletion.h>
00096 #include <klineedit.h>
00097 #include <kseparator.h>
00098 #include <ksqueezedtextlabel.h>
00099 #include <klibloader.h>
00100 #include <ktrader.h>
00101 #include <kparts/componentfactory.h>
00102 #include <kmetaprops.h>
00103 #include <kprocess.h>
00104 #include <krun.h>
00105 #include <klistview.h>
00106 #include "kfilesharedlg.h"
00107
00108 #include "kpropertiesdesktopbase.h"
00109 #include "kpropertiesdesktopadvbase.h"
00110 #include "kpropertiesmimetypebase.h"
00111
00112 #include "kpropertiesdialog.h"
00113
00114 static QString nameFromFileName(QString nameStr)
00115 {
00116 if ( nameStr.endsWith(".desktop") )
00117 nameStr.truncate( nameStr.length() - 8 );
00118 if ( nameStr.endsWith(".kdelnk") )
00119 nameStr.truncate( nameStr.length() - 7 );
00120
00121 nameStr = KIO::decodeFileName( nameStr );
00122 return nameStr;
00123 }
00124
00125 mode_t KFilePermissionsPropsPlugin::fperm[3][4] = {
00126 {S_IRUSR, S_IWUSR, S_IXUSR, S_ISUID},
00127 {S_IRGRP, S_IWGRP, S_IXGRP, S_ISGID},
00128 {S_IROTH, S_IWOTH, S_IXOTH, S_ISVTX}
00129 };
00130
00131 class KPropertiesDialog::KPropertiesDialogPrivate
00132 {
00133 public:
00134 KPropertiesDialogPrivate()
00135 {
00136 m_aborted = false;
00137 }
00138 ~KPropertiesDialogPrivate()
00139 {
00140 }
00141 bool m_aborted:1;
00142 };
00143
00144 KPropertiesDialog::KPropertiesDialog (KFileItem* item,
00145 QWidget* parent, const char* name,
00146 bool modal, bool autoShow)
00147 : KDialogBase (KDialogBase::Tabbed, i18n( "Properties for %1" ).arg(KIO::decodeFileName(item->url().fileName())),
00148 KDialogBase::Ok | KDialogBase::Cancel, KDialogBase::Ok,
00149 parent, name, modal)
00150 {
00151 d = new KPropertiesDialogPrivate;
00152 assert( item );
00153 m_items.append( new KFileItem(*item) );
00154
00155 m_singleUrl = item->url();
00156 assert(!m_singleUrl.isEmpty());
00157
00158 init (modal, autoShow);
00159 }
00160
00161 KPropertiesDialog::KPropertiesDialog (const QString& title,
00162 QWidget* parent, const char* name, bool modal)
00163 : KDialogBase (KDialogBase::Tabbed, i18n ("Properties for %1").arg(title),
00164 KDialogBase::Ok | KDialogBase::Cancel, KDialogBase::Ok,
00165 parent, name, modal)
00166 {
00167 d = new KPropertiesDialogPrivate;
00168
00169 init (modal, false);
00170 }
00171
00172 KPropertiesDialog::KPropertiesDialog (KFileItemList _items,
00173 QWidget* parent, const char* name,
00174 bool modal, bool autoShow)
00175 : KDialogBase (KDialogBase::Tabbed,
00176 i18n( "Properties for %1" ).arg(KIO::decodeFileName(_items.first()->url().fileName())),
00177 KDialogBase::Ok | KDialogBase::Cancel, KDialogBase::Ok,
00178 parent, name, modal)
00179 {
00180 d = new KPropertiesDialogPrivate;
00181
00182 assert( !_items.isEmpty() );
00183 m_singleUrl = _items.first()->url();
00184 assert(!m_singleUrl.isEmpty());
00185
00186 KFileItemListIterator it ( _items );
00187
00188 for ( ; it.current(); ++it )
00189 m_items.append( new KFileItem( **it ) );
00190
00191 init (modal, autoShow);
00192 }
00193
00194 #ifndef KDE_NO_COMPAT
00195 KPropertiesDialog::KPropertiesDialog (const KURL& _url, mode_t ,
00196 QWidget* parent, const char* name,
00197 bool modal, bool autoShow)
00198 : KDialogBase (KDialogBase::Tabbed,
00199 i18n( "Properties for %1" ).arg(KIO::decodeFileName(_url.fileName())),
00200 KDialogBase::Ok | KDialogBase::Cancel, KDialogBase::Ok,
00201 parent, name, modal),
00202 m_singleUrl( _url )
00203 {
00204 d = new KPropertiesDialogPrivate;
00205
00206 KIO::UDSEntry entry;
00207
00208 KIO::NetAccess::stat(_url, entry, parent);
00209
00210 m_items.append( new KFileItem( entry, _url ) );
00211 init (modal, autoShow);
00212 }
00213 #endif
00214
00215 KPropertiesDialog::KPropertiesDialog (const KURL& _url,
00216 QWidget* parent, const char* name,
00217 bool modal, bool autoShow)
00218 : KDialogBase (KDialogBase::Tabbed,
00219 i18n( "Properties for %1" ).arg(KIO::decodeFileName(_url.fileName())),
00220 KDialogBase::Ok | KDialogBase::Cancel, KDialogBase::Ok,
00221 parent, name, modal),
00222 m_singleUrl( _url )
00223 {
00224 d = new KPropertiesDialogPrivate;
00225
00226 KIO::UDSEntry entry;
00227
00228 KIO::NetAccess::stat(_url, entry, parent);
00229
00230 m_items.append( new KFileItem( entry, _url ) );
00231 init (modal, autoShow);
00232 }
00233
00234 KPropertiesDialog::KPropertiesDialog (const KURL& _tempUrl, const KURL& _currentDir,
00235 const QString& _defaultName,
00236 QWidget* parent, const char* name,
00237 bool modal, bool autoShow)
00238 : KDialogBase (KDialogBase::Tabbed,
00239 i18n( "Properties for %1" ).arg(KIO::decodeFileName(_tempUrl.fileName())),
00240 KDialogBase::Ok | KDialogBase::Cancel, KDialogBase::Ok,
00241 parent, name, modal),
00242
00243 m_singleUrl( _tempUrl ),
00244 m_defaultName( _defaultName ),
00245 m_currentDir( _currentDir )
00246 {
00247 d = new KPropertiesDialogPrivate;
00248
00249 assert(!m_singleUrl.isEmpty());
00250
00251
00252 m_items.append( new KFileItem( KFileItem::Unknown, KFileItem::Unknown, m_singleUrl ) );
00253 init (modal, autoShow);
00254 }
00255
00256 void KPropertiesDialog::init (bool modal, bool autoShow)
00257 {
00258 m_pageList.setAutoDelete( true );
00259 m_items.setAutoDelete( true );
00260
00261 insertPages();
00262
00263 if (autoShow)
00264 {
00265 if (!modal)
00266 show();
00267 else
00268 exec();
00269 }
00270 }
00271
00272 void KPropertiesDialog::showFileSharingPage()
00273 {
00274 KPropsDlgPlugin *it;
00275
00276 for ( it=m_pageList.first(); it != 0L; it=m_pageList.next() )
00277 {
00278 KFileSharePropsPlugin* plugin = dynamic_cast<KFileSharePropsPlugin*>(it);
00279 if ( plugin )
00280 {
00281 showPage( pageIndex( plugin->page() ) );
00282 break;
00283 }
00284 }
00285 }
00286
00287 void KPropertiesDialog::setFileNameReadOnly( bool ro )
00288 {
00289 KPropsDlgPlugin *it;
00290
00291 for ( it=m_pageList.first(); it != 0L; it=m_pageList.next() )
00292 {
00293 KFilePropsPlugin* plugin = dynamic_cast<KFilePropsPlugin*>(it);
00294 if ( plugin ) {
00295 plugin->setFileNameReadOnly( ro );
00296 break;
00297 }
00298 }
00299 }
00300
00301 void KPropertiesDialog::slotStatResult( KIO::Job * )
00302 {
00303 }
00304
00305 KPropertiesDialog::~KPropertiesDialog()
00306 {
00307 m_pageList.clear();
00308 delete d;
00309 }
00310
00311 void KPropertiesDialog::insertPlugin (KPropsDlgPlugin* plugin)
00312 {
00313 connect (plugin, SIGNAL (changed ()),
00314 plugin, SLOT (setDirty ()));
00315
00316 m_pageList.append (plugin);
00317 }
00318
00319 bool KPropertiesDialog::canDisplay( KFileItemList _items )
00320 {
00321
00322 return KFilePropsPlugin::supports( _items ) ||
00323 KFilePermissionsPropsPlugin::supports( _items ) ||
00324 KDesktopPropsPlugin::supports( _items ) ||
00325 KBindingPropsPlugin::supports( _items ) ||
00326 KURLPropsPlugin::supports( _items ) ||
00327 KDevicePropsPlugin::supports( _items ) ||
00328 KFileMetaPropsPlugin::supports( _items );
00329 }
00330
00331 void KPropertiesDialog::slotOk()
00332 {
00333 KPropsDlgPlugin *page;
00334 d->m_aborted = false;
00335
00336 KFilePropsPlugin * filePropsPlugin = 0L;
00337 if ( m_pageList.first()->isA("KFilePropsPlugin") )
00338 filePropsPlugin = static_cast<KFilePropsPlugin *>(m_pageList.first());
00339
00340
00341
00342
00343 for ( page = m_pageList.first(); page != 0L; page = m_pageList.next() )
00344 if ( page->isDirty() && filePropsPlugin )
00345 {
00346 filePropsPlugin->setDirty();
00347 break;
00348 }
00349
00350
00351
00352
00353
00354 for ( page = m_pageList.first(); page != 0L && !d->m_aborted; page = m_pageList.next() )
00355 if ( page->isDirty() )
00356 {
00357 kdDebug( 250 ) << "applying changes for " << page->className() << endl;
00358 page->applyChanges();
00359
00360 }
00361 else
00362 kdDebug( 250 ) << "skipping page " << page->className() << endl;
00363
00364 if ( !d->m_aborted && filePropsPlugin )
00365 filePropsPlugin->postApplyChanges();
00366
00367 if ( !d->m_aborted )
00368 {
00369 emit applied();
00370 emit propertiesClosed();
00371 deleteLater();
00372 accept();
00373 }
00374 }
00375
00376 void KPropertiesDialog::slotCancel()
00377 {
00378 emit canceled();
00379 emit propertiesClosed();
00380
00381 deleteLater();
00382 done( Rejected );
00383 }
00384
00385 void KPropertiesDialog::insertPages()
00386 {
00387 if (m_items.isEmpty())
00388 return;
00389
00390 if ( KFilePropsPlugin::supports( m_items ) )
00391 {
00392 KPropsDlgPlugin *p = new KFilePropsPlugin( this );
00393 insertPlugin (p);
00394 }
00395
00396 if ( KFilePermissionsPropsPlugin::supports( m_items ) )
00397 {
00398 KPropsDlgPlugin *p = new KFilePermissionsPropsPlugin( this );
00399 insertPlugin (p);
00400 }
00401
00402 if ( KDesktopPropsPlugin::supports( m_items ) )
00403 {
00404 KPropsDlgPlugin *p = new KDesktopPropsPlugin( this );
00405 insertPlugin (p);
00406 }
00407
00408 if ( KBindingPropsPlugin::supports( m_items ) )
00409 {
00410 KPropsDlgPlugin *p = new KBindingPropsPlugin( this );
00411 insertPlugin (p);
00412 }
00413
00414 if ( KURLPropsPlugin::supports( m_items ) )
00415 {
00416 KPropsDlgPlugin *p = new KURLPropsPlugin( this );
00417 insertPlugin (p);
00418 }
00419
00420 if ( KDevicePropsPlugin::supports( m_items ) )
00421 {
00422 KPropsDlgPlugin *p = new KDevicePropsPlugin( this );
00423 insertPlugin (p);
00424 }
00425
00426 if ( KFileMetaPropsPlugin::supports( m_items ) )
00427 {
00428 KPropsDlgPlugin *p = new KFileMetaPropsPlugin( this );
00429 insertPlugin (p);
00430 }
00431
00432
00433 if ( KFileSharePropsPlugin::supports( m_items ) )
00434 {
00435
00436 QString path = m_items.first()->url().path(-1);
00437 bool isLocal = m_items.first()->url().isLocalFile();
00438 bool isIntoTrash = isLocal && path.startsWith(KGlobalSettings::trashPath());
00439 if ( !isIntoTrash )
00440 {
00441 KPropsDlgPlugin *p = new KFileSharePropsPlugin( this );
00442 insertPlugin (p);
00443 }
00444 }
00445
00446
00447
00448 if ( m_items.count() != 1 )
00449 return;
00450
00451 KFileItem *item = m_items.first();
00452 QString mimetype = item->mimetype();
00453
00454 if ( mimetype.isEmpty() )
00455 return;
00456
00457 QString query = QString::fromLatin1(
00458 "('KPropsDlg/Plugin' in ServiceTypes) and "
00459 "((not exist [X-KDE-Protocol]) or "
00460 " ([X-KDE-Protocol] == '%1' ) )" ).arg(item->url().protocol());
00461
00462 kdDebug( 250 ) << "trader query: " << query << endl;
00463 KTrader::OfferList offers = KTrader::self()->query( mimetype, query );
00464 KTrader::OfferList::ConstIterator it = offers.begin();
00465 KTrader::OfferList::ConstIterator end = offers.end();
00466 for (; it != end; ++it )
00467 {
00468 KPropsDlgPlugin *plugin = KParts::ComponentFactory
00469 ::createInstanceFromLibrary<KPropsDlgPlugin>( (*it)->library().local8Bit().data(),
00470 this,
00471 (*it)->name().latin1() );
00472 if ( !plugin )
00473 continue;
00474
00475 insertPlugin( plugin );
00476 }
00477 }
00478
00479 void KPropertiesDialog::updateUrl( const KURL& _newUrl )
00480 {
00481 Q_ASSERT( m_items.count() == 1 );
00482 kdDebug(250) << "KPropertiesDialog::updateUrl (pre)" << _newUrl.url() << endl;
00483 KURL newUrl = _newUrl;
00484 emit saveAs(m_singleUrl, newUrl);
00485 kdDebug(250) << "KPropertiesDialog::updateUrl (post)" << newUrl.url() << endl;
00486
00487 m_singleUrl = newUrl;
00488 m_items.first()->setURL( newUrl );
00489 assert(!m_singleUrl.isEmpty());
00490
00491
00492 for ( QPtrListIterator<KPropsDlgPlugin> it(m_pageList); it.current(); ++it )
00493 if ( it.current()->isA("KExecPropsPlugin") ||
00494 it.current()->isA("KURLPropsPlugin") ||
00495 it.current()->isA("KDesktopPropsPlugin"))
00496 {
00497
00498 it.current()->setDirty();
00499 break;
00500 }
00501 }
00502
00503 void KPropertiesDialog::rename( const QString& _name )
00504 {
00505 Q_ASSERT( m_items.count() == 1 );
00506 kdDebug(250) << "KPropertiesDialog::rename " << _name << endl;
00507 KURL newUrl;
00508
00509 if ( !m_currentDir.isEmpty() )
00510 {
00511 newUrl = m_currentDir;
00512 newUrl.addPath( _name );
00513 }
00514 else
00515 {
00516 QString tmpurl = m_singleUrl.url();
00517 if ( tmpurl.at(tmpurl.length() - 1) == '/')
00518
00519 tmpurl.truncate( tmpurl.length() - 1);
00520 newUrl = tmpurl;
00521 newUrl.setFileName( _name );
00522 }
00523 updateUrl( newUrl );
00524 }
00525
00526 void KPropertiesDialog::abortApplying()
00527 {
00528 d->m_aborted = true;
00529 }
00530
00531 class KPropsDlgPlugin::KPropsDlgPluginPrivate
00532 {
00533 public:
00534 KPropsDlgPluginPrivate()
00535 {
00536 }
00537 ~KPropsDlgPluginPrivate()
00538 {
00539 }
00540
00541 bool m_bDirty;
00542 };
00543
00544 KPropsDlgPlugin::KPropsDlgPlugin( KPropertiesDialog *_props )
00545 : QObject( _props, 0L )
00546 {
00547 d = new KPropsDlgPluginPrivate;
00548 properties = _props;
00549 fontHeight = 2*properties->fontMetrics().height();
00550 d->m_bDirty = false;
00551 }
00552
00553 KPropsDlgPlugin::~KPropsDlgPlugin()
00554 {
00555 delete d;
00556 }
00557
00558 bool KPropsDlgPlugin::isDesktopFile( KFileItem * _item )
00559 {
00560
00561 if ( !_item->isLocalFile() )
00562 return false;
00563
00564
00565 if ( !S_ISREG( _item->mode() ) )
00566 return false;
00567
00568 QString t( _item->url().path() );
00569
00570
00571 FILE *f = fopen( QFile::encodeName(t), "r" );
00572 if ( f == 0L )
00573 return false;
00574 fclose(f);
00575
00576
00577 return ( _item->mimetype() == "application/x-desktop" );
00578 }
00579
00580 void KPropsDlgPlugin::setDirty( bool b )
00581 {
00582 d->m_bDirty = b;
00583 }
00584
00585 void KPropsDlgPlugin::setDirty()
00586 {
00587 d->m_bDirty = true;
00588 }
00589
00590 bool KPropsDlgPlugin::isDirty() const
00591 {
00592 return d->m_bDirty;
00593 }
00594
00595 void KPropsDlgPlugin::applyChanges()
00596 {
00597 kdWarning(250) << "applyChanges() not implemented in page !" << endl;
00598 }
00599
00601
00602 class KFilePropsPlugin::KFilePropsPluginPrivate
00603 {
00604 public:
00605 KFilePropsPluginPrivate()
00606 {
00607 dirSizeJob = 0L;
00608 dirSizeUpdateTimer = 0L;
00609 m_lined = 0;
00610 }
00611 ~KFilePropsPluginPrivate()
00612 {
00613 if ( dirSizeJob )
00614 dirSizeJob->kill();
00615 }
00616
00617 KDirSize * dirSizeJob;
00618 QTimer *dirSizeUpdateTimer;
00619 QFrame *m_frame;
00620 bool bMultiple;
00621 bool bIconChanged;
00622 bool bKDesktopMode;
00623 bool bDesktopFile;
00624 QLabel *m_freeSpaceLabel;
00625 QString mimeType;
00626 QString oldFileName;
00627 KLineEdit* m_lined;
00628 };
00629
00630 KFilePropsPlugin::KFilePropsPlugin( KPropertiesDialog *_props )
00631 : KPropsDlgPlugin( _props )
00632 {
00633 d = new KFilePropsPluginPrivate;
00634 d->bMultiple = (properties->items().count() > 1);
00635 d->bIconChanged = false;
00636 d->bKDesktopMode = (QCString(qApp->name()) == "kdesktop");
00637 d->bDesktopFile = KDesktopPropsPlugin::supports(properties->items());
00638 kdDebug(250) << "KFilePropsPlugin::KFilePropsPlugin bMultiple=" << d->bMultiple << endl;
00639
00640
00641
00642 bool isLocal = properties->kurl().isLocalFile();
00643 KFileItem * item = properties->item();
00644 bool bDesktopFile = isDesktopFile(item);
00645 mode_t mode = item->mode();
00646 bool hasDirs = item->isDir() && !item->isLink();
00647 bool hasRoot = isLocal && properties->kurl().path() == QString::fromLatin1("/");
00648 QString iconStr = KMimeType::iconForURL(properties->kurl(), mode);
00649 QString directory = properties->kurl().directory();
00650 QString protocol = properties->kurl().protocol();
00651 QString mimeComment = item->mimeComment();
00652 d->mimeType = item->mimetype();
00653 KIO::filesize_t totalSize = item->size();
00654 QString magicMimeComment;
00655 if ( isLocal ) {
00656 KMimeType::Ptr magicMimeType = KMimeType::findByFileContent( properties->kurl().path() );
00657 if ( magicMimeType->name() != KMimeType::defaultMimeType() )
00658 magicMimeComment = magicMimeType->comment();
00659 }
00660
00661
00662 QString filename = QString::null;
00663 bool isTrash = false;
00664 bool isIntoTrash = false;
00665 bool isDevice = false;
00666 m_bFromTemplate = false;
00667
00668
00669 uint iDirCount = S_ISDIR(mode) ? 1 : 0;
00670 uint iFileCount = 1-iDirCount;
00671
00672 d->m_frame = properties->addPage (i18n("&General"));
00673
00674 QVBoxLayout *vbl = new QVBoxLayout( d->m_frame, 0,
00675 KDialog::spacingHint(), "vbl");
00676 QGridLayout *grid = new QGridLayout(0, 3);
00677 grid->setColStretch(0, 0);
00678 grid->setColStretch(1, 0);
00679 grid->setColStretch(2, 1);
00680 grid->addColSpacing(1, KDialog::spacingHint());
00681 vbl->addLayout(grid);
00682 int curRow = 0;
00683
00684 if ( !d->bMultiple )
00685 {
00686
00687 filename = properties->defaultName();
00688 if ( filename.isEmpty() )
00689 filename = properties->kurl().fileName();
00690 else
00691 {
00692 m_bFromTemplate = true;
00693 setDirty();
00694 }
00695 d->oldFileName = filename;
00696
00697
00698 filename = nameFromFileName( filename );
00699
00700 if ( d->bKDesktopMode && d->bDesktopFile ) {
00701 KDesktopFile config( properties->kurl().path(), true );
00702 if ( config.hasKey( "Name" ) ) {
00703 filename = config.readName();
00704 }
00705 }
00706
00707 oldName = filename;
00708
00709 QString path;
00710
00711 if ( !m_bFromTemplate ) {
00712 QString tmp = properties->kurl().path( 1 );
00713
00714 if ( isLocal )
00715 {
00716 if ( tmp == KGlobalSettings::trashPath())
00717 isTrash = true;
00718 if ( tmp.startsWith(KGlobalSettings::trashPath()))
00719 isIntoTrash = true;
00720 }
00721 if ( properties->kurl().protocol().find("device", 0, false)==0)
00722 isDevice = true;
00723
00724 if ( isLocal )
00725 path = properties->kurl().path();
00726 else
00727 path = properties->kurl().prettyURL();
00728 } else {
00729 path = properties->currentDir().path(1) + properties->defaultName();
00730 directory = properties->currentDir().prettyURL();
00731 }
00732
00733 if (KExecPropsPlugin::supports(properties->items()) ||
00734 d->bDesktopFile ||
00735 KBindingPropsPlugin::supports(properties->items())) {
00736
00737 determineRelativePath( path );
00738
00739 }
00740
00741 }
00742 else
00743 {
00744
00745 KFileItemList items = properties->items();
00746 KFileItemListIterator it( items );
00747 for ( ++it ; it.current(); ++it )
00748 {
00749 KURL url = (*it)->url();
00750 kdDebug(250) << "KFilePropsPlugin::KFilePropsPlugin " << url.prettyURL() << endl;
00751
00752
00753 if ( url.isLocalFile() != isLocal )
00754 isLocal = false;
00755 if ( bDesktopFile && isDesktopFile(*it) != bDesktopFile )
00756 bDesktopFile = false;
00757 if ( (*it)->mode() != mode )
00758 mode = (mode_t)0;
00759 if ( KMimeType::iconForURL(url, mode) != iconStr )
00760 iconStr = "kmultiple";
00761 if ( url.directory() != directory )
00762 directory = QString::null;
00763 if ( url.protocol() != protocol )
00764 protocol = QString::null;
00765 if ( !mimeComment.isNull() && (*it)->mimeComment() != mimeComment )
00766 mimeComment = QString::null;
00767 if ( isLocal && !magicMimeComment.isNull() ) {
00768 KMimeType::Ptr magicMimeType = KMimeType::findByFileContent( url.path() );
00769 if ( magicMimeType->comment() != magicMimeComment )
00770 magicMimeComment = QString::null;
00771 }
00772
00773 if ( isLocal && url.path() == QString::fromLatin1("/") )
00774 hasRoot = true;
00775 if ( (*it)->isDir() && !(*it)->isLink() )
00776 {
00777 iDirCount++;
00778 hasDirs = true;
00779 }
00780 else
00781 {
00782 iFileCount++;
00783 totalSize += (*it)->size();
00784 }
00785 }
00786 }
00787
00788 if (!isLocal && !protocol.isEmpty())
00789 {
00790 directory += ' ';
00791 directory += '(';
00792 directory += protocol;
00793 directory += ')';
00794 }
00795
00796 if ( !isDevice && !isIntoTrash && (bDesktopFile || S_ISDIR(mode)) && !d->bMultiple )
00797 {
00798 KIconButton *iconButton = new KIconButton( d->m_frame );
00799 int bsize = 66 + 2 * iconButton->style().pixelMetric(QStyle::PM_ButtonMargin);
00800 iconButton->setFixedSize(bsize, bsize);
00801 iconButton->setStrictIconSize(false);
00802
00803
00804 QString iconStr = KMimeType::findByURL( properties->kurl(),
00805 mode )->icon( properties->kurl(),
00806 isLocal );
00807 if ( bDesktopFile && isLocal )
00808 {
00809 KDesktopFile config( properties->kurl().path(), true );
00810 config.setDesktopGroup();
00811 iconStr = config.readEntry( "Icon" );
00812 if ( config.hasDeviceType() )
00813 iconButton->setIconType( KIcon::Desktop, KIcon::Device );
00814 else
00815 iconButton->setIconType( KIcon::Desktop, KIcon::Application );
00816 } else
00817 iconButton->setIconType( KIcon::Desktop, KIcon::FileSystem );
00818 iconButton->setIcon(iconStr);
00819 iconArea = iconButton;
00820 connect( iconButton, SIGNAL( iconChanged(QString) ),
00821 this, SLOT( slotIconChanged() ) );
00822 } else {
00823 QLabel *iconLabel = new QLabel( d->m_frame );
00824 int bsize = 66 + 2 * iconLabel->style().pixelMetric(QStyle::PM_ButtonMargin);
00825 iconLabel->setFixedSize(bsize, bsize);
00826 iconLabel->setPixmap( DesktopIcon( iconStr ) );
00827 iconArea = iconLabel;
00828 }
00829 grid->addWidget(iconArea, curRow, 0, AlignLeft);
00830
00831 if (d->bMultiple || isTrash || isIntoTrash || isDevice || filename == QString::fromLatin1("/"))
00832 {
00833 QLabel *lab = new QLabel(d->m_frame );
00834 if ( d->bMultiple )
00835 lab->setText( KIO::itemsSummaryString( iFileCount + iDirCount, iFileCount, iDirCount, 0, false ) );
00836 else
00837 lab->setText( filename );
00838 nameArea = lab;
00839 } else
00840 {
00841 d->m_lined = new KLineEdit( d->m_frame );
00842 d->m_lined->setText(filename);
00843 nameArea = d->m_lined;
00844 d->m_lined->setFocus();
00845 connect( d->m_lined, SIGNAL( textChanged( const QString & ) ),
00846 this, SLOT( nameFileChanged(const QString & ) ) );
00847 }
00848
00849 grid->addWidget(nameArea, curRow++, 2);
00850
00851 KSeparator* sep = new KSeparator( KSeparator::HLine, d->m_frame);
00852 grid->addMultiCellWidget(sep, curRow, curRow, 0, 2);
00853 ++curRow;
00854
00855 QLabel *l;
00856 if ( !mimeComment.isEmpty() && !isDevice && !isIntoTrash)
00857 {
00858 l = new QLabel(i18n("Type:"), d->m_frame );
00859
00860 grid->addWidget(l, curRow, 0);
00861
00862 QHBox *box = new QHBox(d->m_frame);
00863 l = new QLabel(mimeComment, box );
00864
00865 QPushButton *button = new QPushButton(box);
00866
00867 QIconSet iconSet = SmallIconSet(QString::fromLatin1("configure"));
00868 QPixmap pixMap = iconSet.pixmap( QIconSet::Small, QIconSet::Normal );
00869 button->setIconSet( iconSet );
00870 button->setFixedSize( pixMap.width()+8, pixMap.height()+8 );
00871 QToolTip::add(button, i18n("Edit file type"));
00872
00873 connect( button, SIGNAL( clicked() ), SLOT( slotEditFileType() ));
00874
00875
00876 grid->addWidget(box, curRow++, 2);
00877 }
00878
00879 if ( !magicMimeComment.isEmpty() && magicMimeComment != mimeComment )
00880 {
00881 l = new QLabel(i18n("Contents:"), d->m_frame );
00882 grid->addWidget(l, curRow, 0);
00883
00884 l = new QLabel(magicMimeComment, d->m_frame );
00885 grid->addWidget(l, curRow++, 2);
00886 }
00887
00888 if ( !directory.isEmpty() )
00889 {
00890 l = new QLabel( i18n("Location:"), d->m_frame );
00891 grid->addWidget(l, curRow, 0);
00892
00893 l = new KSqueezedTextLabel( d->m_frame );
00894 l->setText( directory );
00895 grid->addWidget(l, curRow++, 2);
00896 }
00897
00898 l = new QLabel(i18n("Size:"), d->m_frame );
00899 grid->addWidget(l, curRow, 0);
00900
00901 m_sizeLabel = new QLabel( d->m_frame );
00902 grid->addWidget( m_sizeLabel, curRow++, 2 );
00903
00904 if ( !hasDirs )
00905 {
00906 m_sizeLabel->setText(QString::fromLatin1("%1 (%2)").arg(KIO::convertSize(totalSize))
00907 .arg(KGlobal::locale()->formatNumber(totalSize, 0)));
00908 m_sizeDetermineButton = 0L;
00909 m_sizeStopButton = 0L;
00910 }
00911 else
00912 {
00913 QHBoxLayout * sizelay = new QHBoxLayout(KDialog::spacingHint());
00914 grid->addLayout( sizelay, curRow++, 2 );
00915
00916
00917 m_sizeDetermineButton = new QPushButton( i18n("Calculate"), d->m_frame );
00918 m_sizeStopButton = new QPushButton( i18n("Stop"), d->m_frame );
00919 connect( m_sizeDetermineButton, SIGNAL( clicked() ), this, SLOT( slotSizeDetermine() ) );
00920 connect( m_sizeStopButton, SIGNAL( clicked() ), this, SLOT( slotSizeStop() ) );
00921 sizelay->addWidget(m_sizeDetermineButton, 0);
00922 sizelay->addWidget(m_sizeStopButton, 0);
00923 sizelay->addStretch(10);
00924
00925
00926 if ( isLocal && !hasRoot )
00927 {
00928 m_sizeDetermineButton->setText( i18n("Refresh") );
00929 slotSizeDetermine();
00930 }
00931 else
00932 m_sizeStopButton->setEnabled( false );
00933 }
00934
00935 if ( isLocal )
00936 {
00937 QString mountPoint = KIO::findPathMountPoint( properties->item()->url().path() );
00938
00939 if (mountPoint != "/")
00940 {
00941 l = new QLabel(i18n("Mounted on:"), d->m_frame );
00942 grid->addWidget(l, curRow, 0);
00943
00944 l = new KSqueezedTextLabel( mountPoint, d->m_frame );
00945 grid->addWidget( l, curRow++, 2 );
00946 }
00947
00948 l = new QLabel(i18n("Free disk space:"), d->m_frame );
00949 grid->addWidget(l, curRow, 0);
00950
00951 d->m_freeSpaceLabel = new QLabel( d->m_frame );
00952 grid->addWidget( d->m_freeSpaceLabel, curRow++, 2 );
00953
00954 KDiskFreeSp * job = new KDiskFreeSp;
00955 connect( job, SIGNAL( foundMountPoint( const unsigned long&, const unsigned long&,
00956 const unsigned long&, const QString& ) ),
00957 this, SLOT( slotFoundMountPoint( const unsigned long&, const unsigned long&,
00958 const unsigned long&, const QString& ) ) );
00959 job->readDF( mountPoint );
00960 }
00961
00962 if (!d->bMultiple && item->isLink()) {
00963 l = new QLabel(i18n("Points to:"), d->m_frame );
00964 grid->addWidget(l, curRow, 0);
00965
00966 l = new QLabel(item->linkDest(), d->m_frame );
00967 grid->addWidget(l, curRow++, 2);
00968 }
00969
00970 if (!d->bMultiple)
00971 {
00972 sep = new KSeparator( KSeparator::HLine, d->m_frame);
00973 grid->addMultiCellWidget(sep, curRow, curRow, 0, 2);
00974 ++curRow;
00975
00976 QDateTime dt;
00977 time_t tim = item->time(KIO::UDS_CREATION_TIME);
00978 if ( tim )
00979 {
00980 l = new QLabel(i18n("Created:"), d->m_frame );
00981 grid->addWidget(l, curRow, 0);
00982
00983 dt.setTime_t( tim );
00984 l = new QLabel(KGlobal::locale()->formatDateTime(dt), d->m_frame );
00985 grid->addWidget(l, curRow++, 2);
00986 }
00987
00988 tim = item->time(KIO::UDS_MODIFICATION_TIME);
00989 if ( tim )
00990 {
00991 l = new QLabel(i18n("Modified:"), d->m_frame );
00992 grid->addWidget(l, curRow, 0);
00993
00994 dt.setTime_t( tim );
00995 l = new QLabel(KGlobal::locale()->formatDateTime(dt), d->m_frame );
00996 grid->addWidget(l, curRow++, 2);
00997 }
00998
00999 tim = item->time(KIO::UDS_ACCESS_TIME);
01000 if ( tim )
01001 {
01002 l = new QLabel(i18n("Accessed:"), d->m_frame );
01003 grid->addWidget(l, curRow, 0);
01004
01005 dt.setTime_t( tim );
01006 l = new QLabel(KGlobal::locale()->formatDateTime(dt), d->m_frame );
01007 grid->addWidget(l, curRow++, 2);
01008 }
01009 }
01010 vbl->addStretch(1);
01011 }
01012
01013
01014
01015
01016
01017
01018 void KFilePropsPlugin::setFileNameReadOnly( bool ro )
01019 {
01020 if ( d->m_lined )
01021 d->m_lined->setReadOnly( ro );
01022 }
01023
01024 void KFilePropsPlugin::slotEditFileType()
01025 {
01026 QString keditfiletype = QString::fromLatin1("keditfiletype");
01027 KRun::runCommand( keditfiletype
01028 + " --parent " + QString::number( properties->topLevelWidget()->winId())
01029 + " " + KProcess::quote(d->mimeType),
01030 keditfiletype, keditfiletype );
01031 }
01032
01033 void KFilePropsPlugin::slotIconChanged()
01034 {
01035 d->bIconChanged = true;
01036 emit changed();
01037 }
01038
01039 void KFilePropsPlugin::nameFileChanged(const QString &text )
01040 {
01041 properties->enableButtonOK(!text.isEmpty());
01042 emit changed();
01043 }
01044
01045 void KFilePropsPlugin::determineRelativePath( const QString & path )
01046 {
01047
01048 QStringList dirs;
01049 if (KBindingPropsPlugin::supports(properties->items()))
01050 {
01051 m_sRelativePath =KGlobal::dirs()->relativeLocation("mime", path);
01052 if (m_sRelativePath.startsWith("/"))
01053 m_sRelativePath = QString::null;
01054 }
01055 else
01056 {
01057 m_sRelativePath =KGlobal::dirs()->relativeLocation("apps", path);
01058 if (m_sRelativePath.startsWith("/"))
01059 {
01060 m_sRelativePath =KGlobal::dirs()->relativeLocation("xdgdata-apps", path);
01061 if (m_sRelativePath.startsWith("/"))
01062 m_sRelativePath = QString::null;
01063 else
01064 m_sRelativePath = path;
01065 }
01066 }
01067 if ( m_sRelativePath.isEmpty() )
01068 {
01069 if (KBindingPropsPlugin::supports(properties->items()))
01070 kdWarning(250) << "Warning : editing a mimetype file out of the mimetype dirs!" << endl;
01071 }
01072 }
01073
01074 void KFilePropsPlugin::slotFoundMountPoint( const QString&,
01075 unsigned long kBSize,
01076 unsigned long ,
01077 unsigned long kBAvail )
01078 {
01079 d->m_freeSpaceLabel->setText(
01080 i18n("Available space out of total partition size (percent used)", "%1 out of %2 (%3% used)")
01081 .arg(KIO::convertSizeFromKB(kBAvail))
01082 .arg(KIO::convertSizeFromKB(kBSize))
01083 .arg( 100 - (int)(100.0 * kBAvail / kBSize) ));
01084 }
01085
01086
01087
01088 void KFilePropsPlugin::slotFoundMountPoint( const unsigned long& kBSize,
01089 const unsigned long& ,
01090 const unsigned long& kBAvail,
01091 const QString& )
01092 {
01093 d->m_freeSpaceLabel->setText(
01094 i18n("Available space out of total partition size (percent used)", "%1 out of %2 (%3% used)")
01095 .arg(KIO::convertSizeFromKB(kBAvail))
01096 .arg(KIO::convertSizeFromKB(kBSize))
01097 .arg( 100 - (int)(100.0 * kBAvail / kBSize) ));
01098 }
01099
01100 void KFilePropsPlugin::slotDirSizeUpdate()
01101 {
01102 KIO::filesize_t totalSize = d->dirSizeJob->totalSize();
01103 m_sizeLabel->setText( i18n("Calculating... %1 (%2)")
01104 .arg(KIO::convertSize(totalSize))
01105 .arg(KGlobal::locale()->formatNumber(totalSize, 0)) );
01106 }
01107
01108 void KFilePropsPlugin::slotDirSizeFinished( KIO::Job * job )
01109 {
01110 if (job->error())
01111 m_sizeLabel->setText( job->errorString() );
01112 else
01113 {
01114 KIO::filesize_t totalSize = static_cast<KDirSize*>(job)->totalSize();
01115 m_sizeLabel->setText( QString::fromLatin1("%1 (%2)")
01116 .arg(KIO::convertSize(totalSize))
01117 .arg(KGlobal::locale()->formatNumber(totalSize, 0)) );
01118 }
01119 m_sizeStopButton->setEnabled(false);
01120
01121 m_sizeDetermineButton->setText( i18n("Refresh") );
01122 m_sizeDetermineButton->setEnabled(true);
01123 d->dirSizeJob = 0L;
01124 delete d->dirSizeUpdateTimer;
01125 d->dirSizeUpdateTimer = 0L;
01126 }
01127
01128 void KFilePropsPlugin::slotSizeDetermine()
01129 {
01130 m_sizeLabel->setText( i18n("Calculating...") );
01131 kdDebug(250) << " KFilePropsPlugin::slotSizeDetermine() properties->item()=" << properties->item() << endl;
01132 kdDebug(250) << " URL=" << properties->item()->url().url() << endl;
01133 d->dirSizeJob = KDirSize::dirSizeJob( properties->items() );
01134 d->dirSizeUpdateTimer = new QTimer(this);
01135 connect( d->dirSizeUpdateTimer, SIGNAL( timeout() ),
01136 SLOT( slotDirSizeUpdate() ) );
01137 d->dirSizeUpdateTimer->start(500);
01138 connect( d->dirSizeJob, SIGNAL( result( KIO::Job * ) ),
01139 SLOT( slotDirSizeFinished( KIO::Job * ) ) );
01140 m_sizeStopButton->setEnabled(true);
01141 m_sizeDetermineButton->setEnabled(false);
01142 }
01143
01144 void KFilePropsPlugin::slotSizeStop()
01145 {
01146 if ( d->dirSizeJob )
01147 {
01148 m_sizeLabel->setText( i18n("Stopped") );
01149 d->dirSizeJob->kill();
01150 d->dirSizeJob = 0;
01151 }
01152 if ( d->dirSizeUpdateTimer )
01153 d->dirSizeUpdateTimer->stop();
01154
01155 m_sizeStopButton->setEnabled(false);
01156 m_sizeDetermineButton->setEnabled(true);
01157 }
01158
01159 KFilePropsPlugin::~KFilePropsPlugin()
01160 {
01161 delete d;
01162 }
01163
01164 bool KFilePropsPlugin::supports( KFileItemList )
01165 {
01166 return true;
01167 }
01168
01169
01170 void qt_enter_modal( QWidget *widget );
01171 void qt_leave_modal( QWidget *widget );
01172
01173 void KFilePropsPlugin::applyChanges()
01174 {
01175 if ( d->dirSizeJob )
01176 slotSizeStop();
01177
01178 kdDebug(250) << "KFilePropsPlugin::applyChanges" << endl;
01179
01180 if (nameArea->inherits("QLineEdit"))
01181 {
01182 QString n = ((QLineEdit *) nameArea)->text();
01183
01184 while ( n[n.length()-1].isSpace() )
01185 n.truncate( n.length() - 1 );
01186 if ( n.isEmpty() )
01187 {
01188 KMessageBox::sorry( properties, i18n("The new file name is empty!"));
01189 properties->abortApplying();
01190 return;
01191 }
01192
01193
01194 kdDebug(250) << "oldname = " << oldName << endl;
01195 kdDebug(250) << "newname = " << n << endl;
01196 if ( oldName != n || m_bFromTemplate ) {
01197 KIO::Job * job = 0L;
01198 KURL oldurl = properties->kurl();
01199
01200 QString newFileName = KIO::encodeFileName(n);
01201 if (d->bDesktopFile && !newFileName.endsWith(".desktop") && !newFileName.endsWith(".kdelnk"))
01202 newFileName += ".desktop";
01203
01204
01205 properties->rename( newFileName );
01206
01207
01208 if ( !m_sRelativePath.isEmpty() )
01209 determineRelativePath( properties->kurl().path() );
01210
01211 kdDebug(250) << "New URL = " << properties->kurl().url() << endl;
01212 kdDebug(250) << "old = " << oldurl.url() << endl;
01213
01214
01215 if ( !m_bFromTemplate )
01216 job = KIO::move( oldurl, properties->kurl() );
01217 else
01218 job = KIO::copy( oldurl, properties->kurl() );
01219
01220 connect( job, SIGNAL( result( KIO::Job * ) ),
01221 SLOT( slotCopyFinished( KIO::Job * ) ) );
01222 connect( job, SIGNAL( renamed( KIO::Job *, const KURL &, const KURL & ) ),
01223 SLOT( slotFileRenamed( KIO::Job *, const KURL &, const KURL & ) ) );
01224
01225 QWidget dummy(0,0,WType_Dialog|WShowModal);
01226 qt_enter_modal(&dummy);
01227 qApp->enter_loop();
01228 qt_leave_modal(&dummy);
01229 return;
01230 }
01231 }
01232
01233
01234 slotCopyFinished( 0L );
01235 }
01236
01237 void KFilePropsPlugin::slotCopyFinished( KIO::Job * job )
01238 {
01239 kdDebug(250) << "KFilePropsPlugin::slotCopyFinished" << endl;
01240 if (job)
01241 {
01242
01243 qApp->exit_loop();
01244 if ( job->error() )
01245 {
01246 job->showErrorDialog( d->m_frame );
01247
01248 properties->updateUrl( static_cast<KIO::CopyJob*>(job)->srcURLs().first() );
01249 properties->abortApplying();
01250 return;
01251 }
01252 }
01253
01254 assert( properties->item() );
01255 assert( !properties->item()->url().isEmpty() );
01256
01257
01258 if (KBindingPropsPlugin::supports(properties->items()) && !m_sRelativePath.isEmpty())
01259 {
01260 KURL newURL;
01261 newURL.setPath( locateLocal("mime", m_sRelativePath) );
01262 properties->updateUrl( newURL );
01263 }
01264 else if (d->bDesktopFile && !m_sRelativePath.isEmpty())
01265 {
01266 kdDebug(250) << "KFilePropsPlugin::slotCopyFinished " << m_sRelativePath << endl;
01267 KURL newURL;
01268 newURL.setPath( KDesktopFile::locateLocal(m_sRelativePath) );
01269 kdDebug(250) << "KFilePropsPlugin::slotCopyFinished path=" << newURL.path() << endl;
01270 properties->updateUrl( newURL );
01271 }
01272
01273 if ( d->bKDesktopMode && d->bDesktopFile ) {
01274
01275 if ( d->oldFileName != properties->kurl().fileName() || m_bFromTemplate ) {
01276 KDesktopFile config( properties->kurl().path() );
01277 QString nameStr = nameFromFileName(properties->kurl().fileName());
01278 config.writeEntry( "Name", nameStr );
01279 config.writeEntry( "Name", nameStr, true, false, true );
01280 }
01281 }
01282 }
01283
01284 void KFilePropsPlugin::applyIconChanges()
01285 {
01286
01287
01288 if (!iconArea->isA(