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