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