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