Hello,

I have debugged the issue that I sent an email about yesterday some
more. I noticed the following:

- modifying a KCoreConfigSkeleton::ItemString value does not write
this value to disk on KCoreConfigSkeleton::writeConfig()
- however, calling KCoreConfigSkeleton::ItemString::setValue() causes
the value to be updated correctly.

I have attached an updated version of the script that illustrates
this, with the method setSimpleThing() on line 36 being the crucial
part:

        def setSimpleThing(self,  simpleThing):
                # BUG: This does not update the KConfigItem value
                self._simpleThing = simpleThing
                # BUG: The explicit setting however, does.
                self._simpleThingKC.setValue(simpleThing)

I found this when looking at KCoreConfigSkeleton::ItemString:

void KCoreConfigSkeleton::ItemString::writeConfig( KConfig *config )
{
  if ( mReference != mLoadedValue ) // WABA: Is this test needed?
  {
    KConfigGroup cg(config, mGroup );
    if ((mDefault == mReference) && !cg.hasDefault( mKey))
      cg.revertToDefault( mKey );
    else if ( mType == Path )
      cg.writePathEntry( mKey, mReference );
    else if ( mType == Password )
      cg.writeEntry( mKey, KStringHandler::obscure( mReference ) );
    else
      cg.writeEntry( mKey, mReference );
  }
}

The first line (mReference!=mLoadedValue) is where PyQt "fails".
mReference is of type QString& and is supposed to point to the value
that gets passed to KCoreConfigSkeleton::addItemString:

[Python Code]
myString = QString("foo")
KCoreConfigSkeleton::addItemString("bar", myString, "barDefaultValue")

At this point, mReference points to myString and
mReference==mLoadedValue. Now, in Python:

myString = QString("bar")

At this point, mReference still seems to contain or point to a string
"foo", which causes the check in
KCoreConfigSkeleton::ItemString::writeConfig() to fail.

My assumption is (I do not have any knowledge about PyQt's inner
workings) that the Python string and the QString copy live at
different positions in memory, even though they are supposed to be
passed by reference. This behavior also does not change when using
QString() instances directly in the Python code. (I adjusted my
example from yesterday accordingly)

However, at least when using QStrings directly from Python, I would
assume the reference to be passed correctly to KCoreConfigSkeleton so
that it catches any updates inside its code. Is this assumption wrong
or is it a bug in PyQt/PyKDE?

I am using the bindings packaged in Kubuntu, version 4:4.2.1-0ubuntu1~intrepid2.

Thanks,

Till

On 3/10/09, Till Gerken <[email protected]> wrote:
> Hello,
>
> I have a problem with KConfigSkeleton not writing its configuration to
> disk when calling KCoreConfigSkeleton::writeConfig(). The odd thing
> about this is that it works when being used together with
> KConfigDialog and KConfigDialogManager, in which case the
> configuration file is written correctly.
>
> I have attached a small sample illustrating this behavior. When run,
> the value that is entered in the configuration widget will be written
> to disk. However, the value that is specified in
> MyConfigMain.queryClose() is not written.
>
> Is this a bug in PyKDE or am I missing something?
>
> Thanks,
>
> Till
>
import sys

from PyKDE4.kdecore import *
from PyKDE4.kdeui import *

from PyQt4.QtCore import *
from PyQt4.QtGui import *

from PyQt4 import uic

#
# Configuration storage
#
class MyConfig(KConfigSkeleton):
	_simpleThing = QString()
	_simpleThingKC = None
	_simpleThingDlg = QString()
	__instance = None

	def __init__(self):
		if self.__instance:
			raise self.__instance
		self.__instance = self
		KConfigSkeleton.__init__(self, "configtestrc")
		self.createConfig()
		self.readConfig()

	def createConfig(self):
		# Create entries for the main window
		self._simpleThingKC = self.addItemString ("simpleThing",  self._simpleThing,  QString("foo"))
		self.addItemString ("simpleThingDlg",  self._simpleThingDlg,  QString("bar"))

	def simpleThing(self):
		return self._simpleThing
		
	def setSimpleThing(self,  simpleThing):
		# BUG: This does not update the KConfigItem value
		self._simpleThing = simpleThing
		# BUG: The explicit setting however, does.
		self._simpleThingKC.setValue(simpleThing)
		

	def simpleThingDlg(self):
		return self._simpleThingDlg
		
	def setSimpleThingDlg(self,  simpleThingDlg):
		self._simpleThingDlg = simpleThingDlg

#
# Configuration dialog
#
class MyConfigDialog(KConfigDialog):
	def __init__(self, parentWidget, configuration):
		KConfigDialog.__init__(self, parentWidget, "MainSettings", configuration )
		self.setFaceType ( KPageDialog.Plain )
		self.configWidget = QWidget()
		uic.loadUi ( "mycfg.ui", self.configWidget )
		self.addPage ( self.configWidget, "Configuration" )

#
# Main application class
#
class MyConfigMain(KMainWindow):
	def __init__(self):
		KMainWindow.__init__(self)

		# Create configuration
		self.config = MyConfig()

		#
		# BUG?: A value that is accessed from the dialog below is written to the file when changed (desired behavior)
		#
		self.cfgDialog = MyConfigDialog(self, self.config)
		self.cfgDialogManager = KConfigDialogManager(self.cfgDialog, self.config)
		self.cfgDialog.show()
		
		# not necessary, nothing here - but do something
		self.show()

	def queryClose(self):
		#
		# BUG?: This should cause the text to be written to the configuration file, but it does not appear (not desired)
		#
		self.config.setSimpleThing(QString("foobar!"))
		self.config.writeConfig()
		return True

#
# Startup Code
#
# Create main window and application info,
# then instantiate main class and jump there
#

appName = "configtest"
catalog = ""
programName = ki18n("Configuration Test")
version = "0.1"
description = ki18n("Configuration Test")
license = KAboutData.License_GPL
copyright = ki18n("(c) 2009 Till Gerken, <[email protected]>")
text = ki18n("none")
homePage = ""
bugEmail = "[email protected]"

aboutData = KAboutData ( appName, catalog, programName, version, description, license, copyright, text, homePage, bugEmail )

KCmdLineArgs.init ( sys.argv, aboutData )
app = KApplication()

docmgr = MyConfigMain()

sys.exit(app.exec_())

Attachment: mycfg.ui
Description: application/designer

_______________________________________________
PyQt mailing list    [email protected]
http://www.riverbankcomputing.com/mailman/listinfo/pyqt

Reply via email to