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