Init lcd_semaphore when kernel is active.
[bertos.git] / wizard / BModulePage.py
index e0bcd9db956545199a0ee753581b8121ca2ce737..8d382be26ab953624106fb9b331b6aafe87d0790 100644 (file)
@@ -1,8 +1,32 @@
 #!/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$
 #
 #
 # $Id$
 #
@@ -53,6 +77,7 @@ 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.propertyTable, SIGNAL("itemSelectionChanged()"), self.showPropertyDescription)
 
         self.connect(self.pageContent.moduleTree, SIGNAL("itemChanged(QTreeWidgetItem*, int)"), self.dependencyCheck)
         self.connect(self.pageContent.propertyTable, SIGNAL("itemSelectionChanged()"), self.showPropertyDescription)
 
@@ -70,6 +95,9 @@ class BModulePage(BWizardPage):
     
     ## 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.
@@ -77,11 +105,11 @@ class BModulePage(BWizardPage):
         the source tree.
         """
         module = self.currentModule()
         the source tree.
         """
         module = self.currentModule()
-        if module is not None:
+        if module:
             try:
                 supported = bertos_utils.isSupported(self.project(), module=module)
             except SupportedException, e:
             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(selectedModule))
+                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"]
                 supported = True
             self._control_group.clear()
             configuration = self.projectInfo("MODULES")[module]["configuration"]
@@ -108,7 +136,7 @@ class BModulePage(BWizardPage):
                     try:
                         param_supported = bertos_utils.isSupported(self.project(), property_id=(configuration, property))
                     except SupportedException, e:
                     try:
                         param_supported = bertos_utils.isSupported(self.project(), property_id=(configuration, property))
                     except SupportedException, e:
-                        self.exceptionOccurred(self.tr("Error evaluating \"%1\" for module %2").arg(e.support_string).arg(selectedModule))
+                        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
                         param_supported = True
                     if not param_supported:
                         # Doesn't show the unsupported parameters
@@ -118,9 +146,9 @@ class BModulePage(BWizardPage):
                     item = QTableWidgetItem(configurations[property]["brief"])
                     item.setData(Qt.UserRole, qvariant_converter.convertString(property))
                     self.pageContent.propertyTable.setItem(index, 0, item)
                     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":
+                    if "type" in configurations[property]["informations"] and configurations[property]["informations"]["type"] == "boolean":
                         self.insertCheckBox(index, configurations[property]["value"])
                         self.insertCheckBox(index, configurations[property]["value"])
-                    elif "type" in configurations[property]["informations"].keys() and configurations[property]["informations"]["type"] == "enum":
+                    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"])
                         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"])
@@ -131,7 +159,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):
         """
@@ -152,7 +185,7 @@ class BModulePage(BWizardPage):
         """
         self.resetPropertyDescription()
         configurations = self.currentModuleConfigurations()
         """
         self.resetPropertyDescription()
         configurations = self.currentModuleConfigurations()
-        if self.currentProperty() in configurations.keys():
+        if self.currentProperty() in configurations:
             description = configurations[self.currentProperty()]["brief"]
             name = self.currentProperty()
             self.currentPropertyItem().setText(description + "\n" + name)
             description = configurations[self.currentProperty()]["brief"]
             name = self.currentProperty()
             self.currentPropertyItem().setText(description + "\n" + name)
@@ -164,8 +197,8 @@ class BModulePage(BWizardPage):
         property = qvariant_converter.getString(self.pageContent.propertyTable.item(index, 0).data(Qt.UserRole))
         configuration = self.projectInfo("MODULES")[self.currentModule()]["configuration"]
         configurations = self.projectInfo("CONFIGURATIONS")
         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"].keys() or configurations[configuration][property]["informations"]["type"] == "int":
-            configurations[configuration][property]["value"] = str(int(self.pageContent.propertyTable.cellWidget(index, 1).value()))
+        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":
         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":
@@ -174,6 +207,8 @@ class BModulePage(BWizardPage):
             else:
                 configurations[configuration][property]["value"] = "0"
         self.setProjectInfo("CONFIGURATIONS", configurations)
             else:
                 configurations[configuration][property]["value"] = "0"
         self.setProjectInfo("CONFIGURATIONS", configurations)
+        if self.moduleItem(self.currentModule()).checkState(0) == Qt.Checked:
+            self.dependencyCheck(self.moduleItem(self.currentModule()))
 
     ####
     
 
     ####
     
@@ -182,9 +217,9 @@ class BModulePage(BWizardPage):
         Loads the module data.
         """
         # Load the module data only if it isn't already loaded
         Loads the module data.
         """
         # Load the module data only if it isn't already loaded
-        if self.projectInfo("MODULES") == None \
-                and self.projectInfo("LISTS") == None \
-                and self.projectInfo("CONFIGURATIONS") == None:
+        if not self.projectInfo("MODULES") \
+                and not self.projectInfo("LISTS") \
+                and not self.projectInfo("CONFIGURATIONS"):
             try:
                 bertos_utils.loadModuleData(self.project())
             except ModuleDefineException, e:
             try:
                 bertos_utils.loadModuleData(self.project())
             except ModuleDefineException, e:
@@ -198,12 +233,13 @@ 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")
         modules = self.projectInfo("MODULES")
-        if modules is None:
+        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():
@@ -214,7 +250,7 @@ class BModulePage(BWizardPage):
                 try:
                     supported = bertos_utils.isSupported(self.project(), module=module)
                 except SupportedException, e:
                 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(selectedModule))
+                    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)))
                     supported = True
                 if not supported:
                     module_item.setForeground(0, QBrush(QColor(Qt.red)))
@@ -224,6 +260,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):
         """
@@ -284,9 +321,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)
@@ -300,10 +337,19 @@ class BModulePage(BWizardPage):
         """
         current_module = self.pageContent.moduleTree.currentItem()
         # return only the child items
         """
         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):
         """
@@ -340,10 +386,17 @@ class BModulePage(BWizardPage):
         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...
         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
             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 moduleSelected(self, selectedModule):
         """
         Resolves the selection dependencies.
     def moduleSelected(self, selectedModule):
         """
         Resolves the selection dependencies.
@@ -363,6 +416,8 @@ class BModulePage(BWizardPage):
                 item = self.pageContent.moduleTree.topLevelItem(category)
                 for child in range(item.childCount()):
                     if unicode(item.child(child).text(0)) in unsatisfied:
                 item = self.pageContent.moduleTree.topLevelItem(category)
                 for child in range(item.childCount()):
                     if unicode(item.child(child).text(0)) in unsatisfied:
+                        self.setBold(item.child(child), True)
+                        self.setBold(item, True)
                         item.child(child).setCheckState(0, Qt.Checked)
     
     def moduleUnselected(self, unselectedModule):
                         item.child(child).setCheckState(0, Qt.Checked)
     
     def moduleUnselected(self, unselectedModule):
@@ -373,12 +428,24 @@ class BModulePage(BWizardPage):
         modules[unselectedModule]["enabled"] = False
         self.setProjectInfo("MODULES", modules)
         unsatisfied = []
         modules[unselectedModule]["enabled"] = False
         self.setProjectInfo("MODULES", modules)
         unsatisfied = []
+        unsatisfied_params = []
         if self.pageContent.automaticFix.isChecked():
         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)
+            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?"))
+            choice = QMessageBox.warning(self, self.tr("Dependency error"), message_str, QMessageBox.Yes | QMessageBox.No, QMessageBox.Yes)
             if choice == QMessageBox.Yes:
                 for module in unsatisfied:
                     modules = self.projectInfo("MODULES")
             if choice == QMessageBox.Yes:
                 for module in unsatisfied:
                     modules = self.projectInfo("MODULES")
@@ -388,6 +455,11 @@ class BModulePage(BWizardPage):
                     for child in range(item.childCount()):
                         if unicode(item.child(child).text(0)) in unsatisfied:
                             item.child(child).setCheckState(0, Qt.Unchecked)
                     for child in range(item.childCount()):
                         if unicode(item.child(child).text(0)) in unsatisfied:
                             item.child(child).setCheckState(0, Qt.Unchecked)
+                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)
     
     def selectDependencyCheck(self, module):
         """
     
     def selectDependencyCheck(self, module):
         """
@@ -396,7 +468,13 @@ 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:
@@ -414,13 +492,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):
         """
@@ -472,4 +564,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)