~ubuntu-branches/debian/squeeze/kdelibs/squeeze

« back to all changes in this revision

Viewing changes to .pc/21_kfreebsd_support.diff/kio/kfile/kpropertiesdialog.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Modestas Vainius
  • Date: 2010-08-07 23:20:21 UTC
  • Revision ID: james.westby@ubuntu.com-20100807232021-owvkgp5wpc076s33
Tags: 4:3.5.10.dfsg.1-5
* Change by email address to @debian.org.
* Drop common HTML docs from kdelibs-data package. Instead suggest
  kdelibs5-data which ships them (Closes: #591609). What's more, whoever
  wants to view docs, will have to install khelpcenter4 which pulls in
  kdelibs5-data anyway.
* Switch to dpkg-source format 3.0 (quilt):
  - drop simple-patchsys.mk from debian/rules;
  - add debian/patches/series file.
* Fix corruption of zip files caused by wrong encoding of umlauts in kzip
  (patch 67_kio_zip_file_encoding.diff). (Closes: #563942) Thanks to Bjoern
  Ricks for the patch.
* Support opening of KDE 4 khelpcenter in Help -> Handbook. (Closes: #525621)
  Thanks to Ben Burton for the patch.
* Do not recurse into .pc subdirectory with doxygen 
  (patch debian/patches/02_exclude_pc_from_dox.diff).
* Urgency=medium due to multiple RC bug fixes.

Show diffs side-by-side

added added

removed removed

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