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