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