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