|
1 # -*- coding: utf-8 -*- |
|
2 |
|
3 # Copyright (c) 2004 - 2019 Detlev Offenbach <detlev@die-offenbachs.de> |
|
4 # |
|
5 |
|
6 """ |
|
7 Module implementing a dialog to search for files. |
|
8 """ |
|
9 |
|
10 from __future__ import unicode_literals |
|
11 |
|
12 import os |
|
13 import sys |
|
14 |
|
15 from PyQt5.QtCore import pyqtSignal, pyqtSlot |
|
16 from PyQt5.QtWidgets import QWidget, QHeaderView, QApplication, \ |
|
17 QDialogButtonBox, QTreeWidgetItem |
|
18 |
|
19 from E5Gui.E5PathPicker import E5PathPickerModes |
|
20 |
|
21 from .Ui_FindFileNameDialog import Ui_FindFileNameDialog |
|
22 |
|
23 from Utilities import direntries |
|
24 import Utilities |
|
25 |
|
26 |
|
27 class FindFileNameDialog(QWidget, Ui_FindFileNameDialog): |
|
28 """ |
|
29 Class implementing a dialog to search for files. |
|
30 |
|
31 The occurrences found are displayed in a QTreeWidget showing the |
|
32 filename and the pathname. The file will be opened upon a double click |
|
33 onto the respective entry of the list. |
|
34 |
|
35 @signal sourceFile(str) emitted to open a file in the editor |
|
36 @signal designerFile(str) emitted to open a Qt-Designer file |
|
37 """ |
|
38 sourceFile = pyqtSignal(str) |
|
39 designerFile = pyqtSignal(str) |
|
40 |
|
41 def __init__(self, project, parent=None): |
|
42 """ |
|
43 Constructor |
|
44 |
|
45 @param project reference to the project object |
|
46 @param parent parent widget of this dialog (QWidget) |
|
47 """ |
|
48 super(FindFileNameDialog, self).__init__(parent) |
|
49 self.setupUi(self) |
|
50 |
|
51 self.searchDirPicker.setMode(E5PathPickerModes.DirectoryMode) |
|
52 |
|
53 self.fileList.headerItem().setText(self.fileList.columnCount(), "") |
|
54 |
|
55 self.stopButton = self.buttonBox.addButton( |
|
56 self.tr("Stop"), QDialogButtonBox.ActionRole) |
|
57 self.stopButton.setToolTip(self.tr("Press to stop the search")) |
|
58 self.stopButton.setEnabled(False) |
|
59 self.buttonBox.button(QDialogButtonBox.Open).setToolTip( |
|
60 self.tr("Opens the selected file")) |
|
61 self.buttonBox.button(QDialogButtonBox.Open).setEnabled(False) |
|
62 |
|
63 self.project = project |
|
64 self.extsepLabel.setText(os.extsep) |
|
65 |
|
66 self.shouldStop = False |
|
67 |
|
68 def on_buttonBox_clicked(self, button): |
|
69 """ |
|
70 Private slot called by a button of the button box clicked. |
|
71 |
|
72 @param button button that was clicked (QAbstractButton) |
|
73 """ |
|
74 if button == self.stopButton: |
|
75 self.shouldStop = True |
|
76 elif button == self.buttonBox.button(QDialogButtonBox.Open): |
|
77 self.__openFile() |
|
78 |
|
79 def __openFile(self, itm=None): |
|
80 """ |
|
81 Private slot to open a file. |
|
82 |
|
83 It emits the signal sourceFile or designerFile depending on the |
|
84 file extension. |
|
85 |
|
86 @param itm item to be opened (QTreeWidgetItem) |
|
87 """ |
|
88 if itm is None: |
|
89 itm = self.fileList.currentItem() |
|
90 if itm is not None: |
|
91 fileName = itm.text(0) |
|
92 filePath = itm.text(1) |
|
93 |
|
94 if fileName.endswith('.ui'): |
|
95 self.designerFile.emit(os.path.join(filePath, fileName)) |
|
96 else: |
|
97 self.sourceFile.emit(os.path.join(filePath, fileName)) |
|
98 |
|
99 def __searchFile(self): |
|
100 """ |
|
101 Private slot to handle the search. |
|
102 """ |
|
103 fileName = self.fileNameEdit.text() |
|
104 if not fileName: |
|
105 self.fileList.clear() |
|
106 return |
|
107 fileExt = self.fileExtEdit.text() |
|
108 if not fileExt and Utilities.isWindowsPlatform(): |
|
109 self.fileList.clear() |
|
110 return |
|
111 |
|
112 patternFormat = fileExt and "{0}{1}{2}" or "{0}*{1}{2}" |
|
113 fileNamePattern = patternFormat.format( |
|
114 fileName, os.extsep, fileExt and fileExt or '*') |
|
115 |
|
116 searchPaths = [] |
|
117 if self.searchDirCheckBox.isChecked() and \ |
|
118 self.searchDirPicker.text() != "": |
|
119 searchPaths.append(self.searchDirPicker.text()) |
|
120 if self.projectCheckBox.isChecked(): |
|
121 searchPaths.append(self.project.ppath) |
|
122 if self.syspathCheckBox.isChecked(): |
|
123 searchPaths.extend(sys.path) |
|
124 |
|
125 found = False |
|
126 self.fileList.clear() |
|
127 locations = {} |
|
128 self.shouldStop = False |
|
129 self.stopButton.setEnabled(True) |
|
130 QApplication.processEvents() |
|
131 |
|
132 for path in searchPaths: |
|
133 if os.path.isdir(path): |
|
134 files = direntries(path, True, fileNamePattern, |
|
135 False, self.checkStop) |
|
136 if files: |
|
137 found = True |
|
138 for file in files: |
|
139 fp, fn = os.path.split(file) |
|
140 if fn in locations: |
|
141 if fp in locations[fn]: |
|
142 continue |
|
143 else: |
|
144 locations[fn].append(fp) |
|
145 else: |
|
146 locations[fn] = [fp] |
|
147 QTreeWidgetItem(self.fileList, [fn, fp]) |
|
148 QApplication.processEvents() |
|
149 |
|
150 del locations |
|
151 self.stopButton.setEnabled(False) |
|
152 self.fileList.header().resizeSections(QHeaderView.ResizeToContents) |
|
153 self.fileList.header().setStretchLastSection(True) |
|
154 |
|
155 if found: |
|
156 self.fileList.setCurrentItem(self.fileList.topLevelItem(0)) |
|
157 |
|
158 def checkStop(self): |
|
159 """ |
|
160 Public method to check, if the search should be stopped. |
|
161 |
|
162 @return flag indicating the search should be stopped (boolean) |
|
163 """ |
|
164 QApplication.processEvents() |
|
165 return self.shouldStop |
|
166 |
|
167 def on_fileNameEdit_textChanged(self, text): |
|
168 """ |
|
169 Private slot to handle the textChanged signal of the file name edit. |
|
170 |
|
171 @param text (ignored) |
|
172 """ |
|
173 self.__searchFile() |
|
174 |
|
175 def on_fileExtEdit_textChanged(self, text): |
|
176 """ |
|
177 Private slot to handle the textChanged signal of the file extension |
|
178 edit. |
|
179 |
|
180 @param text (ignored) |
|
181 """ |
|
182 self.__searchFile() |
|
183 |
|
184 def on_searchDirPicker_textChanged(self, text): |
|
185 """ |
|
186 Private slot to handle the textChanged signal of the search directory |
|
187 edit. |
|
188 |
|
189 @param text text of the search dir edit (string) |
|
190 """ |
|
191 self.searchDirCheckBox.setEnabled(text != "") |
|
192 if self.searchDirCheckBox.isChecked(): |
|
193 self.__searchFile() |
|
194 |
|
195 def on_searchDirCheckBox_toggled(self, checked): |
|
196 """ |
|
197 Private slot to handle the toggled signal of the search directory |
|
198 checkbox. |
|
199 |
|
200 @param checked flag indicating the state of the checkbox (boolean) |
|
201 """ |
|
202 if self.searchDirPicker.text(): |
|
203 self.__searchFile() |
|
204 |
|
205 def on_projectCheckBox_toggled(self, checked): |
|
206 """ |
|
207 Private slot to handle the toggled signal of the project checkbox. |
|
208 |
|
209 @param checked flag indicating the state of the checkbox (boolean) |
|
210 """ |
|
211 self.__searchFile() |
|
212 |
|
213 def on_syspathCheckBox_toggled(self, checked): |
|
214 """ |
|
215 Private slot to handle the toggled signal of the sys.path checkbox. |
|
216 |
|
217 @param checked flag indicating the state of the checkbox (boolean) |
|
218 """ |
|
219 self.__searchFile() |
|
220 |
|
221 def on_fileList_itemActivated(self, itm, column): |
|
222 """ |
|
223 Private slot to handle the double click on a file item. |
|
224 |
|
225 It emits the signal sourceFile or designerFile depending on the |
|
226 file extension. |
|
227 |
|
228 @param itm the double clicked listview item (QTreeWidgetItem) |
|
229 @param column column that was double clicked (integer) (ignored) |
|
230 """ |
|
231 self.__openFile(itm) |
|
232 |
|
233 @pyqtSlot(QTreeWidgetItem, QTreeWidgetItem) |
|
234 def on_fileList_currentItemChanged(self, current, previous): |
|
235 """ |
|
236 Private slot handling a change of the current item. |
|
237 |
|
238 @param current current item (QTreeWidgetItem) |
|
239 @param previous prevoius current item (QTreeWidgetItem) |
|
240 """ |
|
241 self.buttonBox.button(QDialogButtonBox.Open).setEnabled( |
|
242 current is not None) |
|
243 |
|
244 def show(self): |
|
245 """ |
|
246 Public method to enable/disable the project checkbox. |
|
247 """ |
|
248 if self.project and self.project.isOpen(): |
|
249 self.projectCheckBox.setEnabled(True) |
|
250 self.projectCheckBox.setChecked(True) |
|
251 else: |
|
252 self.projectCheckBox.setEnabled(False) |
|
253 self.projectCheckBox.setChecked(False) |
|
254 |
|
255 self.fileNameEdit.selectAll() |
|
256 self.fileNameEdit.setFocus() |
|
257 |
|
258 super(FindFileNameDialog, self).show() |