Correct a bug under Windows
[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         sel_toolchain = self.projectInfo("TOOLCHAIN")
140         for key, value in toolchains.items():
141             item = QListWidgetItem(key)
142             item.setData(Qt.UserRole, qvariant_converter.convertStringDict({"path": key}))
143             self.pageContent.toolchainList.addItem(item)
144             if sel_toolchain is not None and sel_toolchain["path"] == key:
145                 self.pageContent.toolchainList.setCurrentItem(item)
146             if value:
147                 self.validateToolchain(self.pageContent.toolchainList.row(item))
148
149     def _clearList(self):
150         """
151         Removes all the toolchain from the list.
152         """
153         self.pageContent.toolchainList.clear()
154
155     def _search(self):
156         """
157         Searches for toolchains in the stored directories, and stores them in the
158         QSettings.
159         """
160         dir_list = self.searchDirList()
161         if self.pathSearch():
162             dir_list += [element for element in bertos_utils.getSystemPath()]
163         toolchain_list = bertos_utils.findToolchains(dir_list)
164         stored_toolchains = self.toolchains()
165         for element in toolchain_list:
166             if not element in stored_toolchains.keys():
167                 item = QListWidgetItem(element)
168                 item.setData(Qt.UserRole, qvariant_converter.convertStringDict({"path": element}))
169                 self.pageContent.toolchainList.addItem(item)
170                 stored_toolchains[element] = False
171         self.setToolchains(stored_toolchains)
172
173     def _validItem(self, index, infos):
174         """
175         Sets the item at index as a valid item and associates the given info to it.
176         """
177         item = self.pageContent.toolchainList.item(index)
178         new_data = qvariant_converter.getStringDict(self.pageContent.toolchainList.item(index).data(Qt.UserRole))
179         new_data.update(infos)
180         item.setData(Qt.UserRole, qvariant_converter.convertStringDict(new_data))
181         needed = self.projectInfo("CPU_INFOS")
182         if "target" in infos.keys() and infos["target"].find(needed["TOOLCHAIN"]) != -1:
183             item.setIcon(QIcon(":/images/ok.png"))
184         else:
185             item.setIcon(QIcon(":/images/warning.png"))
186         if "version" in infos.keys() and "target" in infos.keys():
187             item.setText("GCC " + infos["version"] + " - " + infos["target"])
188
189     def _invalidItem(self, index):
190         """
191         Sets the item at index as an invalid item.
192         """
193         item = self.pageContent.toolchainList.item(index)
194         item.setIcon(QIcon(":/images/error.png"))
195
196     def validateToolchain(self, i):
197         """
198         Toolchain validation procedure.
199         """
200         filename = qvariant_converter.getStringDict(self.pageContent.toolchainList.item(i).data(Qt.UserRole))["path"]
201         valid = False
202         info = {}
203         # Check for the other tools of the toolchain
204         for tool in TOOLCHAIN_ITEMS:
205             if os.path.exists(filename.replace("gcc", tool)):
206                 valid = True
207             else:
208                 valid = False
209                 break
210         # Try to retrieve the informations about the toolchain only for the valid toolchains
211         if valid:
212             self._validation_process = QProcess()
213             self._validation_process.start(filename, ["-v"])
214             self._validation_process.waitForStarted(1000)
215             if self._validation_process.waitForFinished(200):
216                 description = str(self._validation_process.readAllStandardError())
217                 info = bertos_utils.getToolchainInfo(description)
218                 if len(info.keys()) >= 4:
219                     valid = True
220             else:
221                 self._validation_process.kill()
222         # Add the item in the list with the appropriate associate data.
223         if valid:
224             self._validItem(i, info)
225         else:
226             self._invalidItem(i)
227         toolchains = self.toolchains()
228         toolchains[filename] = True
229         self.setToolchains(toolchains)