class Central(QStackedWidget): # {{{ ' The central widget, hosts the editors ' current_editor_changed = pyqtSignal() close_requested = pyqtSignal(object) def __init__(self, parent=None): QStackedWidget.__init__(self, parent) self.welcome = w = QLabel('<p>'+_( 'Double click a file in the left panel to start editing' ' it.')) self.addWidget(w) w.setWordWrap(True) w.setAlignment(Qt.AlignTop | Qt.AlignHCenter) self.container = c = QWidget(self) self.addWidget(c) l = c.l = QVBoxLayout(c) c.setLayout(l) l.setContentsMargins(0, 0, 0, 0) self.editor_tabs = t = QTabWidget(c) l.addWidget(t) t.setDocumentMode(True) t.setTabsClosable(True) t.setMovable(True) pal = self.palette() if pal.color(pal.WindowText).lightness() > 128: i = QImage(I('modified.png')) i.invertPixels() self.modified_icon = QIcon(QPixmap.fromImage(i)) else: self.modified_icon = QIcon(I('modified.png')) self.editor_tabs.currentChanged.connect(self.current_editor_changed) self.editor_tabs.tabCloseRequested.connect(self._close_requested) self.search_panel = SearchPanel(self) l.addWidget(self.search_panel) self.restore_state() self.editor_tabs.tabBar().installEventFilter(self) def _close_requested(self, index): editor = self.editor_tabs.widget(index) self.close_requested.emit(editor) def add_editor(self, name, editor): fname = name.rpartition('/')[2] index = self.editor_tabs.addTab(editor, fname) self.editor_tabs.setTabToolTip(index, _('Full path:') + ' ' + name) editor.modification_state_changed.connect(self.editor_modified) @property def tab_order(self): ans = [] rmap = {v:k for k, v in editors.iteritems()} for i in xrange(self.editor_tabs.count()): name = rmap.get(self.editor_tabs.widget(i)) if name is not None: ans.append(name) return ans def rename_editor(self, editor, name): for i in xrange(self.editor_tabs.count()): if self.editor_tabs.widget(i) is editor: fname = name.rpartition('/')[2] self.editor_tabs.setTabText(i, fname) self.editor_tabs.setTabToolTip(i, _('Full path:') + ' ' + name) def show_editor(self, editor): self.setCurrentIndex(1) self.editor_tabs.setCurrentWidget(editor) def close_editor(self, editor): for i in xrange(self.editor_tabs.count()): if self.editor_tabs.widget(i) is editor: self.editor_tabs.removeTab(i) if self.editor_tabs.count() == 0: self.setCurrentIndex(0) return True return False def editor_modified(self, *args): tb = self.editor_tabs.tabBar() for i in xrange(self.editor_tabs.count()): editor = self.editor_tabs.widget(i) modified = getattr(editor, 'is_modified', False) tb.setTabIcon(i, self.modified_icon if modified else QIcon()) def close_current_editor(self): ed = self.current_editor if ed is not None: self.close_requested.emit(ed) def close_all_but_current_editor(self): self.close_all_but(self.current_editor) def close_all_but(self, ed): close = [] if ed is not None: for i in xrange(self.editor_tabs.count()): q = self.editor_tabs.widget(i) if q is not None and q is not ed: close.append(q) for q in close: self.close_requested.emit(q) @property def current_editor(self): return self.editor_tabs.currentWidget() def save_state(self): tprefs.set('search-panel-visible', self.search_panel.isVisible()) self.search_panel.save_state() for ed in editors.itervalues(): ed.save_state() if self.current_editor is not None: self.current_editor.save_state() # Ensure the current editor saves it state last def restore_state(self): self.search_panel.setVisible(tprefs.get('search-panel-visible', False)) self.search_panel.restore_state() def show_find(self): self.search_panel.show_panel() def pre_fill_search(self, text): self.search_panel.pre_fill(text) def eventFilter(self, obj, event): base = super(Central, self) if obj is not self.editor_tabs.tabBar() or event.type() != QEvent.MouseButtonPress or event.button() not in (Qt.RightButton, Qt.MidButton): return base.eventFilter(obj, event) index = self.editor_tabs.tabBar().tabAt(event.pos()) if index < 0: return base.eventFilter(obj, event) if event.button() == Qt.MidButton: self._close_requested(index) ed = self.editor_tabs.widget(index) if ed is not None: menu = QMenu(self) menu.addAction(actions['close-current-tab'].icon(), _('Close tab'), partial(self.close_requested.emit, ed)) menu.addSeparator() menu.addAction(actions['close-all-but-current-tab'].icon(), _('Close other tabs'), partial(self.close_all_but, ed)) menu.exec_(self.editor_tabs.tabBar().mapToGlobal(event.pos())) return True
class Central(QStackedWidget): ' The central widget, hosts the editors ' current_editor_changed = pyqtSignal() close_requested = pyqtSignal(object) def __init__(self, parent=None): QStackedWidget.__init__(self, parent) self.welcome = w = QLabel('<p>'+_( 'Double click a file in the left panel to start editing' ' it.')) self.addWidget(w) w.setWordWrap(True) w.setAlignment(Qt.AlignTop | Qt.AlignHCenter) self.container = c = QWidget(self) self.addWidget(c) l = c.l = QVBoxLayout(c) c.setLayout(l) l.setContentsMargins(0, 0, 0, 0) self.editor_tabs = t = QTabWidget(c) l.addWidget(t) t.setDocumentMode(True) t.setTabsClosable(True) t.setMovable(True) pal = self.palette() if pal.color(pal.WindowText).lightness() > 128: i = QImage(I('modified.png')) i.invertPixels() self.modified_icon = QIcon(QPixmap.fromImage(i)) else: self.modified_icon = QIcon(I('modified.png')) self.editor_tabs.currentChanged.connect(self.current_editor_changed) self.editor_tabs.tabCloseRequested.connect(self._close_requested) self.search_panel = SearchPanel(self) l.addWidget(self.search_panel) self.restore_state() def _close_requested(self, index): editor = self.editor_tabs.widget(index) self.close_requested.emit(editor) def add_editor(self, name, editor): fname = name.rpartition('/')[2] index = self.editor_tabs.addTab(editor, fname) self.editor_tabs.setTabToolTip(index, _('Full path:') + ' ' + name) editor.modification_state_changed.connect(self.editor_modified) def show_editor(self, editor): self.setCurrentIndex(1) self.editor_tabs.setCurrentWidget(editor) def close_editor(self, editor): for i in xrange(self.editor_tabs.count()): if self.editor_tabs.widget(i) is editor: self.editor_tabs.removeTab(i) if self.editor_tabs.count() == 0: self.setCurrentIndex(0) return True return False def editor_modified(self, *args): tb = self.editor_tabs.tabBar() for i in xrange(self.editor_tabs.count()): editor = self.editor_tabs.widget(i) modified = getattr(editor, 'is_modified', False) tb.setTabIcon(i, self.modified_icon if modified else QIcon()) @property def current_editor(self): return self.editor_tabs.currentWidget() def save_state(self): tprefs.set('search-panel-visible', self.search_panel.isVisible()) self.search_panel.save_state() def restore_state(self): self.search_panel.setVisible(tprefs.get('search-panel-visible', False)) self.search_panel.restore_state() def show_find(self): self.search_panel.show_panel()
class Central(QStackedWidget): # {{{ ' The central widget, hosts the editors ' current_editor_changed = pyqtSignal() close_requested = pyqtSignal(object) def __init__(self, parent=None): QStackedWidget.__init__(self, parent) self.welcome = w = QLabel( '<p>' + _('Double click a file in the left panel to start editing' ' it.')) self.addWidget(w) w.setWordWrap(True) w.setAlignment(Qt.AlignTop | Qt.AlignHCenter) self.container = c = QWidget(self) self.addWidget(c) l = c.l = QVBoxLayout(c) c.setLayout(l) l.setContentsMargins(0, 0, 0, 0) self.editor_tabs = t = QTabWidget(c) l.addWidget(t) t.setDocumentMode(True) t.setTabsClosable(True) t.setMovable(True) pal = self.palette() if pal.color(pal.WindowText).lightness() > 128: i = QImage(I('modified.png')) i.invertPixels() self.modified_icon = QIcon(QPixmap.fromImage(i)) else: self.modified_icon = QIcon(I('modified.png')) self.editor_tabs.currentChanged.connect(self.current_editor_changed) self.editor_tabs.tabCloseRequested.connect(self._close_requested) self.search_panel = SearchPanel(self) l.addWidget(self.search_panel) self.restore_state() self.editor_tabs.tabBar().installEventFilter(self) def _close_requested(self, index): editor = self.editor_tabs.widget(index) self.close_requested.emit(editor) def add_editor(self, name, editor): fname = name.rpartition('/')[2] index = self.editor_tabs.addTab(editor, fname) self.editor_tabs.setTabToolTip(index, _('Full path:') + ' ' + name) editor.modification_state_changed.connect(self.editor_modified) @property def tab_order(self): ans = [] rmap = {v: k for k, v in iteritems(editors)} for i in range(self.editor_tabs.count()): name = rmap.get(self.editor_tabs.widget(i)) if name is not None: ans.append(name) return ans def rename_editor(self, editor, name): for i in range(self.editor_tabs.count()): if self.editor_tabs.widget(i) is editor: fname = name.rpartition('/')[2] self.editor_tabs.setTabText(i, fname) self.editor_tabs.setTabToolTip(i, _('Full path:') + ' ' + name) def show_editor(self, editor): self.setCurrentIndex(1) self.editor_tabs.setCurrentWidget(editor) def close_editor(self, editor): for i in range(self.editor_tabs.count()): if self.editor_tabs.widget(i) is editor: self.editor_tabs.removeTab(i) if self.editor_tabs.count() == 0: self.setCurrentIndex(0) return True return False def editor_modified(self, *args): tb = self.editor_tabs.tabBar() for i in range(self.editor_tabs.count()): editor = self.editor_tabs.widget(i) modified = getattr(editor, 'is_modified', False) tb.setTabIcon(i, self.modified_icon if modified else QIcon()) def close_current_editor(self): ed = self.current_editor if ed is not None: self.close_requested.emit(ed) def close_all_but_current_editor(self): self.close_all_but(self.current_editor) def close_all_but(self, ed): close = [] if ed is not None: for i in range(self.editor_tabs.count()): q = self.editor_tabs.widget(i) if q is not None and q is not ed: close.append(q) for q in close: self.close_requested.emit(q) @property def current_editor(self): return self.editor_tabs.currentWidget() def save_state(self): tprefs.set('search-panel-visible', self.search_panel.isVisible()) self.search_panel.save_state() for ed in itervalues(editors): ed.save_state() if self.current_editor is not None: self.current_editor.save_state( ) # Ensure the current editor saves it state last def restore_state(self): self.search_panel.setVisible(tprefs.get('search-panel-visible', False)) self.search_panel.restore_state() def show_find(self): self.search_panel.show_panel() def pre_fill_search(self, text): self.search_panel.pre_fill(text) def eventFilter(self, obj, event): base = super(Central, self) if obj is not self.editor_tabs.tabBar() or event.type( ) != QEvent.MouseButtonPress or event.button() not in (Qt.RightButton, Qt.MidButton): return base.eventFilter(obj, event) index = self.editor_tabs.tabBar().tabAt(event.pos()) if index < 0: return base.eventFilter(obj, event) if event.button() == Qt.MidButton: self._close_requested(index) ed = self.editor_tabs.widget(index) if ed is not None: menu = QMenu(self) menu.addAction(actions['close-current-tab'].icon(), _('Close tab'), partial(self.close_requested.emit, ed)) menu.addSeparator() menu.addAction(actions['close-all-but-current-tab'].icon(), _('Close other tabs'), partial(self.close_all_but, ed)) menu.exec_(self.editor_tabs.tabBar().mapToGlobal(event.pos())) return True
class Central(QStackedWidget): ' The central widget, hosts the editors ' current_editor_changed = pyqtSignal() close_requested = pyqtSignal(object) def __init__(self, parent=None): QStackedWidget.__init__(self, parent) self.welcome = w = QLabel( '<p>' + _('Double click a file in the left panel to start editing' ' it.')) self.addWidget(w) w.setWordWrap(True) w.setAlignment(Qt.AlignTop | Qt.AlignHCenter) self.container = c = QWidget(self) self.addWidget(c) l = c.l = QVBoxLayout(c) c.setLayout(l) l.setContentsMargins(0, 0, 0, 0) self.editor_tabs = t = QTabWidget(c) l.addWidget(t) t.setDocumentMode(True) t.setTabsClosable(True) t.setMovable(True) pal = self.palette() if pal.color(pal.WindowText).lightness() > 128: i = QImage(I('modified.png')) i.invertPixels() self.modified_icon = QIcon(QPixmap.fromImage(i)) else: self.modified_icon = QIcon(I('modified.png')) self.editor_tabs.currentChanged.connect(self.current_editor_changed) self.editor_tabs.tabCloseRequested.connect(self._close_requested) self.search_panel = SearchPanel(self) l.addWidget(self.search_panel) self.restore_state() def _close_requested(self, index): editor = self.editor_tabs.widget(index) self.close_requested.emit(editor) def add_editor(self, name, editor): fname = name.rpartition('/')[2] index = self.editor_tabs.addTab(editor, fname) self.editor_tabs.setTabToolTip(index, _('Full path:') + ' ' + name) editor.modification_state_changed.connect(self.editor_modified) def rename_editor(self, editor, name): for i in xrange(self.editor_tabs.count()): if self.editor_tabs.widget(i) is editor: fname = name.rpartition('/')[2] self.editor_tabs.setTabText(i, fname) self.editor_tabs.setTabToolTip(i, _('Full path:') + ' ' + name) def show_editor(self, editor): self.setCurrentIndex(1) self.editor_tabs.setCurrentWidget(editor) def close_editor(self, editor): for i in xrange(self.editor_tabs.count()): if self.editor_tabs.widget(i) is editor: self.editor_tabs.removeTab(i) if self.editor_tabs.count() == 0: self.setCurrentIndex(0) return True return False def editor_modified(self, *args): tb = self.editor_tabs.tabBar() for i in xrange(self.editor_tabs.count()): editor = self.editor_tabs.widget(i) modified = getattr(editor, 'is_modified', False) tb.setTabIcon(i, self.modified_icon if modified else QIcon()) @property def current_editor(self): return self.editor_tabs.currentWidget() def save_state(self): tprefs.set('search-panel-visible', self.search_panel.isVisible()) self.search_panel.save_state() def restore_state(self): self.search_panel.setVisible(tprefs.get('search-panel-visible', False)) self.search_panel.restore_state() def show_find(self): self.search_panel.show_panel() def pre_fill_search(self, text): self.search_panel.pre_fill(text)