[prev in list] [next in list] [prev in thread] [next in thread] 

List:       kde-core-devel
Subject:    KConfigureDialog (finally with code)
From:       Matthias Kretz <kretz () kde ! org>
Date:       2003-08-16 17:04:33
[Download RAW message or body]

[Attachment #2 (multipart/mixed)]


[sorry for the garbled text, saving in drafts folder of KMail did that - and I 
don't feel like writing it again]

Hi,

I've been telling this list of the configuration dialog merging stuff befor=
e...
Now I've finally implemented most of the things I proposed. I'd like to get=
 it into CVS as soon as possible so that KView and Kontact may begin using =
it.

Short summary:
KConfigureDialog is simple class to be used in your application with only t=
wo lines of code :-)
m_dlg =3D new KConfigureDialog( this );
m_dlg->show();

The configuration dialog then looks for all KCModules with X-KDE-ParentApp =
set to the application's instance name and embeds them into the KCMultiDial=
og. This works using KTrader - not the KControl directories.

If you have some special needs (think Kontact) there's another ctor:
m_dlg =3D new KConfigureDialog( QStringList::split( ";", "kmailpart;knodepa=
rt;knotespart;korganizerpart", this );

The dialog then merges all KCMs with X-KDE-ParentApp set to the app's insta=
nce name + all the KCMs with X-KDE-KCDParents=3D{kmailpart,knodepart,knotesp=
art,korganizerpart}.

A special plugin configuration page is in the works that shows the plugins =
KCM(s) on that page so that the user (hopefully) understands the connection=
 between the plugins config and the plugin being activated.

I've seen several apps installing KCMs into KControl, but I don't believe t=
he configuration of applications belongs into KControl - even for Konqueror=
=2E Though the framework would make it easy to open up all KCMs from all ap=
plications (if anybody would want to do that) and configure all apps in one=
 central place - might be nice for admins to create a default config, thoug=
h...

Ah forgot one thing: Your app wants to know when the user changed the confi=
g in the dialog. That's what KCDDispatcher can do for you. Every part of yo=
ur application (I'm missing the right terminology here), like KParts::MainW=
indow, KParts and Plugins have there own independent config and need to be =
informed. This is what you have to do:
KCDDispatcher::self()->registerInstance( instance()->instanceName(), this, =
SLOT( readSettings() ) );

Though I think the need for KCDDispatcher might go away if KPrefs goes into=
 kdelibs. Because the KCMs are loaded inprocess and therefor the KPrefs obj=
ect could be the same for the app and the KCMs.

-- 
C'ya
        Matthias
________________________________________________________
Matthias Kretz (Germany)                          <><
http://Vir.homeip.net/
MatthiasKretz@gmx.net, kretz@kde.org,
Matthias.Kretz@urz.uni-heidelberg.de

["kcd.patch" (text/x-diff)]

Index: Makefile.am
===================================================================
RCS file: /home/kde/kdelibs/kutils/Makefile.am,v
retrieving revision 1.14
diff -u -3 -p -r1.14 Makefile.am
--- Makefile.am	6 Jun 2003 21:56:13 -0000	1.14
+++ Makefile.am	16 Aug 2003 17:00:50 -0000
@@ -6,12 +6,14 @@ libkutils_la_LDFLAGS = $(all_libraries) 
 libkutils_la_LIBADD  = ../kio/libkio.la
 
 libkutils_la_SOURCES = kfind.cpp kfinddialog.cpp kreplace.cpp \
                kreplacedialog.cpp \
-                       kcmoduleinfo.cpp kcmoduleloader.cpp \
                kcmultidialog.cpp kmultitabbar.cpp
-
- # kreplace.cpp
+                       kcmoduleinfo.cpp kcmoduleloader.cpp \
kcmultidialog.cpp kmultitabbar.cpp \ +                       \
kcddispatcher.cpp kconfiguredialog.cpp  
 include_HEADERS = kfind.h kfinddialog.h kreplace.h kreplacedialog.h \
-	              kcmoduleinfo.h kcmoduleloader.h kcmultidialog.h \
kmultitabbar.h +                  kcmoduleinfo.h kcmoduleloader.h \
kcmultidialog.h kmultitabbar.h \ +                  kcddispatcher.h \
kconfiguredialog.h +
+noinst_HEADERS = kmultitabbar_p.h
 
 METASOURCES = AUTO
 
Index: kcddispatcher.cpp
===================================================================
RCS file: kcddispatcher.cpp
diff -N kcddispatcher.cpp
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ kcddispatcher.cpp	16 Aug 2003 17:00:50 -0000
@@ -0,0 +1,113 @@
+/*  This file is part of the KDE project
+    Copyright (C) 2003 Matthias Kretz <kretz@kde.org>
+
+    This library is free software; you can redistribute it and/or
+    modify it under the terms of the GNU Library General Public
+    License version 2 as published by the Free Software Foundation.
+
+    This library is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+    Library General Public License for more details.
+
+    You should have received a copy of the GNU Library General Public \
License +    along with this library; see the file COPYING.LIB.  If not, \
write to +    the Free Software Foundation, Inc., 59 Temple Place - Suite \
330, +    Boston, MA 02111-1307, USA.
+
+*/
+
+#include "kcddispatcher.h"
+
+#include <qstrlist.h>
+#include <qcstring.h>
+#include <qsignal.h>
+
+#include <kstaticdeleter.h>
+#include <kdebug.h>
+#include <kinstance.h>
+
+//class KCDDispatcher::KCDDispatcherPrivate
+//{
+//};
+
+static KStaticDeleter<KCDDispatcher> ksd_kpd;
+
+KCDDispatcher * KCDDispatcher::m_self = 0;
+
+KCDDispatcher * KCDDispatcher::self()
+{
+	kdDebug( 701 ) << k_funcinfo << endl;
+	if( m_self == 0 )
+		ksd_kpd.setObject( m_self, new KCDDispatcher() );
+	return m_self;
+}
+
+KCDDispatcher::KCDDispatcher( QObject * parent, const char * name )
+	: QObject( parent, name )
+	//, d( 0 )
+{
+	kdDebug( 701 ) << k_funcinfo << endl;
+}
+
+KCDDispatcher::~KCDDispatcher()
+{
+	kdDebug( 701 ) << k_funcinfo << endl;
+	//delete d;
+}
+
+void KCDDispatcher::registerInstance( const QCString & instanceName, \
QObject * recv, const char * slot ) +{
+	kdDebug( 701 ) << k_funcinfo << instanceName << endl;
+	m_instanceName[ recv ] = instanceName;
+	QSignal * sig = m_signals.contains( instanceName ) ?
+		m_signals[ instanceName ] :
+		m_signals[ instanceName ] = new QSignal( this, "signal dispatcher" );
+	sig->connect( recv, slot );
+
+	++m_instanceNameCount[ instanceName ];
+	connect( recv, SIGNAL( destroyed( QObject * ) ), this, SLOT( \
unregisterInstance( QObject * ) ) ); +}
+
+void KCDDispatcher::registerInstance( const KInstance * instance, QObject \
* recv, const char * slot ) +{
+	registerInstance( instance->instanceName(), recv, slot );
+}
+
+QStrList KCDDispatcher::instanceNames() const
+{
+	kdDebug( 701 ) << k_funcinfo << endl;
+	QStrList names;
+	for( QMap<QCString, int>::const_iterator it = \
m_instanceNameCount.begin(); it != m_instanceNameCount.end(); ++it ) +		if( \
*it > 0 ) +			names.append( it.key() );
+	return names;
+}
+
+void KCDDispatcher::reparseConfiguration( const QCString & instanceName )
+{
+	kdDebug( 701 ) << k_funcinfo << instanceName << endl;
+	QSignal * sig = m_signals[ instanceName ];
+	if( sig )
+	{
+		kdDebug( 701 ) << "emit signal to instance" << endl;
+		sig->activate();
+	}
+}
+
+void KCDDispatcher::unregisterInstance( QObject * obj )
+{
+	kdDebug( 701 ) << k_funcinfo << endl;
+	QCString name = m_instanceName[ obj ];
+	m_instanceName.remove( obj ); //obj will be destroyed when we return, so \
we better remove this entry +	--m_instanceNameCount[ name ];
+	if( m_instanceNameCount[ name ] == 0 )
+	{
+		delete m_signals[ name ];
+		m_signals.remove( name );
+	}
+}
+
+#include "kcddispatcher.moc"
+
+// vim: sw=4 ts=4 noet
Index: kcddispatcher.h
===================================================================
RCS file: kcddispatcher.h
diff -N kcddispatcher.h
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ kcddispatcher.h	16 Aug 2003 17:00:50 -0000
@@ -0,0 +1,92 @@
+/*  This file is part of the KDE project
+    Copyright (C) 2003 Matthias Kretz <kretz@kde.org>
+
+    This library is free software; you can redistribute it and/or
+    modify it under the terms of the GNU Library General Public
+    License version 2 as published by the Free Software Foundation.
+
+    This library is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+    Library General Public License for more details.
+
+    You should have received a copy of the GNU Library General Public \
License +    along with this library; see the file COPYING.LIB.  If not, \
write to +    the Free Software Foundation, Inc., 59 Temple Place - Suite \
330, +    Boston, MA 02111-1307, USA.
+
+*/
+
+#ifndef KCDDISPATCHER_H
+#define KCDDISPATCHER_H
+
+#include <qobject.h>
+#include <qmap.h>
+
+class QCString;
+class QSignal;
+class QStrList;
+template<class T> class KStaticDeleter;
+class KInstance;
+
+class KCDDispatcher : public QObject
+{
+	friend class KStaticDeleter<KCDDispatcher>;
+
+	Q_OBJECT
+	public:
+		static KCDDispatcher * self();
+
+		/**
+		 * Register a slot to be called when the configuration for the instance
+		 * associated with @p instanceName has changed. The instanceName is the
+		 * name that is passed to KGenericFactory (if it is used). You can query
+		 * it with KGenericFactory<YourClassName>::instance()->instanceName().
+		 * This is the same name that is put into the .desktop file of the KCMs
+		 * for the X-KDE-KCDParents.
+		 *
+		 * @param instanceName The internal name of the KInstance object and
+		 *                     also the value of X-KDE-KCDParents.
+		 * @param recv         The object that should receive the signal
+		 * @param slot         The slot to be called: SLOT( slotName() )
+		 */
+		void registerInstance( const QCString & instanceName, QObject * recv, \
const char * slot ); +
+		/**
+		 * Convenience function. See above for what it does.
+		 */
+		void registerInstance( const KInstance * instance, QObject * recv, const \
char * slot ); +
+		/**
+		 * @return a list of all the instance names that are currently
+		 * registered
+		 */
+		QStrList instanceNames() const;
+
+	public slots:
+		/**
+		 * Call this slot when the configuration belonging to the associated
+		 * instance name has changed. The registered slot will be called.
+		 *
+		 * @param instanceName The value of X-KDE-KCDParents.
+		 */
+		void reparseConfiguration( const QCString & instanceName );
+
+	private slots:
+		void unregisterInstance( QObject * );
+
+	private:
+		KCDDispatcher( QObject * parent = 0, const char * name = 0 );
+		~KCDDispatcher();
+		static KCDDispatcher * m_self;
+
+		QMap<QCString, QSignal *> m_signals;
+		QMap<QCString, int> m_instanceNameCount;
+		QMap<QObject *, QCString> m_instanceName;
+
+		class KCDDispatcherPrivate;
+		KCDDispatcherPrivate * d;
+};
+
+// vim: sw=4 ts=4 noet
+#endif // KCDDISPATCHER_H
Index: kcmoduleinfo.cpp
===================================================================
RCS file: /home/kde/kdelibs/kutils/kcmoduleinfo.cpp,v
retrieving revision 1.40
diff -u -3 -p -r1.40 kcmoduleinfo.cpp
--- kcmoduleinfo.cpp	21 Jun 2003 00:15:51 -0000	1.40
+++ kcmoduleinfo.cpp	16 Aug 2003 17:00:50 -0000
@@ -2,6 +2,7 @@
   Copyright (c) 1999 Matthias Hoelzer-Kluepfel <hoelzer@kde.org>
   Copyright (c) 2000 Matthias Elter <elter@kde.org>
   Copyright (c) 2003 Daniel Molkentin <molkentin@kde.org>
+  Copyright (c) 2003 Matthias Kretz <kretz@kde.org>
 
   This file is part of the KDE project
   
@@ -21,10 +22,12 @@
 */
 
 
+#include "kcmoduleinfo.h"
+
 #include <kdesktopfile.h>
 #include <kdebug.h>
-
-#include "kcmoduleinfo.h"
+#include <kglobal.h>
+#include <kstandarddirs.h>
 
 KCModuleInfo::KCModuleInfo(const QString& desktopFile, const QString& \
baseGroup)  : _fileName(desktopFile), d(0L)
@@ -62,6 +65,31 @@ KCModuleInfo::KCModuleInfo(const QString
   setGroups(groups);
 }
 
+KCModuleInfo::KCModuleInfo( KService::Ptr moduleInfo )
+  : _fileName( KGlobal::dirs()->findResource( "services", \
moduleInfo->desktopEntryPath() ) ) +{
+  kdDebug() << k_funcinfo << _fileName << endl;
+  _allLoaded = false;
+
+  _service = moduleInfo;
+  Q_ASSERT(_service != 0L);
+
+  // set the modules simple attributes
+  setName(_service->name());
+  setComment(_service->comment());
+  setIcon(_service->icon());
+
+  // library and factory
+  setLibrary(_service->library());
+
+  // get the keyword list
+  setKeywords(_service->keywords());
+
+  // get the groups list
+  KDesktopFile desktop(_fileName);
+  setGroups( QStringList::split( ';', desktop.readEntry( "X-KDE-Groups" ) \
) ); +}
+
 KCModuleInfo::KCModuleInfo( const KCModuleInfo &rhs )
     : d( 0 )
 {
@@ -82,6 +110,7 @@ KCModuleInfo &KCModuleInfo::operator=( c
     _fileName = rhs._fileName;
     _doc = rhs._doc;
     _comment = rhs._comment;
+    _kcdparents = rhs._kcdparents;
     _needsRootPrivileges = rhs._needsRootPrivileges;
     _isHiddenByDefault = rhs._isHiddenByDefault;
     _allLoaded = rhs._allLoaded;
@@ -104,6 +133,9 @@ KCModuleInfo::loadAll() 
   // library and factory
   setHandle(desktop.readEntry("X-KDE-FactoryName"));
 
+  // KCD parent
+  setKCDParents(desktop.readListEntry("X-KDE-KCDParents"));
+
   // does the module need super user privileges?
   setNeedsRootPrivileges(desktop.readBoolEntry("X-KDE-RootOnly", false));
 
@@ -149,6 +181,15 @@ KCModuleInfo::handle() const
      return _lib;
 
   return _handle;
+}
+
+const QStringList &
+KCModuleInfo::KCDParents() const
+{
+  if( !_allLoaded )
+    const_cast<KCModuleInfo*>( this )->loadAll();
+
+  return _kcdparents;
 }
 
 bool
Index: kcmoduleinfo.h
===================================================================
RCS file: /home/kde/kdelibs/kutils/kcmoduleinfo.h,v
retrieving revision 1.21
diff -u -3 -p -r1.21 kcmoduleinfo.h
--- kcmoduleinfo.h	10 Jun 2003 13:06:19 -0000	1.21
+++ kcmoduleinfo.h	16 Aug 2003 17:00:51 -0000
@@ -2,6 +2,7 @@
   Copyright (c) 1999 Matthias Hoelzer-Kluepfel <hoelzer@kde.org>
   Copyright (c) 2000 Matthias Elter <elter@kde.org>
   Copyright (c) 2003 Daniel Molkentin <molkentin@kde.org>
+  Copyright (c) 2003 Matthias Kretz <kretz@kde.org>
 
   This file is part of the KDE project
   
@@ -47,37 +48,83 @@ public:
   /**
    * Constructs a KCModuleInfo, note that you will have to take care about \
                the deletion
    * yourself!
-   **/
+   */
   KCModuleInfo(const QString& desktopFile, const QString& baseGroup /* = \
QString::fromLatin1("settings")*/); +
+  /**
+   * Construct a KCModuleInfo from a KService object.
+   */
+  KCModuleInfo( KService::Ptr moduleInfo );
+
   KCModuleInfo( const KCModuleInfo &rhs );
   KCModuleInfo &operator=( const KCModuleInfo &rhs );
   ~KCModuleInfo();
 
-  /** @return the filename passed in the constructor **/
+  /**
+   * @return the filename of the .desktop file that describes the KCM
+   */
   QString fileName() const { return _fileName; };
-  /** @return the list of **/
+
+  /**
+   * @return the list of groups this KCM belongs to.
+   */
   const QStringList &groups() const { return _groups; };
-  /** @return **/
+
+  /**
+   * @return the keywords associated with this KCM.
+   */
   const QStringList &keywords() const { return _keywords; };
-  
+
   // changed from name() to avoid abiguity with QObject::name() on \
                multiple inheritance
-  /** @return the modules name **/
+  /**
+   * @return the module's (translated) name
+   */
   QString moduleName() const { return _name; };
-  /** @return a pointer to KService created from the modules .desktop file \
**/ +
+  /**
+   * @return a @ref KSharedPtr to @ref KService created from the modules \
.desktop file +   */
   KService::Ptr service() const { return _service; };
-  /** @return the comment field **/
+
+  /**
+   * @return the module's (translated) comment field
+   */
   QString comment() const { return _comment; };
-  /** @return the icon name **/
+
+  /**
+   * @return the module's icon name
+   */
   QString icon() const { return _icon; };
-  /** @return the path of the module documentation **/
+
+  /**
+   * @return the path of the module's documentation
+   */
   QString docPath() const;
-  /** @return the library name **/
+
+  /**
+   * @return the library name
+   */
   QString library() const { return _lib; };
-  /** @return a handle (usually the contents of the FactoryName field) **/
+
+  /**
+   * @return a handle (usually the contents of the FactoryName field)
+   */
   QString handle() const;
-  /** @return wether the module might require root permissions **/
+
+  /**
+   * @return the KCD parent
+   */
+  const QStringList & KCDParents() const;
+
+  /**
+   * @return whether the module might require root permissions
+   */
   bool needsRootPrivileges() const;
-  /** @return the isHiddenByDefault attribute. @deprecated **/
+
+  /**
+   * @deprecated
+   * @return the isHiddenByDefault attribute.
+   */
   bool isHiddenByDefault() const;
 
   QCString moduleId() const;
@@ -91,6 +138,7 @@ protected:
   void setIcon(const QString &icon) { _icon = icon; };
   void setLibrary(const QString &lib) { _lib = lib; };
   void setHandle(const QString &handle) { _handle = handle; };
+  void setKCDParents(const QStringList &kcdparents) { _kcdparents = \
kcdparents; }  void setNeedsRootPrivileges(bool needsRootPrivileges) { \
_needsRootPrivileges = needsRootPrivileges; };  void \
setIsHiddenByDefault(bool isHiddenByDefault) { _isHiddenByDefault = \
isHiddenByDefault; };  void setDocPath(const QString &p) { _doc = p; };
@@ -99,7 +147,7 @@ protected:
 private:
 
   // when adding members, don't forget to take care about them in the \
                assignment operator
-  QStringList _groups, _keywords;
+  QStringList _groups, _keywords, _kcdparents;
   QString     _name, _icon, _lib, _handle, _fileName, _doc, _comment;
   bool        _needsRootPrivileges : 1; 
   bool        _isHiddenByDefault : 1;
Index: kcmultidialog.cpp
===================================================================
RCS file: /home/kde/kdelibs/kutils/kcmultidialog.cpp,v
retrieving revision 1.29
diff -u -3 -p -r1.29 kcmultidialog.cpp
--- kcmultidialog.cpp	26 Jun 2003 19:06:23 -0000	1.29
+++ kcmultidialog.cpp	16 Aug 2003 17:00:51 -0000
@@ -1,6 +1,7 @@
 /*
    Copyright (c) 2000 Matthias Elter <elter@kde.org>
    Copyright (c) 2003 Daniel Molkentin <molkentin@kde.org>
+   Copyright (c) 2003 Matthias Kretz <kretz@kde.org>
 
    This library is free software; you can redistribute it and/or
    modify it under the terms of the GNU Library General Public
@@ -29,19 +30,35 @@
 #include <klibloader.h>
 #include <krun.h>
 #include <kprocess.h>
+#include <kaboutdata.h>
 
 #include "kcmultidialog.h"
 #include "kcmultidialog.moc"
 #include "kcmoduleloader.h"
+#include <assert.h>
 
 KCMultiDialog::KCMultiDialog(const QString& baseGroup, QWidget *parent, \
const char *name, bool modal)  : KDialogBase(IconList, i18n("Configure"), \
                Help | Default |Cancel | Apply | Ok, Ok,
-                parent, name, modal, true), d(0L)
+                parent, name, modal, true)
+  , _baseGroup(baseGroup)
 {
+    init();
+}
+
+KCMultiDialog::KCMultiDialog( int dialogFace, const QString & caption, \
QWidget * parent, const char * name, bool modal ) +    : KDialogBase( \
dialogFace, caption, Help | Default | Cancel | Apply | Ok, Ok, +            \
parent, name, modal, true ) +{
+    init();
+}
+
+inline void KCMultiDialog::init()
+{
+    d = 0L;
     enableButton(Apply, false);
     connect(this, SIGNAL(aboutToShowPage(QWidget *)), this, \
SLOT(slotAboutToShow(QWidget *)));  setInitialSize(QSize(640,480));
-	_baseGroup = baseGroup;
+    modulePrefParent.setAutoDelete( true );
 }
 
 KCMultiDialog::~KCMultiDialog()
@@ -65,12 +82,32 @@ void KCMultiDialog::slotDefault()
     }
 }
 
+void KCMultiDialog::apply()
+{
+    QStringList updatedModules;
+    for( KCModule * m = modules.first(); m; m = modules.next() )
+    {
+        kdDebug() << k_funcinfo << m->name() << ' ' << ( m->aboutData() ? \
m->aboutData()->appName() : "" ) << endl; +        if( m->changed() )
+        {
+            m->save();
+            QStringList * names = modulePrefParent[ m ];
+            kdDebug() << k_funcinfo << *names << " saved and added to the \
list" << endl; +            for( QStringList::ConstIterator it = \
names->begin(); it != names->end(); ++it ) +                if( \
updatedModules.find( *it ) == updatedModules.end() ) +                    \
updatedModules.append( *it ); +        }
+    }
+    for( QStringList::const_iterator it = updatedModules.begin(); it != \
updatedModules.end(); ++it ) +    {
+        kdDebug() << k_funcinfo << *it << " " << ( *it ).latin1() << endl;
+        emit configCommitted( ( *it ).latin1() );
+    }
+}
+
 void KCMultiDialog::slotApply()
 {
-    QPtrListIterator<KCModule> it(modules);
-    for (; it.current(); ++it)
-      (*it)->save();
-    clientChanged(false);
+    apply();
 
     emit applyClicked();
 }
@@ -78,9 +115,7 @@ void KCMultiDialog::slotApply()
 
 void KCMultiDialog::slotOk()
 {
-    QPtrListIterator<KCModule> it(modules);
-    for (; it.current(); ++it)
-      (*it)->save();
+    apply();
     accept();
 
     emit okClicked();
@@ -103,7 +138,14 @@ void KCMultiDialog::slotHelp()
 
 void KCMultiDialog::clientChanged(bool state)
 {
-    enableButton(Apply, state);
+    kdDebug( 1208 ) << k_funcinfo << state << endl;
+    for( KCModule * m = modules.first(); m; m = modules.next() )
+        if( m->changed() )
+        {
+            enableButton( Apply, true );
+            return;
+        }
+    enableButton( Apply, false );
 }
 
 void KCMultiDialog::addModule(const QString& path, bool withfallback)
@@ -116,18 +158,27 @@ void KCMultiDialog::addModule(const QStr
     }
 
     KCModuleInfo info(path, _baseGroup);
+    addModule(info, withfallback);
+}
+
+void KCMultiDialog::addModule(const KCModuleInfo& moduleinfo, bool \
withfallback) +{
+    kdDebug(1208) << "KCMultiDialog::addModule " << \
moduleinfo.moduleName() << " for KCDParents=" << moduleinfo.KCDParents() << \
endl;  
     QHBox* page = 0;
-    if (!info.service()->noDisplay())
-        page = addHBoxPage(info.moduleName(), info.comment(),
-                              KGlobal::iconLoader()->loadIcon(info.icon(), \
KIcon::Desktop, KIcon::SizeMedium)); +    if \
(!moduleinfo.service()->noDisplay()) +        page = \
addHBoxPage(moduleinfo.moduleName(), moduleinfo.comment(), +                \
KGlobal::iconLoader()->loadIcon(moduleinfo.icon(), KIcon::Desktop, \
KIcon::SizeMedium));  if(!page) {
-        KCModuleLoader::unloadModule(info);
+        KCModuleLoader::unloadModule(moduleinfo);
         return;
     }
-    moduleDict.insert(page, new LoadInfo(path, withfallback));
+    moduleDict.insert(page, new LoadInfo(moduleinfo, withfallback));
     if (modules.isEmpty())
-       slotAboutToShow(page);
+    {
+        kdDebug() << k_funcinfo << moduleinfo.KCDParents() << endl;
+        slotAboutToShow(page);
+    }
 }
 
 void KCMultiDialog::slotAboutToShow(QWidget *page)
@@ -136,13 +187,15 @@ void KCMultiDialog::slotAboutToShow(QWid
     if (!loadInfo)
        return;
 
+    kdDebug() << k_funcinfo << loadInfo->info.KCDParents() << endl;
+
     QApplication::setOverrideCursor(Qt::WaitCursor);
 
     moduleDict.remove(page);
 
-    KCModuleInfo info(loadInfo->path, _baseGroup);
+    KCModule *module = KCModuleLoader::loadModule(loadInfo->info, \
loadInfo->withfallback);  
-    KCModule *module = KCModuleLoader::loadModule(info, \
loadInfo->withfallback); +    kdDebug() << k_funcinfo << \
loadInfo->info.KCDParents() << endl;  
     if (!module)
     {
@@ -152,10 +205,17 @@ void KCMultiDialog::slotAboutToShow(QWid
         return;
     }
 
+    kdDebug() << k_funcinfo << "KCDParents=" << \
loadInfo->info.KCDParents() << endl; +    modulePrefParent.insert( module, \
new QStringList( loadInfo->info.KCDParents() ) );  \
                module->reparent(page,0,QPoint(0,0),true);
     connect(module, SIGNAL(changed(bool)), this, \
SLOT(clientChanged(bool))); +    if( module->changed() )
+    {
+        kdWarning() << "Just loaded a KCModule but it's already changed.";
+        clientChanged( true );
+    }
     //setHelp( docpath, QString::null );
-    _docPath = info.docPath();
+    _docPath = loadInfo->info.docPath();
     modules.append(module);
 
     //KCGlobal::repairAccels( topLevelWidget() );
@@ -164,3 +224,5 @@ void KCMultiDialog::slotAboutToShow(QWid
 
     QApplication::restoreOverrideCursor();
 }
+
+// vim: sw=4 et sts=4
Index: kcmultidialog.h
===================================================================
RCS file: /home/kde/kdelibs/kutils/kcmultidialog.h,v
retrieving revision 1.14
diff -u -3 -p -r1.14 kcmultidialog.h
--- kcmultidialog.h	11 Jan 2003 19:25:15 -0000	1.14
+++ kcmultidialog.h	16 Aug 2003 17:00:51 -0000
@@ -1,6 +1,7 @@
 /*
    Copyright (c) 2000 Matthias Elter <elter@kde.org>
    Copyright (c) 2003 Daniel Molkentin <molkentin@kde.org>
+   Copyright (c) 2003 Matthias Kretz <kretz@kde.org>
 
    This library is free software; you can redistribute it and/or
    modify it under the terms of the GNU Library General Public
@@ -27,6 +28,7 @@
 
 #include <kdialogbase.h>
 #include <kcmodule.h>
+#include "kcmoduleinfo.h"
 
 /**
  * A class that offers a @ref KDialogBase containing arbitrary KControl \
Modules @@ -56,6 +58,21 @@ public:
                   bool modal=false);
 
     /**
+     * Construct a personalized KCMultiDialog.
+     *
+     * @param dialogFace You can use TreeList, Tabbed, Plain, Swallow or
+     *        IconList.
+     * @param caption The dialog caption. Do not specify the application \
name +     *        here. The class will take care of that.
+     * @param parent Parent of the dialog.
+     * @param name Dialog name (for internal use only).
+     * @param modal Controls dialog modality. If @p false, the rest of the
+     *        program interface (example: other dialogs) is accessible \
while +     *        the dialog is open.
+     */
+    KCMultiDialog( int dialogFace, const QString & caption, QWidget * \
parent = 0, const char * name = 0, bool modal = false ); +
+    /**
      * Destructor
      **/
    virtual ~KCMultiDialog();
@@ -71,6 +88,21 @@ public:
      **/
     void addModule(const QString& module, bool withfallback=true);
 
+    /**
+     * Add a module.
+     *
+     * @param moduleinfo Pass a @ref KCModuleInfo object which will be
+     *                   used for creating the module. It will be added
+     *                   to the list of modules the dialog will show.
+     *
+     * @param withfallback Try harder to load the module. Might result
+     *                     in the module appearing outside the dialog.
+     **/
+    void addModule(const KCModuleInfo& moduleinfo, bool \
withfallback=false); +
+signals:
+    void configCommitted( const QCString & instanceName );
+
 protected slots:
     /**
      * This slot is called when the user presses the "Default" Button
@@ -111,15 +143,19 @@ private slots:
     void clientChanged(bool state);
 
 private:
+    void init();
+    void apply();
+
     struct LoadInfo {
-      LoadInfo(const QString &_path, bool _withfallback)
-         : path(_path), withfallback(_withfallback)
+      LoadInfo(const KCModuleInfo &_info, bool _withfallback)
+         : info(_info), withfallback(_withfallback)
          { }
-      QString path;
+      KCModuleInfo info;
       bool withfallback;
     };
     QPtrList<KCModule> modules;
     QPtrDict<LoadInfo> moduleDict;
+    QPtrDict<QStringList>  modulePrefParent;
     QString _docPath;
     QString _baseGroup;
 
Index: kconfiguredialog.cpp
===================================================================
RCS file: kconfiguredialog.cpp
diff -N kconfiguredialog.cpp
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ kconfiguredialog.cpp	16 Aug 2003 17:00:51 -0000
@@ -0,0 +1,161 @@
+/*  This file is part of the KDE project
+    Copyright (C) 2003 Matthias Kretz <kretz@kde.org>
+
+    This library is free software; you can redistribute it and/or
+    modify it under the terms of the GNU Library General Public
+    License version 2 as published by the Free Software Foundation.
+
+    This library is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+    Library General Public License for more details.
+
+    You should have received a copy of the GNU Library General Public \
License +    along with this library; see the file COPYING.LIB.  If not, \
write to +    the Free Software Foundation, Inc., 59 Temple Place - Suite \
330, +    Boston, MA 02111-1307, USA.
+
+*/
+
+#include "kconfiguredialog.h"
+
+#include <qptrlist.h>
+
+#include "kcddispatcher.h"
+#include "kcmultidialog.h"
+#include <kglobal.h>
+#include <klocale.h>
+#include <kinstance.h>
+#include <kservicegroup.h>
+#include <kjanuswidget.h>
+#include <kdebug.h>
+#include <ktrader.h>
+
+class KConfigureDialog::KConfigureDialogPrivate
+{
+	public:
+		KConfigureDialogPrivate()
+			: dlg( 0 )
+		{
+			moduleinfos.setAutoDelete( true );
+		}
+
+		QPtrList<KCModuleInfo> moduleinfos;
+		KCMultiDialog * dlg;
+};
+
+KConfigureDialog::KConfigureDialog( QObject * parent, const char * name )
+	: QObject( parent, name )
+	, d( new KConfigureDialogPrivate )
+{
+	QValueList<KService::Ptr> services = instanceServices();
+	createDialogFromServices( services );
+}
+
+KConfigureDialog::KConfigureDialog( const QStringList & kcdparents, \
QObject * parent, const char * name ) +	: QObject( parent, name )
+	, d( new KConfigureDialogPrivate )
+{
+	QValueList<KService::Ptr> services = instanceServices() + \
KCDParentsServices( kcdparents ); +	createDialogFromServices( services );
+}
+
+KConfigureDialog::~KConfigureDialog()
+{
+	delete d;
+}
+
+void KConfigureDialog::addKPartsPluginPage()
+{
+	kdDebug( 700 ) << k_funcinfo << endl;
+	QValueList<KService::Ptr> services = KTrader::self()->query( "KCModule", \
"Library == 'kpartspluginpage'" ); +	kdDebug( 700 ) << "got " << \
services.count() << " offers" << endl; +	for( \
QValueList<KService::Ptr>::ConstIterator it = services.begin(); it != \
services.end(); ++it ) +	{
+		kdDebug( 700 ) << k_funcinfo << ( *it )->type() << ( *it )->name() << ( \
*it )->library() << endl; +	}
+	KService::Ptr service = services.first();
+	if( service.data() )
+	{
+		KCModuleInfo * moduleinfo = new KCModuleInfo( service );
+		d->moduleinfos.append( moduleinfo );
+		d->dlg->addModule( *moduleinfo );
+	}
+}
+
+void KConfigureDialog::show()
+{
+	return d->dlg->show();
+}
+
+QValueList<KService::Ptr> KConfigureDialog::instanceServices() const
+{
+	kdDebug( 700 ) << k_funcinfo << endl;
+	QString instanceName = KGlobal::instance()->instanceName();
+	kdDebug( 700 ) << "calling KServiceGroup::childGroup( " << instanceName \
<< " )" << endl; +	KServiceGroup::Ptr service = KServiceGroup::childGroup( \
instanceName ); +
+	QValueList<KService::Ptr> ret;
+
+	if( service && service->isValid() )
+	{
+		kdDebug( 700 ) << "call was successfull" << endl;
+		KServiceGroup::List list = service->entries();
+		for( KServiceGroup::List::ConstIterator it = list.begin(); it != \
list.end(); ++it ) +		{
+			KSycocaEntry * p = *it;
+			if( p->isType( KST_KService ) )
+			{
+				kdDebug( 700 ) << "found service" << endl;
+				ret << static_cast<KService *>( p );
+			}
+			else
+				kdWarning( 700 ) << "KServiceGroup::childGroup returned something else \
than a KService (kinda)" << endl; +		}
+	}
+
+	return ret;
+}
+
+QValueList<KService::Ptr> KConfigureDialog::KCDParentsServices( const \
QStringList & kcdparents ) const +{
+	QString constraint = kcdparents.join( "' in [X-KDE-KCDParents]) or ('" );
+	constraint = "('" + constraint + "' in [X-KDE-KCDParents])";
+
+	kdDebug( 700 ) << "constraint = " << constraint << endl;
+	return KTrader::self()->query( "KCModule", constraint );
+}
+
+void KConfigureDialog::createDialogFromServices( const \
QValueList<KService::Ptr> & services ) +{
+	int dialogface = KJanusWidget::IconList;
+	QString basegroup;
+	for( QValueList<KService::Ptr>::const_iterator it = services.begin(); it \
!= services.end(); ++it ) +	{
+		KCModuleInfo * moduleinfo = new KCModuleInfo( *it );
+		d->moduleinfos.append( moduleinfo );
+		if( basegroup.isNull() )
+			basegroup = moduleinfo->groups().front();
+		else if( basegroup != moduleinfo->groups().front() )
+			// we need a treelist dialog
+			dialogface = KJanusWidget::TreeList;
+	}
+
+	kdDebug( 700 ) << "creating KCMultiDialog" << endl;
+	d->dlg = new KCMultiDialog( dialogface, i18n( "Preferences" ) );
+	if( dialogface == KJanusWidget::TreeList )
+	{
+		d->dlg->setShowIconsInTreeList( true );
+		d->dlg->unfoldTreeList( true );
+	}
+	connect( d->dlg, SIGNAL( configCommitted( const QCString & ) ), \
KCDDispatcher::self(), SLOT( reparseConfiguration( const QCString & ) ) ); \
+	for( KCModuleInfo * info = d->moduleinfos.first(); info; info = \
d->moduleinfos.next() ) +	{
+		kdDebug( 700 ) << "add module: " << info->fileName() << " with \
KCDParents=" << info->KCDParents() << endl; +		d->dlg->addModule( *info );
+	}
+}
+
+#include "kconfiguredialog.moc"
+
+// vim: sw=4 ts=4
Index: kconfiguredialog.h
===================================================================
RCS file: kconfiguredialog.h
diff -N kconfiguredialog.h
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ kconfiguredialog.h	16 Aug 2003 17:00:51 -0000
@@ -0,0 +1,60 @@
+/*  This file is part of the KDE project
+    Copyright (C) 2003 Matthias Kretz <kretz@kde.org>
+
+    This library is free software; you can redistribute it and/or
+    modify it under the terms of the GNU Library General Public
+    License version 2 as published by the Free Software Foundation.
+
+    This library is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+    Library General Public License for more details.
+
+    You should have received a copy of the GNU Library General Public \
License +    along with this library; see the file COPYING.LIB.  If not, \
write to +    the Free Software Foundation, Inc., 59 Temple Place - Suite \
330, +    Boston, MA 02111-1307, USA.
+
+*/
+
+#ifndef KCONFIGUREDIALOG_H
+#define KCONFIGUREDIALOG_H
+
+#include <qobject.h>
+#include <kservice.h>
+
+class KConfigureDialog : public QObject
+{
+	Q_OBJECT
+	public:
+		/**
+		 * Construct a new Preferences Dialog for the application.
+		 */
+		KConfigureDialog( QObject * parent = 0, const char * name = 0 );
+
+		/**
+		 * Construct a new Preferences Dialog with the pages for the selected
+		 * instance names. For example if you want to have the configuration
+		 * pages for the kviewviewer KPart and all it's plugins you would pass a
+		 * QStringList consisting of only the name of the part "kviewviewer".
+		 */
+		KConfigureDialog( const QStringList & kcdparents, QObject * parent = 0, \
const char * name = 0 ); +
+		void addKPartsPluginPage();
+
+		~KConfigureDialog();
+
+	public slots:
+		void show();
+
+	private:
+		QValueList<KService::Ptr> instanceServices() const;
+		QValueList<KService::Ptr> KCDParentsServices( const QStringList & ) \
const; +		void createDialogFromServices( const QValueList<KService::Ptr> & \
); +		class KConfigureDialogPrivate;
+		KConfigureDialogPrivate * d;
+};
+
+#endif // KCONFIGUREDIALOG_H
+
+// vim: sw=4 ts=4


[Attachment #6 (application/pgp-signature)]

[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic