[prev in list] [next in list] [prev in thread] [next in thread]
List: kde-core-devel
Subject: Re: Extending KCModuleProxy
From: Frans Englich <frans.englich () telia ! com>
Date: 2004-03-18 6:30:30
Message-ID: 200403180730.30195.frans.englich () telia ! com
[Download RAW message or body]
On Wednesday 17 March 2004 19:42, Frans Englich wrote:
> On Tuesday 16 March 2004 14:27, Matthias Kretz wrote:
OK. This version should be bug free. Right..
(How can it be one almost always find the answer right after asking?)
Kontact works, Konqueror works, `kcmshell mouse kdm keyboard` works.
BTW, I have a question - is it possible to get a KServiceGroup::List of /all/
modules(belonging to base group "Settings/") regardless of what sub-group
they belong to? Rephrased: A list containing all KCMs but no sub categories
of Settings/.
(kdebase/kcontrol/kcontrol/modules.cpp::readDesktopEntriesRecursive does it
by recursing through each sub group)
Frans
["kcmoduleproxy.diff" (text/x-diff)]
Index: kutils/kcmoduleproxy.cpp
===================================================================
RCS file: /home/kde/kdelibs/kutils/kcmoduleproxy.cpp,v
retrieving revision 1.2
diff -u -3 -p -r1.2 kcmoduleproxy.cpp
--- kutils/kcmoduleproxy.cpp 24 Jan 2004 20:28:02 -0000 1.2
+++ kutils/kcmoduleproxy.cpp 18 Mar 2004 06:13:31 -0000
@@ -1,4 +1,5 @@
/* This file is part of the KDE project
+ Copyright (C) 2004 Frans Englich <frans.englich@telia.com>
Copyright (C) 2003 Matthias Kretz <kretz@kde.org>
This library is free software; you can redistribute it and/or
@@ -14,24 +15,185 @@
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 "kcmoduleproxy.h"
-#include "kcmoduleloader.h"
-#include "kcmoduleinfo.h"
#include <qlayout.h>
#include <qapplication.h>
+#include <qlabel.h>
#include <qcursor.h>
+#include <qpoint.h>
+#include <qlayout.h>
+#include <qframe.h>
+#include <qfileinfo.h>
+#include <qwhatsthis.h>
+#include <qwidget.h>
+#include <dcopclient.h>
+#include <qvbox.h>
+#include <qxembed.h>
+#include <qscrollview.h>
+
+#include <kdialog.h>
+#include <kuser.h>
+#include <kcmodule.h>
+#include <kstandarddirs.h>
+#include <kdebug.h>
+#include <kapplication.h>
+#include <klocale.h>
+#include <kprocess.h>
+#include <kservice.h>
+#include <kcmoduleloader.h>
+#include <kcmoduleinfo.h>
+
+#include <X11/Xlib.h>
+
+#include "kcmoduleproxy.h"
+#include "kcmoduleproxy.moc"
+
+/***************************************************************/
+class WhatsThis : public QWhatsThis
+{
+ public:
+ WhatsThis( KCModuleProxy* parent )
+ : QWhatsThis( parent ), proxy( parent ) {}
+
+ ~WhatsThis(){};
+
+ QString text( const QPoint & )
+ {
+ if ( !proxy->quickHelp().isEmpty() )
+ return proxy->quickHelp();
+ else
+ {
+ kdDebug() << "HEY! Your module does not have any quick help. Fix it!" << endl;
+ return i18n("The currently loaded configuration module.");
+ }
+ }
+
+ private:
+ KCModuleProxy* proxy;
+};
+/***************************************************************/
+
+
+
+
+
+
+/***************************************************************/
+/**
+ * The text you see at the top when a
+ * module requires root access.
+ */
+class RootInfoWidget : public QLabel
+{
+public:
+ RootInfoWidget(QWidget *parent, const char *name);
+ void setRootMsg(const QString& s) { setText(s); }
+};
+
+RootInfoWidget::RootInfoWidget(QWidget *parent, const char *name = 0)
+ : QLabel(parent, name)
+{
+ setFrameShape(QFrame::Box);
+ setFrameShadow(QFrame::Raised);
+
+ setText(i18n("<b>Changes in this section require root access.</b><br>"
+ "Click the \"Administrator Mode\" button to "
+ "allow modifications."));
+
+ QWhatsThis::add(this, i18n("This section requires special permissions, probably \
" + "for system-wide changes. Therefore it is "
+ "required that you provide the root password to be "
+ "able to change the modules properties. As long as "
+ "you don't provide the password, the module will be "
+ "disabled."));
+}
+/***************************************************************/
+
+
+
+
+
+
+/***************************************************************/
+class ProxyContentWidget : public QWidget
+{
+public:
+ ProxyContentWidget( QWidget* parent ) : QWidget( parent ) {}
+ ~ProxyContentWidget(){}
+
+ // this should be really done by qscrollview in AutoOneFit mode!
+ QSize sizeHint() const { return minimumSizeHint(); }
+};
+/***************************************************************/
+
+
+
+
+
+
+/***************************************************************/
+/**
+ * This is the wrapper closest to the real KCModule. It ensures the
+ * KCModule does not "explode" on small screens
+ * by encapsulating it in a qscrollview.
+ */
+class ProxyView : public QScrollView
+{
+public:
+ ProxyView::ProxyView(KCModule *client, QWidget *parent, bool run_as_root, const \
char *name) + : QScrollView(parent, name)
+ {
+ setResizePolicy(QScrollView::AutoOneFit);
+ setFrameStyle( NoFrame );
+ QWidget* contentWidget = new ProxyContentWidget( viewport() );
+
+ QVBoxLayout* vbox = new QVBoxLayout( contentWidget );
+
+ if (run_as_root && client->useRootOnlyMsg()) // notify the user
+ {
+ RootInfoWidget *infoBox = new RootInfoWidget(contentWidget);
+ vbox->addWidget( infoBox );
+ QString msg = client->rootOnlyMsg();
+
+ if (!msg.isEmpty())
+ infoBox->setRootMsg(msg);
+ vbox->setSpacing(KDialog::spacingHint());
+ }
+
+ client->reparent(contentWidget,0,QPoint(0,0),true);
+ vbox->addWidget( client );
+ vbox->activate(); // Make sure we have a proper minimumSizeHint
+ addChild(contentWidget);
+ }
+
+private:
+ virtual void resizeEvent(QResizeEvent *e)
+ {
+ QScrollView::resizeEvent(e);
+ }
+};
+/***************************************************************/
+
+
+
+/***************************************************************/
class KCModuleProxy::KCModuleProxyPrivate
{
public:
KCModuleProxyPrivate( const KCModuleInfo & info )
- : kcm( 0 )
- , modinfo( info )
+ : args( 0 )
+ , kcm( 0 )
+ , view( 0 )
+ , embedWidget( 0 )
+ , rootProcess ( 0 )
+ , embedLayout ( 0 )
+ , embedFrame ( 0 )
+ , modInfo( info )
+ , withFallback( false )
, changed( false )
- , failed( false )
+ , rootMode( false )
{}
~KCModuleProxyPrivate()
@@ -39,27 +201,332 @@ class KCModuleProxy::KCModuleProxyPrivat
delete kcm;
}
- QStringList args;
- KCModule * kcm;
- KCModuleInfo modinfo;
- bool withfallback;
+ /**
+ * Used when loading the real module
+ */
+ QStringList args;
+
+ KCModule *kcm;
+ QWidget *view;
+ QXEmbed *embedWidget;
+ KProcess *rootProcess;
+ QVBoxLayout *embedLayout;
+ QVBox *embedFrame;
+
+ KCModuleInfo modInfo;
+ bool withFallback;
bool changed;
- bool failed;
+ bool rootMode;
};
+/***************************************************************/
+
+
+
+
+
+/***************************************************************/
+/**
+ * When something goes wrong in loading the module, this one
+ * jumps in as a "dummy" module.
+ */
+class KCMError : public KCModule
+{
+ public:
+ KCMError( const QString& msg, QWidget* parent )
+ : KCModule( parent, "KCMError" )
+ {
+ QVBoxLayout* topLayout = new QVBoxLayout( this );
+ topLayout->addWidget( new QLabel( msg, this ) );
+ }
+};
+/***************************************************************/
+
+
+
+
+/***************************************************************/
+KCModule * KCModuleProxy::realModule() const
+{
+ if( d->kcm)
+ return d->kcm;
+
+ bool run_as_root = (moduleInfo().needsRootPrivileges() && !KUser().isSuperUser());
+ KCModuleProxy * that = const_cast<KCModuleProxy*>( this );
+
+ if ( run_as_root )
+ {
+ /* Try to make the root KCM have the same look as a regular one */
+ QCString replyType;
+ QByteArray replyData;
+
+ if (kapp->dcopClient()->call("kcontrol", "moduleIface", "getPalette()", \
QByteArray(), + replyType, replyData)
+ && replyType == "QPalette")
+ {
+ QDataStream reply( replyData, IO_ReadOnly );
+ QPalette pal;
+ reply >> pal;
+ that->setPalette(pal);
+ }
+ if (kapp->dcopClient()->call("kcontrol", "moduleIface", "getFont()", QByteArray(),
+ replyType, replyData))
+ if ( replyType == "QFont")
+ {
+ QDataStream reply( replyData, IO_ReadOnly );
+ QFont font;
+ reply >> font;
+ that->setFont(font);
+ }
+ }
+
+ kdDebug() << "MODULE FILENAME = " << moduleInfo().fileName();
+ KService::Ptr s = moduleInfo().service();
+ if ( !s )
+ {
+ d->kcm = new KCMError( i18n("The module %1(the desktop file to be exact) could not \
be found.").arg( + moduleInfo().fileName() ), that );
+ }
+ else if ( s->library().isEmpty() )
+ {
+ d->kcm = new KCMError( i18n("The specified library %1 could not be found.").arg(
+ moduleInfo().library() ), that );
+ }
+ else /* "Prfft! Relax! Nothing to worry about!" */
+ {
+ QApplication::setOverrideCursor(Qt::WaitCursor);
+ d->kcm = KCModuleLoader::loadModule( moduleInfo(), d->withFallback,
+ that, name(), d->args );
+ if( ! d->kcm )
+ {
+ d->kcm = new KCMError( i18n("There was an error when loading the module. "
+ "The desktop file as well as the library was found but "
+ "yet the module could not be loaded properly. Most likely "
+ "the factory declaration was wrong, or the "
+ "create_* function was missing."), that );
+ QApplication::restoreOverrideCursor();
+ }
+
+ connect( d->kcm, SIGNAL( changed( bool ) ),
+ SLOT(moduleChanged(bool)) );
+ connect( d->kcm, SIGNAL( destroyed() ),
+ SLOT( moduleDestroyed() ) );
+ connect( d->kcm, SIGNAL(quickHelpChanged()),
+ SIGNAL(quickHelpChanged()));
+
+ QApplication::restoreOverrideCursor();
+ }
+
+ ( new QHBoxLayout( that, 0, 0 ) )->setAutoAdd( true );
+ d->view = new ProxyView(d->kcm, that, run_as_root, "proxyview");
+ (void) new WhatsThis( that );
+
+ return d->kcm;
+}
+
+void KCModuleProxy::runAsRoot()
+{
+ if (!d->view || !moduleInfo().needsRootPrivileges() )
+ return;
+
+ delete d->rootProcess;
+ delete d->embedWidget;
+ delete d->embedLayout;
+
+ // create an embed widget that will embed the
+ // kcmshell running as root
+ d->embedLayout = new QVBoxLayout(d->view->parentWidget());
+ d->embedFrame = new QVBox( d->view->parentWidget() );
+ d->embedFrame->setFrameStyle( QFrame::Box | QFrame::Raised );
+ QPalette pal( red );
+ pal.setColor( QColorGroup::Background,
+ d->view->parentWidget()->colorGroup().background() );
+ d->embedFrame->setPalette( pal );
+ d->embedFrame->setLineWidth( 2 );
+ d->embedFrame->setMidLineWidth( 2 );
+ d->embedLayout->addWidget(d->embedFrame,1);
+ d->embedWidget = new QXEmbed(d->embedFrame );
+ d->view->hide();
+ d->embedFrame->show();
+ QLabel *lblBusy = new QLabel(i18n("<big>Loading...</big>"), d->embedWidget);
+ lblBusy->setAlignment(AlignCenter);
+ lblBusy->setTextFormat(RichText);
+ lblBusy->setGeometry(0,0, d->view->width(), d->view->height());
+ lblBusy->show();
+
+ // prepare the process to run the kcmshell
+ QString cmd = moduleInfo().service()->exec().stripWhiteSpace();
+ bool kdeshell = false;
+ if (cmd.left(5) == "kdesu")
+ {
+ cmd = cmd.remove(0,5).stripWhiteSpace();
+
+ // remove all kdesu switches
+ while( cmd.length() > 1 && cmd[ 0 ] == '-' )
+ {
+ int pos = cmd.find( ' ' );
+ cmd = cmd.remove( 0, pos ).stripWhiteSpace();
+ }
+ }
-KCModuleProxy::KCModuleProxy( const KCModuleInfo & info, bool fallback,
+ if (cmd.left(8) == "kcmshell")
+ {
+ cmd = cmd.remove(0,8).stripWhiteSpace();
+ kdeshell = true;
+ }
+
+ // run the process
+ QString kdesu = KStandardDirs::findExe("kdesu");
+ if (!kdesu.isEmpty())
+ {
+ d->rootProcess = new KProcess;
+ *d->rootProcess << kdesu;
+ *d->rootProcess << "--nonewdcop";
+ // We have to disable the keep-password feature because
+ // in that case the modules is started through kdesud and kdesu
+ // returns before the module is running and that doesn't work.
+ // We also don't have a way to close the module in that case.
+ *d->rootProcess << "--n"; // Don't keep password.
+ if (kdeshell)
+ {
+ *d->rootProcess << QString("kcmshell %1 --embed %2 --lang %3").arg(cmd).arg
+ (d->embedWidget->winId()).arg(KGlobal::locale()->language());
+ }
+ else
+ {
+ *d->rootProcess << QString("%1 --embed %2 --lang %3").arg(cmd).arg
+ (d->embedWidget->winId()).arg( KGlobal::locale()->language() );
+ }
+
+ connect(d->rootProcess, SIGNAL(processExited(KProcess*)), SLOT(rootExited()));
+
+ if ( !d->rootProcess->start(KProcess::NotifyOnExit) )
+ {
+ d->rootMode = false;
+ rootExited();
+ }
+ else
+ {
+ d->rootMode = true;
+ }
+ delete lblBusy;
+ return;
+ }
+
+ /* Clean up in case of failure */
+ delete d->embedFrame;
+ d->embedFrame = 0;
+ delete d->embedWidget;
+ d->embedWidget = 0;
+ delete d->embedLayout;
+ d->embedLayout = 0;
+
+ d->view->show();
+}
+
+void KCModuleProxy::rootExited()
+{
+ if (d->embedWidget->embeddedWinId())
+ XDestroyWindow(qt_xdisplay(), d->embedWidget->embeddedWinId());
+
+ delete d->embedWidget;
+ d->embedWidget = 0;
+
+ delete d->rootProcess;
+ d->rootProcess = 0;
+
+ delete d->embedLayout;
+ d->embedLayout = 0;
+
+ delete d->embedFrame;
+ d->embedFrame=0;
+
+ d->view->show();
+ d->rootMode = false;
+ moduleChanged( false );
+ emit childClosed();
+
+}
+
+KCModuleProxy::~KCModuleProxy()
+{
+ deleteClient();
+ delete d;
+}
+
+void KCModuleProxy::deleteClient()
+{
+
+ if (d->embedWidget)
+ XKillClient(qt_xdisplay(), d->embedWidget->embeddedWinId());
+
+ delete d->rootProcess;
+ d->rootProcess = 0;
+
+ delete d->embedWidget;
+ d->embedWidget = 0;
+
+ delete d->embedFrame;
+ d->embedFrame = 0;
+ kapp->syncX();
+
+ delete d->view;
+ d->view = 0;
+
+ delete d->embedLayout;
+ d->embedLayout = 0;
+
+ KCModuleLoader::unloadModule(moduleInfo());
+ d->kcm = 0;
+
+}
+
+void KCModuleProxy::showEvent( QShowEvent * ev )
+{
+ ( void )realModule();
+ QWidget::showEvent( ev );
+}
+
+void KCModuleProxy::moduleChanged( bool c )
+{
+ if( d && d->changed != c )
+ {
+ d->changed = c;
+ emit changed( c );
+ emit changed( this );
+ }
+}
+
+void KCModuleProxy::moduleDestroyed()
+{
+ d->kcm = 0;
+}
+
+KCModuleProxy::KCModuleProxy( const KService::Ptr & service, bool withFallback,
+ QWidget * parent, const char * name, const QStringList & args)
+ : QWidget( parent, name )
+ , d( new KCModuleProxyPrivate( KCModuleInfo( service )))
+{
+ d->args = args;
+ d->withFallback = withFallback;
+}
+
+KCModuleProxy::KCModuleProxy( const KCModuleInfo & info, bool withFallback,
QWidget * parent, const char * name, const QStringList & args )
: QWidget( parent, name )
, d( new KCModuleProxyPrivate( info ) )
{
d->args = args;
- d->withfallback = fallback;
+ d->withFallback = withFallback;
}
-KCModuleProxy::~KCModuleProxy()
+KCModuleProxy::KCModuleProxy( const QString& serviceName, bool withFallback,
+ QWidget * parent, const char * name,
+ const QStringList & args)
+ : QWidget( parent, name )
+ , d( new KCModuleProxyPrivate( KCModuleInfo( serviceName )))
{
- KCModuleLoader::unloadModule( d->modinfo );
- delete d;
+ d->args = args;
+ d->withFallback = withFallback;
}
void KCModuleProxy::load()
@@ -73,7 +540,7 @@ void KCModuleProxy::load()
void KCModuleProxy::save()
{
- if( d->kcm )
+ if( d->kcm && d->changed )
{
d->kcm->save();
moduleChanged( false );
@@ -124,56 +591,14 @@ bool KCModuleProxy::changed() const
return d->changed;
}
-KCModule * KCModuleProxy::realModule() const
-{
- if( ! d->kcm && ! d->failed )
- {
- QApplication::setOverrideCursor(Qt::WaitCursor);
- KCModuleProxy * that = const_cast<KCModuleProxy*>( this );
- ( new QHBoxLayout( that, 0, 0 ) )->setAutoAdd( true );
- d->kcm = KCModuleLoader::loadModule( d->modinfo, d->withfallback,
- that, name(), d->args );
- if( ! d->kcm )
- {
- QApplication::restoreOverrideCursor();
- KCModuleLoader::showLastLoaderError( that );
- d->failed = true;
- return 0;
- }
- connect( d->kcm, SIGNAL( changed( bool ) ),
- this, SLOT( moduleChanged( bool ) ) );
- connect( d->kcm, SIGNAL( destroyed() ),
- this, SLOT( moduleDestroyed() ) );
- QApplication::restoreOverrideCursor();
- }
- return d->kcm;
-}
-
KCModuleInfo KCModuleProxy::moduleInfo() const
{
- return d->modinfo;
-}
-
-void KCModuleProxy::showEvent( QShowEvent * ev )
-{
- ( void )realModule();
- QWidget::showEvent( ev );
-}
-
-void KCModuleProxy::moduleChanged( bool c )
-{
- if( d->changed != c )
- {
- d->changed = c;
- emit changed( c );
- }
+ return d->modInfo;
}
-void KCModuleProxy::moduleDestroyed()
+bool KCModuleProxy::rootMode() const
{
- d->kcm = 0;
+ return d->rootMode;
}
-#include "kcmoduleproxy.moc"
-
-// vim: sw=4 ts=4 noet
+/***************************************************************/
Index: kutils/kcmoduleproxy.h
===================================================================
RCS file: /home/kde/kdelibs/kutils/kcmoduleproxy.h,v
retrieving revision 1.2
diff -u -3 -p -r1.2 kcmoduleproxy.h
--- kutils/kcmoduleproxy.h 24 Jan 2004 20:28:02 -0000 1.2
+++ kutils/kcmoduleproxy.h 18 Mar 2004 06:13:31 -0000
@@ -1,5 +1,6 @@
/* This file is part of the KDE project
Copyright (C) 2003 Matthias Kretz <kretz@kde.org>
+ Copyright (C) 2004 Frans Englich <frans.englich@telia.com>
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public
@@ -23,46 +24,250 @@
#include <qwidget.h>
#include <qstringlist.h>
+
+class KService;
class KCModuleInfo;
class KAboutData;
class KInstance;
class KCModule;
+/**
+ *
+ * @brief Encapsulates a @ref KCModule for embedding.
+ *
+ * @description @ref KCModuleProxy is a wrapper for KCModule intended for cases \
where + * modules are to be displayed. It ensures layout is consistent, handles
+ * root/administrator modules and in general takes care of the details
+ * needed for making a module available in an interface. A KCModuleProxy
+ * can be treated as a QWidget, without worrying about the details specific
+ * for modules such as library loading. KCModuleProxy is not a sub class of KCModule \
+ * but its API closely resembles KCModule's.\n
+ * Usually, an instance is created by passing one of the constructors a @ref \
KService::Ptr, + * @ref KCModuleInfo or simply the name of the module and then added \
to the layout as any + * other widget. \n
+ * When the user have changed the module, @ref changed( bool ) as well as @ref \
changed ( KCModuleProxy * ) + * is emitted. KCModuleProxy does not take care of \
prompting for saving - if the object is deleted while + * changes is not saved the \
changes will be lost. @ref changed() returns true if changes are unsaved. \n + * \n
+ * KCModuleProxy does not take care of authorization of KCModules. \n
+ * KCModuleProxy do lazy loading, meaning the library will not be loaded or
+ * any other initialization done before its show() function is called. This means
+ * modules will only be loaded when they are actually needed as well as it is \
possible to + * load many KCModuleProxy without any speed penalty.
+ *
+ * KCModuleProxy should be used in all cases where modules are embedded in order to
+ * promote code efficiency and usability consistency.
+ *
+ * @author Frans Englich <frans.englich@telia.com>
+ * @author Matthias Kretz <kretz@kde.org>
+ * @internal
+ *
+ */
class KCModuleProxy : public QWidget
{
- Q_OBJECT
- public:
- KCModuleProxy( const KCModuleInfo & info, bool withfallback = false,
- QWidget * parent = 0, const char * name = 0,
- const QStringList & args = QStringList() );
- ~KCModuleProxy();
- void load();
- void save();
- void defaults();
- QString quickHelp() const;
- const KAboutData * aboutData() const;
- int buttons() const;
- QString rootOnlyMsg() const;
- bool useRootOnlyMsg() const;
- KInstance * instance() const;
- bool changed() const;
- KCModule * realModule() const;
- KCModuleInfo moduleInfo() const;
-
- signals:
- void changed( bool );
-
- protected:
- void showEvent( QShowEvent * );
-
- private slots:
- void moduleChanged( bool );
- void moduleDestroyed();
-
- private:
- class KCModuleProxyPrivate;
- KCModuleProxyPrivate * d;
+Q_OBJECT
+public:
+
+ /**
+ * Constructs a KCModuleProxy from a KCModuleInfo class.
+ *
+ * @param info The KCModuleInfo to construct the module from.
+ *
+ * @param withfallback If set to true and loading of the module fails,
+ * a alternative will be tried, resulting in the module appearing in its
+ * own window, if at all.
+ * The embedded module will be load()ed.
+ *
+ * @param args This is used in the implementation and is internal. Use the
+ * default.
+ */
+ KCModuleProxy( const KCModuleInfo & info, bool withFallback = true,
+ QWidget * parent = 0, const char * name = 0,
+ const QStringList & args = QStringList() );
+
+ /**
+ * Constructs a KCModuleProxy from a module's service name, which is
+ * equivalent to the desktop file for the kcm without the ".desktop" part.
+ * Otherwise equal to the one above.
+ *
+ * @param serviceName The module's service name to construct from.
+ */
+ KCModuleProxy( const QString& serviceName, bool withFallback = true,
+ QWidget * parent = 0, const char * name = 0,
+ const QStringList & args = QStringList() );
+
+ /**
+ * Constructs a KCModuleProxy from KService. Otherwise equal to the one above.
+ *
+ * @param service The KService to construct from.
+ */
+ KCModuleProxy( const KService::Ptr& service, bool withFallback = true,
+ QWidget * parent = 0, const char * name = 0,
+ const QStringList & args = QStringList() );
+
+ /**
+ * Default destructor
+ */
+ ~KCModuleProxy();
+
+ /**
+ * Calling it will cause the contained module to
+ * run its load() routine.
+ */
+ void load();
+
+ /**
+ * Calling it will cause the contained module to
+ * run its save() routine.
+ *
+ * If the module was not modified, it will not be asked
+ * to save.
+ */
+ void save();
+
+ /**
+ * @return the module's quickHelp();
+ */
+ QString quickHelp() const;
+
+ /**
+ * @return the module's aboutData()
+ */
+ const KAboutData * aboutData() const;
+
+ /**
+ * @return what buttons the module
+ * needs
+ */
+ int buttons() const;
+
+ /**
+ * @return The module's custom root
+ * message, if it has one
+ * @deprecated
+ */
+ QString rootOnlyMsg() const KDE_DEPRECATED;
+ //KDE4 remove. There's a limit for convenience functions,
+ // this one's available via moduleInfo()-> and realModule()->
+
+ /**
+ * @return If the module is a root module.
+ * @deprecated
+ */
+ bool useRootOnlyMsg() const KDE_DEPRECATED;
+ //KDE4 remove. There's a limit for convenience functions,
+ // this one's available via moduleInfo()-> and realModule()->
+
+ /**
+ * Returns the embedded KCModule's KInstance.
+ * @return The module's KInstance.
+ * @deprecated
+ */
+ KInstance * instance() const KDE_DEPRECATED;
+ //KDE4 remove. There's a limit for convenience functions,
+ // this one's available via realModule()
+
+ /**
+ * @return true if the module is modified
+ * and needs to be saved
+ */
+ bool changed() const;
+
+ /**
+ * Returns whether the module is running in root mode. A module is in root mode
+ * when @ref runAsRoot() has been called. A session under root user will never \
reach + * root mode.
+ * @return true if the module is running with root privileges
+ */
+ bool rootMode() const;
+
+ /**
+ * @return the encapsulated module.
+ */
+ KCModule* realModule() const;
+
+ /**
+ * @return a KCModuleInfo for the encapsulated
+ * module
+ */
+ KCModuleInfo moduleInfo() const;
+
+public slots:
+
+ /**
+ * Calling this will cause the module to be run in
+ * "administrator mode".
+ *
+ */
+ void runAsRoot();
+
+ /**
+ * Calling it will cause the contained module to
+ * load its default values.
+ */
+ void defaults();
+
+signals:
+
+ /*
+ * This signal is relayed from the encapsulated module, and
+ * is equivalent to the module's own changed(bool) signal.
+ */
+ void changed( bool state );
+
+ /**
+ * This is emitted in the same situations as in the one above. Practical
+ * when several KCModuleProxys are loaded.
+ */
+ void changed( KCModuleProxy* mod );
+
+ /**
+ * When a module running with root privileges and exits, returns to normal mode, \
the + * childClosed() signal is emitted.
+ */
+ void childClosed();
+
+ /*
+ * This signal is relayed from the encapsulated module, and
+ * is equivalent to the module's own quickHelpChanged() signal.
+ */
+ void quickHelpChanged();
+
+protected:
+
+ /**
+ * Reimplemented for internal purposes. Makes sure the encapsulated
+ * module is loaded before the show event is taken care of.
+ */
+ void showEvent( QShowEvent * );
+
+private slots:
+
+ /**
+ * This is called when the module exits from root mode. It zeroes
+ * pointers, deletes the embed window, etc.
+ */
+ void rootExited();
+
+ /**
+ * Makes sure the proper variables is set and signals are emited.
+ */
+ void moduleChanged( bool );
+
+ /**
+ * Zeroes d->kcm
+ */
+ void moduleDestroyed();
+
+ /**
+ * Exits root mode and unloads the module.
+ */
+ void deleteClient();
+
+private:
+ class KCModuleProxyPrivate;
+ KCModuleProxyPrivate * d;
};
-// vim: sw=4 ts=4 noet
#endif // KCMODULEPROXY_H
+
["kcmultidialog.diff" (text/x-diff)]
Index: kutils/kcmultidialog.cpp
===================================================================
RCS file: /home/kde/kdelibs/kutils/kcmultidialog.cpp,v
retrieving revision 1.51
diff -u -3 -p -r1.51 kcmultidialog.cpp
--- kutils/kcmultidialog.cpp 24 Jan 2004 20:28:02 -0000 1.51
+++ kutils/kcmultidialog.cpp 18 Mar 2004 06:13:40 -0000
@@ -2,6 +2,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>
+ Copyright (c) 2004 Frans Englich <frans.erglich.com>
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public
@@ -24,10 +25,12 @@
#include <qcursor.h>
#include <klocale.h>
+#include <kstdguiitem.h>
#include <kdebug.h>
#include <kiconloader.h>
#include <kmessagebox.h>
#include <klibloader.h>
+#include <kapplication.h>
#include <krun.h>
#include <kprocess.h>
#include <kaboutdata.h>
@@ -39,23 +42,33 @@
#include <assert.h>
#include <qlayout.h>
+class KCMultiDialog::KCMultiDialogPrivate
+{
+ public:
+ KCMultiDialogPrivate()
+ : hasRootKCM( false ), currentModule( 0 )
+ {}
+
+ bool hasRootKCM;
+ KCModuleProxy* currentModule;
+};
+
+
KCMultiDialog::KCMultiDialog(QWidget *parent, const char *name, bool modal)
: KDialogBase(IconList, i18n("Configure"), Help | Default |Cancel | Apply |
- Ok | User1, Ok, parent, name, modal, true,
- KGuiItem( i18n( "&Reset" ), "undo" ) )
- , dialogface( IconList )
+ Ok | User1 | User2, Ok, parent, name, modal, true,
+ KStdGuiItem::reset(), KStdGuiItem::adminMode())
+ , dialogface( IconList ), d( new KCMultiDialogPrivate )
{
- showButton( User1, false );;
init();
}
KCMultiDialog::KCMultiDialog( int dialogFace, const QString & caption, QWidget * \
parent, const char * name, bool modal )
: KDialogBase( dialogFace, caption, Help | Default | Cancel | Apply | Ok |
- User1, Ok, parent, name, modal, true,
- KGuiItem( i18n( "&Reset" ), "undo" ) )
- , dialogface( dialogFace )
+ User1 | User2, Ok, parent, name, modal, true,
+ KStdGuiItem::reset(), KStdGuiItem::adminMode())
+ , dialogface( dialogFace ), d( new KCMultiDialogPrivate )
{
- showButton( User1, false );;
init();
}
@@ -63,17 +76,17 @@ KCMultiDialog::KCMultiDialog( int dialog
const KGuiItem &user3, int buttonMask, const QString &caption,
QWidget *parent, const char *name, bool modal )
: KDialogBase( dialogFace, caption, buttonMask | Help | Default | Cancel |
- Apply | Ok | User1, Ok, parent, name, modal, true,
- KGuiItem( i18n( "&Reset" ), "undo" ), user2, user3 )
- , dialogface( dialogFace )
+ Apply | Ok | User1 | User2 | User3, Ok, parent, name, modal, true,
+ KStdGuiItem::reset(), KStdGuiItem::adminMode(), user3 )
+ , dialogface( dialogFace ), d( new KCMultiDialogPrivate )
{
- showButton( User1, false );;
- init();
+ init();
}
inline void KCMultiDialog::init()
{
- d = 0L;
+ showButton( User1, false );
+ showButton( User2, false );
enableButton(Apply, false);
connect(this, SIGNAL(aboutToShowPage(QWidget *)), this, \
SLOT(slotAboutToShow(QWidget *))); setInitialSize(QSize(640,480));
@@ -197,7 +210,6 @@ void KCMultiDialog::clientChanged(bool s
void KCMultiDialog::addModule(const QString& path, bool withfallback)
{
- kdDebug(710) << "KCMultiDialog::addModule " << path << endl;
KService::Ptr s = KService::serviceByStorageId(path);
if (!s) {
@@ -212,9 +224,13 @@ void KCMultiDialog::addModule(const QStr
void KCMultiDialog::addModule(const KCModuleInfo& moduleinfo,
QStringList parentmodulenames, bool withfallback)
{
+
kdDebug(710) << "KCMultiDialog::addModule " << moduleinfo.moduleName() <<
endl;
+ if ( !kapp->authorizeControlModule( moduleinfo.service()->menuId() ))
+ return;
+
QFrame* page = 0;
if (!moduleinfo.service()->noDisplay())
switch( dialogface )
@@ -280,6 +296,11 @@ void KCMultiDialog::addModule(const KCMo
cm.kcm = module;
cm.service = moduleinfo.service();
m_modules.append( cm );
+ if ( moduleinfo.needsRootPrivileges() && !d->hasRootKCM )
+ {
+ d->hasRootKCM = true;
+ showButton( User2, true );
+ }
}
void KCMultiDialog::removeAllModules()
@@ -321,8 +342,6 @@ void KCMultiDialog::show()
void KCMultiDialog::slotAboutToShow(QWidget *page)
{
- kdDebug( 710 ) << k_funcinfo << endl;
- // honor KCModule::buttons
QObject * obj = page->child( 0, "KCModuleProxy" );
if( ! obj )
return;
@@ -330,12 +349,37 @@ void KCMultiDialog::slotAboutToShow(QWid
"KCModuleProxy" );
if( ! module )
return;
- // TODO: if the dialogface is Plain we should hide the buttons instead of
- // disabling
+ d->currentModule = module;
+
enableButton( KDialogBase::Help,
- module->buttons() & KCModule::Help );
+ d->currentModule->buttons() & KCModule::Help );
enableButton( KDialogBase::Default,
- module->buttons() & KCModule::Default );
+ d->currentModule->buttons() & KCModule::Default );
+
+ disconnect( this, SIGNAL(user2Clicked()), 0, 0);
+ /* Enable the Admin Mode button */
+ if (d->currentModule->moduleInfo().needsRootPrivileges())
+ {
+ enableButton( User2, true );
+ connect( this, SIGNAL(user2Clicked()), d->currentModule, SLOT( runAsRoot() \
)); + }
+ else
+ enableButton( User2, false);
}
+void KCMultiDialog::slotUser2Clicked() /* Admin Mode */
+{
+ if ( !d->currentModule )
+ return;
+
+ enableButton( User2, false );
+ connect ( d->currentModule, SIGNAL( childClosed() ), SLOT( rootExit() ));
+}
+
+void KCMultiDialog::rootExit()
+{
+ enableButton( User2, true);
+}
+
+
// vim: sw=4 et sts=4
Index: kutils/kcmultidialog.h
===================================================================
RCS file: /home/kde/kdelibs/kutils/kcmultidialog.h,v
retrieving revision 1.31
diff -u -3 -p -r1.31 kcmultidialog.h
--- kutils/kcmultidialog.h 15 Jan 2004 15:56:00 -0000 1.31
+++ kutils/kcmultidialog.h 18 Mar 2004 06:13:40 -0000
@@ -209,12 +209,20 @@ protected slots:
**/
virtual void slotHelp();
+ /**
+ * This slot is called when the user pressed the "Administrator Mode"
+ * button
+ */
+ virtual void slotUser2Clicked();
+
private slots:
void slotAboutToShow(QWidget *);
void clientChanged(bool state);
+ void rootExit();
+
private:
void init();
void apply();
@@ -234,7 +242,6 @@ private:
QString _docPath;
int dialogface;
- // For future use
class KCMultiDialogPrivate;
KCMultiDialogPrivate *d;
};
[prev in list] [next in list] [prev in thread] [next in thread]
Configure |
About |
News |
Add a list |
Sponsored by KoreLogic