When there is only one toolchain for the specified architecture the wizard selects...
[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             self.emit(SIGNAL("completeChanged()"))
91
92     def addToolchain(self):
93         """
94         Slot called when the user adds manually a toolchain.
95         """
96         sel_toolchain = unicode(QFileDialog.getOpenFileName(self, self.tr("Choose the toolchain"), ""))
97         if sel_toolchain != "":
98             item = QListWidgetItem(sel_toolchain)
99             item.setData(Qt.UserRole, qvariant_converter.convertStringDict({"path": sel_toolchain}))
100             self.pageContent.toolchainList.addItem(item)
101             toolchains = self.toolchains()
102             toolchains[sel_toolchain] = False
103             self.setToolchains(toolchains)
104
105     def removeToolchain(self):
106         """
107         Slot called when the user removes manually a toolchain.
108         """
109         if self.pageContent.toolchainList.currentRow() != -1:
110             item = self.pageContent.toolchainList.takeItem(self.pageContent.toolchainList.currentRow())
111             toolchain = qvariant_converter.getStringDict(item.data(Qt.UserRole))["path"]
112             toolchains = self.toolchains()
113             del toolchains[toolchain]
114             self.setToolchains(toolchains)
115
116     def searchToolchain(self):
117         """
118         Slot called when the user clicks on the 'search' button. It opens the
119         toolchain search dialog.
120         """
121         search = BToolchainSearch.BToolchainSearch()
122         self.connect(search, SIGNAL("accepted()"), self._search)
123         search.exec_()
124
125     def validateAllToolchains(self):
126         """
127         Slot called when the user clicks on the validate button. It starts the
128         toolchain validation procedure for all the toolchains.
129         """
130         QApplication.instance().setOverrideCursor(Qt.WaitCursor)
131         for i in range(self.pageContent.toolchainList.count()):
132             self.validateToolchain(i)
133         QApplication.instance().restoreOverrideCursor()
134
135     ####
136
137     def _populateToolchainList(self):
138         """
139         Fills the toolchain list with the toolchains stored in the QSettings.
140         """
141         toolchains = self.toolchains()
142         if os.name == "nt":
143             import winreg_importer
144             stored_toolchains = winreg_importer.getBertosToolchains()
145             for toolchain in stored_toolchains:
146                 toolchains[toolchain] = True
147         sel_toolchain = self.projectInfo("TOOLCHAIN")
148         for key, value in toolchains.items():
149             item = QListWidgetItem(key)
150             item.setData(Qt.UserRole, qvariant_converter.convertStringDict({"path": key}))
151             self.pageContent.toolchainList.addItem(item)
152             if sel_toolchain and sel_toolchain["path"] == key:
153                 self.pageContent.toolchainList.setCurrentItem(item)
154             if value:
155                 self.validateToolchain(self.pageContent.toolchainList.row(item))
156
157     def _clearList(self):
158         """
159         Removes all the toolchain from the list.
160         """
161         self.pageContent.toolchainList.clear()
162
163     def _search(self):
164         """
165         Searches for toolchains in the stored directories, and stores them in the
166         QSettings.
167         """
168         dir_list = self.searchDirList()
169         if self.pathSearch():
170             dir_list += [element for element in bertos_utils.getSystemPath()]
171         toolchain_list = bertos_utils.findToolchains(dir_list)
172         stored_toolchains = self.toolchains()
173         for element in toolchain_list:
174             if not element in stored_toolchains:
175                 item = QListWidgetItem(element)
176                 item.setData(Qt.UserRole, qvariant_converter.convertStringDict({"path": element}))
177                 self.pageContent.toolchainList.addItem(item)
178                 stored_toolchains[element] = False
179         self.setToolchains(stored_toolchains)
180         self.showMessage(self.tr("Toolchain search result."), self.tr("%1 toolchains founded").arg(len(stored_toolchains)))
181
182     def _validItem(self, index, infos):
183         """
184         Sets the item at index as a valid item and associates the given info to it.
185         """
186         item = self.pageContent.toolchainList.item(index)
187         new_data = qvariant_converter.getStringDict(self.pageContent.toolchainList.item(index).data(Qt.UserRole))
188         new_data.update(infos)
189         item.setData(Qt.UserRole, qvariant_converter.convertStringDict(new_data))
190         needed = self.projectInfo("CPU_INFOS")
191         if "target" in infos and infos["target"].find(needed["TOOLCHAIN"]) != -1:
192             item.setIcon(QIcon(":/images/ok.png"))
193             self._valid_items.append(item)
194         else:
195             item.setIcon(QIcon(":/images/warning.png"))
196         if "version" in infos and "target" in infos:
197             item.setText("GCC " + infos["version"] + " - " + infos["target"].strip())
198
199     def _invalidItem(self, index):
200         """
201         Sets the item at index as an invalid item.
202         """
203         item = self.pageContent.toolchainList.item(index)
204         item.setIcon(QIcon(":/images/error.png"))
205
206     def validateToolchain(self, i):
207         """
208         Toolchain validation procedure.
209         """
210         filename = qvariant_converter.getStringDict(self.pageContent.toolchainList.item(i).data(Qt.UserRole))["path"]
211         valid = False
212         info = {}
213         # Check for the other tools of the toolchain
214         for tool in TOOLCHAIN_ITEMS:
215             if os.path.exists(filename.replace("gcc", tool)):
216                 valid = True
217             else:
218                 valid = False
219                 break
220         # Try to retrieve the informations about the toolchain only for the valid toolchains
221         if valid:
222             self._validation_process = QProcess()
223             self._validation_process.start(filename, ["-v"])
224             self._validation_process.waitForStarted(1000)
225             if self._validation_process.waitForFinished(200):
226                 description = str(self._validation_process.readAllStandardError())
227                 info = bertos_utils.getToolchainInfo(description)
228                 if len(info) >= 4:
229                     valid = True
230             else:
231                 self._validation_process.kill()
232         # Add the item in the list with the appropriate associate data.
233         if valid:
234             self._validItem(i, info)
235         else:
236             self._invalidItem(i)
237         toolchains = self.toolchains()
238         toolchains[filename] = True
239         self.setToolchains(toolchains)