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