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 bool allDisable = true;
01887 QCheckBox *cba[3][4];
01888 for (int row = 0; row < 3 ; ++row) {
01889 for (int col = 0; col < 4; ++col) {
01890 QCheckBox *cb = new QCheckBox(gb);
01891 cba[row][col] = cb;
01892 cb->setChecked(aPermissions & fperm[row][col]);
01893 if ( aPartialPermissions & fperm[row][col] )
01894 {
01895 cb->setTristate();
01896 cb->setNoChange();
01897 }
01898 else if (d->cbRecursive && d->cbRecursive->isChecked())
01899 cb->setTristate();
01900
01901 if( d->canChangePermissions)
01902 allDisable = false;
01903 cb->setEnabled( d->canChangePermissions );
01904 gl->addWidget (cb, row+2, col+1);
01905 switch(col) {
01906 case 0:
01907 QWhatsThis::add(cb, readWhatsThis);
01908 break;
01909 case 1:
01910 QWhatsThis::add(cb, writeWhatsThis);
01911 break;
01912 case 2:
01913 QWhatsThis::add(cb, execWhatsThis);
01914 break;
01915 case 3:
01916 switch(row) {
01917 case 0:
01918 QWhatsThis::add(cb, setUidWhatsThis);
01919 break;
01920 case 1:
01921 QWhatsThis::add(cb, setGidWhatsThis);
01922 break;
01923 case 2:
01924 QWhatsThis::add(cb, stickyWhatsThis);
01925 break;
01926 }
01927 break;
01928 }
01929 }
01930 }
01931 gl->setColStretch(6, 10);
01932
01933 if( allDisable )
01934 dlg.enableButtonOK(false );
01935 if (dlg.exec() != KDialogBase::Accepted)
01936 return;
01937
01938 mode_t andPermissions = mode_t(~0);
01939 mode_t orPermissions = 0;
01940 for (int row = 0; row < 3; ++row)
01941 for (int col = 0; col < 4; ++col) {
01942 switch (cba[row][col]->state())
01943 {
01944 case QCheckBox::On:
01945 orPermissions |= fperm[row][col];
01946
01947 case QCheckBox::Off:
01948 andPermissions &= ~fperm[row][col];
01949 break;
01950 default:
01951 break;
01952 }
01953 }
01954
01955 d->isIrregular = false;
01956 KFileItemList items = properties->items();
01957 for (KFileItemListIterator it(items); it.current(); ++it) {
01958 if (isIrregular(((*it)->permissions() & andPermissions) | orPermissions,
01959 (*it)->isDir(), (*it)->isLink())) {
01960 d->isIrregular = true;
01961 break;
01962 }
01963 }
01964
01965 permissions = orPermissions;
01966 d->partialPermissions = andPermissions;
01967
01968 emit changed();
01969 updateAccessControls();
01970 }
01971
01972
01973
01974
01975
01976
01977 KFilePermissionsPropsPlugin::~KFilePermissionsPropsPlugin()
01978 {
01979 delete d;
01980 }
01981
01982 bool KFilePermissionsPropsPlugin::supports( KFileItemList _items )
01983 {
01984 for (KFileItemListIterator it(_items); it.current(); ++it) {
01985 if ( (*it)->url().protocol().find("device", 0, false)!=-1)
01986 return false;
01987 }
01988
01989 return true;
01990 }
01991
01992
01993 void KFilePermissionsPropsPlugin::setComboContent(QComboBox *combo, PermissionsTarget target,
01994 mode_t permissions, mode_t partial) {
01995 combo->clear();
01996 if (d->pmode == PermissionsOnlyLinks) {
01997 combo->insertItem(i18n("Link"));
01998 combo->setCurrentItem(0);
01999 return;
02000 }
02001
02002 mode_t tMask = permissionsMasks[target];
02003 int textIndex;
02004 for (textIndex = 0; standardPermissions[textIndex] != (mode_t)-1; textIndex++)
02005 if ((standardPermissions[textIndex]&tMask) == (permissions&tMask&(UniRead|UniWrite)))
02006 break;
02007 Q_ASSERT(standardPermissions[textIndex] != (mode_t)-1);
02008
02009 for (int i = 0; permissionsTexts[(int)d->pmode][i]; i++)
02010 combo->insertItem(i18n(permissionsTexts[(int)d->pmode][i]));
02011
02012 if (partial & tMask & ~UniExec) {
02013 combo->insertItem(i18n("Varying (No Change)"));
02014 combo->setCurrentItem(3);
02015 }
02016 else
02017 combo->setCurrentItem(textIndex);
02018 }
02019
02020
02021 bool KFilePermissionsPropsPlugin::isIrregular(mode_t permissions, bool isDir, bool isLink) {
02022 if (isLink)
02023 return false;
02024
02025 mode_t p = permissions;
02026 if (p & (S_ISUID | S_ISGID))
02027 return true;
02028 if (isDir) {
02029 p &= ~S_ISVTX;
02030
02031
02032 mode_t p0 = p & UniOwner;
02033 if ((p0 != 0) && (p0 != (S_IRUSR | S_IXUSR)) && (p0 != UniOwner))
02034 return true;
02035 p0 = p & UniGroup;
02036 if ((p0 != 0) && (p0 != (S_IRGRP | S_IXGRP)) && (p0 != UniGroup))
02037 return true;
02038 p0 = p & UniOthers;
02039 if ((p0 != 0) && (p0 != (S_IROTH | S_IXOTH)) && (p0 != UniOthers))
02040 return true;
02041 return false;
02042 }
02043 if (p & S_ISVTX)
02044 return true;
02045
02046
02047 mode_t p0 = p & UniOwner;
02048 bool usrXPossible = !p0;
02049 if (p0 & S_IXUSR) {
02050 if ((p0 == S_IXUSR) || (p0 == (S_IWUSR | S_IXUSR)))
02051 return true;
02052 usrXPossible = true;
02053 }
02054 else if (p0 == S_IWUSR)
02055 return true;
02056
02057 p0 = p & UniGroup;
02058 bool grpXPossible = !p0;
02059 if (p0 & S_IXGRP) {
02060 if ((p0 == S_IXGRP) || (p0 == (S_IWGRP | S_IXGRP)))
02061 return true;
02062 grpXPossible = true;
02063 }
02064 else if (p0 == S_IWGRP)
02065 return true;
02066 if (p0 == 0)
02067 grpXPossible = true;
02068
02069 p0 = p & UniOthers;
02070 bool othXPossible = !p0;
02071 if (p0 & S_IXOTH) {
02072 if ((p0 == S_IXOTH) || (p0 == (S_IWOTH | S_IXOTH)))
02073 return true;
02074 othXPossible = true;
02075 }
02076 else if (p0 == S_IWOTH)
02077 return true;
02078
02079
02080 return (p & UniExec) && !(usrXPossible && grpXPossible && othXPossible);
02081 }
02082
02083
02084 void KFilePermissionsPropsPlugin::enableAccessControls(bool enable) {
02085 d->ownerPermCombo->setEnabled(enable);
02086 d->groupPermCombo->setEnabled(enable);
02087 d->othersPermCombo->setEnabled(enable);
02088 if (d->extraCheckbox)
02089 d->extraCheckbox->setEnabled(enable);
02090 if ( d->cbRecursive )
02091 d->cbRecursive->setEnabled(enable);
02092 }
02093
02094
02095 void KFilePermissionsPropsPlugin::updateAccessControls() {
02096 setComboContent(d->ownerPermCombo, PermissionsOwner,
02097 permissions, d->partialPermissions);
02098 setComboContent(d->groupPermCombo, PermissionsGroup,
02099 permissions, d->partialPermissions);
02100 setComboContent(d->othersPermCombo, PermissionsOthers,
02101 permissions, d->partialPermissions);
02102
02103 switch(d->pmode) {
02104 case PermissionsOnlyLinks:
02105 enableAccessControls(false);
02106 break;
02107 case PermissionsOnlyFiles:
02108 enableAccessControls(d->canChangePermissions && !d->isIrregular);
02109 if (d->canChangePermissions)
02110 d->explanationLabel->setText(d->isIrregular ?
02111 i18n("This file uses advanced permissions",
02112 "These files use advanced permissions.",
02113 properties->items().count()) : "");
02114 if (d->partialPermissions & UniExec) {
02115 d->extraCheckbox->setTristate();
02116 d->extraCheckbox->setNoChange();
02117 }
02118 else {
02119 d->extraCheckbox->setTristate(false);
02120 d->extraCheckbox->setChecked(permissions & UniExec);
02121 }
02122 break;
02123 case PermissionsOnlyDirs:
02124 enableAccessControls(d->canChangePermissions && !d->isIrregular);
02125 if (d->canChangePermissions)
02126 d->explanationLabel->setText(d->isIrregular ?
02127 i18n("This folder uses advanced permissions.",
02128 "These folders use advanced permissions.",
02129 properties->items().count()) : "");
02130 if (d->partialPermissions & S_ISVTX) {
02131 d->extraCheckbox->setTristate();
02132 d->extraCheckbox->setNoChange();
02133 }
02134 else {
02135 d->extraCheckbox->setTristate(false);
02136 d->extraCheckbox->setChecked(permissions & S_ISVTX);
02137 }
02138 break;
02139 case PermissionsMixed:
02140 enableAccessControls(d->canChangePermissions && !d->isIrregular);
02141 if (d->canChangePermissions)
02142 d->explanationLabel->setText(d->isIrregular ?
02143 i18n("These files use advanced permissions.") : "");
02144 break;
02145 if (d->partialPermissions & S_ISVTX) {
02146 d->extraCheckbox->setTristate();
02147 d->extraCheckbox->setNoChange();
02148 }
02149 else {
02150 d->extraCheckbox->setTristate(false);
02151 d->extraCheckbox->setChecked(permissions & S_ISVTX);
02152 }
02153 break;
02154 }
02155 }
02156
02157
02158 void KFilePermissionsPropsPlugin::getPermissionMasks(mode_t &andFilePermissions,
02159 mode_t &andDirPermissions,
02160 mode_t &orFilePermissions,
02161 mode_t &orDirPermissions) {
02162 andFilePermissions = mode_t(~UniSpecial);
02163 andDirPermissions = mode_t(~(S_ISUID|S_ISGID));
02164 orFilePermissions = 0;
02165 orDirPermissions = 0;
02166 if (d->isIrregular)
02167 return;
02168
02169 mode_t m = standardPermissions[d->ownerPermCombo->currentItem()];
02170 if (m != (mode_t) -1) {
02171 orFilePermissions |= m & UniOwner;
02172 if ((m & UniOwner) &&
02173 ((d->pmode == PermissionsMixed) ||
02174 ((d->pmode == PermissionsOnlyFiles) && (d->extraCheckbox->state() == QButton::NoChange))))
02175 andFilePermissions &= ~(S_IRUSR | S_IWUSR);
02176 else {
02177 andFilePermissions &= ~(S_IRUSR | S_IWUSR | S_IXUSR);
02178 if ((m & S_IRUSR) && (d->extraCheckbox->state() == QButton::On))
02179 orFilePermissions |= S_IXUSR;
02180 }
02181
02182 orDirPermissions |= m & UniOwner;
02183 if (m & S_IRUSR)
02184 orDirPermissions |= S_IXUSR;
02185 andDirPermissions &= ~(S_IRUSR | S_IWUSR | S_IXUSR);
02186 }
02187
02188 m = standardPermissions[d->groupPermCombo->currentItem()];
02189 if (m != (mode_t) -1) {
02190 orFilePermissions |= m & UniGroup;
02191 if ((m & UniGroup) &&
02192 ((d->pmode == PermissionsMixed) ||
02193 ((d->pmode == PermissionsOnlyFiles) && (d->extraCheckbox->state() == QButton::NoChange))))
02194 andFilePermissions &= ~(S_IRGRP | S_IWGRP);
02195 else {
02196 andFilePermissions &= ~(S_IRGRP | S_IWGRP | S_IXGRP);
02197 if ((m & S_IRGRP) && (d->extraCheckbox->state() == QButton::On))
02198 orFilePermissions |= S_IXGRP;
02199 }
02200
02201 orDirPermissions |= m & UniGroup;
02202 if (m & S_IRGRP)
02203 orDirPermissions |= S_IXGRP;
02204 andDirPermissions &= ~(S_IRGRP | S_IWGRP | S_IXGRP);
02205 }
02206
02207 m = standardPermissions[d->othersPermCombo->currentItem()];
02208 if (m != (mode_t) -1) {
02209 orFilePermissions |= m & UniOthers;
02210 if ((m & UniOthers) &&
02211 ((d->pmode == PermissionsMixed) ||
02212 ((d->pmode == PermissionsOnlyFiles) && (d->extraCheckbox->state() == QButton::NoChange))))
02213 andFilePermissions &= ~(S_IROTH | S_IWOTH);
02214 else {
02215 andFilePermissions &= ~(S_IROTH | S_IWOTH | S_IXOTH);
02216 if ((m & S_IROTH) && (d->extraCheckbox->state() == QButton::On))
02217 orFilePermissions |= S_IXOTH;
02218 }
02219
02220 orDirPermissions |= m & UniOthers;
02221 if (m & S_IROTH)
02222 orDirPermissions |= S_IXOTH;
02223 andDirPermissions &= ~(S_IROTH | S_IWOTH | S_IXOTH);
02224 }
02225
02226 if (((d->pmode == PermissionsMixed) || (d->pmode == PermissionsOnlyDirs)) &&
02227 (d->extraCheckbox->state() != QButton::NoChange)) {
02228 andDirPermissions &= ~S_ISVTX;
02229 if (d->extraCheckbox->state() == QButton::On)
02230 orDirPermissions |= S_ISVTX;
02231 }
02232 }
02233
02234 void KFilePermissionsPropsPlugin::applyChanges()
02235 {
02236 mode_t orFilePermissions;
02237 mode_t orDirPermissions;
02238 mode_t andFilePermissions;
02239 mode_t andDirPermissions;
02240
02241 if (!d->canChangePermissions)
02242 return;
02243
02244 if (!d->isIrregular)
02245 getPermissionMasks(andFilePermissions,
02246 andDirPermissions,
02247 orFilePermissions,
02248 orDirPermissions);
02249 else {
02250 orFilePermissions = permissions;
02251 andFilePermissions = d->partialPermissions;
02252 orDirPermissions = permissions;
02253 andDirPermissions = d->partialPermissions;
02254 }
02255
02256 QString owner, group;
02257 if (usrEdit)
02258 owner = usrEdit->text();
02259 if (grpEdit)
02260 group = grpEdit->text();
02261 else if (grpCombo)
02262 group = grpCombo->currentText();
02263
02264 if (owner == strOwner)
02265 owner = QString::null;
02266
02267 if (group == strGroup)
02268 group = QString::null;
02269
02270 bool recursive = d->cbRecursive && d->cbRecursive->isChecked();
02271 bool permissionChange = false;
02272
02273 KFileItemList files, dirs;
02274 KFileItemList items = properties->items();
02275 for (KFileItemListIterator it(items); it.current(); ++it) {
02276 if ((*it)->isDir()) {
02277 dirs.append(*it);
02278 if ((*it)->permissions() != (((*it)->permissions() & andDirPermissions) | orDirPermissions))
02279 permissionChange = true;
02280 }
02281 else if ((*it)->isFile()) {
02282 files.append(*it);
02283 if ((*it)->permissions() != (((*it)->permissions() & andFilePermissions) | orFilePermissions))
02284 permissionChange = true;
02285 }
02286 }
02287
02288 if ( !owner.isEmpty() || !group.isEmpty() || recursive || permissionChange)
02289 {
02290 KIO::Job * job;
02291 if (files.count() > 0) {
02292 job = KIO::chmod( files, orFilePermissions, ~andFilePermissions,
02293 owner, group, false );
02294 connect( job, SIGNAL( result( KIO::Job * ) ),
02295 SLOT( slotChmodResult( KIO::Job * ) ) );
02296
02297 QWidget dummy(0,0,WType_Dialog|WShowModal);
02298 qt_enter_modal(&dummy);
02299 qApp->enter_loop();
02300 qt_leave_modal(&dummy);
02301 }
02302 if (dirs.count() > 0) {
02303 job = KIO::chmod( dirs, orDirPermissions, ~andDirPermissions,
02304 owner, group, recursive );
02305 connect( job, SIGNAL( result( KIO::Job * ) ),
02306 SLOT( slotChmodResult( KIO::Job * ) ) );
02307
02308 QWidget dummy(0,0,WType_Dialog|WShowModal);
02309 qt_enter_modal(&dummy);
02310 qApp->enter_loop();
02311 qt_leave_modal(&dummy);
02312 }
02313 }
02314 }
02315
02316 void KFilePermissionsPropsPlugin::slotChmodResult( KIO::Job * job )
02317 {
02318 kdDebug(250) << "KFilePermissionsPropsPlugin::slotChmodResult" << endl;
02319 if (job->error())
02320 job->showErrorDialog( d->m_frame );
02321
02322 qApp->exit_loop();
02323 }
02324
02325
02326
02327
02328 class KURLPropsPlugin::KURLPropsPluginPrivate
02329 {
02330 public:
02331 KURLPropsPluginPrivate()
02332 {
02333 }
02334 ~KURLPropsPluginPrivate()
02335 {
02336 }
02337
02338 QFrame *m_frame;
02339 };
02340
02341 KURLPropsPlugin::KURLPropsPlugin( KPropertiesDialog *_props )
02342 : KPropsDlgPlugin( _props )
02343 {
02344 d = new KURLPropsPluginPrivate;
02345 d->m_frame = properties->addPage(i18n("U&RL"));
02346 QVBoxLayout *layout = new QVBoxLayout(d->m_frame, 0, KDialog::spacingHint());
02347
02348 QLabel *l;
02349 l = new QLabel( d->m_frame, "Label_1" );
02350 l->setText( i18n("URL:") );
02351 layout->addWidget(l);
02352
02353 URLEdit = new KURLRequester( d->m_frame, "URL Requester" );
02354 layout->addWidget(URLEdit);
02355
02356 QString path = properties->kurl().path();
02357
02358 QFile f( path );
02359 if ( !f.open( IO_ReadOnly ) )
02360 return;
02361 f.close();
02362
02363 KSimpleConfig config( path );
02364 config.setDesktopGroup();
02365 URLStr = config.readPathEntry( "URL" );
02366
02367 if ( !URLStr.isNull() )
02368 URLEdit->setURL( URLStr );
02369
02370 connect( URLEdit, SIGNAL( textChanged( const QString & ) ),
02371 this, SIGNAL( changed() ) );
02372
02373 layout->addStretch (1);
02374 }
02375
02376 KURLPropsPlugin::~KURLPropsPlugin()
02377 {
02378 delete d;
02379 }
02380
02381
02382
02383
02384
02385
02386 bool KURLPropsPlugin::supports( KFileItemList _items )
02387 {
02388 if ( _items.count() != 1 )
02389 return false;
02390 KFileItem * item = _items.first();
02391
02392 if ( !KPropsDlgPlugin::isDesktopFile( item ) )
02393 return false;
02394
02395
02396 KDesktopFile config( item->url().path(), true );
02397 return config.hasLinkType();
02398 }
02399
02400 void KURLPropsPlugin::applyChanges()
02401 {
02402 QString path = properties->kurl().path();
02403
02404 QFile f( path );
02405 if ( !f.open( IO_ReadWrite ) ) {
02406 KMessageBox::sorry( 0, i18n("<qt>Could not save properties. You do not have "
02407 "sufficient access to write to <b>%1</b>.</qt>").arg(path));
02408 return;
02409 }
02410 f.close();
02411
02412 KSimpleConfig config( path );
02413 config.setDesktopGroup();
02414 config.writeEntry( "Type", QString::fromLatin1("Link"));
02415 config.writePathEntry( "URL", URLEdit->url() );
02416
02417
02418 if ( config.hasKey("Name") )
02419 {
02420 QString nameStr = nameFromFileName(properties->kurl().fileName());
02421 config.writeEntry( "Name", nameStr );
02422 config.writeEntry( "Name", nameStr, true, false, true );
02423
02424 }
02425 }
02426
02427
02428
02429
02430
02431
02432
02433
02434 class KBindingPropsPlugin::KBindingPropsPluginPrivate
02435 {
02436 public:
02437 KBindingPropsPluginPrivate()
02438 {
02439 }
02440 ~KBindingPropsPluginPrivate()
02441 {
02442 }
02443
02444 QFrame *m_frame;
02445 };
02446
02447 KBindingPropsPlugin::KBindingPropsPlugin( KPropertiesDialog *_props ) : KPropsDlgPlugin( _props )
02448 {
02449 d = new KBindingPropsPluginPrivate;
02450 d->m_frame = properties->addPage(i18n("A&ssociation"));
02451 patternEdit = new KLineEdit( d->m_frame, "LineEdit_1" );
02452 commentEdit = new KLineEdit( d->m_frame, "LineEdit_2" );
02453 mimeEdit = new KLineEdit( d->m_frame, "LineEdit_3" );
02454
02455 QBoxLayout *mainlayout = new QVBoxLayout(d->m_frame, 0, KDialog::spacingHint());
02456 QLabel* tmpQLabel;
02457
02458 tmpQLabel = new QLabel( d->m_frame, "Label_1" );
02459 tmpQLabel->setText( i18n("Pattern ( example: *.html;*.htm )") );
02460 tmpQLabel->setMinimumSize(tmpQLabel->sizeHint());
02461 mainlayout->addWidget(tmpQLabel, 1);
02462
02463
02464
02465 patternEdit->setMaxLength( 512 );
02466 patternEdit->setMinimumSize( patternEdit->sizeHint() );
02467 patternEdit->setFixedHeight( fontHeight );
02468 mainlayout->addWidget(patternEdit, 1);
02469
02470 tmpQLabel = new QLabel( d->m_frame, "Label_2" );
02471 tmpQLabel->setText( i18n("Mime Type") );
02472 tmpQLabel->setMinimumSize(tmpQLabel->sizeHint());
02473 mainlayout->addWidget(tmpQLabel, 1);
02474
02475
02476 mimeEdit->setMaxLength( 256 );
02477 mimeEdit->setMinimumSize( mimeEdit->sizeHint() );
02478 mimeEdit->setFixedHeight( fontHeight );
02479 mainlayout->addWidget(mimeEdit, 1);
02480
02481 tmpQLabel = new QLabel( d->m_frame, "Label_3" );
02482 tmpQLabel->setText( i18n("Comment") );
02483 tmpQLabel->setMinimumSize(tmpQLabel->sizeHint());
02484 mainlayout->addWidget(tmpQLabel, 1);
02485
02486
02487 commentEdit->setMaxLength( 256 );
02488 commentEdit->setMinimumSize( commentEdit->sizeHint() );
02489 commentEdit->setFixedHeight( fontHeight );
02490 mainlayout->addWidget(commentEdit, 1);
02491
02492 cbAutoEmbed = new QCheckBox( i18n("Left click previews"), d->m_frame, "cbAutoEmbed" );
02493 mainlayout->addWidget(cbAutoEmbed, 1);
02494
02495 mainlayout->addStretch (10);
02496 mainlayout->activate();
02497
02498 QFile f( _props->kurl().path() );
02499 if ( !f.open( IO_ReadOnly ) )
02500 return;
02501 f.close();
02502
02503 KSimpleConfig config( _props->kurl().path() );
02504 config.setDesktopGroup();
02505 QString patternStr = config.readEntry( "Patterns" );
02506 QString iconStr = config.readEntry( "Icon" );
02507 QString commentStr = config.readEntry( "Comment" );
02508 m_sMimeStr = config.readEntry( "MimeType" );
02509
02510 if ( !patternStr.isEmpty() )
02511 patternEdit->setText( patternStr );
02512 if ( !commentStr.isEmpty() )
02513 commentEdit->setText( commentStr );
02514 if ( !m_sMimeStr.isEmpty() )
02515 mimeEdit->setText( m_sMimeStr );
02516 cbAutoEmbed->setTristate();
02517 if ( config.hasKey( "X-KDE-AutoEmbed" ) )
02518 cbAutoEmbed->setChecked( config.readBoolEntry( "X-KDE-AutoEmbed" ) );
02519 else
02520 cbAutoEmbed->setNoChange();
02521
02522 connect( patternEdit, SIGNAL( textChanged( const QString & ) ),
02523 this, SIGNAL( changed() ) );
02524 connect( commentEdit, SIGNAL( textChanged( const QString & ) ),
02525 this, SIGNAL( changed() ) );
02526 connect( mimeEdit, SIGNAL( textChanged( const QString & ) ),
02527 this, SIGNAL( changed() ) );
02528 connect( cbAutoEmbed, SIGNAL( toggled( bool ) ),
02529 this, SIGNAL( changed() ) );
02530 }
02531
02532 KBindingPropsPlugin::~KBindingPropsPlugin()
02533 {
02534 delete d;
02535 }
02536
02537
02538
02539
02540
02541
02542 bool KBindingPropsPlugin::supports( KFileItemList _items )
02543 {
02544 if ( _items.count() != 1 )
02545 return false;
02546 KFileItem * item = _items.first();
02547
02548 if ( !KPropsDlgPlugin::isDesktopFile( item ) )
02549 return false;
02550
02551
02552 KDesktopFile config( item->url().path(), true );
02553 return config.hasMimeTypeType();
02554 }
02555
02556 void KBindingPropsPlugin::applyChanges()
02557 {
02558 QString path = properties->kurl().path();
02559 QFile f( path );
02560
02561 if ( !f.open( IO_ReadWrite ) )
02562 {
02563 KMessageBox::sorry( 0, i18n("<qt>Could not save properties. You do not have "
02564 "sufficient access to write to <b>%1</b>.</qt>").arg(path));
02565 return;
02566 }
02567 f.close();
02568
02569 KSimpleConfig config( path );
02570 config.setDesktopGroup();
02571 config.writeEntry( "Type", QString::fromLatin1("MimeType") );
02572
02573 config.writeEntry( "Patterns", patternEdit->text() );
02574 config.writeEntry( "Comment", commentEdit->text() );
02575 config.writeEntry( "Comment",
02576 commentEdit->text(), true, false, true );
02577 config.writeEntry( "MimeType", mimeEdit->text() );
02578 if ( cbAutoEmbed->state() == QButton::NoChange )
02579 config.deleteEntry( "X-KDE-AutoEmbed", false );
02580 else
02581 config.writeEntry( "X-KDE-AutoEmbed", cbAutoEmbed->isChecked() );
02582 config.sync();
02583 }
02584
02585
02586
02587
02588
02589
02590
02591 class KDevicePropsPlugin::KDevicePropsPluginPrivate
02592 {
02593 public:
02594 KDevicePropsPluginPrivate()
02595 {
02596 }
02597 ~KDevicePropsPluginPrivate()
02598 {
02599 }
02600
02601 QFrame *m_frame;
02602 QStringList mountpointlist;
02603 };
02604
02605 KDevicePropsPlugin::KDevicePropsPlugin( KPropertiesDialog *_props ) : KPropsDlgPlugin( _props )
02606 {
02607 d = new KDevicePropsPluginPrivate;
02608 d->m_frame = properties->addPage(i18n("De&vice"));
02609
02610 QStringList devices;
02611 KMountPoint::List mountPoints = KMountPoint::possibleMountPoints();
02612
02613 for(KMountPoint::List::ConstIterator it = mountPoints.begin();
02614 it != mountPoints.end(); ++it)
02615 {
02616 KMountPoint *mp = *it;
02617 QString mountPoint = mp->mountPoint();
02618 QString device = mp->mountedFrom();
02619 kdDebug()<<"mountPoint :"<<mountPoint<<" device :"<<device<<" mp->mountType() :"<<mp->mountType()<<endl;
02620
02621 if ((mountPoint != "-") && (mountPoint != "none") && !mountPoint.isEmpty()
02622 && device != "none")
02623 {
02624 devices.append( device + QString::fromLatin1(" (")
02625 + mountPoint + QString::fromLatin1(")") );
02626 m_devicelist.append(device);
02627 d->mountpointlist.append(mountPoint);
02628 }
02629 }
02630
02631 QGridLayout *layout = new QGridLayout( d->m_frame, 0, 3, 0,
02632 KDialog::spacingHint());
02633 layout->setColStretch(1, 1);
02634
02635 QLabel* label;
02636 label = new QLabel( d->m_frame );
02637 label->setText( devices.count() == 0 ?
02638 i18n("Device (/dev/fd0):") :
02639 i18n("Device:") );
02640 layout->addWidget(label, 0, 0);
02641
02642 device = new QComboBox( true, d->m_frame, "ComboBox_device" );
02643 device->insertStringList( devices );
02644 layout->addWidget(device, 0, 1);
02645 connect( device, SIGNAL( activated( int ) ),
02646 this, SLOT( slotActivated( int ) ) );
02647
02648 readonly = new QCheckBox( d->m_frame, "CheckBox_readonly" );
02649 readonly->setText( i18n("Read only") );
02650 layout->addWidget(readonly, 1, 1);
02651
02652 label = new QLabel( d->m_frame );
02653 label->setText( devices.count()==0 ?
02654 i18n("Mount point (/mnt/floppy):") :
02655 i18n("Mount point:"));
02656 layout->addWidget(label, 2, 0);
02657
02658 mountpoint = new QLabel( d->m_frame, "LineEdit_mountpoint" );
02659
02660 layout->addWidget(mountpoint, 2, 1);
02661
02662 KSeparator* sep = new KSeparator( KSeparator::HLine, d->m_frame);
02663 layout->addMultiCellWidget(sep, 4, 4, 0, 2);
02664
02665 unmounted = new KIconButton( d->m_frame );
02666 int bsize = 66 + 2 * unmounted->style().pixelMetric(QStyle::PM_ButtonMargin);
02667 unmounted->setFixedSize(bsize, bsize);
02668 unmounted->setIconType(KIcon::Desktop, KIcon::Device);
02669 layout->addWidget(unmounted, 5, 0);
02670
02671 label = new QLabel( i18n("Unmounted Icon"), d->m_frame );
02672 layout->addWidget(label, 5, 1);
02673
02674 layout->setRowStretch(6, 1);
02675
02676 QString path( _props->kurl().path() );
02677
02678 QFile f( path );
02679 if ( !f.open( IO_ReadOnly ) )
02680 return;
02681 f.close();
02682
02683 KSimpleConfig config( path );
02684 config.setDesktopGroup();
02685 QString deviceStr = config.readEntry( "Dev" );
02686 QString mountPointStr = config.readEntry( "MountPoint" );
02687 bool ro = config.readBoolEntry( "ReadOnly", false );
02688 QString unmountedStr = config.readEntry( "UnmountIcon" );
02689
02690 device->setEditText( deviceStr );
02691 if ( !deviceStr.isEmpty() ) {
02692
02693 int index = m_devicelist.findIndex(deviceStr);
02694 if (index != -1)
02695 {
02696
02697 slotActivated( index );
02698 }
02699 }
02700
02701 if ( !mountPointStr.isEmpty() )
02702 mountpoint->setText( mountPointStr );
02703
02704 readonly->setChecked( ro );
02705
02706 if ( unmountedStr.isEmpty() )
02707 unmountedStr = KMimeType::mimeType(QString::fromLatin1("application/octet-stream"))->KServiceType::icon();
02708
02709 unmounted->setIcon( unmountedStr );
02710
02711 connect( device, SIGNAL( activated( int ) ),
02712 this, SIGNAL( changed() ) );
02713 connect( device, SIGNAL( textChanged( const QString & ) ),
02714 this, SIGNAL( changed() ) );
02715 connect( readonly, SIGNAL( toggled( bool ) ),
02716 this, SIGNAL( changed() ) );
02717 connect( unmounted, SIGNAL( iconChanged( QString ) ),
02718 this, SIGNAL( changed() ) );
02719
02720 connect( device, SIGNAL( textChanged( const QString & ) ),
02721 this, SLOT( slotDeviceChanged() ) );
02722 }
02723
02724 KDevicePropsPlugin::~KDevicePropsPlugin()
02725 {
02726 delete d;
02727 }
02728
02729
02730
02731
02732
02733
02734 void KDevicePropsPlugin::slotActivated( int index )
02735 {
02736
02737 device->setEditText( m_devicelist[index] );
02738 mountpoint->setText( d->mountpointlist[index] );
02739 }
02740
02741 void KDevicePropsPlugin::slotDeviceChanged()
02742 {
02743
02744 int index = m_devicelist.findIndex( device->currentText() );
02745 if ( index != -1 )
02746 mountpoint->setText( d->mountpointlist[index] );
02747 else
02748 mountpoint->setText( QString::null );
02749 }
02750
02751 bool KDevicePropsPlugin::supports( KFileItemList _items )
02752 {
02753 if ( _items.count() != 1 )
02754 return false;
02755 KFileItem * item = _items.first();
02756
02757 if ( !KPropsDlgPlugin::isDesktopFile( item ) )
02758 return false;
02759
02760 KDesktopFile config( item->url().path(), true );
02761 return config.hasDeviceType();
02762 }
02763
02764 void KDevicePropsPlugin::applyChanges()
02765 {
02766 QString path = properties->kurl().path();
02767 QFile f( path );
02768 if ( !f.open( IO_ReadWrite ) )
02769 {
02770 KMessageBox::sorry( 0, i18n("<qt>Could not save properties. You do not have sufficient "
02771 "access to write to <b>%1</b>.</qt>").arg(path));
02772 return;
02773 }
02774 f.close();
02775
02776 KSimpleConfig config( path );
02777 config.setDesktopGroup();
02778 config.writeEntry( "Type", QString::fromLatin1("FSDevice") );
02779
02780 config.writeEntry( "Dev", device->currentText() );
02781 config.writeEntry( "MountPoint", mountpoint->text() );
02782
02783 config.writeEntry( "UnmountIcon", unmounted->icon() );
02784 kdDebug(250) << "unmounted->icon() = " << unmounted->icon() << endl;
02785
02786 config.writeEntry( "ReadOnly", readonly->isChecked() );
02787
02788 config.sync();
02789 }
02790
02791
02792
02793
02794
02795
02796
02797
02798
02799 KDesktopPropsPlugin::KDesktopPropsPlugin( KPropertiesDialog *_props )
02800 : KPropsDlgPlugin( _props )
02801 {
02802 QFrame *frame = properties->addPage(i18n("&Application"));
02803 QVBoxLayout *mainlayout = new QVBoxLayout( frame, 0, KDialog::spacingHint() );
02804
02805 w = new KPropertiesDesktopBase(frame);
02806 mainlayout->addWidget(w);
02807
02808 bool bKDesktopMode = (QCString(qApp->name()) == "kdesktop");
02809
02810 if (bKDesktopMode)
02811 {
02812
02813 w->nameEdit->hide();
02814 w->nameLabel->hide();
02815 }
02816
02817 w->pathEdit->setMode(KFile::Directory | KFile::LocalOnly);
02818 w->pathEdit->lineEdit()->setAcceptDrops(false);
02819
02820 connect( w->nameEdit, SIGNAL( textChanged( const QString & ) ), this, SIGNAL( changed() ) );
02821 connect( w->genNameEdit, SIGNAL( textChanged( const QString & ) ), this, SIGNAL( changed() ) );
02822 connect( w->commentEdit, SIGNAL( textChanged( const QString & ) ), this, SIGNAL( changed() ) );
02823 connect( w->commandEdit, SIGNAL( textChanged( const QString & ) ), this, SIGNAL( changed() ) );
02824 connect( w->pathEdit, SIGNAL( textChanged( const QString & ) ), this, SIGNAL( changed() ) );
02825
02826 connect( w->browseButton, SIGNAL( clicked() ), this, SLOT( slotBrowseExec() ) );
02827 connect( w->addFiletypeButton, SIGNAL( clicked() ), this, SLOT( slotAddFiletype() ) );
02828 connect( w->delFiletypeButton, SIGNAL( clicked() ), this, SLOT( slotDelFiletype() ) );
02829 connect( w->advancedButton, SIGNAL( clicked() ), this, SLOT( slotAdvanced() ) );
02830
02831
02832 QString path = _props->kurl().path();
02833 QFile f( path );
02834 if ( !f.open( IO_ReadOnly ) )
02835 return;
02836 f.close();
02837
02838 KSimpleConfig config( path );
02839 config.setDollarExpansion( false );
02840 config.setDesktopGroup();
02841 QString nameStr = config.readEntry( "Name" );
02842 QString genNameStr = config.readEntry( "GenericName" );
02843 QString commentStr = config.readEntry( "Comment" );
02844 QString commandStr = config.readPathEntry( "Exec" );
02845 if (commandStr.left(12) == "ksystraycmd ")
02846 {
02847 commandStr.remove(0, 12);
02848 m_systrayBool = true;
02849 }
02850 else
02851 m_systrayBool = false;
02852
02853 m_origCommandStr = commandStr;
02854 QString pathStr = config.readPathEntry( "Path" );
02855 m_terminalBool = config.readBoolEntry( "Terminal" );
02856 m_terminalOptionStr = config.readEntry( "TerminalOptions" );
02857 m_suidBool = config.readBoolEntry( "X-KDE-SubstituteUID" );
02858 m_suidUserStr = config.readEntry( "X-KDE-Username" );
02859 if( config.hasKey( "StartupNotify" ))
02860 m_startupBool = config.readBoolEntry( "StartupNotify", true );
02861 else
02862 m_startupBool = config.readBoolEntry( "X-KDE-StartupNotify", true );
02863 m_dcopServiceType = config.readEntry("X-DCOP-ServiceType").lower();
02864
02865 QStringList mimeTypes = config.readListEntry( "MimeType", ';' );
02866
02867 if ( nameStr.isEmpty() || bKDesktopMode ) {
02868
02869
02870
02871 setDirty();
02872 }
02873 if ( !bKDesktopMode )
02874 w->nameEdit->setText(nameStr);
02875
02876 w->genNameEdit->setText( genNameStr );
02877 w->commentEdit->setText( commentStr );
02878 w->commandEdit->setText( commandStr );
02879 w->pathEdit->lineEdit()->setText( pathStr );
02880 w->filetypeList->setAllColumnsShowFocus(true);
02881
02882 KMimeType::Ptr defaultMimetype = KMimeType::defaultMimeTypePtr();
02883 for(QStringList::ConstIterator it = mimeTypes.begin();
02884 it != mimeTypes.end(); )
02885 {
02886 KMimeType::Ptr p = KMimeType::mimeType(*it);
02887 ++it;
02888 QString preference;
02889 if (it != mimeTypes.end())
02890 {
02891 bool numeric;
02892 (*it).toInt(&numeric);
02893 if (numeric)
02894 {
02895 preference = *it;
02896 ++it;
02897 }
02898 }
02899 if (p && (p != defaultMimetype))
02900 {
02901 new QListViewItem(w->filetypeList, p->name(), p->comment(), preference);
02902 }
02903 }
02904
02905 }
02906
02907 KDesktopPropsPlugin::~KDesktopPropsPlugin()
02908 {
02909 }
02910
02911 void KDesktopPropsPlugin::slotSelectMimetype()
02912 {
02913 QListView *w = (QListView*)sender();
02914 QListViewItem *item = w->firstChild();
02915 while(item)
02916 {
02917 if (item->isSelected())
02918 w->setSelected(item, false);
02919 item = item->nextSibling();
02920 }
02921 }
02922
02923 void KDesktopPropsPlugin::slotAddFiletype()
02924 {
02925 KDialogBase dlg(w, "KPropertiesMimetypes", true,
02926 i18n("Add File Type for %1").arg(properties->kurl().fileName()),
02927 KDialogBase::Ok|KDialogBase::Cancel, KDialogBase::Ok);
02928
02929 KGuiItem okItem(i18n("&Add"), QString::null ,
02930 i18n("Add the selected file types to\nthe list of supported file types."),
02931 i18n("Add the selected file types to\nthe list of supported file types."));
02932 dlg.setButtonOK(okItem);
02933
02934 KPropertiesMimetypeBase *mw = new KPropertiesMimetypeBase(&dlg);
02935
02936 dlg.setMainWidget(mw);
02937
02938 {
02939 mw->listView->setRootIsDecorated(true);
02940 mw->listView->setSelectionMode(QListView::Extended);
02941 mw->listView->setAllColumnsShowFocus(true);
02942 mw->listView->setFullWidth(true);
02943 mw->listView->setMinimumSize(500,400);
02944
02945 connect(mw->listView, SIGNAL(selectionChanged()),
02946 this, SLOT(slotSelectMimetype()));
02947 connect(mw->listView, SIGNAL(doubleClicked( QListViewItem *, const QPoint &, int )),
02948 &dlg, SLOT( slotOk()));
02949
02950 QMap<QString,QListViewItem*> majorMap;
02951 QListViewItem *majorGroup;
02952 KMimeType::List mimetypes = KMimeType::allMimeTypes();
02953 QValueListIterator<KMimeType::Ptr> it(mimetypes.begin());
02954 for (; it != mimetypes.end(); ++it) {
02955 QString mimetype = (*it)->name();
02956 if (mimetype == "application/octet-stream")
02957 continue;
02958 int index = mimetype.find("/");
02959 QString maj = mimetype.left(index);
02960 QString min = mimetype.mid(index+1);
02961
02962 QMapIterator<QString,QListViewItem*> mit = majorMap.find( maj );
02963 if ( mit == majorMap.end() ) {
02964 majorGroup = new QListViewItem( mw->listView, maj );
02965 majorGroup->setExpandable(true);
02966 mw->listView->setOpen(majorGroup, true);
02967 majorMap.insert( maj, majorGroup );
02968 }
02969 else
02970 {
02971 majorGroup = mit.data();
02972 }
02973
02974 QListViewItem *item = new QListViewItem(majorGroup, min, (*it)->comment());
02975 item->setPixmap(0, (*it)->pixmap(KIcon::Small, IconSize(KIcon::Small)));
02976 }
02977 QMapIterator<QString,QListViewItem*> mit = majorMap.find( "all" );
02978 if ( mit != majorMap.end())
02979 {
02980 mw->listView->setCurrentItem(mit.data());
02981 mw->listView->ensureItemVisible(mit.data());
02982 }
02983 }
02984
02985 if (dlg.exec() == KDialogBase::Accepted)
02986 {
02987 KMimeType::Ptr defaultMimetype = KMimeType::defaultMimeTypePtr();
02988 QListViewItem *majorItem = mw->listView->firstChild();
02989 while(majorItem)
02990 {
02991 QString major = majorItem->text(0);
02992
02993 QListViewItem *minorItem = majorItem->firstChild();
02994 while(minorItem)
02995 {
02996 if (minorItem->isSelected())
02997 {
02998 QString mimetype = major + "/" + minorItem->text(0);
02999 KMimeType::Ptr p = KMimeType::mimeType(mimetype);
03000 if (p && (p != defaultMimetype))
03001 {
03002 mimetype = p->name();
03003 bool found = false;
03004 QListViewItem *item = w->filetypeList->firstChild();
03005 while (item)
03006 {
03007 if (mimetype == item->text(0))
03008 {
03009 found = true;
03010 break;
03011 }
03012 item = item->nextSibling();
03013 }
03014 if (!found)
03015 new QListViewItem(w->filetypeList, p->name(), p->comment());
03016 }
03017 }
03018 minorItem = minorItem->nextSibling();
03019 }
03020
03021 majorItem = majorItem->nextSibling();
03022 }
03023
03024 }
03025 }
03026
03027 void KDesktopPropsPlugin::slotDelFiletype()
03028 {
03029 delete w->filetypeList->currentItem();
03030 }
03031
03032 void KDesktopPropsPlugin::checkCommandChanged()
03033 {
03034 if (KRun::binaryName(w->commandEdit->text(), true) !=
03035 KRun::binaryName(m_origCommandStr, true))
03036 {
03037 QString m_origCommandStr = w->commandEdit->text();
03038 m_dcopServiceType= QString::null;
03039 }
03040 }
03041
03042 void KDesktopPropsPlugin::applyChanges()
03043 {
03044 kdDebug(250) << "KDesktopPropsPlugin::applyChanges" << endl;
03045 QString path = properties->kurl().path();
03046
03047 QFile f( path );
03048
03049 if ( !f.open( IO_ReadWrite ) ) {
03050 KMessageBox::sorry( 0, i18n("<qt>Could not save properties. You do not have "
03051 "sufficient access to write to <b>%1</b>.</qt>").arg(path));
03052 return;
03053 }
03054 f.close();
03055
03056
03057
03058 checkCommandChanged();
03059
03060 KSimpleConfig config( path );
03061 config.setDesktopGroup();
03062 config.writeEntry( "Type", QString::fromLatin1("Application"));
03063 config.writeEntry( "Comment", w->commentEdit->text() );
03064 config.writeEntry( "Comment", w->commentEdit->text(), true, false, true );
03065 config.writeEntry( "GenericName", w->genNameEdit->text() );
03066 config.writeEntry( "GenericName", w->genNameEdit->text(), true, false, true );
03067
03068 if (m_systrayBool)
03069 config.writePathEntry( "Exec", w->commandEdit->text().prepend("ksystraycmd ") );
03070 else
03071 config.writePathEntry( "Exec", w->commandEdit->text() );
03072 config.writePathEntry( "Path", w->pathEdit->lineEdit()->text() );
03073
03074
03075 QStringList mimeTypes;
03076 for( QListViewItem *item = w->filetypeList->firstChild();
03077 item; item = item->nextSibling() )
03078 {
03079 QString preference = item->text(2);
03080 mimeTypes.append(item->text(0));
03081 if (!preference.isEmpty())
03082 mimeTypes.append(preference);
03083 }
03084
03085 config.writeEntry( "MimeType", mimeTypes, ';' );
03086
03087 if ( !w->nameEdit->isHidden() ) {
03088 QString nameStr = w->nameEdit->text();
03089 config.writeEntry( "Name", nameStr );
03090 config.writeEntry( "Name", nameStr, true, false, true );
03091 }
03092
03093 config.writeEntry("Terminal", m_terminalBool);
03094 config.writeEntry("TerminalOptions", m_terminalOptionStr);
03095 config.writeEntry("X-KDE-SubstituteUID", m_suidBool);
03096 config.writeEntry("X-KDE-Username", m_suidUserStr);
03097 config.writeEntry("StartupNotify", m_startupBool);
03098 config.writeEntry("X-DCOP-ServiceType", m_dcopServiceType);
03099 config.sync();
03100
03101
03102 QString sycocaPath = KGlobal::dirs()->relativeLocation("apps", path);
03103 bool updateNeeded = !sycocaPath.startsWith("/");
03104 if (!updateNeeded)
03105 {
03106 sycocaPath = KGlobal::dirs()->relativeLocation("xdgdata-apps", path);
03107 updateNeeded = !sycocaPath.startsWith("/");
03108 }
03109 if (updateNeeded)
03110 KService::rebuildKSycoca(w);
03111 }
03112
03113
03114 void KDesktopPropsPlugin::slotBrowseExec()
03115 {
03116 KURL f = KFileDialog::getOpenURL( QString::null,
03117 QString::null, w );
03118 if ( f.isEmpty() )
03119 return;
03120
03121 if ( !f.isLocalFile()) {
03122 KMessageBox::sorry(w, i18n("Only executables on local file systems are supported."));
03123 return;
03124 }
03125
03126 QString path = f.path();
03127 KRun::shellQuote( path );
03128 w->commandEdit->setText( path );
03129 }
03130
03131 void KDesktopPropsPlugin::slotAdvanced()
03132 {
03133 KDialogBase dlg(w, "KPropertiesDesktopAdv", true,
03134 i18n("Advanced Options for %1").arg(properties->kurl().fileName()),
03135 KDialogBase::Ok|KDialogBase::Cancel, KDialogBase::Ok);
03136 KPropertiesDesktopAdvBase *w = new KPropertiesDesktopAdvBase(&dlg);
03137
03138 dlg.setMainWidget(w);
03139
03140
03141
03142 checkCommandChanged();
03143
03144
03145
03146 KConfigGroup confGroup( KGlobal::config(), QString::fromLatin1("General") );
03147 QString preferredTerminal = confGroup.readPathEntry("TerminalApplication",
03148 QString::fromLatin1("konsole"));
03149
03150 bool terminalCloseBool = false;
03151
03152 if (preferredTerminal == "konsole")
03153 {
03154 terminalCloseBool = (m_terminalOptionStr.contains( "--noclose" ) > 0);
03155 w->terminalCloseCheck->setChecked(terminalCloseBool);
03156 m_terminalOptionStr.replace( "--noclose", "");
03157 }
03158 else
03159 {
03160 w->terminalCloseCheck->hide();
03161 }
03162
03163 w->terminalCheck->setChecked(m_terminalBool);
03164 w->terminalEdit->setText(m_terminalOptionStr);
03165 w->terminalCloseCheck->setEnabled(m_terminalBool);
03166 w->terminalEdit->setEnabled(m_terminalBool);
03167 w->terminalEditLabel->setEnabled(m_terminalBool);
03168
03169 w->suidCheck->setChecked(m_suidBool);
03170 w->suidEdit->setText(m_suidUserStr);
03171 w->suidEdit->setEnabled(m_suidBool);
03172 w->suidEditLabel->setEnabled(m_suidBool);
03173
03174 w->startupInfoCheck->setChecked(m_startupBool);
03175 w->systrayCheck->setChecked(m_systrayBool);
03176
03177 if (m_dcopServiceType == "unique")
03178 w->dcopCombo->setCurrentItem(2);
03179 else if (m_dcopServiceType == "multi")
03180 w->dcopCombo->setCurrentItem(1);
03181 else if (m_dcopServiceType == "wait")
03182 w->dcopCombo->setCurrentItem(3);
03183 else
03184 w->dcopCombo->setCurrentItem(0);
03185
03186
03187 KCompletion *kcom = new KCompletion;
03188 kcom->setOrder(KCompletion::Sorted);
03189 struct passwd *pw;
03190 int i, maxEntries = 1000;
03191 setpwent();
03192 for (i=0; ((pw = getpwent()) != 0L) && (i < maxEntries); i++)
03193 kcom->addItem(QString::fromLatin1(pw->pw_name));
03194 endpwent();
03195 if (i < maxEntries)
03196 {
03197 w->suidEdit->setCompletionObject(kcom, true);
03198 w->suidEdit->setAutoDeleteCompletionObject( true );
03199 w->suidEdit->setCompletionMode(KGlobalSettings::CompletionAuto);
03200 }
03201 else
03202 {
03203 delete kcom;
03204 }
03205
03206 connect( w->terminalEdit, SIGNAL( textChanged( const QString & ) ),
03207 this, SIGNAL( changed() ) );
03208 connect( w->terminalCloseCheck, SIGNAL( toggled( bool ) ),
03209 this, SIGNAL( changed() ) );
03210 connect( w->terminalCheck, SIGNAL( toggled( bool ) ),
03211 this, SIGNAL( changed() ) );
03212 connect( w->suidCheck, SIGNAL( toggled( bool ) ),
03213 this, SIGNAL( changed() ) );
03214 connect( w->suidEdit, SIGNAL( textChanged( const QString & ) ),
03215 this, SIGNAL( changed() ) );
03216 connect( w->startupInfoCheck, SIGNAL( toggled( bool ) ),
03217 this, SIGNAL( changed() ) );
03218 connect( w->systrayCheck, SIGNAL( toggled( bool ) ),
03219 this, SIGNAL( changed() ) );
03220 connect( w->dcopCombo, SIGNAL( highlighted( int ) ),
03221 this, SIGNAL( changed() ) );
03222
03223 if ( dlg.exec() == QDialog::Accepted )
03224 {
03225 m_terminalOptionStr = w->terminalEdit->text().stripWhiteSpace();
03226 m_terminalBool = w->terminalCheck->isChecked();
03227 m_suidBool = w->suidCheck->isChecked();
03228 m_suidUserStr = w->suidEdit->text().stripWhiteSpace();
03229 m_startupBool = w->startupInfoCheck->isChecked();
03230 m_systrayBool = w->systrayCheck->isChecked();
03231
03232 if (w->terminalCloseCheck->isChecked())
03233 {
03234 m_terminalOptionStr.append(" --noclose");
03235 }
03236
03237 switch(w->dcopCombo->currentItem())
03238 {
03239 case 1: m_dcopServiceType = "multi"; break;
03240 case 2: m_dcopServiceType = "unique"; break;
03241 case 3: m_dcopServiceType = "wait"; break;
03242 default: m_dcopServiceType = "none"; break;
03243 }
03244 }
03245 }
03246
03247 bool KDesktopPropsPlugin::supports( KFileItemList _items )
03248 {
03249 if ( _items.count() != 1 )
03250 return false;
03251 KFileItem * item = _items.first();
03252
03253 if ( !KPropsDlgPlugin::isDesktopFile( item ) )
03254 return false;
03255
03256 KDesktopFile config( item->url().path(), true );
03257 return config.hasApplicationType() && kapp->authorize("run_desktop_files") && kapp->authorize("shell_access");
03258 }
03259
03260 void KPropertiesDialog::virtual_hook( int id, void* data )
03261 { KDialogBase::virtual_hook( id, data ); }
03262
03263 void KPropsDlgPlugin::virtual_hook( int, void* )
03264 { }
03265
03266
03267
03268
03269
03275 class KExecPropsPlugin::KExecPropsPluginPrivate
03276 {
03277 public:
03278 KExecPropsPluginPrivate()
03279 {
03280 }
03281 ~KExecPropsPluginPrivate()
03282 {
03283 }
03284
03285 QFrame *m_frame;
03286 QCheckBox *nocloseonexitCheck;
03287 };
03288
03289 KExecPropsPlugin::KExecPropsPlugin( KPropertiesDialog *_props )
03290 : KPropsDlgPlugin( _props )
03291 {
03292 d = new KExecPropsPluginPrivate;
03293 d->m_frame = properties->addPage(i18n("E&xecute"));
03294 QVBoxLayout * mainlayout = new QVBoxLayout( d->m_frame, 0,
03295 KDialog::spacingHint());
03296
03297
03298
03299 QLabel* l;
03300 l = new QLabel( i18n( "Comman&d:" ), d->m_frame );
03301 mainlayout->addWidget(l);
03302
03303 QHBoxLayout * hlayout;
03304 hlayout = new QHBoxLayout(KDialog::spacingHint());
03305 mainlayout->addLayout(hlayout);
03306
03307 execEdit = new KLineEdit( d->m_frame );
03308 QWhatsThis::add(execEdit,i18n(
03309 "Following the command, you can have several place holders which will be replaced "
03310 "with the actual values when the actual program is run:\n"
03311 "%f - a single file name\n"
03312 "%F - a list of files; use for applications that can open several local files at once\n"
03313 "%u - a single URL\n"
03314 "%U - a list of URLs\n"
03315 "%d - the folder of the file to open\n"
03316 "%D - a list of folders\n"
03317 "%i - the icon\n"
03318 "%m - the mini-icon\n"
03319 "%c - the caption"));
03320 hlayout->addWidget(execEdit, 1);
03321
03322 l->setBuddy( execEdit );
03323
03324 execBrowse = new QPushButton( d->m_frame );
03325 execBrowse->setText( i18n("&Browse...") );
03326 hlayout->addWidget(execBrowse);
03327
03328
03329 QGroupBox* tmpQGroupBox;
03330 tmpQGroupBox = new QGroupBox( i18n("Panel Embedding"), d->m_frame );
03331 tmpQGroupBox->setColumnLayout( 0, Qt::Horizontal );
03332
03333 mainlayout->addWidget(tmpQGroupBox);
03334
03335 QGridLayout *grid = new QGridLayout(tmpQGroupBox->layout(), 2, 2);
03336 grid->setSpacing( KDialog::spacingHint() );
03337 grid->setColStretch(1, 1);
03338
03339 l = new QLabel( i18n( "&Execute on click:" ), tmpQGroupBox );
03340 grid->addWidget(l, 0, 0);
03341
03342 swallowExecEdit = new KLineEdit( tmpQGroupBox );
03343 grid->addWidget(swallowExecEdit, 0, 1);
03344
03345 l->setBuddy( swallowExecEdit );
03346
03347 l = new QLabel( i18n( "&Window title:" ), tmpQGroupBox );
03348 grid->addWidget(l, 1, 0);
03349
03350 swallowTitleEdit = new KLineEdit( tmpQGroupBox );
03351 grid->addWidget(swallowTitleEdit, 1, 1);
03352
03353 l->setBuddy( swallowTitleEdit );
03354
03355
03356
03357 tmpQGroupBox = new QGroupBox( d->m_frame );
03358 tmpQGroupBox->setColumnLayout( 0, Qt::Horizontal );
03359
03360 mainlayout->addWidget(tmpQGroupBox);
03361
03362 grid = new QGridLayout(tmpQGroupBox->layout(), 3, 2);
03363 grid->setSpacing( KDialog::spacingHint() );
03364 grid->setColStretch(1, 1);
03365
03366 terminalCheck = new QCheckBox( tmpQGroupBox );
03367 terminalCheck->setText( i18n("&Run in terminal") );
03368 grid->addMultiCellWidget(terminalCheck, 0, 0, 0, 1);
03369
03370
03371
03372 KConfigGroup confGroup( KGlobal::config(), QString::fromLatin1("General") );
03373 QString preferredTerminal = confGroup.readPathEntry("TerminalApplication",
03374 QString::fromLatin1("konsole"));
03375
03376 int posOptions = 1;
03377 d->nocloseonexitCheck = 0L;
03378 if (preferredTerminal == "konsole")
03379 {
03380 posOptions = 2;
03381 d->nocloseonexitCheck = new QCheckBox( tmpQGroupBox );
03382 d->nocloseonexitCheck->setText( i18n("Do not &close when command exits") );
03383 grid->addMultiCellWidget(d->nocloseonexitCheck, 1, 1, 0, 1);
03384 }
03385
03386 terminalLabel = new QLabel( i18n( "&Terminal options:" ), tmpQGroupBox );
03387 grid->addWidget(terminalLabel, posOptions, 0);
03388
03389 terminalEdit = new KLineEdit( tmpQGroupBox );
03390 grid->addWidget(terminalEdit, posOptions, 1);
03391
03392 terminalLabel->setBuddy( terminalEdit );
03393
03394
03395
03396 tmpQGroupBox = new QGroupBox( d->m_frame );
03397 tmpQGroupBox->setColumnLayout( 0, Qt::Horizontal );
03398
03399 mainlayout->addWidget(tmpQGroupBox);
03400
03401 grid = new QGridLayout(tmpQGroupBox->layout(), 2, 2);
03402 grid->setSpacing(KDialog::spacingHint());
03403 grid->setColStretch(1, 1);
03404
03405 suidCheck = new QCheckBox(tmpQGroupBox);
03406 suidCheck->setText(i18n("Ru&n as a different user"));
03407 grid->addMultiCellWidget(suidCheck, 0, 0, 0, 1);
03408
03409 suidLabel = new QLabel(i18n( "&Username:" ), tmpQGroupBox);
03410 grid->addWidget(suidLabel, 1, 0);
03411
03412 suidEdit = new KLineEdit(tmpQGroupBox);
03413 grid->addWidget(suidEdit, 1, 1);
03414
03415 suidLabel->setBuddy( suidEdit );
03416
03417 mainlayout->addStretch(1);
03418
03419
03420 QString path = _props->kurl().path();
03421 QFile f( path );
03422 if ( !f.open( IO_ReadOnly ) )
03423 return;
03424 f.close();
03425
03426 KSimpleConfig config( path );
03427 config.setDollarExpansion( false );
03428 config.setDesktopGroup();
03429 execStr = config.readPathEntry( "Exec" );
03430 swallowExecStr = config.readPathEntry( "SwallowExec" );
03431 swallowTitleStr = config.readEntry( "SwallowTitle" );
03432 termBool = config.readBoolEntry( "Terminal" );
03433 termOptionsStr = config.readEntry( "TerminalOptions" );
03434 suidBool = config.readBoolEntry( "X-KDE-SubstituteUID" );
03435 suidUserStr = config.readEntry( "X-KDE-Username" );
03436
03437 if ( !swallowExecStr.isNull() )
03438 swallowExecEdit->setText( swallowExecStr );
03439 if ( !swallowTitleStr.isNull() )
03440 swallowTitleEdit->setText( swallowTitleStr );
03441
03442 if ( !execStr.isNull() )
03443 execEdit->setText( execStr );
03444
03445 if ( d->nocloseonexitCheck )
03446 {
03447 d->nocloseonexitCheck->setChecked( (termOptionsStr.contains( "--noclose" ) > 0) );
03448 termOptionsStr.replace( "--noclose", "");
03449 }
03450 if ( !termOptionsStr.isNull() )
03451 terminalEdit->setText( termOptionsStr );
03452
03453 terminalCheck->setChecked( termBool );
03454 enableCheckedEdit();
03455
03456 suidCheck->setChecked( suidBool );
03457 suidEdit->setText( suidUserStr );
03458 enableSuidEdit();
03459
03460
03461 KCompletion *kcom = new KCompletion;
03462 kcom->setOrder(KCompletion::Sorted);
03463 struct passwd *pw;
03464 int i, maxEntries = 1000;
03465 setpwent();
03466 for (i=0; ((pw = getpwent()) != 0L) && (i < maxEntries); i++)
03467 kcom->addItem(QString::fromLatin1(pw->pw_name));
03468 endpwent();
03469 if (i < maxEntries)
03470 {
03471 suidEdit->setCompletionObject(kcom, true);
03472 suidEdit->setAutoDeleteCompletionObject( true );
03473 suidEdit->setCompletionMode(KGlobalSettings::CompletionAuto);
03474 }
03475 else
03476 {
03477 delete kcom;
03478 }
03479
03480 connect( swallowExecEdit, SIGNAL( textChanged( const QString & ) ),
03481 this, SIGNAL( changed() ) );
03482 connect( swallowTitleEdit, SIGNAL( textChanged( const QString & ) ),
03483 this, SIGNAL( changed() ) );
03484 connect( execEdit, SIGNAL( textChanged( const QString & ) ),
03485 this, SIGNAL( changed() ) );
03486 connect( terminalEdit, SIGNAL( textChanged( const QString & ) ),
03487 this, SIGNAL( changed() ) );
03488 if (d->nocloseonexitCheck)
03489 connect( d->nocloseonexitCheck, SIGNAL( toggled( bool ) ),
03490 this, SIGNAL( changed() ) );
03491 connect( terminalCheck, SIGNAL( toggled( bool ) ),
03492 this, SIGNAL( changed() ) );
03493 connect( suidCheck, SIGNAL( toggled( bool ) ),
03494 this, SIGNAL( changed() ) );
03495 connect( suidEdit, SIGNAL( textChanged( const QString & ) ),
03496 this, SIGNAL( changed() ) );
03497
03498 connect( execBrowse, SIGNAL( clicked() ), this, SLOT( slotBrowseExec() ) );
03499 connect( terminalCheck, SIGNAL( clicked() ), this, SLOT( enableCheckedEdit() ) );
03500 connect( suidCheck, SIGNAL( clicked() ), this, SLOT( enableSuidEdit() ) );
03501
03502 }
03503
03504 KExecPropsPlugin::~KExecPropsPlugin()
03505 {
03506 delete d;
03507 }
03508
03509 void KExecPropsPlugin::enableCheckedEdit()
03510 {
03511 bool checked = terminalCheck->isChecked();
03512 terminalLabel->setEnabled( checked );
03513 if (d->nocloseonexitCheck)
03514 d->nocloseonexitCheck->setEnabled( checked );
03515 terminalEdit->setEnabled( checked );
03516 }
03517
03518 void KExecPropsPlugin::enableSuidEdit()
03519 {
03520 bool checked = suidCheck->isChecked();
03521 suidLabel->setEnabled( checked );
03522 suidEdit->setEnabled( checked );
03523 }
03524
03525 bool KExecPropsPlugin::supports( KFileItemList _items )
03526 {
03527 if ( _items.count() != 1 )
03528 return false;
03529 KFileItem * item = _items.first();
03530
03531 if ( !KPropsDlgPlugin::isDesktopFile( item ) )
03532 return false;
03533
03534 KDesktopFile config( item->url().path(), true );
03535 return config.hasApplicationType() && kapp->authorize("run_desktop_files") && kapp->authorize("shell_access");
03536 }
03537
03538 void KExecPropsPlugin::applyChanges()
03539 {
03540 kdDebug(250) << "KExecPropsPlugin::applyChanges" << endl;
03541 QString path = properties->kurl().path();
03542
03543 QFile f( path );
03544
03545 if ( !f.open( IO_ReadWrite ) ) {
03546 KMessageBox::sorry( 0, i18n("<qt>Could not save properties. You do not have "
03547 "sufficient access to write to <b>%1</b>.</qt>").arg(path));
03548 return;
03549 }
03550 f.close();
03551
03552 KSimpleConfig config( path );
03553 config.setDesktopGroup();
03554 config.writeEntry( "Type", QString::fromLatin1("Application"));
03555 config.writePathEntry( "Exec", execEdit->text() );
03556 config.writePathEntry( "SwallowExec", swallowExecEdit->text() );
03557 config.writeEntry( "SwallowTitle", swallowTitleEdit->text() );
03558 config.writeEntry( "Terminal", terminalCheck->isChecked() );
03559 QString temp = terminalEdit->text();
03560 if (d->nocloseonexitCheck )
03561 if ( d->nocloseonexitCheck->isChecked() )
03562 temp += QString::fromLatin1("--noclose ");
03563 temp = temp.stripWhiteSpace();
03564 config.writeEntry( "TerminalOptions", temp );
03565 config.writeEntry( "X-KDE-SubstituteUID", suidCheck->isChecked() );
03566 config.writeEntry( "X-KDE-Username", suidEdit->text() );
03567 }
03568
03569
03570 void KExecPropsPlugin::slotBrowseExec()
03571 {
03572 KURL f = KFileDialog::getOpenURL( QString::null,
03573 QString::null, d->m_frame );
03574 if ( f.isEmpty() )
03575 return;
03576
03577 if ( !f.isLocalFile()) {
03578 KMessageBox::sorry(d->m_frame, i18n("Only executables on local file systems are supported."));
03579 return;
03580 }
03581
03582 QString path = f.path();
03583 KRun::shellQuote( path );
03584 execEdit->setText( path );
03585 }
03586
03587 class KApplicationPropsPlugin::KApplicationPropsPluginPrivate
03588 {
03589 public:
03590 KApplicationPropsPluginPrivate()
03591 {
03592 m_kdesktopMode = QCString(qApp->name()) == "kdesktop";
03593 }
03594 ~KApplicationPropsPluginPrivate()
03595 {
03596 }
03597
03598 QFrame *m_frame;
03599 bool m_kdesktopMode;
03600 };
03601
03602 KApplicationPropsPlugin::KApplicationPropsPlugin( KPropertiesDialog *_props )
03603 : KPropsDlgPlugin( _props )
03604 {
03605 d = new KApplicationPropsPluginPrivate;
03606 d->m_frame = properties->addPage(i18n("&Application"));
03607 QVBoxLayout *toplayout = new QVBoxLayout( d->m_frame, 0, KDialog::spacingHint());
03608
03609 QIconSet iconSet;
03610 QPixmap pixMap;
03611
03612 addExtensionButton = new QPushButton( QString::null, d->m_frame );
03613 iconSet = SmallIconSet( "back" );
03614 addExtensionButton->setIconSet( iconSet );
03615 pixMap = iconSet.pixmap( QIconSet::Small, QIconSet::Normal );
03616 addExtensionButton->setFixedSize( pixMap.width()+8, pixMap.height()+8 );
03617 connect( addExtensionButton, SIGNAL( clicked() ),
03618 SLOT( slotAddExtension() ) );
03619
03620 delExtensionButton = new QPushButton( QString::null, d->m_frame );
03621 iconSet = SmallIconSet( "forward" );
03622 delExtensionButton->setIconSet( iconSet );
03623 delExtensionButton->setFixedSize( pixMap.width()+8, pixMap.height()+8 );
03624 connect( delExtensionButton, SIGNAL( clicked() ),
03625 SLOT( slotDelExtension() ) );
03626
03627 QLabel *l;
03628
03629 QGridLayout *grid = new QGridLayout(2, 2);
03630 grid->setColStretch(1, 1);
03631 toplayout->addLayout(grid);
03632
03633 if ( d->m_kdesktopMode )
03634 {
03635
03636 nameEdit = 0L;
03637 }
03638 else
03639 {
03640 l = new QLabel(i18n("Name:"), d->m_frame, "Label_4" );
03641 grid->addWidget(l, 0, 0);
03642
03643 nameEdit = new KLineEdit( d->m_frame, "LineEdit_3" );
03644 grid->addWidget(nameEdit, 0, 1);
03645 }
03646
03647 l = new QLabel(i18n("Description:"), d->m_frame, "Label_5" );
03648 grid->addWidget(l, 1, 0);
03649
03650 genNameEdit = new KLineEdit( d->m_frame, "LineEdit_4" );
03651 grid->addWidget(genNameEdit, 1, 1);
03652
03653 l = new QLabel(i18n("Comment:"), d->m_frame, "Label_3" );
03654 grid->addWidget(l, 2, 0);
03655
03656 commentEdit = new KLineEdit( d->m_frame, "LineEdit_2" );
03657 grid->addWidget(commentEdit, 2, 1);
03658
03659 l = new QLabel(i18n("File types:"), d->m_frame);
03660 toplayout->addWidget(l, 0, AlignLeft);
03661
03662 grid = new QGridLayout(4, 3);
03663 grid->setColStretch(0, 1);
03664 grid->setColStretch(2, 1);
03665 grid->setRowStretch( 0, 1 );
03666 grid->setRowStretch( 3, 1 );
03667 toplayout->addLayout(grid, 2);
03668
03669 extensionsList = new QListBox( d->m_frame );
03670 extensionsList->setSelectionMode( QListBox::Extended );
03671 grid->addMultiCellWidget(extensionsList, 0, 3, 0, 0);
03672
03673 grid->addWidget(addExtensionButton, 1, 1);
03674 grid->addWidget(delExtensionButton, 2, 1);
03675
03676 availableExtensionsList = new QListBox( d->m_frame );
03677 availableExtensionsList->setSelectionMode( QListBox::Extended );
03678 grid->addMultiCellWidget(availableExtensionsList, 0, 3, 2, 2);
03679
03680 QString path = properties->kurl().path() ;
03681 QFile f( path );
03682 if ( !f.open( IO_ReadOnly ) )
03683 return;
03684 f.close();
03685
03686 KSimpleConfig config( path );
03687 config.setDesktopGroup();
03688 QString commentStr = config.readEntry( "Comment" );
03689 QString genNameStr = config.readEntry( "GenericName" );
03690
03691 QStringList selectedTypes = config.readListEntry( "ServiceTypes" );
03692
03693 selectedTypes += config.readListEntry( "MimeType", ';' );
03694
03695 QString nameStr = config.readEntry( QString::fromLatin1("Name") );
03696 if ( nameStr.isEmpty() || d->m_kdesktopMode ) {
03697
03698
03699
03700 setDirty();
03701 }
03702
03703 commentEdit->setText( commentStr );
03704 genNameEdit->setText( genNameStr );
03705 if ( nameEdit )
03706 nameEdit->setText( nameStr );
03707
03708 selectedTypes.sort();
03709 QStringList::Iterator sit = selectedTypes.begin();
03710 for( ; sit != selectedTypes.end(); ++sit ) {
03711 if ( !((*sit).isEmpty()) )
03712 extensionsList->insertItem( *sit );
03713 }
03714
03715 KMimeType::List mimeTypes = KMimeType::allMimeTypes();
03716 QValueListIterator<KMimeType::Ptr> it2 = mimeTypes.begin();
03717 for ( ; it2 != mimeTypes.end(); ++it2 )
03718 addMimeType ( (*it2)->name() );
03719
03720 updateButton();
03721
03722 connect( extensionsList, SIGNAL( highlighted( int ) ),
03723 this, SLOT( updateButton() ) );
03724 connect( availableExtensionsList, SIGNAL( highlighted( int ) ),
03725 this, SLOT( updateButton() ) );
03726
03727 connect( addExtensionButton, SIGNAL( clicked() ),
03728 this, SIGNAL( changed() ) );
03729 connect( delExtensionButton, SIGNAL( clicked() ),
03730 this, SIGNAL( changed() ) );
03731 if ( nameEdit )
03732 connect( nameEdit, SIGNAL( textChanged( const QString & ) ),
03733 this, SIGNAL( changed() ) );
03734 connect( commentEdit, SIGNAL( textChanged( const QString & ) ),
03735 this, SIGNAL( changed() ) );
03736 connect( genNameEdit, SIGNAL( textChanged( const QString & ) ),
03737 this, SIGNAL( changed() ) );
03738 connect( availableExtensionsList, SIGNAL( selected( int ) ),
03739 this, SIGNAL( changed() ) );
03740 connect( extensionsList, SIGNAL( selected( int ) ),
03741 this, SIGNAL( changed() ) );
03742 }
03743
03744 KApplicationPropsPlugin::~KApplicationPropsPlugin()
03745 {
03746 delete d;
03747 }
03748
03749
03750
03751
03752
03753
03754 void KApplicationPropsPlugin::updateButton()
03755 {
03756 addExtensionButton->setEnabled(availableExtensionsList->currentItem()>-1);
03757 delExtensionButton->setEnabled(extensionsList->currentItem()>-1);
03758 }
03759
03760 void KApplicationPropsPlugin::addMimeType( const QString & name )
03761 {
03762
03763
03764 bool insert = true;
03765
03766 for ( uint i = 0; i < extensionsList->count(); i++ )
03767 if ( extensionsList->text( i ) == name )
03768 insert = false;
03769
03770 if ( insert )
03771 {
03772 availableExtensionsList->insertItem( name );
03773 availableExtensionsList->sort();
03774 }
03775 }
03776
03777 bool KApplicationPropsPlugin::supports( KFileItemList _items )
03778 {
03779
03780 return KExecPropsPlugin::supports( _items );
03781 }
03782
03783 void KApplicationPropsPlugin::applyChanges()
03784 {
03785 QString path = properties->kurl().path();
03786
03787 QFile f( path );
03788
03789 if ( !f.open( IO_ReadWrite ) ) {
03790 KMessageBox::sorry( 0, i18n("<qt>Could not save properties. You do not "
03791 "have sufficient access to write to <b>%1</b>.</qt>").arg(path));
03792 return;
03793 }
03794 f.close();
03795
03796 KSimpleConfig config( path );
03797 config.setDesktopGroup();
03798 config.writeEntry( "Type", QString::fromLatin1("Application"));
03799 config.writeEntry( "Comment", commentEdit->text() );
03800 config.writeEntry( "Comment", commentEdit->text(), true, false, true );
03801 config.writeEntry( "GenericName", genNameEdit->text() );
03802 config.writeEntry( "GenericName", genNameEdit->text(), true, false, true );
03803
03804 QStringList selectedTypes;
03805 for ( uint i = 0; i < extensionsList->count(); i++ )
03806 selectedTypes.append( extensionsList->text( i ) );
03807
03808 config.writeEntry( "MimeType", selectedTypes, ';' );
03809 config.writeEntry( "ServiceTypes", "" );
03810
03811
03812 QString nameStr = nameEdit ? nameEdit->text() : QString::null;
03813 if ( nameStr.isEmpty() )
03814 nameStr = nameFromFileName(properties->kurl().fileName());
03815
03816 config.writeEntry( "Name", nameStr );
03817 config.writeEntry( "Name", nameStr, true, false, true );
03818
03819 config.sync();
03820 }
03821
03822 void KApplicationPropsPlugin::slotAddExtension()
03823 {
03824 QListBoxItem *item = availableExtensionsList->firstItem();
03825 QListBoxItem *nextItem;
03826
03827 while ( item )
03828 {
03829 nextItem = item->next();
03830
03831 if ( item->isSelected() )
03832 {
03833 extensionsList->insertItem( item->text() );
03834 availableExtensionsList->removeItem( availableExtensionsList->index( item ) );
03835 }
03836
03837 item = nextItem;
03838 }
03839
03840 extensionsList->sort();
03841 updateButton();
03842 }
03843
03844 void KApplicationPropsPlugin::slotDelExtension()
03845 {
03846 QListBoxItem *item = extensionsList->firstItem();
03847 QListBoxItem *nextItem;
03848
03849 while ( item )
03850 {
03851 nextItem = item->next();
03852
03853 if ( item->isSelected() )
03854 {
03855 availableExtensionsList->insertItem( item->text() );
03856 extensionsList->removeItem( extensionsList->index( item ) );
03857 }
03858
03859 item = nextItem;
03860 }
03861
03862 availableExtensionsList->sort();
03863 updateButton();
03864 }
03865
03866
03867
03868 #include "kpropertiesdialog.moc"