• Skip to content
  • Skip to link menu
Trinity API Reference
  • Trinity API Reference
  • tdeio/tdefile
 

tdeio/tdefile

  • tdeio
  • tdefile
kpropertiesdialog.cpp
1 /* This file is part of the KDE project
2 
3  Copyright (C) 1998, 1999 Torben Weis <weis@kde.org>
4  Copyright (c) 1999, 2000 Preston Brown <pbrown@kde.org>
5  Copyright (c) 2000 Simon Hausmann <hausmann@kde.org>
6  Copyright (c) 2000 David Faure <faure@kde.org>
7  Copyright (c) 2003 Waldo Bastian <bastian@kde.org>
8 
9  This library is free software; you can redistribute it and/or
10  modify it under the terms of the GNU Library General Public
11  License as published by the Free Software Foundation; either
12  version 2 of the License, or (at your option) any later version.
13 
14  This library is distributed in the hope that it will be useful,
15  but WITHOUT ANY WARRANTY; without even the implied warranty of
16  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17  Library General Public License for more details.
18 
19  You should have received a copy of the GNU Library General Public License
20  along with this library; see the file COPYING.LIB. If not, write to
21  the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
22  Boston, MA 02110-1301, USA.
23 */
24 
25 /*
26  * kpropertiesdialog.cpp
27  * View/Edit Properties of files, locally or remotely
28  *
29  * some FilePermissionsPropsPlugin-changes by
30  * Henner Zeller <zeller@think.de>
31  * some layout management by
32  * Bertrand Leconte <B.Leconte@mail.dotcom.fr>
33  * the rest of the layout management, bug fixes, adaptation to libtdeio,
34  * template feature by
35  * David Faure <faure@kde.org>
36  * More layout, cleanups, and fixes by
37  * Preston Brown <pbrown@kde.org>
38  * Plugin capability, cleanups and port to KDialogBase by
39  * Simon Hausmann <hausmann@kde.org>
40  * KDesktopPropsPlugin by
41  * Waldo Bastian <bastian@kde.org>
42  */
43 
44 #include <config.h>
45 extern "C" {
46 #include <pwd.h>
47 #include <grp.h>
48 #include <time.h>
49 #include <sys/types.h>
50 }
51 #include <unistd.h>
52 #include <errno.h>
53 #include <assert.h>
54 #include <algorithm>
55 #include <functional>
56 
57 #include <tqfile.h>
58 #include <tqdir.h>
59 #include <tqlabel.h>
60 #include <tqpushbutton.h>
61 #include <tqcheckbox.h>
62 #include <tqstrlist.h>
63 #include <tqstringlist.h>
64 #include <tqtextstream.h>
65 #include <tqpainter.h>
66 #include <tqlayout.h>
67 #include <tqcombobox.h>
68 #include <tqgroupbox.h>
69 #include <tqwhatsthis.h>
70 #include <tqtooltip.h>
71 #include <tqstyle.h>
72 #include <tqprogressbar.h>
73 #include <tqvbox.h>
74 #include <tqvaluevector.h>
75 
76 #ifdef USE_POSIX_ACL
77 extern "C" {
78 #include <sys/param.h>
79 #ifdef HAVE_SYS_MOUNT_H
80 #include <sys/mount.h>
81 #endif
82 #ifdef HAVE_SYS_XATTR_H
83 #include <sys/xattr.h>
84 #endif
85 }
86 #endif
87 
88 #include <tdeapplication.h>
89 #include <kdialog.h>
90 #include <kdirsize.h>
91 #include <kdirwatch.h>
92 #include <kdirnotify_stub.h>
93 #include <kdiskfreesp.h>
94 #include <kdebug.h>
95 #include <kdesktopfile.h>
96 #include <kicondialog.h>
97 #include <kurl.h>
98 #include <kurlrequester.h>
99 #include <tdelocale.h>
100 #include <tdeglobal.h>
101 #include <tdeglobalsettings.h>
102 #include <kstandarddirs.h>
103 #include <tdeio/job.h>
104 #include <tdeio/chmodjob.h>
105 #include <tdeio/renamedlg.h>
106 #include <tdeio/netaccess.h>
107 #include <tdeio/kservicetypefactory.h>
108 #include <tdefiledialog.h>
109 #include <kmimetype.h>
110 #include <kmountpoint.h>
111 #include <kiconloader.h>
112 #include <tdemessagebox.h>
113 #include <kservice.h>
114 #include <kcompletion.h>
115 #include <klineedit.h>
116 #include <kseparator.h>
117 #include <ksqueezedtextlabel.h>
118 #include <klibloader.h>
119 #include <ktrader.h>
120 #include <tdeparts/componentfactory.h>
121 #include <kmetaprops.h>
122 #include <kpreviewprops.h>
123 #include <kprocess.h>
124 #include <krun.h>
125 #include <tdelistview.h>
126 #include <kacl.h>
127 #include "tdefilesharedlg.h"
128 
129 #include "kpropertiesdesktopbase.h"
130 #include "kpropertiesdesktopadvbase.h"
131 #include "kpropertiesmimetypebase.h"
132 #ifdef USE_POSIX_ACL
133 #include "kacleditwidget.h"
134 #endif
135 
136 #include "kpropertiesdialog.h"
137 
138 #ifdef Q_WS_WIN
139 # include <win32_utils.h>
140 #endif
141 
142 static TQString nameFromFileName(TQString nameStr)
143 {
144  if ( nameStr.endsWith(".desktop") )
145  nameStr.truncate( nameStr.length() - 8 );
146  if ( nameStr.endsWith(".kdelnk") )
147  nameStr.truncate( nameStr.length() - 7 );
148  // Make it human-readable (%2F => '/', ...)
149  nameStr = TDEIO::decodeFileName( nameStr );
150  return nameStr;
151 }
152 
153 mode_t KFilePermissionsPropsPlugin::fperm[3][4] = {
154  {S_IRUSR, S_IWUSR, S_IXUSR, S_ISUID},
155  {S_IRGRP, S_IWGRP, S_IXGRP, S_ISGID},
156  {S_IROTH, S_IWOTH, S_IXOTH, S_ISVTX}
157  };
158 
159 class KPropertiesDialog::KPropertiesDialogPrivate
160 {
161 public:
162  KPropertiesDialogPrivate()
163  {
164  m_aborted = false;
165  fileSharePage = 0;
166  }
167  ~KPropertiesDialogPrivate()
168  {
169  }
170  bool m_aborted:1;
171  TQWidget* fileSharePage;
172 };
173 
174 KPropertiesDialog::KPropertiesDialog (KFileItem* item,
175  TQWidget* parent, const char* name,
176  bool modal, bool autoShow)
177  : KDialogBase (KDialogBase::Tabbed, i18n( "Properties for %1" ).arg(TDEIO::decodeFileName(item->url().fileName())),
178  KDialogBase::Ok | KDialogBase::Cancel, KDialogBase::Ok,
179  parent, name, modal)
180 {
181  d = new KPropertiesDialogPrivate;
182  assert( item );
183  m_items.append( new KFileItem(*item) ); // deep copy
184 
185  m_singleUrl = item->url();
186  assert(!m_singleUrl.isEmpty());
187 
188  init (modal, autoShow);
189 }
190 
191 KPropertiesDialog::KPropertiesDialog (const TQString& title,
192  TQWidget* parent, const char* name, bool modal)
193  : KDialogBase (KDialogBase::Tabbed, i18n ("Properties for %1").arg(title),
194  KDialogBase::Ok | KDialogBase::Cancel, KDialogBase::Ok,
195  parent, name, modal)
196 {
197  d = new KPropertiesDialogPrivate;
198 
199  init (modal, false);
200 }
201 
202 KPropertiesDialog::KPropertiesDialog (KFileItemList _items,
203  TQWidget* parent, const char* name,
204  bool modal, bool autoShow)
205  : KDialogBase (KDialogBase::Tabbed,
206  // TODO: replace <never used> with "Properties for 1 item". It's very confusing how it has to be translated otherwise
207  // (empty translation before the "\n" is not allowed by msgfmt...)
208  _items.count()>1 ? i18n( "<never used>","Properties for %n Selected Items",_items.count()) :
209  i18n( "Properties for %1" ).arg(TDEIO::decodeFileName(_items.first()->url().fileName())),
210  KDialogBase::Ok | KDialogBase::Cancel, KDialogBase::Ok,
211  parent, name, modal)
212 {
213  d = new KPropertiesDialogPrivate;
214 
215  assert( !_items.isEmpty() );
216  m_singleUrl = _items.first()->url();
217  assert(!m_singleUrl.isEmpty());
218 
219  KFileItemListIterator it ( _items );
220  // Deep copy
221  for ( ; it.current(); ++it )
222  m_items.append( new KFileItem( **it ) );
223 
224  init (modal, autoShow);
225 }
226 
227 #ifndef KDE_NO_COMPAT
228 KPropertiesDialog::KPropertiesDialog (const KURL& _url, mode_t /* _mode is now unused */,
229  TQWidget* parent, const char* name,
230  bool modal, bool autoShow)
231  : KDialogBase (KDialogBase::Tabbed,
232  i18n( "Properties for %1" ).arg(TDEIO::decodeFileName(_url.fileName())),
233  KDialogBase::Ok | KDialogBase::Cancel, KDialogBase::Ok,
234  parent, name, modal),
235  m_singleUrl( _url )
236 {
237  d = new KPropertiesDialogPrivate;
238 
239  TDEIO::UDSEntry entry;
240 
241  TDEIO::NetAccess::stat(_url, entry, parent);
242 
243  m_items.append( new KFileItem( entry, _url ) );
244  init (modal, autoShow);
245 }
246 #endif
247 
248 KPropertiesDialog::KPropertiesDialog (const KURL& _url,
249  TQWidget* parent, const char* name,
250  bool modal, bool autoShow)
251  : KDialogBase (KDialogBase::Tabbed,
252  i18n( "Properties for %1" ).arg(TDEIO::decodeFileName(_url.fileName())),
253  KDialogBase::Ok | KDialogBase::Cancel, KDialogBase::Ok,
254  parent, name, modal),
255  m_singleUrl( _url )
256 {
257  d = new KPropertiesDialogPrivate;
258 
259  TDEIO::UDSEntry entry;
260 
261  TDEIO::NetAccess::stat(_url, entry, parent);
262 
263  m_items.append( new KFileItem( entry, _url ) );
264  init (modal, autoShow);
265 }
266 
267 KPropertiesDialog::KPropertiesDialog (const KURL& _tempUrl, const KURL& _currentDir,
268  const TQString& _defaultName,
269  TQWidget* parent, const char* name,
270  bool modal, bool autoShow)
271  : KDialogBase (KDialogBase::Tabbed,
272  i18n( "Properties for %1" ).arg(TDEIO::decodeFileName(_tempUrl.fileName())),
273  KDialogBase::Ok | KDialogBase::Cancel, KDialogBase::Ok,
274  parent, name, modal),
275 
276  m_singleUrl( _tempUrl ),
277  m_defaultName( _defaultName ),
278  m_currentDir( _currentDir )
279 {
280  d = new KPropertiesDialogPrivate;
281 
282  assert(!m_singleUrl.isEmpty());
283 
284  // Create the KFileItem for the _template_ file, in order to read from it.
285  m_items.append( new KFileItem( KFileItem::Unknown, KFileItem::Unknown, m_singleUrl ) );
286  init (modal, autoShow);
287 }
288 
289 bool KPropertiesDialog::showDialog(KFileItem* item, TQWidget* parent,
290  const char* name, bool modal)
291 {
292 #ifdef Q_WS_WIN
293  TQString localPath = item->localPath();
294  if (!localPath.isEmpty())
295  return showWin32FilePropertyDialog(localPath);
296 #endif
297  new KPropertiesDialog(item, parent, name, modal);
298  return true;
299 }
300 
301 bool KPropertiesDialog::showDialog(const KURL& _url, TQWidget* parent,
302  const char* name, bool modal)
303 {
304 #ifdef Q_WS_WIN
305  if (_url.isLocalFile())
306  return showWin32FilePropertyDialog( _url.path() );
307 #endif
308  new KPropertiesDialog(_url, parent, name, modal);
309  return true;
310 }
311 
312 bool KPropertiesDialog::showDialog(const KFileItemList& _items, TQWidget* parent,
313  const char* name, bool modal)
314 {
315  if (_items.count()==1)
316  return KPropertiesDialog::showDialog(_items.getFirst(), parent, name, modal);
317  new KPropertiesDialog(_items, parent, name, modal);
318  return true;
319 }
320 
321 void KPropertiesDialog::init (bool modal, bool autoShow)
322 {
323  m_pageList.setAutoDelete( true );
324  m_items.setAutoDelete( true );
325 
326  insertPages();
327 
328  if (autoShow)
329  {
330  if (!modal)
331  show();
332  else
333  exec();
334  }
335 }
336 
337 void KPropertiesDialog::showFileSharingPage()
338 {
339  if (d->fileSharePage) {
340  showPage( pageIndex( d->fileSharePage));
341  }
342 }
343 
344 void KPropertiesDialog::setFileSharingPage(TQWidget* page) {
345  d->fileSharePage = page;
346 }
347 
348 
349 void KPropertiesDialog::setFileNameReadOnly( bool ro )
350 {
351  KPropsDlgPlugin *it;
352 
353  for ( it=m_pageList.first(); it != 0L; it=m_pageList.next() )
354  {
355  KFilePropsPlugin* plugin = dynamic_cast<KFilePropsPlugin*>(it);
356  if ( plugin ) {
357  plugin->setFileNameReadOnly( ro );
358  break;
359  }
360  }
361 }
362 
363 void KPropertiesDialog::slotStatResult( TDEIO::Job * )
364 {
365 }
366 
367 KPropertiesDialog::~KPropertiesDialog()
368 {
369  m_pageList.clear();
370  delete d;
371 }
372 
373 void KPropertiesDialog::insertPlugin (KPropsDlgPlugin* plugin)
374 {
375  connect (plugin, TQT_SIGNAL (changed ()),
376  plugin, TQT_SLOT (setDirty ()));
377 
378  m_pageList.append (plugin);
379 }
380 
381 bool KPropertiesDialog::canDisplay( KFileItemList _items )
382 {
383  // TODO: cache the result of those calls. Currently we parse .desktop files far too many times
384  return KFilePropsPlugin::supports( _items ) ||
385  KFilePermissionsPropsPlugin::supports( _items ) ||
386  KDesktopPropsPlugin::supports( _items ) ||
387  KBindingPropsPlugin::supports( _items ) ||
388  KURLPropsPlugin::supports( _items ) ||
389  KDevicePropsPlugin::supports( _items ) ||
390  KFileMetaPropsPlugin::supports( _items ) ||
391  KPreviewPropsPlugin::supports( _items );
392 }
393 
394 void KPropertiesDialog::slotOk()
395 {
396  KPropsDlgPlugin *page;
397  d->m_aborted = false;
398 
399  KFilePropsPlugin * filePropsPlugin = 0L;
400  if ( m_pageList.first()->isA("KFilePropsPlugin") )
401  filePropsPlugin = static_cast<KFilePropsPlugin *>(m_pageList.first());
402 
403  // If any page is dirty, then set the main one (KFilePropsPlugin) as
404  // dirty too. This is what makes it possible to save changes to a global
405  // desktop file into a local one. In other cases, it doesn't hurt.
406  for ( page = m_pageList.first(); page != 0L; page = m_pageList.next() )
407  if ( page->isDirty() && filePropsPlugin )
408  {
409  filePropsPlugin->setDirty();
410  break;
411  }
412 
413  // Apply the changes in the _normal_ order of the tabs now
414  // This is because in case of renaming a file, KFilePropsPlugin will call
415  // KPropertiesDialog::rename, so other tab will be ok with whatever order
416  // BUT for file copied from templates, we need to do the renaming first !
417  for ( page = m_pageList.first(); page != 0L && !d->m_aborted; page = m_pageList.next() )
418  if ( page->isDirty() )
419  {
420  kdDebug( 250 ) << "applying changes for " << page->className() << endl;
421  page->applyChanges();
422  // applyChanges may change d->m_aborted.
423  }
424  else
425  kdDebug( 250 ) << "skipping page " << page->className() << endl;
426 
427  if ( !d->m_aborted && filePropsPlugin )
428  filePropsPlugin->postApplyChanges();
429 
430  if ( !d->m_aborted )
431  {
432  emit applied();
433  emit propertiesClosed();
434  deleteLater();
435  accept();
436  } // else, keep dialog open for user to fix the problem.
437 }
438 
439 void KPropertiesDialog::slotCancel()
440 {
441  emit canceled();
442  emit propertiesClosed();
443 
444  deleteLater();
445  done( Rejected );
446 }
447 
448 void KPropertiesDialog::insertPages()
449 {
450  if (m_items.isEmpty())
451  return;
452 
453  if ( KFilePropsPlugin::supports( m_items ) )
454  {
455  KPropsDlgPlugin *p = new KFilePropsPlugin( this );
456  insertPlugin (p);
457  }
458 
459  if ( KFilePermissionsPropsPlugin::supports( m_items ) )
460  {
461  KPropsDlgPlugin *p = new KFilePermissionsPropsPlugin( this );
462  insertPlugin (p);
463  }
464 
465  if ( KDesktopPropsPlugin::supports( m_items ) )
466  {
467  KPropsDlgPlugin *p = new KDesktopPropsPlugin( this );
468  insertPlugin (p);
469  }
470 
471  if ( KBindingPropsPlugin::supports( m_items ) )
472  {
473  KPropsDlgPlugin *p = new KBindingPropsPlugin( this );
474  insertPlugin (p);
475  }
476 
477  if ( KURLPropsPlugin::supports( m_items ) )
478  {
479  KPropsDlgPlugin *p = new KURLPropsPlugin( this );
480  insertPlugin (p);
481  }
482 
483  if ( KDevicePropsPlugin::supports( m_items ) )
484  {
485  KPropsDlgPlugin *p = new KDevicePropsPlugin( this );
486  insertPlugin (p);
487  }
488 
489  if ( KFileMetaPropsPlugin::supports( m_items ) )
490  {
491  KPropsDlgPlugin *p = new KFileMetaPropsPlugin( this );
492  insertPlugin (p);
493  }
494 
495  if ( KPreviewPropsPlugin::supports( m_items ) )
496  {
497  KPropsDlgPlugin *p = new KPreviewPropsPlugin( this );
498  insertPlugin (p);
499  }
500 
501  if ( kapp->authorizeTDEAction("sharefile") &&
502  KFileSharePropsPlugin::supports( m_items ) )
503  {
504  KPropsDlgPlugin *p = new KFileSharePropsPlugin( this );
505  insertPlugin (p);
506  }
507 
508  //plugins
509 
510  if ( m_items.count() != 1 )
511  return;
512 
513  KFileItem *item = m_items.first();
514  TQString mimetype = item->mimetype();
515 
516  if ( mimetype.isEmpty() )
517  return;
518 
519  TQString query = TQString::fromLatin1(
520  "('KPropsDlg/Plugin' in ServiceTypes) and "
521  "((not exist [X-TDE-Protocol]) or "
522  " ([X-TDE-Protocol] == '%1' ) )" ).arg(item->url().protocol());
523 
524  kdDebug( 250 ) << "trader query: " << query << endl;
525  TDETrader::OfferList offers = TDETrader::self()->query( mimetype, query );
526  TDETrader::OfferList::ConstIterator it = offers.begin();
527  TDETrader::OfferList::ConstIterator end = offers.end();
528  for (; it != end; ++it )
529  {
530  KPropsDlgPlugin *plugin = KParts::ComponentFactory
531  ::createInstanceFromLibrary<KPropsDlgPlugin>( (*it)->library().local8Bit().data(),
532  TQT_TQOBJECT(this),
533  (*it)->name().latin1() );
534  if ( !plugin )
535  continue;
536 
537  insertPlugin( plugin );
538  }
539 }
540 
541 void KPropertiesDialog::updateUrl( const KURL& _newUrl )
542 {
543  Q_ASSERT( m_items.count() == 1 );
544  kdDebug(250) << "KPropertiesDialog::updateUrl (pre)" << _newUrl.url() << endl;
545  KURL newUrl = _newUrl;
546  emit saveAs(m_singleUrl, newUrl);
547  kdDebug(250) << "KPropertiesDialog::updateUrl (post)" << newUrl.url() << endl;
548 
549  m_singleUrl = newUrl;
550  m_items.first()->setURL( newUrl );
551  assert(!m_singleUrl.isEmpty());
552  // If we have an Desktop page, set it dirty, so that a full file is saved locally
553  // Same for a URL page (because of the Name= hack)
554  for ( TQPtrListIterator<KPropsDlgPlugin> it(m_pageList); it.current(); ++it )
555  if ( it.current()->isA("KExecPropsPlugin") || // KDE4 remove me
556  it.current()->isA("KURLPropsPlugin") ||
557  it.current()->isA("KDesktopPropsPlugin"))
558  {
559  //kdDebug(250) << "Setting page dirty" << endl;
560  it.current()->setDirty();
561  break;
562  }
563 }
564 
565 void KPropertiesDialog::rename( const TQString& _name )
566 {
567  Q_ASSERT( m_items.count() == 1 );
568  kdDebug(250) << "KPropertiesDialog::rename " << _name << endl;
569  KURL newUrl;
570  // if we're creating from a template : use currentdir
571  if ( !m_currentDir.isEmpty() )
572  {
573  newUrl = m_currentDir;
574  newUrl.addPath( _name );
575  }
576  else
577  {
578  TQString tmpurl = m_singleUrl.url();
579  if ( tmpurl.at(tmpurl.length() - 1) == '/')
580  // It's a directory, so strip the trailing slash first
581  tmpurl.truncate( tmpurl.length() - 1);
582  newUrl = tmpurl;
583  newUrl.setFileName( _name );
584  }
585  updateUrl( newUrl );
586 }
587 
588 void KPropertiesDialog::abortApplying()
589 {
590  d->m_aborted = true;
591 }
592 
593 class KPropsDlgPlugin::KPropsDlgPluginPrivate
594 {
595 public:
596  KPropsDlgPluginPrivate()
597  {
598  }
599  ~KPropsDlgPluginPrivate()
600  {
601  }
602 
603  bool m_bDirty;
604 };
605 
606 KPropsDlgPlugin::KPropsDlgPlugin( KPropertiesDialog *_props )
607 : TQObject( _props, 0L )
608 {
609  d = new KPropsDlgPluginPrivate;
610  properties = _props;
611  fontHeight = 2*properties->fontMetrics().height();
612  d->m_bDirty = false;
613 }
614 
615 KPropsDlgPlugin::~KPropsDlgPlugin()
616 {
617  delete d;
618 }
619 
620 bool KPropsDlgPlugin::isDesktopFile( KFileItem * _item )
621 {
622  // only local files
623  bool isLocal;
624  KURL url = _item->mostLocalURL( isLocal );
625  if ( !isLocal )
626  return false;
627 
628  // only regular files
629  if ( !S_ISREG( _item->mode() ) )
630  return false;
631 
632  TQString t( url.path() );
633 
634  // only if readable
635  FILE *f = fopen( TQFile::encodeName(t), "r" );
636  if ( f == 0L )
637  return false;
638  fclose(f);
639 
640  // return true if desktop file
641  return ( (_item->mimetype() == "application/x-desktop")
642  || (_item->mimetype() == "media/builtin-mydocuments")
643  || (_item->mimetype() == "media/builtin-mycomputer")
644  || (_item->mimetype() == "media/builtin-mynetworkplaces")
645  || (_item->mimetype() == "media/builtin-printers")
646  || (_item->mimetype() == "media/builtin-trash")
647  || (_item->mimetype() == "media/builtin-webbrowser") );
648 }
649 
650 void KPropsDlgPlugin::setDirty( bool b )
651 {
652  d->m_bDirty = b;
653 }
654 
655 void KPropsDlgPlugin::setDirty()
656 {
657  d->m_bDirty = true;
658 }
659 
660 bool KPropsDlgPlugin::isDirty() const
661 {
662  return d->m_bDirty;
663 }
664 
665 void KPropsDlgPlugin::applyChanges()
666 {
667  kdWarning(250) << "applyChanges() not implemented in page !" << endl;
668 }
669 
671 
672 class KFilePropsPlugin::KFilePropsPluginPrivate
673 {
674 public:
675  KFilePropsPluginPrivate()
676  {
677  dirSizeJob = 0L;
678  dirSizeUpdateTimer = 0L;
679  m_lined = 0;
680  m_freeSpaceLabel = 0;
681  }
682  ~KFilePropsPluginPrivate()
683  {
684  if ( dirSizeJob )
685  dirSizeJob->kill();
686  }
687 
688  KDirSize * dirSizeJob;
689  TQTimer *dirSizeUpdateTimer;
690  TQFrame *m_frame;
691  bool bMultiple;
692  bool bIconChanged;
693  bool bKDesktopMode;
694  bool bDesktopFile;
695  TQLabel *m_freeSpaceLabel;
696  TQString mimeType;
697  TQString oldFileName;
698  KLineEdit* m_lined;
699 };
700 
701 KFilePropsPlugin::KFilePropsPlugin( KPropertiesDialog *_props )
702  : KPropsDlgPlugin( _props )
703 {
704  d = new KFilePropsPluginPrivate;
705  d->bMultiple = (properties->items().count() > 1);
706  d->bIconChanged = false;
707  d->bKDesktopMode = (TQCString(tqApp->name()) == "kdesktop"); // nasty heh?
708  d->bDesktopFile = KDesktopPropsPlugin::supports(properties->items());
709  kdDebug(250) << "KFilePropsPlugin::KFilePropsPlugin bMultiple=" << d->bMultiple << endl;
710 
711  // We set this data from the first item, and we'll
712  // check that the other items match against it, resetting when not.
713  bool isLocal;
714  KFileItem * item = properties->item();
715  KURL url = item->mostLocalURL( isLocal );
716  bool isReallyLocal = item->url().isLocalFile();
717  bool bDesktopFile = isDesktopFile(item);
718  kdDebug() << "url=" << url << " bDesktopFile=" << bDesktopFile << " isLocal=" << isLocal << " isReallyLocal=" << isReallyLocal << endl;
719  mode_t mode = item->mode();
720  bool hasDirs = item->isDir() && !item->isLink();
721  bool hasRoot = url.path() == TQString::fromLatin1("/");
722  TQString iconStr = KMimeType::iconForURL(url, mode);
723  TQString directory = properties->kurl().directory();
724  TQString protocol = properties->kurl().protocol();
725  TQString mimeComment = item->mimeComment();
726  d->mimeType = item->mimetype();
727  bool hasTotalSize;
728  TDEIO::filesize_t totalSize = item->size(hasTotalSize);
729  TQString magicMimeComment;
730  if ( isLocal ) {
731  KMimeType::Ptr magicMimeType = KMimeType::findByFileContent( url.path() );
732  if ( magicMimeType->name() != KMimeType::defaultMimeType() ) {
733  magicMimeComment = magicMimeType->comment();
734  }
735  }
736 
737  // Those things only apply to 'single file' mode
738  TQString filename = TQString::null;
739  bool isTrash = false;
740  bool isDevice = false;
741  bool isMediaNode = false;
742  m_bFromTemplate = false;
743 
744  // And those only to 'multiple' mode
745  uint iDirCount = hasDirs ? 1 : 0;
746  uint iFileCount = 1-iDirCount;
747 
748  d->m_frame = properties->addPage (i18n("&General"));
749 
750  TQVBoxLayout *vbl = new TQVBoxLayout( d->m_frame, 0,
751  KDialog::spacingHint(), "vbl");
752  TQGridLayout *grid = new TQGridLayout(0, 3); // unknown rows
753  grid->setColStretch(0, 0);
754  grid->setColStretch(1, 0);
755  grid->setColStretch(2, 1);
756  grid->addColSpacing(1, KDialog::spacingHint());
757  vbl->addLayout(TQT_TQLAYOUT(grid));
758  int curRow = 0;
759 
760  if ( !d->bMultiple )
761  {
762  TQString path;
763  if ( !m_bFromTemplate ) {
764  isTrash = ( properties->kurl().protocol().find( "trash", 0, false)==0 );
765  if ( properties->kurl().protocol().find("device", 0, false)==0) {
766  isDevice = true;
767  }
768  if (d->mimeType.startsWith("media/")) {
769  isMediaNode = true;
770  }
771  // Extract the full name, but without file: for local files
772  if ( isReallyLocal ) {
773  path = properties->kurl().path();
774  }
775  else {
776  path = properties->kurl().prettyURL();
777  }
778  } else {
779  path = properties->currentDir().path(1) + properties->defaultName();
780  directory = properties->currentDir().prettyURL();
781  }
782 
783  if (KExecPropsPlugin::supports(properties->items()) || // KDE4 remove me
784  d->bDesktopFile ||
785  KBindingPropsPlugin::supports(properties->items())) {
786  determineRelativePath( path );
787  }
788 
789  // Extract the file name only
790  filename = properties->defaultName();
791  if ( filename.isEmpty() ) { // no template
792  filename = item->name(); // this gives support for UDS_NAME, e.g. for tdeio_trash or tdeio_system
793  } else {
794  m_bFromTemplate = true;
795  setDirty(); // to enforce that the copy happens
796  }
797  d->oldFileName = filename;
798 
799  // Make it human-readable
800  filename = nameFromFileName( filename );
801 
802  if ( d->bKDesktopMode && d->bDesktopFile ) {
803  KDesktopFile config( url.path(), true /* readonly */ );
804  if ( config.hasKey( "Name" ) ) {
805  filename = config.readName();
806  }
807  }
808 
809  oldName = filename;
810  }
811  else
812  {
813  // Multiple items: see what they have in common
814  KFileItemList items = properties->items();
815  KFileItemListIterator it( items );
816  for ( ++it /*no need to check the first one again*/ ; it.current(); ++it )
817  {
818  KURL url = (*it)->url();
819  kdDebug(250) << "KFilePropsPlugin::KFilePropsPlugin " << url.prettyURL() << endl;
820  // The list of things we check here should match the variables defined
821  // at the beginning of this method.
822  if ( url.isLocalFile() != isLocal )
823  isLocal = false; // not all local
824  if ( bDesktopFile && isDesktopFile(*it) != bDesktopFile )
825  bDesktopFile = false; // not all desktop files
826  if ( (*it)->mode() != mode )
827  mode = (mode_t)0;
828  if ( KMimeType::iconForURL(url, mode) != iconStr )
829  iconStr = "application-vnd.tde.tdemultiple";
830  if ( url.directory() != directory )
831  directory = TQString::null;
832  if ( url.protocol() != protocol )
833  protocol = TQString::null;
834  if ( !mimeComment.isNull() && (*it)->mimeComment() != mimeComment )
835  mimeComment = TQString::null;
836  if ( isLocal && !magicMimeComment.isNull() ) {
837  KMimeType::Ptr magicMimeType = KMimeType::findByFileContent( url.path() );
838  if ( magicMimeType->comment() != magicMimeComment )
839  magicMimeComment = TQString::null;
840  }
841 
842  if ( url.path() == TQString::fromLatin1("/") )
843  hasRoot = true;
844  if ( (*it)->isDir() && !(*it)->isLink() )
845  {
846  iDirCount++;
847  hasDirs = true;
848  }
849  else
850  {
851  iFileCount++;
852  bool hasSize;
853  totalSize += (*it)->size(hasSize);
854  hasTotalSize = hasTotalSize || hasSize;
855  }
856  }
857  }
858 
859  if (!isReallyLocal && !protocol.isEmpty())
860  {
861  directory += ' ';
862  directory += '(';
863  directory += protocol;
864  directory += ')';
865  }
866 
867  if ( !isDevice && !isMediaNode && !isTrash && (bDesktopFile || S_ISDIR(mode)) && !d->bMultiple /*not implemented for multiple*/ )
868  {
869  TDEIconButton *iconButton = new TDEIconButton( d->m_frame );
870  int bsize = 66 + 2 * iconButton->style().pixelMetric(TQStyle::PM_ButtonMargin);
871  iconButton->setFixedSize(bsize, bsize);
872  iconButton->setIconSize(48);
873  iconButton->setStrictIconSize(false);
874  // This works for everything except Device icons on unmounted devices
875  // So we have to really open .desktop files
876  TQString iconStr = KMimeType::findByURL( url, mode )->icon( url, isLocal );
877  if ( bDesktopFile && isLocal ) {
878  KDesktopFile config( url.path(), true );
879  config.setDesktopGroup();
880  iconStr = config.readEntry( "Icon" );
881  if ( config.hasDeviceType() ) {
882  iconButton->setIconType( TDEIcon::Desktop, TDEIcon::Device );
883  }
884  else {
885  iconButton->setIconType( TDEIcon::Desktop, TDEIcon::Application );
886  }
887  }
888  else {
889  iconButton->setIconType( TDEIcon::Desktop, TDEIcon::Place );
890  }
891  iconButton->setIcon(iconStr);
892  iconArea = iconButton;
893  connect( iconButton, TQT_SIGNAL( iconChanged(TQString) ),
894  this, TQT_SLOT( slotIconChanged() ) );
895  } else {
896  TQLabel *iconLabel = new TQLabel( d->m_frame );
897  int bsize = 66 + 2 * iconLabel->style().pixelMetric(TQStyle::PM_ButtonMargin);
898  iconLabel->setFixedSize(bsize, bsize);
899  if (isMediaNode) {
900  // Display the correct device icon
901  iconLabel->setPixmap( TDEGlobal::iconLoader()->loadIcon( item->iconName(), TDEIcon::Desktop, 48) );
902  }
903  else {
904  // Display the generic folder icon
905  iconLabel->setPixmap( TDEGlobal::iconLoader()->loadIcon( iconStr, TDEIcon::Desktop, 48) );
906  }
907  iconArea = iconLabel;
908  }
909  grid->addWidget(iconArea, curRow, 0, Qt::AlignLeft);
910 
911  if (d->bMultiple || isTrash || isDevice || isMediaNode || hasRoot)
912  {
913  TQLabel *lab = new TQLabel(d->m_frame );
914  if ( d->bMultiple )
915  lab->setText( TDEIO::itemsSummaryString( iFileCount + iDirCount, iFileCount, iDirCount, 0, false ) );
916  else
917  lab->setText( filename );
918  nameArea = lab;
919  } else
920  {
921  d->m_lined = new KLineEdit( d->m_frame );
922  d->m_lined->setText(filename);
923  nameArea = d->m_lined;
924  d->m_lined->setFocus();
925 
926  // Enhanced rename: Don't highlight the file extension.
927  TQString pattern;
928  KServiceTypeFactory::self()->findFromPattern( filename, &pattern );
929  if (!pattern.isEmpty() && pattern.at(0)=='*' && pattern.find('*',1)==-1)
930  d->m_lined->setSelection(0, filename.length()-pattern.stripWhiteSpace().length()+1);
931  else
932  {
933  int lastDot = filename.findRev('.');
934  if (lastDot > 0)
935  d->m_lined->setSelection(0, lastDot);
936  }
937 
938  connect( d->m_lined, TQT_SIGNAL( textChanged( const TQString & ) ),
939  this, TQT_SLOT( nameFileChanged(const TQString & ) ) );
940  }
941 
942  grid->addWidget(nameArea, curRow++, 2);
943 
944  KSeparator* sep = new KSeparator( KSeparator::HLine, d->m_frame);
945  grid->addMultiCellWidget(sep, curRow, curRow, 0, 2);
946  ++curRow;
947 
948  TQLabel *l;
949  if ( !mimeComment.isEmpty() && !isDevice && !isMediaNode && !isTrash)
950  {
951  l = new TQLabel(i18n("Type:"), d->m_frame );
952 
953  grid->addWidget(l, curRow, 0);
954 
955  TQHBox *box = new TQHBox(d->m_frame);
956  box->setSpacing(20);
957  l = new TQLabel(mimeComment, box );
958 
959 #ifdef Q_WS_X11
960  //TODO: wrap for win32 or mac?
961  TQPushButton *button = new TQPushButton(box);
962 
963  TQIconSet iconSet = SmallIconSet(TQString::fromLatin1("configure"));
964  TQPixmap pixMap = iconSet.pixmap( TQIconSet::Small, TQIconSet::Normal );
965  button->setIconSet( iconSet );
966  button->setFixedSize( pixMap.width()+8, pixMap.height()+8 );
967  if ( d->mimeType == KMimeType::defaultMimeType() )
968  TQToolTip::add(button, i18n("Create new file type"));
969  else
970  TQToolTip::add(button, i18n("Edit file type"));
971 
972  connect( button, TQT_SIGNAL( clicked() ), TQT_SLOT( slotEditFileType() ));
973 
974  if (!kapp->authorizeTDEAction("editfiletype"))
975  button->hide();
976 #endif
977 
978  grid->addWidget(box, curRow++, 2);
979  }
980 
981  if ( !magicMimeComment.isEmpty() && magicMimeComment != mimeComment )
982  {
983  l = new TQLabel(i18n("Contents:"), d->m_frame );
984  grid->addWidget(l, curRow, 0);
985 
986  l = new TQLabel(magicMimeComment, d->m_frame );
987  grid->addWidget(l, curRow++, 2);
988  }
989 
990  if ( !directory.isEmpty() )
991  {
992  l = new TQLabel( i18n("Location:"), d->m_frame );
993  grid->addWidget(l, curRow, 0);
994 
995  l = new KSqueezedTextLabel( d->m_frame );
996  l->setText( directory );
997  grid->addWidget(l, curRow++, 2);
998  }
999 
1000  if( hasDirs || hasTotalSize ) {
1001  l = new TQLabel(i18n("Size:"), d->m_frame );
1002  grid->addWidget(l, curRow, 0);
1003 
1004  m_sizeLabel = new TQLabel( d->m_frame );
1005  grid->addWidget( m_sizeLabel, curRow++, 2 );
1006  } else {
1007  m_sizeLabel = 0;
1008  }
1009 
1010  if ( !hasDirs ) // Only files [and symlinks]
1011  {
1012  if(hasTotalSize) {
1013  m_sizeLabel->setText(TDEIO::convertSizeWithBytes(totalSize));
1014  }
1015 
1016  m_sizeDetermineButton = 0L;
1017  m_sizeStopButton = 0L;
1018  }
1019  else // Directory
1020  {
1021  TQHBoxLayout * sizelay = new TQHBoxLayout(KDialog::spacingHint());
1022  grid->addLayout( sizelay, curRow++, 2 );
1023 
1024  // buttons
1025  m_sizeDetermineButton = new TQPushButton( i18n("Calculate"), d->m_frame );
1026  m_sizeStopButton = new TQPushButton( i18n("Stop"), d->m_frame );
1027  connect( m_sizeDetermineButton, TQT_SIGNAL( clicked() ), this, TQT_SLOT( slotSizeDetermine() ) );
1028  connect( m_sizeStopButton, TQT_SIGNAL( clicked() ), this, TQT_SLOT( slotSizeStop() ) );
1029  sizelay->addWidget(m_sizeDetermineButton, 0);
1030  sizelay->addWidget(m_sizeStopButton, 0);
1031  sizelay->addStretch(10); // so that the buttons don't grow horizontally
1032 
1033  // auto-launch for local dirs only, and not for '/'
1034  if ( isLocal && !hasRoot )
1035  {
1036  m_sizeDetermineButton->setText( i18n("Refresh") );
1037  slotSizeDetermine();
1038  }
1039  else
1040  m_sizeStopButton->setEnabled( false );
1041  }
1042 
1043  if (!d->bMultiple && item->isLink()) {
1044  l = new TQLabel(i18n("Points to:"), d->m_frame );
1045  grid->addWidget(l, curRow, 0);
1046 
1047  l = new KSqueezedTextLabel(item->linkDest(), d->m_frame );
1048  grid->addWidget(l, curRow++, 2);
1049  }
1050 
1051  if (!d->bMultiple) // Dates for multiple don't make much sense...
1052  {
1053  TQDateTime dt;
1054  bool hasTime;
1055  time_t tim = item->time(TDEIO::UDS_CREATION_TIME, hasTime);
1056  if ( hasTime )
1057  {
1058  l = new TQLabel(i18n("Created:"), d->m_frame );
1059  grid->addWidget(l, curRow, 0);
1060 
1061  dt.setTime_t( tim );
1062  l = new TQLabel(TDEGlobal::locale()->formatDateTime(dt), d->m_frame );
1063  grid->addWidget(l, curRow++, 2);
1064  }
1065 
1066  tim = item->time(TDEIO::UDS_MODIFICATION_TIME, hasTime);
1067  if ( hasTime )
1068  {
1069  l = new TQLabel(i18n("Modified:"), d->m_frame );
1070  grid->addWidget(l, curRow, 0);
1071 
1072  dt.setTime_t( tim );
1073  l = new TQLabel(TDEGlobal::locale()->formatDateTime(dt), d->m_frame );
1074  grid->addWidget(l, curRow++, 2);
1075  }
1076 
1077  tim = item->time(TDEIO::UDS_ACCESS_TIME, hasTime);
1078  if ( hasTime )
1079  {
1080  l = new TQLabel(i18n("Accessed:"), d->m_frame );
1081  grid->addWidget(l, curRow, 0);
1082 
1083  dt.setTime_t( tim );
1084  l = new TQLabel(TDEGlobal::locale()->formatDateTime(dt), d->m_frame );
1085  grid->addWidget(l, curRow++, 2);
1086  }
1087  }
1088 
1089  if ( isLocal && hasDirs ) // only for directories
1090  {
1091  sep = new KSeparator( KSeparator::HLine, d->m_frame);
1092  grid->addMultiCellWidget(sep, curRow, curRow, 0, 2);
1093  ++curRow;
1094 
1095  TQString mountPoint = TDEIO::findPathMountPoint( url.path() );
1096 
1097  if (mountPoint != "/")
1098  {
1099  l = new TQLabel(i18n("Mounted on:"), d->m_frame );
1100  grid->addWidget(l, curRow, 0);
1101 
1102  l = new KSqueezedTextLabel( mountPoint, d->m_frame );
1103  grid->addWidget( l, curRow++, 2 );
1104  }
1105 
1106  l = new TQLabel(i18n("Free disk space:"), d->m_frame );
1107  grid->addWidget(l, curRow, 0);
1108 
1109  d->m_freeSpaceLabel = new TQLabel( d->m_frame );
1110  grid->addWidget( d->m_freeSpaceLabel, curRow++, 2 );
1111 
1112  KDiskFreeSp * job = new KDiskFreeSp;
1113  connect( job, TQT_SIGNAL( foundMountPoint( const unsigned long&, const unsigned long&,
1114  const unsigned long&, const TQString& ) ),
1115  this, TQT_SLOT( slotFoundMountPoint( const unsigned long&, const unsigned long&,
1116  const unsigned long&, const TQString& ) ) );
1117  job->readDF( mountPoint );
1118  }
1119 
1120  vbl->addStretch(1);
1121 }
1122 
1123 // TQString KFilePropsPlugin::tabName () const
1124 // {
1125 // return i18n ("&General");
1126 // }
1127 
1128 void KFilePropsPlugin::setFileNameReadOnly( bool ro )
1129 {
1130  if ( d->m_lined )
1131  {
1132  d->m_lined->setReadOnly( ro );
1133  if (ro)
1134  {
1135  // Don't put the initial focus on the line edit when it is ro
1136  TQPushButton *button = properties->actionButton(KDialogBase::Ok);
1137  if (button)
1138  button->setFocus();
1139  }
1140  }
1141 }
1142 
1143 void KFilePropsPlugin::slotEditFileType()
1144 {
1145 #ifdef Q_WS_X11
1146  TQString mime;
1147  if ( d->mimeType == KMimeType::defaultMimeType() ) {
1148  int pos = d->oldFileName.findRev( '.' );
1149  if ( pos != -1 )
1150  mime = "*" + d->oldFileName.mid(pos);
1151  else
1152  mime = "*";
1153  }
1154  else
1155  mime = d->mimeType;
1156  //TODO: wrap for win32 or mac?
1157  TQString keditfiletype = TQString::fromLatin1("keditfiletype");
1158  KRun::runCommand( keditfiletype
1159  + " --parent " + TQString::number( (ulong)properties->topLevelWidget()->winId())
1160  + " " + TDEProcess::quote(mime),
1161  keditfiletype, keditfiletype /*unused*/);
1162 #endif
1163 }
1164 
1165 void KFilePropsPlugin::slotIconChanged()
1166 {
1167  d->bIconChanged = true;
1168  emit changed();
1169 }
1170 
1171 void KFilePropsPlugin::nameFileChanged(const TQString &text )
1172 {
1173  properties->enableButtonOK(!text.isEmpty());
1174  emit changed();
1175 }
1176 
1177 void KFilePropsPlugin::determineRelativePath( const TQString & path )
1178 {
1179  // now let's make it relative
1180  TQStringList dirs;
1181  if (KBindingPropsPlugin::supports(properties->items()))
1182  {
1183  m_sRelativePath =TDEGlobal::dirs()->relativeLocation("mime", path);
1184  if (m_sRelativePath.startsWith("/"))
1185  m_sRelativePath = TQString::null;
1186  }
1187  else
1188  {
1189  m_sRelativePath =TDEGlobal::dirs()->relativeLocation("apps", path);
1190  if (m_sRelativePath.startsWith("/"))
1191  {
1192  m_sRelativePath =TDEGlobal::dirs()->relativeLocation("xdgdata-apps", path);
1193  if (m_sRelativePath.startsWith("/"))
1194  m_sRelativePath = TQString::null;
1195  else
1196  m_sRelativePath = path;
1197  }
1198  }
1199  if ( m_sRelativePath.isEmpty() )
1200  {
1201  if (KBindingPropsPlugin::supports(properties->items()))
1202  kdWarning(250) << "Warning : editing a mimetype file out of the mimetype dirs!" << endl;
1203  }
1204 }
1205 
1206 void KFilePropsPlugin::slotFoundMountPoint( const TQString&,
1207  unsigned long kBSize,
1208  unsigned long /*kBUsed*/,
1209  unsigned long kBAvail )
1210 {
1211  d->m_freeSpaceLabel->setText(
1212  // xgettext:no-c-format -- Don't warn about translating the %1 out of %2 part.
1213  i18n("Available space out of total partition size (percent used)", "%1 out of %2 (%3% used)")
1214  .arg(TDEIO::convertSizeFromKB(kBAvail))
1215  .arg(TDEIO::convertSizeFromKB(kBSize))
1216  .arg( 100 - (int)(100.0 * kBAvail / kBSize) ));
1217 }
1218 
1219 // attention: copy&paste below, due to compiler bug
1220 // it doesn't like those unsigned long parameters -- unsigned long& are ok :-/
1221 void KFilePropsPlugin::slotFoundMountPoint( const unsigned long& kBSize,
1222  const unsigned long& /*kBUsed*/,
1223  const unsigned long& kBAvail,
1224  const TQString& )
1225 {
1226  d->m_freeSpaceLabel->setText(
1227  // xgettext:no-c-format -- Don't warn about translating the %1 out of %2 part.
1228  i18n("Available space out of total partition size (percent used)", "%1 out of %2 (%3% used)")
1229  .arg(TDEIO::convertSizeFromKB(kBAvail))
1230  .arg(TDEIO::convertSizeFromKB(kBSize))
1231  .arg( 100 - (int)(100.0 * kBAvail / kBSize) ));
1232 }
1233 
1234 void KFilePropsPlugin::slotDirSizeUpdate()
1235 {
1236  TDEIO::filesize_t totalSize = d->dirSizeJob->totalSize();
1237  TDEIO::filesize_t totalFiles = d->dirSizeJob->totalFiles();
1238  TDEIO::filesize_t totalSubdirs = d->dirSizeJob->totalSubdirs();
1239  m_sizeLabel->setText( i18n("Calculating... %1 (%2)\n%3, %4")
1240  .arg(TDEIO::convertSize(totalSize))
1241  .arg(TDEGlobal::locale()->formatNumber(totalSize, 0))
1242  .arg(i18n("1 file","%n files",totalFiles))
1243  .arg(i18n("1 sub-folder","%n sub-folders",totalSubdirs)));
1244 }
1245 
1246 void KFilePropsPlugin::slotDirSizeFinished( TDEIO::Job * job )
1247 {
1248  if (job->error())
1249  m_sizeLabel->setText( job->errorString() );
1250  else
1251  {
1252  TDEIO::filesize_t totalSize = static_cast<KDirSize*>(job)->totalSize();
1253  TDEIO::filesize_t totalFiles = static_cast<KDirSize*>(job)->totalFiles();
1254  TDEIO::filesize_t totalSubdirs = static_cast<KDirSize*>(job)->totalSubdirs();
1255  m_sizeLabel->setText( TQString::fromLatin1("%1 (%2)\n%3, %4")
1256  .arg(TDEIO::convertSize(totalSize))
1257  .arg(TDEGlobal::locale()->formatNumber(totalSize, 0))
1258  .arg(i18n("1 file","%n files",totalFiles))
1259  .arg(i18n("1 sub-folder","%n sub-folders",totalSubdirs)));
1260  }
1261  m_sizeStopButton->setEnabled(false);
1262  // just in case you change something and try again :)
1263  m_sizeDetermineButton->setText( i18n("Refresh") );
1264  m_sizeDetermineButton->setEnabled(true);
1265  d->dirSizeJob = 0L;
1266  delete d->dirSizeUpdateTimer;
1267  d->dirSizeUpdateTimer = 0L;
1268 }
1269 
1270 void KFilePropsPlugin::slotSizeDetermine()
1271 {
1272  m_sizeLabel->setText( i18n("Calculating...") );
1273  kdDebug(250) << " KFilePropsPlugin::slotSizeDetermine() properties->item()=" << properties->item() << endl;
1274  kdDebug(250) << " URL=" << properties->item()->url().url() << endl;
1275  d->dirSizeJob = KDirSize::dirSizeJob( properties->items() );
1276  d->dirSizeUpdateTimer = new TQTimer(this);
1277  connect( d->dirSizeUpdateTimer, TQT_SIGNAL( timeout() ),
1278  TQT_SLOT( slotDirSizeUpdate() ) );
1279  d->dirSizeUpdateTimer->start(500);
1280  connect( d->dirSizeJob, TQT_SIGNAL( result( TDEIO::Job * ) ),
1281  TQT_SLOT( slotDirSizeFinished( TDEIO::Job * ) ) );
1282  m_sizeStopButton->setEnabled(true);
1283  m_sizeDetermineButton->setEnabled(false);
1284 
1285  // also update the "Free disk space" display
1286  if ( d->m_freeSpaceLabel )
1287  {
1288  bool isLocal;
1289  KFileItem * item = properties->item();
1290  KURL url = item->mostLocalURL( isLocal );
1291  TQString mountPoint = TDEIO::findPathMountPoint( url.path() );
1292 
1293  KDiskFreeSp * job = new KDiskFreeSp;
1294  connect( job, TQT_SIGNAL( foundMountPoint( const unsigned long&, const unsigned long&,
1295  const unsigned long&, const TQString& ) ),
1296  this, TQT_SLOT( slotFoundMountPoint( const unsigned long&, const unsigned long&,
1297  const unsigned long&, const TQString& ) ) );
1298  job->readDF( mountPoint );
1299  }
1300 }
1301 
1302 void KFilePropsPlugin::slotSizeStop()
1303 {
1304  if ( d->dirSizeJob )
1305  {
1306  m_sizeLabel->setText( i18n("Stopped") );
1307  d->dirSizeJob->kill();
1308  d->dirSizeJob = 0;
1309  }
1310  if ( d->dirSizeUpdateTimer )
1311  d->dirSizeUpdateTimer->stop();
1312 
1313  m_sizeStopButton->setEnabled(false);
1314  m_sizeDetermineButton->setEnabled(true);
1315 }
1316 
1317 KFilePropsPlugin::~KFilePropsPlugin()
1318 {
1319  delete d;
1320 }
1321 
1322 bool KFilePropsPlugin::supports( KFileItemList /*_items*/ )
1323 {
1324  return true;
1325 }
1326 
1327 // Don't do this at home
1328 void tqt_enter_modal( TQWidget *widget );
1329 void tqt_leave_modal( TQWidget *widget );
1330 
1331 void KFilePropsPlugin::applyChanges()
1332 {
1333  if ( d->dirSizeJob ) {
1334  slotSizeStop();
1335  }
1336 
1337  kdDebug(250) << "KFilePropsPlugin::applyChanges" << endl;
1338 
1339  if (nameArea->inherits(TQLINEEDIT_OBJECT_NAME_STRING))
1340  {
1341  TQString n = ((TQLineEdit *) nameArea)->text();
1342  // Remove trailing spaces (#4345)
1343  while ( n[n.length()-1].isSpace() )
1344  n.truncate( n.length() - 1 );
1345  if ( n.isEmpty() )
1346  {
1347  KMessageBox::sorry( properties, i18n("The new file name is empty."));
1348  properties->abortApplying();
1349  return;
1350  }
1351 
1352  // Do we need to rename the file ?
1353  kdDebug(250) << "oldname = " << oldName << endl;
1354  kdDebug(250) << "newname = " << n << endl;
1355  if ( oldName != n || m_bFromTemplate ) { // true for any from-template file
1356  TDEIO::Job * job = 0L;
1357  KURL oldurl = properties->kurl();
1358 
1359  TQString newFileName = TDEIO::encodeFileName(n);
1360  if (d->bDesktopFile && !newFileName.endsWith(".desktop") && !newFileName.endsWith(".kdelnk"))
1361  newFileName += ".desktop";
1362 
1363  // Tell properties. Warning, this changes the result of properties->kurl() !
1364  properties->rename( newFileName );
1365 
1366  // Update also relative path (for apps and mimetypes)
1367  if ( !m_sRelativePath.isEmpty() ) {
1368  determineRelativePath( properties->kurl().path() );
1369  }
1370 
1371  kdDebug(250) << "New URL = " << properties->kurl().url() << endl;
1372  kdDebug(250) << "old = " << oldurl.url() << endl;
1373 
1374  // Don't remove the template !!
1375  if ( !m_bFromTemplate ) { // (normal renaming)
1376  job = TDEIO::move( oldurl, properties->kurl() );
1377  }
1378  else { // Copying a template
1379  job = TDEIO::copy( oldurl, properties->kurl() );
1380  }
1381 
1382  connect( job, TQT_SIGNAL( result( TDEIO::Job * ) ),
1383  TQT_SLOT( slotCopyFinished( TDEIO::Job * ) ) );
1384  connect( job, TQT_SIGNAL( renamed( TDEIO::Job *, const KURL &, const KURL & ) ),
1385  TQT_SLOT( slotFileRenamed( TDEIO::Job *, const KURL &, const KURL & ) ) );
1386  // wait for job
1387  TQWidget dummy(0,0,(WFlags)(WType_Dialog|WShowModal));
1388  tqt_enter_modal(&dummy);
1389  tqApp->enter_loop();
1390  tqt_leave_modal(&dummy);
1391  return;
1392  }
1393  properties->updateUrl(properties->kurl());
1394  // Update also relative path (for apps and mimetypes)
1395  if ( !m_sRelativePath.isEmpty() ) {
1396  determineRelativePath( properties->kurl().path() );
1397  }
1398  }
1399 
1400  // No job, keep going
1401  slotCopyFinished( 0L );
1402 }
1403 
1404 void KFilePropsPlugin::slotCopyFinished( TDEIO::Job * job )
1405 {
1406  kdDebug(250) << "KFilePropsPlugin::slotCopyFinished" << endl;
1407  if (job)
1408  {
1409  // allow apply() to return
1410  tqApp->exit_loop();
1411  if ( job->error() )
1412  {
1413  job->showErrorDialog( d->m_frame );
1414  // Didn't work. Revert the URL to the old one
1415  properties->updateUrl( static_cast<TDEIO::CopyJob*>(job)->srcURLs().first() );
1416  properties->abortApplying(); // Don't apply the changes to the wrong file !
1417  return;
1418  }
1419  }
1420 
1421  assert( properties->item() );
1422  assert( !properties->item()->url().isEmpty() );
1423 
1424  // Save the file where we can -> usually in ~/.trinity/...
1425  if (KBindingPropsPlugin::supports(properties->items()) && !m_sRelativePath.isEmpty())
1426  {
1427  KURL newURL;
1428  newURL.setPath( locateLocal("mime", m_sRelativePath) );
1429  properties->updateUrl( newURL );
1430  }
1431  else if (d->bDesktopFile && !m_sRelativePath.isEmpty())
1432  {
1433  kdDebug(250) << "KFilePropsPlugin::slotCopyFinished " << m_sRelativePath << endl;
1434  KURL newURL;
1435  newURL.setPath( KDesktopFile::locateLocal(m_sRelativePath) );
1436  kdDebug(250) << "KFilePropsPlugin::slotCopyFinished path=" << newURL.path() << endl;
1437  properties->updateUrl( newURL );
1438  }
1439 
1440  if ( d->bKDesktopMode && d->bDesktopFile ) {
1441  // Renamed? Update Name field
1442  if ( d->oldFileName != properties->kurl().fileName() || m_bFromTemplate ) {
1443  KDesktopFile config( properties->kurl().path() );
1444  TQString nameStr = nameFromFileName(properties->kurl().fileName());
1445  config.writeEntry( "Name", nameStr );
1446  config.writeEntry( "Name", nameStr, true, false, true );
1447  }
1448  }
1449 }
1450 
1451 void KFilePropsPlugin::applyIconChanges()
1452 {
1453  TDEIconButton *iconButton = ::tqqt_cast<TDEIconButton *>( iconArea );
1454  if ( !iconButton || !d->bIconChanged )
1455  return;
1456  // handle icon changes - only local files (or pseudo-local) for now
1457  // TODO: Use KTempFile and TDEIO::file_copy with overwrite = true
1458  KURL url = properties->kurl();
1459  url = TDEIO::NetAccess::mostLocalURL( url, properties );
1460  if (url.isLocalFile()) {
1461  TQString path;
1462 
1463  if (S_ISDIR(properties->item()->mode()))
1464  {
1465  path = url.path(1) + TQString::fromLatin1(".directory");
1466  // don't call updateUrl because the other tabs (i.e. permissions)
1467  // apply to the directory, not the .directory file.
1468  }
1469  else
1470  path = url.path();
1471 
1472  // Get the default image
1473  TQString str = KMimeType::findByURL( url,
1474  properties->item()->mode(),
1475  true )->KServiceType::icon();
1476  // Is it another one than the default ?
1477  TQString sIcon;
1478  if ( str != iconButton->icon() )
1479  sIcon = iconButton->icon();
1480  // (otherwise write empty value)
1481 
1482  kdDebug(250) << "**" << path << "**" << endl;
1483  TQFile f( path );
1484 
1485  // If default icon and no .directory file -> don't create one
1486  if ( !sIcon.isEmpty() || f.exists() )
1487  {
1488  if ( !f.open( IO_ReadWrite ) ) {
1489  KMessageBox::sorry( 0, i18n("<qt>Could not save properties. You do not "
1490  "have sufficient access to write to <b>%1</b>.</qt>").arg(path));
1491  return;
1492  }
1493  f.close();
1494 
1495  KDesktopFile cfg(path);
1496  kdDebug(250) << "sIcon = " << (sIcon) << endl;
1497  kdDebug(250) << "str = " << (str) << endl;
1498  cfg.writeEntry( "Icon", sIcon );
1499  cfg.sync();
1500  }
1501  }
1502 }
1503 
1504 void KFilePropsPlugin::slotFileRenamed( TDEIO::Job *, const KURL &, const KURL & newUrl )
1505 {
1506  // This is called in case of an existing local file during the copy/move operation,
1507  // if the user chooses Rename.
1508  properties->updateUrl( newUrl );
1509 }
1510 
1511 void KFilePropsPlugin::postApplyChanges()
1512 {
1513  // Save the icon only after applying the permissions changes (#46192)
1514  applyIconChanges();
1515 
1516  KURL::List lst;
1517  KFileItemList items = properties->items();
1518  for ( KFileItemListIterator it( items ); it.current(); ++it )
1519  lst.append((*it)->url());
1520  KDirNotify_stub allDirNotify("*", "KDirNotify*");
1521  allDirNotify.FilesChanged( lst );
1522 }
1523 
1524 class KFilePermissionsPropsPlugin::KFilePermissionsPropsPluginPrivate
1525 {
1526 public:
1527  KFilePermissionsPropsPluginPrivate()
1528  {
1529  }
1530  ~KFilePermissionsPropsPluginPrivate()
1531  {
1532  }
1533 
1534  TQFrame *m_frame;
1535  TQCheckBox *cbRecursive;
1536  TQLabel *explanationLabel;
1537  TQComboBox *ownerPermCombo, *groupPermCombo, *othersPermCombo;
1538  TQCheckBox *extraCheckbox;
1539  mode_t partialPermissions;
1540  KFilePermissionsPropsPlugin::PermissionsMode pmode;
1541  bool canChangePermissions;
1542  bool isIrregular;
1543  bool hasExtendedACL;
1544  KACL extendedACL;
1545  KACL defaultACL;
1546  bool fileSystemSupportsACLs;
1547 };
1548 
1549 #define UniOwner (S_IRUSR|S_IWUSR|S_IXUSR)
1550 #define UniGroup (S_IRGRP|S_IWGRP|S_IXGRP)
1551 #define UniOthers (S_IROTH|S_IWOTH|S_IXOTH)
1552 #define UniRead (S_IRUSR|S_IRGRP|S_IROTH)
1553 #define UniWrite (S_IWUSR|S_IWGRP|S_IWOTH)
1554 #define UniExec (S_IXUSR|S_IXGRP|S_IXOTH)
1555 #define UniSpecial (S_ISUID|S_ISGID|S_ISVTX)
1556 
1557 // synced with PermissionsTarget
1558 const mode_t KFilePermissionsPropsPlugin::permissionsMasks[3] = {UniOwner, UniGroup, UniOthers};
1559 const mode_t KFilePermissionsPropsPlugin::standardPermissions[4] = { 0, UniRead, UniRead|UniWrite, (mode_t)-1 };
1560 
1561 // synced with PermissionsMode and standardPermissions
1562 const char *KFilePermissionsPropsPlugin::permissionsTexts[4][4] = {
1563  { I18N_NOOP("Forbidden"),
1564  I18N_NOOP("Can Read"),
1565  I18N_NOOP("Can Read & Write"),
1566  0 },
1567  { I18N_NOOP("Forbidden"),
1568  I18N_NOOP("Can View Content"),
1569  I18N_NOOP("Can View & Modify Content"),
1570  0 },
1571  { 0, 0, 0, 0}, // no texts for links
1572  { I18N_NOOP("Forbidden"),
1573  I18N_NOOP("Can View Content & Read"),
1574  I18N_NOOP("Can View/Read & Modify/Write"),
1575  0 }
1576 };
1577 
1578 
1579 KFilePermissionsPropsPlugin::KFilePermissionsPropsPlugin( KPropertiesDialog *_props )
1580  : KPropsDlgPlugin( _props )
1581 {
1582  d = new KFilePermissionsPropsPluginPrivate;
1583  d->cbRecursive = 0L;
1584  grpCombo = 0L; grpEdit = 0;
1585  usrEdit = 0L;
1586  TQString path = properties->kurl().path(-1);
1587  TQString fname = properties->kurl().fileName();
1588  bool isLocal = properties->kurl().isLocalFile();
1589  bool isTrash = ( properties->kurl().protocol().find("trash", 0, false)==0 );
1590  bool IamRoot = (geteuid() == 0);
1591 
1592  KFileItem * item = properties->item();
1593  bool isLink = item->isLink();
1594  bool isDir = item->isDir(); // all dirs
1595  bool hasDir = item->isDir(); // at least one dir
1596  permissions = item->permissions(); // common permissions to all files
1597  d->partialPermissions = permissions; // permissions that only some files have (at first we take everything)
1598  d->isIrregular = isIrregular(permissions, isDir, isLink);
1599  strOwner = item->user();
1600  strGroup = item->group();
1601  d->hasExtendedACL = item->ACL().isExtended() || item->defaultACL().isValid();
1602  d->extendedACL = item->ACL();
1603  d->defaultACL = item->defaultACL();
1604  d->fileSystemSupportsACLs = false;
1605 
1606  if ( properties->items().count() > 1 )
1607  {
1608  // Multiple items: see what they have in common
1609  KFileItemList items = properties->items();
1610  KFileItemListIterator it( items );
1611  for ( ++it /*no need to check the first one again*/ ; it.current(); ++it )
1612  {
1613  if (!d->isIrregular)
1614  d->isIrregular |= isIrregular((*it)->permissions(),
1615  (*it)->isDir() == isDir,
1616  (*it)->isLink() == isLink);
1617  d->hasExtendedACL = d->hasExtendedACL || (*it)->hasExtendedACL();
1618  if ( (*it)->isLink() != isLink )
1619  isLink = false;
1620  if ( (*it)->isDir() != isDir )
1621  isDir = false;
1622  hasDir |= (*it)->isDir();
1623  if ( (*it)->permissions() != permissions )
1624  {
1625  permissions &= (*it)->permissions();
1626  d->partialPermissions |= (*it)->permissions();
1627  }
1628  if ( (*it)->user() != strOwner )
1629  strOwner = TQString::null;
1630  if ( (*it)->group() != strGroup )
1631  strGroup = TQString::null;
1632  }
1633  }
1634 
1635  if (isLink)
1636  d->pmode = PermissionsOnlyLinks;
1637  else if (isDir)
1638  d->pmode = PermissionsOnlyDirs;
1639  else if (hasDir)
1640  d->pmode = PermissionsMixed;
1641  else
1642  d->pmode = PermissionsOnlyFiles;
1643 
1644  // keep only what's not in the common permissions
1645  d->partialPermissions = d->partialPermissions & ~permissions;
1646 
1647  bool isMyFile = false;
1648 
1649  if (isLocal && !strOwner.isEmpty()) { // local files, and all owned by the same person
1650  struct passwd *myself = getpwuid( geteuid() );
1651  if ( myself != 0L )
1652  {
1653  isMyFile = (strOwner == TQString::fromLocal8Bit(myself->pw_name));
1654  } else
1655  kdWarning() << "I don't exist ?! geteuid=" << geteuid() << endl;
1656  } else {
1657  //We don't know, for remote files, if they are ours or not.
1658  //So we let the user change permissions, and
1659  //TDEIO::chmod will tell, if he had no right to do it.
1660  isMyFile = true;
1661  }
1662 
1663  d->canChangePermissions = (isMyFile || IamRoot) && (!isLink);
1664 
1665 
1666  // create GUI
1667 
1668  d->m_frame = properties->addPage(i18n("&Permissions"));
1669 
1670  TQBoxLayout *box = new TQVBoxLayout( d->m_frame, 0, KDialog::spacingHint() );
1671 
1672  TQWidget *l;
1673  TQLabel *lbl;
1674  TQGroupBox *gb;
1675  TQGridLayout *gl;
1676  TQPushButton* pbAdvancedPerm = 0;
1677 
1678  /* Group: Access Permissions */
1679  gb = new TQGroupBox ( 0, Qt::Vertical, i18n("Access Permissions"), d->m_frame );
1680  gb->layout()->setSpacing(KDialog::spacingHint());
1681  gb->layout()->setMargin(KDialog::marginHint());
1682  box->addWidget (gb);
1683 
1684  gl = new TQGridLayout (gb->layout(), 7, 2);
1685  gl->setColStretch(1, 1);
1686 
1687  l = d->explanationLabel = new TQLabel( "", gb );
1688  if (isLink)
1689  d->explanationLabel->setText(i18n("This file is a link and does not have permissions.",
1690  "All files are links and do not have permissions.",
1691  properties->items().count()));
1692  else if (!d->canChangePermissions)
1693  d->explanationLabel->setText(i18n("Only the owner can change permissions."));
1694  gl->addMultiCellWidget(l, 0, 0, 0, 1);
1695 
1696  lbl = new TQLabel( i18n("O&wner:"), gb);
1697  gl->addWidget(lbl, 1, 0);
1698  l = d->ownerPermCombo = new TQComboBox(gb);
1699  lbl->setBuddy(l);
1700  gl->addWidget(l, 1, 1);
1701  connect(l, TQT_SIGNAL( highlighted(int) ), this, TQT_SIGNAL( changed() ));
1702  TQWhatsThis::add(l, i18n("Specifies the actions that the owner is allowed to do."));
1703 
1704  lbl = new TQLabel( i18n("Gro&up:"), gb);
1705  gl->addWidget(lbl, 2, 0);
1706  l = d->groupPermCombo = new TQComboBox(gb);
1707  lbl->setBuddy(l);
1708  gl->addWidget(l, 2, 1);
1709  connect(l, TQT_SIGNAL( highlighted(int) ), this, TQT_SIGNAL( changed() ));
1710  TQWhatsThis::add(l, i18n("Specifies the actions that the members of the group are allowed to do."));
1711 
1712  lbl = new TQLabel( i18n("O&thers:"), gb);
1713  gl->addWidget(lbl, 3, 0);
1714  l = d->othersPermCombo = new TQComboBox(gb);
1715  lbl->setBuddy(l);
1716  gl->addWidget(l, 3, 1);
1717  connect(l, TQT_SIGNAL( highlighted(int) ), this, TQT_SIGNAL( changed() ));
1718  TQWhatsThis::add(l, i18n("Specifies the actions that all users, who are neither "
1719  "owner nor in the group, are allowed to do."));
1720 
1721  if (!isLink) {
1722  l = d->extraCheckbox = new TQCheckBox(hasDir ?
1723  i18n("Only own&er can rename and delete folder content") :
1724  i18n("Is &executable"),
1725  gb );
1726  connect( d->extraCheckbox, TQT_SIGNAL( clicked() ), this, TQT_SIGNAL( changed() ) );
1727  gl->addWidget(l, 4, 1);
1728  TQWhatsThis::add(l, hasDir ? i18n("Enable this option to allow only the folder's owner to "
1729  "delete or rename the contained files and folders. Other "
1730  "users can only add new files, which requires the 'Modify "
1731  "Content' permission.")
1732  : i18n("Enable this option to mark the file as executable. This only makes "
1733  "sense for programs and scripts. It is required when you want to "
1734  "execute them."));
1735 
1736  TQLayoutItem *spacer = TQT_TQLAYOUTITEM(new TQSpacerItem(0, 20, TQSizePolicy::Minimum, TQSizePolicy::Expanding));
1737  gl->addMultiCell(spacer, 5, 5, 0, 1);
1738 
1739  pbAdvancedPerm = new TQPushButton(i18n("A&dvanced Permissions"), gb);
1740  gl->addMultiCellWidget(pbAdvancedPerm, 6, 6, 0, 1, Qt::AlignRight);
1741  connect(pbAdvancedPerm, TQT_SIGNAL( clicked() ), this, TQT_SLOT( slotShowAdvancedPermissions() ));
1742  }
1743  else
1744  d->extraCheckbox = 0;
1745 
1746 
1747  /**** Group: Ownership ****/
1748  gb = new TQGroupBox ( 0, Qt::Vertical, i18n("Ownership"), d->m_frame );
1749  gb->layout()->setSpacing(KDialog::spacingHint());
1750  gb->layout()->setMargin(KDialog::marginHint());
1751  box->addWidget (gb);
1752 
1753  gl = new TQGridLayout (gb->layout(), 4, 3);
1754  gl->addRowSpacing(0, 10);
1755 
1756  /*** Set Owner ***/
1757  l = new TQLabel( i18n("User:"), gb );
1758  gl->addWidget (l, 1, 0);
1759 
1760  /* GJ: Don't autocomplete more than 1000 users. This is a kind of random
1761  * value. Huge sites having 10.000+ user have a fair chance of using NIS,
1762  * (possibly) making this unacceptably slow.
1763  * OTOH, it is nice to offer this functionality for the standard user.
1764  */
1765  int i, maxEntries = 1000;
1766  struct passwd *user;
1767 
1768  /* File owner: For root, offer a KLineEdit with autocompletion.
1769  * For a user, who can never chown() a file, offer a TQLabel.
1770  */
1771  if (IamRoot && isLocal)
1772  {
1773  usrEdit = new KLineEdit( gb );
1774  TDECompletion *kcom = usrEdit->completionObject();
1775  kcom->setOrder(TDECompletion::Sorted);
1776  setpwent();
1777  for (i=0; ((user = getpwent()) != 0L) && (i < maxEntries); i++)
1778  kcom->addItem(TQString::fromLatin1(user->pw_name));
1779  endpwent();
1780  usrEdit->setCompletionMode((i < maxEntries) ? TDEGlobalSettings::CompletionAuto :
1781  TDEGlobalSettings::CompletionNone);
1782  usrEdit->setText(strOwner);
1783  gl->addWidget(usrEdit, 1, 1);
1784  connect( usrEdit, TQT_SIGNAL( textChanged( const TQString & ) ),
1785  this, TQT_SIGNAL( changed() ) );
1786  }
1787  else
1788  {
1789  l = new TQLabel(strOwner, gb);
1790  gl->addWidget(l, 1, 1);
1791  }
1792 
1793  /*** Set Group ***/
1794 
1795  TQStringList groupList;
1796  TQCString strUser;
1797  user = getpwuid(geteuid());
1798  if (user != 0L)
1799  strUser = user->pw_name;
1800 
1801 #ifdef Q_OS_UNIX
1802  gid_t *groups = NULL;
1803  int ng = 1;
1804  struct group *mygroup;
1805  gid_t *newgroups = NULL;
1806 
1807  groups = (gid_t *) malloc(ng * sizeof(gid_t));
1808 
1809  if (getgrouplist(strUser, user->pw_gid, groups, &ng) == -1) {
1810  newgroups = (gid_t *) malloc(ng * sizeof(gid_t));
1811  if (newgroups != NULL) {
1812  free(groups);
1813  groups = newgroups;
1814  getgrouplist(strUser, user->pw_gid, groups, &ng);
1815  } else ng = 1;
1816  }
1817 
1818  for (i = 0; i < ng; i++) {
1819  mygroup = getgrgid(groups[i]);
1820  if (mygroup != NULL) groupList += TQString::fromLocal8Bit(mygroup->gr_name);
1821  }
1822 
1823  free(groups);
1824 
1825 #else //Q_OS_UNIX
1826  struct group *ge;
1827 
1828  /* add the effective Group to the list .. */
1829  ge = getgrgid (getegid());
1830  if (ge) {
1831  TQString name = TQString::fromLatin1(ge->gr_name);
1832  if (name.isEmpty())
1833  name.setNum(ge->gr_gid);
1834  if (groupList.find(name) == groupList.end())
1835  groupList += name;
1836  }
1837 #endif //Q_OS_UNIX
1838 
1839  bool isMyGroup = groupList.contains(strGroup);
1840 
1841  /* add the group the file currently belongs to ..
1842  * .. if its not there already
1843  */
1844  if (!isMyGroup)
1845  groupList += strGroup;
1846 
1847  l = new TQLabel( i18n("Group:"), gb );
1848  gl->addWidget (l, 2, 0);
1849 
1850  /* Set group: if possible to change:
1851  * - Offer a KLineEdit for root, since he can change to any group.
1852  * - Offer a TQComboBox for a normal user, since he can change to a fixed
1853  * (small) set of groups only.
1854  * If not changeable: offer a TQLabel.
1855  */
1856  if (IamRoot && isLocal)
1857  {
1858  grpEdit = new KLineEdit(gb);
1859  TDECompletion *kcom = new TDECompletion;
1860  kcom->setItems(groupList);
1861  grpEdit->setCompletionObject(kcom, true);
1862  grpEdit->setAutoDeleteCompletionObject( true );
1863  grpEdit->setCompletionMode(TDEGlobalSettings::CompletionAuto);
1864  grpEdit->setText(strGroup);
1865  gl->addWidget(grpEdit, 2, 1);
1866  connect( grpEdit, TQT_SIGNAL( textChanged( const TQString & ) ),
1867  this, TQT_SIGNAL( changed() ) );
1868  }
1869  else if ((groupList.count() > 1) && isMyFile && isLocal)
1870  {
1871  grpCombo = new TQComboBox(gb, "combogrouplist");
1872  grpCombo->insertStringList(groupList);
1873  grpCombo->setCurrentItem(groupList.findIndex(strGroup));
1874  gl->addWidget(grpCombo, 2, 1);
1875  connect( grpCombo, TQT_SIGNAL( activated( int ) ),
1876  this, TQT_SIGNAL( changed() ) );
1877  }
1878  else
1879  {
1880  l = new TQLabel(strGroup, gb);
1881  gl->addWidget(l, 2, 1);
1882  }
1883 
1884  gl->setColStretch(2, 10);
1885 
1886  // "Apply recursive" checkbox
1887  if ( hasDir && !isLink && !isTrash )
1888  {
1889  d->cbRecursive = new TQCheckBox( i18n("Apply changes to all subfolders and their contents"), d->m_frame );
1890  connect( d->cbRecursive, TQT_SIGNAL( clicked() ), this, TQT_SIGNAL( changed() ) );
1891  box->addWidget( d->cbRecursive );
1892  }
1893 
1894  updateAccessControls();
1895 
1896 
1897  if ( isTrash || !d->canChangePermissions )
1898  {
1899  //don't allow to change properties for file into trash
1900  enableAccessControls(false);
1901  if ( pbAdvancedPerm && !d->hasExtendedACL )
1902  pbAdvancedPerm->setEnabled(false);
1903  }
1904 
1905  box->addStretch (10);
1906 }
1907 
1908 #ifdef USE_POSIX_ACL
1909 static bool fileSystemSupportsACL( const TQCString& pathCString )
1910 {
1911  bool fileSystemSupportsACLs = false;
1912 #ifdef Q_OS_FREEBSD
1913  struct statfs buf;
1914  fileSystemSupportsACLs = ( statfs( pathCString.data(), &buf ) == 0 ) && ( buf.f_flags & MNT_ACLS );
1915 #else
1916  fileSystemSupportsACLs =
1917  getxattr( pathCString.data(), "system.posix_acl_access", NULL, 0 ) >= 0
1918 #ifdef ENODATA
1919  || (errno == ENODATA)
1920 #endif
1921 #ifdef ENOATTR
1922  || (errno == ENOATTR)
1923 #endif
1924  ;
1925 #endif
1926  return fileSystemSupportsACLs;
1927 }
1928 #endif
1929 
1930 
1931 void KFilePermissionsPropsPlugin::slotShowAdvancedPermissions() {
1932 
1933  bool isDir = (d->pmode == PermissionsOnlyDirs) || (d->pmode == PermissionsMixed);
1934  KDialogBase dlg(properties, 0, true, i18n("Advanced Permissions"),
1935  KDialogBase::Ok|KDialogBase::Cancel);
1936 
1937  TQLabel *l, *cl[3];
1938  TQGroupBox *gb;
1939  TQGridLayout *gl;
1940 
1941  TQVBox *mainVBox = dlg.makeVBoxMainWidget();
1942 
1943  // Group: Access Permissions
1944  gb = new TQGroupBox ( 0, Qt::Vertical, i18n("Access Permissions"), mainVBox );
1945  gb->layout()->setSpacing(KDialog::spacingHint());
1946  gb->layout()->setMargin(KDialog::marginHint());
1947 
1948  gl = new TQGridLayout (gb->layout(), 6, 6);
1949  gl->addRowSpacing(0, 10);
1950 
1951  TQValueVector<TQWidget*> theNotSpecials;
1952 
1953  l = new TQLabel(i18n("Class"), gb );
1954  gl->addWidget(l, 1, 0);
1955  theNotSpecials.append( l );
1956 
1957  if (isDir)
1958  l = new TQLabel( i18n("Show\nEntries"), gb );
1959  else
1960  l = new TQLabel( i18n("Read"), gb );
1961  gl->addWidget (l, 1, 1);
1962  theNotSpecials.append( l );
1963  TQString readWhatsThis;
1964  if (isDir)
1965  readWhatsThis = i18n("This flag allows viewing the content of the folder.");
1966  else
1967  readWhatsThis = i18n("The Read flag allows viewing the content of the file.");
1968  TQWhatsThis::add(l, readWhatsThis);
1969 
1970  if (isDir)
1971  l = new TQLabel( i18n("Write\nEntries"), gb );
1972  else
1973  l = new TQLabel( i18n("Write"), gb );
1974  gl->addWidget (l, 1, 2);
1975  theNotSpecials.append( l );
1976  TQString writeWhatsThis;
1977  if (isDir)
1978  writeWhatsThis = i18n("This flag allows adding, renaming and deleting of files. "
1979  "Note that deleting and renaming can be limited using the Sticky flag.");
1980  else
1981  writeWhatsThis = i18n("The Write flag allows modifying the content of the file.");
1982  TQWhatsThis::add(l, writeWhatsThis);
1983 
1984  TQString execWhatsThis;
1985  if (isDir) {
1986  l = new TQLabel( i18n("Enter folder", "Enter"), gb );
1987  execWhatsThis = i18n("Enable this flag to allow entering the folder.");
1988  }
1989  else {
1990  l = new TQLabel( i18n("Exec"), gb );
1991  execWhatsThis = i18n("Enable this flag to allow executing the file as a program.");
1992  }
1993  TQWhatsThis::add(l, execWhatsThis);
1994  theNotSpecials.append( l );
1995  // GJ: Add space between normal and special modes
1996  TQSize size = l->sizeHint();
1997  size.setWidth(size.width() + 15);
1998  l->setFixedSize(size);
1999  gl->addWidget (l, 1, 3);
2000 
2001  l = new TQLabel( i18n("Special"), gb );
2002  gl->addMultiCellWidget(l, 1, 1, 4, 5);
2003  TQString specialWhatsThis;
2004  if (isDir)
2005  specialWhatsThis = i18n("Special flag. Valid for the whole folder, the exact "
2006  "meaning of the flag can be seen in the right hand column.");
2007  else
2008  specialWhatsThis = i18n("Special flag. The exact meaning of the flag can be seen "
2009  "in the right hand column.");
2010  TQWhatsThis::add(l, specialWhatsThis);
2011 
2012  cl[0] = new TQLabel( i18n("User"), gb );
2013  gl->addWidget (cl[0], 2, 0);
2014  theNotSpecials.append( cl[0] );
2015 
2016  cl[1] = new TQLabel( i18n("Group"), gb );
2017  gl->addWidget (cl[1], 3, 0);
2018  theNotSpecials.append( cl[1] );
2019 
2020  cl[2] = new TQLabel( i18n("Others"), gb );
2021  gl->addWidget (cl[2], 4, 0);
2022  theNotSpecials.append( cl[2] );
2023 
2024  l = new TQLabel(i18n("Set UID"), gb);
2025  gl->addWidget(l, 2, 5);
2026  TQString setUidWhatsThis;
2027  if (isDir)
2028  setUidWhatsThis = i18n("If this flag is set, the owner of this folder will be "
2029  "the owner of all new files.");
2030  else
2031  setUidWhatsThis = i18n("If this file is an executable and the flag is set, it will "
2032  "be executed with the permissions of the owner.");
2033  TQWhatsThis::add(l, setUidWhatsThis);
2034 
2035  l = new TQLabel(i18n("Set GID"), gb);
2036  gl->addWidget(l, 3, 5);
2037  TQString setGidWhatsThis;
2038  if (isDir)
2039  setGidWhatsThis = i18n("If this flag is set, the group of this folder will be "
2040  "set for all new files.");
2041  else
2042  setGidWhatsThis = i18n("If this file is an executable and the flag is set, it will "
2043  "be executed with the permissions of the group.");
2044  TQWhatsThis::add(l, setGidWhatsThis);
2045 
2046  l = new TQLabel(i18n("File permission", "Sticky"), gb);
2047  gl->addWidget(l, 4, 5);
2048  TQString stickyWhatsThis;
2049  if (isDir)
2050  stickyWhatsThis = i18n("If the Sticky flag is set on a folder, only the owner "
2051  "and root can delete or rename files. Otherwise everybody "
2052  "with write permissions can do this.");
2053  else
2054  stickyWhatsThis = i18n("The Sticky flag on a file is ignored on Linux, but may "
2055  "be used on some systems");
2056  TQWhatsThis::add(l, stickyWhatsThis);
2057 
2058  mode_t aPermissions, aPartialPermissions;
2059  mode_t dummy1, dummy2;
2060 
2061  if (!d->isIrregular) {
2062  switch (d->pmode) {
2063  case PermissionsOnlyFiles:
2064  getPermissionMasks(aPartialPermissions,
2065  dummy1,
2066  aPermissions,
2067  dummy2);
2068  break;
2069  case PermissionsOnlyDirs:
2070  case PermissionsMixed:
2071  getPermissionMasks(dummy1,
2072  aPartialPermissions,
2073  dummy2,
2074  aPermissions);
2075  break;
2076  case PermissionsOnlyLinks:
2077  aPermissions = UniRead | UniWrite | UniExec | UniSpecial;
2078  aPartialPermissions = 0;
2079  break;
2080  }
2081  }
2082  else {
2083  aPermissions = permissions;
2084  aPartialPermissions = d->partialPermissions;
2085  }
2086 
2087  // Draw Checkboxes
2088  bool allDisable = true;
2089  TQCheckBox *cba[3][4];
2090  for (int row = 0; row < 3 ; ++row) {
2091  for (int col = 0; col < 4; ++col) {
2092  TQCheckBox *cb = new TQCheckBox( gb );
2093  if ( col != 3 ) theNotSpecials.append( cb );
2094  cba[row][col] = cb;
2095  cb->setChecked(aPermissions & fperm[row][col]);
2096  if ( d->canChangePermissions )
2097  {
2098  allDisable = false;
2099  }
2100  if ( aPartialPermissions & fperm[row][col] )
2101  {
2102  cb->setTristate();
2103  cb->setNoChange();
2104  }
2105  else if (d->cbRecursive && d->cbRecursive->isChecked())
2106  {
2107  cb->setTristate();
2108  }
2109 
2110  cb->setEnabled( d->canChangePermissions );
2111  gl->addWidget (cb, row+2, col+1);
2112  switch(col) {
2113  case 0:
2114  TQWhatsThis::add(cb, readWhatsThis);
2115  break;
2116  case 1:
2117  TQWhatsThis::add(cb, writeWhatsThis);
2118  break;
2119  case 2:
2120  TQWhatsThis::add(cb, execWhatsThis);
2121  break;
2122  case 3:
2123  switch(row) {
2124  case 0:
2125  TQWhatsThis::add(cb, setUidWhatsThis);
2126  break;
2127  case 1:
2128  TQWhatsThis::add(cb, setGidWhatsThis);
2129  break;
2130  case 2:
2131  TQWhatsThis::add(cb, stickyWhatsThis);
2132  break;
2133  }
2134  break;
2135  }
2136  }
2137  }
2138  gl->setColStretch(6, 10);
2139 
2140 #ifdef USE_POSIX_ACL
2141  KACLEditWidget *extendedACLs = 0;
2142 
2143  // FIXME make it work with partial entries
2144  if ( properties->items().count() == 1 ) {
2145  TQCString pathCString = TQFile::encodeName( properties->item()->url().path() );
2146  d->fileSystemSupportsACLs = fileSystemSupportsACL( pathCString );
2147  }
2148  if ( d->fileSystemSupportsACLs ) {
2149  std::for_each( theNotSpecials.begin(), theNotSpecials.end(), std::mem_fun( &TQWidget::hide ) );
2150  extendedACLs = new KACLEditWidget( mainVBox );
2151  if ( d->extendedACL.isValid() && d->extendedACL.isExtended() )
2152  extendedACLs->setACL( d->extendedACL );
2153  else
2154  extendedACLs->setACL( KACL( aPermissions ) );
2155 
2156  if ( d->defaultACL.isValid() )
2157  extendedACLs->setDefaultACL( d->defaultACL );
2158 
2159  if ( properties->items().first()->isDir() )
2160  extendedACLs->setAllowDefaults( true );
2161  if ( !d->canChangePermissions )
2162  extendedACLs->setReadOnly( true );
2163 
2164  }
2165 #endif
2166  if ( allDisable ) {
2167  dlg.enableButtonOK( false );
2168  }
2169 
2170  if (dlg.exec() != KDialogBase::Accepted)
2171  return;
2172 
2173  mode_t andPermissions = mode_t(~0);
2174  mode_t orPermissions = 0;
2175  for (int row = 0; row < 3; ++row)
2176  for (int col = 0; col < 4; ++col) {
2177  switch (cba[row][col]->state())
2178  {
2179  case TQCheckBox::On:
2180  orPermissions |= fperm[row][col];
2181  //fall through
2182  case TQCheckBox::Off:
2183  andPermissions &= ~fperm[row][col];
2184  break;
2185  default: // NoChange
2186  break;
2187  }
2188  }
2189 
2190  d->isIrregular = false;
2191  KFileItemList items = properties->items();
2192  for (KFileItemListIterator it(items); it.current(); ++it) {
2193  if (isIrregular(((*it)->permissions() & andPermissions) | orPermissions,
2194  (*it)->isDir(), (*it)->isLink())) {
2195  d->isIrregular = true;
2196  break;
2197  }
2198  }
2199 
2200  permissions = orPermissions;
2201  d->partialPermissions = andPermissions;
2202 
2203 #ifdef USE_POSIX_ACL
2204  // override with the acls, if present
2205  if ( extendedACLs ) {
2206  d->extendedACL = extendedACLs->getACL();
2207  d->defaultACL = extendedACLs->getDefaultACL();
2208  d->hasExtendedACL = d->extendedACL.isExtended() || d->defaultACL.isValid();
2209  permissions = d->extendedACL.basePermissions();
2210  permissions |= ( andPermissions | orPermissions ) & ( S_ISUID|S_ISGID|S_ISVTX );
2211  }
2212 #endif
2213 
2214  updateAccessControls();
2215  emit changed();
2216 }
2217 
2218 // TQString KFilePermissionsPropsPlugin::tabName () const
2219 // {
2220 // return i18n ("&Permissions");
2221 // }
2222 
2223 KFilePermissionsPropsPlugin::~KFilePermissionsPropsPlugin()
2224 {
2225  delete d;
2226 }
2227 
2228 bool KFilePermissionsPropsPlugin::supports( KFileItemList _items )
2229 {
2230  KFileItemList::const_iterator it = _items.constBegin();
2231  for ( ; it != _items.constEnd(); ++it ) {
2232  KFileItem *item = *it;
2233  if( !item->user().isEmpty() || !item->group().isEmpty() )
2234  return true;
2235  }
2236  return false;
2237 }
2238 
2239 // sets a combo box in the Access Control frame
2240 void KFilePermissionsPropsPlugin::setComboContent(TQComboBox *combo, PermissionsTarget target,
2241  mode_t permissions, mode_t partial) {
2242  combo->clear();
2243  if (d->pmode == PermissionsOnlyLinks) {
2244  combo->insertItem(i18n("Link"));
2245  combo->setCurrentItem(0);
2246  return;
2247  }
2248 
2249  mode_t tMask = permissionsMasks[target];
2250  int textIndex;
2251  for (textIndex = 0; standardPermissions[textIndex] != (mode_t)-1; textIndex++)
2252  if ((standardPermissions[textIndex]&tMask) == (permissions&tMask&(UniRead|UniWrite)))
2253  break;
2254  Q_ASSERT(standardPermissions[textIndex] != (mode_t)-1); // must not happen, would be irreglar
2255 
2256  for (int i = 0; permissionsTexts[(int)d->pmode][i]; i++)
2257  combo->insertItem(i18n(permissionsTexts[(int)d->pmode][i]));
2258 
2259  if (partial & tMask & ~UniExec) {
2260  combo->insertItem(i18n("Varying (No Change)"));
2261  combo->setCurrentItem(3);
2262  }
2263  else
2264  combo->setCurrentItem(textIndex);
2265 }
2266 
2267 // permissions are irregular if they cant be displayed in a combo box.
2268 bool KFilePermissionsPropsPlugin::isIrregular(mode_t permissions, bool isDir, bool isLink) {
2269  if (isLink) // links are always ok
2270  return false;
2271 
2272  mode_t p = permissions;
2273  if (p & (S_ISUID | S_ISGID)) // setuid/setgid -> irregular
2274  return true;
2275  if (isDir) {
2276  p &= ~S_ISVTX; // ignore sticky on dirs
2277 
2278  // check supported flag combinations
2279  mode_t p0 = p & UniOwner;
2280  if ((p0 != 0) && (p0 != (S_IRUSR | S_IXUSR)) && (p0 != UniOwner))
2281  return true;
2282  p0 = p & UniGroup;
2283  if ((p0 != 0) && (p0 != (S_IRGRP | S_IXGRP)) && (p0 != UniGroup))
2284  return true;
2285  p0 = p & UniOthers;
2286  if ((p0 != 0) && (p0 != (S_IROTH | S_IXOTH)) && (p0 != UniOthers))
2287  return true;
2288  return false;
2289  }
2290  if (p & S_ISVTX) // sticky on file -> irregular
2291  return true;
2292 
2293  // check supported flag combinations
2294  mode_t p0 = p & UniOwner;
2295  bool usrXPossible = !p0; // true if this file could be an executable
2296  if (p0 & S_IXUSR) {
2297  if ((p0 == S_IXUSR) || (p0 == (S_IWUSR | S_IXUSR)))
2298  return true;
2299  usrXPossible = true;
2300  }
2301  else if (p0 == S_IWUSR)
2302  return true;
2303 
2304  p0 = p & UniGroup;
2305  bool grpXPossible = !p0; // true if this file could be an executable
2306  if (p0 & S_IXGRP) {
2307  if ((p0 == S_IXGRP) || (p0 == (S_IWGRP | S_IXGRP)))
2308  return true;
2309  grpXPossible = true;
2310  }
2311  else if (p0 == S_IWGRP)
2312  return true;
2313  if (p0 == 0)
2314  grpXPossible = true;
2315 
2316  p0 = p & UniOthers;
2317  bool othXPossible = !p0; // true if this file could be an executable
2318  if (p0 & S_IXOTH) {
2319  if ((p0 == S_IXOTH) || (p0 == (S_IWOTH | S_IXOTH)))
2320  return true;
2321  othXPossible = true;
2322  }
2323  else if (p0 == S_IWOTH)
2324  return true;
2325 
2326  // check that there either all targets are executable-compatible, or none
2327  return (p & UniExec) && !(usrXPossible && grpXPossible && othXPossible);
2328 }
2329 
2330 // enables/disabled the widgets in the Access Control frame
2331 void KFilePermissionsPropsPlugin::enableAccessControls(bool enable) {
2332  d->ownerPermCombo->setEnabled(enable);
2333  d->groupPermCombo->setEnabled(enable);
2334  d->othersPermCombo->setEnabled(enable);
2335  if (d->extraCheckbox)
2336  d->extraCheckbox->setEnabled(enable);
2337  if ( d->cbRecursive )
2338  d->cbRecursive->setEnabled(enable);
2339 }
2340 
2341 // updates all widgets in the Access Control frame
2342 void KFilePermissionsPropsPlugin::updateAccessControls() {
2343  setComboContent(d->ownerPermCombo, PermissionsOwner,
2344  permissions, d->partialPermissions);
2345  setComboContent(d->groupPermCombo, PermissionsGroup,
2346  permissions, d->partialPermissions);
2347  setComboContent(d->othersPermCombo, PermissionsOthers,
2348  permissions, d->partialPermissions);
2349 
2350  switch(d->pmode) {
2351  case PermissionsOnlyLinks:
2352  enableAccessControls(false);
2353  break;
2354  case PermissionsOnlyFiles:
2355  enableAccessControls(d->canChangePermissions && !d->isIrregular && !d->hasExtendedACL);
2356  if (d->canChangePermissions)
2357  d->explanationLabel->setText(d->isIrregular || d->hasExtendedACL ?
2358  i18n("This file uses advanced permissions",
2359  "These files use advanced permissions.",
2360  properties->items().count()) : "");
2361  if (d->partialPermissions & UniExec) {
2362  d->extraCheckbox->setTristate();
2363  d->extraCheckbox->setNoChange();
2364  }
2365  else {
2366  d->extraCheckbox->setTristate(false);
2367  d->extraCheckbox->setChecked(permissions & UniExec);
2368  }
2369  break;
2370  case PermissionsOnlyDirs:
2371  enableAccessControls(d->canChangePermissions && !d->isIrregular && !d->hasExtendedACL);
2372  // if this is a dir, and we can change permissions, don't dis-allow
2373  // recursive, we can do that for ACL setting.
2374  if ( d->cbRecursive )
2375  d->cbRecursive->setEnabled( d->canChangePermissions && !d->isIrregular );
2376 
2377  if (d->canChangePermissions)
2378  d->explanationLabel->setText(d->isIrregular || d->hasExtendedACL ?
2379  i18n("This folder uses advanced permissions.",
2380  "These folders use advanced permissions.",
2381  properties->items().count()) : "");
2382  if (d->partialPermissions & S_ISVTX) {
2383  d->extraCheckbox->setTristate();
2384  d->extraCheckbox->setNoChange();
2385  }
2386  else {
2387  d->extraCheckbox->setTristate(false);
2388  d->extraCheckbox->setChecked(permissions & S_ISVTX);
2389  }
2390  break;
2391  case PermissionsMixed:
2392  enableAccessControls(d->canChangePermissions && !d->isIrregular && !d->hasExtendedACL);
2393  if (d->canChangePermissions)
2394  d->explanationLabel->setText(d->isIrregular || d->hasExtendedACL ?
2395  i18n("These files use advanced permissions.") : "");
2396  break;
2397  if (d->partialPermissions & S_ISVTX) {
2398  d->extraCheckbox->setTristate();
2399  d->extraCheckbox->setNoChange();
2400  }
2401  else {
2402  d->extraCheckbox->setTristate(false);
2403  d->extraCheckbox->setChecked(permissions & S_ISVTX);
2404  }
2405  break;
2406  }
2407 }
2408 
2409 // gets masks for files and dirs from the Access Control frame widgets
2410 void KFilePermissionsPropsPlugin::getPermissionMasks(mode_t &andFilePermissions,
2411  mode_t &andDirPermissions,
2412  mode_t &orFilePermissions,
2413  mode_t &orDirPermissions) {
2414  andFilePermissions = mode_t(~UniSpecial);
2415  andDirPermissions = mode_t(~(S_ISUID|S_ISGID));
2416  orFilePermissions = 0;
2417  orDirPermissions = 0;
2418  if (d->isIrregular)
2419  return;
2420 
2421  mode_t m = standardPermissions[d->ownerPermCombo->currentItem()];
2422  if (m != (mode_t) -1) {
2423  orFilePermissions |= m & UniOwner;
2424  if ((m & UniOwner) &&
2425  ((d->pmode == PermissionsMixed) ||
2426  ((d->pmode == PermissionsOnlyFiles) && (d->extraCheckbox->state() == TQButton::NoChange))))
2427  andFilePermissions &= ~(S_IRUSR | S_IWUSR);
2428  else {
2429  andFilePermissions &= ~(S_IRUSR | S_IWUSR | S_IXUSR);
2430  if ((m & S_IRUSR) && (d->extraCheckbox->state() == TQButton::On))
2431  orFilePermissions |= S_IXUSR;
2432  }
2433 
2434  orDirPermissions |= m & UniOwner;
2435  if (m & S_IRUSR)
2436  orDirPermissions |= S_IXUSR;
2437  andDirPermissions &= ~(S_IRUSR | S_IWUSR | S_IXUSR);
2438  }
2439 
2440  m = standardPermissions[d->groupPermCombo->currentItem()];
2441  if (m != (mode_t) -1) {
2442  orFilePermissions |= m & UniGroup;
2443  if ((m & UniGroup) &&
2444  ((d->pmode == PermissionsMixed) ||
2445  ((d->pmode == PermissionsOnlyFiles) && (d->extraCheckbox->state() == TQButton::NoChange))))
2446  andFilePermissions &= ~(S_IRGRP | S_IWGRP);
2447  else {
2448  andFilePermissions &= ~(S_IRGRP | S_IWGRP | S_IXGRP);
2449  if ((m & S_IRGRP) && (d->extraCheckbox->state() == TQButton::On))
2450  orFilePermissions |= S_IXGRP;
2451  }
2452 
2453  orDirPermissions |= m & UniGroup;
2454  if (m & S_IRGRP)
2455  orDirPermissions |= S_IXGRP;
2456  andDirPermissions &= ~(S_IRGRP | S_IWGRP | S_IXGRP);
2457  }
2458 
2459  m = standardPermissions[d->othersPermCombo->currentItem()];
2460  if (m != (mode_t) -1) {
2461  orFilePermissions |= m & UniOthers;
2462  if ((m & UniOthers) &&
2463  ((d->pmode == PermissionsMixed) ||
2464  ((d->pmode == PermissionsOnlyFiles) && (d->extraCheckbox->state() == TQButton::NoChange))))
2465  andFilePermissions &= ~(S_IROTH | S_IWOTH);
2466  else {
2467  andFilePermissions &= ~(S_IROTH | S_IWOTH | S_IXOTH);
2468  if ((m & S_IROTH) && (d->extraCheckbox->state() == TQButton::On))
2469  orFilePermissions |= S_IXOTH;
2470  }
2471 
2472  orDirPermissions |= m & UniOthers;
2473  if (m & S_IROTH)
2474  orDirPermissions |= S_IXOTH;
2475  andDirPermissions &= ~(S_IROTH | S_IWOTH | S_IXOTH);
2476  }
2477 
2478  if (((d->pmode == PermissionsMixed) || (d->pmode == PermissionsOnlyDirs)) &&
2479  (d->extraCheckbox->state() != TQButton::NoChange)) {
2480  andDirPermissions &= ~S_ISVTX;
2481  if (d->extraCheckbox->state() == TQButton::On)
2482  orDirPermissions |= S_ISVTX;
2483  }
2484 }
2485 
2486 void KFilePermissionsPropsPlugin::applyChanges()
2487 {
2488  mode_t orFilePermissions;
2489  mode_t orDirPermissions;
2490  mode_t andFilePermissions;
2491  mode_t andDirPermissions;
2492 
2493  if (!d->canChangePermissions)
2494  return;
2495 
2496  if (!d->isIrregular)
2497  getPermissionMasks(andFilePermissions,
2498  andDirPermissions,
2499  orFilePermissions,
2500  orDirPermissions);
2501  else {
2502  orFilePermissions = permissions;
2503  andFilePermissions = d->partialPermissions;
2504  orDirPermissions = permissions;
2505  andDirPermissions = d->partialPermissions;
2506  }
2507 
2508  TQString owner, group;
2509  if (usrEdit)
2510  owner = usrEdit->text();
2511  if (grpEdit)
2512  group = grpEdit->text();
2513  else if (grpCombo)
2514  group = grpCombo->currentText();
2515 
2516  if (owner == strOwner)
2517  owner = TQString::null; // no change
2518 
2519  if (group == strGroup)
2520  group = TQString::null;
2521 
2522  bool recursive = d->cbRecursive && d->cbRecursive->isChecked();
2523  bool permissionChange = false;
2524 
2525  KFileItemList files, dirs;
2526  KFileItemList items = properties->items();
2527  for (KFileItemListIterator it(items); it.current(); ++it) {
2528  if ((*it)->isDir()) {
2529  dirs.append(*it);
2530  if ((*it)->permissions() != (((*it)->permissions() & andDirPermissions) | orDirPermissions))
2531  permissionChange = true;
2532  }
2533  else if ((*it)->isFile()) {
2534  files.append(*it);
2535  if ((*it)->permissions() != (((*it)->permissions() & andFilePermissions) | orFilePermissions))
2536  permissionChange = true;
2537  }
2538  }
2539 
2540  const bool ACLChange = ( d->extendedACL != properties->item()->ACL() );
2541  const bool defaultACLChange = ( d->defaultACL != properties->item()->defaultACL() );
2542 
2543  if ( owner.isEmpty() && group.isEmpty() && !recursive
2544  && !permissionChange && !ACLChange && !defaultACLChange )
2545  return;
2546 
2547  TDEIO::Job * job;
2548  if (files.count() > 0) {
2549  job = TDEIO::chmod( files, orFilePermissions, ~andFilePermissions,
2550  owner, group, false );
2551  if ( ACLChange && d->fileSystemSupportsACLs )
2552  job->addMetaData( "ACL_STRING", d->extendedACL.isValid()?d->extendedACL.asString():"ACL_DELETE" );
2553  if ( defaultACLChange && d->fileSystemSupportsACLs )
2554  job->addMetaData( "DEFAULT_ACL_STRING", d->defaultACL.isValid()?d->defaultACL.asString():"ACL_DELETE" );
2555 
2556  connect( job, TQT_SIGNAL( result( TDEIO::Job * ) ),
2557  TQT_SLOT( slotChmodResult( TDEIO::Job * ) ) );
2558  // Wait for job
2559  TQWidget dummy(0,0,(WFlags)(WType_Dialog|WShowModal));
2560  tqt_enter_modal(&dummy);
2561  tqApp->enter_loop();
2562  tqt_leave_modal(&dummy);
2563  }
2564  if (dirs.count() > 0) {
2565  job = TDEIO::chmod( dirs, orDirPermissions, ~andDirPermissions,
2566  owner, group, recursive );
2567  if ( ACLChange && d->fileSystemSupportsACLs )
2568  job->addMetaData( "ACL_STRING", d->extendedACL.isValid()?d->extendedACL.asString():"ACL_DELETE" );
2569  if ( defaultACLChange && d->fileSystemSupportsACLs )
2570  job->addMetaData( "DEFAULT_ACL_STRING", d->defaultACL.isValid()?d->defaultACL.asString():"ACL_DELETE" );
2571 
2572  connect( job, TQT_SIGNAL( result( TDEIO::Job * ) ),
2573  TQT_SLOT( slotChmodResult( TDEIO::Job * ) ) );
2574  // Wait for job
2575  TQWidget dummy(0,0,(WFlags)(WType_Dialog|WShowModal));
2576  tqt_enter_modal(&dummy);
2577  tqApp->enter_loop();
2578  tqt_leave_modal(&dummy);
2579  }
2580 }
2581 
2582 void KFilePermissionsPropsPlugin::slotChmodResult( TDEIO::Job * job )
2583 {
2584  kdDebug(250) << "KFilePermissionsPropsPlugin::slotChmodResult" << endl;
2585  if (job->error())
2586  job->showErrorDialog( d->m_frame );
2587  // allow apply() to return
2588  tqApp->exit_loop();
2589 }
2590 
2591 
2592 
2593 
2594 class KURLPropsPlugin::KURLPropsPluginPrivate
2595 {
2596 public:
2597  KURLPropsPluginPrivate()
2598  {
2599  }
2600  ~KURLPropsPluginPrivate()
2601  {
2602  }
2603 
2604  TQFrame *m_frame;
2605 };
2606 
2607 KURLPropsPlugin::KURLPropsPlugin( KPropertiesDialog *_props )
2608  : KPropsDlgPlugin( _props )
2609 {
2610  d = new KURLPropsPluginPrivate;
2611  d->m_frame = properties->addPage(i18n("U&RL"));
2612  TQVBoxLayout *layout = new TQVBoxLayout(d->m_frame, 0, KDialog::spacingHint());
2613 
2614  TQLabel *l;
2615  l = new TQLabel( d->m_frame, "Label_1" );
2616  l->setText( i18n("URL:") );
2617  layout->addWidget(l);
2618 
2619  URLEdit = new KURLRequester( d->m_frame, "URL Requester" );
2620  layout->addWidget(URLEdit);
2621 
2622  TQString path = properties->kurl().path();
2623 
2624  TQFile f( path );
2625  if ( !f.open( IO_ReadOnly ) ) {
2626  return;
2627  }
2628  f.close();
2629 
2630  KSimpleConfig config( path );
2631  config.setDesktopGroup();
2632  URLStr = config.readPathEntry( "URL" );
2633 
2634  KFileItem * item = properties->item();
2635 
2636  if (item && item->mimetype().startsWith("media/builtin-")) {
2637  URLEdit->setEnabled(false);
2638  }
2639 
2640  if ( !URLStr.isNull() ) {
2641  URLEdit->setURL( URLStr );
2642  }
2643 
2644  connect( URLEdit, TQT_SIGNAL( textChanged( const TQString & ) ),
2645  this, TQT_SIGNAL( changed() ) );
2646 
2647  layout->addStretch (1);
2648 }
2649 
2650 KURLPropsPlugin::~KURLPropsPlugin()
2651 {
2652  delete d;
2653 }
2654 
2655 // TQString KURLPropsPlugin::tabName () const
2656 // {
2657 // return i18n ("U&RL");
2658 // }
2659 
2660 bool KURLPropsPlugin::supports( KFileItemList _items )
2661 {
2662  if ( _items.count() != 1 )
2663  return false;
2664  KFileItem * item = _items.first();
2665  // check if desktop file
2666  if ( !KPropsDlgPlugin::isDesktopFile( item ) )
2667  return false;
2668 
2669  // open file and check type
2670  KDesktopFile config( item->url().path(), true /* readonly */ );
2671  return config.hasLinkType();
2672 }
2673 
2674 void KURLPropsPlugin::applyChanges()
2675 {
2676  TQString path = properties->kurl().path();
2677  KFileItem * item = properties->item();
2678 
2679  if (item && item->mimetype().startsWith("media/builtin-")) {
2680  return;
2681  }
2682 
2683  TQFile f( path );
2684  if ( !f.open( IO_ReadWrite ) ) {
2685  KMessageBox::sorry( 0, i18n("<qt>Could not save properties. You do not have "
2686  "sufficient access to write to <b>%1</b>.</qt>").arg(path));
2687  return;
2688  }
2689  f.close();
2690 
2691  KSimpleConfig config( path );
2692  config.setDesktopGroup();
2693  config.writeEntry( "Type", TQString::fromLatin1("Link"));
2694  config.writePathEntry( "URL", URLEdit->url() );
2695  // Users can't create a Link .desktop file with a Name field,
2696  // but distributions can. Update the Name field in that case.
2697  if ( config.hasKey("Name") )
2698  {
2699  TQString nameStr = nameFromFileName(properties->kurl().fileName());
2700  config.writeEntry( "Name", nameStr );
2701  config.writeEntry( "Name", nameStr, true, false, true );
2702 
2703  }
2704 }
2705 
2706 
2707 /* ----------------------------------------------------
2708  *
2709  * KBindingPropsPlugin
2710  *
2711  * -------------------------------------------------- */
2712 
2713 class KBindingPropsPlugin::KBindingPropsPluginPrivate
2714 {
2715 public:
2716  KBindingPropsPluginPrivate()
2717  {
2718  }
2719  ~KBindingPropsPluginPrivate()
2720  {
2721  }
2722 
2723  TQFrame *m_frame;
2724 };
2725 
2726 KBindingPropsPlugin::KBindingPropsPlugin( KPropertiesDialog *_props ) : KPropsDlgPlugin( _props )
2727 {
2728  d = new KBindingPropsPluginPrivate;
2729  d->m_frame = properties->addPage(i18n("A&ssociation"));
2730  patternEdit = new KLineEdit( d->m_frame, "LineEdit_1" );
2731  commentEdit = new KLineEdit( d->m_frame, "LineEdit_2" );
2732  mimeEdit = new KLineEdit( d->m_frame, "LineEdit_3" );
2733 
2734  TQBoxLayout *mainlayout = new TQVBoxLayout(d->m_frame, 0, KDialog::spacingHint());
2735  TQLabel* tmpQLabel;
2736 
2737  tmpQLabel = new TQLabel( d->m_frame, "Label_1" );
2738  tmpQLabel->setText( i18n("Pattern ( example: *.html;*.htm )") );
2739  tmpQLabel->setMinimumSize(tmpQLabel->sizeHint());
2740  mainlayout->addWidget(tmpQLabel, 1);
2741 
2742  //patternEdit->setGeometry( 10, 40, 210, 30 );
2743  //patternEdit->setText( "" );
2744  patternEdit->setMaxLength( 512 );
2745  patternEdit->setMinimumSize( patternEdit->sizeHint() );
2746  patternEdit->setFixedHeight( fontHeight );
2747  mainlayout->addWidget(patternEdit, 1);
2748 
2749  tmpQLabel = new TQLabel( d->m_frame, "Label_2" );
2750  tmpQLabel->setText( i18n("Mime Type") );
2751  tmpQLabel->setMinimumSize(tmpQLabel->sizeHint());
2752  mainlayout->addWidget(tmpQLabel, 1);
2753 
2754  //mimeEdit->setGeometry( 10, 160, 210, 30 );
2755  mimeEdit->setMaxLength( 256 );
2756  mimeEdit->setMinimumSize( mimeEdit->sizeHint() );
2757  mimeEdit->setFixedHeight( fontHeight );
2758  mainlayout->addWidget(mimeEdit, 1);
2759 
2760  tmpQLabel = new TQLabel( d->m_frame, "Label_3" );
2761  tmpQLabel->setText( i18n("Comment") );
2762  tmpQLabel->setMinimumSize(tmpQLabel->sizeHint());
2763  mainlayout->addWidget(tmpQLabel, 1);
2764 
2765  //commentEdit->setGeometry( 10, 100, 210, 30 );
2766  commentEdit->setMaxLength( 256 );
2767  commentEdit->setMinimumSize( commentEdit->sizeHint() );
2768  commentEdit->setFixedHeight( fontHeight );
2769  mainlayout->addWidget(commentEdit, 1);
2770 
2771  cbAutoEmbed = new TQCheckBox( i18n("Left click previews"), d->m_frame, "cbAutoEmbed" );
2772  mainlayout->addWidget(cbAutoEmbed, 1);
2773 
2774  mainlayout->addStretch (10);
2775  mainlayout->activate();
2776 
2777  TQFile f( _props->kurl().path() );
2778  if ( !f.open( IO_ReadOnly ) )
2779  return;
2780  f.close();
2781 
2782  KSimpleConfig config( _props->kurl().path() );
2783  config.setDesktopGroup();
2784  TQString patternStr = config.readEntry( "Patterns" );
2785  TQString iconStr = config.readEntry( "Icon" );
2786  TQString commentStr = config.readEntry( "Comment" );
2787  m_sMimeStr = config.readEntry( "MimeType" );
2788 
2789  if ( !patternStr.isEmpty() )
2790  patternEdit->setText( patternStr );
2791  if ( !commentStr.isEmpty() )
2792  commentEdit->setText( commentStr );
2793  if ( !m_sMimeStr.isEmpty() )
2794  mimeEdit->setText( m_sMimeStr );
2795  cbAutoEmbed->setTristate();
2796  if ( config.hasKey( "X-TDE-AutoEmbed" ) )
2797  cbAutoEmbed->setChecked( config.readBoolEntry( "X-TDE-AutoEmbed" ) );
2798  else
2799  cbAutoEmbed->setNoChange();
2800 
2801  connect( patternEdit, TQT_SIGNAL( textChanged( const TQString & ) ),
2802  this, TQT_SIGNAL( changed() ) );
2803  connect( commentEdit, TQT_SIGNAL( textChanged( const TQString & ) ),
2804  this, TQT_SIGNAL( changed() ) );
2805  connect( mimeEdit, TQT_SIGNAL( textChanged( const TQString & ) ),
2806  this, TQT_SIGNAL( changed() ) );
2807  connect( cbAutoEmbed, TQT_SIGNAL( toggled( bool ) ),
2808  this, TQT_SIGNAL( changed() ) );
2809 }
2810 
2811 KBindingPropsPlugin::~KBindingPropsPlugin()
2812 {
2813  delete d;
2814 }
2815 
2816 // TQString KBindingPropsPlugin::tabName () const
2817 // {
2818 // return i18n ("A&ssociation");
2819 // }
2820 
2821 bool KBindingPropsPlugin::supports( KFileItemList _items )
2822 {
2823  if ( _items.count() != 1 )
2824  return false;
2825  KFileItem * item = _items.first();
2826  // check if desktop file
2827  if ( !KPropsDlgPlugin::isDesktopFile( item ) )
2828  return false;
2829 
2830  // open file and check type
2831  KDesktopFile config( item->url().path(), true /* readonly */ );
2832  return config.hasMimeTypeType();
2833 }
2834 
2835 void KBindingPropsPlugin::applyChanges()
2836 {
2837  TQString path = properties->kurl().path();
2838  TQFile f( path );
2839 
2840  if ( !f.open( IO_ReadWrite ) )
2841  {
2842  KMessageBox::sorry( 0, i18n("<qt>Could not save properties. You do not have "
2843  "sufficient access to write to <b>%1</b>.</qt>").arg(path));
2844  return;
2845  }
2846  f.close();
2847 
2848  KSimpleConfig config( path );
2849  config.setDesktopGroup();
2850  config.writeEntry( "Type", TQString::fromLatin1("MimeType") );
2851 
2852  config.writeEntry( "Patterns", patternEdit->text() );
2853  config.writeEntry( "Comment", commentEdit->text() );
2854  config.writeEntry( "Comment",
2855  commentEdit->text(), true, false, true ); // for compat
2856  config.writeEntry( "MimeType", mimeEdit->text() );
2857  if ( cbAutoEmbed->state() == TQButton::NoChange )
2858  config.deleteEntry( "X-TDE-AutoEmbed", false );
2859  else
2860  config.writeEntry( "X-TDE-AutoEmbed", cbAutoEmbed->isChecked() );
2861  config.sync();
2862 }
2863 
2864 /* ----------------------------------------------------
2865  *
2866  * KDevicePropsPlugin
2867  *
2868  * -------------------------------------------------- */
2869 
2870 class KDevicePropsPlugin::KDevicePropsPluginPrivate
2871 {
2872 public:
2873  KDevicePropsPluginPrivate()
2874  {
2875  }
2876  ~KDevicePropsPluginPrivate()
2877  {
2878  }
2879 
2880  TQFrame *m_frame;
2881  TQStringList mountpointlist;
2882  TQLabel *m_freeSpaceText;
2883  TQLabel *m_freeSpaceLabel;
2884  TQProgressBar *m_freeSpaceBar;
2885 };
2886 
2887 KDevicePropsPlugin::KDevicePropsPlugin( KPropertiesDialog *_props ) : KPropsDlgPlugin( _props )
2888 {
2889  d = new KDevicePropsPluginPrivate;
2890  d->m_frame = properties->addPage(i18n("De&vice"));
2891 
2892  TQStringList devices;
2893  KMountPoint::List mountPoints = KMountPoint::possibleMountPoints();
2894 
2895  for(KMountPoint::List::ConstIterator it = mountPoints.begin();
2896  it != mountPoints.end(); ++it)
2897  {
2898  KMountPoint *mp = *it;
2899  TQString mountPoint = mp->mountPoint();
2900  TQString device = mp->mountedFrom();
2901  kdDebug()<<"mountPoint :"<<mountPoint<<" device :"<<device<<" mp->mountType() :"<<mp->mountType()<<endl;
2902 
2903  if ((mountPoint != "-") && (mountPoint != "none") && !mountPoint.isEmpty()
2904  && device != "none")
2905  {
2906  devices.append( device + TQString::fromLatin1(" (")
2907  + mountPoint + TQString::fromLatin1(")") );
2908  m_devicelist.append(device);
2909  d->mountpointlist.append(mountPoint);
2910  }
2911  }
2912 
2913  TQGridLayout *layout = new TQGridLayout( d->m_frame, 0, 2, 0,
2914  KDialog::spacingHint());
2915  layout->setColStretch(1, 1);
2916 
2917  TQLabel* label;
2918  label = new TQLabel( d->m_frame );
2919  label->setText( devices.count() == 0 ?
2920  i18n("Device (/dev/fd0):") : // old style
2921  i18n("Device:") ); // new style (combobox)
2922  layout->addWidget(label, 0, 0);
2923 
2924  device = new TQComboBox( true, d->m_frame, "ComboBox_device" );
2925  device->insertStringList( devices );
2926  layout->addWidget(device, 0, 1);
2927  connect( device, TQT_SIGNAL( activated( int ) ),
2928  this, TQT_SLOT( slotActivated( int ) ) );
2929 
2930  readonly = new TQCheckBox( d->m_frame, "CheckBox_readonly" );
2931  readonly->setText( i18n("Read only") );
2932  layout->addWidget(readonly, 1, 1);
2933 
2934  label = new TQLabel( d->m_frame );
2935  label->setText( i18n("File system:") );
2936  layout->addWidget(label, 2, 0);
2937 
2938  TQLabel *fileSystem = new TQLabel( d->m_frame );
2939  layout->addWidget(fileSystem, 2, 1);
2940 
2941  label = new TQLabel( d->m_frame );
2942  label->setText( devices.count()==0 ?
2943  i18n("Mount point (/mnt/floppy):") : // old style
2944  i18n("Mount point:")); // new style (combobox)
2945  layout->addWidget(label, 3, 0);
2946 
2947  mountpoint = new TQLabel( d->m_frame, "LineEdit_mountpoint" );
2948 
2949  layout->addWidget(mountpoint, 3, 1);
2950 
2951  // show disk free
2952  d->m_freeSpaceText = new TQLabel(i18n("Free disk space:"), d->m_frame );
2953  layout->addWidget(d->m_freeSpaceText, 4, 0);
2954 
2955  d->m_freeSpaceLabel = new TQLabel( d->m_frame );
2956  layout->addWidget( d->m_freeSpaceLabel, 4, 1 );
2957 
2958  d->m_freeSpaceBar = new TQProgressBar( d->m_frame, "freeSpaceBar" );
2959  layout->addMultiCellWidget(d->m_freeSpaceBar, 5, 5, 0, 1);
2960 
2961  // we show it in the slot when we know the values
2962  d->m_freeSpaceText->hide();
2963  d->m_freeSpaceLabel->hide();
2964  d->m_freeSpaceBar->hide();
2965 
2966  KSeparator* sep = new KSeparator( KSeparator::HLine, d->m_frame);
2967  layout->addMultiCellWidget(sep, 6, 6, 0, 1);
2968 
2969  unmounted = new TDEIconButton( d->m_frame );
2970  int bsize = 66 + 2 * unmounted->style().pixelMetric(TQStyle::PM_ButtonMargin);
2971  unmounted->setFixedSize(bsize, bsize);
2972  unmounted->setIconType(TDEIcon::Desktop, TDEIcon::Device);
2973  layout->addWidget(unmounted, 7, 0);
2974 
2975  label = new TQLabel( i18n("Unmounted Icon"), d->m_frame );
2976  layout->addWidget(label, 7, 1);
2977 
2978  layout->setRowStretch(8, 1);
2979 
2980  TQString path( _props->kurl().path() );
2981 
2982  TQFile f( path );
2983  if ( !f.open( IO_ReadOnly ) )
2984  return;
2985  f.close();
2986 
2987  KSimpleConfig config( path );
2988  config.setDesktopGroup();
2989  TQString deviceStr = config.readEntry( "Dev" );
2990  TQString mountPointStr = config.readEntry( "MountPoint" );
2991  bool ro = config.readBoolEntry( "ReadOnly", false );
2992  TQString unmountedStr = config.readEntry( "UnmountIcon" );
2993 
2994  TQString fsType = config.readEntry("FSType");
2995  fileSystem->setText( (fsType.stripWhiteSpace() != "") ? i18n(fsType.local8Bit()) : "" );
2996 
2997  device->setEditText( deviceStr );
2998  if ( !deviceStr.isEmpty() ) {
2999  // Set default options for this device (first matching entry)
3000  int index = m_devicelist.findIndex(deviceStr);
3001  if (index != -1)
3002  {
3003  //kdDebug(250) << "found it " << index << endl;
3004  slotActivated( index );
3005  }
3006  }
3007 
3008  if ( !mountPointStr.isEmpty() )
3009  {
3010  mountpoint->setText( mountPointStr );
3011  updateInfo();
3012  }
3013 
3014  readonly->setChecked( ro );
3015 
3016  if ( unmountedStr.isEmpty() )
3017  unmountedStr = KMimeType::defaultMimeTypePtr()->KServiceType::icon(); // default icon
3018 
3019  unmounted->setIcon( unmountedStr );
3020 
3021  connect( device, TQT_SIGNAL( activated( int ) ),
3022  this, TQT_SIGNAL( changed() ) );
3023  connect( device, TQT_SIGNAL( textChanged( const TQString & ) ),
3024  this, TQT_SIGNAL( changed() ) );
3025  connect( readonly, TQT_SIGNAL( toggled( bool ) ),
3026  this, TQT_SIGNAL( changed() ) );
3027  connect( unmounted, TQT_SIGNAL( iconChanged( TQString ) ),
3028  this, TQT_SIGNAL( changed() ) );
3029 
3030  connect( device, TQT_SIGNAL( textChanged( const TQString & ) ),
3031  this, TQT_SLOT( slotDeviceChanged() ) );
3032 
3033  processLockouts();
3034 }
3035 
3036 KDevicePropsPlugin::~KDevicePropsPlugin()
3037 {
3038  delete d;
3039 }
3040 
3041 // TQString KDevicePropsPlugin::tabName () const
3042 // {
3043 // return i18n ("De&vice");
3044 // }
3045 
3046 void KDevicePropsPlugin::processLockouts()
3047 {
3048  if (device->currentText().stripWhiteSpace() != "")
3049  {
3050  properties->enableButtonOK(true);
3051  }
3052  else
3053  {
3054  properties->enableButtonOK(false);
3055  }
3056 }
3057 
3058 void KDevicePropsPlugin::updateInfo()
3059 {
3060  // we show it in the slot when we know the values
3061  d->m_freeSpaceText->hide();
3062  d->m_freeSpaceLabel->hide();
3063  d->m_freeSpaceBar->hide();
3064 
3065  if ( !mountpoint->text().isEmpty() )
3066  {
3067  KDiskFreeSp * job = new KDiskFreeSp;
3068  connect( job, TQT_SIGNAL( foundMountPoint( const unsigned long&, const unsigned long&,
3069  const unsigned long&, const TQString& ) ),
3070  this, TQT_SLOT( slotFoundMountPoint( const unsigned long&, const unsigned long&,
3071  const unsigned long&, const TQString& ) ) );
3072 
3073  job->readDF( mountpoint->text() );
3074  }
3075 
3076  processLockouts();
3077 }
3078 
3079 void KDevicePropsPlugin::slotActivated( int index )
3080 {
3081  // Update mountpoint so that it matches the device that was selected in the combo
3082  device->setEditText( m_devicelist[index] );
3083  mountpoint->setText( d->mountpointlist[index] );
3084 
3085  updateInfo();
3086 }
3087 
3088 void KDevicePropsPlugin::slotDeviceChanged()
3089 {
3090  // Update mountpoint so that it matches the typed device
3091  int index = m_devicelist.findIndex( device->currentText() );
3092  if ( index != -1 )
3093  mountpoint->setText( d->mountpointlist[index] );
3094  else
3095  mountpoint->setText( TQString::null );
3096 
3097  updateInfo();
3098 }
3099 
3100 void KDevicePropsPlugin::slotFoundMountPoint( const unsigned long& kBSize,
3101  const unsigned long& /*kBUsed*/,
3102  const unsigned long& kBAvail,
3103  const TQString& )
3104 {
3105  d->m_freeSpaceText->show();
3106  d->m_freeSpaceLabel->show();
3107 
3108  int percUsed = 100 - (int)(100.0 * kBAvail / kBSize);
3109 
3110  d->m_freeSpaceLabel->setText(
3111  // xgettext:no-c-format -- Don't warn about translating the %1 out of %2 part.
3112  i18n("Available space out of total partition size (percent used)", "%1 out of %2 (%3% used)")
3113  .arg(TDEIO::convertSizeFromKB(kBAvail))
3114  .arg(TDEIO::convertSizeFromKB(kBSize))
3115  .arg( 100 - (int)(100.0 * kBAvail / kBSize) ));
3116 
3117  d->m_freeSpaceBar->setProgress(percUsed, 100);
3118  d->m_freeSpaceBar->show();
3119 }
3120 
3121 bool KDevicePropsPlugin::supports( KFileItemList _items )
3122 {
3123  if ( _items.count() != 1 )
3124  return false;
3125  KFileItem * item = _items.first();
3126  // check if desktop file
3127  if ( !KPropsDlgPlugin::isDesktopFile( item ) )
3128  return false;
3129  // open file and check type
3130  KDesktopFile config( item->url().path(), true /* readonly */ );
3131  return config.hasDeviceType();
3132 }
3133 
3134 void KDevicePropsPlugin::applyChanges()
3135 {
3136  TQString path = properties->kurl().path();
3137  TQFile f( path );
3138  if ( !f.open( IO_ReadWrite ) )
3139  {
3140  KMessageBox::sorry( 0, i18n("<qt>Could not save properties. You do not have sufficient "
3141  "access to write to <b>%1</b>.</qt>").arg(path));
3142  return;
3143  }
3144  f.close();
3145 
3146  KSimpleConfig config( path );
3147  config.setDesktopGroup();
3148  config.writeEntry( "Type", TQString::fromLatin1("FSDevice") );
3149 
3150  config.writeEntry( "Dev", device->currentText() );
3151  config.writeEntry( "MountPoint", mountpoint->text() );
3152 
3153  config.writeEntry( "UnmountIcon", unmounted->icon() );
3154  kdDebug(250) << "unmounted->icon() = " << unmounted->icon() << endl;
3155 
3156  config.writeEntry( "ReadOnly", readonly->isChecked() );
3157 
3158  config.sync();
3159 }
3160 
3161 
3162 /* ----------------------------------------------------
3163  *
3164  * KDesktopPropsPlugin
3165  *
3166  * -------------------------------------------------- */
3167 
3168 
3169 KDesktopPropsPlugin::KDesktopPropsPlugin( KPropertiesDialog *_props )
3170  : KPropsDlgPlugin( _props )
3171 {
3172  TQFrame *frame = properties->addPage(i18n("&Application"));
3173  TQVBoxLayout *mainlayout = new TQVBoxLayout( frame, 0, KDialog::spacingHint() );
3174 
3175  w = new KPropertiesDesktopBase(frame);
3176  mainlayout->addWidget(w);
3177 
3178  bool bKDesktopMode = (TQCString(tqApp->name()) == "kdesktop"); // nasty heh?
3179 
3180  if (bKDesktopMode)
3181  {
3182  // Hide Name entry
3183  w->nameEdit->hide();
3184  w->nameLabel->hide();
3185  }
3186 
3187  w->pathEdit->setMode(KFile::Directory | KFile::LocalOnly);
3188  w->pathEdit->lineEdit()->setAcceptDrops(false);
3189 
3190  connect( w->nameEdit, TQT_SIGNAL( textChanged( const TQString & ) ), this, TQT_SIGNAL( changed() ) );
3191  connect( w->genNameEdit, TQT_SIGNAL( textChanged( const TQString & ) ), this, TQT_SIGNAL( changed() ) );
3192  connect( w->commentEdit, TQT_SIGNAL( textChanged( const TQString & ) ), this, TQT_SIGNAL( changed() ) );
3193  connect( w->commandEdit, TQT_SIGNAL( textChanged( const TQString & ) ), this, TQT_SIGNAL( changed() ) );
3194  connect( w->pathEdit, TQT_SIGNAL( textChanged( const TQString & ) ), this, TQT_SIGNAL( changed() ) );
3195 
3196  connect( w->browseButton, TQT_SIGNAL( clicked() ), this, TQT_SLOT( slotBrowseExec() ) );
3197  connect( w->addFiletypeButton, TQT_SIGNAL( clicked() ), this, TQT_SLOT( slotAddFiletype() ) );
3198  connect( w->delFiletypeButton, TQT_SIGNAL( clicked() ), this, TQT_SLOT( slotDelFiletype() ) );
3199  connect( w->advancedButton, TQT_SIGNAL( clicked() ), this, TQT_SLOT( slotAdvanced() ) );
3200 
3201  // now populate the page
3202  TQString path = _props->kurl().path();
3203  TQFile f( path );
3204  if ( !f.open( IO_ReadOnly ) )
3205  return;
3206  f.close();
3207 
3208  KDesktopFile config( path );
3209  TQString nameStr = config.readName();
3210  TQString genNameStr = config.readGenericName();
3211  TQString commentStr = config.readComment();
3212  TQString commandStr = config.readPathEntry( "Exec" );
3213  if (commandStr.left(12) == "ksystraycmd ")
3214  {
3215  commandStr.remove(0, 12);
3216  m_systrayBool = true;
3217  }
3218  else
3219  m_systrayBool = false;
3220 
3221  m_origCommandStr = commandStr;
3222  TQString pathStr = config.readPathEntry( "Path" );
3223  m_terminalBool = config.readBoolEntry( "Terminal" );
3224  m_terminalOptionStr = config.readEntry( "TerminalOptions" );
3225  m_suidBool = config.readBoolEntry( "X-TDE-SubstituteUID" ) || config.readBoolEntry( "X-KDE-SubstituteUID" );
3226  if( config.hasKey( "X-TDE-Username" ))
3227  m_suidUserStr = config.readEntry( "X-TDE-Username" );
3228  else
3229  m_suidUserStr = config.readEntry( "X-KDE-Username" );
3230  if( config.hasKey( "StartupNotify" ))
3231  m_startupBool = config.readBoolEntry( "StartupNotify", true );
3232  else
3233  m_startupBool = config.readBoolEntry( "X-TDE-StartupNotify", true );
3234  m_dcopServiceType = config.readEntry("X-DCOP-ServiceType").lower();
3235 
3236  TQStringList mimeTypes = config.readListEntry( "MimeType", ';' );
3237 
3238  if ( nameStr.isEmpty() || bKDesktopMode ) {
3239  // We'll use the file name if no name is specified
3240  // because we _need_ a Name for a valid file.
3241  // But let's do it in apply, not here, so that we pick up the right name.
3242  setDirty();
3243  }
3244  if ( !bKDesktopMode )
3245  w->nameEdit->setText(nameStr);
3246 
3247  w->genNameEdit->setText( genNameStr );
3248  w->commentEdit->setText( commentStr );
3249  w->commandEdit->setText( commandStr );
3250  w->pathEdit->lineEdit()->setText( pathStr );
3251  w->filetypeList->setAllColumnsShowFocus(true);
3252 
3253  KMimeType::Ptr defaultMimetype = KMimeType::defaultMimeTypePtr();
3254  for(TQStringList::ConstIterator it = mimeTypes.begin();
3255  it != mimeTypes.end(); )
3256  {
3257  KMimeType::Ptr p = KMimeType::mimeType(*it);
3258  ++it;
3259  TQString preference;
3260  if (it != mimeTypes.end())
3261  {
3262  bool numeric;
3263  (*it).toInt(&numeric);
3264  if (numeric)
3265  {
3266  preference = *it;
3267  ++it;
3268  }
3269  }
3270  if (p && (p != defaultMimetype))
3271  {
3272  new TQListViewItem(w->filetypeList, p->name(), p->comment(), preference);
3273  }
3274  }
3275 
3276 }
3277 
3278 KDesktopPropsPlugin::~KDesktopPropsPlugin()
3279 {
3280 }
3281 
3282 void KDesktopPropsPlugin::slotSelectMimetype()
3283 {
3284  TQListView *w = (TQListView*)sender();
3285  TQListViewItem *item = w->firstChild();
3286  while(item)
3287  {
3288  if (item->isSelected())
3289  w->setSelected(item, false);
3290  item = item->nextSibling();
3291  }
3292 }
3293 
3294 void KDesktopPropsPlugin::slotAddFiletype()
3295 {
3296  KDialogBase dlg(w, "KPropertiesMimetypes", true,
3297  i18n("Add File Type for %1").arg(properties->kurl().fileName()),
3298  KDialogBase::Ok|KDialogBase::Cancel, KDialogBase::Ok);
3299 
3300  KGuiItem okItem(i18n("&Add"), TQString::null /* no icon */,
3301  i18n("Add the selected file types to\nthe list of supported file types."),
3302  i18n("Add the selected file types to\nthe list of supported file types."));
3303  dlg.setButtonOK(okItem);
3304 
3305  KPropertiesMimetypeBase *mw = new KPropertiesMimetypeBase(&dlg);
3306 
3307  dlg.setMainWidget(mw);
3308 
3309  {
3310  mw->listView->setRootIsDecorated(true);
3311  mw->listView->setSelectionMode(TQListView::Extended);
3312  mw->listView->setAllColumnsShowFocus(true);
3313  mw->listView->setFullWidth(true);
3314  mw->listView->setMinimumSize(500,400);
3315 
3316  connect(mw->listView, TQT_SIGNAL(selectionChanged()),
3317  this, TQT_SLOT(slotSelectMimetype()));
3318  connect(mw->listView, TQT_SIGNAL(doubleClicked( TQListViewItem *, const TQPoint &, int )),
3319  &dlg, TQT_SLOT( slotOk()));
3320 
3321  TQMap<TQString,TQListViewItem*> majorMap;
3322  TQListViewItem *majorGroup;
3323  KMimeType::List mimetypes = KMimeType::allMimeTypes();
3324  TQValueListIterator<KMimeType::Ptr> it(mimetypes.begin());
3325  for (; it != mimetypes.end(); ++it) {
3326  TQString mimetype = (*it)->name();
3327  if (mimetype == KMimeType::defaultMimeType())
3328  continue;
3329  int index = mimetype.find("/");
3330  TQString maj = mimetype.left(index);
3331  TQString min = mimetype.mid(index+1);
3332 
3333  TQMapIterator<TQString,TQListViewItem*> mit = majorMap.find( maj );
3334  if ( mit == majorMap.end() ) {
3335  majorGroup = new TQListViewItem( mw->listView, maj );
3336  majorGroup->setExpandable(true);
3337  mw->listView->setOpen(majorGroup, true);
3338  majorMap.insert( maj, majorGroup );
3339  }
3340  else
3341  {
3342  majorGroup = mit.data();
3343  }
3344 
3345  TQListViewItem *item = new TQListViewItem(majorGroup, min, (*it)->comment());
3346  item->setPixmap(0, (*it)->pixmap(TDEIcon::Small, IconSize(TDEIcon::Small)));
3347  }
3348  TQMapIterator<TQString,TQListViewItem*> mit = majorMap.find( "all" );
3349  if ( mit != majorMap.end())
3350  {
3351  mw->listView->setCurrentItem(mit.data());
3352  mw->listView->ensureItemVisible(mit.data());
3353  }
3354  }
3355 
3356  if (dlg.exec() == KDialogBase::Accepted)
3357  {
3358  KMimeType::Ptr defaultMimetype = KMimeType::defaultMimeTypePtr();
3359  TQListViewItem *majorItem = mw->listView->firstChild();
3360  while(majorItem)
3361  {
3362  TQString major = majorItem->text(0);
3363 
3364  TQListViewItem *minorItem = majorItem->firstChild();
3365  while(minorItem)
3366  {
3367  if (minorItem->isSelected())
3368  {
3369  TQString mimetype = major + "/" + minorItem->text(0);
3370  KMimeType::Ptr p = KMimeType::mimeType(mimetype);
3371  if (p && (p != defaultMimetype))
3372  {
3373  mimetype = p->name();
3374  bool found = false;
3375  TQListViewItem *item = w->filetypeList->firstChild();
3376  while (item)
3377  {
3378  if (mimetype == item->text(0))
3379  {
3380  found = true;
3381  break;
3382  }
3383  item = item->nextSibling();
3384  }
3385  if (!found) {
3386  new TQListViewItem(w->filetypeList, p->name(), p->comment());
3387  emit changed();
3388  }
3389  }
3390  }
3391  minorItem = minorItem->nextSibling();
3392  }
3393 
3394  majorItem = majorItem->nextSibling();
3395  }
3396 
3397  }
3398 }
3399 
3400 void KDesktopPropsPlugin::slotDelFiletype()
3401 {
3402  delete w->filetypeList->currentItem();
3403  emit changed();
3404 }
3405 
3406 void KDesktopPropsPlugin::checkCommandChanged()
3407 {
3408  if (KRun::binaryName(w->commandEdit->text(), true) !=
3409  KRun::binaryName(m_origCommandStr, true))
3410  {
3411  TQString m_origCommandStr = w->commandEdit->text();
3412  m_dcopServiceType= TQString::null; // Reset
3413  }
3414 }
3415 
3416 void KDesktopPropsPlugin::applyChanges()
3417 {
3418  kdDebug(250) << "KDesktopPropsPlugin::applyChanges" << endl;
3419  TQString path = properties->kurl().path();
3420 
3421  TQFile f( path );
3422 
3423  if ( !f.open( IO_ReadWrite ) ) {
3424  KMessageBox::sorry( 0, i18n("<qt>Could not save properties. You do not have "
3425  "sufficient access to write to <b>%1</b>.</qt>").arg(path));
3426  return;
3427  }
3428  f.close();
3429 
3430  // If the command is changed we reset certain settings that are strongly
3431  // coupled to the command.
3432  checkCommandChanged();
3433 
3434  KSimpleConfig config( path );
3435  config.setDesktopGroup();
3436  config.writeEntry( "Type", TQString::fromLatin1("Application"));
3437  config.writeEntry( "Comment", w->commentEdit->text() );
3438  config.writeEntry( "Comment", w->commentEdit->text(), true, false, true ); // for compat
3439  config.writeEntry( "GenericName", w->genNameEdit->text() );
3440  config.writeEntry( "GenericName", w->genNameEdit->text(), true, false, true ); // for compat
3441 
3442  if (m_systrayBool)
3443  config.writePathEntry( "Exec", w->commandEdit->text().prepend("ksystraycmd ") );
3444  else
3445  config.writePathEntry( "Exec", w->commandEdit->text() );
3446  config.writePathEntry( "Path", w->pathEdit->lineEdit()->text() );
3447 
3448  // Write mimeTypes
3449  TQStringList mimeTypes;
3450  for( TQListViewItem *item = w->filetypeList->firstChild();
3451  item; item = item->nextSibling() )
3452  {
3453  TQString preference = item->text(2);
3454  mimeTypes.append(item->text(0));
3455  if (!preference.isEmpty())
3456  mimeTypes.append(preference);
3457  }
3458 
3459  config.writeEntry( "MimeType", mimeTypes, ';' );
3460 
3461  if ( !w->nameEdit->isHidden() ) {
3462  TQString nameStr = w->nameEdit->text();
3463  config.writeEntry( "Name", nameStr );
3464  config.writeEntry( "Name", nameStr, true, false, true );
3465  }
3466 
3467  config.writeEntry("Terminal", m_terminalBool);
3468  config.writeEntry("TerminalOptions", m_terminalOptionStr);
3469  config.writeEntry("X-TDE-SubstituteUID", m_suidBool);
3470  config.writeEntry("X-TDE-Username", m_suidUserStr);
3471  config.writeEntry("StartupNotify", m_startupBool);
3472  config.writeEntry("X-DCOP-ServiceType", m_dcopServiceType);
3473  config.sync();
3474 
3475  // KSycoca update needed?
3476  TQString sycocaPath = TDEGlobal::dirs()->relativeLocation("apps", path);
3477  bool updateNeeded = !sycocaPath.startsWith("/");
3478  if (!updateNeeded)
3479  {
3480  sycocaPath = TDEGlobal::dirs()->relativeLocation("xdgdata-apps", path);
3481  updateNeeded = !sycocaPath.startsWith("/");
3482  }
3483  if (updateNeeded)
3484  KService::rebuildKSycoca(w);
3485 }
3486 
3487 
3488 void KDesktopPropsPlugin::slotBrowseExec()
3489 {
3490  KURL f = KFileDialog::getOpenURL( TQString::null,
3491  TQString::null, w );
3492  if ( f.isEmpty() )
3493  return;
3494 
3495  if ( !f.isLocalFile()) {
3496  KMessageBox::sorry(w, i18n("Only executables on local file systems are supported."));
3497  return;
3498  }
3499 
3500  TQString path = f.path();
3501  KRun::shellQuote( path );
3502  w->commandEdit->setText( path );
3503 }
3504 
3505 void KDesktopPropsPlugin::slotAdvanced()
3506 {
3507  KDialogBase dlg(w, "KPropertiesDesktopAdv", true,
3508  i18n("Advanced Options for %1").arg(properties->kurl().fileName()),
3509  KDialogBase::Ok|KDialogBase::Cancel, KDialogBase::Ok);
3510  KPropertiesDesktopAdvBase *w = new KPropertiesDesktopAdvBase(&dlg);
3511 
3512  dlg.setMainWidget(w);
3513 
3514  // If the command is changed we reset certain settings that are strongly
3515  // coupled to the command.
3516  checkCommandChanged();
3517 
3518  // check to see if we use konsole if not do not add the nocloseonexit
3519  // because we don't know how to do this on other terminal applications
3520  TDEConfigGroup confGroup( TDEGlobal::config(), TQString::fromLatin1("General") );
3521  TQString preferredTerminal = confGroup.readPathEntry("TerminalApplication",
3522  TQString::fromLatin1("konsole"));
3523 
3524  bool terminalCloseBool = false;
3525 
3526  if (preferredTerminal == "konsole")
3527  {
3528  terminalCloseBool = (m_terminalOptionStr.contains( "--noclose" ) > 0);
3529  w->terminalCloseCheck->setChecked(terminalCloseBool);
3530  m_terminalOptionStr.replace( "--noclose", "");
3531  }
3532  else
3533  {
3534  w->terminalCloseCheck->hide();
3535  }
3536 
3537  w->terminalCheck->setChecked(m_terminalBool);
3538  w->terminalEdit->setText(m_terminalOptionStr);
3539  w->terminalCloseCheck->setEnabled(m_terminalBool);
3540  w->terminalEdit->setEnabled(m_terminalBool);
3541  w->terminalEditLabel->setEnabled(m_terminalBool);
3542 
3543  w->suidCheck->setChecked(m_suidBool);
3544  w->suidEdit->setText(m_suidUserStr);
3545  w->suidEdit->setEnabled(m_suidBool);
3546  w->suidEditLabel->setEnabled(m_suidBool);
3547 
3548  w->startupInfoCheck->setChecked(m_startupBool);
3549  w->systrayCheck->setChecked(m_systrayBool);
3550 
3551  if (m_dcopServiceType == "unique")
3552  w->dcopCombo->setCurrentItem(2);
3553  else if (m_dcopServiceType == "multi")
3554  w->dcopCombo->setCurrentItem(1);
3555  else if (m_dcopServiceType == "wait")
3556  w->dcopCombo->setCurrentItem(3);
3557  else
3558  w->dcopCombo->setCurrentItem(0);
3559 
3560  // Provide username completion up to 1000 users.
3561  TDECompletion *kcom = new TDECompletion;
3562  kcom->setOrder(TDECompletion::Sorted);
3563  struct passwd *pw;
3564  int i, maxEntries = 1000;
3565  setpwent();
3566  for (i=0; ((pw = getpwent()) != 0L) && (i < maxEntries); i++)
3567  kcom->addItem(TQString::fromLatin1(pw->pw_name));
3568  endpwent();
3569  if (i < maxEntries)
3570  {
3571  w->suidEdit->setCompletionObject(kcom, true);
3572  w->suidEdit->setAutoDeleteCompletionObject( true );
3573  w->suidEdit->setCompletionMode(TDEGlobalSettings::CompletionAuto);
3574  }
3575  else
3576  {
3577  delete kcom;
3578  }
3579 
3580  connect( w->terminalEdit, TQT_SIGNAL( textChanged( const TQString & ) ),
3581  this, TQT_SIGNAL( changed() ) );
3582  connect( w->terminalCloseCheck, TQT_SIGNAL( toggled( bool ) ),
3583  this, TQT_SIGNAL( changed() ) );
3584  connect( w->terminalCheck, TQT_SIGNAL( toggled( bool ) ),
3585  this, TQT_SIGNAL( changed() ) );
3586  connect( w->suidCheck, TQT_SIGNAL( toggled( bool ) ),
3587  this, TQT_SIGNAL( changed() ) );
3588  connect( w->suidEdit, TQT_SIGNAL( textChanged( const TQString & ) ),
3589  this, TQT_SIGNAL( changed() ) );
3590  connect( w->startupInfoCheck, TQT_SIGNAL( toggled( bool ) ),
3591  this, TQT_SIGNAL( changed() ) );
3592  connect( w->systrayCheck, TQT_SIGNAL( toggled( bool ) ),
3593  this, TQT_SIGNAL( changed() ) );
3594  connect( w->dcopCombo, TQT_SIGNAL( highlighted( int ) ),
3595  this, TQT_SIGNAL( changed() ) );
3596 
3597  if ( dlg.exec() == TQDialog::Accepted )
3598  {
3599  m_terminalOptionStr = w->terminalEdit->text().stripWhiteSpace();
3600  m_terminalBool = w->terminalCheck->isChecked();
3601  m_suidBool = w->suidCheck->isChecked();
3602  m_suidUserStr = w->suidEdit->text().stripWhiteSpace();
3603  m_startupBool = w->startupInfoCheck->isChecked();
3604  m_systrayBool = w->systrayCheck->isChecked();
3605 
3606  if (w->terminalCloseCheck->isChecked())
3607  {
3608  m_terminalOptionStr.append(" --noclose");
3609  }
3610 
3611  switch(w->dcopCombo->currentItem())
3612  {
3613  case 1: m_dcopServiceType = "multi"; break;
3614  case 2: m_dcopServiceType = "unique"; break;
3615  case 3: m_dcopServiceType = "wait"; break;
3616  default: m_dcopServiceType = "none"; break;
3617  }
3618  }
3619 }
3620 
3621 bool KDesktopPropsPlugin::supports( KFileItemList _items )
3622 {
3623  if ( _items.count() != 1 )
3624  return false;
3625  KFileItem * item = _items.first();
3626  // check if desktop file
3627  if ( !KPropsDlgPlugin::isDesktopFile( item ) )
3628  return false;
3629  // open file and check type
3630  KDesktopFile config( item->url().path(), true /* readonly */ );
3631  return config.hasApplicationType() && kapp->authorize("run_desktop_files") && kapp->authorize("shell_access");
3632 }
3633 
3634 void KPropertiesDialog::virtual_hook( int id, void* data )
3635 { KDialogBase::virtual_hook( id, data ); }
3636 
3637 void KPropsDlgPlugin::virtual_hook( int, void* )
3638 { /*BASE::virtual_hook( id, data );*/ }
3639 
3640 
3641 
3642 
3643 
3649 class KExecPropsPlugin::KExecPropsPluginPrivate
3650 {
3651 public:
3652  KExecPropsPluginPrivate()
3653  {
3654  }
3655  ~KExecPropsPluginPrivate()
3656  {
3657  }
3658 
3659  TQFrame *m_frame;
3660  TQCheckBox *nocloseonexitCheck;
3661 };
3662 
3663 KExecPropsPlugin::KExecPropsPlugin( KPropertiesDialog *_props )
3664  : KPropsDlgPlugin( _props )
3665 {
3666  d = new KExecPropsPluginPrivate;
3667  d->m_frame = properties->addPage(i18n("E&xecute"));
3668  TQVBoxLayout * mainlayout = new TQVBoxLayout( d->m_frame, 0,
3669  KDialog::spacingHint());
3670 
3671  // Now the widgets in the top layout
3672 
3673  TQLabel* l;
3674  l = new TQLabel( i18n( "Comman&d:" ), d->m_frame );
3675  mainlayout->addWidget(l);
3676 
3677  TQHBoxLayout * hlayout;
3678  hlayout = new TQHBoxLayout(KDialog::spacingHint());
3679  mainlayout->addLayout(hlayout);
3680 
3681  execEdit = new KLineEdit( d->m_frame );
3682  TQWhatsThis::add(execEdit,i18n(
3683  "Following the command, you can have several place holders which will be replaced "
3684  "with the actual values when the actual program is run:\n"
3685  "%f - a single file name\n"
3686  "%F - a list of files; use for applications that can open several local files at once\n"
3687  "%u - a single URL\n"
3688  "%U - a list of URLs\n"
3689  "%d - the folder of the file to open\n"
3690  "%D - a list of folders\n"
3691  "%i - the icon\n"
3692  "%m - the mini-icon\n"
3693  "%c - the caption"));
3694  hlayout->addWidget(execEdit, 1);
3695 
3696  l->setBuddy( execEdit );
3697 
3698  execBrowse = new TQPushButton( d->m_frame );
3699  execBrowse->setText( i18n("&Browse...") );
3700  hlayout->addWidget(execBrowse);
3701 
3702  // The groupbox about swallowing
3703  TQGroupBox* tmpQGroupBox;
3704  tmpQGroupBox = new TQGroupBox( i18n("Panel Embedding"), d->m_frame );
3705  tmpQGroupBox->setColumnLayout( 0, Qt::Horizontal );
3706 
3707  mainlayout->addWidget(tmpQGroupBox);
3708 
3709  TQGridLayout *grid = new TQGridLayout(tmpQGroupBox->layout(), 2, 2);
3710  grid->setSpacing( KDialog::spacingHint() );
3711  grid->setColStretch(1, 1);
3712 
3713  l = new TQLabel( i18n( "&Execute on click:" ), tmpQGroupBox );
3714  grid->addWidget(l, 0, 0);
3715 
3716  swallowExecEdit = new KLineEdit( tmpQGroupBox );
3717  grid->addWidget(swallowExecEdit, 0, 1);
3718 
3719  l->setBuddy( swallowExecEdit );
3720 
3721  l = new TQLabel( i18n( "&Window title:" ), tmpQGroupBox );
3722  grid->addWidget(l, 1, 0);
3723 
3724  swallowTitleEdit = new KLineEdit( tmpQGroupBox );
3725  grid->addWidget(swallowTitleEdit, 1, 1);
3726 
3727  l->setBuddy( swallowTitleEdit );
3728 
3729  // The groupbox about run in terminal
3730 
3731  tmpQGroupBox = new TQGroupBox( d->m_frame );
3732  tmpQGroupBox->setColumnLayout( 0, Qt::Horizontal );
3733 
3734  mainlayout->addWidget(tmpQGroupBox);
3735 
3736  grid = new TQGridLayout(tmpQGroupBox->layout(), 3, 2);
3737  grid->setSpacing( KDialog::spacingHint() );
3738  grid->setColStretch(1, 1);
3739 
3740  terminalCheck = new TQCheckBox( tmpQGroupBox );
3741  terminalCheck->setText( i18n("&Run in terminal") );
3742  grid->addMultiCellWidget(terminalCheck, 0, 0, 0, 1);
3743 
3744  // check to see if we use konsole if not do not add the nocloseonexit
3745  // because we don't know how to do this on other terminal applications
3746  TDEConfigGroup confGroup( TDEGlobal::config(), TQString::fromLatin1("General") );
3747  TQString preferredTerminal = confGroup.readPathEntry("TerminalApplication",
3748  TQString::fromLatin1("konsole"));
3749 
3750  int posOptions = 1;
3751  d->nocloseonexitCheck = 0L;
3752  if (preferredTerminal == "konsole")
3753  {
3754  posOptions = 2;
3755  d->nocloseonexitCheck = new TQCheckBox( tmpQGroupBox );
3756  d->nocloseonexitCheck->setText( i18n("Do not &close when command exits") );
3757  grid->addMultiCellWidget(d->nocloseonexitCheck, 1, 1, 0, 1);
3758  }
3759 
3760  terminalLabel = new TQLabel( i18n( "&Terminal options:" ), tmpQGroupBox );
3761  grid->addWidget(terminalLabel, posOptions, 0);
3762 
3763  terminalEdit = new KLineEdit( tmpQGroupBox );
3764  grid->addWidget(terminalEdit, posOptions, 1);
3765 
3766  terminalLabel->setBuddy( terminalEdit );
3767 
3768  // The groupbox about run with substituted uid.
3769 
3770  tmpQGroupBox = new TQGroupBox( d->m_frame );
3771  tmpQGroupBox->setColumnLayout( 0, Qt::Horizontal );
3772 
3773  mainlayout->addWidget(tmpQGroupBox);
3774 
3775  grid = new TQGridLayout(tmpQGroupBox->layout(), 2, 2);
3776  grid->setSpacing(KDialog::spacingHint());
3777  grid->setColStretch(1, 1);
3778 
3779  suidCheck = new TQCheckBox(tmpQGroupBox);
3780  suidCheck->setText(i18n("Ru&n as a different user"));
3781  grid->addMultiCellWidget(suidCheck, 0, 0, 0, 1);
3782 
3783  suidLabel = new TQLabel(i18n( "&Username:" ), tmpQGroupBox);
3784  grid->addWidget(suidLabel, 1, 0);
3785 
3786  suidEdit = new KLineEdit(tmpQGroupBox);
3787  grid->addWidget(suidEdit, 1, 1);
3788 
3789  suidLabel->setBuddy( suidEdit );
3790 
3791  mainlayout->addStretch(1);
3792 
3793  // now populate the page
3794  TQString path = _props->kurl().path();
3795  TQFile f( path );
3796  if ( !f.open( IO_ReadOnly ) )
3797  return;
3798  f.close();
3799 
3800  KSimpleConfig config( path );
3801  config.setDollarExpansion( false );
3802  config.setDesktopGroup();
3803  execStr = config.readPathEntry( "Exec" );
3804  swallowExecStr = config.readPathEntry( "SwallowExec" );
3805  swallowTitleStr = config.readEntry( "SwallowTitle" );
3806  termBool = config.readBoolEntry( "Terminal" );
3807  termOptionsStr = config.readEntry( "TerminalOptions" );
3808  suidBool = config.readBoolEntry( "X-TDE-SubstituteUID" );
3809  suidUserStr = config.readEntry( "X-TDE-Username" );
3810 
3811  if ( !swallowExecStr.isNull() )
3812  swallowExecEdit->setText( swallowExecStr );
3813  if ( !swallowTitleStr.isNull() )
3814  swallowTitleEdit->setText( swallowTitleStr );
3815 
3816  if ( !execStr.isNull() )
3817  execEdit->setText( execStr );
3818 
3819  if ( d->nocloseonexitCheck )
3820  {
3821  d->nocloseonexitCheck->setChecked( (termOptionsStr.contains( "--noclose" ) > 0) );
3822  termOptionsStr.replace( "--noclose", "");
3823  }
3824  if ( !termOptionsStr.isNull() )
3825  terminalEdit->setText( termOptionsStr );
3826 
3827  terminalCheck->setChecked( termBool );
3828  enableCheckedEdit();
3829 
3830  suidCheck->setChecked( suidBool );
3831  suidEdit->setText( suidUserStr );
3832  enableSuidEdit();
3833 
3834  // Provide username completion up to 1000 users.
3835  TDECompletion *kcom = new TDECompletion;
3836  kcom->setOrder(TDECompletion::Sorted);
3837  struct passwd *pw;
3838  int i, maxEntries = 1000;
3839  setpwent();
3840  for (i=0; ((pw = getpwent()) != 0L) && (i < maxEntries); i++)
3841  kcom->addItem(TQString::fromLatin1(pw->pw_name));
3842  endpwent();
3843  if (i < maxEntries)
3844  {
3845  suidEdit->setCompletionObject(kcom, true);
3846  suidEdit->setAutoDeleteCompletionObject( true );
3847  suidEdit->setCompletionMode(TDEGlobalSettings::CompletionAuto);
3848  }
3849  else
3850  {
3851  delete kcom;
3852  }
3853 
3854  connect( swallowExecEdit, TQT_SIGNAL( textChanged( const TQString & ) ),
3855  this, TQT_SIGNAL( changed() ) );
3856  connect( swallowTitleEdit, TQT_SIGNAL( textChanged( const TQString & ) ),
3857  this, TQT_SIGNAL( changed() ) );
3858  connect( execEdit, TQT_SIGNAL( textChanged( const TQString & ) ),
3859  this, TQT_SIGNAL( changed() ) );
3860  connect( terminalEdit, TQT_SIGNAL( textChanged( const TQString & ) ),
3861  this, TQT_SIGNAL( changed() ) );
3862  if (d->nocloseonexitCheck)
3863  connect( d->nocloseonexitCheck, TQT_SIGNAL( toggled( bool ) ),
3864  this, TQT_SIGNAL( changed() ) );
3865  connect( terminalCheck, TQT_SIGNAL( toggled( bool ) ),
3866  this, TQT_SIGNAL( changed() ) );
3867  connect( suidCheck, TQT_SIGNAL( toggled( bool ) ),
3868  this, TQT_SIGNAL( changed() ) );
3869  connect( suidEdit, TQT_SIGNAL( textChanged( const TQString & ) ),
3870  this, TQT_SIGNAL( changed() ) );
3871 
3872  connect( execBrowse, TQT_SIGNAL( clicked() ), this, TQT_SLOT( slotBrowseExec() ) );
3873  connect( terminalCheck, TQT_SIGNAL( clicked() ), this, TQT_SLOT( enableCheckedEdit() ) );
3874  connect( suidCheck, TQT_SIGNAL( clicked() ), this, TQT_SLOT( enableSuidEdit() ) );
3875 
3876 }
3877 
3878 KExecPropsPlugin::~KExecPropsPlugin()
3879 {
3880  delete d;
3881 }
3882 
3883 void KExecPropsPlugin::enableCheckedEdit()
3884 {
3885  bool checked = terminalCheck->isChecked();
3886  terminalLabel->setEnabled( checked );
3887  if (d->nocloseonexitCheck)
3888  d->nocloseonexitCheck->setEnabled( checked );
3889  terminalEdit->setEnabled( checked );
3890 }
3891 
3892 void KExecPropsPlugin::enableSuidEdit()
3893 {
3894  bool checked = suidCheck->isChecked();
3895  suidLabel->setEnabled( checked );
3896  suidEdit->setEnabled( checked );
3897 }
3898 
3899 bool KExecPropsPlugin::supports( KFileItemList _items )
3900 {
3901  if ( _items.count() != 1 )
3902  return false;
3903  KFileItem * item = _items.first();
3904  // check if desktop file
3905  if ( !KPropsDlgPlugin::isDesktopFile( item ) )
3906  return false;
3907  // open file and check type
3908  KDesktopFile config( item->url().path(), true /* readonly */ );
3909  return config.hasApplicationType() && kapp->authorize("run_desktop_files") && kapp->authorize("shell_access");
3910 }
3911 
3912 void KExecPropsPlugin::applyChanges()
3913 {
3914  kdDebug(250) << "KExecPropsPlugin::applyChanges" << endl;
3915  TQString path = properties->kurl().path();
3916 
3917  TQFile f( path );
3918 
3919  if ( !f.open( IO_ReadWrite ) ) {
3920  KMessageBox::sorry( 0, i18n("<qt>Could not save properties. You do not have "
3921  "sufficient access to write to <b>%1</b>.</qt>").arg(path));
3922  return;
3923  }
3924  f.close();
3925 
3926  KSimpleConfig config( path );
3927  config.setDesktopGroup();
3928  config.writeEntry( "Type", TQString::fromLatin1("Application"));
3929  config.writePathEntry( "Exec", execEdit->text() );
3930  config.writePathEntry( "SwallowExec", swallowExecEdit->text() );
3931  config.writeEntry( "SwallowTitle", swallowTitleEdit->text() );
3932  config.writeEntry( "Terminal", terminalCheck->isChecked() );
3933  TQString temp = terminalEdit->text();
3934  if (d->nocloseonexitCheck )
3935  if ( d->nocloseonexitCheck->isChecked() )
3936  temp += TQString::fromLatin1("--noclose ");
3937  temp = temp.stripWhiteSpace();
3938  config.writeEntry( "TerminalOptions", temp );
3939  config.writeEntry( "X-TDE-SubstituteUID", suidCheck->isChecked() );
3940  config.writeEntry( "X-TDE-Username", suidEdit->text() );
3941 }
3942 
3943 
3944 void KExecPropsPlugin::slotBrowseExec()
3945 {
3946  KURL f = KFileDialog::getOpenURL( TQString::null,
3947  TQString::null, d->m_frame );
3948  if ( f.isEmpty() )
3949  return;
3950 
3951  if ( !f.isLocalFile()) {
3952  KMessageBox::sorry(d->m_frame, i18n("Only executables on local file systems are supported."));
3953  return;
3954  }
3955 
3956  TQString path = f.path();
3957  KRun::shellQuote( path );
3958  execEdit->setText( path );
3959 }
3960 
3961 class TDEApplicationPropsPlugin::TDEApplicationPropsPluginPrivate
3962 {
3963 public:
3964  TDEApplicationPropsPluginPrivate()
3965  {
3966  m_kdesktopMode = TQCString(tqApp->name()) == "kdesktop"; // nasty heh?
3967  }
3968  ~TDEApplicationPropsPluginPrivate()
3969  {
3970  }
3971 
3972  TQFrame *m_frame;
3973  bool m_kdesktopMode;
3974 };
3975 
3976 TDEApplicationPropsPlugin::TDEApplicationPropsPlugin( KPropertiesDialog *_props )
3977  : KPropsDlgPlugin( _props )
3978 {
3979  d = new TDEApplicationPropsPluginPrivate;
3980  d->m_frame = properties->addPage(i18n("&Application"));
3981  TQVBoxLayout *toplayout = new TQVBoxLayout( d->m_frame, 0, KDialog::spacingHint());
3982 
3983  TQIconSet iconSet;
3984  TQPixmap pixMap;
3985 
3986  addExtensionButton = new TQPushButton( TQString::null, d->m_frame );
3987  iconSet = SmallIconSet( "back" );
3988  addExtensionButton->setIconSet( iconSet );
3989  pixMap = iconSet.pixmap( TQIconSet::Small, TQIconSet::Normal );
3990  addExtensionButton->setFixedSize( pixMap.width()+8, pixMap.height()+8 );
3991  connect( addExtensionButton, TQT_SIGNAL( clicked() ),
3992  TQT_SLOT( slotAddExtension() ) );
3993 
3994  delExtensionButton = new TQPushButton( TQString::null, d->m_frame );
3995  iconSet = SmallIconSet( "forward" );
3996  delExtensionButton->setIconSet( iconSet );
3997  delExtensionButton->setFixedSize( pixMap.width()+8, pixMap.height()+8 );
3998  connect( delExtensionButton, TQT_SIGNAL( clicked() ),
3999  TQT_SLOT( slotDelExtension() ) );
4000 
4001  TQLabel *l;
4002 
4003  TQGridLayout *grid = new TQGridLayout(2, 2);
4004  grid->setColStretch(1, 1);
4005  toplayout->addLayout(TQT_TQLAYOUT(grid));
4006 
4007  if ( d->m_kdesktopMode )
4008  {
4009  // in kdesktop the name field comes from the first tab
4010  nameEdit = 0L;
4011  }
4012  else
4013  {
4014  l = new TQLabel(i18n("Name:"), d->m_frame, "Label_4" );
4015  grid->addWidget(l, 0, 0);
4016 
4017  nameEdit = new KLineEdit( d->m_frame, "LineEdit_3" );
4018  grid->addWidget(nameEdit, 0, 1);
4019  }
4020 
4021  l = new TQLabel(i18n("Description:"), d->m_frame, "Label_5" );
4022  grid->addWidget(l, 1, 0);
4023 
4024  genNameEdit = new KLineEdit( d->m_frame, "LineEdit_4" );
4025  grid->addWidget(genNameEdit, 1, 1);
4026 
4027  l = new TQLabel(i18n("Comment:"), d->m_frame, "Label_3" );
4028  grid->addWidget(l, 2, 0);
4029 
4030  commentEdit = new KLineEdit( d->m_frame, "LineEdit_2" );
4031  grid->addWidget(commentEdit, 2, 1);
4032 
4033  l = new TQLabel(i18n("File types:"), d->m_frame);
4034  toplayout->addWidget(l, 0, AlignLeft);
4035 
4036  grid = new TQGridLayout(4, 3);
4037  grid->setColStretch(0, 1);
4038  grid->setColStretch(2, 1);
4039  grid->setRowStretch( 0, 1 );
4040  grid->setRowStretch( 3, 1 );
4041  toplayout->addLayout(TQT_TQLAYOUT(grid), 2);
4042 
4043  extensionsList = new TQListBox( d->m_frame );
4044  extensionsList->setSelectionMode( TQListBox::Extended );
4045  grid->addMultiCellWidget(extensionsList, 0, 3, 0, 0);
4046 
4047  grid->addWidget(addExtensionButton, 1, 1);
4048  grid->addWidget(delExtensionButton, 2, 1);
4049 
4050  availableExtensionsList = new TQListBox( d->m_frame );
4051  availableExtensionsList->setSelectionMode( TQListBox::Extended );
4052  grid->addMultiCellWidget(availableExtensionsList, 0, 3, 2, 2);
4053 
4054  TQString path = properties->kurl().path() ;
4055  TQFile f( path );
4056  if ( !f.open( IO_ReadOnly ) )
4057  return;
4058  f.close();
4059 
4060  KDesktopFile config( path );
4061  TQString commentStr = config.readComment();
4062  TQString genNameStr = config.readGenericName();
4063 
4064  TQStringList selectedTypes = config.readListEntry( "X-TDE-ServiceTypes" );
4065  // For compatibility with KDE 1.x
4066  selectedTypes += config.readListEntry( "MimeType", ';' );
4067 
4068  TQString nameStr = config.readName();
4069  if ( nameStr.isEmpty() || d->m_kdesktopMode ) {
4070  // We'll use the file name if no name is specified
4071  // because we _need_ a Name for a valid file.
4072  // But let's do it in apply, not here, so that we pick up the right name.
4073  setDirty();
4074  }
4075 
4076  commentEdit->setText( commentStr );
4077  genNameEdit->setText( genNameStr );
4078  if ( nameEdit )
4079  nameEdit->setText( nameStr );
4080 
4081  selectedTypes.sort();
4082  TQStringList::Iterator sit = selectedTypes.begin();
4083  for( ; sit != selectedTypes.end(); ++sit ) {
4084  if ( !((*sit).isEmpty()) )
4085  extensionsList->insertItem( *sit );
4086  }
4087 
4088  KMimeType::List mimeTypes = KMimeType::allMimeTypes();
4089  TQValueListIterator<KMimeType::Ptr> it2 = mimeTypes.begin();
4090  for ( ; it2 != mimeTypes.end(); ++it2 )
4091  addMimeType ( (*it2)->name() );
4092 
4093  updateButton();
4094 
4095  connect( extensionsList, TQT_SIGNAL( highlighted( int ) ),
4096  this, TQT_SLOT( updateButton() ) );
4097  connect( availableExtensionsList, TQT_SIGNAL( highlighted( int ) ),
4098  this, TQT_SLOT( updateButton() ) );
4099 
4100  connect( addExtensionButton, TQT_SIGNAL( clicked() ),
4101  this, TQT_SIGNAL( changed() ) );
4102  connect( delExtensionButton, TQT_SIGNAL( clicked() ),
4103  this, TQT_SIGNAL( changed() ) );
4104  if ( nameEdit )
4105  connect( nameEdit, TQT_SIGNAL( textChanged( const TQString & ) ),
4106  this, TQT_SIGNAL( changed() ) );
4107  connect( commentEdit, TQT_SIGNAL( textChanged( const TQString & ) ),
4108  this, TQT_SIGNAL( changed() ) );
4109  connect( genNameEdit, TQT_SIGNAL( textChanged( const TQString & ) ),
4110  this, TQT_SIGNAL( changed() ) );
4111  connect( availableExtensionsList, TQT_SIGNAL( selected( int ) ),
4112  this, TQT_SIGNAL( changed() ) );
4113  connect( extensionsList, TQT_SIGNAL( selected( int ) ),
4114  this, TQT_SIGNAL( changed() ) );
4115 }
4116 
4117 TDEApplicationPropsPlugin::~TDEApplicationPropsPlugin()
4118 {
4119  delete d;
4120 }
4121 
4122 // TQString TDEApplicationPropsPlugin::tabName () const
4123 // {
4124 // return i18n ("&Application");
4125 // }
4126 
4127 void TDEApplicationPropsPlugin::updateButton()
4128 {
4129  addExtensionButton->setEnabled(availableExtensionsList->currentItem()>-1);
4130  delExtensionButton->setEnabled(extensionsList->currentItem()>-1);
4131 }
4132 
4133 void TDEApplicationPropsPlugin::addMimeType( const TQString & name )
4134 {
4135  // Add a mimetype to the list of available mime types if not in the extensionsList
4136 
4137  bool insert = true;
4138 
4139  for ( uint i = 0; i < extensionsList->count(); i++ )
4140  if ( extensionsList->text( i ) == name )
4141  insert = false;
4142 
4143  if ( insert )
4144  {
4145  availableExtensionsList->insertItem( name );
4146  availableExtensionsList->sort();
4147  }
4148 }
4149 
4150 bool TDEApplicationPropsPlugin::supports( KFileItemList _items )
4151 {
4152  // same constraints as KExecPropsPlugin : desktop file with Type = Application
4153  return KExecPropsPlugin::supports( _items );
4154 }
4155 
4156 void TDEApplicationPropsPlugin::applyChanges()
4157 {
4158  TQString path = properties->kurl().path();
4159 
4160  TQFile f( path );
4161 
4162  if ( !f.open( IO_ReadWrite ) ) {
4163  KMessageBox::sorry( 0, i18n("<qt>Could not save properties. You do not "
4164  "have sufficient access to write to <b>%1</b>.</qt>").arg(path));
4165  return;
4166  }
4167  f.close();
4168 
4169  KSimpleConfig config( path );
4170  config.setDesktopGroup();
4171  config.writeEntry( "Type", TQString::fromLatin1("Application"));
4172  config.writeEntry( "Comment", commentEdit->text() );
4173  config.writeEntry( "Comment", commentEdit->text(), true, false, true ); // for compat
4174  config.writeEntry( "GenericName", genNameEdit->text() );
4175  config.writeEntry( "GenericName", genNameEdit->text(), true, false, true ); // for compat
4176 
4177  TQStringList selectedTypes;
4178  for ( uint i = 0; i < extensionsList->count(); i++ )
4179  selectedTypes.append( extensionsList->text( i ) );
4180 
4181  config.writeEntry( "MimeType", selectedTypes, ';' );
4182  config.writeEntry( "X-TDE-ServiceTypes", "" );
4183  // hmm, actually it should probably be the contrary (but see also typeslistitem.cpp)
4184 
4185  TQString nameStr = nameEdit ? nameEdit->text() : TQString::null;
4186  if ( nameStr.isEmpty() ) // nothing entered, or widget not existing at all (kdesktop mode)
4187  nameStr = nameFromFileName(properties->kurl().fileName());
4188 
4189  config.writeEntry( "Name", nameStr );
4190  config.writeEntry( "Name", nameStr, true, false, true );
4191 
4192  config.sync();
4193 }
4194 
4195 void TDEApplicationPropsPlugin::slotAddExtension()
4196 {
4197  TQListBoxItem *item = availableExtensionsList->firstItem();
4198  TQListBoxItem *nextItem;
4199 
4200  while ( item )
4201  {
4202  nextItem = item->next();
4203 
4204  if ( item->isSelected() )
4205  {
4206  extensionsList->insertItem( item->text() );
4207  availableExtensionsList->removeItem( availableExtensionsList->index( item ) );
4208  }
4209 
4210  item = nextItem;
4211  }
4212 
4213  extensionsList->sort();
4214  updateButton();
4215 }
4216 
4217 void TDEApplicationPropsPlugin::slotDelExtension()
4218 {
4219  TQListBoxItem *item = extensionsList->firstItem();
4220  TQListBoxItem *nextItem;
4221 
4222  while ( item )
4223  {
4224  nextItem = item->next();
4225 
4226  if ( item->isSelected() )
4227  {
4228  availableExtensionsList->insertItem( item->text() );
4229  extensionsList->removeItem( extensionsList->index( item ) );
4230  }
4231 
4232  item = nextItem;
4233  }
4234 
4235  availableExtensionsList->sort();
4236  updateButton();
4237 }
4238 
4239 
4240 
4241 #include "kpropertiesdialog.moc"
KURLRequester::url
TQString url() const
Definition: kurlrequester.cpp:268
KURLPropsPlugin::KURLPropsPlugin
KURLPropsPlugin(KPropertiesDialog *_props)
Constructor.
Definition: kpropertiesdialog.cpp:2607
KPropertiesDialog::slotCancel
virtual void slotCancel()
Called when the user presses 'Cancel'.
Definition: kpropertiesdialog.cpp:439
TDEIconButton::setIconType
void setIconType(TDEIcon::Group group, TDEIcon::Context context, bool user=false)
Sets the icon group and context.
Definition: kicondialog.cpp:711
KPropertiesDialog::applied
void applied()
This signal is emitted when the properties changes are applied (for example, with the OK button) ...
KFileMetaPropsPlugin::supports
static bool supports(KFileItemList _items)
Tests whether the file specified by _items has a 'MetaInfo' plugin.
Definition: kmetaprops.cpp:245
KPropsDlgPlugin::isDesktopFile
static bool isDesktopFile(KFileItem *_item)
Convenience method for most ::supports methods.
Definition: kpropertiesdialog.cpp:620
KURLPropsPlugin
Used to edit the files containing [Desktop Entry] URL=....
Definition: kpropertiesdialog.h:657
TDEIconButton::icon
TQString icon() const
Returns the name of the selected icon.
Definition: kicondialog.h:309
KPropertiesDialog::items
KFileItemList items() const
Definition: kpropertiesdialog.h:267
KPropertiesDialog::kurl
const KURL & kurl() const
The URL of the file that has its properties being displayed.
Definition: kpropertiesdialog.h:253
KExecPropsPlugin::KExecPropsPlugin
KExecPropsPlugin(KPropertiesDialog *_props)
Constructor.
Definition: kpropertiesdialog.cpp:3663
KFilePropsPlugin::applyChanges
virtual void applyChanges()
Applies all changes made.
Definition: kpropertiesdialog.cpp:1331
KPropertiesDialog::saveAs
void saveAs(const KURL &oldUrl, KURL &newUrl)
Emitted before changes to oldUrl are saved as newUrl.
KPreviewPropsPlugin::supports
static bool supports(KFileItemList _items)
Tests whether a preview for the first item should be shown.
Definition: kpreviewprops.cpp:65
KFileMetaPropsPlugin
Definition: kmetaprops.h:31
KDesktopPropsPlugin::applyChanges
virtual void applyChanges()
Applies all changes to the file.
Definition: kpropertiesdialog.cpp:3416
KPropertiesDialog::abortApplying
void abortApplying()
To abort applying changes.
Definition: kpropertiesdialog.cpp:588
TDEIconButton::setStrictIconSize
void setStrictIconSize(bool b)
Sets a strict icon size policy for allowed icons.
Definition: kicondialog.cpp:691
KPropertiesDialog::showDialog
static bool showDialog(KFileItem *item, TQWidget *parent=0, const char *name=0, bool modal=false)
Immediately displays a Properties dialog using constructor with the same parameters.
Definition: kpropertiesdialog.cpp:289
KFilePropsPlugin::postApplyChanges
void postApplyChanges()
Called after all plugins applied their changes.
Definition: kpropertiesdialog.cpp:1511
KPropertiesDialog::insertPlugin
void insertPlugin(KPropsDlgPlugin *plugin)
Adds a "3rd party" properties plugin to the dialog.
Definition: kpropertiesdialog.cpp:373
KPropertiesDialog::rename
void rename(const TQString &_name)
Renames the item to the specified name.
Definition: kpropertiesdialog.cpp:565
TDEIO
Definition: kimagefilepreview.h:26
KFilePermissionsPropsPlugin::supports
static bool supports(KFileItemList _items)
Tests whether the file specified by _items needs a 'Permissions' plugin.
Definition: kpropertiesdialog.cpp:2228
KFilePermissionsPropsPlugin::applyChanges
virtual void applyChanges()
Applies all changes to the file.
Definition: kpropertiesdialog.cpp:2486
TDEIconButton
A pushbutton for choosing an icon.
Definition: kicondialog.h:257
KFilePermissionsPropsPlugin::KFilePermissionsPropsPlugin
KFilePermissionsPropsPlugin(KPropertiesDialog *_props)
Constructor.
Definition: kpropertiesdialog.cpp:1579
KFileDialog::getOpenURL
static KURL getOpenURL(const TQString &startDir=TQString::null, const TQString &filter=TQString::null, TQWidget *parent=0, const TQString &caption=TQString::null)
Creates a modal file dialog and returns the selected URL or an empty string if none was chosen...
Definition: tdefiledialog.cpp:1375
TDEApplicationPropsPlugin::applyChanges
virtual void applyChanges()
Applies all changes to the file.
Definition: kpropertiesdialog.cpp:4156
KDiskFreeSp::readDF
int readDF(const TQString &mountPoint)
Call this to fire a search on the disk usage information for mountPoint.
Definition: kdiskfreesp.cpp:80
KBindingPropsPlugin
Used to edit the files containing [Desktop Entry] Type=MimeType.
Definition: kpropertiesdialog.h:692
KPropertiesDialog::propertiesClosed
void propertiesClosed()
This signal is emitted when the Properties Dialog is closed (for example, with OK or Cancel buttons) ...
KPropsDlgPlugin::KPropsDlgPlugin
KPropsDlgPlugin(KPropertiesDialog *_props)
Constructor To insert tabs into the properties dialog, use the add methods provided by KDialogBase (t...
Definition: kpropertiesdialog.cpp:606
KFilePermissionsPropsPlugin
'Permissions' plugin In this plugin you can modify permissions and change the owner of a file...
Definition: kpropertiesdialog.h:571
KBindingPropsPlugin::KBindingPropsPlugin
KBindingPropsPlugin(KPropertiesDialog *_props)
Constructor.
Definition: kpropertiesdialog.cpp:2726
TDEIconButton::setIconSize
void setIconSize(int size)
Sets the size of the icon to be shown / selected.
Definition: kicondialog.cpp:701
KPropertiesDialog::currentDir
const KURL & currentDir() const
If the dialog is being built from a template, this method returns the current directory.
Definition: kpropertiesdialog.h:287
KPreviewPropsPlugin
Definition: kpreviewprops.h:32
KPropertiesDialog::showFileSharingPage
void showFileSharingPage()
Shows the page that was previously set by setFileSharingPage(), or does nothing if no page was set ye...
Definition: kpropertiesdialog.cpp:337
KDevicePropsPlugin::applyChanges
virtual void applyChanges()
Applies all changes to the file.
Definition: kpropertiesdialog.cpp:3134
TDEApplicationPropsPlugin::TDEApplicationPropsPlugin
TDEApplicationPropsPlugin(KPropertiesDialog *_props)
Constructor.
Definition: kpropertiesdialog.cpp:3976
KPropertiesDialog::defaultName
const TQString & defaultName() const
If the dialog is being built from a template, this method returns the default name.
Definition: kpropertiesdialog.h:295
KFilePropsPlugin
'General' plugin This plugin displays the name of the file, its size and access times.
Definition: kpropertiesdialog.h:495
KPropertiesDialog::slotOk
virtual void slotOk()
Called when the user presses 'Ok'.
Definition: kpropertiesdialog.cpp:394
KURLRequester::setURL
void setURL(const TQString &url)
Sets the url in the lineedit to url.
Definition: kurlrequester.cpp:235
KDirSize
Computes a directory size (similar to "du", but doesn't give the same results since we simply sum up ...
Definition: kdirsize.h:30
KPropertiesDialog::updateUrl
void updateUrl(const KURL &_newUrl)
Updates the item URL (either called by rename or because a global apps/mimelnk desktop file is being ...
Definition: kpropertiesdialog.cpp:541
KPropertiesDialog
The main properties dialog class.
Definition: kpropertiesdialog.h:70
TDEIconButton::setIcon
void setIcon(const TQString &icon)
Sets the button's initial icon.
Definition: kicondialog.cpp:718
KFileSharePropsPlugin
This plugin provides a page to KPropsDlg, showing the "file sharing" options.
Definition: tdefilesharedlg.h:33
KPropsDlgPlugin::changed
void changed()
Emit this signal when the user changed anything in the plugin's tabs.
KDesktopPropsPlugin
Used to edit the files containing [Desktop Entry] Type=Application.
Definition: kpropertiesdialog.h:775
KURLRequester
This class is a widget showing a lineedit and a button, which invokes a filedialog.
Definition: kurlrequester.h:56
KFilePropsPlugin::KFilePropsPlugin
KFilePropsPlugin(KPropertiesDialog *_props)
Constructor.
Definition: kpropertiesdialog.cpp:701
KPropertiesDialog::setFileNameReadOnly
void setFileNameReadOnly(bool ro)
Call this to make the filename lineedit readonly, to prevent the user from renaming the file...
Definition: kpropertiesdialog.cpp:349
KPropertiesDialog::canceled
void canceled()
This signal is emitted when the properties changes are aborted (for example, with the Cancel button) ...
KDevicePropsPlugin
Properties plugin for device .desktop files.
Definition: kpropertiesdialog.h:722
KPropertiesDialog::item
KFileItem * item()
Definition: kpropertiesdialog.h:262
KDirSize::dirSizeJob
static KDirSize * dirSizeJob(const KURL &directory)
Asynchronous method.
Definition: kdirsize.cpp:126
KURLPropsPlugin::applyChanges
virtual void applyChanges()
Applies all changes to the file.
Definition: kpropertiesdialog.cpp:2674
KBindingPropsPlugin::applyChanges
virtual void applyChanges()
Applies all changes to the file.
Definition: kpropertiesdialog.cpp:2835
KDiskFreeSp
This class parses the output of "df" to find the disk usage information for a given partition (mount ...
Definition: kdiskfreesp.h:40
KExecPropsPlugin::applyChanges
virtual void applyChanges()
Applies all changes to the file.
Definition: kpropertiesdialog.cpp:3912
KPropsDlgPlugin
A Plugin in the Properties dialog This is an abstract class.
Definition: kpropertiesdialog.h:437
KPropsDlgPlugin::applyChanges
virtual void applyChanges()
Applies all changes to the file.
Definition: kpropertiesdialog.cpp:665
KDesktopPropsPlugin::KDesktopPropsPlugin
KDesktopPropsPlugin(KPropertiesDialog *_props)
Constructor.
Definition: kpropertiesdialog.cpp:3169
KPropertiesDialog::KPropertiesDialog
KPropertiesDialog(KFileItem *item, TQWidget *parent=0L, const char *name=0L, bool modal=false, bool autoShow=true)
Brings up a Properties dialog, as shown above.
Definition: kpropertiesdialog.cpp:174
KPropertiesDialog::~KPropertiesDialog
virtual ~KPropertiesDialog()
Cleans up the properties dialog and frees any associated resources, including the dialog itself...
Definition: kpropertiesdialog.cpp:367
KPropsDlgPlugin::properties
KPropertiesDialog * properties
Pointer to the dialog.
Definition: kpropertiesdialog.h:480
KPropertiesDialog::canDisplay
static bool canDisplay(KFileItemList _items)
Determine whether there are any property pages available for the given file items.
Definition: kpropertiesdialog.cpp:381
KFilePropsPlugin::supports
static bool supports(KFileItemList _items)
Tests whether the files specified by _items need a 'General' plugin.
Definition: kpropertiesdialog.cpp:1322
KPropertiesDialog::setFileSharingPage
void setFileSharingPage(TQWidget *page)
Sets the file sharing page.
Definition: kpropertiesdialog.cpp:344

tdeio/tdefile

Skip menu "tdeio/tdefile"
  • Main Page
  • Class Hierarchy
  • Alphabetical List
  • Class List
  • File List
  • Class Members
  • Related Pages

tdeio/tdefile

Skip menu "tdeio/tdefile"
  • arts
  • dcop
  • dnssd
  • interfaces
  •   kspeech
  •     interface
  •     library
  •   tdetexteditor
  • kate
  • kded
  • kdoctools
  • kimgio
  • kjs
  • libtdemid
  • libtdescreensaver
  •     tdecore
  • tdeabc
  • tdecmshell
  • tdecore
  • tdefx
  • tdehtml
  • tdeinit
  • tdeio
  •   bookmarks
  •   httpfilter
  •   kpasswdserver
  •   kssl
  • tdeioslave
  •   http
  •   tdefile
  •   tdeio
  •   tdeioexec
  • tdemdi
  •   tdemdi
  • tdenewstuff
  • tdeparts
  • tdeprint
  • tderandr
  • tderesources
  • tdespell2
  • tdesu
  • tdeui
  • tdeunittest
  • tdeutils
  • tdewallet
Generated for tdeio/tdefile by doxygen 1.8.8
This website is maintained by Timothy Pearson.