src/eric7/Plugins/ViewManagerPlugins/Tabview/Tabview.py

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

eric ide

mercurial