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