1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33 import os
34 from PySide import QtGui
35 from PySide import QtCore
36 from PySide import QtUiTools
37
38 import roslib
39 import rospy
40 from xml_highlighter import XmlHighlighter
41
43 '''
44 The XML editor to handle the included files. If an included file in the opened
45 launch file is detected, this can be open by STRG+(mouse click) in a new
46 editor.
47 '''
48
49 load_request_signal = QtCore.Signal(str)
50 ''' @ivar: A signal for request to open a configuration file'''
51
52 - def __init__(self, filename, parent=None):
53 self.parent = parent
54 QtGui.QTextEdit.__init__(self, parent)
55 self.setObjectName(' - '.join(['Editor', filename]))
56 font = QtGui.QFont()
57 font.setFamily("Fixed".decode("utf-8"))
58 font.setPointSize(12)
59 self.setFont(font)
60 self.setLineWrapMode(QtGui.QTextEdit.NoWrap)
61 self.setTabStopWidth(25)
62 self.setAcceptRichText(False)
63 self.setCursorWidth(2)
64 self.setFontFamily("courier new")
65 self.setProperty("backgroundVisible", True)
66 self.regexp_list = [QtCore.QRegExp("\\binclude\\b"), QtCore.QRegExp("\\btextfile\\b"),
67 QtCore.QRegExp("\\bfile\\b")]
68 self.filename = filename
69 file = QtCore.QFile(filename);
70 if file.open(QtCore.QIODevice.ReadOnly | QtCore.QIODevice.Text):
71 self.setText(unicode(file.readAll(), "utf-8"))
72
73 self.path = '.'
74
75
76
77
79 '''
80 Saves changes to the file.
81 '''
82 if self.document().isModified():
83 file = QtCore.QFile(self.filename)
84 if file.open(QtCore.QIODevice.WriteOnly | QtCore.QIODevice.Text):
85 file.write(self.toPlainText().encode('utf-8'))
86 self.document().setModified(False)
87 return True
88 else:
89 QtGui.QMessageBox.critical(self, "Error", "Cannot write XML file")
90 return False
91 return False
92
94 '''
95 Sets the current working path. This path is to open the included files, which
96 contains the relative path.
97 @param path: the path of the current opened file (without the file)
98 @type path: C{str}
99 '''
100 self.path = path
101
103 '''
104 Tries to determine the path of the included file. The statement of
105 C{$(find 'package')} will be resolved.
106 @param path: the sting which contains the included path
107 @type path: C{str}
108 @return: if no leading C{os.sep} is detected, the path setted by L{setCurrentPath()}
109 will be prepend. C{$(find 'package')} will be resolved. Otherwise the parameter
110 itself will be returned
111 @rtype: C{str}
112 '''
113 path = path.strip()
114 index = path.find('$')
115 if index > -1:
116 startIndex = path.find('(', index)
117 if startIndex > -1:
118 endIndex = path.find(')', startIndex+1)
119 script = path[startIndex+1:endIndex].split()
120 if len(script) == 2 and (script[0] == 'find'):
121 pkg = roslib.packages.get_pkg_dir(script[1])
122 return os.path.normpath(''.join([pkg, '/', path[endIndex+1:]]))
123 elif len(path) > 0 and path[0] != '/':
124 return os.path.normpath(''.join([self.path, '/', path]))
125 return os.path.normpath(path)
126
128 '''
129 Searches in the given text for key indicates the including of a file and
130 return their index.
131 @param text: text to find
132 @type text: C{str}
133 @return: the index of the including key or -1
134 @rtype: C{int}
135 '''
136 for pattern in self.regexp_list:
137 index = pattern.indexIn(text)
138 if index > -1:
139 return index
140 return -1
141
143 '''
144 Returns all included files in the document.
145 '''
146 result = []
147 b = self.document().begin()
148 while b != self.document().end():
149 text = b.text()
150 index = self.index(text)
151 if index > -1:
152 startIndex = text.find('"', index)
153 if startIndex > -1:
154 endIndex = text.find('"', startIndex+1)
155 fileName = text[startIndex+1:endIndex]
156 if len(fileName) > 0:
157 path = self.interpretPath(fileName)
158 file = QtCore.QFile(path)
159 if file.exists():
160 result.append(path)
161 b = b.next()
162 return result
163
164 - def fileWithText(self, search_text):
165 '''
166 Searches for given text in this document and all included files.
167 @param search_text: text to find
168 @type search_text: C{str}
169 @return: the list with all files contain the text
170 @rtype: C{[str, ...]}
171 '''
172 result = []
173 start_pos = QtGui.QTextCursor()
174 search_result = self.document().find(search_text, start_pos.position()+1)
175 if not search_result.isNull():
176 result.append(self.filename)
177 inc_files = self.includedFiles()
178 for f in inc_files:
179 editor = Editor(f, None)
180 result[len(result):] = editor.fileWithText(search_text)
181 return result
182
184 '''
185 Opens the new editor, if the user clicked on the included file and sets the
186 default cursor.
187 '''
188 if event.modifiers() == QtCore.Qt.ControlModifier or event.modifiers() == QtCore.Qt.ShiftModifier:
189 cursor = self.cursorForPosition(event.pos())
190 index = self.index(cursor.block().text())
191 if index > -1:
192 startIndex = cursor.block().text().find('"', index)
193 if startIndex > -1:
194 endIndex = cursor.block().text().find('"', startIndex+1)
195 fileName = cursor.block().text()[startIndex+1:endIndex]
196 if len(fileName) > 0:
197 file = QtCore.QFile(self.interpretPath(fileName))
198 if not file.exists():
199
200 result = QtGui.QMessageBox.question(self, "File not found", '\n\n'.join(["Create a new file?", file.fileName()]), QtGui.QMessageBox.Yes | QtGui.QMessageBox.No)
201 if result == QtGui.QMessageBox.Yes:
202 dir = os.path.dirname(file.fileName())
203 if not os.path.exists(dir):
204 os.makedirs(dir)
205 with open(file.fileName(),'w') as f:
206 if file.fileName().endswith('.launch'):
207 f.write('<launch>\n\n</launch>')
208 self.load_request_signal.emit(file.fileName())
209 else:
210 self.load_request_signal.emit(file.fileName())
211 QtGui.QTextEdit.mouseReleaseEvent(self, event)
212
214 '''
215 Sets the X{QtCore.Qt.PointingHandCursor} if the control key is pressed and
216 the mouse is over the included file.
217 '''
218 if event.modifiers() == QtCore.Qt.ControlModifier or event.modifiers() == QtCore.Qt.ShiftModifier:
219 cursor = self.cursorForPosition(event.pos())
220 index = self.index(cursor.block().text())
221 if index > -1:
222 self.viewport().setCursor(QtCore.Qt.PointingHandCursor)
223 else:
224 self.viewport().setCursor(QtCore.Qt.IBeamCursor)
225 else:
226 self.viewport().setCursor(QtCore.Qt.IBeamCursor)
227 QtGui.QTextEdit.mouseMoveEvent(self, event)
228
230 '''
231 Enable the mouse tracking by X{setMouseTracking()} if the control key is pressed.
232 '''
233 if event.key() == QtCore.Qt.Key_Control or event.key() == QtCore.Qt.Key_Shift:
234 self.setMouseTracking(True)
235 if event.key() != QtCore.Qt.Key_Escape:
236
237 if event.key() == QtCore.Qt.Key_Tab:
238 self.shiftText()
239 else:
240 QtGui.QTextEdit.keyPressEvent(self, event)
241 else:
242 event.accept()
243 QtGui.QTextEdit.keyPressEvent(self, event)
244
246 '''
247 Disable the mouse tracking by X{setMouseTracking()} if the control key is
248 released and set the cursor back to X{QtCore.Qt.IBeamCursor}.
249 '''
250 if event.key() == QtCore.Qt.Key_Control or event.key() == QtCore.Qt.Key_Shift:
251 self.setMouseTracking(False)
252 self.viewport().setCursor(QtCore.Qt.IBeamCursor)
253 QtGui.QTextEdit.keyReleaseEvent(self, event)
254
255 - def shiftText(self):
256 '''
257 Increase (Decrease) indentation using Tab (Ctrl+Tab).
258 '''
259 cursor = self.textCursor()
260 if not cursor.isNull():
261 key_mod = QtGui.QApplication.keyboardModifiers()
262
263 cursor.beginEditBlock()
264 start = cursor.selectionStart()
265 end = cursor.selectionEnd()
266 cursor.setPosition(start)
267 block_start = cursor.blockNumber()
268 cursor.setPosition(end)
269 block_end = cursor.blockNumber()
270 if block_end-block_start == 0:
271
272 if key_mod & QtCore.Qt.ControlModifier:
273 for s in range(2):
274 cursor.movePosition(QtGui.QTextCursor.StartOfLine)
275 cursor.movePosition(QtGui.QTextCursor.NextCharacter, QtGui.QTextCursor.KeepAnchor, 1)
276 if cursor.selectedText() == ' ':
277 cursor.insertText('')
278 elif cursor.selectedText() == "\t":
279 cursor.insertText('')
280 break
281 cursor.movePosition(QtGui.QTextCursor.StartOfLine)
282 else:
283
284 cursor.movePosition(QtGui.QTextCursor.NextCharacter, QtGui.QTextCursor.KeepAnchor, end-start)
285 cursor.insertText(' ')
286 else:
287
288 if key_mod & QtCore.Qt.ControlModifier:
289 removed = 0
290 for i in reversed(range(start, end)):
291 cursor.setPosition(i)
292 if cursor.atBlockStart():
293 cursor.movePosition(QtGui.QTextCursor.NextCharacter, QtGui.QTextCursor.KeepAnchor, 2)
294 if cursor.selectedText() == ' ':
295 cursor.insertText('')
296 removed += 2
297 else:
298 cursor.movePosition(QtGui.QTextCursor.StartOfLine)
299 cursor.movePosition(QtGui.QTextCursor.NextCharacter, QtGui.QTextCursor.KeepAnchor, 1)
300 if cursor.selectedText() == ' ':
301 cursor.insertText('')
302 removed += 1
303 elif cursor.selectedText() == "\t":
304 cursor.insertText('')
305 removed += 1
306 cursor.setPosition(start)
307 cursor.movePosition(QtGui.QTextCursor.NextCharacter, QtGui.QTextCursor.KeepAnchor, end-start-removed)
308 else:
309
310 inserted = 0
311 for i in reversed(range(start, end)):
312 cursor.setPosition(i)
313 if cursor.atBlockStart():
314 cursor.insertText(' ')
315 inserted += 2
316 cursor.setPosition(start)
317 cursor.movePosition(QtGui.QTextCursor.NextCharacter, QtGui.QTextCursor.KeepAnchor, end-start+inserted)
318 self.setTextCursor(cursor)
319 cursor.endEditBlock()
320
321
323 '''
324 A dialog to find text in the Editor.
325 '''
326
328 QtGui.QDialog.__init__(self, parent)
329 self.setObjectName('FindDialog')
330 self.setWindowTitle('Search')
331 self.verticalLayout = QtGui.QVBoxLayout(self)
332 self.verticalLayout.setObjectName("verticalLayout")
333
334 self.content = QtGui.QWidget(self)
335 self.contentLayout = QtGui.QFormLayout(self.content)
336
337
338 self.contentLayout.setContentsMargins(0, 0, 0, 0)
339 self.verticalLayout.addWidget(self.content)
340
341 label = QtGui.QLabel("Find:", self.content)
342 self.search_field = QtGui.QLineEdit(self.content)
343 self.contentLayout.addRow(label, self.search_field)
344 replace_label = QtGui.QLabel("Replace:", self.content)
345 self.replace_field = QtGui.QLineEdit(self.content)
346 self.contentLayout.addRow(replace_label, self.replace_field)
347 self.recursive = QtGui.QCheckBox("recursive search")
348 self.contentLayout.addRow(self.recursive)
349 self.result_label = QtGui.QLabel("")
350 self.verticalLayout.addWidget(self.result_label)
351 self.found_files = QtGui.QListWidget()
352 self.found_files.setVisible(False)
353 self.found_files.setSizePolicy(QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Expanding)
354 self.verticalLayout.addWidget(self.found_files)
355
356 self.buttonBox = QtGui.QDialogButtonBox(self)
357 self.find_button = QtGui.QPushButton(self.tr("&Find"))
358 self.find_button.setDefault(True)
359 self.buttonBox.addButton(self.find_button, QtGui.QDialogButtonBox.ActionRole)
360 self.replace_button = QtGui.QPushButton(self.tr("&Replace/Find"))
361 self.buttonBox.addButton(self.replace_button, QtGui.QDialogButtonBox.ActionRole)
362 self.buttonBox.addButton(QtGui.QDialogButtonBox.Close)
363 self.buttonBox.setOrientation(QtCore.Qt.Horizontal)
364 self.buttonBox.setObjectName("buttonBox")
365 self.verticalLayout.addWidget(self.buttonBox)
366
367
368 QtCore.QObject.connect(self.buttonBox, QtCore.SIGNAL("rejected()"), self.reject)
369 QtCore.QMetaObject.connectSlotsByName(self)
370
371 self.search_text = ''
372 self.search_pos = QtGui.QTextCursor()
373
374
375
376
377
379 '''
380 Creates a dialog to edit a launch file.
381 '''
382
383 finished_signal = QtCore.Signal(list)
384 '''
385 finished_signal has as parameter the filenames of the initialization and is emitted, if this
386 dialog was closed.
387 '''
388
389 - def __init__(self, filenames, search_text='', parent=None):
390 '''
391 @param filenames: a list with filenames. The last one will be activated.
392 @type filenames: C{[str, ...]}
393 @param search_text: if not empty, searches in new document for first occurrence of the given text
394 @type search_text: C{str} (Default: C{Empty String})
395 '''
396 QtGui.QDialog.__init__(self, parent)
397 self.setObjectName(' - '.join(['xmlEditor', str(filenames)]))
398 self.setAttribute(QtCore.Qt.WA_DeleteOnClose, True)
399 self.setWindowFlags(QtCore.Qt.Window)
400 self.resize(800,640)
401 self.mIcon = QtGui.QIcon(":/icons/crystal_clear_edit_launch.png")
402 self.setWindowIcon(self.mIcon)
403 self.setWindowTitle("ROSLaunch Editor");
404
405 self.init_filenames = list(filenames)
406
407 self.files = []
408 '''@ivar: list with all open files '''
409
410
411 self.verticalLayout = QtGui.QVBoxLayout(self)
412 self.verticalLayout.setContentsMargins(0, 0, 0, 0)
413 self.verticalLayout.setObjectName("verticalLayout")
414 self.tabWidget = QtGui.QTabWidget(self)
415 self.tabWidget.setTabPosition(QtGui.QTabWidget.North)
416 self.tabWidget.setDocumentMode(True)
417 self.tabWidget.setTabsClosable(True)
418 self.tabWidget.setMovable(False)
419 self.tabWidget.setObjectName("tabWidget")
420 self.tabWidget.tabCloseRequested.connect(self.on_close_tab)
421 self.verticalLayout.addWidget(self.tabWidget)
422
423
424 self.buttons = QtGui.QWidget(self)
425 self.horizontalLayout = QtGui.QHBoxLayout(self.buttons)
426 self.horizontalLayout.setContentsMargins(4, 0, 4, 0)
427 self.horizontalLayout.setObjectName("horizontalLayout")
428
429 self.searchButton = QtGui.QPushButton(self)
430 self.searchButton.setObjectName("searchButton")
431 self.searchButton.clicked.connect(self.on_shortcut_find)
432 self.searchButton.setText(QtGui.QApplication.translate("XmlEditor", "Search", None, QtGui.QApplication.UnicodeUTF8))
433 self.searchButton.setShortcut(QtGui.QApplication.translate("XmlEditor", "Ctrl+F", None, QtGui.QApplication.UnicodeUTF8))
434 self.searchButton.setToolTip('Open a search dialog (Ctrl+F)')
435 self.horizontalLayout.addWidget(self.searchButton)
436
437 self.gotoButton = QtGui.QPushButton(self)
438 self.gotoButton.setObjectName("gotoButton")
439 self.gotoButton.clicked.connect(self.on_shortcut_goto)
440 self.gotoButton.setText(QtGui.QApplication.translate("XmlEditor", "Goto line", None, QtGui.QApplication.UnicodeUTF8))
441 self.gotoButton.setShortcut(QtGui.QApplication.translate("XmlEditor", "Ctrl+L", None, QtGui.QApplication.UnicodeUTF8))
442 self.gotoButton.setToolTip('Open a goto dialog (Ctrl+L)')
443 self.horizontalLayout.addWidget(self.gotoButton)
444
445 spacerItem = QtGui.QSpacerItem(515, 20, QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Minimum)
446 self.horizontalLayout.addItem(spacerItem)
447
448 self.pos_label = QtGui.QLabel()
449 self.horizontalLayout.addWidget(self.pos_label)
450
451 spacerItem = QtGui.QSpacerItem(515, 20, QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Minimum)
452 self.horizontalLayout.addItem(spacerItem)
453
454 self.saveButton = QtGui.QPushButton(self)
455 self.saveButton.setObjectName("saveButton")
456 self.saveButton.clicked.connect(self.on_saveButton_clicked)
457 self.saveButton.setText(QtGui.QApplication.translate("XmlEditor", "Save", None, QtGui.QApplication.UnicodeUTF8))
458 self.saveButton.setShortcut(QtGui.QApplication.translate("XmlEditor", "Ctrl+S", None, QtGui.QApplication.UnicodeUTF8))
459 self.saveButton.setToolTip('Save the changes to the file (Ctrl+S)')
460 self.horizontalLayout.addWidget(self.saveButton)
461 self.verticalLayout.addWidget(self.buttons)
462
463
464 self.find_dialog = FindDialog(self)
465 self.find_dialog.buttonBox.clicked.connect(self.on_find_dialog_clicked)
466 self.find_dialog.found_files.itemActivated.connect(self.find_dialog_itemActivated)
467
468
469
470
471
472 for f in filenames:
473 if f:
474 self.on_load_request(os.path.normpath(f), search_text)
475
476
477
478
479
480
482 '''
483 Loads a file in a new tab or focus the tab, if the file is already open.
484 @param filename: the path to file
485 @type filename: C{str}
486 @param search_text: if not empty, searches in new document for first occurrence of the given text
487 @type search_text: C{str} (Default: C{Empty String})
488 '''
489 if not filename:
490 return
491
492 self.tabWidget.setUpdatesEnabled(False)
493 try:
494 if not filename in self.files:
495 tab_name = self.__getTabName(filename)
496 editor = Editor(filename, self.tabWidget)
497 tab_index = self.tabWidget.addTab(editor, tab_name)
498 self.files.append(filename)
499 editor.setCurrentPath(os.path.basename(filename))
500 editor.load_request_signal.connect(self.on_load_request)
501
502 hl = XmlHighlighter(editor.document())
503 editor.textChanged.connect(self.on_editor_textChanged)
504 editor.cursorPositionChanged.connect(self.on_editor_positionChanged)
505 editor.setFocus(QtCore.Qt.OtherFocusReason)
506 self.tabWidget.setCurrentIndex(tab_index)
507 else:
508 for i in range(self.tabWidget.count()):
509 if self.tabWidget.widget(i).filename == filename:
510 self.tabWidget.setCurrentIndex(i)
511 break
512 except:
513 import traceback
514 rospy.logwarn("Error while open %s: %s", filename, traceback.format_exc())
515
516 self.tabWidget.setUpdatesEnabled(True)
517 if search_text:
518 if self.find(search_text, False):
519 if not self.find_dialog.search_pos.isNull():
520 self.tabWidget.currentWidget().moveCursor(QtGui.QTextCursor.StartOfLine)
521
523 '''
524 Signal handling to close single tabs.
525 @param tab_index: tab index to close
526 @type tab_index: C{int}
527 '''
528 try:
529 doremove = True
530 w = self.tabWidget.widget(tab_index)
531 if w.document().isModified():
532 name = self.__getTabName(w.filename)
533 result = QtGui.QMessageBox.question(self, "Unsaved Changes", '\n\n'.join(["Save the file before closing?", name]), QtGui.QMessageBox.Yes | QtGui.QMessageBox.No | QtGui.QMessageBox.Cancel)
534 if result == QtGui.QMessageBox.Yes:
535 self.tabWidget.currentWidget().save()
536 elif result == QtGui.QMessageBox.No:
537 pass
538 else:
539 doremove = False
540 if doremove:
541
542 if w.filename in self.files:
543 self.files.remove(w.filename)
544
545 self.tabWidget.removeTab(tab_index)
546
547 if not self.tabWidget.count():
548 self.close()
549 except:
550 import traceback
551 rospy.logwarn("Error while close tab %s: %s", str(tab_index), traceback.format_exc())
552
553
554
555
557 '''
558 Test the open files for changes and save this if needed.
559 '''
560 changed = []
561
562 for i in range(self.tabWidget.count()):
563 w = self.tabWidget.widget(i)
564 if w.document().isModified():
565 changed.append(self.__getTabName(w.filename))
566 if changed:
567
568 if self.isHidden():
569 buttons = QtGui.QMessageBox.Yes | QtGui.QMessageBox.No
570 else:
571 buttons = QtGui.QMessageBox.Yes | QtGui.QMessageBox.No | QtGui.QMessageBox.Cancel
572 result = QtGui.QMessageBox.question(self, "Unsaved Changes", '\n\n'.join(["Save the file before closing?", '\n'.join(changed)]), buttons)
573 if result == QtGui.QMessageBox.Yes:
574 for i in range(self.tabWidget.count()):
575 w = self.tabWidget.widget(i).save()
576 event.accept()
577 elif result == QtGui.QMessageBox.No:
578 event.accept()
579 else:
580 event.ignore()
581 else:
582 event.accept()
583 if event.isAccepted():
584 self.finished_signal.emit(self.init_filenames)
585
593
595 '''
596 If the content was changed, a '*' will be shown in the tab name.
597 '''
598 tab_name = self.__getTabName(self.tabWidget.currentWidget().filename)
599 if (self.tabWidget.currentWidget().document().isModified()):
600 tab_name = ''.join(['*', tab_name])
601 self.tabWidget.setTabText(self.tabWidget.currentIndex(), tab_name)
602
604 '''
605 Shows the number of the line and column in a label.
606 '''
607 cursor = self.tabWidget.currentWidget().textCursor()
608 self.pos_label.setText(''.join([str(cursor.blockNumber()+1), ':', str(cursor.columnNumber()+1)]))
609
611 '''
612 Opens a find dialog.
613 '''
614 self.find_dialog.show()
615 self.find_dialog.raise_()
616 self.find_dialog.activateWindow()
617
619 '''
620 Opens a C{goto} dialog.
621 '''
622 value, ok = QtGui.QInputDialog.getInt(self, "Goto",
623 self.tr("Line number:"), QtGui.QLineEdit.Normal,
624 minValue=1, step=1)
625 if ok:
626 if value > self.tabWidget.currentWidget().document().blockCount():
627 value = self.tabWidget.currentWidget().document().blockCount()
628 curpos = self.tabWidget.currentWidget().textCursor().blockNumber()+1
629 while curpos != value:
630 mov = QtGui.QTextCursor.NextBlock if curpos < value else QtGui.QTextCursor.PreviousBlock
631 self.tabWidget.currentWidget().moveCursor(mov)
632 curpos = self.tabWidget.currentWidget().textCursor().blockNumber()+1
633
635 base = os.path.basename(file).replace('.launch', '')
636 package = self.__getPackageName(os.path.dirname(file))
637 return ''.join([str(base), ' [', str(package),']'])
638
640 if not (dir is None) and dir and dir != '/' and os.path.isdir(dir):
641 package = os.path.basename(dir)
642 fileList = os.listdir(dir)
643 for file in fileList:
644 if file == 'manifest.xml':
645 return package
646 return self.__getPackageName(os.path.dirname(dir))
647 return None
648
649
651 '''
652 Method to handle the button actions of the C{find dialog}.
653 '''
654 if button == self.find_dialog.find_button:
655 self.find(self.find_dialog.search_field.text(), self.find_dialog.recursive.isChecked())
656 elif button == self.find_dialog.replace_button:
657 self.find_dialog.recursive.setChecked(False)
658 cursor = self.tabWidget.currentWidget().textCursor()
659 if self.find_dialog.search_field.text() and cursor.selectedText() == self.find_dialog.search_field.text():
660 cursor.insertText(self.find_dialog.replace_field.text())
661 currentLine = str(cursor.blockNumber()+1)
662 self.find_dialog.result_label.setText(''.join(["'", self.find_dialog.search_text, "'", ' replaced at line: ', currentLine, ' by ', "'", self.find_dialog.replace_field.text(),"'"]))
663 self.tabWidget.currentWidget().setTextCursor(cursor)
664 self.find(self.find_dialog.search_field.text(), self.find_dialog.recursive.isChecked())
665
666 - def find(self, search_text, recursive):
667 '''
668 Searches for text in the current text editor. If `recursive` is C{True},
669 the included files will be searched.
670 @param search_text: text to find
671 @type search_text: C{str}
672 @param recursive: search in included files if this is C{True}
673 @type recursive: C{bool}
674 '''
675 found = False
676 if self.find_dialog.search_text != search_text:
677 self.find_dialog.search_pos = QtGui.QTextCursor()
678 self.find_dialog.found_files.clear()
679 self.find_dialog.found_files.setVisible(False)
680 self.find_dialog.result_label.setText(''.join(["'", search_text, "'", ' not found!']))
681 self.find_dialog.search_text = search_text
682 if search_text:
683 if recursive:
684 files = self.tabWidget.currentWidget().fileWithText(search_text)
685 items = list(set(files))
686 self.find_dialog.result_label.setText(''.join(["'", search_text, "'", ' found in ', str(len(items)), ' files:']))
687 self.find_dialog.found_files.clear()
688 self.find_dialog.found_files.addItems(items)
689 self.find_dialog.found_files.setVisible(True)
690 self.find_dialog.resize(self.find_dialog.found_files.contentsSize())
691 found = True
692 else:
693 tmp_pos = self.find_dialog.search_pos
694 self.find_dialog.search_pos = self.tabWidget.currentWidget().document().find(search_text, self.find_dialog.search_pos.position()+1)
695 if self.find_dialog.search_pos.isNull() and not tmp_pos.isNull():
696 self.find_dialog.search_pos = self.tabWidget.currentWidget().document().find(search_text, self.find_dialog.search_pos.position()+1)
697
698 if not self.find_dialog.search_pos.isNull():
699 self.tabWidget.currentWidget().setTextCursor(self.find_dialog.search_pos)
700 currentTabName = self.tabWidget.tabText(self.tabWidget.currentIndex())
701 currentLine = str(self.tabWidget.currentWidget().textCursor().blockNumber()+1)
702 self.find_dialog.result_label.setText(''.join(["'", search_text, "'", ' found at line: ', currentLine, ' in ', "'", currentTabName,"'"]))
703 found = True
704 else:
705 self.find_dialog.result_label.setText(''.join(["'", search_text, "'", ' not found!']))
706 return found
707
709 '''
710 On recursive search all files contained the search text are listed. If one of
711 this file is activated, it will be open in a new tab and the cursor moved to
712 the C{search text} position.
713 @param item: The activated item of the C{QListWidget}
714 @type item: L{PySide.QtGui.QListWidgetItem}
715 '''
716 self.find_dialog.recursive.setChecked(False)
717 self.on_load_request(item.text(), self.find_dialog.search_text)
718 self.find(self.find_dialog.search_text, False)
719 currentTabName = self.tabWidget.tabText(self.tabWidget.currentIndex())
720 currentLine = str(self.tabWidget.currentWidget().textCursor().blockNumber()+1)
721 self.find_dialog.result_label.setText(''.join(["'", self.find_dialog.search_text, "'", ' found at line: ', currentLine, ' in ', "'", currentTabName,"'"]))
722