• 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 ( aPartialPermissions & fperm[row][col] )
2097  {
2098  cb->setTristate();
2099  if( d->canChangePermissions ) {
2100  allDisable = false;
2101  }
2102  cb->setNoChange();
2103  }
2104  else if (d->cbRecursive && d->cbRecursive->isChecked())
2105  cb->setTristate();
2106 
2107  cb->setEnabled( d->canChangePermissions );
2108  gl->addWidget (cb, row+2, col+1);
2109  switch(col) {
2110  case 0:
2111  TQWhatsThis::add(cb, readWhatsThis);
2112  break;
2113  case 1:
2114  TQWhatsThis::add(cb, writeWhatsThis);
2115  break;
2116  case 2:
2117  TQWhatsThis::add(cb, execWhatsThis);
2118  break;
2119  case 3:
2120  switch(row) {
2121  case 0:
2122  TQWhatsThis::add(cb, setUidWhatsThis);
2123  break;
2124  case 1:
2125  TQWhatsThis::add(cb, setGidWhatsThis);
2126  break;
2127  case 2:
2128  TQWhatsThis::add(cb, stickyWhatsThis);
2129  break;
2130  }
2131  break;
2132  }
2133  }
2134  }
2135  gl->setColStretch(6, 10);
2136 
2137 #ifdef USE_POSIX_ACL
2138  KACLEditWidget *extendedACLs = 0;
2139 
2140  // FIXME make it work with partial entries
2141  if ( properties->items().count() == 1 ) {
2142  TQCString pathCString = TQFile::encodeName( properties->item()->url().path() );
2143  d->fileSystemSupportsACLs = fileSystemSupportsACL( pathCString );
2144  }
2145  if ( d->fileSystemSupportsACLs ) {
2146  std::for_each( theNotSpecials.begin(), theNotSpecials.end(), std::mem_fun( &TQWidget::hide ) );
2147  extendedACLs = new KACLEditWidget( mainVBox );
2148  if ( d->extendedACL.isValid() && d->extendedACL.isExtended() )
2149  extendedACLs->setACL( d->extendedACL );
2150  else
2151  extendedACLs->setACL( KACL( aPermissions ) );
2152 
2153  if ( d->defaultACL.isValid() )
2154  extendedACLs->setDefaultACL( d->defaultACL );
2155 
2156  if ( properties->items().first()->isDir() )
2157  extendedACLs->setAllowDefaults( true );
2158  if ( !d->canChangePermissions )
2159  extendedACLs->setReadOnly( true );
2160 
2161  }
2162 #endif
2163  if ( allDisable ) {
2164  dlg.enableButtonOK( false );
2165  }
2166 
2167  if (dlg.exec() != KDialogBase::Accepted)
2168  return;
2169 
2170  mode_t andPermissions = mode_t(~0);
2171  mode_t orPermissions = 0;
2172  for (int row = 0; row < 3; ++row)
2173  for (int col = 0; col < 4; ++col) {
2174  switch (cba[row][col]->state())
2175  {
2176  case TQCheckBox::On:
2177  orPermissions |= fperm[row][col];
2178  //fall through
2179  case TQCheckBox::Off:
2180  andPermissions &= ~fperm[row][col];
2181  break;
2182  default: // NoChange
2183  break;
2184  }
2185  }
2186 
2187  d->isIrregular = false;
2188  KFileItemList items = properties->items();
2189  for (KFileItemListIterator it(items); it.current(); ++it) {
2190  if (isIrregular(((*it)->permissions() & andPermissions) | orPermissions,
2191  (*it)->isDir(), (*it)->isLink())) {
2192  d->isIrregular = true;
2193  break;
2194  }
2195  }
2196 
2197  permissions = orPermissions;
2198  d->partialPermissions = andPermissions;
2199 
2200 #ifdef USE_POSIX_ACL
2201  // override with the acls, if present
2202  if ( extendedACLs ) {
2203  d->extendedACL = extendedACLs->getACL();
2204  d->defaultACL = extendedACLs->getDefaultACL();
2205  d->hasExtendedACL = d->extendedACL.isExtended() || d->defaultACL.isValid();
2206  permissions = d->extendedACL.basePermissions();
2207  permissions |= ( andPermissions | orPermissions ) & ( S_ISUID|S_ISGID|S_ISVTX );
2208  }
2209 #endif
2210 
2211  updateAccessControls();
2212  emit changed();
2213 }
2214 
2215 // TQString KFilePermissionsPropsPlugin::tabName () const
2216 // {
2217 // return i18n ("&Permissions");
2218 // }
2219 
2220 KFilePermissionsPropsPlugin::~KFilePermissionsPropsPlugin()
2221 {
2222  delete d;
2223 }
2224 
2225 bool KFilePermissionsPropsPlugin::supports( KFileItemList _items )
2226 {
2227  KFileItemList::const_iterator it = _items.constBegin();
2228  for ( ; it != _items.constEnd(); ++it ) {
2229  KFileItem *item = *it;
2230  if( !item->user().isEmpty() || !item->group().isEmpty() )
2231  return true;
2232  }
2233  return false;
2234 }
2235 
2236 // sets a combo box in the Access Control frame
2237 void KFilePermissionsPropsPlugin::setComboContent(TQComboBox *combo, PermissionsTarget target,
2238  mode_t permissions, mode_t partial) {
2239  combo->clear();
2240  if (d->pmode == PermissionsOnlyLinks) {
2241  combo->insertItem(i18n("Link"));
2242  combo->setCurrentItem(0);
2243  return;
2244  }
2245 
2246  mode_t tMask = permissionsMasks[target];
2247  int textIndex;
2248  for (textIndex = 0; standardPermissions[textIndex] != (mode_t)-1; textIndex++)
2249  if ((standardPermissions[textIndex]&tMask) == (permissions&tMask&(UniRead|UniWrite)))
2250  break;
2251  Q_ASSERT(standardPermissions[textIndex] != (mode_t)-1); // must not happen, would be irreglar
2252 
2253  for (int i = 0; permissionsTexts[(int)d->pmode][i]; i++)
2254  combo->insertItem(i18n(permissionsTexts[(int)d->pmode][i]));
2255 
2256  if (partial & tMask & ~UniExec) {
2257  combo->insertItem(i18n("Varying (No Change)"));
2258  combo->setCurrentItem(3);
2259  }
2260  else
2261  combo->setCurrentItem(textIndex);
2262 }
2263 
2264 // permissions are irregular if they cant be displayed in a combo box.
2265 bool KFilePermissionsPropsPlugin::isIrregular(mode_t permissions, bool isDir, bool isLink) {
2266  if (isLink) // links are always ok
2267  return false;
2268 
2269  mode_t p = permissions;
2270  if (p & (S_ISUID | S_ISGID)) // setuid/setgid -> irregular
2271  return true;
2272  if (isDir) {
2273  p &= ~S_ISVTX; // ignore sticky on dirs
2274 
2275  // check supported flag combinations
2276  mode_t p0 = p & UniOwner;
2277  if ((p0 != 0) && (p0 != (S_IRUSR | S_IXUSR)) && (p0 != UniOwner))
2278  return true;
2279  p0 = p & UniGroup;
2280  if ((p0 != 0) && (p0 != (S_IRGRP | S_IXGRP)) && (p0 != UniGroup))
2281  return true;
2282  p0 = p & UniOthers;
2283  if ((p0 != 0) && (p0 != (S_IROTH | S_IXOTH)) && (p0 != UniOthers))
2284  return true;
2285  return false;
2286  }
2287  if (p & S_ISVTX) // sticky on file -> irregular
2288  return true;
2289 
2290  // check supported flag combinations
2291  mode_t p0 = p & UniOwner;
2292  bool usrXPossible = !p0; // true if this file could be an executable
2293  if (p0 & S_IXUSR) {
2294  if ((p0 == S_IXUSR) || (p0 == (S_IWUSR | S_IXUSR)))
2295  return true;
2296  usrXPossible = true;
2297  }
2298  else if (p0 == S_IWUSR)
2299  return true;
2300 
2301  p0 = p & UniGroup;
2302  bool grpXPossible = !p0; // true if this file could be an executable
2303  if (p0 & S_IXGRP) {
2304  if ((p0 == S_IXGRP) || (p0 == (S_IWGRP | S_IXGRP)))
2305  return true;
2306  grpXPossible = true;
2307  }
2308  else if (p0 == S_IWGRP)
2309  return true;
2310  if (p0 == 0)
2311  grpXPossible = true;
2312 
2313  p0 = p & UniOthers;
2314  bool othXPossible = !p0; // true if this file could be an executable
2315  if (p0 & S_IXOTH) {
2316  if ((p0 == S_IXOTH) || (p0 == (S_IWOTH | S_IXOTH)))
2317  return true;
2318  othXPossible = true;
2319  }
2320  else if (p0 == S_IWOTH)
2321  return true;
2322 
2323  // check that there either all targets are executable-compatible, or none
2324  return (p & UniExec) && !(usrXPossible && grpXPossible && othXPossible);
2325 }
2326 
2327 // enables/disabled the widgets in the Access Control frame
2328 void KFilePermissionsPropsPlugin::enableAccessControls(bool enable) {
2329  d->ownerPermCombo->setEnabled(enable);
2330  d->groupPermCombo->setEnabled(enable);
2331  d->othersPermCombo->setEnabled(enable);
2332  if (d->extraCheckbox)
2333  d->extraCheckbox->setEnabled(enable);
2334  if ( d->cbRecursive )
2335  d->cbRecursive->setEnabled(enable);
2336 }
2337 
2338 // updates all widgets in the Access Control frame
2339 void KFilePermissionsPropsPlugin::updateAccessControls() {
2340  setComboContent(d->ownerPermCombo, PermissionsOwner,
2341  permissions, d->partialPermissions);
2342  setComboContent(d->groupPermCombo, PermissionsGroup,
2343  permissions, d->partialPermissions);
2344  setComboContent(d->othersPermCombo, PermissionsOthers,
2345  permissions, d->partialPermissions);
2346 
2347  switch(d->pmode) {
2348  case PermissionsOnlyLinks:
2349  enableAccessControls(false);
2350  break;
2351  case PermissionsOnlyFiles:
2352  enableAccessControls(d->canChangePermissions && !d->isIrregular && !d->hasExtendedACL);
2353  if (d->canChangePermissions)
2354  d->explanationLabel->setText(d->isIrregular || d->hasExtendedACL ?
2355  i18n("This file uses advanced permissions",
2356  "These files use advanced permissions.",
2357  properties->items().count()) : "");
2358  if (d->partialPermissions & UniExec) {
2359  d->extraCheckbox->setTristate();
2360  d->extraCheckbox->setNoChange();
2361  }
2362  else {
2363  d->extraCheckbox->setTristate(false);
2364  d->extraCheckbox->setChecked(permissions & UniExec);
2365  }
2366  break;
2367  case PermissionsOnlyDirs:
2368  enableAccessControls(d->canChangePermissions && !d->isIrregular && !d->hasExtendedACL);
2369  // if this is a dir, and we can change permissions, don't dis-allow
2370  // recursive, we can do that for ACL setting.
2371  if ( d->cbRecursive )
2372  d->cbRecursive->setEnabled( d->canChangePermissions && !d->isIrregular );
2373 
2374  if (d->canChangePermissions)
2375  d->explanationLabel->setText(d->isIrregular || d->hasExtendedACL ?
2376  i18n("This folder uses advanced permissions.",
2377  "These folders use advanced permissions.",
2378  properties->items().count()) : "");
2379  if (d->partialPermissions & S_ISVTX) {
2380  d->extraCheckbox->setTristate();
2381  d->extraCheckbox->setNoChange();
2382  }
2383  else {
2384  d->extraCheckbox->setTristate(false);
2385  d->extraCheckbox->setChecked(permissions & S_ISVTX);
2386  }
2387  break;
2388  case PermissionsMixed:
2389  enableAccessControls(d->canChangePermissions && !d->isIrregular && !d->hasExtendedACL);
2390  if (d->canChangePermissions)
2391  d->explanationLabel->setText(d->isIrregular || d->hasExtendedACL ?
2392  i18n("These files use advanced permissions.") : "");
2393  break;
2394  if (d->partialPermissions & S_ISVTX) {
2395  d->extraCheckbox->setTristate();
2396  d->extraCheckbox->setNoChange();
2397  }
2398  else {
2399  d->extraCheckbox->setTristate(false);
2400  d->extraCheckbox->setChecked(permissions & S_ISVTX);
2401  }
2402  break;
2403  }
2404 }
2405 
2406 // gets masks for files and dirs from the Access Control frame widgets
2407 void KFilePermissionsPropsPlugin::getPermissionMasks(mode_t &andFilePermissions,
2408  mode_t &andDirPermissions,
2409  mode_t &orFilePermissions,
2410  mode_t &orDirPermissions) {
2411  andFilePermissions = mode_t(~UniSpecial);
2412  andDirPermissions = mode_t(~(S_ISUID|S_ISGID));
2413  orFilePermissions = 0;
2414  orDirPermissions = 0;
2415  if (d->isIrregular)
2416  return;
2417 
2418  mode_t m = standardPermissions[d->ownerPermCombo->currentItem()];
2419  if (m != (mode_t) -1) {
2420  orFilePermissions |= m & UniOwner;
2421  if ((m & UniOwner) &&
2422  ((d->pmode == PermissionsMixed) ||
2423  ((d->pmode == PermissionsOnlyFiles) && (d->extraCheckbox->state() == TQButton::NoChange))))
2424  andFilePermissions &= ~(S_IRUSR | S_IWUSR);
2425  else {
2426  andFilePermissions &= ~(S_IRUSR | S_IWUSR | S_IXUSR);
2427  if ((m & S_IRUSR) && (d->extraCheckbox->state() == TQButton::On))
2428  orFilePermissions |= S_IXUSR;
2429  }
2430 
2431  orDirPermissions |= m & UniOwner;
2432  if (m & S_IRUSR)
2433  orDirPermissions |= S_IXUSR;
2434  andDirPermissions &= ~(S_IRUSR | S_IWUSR | S_IXUSR);
2435  }
2436 
2437  m = standardPermissions[d->groupPermCombo->currentItem()];
2438  if (m != (mode_t) -1) {
2439  orFilePermissions |= m & UniGroup;
2440  if ((m & UniGroup) &&
2441  ((d->pmode == PermissionsMixed) ||
2442  ((d->pmode == PermissionsOnlyFiles) && (d->extraCheckbox->state() == TQButton::NoChange))))
2443  andFilePermissions &= ~(S_IRGRP | S_IWGRP);
2444  else {
2445  andFilePermissions &= ~(S_IRGRP | S_IWGRP | S_IXGRP);
2446  if ((m & S_IRGRP) && (d->extraCheckbox->state() == TQButton::On))
2447  orFilePermissions |= S_IXGRP;
2448  }
2449 
2450  orDirPermissions |= m & UniGroup;
2451  if (m & S_IRGRP)
2452  orDirPermissions |= S_IXGRP;
2453  andDirPermissions &= ~(S_IRGRP | S_IWGRP | S_IXGRP);
2454  }
2455 
2456  m = standardPermissions[d->othersPermCombo->currentItem()];
2457  if (m != (mode_t) -1) {
2458  orFilePermissions |= m & UniOthers;
2459  if ((m & UniOthers) &&
2460  ((d->pmode == PermissionsMixed) ||
2461  ((d->pmode == PermissionsOnlyFiles) && (d->extraCheckbox->state() == TQButton::NoChange))))
2462  andFilePermissions &= ~(S_IROTH | S_IWOTH);
2463  else {
2464  andFilePermissions &= ~(S_IROTH | S_IWOTH | S_IXOTH);
2465  if ((m & S_IROTH) && (d->extraCheckbox->state() == TQButton::On))
2466  orFilePermissions |= S_IXOTH;
2467  }
2468 
2469  orDirPermissions |= m & UniOthers;
2470  if (m & S_IROTH)
2471  orDirPermissions |= S_IXOTH;
2472  andDirPermissions &= ~(S_IROTH | S_IWOTH | S_IXOTH);
2473  }
2474 
2475  if (((d->pmode == PermissionsMixed) || (d->pmode == PermissionsOnlyDirs)) &&
2476  (d->extraCheckbox->state() != TQButton::NoChange)) {
2477  andDirPermissions &= ~S_ISVTX;
2478  if (d->extraCheckbox->state() == TQButton::On)
2479  orDirPermissions |= S_ISVTX;
2480  }
2481 }
2482 
2483 void KFilePermissionsPropsPlugin::applyChanges()
2484 {
2485  mode_t orFilePermissions;
2486  mode_t orDirPermissions;
2487  mode_t andFilePermissions;
2488  mode_t andDirPermissions;
2489 
2490  if (!d->canChangePermissions)
2491  return;
2492 
2493  if (!d->isIrregular)
2494  getPermissionMasks(andFilePermissions,
2495  andDirPermissions,
2496  orFilePermissions,
2497  orDirPermissions);
2498  else {
2499  orFilePermissions = permissions;
2500  andFilePermissions = d->partialPermissions;
2501  orDirPermissions = permissions;
2502  andDirPermissions = d->partialPermissions;
2503  }
2504 
2505  TQString owner, group;
2506  if (usrEdit)
2507  owner = usrEdit->text();
2508  if (grpEdit)
2509  group = grpEdit->text();
2510  else if (grpCombo)
2511  group = grpCombo->currentText();
2512 
2513  if (owner == strOwner)
2514  owner = TQString::null; // no change
2515 
2516  if (group == strGroup)
2517  group = TQString::null;
2518 
2519  bool recursive = d->cbRecursive && d->cbRecursive->isChecked();
2520  bool permissionChange = false;
2521 
2522  KFileItemList files, dirs;
2523  KFileItemList items = properties->items();
2524  for (KFileItemListIterator it(items); it.current(); ++it) {
2525  if ((*it)->isDir()) {
2526  dirs.append(*it);
2527  if ((*it)->permissions() != (((*it)->permissions() & andDirPermissions) | orDirPermissions))
2528  permissionChange = true;
2529  }
2530  else if ((*it)->isFile()) {
2531  files.append(*it);
2532  if ((*it)->permissions() != (((*it)->permissions() & andFilePermissions) | orFilePermissions))
2533  permissionChange = true;
2534  }
2535  }
2536 
2537  const bool ACLChange = ( d->extendedACL != properties->item()->ACL() );
2538  const bool defaultACLChange = ( d->defaultACL != properties->item()->defaultACL() );
2539 
2540  if ( owner.isEmpty() && group.isEmpty() && !recursive
2541  && !permissionChange && !ACLChange && !defaultACLChange )
2542  return;
2543 
2544  TDEIO::Job * job;
2545  if (files.count() > 0) {
2546  job = TDEIO::chmod( files, orFilePermissions, ~andFilePermissions,
2547  owner, group, false );
2548  if ( ACLChange && d->fileSystemSupportsACLs )
2549  job->addMetaData( "ACL_STRING", d->extendedACL.isValid()?d->extendedACL.asString():"ACL_DELETE" );
2550  if ( defaultACLChange && d->fileSystemSupportsACLs )
2551  job->addMetaData( "DEFAULT_ACL_STRING", d->defaultACL.isValid()?d->defaultACL.asString():"ACL_DELETE" );
2552 
2553  connect( job, TQT_SIGNAL( result( TDEIO::Job * ) ),
2554  TQT_SLOT( slotChmodResult( TDEIO::Job * ) ) );
2555  // Wait for job
2556  TQWidget dummy(0,0,(WFlags)(WType_Dialog|WShowModal));
2557  tqt_enter_modal(&dummy);
2558  tqApp->enter_loop();
2559  tqt_leave_modal(&dummy);
2560  }
2561  if (dirs.count() > 0) {
2562  job = TDEIO::chmod( dirs, orDirPermissions, ~andDirPermissions,
2563  owner, group, recursive );
2564  if ( ACLChange && d->fileSystemSupportsACLs )
2565  job->addMetaData( "ACL_STRING", d->extendedACL.isValid()?d->extendedACL.asString():"ACL_DELETE" );
2566  if ( defaultACLChange && d->fileSystemSupportsACLs )
2567  job->addMetaData( "DEFAULT_ACL_STRING", d->defaultACL.isValid()?d->defaultACL.asString():"ACL_DELETE" );
2568 
2569  connect( job, TQT_SIGNAL( result( TDEIO::Job * ) ),
2570  TQT_SLOT( slotChmodResult( TDEIO::Job * ) ) );
2571  // Wait for job
2572  TQWidget dummy(0,0,(WFlags)(WType_Dialog|WShowModal));
2573  tqt_enter_modal(&dummy);
2574  tqApp->enter_loop();
2575  tqt_leave_modal(&dummy);
2576  }
2577 }
2578 
2579 void KFilePermissionsPropsPlugin::slotChmodResult( TDEIO::Job * job )
2580 {
2581  kdDebug(250) << "KFilePermissionsPropsPlugin::slotChmodResult" << endl;
2582  if (job->error())
2583  job->showErrorDialog( d->m_frame );
2584  // allow apply() to return
2585  tqApp->exit_loop();
2586 }
2587 
2588 
2589 
2590 
2591 class KURLPropsPlugin::KURLPropsPluginPrivate
2592 {
2593 public:
2594  KURLPropsPluginPrivate()
2595  {
2596  }
2597  ~KURLPropsPluginPrivate()
2598  {
2599  }
2600 
2601  TQFrame *m_frame;
2602 };
2603 
2604 KURLPropsPlugin::KURLPropsPlugin( KPropertiesDialog *_props )
2605  : KPropsDlgPlugin( _props )
2606 {
2607  d = new KURLPropsPluginPrivate;
2608  d->m_frame = properties->addPage(i18n("U&RL"));
2609  TQVBoxLayout *layout = new TQVBoxLayout(d->m_frame, 0, KDialog::spacingHint());
2610 
2611  TQLabel *l;
2612  l = new TQLabel( d->m_frame, "Label_1" );
2613  l->setText( i18n("URL:") );
2614  layout->addWidget(l);
2615 
2616  URLEdit = new KURLRequester( d->m_frame, "URL Requester" );
2617  layout->addWidget(URLEdit);
2618 
2619  TQString path = properties->kurl().path();
2620 
2621  TQFile f( path );
2622  if ( !f.open( IO_ReadOnly ) ) {
2623  return;
2624  }
2625  f.close();
2626 
2627  KSimpleConfig config( path );
2628  config.setDesktopGroup();
2629  URLStr = config.readPathEntry( "URL" );
2630 
2631  KFileItem * item = properties->item();
2632 
2633  if (item && item->mimetype().startsWith("media/builtin-")) {
2634  URLEdit->setEnabled(false);
2635  }
2636 
2637  if ( !URLStr.isNull() ) {
2638  URLEdit->setURL( URLStr );
2639  }
2640 
2641  connect( URLEdit, TQT_SIGNAL( textChanged( const TQString & ) ),
2642  this, TQT_SIGNAL( changed() ) );
2643 
2644  layout->addStretch (1);
2645 }
2646 
2647 KURLPropsPlugin::~KURLPropsPlugin()
2648 {
2649  delete d;
2650 }
2651 
2652 // TQString KURLPropsPlugin::tabName () const
2653 // {
2654 // return i18n ("U&RL");
2655 // }
2656 
2657 bool KURLPropsPlugin::supports( KFileItemList _items )
2658 {
2659  if ( _items.count() != 1 )
2660  return false;
2661  KFileItem * item = _items.first();
2662  // check if desktop file
2663  if ( !KPropsDlgPlugin::isDesktopFile( item ) )
2664  return false;
2665 
2666  // open file and check type
2667  KDesktopFile config( item->url().path(), true /* readonly */ );
2668  return config.hasLinkType();
2669 }
2670 
2671 void KURLPropsPlugin::applyChanges()
2672 {
2673  TQString path = properties->kurl().path();
2674  KFileItem * item = properties->item();
2675 
2676  if (item && item->mimetype().startsWith("media/builtin-")) {
2677  return;
2678  }
2679 
2680  TQFile f( path );
2681  if ( !f.open( IO_ReadWrite ) ) {
2682  KMessageBox::sorry( 0, i18n("<qt>Could not save properties. You do not have "
2683  "sufficient access to write to <b>%1</b>.</qt>").arg(path));
2684  return;
2685  }
2686  f.close();
2687 
2688  KSimpleConfig config( path );
2689  config.setDesktopGroup();
2690  config.writeEntry( "Type", TQString::fromLatin1("Link"));
2691  config.writePathEntry( "URL", URLEdit->url() );
2692  // Users can't create a Link .desktop file with a Name field,
2693  // but distributions can. Update the Name field in that case.
2694  if ( config.hasKey("Name") )
2695  {
2696  TQString nameStr = nameFromFileName(properties->kurl().fileName());
2697  config.writeEntry( "Name", nameStr );
2698  config.writeEntry( "Name", nameStr, true, false, true );
2699 
2700  }
2701 }
2702 
2703 
2704 /* ----------------------------------------------------
2705  *
2706  * KBindingPropsPlugin
2707  *
2708  * -------------------------------------------------- */
2709 
2710 class KBindingPropsPlugin::KBindingPropsPluginPrivate
2711 {
2712 public:
2713  KBindingPropsPluginPrivate()
2714  {
2715  }
2716  ~KBindingPropsPluginPrivate()
2717  {
2718  }
2719 
2720  TQFrame *m_frame;
2721 };
2722 
2723 KBindingPropsPlugin::KBindingPropsPlugin( KPropertiesDialog *_props ) : KPropsDlgPlugin( _props )
2724 {
2725  d = new KBindingPropsPluginPrivate;
2726  d->m_frame = properties->addPage(i18n("A&ssociation"));
2727  patternEdit = new KLineEdit( d->m_frame, "LineEdit_1" );
2728  commentEdit = new KLineEdit( d->m_frame, "LineEdit_2" );
2729  mimeEdit = new KLineEdit( d->m_frame, "LineEdit_3" );
2730 
2731  TQBoxLayout *mainlayout = new TQVBoxLayout(d->m_frame, 0, KDialog::spacingHint());
2732  TQLabel* tmpQLabel;
2733 
2734  tmpQLabel = new TQLabel( d->m_frame, "Label_1" );
2735  tmpQLabel->setText( i18n("Pattern ( example: *.html;*.htm )") );
2736  tmpQLabel->setMinimumSize(tmpQLabel->sizeHint());
2737  mainlayout->addWidget(tmpQLabel, 1);
2738 
2739  //patternEdit->setGeometry( 10, 40, 210, 30 );
2740  //patternEdit->setText( "" );
2741  patternEdit->setMaxLength( 512 );
2742  patternEdit->setMinimumSize( patternEdit->sizeHint() );
2743  patternEdit->setFixedHeight( fontHeight );
2744  mainlayout->addWidget(patternEdit, 1);
2745 
2746  tmpQLabel = new TQLabel( d->m_frame, "Label_2" );
2747  tmpQLabel->setText( i18n("Mime Type") );
2748  tmpQLabel->setMinimumSize(tmpQLabel->sizeHint());
2749  mainlayout->addWidget(tmpQLabel, 1);
2750 
2751  //mimeEdit->setGeometry( 10, 160, 210, 30 );
2752  mimeEdit->setMaxLength( 256 );
2753  mimeEdit->setMinimumSize( mimeEdit->sizeHint() );
2754  mimeEdit->setFixedHeight( fontHeight );
2755  mainlayout->addWidget(mimeEdit, 1);
2756 
2757  tmpQLabel = new TQLabel( d->m_frame, "Label_3" );
2758  tmpQLabel->setText( i18n("Comment") );
2759  tmpQLabel->setMinimumSize(tmpQLabel->sizeHint());
2760  mainlayout->addWidget(tmpQLabel, 1);
2761 
2762  //commentEdit->setGeometry( 10, 100, 210, 30 );
2763  commentEdit->setMaxLength( 256 );
2764  commentEdit->setMinimumSize( commentEdit->sizeHint() );
2765  commentEdit->setFixedHeight( fontHeight );
2766  mainlayout->addWidget(commentEdit, 1);
2767 
2768  cbAutoEmbed = new TQCheckBox( i18n("Left click previews"), d->m_frame, "cbAutoEmbed" );
2769  mainlayout->addWidget(cbAutoEmbed, 1);
2770 
2771  mainlayout->addStretch (10);
2772  mainlayout->activate();
2773 
2774  TQFile f( _props->kurl().path() );
2775  if ( !f.open( IO_ReadOnly ) )
2776  return;
2777  f.close();
2778 
2779  KSimpleConfig config( _props->kurl().path() );
2780  config.setDesktopGroup();
2781  TQString patternStr = config.readEntry( "Patterns" );
2782  TQString iconStr = config.readEntry( "Icon" );
2783  TQString commentStr = config.readEntry( "Comment" );
2784  m_sMimeStr = config.readEntry( "MimeType" );
2785 
2786  if ( !patternStr.isEmpty() )
2787  patternEdit->setText( patternStr );
2788  if ( !commentStr.isEmpty() )
2789  commentEdit->setText( commentStr );
2790  if ( !m_sMimeStr.isEmpty() )
2791  mimeEdit->setText( m_sMimeStr );
2792  cbAutoEmbed->setTristate();
2793  if ( config.hasKey( "X-TDE-AutoEmbed" ) )
2794  cbAutoEmbed->setChecked( config.readBoolEntry( "X-TDE-AutoEmbed" ) );
2795  else
2796  cbAutoEmbed->setNoChange();
2797 
2798  connect( patternEdit, TQT_SIGNAL( textChanged( const TQString & ) ),
2799  this, TQT_SIGNAL( changed() ) );
2800  connect( commentEdit, TQT_SIGNAL( textChanged( const TQString & ) ),
2801  this, TQT_SIGNAL( changed() ) );
2802  connect( mimeEdit, TQT_SIGNAL( textChanged( const TQString & ) ),
2803  this, TQT_SIGNAL( changed() ) );
2804  connect( cbAutoEmbed, TQT_SIGNAL( toggled( bool ) ),
2805  this, TQT_SIGNAL( changed() ) );
2806 }
2807 
2808 KBindingPropsPlugin::~KBindingPropsPlugin()
2809 {
2810  delete d;
2811 }
2812 
2813 // TQString KBindingPropsPlugin::tabName () const
2814 // {
2815 // return i18n ("A&ssociation");
2816 // }
2817 
2818 bool KBindingPropsPlugin::supports( KFileItemList _items )
2819 {
2820  if ( _items.count() != 1 )
2821  return false;
2822  KFileItem * item = _items.first();
2823  // check if desktop file
2824  if ( !KPropsDlgPlugin::isDesktopFile( item ) )
2825  return false;
2826 
2827  // open file and check type
2828  KDesktopFile config( item->url().path(), true /* readonly */ );
2829  return config.hasMimeTypeType();
2830 }
2831 
2832 void KBindingPropsPlugin::applyChanges()
2833 {
2834  TQString path = properties->kurl().path();
2835  TQFile f( path );
2836 
2837  if ( !f.open( IO_ReadWrite ) )
2838  {
2839  KMessageBox::sorry( 0, i18n("<qt>Could not save properties. You do not have "
2840  "sufficient access to write to <b>%1</b>.</qt>").arg(path));
2841  return;
2842  }
2843  f.close();
2844 
2845  KSimpleConfig config( path );
2846  config.setDesktopGroup();
2847  config.writeEntry( "Type", TQString::fromLatin1("MimeType") );
2848 
2849  config.writeEntry( "Patterns", patternEdit->text() );
2850  config.writeEntry( "Comment", commentEdit->text() );
2851  config.writeEntry( "Comment",
2852  commentEdit->text(), true, false, true ); // for compat
2853  config.writeEntry( "MimeType", mimeEdit->text() );
2854  if ( cbAutoEmbed->state() == TQButton::NoChange )
2855  config.deleteEntry( "X-TDE-AutoEmbed", false );
2856  else
2857  config.writeEntry( "X-TDE-AutoEmbed", cbAutoEmbed->isChecked() );
2858  config.sync();
2859 }
2860 
2861 /* ----------------------------------------------------
2862  *
2863  * KDevicePropsPlugin
2864  *
2865  * -------------------------------------------------- */
2866 
2867 class KDevicePropsPlugin::KDevicePropsPluginPrivate
2868 {
2869 public:
2870  KDevicePropsPluginPrivate()
2871  {
2872  }
2873  ~KDevicePropsPluginPrivate()
2874  {
2875  }
2876 
2877  TQFrame *m_frame;
2878  TQStringList mountpointlist;
2879  TQLabel *m_freeSpaceText;
2880  TQLabel *m_freeSpaceLabel;
2881  TQProgressBar *m_freeSpaceBar;
2882 };
2883 
2884 KDevicePropsPlugin::KDevicePropsPlugin( KPropertiesDialog *_props ) : KPropsDlgPlugin( _props )
2885 {
2886  d = new KDevicePropsPluginPrivate;
2887  d->m_frame = properties->addPage(i18n("De&vice"));
2888 
2889  TQStringList devices;
2890  KMountPoint::List mountPoints = KMountPoint::possibleMountPoints();
2891 
2892  for(KMountPoint::List::ConstIterator it = mountPoints.begin();
2893  it != mountPoints.end(); ++it)
2894  {
2895  KMountPoint *mp = *it;
2896  TQString mountPoint = mp->mountPoint();
2897  TQString device = mp->mountedFrom();
2898  kdDebug()<<"mountPoint :"<<mountPoint<<" device :"<<device<<" mp->mountType() :"<<mp->mountType()<<endl;
2899 
2900  if ((mountPoint != "-") && (mountPoint != "none") && !mountPoint.isEmpty()
2901  && device != "none")
2902  {
2903  devices.append( device + TQString::fromLatin1(" (")
2904  + mountPoint + TQString::fromLatin1(")") );
2905  m_devicelist.append(device);
2906  d->mountpointlist.append(mountPoint);
2907  }
2908  }
2909 
2910  TQGridLayout *layout = new TQGridLayout( d->m_frame, 0, 2, 0,
2911  KDialog::spacingHint());
2912  layout->setColStretch(1, 1);
2913 
2914  TQLabel* label;
2915  label = new TQLabel( d->m_frame );
2916  label->setText( devices.count() == 0 ?
2917  i18n("Device (/dev/fd0):") : // old style
2918  i18n("Device:") ); // new style (combobox)
2919  layout->addWidget(label, 0, 0);
2920 
2921  device = new TQComboBox( true, d->m_frame, "ComboBox_device" );
2922  device->insertStringList( devices );
2923  layout->addWidget(device, 0, 1);
2924  connect( device, TQT_SIGNAL( activated( int ) ),
2925  this, TQT_SLOT( slotActivated( int ) ) );
2926 
2927  readonly = new TQCheckBox( d->m_frame, "CheckBox_readonly" );
2928  readonly->setText( i18n("Read only") );
2929  layout->addWidget(readonly, 1, 1);
2930 
2931  label = new TQLabel( d->m_frame );
2932  label->setText( i18n("File system:") );
2933  layout->addWidget(label, 2, 0);
2934 
2935  TQLabel *fileSystem = new TQLabel( d->m_frame );
2936  layout->addWidget(fileSystem, 2, 1);
2937 
2938  label = new TQLabel( d->m_frame );
2939  label->setText( devices.count()==0 ?
2940  i18n("Mount point (/mnt/floppy):") : // old style
2941  i18n("Mount point:")); // new style (combobox)
2942  layout->addWidget(label, 3, 0);
2943 
2944  mountpoint = new TQLabel( d->m_frame, "LineEdit_mountpoint" );
2945 
2946  layout->addWidget(mountpoint, 3, 1);
2947 
2948  // show disk free
2949  d->m_freeSpaceText = new TQLabel(i18n("Free disk space:"), d->m_frame );
2950  layout->addWidget(d->m_freeSpaceText, 4, 0);
2951 
2952  d->m_freeSpaceLabel = new TQLabel( d->m_frame );
2953  layout->addWidget( d->m_freeSpaceLabel, 4, 1 );
2954 
2955  d->m_freeSpaceBar = new TQProgressBar( d->m_frame, "freeSpaceBar" );
2956  layout->addMultiCellWidget(d->m_freeSpaceBar, 5, 5, 0, 1);
2957 
2958  // we show it in the slot when we know the values
2959  d->m_freeSpaceText->hide();
2960  d->m_freeSpaceLabel->hide();
2961  d->m_freeSpaceBar->hide();
2962 
2963  KSeparator* sep = new KSeparator( KSeparator::HLine, d->m_frame);
2964  layout->addMultiCellWidget(sep, 6, 6, 0, 1);
2965 
2966  unmounted = new TDEIconButton( d->m_frame );
2967  int bsize = 66 + 2 * unmounted->style().pixelMetric(TQStyle::PM_ButtonMargin);
2968  unmounted->setFixedSize(bsize, bsize);
2969  unmounted->setIconType(TDEIcon::Desktop, TDEIcon::Device);
2970  layout->addWidget(unmounted, 7, 0);
2971 
2972  label = new TQLabel( i18n("Unmounted Icon"), d->m_frame );
2973  layout->addWidget(label, 7, 1);
2974 
2975  layout->setRowStretch(8, 1);
2976 
2977  TQString path( _props->kurl().path() );
2978 
2979  TQFile f( path );
2980  if ( !f.open( IO_ReadOnly ) )
2981  return;
2982  f.close();
2983 
2984  KSimpleConfig config( path );
2985  config.setDesktopGroup();
2986  TQString deviceStr = config.readEntry( "Dev" );
2987  TQString mountPointStr = config.readEntry( "MountPoint" );
2988  bool ro = config.readBoolEntry( "ReadOnly", false );
2989  TQString unmountedStr = config.readEntry( "UnmountIcon" );
2990 
2991  TQString fsType = config.readEntry("FSType");
2992  fileSystem->setText( (fsType.stripWhiteSpace() != "") ? i18n(fsType.local8Bit()) : "" );
2993 
2994  device->setEditText( deviceStr );
2995  if ( !deviceStr.isEmpty() ) {
2996  // Set default options for this device (first matching entry)
2997  int index = m_devicelist.findIndex(deviceStr);
2998  if (index != -1)
2999  {
3000  //kdDebug(250) << "found it " << index << endl;
3001  slotActivated( index );
3002  }
3003  }
3004 
3005  if ( !mountPointStr.isEmpty() )
3006  {
3007  mountpoint->setText( mountPointStr );
3008  updateInfo();
3009  }
3010 
3011  readonly->setChecked( ro );
3012 
3013  if ( unmountedStr.isEmpty() )
3014  unmountedStr = KMimeType::defaultMimeTypePtr()->KServiceType::icon(); // default icon
3015 
3016  unmounted->setIcon( unmountedStr );
3017 
3018  connect( device, TQT_SIGNAL( activated( int ) ),
3019  this, TQT_SIGNAL( changed() ) );
3020  connect( device, TQT_SIGNAL( textChanged( const TQString & ) ),
3021  this, TQT_SIGNAL( changed() ) );
3022  connect( readonly, TQT_SIGNAL( toggled( bool ) ),
3023  this, TQT_SIGNAL( changed() ) );
3024  connect( unmounted, TQT_SIGNAL( iconChanged( TQString ) ),
3025  this, TQT_SIGNAL( changed() ) );
3026 
3027  connect( device, TQT_SIGNAL( textChanged( const TQString & ) ),
3028  this, TQT_SLOT( slotDeviceChanged() ) );
3029 
3030  processLockouts();
3031 }
3032 
3033 KDevicePropsPlugin::~KDevicePropsPlugin()
3034 {
3035  delete d;
3036 }
3037 
3038 // TQString KDevicePropsPlugin::tabName () const
3039 // {
3040 // return i18n ("De&vice");
3041 // }
3042 
3043 void KDevicePropsPlugin::processLockouts()
3044 {
3045  if (device->currentText().stripWhiteSpace() != "")
3046  {
3047  properties->enableButtonOK(true);
3048  }
3049  else
3050  {
3051  properties->enableButtonOK(false);
3052  }
3053 }
3054 
3055 void KDevicePropsPlugin::updateInfo()
3056 {
3057  // we show it in the slot when we know the values
3058  d->m_freeSpaceText->hide();
3059  d->m_freeSpaceLabel->hide();
3060  d->m_freeSpaceBar->hide();
3061 
3062  if ( !mountpoint->text().isEmpty() )
3063  {
3064  KDiskFreeSp * job = new KDiskFreeSp;
3065  connect( job, TQT_SIGNAL( foundMountPoint( const unsigned long&, const unsigned long&,
3066  const unsigned long&, const TQString& ) ),
3067  this, TQT_SLOT( slotFoundMountPoint( const unsigned long&, const unsigned long&,
3068  const unsigned long&, const TQString& ) ) );
3069 
3070  job->readDF( mountpoint->text() );
3071  }
3072 
3073  processLockouts();
3074 }
3075 
3076 void KDevicePropsPlugin::slotActivated( int index )
3077 {
3078  // Update mountpoint so that it matches the device that was selected in the combo
3079  device->setEditText( m_devicelist[index] );
3080  mountpoint->setText( d->mountpointlist[index] );
3081 
3082  updateInfo();
3083 }
3084 
3085 void KDevicePropsPlugin::slotDeviceChanged()
3086 {
3087  // Update mountpoint so that it matches the typed device
3088  int index = m_devicelist.findIndex( device->currentText() );
3089  if ( index != -1 )
3090  mountpoint->setText( d->mountpointlist[index] );
3091  else
3092  mountpoint->setText( TQString::null );
3093 
3094  updateInfo();
3095 }
3096 
3097 void KDevicePropsPlugin::slotFoundMountPoint( const unsigned long& kBSize,
3098  const unsigned long& /*kBUsed*/,
3099  const unsigned long& kBAvail,
3100  const TQString& )
3101 {
3102  d->m_freeSpaceText->show();
3103  d->m_freeSpaceLabel->show();
3104 
3105  int percUsed = 100 - (int)(100.0 * kBAvail / kBSize);
3106 
3107  d->m_freeSpaceLabel->setText(
3108  // xgettext:no-c-format -- Don't warn about translating the %1 out of %2 part.
3109  i18n("Available space out of total partition size (percent used)", "%1 out of %2 (%3% used)")
3110  .arg(TDEIO::convertSizeFromKB(kBAvail))
3111  .arg(TDEIO::convertSizeFromKB(kBSize))
3112  .arg( 100 - (int)(100.0 * kBAvail / kBSize) ));
3113 
3114  d->m_freeSpaceBar->setProgress(percUsed, 100);
3115  d->m_freeSpaceBar->show();
3116 }
3117 
3118 bool KDevicePropsPlugin::supports( KFileItemList _items )
3119 {
3120  if ( _items.count() != 1 )
3121  return false;
3122  KFileItem * item = _items.first();
3123  // check if desktop file
3124  if ( !KPropsDlgPlugin::isDesktopFile( item ) )
3125  return false;
3126  // open file and check type
3127  KDesktopFile config( item->url().path(), true /* readonly */ );
3128  return config.hasDeviceType();
3129 }
3130 
3131 void KDevicePropsPlugin::applyChanges()
3132 {
3133  TQString path = properties->kurl().path();
3134  TQFile f( path );
3135  if ( !f.open( IO_ReadWrite ) )
3136  {
3137  KMessageBox::sorry( 0, i18n("<qt>Could not save properties. You do not have sufficient "
3138  "access to write to <b>%1</b>.</qt>").arg(path));
3139  return;
3140  }
3141  f.close();
3142 
3143  KSimpleConfig config( path );
3144  config.setDesktopGroup();
3145  config.writeEntry( "Type", TQString::fromLatin1("FSDevice") );
3146 
3147  config.writeEntry( "Dev", device->currentText() );
3148  config.writeEntry( "MountPoint", mountpoint->text() );
3149 
3150  config.writeEntry( "UnmountIcon", unmounted->icon() );
3151  kdDebug(250) << "unmounted->icon() = " << unmounted->icon() << endl;
3152 
3153  config.writeEntry( "ReadOnly", readonly->isChecked() );
3154 
3155  config.sync();
3156 }
3157 
3158 
3159 /* ----------------------------------------------------
3160  *
3161  * KDesktopPropsPlugin
3162  *
3163  * -------------------------------------------------- */
3164 
3165 
3166 KDesktopPropsPlugin::KDesktopPropsPlugin( KPropertiesDialog *_props )
3167  : KPropsDlgPlugin( _props )
3168 {
3169  TQFrame *frame = properties->addPage(i18n("&Application"));
3170  TQVBoxLayout *mainlayout = new TQVBoxLayout( frame, 0, KDialog::spacingHint() );
3171 
3172  w = new KPropertiesDesktopBase(frame);
3173  mainlayout->addWidget(w);
3174 
3175  bool bKDesktopMode = (TQCString(tqApp->name()) == "kdesktop"); // nasty heh?
3176 
3177  if (bKDesktopMode)
3178  {
3179  // Hide Name entry
3180  w->nameEdit->hide();
3181  w->nameLabel->hide();
3182  }
3183 
3184  w->pathEdit->setMode(KFile::Directory | KFile::LocalOnly);
3185  w->pathEdit->lineEdit()->setAcceptDrops(false);
3186 
3187  connect( w->nameEdit, TQT_SIGNAL( textChanged( const TQString & ) ), this, TQT_SIGNAL( changed() ) );
3188  connect( w->genNameEdit, TQT_SIGNAL( textChanged( const TQString & ) ), this, TQT_SIGNAL( changed() ) );
3189  connect( w->commentEdit, TQT_SIGNAL( textChanged( const TQString & ) ), this, TQT_SIGNAL( changed() ) );
3190  connect( w->commandEdit, TQT_SIGNAL( textChanged( const TQString & ) ), this, TQT_SIGNAL( changed() ) );
3191  connect( w->pathEdit, TQT_SIGNAL( textChanged( const TQString & ) ), this, TQT_SIGNAL( changed() ) );
3192 
3193  connect( w->browseButton, TQT_SIGNAL( clicked() ), this, TQT_SLOT( slotBrowseExec() ) );
3194  connect( w->addFiletypeButton, TQT_SIGNAL( clicked() ), this, TQT_SLOT( slotAddFiletype() ) );
3195  connect( w->delFiletypeButton, TQT_SIGNAL( clicked() ), this, TQT_SLOT( slotDelFiletype() ) );
3196  connect( w->advancedButton, TQT_SIGNAL( clicked() ), this, TQT_SLOT( slotAdvanced() ) );
3197 
3198  // now populate the page
3199  TQString path = _props->kurl().path();
3200  TQFile f( path );
3201  if ( !f.open( IO_ReadOnly ) )
3202  return;
3203  f.close();
3204 
3205  KDesktopFile config( path );
3206  TQString nameStr = config.readName();
3207  TQString genNameStr = config.readGenericName();
3208  TQString commentStr = config.readComment();
3209  TQString commandStr = config.readPathEntry( "Exec" );
3210  if (commandStr.left(12) == "ksystraycmd ")
3211  {
3212  commandStr.remove(0, 12);
3213  m_systrayBool = true;
3214  }
3215  else
3216  m_systrayBool = false;
3217 
3218  m_origCommandStr = commandStr;
3219  TQString pathStr = config.readPathEntry( "Path" );
3220  m_terminalBool = config.readBoolEntry( "Terminal" );
3221  m_terminalOptionStr = config.readEntry( "TerminalOptions" );
3222  m_suidBool = config.readBoolEntry( "X-TDE-SubstituteUID" ) || config.readBoolEntry( "X-KDE-SubstituteUID" );
3223  if( config.hasKey( "X-TDE-Username" ))
3224  m_suidUserStr = config.readEntry( "X-TDE-Username" );
3225  else
3226  m_suidUserStr = config.readEntry( "X-KDE-Username" );
3227  if( config.hasKey( "StartupNotify" ))
3228  m_startupBool = config.readBoolEntry( "StartupNotify", true );
3229  else
3230  m_startupBool = config.readBoolEntry( "X-TDE-StartupNotify", true );
3231  m_dcopServiceType = config.readEntry("X-DCOP-ServiceType").lower();
3232 
3233  TQStringList mimeTypes = config.readListEntry( "MimeType", ';' );
3234 
3235  if ( nameStr.isEmpty() || bKDesktopMode ) {
3236  // We'll use the file name if no name is specified
3237  // because we _need_ a Name for a valid file.
3238  // But let's do it in apply, not here, so that we pick up the right name.
3239  setDirty();
3240  }
3241  if ( !bKDesktopMode )
3242  w->nameEdit->setText(nameStr);
3243 
3244  w->genNameEdit->setText( genNameStr );
3245  w->commentEdit->setText( commentStr );
3246  w->commandEdit->setText( commandStr );
3247  w->pathEdit->lineEdit()->setText( pathStr );
3248  w->filetypeList->setAllColumnsShowFocus(true);
3249 
3250  KMimeType::Ptr defaultMimetype = KMimeType::defaultMimeTypePtr();
3251  for(TQStringList::ConstIterator it = mimeTypes.begin();
3252  it != mimeTypes.end(); )
3253  {
3254  KMimeType::Ptr p = KMimeType::mimeType(*it);
3255  ++it;
3256  TQString preference;
3257  if (it != mimeTypes.end())
3258  {
3259  bool numeric;
3260  (*it).toInt(&numeric);
3261  if (numeric)
3262  {
3263  preference = *it;
3264  ++it;
3265  }
3266  }
3267  if (p && (p != defaultMimetype))
3268  {
3269  new TQListViewItem(w->filetypeList, p->name(), p->comment(), preference);
3270  }
3271  }
3272 
3273 }
3274 
3275 KDesktopPropsPlugin::~KDesktopPropsPlugin()
3276 {
3277 }
3278 
3279 void KDesktopPropsPlugin::slotSelectMimetype()
3280 {
3281  TQListView *w = (TQListView*)sender();
3282  TQListViewItem *item = w->firstChild();
3283  while(item)
3284  {
3285  if (item->isSelected())
3286  w->setSelected(item, false);
3287  item = item->nextSibling();
3288  }
3289 }
3290 
3291 void KDesktopPropsPlugin::slotAddFiletype()
3292 {
3293  KDialogBase dlg(w, "KPropertiesMimetypes", true,
3294  i18n("Add File Type for %1").arg(properties->kurl().fileName()),
3295  KDialogBase::Ok|KDialogBase::Cancel, KDialogBase::Ok);
3296 
3297  KGuiItem okItem(i18n("&Add"), TQString::null /* no icon */,
3298  i18n("Add the selected file types to\nthe list of supported file types."),
3299  i18n("Add the selected file types to\nthe list of supported file types."));
3300  dlg.setButtonOK(okItem);
3301 
3302  KPropertiesMimetypeBase *mw = new KPropertiesMimetypeBase(&dlg);
3303 
3304  dlg.setMainWidget(mw);
3305 
3306  {
3307  mw->listView->setRootIsDecorated(true);
3308  mw->listView->setSelectionMode(TQListView::Extended);
3309  mw->listView->setAllColumnsShowFocus(true);
3310  mw->listView->setFullWidth(true);
3311  mw->listView->setMinimumSize(500,400);
3312 
3313  connect(mw->listView, TQT_SIGNAL(selectionChanged()),
3314  this, TQT_SLOT(slotSelectMimetype()));
3315  connect(mw->listView, TQT_SIGNAL(doubleClicked( TQListViewItem *, const TQPoint &, int )),
3316  &dlg, TQT_SLOT( slotOk()));
3317 
3318  TQMap<TQString,TQListViewItem*> majorMap;
3319  TQListViewItem *majorGroup;
3320  KMimeType::List mimetypes = KMimeType::allMimeTypes();
3321  TQValueListIterator<KMimeType::Ptr> it(mimetypes.begin());
3322  for (; it != mimetypes.end(); ++it) {
3323  TQString mimetype = (*it)->name();
3324  if (mimetype == KMimeType::defaultMimeType())
3325  continue;
3326  int index = mimetype.find("/");
3327  TQString maj = mimetype.left(index);
3328  TQString min = mimetype.mid(index+1);
3329 
3330  TQMapIterator<TQString,TQListViewItem*> mit = majorMap.find( maj );
3331  if ( mit == majorMap.end() ) {
3332  majorGroup = new TQListViewItem( mw->listView, maj );
3333  majorGroup->setExpandable(true);
3334  mw->listView->setOpen(majorGroup, true);
3335  majorMap.insert( maj, majorGroup );
3336  }
3337  else
3338  {
3339  majorGroup = mit.data();
3340  }
3341 
3342  TQListViewItem *item = new TQListViewItem(majorGroup, min, (*it)->comment());
3343  item->setPixmap(0, (*it)->pixmap(TDEIcon::Small, IconSize(TDEIcon::Small)));
3344  }
3345  TQMapIterator<TQString,TQListViewItem*> mit = majorMap.find( "all" );
3346  if ( mit != majorMap.end())
3347  {
3348  mw->listView->setCurrentItem(mit.data());
3349  mw->listView->ensureItemVisible(mit.data());
3350  }
3351  }
3352 
3353  if (dlg.exec() == KDialogBase::Accepted)
3354  {
3355  KMimeType::Ptr defaultMimetype = KMimeType::defaultMimeTypePtr();
3356  TQListViewItem *majorItem = mw->listView->firstChild();
3357  while(majorItem)
3358  {
3359  TQString major = majorItem->text(0);
3360 
3361  TQListViewItem *minorItem = majorItem->firstChild();
3362  while(minorItem)
3363  {
3364  if (minorItem->isSelected())
3365  {
3366  TQString mimetype = major + "/" + minorItem->text(0);
3367  KMimeType::Ptr p = KMimeType::mimeType(mimetype);
3368  if (p && (p != defaultMimetype))
3369  {
3370  mimetype = p->name();
3371  bool found = false;
3372  TQListViewItem *item = w->filetypeList->firstChild();
3373  while (item)
3374  {
3375  if (mimetype == item->text(0))
3376  {
3377  found = true;
3378  break;
3379  }
3380  item = item->nextSibling();
3381  }
3382  if (!found) {
3383  new TQListViewItem(w->filetypeList, p->name(), p->comment());
3384  emit changed();
3385  }
3386  }
3387  }
3388  minorItem = minorItem->nextSibling();
3389  }
3390 
3391  majorItem = majorItem->nextSibling();
3392  }
3393 
3394  }
3395 }
3396 
3397 void KDesktopPropsPlugin::slotDelFiletype()
3398 {
3399  delete w->filetypeList->currentItem();
3400  emit changed();
3401 }
3402 
3403 void KDesktopPropsPlugin::checkCommandChanged()
3404 {
3405  if (KRun::binaryName(w->commandEdit->text(), true) !=
3406  KRun::binaryName(m_origCommandStr, true))
3407  {
3408  TQString m_origCommandStr = w->commandEdit->text();
3409  m_dcopServiceType= TQString::null; // Reset
3410  }
3411 }
3412 
3413 void KDesktopPropsPlugin::applyChanges()
3414 {
3415  kdDebug(250) << "KDesktopPropsPlugin::applyChanges" << endl;
3416  TQString path = properties->kurl().path();
3417 
3418  TQFile f( path );
3419 
3420  if ( !f.open( IO_ReadWrite ) ) {
3421  KMessageBox::sorry( 0, i18n("<qt>Could not save properties. You do not have "
3422  "sufficient access to write to <b>%1</b>.</qt>").arg(path));
3423  return;
3424  }
3425  f.close();
3426 
3427  // If the command is changed we reset certain settings that are strongly
3428  // coupled to the command.
3429  checkCommandChanged();
3430 
3431  KSimpleConfig config( path );
3432  config.setDesktopGroup();
3433  config.writeEntry( "Type", TQString::fromLatin1("Application"));
3434  config.writeEntry( "Comment", w->commentEdit->text() );
3435  config.writeEntry( "Comment", w->commentEdit->text(), true, false, true ); // for compat
3436  config.writeEntry( "GenericName", w->genNameEdit->text() );
3437  config.writeEntry( "GenericName", w->genNameEdit->text(), true, false, true ); // for compat
3438 
3439  if (m_systrayBool)
3440  config.writePathEntry( "Exec", w->commandEdit->text().prepend("ksystraycmd ") );
3441  else
3442  config.writePathEntry( "Exec", w->commandEdit->text() );
3443  config.writePathEntry( "Path", w->pathEdit->lineEdit()->text() );
3444 
3445  // Write mimeTypes
3446  TQStringList mimeTypes;
3447  for( TQListViewItem *item = w->filetypeList->firstChild();
3448  item; item = item->nextSibling() )
3449  {
3450  TQString preference = item->text(2);
3451  mimeTypes.append(item->text(0));
3452  if (!preference.isEmpty())
3453  mimeTypes.append(preference);
3454  }
3455 
3456  config.writeEntry( "MimeType", mimeTypes, ';' );
3457 
3458  if ( !w->nameEdit->isHidden() ) {
3459  TQString nameStr = w->nameEdit->text();
3460  config.writeEntry( "Name", nameStr );
3461  config.writeEntry( "Name", nameStr, true, false, true );
3462  }
3463 
3464  config.writeEntry("Terminal", m_terminalBool);
3465  config.writeEntry("TerminalOptions", m_terminalOptionStr);
3466  config.writeEntry("X-TDE-SubstituteUID", m_suidBool);
3467  config.writeEntry("X-TDE-Username", m_suidUserStr);
3468  config.writeEntry("StartupNotify", m_startupBool);
3469  config.writeEntry("X-DCOP-ServiceType", m_dcopServiceType);
3470  config.sync();
3471 
3472  // KSycoca update needed?
3473  TQString sycocaPath = TDEGlobal::dirs()->relativeLocation("apps", path);
3474  bool updateNeeded = !sycocaPath.startsWith("/");
3475  if (!updateNeeded)
3476  {
3477  sycocaPath = TDEGlobal::dirs()->relativeLocation("xdgdata-apps", path);
3478  updateNeeded = !sycocaPath.startsWith("/");
3479  }
3480  if (updateNeeded)
3481  KService::rebuildKSycoca(w);
3482 }
3483 
3484 
3485 void KDesktopPropsPlugin::slotBrowseExec()
3486 {
3487  KURL f = KFileDialog::getOpenURL( TQString::null,
3488  TQString::null, w );
3489  if ( f.isEmpty() )
3490  return;
3491 
3492  if ( !f.isLocalFile()) {
3493  KMessageBox::sorry(w, i18n("Only executables on local file systems are supported."));
3494  return;
3495  }
3496 
3497  TQString path = f.path();
3498  KRun::shellQuote( path );
3499  w->commandEdit->setText( path );
3500 }
3501 
3502 void KDesktopPropsPlugin::slotAdvanced()
3503 {
3504  KDialogBase dlg(w, "KPropertiesDesktopAdv", true,
3505  i18n("Advanced Options for %1").arg(properties->kurl().fileName()),
3506  KDialogBase::Ok|KDialogBase::Cancel, KDialogBase::Ok);
3507  KPropertiesDesktopAdvBase *w = new KPropertiesDesktopAdvBase(&dlg);
3508 
3509  dlg.setMainWidget(w);
3510 
3511  // If the command is changed we reset certain settings that are strongly
3512  // coupled to the command.
3513  checkCommandChanged();
3514 
3515  // check to see if we use konsole if not do not add the nocloseonexit
3516  // because we don't know how to do this on other terminal applications
3517  TDEConfigGroup confGroup( TDEGlobal::config(), TQString::fromLatin1("General") );
3518  TQString preferredTerminal = confGroup.readPathEntry("TerminalApplication",
3519  TQString::fromLatin1("konsole"));
3520 
3521  bool terminalCloseBool = false;
3522 
3523  if (preferredTerminal == "konsole")
3524  {
3525  terminalCloseBool = (m_terminalOptionStr.contains( "--noclose" ) > 0);
3526  w->terminalCloseCheck->setChecked(terminalCloseBool);
3527  m_terminalOptionStr.replace( "--noclose", "");
3528  }
3529  else
3530  {
3531  w->terminalCloseCheck->hide();
3532  }
3533 
3534  w->terminalCheck->setChecked(m_terminalBool);
3535  w->terminalEdit->setText(m_terminalOptionStr);
3536  w->terminalCloseCheck->setEnabled(m_terminalBool);
3537  w->terminalEdit->setEnabled(m_terminalBool);
3538  w->terminalEditLabel->setEnabled(m_terminalBool);
3539 
3540  w->suidCheck->setChecked(m_suidBool);
3541  w->suidEdit->setText(m_suidUserStr);
3542  w->suidEdit->setEnabled(m_suidBool);
3543  w->suidEditLabel->setEnabled(m_suidBool);
3544 
3545  w->startupInfoCheck->setChecked(m_startupBool);
3546  w->systrayCheck->setChecked(m_systrayBool);
3547 
3548  if (m_dcopServiceType == "unique")
3549  w->dcopCombo->setCurrentItem(2);
3550  else if (m_dcopServiceType == "multi")
3551  w->dcopCombo->setCurrentItem(1);
3552  else if (m_dcopServiceType == "wait")
3553  w->dcopCombo->setCurrentItem(3);
3554  else
3555  w->dcopCombo->setCurrentItem(0);
3556 
3557  // Provide username completion up to 1000 users.
3558  TDECompletion *kcom = new TDECompletion;
3559  kcom->setOrder(TDECompletion::Sorted);
3560  struct passwd *pw;
3561  int i, maxEntries = 1000;
3562  setpwent();
3563  for (i=0; ((pw = getpwent()) != 0L) && (i < maxEntries); i++)
3564  kcom->addItem(TQString::fromLatin1(pw->pw_name));
3565  endpwent();
3566  if (i < maxEntries)
3567  {
3568  w->suidEdit->setCompletionObject(kcom, true);
3569  w->suidEdit->setAutoDeleteCompletionObject( true );
3570  w->suidEdit->setCompletionMode(TDEGlobalSettings::CompletionAuto);
3571  }
3572  else
3573  {
3574  delete kcom;
3575  }
3576 
3577  connect( w->terminalEdit, TQT_SIGNAL( textChanged( const TQString & ) ),
3578  this, TQT_SIGNAL( changed() ) );
3579  connect( w->terminalCloseCheck, TQT_SIGNAL( toggled( bool ) ),
3580  this, TQT_SIGNAL( changed() ) );
3581  connect( w->terminalCheck, TQT_SIGNAL( toggled( bool ) ),
3582  this, TQT_SIGNAL( changed() ) );
3583  connect( w->suidCheck, TQT_SIGNAL( toggled( bool ) ),
3584  this, TQT_SIGNAL( changed() ) );
3585  connect( w->suidEdit, TQT_SIGNAL( textChanged( const TQString & ) ),
3586  this, TQT_SIGNAL( changed() ) );
3587  connect( w->startupInfoCheck, TQT_SIGNAL( toggled( bool ) ),
3588  this, TQT_SIGNAL( changed() ) );
3589  connect( w->systrayCheck, TQT_SIGNAL( toggled( bool ) ),
3590  this, TQT_SIGNAL( changed() ) );
3591  connect( w->dcopCombo, TQT_SIGNAL( highlighted( int ) ),
3592  this, TQT_SIGNAL( changed() ) );
3593 
3594  if ( dlg.exec() == TQDialog::Accepted )
3595  {
3596  m_terminalOptionStr = w->terminalEdit->text().stripWhiteSpace();
3597  m_terminalBool = w->terminalCheck->isChecked();
3598  m_suidBool = w->suidCheck->isChecked();
3599  m_suidUserStr = w->suidEdit->text().stripWhiteSpace();
3600  m_startupBool = w->startupInfoCheck->isChecked();
3601  m_systrayBool = w->systrayCheck->isChecked();
3602 
3603  if (w->terminalCloseCheck->isChecked())
3604  {
3605  m_terminalOptionStr.append(" --noclose");
3606  }
3607 
3608  switch(w->dcopCombo->currentItem())
3609  {
3610  case 1: m_dcopServiceType = "multi"; break;
3611  case 2: m_dcopServiceType = "unique"; break;
3612  case 3: m_dcopServiceType = "wait"; break;
3613  default: m_dcopServiceType = "none"; break;
3614  }
3615  }
3616 }
3617 
3618 bool KDesktopPropsPlugin::supports( KFileItemList _items )
3619 {
3620  if ( _items.count() != 1 )
3621  return false;
3622  KFileItem * item = _items.first();
3623  // check if desktop file
3624  if ( !KPropsDlgPlugin::isDesktopFile( item ) )
3625  return false;
3626  // open file and check type
3627  KDesktopFile config( item->url().path(), true /* readonly */ );
3628  return config.hasApplicationType() && kapp->authorize("run_desktop_files") && kapp->authorize("shell_access");
3629 }
3630 
3631 void KPropertiesDialog::virtual_hook( int id, void* data )
3632 { KDialogBase::virtual_hook( id, data ); }
3633 
3634 void KPropsDlgPlugin::virtual_hook( int, void* )
3635 { /*BASE::virtual_hook( id, data );*/ }
3636 
3637 
3638 
3639 
3640 
3646 class KExecPropsPlugin::KExecPropsPluginPrivate
3647 {
3648 public:
3649  KExecPropsPluginPrivate()
3650  {
3651  }
3652  ~KExecPropsPluginPrivate()
3653  {
3654  }
3655 
3656  TQFrame *m_frame;
3657  TQCheckBox *nocloseonexitCheck;
3658 };
3659 
3660 KExecPropsPlugin::KExecPropsPlugin( KPropertiesDialog *_props )
3661  : KPropsDlgPlugin( _props )
3662 {
3663  d = new KExecPropsPluginPrivate;
3664  d->m_frame = properties->addPage(i18n("E&xecute"));
3665  TQVBoxLayout * mainlayout = new TQVBoxLayout( d->m_frame, 0,
3666  KDialog::spacingHint());
3667 
3668  // Now the widgets in the top layout
3669 
3670  TQLabel* l;
3671  l = new TQLabel( i18n( "Comman&d:" ), d->m_frame );
3672  mainlayout->addWidget(l);
3673 
3674  TQHBoxLayout * hlayout;
3675  hlayout = new TQHBoxLayout(KDialog::spacingHint());
3676  mainlayout->addLayout(hlayout);
3677 
3678  execEdit = new KLineEdit( d->m_frame );
3679  TQWhatsThis::add(execEdit,i18n(
3680  "Following the command, you can have several place holders which will be replaced "
3681  "with the actual values when the actual program is run:\n"
3682  "%f - a single file name\n"
3683  "%F - a list of files; use for applications that can open several local files at once\n"
3684  "%u - a single URL\n"
3685  "%U - a list of URLs\n"
3686  "%d - the folder of the file to open\n"
3687  "%D - a list of folders\n"
3688  "%i - the icon\n"
3689  "%m - the mini-icon\n"
3690  "%c - the caption"));
3691  hlayout->addWidget(execEdit, 1);
3692 
3693  l->setBuddy( execEdit );
3694 
3695  execBrowse = new TQPushButton( d->m_frame );
3696  execBrowse->setText( i18n("&Browse...") );
3697  hlayout->addWidget(execBrowse);
3698 
3699  // The groupbox about swallowing
3700  TQGroupBox* tmpQGroupBox;
3701  tmpQGroupBox = new TQGroupBox( i18n("Panel Embedding"), d->m_frame );
3702  tmpQGroupBox->setColumnLayout( 0, Qt::Horizontal );
3703 
3704  mainlayout->addWidget(tmpQGroupBox);
3705 
3706  TQGridLayout *grid = new TQGridLayout(tmpQGroupBox->layout(), 2, 2);
3707  grid->setSpacing( KDialog::spacingHint() );
3708  grid->setColStretch(1, 1);
3709 
3710  l = new TQLabel( i18n( "&Execute on click:" ), tmpQGroupBox );
3711  grid->addWidget(l, 0, 0);
3712 
3713  swallowExecEdit = new KLineEdit( tmpQGroupBox );
3714  grid->addWidget(swallowExecEdit, 0, 1);
3715 
3716  l->setBuddy( swallowExecEdit );
3717 
3718  l = new TQLabel( i18n( "&Window title:" ), tmpQGroupBox );
3719  grid->addWidget(l, 1, 0);
3720 
3721  swallowTitleEdit = new KLineEdit( tmpQGroupBox );
3722  grid->addWidget(swallowTitleEdit, 1, 1);
3723 
3724  l->setBuddy( swallowTitleEdit );
3725 
3726  // The groupbox about run in terminal
3727 
3728  tmpQGroupBox = new TQGroupBox( d->m_frame );
3729  tmpQGroupBox->setColumnLayout( 0, Qt::Horizontal );
3730 
3731  mainlayout->addWidget(tmpQGroupBox);
3732 
3733  grid = new TQGridLayout(tmpQGroupBox->layout(), 3, 2);
3734  grid->setSpacing( KDialog::spacingHint() );
3735  grid->setColStretch(1, 1);
3736 
3737  terminalCheck = new TQCheckBox( tmpQGroupBox );
3738  terminalCheck->setText( i18n("&Run in terminal") );
3739  grid->addMultiCellWidget(terminalCheck, 0, 0, 0, 1);
3740 
3741  // check to see if we use konsole if not do not add the nocloseonexit
3742  // because we don't know how to do this on other terminal applications
3743  TDEConfigGroup confGroup( TDEGlobal::config(), TQString::fromLatin1("General") );
3744  TQString preferredTerminal = confGroup.readPathEntry("TerminalApplication",
3745  TQString::fromLatin1("konsole"));
3746 
3747  int posOptions = 1;
3748  d->nocloseonexitCheck = 0L;
3749  if (preferredTerminal == "konsole")
3750  {
3751  posOptions = 2;
3752  d->nocloseonexitCheck = new TQCheckBox( tmpQGroupBox );
3753  d->nocloseonexitCheck->setText( i18n("Do not &close when command exits") );
3754  grid->addMultiCellWidget(d->nocloseonexitCheck, 1, 1, 0, 1);
3755  }
3756 
3757  terminalLabel = new TQLabel( i18n( "&Terminal options:" ), tmpQGroupBox );
3758  grid->addWidget(terminalLabel, posOptions, 0);
3759 
3760  terminalEdit = new KLineEdit( tmpQGroupBox );
3761  grid->addWidget(terminalEdit, posOptions, 1);
3762 
3763  terminalLabel->setBuddy( terminalEdit );
3764 
3765  // The groupbox about run with substituted uid.
3766 
3767  tmpQGroupBox = new TQGroupBox( d->m_frame );
3768  tmpQGroupBox->setColumnLayout( 0, Qt::Horizontal );
3769 
3770  mainlayout->addWidget(tmpQGroupBox);
3771 
3772  grid = new TQGridLayout(tmpQGroupBox->layout(), 2, 2);
3773  grid->setSpacing(KDialog::spacingHint());
3774  grid->setColStretch(1, 1);
3775 
3776  suidCheck = new TQCheckBox(tmpQGroupBox);
3777  suidCheck->setText(i18n("Ru&n as a different user"));
3778  grid->addMultiCellWidget(suidCheck, 0, 0, 0, 1);
3779 
3780  suidLabel = new TQLabel(i18n( "&Username:" ), tmpQGroupBox);
3781  grid->addWidget(suidLabel, 1, 0);
3782 
3783  suidEdit = new KLineEdit(tmpQGroupBox);
3784  grid->addWidget(suidEdit, 1, 1);
3785 
3786  suidLabel->setBuddy( suidEdit );
3787 
3788  mainlayout->addStretch(1);
3789 
3790  // now populate the page
3791  TQString path = _props->kurl().path();
3792  TQFile f( path );
3793  if ( !f.open( IO_ReadOnly ) )
3794  return;
3795  f.close();
3796 
3797  KSimpleConfig config( path );
3798  config.setDollarExpansion( false );
3799  config.setDesktopGroup();
3800  execStr = config.readPathEntry( "Exec" );
3801  swallowExecStr = config.readPathEntry( "SwallowExec" );
3802  swallowTitleStr = config.readEntry( "SwallowTitle" );
3803  termBool = config.readBoolEntry( "Terminal" );
3804  termOptionsStr = config.readEntry( "TerminalOptions" );
3805  suidBool = config.readBoolEntry( "X-TDE-SubstituteUID" );
3806  suidUserStr = config.readEntry( "X-TDE-Username" );
3807 
3808  if ( !swallowExecStr.isNull() )
3809  swallowExecEdit->setText( swallowExecStr );
3810  if ( !swallowTitleStr.isNull() )
3811  swallowTitleEdit->setText( swallowTitleStr );
3812 
3813  if ( !execStr.isNull() )
3814  execEdit->setText( execStr );
3815 
3816  if ( d->nocloseonexitCheck )
3817  {
3818  d->nocloseonexitCheck->setChecked( (termOptionsStr.contains( "--noclose" ) > 0) );
3819  termOptionsStr.replace( "--noclose", "");
3820  }
3821  if ( !termOptionsStr.isNull() )
3822  terminalEdit->setText( termOptionsStr );
3823 
3824  terminalCheck->setChecked( termBool );
3825  enableCheckedEdit();
3826 
3827  suidCheck->setChecked( suidBool );
3828  suidEdit->setText( suidUserStr );
3829  enableSuidEdit();
3830 
3831  // Provide username completion up to 1000 users.
3832  TDECompletion *kcom = new TDECompletion;
3833  kcom->setOrder(TDECompletion::Sorted);
3834  struct passwd *pw;
3835  int i, maxEntries = 1000;
3836  setpwent();
3837  for (i=0; ((pw = getpwent()) != 0L) && (i < maxEntries); i++)
3838  kcom->addItem(TQString::fromLatin1(pw->pw_name));
3839  endpwent();
3840  if (i < maxEntries)
3841  {
3842  suidEdit->setCompletionObject(kcom, true);
3843  suidEdit->setAutoDeleteCompletionObject( true );
3844  suidEdit->setCompletionMode(TDEGlobalSettings::CompletionAuto);
3845  }
3846  else
3847  {
3848  delete kcom;
3849  }
3850 
3851  connect( swallowExecEdit, TQT_SIGNAL( textChanged( const TQString & ) ),
3852  this, TQT_SIGNAL( changed() ) );
3853  connect( swallowTitleEdit, TQT_SIGNAL( textChanged( const TQString & ) ),
3854  this, TQT_SIGNAL( changed() ) );
3855  connect( execEdit, TQT_SIGNAL( textChanged( const TQString & ) ),
3856  this, TQT_SIGNAL( changed() ) );
3857  connect( terminalEdit, TQT_SIGNAL( textChanged( const TQString & ) ),
3858  this, TQT_SIGNAL( changed() ) );
3859  if (d->nocloseonexitCheck)
3860  connect( d->nocloseonexitCheck, TQT_SIGNAL( toggled( bool ) ),
3861  this, TQT_SIGNAL( changed() ) );
3862  connect( terminalCheck, TQT_SIGNAL( toggled( bool ) ),
3863  this, TQT_SIGNAL( changed() ) );
3864  connect( suidCheck, TQT_SIGNAL( toggled( bool ) ),
3865  this, TQT_SIGNAL( changed() ) );
3866  connect( suidEdit, TQT_SIGNAL( textChanged( const TQString & ) ),
3867  this, TQT_SIGNAL( changed() ) );
3868 
3869  connect( execBrowse, TQT_SIGNAL( clicked() ), this, TQT_SLOT( slotBrowseExec() ) );
3870  connect( terminalCheck, TQT_SIGNAL( clicked() ), this, TQT_SLOT( enableCheckedEdit() ) );
3871  connect( suidCheck, TQT_SIGNAL( clicked() ), this, TQT_SLOT( enableSuidEdit() ) );
3872 
3873 }
3874 
3875 KExecPropsPlugin::~KExecPropsPlugin()
3876 {
3877  delete d;
3878 }
3879 
3880 void KExecPropsPlugin::enableCheckedEdit()
3881 {
3882  bool checked = terminalCheck->isChecked();
3883  terminalLabel->setEnabled( checked );
3884  if (d->nocloseonexitCheck)
3885  d->nocloseonexitCheck->setEnabled( checked );
3886  terminalEdit->setEnabled( checked );
3887 }
3888 
3889 void KExecPropsPlugin::enableSuidEdit()
3890 {
3891  bool checked = suidCheck->isChecked();
3892  suidLabel->setEnabled( checked );
3893  suidEdit->setEnabled( checked );
3894 }
3895 
3896 bool KExecPropsPlugin::supports( KFileItemList _items )
3897 {
3898  if ( _items.count() != 1 )
3899  return false;
3900  KFileItem * item = _items.first();
3901  // check if desktop file
3902  if ( !KPropsDlgPlugin::isDesktopFile( item ) )
3903  return false;
3904  // open file and check type
3905  KDesktopFile config( item->url().path(), true /* readonly */ );
3906  return config.hasApplicationType() && kapp->authorize("run_desktop_files") && kapp->authorize("shell_access");
3907 }
3908 
3909 void KExecPropsPlugin::applyChanges()
3910 {
3911  kdDebug(250) << "KExecPropsPlugin::applyChanges" << endl;
3912  TQString path = properties->kurl().path();
3913 
3914  TQFile f( path );
3915 
3916  if ( !f.open( IO_ReadWrite ) ) {
3917  KMessageBox::sorry( 0, i18n("<qt>Could not save properties. You do not have "
3918  "sufficient access to write to <b>%1</b>.</qt>").arg(path));
3919  return;
3920  }
3921  f.close();
3922 
3923  KSimpleConfig config( path );
3924  config.setDesktopGroup();
3925  config.writeEntry( "Type", TQString::fromLatin1("Application"));
3926  config.writePathEntry( "Exec", execEdit->text() );
3927  config.writePathEntry( "SwallowExec", swallowExecEdit->text() );
3928  config.writeEntry( "SwallowTitle", swallowTitleEdit->text() );
3929  config.writeEntry( "Terminal", terminalCheck->isChecked() );
3930  TQString temp = terminalEdit->text();
3931  if (d->nocloseonexitCheck )
3932  if ( d->nocloseonexitCheck->isChecked() )
3933  temp += TQString::fromLatin1("--noclose ");
3934  temp = temp.stripWhiteSpace();
3935  config.writeEntry( "TerminalOptions", temp );
3936  config.writeEntry( "X-TDE-SubstituteUID", suidCheck->isChecked() );
3937  config.writeEntry( "X-TDE-Username", suidEdit->text() );
3938 }
3939 
3940 
3941 void KExecPropsPlugin::slotBrowseExec()
3942 {
3943  KURL f = KFileDialog::getOpenURL( TQString::null,
3944  TQString::null, d->m_frame );
3945  if ( f.isEmpty() )
3946  return;
3947 
3948  if ( !f.isLocalFile()) {
3949  KMessageBox::sorry(d->m_frame, i18n("Only executables on local file systems are supported."));
3950  return;
3951  }
3952 
3953  TQString path = f.path();
3954  KRun::shellQuote( path );
3955  execEdit->setText( path );
3956 }
3957 
3958 class TDEApplicationPropsPlugin::TDEApplicationPropsPluginPrivate
3959 {
3960 public:
3961  TDEApplicationPropsPluginPrivate()
3962  {
3963  m_kdesktopMode = TQCString(tqApp->name()) == "kdesktop"; // nasty heh?
3964  }
3965  ~TDEApplicationPropsPluginPrivate()
3966  {
3967  }
3968 
3969  TQFrame *m_frame;
3970  bool m_kdesktopMode;
3971 };
3972 
3973 TDEApplicationPropsPlugin::TDEApplicationPropsPlugin( KPropertiesDialog *_props )
3974  : KPropsDlgPlugin( _props )
3975 {
3976  d = new TDEApplicationPropsPluginPrivate;
3977  d->m_frame = properties->addPage(i18n("&Application"));
3978  TQVBoxLayout *toplayout = new TQVBoxLayout( d->m_frame, 0, KDialog::spacingHint());
3979 
3980  TQIconSet iconSet;
3981  TQPixmap pixMap;
3982 
3983  addExtensionButton = new TQPushButton( TQString::null, d->m_frame );
3984  iconSet = SmallIconSet( "back" );
3985  addExtensionButton->setIconSet( iconSet );
3986  pixMap = iconSet.pixmap( TQIconSet::Small, TQIconSet::Normal );
3987  addExtensionButton->setFixedSize( pixMap.width()+8, pixMap.height()+8 );
3988  connect( addExtensionButton, TQT_SIGNAL( clicked() ),
3989  TQT_SLOT( slotAddExtension() ) );
3990 
3991  delExtensionButton = new TQPushButton( TQString::null, d->m_frame );
3992  iconSet = SmallIconSet( "forward" );
3993  delExtensionButton->setIconSet( iconSet );
3994  delExtensionButton->setFixedSize( pixMap.width()+8, pixMap.height()+8 );
3995  connect( delExtensionButton, TQT_SIGNAL( clicked() ),
3996  TQT_SLOT( slotDelExtension() ) );
3997 
3998  TQLabel *l;
3999 
4000  TQGridLayout *grid = new TQGridLayout(2, 2);
4001  grid->setColStretch(1, 1);
4002  toplayout->addLayout(TQT_TQLAYOUT(grid));
4003 
4004  if ( d->m_kdesktopMode )
4005  {
4006  // in kdesktop the name field comes from the first tab
4007  nameEdit = 0L;
4008  }
4009  else
4010  {
4011  l = new TQLabel(i18n("Name:"), d->m_frame, "Label_4" );
4012  grid->addWidget(l, 0, 0);
4013 
4014  nameEdit = new KLineEdit( d->m_frame, "LineEdit_3" );
4015  grid->addWidget(nameEdit, 0, 1);
4016  }
4017 
4018  l = new TQLabel(i18n("Description:"), d->m_frame, "Label_5" );
4019  grid->addWidget(l, 1, 0);
4020 
4021  genNameEdit = new KLineEdit( d->m_frame, "LineEdit_4" );
4022  grid->addWidget(genNameEdit, 1, 1);
4023 
4024  l = new TQLabel(i18n("Comment:"), d->m_frame, "Label_3" );
4025  grid->addWidget(l, 2, 0);
4026 
4027  commentEdit = new KLineEdit( d->m_frame, "LineEdit_2" );
4028  grid->addWidget(commentEdit, 2, 1);
4029 
4030  l = new TQLabel(i18n("File types:"), d->m_frame);
4031  toplayout->addWidget(l, 0, AlignLeft);
4032 
4033  grid = new TQGridLayout(4, 3);
4034  grid->setColStretch(0, 1);
4035  grid->setColStretch(2, 1);
4036  grid->setRowStretch( 0, 1 );
4037  grid->setRowStretch( 3, 1 );
4038  toplayout->addLayout(TQT_TQLAYOUT(grid), 2);
4039 
4040  extensionsList = new TQListBox( d->m_frame );
4041  extensionsList->setSelectionMode( TQListBox::Extended );
4042  grid->addMultiCellWidget(extensionsList, 0, 3, 0, 0);
4043 
4044  grid->addWidget(addExtensionButton, 1, 1);
4045  grid->addWidget(delExtensionButton, 2, 1);
4046 
4047  availableExtensionsList = new TQListBox( d->m_frame );
4048  availableExtensionsList->setSelectionMode( TQListBox::Extended );
4049  grid->addMultiCellWidget(availableExtensionsList, 0, 3, 2, 2);
4050 
4051  TQString path = properties->kurl().path() ;
4052  TQFile f( path );
4053  if ( !f.open( IO_ReadOnly ) )
4054  return;
4055  f.close();
4056 
4057  KDesktopFile config( path );
4058  TQString commentStr = config.readComment();
4059  TQString genNameStr = config.readGenericName();
4060 
4061  TQStringList selectedTypes = config.readListEntry( "X-TDE-ServiceTypes" );
4062  // For compatibility with KDE 1.x
4063  selectedTypes += config.readListEntry( "MimeType", ';' );
4064 
4065  TQString nameStr = config.readName();
4066  if ( nameStr.isEmpty() || d->m_kdesktopMode ) {
4067  // We'll use the file name if no name is specified
4068  // because we _need_ a Name for a valid file.
4069  // But let's do it in apply, not here, so that we pick up the right name.
4070  setDirty();
4071  }
4072 
4073  commentEdit->setText( commentStr );
4074  genNameEdit->setText( genNameStr );
4075  if ( nameEdit )
4076  nameEdit->setText( nameStr );
4077 
4078  selectedTypes.sort();
4079  TQStringList::Iterator sit = selectedTypes.begin();
4080  for( ; sit != selectedTypes.end(); ++sit ) {
4081  if ( !((*sit).isEmpty()) )
4082  extensionsList->insertItem( *sit );
4083  }
4084 
4085  KMimeType::List mimeTypes = KMimeType::allMimeTypes();
4086  TQValueListIterator<KMimeType::Ptr> it2 = mimeTypes.begin();
4087  for ( ; it2 != mimeTypes.end(); ++it2 )
4088  addMimeType ( (*it2)->name() );
4089 
4090  updateButton();
4091 
4092  connect( extensionsList, TQT_SIGNAL( highlighted( int ) ),
4093  this, TQT_SLOT( updateButton() ) );
4094  connect( availableExtensionsList, TQT_SIGNAL( highlighted( int ) ),
4095  this, TQT_SLOT( updateButton() ) );
4096 
4097  connect( addExtensionButton, TQT_SIGNAL( clicked() ),
4098  this, TQT_SIGNAL( changed() ) );
4099  connect( delExtensionButton, TQT_SIGNAL( clicked() ),
4100  this, TQT_SIGNAL( changed() ) );
4101  if ( nameEdit )
4102  connect( nameEdit, TQT_SIGNAL( textChanged( const TQString & ) ),
4103  this, TQT_SIGNAL( changed() ) );
4104  connect( commentEdit, TQT_SIGNAL( textChanged( const TQString & ) ),
4105  this, TQT_SIGNAL( changed() ) );
4106  connect( genNameEdit, TQT_SIGNAL( textChanged( const TQString & ) ),
4107  this, TQT_SIGNAL( changed() ) );
4108  connect( availableExtensionsList, TQT_SIGNAL( selected( int ) ),
4109  this, TQT_SIGNAL( changed() ) );
4110  connect( extensionsList, TQT_SIGNAL( selected( int ) ),
4111  this, TQT_SIGNAL( changed() ) );
4112 }
4113 
4114 TDEApplicationPropsPlugin::~TDEApplicationPropsPlugin()
4115 {
4116  delete d;
4117 }
4118 
4119 // TQString TDEApplicationPropsPlugin::tabName () const
4120 // {
4121 // return i18n ("&Application");
4122 // }
4123 
4124 void TDEApplicationPropsPlugin::updateButton()
4125 {
4126  addExtensionButton->setEnabled(availableExtensionsList->currentItem()>-1);
4127  delExtensionButton->setEnabled(extensionsList->currentItem()>-1);
4128 }
4129 
4130 void TDEApplicationPropsPlugin::addMimeType( const TQString & name )
4131 {
4132  // Add a mimetype to the list of available mime types if not in the extensionsList
4133 
4134  bool insert = true;
4135 
4136  for ( uint i = 0; i < extensionsList->count(); i++ )
4137  if ( extensionsList->text( i ) == name )
4138  insert = false;
4139 
4140  if ( insert )
4141  {
4142  availableExtensionsList->insertItem( name );
4143  availableExtensionsList->sort();
4144  }
4145 }
4146 
4147 bool TDEApplicationPropsPlugin::supports( KFileItemList _items )
4148 {
4149  // same constraints as KExecPropsPlugin : desktop file with Type = Application
4150  return KExecPropsPlugin::supports( _items );
4151 }
4152 
4153 void TDEApplicationPropsPlugin::applyChanges()
4154 {
4155  TQString path = properties->kurl().path();
4156 
4157  TQFile f( path );
4158 
4159  if ( !f.open( IO_ReadWrite ) ) {
4160  KMessageBox::sorry( 0, i18n("<qt>Could not save properties. You do not "
4161  "have sufficient access to write to <b>%1</b>.</qt>").arg(path));
4162  return;
4163  }
4164  f.close();
4165 
4166  KSimpleConfig config( path );
4167  config.setDesktopGroup();
4168  config.writeEntry( "Type", TQString::fromLatin1("Application"));
4169  config.writeEntry( "Comment", commentEdit->text() );
4170  config.writeEntry( "Comment", commentEdit->text(), true, false, true ); // for compat
4171  config.writeEntry( "GenericName", genNameEdit->text() );
4172  config.writeEntry( "GenericName", genNameEdit->text(), true, false, true ); // for compat
4173 
4174  TQStringList selectedTypes;
4175  for ( uint i = 0; i < extensionsList->count(); i++ )
4176  selectedTypes.append( extensionsList->text( i ) );
4177 
4178  config.writeEntry( "MimeType", selectedTypes, ';' );
4179  config.writeEntry( "X-TDE-ServiceTypes", "" );
4180  // hmm, actually it should probably be the contrary (but see also typeslistitem.cpp)
4181 
4182  TQString nameStr = nameEdit ? nameEdit->text() : TQString::null;
4183  if ( nameStr.isEmpty() ) // nothing entered, or widget not existing at all (kdesktop mode)
4184  nameStr = nameFromFileName(properties->kurl().fileName());
4185 
4186  config.writeEntry( "Name", nameStr );
4187  config.writeEntry( "Name", nameStr, true, false, true );
4188 
4189  config.sync();
4190 }
4191 
4192 void TDEApplicationPropsPlugin::slotAddExtension()
4193 {
4194  TQListBoxItem *item = availableExtensionsList->firstItem();
4195  TQListBoxItem *nextItem;
4196 
4197  while ( item )
4198  {
4199  nextItem = item->next();
4200 
4201  if ( item->isSelected() )
4202  {
4203  extensionsList->insertItem( item->text() );
4204  availableExtensionsList->removeItem( availableExtensionsList->index( item ) );
4205  }
4206 
4207  item = nextItem;
4208  }
4209 
4210  extensionsList->sort();
4211  updateButton();
4212 }
4213 
4214 void TDEApplicationPropsPlugin::slotDelExtension()
4215 {
4216  TQListBoxItem *item = extensionsList->firstItem();
4217  TQListBoxItem *nextItem;
4218 
4219  while ( item )
4220  {
4221  nextItem = item->next();
4222 
4223  if ( item->isSelected() )
4224  {
4225  availableExtensionsList->insertItem( item->text() );
4226  extensionsList->removeItem( extensionsList->index( item ) );
4227  }
4228 
4229  item = nextItem;
4230  }
4231 
4232  availableExtensionsList->sort();
4233  updateButton();
4234 }
4235 
4236 
4237 
4238 #include "kpropertiesdialog.moc"
KURLPropsPlugin::KURLPropsPlugin
KURLPropsPlugin(KPropertiesDialog *_props)
Constructor.
Definition: kpropertiesdialog.cpp:2604
KPropertiesDialog::slotCancel
virtual void slotCancel()
Called when the user presses &#39;Cancel&#39;.
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 &#39;MetaInfo&#39; plugin.
Definition: kmetaprops.cpp:245
KPropsDlgPlugin::isDesktopFile
static bool isDesktopFile(KFileItem *_item)
Convenience method for most ::supports methods.
Definition: kpropertiesdialog.cpp:620
KPropertiesDialog::items
KFileItemList items() const
Definition: kpropertiesdialog.h:267
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
KExecPropsPlugin::KExecPropsPlugin
KExecPropsPlugin(KPropertiesDialog *_props)
Constructor.
Definition: kpropertiesdialog.cpp:3660
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:3413
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 &#39;Permissions&#39; plugin.
Definition: kpropertiesdialog.cpp:2225
KFilePermissionsPropsPlugin::applyChanges
virtual void applyChanges()
Applies all changes to the file.
Definition: kpropertiesdialog.cpp:2483
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
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:4153
KDiskFreeSp::readDF
int readDF(const TQString &mountPoint)
Call this to fire a search on the disk usage information for mountPoint.
Definition: kdiskfreesp.cpp:80
KPropertiesDialog::kurl
const KURL & kurl() const
The URL of the file that has its properties being displayed.
Definition: kpropertiesdialog.h:253
KBindingPropsPlugin
Used to edit the files containing [Desktop Entry] Type=MimeType.
Definition: kpropertiesdialog.h:692
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
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
&#39;Permissions&#39; 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:2723
TDEIconButton::setIconSize
void setIconSize(int size)
Sets the size of the icon to be shown / selected.
Definition: kicondialog.cpp:701
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:3131
TDEApplicationPropsPlugin::TDEApplicationPropsPlugin
TDEApplicationPropsPlugin(KPropertiesDialog *_props)
Constructor.
Definition: kpropertiesdialog.cpp:3973
KURLRequester::url
TQString url() const
Definition: kurlrequester.cpp:268
KFilePropsPlugin
&#39;General&#39; 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 &#39;Ok&#39;.
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&#39;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&#39;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&#39;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:2671
KBindingPropsPlugin::applyChanges
virtual void applyChanges()
Applies all changes to the file.
Definition: kpropertiesdialog.cpp:2832
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:3909
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:3166
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 &#39;General&#39; 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
  • tdeabc
  • tdecmshell
  • tdecore
  • tdefx
  • tdehtml
  • tdeinit
  • tdeio
  •   bookmarks
  •   httpfilter
  •   kpasswdserver
  •   kssl
  •   tdefile
  •   tdeio
  •   tdeioexec
  • tdeioslave
  •   http
  • tdemdi
  •   tdemdi
  • tdenewstuff
  • tdeparts
  • tdeprint
  • tderandr
  • tderesources
  • tdespell2
  • tdesu
  • tdeui
  • tdeunittest
  • tdeutils
  • tdewallet
Generated for tdeio/tdefile by doxygen 1.8.13
This website is maintained by Timothy Pearson.