def new_button(self): i = self.currentIndex() + 1 e = Editor() self.insertTab(i, e, '') b = QtWidgets.QToolButton() b.editor = e b.clicked.connect(self.close_tab) self.tabs.append(b) b.setText('x') l = QtWidgets.QLabel('Widget') self.tabs.append(l) tb = self.tabBar() tb.setTabButton(i, QtWidgets.QTabBar.RightSide, b) tb.setTabButton(i, QtWidgets.QTabBar.LeftSide, l)
def __init__(self, parent=None): super(PythonEditor, self).__init__(parent=parent) self.setObjectName('PythonEditor') self._parent = parent if parent is not None: self.setParent(parent) layout = QtWidgets.QVBoxLayout(self) layout.setObjectName('PythonEditor_MainLayout') layout.setContentsMargins(0, 0, 0, 0) self.tabeditor = tabs.TabEditor(self) self.editor = self.tabeditor.editor self.terminal = terminal.Terminal() splitter = QtWidgets.QSplitter(QtCore.Qt.Vertical) splitter.setObjectName('PythonEditor_MainVerticalSplitter') splitter.addWidget(self.terminal) splitter.addWidget(self.tabeditor) layout.addWidget(splitter) self.splitter = splitter act = actions.Actions( pythoneditor=self, editor=self.editor, tabeditor=self.tabeditor, terminal=self.terminal, ) sch = shortcuts.ShortcutHandler( editor=self.editor, tabeditor=self.tabeditor, terminal=self.terminal, ) self.menubar = menubar.MenuBar(self) SE = shortcuteditor.ShortcutEditor self.shortcuteditor = SE(editor=self.editor, tabeditor=self.tabeditor, terminal=self.terminal) PE = preferences.PreferencesEditor self.preferenceseditor = PE() # Loading the AutosaveManager will also load # all the contents of the autosave into tabs. AM = autosavexml.AutoSaveManager self.filehandler = AM(self.tabeditor)
def __init__(self, knobs): super(PyKnobs, self).__init__() self.knobs = knobs self._knob = knobs[0] self.layout = QtWidgets.QVBoxLayout(self) self.knobChooser = QtWidgets.QComboBox() self.knobChooser.addItems([k.name() for k in knobs]) self.editor = PyKnobEdit(self._knob) self.layout.addWidget(self.knobChooser) self.layout.addWidget(self.editor) self.knobChooser.currentIndexChanged.connect(self.updateKnob)
def set_external_editor_path(path=None, ask_user=False): """ Prompts the user for a new external editor path. TODO: Set temp program if none found. """ root, editor_elements = get_editor_xml() for e in editor_elements: root.remove(e) if ask_user and not path: from PythonEditor.ui.Qt import QtWidgets dialog = QtWidgets.QInputDialog() args = (dialog, u'Get Editor Path', u'Path to external text editor:') results = QtWidgets.QInputDialog.getText(*args) path, ok = results if not ok: msg = 'Certain features will not work without '\ 'an external editor. \nYou can add or change '\ 'an external editor path later in Edit > Preferences.' msgBox = QtWidgets.QMessageBox() msgBox.setText(msg) msgBox.exec_() return None if path and os.path.isdir(os.path.dirname(path)): editor_path = path os.environ['EXTERNAL_EDITOR_PATH'] = editor_path element = ETree.Element('external_editor_path') element.text = path root.append(element) writexml(root) return path elif ask_user: from PythonEditor.ui.Qt import QtWidgets msg = u'External editor not found. '\ 'Certain features will not work.'\ '\nYou can add or change an external '\ 'editor path later in Edit > Preferences.' msgBox = QtWidgets.QMessageBox() msgBox.setText(msg) msgBox.exec_() return None
def prompt_user_to_save(self, index): """ Ask the user if they wish to close a tab that has unsaved contents. """ name = self.tabText(index) msg_box = QtWidgets.QMessageBox() msg_box.setWindowTitle('Save changes?') msg_box.setText('%s has not been saved to a file.' % name) msg_box.setInformativeText('Do you want to save your changes?') buttons = (msg_box.Save | msg_box.Discard | msg_box.Cancel) msg_box.setStandardButtons(buttons) msg_box.setDefaultButton(msg_box.Save) ret = msg_box.exec_() user_cancelled = (ret == msg_box.Cancel) if (ret == msg_box.Save): data = self.tabData(index) path = save.save(data['text'], data['path']) if path is None: user_cancelled = True if user_cancelled: return False return True
def setup_new_tab_btn(self): """ Adds a new tab [+] button to the right of the tabs. """ widget = QtWidgets.QWidget() widget.setObjectName('Tab_Widget_New_Button') self.insertTab(0, widget, '') nb = self.new_btn = QtWidgets.QToolButton() nb.setMinimumSize(QtCore.QSize(50, 10)) nb.setText('+') # you could set an icon instead of text nb.setAutoRaise(True) nb.clicked.connect(self.new_tab) tabBar = self.tabBar() tabBar.setTabButton(0, QtWidgets.QTabBar.RightSide, nb) tabBar.setTabEnabled(0, False)
def construct_ui(self): layout = QtWidgets.QVBoxLayout(self) layout.setObjectName('PythonEditor_MainLayout') layout.setContentsMargins(0, 0, 0, 0) self.tabeditor = tabs.TabEditor(self) self.editor = self.tabeditor.editor self.terminal = terminal.Terminal() self.menubar = menubar.MenuBar(self) splitter = QtWidgets.QSplitter(QtCore.Qt.Vertical) splitter.setObjectName('PythonEditor_MainVerticalSplitter') splitter.addWidget(self.terminal) splitter.addWidget(self.tabeditor) layout.addWidget(splitter)
def __init__(self, parent=None): super(IDE, self).__init__(parent) self.setLayout(QtWidgets.QHBoxLayout(self)) self.layout().setContentsMargins(0, 0, 0, 0) self.setObjectName('IDE') self.setWindowTitle('Python Editor') self.buildUI()
def _show_name_edit(self, index): """ Shows a QLineEdit widget where the tab text is, allowing renaming of tabs. """ rect = self.tabRect(index) label = self.tabText(index) self.renaming_label = label self.tab_text = label self.tab_index = index self.name_edit = QtWidgets.QLineEdit(self) self.name_edit.resize(rect.width(), rect.height() - 7) self.name_edit.tab_index = index self.name_edit.tab_text = label self.name_edit.editingFinished.connect(self.rename_tab) self.name_edit.setText(label.strip()) self.name_edit.selectAll() self.name_edit.show() self.name_edit.raise_() p = rect.topLeft() self.name_edit.move(p.x(), p.y() + 5) self.name_edit.setFocus(QtCore.Qt.MouseFocusReason)
def __init__(self): QtWidgets.QTabWidget.__init__(self) self.setTabBar(TabBar(self)) self.setTabsClosable(True) self.user_cancelled_tab_close = False self.setTabShape(QtWidgets.QTabWidget.Rounded) self.tab_count = 0 self.current_index = 0 tabBar = self.tabBar() tabBar.setMovable(True) tabBar.tabMoved.connect(self.tab_restrict_move, QtCore.Qt.DirectConnection) self.setup_new_tab_btn() self.tabCloseRequested.connect(self.close_tab) self.reset_tab_signal.connect(self.reset_tabs) self.currentChanged.connect(self.widget_changed) self.setStyleSheet("QTabBar::tab { height: 24px; }") # add tab list button self.corner_button = QtWidgets.QPushButton(':') self.corner_button.setFixedSize(24, 24) self.corner_button.setStyleSheet("border: 5px solid black") self.corner_button.clicked.connect(self.show_tab_menu) self.setCornerWidget(self.corner_button, corner=QtCore.Qt.TopRightCorner)
def show_name_edit(self): """ Shows a QLineEdit widget where the tab text is, allowing renaming of tabs. """ self.rename_tab() editor = self.edittabs.currentWidget() if not editor.objectName() == 'Editor': return index = self.currentIndex() button = self.tabButton(index, QtWidgets.QTabBar.LeftSide) if isinstance(button, TabButton): label = button.text() else: label = self.tabText(index) self.editor = editor self.tab_text = label self.tab_index = index self.setTabText(index, '') self.name_edit = QtWidgets.QLineEdit(self) self.name_edit.editingFinished.connect(self.rename_tab) self.name_edit.setText(label) self.name_edit.selectAll() self.setTabButton(index, QtWidgets.QTabBar.LeftSide, self.name_edit) self.name_edit.setFocus(QtCore.Qt.MouseFocusReason)
def __init__(self): super(VisualDebug, self).__init__() self.layout = QtWidgets.QGridLayout(self) self.setMinimumWidth(900) self.setWindowFlags(QtCore.Qt.WindowStaysOnTopHint) self.treeview = WidgetTreeView() self.treemodel = QtGui.QStandardItemModel() self.treeview.setModel(self.treemodel) self.treeview.setUniformRowHeights(True) self.layout.addWidget(self.treeview) self.treemodel.setHorizontalHeaderLabels([ 'metaObject className', 'objectName', 'windowTitle', 'text', 'title', '__repr__', ]) self.treeview.header().setStretchLastSection(False) mode = QtWidgets.QHeaderView.ResizeToContents try: self.treeview.header().setResizeMode(mode) except AttributeError: # setResizeMode not supported in PyQt pass rootItem = self.treemodel.invisibleRootItem() qApp = QtWidgets.QApplication.instance() for w in qApp.topLevelWidgets(): # extra stuff self.recurseWidgets(w, rootItem)
def __init__(self): super(PreferencesEditor, self).__init__() self.setObjectName('PythonEditorPreferences') self.layout = QtWidgets.QVBoxLayout(self) self.setWindowTitle('Python Editor Preferences') self.build_layout() self.connect_signals()
def setup_menu(self): """ Adds top menu bar and various menu items. """ menu_bar = QtWidgets.QMenuBar(self.widget) file_menu = QtWidgets.QMenu('File') help_menu = QtWidgets.QMenu('Help') edit_menu = QtWidgets.QMenu('Edit') for menu in [file_menu, edit_menu, help_menu]: menu_bar.addMenu(menu) file_menu.addAction('New', self.new) file_menu.addAction('Open', self.open) file_menu.addAction('&Save', self.save) file_menu.addAction('Save As', self.save) export_menu = QtWidgets.QMenu('Export') file_menu.addMenu(export_menu) ex = export_menu.addAction ex('Save Selected Text', self.save_selected_text) ex('Export Selected To External Editor', self.export_selected_to_external_editor) ex('Export Current Tab To External Editor', self.export_current_tab_to_external_editor) ex('Export All Tabs To External Editor', self.export_all_tabs_to_external_editor) help_menu.addAction('Reload Python Editor', self.widget._parent.reload_package) help_menu.addAction('About Python Editor', self.show_about_dialog) edit_menu.addAction('Preferences', self.show_preferences) edit_menu.addAction('Shortcuts', self.show_shortcuts) self.widget.layout().addWidget(menu_bar)
def test_toggle_backslashes(qtbot): editor = QtWidgets.QPlainTextEdit() test_path = "c:\\path/to\\some\\file.jpg" editor.setPlainText(test_path) textCursor = editor.textCursor() textCursor.setPosition(0, QtGui.QTextCursor.MoveAnchor) editor.setTextCursor(textCursor) actions.toggle_backslashes(editor) assert editor.toPlainText() == "c:/path/to/some/file.jpg"
def show_popup_bar(self): #editor = _ide.python_editor.editor #layout = _ide.python_editor.tabeditor.layout() editor = self.editor layout = self.tabeditor.layout() # first remove any previous widgets name = 'Document out of sync warning' for i in range(layout.count()): item = layout.itemAt(i) if item is None: continue widget = item.widget() if widget.objectName() != name: continue layout.removeItem(item) widget.deleteLater() popup_bar = QtWidgets.QWidget() popup_bar.setObjectName('Document out of sync warning') bar_layout = QtWidgets.QHBoxLayout(popup_bar) l = QtWidgets.QLabel() l.setText('This tab is out of sync with the autosave.') new_button = QtWidgets.QPushButton('Load into New Tab') save_button = QtWidgets.QPushButton('Save This Version') update_button = QtWidgets.QPushButton('Update From Autosave') diff_button = QtWidgets.QPushButton('Show Diff') stylesheet = """ QPushButton { background-color: #444; } QPushButton:hover { background-color: orange; } """ for b in new_button, save_button, update_button, diff_button: #b.setFlat(True) b.setStyleSheet(stylesheet) for b in l, new_button, save_button, update_button, diff_button: bar_layout.addWidget(b) layout.insertWidget(1, popup_bar) popup_bar.setMaximumHeight(0) #print popup_bar.maximumHeight() #popup_bar.setMaximumHeight(46) def anim_popup_bar(popup_bar): anim = QtCore.QPropertyAnimation( popup_bar, 'maximumHeight' ) anim.setStartValue(0) anim.setEndValue(46) anim.setDuration(400) anim.start() anim_popup_bar.anim = anim anim_popup_bar(popup_bar)
def __init__(self, parent=None): super(TabEditor, self).__init__(parent) if parent is not None: self.setParent(parent) self.setLayout(QtWidgets.QVBoxLayout(self)) self.layout().setContentsMargins(0, 0, 0, 0) self.tab_widget = QtWidgets.QWidget() twl = QtWidgets.QHBoxLayout(self.tab_widget) self.tab_widget_layout = twl self.tab_widget_layout.setContentsMargins(0, 0, 0, 0) self.tabs = Tabs() self.tab_widget_layout.addWidget(self.tabs) # add corner buttons tb = QtWidgets.QToolButton() self.tab_list_button = tb tb.setArrowType(QtCore.Qt.DownArrow) tb.setToolTip('Click for a list of tabs.') tb.setAutoRaise(True) tb.setFixedSize(24, 24) self.tab_list_button.clicked.connect(self.show_tab_menu) nb = QtWidgets.QToolButton() self.new_tab_button = nb nb.setToolTip('Click to add a new tab.') nb.setText('+') nb.setAutoRaise(True) self.new_tab_button.clicked.connect(self.new_tab) for button in [self.new_tab_button, self.tab_list_button]: self.tab_widget_layout.addWidget(button) self.editor = editor.Editor(handle_shortcuts=False) for widget in self.tab_widget, self.editor: self.layout().addWidget(widget) # Give the autosave a chance to load all # tabs before connecting signals between # tabs and editor. QtCore.QTimer.singleShot(0, self.connect_signals)
def set_model(self, path): model = QtWidgets.QFileSystemModel() model.setRootPath(path) model.setNameFilterDisables(False) model.setNameFilters(['*.py', '*.txt', '*.md']) self.setModel(model) RTC = QtWidgets.QHeaderView.ResizeToContents self.header().setResizeMode(RTC) self.setRootIndex(model.index(path))
def mousePressEvent(self, event): if event.button() == QtCore.Qt.LeftButton: super(FileTree, self).mousePressEvent(event) if event.button() == QtCore.Qt.RightButton: menu = QtWidgets.QMenu() menu.addAction('New', 'print "does nothing"') menu.addAction('Delete', 'print "does nothing"') cursor = QtGui.QCursor() pos = cursor.pos() menu.exec_(pos)
def __init__(self, path): QtWidgets.QDialog.__init__(self) self.setWindowTitle('Nuke Mini Browser') self._layout = QtWidgets.QVBoxLayout() self.setLayout(self._layout) self.resize(400, 320) self.file_tree = FileTree(path) self._layout.addWidget(self.file_tree)
def show_about_dialog(self): """ Shows an about dialog with version information. TODO: Make it a borderless splash screen, centred, nice text, major and minor version numbers set in one place in the project. """ msg = 'Python Editor version {0} by Max Last'.format(__version__) self.about_dialog = QtWidgets.QLabel(msg) self.about_dialog.show()
def __init__(self): super(SingleTab, self).__init__() l = LoaderList() self.l = l root, subscripts = autosavexml.parsexml('subscript') for s in subscripts: name = s.attrib.get('name') a = s.attrib.copy() a['text'] = s.text l[name] = a self.t = edittabs.EditTabs() self.l.emit_tab.connect(self.receive_tab) self._layout = QtWidgets.QHBoxLayout(self) self.splitter = QtWidgets.QSplitter(self) self._layout.addWidget(self.splitter) self.setLayout(self._layout) self.splitter.addWidget(self.l) self.splitter.addWidget(self.t)
def __init__(self): super(ObjectInspector, self).__init__() self.layout = QtWidgets.QGridLayout(self) self.setMinimumWidth(900) self.setWindowFlags(QtCore.Qt.WindowStaysOnTopHint) self.treeview = QtWidgets.QTreeView() self.treemodel = QtGui.QStandardItemModel() self.treeview.setModel(self.treemodel) self.treeview.setUniformRowHeights(True) self.layout.addWidget(self.treeview) self.treemodel.setHorizontalHeaderLabels(['object name', 'object']) self.treeview.header().setStretchLastSection(False) mode = QtWidgets.QHeaderView.ResizeToContents self.treeview.header().setResizeMode(mode) self.load_globals() self.start_timer()
def show_tab_menu(self): """ Show a list of tabs and go to the tab clicked. """ menu = QtWidgets.QMenu() from functools import partial for i in range(self.count()): tab_name = self.tabText(i) if not tab_name.strip(): button = self.tabBar().tabButton(i, QtWidgets.QTabBar.LeftSide) if not isinstance(button, TabButton): continue tab_name = button.text() action = partial(self.setCurrentIndex, i) menu.addAction(tab_name, action) menu.exec_(QtGui.QCursor().pos())
def mouseReleaseEvent(self, event): self.tab_pressed = False i = self.tabAt(event.pos()) if event.button() == QtCore.Qt.LeftButton: if i == -1: i = self.currentIndex() if (i != self.start_move_index): self.tab_repositioned_signal.emit(i, self.start_move_index) self.handle_close_button_display(event) elif event.button() == QtCore.Qt.RightButton: menu = QtWidgets.QMenu() rename = partial(self._show_name_edit, i) menu.addAction('Rename', rename) move_to_first = partial(self.move_to_first, i) menu.addAction('Move Tab to First', move_to_first) move_to_last = partial(self.move_to_last, i) menu.addAction('Move Tab to Last', move_to_last) close_tab_func = partial(self.removeTab, i) menu.addAction('Close Tab', close_tab_func) copy_file_path = partial(self.copy_tab_file_path, i) menu.addAction('Copy File Path', copy_file_path) # Other ideas (TODO) """ menu.addAction('Close Other Tabs', ) menu.addAction('Close Tabs to Right', ) menu.addAction('Close Tabs to Left', ) menu.addAction('Pin Tab', ) """ menu.exec_(QtGui.QCursor().pos()) elif event.button() == QtCore.Qt.MiddleButton: if i != -1: self.removeTab(i) return super(Tabs, self).mouseReleaseEvent(event)
def show_tab_menu(self): """ Show a list of tabs and go to the tab clicked. """ menu = QtWidgets.QMenu() current_index = self.tabs.currentIndex() from functools import partial for i in range(self.tabs.count()): tab_name = self.tabs.tabText(i) if not tab_name.strip(): continue func = partial(self.tabs.setCurrentIndex, i) action = menu.addAction(tab_name, func) if i == current_index: font = action.font() font.setBold(True) font.setUnderline(True) action.setFont(font) menu.setActiveAction(action) menu.exec_(QtGui.QCursor().pos())
def menu_setup(self): """ Adds top menu bar and various menu items based on a json config file. """ self.menu = QtWidgets.QMenuBar(self.pythoneditor) names = [ 'File', 'Edit', 'View', 'Tools', 'Find', 'Selection', 'Preferences', 'Help', ] for name in names: self.menu.addMenu(name) for widget, action_name, attributes in actions.class_actions(self): location = attributes.get('Menu Location') if location is None: continue for action in widget.actions(): if action.text() != action_name: continue break else: continue menu = self.menu if location.strip(): for name in location.split('/'): item = actions.find_menu_item(menu, name) if item is None: item = menu.addMenu(name) menu = item menu.addAction(action) self.pythoneditor.layout().insertWidget(0, self.menu)
def main(): app = QtWidgets.QApplication.instance() if not app: app = QtWidgets.QApplication(sys.argv) for widget in app.allWidgets(): if widget.objectName() == 'IDE': widget.close() PDF = 'PYTHONEDITOR_DEFAULT_FONT' fontbase = QtGui.QFontDatabase() current_folder = os.path.dirname(__file__) user_font_file = os.path.join(current_folder, 'scripts', 'fonts', 'DejaVu Sans Mono for Powerline.ttf') fontbase.addApplicationFont(user_font_file) os.environ[PDF] = 'DejaVu Sans Mono for Powerline' _ide = ide.IDE() _ide.setParent(app.activeWindow()) _ide.setWindowFlags(QtCore.Qt.Window) _ide.setPalette(ui_palette.get_palette_style()) # Plastique isn't available on Windows, so try multiple styles. styles = QtWidgets.QStyleFactory.keys() style_found = False for style_name in ['Plastique', 'Fusion']: if style_name in styles: print('Setting style to:', style_name) style_found = True break if style_found: style = QtWidgets.QStyleFactory.create(style_name) _ide.setStyle(style) print('PythonEditor import time: %.04f seconds' % (time.time() - start)) #_ide.showMaximized() _ide.show() if app.applicationName() in ['python', 'mayapy', 'UE4Editor']: sys.exit(app.exec_())
def build_layout(self): """ Create the layout. """ layout = QtWidgets.QVBoxLayout(self) layout.setContentsMargins(0, 0, 0, 0) # self.setup_menu() self.menubar = menubar.MenuBar(self) left_widget = QtWidgets.QWidget() left_layout = QtWidgets.QVBoxLayout(left_widget) path_edit = QtWidgets.QLineEdit() path_edit.textChanged.connect(self.update_tree) self.path_edit = path_edit splitter = QtWidgets.QSplitter(QtCore.Qt.Horizontal) self.splitter = splitter self.xpanded = False self.setLayout(layout) self.tool_button = QtWidgets.QToolButton() self.tool_button.setText('<') self.tool_button.clicked.connect(self.xpand) self.tool_button.setMaximumWidth(20) layout.addWidget(splitter) browse = browser.FileTree(NUKE_DIR) self.browser = browse left_layout.addWidget(self.path_edit) left_layout.addWidget(self.browser) self.tabs = edittabs.EditTabs() widgets = [left_widget, self.tool_button, self.tabs] for w in widgets: splitter.addWidget(w) splitter.setSizes([200, 10, 800]) self.install_features() self.check_modified_tabs() if self.tabs.count() == 0: self.tabs.new_tab()
def build_layout(self): """ Create the layout. """ layout = QtWidgets.QVBoxLayout(self) layout.setContentsMargins(0, 0, 0, 0) # self.setup_menu() self.read_only = True self.menubar = menubar.MenuBar(self) left_widget = QtWidgets.QWidget() left_layout = QtWidgets.QVBoxLayout(left_widget) path_edit = QtWidgets.QLineEdit() path_edit.textChanged.connect(self.update_tree) self.path_edit = path_edit splitter = QtWidgets.QSplitter(QtCore.Qt.Horizontal) self.splitter = splitter self.xpanded = False self.setLayout(layout) self.tool_button = QtWidgets.QToolButton() self.tool_button.setText('<') self.tool_button.clicked.connect(self.xpand) self.tool_button.setMaximumWidth(20) layout.addWidget(splitter) browse = browser.FileTree(NUKE_DIR) self.browser = browse left_layout.addWidget(self.path_edit) left_layout.addWidget(self.browser) self.editor = editor.Editor(handle_shortcuts=True) self.editor.path = 'C:/Users/tsalx/Desktop/temp_editor_save.py' widgets = [left_widget, self.tool_button, self.editor] for w in widgets: splitter.addWidget(w) splitter.setSizes([200, 10, 800]) self.browser.path_signal.connect(self.read) self.editor.textChanged.connect(self.write) self.editor.modificationChanged.connect(self.handle_changed)