Correct error
[bertos.git] / wizard / BToolchainPage.py
1 #!/usr/bin/env python
2 # encoding: utf-8
3 #
4 # Copyright 2008 Develer S.r.l. (http://www.develer.com/)
5 # All rights reserved.
6 #
7 # $Id$
8 #
9 # Author: Lorenzo Berni <duplo@develer.com>
10 #
11
12 import os
13 import collections
14
15 from BWizardPage import *
16 import BToolchainSearch
17 import bertos_utils
18 import qvariant_converter
19
20 from const import *
21
22 class BToolchainPage(BWizardPage):
23     """
24     Page of the wizard that permits to choose the toolchain to use for the
25     project.
26     """
27
28     def __init__(self):
29         BWizardPage.__init__(self, UI_LOCATION + "/toolchain_select.ui")
30         self.setTitle(self.tr("Select toolchain"))
31         self._validation_process = None
32         self._valid_items = []
33
34     ## Overloaded QWizardPage methods. ##
35
36     def isComplete(self):
37         """
38         Overload of the QWizard isComplete method.
39         """
40         if self.pageContent.toolchainList.currentRow() != -1:
41             self.setProjectInfo("TOOLCHAIN",
42                 qvariant_converter.getStringDict(self.pageContent.toolchainList.currentItem().data(Qt.UserRole)))
43             return True
44         else:
45             return False
46
47     ####
48
49     ## Overloaded BWizardPage methods. ##
50
51     def setupUi(self):
52         """
53         Sets up the user interface.
54         """
55         self.pageContent.infoLabel.setVisible(False)
56
57     def connectSignals(self):
58         """
59         Connects the signals with the related slots.
60         """
61         self.connect(self.pageContent.toolchainList, SIGNAL("itemSelectionChanged()"), self.selectionChanged)
62         self.connect(self.pageContent.addButton, SIGNAL("clicked()"), self.addToolchain)
63         self.connect(self.pageContent.removeButton, SIGNAL("clicked()"), self.removeToolchain)
64         self.connect(self.pageContent.searchButton, SIGNAL("clicked()"), self.searchToolchain)
65         self.connect(self.pageContent.checkButton, SIGNAL("clicked()"), self.validateAllToolchains)
66
67     def reloadData(self):
68         """
69         Overload of the BWizard reloadData method.
70         """
71         self._clearList()
72         self.setupUi()
73         self._populateToolchainList()
74         if len(self._valid_items) == 1:
75             self.pageContent.toolchainList.setCurrentItem(self._valid_items[0])
76
77     ####
78
79     ## Slots ##
80
81     def selectionChanged(self):
82         """
83         Slot called when the user click on an entry of the toolchain list.
84         """
85         if self.pageContent.toolchainList.currentRow() != -1:
86             infos = collections.defaultdict(lambda: unicode("not defined"))
87             infos.update(qvariant_converter.getStringDict(self.pageContent.toolchainList.currentItem().data(Qt.UserRole)))
88             self.pageContent.infoLabel.setText("GCC " + infos["version"] + " (" + infos["build"] + ")\nTarget: " + infos["target"] + "\nPath: " + os.path.normpath(infos["path"]))
89             self.pageContent.infoLabel.setVisible(True)
90             if self.isDefaultToolchain(infos):
91                 self.disableRemoveButton()
92             else:
93                 self.enableRemoveButton()
94             self.emit(SIGNAL("completeChanged()"))
95
96     def addToolchain(self):
97         """
98         Slot called when the user adds manually a toolchain.
99         """
100         sel_toolchain = unicode(QFileDialog.getOpenFileName(self, self.tr("Choose the toolchain"), ""))
101         if sel_toolchain != "":
102             item = QListWidgetItem(sel_toolchain)
103             item.setData(Qt.UserRole, qvariant_converter.convertStringDict({"path": sel_toolchain}))
104             self.pageContent.toolchainList.addItem(item)
105             toolchains = self.toolchains()
106             toolchains[sel_toolchain] = False
107             self.setToolchains(toolchains)
108
109     def removeToolchain(self):
110         """
111         Slot called when the user removes manually a toolchain.
112         """
113         if self.pageContent.toolchainList.currentRow() != -1:
114             item = self.pageContent.toolchainList.takeItem(self.pageContent.toolchainList.currentRow())
115             toolchain = qvariant_converter.getStringDict(item.data(Qt.UserRole))["path"]
116             toolchains = self.toolchains()
117             del toolchains[toolchain]
118             self.setToolchains(toolchains)
119
120     def searchToolchain(self):
121         """
122         Slot called when the user clicks on the 'search' button. It opens the
123         toolchain search dialog.
124         """
125         search = BToolchainSearch.BToolchainSearch()
126         self.connect(search, SIGNAL("accepted()"), self._search)
127         search.exec_()
128
129     def validateAllToolchains(self):
130         """
131         Slot called when the user clicks on the validate button. It starts the
132         toolchain validation procedure for all the toolchains.
133         """
134         QApplication.instance().setOverrideCursor(Qt.WaitCursor)
135         for i in range(self.pageContent.toolchainList.count()):
136             self.validateToolchain(i)
137         QApplication.instance().restoreOverrideCursor()
138
139     ####
140
141     def _populateToolchainList(self):
142         """
143         Fills the toolchain list with the toolchains stored in the QSettings.
144         """
145         toolchains = self.toolchains()
146         if os.name == "nt":
147             import winreg_importer
148             stored_toolchains = winreg_importer.getBertosToolchains()
149             for toolchain in stored_toolchains:
150                 toolchains[toolchain] = True
151         sel_toolchain = self.projectInfo("TOOLCHAIN")
152         for key, value in toolchains.items():
153             item = QListWidgetItem(key)
154             item.setData(Qt.UserRole, qvariant_converter.convertStringDict({"path": key}))
155             self.pageContent.toolchainList.addItem(item)
156             if sel_toolchain and sel_toolchain["path"] == key:
157                 self.pageContent.toolchainList.setCurrentItem(item)
158             if value:
159                 self.validateToolchain(self.pageContent.toolchainList.row(item))
160
161     def _clearList(self):
162         """
163         Removes all the toolchain from the list.
164         """
165         self.pageContent.toolchainList.clear()
166
167     def _search(self):
168         """
169         Searches for toolchains in the stored directories, and stores them in the
170         QSettings.
171         """
172         dir_list = self.searchDirList()
173         if self.pathSearch():
174             dir_list += [element for element in bertos_utils.getSystemPath()]
175         toolchain_list = bertos_utils.findToolchains(dir_list)
176         stored_toolchains = self.toolchains()
177         for element in toolchain_list:
178             if not element in stored_toolchains:
179                 item = QListWidgetItem(element)
180                 item.setData(Qt.UserRole, qvariant_converter.convertStringDict({"path": element}))
181                 self.pageContent.toolchainList.addItem(item)
182                 stored_toolchains[element] = False
183         self.setToolchains(stored_toolchains)
184         self.showMessage(self.tr("Toolchain search result."), self.tr("%1 toolchains founded").arg(len(stored_toolchains)))
185
186     def _validItem(self, index, infos):
187         """
188         Sets the item at index as a valid item and associates the given info to it.
189         """
190         item = self.pageContent.toolchainList.item(index)
191         new_data = qvariant_converter.getStringDict(self.pageContent.toolchainList.item(index).data(Qt.UserRole))
192         new_data.update(infos)
193         item.setData(Qt.UserRole, qvariant_converter.convertStringDict(new_data))
194         needed = self.projectInfo("CPU_INFOS")
195         if "target" in infos and infos["target"].find(needed["TOOLCHAIN"]) != -1:
196             item.setIcon(QIcon(":/images/ok.png"))
197             self._valid_items.append(item)
198         else:
199             item.setIcon(QIcon(":/images/warning.png"))
200         if "version" in infos and "target" in infos:
201             item.setText("GCC " + infos["version"] + " - " + infos["target"].strip())
202
203     def _invalidItem(self, index):
204         """
205         Sets the item at index as an invalid item.
206         """
207         item = self.pageContent.toolchainList.item(index)
208         item.setIcon(QIcon(":/images/error.png"))
209
210     def validateToolchain(self, i):
211         """
212         Toolchain validation procedure.
213         """
214         filename = qvariant_converter.getStringDict(self.pageContent.toolchainList.item(i).data(Qt.UserRole))["path"]
215         valid = False
216         info = {}
217         # Check for the other tools of the toolchain
218         for tool in TOOLCHAIN_ITEMS:
219             if os.path.exists(filename.replace("gcc", tool)):
220                 valid = True
221             else:
222                 valid = False
223                 break
224         # Try to retrieve the informations about the toolchain only for the valid toolchains
225         if valid:
226             self._validation_process = QProcess()
227             self._validation_process.start(filename, ["-v"])
228             self._validation_process.waitForStarted(1000)
229             if self._validation_process.waitForFinished(200):
230                 description = str(self._validation_process.readAllStandardError())
231                 info = bertos_utils.getToolchainInfo(description)
232                 if len(info) >= 4:
233                     valid = True
234             else:
235                 self._validation_process.kill()
236         # Add the item in the list with the appropriate associate data.
237         if valid:
238             self._validItem(i, info)
239         else:
240             self._invalidItem(i)
241         toolchains = self.toolchains()
242         toolchains[filename] = True
243         self.setToolchains(toolchains)
244     
245     def isDefaultToolchain(self, toolchain):
246         """
247         Returns True if the given toolchain is one of the default toolchains.
248         """
249         if os.name == "nt":
250             import winreg_importer
251             stored_toolchains = winreg_importer.getBertosToolchains()
252             if toolchain["path"] in stored_toolchains:
253                 return True
254         return False
255     
256     def disableRemoveButton(self):
257         """
258         Disable the remove button.
259         """
260         self.pageContent.removeButton.setEnabled(False)
261     
262     def enableRemoveButton(self):
263         """
264         Enable the remove button.
265         """
266         self.pageContent.removeButton.setEnabled(True)
267