doc: exclude the lwIP source code from the Doxygen-generated documentation.
[bertos.git] / wizard / BModulePage.py
index 2a5e0a420f361dbde5545b24a7ce95a2ee4204fc..5bee07241ac296482621c655e327a5495ff48640 100644 (file)
@@ -1,20 +1,45 @@
 #!/usr/bin/env python
 # encoding: utf-8
 #
 #!/usr/bin/env python
 # encoding: utf-8
 #
-# Copyright 2009 Develer S.r.l. (http://www.develer.com/)
-# All rights reserved.
+# This file is part of BeRTOS.
+#
+# Bertos is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program 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 General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+#
+# As a special exception, you may use this file as part of a free software
+# library without restriction.  Specifically, if other files instantiate
+# templates or use macros or inline functions from this file, or you compile
+# this file and link it with other files to produce an executable, this
+# file does not by itself cause the resulting executable to be covered by
+# the GNU General Public License.  This exception does not however
+# invalidate any other reasons why the executable file might be covered by
+# the GNU General Public License.
+#
+# 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
 
+from bertos_utils import SupportedException
 from DefineException import *
 from const import *
 
 from DefineException import *
 from const import *
 
@@ -27,53 +52,209 @@ class BModulePage(BWizardPage):
         BWizardPage.__init__(self, UI_LOCATION + "/module_select.ui")
         self.setTitle(self.tr("Configure the BeRTOS modules"))
         self._control_group = QControlGroup()
         BWizardPage.__init__(self, UI_LOCATION + "/module_select.ui")
         self.setTitle(self.tr("Configure the BeRTOS modules"))
         self._control_group = QControlGroup()
-        self._connectSignals()
+        ## special connection needed for the QControlGroup
+        self.connect(self._control_group, SIGNAL("stateChanged"), self.saveValue)
     
     
-    def reloadData(self):
+    ## Overloaded BWizardPage methods ##
+
+    def setupUi(self):
+        """
+        Overload of BWizardPage setupUi method.
+        """
+        self.pageContent.moduleTree.clear()
+        self.pageContent.moduleTree.setHeaderHidden(True)
+        self.pageContent.propertyTable.horizontalHeader().setResizeMode(QHeaderView.Stretch)
+        self.pageContent.propertyTable.horizontalHeader().setVisible(False)
+        self.pageContent.propertyTable.verticalHeader().setResizeMode(QHeaderView.ResizeToContents)
+        self.pageContent.propertyTable.verticalHeader().setVisible(False)
+        self.pageContent.propertyTable.setColumnCount(2)
+        self.pageContent.propertyTable.setRowCount(0)
+        self.pageContent.moduleLabel.setVisible(False)
+        self.pageContent.warningLabel.setVisible(False)
+    
+    def connectSignals(self):
+        """
+        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)
+
+    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()
+    
+    ####
     
     
-    def _setupButtonGroup(self):
+    ## Slots ##
+
+    def moduleClicked(self, item, column):
+        self.setBold(item, False)
+
+    def fillPropertyTable(self):
         """
         """
-        Sets up the button group.
+        Slot called when the user selects a module from the module tree.
+        Fills the property table using the configuration parameters defined in
+        the source tree.
         """
         """
-        self._button_group = QButtonGroup()
-        self._button_group.setExclusive(False)
-        self.connect(self._button_group, SIGNAL("buttonClicked(int)"), self._moduleSelectionChanged)
+        module = self.currentModule()
+        if module:
+            try:
+                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
+            self._control_group.clear()
+            configuration = self.projectInfo("MODULES")[module]["configuration"]
+            module_description = self.projectInfo("MODULES")[module]["description"]
+            self.pageContent.moduleLabel.setText(module_description)
+            self.pageContent.moduleLabel.setVisible(True)
+            if not supported:
+                self.pageContent.warningLabel.setVisible(True)
+                selected_cpu = self.projectInfo("CPU_NAME")
+                self.pageContent.warningLabel.setText(self.tr("<font color='#FF0000'>Warning: the selected module, \
+                    is not completely supported by the %1.</font>").arg(selected_cpu))
+            else:
+                self.pageContent.warningLabel.setVisible(False)
+            self.pageContent.propertyTable.clear()
+            self.pageContent.propertyTable.setRowCount(0)
+            if configuration != "":
+                configurations = self.projectInfo("CONFIGURATIONS")[configuration]
+                param_list = sorted(configurations["paramlist"])
+                index = 0
+                for i, property in param_list:
+                    if "type" in configurations[property]["informations"] and configurations[property]["informations"]["type"] == "autoenabled":
+                        # Doesn't show the hidden fields
+                        continue
+                    try:
+                        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
+                    if not param_supported:
+                        # Doesn't show the unsupported parameters
+                        continue
+                    # 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":
+                        self.insertCheckBox(index, configurations[property]["value"])
+                    elif "type" in configurations[property]["informations"] and configurations[property]["informations"]["type"] == "enum":
+                        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"]))
+                    index += 1
+            if self.pageContent.propertyTable.rowCount() == 0:
+                module_label = self.pageContent.moduleLabel.text()
+                module_label += "\n\nNo configuration needed."
+                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):
+        """
+        Checks the dependencies of the module associated with the given item.
+        """
+        checked = False
+        module = unicode(item.text(0))
+        if item.checkState(0) == Qt.Checked:
+            self.moduleSelected(module)
+        else:
+            self.moduleUnselected(module)
+            self.removeFileDependencies(module)
+
+    def showPropertyDescription(self):
+        """
+        Slot called when the property selection changes. Shows the description
+        of the selected property.
+        """
+        self.resetPropertyDescription()
+        configurations = self.currentModuleConfigurations()
+        if self.currentProperty() in configurations:
+            description = configurations[self.currentProperty()]["brief"]
+            name = self.currentProperty()
+            self.currentPropertyItem().setText(description + "\n" + name)
+
+    def saveValue(self, index):
+        """
+        Slot called when the user modifies one of the configuration parameters.
+        It stores the new value."""
+        property = qvariant_converter.getString(self.pageContent.propertyTable.item(index, 0).data(Qt.UserRole))
+        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"] = 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":
+            if self.pageContent.propertyTable.cellWidget(index, 1).isChecked():
+                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)
+        if self.moduleItem(self.currentModule()).checkState(0) == Qt.Checked:
+            self.dependencyCheck(self.moduleItem(self.currentModule()))
+
+    ####
     
     
-    def _loadModuleData(self):
+    def loadModuleData(self):
         """
         Loads the module data.
         """
         """
         Loads the module data.
         """
-        ## Load the module data only if it isn't already loaded
-        if self._projectInfoRetrieve("MODULES") == None \
-                and self._projectInfoRetrieve("LISTS") == None \
-                and self._projectInfoRetrieve("CONFIGURATIONS") == None:
+        # 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:
             except ModuleDefineException, e:
-                self._exceptionOccurred(self.tr("Error parsing line '%2' in file %1").arg(e.path).arg(e.line))
+                self.exceptionOccurred(self.tr("Error parsing line '%2' in file %1").arg(e.path).arg(e.line))
             except EnumDefineException, e:
             except EnumDefineException, e:
-                self._exceptionOccurred(self.tr("Error parsing line '%2' in file %1").arg(e.path).arg(e.line))
+                self.exceptionOccurred(self.tr("Error parsing line '%2' in file %1").arg(e.path).arg(e.line))
             except ConfigurationDefineException, e:
             except ConfigurationDefineException, e:
-                self._exceptionOccurred(self.tr("Error parsing line '%2' in file %1").arg(e.path).arg(e.line))
+                self.exceptionOccurred(self.tr("Error parsing line '%2' in file %1").arg(e.path).arg(e.line))
     
     
-    def _fillModuleTree(self):
+    def fillModuleTree(self):
         """
         Fills the module tree with the module entries separated in categories.
         """
         """
         Fills the module tree with the module entries separated in categories.
         """
-        modules = self._projectInfoRetrieve("MODULES")
-        if modules is None:
+        self.pageContent.moduleTree.clear()
+        modules = self.projectInfo("MODULES")
+        if not modules:
             return
         categories = {}
         for module, information in modules.items():
             return
         categories = {}
         for module, information in modules.items():
-            if information["category"] not in categories.keys():
+            if information["category"] not in categories:
                 categories[information["category"]] = []
             categories[information["category"]].append(module)
         for category, module_list in categories.items():
                 categories[information["category"]] = []
             categories[information["category"]].append(module)
         for category, module_list in categories.items():
@@ -81,59 +262,22 @@ class BModulePage(BWizardPage):
             for module in module_list:
                 enabled = modules[module]["enabled"]
                 module_item = QTreeWidgetItem(item, QStringList([module]))
             for module in module_list:
                 enabled = modules[module]["enabled"]
                 module_item = QTreeWidgetItem(item, QStringList([module]))
+                try:
+                    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
+                if not supported:
+                    module_item.setForeground(0, QBrush(QColor(Qt.red)))
                 if enabled:
                     module_item.setCheckState(0, Qt.Checked)
                 else:
                     module_item.setCheckState(0, Qt.Unchecked)
             self.pageContent.moduleTree.addTopLevelItem(item)
         self.pageContent.moduleTree.sortItems(0, Qt.AscendingOrder)
                 if enabled:
                     module_item.setCheckState(0, Qt.Checked)
                 else:
                     module_item.setCheckState(0, Qt.Unchecked)
             self.pageContent.moduleTree.addTopLevelItem(item)
         self.pageContent.moduleTree.sortItems(0, Qt.AscendingOrder)
-        
-    
-    def _fillPropertyTable(self):
-        """
-        Slot called when the user selects a module from the module tree.
-        Fills the property table using the configuration parameters defined in
-        the source tree.
-        """
-        module = self._currentModule()
-        if module is not None:
-            self._control_group.clear()
-            configuration = self._projectInfoRetrieve("MODULES")[module]["configuration"]
-            module_description = self._projectInfoRetrieve("MODULES")[module]["description"]
-            self.pageContent.moduleLabel.setText(module_description)
-            self.pageContent.moduleLabel.setVisible(True)
-            self.pageContent.propertyTable.clear()
-            self.pageContent.propertyTable.setRowCount(0)
-            if configuration != "":
-                configurations = self._projectInfoRetrieve("CONFIGURATIONS")[configuration]
-                param_list = sorted(configurations["paramlist"])
-                index = 0
-                for i, property in param_list:
-                    if "type" in configurations[property]["informations"] and configurations[property]["informations"]["type"] == "autoenabled":
-                        ## Doesn't show the hidden fields
-                        pass
-                    else:
-                        ## Set the row count to the current index + 1
-                        self.pageContent.propertyTable.setRowCount(index + 1)
-                        item = QTableWidgetItem(configurations[property]["brief"])
-                        item.setData(Qt.UserRole, qvariant_converter.convertString(property))
-                        self.pageContent.propertyTable.setItem(index, 0, item)
-                        if "type" in configurations[property]["informations"].keys() and configurations[property]["informations"]["type"] == "boolean":
-                            self._insertCheckBox(index, configurations[property]["value"])
-                        elif "type" in configurations[property]["informations"].keys() and configurations[property]["informations"]["type"] == "enum":
-                            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"])
-                        else:
-                            # Not defined type, rendered as a text field
-                            self.pageContent.propertyTable.setItem(index, 1, QTableWidgetItem(configurations[property]["value"]))
-                        index += 1
-            if self.pageContent.propertyTable.rowCount() == 0:
-                module_label = self.pageContent.moduleLabel.text()
-                module_label += "\n\nNo configuration needed."
-                self.pageContent.moduleLabel.setText(module_label)
-    
-    def _insertCheckBox(self, index, value):
+        self.fillPropertyTable()
+            
+    def insertCheckBox(self, index, value):
         """
         Inserts in the table at index a checkbox for a boolean property setted
         to value.
         """
         Inserts in the table at index a checkbox for a boolean property setted
         to value.
@@ -146,13 +290,13 @@ class BModulePage(BWizardPage):
             check_box.setChecked(False)
         self._control_group.addControl(index, check_box)
     
             check_box.setChecked(False)
         self._control_group.addControl(index, check_box)
     
-    def _insertComboBox(self, index, value, value_list):
+    def insertComboBox(self, index, value, value_list):
         """
         Inserts in the table at index a combobox for an enum property setted
         to value.
         """
         try:
         """
         Inserts in the table at index a combobox for an enum property setted
         to value.
         """
         try:
-            enum = self._projectInfoRetrieve("LISTS")[value_list]
+            enum = self.projectInfo("LISTS")[value_list]
             combo_box = QComboBox()
             self.pageContent.propertyTable.setCellWidget(index, 1, combo_box)
             for i, element in enumerate(enum):
             combo_box = QComboBox()
             self.pageContent.propertyTable.setCellWidget(index, 1, combo_box)
             for i, element in enumerate(enum):
@@ -161,15 +305,15 @@ class BModulePage(BWizardPage):
                     combo_box.setCurrentIndex(i)
             self._control_group.addControl(index, combo_box)
         except KeyError:
                     combo_box.setCurrentIndex(i)
             self._control_group.addControl(index, combo_box)
         except KeyError:
-            self._exceptionOccurred(self.tr("Define list \"%1\" not found. Check definition files.").arg(value_list))
+            self.exceptionOccurred(self.tr("Define list \"%1\" not found. Check definition files.").arg(value_list))
             self.pageContent.propertyTable.setItem(index, 1, QTableWidgetItem(value))
     
             self.pageContent.propertyTable.setItem(index, 1, QTableWidgetItem(value))
     
-    def _insertSpinBox(self, index, value, informations):
+    def insertSpinBox(self, index, value, informations):
         """
         Inserts in the table at index a spinbox for an int, a long or an unsigned
         long property setted to value.
         """
         """
         Inserts in the table at index a spinbox for an int, a long or an unsigned
         long property setted to value.
         """
-        ## int, long or undefined type property
+        # int, long or undefined type property
         spin_box = None
         if bertos_utils.isLong(informations) or bertos_utils.isUnsignedLong(informations):
             spin_box = QDoubleSpinBox()
         spin_box = None
         if bertos_utils.isLong(informations) or bertos_utils.isUnsignedLong(informations):
             spin_box = QDoubleSpinBox()
@@ -192,9 +336,9 @@ class BModulePage(BWizardPage):
             minimum = 0
             maximum = 4294967295
             suff = "UL"
             minimum = 0
             maximum = 4294967295
             suff = "UL"
-        if "min" in informations.keys():
+        if "min" in informations:
             minimum = int(informations["min"])
             minimum = int(informations["min"])
-        if "max" in informations.keys():
+        if "max" in informations:
             maximum = int(informations["max"])
         spin_box.setRange(minimum, maximum)
         spin_box.setSuffix(suff)
             maximum = int(informations["max"])
         spin_box.setRange(minimum, maximum)
         spin_box.setSuffix(suff)
@@ -202,185 +346,189 @@ class BModulePage(BWizardPage):
         self._control_group.addControl(index, spin_box)
         
     
         self._control_group.addControl(index, spin_box)
         
     
-    def _currentModule(self):
+    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.
         """
         current_module = self.pageContent.moduleTree.currentItem()
         # return only the child items
         """
         Retuns the current module name.
         """
         current_module = self.pageContent.moduleTree.currentItem()
         # return only the child items
-        if current_module is not None and current_module.parent() is not None:
+        if current_module and current_module.parent():
             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):
         """
         Returns the current module configuration.
         """
         """
         Returns the current module configuration.
         """
-        return self._configurations(self._currentModule())
+        return self.configurations(self.currentModule())
     
     
-    def _currentProperty(self):
+    def currentProperty(self):
         """
         Rerturns the current property from the property table.
         """
         return qvariant_converter.getString(self.pageContent.propertyTable.item(self.pageContent.propertyTable.currentRow(), 0).data(Qt.UserRole))
     
         """
         Rerturns the current property from the property table.
         """
         return qvariant_converter.getString(self.pageContent.propertyTable.item(self.pageContent.propertyTable.currentRow(), 0).data(Qt.UserRole))
     
-    def _currentPropertyItem(self):
+    def currentPropertyItem(self):
         """
         Returns the QTableWidgetItem of the current property.
         """
         return self.pageContent.propertyTable.item(self.pageContent.propertyTable.currentRow(), 0)
     
         """
         Returns the QTableWidgetItem of the current property.
         """
         return self.pageContent.propertyTable.item(self.pageContent.propertyTable.currentRow(), 0)
     
-    def _configurations(self, module):
+    def configurations(self, module):
         """
         Returns the configuration for the selected module.
         """
         """
         Returns the configuration for the selected module.
         """
-        configuration = self._projectInfoRetrieve("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:
         if len(configuration) > 0:
-            return self._projectInfoRetrieve("CONFIGURATIONS")[configuration]
+            return self.projectInfo("CONFIGURATIONS")[configuration]
         else:
             return {}
     
         else:
             return {}
     
-    def _resetPropertyDescription(self):
+    def resetPropertyDescription(self):
         """
         Resets the label for each property table entry.
         """
         for index in range(self.pageContent.propertyTable.rowCount()):
             property_name = qvariant_converter.getString(self.pageContent.propertyTable.item(index, 0).data(Qt.UserRole))
             # Awful solution! Needed because if the user change the module, the selection changed...
         """
         Resets the label for each property table entry.
         """
         for index in range(self.pageContent.propertyTable.rowCount()):
             property_name = qvariant_converter.getString(self.pageContent.propertyTable.item(index, 0).data(Qt.UserRole))
             # Awful solution! Needed because if the user change the module, the selection changed...
-            if property_name not in self._currentModuleConfigurations().keys():
+            if property_name not in self.currentModuleConfigurations():
                 break
                 break
-            self.pageContent.propertyTable.item(index, 0).setText(self._currentModuleConfigurations()[property_name]['brief'])
-    
-    def _showPropertyDescription(self):
-        """
-        Slot called when the property selection changes. Shows the description
-        of the selected property.
-        """
-        self._resetPropertyDescription()
-        configurations = self._currentModuleConfigurations()
-        if self._currentProperty() in configurations.keys():
-            description = configurations[self._currentProperty()]["brief"]
-            name = self._currentProperty()
-            self._currentPropertyItem().setText(description + "\n" + name)
-    
-    def _setupUi(self):
-        """
-        Set up the user interface.
-        """
-        self.pageContent.moduleTree.clear()
-        self.pageContent.moduleTree.setHeaderHidden(True)
-        self.pageContent.propertyTable.horizontalHeader().setResizeMode(QHeaderView.Stretch)
-        self.pageContent.propertyTable.horizontalHeader().setVisible(False)
-        self.pageContent.propertyTable.verticalHeader().setResizeMode(QHeaderView.ResizeToContents)
-        self.pageContent.propertyTable.verticalHeader().setVisible(False)
-        self.pageContent.propertyTable.setColumnCount(2)
-        self.pageContent.propertyTable.setRowCount(0)
-        self.pageContent.moduleLabel.setVisible(False)
-    
-    def _connectSignals(self):
-        """
-        Connect the signals with the related slots.
-        """
-        self.connect(self.pageContent.moduleTree, SIGNAL("itemPressed(QTreeWidgetItem*, int)"), self._fillPropertyTable)
-        self.connect(self.pageContent.moduleTree, SIGNAL("itemChanged(QTreeWidgetItem*, int)"), self._dependencyCheck)
-        self.connect(self.pageContent.propertyTable, SIGNAL("itemSelectionChanged()"), self._showPropertyDescription)
-        self.connect(self._control_group, SIGNAL("stateChanged"), self._saveValue)
+            self.pageContent.propertyTable.item(index, 0).setText(self.currentModuleConfigurations()[property_name]['brief'])
     
     
-    def _saveValue(self, index):
-        """
-        Slot called when the user modifies one of the configuration parameters.
-        It stores the new value."""
-        property = qvariant_converter.getString(self.pageContent.propertyTable.item(index, 0).data(Qt.UserRole))
-        configuration = self._projectInfoRetrieve("MODULES")[self._currentModule()]["configuration"]
-        configurations = self._projectInfoRetrieve("CONFIGURATIONS")
-        if "type" not in configurations[configuration][property]["informations"].keys() or configurations[configuration][property]["informations"]["type"] == "int":
-            configurations[configuration][property]["value"] = str(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":
-            if self.pageContent.propertyTable.cellWidget(index, 1).isChecked():
-                configurations[configuration][property]["value"] = "1"
-            else:
-                configurations[configuration][property]["value"] = "0"
-        self._projectInfoStore("CONFIGURATIONS", configurations)
-    
-    def _moduleSelectionChanged(self, index):
-        """
-        Slot called when the user selects or unselects a module from the module
-        tree.
-        """
-        module = unicode(self.pageContent.moduleTable.item(index, 1).text())
-        if self._button_group.button(index).isChecked():
-            self._moduleSelected(module)
-        else:
-            self._moduleUnselected(module)
-    
-    def _dependencyCheck(self, item):
-        """
-        Checks the dependencies of the module associated with the given item.
-        """
-        checked = False
-        module = unicode(item.text(0))
-        if item.checkState(0) == Qt.Checked:
-            self._moduleSelected(module)
-        else:
-            self._moduleUnselected(module)
-            self.removeFileDependencies(module)
-    
-    def _moduleSelected(self, selectedModule):
+    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.
         """
         """
         Resolves the selection dependencies.
         """
-        modules = self._projectInfoRetrieve("MODULES")
-        modules[selectedModule]["enabled"] = True
-        self._projectInfoStore("MODULES", modules)
-        depends = self._projectInfoRetrieve("MODULES")[selectedModule]["depends"]
-        unsatisfied = []
-        if self.pageContent.automaticFix.isChecked():
-            unsatisfied = self.selectDependencyCheck(selectedModule)
-        if len(unsatisfied) > 0:
-            for module in unsatisfied:
-                modules = self._projectInfoRetrieve("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._projectInfoRetrieve("MODULES")
-        modules[unselectedModule]["enabled"] = False
-        self._projectInfoStore("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:
                 for module in unsatisfied:
-                    modules = self._projectInfoRetrieve("MODULES")
-                    modules[module]["enabled"] = False
+                    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:
                 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):
         """
         Returns the list of unsatisfied dependencies after a selection.
         """
         unsatisfied = set()
     
     def selectDependencyCheck(self, module):
         """
         Returns the list of unsatisfied dependencies after a selection.
         """
         unsatisfied = set()
-        modules = self._projectInfoRetrieve("MODULES")
-        files = self._projectInfoRetrieve("FILES")
-        for dependency in modules[module]["depends"]:
+        modules = self.projectInfo("MODULES")
+        files = self.projectInfo("FILES")
+        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:
@@ -390,7 +538,7 @@ class BModulePage(BWizardPage):
                     files[dependency] += 1
                 else:
                     files[dependency] = 1
                     files[dependency] += 1
                 else:
                     files[dependency] = 1
-        self._projectInfoStore("FILES", files)
+        self.setProjectInfo("FILES", files)
         return unsatisfied
     
     def unselectDependencyCheck(self, dependency):
         return unsatisfied
     
     def unselectDependencyCheck(self, dependency):
@@ -398,27 +546,41 @@ 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()
-        modules = self._projectInfoRetrieve("MODULES")
+        unsatisfied_params = set()
+        modules = self.projectInfo("MODULES")
         for module, informations in modules.items():
         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):
         """
         Removes the files dependencies of the given module.
         """
     
     def removeFileDependencies(self, module):
         """
         Removes the files dependencies of the given module.
         """
-        modules = self._projectInfoRetrieve("MODULES")
-        files = self._projectInfoRetrieve("FILES")
+        modules = self.projectInfo("MODULES")
+        files = self.projectInfo("FILES")
         dependencies = modules[module]["depends"]
         for dependency in dependencies:
             if dependency in files:
                 files[dependency] -= 1
                 if files[dependency] == 0:
                     del files[dependency]
         dependencies = modules[module]["depends"]
         for dependency in dependencies:
             if dependency in files:
                 files[dependency] -= 1
                 if files[dependency] == 0:
                     del files[dependency]
-        self._projectInfoStore("FILES", files)
+        self.setProjectInfo("FILES", files)
 
 class QControlGroup(QObject):
     """
 
 class QControlGroup(QObject):
     """
@@ -437,13 +599,15 @@ class QControlGroup(QObject):
         """
         self._controls[id] = control
         if type(control) == QCheckBox:
         """
         self._controls[id] = control
         if type(control) == QCheckBox:
-            self.connect(control, SIGNAL("stateChanged(int)"), lambda: self._stateChanged(id))
+            self.connect(control, SIGNAL("stateChanged(int)"), lambda: self.stateChanged(id))
         elif type(control) == QSpinBox:
         elif type(control) == QSpinBox:
-            self.connect(control, SIGNAL("valueChanged(int)"), lambda: self._stateChanged(id))
+            self.connect(control, SIGNAL("valueChanged(int)"), lambda: self.stateChanged(id))
         elif type(control) == QComboBox:
         elif type(control) == QComboBox:
-            self.connect(control, SIGNAL("currentIndexChanged(int)"), lambda: self._stateChanged(id))
+            self.connect(control, SIGNAL("currentIndexChanged(int)"), lambda: self.stateChanged(id))
         elif type(control) == QDoubleSpinBox:
         elif type(control) == QDoubleSpinBox:
-            self.connect(control, SIGNAL("valueChanged(double)"), lambda: self._stateChanged(id))
+            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):
         """
@@ -451,9 +615,9 @@ class QControlGroup(QObject):
         """
         self._controls = {}
     
         """
         self._controls = {}
     
-    def _stateChanged(self, id):
+    def stateChanged(self, id):
         """
         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)