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