c012a200307032f3fb25aef78da8100ecf5e3d91
[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
33     ## Overloaded QWizardPage methods. ##
34
35     def isComplete(self):
36         """
37         Overload of the QWizard isComplete method.
38         """
39         if self.pageContent.toolchainList.currentRow() != -1:
40             self.setProjectInfo("TOOLCHAIN",
41                 qvariant_converter.getStringDict(self.pageContent.toolchainList.currentItem().data(Qt.UserRole)))
42             return True
43         else:
44             return False
45
46     ####
47
48     ## Overloaded BWizardPage methods. ##
49
50     def setupUi(self):
51         """
52         Sets up the user interface.
53         """
54         self.pageContent.infoLabel.setVisible(False)
55
56     def connectSignals(self):
57         """
58         Connects the signals with the related slots.
59         """
60         self.connect(self.pageContent.toolchainList, SIGNAL("itemSelectionChanged()"), self.selectionChanged)
61         self.connect(self.pageContent.addButton, SIGNAL("clicked()"), self.addToolchain)
62         self.connect(self.pageContent.removeButton, SIGNAL("clicked()"), self.removeToolchain)
63         self.connect(self.pageContent.searchButton, SIGNAL("clicked()"), self.searchToolchain)
64         self.connect(self.pageContent.checkButton, SIGNAL("clicked()"), self.validateAllToolchains)
65
66     def reloadData(self):
67         """
68         Overload of the BWizard reloadData method.
69         """
70         self._clearList()
71         self.setupUi()
72         self._populateToolchainList()
73
74     ####
75
76     ## Slots ##
77
78     def selectionChanged(self):
79         """
80         Slot called when the user click on an entry of the toolchain list.
81         """
82         if self.pageContent.toolchainList.currentRow() != -1:
83             infos = collections.defaultdict(lambda: unicode("not defined"))
84             infos.update(qvariant_converter.getStringDict(self.pageContent.toolchainList.currentItem().data(Qt.UserRole)))
85             self.pageContent.infoLabel.setText("GCC " + infos["version"] + " (" + infos["build"] + ")\nTarget: " + infos["target"] + "\nPath: " + os.path.normpath(infos["path"]))
86             self.pageContent.infoLabel.setVisible(True)
87             self.emit(SIGNAL("completeChanged()"))
88
89     def addToolchain(self):
90         """
91         Slot called when the user adds manually a toolchain.
92         """
93         sel_toolchain = unicode(QFileDialog.getOpenFileName(self, self.tr("Choose the toolchain"), ""))
94         if sel_toolchain != "":
95             item = QListWidgetItem(sel_toolchain)
96             item.setData(Qt.UserRole, qvariant_converter.convertStringDict({"path": sel_toolchain}))
97             self.pageContent.toolchainList.addItem(item)
98             toolchains = self.toolchains()
99             toolchains[sel_toolchain] = False
100             self.setToolchains(toolchains)
101
102     def removeToolchain(self):
103         """
104         Slot called when the user removes manually a toolchain.
105         """
106         if self.pageContent.toolchainList.currentRow() != -1:
107             item = self.pageContent.toolchainList.takeItem(self.pageContent.toolchainList.currentRow())
108             toolchain = qvariant_converter.getStringDict(item.data(Qt.UserRole))["path"]
109             toolchains = self.toolchains()
110             del toolchains[toolchain]
111             self.setToolchains(toolchains)
112
113     def searchToolchain(self):
114         """
115         Slot called when the user clicks on the 'search' button. It opens the
116         toolchain search dialog.
117         """
118         search = BToolchainSearch.BToolchainSearch()
119         self.connect(search, SIGNAL("accepted()"), self._search)
120         search.exec_()
121
122     def validateAllToolchains(self):
123         """
124         Slot called when the user clicks on the validate button. It starts the
125         toolchain validation procedure for all the toolchains.
126         """
127         QApplication.instance().setOverrideCursor(Qt.WaitCursor)
128         for i in range(self.pageContent.toolchainList.count()):
129             self.validateToolchain(i)
130         QApplication.instance().restoreOverrideCursor()
131
132     ####
133
134     def _populateToolchainList(self):
135         """
136         Fills the toolchain list with the toolchains stored in the QSettings.
137         """
138         toolchains = self.toolchains()
139         if os.name == "nt":
140             import winreg_importer
141             stored_toolchains = winreg_importer.getBertosToolchains()
142             for toolchain in stored_toolchains:
143                 toolchains[toolchain] = True
144         sel_toolchain = self.projectInfo("TOOLCHAIN")
145         for key, value in toolchains.items():
146             item = QListWidgetItem(key)
147             item.setData(Qt.UserRole, qvariant_converter.convertStringDict({"path": key}))
148             self.pageContent.toolchainList.addItem(item)
149             if sel_toolchain and sel_toolchain["path"] == key:
150                 self.pageContent.toolchainList.setCurrentItem(item)
151             if value:
152                 self.validateToolchain(self.pageContent.toolchainList.row(item))
153
154     def _clearList(self):
155         """
156         Removes all the toolchain from the list.
157         """
158         self.pageContent.toolchainList.clear()
159
160     def _search(self):
161         """
162         Searches for toolchains in the stored directories, and stores them in the
163         QSettings.
164         """
165         dir_list = self.searchDirList()
166         if self.pathSearch():
167             dir_list += [element for element in bertos_utils.getSystemPath()]
168         toolchain_list = bertos_utils.findToolchains(dir_list)
169         stored_toolchains = self.toolchains()
170         for element in toolchain_list:
171             if not element in stored_toolchains:
172                 item = QListWidgetItem(element)
173                 item.setData(Qt.UserRole, qvariant_converter.convertStringDict({"path": element}))
174                 self.pageContent.toolchainList.addItem(item)
175                 stored_toolchains[element] = False
176         self.setToolchains(stored_toolchains)
177         self.showMessage(self.tr("Toolchain search result."), self.tr("%1 toolchains founded").arg(len(stored_toolchains)))
178
179     def _validItem(self, index, infos):
180         """
181         Sets the item at index as a valid item and associates the given info to it.
182         """
183         item = self.pageContent.toolchainList.item(index)
184         new_data = qvariant_converter.getStringDict(self.pageContent.toolchainList.item(index).data(Qt.UserRole))
185         new_data.update(infos)
186         item.setData(Qt.UserRole, qvariant_converter.convertStringDict(new_data))
187         needed = self.projectInfo("CPU_INFOS")
188         if "target" in infos and infos["target"].find(needed["TOOLCHAIN"]) != -1:
189             item.setIcon(QIcon(":/images/ok.png"))
190         else:
191             item.setIcon(QIcon(":/images/warning.png"))
192         if "version" in infos and "target" in infos:
193             item.setText("GCC " + infos["version"] + " - " + infos["target"].strip())
194
195     def _invalidItem(self, index):
196         """
197         Sets the item at index as an invalid item.
198         """
199         item = self.pageContent.toolchainList.item(index)
200         item.setIcon(QIcon(":/images/error.png"))
201
202     def validateToolchain(self, i):
203         """
204         Toolchain validation procedure.
205         """
206         filename = qvariant_converter.getStringDict(self.pageContent.toolchainList.item(i).data(Qt.UserRole))["path"]
207         valid = False
208         info = {}
209         # Check for the other tools of the toolchain
210         for tool in TOOLCHAIN_ITEMS:
211             if os.path.exists(filename.replace("gcc", tool)):
212                 valid = True
213             else:
214                 valid = False
215                 break
216         # Try to retrieve the informations about the toolchain only for the valid toolchains
217         if valid:
218             self._validation_process = QProcess()
219             self._validation_process.start(filename, ["-v"])
220             self._validation_process.waitForStarted(1000)
221             if self._validation_process.waitForFinished(200):
222                 description = str(self._validation_process.readAllStandardError())
223                 info = bertos_utils.getToolchainInfo(description)
224                 if len(info) >= 4:
225                     valid = True
226             else:
227                 self._validation_process.kill()
228         # Add the item in the list with the appropriate associate data.
229         if valid:
230             self._validItem(i, info)
231         else:
232             self._invalidItem(i)
233         toolchains = self.toolchains()
234         toolchains[filename] = True
235         self.setToolchains(toolchains)