Clean up code. Add comments. Init module with callback to register all
[bertos.git] / wizard / BModulePage.py
index 9fbcf01554620df8fbbead350be21f1548feb64c..5bee07241ac296482621c655e327a5495ff48640 100644 (file)
 #
 # Copyright 2008 Develer S.r.l. (http://www.develer.com/)
 #
 #
 # Copyright 2008 Develer S.r.l. (http://www.develer.com/)
 #
-# $Id$
 #
 # Author: Lorenzo Berni <duplo@develer.com>
 #
 
 import os
 
 #
 # Author: Lorenzo Berni <duplo@develer.com>
 #
 
 import os
 
+from PyQt4.QtCore import *
 from PyQt4.QtGui import *
 from BWizardPage import *
 import bertos_utils
 from PyQt4.QtGui import *
 from BWizardPage import *
 import bertos_utils
@@ -77,23 +77,31 @@ class BModulePage(BWizardPage):
         Overload of the BWizardPage connectSignals method.
         """
         self.connect(self.pageContent.moduleTree, SIGNAL("itemPressed(QTreeWidgetItem*, int)"), self.fillPropertyTable)
         Overload of the BWizardPage connectSignals method.
         """
         self.connect(self.pageContent.moduleTree, SIGNAL("itemPressed(QTreeWidgetItem*, int)"), self.fillPropertyTable)
+        self.connect(self.pageContent.moduleTree, SIGNAL("itemPressed(QTreeWidgetItem*, int)"), self.moduleClicked)
         self.connect(self.pageContent.moduleTree, SIGNAL("itemChanged(QTreeWidgetItem*, int)"), self.dependencyCheck)
         self.connect(self.pageContent.moduleTree, SIGNAL("itemChanged(QTreeWidgetItem*, int)"), self.dependencyCheck)
-        self.connect(self.pageContent.propertyTable, SIGNAL("itemSelectionChanged()"), self.showPropertyDescription)
 
 
-    def reloadData(self):
+    def reloadData(self, previous_id=None):
         """
         Overload of the BWizardPage reloadData method.
         """
         """
         Overload of the BWizardPage reloadData method.
         """
-        QApplication.instance().setOverrideCursor(Qt.WaitCursor)
-        self.setupUi()
-        self.loadModuleData()
-        self.fillModuleTree()
-        QApplication.instance().restoreOverrideCursor()
+        # Check if the user are approaching this page from the previous or the
+        # next one.
+        if previous_id is None or previous_id < self.wizard().currentId():
+            try:
+                QApplication.instance().setOverrideCursor(Qt.WaitCursor)
+                self.setupUi()
+                self.loadModuleData()
+                self.fillModuleTree()
+            finally:
+                QApplication.instance().restoreOverrideCursor()
     
     ####
     
     ## Slots ##
 
     
     ####
     
     ## Slots ##
 
+    def moduleClicked(self, item, column):
+        self.setBold(item, False)
+
     def fillPropertyTable(self):
         """
         Slot called when the user selects a module from the module tree.
     def fillPropertyTable(self):
         """
         Slot called when the user selects a module from the module tree.
@@ -103,7 +111,7 @@ class BModulePage(BWizardPage):
         module = self.currentModule()
         if module:
             try:
         module = self.currentModule()
         if module:
             try:
-                supported = bertos_utils.isSupported(self.project(), module=module)
+                supported = bertos_utils.isSupported(self.project, module=module)
             except SupportedException, e:
                 self.exceptionOccurred(self.tr("Error evaluating \"%1\" for module %2").arg(e.support_string).arg(module))
                 supported = True
             except SupportedException, e:
                 self.exceptionOccurred(self.tr("Error evaluating \"%1\" for module %2").arg(e.support_string).arg(module))
                 supported = True
@@ -130,7 +138,7 @@ class BModulePage(BWizardPage):
                         # Doesn't show the hidden fields
                         continue
                     try:
                         # Doesn't show the hidden fields
                         continue
                     try:
-                        param_supported = bertos_utils.isSupported(self.project(), property_id=(configuration, property))
+                        param_supported = bertos_utils.isSupported(self.project, property_id=(configuration, property))
                     except SupportedException, e:
                         self.exceptionOccurred(self.tr("Error evaluating \"%1\" for parameter %2").arg(e.support_string).arg(property))
                         param_supported = True
                     except SupportedException, e:
                         self.exceptionOccurred(self.tr("Error evaluating \"%1\" for parameter %2").arg(e.support_string).arg(property))
                         param_supported = True
@@ -140,6 +148,12 @@ class BModulePage(BWizardPage):
                     # Set the row count to the current index + 1
                     self.pageContent.propertyTable.setRowCount(index + 1)
                     item = QTableWidgetItem(configurations[property]["brief"])
                     # Set the row count to the current index + 1
                     self.pageContent.propertyTable.setRowCount(index + 1)
                     item = QTableWidgetItem(configurations[property]["brief"])
+                    item.setFlags(item.flags() & ~Qt.ItemIsSelectable)
+                    tooltip = property
+                    description = configurations[property].get("description", None)
+                    if description:
+                        tooltip = tooltip + ": " + description
+                    item.setToolTip(tooltip)
                     item.setData(Qt.UserRole, qvariant_converter.convertString(property))
                     self.pageContent.propertyTable.setItem(index, 0, item)
                     if "type" in configurations[property]["informations"] and configurations[property]["informations"]["type"] == "boolean":
                     item.setData(Qt.UserRole, qvariant_converter.convertString(property))
                     self.pageContent.propertyTable.setItem(index, 0, item)
                     if "type" in configurations[property]["informations"] and configurations[property]["informations"]["type"] == "boolean":
@@ -148,6 +162,8 @@ class BModulePage(BWizardPage):
                         self.insertComboBox(index, configurations[property]["value"], configurations[property]["informations"]["value_list"])
                     elif "type" in configurations[property]["informations"] and configurations[property]["informations"]["type"] == "int":
                         self.insertSpinBox(index, configurations[property]["value"], configurations[property]["informations"])
                         self.insertComboBox(index, configurations[property]["value"], configurations[property]["informations"]["value_list"])
                     elif "type" in configurations[property]["informations"] and configurations[property]["informations"]["type"] == "int":
                         self.insertSpinBox(index, configurations[property]["value"], configurations[property]["informations"])
+                    elif "type" in configurations[property]["informations"] and configurations[property]["informations"]["type"] == "hex":
+                        self.insertLineEdit(index, configurations[property]["value"], configurations[property]["informations"])
                     else:
                         # Not defined type, rendered as a text field
                         self.pageContent.propertyTable.setItem(index, 1, QTableWidgetItem(configurations[property]["value"]))
                     else:
                         # Not defined type, rendered as a text field
                         self.pageContent.propertyTable.setItem(index, 1, QTableWidgetItem(configurations[property]["value"]))
@@ -155,7 +171,12 @@ class BModulePage(BWizardPage):
             if self.pageContent.propertyTable.rowCount() == 0:
                 module_label = self.pageContent.moduleLabel.text()
                 module_label += "\n\nNo configuration needed."
             if self.pageContent.propertyTable.rowCount() == 0:
                 module_label = self.pageContent.moduleLabel.text()
                 module_label += "\n\nNo configuration needed."
-                self.pageContent.moduleLabel.setText(module_label)
+                self.pageContent.moduleLabel.setText(module_label) 
+        else:
+            self.pageContent.moduleLabel.setText("")
+            self.pageContent.moduleLabel.setVisible(False)
+            self.pageContent.propertyTable.clear()
+            self.pageContent.propertyTable.setRowCount(0)
 
     def dependencyCheck(self, item):
         """
 
     def dependencyCheck(self, item):
         """
@@ -189,7 +210,7 @@ class BModulePage(BWizardPage):
         configuration = self.projectInfo("MODULES")[self.currentModule()]["configuration"]
         configurations = self.projectInfo("CONFIGURATIONS")
         if "type" not in configurations[configuration][property]["informations"] or configurations[configuration][property]["informations"]["type"] == "int":
         configuration = self.projectInfo("MODULES")[self.currentModule()]["configuration"]
         configurations = self.projectInfo("CONFIGURATIONS")
         if "type" not in configurations[configuration][property]["informations"] or configurations[configuration][property]["informations"]["type"] == "int":
-            configurations[configuration][property]["value"] = str(int(self.pageContent.propertyTable.cellWidget(index, 1).value()))
+            configurations[configuration][property]["value"] = unicode(int(self.pageContent.propertyTable.cellWidget(index, 1).value()))
         elif configurations[configuration][property]["informations"]["type"] == "enum":
             configurations[configuration][property]["value"] = unicode(self.pageContent.propertyTable.cellWidget(index, 1).currentText())
         elif configurations[configuration][property]["informations"]["type"] == "boolean":
         elif configurations[configuration][property]["informations"]["type"] == "enum":
             configurations[configuration][property]["value"] = unicode(self.pageContent.propertyTable.cellWidget(index, 1).currentText())
         elif configurations[configuration][property]["informations"]["type"] == "boolean":
@@ -197,7 +218,11 @@ class BModulePage(BWizardPage):
                 configurations[configuration][property]["value"] = "1"
             else:
                 configurations[configuration][property]["value"] = "0"
                 configurations[configuration][property]["value"] = "1"
             else:
                 configurations[configuration][property]["value"] = "0"
+        elif configurations[configuration][property]["informations"]["type"] == "hex":
+            configurations[configuration][property]["value"] = unicode(self.pageContent.propertyTable.cellWidget(index, 1).text())
         self.setProjectInfo("CONFIGURATIONS", configurations)
         self.setProjectInfo("CONFIGURATIONS", configurations)
+        if self.moduleItem(self.currentModule()).checkState(0) == Qt.Checked:
+            self.dependencyCheck(self.moduleItem(self.currentModule()))
 
     ####
     
 
     ####
     
@@ -205,12 +230,13 @@ class BModulePage(BWizardPage):
         """
         Loads the module data.
         """
         """
         Loads the module data.
         """
-        # Load the module data only if it isn't already loaded
-        if not self.projectInfo("MODULES") \
-                and not self.projectInfo("LISTS") \
-                and not self.projectInfo("CONFIGURATIONS"):
+        # Do not load the module data again when the Wizard is in editing mode
+        # or when it's working on a preset.
+        if not self.project.edit and not self.project.from_preset:
+            # Load the module data every time so that if the user changed the cpu
+            # the right configurations are picked up.
             try:
             try:
-                bertos_utils.loadModuleData(self.project())
+                self.project.loadModuleData()
             except ModuleDefineException, e:
                 self.exceptionOccurred(self.tr("Error parsing line '%2' in file %1").arg(e.path).arg(e.line))
             except EnumDefineException, e:
             except ModuleDefineException, e:
                 self.exceptionOccurred(self.tr("Error parsing line '%2' in file %1").arg(e.path).arg(e.line))
             except EnumDefineException, e:
@@ -222,6 +248,7 @@ class BModulePage(BWizardPage):
         """
         Fills the module tree with the module entries separated in categories.
         """
         """
         Fills the module tree with the module entries separated in categories.
         """
+        self.pageContent.moduleTree.clear()
         modules = self.projectInfo("MODULES")
         if not modules:
             return
         modules = self.projectInfo("MODULES")
         if not modules:
             return
@@ -236,7 +263,7 @@ class BModulePage(BWizardPage):
                 enabled = modules[module]["enabled"]
                 module_item = QTreeWidgetItem(item, QStringList([module]))
                 try:
                 enabled = modules[module]["enabled"]
                 module_item = QTreeWidgetItem(item, QStringList([module]))
                 try:
-                    supported = bertos_utils.isSupported(self.project(), module=module)
+                    supported = bertos_utils.isSupported(self.project, module=module)
                 except SupportedException, e:
                     self.exceptionOccurred(self.tr("Error evaluating \"%1\" for module %2").arg(e.support_string).arg(module))
                     supported = True
                 except SupportedException, e:
                     self.exceptionOccurred(self.tr("Error evaluating \"%1\" for module %2").arg(e.support_string).arg(module))
                     supported = True
@@ -248,6 +275,7 @@ class BModulePage(BWizardPage):
                     module_item.setCheckState(0, Qt.Unchecked)
             self.pageContent.moduleTree.addTopLevelItem(item)
         self.pageContent.moduleTree.sortItems(0, Qt.AscendingOrder)
                     module_item.setCheckState(0, Qt.Unchecked)
             self.pageContent.moduleTree.addTopLevelItem(item)
         self.pageContent.moduleTree.sortItems(0, Qt.AscendingOrder)
+        self.fillPropertyTable()
             
     def insertCheckBox(self, index, value):
         """
             
     def insertCheckBox(self, index, value):
         """
@@ -318,6 +346,18 @@ class BModulePage(BWizardPage):
         self._control_group.addControl(index, spin_box)
         
     
         self._control_group.addControl(index, spin_box)
         
     
+    def insertLineEdit(self, index, value, informations):
+        """
+        Inserts in the table at index a line edit for hexadecimal property
+        setted to value.
+        """
+        edit_box = QLineEdit()
+        edit_validator = QRegExpValidator(QRegExp(r"^0x[0-9A-Fa-f]+$"), edit_box)
+        edit_box.setValidator(edit_validator)
+        self.pageContent.propertyTable.setCellWidget(index, 1, edit_box)
+        edit_box.setText(value)
+        self._control_group.addControl(index, edit_box)
+
     def currentModule(self):
         """
         Retuns the current module name.
     def currentModule(self):
         """
         Retuns the current module name.
@@ -328,6 +368,15 @@ class BModulePage(BWizardPage):
             return unicode(current_module.text(0))
         else:
             return None
             return unicode(current_module.text(0))
         else:
             return None
+
+    def moduleItem(self, module):
+        for top_level_index in range(self.pageContent.moduleTree.topLevelItemCount()):
+            top_level_item = self.pageContent.moduleTree.topLevelItem(top_level_index)
+            for child_index in range(top_level_item.childCount()):
+                child_item = top_level_item.child(child_index)
+                if unicode(child_item.text(0)) == module:
+                    return child_item
+        return None
     
     def currentModuleConfigurations(self):
         """
     
     def currentModuleConfigurations(self):
         """
@@ -351,7 +400,12 @@ class BModulePage(BWizardPage):
         """
         Returns the configuration for the selected module.
         """
         """
         Returns the configuration for the selected module.
         """
-        configuration = self.projectInfo("MODULES")[module]["configuration"]
+        configuration = []
+        if module:
+            # On linux platform it seems that the behaviour of the focus
+            # changing is a bit different from the mac one. So if module is
+            # None then no configurations should be returned.
+            configuration = self.projectInfo("MODULES")[module]["configuration"]
         if len(configuration) > 0:
             return self.projectInfo("CONFIGURATIONS")[configuration]
         else:
         if len(configuration) > 0:
             return self.projectInfo("CONFIGURATIONS")[configuration]
         else:
@@ -368,50 +422,94 @@ class BModulePage(BWizardPage):
                 break
             self.pageContent.propertyTable.item(index, 0).setText(self.currentModuleConfigurations()[property_name]['brief'])
     
                 break
             self.pageContent.propertyTable.item(index, 0).setText(self.currentModuleConfigurations()[property_name]['brief'])
     
+    def setBold(self, item, bold):
+        self.pageContent.moduleTree.blockSignals(True)
+        font = item.font(0)
+        font.setBold(bold)
+        item.setFont(0, font)
+        self.pageContent.moduleTree.blockSignals(False)
+
+    def isBold(self, item):
+        return item.font(0).bold()
+
     def moduleSelected(self, selectedModule):
         """
         Resolves the selection dependencies.
         """
     def moduleSelected(self, selectedModule):
         """
         Resolves the selection dependencies.
         """
-        modules = self.projectInfo("MODULES")
-        modules[selectedModule]["enabled"] = True
-        self.setProjectInfo("MODULES", modules)
-        depends = self.projectInfo("MODULES")[selectedModule]["depends"]
-        unsatisfied = []
-        if self.pageContent.automaticFix.isChecked():
-            unsatisfied = self.selectDependencyCheck(selectedModule)
-        if len(unsatisfied) > 0:
-            for module in unsatisfied:
-                modules = self.projectInfo("MODULES")
-                modules[module]["enabled"] = True
-            for category in range(self.pageContent.moduleTree.topLevelItemCount()):
-                item = self.pageContent.moduleTree.topLevelItem(category)
-                for child in range(item.childCount()):
-                    if unicode(item.child(child).text(0)) in unsatisfied:
-                        item.child(child).setCheckState(0, Qt.Checked)
-    
-    def moduleUnselected(self, unselectedModule):
-        """
-        Resolves the unselection dependencies.
-        """
-        modules = self.projectInfo("MODULES")
-        modules[unselectedModule]["enabled"] = False
-        self.setProjectInfo("MODULES", modules)
-        unsatisfied = []
-        if self.pageContent.automaticFix.isChecked():
-            unsatisfied = self.unselectDependencyCheck(unselectedModule)
-        if len(unsatisfied) > 0:
-            message = self.tr("The module %1 is needed by the following modules:\n%2.\n\nDo you want to remove these modules too?")
-            message = message.arg(unselectedModule).arg(", ".join(unsatisfied))
-            choice = QMessageBox.warning(self, self.tr("Dependency error"), message, QMessageBox.Yes | QMessageBox.No, QMessageBox.Yes)
-            if choice == QMessageBox.Yes:
+        try:
+            qApp.setOverrideCursor(Qt.WaitCursor)
+            modules = self.projectInfo("MODULES")
+            modules[selectedModule]["enabled"] = True
+            self.setProjectInfo("MODULES", modules)
+            depends = self.projectInfo("MODULES")[selectedModule]["depends"]
+            unsatisfied = []
+            if self.pageContent.automaticFix.isChecked():
+                unsatisfied = self.selectDependencyCheck(selectedModule)
+            if len(unsatisfied) > 0:
                 for module in unsatisfied:
                     modules = self.projectInfo("MODULES")
                 for module in unsatisfied:
                     modules = self.projectInfo("MODULES")
-                    modules[module]["enabled"] = False
+                    modules[module]["enabled"] = True
                 for category in range(self.pageContent.moduleTree.topLevelItemCount()):
                     item = self.pageContent.moduleTree.topLevelItem(category)
                     for child in range(item.childCount()):
                         if unicode(item.child(child).text(0)) in unsatisfied:
                 for category in range(self.pageContent.moduleTree.topLevelItemCount()):
                     item = self.pageContent.moduleTree.topLevelItem(category)
                     for child in range(item.childCount()):
                         if unicode(item.child(child).text(0)) in unsatisfied:
-                            item.child(child).setCheckState(0, Qt.Unchecked)
+                            self.setBold(item.child(child), True)
+                            self.setBold(item, True)
+                            item.child(child).setCheckState(0, Qt.Checked)
+        finally:
+            qApp.restoreOverrideCursor()
+    
+    def moduleUnselected(self, unselectedModule):
+        """
+        Resolves the unselection dependencies.
+        """
+        try:
+            qApp.setOverrideCursor(Qt.WaitCursor)
+            modules = self.projectInfo("MODULES")
+            modules[unselectedModule]["enabled"] = False
+            self.setProjectInfo("MODULES", modules)
+            unsatisfied = []
+            unsatisfied_params = []
+            if self.pageContent.automaticFix.isChecked():
+                unsatisfied, unsatisfied_params = self.unselectDependencyCheck(unselectedModule)
+            if len(unsatisfied) > 0 or len(unsatisfied_params) > 0:
+                message = []
+                heading = self.tr("The module %1 is needed by").arg(unselectedModule)
+                message.append(heading)
+                module_list = ", ".join(unsatisfied)
+                param_list = ", ".join(["%s (%s)" %(param_name, module) for module, param_name in unsatisfied_params])
+                if module_list:
+                    message.append(QString(module_list))
+                if module_list and param_list:
+                    message.append(self.tr("and by"))
+                if param_list:
+                    message.append(QString(param_list))
+                message_str = QStringList(message).join(" ")
+                message_str.append(self.tr("\n\nDo you want to automatically fix these conflicts?"))
+                qApp.restoreOverrideCursor()
+                choice = QMessageBox.warning(self, self.tr("Dependency error"), message_str, QMessageBox.Yes | QMessageBox.No, QMessageBox.Yes)
+                qApp.setOverrideCursor(Qt.WaitCursor)
+                if choice == QMessageBox.Yes:
+                    for module in unsatisfied:
+                        modules = self.projectInfo("MODULES")
+                        modules[module]["enabled"] = False
+                    for category in range(self.pageContent.moduleTree.topLevelItemCount()):
+                        item = self.pageContent.moduleTree.topLevelItem(category)
+                        self.setBold(item, False)
+                        for child in range(item.childCount()):
+                            if unicode(item.child(child).text(0)) in unsatisfied:
+                                self.setBold(item.child(child), False)
+                                item.child(child).setCheckState(0, Qt.Unchecked)
+                            else:
+                                if self.isBold(item.child(child)):
+                                    self.setBold(item, True)
+                    for module, param in unsatisfied_params:
+                        configuration_file = self.projectInfo("MODULES")[module]["configuration"]
+                        configurations = self.projectInfo("CONFIGURATIONS")
+                        configurations[configuration_file][param]["value"] = "0"
+                        self.setProjectInfo("CONFIGURATIONS", configurations)
+        finally:
+            qApp.restoreOverrideCursor()
     
     def selectDependencyCheck(self, module):
         """
     
     def selectDependencyCheck(self, module):
         """
@@ -420,7 +518,17 @@ class BModulePage(BWizardPage):
         unsatisfied = set()
         modules = self.projectInfo("MODULES")
         files = self.projectInfo("FILES")
         unsatisfied = set()
         modules = self.projectInfo("MODULES")
         files = self.projectInfo("FILES")
-        for dependency in modules[module]["depends"]:
+        configurations = self.projectInfo("CONFIGURATIONS").get(modules[module]["configuration"], {"paramlist": ()})
+        conditional_deps = ()
+        for i, param_name in configurations["paramlist"]:
+            information = configurations[param_name]
+            if information["informations"]["type"] == "boolean" and \
+                information["value"] != "0" and \
+                "conditional_deps" in information["informations"]:
+
+                conditional_deps += information["informations"]["conditional_deps"]
+
+        for dependency in modules[module]["depends"] + conditional_deps:
             if dependency in modules and not modules[dependency]["enabled"]:
                 unsatisfied |= set([dependency])
                 if dependency not in unsatisfied:
             if dependency in modules and not modules[dependency]["enabled"]:
                 unsatisfied |= set([dependency])
                 if dependency not in unsatisfied:
@@ -438,13 +546,27 @@ class BModulePage(BWizardPage):
         Returns the list of unsatisfied dependencies after an unselection.
         """
         unsatisfied = set()
         Returns the list of unsatisfied dependencies after an unselection.
         """
         unsatisfied = set()
+        unsatisfied_params = set()
         modules = self.projectInfo("MODULES")
         for module, informations in modules.items():
         modules = self.projectInfo("MODULES")
         for module, informations in modules.items():
+            configurations = self.projectInfo("CONFIGURATIONS").get(informations["configuration"], {"paramlist": ()})
+            conditional_deps = {}
+            for i, param_name in configurations["paramlist"]:
+                information = configurations[param_name]
+                if information["informations"]["type"] == "boolean" and information["value"] != "0" and "conditional_deps" in information["informations"]:
+                    for dep in information["informations"]["conditional_deps"]:
+                        if not dep in conditional_deps:
+                            conditional_deps[dep] = []
+                        conditional_deps[dep].append((module, param_name))
             if dependency in informations["depends"] and informations["enabled"]:
                 unsatisfied |= set([module])
                 if dependency not in unsatisfied:
             if dependency in informations["depends"] and informations["enabled"]:
                 unsatisfied |= set([module])
                 if dependency not in unsatisfied:
-                    unsatisfied |= self.unselectDependencyCheck(module)
-        return unsatisfied
+                    tmp = self.unselectDependencyCheck(module)
+                    unsatisfied |= tmp[0]
+                    unsatisfied_params |= tmp[1]
+            if dependency in conditional_deps:
+                unsatisfied_params |= set(conditional_deps[dependency])
+        return unsatisfied, unsatisfied_params
     
     def removeFileDependencies(self, module):
         """
     
     def removeFileDependencies(self, module):
         """
@@ -484,6 +606,8 @@ class QControlGroup(QObject):
             self.connect(control, SIGNAL("currentIndexChanged(int)"), lambda: self.stateChanged(id))
         elif type(control) == QDoubleSpinBox:
             self.connect(control, SIGNAL("valueChanged(double)"), lambda: self.stateChanged(id))
             self.connect(control, SIGNAL("currentIndexChanged(int)"), lambda: self.stateChanged(id))
         elif type(control) == QDoubleSpinBox:
             self.connect(control, SIGNAL("valueChanged(double)"), lambda: self.stateChanged(id))
+        elif type(control) == QLineEdit:
+            self.connect(control, SIGNAL("textChanged(QString)"), lambda: self.stateChanged(id))
     
     def clear(self):
         """
     
     def clear(self):
         """
@@ -496,4 +620,4 @@ class QControlGroup(QObject):
         Slot called when the value of one of the stored widget changes. It emits
         another signal.
         """
         Slot called when the value of one of the stored widget changes. It emits
         another signal.
         """
-        self.emit(SIGNAL("stateChanged"), id)
\ No newline at end of file
+        self.emit(SIGNAL("stateChanged"), id)