00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044 #include <config.h>
00045 extern "C" {
00046 #include <pwd.h>
00047 #include <grp.h>
00048 #include <time.h>
00049 }
00050 #include <unistd.h>
00051 #include <errno.h>
00052 #include <assert.h>
00053
00054 #include <qfile.h>
00055 #include <qdir.h>
00056 #include <qlabel.h>
00057 #include <qpushbutton.h>
00058 #include <qcheckbox.h>
00059 #include <qstrlist.h>
00060 #include <qstringlist.h>
00061 #include <qtextstream.h>
00062 #include <qpainter.h>
00063 #include <qlayout.h>
00064 #include <qcombobox.h>
00065 #include <qgroupbox.h>
00066 #include <qwhatsthis.h>
00067 #include <qtooltip.h>
00068
00069 #include <kapplication.h>
00070 #include <kdialog.h>
00071 #include <kdirsize.h>
00072 #include <kdirwatch.h>
00073 #include <kdirnotify_stub.h>
00074 #include <kdiskfreesp.h>
00075 #include <kdebug.h>
00076 #include <kdesktopfile.h>
00077 #include <kicondialog.h>
00078 #include <kurl.h>
00079 #include <kurlrequester.h>
00080 #include <klocale.h>
00081 #include <kglobal.h>
00082 #include <kglobalsettings.h>
00083 #include <kstandarddirs.h>
00084 #include <kio/job.h>
00085 #include <kio/chmodjob.h>
00086 #include <kio/renamedlg.h>
00087 #include <kio/netaccess.h>
00088 #include <kfiledialog.h>
00089 #include <kmimetype.h>
00090 #include <kmountpoint.h>
00091 #include <kiconloader.h>
00092 #include <kmessagebox.h>
00093 #include <kservice.h>
00094 #include <kcompletion.h>
00095 #include <klineedit.h>
00096 #include <kseparator.h>
00097 #include <ksqueezedtextlabel.h>
00098 #include <klibloader.h>
00099 #include <ktrader.h>
00100 #include <kparts/componentfactory.h>
00101 #include <kmetaprops.h>
00102 #include <kprocess.h>
00103 #include <krun.h>
00104 #include <klistview.h>
00105 #include "kfilesharedlg.h"
00106
00107 #include "kpropertiesdesktopbase.h"
00108 #include "kpropertiesdesktopadvbase.h"
00109 #include "kpropertiesmimetypebase.h"
00110
00111 #include "kpropertiesdialog.h"
00112
00113 mode_t KFilePermissionsPropsPlugin::fperm[3][4] = {
00114 {S_IRUSR, S_IWUSR, S_IXUSR, S_ISUID},
00115 {S_IRGRP, S_IWGRP, S_IXGRP, S_ISGID},
00116 {S_IROTH, S_IWOTH, S_IXOTH, S_ISVTX}
00117 };
00118
00119 class KPropertiesDialog::KPropertiesDialogPrivate
00120 {
00121 public:
00122 KPropertiesDialogPrivate()
00123 {
00124 m_aborted = false;
00125 }
00126 ~KPropertiesDialogPrivate()
00127 {
00128 }
00129 bool m_aborted:1;
00130 };
00131
00132 KPropertiesDialog::KPropertiesDialog (KFileItem* item,
00133 QWidget* parent, const char* name,
00134 bool modal, bool autoShow)
00135 : KDialogBase (KDialogBase::Tabbed, i18n( "Properties for %1" ).arg(KIO::decodeFileName(item->url().fileName())),
00136 KDialogBase::Ok | KDialogBase::Cancel, KDialogBase::Ok,
00137 parent, name, modal)
00138 {
00139 d = new KPropertiesDialogPrivate;
00140 assert( item );
00141 m_items.append( new KFileItem(*item) );
00142
00143 m_singleUrl = item->url();
00144 assert(!m_singleUrl.isEmpty());
00145
00146 init (modal, autoShow);
00147 }
00148
00149 KPropertiesDialog::KPropertiesDialog (const QString& title,
00150 QWidget* parent, const char* name, bool modal)
00151 : KDialogBase (KDialogBase::Tabbed, i18n ("Properties for %1").arg(title),
00152 KDialogBase::Ok | KDialogBase::Cancel, KDialogBase::Ok,
00153 parent, name, modal)
00154 {
00155 d = new KPropertiesDialogPrivate;
00156
00157 init (modal, false);
00158 }
00159
00160 KPropertiesDialog::KPropertiesDialog (KFileItemList _items,
00161 QWidget* parent, const char* name,
00162 bool modal, bool autoShow)
00163 : KDialogBase (KDialogBase::Tabbed,
00164 i18n( "Properties for %1" ).arg(KIO::decodeFileName(_items.first()->url().fileName())),
00165 KDialogBase::Ok | KDialogBase::Cancel, KDialogBase::Ok,
00166 parent, name, modal)
00167 {
00168 d = new KPropertiesDialogPrivate;
00169
00170 assert( !_items.isEmpty() );
00171 m_singleUrl = _items.first()->url();
00172 assert(!m_singleUrl.isEmpty());
00173
00174 KFileItemListIterator it ( _items );
00175
00176 for ( ; it.current(); ++it )
00177 m_items.append( new KFileItem( **it ) );
00178
00179 init (modal, autoShow);
00180 }
00181
00182 #ifndef KDE_NO_COMPAT
00183 KPropertiesDialog::KPropertiesDialog (const KURL& _url, mode_t ,
00184 QWidget* parent, const char* name,
00185 bool modal, bool autoShow)
00186 : KDialogBase (KDialogBase::Tabbed,
00187 i18n( "Properties for %1" ).arg(KIO::decodeFileName(_url.fileName())),
00188 KDialogBase::Ok | KDialogBase::Cancel, KDialogBase::Ok,
00189 parent, name, modal),
00190 m_singleUrl( _url )
00191 {
00192 d = new KPropertiesDialogPrivate;
00193
00194 KIO::UDSEntry entry;
00195
00196 KIO::NetAccess::stat(_url, entry, parent);
00197
00198 m_items.append( new KFileItem( entry, _url ) );
00199 init (modal, autoShow);
00200 }
00201 #endif
00202
00203 KPropertiesDialog::KPropertiesDialog (const KURL& _url,
00204 QWidget* parent, const char* name,
00205 bool modal, bool autoShow)
00206 : KDialogBase (KDialogBase::Tabbed,
00207 i18n( "Properties for %1" ).arg(KIO::decodeFileName(_url.fileName())),
00208 KDialogBase::Ok | KDialogBase::Cancel, KDialogBase::Ok,
00209 parent, name, modal),
00210 m_singleUrl( _url )
00211 {
00212 d = new KPropertiesDialogPrivate;
00213
00214 KIO::UDSEntry entry;
00215
00216 KIO::NetAccess::stat(_url, entry, parent);
00217
00218 m_items.append( new KFileItem( entry, _url ) );
00219 init (modal, autoShow);
00220 }
00221
00222 KPropertiesDialog::KPropertiesDialog (const KURL& _tempUrl, const KURL& _currentDir,
00223 const QString& _defaultName,
00224 QWidget* parent, const char* name,
00225 bool modal, bool autoShow)
00226 : KDialogBase (KDialogBase::Tabbed,
00227 i18n( "Properties for %1" ).arg(KIO::decodeFileName(_tempUrl.fileName())),
00228 KDialogBase::Ok | KDialogBase::Cancel, KDialogBase::Ok,
00229 parent, name, modal),
00230
00231 m_singleUrl( _tempUrl ),
00232 m_defaultName( _defaultName ),
00233 m_currentDir( _currentDir )
00234 {
00235 d = new KPropertiesDialogPrivate;
00236
00237 assert(!m_singleUrl.isEmpty());
00238
00239
00240 m_items.append( new KFileItem( KFileItem::Unknown, KFileItem::Unknown, m_singleUrl ) );
00241 init (modal, autoShow);
00242 }
00243
00244 void KPropertiesDialog::init (bool modal, bool autoShow)
00245 {
00246 m_pageList.setAutoDelete( true );
00247 m_items.setAutoDelete( true );
00248
00249 insertPages();
00250
00251 if (autoShow)
00252 {
00253 if (!modal)
00254 show();
00255 else
00256 exec();
00257 }
00258 }
00259
00260 void KPropertiesDialog::showFileSharingPage()
00261 {
00262 KPropsDlgPlugin *it;
00263
00264 for ( it=m_pageList.first(); it != 0L; it=m_pageList.next() )
00265 {
00266 KFileSharePropsPlugin* plugin = dynamic_cast<KFileSharePropsPlugin*>(it);
00267 if ( plugin )
00268 {
00269 showPage( pageIndex( plugin->page() ) );
00270 break;
00271 }
00272 }
00273 }
00274
00275 void KPropertiesDialog::setFileNameReadOnly( bool ro )
00276 {
00277 KPropsDlgPlugin *it;
00278
00279 for ( it=m_pageList.first(); it != 0L; it=m_pageList.next() )
00280 {
00281 KFilePropsPlugin* plugin = dynamic_cast<KFilePropsPlugin*>(it);
00282 if ( plugin ) {
00283 plugin->setFileNameReadOnly( ro );
00284 break;
00285 }
00286 }
00287 }
00288
00289 void KPropertiesDialog::slotStatResult( KIO::Job * )
00290 {
00291 }
00292
00293 KPropertiesDialog::~KPropertiesDialog()
00294 {
00295 m_pageList.clear();
00296 delete d;
00297 }
00298
00299 void KPropertiesDialog::insertPlugin (KPropsDlgPlugin* plugin)
00300 {
00301 connect (plugin, SIGNAL (changed ()),
00302 plugin, SLOT (setDirty ()));
00303
00304 m_pageList.append (plugin);
00305 }
00306
00307 bool KPropertiesDialog::canDisplay( KFileItemList _items )
00308 {
00309
00310 return KFilePropsPlugin::supports( _items ) ||
00311 KFilePermissionsPropsPlugin::supports( _items ) ||
00312 KDesktopPropsPlugin::supports( _items ) ||
00313 KBindingPropsPlugin::supports( _items ) ||
00314 KURLPropsPlugin::supports( _items ) ||
00315 KDevicePropsPlugin::supports( _items ) ||
00316 KFileMetaPropsPlugin::supports( _items );
00317 }
00318
00319 void KPropertiesDialog::slotOk()
00320 {
00321 KPropsDlgPlugin *page;
00322 d->m_aborted = false;
00323
00324 KFilePropsPlugin * filePropsPlugin = 0L;
00325 if ( m_pageList.first()->isA("KFilePropsPlugin") )
00326 filePropsPlugin = static_cast<KFilePropsPlugin *>(m_pageList.first());
00327
00328
00329
00330
00331 for ( page = m_pageList.first(); page != 0L; page = m_pageList.next() )
00332 if ( page->isDirty() && filePropsPlugin )
00333 {
00334 filePropsPlugin->setDirty();
00335 break;
00336 }
00337
00338
00339
00340
00341
00342 for ( page = m_pageList.first(); page != 0L && !d->m_aborted; page = m_pageList.next() )
00343 if ( page->isDirty() )
00344 {
00345 kdDebug( 250 ) << "applying changes for " << page->className() << endl;
00346 page->applyChanges();
00347
00348 }
00349 else
00350 kdDebug( 250 ) << "skipping page " << page->className() << endl;
00351
00352 if ( !d->m_aborted && filePropsPlugin )
00353 filePropsPlugin->postApplyChanges();
00354
00355 if ( !d->m_aborted )
00356 {
00357 emit applied();
00358 emit propertiesClosed();
00359 deleteLater();
00360 accept();
00361 }
00362 }
00363
00364 void KPropertiesDialog::slotCancel()
00365 {
00366 emit canceled();
00367 emit propertiesClosed();
00368
00369 deleteLater();
00370 done( Rejected );
00371 }
00372
00373 void KPropertiesDialog::insertPages()
00374 {
00375 if (m_items.isEmpty())
00376 return;
00377
00378 if ( KFilePropsPlugin::supports( m_items ) )
00379 {
00380 KPropsDlgPlugin *p = new KFilePropsPlugin( this );
00381 insertPlugin (p);
00382 }
00383
00384 if ( KFilePermissionsPropsPlugin::supports( m_items ) )
00385 {
00386 KPropsDlgPlugin *p = new KFilePermissionsPropsPlugin( this );
00387 insertPlugin (p);
00388 }
00389
00390 if ( KDesktopPropsPlugin::supports( m_items ) )
00391 {
00392 KPropsDlgPlugin *p = new KDesktopPropsPlugin( this );
00393 insertPlugin (p);
00394 }
00395
00396 if ( KBindingPropsPlugin::supports( m_items ) )
00397 {
00398 KPropsDlgPlugin *p = new KBindingPropsPlugin( this );
00399 insertPlugin (p);
00400 }
00401
00402 if ( KURLPropsPlugin::supports( m_items ) )
00403 {
00404 KPropsDlgPlugin *p = new KURLPropsPlugin( this );
00405 insertPlugin (p);
00406 }
00407
00408 if ( KDevicePropsPlugin::supports( m_items ) )
00409 {
00410 KPropsDlgPlugin *p = new KDevicePropsPlugin( this );
00411 insertPlugin (p);
00412 }
00413
00414 if ( KFileMetaPropsPlugin::supports( m_items ) )
00415 {
00416 KPropsDlgPlugin *p = new KFileMetaPropsPlugin( this );
00417 insertPlugin (p);
00418 }
00419
00420
00421 if ( KFileSharePropsPlugin::supports( m_items ) )
00422 {
00423
00424 QString path = m_items.first()->url().path(-1);
00425 bool isLocal = m_items.first()->url().isLocalFile();
00426 bool isIntoTrash = isLocal && path.startsWith(KGlobalSettings::trashPath());
00427 if ( !isIntoTrash )
00428 {
00429 KPropsDlgPlugin *p = new KFileSharePropsPlugin( this );
00430 insertPlugin (p);
00431 }
00432 }
00433
00434
00435
00436 if ( m_items.count() != 1 )
00437 return;
00438
00439 KFileItem *item = m_items.first();
00440 QString mimetype = item->mimetype();
00441
00442 if ( mimetype.isEmpty() )
00443 return;
00444
00445 QString query = QString::fromLatin1(
00446 "('KPropsDlg/Plugin' in ServiceTypes) and "
00447 "((not exist [X-KDE-Protocol]) or "
00448 " ([X-KDE-Protocol] == '%1' ) )" ).arg(item->url().protocol());
00449
00450 kdDebug( 250 ) << "trader query: " << query << endl;
00451 KTrader::OfferList offers = KTrader::self()->query( mimetype, query );
00452 KTrader::OfferList::ConstIterator it = offers.begin();
00453 KTrader::OfferList::ConstIterator end = offers.end();
00454 for (; it != end; ++it )
00455 {
00456 KPropsDlgPlugin *plugin = KParts::ComponentFactory
00457 ::createInstanceFromLibrary<KPropsDlgPlugin>( (*it)->library().local8Bit().data(),
00458 this,
00459 (*it)->name().latin1() );
00460 if ( !plugin )
00461 continue;
00462
00463 insertPlugin( plugin );
00464 }
00465 }
00466
00467 void KPropertiesDialog::updateUrl( const KURL& _newUrl )
00468 {
00469 Q_ASSERT( m_items.count() == 1 );
00470 kdDebug(250) << "KPropertiesDialog::updateUrl (pre)" << _newUrl.url() << endl;
00471 KURL newUrl = _newUrl;
00472 emit saveAs(m_singleUrl, newUrl);
00473 kdDebug(250) << "KPropertiesDialog::updateUrl (post)" << newUrl.url() << endl;
00474
00475 m_singleUrl = newUrl;
00476 m_items.first()->setURL( newUrl );
00477 assert(!m_singleUrl.isEmpty());
00478
00479
00480 for ( QPtrListIterator<KPropsDlgPlugin> it(m_pageList); it.current(); ++it )
00481 if ( it.current()->isA("KExecPropsPlugin") ||
00482 it.current()->isA("KURLPropsPlugin") ||
00483 it.current()->isA("KDesktopPropsPlugin"))
00484 {
00485
00486 it.current()->setDirty();
00487 break;
00488 }
00489 }
00490
00491 void KPropertiesDialog::rename( const QString& _name )
00492 {
00493 Q_ASSERT( m_items.count() == 1 );
00494 kdDebug(250) << "KPropertiesDialog::rename " << _name << endl;
00495 KURL newUrl;
00496
00497 if ( !m_currentDir.isEmpty() )
00498 {
00499 newUrl = m_currentDir;
00500 newUrl.addPath( _name );
00501 }
00502 else
00503 {
00504 QString tmpurl = m_singleUrl.url();
00505 if ( tmpurl.at(tmpurl.length() - 1) == '/')
00506
00507 tmpurl.truncate( tmpurl.length() - 1);
00508 newUrl = tmpurl;
00509 newUrl.setFileName( _name );
00510 }
00511 updateUrl( newUrl );
00512 }
00513
00514 void KPropertiesDialog::abortApplying()
00515 {
00516 d->m_aborted = true;
00517 }
00518
00519 class KPropsDlgPlugin::KPropsDlgPluginPrivate
00520 {
00521 public:
00522 KPropsDlgPluginPrivate()
00523 {
00524 }
00525 ~KPropsDlgPluginPrivate()
00526 {
00527 }
00528
00529 bool m_bDirty;
00530 };
00531
00532 KPropsDlgPlugin::KPropsDlgPlugin( KPropertiesDialog *_props )
00533 : QObject( _props, 0L )
00534 {
00535 d = new KPropsDlgPluginPrivate;
00536 properties = _props;
00537 fontHeight = 2*properties->fontMetrics().height();
00538 d->m_bDirty = false;
00539 }
00540
00541 KPropsDlgPlugin::~KPropsDlgPlugin()
00542 {
00543 delete d;
00544 }
00545
00546 bool KPropsDlgPlugin::isDesktopFile( KFileItem * _item )
00547 {
00548
00549 if ( !_item->isLocalFile() )
00550 return false;
00551
00552
00553 if ( !S_ISREG( _item->mode() ) )
00554 return false;
00555
00556 QString t( _item->url().path() );
00557
00558
00559 FILE *f = fopen( QFile::encodeName(t), "r" );
00560 if ( f == 0L )
00561 return false;
00562 fclose(f);
00563
00564
00565 return ( _item->mimetype() == "application/x-desktop" );
00566 }
00567
00568 void KPropsDlgPlugin::setDirty( bool b )
00569 {
00570 d->m_bDirty = b;
00571 }
00572
00573 void KPropsDlgPlugin::setDirty()
00574 {
00575 d->m_bDirty = true;
00576 }
00577
00578 bool KPropsDlgPlugin::isDirty() const
00579 {
00580 return d->m_bDirty;
00581 }
00582
00583 void KPropsDlgPlugin::applyChanges()
00584 {
00585 kdWarning(250) << "applyChanges() not implemented in page !" << endl;
00586 }
00587
00589
00590 class KFilePropsPlugin::KFilePropsPluginPrivate
00591 {
00592 public:
00593 KFilePropsPluginPrivate()
00594 {
00595 dirSizeJob = 0L;
00596 dirSizeUpdateTimer = 0L;
00597 m_lined = 0;
00598 }
00599 ~KFilePropsPluginPrivate()
00600 {
00601 if ( dirSizeJob )
00602 dirSizeJob->kill();
00603 }
00604
00605 KDirSize * dirSizeJob;
00606 QTimer *dirSizeUpdateTimer;
00607 QFrame *m_frame;
00608 bool bMultiple;
00609 bool bIconChanged;
00610 bool bKDesktopMode;
00611 QLabel *m_freeSpaceLabel;
00612 QString mimeType;
00613 KLineEdit* m_lined;
00614 };
00615
00616 KFilePropsPlugin::KFilePropsPlugin( KPropertiesDialog *_props )
00617 : KPropsDlgPlugin( _props )
00618 {
00619 d = new KFilePropsPluginPrivate;
00620 d->bMultiple = (properties->items().count() > 1);
00621 d->bIconChanged = false;
00622 d->bKDesktopMode = (QCString(qApp->name()) == "kdesktop");
00623 kdDebug(250) << "KFilePropsPlugin::KFilePropsPlugin bMultiple=" << d->bMultiple << endl;
00624
00625
00626
00627 bool isLocal = properties->kurl().isLocalFile();
00628 KFileItem * item = properties->item();
00629 bool bDesktopFile = isDesktopFile(item);
00630 mode_t mode = item->mode();
00631 bool hasDirs = item->isDir() && !item->isLink();
00632 bool hasRoot = isLocal && properties->kurl().path() == QString::fromLatin1("/");
00633 QString iconStr = KMimeType::iconForURL(properties->kurl(), mode);
00634 QString directory = properties->kurl().directory();
00635 QString protocol = properties->kurl().protocol();
00636 QString mimeComment = item->mimeComment();
00637 d->mimeType = item->mimetype();
00638 KIO::filesize_t totalSize = item->size();
00639 QString magicMimeComment;
00640 if ( isLocal ) {
00641 KMimeType::Ptr magicMimeType = KMimeType::findByFileContent( properties->kurl().path() );
00642 if ( magicMimeType->name() != KMimeType::defaultMimeType() )
00643 magicMimeComment = magicMimeType->comment();
00644 }
00645
00646
00647 QString filename = QString::null;
00648 bool isTrash = false;
00649 bool isIntoTrash = false;
00650 bool isDevice = false;
00651 m_bFromTemplate = false;
00652
00653
00654 uint iDirCount = S_ISDIR(mode) ? 1 : 0;
00655 uint iFileCount = 1-iDirCount;
00656
00657 d->m_frame = properties->addPage (i18n("&General"));
00658
00659 QVBoxLayout *vbl = new QVBoxLayout( d->m_frame, 0,
00660 KDialog::spacingHint(), "vbl");
00661 QGridLayout *grid = new QGridLayout(0, 3);
00662 grid->setColStretch(0, 0);
00663 grid->setColStretch(1, 0);
00664 grid->setColStretch(2, 1);
00665 grid->addColSpacing(1, KDialog::spacingHint());
00666 vbl->addLayout(grid);
00667 int curRow = 0;
00668
00669 if ( !d->bMultiple )
00670 {
00671
00672 filename = properties->defaultName();
00673 if ( filename.isEmpty() )
00674 filename = properties->kurl().fileName();
00675 else
00676 {
00677 m_bFromTemplate = true;
00678 setDirty();
00679 }
00680
00681 bool isDesktopFile = KDesktopPropsPlugin::supports(properties->items());
00682 if ( d->bKDesktopMode && isDesktopFile ) {
00683 KDesktopFile config( properties->kurl().path(), true );
00684 if ( config.hasKey( "Name" ) ) {
00685 filename = config.readName();
00686 }
00687 }
00688
00689 oldName = filename;
00690
00691
00692 filename = KIO::decodeFileName( filename );
00693
00694 QString path;
00695
00696 if ( !m_bFromTemplate ) {
00697 QString tmp = properties->kurl().path( 1 );
00698
00699 if ( isLocal )
00700 {
00701 if ( tmp == KGlobalSettings::trashPath())
00702 isTrash = true;
00703 if ( tmp.startsWith(KGlobalSettings::trashPath()))
00704 isIntoTrash = true;
00705 }
00706 if ( properties->kurl().protocol().find("device", 0, false)==0)
00707 isDevice = true;
00708
00709 if ( isLocal )
00710 path = properties->kurl().path();
00711 else
00712 path = properties->kurl().prettyURL();
00713 } else {
00714 path = properties->currentDir().path(1) + properties->defaultName();
00715 directory = properties->currentDir().prettyURL();
00716 }
00717
00718 if (KExecPropsPlugin::supports(properties->items()) ||
00719 isDesktopFile ||
00720 KBindingPropsPlugin::supports(properties->items())) {
00721
00722 determineRelativePath( path );
00723
00724 }
00725
00726 }
00727 else
00728 {
00729
00730 KFileItemList items = properties->items();
00731 KFileItemListIterator it( items );
00732 for ( ++it ; it.current(); ++it )
00733 {
00734 KURL url = (*it)->url();
00735 kdDebug(250) << "KFilePropsPlugin::KFilePropsPlugin " << url.prettyURL() << endl;
00736
00737
00738 if ( url.isLocalFile() != isLocal )
00739 isLocal = false;
00740 if ( bDesktopFile && isDesktopFile(*it) != bDesktopFile )
00741 bDesktopFile = false;
00742 if ( (*it)->mode() != mode )
00743 mode = (mode_t)0;
00744 if ( KMimeType::iconForURL(url, mode) != iconStr )
00745 iconStr = "kmultiple";
00746 if ( url.directory() != directory )
00747 directory = QString::null;
00748 if ( url.protocol() != protocol )
00749 protocol = QString::null;
00750 if ( !mimeComment.isNull() && (*it)->mimeComment() != mimeComment )
00751 mimeComment = QString::null;
00752 if ( isLocal && !magicMimeComment.isNull() ) {
00753 KMimeType::Ptr magicMimeType = KMimeType::findByFileContent( url.path() );
00754 if ( magicMimeType->comment() != magicMimeComment )
00755 magicMimeComment = QString::null;
00756 }
00757
00758 if ( isLocal && url.path() == QString::fromLatin1("/") )
00759 hasRoot = true;
00760 if ( (*it)->isDir() && !(*it)->isLink() )
00761 {
00762 iDirCount++;
00763 hasDirs = true;
00764 }
00765 else
00766 {
00767 iFileCount++;
00768 totalSize += (*it)->size();
00769 }
00770 }
00771 }
00772
00773 if (!isLocal && !protocol.isEmpty())
00774 {
00775 directory += ' ';
00776 directory += '(';
00777 directory += protocol;
00778 directory += ')';
00779 }
00780
00781 if ( !isDevice && !isIntoTrash && (bDesktopFile || S_ISDIR(mode)) && !d->bMultiple )
00782 {
00783 KIconButton *iconButton = new KIconButton( d->m_frame );
00784 iconButton->setFixedSize(70, 70);
00785 iconButton->setStrictIconSize(false);
00786 iconButton->setIconType(KIcon::Desktop, KIcon::Device);
00787
00788
00789 QString iconStr = KMimeType::findByURL( properties->kurl(),
00790 mode )->icon( properties->kurl(),
00791 isLocal );
00792 if ( bDesktopFile && isLocal )
00793 {
00794 KSimpleConfig config( properties->kurl().path() );
00795 config.setDesktopGroup();
00796 iconStr = config.readEntry( "Icon" );
00797 }
00798 iconButton->setIcon(iconStr);
00799 iconArea = iconButton;
00800 connect( iconButton, SIGNAL( iconChanged(QString) ),
00801 this, SLOT( slotIconChanged() ) );
00802 } else {
00803 QLabel *iconLabel = new QLabel( d->m_frame );
00804 iconLabel->setFixedSize(70, 70);
00805 iconLabel->setPixmap( DesktopIcon( iconStr ) );
00806 iconArea = iconLabel;
00807 }
00808 grid->addWidget(iconArea, curRow, 0, AlignLeft);
00809
00810 if (d->bMultiple || isTrash || isIntoTrash || isDevice || filename == QString::fromLatin1("/"))
00811 {
00812 QLabel *lab = new QLabel(d->m_frame );
00813 if ( d->bMultiple )
00814 lab->setText( KIO::itemsSummaryString( iFileCount + iDirCount, iFileCount, iDirCount, 0, false ) );
00815 else
00816 lab->setText( filename );
00817 nameArea = lab;
00818 } else
00819 {
00820 d->m_lined = new KLineEdit( d->m_frame );
00821 d->m_lined->setText(filename);
00822 nameArea = d->m_lined;
00823 d->m_lined->setFocus();
00824 connect( d->m_lined, SIGNAL( textChanged( const QString & ) ),
00825 this, SLOT( nameFileChanged(const QString & ) ) );
00826 }
00827
00828 grid->addWidget(nameArea, curRow++, 2);
00829
00830 KSeparator* sep = new KSeparator( KSeparator::HLine, d->m_frame);
00831 grid->addMultiCellWidget(sep, curRow, curRow, 0, 2);
00832 ++curRow;
00833
00834 QLabel *l;
00835 if ( !mimeComment.isEmpty() && !isDevice && !isIntoTrash)
00836 {
00837 l = new QLabel(i18n("Type:"), d->m_frame );
00838
00839 grid->addWidget(l, curRow, 0);
00840
00841 QHBox *box = new QHBox(d->m_frame);
00842 l = new QLabel(mimeComment, box );
00843
00844 QPushButton *button = new QPushButton(box);
00845
00846 QIconSet iconSet = SmallIconSet(QString::fromLatin1("configure"));
00847 QPixmap pixMap = iconSet.pixmap( QIconSet::Small, QIconSet::Normal );
00848 button->setIconSet( iconSet );
00849 button->setFixedSize( pixMap.width()+8, pixMap.height()+8 );
00850 QToolTip::add(button, i18n("Edit file type"));
00851
00852 connect( button, SIGNAL( clicked() ), SLOT( slotEditFileType() ));
00853
00854
00855 grid->addWidget(box, curRow++, 2);
00856 }
00857
00858 if ( !magicMimeComment.isEmpty() && magicMimeComment != mimeComment )
00859 {
00860 l = new QLabel(i18n("Contents:"), d->m_frame );
00861 grid->addWidget(l, curRow, 0);
00862
00863 l = new QLabel(magicMimeComment, d->m_frame );
00864 grid->addWidget(l, curRow++, 2);
00865 }
00866
00867 if ( !directory.isEmpty() )
00868 {
00869 l = new QLabel( i18n("Location:"), d->m_frame );
00870 grid->addWidget(l, curRow, 0);
00871
00872 l = new KSqueezedTextLabel( d->m_frame );
00873 l->setText( directory );
00874 grid->addWidget(l, curRow++, 2);
00875 }
00876
00877 l = new QLabel(i18n("Size:"), d->m_frame );
00878 grid->addWidget(l, curRow, 0);
00879
00880 m_sizeLabel = new QLabel( d->m_frame );
00881 grid->addWidget( m_sizeLabel, curRow++, 2 );
00882
00883 if ( !hasDirs )
00884 {
00885 m_sizeLabel->setText(QString::fromLatin1("%1 (%2)").arg(KIO::convertSize(totalSize))
00886 .arg(KGlobal::locale()->formatNumber(totalSize, 0)));
00887 m_sizeDetermineButton = 0L;
00888 m_sizeStopButton = 0L;
00889 }
00890 else
00891 {
00892 QHBoxLayout * sizelay = new QHBoxLayout(KDialog::spacingHint());
00893 grid->addLayout( sizelay, curRow++, 2 );
00894
00895
00896 m_sizeDetermineButton = new QPushButton( i18n("Calculate"), d->m_frame );
00897 m_sizeStopButton = new QPushButton( i18n("Stop"), d->m_frame );
00898 connect( m_sizeDetermineButton, SIGNAL( clicked() ), this, SLOT( slotSizeDetermine() ) );
00899 connect( m_sizeStopButton, SIGNAL( clicked() ), this, SLOT( slotSizeStop() ) );
00900 sizelay->addWidget(m_sizeDetermineButton, 0);
00901 sizelay->addWidget(m_sizeStopButton, 0);
00902 sizelay->addStretch(10);
00903
00904
00905 if ( isLocal && !hasRoot )
00906 {
00907 m_sizeDetermineButton->setText( i18n("Refresh") );
00908 slotSizeDetermine();
00909 }
00910 else
00911 m_sizeStopButton->setEnabled( false );
00912 }
00913
00914 if ( isLocal )
00915 {
00916 QString mountPoint = KIO::findPathMountPoint( properties->item()->url().path() );
00917
00918 if (mountPoint != "/")
00919 {
00920 l = new QLabel(i18n("Mounted on:"), d->m_frame );
00921 grid->addWidget(l, curRow, 0);
00922
00923 l = new KSqueezedTextLabel( mountPoint, d->m_frame );
00924 grid->addWidget( l, curRow++, 2 );
00925 }
00926
00927 l = new QLabel(i18n("Free disk space:"), d->m_frame );
00928 grid->addWidget(l, curRow, 0);
00929
00930 d->m_freeSpaceLabel = new QLabel( d->m_frame );
00931 grid->addWidget( d->m_freeSpaceLabel, curRow++, 2 );
00932
00933 KDiskFreeSp * job = new KDiskFreeSp;
00934 connect( job, SIGNAL( foundMountPoint( const unsigned long&, const unsigned long&,
00935 const unsigned long&, const QString& ) ),
00936 this, SLOT( slotFoundMountPoint( const unsigned long&, const unsigned long&,
00937 const unsigned long&, const QString& ) ) );
00938 job->readDF( mountPoint );
00939 }
00940
00941 if (!d->bMultiple && item->isLink()) {
00942 l = new QLabel(i18n("Points to:"), d->m_frame );
00943 grid->addWidget(l, curRow, 0);
00944
00945 l = new QLabel(item->linkDest(), d->m_frame );
00946 grid->addWidget(l, curRow++, 2);
00947 }
00948
00949 if (!d->bMultiple)
00950 {
00951 sep = new KSeparator( KSeparator::HLine, d->m_frame);
00952 grid->addMultiCellWidget(sep, curRow, curRow, 0, 2);
00953 ++curRow;
00954
00955 QDateTime dt;
00956 time_t tim = item->time(KIO::UDS_CREATION_TIME);
00957 if ( tim )
00958 {
00959 l = new QLabel(i18n("Created:"), d->m_frame );
00960 grid->addWidget(l, curRow, 0);
00961
00962 dt.setTime_t( tim );
00963 l = new QLabel(KGlobal::locale()->formatDateTime(dt), d->m_frame );
00964 grid->addWidget(l, curRow++, 2);
00965 }
00966
00967 tim = item->time(KIO::UDS_MODIFICATION_TIME);
00968 if ( tim )
00969 {
00970 l = new QLabel(i18n("Modified:"), d->m_frame );
00971 grid->addWidget(l, curRow, 0);
00972
00973 dt.setTime_t( tim );
00974 l = new QLabel(KGlobal::locale()->formatDateTime(dt), d->m_frame );
00975 grid->addWidget(l, curRow++, 2);
00976 }
00977
00978 tim = item->time(KIO::UDS_ACCESS_TIME);
00979 if ( tim )
00980 {
00981 l = new QLabel(i18n("Accessed:"), d->m_frame );
00982 grid->addWidget(l, curRow, 0);
00983
00984 dt.setTime_t( tim );
00985 l = new QLabel(KGlobal::locale()->formatDateTime(dt), d->m_frame );
00986 grid->addWidget(l, curRow++, 2);
00987 }
00988 }
00989 vbl->addStretch(1);
00990 }
00991
00992
00993
00994
00995
00996
00997 void KFilePropsPlugin::setFileNameReadOnly( bool ro )
00998 {
00999 if ( d->m_lined )
01000 d->m_lined->setReadOnly( ro );
01001 }
01002
01003 void KFilePropsPlugin::slotEditFileType()
01004 {
01005 QString keditfiletype = QString::fromLatin1("keditfiletype");
01006 KRun::runCommand( keditfiletype + " " + KProcess::quote(d->mimeType),
01007 keditfiletype, keditfiletype );
01008 }
01009
01010 void KFilePropsPlugin::slotIconChanged()
01011 {
01012 d->bIconChanged = true;
01013 emit changed();
01014 }
01015
01016 void KFilePropsPlugin::nameFileChanged(const QString &text )
01017 {
01018 properties->enableButtonOK(!text.isEmpty());
01019 emit changed();
01020 }
01021
01022 void KFilePropsPlugin::determineRelativePath( const QString & path )
01023 {
01024
01025 QStringList dirs;
01026 if (KBindingPropsPlugin::supports(properties->items()))
01027 {
01028 m_sRelativePath =KGlobal::dirs()->relativeLocation("mime", path);
01029 if (m_sRelativePath.startsWith("/"))
01030 m_sRelativePath = QString::null;
01031 }
01032 else
01033 {
01034 m_sRelativePath =KGlobal::dirs()->relativeLocation("apps", path);
01035 if (m_sRelativePath.startsWith("/"))
01036 {
01037 m_sRelativePath =KGlobal::dirs()->relativeLocation("xdgdata-apps", path);
01038 if (m_sRelativePath.startsWith("/"))
01039 m_sRelativePath = QString::null;
01040 else
01041 m_sRelativePath = path;
01042 }
01043 }
01044 if ( m_sRelativePath.isEmpty() )
01045 {
01046 if (KBindingPropsPlugin::supports(properties->items()))
01047 kdWarning(250) << "Warning : editing a mimetype file out of the mimetype dirs!" << endl;
01048 }
01049 }
01050
01051 void KFilePropsPlugin::slotFoundMountPoint( const QString&,
01052 unsigned long kBSize,
01053 unsigned long ,
01054 unsigned long kBAvail )
01055 {
01056 d->m_freeSpaceLabel->setText(
01057 i18n("Available space out of total partition size (percent used)", "%1 out of %2 (%3% used)")
01058 .arg(KIO::convertSizeFromKB(kBAvail))
01059 .arg(KIO::convertSizeFromKB(kBSize))
01060 .arg( 100 - (int)(100.0 * kBAvail / kBSize) ));
01061 }
01062
01063
01064
01065 void KFilePropsPlugin::slotFoundMountPoint( const unsigned long& kBSize,
01066 const unsigned long& ,
01067 const unsigned long& kBAvail,
01068 const QString& )
01069 {
01070 d->m_freeSpaceLabel->setText(
01071 i18n("Available space out of total partition size (percent used)", "%1 out of %2 (%3% used)")
01072 .arg(KIO::convertSizeFromKB(kBAvail))
01073 .arg(KIO::convertSizeFromKB(kBSize))
01074 .arg( 100 - (int)(100.0 * kBAvail / kBSize) ));
01075 }
01076
01077 void KFilePropsPlugin::slotDirSizeUpdate()
01078 {
01079 KIO::filesize_t totalSize = d->dirSizeJob->totalSize();
01080 m_sizeLabel->setText( i18n("Calculating... %1 (%2)")
01081 .arg(KIO::convertSize(totalSize))
01082 .arg(KGlobal::locale()->formatNumber(totalSize, 0)) );
01083 }
01084
01085 void KFilePropsPlugin::slotDirSizeFinished( KIO::Job * job )
01086 {
01087 if (job->error())
01088 m_sizeLabel->setText( job->errorString() );
01089 else
01090 {
01091 KIO::filesize_t totalSize = static_cast<KDirSize*>(job)->totalSize();
01092 m_sizeLabel->setText( QString::fromLatin1("%1 (%2)")
01093 .arg(KIO::convertSize(totalSize))
01094 .arg(KGlobal::locale()->formatNumber(totalSize, 0)) );
01095 }
01096 m_sizeStopButton->setEnabled(false);
01097
01098 m_sizeDetermineButton->setText( i18n("Refresh") );
01099 m_sizeDetermineButton->setEnabled(true);
01100 d->dirSizeJob = 0L;
01101 delete d->dirSizeUpdateTimer;
01102 d->dirSizeUpdateTimer = 0L;
01103 }
01104
01105 void KFilePropsPlugin::slotSizeDetermine()
01106 {
01107 m_sizeLabel->setText( i18n("Calculating...") );
01108 kdDebug(250) << " KFilePropsPlugin::slotSizeDetermine() properties->item()=" << properties->item() << endl;
01109 kdDebug(250) << " URL=" << properties->item()->url().url() << endl;
01110 d->dirSizeJob = KDirSize::dirSizeJob( properties->items() );
01111 d->dirSizeUpdateTimer = new QTimer(this);
01112 connect( d->dirSizeUpdateTimer, SIGNAL( timeout() ),
01113 SLOT( slotDirSizeUpdate() ) );
01114 d->dirSizeUpdateTimer->start(500);
01115 connect( d->dirSizeJob, SIGNAL( result( KIO::Job * ) ),
01116 SLOT( slotDirSizeFinished( KIO::Job * ) ) );
01117 m_sizeStopButton->setEnabled(true);
01118 m_sizeDetermineButton->setEnabled(false);
01119 }
01120
01121 void KFilePropsPlugin::slotSizeStop()
01122 {
01123 if ( d->dirSizeJob )
01124 {
01125 m_sizeLabel->setText( i18n("Stopped") );
01126 d->dirSizeJob->kill();
01127 d->dirSizeJob = 0;
01128 }
01129 if ( d->dirSizeUpdateTimer )
01130 d->dirSizeUpdateTimer->stop();
01131
01132 m_sizeStopButton->setEnabled(false);
01133 m_sizeDetermineButton->setEnabled(true);
01134 }
01135
01136 KFilePropsPlugin::~KFilePropsPlugin()
01137 {
01138 delete d;
01139 }
01140
01141 bool KFilePropsPlugin::supports( KFileItemList )
01142 {
01143 return true;
01144 }
01145
01146
01147 void qt_enter_modal( QWidget *widget );
01148 void qt_leave_modal( QWidget *widget );
01149
01150 void KFilePropsPlugin::applyChanges()
01151 {
01152 if ( d->dirSizeJob )
01153 slotSizeStop();
01154
01155 kdDebug(250) << "KFilePropsPlugin::applyChanges" << endl;
01156
01157 if (nameArea->inherits("QLineEdit"))
01158 {
01159 QString n = KIO::encodeFileName(((QLineEdit *) nameArea)->text());
01160
01161 while ( n[n.length()-1].isSpace() )
01162 n.truncate( n.length() - 1 );
01163 if ( n.isEmpty() )
01164 {
01165 KMessageBox::sorry( properties, i18n("The new file name is empty!"));
01166 properties->abortApplying();
01167 return;
01168 }
01169
01170
01171 kdDebug(250) << "oldname = " << oldName << endl;
01172 kdDebug(250) << "newname = " << n << endl;
01173 if ( oldName != n || m_bFromTemplate ) {
01174 KIO::Job * job = 0L;
01175 KURL oldurl = properties->kurl();
01176
01177 properties->rename( n );
01178
01179
01180 if ( !m_sRelativePath.isEmpty() )
01181 determineRelativePath( properties->kurl().path() );
01182
01183 kdDebug(250) << "New URL = " << properties->kurl().url() << endl;
01184 kdDebug(250) << "old = " << oldurl.url() << endl;
01185
01186
01187 if ( !m_bFromTemplate )
01188 job = KIO::move( oldurl, properties->kurl() );
01189 else
01190 job = KIO::copy( oldurl, properties->kurl() );
01191
01192 connect( job, SIGNAL( result( KIO::Job * ) ),
01193 SLOT( slotCopyFinished( KIO::Job * ) ) );
01194 connect( job, SIGNAL( renamed( KIO::Job *, const KURL &, const KURL & ) ),
01195 SLOT( slotFileRenamed( KIO::Job *, const KURL &, const KURL & ) ) );
01196
01197 QWidget dummy(0,0,WType_Dialog|WShowModal);
01198 qt_enter_modal(&dummy);
01199 qApp->enter_loop();
01200 qt_leave_modal(&dummy);
01201 return;
01202 }
01203 }
01204
01205
01206 slotCopyFinished( 0L );
01207 }
01208
01209 void KFilePropsPlugin::slotCopyFinished( KIO::Job * job )
01210 {
01211 kdDebug(250) << "KFilePropsPlugin::slotCopyFinished" << endl;
01212 if (job)
01213 {
01214
01215 qApp->exit_loop();
01216 if ( job->error() )
01217 {
01218 job->showErrorDialog( d->m_frame );
01219
01220 properties->updateUrl( static_cast<KIO::CopyJob*>(job)->srcURLs().first() );
01221 properties->abortApplying();
01222 return;
01223 }
01224 }
01225
01226 assert( properties->item() );
01227 assert( !properties->item()->url().isEmpty() );
01228 bool isDesktopFile = KDesktopPropsPlugin::supports(properties->items());
01229
01230
01231 if (KBindingPropsPlugin::supports(properties->items()) && !m_sRelativePath.isEmpty())
01232 {
01233 KURL newURL;
01234 newURL.setPath( locateLocal("mime", m_sRelativePath) );
01235 properties->updateUrl( newURL );
01236 }
01237 else if (isDesktopFile && !m_sRelativePath.isEmpty())
01238 {
01239 kdDebug(250) << "KFilePropsPlugin::slotCopyFinished " << m_sRelativePath << endl;
01240 KURL newURL;
01241 newURL.setPath( KDesktopFile::locateLocal(m_sRelativePath) );
01242 kdDebug(250) << "KFilePropsPlugin::slotCopyFinished path=" << newURL.path() << endl;
01243 properties->updateUrl( newURL );
01244 }
01245
01246 if ( d->bKDesktopMode && isDesktopFile ) {
01247
01248 if ( oldName != properties->kurl().fileName() || m_bFromTemplate ) {
01249 KDesktopFile config( properties->kurl().path() );
01250 QString nameStr = properties->kurl().fileName();
01251 config.writeEntry( "Name", nameStr );
01252 config.writeEntry( "Name", nameStr, true, false, true );
01253 }
01254 }
01255 }
01256
01257 void KFilePropsPlugin::applyIconChanges()
01258 {
01259
01260
01261 if (!iconArea->isA("QLabel") && properties->kurl().isLocalFile() && d->bIconChanged) {
01262 KIconButton *iconButton = (KIconButton *) iconArea;
01263 QString path;
01264
01265 if (S_ISDIR(properties->item()->mode()))
01266 {
01267 path = properties->kurl().path(1) + QString::fromLatin1(".directory");
01268
01269
01270 }
01271 else
01272 path = properties->kurl().path();
01273
01274
01275 QString str = KMimeType::findByURL( properties->kurl(),
01276 properties->item()->mode(),
01277 true )->KServiceType::icon();
01278
01279 QString sIcon;
01280 if ( str != iconButton->icon() )
01281 sIcon = iconButton->icon();
01282
01283
01284 kdDebug(250) << "**" << path << "**" << endl;
01285 QFile f( path );
01286
01287
01288 if ( !sIcon.isEmpty() || f.exists() )
01289 {
01290 if ( !f.open( IO_ReadWrite ) ) {
01291 KMessageBox::sorry( 0, i18n("<qt>Could not save properties. You do not "
01292 "have sufficient access to write to <b>%1</b>.</qt>").arg(path));
01293 return;
01294 }
01295 f.close();
01296
01297 KDesktopFile cfg(path);
01298 kdDebug(250) << "sIcon = " << (sIcon) << endl;
01299 kdDebug(250) << "str = " << (str) << endl;
01300 cfg.writeEntry( "Icon", sIcon );
01301 cfg.sync();
01302 }
01303 }
01304 }
01305
01306 void KFilePropsPlugin::slotFileRenamed( KIO::Job *, const KURL &, const KURL & newUrl )
01307 {
01308
01309
01310 properties->updateUrl( newUrl );
01311 }
01312
01313 void KFilePropsPlugin::postApplyChanges()
01314 {
01315
01316 applyIconChanges();
01317
01318 KURL::List lst;
01319 KFileItemList items = properties->items();
01320 for ( KFileItemListIterator it( items ); it.current(); ++it )
01321 lst.append((*it)->url());
01322 KDirNotify_stub allDirNotify("*", "KDirNotify*");
01323 allDirNotify.FilesChanged( lst );
01324 }
01325
01326 class KFilePermissionsPropsPlugin::KFilePermissionsPropsPluginPrivate
01327 {
01328 public:
01329 KFilePermissionsPropsPluginPrivate()
01330 {
01331 }
01332 ~KFilePermissionsPropsPluginPrivate()
01333 {
01334 }
01335
01336 QFrame *m_frame;
01337 QCheckBox *cbRecursive;
01338 QLabel *explanationLabel;
01339 QComboBox *ownerPermCombo, *groupPermCombo, *othersPermCombo;
01340 QCheckBox *extraCheckbox;
01341 mode_t partialPermissions;
01342 KFilePermissionsPropsPlugin::PermissionsMode pmode;
01343 bool canChangePermissions;
01344 bool isIrregular;
01345 };
01346
01347 #define UniOwner (S_IRUSR|S_IWUSR|S_IXUSR)
01348 #define UniGroup (S_IRGRP|S_IWGRP|S_IXGRP)
01349 #define UniOthers (S_IROTH|S_IWOTH|S_IXOTH)
01350 #define UniRead (S_IRUSR|S_IRGRP|S_IROTH)
01351 #define UniWrite (S_IWUSR|S_IWGRP|S_IWOTH)
01352 #define UniExec (S_IXUSR|S_IXGRP|S_IXOTH)
01353 #define UniSpecial (S_ISUID|S_ISGID|S_ISVTX)
01354
01355
01356 const mode_t KFilePermissionsPropsPlugin::permissionsMasks[3] = {UniOwner, UniGroup, UniOthers};
01357 const mode_t KFilePermissionsPropsPlugin::standardPermissions[4] = { 0, UniRead, UniRead|UniWrite, (mode_t)-1 };
01358
01359
01360 const char *KFilePermissionsPropsPlugin::permissionsTexts[4][4] = {
01361 { I18N_NOOP("Forbidden"),
01362 I18N_NOOP("Can Read"),
01363 I18N_NOOP("Can Read & Write"),
01364 0 },
01365 { I18N_NOOP("Forbidden"),
01366 I18N_NOOP("Can View Content"),
01367 I18N_NOOP("Can View & Modify Content"),
01368 0 },
01369 { 0, 0, 0, 0},
01370 { I18N_NOOP("Forbidden"),
01371 I18N_NOOP("Can View Content & Read"),
01372 I18N_NOOP("Can View/Read & Modify/Write"),
01373 0 }
01374 };
01375
01376
01377 KFilePermissionsPropsPlugin::KFilePermissionsPropsPlugin( KPropertiesDialog *_props )
01378 : KPropsDlgPlugin( _props )
01379 {
01380 d = new KFilePermissionsPropsPluginPrivate;
01381 d->cbRecursive = 0L;
01382 grpCombo = 0L; grpEdit = 0;
01383 usrEdit = 0L;
01384 QString path = properties->kurl().path(-1);
01385 QString fname = properties->kurl().fileName();
01386 bool isLocal = properties->kurl().isLocalFile();
01387 bool isIntoTrash = isLocal && path.startsWith(KGlobalSettings::trashPath());
01388 bool isTrash = isLocal && ( properties->kurl().path( 1 ) == KGlobalSettings::trashPath() );
01389 bool IamRoot = (geteuid() == 0);
01390
01391 KFileItem * item = properties->item();
01392 bool isLink = item->isLink();
01393 bool isDir = item->isDir();
01394 bool hasDir = item->isDir();
01395 permissions = item->permissions();
01396 d->partialPermissions = permissions;
01397 d->isIrregular = isIrregular(permissions, isDir, isLink);
01398 strOwner = item->user();
01399 strGroup = item->group();
01400
01401 if ( properties->items().count() > 1 )
01402 {
01403
01404 KFileItemList items = properties->items();
01405 KFileItemListIterator it( items );
01406 for ( ++it ; it.current(); ++it )
01407 {
01408 if (!d->isIrregular)
01409 d->isIrregular |= isIrregular((*it)->permissions(),
01410 (*it)->isDir() == isDir,
01411 (*it)->isLink() == isLink);
01412 if ( (*it)->isLink() != isLink )
01413 isLink = false;
01414 if ( (*it)->isDir() != isDir )
01415 isDir = false;
01416 hasDir |= (*it)->isDir();
01417 if ( (*it)->permissions() != permissions )
01418 {
01419 permissions &= (*it)->permissions();
01420 d->partialPermissions |= (*it)->permissions();
01421 }
01422 if ( (*it)->user() != strOwner )
01423 strOwner = QString::null;
01424 if ( (*it)->group() != strGroup )
01425 strGroup = QString::null;
01426 }
01427 }
01428
01429 if (isLink)
01430 d->pmode = PermissionsOnlyLinks;
01431 else if (isDir)
01432 d->pmode = PermissionsOnlyDirs;
01433 else if (hasDir)
01434 d->pmode = PermissionsMixed;
01435 else
01436 d->pmode = PermissionsOnlyFiles;
01437
01438
01439 d->partialPermissions = d->partialPermissions & ~permissions;
01440
01441 bool isMyFile = false;
01442
01443 if (isLocal && !strOwner.isEmpty()) {
01444 struct passwd *myself = getpwuid( geteuid() );
01445 if ( myself != 0L )
01446 {
01447 isMyFile = (strOwner == QString::fromLocal8Bit(myself->pw_name));
01448 } else
01449 kdWarning() << "I don't exist ?! geteuid=" << geteuid() << endl;
01450 } else {
01451
01452
01453
01454 isMyFile = true;
01455 }
01456
01457 d->canChangePermissions = (isMyFile || IamRoot) && (!isLink);
01458
01459
01460
01461
01462 d->m_frame = properties->addPage(i18n("&Permissions"));
01463
01464 QBoxLayout *box = new QVBoxLayout( d->m_frame, 0, KDialog::spacingHint() );
01465
01466 QWidget *l;
01467 QLabel *lbl;
01468 QGroupBox *gb;
01469 QGridLayout *gl;
01470 QPushButton* pbAdvancedPerm = 0;
01471
01472
01473 gb = new QGroupBox ( 0, Qt::Vertical, i18n("Access Permissions"), d->m_frame );
01474 gb->layout()->setSpacing(KDialog::spacingHint());
01475 gb->layout()->setMargin(KDialog::marginHint());
01476 box->addWidget (gb);
01477
01478 gl = new QGridLayout (gb->layout(), 7, 2);
01479 gl->setColStretch(1, 1);
01480
01481 l = d->explanationLabel = new QLabel( "", gb );
01482 if (isLink)
01483 d->explanationLabel->setText(i18n("This file is a link and does not have permissions.",
01484 "All files are links and do not have permissions.",
01485 properties->items().count()));
01486 else if (!d->canChangePermissions)
01487 d->explanationLabel->setText(i18n("Only the owner can change permissions."));
01488 gl->addMultiCellWidget(l, 0, 0, 0, 1);
01489
01490 lbl = new QLabel( i18n("O&wner:"), gb);
01491 gl->addWidget(lbl, 1, 0);
01492 l = d->ownerPermCombo = new QComboBox(gb);
01493 lbl->setBuddy(l);
01494 gl->addWidget(l, 1, 1);
01495 connect(l, SIGNAL( highlighted(int) ), this, SIGNAL( changed() ));
01496 QWhatsThis::add(l, i18n("Specifies the actions that the owner is allowed to do."));
01497
01498 lbl = new QLabel( i18n("Gro&up:"), gb);
01499 gl->addWidget(lbl, 2, 0);
01500 l = d->groupPermCombo = new QComboBox(gb);
01501 lbl->setBuddy(l);
01502 gl->addWidget(l, 2, 1);
01503 connect(l, SIGNAL( highlighted(int) ), this, SIGNAL( changed() ));
01504 QWhatsThis::add(l, i18n("Specifies the actions that the members of the group are allowed to do."));
01505
01506 lbl = new QLabel( i18n("O&thers:"), gb);
01507 gl->addWidget(lbl, 3, 0);
01508 l = d->othersPermCombo = new QComboBox(gb);
01509 lbl->setBuddy(l);
01510 gl->addWidget(l, 3, 1);
01511 connect(l, SIGNAL( highlighted(int) ), this, SIGNAL( changed() ));
01512 QWhatsThis::add(l, i18n("Specifies the actions that all users, who are neither "
01513 "owner nor in the group, are allowed to do."));
01514
01515 if (!isLink) {
01516 l = d->extraCheckbox = new QCheckBox(hasDir ?
01517 i18n("Only own&er can rename and delete folder content") :
01518 i18n("Is &executable"),
01519 gb );
01520 connect( d->extraCheckbox, SIGNAL( clicked() ), this, SIGNAL( changed() ) );
01521 gl->addWidget(l, 4, 1);
01522 QWhatsThis::add(l, hasDir ? i18n("Enable this option to allow only the folder's owner to "
01523 "delete or rename the contained files and folders. Other "
01524 "users can only add new files, which requires the 'Modify "
01525 "Content' permission.")
01526 : i18n("Enable this option to mark the file as executable. This only makes "
01527 "sense for programs and scripts. It is required when you want to "
01528 "execute them."));
01529
01530 QLayoutItem *spacer = new QSpacerItem(0, 20, QSizePolicy::Minimum, QSizePolicy::Expanding);
01531 gl->addMultiCell(spacer, 5, 5, 0, 1);
01532
01533 pbAdvancedPerm = new QPushButton(i18n("A&dvanced Permissions..."), gb);
01534 gl->addMultiCellWidget(pbAdvancedPerm, 6, 6, 0, 1, AlignRight);
01535 connect(pbAdvancedPerm, SIGNAL( clicked() ), this, SLOT( slotShowAdvancedPermissions() ));
01536 }
01537 else
01538 d->extraCheckbox = 0;
01539
01540
01541
01542 gb = new QGroupBox ( i18n("Ownership"), d->m_frame );
01543 box->addWidget (gb);
01544
01545 gl = new QGridLayout (gb, 4, 3, KDialog::marginHint(), KDialog::spacingHint());
01546 gl->addRowSpacing(0, 10);
01547
01548
01549 l = new QLabel( i18n("User:"), gb );
01550 gl->addWidget (l, 1, 0);
01551
01552
01553
01554
01555
01556
01557 int i, maxEntries = 1000;
01558 struct passwd *user;
01559 struct group *ge;
01560
01561
01562
01563
01564 if (IamRoot && isLocal)
01565 {
01566 usrEdit = new KLineEdit( gb );
01567 KCompletion *kcom = usrEdit->completionObject();
01568 kcom->setOrder(KCompletion::Sorted);
01569 setpwent();
01570 for (i=0; ((user = getpwent()) != 0L) && (i < maxEntries); i++)
01571 kcom->addItem(QString::fromLatin1(user->pw_name));
01572 endpwent();
01573 usrEdit->setCompletionMode((i < maxEntries) ? KGlobalSettings::CompletionAuto :
01574 KGlobalSettings::CompletionNone);
01575 usrEdit->setText(strOwner);
01576 gl->addWidget(usrEdit, 1, 1);
01577 connect( usrEdit, SIGNAL( textChanged( const QString & ) ),
01578 this, SIGNAL( changed() ) );
01579 }
01580 else
01581 {
01582 l = new QLabel(strOwner, gb);
01583 gl->addWidget(l, 1, 1);
01584 }
01585
01586
01587
01588 QStringList groupList;
01589 QCString strUser;
01590 user = getpwuid(geteuid());
01591 if (user != 0L)
01592 strUser = user->pw_name;
01593
01594 setgrent();
01595 for (i=0; ((ge = getgrent()) != 0L) && (i < maxEntries); i++)
01596 {
01597 if (IamRoot)
01598 groupList += QString::fromLatin1(ge->gr_name);
01599 else
01600 {
01601
01602 char ** members = ge->gr_mem;
01603 char * member;
01604 while ((member = *members) != 0L) {
01605 if (strUser == member) {
01606 groupList += QString::fromLocal8Bit(ge->gr_name);
01607 break;
01608 }
01609 ++members;
01610 }
01611 }
01612 }
01613 endgrent();
01614
01615
01616 ge = getgrgid (getegid());
01617 if (ge) {
01618 QString name = QString::fromLatin1(ge->gr_name);
01619 if (name.isEmpty())
01620 name.setNum(ge->gr_gid);
01621 if (groupList.find(name) == groupList.end())
01622 groupList += name;
01623 }
01624
01625 bool isMyGroup = groupList.contains(strGroup);
01626
01627
01628
01629
01630 if (!isMyGroup)
01631 groupList += strGroup;
01632
01633 l = new QLabel( i18n("Group:"), gb );
01634 gl->addWidget (l, 2, 0);
01635
01636
01637
01638
01639
01640
01641
01642 if (IamRoot && isLocal)
01643 {
01644 grpEdit = new KLineEdit(gb);
01645 KCompletion *kcom = new KCompletion;
01646 kcom->setItems(groupList);
01647 grpEdit->setCompletionObject(kcom, true);
01648 grpEdit->setAutoDeleteCompletionObject( true );
01649 grpEdit->setCompletionMode(KGlobalSettings::CompletionAuto);
01650 grpEdit->setText(strGroup);
01651 gl->addWidget(grpEdit, 2, 1);
01652 connect( grpEdit, SIGNAL( textChanged( const QString & ) ),
01653 this, SIGNAL( changed() ) );
01654 }
01655 else if ((groupList.count() > 1) && isMyFile && isLocal)
01656 {
01657 grpCombo = new QComboBox(gb, "combogrouplist");
01658 grpCombo->insertStringList(groupList);
01659 grpCombo->setCurrentItem(groupList.findIndex(strGroup));
01660 gl->addWidget(grpCombo, 2, 1);
01661 connect( grpCombo, SIGNAL( activated( int ) ),
01662 this, SIGNAL( changed() ) );
01663 }
01664 else
01665 {
01666 l = new QLabel(strGroup, gb);
01667 gl->addWidget(l, 2, 1);
01668 }
01669
01670 gl->setColStretch(2, 10);
01671
01672
01673 if ( hasDir && !isLink && !isIntoTrash )
01674 {
01675 d->cbRecursive = new QCheckBox( i18n("Apply changes to all subfolders and their contents"), d->m_frame );
01676 connect( d->cbRecursive, SIGNAL( clicked() ), this, SIGNAL( changed() ) );
01677 box->addWidget( d->cbRecursive );
01678 }
01679
01680 updateAccessControls();
01681
01682
01683 if ( isIntoTrash || isTrash )
01684 {
01685
01686 enableAccessControls(false);
01687 if ( pbAdvancedPerm)
01688 pbAdvancedPerm->setEnabled(false);
01689 }
01690
01691 box->addStretch (10);
01692 }
01693
01694 void KFilePermissionsPropsPlugin::slotShowAdvancedPermissions() {
01695
01696 bool isDir = (d->pmode == PermissionsOnlyDirs) || (d->pmode == PermissionsMixed);
01697 KDialogBase dlg(properties, 0, true, i18n("Advanced Permissions"),
01698 KDialogBase::Ok|KDialogBase::Cancel);
01699
01700 QLabel *l, *cl[3];
01701 QGroupBox *gb;
01702 QGridLayout *gl;
01703
01704
01705 gb = new QGroupBox ( i18n("Access Permissions"), &dlg );
01706 dlg.setMainWidget(gb);
01707
01708 gl = new QGridLayout (gb, 6, 6, 15);
01709 gl->addRowSpacing(0, 10);
01710
01711 l = new QLabel(i18n("Class"), gb);
01712 gl->addWidget(l, 1, 0);
01713
01714 if (isDir)
01715 l = new QLabel( i18n("Show\nEntries"), gb );
01716 else
01717 l = new QLabel( i18n("Read"), gb );
01718 gl->addWidget (l, 1, 1);
01719 QString readWhatsThis;
01720 if (isDir)
01721 readWhatsThis = i18n("This flag allows viewing the content of the folder.");
01722 else
01723 readWhatsThis = i18n("The Read flag allows viewing the content of the file.");
01724 QWhatsThis::add(l, readWhatsThis);
01725
01726 if (isDir)
01727 l = new QLabel( i18n("Write\nEntries"), gb );
01728 else
01729 l = new QLabel( i18n("Write"), gb );
01730 gl->addWidget (l, 1, 2);
01731 QString writeWhatsThis;
01732 if (isDir)
01733 writeWhatsThis = i18n("This flag allows adding, renaming and deleting of files. "
01734 "Note that deleting and renaming can be limited using the Sticky flag.");
01735 else
01736 writeWhatsThis = i18n("The Write flag allows modifying the content of the file.");
01737 QWhatsThis::add(l, writeWhatsThis);
01738
01739 QString execWhatsThis;
01740 if (isDir) {
01741 l = new QLabel( i18n("Enter folder", "Enter"), gb );
01742 execWhatsThis = i18n("Enable this flag to allow entering the folder.");
01743 }
01744 else {
01745 l = new QLabel( i18n("Exec"), gb );
01746 execWhatsThis = i18n("Enable this flag to allow executing the file as a program.");
01747 }
01748 QWhatsThis::add(l, execWhatsThis);
01749
01750 QSize size = l->sizeHint();
01751 size.setWidth(size.width() + 15);
01752 l->setFixedSize(size);
01753 gl->addWidget (l, 1, 3);
01754
01755 l = new QLabel( i18n("Special"), gb );
01756 gl->addMultiCellWidget(l, 1, 1, 4, 5);
01757 QString specialWhatsThis;
01758 if (isDir)
01759 specialWhatsThis = i18n("Special flag. Valid for the whole folder, the exact "
01760 "meaning of the flag can be seen in the right hand column.");
01761 else
01762 specialWhatsThis = i18n("Special flag. The exact meaning of the flag can be seen "
01763 "in the right hand column.");
01764 QWhatsThis::add(l, specialWhatsThis);
01765
01766 cl[0] = new QLabel( i18n("User"), gb );
01767 gl->addWidget (cl[0], 2, 0);
01768
01769 cl[1] = new QLabel( i18n("Group"), gb );
01770 gl->addWidget (cl[1], 3, 0);
01771
01772 cl[2] = new QLabel( i18n("Others"), gb );
01773 gl->addWidget (cl[2], 4, 0);
01774
01775 l = new QLabel(i18n("Set UID"), gb);
01776 gl->addWidget(l, 2, 5);
01777 QString setUidWhatsThis;
01778 if (isDir)
01779 setUidWhatsThis = i18n("If this flag is set, the owner of this folder will be "
01780 "the owner of all new files.");
01781 else
01782 setUidWhatsThis = i18n("If this file is an executable and the flag is set, it will "
01783 "be executed with the permissions of the owner.");
01784 QWhatsThis::add(l, setUidWhatsThis);
01785
01786 l = new QLabel(i18n("Set GID"), gb);
01787 gl->addWidget(l, 3, 5);
01788 QString setGidWhatsThis;
01789 if (isDir)
01790 setGidWhatsThis = i18n("If this flag is set, the group of this folder will be "
01791 "set for all new files.");
01792 else
01793 setGidWhatsThis = i18n("If this file is an executable and the flag is set, it will "
01794 "be executed with the permissions of the group.");
01795 QWhatsThis::add(l, setGidWhatsThis);
01796
01797 l = new QLabel(i18n("File permission, sets user or group ID on execution", "Sticky"), gb);
01798 gl->addWidget(l, 4, 5);
01799 QString stickyWhatsThis;
01800 if (isDir)
01801 stickyWhatsThis = i18n("If the Sticky flag is set on a folder, only the owner "
01802 "and root can delete or rename files. Otherwise everybody "
01803 "with write permissions can do this.");
01804 else
01805 stickyWhatsThis = i18n("The Sticky flag on a file is ignored on Linux, but may "
01806 "be used on some systems");
01807 QWhatsThis::add(l, stickyWhatsThis);
01808
01809 mode_t aPermissions, aPartialPermissions;
01810 mode_t dummy1, dummy2;
01811
01812 if (!d->isIrregular) {
01813 switch (d->pmode) {
01814 case PermissionsOnlyFiles:
01815 getPermissionMasks(aPartialPermissions,
01816 dummy1,
01817 aPermissions,
01818 dummy2);
01819 break;
01820 case PermissionsOnlyDirs:
01821 case PermissionsMixed:
01822 getPermissionMasks(dummy1,
01823 aPartialPermissions,
01824 dummy2,
01825 aPermissions);
01826 break;
01827 case PermissionsOnlyLinks:
01828 aPermissions = UniRead | UniWrite | UniExec | UniSpecial;
01829 aPartialPermissions = 0;
01830 break;
01831 }
01832 }
01833 else {
01834 aPermissions = permissions;
01835 aPartialPermissions = d->partialPermissions;
01836 }
01837
01838
01839 QCheckBox *cba[3][4];
01840 for (int row = 0; row < 3 ; ++row) {
01841 for (int col = 0; col < 4; ++col) {
01842 QCheckBox *cb = new QCheckBox(gb);
01843 cba[row][col] = cb;
01844 cb->setChecked(aPermissions & fperm[row][col]);
01845 if ( aPartialPermissions & fperm[row][col] )
01846 {
01847 cb->setTristate();
01848 cb->setNoChange();
01849 }
01850 else if (d->cbRecursive && d->cbRecursive->isChecked())
01851 cb->setTristate();
01852
01853 cb->setEnabled( d->canChangePermissions );
01854 gl->addWidget (cb, row+2, col+1);
01855 switch(col) {
01856 case 0:
01857 QWhatsThis::add(cb, readWhatsThis);
01858 break;
01859 case 1:
01860 QWhatsThis::add(cb, writeWhatsThis);
01861 break;
01862 case 2:
01863 QWhatsThis::add(cb, execWhatsThis);
01864 break;
01865 case 3:
01866 switch(row) {
01867 case 0:
01868 QWhatsThis::add(cb, setUidWhatsThis);
01869 break;
01870 case 1:
01871 QWhatsThis::add(cb, setGidWhatsThis);
01872 break;
01873 case 2:
01874 QWhatsThis::add(cb, stickyWhatsThis);
01875 break;
01876 }
01877 break;
01878 }
01879 }
01880 }
01881 gl->setColStretch(6, 10);
01882
01883 if (dlg.exec() != KDialogBase::Accepted)
01884 return;
01885
01886 mode_t andPermissions = mode_t(~0);
01887 mode_t orPermissions = 0;
01888 for (int row = 0; row < 3; ++row)
01889 for (int col = 0; col < 4; ++col) {
01890 switch (cba[row][col]->state())
01891 {
01892 case QCheckBox::On:
01893 orPermissions |= fperm[row][col];
01894
01895 case QCheckBox::Off:
01896 andPermissions &= ~fperm[row][col];
01897 break;
01898 default:
01899 break;
01900 }
01901 }
01902
01903 d->isIrregular = false;
01904 KFileItemList items = properties->items();
01905 for (KFileItemListIterator it(items); it.current(); ++it) {
01906 if (isIrregular(((*it)->permissions() & andPermissions) | orPermissions,
01907 (*it)->isDir(), (*it)->isLink())) {
01908 d->isIrregular = true;
01909 break;
01910 }
01911 }
01912
01913 permissions = orPermissions;
01914 d->partialPermissions = andPermissions;
01915
01916 emit changed();
01917 updateAccessControls();
01918 }
01919
01920
01921
01922
01923
01924
01925 KFilePermissionsPropsPlugin::~KFilePermissionsPropsPlugin()
01926 {
01927 delete d;
01928 }
01929
01930 bool KFilePermissionsPropsPlugin::supports( KFileItemList )
01931 {
01932 return true;
01933 }
01934
01935
01936 void KFilePermissionsPropsPlugin::setComboContent(QComboBox *combo, PermissionsTarget target,
01937 mode_t permissions, mode_t partial) {
01938 combo->clear();
01939 if (d->pmode == PermissionsOnlyLinks) {
01940 combo->insertItem(i18n("Link"));
01941 combo->setCurrentItem(0);
01942 return;
01943 }
01944
01945 mode_t tMask = permissionsMasks[target];
01946 int textIndex;
01947 for (textIndex = 0; standardPermissions[textIndex] != (mode_t)-1; textIndex++)
01948 if ((standardPermissions[textIndex]&tMask) == (permissions&tMask&(UniRead|UniWrite)))
01949 break;
01950 Q_ASSERT(standardPermissions[textIndex] != (mode_t)-1);
01951
01952 for (int i = 0; permissionsTexts[(int)d->pmode][i]; i++)
01953 combo->insertItem(i18n(permissionsTexts[(int)d->pmode][i]));
01954
01955 if (partial & tMask & ~UniExec) {
01956 combo->insertItem(i18n("Varying (No Change)"));
01957 combo->setCurrentItem(3);
01958 }
01959 else
01960 combo->setCurrentItem(textIndex);
01961 }
01962
01963
01964 bool KFilePermissionsPropsPlugin::isIrregular(mode_t permissions, bool isDir, bool isLink) {
01965 if (isLink)
01966 return false;
01967
01968 mode_t p = permissions;
01969 if (p & (S_ISUID | S_ISGID))
01970 return true;
01971 if (isDir) {
01972 p &= ~S_ISVTX;
01973
01974
01975 mode_t p0 = p & UniOwner;
01976 if ((p0 != 0) && (p0 != (S_IRUSR | S_IXUSR)) && (p0 != UniOwner))
01977 return true;
01978 p0 = p & UniGroup;
01979 if ((p0 != 0) && (p0 != (S_IRGRP | S_IXGRP)) && (p0 != UniGroup))
01980 return true;
01981 p0 = p & UniOthers;
01982 if ((p0 != 0) && (p0 != (S_IROTH | S_IXOTH)) && (p0 != UniOthers))
01983 return true;
01984 return false;
01985 }
01986 if (p & S_ISVTX)
01987 return true;
01988
01989
01990 mode_t p0 = p & UniOwner;
01991 bool usrXPossible = !p0;
01992 if (p0 & S_IXUSR) {
01993 if ((p0 == S_IXUSR) || (p0 == (S_IWUSR | S_IXUSR)))
01994 return true;
01995 usrXPossible = true;
01996 }
01997 else if (p0 == S_IWUSR)
01998 return true;
01999
02000 p0 = p & UniGroup;
02001 bool grpXPossible = !p0;
02002 if (p0 & S_IXGRP) {
02003 if ((p0 == S_IXGRP) || (p0 == (S_IWGRP | S_IXGRP)))
02004 return true;
02005 grpXPossible = true;
02006 }
02007 else if (p0 == S_IWGRP)
02008 return true;
02009 if (p0 == 0)
02010 grpXPossible = true;
02011
02012 p0 = p & UniOthers;
02013 bool othXPossible = !p0;
02014 if (p0 & S_IXOTH) {
02015 if ((p0 == S_IXOTH) || (p0 == (S_IWOTH | S_IXOTH)))
02016 return true;
02017 othXPossible = true;
02018 }
02019 else if (p0 == S_IWOTH)
02020 return true;
02021
02022
02023 return (p & UniExec) && !(usrXPossible && grpXPossible && othXPossible);
02024 }
02025
02026
02027 void KFilePermissionsPropsPlugin::enableAccessControls(bool enable) {
02028 d->ownerPermCombo->setEnabled(enable);
02029 d->groupPermCombo->setEnabled(enable);
02030 d->othersPermCombo->setEnabled(enable);
02031 if (d->extraCheckbox)
02032 d->extraCheckbox->setEnabled(enable);
02033 if ( d->cbRecursive )
02034 d->cbRecursive->setEnabled(enable);
02035 }
02036
02037
02038 void KFilePermissionsPropsPlugin::updateAccessControls() {
02039 setComboContent(d->ownerPermCombo, PermissionsOwner,
02040 permissions, d->partialPermissions);
02041 setComboContent(d->groupPermCombo, PermissionsGroup,
02042 permissions, d->partialPermissions);
02043 setComboContent(d->othersPermCombo, PermissionsOthers,
02044 permissions, d->partialPermissions);
02045
02046 switch(d->pmode) {
02047 case PermissionsOnlyLinks:
02048 enableAccessControls(false);
02049 break;
02050 case PermissionsOnlyFiles:
02051 enableAccessControls(d->canChangePermissions && !d->isIrregular);
02052 if (d->canChangePermissions)
02053 d->explanationLabel->setText(d->isIrregular ?
02054 i18n("This file uses advanced permissions",
02055 "These files use advanced permissions.",
02056 properties->items().count()) : "");
02057 if (d->partialPermissions & UniExec) {
02058 d->extraCheckbox->setTristate();
02059 d->extraCheckbox->setNoChange();
02060 }
02061 else {
02062 d->extraCheckbox->setTristate(false);
02063 d->extraCheckbox->setChecked(permissions & UniExec);
02064 }
02065 break;
02066 case PermissionsOnlyDirs:
02067 enableAccessControls(d->canChangePermissions && !d->isIrregular);
02068 if (d->canChangePermissions)
02069 d->explanationLabel->setText(d->isIrregular ?
02070 i18n("This folder uses advanced permissions.",
02071 "These folders use advanced permissions.",
02072 properties->items().count()) : "");
02073 if (d->partialPermissions & S_ISVTX) {
02074 d->extraCheckbox->setTristate();
02075 d->extraCheckbox->setNoChange();
02076 }
02077 else {
02078 d->extraCheckbox->setTristate(false);
02079 d->extraCheckbox->setChecked(permissions & S_ISVTX);
02080 }
02081 break;
02082 case PermissionsMixed:
02083 enableAccessControls(d->canChangePermissions && !d->isIrregular);
02084 if (d->canChangePermissions)
02085 d->explanationLabel->setText(d->isIrregular ?
02086 i18n("These files use advanced permissions.") : "");
02087 break;
02088 if (d->partialPermissions & S_ISVTX) {
02089 d->extraCheckbox->setTristate();
02090 d->extraCheckbox->setNoChange();
02091 }
02092 else {
02093 d->extraCheckbox->setTristate(false);
02094 d->extraCheckbox->setChecked(permissions & S_ISVTX);
02095 }
02096 break;
02097 }
02098 }
02099
02100
02101 void KFilePermissionsPropsPlugin::getPermissionMasks(mode_t &andFilePermissions,
02102 mode_t &andDirPermissions,
02103 mode_t &orFilePermissions,
02104 mode_t &orDirPermissions) {
02105 andFilePermissions = mode_t(~UniSpecial);
02106 andDirPermissions = mode_t(~(S_ISUID|S_ISGID));
02107 orFilePermissions = 0;
02108 orDirPermissions = 0;
02109 if (d->isIrregular)
02110 return;
02111
02112 mode_t m = standardPermissions[d->ownerPermCombo->currentItem()];
02113 if (m != (mode_t) -1) {
02114 orFilePermissions |= m & UniOwner;
02115 if ((m & UniOwner) &&
02116 ((d->pmode == PermissionsMixed) ||
02117 ((d->pmode == PermissionsOnlyFiles) && (d->extraCheckbox->state() == QButton::NoChange))))
02118 andFilePermissions &= ~(S_IRUSR | S_IWUSR);
02119 else {
02120 andFilePermissions &= ~(S_IRUSR | S_IWUSR | S_IXUSR);
02121 if ((m & S_IRUSR) && (d->extraCheckbox->state() == QButton::On))
02122 orFilePermissions |= S_IXUSR;
02123 }
02124
02125 orDirPermissions |= m & UniOwner;
02126 if (m & S_IRUSR)
02127 orDirPermissions |= S_IXUSR;
02128 andDirPermissions &= ~(S_IRUSR | S_IWUSR | S_IXUSR);
02129 }
02130
02131 m = standardPermissions[d->groupPermCombo->currentItem()];
02132 if (m != (mode_t) -1) {
02133 orFilePermissions |= m & UniGroup;
02134 if ((m & UniGroup) &&
02135 ((d->pmode == PermissionsMixed) ||
02136 ((d->pmode == PermissionsOnlyFiles) && (d->extraCheckbox->state() == QButton::NoChange))))
02137 andFilePermissions &= ~(S_IRGRP | S_IWGRP);
02138 else {
02139 andFilePermissions &= ~(S_IRGRP | S_IWGRP | S_IXGRP);
02140 if ((m & S_IRGRP) && (d->extraCheckbox->state() == QButton::On))
02141 orFilePermissions |= S_IXGRP;
02142 }
02143
02144 orDirPermissions |= m & UniGroup;
02145 if (m & S_IRGRP)
02146 orDirPermissions |= S_IXGRP;
02147 andDirPermissions &= ~(S_IRGRP | S_IWGRP | S_IXGRP);
02148 }
02149
02150 m = standardPermissions[d->othersPermCombo->currentItem()];
02151 if (m != (mode_t) -1) {
02152 orFilePermissions |= m & UniOthers;
02153 if ((m & UniOthers) &&
02154 ((d->pmode == PermissionsMixed) ||
02155 ((d->pmode == PermissionsOnlyFiles) && (d->extraCheckbox->state() == QButton::NoChange))))
02156 andFilePermissions &= ~(S_IROTH | S_IWOTH);
02157 else {
02158 andFilePermissions &= ~(S_IROTH | S_IWOTH | S_IXOTH);
02159 if ((m & S_IROTH) && (d->extraCheckbox->state() == QButton::On))
02160 orFilePermissions |= S_IXOTH;
02161 }
02162
02163 orDirPermissions |= m & UniOthers;
02164 if (m & S_IROTH)
02165 orDirPermissions |= S_IXOTH;
02166 andDirPermissions &= ~(S_IROTH | S_IWOTH | S_IXOTH);
02167 }
02168
02169 if (((d->pmode == PermissionsMixed) || (d->pmode == PermissionsOnlyDirs)) &&
02170 (d->extraCheckbox->state() != QButton::NoChange)) {
02171 andDirPermissions &= ~S_ISVTX;
02172 if (d->extraCheckbox->state() == QButton::On)
02173 orDirPermissions |= S_ISVTX;
02174 }
02175 }
02176
02177 void KFilePermissionsPropsPlugin::applyChanges()
02178 {
02179 mode_t orFilePermissions;
02180 mode_t orDirPermissions;
02181 mode_t andFilePermissions;
02182 mode_t andDirPermissions;
02183
02184 if (!d->canChangePermissions)
02185 return;
02186
02187 if (!d->isIrregular)
02188 getPermissionMasks(andFilePermissions,
02189 andDirPermissions,
02190 orFilePermissions,
02191 orDirPermissions);
02192 else {
02193 orFilePermissions = permissions;
02194 andFilePermissions = d->partialPermissions;
02195 orDirPermissions = permissions;
02196 andDirPermissions = d->partialPermissions;
02197 }
02198
02199 QString owner, group;
02200 if (usrEdit)
02201 owner = usrEdit->text();
02202 if (grpEdit)
02203 group = grpEdit->text();
02204 else if (grpCombo)
02205 group = grpCombo->currentText();
02206
02207 if (owner == strOwner)
02208 owner = QString::null;
02209
02210 if (group == strGroup)
02211 group = QString::null;
02212
02213 bool recursive = d->cbRecursive && d->cbRecursive->isChecked();
02214 bool permissionChange = false;
02215
02216 KFileItemList files, dirs;
02217 KFileItemList items = properties->items();
02218 for (KFileItemListIterator it(items); it.current(); ++it) {
02219 if ((*it)->isDir()) {
02220 dirs.append(*it);
02221 if ((*it)->permissions() != (((*it)->permissions() & andDirPermissions) | orDirPermissions))
02222 permissionChange = true;
02223 }
02224 else if ((*it)->isFile()) {
02225 files.append(*it);
02226 if ((*it)->permissions() != (((*it)->permissions() & andFilePermissions) | orFilePermissions))
02227 permissionChange = true;
02228 }
02229 }
02230
02231 if ( !owner.isEmpty() || !group.isEmpty() || recursive || permissionChange)
02232 {
02233 KIO::Job * job;
02234 if (files.count() > 0) {
02235 job = KIO::chmod( files, orFilePermissions, ~andFilePermissions,
02236 owner, group, false );
02237 connect( job, SIGNAL( result( KIO::Job * ) ),
02238 SLOT( slotChmodResult( KIO::Job * ) ) );
02239
02240 QWidget dummy(0,0,WType_Dialog|WShowModal);
02241 qt_enter_modal(&dummy);
02242 qApp->enter_loop();
02243 qt_leave_modal(&dummy);
02244 }
02245 if (dirs.count() > 0) {
02246 job = KIO::chmod( dirs, orDirPermissions, ~andDirPermissions,
02247 owner, group, recursive );
02248 connect( job, SIGNAL( result( KIO::Job * ) ),
02249 SLOT( slotChmodResult( KIO::Job * ) ) );
02250
02251 QWidget dummy(0,0,WType_Dialog|WShowModal);
02252 qt_enter_modal(&dummy);
02253 qApp->enter_loop();
02254 qt_leave_modal(&dummy);
02255 }
02256 }
02257 }
02258
02259 void KFilePermissionsPropsPlugin::slotChmodResult( KIO::Job * job )
02260 {
02261 kdDebug(250) << "KFilePermissionsPropsPlugin::slotChmodResult" << endl;
02262 if (job->error())
02263 job->showErrorDialog( d->m_frame );
02264
02265 qApp->exit_loop();
02266 }
02267
02268
02269
02270
02271 class KURLPropsPlugin::KURLPropsPluginPrivate
02272 {
02273 public:
02274 KURLPropsPluginPrivate()
02275 {
02276 }
02277 ~KURLPropsPluginPrivate()
02278 {
02279 }
02280
02281 QFrame *m_frame;
02282 };
02283
02284 KURLPropsPlugin::KURLPropsPlugin( KPropertiesDialog *_props )
02285 : KPropsDlgPlugin( _props )
02286 {
02287 d = new KURLPropsPluginPrivate;
02288 d->m_frame = properties->addPage(i18n("U&RL"));
02289 QVBoxLayout *layout = new QVBoxLayout(d->m_frame, 0, KDialog::spacingHint());
02290
02291 QLabel *l;
02292 l = new QLabel( d->m_frame, "Label_1" );
02293 l->setText( i18n("URL:") );
02294 layout->addWidget(l);
02295
02296 URLEdit = new KURLRequester( d->m_frame, "URL Requester" );
02297 layout->addWidget(URLEdit);
02298
02299 QString path = properties->kurl().path();
02300
02301 QFile f( path );
02302 if ( !f.open( IO_ReadOnly ) )
02303 return;
02304 f.close();
02305
02306 KSimpleConfig config( path );
02307 config.setDesktopGroup();
02308 URLStr = config.readPathEntry( "URL" );
02309
02310 if ( !URLStr.isNull() )
02311 URLEdit->setURL( URLStr );
02312
02313 connect( URLEdit, SIGNAL( textChanged( const QString & ) ),
02314 this, SIGNAL( changed() ) );
02315
02316 layout->addStretch (1);
02317 }
02318
02319 KURLPropsPlugin::~KURLPropsPlugin()
02320 {
02321 delete d;
02322 }
02323
02324
02325
02326
02327
02328
02329 bool KURLPropsPlugin::supports( KFileItemList _items )
02330 {
02331 if ( _items.count() != 1 )
02332 return false;
02333 KFileItem * item = _items.first();
02334
02335 if ( !KPropsDlgPlugin::isDesktopFile( item ) )
02336 return false;
02337
02338
02339 KDesktopFile config( item->url().path(), true );
02340 return config.hasLinkType();
02341 }
02342
02343 void KURLPropsPlugin::applyChanges()
02344 {
02345 QString path = properties->kurl().path();
02346
02347 QFile f( path );
02348 if ( !f.open( IO_ReadWrite ) ) {
02349 KMessageBox::sorry( 0, i18n("<qt>Could not save properties. You do not have "
02350 "sufficient access to write to <b>%1</b>.</qt>").arg(path));
02351 return;
02352 }
02353 f.close();
02354
02355 KSimpleConfig config( path );
02356 config.setDesktopGroup();
02357 config.writeEntry( "Type", QString::fromLatin1("Link"));
02358 config.writePathEntry( "URL", URLEdit->url() );
02359
02360
02361 if ( config.hasKey("Name") )
02362 {
02363
02364 QString nameStr = properties->kurl().fileName();
02365 if ( nameStr.right(8) == QString::fromLatin1(".desktop") )
02366 nameStr.truncate( nameStr.length() - 8 );
02367 if ( nameStr.right(7) == QString::fromLatin1(".kdelnk") )
02368 nameStr.truncate( nameStr.length() - 7 );
02369 config.writeEntry( "Name", nameStr );
02370 config.writeEntry( "Name", nameStr, true, false, true );
02371
02372 }
02373 }
02374
02375
02376
02377
02378
02379
02380
02381
02382 class KBindingPropsPlugin::KBindingPropsPluginPrivate
02383 {
02384 public:
02385 KBindingPropsPluginPrivate()
02386 {
02387 }
02388 ~KBindingPropsPluginPrivate()
02389 {
02390 }
02391
02392 QFrame *m_frame;
02393 };
02394
02395 KBindingPropsPlugin::KBindingPropsPlugin( KPropertiesDialog *_props ) : KPropsDlgPlugin( _props )
02396 {
02397 d = new KBindingPropsPluginPrivate;
02398 d->m_frame = properties->addPage(i18n("A&ssociation"));
02399 patternEdit = new KLineEdit( d->m_frame, "LineEdit_1" );
02400 commentEdit = new KLineEdit( d->m_frame, "LineEdit_2" );
02401 mimeEdit = new KLineEdit( d->m_frame, "LineEdit_3" );
02402
02403 QBoxLayout *mainlayout = new QVBoxLayout(d->m_frame, 0, KDialog::spacingHint());
02404 QLabel* tmpQLabel;
02405
02406 tmpQLabel = new QLabel( d->m_frame, "Label_1" );
02407 tmpQLabel->setText( i18n("Pattern ( example: *.html;*.htm )") );
02408 tmpQLabel->setMinimumSize(tmpQLabel->sizeHint());
02409 mainlayout->addWidget(tmpQLabel, 1);
02410
02411
02412
02413 patternEdit->setMaxLength( 512 );
02414 patternEdit->setMinimumSize( patternEdit->sizeHint() );
02415 patternEdit->setFixedHeight( fontHeight );
02416 mainlayout->addWidget(patternEdit, 1);
02417
02418 tmpQLabel = new QLabel( d->m_frame, "Label_2" );
02419 tmpQLabel->setText( i18n("Mime Type") );
02420 tmpQLabel->setMinimumSize(tmpQLabel->sizeHint());
02421 mainlayout->addWidget(tmpQLabel, 1);
02422
02423
02424 mimeEdit->setMaxLength( 256 );
02425 mimeEdit->setMinimumSize( mimeEdit->sizeHint() );
02426 mimeEdit->setFixedHeight( fontHeight );
02427 mainlayout->addWidget(mimeEdit, 1);
02428
02429 tmpQLabel = new QLabel( d->m_frame, "Label_3" );
02430 tmpQLabel->setText( i18n("Comment") );
02431 tmpQLabel->setMinimumSize(tmpQLabel->sizeHint());
02432 mainlayout->addWidget(tmpQLabel, 1);
02433
02434
02435 commentEdit->setMaxLength( 256 );
02436 commentEdit->setMinimumSize( commentEdit->sizeHint() );
02437 commentEdit->setFixedHeight( fontHeight );
02438 mainlayout->addWidget(commentEdit, 1);
02439
02440 cbAutoEmbed = new QCheckBox( i18n("Left click previews"), d->m_frame, "cbAutoEmbed" );
02441 mainlayout->addWidget(cbAutoEmbed, 1);
02442
02443 mainlayout->addStretch (10);
02444 mainlayout->activate();
02445
02446 QFile f( _props->kurl().path() );
02447 if ( !f.open( IO_ReadOnly ) )
02448 return;
02449 f.close();
02450
02451 KSimpleConfig config( _props->kurl().path() );
02452 config.setDesktopGroup();
02453 QString patternStr = config.readEntry( "Patterns" );
02454 QString iconStr = config.readEntry( "Icon" );
02455 QString commentStr = config.readEntry( "Comment" );
02456 m_sMimeStr = config.readEntry( "MimeType" );
02457
02458 if ( !patternStr.isEmpty() )
02459 patternEdit->setText( patternStr );
02460 if ( !commentStr.isEmpty() )
02461 commentEdit->setText( commentStr );
02462 if ( !m_sMimeStr.isEmpty() )
02463 mimeEdit->setText( m_sMimeStr );
02464 cbAutoEmbed->setTristate();
02465 if ( config.hasKey( "X-KDE-AutoEmbed" ) )
02466 cbAutoEmbed->setChecked( config.readBoolEntry( "X-KDE-AutoEmbed" ) );
02467 else
02468 cbAutoEmbed->setNoChange();
02469
02470 connect( patternEdit, SIGNAL( textChanged( const QString & ) ),
02471 this, SIGNAL( changed() ) );
02472 connect( commentEdit, SIGNAL( textChanged( const QString & ) ),
02473 this, SIGNAL( changed() ) );
02474 connect( mimeEdit, SIGNAL( textChanged( const QString & ) ),
02475 this, SIGNAL( changed() ) );
02476 connect( cbAutoEmbed, SIGNAL( toggled( bool ) ),
02477 this, SIGNAL( changed() ) );
02478 }
02479
02480 KBindingPropsPlugin::~KBindingPropsPlugin()
02481 {
02482 delete d;
02483 }
02484
02485
02486
02487
02488
02489
02490 bool KBindingPropsPlugin::supports( KFileItemList _items )
02491 {
02492 if ( _items.count() != 1 )
02493 return false;
02494 KFileItem * item = _items.first();
02495
02496 if ( !KPropsDlgPlugin::isDesktopFile( item ) )
02497 return false;
02498
02499
02500 KDesktopFile config( item->url().path(), true );
02501 return config.hasMimeTypeType();
02502 }
02503
02504 void KBindingPropsPlugin::applyChanges()
02505 {
02506 QString path = properties->kurl().path();
02507 QFile f( path );
02508
02509 if ( !f.open( IO_ReadWrite ) )
02510 {
02511 KMessageBox::sorry( 0, i18n("<qt>Could not save properties. You do not have "
02512 "sufficient access to write to <b>%1</b>.</qt>").arg(path));
02513 return;
02514 }
02515 f.close();
02516
02517 KSimpleConfig config( path );
02518 config.setDesktopGroup();
02519 config.writeEntry( "Type", QString::fromLatin1("MimeType") );
02520
02521 config.writeEntry( "Patterns", patternEdit->text() );
02522 config.writeEntry( "Comment", commentEdit->text() );
02523 config.writeEntry( "Comment",
02524 commentEdit->text(), true, false, true );
02525 config.writeEntry( "MimeType", mimeEdit->text() );
02526 if ( cbAutoEmbed->state() == QButton::NoChange )
02527 config.deleteEntry( "X-KDE-AutoEmbed", false );
02528 else
02529 config.writeEntry( "X-KDE-AutoEmbed", cbAutoEmbed->isChecked() );
02530 config.sync();
02531 }
02532
02533
02534
02535
02536
02537
02538
02539 class KDevicePropsPlugin::KDevicePropsPluginPrivate
02540 {
02541 public:
02542 KDevicePropsPluginPrivate()
02543 {
02544 }
02545 ~KDevicePropsPluginPrivate()
02546 {
02547 }
02548
02549 QFrame *m_frame;
02550 QStringList mountpointlist;
02551 };
02552
02553 KDevicePropsPlugin::KDevicePropsPlugin( KPropertiesDialog *_props ) : KPropsDlgPlugin( _props )
02554 {
02555 d = new KDevicePropsPluginPrivate;
02556 d->m_frame = properties->addPage(i18n("De&vice"));
02557
02558 QStringList devices;
02559 KMountPoint::List mountPoints = KMountPoint::possibleMountPoints();
02560
02561 for(KMountPoint::List::ConstIterator it = mountPoints.begin();
02562 it != mountPoints.end(); ++it)
02563 {
02564 KMountPoint *mp = *it;
02565 QString mountPoint = mp->mountPoint();
02566 QString device = mp->mountedFrom();
02567 kdDebug()<<"mountPoint :"<<mountPoint<<" device :"<<device<<" mp->mountType() :"<<mp->mountType()<<endl;
02568
02569 if (device.startsWith("/") && (mountPoint != "-") &&
02570 (mountPoint != "none") && !mountPoint.isEmpty())
02571 {
02572 devices.append( device + QString::fromLatin1(" (")
02573 + mountPoint + QString::fromLatin1(")") );
02574 m_devicelist.append(device);
02575 d->mountpointlist.append(mountPoint);
02576 }
02577 }
02578
02579 QGridLayout *layout = new QGridLayout( d->m_frame, 0, 3, 0,
02580 KDialog::spacingHint());
02581 layout->setColStretch(1, 1);
02582
02583 QLabel* label;
02584 label = new QLabel( d->m_frame );
02585 label->setText( devices.count() == 0 ?
02586 i18n("Device (/dev/fd0):") :
02587 i18n("Device:") );
02588 layout->addWidget(label, 0, 0);
02589
02590 device = new QComboBox( true, d->m_frame, "ComboBox_device" );
02591 device->insertStringList( devices );
02592 layout->addWidget(device, 0, 1);
02593 connect( device, SIGNAL( activated( int ) ),
02594 this, SLOT( slotActivated( int ) ) );
02595
02596 readonly = new QCheckBox( d->m_frame, "CheckBox_readonly" );
02597 readonly->setText( i18n("Read only") );
02598 layout->addWidget(readonly, 1, 1);
02599
02600 label = new QLabel( d->m_frame );
02601 label->setText( devices.count()==0 ?
02602 i18n("Mount point (/mnt/floppy):") :
02603 i18n("Mount point:"));
02604 layout->addWidget(label, 2, 0);
02605
02606 mountpoint = new QLabel( d->m_frame, "LineEdit_mountpoint" );
02607
02608 layout->addWidget(mountpoint, 2, 1);
02609
02610 KSeparator* sep = new KSeparator( KSeparator::HLine, d->m_frame);
02611 layout->addMultiCellWidget(sep, 4, 4, 0, 2);
02612
02613 unmounted = new KIconButton( d->m_frame );
02614 unmounted->setFixedSize(70, 70);
02615 unmounted->setIconType(KIcon::Desktop, KIcon::Device);
02616 layout->addWidget(unmounted, 5, 0);
02617
02618 label = new QLabel( i18n("Unmounted Icon"), d->m_frame );
02619 layout->addWidget(label, 5, 1);
02620
02621 layout->setRowStretch(6, 1);
02622
02623 QString path( _props->kurl().path() );
02624
02625 QFile f( path );
02626 if ( !f.open( IO_ReadOnly ) )
02627 return;
02628 f.close();
02629
02630 KSimpleConfig config( path );
02631 config.setDesktopGroup();
02632 QString deviceStr = config.readEntry( "Dev" );
02633 QString mountPointStr = config.readEntry( "MountPoint" );
02634 bool ro = config.readBoolEntry( "ReadOnly", false );
02635 QString unmountedStr = config.readEntry( "UnmountIcon" );
02636
02637 device->setEditText( deviceStr );
02638 if ( !deviceStr.isEmpty() ) {
02639
02640 int index = m_devicelist.findIndex(deviceStr);
02641 if (index != -1)
02642 {
02643
02644 slotActivated( index );
02645 }
02646 }
02647
02648 if ( !mountPointStr.isEmpty() )
02649 mountpoint->setText( mountPointStr );
02650
02651 readonly->setChecked( ro );
02652
02653 if ( unmountedStr.isEmpty() )
02654 unmountedStr = KMimeType::mimeType(QString::fromLatin1("application/octet-stream"))->KServiceType::icon();
02655
02656 unmounted->setIcon( unmountedStr );
02657
02658 connect( device, SIGNAL( activated( int ) ),
02659 this, SIGNAL( changed() ) );
02660 connect( device, SIGNAL( textChanged( const QString & ) ),
02661 this, SIGNAL( changed() ) );
02662 connect( readonly, SIGNAL( toggled( bool ) ),
02663 this, SIGNAL( changed() ) );
02664 connect( unmounted, SIGNAL( iconChanged( QString ) ),
02665 this, SIGNAL( changed() ) );
02666
02667 connect( device, SIGNAL( textChanged( const QString & ) ),
02668 this, SLOT( slotDeviceChanged() ) );
02669 }
02670
02671 KDevicePropsPlugin::~KDevicePropsPlugin()
02672 {
02673 delete d;
02674 }
02675
02676
02677
02678
02679
02680
02681 void KDevicePropsPlugin::slotActivated( int index )
02682 {
02683
02684 device->setEditText( m_devicelist[index] );
02685 mountpoint->setText( d->mountpointlist[index] );
02686 }
02687
02688 void KDevicePropsPlugin::slotDeviceChanged()
02689 {
02690
02691 int index = m_devicelist.findIndex( device->currentText() );
02692 if ( index != -1 )
02693 mountpoint->setText( d->mountpointlist[index] );
02694 else
02695 mountpoint->setText( QString::null );
02696 }
02697
02698 bool KDevicePropsPlugin::supports( KFileItemList _items )
02699 {
02700 if ( _items.count() != 1 )
02701 return false;
02702 KFileItem * item = _items.first();
02703
02704 if ( !KPropsDlgPlugin::isDesktopFile( item ) )
02705 return false;
02706
02707 KDesktopFile config( item->url().path(), true );
02708 return config.hasDeviceType();
02709 }
02710
02711 void KDevicePropsPlugin::applyChanges()
02712 {
02713 QString path = properties->kurl().path();
02714 QFile f( path );
02715 if ( !f.open( IO_ReadWrite ) )
02716 {
02717 KMessageBox::sorry( 0, i18n("<qt>Could not save properties. You do not have sufficient "
02718 "access to write to <b>%1</b>.</qt>").arg(path));
02719 return;
02720 }
02721 f.close();
02722
02723 KSimpleConfig config( path );
02724 config.setDesktopGroup();
02725 config.writeEntry( "Type", QString::fromLatin1("FSDevice") );
02726
02727 config.writeEntry( "Dev", device->currentText() );
02728 config.writeEntry( "MountPoint", mountpoint->text() );
02729
02730 config.writeEntry( "UnmountIcon", unmounted->icon() );
02731 kdDebug(250) << "unmounted->icon() = " << unmounted->icon() << endl;
02732
02733 config.writeEntry( "ReadOnly", readonly->isChecked() );
02734
02735 config.sync();
02736 }
02737
02738
02739
02740
02741
02742
02743
02744
02745
02746 KDesktopPropsPlugin::KDesktopPropsPlugin( KPropertiesDialog *_props )
02747 : KPropsDlgPlugin( _props )
02748 {
02749 QFrame *frame = properties->addPage(i18n("&Application"));
02750 QVBoxLayout *mainlayout = new QVBoxLayout( frame, 0, KDialog::spacingHint() );
02751
02752 w = new KPropertiesDesktopBase(frame);
02753 mainlayout->addWidget(w);
02754
02755 bool bKDesktopMode = (QCString(qApp->name()) == "kdesktop");
02756
02757 if (bKDesktopMode)
02758 {
02759
02760 w->nameEdit->hide();
02761 w->nameLabel->hide();
02762 }
02763
02764 connect( w->nameEdit, SIGNAL( textChanged( const QString & ) ), this, SIGNAL( changed() ) );
02765 connect( w->genNameEdit, SIGNAL( textChanged( const QString & ) ), this, SIGNAL( changed() ) );
02766 connect( w->commentEdit, SIGNAL( textChanged( const QString & ) ), this, SIGNAL( changed() ) );
02767 connect( w->commandEdit, SIGNAL( textChanged( const QString & ) ), this, SIGNAL( changed() ) );
02768
02769 connect( w->browseButton, SIGNAL( clicked() ), this, SLOT( slotBrowseExec() ) );
02770 connect( w->addFiletypeButton, SIGNAL( clicked() ), this, SLOT( slotAddFiletype() ) );
02771 connect( w->delFiletypeButton, SIGNAL( clicked() ), this, SLOT( slotDelFiletype() ) );
02772 connect( w->advancedButton, SIGNAL( clicked() ), this, SLOT( slotAdvanced() ) );
02773
02774
02775 QString path = _props->kurl().path();
02776 QFile f( path );
02777 if ( !f.open( IO_ReadOnly ) )
02778 return;
02779 f.close();
02780
02781 KSimpleConfig config( path );
02782 config.setDollarExpansion( false );
02783 config.setDesktopGroup();
02784 QString nameStr = config.readEntry( "Name" );
02785 QString genNameStr = config.readEntry( "GenericName" );
02786 QString commentStr = config.readEntry( "Comment" );
02787 QString commandStr = config.readPathEntry( "Exec" );
02788 m_origCommandStr = commandStr;
02789 m_terminalBool = config.readBoolEntry( "Terminal" );
02790 m_terminalOptionStr = config.readEntry( "TerminalOptions" );
02791 m_suidBool = config.readBoolEntry( "X-KDE-SubstituteUID" );
02792 m_suidUserStr = config.readEntry( "X-KDE-Username" );
02793 if( config.hasKey( "StartupNotify" ))
02794 m_startupBool = config.readBoolEntry( "StartupNotify", true );
02795 else
02796 m_startupBool = config.readBoolEntry( "X-KDE-StartupNotify", true );
02797 m_dcopServiceType = config.readEntry("X-DCOP-ServiceType").lower();
02798
02799 QStringList mimeTypes = config.readListEntry( "MimeType", ';' );
02800
02801 if ( nameStr.isEmpty() || bKDesktopMode ) {
02802
02803
02804
02805 setDirty();
02806 }
02807 if ( !bKDesktopMode )
02808 w->nameEdit->setText(nameStr);
02809
02810 w->genNameEdit->setText( genNameStr );
02811 w->commentEdit->setText( commentStr );
02812 w->commandEdit->setText( commandStr );
02813 w->filetypeList->setAllColumnsShowFocus(true);
02814
02815 KMimeType::Ptr defaultMimetype = KMimeType::defaultMimeTypePtr();
02816 for(QStringList::ConstIterator it = mimeTypes.begin();
02817 it != mimeTypes.end(); )
02818 {
02819 KMimeType::Ptr p = KMimeType::mimeType(*it);
02820 ++it;
02821 QString preference;
02822 if (it != mimeTypes.end())
02823 {
02824 bool numeric;
02825 (*it).toInt(&numeric);
02826 if (numeric)
02827 {
02828 preference = *it;
02829 ++it;
02830 }
02831 }
02832 if (p && (p != defaultMimetype))
02833 {
02834 new QListViewItem(w->filetypeList, p->name(), p->comment(), preference);
02835 }
02836 }
02837
02838 }
02839
02840 KDesktopPropsPlugin::~KDesktopPropsPlugin()
02841 {
02842 }
02843
02844 void KDesktopPropsPlugin::slotSelectMimetype()
02845 {
02846 QListView *w = (QListView*)sender();
02847 QListViewItem *item = w->firstChild();
02848 while(item)
02849 {
02850 if (item->isSelected())
02851 w->setSelected(item, false);
02852 item = item->nextSibling();
02853 }
02854 }
02855
02856 void KDesktopPropsPlugin::slotAddFiletype()
02857 {
02858 KDialogBase dlg(w, "KPropertiesMimetypes", true,
02859 i18n("Add File Type for %1").arg(properties->kurl().fileName()),
02860 KDialogBase::Ok|KDialogBase::Cancel, KDialogBase::Ok);
02861
02862 dlg.setButtonOKText(i18n("&Add"), i18n("Add the selected file types to\nthe list of supported file types."),
02863 i18n("Add the selected file types to\nthe list of supported file types."));
02864
02865 KPropertiesMimetypeBase *mw = new KPropertiesMimetypeBase(&dlg);
02866
02867 dlg.setMainWidget(mw);
02868
02869 {
02870 mw->listView->setRootIsDecorated(true);
02871 mw->listView->setSelectionMode(QListView::Multi);
02872 mw->listView->setAllColumnsShowFocus(true);
02873 mw->listView->setFullWidth(true);
02874 mw->listView->setMinimumSize(500,400);
02875
02876 connect(mw->listView, SIGNAL(selectionChanged()),
02877 this, SLOT(slotSelectMimetype()));
02878 connect(mw->listView, SIGNAL(doubleClicked( QListViewItem *, const QPoint &, int )),
02879 &dlg, SLOT( slotOk()));
02880
02881 QMap<QString,QListViewItem*> majorMap;
02882 QListViewItem *majorGroup;
02883 KMimeType::List mimetypes = KMimeType::allMimeTypes();
02884 QValueListIterator<KMimeType::Ptr> it(mimetypes.begin());
02885 for (; it != mimetypes.end(); ++it) {
02886 QString mimetype = (*it)->name();
02887 if (mimetype == "application/octet-stream")
02888 continue;
02889 int index = mimetype.find("/");
02890 QString maj = mimetype.left(index);
02891 QString min = mimetype.mid(index+1);
02892
02893 QMapIterator<QString,QListViewItem*> mit = majorMap.find( maj );
02894 if ( mit == majorMap.end() ) {
02895 majorGroup = new QListViewItem( mw->listView, maj );
02896 majorGroup->setExpandable(true);
02897 mw->listView->setOpen(majorGroup, true);
02898 majorMap.insert( maj, majorGroup );
02899 }
02900 else
02901 {
02902 majorGroup = mit.data();
02903 }
02904
02905 QListViewItem *item = new QListViewItem(majorGroup, min, (*it)->comment());
02906 item->setPixmap(0, (*it)->pixmap(KIcon::Small, IconSize(KIcon::Small)));
02907 }
02908 QMapIterator<QString,QListViewItem*> mit = majorMap.find( "all" );
02909 if ( mit != majorMap.end())
02910 {
02911 mw->listView->setCurrentItem(mit.data());
02912 mw->listView->ensureItemVisible(mit.data());
02913 }
02914 }
02915
02916 if (dlg.exec() == KDialogBase::Accepted)
02917 {
02918 KMimeType::Ptr defaultMimetype = KMimeType::defaultMimeTypePtr();
02919 QListViewItem *majorItem = mw->listView->firstChild();
02920 while(majorItem)
02921 {
02922 QString major = majorItem->text(0);
02923
02924 QListViewItem *minorItem = majorItem->firstChild();
02925 while(minorItem)
02926 {
02927 if (minorItem->isSelected())
02928 {
02929 QString mimetype = major + "/" + minorItem->text(0);
02930 KMimeType::Ptr p = KMimeType::mimeType(mimetype);
02931 if (p && (p != defaultMimetype))
02932 {
02933 mimetype = p->name();
02934 bool found = false;
02935 QListViewItem *item = w->filetypeList->firstChild();
02936 while (item)
02937 {
02938 if (mimetype == item->text(0))
02939 {
02940 found = true;
02941 break;
02942 }
02943 item = item->nextSibling();
02944 }
02945 if (!found)
02946 new QListViewItem(w->filetypeList, p->name(), p->comment());
02947 }
02948 }
02949 minorItem = minorItem->nextSibling();
02950 }
02951
02952 majorItem = majorItem->nextSibling();
02953 }
02954
02955 }
02956 }
02957
02958 void KDesktopPropsPlugin::slotDelFiletype()
02959 {
02960 delete w->filetypeList->currentItem();
02961 }
02962
02963 void KDesktopPropsPlugin::checkCommandChanged()
02964 {
02965 if (KRun::binaryName(w->commandEdit->text(), true) !=
02966 KRun::binaryName(m_origCommandStr, true))
02967 {
02968 QString m_origCommandStr = w->commandEdit->text();
02969 m_dcopServiceType= QString::null;
02970 }
02971 }
02972
02973 void KDesktopPropsPlugin::applyChanges()
02974 {
02975 kdDebug(250) << "KDesktopPropsPlugin::applyChanges" << endl;
02976 QString path = properties->kurl().path();
02977
02978 QFile f( path );
02979
02980 if ( !f.open( IO_ReadWrite ) ) {
02981 KMessageBox::sorry( 0, i18n("<qt>Could not save properties. You do not have "
02982 "sufficient access to write to <b>%1</b>.</qt>").arg(path));
02983 return;
02984 }
02985 f.close();
02986
02987
02988
02989 checkCommandChanged();
02990
02991 KSimpleConfig config( path );
02992 config.setDesktopGroup();
02993 config.writeEntry( "Type", QString::fromLatin1("Application"));
02994 config.writeEntry( "Comment", w->commentEdit->text() );
02995 config.writeEntry( "Comment", w->commentEdit->text(), true, false, true );
02996 config.writeEntry( "GenericName", w->genNameEdit->text() );
02997 config.writeEntry( "GenericName", w->genNameEdit->text(), true, false, true );
02998
02999 config.writePathEntry( "Exec", w->commandEdit->text() );
03000
03001
03002 QStringList mimeTypes;
03003 for( QListViewItem *item = w->filetypeList->firstChild();
03004 item; item = item->nextSibling() )
03005 {
03006 QString preference = item->text(2);
03007 mimeTypes.append(item->text(0));
03008 if (!preference.isEmpty())
03009 mimeTypes.append(preference);
03010 }
03011
03012 config.writeEntry( "MimeType", mimeTypes, ';' );
03013
03014 if ( !w->nameEdit->isHidden() ) {
03015 QString nameStr = w->nameEdit->text();
03016 config.writeEntry( "Name", nameStr );
03017 config.writeEntry( "Name", nameStr, true, false, true );
03018 }
03019
03020 config.writeEntry("Terminal", m_terminalBool);
03021 config.writeEntry("TerminalOptions", m_terminalOptionStr);
03022 config.writeEntry("X-KDE-SubstituteUID", m_suidBool);
03023 config.writeEntry("X-KDE-Username", m_suidUserStr);
03024 config.writeEntry("StartupNotify", m_startupBool);
03025 config.writeEntry("X-DCOP-ServiceType", m_dcopServiceType);
03026 config.sync();
03027
03028
03029 QString sycocaPath = KGlobal::dirs()->relativeLocation("apps", path);
03030 bool updateNeeded = !sycocaPath.startsWith("/");
03031 if (!updateNeeded)
03032 {
03033 sycocaPath = KGlobal::dirs()->relativeLocation("xdgdata-apps", path);
03034 updateNeeded = !sycocaPath.startsWith("/");
03035 }
03036 if (updateNeeded)
03037 KService::rebuildKSycoca(w);
03038 }
03039
03040
03041 void KDesktopPropsPlugin::slotBrowseExec()
03042 {
03043 KURL f = KFileDialog::getOpenURL( QString::null,
03044 QString::null, w );
03045 if ( f.isEmpty() )
03046 return;
03047
03048 if ( !f.isLocalFile()) {
03049 KMessageBox::sorry(w, i18n("Only executables on local file systems are supported."));
03050 return;
03051 }
03052
03053 QString path = f.path();
03054 KRun::shellQuote( path );
03055 w->commandEdit->setText( path );
03056 }
03057
03058 void KDesktopPropsPlugin::slotAdvanced()
03059 {
03060 KDialogBase dlg(w, "KPropertiesDesktopAdv", true,
03061 i18n("Advanced Options for %1").arg(properties->kurl().fileName()),
03062 KDialogBase::Ok|KDialogBase::Cancel, KDialogBase::Ok);
03063 KPropertiesDesktopAdvBase *w = new KPropertiesDesktopAdvBase(&dlg);
03064
03065 dlg.setMainWidget(w);
03066
03067
03068
03069 checkCommandChanged();
03070
03071
03072
03073 KConfigGroup confGroup( KGlobal::config(), QString::fromLatin1("General") );
03074 QString preferredTerminal = confGroup.readEntry("TerminalApplication",
03075 QString::fromLatin1("konsole"));
03076
03077 bool terminalCloseBool = false;
03078
03079 if (preferredTerminal == "konsole")
03080 {
03081 terminalCloseBool = (m_terminalOptionStr.contains( "--noclose" ) > 0);
03082 w->terminalCloseCheck->setChecked(terminalCloseBool);
03083 m_terminalOptionStr.replace( "--noclose", "");
03084 }
03085 else
03086 {
03087 w->terminalCloseCheck->hide();
03088 }
03089
03090 w->terminalCheck->setChecked(m_terminalBool);
03091 w->terminalEdit->setText(m_terminalOptionStr);
03092 w->terminalCloseCheck->setEnabled(m_terminalBool);
03093 w->terminalEdit->setEnabled(m_terminalBool);
03094 w->terminalEditLabel->setEnabled(m_terminalBool);
03095
03096 w->suidCheck->setChecked(m_suidBool);
03097 w->suidEdit->setText(m_suidUserStr);
03098 w->suidEdit->setEnabled(m_suidBool);
03099 w->suidEditLabel->setEnabled(m_suidBool);
03100
03101 w->startupInfoCheck->setChecked(m_startupBool);
03102
03103 if (m_dcopServiceType == "unique")
03104 w->dcopCombo->setCurrentItem(2);
03105 else if (m_dcopServiceType == "multi")
03106 w->dcopCombo->setCurrentItem(1);
03107 else if (m_dcopServiceType == "wait")
03108 w->dcopCombo->setCurrentItem(3);
03109 else
03110 w->dcopCombo->setCurrentItem(0);
03111
03112
03113 KCompletion *kcom = new KCompletion;
03114 kcom->setOrder(KCompletion::Sorted);
03115 struct passwd *pw;
03116 int i, maxEntries = 1000;
03117 setpwent();
03118 for (i=0; ((pw = getpwent()) != 0L) && (i < maxEntries); i++)
03119 kcom->addItem(QString::fromLatin1(pw->pw_name));
03120 endpwent();
03121 if (i < maxEntries)
03122 {
03123 w->suidEdit->setCompletionObject(kcom, true);
03124 w->suidEdit->setAutoDeleteCompletionObject( true );
03125 w->suidEdit->setCompletionMode(KGlobalSettings::CompletionAuto);
03126 }
03127 else
03128 {
03129 delete kcom;
03130 }
03131
03132 connect( w->terminalEdit, SIGNAL( textChanged( const QString & ) ),
03133 this, SIGNAL( changed() ) );
03134 connect( w->terminalCloseCheck, SIGNAL( toggled( bool ) ),
03135 this, SIGNAL( changed() ) );
03136 connect( w->terminalCheck, SIGNAL( toggled( bool ) ),
03137 this, SIGNAL( changed() ) );
03138 connect( w->suidCheck, SIGNAL( toggled( bool ) ),
03139 this, SIGNAL( changed() ) );
03140 connect( w->suidEdit, SIGNAL( textChanged( const QString & ) ),
03141 this, SIGNAL( changed() ) );
03142 connect( w->startupInfoCheck, SIGNAL( toggled( bool ) ),
03143 this, SIGNAL( changed() ) );
03144 connect( w->dcopCombo, SIGNAL( highlighted( int ) ),
03145 this, SIGNAL( changed() ) );
03146
03147 if ( dlg.exec() == QDialog::Accepted )
03148 {
03149 m_terminalOptionStr = w->terminalEdit->text().stripWhiteSpace();
03150 m_terminalBool = w->terminalCheck->isChecked();
03151 m_suidBool = w->suidCheck->isChecked();
03152 m_suidUserStr = w->suidEdit->text().stripWhiteSpace();
03153 m_startupBool = w->startupInfoCheck->isChecked();
03154
03155 if (w->terminalCloseCheck->isChecked())
03156 {
03157 m_terminalOptionStr.append(" --noclose");
03158 }
03159
03160 switch(w->dcopCombo->currentItem())
03161 {
03162 case 1: m_dcopServiceType = "multi"; break;
03163 case 2: m_dcopServiceType = "unique"; break;
03164 case 3: m_dcopServiceType = "wait"; break;
03165 default: m_dcopServiceType = "none"; break;
03166 }
03167 }
03168 }
03169
03170 bool KDesktopPropsPlugin::supports( KFileItemList _items )
03171 {
03172 if ( _items.count() != 1 )
03173 return false;
03174 KFileItem * item = _items.first();
03175
03176 if ( !KPropsDlgPlugin::isDesktopFile( item ) )
03177 return false;
03178
03179 KDesktopFile config( item->url().path(), true );
03180 return config.hasApplicationType() && kapp->authorize("run_desktop_files") && kapp->authorize("shell_access");
03181 }
03182
03183 void KPropertiesDialog::virtual_hook( int id, void* data )
03184 { KDialogBase::virtual_hook( id, data ); }
03185
03186 void KPropsDlgPlugin::virtual_hook( int, void* )
03187 { }
03188
03189
03190
03191
03192
03198 class KExecPropsPlugin::KExecPropsPluginPrivate
03199 {
03200 public:
03201 KExecPropsPluginPrivate()
03202 {
03203 }
03204 ~KExecPropsPluginPrivate()
03205 {
03206 }
03207
03208 QFrame *m_frame;
03209 QCheckBox *nocloseonexitCheck;
03210 };
03211
03212 KExecPropsPlugin::KExecPropsPlugin( KPropertiesDialog *_props )
03213 : KPropsDlgPlugin( _props )
03214 {
03215 d = new KExecPropsPluginPrivate;
03216 d->m_frame = properties->addPage(i18n("E&xecute"));
03217 QVBoxLayout * mainlayout = new QVBoxLayout( d->m_frame, 0,
03218 KDialog::spacingHint());
03219
03220
03221
03222 QLabel* l;
03223 l = new QLabel( i18n( "Comman&d:" ), d->m_frame );
03224 mainlayout->addWidget(l);
03225
03226 QHBoxLayout * hlayout;
03227 hlayout = new QHBoxLayout(KDialog::spacingHint());
03228 mainlayout->addLayout(hlayout);
03229
03230 execEdit = new KLineEdit( d->m_frame );
03231 QWhatsThis::add(execEdit,i18n(
03232 "Following the command, you can have several place holders which will be replaced "
03233 "with the actual values when the actual program is run:\n"
03234 "%f - a single file name\n"
03235 "%F - a list of files; use for applications that can open several local files at once\n"
03236 "%u - a single URL\n"
03237 "%U - a list of URLs\n"
03238 "%d - the folder of the file to open\n"
03239 "%D - a list of folders\n"
03240 "%i - the icon\n"
03241 "%m - the mini-icon\n"
03242 "%c - the caption"));
03243 hlayout->addWidget(execEdit, 1);
03244
03245 l->setBuddy( execEdit );
03246
03247 execBrowse = new QPushButton( d->m_frame );
03248 execBrowse->setText( i18n("&Browse...") );
03249 hlayout->addWidget(execBrowse);
03250
03251
03252 QGroupBox* tmpQGroupBox;
03253 tmpQGroupBox = new QGroupBox( i18n("Panel Embedding"), d->m_frame );
03254 tmpQGroupBox->setColumnLayout( 0, Qt::Horizontal );
03255
03256 mainlayout->addWidget(tmpQGroupBox);
03257
03258 QGridLayout *grid = new QGridLayout(tmpQGroupBox->layout(), 2, 2);
03259 grid->setSpacing( KDialog::spacingHint() );
03260 grid->setColStretch(1, 1);
03261
03262 l = new QLabel( i18n( "&Execute on click:" ), tmpQGroupBox );
03263 grid->addWidget(l, 0, 0);
03264
03265 swallowExecEdit = new KLineEdit( tmpQGroupBox );
03266 grid->addWidget(swallowExecEdit, 0, 1);
03267
03268 l->setBuddy( swallowExecEdit );
03269
03270 l = new QLabel( i18n( "&Window title:" ), tmpQGroupBox );
03271 grid->addWidget(l, 1, 0);
03272
03273 swallowTitleEdit = new KLineEdit( tmpQGroupBox );
03274 grid->addWidget(swallowTitleEdit, 1, 1);
03275
03276 l->setBuddy( swallowTitleEdit );
03277
03278
03279
03280 tmpQGroupBox = new QGroupBox( d->m_frame );
03281 tmpQGroupBox->setColumnLayout( 0, Qt::Horizontal );
03282
03283 mainlayout->addWidget(tmpQGroupBox);
03284
03285 grid = new QGridLayout(tmpQGroupBox->layout(), 3, 2);
03286 grid->setSpacing( KDialog::spacingHint() );
03287 grid->setColStretch(1, 1);
03288
03289 terminalCheck = new QCheckBox( tmpQGroupBox );
03290 terminalCheck->setText( i18n("&Run in terminal") );
03291 grid->addMultiCellWidget(terminalCheck, 0, 0, 0, 1);
03292
03293
03294
03295 KConfigGroup confGroup( KGlobal::config(), QString::fromLatin1("General") );
03296 QString preferredTerminal = confGroup.readEntry("TerminalApplication",
03297 QString::fromLatin1("konsole"));
03298
03299 int posOptions = 1;
03300 d->nocloseonexitCheck = 0L;
03301 if (preferredTerminal == "konsole")
03302 {
03303 posOptions = 2;
03304 d->nocloseonexitCheck = new QCheckBox( tmpQGroupBox );
03305 d->nocloseonexitCheck->setText( i18n("Do not &close when command exits") );
03306 grid->addMultiCellWidget(d->nocloseonexitCheck, 1, 1, 0, 1);
03307 }
03308
03309 terminalLabel = new QLabel( i18n( "&Terminal options:" ), tmpQGroupBox );
03310 grid->addWidget(terminalLabel, posOptions, 0);
03311
03312 terminalEdit = new KLineEdit( tmpQGroupBox );
03313 grid->addWidget(terminalEdit, posOptions, 1);
03314
03315 terminalLabel->setBuddy( terminalEdit );
03316
03317
03318
03319 tmpQGroupBox = new QGroupBox( d->m_frame );
03320 tmpQGroupBox->setColumnLayout( 0, Qt::Horizontal );
03321
03322 mainlayout->addWidget(tmpQGroupBox);
03323
03324 grid = new QGridLayout(tmpQGroupBox->layout(), 2, 2);
03325 grid->setSpacing(KDialog::spacingHint());
03326 grid->setColStretch(1, 1);
03327
03328 suidCheck = new QCheckBox(tmpQGroupBox);
03329 suidCheck->setText(i18n("Ru&n as a different user"));
03330 grid->addMultiCellWidget(suidCheck, 0, 0, 0, 1);
03331
03332 suidLabel = new QLabel(i18n( "&Username:" ), tmpQGroupBox);
03333 grid->addWidget(suidLabel, 1, 0);
03334
03335 suidEdit = new KLineEdit(tmpQGroupBox);
03336 grid->addWidget(suidEdit, 1, 1);
03337
03338 suidLabel->setBuddy( suidEdit );
03339
03340 mainlayout->addStretch(1);
03341
03342
03343 QString path = _props->kurl().path();
03344 QFile f( path );
03345 if ( !f.open( IO_ReadOnly ) )
03346 return;
03347 f.close();
03348
03349 KSimpleConfig config( path );
03350 config.setDollarExpansion( false );
03351 config.setDesktopGroup();
03352 execStr = config.readPathEntry( "Exec" );
03353 swallowExecStr = config.readPathEntry( "SwallowExec" );
03354 swallowTitleStr = config.readEntry( "SwallowTitle" );
03355 termBool = config.readBoolEntry( "Terminal" );
03356 termOptionsStr = config.readEntry( "TerminalOptions" );
03357 suidBool = config.readBoolEntry( "X-KDE-SubstituteUID" );
03358 suidUserStr = config.readEntry( "X-KDE-Username" );
03359
03360 if ( !swallowExecStr.isNull() )
03361 swallowExecEdit->setText( swallowExecStr );
03362 if ( !swallowTitleStr.isNull() )
03363 swallowTitleEdit->setText( swallowTitleStr );
03364
03365 if ( !execStr.isNull() )
03366 execEdit->setText( execStr );
03367
03368 if ( d->nocloseonexitCheck )
03369 {
03370 d->nocloseonexitCheck->setChecked( (termOptionsStr.contains( "--noclose" ) > 0) );
03371 termOptionsStr.replace( "--noclose", "");
03372 }
03373 if ( !termOptionsStr.isNull() )
03374 terminalEdit->setText( termOptionsStr );
03375
03376 terminalCheck->setChecked( termBool );
03377 enableCheckedEdit();
03378
03379 suidCheck->setChecked( suidBool );
03380 suidEdit->setText( suidUserStr );
03381 enableSuidEdit();
03382
03383
03384 KCompletion *kcom = new KCompletion;
03385 kcom->setOrder(KCompletion::Sorted);
03386 struct passwd *pw;
03387 int i, maxEntries = 1000;
03388 setpwent();
03389 for (i=0; ((pw = getpwent()) != 0L) && (i < maxEntries); i++)
03390 kcom->addItem(QString::fromLatin1(pw->pw_name));
03391 endpwent();
03392 if (i < maxEntries)
03393 {
03394 suidEdit->setCompletionObject(kcom, true);
03395 suidEdit->setAutoDeleteCompletionObject( true );
03396 suidEdit->setCompletionMode(KGlobalSettings::CompletionAuto);
03397 }
03398 else
03399 {
03400 delete kcom;
03401 }
03402
03403 connect( swallowExecEdit, SIGNAL( textChanged( const QString & ) ),
03404 this, SIGNAL( changed() ) );
03405 connect( swallowTitleEdit, SIGNAL( textChanged( const QString & ) ),
03406 this, SIGNAL( changed() ) );
03407 connect( execEdit, SIGNAL( textChanged( const QString & ) ),
03408 this, SIGNAL( changed() ) );
03409 connect( terminalEdit, SIGNAL( textChanged( const QString & ) ),
03410 this, SIGNAL( changed() ) );
03411 if (d->nocloseonexitCheck)
03412 connect( d->nocloseonexitCheck, SIGNAL( toggled( bool ) ),
03413 this, SIGNAL( changed() ) );
03414 connect( terminalCheck, SIGNAL( toggled( bool ) ),
03415 this, SIGNAL( changed() ) );
03416 connect( suidCheck, SIGNAL( toggled( bool ) ),
03417 this, SIGNAL( changed() ) );
03418 connect( suidEdit, SIGNAL( textChanged( const QString & ) ),
03419 this, SIGNAL( changed() ) );
03420
03421 connect( execBrowse, SIGNAL( clicked() ), this, SLOT( slotBrowseExec() ) );
03422 connect( terminalCheck, SIGNAL( clicked() ), this, SLOT( enableCheckedEdit() ) );
03423 connect( suidCheck, SIGNAL( clicked() ), this, SLOT( enableSuidEdit() ) );
03424
03425 }
03426
03427 KExecPropsPlugin::~KExecPropsPlugin()
03428 {
03429 delete d;
03430 }
03431
03432 void KExecPropsPlugin::enableCheckedEdit()
03433 {
03434 bool checked = terminalCheck->isChecked();
03435 terminalLabel->setEnabled( checked );
03436 if (d->nocloseonexitCheck)
03437 d->nocloseonexitCheck->setEnabled( checked );
03438 terminalEdit->setEnabled( checked );
03439 }
03440
03441 void KExecPropsPlugin::enableSuidEdit()
03442 {
03443 bool checked = suidCheck->isChecked();
03444 suidLabel->setEnabled( checked );
03445 suidEdit->setEnabled( checked );
03446 }
03447
03448 bool KExecPropsPlugin::supports( KFileItemList _items )
03449 {
03450 if ( _items.count() != 1 )
03451 return false;
03452 KFileItem * item = _items.first();
03453
03454 if ( !KPropsDlgPlugin::isDesktopFile( item ) )
03455 return false;
03456
03457 KDesktopFile config( item->url().path(), true );
03458 return config.hasApplicationType() && kapp->authorize("run_desktop_files") && kapp->authorize("shell_access");
03459 }
03460
03461 void KExecPropsPlugin::applyChanges()
03462 {
03463 kdDebug(250) << "KExecPropsPlugin::applyChanges" << endl;
03464 QString path = properties->kurl().path();
03465
03466 QFile f( path );
03467
03468 if ( !f.open( IO_ReadWrite ) ) {
03469 KMessageBox::sorry( 0, i18n("<qt>Could not save properties. You do not have "
03470 "sufficient access to write to <b>%1</b>.</qt>").arg(path));
03471 return;
03472 }
03473 f.close();
03474
03475 KSimpleConfig config( path );
03476 config.setDesktopGroup();
03477 config.writeEntry( "Type", QString::fromLatin1("Application"));
03478 config.writePathEntry( "Exec", execEdit->text() );
03479 config.writePathEntry( "SwallowExec", swallowExecEdit->text() );
03480 config.writeEntry( "SwallowTitle", swallowTitleEdit->text() );
03481 config.writeEntry( "Terminal", terminalCheck->isChecked() );
03482 QString temp = terminalEdit->text();
03483 if (d->nocloseonexitCheck )
03484 if ( d->nocloseonexitCheck->isChecked() )
03485 temp += QString::fromLatin1("--noclose ");
03486 temp = temp.stripWhiteSpace();
03487 config.writeEntry( "TerminalOptions", temp );
03488 config.writeEntry( "X-KDE-SubstituteUID", suidCheck->isChecked() );
03489 config.writeEntry( "X-KDE-Username", suidEdit->text() );
03490 }
03491
03492
03493 void KExecPropsPlugin::slotBrowseExec()
03494 {
03495 KURL f = KFileDialog::getOpenURL( QString::null,
03496 QString::null, d->m_frame );
03497 if ( f.isEmpty() )
03498 return;
03499
03500 if ( !f.isLocalFile()) {
03501 KMessageBox::sorry(d->m_frame, i18n("Only executables on local file systems are supported."));
03502 return;
03503 }
03504
03505 QString path = f.path();
03506 KRun::shellQuote( path );
03507 execEdit->setText( path );
03508 }
03509
03510 class KApplicationPropsPlugin::KApplicationPropsPluginPrivate
03511 {
03512 public:
03513 KApplicationPropsPluginPrivate()
03514 {
03515 m_kdesktopMode = QCString(qApp->name()) == "kdesktop";
03516 }
03517 ~KApplicationPropsPluginPrivate()
03518 {
03519 }
03520
03521 QFrame *m_frame;
03522 bool m_kdesktopMode;
03523 };
03524
03525 KApplicationPropsPlugin::KApplicationPropsPlugin( KPropertiesDialog *_props )
03526 : KPropsDlgPlugin( _props )
03527 {
03528 d = new KApplicationPropsPluginPrivate;
03529 d->m_frame = properties->addPage(i18n("&Application"));
03530 QVBoxLayout *toplayout = new QVBoxLayout( d->m_frame, 0, KDialog::spacingHint());
03531
03532 QIconSet iconSet;
03533 QPixmap pixMap;
03534
03535 addExtensionButton = new QPushButton( QString::null, d->m_frame );
03536 iconSet = SmallIconSet( "back" );
03537 addExtensionButton->setIconSet( iconSet );
03538 pixMap = iconSet.pixmap( QIconSet::Small, QIconSet::Normal );
03539 addExtensionButton->setFixedSize( pixMap.width()+8, pixMap.height()+8 );
03540 connect( addExtensionButton, SIGNAL( clicked() ),
03541 SLOT( slotAddExtension() ) );
03542
03543 delExtensionButton = new QPushButton( QString::null, d->m_frame );
03544 iconSet = SmallIconSet( "forward" );
03545 delExtensionButton->setIconSet( iconSet );
03546 delExtensionButton->setFixedSize( pixMap.width()+8, pixMap.height()+8 );
03547 connect( delExtensionButton, SIGNAL( clicked() ),
03548 SLOT( slotDelExtension() ) );
03549
03550 QLabel *l;
03551
03552 QGridLayout *grid = new QGridLayout(2, 2);
03553 grid->setColStretch(1, 1);
03554 toplayout->addLayout(grid);
03555
03556 if ( d->m_kdesktopMode )
03557 {
03558
03559 nameEdit = 0L;
03560 }
03561 else
03562 {
03563 l = new QLabel(i18n("Name:"), d->m_frame, "Label_4" );
03564 grid->addWidget(l, 0, 0);
03565
03566 nameEdit = new KLineEdit( d->m_frame, "LineEdit_3" );
03567 grid->addWidget(nameEdit, 0, 1);
03568 }
03569
03570 l = new QLabel(i18n("Description:"), d->m_frame, "Label_5" );
03571 grid->addWidget(l, 1, 0);
03572
03573 genNameEdit = new KLineEdit( d->m_frame, "LineEdit_4" );
03574 grid->addWidget(genNameEdit, 1, 1);
03575
03576 l = new QLabel(i18n("Comment:"), d->m_frame, "Label_3" );
03577 grid->addWidget(l, 2, 0);
03578
03579 commentEdit = new KLineEdit( d->m_frame, "LineEdit_2" );
03580 grid->addWidget(commentEdit, 2, 1);
03581
03582 l = new QLabel(i18n("File types:"), d->m_frame);
03583 toplayout->addWidget(l, 0, AlignLeft);
03584
03585 grid = new QGridLayout(4, 3);
03586 grid->setColStretch(0, 1);
03587 grid->setColStretch(2, 1);
03588 grid->setRowStretch( 0, 1 );
03589 grid->setRowStretch( 3, 1 );
03590 toplayout->addLayout(grid, 2);
03591
03592 extensionsList = new QListBox( d->m_frame );
03593 extensionsList->setSelectionMode( QListBox::Extended );
03594 grid->addMultiCellWidget(extensionsList, 0, 3, 0, 0);
03595
03596 grid->addWidget(addExtensionButton, 1, 1);
03597 grid->addWidget(delExtensionButton, 2, 1);
03598
03599 availableExtensionsList = new QListBox( d->m_frame );
03600 availableExtensionsList->setSelectionMode( QListBox::Extended );
03601 grid->addMultiCellWidget(availableExtensionsList, 0, 3, 2, 2);
03602
03603 QString path = properties->kurl().path() ;
03604 QFile f( path );
03605 if ( !f.open( IO_ReadOnly ) )
03606 return;
03607 f.close();
03608
03609 KSimpleConfig config( path );
03610 config.setDesktopGroup();
03611 QString commentStr = config.readEntry( "Comment" );
03612 QString genNameStr = config.readEntry( "GenericName" );
03613
03614 QStringList selectedTypes = config.readListEntry( "ServiceTypes" );
03615
03616 selectedTypes += config.readListEntry( "MimeType", ';' );
03617
03618 QString nameStr = config.readEntry( QString::fromLatin1("Name") );
03619 if ( nameStr.isEmpty() || d->m_kdesktopMode ) {
03620
03621
03622
03623 setDirty();
03624 }
03625
03626 commentEdit->setText( commentStr );
03627 genNameEdit->setText( genNameStr );
03628 if ( nameEdit )
03629 nameEdit->setText( nameStr );
03630
03631 selectedTypes.sort();
03632 QStringList::Iterator sit = selectedTypes.begin();
03633 for( ; sit != selectedTypes.end(); ++sit ) {
03634 if ( !((*sit).isEmpty()) )
03635 extensionsList->insertItem( *sit );
03636 }
03637
03638 KMimeType::List mimeTypes = KMimeType::allMimeTypes();
03639 QValueListIterator<KMimeType::Ptr> it2 = mimeTypes.begin();
03640 for ( ; it2 != mimeTypes.end(); ++it2 )
03641 addMimeType ( (*it2)->name() );
03642
03643 updateButton();
03644
03645 connect( extensionsList, SIGNAL( highlighted( int ) ),
03646 this, SLOT( updateButton() ) );
03647 connect( availableExtensionsList, SIGNAL( highlighted( int ) ),
03648 this, SLOT( updateButton() ) );
03649
03650 connect( addExtensionButton, SIGNAL( clicked() ),
03651 this, SIGNAL( changed() ) );
03652 connect( delExtensionButton, SIGNAL( clicked() ),
03653 this, SIGNAL( changed() ) );
03654 if ( nameEdit )
03655 connect( nameEdit, SIGNAL( textChanged( const QString & ) ),
03656 this, SIGNAL( changed() ) );
03657 connect( commentEdit, SIGNAL( textChanged( const QString & ) ),
03658 this, SIGNAL( changed() ) );
03659 connect( genNameEdit, SIGNAL( textChanged( const QString & ) ),
03660 this, SIGNAL( changed() ) );
03661 connect( availableExtensionsList, SIGNAL( selected( int ) ),
03662 this, SIGNAL( changed() ) );
03663 connect( extensionsList, SIGNAL( selected( int ) ),
03664 this, SIGNAL( changed() ) );
03665 }
03666
03667 KApplicationPropsPlugin::~KApplicationPropsPlugin()
03668 {
03669 delete d;
03670 }
03671
03672
03673
03674
03675
03676
03677 void KApplicationPropsPlugin::updateButton()
03678 {
03679 addExtensionButton->setEnabled(availableExtensionsList->currentItem()>-1);
03680 delExtensionButton->setEnabled(extensionsList->currentItem()>-1);
03681 }
03682
03683 void KApplicationPropsPlugin::addMimeType( const QString & name )
03684 {
03685
03686
03687 bool insert = true;
03688
03689 for ( uint i = 0; i < extensionsList->count(); i++ )
03690 if ( extensionsList->text( i ) == name )
03691 insert = false;
03692
03693 if ( insert )
03694 {
03695 availableExtensionsList->insertItem( name );
03696 availableExtensionsList->sort();
03697 }
03698 }
03699
03700 bool KApplicationPropsPlugin::supports( KFileItemList _items )
03701 {
03702
03703 return KExecPropsPlugin::supports( _items );
03704 }
03705
03706 void KApplicationPropsPlugin::applyChanges()
03707 {
03708 QString path = properties->kurl().path();
03709
03710 QFile f( path );
03711
03712 if ( !f.open( IO_ReadWrite ) ) {
03713 KMessageBox::sorry( 0, i18n("<qt>Could not save properties. You do not "
03714 "have sufficient access to write to <b>%1</b>.</qt>").arg(path));
03715 return;
03716 }
03717 f.close();
03718
03719 KSimpleConfig config( path );
03720 config.setDesktopGroup();
03721 config.writeEntry( "Type", QString::fromLatin1("Application"));
03722 config.writeEntry( "Comment", commentEdit->text() );
03723 config.writeEntry( "Comment", commentEdit->text(), true, false, true );
03724 config.writeEntry( "GenericName", genNameEdit->text() );
03725 config.writeEntry( "GenericName", genNameEdit->text(), true, false, true );
03726
03727 QStringList selectedTypes;
03728 for ( uint i = 0; i < extensionsList->count(); i++ )
03729 selectedTypes.append( extensionsList->text( i ) );
03730
03731 config.writeEntry( "MimeType", selectedTypes, ';' );
03732 config.writeEntry( "ServiceTypes", "" );
03733
03734
03735 QString nameStr = nameEdit ? nameEdit->text() : QString::null;
03736 if ( nameStr.isEmpty() )
03737 {
03738 nameStr = properties->kurl().fileName();
03739 if ( nameStr.right(8) == QString::fromLatin1(".desktop") )
03740 nameStr.truncate( nameStr.length() - 8 );
03741 if ( nameStr.right(7) == QString::fromLatin1(".kdelnk") )
03742 nameStr.truncate( nameStr.length() - 7 );
03743 }
03744 config.writeEntry( "Name", nameStr );
03745 config.writeEntry( "Name", nameStr, true, false, true );
03746
03747 config.sync();
03748 }
03749
03750 void KApplicationPropsPlugin::slotAddExtension()
03751 {
03752 QListBoxItem *item = availableExtensionsList->firstItem();
03753 QListBoxItem *nextItem;
03754
03755 while ( item )
03756 {
03757 nextItem = item->next();
03758
03759 if ( item->isSelected() )
03760 {
03761 extensionsList->insertItem( item->text() );
03762 availableExtensionsList->removeItem( availableExtensionsList->index( item ) );
03763 }
03764
03765 item = nextItem;
03766 }
03767
03768 extensionsList->sort();
03769 updateButton();
03770 }
03771
03772 void KApplicationPropsPlugin::slotDelExtension()
03773 {
03774 QListBoxItem *item = extensionsList->firstItem();
03775 QListBoxItem *nextItem;
03776
03777 while ( item )
03778 {
03779 nextItem = item->next();
03780
03781 if ( item->isSelected() )
03782 {
03783 availableExtensionsList->insertItem( item->text() );
03784 extensionsList->removeItem( extensionsList->index( item ) );
03785 }
03786
03787 item = nextItem;
03788 }
03789
03790 availableExtensionsList->sort();
03791 updateButton();
03792 }
03793
03794
03795
03796 #include "kpropertiesdialog.moc"