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