def __init__(self, original=False): super(ComboEditor, self).__init__() self.__original = original self._symbols_index = [] vbox = QVBoxLayout(self) vbox.setContentsMargins(0, 0, 0, 0) vbox.setSpacing(0) self.bar = ActionBar() vbox.addWidget(self.bar) self.stacked = QStackedLayout() vbox.addLayout(self.stacked) self._main_container = IDE.get_service('main_container') self.connect(self.bar, SIGNAL("changeCurrent(PyQt_PyObject)"), self.set_current) self.connect(self.bar, SIGNAL("runFile(QString)"), self._run_file) self.connect(self.bar, SIGNAL("addToProject(QString)"), self._add_to_project) self.connect(self.bar, SIGNAL("goToSymbol(int)"), self._go_to_symbol) self.connect(self.bar, SIGNAL("reopenTab(QString)"), lambda path: self._main_container.open_file(path)) self.connect(self.bar, SIGNAL("recentTabsModified()"), lambda: self._main_container.recent_files_changed()) self.connect(self.bar.code_navigator.btnPrevious, SIGNAL("clicked()"), lambda: self._navigate_code(False)) self.connect(self.bar.code_navigator.btnNext, SIGNAL("clicked()"), lambda: self._navigate_code(True))
def __init__(self, parent=None): super(_MainContainer, self).__init__(parent) self._parent = parent self.stack = QStackedLayout(self) self.stack.setStackingMode(QStackedLayout.StackAll) self.splitter = dynamic_splitter.DynamicSplitter() self.setAcceptDrops(True) self.files_handler = files_handler.FilesHandler(self) #documentation browser self.docPage = None #Code Navigation self._locator = locator.GoToDefinition() self.__codeBack = [] self.__codeForward = [] self.__bookmarksFile = '' self.__bookmarksPos = -1 self.__breakpointsFile = '' self.__breakpointsPos = -1 self.__operations = { 0: self._navigate_code_jumps, 1: self._navigate_bookmarks, 2: self._navigate_breakpoints} self.connect(self, SIGNAL("locateFunction(QString, QString, bool)"), self.locate_function) IDE.register_service('main_container', self) #Register signals connections connections = ( {'target': 'menu_file', 'signal_name': 'openFile(QString)', 'slot': self.open_file}, {'target': 'explorer_container', 'signal_name': 'goToDefinition(int)', 'slot': self.editor_go_to_line}, {'target': 'explorer_container', 'signal_name': 'pep8Activated(bool)', 'slot': self.reset_pep8_warnings}, {'target': 'explorer_container', 'signal_name': 'lintActivated(bool)', 'slot': self.reset_lint_warnings}, ) IDE.register_signals('main_container', connections) self.selector = main_selector.MainSelector(self) self.add_widget(self.selector) if settings.SHOW_START_PAGE: self.show_start_page() self.connect(self.selector, SIGNAL("changeCurrent(int)"), self._change_current_stack) self.connect(self.selector, SIGNAL("ready()"), self._selector_ready)
def setGeometry(self, rect): QStackedLayout.setGeometry(self, rect) for i in range(self.count()): w = self.widget(i) hint = w.sizeHint() geom = QRect(rect) size = clipMinMax(rect.size(), w.minimumSize(), w.maximumSize()) size = fixSizePolicy(size, hint, w.sizePolicy()) geom.setSize(size) if geom != w.geometry(): w.setGeometry(geom)
def __init__(self): super(ComboTabs, self).__init__() vbox = QVBoxLayout(self) vbox.setContentsMargins(0, 0, 0, 0) self.bar = ActionBar() vbox.addWidget(self.bar) self.stacked = QStackedLayout() self.editable = neditable.NEditable('') self.editor_widget = editor.create_editor(self.editable) self.stacked.addWidget(self.editor_widget) vbox.addLayout(self.stacked)
def __init__(self, editor): super(CodeCompletionWidget, self).__init__(None, Qt.FramelessWindowHint | Qt.ToolTip) self._editor = editor self._revision = 0 self._block = 0 self.stack_layout = QStackedLayout(self) self.stack_layout.setContentsMargins(0, 0, 0, 0) self.stack_layout.setSpacing(0) self.completion_list = QListWidget() self.completion_list.setMinimumHeight(200) self.completion_list.setAlternatingRowColors(True) self._list_index = self.stack_layout.addWidget(self.completion_list) self._icons = { 'a': resources.IMAGES['attribute'], 'f': resources.IMAGES['function'], 'c': resources.IMAGES['class'], 'm': resources.IMAGES['module'] } self.cc = code_completion.CodeCompletion() self._completion_results = {} self._prefix = '' self.setVisible(False) self.source = '' self._key_operations = { Qt.Key_Up: self._select_previous_row, Qt.Key_Down: self._select_next_row, Qt.Key_PageUp: (lambda: self._select_previous_row(6)), Qt.Key_PageDown: (lambda: self._select_next_row(6)), Qt.Key_Right: lambda: None, Qt.Key_Left: lambda: None, Qt.Key_Enter: self.pre_key_insert_completion, Qt.Key_Return: self.pre_key_insert_completion, Qt.Key_Tab: self.pre_key_insert_completion, Qt.Key_Space: self.hide_completer, Qt.Key_Escape: self.hide_completer, Qt.Key_Backtab: self.hide_completer, Qt.NoModifier: self.hide_completer, Qt.ShiftModifier: self.hide_completer, } self.desktop = QApplication.instance().desktop() self.connect(self.completion_list, SIGNAL("itemClicked(QListWidgetItem*)"), self.pre_key_insert_completion) self.connect(self._editor.document(), SIGNAL("cursorPositionChanged(QTextCursor)"), self.update_metadata)
def __init__(self, parent=None): super(CenterView, self).__init__(parent) layout = QVBoxLayout() self.setLayout(layout) self.center = QStackedLayout() self.camview = widgets.CamView((640, 480), self, draw_logo=True) self.label_up = QLabel() self.label_down = QLabel() self.center.addWidget(self.camview) layout.addLayout(self.center) layout.addWidget(self.label_up) layout.addWidget(self.label_down) self.adjustSize() self.setFixedSize(self.sizeHint())
def __init__(self, original=False): super(ComboEditor, self).__init__(None, Qt.WindowStaysOnTopHint) self.__original = original self.__undocked = [] self._symbols_index = [] vbox = QVBoxLayout(self) vbox.setContentsMargins(0, 0, 0, 0) vbox.setSpacing(0) self.bar = ActionBar(main_combo=original) vbox.addWidget(self.bar) self.stacked = QStackedLayout() vbox.addLayout(self.stacked) self._main_container = IDE.get_service('main_container') if not self.__original: self.connect(self._main_container, SIGNAL("fileOpened(QString)"), self._file_opened_by_main) self.connect(self.bar.combo, SIGNAL("showComboSelector()"), lambda: self.emit(SIGNAL("showComboSelector()"))) self.connect(self.bar, SIGNAL("changeCurrent(PyQt_PyObject, int)"), self._set_current) self.connect(self.bar, SIGNAL("splitEditor(bool)"), self.split_editor) self.connect(self.bar, SIGNAL("runFile(QString)"), self._run_file) self.connect(self.bar, SIGNAL("closeSplit()"), lambda: self.emit(SIGNAL("closeSplit(PyQt_PyObject)"), self)) self.connect(self.bar, SIGNAL("addToProject(QString)"), self._add_to_project) self.connect(self.bar, SIGNAL("showFileInExplorer(QString)"), self._show_file_in_explorer) self.connect(self.bar, SIGNAL("goToSymbol(int)"), self._go_to_symbol) self.connect(self.bar, SIGNAL("undockEditor()"), self.undock_editor) self.connect(self.bar, SIGNAL("reopenTab(QString)"), lambda path: self._main_container.open_file(path)) self.connect(self.bar, SIGNAL("recentTabsModified()"), lambda: self._main_container.recent_files_changed()) self.connect(self.bar.code_navigator.btnPrevious, SIGNAL("clicked()"), lambda: self._navigate_code(False)) self.connect(self.bar.code_navigator.btnNext, SIGNAL("clicked()"), lambda: self._navigate_code(True))
def __init__(self, parent=None): super(_MainContainer, self).__init__(parent) self._parent = parent self.stack = QStackedLayout(self) self.stack.setStackingMode(QStackedLayout.StackAll) self.splitter = dynamic_splitter.DynamicSplitter() self.setAcceptDrops(True) self.tabs_handler = tabs_handler.TabsHandler(self) #documentation browser self.docPage = None #Code Navigation self._locator = locator.GoToDefinition() self.__codeBack = [] self.__codeForward = [] self.__bookmarksFile = '' self.__bookmarksPos = -1 self.__breakpointsFile = '' self.__breakpointsPos = -1 self.__operations = { 0: self._navigate_code_jumps, 1: self._navigate_bookmarks, 2: self._navigate_breakpoints} self.connect(self, SIGNAL("locateFunction(QString, QString, bool)"), self.locate_function) IDE.register_service('main_container', self) #Register signals connections connections = ( {'target': 'menu_file', 'signal_name': 'openFile(QString)', 'slot': self.open_file}, {'target': 'explorer_container', 'signal_name': 'goToDefinition(int)', 'slot': self.editor_go_to_line}, {'target': 'explorer_container', 'signal_name': 'pep8Activated(bool)', 'slot': self.reset_pep8_warnings}, {'target': 'explorer_container', 'signal_name': 'lintActivated(bool)', 'slot': self.reset_lint_warnings}, ) IDE.register_signals('main_container', connections) self.selector = main_selector.MainSelector(self) self.add_widget(self.selector) if settings.SHOW_START_PAGE: self.show_start_page() self.connect(self.selector, SIGNAL("changeCurrent(int)"), self._change_current_stack) self.connect(self.selector, SIGNAL("ready()"), self._selector_ready)
class ComboTabs(QWidget): def __init__(self): super(ComboTabs, self).__init__() vbox = QVBoxLayout(self) vbox.setContentsMargins(0, 0, 0, 0) self.bar = ActionBar() vbox.addWidget(self.bar) self.stacked = QStackedLayout() self.editable = neditable.NEditable('') self.editor_widget = editor.create_editor(self.editable) self.stacked.addWidget(self.editor_widget) vbox.addLayout(self.stacked) def currentWidget(self): return self.editor_widget
class ComboEditor(QWidget): def __init__(self, original=False): super(ComboEditor, self).__init__() self.__original = original vbox = QVBoxLayout(self) vbox.setContentsMargins(0, 0, 0, 0) self.bar = ActionBar() self.connect(self.bar, SIGNAL("changeCurrent(PyQt_PyObject)"), self.set_current) vbox.addWidget(self.bar) self.stacked = QStackedLayout() vbox.addLayout(self.stacked) def currentWidget(self): return self.stacked.currentWidget() def add_editor(self, neditable): """Add Editor Widget to the UI area.""" if neditable.editor: self.stacked.addWidget(neditable.editor) self.bar.add_item(neditable.display_name, neditable) # Editor Signals self.connect(neditable.editor, SIGNAL("cursorPositionChanged()"), self._update_cursor_position) # Connect file system signals only in the original if self.__original: pass def set_current(self, neditable): self.stacked.setCurrentWidget(neditable.editor) self._update_cursor_position(ignore_sender=True) neditable.editor.setFocus() def widget(self, index): return self.stacked.widget(index) def count(self): """Return the number of editors opened.""" return self.stacked.count() def _update_cursor_position(self, ignore_sender=False): obj = self.sender() editor = self.stacked.currentWidget() # Check if it's current to avoid signals from other splits. if ignore_sender or editor == obj: line = editor.textCursor().blockNumber() + 1 col = editor.textCursor().columnNumber() self.bar.update_line_col(line, col)
def sizeHint(self): current = self.currentWidget() if current: hint = current.sizeHint() # Clip the hint with min/max sizes. hint = clipMinMax(hint, current.minimumSize(), current.maximumSize()) return hint else: return QStackedLayout.sizeHint(self)
def __init__(self): QMainWindow.__init__(self) layout = QGridLayout(self) layout.setMargin(2) btnFiles = QPushButton(u'Файлы', self) btnVideo = QPushButton(u'Видео', self) btnPlay = QPushButton(u'Play/Pause', self) btnStop = QPushButton(u'Stop', self) btnMute = QPushButton(u'Mute', self) btnMute.setCheckable(True) btnMainMenu = QPushButton(u'Main', self) self.sldVolume = QSlider(Qt.Vertical, self) self.sldPosition = QSlider(Qt.Horizontal, self) self.layMain = QStackedLayout() btnFiles.setSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed) btnVideo.setSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed) btnPlay.setSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed) btnStop.setSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed) btnMute.setSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed) btnMainMenu.setSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed) self.sldVolume.setSizePolicy(QSizePolicy.Fixed, QSizePolicy.Expanding) self.sldPosition.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed) layout.addWidget(btnFiles, 0, 0) layout.addWidget(btnVideo, 0, 1) layout.addWidget(btnPlay, 0, 3) layout.addWidget(btnStop, 0, 4) layout.addWidget(btnMute, 0, 5) layout.addWidget(btnMainMenu, 2, 5) layout.addWidget(self.sldVolume, 1, 5) layout.addWidget(self.sldPosition, 2, 0, 1, 5) layout.addLayout(self.layMain, 1, 0, 1, 5) fileBrowser = CFileBrowser(self) self.videoWidget = QWidget(self) self.exitMenu = CExitMenu(self) self.mplayer = MPlayerControl(self, self.videoWidget) fileBrowser.chosen.connect(self.startPlay) btnFiles.clicked.connect(lambda: self.selectMode(0)) btnVideo.clicked.connect(lambda: self.selectMode(1)) btnMainMenu.clicked.connect(lambda: self.selectMode(2)) self.sldPosition.valueChanged.connect(self.mplayer.seek) self.sldVolume.valueChanged.connect(self.mplayer.setvol) btnMute.clicked.connect(lambda: self.mplayer.mute(btnMute.isChecked())) btnPlay.clicked.connect(self.mplayer.play) btnStop.clicked.connect(self.mplayer.stop) self.sldVolume.setValue(QtGui.qApp.settings['volume']) self.mplayer.percent_position.connect(self.on_mplayer_position) self.layMain.addWidget(fileBrowser) self.layMain.addWidget(self.videoWidget) self.layMain.addWidget(self.exitMenu)
def __init__(self, config, network, storage, app): QDialog.__init__(self) self.app = app self.config = config self.network = network self.storage = storage self.setMinimumSize(575, 400) self.setMaximumSize(575, 400) self.setWindowTitle('Electrum-VCN' + ' - ' + _('Install Wizard')) self.connect(self, QtCore.SIGNAL('accept'), self.accept) self.stack = QStackedLayout() self.setLayout(self.stack)
def setupUi(self, option): option.setWindowTitle(QApplication.translate("option", "Option")) main_layout = QGridLayout(option) main_layout.setSpacing(5) main_layout.setContentsMargins(10, 10, 10, 10) main_layout.setColumnStretch(1, 1) self.list_option = self.createListOption() main_layout.addWidget(self.list_option, 0, 0) self.page_container = QStackedLayout() self.page_container.setContentsMargins(0, 0, 0, 0) main_layout.addLayout(self.page_container, 0, 1) self.populatePages() main_layout.addWidget(self.createLine(), 1, 0, 1, 2) close_layout = QHBoxLayout() close_layout.setContentsMargins(0, 0, 5, 0) close_layout.setSpacing(5) close_option = QPushButton() close_option.setText(QApplication.translate("option", "Close")) option.connect(close_option, QtCore.SIGNAL("clicked()"), option.accept) close_layout.addWidget(close_option) main_layout.addLayout(close_layout, 2, 1, 1, 2, Qt.AlignRight) self.list_option.setCurrentRow(0) self.page_container.setCurrentIndex(0) option.setTabOrder(self.list_option, self.list_conn) option.setTabOrder(self.list_conn, self.name_conn) option.setTabOrder(self.name_conn, self.host_conn) option.setTabOrder(self.host_conn, self.port_conn) option.setTabOrder(self.port_conn, self.save_conn) option.setTabOrder(self.save_conn, self.delete_conn) option.setTabOrder(self.delete_conn, self.list_conn_account) option.setTabOrder(self.list_conn_account, self.list_account) option.setTabOrder(self.list_account, self.delete_account) option.setTabOrder(self.delete_account, self.list_conn_alias) option.setTabOrder(self.list_conn_alias, self.list_alias) option.setTabOrder(self.list_alias, self.label_alias) option.setTabOrder(self.label_alias, self.body_alias) option.setTabOrder(self.body_alias, self.save_alias) option.setTabOrder(self.save_alias, self.delete_alias) option.setTabOrder(self.delete_alias, self.list_conn_macro) option.setTabOrder(self.list_conn_macro, self.list_macro) option.setTabOrder(self.list_macro, self.register_macro) option.setTabOrder(self.register_macro, self.keys_macro) option.setTabOrder(self.keys_macro, self.command_macro) option.setTabOrder(self.command_macro, self.save_macro) option.setTabOrder(self.save_macro, self.delete_macro) option.setTabOrder(self.delete_macro, self.echo_color_button) option.setTabOrder(self.echo_color_button, self.save_log)
def __init__(self, parent=None): super(_MainContainer, self).__init__(parent) self._parent = parent self._vbox = QVBoxLayout(self) self._vbox.setContentsMargins(0, 0, 0, 0) self._vbox.setSpacing(0) self.stack = QStackedLayout() self.stack.setStackingMode(QStackedLayout.StackAll) self._vbox.addLayout(self.stack) self.splitter = dynamic_splitter.DynamicSplitter() self.setAcceptDrops(True) self._files_handler = files_handler.FilesHandler(self) self._add_file_folder = add_file_folder.AddFileFolderWidget(self) # documentation browser self.docPage = None # Code Navigation self._locator = locator.GoToDefinition() self.__codeBack = [] self.__codeForward = [] self.__bookmarksFile = "" self.__bookmarksPos = -1 self.__breakpointsFile = "" self.__breakpointsPos = -1 self.__operations = {0: self._navigate_code_jumps, 1: self._navigate_bookmarks, 2: self._navigate_breakpoints} self.connect(self, SIGNAL("locateFunction(QString, QString, bool)"), self.locate_function) IDE.register_service("main_container", self) # Register signals connections connections = ( {"target": "menu_file", "signal_name": "openFile(QString)", "slot": self.open_file}, {"target": "explorer_container", "signal_name": "goToDefinition(int)", "slot": self.editor_go_to_line}, {"target": "explorer_container", "signal_name": "pep8Activated(bool)", "slot": self.reset_pep8_warnings}, {"target": "explorer_container", "signal_name": "lintActivated(bool)", "slot": self.reset_lint_warnings}, ) IDE.register_signals("main_container", connections) self.selector = main_selector.MainSelector(self) self._opening_dialog = False self.add_widget(self.selector) if settings.SHOW_START_PAGE: self.show_start_page() self.connect(self.selector, SIGNAL("changeCurrent(int)"), self._change_current_stack) self.connect(self.selector, SIGNAL("removeWidget(int)"), self._remove_item_from_stack) self.connect(self.selector, SIGNAL("ready()"), self._selector_ready) self.connect(self.selector, SIGNAL("animationCompleted()"), self._selector_animation_completed) self.connect(self, SIGNAL("closeDialog(PyQt_PyObject)"), self.remove_widget)
def __init__(self, parent=None): super(Preferences, self).__init__(parent, Qt.Dialog) self.setWindowTitle(translations.TR_PREFERENCES_TITLE) self.setMinimumSize(QSize(800, 600)) self.setMaximumSize(QSize(0, 0)) vbox = QVBoxLayout(self) hbox = QHBoxLayout() vbox.setContentsMargins(0, 0, 5, 5) hbox.setContentsMargins(0, 0, 0, 0) self.tree = QTreeWidget() self.tree.header().setHidden(True) self.tree.setSelectionMode(QTreeWidget.SingleSelection) self.tree.setAnimated(True) self.tree.header().setHorizontalScrollMode( QAbstractItemView.ScrollPerPixel) self.tree.header().setResizeMode(0, QHeaderView.ResizeToContents) self.tree.header().setStretchLastSection(False) self.tree.setFixedWidth(200) self.stacked = QStackedLayout() hbox.addWidget(self.tree) hbox.addLayout(self.stacked) vbox.addLayout(hbox) hbox_footer = QHBoxLayout() self._btnSave = QPushButton(translations.TR_SAVE) self._btnCancel = QPushButton(translations.TR_CANCEL) hbox_footer.addSpacerItem(QSpacerItem(1, 0, QSizePolicy.Expanding)) hbox_footer.addWidget(self._btnCancel) hbox_footer.addWidget(self._btnSave) vbox.addLayout(hbox_footer) self.connect(self.tree, SIGNAL("itemSelectionChanged()"), self._change_current) self.connect(self._btnCancel, SIGNAL("clicked()"), self.close) self.connect(self._btnSave, SIGNAL("clicked()"), self._save_preferences) self.load_ui() self.tree.setCurrentItem(self.tree.topLevelItem(0))
def __init__(self, parent=None): super(ProjectTreeColumn, self).__init__(parent, Qt.WindowStaysOnTopHint) vbox = QVBoxLayout(self) vbox.setSizeConstraint(QVBoxLayout.SetDefaultConstraint) vbox.setContentsMargins(0, 0, 0, 0) self._buttons = [] self._combo_project = QComboBox() self._combo_project.setMinimumHeight(30) self._combo_project.setContextMenuPolicy(Qt.CustomContextMenu) vbox.addWidget(self._combo_project) self._projects_area = QStackedLayout() logger.debug("This is the projects area") logger.debug(self._projects_area) vbox.addLayout(self._projects_area) self.projects = [] self.connect(self._combo_project, SIGNAL("currentIndexChanged(int)"), self._change_current_project) self.connect(self._combo_project, SIGNAL("customContextMenuRequested(const QPoint &)"), self.context_menu_for_root) connections = ( { 'target': 'main_container', 'signal_name': 'addToProject(QString)', 'slot': self._add_file_to_project }, { 'target': 'main_container', 'signal_name': 'showFileInExplorer(QString)', 'slot': self._show_file_in_explorer }, ) IDE.register_service('projects_explorer', self) IDE.register_signals('projects_explorer', connections) ExplorerContainer.register_tab(translations.TR_TAB_PROJECTS, self)
def __init__(self, original=False): super(ComboEditor, self).__init__() self.__original = original vbox = QVBoxLayout(self) vbox.setContentsMargins(0, 0, 0, 0) self.bar = ActionBar() self.connect(self.bar, SIGNAL("changeCurrent(PyQt_PyObject)"), self.set_current) vbox.addWidget(self.bar) self.stacked = QStackedLayout() vbox.addLayout(self.stacked)
def __init__(self, editor): super(CodeCompletionWidget, self).__init__( None, Qt.FramelessWindowHint | Qt.ToolTip) self._editor = editor self._revision = 0 self._block = 0 self.stack_layout = QStackedLayout(self) self.stack_layout.setContentsMargins(0, 0, 0, 0) self.stack_layout.setSpacing(0) self.completion_list = QListWidget() self.completion_list.setMinimumHeight(200) self.completion_list.setAlternatingRowColors(True) self._list_index = self.stack_layout.addWidget(self.completion_list) self._icons = {'a': resources.IMAGES['attribute'], 'f': resources.IMAGES['function'], 'c': resources.IMAGES['class'], 'm': resources.IMAGES['module']} self.cc = code_completion.CodeCompletion() self._completion_results = {} self._prefix = u'' self.setVisible(False) self.source = '' self._key_operations = { Qt.Key_Up: self._select_previous_row, Qt.Key_Down: self._select_next_row, Qt.Key_PageUp: (lambda: self._select_previous_row(6)), Qt.Key_PageDown: (lambda: self._select_next_row(6)), Qt.Key_Right: lambda: None, Qt.Key_Left: lambda: None, Qt.Key_Enter: self.pre_key_insert_completion, Qt.Key_Return: self.pre_key_insert_completion, Qt.Key_Tab: self.pre_key_insert_completion, Qt.Key_Space: self.hide_completer, Qt.Key_Escape: self.hide_completer, Qt.Key_Backtab: self.hide_completer, Qt.NoModifier: self.hide_completer, Qt.ShiftModifier: self.hide_completer, } desktop = QApplication.instance().desktop() self._desktop_geometry = desktop.availableGeometry() self.connect(self.completion_list, SIGNAL("itemClicked(QListWidgetItem*)"), self.pre_key_insert_completion) self.connect(self._editor.document(), SIGNAL("cursorPositionChanged(QTextCursor)"), self.update_metadata)
def __init__(self, parent=None): super(MusicPreviewWidget, self).__init__(parent) self._lastbuildtime = 10.0 self._running = None self._current = None self._chooserLabel = QLabel() self._chooser = QComboBox(self, activated=self.selectDocument) self._log = log.Log() self._view = popplerview.View() self._progress = widgets.progressbar.TimedProgressBar() self._stack = QStackedLayout() self._top = QWidget() layout = QVBoxLayout() self.setLayout(layout) layout.addWidget(self._top) layout.addLayout(self._stack) layout.addWidget(self._progress) top = QHBoxLayout() top.setContentsMargins(0, 0, 0, 0) top.setSpacing(2) self._top.setLayout(top) top.addWidget(self._chooserLabel) top.addWidget(self._chooser) top.addStretch(1) self._stack.addWidget(self._log) self._stack.addWidget(self._view) self._top.hide() app.aboutToQuit.connect(self.cleanup) app.translateUI(self)
def __init__(self, parent=None, **kwargs): super(CSVImportDialog, self).__init__(parent, **kwargs) self.setLayout(QVBoxLayout()) self._options = None self._path = None self.__update_pending = False self._optionswidget = CSVOptionsWidget() self._optionswidget.format_changed.connect(self._invalidate_preview) self._stack = QStackedLayout() self._stack.setContentsMargins(0, 0, 0, 0) prev_box = QGroupBox("Preview") prev_box.setLayout(self._stack) self._preview = QTableView(tabKeyNavigation=False) self._preview_error = QLabel() self._stack.addWidget(self._preview) self._stack.addWidget(self._preview_error) buttons = QDialogButtonBox( orientation=Qt.Horizontal, standardButtons=(QDialogButtonBox.Ok | QDialogButtonBox.Cancel | QDialogButtonBox.Reset)) buttons.accepted.connect(self.accept) buttons.rejected.connect(self.reject) def on_clicked(button): if buttons.buttonRole(button) == QDialogButtonBox.ResetRole: self.reset() buttons.clicked.connect(on_clicked) self.layout().addWidget(self._optionswidget) self.layout().addWidget(prev_box) self.layout().addWidget(buttons)
def __init__(self, original=False): super(ComboEditor, self).__init__(None, Qt.WindowStaysOnTopHint) self.__original = original self.__undocked = [] self._symbols_index = [] vbox = QVBoxLayout(self) vbox.setContentsMargins(0, 0, 0, 0) vbox.setSpacing(0) self.bar = ActionBar(main_combo=original) vbox.addWidget(self.bar) self.stacked = QStackedLayout() vbox.addLayout(self.stacked) self._main_container = IDE.get_service('main_container') if not self.__original: self.connect(self._main_container, SIGNAL("fileOpened(QString)"), self._file_opened_by_main) self.connect(self.bar.combo, SIGNAL("showComboSelector()"), lambda: self._main_container.change_tab()) self.connect(self.bar, SIGNAL("changeCurrent(PyQt_PyObject, int)"), self._set_current) self.connect(self.bar, SIGNAL("splitEditor(bool)"), self.split_editor) self.connect(self.bar, SIGNAL("runFile(QString)"), self._run_file) self.connect(self.bar, SIGNAL("closeSplit()"), lambda: self.emit( SIGNAL("closeSplit(PyQt_PyObject)"), self)) self.connect(self.bar, SIGNAL("addToProject(QString)"), self._add_to_project) self.connect(self.bar, SIGNAL("showFileInExplorer(QString)"), self._show_file_in_explorer) self.connect(self.bar, SIGNAL("goToSymbol(int)"), self._go_to_symbol) self.connect(self.bar, SIGNAL("undockEditor()"), self.undock_editor) self.connect(self.bar, SIGNAL("reopenTab(QString)"), lambda path: self._main_container.open_file(path)) self.connect(self.bar, SIGNAL("recentTabsModified()"), lambda: self._main_container.recent_files_changed()) self.connect(self.bar.code_navigator.btnPrevious, SIGNAL("clicked()"), lambda: self._navigate_code(False)) self.connect(self.bar.code_navigator.btnNext, SIGNAL("clicked()"), lambda: self._navigate_code(True))
def __init__(self, editor): super(CodeCompletionWidget, self).__init__(None, Qt.FramelessWindowHint | Qt.ToolTip) self._editor = editor self.stack_layout = QStackedLayout(self) self.stack_layout.setContentsMargins(0, 0, 0, 0) self.stack_layout.setSpacing(0) self.completion_list = QListWidget() self.completion_list.setMinimumHeight(200) self.completion_list.setAlternatingRowColors(True) self._list_index = self.stack_layout.addWidget(self.completion_list) self._icons = { "a": resources.IMAGES["attribute"], "f": resources.IMAGES["function"], "c": resources.IMAGES["class"], } self.cc = code_completion.CodeCompletion() self._completion_results = [] self._prefix = u"" self.setVisible(False) self.source = "" self._key_operations = { Qt.Key_Up: self._select_previous_row, Qt.Key_Down: self._select_next_row, Qt.Key_PageUp: (lambda: self._select_previous_row(6)), Qt.Key_PageDown: (lambda: self._select_next_row(6)), Qt.Key_Right: lambda: None, Qt.Key_Left: lambda: None, Qt.Key_Enter: self.pre_key_insert_completion, Qt.Key_Return: self.pre_key_insert_completion, Qt.Key_Tab: self.pre_key_insert_completion, Qt.Key_Space: self.hide_completer, Qt.Key_Escape: self.hide_completer, Qt.Key_Backtab: self.hide_completer, Qt.NoModifier: self.hide_completer, Qt.ShiftModifier: self.hide_completer, } desktop = QApplication.instance().desktop() self._desktop_geometry = desktop.availableGeometry() self.connect(self._editor.document(), SIGNAL("blockCountChanged(int)"), self.update_metadata)
def __init__(self, parent=None, **kwargs): super(CSVImportDialog, self).__init__(parent, **kwargs) self.setLayout(QVBoxLayout()) self._options = None self._path = None self.__update_pending = False self._optionswidget = CSVOptionsWidget() self._optionswidget.format_changed.connect(self._invalidate_preview) self._stack = QStackedLayout() self._stack.setContentsMargins(0, 0, 0, 0) prev_box = QGroupBox("Preview") prev_box.setLayout(self._stack) self._preview = QTableView(tabKeyNavigation=False) self._preview_error = QLabel() self._stack.addWidget(self._preview) self._stack.addWidget(self._preview_error) buttons = QDialogButtonBox( orientation=Qt.Horizontal, standardButtons=(QDialogButtonBox.Ok | QDialogButtonBox.Cancel | QDialogButtonBox.Reset) ) buttons.accepted.connect(self.accept) buttons.rejected.connect(self.reject) def on_clicked(button): if buttons.buttonRole(button) == QDialogButtonBox.ResetRole: self.reset() buttons.clicked.connect(on_clicked) self.layout().addWidget(self._optionswidget) self.layout().addWidget(prev_box) self.layout().addWidget(buttons)
def __init__(self, parent=None): super(ProjectTreeColumn, self).__init__(parent, Qt.WindowStaysOnTopHint) vbox = QVBoxLayout(self) vbox.setSizeConstraint(QVBoxLayout.SetDefaultConstraint) vbox.setContentsMargins(0, 0, 0, 0) #vbox.setSpacing(0) self._buttons = [] self._combo_project = QComboBox() self._combo_project.setMinimumHeight(30) self._combo_project.setContextMenuPolicy(Qt.CustomContextMenu) vbox.addWidget(self._combo_project) self._projects_area = QStackedLayout() logger.debug("This is the projects area") logger.debug(self._projects_area) vbox.addLayout(self._projects_area) self.projects = [] self.connect(self._combo_project, SIGNAL("currentIndexChanged(int)"), self._change_current_project) self.connect(self._combo_project, SIGNAL( "customContextMenuRequested(const QPoint &)"), self.context_menu_for_root) connections = ( {'target': 'main_container', 'signal_name': 'addToProject(QString)', 'slot': self._add_file_to_project}, {'target': 'main_container', 'signal_name': 'showFileInExplorer(QString)', 'slot': self._show_file_in_explorer}, ) IDE.register_service('projects_explorer', self) IDE.register_signals('projects_explorer', connections) ExplorerContainer.register_tab(translations.TR_TAB_PROJECTS, self)
def __init__(self, w=550, h=480, titre=u"Configuration de Ekd", parent=None): super(EkdConfigBox, self).__init__(parent) self.resize(w,h) self.w = w self.h = h self.setWindowTitle(titre) self.layout = QVBoxLayout(self) ## Menu contient l'ensemble des sections à paramétrer self.menu = QListWidget(self) self.layout.addWidget(self.menu) ## Pour chaque section à paramétrer, on utilise un Stack d'objets self.leftpart = QStackedLayout() self.leftpart.setSizeConstraint(QLayout.SetNoConstraint) self.layout.addLayout(self.leftpart) ## propWidget contient l'ensemble des objets propriété de toutes les section ## (il est nécessaire de les stocker pour être capable de les faire interagir) self.propWidget=[] wid = 0 ## On crée les différentes parties de configuration qui ne sont pas inclues dans le tableau SECTION_MASK de EkdConfig for section in EkdConfig.SECTIONS : if not section in EkdConfig.SECTION_MASK : self.menu.addItem(EkdConfig.SECTIONS[section]) allprops = EkdConfig.getAllProperties(EkdConfig.getConfigSection(section)) scroll = QScrollArea() frame = QFrame() frame.setMinimumSize(self.w-50, self.h/2) # Ajouté le 10/12/2009 Pour que la partie réglage prenne toute la place dispo. frame.setMaximumSize(self.w, self.h) linelayout = QGridLayout(frame) linelayout.setSizeConstraint(QLayout.SetMinAndMaxSize) row = 0 ## Insertion des propriété de la section en fonction de son type allkeys = allprops.keys() found = False for prop in allkeys : if not prop in EkdConfig.PROPERTIES_MASK : if prop in EkdConfig.PATH_PROPERTIES : self.propWidget.append( EkdPathPropertie(prop, EkdConfig.PROPERTIES[prop], allprops[prop], section=section) ) linelayout.addWidget(self.propWidget[wid].label, row, 0) linelayout.addWidget(self.propWidget[wid].widget, row, 1) wid += 1 found = True row += 1 for prop in allkeys : if not prop in EkdConfig.PROPERTIES_MASK : if prop in EkdConfig.STYLE_PROPERTIES : self.propWidget.append( EkdStylePropertie(prop, EkdConfig.PROPERTIES[prop], allprops[prop], EkdConfig.STYLE_PROPERTIES[prop], section=section ) ) linelayout.addWidget(self.propWidget[wid].label, row, 0) linelayout.addWidget(self.propWidget[wid].widget, row, 1) wid += 1 found = True row += 1 for prop in allkeys : if not prop in EkdConfig.PROPERTIES_MASK : if prop in EkdConfig.CODEC_PROPERTIES : self.propWidget.append( EkdCodecPropertie(prop, EkdConfig.PROPERTIES[prop], allprops[prop], EkdConfig.CODEC_PROPERTIES[prop], section=section ) ) linelayout.addWidget(self.propWidget[wid].label, row, 0) linelayout.addWidget(self.propWidget[wid].widget, row, 1) wid += 1 found = True row += 1 for prop in allkeys : if not prop in EkdConfig.PROPERTIES_MASK : if prop in EkdConfig.BOOLEAN_PROPERTIES : self.propWidget.append( EkdBoolPropertie(prop, EkdConfig.PROPERTIES[prop], allprops[prop], section=section) ) linelayout.addWidget(self.propWidget[wid].widget, row, 0, 1, 2) wid += 1 found = True row += 1 for prop in allkeys : if not prop in EkdConfig.PROPERTIES_MASK : if prop in EkdConfig.NUM_PROPERTIES : self.propWidget.append( EkdNumPropertie(prop, EkdConfig.PROPERTIES[prop], allprops[prop], section=section) ) linelayout.addWidget(self.propWidget[wid].label, row, 0) linelayout.addWidget(self.propWidget[wid].widget, row, 1) wid += 1 found = True row += 1 for prop in allkeys : if not prop in EkdConfig.PROPERTIES_MASK : if prop in EkdConfig.TIME_PROPERTIES : self.propWidget.append( EkdTimePropertie(prop, EkdConfig.PROPERTIES[prop], allprops[prop], section=section) ) linelayout.addWidget(self.propWidget[wid].label, row, 0) linelayout.addWidget(self.propWidget[wid].widget, row, 1) wid += 1 found = True row += 1 for prop in allkeys : if not prop in EkdConfig.PROPERTIES_MASK : if prop in EkdConfig.COLOR_PROPERTIES : self.propWidget.append( EkdColorPropertie(prop, EkdConfig.PROPERTIES[prop], allprops[prop], section=section) ) linelayout.addWidget(self.propWidget[wid].label, row, 0) linelayout.addWidget(self.propWidget[wid].widget, row, 1) wid += 1 found = True elif not found: line = QLineEdit(allprops[prop]) linelayout.addWidget(QLabel(prop), row, 0) linelayout.addWidget(line, row, 1) row += 1 frame.setLineWidth(0) scroll.setWidget(frame) self.leftpart.addWidget(scroll) self.menu.setAlternatingRowColors(True) # Define the size of the list depending of its content self.menu.setFixedHeight(( self.menu.sizeHintForRow(0) + self.menu.verticalStepsPerItem() + 1)* self.menu.count()) self.menu.updateGeometries() ## Boutton pour fermer la boite de dialogue self.fermer = QPushButton(_(u"Fermer")) self.layout.addWidget(self.fermer) ## Lorsqu'on clique sur fermer, la fenêtre se ferme self.connect(self.fermer, SIGNAL("clicked()"), self.close) ## Lorsqu'on selectionne un élément du menu, on met à jour la partie droite du menu self.connect(self.menu, SIGNAL("currentItemChanged(QListWidgetItem *,QListWidgetItem *)"), self.updateMenu)
class _MainContainer(QWidget): ############################################################################### # MainContainer SIGNALS ############################################################################### """ newFileOpened(QString) allTabClosed() runFile(QString) addToProject(QString) showFileInExplorer(QString) recentTabsModified() currentEditorChanged(QString) fileOpened(QString) ---------migrationAnalyzed() findOcurrences(QString) ---------updateFileMetadata() editorKeyPressEvent(QEvent) locateFunction(QString, QString, bool) [functionName, filePath, isVariable] updateLocator(QString) beforeFileSaved(QString) fileSaved(QString) openPreferences() --------openProject(QString) ---------dontOpenStartPage() """ ############################################################################### def __init__(self, parent=None): super(_MainContainer, self).__init__(parent) self._parent = parent self._vbox = QVBoxLayout(self) self._vbox.setContentsMargins(0, 0, 0, 0) self._vbox.setSpacing(0) self.stack = QStackedLayout() self.stack.setStackingMode(QStackedLayout.StackAll) self._vbox.addLayout(self.stack) self.splitter = dynamic_splitter.DynamicSplitter() self.setAcceptDrops(True) self._files_handler = files_handler.FilesHandler(self) self._add_file_folder = add_file_folder.AddFileFolderWidget(self) #documentation browser self.docPage = None #Code Navigation self._locator = locator.GoToDefinition() self.__codeBack = [] self.__codeForward = [] self.__bookmarksFile = '' self.__bookmarksPos = -1 self.__breakpointsFile = '' self.__breakpointsPos = -1 self.__operations = { 0: self._navigate_code_jumps, 1: self._navigate_bookmarks, 2: self._navigate_breakpoints } self.connect(self, SIGNAL("locateFunction(QString, QString, bool)"), self.locate_function) IDE.register_service('main_container', self) #Register signals connections connections = ( { 'target': 'menu_file', 'signal_name': 'openFile(QString)', 'slot': self.open_file }, { 'target': 'explorer_container', 'signal_name': 'goToDefinition(int)', 'slot': self.editor_go_to_line }, { 'target': 'explorer_container', 'signal_name': 'pep8Activated(bool)', 'slot': self.reset_pep8_warnings }, { 'target': 'explorer_container', 'signal_name': 'lintActivated(bool)', 'slot': self.reset_lint_warnings }, ) IDE.register_signals('main_container', connections) self.selector = main_selector.MainSelector(self) self._opening_dialog = False self.add_widget(self.selector) if settings.SHOW_START_PAGE: self.show_start_page() self.connect(self.selector, SIGNAL("changeCurrent(int)"), self._change_current_stack) self.connect(self.selector, SIGNAL("removeWidget(int)"), self._remove_item_from_stack) self.connect(self.selector, SIGNAL("ready()"), self._selector_ready) self.connect(self.selector, SIGNAL("animationCompleted()"), self._selector_animation_completed) self.connect(self, SIGNAL("closeDialog(PyQt_PyObject)"), self.remove_widget) def install(self): ide = IDE.get_service('ide') ide.place_me_on("main_container", self, "central", top=True) self.combo_area = combo_editor.ComboEditor(original=True) self.connect(self.combo_area, SIGNAL("allFilesClosed()"), self._files_closed) self.splitter.add_widget(self.combo_area) self.add_widget(self.splitter) self.current_widget = self.combo_area ui_tools.install_shortcuts(self, actions.ACTIONS, ide) def add_status_bar(self, status): self._vbox.addWidget(status) @property def combo_header_size(self): return self.combo_area.bar.height() def add_widget(self, widget): self.stack.addWidget(widget) def remove_widget(self, widget): self.stack.removeWidget(widget) def _close_dialog(self, widget): self.emit(SIGNAL("closeDialog(PyQt_PyObject)"), widget) self.disconnect(widget, SIGNAL("finished(int)"), lambda: self._close_dialog(widget)) def show_dialog(self, widget): self._opening_dialog = True self.connect(widget, SIGNAL("finished(int)"), lambda: self._close_dialog(widget)) self.setVisible(True) self.stack.addWidget(widget) self.show_selector() def show_selector(self): if self.selector != self.stack.currentWidget(): temp_dir = os.path.join(QDir.tempPath(), "ninja-ide") if not os.path.exists(temp_dir): os.mkdir(temp_dir) collected_data = [] current = self.stack.currentIndex() for index in range(self.stack.count()): widget = self.stack.widget(index) if widget == self.selector: continue closable = True if widget == self.splitter: closable = False pixmap = QPixmap.grabWidget(widget, widget.rect()) path = os.path.join(temp_dir, "screen%s.png" % index) pixmap.save(path) if index == current: self.selector.set_preview(index, path) collected_data.insert(0, (index, path, closable)) else: collected_data.append((index, path, closable)) self.selector.set_model(collected_data) else: self.selector.close_selector() def _selector_ready(self): self.stack.setCurrentWidget(self.selector) self.selector.start_animation() def _selector_animation_completed(self): if self._opening_dialog: # We choose the last one with -2, -1 (for last one) + # -1 for the hidden selector widget which is in the stacked too. self.selector.open_item(self.stack.count() - 2) self._opening_dialog = False def _change_current_stack(self, index): self.stack.setCurrentIndex(index) def _remove_item_from_stack(self, index): widget = self.stack.takeAt(index) del widget def show_editor_area(self): self.stack.setCurrentWidget(self.splitter) def _files_closed(self): if settings.SHOW_START_PAGE: self.show_start_page() def change_visibility(self): """Show/Hide the Main Container area.""" if self.isVisible(): self.hide() else: self.show() def expand_symbol_combo(self): self.stack.setCurrentWidget(self.splitter) self.current_widget.show_combo_symbol() def expand_file_combo(self): self.stack.setCurrentWidget(self.splitter) self.current_widget.show_combo_file() def locate_function(self, function, filePath, isVariable): """Move the cursor to the proper position in the navigate stack.""" editorWidget = self.get_current_editor() if editorWidget: self.__codeBack.append( (editorWidget.file_path, editorWidget.getCursorPosition())) self.__codeForward = [] self._locator.navigate_to(function, filePath, isVariable) def run_file(self, path): self.emit(SIGNAL("runFile(QString)"), path) def _add_to_project(self, path): self.emit(SIGNAL("addToProject(QString)"), path) def _show_file_in_explorer(self, path): self.emit(SIGNAL("showFileInExplorer(QString)"), path) def paste_history(self): """Paste the text from the copy/paste history.""" editorWidget = self.get_current_editor() if editorWidget and editorWidget.hasFocus(): line, index = editorWidget.getCursorPosition() central = IDE.get_service('central_container') if central: editorWidget.insertAt(central.get_paste(), line, index) def copy_history(self): """Copy the selected text into the copy/paste history.""" editorWidget = self.get_current_editor() if editorWidget and editorWidget.hasFocus(): copy = editorWidget.selectedText() central = IDE.get_service('central_container') if central: central.add_copy(copy) def import_from_everywhere(self): """Insert an import line from any place in the editor.""" editorWidget = self.get_current_editor() if editorWidget: dialog = from_import_dialog.FromImportDialog(editorWidget, self) dialog.show() def add_back_item_navigation(self): """Add an item to the back stack and reset the forward stack.""" editorWidget = self.get_current_editor() if editorWidget: self.__codeBack.append( (editorWidget.file_path, editorWidget.getCursorPosition())) self.__codeForward = [] def preview_in_browser(self): """Load the current html file in the default browser.""" editorWidget = self.get_current_editor() if editorWidget: if not editorWidget.file_path: self.save_file() ext = file_manager.get_file_extension(editorWidget.file_path) if ext == 'html': webbrowser.open(editorWidget.file_path) def add_bookmark_breakpoint(self): """Add a bookmark or breakpoint to the current file in the editor.""" editorWidget = self.get_current_editor() if editorWidget and editorWidget.hasFocus(): if self.current_widget.bar.code_navigator.operation == 1: editorWidget.handle_bookmarks_breakpoints( editorWidget.getCursorPosition()[0], Qt.ControlModifier) elif self.current_widget.bar.code_navigator.operation == 2: editorWidget.handle_bookmarks_breakpoints( editorWidget.getCursorPosition()[0], Qt.NoModifier) def __navigate_with_keyboard(self, val): """Navigate between the positions in the jump history stack.""" op = self.current_widget.bar.code_navigator.operation self.navigate_code_history(val, op) def navigate_code_history(self, val, op): """Navigate the code history.""" self.__operations[op](val) def _navigate_code_jumps(self, val): """Navigate between the jump points.""" node = None if not val and self.__codeBack: node = self.__codeBack.pop() editorWidget = self.get_current_editor() if editorWidget: self.__codeForward.append( (editorWidget.file_path, editorWidget.getCursorPosition())) elif val and self.__codeForward: node = self.__codeForward.pop() editorWidget = self.get_current_editor() if editorWidget: self.__codeBack.append( (editorWidget.file_path, editorWidget.getCursorPosition())) if node: filename = node[0] line, col = node[1] self.open_file(filename, line, col) def _navigate_breakpoints(self, val): """Navigate between the breakpoints.""" #FIXME: put navigate breakpoints and bookmarks as one method. breakList = list(settings.BREAKPOINTS.keys()) breakList.sort() if not breakList: return if self.__breakpointsFile not in breakList: self.__breakpointsFile = breakList[0] index = breakList.index(self.__breakpointsFile) breaks = settings.BREAKPOINTS.get(self.__breakpointsFile, []) lineNumber = 0 #val == True: forward if val: if (len(breaks) - 1) > self.__breakpointsPos: self.__breakpointsPos += 1 lineNumber = breaks[self.__breakpointsPos] elif len(breaks) > 0: if index < (len(breakList) - 1): self.__breakpointsFile = breakList[index + 1] else: self.__breakpointsFile = breakList[0] self.__breakpointsPos = 0 lineNumber = settings.BREAKPOINTS[self.__breakpointsFile][0] else: if self.__breakpointsPos > 0: self.__breakpointsPos -= 1 lineNumber = breaks[self.__breakpointsPos] elif len(breaks) > 0: self.__breakpointsFile = breakList[index - 1] breaks = settings.BREAKPOINTS[self.__breakpointsFile] self.__breakpointsPos = len(breaks) - 1 lineNumber = breaks[self.__breakpointsPos] if file_manager.file_exists(self.__breakpointsFile): self.open_file(self.__breakpointsFile, lineNumber, None, True) else: settings.BREAKPOINTS.pop(self.__breakpointsFile) if settings.BREAKPOINTS: self._navigate_breakpoints(val) def _navigate_bookmarks(self, val): """Navigate between the bookmarks.""" bookList = list(settings.BOOKMARKS.keys()) bookList.sort() if not bookList: return if self.__bookmarksFile not in bookList: self.__bookmarksFile = bookList[0] index = bookList.index(self.__bookmarksFile) bookms = settings.BOOKMARKS.get(self.__bookmarksFile, []) lineNumber = 0 #val == True: forward if val: if (len(bookms) - 1) > self.__bookmarksPos: self.__bookmarksPos += 1 lineNumber = bookms[self.__bookmarksPos] elif len(bookms) > 0: if index < (len(bookList) - 1): self.__bookmarksFile = bookList[index + 1] else: self.__bookmarksFile = bookList[0] self.__bookmarksPos = 0 lineNumber = settings.BOOKMARKS[self.__bookmarksFile][0] else: if self.__bookmarksPos > 0: self.__bookmarksPos -= 1 lineNumber = bookms[self.__bookmarksPos] elif len(bookms) > 0: self.__bookmarksFile = bookList[index - 1] bookms = settings.BOOKMARKS[self.__bookmarksFile] self.__bookmarksPos = len(bookms) - 1 lineNumber = bookms[self.__bookmarksPos] if file_manager.file_exists(self.__bookmarksFile): self.open_file(self.__bookmarksFile, lineNumber, None, True) else: settings.BOOKMARKS.pop(self.__bookmarksFile) if settings.BOOKMARKS: self._navigate_bookmarks(val) def count_file_code_lines(self): """Count the lines of code in the current file.""" editorWidget = self.get_current_editor() if editorWidget: block_count = editorWidget.lines() blanks = re.findall('(^\n)|(^(\s+)?#)|(^( +)?($|\n))', editorWidget.text(), re.M) blanks_count = len(blanks) resume = self.tr("Lines code: %s\n") % (block_count - blanks_count) resume += (self.tr("Blanks and commented lines: %s\n\n") % blanks_count) resume += self.tr("Total lines: %s") % block_count msgBox = QMessageBox(QMessageBox.Information, self.tr("Summary of lines"), resume, QMessageBox.Ok, editorWidget) msgBox.exec_() def editor_cut(self): editorWidget = self.get_current_editor() if editorWidget: editorWidget.cut() def editor_copy(self): editorWidget = self.get_current_editor() if editorWidget: editorWidget.copy() def editor_paste(self): editorWidget = self.get_current_editor() if editorWidget: editorWidget.paste() def editor_upper(self): editorWidget = self.get_current_editor() if editorWidget: editorWidget.to_upper() def editor_lower(self): editorWidget = self.get_current_editor() if editorWidget: editorWidget.to_lower() def editor_title(self): editorWidget = self.get_current_editor() if editorWidget: editorWidget.to_title() def editor_go_to_definition(self): """Search the definition of the method or variable under the cursor. If more than one method or variable is found with the same name, shows a table with the results and let the user decide where to go.""" editorWidget = self.get_current_editor() if editorWidget and editorWidget.hasFocus(): editorWidget.go_to_definition() def editor_redo(self): """Execute the redo action in the current editor.""" editorWidget = self.get_current_editor() if editorWidget and editorWidget.hasFocus(): editorWidget.redo() def editor_undo(self): editorWidget = self.get_current_editor() if editorWidget and editorWidget.hasFocus(): editorWidget.undo() def editor_indent_less(self): """Indent 1 position to the left for the current line or selection.""" editorWidget = self.get_current_editor() if editorWidget and editorWidget.hasFocus(): editorWidget.indent_less() def editor_indent_more(self): """Indent 1 position to the right for the current line or selection.""" editorWidget = self.get_current_editor() if editorWidget and editorWidget.hasFocus(): editorWidget.indent() def editor_insert_debugging_prints(self): """Insert a print statement in each selected line.""" editorWidget = self.get_current_editor() if editorWidget: helpers.insert_debugging_prints(editorWidget) def editor_insert_pdb(self): """Insert a pdb.set_trace() statement in tjhe current line.""" editorWidget = self.get_current_editor() if editorWidget: helpers.insert_pdb(editorWidget) def editor_comment(self): """Mark the current line or selection as a comment.""" editorWidget = self.get_current_editor() if editorWidget and editorWidget.hasFocus(): helpers.comment(editorWidget) def editor_uncomment(self): """Uncomment the current line or selection.""" editorWidget = self.get_current_editor() if editorWidget and editorWidget.hasFocus(): helpers.uncomment(editorWidget) def editor_insert_horizontal_line(self): """Insert an horizontal lines of comment symbols.""" editorWidget = self.get_current_editor() if editorWidget and editorWidget.hasFocus(): helpers.insert_horizontal_line(editorWidget) def editor_insert_title_comment(self): """Insert a Title surrounded by comment symbols.""" editorWidget = self.get_current_editor() if editorWidget and editorWidget.hasFocus(): helpers.insert_title_comment(editorWidget) def editor_remove_trailing_spaces(self): """Remove the trailing spaces in the current editor.""" editorWidget = self.get_current_editor() if editorWidget: helpers.remove_trailing_spaces(editorWidget) def editor_replace_tabs_with_spaces(self): """Replace the Tabs with Spaces in the current editor.""" editorWidget = self.get_current_editor() if editorWidget: helpers.replace_tabs_with_spaces(editorWidget) def editor_move_up(self): """Move the current line or selection one position up.""" editorWidget = self.get_current_editor() if editorWidget and editorWidget.hasFocus(): helpers.move_up(editorWidget) def editor_move_down(self): """Move the current line or selection one position down.""" editorWidget = self.get_current_editor() if editorWidget and editorWidget.hasFocus(): helpers.move_down(editorWidget) def editor_remove_line(self): """Remove the current line or selection.""" editorWidget = self.get_current_editor() if editorWidget and editorWidget.hasFocus(): helpers.remove_line(editorWidget) def editor_duplicate(self): """Duplicate the current line or selection.""" editorWidget = self.get_current_editor() if editorWidget and editorWidget.hasFocus(): helpers.duplicate(editorWidget) def editor_highlight_word(self): """Highlight the occurrences of the current word in the editor.""" editorWidget = self.get_current_editor() if editorWidget and editorWidget.hasFocus(): editorWidget.highlight_selected_word() def editor_complete_declaration(self): """Do the opposite action that Complete Declaration expect.""" editorWidget = self.get_current_editor() if editorWidget and editorWidget.hasFocus(): editorWidget.complete_declaration() def editor_go_to_line(self, line): """Jump to the specified line in the current editor.""" editorWidget = self.get_current_editor() if editorWidget: editorWidget.jump_to_line(line) def zoom_in_editor(self): """Increase the font size in the current editor.""" editorWidget = self.get_current_editor() if editorWidget: editorWidget.zoom_in() def zoom_out_editor(self): """Decrease the font size in the current editor.""" editorWidget = self.get_current_editor() if editorWidget: editorWidget.zoom_out() def recent_files_changed(self): self.emit(SIGNAL("recentTabsModified()")) def dragEnterEvent(self, event): if event.mimeData().hasUrls(): event.accept() else: event.ignore() def dropEvent(self, event): file_path = event.mimeData().urls()[0].toLocalFile() self.open_file(file_path) def setFocus(self): widget = self.get_current_widget() if widget: widget.setFocus() def current_editor_changed(self, filename): """Notify the new filename of the current editor.""" if filename is None: filename = translations.TR_NEW_DOCUMENT self.emit(SIGNAL("currentEditorChanged(QString)"), filename) def show_split(self, orientation_vertical=False): #IDE.select_current(self.current_widget.currentWidget()) self.current_widget.split_editor(orientation_vertical) def add_editor(self, fileName=None, ignore_checkers=False): ninjaide = IDE.get_service('ide') editable = ninjaide.get_or_create_editable(fileName) if editable.editor: self.current_widget.set_current(editable) return editable.editor else: editable.ignore_checkers = ignore_checkers editorWidget = self.create_editor_from_editable(editable) #add the tab if self.current_widget != self.combo_area: self.combo_area.add_editor(editable) self.current_widget.add_editor(editable) #emit a signal about the file open self.emit(SIGNAL("fileOpened(QString)"), fileName) self.stack.setCurrentWidget(self.splitter) return editorWidget def create_editor_from_editable(self, editable): editorWidget = editor.create_editor(editable) #Connect signals self.connect(editable, SIGNAL("fileSaved(PyQt_PyObject)"), self._editor_tab_was_saved) self.connect(editorWidget, SIGNAL("openDropFile(QString)"), self.open_file) self.connect(editorWidget, SIGNAL("addBackItemNavigation()"), self.add_back_item_navigation) self.connect(editorWidget, SIGNAL("locateFunction(QString, QString, bool)"), self._editor_locate_function) self.connect(editorWidget, SIGNAL("findOcurrences(QString)"), self._find_occurrences) #keyPressEventSignal for plugins self.connect(editorWidget, SIGNAL("keyPressEvent(QEvent)"), self._editor_keyPressEvent) return editorWidget def reset_pep8_warnings(self, value): pass #FIXME: check how we handle this #for i in range(self._tabMain.count()): #widget = self._tabMain.widget(i) #if type(widget) is editor.Editor: #if value: #widget.syncDocErrorsSignal = True #widget.pep8.check_style() #else: #widget.hide_pep8_errors() def reset_lint_warnings(self, value): pass #FIXME: check how we handle this #for i in range(self._tabMain.count()): #widget = self._tabMain.widget(i) #if type(widget) is editor.Editor: #if value: #widget.syncDocErrorsSignal = True #widget.errors.check_errors() #else: #widget.hide_lint_errors() def _find_occurrences(self, word): self.emit(SIGNAL("findOcurrences(QString)"), word) def _editor_keyPressEvent(self, event): self.emit(SIGNAL("editorKeyPressEvent(QEvent)"), event) def _editor_locate_function(self, function, filePath, isVariable): self.emit(SIGNAL("locateFunction(QString, QString, bool)"), function, filePath, isVariable) def _editor_tab_was_saved(self, editable=None): self.emit(SIGNAL("updateLocator(QString)"), editable.file_path) def get_current_widget(self): return self.current_widget.currentWidget() def get_current_editor(self): """Return the Actual Editor or None Return an instance of Editor if the Current Tab contains an Editor or None if it is not an instance of Editor""" widget = self.current_widget.currentWidget() if isinstance(widget, editor.Editor): return widget return None def reload_file(self, editorWidget=None): if editorWidget is None: editorWidget = self.get_current_editor() editorWidget.neditable.reload_file() def add_tab(self, widget, tabName, tabIndex=None): pass #return self.tabs.add_tab(widget, tabName, index=tabIndex) def open_image(self, fileName): try: if not self.is_open(fileName): viewer = image_viewer.ImageViewer(fileName) self.add_tab(viewer, file_manager.get_basename(fileName)) viewer.ID = fileName else: self.move_to_open(fileName) except Exception as reason: logger.error('open_image: %s', reason) QMessageBox.information(self, self.tr("Incorrect File"), self.tr("The image couldn\'t be open")) def open_file(self, filename='', line=-1, col=0, ignore_checkers=False): logger.debug("will try to open %s" % filename) if not filename: logger.debug("has nofilename") if settings.WORKSPACE: directory = settings.WORKSPACE else: directory = os.path.expanduser("~") editorWidget = self.get_current_editor() ninjaide = IDE.get_service('ide') if ninjaide: current_project = ninjaide.get_current_project() if current_project is not None: directory = current_project elif editorWidget is not None and editorWidget.file_path: directory = file_manager.get_folder( editorWidget.file_path) extensions = ';;'.join([ '{}(*{})'.format(e.upper()[1:], e) for e in settings.SUPPORTED_EXTENSIONS + ['.*', ''] ]) fileNames = list( QFileDialog.getOpenFileNames(self, self.tr("Open File"), directory, extensions)) else: logger.debug("has filename") fileNames = [filename] if not fileNames: return for filename in fileNames: if file_manager.get_file_extension(filename) in ('jpg', 'png'): logger.debug("will open as image") self.open_image(filename) elif file_manager.get_file_extension(filename).endswith('ui'): logger.debug("will load in ui editor") self.w = uic.loadUi(filename) self.w.show() else: logger.debug("will try to open: " + filename) self.__open_file(filename, line, col, ignore_checkers) def __open_file(self, fileName='', line=-1, col=0, ignore_checkers=False): try: editorWidget = self.add_editor(fileName, ignore_checkers=ignore_checkers) if line != -1: editorWidget.set_cursor_position(line, col) self.emit(SIGNAL("currentEditorChanged(QString)"), fileName) except file_manager.NinjaIOException as reason: QMessageBox.information(self, self.tr("The file couldn't be open"), str(reason)) def is_open(self, filename): pass #return self.tabs.is_open(filename) != -1 def move_to_open(self, filename): pass #FIXME: add in the current split? #if self.tabs.is_open(filename) != -1: #self.tabs.move_to_open(filename) #self.tabs.currentWidget().setFocus() #self.emit(SIGNAL("currentEditorChanged(QString)"), filename) def get_widget_for_id(self, filename): pass #widget = None #index = self.tabs.is_open(filename) #if index != -1: #widget = self.tabs.widget(index) #return widget def change_open_tab_id(self, idname, newId): """Search for the Tab with idname, and set the newId to that Tab.""" pass #index = self.tabs.is_open(idname) #if index != -1: #widget = self.tabs.widget(index) #tabName = file_manager.get_basename(newId) #self.tabs.change_open_tab_name(index, tabName) #widget.ID = newId def close_deleted_file(self, idname): """Search for the Tab with id, and ask the user if should be closed.""" pass #index = self.tabs.is_open(idname) #if index != -1: #result = QMessageBox.question(self, self.tr("Close Deleted File"), #self.tr("Are you sure you want to close the deleted file?\n" #"The content will be completely deleted."), #buttons=QMessageBox.Yes | QMessageBox.No) #if result == QMessageBox.Yes: #self.tabs.removeTab(index) def save_file(self, editorWidget=None): #FIXME: check how we handle this if not editorWidget: editorWidget = self.get_current_editor() if not editorWidget: return False try: #editorWidget.just_saved = True if (editorWidget.nfile.is_new_file or not editorWidget.nfile.has_write_permission()): return self.save_file_as() self.emit(SIGNAL("beforeFileSaved(QString)"), editorWidget.file_path) if settings.REMOVE_TRAILING_SPACES: helpers.remove_trailing_spaces(editorWidget) editorWidget.neditable.save_content() #file_manager.store_file_content( #fileName, content, addExtension=False) encoding = file_manager.get_file_encoding(editorWidget.text()) editorWidget.encoding = encoding self.emit(SIGNAL("fileSaved(QString)"), (self.tr("File Saved: %s") % editorWidget.file_path)) return True except Exception as reason: logger.error('save_file: %s', reason) QMessageBox.information(self, self.tr("Save Error"), self.tr("The file couldn't be saved!")) return False def save_file_as(self): editorWidget = self.get_current_editor() if not editorWidget: return False try: filters = '(*.py);;(*.*)' if editorWidget.file_path: ext = file_manager.get_file_extension(editorWidget.file_path) if ext != 'py': filters = '(*.%s);;(*.py);;(*.*)' % ext save_folder = self._get_save_folder(editorWidget.file_path) fileName = QFileDialog.getSaveFileName(self._parent, self.tr("Save File"), save_folder, filters) if not fileName: return False if settings.REMOVE_TRAILING_SPACES: helpers.remove_trailing_spaces(editorWidget) editorWidget.neditable.save_content(path=fileName) editorWidget.register_syntax( file_manager.get_file_extension(fileName)) self.emit(SIGNAL("fileSaved(QString)"), (self.tr("File Saved: %s") % fileName)) self.emit(SIGNAL("currentEditorChanged(QString)"), fileName) return True except file_manager.NinjaFileExistsException as ex: QMessageBox.information( self, self.tr("File Already Exists"), (self.tr("Invalid Path: the file '%s' " " already exists.") % ex.filename)) except Exception as reason: logger.error('save_file_as: %s', reason) QMessageBox.information(self, self.tr("Save Error"), self.tr("The file couldn't be saved!")) return False def _get_save_folder(self, fileName): """ Returns the root directory of the 'Main Project' or the home folder """ ninjaide = IDE.get_service('ide') current_project = ninjaide.get_current_project() if current_project: return current_project.path return os.path.expanduser("~") def save_project(self, projectFolder): pass #FIXME: check how we handle this #for i in range(self._tabMain.count()): #editorWidget = self._tabMain.widget(i) #if type(editorWidget) is editor.Editor and \ #file_manager.belongs_to_folder(projectFolder, #editorWidget.file_path): #reloaded = self._tabMain.check_for_external_modifications( #editorWidget) #if not reloaded: #self.save_file(editorWidget) #for i in range(self.tabsecondary.count()): #editorWidget = self.tabsecondary.widget(i) #if type(editorWidget) is editor.Editor and \ #file_manager.belongs_to_folder(projectFolder, #editorWidget.file_path): #reloaded = self.tabsecondary.check_for_external_modifications( #editorWidget) #if not reloaded: #self.save_file(editorWidget) def save_all(self): pass #FIXME: check how we handle this #for i in range(self._tabMain.count()): #editorWidget = self._tabMain.widget(i) #if type(editorWidget) is editor.Editor: #reloaded = self._tabMain.check_for_external_modifications( #editorWidget) #if not reloaded: #self.save_file(editorWidget) #for i in range(self.tabsecondary.count()): #editorWidget = self.tabsecondary.widget(i) #self.tabsecondary.check_for_external_modifications(editorWidget) #if type(editorWidget) is editor.Editor: #reloaded = self.tabsecondary.check_for_external_modifications( #editorWidget) #if not reloaded: #self.save_file(editorWidget) def call_editors_function(self, call_function, *arguments): pass #args = arguments[0] #kwargs = arguments[1] #for i in range(self.tabs.count()): #editorWidget = self.tabs.widget(i) #if isinstance(editorWidget, editor.Editor): #function = getattr(editorWidget, call_function) #function(*args, **kwargs) #TODO: add other splits def show_start_page(self): start = self.stack.widget(0) if isinstance(start, start_page.StartPage): self.stack.setCurrentIndex(0) else: startPage = start_page.StartPage(parent=self) self.connect(startPage, SIGNAL("openProject(QString)"), self.open_project) self.connect(startPage, SIGNAL("openPreferences()"), lambda: self.emit(SIGNAL("openPreferences()"))) self.connect(startPage, SIGNAL("newFile()"), self.add_editor) self.stack.insertWidget(0, startPage) self.stack.setCurrentIndex(0) def show_python_doc(self): if sys.platform == 'win32': self.docPage = browser_widget.BrowserWidget( 'http://docs.python.org/') else: process = runner.start_pydoc() self.docPage = browser_widget.BrowserWidget(process[1], process[0]) self.add_tab(self.docPage, translations.TR_PYTHON_DOC) def show_report_bugs(self): webbrowser.open(resources.BUGS_PAGE) def show_plugins_doc(self): bugsPage = browser_widget.BrowserWidget(resources.PLUGINS_DOC, self) self.add_tab(bugsPage, translations.TR_HOW_TO_WRITE_PLUGINS) def editor_jump_to_line(self, lineno=None): """Jump to line *lineno* if it is not None otherwise ask to the user the line number to jump """ editorWidget = self.get_current_editor() if editorWidget: editorWidget.jump_to_line(lineno=lineno) def get_opened_documents(self): #return self.tabs.get_documents_data() return [] def check_for_unsaved_files(self): pass #return self.tabs._check_unsaved_tabs() def get_unsaved_files(self): pass #return self.tabs.get_unsaved_files() def reset_editor_flags(self): pass #for i in range(self.tabs.count()): #widget = self.tabs.widget(i) #if isinstance(widget, editor.Editor): #widget.set_flags() def _specify_syntax(self, widget, syntaxLang): if isinstance(widget, editor.Editor): widget.restyle(syntaxLang) def apply_editor_theme(self, family, size): pass #for i in range(self.tabs.count()): #widget = self.tabs.widget(i) #if isinstance(widget, editor.Editor): #widget.restyle() #widget.set_font(family, size) def update_editor_margin_line(self): pass #for i in range(self.tabs.count()): #widget = self.tabs.widget(i) #if isinstance(widget, editor.Editor): #widget._update_margin_line() def open_project(self, path): self.emit(SIGNAL("openProject(QString)"), path) def close_python_doc(self): pass #close the python document server (if running) #if self.docPage: #index = self.tabs.indexOf(self.docPage) #self.tabs.removeTab(index) ##assign None to the browser #self.docPage = None def close_file(self): """Close the current tab in the current TabWidget.""" self.current_widget.close_current_file() def create_file(self, base_path, project_path): self._add_file_folder.create_file(base_path, project_path) def create_folder(self, base_path, project_path): self._add_file_folder.create_folder(base_path, project_path) def change_tab(self): """Change the tab in the current TabWidget.""" self.stack.setCurrentWidget(self.splitter) self._files_handler.next_item() def change_tab_reverse(self): """Change the tab in the current TabWidget backwards.""" self.stack.setCurrentWidget(self.splitter) self._files_handler.previous_item() def toggle_tabs_and_spaces(self): """ Toggle Show/Hide Tabs and Spaces """ settings.SHOW_TABS_AND_SPACES = not settings.SHOW_TABS_AND_SPACES qsettings = IDE.ninja_settings() qsettings.setValue('preferences/editor/showTabsAndSpaces', settings.SHOW_TABS_AND_SPACES) def show_navigation_buttons(self): """Show Navigation menu.""" self.stack.setCurrentWidget(self.splitter) self.combo_area.show_menu_navigation() def change_split_focus(self): pass #FIXME: check how we handle this #if self.actualTab == self._tabMain and self.tabsecondary.isVisible(): #self.actualTab = self.tabsecondary #else: #self.actualTab = self._tabMain #widget = self.actualTab.currentWidget() #if widget is not None: #widget.setFocus() def shortcut_index(self, index): pass #self.tabs.setCurrentIndex(index) def print_file(self): """Call the print of ui_tool Call print of ui_tool depending on the focus of the application""" #TODO: Add funtionality for proyect tab and methods tab editorWidget = self.get_current_editor() if editorWidget is not None: fileName = "newDocument.pdf" if editorWidget.file_path: fileName = file_manager.get_basename(editorWidget.file_path) fileName = fileName[:fileName.rfind('.')] + '.pdf' ui_tools.print_file(fileName, editorWidget.print_) def split_assistance(self): dialog = split_orientation.SplitOrientation(self) dialog.show() def close_split(self): if self.current_widget != self.combo_area: self.current_widget.bar.close_split() def split_vertically(self): self.show_split(False) def split_horizontally(self): self.show_split(True) def navigate_back(self): self.__navigate_with_keyboard(False) def navigate_forward(self): self.__navigate_with_keyboard(True)
def __init__(self, parent=None): super().__init__(parent) self.modified = False box = group_box(self.tr("Default method"), layout=layout(Qt.Vertical)) self.controlArea.layout().addWidget(box) bgroup = QButtonGroup() for i, m in enumerate(self.METHODS[1:-1], 1): b = radio_button(m.name, checked=i == self.default_method, group=bgroup, group_id=i) box.layout().addWidget(b) self.defbggroup = bgroup bgroup.buttonClicked[int].connect(self.set_default_method) box = group_box(self.tr("Individual attribute settings"), layout=layout(Qt.Horizontal)) self.controlArea.layout().addWidget(box) self.varview = QtGui.QListView( selectionMode=QtGui.QListView.ExtendedSelection ) self.varview.setItemDelegate(DisplayFormatDelegate()) self.varmodel = itemmodels.VariableListModel() self.varview.setModel(self.varmodel) self.varview.selectionModel().selectionChanged.connect( self._on_var_selection_changed ) self.selection = self.varview.selectionModel() box.layout().addWidget(self.varview) method_layout = layout(Qt.Vertical, margins=0) box.layout().addLayout(method_layout) methodbox = group_box(layout=layout(Qt.Vertical)) bgroup = QButtonGroup() for i, m in enumerate(self.METHODS): b = radio_button(m.name, group=bgroup, group_id=i) methodbox.layout().addWidget(b) assert self.METHODS[-1].short == "value" self.value_stack = value_stack = QStackedLayout() self.value_combo = QComboBox(activated=self._on_value_changed) self.value_line = QLineEdit(editingFinished=self._on_value_changed) self.value_line.setValidator(QDoubleValidator()) value_stack.addWidget(self.value_combo) value_stack.addWidget(self.value_line) methodbox.layout().addLayout(value_stack) bgroup.buttonClicked[int].connect( self.set_method_for_current_selection ) reset_button = push_button("Restore all to default", clicked=self.reset_var_methods, default=False, autoDefault=False) method_layout.addWidget(methodbox) method_layout.addStretch(2) method_layout.addWidget(reset_button) self.varmethodbox = methodbox self.varbgroup = bgroup commitbox = group_box("Commit", layout=layout(margins=0)) cwidget = commit_widget( button_text="Commit", button_default=True, check_text="Commit on any change", checked=self.autocommit, clicked=self.commit ) def toggle_auto_commit(b): self.autocommit = b if self.modified: self.commit() cwidget.auto_commit_check.toggled[bool].connect(toggle_auto_commit) commitbox.layout().addWidget(cwidget) self.addAction(cwidget.commit_action) self.controlArea.layout().addWidget(commitbox) self.data = None self.fitter = None
class CodeCompletionWidget(QFrame): def __init__(self, editor): super(CodeCompletionWidget, self).__init__(None, Qt.FramelessWindowHint | Qt.ToolTip) self._editor = editor self.stack_layout = QStackedLayout(self) self.stack_layout.setContentsMargins(0, 0, 0, 0) self.stack_layout.setSpacing(0) self.completion_list = QListWidget() self.completion_list.setMinimumHeight(200) self.completion_list.setAlternatingRowColors(True) self._list_index = self.stack_layout.addWidget(self.completion_list) self._icons = { 'a': resources.IMAGES['attribute'], 'f': resources.IMAGES['function'], 'c': resources.IMAGES['class'], 'm': resources.IMAGES['module'] } self.cc = code_completion.CodeCompletion() self._completion_results = {} self._prefix = u'' self.setVisible(False) self.source = '' self._key_operations = { Qt.Key_Up: self._select_previous_row, Qt.Key_Down: self._select_next_row, Qt.Key_PageUp: (lambda: self._select_previous_row(6)), Qt.Key_PageDown: (lambda: self._select_next_row(6)), Qt.Key_Right: lambda: None, Qt.Key_Left: lambda: None, Qt.Key_Enter: self.pre_key_insert_completion, Qt.Key_Return: self.pre_key_insert_completion, Qt.Key_Tab: self.pre_key_insert_completion, Qt.Key_Space: self.hide_completer, Qt.Key_Escape: self.hide_completer, Qt.Key_Backtab: self.hide_completer, Qt.NoModifier: self.hide_completer, Qt.ShiftModifier: self.hide_completer, } desktop = QApplication.instance().desktop() self._desktop_geometry = desktop.availableGeometry() self.connect(self._editor.document(), SIGNAL("blockCountChanged(int)"), self.update_metadata) def _select_next_row(self, move=1): new_row = self.completion_list.currentRow() + move if new_row < self.completion_list.count(): self.completion_list.setCurrentRow(new_row) else: self.completion_list.setCurrentRow(0) return True def _select_previous_row(self, move=1): new_row = self.completion_list.currentRow() - move if new_row >= 0: self.completion_list.setCurrentRow(new_row) else: self.completion_list.setCurrentRow(self.completion_list.count() - move) return True def update_metadata(self): source = self._editor.get_text() source = source.encode(self._editor.encoding) self.cc.analyze_file('', source) def insert_completion(self, insert): if insert != self._prefix: extra = len(self._prefix) - len(insert) self._editor.textCursor().insertText(insert[extra:]) self.hide_completer() def _get_geometry(self): cr = self._editor.cursorRect() point = self._editor.mapToGlobal(cr.topLeft()) cr.moveTopLeft(point) #Check new position according desktop geometry width = (self.completion_list.sizeHintForColumn(0) + \ self.completion_list.verticalScrollBar().sizeHint().width() + 10) height = 200 orientation = (point.y() + height) < self._desktop_geometry.height() if orientation: cr.moveTop(cr.bottom()) cr.setWidth(width) cr.setHeight(height) if not orientation: cr.moveBottom(cr.top()) xpos = self._desktop_geometry.width() - (point.x() + width) if xpos < 0: cr.moveLeft(cr.left() + xpos) return cr def complete(self, results): self.add_list_items(results) self.completion_list.setCurrentRow(0) cr = self._get_geometry() self.setGeometry(cr) self.completion_list.updateGeometries() self.show() def add_list_items(self, proposals): self.completion_list.clear() for p in proposals: self.completion_list.addItem( QListWidgetItem( QIcon(self._icons.get(p[0], resources.IMAGES['attribute'])), p[1])) def set_completion_prefix(self, prefix, valid=True): self._prefix = prefix proposals = [] proposals += [('m', item) \ for item in self._completion_results.get('modules', []) \ if item.startswith(prefix)] proposals += [('c', item) \ for item in self._completion_results.get('classes', []) \ if item.startswith(prefix)] proposals += [('a', item) \ for item in self._completion_results.get('attributes', []) \ if item.startswith(prefix)] proposals += [('f', item) \ for item in self._completion_results.get('functions', []) \ if item.startswith(prefix)] if proposals and valid: self.complete(proposals) else: self.hide_completer() def fill_completer(self): source = self._editor.get_text() source = source.encode(self._editor.encoding) offset = self._editor.textCursor().position() results = self.cc.get_completion(source, offset) self._completion_results = results prefix = self._editor._text_under_cursor() self.set_completion_prefix(prefix) def hide_completer(self): self._prefix = '' self.hide() def pre_key_insert_completion(self): insert = unicode(self.completion_list.currentItem().text()) self.insert_completion(insert) self.hide_completer() return True def process_pre_key_event(self, event): if not self.isVisible() or self._editor.lang != "python": return False skip = self._key_operations.get(event.key(), lambda: False)() self._key_operations.get(event.modifiers(), lambda: False)() if skip is None: skip = False return skip def process_post_key_event(self, event): if not settings.CODE_COMPLETION or self._editor.lang != "python": return if self.isVisible(): source = self._editor.get_text() source = source.encode(self._editor.encoding) offset = self._editor.textCursor().position() prefix, valid = self.cc.get_prefix(source, offset) self.set_completion_prefix(prefix, valid) self.completion_list.setCurrentRow(0) if event.key() == Qt.Key_Period or (event.key() == Qt.Key_Space and \ event.modifiers() == Qt.ControlModifier): self.fill_completer()
class CSVImportDialog(QDialog): def __init__(self, parent=None, **kwargs): super(CSVImportDialog, self).__init__(parent, **kwargs) self.setLayout(QVBoxLayout()) self._options = None self._path = None self.__update_pending = False self._optionswidget = CSVOptionsWidget() self._optionswidget.format_changed.connect(self._invalidate_preview) self._stack = QStackedLayout() self._stack.setContentsMargins(0, 0, 0, 0) prev_box = QGroupBox("Preview") prev_box.setLayout(self._stack) self._preview = QTableView(tabKeyNavigation=False) self._preview_error = QLabel() self._stack.addWidget(self._preview) self._stack.addWidget(self._preview_error) buttons = QDialogButtonBox( orientation=Qt.Horizontal, standardButtons=(QDialogButtonBox.Ok | QDialogButtonBox.Cancel | QDialogButtonBox.Reset) ) buttons.accepted.connect(self.accept) buttons.rejected.connect(self.reject) def on_clicked(button): if buttons.buttonRole(button) == QDialogButtonBox.ResetRole: self.reset() buttons.clicked.connect(on_clicked) self.layout().addWidget(self._optionswidget) self.layout().addWidget(prev_box) self.layout().addWidget(buttons) def set_options(self, options): self._options = options self._optionswidget.set_dialect(options.dialect) self._optionswidget.set_header_format(options.header_format) self._optionswidget.set_missing_values(options.missing_values or "") self._invalidate_preview() def options(self): missing_values = self._optionswidget.missing_values() return CSV(self._optionswidget.dialect(), header_format=self._optionswidget.header_format(), missing_values=missing_values) def set_path(self, path): """Set the preview path.""" if self._path != path: self._path = path self._invalidate_preview() def path(self): """Return the preview path""" return self._path def reset(self): """Reset the options to their default values.""" self.set_options(self._options) def _invalidate_preview(self): if not self.__update_pending: self.__update_pending = True QApplication.postEvent(self, QEvent(QEvent.User)) def customEvent(self, event): if self.__update_pending: self.__update_pending = False self._update_preview() def _update_preview(self): if not self._path: return head = itertools.islice(open(self._path, "rU"), 20) head = StringIO("".join(head)) try: data = load_csv(head, **self.options()._asdict()) except csv.Error as err: self._preview_error.setText( "Cannot load data preview:\n {!s}".format(err) ) self._stack.setCurrentWidget(self._preview_error) except (Orange.data.io.CSVFormatError, Orange.data.io.VariableDefinitionError) as err: self._preview_error.setText( "Data formating error:\n {!s}".format(err) ) self._stack.setCurrentWidget(self._preview_error) except Exception as err: self._preview_error.setText( "Cannot load data preview:\n {!s}".format(err) ) self._stack.setCurrentWidget(self._preview_error) raise else: model = TableModel(data, None, self) self._preview.setModel(model) self._preview.resizeColumnsToContents() self._stack.setCurrentWidget(self._preview)
class CSVImportDialog(QDialog): def __init__(self, parent=None, **kwargs): super(CSVImportDialog, self).__init__(parent, **kwargs) self.setLayout(QVBoxLayout()) self._options = None self._path = None self.__update_pending = False self._optionswidget = CSVOptionsWidget() self._optionswidget.format_changed.connect(self._invalidate_preview) self._stack = QStackedLayout() self._stack.setContentsMargins(0, 0, 0, 0) prev_box = QGroupBox("Preview") prev_box.setLayout(self._stack) self._preview = QTableView(tabKeyNavigation=False) self._preview_error = QLabel() self._stack.addWidget(self._preview) self._stack.addWidget(self._preview_error) buttons = QDialogButtonBox( orientation=Qt.Horizontal, standardButtons=(QDialogButtonBox.Ok | QDialogButtonBox.Cancel | QDialogButtonBox.Reset)) buttons.accepted.connect(self.accept) buttons.rejected.connect(self.reject) def on_clicked(button): if buttons.buttonRole(button) == QDialogButtonBox.ResetRole: self.reset() buttons.clicked.connect(on_clicked) self.layout().addWidget(self._optionswidget) self.layout().addWidget(prev_box) self.layout().addWidget(buttons) def set_options(self, options): self._options = options self._optionswidget.set_dialect(options.dialect) self._optionswidget.set_header_format(options.header_format) self._optionswidget.set_missing_values(options.missing_values or "") self._invalidate_preview() def options(self): missing_values = self._optionswidget.missing_values() return CSV(self._optionswidget.dialect(), header_format=self._optionswidget.header_format(), missing_values=missing_values) def set_path(self, path): """Set the preview path.""" if self._path != path: self._path = path self._invalidate_preview() def path(self): """Return the preview path""" return self._path def reset(self): """Reset the options to their default values.""" self.set_options(self._options) def _invalidate_preview(self): if not self.__update_pending: self.__update_pending = True QApplication.postEvent(self, QEvent(QEvent.User)) def customEvent(self, event): if self.__update_pending: self.__update_pending = False self._update_preview() def _update_preview(self): if not self._path: return head = itertools.islice(open(self._path, "rU"), 20) head = StringIO("".join(head)) try: data = load_csv(head, **self.options()._asdict()) except csv.Error as err: self._preview_error.setText( "Cannot load data preview:\n {!s}".format(err)) self._stack.setCurrentWidget(self._preview_error) except (Orange.data.io.CSVFormatError, Orange.data.io.VariableDefinitionError) as err: self._preview_error.setText( "Data formating error:\n {!s}".format(err)) self._stack.setCurrentWidget(self._preview_error) except Exception as err: self._preview_error.setText( "Cannot load data preview:\n {!s}".format(err)) self._stack.setCurrentWidget(self._preview_error) raise else: model = TableModel(data, None, self) self._preview.setModel(model) self._preview.resizeColumnsToContents() self._stack.setCurrentWidget(self._preview)
class ComboEditor(QDialog): def __init__(self, original=False): super(ComboEditor, self).__init__(None, Qt.WindowStaysOnTopHint) self.__original = original self.__undocked = [] self._symbols_index = [] vbox = QVBoxLayout(self) vbox.setContentsMargins(0, 0, 0, 0) vbox.setSpacing(0) self.bar = ActionBar(main_combo=original) vbox.addWidget(self.bar) self.stacked = QStackedLayout() vbox.addLayout(self.stacked) self._main_container = IDE.get_service('main_container') if not self.__original: self.connect(self._main_container, SIGNAL("fileOpened(QString)"), self._file_opened_by_main) self.connect(self.bar.combo, SIGNAL("showComboSelector()"), lambda: self.emit(SIGNAL("showComboSelector()"))) self.connect(self.bar, SIGNAL("changeCurrent(PyQt_PyObject, int)"), self._set_current) self.connect(self.bar, SIGNAL("splitEditor(bool)"), self.split_editor) self.connect(self.bar, SIGNAL("runFile(QString)"), self._run_file) self.connect(self.bar, SIGNAL("closeSplit()"), lambda: self.emit(SIGNAL("closeSplit(PyQt_PyObject)"), self)) self.connect(self.bar, SIGNAL("addToProject(QString)"), self._add_to_project) self.connect(self.bar, SIGNAL("showFileInExplorer(QString)"), self._show_file_in_explorer) self.connect(self.bar, SIGNAL("goToSymbol(int)"), self._go_to_symbol) self.connect(self.bar, SIGNAL("undockEditor()"), self.undock_editor) self.connect(self.bar, SIGNAL("reopenTab(QString)"), lambda path: self._main_container.open_file(path)) self.connect(self.bar, SIGNAL("recentTabsModified()"), lambda: self._main_container.recent_files_changed()) self.connect(self.bar.code_navigator.btnPrevious, SIGNAL("clicked()"), lambda: self._navigate_code(False)) self.connect(self.bar.code_navigator.btnNext, SIGNAL("clicked()"), lambda: self._navigate_code(True)) def _navigate_code(self, val): op = self.bar.code_navigator.operation self._main_container.navigate_code_history(val, op) def currentWidget(self): return self.stacked.currentWidget() def setFocus(self): super(ComboEditor, self).setFocus() self.stacked.currentWidget().setFocus() self._editor_with_focus() def _file_opened_by_main(self, path): index = self.stacked.currentIndex() ninjaide = IDE.get_service('ide') editable = ninjaide.get_or_create_editable(path) self.add_editor(editable) self.bar.set_current_by_index(index) def add_editor(self, neditable): """Add Editor Widget to the UI area.""" if neditable.editor: if self.__original: editor = neditable.editor else: editor = self._main_container.create_editor_from_editable( neditable) self.stacked.addWidget(editor) self.bar.add_item(neditable.display_name, neditable) # Editor Signals self.connect(editor, SIGNAL("cursorPositionChanged()"), self._update_cursor_position) self.connect(editor, SIGNAL("editorFocusObtained()"), self._editor_with_focus) self.connect(editor, SIGNAL("currentLineChanged(int)"), self._set_current_symbol) self.connect(editor, SIGNAL("modificationChanged(bool)"), self._editor_modified) self.connect(neditable, SIGNAL("checkersUpdated(PyQt_PyObject)"), self._show_notification_icon) self.connect(neditable, SIGNAL("fileSaved(PyQt_PyObject)"), self._update_symbols) self.connect(neditable, SIGNAL("fileSaved(PyQt_PyObject)"), self._update_combo_info) # Connect file system signals only in the original self.connect(neditable, SIGNAL("fileClosing(PyQt_PyObject)"), self._close_file) if self.__original: self.connect(neditable, SIGNAL("neverSavedFileClosing(PyQt_PyObject)"), self._ask_for_save) self.connect(neditable, SIGNAL("fileChanged(PyQt_PyObject)"), self._file_has_been_modified) # Load Symbols self._load_symbols(neditable) def show_combo_file(self): self.bar.combo.showPopup() def show_combo_symbol(self): self.bar.symbols_combo.showPopup() def split_editor(self, orientationVertical): new_widget = ComboEditor() for neditable in self.bar.get_editables(): new_widget.add_editor(neditable) self.emit(SIGNAL("splitEditor(PyQt_PyObject, PyQt_PyObject, bool)"), self, new_widget, orientationVertical) def undock_editor(self): new_combo = ComboEditor() new_combo.setWindowTitle("NINJA-IDE") self.__undocked.append(new_combo) for neditable in self.bar.get_editables(): new_combo.add_editor(neditable) new_combo.resize(500, 500) self.connect(new_combo, SIGNAL("aboutToCloseComboEditor()"), self._remove_undock) new_combo.show() def _remove_undock(self): widget = self.sender() self.__undocked.remove(widget) def close_current_file(self): self.bar.about_to_close_file() def _close_file(self, neditable): index = self.bar.close_file(neditable) layoutItem = self.stacked.takeAt(index) #neditable.editor.completer.cc.unload_module() self._add_to_last_opened(neditable.file_path) layoutItem.widget().deleteLater() if self.stacked.isEmpty(): self.emit(SIGNAL("allFilesClosed()")) def _add_to_last_opened(self, path): if path not in settings.LAST_OPENED_FILES: settings.LAST_OPENED_FILES.append(path) if len(settings.LAST_OPENED_FILES) > settings.MAX_REMEMBER_TABS: self.__lastOpened = self.__lastOpened[1:] self.emit(SIGNAL("recentTabsModified()")) def _editor_with_focus(self): if self._main_container.current_widget is not self: self._main_container.current_widget = self editor = self.stacked.currentWidget() self._main_container.current_editor_changed( editor.neditable.file_path) self._load_symbols(editor.neditable) editor.neditable.update_checkers_display() def _ask_for_save(self, neditable): val = QMessageBox.No fileName = neditable.nfile.file_name val = QMessageBox.question( self, (self.tr('The file %s was not saved') % fileName), self.tr("Do you want to save before closing?"), QMessageBox.Yes | QMessageBox.No | QMessageBox.Cancel) if val == QMessageBox.No: neditable.nfile.close(force_close=True) elif val == QMessageBox.Yes: self._main_container.save_file(neditable.editor) neditable.nfile.close() def _file_has_been_modified(self, neditable): val = QMessageBox.No fileName = neditable.file_path val = QMessageBox.question( self, translations.TR_FILE_HAS_BEEN_MODIFIED, "%s%s" % (fileName, translations.TR_FILE_MODIFIED_OUTSIDE), QMessageBox.Yes | QMessageBox.No) if val == QMessageBox.Yes: neditable.reload_file() def _run_file(self, path): self._main_container.run_file(path) def _add_to_project(self, path): self._main_container._add_to_project(path) def _show_file_in_explorer(self, path): '''Connected to ActionBar's showFileInExplorer(QString) signal, forwards the file path on to the main container.''' self._main_container._show_file_in_explorer(path) def set_current(self, neditable): if neditable: self.bar.set_current_file(neditable) def _set_current(self, neditable, index): if neditable: self.stacked.setCurrentIndex(index) editor = self.stacked.currentWidget() self._update_cursor_position(ignore_sender=True) editor.setFocus() self._main_container.current_editor_changed( neditable.file_path) self._load_symbols(neditable) neditable.update_checkers_display() def widget(self, index): return self.stacked.widget(index) def count(self): """Return the number of editors opened.""" return self.stacked.count() def _update_cursor_position(self, ignore_sender=False): obj = self.sender() editor = self.stacked.currentWidget() # Check if it's current to avoid signals from other splits. if ignore_sender or editor == obj: line = editor.textCursor().blockNumber() + 1 col = editor.textCursor().columnNumber() self.bar.update_line_col(line, col) def _set_current_symbol(self, line, ignore_sender=False): obj = self.sender() editor = self.stacked.currentWidget() # Check if it's current to avoid signals from other splits. if ignore_sender or editor == obj: index = bisect.bisect(self._symbols_index, line) if (index >= len(self._symbols_index) or self._symbols_index[index] > (line + 1)): index -= 1 self.bar.set_current_symbol(index) def _editor_modified(self, value): obj = self.sender() neditable = obj.neditable if value: text = "%s (*)" % neditable.display_name self.bar.update_item_text(neditable, text) else: self.bar.update_item_text(neditable, neditable.display_name) def _go_to_symbol(self, index): line = self._symbols_index[index] editor = self.stacked.currentWidget() editor.go_to_line(line) def _update_symbols(self, neditable): editor = self.stacked.currentWidget() # Check if it's current to avoid signals from other splits. if editor == neditable.editor: self._load_symbols(neditable) def _update_combo_info(self, neditable): self.bar.update_item_text(neditable, neditable.display_name) self._main_container.current_editor_changed(neditable.file_path) def _load_symbols(self, neditable): symbols_handler = handlers.get_symbols_handler('py') source = neditable.editor.toPlainText() source = source.encode(neditable.editor.encoding) symbols, symbols_simplified = symbols_handler.obtain_symbols( source, simple=True) self._symbols_index = sorted(symbols_simplified.keys()) symbols_simplified = sorted( list(symbols_simplified.items()), key=lambda x: x[0]) self.bar.add_symbols(symbols_simplified) line = neditable.editor.textCursor().blockNumber() self._set_current_symbol(line, True) tree_symbols = IDE.get_service('symbols_explorer') tree_symbols.update_symbols_tree(symbols, neditable.file_path) def _show_notification_icon(self, neditable): checkers = neditable.sorted_checkers icon = QIcon() for items in checkers: checker, color, _ = items if checker.checks: if isinstance(checker.checker_icon, int): icon = self.style().standardIcon(checker.checker_icon) elif isinstance(checker.checker_icon, str): icon = QIcon(checker.checker_icon) break self.bar.update_item_icon(neditable, icon) def show_menu_navigation(self): self.bar.code_navigator.show_menu_navigation() def closeEvent(self, event): self.emit(SIGNAL("aboutToCloseComboEditor()")) super(ComboEditor, self).closeEvent(event) def reject(self): if not self.__original: super(ComboEditor, self).reject()
class CodeCompletionWidget(QFrame): def __init__(self, editor): super(CodeCompletionWidget, self).__init__(None, Qt.FramelessWindowHint | Qt.ToolTip) self._editor = editor self._revision = 0 self._block = 0 self.stack_layout = QStackedLayout(self) self.stack_layout.setContentsMargins(0, 0, 0, 0) self.stack_layout.setSpacing(0) self.completion_list = QListWidget() self.completion_list.setMinimumHeight(200) self.completion_list.setAlternatingRowColors(True) self._list_index = self.stack_layout.addWidget(self.completion_list) self._icons = { 'a': resources.IMAGES['attribute'], 'f': resources.IMAGES['function'], 'c': resources.IMAGES['class'], 'm': resources.IMAGES['module'] } self.cc = code_completion.CodeCompletion() self._completion_results = {} self._prefix = '' self.setVisible(False) self.source = '' self._key_operations = { Qt.Key_Up: self._select_previous_row, Qt.Key_Down: self._select_next_row, Qt.Key_PageUp: (lambda: self._select_previous_row(6)), Qt.Key_PageDown: (lambda: self._select_next_row(6)), Qt.Key_Right: lambda: None, Qt.Key_Left: lambda: None, Qt.Key_Enter: self.pre_key_insert_completion, Qt.Key_Return: self.pre_key_insert_completion, Qt.Key_Tab: self.pre_key_insert_completion, Qt.Key_Space: self.hide_completer, Qt.Key_Escape: self.hide_completer, Qt.Key_Backtab: self.hide_completer, Qt.NoModifier: self.hide_completer, Qt.ShiftModifier: self.hide_completer, } self.desktop = QApplication.instance().desktop() self.connect(self.completion_list, SIGNAL("itemClicked(QListWidgetItem*)"), self.pre_key_insert_completion) self.connect(self._editor.document(), SIGNAL("cursorPositionChanged(QTextCursor)"), self.update_metadata) def _select_next_row(self, move=1): new_row = self.completion_list.currentRow() + move if new_row < self.completion_list.count(): self.completion_list.setCurrentRow(new_row) else: self.completion_list.setCurrentRow(0) return True def _select_previous_row(self, move=1): new_row = self.completion_list.currentRow() - move if new_row >= 0: self.completion_list.setCurrentRow(new_row) else: self.completion_list.setCurrentRow(self.completion_list.count() - move) return True def update_metadata(self, cursor): if settings.CODE_COMPLETION: if self._editor.document().revision() != self._revision and \ cursor.block().blockNumber() != self._block: source = self._editor.get_text() source = source.encode(self._editor.encoding) self.cc.analyze_file(self._editor.ID, source, self._editor.indent, self._editor.useTabs) self._revision = self._editor.document().revision() self._block = cursor.block().blockNumber() def insert_completion(self, insert, type_=ord('a')): if insert != self._prefix: closing = '' if type_ in (ord('f'), ord('c')): closing = '()' extra = len(self._prefix) - len(insert) insertion = '%s%s' % (insert[extra:], closing) self._editor.textCursor().insertText(insertion) self.hide_completer() def _get_geometry(self): cr = self._editor.cursorRect() desktop_geometry = self.desktop.availableGeometry(self._editor) point = self._editor.mapToGlobal(cr.topLeft()) cr.moveTopLeft(point) #Check new position according desktop geometry width = (self.completion_list.sizeHintForColumn(0) + self.completion_list.verticalScrollBar().sizeHint().width() + 10) height = 200 orientation = (point.y() + height) < desktop_geometry.height() if orientation: cr.moveTop(cr.bottom()) cr.setWidth(width) cr.setHeight(height) if not orientation: cr.moveBottom(cr.top()) xpos = desktop_geometry.width() - (point.x() + width) if xpos < 0: cr.moveLeft(cr.left() + xpos) return cr def complete(self, results): self.add_list_items(results) self.completion_list.setCurrentRow(0) cr = self._get_geometry() self.setGeometry(cr) self.completion_list.updateGeometries() self.show() def add_list_items(self, proposals): self.completion_list.clear() for p in proposals: self.completion_list.addItem( QListWidgetItem(QIcon( self._icons.get(p[0], resources.IMAGES['attribute'])), p[1], type=ord(p[0]))) def set_completion_prefix(self, prefix, valid=True): self._prefix = prefix proposals = [] proposals += [('m', item) for item in self._completion_results.get('modules', []) if item.startswith(prefix)] proposals += [('c', item) for item in self._completion_results.get('classes', []) if item.startswith(prefix)] proposals += [ ('a', item) for item in self._completion_results.get('attributes', []) if item.startswith(prefix) ] proposals += [ ('f', item) for item in self._completion_results.get('functions', []) if item.startswith(prefix) ] if proposals and valid: self.complete(proposals) else: self.hide_completer() def _invalid_completion_position(self): result = False cursor = self._editor.textCursor() cursor.movePosition(QTextCursor.StartOfLine, QTextCursor.KeepAnchor) selection = cursor.selectedText()[:-1].split(' ') if len(selection) == 0 or selection[-1] == '' or \ selection[-1].isdigit(): result = True return result def fill_completer(self, force_completion=False): if not force_completion and (self._editor.cursor_inside_string() or self._editor.cursor_inside_comment() or self._invalid_completion_position()): return source = self._editor.get_text() source = source.encode(self._editor.encoding) offset = self._editor.textCursor().position() results = self.cc.get_completion(source, offset) self._completion_results = results if force_completion: cursor = self._editor.textCursor() cursor.movePosition(QTextCursor.StartOfWord, QTextCursor.KeepAnchor) prefix = cursor.selectedText() else: prefix = self._editor._text_under_cursor() self.set_completion_prefix(prefix) def hide_completer(self): self._prefix = '' self.hide() def pre_key_insert_completion(self): type_ = ord('a') current = self.completion_list.currentItem() insert = current.text() if not insert.endswith(')'): type_ = current.type() self.insert_completion(insert, type_) self.hide_completer() return True def process_pre_key_event(self, event): if not self.isVisible() or self._editor.lang != "python": return False skip = self._key_operations.get(event.key(), lambda: False)() self._key_operations.get(event.modifiers(), lambda: False)() if skip is None: skip = False return skip def process_post_key_event(self, event): if not settings.CODE_COMPLETION or self._editor.lang != "python": return if self.isVisible(): source = self._editor.get_text() source = source.encode(self._editor.encoding) offset = self._editor.textCursor().position() prefix, valid = self.cc.get_prefix(source, offset) self.set_completion_prefix(prefix, valid) self.completion_list.setCurrentRow(0) force_completion = (event.key() == Qt.Key_Space and event.modifiers() == Qt.ControlModifier) if event.key() == Qt.Key_Period or force_completion: self.fill_completer(force_completion)
class ProjectTreeColumn(QDialog): def __init__(self, parent=None): super(ProjectTreeColumn, self).__init__(parent, Qt.WindowStaysOnTopHint) vbox = QVBoxLayout(self) vbox.setSizeConstraint(QVBoxLayout.SetDefaultConstraint) vbox.setContentsMargins(0, 0, 0, 0) self._buttons = [] self._combo_project = QComboBox() self._combo_project.setMinimumHeight(30) self._combo_project.setContextMenuPolicy(Qt.CustomContextMenu) vbox.addWidget(self._combo_project) self._projects_area = QStackedLayout() logger.debug("This is the projects area") logger.debug(self._projects_area) vbox.addLayout(self._projects_area) self.projects = [] self.connect(self._combo_project, SIGNAL("currentIndexChanged(int)"), self._change_current_project) self.connect(self._combo_project, SIGNAL("customContextMenuRequested(const QPoint &)"), self.context_menu_for_root) connections = ( { 'target': 'main_container', 'signal_name': 'addToProject(QString)', 'slot': self._add_file_to_project }, { 'target': 'main_container', 'signal_name': 'showFileInExplorer(QString)', 'slot': self._show_file_in_explorer }, ) IDE.register_service('projects_explorer', self) IDE.register_signals('projects_explorer', connections) ExplorerContainer.register_tab(translations.TR_TAB_PROJECTS, self) #FIXME: Should have a ninja settings object that stores tree state #FIXME: Or bettter, application data object #TODO: check this: #self.connect(ide, SIGNAL("goingDown()"), #self.tree_projects.shutdown) #def close_project_signal(): #self.emit(SIGNAL("updateLocator()")) def install_tab(self): ide = IDE.get_service('ide') ui_tools.install_shortcuts(self, actions.PROJECTS_TREE_ACTIONS, ide) self.connect(ide, SIGNAL("goingDown()"), self.close) def load_session_projects(self, projects): for project in projects: if os.path.exists(project): self._open_project_folder(project) def open_project_folder(self, folderName=None): if settings.WORKSPACE: directory = settings.WORKSPACE else: directory = os.path.expanduser("~") if folderName is None: folderName = QFileDialog.getExistingDirectory( self, translations.TR_OPEN_PROJECT_DIRECTORY, directory) logger.debug("Choosing Foldername") if folderName: logger.debug("Opening %s" % folderName) self._open_project_folder(folderName) def _open_project_folder(self, folderName): ninjaide = IDE.get_service("ide") project = NProject(folderName) qfsm = ninjaide.filesystem.open_project(project) if qfsm: self.add_project(project) self.emit(SIGNAL("updateLocator()")) self.save_recent_projects(folderName) main_container = IDE.get_service('main_container') if main_container: main_container.show_editor_area() def _add_file_to_project(self, path): """Add the file for 'path' in the project the user choose here.""" if self._active_project: pathProject = [self._active_project.project] addToProject = add_to_project.AddToProject(pathProject, self) addToProject.exec_() if not addToProject.pathSelected: return main_container = IDE.get_service('main_container') if not main_container: return editorWidget = main_container.get_current_editor() if not editorWidget.file_path: name = QInputDialog.getText( None, translations.TR_ADD_FILE_TO_PROJECT, translations.TR_FILENAME + ": ")[0] if not name: QMessageBox.information( self, translations.TR_INVALID_FILENAME, translations.TR_INVALID_FILENAME_ENTER_A_FILENAME) return else: name = file_manager.get_basename(editorWidget.file_path) new_path = file_manager.create_path(addToProject.pathSelected, name) ide_srv = IDE.get_service("ide") old_file = ide_srv.get_or_create_nfile(path) new_file = old_file.save(editorWidget.get_text(), new_path) #FIXME: Make this file replace the original in the open tab else: pass # Message about no project def _show_file_in_explorer(self, path): '''Iterate through the list of available projects and show the current file in the explorer view for the first project that contains it (i.e. if the same file is included in multiple open projects, the path will be expanded for the first project only). Note: This slot is connected to the main container's "showFileInExplorer(QString)" signal.''' for project in self.projects: index = project.model().index(path) if index.isValid(): # Show the explorer if it is currently hidden central = IDE.get_service('central_container') if central and not central.is_lateral_panel_visible(): central.change_lateral_visibility() # This highlights the index in the tree for us project.setCurrentIndex(index) # Loop through the parents to expand the tree # all the way up to the selected index. while index.isValid(): project.expand(index) index = index.parent() break def add_project(self, project): if project not in self.projects: self._combo_project.addItem(project.name) ptree = TreeProjectsWidget(project) self._projects_area.addWidget(ptree) self.connect(ptree, SIGNAL("closeProject(PyQt_PyObject)"), self._close_project) pmodel = project.model ptree.setModel(pmodel) pindex = pmodel.index(pmodel.rootPath()) ptree.setRootIndex(pindex) self.projects.append(ptree) current_index = self._projects_area.count() self._projects_area.setCurrentIndex(current_index - 1) self._combo_project.setCurrentIndex(current_index - 1) def _close_project(self, widget): """Close the project related to the tree widget.""" index = self._projects_area.currentIndex() self.projects.remove(widget) self._projects_area.takeAt(index) self._combo_project.removeItem(index) index = self._combo_project.currentIndex() self._projects_area.setCurrentIndex(index) ninjaide = IDE.get_service('ide') ninjaide.filesystem.close_project(widget.project.path) widget.deleteLater() def _change_current_project(self, index): self._projects_area.setCurrentIndex(index) def close_opened_projects(self): for project in reversed(self.projects): self._close_project(project) def save_project(self): """Save all the opened files that belongs to the actual project.""" if self._active_project: path = self._projects_area.currentWidget().project.path main_container = IDE.get_service('main_container') if path and main_container: main_container.save_project(path) def create_new_project(self): wizard = new_project_manager.NewProjectManager(self) wizard.show() @property def current_project(self): if self._projects_area.count() > 0: return self._projects_area.currentWidget().project @property def current_tree(self): return self._projects_area.currentWidget() def save_recent_projects(self, folder): settings = IDE.data_settings() recent_project_list = settings.value('recentProjects', {}) #if already exist on the list update the date time projectProperties = json_manager.read_ninja_project(folder) name = projectProperties.get('name', '') description = projectProperties.get('description', '') if name == '': name = file_manager.get_basename(folder) if description == '': description = translations.TR_NO_DESCRIPTION if folder in recent_project_list: properties = recent_project_list[folder] properties["lastopen"] = QDateTime.currentDateTime() properties["name"] = name properties["description"] = description recent_project_list[folder] = properties else: recent_project_list[folder] = { "name": name, "description": description, "isFavorite": False, "lastopen": QDateTime.currentDateTime() } #if the length of the project list it's high that 10 then delete #the most old #TODO: add the length of available projects to setting if len(recent_project_list) > 10: del recent_project_list[self.find_most_old_open( recent_project_list)] settings.setValue('recentProjects', recent_project_list) def find_most_old_open(self, recent_project_list): listFounder = [] for recent_project_path, content in list(recent_project_list.items()): listFounder.append( (recent_project_path, int(content["lastopen"].toString("yyyyMMddHHmmzzz")))) listFounder = sorted(listFounder, key=lambda date: listFounder[1], reverse=True) # sort by date last used return listFounder[0][0] def reject(self): if self.parent() is None: self.emit(SIGNAL("dockWidget(PyQt_PyObject)"), self) def closeEvent(self, event): self.emit(SIGNAL("dockWidget(PyQt_PyObject)"), self) event.ignore() def context_menu_for_root(self): menu = QMenu(self) path = self.current_tree.project.path action_add_file = menu.addAction(QIcon(":img/new"), translations.TR_ADD_NEW_FILE) action_add_folder = menu.addAction(QIcon(":img/openProj"), translations.TR_ADD_NEW_FOLDER) action_create_init = menu.addAction(translations.TR_CREATE_INIT) self.connect(action_add_file, SIGNAL("triggered()"), lambda: self.current_tree._add_new_file(path)) self.connect(action_add_folder, SIGNAL("triggered()"), lambda: self.current_tree._add_new_folder(path)) self.connect(action_create_init, SIGNAL("triggered()"), lambda: self.current_tree._create_init(path)) menu.addSeparator() actionRunProject = menu.addAction(QIcon(":img/play"), translations.TR_RUN_PROJECT) self.connect(actionRunProject, SIGNAL("triggered()"), self.current_tree._execute_project) if self.current_tree._added_to_console: actionRemoveFromConsole = menu.addAction( translations.TR_REMOVE_PROJECT_FROM_PYTHON_CONSOLE) self.connect(actionRemoveFromConsole, SIGNAL("triggered()"), self.current_tree._remove_project_from_console) else: actionAdd2Console = menu.addAction( translations.TR_ADD_PROJECT_TO_PYTHON_CONSOLE) self.connect(actionAdd2Console, SIGNAL("triggered()"), self.current_tree._add_project_to_console) actionShowFileSizeInfo = menu.addAction(translations.TR_SHOW_FILESIZE) self.connect(actionShowFileSizeInfo, SIGNAL("triggered()"), self.current_tree.show_filesize_info) actionProperties = menu.addAction(QIcon(":img/pref"), translations.TR_PROJECT_PROPERTIES) self.connect(actionProperties, SIGNAL("triggered()"), self.current_tree.open_project_properties) menu.addSeparator() action_close = menu.addAction( self.style().standardIcon(QStyle.SP_DialogCloseButton), translations.TR_CLOSE_PROJECT) self.connect(action_close, SIGNAL("triggered()"), self.current_tree._close_project) #menu for the project for m in self.current_tree.extra_menus_by_scope['project']: if isinstance(m, QMenu): menu.addSeparator() menu.addMenu(m) #show the menu! menu.exec_(QCursor.pos())
class Preferences(QDialog): configuration = {} weight = 0 def __init__(self, parent=None): super(Preferences, self).__init__(parent, Qt.Dialog) self.setWindowTitle(translations.TR_PREFERENCES_TITLE) self.setMinimumSize(QSize(800, 600)) self.setMaximumSize(QSize(0, 0)) vbox = QVBoxLayout(self) hbox = QHBoxLayout() vbox.setContentsMargins(0, 0, 5, 5) hbox.setContentsMargins(0, 0, 0, 0) self.tree = QTreeWidget() self.tree.header().setHidden(True) self.tree.setSelectionMode(QTreeWidget.SingleSelection) self.tree.setAnimated(True) self.tree.header().setHorizontalScrollMode( QAbstractItemView.ScrollPerPixel) self.tree.header().setResizeMode(0, QHeaderView.ResizeToContents) self.tree.header().setStretchLastSection(False) self.tree.setFixedWidth(200) self.stacked = QStackedLayout() hbox.addWidget(self.tree) hbox.addLayout(self.stacked) vbox.addLayout(hbox) hbox_footer = QHBoxLayout() self._btnSave = QPushButton(translations.TR_SAVE) self._btnCancel = QPushButton(translations.TR_CANCEL) hbox_footer.addSpacerItem(QSpacerItem(1, 0, QSizePolicy.Expanding)) hbox_footer.addWidget(self._btnCancel) hbox_footer.addWidget(self._btnSave) vbox.addLayout(hbox_footer) self.connect(self.tree, SIGNAL("itemSelectionChanged()"), self._change_current) self.connect(self._btnCancel, SIGNAL("clicked()"), self.close) self.connect(self._btnSave, SIGNAL("clicked()"), self._save_preferences) self.load_ui() self.tree.setCurrentItem(self.tree.topLevelItem(0)) def _save_preferences(self): self.emit(SIGNAL("savePreferences()")) self.close() def load_ui(self): sections = sorted( list(Preferences.configuration.keys()), key=lambda item: Preferences.configuration[item]['weight']) for section in sections: text = Preferences.configuration[section]['text'] Widget = Preferences.configuration[section]['widget'] widget = Widget(self) area = QScrollArea() area.setWidgetResizable(True) area.setWidget(widget) index = self.stacked.addWidget(area) item = QTreeWidgetItem([text]) item.setData(0, Qt.UserRole, index) self.tree.addTopLevelItem(item) #Sort Item Children subcontent = Preferences.configuration[section].get( 'subsections', {}) subsections = sorted(list(subcontent.keys()), key=lambda item: subcontent[item]['weight']) for sub in subsections: text = subcontent[sub]['text'] Widget = subcontent[sub]['widget'] widget = Widget(self) area = QScrollArea() area.setWidgetResizable(True) area.setWidget(widget) index = self.stacked.addWidget(area) subitem = QTreeWidgetItem([text]) subitem.setData(0, Qt.UserRole, index) item.addChild(subitem) self.tree.expandAll() def _change_current(self): item = self.tree.currentItem() index = item.data(0, Qt.UserRole) self.stacked.setCurrentIndex(index) @classmethod def register_configuration(cls, section, widget, text, weight=None, subsection=None): if weight is None: Preferences.weight += 1 weight = Preferences.weight if not subsection: Preferences.configuration[section] = { 'widget': widget, 'weight': weight, 'text': text } else: config = Preferences.configuration.get(section, {}) if not config: config[section] = {'widget': None, 'weight': 100} subconfig = config.get('subsections', {}) subconfig[subsection] = { 'widget': widget, 'weight': weight, 'text': text } config['subsections'] = subconfig Preferences.configuration[section] = config
class MusicPreviewWidget(QWidget): def __init__(self, parent=None): super(MusicPreviewWidget, self).__init__(parent) self._lastbuildtime = 10.0 self._running = None self._current = None self._chooserLabel = QLabel() self._chooser = QComboBox(self, activated=self.selectDocument) self._log = log.Log() self._view = popplerview.View() self._progress = widgets.progressbar.TimedProgressBar() self._stack = QStackedLayout() self._top = QWidget() layout = QVBoxLayout() self.setLayout(layout) layout.addWidget(self._top) layout.addLayout(self._stack) layout.addWidget(self._progress) top = QHBoxLayout() top.setContentsMargins(0, 0, 0, 0) top.setSpacing(2) self._top.setLayout(top) top.addWidget(self._chooserLabel) top.addWidget(self._chooser) top.addStretch(1) self._stack.addWidget(self._log) self._stack.addWidget(self._view) self._top.hide() app.aboutToQuit.connect(self.cleanup) app.translateUI(self) def translateUI(self): self._chooserLabel.setText(_("Document:")) def preview(self, text, title=None): """Runs LilyPond on the given text and shows the resulting PDF.""" j = self._running = MusicPreviewJob(text, title) j.done.connect(self._done) self._log.clear() self._log.connectJob(j) j.start() self._progress.start(self._lastbuildtime) def _done(self, success): self._progress.stop(False) pdfs = self._running.resultfiles() self.setDocuments(pdfs) if not pdfs: self._stack.setCurrentWidget(self._log) return self._lastbuildtime = self._running.elapsed_time() self._stack.setCurrentWidget(self._view) if self._current: self._current.cleanup() self._current = self._running # keep the tempdir self._running = None def setDocuments(self, pdfs): """Loads the given PDF path names in the UI.""" self._documents = [popplertools.Document(name) for name in pdfs] self._chooser.clear() self._chooser.addItems([d.name() for d in self._documents]) self._top.setVisible(len(self._documents) > 1) if pdfs: self._chooser.setCurrentIndex(0) self.selectDocument(0) else: self._view.clear() def selectDocument(self, index): doc = self._documents[index].document() if doc: self._view.load(doc) def cleanup(self): if self._running: self._running.abort() self._running.cleanup() self._running = None if self._current: self._current.cleanup() self._current = None self._stack.setCurrentWidget(self._log) self._top.hide() self._view.clear() def print_(self): """Prints the currently displayed document.""" if self._documents: doc = self._documents[self._chooser.currentIndex()] import popplerprint popplerprint.printDocument(doc, self)
class ProjectTreeColumn(QDialog): def __init__(self, parent=None): super(ProjectTreeColumn, self).__init__(parent, Qt.WindowStaysOnTopHint) vbox = QVBoxLayout(self) vbox.setSizeConstraint(QVBoxLayout.SetDefaultConstraint) vbox.setContentsMargins(0, 0, 0, 0) self._buttons = [] self._combo_project = QComboBox() self._combo_project.setMinimumHeight(30) self._combo_project.setContextMenuPolicy(Qt.CustomContextMenu) vbox.addWidget(self._combo_project) self._projects_area = QStackedLayout() logger.debug("This is the projects area") logger.debug(self._projects_area) vbox.addLayout(self._projects_area) self.projects = [] self.connect(self._combo_project, SIGNAL("currentIndexChanged(int)"), self._change_current_project) self.connect(self._combo_project, SIGNAL( "customContextMenuRequested(const QPoint &)"), self.context_menu_for_root) connections = ( {'target': 'main_container', 'signal_name': 'addToProject(QString)', 'slot': self._add_file_to_project}, {'target': 'main_container', 'signal_name': 'showFileInExplorer(QString)', 'slot': self._show_file_in_explorer}, ) IDE.register_service('projects_explorer', self) IDE.register_signals('projects_explorer', connections) ExplorerContainer.register_tab(translations.TR_TAB_PROJECTS, self) #FIXME: Should have a ninja settings object that stores tree state #FIXME: Or bettter, application data object #TODO: check this: #self.connect(ide, SIGNAL("goingDown()"), #self.tree_projects.shutdown) #def close_project_signal(): #self.emit(SIGNAL("updateLocator()")) def install_tab(self): ide = IDE.get_service('ide') ui_tools.install_shortcuts(self, actions.PROJECTS_TREE_ACTIONS, ide) self.connect(ide, SIGNAL("goingDown()"), self.close) def load_session_projects(self, projects): for project in projects: if os.path.exists(project): self._open_project_folder(project) def open_project_folder(self, folderName=None): if settings.WORKSPACE: directory = settings.WORKSPACE else: directory = os.path.expanduser("~") if folderName is None: folderName = QFileDialog.getExistingDirectory( self, translations.TR_OPEN_PROJECT_DIRECTORY, directory) logger.debug("Choosing Foldername") if folderName: logger.debug("Opening %s" % folderName) self._open_project_folder(folderName) def _open_project_folder(self, folderName): ninjaide = IDE.get_service("ide") project = NProject(folderName) qfsm = ninjaide.filesystem.open_project(project) if qfsm: self.add_project(project) self.emit(SIGNAL("updateLocator()")) self.save_recent_projects(folderName) main_container = IDE.get_service('main_container') if main_container: main_container.show_editor_area() def _add_file_to_project(self, path): """Add the file for 'path' in the project the user choose here.""" if self._active_project: pathProject = [self._active_project.project] addToProject = add_to_project.AddToProject(pathProject, self) addToProject.exec_() if not addToProject.pathSelected: return main_container = IDE.get_service('main_container') if not main_container: return editorWidget = main_container.get_current_editor() if not editorWidget.file_path: name = QInputDialog.getText(None, translations.TR_ADD_FILE_TO_PROJECT, translations.TR_FILENAME + ": ")[0] if not name: QMessageBox.information( self, translations.TR_INVALID_FILENAME, translations.TR_INVALID_FILENAME_ENTER_A_FILENAME) return else: name = file_manager.get_basename(editorWidget.file_path) new_path = file_manager.create_path(addToProject.pathSelected, name) ide_srv = IDE.get_service("ide") old_file = ide_srv.get_or_create_nfile(path) new_file = old_file.save(editorWidget.get_text(), new_path) #FIXME: Make this file replace the original in the open tab else: pass # Message about no project def _show_file_in_explorer(self, path): '''Iterate through the list of available projects and show the current file in the explorer view for the first project that contains it (i.e. if the same file is included in multiple open projects, the path will be expanded for the first project only). Note: This slot is connected to the main container's "showFileInExplorer(QString)" signal.''' for project in self.projects: index = project.model().index(path) if index.isValid(): # Show the explorer if it is currently hidden central = IDE.get_service('central_container') if central and not central.is_lateral_panel_visible(): central.change_lateral_visibility() # This highlights the index in the tree for us project.setCurrentIndex(index) # Loop through the parents to expand the tree # all the way up to the selected index. while index.isValid(): project.expand(index) index = index.parent() break def add_project(self, project): if project not in self.projects: self._combo_project.addItem(project.name) ptree = TreeProjectsWidget(project) self._projects_area.addWidget(ptree) self.connect(ptree, SIGNAL("closeProject(PyQt_PyObject)"), self._close_project) pmodel = project.model ptree.setModel(pmodel) pindex = pmodel.index(pmodel.rootPath()) ptree.setRootIndex(pindex) self.projects.append(ptree) current_index = self._projects_area.count() self._projects_area.setCurrentIndex(current_index - 1) self._combo_project.setCurrentIndex(current_index - 1) def _close_project(self, widget): """Close the project related to the tree widget.""" index = self._projects_area.currentIndex() self.projects.remove(widget) self._projects_area.takeAt(index) self._combo_project.removeItem(index) index = self._combo_project.currentIndex() self._projects_area.setCurrentIndex(index) ninjaide = IDE.get_service('ide') ninjaide.filesystem.close_project(widget.project.path) widget.deleteLater() def _change_current_project(self, index): self._projects_area.setCurrentIndex(index) def close_opened_projects(self): for project in reversed(self.projects): self._close_project(project) def save_project(self): """Save all the opened files that belongs to the actual project.""" if self._active_project: path = self._projects_area.currentWidget().project.path main_container = IDE.get_service('main_container') if path and main_container: main_container.save_project(path) def create_new_project(self): wizard = new_project_manager.NewProjectManager(self) wizard.show() @property def current_project(self): if self._projects_area.count() > 0: return self._projects_area.currentWidget().project @property def current_tree(self): return self._projects_area.currentWidget() def save_recent_projects(self, folder): settings = IDE.data_settings() recent_project_list = settings.value('recentProjects', {}) #if already exist on the list update the date time projectProperties = json_manager.read_ninja_project(folder) name = projectProperties.get('name', '') description = projectProperties.get('description', '') if name == '': name = file_manager.get_basename(folder) if description == '': description = translations.TR_NO_DESCRIPTION if folder in recent_project_list: properties = recent_project_list[folder] properties["lastopen"] = QDateTime.currentDateTime() properties["name"] = name properties["description"] = description recent_project_list[folder] = properties else: recent_project_list[folder] = { "name": name, "description": description, "isFavorite": False, "lastopen": QDateTime.currentDateTime()} #if the length of the project list it's high that 10 then delete #the most old #TODO: add the length of available projects to setting if len(recent_project_list) > 10: del recent_project_list[self.find_most_old_open( recent_project_list)] settings.setValue('recentProjects', recent_project_list) def find_most_old_open(self, recent_project_list): listFounder = [] for recent_project_path, content in list(recent_project_list.items()): listFounder.append((recent_project_path, int( content["lastopen"].toString("yyyyMMddHHmmzzz")))) listFounder = sorted(listFounder, key=lambda date: listFounder[1], reverse=True) # sort by date last used return listFounder[0][0] def reject(self): if self.parent() is None: self.emit(SIGNAL("dockWidget(PyQt_PyObject)"), self) def closeEvent(self, event): self.emit(SIGNAL("dockWidget(PyQt_PyObject)"), self) event.ignore() def context_menu_for_root(self): menu = QMenu(self) path = self.current_tree.project.path action_add_file = menu.addAction(QIcon(":img/new"), translations.TR_ADD_NEW_FILE) action_add_folder = menu.addAction(QIcon( ":img/openProj"), translations.TR_ADD_NEW_FOLDER) action_create_init = menu.addAction(translations.TR_CREATE_INIT) self.connect(action_add_file, SIGNAL("triggered()"), lambda: self.current_tree._add_new_file(path)) self.connect(action_add_folder, SIGNAL("triggered()"), lambda: self.current_tree._add_new_folder(path)) self.connect(action_create_init, SIGNAL("triggered()"), lambda: self.current_tree._create_init(path)) menu.addSeparator() actionRunProject = menu.addAction(QIcon( ":img/play"), translations.TR_RUN_PROJECT) self.connect(actionRunProject, SIGNAL("triggered()"), self.current_tree._execute_project) if self.current_tree._added_to_console: actionRemoveFromConsole = menu.addAction( translations.TR_REMOVE_PROJECT_FROM_PYTHON_CONSOLE) self.connect(actionRemoveFromConsole, SIGNAL("triggered()"), self.current_tree._remove_project_from_console) else: actionAdd2Console = menu.addAction( translations.TR_ADD_PROJECT_TO_PYTHON_CONSOLE) self.connect(actionAdd2Console, SIGNAL("triggered()"), self.current_tree._add_project_to_console) actionShowFileSizeInfo = menu.addAction(translations.TR_SHOW_FILESIZE) self.connect(actionShowFileSizeInfo, SIGNAL("triggered()"), self.current_tree.show_filesize_info) actionProperties = menu.addAction(QIcon(":img/pref"), translations.TR_PROJECT_PROPERTIES) self.connect(actionProperties, SIGNAL("triggered()"), self.current_tree.open_project_properties) menu.addSeparator() action_close = menu.addAction( self.style().standardIcon(QStyle.SP_DialogCloseButton), translations.TR_CLOSE_PROJECT) self.connect(action_close, SIGNAL("triggered()"), self.current_tree._close_project) #menu for the project for m in self.current_tree.extra_menus_by_scope['project']: if isinstance(m, QMenu): menu.addSeparator() menu.addMenu(m) #show the menu! menu.exec_(QCursor.pos())
class CodeCompletionWidget(QFrame): def __init__(self, editor): super(CodeCompletionWidget, self).__init__( None, Qt.FramelessWindowHint | Qt.ToolTip) self._editor = editor self._revision = 0 self._block = 0 self.stack_layout = QStackedLayout(self) self.stack_layout.setContentsMargins(0, 0, 0, 0) self.stack_layout.setSpacing(0) self.completion_list = QListWidget() self.completion_list.setMinimumHeight(200) self.completion_list.setAlternatingRowColors(True) self._list_index = self.stack_layout.addWidget(self.completion_list) self._icons = {'a': resources.IMAGES['attribute'], 'f': resources.IMAGES['function'], 'c': resources.IMAGES['class'], 'm': resources.IMAGES['module']} self.cc = code_completion.CodeCompletion() self._completion_results = {} self._prefix = u'' self.setVisible(False) self.source = '' self._key_operations = { Qt.Key_Up: self._select_previous_row, Qt.Key_Down: self._select_next_row, Qt.Key_PageUp: (lambda: self._select_previous_row(6)), Qt.Key_PageDown: (lambda: self._select_next_row(6)), Qt.Key_Right: lambda: None, Qt.Key_Left: lambda: None, Qt.Key_Enter: self.pre_key_insert_completion, Qt.Key_Return: self.pre_key_insert_completion, Qt.Key_Tab: self.pre_key_insert_completion, Qt.Key_Space: self.hide_completer, Qt.Key_Escape: self.hide_completer, Qt.Key_Backtab: self.hide_completer, Qt.NoModifier: self.hide_completer, Qt.ShiftModifier: self.hide_completer, } self.desktop = QApplication.instance().desktop() self.connect(self.completion_list, SIGNAL("itemClicked(QListWidgetItem*)"), self.pre_key_insert_completion) self.connect(self._editor.document(), SIGNAL("cursorPositionChanged(QTextCursor)"), self.update_metadata) def _select_next_row(self, move=1): new_row = self.completion_list.currentRow() + move if new_row < self.completion_list.count(): self.completion_list.setCurrentRow(new_row) else: self.completion_list.setCurrentRow(0) return True def _select_previous_row(self, move=1): new_row = self.completion_list.currentRow() - move if new_row >= 0: self.completion_list.setCurrentRow(new_row) else: self.completion_list.setCurrentRow( self.completion_list.count() - move) return True def update_metadata(self, cursor): if settings.CODE_COMPLETION: if self._editor.document().revision() != self._revision and \ cursor.block().blockNumber() != self._block: source = self._editor.get_text() source = source.encode(self._editor.encoding) self.cc.analyze_file(self._editor.ID, source) self._revision = self._editor.document().revision() self._block = cursor.block().blockNumber() def insert_completion(self, insert, type_=ord('a')): if insert != self._prefix: closing = '' if type_ in (ord('f'), ord('c')): closing = '()' extra = len(self._prefix) - len(insert) insertion = '%s%s' % (insert[extra:], closing) self._editor.textCursor().insertText(insertion) self.hide_completer() def _get_geometry(self): cr = self._editor.cursorRect() desktop_geometry = self.desktop.availableGeometry(self._editor) point = self._editor.mapToGlobal(cr.topLeft()) cr.moveTopLeft(point) #Check new position according desktop geometry width = (self.completion_list.sizeHintForColumn(0) + self.completion_list.verticalScrollBar().sizeHint().width() + 10) height = 200 orientation = (point.y() + height) < desktop_geometry.height() if orientation: cr.moveTop(cr.bottom()) cr.setWidth(width) cr.setHeight(height) if not orientation: cr.moveBottom(cr.top()) xpos = desktop_geometry.width() - (point.x() + width) if xpos < 0: cr.moveLeft(cr.left() + xpos) return cr def complete(self, results): self.add_list_items(results) self.completion_list.setCurrentRow(0) cr = self._get_geometry() self.setGeometry(cr) self.completion_list.updateGeometries() self.show() def add_list_items(self, proposals): self.completion_list.clear() for p in proposals: self.completion_list.addItem( QListWidgetItem( QIcon(self._icons.get(p[0], resources.IMAGES['attribute'])), p[1], type=ord(p[0]))) def set_completion_prefix(self, prefix, valid=True): self._prefix = prefix proposals = [] proposals += [('m', item) for item in self._completion_results.get('modules', []) if item.startswith(prefix)] proposals += [('c', item) for item in self._completion_results.get('classes', []) if item.startswith(prefix)] proposals += [('a', item) for item in self._completion_results.get('attributes', []) if item.startswith(prefix)] proposals += [('f', item) for item in self._completion_results.get('functions', []) if item.startswith(prefix)] if proposals and valid: self.complete(proposals) else: self.hide_completer() def _invalid_completion_position(self): result = False cursor = self._editor.textCursor() cursor.movePosition(QTextCursor.StartOfLine, QTextCursor.KeepAnchor) selection = unicode(cursor.selectedText())[:-1].split(' ') if len(selection) == 0 or selection[-1] == '' or \ selection[-1].isdigit(): result = True return result def fill_completer(self, force_completion=False): if not force_completion and (self._editor.cursor_inside_string() or self._editor.cursor_inside_comment() or self._invalid_completion_position()): return source = self._editor.get_text() source = source.encode(self._editor.encoding) offset = self._editor.textCursor().position() results = self.cc.get_completion(source, offset) self._completion_results = results if force_completion: cursor = self._editor.textCursor() cursor.movePosition(QTextCursor.StartOfWord, QTextCursor.KeepAnchor) prefix = cursor.selectedText() else: prefix = self._editor._text_under_cursor() self.set_completion_prefix(prefix) def hide_completer(self): self._prefix = '' self.hide() def pre_key_insert_completion(self): type_ = ord('a') current = self.completion_list.currentItem() insert = unicode(current.text()) if not insert.endswith(')'): type_ = current.type() self.insert_completion(insert, type_) self.hide_completer() return True def process_pre_key_event(self, event): if not self.isVisible() or self._editor.lang != "python": return False skip = self._key_operations.get(event.key(), lambda: False)() self._key_operations.get(event.modifiers(), lambda: False)() if skip is None: skip = False return skip def process_post_key_event(self, event): if not settings.CODE_COMPLETION or self._editor.lang != "python": return if self.isVisible(): source = self._editor.get_text() source = source.encode(self._editor.encoding) offset = self._editor.textCursor().position() prefix, valid = self.cc.get_prefix(source, offset) self.set_completion_prefix(prefix, valid) self.completion_list.setCurrentRow(0) force_completion = (event.key() == Qt.Key_Space and event.modifiers() == Qt.ControlModifier) if event.key() == Qt.Key_Period or force_completion: self.fill_completer(force_completion)
class _MainContainer(QWidget): ############################################################################### # MainContainer SIGNALS ############################################################################### """ beforeFileSaved(QString) fileSaved(QString) currentTabChanged(QString) locateFunction(QString, QString, bool) [functionName, filePath, isVariable] --------openProject(QString) openPreferences() ---------dontOpenStartPage() -------navigateCode(bool, int) ----------addBackItemNavigation() ----------updateLocator(QString) ---------updateFileMetadata() findOcurrences(QString) --------cursorPositionChange(int, int) #row, col fileOpened(QString) newFileOpened(QString) --------recentTabsModified(QStringList) ---------migrationAnalyzed() allTabClosed() """ ############################################################################### def __init__(self, parent=None): super(_MainContainer, self).__init__(parent) self._parent = parent self.stack = QStackedLayout(self) self.splitter = dynamic_splitter.DynamicSplitter() self.combo_area = combo_editor.ComboEditor(original=True) #self.tabs = tab_widget.TabWidget(self) self.setAcceptDrops(True) self.splitter.addWidget(self.combo_area) self.stack.addWidget(self.splitter) self.current_split = self.combo_area #documentation browser self.docPage = None #Code Navigation self._locator = locator.Locator() self.__codeBack = [] self.__codeForward = [] self.__bookmarksFile = '' self.__bookmarksPos = -1 self.__breakpointsFile = '' self.__breakpointsPos = -1 self.__operations = { 0: self._navigate_code_jumps, 1: self._navigate_bookmarks, 2: self._navigate_breakpoints} self.connect(self, SIGNAL("locateFunction(QString, QString, bool)"), self.locate_function) #self.connect(self.tabs, SIGNAL("currentChanged(int)"), #self._current_tab_changed) #self.connect(self.tabs, SIGNAL("splitTab(QTabWidget, int, bool)"), #self._split_this_tab) #self.connect(self.tabs, SIGNAL("reopenTab(QString)"), #self.open_file) #self.connect(self.tabs, SIGNAL("syntaxChanged(QWidget, QString)"), #self._specify_syntax) #self.connect(self.tabs, SIGNAL("allTabsClosed()"), #self._main_without_tabs) ##reload file #self.connect(self.tabs, SIGNAL("reloadFile(QWidget)"), #self.reload_file) ##for Save on Close operation #self.connect(self.tabs, SIGNAL("saveActualEditor()"), #self.save_file) ##Navigate Code #self.connect(self.tabs, SIGNAL("navigateCode(bool, int)"), #self.navigate_code_history) ## Refresh recent tabs #self.connect(self.tabs, SIGNAL("recentTabsModified(QStringList)"), #self._recent_files_changed) IDE.register_service('main_container', self) #Register signals connections connections = ( {'target': 'menu_file', 'signal_name': 'openFile(QString)', 'slot': self.open_file}, {'target': 'explorer_container', 'signal_name': 'goToDefinition(int)', 'slot': self.editor_go_to_line}, {'target': 'explorer_container', 'signal_name': 'pep8Activated(bool)', 'slot': self.reset_pep8_warnings}, {'target': 'explorer_container', 'signal_name': 'lintActivated(bool)', 'slot': self.reset_lint_warnings}, ) IDE.register_signals('main_container', connections) if settings.SHOW_START_PAGE: self.show_start_page() def install(self): ide = IDE.get_service('ide') ide.place_me_on("main_container", self, "central", top=True) ui_tools.install_shortcuts(self, actions.ACTIONS, ide) def change_visibility(self): """Show/Hide the Main Container area.""" if self.isVisible(): self.hide() else: self.show() def locate_function(self, function, filePath, isVariable): """Move the cursor to the proper position in the navigate stack.""" editorWidget = self.get_current_editor() if editorWidget: self.__codeBack.append((editorWidget.ID, editorWidget.textCursor().position())) self.__codeForward = [] self._locator.navigate_to(function, filePath, isVariable) def paste_history(self): """Paste the text from the copy/paste history.""" editorWidget = self.get_current_editor() if editorWidget and editorWidget.hasFocus(): cursor = editorWidget.textCursor() central = IDE.get_service('central_container') if central: cursor.insertText(central.get_paste()) def copy_history(self): """Copy the selected text into the copy/paste history.""" editorWidget = self.get_current_editor() if editorWidget and editorWidget.hasFocus(): cursor = editorWidget.textCursor() copy = cursor.selectedText() central = IDE.get_service('central_container') if central: central.add_copy(copy) def import_from_everywhere(self): """Add an item to the back stack and reset the forward stack.""" editorWidget = self.get_current_editor() if editorWidget: dialog = from_import_dialog.FromImportDialog(editorWidget, self) dialog.show() def add_back_item_navigation(self): """Add an item to the back stack and reset the forward stack.""" editorWidget = self.get_current_editor() if editorWidget: self.__codeBack.append((editorWidget.ID, editorWidget.textCursor().position())) self.__codeForward = [] def preview_in_browser(self): """Load the current html file in the default browser.""" editorWidget = self.get_current_editor() if editorWidget: if not editorWidget.ID: self.save_file() ext = file_manager.get_file_extension(editorWidget.ID) if ext == 'html': webbrowser.open(editorWidget.ID) def add_bookmark_breakpoint(self): """Add a bookmark or breakpoint to the current file in the editor.""" pass #TODO #editorWidget = self.get_current_editor() #if editorWidget and editorWidget.hasFocus(): #if self.tabs.navigator.operation == 1: #editorWidget._sidebarWidget.set_bookmark( #editorWidget.textCursor().blockNumber()) #elif self.tabs.navigator.operation == 2: #editorWidget._sidebarWidget.set_breakpoint( #editorWidget.textCursor().blockNumber()) def __navigate_with_keyboard(self, val): """Navigate between the positions in the jump history stack.""" op = self.actualTab._tabs.operation self.navigate_code_history(val, op) def navigate_code_history(self, val, op): """Navigate the code history.""" self.__operations[op](val) def _navigate_code_jumps(self, val): """Navigate between the jump points.""" node = None if not val and self.__codeBack: node = self.__codeBack.pop() editorWidget = self.get_current_editor() if editorWidget: self.__codeForward.append((editorWidget.ID, editorWidget.textCursor().position())) elif val and self.__codeForward: node = self.__codeForward.pop() editorWidget = self.get_current_editor() if editorWidget: self.__codeBack.append((editorWidget.ID, editorWidget.textCursor().position())) if node: self.open_file(node[0], node[1]) def _navigate_breakpoints(self, val): """Navigate between the breakpoints.""" #FIXME: put navigate breakpoints and bookmarks as one method. breakList = list(settings.BREAKPOINTS.keys()) breakList.sort() if not breakList: return if self.__breakpointsFile not in breakList: self.__breakpointsFile = breakList[0] index = breakList.index(self.__breakpointsFile) breaks = settings.BREAKPOINTS.get(self.__breakpointsFile, []) lineNumber = 0 #val == True: forward if val: if (len(breaks) - 1) > self.__breakpointsPos: self.__breakpointsPos += 1 lineNumber = breaks[self.__breakpointsPos] elif len(breaks) > 0: if index < (len(breakList) - 1): self.__breakpointsFile = breakList[index + 1] else: self.__breakpointsFile = breakList[0] self.__breakpointsPos = 0 lineNumber = settings.BREAKPOINTS[self.__breakpointsFile][0] else: if self.__breakpointsPos > 0: self.__breakpointsPos -= 1 lineNumber = breaks[self.__breakpointsPos] elif len(breaks) > 0: self.__breakpointsFile = breakList[index - 1] breaks = settings.BREAKPOINTS[self.__breakpointsFile] self.__breakpointsPos = len(breaks) - 1 lineNumber = breaks[self.__breakpointsPos] if file_manager.file_exists(self.__breakpointsFile): self.open_file(self.__breakpointsFile, lineNumber, None, True) else: settings.BREAKPOINTS.pop(self.__breakpointsFile) if settings.BREAKPOINTS: self._navigate_breakpoints(val) def _navigate_bookmarks(self, val): """Navigate between the bookmarks.""" bookList = list(settings.BOOKMARKS.keys()) bookList.sort() if not bookList: return if self.__bookmarksFile not in bookList: self.__bookmarksFile = bookList[0] index = bookList.index(self.__bookmarksFile) bookms = settings.BOOKMARKS.get(self.__bookmarksFile, []) lineNumber = 0 #val == True: forward if val: if (len(bookms) - 1) > self.__bookmarksPos: self.__bookmarksPos += 1 lineNumber = bookms[self.__bookmarksPos] elif len(bookms) > 0: if index < (len(bookList) - 1): self.__bookmarksFile = bookList[index + 1] else: self.__bookmarksFile = bookList[0] self.__bookmarksPos = 0 lineNumber = settings.BOOKMARKS[self.__bookmarksFile][0] else: if self.__bookmarksPos > 0: self.__bookmarksPos -= 1 lineNumber = bookms[self.__bookmarksPos] elif len(bookms) > 0: self.__bookmarksFile = bookList[index - 1] bookms = settings.BOOKMARKS[self.__bookmarksFile] self.__bookmarksPos = len(bookms) - 1 lineNumber = bookms[self.__bookmarksPos] if file_manager.file_exists(self.__bookmarksFile): self.open_file(self.__bookmarksFile, lineNumber, None, True) else: settings.BOOKMARKS.pop(self.__bookmarksFile) if settings.BOOKMARKS: self._navigate_bookmarks(val) def count_file_code_lines(self): """Count the lines of code in the current file.""" editorWidget = self.get_current_editor() if editorWidget: block_count = editorWidget.blockCount() blanks = re.findall('(^\n)|(^(\s+)?#)|(^( +)?($|\n))', editorWidget.get_text(), re.M) blanks_count = len(blanks) resume = self.tr("Lines code: %s\n") % (block_count - blanks_count) resume += (self.tr("Blanks and commented lines: %s\n\n") % blanks_count) resume += self.tr("Total lines: %s") % block_count msgBox = QMessageBox(QMessageBox.Information, self.tr("Summary of lines"), resume, QMessageBox.Ok, editorWidget) msgBox.exec_() def editor_cut(self): editorWidget = self.get_current_editor() if editorWidget: editorWidget.cut() def editor_copy(self): editorWidget = self.get_current_editor() if editorWidget: editorWidget.copy() def editor_paste(self): editorWidget = self.get_current_editor() if editorWidget: editorWidget.paste() def editor_upper(self): editorWidget = self.get_current_editor() if editorWidget: editorWidget.to_upper() def editor_lower(self): editorWidget = self.get_current_editor() if editorWidget: editorWidget.to_lower() def editor_title(self): editorWidget = self.get_current_editor() if editorWidget: editorWidget.to_title() def editor_go_to_definition(self): """Search the definition of the method or variable under the cursor. If more than one method or variable is found with the same name, shows a table with the results and let the user decide where to go.""" editorWidget = self.get_current_editor() if editorWidget and editorWidget.hasFocus(): editorWidget.go_to_definition() def editor_redo(self): """Execute the redo action in the current editor.""" editorWidget = self.get_current_editor() if editorWidget and editorWidget.hasFocus(): editorWidget.redo() def editor_undo(self): editorWidget = self.get_current_editor() if editorWidget and editorWidget.hasFocus(): editorWidget.undo() def editor_indent_less(self): """Indent 1 position to the left for the current line or selection.""" editorWidget = self.get_current_editor() if editorWidget and editorWidget.hasFocus(): editorWidget.indent_less() def editor_indent_more(self): """Indent 1 position to the right for the current line or selection.""" editorWidget = self.get_current_editor() if editorWidget and editorWidget.hasFocus(): editorWidget.indent_more() def editor_insert_debugging_prints(self): """Insert a print statement in each selected line.""" editorWidget = self.get_current_editor() if editorWidget: helpers.insert_debugging_prints(editorWidget) def editor_insert_pdb(self): """Insert a pdb.set_trace() statement in tjhe current line.""" editorWidget = self.get_current_editor() if editorWidget: helpers.insert_pdb(editorWidget) def editor_comment(self): """Mark the current line or selection as a comment.""" editorWidget = self.get_current_editor() if editorWidget and editorWidget.hasFocus(): helpers.comment(editorWidget) def editor_uncomment(self): """Uncomment the current line or selection.""" editorWidget = self.get_current_editor() if editorWidget and editorWidget.hasFocus(): helpers.uncomment(editorWidget) def editor_insert_horizontal_line(self): """Insert an horizontal lines of comment symbols.""" editorWidget = self.get_current_editor() if editorWidget and editorWidget.hasFocus(): helpers.insert_horizontal_line(editorWidget) def editor_insert_title_comment(self): """Insert a Title surrounded by comment symbols.""" editorWidget = self.get_current_editor() if editorWidget and editorWidget.hasFocus(): helpers.insert_title_comment(editorWidget) def editor_remove_trailing_spaces(self): """Remove the trailing spaces in the current editor.""" editorWidget = self.get_current_editor() if editorWidget: helpers.remove_trailing_spaces(editorWidget) def editor_replace_tabs_with_spaces(self): """Replace the Tabs with Spaces in the current editor.""" editorWidget = self.get_current_editor() if editorWidget: helpers.replace_tabs_with_spaces(editorWidget) def editor_move_up(self): """Move the current line or selection one position up.""" editorWidget = self.get_current_editor() if editorWidget and editorWidget.hasFocus(): helpers.move_up(editorWidget) def editor_move_down(self): """Move the current line or selection one position down.""" editorWidget = self.get_current_editor() if editorWidget and editorWidget.hasFocus(): helpers.move_down(editorWidget) def editor_remove_line(self): """Remove the current line or selection.""" editorWidget = self.get_current_editor() if editorWidget and editorWidget.hasFocus(): helpers.remove_line(editorWidget) def editor_duplicate(self): """Duplicate the current line or selection.""" editorWidget = self.get_current_editor() if editorWidget and editorWidget.hasFocus(): helpers.duplicate(editorWidget) def editor_highlight_word(self): """Highlight the occurrences of the current word in the editor.""" editorWidget = self.get_current_editor() if editorWidget and editorWidget.hasFocus(): editorWidget.highlight_selected_word() def editor_complete_declaration(self): """Do the opposite action that Complete Declaration expect.""" editorWidget = self.get_current_editor() if editorWidget and editorWidget.hasFocus(): editorWidget.complete_declaration() def editor_go_to_line(self, line): """Jump to the specified line in the current editor.""" editorWidget = self.get_current_editor() if editorWidget: editorWidget.jump_to_line(line) def zoom_in_editor(self): """Increase the font size in the current editor.""" editorWidget = self.get_current_editor() if editorWidget: editorWidget.zoom_in() def zoom_out_editor(self): """Decrease the font size in the current editor.""" editorWidget = self.get_current_editor() if editorWidget: editorWidget.zoom_out() def _recent_files_changed(self, files): self.emit(SIGNAL("recentTabsModified(QStringList)"), files) def dragEnterEvent(self, event): if event.mimeData().hasUrls(): event.accept() else: event.ignore() def dropEvent(self, event): file_path = event.mimeData().urls()[0].toLocalFile() self.open_file(file_path) def setFocus(self): widget = self.get_actual_widget() if widget: widget.setFocus() def group_tabs_together(self): """Group files that belongs to the same project together.""" pass #TODO #ninjaide = IDE.get_service('ide') #projects = ninjaide.get_opened_projects() #for project in projects: #project_name = projects[project].name #project_path = projects[project].path #tabGroup = tab_group.TabGroup(project_path, project_name, self) #self.connect(tabGroup, SIGNAL("expandAll()"), #self.deactivate_tabs_groups) #for index in reversed(list(range(self.tabs.count()))): #widget = self.tabs.widget(index) #if (isinstance(widget, editor.Editor) and #widget.project == projects[project]): #tabGroup.add_widget(widget) #self.tabs.removeTab(index) #if tabGroup.tabs: #self.tabs.add_tab(tabGroup, project_name) def deactivate_tabs_groups(self): """Deactivate tab grouping based in the project they belong.""" #TODO #for index in reversed(list(range(self.tabs.count()))): #widget = self.tabs.widget(index) #if isinstance(widget, tab_group.TabGroup): #widget.expand() def _main_without_tabs(self): """Notify that there are no more tabs opened.""" self.emit(SIGNAL("allTabsClosed()")) def _current_tab_changed(self, index): """Notify the new ID of the current tab.""" widget = self.combo_area.widget(index) if widget: self.emit(SIGNAL("currentTabChanged(QString)"), widget.ID) def split_tab(self, orientation): pass #FIXME: check how we handle this #"""Split the main container.""" #if orientationHorizontal: #self.show_split(Qt.Vertical) #else: #self.show_split(Qt.Horizontal) def _split_this_tab(self, tab, index, orientationHorizontal): pass #FIXME: check how we handle this #tab.setCurrentIndex(index) #if orientationHorizontal: #self.show_split(Qt.Horizontal) #else: #self.show_split(Qt.Vertical) def change_tabs_visibility(self): if self._tabMain.tabBar().isVisible(): self._tabMain.tabBar().hide() else: self._tabMain.tabBar().show() def show_split(self, orientation): pass #FIXME: check how we handle this #closingFollowMode = self._followMode #if self._followMode: #self._exit_follow_mode() #if self.tabsecondary.isVisible() and \ #orientation == self.orientation(): #self.tabsecondary.hide() #self.split_visible = False #for i in range(self.tabsecondary.count()): #widget = self.tabsecondary.widget(0) #name = self.tabsecondary.tabText(0) #self._tabMain.add_tab(widget, name) #if name in self.tabsecondary.titles: #self.tabsecondary.titles.remove(name) #if type(widget) is editor.Editor and widget.textModified: #self._tabMain.tab_was_modified(True) #self.actualTab = self._tabMain #elif not self.tabsecondary.isVisible() and not closingFollowMode: #widget = self.get_actual_widget() #name = self._tabMain.tabText(self._tabMain.currentIndex()) #self.tabsecondary.add_tab(widget, name) #if name in self._tabMain.titles: #self._tabMain.titles.remove(name) #if type(widget) is editor.Editor and widget.textModified: #self.tabsecondary.tab_was_modified(True) #self.tabsecondary.show() #self.split_visible = True #self.splitter.setSizes([1, 1]) #self.actualTab = self.tabsecondary #self.emit(SIGNAL("currentTabChanged(QString)"), widget.ID) #self.splitter.setOrientation(orientation) def add_editor(self, fileName=None, tabIndex=None): ninjaide = IDE.get_service('ide') editable = ninjaide.get_or_create_editable(fileName) editorWidget = editor.create_editor(editable) #add the tab self.combo_area.add_editor(editable) #index = self.add_tab(editorWidget, tab_name, tabIndex=tabIndex) #self.tabs.setTabToolTip(index, QDir.toNativeSeparators(fileName)) #Connect signals self.connect(editorWidget, SIGNAL("modificationChanged(bool)"), self._editor_tab_was_modified) self.connect(editorWidget, SIGNAL("fileSaved(QPlainTextEdit)"), self._editor_tab_was_saved) self.connect(editorWidget, SIGNAL("openDropFile(QString)"), self.open_file) self.connect(editorWidget, SIGNAL("addBackItemNavigation()"), self.add_back_item_navigation) self.connect(editorWidget, SIGNAL("locateFunction(QString, QString, bool)"), self._editor_locate_function) self.connect(editorWidget, SIGNAL("checksFound(QPlainTextEdit, PyQt_PyObject)"), self._show_tab_indicator) self.connect(editorWidget, SIGNAL("cleanDocument(QPlainTextEdit)"), self._hide_icon_tab_indicator) self.connect(editorWidget, SIGNAL("findOcurrences(QString)"), self._find_occurrences) self.connect(editorWidget, SIGNAL("migrationAnalyzed()"), lambda: self.emit(SIGNAL("migrationAnalyzed()"))) #Cursor position changed self.connect(editorWidget, SIGNAL("cursorPositionChange(int, int)"), self._cursor_position_changed) #keyPressEventSignal for plugins self.connect(editorWidget, SIGNAL("keyPressEvent(QEvent)"), self._editor_keyPressEvent) #emit a signal about the file open self.emit(SIGNAL("fileOpened(QString)"), fileName) return editorWidget def update_editor_project(self): pass #FIXME: check how we handle this #for i in range(self._tabMain.count()): #widget = self._tabMain.widget(i) #if type(widget) is editor.Editor: #project = self._parent.explorer.get_project_given_filename( #widget.ID) #widget.set_project(project) def reset_pep8_warnings(self, value): pass #FIXME: check how we handle this #for i in range(self._tabMain.count()): #widget = self._tabMain.widget(i) #if type(widget) is editor.Editor: #if value: #widget.syncDocErrorsSignal = True #widget.pep8.check_style() #else: #widget.hide_pep8_errors() #for i in range(self.tabsecondary.count()): #widget = self.tabsecondary.widget(i) #if type(widget) is editor.Editor: #if value: #widget.syncDocErrorsSignal = True #widget.pep8.check_style() #else: #widget.hide_pep8_errors() def reset_lint_warnings(self, value): pass #FIXME: check how we handle this #for i in range(self._tabMain.count()): #widget = self._tabMain.widget(i) #if type(widget) is editor.Editor: #if value: #widget.syncDocErrorsSignal = True #widget.errors.check_errors() #else: #widget.hide_lint_errors() #for i in range(self.tabsecondary.count()): #widget = self.tabsecondary.widget(i) #if type(widget) is editor.Editor: #if value: #widget.syncDocErrorsSignal = True #widget.errors.check_errors() #else: #widget.hide_lint_errors() def _cursor_position_changed(self, row, col): self.emit(SIGNAL("cursorPositionChange(int, int)"), row, col) def _find_occurrences(self, word): self.emit(SIGNAL("findOcurrences(QString)"), word) def _show_tab_indicator(self, editorWidget, icon): pass #index = self.tabs.indexOf(editorWidget) #self.emit(SIGNAL("updateFileMetadata()")) #if index >= 0 and icon: #if isinstance(icon, int): #icon = QIcon(self.style().standardIcon(icon)) #self.tabs.setTabIcon(index, icon) def _hide_icon_tab_indicator(self, editorWidget): pass #index = self.tabs.indexOf(editorWidget) #self.emit(SIGNAL("updateFileMetadata()")) #if index >= 0: #self.tabs.setTabIcon(index, QIcon()) def _editor_keyPressEvent(self, event): self.emit(SIGNAL("editorKeyPressEvent(QEvent)"), event) def _editor_locate_function(self, function, filePath, isVariable): self.emit(SIGNAL("locateFunction(QString, QString, bool)"), function, filePath, isVariable) def _editor_tab_was_modified(self, val=True): pass #self.tabs.tab_was_modified(val) def _editor_tab_was_saved(self, editorWidget=None): pass #self.tabs.tab_was_saved(editorWidget) #self.emit(SIGNAL("updateLocator(QString)"), editorWidget.ID) def get_current_widget(self): return self.current_split.currentWidget() def get_current_editor(self): """Return the Actual Editor or None Return an instance of Editor if the Current Tab contains an Editor or None if it is not an instance of Editor""" widget = self.current_split.currentWidget() if isinstance(widget, editor.Editor): return widget return None def reload_file(self, editorWidget=None): if editorWidget is None: editorWidget = self.get_current_editor() #if editorWidget is not None and editorWidget.ID: #fileName = editorWidget.ID #old_cursor_position = editorWidget.textCursor().position() #old_widget_index = self.tabs.indexOf(editorWidget) #self.tabs.removeTab(old_widget_index) ##open the file in the same tab as before #self.open_file(fileName, tabIndex=old_widget_index) ##get the new editor and set the old cursor position #editorWidget = self.get_current_editor() #cursor = editorWidget.textCursor() #cursor.setPosition(old_cursor_position) #editorWidget.setTextCursor(cursor) def add_tab(self, widget, tabName, tabIndex=None): pass #return self.tabs.add_tab(widget, tabName, index=tabIndex) def open_image(self, fileName): try: if not self.is_open(fileName): viewer = image_viewer.ImageViewer(fileName) self.add_tab(viewer, file_manager.get_basename(fileName)) viewer.ID = fileName else: self.move_to_open(fileName) except Exception as reason: logger.error('open_image: %s', reason) QMessageBox.information(self, self.tr("Incorrect File"), self.tr("The image couldn\'t be open")) def open_file(self, filename='', cursorPosition=-1, tabIndex=None, positionIsLineNumber=False, notStart=True): if not filename: if settings.WORKSPACE: directory = settings.WORKSPACE else: directory = os.path.expanduser("~") editorWidget = self.get_current_editor() ninjaide = IDE.get_service('ide') if ninjaide: current_project = ninjaide.get_current_project() if current_project is not None: directory = current_project elif editorWidget is not None and editorWidget.ID: directory = file_manager.get_folder(editorWidget.ID) extensions = ';;'.join( ['(*%s)' % e for e in settings.SUPPORTED_EXTENSIONS + ['.*', '']]) fileNames = list(QFileDialog.getOpenFileNames(self, self.tr("Open File"), directory, extensions)) else: fileNames = [filename] if not fileNames: return for filename in fileNames: if file_manager.get_file_extension(filename) in ('jpg', 'png'): self.open_image(filename) elif file_manager.get_file_extension(filename).endswith('ui'): self.w = uic.loadUi(filename) self.w.show() else: self.__open_file(filename, cursorPosition, tabIndex, positionIsLineNumber) def __open_file(self, fileName='', cursorPosition=-1, tabIndex=None, positionIsLineNumber=False): try: if not self.is_open(fileName): editorWidget = self.add_editor(fileName, tabIndex=tabIndex) if cursorPosition == -1: cursorPosition = 0 if positionIsLineNumber: editorWidget.go_to_line(cursorPosition) else: editorWidget.set_cursor_position(cursorPosition) else: self.move_to_open(fileName) editorWidget = self.get_current_editor() if editorWidget and cursorPosition != -1: if positionIsLineNumber: editorWidget.go_to_line(cursorPosition) else: editorWidget.set_cursor_position(cursorPosition) self.emit(SIGNAL("currentTabChanged(QString)"), fileName) except file_manager.NinjaIOException as reason: QMessageBox.information(self, self.tr("The file couldn't be open"), str(reason)) except Exception as reason: logger.error('open_file: %s', reason) def is_open(self, filename): pass #return self.tabs.is_open(filename) != -1 def move_to_open(self, filename): pass #FIXME: add in the current split? #if self.tabs.is_open(filename) != -1: #self.tabs.move_to_open(filename) #self.tabs.currentWidget().setFocus() #self.emit(SIGNAL("currentTabChanged(QString)"), filename) def move_tab_right(self): self._move_tab() def move_tab_left(self): self._move_tab(forward=False) def _move_tab(self, forward=True, widget=None): pass #if widget is None: #widget = self.tabs.currentWidget() #if widget is not None: #old_widget_index = self.tabs.indexOf(widget) #if forward and old_widget_index < self.tabs.count() - 1: #new_widget_index = old_widget_index + 1 #elif old_widget_index > 0 and not forward: #new_widget_index = old_widget_index - 1 #else: #return #tabName = self.tabs.tabText(old_widget_index) #self.tabs.insertTab(new_widget_index, widget, tabName) #self.tabs.setCurrentIndex(new_widget_index) def get_widget_for_id(self, filename): pass #widget = None #index = self.tabs.is_open(filename) #if index != -1: #widget = self.tabs.widget(index) #return widget def change_open_tab_id(self, idname, newId): """Search for the Tab with idname, and set the newId to that Tab.""" pass #index = self.tabs.is_open(idname) #if index != -1: #widget = self.tabs.widget(index) #tabName = file_manager.get_basename(newId) #self.tabs.change_open_tab_name(index, tabName) #widget.ID = newId def close_deleted_file(self, idname): """Search for the Tab with id, and ask the user if should be closed.""" pass #index = self.tabs.is_open(idname) #if index != -1: #result = QMessageBox.question(self, self.tr("Close Deleted File"), #self.tr("Are you sure you want to close the deleted file?\n" #"The content will be completely deleted."), #buttons=QMessageBox.Yes | QMessageBox.No) #if result == QMessageBox.Yes: #self.tabs.removeTab(index) def save_file(self, editorWidget=None): #FIXME: check how we handle this if not editorWidget: editorWidget = self.get_current_editor() if not editorWidget: return False try: #editorWidget.just_saved = True nfile = editorWidget.nfile if nfile.is_new_file or not nfile.has_write_permission(): return self.save_file_as() self.emit(SIGNAL("beforeFileSaved(QString)"), nfile.file_path) if settings.REMOVE_TRAILING_SPACES: helpers.remove_trailing_spaces(editorWidget) content = editorWidget.get_text() nfile.save(content) #file_manager.store_file_content( #fileName, content, addExtension=False) encoding = file_manager.get_file_encoding(content) editorWidget.encoding = encoding self.emit(SIGNAL("fileSaved(QString)"), (self.tr("File Saved: %s") % nfile.file_path)) editorWidget._file_saved() return True except Exception as reason: #editorWidget.just_saved = False logger.error('save_file: %s', reason) QMessageBox.information(self, self.tr("Save Error"), self.tr("The file couldn't be saved!")) return False def save_file_as(self): editorWidget = self.get_current_editor() if not editorWidget: return False nfile = editorWidget.nfile try: #editorWidget.just_saved = True filters = '(*.py);;(*.*)' if nfile.file_path: ext = file_manager.get_file_extension(nfile.file_path) if ext != 'py': filters = '(*.%s);;(*.py);;(*.*)' % ext save_folder = self._get_save_folder(nfile.file_path) fileName = QFileDialog.getSaveFileName( self._parent, self.tr("Save File"), save_folder, filters) if not fileName: return False if settings.REMOVE_TRAILING_SPACES: helpers.remove_trailing_spaces(editorWidget) #newFile = file_manager.get_file_extension(fileName) == '' nfile.save(editorWidget.get_text(), path=fileName) print editorWidget.nfile._file_path #fileName = file_manager.store_file_content( #fileName, editorWidget.get_text(), #addExtension=True, newFile=newFile) #self.actualTab.setTabText(self.actualTab.currentIndex(), #file_manager.get_basename(fileName)) editorWidget.register_syntax( file_manager.get_file_extension(fileName)) #self._file_watcher.allow_kill = False #if editorWidget.ID != fileName: #self.remove_standalone_watcher(editorWidget.ID) #editorWidget.ID = fileName self.emit(SIGNAL("fileSaved(QString)"), (self.tr("File Saved: %s") % fileName)) self.emit(SIGNAL("currentTabChanged(QString)"), fileName) editorWidget._file_saved() #self.add_standalone_watcher(fileName) #self._file_watcher.allow_kill = True return True except file_manager.NinjaFileExistsException as ex: #editorWidget.just_saved = False QMessageBox.information(self, self.tr("File Already Exists"), (self.tr("Invalid Path: the file '%s' already exists.") % ex.filename)) except Exception as reason: #editorWidget.just_saved = False logger.error('save_file_as: %s', reason) QMessageBox.information(self, self.tr("Save Error"), self.tr("The file couldn't be saved!")) self.actualTab.setTabText(self.actualTab.currentIndex(), self.tr("New Document")) return False def _get_save_folder(self, fileName): """ Returns the root directory of the 'Main Project' or the home folder """ ninjaide = IDE.get_service('ide') current_project = ninjaide.get_current_project() if current_project: return current_project.path return os.path.expanduser("~") def save_project(self, projectFolder): pass #FIXME: check how we handle this #for i in range(self._tabMain.count()): #editorWidget = self._tabMain.widget(i) #if type(editorWidget) is editor.Editor and \ #file_manager.belongs_to_folder(projectFolder, editorWidget.ID): #reloaded = self._tabMain.check_for_external_modifications( #editorWidget) #if not reloaded: #self.save_file(editorWidget) #for i in range(self.tabsecondary.count()): #editorWidget = self.tabsecondary.widget(i) #if type(editorWidget) is editor.Editor and \ #file_manager.belongs_to_folder(projectFolder, editorWidget.ID): #reloaded = self.tabsecondary.check_for_external_modifications( #editorWidget) #if not reloaded: #self.save_file(editorWidget) def save_all(self): pass #FIXME: check how we handle this #for i in range(self._tabMain.count()): #editorWidget = self._tabMain.widget(i) #if type(editorWidget) is editor.Editor: #reloaded = self._tabMain.check_for_external_modifications( #editorWidget) #if not reloaded: #self.save_file(editorWidget) #for i in range(self.tabsecondary.count()): #editorWidget = self.tabsecondary.widget(i) #self.tabsecondary.check_for_external_modifications(editorWidget) #if type(editorWidget) is editor.Editor: #reloaded = self.tabsecondary.check_for_external_modifications( #editorWidget) #if not reloaded: #self.save_file(editorWidget) def call_editors_function(self, call_function, *arguments): pass #args = arguments[0] #kwargs = arguments[1] #for i in range(self.tabs.count()): #editorWidget = self.tabs.widget(i) #if isinstance(editorWidget, editor.Editor): #function = getattr(editorWidget, call_function) #function(*args, **kwargs) #TODO: add other splits def show_start_page(self): pass #if not self.is_open("Start Page"): #startPage = start_page.StartPage(parent=self) #self.connect(startPage, SIGNAL("openProject(QString)"), #self.open_project) #self.connect(startPage, SIGNAL("openPreferences()"), #lambda: self.emit(SIGNAL("openPreferences()"))) #self.add_tab(startPage, 'Start Page') #else: #self.move_to_open("Start Page") def show_python_doc(self): if sys.platform == 'win32': self.docPage = browser_widget.BrowserWidget( 'http://docs.python.org/') else: process = runner.start_pydoc() self.docPage = browser_widget.BrowserWidget(process[1], process[0]) self.add_tab(self.docPage, translations.TR_PYTHON_DOC) def show_report_bugs(self): webbrowser.open(resources.BUGS_PAGE) def show_plugins_doc(self): bugsPage = browser_widget.BrowserWidget(resources.PLUGINS_DOC, self) self.add_tab(bugsPage, translations.TR_HOW_TO_WRITE_PLUGINS) def editor_jump_to_line(self, lineno=None): """Jump to line *lineno* if it is not None otherwise ask to the user the line number to jump """ editorWidget = self.get_current_editor() if editorWidget: editorWidget.jump_to_line(lineno=lineno) def get_opened_documents(self): pass #return self.tabs.get_documents_data() def open_files(self, files): for fileData in files: if file_manager.file_exists(fileData[0]): self.open_file(fileData[0], fileData[1]) def check_for_unsaved_tabs(self): pass #return self.tabs._check_unsaved_tabs() def get_unsaved_files(self): pass #return self.tabs.get_unsaved_files() def reset_editor_flags(self): pass #for i in range(self.tabs.count()): #widget = self.tabs.widget(i) #if isinstance(widget, editor.Editor): #widget.set_flags() def _specify_syntax(self, widget, syntaxLang): if isinstance(widget, editor.Editor): widget.restyle(syntaxLang) def apply_editor_theme(self, family, size): pass #for i in range(self.tabs.count()): #widget = self.tabs.widget(i) #if isinstance(widget, editor.Editor): #widget.restyle() #widget.set_font(family, size) def update_editor_margin_line(self): pass #for i in range(self.tabs.count()): #widget = self.tabs.widget(i) #if isinstance(widget, editor.Editor): #widget._update_margin_line() def open_project(self, path): self.emit(SIGNAL("openProject(QString)"), path) def close_python_doc(self): pass #close the python document server (if running) #if self.docPage: #index = self.tabs.indexOf(self.docPage) #self.tabs.removeTab(index) ##assign None to the browser #self.docPage = None def close_tab(self): """Close the current tab in the current TabWidget.""" pass #self.tabs.close_tab() def change_tab(self): """Change the tab in the current TabWidget.""" pass #self.tabs.change_tab() def change_tab_reverse(self): """Change the tab in the current TabWidget backwards.""" pass #self.tabs.change_tab_reverse() def show_navigation_buttons(self): pass #self.tabs.navigator.show_menu_navigation() def change_split_focus(self): pass #FIXME: check how we handle this #if self.actualTab == self._tabMain and self.tabsecondary.isVisible(): #self.actualTab = self.tabsecondary #else: #self.actualTab = self._tabMain #widget = self.actualTab.currentWidget() #if widget is not None: #widget.setFocus() def shortcut_index(self, index): pass #self.tabs.setCurrentIndex(index) def print_file(self): """Call the print of ui_tool Call print of ui_tool depending on the focus of the application""" #TODO: Add funtionality for proyect tab and methods tab editorWidget = self.get_current_editor() if editorWidget is not None: fileName = "newDocument.pdf" if editorWidget.ID: fileName = file_manager.get_basename( editorWidget.ID) fileName = fileName[:fileName.rfind('.')] + '.pdf' ui_tools.print_file(fileName, editorWidget.print_) def split_tabh(self): self.split_tab(True) def split_tabv(self): self.split_tab(False) def split_assistance(self): dialog = split_orientation.SplitOrientation(self) dialog.show() def close_split(self): pass def navigate_back(self): self.__navigate_with_keyboard(False) def navigate_forward(self): self.__navigate_with_keyboard(True)
def __init__(self, parent=None): super(_MainContainer, self).__init__(parent) self._parent = parent self.stack = QStackedLayout(self) self.splitter = dynamic_splitter.DynamicSplitter() self.combo_area = combo_editor.ComboEditor(original=True) #self.tabs = tab_widget.TabWidget(self) self.setAcceptDrops(True) self.splitter.addWidget(self.combo_area) self.stack.addWidget(self.splitter) self.current_split = self.combo_area #documentation browser self.docPage = None #Code Navigation self._locator = locator.Locator() self.__codeBack = [] self.__codeForward = [] self.__bookmarksFile = '' self.__bookmarksPos = -1 self.__breakpointsFile = '' self.__breakpointsPos = -1 self.__operations = { 0: self._navigate_code_jumps, 1: self._navigate_bookmarks, 2: self._navigate_breakpoints} self.connect(self, SIGNAL("locateFunction(QString, QString, bool)"), self.locate_function) #self.connect(self.tabs, SIGNAL("currentChanged(int)"), #self._current_tab_changed) #self.connect(self.tabs, SIGNAL("splitTab(QTabWidget, int, bool)"), #self._split_this_tab) #self.connect(self.tabs, SIGNAL("reopenTab(QString)"), #self.open_file) #self.connect(self.tabs, SIGNAL("syntaxChanged(QWidget, QString)"), #self._specify_syntax) #self.connect(self.tabs, SIGNAL("allTabsClosed()"), #self._main_without_tabs) ##reload file #self.connect(self.tabs, SIGNAL("reloadFile(QWidget)"), #self.reload_file) ##for Save on Close operation #self.connect(self.tabs, SIGNAL("saveActualEditor()"), #self.save_file) ##Navigate Code #self.connect(self.tabs, SIGNAL("navigateCode(bool, int)"), #self.navigate_code_history) ## Refresh recent tabs #self.connect(self.tabs, SIGNAL("recentTabsModified(QStringList)"), #self._recent_files_changed) IDE.register_service('main_container', self) #Register signals connections connections = ( {'target': 'menu_file', 'signal_name': 'openFile(QString)', 'slot': self.open_file}, {'target': 'explorer_container', 'signal_name': 'goToDefinition(int)', 'slot': self.editor_go_to_line}, {'target': 'explorer_container', 'signal_name': 'pep8Activated(bool)', 'slot': self.reset_pep8_warnings}, {'target': 'explorer_container', 'signal_name': 'lintActivated(bool)', 'slot': self.reset_lint_warnings}, ) IDE.register_signals('main_container', connections) if settings.SHOW_START_PAGE: self.show_start_page()
def __init__(self, parent=None): super(_MainContainer, self).__init__(parent) self._parent = parent self.stack = QStackedLayout(self) #Create scrollbar for follow mode self.scrollBar = QScrollBar(Qt.Vertical, self) self.scrollBar.setFixedWidth(20) self.scrollBar.setToolTip( self.tr('Follow Mode: Scroll the Editors together')) self.scrollBar.hide() #hbox.addWidget(self.scrollBar) self.splitter = dynamic_splitter.DynamicSplitter() self.tabs = tab_widget.TabWidget(self) self.setAcceptDrops(True) self.splitter.addWidget(self.tabs) self.stack.addWidget(self.splitter) self.current_split = None #documentation browser self.docPage = None #Code Navigation self._locator = locator.Locator() self.__codeBack = [] self.__codeForward = [] self.__bookmarksFile = '' self.__bookmarksPos = -1 self.__breakpointsFile = '' self.__breakpointsPos = -1 self.__operations = { 0: self._navigate_code_jumps, 1: self._navigate_bookmarks, 2: self._navigate_breakpoints} self.connect(self, SIGNAL("locateFunction(QString, QString, bool)"), self.locate_function) self.connect(self.tabs, SIGNAL("currentChanged(int)"), self._current_tab_changed) self.connect(self.tabs, SIGNAL("splitTab(QTabWidget, int, bool)"), self._split_this_tab) self.connect(self.tabs, SIGNAL("reopenTab(QString)"), self.open_file) self.connect(self.tabs, SIGNAL("syntaxChanged(QWidget, QString)"), self._specify_syntax) self.connect(self.tabs, SIGNAL("allTabsClosed()"), self._main_without_tabs) #reload file self.connect(self.tabs, SIGNAL("reloadFile(QWidget)"), self.reload_file) #for Save on Close operation self.connect(self.tabs, SIGNAL("saveActualEditor()"), self.save_file) #Navigate Code self.connect(self.tabs, SIGNAL("navigateCode(bool, int)"), self.navigate_code_history) # Refresh recent tabs self.connect(self.tabs, SIGNAL("recentTabsModified(QStringList)"), self._recent_files_changed) IDE.register_service('main_container', self) #Register signals connections connections = ( {'target': 'menu_file', 'signal_name': 'openFile(QString)', 'slot': self.open_file}, {'target': 'explorer_container', 'signal_name': 'goToDefinition(int)', 'slot': self.editor_go_to_line}, {'target': 'explorer_container', 'signal_name': 'projectClosed(QString)', 'slot': self.close_files_from_project}, {'target': 'explorer_container', 'signal_name': 'pep8Activated(bool)', 'slot': self.reset_pep8_warnings}, {'target': 'explorer_container', 'signal_name': 'lintActivated(bool)', 'slot': self.reset_lint_warnings}, ) IDE.register_signals('main_container', connections) if settings.SHOW_START_PAGE: self.show_start_page()
def __init__(self, parent=None): super().__init__(parent) self.selectedDatabase = 0 self.uniqueRows = True gui.button(gui.widgetBox(self.controlArea, "Cache", addSpace=True), self, "Clear cache", tooltip="Clear saved query results", callback=self.clearCache) self.martsCombo = gui.comboBox( self.controlArea, self, "selectedDatabase", "Database", callback=self.setSelectedMart, addSpace=True) self.martsCombo.setMaximumWidth(250) self.datasetsCombo = gui.comboBox( self.controlArea, self, "selectedDataset", "Dataset", callback=self.setSelectedDataset, addSpace=True) self.datasetsCombo.setMaximumWidth(250) gui.rubber(self.controlArea) box = gui.widgetBox(self.controlArea, "Results") gui.checkBox( box, self, "uniqueRows", "Unique results only", tooltip="Return unique results only.",) self.commitButton = gui.button( box, self, "Get Results", callback=self.commit, tooltip="Query the BioMart server and output the results", autoDefault=True) self.commitButton.setEnabled(False) self.mainWidget = gui.widgetBox( self.mainArea, orientation=QStackedLayout()) self.mainTab = QTabWidget() self.mainWidget.layout().addWidget(self.mainTab) self.attributesConfigurationBox = gui.createTabPage(self.mainTab, "Attributes") if self.SHOW_FILTERS: # ?? self.filtersConfigurationBox = gui.createTabPage(self.mainTab, "Filters") self.error(0) self.setEnabled(False) self._executor = concurrent.ThreadExecutor( threadPool=QThreadPool(maxThreadCount=2) ) self._task = task = concurrent.Task(function=self._get_registry) task.resultReady.connect(self.setBioMartRegistry) task.exceptionReady.connect(self._handleException) self._executor.submit(task) self._afterInitQueue = [] try: from Bio import SeqIO self.hasBiopython = True except ImportError: self.warning(100, "Biopython package not found.\nTo retrieve FASTA sequence data from BioMart install Biopython.") self.hasBiopython = False
def maximumSize(self): current = self.currentWidget() if current: return current.maximumSize() else: return QStackedLayout.maximumSize(self)
class ComboEditor(QWidget): def __init__(self, original=False): super(ComboEditor, self).__init__() self.__original = original self._symbols_index = [] vbox = QVBoxLayout(self) vbox.setContentsMargins(0, 0, 0, 0) vbox.setSpacing(0) self.bar = ActionBar() vbox.addWidget(self.bar) self.stacked = QStackedLayout() vbox.addLayout(self.stacked) self._main_container = IDE.get_service('main_container') self.connect(self.bar, SIGNAL("changeCurrent(PyQt_PyObject)"), self.set_current) self.connect(self.bar, SIGNAL("runFile(QString)"), self._run_file) self.connect(self.bar, SIGNAL("addToProject(QString)"), self._add_to_project) self.connect(self.bar, SIGNAL("goToSymbol(int)"), self._go_to_symbol) self.connect(self.bar, SIGNAL("reopenTab(QString)"), lambda path: self._main_container.open_file(path)) self.connect(self.bar, SIGNAL("recentTabsModified()"), lambda: self._main_container.recent_files_changed()) self.connect(self.bar.code_navigator.btnPrevious, SIGNAL("clicked()"), lambda: self._navigate_code(False)) self.connect(self.bar.code_navigator.btnNext, SIGNAL("clicked()"), lambda: self._navigate_code(True)) def _navigate_code(self, val): op = self.bar.code_navigator.operation self._main_container.navigate_code_history(val, op) def currentWidget(self): return self.stacked.currentWidget() def add_editor(self, neditable): """Add Editor Widget to the UI area.""" if neditable.editor: self.stacked.addWidget(neditable.editor) self.bar.add_item(neditable.display_name, neditable) # Editor Signals self.connect(neditable.editor, SIGNAL("cursorPositionChanged()"), self._update_cursor_position) self.connect(neditable.editor, SIGNAL("currentLineChanged(int)"), self._set_current_symbol) self.connect(neditable, SIGNAL("checkersUpdated(PyQt_PyObject)"), self._show_notification_icon) self.connect(neditable, SIGNAL("fileSaved(PyQt_PyObject)"), self._update_symbols) # Connect file system signals only in the original self.connect(neditable, SIGNAL("fileClosing(PyQt_PyObject)"), self._close_file) if self.__original: self.connect(neditable, SIGNAL("neverSavedFileClosing(PyQt_PyObject)"), self._ask_for_save) # Load Symbols self._load_symbols(neditable) def show_combo_file(self): self.bar.combo.showPopup() def close_current_file(self): self.bar.about_to_close_file() def _close_file(self, neditable): index = self.bar.close_file(neditable) layoutItem = self.stacked.takeAt(index) neditable.editor.completer.cc.unload_module() self._add_to_last_opened(neditable.file_path) layoutItem.widget().deleteLater() def _add_to_last_opened(self, path): if path not in settings.LAST_OPENED_FILES: settings.LAST_OPENED_FILES.append(path) if len(settings.LAST_OPENED_FILES) > settings.MAX_REMEMBER_TABS: self.__lastOpened = self.__lastOpened[1:] self.emit(SIGNAL("recentTabsModified()")) def _ask_for_save(self, neditable): val = QMessageBox.No fileName = neditable.file_path val = QMessageBox.question( self, (self.tr('The file %s was not saved') % fileName), self.tr("Do you want to save before closing?"), QMessageBox.Yes | QMessageBox.No | QMessageBox.Cancel) if val == QMessageBox.No: neditable.nfile.close(force_close=True) elif val == QMessageBox.Yes: self._main_container.save_file(neditable.editor) neditable.nfile.close() def _run_file(self, path): self._main_container.run_file(path) def _add_to_project(self, path): self._main_container._add_to_project(path) def set_current(self, neditable): if neditable: self.stacked.setCurrentWidget(neditable.editor) self._update_cursor_position(ignore_sender=True) neditable.editor.setFocus() self._main_container.current_editor_changed( neditable.file_path) def widget(self, index): return self.stacked.widget(index) def count(self): """Return the number of editors opened.""" return self.stacked.count() def _update_cursor_position(self, ignore_sender=False): obj = self.sender() editor = self.stacked.currentWidget() # Check if it's current to avoid signals from other splits. if ignore_sender or editor == obj: line = editor.textCursor().blockNumber() + 1 col = editor.textCursor().columnNumber() self.bar.update_line_col(line, col) def _set_current_symbol(self, line, ignore_sender=False): obj = self.sender() editor = self.stacked.currentWidget() # Check if it's current to avoid signals from other splits. if ignore_sender or editor == obj: index = bisect.bisect(self._symbols_index, line) if (index >= len(self._symbols_index) or self._symbols_index[index] > (line + 1)): index -= 1 self.bar.set_current_symbol(index) def _go_to_symbol(self, index): line = self._symbols_index[index] editor = self.stacked.currentWidget() editor.go_to_line(line) def _update_symbols(self, neditable): editor = self.stacked.currentWidget() # Check if it's current to avoid signals from other splits. if editor == neditable.editor: self._load_symbols(neditable) def _load_symbols(self, neditable): symbols_handler = settings.get_symbols_handler('py') source = neditable.editor.toPlainText() source = source.encode(neditable.editor.encoding) symbols = symbols_handler.get_symbols_simplified(source) self._symbols_index = sorted(symbols.keys()) symbols = sorted(list(symbols.items()), key=lambda x: x[0]) self.bar.add_symbols(symbols) line = neditable.editor.textCursor().blockNumber() self._set_current_symbol(line, True) def _show_notification_icon(self, neditable): checkers = neditable.sorted_checkers icon = QIcon() for items in checkers: checker, color, _ = items if checker.checks: if isinstance(checker.checker_icon, int): icon = self.style().standardIcon(checker.checker_icon) elif isinstance(checker.checker_icon, str): icon = QIcon(checker.checker_icon) break self.bar.update_item_icon(neditable, icon)
class _MainContainer(QWidget): ############################################################################### # MainContainer SIGNALS ############################################################################### """ newFileOpened(QString) allTabClosed() runFile(QString) addToProject(QString) showFileInExplorer(QString) recentTabsModified() currentEditorChanged(QString) fileOpened(QString) ---------migrationAnalyzed() findOcurrences(QString) ---------updateFileMetadata() editorKeyPressEvent(QEvent) locateFunction(QString, QString, bool) [functionName, filePath, isVariable] updateLocator(QString) beforeFileSaved(QString) fileSaved(QString) openPreferences() --------openProject(QString) ---------dontOpenStartPage() """ ############################################################################### def __init__(self, parent=None): super(_MainContainer, self).__init__(parent) self._parent = parent self._vbox = QVBoxLayout(self) self._vbox.setContentsMargins(0, 0, 0, 0) self._vbox.setSpacing(0) self.stack = QStackedLayout() self.stack.setStackingMode(QStackedLayout.StackAll) self._vbox.addLayout(self.stack) self.splitter = dynamic_splitter.DynamicSplitter() self.setAcceptDrops(True) self._files_handler = files_handler.FilesHandler(self) self._add_file_folder = add_file_folder.AddFileFolderWidget(self) #documentation browser self.docPage = None #Code Navigation self._locator = locator.GoToDefinition() self.__codeBack = [] self.__codeForward = [] self.__bookmarksFile = '' self.__bookmarksPos = -1 self.__breakpointsFile = '' self.__breakpointsPos = -1 self.__operations = { 0: self._navigate_code_jumps, 1: self._navigate_bookmarks, 2: self._navigate_breakpoints} self.connect(self, SIGNAL("locateFunction(QString, QString, bool)"), self.locate_function) IDE.register_service('main_container', self) #Register signals connections connections = ( {'target': 'menu_file', 'signal_name': 'openFile(QString)', 'slot': self.open_file}, {'target': 'explorer_container', 'signal_name': 'goToDefinition(int)', 'slot': self.editor_go_to_line}, {'target': 'explorer_container', 'signal_name': 'pep8Activated(bool)', 'slot': self.reset_pep8_warnings}, {'target': 'explorer_container', 'signal_name': 'lintActivated(bool)', 'slot': self.reset_lint_warnings}, ) IDE.register_signals('main_container', connections) self.selector = main_selector.MainSelector(self) self._opening_dialog = False self.add_widget(self.selector) if settings.SHOW_START_PAGE: self.show_start_page() self.connect(self.selector, SIGNAL("changeCurrent(int)"), self._change_current_stack) self.connect(self.selector, SIGNAL("removeWidget(int)"), self._remove_item_from_stack) self.connect(self.selector, SIGNAL("ready()"), self._selector_ready) self.connect(self.selector, SIGNAL("animationCompleted()"), self._selector_animation_completed) self.connect(self, SIGNAL("closeDialog(PyQt_PyObject)"), self.remove_widget) def install(self): ide = IDE.get_service('ide') ide.place_me_on("main_container", self, "central", top=True) self.combo_area = combo_editor.ComboEditor(original=True) self.connect(self.combo_area, SIGNAL("allFilesClosed()"), self._files_closed) self.splitter.add_widget(self.combo_area) self.add_widget(self.splitter) self.current_widget = self.combo_area ui_tools.install_shortcuts(self, actions.ACTIONS, ide) def add_status_bar(self, status): self._vbox.addWidget(status) @property def combo_header_size(self): return self.combo_area.bar.height() def add_widget(self, widget): self.stack.addWidget(widget) def remove_widget(self, widget): self.stack.removeWidget(widget) def _close_dialog(self, widget): self.emit(SIGNAL("closeDialog(PyQt_PyObject)"), widget) self.disconnect(widget, SIGNAL("finished(int)"), lambda: self._close_dialog(widget)) def show_dialog(self, widget): self._opening_dialog = True self.connect(widget, SIGNAL("finished(int)"), lambda: self._close_dialog(widget)) self.setVisible(True) self.stack.addWidget(widget) self.show_selector() def show_selector(self): if self.selector != self.stack.currentWidget(): temp_dir = os.path.join(QDir.tempPath(), "ninja-ide") if not os.path.exists(temp_dir): os.mkdir(temp_dir) collected_data = [] current = self.stack.currentIndex() for index in range(self.stack.count()): widget = self.stack.widget(index) if widget == self.selector: continue closable = True if widget == self.splitter: closable = False pixmap = QPixmap.grabWidget(widget, widget.rect()) path = os.path.join(temp_dir, "screen%s.png" % index) pixmap.save(path) if index == current: self.selector.set_preview(index, path) collected_data.insert(0, (index, path, closable)) else: collected_data.append((index, path, closable)) self.selector.set_model(collected_data) else: self.selector.close_selector() def _selector_ready(self): self.stack.setCurrentWidget(self.selector) self.selector.start_animation() def _selector_animation_completed(self): if self._opening_dialog: # We choose the last one with -2, -1 (for last one) + # -1 for the hidden selector widget which is in the stacked too. self.selector.open_item(self.stack.count() - 2) self._opening_dialog = False def _change_current_stack(self, index): self.stack.setCurrentIndex(index) def _remove_item_from_stack(self, index): widget = self.stack.takeAt(index) del widget def show_editor_area(self): self.stack.setCurrentWidget(self.splitter) def _files_closed(self): if settings.SHOW_START_PAGE: self.show_start_page() def change_visibility(self): """Show/Hide the Main Container area.""" if self.isVisible(): self.hide() else: self.show() def expand_symbol_combo(self): self.stack.setCurrentWidget(self.splitter) self.current_widget.show_combo_symbol() def expand_file_combo(self): self.stack.setCurrentWidget(self.splitter) self.current_widget.show_combo_file() def locate_function(self, function, filePath, isVariable): """Move the cursor to the proper position in the navigate stack.""" editorWidget = self.get_current_editor() if editorWidget: self.__codeBack.append((editorWidget.file_path, editorWidget.getCursorPosition())) self.__codeForward = [] self._locator.navigate_to(function, filePath, isVariable) def run_file(self, path): self.emit(SIGNAL("runFile(QString)"), path) def _add_to_project(self, path): self.emit(SIGNAL("addToProject(QString)"), path) def _show_file_in_explorer(self, path): self.emit(SIGNAL("showFileInExplorer(QString)"), path) def paste_history(self): """Paste the text from the copy/paste history.""" editorWidget = self.get_current_editor() if editorWidget and editorWidget.hasFocus(): line, index = editorWidget.getCursorPosition() central = IDE.get_service('central_container') if central: editorWidget.insertAt(central.get_paste(), line, index) def copy_history(self): """Copy the selected text into the copy/paste history.""" editorWidget = self.get_current_editor() if editorWidget and editorWidget.hasFocus(): copy = editorWidget.selectedText() central = IDE.get_service('central_container') if central: central.add_copy(copy) def import_from_everywhere(self): """Insert an import line from any place in the editor.""" editorWidget = self.get_current_editor() if editorWidget: dialog = from_import_dialog.FromImportDialog(editorWidget, self) dialog.show() def add_back_item_navigation(self): """Add an item to the back stack and reset the forward stack.""" editorWidget = self.get_current_editor() if editorWidget: self.__codeBack.append((editorWidget.file_path, editorWidget.getCursorPosition())) self.__codeForward = [] def preview_in_browser(self): """Load the current html file in the default browser.""" editorWidget = self.get_current_editor() if editorWidget: if not editorWidget.file_path: self.save_file() ext = file_manager.get_file_extension(editorWidget.file_path) if ext == 'html': webbrowser.open(editorWidget.file_path) def add_bookmark_breakpoint(self): """Add a bookmark or breakpoint to the current file in the editor.""" editorWidget = self.get_current_editor() if editorWidget and editorWidget.hasFocus(): if self.current_widget.bar.code_navigator.operation == 1: editorWidget.handle_bookmarks_breakpoints( editorWidget.getCursorPosition()[0], Qt.ControlModifier) elif self.current_widget.bar.code_navigator.operation == 2: editorWidget.handle_bookmarks_breakpoints( editorWidget.getCursorPosition()[0], Qt.NoModifier) def __navigate_with_keyboard(self, val): """Navigate between the positions in the jump history stack.""" op = self.current_widget.bar.code_navigator.operation self.navigate_code_history(val, op) def navigate_code_history(self, val, op): """Navigate the code history.""" self.__operations[op](val) def _navigate_code_jumps(self, val): """Navigate between the jump points.""" node = None if not val and self.__codeBack: node = self.__codeBack.pop() editorWidget = self.get_current_editor() if editorWidget: self.__codeForward.append((editorWidget.file_path, editorWidget.getCursorPosition())) elif val and self.__codeForward: node = self.__codeForward.pop() editorWidget = self.get_current_editor() if editorWidget: self.__codeBack.append((editorWidget.file_path, editorWidget.getCursorPosition())) if node: filename = node[0] line, col = node[1] self.open_file(filename, line, col) def _navigate_breakpoints(self, val): """Navigate between the breakpoints.""" #FIXME: put navigate breakpoints and bookmarks as one method. breakList = list(settings.BREAKPOINTS.keys()) breakList.sort() if not breakList: return if self.__breakpointsFile not in breakList: self.__breakpointsFile = breakList[0] index = breakList.index(self.__breakpointsFile) breaks = settings.BREAKPOINTS.get(self.__breakpointsFile, []) lineNumber = 0 #val == True: forward if val: if (len(breaks) - 1) > self.__breakpointsPos: self.__breakpointsPos += 1 lineNumber = breaks[self.__breakpointsPos] elif len(breaks) > 0: if index < (len(breakList) - 1): self.__breakpointsFile = breakList[index + 1] else: self.__breakpointsFile = breakList[0] self.__breakpointsPos = 0 lineNumber = settings.BREAKPOINTS[self.__breakpointsFile][0] else: if self.__breakpointsPos > 0: self.__breakpointsPos -= 1 lineNumber = breaks[self.__breakpointsPos] elif len(breaks) > 0: self.__breakpointsFile = breakList[index - 1] breaks = settings.BREAKPOINTS[self.__breakpointsFile] self.__breakpointsPos = len(breaks) - 1 lineNumber = breaks[self.__breakpointsPos] if file_manager.file_exists(self.__breakpointsFile): self.open_file(self.__breakpointsFile, lineNumber, None, True) else: settings.BREAKPOINTS.pop(self.__breakpointsFile) if settings.BREAKPOINTS: self._navigate_breakpoints(val) def _navigate_bookmarks(self, val): """Navigate between the bookmarks.""" bookList = list(settings.BOOKMARKS.keys()) bookList.sort() if not bookList: return if self.__bookmarksFile not in bookList: self.__bookmarksFile = bookList[0] index = bookList.index(self.__bookmarksFile) bookms = settings.BOOKMARKS.get(self.__bookmarksFile, []) lineNumber = 0 #val == True: forward if val: if (len(bookms) - 1) > self.__bookmarksPos: self.__bookmarksPos += 1 lineNumber = bookms[self.__bookmarksPos] elif len(bookms) > 0: if index < (len(bookList) - 1): self.__bookmarksFile = bookList[index + 1] else: self.__bookmarksFile = bookList[0] self.__bookmarksPos = 0 lineNumber = settings.BOOKMARKS[self.__bookmarksFile][0] else: if self.__bookmarksPos > 0: self.__bookmarksPos -= 1 lineNumber = bookms[self.__bookmarksPos] elif len(bookms) > 0: self.__bookmarksFile = bookList[index - 1] bookms = settings.BOOKMARKS[self.__bookmarksFile] self.__bookmarksPos = len(bookms) - 1 lineNumber = bookms[self.__bookmarksPos] if file_manager.file_exists(self.__bookmarksFile): self.open_file(self.__bookmarksFile, lineNumber, None, True) else: settings.BOOKMARKS.pop(self.__bookmarksFile) if settings.BOOKMARKS: self._navigate_bookmarks(val) def count_file_code_lines(self): """Count the lines of code in the current file.""" editorWidget = self.get_current_editor() if editorWidget: block_count = editorWidget.lines() blanks = re.findall('(^\n)|(^(\s+)?#)|(^( +)?($|\n))', editorWidget.text(), re.M) blanks_count = len(blanks) resume = self.tr("Lines code: %s\n") % (block_count - blanks_count) resume += (self.tr("Blanks and commented lines: %s\n\n") % blanks_count) resume += self.tr("Total lines: %s") % block_count msgBox = QMessageBox(QMessageBox.Information, self.tr("Summary of lines"), resume, QMessageBox.Ok, editorWidget) msgBox.exec_() def editor_cut(self): editorWidget = self.get_current_editor() if editorWidget: editorWidget.cut() def editor_copy(self): editorWidget = self.get_current_editor() if editorWidget: editorWidget.copy() def editor_paste(self): editorWidget = self.get_current_editor() if editorWidget: editorWidget.paste() def editor_upper(self): editorWidget = self.get_current_editor() if editorWidget: editorWidget.to_upper() def editor_lower(self): editorWidget = self.get_current_editor() if editorWidget: editorWidget.to_lower() def editor_title(self): editorWidget = self.get_current_editor() if editorWidget: editorWidget.to_title() def editor_go_to_definition(self): """Search the definition of the method or variable under the cursor. If more than one method or variable is found with the same name, shows a table with the results and let the user decide where to go.""" editorWidget = self.get_current_editor() if editorWidget and editorWidget.hasFocus(): editorWidget.go_to_definition() def editor_redo(self): """Execute the redo action in the current editor.""" editorWidget = self.get_current_editor() if editorWidget and editorWidget.hasFocus(): editorWidget.redo() def editor_undo(self): editorWidget = self.get_current_editor() if editorWidget and editorWidget.hasFocus(): editorWidget.undo() def editor_indent_less(self): """Indent 1 position to the left for the current line or selection.""" editorWidget = self.get_current_editor() if editorWidget and editorWidget.hasFocus(): editorWidget.indent_less() def editor_indent_more(self): """Indent 1 position to the right for the current line or selection.""" editorWidget = self.get_current_editor() if editorWidget and editorWidget.hasFocus(): editorWidget.indent() def editor_insert_debugging_prints(self): """Insert a print statement in each selected line.""" editorWidget = self.get_current_editor() if editorWidget: helpers.insert_debugging_prints(editorWidget) def editor_insert_pdb(self): """Insert a pdb.set_trace() statement in tjhe current line.""" editorWidget = self.get_current_editor() if editorWidget: helpers.insert_pdb(editorWidget) def editor_comment(self): """Mark the current line or selection as a comment.""" editorWidget = self.get_current_editor() if editorWidget and editorWidget.hasFocus(): helpers.comment(editorWidget) def editor_uncomment(self): """Uncomment the current line or selection.""" editorWidget = self.get_current_editor() if editorWidget and editorWidget.hasFocus(): helpers.uncomment(editorWidget) def editor_insert_horizontal_line(self): """Insert an horizontal lines of comment symbols.""" editorWidget = self.get_current_editor() if editorWidget and editorWidget.hasFocus(): helpers.insert_horizontal_line(editorWidget) def editor_insert_title_comment(self): """Insert a Title surrounded by comment symbols.""" editorWidget = self.get_current_editor() if editorWidget and editorWidget.hasFocus(): helpers.insert_title_comment(editorWidget) def editor_remove_trailing_spaces(self): """Remove the trailing spaces in the current editor.""" editorWidget = self.get_current_editor() if editorWidget: helpers.remove_trailing_spaces(editorWidget) def editor_replace_tabs_with_spaces(self): """Replace the Tabs with Spaces in the current editor.""" editorWidget = self.get_current_editor() if editorWidget: helpers.replace_tabs_with_spaces(editorWidget) def editor_move_up(self): """Move the current line or selection one position up.""" editorWidget = self.get_current_editor() if editorWidget and editorWidget.hasFocus(): helpers.move_up(editorWidget) def editor_move_down(self): """Move the current line or selection one position down.""" editorWidget = self.get_current_editor() if editorWidget and editorWidget.hasFocus(): helpers.move_down(editorWidget) def editor_remove_line(self): """Remove the current line or selection.""" editorWidget = self.get_current_editor() if editorWidget and editorWidget.hasFocus(): helpers.remove_line(editorWidget) def editor_duplicate(self): """Duplicate the current line or selection.""" editorWidget = self.get_current_editor() if editorWidget and editorWidget.hasFocus(): helpers.duplicate(editorWidget) def editor_highlight_word(self): """Highlight the occurrences of the current word in the editor.""" editorWidget = self.get_current_editor() if editorWidget and editorWidget.hasFocus(): editorWidget.highlight_selected_word() def editor_complete_declaration(self): """Do the opposite action that Complete Declaration expect.""" editorWidget = self.get_current_editor() if editorWidget and editorWidget.hasFocus(): editorWidget.complete_declaration() def editor_go_to_line(self, line): """Jump to the specified line in the current editor.""" editorWidget = self.get_current_editor() if editorWidget: editorWidget.jump_to_line(line) def zoom_in_editor(self): """Increase the font size in the current editor.""" editorWidget = self.get_current_editor() if editorWidget: editorWidget.zoom_in() def zoom_out_editor(self): """Decrease the font size in the current editor.""" editorWidget = self.get_current_editor() if editorWidget: editorWidget.zoom_out() def recent_files_changed(self): self.emit(SIGNAL("recentTabsModified()")) def dragEnterEvent(self, event): if event.mimeData().hasUrls(): event.accept() else: event.ignore() def dropEvent(self, event): file_path = event.mimeData().urls()[0].toLocalFile() self.open_file(file_path) def setFocus(self): widget = self.get_current_widget() if widget: widget.setFocus() def current_editor_changed(self, filename): """Notify the new filename of the current editor.""" if filename is None: filename = translations.TR_NEW_DOCUMENT self.emit(SIGNAL("currentEditorChanged(QString)"), filename) def show_split(self, orientation_vertical=False): #IDE.select_current(self.current_widget.currentWidget()) self.current_widget.split_editor(orientation_vertical) def add_editor(self, fileName=None, ignore_checkers=False): ninjaide = IDE.get_service('ide') editable = ninjaide.get_or_create_editable(fileName) if editable.editor: self.current_widget.set_current(editable) return editable.editor else: editable.ignore_checkers = ignore_checkers editorWidget = self.create_editor_from_editable(editable) #add the tab if self.current_widget != self.combo_area: self.combo_area.add_editor(editable) self.current_widget.add_editor(editable) #emit a signal about the file open self.emit(SIGNAL("fileOpened(QString)"), fileName) self.stack.setCurrentWidget(self.splitter) return editorWidget def create_editor_from_editable(self, editable): editorWidget = editor.create_editor(editable) #Connect signals self.connect(editable, SIGNAL("fileSaved(PyQt_PyObject)"), self._editor_tab_was_saved) self.connect(editorWidget, SIGNAL("openDropFile(QString)"), self.open_file) self.connect(editorWidget, SIGNAL("addBackItemNavigation()"), self.add_back_item_navigation) self.connect(editorWidget, SIGNAL("locateFunction(QString, QString, bool)"), self._editor_locate_function) self.connect(editorWidget, SIGNAL("findOcurrences(QString)"), self._find_occurrences) #keyPressEventSignal for plugins self.connect(editorWidget, SIGNAL("keyPressEvent(QEvent)"), self._editor_keyPressEvent) return editorWidget def reset_pep8_warnings(self, value): pass #FIXME: check how we handle this #for i in range(self._tabMain.count()): #widget = self._tabMain.widget(i) #if type(widget) is editor.Editor: #if value: #widget.syncDocErrorsSignal = True #widget.pep8.check_style() #else: #widget.hide_pep8_errors() def reset_lint_warnings(self, value): pass #FIXME: check how we handle this #for i in range(self._tabMain.count()): #widget = self._tabMain.widget(i) #if type(widget) is editor.Editor: #if value: #widget.syncDocErrorsSignal = True #widget.errors.check_errors() #else: #widget.hide_lint_errors() def _find_occurrences(self, word): self.emit(SIGNAL("findOcurrences(QString)"), word) def _editor_keyPressEvent(self, event): self.emit(SIGNAL("editorKeyPressEvent(QEvent)"), event) def _editor_locate_function(self, function, filePath, isVariable): self.emit(SIGNAL("locateFunction(QString, QString, bool)"), function, filePath, isVariable) def _editor_tab_was_saved(self, editable=None): self.emit(SIGNAL("updateLocator(QString)"), editable.file_path) def get_current_widget(self): return self.current_widget.currentWidget() def get_current_editor(self): """Return the Actual Editor or None Return an instance of Editor if the Current Tab contains an Editor or None if it is not an instance of Editor""" widget = self.current_widget.currentWidget() if isinstance(widget, editor.Editor): return widget return None def reload_file(self, editorWidget=None): if editorWidget is None: editorWidget = self.get_current_editor() editorWidget.neditable.reload_file() def add_tab(self, widget, tabName, tabIndex=None): pass #return self.tabs.add_tab(widget, tabName, index=tabIndex) def open_image(self, fileName): try: if not self.is_open(fileName): viewer = image_viewer.ImageViewer(fileName) self.add_tab(viewer, file_manager.get_basename(fileName)) viewer.ID = fileName else: self.move_to_open(fileName) except Exception as reason: logger.error('open_image: %s', reason) QMessageBox.information(self, self.tr("Incorrect File"), self.tr("The image couldn\'t be open")) def open_file(self, filename='', line=-1, col=0, ignore_checkers=False): logger.debug("will try to open %s" % filename) if not filename: logger.debug("has nofilename") if settings.WORKSPACE: directory = settings.WORKSPACE else: directory = os.path.expanduser("~") editorWidget = self.get_current_editor() ninjaide = IDE.get_service('ide') if ninjaide: current_project = ninjaide.get_current_project() if current_project is not None: directory = current_project elif editorWidget is not None and editorWidget.file_path: directory = file_manager.get_folder( editorWidget.file_path) extensions = ';;'.join( ['{}(*{})'.format(e.upper()[1:], e) for e in settings.SUPPORTED_EXTENSIONS + ['.*', '']]) fileNames = list(QFileDialog.getOpenFileNames(self, self.tr("Open File"), directory, extensions)) else: logger.debug("has filename") fileNames = [filename] if not fileNames: return for filename in fileNames: if file_manager.get_file_extension(filename) in ('jpg', 'png'): logger.debug("will open as image") self.open_image(filename) elif file_manager.get_file_extension(filename).endswith('ui'): logger.debug("will load in ui editor") self.w = uic.loadUi(filename) self.w.show() else: logger.debug("will try to open: " + filename) self.__open_file(filename, line, col, ignore_checkers) def __open_file(self, fileName='', line=-1, col=0, ignore_checkers=False): try: editorWidget = self.add_editor(fileName, ignore_checkers=ignore_checkers) if line != -1: editorWidget.set_cursor_position(line, col) self.emit(SIGNAL("currentEditorChanged(QString)"), fileName) except file_manager.NinjaIOException as reason: QMessageBox.information(self, self.tr("The file couldn't be open"), str(reason)) def is_open(self, filename): pass #return self.tabs.is_open(filename) != -1 def move_to_open(self, filename): pass #FIXME: add in the current split? #if self.tabs.is_open(filename) != -1: #self.tabs.move_to_open(filename) #self.tabs.currentWidget().setFocus() #self.emit(SIGNAL("currentEditorChanged(QString)"), filename) def get_widget_for_id(self, filename): pass #widget = None #index = self.tabs.is_open(filename) #if index != -1: #widget = self.tabs.widget(index) #return widget def change_open_tab_id(self, idname, newId): """Search for the Tab with idname, and set the newId to that Tab.""" pass #index = self.tabs.is_open(idname) #if index != -1: #widget = self.tabs.widget(index) #tabName = file_manager.get_basename(newId) #self.tabs.change_open_tab_name(index, tabName) #widget.ID = newId def close_deleted_file(self, idname): """Search for the Tab with id, and ask the user if should be closed.""" pass #index = self.tabs.is_open(idname) #if index != -1: #result = QMessageBox.question(self, self.tr("Close Deleted File"), #self.tr("Are you sure you want to close the deleted file?\n" #"The content will be completely deleted."), #buttons=QMessageBox.Yes | QMessageBox.No) #if result == QMessageBox.Yes: #self.tabs.removeTab(index) def save_file(self, editorWidget=None): #FIXME: check how we handle this if not editorWidget: editorWidget = self.get_current_editor() if not editorWidget: return False try: #editorWidget.just_saved = True if (editorWidget.nfile.is_new_file or not editorWidget.nfile.has_write_permission()): return self.save_file_as() self.emit(SIGNAL("beforeFileSaved(QString)"), editorWidget.file_path) if settings.REMOVE_TRAILING_SPACES: helpers.remove_trailing_spaces(editorWidget) editorWidget.neditable.save_content() #file_manager.store_file_content( #fileName, content, addExtension=False) encoding = file_manager.get_file_encoding(editorWidget.text()) editorWidget.encoding = encoding self.emit(SIGNAL("fileSaved(QString)"), (self.tr("File Saved: %s") % editorWidget.file_path)) return True except Exception as reason: logger.error('save_file: %s', reason) QMessageBox.information(self, self.tr("Save Error"), self.tr("The file couldn't be saved!")) return False def save_file_as(self): editorWidget = self.get_current_editor() if not editorWidget: return False try: filters = '(*.py);;(*.*)' if editorWidget.file_path: ext = file_manager.get_file_extension(editorWidget.file_path) if ext != 'py': filters = '(*.%s);;(*.py);;(*.*)' % ext save_folder = self._get_save_folder(editorWidget.file_path) fileName = QFileDialog.getSaveFileName( self._parent, self.tr("Save File"), save_folder, filters) if not fileName: return False if settings.REMOVE_TRAILING_SPACES: helpers.remove_trailing_spaces(editorWidget) editorWidget.neditable.save_content(path=fileName) editorWidget.register_syntax( file_manager.get_file_extension(fileName)) self.emit(SIGNAL("fileSaved(QString)"), (self.tr("File Saved: %s") % fileName)) self.emit(SIGNAL("currentEditorChanged(QString)"), fileName) return True except file_manager.NinjaFileExistsException as ex: QMessageBox.information(self, self.tr("File Already Exists"), (self.tr("Invalid Path: the file '%s' " " already exists.") % ex.filename)) except Exception as reason: logger.error('save_file_as: %s', reason) QMessageBox.information(self, self.tr("Save Error"), self.tr("The file couldn't be saved!")) return False def _get_save_folder(self, fileName): """ Returns the root directory of the 'Main Project' or the home folder """ ninjaide = IDE.get_service('ide') current_project = ninjaide.get_current_project() if current_project: return current_project.path return os.path.expanduser("~") def save_project(self, projectFolder): pass #FIXME: check how we handle this #for i in range(self._tabMain.count()): #editorWidget = self._tabMain.widget(i) #if type(editorWidget) is editor.Editor and \ #file_manager.belongs_to_folder(projectFolder, #editorWidget.file_path): #reloaded = self._tabMain.check_for_external_modifications( #editorWidget) #if not reloaded: #self.save_file(editorWidget) #for i in range(self.tabsecondary.count()): #editorWidget = self.tabsecondary.widget(i) #if type(editorWidget) is editor.Editor and \ #file_manager.belongs_to_folder(projectFolder, #editorWidget.file_path): #reloaded = self.tabsecondary.check_for_external_modifications( #editorWidget) #if not reloaded: #self.save_file(editorWidget) def save_all(self): pass #FIXME: check how we handle this #for i in range(self._tabMain.count()): #editorWidget = self._tabMain.widget(i) #if type(editorWidget) is editor.Editor: #reloaded = self._tabMain.check_for_external_modifications( #editorWidget) #if not reloaded: #self.save_file(editorWidget) #for i in range(self.tabsecondary.count()): #editorWidget = self.tabsecondary.widget(i) #self.tabsecondary.check_for_external_modifications(editorWidget) #if type(editorWidget) is editor.Editor: #reloaded = self.tabsecondary.check_for_external_modifications( #editorWidget) #if not reloaded: #self.save_file(editorWidget) def call_editors_function(self, call_function, *arguments): pass #args = arguments[0] #kwargs = arguments[1] #for i in range(self.tabs.count()): #editorWidget = self.tabs.widget(i) #if isinstance(editorWidget, editor.Editor): #function = getattr(editorWidget, call_function) #function(*args, **kwargs) #TODO: add other splits def show_start_page(self): start = self.stack.widget(0) if isinstance(start, start_page.StartPage): self.stack.setCurrentIndex(0) else: startPage = start_page.StartPage(parent=self) self.connect(startPage, SIGNAL("openProject(QString)"), self.open_project) self.connect(startPage, SIGNAL("openPreferences()"), lambda: self.emit(SIGNAL("openPreferences()"))) self.connect(startPage, SIGNAL("newFile()"), self.add_editor) self.stack.insertWidget(0, startPage) self.stack.setCurrentIndex(0) def show_python_doc(self): if sys.platform == 'win32': self.docPage = browser_widget.BrowserWidget( 'http://docs.python.org/') else: process = runner.start_pydoc() self.docPage = browser_widget.BrowserWidget(process[1], process[0]) self.add_tab(self.docPage, translations.TR_PYTHON_DOC) def show_report_bugs(self): webbrowser.open(resources.BUGS_PAGE) def show_plugins_doc(self): bugsPage = browser_widget.BrowserWidget(resources.PLUGINS_DOC, self) self.add_tab(bugsPage, translations.TR_HOW_TO_WRITE_PLUGINS) def editor_jump_to_line(self, lineno=None): """Jump to line *lineno* if it is not None otherwise ask to the user the line number to jump """ editorWidget = self.get_current_editor() if editorWidget: editorWidget.jump_to_line(lineno=lineno) def get_opened_documents(self): #return self.tabs.get_documents_data() return [] def check_for_unsaved_files(self): pass #return self.tabs._check_unsaved_tabs() def get_unsaved_files(self): pass #return self.tabs.get_unsaved_files() def reset_editor_flags(self): pass #for i in range(self.tabs.count()): #widget = self.tabs.widget(i) #if isinstance(widget, editor.Editor): #widget.set_flags() def _specify_syntax(self, widget, syntaxLang): if isinstance(widget, editor.Editor): widget.restyle(syntaxLang) def apply_editor_theme(self, family, size): pass #for i in range(self.tabs.count()): #widget = self.tabs.widget(i) #if isinstance(widget, editor.Editor): #widget.restyle() #widget.set_font(family, size) def update_editor_margin_line(self): pass #for i in range(self.tabs.count()): #widget = self.tabs.widget(i) #if isinstance(widget, editor.Editor): #widget._update_margin_line() def open_project(self, path): self.emit(SIGNAL("openProject(QString)"), path) def close_python_doc(self): pass #close the python document server (if running) #if self.docPage: #index = self.tabs.indexOf(self.docPage) #self.tabs.removeTab(index) ##assign None to the browser #self.docPage = None def close_file(self): """Close the current tab in the current TabWidget.""" self.current_widget.close_current_file() def create_file(self, base_path, project_path): self._add_file_folder.create_file(base_path, project_path) def create_folder(self, base_path, project_path): self._add_file_folder.create_folder(base_path, project_path) def change_tab(self): """Change the tab in the current TabWidget.""" self.stack.setCurrentWidget(self.splitter) self._files_handler.next_item() def change_tab_reverse(self): """Change the tab in the current TabWidget backwards.""" self.stack.setCurrentWidget(self.splitter) self._files_handler.previous_item() def toggle_tabs_and_spaces(self): """ Toggle Show/Hide Tabs and Spaces """ settings.SHOW_TABS_AND_SPACES = not settings.SHOW_TABS_AND_SPACES qsettings = IDE.ninja_settings() qsettings.setValue('preferences/editor/showTabsAndSpaces', settings.SHOW_TABS_AND_SPACES) def show_navigation_buttons(self): """Show Navigation menu.""" self.stack.setCurrentWidget(self.splitter) self.combo_area.show_menu_navigation() def change_split_focus(self): pass #FIXME: check how we handle this #if self.actualTab == self._tabMain and self.tabsecondary.isVisible(): #self.actualTab = self.tabsecondary #else: #self.actualTab = self._tabMain #widget = self.actualTab.currentWidget() #if widget is not None: #widget.setFocus() def shortcut_index(self, index): pass #self.tabs.setCurrentIndex(index) def print_file(self): """Call the print of ui_tool Call print of ui_tool depending on the focus of the application""" #TODO: Add funtionality for proyect tab and methods tab editorWidget = self.get_current_editor() if editorWidget is not None: fileName = "newDocument.pdf" if editorWidget.file_path: fileName = file_manager.get_basename( editorWidget.file_path) fileName = fileName[:fileName.rfind('.')] + '.pdf' ui_tools.print_file(fileName, editorWidget.print_) def split_assistance(self): dialog = split_orientation.SplitOrientation(self) dialog.show() def close_split(self): if self.current_widget != self.combo_area: self.current_widget.bar.close_split() def split_vertically(self): self.show_split(False) def split_horizontally(self): self.show_split(True) def navigate_back(self): self.__navigate_with_keyboard(False) def navigate_forward(self): self.__navigate_with_keyboard(True)
def __init__(self, parent=None): QStackedLayout.__init__(self, parent) self.currentChanged.connect(self._onCurrentChanged)
class CenterView(QWidget): img_correct = '<img src="%s" height="22" width="22">'%\ utils.resource_path('correct.svg') img_incorrect = '<img src="%s" height="22" width="22">'%\ utils.resource_path('incorrect.svg') img_unanswered = '<img src="%s" height="22" width="22">'%\ utils.resource_path('unanswered.svg') def __init__(self, parent=None): super(CenterView, self).__init__(parent) layout = QVBoxLayout() self.setLayout(layout) self.center = QStackedLayout() self.camview = widgets.CamView((640, 480), self, draw_logo=True) self.label_up = QLabel() self.label_down = QLabel() self.center.addWidget(self.camview) layout.addLayout(self.center) layout.addWidget(self.label_up) layout.addWidget(self.label_down) self.adjustSize() self.setFixedSize(self.sizeHint()) def update_status(self, score, model=None, seq_num=None, survey_mode=False): parts = [] if score is not None: if not survey_mode: parts.append(CenterView.img_correct) if score.correct is not None: parts.append(str(score.correct) + ' ') else: parts.append('--- ') parts.append(CenterView.img_incorrect) if score.incorrect is not None: parts.append(str(score.incorrect) + ' ') else: parts.append('--- ') parts.append(CenterView.img_unanswered) if score.blank is not None: parts.append(str(score.blank) + ' ') else: parts.append('--- ') if score.score is not None and score.max_score is not None: parts.append(_('Score: {0:.2f} / {1:.2f}')\ .format(score.score, score.max_score)) parts.append(' ') else: parts.append(_('[Survey mode on]')) parts.append(' ') if model is not None: parts.append(_('Model:') + ' ' + model + ' ') if seq_num is not None: parts.append(_('Num.:') + ' ' + str(seq_num) + ' ') self.label_down.setText( ('<span style="white-space: pre">' + ' '.join(parts) + '</span>')) def update_text_up(self, text): self.label_up.setText(text) def update_text_down(self, text): self.label_down.setText(text) def display_capture(self, ipl_image): """Displays a captured image in the window. The image is in the OpenCV IPL format. """ self.camview.display_capture(ipl_image) def display_wait_image(self): """Displays the default image instead of a camera capture.""" self.camview.display_wait_image() def register_listener(self, key, listener): """Registers listeners for the center view. Available listeners are: - ('camview', 'mouse_pressed'): mouse pressed in the camview area. The listener receives the coordinates (x, y) as a tuple. """ if key[0] == 'camview': if key[1] == 'mouse_pressed': self.camview.register_mouse_pressed_listener(listener) else: assert False, 'Undefined listener key: {0}'.format(key) else: assert False, 'Undefined listener key: {0}'.format(key)
def __init__(self): super().__init__() self.modified = False box = group_box(self.tr("Default method"), layout=layout(Qt.Vertical)) self.controlArea.layout().addWidget(box) bgroup = QButtonGroup() for i, m in enumerate(self.METHODS[1:-1], 1): b = radio_button(m.name, checked=i == self.default_method, group=bgroup, group_id=i) box.layout().addWidget(b) self.defbggroup = bgroup bgroup.buttonClicked[int].connect(self.set_default_method) box = group_box(self.tr("Individual attribute settings"), layout=layout(Qt.Horizontal)) self.controlArea.layout().addWidget(box) self.varview = QtGui.QListView( selectionMode=QtGui.QListView.ExtendedSelection ) self.varview.setItemDelegate(DisplayFormatDelegate()) self.varmodel = itemmodels.VariableListModel() self.varview.setModel(self.varmodel) self.varview.selectionModel().selectionChanged.connect( self._on_var_selection_changed ) self.selection = self.varview.selectionModel() box.layout().addWidget(self.varview) method_layout = layout(Qt.Vertical, margins=0) box.layout().addLayout(method_layout) methodbox = group_box(layout=layout(Qt.Vertical)) bgroup = QButtonGroup() for i, m in enumerate(self.METHODS): b = radio_button(m.name, group=bgroup, group_id=i) methodbox.layout().addWidget(b) assert self.METHODS[-1].short == "value" self.value_stack = value_stack = QStackedLayout() self.value_combo = QComboBox( minimumContentsLength=8, sizeAdjustPolicy=QComboBox.AdjustToMinimumContentsLength, activated=self._on_value_changed) self.value_line = QLineEdit(editingFinished=self._on_value_changed) self.value_line.setValidator(QDoubleValidator()) value_stack.addWidget(self.value_combo) value_stack.addWidget(self.value_line) methodbox.layout().addLayout(value_stack) bgroup.buttonClicked[int].connect( self.set_method_for_current_selection ) reset_button = push_button("Restore all to default", clicked=self.reset_var_methods, default=False, autoDefault=False) method_layout.addWidget(methodbox) method_layout.addStretch(2) method_layout.addWidget(reset_button) self.varmethodbox = methodbox self.varbgroup = bgroup box = gui.auto_commit( self.controlArea, self, "autocommit", "Commit", orientation=Qt.Horizontal, checkbox_label="Commit on any change") box.layout().insertSpacing(0, 80) box.layout().insertWidget(0, self.report_button) self.data = None self.learner = None
class _MainContainer(QWidget): ############################################################################### # MainContainer SIGNALS ############################################################################### """ beforeFileSaved(QString) fileSaved(QString) currentTabChanged(QString) locateFunction(QString, QString, bool) [functionName, filePath, isVariable] openProject(QString) openPreferences() dontOpenStartPage() navigateCode(bool, int) addBackItemNavigation() updateLocator(QString) updateFileMetadata() findOcurrences(QString) cursorPositionChange(int, int) #row, col fileOpened(QString) newFileOpened(QString) recentTabsModified(QStringList) migrationAnalyzed() allTabClosed() """ ############################################################################### def __init__(self, parent=None): super(_MainContainer, self).__init__(parent) self._parent = parent self.stack = QStackedLayout(self) #Create scrollbar for follow mode self.scrollBar = QScrollBar(Qt.Vertical, self) self.scrollBar.setFixedWidth(20) self.scrollBar.setToolTip( self.tr('Follow Mode: Scroll the Editors together')) self.scrollBar.hide() #hbox.addWidget(self.scrollBar) self.splitter = dynamic_splitter.DynamicSplitter() self.tabs = tab_widget.TabWidget(self) self.setAcceptDrops(True) self.splitter.addWidget(self.tabs) self.stack.addWidget(self.splitter) self.current_split = None #documentation browser self.docPage = None #Code Navigation self._locator = locator.Locator() self.__codeBack = [] self.__codeForward = [] self.__bookmarksFile = '' self.__bookmarksPos = -1 self.__breakpointsFile = '' self.__breakpointsPos = -1 self.__operations = { 0: self._navigate_code_jumps, 1: self._navigate_bookmarks, 2: self._navigate_breakpoints} self.connect(self, SIGNAL("locateFunction(QString, QString, bool)"), self.locate_function) self.connect(self.tabs, SIGNAL("currentChanged(int)"), self._current_tab_changed) self.connect(self.tabs, SIGNAL("splitTab(QTabWidget, int, bool)"), self._split_this_tab) self.connect(self.tabs, SIGNAL("reopenTab(QString)"), self.open_file) self.connect(self.tabs, SIGNAL("syntaxChanged(QWidget, QString)"), self._specify_syntax) self.connect(self.tabs, SIGNAL("allTabsClosed()"), self._main_without_tabs) #reload file self.connect(self.tabs, SIGNAL("reloadFile(QWidget)"), self.reload_file) #for Save on Close operation self.connect(self.tabs, SIGNAL("saveActualEditor()"), self.save_file) #Navigate Code self.connect(self.tabs, SIGNAL("navigateCode(bool, int)"), self.navigate_code_history) # Refresh recent tabs self.connect(self.tabs, SIGNAL("recentTabsModified(QStringList)"), self._recent_files_changed) IDE.register_service('main_container', self) #Register signals connections connections = ( {'target': 'menu_file', 'signal_name': 'openFile(QString)', 'slot': self.open_file}, {'target': 'explorer_container', 'signal_name': 'goToDefinition(int)', 'slot': self.editor_go_to_line}, {'target': 'explorer_container', 'signal_name': 'projectClosed(QString)', 'slot': self.close_files_from_project}, {'target': 'explorer_container', 'signal_name': 'pep8Activated(bool)', 'slot': self.reset_pep8_warnings}, {'target': 'explorer_container', 'signal_name': 'lintActivated(bool)', 'slot': self.reset_lint_warnings}, ) IDE.register_signals('main_container', connections) if settings.SHOW_START_PAGE: self.show_start_page() def install(self): ide = IDE.get_service('ide') ide.place_me_on("main_container", self, "central", top=True) ui_tools.install_shortcuts(self, actions.ACTIONS, ide) def change_visibility(self): """Show/Hide the Main Container area.""" if self.isVisible(): self.hide() else: self.show() def locate_function(self, function, filePath, isVariable): """Move the cursor to the proper position in the navigate stack.""" editorWidget = self.get_current_editor() if editorWidget: self.__codeBack.append((editorWidget.ID, editorWidget.textCursor().position())) self.__codeForward = [] self._locator.navigate_to(function, filePath, isVariable) def close_files_from_project(self, project): """Close the files related to this project.""" if project: for tabIndex in reversed(list(range(self.tabs.count()))): if file_manager.belongs_to_folder( project, self.tabs.widget(tabIndex).ID): self.tabs.removeTab(tabIndex) #TODO: HANDLE SPLITS CLOSE? def paste_history(self): """Paste the text from the copy/paste history.""" editorWidget = self.get_current_editor() if editorWidget and editorWidget.hasFocus(): cursor = editorWidget.textCursor() central = IDE.get_service('central_container') if central: cursor.insertText(central.get_paste()) def copy_history(self): """Copy the selected text into the copy/paste history.""" editorWidget = self.get_current_editor() if editorWidget and editorWidget.hasFocus(): cursor = editorWidget.textCursor() copy = cursor.selectedText() central = IDE.get_service('central_container') if central: central.add_copy(copy) def import_from_everywhere(self): """Add an item to the back stack and reset the forward stack.""" editorWidget = self.get_current_editor() if editorWidget: dialog = from_import_dialog.FromImportDialog(editorWidget, self) dialog.show() def add_back_item_navigation(self): """Add an item to the back stack and reset the forward stack.""" editorWidget = self.get_current_editor() if editorWidget: self.__codeBack.append((editorWidget.ID, editorWidget.textCursor().position())) self.__codeForward = [] def preview_in_browser(self): """Load the current html file in the default browser.""" editorWidget = self.get_current_editor() if editorWidget: if not editorWidget.ID: self.save_file() ext = file_manager.get_file_extension(editorWidget.ID) if ext == 'html': webbrowser.open(editorWidget.ID) def add_bookmark_breakpoint(self): """Add a bookmark or breakpoint to the current file in the editor.""" editorWidget = self.get_current_editor() if editorWidget and editorWidget.hasFocus(): if self.tabs.navigator.operation == 1: editorWidget._sidebarWidget.set_bookmark( editorWidget.textCursor().blockNumber()) elif self.tabs.navigator.operation == 2: editorWidget._sidebarWidget.set_breakpoint( editorWidget.textCursor().blockNumber()) def __navigate_with_keyboard(self, val): """Navigate between the positions in the jump history stack.""" op = self.actualTab._tabs.operation self.navigate_code_history(val, op) def navigate_code_history(self, val, op): """Navigate the code history.""" self.__operations[op](val) def _navigate_code_jumps(self, val): """Navigate between the jump points.""" node = None if not val and self.__codeBack: node = self.__codeBack.pop() editorWidget = self.get_current_editor() if editorWidget: self.__codeForward.append((editorWidget.ID, editorWidget.textCursor().position())) elif val and self.__codeForward: node = self.__codeForward.pop() editorWidget = self.get_current_editor() if editorWidget: self.__codeBack.append((editorWidget.ID, editorWidget.textCursor().position())) if node: self.open_file(node[0], node[1]) def _navigate_breakpoints(self, val): """Navigate between the breakpoints.""" #FIXME: put navigate breakpoints and bookmarks as one method. breakList = list(settings.BREAKPOINTS.keys()) breakList.sort() if not breakList: return if self.__breakpointsFile not in breakList: self.__breakpointsFile = breakList[0] index = breakList.index(self.__breakpointsFile) breaks = settings.BREAKPOINTS.get(self.__breakpointsFile, []) lineNumber = 0 #val == True: forward if val: if (len(breaks) - 1) > self.__breakpointsPos: self.__breakpointsPos += 1 lineNumber = breaks[self.__breakpointsPos] elif len(breaks) > 0: if index < (len(breakList) - 1): self.__breakpointsFile = breakList[index + 1] else: self.__breakpointsFile = breakList[0] self.__breakpointsPos = 0 lineNumber = settings.BREAKPOINTS[self.__breakpointsFile][0] else: if self.__breakpointsPos > 0: self.__breakpointsPos -= 1 lineNumber = breaks[self.__breakpointsPos] elif len(breaks) > 0: self.__breakpointsFile = breakList[index - 1] breaks = settings.BREAKPOINTS[self.__breakpointsFile] self.__breakpointsPos = len(breaks) - 1 lineNumber = breaks[self.__breakpointsPos] if file_manager.file_exists(self.__breakpointsFile): self.open_file(self.__breakpointsFile, lineNumber, None, True) else: settings.BREAKPOINTS.pop(self.__breakpointsFile) if settings.BREAKPOINTS: self._navigate_breakpoints(val) def _navigate_bookmarks(self, val): """Navigate between the bookmarks.""" bookList = list(settings.BOOKMARKS.keys()) bookList.sort() if not bookList: return if self.__bookmarksFile not in bookList: self.__bookmarksFile = bookList[0] index = bookList.index(self.__bookmarksFile) bookms = settings.BOOKMARKS.get(self.__bookmarksFile, []) lineNumber = 0 #val == True: forward if val: if (len(bookms) - 1) > self.__bookmarksPos: self.__bookmarksPos += 1 lineNumber = bookms[self.__bookmarksPos] elif len(bookms) > 0: if index < (len(bookList) - 1): self.__bookmarksFile = bookList[index + 1] else: self.__bookmarksFile = bookList[0] self.__bookmarksPos = 0 lineNumber = settings.BOOKMARKS[self.__bookmarksFile][0] else: if self.__bookmarksPos > 0: self.__bookmarksPos -= 1 lineNumber = bookms[self.__bookmarksPos] elif len(bookms) > 0: self.__bookmarksFile = bookList[index - 1] bookms = settings.BOOKMARKS[self.__bookmarksFile] self.__bookmarksPos = len(bookms) - 1 lineNumber = bookms[self.__bookmarksPos] if file_manager.file_exists(self.__bookmarksFile): self.open_file(self.__bookmarksFile, lineNumber, None, True) else: settings.BOOKMARKS.pop(self.__bookmarksFile) if settings.BOOKMARKS: self._navigate_bookmarks(val) def count_file_code_lines(self): """Count the lines of code in the current file.""" editorWidget = self.get_current_editor() if editorWidget: block_count = editorWidget.blockCount() blanks = re.findall('(^\n)|(^(\s+)?#)|(^( +)?($|\n))', editorWidget.get_text(), re.M) blanks_count = len(blanks) resume = self.tr("Lines code: %s\n") % (block_count - blanks_count) resume += (self.tr("Blanks and commented lines: %s\n\n") % blanks_count) resume += self.tr("Total lines: %s") % block_count msgBox = QMessageBox(QMessageBox.Information, self.tr("Summary of lines"), resume, QMessageBox.Ok, editorWidget) msgBox.exec_() def editor_cut(self): editorWidget = self.get_current_editor() if editorWidget: editorWidget.cut() def editor_copy(self): editorWidget = self.get_current_editor() if editorWidget: editorWidget.copy() def editor_paste(self): editorWidget = self.get_current_editor() if editorWidget: editorWidget.paste() def editor_upper(self): editorWidget = self.get_current_editor() if editorWidget: editorWidget.to_upper() def editor_lower(self): editorWidget = self.get_current_editor() if editorWidget: editorWidget.to_lower() def editor_title(self): editorWidget = self.get_current_editor() if editorWidget: editorWidget.to_title() def editor_go_to_definition(self): """Search the definition of the method or variable under the cursor. If more than one method or variable is found with the same name, shows a table with the results and let the user decide where to go.""" editorWidget = self.get_current_editor() if editorWidget and editorWidget.hasFocus(): editorWidget.go_to_definition() def editor_redo(self): """Execute the redo action in the current editor.""" editorWidget = self.get_current_editor() if editorWidget and editorWidget.hasFocus(): editorWidget.redo() def editor_undo(self): editorWidget = self.get_current_editor() if editorWidget and editorWidget.hasFocus(): editorWidget.undo() def editor_indent_less(self): """Indent 1 position to the left for the current line or selection.""" editorWidget = self.get_current_editor() if editorWidget and editorWidget.hasFocus(): editorWidget.indent_less() def editor_indent_more(self): """Indent 1 position to the right for the current line or selection.""" editorWidget = self.get_current_editor() if editorWidget and editorWidget.hasFocus(): editorWidget.indent_more() def editor_insert_debugging_prints(self): """Insert a print statement in each selected line.""" editorWidget = self.get_current_editor() if editorWidget: helpers.insert_debugging_prints(editorWidget) def editor_insert_pdb(self): """Insert a pdb.set_trace() statement in tjhe current line.""" editorWidget = self.get_current_editor() if editorWidget: helpers.insert_pdb(editorWidget) def editor_comment(self): """Mark the current line or selection as a comment.""" editorWidget = self.get_current_editor() if editorWidget and editorWidget.hasFocus(): helpers.comment(editorWidget) def editor_uncomment(self): """Uncomment the current line or selection.""" editorWidget = self.get_current_editor() if editorWidget and editorWidget.hasFocus(): helpers.uncomment(editorWidget) def editor_insert_horizontal_line(self): """Insert an horizontal lines of comment symbols.""" editorWidget = self.get_current_editor() if editorWidget and editorWidget.hasFocus(): helpers.insert_horizontal_line(editorWidget) def editor_insert_title_comment(self): """Insert a Title surrounded by comment symbols.""" editorWidget = self.get_current_editor() if editorWidget and editorWidget.hasFocus(): helpers.insert_title_comment(editorWidget) def editor_remove_trailing_spaces(self): """Remove the trailing spaces in the current editor.""" editorWidget = self.get_current_editor() if editorWidget: helpers.remove_trailing_spaces(editorWidget) def editor_replace_tabs_with_spaces(self): """Replace the Tabs with Spaces in the current editor.""" editorWidget = self.get_current_editor() if editorWidget: helpers.replace_tabs_with_spaces(editorWidget) def editor_move_up(self): """Move the current line or selection one position up.""" editorWidget = self.get_current_editor() if editorWidget and editorWidget.hasFocus(): helpers.move_up(editorWidget) def editor_move_down(self): """Move the current line or selection one position down.""" editorWidget = self.get_current_editor() if editorWidget and editorWidget.hasFocus(): helpers.move_down(editorWidget) def editor_remove_line(self): """Remove the current line or selection.""" editorWidget = self.get_current_editor() if editorWidget and editorWidget.hasFocus(): helpers.remove_line(editorWidget) def editor_duplicate(self): """Duplicate the current line or selection.""" editorWidget = self.get_current_editor() if editorWidget and editorWidget.hasFocus(): helpers.duplicate(editorWidget) def editor_highlight_word(self): """Highlight the occurrences of the current word in the editor.""" editorWidget = self.get_current_editor() if editorWidget and editorWidget.hasFocus(): editorWidget.highlight_selected_word() def editor_complete_declaration(self): """Do the opposite action that Complete Declaration expect.""" editorWidget = self.get_current_editor() if editorWidget and editorWidget.hasFocus(): editorWidget.complete_declaration() def editor_go_to_line(self, line): """Jump to the specified line in the current editor.""" editorWidget = self.get_current_editor() if editorWidget: editorWidget.jump_to_line(line) def zoom_in_editor(self): """Increase the font size in the current editor.""" editorWidget = self.get_current_editor() if editorWidget: editorWidget.zoom_in() def zoom_out_editor(self): """Decrease the font size in the current editor.""" editorWidget = self.get_current_editor() if editorWidget: editorWidget.zoom_out() def _recent_files_changed(self, files): self.emit(SIGNAL("recentTabsModified(QStringList)"), files) def dragEnterEvent(self, event): if event.mimeData().hasUrls(): event.accept() else: event.ignore() def dropEvent(self, event): file_path = event.mimeData().urls()[0].toLocalFile() self.open_file(file_path) def setFocus(self): widget = self.get_actual_widget() if widget: widget.setFocus() def group_tabs_together(self): """Group files that belongs to the same project together.""" ninjaide = IDE.get_service('ide') projects = ninjaide.get_opened_projects() for project in projects: project_name = projects[project].name project_path = projects[project].path tabGroup = tab_group.TabGroup(project_path, project_name, self) self.connect(tabGroup, SIGNAL("expandAll()"), self.deactivate_tabs_groups) for index in reversed(list(range(self.tabs.count()))): widget = self.tabs.widget(index) if (isinstance(widget, editor.Editor) and widget.project == projects[project]): tabGroup.add_widget(widget) self.tabs.removeTab(index) if tabGroup.tabs: self.tabs.add_tab(tabGroup, project_name) def deactivate_tabs_groups(self): """Deactivate tab grouping based in the project they belong.""" for index in reversed(list(range(self.tabs.count()))): widget = self.tabs.widget(index) if isinstance(widget, tab_group.TabGroup): widget.expand() def _main_without_tabs(self): """Notify that there are no more tabs opened.""" self.emit(SIGNAL("allTabsClosed()")) def _current_tab_changed(self, index): """Notify the new ID of the current tab.""" widget = self.tabs.widget(index) if widget: self.emit(SIGNAL("currentTabChanged(QString)"), widget.ID) def split_tab(self, orientation): pass #FIXME: check how we handle this #"""Split the main container.""" #if orientationHorizontal: #self.show_split(Qt.Vertical) #else: #self.show_split(Qt.Horizontal) def _split_this_tab(self, tab, index, orientationHorizontal): pass #FIXME: check how we handle this #tab.setCurrentIndex(index) #if orientationHorizontal: #self.show_split(Qt.Horizontal) #else: #self.show_split(Qt.Vertical) def change_tabs_visibility(self): if self._tabMain.tabBar().isVisible(): self._tabMain.tabBar().hide() else: self._tabMain.tabBar().show() def show_split(self, orientation): pass #FIXME: check how we handle this #closingFollowMode = self._followMode #if self._followMode: #self._exit_follow_mode() #if self.tabsecondary.isVisible() and \ #orientation == self.orientation(): #self.tabsecondary.hide() #self.split_visible = False #for i in range(self.tabsecondary.count()): #widget = self.tabsecondary.widget(0) #name = self.tabsecondary.tabText(0) #self._tabMain.add_tab(widget, name) #if name in self.tabsecondary.titles: #self.tabsecondary.titles.remove(name) #if type(widget) is editor.Editor and widget.textModified: #self._tabMain.tab_was_modified(True) #self.actualTab = self._tabMain #elif not self.tabsecondary.isVisible() and not closingFollowMode: #widget = self.get_actual_widget() #name = self._tabMain.tabText(self._tabMain.currentIndex()) #self.tabsecondary.add_tab(widget, name) #if name in self._tabMain.titles: #self._tabMain.titles.remove(name) #if type(widget) is editor.Editor and widget.textModified: #self.tabsecondary.tab_was_modified(True) #self.tabsecondary.show() #self.split_visible = True #self.splitter.setSizes([1, 1]) #self.actualTab = self.tabsecondary #self.emit(SIGNAL("currentTabChanged(QString)"), widget.ID) #self.splitter.setOrientation(orientation) def add_editor(self, fileName="", tabIndex=None): ninjaide = IDE.get_service('ide') project = ninjaide.get_project_for_file(fileName) editable = ninjaide.get_editable(fileName, project) editorWidget = editor.create_editor(editable) tab_name = editable.display_name #add the tab index = self.add_tab(editorWidget, tab_name, tabIndex=tabIndex) self.tabs.setTabToolTip(index, QDir.toNativeSeparators(fileName)) #Connect signals self.connect(editorWidget, SIGNAL("modificationChanged(bool)"), self._editor_tab_was_modified) self.connect(editorWidget, SIGNAL("fileSaved(QPlainTextEdit)"), self._editor_tab_was_saved) self.connect(editorWidget, SIGNAL("openDropFile(QString)"), self.open_file) self.connect(editorWidget, SIGNAL("addBackItemNavigation()"), self.add_back_item_navigation) self.connect(editorWidget, SIGNAL("locateFunction(QString, QString, bool)"), self._editor_locate_function) self.connect(editorWidget, SIGNAL("checksFound(QPlainTextEdit, PyQt_PyObject)"), self._show_tab_indicator) self.connect(editorWidget, SIGNAL("cleanDocument(QPlainTextEdit)"), self._hide_icon_tab_indicator) self.connect(editorWidget, SIGNAL("findOcurrences(QString)"), self._find_occurrences) self.connect(editorWidget, SIGNAL("migrationAnalyzed()"), lambda: self.emit(SIGNAL("migrationAnalyzed()"))) #Cursor position changed self.connect(editorWidget, SIGNAL("cursorPositionChange(int, int)"), self._cursor_position_changed) #keyPressEventSignal for plugins self.connect(editorWidget, SIGNAL("keyPressEvent(QEvent)"), self._editor_keyPressEvent) #emit a signal about the file open self.emit(SIGNAL("fileOpened(QString)"), fileName) return editorWidget def update_editor_project(self): pass #FIXME: check how we handle this #for i in range(self._tabMain.count()): #widget = self._tabMain.widget(i) #if type(widget) is editor.Editor: #project = self._parent.explorer.get_project_given_filename( #widget.ID) #widget.set_project(project) def reset_pep8_warnings(self, value): pass #FIXME: check how we handle this #for i in range(self._tabMain.count()): #widget = self._tabMain.widget(i) #if type(widget) is editor.Editor: #if value: #widget.syncDocErrorsSignal = True #widget.pep8.check_style() #else: #widget.hide_pep8_errors() #for i in range(self.tabsecondary.count()): #widget = self.tabsecondary.widget(i) #if type(widget) is editor.Editor: #if value: #widget.syncDocErrorsSignal = True #widget.pep8.check_style() #else: #widget.hide_pep8_errors() def reset_lint_warnings(self, value): pass #FIXME: check how we handle this #for i in range(self._tabMain.count()): #widget = self._tabMain.widget(i) #if type(widget) is editor.Editor: #if value: #widget.syncDocErrorsSignal = True #widget.errors.check_errors() #else: #widget.hide_lint_errors() #for i in range(self.tabsecondary.count()): #widget = self.tabsecondary.widget(i) #if type(widget) is editor.Editor: #if value: #widget.syncDocErrorsSignal = True #widget.errors.check_errors() #else: #widget.hide_lint_errors() def _cursor_position_changed(self, row, col): self.emit(SIGNAL("cursorPositionChange(int, int)"), row, col) def _find_occurrences(self, word): self.emit(SIGNAL("findOcurrences(QString)"), word) def _show_tab_indicator(self, editorWidget, icon): index = self.tabs.indexOf(editorWidget) self.emit(SIGNAL("updateFileMetadata()")) if index >= 0 and icon: if isinstance(icon, int): icon = QIcon(self.style().standardIcon(icon)) self.tabs.setTabIcon(index, icon) def _hide_icon_tab_indicator(self, editorWidget): index = self.tabs.indexOf(editorWidget) self.emit(SIGNAL("updateFileMetadata()")) if index >= 0: self.tabs.setTabIcon(index, QIcon()) def _editor_keyPressEvent(self, event): self.emit(SIGNAL("editorKeyPressEvent(QEvent)"), event) def _editor_locate_function(self, function, filePath, isVariable): self.emit(SIGNAL("locateFunction(QString, QString, bool)"), function, filePath, isVariable) def _editor_tab_was_modified(self, val=True): self.tabs.tab_was_modified(val) def _editor_tab_was_saved(self, editorWidget=None): self.tabs.tab_was_saved(editorWidget) self.emit(SIGNAL("updateLocator(QString)"), editorWidget.ID) def get_current_widget(self): return self.current_split.currentWidget() def get_current_editor(self): """Return the Actual Editor or None Return an instance of Editor if the Current Tab contains an Editor or None if it is not an instance of Editor""" widget = self.current_split.currentWidget() if isinstance(widget, editor.Editor): return widget return None def reload_file(self, editorWidget=None): if editorWidget is None: editorWidget = self.get_current_editor() if editorWidget is not None and editorWidget.ID: fileName = editorWidget.ID old_cursor_position = editorWidget.textCursor().position() old_widget_index = self.tabs.indexOf(editorWidget) self.tabs.removeTab(old_widget_index) #open the file in the same tab as before self.open_file(fileName, tabIndex=old_widget_index) #get the new editor and set the old cursor position editorWidget = self.get_current_editor() cursor = editorWidget.textCursor() cursor.setPosition(old_cursor_position) editorWidget.setTextCursor(cursor) def add_tab(self, widget, tabName, tabIndex=None): return self.tabs.add_tab(widget, tabName, index=tabIndex) def open_image(self, fileName): try: if not self.is_open(fileName): viewer = image_viewer.ImageViewer(fileName) self.add_tab(viewer, file_manager.get_basename(fileName)) viewer.ID = fileName else: self.move_to_open(fileName) except Exception as reason: logger.error('open_image: %s', reason) QMessageBox.information(self, self.tr("Incorrect File"), self.tr("The image couldn\'t be open")) def open_file(self, filename='', cursorPosition=-1, tabIndex=None, positionIsLineNumber=False, notStart=True): if not filename: if settings.WORKSPACE: directory = settings.WORKSPACE else: directory = os.path.expanduser("~") editorWidget = self.get_current_editor() ninjaide = IDE.get_service('ide') if ninjaide: current_project = ninjaide.get_current_project() if current_project is not None: directory = current_project elif editorWidget is not None and editorWidget.ID: directory = file_manager.get_folder(editorWidget.ID) extensions = ';;'.join( ['(*%s)' % e for e in settings.SUPPORTED_EXTENSIONS + ['.*', '']]) fileNames = list(QFileDialog.getOpenFileNames(self, self.tr("Open File"), directory, extensions)) else: fileNames = [filename] if not fileNames: return for filename in fileNames: if file_manager.get_file_extension(filename) in ('jpg', 'png'): self.open_image(filename) elif file_manager.get_file_extension(filename).endswith('ui'): self.w = uic.loadUi(filename) self.w.show() else: self.__open_file(filename, cursorPosition, tabIndex, positionIsLineNumber, notStart) def __open_file(self, fileName='', cursorPosition=-1, tabIndex=None, positionIsLineNumber=False): try: if not self.is_open(fileName): editorWidget = self.add_editor(fileName, tabIndex=tabIndex) if cursorPosition == -1: cursorPosition = 0 if positionIsLineNumber: editorWidget.go_to_line(cursorPosition) else: editorWidget.set_cursor_position(cursorPosition) else: self.move_to_open(fileName) editorWidget = self.get_current_editor() if editorWidget and cursorPosition != -1: if positionIsLineNumber: editorWidget.go_to_line(cursorPosition) else: editorWidget.set_cursor_position(cursorPosition) self.emit(SIGNAL("currentTabChanged(QString)"), fileName) except file_manager.NinjaIOException as reason: QMessageBox.information(self, self.tr("The file couldn't be open"), str(reason)) except Exception as reason: logger.error('open_file: %s', reason) def is_open(self, filename): return self.tabs.is_open(filename) != -1 def move_to_open(self, filename): #FIXME: add in the current split? if self.tabs.is_open(filename) != -1: self.tabs.move_to_open(filename) self.tabs.currentWidget().setFocus() self.emit(SIGNAL("currentTabChanged(QString)"), filename) def move_tab_right(self): self._move_tab() def move_tab_left(self): self._move_tab(forward=False) def _move_tab(self, forward=True, widget=None): if widget is None: widget = self.tabs.currentWidget() if widget is not None: old_widget_index = self.tabs.indexOf(widget) if forward and old_widget_index < self.tabs.count() - 1: new_widget_index = old_widget_index + 1 elif old_widget_index > 0 and not forward: new_widget_index = old_widget_index - 1 else: return tabName = self.tabs.tabText(old_widget_index) self.tabs.insertTab(new_widget_index, widget, tabName) self.tabs.setCurrentIndex(new_widget_index) def get_widget_for_id(self, filename): widget = None index = self.tabs.is_open(filename) if index != -1: widget = self.tabs.widget(index) return widget def change_open_tab_id(self, idname, newId): """Search for the Tab with idname, and set the newId to that Tab.""" index = self.tabs.is_open(idname) if index != -1: widget = self.tabs.widget(index) tabName = file_manager.get_basename(newId) self.tabs.change_open_tab_name(index, tabName) widget.ID = newId def close_deleted_file(self, idname): """Search for the Tab with id, and ask the user if should be closed.""" index = self.tabs.is_open(idname) if index != -1: result = QMessageBox.question(self, self.tr("Close Deleted File"), self.tr("Are you sure you want to close the deleted file?\n" "The content will be completely deleted."), buttons=QMessageBox.Yes | QMessageBox.No) if result == QMessageBox.Yes: self.tabs.removeTab(index) def save_file(self, editorWidget=None): pass #FIXME: check how we handle this #if not editorWidget: #editorWidget = self.get_current_editor() #if not editorWidget: #return False #try: #editorWidget.just_saved = True #if editorWidget.newDocument or \ #not file_manager.has_write_permission(editorWidget.ID): #return self.save_file_as() #fileName = editorWidget.ID #self.emit(SIGNAL("beforeFileSaved(QString)"), fileName) #if settings.REMOVE_TRAILING_SPACES: #helpers.remove_trailing_spaces(editorWidget) #content = editorWidget.get_text() #file_manager.store_file_content( #fileName, content, addExtension=False) #self._file_watcher.allow_kill = False #if editorWidget.ID != fileName: #self.remove_standalone_watcher(editorWidget.ID) #self.add_standalone_watcher(fileName) #self._file_watcher.allow_kill = True #editorWidget.ID = fileName #encoding = file_manager.get_file_encoding(content) #editorWidget.encoding = encoding #self.emit(SIGNAL("fileSaved(QString)"), #(self.tr("File Saved: %s") % fileName)) #editorWidget._file_saved() #return True #except Exception as reason: #editorWidget.just_saved = False #logger.error('save_file: %s', reason) #QMessageBox.information(self, self.tr("Save Error"), #self.tr("The file couldn't be saved!")) #return False def save_file_as(self): pass #FIXME: check how we handle this #editorWidget = self.get_current_editor() #if not editorWidget: #return False #try: #editorWidget.just_saved = True #filters = '(*.py);;(*.*)' #if editorWidget.ID: #ext = file_manager.get_file_extension(editorWidget.ID) #if ext != 'py': #filters = '(*.%s);;(*.py);;(*.*)' % ext #save_folder = self._get_save_folder(editorWidget.ID) #fileName = QFileDialog.getSaveFileName( #self._parent, self.tr("Save File"), save_folder, filters) #if not fileName: #return False #if settings.REMOVE_TRAILING_SPACES: #helpers.remove_trailing_spaces(editorWidget) #newFile = file_manager.get_file_extension(fileName) == '' #fileName = file_manager.store_file_content( #fileName, editorWidget.get_text(), #addExtension=True, newFile=newFile) #self.actualTab.setTabText(self.actualTab.currentIndex(), #file_manager.get_basename(fileName)) #editorWidget.register_syntax( #file_manager.get_file_extension(fileName)) #self._file_watcher.allow_kill = False #if editorWidget.ID != fileName: #self.remove_standalone_watcher(editorWidget.ID) #editorWidget.ID = fileName #self.emit(SIGNAL("fileSaved(QString)"), #(self.tr("File Saved: %s") % fileName)) #self.emit(SIGNAL("currentTabChanged(QString)"), fileName) #editorWidget._file_saved() #self.add_standalone_watcher(fileName) #self._file_watcher.allow_kill = True #return True #except file_manager.NinjaFileExistsException as ex: #editorWidget.just_saved = False #QMessageBox.information(self, self.tr("File Already Exists"), #(self.tr("Invalid Path: the file '%s' already exists.") % #ex.filename)) #except Exception as reason: #editorWidget.just_saved = False #logger.error('save_file_as: %s', reason) #QMessageBox.information(self, self.tr("Save Error"), #self.tr("The file couldn't be saved!")) #self.actualTab.setTabText(self.actualTab.currentIndex(), #self.tr("New Document")) #return False def _get_save_folder(self, fileName): pass #FIXME: check how we handle this #""" #Returns the root directory of the 'Main Project' or the home folder #""" #actual_project = self._parent.explorer.get_actual_project() #if actual_project: #return actual_project #return os.path.expanduser("~") def save_project(self, projectFolder): pass #FIXME: check how we handle this #for i in range(self._tabMain.count()): #editorWidget = self._tabMain.widget(i) #if type(editorWidget) is editor.Editor and \ #file_manager.belongs_to_folder(projectFolder, editorWidget.ID): #reloaded = self._tabMain.check_for_external_modifications( #editorWidget) #if not reloaded: #self.save_file(editorWidget) #for i in range(self.tabsecondary.count()): #editorWidget = self.tabsecondary.widget(i) #if type(editorWidget) is editor.Editor and \ #file_manager.belongs_to_folder(projectFolder, editorWidget.ID): #reloaded = self.tabsecondary.check_for_external_modifications( #editorWidget) #if not reloaded: #self.save_file(editorWidget) def save_all(self): pass #FIXME: check how we handle this #for i in range(self._tabMain.count()): #editorWidget = self._tabMain.widget(i) #if type(editorWidget) is editor.Editor: #reloaded = self._tabMain.check_for_external_modifications( #editorWidget) #if not reloaded: #self.save_file(editorWidget) #for i in range(self.tabsecondary.count()): #editorWidget = self.tabsecondary.widget(i) #self.tabsecondary.check_for_external_modifications(editorWidget) #if type(editorWidget) is editor.Editor: #reloaded = self.tabsecondary.check_for_external_modifications( #editorWidget) #if not reloaded: #self.save_file(editorWidget) def call_editors_function(self, call_function, *arguments): args = arguments[0] kwargs = arguments[1] for i in range(self.tabs.count()): editorWidget = self.tabs.widget(i) if isinstance(editorWidget, editor.Editor): function = getattr(editorWidget, call_function) function(*args, **kwargs) #TODO: add other splits def show_start_page(self): if not self.is_open("Start Page"): startPage = start_page.StartPage(parent=self) self.connect(startPage, SIGNAL("openProject(QString)"), self.open_project) self.connect(startPage, SIGNAL("openPreferences()"), lambda: self.emit(SIGNAL("openPreferences()"))) self.add_tab(startPage, 'Start Page') else: self.move_to_open("Start Page") def show_python_doc(self): if sys.platform == 'win32': self.docPage = browser_widget.BrowserWidget( 'http://docs.python.org/') else: process = runner.start_pydoc() self.docPage = browser_widget.BrowserWidget(process[1], process[0]) self.add_tab(self.docPage, translations.TR_PYTHON_DOC) def show_report_bugs(self): webbrowser.open(resources.BUGS_PAGE) def show_plugins_doc(self): bugsPage = browser_widget.BrowserWidget(resources.PLUGINS_DOC, self) self.add_tab(bugsPage, translations.TR_HOW_TO_WRITE_PLUGINS) def editor_jump_to_line(self, lineno=None): """Jump to line *lineno* if it is not None otherwise ask to the user the line number to jump """ editorWidget = self.get_current_editor() if editorWidget: editorWidget.jump_to_line(lineno=lineno) def get_opened_documents(self): return self.tabs.get_documents_data() def open_files(self, files): for fileData in files: if file_manager.file_exists(fileData[0]): self.open_file(fileData[0], fileData[1]) def check_for_unsaved_tabs(self): return self.tabs._check_unsaved_tabs() def get_unsaved_files(self): return self.tabs.get_unsaved_files() def reset_editor_flags(self): for i in range(self.tabs.count()): widget = self.tabs.widget(i) if isinstance(widget, editor.Editor): widget.set_flags() def _specify_syntax(self, widget, syntaxLang): if isinstance(widget, editor.Editor): widget.restyle(syntaxLang) def apply_editor_theme(self, family, size): for i in range(self.tabs.count()): widget = self.tabs.widget(i) if isinstance(widget, editor.Editor): widget.restyle() widget.set_font(family, size) def update_editor_margin_line(self): for i in range(self.tabs.count()): widget = self.tabs.widget(i) if isinstance(widget, editor.Editor): widget._update_margin_line() def open_project(self, path): self.emit(SIGNAL("openProject(QString)"), path) def close_python_doc(self): #close the python document server (if running) if self.docPage: index = self.tabs.indexOf(self.docPage) self.tabs.removeTab(index) #assign None to the browser self.docPage = None def close_tab(self): """Close the current tab in the current TabWidget.""" self.tabs.close_tab() def change_tab(self): """Change the tab in the current TabWidget.""" self.tabs.change_tab() def change_tab_reverse(self): """Change the tab in the current TabWidget backwards.""" self.tabs.change_tab_reverse() def show_navigation_buttons(self): self.tabs.navigator.show_menu_navigation() def change_split_focus(self): pass #FIXME: check how we handle this #if self.actualTab == self._tabMain and self.tabsecondary.isVisible(): #self.actualTab = self.tabsecondary #else: #self.actualTab = self._tabMain #widget = self.actualTab.currentWidget() #if widget is not None: #widget.setFocus() def shortcut_index(self, index): self.tabs.setCurrentIndex(index) def print_file(self): """Call the print of ui_tool Call print of ui_tool depending on the focus of the application""" #TODO: Add funtionality for proyect tab and methods tab editorWidget = self.get_current_editor() if editorWidget is not None: fileName = "newDocument.pdf" if editorWidget.ID: fileName = file_manager.get_basename( editorWidget.ID) fileName = fileName[:fileName.rfind('.')] + '.pdf' ui_tools.print_file(fileName, editorWidget.print_) def split_tabh(self): self.split_tab(True) def split_tabv(self): self.split_tab(False) def split_assistance(self): dialog = split_orientation.SplitOrientation(self) dialog.show() def close_split(self): pass def navigate_back(self): self.__navigate_with_keyboard(False) def navigate_forward(self): self.__navigate_with_keyboard(True)
class ComboEditor(QDialog): def __init__(self, original=False): super(ComboEditor, self).__init__(None, Qt.WindowStaysOnTopHint) self.__original = original self.__undocked = [] self._symbols_index = [] vbox = QVBoxLayout(self) vbox.setContentsMargins(0, 0, 0, 0) vbox.setSpacing(0) self.bar = ActionBar(main_combo=original) vbox.addWidget(self.bar) self.stacked = QStackedLayout() vbox.addLayout(self.stacked) self._main_container = IDE.get_service('main_container') if not self.__original: self.connect(self._main_container, SIGNAL("fileOpened(QString)"), self._file_opened_by_main) self.connect(self.bar, SIGNAL("changeCurrent(PyQt_PyObject, int)"), self._set_current) self.connect(self.bar, SIGNAL("splitEditor(bool)"), self.split_editor) self.connect(self.bar, SIGNAL("runFile(QString)"), self._run_file) self.connect(self.bar, SIGNAL("closeSplit()"), lambda: self.emit(SIGNAL("closeSplit(PyQt_PyObject)"), self)) self.connect(self.bar, SIGNAL("addToProject(QString)"), self._add_to_project) self.connect(self.bar, SIGNAL("goToSymbol(int)"), self._go_to_symbol) self.connect(self.bar, SIGNAL("undockEditor()"), self.undock_editor) self.connect(self.bar, SIGNAL("reopenTab(QString)"), lambda path: self._main_container.open_file(path)) self.connect(self.bar, SIGNAL("recentTabsModified()"), lambda: self._main_container.recent_files_changed()) self.connect(self.bar.code_navigator.btnPrevious, SIGNAL("clicked()"), lambda: self._navigate_code(False)) self.connect(self.bar.code_navigator.btnNext, SIGNAL("clicked()"), lambda: self._navigate_code(True)) def _navigate_code(self, val): op = self.bar.code_navigator.operation self._main_container.navigate_code_history(val, op) def currentWidget(self): return self.stacked.currentWidget() def setFocus(self): super(ComboEditor, self).setFocus() self.stacked.currentWidget().setFocus() self._editor_with_focus() def _file_opened_by_main(self, path): index = self.stacked.currentIndex() ninjaide = IDE.get_service('ide') editable = ninjaide.get_or_create_editable(path) self.add_editor(editable) self.bar.set_current_by_index(index) def add_editor(self, neditable): """Add Editor Widget to the UI area.""" if neditable.editor: if self.__original: editor = neditable.editor else: editor = self._main_container.create_editor_from_editable( neditable) self.stacked.addWidget(editor) self.bar.add_item(neditable.display_name, neditable) # Editor Signals self.connect(editor, SIGNAL("cursorPositionChanged()"), self._update_cursor_position) self.connect(editor, SIGNAL("editorFocusObtained()"), self._editor_with_focus) self.connect(editor, SIGNAL("currentLineChanged(int)"), self._set_current_symbol) self.connect(editor, SIGNAL("modificationChanged(bool)"), self._editor_modified) self.connect(neditable, SIGNAL("checkersUpdated(PyQt_PyObject)"), self._show_notification_icon) self.connect(neditable, SIGNAL("fileSaved(PyQt_PyObject)"), self._update_symbols) self.connect(neditable, SIGNAL("fileSaved(PyQt_PyObject)"), self._update_combo_info) # Connect file system signals only in the original self.connect(neditable, SIGNAL("fileClosing(PyQt_PyObject)"), self._close_file) if self.__original: self.connect(neditable, SIGNAL("neverSavedFileClosing(PyQt_PyObject)"), self._ask_for_save) self.connect(neditable, SIGNAL("fileChanged(PyQt_PyObject)"), self._file_has_been_modified) # Load Symbols self._load_symbols(neditable) def show_combo_file(self): self.bar.combo.showPopup() def show_combo_symbol(self): self.bar.symbols_combo.showPopup() def split_editor(self, orientationVertical): new_widget = ComboEditor() for neditable in self.bar.get_editables(): new_widget.add_editor(neditable) self.emit(SIGNAL("splitEditor(PyQt_PyObject, PyQt_PyObject, bool)"), self, new_widget, orientationVertical) def undock_editor(self): new_combo = ComboEditor() new_combo.setWindowTitle("NINJA-IDE") self.__undocked.append(new_combo) for neditable in self.bar.get_editables(): new_combo.add_editor(neditable) new_combo.resize(500, 500) self.connect(new_combo, SIGNAL("aboutToCloseComboEditor()"), self._remove_undock) new_combo.show() def _remove_undock(self): widget = self.sender() self.__undocked.remove(widget) def close_current_file(self): self.bar.about_to_close_file() def _close_file(self, neditable): index = self.bar.close_file(neditable) layoutItem = self.stacked.takeAt(index) neditable.editor.completer.cc.unload_module() self._add_to_last_opened(neditable.file_path) layoutItem.widget().deleteLater() if self.stacked.isEmpty(): self.emit(SIGNAL("allFilesClosed()")) def _add_to_last_opened(self, path): if path not in settings.LAST_OPENED_FILES: settings.LAST_OPENED_FILES.append(path) if len(settings.LAST_OPENED_FILES) > settings.MAX_REMEMBER_TABS: self.__lastOpened = self.__lastOpened[1:] self.emit(SIGNAL("recentTabsModified()")) def _editor_with_focus(self): if self._main_container.current_widget is not self: self._main_container.current_widget = self editor = self.stacked.currentWidget() self._main_container.current_editor_changed( editor.neditable.file_path) self._load_symbols(editor.neditable) editor.neditable.update_checkers_display() def _ask_for_save(self, neditable): val = QMessageBox.No fileName = neditable.file_path val = QMessageBox.question( self, (self.tr('The file %s was not saved') % fileName), self.tr("Do you want to save before closing?"), QMessageBox.Yes | QMessageBox.No | QMessageBox.Cancel) if val == QMessageBox.No: neditable.nfile.close(force_close=True) elif val == QMessageBox.Yes: self._main_container.save_file(neditable.editor) neditable.nfile.close() def _file_has_been_modified(self, neditable): val = QMessageBox.No fileName = neditable.file_path val = QMessageBox.question(self, translations.TR_FILE_HAS_BEEN_MODIFIED, "%s%s" % (fileName, translations.TR_FILE_MODIFIED_OUTSIDE), QMessageBox.Yes | QMessageBox.No) if val == QMessageBox.Yes: neditable.reload_file() def _run_file(self, path): self._main_container.run_file(path) def _add_to_project(self, path): self._main_container._add_to_project(path) def set_current(self, neditable): if neditable: self.bar.set_current_file(neditable) def _set_current(self, neditable, index): if neditable: self.stacked.setCurrentIndex(index) editor = self.stacked.currentWidget() self._update_cursor_position(ignore_sender=True) editor.setFocus() self._main_container.current_editor_changed( neditable.file_path) self._load_symbols(neditable) neditable.update_checkers_display() def widget(self, index): return self.stacked.widget(index) def count(self): """Return the number of editors opened.""" return self.stacked.count() def _update_cursor_position(self, ignore_sender=False): obj = self.sender() editor = self.stacked.currentWidget() # Check if it's current to avoid signals from other splits. if ignore_sender or editor == obj: line = editor.textCursor().blockNumber() + 1 col = editor.textCursor().columnNumber() self.bar.update_line_col(line, col) def _set_current_symbol(self, line, ignore_sender=False): obj = self.sender() editor = self.stacked.currentWidget() # Check if it's current to avoid signals from other splits. if ignore_sender or editor == obj: index = bisect.bisect(self._symbols_index, line) if (index >= len(self._symbols_index) or self._symbols_index[index] > (line + 1)): index -= 1 self.bar.set_current_symbol(index) def _editor_modified(self, value): obj = self.sender() neditable = obj.neditable if value: text = "%s (*)" % neditable.display_name self.bar.update_item_text(neditable, text) else: self.bar.update_item_text(neditable, neditable.display_name) def _go_to_symbol(self, index): line = self._symbols_index[index] editor = self.stacked.currentWidget() editor.go_to_line(line) def _update_symbols(self, neditable): editor = self.stacked.currentWidget() # Check if it's current to avoid signals from other splits. if editor == neditable.editor: self._load_symbols(neditable) def _update_combo_info(self, neditable): self.bar.update_item_text(neditable, neditable.display_name) self._main_container.current_editor_changed(neditable.file_path) def _load_symbols(self, neditable): symbols_handler = handlers.get_symbols_handler('py') source = neditable.editor.toPlainText() source = source.encode(neditable.editor.encoding) symbols, symbols_simplified = symbols_handler.obtain_symbols( source, simple=True) self._symbols_index = sorted(symbols_simplified.keys()) symbols_simplified = sorted( list(symbols_simplified.items()), key=lambda x: x[0]) self.bar.add_symbols(symbols_simplified) line = neditable.editor.textCursor().blockNumber() self._set_current_symbol(line, True) tree_symbols = IDE.get_service('symbols_explorer') tree_symbols.update_symbols_tree(symbols, neditable.file_path) def _show_notification_icon(self, neditable): checkers = neditable.sorted_checkers icon = QIcon() for items in checkers: checker, color, _ = items if checker.checks: if isinstance(checker.checker_icon, int): icon = self.style().standardIcon(checker.checker_icon) elif isinstance(checker.checker_icon, str): icon = QIcon(checker.checker_icon) break self.bar.update_item_icon(neditable, icon) def show_menu_navigation(self): self.bar.code_navigator.show_menu_navigation() def closeEvent(self, event): self.emit(SIGNAL("aboutToCloseComboEditor()")) super(ComboEditor, self).closeEvent(event) def reject(self): if not self.__original: super(ComboEditor, self).reject()
class CodeCompletionWidget(QFrame): def __init__(self, editor): super(CodeCompletionWidget, self).__init__(None, Qt.FramelessWindowHint | Qt.ToolTip) self._editor = editor self.stack_layout = QStackedLayout(self) self.stack_layout.setContentsMargins(0, 0, 0, 0) self.stack_layout.setSpacing(0) self.completion_list = QListWidget() self.completion_list.setMinimumHeight(200) self.completion_list.setAlternatingRowColors(True) self._list_index = self.stack_layout.addWidget(self.completion_list) self._icons = { "a": resources.IMAGES["attribute"], "f": resources.IMAGES["function"], "c": resources.IMAGES["class"], } self.cc = code_completion.CodeCompletion() self._completion_results = [] self._prefix = u"" self.setVisible(False) self.source = "" self._key_operations = { Qt.Key_Up: self._select_previous_row, Qt.Key_Down: self._select_next_row, Qt.Key_PageUp: (lambda: self._select_previous_row(6)), Qt.Key_PageDown: (lambda: self._select_next_row(6)), Qt.Key_Right: lambda: None, Qt.Key_Left: lambda: None, Qt.Key_Enter: self.pre_key_insert_completion, Qt.Key_Return: self.pre_key_insert_completion, Qt.Key_Tab: self.pre_key_insert_completion, Qt.Key_Space: self.hide_completer, Qt.Key_Escape: self.hide_completer, Qt.Key_Backtab: self.hide_completer, Qt.NoModifier: self.hide_completer, Qt.ShiftModifier: self.hide_completer, } desktop = QApplication.instance().desktop() self._desktop_geometry = desktop.availableGeometry() self.connect(self._editor.document(), SIGNAL("blockCountChanged(int)"), self.update_metadata) def _select_next_row(self, move=1): new_row = self.completion_list.currentRow() + move if new_row < self.completion_list.count(): self.completion_list.setCurrentRow(new_row) else: self.completion_list.setCurrentRow(0) return True def _select_previous_row(self, move=1): new_row = self.completion_list.currentRow() - move if new_row >= 0: self.completion_list.setCurrentRow(new_row) else: self.completion_list.setCurrentRow(self.completion_list.count() - move) return True def update_metadata(self): source = self._editor.get_text() source = source.encode(self._editor.encoding) self.cc.analyze_file("", source) def insert_completion(self, insert): if insert != self._prefix: extra = len(self._prefix) - len(insert) self._editor.textCursor().insertText(insert[extra:]) self.hide_completer() def _get_geometry(self): cr = self._editor.cursorRect() point = self._editor.mapToGlobal(cr.topLeft()) cr.moveTopLeft(point) # Check new position according desktop geometry width = ( self.completion_list.sizeHintForColumn(0) + self.completion_list.verticalScrollBar().sizeHint().width() + 10 ) height = 200 orientation = (point.y() + height) < self._desktop_geometry.height() if orientation: cr.moveTop(cr.bottom()) cr.setWidth(width) cr.setHeight(height) if not orientation: cr.moveBottom(cr.top()) xpos = self._desktop_geometry.width() - (point.x() + width) if xpos < 0: cr.moveLeft(cr.left() + xpos) return cr def complete(self, results): self.add_list_items(results) self.completion_list.setCurrentRow(0) cr = self._get_geometry() self.setGeometry(cr) self.completion_list.updateGeometries() self.show() def add_list_items(self, proposals): self.completion_list.clear() for p in proposals: self.completion_list.addItem( QListWidgetItem(QIcon(self._icons.get(p[0], resources.IMAGES["attribute"])), p[1]) ) def set_completion_prefix(self, prefix): self._prefix = prefix proposals = [] proposals += [("c", item) for item in self.completion_results.get("classes", []) if item.startswith(prefix)] proposals += [("a", item) for item in self.completion_results.get("attributes", []) if item.startswith(prefix)] proposals += [("f", item) for item in self.completion_results.get("functions", []) if item.startswith(prefix)] if proposals: self.complete(proposals) else: self.hide_completer() def fill_completer(self): source = self._editor.get_text() source = source.encode(self._editor.encoding) offset = self._editor.textCursor().position() results = self.cc.get_completion(source, offset) self.completion_results = results prefix = self._editor._text_under_cursor() self.set_completion_prefix(prefix) def hide_completer(self): self._prefix = "" self.hide() def pre_key_insert_completion(self): insert = unicode(self.completion_list.currentItem().text()) self.insert_completion(insert) self.hide_completer() return True def process_pre_key_event(self, event): if not self.isVisible(): return False skip = self._key_operations.get(event.key(), lambda: False)() self._key_operations.get(event.modifiers(), lambda: False)() if skip is None: skip = False return skip def process_post_key_event(self, event): if not settings.CODE_COMPLETION or self._editor.lang != "python": return if self.isVisible(): source = self._editor.get_text() source = source.encode(self._editor.encoding) offset = self._editor.textCursor().position() prefix = self.cc.get_prefix(source, offset) self.set_completion_prefix(prefix) self.completion_list.setCurrentRow(0) if event.key() == Qt.Key_Period or (event.key() == Qt.Key_Space and event.modifiers() == Qt.ControlModifier): self.fill_completer()