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