eric6/Plugins/ViewManagerPlugins/Tabview/Tabview.py

changeset 6942
2602857055c5
parent 6932
8a3df4c6ac9a
child 6989
8b8cadf8d7e9
child 6999
f23e546a7eb9
equal deleted inserted replaced
6941:f99d60d6b59b 6942:2602857055c5
1 # -*- coding: utf-8 -*-
2
3 # Copyright (c) 2002 - 2019 Detlev Offenbach <detlev@die-offenbachs.de>
4 #
5
6 """
7 Module implementing a tabbed viewmanager class.
8 """
9
10 from __future__ import unicode_literals
11
12 import os
13
14 from PyQt5.QtCore import pyqtSlot, QPoint, QFileInfo, pyqtSignal, QEvent, \
15 QByteArray, QMimeData, Qt, QSize
16 from PyQt5.QtGui import QColor, QDrag, QPixmap
17 from PyQt5.QtWidgets import QWidget, QHBoxLayout, QSplitter, QTabBar, \
18 QApplication, QToolButton, QMenu, QLabel
19
20 from E5Gui.E5Application import e5App
21
22 from ViewManager.ViewManager import ViewManager
23
24 import QScintilla.Editor
25 from QScintilla.Editor import Editor
26 from QScintilla.EditorAssembly import EditorAssembly
27
28 import UI.PixmapCache
29
30 from E5Gui.E5TabWidget import E5TabWidget, E5WheelTabBar
31 from E5Gui.E5Led import E5Led
32
33 import Preferences
34 from Globals import isMacPlatform
35
36 from eric6config import getConfig
37
38
39 class TabBar(E5WheelTabBar):
40 """
41 Class implementing a customized tab bar supporting drag & drop.
42
43 @signal tabMoveRequested(int, int) emitted to signal a tab move request
44 giving the old and new index position
45 @signal tabRelocateRequested(str, int, int) emitted to signal a tab
46 relocation request giving the string encoded id of the old tab widget,
47 the index in the old tab widget and the new index position
48 @signal tabCopyRequested(str, int, int) emitted to signal a clone request
49 giving the string encoded id of the source tab widget, the index in the
50 source tab widget and the new index position
51 @signal tabCopyRequested(int, int) emitted to signal a clone request giving
52 the old and new index position
53 """
54 tabMoveRequested = pyqtSignal(int, int)
55 tabRelocateRequested = pyqtSignal(str, int, int)
56 tabCopyRequested = pyqtSignal((str, int, int), (int, int))
57
58 def __init__(self, parent=None):
59 """
60 Constructor
61
62 @param parent reference to the parent widget
63 @type QWidget
64 """
65 super(TabBar, self).__init__(parent)
66 self.setAcceptDrops(True)
67
68 self.__dragStartPos = QPoint()
69
70 def mousePressEvent(self, event):
71 """
72 Protected method to handle mouse press events.
73
74 @param event reference to the mouse press event
75 @type QMouseEvent
76 """
77 if event.button() == Qt.LeftButton:
78 self.__dragStartPos = QPoint(event.pos())
79 super(TabBar, self).mousePressEvent(event)
80
81 def mouseMoveEvent(self, event):
82 """
83 Protected method to handle mouse move events.
84
85 @param event reference to the mouse move event
86 @type QMouseEvent
87 """
88 if event.buttons() == Qt.MouseButtons(Qt.LeftButton) and \
89 (event.pos() - self.__dragStartPos).manhattanLength() > \
90 QApplication.startDragDistance():
91 drag = QDrag(self)
92 mimeData = QMimeData()
93 index = self.tabAt(event.pos())
94 mimeData.setText(self.tabText(index))
95 mimeData.setData("action", b"tab-reordering")
96 mimeData.setData("tabbar-id", str(id(self)).encode("utf-8"))
97 mimeData.setData(
98 "source-index",
99 QByteArray.number(self.tabAt(self.__dragStartPos)))
100 mimeData.setData(
101 "tabwidget-id",
102 str(id(self.parentWidget())).encode("utf-8"))
103 drag.setMimeData(mimeData)
104 if event.modifiers() == Qt.KeyboardModifiers(Qt.ShiftModifier):
105 drag.exec_(Qt.DropActions(Qt.CopyAction))
106 elif event.modifiers() == Qt.KeyboardModifiers(Qt.NoModifier):
107 drag.exec_(Qt.DropActions(Qt.MoveAction))
108 super(TabBar, self).mouseMoveEvent(event)
109
110 def dragEnterEvent(self, event):
111 """
112 Protected method to handle drag enter events.
113
114 @param event reference to the drag enter event
115 @type QDragEnterEvent
116 """
117 mimeData = event.mimeData()
118 formats = mimeData.formats()
119 if "action" in formats and \
120 mimeData.data("action") == b"tab-reordering" and \
121 "tabbar-id" in formats and \
122 "source-index" in formats and \
123 "tabwidget-id" in formats:
124 event.acceptProposedAction()
125 super(TabBar, self).dragEnterEvent(event)
126
127 def dropEvent(self, event):
128 """
129 Protected method to handle drop events.
130
131 @param event reference to the drop event
132 @type QDropEvent
133 """
134 mimeData = event.mimeData()
135 oldID = int(mimeData.data("tabbar-id"))
136 fromIndex = int(mimeData.data("source-index"))
137 toIndex = self.tabAt(event.pos())
138 if oldID != id(self):
139 parentID = int(mimeData.data("tabwidget-id"))
140 if event.proposedAction() == Qt.MoveAction:
141 self.tabRelocateRequested.emit(
142 str(parentID), fromIndex, toIndex)
143 event.acceptProposedAction()
144 elif event.proposedAction() == Qt.CopyAction:
145 self.tabCopyRequested[str, int, int].emit(
146 str(parentID), fromIndex, toIndex)
147 event.acceptProposedAction()
148 else:
149 if fromIndex != toIndex:
150 if event.proposedAction() == Qt.MoveAction:
151 self.tabMoveRequested.emit(fromIndex, toIndex)
152 event.acceptProposedAction()
153 elif event.proposedAction() == Qt.CopyAction:
154 self.tabCopyRequested[int, int].emit(fromIndex, toIndex)
155 event.acceptProposedAction()
156 super(TabBar, self).dropEvent(event)
157
158
159 class TabWidget(E5TabWidget):
160 """
161 Class implementing a custimized tab widget.
162 """
163 def __init__(self, vm):
164 """
165 Constructor
166
167 @param vm view manager widget
168 @type Tabview
169 """
170 super(TabWidget, self).__init__()
171
172 self.__tabBar = TabBar(self)
173 self.setTabBar(self.__tabBar)
174 iconSize = self.__tabBar.iconSize()
175 self.__tabBar.setIconSize(
176 QSize(2 * iconSize.width(), iconSize.height()))
177
178 self.setUsesScrollButtons(True)
179 self.setElideMode(Qt.ElideNone)
180 if isMacPlatform():
181 self.setDocumentMode(True)
182
183 self.__tabBar.tabMoveRequested.connect(self.moveTab)
184 self.__tabBar.tabRelocateRequested.connect(self.__relocateTab)
185 self.__tabBar.tabCopyRequested[str, int, int].connect(
186 self.__copyTabOther)
187 self.__tabBar.tabCopyRequested[int, int].connect(self.__copyTab)
188
189 self.vm = vm
190 self.editors = []
191
192 self.indicator = E5Led(self)
193 self.setCornerWidget(self.indicator, Qt.TopLeftCorner)
194
195 self.rightCornerWidget = QWidget(self)
196 self.rightCornerWidgetLayout = QHBoxLayout(self.rightCornerWidget)
197 self.rightCornerWidgetLayout.setContentsMargins(0, 0, 0, 0)
198 self.rightCornerWidgetLayout.setSpacing(0)
199
200 self.__navigationMenu = QMenu(self)
201 self.__navigationMenu.aboutToShow.connect(self.__showNavigationMenu)
202 self.__navigationMenu.triggered.connect(self.__navigationMenuTriggered)
203
204 self.navigationButton = QToolButton(self)
205 self.navigationButton.setIcon(UI.PixmapCache.getIcon("1downarrow.png"))
206 self.navigationButton.setToolTip(self.tr("Show a navigation menu"))
207 self.navigationButton.setPopupMode(QToolButton.InstantPopup)
208 self.navigationButton.setMenu(self.__navigationMenu)
209 self.navigationButton.setEnabled(False)
210 self.rightCornerWidgetLayout.addWidget(self.navigationButton)
211
212 if Preferences.getUI("SingleCloseButton") or \
213 not hasattr(self, 'setTabsClosable'):
214 self.closeButton = QToolButton(self)
215 self.closeButton.setIcon(UI.PixmapCache.getIcon("close.png"))
216 self.closeButton.setToolTip(
217 self.tr("Close the current editor"))
218 self.closeButton.setEnabled(False)
219 self.closeButton.clicked[bool].connect(self.__closeButtonClicked)
220 self.rightCornerWidgetLayout.addWidget(self.closeButton)
221 else:
222 self.tabCloseRequested.connect(self.__closeRequested)
223 self.closeButton = None
224
225 self.setCornerWidget(self.rightCornerWidget, Qt.TopRightCorner)
226
227 self.__initMenu()
228 self.contextMenuEditor = None
229 self.contextMenuIndex = -1
230
231 self.setTabContextMenuPolicy(Qt.CustomContextMenu)
232 self.customTabContextMenuRequested.connect(self.__showContextMenu)
233
234 ericPic = QPixmap(
235 os.path.join(getConfig('ericPixDir'), 'eric_small.png'))
236 self.emptyLabel = QLabel()
237 self.emptyLabel.setPixmap(ericPic)
238 self.emptyLabel.setAlignment(Qt.AlignVCenter | Qt.AlignHCenter)
239 super(TabWidget, self).addTab(
240 self.emptyLabel,
241 UI.PixmapCache.getIcon("empty.png"), "")
242
243 def __initMenu(self):
244 """
245 Private method to initialize the tab context menu.
246 """
247 self.__menu = QMenu(self)
248 self.leftMenuAct = self.__menu.addAction(
249 UI.PixmapCache.getIcon("1leftarrow.png"),
250 self.tr('Move Left'), self.__contextMenuMoveLeft)
251 self.rightMenuAct = self.__menu.addAction(
252 UI.PixmapCache.getIcon("1rightarrow.png"),
253 self.tr('Move Right'), self.__contextMenuMoveRight)
254 self.firstMenuAct = self.__menu.addAction(
255 UI.PixmapCache.getIcon("2leftarrow.png"),
256 self.tr('Move First'), self.__contextMenuMoveFirst)
257 self.lastMenuAct = self.__menu.addAction(
258 UI.PixmapCache.getIcon("2rightarrow.png"),
259 self.tr('Move Last'), self.__contextMenuMoveLast)
260 self.__menu.addSeparator()
261 self.__menu.addAction(
262 UI.PixmapCache.getIcon("tabClose.png"),
263 self.tr('Close'), self.__contextMenuClose)
264 self.closeOthersMenuAct = self.__menu.addAction(
265 UI.PixmapCache.getIcon("tabCloseOther.png"),
266 self.tr("Close Others"), self.__contextMenuCloseOthers)
267 self.__menu.addAction(
268 self.tr('Close All'), self.__contextMenuCloseAll)
269 self.__menu.addSeparator()
270 self.saveMenuAct = self.__menu.addAction(
271 UI.PixmapCache.getIcon("fileSave.png"),
272 self.tr('Save'), self.__contextMenuSave)
273 self.__menu.addAction(
274 UI.PixmapCache.getIcon("fileSaveAs.png"),
275 self.tr('Save As...'), self.__contextMenuSaveAs)
276 self.__menu.addAction(
277 UI.PixmapCache.getIcon("fileSaveAll.png"),
278 self.tr('Save All'), self.__contextMenuSaveAll)
279 self.__menu.addSeparator()
280 self.openRejectionsMenuAct = self.__menu.addAction(
281 self.tr("Open 'rejection' file"),
282 self.__contextMenuOpenRejections)
283 self.__menu.addSeparator()
284 self.__menu.addAction(
285 UI.PixmapCache.getIcon("print.png"),
286 self.tr('Print'), self.__contextMenuPrintFile)
287 self.__menu.addSeparator()
288 self.copyPathAct = self.__menu.addAction(
289 self.tr("Copy Path to Clipboard"),
290 self.__contextMenuCopyPathToClipboard)
291
292 def __showContextMenu(self, coord, index):
293 """
294 Private slot to show the tab context menu.
295
296 @param coord the position of the mouse pointer
297 @type QPoint
298 @param index index of the tab the menu is requested for
299 @type int
300 """
301 if self.editors:
302 widget = self.widget(index)
303 if widget is not None:
304 self.contextMenuEditor = widget.getEditor()
305 if self.contextMenuEditor:
306 self.saveMenuAct.setEnabled(
307 self.contextMenuEditor.isModified())
308 fileName = self.contextMenuEditor.getFileName()
309 self.copyPathAct.setEnabled(bool(fileName))
310 if fileName:
311 rej = "{0}.rej".format(fileName)
312 self.openRejectionsMenuAct.setEnabled(
313 os.path.exists(rej))
314 else:
315 self.openRejectionsMenuAct.setEnabled(False)
316
317 self.contextMenuIndex = index
318 self.leftMenuAct.setEnabled(index > 0)
319 self.rightMenuAct.setEnabled(index < self.count() - 1)
320 self.firstMenuAct.setEnabled(index > 0)
321 self.lastMenuAct.setEnabled(index < self.count() - 1)
322
323 self.closeOthersMenuAct.setEnabled(self.count() > 1)
324
325 coord = self.mapToGlobal(coord)
326 self.__menu.popup(coord)
327
328 def __showNavigationMenu(self):
329 """
330 Private slot to show the navigation button menu.
331 """
332 self.__navigationMenu.clear()
333 for index in range(self.count()):
334 act = self.__navigationMenu.addAction(self.tabIcon(index),
335 self.tabText(index))
336 act.setData(index)
337
338 def __navigationMenuTriggered(self, act):
339 """
340 Private slot called to handle the navigation button menu selection.
341
342 @param act reference to the selected action
343 @type QAction
344 """
345 index = act.data()
346 if index is not None:
347 self.setCurrentIndex(index)
348
349 def showIndicator(self, on):
350 """
351 Public slot to set the indicator on or off.
352
353 @param on flag indicating the state of the indicator
354 @type bool
355 """
356 if on:
357 self.indicator.setColor(QColor("green"))
358 else:
359 self.indicator.setColor(QColor("red"))
360
361 def addTab(self, assembly, title):
362 """
363 Public method to add a new tab.
364
365 @param assembly editor assembly object to be added
366 @type QScintilla.EditorAssembly.EditorAssembly
367 @param title title for the new tab
368 @type str
369 """
370 editor = assembly.getEditor()
371 super(TabWidget, self).addTab(
372 assembly, UI.PixmapCache.getIcon("empty.png"), title)
373 if self.closeButton:
374 self.closeButton.setEnabled(True)
375 else:
376 self.setTabsClosable(True)
377 self.navigationButton.setEnabled(True)
378
379 if editor not in self.editors:
380 self.editors.append(editor)
381 editor.captionChanged.connect(self.__captionChange)
382 editor.cursorLineChanged.connect(
383 lambda lineno: self.__cursorLineChanged(lineno, editor))
384
385 emptyIndex = self.indexOf(self.emptyLabel)
386 if emptyIndex > -1:
387 self.removeTab(emptyIndex)
388
389 def insertWidget(self, index, assembly, title):
390 """
391 Public method to insert a new tab.
392
393 @param index index position for the new tab
394 @type int
395 @param assembly editor assembly object to be added
396 @type QScintilla.EditorAssembly.EditorAssembly
397 @param title title for the new tab
398 @type str
399 @return index of the inserted tab
400 @rtype int
401 """
402 editor = assembly.getEditor()
403 newIndex = super(TabWidget, self).insertTab(
404 index, assembly,
405 UI.PixmapCache.getIcon("empty.png"),
406 title)
407 if self.closeButton:
408 self.closeButton.setEnabled(True)
409 else:
410 self.setTabsClosable(True)
411 self.navigationButton.setEnabled(True)
412
413 if editor not in self.editors:
414 self.editors.append(editor)
415 editor.captionChanged.connect(self.__captionChange)
416 editor.cursorLineChanged.connect(
417 lambda lineno: self.__cursorLineChanged(lineno, editor))
418 emptyIndex = self.indexOf(self.emptyLabel)
419 if emptyIndex > -1:
420 self.removeTab(emptyIndex)
421
422 return newIndex
423
424 def __captionChange(self, cap, editor):
425 """
426 Private slot to handle Caption change signals from the editor.
427
428 Updates the tab text and tooltip text to reflect the new caption
429 information.
430
431 @param cap Caption for the editor
432 @type str
433 @param editor Editor to update the caption for
434 @type Editor
435 """
436 fn = editor.getFileName()
437 if fn:
438 if Preferences.getUI("TabViewManagerFilenameOnly"):
439 txt = os.path.basename(fn)
440 else:
441 txt = e5App().getObject("Project").getRelativePath(fn)
442
443 maxFileNameChars = Preferences.getUI(
444 "TabViewManagerFilenameLength")
445 if len(txt) > maxFileNameChars:
446 txt = "...{0}".format(txt[-maxFileNameChars:])
447 if editor.isReadOnly():
448 txt = self.tr("{0} (ro)").format(txt)
449
450 assembly = editor.parent()
451 index = self.indexOf(assembly)
452 if index > -1:
453 self.setTabText(index, txt)
454 self.setTabToolTip(index, fn)
455
456 def __cursorLineChanged(self, lineno, editor):
457 """
458 Private slot to handle a change of the current editor's cursor line.
459
460 @param lineno line number of the editor's cursor (zero based)
461 @type int
462 @param editor reference to the editor
463 @type Editor
464 """
465 if editor and isinstance(editor, QScintilla.Editor.Editor):
466 fn = editor.getFileName()
467 if fn:
468 self.vm.editorLineChanged.emit(fn, lineno + 1)
469
470 def removeWidget(self, widget):
471 """
472 Public method to remove a widget.
473
474 @param widget widget to be removed
475 @type QWidget
476 """
477 if isinstance(widget, QScintilla.Editor.Editor):
478 widget.cursorLineChanged.disconnect()
479 widget.captionChanged.disconnect()
480 self.editors.remove(widget)
481 index = self.indexOf(widget.parent())
482 else:
483 index = self.indexOf(widget)
484 if index > -1:
485 self.removeTab(index)
486
487 if not self.editors:
488 super(TabWidget, self).addTab(
489 self.emptyLabel, UI.PixmapCache.getIcon("empty.png"), "")
490 self.emptyLabel.show()
491 if self.closeButton:
492 self.closeButton.setEnabled(False)
493 else:
494 self.setTabsClosable(False)
495 self.navigationButton.setEnabled(False)
496
497 def __relocateTab(self, sourceId, sourceIndex, targetIndex):
498 """
499 Private method to relocate an editor from another TabWidget.
500
501 @param sourceId id of the TabWidget to get the editor from
502 @type str
503 @param sourceIndex index of the tab in the old tab widget
504 @type int
505 @param targetIndex index position to place it to
506 @type int
507 """
508 tw = self.vm.getTabWidgetById(int(sourceId))
509 if tw is not None:
510 # step 1: get data of the tab of the source
511 toolTip = tw.tabToolTip(sourceIndex)
512 text = tw.tabText(sourceIndex)
513 icon = tw.tabIcon(sourceIndex)
514 whatsThis = tw.tabWhatsThis(sourceIndex)
515 assembly = tw.widget(sourceIndex)
516
517 # step 2: relocate the tab
518 tw.removeWidget(assembly.getEditor())
519 self.insertWidget(targetIndex, assembly, text)
520
521 # step 3: set the tab data again
522 self.setTabIcon(targetIndex, icon)
523 self.setTabToolTip(targetIndex, toolTip)
524 self.setTabWhatsThis(targetIndex, whatsThis)
525
526 # step 4: set current widget
527 self.setCurrentIndex(targetIndex)
528
529 def __copyTabOther(self, sourceId, sourceIndex, targetIndex):
530 """
531 Private method to copy an editor from another TabWidget.
532
533 @param sourceId id of the TabWidget to get the editor from
534 @type str
535 @param sourceIndex index of the tab in the old tab widget
536 @type int
537 @param targetIndex index position to place it to
538 @type int
539 """
540 tw = self.vm.getTabWidgetById(int(sourceId))
541 if tw is not None:
542 editor = tw.widget(sourceIndex).getEditor()
543 newEditor, assembly = self.vm.cloneEditor(
544 editor, editor.getFileType(), editor.getFileName())
545 self.vm.insertView(assembly, self, targetIndex,
546 editor.getFileName(), editor.getNoName())
547
548 def __copyTab(self, sourceIndex, targetIndex):
549 """
550 Private method to copy an editor.
551
552 @param sourceIndex index of the tab
553 @type int
554 @param targetIndex index position to place it to
555 @type int
556 """
557 editor = self.widget(sourceIndex).getEditor()
558 newEditor, assembly = self.vm.cloneEditor(
559 editor, editor.getFileType(), editor.getFileName())
560 self.vm.insertView(assembly, self, targetIndex,
561 editor.getFileName(), editor.getNoName())
562
563 def currentWidget(self):
564 """
565 Public method to return a reference to the current page.
566
567 @return reference to the current page
568 @rtype Editor
569 """
570 if not self.editors:
571 return None
572 else:
573 return super(TabWidget, self).currentWidget()
574
575 def setCurrentWidget(self, assembly):
576 """
577 Public method to set the current tab by the given editor assembly.
578
579 @param assembly editor assembly to determine current tab from
580 @type EditorAssembly.EditorAssembly
581 """
582 super(TabWidget, self).setCurrentWidget(assembly)
583
584 def indexOf(self, widget):
585 """
586 Public method to get the tab index of the given editor.
587
588 @param widget widget to get the index for
589 @type QLabel or Editor
590 @return tab index of the editor
591 @rtype int
592 """
593 if isinstance(widget, QScintilla.Editor.Editor):
594 widget = widget.parent()
595 return super(TabWidget, self).indexOf(widget)
596
597 def hasEditor(self, editor):
598 """
599 Public method to check for an editor.
600
601 @param editor editor object to check for
602 @type Editor
603 @return flag indicating, whether the editor to be checked belongs
604 to the list of editors managed by this tab widget.
605 @rtype bool
606 """
607 return editor in self.editors
608
609 def hasEditors(self):
610 """
611 Public method to test, if any editor is managed.
612
613 @return flag indicating editors are managed
614 @rtype bool
615 """
616 return len(self.editors) > 0
617
618 def __contextMenuClose(self):
619 """
620 Private method to close the selected tab.
621 """
622 if self.contextMenuEditor:
623 self.vm.closeEditorWindow(self.contextMenuEditor)
624
625 def __contextMenuCloseOthers(self):
626 """
627 Private method to close the other tabs.
628 """
629 index = self.contextMenuIndex
630 for i in list(range(self.count() - 1, index, -1)) + \
631 list(range(index - 1, -1, -1)):
632 editor = self.widget(i).getEditor()
633 self.vm.closeEditorWindow(editor)
634
635 def __contextMenuCloseAll(self):
636 """
637 Private method to close all tabs.
638 """
639 savedEditors = self.editors[:]
640 for editor in savedEditors:
641 self.vm.closeEditorWindow(editor)
642
643 def __contextMenuSave(self):
644 """
645 Private method to save the selected tab.
646 """
647 if self.contextMenuEditor:
648 self.vm.saveEditorEd(self.contextMenuEditor)
649
650 def __contextMenuSaveAs(self):
651 """
652 Private method to save the selected tab to a new file.
653 """
654 if self.contextMenuEditor:
655 self.vm.saveAsEditorEd(self.contextMenuEditor)
656
657 def __contextMenuSaveAll(self):
658 """
659 Private method to save all tabs.
660 """
661 self.vm.saveEditorsList(self.editors)
662
663 def __contextMenuOpenRejections(self):
664 """
665 Private slot to open a rejections file associated with the selected
666 tab.
667 """
668 if self.contextMenuEditor:
669 fileName = self.contextMenuEditor.getFileName()
670 if fileName:
671 rej = "{0}.rej".format(fileName)
672 if os.path.exists(rej):
673 self.vm.openSourceFile(rej)
674
675 def __contextMenuPrintFile(self):
676 """
677 Private method to print the selected tab.
678 """
679 if self.contextMenuEditor:
680 self.vm.printEditor(self.contextMenuEditor)
681
682 def __contextMenuCopyPathToClipboard(self):
683 """
684 Private method to copy the file name of the selected tab to the
685 clipboard.
686 """
687 if self.contextMenuEditor:
688 fn = self.contextMenuEditor.getFileName()
689 if fn:
690 cb = QApplication.clipboard()
691 cb.setText(fn)
692
693 def __contextMenuMoveLeft(self):
694 """
695 Private method to move a tab one position to the left.
696 """
697 self.moveTab(self.contextMenuIndex, self.contextMenuIndex - 1)
698
699 def __contextMenuMoveRight(self):
700 """
701 Private method to move a tab one position to the right.
702 """
703 self.moveTab(self.contextMenuIndex, self.contextMenuIndex + 1)
704
705 def __contextMenuMoveFirst(self):
706 """
707 Private method to move a tab to the first position.
708 """
709 self.moveTab(self.contextMenuIndex, 0)
710
711 def __contextMenuMoveLast(self):
712 """
713 Private method to move a tab to the last position.
714 """
715 self.moveTab(self.contextMenuIndex, self.count() - 1)
716
717 def __closeButtonClicked(self):
718 """
719 Private method to handle the press of the close button.
720 """
721 self.vm.closeEditorWindow(self.currentWidget().getEditor())
722
723 def __closeRequested(self, index):
724 """
725 Private method to handle the press of the individual tab close button.
726
727 @param index index of the tab (integer)
728 """
729 if index >= 0:
730 self.vm.closeEditorWindow(self.widget(index).getEditor())
731
732 def mouseDoubleClickEvent(self, event):
733 """
734 Protected method handling double click events.
735
736 @param event reference to the event object (QMouseEvent)
737 """
738 self.vm.newEditor()
739
740
741 class Tabview(ViewManager):
742 """
743 Class implementing a tabbed viewmanager class embedded in a splitter.
744
745 @signal changeCaption(str) emitted if a change of the caption is necessary
746 @signal editorChanged(str) emitted when the current editor has changed
747 @signal editorChangedEd(Editor) emitted when the current editor has changed
748 @signal lastEditorClosed() emitted after the last editor window was closed
749 @signal editorOpened(str) emitted after an editor window was opened
750 @signal editorOpenedEd(Editor) emitted after an editor window was opened
751 @signal editorClosed(str) emitted just before an editor window gets closed
752 @signal editorClosedEd(Editor) emitted just before an editor window gets
753 closed
754 @signal editorRenamed(str) emitted after an editor was renamed
755 @signal editorRenamedEd(Editor) emitted after an editor was renamed
756 @signal editorSaved(str) emitted after an editor window was saved
757 @signal editorSavedEd(Editor) emitted after an editor window was saved
758 @signal checkActions(Editor) emitted when some actions should be checked
759 for their status
760 @signal cursorChanged(Editor) emitted after the cursor position of the
761 active window has changed
762 @signal breakpointToggled(Editor) emitted when a breakpoint is toggled.
763 @signal bookmarkToggled(Editor) emitted when a bookmark is toggled.
764 @signal syntaxerrorToggled(Editor) emitted when a syntax error is toggled.
765 @signal previewStateChanged(bool) emitted to signal a change in the
766 preview state
767 @signal previewStateChanged(bool) emitted to signal a change in the
768 preview state
769 @signal astViewerStateChanged(bool) emitted to signal a change in the
770 AST viewer state
771 @signal editorLanguageChanged(Editor) emitted to signal a change of an
772 editors language
773 @signal editorTextChanged(Editor) emitted to signal a change of an
774 editor's text
775 @signal editorLineChanged(str,int) emitted to signal a change of an
776 editor's current line (line is given one based)
777 """
778 changeCaption = pyqtSignal(str)
779 editorChanged = pyqtSignal(str)
780 editorChangedEd = pyqtSignal(Editor)
781 lastEditorClosed = pyqtSignal()
782 editorOpened = pyqtSignal(str)
783 editorOpenedEd = pyqtSignal(Editor)
784 editorClosed = pyqtSignal(str)
785 editorClosedEd = pyqtSignal(Editor)
786 editorRenamed = pyqtSignal(str)
787 editorRenamedEd = pyqtSignal(Editor)
788 editorSaved = pyqtSignal(str)
789 editorSavedEd = pyqtSignal(Editor)
790 checkActions = pyqtSignal(Editor)
791 cursorChanged = pyqtSignal(Editor)
792 breakpointToggled = pyqtSignal(Editor)
793 bookmarkToggled = pyqtSignal(Editor)
794 syntaxerrorToggled = pyqtSignal(Editor)
795 previewStateChanged = pyqtSignal(bool)
796 astViewerStateChanged = pyqtSignal(bool)
797 editorLanguageChanged = pyqtSignal(Editor)
798 editorTextChanged = pyqtSignal(Editor)
799 editorLineChanged = pyqtSignal(str, int)
800
801 def __init__(self, parent):
802 """
803 Constructor
804
805 @param parent parent widget
806 @type QWidget
807 """
808 self.tabWidgets = []
809
810 self.__splitter = QSplitter(parent)
811 ViewManager.__init__(self)
812 self.__splitter.setChildrenCollapsible(False)
813
814 tw = TabWidget(self)
815 self.__splitter.addWidget(tw)
816 self.tabWidgets.append(tw)
817 self.currentTabWidget = tw
818 self.currentTabWidget.showIndicator(True)
819 tw.currentChanged.connect(self.__currentChanged)
820 tw.installEventFilter(self)
821 tw.tabBar().installEventFilter(self)
822 self.__splitter.setOrientation(Qt.Vertical)
823 self.__inRemoveView = False
824
825 self.maxFileNameChars = Preferences.getUI(
826 "TabViewManagerFilenameLength")
827 self.filenameOnly = Preferences.getUI("TabViewManagerFilenameOnly")
828
829 def mainWidget(self):
830 """
831 Public method to return a reference to the main Widget of a
832 specific view manager subclass.
833
834 @return reference to the main widget
835 @rtype QWidget
836 """
837 return self.__splitter
838
839 def canCascade(self):
840 """
841 Public method to signal if cascading of managed windows is available.
842
843 @return flag indicating cascading of windows is available
844 @rtype bool
845 """
846 return False
847
848 def canTile(self):
849 """
850 Public method to signal if tiling of managed windows is available.
851
852 @return flag indicating tiling of windows is available
853 @rtype bool
854 """
855 return False
856
857 def canSplit(self):
858 """
859 public method to signal if splitting of the view is available.
860
861 @return flag indicating splitting of the view is available.
862 @rtype bool
863 """
864 return True
865
866 def tile(self):
867 """
868 Public method to tile the managed windows.
869 """
870 pass
871
872 def cascade(self):
873 """
874 Public method to cascade the managed windows.
875 """
876 pass
877
878 def _removeAllViews(self):
879 """
880 Protected method to remove all views (i.e. windows).
881 """
882 for win in self.editors:
883 self._removeView(win)
884
885 def _removeView(self, win):
886 """
887 Protected method to remove a view (i.e. window).
888
889 @param win editor window to be removed
890 @type Editor
891 """
892 self.__inRemoveView = True
893 for tw in self.tabWidgets:
894 if tw.hasEditor(win):
895 tw.removeWidget(win)
896 break
897 win.closeIt()
898 self.__inRemoveView = False
899
900 # if this was the last editor in this view, switch to the next, that
901 # still has open editors
902 for i in list(range(self.tabWidgets.index(tw), -1, -1)) + \
903 list(range(self.tabWidgets.index(tw) + 1,
904 len(self.tabWidgets))):
905 if self.tabWidgets[i].hasEditors():
906 self.currentTabWidget.showIndicator(False)
907 self.currentTabWidget = self.tabWidgets[i]
908 self.currentTabWidget.showIndicator(True)
909 self.activeWindow().setFocus()
910 break
911
912 aw = self.activeWindow()
913 fn = aw and aw.getFileName() or None
914 if fn:
915 self.changeCaption.emit(fn)
916 self.editorChanged.emit(fn)
917 self.editorLineChanged.emit(fn, aw.getCursorPosition()[0] + 1)
918 else:
919 self.changeCaption.emit("")
920 self.editorChangedEd.emit(aw)
921
922 def _addView(self, win, fn=None, noName="", addNext=False, indexes=None):
923 """
924 Protected method to add a view (i.e. window).
925
926 @param win editor assembly to be added
927 @type EditorAssembly
928 @param fn filename of this editor
929 @type str
930 @param noName name to be used for an unnamed editor
931 @type str
932 @param addNext flag indicating to add the view next to the current
933 view
934 @type bool
935 @param indexes of the editor, first the split view index, second the
936 index within the view
937 @type tuple of two int
938 """
939 editor = win.getEditor()
940 if not fn:
941 if not noName:
942 self.untitledCount += 1
943 noName = self.tr("Untitled {0}").format(self.untitledCount)
944 if addNext:
945 index = self.currentTabWidget.currentIndex() + 1
946 self.currentTabWidget.insertWidget(index, win, noName)
947 elif indexes:
948 if indexes[0] < len(self.tabWidgets):
949 tw = self.tabWidgets[indexes[0]]
950 else:
951 tw = self.tabWidgets[-1]
952 tw.insertWidget(indexes[1], win, noName)
953 else:
954 self.currentTabWidget.addTab(win, noName)
955 editor.setNoName(noName)
956 else:
957 if self.filenameOnly:
958 txt = os.path.basename(fn)
959 else:
960 txt = e5App().getObject("Project").getRelativePath(fn)
961 if len(txt) > self.maxFileNameChars:
962 txt = "...{0}".format(txt[-self.maxFileNameChars:])
963 if not QFileInfo(fn).isWritable():
964 txt = self.tr("{0} (ro)").format(txt)
965 if addNext:
966 index = self.currentTabWidget.currentIndex() + 1
967 self.currentTabWidget.insertWidget(index, win, txt)
968 elif indexes:
969 if indexes[0] < len(self.tabWidgets):
970 tw = self.tabWidgets[indexes[0]]
971 else:
972 tw = self.tabWidgets[-1]
973 tw.insertWidget(indexes[1], win, txt)
974 else:
975 self.currentTabWidget.addTab(win, txt)
976 index = self.currentTabWidget.indexOf(win)
977 self.currentTabWidget.setTabToolTip(index, fn)
978 self.currentTabWidget.setCurrentWidget(win)
979 win.show()
980 editor.setFocus()
981 if fn:
982 self.changeCaption.emit(fn)
983 self.editorChanged.emit(fn)
984 self.editorLineChanged.emit(fn, editor.getCursorPosition()[0] + 1)
985 else:
986 self.changeCaption.emit("")
987 self.editorChangedEd.emit(editor)
988
989 def insertView(self, win, tabWidget, index, fn=None, noName=""):
990 """
991 Public method to add a view (i.e. window).
992
993 @param win editor assembly to be inserted
994 @type EditorAssembly
995 @param tabWidget reference to the tab widget to insert the editor into
996 @type TabWidget
997 @param index index position to insert at
998 @type int
999 @param fn filename of this editor
1000 @type str
1001 @param noName name to be used for an unnamed editor
1002 @type str
1003 """
1004 editor = win.getEditor()
1005 if fn is None:
1006 if not noName:
1007 self.untitledCount += 1
1008 noName = self.tr("Untitled {0}").format(self.untitledCount)
1009 tabWidget.insertWidget(index, win, noName)
1010 editor.setNoName(noName)
1011 else:
1012 if self.filenameOnly:
1013 txt = os.path.basename(fn)
1014 else:
1015 txt = e5App().getObject("Project").getRelativePath(fn)
1016 if len(txt) > self.maxFileNameChars:
1017 txt = "...{0}".format(txt[-self.maxFileNameChars:])
1018 if not QFileInfo(fn).isWritable():
1019 txt = self.tr("{0} (ro)").format(txt)
1020 nindex = tabWidget.insertWidget(index, win, txt)
1021 tabWidget.setTabToolTip(nindex, fn)
1022 tabWidget.setCurrentWidget(win)
1023 win.show()
1024 editor.setFocus()
1025 if fn:
1026 self.changeCaption.emit(fn)
1027 self.editorChanged.emit(fn)
1028 self.editorLineChanged.emit(fn, editor.getCursorPosition()[0] + 1)
1029 else:
1030 self.changeCaption.emit("")
1031 self.editorChangedEd.emit(editor)
1032
1033 self._modificationStatusChanged(editor.isModified(), editor)
1034 self._checkActions(editor)
1035
1036 def _showView(self, win, fn=None):
1037 """
1038 Protected method to show a view (i.e. window).
1039
1040 @param win editor assembly to be shown
1041 @type EditorAssembly
1042 @param fn filename of this editor
1043 @type str
1044 """
1045 win.show()
1046 editor = win.getEditor()
1047 for tw in self.tabWidgets:
1048 if tw.hasEditor(editor):
1049 tw.setCurrentWidget(win)
1050 self.currentTabWidget.showIndicator(False)
1051 self.currentTabWidget = tw
1052 self.currentTabWidget.showIndicator(True)
1053 break
1054 editor.setFocus()
1055
1056 def activeWindow(self):
1057 """
1058 Public method to return the active (i.e. current) window.
1059
1060 @return reference to the active editor
1061 @rtype Editor
1062 """
1063 cw = self.currentTabWidget.currentWidget()
1064 if cw:
1065 return cw.getEditor()
1066 else:
1067 return None
1068
1069 def showWindowMenu(self, windowMenu):
1070 """
1071 Public method to set up the viewmanager part of the Window menu.
1072
1073 @param windowMenu reference to the window menu
1074 @type QMenu
1075 """
1076 pass
1077
1078 def _initWindowActions(self):
1079 """
1080 Protected method to define the user interface actions for window
1081 handling.
1082 """
1083 pass
1084
1085 def setEditorName(self, editor, newName):
1086 """
1087 Public method to change the displayed name of the editor.
1088
1089 @param editor editor window to be changed
1090 @type Editor
1091 @param newName new name to be shown
1092 @type str
1093 """
1094 if newName:
1095 if self.filenameOnly:
1096 tabName = os.path.basename(newName)
1097 else:
1098 tabName = e5App().getObject("Project").getRelativePath(newName)
1099 if len(tabName) > self.maxFileNameChars:
1100 tabName = "...{0}".format(tabName[-self.maxFileNameChars:])
1101 index = self.currentTabWidget.indexOf(editor)
1102 self.currentTabWidget.setTabText(index, tabName)
1103 self.currentTabWidget.setTabToolTip(index, newName)
1104 self.changeCaption.emit(newName)
1105
1106 def _modificationStatusChanged(self, m, editor):
1107 """
1108 Protected slot to handle the modificationStatusChanged signal.
1109
1110 @param m flag indicating the modification status
1111 @type bool
1112 @param editor editor window changed
1113 @type Editor
1114 """
1115 for tw in self.tabWidgets:
1116 if tw.hasEditor(editor):
1117 break
1118 index = tw.indexOf(editor)
1119 keys = []
1120 if m:
1121 keys.append("fileModified.png")
1122 if editor.hasSyntaxErrors():
1123 keys.append("syntaxError22.png")
1124 elif editor.hasWarnings():
1125 keys.append("warning22.png")
1126 if not keys:
1127 keys.append("empty.png")
1128 tw.setTabIcon(index, UI.PixmapCache.getCombinedIcon(keys))
1129 self._checkActions(editor)
1130
1131 def _syntaxErrorToggled(self, editor):
1132 """
1133 Protected slot to handle the syntaxerrorToggled signal.
1134
1135 @param editor editor that sent the signal
1136 @type Editor
1137 """
1138 for tw in self.tabWidgets:
1139 if tw.hasEditor(editor):
1140 break
1141 index = tw.indexOf(editor)
1142 keys = []
1143 if editor.isModified():
1144 keys.append("fileModified.png")
1145 if editor.hasSyntaxErrors():
1146 keys.append("syntaxError22.png")
1147 elif editor.hasWarnings():
1148 keys.append("warning22.png")
1149 if not keys:
1150 keys.append("empty.png")
1151 tw.setTabIcon(index, UI.PixmapCache.getCombinedIcon(keys))
1152
1153 ViewManager._syntaxErrorToggled(self, editor)
1154
1155 def addSplit(self):
1156 """
1157 Public method used to split the current view.
1158 """
1159 tw = TabWidget(self)
1160 tw.show()
1161 self.__splitter.addWidget(tw)
1162 self.tabWidgets.append(tw)
1163 self.currentTabWidget.showIndicator(False)
1164 self.currentTabWidget = self.tabWidgets[-1]
1165 self.currentTabWidget.showIndicator(True)
1166 tw.currentChanged.connect(self.__currentChanged)
1167 tw.installEventFilter(self)
1168 tw.tabBar().installEventFilter(self)
1169 if self.__splitter.orientation() == Qt.Horizontal:
1170 size = self.width()
1171 else:
1172 size = self.height()
1173 self.__splitter.setSizes(
1174 [int(size / len(self.tabWidgets))] * len(self.tabWidgets))
1175 self.splitRemoveAct.setEnabled(True)
1176 self.nextSplitAct.setEnabled(True)
1177 self.prevSplitAct.setEnabled(True)
1178
1179 @pyqtSlot()
1180 def removeSplit(self, index=-1):
1181 """
1182 Public method used to remove the current split view or a split view
1183 by index.
1184
1185 @param index index of the split to be removed (-1 means to
1186 delete the current split)
1187 @type int
1188 @return flag indicating successful deletion
1189 @rtype bool
1190 """
1191 if len(self.tabWidgets) > 1:
1192 if index == -1:
1193 tw = self.currentTabWidget
1194 else:
1195 if index < len(self.tabWidgets):
1196 tw = self.tabWidgets[index]
1197 else:
1198 tw = self.tabWidgets[-1]
1199 res = True
1200 savedEditors = tw.editors[:]
1201 for editor in savedEditors:
1202 res &= self.closeEditor(editor)
1203 if res:
1204 try:
1205 i = self.tabWidgets.index(tw)
1206 except ValueError:
1207 return True
1208 if i == len(self.tabWidgets) - 1:
1209 i -= 1
1210 self.tabWidgets.remove(tw)
1211 tw.close()
1212 self.currentTabWidget = self.tabWidgets[i]
1213 for tw in self.tabWidgets:
1214 tw.showIndicator(tw == self.currentTabWidget)
1215 if self.currentTabWidget is not None:
1216 assembly = self.currentTabWidget.currentWidget()
1217 if assembly is not None:
1218 editor = assembly.getEditor()
1219 if editor is not None:
1220 editor.setFocus(Qt.OtherFocusReason)
1221 if len(self.tabWidgets) == 1:
1222 self.splitRemoveAct.setEnabled(False)
1223 self.nextSplitAct.setEnabled(False)
1224 self.prevSplitAct.setEnabled(False)
1225 return True
1226
1227 return False
1228
1229 def splitCount(self):
1230 """
1231 Public method to get the number of splitted views.
1232
1233 @return number of splitted views
1234 @rtype int
1235 """
1236 return len(self.tabWidgets)
1237
1238 def setSplitCount(self, count):
1239 """
1240 Public method to set the number of split views.
1241
1242 @param count number of split views
1243 @type int
1244 """
1245 if count > self.splitCount():
1246 while self.splitCount() < count:
1247 self.addSplit()
1248 elif count < self.splitCount():
1249 while self.splitCount() > count:
1250 # use an arbitrarily large index to remove the last one
1251 self.removeSplit(index=100)
1252
1253 def getSplitOrientation(self):
1254 """
1255 Public method to get the orientation of the split view.
1256
1257 @return orientation of the split
1258 @rtype Qt.Horizontal or Qt.Vertical
1259 """
1260 return self.__splitter.orientation()
1261
1262 def setSplitOrientation(self, orientation):
1263 """
1264 Public method used to set the orientation of the split view.
1265
1266 @param orientation orientation of the split
1267 @type Qt.Horizontal or Qt.Vertical
1268 """
1269 self.__splitter.setOrientation(orientation)
1270
1271 def nextSplit(self):
1272 """
1273 Public slot used to move to the next split.
1274 """
1275 aw = self.activeWindow()
1276 _hasFocus = aw and aw.hasFocus()
1277 ind = self.tabWidgets.index(self.currentTabWidget) + 1
1278 if ind == len(self.tabWidgets):
1279 ind = 0
1280
1281 self.currentTabWidget.showIndicator(False)
1282 self.currentTabWidget = self.tabWidgets[ind]
1283 self.currentTabWidget.showIndicator(True)
1284 if _hasFocus:
1285 aw = self.activeWindow()
1286 if aw:
1287 aw.setFocus()
1288
1289 def prevSplit(self):
1290 """
1291 Public slot used to move to the previous split.
1292 """
1293 aw = self.activeWindow()
1294 _hasFocus = aw and aw.hasFocus()
1295 ind = self.tabWidgets.index(self.currentTabWidget) - 1
1296 if ind == -1:
1297 ind = len(self.tabWidgets) - 1
1298
1299 self.currentTabWidget.showIndicator(False)
1300 self.currentTabWidget = self.tabWidgets[ind]
1301 self.currentTabWidget.showIndicator(True)
1302 if _hasFocus:
1303 aw = self.activeWindow()
1304 if aw:
1305 aw.setFocus()
1306
1307 def __currentChanged(self, index):
1308 """
1309 Private slot to handle the currentChanged signal.
1310
1311 @param index index of the current tab
1312 @type int
1313 """
1314 if index == -1 or not self.editors:
1315 return
1316
1317 editor = self.activeWindow()
1318 if editor is None:
1319 return
1320
1321 self._checkActions(editor)
1322 editor.setFocus()
1323 fn = editor.getFileName()
1324 if fn:
1325 self.changeCaption.emit(fn)
1326 if not self.__inRemoveView:
1327 self.editorChanged.emit(fn)
1328 self.editorLineChanged.emit(
1329 fn, editor.getCursorPosition()[0] + 1)
1330 else:
1331 self.changeCaption.emit("")
1332 self.editorChangedEd.emit(editor)
1333
1334 def eventFilter(self, watched, event):
1335 """
1336 Public method called to filter the event queue.
1337
1338 @param watched the QObject being watched
1339 @type QObject
1340 @param event the event that occurred
1341 @type QEvent
1342 @return always False
1343 @rtype bool
1344 """
1345 if event.type() == QEvent.MouseButtonPress and \
1346 not event.button() == Qt.RightButton:
1347 switched = True
1348 self.currentTabWidget.showIndicator(False)
1349 if isinstance(watched, E5TabWidget):
1350 switched = watched is not self.currentTabWidget
1351 self.currentTabWidget = watched
1352 elif isinstance(watched, QTabBar):
1353 switched = watched.parent() is not self.currentTabWidget
1354 self.currentTabWidget = watched.parent()
1355 if switched:
1356 index = self.currentTabWidget.selectTab(event.pos())
1357 switched = self.currentTabWidget.widget(index) is \
1358 self.activeWindow()
1359 elif isinstance(watched, QScintilla.Editor.Editor):
1360 for tw in self.tabWidgets:
1361 if tw.hasEditor(watched):
1362 switched = tw is not self.currentTabWidget
1363 self.currentTabWidget = tw
1364 break
1365 self.currentTabWidget.showIndicator(True)
1366
1367 aw = self.activeWindow()
1368 if aw is not None:
1369 self._checkActions(aw)
1370 aw.setFocus()
1371 fn = aw.getFileName()
1372 if fn:
1373 self.changeCaption.emit(fn)
1374 if switched:
1375 self.editorChanged.emit(fn)
1376 self.editorLineChanged.emit(
1377 fn, aw.getCursorPosition()[0] + 1)
1378 else:
1379 self.changeCaption.emit("")
1380 self.editorChangedEd.emit(aw)
1381
1382 return False
1383
1384 def preferencesChanged(self):
1385 """
1386 Public slot to handle the preferencesChanged signal.
1387 """
1388 ViewManager.preferencesChanged(self)
1389
1390 self.maxFileNameChars = Preferences.getUI(
1391 "TabViewManagerFilenameLength")
1392 self.filenameOnly = Preferences.getUI("TabViewManagerFilenameOnly")
1393
1394 for tabWidget in self.tabWidgets:
1395 for index in range(tabWidget.count()):
1396 editor = tabWidget.widget(index)
1397 if isinstance(editor, QScintilla.Editor.Editor):
1398 fn = editor.getFileName()
1399 if fn:
1400 if self.filenameOnly:
1401 txt = os.path.basename(fn)
1402 else:
1403 txt = e5App().getObject("Project")\
1404 .getRelativePath(fn)
1405 if len(txt) > self.maxFileNameChars:
1406 txt = "...{0}".format(txt[-self.maxFileNameChars:])
1407 if not QFileInfo(fn).isWritable():
1408 txt = self.tr("{0} (ro)").format(txt)
1409 tabWidget.setTabText(index, txt)
1410
1411 def getTabWidgetById(self, id_):
1412 """
1413 Public method to get a reference to a tab widget knowing its ID.
1414
1415 @param id_ id of the tab widget
1416 @type int
1417 @return reference to the tab widget
1418 @rtype TabWidget
1419 """
1420 for tw in self.tabWidgets:
1421 if id(tw) == id_:
1422 return tw
1423 return None
1424
1425 def getOpenEditorsForSession(self):
1426 """
1427 Public method to get a lists of all open editors.
1428
1429 The returned list contains one list per split view. If the view manager
1430 cannot split the view, only one list of editors is returned.
1431
1432 @return list of list of editor references
1433 @rtype list of list of Editor
1434 """
1435 editorLists = []
1436 for tabWidget in self.tabWidgets:
1437 editors = []
1438 for index in range(tabWidget.count()):
1439 widget = tabWidget.widget(index)
1440 if isinstance(widget, EditorAssembly):
1441 editor = widget.getEditor()
1442 editors.append(editor)
1443 editorLists.append(editors)
1444 return editorLists

eric ide

mercurial