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

tdeio/tdefile

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

tdeio/tdefile

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

tdeio/tdefile

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