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