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.startsWith("/"))
01166 {
01167 m_sRelativePath =KGlobal::dirs()->relativeLocation("xdgdata-apps", path);
01168 if (m_sRelativePath.startsWith("/"))
01169 m_sRelativePath = QString::null;
01170 else
01171 m_sRelativePath = path;
01172 }
01173 }
01174 if ( m_sRelativePath.isEmpty() )
01175 {
01176 if (KBindingPropsPlugin::supports(properties->items()))
01177 kdWarning(250) << "Warning : editing a mimetype file out of the mimetype dirs!" << endl;
01178 }
01179 }
01180
01181 void KFilePropsPlugin::slotFoundMountPoint( const QString&,
01182 unsigned long kBSize,
01183 unsigned long ,
01184 unsigned long kBAvail )
01185 {
01186 d->m_freeSpaceLabel->setText(
01187
01188 i18n("Available space out of total partition size (percent used)", "%1 out of %2 (%3% used)")
01189 .arg(KIO::convertSizeFromKB(kBAvail))
01190 .arg(KIO::convertSizeFromKB(kBSize))
01191 .arg( 100 - (int)(100.0 * kBAvail / kBSize) ));
01192 }
01193
01194
01195
01196 void KFilePropsPlugin::slotFoundMountPoint( const unsigned long& kBSize,
01197 const unsigned long& ,
01198 const unsigned long& kBAvail,
01199 const QString& )
01200 {
01201 d->m_freeSpaceLabel->setText(
01202
01203 i18n("Available space out of total partition size (percent used)", "%1 out of %2 (%3% used)")
01204 .arg(KIO::convertSizeFromKB(kBAvail))
01205 .arg(KIO::convertSizeFromKB(kBSize))
01206 .arg( 100 - (int)(100.0 * kBAvail / kBSize) ));
01207 }
01208
01209 void KFilePropsPlugin::slotDirSizeUpdate()
01210 {
01211 KIO::filesize_t totalSize = d->dirSizeJob->totalSize();
01212 KIO::filesize_t totalFiles = d->dirSizeJob->totalFiles();
01213 KIO::filesize_t totalSubdirs = d->dirSizeJob->totalSubdirs();
01214 m_sizeLabel->setText( i18n("Calculating... %1 (%2)\n%3, %4")
01215 .arg(KIO::convertSize(totalSize))
01216 .arg(KGlobal::locale()->formatNumber(totalSize, 0))
01217 .arg(i18n("1 file","%n files",totalFiles))
01218 .arg(i18n("1 sub-folder","%n sub-folders",totalSubdirs)));
01219 }
01220
01221 void KFilePropsPlugin::slotDirSizeFinished( KIO::Job * job )
01222 {
01223 if (job->error())
01224 m_sizeLabel->setText( job->errorString() );
01225 else
01226 {
01227 KIO::filesize_t totalSize = static_cast<KDirSize*>(job)->totalSize();
01228 KIO::filesize_t totalFiles = static_cast<KDirSize*>(job)->totalFiles();
01229 KIO::filesize_t totalSubdirs = static_cast<KDirSize*>(job)->totalSubdirs();
01230 m_sizeLabel->setText( QString::fromLatin1("%1 (%2)\n%3, %4")
01231 .arg(KIO::convertSize(totalSize))
01232 .arg(KGlobal::locale()->formatNumber(totalSize, 0))
01233 .arg(i18n("1 file","%n files",totalFiles))
01234 .arg(i18n("1 sub-folder","%n sub-folders",totalSubdirs)));
01235 }
01236 m_sizeStopButton->setEnabled(false);
01237
01238 m_sizeDetermineButton->setText( i18n("Refresh") );
01239 m_sizeDetermineButton->setEnabled(true);
01240 d->dirSizeJob = 0L;
01241 delete d->dirSizeUpdateTimer;
01242 d->dirSizeUpdateTimer = 0L;
01243 }
01244
01245 void KFilePropsPlugin::slotSizeDetermine()
01246 {
01247 m_sizeLabel->setText( i18n("Calculating...") );
01248 kdDebug(250) << " KFilePropsPlugin::slotSizeDetermine() properties->item()=" << properties->item() << endl;
01249 kdDebug(250) << " URL=" << properties->item()->url().url() << endl;
01250 d->dirSizeJob = KDirSize::dirSizeJob( properties->items() );
01251 d->dirSizeUpdateTimer = new QTimer(this);
01252 connect( d->dirSizeUpdateTimer, SIGNAL( timeout() ),
01253 SLOT( slotDirSizeUpdate() ) );
01254 d->dirSizeUpdateTimer->start(500);
01255 connect( d->dirSizeJob, SIGNAL( result( KIO::Job * ) ),
01256 SLOT( slotDirSizeFinished( KIO::Job * ) ) );
01257 m_sizeStopButton->setEnabled(true);
01258 m_sizeDetermineButton->setEnabled(false);
01259 }
01260
01261 void KFilePropsPlugin::slotSizeStop()
01262 {
01263 if ( d->dirSizeJob )
01264 {
01265 m_sizeLabel->setText( i18n("Stopped") );
01266 d->dirSizeJob->kill();
01267 d->dirSizeJob = 0;
01268 }
01269 if ( d->dirSizeUpdateTimer )
01270 d->dirSizeUpdateTimer->stop();
01271
01272 m_sizeStopButton->setEnabled(false);
01273 m_sizeDetermineButton->setEnabled(true);
01274 }
01275
01276 KFilePropsPlugin::~KFilePropsPlugin()
01277 {
01278 delete d;
01279 }
01280
01281 bool KFilePropsPlugin::supports( KFileItemList )
01282 {
01283 return true;
01284 }
01285
01286
01287 void qt_enter_modal( QWidget *widget );
01288 void qt_leave_modal( QWidget *widget );
01289
01290 void KFilePropsPlugin::applyChanges()
01291 {
01292 if ( d->dirSizeJob )
01293 slotSizeStop();
01294
01295 kdDebug(250) << "KFilePropsPlugin::applyChanges" << endl;
01296
01297 if (nameArea->inherits("QLineEdit"))
01298 {
01299 QString n = ((QLineEdit *) nameArea)->text();
01300
01301 while ( n[n.length()-1].isSpace() )
01302 n.truncate( n.length() - 1 );
01303 if ( n.isEmpty() )
01304 {
01305 KMessageBox::sorry( properties, i18n("The new file name is empty."));
01306 properties->abortApplying();
01307 return;
01308 }
01309
01310
01311 kdDebug(250) << "oldname = " << oldName << endl;
01312 kdDebug(250) << "newname = " << n << endl;
01313 if ( oldName != n || m_bFromTemplate ) {
01314 KIO::Job * job = 0L;
01315 KURL oldurl = properties->kurl();
01316
01317 QString newFileName = KIO::encodeFileName(n);
01318 if (d->bDesktopFile && !newFileName.endsWith(".desktop") && !newFileName.endsWith(".kdelnk"))
01319 newFileName += ".desktop";
01320
01321
01322 properties->rename( newFileName );
01323
01324
01325 if ( !m_sRelativePath.isEmpty() )
01326 determineRelativePath( properties->kurl().path() );
01327
01328 kdDebug(250) << "New URL = " << properties->kurl().url() << endl;
01329 kdDebug(250) << "old = " << oldurl.url() << endl;
01330
01331
01332 if ( !m_bFromTemplate )
01333 job = KIO::move( oldurl, properties->kurl() );
01334 else
01335 job = KIO::copy( oldurl, properties->kurl() );
01336
01337 connect( job, SIGNAL( result( KIO::Job * ) ),
01338 SLOT( slotCopyFinished( KIO::Job * ) ) );
01339 connect( job, SIGNAL( renamed( KIO::Job *, const KURL &, const KURL & ) ),
01340 SLOT( slotFileRenamed( KIO::Job *, const KURL &, const KURL & ) ) );
01341
01342 QWidget dummy(0,0,WType_Dialog|WShowModal);
01343 qt_enter_modal(&dummy);
01344 qApp->enter_loop();
01345 qt_leave_modal(&dummy);
01346 return;
01347 }
01348 properties->updateUrl(properties->kurl());
01349
01350 if ( !m_sRelativePath.isEmpty() )
01351 determineRelativePath( properties->kurl().path() );
01352 }
01353
01354
01355 slotCopyFinished( 0L );
01356 }
01357
01358 void KFilePropsPlugin::slotCopyFinished( KIO::Job * job )
01359 {
01360 kdDebug(250) << "KFilePropsPlugin::slotCopyFinished" << endl;
01361 if (job)
01362 {
01363
01364 qApp->exit_loop();
01365 if ( job->error() )
01366 {
01367 job->showErrorDialog( d->m_frame );
01368
01369 properties->updateUrl( static_cast<KIO::CopyJob*>(job)->srcURLs().first() );
01370 properties->abortApplying();
01371 return;
01372 }
01373 }
01374
01375 assert( properties->item() );
01376 assert( !properties->item()->url().isEmpty() );
01377
01378
01379 if (KBindingPropsPlugin::supports(properties->items()) && !m_sRelativePath.isEmpty())
01380 {
01381 KURL newURL;
01382 newURL.setPath( locateLocal("mime", m_sRelativePath) );
01383 properties->updateUrl( newURL );
01384 }
01385 else if (d->bDesktopFile && !m_sRelativePath.isEmpty())
01386 {
01387 kdDebug(250) << "KFilePropsPlugin::slotCopyFinished " << m_sRelativePath << endl;
01388 KURL newURL;
01389 newURL.setPath( KDesktopFile::locateLocal(m_sRelativePath) );
01390 kdDebug(250) << "KFilePropsPlugin::slotCopyFinished path=" << newURL.path() << endl;
01391 properties->updateUrl( newURL );
01392 }
01393
01394 if ( d->bKDesktopMode && d->bDesktopFile ) {
01395
01396 if ( d->oldFileName != properties->kurl().fileName() || m_bFromTemplate ) {
01397 KDesktopFile config( properties->kurl().path() );
01398 QString nameStr = nameFromFileName(properties->kurl().fileName());
01399 config.writeEntry( "Name", nameStr );
01400 config.writeEntry( "Name", nameStr, true, false, true );
01401 }
01402 }
01403 }
01404
01405 void KFilePropsPlugin::applyIconChanges()
01406 {
01407 KIconButton *iconButton = ::qt_cast<KIconButton *>( iconArea );
01408 if ( !iconButton || !d->bIconChanged )
01409 return;
01410
01411
01412 KURL url = properties->kurl();
01413 url = KIO::NetAccess::mostLocalURL( url, properties );
01414 if (url.isLocalFile()) {
01415 QString path;
01416
01417 if (S_ISDIR(properties->item()->mode()))
01418 {
01419 path = url.path(1) + QString::fromLatin1(".directory");
01420
01421
01422 }
01423 else
01424 path = url.path();
01425
01426
01427 QString str = KMimeType::findByURL( url,
01428 properties->item()->mode(),
01429 true )->KServiceType::icon();
01430
01431 QString sIcon;
01432 if ( str != iconButton->icon() )
01433 sIcon = iconButton->icon();
01434
01435
01436 kdDebug(250) << "**" << path << "**" << endl;
01437 QFile f( path );
01438
01439
01440 if ( !sIcon.isEmpty() || f.exists() )
01441 {
01442 if ( !f.open( IO_ReadWrite ) ) {
01443 KMessageBox::sorry( 0, i18n("<qt>Could not save properties. You do not "
01444 "have sufficient access to write to <b>%1</b>.</qt>").arg(path));
01445 return;
01446 }
01447 f.close();
01448
01449 KDesktopFile cfg(path);
01450 kdDebug(250) << "sIcon = " << (sIcon) << endl;
01451 kdDebug(250) << "str = " << (str) << endl;
01452 cfg.writeEntry( "Icon", sIcon );
01453 cfg.sync();
01454 }
01455 }
01456 }
01457
01458 void KFilePropsPlugin::slotFileRenamed( KIO::Job *, const KURL &, const KURL & newUrl )
01459 {
01460
01461
01462 properties->updateUrl( newUrl );
01463 }
01464
01465 void KFilePropsPlugin::postApplyChanges()
01466 {
01467
01468 applyIconChanges();
01469
01470 KURL::List lst;
01471 KFileItemList items = properties->items();
01472 for ( KFileItemListIterator it( items ); it.current(); ++it )
01473 lst.append((*it)->url());
01474 KDirNotify_stub allDirNotify("*", "KDirNotify*");
01475 allDirNotify.FilesChanged( lst );
01476 }
01477
01478 class KFilePermissionsPropsPlugin::KFilePermissionsPropsPluginPrivate
01479 {
01480 public:
01481 KFilePermissionsPropsPluginPrivate()
01482 {
01483 }
01484 ~KFilePermissionsPropsPluginPrivate()
01485 {
01486 }
01487
01488 QFrame *m_frame;
01489 QCheckBox *cbRecursive;
01490 QLabel *explanationLabel;
01491 QComboBox *ownerPermCombo, *groupPermCombo, *othersPermCombo;
01492 QCheckBox *extraCheckbox;
01493 mode_t partialPermissions;
01494 KFilePermissionsPropsPlugin::PermissionsMode pmode;
01495 bool canChangePermissions;
01496 bool isIrregular;
01497 bool hasExtendedACL;
01498 KACL extendedACL;
01499 KACL defaultACL;
01500 bool fileSystemSupportsACLs;
01501 };
01502
01503 #define UniOwner (S_IRUSR|S_IWUSR|S_IXUSR)
01504 #define UniGroup (S_IRGRP|S_IWGRP|S_IXGRP)
01505 #define UniOthers (S_IROTH|S_IWOTH|S_IXOTH)
01506 #define UniRead (S_IRUSR|S_IRGRP|S_IROTH)
01507 #define UniWrite (S_IWUSR|S_IWGRP|S_IWOTH)
01508 #define UniExec (S_IXUSR|S_IXGRP|S_IXOTH)
01509 #define UniSpecial (S_ISUID|S_ISGID|S_ISVTX)
01510
01511
01512 const mode_t KFilePermissionsPropsPlugin::permissionsMasks[3] = {UniOwner, UniGroup, UniOthers};
01513 const mode_t KFilePermissionsPropsPlugin::standardPermissions[4] = { 0, UniRead, UniRead|UniWrite, (mode_t)-1 };
01514
01515
01516 const char *KFilePermissionsPropsPlugin::permissionsTexts[4][4] = {
01517 { I18N_NOOP("Forbidden"),
01518 I18N_NOOP("Can Read"),
01519 I18N_NOOP("Can Read & Write"),
01520 0 },
01521 { I18N_NOOP("Forbidden"),
01522 I18N_NOOP("Can View Content"),
01523 I18N_NOOP("Can View & Modify Content"),
01524 0 },
01525 { 0, 0, 0, 0},
01526 { I18N_NOOP("Forbidden"),
01527 I18N_NOOP("Can View Content & Read"),
01528 I18N_NOOP("Can View/Read & Modify/Write"),
01529 0 }
01530 };
01531
01532
01533 KFilePermissionsPropsPlugin::KFilePermissionsPropsPlugin( KPropertiesDialog *_props )
01534 : KPropsDlgPlugin( _props )
01535 {
01536 d = new KFilePermissionsPropsPluginPrivate;
01537 d->cbRecursive = 0L;
01538 grpCombo = 0L; grpEdit = 0;
01539 usrEdit = 0L;
01540 QString path = properties->kurl().path(-1);
01541 QString fname = properties->kurl().fileName();
01542 bool isLocal = properties->kurl().isLocalFile();
01543 bool isTrash = ( properties->kurl().protocol().find("trash", 0, false)==0 );
01544 bool IamRoot = (geteuid() == 0);
01545
01546 KFileItem * item = properties->item();
01547 bool isLink = item->isLink();
01548 bool isDir = item->isDir();
01549 bool hasDir = item->isDir();
01550 permissions = item->permissions();
01551 d->partialPermissions = permissions;
01552 d->isIrregular = isIrregular(permissions, isDir, isLink);
01553 strOwner = item->user();
01554 strGroup = item->group();
01555 d->hasExtendedACL = item->ACL().isExtended() || item->defaultACL().isValid();
01556 d->extendedACL = item->ACL();
01557 d->defaultACL = item->defaultACL();
01558 d->fileSystemSupportsACLs = false;
01559
01560 if ( properties->items().count() > 1 )
01561 {
01562
01563 KFileItemList items = properties->items();
01564 KFileItemListIterator it( items );
01565 for ( ++it ; it.current(); ++it )
01566 {
01567 if (!d->isIrregular)
01568 d->isIrregular |= isIrregular((*it)->permissions(),
01569 (*it)->isDir() == isDir,
01570 (*it)->isLink() == isLink);
01571 d->hasExtendedACL = d->hasExtendedACL || (*it)->hasExtendedACL();
01572 if ( (*it)->isLink() != isLink )
01573 isLink = false;
01574 if ( (*it)->isDir() != isDir )
01575 isDir = false;
01576 hasDir |= (*it)->isDir();
01577 if ( (*it)->permissions() != permissions )
01578 {
01579 permissions &= (*it)->permissions();
01580 d->partialPermissions |= (*it)->permissions();
01581 }
01582 if ( (*it)->user() != strOwner )
01583 strOwner = QString::null;
01584 if ( (*it)->group() != strGroup )
01585 strGroup = QString::null;
01586 }
01587 }
01588
01589 if (isLink)
01590 d->pmode = PermissionsOnlyLinks;
01591 else if (isDir)
01592 d->pmode = PermissionsOnlyDirs;
01593 else if (hasDir)
01594 d->pmode = PermissionsMixed;
01595 else
01596 d->pmode = PermissionsOnlyFiles;
01597
01598
01599 d->partialPermissions = d->partialPermissions & ~permissions;
01600
01601 bool isMyFile = false;
01602
01603 if (isLocal && !strOwner.isEmpty()) {
01604 struct passwd *myself = getpwuid( geteuid() );
01605 if ( myself != 0L )
01606 {
01607 isMyFile = (strOwner == QString::fromLocal8Bit(myself->pw_name));
01608 } else
01609 kdWarning() << "I don't exist ?! geteuid=" << geteuid() << endl;
01610 } else {
01611
01612
01613
01614 isMyFile = true;
01615 }
01616
01617 d->canChangePermissions = (isMyFile || IamRoot) && (!isLink);
01618
01619
01620
01621
01622 d->m_frame = properties->addPage(i18n("&Permissions"));
01623
01624 QBoxLayout *box = new QVBoxLayout( d->m_frame, 0, KDialog::spacingHint() );
01625
01626 QWidget *l;
01627 QLabel *lbl;
01628 QGroupBox *gb;
01629 QGridLayout *gl;
01630 QPushButton* pbAdvancedPerm = 0;
01631
01632
01633 gb = new QGroupBox ( 0, Qt::Vertical, i18n("Access Permissions"), d->m_frame );
01634 gb->layout()->setSpacing(KDialog::spacingHint());
01635 gb->layout()->setMargin(KDialog::marginHint());
01636 box->addWidget (gb);
01637
01638 gl = new QGridLayout (gb->layout(), 7, 2);
01639 gl->setColStretch(1, 1);
01640
01641 l = d->explanationLabel = new QLabel( "", gb );
01642 if (isLink)
01643 d->explanationLabel->setText(i18n("This file is a link and does not have permissions.",
01644 "All files are links and do not have permissions.",
01645 properties->items().count()));
01646 else if (!d->canChangePermissions)
01647 d->explanationLabel->setText(i18n("Only the owner can change permissions."));
01648 gl->addMultiCellWidget(l, 0, 0, 0, 1);
01649
01650 lbl = new QLabel( i18n("O&wner:"), gb);
01651 gl->addWidget(lbl, 1, 0);
01652 l = d->ownerPermCombo = new QComboBox(gb);
01653 lbl->setBuddy(l);
01654 gl->addWidget(l, 1, 1);
01655 connect(l, SIGNAL( highlighted(int) ), this, SIGNAL( changed() ));
01656 QWhatsThis::add(l, i18n("Specifies the actions that the owner is allowed to do."));
01657
01658 lbl = new QLabel( i18n("Gro&up:"), gb);
01659 gl->addWidget(lbl, 2, 0);
01660 l = d->groupPermCombo = new QComboBox(gb);
01661 lbl->setBuddy(l);
01662 gl->addWidget(l, 2, 1);
01663 connect(l, SIGNAL( highlighted(int) ), this, SIGNAL( changed() ));
01664 QWhatsThis::add(l, i18n("Specifies the actions that the members of the group are allowed to do."));
01665
01666 lbl = new QLabel( i18n("O&thers:"), gb);
01667 gl->addWidget(lbl, 3, 0);
01668 l = d->othersPermCombo = new QComboBox(gb);
01669 lbl->setBuddy(l);
01670 gl->addWidget(l, 3, 1);
01671 connect(l, SIGNAL( highlighted(int) ), this, SIGNAL( changed() ));
01672 QWhatsThis::add(l, i18n("Specifies the actions that all users, who are neither "
01673 "owner nor in the group, are allowed to do."));
01674
01675 if (!isLink) {
01676 l = d->extraCheckbox = new QCheckBox(hasDir ?
01677 i18n("Only own&er can rename and delete folder content") :
01678 i18n("Is &executable"),
01679 gb );
01680 connect( d->extraCheckbox, SIGNAL( clicked() ), this, SIGNAL( changed() ) );
01681 gl->addWidget(l, 4, 1);
01682 QWhatsThis::add(l, hasDir ? i18n("Enable this option to allow only the folder's owner to "
01683 "delete or rename the contained files and folders. Other "
01684 "users can only add new files, which requires the 'Modify "
01685 "Content' permission.")
01686 : i18n("Enable this option to mark the file as executable. This only makes "
01687 "sense for programs and scripts. It is required when you want to "
01688 "execute them."));
01689
01690 QLayoutItem *spacer = new QSpacerItem(0, 20, QSizePolicy::Minimum, QSizePolicy::Expanding);
01691 gl->addMultiCell(spacer, 5, 5, 0, 1);
01692
01693 pbAdvancedPerm = new QPushButton(i18n("A&dvanced Permissions"), gb);
01694 gl->addMultiCellWidget(pbAdvancedPerm, 6, 6, 0, 1, AlignRight);
01695 connect(pbAdvancedPerm, SIGNAL( clicked() ), this, SLOT( slotShowAdvancedPermissions() ));
01696 }
01697 else
01698 d->extraCheckbox = 0;
01699
01700
01701
01702 gb = new QGroupBox ( 0, Qt::Vertical, i18n("Ownership"), d->m_frame );
01703 gb->layout()->setSpacing(KDialog::spacingHint());
01704 gb->layout()->setMargin(KDialog::marginHint());
01705 box->addWidget (gb);
01706
01707 gl = new QGridLayout (gb->layout(), 4, 3);
01708 gl->addRowSpacing(0, 10);
01709
01710
01711 l = new QLabel( i18n("User:"), gb );
01712 gl->addWidget (l, 1, 0);
01713
01714
01715
01716
01717
01718
01719 int i, maxEntries = 1000;
01720 struct passwd *user;
01721 struct group *ge;
01722
01723
01724
01725
01726 if (IamRoot && isLocal)
01727 {
01728 usrEdit = new KLineEdit( gb );
01729 KCompletion *kcom = usrEdit->completionObject();
01730 kcom->setOrder(KCompletion::Sorted);
01731 setpwent();
01732 for (i=0; ((user = getpwent()) != 0L) && (i < maxEntries); i++)
01733 kcom->addItem(QString::fromLatin1(user->pw_name));
01734 endpwent();
01735 usrEdit->setCompletionMode((i < maxEntries) ? KGlobalSettings::CompletionAuto :
01736 KGlobalSettings::CompletionNone);
01737 usrEdit->setText(strOwner);
01738 gl->addWidget(usrEdit, 1, 1);
01739 connect( usrEdit, SIGNAL( textChanged( const QString & ) ),
01740 this, SIGNAL( changed() ) );
01741 }
01742 else
01743 {
01744 l = new QLabel(strOwner, gb);
01745 gl->addWidget(l, 1, 1);
01746 }
01747
01748
01749
01750 QStringList groupList;
01751 QCString strUser;
01752 user = getpwuid(geteuid());
01753 if (user != 0L)
01754 strUser = user->pw_name;
01755
01756 #ifdef Q_OS_UNIX
01757 setgrent();
01758 for (i=0; ((ge = getgrent()) != 0L) && (i < maxEntries); i++)
01759 {
01760 if (IamRoot)
01761 groupList += QString::fromLatin1(ge->gr_name);
01762 else
01763 {
01764
01765 char ** members = ge->gr_mem;
01766 char * member;
01767 while ((member = *members) != 0L) {
01768 if (strUser == member) {
01769 groupList += QString::fromLocal8Bit(ge->gr_name);
01770 break;
01771 }
01772 ++members;
01773 }
01774 }
01775 }
01776 endgrent();
01777 #endif //Q_OS_UNIX
01778
01779
01780 ge = getgrgid (getegid());
01781 if (ge) {
01782 QString name = QString::fromLatin1(ge->gr_name);
01783 if (name.isEmpty())
01784 name.setNum(ge->gr_gid);
01785 if (groupList.find(name) == groupList.end())
01786 groupList += name;
01787 }
01788
01789 bool isMyGroup = groupList.contains(strGroup);
01790
01791
01792
01793
01794 if (!isMyGroup)
01795 groupList += strGroup;
01796
01797 l = new QLabel( i18n("Group:"), gb );
01798 gl->addWidget (l, 2, 0);
01799
01800
01801
01802
01803
01804
01805
01806 if (IamRoot && isLocal)
01807 {
01808 grpEdit = new KLineEdit(gb);
01809 KCompletion *kcom = new KCompletion;
01810 kcom->setItems(groupList);
01811 grpEdit->setCompletionObject(kcom, true);
01812 grpEdit->setAutoDeleteCompletionObject( true );
01813 grpEdit->setCompletionMode(KGlobalSettings::CompletionAuto);
01814 grpEdit->setText(strGroup);
01815 gl->addWidget(grpEdit, 2, 1);
01816 connect( grpEdit, SIGNAL( textChanged( const QString & ) ),
01817 this, SIGNAL( changed() ) );
01818 }
01819 else if ((groupList.count() > 1) && isMyFile && isLocal)
01820 {
01821 grpCombo = new QComboBox(gb, "combogrouplist");
01822 grpCombo->insertStringList(groupList);
01823 grpCombo->setCurrentItem(groupList.findIndex(strGroup));
01824 gl->addWidget(grpCombo, 2, 1);
01825 connect( grpCombo, SIGNAL( activated( int ) ),
01826 this, SIGNAL( changed() ) );
01827 }
01828 else
01829 {
01830 l = new QLabel(strGroup, gb);
01831 gl->addWidget(l, 2, 1);
01832 }
01833
01834 gl->setColStretch(2, 10);
01835
01836
01837 if ( hasDir && !isLink && !isTrash )
01838 {
01839 d->cbRecursive = new QCheckBox( i18n("Apply changes to all subfolders and their contents"), d->m_frame );
01840 connect( d->cbRecursive, SIGNAL( clicked() ), this, SIGNAL( changed() ) );
01841 box->addWidget( d->cbRecursive );
01842 }
01843
01844 updateAccessControls();
01845
01846
01847 if ( isTrash || !d->canChangePermissions )
01848 {
01849
01850 enableAccessControls(false);
01851 if ( pbAdvancedPerm && !d->hasExtendedACL )
01852 pbAdvancedPerm->setEnabled(false);
01853 }
01854
01855 box->addStretch (10);
01856 }
01857
01858 #ifdef USE_POSIX_ACL
01859 static bool fileSystemSupportsACL( const QCString& pathCString )
01860 {
01861 bool fileSystemSupportsACLs = false;
01862 #ifdef Q_OS_FREEBSD
01863 struct statfs buf;
01864 fileSystemSupportsACLs = ( statfs( pathCString.data(), &buf ) == 0 ) && ( buf.f_flags & MNT_ACLS );
01865 #else
01866 fileSystemSupportsACLs =
01867 getxattr( pathCString.data(), "system.posix_acl_access", NULL, 0 ) >= 0 || errno == ENODATA;
01868 #endif
01869 return fileSystemSupportsACLs;
01870 }
01871 #endif
01872
01873
01874 void KFilePermissionsPropsPlugin::slotShowAdvancedPermissions() {
01875
01876 bool isDir = (d->pmode == PermissionsOnlyDirs) || (d->pmode == PermissionsMixed);
01877 KDialogBase dlg(properties, 0, true, i18n("Advanced Permissions"),
01878 KDialogBase::Ok|KDialogBase::Cancel);
01879
01880 QLabel *l, *cl[3];
01881 QGroupBox *gb;
01882 QGridLayout *gl;
01883
01884 QVBox *mainVBox = dlg.makeVBoxMainWidget();
01885
01886
01887 gb = new QGroupBox ( 0, Qt::Vertical, i18n("Access Permissions"), mainVBox );
01888 gb->layout()->setSpacing(KDialog::spacingHint());
01889 gb->layout()->setMargin(KDialog::marginHint());
01890
01891 gl = new QGridLayout (gb->layout(), 6, 6);
01892 gl->addRowSpacing(0, 10);
01893
01894 QValueVector<QWidget*> theNotSpecials;
01895
01896 l = new QLabel(i18n("Class"), gb );
01897 gl->addWidget(l, 1, 0);
01898 theNotSpecials.append( l );
01899
01900 if (isDir)
01901 l = new QLabel( i18n("Show\nEntries"), gb );
01902 else
01903 l = new QLabel( i18n("Read"), gb );
01904 gl->addWidget (l, 1, 1);
01905 theNotSpecials.append( l );
01906 QString readWhatsThis;
01907 if (isDir)
01908 readWhatsThis = i18n("This flag allows viewing the content of the folder.");
01909 else
01910 readWhatsThis = i18n("The Read flag allows viewing the content of the file.");
01911 QWhatsThis::add(l, readWhatsThis);
01912
01913 if (isDir)
01914 l = new QLabel( i18n("Write\nEntries"), gb );
01915 else
01916 l = new QLabel( i18n("Write"), gb );
01917 gl->addWidget (l, 1, 2);
01918 theNotSpecials.append( l );
01919 QString writeWhatsThis;
01920 if (isDir)
01921 writeWhatsThis = i18n("This flag allows adding, renaming and deleting of files. "
01922 "Note that deleting and renaming can be limited using the Sticky flag.");
01923 else
01924 writeWhatsThis = i18n("The Write flag allows modifying the content of the file.");
01925 QWhatsThis::add(l, writeWhatsThis);
01926
01927 QString execWhatsThis;
01928 if (isDir) {
01929 l = new QLabel( i18n("Enter folder", "Enter"), gb );
01930 execWhatsThis = i18n("Enable this flag to allow entering the folder.");
01931 }
01932 else {
01933 l = new QLabel( i18n("Exec"), gb );
01934 execWhatsThis = i18n("Enable this flag to allow executing the file as a program.");
01935 }
01936 QWhatsThis::add(l, execWhatsThis);
01937 theNotSpecials.append( l );
01938
01939 QSize size = l->sizeHint();
01940 size.setWidth(size.width() + 15);
01941 l->setFixedSize(size);
01942 gl->addWidget (l, 1, 3);
01943
01944 l = new QLabel( i18n("Special"), gb );
01945 gl->addMultiCellWidget(l, 1, 1, 4, 5);
01946 QString specialWhatsThis;
01947 if (isDir)
01948 specialWhatsThis = i18n("Special flag. Valid for the whole folder, the exact "
01949 "meaning of the flag can be seen in the right hand column.");
01950 else
01951 specialWhatsThis = i18n("Special flag. The exact meaning of the flag can be seen "
01952 "in the right hand column.");
01953 QWhatsThis::add(l, specialWhatsThis);
01954
01955 cl[0] = new QLabel( i18n("User"), gb );
01956 gl->addWidget (cl[0], 2, 0);
01957 theNotSpecials.append( cl[0] );
01958
01959 cl[1] = new QLabel( i18n("Group"), gb );
01960 gl->addWidget (cl[1], 3, 0);
01961 theNotSpecials.append( cl[1] );
01962
01963 cl[2] = new QLabel( i18n("Others"), gb );
01964 gl->addWidget (cl[2], 4, 0);
01965 theNotSpecials.append( cl[2] );
01966
01967 l = new QLabel(i18n("Set UID"), gb);
01968 gl->addWidget(l, 2, 5);
01969 QString setUidWhatsThis;
01970 if (isDir)
01971 setUidWhatsThis = i18n("If this flag is set, the owner of this folder will be "
01972 "the owner of all new files.");
01973 else
01974 setUidWhatsThis = i18n("If this file is an executable and the flag is set, it will "
01975 "be executed with the permissions of the owner.");
01976 QWhatsThis::add(l, setUidWhatsThis);
01977
01978 l = new QLabel(i18n("Set GID"), gb);
01979 gl->addWidget(l, 3, 5);
01980 QString setGidWhatsThis;
01981 if (isDir)
01982 setGidWhatsThis = i18n("If this flag is set, the group of this folder will be "
01983 "set for all new files.");
01984 else
01985 setGidWhatsThis = i18n("If this file is an executable and the flag is set, it will "
01986 "be executed with the permissions of the group.");
01987 QWhatsThis::add(l, setGidWhatsThis);
01988
01989 l = new QLabel(i18n("File permission", "Sticky"), gb);
01990 gl->addWidget(l, 4, 5);
01991 QString stickyWhatsThis;
01992 if (isDir)
01993 stickyWhatsThis = i18n("If the Sticky flag is set on a folder, only the owner "
01994 "and root can delete or rename files. Otherwise everybody "
01995 "with write permissions can do this.");
01996 else
01997 stickyWhatsThis = i18n("The Sticky flag on a file is ignored on Linux, but may "
01998 "be used on some systems");
01999 QWhatsThis::add(l, stickyWhatsThis);
02000
02001 mode_t aPermissions, aPartialPermissions;
02002 mode_t dummy1, dummy2;
02003
02004 if (!d->isIrregular) {
02005 switch (d->pmode) {
02006 case PermissionsOnlyFiles:
02007 getPermissionMasks(aPartialPermissions,
02008 dummy1,
02009 aPermissions,
02010 dummy2);
02011 break;
02012 case PermissionsOnlyDirs:
02013 case PermissionsMixed:
02014 getPermissionMasks(dummy1,
02015 aPartialPermissions,
02016 dummy2,
02017 aPermissions);
02018 break;
02019 case PermissionsOnlyLinks:
02020 aPermissions = UniRead | UniWrite | UniExec | UniSpecial;
02021 aPartialPermissions = 0;
02022 break;
02023 }
02024 }
02025 else {
02026 aPermissions = permissions;
02027 aPartialPermissions = d->partialPermissions;
02028 }
02029
02030
02031 QCheckBox *cba[3][4];
02032 for (int row = 0; row < 3 ; ++row) {
02033 for (int col = 0; col < 4; ++col) {
02034 QCheckBox *cb = new QCheckBox( gb );
02035 if ( col != 3 ) theNotSpecials.append( cb );
02036 cba[row][col] = cb;
02037 cb->setChecked(aPermissions & fperm[row][col]);
02038 if ( aPartialPermissions & fperm[row][col] )
02039 {
02040 cb->setTristate();
02041 cb->setNoChange();
02042 }
02043 else if (d->cbRecursive && d->cbRecursive->isChecked())
02044 cb->setTristate();
02045
02046 cb->setEnabled( d->canChangePermissions );
02047 gl->addWidget (cb, row+2, col+1);
02048 switch(col) {
02049 case 0:
02050 QWhatsThis::add(cb, readWhatsThis);
02051 break;
02052 case 1:
02053 QWhatsThis::add(cb, writeWhatsThis);
02054 break;
02055 case 2:
02056 QWhatsThis::add(cb, execWhatsThis);
02057 break;
02058 case 3:
02059 switch(row) {
02060 case 0:
02061 QWhatsThis::add(cb, setUidWhatsThis);
02062 break;
02063 case 1:
02064 QWhatsThis::add(cb, setGidWhatsThis);
02065 break;
02066 case 2:
02067 QWhatsThis::add(cb, stickyWhatsThis);
02068 break;
02069 }
02070 break;
02071 }
02072 }
02073 }
02074 gl->setColStretch(6, 10);
02075
02076 #ifdef USE_POSIX_ACL
02077 KACLEditWidget *extendedACLs = 0;
02078
02079
02080 if ( properties->items().count() == 1 ) {
02081 QCString pathCString = QFile::encodeName( properties->item()->url().path() );
02082 d->fileSystemSupportsACLs = fileSystemSupportsACL( pathCString );
02083 }
02084 if ( d->fileSystemSupportsACLs ) {
02085 std::for_each( theNotSpecials.begin(), theNotSpecials.end(), std::mem_fun( &QWidget::hide ) );
02086 extendedACLs = new KACLEditWidget( mainVBox );
02087 if ( d->extendedACL.isValid() && d->extendedACL.isExtended() )
02088 extendedACLs->setACL( d->extendedACL );
02089 else
02090 extendedACLs->setACL( KACL( aPermissions ) );
02091
02092 if ( d->defaultACL.isValid() )
02093 extendedACLs->setDefaultACL( d->defaultACL );
02094
02095 if ( properties->items().first()->isDir() )
02096 extendedACLs->setAllowDefaults( true );
02097 if ( !d->canChangePermissions )
02098 extendedACLs->setReadOnly( true );
02099
02100 }
02101 #endif
02102 if (dlg.exec() != KDialogBase::Accepted)
02103 return;
02104
02105 mode_t andPermissions = mode_t(~0);
02106 mode_t orPermissions = 0;
02107 for (int row = 0; row < 3; ++row)
02108 for (int col = 0; col < 4; ++col) {
02109 switch (cba[row][col]->state())
02110 {
02111 case QCheckBox::On:
02112 orPermissions |= fperm[row][col];
02113
02114 case QCheckBox::Off:
02115 andPermissions &= ~fperm[row][col];
02116 break;
02117 default:
02118 break;
02119 }
02120 }
02121
02122 d->isIrregular = false;
02123 KFileItemList items = properties->items();
02124 for (KFileItemListIterator it(items); it.current(); ++it) {
02125 if (isIrregular(((*it)->permissions() & andPermissions) | orPermissions,
02126 (*it)->isDir(), (*it)->isLink())) {
02127 d->isIrregular = true;
02128 break;
02129 }
02130 }
02131
02132 permissions = orPermissions;
02133 d->partialPermissions = andPermissions;
02134
02135 #ifdef USE_POSIX_ACL
02136
02137 if ( extendedACLs ) {
02138 d->extendedACL = extendedACLs->getACL();
02139 d->defaultACL = extendedACLs->getDefaultACL();
02140 d->hasExtendedACL = d->extendedACL.isExtended() || d->defaultACL.isValid();
02141 permissions = d->extendedACL.basePermissions();
02142 permissions |= ( andPermissions | orPermissions ) & ( S_ISUID|S_ISGID|S_ISVTX );
02143 }
02144 #endif
02145
02146 updateAccessControls();
02147 emit changed();
02148 }
02149
02150
02151
02152
02153
02154
02155 KFilePermissionsPropsPlugin::~KFilePermissionsPropsPlugin()
02156 {
02157 delete d;
02158 }
02159
02160 bool KFilePermissionsPropsPlugin::supports( KFileItemList _items )
02161 {
02162 KFileItemList::const_iterator it = _items.constBegin();
02163 for ( ; it != _items.constEnd(); ++it ) {
02164 KFileItem *item = *it;
02165 if( !item->user().isEmpty() || !item->group().isEmpty() )
02166 return true;
02167 }
02168 return false;
02169 }
02170
02171
02172 void KFilePermissionsPropsPlugin::setComboContent(QComboBox *combo, PermissionsTarget target,
02173 mode_t permissions, mode_t partial) {
02174 combo->clear();
02175 if (d->pmode == PermissionsOnlyLinks) {
02176 combo->insertItem(i18n("Link"));
02177 combo->setCurrentItem(0);
02178 return;
02179 }
02180
02181 mode_t tMask = permissionsMasks[target];
02182 int textIndex;
02183 for (textIndex = 0; standardPermissions[textIndex] != (mode_t)-1; textIndex++)
02184 if ((standardPermissions[textIndex]&tMask) == (permissions&tMask&(UniRead|UniWrite)))
02185 break;
02186 Q_ASSERT(standardPermissions[textIndex] != (mode_t)-1);
02187
02188 for (int i = 0; permissionsTexts[(int)d->pmode][i]; i++)
02189 combo->insertItem(i18n(permissionsTexts[(int)d->pmode][i]));
02190
02191 if (partial & tMask & ~UniExec) {
02192 combo->insertItem(i18n("Varying (No Change)"));
02193 combo->setCurrentItem(3);
02194 }
02195 else
02196 combo->setCurrentItem(textIndex);
02197 }
02198
02199
02200 bool KFilePermissionsPropsPlugin::isIrregular(mode_t permissions, bool isDir, bool isLink) {
02201 if (isLink)
02202 return false;
02203
02204 mode_t p = permissions;
02205 if (p & (S_ISUID | S_ISGID))
02206 return true;
02207 if (isDir) {
02208 p &= ~S_ISVTX;
02209
02210
02211 mode_t p0 = p & UniOwner;
02212 if ((p0 != 0) && (p0 != (S_IRUSR | S_IXUSR)) && (p0 != UniOwner))
02213 return true;
02214 p0 = p & UniGroup;
02215 if ((p0 != 0) && (p0 != (S_IRGRP | S_IXGRP)) && (p0 != UniGroup))
02216 return true;
02217 p0 = p & UniOthers;
02218 if ((p0 != 0) && (p0 != (S_IROTH | S_IXOTH)) && (p0 != UniOthers))
02219 return true;
02220 return false;
02221 }
02222 if (p & S_ISVTX)
02223 return true;
02224
02225
02226 mode_t p0 = p & UniOwner;
02227 bool usrXPossible = !p0;
02228 if (p0 & S_IXUSR) {
02229 if ((p0 == S_IXUSR) || (p0 == (S_IWUSR | S_IXUSR)))
02230 return true;
02231 usrXPossible = true;
02232 }
02233 else if (p0 == S_IWUSR)
02234 return true;
02235
02236 p0 = p & UniGroup;
02237 bool grpXPossible = !p0;
02238 if (p0 & S_IXGRP) {
02239 if ((p0 == S_IXGRP) || (p0 == (S_IWGRP | S_IXGRP)))
02240 return true;
02241 grpXPossible = true;
02242 }
02243 else if (p0 == S_IWGRP)
02244 return true;
02245 if (p0 == 0)
02246 grpXPossible = true;
02247
02248 p0 = p & UniOthers;
02249 bool othXPossible = !p0;
02250 if (p0 & S_IXOTH) {
02251 if ((p0 == S_IXOTH) || (p0 == (S_IWOTH | S_IXOTH)))
02252 return true;
02253 othXPossible = true;
02254 }
02255 else if (p0 == S_IWOTH)
02256 return true;
02257
02258
02259 return (p & UniExec) && !(usrXPossible && grpXPossible && othXPossible);
02260 }
02261
02262
02263 void KFilePermissionsPropsPlugin::enableAccessControls(bool enable) {
02264 d->ownerPermCombo->setEnabled(enable);
02265 d->groupPermCombo->setEnabled(enable);
02266 d->othersPermCombo->setEnabled(enable);
02267 if (d->extraCheckbox)
02268 d->extraCheckbox->setEnabled(enable);
02269 if ( d->cbRecursive )
02270 d->cbRecursive->setEnabled(enable);
02271 }
02272
02273
02274 void KFilePermissionsPropsPlugin::updateAccessControls() {
02275 setComboContent(d->ownerPermCombo, PermissionsOwner,
02276 permissions, d->partialPermissions);
02277 setComboContent(d->groupPermCombo, PermissionsGroup,
02278 permissions, d->partialPermissions);
02279 setComboContent(d->othersPermCombo, PermissionsOthers,
02280 permissions, d->partialPermissions);
02281
02282 switch(d->pmode) {
02283 case PermissionsOnlyLinks:
02284 enableAccessControls(false);
02285 break;
02286 case PermissionsOnlyFiles:
02287 enableAccessControls(d->canChangePermissions && !d->isIrregular && !d->hasExtendedACL);
02288 if (d->canChangePermissions)
02289 d->explanationLabel->setText(d->isIrregular || d->hasExtendedACL ?
02290 i18n("This file uses advanced permissions",
02291 "These files use advanced permissions.",
02292 properties->items().count()) : "");
02293 if (d->partialPermissions & UniExec) {
02294 d->extraCheckbox->setTristate();
02295 d->extraCheckbox->setNoChange();
02296 }
02297 else {
02298 d->extraCheckbox->setTristate(false);
02299 d->extraCheckbox->setChecked(permissions & UniExec);
02300 }
02301 break;
02302 case PermissionsOnlyDirs:
02303 enableAccessControls(d->canChangePermissions && !d->isIrregular && !d->hasExtendedACL);
02304
02305
02306 if ( d->cbRecursive )
02307 d->cbRecursive->setEnabled( d->canChangePermissions && !d->isIrregular );
02308
02309 if (d->canChangePermissions)
02310 d->explanationLabel->setText(d->isIrregular || d->hasExtendedACL ?
02311 i18n("This folder uses advanced permissions.",
02312 "These folders use advanced permissions.",
02313 properties->items().count()) : "");
02314 if (d->partialPermissions & S_ISVTX) {
02315 d->extraCheckbox->setTristate();
02316 d->extraCheckbox->setNoChange();
02317 }
02318 else {
02319 d->extraCheckbox->setTristate(false);
02320 d->extraCheckbox->setChecked(permissions & S_ISVTX);
02321 }
02322 break;
02323 case PermissionsMixed:
02324 enableAccessControls(d->canChangePermissions && !d->isIrregular && !d->hasExtendedACL);
02325 if (d->canChangePermissions)
02326 d->explanationLabel->setText(d->isIrregular || d->hasExtendedACL ?
02327 i18n("These files use advanced permissions.") : "");
02328 break;
02329 if (d->partialPermissions & S_ISVTX) {
02330 d->extraCheckbox->setTristate();
02331 d->extraCheckbox->setNoChange();
02332 }
02333 else {
02334 d->extraCheckbox->setTristate(false);
02335 d->extraCheckbox->setChecked(permissions & S_ISVTX);
02336 }
02337 break;
02338 }
02339 }
02340
02341
02342 void KFilePermissionsPropsPlugin::getPermissionMasks(mode_t &andFilePermissions,
02343 mode_t &andDirPermissions,
02344 mode_t &orFilePermissions,
02345 mode_t &orDirPermissions) {
02346 andFilePermissions = mode_t(~UniSpecial);
02347 andDirPermissions = mode_t(~(S_ISUID|S_ISGID));
02348 orFilePermissions = 0;
02349 orDirPermissions = 0;
02350 if (d->isIrregular)
02351 return;
02352
02353 mode_t m = standardPermissions[d->ownerPermCombo->currentItem()];
02354 if (m != (mode_t) -1) {
02355 orFilePermissions |= m & UniOwner;
02356 if ((m & UniOwner) &&
02357 ((d->pmode == PermissionsMixed) ||
02358 ((d->pmode == PermissionsOnlyFiles) && (d->extraCheckbox->state() == QButton::NoChange))))
02359 andFilePermissions &= ~(S_IRUSR | S_IWUSR);
02360 else {
02361 andFilePermissions &= ~(S_IRUSR | S_IWUSR | S_IXUSR);
02362 if ((m & S_IRUSR) && (d->extraCheckbox->state() == QButton::On))
02363 orFilePermissions |= S_IXUSR;
02364 }
02365
02366 orDirPermissions |= m & UniOwner;
02367 if (m & S_IRUSR)
02368 orDirPermissions |= S_IXUSR;
02369 andDirPermissions &= ~(S_IRUSR | S_IWUSR | S_IXUSR);
02370 }
02371
02372 m = standardPermissions[d->groupPermCombo->currentItem()];
02373 if (m != (mode_t) -1) {
02374 orFilePermissions |= m & UniGroup;
02375 if ((m & UniGroup) &&
02376 ((d->pmode == PermissionsMixed) ||
02377 ((d->pmode == PermissionsOnlyFiles) && (d->extraCheckbox->state() == QButton::NoChange))))
02378 andFilePermissions &= ~(S_IRGRP | S_IWGRP);
02379 else {
02380 andFilePermissions &= ~(S_IRGRP | S_IWGRP | S_IXGRP);
02381 if ((m & S_IRGRP) && (d->extraCheckbox->state() == QButton::On))
02382 orFilePermissions |= S_IXGRP;
02383 }
02384
02385 orDirPermissions |= m & UniGroup;
02386 if (m & S_IRGRP)
02387 orDirPermissions |= S_IXGRP;
02388 andDirPermissions &= ~(S_IRGRP | S_IWGRP | S_IXGRP);
02389 }
02390
02391 m = standardPermissions[d->othersPermCombo->currentItem()];
02392 if (m != (mode_t) -1) {
02393 orFilePermissions |= m & UniOthers;
02394 if ((m & UniOthers) &&
02395 ((d->pmode == PermissionsMixed) ||
02396 ((d->pmode == PermissionsOnlyFiles) && (d->extraCheckbox->state() == QButton::NoChange))))
02397 andFilePermissions &= ~(S_IROTH | S_IWOTH);
02398 else {
02399 andFilePermissions &= ~(S_IROTH | S_IWOTH | S_IXOTH);
02400 if ((m & S_IROTH) && (d->extraCheckbox->state() == QButton::On))
02401 orFilePermissions |= S_IXOTH;
02402 }
02403
02404 orDirPermissions |= m & UniOthers;
02405 if (m & S_IROTH)
02406 orDirPermissions |= S_IXOTH;
02407 andDirPermissions &= ~(S_IROTH | S_IWOTH | S_IXOTH);
02408 }
02409
02410 if (((d->pmode == PermissionsMixed) || (d->pmode == PermissionsOnlyDirs)) &&
02411 (d->extraCheckbox->state() != QButton::NoChange)) {
02412 andDirPermissions &= ~S_ISVTX;
02413 if (d->extraCheckbox->state() == QButton::On)
02414 orDirPermissions |= S_ISVTX;
02415 }
02416 }
02417
02418 void KFilePermissionsPropsPlugin::applyChanges()
02419 {
02420 mode_t orFilePermissions;
02421 mode_t orDirPermissions;
02422 mode_t andFilePermissions;
02423 mode_t andDirPermissions;
02424
02425 if (!d->canChangePermissions)
02426 return;
02427
02428 if (!d->isIrregular)
02429 getPermissionMasks(andFilePermissions,
02430 andDirPermissions,
02431 orFilePermissions,
02432 orDirPermissions);
02433 else {
02434 orFilePermissions = permissions;
02435 andFilePermissions = d->partialPermissions;
02436 orDirPermissions = permissions;
02437 andDirPermissions = d->partialPermissions;
02438 }
02439
02440 QString owner, group;
02441 if (usrEdit)
02442 owner = usrEdit->text();
02443 if (grpEdit)
02444 group = grpEdit->text();
02445 else if (grpCombo)
02446 group = grpCombo->currentText();
02447
02448 if (owner == strOwner)
02449 owner = QString::null;
02450
02451 if (group == strGroup)
02452 group = QString::null;
02453
02454 bool recursive = d->cbRecursive && d->cbRecursive->isChecked();
02455 bool permissionChange = false;
02456
02457 KFileItemList files, dirs;
02458 KFileItemList items = properties->items();
02459 for (KFileItemListIterator it(items); it.current(); ++it) {
02460 if ((*it)->isDir()) {
02461 dirs.append(*it);
02462 if ((*it)->permissions() != (((*it)->permissions() & andDirPermissions) | orDirPermissions))
02463 permissionChange = true;
02464 }
02465 else if ((*it)->isFile()) {
02466 files.append(*it);
02467 if ((*it)->permissions() != (((*it)->permissions() & andFilePermissions) | orFilePermissions))
02468 permissionChange = true;
02469 }
02470 }
02471
02472 const bool ACLChange = ( d->extendedACL != properties->item()->ACL() );
02473 const bool defaultACLChange = ( d->defaultACL != properties->item()->defaultACL() );
02474
02475 if ( owner.isEmpty() && group.isEmpty() && !recursive
02476 && !permissionChange && !ACLChange && !defaultACLChange )
02477 return;
02478
02479 KIO::Job * job;
02480 if (files.count() > 0) {
02481 job = KIO::chmod( files, orFilePermissions, ~andFilePermissions,
02482 owner, group, false );
02483 if ( ACLChange && d->fileSystemSupportsACLs )
02484 job->addMetaData( "ACL_STRING", d->extendedACL.isValid()?d->extendedACL.asString():"ACL_DELETE" );
02485 if ( defaultACLChange && d->fileSystemSupportsACLs )
02486 job->addMetaData( "DEFAULT_ACL_STRING", d->defaultACL.isValid()?d->defaultACL.asString():"ACL_DELETE" );
02487
02488 connect( job, SIGNAL( result( KIO::Job * ) ),
02489 SLOT( slotChmodResult( KIO::Job * ) ) );
02490
02491 QWidget dummy(0,0,WType_Dialog|WShowModal);
02492 qt_enter_modal(&dummy);
02493 qApp->enter_loop();
02494 qt_leave_modal(&dummy);
02495 }
02496 if (dirs.count() > 0) {
02497 job = KIO::chmod( dirs, orDirPermissions, ~andDirPermissions,
02498 owner, group, recursive );
02499 if ( ACLChange && d->fileSystemSupportsACLs )
02500 job->addMetaData( "ACL_STRING", d->extendedACL.isValid()?d->extendedACL.asString():"ACL_DELETE" );
02501 if ( defaultACLChange && d->fileSystemSupportsACLs )
02502 job->addMetaData( "DEFAULT_ACL_STRING", d->defaultACL.isValid()?d->defaultACL.asString():"ACL_DELETE" );
02503
02504 connect( job, SIGNAL( result( KIO::Job * ) ),
02505 SLOT( slotChmodResult( KIO::Job * ) ) );
02506
02507 QWidget dummy(0,0,WType_Dialog|WShowModal);
02508 qt_enter_modal(&dummy);
02509 qApp->enter_loop();
02510 qt_leave_modal(&dummy);
02511 }
02512 }
02513
02514 void KFilePermissionsPropsPlugin::slotChmodResult( KIO::Job * job )
02515 {
02516 kdDebug(250) << "KFilePermissionsPropsPlugin::slotChmodResult" << endl;
02517 if (job->error())
02518 job->showErrorDialog( d->m_frame );
02519
02520 qApp->exit_loop();
02521 }
02522
02523
02524
02525
02526 class KURLPropsPlugin::KURLPropsPluginPrivate
02527 {
02528 public:
02529 KURLPropsPluginPrivate()
02530 {
02531 }
02532 ~KURLPropsPluginPrivate()
02533 {
02534 }
02535
02536 QFrame *m_frame;
02537 };
02538
02539 KURLPropsPlugin::KURLPropsPlugin( KPropertiesDialog *_props )
02540 : KPropsDlgPlugin( _props )
02541 {
02542 d = new KURLPropsPluginPrivate;
02543 d->m_frame = properties->addPage(i18n("U&RL"));
02544 QVBoxLayout *layout = new QVBoxLayout(d->m_frame, 0, KDialog::spacingHint());
02545
02546 QLabel *l;
02547 l = new QLabel( d->m_frame, "Label_1" );
02548 l->setText( i18n("URL:") );
02549 layout->addWidget(l);
02550
02551 URLEdit = new KURLRequester( d->m_frame, "URL Requester" );
02552 layout->addWidget(URLEdit);
02553
02554 QString path = properties->kurl().path();
02555
02556 QFile f( path );
02557 if ( !f.open( IO_ReadOnly ) )
02558 return;
02559 f.close();
02560
02561 KSimpleConfig config( path );
02562 config.setDesktopGroup();
02563 URLStr = config.readPathEntry( "URL" );
02564
02565 if ( !URLStr.isNull() )
02566 URLEdit->setURL( URLStr );
02567
02568 connect( URLEdit, SIGNAL( textChanged( const QString & ) ),
02569 this, SIGNAL( changed() ) );
02570
02571 layout->addStretch (1);
02572 }
02573
02574 KURLPropsPlugin::~KURLPropsPlugin()
02575 {
02576 delete d;
02577 }
02578
02579
02580
02581
02582
02583
02584 bool KURLPropsPlugin::supports( KFileItemList _items )
02585 {
02586 if ( _items.count() != 1 )
02587 return false;
02588 KFileItem * item = _items.first();
02589
02590 if ( !KPropsDlgPlugin::isDesktopFile( item ) )
02591 return false;
02592
02593
02594 KDesktopFile config( item->url().path(), true );
02595 return config.hasLinkType();
02596 }
02597
02598 void KURLPropsPlugin::applyChanges()
02599 {
02600 QString path = properties->kurl().path();
02601
02602 QFile f( path );
02603 if ( !f.open( IO_ReadWrite ) ) {
02604 KMessageBox::sorry( 0, i18n("<qt>Could not save properties. You do not have "
02605 "sufficient access to write to <b>%1</b>.</qt>").arg(path));
02606 return;
02607 }
02608 f.close();
02609
02610 KSimpleConfig config( path );
02611 config.setDesktopGroup();
02612 config.writeEntry( "Type", QString::fromLatin1("Link"));
02613 config.writePathEntry( "URL", URLEdit->url() );
02614
02615
02616 if ( config.hasKey("Name") )
02617 {
02618 QString nameStr = nameFromFileName(properties->kurl().fileName());
02619 config.writeEntry( "Name", nameStr );
02620 config.writeEntry( "Name", nameStr, true, false, true );
02621
02622 }
02623 }
02624
02625
02626
02627
02628
02629
02630
02631
02632 class KBindingPropsPlugin::KBindingPropsPluginPrivate
02633 {
02634 public:
02635 KBindingPropsPluginPrivate()
02636 {
02637 }
02638 ~KBindingPropsPluginPrivate()
02639 {
02640 }
02641
02642 QFrame *m_frame;
02643 };
02644
02645 KBindingPropsPlugin::KBindingPropsPlugin( KPropertiesDialog *_props ) : KPropsDlgPlugin( _props )
02646 {
02647 d = new KBindingPropsPluginPrivate;
02648 d->m_frame = properties->addPage(i18n("A&ssociation"));
02649 patternEdit = new KLineEdit( d->m_frame, "LineEdit_1" );
02650 commentEdit = new KLineEdit( d->m_frame, "LineEdit_2" );
02651 mimeEdit = new KLineEdit( d->m_frame, "LineEdit_3" );
02652
02653 QBoxLayout *mainlayout = new QVBoxLayout(d->m_frame, 0, KDialog::spacingHint());
02654 QLabel* tmpQLabel;
02655
02656 tmpQLabel = new QLabel( d->m_frame, "Label_1" );
02657 tmpQLabel->setText( i18n("Pattern ( example: *.html;*.htm )") );
02658 tmpQLabel->setMinimumSize(tmpQLabel->sizeHint());
02659 mainlayout->addWidget(tmpQLabel, 1);
02660
02661
02662
02663 patternEdit->setMaxLength( 512 );
02664 patternEdit->setMinimumSize( patternEdit->sizeHint() );
02665 patternEdit->setFixedHeight( fontHeight );
02666 mainlayout->addWidget(patternEdit, 1);
02667
02668 tmpQLabel = new QLabel( d->m_frame, "Label_2" );
02669 tmpQLabel->setText( i18n("Mime Type") );
02670 tmpQLabel->setMinimumSize(tmpQLabel->sizeHint());
02671 mainlayout->addWidget(tmpQLabel, 1);
02672
02673
02674 mimeEdit->setMaxLength( 256 );
02675 mimeEdit->setMinimumSize( mimeEdit->sizeHint() );
02676 mimeEdit->setFixedHeight( fontHeight );
02677 mainlayout->addWidget(mimeEdit, 1);
02678
02679 tmpQLabel = new QLabel( d->m_frame, "Label_3" );
02680 tmpQLabel->setText( i18n("Comment") );
02681 tmpQLabel->setMinimumSize(tmpQLabel->sizeHint());
02682 mainlayout->addWidget(tmpQLabel, 1);
02683
02684
02685 commentEdit->setMaxLength( 256 );
02686 commentEdit->setMinimumSize( commentEdit->sizeHint() );
02687 commentEdit->setFixedHeight( fontHeight );
02688 mainlayout->addWidget(commentEdit, 1);
02689
02690 cbAutoEmbed = new QCheckBox( i18n("Left click previews"), d->m_frame, "cbAutoEmbed" );
02691 mainlayout->addWidget(cbAutoEmbed, 1);
02692
02693 mainlayout->addStretch (10);
02694 mainlayout->activate();
02695
02696 QFile f( _props->kurl().path() );
02697 if ( !f.open( IO_ReadOnly ) )
02698 return;
02699 f.close();
02700
02701 KSimpleConfig config( _props->kurl().path() );
02702 config.setDesktopGroup();
02703 QString patternStr = config.readEntry( "Patterns" );
02704 QString iconStr = config.readEntry( "Icon" );
02705 QString commentStr = config.readEntry( "Comment" );
02706 m_sMimeStr = config.readEntry( "MimeType" );
02707
02708 if ( !patternStr.isEmpty() )
02709 patternEdit->setText( patternStr );
02710 if ( !commentStr.isEmpty() )
02711 commentEdit->setText( commentStr );
02712 if ( !m_sMimeStr.isEmpty() )
02713 mimeEdit->setText( m_sMimeStr );
02714 cbAutoEmbed->setTristate();
02715 if ( config.hasKey( "X-KDE-AutoEmbed" ) )
02716 cbAutoEmbed->setChecked( config.readBoolEntry( "X-KDE-AutoEmbed" ) );
02717 else
02718 cbAutoEmbed->setNoChange();
02719
02720 connect( patternEdit, SIGNAL( textChanged( const QString & ) ),
02721 this, SIGNAL( changed() ) );
02722 connect( commentEdit, SIGNAL( textChanged( const QString & ) ),
02723 this, SIGNAL( changed() ) );
02724 connect( mimeEdit, SIGNAL( textChanged( const QString & ) ),
02725 this, SIGNAL( changed() ) );
02726 connect( cbAutoEmbed, SIGNAL( toggled( bool ) ),
02727 this, SIGNAL( changed() ) );
02728 }
02729
02730 KBindingPropsPlugin::~KBindingPropsPlugin()
02731 {
02732 delete d;
02733 }
02734
02735
02736
02737
02738
02739
02740 bool KBindingPropsPlugin::supports( KFileItemList _items )
02741 {
02742 if ( _items.count() != 1 )
02743 return false;
02744 KFileItem * item = _items.first();
02745
02746 if ( !KPropsDlgPlugin::isDesktopFile( item ) )
02747 return false;
02748
02749
02750 KDesktopFile config( item->url().path(), true );
02751 return config.hasMimeTypeType();
02752 }
02753
02754 void KBindingPropsPlugin::applyChanges()
02755 {
02756 QString path = properties->kurl().path();
02757 QFile f( path );
02758
02759 if ( !f.open( IO_ReadWrite ) )
02760 {
02761 KMessageBox::sorry( 0, i18n("<qt>Could not save properties. You do not have "
02762 "sufficient access to write to <b>%1</b>.</qt>").arg(path));
02763 return;
02764 }
02765 f.close();
02766
02767 KSimpleConfig config( path );
02768 config.setDesktopGroup();
02769 config.writeEntry( "Type", QString::fromLatin1("MimeType") );
02770
02771 config.writeEntry( "Patterns", patternEdit->text() );
02772 config.writeEntry( "Comment", commentEdit->text() );
02773 config.writeEntry( "Comment",
02774 commentEdit->text(), true, false, true );
02775 config.writeEntry( "MimeType", mimeEdit->text() );
02776 if ( cbAutoEmbed->state() == QButton::NoChange )
02777 config.deleteEntry( "X-KDE-AutoEmbed", false );
02778 else
02779 config.writeEntry( "X-KDE-AutoEmbed", cbAutoEmbed->isChecked() );
02780 config.sync();
02781 }
02782
02783
02784
02785
02786
02787
02788
02789 class KDevicePropsPlugin::KDevicePropsPluginPrivate
02790 {
02791 public:
02792 KDevicePropsPluginPrivate()
02793 {
02794 }
02795 ~KDevicePropsPluginPrivate()
02796 {
02797 }
02798
02799 QFrame *m_frame;
02800 QStringList mountpointlist;
02801 QLabel *m_freeSpaceText;
02802 QLabel *m_freeSpaceLabel;
02803 QProgressBar *m_freeSpaceBar;
02804 };
02805
02806 KDevicePropsPlugin::KDevicePropsPlugin( KPropertiesDialog *_props ) : KPropsDlgPlugin( _props )
02807 {
02808 d = new KDevicePropsPluginPrivate;
02809 d->m_frame = properties->addPage(i18n("De&vice"));
02810
02811 QStringList devices;
02812 KMountPoint::List mountPoints = KMountPoint::possibleMountPoints();
02813
02814 for(KMountPoint::List::ConstIterator it = mountPoints.begin();
02815 it != mountPoints.end(); ++it)
02816 {
02817 KMountPoint *mp = *it;
02818 QString mountPoint = mp->mountPoint();
02819 QString device = mp->mountedFrom();
02820 kdDebug()<<"mountPoint :"<<mountPoint<<" device :"<<device<<" mp->mountType() :"<<mp->mountType()<<endl;
02821
02822 if ((mountPoint != "-") && (mountPoint != "none") && !mountPoint.isEmpty()
02823 && device != "none")
02824 {
02825 devices.append( device + QString::fromLatin1(" (")
02826 + mountPoint + QString::fromLatin1(")") );
02827 m_devicelist.append(device);
02828 d->mountpointlist.append(mountPoint);
02829 }
02830 }
02831
02832 QGridLayout *layout = new QGridLayout( d->m_frame, 0, 2, 0,
02833 KDialog::spacingHint());
02834 layout->setColStretch(1, 1);
02835
02836 QLabel* label;
02837 label = new QLabel( d->m_frame );
02838 label->setText( devices.count() == 0 ?
02839 i18n("Device (/dev/fd0):") :
02840 i18n("Device:") );
02841 layout->addWidget(label, 0, 0);
02842
02843 device = new QComboBox( true, d->m_frame, "ComboBox_device" );
02844 device->insertStringList( devices );
02845 layout->addWidget(device, 0, 1);
02846 connect( device, SIGNAL( activated( int ) ),
02847 this, SLOT( slotActivated( int ) ) );
02848
02849 readonly = new QCheckBox( d->m_frame, "CheckBox_readonly" );
02850 readonly->setText( i18n("Read only") );
02851 layout->addWidget(readonly, 1, 1);
02852
02853 label = new QLabel( d->m_frame );
02854 label->setText( i18n("File system:") );
02855 layout->addWidget(label, 2, 0);
02856
02857 QLabel *fileSystem = new QLabel( d->m_frame );
02858 layout->addWidget(fileSystem, 2, 1);
02859
02860 label = new QLabel( d->m_frame );
02861 label->setText( devices.count()==0 ?
02862 i18n("Mount point (/mnt/floppy):") :
02863 i18n("Mount point:"));
02864 layout->addWidget(label, 3, 0);
02865
02866 mountpoint = new QLabel( d->m_frame, "LineEdit_mountpoint" );
02867
02868 layout->addWidget(mountpoint, 3, 1);
02869
02870
02871 d->m_freeSpaceText = new QLabel(i18n("Free disk space:"), d->m_frame );
02872 layout->addWidget(d->m_freeSpaceText, 4, 0);
02873
02874 d->m_freeSpaceLabel = new QLabel( d->m_frame );
02875 layout->addWidget( d->m_freeSpaceLabel, 4, 1 );
02876
02877 d->m_freeSpaceBar = new QProgressBar( d->m_frame, "freeSpaceBar" );
02878 layout->addMultiCellWidget(d->m_freeSpaceBar, 5, 5, 0, 1);
02879
02880
02881 d->m_freeSpaceText->hide();
02882 d->m_freeSpaceLabel->hide();
02883 d->m_freeSpaceBar->hide();
02884
02885 KSeparator* sep = new KSeparator( KSeparator::HLine, d->m_frame);
02886 layout->addMultiCellWidget(sep, 6, 6, 0, 1);
02887
02888 unmounted = new KIconButton( d->m_frame );
02889 int bsize = 66 + 2 * unmounted->style().pixelMetric(QStyle::PM_ButtonMargin);
02890 unmounted->setFixedSize(bsize, bsize);
02891 unmounted->setIconType(KIcon::Desktop, KIcon::Device);
02892 layout->addWidget(unmounted, 7, 0);
02893
02894 label = new QLabel( i18n("Unmounted Icon"), d->m_frame );
02895 layout->addWidget(label, 7, 1);
02896
02897 layout->setRowStretch(8, 1);
02898
02899 QString path( _props->kurl().path() );
02900
02901 QFile f( path );
02902 if ( !f.open( IO_ReadOnly ) )
02903 return;
02904 f.close();
02905
02906 KSimpleConfig config( path );
02907 config.setDesktopGroup();
02908 QString deviceStr = config.readEntry( "Dev" );
02909 QString mountPointStr = config.readEntry( "MountPoint" );
02910 bool ro = config.readBoolEntry( "ReadOnly", false );
02911 QString unmountedStr = config.readEntry( "UnmountIcon" );
02912
02913 fileSystem->setText( i18n(config.readEntry("FSType").local8Bit()) );
02914
02915 device->setEditText( deviceStr );
02916 if ( !deviceStr.isEmpty() ) {
02917
02918 int index = m_devicelist.findIndex(deviceStr);
02919 if (index != -1)
02920 {
02921
02922 slotActivated( index );
02923 }
02924 }
02925
02926 if ( !mountPointStr.isEmpty() )
02927 {
02928 mountpoint->setText( mountPointStr );
02929 updateInfo();
02930 }
02931
02932 readonly->setChecked( ro );
02933
02934 if ( unmountedStr.isEmpty() )
02935 unmountedStr = KMimeType::defaultMimeTypePtr()->KServiceType::icon();
02936
02937 unmounted->setIcon( unmountedStr );
02938
02939 connect( device, SIGNAL( activated( int ) ),
02940 this, SIGNAL( changed() ) );
02941 connect( device, SIGNAL( textChanged( const QString & ) ),
02942 this, SIGNAL( changed() ) );
02943 connect( readonly, SIGNAL( toggled( bool ) ),
02944 this, SIGNAL( changed() ) );
02945 connect( unmounted, SIGNAL( iconChanged( QString ) ),
02946 this, SIGNAL( changed() ) );
02947
02948 connect( device, SIGNAL( textChanged( const QString & ) ),
02949 this, SLOT( slotDeviceChanged() ) );
02950 }
02951
02952 KDevicePropsPlugin::~KDevicePropsPlugin()
02953 {
02954 delete d;
02955 }
02956
02957
02958
02959
02960
02961
02962 void KDevicePropsPlugin::updateInfo()
02963 {
02964
02965 d->m_freeSpaceText->hide();
02966 d->m_freeSpaceLabel->hide();
02967 d->m_freeSpaceBar->hide();
02968
02969 if ( !mountpoint->text().isEmpty() )
02970 {
02971 KDiskFreeSp * job = new KDiskFreeSp;
02972 connect( job, SIGNAL( foundMountPoint( const unsigned long&, const unsigned long&,
02973 const unsigned long&, const QString& ) ),
02974 this, SLOT( slotFoundMountPoint( const unsigned long&, const unsigned long&,
02975 const unsigned long&, const QString& ) ) );
02976
02977 job->readDF( mountpoint->text() );
02978 }
02979 }
02980
02981 void KDevicePropsPlugin::slotActivated( int index )
02982 {
02983
02984 device->setEditText( m_devicelist[index] );
02985 mountpoint->setText( d->mountpointlist[index] );
02986
02987 updateInfo();
02988 }
02989
02990 void KDevicePropsPlugin::slotDeviceChanged()
02991 {
02992
02993 int index = m_devicelist.findIndex( device->currentText() );
02994 if ( index != -1 )
02995 mountpoint->setText( d->mountpointlist[index] );
02996 else
02997 mountpoint->setText( QString::null );
02998
02999 updateInfo();
03000 }
03001
03002 void KDevicePropsPlugin::slotFoundMountPoint( const unsigned long& kBSize,
03003 const unsigned long& ,
03004 const unsigned long& kBAvail,
03005 const QString& )
03006 {
03007 d->m_freeSpaceText->show();
03008 d->m_freeSpaceLabel->show();
03009
03010 int percUsed = 100 - (int)(100.0 * kBAvail / kBSize);
03011
03012 d->m_freeSpaceLabel->setText(
03013
03014 i18n("Available space out of total partition size (percent used)", "%1 out of %2 (%3% used)")
03015 .arg(KIO::convertSizeFromKB(kBAvail))
03016 .arg(KIO::convertSizeFromKB(kBSize))
03017 .arg( 100 - (int)(100.0 * kBAvail / kBSize) ));
03018
03019 d->m_freeSpaceBar->setProgress(percUsed, 100);
03020 d->m_freeSpaceBar->show();
03021 }
03022
03023 bool KDevicePropsPlugin::supports( KFileItemList _items )
03024 {
03025 if ( _items.count() != 1 )
03026 return false;
03027 KFileItem * item = _items.first();
03028
03029 if ( !KPropsDlgPlugin::isDesktopFile( item ) )
03030 return false;
03031
03032 KDesktopFile config( item->url().path(), true );
03033 return config.hasDeviceType();
03034 }
03035
03036 void KDevicePropsPlugin::applyChanges()
03037 {
03038 QString path = properties->kurl().path();
03039 QFile f( path );
03040 if ( !f.open( IO_ReadWrite ) )
03041 {
03042 KMessageBox::sorry( 0, i18n("<qt>Could not save properties. You do not have sufficient "
03043 "access to write to <b>%1</b>.</qt>").arg(path));
03044 return;
03045 }
03046 f.close();
03047
03048 KSimpleConfig config( path );
03049 config.setDesktopGroup();
03050 config.writeEntry( "Type", QString::fromLatin1("FSDevice") );
03051
03052 config.writeEntry( "Dev", device->currentText() );
03053 config.writeEntry( "MountPoint", mountpoint->text() );
03054
03055 config.writeEntry( "UnmountIcon", unmounted->icon() );
03056 kdDebug(250) << "unmounted->icon() = " << unmounted->icon() << endl;
03057
03058 config.writeEntry( "ReadOnly", readonly->isChecked() );
03059
03060 config.sync();
03061 }
03062
03063
03064
03065
03066
03067
03068
03069
03070
03071 KDesktopPropsPlugin::KDesktopPropsPlugin( KPropertiesDialog *_props )
03072 : KPropsDlgPlugin( _props )
03073 {
03074 QFrame *frame = properties->addPage(i18n("&Application"));
03075 QVBoxLayout *mainlayout = new QVBoxLayout( frame, 0, KDialog::spacingHint() );
03076
03077 w = new KPropertiesDesktopBase(frame);
03078 mainlayout->addWidget(w);
03079
03080 bool bKDesktopMode = (QCString(qApp->name()) == "kdesktop");
03081
03082 if (bKDesktopMode)
03083 {
03084
03085 w->nameEdit->hide();
03086 w->nameLabel->hide();
03087 }
03088
03089 w->pathEdit->setMode(KFile::Directory | KFile::LocalOnly);
03090 w->pathEdit->lineEdit()->setAcceptDrops(false);
03091
03092 connect( w->nameEdit, SIGNAL( textChanged( const QString & ) ), this, SIGNAL( changed() ) );
03093 connect( w->genNameEdit, SIGNAL( textChanged( const QString & ) ), this, SIGNAL( changed() ) );
03094 connect( w->commentEdit, SIGNAL( textChanged( const QString & ) ), this, SIGNAL( changed() ) );
03095 connect( w->commandEdit, SIGNAL( textChanged( const QString & ) ), this, SIGNAL( changed() ) );
03096 connect( w->pathEdit, SIGNAL( textChanged( const QString & ) ), this, SIGNAL( changed() ) );
03097
03098 connect( w->browseButton, SIGNAL( clicked() ), this, SLOT( slotBrowseExec() ) );
03099 connect( w->addFiletypeButton, SIGNAL( clicked() ), this, SLOT( slotAddFiletype() ) );
03100 connect( w->delFiletypeButton, SIGNAL( clicked() ), this, SLOT( slotDelFiletype() ) );
03101 connect( w->advancedButton, SIGNAL( clicked() ), this, SLOT( slotAdvanced() ) );
03102
03103
03104 QString path = _props->kurl().path();
03105 QFile f( path );
03106 if ( !f.open( IO_ReadOnly ) )
03107 return;
03108 f.close();
03109
03110 KDesktopFile config( path );
03111 QString nameStr = config.readName();
03112 QString genNameStr = config.readGenericName();
03113 QString commentStr = config.readComment();
03114 QString commandStr = config.readPathEntry( "Exec" );
03115 if (commandStr.left(12) == "ksystraycmd ")
03116 {
03117 commandStr.remove(0, 12);
03118 m_systrayBool = true;
03119 }
03120 else
03121 m_systrayBool = false;
03122
03123 m_origCommandStr = commandStr;
03124 QString pathStr = config.readPathEntry( "Path" );
03125 m_terminalBool = config.readBoolEntry( "Terminal" );
03126 m_terminalOptionStr = config.readEntry( "TerminalOptions" );
03127 m_suidBool = config.readBoolEntry( "X-KDE-SubstituteUID" );
03128 m_suidUserStr = config.readEntry( "X-KDE-Username" );
03129 if( config.hasKey( "StartupNotify" ))
03130 m_startupBool = config.readBoolEntry( "StartupNotify", true );
03131 else
03132 m_startupBool = config.readBoolEntry( "X-KDE-StartupNotify", true );
03133 m_dcopServiceType = config.readEntry("X-DCOP-ServiceType").lower();
03134
03135 QStringList mimeTypes = config.readListEntry( "MimeType", ';' );
03136
03137 if ( nameStr.isEmpty() || bKDesktopMode ) {
03138
03139
03140
03141 setDirty();
03142 }
03143 if ( !bKDesktopMode )
03144 w->nameEdit->setText(nameStr);
03145
03146 w->genNameEdit->setText( genNameStr );
03147 w->commentEdit->setText( commentStr );
03148 w->commandEdit->setText( commandStr );
03149 w->pathEdit->lineEdit()->setText( pathStr );
03150 w->filetypeList->setAllColumnsShowFocus(true);
03151
03152 KMimeType::Ptr defaultMimetype = KMimeType::defaultMimeTypePtr();
03153 for(QStringList::ConstIterator it = mimeTypes.begin();
03154 it != mimeTypes.end(); )
03155 {
03156 KMimeType::Ptr p = KMimeType::mimeType(*it);
03157 ++it;
03158 QString preference;
03159 if (it != mimeTypes.end())
03160 {
03161 bool numeric;
03162 (*it).toInt(&numeric);
03163 if (numeric)
03164 {
03165 preference = *it;
03166 ++it;
03167 }
03168 }
03169 if (p && (p != defaultMimetype))
03170 {
03171 new QListViewItem(w->filetypeList, p->name(), p->comment(), preference);
03172 }
03173 }
03174
03175 }
03176
03177 KDesktopPropsPlugin::~KDesktopPropsPlugin()
03178 {
03179 }
03180
03181 void KDesktopPropsPlugin::slotSelectMimetype()
03182 {
03183 QListView *w = (QListView*)sender();
03184 QListViewItem *item = w->firstChild();
03185 while(item)
03186 {
03187 if (item->isSelected())
03188 w->setSelected(item, false);
03189 item = item->nextSibling();
03190 }
03191 }
03192
03193 void KDesktopPropsPlugin::slotAddFiletype()
03194 {
03195 KDialogBase dlg(w, "KPropertiesMimetypes", true,
03196 i18n("Add File Type for %1").arg(properties->kurl().fileName()),
03197 KDialogBase::Ok|KDialogBase::Cancel, KDialogBase::Ok);
03198
03199 KGuiItem okItem(i18n("&Add"), QString::null ,
03200 i18n("Add the selected file types to\nthe list of supported file types."),
03201 i18n("Add the selected file types to\nthe list of supported file types."));
03202 dlg.setButtonOK(okItem);
03203
03204 KPropertiesMimetypeBase *mw = new KPropertiesMimetypeBase(&dlg);
03205
03206 dlg.setMainWidget(mw);
03207
03208 {
03209 mw->listView->setRootIsDecorated(true);
03210 mw->listView->setSelectionMode(QListView::Extended);
03211 mw->listView->setAllColumnsShowFocus(true);
03212 mw->listView->setFullWidth(true);
03213 mw->listView->setMinimumSize(500,400);
03214
03215 connect(mw->listView, SIGNAL(selectionChanged()),
03216 this, SLOT(slotSelectMimetype()));
03217 connect(mw->listView, SIGNAL(doubleClicked( QListViewItem *, const QPoint &, int )),
03218 &dlg, SLOT( slotOk()));
03219
03220 QMap<QString,QListViewItem*> majorMap;
03221 QListViewItem *majorGroup;
03222 KMimeType::List mimetypes = KMimeType::allMimeTypes();
03223 QValueListIterator<KMimeType::Ptr> it(mimetypes.begin());
03224 for (; it != mimetypes.end(); ++it) {
03225 QString mimetype = (*it)->name();
03226 if (mimetype == KMimeType::defaultMimeType())
03227 continue;
03228 int index = mimetype.find("/");
03229 QString maj = mimetype.left(index);
03230 QString min = mimetype.mid(index+1);
03231
03232 QMapIterator<QString,QListViewItem*> mit = majorMap.find( maj );
03233 if ( mit == majorMap.end() ) {
03234 majorGroup = new QListViewItem( mw->listView, maj );
03235 majorGroup->setExpandable(true);
03236 mw->listView->setOpen(majorGroup, true);
03237 majorMap.insert( maj, majorGroup );
03238 }
03239 else
03240 {
03241 majorGroup = mit.data();
03242 }
03243
03244 QListViewItem *item = new QListViewItem(majorGroup, min, (*it)->comment());
03245 item->setPixmap(0, (*it)->pixmap(KIcon::Small, IconSize(KIcon::Small)));
03246 }
03247 QMapIterator<QString,QListViewItem*> mit = majorMap.find( "all" );
03248 if ( mit != majorMap.end())
03249 {
03250 mw->listView->setCurrentItem(mit.data());
03251 mw->listView->ensureItemVisible(mit.data());
03252 }
03253 }
03254
03255 if (dlg.exec() == KDialogBase::Accepted)
03256 {
03257 KMimeType::Ptr defaultMimetype = KMimeType::defaultMimeTypePtr();
03258 QListViewItem *majorItem = mw->listView->firstChild();
03259 while(majorItem)
03260 {
03261 QString major = majorItem->text(0);
03262
03263 QListViewItem *minorItem = majorItem->firstChild();
03264 while(minorItem)
03265 {
03266 if (minorItem->isSelected())
03267 {
03268 QString mimetype = major + "/" + minorItem->text(0);
03269 KMimeType::Ptr p = KMimeType::mimeType(mimetype);
03270 if (p && (p != defaultMimetype))
03271 {
03272 mimetype = p->name();
03273 bool found = false;
03274 QListViewItem *item = w->filetypeList->firstChild();
03275 while (item)
03276 {
03277 if (mimetype == item->text(0))
03278 {
03279 found = true;
03280 break;
03281 }
03282 item = item->nextSibling();
03283 }
03284 if (!found) {
03285 new QListViewItem(w->filetypeList, p->name(), p->comment());
03286 emit changed();
03287 }
03288 }
03289 }
03290 minorItem = minorItem->nextSibling();
03291 }
03292
03293 majorItem = majorItem->nextSibling();
03294 }
03295
03296 }
03297 }
03298
03299 void KDesktopPropsPlugin::slotDelFiletype()
03300 {
03301 delete w->filetypeList->currentItem();
03302 emit changed();
03303 }
03304
03305 void KDesktopPropsPlugin::checkCommandChanged()
03306 {
03307 if (KRun::binaryName(w->commandEdit->text(), true) !=
03308 KRun::binaryName(m_origCommandStr, true))
03309 {
03310 QString m_origCommandStr = w->commandEdit->text();
03311 m_dcopServiceType= QString::null;
03312 }
03313 }
03314
03315 void KDesktopPropsPlugin::applyChanges()
03316 {
03317 kdDebug(250) << "KDesktopPropsPlugin::applyChanges" << endl;
03318 QString path = properties->kurl().path();
03319
03320 QFile f( path );
03321
03322 if ( !f.open( IO_ReadWrite ) ) {
03323 KMessageBox::sorry( 0, i18n("<qt>Could not save properties. You do not have "
03324 "sufficient access to write to <b>%1</b>.</qt>").arg(path));
03325 return;
03326 }
03327 f.close();
03328
03329
03330
03331 checkCommandChanged();
03332
03333 KSimpleConfig config( path );
03334 config.setDesktopGroup();
03335 config.writeEntry( "Type", QString::fromLatin1("Application"));
03336 config.writeEntry( "Comment", w->commentEdit->text() );
03337 config.writeEntry( "Comment", w->commentEdit->text(), true, false, true );
03338 config.writeEntry( "GenericName", w->genNameEdit->text() );
03339 config.writeEntry( "GenericName", w->genNameEdit->text(), true, false, true );
03340
03341 if (m_systrayBool)
03342 config.writePathEntry( "Exec", w->commandEdit->text().prepend("ksystraycmd ") );
03343 else
03344 config.writePathEntry( "Exec", w->commandEdit->text() );
03345 config.writePathEntry( "Path", w->pathEdit->lineEdit()->text() );
03346
03347
03348 QStringList mimeTypes;
03349 for( QListViewItem *item = w->filetypeList->firstChild();
03350 item; item = item->nextSibling() )
03351 {
03352 QString preference = item->text(2);
03353 mimeTypes.append(item->text(0));
03354 if (!preference.isEmpty())
03355 mimeTypes.append(preference);
03356 }
03357
03358 config.writeEntry( "MimeType", mimeTypes, ';' );
03359
03360 if ( !w->nameEdit->isHidden() ) {
03361 QString nameStr = w->nameEdit->text();
03362 config.writeEntry( "Name", nameStr );
03363 config.writeEntry( "Name", nameStr, true, false, true );
03364 }
03365
03366 config.writeEntry("Terminal", m_terminalBool);
03367 config.writeEntry("TerminalOptions", m_terminalOptionStr);
03368 config.writeEntry("X-KDE-SubstituteUID", m_suidBool);
03369 config.writeEntry("X-KDE-Username", m_suidUserStr);
03370 config.writeEntry("StartupNotify", m_startupBool);
03371 config.writeEntry("X-DCOP-ServiceType", m_dcopServiceType);
03372 config.sync();
03373
03374
03375 QString sycocaPath = KGlobal::dirs()->relativeLocation("apps", path);
03376 bool updateNeeded = !sycocaPath.startsWith("/");
03377 if (!updateNeeded)
03378 {
03379 sycocaPath = KGlobal::dirs()->relativeLocation("xdgdata-apps", path);
03380 updateNeeded = !sycocaPath.startsWith("/");
03381 }
03382 if (updateNeeded)
03383 KService::rebuildKSycoca(w);
03384 }
03385
03386
03387 void KDesktopPropsPlugin::slotBrowseExec()
03388 {
03389 KURL f = KFileDialog::getOpenURL( QString::null,
03390 QString::null, w );
03391 if ( f.isEmpty() )
03392 return;
03393
03394 if ( !f.isLocalFile()) {
03395 KMessageBox::sorry(w, i18n("Only executables on local file systems are supported."));
03396 return;
03397 }
03398
03399 QString path = f.path();
03400 KRun::shellQuote( path );
03401 w->commandEdit->setText( path );
03402 }
03403
03404 void KDesktopPropsPlugin::slotAdvanced()
03405 {
03406 KDialogBase dlg(w, "KPropertiesDesktopAdv", true,
03407 i18n("Advanced Options for %1").arg(properties->kurl().fileName()),
03408 KDialogBase::Ok|KDialogBase::Cancel, KDialogBase::Ok);
03409 KPropertiesDesktopAdvBase *w = new KPropertiesDesktopAdvBase(&dlg);
03410
03411 dlg.setMainWidget(w);
03412
03413
03414
03415 checkCommandChanged();
03416
03417
03418
03419 KConfigGroup confGroup( KGlobal::config(), QString::fromLatin1("General") );
03420 QString preferredTerminal = confGroup.readPathEntry("TerminalApplication",
03421 QString::fromLatin1("konsole"));
03422
03423 bool terminalCloseBool = false;
03424
03425 if (preferredTerminal == "konsole")
03426 {
03427 terminalCloseBool = (m_terminalOptionStr.contains( "--noclose" ) > 0);
03428 w->terminalCloseCheck->setChecked(terminalCloseBool);
03429 m_terminalOptionStr.replace( "--noclose", "");
03430 }
03431 else
03432 {
03433 w->terminalCloseCheck->hide();
03434 }
03435
03436 w->terminalCheck->setChecked(m_terminalBool);
03437 w->terminalEdit->setText(m_terminalOptionStr);
03438 w->terminalCloseCheck->setEnabled(m_terminalBool);
03439 w->terminalEdit->setEnabled(m_terminalBool);
03440 w->terminalEditLabel->setEnabled(m_terminalBool);
03441
03442 w->suidCheck->setChecked(m_suidBool);
03443 w->suidEdit->setText(m_suidUserStr);
03444 w->suidEdit->setEnabled(m_suidBool);
03445 w->suidEditLabel->setEnabled(m_suidBool);
03446
03447 w->startupInfoCheck->setChecked(m_startupBool);
03448 w->systrayCheck->setChecked(m_systrayBool);
03449
03450 if (m_dcopServiceType == "unique")
03451 w->dcopCombo->setCurrentItem(2);
03452 else if (m_dcopServiceType == "multi")
03453 w->dcopCombo->setCurrentItem(1);
03454 else if (m_dcopServiceType == "wait")
03455 w->dcopCombo->setCurrentItem(3);
03456 else
03457 w->dcopCombo->setCurrentItem(0);
03458
03459
03460 KCompletion *kcom = new KCompletion;
03461 kcom->setOrder(KCompletion::Sorted);
03462 struct passwd *pw;
03463 int i, maxEntries = 1000;
03464 setpwent();
03465 for (i=0; ((pw = getpwent()) != 0L) && (i < maxEntries); i++)
03466 kcom->addItem(QString::fromLatin1(pw->pw_name));
03467 endpwent();
03468 if (i < maxEntries)
03469 {
03470 w->suidEdit->setCompletionObject(kcom, true);
03471 w->suidEdit->setAutoDeleteCompletionObject( true );
03472 w->suidEdit->setCompletionMode(KGlobalSettings::CompletionAuto);
03473 }
03474 else
03475 {
03476 delete kcom;
03477 }
03478
03479 connect( w->terminalEdit, SIGNAL( textChanged( const QString & ) ),
03480 this, SIGNAL( changed() ) );
03481 connect( w->terminalCloseCheck, SIGNAL( toggled( bool ) ),
03482 this, SIGNAL( changed() ) );
03483 connect( w->terminalCheck, SIGNAL( toggled( bool ) ),
03484 this, SIGNAL( changed() ) );
03485 connect( w->suidCheck, SIGNAL( toggled( bool ) ),
03486 this, SIGNAL( changed() ) );
03487 connect( w->suidEdit, SIGNAL( textChanged( const QString & ) ),
03488 this, SIGNAL( changed() ) );
03489 connect( w->startupInfoCheck, SIGNAL( toggled( bool ) ),
03490 this, SIGNAL( changed() ) );
03491 connect( w->systrayCheck, SIGNAL( toggled( bool ) ),
03492 this, SIGNAL( changed() ) );
03493 connect( w->dcopCombo, SIGNAL( highlighted( int ) ),
03494 this, SIGNAL( changed() ) );
03495
03496 if ( dlg.exec() == QDialog::Accepted )
03497 {
03498 m_terminalOptionStr = w->terminalEdit->text().stripWhiteSpace();
03499 m_terminalBool = w->terminalCheck->isChecked();
03500 m_suidBool = w->suidCheck->isChecked();
03501 m_suidUserStr = w->suidEdit->text().stripWhiteSpace();
03502 m_startupBool = w->startupInfoCheck->isChecked();
03503 m_systrayBool = w->systrayCheck->isChecked();
03504
03505 if (w->terminalCloseCheck->isChecked())
03506 {
03507 m_terminalOptionStr.append(" --noclose");
03508 }
03509
03510 switch(w->dcopCombo->currentItem())
03511 {
03512 case 1: m_dcopServiceType = "multi"; break;
03513 case 2: m_dcopServiceType = "unique"; break;
03514 case 3: m_dcopServiceType = "wait"; break;
03515 default: m_dcopServiceType = "none"; break;
03516 }
03517 }
03518 }
03519
03520 bool KDesktopPropsPlugin::supports( KFileItemList _items )
03521 {
03522 if ( _items.count() != 1 )
03523 return false;
03524 KFileItem * item = _items.first();
03525
03526 if ( !KPropsDlgPlugin::isDesktopFile( item ) )
03527 return false;
03528
03529 KDesktopFile config( item->url().path(), true );
03530 return config.hasApplicationType() && kapp->authorize("run_desktop_files") && kapp->authorize("shell_access");
03531 }
03532
03533 void KPropertiesDialog::virtual_hook( int id, void* data )
03534 { KDialogBase::virtual_hook( id, data ); }
03535
03536 void KPropsDlgPlugin::virtual_hook( int, void* )
03537 { }
03538
03539
03540
03541
03542
03548 class KExecPropsPlugin::KExecPropsPluginPrivate
03549 {
03550 public:
03551 KExecPropsPluginPrivate()
03552 {
03553 }
03554 ~KExecPropsPluginPrivate()
03555 {
03556 }
03557
03558 QFrame *m_frame;
03559 QCheckBox *nocloseonexitCheck;
03560 };
03561
03562 KExecPropsPlugin::KExecPropsPlugin( KPropertiesDialog *_props )
03563 : KPropsDlgPlugin( _props )
03564 {
03565 d = new KExecPropsPluginPrivate;
03566 d->m_frame = properties->addPage(i18n("E&xecute"));
03567 QVBoxLayout * mainlayout = new QVBoxLayout( d->m_frame, 0,
03568 KDialog::spacingHint());
03569
03570
03571
03572 QLabel* l;
03573 l = new QLabel( i18n( "Comman&d:" ), d->m_frame );
03574 mainlayout->addWidget(l);
03575
03576 QHBoxLayout * hlayout;
03577 hlayout = new QHBoxLayout(KDialog::spacingHint());
03578 mainlayout->addLayout(hlayout);
03579
03580 execEdit = new KLineEdit( d->m_frame );
03581 QWhatsThis::add(execEdit,i18n(
03582 "Following the command, you can have several place holders which will be replaced "
03583 "with the actual values when the actual program is run:\n"
03584 "%f - a single file name\n"
03585 "%F - a list of files; use for applications that can open several local files at once\n"
03586 "%u - a single URL\n"
03587 "%U - a list of URLs\n"
03588 "%d - the folder of the file to open\n"
03589 "%D - a list of folders\n"
03590 "%i - the icon\n"
03591 "%m - the mini-icon\n"
03592 "%c - the caption"));
03593 hlayout->addWidget(execEdit, 1);
03594
03595 l->setBuddy( execEdit );
03596
03597 execBrowse = new QPushButton( d->m_frame );
03598 execBrowse->setText( i18n("&Browse...") );
03599 hlayout->addWidget(execBrowse);
03600
03601
03602 QGroupBox* tmpQGroupBox;
03603 tmpQGroupBox = new QGroupBox( i18n("Panel Embedding"), d->m_frame );
03604 tmpQGroupBox->setColumnLayout( 0, Qt::Horizontal );
03605
03606 mainlayout->addWidget(tmpQGroupBox);
03607
03608 QGridLayout *grid = new QGridLayout(tmpQGroupBox->layout(), 2, 2);
03609 grid->setSpacing( KDialog::spacingHint() );
03610 grid->setColStretch(1, 1);
03611
03612 l = new QLabel( i18n( "&Execute on click:" ), tmpQGroupBox );
03613 grid->addWidget(l, 0, 0);
03614
03615 swallowExecEdit = new KLineEdit( tmpQGroupBox );
03616 grid->addWidget(swallowExecEdit, 0, 1);
03617
03618 l->setBuddy( swallowExecEdit );
03619
03620 l = new QLabel( i18n( "&Window title:" ), tmpQGroupBox );
03621 grid->addWidget(l, 1, 0);
03622
03623 swallowTitleEdit = new KLineEdit( tmpQGroupBox );
03624 grid->addWidget(swallowTitleEdit, 1, 1);
03625
03626 l->setBuddy( swallowTitleEdit );
03627
03628
03629
03630 tmpQGroupBox = new QGroupBox( d->m_frame );
03631 tmpQGroupBox->setColumnLayout( 0, Qt::Horizontal );
03632
03633 mainlayout->addWidget(tmpQGroupBox);
03634
03635 grid = new QGridLayout(tmpQGroupBox->layout(), 3, 2);
03636 grid->setSpacing( KDialog::spacingHint() );
03637 grid->setColStretch(1, 1);
03638
03639 terminalCheck = new QCheckBox( tmpQGroupBox );
03640 terminalCheck->setText( i18n("&Run in terminal") );
03641 grid->addMultiCellWidget(terminalCheck, 0, 0, 0, 1);
03642
03643
03644
03645 KConfigGroup confGroup( KGlobal::config(), QString::fromLatin1("General") );
03646 QString preferredTerminal = confGroup.readPathEntry("TerminalApplication",
03647 QString::fromLatin1("konsole"));
03648
03649 int posOptions = 1;
03650 d->nocloseonexitCheck = 0L;
03651 if (preferredTerminal == "konsole")
03652 {
03653 posOptions = 2;
03654 d->nocloseonexitCheck = new QCheckBox( tmpQGroupBox );
03655 d->nocloseonexitCheck->setText( i18n("Do not &close when command exits") );
03656 grid->addMultiCellWidget(d->nocloseonexitCheck, 1, 1, 0, 1);
03657 }
03658
03659 terminalLabel = new QLabel( i18n( "&Terminal options:" ), tmpQGroupBox );
03660 grid->addWidget(terminalLabel, posOptions, 0);
03661
03662 terminalEdit = new KLineEdit( tmpQGroupBox );
03663 grid->addWidget(terminalEdit, posOptions, 1);
03664
03665 terminalLabel->setBuddy( terminalEdit );
03666
03667
03668
03669 tmpQGroupBox = new QGroupBox( d->m_frame );
03670 tmpQGroupBox->setColumnLayout( 0, Qt::Horizontal );
03671
03672 mainlayout->addWidget(tmpQGroupBox);
03673
03674 grid = new QGridLayout(tmpQGroupBox->layout(), 2, 2);
03675 grid->setSpacing(KDialog::spacingHint());
03676 grid->setColStretch(1, 1);
03677
03678 suidCheck = new QCheckBox(tmpQGroupBox);
03679 suidCheck->setText(i18n("Ru&n as a different user"));
03680 grid->addMultiCellWidget(suidCheck, 0, 0, 0, 1);
03681
03682 suidLabel = new QLabel(i18n( "&Username:" ), tmpQGroupBox);
03683 grid->addWidget(suidLabel, 1, 0);
03684
03685 suidEdit = new KLineEdit(tmpQGroupBox);
03686 grid->addWidget(suidEdit, 1, 1);
03687
03688 suidLabel->setBuddy( suidEdit );
03689
03690 mainlayout->addStretch(1);
03691
03692
03693 QString path = _props->kurl().path();
03694 QFile f( path );
03695 if ( !f.open( IO_ReadOnly ) )
03696 return;
03697 f.close();
03698
03699 KSimpleConfig config( path );
03700 config.setDollarExpansion( false );
03701 config.setDesktopGroup();
03702 execStr = config.readPathEntry( "Exec" );
03703 swallowExecStr = config.readPathEntry( "SwallowExec" );
03704 swallowTitleStr = config.readEntry( "SwallowTitle" );
03705 termBool = config.readBoolEntry( "Terminal" );
03706 termOptionsStr = config.readEntry( "TerminalOptions" );
03707 suidBool = config.readBoolEntry( "X-KDE-SubstituteUID" );
03708 suidUserStr = config.readEntry( "X-KDE-Username" );
03709
03710 if ( !swallowExecStr.isNull() )
03711 swallowExecEdit->setText( swallowExecStr );
03712 if ( !swallowTitleStr.isNull() )
03713 swallowTitleEdit->setText( swallowTitleStr );
03714
03715 if ( !execStr.isNull() )
03716 execEdit->setText( execStr );
03717
03718 if ( d->nocloseonexitCheck )
03719 {
03720 d->nocloseonexitCheck->setChecked( (termOptionsStr.contains( "--noclose" ) > 0) );
03721 termOptionsStr.replace( "--noclose", "");
03722 }
03723 if ( !termOptionsStr.isNull() )
03724 terminalEdit->setText( termOptionsStr );
03725
03726 terminalCheck->setChecked( termBool );
03727 enableCheckedEdit();
03728
03729 suidCheck->setChecked( suidBool );
03730 suidEdit->setText( suidUserStr );
03731 enableSuidEdit();
03732
03733
03734 KCompletion *kcom = new KCompletion;
03735 kcom->setOrder(KCompletion::Sorted);
03736 struct passwd *pw;
03737 int i, maxEntries = 1000;
03738 setpwent();
03739 for (i=0; ((pw = getpwent()) != 0L) && (i < maxEntries); i++)
03740 kcom->addItem(QString::fromLatin1(pw->pw_name));
03741 endpwent();
03742 if (i < maxEntries)
03743 {
03744 suidEdit->setCompletionObject(kcom, true);
03745 suidEdit->setAutoDeleteCompletionObject( true );
03746 suidEdit->setCompletionMode(KGlobalSettings::CompletionAuto);
03747 }
03748 else
03749 {
03750 delete kcom;
03751 }
03752
03753 connect( swallowExecEdit, SIGNAL( textChanged( const QString & ) ),
03754 this, SIGNAL( changed() ) );
03755 connect( swallowTitleEdit, SIGNAL( textChanged( const QString & ) ),
03756 this, SIGNAL( changed() ) );
03757 connect( execEdit, SIGNAL( textChanged( const QString & ) ),
03758 this, SIGNAL( changed() ) );
03759 connect( terminalEdit, SIGNAL( textChanged( const QString & ) ),
03760 this, SIGNAL( changed() ) );
03761 if (d->nocloseonexitCheck)
03762 connect( d->nocloseonexitCheck, SIGNAL( toggled( bool ) ),
03763 this, SIGNAL( changed() ) );
03764 connect( terminalCheck, SIGNAL( toggled( bool ) ),
03765 this, SIGNAL( changed() ) );
03766 connect( suidCheck, SIGNAL( toggled( bool ) ),
03767 this, SIGNAL( changed() ) );
03768 connect( suidEdit, SIGNAL( textChanged( const QString & ) ),
03769 this, SIGNAL( changed() ) );
03770
03771 connect( execBrowse, SIGNAL( clicked() ), this, SLOT( slotBrowseExec() ) );
03772 connect( terminalCheck, SIGNAL( clicked() ), this, SLOT( enableCheckedEdit() ) );
03773 connect( suidCheck, SIGNAL( clicked() ), this, SLOT( enableSuidEdit() ) );
03774
03775 }
03776
03777 KExecPropsPlugin::~KExecPropsPlugin()
03778 {
03779 delete d;
03780 }
03781
03782 void KExecPropsPlugin::enableCheckedEdit()
03783 {
03784 bool checked = terminalCheck->isChecked();
03785 terminalLabel->setEnabled( checked );
03786 if (d->nocloseonexitCheck)
03787 d->nocloseonexitCheck->setEnabled( checked );
03788 terminalEdit->setEnabled( checked );
03789 }
03790
03791 void KExecPropsPlugin::enableSuidEdit()
03792 {
03793 bool checked = suidCheck->isChecked();
03794 suidLabel->setEnabled( checked );
03795 suidEdit->setEnabled( checked );
03796 }
03797
03798 bool KExecPropsPlugin::supports( KFileItemList _items )
03799 {
03800 if ( _items.count() != 1 )
03801 return false;
03802 KFileItem * item = _items.first();
03803
03804 if ( !KPropsDlgPlugin::isDesktopFile( item ) )
03805 return false;
03806
03807 KDesktopFile config( item->url().path(), true );
03808 return config.hasApplicationType() && kapp->authorize("run_desktop_files") && kapp->authorize("shell_access");
03809 }
03810
03811 void KExecPropsPlugin::applyChanges()
03812 {
03813 kdDebug(250) << "KExecPropsPlugin::applyChanges" << endl;
03814 QString path = properties->kurl().path();
03815
03816 QFile f( path );
03817
03818 if ( !f.open( IO_ReadWrite ) ) {
03819 KMessageBox::sorry( 0, i18n("<qt>Could not save properties. You do not have "
03820 "sufficient access to write to <b>%1</b>.</qt>").arg(path));
03821 return;
03822 }
03823 f.close();
03824
03825 KSimpleConfig config( path );
03826 config.setDesktopGroup();
03827 config.writeEntry( "Type", QString::fromLatin1("Application"));
03828 config.writePathEntry( "Exec", execEdit->text() );
03829 config.writePathEntry( "SwallowExec", swallowExecEdit->text() );
03830 config.writeEntry( "SwallowTitle", swallowTitleEdit->text() );
03831 config.writeEntry( "Terminal", terminalCheck->isChecked() );
03832 QString temp = terminalEdit->text();
03833 if (d->nocloseonexitCheck )
03834 if ( d->nocloseonexitCheck->isChecked() )
03835 temp += QString::fromLatin1("--noclose ");
03836 temp = temp.stripWhiteSpace();
03837 config.writeEntry( "TerminalOptions", temp );
03838 config.writeEntry( "X-KDE-SubstituteUID", suidCheck->isChecked() );
03839 config.writeEntry( "X-KDE-Username", suidEdit->text() );
03840 }
03841
03842
03843 void KExecPropsPlugin::slotBrowseExec()
03844 {
03845 KURL f = KFileDialog::getOpenURL( QString::null,
03846 QString::null, d->m_frame );
03847 if ( f.isEmpty() )
03848 return;
03849
03850 if ( !f.isLocalFile()) {
03851 KMessageBox::sorry(d->m_frame, i18n("Only executables on local file systems are supported."));
03852 return;
03853 }
03854
03855 QString path = f.path();
03856 KRun::shellQuote( path );
03857 execEdit->setText( path );
03858 }
03859
03860 class KApplicationPropsPlugin::KApplicationPropsPluginPrivate
03861 {
03862 public:
03863 KApplicationPropsPluginPrivate()
03864 {
03865 m_kdesktopMode = QCString(qApp->name()) == "kdesktop";
03866 }
03867 ~KApplicationPropsPluginPrivate()
03868 {
03869 }
03870
03871 QFrame *m_frame;
03872 bool m_kdesktopMode;
03873 };
03874
03875 KApplicationPropsPlugin::KApplicationPropsPlugin( KPropertiesDialog *_props )
03876 : KPropsDlgPlugin( _props )
03877 {
03878 d = new KApplicationPropsPluginPrivate;
03879 d->m_frame = properties->addPage(i18n("&Application"));
03880 QVBoxLayout *toplayout = new QVBoxLayout( d->m_frame, 0, KDialog::spacingHint());
03881
03882 QIconSet iconSet;
03883 QPixmap pixMap;
03884
03885 addExtensionButton = new QPushButton( QString::null, d->m_frame );
03886 iconSet = SmallIconSet( "back" );
03887 addExtensionButton->setIconSet( iconSet );
03888 pixMap = iconSet.pixmap( QIconSet::Small, QIconSet::Normal );
03889 addExtensionButton->setFixedSize( pixMap.width()+8, pixMap.height()+8 );
03890 connect( addExtensionButton, SIGNAL( clicked() ),
03891 SLOT( slotAddExtension() ) );
03892
03893 delExtensionButton = new QPushButton( QString::null, d->m_frame );
03894 iconSet = SmallIconSet( "forward" );
03895 delExtensionButton->setIconSet( iconSet );
03896 delExtensionButton->setFixedSize( pixMap.width()+8, pixMap.height()+8 );
03897 connect( delExtensionButton, SIGNAL( clicked() ),
03898 SLOT( slotDelExtension() ) );
03899
03900 QLabel *l;
03901
03902 QGridLayout *grid = new QGridLayout(2, 2);
03903 grid->setColStretch(1, 1);
03904 toplayout->addLayout(grid);
03905
03906 if ( d->m_kdesktopMode )
03907 {
03908
03909 nameEdit = 0L;
03910 }
03911 else
03912 {
03913 l = new QLabel(i18n("Name:"), d->m_frame, "Label_4" );
03914 grid->addWidget(l, 0, 0);
03915
03916 nameEdit = new KLineEdit( d->m_frame, "LineEdit_3" );
03917 grid->addWidget(nameEdit, 0, 1);
03918 }
03919
03920 l = new QLabel(i18n("Description:"), d->m_frame, "Label_5" );
03921 grid->addWidget(l, 1, 0);
03922
03923 genNameEdit = new KLineEdit( d->m_frame, "LineEdit_4" );
03924 grid->addWidget(genNameEdit, 1, 1);
03925
03926 l = new QLabel(i18n("Comment:"), d->m_frame, "Label_3" );
03927 grid->addWidget(l, 2, 0);
03928
03929 commentEdit = new KLineEdit( d->m_frame, "LineEdit_2" );
03930 grid->addWidget(commentEdit, 2, 1);
03931
03932 l = new QLabel(i18n("File types:"), d->m_frame);
03933 toplayout->addWidget(l, 0, AlignLeft);
03934
03935 grid = new QGridLayout(4, 3);
03936 grid->setColStretch(0, 1);
03937 grid->setColStretch(2, 1);
03938 grid->setRowStretch( 0, 1 );
03939 grid->setRowStretch( 3, 1 );
03940 toplayout->addLayout(grid, 2);
03941
03942 extensionsList = new QListBox( d->m_frame );
03943 extensionsList->setSelectionMode( QListBox::Extended );
03944 grid->addMultiCellWidget(extensionsList, 0, 3, 0, 0);
03945
03946 grid->addWidget(addExtensionButton, 1, 1);
03947 grid->addWidget(delExtensionButton, 2, 1);
03948
03949 availableExtensionsList = new QListBox( d->m_frame );
03950 availableExtensionsList->setSelectionMode( QListBox::Extended );
03951 grid->addMultiCellWidget(availableExtensionsList, 0, 3, 2, 2);
03952
03953 QString path = properties->kurl().path() ;
03954 QFile f( path );
03955 if ( !f.open( IO_ReadOnly ) )
03956 return;
03957 f.close();
03958
03959 KDesktopFile config( path );
03960 QString commentStr = config.readComment();
03961 QString genNameStr = config.readGenericName();
03962
03963 QStringList selectedTypes = config.readListEntry( "ServiceTypes" );
03964
03965 selectedTypes += config.readListEntry( "MimeType", ';' );
03966
03967 QString nameStr = config.readName();
03968 if ( nameStr.isEmpty() || d->m_kdesktopMode ) {
03969
03970
03971
03972 setDirty();
03973 }
03974
03975 commentEdit->setText( commentStr );
03976 genNameEdit->setText( genNameStr );
03977 if ( nameEdit )
03978 nameEdit->setText( nameStr );
03979
03980 selectedTypes.sort();
03981 QStringList::Iterator sit = selectedTypes.begin();
03982 for( ; sit != selectedTypes.end(); ++sit ) {
03983 if ( !((*sit).isEmpty()) )
03984 extensionsList->insertItem( *sit );
03985 }
03986
03987 KMimeType::List mimeTypes = KMimeType::allMimeTypes();
03988 QValueListIterator<KMimeType::Ptr> it2 = mimeTypes.begin();
03989 for ( ; it2 != mimeTypes.end(); ++it2 )
03990 addMimeType ( (*it2)->name() );
03991
03992 updateButton();
03993
03994 connect( extensionsList, SIGNAL( highlighted( int ) ),
03995 this, SLOT( updateButton() ) );
03996 connect( availableExtensionsList, SIGNAL( highlighted( int ) ),
03997 this, SLOT( updateButton() ) );
03998
03999 connect( addExtensionButton, SIGNAL( clicked() ),
04000 this, SIGNAL( changed() ) );
04001 connect( delExtensionButton, SIGNAL( clicked() ),
04002 this, SIGNAL( changed() ) );
04003 if ( nameEdit )
04004 connect( nameEdit, SIGNAL( textChanged( const QString & ) ),
04005 this, SIGNAL( changed() ) );
04006 connect( commentEdit, SIGNAL( textChanged( const QString & ) ),
04007 this, SIGNAL( changed() ) );
04008 connect( genNameEdit, SIGNAL( textChanged( const QString & ) ),
04009 this, SIGNAL( changed() ) );
04010 connect( availableExtensionsList, SIGNAL( selected( int ) ),
04011 this, SIGNAL( changed() ) );
04012 connect( extensionsList, SIGNAL( selected( int ) ),
04013 this, SIGNAL( changed() ) );
04014 }
04015
04016 KApplicationPropsPlugin::~KApplicationPropsPlugin()
04017 {
04018 delete d;
04019 }
04020
04021
04022
04023
04024
04025
04026 void KApplicationPropsPlugin::updateButton()
04027 {
04028 addExtensionButton->setEnabled(availableExtensionsList->currentItem()>-1);
04029 delExtensionButton->setEnabled(extensionsList->currentItem()>-1);
04030 }
04031
04032 void KApplicationPropsPlugin::addMimeType( const QString & name )
04033 {
04034
04035
04036 bool insert = true;
04037
04038 for ( uint i = 0; i < extensionsList->count(); i++ )
04039 if ( extensionsList->text( i ) == name )
04040 insert = false;
04041
04042 if ( insert )
04043 {
04044 availableExtensionsList->insertItem( name );
04045 availableExtensionsList->sort();
04046 }
04047 }
04048
04049 bool KApplicationPropsPlugin::supports( KFileItemList _items )
04050 {
04051
04052 return KExecPropsPlugin::supports( _items );
04053 }
04054
04055 void KApplicationPropsPlugin::applyChanges()
04056 {
04057 QString path = properties->kurl().path();
04058
04059 QFile f( path );
04060
04061 if ( !f.open( IO_ReadWrite ) ) {
04062 KMessageBox::sorry( 0, i18n("<qt>Could not save properties. You do not "
04063 "have sufficient access to write to <b>%1</b>.</qt>").arg(path));
04064 return;
04065 }
04066 f.close();
04067
04068 KSimpleConfig config( path );
04069 config.setDesktopGroup();
04070 config.writeEntry( "Type", QString::fromLatin1("Application"));
04071 config.writeEntry( "Comment", commentEdit->text() );
04072 config.writeEntry( "Comment", commentEdit->text(), true, false, true );
04073 config.writeEntry( "GenericName", genNameEdit->text() );
04074 config.writeEntry( "GenericName", genNameEdit->text(), true, false, true );
04075
04076 QStringList selectedTypes;
04077 for ( uint i = 0; i < extensionsList->count(); i++ )
04078 selectedTypes.append( extensionsList->text( i ) );
04079
04080 config.writeEntry( "MimeType", selectedTypes, ';' );
04081 config.writeEntry( "ServiceTypes", "" );
04082
04083
04084 QString nameStr = nameEdit ? nameEdit->text() : QString::null;
04085 if ( nameStr.isEmpty() )
04086 nameStr = nameFromFileName(properties->kurl().fileName());
04087
04088 config.writeEntry( "Name", nameStr );
04089 config.writeEntry( "Name", nameStr, true, false, true );
04090
04091 config.sync();
04092 }
04093
04094 void KApplicationPropsPlugin::slotAddExtension()
04095 {
04096 QListBoxItem *item = availableExtensionsList->firstItem();
04097 QListBoxItem *nextItem;
04098
04099 while ( item )
04100 {
04101 nextItem = item->next();
04102
04103 if ( item->isSelected() )
04104 {
04105 extensionsList->insertItem( item->text() );
04106 availableExtensionsList->removeItem( availableExtensionsList->index( item ) );
04107 }
04108
04109 item = nextItem;
04110 }
04111
04112 extensionsList->sort();
04113 updateButton();
04114 }
04115
04116 void KApplicationPropsPlugin::slotDelExtension()
04117 {
04118 QListBoxItem *item = extensionsList->firstItem();
04119 QListBoxItem *nextItem;
04120
04121 while ( item )
04122 {
04123 nextItem = item->next();
04124
04125 if ( item->isSelected() )
04126 {
04127 availableExtensionsList->insertItem( item->text() );
04128 extensionsList->removeItem( extensionsList->index( item ) );
04129 }
04130
04131 item = nextItem;
04132 }
04133
04134 availableExtensionsList->sort();
04135 updateButton();
04136 }
04137
04138
04139
04140 #include "kpropertiesdialog.moc"