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