File: advanced_editor_area_pane.py

package info (click to toggle)
python-pyface 8.0.0-5
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 13,944 kB
  • sloc: python: 54,107; makefile: 82
file content (700 lines) | stat: -rw-r--r-- 25,971 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
# (C) Copyright 2005-2023 Enthought, Inc., Austin, TX
# All rights reserved.
#
# This software is provided without warranty under the terms of the BSD
# license included in LICENSE.txt and may be redistributed only under
# the conditions described in the aforementioned license. The license
# is also available online at http://www.enthought.com/licenses/BSD.txt
#
# Thanks for using Enthought open source!

import sys


from pyface.qt import QtCore, QtGui, is_pyside, is_qt6


from traits.api import (
    Any, Callable, DelegatesTo, Instance, List, observe, provides, Tuple
)


from pyface.tasks.i_advanced_editor_area_pane import IAdvancedEditorAreaPane
from pyface.tasks.i_editor_area_pane import MEditorAreaPane
from .editor_area_pane import EditorAreaDropFilter
from .main_window_layout import MainWindowLayout, PaneItem
from .task_pane import TaskPane
from .util import set_focus

# ----------------------------------------------------------------------------
# 'AdvancedEditorAreaPane' class.
# ----------------------------------------------------------------------------


@provides(IAdvancedEditorAreaPane)
class AdvancedEditorAreaPane(TaskPane, MEditorAreaPane):
    """ The toolkit-specific implementation of an AdvancedEditorAreaPane.

    See the IAdvancedEditorAreaPane interface for API documentation.
    """

    # Private interface ----------------------------------------------------

    _main_window_layout = Instance(MainWindowLayout)

    #: A list of connected Qt signals to be removed before destruction.
    #: First item in the tuple is the Qt signal. The second item is the event
    #: handler.
    _connections_to_remove = List(Tuple(Any, Callable))

    # ------------------------------------------------------------------------
    # 'TaskPane' interface.
    # ------------------------------------------------------------------------

    def create(self, parent):
        """ Create and set the toolkit-specific control that represents the
            pane.
        """
        self.control = EditorAreaWidget(self, parent)
        self._filter = EditorAreaDropFilter(self)
        self.control.installEventFilter(self._filter)

        # Add shortcuts for scrolling through tabs.
        if sys.platform == "darwin":
            next_seq = "Ctrl+}"
            prev_seq = "Ctrl+{"
        else:
            next_seq = "Ctrl+PgDown"
            prev_seq = "Ctrl+PgUp"
        shortcut = QtGui.QShortcut(QtGui.QKeySequence(next_seq), self.control)
        shortcut.activated.connect(self._next_tab)
        self._connections_to_remove.append(
            (shortcut.activated, self._next_tab)
        )
        shortcut = QtGui.QShortcut(QtGui.QKeySequence(prev_seq), self.control)
        shortcut.activated.connect(self._previous_tab)
        self._connections_to_remove.append(
            (shortcut.activated, self._previous_tab)
        )

        # Add shortcuts for switching to a specific tab.
        mod = "Ctrl+" if sys.platform == "darwin" else "Alt+"
        mapper = QtCore.QSignalMapper(self.control)
        if is_pyside and is_qt6:
            mapper.mappedInt.connect(self._activate_tab)
            self._connections_to_remove.append(
                (mapper.mappedInt, self._activate_tab)
            )
        else:
            mapper.mapped.connect(self._activate_tab)
            self._connections_to_remove.append(
                (mapper.mapped, self._activate_tab)
            )

        for i in range(1, 10):
            sequence = QtGui.QKeySequence(mod + str(i))
            shortcut = QtGui.QShortcut(sequence, self.control)
            shortcut.activated.connect(mapper.map)
            self._connections_to_remove.append(
                (shortcut.activated, mapper.map)
            )
            mapper.setMapping(shortcut, i - 1)

    def destroy(self):
        """ Destroy the toolkit-specific control that represents the pane.
        """
        if self.control is not None:
            self.control.removeEventFilter(self._filter)
            self.control._remove_event_listeners()
            self._filter = None

            for editor in self.editors:
                editor_widget = editor.control.parent()
                self.control.destroy_editor_widget(editor_widget)
                editor.editor_area = None
            self.active_editor = None

            while self._connections_to_remove:
                signal, handler = self._connections_to_remove.pop()
                signal.disconnect(handler)

        super().destroy()

    # ------------------------------------------------------------------------
    # 'IEditorAreaPane' interface.
    # ------------------------------------------------------------------------

    def activate_editor(self, editor):
        """ Activates the specified editor in the pane.
        """
        editor_widget = editor.control.parent()
        editor_widget.setVisible(True)
        editor_widget.raise_()
        editor.control.setFocus()
        self.active_editor = editor

    def add_editor(self, editor):
        """ Adds an editor to the pane.
        """
        editor.editor_area = self
        editor_widget = EditorWidget(editor, self.control)
        self.control.add_editor_widget(editor_widget)
        self.editors.append(editor)

    def remove_editor(self, editor):
        """ Removes an editor from the pane.
        """
        editor_widget = editor.control.parent()
        self.editors.remove(editor)
        self.control.remove_editor_widget(editor_widget)
        editor.editor_area = None
        if not self.editors:
            self.active_editor = None

    # ------------------------------------------------------------------------
    # 'IAdvancedEditorAreaPane' interface.
    # ------------------------------------------------------------------------

    def get_layout(self):
        """ Returns a LayoutItem that reflects the current state of the editors.
        """
        return self._main_window_layout.get_layout_for_area(
            QtCore.Qt.DockWidgetArea.LeftDockWidgetArea
        )

    def set_layout(self, layout):
        """ Applies a LayoutItem to the editors in the pane.
        """
        if layout is not None:
            self._main_window_layout.set_layout_for_area(
                layout, QtCore.Qt.DockWidgetArea.LeftDockWidgetArea
            )

    # ------------------------------------------------------------------------
    # Private interface.
    # ------------------------------------------------------------------------

    def _activate_tab(self, index):
        """ Activates the tab with the specified index, if there is one.
        """
        widgets = self.control.get_dock_widgets_ordered()
        if index < len(widgets):
            self.activate_editor(widgets[index].editor)

    def _next_tab(self):
        """ Activate the tab after the currently active tab.
        """
        if self.active_editor:
            widgets = self.control.get_dock_widgets_ordered()
            index = widgets.index(self.active_editor.control.parent()) + 1
            if index < len(widgets):
                self.activate_editor(widgets[index].editor)

    def _previous_tab(self):
        """ Activate the tab before the currently active tab.
        """
        if self.active_editor:
            widgets = self.control.get_dock_widgets_ordered()
            index = widgets.index(self.active_editor.control.parent()) - 1
            if index >= 0:
                self.activate_editor(widgets[index].editor)

    def _get_label(self, editor):
        """ Return a tab label for an editor.
        """
        label = editor.name
        if editor.dirty:
            label = "*" + label
        return label

    # Trait initializers ---------------------------------------------------

    def __main_window_layout_default(self):
        return EditorAreaMainWindowLayout(editor_area=self)

    # Trait change handlers ------------------------------------------------

    @observe("editors:items:[dirty, name]")
    def _update_label(self, event):
        editor = event.object
        editor.control.parent().update_title()

    @observe("editors:items:tooltip")
    def _update_tooltip(self, event):
        editor = event.object
        editor.control.parent().update_tooltip()


# ----------------------------------------------------------------------------
# Auxillary classes.
# ----------------------------------------------------------------------------


class EditorAreaMainWindowLayout(MainWindowLayout):
    """ A MainWindowLayout for implementing AdvancedEditorAreaPane.

    Used for getting and setting layouts for the pane.
    """

    # 'MainWindowLayout' interface -----------------------------------------

    control = DelegatesTo("editor_area")

    # 'TaskWindowLayout' interface -----------------------------------------

    editor_area = Instance(AdvancedEditorAreaPane)

    # ------------------------------------------------------------------------
    # 'MainWindowLayout' abstract interface.
    # ------------------------------------------------------------------------

    def _get_dock_widget(self, pane):
        """ Returns the QDockWidget associated with a PaneItem.
        """
        try:
            editor = self.editor_area.editors[pane.id]
            return editor.control.parent()
        except IndexError:
            return None

    def _get_pane(self, dock_widget):
        """ Returns a PaneItem for a QDockWidget.
        """
        for i, editor in enumerate(self.editor_area.editors):
            if editor.control == dock_widget.widget():
                return PaneItem(id=i)
        return None


class EditorAreaWidget(QtGui.QMainWindow):
    """ An auxillary widget for implementing AdvancedEditorAreaPane.
    """

    # ------------------------------------------------------------------------
    # 'EditorAreaWidget' interface.
    # ------------------------------------------------------------------------

    def __init__(self, editor_area, parent=None):
        super().__init__(parent)
        self.editor_area = editor_area
        self.reset_drag()

        # Fish out the rubber band used by Qt to indicate a drop region. We use
        # it to determine which dock widget is the hover widget.
        for child in self.children():
            if isinstance(child, QtGui.QRubberBand):
                child.installEventFilter(self)
                self._rubber_band = child
                break

        # Monitor focus changes so we can set the active editor.
        QtGui.QApplication.instance().focusChanged.connect(self._update_active_editor)

        # Configure the QMainWindow.
        # FIXME: Currently animation is not supported.
        self.setAcceptDrops(True)
        self.setAnimated(False)
        self.setDockNestingEnabled(True)
        self.setDocumentMode(True)
        self.setFocusPolicy(QtCore.Qt.FocusPolicy.StrongFocus)
        self.setTabPosition(
            QtCore.Qt.DockWidgetArea.AllDockWidgetAreas, QtGui.QTabWidget.TabPosition.North
        )

    def _remove_event_listeners(self):
        """ Disconnects focusChanged signal of the application """
        app = QtGui.QApplication.instance()
        app.focusChanged.disconnect(self._update_active_editor)

    def add_editor_widget(self, editor_widget):
        """ Adds a dock widget to the editor area.
        """
        editor_widget.installEventFilter(self)
        self.addDockWidget(QtCore.Qt.DockWidgetArea.LeftDockWidgetArea, editor_widget)

        # Try to place the editor in a sensible spot.
        top_left = None
        for widget in self.get_dock_widgets():
            if top_left is None or (
                widget.pos().manhattanLength()
                < top_left.pos().manhattanLength()
            ):
                top_left = widget
        if top_left:
            self.tabifyDockWidget(top_left, editor_widget)
            top_left.set_title_bar(False)

        # Qt will not give the dock widget focus by default.
        self.editor_area.activate_editor(editor_widget.editor)

    def destroy_editor_widget(self, editor_widget):
        """ Destroys a dock widget in the editor area.
        """
        editor_widget.hide()
        editor_widget.removeEventFilter(self)
        editor_widget._remove_event_listeners()
        editor_widget.editor.destroy()
        self.removeDockWidget(editor_widget)

    def get_dock_widgets(self):
        """ Gets all visible dock widgets.
        """
        return [
            child
            for child in self.children()
            if isinstance(child, QtGui.QDockWidget) and child.isVisible()
        ]

    def get_dock_widgets_for_bar(self, tab_bar):
        """ Get the dock widgets, in order, attached to given tab bar.

        Because QMainWindow locks this info down, we have resorted to a hack.
        """
        pos = tab_bar.pos()
        key = lambda w: QtGui.QVector2D(pos - w.pos()).lengthSquared()
        all_widgets = self.get_dock_widgets()
        if all_widgets:
            current = min(all_widgets, key=key)
            widgets = self.tabifiedDockWidgets(current)
            widgets.insert(tab_bar.currentIndex(), current)
            return widgets
        return []

    def get_dock_widgets_ordered(self, visible_only=False):
        """ Gets all dock widgets in left-to-right, top-to-bottom order.
        """
        children = []
        for child in self.children():
            if (
                child.isWidgetType()
                and child.isVisible()
                and (
                    (isinstance(child, QtGui.QTabBar) and not visible_only)
                    or (
                        isinstance(child, QtGui.QDockWidget)
                        and (
                            visible_only or not self.tabifiedDockWidgets(child)
                        )
                    )
                )
            ):
                children.append(child)
        children.sort(key=lambda _child: (_child.pos().y(), _child.pos().x()))

        widgets = []
        for child in children:
            if isinstance(child, QtGui.QTabBar):
                widgets.extend(self.get_dock_widgets_for_bar(child))
            else:
                widgets.append(child)
        return widgets

    def remove_editor_widget(self, editor_widget):
        """ Removes a dock widget from the editor area.
        """
        # Get the tabs in this editor's dock area before removing it.
        tabified = self.tabifiedDockWidgets(editor_widget)
        if tabified:
            widgets = self.get_dock_widgets_ordered()
            tabified = [
                widget
                for widget in widgets
                if widget in tabified or widget == editor_widget
            ]
        visible = self.get_dock_widgets_ordered(visible_only=True)

        # Destroy and remove the editor. Get the active widget first, since it
        # may be destroyed!
        next_widget = self.editor_area.active_editor.control.parent()
        self.destroy_editor_widget(editor_widget)

        # Ensure that the appropriate editor is activated.
        editor_area = self.editor_area
        choices = tabified if len(tabified) >= 2 else visible
        if len(choices) >= 2 and editor_widget == next_widget:
            i = choices.index(editor_widget)
            next_widget = (
                choices[i + 1] if i + 1 < len(choices) else choices[i - 1]
            )
            editor_area.activate_editor(next_widget.editor)

        # Update tab bar hide state.
        if len(tabified) == 2:
            next_widget.editor.control.parent().set_title_bar(True)
        if editor_area.hide_tab_bar and len(editor_area.editors) == 1:
            editor_area.editors[0].control.parent().set_title_bar(False)

    def reset_drag(self):
        """ Clear out all drag state.
        """
        self._drag_widget = None
        self._hover_widget = None
        self._tear_handled = False
        self._tear_widgets = []

    def set_hover_widget(self, widget):
        """ Set the dock widget being 'hovered over' during a drag.
        """
        old_widget = self._hover_widget
        self._hover_widget = widget

        if old_widget:
            if old_widget in self._tear_widgets:
                if len(self._tear_widgets) == 1:
                    old_widget.set_title_bar(True)
            elif not self.tabifiedDockWidgets(old_widget):
                old_widget.set_title_bar(True)

        if widget:
            if widget in self._tear_widgets:
                if len(self._tear_widgets) == 1:
                    widget.set_title_bar(False)
            elif len(self.tabifiedDockWidgets(widget)) == 1:
                widget.set_title_bar(False)

    # ------------------------------------------------------------------------
    # Event handlers.
    # ------------------------------------------------------------------------

    def childEvent(self, event):
        """ Reimplemented to gain access to the tab bars as they are created.
        """
        super().childEvent(event)
        if event.polished():
            child = event.child()
            if isinstance(child, QtGui.QTabBar):
                # Use UniqueConnections since Qt recycles the tab bars.
                child.installEventFilter(self)
                child.currentChanged.connect(
                    self._update_editor_in_focus, QtCore.Qt.ConnectionType.UniqueConnection
                )
                child.setTabsClosable(True)
                child.setUsesScrollButtons(True)
                child.tabCloseRequested.connect(
                    self._tab_close_requested, QtCore.Qt.ConnectionType.UniqueConnection
                )
                # FIXME: We would like to have the tabs movable, but this
                # confuses the QMainWindowLayout. For now, we disable this.
                # child.setMovable(True)

    def eventFilter(self, obj, event):
        """ Reimplemented to dispatch to sub-handlers.
        """
        if isinstance(obj, QtGui.QDockWidget):
            return self._filter_dock_widget(obj, event)

        elif isinstance(obj, QtGui.QRubberBand):
            return self._filter_rubber_band(obj, event)

        elif isinstance(obj, QtGui.QTabBar):
            return self._filter_tab_bar(obj, event)

        return False

    def _filter_dock_widget(self, widget, event):
        """ Support hover widget state tracking.
        """
        if self._drag_widget and event.type() == QtCore.QEvent.Type.Resize:
            if widget.geometry() == self._rubber_band.geometry():
                self.set_hover_widget(widget)

        elif (
            self._drag_widget == widget and event.type() == QtCore.QEvent.Type.Move
        ):
            if len(self._tear_widgets) == 1 and not self._tear_handled:
                widget = self._tear_widgets[0]
                widget.set_title_bar(True)
                self._tear_handled = True

        elif (
            self._drag_widget == widget
            and event.type() == QtCore.QEvent.Type.MouseButtonRelease
        ):
            self.reset_drag()

        return False

    def _filter_rubber_band(self, rubber_band, event):
        """ Support hover widget state tracking.
        """
        if self._drag_widget and event.type() in (
            QtCore.QEvent.Type.Resize,
            QtCore.QEvent.Type.Move,
        ):
            self.set_hover_widget(None)

        return False

    def _filter_tab_bar(self, tab_bar, event):
        """ Support 'tearing off' a tab.
        """
        if event.type() == QtCore.QEvent.Type.MouseMove:
            if tab_bar.rect().contains(event.pos()):
                self.reset_drag()
            else:
                if not self._drag_widget:
                    index = tab_bar.currentIndex()
                    self._tear_widgets = self.get_dock_widgets_for_bar(tab_bar)
                    self._drag_widget = widget = self._tear_widgets.pop(index)

                    pos = QtCore.QPoint(0, 0)
                    press_event = QtGui.QMouseEvent(
                        QtCore.QEvent.Type.MouseButtonPress,
                        pos,
                        widget.mapToGlobal(pos),
                        QtCore.Qt.MouseButton.LeftButton,
                        QtCore.Qt.MouseButton.LeftButton,
                        event.modifiers(),
                    )
                    QtCore.QCoreApplication.sendEvent(widget, press_event)
                    return True

                event = QtGui.QMouseEvent(
                    QtCore.QEvent.Type.MouseMove,
                    event.pos(),
                    event.globalPos(),
                    event.button(),
                    event.buttons(),
                    event.modifiers(),
                )
                QtCore.QCoreApplication.sendEvent(self._drag_widget, event)
                return True

        elif event.type() == QtCore.QEvent.Type.ToolTip:
            # QDockAreaLayout forces the tooltips to be QDockWidget.windowTitle,
            # so we provide the tooltips manually.
            widgets = self.get_dock_widgets_for_bar(tab_bar)
            index = tab_bar.tabAt(event.pos())
            tooltip = widgets[index].editor.tooltip if index >= 0 else ""
            if tooltip:
                QtGui.QToolTip.showText(event.globalPos(), tooltip, tab_bar)
            return True

        return False

    def focusInEvent(self, event):
        """ Assign focus to the active editor, if possible.
        """
        active_editor = self.editor_area.active_editor
        if active_editor:
            set_focus(active_editor.control)

    # ------------------------------------------------------------------------
    # Signal handlers.
    # ------------------------------------------------------------------------

    def _update_active_editor(self, old, new):
        """ Handle an application-level focus change.
        """
        if new is not None:
            for editor in self.editor_area.editors:
                control = editor.control
                if control is not None and control.isAncestorOf(new):
                    self.editor_area.active_editor = editor
                    break
            else:
                if not self.editor_area.editors:
                    self.editor_area.active_editor = None

    def _update_editor_in_focus(self, index):
        """ Handle a tab selection.
        """
        widgets = self.get_dock_widgets_for_bar(self.sender())
        if index < len(widgets):
            editor_widget = widgets[index]
            editor_widget.editor.control.setFocus()

    def _tab_close_requested(self, index):
        """ Handle a tab close request.
        """
        editor_widget = self.get_dock_widgets_for_bar(self.sender())[index]
        editor_widget.editor.close()


class EditorWidget(QtGui.QDockWidget):
    """ An auxillary widget for implementing AdvancedEditorAreaPane.
    """

    def __init__(self, editor, parent=None):
        super().__init__(parent)
        self.editor = editor
        self.editor.create(self)
        self.setAllowedAreas(QtCore.Qt.DockWidgetArea.LeftDockWidgetArea)
        self.setFeatures(
            QtGui.QDockWidget.DockWidgetFeature.DockWidgetClosable
            | QtGui.QDockWidget.DockWidgetFeature.DockWidgetMovable
        )
        self.setWidget(editor.control)
        self.update_title()

        # Update the minimum size.
        contents_minsize = editor.control.minimumSize()
        style = self.style()
        contents_minsize.setHeight(
            contents_minsize.height()
            + style.pixelMetric(style.PixelMetric.PM_DockWidgetHandleExtent)
        )
        self.setMinimumSize(contents_minsize)

        self.dockLocationChanged.connect(self.update_title_bar)
        self.visibilityChanged.connect(self.update_title_bar)

    def _remove_event_listeners(self):
        self.dockLocationChanged.disconnect(self.update_title_bar)
        self.visibilityChanged.disconnect(self.update_title_bar)

    def update_title(self):
        title = self.editor.editor_area._get_label(self.editor)
        self.setWindowTitle(title)

        title_bar = self.titleBarWidget()
        if isinstance(title_bar, EditorTitleBarWidget):
            title_bar.setTabText(0, title)

    def update_tooltip(self):
        title_bar = self.titleBarWidget()
        if isinstance(title_bar, EditorTitleBarWidget):
            title_bar.setTabToolTip(0, self.editor.tooltip)

    def update_title_bar(self):
        if self not in self.parent()._tear_widgets:
            tabbed = self.parent().tabifiedDockWidgets(self)
            self.set_title_bar(not tabbed)

    def set_title_bar(self, title_bar):
        current = self.titleBarWidget()
        editor_area = self.editor.editor_area
        if (
            title_bar
            and editor_area
            and (not editor_area.hide_tab_bar or len(editor_area.editors) > 1)
        ):
            if not isinstance(current, EditorTitleBarWidget):
                self.setTitleBarWidget(EditorTitleBarWidget(self))
        elif current is None or isinstance(current, EditorTitleBarWidget):
            self.setTitleBarWidget(QtGui.QWidget())


class EditorTitleBarWidget(QtGui.QTabBar):
    """ An auxillary widget for implementing AdvancedEditorAreaPane.
    """

    def __init__(self, editor_widget):
        super().__init__(editor_widget)
        self.addTab(editor_widget.windowTitle())
        self.setTabToolTip(0, editor_widget.editor.tooltip)
        self.setDocumentMode(True)
        self.setExpanding(False)
        self.setTabsClosable(True)

        self.tabCloseRequested.connect(editor_widget.editor.close)

    def mousePressEvent(self, event):
        self.parent().parent()._drag_widget = self.parent()
        event.ignore()

    def mouseMoveEvent(self, event):
        event.ignore()

    def mouseReleaseEvent(self, event):
        event.ignore()