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