def test_dock(self): reg = global_registry() reg = QtWidgetRegistry(reg, parent=self.app) toolbox = WidgetToolBox() toolbox.setObjectName("widgets-toolbox") toolbox.setModel(reg.model()) text = QTextEdit() splitter = QSplitter() splitter.setOrientation(Qt.Vertical) splitter.addWidget(toolbox) splitter.addWidget(text) dock = CollapsibleDockWidget() dock.setExpandedWidget(splitter) toolbar = QToolBar() toolbar.addAction("1") toolbar.setOrientation(Qt.Vertical) toolbar.setMovable(False) toolbar.setFloatable(False) dock.setCollapsedWidget(toolbar) dock.show() self.app.exec_()
def __init__(self, callback): super().__init__() self.callback = callback #Toolbar toolbar = QToolBar(self) self.button_test = toolbar.addAction("Test script") self.button_burn = toolbar.addAction("Write script to ROM") #self.button_reload = toolbar.addAction("Refresh") self.button_pokescriptdoc = toolbar.addAction("PokeScript doc") self.button_pokescriptdoc.setToolTip("Opens your webbrowser, pointing at a page where some elemnets of PokeScript are explained.") self.button_scriptdoc = toolbar.addAction("List of commands.") self.button_scriptdoc.setToolTip("Opens a list of available commands in your default browser.") toolbar.actionTriggered.connect(self.toolbarAction) #Code editor sourceeditor = LNTextEdit(self) font = QFont("Monospace") font.setStyleHint(QFont.TypeWriter) sourceeditor.setFont(font) sourceeditor.setLineWrapMode(0) sourceeditor.setHighlighterClass(PokeScriptHighlighter) #Wrap it up layout = QVBoxLayout(self) layout.addWidget(toolbar) layout.addWidget(sourceeditor) layout.setContentsMargins(0, 0, 0, 0) #Store elements that we need later self.sourceeditor = sourceeditor
def __init__(self, page, parent=None): super(HelpForm, self).__init__(parent) self.setAttribute(Qt.WA_DeleteOnClose) self.setAttribute(Qt.WA_GroupLeader) backAction = QAction(QIcon(":/back.png"), "&Back", self) backAction.setShortcut(QKeySequence.Back) homeAction = QAction(QIcon(":/home.png"), "&Home", self) homeAction.setShortcut("Home") self.pageLabel = QLabel() toolBar = QToolBar() toolBar.addAction(backAction) toolBar.addAction(homeAction) toolBar.addWidget(self.pageLabel) self.textBrowser = QTextBrowser() layout = QVBoxLayout() layout.addWidget(toolBar) layout.addWidget(self.textBrowser, 1) self.setLayout(layout) self.connect(backAction, SIGNAL("triggered()"), self.textBrowser, SLOT("backward()")) self.connect(homeAction, SIGNAL("triggered()"), self.textBrowser, SLOT("home()")) self.connect(self.textBrowser, SIGNAL("sourceChanged(QUrl)"), self.updatePageTitle) self.textBrowser.setSearchPaths([":/help"]) self.textBrowser.setSource(QUrl(page)) self.resize(400, 600) self.setWindowTitle("{0} Help".format(QApplication.applicationName()))
def __init__(self, callback): super().__init__() self.callback = callback #Toolbar toolbar = QToolBar(self) self.button_test = toolbar.addAction("Test script") self.button_burn = toolbar.addAction("Write script to ROM") #self.button_reload = toolbar.addAction("Refresh") self.button_pokescriptdoc = toolbar.addAction("PokeScript doc") self.button_pokescriptdoc.setToolTip( "Opens your webbrowser, pointing at a page where some elemnets of PokeScript are explained." ) self.button_scriptdoc = toolbar.addAction("List of commands.") self.button_scriptdoc.setToolTip( "Opens a list of available commands in your default browser.") toolbar.actionTriggered.connect(self.toolbarAction) #Code editor sourceeditor = LNTextEdit(self) font = QFont("Monospace") font.setStyleHint(QFont.TypeWriter) sourceeditor.setFont(font) sourceeditor.setLineWrapMode(0) sourceeditor.setHighlighterClass(PokeScriptHighlighter) #Wrap it up layout = QVBoxLayout(self) layout.addWidget(toolbar) layout.addWidget(sourceeditor) layout.setContentsMargins(0, 0, 0, 0) #Store elements that we need later self.sourceeditor = sourceeditor
def __init__(self, page, parent=None): super(HelpForm, self).__init__(parent) self.setAttribute(Qt.WA_DeleteOnClose) self.setAttribute(Qt.WA_GroupLeader) backAction = QAction(QIcon(":/back.png"), "&Back", self) backAction.setShortcut(QKeySequence.Back) homeAction = QAction(QIcon(":/home.png"), "&Home", self) homeAction.setShortcut("Home") self.pageLabel = QLabel() toolBar = QToolBar() toolBar.addAction(backAction) toolBar.addAction(homeAction) toolBar.addWidget(self.pageLabel) self.textBrowser = QTextBrowser() layout = QVBoxLayout() layout.addWidget(toolBar) layout.addWidget(self.textBrowser, 1) self.setLayout(layout) self.connect(backAction, SIGNAL("triggered()"), self.textBrowser, SLOT("backward()")) self.connect(homeAction, SIGNAL("triggered()"), self.textBrowser, SLOT("home()")) self.connect(self.textBrowser, SIGNAL("sourceChanged(QUrl)"), self.updatePageTitle) self.textBrowser.setSearchPaths([":/help"]) self.textBrowser.setSource(QUrl(page)) self.resize(400, 600) self.setWindowTitle("{0} Help".format( QApplication.applicationName()))
def __init__(self, config_file_path, help_tool): QWidget.__init__(self) layout = QVBoxLayout() toolbar = QToolBar("toolbar") save_action = toolbar.addAction(util.resourceIcon("ide/disk"), "Save") save_action.triggered.connect(self.save) save_as_action = toolbar.addAction(util.resourceIcon("ide/save_as"), "Save As") save_as_action.triggered.connect(self.saveAs) # reload_icon = toolbar.style().standardIcon(QStyle.SP_BrowserReload) # reload_action = toolbar.addAction(reload_icon, "Reload") # reload_action.triggered.connect(self.reload) toolbar.addSeparator() toolbar.addAction(help_tool.getAction()) stretchy_separator = QWidget() stretchy_separator.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding) toolbar.addWidget(stretchy_separator) search = SearchBox() search.setMaximumWidth(200) search.setContentsMargins(5, 2, 5, 2) toolbar.addWidget(search) layout.addWidget(toolbar) self.ide_panel = IdePanel() layout.addWidget(self.ide_panel, 1) self.config_file_path = config_file_path with open(config_file_path) as f: config_file_text = f.read() self.highlighter = KeywordHighlighter(self.ide_panel.document()) search.filterChanged.connect(self.highlighter.setSearchString) self.parseDefines(config_file_text) self.ide_panel.document().setPlainText(config_file_text) cursor = self.ide_panel.textCursor() cursor.setPosition(0) self.ide_panel.setTextCursor(cursor) self.ide_panel.setFocus() self.setLayout(layout)
def getSchedulerToolBar(self): bar = QToolBar("Run", self) self.resetAction = bar.addAction( QIcon( os.path.join( config.MOOSE_ICON_DIR, 'reset.png' ) ) , 'Reset' , self.resetSimulation ) self.resetAction.setToolTip('Reset simulation.') self.runAction = bar.addAction( QIcon( os.path.join( config.MOOSE_ICON_DIR, 'run.png') ) , 'Run' , self.runSimulation ) self.runAction.setToolTip('Run simulation.') self.stopAction = bar.addAction( QIcon( os.path.join( config.MOOSE_ICON_DIR, 'stop.png') ) , 'Stop' , self.runner.togglePauseSimulation ) self.stopAction.setToolTip('Stop simulation.') bar.addSeparator() runtimeLabel = QLabel('Run for') self.simulationRuntime = QLineEdit() self.simulationRuntime.setValidator(QDoubleValidator()) self.simulationRuntime.setFixedWidth(75) bar.addWidget(runtimeLabel) bar.addWidget(self.simulationRuntime) bar.addWidget(QLabel(' (s)')) bar.addSeparator() #: current time self.currentSimulationRuntime = QLineEdit() # 6 digits self.currentSimulationRuntime.setToolTip('Current simulation runtime.') self.currentSimulationRuntime.setFixedWidth(75) self.currentSimulationRuntime.setValidator(QDoubleValidator()) self.currentSimulationRuntime.setText("0.0") self.currentSimulationRuntime.setReadOnly(True) # self.runner.currentTime.connect(self.currentTimeWidget.display) bar.addWidget(QLabel("Current Time : ")) bar.addWidget(self.currentSimulationRuntime) bar.addWidget(QLabel(" (s)")) bar.addSeparator() self.preferencesButton = QToolButton() self.preferencesButton.setText("Preferences") self.preferencesButton.clicked.connect(self.preferencesToggler) bar.addWidget(self.preferencesButton) return bar
def __init__(self, config_file_path, help_tool): QWidget.__init__(self) layout = QVBoxLayout() toolbar = QToolBar("toolbar") save_action = toolbar.addAction(resourceIcon("ide/disk"), "Save") save_action.triggered.connect(self.save) save_as_action = toolbar.addAction(resourceIcon("ide/save_as"), "Save As") save_as_action.triggered.connect(self.saveAs) # reload_icon = toolbar.style().standardIcon(QStyle.SP_BrowserReload) # reload_action = toolbar.addAction(reload_icon, "Reload") # reload_action.triggered.connect(self.reload) toolbar.addSeparator() toolbar.addAction(help_tool.getAction()) stretchy_separator = QWidget() stretchy_separator.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding) toolbar.addWidget(stretchy_separator) search = SearchBox() search.setMaximumWidth(200) search.setContentsMargins(5, 2, 5, 2) toolbar.addWidget(search) layout.addWidget(toolbar) self.ide_panel = IdePanel() layout.addWidget(self.ide_panel, 1) self.config_file_path = config_file_path with open(config_file_path) as f: config_file_text = f.read() self.highlighter = KeywordHighlighter(self.ide_panel.document()) search.filterChanged.connect(self.highlighter.setSearchString) self.parseDefines(config_file_text) self.ide_panel.document().setPlainText(config_file_text) cursor = self.ide_panel.textCursor() cursor.setPosition(0) self.ide_panel.setTextCursor(cursor) self.ide_panel.setFocus() self.setLayout(layout)
def __init__(self, parent=None): QWidget.__init__(self, parent) self.debug = False self.connections = {} self.setWindowTitle("Servers") #s#elf.setWindowFlags(self.windowFlags() | QtCore.Qt.WindowStaysOnTopHint) self.mainLayout = QVBoxLayout() self.mainLayout.setContentsMargins(0, 0, 0, 0) self.mainLayout.setSpacing(0) self.setLayout(self.mainLayout) #============================================= ## Top Toolbar topBar = QToolBar() topBar.setToolButtonStyle(Qt.ToolButtonTextBesideIcon) self.mainLayout.addWidget(topBar) ## Add the action buttons topBar.addAction(Ico.icon(Ico.ServerAdd), "Add", self.on_server_add) self.actionServerEdit = topBar.addAction(Ico.icon(Ico.ServerEdit), "Edit", self.on_server_edit) self.actionServerDelete = topBar.addAction(Ico.icon(Ico.ServerDelete), "Delete", self.on_server_delete) #============================================= ## Tree self.tree = QTreeWidget() self.mainLayout.addWidget(self.tree) self.tree.setUniformRowHeights(True) self.tree.setRootIsDecorated(True) self.tree.setHeaderLabels(["Server", "Butt"]) # set header, but hide anyway self.tree.header().hide() self.tree.header().setResizeMode(C.node, QHeaderView.Stretch) self.tree.setColumnWidth(C.butt, 20) self.connect(self.tree, SIGNAL('itemSelectionChanged()'), self.on_tree_selection_changed) self.connect(self.tree, SIGNAL('itemDoubleClicked (QTreeWidgetItem *,int)'), self.on_tree_double_clicked) self.buttGroup = QButtonGroup(self) self.connect(self.buttGroup, SIGNAL("buttonClicked(QAbstractButton*)"), self.on_open_server) self.on_tree_selection_changed() self.load_servers()
def __init__(self, parent=None): super(FeatureFormWidget, self).__init__(parent) self.setupUi(self) toolbar = QToolBar() size = QSize(48, 48) toolbar.setIconSize(size) style = Qt.ToolButtonTextUnderIcon toolbar.setToolButtonStyle(style) self.actionDelete = toolbar.addAction(QIcon(":/icons/delete"), "Delete") self.actionDelete.triggered.connect(self.delete_feature) label = '<b style="color:red">*</b> Required fields' self.missingfieldsLabel = QLabel(label) self.missingfieldsLabel.hide() self.missingfieldaction = toolbar.addWidget(self.missingfieldsLabel) titlespacer = QWidget() titlespacer.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding) toolbar.addWidget(titlespacer) self.titlellabel = QLabel(label) self.titlellabel.setProperty("headerlabel", True) self.titlelabelaction = toolbar.addWidget(self.titlellabel) spacer = QWidget() spacer2 = QWidget() spacer2.setMinimumWidth(40) spacer.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding) spacer2.setSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed) toolbar.addWidget(spacer) self.actionCancel = toolbar.addAction(QIcon(":/icons/cancel"), "Cancel") toolbar.addWidget(spacer2) self.actionSave = toolbar.addAction(QIcon(":/icons/save"), "Save") self.actionSave.triggered.connect(self.save_feature) self.layout().setContentsMargins(0, 3, 0, 3) self.layout().insertWidget(0, toolbar) self.actiontoolbar = QToolBar() self.actiontoolbar.setToolButtonStyle(Qt.ToolButtonTextUnderIcon) spacer = QWidget() spacer.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding) self.actiontoolbar.addWidget(spacer) self.layout().insertWidget(1, self.actiontoolbar) self.flickwidget = FlickCharm() self.flickwidget.activateOn(self.scrollArea) self.featureform = None self.values = {} self.config = {} self.feature = None
def _create_toolbar(self, color_maps): toolbar = QToolBar() toolbar.setFloatable(False) toolbar.setMovable(False) self._layout_combo = LayoutCombo() self._layout_combo_action = QWidgetAction(self._layout_combo) self._layout_combo_action.setDefaultWidget(self._layout_combo) toolbar.addAction(self._layout_combo_action) self._layout_combo.layout_changed.connect( self._slice_view_widget.set_plot_layout) # self._colormap_combo = ColormapCombo(['seismic', 'spectral', 'RdGy', 'hot', 'jet', 'gray']) self._colormap_combo = ColormapCombo(color_maps) self._colormap_combo.currentIndexChanged[int].connect( self._colormap_changed) toolbar.addWidget(self._colormap_combo) self._save_button = QToolButton() self._save_button.setToolTip("Save as image") self._save_button.setIcon(resource_icon("table_export.png")) self._save_button.clicked.connect(self._save_figure) toolbar.addWidget(self._save_button) self._settings_button = QToolButton() self._settings_button.setToolTip("Toggle settings visibility") self._settings_button.setIcon(resource_icon("cog.png")) self._settings_button.setCheckable(True) self._settings_button.toggled.connect(self._show_settings) toolbar.addWidget(self._settings_button) self._help_button = QToolButton() self._help_button.setToolTip("View help") self._help_button.setIcon(resource_icon("help.png")) self._help_button.setCheckable(True) self._help_button.toggled.connect(self._show_help) toolbar.addWidget(self._help_button) def toggle_on_close(event): self._settings_button.setChecked(False) event.accept() def toggle_on_close_help(event): self._help_button.setChecked(False) event.accept() self._settings_window.closeEvent = toggle_on_close self._help_window.closeEvent = toggle_on_close_help self._colormap_combo.setCurrentIndex(45) self.set_default_layout() return toolbar
def __init__(self, parent=None): QWidget.__init__(self, parent) self.debug = False self.connections = {} self.setWindowTitle("Servers") #s#elf.setWindowFlags(self.windowFlags() | QtCore.Qt.WindowStaysOnTopHint) self.mainLayout = QVBoxLayout() self.mainLayout.setContentsMargins(0, 0, 0, 0) self.mainLayout.setSpacing(0) self.setLayout(self.mainLayout) #============================================= ## Top Toolbar topBar = QToolBar() topBar.setToolButtonStyle(Qt.ToolButtonTextBesideIcon) self.mainLayout.addWidget(topBar) ## Add the action buttons topBar.addAction(Ico.icon(Ico.ServerAdd), "Add", self.on_server_add) self.actionServerEdit = topBar.addAction(Ico.icon(Ico.ServerEdit), "Edit", self.on_server_edit) self.actionServerDelete = topBar.addAction(Ico.icon(Ico.ServerDelete), "Delete", self.on_server_delete) #============================================= ## Tree self.tree = QTreeWidget() self.mainLayout.addWidget(self.tree) self.tree.setUniformRowHeights(True) self.tree.setRootIsDecorated(True) self.tree.setHeaderLabels(["Server", "Butt"]) # set header, but hide anyway self.tree.header().hide() self.tree.header().setResizeMode(C.node, QHeaderView.Stretch) self.tree.setColumnWidth(C.butt, 20) self.connect( self.tree, SIGNAL( 'itemSelectionChanged()' ), self.on_tree_selection_changed ) self.connect( self.tree, SIGNAL( 'itemDoubleClicked (QTreeWidgetItem *,int)' ), self.on_tree_double_clicked ) self.buttGroup = QButtonGroup(self) self.connect(self.buttGroup, SIGNAL("buttonClicked(QAbstractButton*)"), self.on_open_server) self.on_tree_selection_changed() self.load_servers()
def load_ui(self): container = QVBoxLayout(self) box = QHBoxLayout() box.setContentsMargins(0, 0, 0, 0) box.setSpacing(0) toolbar = QToolBar() toolbar.setToolButtonStyle(3) toolbar.setOrientation(Qt.Vertical) toolbar.setIconSize(QSize(30, 30)) toolbar.setObjectName("preferencias") environment_section = toolbar.addAction( QIcon(":image/general-pref"), "Entorno") editor_section = toolbar.addAction( QIcon(":image/editor-pref"), "Editor") compiler_section = toolbar.addAction( QIcon(":image/compiler-pref"), "Compilador") self.connect(environment_section, SIGNAL("triggered()"), lambda: self.change_widget(0)) self.connect(editor_section, SIGNAL("triggered()"), lambda: self.change_widget(1)) self.connect(compiler_section, SIGNAL("triggered()"), lambda: self.change_widget(2)) # Set size for action in toolbar.actions(): widget = toolbar.widgetForAction(action) widget.setFixedSize(80, 50) box.addWidget(toolbar) self.stack = QStackedWidget() box.addWidget(self.stack) # Load sections and subsections for section in self.__sections: for name, obj in list(section.get_tabs().items()): section.install_tab(obj, name) self.stack.addWidget(section) box_buttons = QHBoxLayout() box_buttons.setMargin(10) box_buttons.setSpacing(10) box_buttons.addStretch(1) self.btn_cancel = QPushButton(self.tr("Cancelar")) self.btn_guardar = QPushButton(self.tr("Guardar")) box_buttons.addWidget(self.btn_cancel) box_buttons.addWidget(self.btn_guardar) container.addLayout(box) container.addLayout(box_buttons)
def load_ui(self): container = QVBoxLayout(self) box = QHBoxLayout() box.setContentsMargins(0, 0, 0, 0) box.setSpacing(0) toolbar = QToolBar() toolbar.setToolButtonStyle(3) toolbar.setOrientation(Qt.Vertical) toolbar.setIconSize(QSize(30, 30)) toolbar.setObjectName("preferencias") environment_section = toolbar.addAction(QIcon(":image/general-pref"), "Entorno") editor_section = toolbar.addAction(QIcon(":image/editor-pref"), "Editor") compiler_section = toolbar.addAction(QIcon(":image/compiler-pref"), "Compilador") self.connect(environment_section, SIGNAL("triggered()"), lambda: self.change_widget(0)) self.connect(editor_section, SIGNAL("triggered()"), lambda: self.change_widget(1)) self.connect(compiler_section, SIGNAL("triggered()"), lambda: self.change_widget(2)) # Set size for action in toolbar.actions(): widget = toolbar.widgetForAction(action) widget.setFixedSize(80, 50) box.addWidget(toolbar) self.stack = QStackedWidget() box.addWidget(self.stack) # Load sections and subsections for section in self.__sections: for name, obj in list(section.get_tabs().items()): section.install_tab(obj, name) self.stack.addWidget(section) box_buttons = QHBoxLayout() box_buttons.setMargin(10) box_buttons.setSpacing(10) box_buttons.addStretch(1) self.btn_cancel = QPushButton(self.tr("Cancelar")) self.btn_guardar = QPushButton(self.tr("Guardar")) box_buttons.addWidget(self.btn_cancel) box_buttons.addWidget(self.btn_guardar) container.addLayout(box) container.addLayout(box_buttons)
def __init__(self, iface): locale = QSettings().value('locale/userLocale')[0:2] locale_path = os.path.join(os.path.dirname(__file__), 'i18n', 'annotationManager_{}.qm'.format(locale)) self.translator = None if os.path.exists(locale_path): self.translator = QTranslator() self.translator.load(locale_path) QCoreApplication.installTranslator(self.translator) self.iface = iface self.iface.projectRead.connect(self.projectOpen) self.dock = QDockWidget(self.tr('Annotations manager')) self.manager = QWidget() toolbar = QToolBar() self.annotationList = QListWidget() self.annotationList.itemClicked.connect(self.selectAnnotation) self.annotationList.itemChanged.connect(self.checkItem) action_refresh = QAction( QIcon(':/plugins/annotationManager/resources/mActionDraw.png'), self.tr('Refresh the annotations list'), self.manager) action_refresh.triggered.connect(self.refreshAnnotations) action_remove = QAction( QIcon( ':/plugins/annotationManager/resources/mActionRemoveAnnotation.png' ), self.tr('Remove the selected annotation'), self.manager) action_remove.triggered.connect(self.removeAnnotation) toolbar.addAction(action_refresh) toolbar.addAction(action_remove) toolbar.setIconSize(QSize(16, 16)) p1_vertical = QVBoxLayout() p1_vertical.setContentsMargins(0, 0, 0, 0) p1_vertical.addWidget(toolbar) p1_vertical.addWidget(self.annotationList) self.manager.setLayout(p1_vertical) self.dock.setWidget(self.manager) self.dock.setAllowedAreas(Qt.LeftDockWidgetArea | Qt.RightDockWidgetArea) self.iface.addDockWidget(Qt.LeftDockWidgetArea, self.dock) self.rb = QgsRubberBand(self.iface.mapCanvas(), QGis.Polygon) self.annotations = [] self.annotationsName = []
class HtmlViewerWidget(QWidget): def __init__(self, parent): super(HtmlViewerWidget, self).__init__(parent) self.setLayout(QGridLayout()) self.layout().setContentsMargins(0, 0, 0, 0) self.view = QWebView() self.view.page().setLinkDelegationPolicy(QWebPage.DelegateAllLinks) self.frame = QFrame() self.frame.setLayout(QGridLayout()) self.frame.layout().setContentsMargins(0, 0, 0, 0) self.toolbar = QToolBar() self.spacer = QWidget() self.spacer.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding) self.copyAction = self.toolbar.addAction(QIcon(":/icons/clipboard"), "Copy Text") self.label = QLabel() self.closeAction = self.toolbar.addAction(QIcon(":/icons/cancel"), "Close") self.spaceraction = self.toolbar.insertWidget(self.closeAction, self.spacer) self.labelaction = self.toolbar.insertWidget(self.spaceraction, self.label) self.closeAction.triggered.connect(self.close) self.copyAction.triggered.connect(self.copy_text) self.layout().addWidget(self.frame) self.frame.layout().addWidget(self.toolbar) self.frame.layout().addWidget(self.view) self.effect = QGraphicsOpacityEffect() self.label.setGraphicsEffect(self.effect) self.anim = QPropertyAnimation(self.effect, "opacity") self.anim.setDuration(2000) self.anim.setStartValue(1.0) self.anim.setEndValue(0.0) self.anim.setEasingCurve(QEasingCurve.OutQuad) def copy_text(self): self.label.setText("Copied to clipboard") text = self.view.page().mainFrame().toPlainText() QApplication.clipboard().setText(text) self.anim.stop() self.anim.start() def showHTML(self, template, level, **data): html = templates.render_tample(template, **data) self.view.setHtml(html, templates.baseurl)
class HelpForm(QDialog): def __init__(self, page, parent=None): super(HelpForm, self).__init__(parent) self.setAttribute(Qt.WA_DeleteOnClose) self.setAttribute(Qt.WA_GroupLeader) self.create_widgets() self.layout_widgets() self.create_connections() self.textBrowser.setSearchPaths([":/"]) self.textBrowser.setSource(QUrl(page)) self.resize(400, 600) self.setWindowTitle(self.tr("%1 Help").arg( QApplication.applicationName())) def create_widgets(self): self.backAction = QAction(QIcon(":/back.png"), self.tr("&Back"), self) self.backAction.setShortcut(QKeySequence.Back) self.homeAction = QAction(QIcon(":/home.png"), self.tr("&Home"), self) self.homeAction.setShortcut(self.tr("Home")) self.pageLabel = QLabel() self.toolBar = QToolBar() self.toolBar.addAction(self.backAction) self.toolBar.addAction(self.homeAction) self.toolBar.addWidget(self.pageLabel) self.textBrowser = QTextBrowser() def layout_widgets(self): layout = QVBoxLayout() layout.addWidget(self.toolBar) layout.addWidget(self.textBrowser, 1) self.setLayout(layout) def create_connections(self): self.backAction.triggered.connect(self.textBrowser.backward) self.homeAction.triggered.connect(self.textBrowser.home) self.textBrowser.sourceChanged.connect(self.updatePageTitle) def updatePageTitle(self): self.pageLabel.setText(self.textBrowser.documentTitle())
def __init__(self, config_file_path): QWidget.__init__(self) layout = QVBoxLayout() toolbar = QToolBar("toolbar") # start_icon = toolbar.style().standardIcon(QStyle.SP_MediaPlay) # start_action = toolbar.addAction(start_icon, "Run simulations") # start_action.triggered.connect(self.start) # # toolbar.addSeparator() save_icon = toolbar.style().standardIcon(QStyle.SP_DialogSaveButton) save_action = toolbar.addAction(save_icon, "Save") save_action.triggered.connect(self.save) # reload_icon = toolbar.style().standardIcon(QStyle.SP_BrowserReload) # reload_action = toolbar.addAction(reload_icon, "Reload") # reload_action.triggered.connect(self.reload) toolbar.addSeparator() stretchy_separator = QWidget() stretchy_separator.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding) toolbar.addWidget(stretchy_separator) search = SearchBox() search.setMaximumWidth(200) search.setContentsMargins(5, 2, 5, 2) toolbar.addWidget(search) layout.addWidget(toolbar) self.ide_panel = IdePanel() layout.addWidget(self.ide_panel, 1) self.config_file_path = config_file_path with open(config_file_path) as f: config_file_text = f.read() self.highlighter = KeywordHighlighter(self.ide_panel.document()) search.filterChanged.connect(self.highlighter.setSearchString) self.ide_panel.document().setPlainText(config_file_text) cursor = self.ide_panel.textCursor() cursor.setPosition(0) self.ide_panel.setTextCursor(cursor) self.ide_panel.setFocus() self.setLayout(layout)
def __init__(self, parent=None): super(FeatureFormWidget, self).__init__(parent) self.setupUi(self) toolbar = QToolBar() size = QSize(48, 48) toolbar.setIconSize(size) style = Qt.ToolButtonTextUnderIcon toolbar.setToolButtonStyle(style) self.actionDelete = toolbar.addAction(QIcon(":/icons/delete"), "Delete") self.actionDelete.triggered.connect(self.delete_feature) label = 'Required fields marked in <b style="background-color:rgba(255, 221, 48,150)">yellow</b>' self.missingfieldsLabel = QLabel(label) self.missingfieldsLabel.hide() self.missingfieldaction = toolbar.addWidget(self.missingfieldsLabel) titlespacer = QWidget() titlespacer.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding) toolbar.addWidget(titlespacer) self.titlellabel = QLabel(label) self.titlellabel.setProperty("headerlabel", True) self.titlelabelaction = toolbar.addWidget(self.titlellabel) spacer = QWidget() spacer2 = QWidget() spacer2.setMinimumWidth(20) spacer.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding) spacer2.setSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed) toolbar.addWidget(spacer) self.actionCancel = toolbar.addAction(QIcon(":/icons/cancel"), "Cancel") toolbar.addWidget(spacer2) self.actionSave = toolbar.addAction(QIcon(":/icons/save"), "Save") self.actionSave.triggered.connect(self.save_feature) self.layout().insertWidget(0, toolbar) self.flickwidget = FlickCharm() self.flickwidget.activateOn(self.scrollArea) self.featureform = None self.values = {} self.config = {} self.feature = None
class HtmlViewerWidget(QWidget): def __init__(self, parent): super(HtmlViewerWidget, self).__init__(parent) self.setLayout(QGridLayout()) self.layout().setContentsMargins(0, 0, 0, 0) self.view = QWebView() self.view.page().setLinkDelegationPolicy(QWebPage.DelegateAllLinks) self.frame = QFrame() self.frame.setLayout(QGridLayout()) self.frame.layout().setContentsMargins(0, 0, 0, 0) self.toolbar = QToolBar() self.spacer = QWidget() self.spacer.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding) self.copyAction = self.toolbar.addAction(QIcon(":/icons/clipboard"), "Copy Text") self.label = QLabel() self.closeAction = self.toolbar.addAction(QIcon(":/icons/cancel"), "Close") self.spaceraction = self.toolbar.insertWidget(self.closeAction, self.spacer) self.labelaction = self.toolbar.insertWidget(self.spaceraction, self.label) self.closeAction.triggered.connect(self.close) self.copyAction.triggered.connect(self.copy_text) self.layout().addWidget(self.frame) self.frame.layout().addWidget(self.toolbar) self.frame.layout().addWidget(self.view) self.effect = QGraphicsOpacityEffect() self.label.setGraphicsEffect(self.effect) self.anim = QPropertyAnimation(self.effect, "opacity") self.anim.setDuration(2000) self.anim.setStartValue(1.0) self.anim.setEndValue(0.0) self.anim.setEasingCurve(QEasingCurve.OutQuad ) def copy_text(self): self.label.setText("Copied to clipboard") text = self.view.page().mainFrame().toPlainText() QApplication.clipboard().setText(text) self.anim.stop() self.anim.start() def showHTML(self, template, level, **data): html = templates.render_tample(template, **data) self.view.setHtml(html, templates.baseurl)
class HelpForm(QDialog): def __init__(self, page, parent=None): super(HelpForm, self).__init__(parent) self.setAttribute(Qt.WA_DeleteOnClose) self.setAttribute(Qt.WA_GroupLeader) self.create_widgets() self.layout_widgets() self.create_connections() self.textBrowser.setSearchPaths([":/help"]) self.textBrowser.setSource(QUrl(page)) self.resize(450, 400) self.setWindowTitle("{0} Help".format( QApplication.applicationName())) def create_widgets(self): self.backAction = QAction(QIcon(":/back.png"), "&Atras", self) self.backAction.setShortcut(QKeySequence.Back) self.homeAction = QAction(QIcon(":/home.png"), "&Inicio", self) self.homeAction.setShortcut("Inicio") self.pageLabel = QLabel() self.toolBar = QToolBar() self.toolBar.addAction(self.backAction) self.toolBar.addAction(self.homeAction) self.toolBar.addWidget(self.pageLabel) self.textBrowser = QTextBrowser() def layout_widgets(self): layout = QVBoxLayout() layout.addWidget(self.toolBar) layout.addWidget(self.textBrowser, 1) self.setLayout(layout) def create_connections(self): self.backAction.triggered.connect(self.textBrowser.backward) self.homeAction.triggered.connect(self.textBrowser.home) self.textBrowser.sourceChanged.connect(self.updatePageTitle) def updatePageTitle(self): self.pageLabel.setText(self.textBrowser.documentTitle())
def __createLayout( self ): " Creates the toolbar and layout " # Buttons printButton = QAction( PixmapCache().getIcon( 'printer.png' ), 'Print', self ) #printButton.setShortcut( 'Ctrl+' ) printButton.triggered.connect( self.__onPrint ) printPreviewButton = QAction( \ PixmapCache().getIcon( 'printpreview.png' ), 'Print preview', self ) #printPreviewButton.setShortcut( 'Ctrl+' ) printPreviewButton.triggered.connect( self.__onPrintPreview ) fixedSpacer = QWidget() fixedSpacer.setFixedHeight( 16 ) zoomInButton = QAction( PixmapCache().getIcon( 'zoomin.png' ), 'Zoom in (Ctrl+=)', self ) zoomInButton.setShortcut( 'Ctrl+=' ) zoomInButton.triggered.connect( self.onZoomIn ) zoomOutButton = QAction( PixmapCache().getIcon( 'zoomout.png' ), 'Zoom out (Ctrl+-)', self ) zoomOutButton.setShortcut( 'Ctrl+-' ) zoomOutButton.triggered.connect( self.onZoomOut ) zoomResetButton = QAction( PixmapCache().getIcon( 'zoomreset.png' ), 'Zoom reset (Ctrl+0)', self ) zoomResetButton.setShortcut( 'Ctrl+0' ) zoomResetButton.triggered.connect( self.onZoomReset ) # Toolbar toolbar = QToolBar( self ) toolbar.setOrientation( Qt.Vertical ) toolbar.setMovable( False ) toolbar.setAllowedAreas( Qt.RightToolBarArea ) toolbar.setIconSize( QSize( 16, 16 ) ) toolbar.setFixedWidth( 28 ) toolbar.setContentsMargins( 0, 0, 0, 0 ) #toolbar.addAction( printPreviewButton ) #toolbar.addAction( printButton ) #toolbar.addWidget( fixedSpacer ) toolbar.addAction( zoomInButton ) toolbar.addAction( zoomOutButton ) toolbar.addAction( zoomResetButton ) hLayout = QHBoxLayout() hLayout.setContentsMargins( 0, 0, 0, 0 ) hLayout.setSpacing( 0 ) hLayout.addWidget( self.__viewer ) hLayout.addWidget( toolbar ) self.setLayout( hLayout ) return
def __createLayout(self): " Creates the toolbar and layout " # Buttons printButton = QAction(PixmapCache().getIcon('printer.png'), 'Print', self) #printButton.setShortcut( 'Ctrl+' ) printButton.triggered.connect(self.__onPrint) printPreviewButton = QAction( \ PixmapCache().getIcon( 'printpreview.png' ), 'Print preview', self ) #printPreviewButton.setShortcut( 'Ctrl+' ) printPreviewButton.triggered.connect(self.__onPrintPreview) fixedSpacer = QWidget() fixedSpacer.setFixedHeight(16) zoomInButton = QAction(PixmapCache().getIcon('zoomin.png'), 'Zoom in (Ctrl+=)', self) zoomInButton.setShortcut('Ctrl+=') zoomInButton.triggered.connect(self.onZoomIn) zoomOutButton = QAction(PixmapCache().getIcon('zoomout.png'), 'Zoom out (Ctrl+-)', self) zoomOutButton.setShortcut('Ctrl+-') zoomOutButton.triggered.connect(self.onZoomOut) zoomResetButton = QAction(PixmapCache().getIcon('zoomreset.png'), 'Zoom reset (Ctrl+0)', self) zoomResetButton.setShortcut('Ctrl+0') zoomResetButton.triggered.connect(self.onZoomReset) # Toolbar toolbar = QToolBar(self) toolbar.setOrientation(Qt.Vertical) toolbar.setMovable(False) toolbar.setAllowedAreas(Qt.RightToolBarArea) toolbar.setIconSize(QSize(16, 16)) toolbar.setFixedWidth(28) toolbar.setContentsMargins(0, 0, 0, 0) #toolbar.addAction( printPreviewButton ) #toolbar.addAction( printButton ) #toolbar.addWidget( fixedSpacer ) toolbar.addAction(zoomInButton) toolbar.addAction(zoomOutButton) toolbar.addAction(zoomResetButton) hLayout = QHBoxLayout() hLayout.setContentsMargins(0, 0, 0, 0) hLayout.setSpacing(0) hLayout.addWidget(self.__viewer) hLayout.addWidget(toolbar) self.setLayout(hLayout) return
def __setup_menu(self): fileMenu = QMenu("Db", self) profileMenu = QMenu('Profiles', self) self.menuBar().addMenu(fileMenu) self.menuBar().addMenu(profileMenu) self.__new_action = QAction(QIcon(ICON_IDR + 'add_database.png'), "&New", fileMenu) fileMenu.addAction(self.__new_action) self.__profile_action = QAction(QIcon(ICON_IDR + 'profiles.png'), "&Open profiles", profileMenu) profileMenu.addAction(self.__profile_action) tool_bar = QToolBar() tool_bar.setMovable(False) tool_bar.setToolButtonStyle(Qt.ToolButtonIconOnly) tool_bar.addAction(self.__new_action) tool_bar.addAction(self.__profile_action) tool_bar.setIconSize(QSize(30, 30)) #tool_bar.setStyleSheet("QToolButton { padding-left: 5px; padding-right: 5px; } QToolBar{padding-left: 5px; padding-right: 5px}") self.addToolBar(tool_bar)
def __init__(self, parent=None): super(SR785_MainWindow, self).__init__(parent) centralWidget = SR785_Widget() self.setCentralWidget(centralWidget) visaResource = 'GPIB0::10' sr785 = SR785(visaResource) sr785.configureScreenDump() centralWidget.associateInstrument(sr785) self.setWindowTitle('SR785 Front Panel Emulation: %s' % sr785.visaId()) self.progressBar = QProgressBar() statusBar = self.statusBar() statusBar.addWidget(self.progressBar) toolBar = QToolBar('Screen') toolBar.addActions(centralWidget.screenActions) self.addToolBar(toolBar) thread = centralWidget.workerThread thread.gifDownloadStarted.connect(self.gifDownloadStarted) thread.gifReceived.connect(self.gifReceived) thread.keyPressSimulated.connect(self.keyPressSimulated) thread.knobRotated.connect(self.knobRotated) dockWidget = QDockWidget('History') self.historyTe = QTextEdit() dockWidget.setWidget(self.historyTe) self.addDockWidget(Qt.TopDockWidgetArea, dockWidget) toolBar = self.addToolBar('File') action = QAction('Save screen', self) action.triggered.connect(self.saveScreen) toolBar.addAction(action) action = QAction('Print', self) action.triggered.connect(self.printScreen) toolBar.addAction(action)
def __createLayout( self ): " Creates the toolbar and layout " # Buttons printButton = QAction( PixmapCache().getIcon( 'printer.png' ), 'Print', self ) printButton.triggered.connect( self.__onPrint ) printButton.setEnabled( False ) printButton.setVisible( False ) printPreviewButton = QAction( PixmapCache().getIcon( 'printpreview.png' ), 'Print preview', self ) printPreviewButton.triggered.connect( self.__onPrintPreview ) printPreviewButton.setEnabled( False ) printPreviewButton.setVisible( False ) spacer = QWidget() spacer.setSizePolicy( QSizePolicy.Expanding, QSizePolicy.Expanding ) self.lineCounterButton = QAction( PixmapCache().getIcon( 'linecounter.png' ), 'Line counter', self ) self.lineCounterButton.triggered.connect( self.onLineCounter ) # The toolbar toolbar = QToolBar( self ) toolbar.setOrientation( Qt.Vertical ) toolbar.setMovable( False ) toolbar.setAllowedAreas( Qt.RightToolBarArea ) toolbar.setIconSize( QSize( 16, 16 ) ) toolbar.setFixedWidth( 28 ) toolbar.setContentsMargins( 0, 0, 0, 0 ) toolbar.addAction( printPreviewButton ) toolbar.addAction( printButton ) toolbar.addWidget( spacer ) toolbar.addAction( self.lineCounterButton ) self.__importsBar = ImportListWidget( self.__viewer ) self.__importsBar.hide() hLayout = QHBoxLayout() hLayout.setContentsMargins( 0, 0, 0, 0 ) hLayout.setSpacing( 0 ) hLayout.addWidget( self.__viewer ) hLayout.addWidget( toolbar ) self.setLayout( hLayout ) return
def __init__(self, parent, *args): QToolBar.__init__(self, parent, *args) self.setSizePolicy( QSizePolicy( QSizePolicy.Expanding, QSizePolicy.Maximum ) ) self._dock = parent self.aClose = QToolBar.addAction(self, self.style().standardIcon( QStyle.SP_TitleBarCloseButton ), "") self.setMovable( False ) self.setFloatable( False ) self.aClose.triggered.connect(self._dock.close) textHeight = QFontMetrics(self.font()).height() self.setIconSize(QSize(textHeight, textHeight)) # a fake spacer widget self._spacer = QWidget( self ) self._spacer.setSizePolicy( QSizePolicy( QSizePolicy.Expanding, QSizePolicy.MinimumExpanding ) ) self.addWidget( self._spacer )
def __init__(self, parent): QToolBar.__init__(self, parent) assert parent self.dock = parent # a fake spacer widget w = QWidget(self) l = QHBoxLayout(w) l.setMargin(0) l.setSpacing(0) l.addStretch() frame = QFrame() layout = QBoxLayout(QBoxLayout.LeftToRight, frame) layout.setContentsMargins(4, 4, 0, 0) layout.setSpacing(2) self.aDockFrame = self.addWidget(frame) self.__icon = QLabel() layout.addWidget(self.__icon) layout.addWidget(QLabel(self.dock.windowTitle())) self.dock.windowIconChanged.connect(self.__setWindowIcon) # fake spacer item spacer = QWidgetAction(self) spacer.setDefaultWidget(w) self.setMovable(False) self.setFloatable(False) self.setIconSize(QSize(12, 12)) self.aFloat = QAction(self) self.aClose = QAction(self) QToolBar.addAction(self, spacer) self.separator = QToolBar.addSeparator(self) QToolBar.addAction(self, self.aFloat) QToolBar.addAction(self, self.aClose) self.updateStandardIcons() self.dockWidgetFeaturesChanged(self.dock.features()) self.dock.featuresChanged.connect(self.dockWidgetFeaturesChanged) self.aFloat.triggered.connect(self._floatTriggered) self.aClose.triggered.connect(self.dock.close)
def __createLayout(self): " Creates the toolbar and layout " # Buttons printButton = QAction(PixmapCache().getIcon('printer.png'), 'Print', self) printButton.triggered.connect(self.__onPrint) printButton.setEnabled(False) printButton.setVisible(False) printPreviewButton = QAction(PixmapCache().getIcon('printpreview.png'), 'Print preview', self) printPreviewButton.triggered.connect(self.__onPrintPreview) printPreviewButton.setEnabled(False) printPreviewButton.setVisible(False) spacer = QWidget() spacer.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding) self.lineCounterButton = QAction( PixmapCache().getIcon('linecounter.png'), 'Line counter', self) self.lineCounterButton.triggered.connect(self.onLineCounter) # The toolbar toolbar = QToolBar(self) toolbar.setOrientation(Qt.Vertical) toolbar.setMovable(False) toolbar.setAllowedAreas(Qt.RightToolBarArea) toolbar.setIconSize(QSize(16, 16)) toolbar.setFixedWidth(28) toolbar.setContentsMargins(0, 0, 0, 0) toolbar.addAction(printPreviewButton) toolbar.addAction(printButton) toolbar.addWidget(spacer) toolbar.addAction(self.lineCounterButton) self.__importsBar = ImportListWidget(self.__viewer) self.__importsBar.hide() hLayout = QHBoxLayout() hLayout.setContentsMargins(0, 0, 0, 0) hLayout.setSpacing(0) hLayout.addWidget(self.__viewer) hLayout.addWidget(toolbar) self.setLayout(hLayout) return
def __init__(self, parent, *args): QToolBar.__init__(self, parent, *args) self.setSizePolicy( QSizePolicy(QSizePolicy.Expanding, QSizePolicy.Maximum)) self._dock = parent self.aClose = QToolBar.addAction( self, self.style().standardIcon(QStyle.SP_TitleBarCloseButton), "") self.setMovable(False) self.setFloatable(False) self.aClose.triggered.connect(self._dock.close) textHeight = QFontMetrics(self.font()).height() self.setIconSize(QSize(textHeight, textHeight)) # a fake spacer widget self._spacer = QWidget(self) self._spacer.setSizePolicy( QSizePolicy(QSizePolicy.Expanding, QSizePolicy.MinimumExpanding)) self.addWidget(self._spacer)
def setupUi(self): bar = QToolBar() bar.addAction(self.playAction) bar.addAction(self.pauseAction) bar.addAction(self.stopAction) self.seekSlider = Phonon.SeekSlider(self) self.seekSlider.setMediaObject(media) self.volumeSlider = Phonon.VolumeSlider(self) self.volumeSlider.setAudioOutput(audio) self.volumeSlider.setSizePolicy(QSizePolicy.Maximum, QSizePolicy.Maximum) volumeLabel = QLabel() volumeLabel.setPixmap(QPixmap('images/volume.png')) palette = QPalette() palette.setBrush(QPalette.Light, Qt.darkGray) self.timeLcd = QLCDNumber() self.timeLcd.setPalette(palette) headers = ("Title", "Artist", "Album", "Year") seekerLayout = QHBoxLayout() seekerLayout.addWidget(self.seekSlider) seekerLayout.addWidget(self.timeLcd) playbackLayout = QHBoxLayout() playbackLayout.addWidget(bar) playbackLayout.addStretch() playbackLayout.addWidget(volumeLabel) playbackLayout.addWidget(self.volumeSlider) mainLayout = QVBoxLayout() mainLayout.addWidget(video) mainLayout.addLayout(seekerLayout) mainLayout.addLayout(playbackLayout) self.setLayout(mainLayout)
def initToolbar(self): toolBar = QToolBar(self) chooseAction = QAction(self.style().standardIcon( QStyle.SP_DialogOpenButton), 'Open', toolBar) chooseAction.triggered.connect(self.chooseEbook) toolBar.addAction(chooseAction) self.prevAction = QAction(self.style().standardIcon( QStyle.SP_ArrowBack), 'Go back', toolBar) self.prevAction.setEnabled(False) self.prevAction.triggered.connect(self.prevChapter) toolBar.addAction(self.prevAction) self.nextAction = QAction(self.style().standardIcon( QStyle.SP_ArrowForward), 'Go forward', toolBar) self.nextAction.setEnabled(False) self.nextAction.triggered.connect(self.nextChapter) toolBar.addAction(self.nextAction) self.addToolBar(toolBar)
def _setupUi(self, background=None): """ Make the GUI """ # mdi self.mdiArea = MSMdiArea(self) self.mdiArea.setBackground(QBrush(QPixmap(path.normcase("gui/icons/blac2.png")))) # QColor(Qt.blue).darker())) self.setCentralWidget(self.mdiArea) # sample dock widget self.sampleDockWidget = QDockWidget("Samples", self) # sampleWidget = QWidget() self.sampleTableView = MSDragFromTableView() self.sampleTableView.setModel(self.sampleModel) self.sampleTableView.setSelectionBehavior(1) self.sampleTableView.verticalHeader().hide() self.sampleTableView.verticalHeader().setDefaultSectionSize(15) self.sampleTableView.horizontalHeader().setDefaultSectionSize(150) self.sampleDockWidget.setWidget(self.sampleTableView) # sampleWidget) self.sampleDockWidget.visible = True # workflow dock self.workflowDockWidget = QDockWidget("Visualizer", self) self.workflowDockWidget.visible = True a = QWidget(self) v = QVBoxLayout(a) q = QToolBar() # self.workingSample = QLabel("Working Sample:None") # q.addWidget(self.workingSample) q.addWidget(QLabel("ppm :")) self.ppmEditer = QDoubleSpinBox() self.usePpm = QCheckBox("use ?") q.addWidget(self.ppmEditer) q.addWidget(self.usePpm) q.addSeparator() self.removeButton = QToolButton(self) self.removeButton.setIcon(QIcon(path.normcase("gui/icons/delete.png"))) q.addWidget(self.removeButton) self.markAsGood = QAction(QIcon(path.normcase("gui/icons/button_ok.png")), "mark peak as good", self) self.markAsBad = QAction(QIcon(path.normcase("gui/icons/stop.png")), "mark peak as bad", self) self.hideItem = QAction(QIcon(path.normcase("gui/icons/list_remove.png")), "Hide Item", self) q.addAction(self.markAsGood) q.addAction(self.markAsBad) q.addAction(self.hideItem) v.addWidget(q) self.tabWidget = QTabWidget() self.tab = QWidget() verticalLayout = QVBoxLayout(self.tab) self.treeView = MSToDropTableView() self.treeView.verticalHeader().setDefaultSectionSize(20) self.treeView.setModel(self.spectraModel) self.spectraLabel = QLabel("Sample: None") verticalLayout.addWidget(self.treeView) verticalLayout.addWidget(self.spectraLabel) self.tabWidget.addTab(self.tab, QIcon(path.normcase("gui/icons/spectrumicon.png")), "Spectra") self.tab_2 = QWidget() verticalLayout_4 = QVBoxLayout(self.tab_2) self.treeView_2 = MSToDropTableView() # MSTreeView(self.tab_2)# QTableView(self)# self.treeView_2.verticalHeader().setDefaultSectionSize(20) self.treeView_2.setModel(self.peakModel) self.peakLabel = QLabel("Sample: None") verticalLayout_4.addWidget(self.treeView_2) verticalLayout_4.addWidget(self.peakLabel) self.tabWidget.addTab(self.tab_2, QIcon(path.normcase("gui/icons/peakicon.png")), "Peaks List") self.tab_3 = QWidget() verticalLayout_5 = QVBoxLayout(self.tab_3) self.treeView_3 = MSToDropTreeView() self.treeView_3.setAnimated(True) self.treeView_3.setModel(self.clusterModel) self.clusterLabel = QLabel("Sample: None") verticalLayout_5.addWidget(self.treeView_3) verticalLayout_5.addWidget(self.clusterLabel) self.tabWidget.addTab(self.tab_3, QIcon(path.normcase("gui/icons/clustering.png")), "Clusters") self.tabWidget.setCurrentIndex(0) for l in (self.spectraLabel, self.peakLabel, self.clusterLabel): l.setAutoFillBackground(True) v.addWidget(self.tabWidget) self.workflowDockWidget.setWidget(a) self.addDockWidget(Qt.DockWidgetArea(0x2), self.workflowDockWidget) from gui.MetBaseGui import MSIsoCalculator self.isoCalc = MSIsoCalculator(self) self.isoCalcDockWidget = QDockWidget("isotopes calculation", self) self.isoCalcDockWidget.setWidget(self.isoCalc) self.addDockWidget(Qt.DockWidgetArea(0x2), self.isoCalcDockWidget) self.isoCalcDockWidget.setVisible(False) self.isoCalcDockWidget.visible = False from gui.MetBaseGui import FormulaGenerator self.generator = FormulaGenerator(self) self.generatorDockWidget = QDockWidget("formula generator", self) self.generatorDockWidget.setWidget(self.generator) self.addDockWidget(Qt.DockWidgetArea(0x2), self.generatorDockWidget) self.generatorDockWidget.setVisible(False) self.generatorDockWidget.visible = False self.compoundTreeView = MSCompoundTreeView(self) self.compoundDockWidget = QDockWidget("Compounds", self) self.compoundDockWidget.setWidget(self.compoundTreeView) self.addDockWidget(Qt.DockWidgetArea(0x2), self.compoundDockWidget) self.compoundDockWidget.setVisible(False) self.compoundDockWidget.visible = False self.comparativeTableView = QTableView(self) self.comparativeTableView.horizontalHeader().setStretchLastSection(True) self.comparativeTableView.verticalHeader().setDefaultSectionSize(20) self.comparativeDock = QDockWidget("Comparative View", self) self.comparativeDock.setWidget(self.comparativeTableView) self.addDockWidget(Qt.DockWidgetArea(0x8), self.comparativeDock) self.comparativeDock.setVisible(False) self.comparativeDock.visible = False self.tabifyDockWidget(self.compoundDockWidget, self.isoCalcDockWidget) self.tabifyDockWidget(self.isoCalcDockWidget, self.workflowDockWidget) self.tabifyDockWidget(self.workflowDockWidget, self.generatorDockWidget) # set the end # WARNING: possible that the internal shell widget cause random segfault # with the error of QObject::killTimers...? not sure ! self.shell = QWidget() # InternalShell(namespace={'metms': QApplication.instance()}, # parent=self, # multithreaded=False) self.shellDock = QDockWidget("Python Shell", self) self.shellDock.setWindowIcon(QIcon(path.normcase("gui/icons/stop.png"))) self.shellDock.setWidget(self.shell) self.shellDock.setMinimumWidth(255) self.shellDock.visible = True self.addDockWidget(0x2, self.shellDock) self.addDockWidget(0x2, self.sampleDockWidget) self.tabifyDockWidget(self.shellDock, self.sampleDockWidget) self.pb = QProgressBar(self) self.pb.setMaximumWidth(245) self.stopProcess = QToolButton(self) self.stopProcess.setIcon(QIcon(path.normcase("gui/icons/process_stop.png"))) m = QMenu() # self.connect(m, SIGNAL('triggered(QAction*'), QApplication.instance().taskManager.abortByName) self.stopProcess.setMenu(m) self.stopProcess.setPopupMode(1) # Menu Button # self.connect(self.stopProcess, SIGNAL("clicked()"), self.stopThread) self.statusBar().addPermanentWidget(self.stopProcess) self.statusBar().addPermanentWidget(self.pb)
class _CameraWidget(QWidget): imagecaptured = pyqtSignal(QPixmap) done = pyqtSignal() def __init__(self, parent=None): super(_CameraWidget, self).__init__(parent) self.cameralabel = QLabel() self.cameralabel.setScaledContents(True) self.setLayout(QGridLayout()) self.toolbar = QToolBar() spacer = QWidget() # spacer.setMinimumWidth(30) spacer.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed) self.toolbar.setIconSize(QSize(48, 48)) self.toolbar.addWidget(spacer) self.swapaction = self.toolbar.addAction(QIcon(":/widgets/cameraswap"), "Swap Camera") self.swapaction.triggered.connect(self.swapcamera) self.cameralabel.mouseReleaseEvent = self.takeimage self.layout().setContentsMargins(0, 0, 0, 0) self.layout().addWidget(self.toolbar) self.layout().addWidget(self.cameralabel) self.timer = QTimer() self.timer.setInterval(20) self.timer.timeout.connect(self.showimage) self.cam = None self.pixmap = None self.currentdevice = 1 def swapcamera(self): self.stop() if self.currentdevice == 0: self.start(1) else: self.start(0) def showimage(self): if self.cam is None: return img = self.cam.getImage() self.image = ImageQt(img) pixmap = QPixmap.fromImage(self.image) self.cameralabel.setPixmap(pixmap) def takeimage(self, *args): self.timer.stop() img = self.cam.getImage() self.image = ImageQt(img) self.pixmap = QPixmap.fromImage(self.image) self.cameralabel.setPixmap(self.pixmap) self.imagecaptured.emit(self.pixmap) self.done.emit() @property def camera_res(self): width, height = tuple(roam.config.settings['camera_res'].split(',')) return width, height def start(self, dev=1): try: self.cam = vc.Device(dev) try: width, height = self.camera_res self.cam.setResolution(int(width), int(height)) except KeyError: pass self.currentdevice = dev except vidcap.error: if dev == 0: utils.error("Could not start camera") raise CameraError("Could not start camera") self.start(dev=0) return roam.config.settings['camera'] = self.currentdevice self.timer.start() def stop(self): self.timer.stop() del self.cam self.cam = None
class DUdpReplay(QtHelper.EnhancedQDialog, Logger.ClassLogger): """ Http replay dialog """ def __init__(self, parent=None, offlineMode=False): """ Constructor @param parent: @type parent: """ super(DUdpReplay, self).__init__(parent) self.offlineMode = offlineMode self.defaultIp = "127.0.0.1" self.defaultPort = "80" self.newTest = '' self.newTestExec = '' self.newInputs = [] self.requests = [] self.responses = [] self.defaultTemplates = DefaultTemplates.Templates() self.testType = None self.createDialog() self.createConnections() self.createActions() self.createToolbar() def createActions(self): """ Create qt actions """ self.openAction = QtHelper.createAction(self, "&Open", self.importTrace, icon=QIcon(":/folder_add.png"), tip='Open network trace.') self.exportTUAction = QtHelper.createAction( self, "&Test Unit", self.exportToTU, icon=QIcon(":/%s.png" % WWorkspace.TestUnit.TYPE), tip='Export to Test Unit') self.exportTSAction = QtHelper.createAction( self, "&Test Suite", self.exportToTS, icon=QIcon(":/%s.png" % WWorkspace.TestSuite.TYPE), tip='Export to Test Suite') self.cancelAction = QtHelper.createAction(self, "&Cancel", self.reject, tip='Cancel') menu = QMenu(self) menu.addAction(self.exportTUAction) menu.addAction(self.exportTSAction) self.exportToAction = QtHelper.createAction( self, "&Export to", self.exportToTU, icon=QIcon(":/%s.png" % WWorkspace.TestUnit.TYPE), tip='Export to tests') self.exportToAction.setMenu(menu) self.exportToAction.setEnabled(False) def createDialog(self): """ Create dialog """ self.dockToolbar = QToolBar(self) self.dockToolbar.setToolButtonStyle(Qt.ToolButtonTextBesideIcon) self.setWindowTitle(WINDOW_TITLE) self.resize(500, 400) self.ipEdit = QLineEdit(self.defaultIp) ipRegExpVal = QRegExpValidator(self) ipRegExp = QRegExp("\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}") ipRegExpVal.setRegExp(ipRegExp) self.ipEdit.setValidator(ipRegExpVal) self.portEdit = QLineEdit(self.defaultPort) self.portEdit.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed) validatorPort = QIntValidator(self) self.portEdit.setValidator(validatorPort) self.progressBar = QProgressBar(self) self.progressBar.setMaximum(100) self.progressBar.setProperty("value", 0) self.progressBar.setAlignment(Qt.AlignCenter) self.progressBar.setObjectName("progressBar") self.guiSikuliGroupBox = QGroupBox("") self.guiSikuliGroupBox.setFlat(True) self.automaticAdp = QRadioButton("Automatic") self.automaticAdp.setChecked(True) self.defaultAdp = QRadioButton("Default") self.genericAdp = QRadioButton("Generic") vbox = QHBoxLayout() vbox.addWidget(self.automaticAdp) vbox.addWidget(self.defaultAdp) vbox.addWidget(self.genericAdp) vbox.addStretch(1) self.guiSikuliGroupBox.setLayout(vbox) layout = QVBoxLayout() layout.addWidget(self.dockToolbar) layout.addSpacing(12) paramLayout = QGridLayout() paramLayout.addWidget(QLabel("Destination IP:"), 0, 0, Qt.AlignRight) paramLayout.addWidget(self.ipEdit, 0, 1) paramLayout.addWidget(QLabel("Destination Port:"), 1, 0, Qt.AlignRight) paramLayout.addWidget(self.portEdit, 1, 1) paramLayout.addWidget(QLabel(self.tr("Gui adapter selector:")), 2, 0, Qt.AlignRight) paramLayout.addWidget(self.guiSikuliGroupBox, 2, 1) layout.addLayout(paramLayout) self.logsEdit = QTextEdit() self.logsEdit.setReadOnly(True) self.logsEdit.setTextInteractionFlags(Qt.NoTextInteraction) layout.addSpacing(12) layout.addWidget(self.logsEdit) layout.addSpacing(12) layout.addWidget(self.progressBar) self.setLayout(layout) def createToolbar(self): """ Create toolbar """ self.dockToolbar.setObjectName("File toolbar") self.dockToolbar.addAction(self.openAction) self.dockToolbar.addSeparator() self.dockToolbar.addAction(self.exportToAction) self.dockToolbar.addSeparator() self.dockToolbar.setIconSize(QSize(16, 16)) def createConnections(self): """ Create qt connections """ pass def autoScrollOnTextEdit(self): """ Automatic scroll on text edit """ cursor = self.logsEdit.textCursor() cursor.movePosition(QTextCursor.End) self.logsEdit.setTextCursor(cursor) def strip_html(self, txt): """ Strip html """ if "<" in txt: txt = txt.replace('<', '<') if ">" in txt: txt = txt.replace('>', '>') return txt def addLogSuccess(self, txt): """ Add log success in the text edit """ self.logsEdit.insertHtml( "<span style='color:darkgreen'>%s</span><br />" % unicode(self.strip_html(txt))) self.autoScrollOnTextEdit() def addLogWarning(self, txt): """ Add log warning in the text edit """ self.logsEdit.insertHtml( "<span style='color:darkorange'>%s</span><br />" % unicode(self.strip_html(txt))) self.autoScrollOnTextEdit() def addLogError(self, txt): """ Add log error in the text edit """ self.logsEdit.insertHtml("<span style='color:red'>%s</span><br />" % unicode(self.strip_html(txt))) self.autoScrollOnTextEdit() def addLog(self, txt): """ Append log to the logsEdit widget """ self.logsEdit.insertHtml("%s<br />" % unicode(self.strip_html(txt))) self.autoScrollOnTextEdit() def importTrace(self): """ Import network trace """ self.logsEdit.clear() self.testType = None if not self.offlineMode: if not RCI.instance().isAuthenticated(): self.addLogWarning( txt="<< Connect to the test center in first!") QMessageBox.warning(self, "Import", "Connect to the test center in first!") return self.exportToAction.setEnabled(False) self.newTest = '' self.progressBar.setMaximum(100) self.progressBar.setValue(0) if sys.version_info > (3, ): fileName = QFileDialog.getOpenFileName( self, self.tr("Open File"), "", "Network dump (*.cap;*.pcap;*.pcapng)") else: fileName = QFileDialog.getOpenFileName(self, self.tr("Open File"), "", "Network dump (*.cap)") # new in v18 to support qt5 if QtHelper.IS_QT5: _fileName, _type = fileName else: _fileName = fileName # end of new if not _fileName: return if sys.version_info < (3, ): extension = str(_fileName).rsplit(".", 1)[1] if not (extension == "cap"): self.addLogError(txt="<< File not supported %s" % _fileName) QMessageBox.critical(self, "Open", "File not supported") return _fileName = str(_fileName) capName = _fileName.rsplit("/", 1)[1] self.addLogSuccess(txt=">> Reading the file %s" % _fileName) self.readFileV2(fileName=_fileName) def exportToTS(self): """ Export to test suite """ self.testType = TS self.exportToTest(TS=True, TU=False) def exportToTU(self): """ Export to test unit """ self.testType = TU self.exportToTest(TS=False, TU=True) def searchUDP(self): """ Search UDP module in assistant """ # modules accessor ret = "SutAdapters" if self.automaticAdp.isChecked(): isGeneric = WWorkspace.Helper.instance().isGuiGeneric(name="GUI") if isGeneric: ret = "SutAdapters.Generic" elif self.defaultAdp.isChecked(): return ret elif self.genericAdp.isChecked(): ret = "SutAdapters.Generic" else: pass return ret def exportToTest(self, TS=True, TU=False): """ Export to test """ if not RCI.instance().isAuthenticated(): self.addLogWarning(txt="<< Connect to the test center in first!") QMessageBox.warning(self, "Import", "Connect to the test center in first!") return if TS: self.newTest = self.defaultTemplates.getTestDefinitionAuto() self.newTestExec = self.defaultTemplates.getTestExecutionAuto() if TU: self.newTest = self.defaultTemplates.getTestUnitDefinitionAuto() destIp = str(self.ipEdit.text()) destPort = str(self.portEdit.text()) self.newInputs = [] self.newInputs.append({ 'type': 'self-ip', 'name': 'BIND_IP', 'description': '', 'value': '0.0.0.0', 'color': '' }) self.newInputs.append({ 'type': 'int', 'name': 'BIND_PORT', 'description': '', 'value': '0', 'color': '' }) self.newInputs.append({ 'type': 'str', 'name': 'DEST_IP', 'description': '', 'value': '%s' % destIp, 'color': '' }) self.newInputs.append({ 'type': 'int', 'name': 'DEST_PORT', 'description': '', 'value': '%s' % destPort, 'color': '' }) self.newInputs.append({ 'type': 'bool', 'name': 'DEBUG', 'description': '', 'value': 'False', 'color': '' }) self.newInputs.append({ 'type': 'float', 'name': 'TIMEOUT', 'description': '', 'value': '5.0', 'color': '' }) adps = """self.ADP_UDP = %s.UDP.Client(parent=self, bindIp=input('BIND_IP'), bindPort=input('BIND_PORT'), destinationIp=input('DEST_IP'), destinationPort=input('DEST_PORT'), debug=input('DEBUG'), separatorDisabled=True)""" % self.searchUDP( ) # prepare steps steps = [] j = 0 for i in xrange(len(self.requests)): j = i + 1 sentrecv, req = self.requests[i] if sentrecv == 'sent': steps.append( 'self.step%s = self.addStep(expected="udp data sent", description="send udp data", summary="send udp data")' % j) else: steps.append( 'self.step%s = self.addStep(expected="udp data received", description="received udp data", summary="received udp data")' % j) tests = [] for i in xrange(len(self.requests)): j = i + 1 sentrecv, req = self.requests[i] (source, dest, source_port, dest_port, data) = req if sentrecv == 'sent': tests.append("# data to sent %s" % j) tests.append('self.step%s.start()' % j) if sys.version_info > (3, ): tests.append('rawSent = %s' % data.replace(b"'", b"\\'")) else: tests.append('rawSent = """%s"""' % data) tests.append('SentMsg = self.ADP_UDP.sendData(data=rawSent)') tests.append('if not SentMsg:') tests.append( '\tself.step%s.setFailed(actual="unable to send data")' % j) tests.append('else:') tests.append( '\tself.step%s.setPassed(actual="udp data sent succesfully")' % j) tests.append('') if sentrecv == 'recv': tests.append("# data to received %s" % j) tests.append('self.step%s.start()' % j) if sys.version_info > (3, ): tests.append('rawRecv = %s' % data.replace(b'"', b'\\"')) else: tests.append('rawRecv = """%s"""' % data) tests.append( 'RecvMsg = self.ADP_UDP.hasReceivedData(data=rawRecv, timeout=input("TIMEOUT"))' ) tests.append('if RecvMsg is None:') tests.append( '\tself.step%s.setFailed(actual="unable to received data")' % j) tests.append('else:') tests.append( '\tself.step%s.setPassed(actual="udp data received succesfully")' % j) tests.append('') if TS: init = """self.ADP_UDP.startListening() udpListening = self.ADP_UDP.isListening( timeout=input('TIMEOUT') ) if not udpListening: self.abort( 'unable to listing to the udp port %s' ) """ % str(self.portEdit.text()) if TU: init = """self.ADP_UDP.startListening() udpListening = self.ADP_UDP.isListening( timeout=input('TIMEOUT') ) if not udpListening: self.abort( 'unable to connect to the udp port %s' ) """ % str(self.portEdit.text()) if TS: cleanup = """self.ADP_UDP.stopListening() udpStopped = self.ADP_UDP.isStopped( timeout=input('TIMEOUT') ) if not udpStopped: self.error( 'unable to no more listen from the udp port %s' ) """ % str(self.portEdit.text()) if TU: cleanup = """self.ADP_UDP.stopListening() udpStopped = self.ADP_UDP.isStopped( timeout=input('TIMEOUT') ) if not udpStopped: self.error( 'unable to no more listen from the udp port %s' ) """ % str(self.portEdit.text()) self.newTest = self.newTest.replace( "<<PURPOSE>>", 'self.setPurpose(purpose="Replay UDP")') self.newTest = self.newTest.replace("<<ADPS>>", adps) if TS: self.newTest = self.newTest.replace("<<STEPS>>", '\n\t\t'.join(steps)) if TU: self.newTest = self.newTest.replace("<<STEPS>>", '\n\t'.join(steps)) self.newTest = self.newTest.replace("<<INIT>>", init) self.newTest = self.newTest.replace("<<CLEANUP>>", cleanup) if TS: self.newTest = self.newTest.replace("<<TESTS>>", '\n\t\t'.join(tests)) if TU: self.newTest = self.newTest.replace("<<TESTS>>", '\n\t'.join(tests)) self.accept() def readFileV2(self, fileName): """ Read pcap file Support pcap-ng too """ fd = open(fileName, 'rb') fileFormat, fileHead = PcapParse.extractFormat(fd) if fileFormat == PcapParse.FileFormat.PCAP: self.trace("pcap file detected") pcapFile = PcapReader.PcapFile(fd, fileHead).read_packet self.readFilePacket(pcapFile=pcapFile) elif fileFormat == PcapParse.FileFormat.PCAP_NG: self.trace("pcap-png file detected") pcapFile = PcapngReader.PcapngFile(fd, fileHead).read_packet self.readFilePacket(pcapFile=pcapFile) else: self.addLogError(txt="<< Error to open the network trace") self.error('unable to open the network trace: file format = %s' % fileFormat) QMessageBox.critical(self, "Import", "File not supported") def readFilePacket(self, pcapFile): """ Read file packet by packet """ ip_expected = str(self.ipEdit.text()) port_expected = int(self.portEdit.text()) # read packet) packets = pcapFile() ethernetPackets = list(packets) self.addLogSuccess(txt="<< Total packets detected: %s " % len(ethernetPackets)) # extract udp packet according to the expected ip and port self.requests = [] i = 1 self.progressBar.setMaximum(len(ethernetPackets)) self.progressBar.setValue(0) for pkt in ethernetPackets: self.progressBar.setValue(i) i += 1 pktDecoded = PcapParse.decodePacket(pkt, getTcp=False, getUdp=True) if pktDecoded is not None: (source, dest, source_port, dest_port, data) = pktDecoded # skip when no data exists if dest == ip_expected and int(dest_port) == int( port_expected) and len(data) > 0: self.requests.append(('sent', pktDecoded)) if source == ip_expected and int(source_port) == int( port_expected) and len(data) > 0: self.requests.append(('recv', pktDecoded)) self.addLogSuccess(txt="<< Number of UDP packets detected: %s" % len(self.requests)) if self.requests: self.addLogSuccess("<< File decoded with success!") self.addLogWarning( "<< Click on the export button to generate the test!") self.exportToAction.setEnabled(True) else: self.addLogWarning("<< No udp extracted!")
class QueryTab(QTabWidget, Ui_QueryWidget): def __init__(self, db, dbName, query="SHOW TABLES"): QTabWidget.__init__(self) self.db = db self.dbName = dbName self.queryThread = None self.setupUi(self) self.tableQueryResult.verticalHeader().hide() # toolbar self.toolbar = QToolBar(self) self.toolbar.addAction(self.actionLoadQuery) self.toolbar.addAction(self.actionSaveQuery) self.toolbar.addAction(self.actionSaveQueryAs) self.toolbarLayout.insertWidget(0, self.toolbar) self.txtQuery.setText(query) self.btnKillQuery.setVisible(False) @pyqtSignature("") def on_actionLoadQuery_triggered(self): self.txtQuery.loadDialog() @pyqtSignature("") def on_actionSaveQuery_triggered(self): self.txtQuery.save() @pyqtSignature("") def on_actionSaveQueryAs_triggered(self): self.txtQuery.saveAsDialog() @pyqtSignature("") def on_btnExecuteQuery_clicked(self): self.db.setDatabase(self.dbName) queryModel = QPySelectModel(self, self.db) def queryTerminated(): self.btnExecuteQuery.setVisible(True) self.btnKillQuery.setVisible(False) def queryExecuted(t): queryModel.setResult(t.result, t.cursor) self.tableQueryResult.setModel(queryModel) if self.txtQuery.text().strip().lower().startswith('select'): self.labelQueryError.setText("%d rows returned" % t.cursor.rowcount) else: self.labelQueryError.setText("%d rows affected" % t.cursor.rowcount) self.labelQueryTime.setText("Query took %f sec" % t.elapsed_time) self.tableQueryResult.resizeColumnsToContents() self.tableQueryResult.resizeRowsToContents() warningsModel = QPySelectModel(self, self.db) warningsModel.setSelect("SHOW WARNINGS") warningsModel.select() self.tableWarnings.setModel(warningsModel) self.tableWarnings.resizeColumnsToContents() self.tableWarnings.resizeRowsToContents() height = 0 for i in range(len(warningsModel._rows)): height += self.tableWarnings.rowHeight(i) + 2 if height: height += 4 self.tableWarnings.setMaximumHeight(height) queryTerminated() def queryError(errno, errmsg): self.labelQueryError.setText(errmsg) self.labelQueryTime.setText("") queryTerminated() self.labelQueryError.setText("Running query...") self.labelQueryTime.setText("") self.btnExecuteQuery.setVisible(False) self.btnKillQuery.setVisible(True) self.queryThread = self.db.asyncQuery(self.txtQuery.text(), db=self.dbName, callback=queryExecuted, callback_error=queryError) @pyqtSignature("") def on_btnKillQuery_clicked(self): if self.queryThread: self.queryThread.kill()
class UploadManagerView(QTreeWidget,View): """ This component has a list of UploadTransactionView objects. This component depicts the status of the UploadManager object. """ _widget = None _uploadTransactionViews = None _mainLayout = None _toolbar = None def __init__(self,parentWidget): QTreeWidget.__init__(self,parentWidget) View.__init__(self) self._mutex = QMutex() self._uploadTransactionViews = [] self.setColumnCount(3) columnNames = QStringList() columnNames.append("Filename") columnNames.append("Status") columnNames.append("Upload progress") self.setHeaderLabels(columnNames) self.setSelectionMode(self.ExtendedSelection) #on double click of a transaction, let's have the controller deal with whatever happened self.connect(self,SIGNAL("itemDoubleClicked (QTreeWidgetItem *,int)"), self.onItemDoubleClicked) #self.adjustSize() self.initToolBar() def initToolBar(self): self._toolbar = QToolBar(QString("Blooploads"),self.parent()) from controllers.ActionManager import ActionManager uploadManagerActions = ActionManager.getInstance().getBloopUploadManagerActions() for action in uploadManagerActions: self._toolbar.addAction(action) #utils.trace("UploadManagerView","initToolBar()",self._toolbar) def getToolBar(self): if self._toolbar is None: self.initToolBar() #utils.trace("UploadManagerView","getToolBar()",self._toolbar) return self._toolbar def onItemDoubleClicked(self, uploadTransactionView, column): if self.getController() is not None: self.getController().onTransactionDoubleClicked(uploadTransactionView, column) def addUploadTransactionView(self, uploadTransactionView): #We won't add it if its there already if uploadTransactionView in self._uploadTransactionViews: #print #utils.trace("UploadManagerView","addUploadTransactionView","Skipping, transaction exists already on the view") #print uploadTransactionView #print return self._uploadTransactionViews.append(uploadTransactionView) itemCount = len(self._uploadTransactionViews) self.insertTopLevelItem(itemCount-1,uploadTransactionView) #uploadTransactionView.updateStatus() #utils.trace("UploadManagerView","addUploadTransactionView","ADDED ONE TRANSACTION TO THE VIEW") #utils.trace("UploadManagerView","addUploadTransactionView",uploadTransactionView) def clearUploadTransactions(self): ''' It will clear whatever is on the UploadTransactionView. ''' while len(self._uploadTransactionViews) > 0: uploadTransactionView = self._uploadTransactionViews.pop() self.takeTopLevelItem(self.indexOfTopLevelItem(uploadTransactionView)) self._uploadTransactionViews.remove(uploadTransactionView) uploadTransactionView.deleteLater() self._uploadTransactionViews = [] def removeUploadTransactionView(self, uploadTransactionView): try: self._uploadTransactionViews.remove(uploadTransactionView) except ValueError: #utils.trace("UploadManagerView","removeUploadTransactionView","ELEMENT IS GONE ALREADY, CANT REMOVE") pass indexOfUploadTransactionView = self.indexOfTopLevelItem(uploadTransactionView) self.takeTopLevelItem(indexOfUploadTransactionView) #utils.trace("UploadManagerView","removeUploadTransactionView",uploadTransactionView) #utils.trace("UploadManagerView","removeUploadTransactionView","at index " + str(indexOfUploadTransactionView))
class MainWindow(QMainWindow): """ This class is the main application class, it defines the GUI window for the browser """ def createAction(self, text, slot=None, shortcut=None, icon=None, tip=None, checkable=False, signal="triggered()"): """Borrowed from 'Rapid GUI Development with PyQT by Mark Summerset'""" action = QAction(text, self) if icon is not None: action.setIcon(QIcon.fromTheme(icon, QIcon(":/%s.png" % icon))) if shortcut is not None and not shortcut.isEmpty(): action.setShortcut(shortcut) tip += " (%s)" % shortcut.toString() if tip is not None: action.setToolTip(tip) action.setStatusTip(tip) if slot is not None: self.connect(action, SIGNAL(signal), slot) if checkable: action.setCheckable() return action def __init__(self, options, parent=None): super(MainWindow, self).__init__(parent) #Load config file self.setWindowTitle("Browser") self.options = options self.configuration = {} debug("loading configuration from '%s'" % options.config_file) if self.options.config_file: self.configuration = yaml.safe_load(open(self.options.config_file, 'r')) debug(self.configuration) self.default_user = options.default_user or self.configuration.get("default_user") self.default_password = options.default_password or self.configuration.get("default_password") self.start_url = options.url or self.configuration.get("start_url", "about:blank") self.screensaver_url = self.configuration.get("screensaver_url", "about:blank") self.screensaver_active = False self.whitelist = self.configuration.get("whitelist", False) # self.proxy_server = options.proxy_server or os.environ.get("http_proxy") or self.configuration.get("proxy_server") self.proxy_server = self.configuration.get("proxy_server") self.popup = None # Stylesheet support self.stylesheet = self.configuration.get("stylesheet") if self.stylesheet: try: with open(self.stylesheet) as ss: self.setStyleSheet(ss.read()) except: debug("""Problem loading stylesheet file "%s", using default style.""" % self.stylesheet) self.setObjectName("global") #The following variable sets the error code when a page cannot be reached, # either because of a generic 404, or because you've blocked it. # You can override it using the "page_unavailable_html" setting in the configuration file. self.html404 = DEFAULT_404 % (self.start_url) if (self.configuration.get("page_unavailable_html")): try: html404 = open(self.configuration.get("page_unavailable_html"), 'r').read() except: html404 = None debug("Couldn't read file: %s" % self.configuration.get("page_unavailable_html")) self.html404 = html404 or self.html404 #This string is shown when sites that should be reachable (e.g. the start page) aren't. #You might want to put in contact information for your tech support, etc. # You can override it use the "network_down_html" setting in the configuration file. self.html_network_down = DEFAULT_NETWORK_DOWN % (self.start_url) if (self.configuration.get("network_down_html")): try: html_network_down = open(self.configuration.get("network_down_html"), 'r').read() except: html_network_down = None debug("Couldn't read file: %s" % self.configuration.get("network_down_html")) self.html_network_down = html_network_down or self.html_network_down self.build_ui(self.options, self.configuration) def build_ui(self, options, configuration): """ This is all the twisted logic of setting up the UI, which is re-run whenever the browser is "reset" by the user. """ debug("build_ui") inactivity_timeout = options.timeout or int(configuration.get("timeout", 0)) timeout_mode = configuration.get('timeout_mode', 'reset') self.refresh_timer = int(configuration.get("refresh_timer", 0)) self.icon_theme = options.icon_theme or configuration.get("icon_theme", None) self.zoomfactor = options.zoomfactor or float(configuration.get("zoom_factor") or 1.0) self.allow_popups = options.allow_popups or configuration.get("allow_popups", False) self.ssl_mode = (configuration.get("ssl_mode") in ['strict', 'ignore'] and configuration.get("ssl_mode")) or 'strict' self.is_fullscreen = options.is_fullscreen or configuration.get("fullscreen", False) self.show_navigation = not options.no_navigation and configuration.get('navigation', True) self.navigation_layout = configuration.get( "navigation_layout", ['back', 'forward', 'refresh', 'stop', 'zoom_in', 'zoom_out', 'separator', 'bookmarks', 'separator', 'spacer', 'quit']) self.content_handlers = self.configuration.get("content_handlers", {}) self.allow_external_content = options.allow_external_content or self.configuration.get("allow_external_content", False) self.allow_plugins = options.allow_plugins or self.configuration.get("allow_plugins", False) self.privacy_mode = self.configuration.get("privacy_mode", True) self.quit_button_mode = self.configuration.get("quit_button_mode", 'reset') self.quit_button_text = self.configuration.get("quit_button_text", "I'm &Finished") self.quit_button_tooltip = (self.quit_button_mode == 'close' and "Click here to quit the browser.") or \ """Click here when you are done.\nIt will clear your browsing history and return you to the start page.""" self.window_size = options.window_size or self.configuration.get("window_size", None) self.allow_printing = self.configuration.get("allow_printing", False) qb_mode_callbacks = {'close': self.close, 'reset': self.reset_browser} to_mode_callbacks = {'close': self.close, 'reset': self.reset_browser, 'screensaver': self.screensaver} #If the whitelist is activated, add the bookmarks and start_url if self.whitelist: # we can just specify whitelist = True, #which should whitelist just the start_url and bookmark urls. if type(self.whitelist) is not list: self.whitelist = [] self.whitelist.append(str(QUrl(self.start_url).host())) bookmarks = self.configuration.get("bookmarks") if bookmarks: self.whitelist += [str(QUrl(b.get("url")).host()) for k,b in bookmarks.items()] self.whitelist = list(set(self.whitelist)) #uniquify self.whitelist = [item.replace(".", "\.") for item in self.whitelist] #escape dots debug("Generated whitelist: " + str(self.whitelist)) ###Start GUI configuration### self.browser_window = WcgWebView( allow_popups=self.allow_popups, default_user=self.default_user, default_password=self.default_password, zoomfactor=self.zoomfactor, content_handlers=self.content_handlers, allow_external_content=self.allow_external_content, html404=self.html404, html_network_down=self.html_network_down, start_url=self.start_url, ssl_mode=self.ssl_mode, allow_plugins = self.allow_plugins, whitelist = self.whitelist, allow_printing = self.allow_printing, proxy_server = self.proxy_server, privacy_mode = self.privacy_mode ) self.browser_window.setObjectName("web_content") if self.icon_theme is not None and QT_VERSION_STR > '4.6': QIcon.setThemeName(self.icon_theme) self.setCentralWidget(self.browser_window) debug(options) debug("loading %s" % self.start_url) self.browser_window.setUrl(QUrl(self.start_url)) if self.is_fullscreen is True: self.showFullScreen() elif self.window_size and self.window_size.lower() == 'max': self.showMaximized() elif self.window_size: size = re.match(r"(\d+)x(\d+)", self.window_size) if size: width, height = size.groups() self.setFixedSize(int(width), int(height)) else: debug("Ignoring invalid window size \"%s\"" % self.window_size) #Set up the top navigation bar if it's configured to exist if self.show_navigation is True: self.navigation_bar = QToolBar("Navigation") self.navigation_bar.setObjectName("navigation") self.addToolBar(Qt.TopToolBarArea, self.navigation_bar) self.navigation_bar.setMovable(False) self.navigation_bar.setFloatable(False) #Standard navigation tools self.nav_items = {} self.nav_items["back"] = self.browser_window.pageAction(QWebPage.Back) self.nav_items["forward"] = self.browser_window.pageAction(QWebPage.Forward) self.nav_items["refresh"] = self.browser_window.pageAction(QWebPage.Reload) self.nav_items["stop"] = self.browser_window.pageAction(QWebPage.Stop) #The "I'm finished" button. self.nav_items["quit"] = self.createAction( self.quit_button_text, qb_mode_callbacks.get(self.quit_button_mode, self.reset_browser), QKeySequence("Alt+F"), None, self.quit_button_tooltip) #Zoom buttons self.nav_items["zoom_in"] = self.createAction( "Zoom In", self.zoom_in, QKeySequence("Alt++"), "zoom-in", "Increase the size of the text and images on the page") self.nav_items["zoom_out"] = self.createAction( "Zoom Out", self.zoom_out, QKeySequence("Alt+-"), "zoom-out", "Decrease the size of text and images on the page") if self.allow_printing: self.nav_items["print"] = self.createAction("Print", self.browser_window.print_webpage, QKeySequence("Ctrl+p"), "document-print", "Print this page") #Add all the actions to the navigation bar. for item in self.navigation_layout: if item == "separator": self.navigation_bar.addSeparator() elif item == "spacer": #an expanding spacer. spacer = QWidget() spacer.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Preferred) self.navigation_bar.addWidget(spacer) elif item == "bookmarks": #Insert bookmarks buttons here. self.bookmark_buttons = [] if configuration.get("bookmarks"): for bookmark in configuration.get("bookmarks").items(): debug("Bookmark:\n" + bookmark.__str__()) #bookmark name will use the "name" attribute, if present #or else just the key: bookmark_name = bookmark[1].get("name") or bookmark[0] #Create a button for the bookmark as a QAction, #which we'll add to the toolbar button = self.createAction( bookmark_name, lambda url=bookmark[1].get("url"): self.browser_window.load(QUrl(url)), QKeySequence.mnemonic(bookmark_name), None, bookmark[1].get("description") ) self.navigation_bar.addAction(button) self.navigation_bar.widgetForAction(button).setObjectName("navigation_button") else: action = self.nav_items.get(item, None) if action: self.navigation_bar.addAction(action) self.navigation_bar.widgetForAction(action).setObjectName("navigation_button") #This removes the ability to toggle off the navigation bar: self.nav_toggle = self.navigation_bar.toggleViewAction() self.nav_toggle.setVisible(False) #End "if show_navigation is True" block # set hidden quit action # For reasons I haven't adequately ascertained, #this shortcut fails now and then claiming "Ambiguous shortcut overload". # No idea why, as it isn't consistent. self.really_quit = self.createAction("", self.close, QKeySequence("Ctrl+Alt+Q"), None, "") self.addAction(self.really_quit) #Call a reset function after timeout if inactivity_timeout != 0: self.event_filter = InactivityFilter(inactivity_timeout) QCoreApplication.instance().installEventFilter(self.event_filter) self.browser_window.page().installEventFilter(self.event_filter) self.connect(self.event_filter, SIGNAL("timeout()"), to_mode_callbacks.get(timeout_mode, self.reset_browser)) else: self.event_filter = None if self.refresh_timer != 0: # Create a QTimer self.timer = QTimer() # Connect it to self.refresh_browser self.timer.timeout.connect(self.refresh_browser) # Call refresh_browser() every self.refresh_timer seconds self.timer.start(self.refresh_timer*1000) ###END OF CONSTRUCTOR### def screensaver(self): debug("screensaver started") self.screensaver_active = True if self.popup: self.popup.close() if self.show_navigation is True: self.navigation_bar.hide() self.browser_window.setZoomFactor(self.zoomfactor) self.browser_window.load(QUrl(self.screensaver_url)) self.disconnect(self.event_filter, SIGNAL("activity"), self.reset_browser) self.connect(self.event_filter, SIGNAL("activity"), self.reset_browser) def reset_browser(self): """ This function clears the history and resets the UI. It's called whenever the inactivity filter times out, Or when the user clicks the "finished" button when in 'reset' mode. """ # Clear out the memory cache QWebSettings.clearMemoryCaches() self.browser_window.history().clear() # self.navigation_bar.clear() doesn't do its job, #so remove the toolbar first, then rebuild the UI. debug("RESET BROWSER") if self.event_filter: self.event_filter.blockSignals(True) if self.screensaver_active is True: self.screensaver_active = False self.disconnect(self.event_filter, SIGNAL("activity"), self.reset_browser) if self.event_filter: self.event_filter.blockSignals(False) if hasattr(self, "navigation_bar"): self.removeToolBar(self.navigation_bar) self.build_ui(self.options, self.configuration) def zoom_in(self): """ This is the callback for the zoom in action. Note that we cap zooming in at a factor of 3x. """ if self.browser_window.zoomFactor() < 3.0: self.browser_window.setZoomFactor(self.browser_window.zoomFactor() + 0.1) self.nav_items["zoom_out"].setEnabled(True) else: self.nav_items["zoom_in"].setEnabled(False) def zoom_out(self): """ This is the callback for the zoom out action. Note that we cap zooming out at 0.1x. """ if self.browser_window.zoomFactor() > 0.1: self.browser_window.setZoomFactor(self.browser_window.zoomFactor() - 0.1) self.nav_items["zoom_in"].setEnabled(True) else: self.nav_items["zoom_out"].setEnabled(False) def refresh_browser(self): debug("Refreshing Browser") self.browser_window.reload() self.timer.start(self.refresh_timer*1000)
class MainApp(QDockWidget, QMainWindow, Ui_MainApp): # signals goBack = pyqtSignal() searchOpsubByName = pyqtSignal(str) enableSearch = pyqtSignal(bool) refreshLegend = pyqtSignal(QgsMapLayer) ogrDatasourceLoaded = pyqtSignal(bool) class VfkLayer(object): Par = 0 Bud = 1 def __init__(self, iface): QDockWidget.__init__(self, iface.mainWindow()) self.setupUi(self) self.iface = iface # variables self.__mLastVfkFile = [] self.__mOgrDataSource = None self.__mDataSourceName = '' self.__fileName = [] self.__mLoadedLayers = {} self.__mDefaultPalette = self.vfkFileLineEdit.palette() # new lineEdits variables self.lineEditsCount = 1 self.__browseButtons = {} self.__vfkLineEdits = {} # data will be load from source according to checked radiobox self.__source_for_data = 'file' # apply changes into main database self.__databases = {} # self.pb_applyChanges.setEnabled(False) self.changes_instance = ApplyChanges() # Connect ui with functions self.__createToolbarsAndConnect() # check GDAL version self.__gdal_version = int(gdal.VersionInfo()) if self.__gdal_version < 2020000: self.actionZpracujZmeny.setEnabled(False) self.pb_nextFile.setEnabled(False) self.pb_nextFile.setToolTip( u'Není možné načíst více souborů, verze GDAL je nižší než 2.2.0.') self.actionZpracujZmeny.setToolTip(u'Zpracování změn není povoleno, verze GDAL je nižší než 2.2.0.') self.groupBox.setEnabled(False) # settings self.loadVfkButton.setDisabled(True) self.searchFormMainControls = SearchFormController.MainControls() self.searchFormMainControls.formCombobox = self.searchCombo self.searchFormMainControls.searchForms = self.searchForms self.searchFormMainControls.searchButton = self.searchButton self.searchForms = SearchFormController.SearchForms() self.searchForms.vlastnici = self.vlastniciSearchForm self.searchForms.parcely = self.parcelySearchForm self.searchForms.budovy = self.budovySearchForm self.searchForms.jednotky = self.jednotkySearchForm # search form controller self.__mSearchController = SearchFormController( self.searchFormMainControls, self.searchForms, self) self.connect(self.__mSearchController, SIGNAL( "actionTriggered(QUrl)"), self.vfkBrowser.processAction) self.connect( self, SIGNAL("enableSearch"), self.searchButton.setEnabled) self.connect(self.vfkBrowser, SIGNAL("showParcely"), self.showParInMap) self.connect(self.vfkBrowser, SIGNAL("showBudovy"), self.showBudInMap) # connect lineEdits and returnPressed action self.connect(self.vfkFileLineEdit, SIGNAL( "returnPressed()"), self.loadVfkButton_clicked) self.connect(self.vlastniciSearchForm.ui.jmenoLineEdit, SIGNAL("returnPressed()"), self.__mSearchController.search) self.connect(self.vlastniciSearchForm.ui.rcIcoLineEdit, SIGNAL("returnPressed()"), self.__mSearchController.search) self.connect(self.vlastniciSearchForm.ui.lvVlastniciLineEdit, SIGNAL("returnPressed()"), self.__mSearchController.search) self.connect(self.parcelySearchForm.ui.parCisloLineEdit, SIGNAL("returnPressed()"), self.__mSearchController.search) self.connect(self.parcelySearchForm.ui.lvParcelyLineEdit, SIGNAL("returnPressed()"), self.__mSearchController.search) self.connect(self.budovySearchForm.ui.cisloDomovniLineEdit, SIGNAL("returnPressed()"), self.__mSearchController.search) self.connect(self.budovySearchForm.ui.naParceleLineEdit, SIGNAL("returnPressed()"), self.__mSearchController.search) self.connect(self.budovySearchForm.ui.lvBudovyLineEdit, SIGNAL("returnPressed()"), self.__mSearchController.search) self.connect(self.jednotkySearchForm.ui.mCisloJednotkyLineEdit, SIGNAL("returnPressed()"), self.__mSearchController.search) self.connect(self.jednotkySearchForm.ui.mCisloDomovniLineEdit, SIGNAL("returnPressed()"), self.__mSearchController.search) self.connect(self.jednotkySearchForm.ui.mNaParceleLineEdit, SIGNAL("returnPressed()"), self.__mSearchController.search) self.connect(self.jednotkySearchForm.ui.mLvJednotkyLineEdit, SIGNAL("returnPressed()"), self.__mSearchController.search) self.vfkBrowser.showHelpPage() def browseButton_clicked(self, browseButton_id=1): """ :param browseButton_id: ID of clicked browse button. :return: """ title = u'Načti soubor VFK' settings = QSettings() lastUsedDir = '' if self.__source_for_data == 'file': ext = '*.vfk' if self.__gdal_version >= 2020000: ext += ' *.db' loaded_file = QFileDialog.getOpenFileName( self, title, lastUsedDir, u'Soubory podporované ovladačem VFK GDAL ({})'.format(ext)) if not loaded_file: return else: self.__fileName.append(loaded_file) if browseButton_id == 1: self.vfkFileLineEdit.setText(self.__fileName[0]) else: self.__vfkLineEdits['vfkLineEdit_{}'.format(len(self.__vfkLineEdits))].setText( self.__fileName[browseButton_id - 1]) elif self.__source_for_data == 'directory': loaded_file = QFileDialog.getExistingDirectory(self, u"Vyberte adresář s daty VFK") if not loaded_file: return else: self.__fileName = [] self.__fileName.append(loaded_file) self.vfkFileLineEdit.setText(self.__fileName[0]) else: qDebug('(VFK) Not valid source') self.loadVfkButton.setEnabled(True) def browserGoBack(self): self.vfkBrowser.goBack() def browserGoForward(self): self.vfkBrowser.goForth() def selectParInMap(self): self.showInMap(self.vfkBrowser.currentParIds(), "PAR") def selectBudInMap(self): self.showInMap(self.vfkBrowser.currentBudIds(), "BUD") def latexExport(self): fileName = QFileDialog.getSaveFileName( self, u"Jméno exportovaného souboru", ".tex", "LaTeX (*.tex)") if fileName: export_succesfull = self.vfkBrowser.exportDocument( self.vfkBrowser.currentUrl(), fileName, self.vfkBrowser.ExportFormat.Latex) if export_succesfull: self.succesfullExport("LaTeX") def htmlExport(self): fileName = QFileDialog.getSaveFileName( self, u"Jméno exportovaného souboru", ".html", "HTML (*.html)") if fileName: export_succesfull = self.vfkBrowser.exportDocument( self.vfkBrowser.currentUrl(), fileName, self.vfkBrowser.ExportFormat.Html) if export_succesfull: self.succesfullExport("HTML") def setSelectionChangedConnected(self, connected): """ :type connected: bool :return: """ for layer in self.__mLoadedLayers: id = self.__mLoadedLayers[layer] vectorLayer = QgsMapLayerRegistry.instance().mapLayer(id) if connected: self.connect( vectorLayer, SIGNAL("selectionChanged()"), self.showInfoAboutSelection) else: self.disconnect( vectorLayer, SIGNAL("selectionChanged()"), self.showInfoAboutSelection) def showInMap(self, ids, layerName): """ :type ids: list :type layerName: str :return: """ if layerName in self.__mLoadedLayers: id = self.__mLoadedLayers[layerName] vectorLayer = QgsMapLayerRegistry.instance().mapLayer(id) searchString = "ID IN ({})".format(", ".join(ids)) error = '' fIds = self.__search(vectorLayer, searchString, error) if error: qDebug('\n (VFK) ERROR in showInMap: {}'.format(error)) return else: vectorLayer.setSelectedFeatures(fIds) def __search(self, layer, searchString, error): """ :type layer: QgsVectorLayer :type searchString: str :type error: str :return: """ # parse search string and build parsed tree search = QgsExpression(searchString) rect = QgsRectangle() fIds = [] if search.hasParserError(): error += "Parsing error:" + search.parserErrorString() return fIds if not search.prepare(layer.pendingFields()): error + "Evaluation error:" + search.evalErrorString() layer.select(rect, False) fit = QgsFeatureIterator(layer.getFeatures()) f = QgsFeature() while fit.nextFeature(f): if search.evaluate(f): fIds.append(f.id()) # check if there were errors during evaluating if search.hasEvalError(): qDebug('\n (VFK) Evaluate error: {}'.format(error)) break return fIds def loadVfkButton_clicked(self): """ After click method starts loading all inserted files """ # check the source of data if self.__source_for_data == 'directory': dir_path = self.__fileName[0] self.__fileName = self.__findVFKFilesInDirectory(dir_path) # check if first file is amendment amendment_file = self.__checkIfAmendmentFile(self.__fileName[0]) # prepare name for database if amendment_file: new_database_name = '{}_zmeny.db'.format(os.path.basename(self.__fileName[0]).split('.')[0]) else: new_database_name = '{}_stav.db'.format(os.path.basename(self.__fileName[0]).split('.')[0]) os.environ['OGR_VFK_DB_NAME'] = os.path.join( os.path.dirname(os.path.dirname(self.__fileName[0])), new_database_name) self.__mDataSourceName = self.__fileName[0] # os.environ['OGR_VFK_DB_NAME'] QgsApplication.processEvents() self.importThread = OpenThread(self.__fileName) self.importThread.working.connect(self.runLoadingLayer) if not self.importThread.isRunning(): self.importThread.start() def runLoadingLayer(self, fileName): """ :return: """ if fileName not in self.__mLastVfkFile: self.labelLoading.setText( u'Načítám data do SQLite databáze (může nějaký čas trvat...)') try: self.loadVfkFile(fileName) except VFKError as e: QMessageBox.critical( self, u'Chyba', u'{}'.format(e), QMessageBox.Ok) self.emit(SIGNAL("enableSearch"), False) return self.__mLastVfkFile.append(fileName) self.importThread.nextLayer = False if fileName == self.__fileName[-1]: self.loadingLayersFinished() def loadingLayersFinished(self): """ :return: """ try: self.__openDatabase( os.environ['OGR_VFK_DB_NAME']) # self.__mDataSourceName) except VFKError as e: QMessageBox.critical( self, u'Chyba', u'{}'.format(e), QMessageBox.Ok) self.emit(SIGNAL("enableSearch"), False) return self.vfkBrowser.setConnectionName(self.property("connectionName")) self.__mSearchController.setConnectionName( self.property("connectionName")) self.emit(SIGNAL("enableSearch"), True) self.__mLoadedLayers.clear() if self.parCheckBox.isChecked(): self.__loadVfkLayer('PAR') else: self.__unLoadVfkLayer('PAR') if self.budCheckBox.isChecked(): self.__loadVfkLayer('BUD') else: self.__unLoadVfkLayer('BUD') self.labelLoading.setText(u'Načítání souborů VFK bylo dokončeno.') def vfkFileLineEdit_textChanged(self, arg1): """ :type arg1: str :return: """ info = QFileInfo(arg1) if info.isFile(): self.loadVfkButton.setEnabled(True) self.vfkFileLineEdit.setPalette(self.__mDefaultPalette) else: self.loadVfkButton.setEnabled(False) pal = QPalette(self.vfkFileLineEdit.palette()) pal.setColor(QPalette.text(), Qt.red) self.vfkFileLineEdit.setPalette(pal) def __loadVfkLayer(self, vfkLayerName): """ :type vfkLayerName: str :return: """ qDebug("\n(VFK) Loading vfk layer {}".format(vfkLayerName)) if vfkLayerName in self.__mLoadedLayers: qDebug( "\n(VFK) Vfk layer {} is already loaded".format(vfkLayerName)) return composedURI = self.__mDataSourceName + "|layername=" + vfkLayerName layer = QgsVectorLayer(composedURI, vfkLayerName, "ogr") if not layer.isValid(): qDebug("\n(VFK) Layer failed to load!") self.__mLoadedLayers[vfkLayerName] = layer.id() try: self.__setSymbology(layer) except VFKWarning as e: QMessageBox.information(self, 'Load Style', e, QMessageBox.Ok) QgsMapLayerRegistry.instance().addMapLayer(layer) def __unLoadVfkLayer(self, vfkLayerName): """ :type vfkLayerName: str :return: """ qDebug("\n(VFK) Unloading vfk layer {}".format(vfkLayerName)) if vfkLayerName not in self.__mLoadedLayers: qDebug( "\n(VFK) Vfk layer {} is already unloaded".format(vfkLayerName)) return QgsMapLayerRegistry.instance().removeMapLayer( self.__mLoadedLayers[vfkLayerName]) del self.__mLoadedLayers[vfkLayerName] def __setSymbology(self, layer): """ :type layer: QgsVectorLayer :return: """ name = layer.name() symbologyFile = '' if name == 'PAR': symbologyFile = ':/parStyle.qml' elif name == 'BUD': symbologyFile = ':/budStyle.qml' errorMsg, resultFlag = layer.loadNamedStyle(symbologyFile) if not resultFlag: raise VFKWarning(u'Load style: {}'.format(errorMsg)) layer.triggerRepaint() self.emit(SIGNAL("refreshLegend"), layer) def __openDatabase(self, dbPath): """ :type dbPath: str :return: """ qDebug("\n(VFK) Open DB: {}".format(dbPath)) if not QSqlDatabase.isDriverAvailable('QSQLITE'): raise VFKError(u'Databázový ovladač QSQLITE není dostupný.') connectionName = QUuid.createUuid().toString() db = QSqlDatabase.addDatabase("QSQLITE", connectionName) db.setDatabaseName(dbPath) if not db.open(): raise VFKError(u'Nepodařilo se otevřít databázi. ') self.setProperty("connectionName", connectionName) def loadVfkFile(self, fileName): """ :type fileName: str :return: """ label_text = fileName.split('/') label_text = '...' + label_text[-2] + '/' + label_text[-1] # overwrite database if fileName == self.__fileName[0]: if self.overwriteCheckBox.isChecked(): qDebug('\n (VFK) Database will be overwritten') os.environ['OGR_VFK_DB_OVERWRITE'] = '1' if self.__mOgrDataSource: self.__mOgrDataSource.Destroy() self.__mOgrDataSource = None QgsApplication.registerOgrDrivers() self.progressBar.setRange(0, 1) self.progressBar.setValue(0) QgsApplication.processEvents() #os.environ['OGR_VFK_DB_READ_ALL_BLOCKS'] = 'NO' self.labelLoading.setText( u'Načítám soubor {} (může nějaký čas trvat...)'.format(label_text)) QgsApplication.processEvents() self.__mOgrDataSource = ogr.Open( fileName, 0) # 0 - datasource is open in read-only mode if not self.__mOgrDataSource: raise VFKError( u"Nelze otevřít VFK soubor '{}' jako platný OGR datasource.".format(fileName)) layerCount = self.__mOgrDataSource.GetLayerCount() layers_names = [] for i in xrange(layerCount): layers_names.append( self.__mOgrDataSource.GetLayer(i).GetLayerDefn().GetName()) if ('PAR' not in layers_names or 'BUD' not in layers_names) and len(self.__vfkLineEdits) == 1: self.__dataWithoutParBud() self.labelLoading.setText( u'Data nemohla být načtena. Vstupní soubor neobsahuje bloky PAR a BUD.') QgsApplication.processEvents() return # load all layers self.progressBar.setRange(0, layerCount - 1) for i in xrange(layerCount): self.progressBar.setValue(i) theLayerName = self.__mOgrDataSource.GetLayer( i).GetLayerDefn().GetName() self.labelLoading.setText( u"VFK data {}/{}: {}".format(i + 1, layerCount, theLayerName)) QgsApplication.processEvents() self.__mOgrDataSource.GetLayer(i).GetFeatureCount(True) time.sleep(0.02) self.labelLoading.setText( u'Soubor {} úspěšně načten.'.format(label_text)) os.environ['OGR_VFK_DB_OVERWRITE'] = '0' self.__mOgrDataSource.Destroy() self.__mOgrDataSource = None def __selectedIds(self, layer): """ :type layer: QgsVectorLayer :return: """ ids = [] flist = layer.selectedFeatures() for it in flist: f = QgsFeature(it) ids.append(str(f.attribute("ID"))) return ids def showInfoAboutSelection(self): layers = ["PAR", "BUD"] layerIds = {} for layer in layers: if layer in self.__mLoadedLayers: id = str(self.__mLoadedLayers[layer]) vectorLayer = QgsMapLayerRegistry.instance().mapLayer(id) layerIds[layer] = self.__selectedIds(vectorLayer) self.vfkBrowser.showInfoAboutSelection( layerIds["PAR"], layerIds["BUD"]) def showParInMap(self, ids): """ :type ids: list :return: """ if self.actionShowInfoaboutSelection.isChecked(): self.setSelectionChangedConnected(False) self.showInMap(ids, "PAR") self.setSelectionChangedConnected(True) else: self.showInMap(ids, "PAR") def showBudInMap(self, ids): """ :type ids: list :return: """ if self.actionShowInfoaboutSelection.isChecked(): self.setSelectionChangedConnected(False) self.showInMap(ids, "BUD") self.setSelectionChangedConnected(True) else: self.showInMap(ids, "BUD") def showOnCuzk(self): x = self.vfkBrowser.currentDefinitionPoint().first.split(".")[0] y = self.vfkBrowser.currentDefinitionPoint().second.split(".")[0] url = "http://nahlizenidokn.cuzk.cz/MapaIdentifikace.aspx?&x=-{}&y=-{}".format( y, x) QDesktopServices.openUrl(QUrl(url, QUrl.TolerantMode)) def switchToImport(self): self.actionImport.trigger() def switchToSearch(self, searchType): """ :type searchType: int """ self.actionVyhledavani.trigger() self.searchCombo.setCurrentIndex(searchType) self.searchFormMainControls.searchForms.setCurrentIndex(searchType) def switchToChanges(self): """ """ self.actionZpracujZmeny.trigger() def succesfullExport(self, export_format): """ :type export_format: str :return: """ QMessageBox.information( self, u'Export', u"Export do formátu {} proběhl úspěšně.".format( export_format), QMessageBox.Ok) def __dataWithoutParBud(self): """ :type export_format: str :return: """ QMessageBox.warning(self, u'Upozornění', u"Zvolený VFK soubor neobsahuje vrstvy s geometrií (PAR, BUD), proto nemohou " u"být pomocí VFK Pluginu načtena. Data je možné načíst v QGIS pomocí volby " u"'Načíst vektorovou vrstvu.'", QMessageBox.Ok) def __addRowToGridLayout(self): if len(self.__vfkLineEdits) >= 5: self.__maximumLineEditsReached() return # update label self.label.setText('VFK soubory:') # new layout horizontalLayout = QtGui.QHBoxLayout() # create new objects self.__browseButtons['browseButton_{}'.format( len(self.__vfkLineEdits) + 1)] = QtGui.QPushButton(u"Procházet") self.__vfkLineEdits['vfkLineEdit_{}'.format( len(self.__vfkLineEdits) + 1)] = QtGui.QLineEdit() horizontalLayout.addWidget(self.__vfkLineEdits[ 'vfkLineEdit_{}'.format(len(self.__vfkLineEdits))]) horizontalLayout.addWidget(self.__browseButtons[ 'browseButton_{}'.format(len(self.__vfkLineEdits))]) # number of lines in gridLayout rows_count = self.gridLayout_12.rowCount( ) # count of rows in gridLayout # export objects from gridLayout item_label = self.gridLayout_12.itemAtPosition(rows_count - 3, 0) item_par = self.gridLayout_12.itemAtPosition(rows_count - 3, 1) item_bud = self.gridLayout_12.itemAtPosition(rows_count - 2, 1) item_settings = self.gridLayout_12.itemAtPosition(rows_count - 1, 0) item_rewrite_db = self.gridLayout_12.itemAtPosition(rows_count - 1, 1) # remove objects from gridLayout self.gridLayout_12.removeItem( self.gridLayout_12.itemAtPosition(rows_count - 3, 0)) self.gridLayout_12.removeItem( self.gridLayout_12.itemAtPosition(rows_count - 3, 1)) self.gridLayout_12.removeItem( self.gridLayout_12.itemAtPosition(rows_count - 2, 1)) self.gridLayout_12.removeItem( self.gridLayout_12.itemAtPosition(rows_count - 1, 0)) self.gridLayout_12.removeItem( self.gridLayout_12.itemAtPosition(rows_count - 1, 1)) # re-build gridLayout self.gridLayout_12.addLayout(horizontalLayout, rows_count - 3, 1) self.gridLayout_12.addItem(item_label, rows_count - 2, 0) self.gridLayout_12.addItem(item_par, rows_count - 2, 1) self.gridLayout_12.addItem(item_bud, rows_count - 1, 1) self.gridLayout_12.addItem(item_settings, rows_count, 0) self.gridLayout_12.addItem(item_rewrite_db, rows_count, 1) self.__browseButtons['browseButton_{}'.format(len(self.__vfkLineEdits))].clicked.\ connect(lambda: self.browseButton_clicked( int('{}'.format(len(self.__vfkLineEdits))))) def __maximumLineEditsReached(self): QMessageBox.information(self, u'Upozornění', u"Byl dosažen maximální počet ({}) VFK souboru pro zpracování." u"\nNačítání dalších souborů není povoleno!". format(self.lineEditsCount), QMessageBox.Ok) def browseDb_clicked(self, database_type): """ Method run dialog for select database in widget with changes. According to pushButton name will fill in relevant lineEdit. :type database_type: str """ title = u'Vyber databázi' settings = QSettings() lastUsedDir = str(settings.value('/UI/' + "lastVectorFileFilter" + "Dir", ".")) if database_type == 'mainDb': self.__databases[database_type] = QFileDialog.getOpenFileName(self, title, lastUsedDir, u'Datábaze (*.db)') if not self.__databases[database_type]: return self.le_mainDb.setText(self.__databases[database_type]) elif database_type == 'amendmentDb': self.__databases[database_type] = QFileDialog.getOpenFileName(self, title, lastUsedDir, u'Datábaze (*.db)') if not self.__databases[database_type]: return self.le_amendmentDb.setText(self.__databases[database_type]) elif database_type == 'exportDb': title = u'Zadej jméno výstupní databáze' self.__databases[database_type] = QFileDialog.getSaveFileName(self, u"Jméno výstupní databáze", ".db", u"Databáze (*.db)") if not self.__databases[database_type]: return self.le_exportDb.setText(self.__databases[database_type]) if len(self.__databases) == 3: self.pb_applyChanges.setEnabled(True) def applyChanges(self): """ Method :return: """ self.changes_instance.run(self.__databases['mainDb'], self.__databases['amendmentDb'], self.__databases['exportDb']) def __updateProgressBarChanges(self, iteration, table_name): """ :type iteration: int :type table_name: str """ self.progressBar_changes.setValue(iteration) self.l_status.setText(u'Aplikuji změny na tabulku {}...'.format(table_name)) QgsApplication.processEvents() def __setRangeProgressBarChanges(self, max_range): """ :type max_range: int """ self.progressBar_changes.setRange(0, max_range) self.progressBar_changes.setValue(0) def __changesApplied(self): """ """ time.sleep(1) self.l_status.setText(u'Změny byly úspěšně aplikovány.') QgsApplication.processEvents() def __changesPreprocessingDatabase(self): """ """ self.l_status.setText(u'Připravuji výstupní databázi...') QgsApplication.processEvents() def __checkIfAmendmentFile(self, file_name): """ :param file_name: Name of the input file :type file_name: str :return: bool """ if file_name.endswith(".vfk"): with open(file_name, 'r') as f: for line in f: line_splited = str(line).split(';') if line_splited[0] == '&HZMENY': if line_splited[1] == '1': return True else: return False else: print 'database' # TODO: dopsat kontrolu, zda se jedna o stavovou, nebo zmenovou databazi def radioButtonValue(self): """ Check which radio button is checked """ self.vfkFileLineEdit.setText('') self.__fileName = [] self.loadVfkButton.setEnabled(False) if self.rb_file.isChecked(): self.__source_for_data = 'file' self.pb_nextFile.show() self.label.setText('VFK soubor:') elif self.rb_directory.isChecked(): self.__source_for_data = 'directory' self.pb_nextFile.hide() self.label.setText(u'Adresář:') # delete if len(self.__browseButtons) > 1: for i, button in enumerate(self.__browseButtons): if i > 0: self.__browseButtons[button].hide() if len(self.__vfkLineEdits) > 1: for i, le in enumerate(self.__vfkLineEdits): if i > 0: self.__vfkLineEdits[le].hide() def __findVFKFilesInDirectory(self, dir_path): """ Finds all files with extension '.vfk' in given directory including subdirectories :param dir_path: Path to directory. :type dir_path: str :return: List of VFK files """ file_paths = [] for root, dirs, files in os.walk(dir_path): for file in files: if file.endswith(".vfk"): file_paths.append(os.path.join(root, file)) return file_paths def __createToolbarsAndConnect(self): actionGroup = QActionGroup(self) actionGroup.addAction(self.actionImport) actionGroup.addAction(self.actionVyhledavani) actionGroup.addAction(self.actionZpracujZmeny) # QSignalMapper self.signalMapper = QSignalMapper(self) # connect to 'clicked' on all buttons self.connect(self.actionImport, SIGNAL( "triggered()"), self.signalMapper, SLOT("map()")) self.connect(self.actionVyhledavani, SIGNAL( "triggered()"), self.signalMapper, SLOT("map()")) self.connect(self.actionZpracujZmeny, SIGNAL( "triggered()"), self.signalMapper, SLOT("map()")) # setMapping on each button to the QStackedWidget index we'd like to # switch to self.signalMapper.setMapping(self.actionImport, 0) self.signalMapper.setMapping(self.actionVyhledavani, 2) self.signalMapper.setMapping(self.actionZpracujZmeny, 1) # connect mapper to stackedWidget self.connect(self.signalMapper, SIGNAL("mapped(int)"), self.stackedWidget, SLOT("setCurrentIndex(int)")) self.actionImport.trigger() self.connect(self.vfkBrowser, SIGNAL( "switchToPanelImport"), self.switchToImport) self.connect(self.vfkBrowser, SIGNAL( "switchToPanelSearch"), self.switchToSearch) self.connect(self.vfkBrowser, SIGNAL( "switchToPanelChanges"), self.switchToChanges) # Browser toolbar # --------------- self.__mBrowserToolbar = QToolBar(self) self.connect(self.actionBack, SIGNAL( "triggered()"), self.vfkBrowser.goBack) self.connect(self.actionForward, SIGNAL( "triggered()"), self.vfkBrowser.goForth) self.connect(self.actionSelectBudInMap, SIGNAL("triggered()"), self.selectBudInMap) self.connect(self.actionSelectParInMap, SIGNAL("triggered()"), self.selectParInMap) self.connect(self.actionCuzkPage, SIGNAL("triggered()"), self.showOnCuzk) self.connect(self.actionExportLatex, SIGNAL("triggered()"), self.latexExport) self.connect(self.actionExportHtml, SIGNAL("triggered()"), self.htmlExport) self.connect(self.actionShowInfoaboutSelection, SIGNAL( "toggled(bool)"), self.setSelectionChangedConnected) self.connect(self.actionShowHelpPage, SIGNAL( "triggered()"), self.vfkBrowser.showHelpPage) self.loadVfkButton.clicked.connect(self.loadVfkButton_clicked) self.__browseButtons['browseButton_1'] = self.browseButton self.__browseButtons['browseButton_1'].clicked.connect( lambda: self.browseButton_clicked(int('{}'.format(len(self.__vfkLineEdits))))) self.__vfkLineEdits['vfkLineEdit_1'] = self.vfkFileLineEdit bt = QToolButton(self.__mBrowserToolbar) bt.setPopupMode(QToolButton.InstantPopup) bt.setText("Export ") menu = QMenu(bt) menu.addAction(self.actionExportLatex) menu.addAction(self.actionExportHtml) bt.setMenu(menu) # add actions to toolbar icons self.__mBrowserToolbar.addAction(self.actionImport) self.__mBrowserToolbar.addAction(self.actionVyhledavani) self.__mBrowserToolbar.addAction(self.actionZpracujZmeny) self.__mBrowserToolbar.addSeparator() self.__mBrowserToolbar.addAction(self.actionBack) self.__mBrowserToolbar.addAction(self.actionForward) self.__mBrowserToolbar.addAction(self.actionSelectParInMap) self.__mBrowserToolbar.addAction(self.actionSelectBudInMap) self.__mBrowserToolbar.addAction(self.actionCuzkPage) self.__mBrowserToolbar.addSeparator() self.__mBrowserToolbar.addAction(self.actionShowInfoaboutSelection) self.__mBrowserToolbar.addSeparator() self.__mBrowserToolbar.addWidget(bt) self.__mBrowserToolbar.addSeparator() self.__mBrowserToolbar.addAction(self.actionShowHelpPage) self.rightWidgetLayout.insertWidget(0, self.__mBrowserToolbar) # connect signals from vfkbrowser when changing history self.connect(self.vfkBrowser, SIGNAL( "currentParIdsChanged"), self.actionSelectParInMap.setEnabled) self.connect(self.vfkBrowser, SIGNAL("currentBudIdsChanged"), self.actionSelectBudInMap.setEnabled) self.connect(self.vfkBrowser, SIGNAL( "historyBefore"), self.actionBack.setEnabled) self.connect(self.vfkBrowser, SIGNAL( "historyAfter"), self.actionForward.setEnabled) self.connect(self.vfkBrowser, SIGNAL( "definitionPointAvailable"), self.actionCuzkPage.setEnabled) # add toolTips self.pb_nextFile.setToolTip(u'Přidej další soubor VFK') self.parCheckBox.setToolTip(u'Načti vrstvu parcel') self.budCheckBox.setToolTip(u'Načti vrstvu budov') # add new VFK file self.pb_nextFile.clicked.connect(self.__addRowToGridLayout) # widget apply changes self.pb_mainDb.clicked.connect( lambda: self.browseDb_clicked('mainDb')) self.pb_amendmentDb.clicked.connect( lambda: self.browseDb_clicked('amendmentDb')) self.pb_exportDb.clicked.connect( lambda: self.browseDb_clicked('exportDb')) self.pb_applyChanges.clicked.connect(self.applyChanges) self.pb_applyChanges.setEnabled(False) self.connect(self.changes_instance, SIGNAL("maxRangeProgressBar"), self.__setRangeProgressBarChanges) self.connect(self.changes_instance, SIGNAL("updateStatus"), self.__updateProgressBarChanges) self.connect(self.changes_instance, SIGNAL("finishedStatus"), self.__changesApplied) self.connect(self.changes_instance, SIGNAL("preprocessingDatabase"), self.__changesPreprocessingDatabase) # connect radio boxes self.rb_file.clicked.connect(self.radioButtonValue) self.rb_directory.clicked.connect(self.radioButtonValue)
class _CameraWidget(QWidget): imagecaptured = pyqtSignal(QPixmap) done = pyqtSignal() def __init__(self, parent=None): super(_CameraWidget, self).__init__(parent) self.cameralabel = QLabel() self.cameralabel.setScaledContents(True) self.setLayout(QGridLayout()) self.toolbar = QToolBar() self.swapaction = self.toolbar.addAction("Swap Camera") self.swapaction.triggered.connect(self.swapcamera) self.cameralabel.mouseReleaseEvent = self.takeimage self.layout().setContentsMargins(0,0,0,0) self.layout().addWidget(self.toolbar) self.layout().addWidget(self.cameralabel) self.timer = QTimer() self.timer.setInterval(20) self.timer.timeout.connect(self.showimage) self.cam = None self.pixmap = None self.currentdevice = 1 def swapcamera(self): self.stop() if self.currentdevice == 0: self.start(1) else: self.start(0) def showimage(self): if self.cam is None: return img = self.cam.getImage() self.image = ImageQt(img) pixmap = QPixmap.fromImage(self.image) self.cameralabel.setPixmap(pixmap) def takeimage(self, *args): self.timer.stop() img = self.cam.getImage() self.image = ImageQt(img) self.pixmap = QPixmap.fromImage(self.image) self.cameralabel.setPixmap(self.pixmap) self.imagecaptured.emit(self.pixmap) self.done.emit() def start(self, dev=1): try: self.cam = vc.Device(dev) self.currentdevice = dev except vidcap.error: if dev == 0: utils.error("Could not start camera") return self.start(dev=0) return self.timer.start() def stop(self): self.timer.stop() del self.cam self.cam = None
class PylintViewer( QWidget ): " Pylint tab widget " # Limits to colorize the final score BadLimit = 8.5 GoodLimit = 9.5 # Options of providing a report SingleFile = 0 DirectoryFiles = 1 ProjectFiles = 2 SingleBuffer = 3 updatePylintTooltip = pyqtSignal( str ) def __init__( self, parent = None ): QWidget.__init__( self, parent ) self.__reportUUID = "" self.__reportFileName = "" self.__reportOption = -1 self.__reportShown = False self.__report = None self.__widgets = [] # Prepare members for reuse if GlobalData().pylintAvailable: self.__noneLabel = QLabel( "\nNo results available" ) else: self.__noneLabel = QLabel( "\nPylint is not available" ) self.__noneLabel.setAutoFillBackground( True ) noneLabelPalette = self.__noneLabel.palette() noneLabelPalette.setColor( QPalette.Background, GlobalData().skin.nolexerPaper ) self.__noneLabel.setPalette( noneLabelPalette ) self.__noneLabel.setFrameShape( QFrame.StyledPanel ) self.__noneLabel.setAlignment( Qt.AlignHCenter ) self.__headerFont = self.__noneLabel.font() self.__headerFont.setPointSize( self.__headerFont.pointSize() + 4 ) self.__noneLabel.setFont( self.__headerFont ) self.__createLayout( parent ) self.__updateButtonsStatus() self.resizeEvent() return def __createLayout( self, parent ): " Creates the toolbar and layout " # Buttons self.printButton = QAction( PixmapCache().getIcon( 'printer.png' ), 'Print', self ) #printButton.setShortcut( 'Ctrl+' ) self.printButton.triggered.connect( self.__onPrint ) self.printButton.setVisible( False ) self.printPreviewButton = QAction( PixmapCache().getIcon( 'printpreview.png' ), 'Print preview', self ) #printPreviewButton.setShortcut( 'Ctrl+' ) self.printPreviewButton.triggered.connect( self.__onPrintPreview ) self.printPreviewButton.setVisible( False ) spacer = QWidget() spacer.setSizePolicy( QSizePolicy.Expanding, QSizePolicy.Expanding ) self.clearButton = QAction( PixmapCache().getIcon( 'trash.png' ), 'Clear', self ) self.clearButton.triggered.connect( self.__clear ) # The toolbar self.toolbar = QToolBar( self ) self.toolbar.setOrientation( Qt.Vertical ) self.toolbar.setMovable( False ) self.toolbar.setAllowedAreas( Qt.RightToolBarArea ) self.toolbar.setIconSize( QSize( 16, 16 ) ) self.toolbar.setFixedWidth( 28 ) self.toolbar.setContentsMargins( 0, 0, 0, 0 ) self.toolbar.addAction( self.printPreviewButton ) self.toolbar.addAction( self.printButton ) self.toolbar.addWidget( spacer ) self.toolbar.addAction( self.clearButton ) self.__vLayout = QVBoxLayout() self.__vLayout.setContentsMargins( 5, 5, 5, 5 ) self.__vLayout.setSpacing( 0 ) self.__vLayout.setSizeConstraint( QLayout.SetFixedSize ) self.__bodyFrame = QFrame( self ) # self.__bodyFrame.setFrameShape( QFrame.StyledPanel ) self.__bodyFrame.setFrameShape( QFrame.NoFrame ) # self.__bodyFrame.setSizePolicy( QSizePolicy.Maximum, # QSizePolicy.Expanding ) self.__bodyFrame.setLayout( self.__vLayout ) self.bodyWidget = QScrollArea( self ) self.bodyWidget.setFocusPolicy( Qt.NoFocus ) self.bodyWidget.setWidget( self.__bodyFrame ) self.bodyWidget.hide() self.__hLayout = QHBoxLayout() self.__hLayout.setContentsMargins( 0, 0, 0, 0 ) self.__hLayout.setSpacing( 0 ) self.__hLayout.addWidget( self.toolbar ) self.__hLayout.addWidget( self.__noneLabel ) self.__hLayout.addWidget( self.bodyWidget ) self.setLayout( self.__hLayout ) return def __updateButtonsStatus( self ): " Updates the buttons status " self.printButton.setEnabled( self.__reportShown ) self.printPreviewButton.setEnabled( self.__reportShown ) self.clearButton.setEnabled( self.__reportShown ) return def __onPrint( self ): " Triggered when the print button is pressed " pass def __onPrintPreview( self ): " triggered when the print preview button is pressed " pass def setFocus( self ): " Overridden setFocus " self.__vLayout.setFocus() return def __clear( self ): " Clears the content of the vertical layout " if not self.__reportShown: return self.__removeAll() self.bodyWidget.hide() self.__noneLabel.show() self.__report = None self.__reportShown = False self.__updateButtonsStatus() self.resizeEvent() self.__updateTooltip() return def __removeAll( self ): " Removes all the items from the report " for item in self.__widgets: item.hide() self.__vLayout.removeWidget( item ) del item self.__widgets = [] return def __createScoreLabel( self, score, previousScore, showFileName, fileName ): " Creates the score label " txt = "Score: " + str( score ) if previousScore != "": txt += " / Previous score: " + str( previousScore ) if not showFileName: txt += " for " + os.path.basename( fileName ) scoreLabel = QLabel( txt ) scoreLabel.setFrameShape( QFrame.StyledPanel ) scoreLabel.setFont( self.__headerFont ) scoreLabel.setAutoFillBackground( True ) palette = scoreLabel.palette() if score < self.BadLimit: palette.setColor( QPalette.Background, QColor( 255, 127, 127 ) ) palette.setColor( QPalette.Foreground, QColor( 0, 0, 0 ) ) elif score > self.GoodLimit: palette.setColor( QPalette.Background, QColor( 220, 255, 220 ) ) palette.setColor( QPalette.Foreground, QColor( 0, 0, 0 ) ) else: palette.setColor( QPalette.Background, QColor( 255, 255, 127 ) ) palette.setColor( QPalette.Foreground, QColor( 0, 0, 0 ) ) scoreLabel.setPalette( palette ) return scoreLabel @staticmethod def __setTableHeight( table ): " Auxiliary function to set the table height " # Height - it is ugly and approximate however I am tired of # calculating the proper height. Why is this so hard, huh? lastRowHeight = table.itemDelegate().lastHeight height = lastRowHeight * ( table.topLevelItemCount() + 1 ) + 10 table.setFixedHeight( height ) return @staticmethod def __shouldShowFileName( messages ): " Decides if the file name column should be supressed " if len( messages ) == 0: return False firstName = messages[ 0 ].fileName for index in range( 1, len( messages ) ): if firstName != messages[ index ].fileName: return True return False def __addErrorsTable( self, messages, showFileName ): " Creates the messages table " errTable = QTreeWidget( self.bodyWidget ) errTable.setAlternatingRowColors( True ) errTable.setRootIsDecorated( False ) errTable.setItemsExpandable( False ) errTable.setSortingEnabled( True ) errTable.setItemDelegate( NoOutlineHeightDelegate( 4 ) ) errTable.setUniformRowHeights( True ) errTable.itemActivated.connect( self.__errorActivated ) headerLabels = [ "File name", "Line", "Message ID", "Object", "Message" ] errTable.setHeaderLabels( headerLabels ) for item in messages: if item.position is None: lineNumber = str( item.lineNumber ) else: lineNumber = str( item.lineNumber ) + ":" + str( item.position ) values = [ item.fileName, lineNumber, item.messageID, item.objectName, item.message ] errTable.addTopLevelItem( ErrorTableItem( values, 1 ) ) # Hide the file name column if required if not showFileName: errTable.setColumnHidden( 0, True ) # Resizing errTable.header().resizeSections( QHeaderView.ResizeToContents ) errTable.header().setStretchLastSection( True ) # Sort indicator if showFileName: sortIndex = 0 # By file names else: sortIndex = 1 # By line number because this is from the same file errTable.header().setSortIndicator( sortIndex, Qt.AscendingOrder ) errTable.sortItems( sortIndex, errTable.header().sortIndicatorOrder() ) # Height self.__setTableHeight( errTable ) self.__vLayout.addWidget( errTable ) self.__widgets.append( errTable ) return def __addSimilarity( self, similarity, titleText ): " Adds a similarity " # Label title = QLabel( titleText ) title.setFont( self.__headerFont ) self.__vLayout.addWidget( title ) self.__widgets.append( title ) # List of files simTable = QTreeWidget( self.bodyWidget ) simTable.setAlternatingRowColors( True ) simTable.setRootIsDecorated( False ) simTable.setItemsExpandable( False ) simTable.setSortingEnabled( False ) simTable.setItemDelegate( NoOutlineHeightDelegate( 4 ) ) simTable.setUniformRowHeights( True ) simTable.itemActivated.connect( self.__similarityActivated ) simTable.setHeaderLabels( [ "File name", "Line" ] ) for item in similarity.files: values = [ item[ 0 ], str( item[ 1 ] ) ] simTable.addTopLevelItem( QTreeWidgetItem( values ) ) # Resizing simTable.header().resizeSections( QHeaderView.ResizeToContents ) simTable.header().setStretchLastSection( True ) # Height self.__setTableHeight( simTable ) self.__vLayout.addWidget( simTable ) self.__widgets.append( simTable ) # The fragment itself if len( similarity.fragment ) > 10: # Take first 9 lines text = "\n".join( similarity.fragment[ : 9 ] ) + "\n ..." toolTip = "\n".join( similarity.fragment ) else: text = "\n".join( similarity.fragment ) toolTip = "" fragmentLabel = QLabel( "<pre>" + self.__htmlEncode( text ) + "</pre>" ) if toolTip != "": fragmentLabel.setToolTip( "<pre>" + self.__htmlEncode( toolTip ) + "</pre>" ) palette = fragmentLabel.palette() palette.setColor( QPalette.Background, QColor( 250, 250, 175 ) ) palette.setColor( QPalette.Foreground, QColor( 0, 0, 0 ) ) fragmentLabel.setPalette( palette ) fragmentLabel.setFrameShape( QFrame.StyledPanel ) fragmentLabel.setAutoFillBackground( True ) labelFont = fragmentLabel.font() labelFont.setFamily( GlobalData().skin.baseMonoFontFace ) fragmentLabel.setFont( labelFont ) self.__vLayout.addWidget( fragmentLabel ) self.__widgets.append( fragmentLabel ) return @staticmethod def __htmlEncode( string ): " Encodes HTML " return string.replace( "&", "&" ) \ .replace( ">", ">" ) \ .replace( "<", "<" ) def __addSectionSpacer( self ): " Adds a fixed height spacer to the VBox layout " spacer = QWidget() spacer.setFixedHeight( 10 ) self.__vLayout.addWidget( spacer ) self.__widgets.append( spacer ) return def __addGenericTable( self, table ): " Adds a generic table to the report " theTable = QTreeWidget( self.bodyWidget ) theTable.setAlternatingRowColors( True ) theTable.setRootIsDecorated( False ) theTable.setItemsExpandable( False ) theTable.setSortingEnabled( False ) theTable.setItemDelegate( NoOutlineHeightDelegate( 4 ) ) theTable.setUniformRowHeights( True ) headerLabels = [] for index in range( 0, len( table.header ) ): headerLabels.append( table.header[ index ] ) theTable.setHeaderLabels( headerLabels ) for item in table.body: row = [] for index in range( 0, len( table.header ) ): row.append( item[ index ] ) theTable.addTopLevelItem( QTreeWidgetItem( row ) ) theTable.setFocusPolicy( Qt.NoFocus ) # Resizing theTable.header().resizeSections( QHeaderView.ResizeToContents ) theTable.header().setStretchLastSection( True ) # Height self.__setTableHeight( theTable ) self.__vLayout.addWidget( theTable ) self.__widgets.append( theTable ) return def __addGenericTableTitle( self, table ): " Adds a generic table title " tableTitle = QLabel( table.title ) tableTitle.setFont( self.__headerFont ) self.__vLayout.addWidget( tableTitle ) self.__widgets.append( tableTitle ) return def __updateTooltip( self ): " Generates a signal with appropriate string message " if not self.__reportShown: tooltip = "No results available" elif self.__reportOption == self.DirectoryFiles: tooltip = "Report generated for directory: " + \ self.__reportFileName elif self.__reportOption == self.ProjectFiles: tooltip = "Report generated for the whole project" elif self.__reportOption == self.SingleFile: tooltip = "Report generated for file: " + self.__reportFileName elif self.__reportOption == self.SingleBuffer: tooltip = "Report generated for unsaved file: " + \ self.__reportFileName else: tooltip = "" self.updatePylintTooltip.emit( tooltip ) return def showReport( self, lint, reportOption, fileName, uuid ): " Shows the pylint results " self.__removeAll() self.__noneLabel.hide() self.__report = lint self.__reportUUID = uuid self.__reportFileName = fileName self.__reportOption = reportOption showFileName = self.__shouldShowFileName( lint.errorMessages ) scoreLabel = self.__createScoreLabel( lint.score, lint.previousScore, showFileName, fileName ) self.__vLayout.addWidget( scoreLabel ) self.__widgets.append( scoreLabel ) if len( lint.errorMessages ) > 0: self.__addSectionSpacer() self.__addErrorsTable( lint.errorMessages, showFileName ) index = 0 for similarity in lint.similarities: self.__addSectionSpacer() self.__addSimilarity( similarity, "Similarity #" + str( index ) ) index += 1 for table in lint.tables: self.__addSectionSpacer() self.__addGenericTableTitle( table ) self.__addGenericTable( table ) self.bodyWidget.show() self.bodyWidget.ensureVisible( 0, 0, 0, 0 ) self.__reportShown = True self.__updateButtonsStatus() self.__updateTooltip() # It helps, but why do I have flickering? QApplication.processEvents() self.__resizeBodyFrame() return def __errorActivated( self, item, column ): " Handles the double click (or Enter) on the item " linePos = str( item.text( 1 ) ) if ":" in linePos: parts = linePos.split( ":" ) lineNumber = int( parts[ 0 ] ) pos = int( parts[ 1 ] ) else: lineNumber = int( linePos ) pos = 0 if self.__reportOption in [ self.SingleFile, self.DirectoryFiles, self.ProjectFiles ]: fileName = str( item.text( 0 ) ) else: # SingleBuffer if self.__reportFileName != "": if os.path.isabs( self.__reportFileName ): fileName = self.__reportFileName else: # Could be unsaved buffer, so try to search by the mainWindow = GlobalData().mainWindow widget = mainWindow.getWidgetByUUID( self.__reportUUID ) if widget is None: logging.error( "The unsaved buffer has been closed" ) return # The widget was found, so jump to the required editor = widget.getEditor() editor.gotoLine( lineNumber, pos ) editor.setFocus() return GlobalData().mainWindow.openFile( fileName, lineNumber, pos ) return def __resizeBodyFrame( self ): " Resizing the frame to occupy all available width " size = self.bodyWidget.maximumViewportSize() self.__bodyFrame.setMinimumWidth( size.width() - 16 ) self.__bodyFrame.setMinimumHeight( size.height() ) return def showEvent( self, showEv = None ): " Called when the widget is shown " self.__resizeBodyFrame() return def resizeEvent( self, resizeEv = None ): " Called when the main window gets resized " self.__resizeBodyFrame() return def onFileUpdated( self, fileName, uuid ): " Called when a buffer is saved or saved as " if not self.__reportShown: return if self.__reportUUID != uuid: return # Currently shown report is for the saved buffer # File name is expected being absolute self.__reportFileName = fileName self.updatePylintTooltip.emit( "Report generated for buffer saved as " + fileName ) return def __similarityActivated( self, item, column ): " Triggered when a similarity is activated " fileName = str( item.text( 0 ) ) lineNumber = int( item.text( 1 ) ) GlobalData().mainWindow.openFile( fileName, lineNumber ) return
class DHttpReplay(QtHelper.EnhancedQDialog, Logger.ClassLogger): """ Http replay dialog """ def __init__(self, parent=None, offlineMode=False): """ Constructor @param parent: @type parent: """ super(DHttpReplay, self).__init__(parent) self.offlineMode = offlineMode self.defaultIp = "127.0.0.1" self.defaultPort = "80" self.newTest = '' self.newTestExec = '' self.newInputs = [] self.requests = [] self.responses = [] self.defaultTemplates = DefaultTemplates.Templates() self.testType = None self.createDialog() self.createConnections() self.createActions() self.createToolbar() def createActions(self): """ Create qt actions """ self.openAction = QtHelper.createAction(self, "&Open", self.importTrace, icon=QIcon(":/folder_add.png"), tip='Open network trace.') self.exportTUAction = QtHelper.createAction( self, "&Test Unit", self.exportToTU, icon=QIcon(":/%s.png" % WWorkspace.TestUnit.TYPE), tip='Export to Test Unit') self.exportTSAction = QtHelper.createAction( self, "&Test Suite", self.exportToTS, icon=QIcon(":/%s.png" % WWorkspace.TestSuite.TYPE), tip='Export to Test Suite') self.cancelAction = QtHelper.createAction(self, "&Cancel", self.reject, tip='Cancel') menu = QMenu(self) menu.addAction(self.exportTUAction) menu.addAction(self.exportTSAction) self.exportToAction = QtHelper.createAction( self, "&Export to", self.exportToTU, icon=QIcon(":/%s.png" % WWorkspace.TestUnit.TYPE), tip='Export to tests') self.exportToAction.setMenu(menu) self.exportToAction.setEnabled(False) def createDialog(self): """ Create dialog """ self.dockToolbar = QToolBar(self) self.dockToolbar.setToolButtonStyle(Qt.ToolButtonTextBesideIcon) self.setWindowTitle(WINDOW_TITLE) self.resize(500, 400) self.ipEdit = QLineEdit(self.defaultIp) ipRegExpVal = QRegExpValidator(self) ipRegExp = QRegExp("\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}") ipRegExpVal.setRegExp(ipRegExp) self.ipEdit.setValidator(ipRegExpVal) self.portEdit = QLineEdit(self.defaultPort) self.portEdit.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed) validatorPort = QIntValidator(self) self.portEdit.setValidator(validatorPort) self.progressBar = QProgressBar(self) self.progressBar.setMaximum(100) self.progressBar.setProperty("value", 0) self.progressBar.setAlignment(Qt.AlignCenter) self.progressBar.setObjectName("progressBar") self.guiSikuliGroupBox = QGroupBox("") self.guiSikuliGroupBox.setFlat(True) self.automaticAdp = QRadioButton("Automatic") self.automaticAdp.setChecked(True) self.defaultAdp = QRadioButton("Default") self.genericAdp = QRadioButton("Generic") vbox = QHBoxLayout() vbox.addWidget(self.automaticAdp) vbox.addWidget(self.defaultAdp) vbox.addWidget(self.genericAdp) vbox.addStretch(1) self.guiSikuliGroupBox.setLayout(vbox) layout = QVBoxLayout() layout.addWidget(self.dockToolbar) layout.addSpacing(12) paramLayout = QGridLayout() paramLayout.addWidget(QLabel("Destination IP:"), 0, 0, Qt.AlignRight) paramLayout.addWidget(self.ipEdit, 0, 1) paramLayout.addWidget(QLabel("Destination Port:"), 1, 0, Qt.AlignRight) paramLayout.addWidget(self.portEdit, 1, 1) paramLayout.addWidget(QLabel(self.tr("Gui adapter selector:")), 2, 0, Qt.AlignRight) paramLayout.addWidget(self.guiSikuliGroupBox, 2, 1) layout.addLayout(paramLayout) self.logsEdit = QTextEdit() self.logsEdit.setReadOnly(True) self.logsEdit.setTextInteractionFlags(Qt.NoTextInteraction) layout.addSpacing(12) layout.addWidget(self.logsEdit) layout.addSpacing(12) layout.addWidget(self.progressBar) self.setLayout(layout) def createToolbar(self): """ Create toolbar """ self.dockToolbar.setObjectName("File toolbar") self.dockToolbar.addAction(self.openAction) self.dockToolbar.addSeparator() self.dockToolbar.addAction(self.exportToAction) self.dockToolbar.addSeparator() self.dockToolbar.setIconSize(QSize(16, 16)) def createConnections(self): """ Create qt connections """ pass def autoScrollOnTextEdit(self): """ Automatic scroll on text edit """ cursor = self.logsEdit.textCursor() cursor.movePosition(QTextCursor.End) self.logsEdit.setTextCursor(cursor) def strip_html(self, txt): """ Strip html """ if "<" in txt: txt = txt.replace('<', '<') if ">" in txt: txt = txt.replace('>', '>') return txt def addLogSuccess(self, txt): """ Add log success in the text edit """ self.logsEdit.insertHtml( "<span style='color:darkgreen'>%s</span><br />" % unicode(self.strip_html(txt))) self.autoScrollOnTextEdit() def addLogWarning(self, txt): """ Add log warning in the text edit """ self.logsEdit.insertHtml( "<span style='color:darkorange'>%s</span><br />" % unicode(self.strip_html(txt))) self.autoScrollOnTextEdit() def addLogError(self, txt): """ Add log error in the text edit """ self.logsEdit.insertHtml("<span style='color:red'>%s</span><br />" % unicode(self.strip_html(txt))) self.autoScrollOnTextEdit() def addLog(self, txt): """ Append log to the logsEdit widget """ self.logsEdit.insertHtml("%s<br />" % unicode(self.strip_html(txt))) self.autoScrollOnTextEdit() def importTrace(self): """ Import network trace """ self.logsEdit.clear() self.testType = None if not self.offlineMode: if not RCI.instance().isAuthenticated(): self.addLogWarning( txt="<< Connect to the test center in first!") QMessageBox.warning(self, "Import", "Connect to the test center in first!") return self.exportToAction.setEnabled(False) self.newTest = '' self.progressBar.setMaximum(100) self.progressBar.setValue(0) if sys.version_info > (3, ): fileName = QFileDialog.getOpenFileName( self, self.tr("Open File"), "", "Network dump (*.cap;*.pcap;*.pcapng)") else: fileName = QFileDialog.getOpenFileName(self, self.tr("Open File"), "", "Network dump (*.cap)") # new in v18 to support qt5 if QtHelper.IS_QT5: _fileName, _type = fileName else: _fileName = fileName # end of new if not _fileName: return if sys.version_info < (3, ): extension = str(_fileName).rsplit(".", 1)[1] if not (extension == "cap"): self.addLogError(txt="<< File not supported %s" % _fileName) QMessageBox.critical(self, "Open", "File not supported") return _fileName = str(_fileName) capName = _fileName.rsplit("/", 1)[1] self.addLogSuccess(txt=">> Reading the file %s" % _fileName) if sys.version_info > (3, ): self.readFileV2(fileName=_fileName) else: self.readFile(fileName=_fileName) def exportToTS(self): """ Export to test suite """ self.testType = TS self.exportToTest(TS=True, TU=False) def exportToTU(self): """ Export to test unit """ self.testType = TU self.exportToTest(TS=False, TU=True) def searchHTTP(self): """ Search HTTP module in assistant """ # modules accessor ret = "SutAdapters" if self.automaticAdp.isChecked(): isGeneric = WWorkspace.Helper.instance().isGuiGeneric(name="GUI") if isGeneric: ret = "SutAdapters.Generic" elif self.defaultAdp.isChecked(): return ret elif self.genericAdp.isChecked(): ret = "SutAdapters.Generic" else: pass return ret def exportToTest(self, TS=True, TU=False): """ Export to test """ if not RCI.instance().isAuthenticated(): self.addLogWarning(txt="<< Connect to the test center in first!") QMessageBox.warning(self, "Import", "Connect to the test center in first!") return if TS: self.newTest = self.defaultTemplates.getTestDefinitionAuto() self.newTestExec = self.defaultTemplates.getTestExecutionAuto() if TU: self.newTest = self.defaultTemplates.getTestUnitDefinitionAuto() destIp = str(self.ipEdit.text()) destPort = str(self.portEdit.text()) self.newInputs = [] self.newInputs.append({ 'type': 'self-ip', 'name': 'BIND_IP', 'description': '', 'value': '0.0.0.0', 'color': '' }) self.newInputs.append({ 'type': 'int', 'name': 'BIND_PORT', 'description': '', 'value': '0', 'color': '' }) self.newInputs.append({ 'type': 'str', 'name': 'DEST_IP', 'description': '', 'value': '%s' % destIp, 'color': '' }) self.newInputs.append({ 'type': 'int', 'name': 'DEST_PORT', 'description': '', 'value': '%s' % destPort, 'color': '' }) self.newInputs.append({ 'type': 'bool', 'name': 'DEBUG', 'description': '', 'value': 'False', 'color': '' }) self.newInputs.append({ 'type': 'float', 'name': 'TIMEOUT', 'description': '', 'value': '5.0', 'color': '' }) adps = """self.ADP_HTTP = %s.HTTP.Client(parent=self, bindIp=input('BIND_IP'), bindPort=input('BIND_PORT'), destinationIp=input('DEST_IP'), destinationPort=input('DEST_PORT'), debug=input('DEBUG'))""" % self.searchHTTP( ) # prepare steps steps = [] j = 0 for i in xrange(len(self.requests)): j = i + 1 if sys.version_info > (3, ): # python3 support (source, dest, source_port, dest_port, buf_req, reqDecoded) = self.requests[i] http_method = str(reqDecoded['method'], 'utf8') http_status = 'no' http_reason = '' else: http_method = self.requests[i]['tcp-object'].method http_status = 'no' http_reason = '' try: if sys.version_info > (3, ): # python3 support (sourceRsp, destRsp, sourcePortRsp, destPortRsp, bufReqRsp, reqDecodedRsp) = self.responses[i] http_status = str(reqDecodedRsp['code']) http_reason = str(reqDecodedRsp['phrase'], 'utf8') else: http_status = self.responses[i]['tcp-object'].status http_reason = self.responses[i]['tcp-object'].reason except Exception as e: print(e) steps.append( 'self.step%s = self.addStep(expected="%s %s response", description="send %s request", summary="send %s request")' % (j, http_status, http_reason, http_method, http_method)) tests = [] for i in xrange(len(self.requests)): j = i + 1 if sys.version_info > (3, ): # python3 support (source, dest, source_port, dest_port, buf_req, reqDecoded) = self.requests[i] tests.append("# request %s" % j) tests.append('self.step%s.start()' % j) if sys.version_info > (3, ): # python3 support lines_req = buf_req.splitlines() else: lines_req = self.requests[i]['tcp-data'].splitlines() if sys.version_info > (3, ): # python3 support tests.append('rawHttp = [%s]' % lines_req[0].replace(b'"', b'\\"')) else: tests.append('rawHttp = ["%s"]' % lines_req[0].replace(b'"', b'\\"')) for lreq in lines_req[1:]: if sys.version_info > (3, ): # python3 support tests.append('rawHttp.append(%s)' % lreq.replace(b'"', b'\\"')) else: tests.append('rawHttp.append("%s")' % lreq.replace(b'"', b'\\"')) tests.append('') tests.append( 'req_tpl = self.ADP_HTTP.constructTemplateRequest(rawHttp=rawHttp)' ) tests.append('req = self.ADP_HTTP.sendRequest(tpl=req_tpl)') try: tests.append('') if sys.version_info > (3, ): # python3 support (sourceRsp, destRsp, sourcePortRsp, destPortRsp, bufReqRsp, reqDecodedRsp) = self.responses[i] lines_res = bufReqRsp.splitlines() else: lines_res = self.responses[i]['tcp-data'].splitlines() if sys.version_info > (3, ): # python3 support tests.append('rawHttpRsp = [%s]' % lines_res[0].replace(b"'", b"\\'")) else: tests.append('rawHttpRsp = ["%s"]' % lines_res[0].replace(b'"', b'\\"')) for lres in lines_res[1:]: if sys.version_info > (3, ): # python3 support tests.append('rawHttpRsp.append(%s)' % lres.replace(b"'", b"\\'")) else: tests.append('rawHttpRsp.append("%s")' % lres.replace(b'"', b'\\"')) except Exception as e: self.error("unable to append response: %s" % e) tests.append( 'rsp_tpl = self.ADP_HTTP.constructTemplateResponse(rawHttp=rawHttpRsp)' ) tests.append( "rsp = self.ADP_HTTP.hasReceivedResponse(expected=rsp_tpl, timeout=input('TIMEOUT'))" ) tests.append('if rsp is None:') tests.append( '\tself.step%s.setFailed(actual="incorrect response")' % j) tests.append('else:') tests.append('\tself.step%s.setPassed(actual="ok")' % j) tests.append('') if TS: init = """self.ADP_HTTP.connect() connected = self.ADP_HTTP.isConnected( timeout=input('TIMEOUT') ) if not connected: self.abort( 'unable to connect to the tcp port %s' ) """ % str(self.portEdit.text()) if TU: init = """self.ADP_HTTP.connect() connected = self.ADP_HTTP.isConnected( timeout=input('TIMEOUT') ) if not connected: self.abort( 'unable to connect to the tcp port %s' ) """ % str(self.portEdit.text()) if TS: cleanup = """self.ADP_HTTP.disconnect() disconnected = self.ADP_HTTP.isDisconnected( timeout=input('TIMEOUT') ) if not disconnected: self.error( 'unable to disconnect from the tcp port %s' ) """ % str(self.portEdit.text()) if TU: cleanup = """self.ADP_HTTP.disconnect() disconnected = self.ADP_HTTP.isDisconnected( timeout=input('TIMEOUT') ) if not disconnected: self.error( 'unable to disconnect from the tcp port %s' ) """ % str(self.portEdit.text()) self.newTest = self.newTest.replace( "<<PURPOSE>>", 'self.setPurpose(purpose="Replay HTTP")') self.newTest = self.newTest.replace("<<ADPS>>", adps) if TS: self.newTest = self.newTest.replace("<<STEPS>>", '\n\t\t'.join(steps)) if TU: self.newTest = self.newTest.replace("<<STEPS>>", '\n\t'.join(steps)) self.newTest = self.newTest.replace("<<INIT>>", init) self.newTest = self.newTest.replace("<<CLEANUP>>", cleanup) if TS: self.newTest = self.newTest.replace("<<TESTS>>", '\n\t\t'.join(tests)) if TU: self.newTest = self.newTest.replace("<<TESTS>>", '\n\t'.join(tests)) self.accept() def decodeHttpRequest(self, data): """ Decode http request Content chunked not yet implemented """ http = {"type": "request"} lines = data.splitlines() try: request_line = lines[0] except Exception: self.error("unable to decode http request: %s" % lines) return None try: http["method"] = request_line.split(b" ", 2)[0] http["uri"] = request_line.split(b" ", 2)[1] http["version"] = request_line.split(b" ", )[2] except Exception: self.error( "unable to decode status code in the http response: %s" % request_line) return None http["body"] = data.split(b"\r\n\r\n")[1] headers = [] contentLenght = 0 contentChunked = False for hdr in data.split(b"\r\n\r\n")[0].splitlines()[1:]: if len(hdr): k, v = hdr.split(b":", 1) if k.lower() == b"content-length": contentLenght = int(v) if k.lower() == b"transfer-encoding": if v.lowert() == b"chunked": contentChunked = True headers.append(hdr) http["headers"] = headers if len(http["body"]) != contentLenght: return None # need more data return http def decodeHttpResponse(self, data): """ Decode http response without body """ http = {"type": "response"} lines = data.splitlines() try: status_line = lines[0] except Exception: self.error("unable to decode http response: %s" % lines) return None try: http["code"] = int(status_line.split(b" ")[1]) http["phrase"] = status_line.split(b" ", 2)[2] except Exception: self.error( "unable to decode status code in the http response: %s" % status_line) return None http["headers"] = lines[1:] return http def readFileV2(self, fileName): """ Read pcap file Support pcap-ng too """ fd = open(fileName, 'rb') fileFormat, fileHead = PcapParse.extractFormat(fd) if fileFormat == PcapParse.FileFormat.PCAP: self.trace("pcap file detected") pcapFile = PcapReader.PcapFile(fd, fileHead).read_packet self.readFilePacket(pcapFile=pcapFile) elif fileFormat == PcapParse.FileFormat.PCAP_NG: self.trace("pcap-png file detected") pcapFile = PcapngReader.PcapngFile(fd, fileHead).read_packet self.readFilePacket(pcapFile=pcapFile) else: self.addLogError(txt="<< Error to open the network trace") self.error('unable to open the network trace: file format = %s' % fileFormat) QMessageBox.critical(self, "Import", "File not supported") def __readRequest(self, buffer, data, request, output): """ Read request """ buffer += data if b'\r\n\r\n' in data: reqDecoded = self.decodeHttpRequest(data=buffer) if reqDecoded is not None: output.append(request + (reqDecoded, )) buffer = b'' else: print("need more data: decode request failed") else: print("need more data, no body separator detected on request") def readFilePacket(self, pcapFile): """ Read file packet by packet """ ip_expected = str(self.ipEdit.text()) port_expected = int(self.portEdit.text()) # read packet) packets = pcapFile() ethernetPackets = list(packets) self.addLogSuccess(txt="<< Number of packets detected: %s " % len(ethernetPackets)) # extract tcp packet according to the expected ip and port tcpPacketsSent = [] tcpPacketsRecv = [] i = 1 self.progressBar.setMaximum(len(ethernetPackets)) self.progressBar.setValue(0) for pkt in ethernetPackets: self.progressBar.setValue(i) i += 1 pktDecoded = PcapParse.decodePacket(pkt, getTcp=True, getUdp=False) if pktDecoded is not None: (source, dest, source_port, dest_port, data) = pktDecoded # skip when no data exists if dest == ip_expected and int(dest_port) == int( port_expected) and len(data) > 0: tcpPacketsSent.append(pktDecoded) if source == ip_expected and int(source_port) == int( port_expected) and len(data) > 0: tcpPacketsRecv.append(pktDecoded) self.addLogSuccess(txt="<< Number of TCP packets sent: %s " % len(tcpPacketsSent)) self.addLogSuccess(txt="<< Number of TCP packets received: %s " % len(tcpPacketsRecv)) # decode https requests self.requests = [] buf_req = b'' i = 1 self.progressBar.setMaximum(len(tcpPacketsSent)) self.progressBar.setValue(0) # decode the complete packet for req in tcpPacketsSent: self.progressBar.setValue(i) i += 1 (source, dest, source_port, dest_port, data) = req if buf_req: buf_req += data if b'\r\n\r\n' in data: reqDecoded = self.decodeHttpRequest(data=buf_req) if reqDecoded is not None: self.requests.append((source, dest, source_port, dest_port, buf_req, reqDecoded)) buf_req = b'' else: if isRequest(data): buf_req += data if b'\r\n\r\n' in data: reqDecoded = self.decodeHttpRequest(data=buf_req) if reqDecoded is not None: self.requests.append( (source, dest, source_port, dest_port, buf_req, reqDecoded)) buf_req = b'' self.addLogSuccess(txt="<< Number of HTTP requests extracted: %s " % len(self.requests)) # decode https response self.responses = [] buf_rsp = b'' i = 1 self.progressBar.setMaximum(len(tcpPacketsRecv)) self.progressBar.setValue(0) # decode just headers for response for req in tcpPacketsRecv: self.progressBar.setValue(i) i += 1 (source, dest, source_port, dest_port, data) = req if buf_rsp: buf_rsp += data # try to decode response without body if b'\r\n\r\n' in data: rspDecoded = self.decodeHttpResponse(data=buf_rsp) if rspDecoded is not None: self.responses.append((source, dest, source_port, dest_port, buf_rsp, rspDecoded)) buf_rsp = b'' else: # is http response ? if data.startswith(b'HTTP/'): buf_rsp += data if b'\r\n\r\n' in data: rspDecoded = self.decodeHttpResponse(data=buf_rsp) if rspDecoded is not None: self.responses.append( (source, dest, source_port, dest_port, buf_rsp, rspDecoded)) buf_rsp = b'' self.addLogSuccess(txt="<< Number of HTTP responses extracted: %s " % len(self.responses)) if self.requests: self.addLogSuccess("<< Read the file finished with success!") self.addLogWarning( "<< Click on the export button to generate the test!") self.exportToAction.setEnabled(True) else: self.addLogWarning("<< No http extracted!") def readFile(self, fileName): """ Read the file passed as argument Old function with dtpkt and python2.7 """ self.requests = [] self.responses = [] ip_expected = socket.inet_aton(str(self.ipEdit.text())) port_expected = str(self.portEdit.text()) try: f = open(fileName, 'rb') pcap = dpkt.pcap.Reader(f) tot_pkts = len(list(pcap)) except Exception as e: self.addLogError(txt="<< Error to open the network trace") self.error('unable to open the network trace: %s' % str(e)) QMessageBox.critical(self, "Import", "File not supported") return else: self.addLogSuccess(txt="<< Total packets detected: %s " % tot_pkts) self.progressBar.setMaximum(tot_pkts) # decode http request i = 1 buf_req = '' for ts, buf in pcap: self.progressBar.setValue(i) i += 1 # read ethernet layer eth = dpkt.ethernet.Ethernet(buf) if eth.type == dpkt.ethernet.ETH_TYPE_IP: # continue with ip decoding layer ip = eth.data if ip.dst == ip_expected: ip_layer = (ip.src, ip.dst) if ip.p == dpkt.ip.IP_PROTO_TCP: tcp = ip.data if tcp.dport == int(port_expected) and len( tcp.data) > 0: tcp_layer = (tcp.sport, tcp.dport) buf_req += tcp.data try: http_req = dpkt.http.Request(buf_req) except dpkt.dpkt.NeedData as e: pass except dpkt.UnpackError as e: pass else: self.requests.append({ 'ip-src': ip.src, 'ip-dst': ip.dst, 'port-src': tcp.sport, 'port-dst': tcp.dport, 'tcp-data': buf_req, 'tcp-object': http_req }) self.addLogWarning( txt="<< %s http request(s) extracted" % len(self.requests)) buf_req = '' # decode http responses i = 1 self.progressBar.setValue(0) for ts, buf in pcap: self.progressBar.setValue(i) i += 1 # read ethernet layer eth = dpkt.ethernet.Ethernet(buf) if eth.type == dpkt.ethernet.ETH_TYPE_IP: # continue with ip decoding layer ip = eth.data if ip.src == ip_expected: ip_layer = (ip.src, ip.dst) if ip.p == dpkt.ip.IP_PROTO_TCP: tcp = ip.data if tcp.sport == int(port_expected) and len( tcp.data) > 0: tcp_layer = (tcp.sport, tcp.dport) if (tcp.data).startswith('HTTP/'): try: new_res = "%s\r\n\r\n" % ( tcp.data).splitlines()[0] http_res = dpkt.http.Response(new_res) except dpkt.dpkt.NeedData as e: pass except dpkt.UnpackError as e: pass else: self.responses.append({ 'ip-src': ip.src, 'ip-dst': ip.dst, 'port-src': tcp.sport, 'port-dst': tcp.dport, 'tcp-data': new_res, 'tcp-object': http_res }) self.addLogWarning( txt= "<< %s http response(s) extracted" % len(self.responses)) if self.requests: self.addLogSuccess("<< File decoded with success!") self.addLogWarning( "<< Click on the export button to generate the test!") self.exportToAction.setEnabled(True) else: self.addLogWarning("<< No http extracted!")
class SafecastDockWidget(QtGui.QDockWidget, FORM_CLASS): closingPlugin = pyqtSignal() def __init__(self, parent=None): """Plugin constructor. :param parent: parent class or None """ super(SafecastDockWidget, self).__init__(parent) self.setupUi(self) # connect ui with functions self._createToolbarAndConnect() # load internal styles self._initStyles() # list of layers (must be defined, otherwise SafecastLayer is # not returned by getActiveLayer() self._layers = [] # settings self._settings = QSettings() def _createToolbarAndConnect(self): """Create toolbar and connect tools.""" self.signalMapper = QSignalMapper(self) self._mToolbar = QToolBar(self) self._mToolbar.addAction(self.actionImport) self._mToolbar.addAction(self.actionSave) self._mToolbar.addSeparator() self._mToolbar.addAction(self.actionSelect) self._mToolbar.addAction(self.actionDeselect) self._mToolbar.addSeparator() self._mToolbar.addAction(self.actionDelete) self.actionSave.setEnabled(False) self.actionSelect.setEnabled(False) self.actionDeselect.setEnabled(False) self.actionDelete.setEnabled(False) self.toolbarLayout.insertWidget(0, self._mToolbar) self.connect(self.actionImport, SIGNAL("triggered()"), self.onLoad) self.connect(self.actionSave, SIGNAL("triggered()"), self.onSave) self.connect(self.actionSelect, SIGNAL("triggered()"), self.onSelect) self.connect(self.actionDeselect, SIGNAL("triggered()"), self.onDeselect) self.connect(self.actionDelete, SIGNAL("triggered()"), self.onDelete) self.connect(self.styleButton, SIGNAL("clicked()"), self.onStyle) def _initStyles(self): """Define internal styles and polulates items in combobox.""" self._styles = [{ 'name': '0.08 - 5.00 microSv/h', 'file': 'normal' }, { 'name': '0.05 - 200.00 microSv/h', 'file': 'high' }] for item in self._styles: self.styleBox.addItem(item['name']) self.styleBox.setCurrentIndex(0) def stylePath(self): """Get style path (when local QML files are located). :return: path given as a string """ styleName = self._styles[self.styleBox.currentIndex()]['file'] stylePath = os.path.join(os.path.dirname(__file__), "styles", styleName + '.qml') if not os.path.isfile(stylePath): raise SafecastError( self.tr("Style '{}' not found").format(styleName)) return stylePath def closeEvent(self, event): """Close plugin. :param event: related event """ self.closingPlugin.emit() event.accept() def onLoad(self): """Load LOG file as a new QGIS point map layer. Input LOG file is given by user via open dialog. Loaded point layer is symbolized using default internal style. Layer is inserted into layer tree (TOC) on first position. Shows error dialog on failure. """ # get last used directory path from settings sender = '{}-lastUserFilePath'.format(self.sender().objectName()) lastPath = self._settings.value(sender, '') filePath = QFileDialog.getOpenFileName( self, self.tr("Load Safecast LOG file"), lastPath, self.tr("LOG file (*.LOG)")) if not filePath: # action canceled return filePath = os.path.normpath(filePath) try: # create reader for input data reader = SafecastReader(filePath) # create new QGIS map layer (read-only) layer = SafecastLayer(filePath) # load data by reader into new layer and set style layer.load(reader) layer.loadNamedStyle(self.stylePath()) # add map layer to the canvas (do not add into TOC) QgsMapLayerRegistry.instance().addMapLayer(layer, False) # force register layer in TOC as a first item QgsProject.instance().layerTreeRoot().insertLayer(0, layer) # select this layer (this must be done manually since we # are inserting item into layer tree) iface.legendInterface().setCurrentLayer(layer) # collapse layer iface.legendInterface().setLayerExpanded(layer, False) # register new layer in plugin's internal list self._layers.append(layer) except (SafecastError, SafecastReaderError) as e: # show error message on failure iface.messageBar().clearWidgets() QMessageBox.critical( None, self.tr("Error"), self.tr( "Failed to load input file '{0}'.\n\nDetails: {1}").format( filePath, e), QMessageBox.Abort) return # enable save, select, style buttons when new layer is # successfully loaded if not self.actionSave.isEnabled(): self.actionSave.setEnabled(True) self.actionSelect.setEnabled(True) self.styleButton.setEnabled(True) # zoom to the new layer (already selected) iface.zoomToActiveLayer() # remember directory path self._settings.setValue(sender, os.path.dirname(filePath)) def onStyle(self): """Apply new style for currently selected layer. Show error message dialog on failure. """ layer = self.getActiveLayer() if not layer: # no layer is currently selected, nothing to do return # apply new style on currently selected layer try: layer.loadNamedStyle(self.stylePath()) except SafecastError as e: # print error message on failure QMessageBox.critical( None, self.tr("Error"), self.tr("Failed to apply style: {0}").format(e), QMessageBox.Abort) # If caching is enabled, a simple canvas refresh might not be sufficient # to trigger a redraw and you must clear the cached image for the layer if iface.mapCanvas().isCachingEnabled(): layer.setCacheImage(None) else: iface.mapCanvas().refresh() iface.legendInterface().refreshLayerSymbology(layer) def onSave(self): """Save currently selected map layer as new LOG file. Show error message dialog on failure. """ # get currently selected layer layer = self.getActiveLayer() # overwrite check disabled because of possible missing file extension filePath = QFileDialog.getSaveFileName( self, self.tr("Save layer as new LOG file"), layer.path() if layer else ".", self.tr("LOG file (*.LOG)"), QFileDialog.DontConfirmOverwrite) if not filePath: # action canceled return if not filePath.upper().endswith('.LOG'): # add missing extension if missing filePath += '.LOG' if os.path.exists(filePath): # check if the file already exists reply = QMessageBox.question( self, self.tr("Overwrite?"), self.tr("File {} already exists. " "Do you want to overwrite it?.").format(filePath), QtGui.QMessageBox.Yes, QtGui.QMessageBox.No) if reply != QtGui.QMessageBox.Yes: return if layer: try: # export layer to LOG file layer.save(filePath) except SafecastWriterError as e: QMessageBox.critical( None, self.tr("Error"), self.tr("Failed to save LOG file: {0}").format(e), QMessageBox.Abort) def onSelect(self): """Select features action.""" layer = self.getActiveLayer() if not layer: # disable select button if no layer selected self.actionSelect.setEnabled(False) return if not self.actionDeselect.isEnabled(): # enable deselect/delete buttons if features selected self.actionDeselect.setEnabled(True) self.actionDelete.setEnabled(True) iface.actionSelect().trigger() def onDeselect(self): """Deselect features action.""" layer = self.getActiveLayer() if layer: # deselect features manually (there is no trigger # available) if requested layer.setSelectedFeatures([ feat.id() for feat in layer.selectedFeaturesIterator() if feat.id() < 0 ]) # disable deselect/delete buttons self.actionDeselect.setEnabled(False) self.actionDelete.setEnabled(False) # select -> pan iface.actionPan().trigger() def onDelete(self): """Delete selected features. Ask user to confirm this action. """ layer = self.getActiveLayer() if not layer: return count = layer.selectedFeatureCount() if count > 0: # ask if features should be really deleted (no undo avaialble) reply = QMessageBox.question( self, self.tr("Delete?"), self.tr("Do you want to delete {} selected features? " "This operation cannot be reverted.").format(count), QtGui.QMessageBox.Yes, QtGui.QMessageBox.No) if reply == QtGui.QMessageBox.Yes: # delete selected features from currently selected layer layer.setReadOnly(False) iface.actionToggleEditing().trigger() iface.actionDeleteSelected().trigger() iface.actionSaveActiveLayerEdits().trigger() iface.actionToggleEditing().trigger() layer.setReadOnly(True) else: # inform user - no features selected, nothing to be deleted iface.messageBar().pushMessage( self.tr("Info"), self.tr("No features selected. Nothing to be deleled."), level=QgsMessageBar.INFO, duration=3) # disable deselect/delete buttons self.actionDeselect.setEnabled(False) self.actionDelete.setEnabled(False) def getActiveLayer(self): """Get currently selected (active) layer. :return: layer instance """ try: layer = iface.activeLayer() if not layer: raise SafecastError(self.tr("No layer loaded or selected")) except SafecastError as e: iface.messageBar().pushMessage( self.tr("Info"), self.tr("No active layer available."), level=QgsMessageBar.INFO, duration=3) return None return layer
class UserSettingsDialog(QMainWindow): """ A User Settings/Defaults dialog. """ MAC_UNIFIED = True def __init__(self, parent=None, **kwargs): QMainWindow.__init__(self, parent, **kwargs) self.setWindowFlags(Qt.Dialog) self.setWindowModality(Qt.ApplicationModal) self.layout().setSizeConstraint(QVBoxLayout.SetFixedSize) self.__macUnified = sys.platform == "darwin" and self.MAC_UNIFIED self._manager = BindingManager(self, submitPolicy=BindingManager.AutoSubmit) self.__loop = None self.__settings = config.settings() self.__setupUi() def __setupUi(self): """Set up the UI. """ if self.__macUnified: self.tab = QToolBar() self.addToolBar(Qt.TopToolBarArea, self.tab) self.setUnifiedTitleAndToolBarOnMac(True) # This does not seem to work self.setWindowFlags(self.windowFlags() & \ ~Qt.MacWindowToolBarButtonHint) self.tab.actionTriggered[QAction].connect( self.__macOnToolBarAction ) central = QStackedWidget() central.setSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed) else: self.tab = central = QTabWidget(self) # Add a close button to the bottom of the dialog # (to satisfy GNOME 3 which shows the dialog without a title bar). container = container_widget_helper() container.layout().addWidget(central) buttonbox = QDialogButtonBox(QDialogButtonBox.Close) buttonbox.rejected.connect(self.close) container.layout().addWidget(buttonbox) self.setCentralWidget(container) self.stack = central # General Tab tab = QWidget() self.addTab(tab, self.tr("General"), toolTip=self.tr("General Options")) form = QFormLayout() tab.setSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed) nodes = QWidget(self, objectName="nodes") nodes.setLayout(QVBoxLayout()) nodes.layout().setContentsMargins(0, 0, 0, 0) cb_anim = QCheckBox( self.tr("Enable node animations"), objectName="enable-node-animations", toolTip=self.tr("Enable shadow and ping animations for node " "items in the scheme.") ) self.bind(cb_anim, "checked", "schemeedit/enable-node-animations") nodes.layout().addWidget(cb_anim) form.addRow(self.tr("Nodes"), nodes) links = QWidget(self, objectName="links") links.setLayout(QVBoxLayout()) links.layout().setContentsMargins(0, 0, 0, 0) cb_show = QCheckBox( self.tr("Show channel names between widgets"), objectName="show-channel-names", toolTip=self.tr("Show source and sink channel names " "over the links.") ) self.bind(cb_show, "checked", "schemeedit/show-channel-names") links.layout().addWidget(cb_show) form.addRow(self.tr("Links"), links) quickmenu = QWidget(self, objectName="quickmenu-options") quickmenu.setLayout(QVBoxLayout()) quickmenu.layout().setContentsMargins(0, 0, 0, 0) cb1 = QCheckBox(self.tr("On double click"), toolTip=self.tr("Open quick menu on a double click " "on an empty spot in the canvas")) cb2 = QCheckBox(self.tr("On right click"), toolTip=self.tr("Open quick menu on a right click " "on an empty spot in the canvas")) cb3 = QCheckBox(self.tr("On space key press"), toolTip=self.tr("On Space key press while the mouse" "is hovering over the canvas.")) cb4 = QCheckBox(self.tr("On any key press"), toolTip=self.tr("On any key press while the mouse" "is hovering over the canvas.")) self.bind(cb1, "checked", "quickmenu/trigger-on-double-click") self.bind(cb2, "checked", "quickmenu/trigger-on-right-click") self.bind(cb3, "checked", "quickmenu/trigger-on-space-key") self.bind(cb4, "checked", "quickmenu/trigger-on-any-key") quickmenu.layout().addWidget(cb1) quickmenu.layout().addWidget(cb2) quickmenu.layout().addWidget(cb3) quickmenu.layout().addWidget(cb4) form.addRow(self.tr("Open quick menu on"), quickmenu) startup = QWidget(self, objectName="startup-group") startup.setLayout(QVBoxLayout()) startup.layout().setContentsMargins(0, 0, 0, 0) cb_splash = QCheckBox(self.tr("Show splash screen"), self, objectName="show-splash-screen") cb_welcome = QCheckBox(self.tr("Show welcome screen"), self, objectName="show-welcome-screen") self.bind(cb_splash, "checked", "startup/show-splash-screen") self.bind(cb_welcome, "checked", "startup/show-welcome-screen") startup.layout().addWidget(cb_splash) startup.layout().addWidget(cb_welcome) form.addRow(self.tr("On startup"), startup) toolbox = QWidget(self, objectName="toolbox-group") toolbox.setLayout(QVBoxLayout()) toolbox.layout().setContentsMargins(0, 0, 0, 0) exclusive = QCheckBox(self.tr("Only one tab can be open at a time")) self.bind(exclusive, "checked", "mainwindow/toolbox-dock-exclusive") toolbox.layout().addWidget(exclusive) form.addRow(self.tr("Tool box"), toolbox) tab.setLayout(form) # Output Tab tab = QWidget() self.addTab(tab, self.tr("Output"), toolTip="Output Redirection") form = QFormLayout() box = QWidget(self, objectName="streams") layout = QVBoxLayout() layout.setContentsMargins(0, 0, 0, 0) cb1 = QCheckBox(self.tr("Standard output")) cb2 = QCheckBox(self.tr("Standard error")) self.bind(cb1, "checked", "output/redirect-stdout") self.bind(cb2, "checked", "output/redirect-stderr") layout.addWidget(cb1) layout.addWidget(cb2) box.setLayout(layout) form.addRow(self.tr("Redirect output"), box) box = QWidget() layout = QVBoxLayout() layout.setContentsMargins(0, 0, 0, 0) combo = QComboBox() combo.addItems([self.tr("Critical"), self.tr("Error"), self.tr("Warn"), self.tr("Info"), self.tr("Debug")]) cb = QCheckBox(self.tr("Show output on 'Error'"), objectName="focus-on-error") self.bind(combo, "currentIndex", "logging/level") self.bind(cb, "checked", "output/show-on-error") layout.addWidget(combo) layout.addWidget(cb) box.setLayout(layout) form.addRow(self.tr("Logging"), box) box = QWidget() layout = QVBoxLayout() layout.setContentsMargins(0, 0, 0, 0) cb1 = QCheckBox(self.tr("Stay on top"), objectName="stay-on-top") cb2 = QCheckBox(self.tr("Dockable"), objectName="output-dockable") self.bind(cb1, "checked", "output/stay-on-top") self.bind(cb2, "checked", "output/dockable") layout.addWidget(cb1) layout.addWidget(cb2) box.setLayout(layout) form.addRow(self.tr("Output window"), box) box = QWidget() layout = QVBoxLayout() layout.setContentsMargins(0, 0, 0, 0) cb1 = QCheckBox(self.tr("Open in external browser"), objectName="open-in-external-browser") cb2 = QCheckBox(self.tr("Stay on top"), objectName="help-stay-on-top") cb3 = QCheckBox(self.tr("Dockable"), objectName="help-dockable") self.bind(cb1, "checked", "help/open-in-external-browser") self.bind(cb2, "checked", "help/stay-on-top") self.bind(cb3, "checked", "help/dockable") layout.addWidget(cb1) layout.addWidget(cb2) layout.addWidget(cb3) box.setLayout(layout) form.addRow(self.tr("Help window"), box) tab.setLayout(form) # Categories Tab tab = QWidget() layout = QVBoxLayout() view = QListView() from .. import registry reg = registry.global_registry() model = QStandardItemModel() settings = QSettings() for cat in reg.categories(): item = QStandardItem() item.setText(cat.name) item.setCheckable(True) visible, _ = category_state(cat, settings) item.setCheckState(Qt.Checked if visible else Qt.Unchecked) model.appendRow([item]) view.setModel(model) layout.addWidget(view) tab.setLayout(layout) model.itemChanged.connect( lambda item: save_category_state( reg.category(str(item.text())), _State(item.checkState() == Qt.Checked, -1), settings ) ) self.addTab(tab, "Categories") if self.__macUnified: # Need some sensible size otherwise mac unified toolbar 'takes' # the space that should be used for layout of the contents self.adjustSize() def addTab(self, widget, text, toolTip=None, icon=None): if self.__macUnified: action = QAction(text, self) if toolTip: action.setToolTip(toolTip) if icon: action.setIcon(toolTip) action.setData(len(self.tab.actions())) self.tab.addAction(action) self.stack.addWidget(widget) else: i = self.tab.addTab(widget, text) if toolTip: self.tab.setTabToolTip(i, toolTip) if icon: self.tab.setTabIcon(i, icon) def keyPressEvent(self, event): if event.key() == Qt.Key_Escape: self.hide() self.deleteLater() def bind(self, source, source_property, key, transformer=None): target = UserDefaultsPropertyBinding(self.__settings, key) source = PropertyBinding(source, source_property) source.set(target.get()) self._manager.bind(target, source) def commit(self): self._manager.commit() def revert(self): self._manager.revert() def reset(self): for target, source in self._manager.bindings(): try: source.reset() except NotImplementedError: # Cannot reset. pass except Exception: log.error("Error reseting %r", source.propertyName, exc_info=True) def exec_(self): self.__loop = QEventLoop() self.show() status = self.__loop.exec_() self.__loop = None return status def hideEvent(self, event): QMainWindow.hideEvent(self, event) if self.__loop is not None: self.__loop.exit(0) self.__loop = None def __macOnToolBarAction(self, action): index, _ = action.data().toInt() self.stack.setCurrentIndex(index)
class NodeWindow(QMainWindow): def __init__(self, data, scheme, parent=None): super(NodeWindow, self).__init__(parent) self.pathWidget = PathWidget(self.openWidgetByPath, data.path()) self.setStatusBar(self.pathWidget) # layout_set_sm_and_mrg(self.layout) self.cachedWidgets = {} self.currentStructuredWidget = None self.stacked = QStackedWidget(self) self.setCentralWidget(self.stacked) self.data, self.scheme = data, scheme self.data.add_set_notify(self.change_caption) self.toolbar = QToolBar() self.toolbar.addActions((self.parent().actionSave,self.parent().actionSaveAs,)) self.addToolBar(self.toolbar) self.setUnifiedTitleAndToolBarOnMac(True) self.messageBoxChanged = None self.reallyQuit = False self.change_caption() if "ExcelScheme" in self.scheme.get_meta(): actionExcelExport = QAction("Export to excel", self) self.toolbar.addAction(actionExcelExport) actionExcelExport.triggered.connect(self.excel_export) actionExcelMerge = QAction("Merge from excel", self) actionExcelMerge.triggered.connect(self.excel_import) self.toolbar.addAction(actionExcelMerge) self.tree_widget = DataTreeWidget(self.data, self) dock = QDockWidget(self) dock.setWidget(self.tree_widget) self.addDockWidget(Qt.LeftDockWidgetArea, dock) self.tree_widget.pathChanged.connect(self._open_widget_by_path) self.openWidgetByPath(Path()) def change_caption(self): changed = "" if self.data.changed: changed = "* " self.setWindowTitle("{} {}".format(changed, self.get_window_caption())) def get_window_caption(self): return os.path.basename(self.parent().save_filename or "New Data") def openWidgetByPath(self, path): self._open_widget_by_path(path) self.tree_widget.pathChange(path) def _open_widget_by_path(self, path): # #fixme # try: if path in self.cachedWidgets: # if self.currentStructuredWidget: # self.currentStructuredWidget.hide() self.currentStructuredWidget = self.cachedWidgets[path] self.stacked.setCurrentWidget(self.currentStructuredWidget) self.pathWidget.setPath(path) else: if "Type" not in path.get(self.scheme): #fimxe soon self.cachedWidgets[path] = StructuredWidget(unicode(path), path.get(self.data, reduce_sub_elements=True), path.get(self.scheme), self.openWidgetByPath, self) self.stacked.addWidget(self.cachedWidgets[path]) self._open_widget_by_path(path) else: print "" pass # except KeyError: # pass def closeEvent(self, event): if self.reallyQuit or not self.data.changed: event.accept() else: self.dialogChanged() event.ignore() def dialogChanged(self): if not self.messageBoxChanged: self.messageBoxChanged = QMessageBox("SDI", "The document has been modified.\n"+ "Do you want to save your changes?", QMessageBox.Warning, QMessageBox.Yes | QMessageBox.Default, QMessageBox.No, QMessageBox.Cancel | QMessageBox.Escape, self ) self.messageBoxChanged.setWindowModality (Qt.WindowModal ) self.messageBoxChanged.finished.connect(self.finishClose) self.messageBoxChanged.show() def finishClose(self, value): if value==QMessageBox.Yes: self.reallyQuit = self.parent().save_data() if not self.reallyQuit: return elif value==QMessageBox.No: self.reallyQuit = True elif value==QMessageBox.Cancel: return self.close() def excel_export(self): excel_filename = unicode(QFileDialog.getSaveFileName(self, "Save File", "New excel file.xls", "Excel files (*.xls)")) if excel_filename: export_to_excel(self.data, self.scheme, excel_filename) def excel_import(self): excel_filename = unicode(QFileDialog.getOpenFileName(self, "Open File", get_home_dir(), "Excel files (*.xls)")) if excel_filename: data_to_merge = import_from_excel(self.scheme, excel_filename) self.parent()._merge_data(data_to_merge)
def __init__(self, iface): QtGui.QWidget.__init__(self) self.setWindowTitle(self.tr('Search results')) self.resize(480,320) self.setMinimumSize(320,240) self.center() # Results export button self.btn_saveTab = QAction(QIcon(':/plugins/qgeric/resources/icon_save.png'), self.tr('Save this tab\'s results'), self) self.btn_saveTab.triggered.connect(self.handler_saveAttributes) self.btn_saveAllTabs = QAction(QIcon(':/plugins/qgeric/resources/icon_saveAll.png'), self.tr('Save all results'), self) self.btn_saveAllTabs.triggered.connect(self.handler_saveAllAttributes) self.btn_export = QAction(QIcon(':/plugins/qgeric/resources/icon_export.png'), self.tr('Export the selection as a memory layer'), self) self.btn_export.triggered.connect(self.exportLayer) self.btn_zoom = QAction(QIcon(':/plugins/qgeric/resources/icon_Zoom.png'), self.tr('Zoom to selected attributes'), self) self.btn_zoom.triggered.connect(self.zoomToFeature) self.btn_selectGeom = QAction(QIcon(':/plugins/qgeric/resources/icon_HlG.png'), self.tr('Highlight feature\'s geometry'), self) self.btn_selectGeom.triggered.connect(self.selectGeomChanged) self.btn_rename = QAction(QIcon(':/plugins/qgeric/resources/icon_Settings.png'), self.tr('Settings'), self) self.btn_rename.triggered.connect(self.renameWindow) self.tabWidget = QtGui.QTabWidget() # Tab container self.tabWidget.setTabsClosable(True) self.connect(self.tabWidget, SIGNAL("currentChanged(int)"), self.tabChanged) self.connect(self.tabWidget, SIGNAL("tabCloseRequested(int)"), self.closeTab) self.loadingWindow = QtGui.QProgressDialog() self.loadingWindow.setWindowTitle(self.tr('Loading...')) self.loadingWindow.setRange(0,100) self.loadingWindow.setAutoClose(False) self.loadingWindow.setCancelButton(None) self.canvas = iface.mapCanvas() iface.connect(self.canvas, SIGNAL("extentsChanged()"), self.highlight_features) self.highlight = [] self.highlight_rows = [] toolbar = QToolBar() toolbar.addAction(self.btn_saveTab) toolbar.addAction(self.btn_saveAllTabs) toolbar.addAction(self.btn_export) toolbar.addSeparator() toolbar.addAction(self.btn_zoom) toolbar.addSeparator() toolbar.addAction(self.btn_selectGeom) toolbar.addAction(self.btn_rename) vbox = QtGui.QVBoxLayout() vbox.setContentsMargins(0,0,0,0) vbox.addWidget(toolbar) vbox.addWidget(self.tabWidget) self.setLayout(vbox) self.mb = iface.messageBar() self.selectGeom = False # False for point, True for geometry
class FeatureFormWidget(Ui_Form, QWidget): # Raise the cancel event, takes a reason and a level canceled = pyqtSignal(str, int) featuresaved = pyqtSignal() featuredeleted = pyqtSignal() def __init__(self, parent=None): super(FeatureFormWidget, self).__init__(parent) self.setupUi(self) toolbar = QToolBar() size = QSize(48, 48) toolbar.setIconSize(size) style = Qt.ToolButtonTextUnderIcon toolbar.setToolButtonStyle(style) self.actionDelete = toolbar.addAction(QIcon(":/icons/delete"), "Delete") self.actionDelete.triggered.connect(self.delete_feature) label = '<b style="color:red">*</b> Required fields' self.missingfieldsLabel = QLabel(label) self.missingfieldsLabel.hide() self.missingfieldaction = toolbar.addWidget(self.missingfieldsLabel) titlespacer = QWidget() titlespacer.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding) toolbar.addWidget(titlespacer) self.titlellabel = QLabel(label) self.titlellabel.setProperty("headerlabel", True) self.titlelabelaction = toolbar.addWidget(self.titlellabel) spacer = QWidget() spacer2 = QWidget() spacer2.setMinimumWidth(40) spacer.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding) spacer2.setSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed) toolbar.addWidget(spacer) self.actionCancel = toolbar.addAction(QIcon(":/icons/cancel"), "Cancel") toolbar.addWidget(spacer2) self.actionSave = toolbar.addAction(QIcon(":/icons/save"), "Save") self.actionSave.triggered.connect(self.save_feature) self.layout().setContentsMargins(0, 3, 0, 3) self.layout().insertWidget(0, toolbar) self.actiontoolbar = QToolBar() self.actiontoolbar.setToolButtonStyle(Qt.ToolButtonTextUnderIcon) spacer = QWidget() spacer.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding) self.actiontoolbar.addWidget(spacer) self.layout().insertWidget(1, self.actiontoolbar) self.flickwidget = FlickCharm() self.flickwidget.activateOn(self.scrollArea) self.featureform = None self.values = {} self.config = {} self.feature = None def set_featureform(self, featureform): """ Note: There can only be one feature form. If you need to show another one make a new FeatureFormWidget """ self.featureform = featureform self.titlellabel.setText(self.featureform.windowTitle()) self.featureform.formvalidation.connect(self._update_validation) self.featureform.helprequest.connect( functools.partial(RoamEvents.helprequest.emit, self)) self.featureform.showlargewidget.connect(RoamEvents.show_widget.emit) self.featureform.enablesave.connect(self.actionSave.setEnabled) self.featureform.enablesave.connect(self.actionSave.setVisible) self.featureform.rejected.connect(self.canceled.emit) self.featureform.accepted.connect(self.featuresaved) actions = self.featureform.form_actions() if actions: for action in actions: self.actiontoolbar.addAction(action) else: self.actiontoolbar.hide() self.featureform.setContentsMargins(0, 0, 0, 0) self.featureformarea.layout().addWidget(self.featureform) def delete_feature(self): try: msg = self.featureform.deletemessage except AttributeError: msg = 'Do you really want to delete this feature?' box = DeleteFeatureDialog(msg) if not box.exec_(): return try: self.featureform.delete() except featureform.DeleteFeatureException as ex: RoamEvents.raisemessage(*ex.error) self.featureform.featuredeleted(self.feature) self.featuredeleted.emit() def feature_saved(self): self.featuresaved.emit() RoamEvents.featuresaved.emit() def save_feature(self): try: self.featureform.save() except featureform.MissingValuesException as ex: RoamEvents.raisemessage(*ex.error) return except featureform.FeatureSaveException as ex: RoamEvents.raisemessage(*ex.error) self.feature_saved() def set_config(self, config): self.config = config editmode = config['editmode'] allowsave = config.get('allowsave', True) self.feature = config.get('feature', None) tools = config.get('tools', []) candelete = True if tools: candelete = "delete" in tools self.featureform.feature = self.feature self.featureform.editingmode = editmode self.actionDelete.setVisible(editmode and candelete) self.actionSave.setEnabled(allowsave) def _update_validation(self, passed): # Show the error if there is missing fields self.missingfieldaction.setVisible(not passed) def bind_values(self, values): self.values = values self.featureform.bindvalues(values) def after_load(self): self.featureform.loaded() def before_load(self): self.featureform.load(self.config['feature'], self.config['layers'], self.values)
class __IDE(QMainWindow): ############################################################################### # SIGNALS # # goingDown() ############################################################################### def __init__(self, start_server=False): QMainWindow.__init__(self) self.setWindowTitle('NINJA-IDE {Ninja-IDE Is Not Just Another IDE}') self.setMinimumSize(700, 500) #Load the size and the position of the main window self.load_window_geometry() #Start server if needed self.s_listener = None if start_server: self.s_listener = QLocalServer() self.s_listener.listen("ninja_ide") self.connect(self.s_listener, SIGNAL("newConnection()"), self._process_connection) #Profile handler self.profile = None #Opacity self.opacity = settings.MAX_OPACITY #Define Actions object before the UI self.actions = actions.Actions() #StatusBar self.status = status_bar.StatusBar(self) self.status.hide() self.setStatusBar(self.status) #Main Widget - Create first than everything else self.central = central_widget.CentralWidget(self) self.load_ui(self.central) self.setCentralWidget(self.central) #ToolBar self.toolbar = QToolBar(self) self.toolbar.setToolTip(self.tr("Press and Drag to Move")) self.toolbar.setToolButtonStyle(Qt.ToolButtonIconOnly) self.addToolBar(settings.TOOLBAR_AREA, self.toolbar) if settings.HIDE_TOOLBAR: self.toolbar.hide() #Install Shortcuts after the UI has been initialized self.actions.install_shortcuts(self) self.connect(self.mainContainer, SIGNAL("currentTabChanged(QString)"), self.actions.update_explorer) #Menu menubar = self.menuBar() file_ = menubar.addMenu(self.tr("&File")) edit = menubar.addMenu(self.tr("&Edit")) view = menubar.addMenu(self.tr("&View")) source = menubar.addMenu(self.tr("&Source")) project = menubar.addMenu(self.tr("&Project")) self.pluginsMenu = menubar.addMenu(self.tr("&Addins")) about = menubar.addMenu(self.tr("Abou&t")) #The order of the icons in the toolbar is defined by this calls self._menuFile = menu_file.MenuFile(file_, self.toolbar, self) self._menuView = menu_view.MenuView(view, self.toolbar, self) self._menuEdit = menu_edit.MenuEdit(edit, self.toolbar) self._menuSource = menu_source.MenuSource(source) self._menuProject = menu_project.MenuProject(project, self.toolbar) self._menuPlugins = menu_plugins.MenuPlugins(self.pluginsMenu) self._menuAbout = menu_about.MenuAbout(about) self.load_toolbar() #Plugin Manager services = { 'editor': plugin_services.MainService(), 'toolbar': plugin_services.ToolbarService(self.toolbar), 'menuApp': plugin_services.MenuAppService(self.pluginsMenu), 'explorer': plugin_services.ExplorerService(), 'misc': plugin_services.MiscContainerService(self.misc)} serviceLocator = plugin_manager.ServiceLocator(services) self.plugin_manager = plugin_manager.PluginManager(resources.PLUGINS, serviceLocator) self.plugin_manager.discover() #load all plugins! self.plugin_manager.load_all() #Tray Icon self.trayIcon = updates.TrayIconUpdates(self) self.trayIcon.show() self.connect(self._menuFile, SIGNAL("openFile(QString)"), self.mainContainer.open_file) self.connect(self.mainContainer, SIGNAL("fileSaved(QString)"), self.show_status_message) self.connect(self.mainContainer, SIGNAL("recentTabsModified(QStringList)"), self._menuFile.update_recent_files) def _process_connection(self): connection = self.s_listener.nextPendingConnection() connection.waitForReadyRead() data = connection.readAll() connection.close() if data: files, projects = data.split(ipc.project_delimiter, 1) files = map(lambda x: (x.split(':')[0], int(x.split(':')[1])), files.split(ipc.file_delimiter)) projects = projects.split(ipc.project_delimiter) self.load_session_files_projects(files, [], projects, None) def load_toolbar(self): self.toolbar.clear() toolbar_items = {} toolbar_items.update(self._menuFile.toolbar_items) toolbar_items.update(self._menuView.toolbar_items) toolbar_items.update(self._menuEdit.toolbar_items) toolbar_items.update(self._menuSource.toolbar_items) toolbar_items.update(self._menuProject.toolbar_items) for item in settings.TOOLBAR_ITEMS: if item == 'separator': self.toolbar.addSeparator() else: tool_item = toolbar_items.get(item, None) if tool_item is not None: self.toolbar.addAction(tool_item) #load action added by plugins, This is a special case when reload #the toolbar after save the preferences widget for toolbar_action in settings.get_toolbar_item_for_plugins(): self.toolbar.addAction(toolbar_action) def load_external_plugins(self, paths): for path in paths: self.plugin_manager.add_plugin_dir(path) #load all plugins! self.plugin_manager.discover() self.plugin_manager.load_all() def show_status_message(self, message): self.status.showMessage(message, 2000) def load_ui(self, centralWidget): #Set Application Font for ToolTips QToolTip.setFont(QFont(settings.FONT_FAMILY, 10)) #Create Main Container to manage Tabs self.mainContainer = main_container.MainContainer(self) self.connect(self.mainContainer, SIGNAL("currentTabChanged(QString)"), self.change_window_title) self.connect(self.mainContainer, SIGNAL("locateFunction(QString, QString, bool)"), self.actions.locate_function) self.connect(self.mainContainer, SIGNAL("navigateCode(bool, int)"), self.actions.navigate_code_history) self.connect(self.mainContainer, SIGNAL("addBackItemNavigation()"), self.actions.add_back_item_navigation) self.connect(self.mainContainer, SIGNAL("updateFileMetadata()"), self.actions.update_explorer) self.connect(self.mainContainer, SIGNAL("updateLocator(QString)"), self.actions.update_explorer) self.connect(self.mainContainer, SIGNAL("openPreferences()"), self._show_preferences) self.connect(self.mainContainer, SIGNAL("dontOpenStartPage()"), self._dont_show_start_page_again) self.connect(self.mainContainer, SIGNAL("currentTabChanged(QString)"), self.status.handle_tab_changed) # Update symbols self.connect(self.mainContainer, SIGNAL("updateLocator(QString)"), self.status.explore_file_code) #Create Explorer Panel self.explorer = explorer_container.ExplorerContainer(self) self.connect(self.central, SIGNAL("splitterCentralRotated()"), self.explorer.rotate_tab_position) self.connect(self.explorer, SIGNAL("updateLocator()"), self.status.explore_code) self.connect(self.explorer, SIGNAL("goToDefinition(int)"), self.actions.editor_go_to_line) self.connect(self.explorer, SIGNAL("projectClosed(QString)"), self.actions.close_files_from_project) #Create Misc Bottom Container self.misc = misc_container.MiscContainer(self) self.connect(self.mainContainer, SIGNAL("findOcurrences(QString)"), self.misc.show_find_occurrences) centralWidget.insert_central_container(self.mainContainer) centralWidget.insert_lateral_container(self.explorer) centralWidget.insert_bottom_container(self.misc) self.connect(self.mainContainer, SIGNAL("cursorPositionChange(int, int)"), self.central.lateralPanel.update_line_col) # TODO: Change current symbol on move #self.connect(self.mainContainer, #SIGNAL("cursorPositionChange(int, int)"), #self.explorer.update_current_symbol) self.connect(self.mainContainer, SIGNAL("enabledFollowMode(bool)"), self.central.enable_follow_mode_scrollbar) if settings.SHOW_START_PAGE: self.mainContainer.show_start_page() def _show_preferences(self): pref = preferences.PreferencesWidget(self.mainContainer) pref.show() def _dont_show_start_page_again(self): settings.SHOW_START_PAGE = False qsettings = QSettings() qsettings.beginGroup('preferences') qsettings.beginGroup('general') qsettings.setValue('showStartPage', settings.SHOW_START_PAGE) qsettings.endGroup() qsettings.endGroup() self.mainContainer.actualTab.close_tab() def load_session_files_projects(self, filesTab1, filesTab2, projects, current_file, recent_files=None): self.mainContainer.open_files(filesTab1, notIDEStart=False) self.mainContainer.open_files(filesTab2, mainTab=False, notIDEStart=False) self.explorer.open_session_projects(projects, notIDEStart=False) if current_file: self.mainContainer.open_file(current_file, notStart=False) if recent_files is not None: self._menuFile.update_recent_files(recent_files) def open_file(self, filename): if filename: self.mainContainer.open_file(filename) def open_project(self, project): if project: self.actions.open_project(project) def __get_profile(self): return self.profile def __set_profile(self, profileName): self.profile = profileName if self.profile is not None: self.setWindowTitle('NINJA-IDE (PROFILE: %s)' % self.profile) else: self.setWindowTitle( 'NINJA-IDE {Ninja-IDE Is Not Just Another IDE}') Profile = property(__get_profile, __set_profile) def change_window_title(self, title): if self.profile is None: self.setWindowTitle('NINJA-IDE - %s' % title) else: self.setWindowTitle('NINJA-IDE (PROFILE: %s) - %s' % ( self.profile, title)) currentEditor = self.mainContainer.get_actual_editor() if currentEditor is not None: line = currentEditor.textCursor().blockNumber() + 1 col = currentEditor.textCursor().columnNumber() self.central.lateralPanel.update_line_col(line, col) def wheelEvent(self, event): if event.modifiers() == Qt.ShiftModifier: if event.delta() == 120 and self.opacity < settings.MAX_OPACITY: self.opacity += 0.1 elif event.delta() == -120 and self.opacity > settings.MIN_OPACITY: self.opacity -= 0.1 self.setWindowOpacity(self.opacity) event.ignore() else: QMainWindow.wheelEvent(self, event) def save_settings(self): """Save the settings before the application is closed with QSettings. Info saved: Tabs and projects opened, windows state(size and position). """ qsettings = QSettings() editor_widget = self.mainContainer.get_actual_editor() current_file = '' if editor_widget is not None: current_file = editor_widget.ID if qsettings.value('preferences/general/loadFiles', 'true') == 'true': openedFiles = self.mainContainer.get_opened_documents() projects_obj = self.explorer.get_opened_projects() projects = [p.path for p in projects_obj] qsettings.setValue('openFiles/projects', projects) if len(openedFiles) > 0: qsettings.setValue('openFiles/mainTab', openedFiles[0]) if len(openedFiles) == 2: qsettings.setValue('openFiles/secondaryTab', openedFiles[1]) qsettings.setValue('openFiles/currentFile', current_file) qsettings.setValue('openFiles/recentFiles', self.mainContainer._tabMain.get_recent_files_list()) qsettings.setValue('preferences/editor/bookmarks', settings.BOOKMARKS) qsettings.setValue('preferences/editor/breakpoints', settings.BREAKPOINTS) qsettings.setValue('preferences/general/toolbarArea', self.toolBarArea(self.toolbar)) #Save if the windows state is maximixed if(self.isMaximized()): qsettings.setValue("window/maximized", True) else: qsettings.setValue("window/maximized", False) #Save the size and position of the mainwindow qsettings.setValue("window/size", self.size()) qsettings.setValue("window/pos", self.pos()) #Save the size of de splitters qsettings.setValue("window/central/areaSize", self.central.get_area_sizes()) qsettings.setValue("window/central/mainSize", self.central.get_main_sizes()) #Save the toolbar visibility qsettings.setValue("window/hide_toolbar", not self.toolbar.isVisible()) #Save Profiles if self.profile is not None: self.actions.save_profile(self.profile) else: qsettings.setValue('ide/profiles', settings.PROFILES) def load_window_geometry(self): """Load from QSettings the window size of de Ninja IDE""" qsettings = QSettings() if qsettings.value("window/maximized", 'true') == 'true': self.setWindowState(Qt.WindowMaximized) else: print dir(QSizeF) self.resize(qsettings.value("window/size", QSizeF(800, 600)).toSize()) self.move(qsettings.value("window/pos", QPointF(100, 100)).toPoint()) def closeEvent(self, event): if self.s_listener: self.s_listener.close() if settings.CONFIRM_EXIT and \ self.mainContainer.check_for_unsaved_tabs(): unsaved_files = self.mainContainer.get_unsaved_files() txt = '\n'.join(unsaved_files) val = QMessageBox.question(self, self.tr("Some changes were not saved"), self.tr("%s\n\nDo you want to exit anyway?" % txt), QMessageBox.Yes, QMessageBox.No) if val == QMessageBox.No: event.ignore() QApplication.instance().setCursorFlashTime(cursor_flash_time) self.emit(SIGNAL("goingDown()")) self.save_settings() completion_daemon.shutdown_daemon() #close python documentation server (if running) self.mainContainer.close_python_doc() #Shutdown PluginManager self.plugin_manager.shutdown() def notify_plugin_errors(self): errors = self.plugin_manager.errors if errors: plugin_error_dialog = traceback_widget.PluginErrorDialog() for err_tuple in errors: plugin_error_dialog.add_traceback(err_tuple[0], err_tuple[1]) #show the dialog plugin_error_dialog.exec_()
class ToolDockWidget(DockWidget): def __init__(self, widget, parent=None): super(ToolDockWidget, self).__init__(parent) self.toolbar = None # QToolBar() self.widget = None # QWidget() self._spacer = None # QSpacerItem() self._contents = None # QWidget() self.toolbar = QToolBar(self) self.toolbar.setObjectName(u'toolbar') self.toolbar.setIconSize(QSize(22, 22)) self.toolbar2 = QToolBar(self) self.toolbar2.setObjectName(u'toolbar') self.toolbar2.setIconSize(QSize(22, 22)) self.toolbar2.setVisible(False) widget.setParent(self) self.widget = widget self._layout = QVBoxLayout(self) self._layout.setAlignment(Qt.AlignTop) self._layout.setObjectName(u'layout') self._layout.setContentsMargins(0, 0, 0, 0) self._layout.addWidget(self.toolbar) self._layout.addWidget(self.toolbar2) self._layout.addWidget(self.widget) self._contents = QWidget(self) self._contents.setObjectName(u'contents') self._contents.setLayout(self._layout) self.setWidget(self._contents) def initGui(self, iface, location, menuAction): super(ToolDockWidget, self).initGui(iface, location, menuAction) def unloadGui(self): super(ToolDockWidget, self).unloadGui() def addToolbarAction(self, iconPath, text, callback=None, enabled=True, checkable=False, tip=None, whatsThis=None): """Add a toolbar icon to the toolbar""" action = QAction(QIcon(iconPath), text, self) if tip is not None: action.setStatusTip(tip) if whatsThis is not None: action.setWhatsThis(whatsThis) if callback is not None: action.triggered.connect(callback) action.setEnabled(enabled) action.setCheckable(checkable) self.toolbar.addAction(action) return action
class RawView(QWidget, Logger.ClassLogger): """ Raw view widget """ def __init__(self, parent, data, toCsv=False, toHtml=False, toXml=False, toPrinter=False, toTxt=False, toPdf=False): """ Raw view widgets @param parent: @type parent: """ QWidget.__init__(self, parent) self.parent = parent self.__data = data self.toXml = toXml self.toCsv = toCsv self.toHtml = toHtml self.toPrinter = toPrinter self.toTxt = toTxt self.toPdf = toPdf self.createWidgets() self.createActions() self.createToolbars() def createWidgets(self): """ Create qt widgets """ self.toolbar = QToolBar(self) self.toolbar.setToolButtonStyle(Qt.ToolButtonTextBesideIcon) layout = QVBoxLayout() if self.toXml: self.txtEdit = QtHelper.RawXmlEditor(parent=self) self.txtEdit.setFolding(QsciScintilla.BoxedTreeFoldStyle) self.txtEdit.setLexer(QsciLexerXML()) self.txtEdit.setText(self.__data) self.txtEdit.setUtf8(True) self.txtEdit.setFont(QFont("Courier", 9)) else: self.txtEdit = QtHelper.RawEditor(parent=self) self.txtEdit.setTabStopWidth(10) self.txtEdit.setText(self.__data) self.txtEdit.setFont(QFont("Courier", 9)) self.txtEdit.setMinimumWidth(650) self.txtEdit.setMinimumHeight(400) layout.addWidget(self.toolbar) layout.addWidget(self.txtEdit) self.setLayout(layout) def createActions(self): """ Qt Actions """ self.saveTxtAction = QtHelper.createAction( self, "&To TXT", self.saveTxt, tip='Save to TXT file', icon=QIcon(":/file-txt.png")) self.saveHtmlAction = QtHelper.createAction(self, "&To HTML", self.saveHtml, tip='Save to HTML file', icon=QIcon(":/web.png")) self.savePdfAction = QtHelper.createAction(self, "&To PDF", self.savePdf, tip='Save to PDF file', icon=QIcon(":/to_pdf.png")) self.saveXmlAction = QtHelper.createAction(self, "&To XML", self.saveXml, tip='Save to XML file', icon=QIcon(":/xml.png")) self.toPrinterAction = QtHelper.createAction( self, "&To Printer", self.savePrinter, tip='Print', icon=QIcon(":/printer.png")) def createToolbars(self): """ Toolbar creation """ self.toolbar.setObjectName("Export toolbar") if self.toTxt: self.toolbar.addAction(self.saveTxtAction) self.toolbar.addSeparator() if self.toHtml: self.toolbar.addAction(self.saveHtmlAction) self.toolbar.addSeparator() if self.toPdf: self.toolbar.addAction(self.savePdfAction) self.toolbar.addSeparator() if self.toXml: self.toolbar.addAction(self.saveXmlAction) self.toolbar.addSeparator() if self.toPrinter: self.toolbar.addAction(self.toPrinterAction) self.toolbar.addSeparator() self.toolbar.setIconSize(QSize(16, 16)) def savePrinter(self): """ Save to printer """ printer = QPrinter() dialog = QPrintDialog(printer, self) dialog.setWindowTitle("Print") if dialog.exec_() != QDialog.Accepted: return doc = QTextDocument() doc.setPlainText(self.txtEdit.text()) doc.print_(printer) def saveTxt(self): """ Save to txt file """ fileName = QFileDialog.getSaveFileName( self, "Save TXT file", "", "TXT file (*.txt);;All Files (*.*)") # new in v17.1 if QtHelper.IS_QT5: _filename, _type = fileName else: _filename = fileName # end of new if _filename: try: f = open(_filename, 'w') f.write(self.txtEdit.toPlainText()) f.close() except Exception as e: self.error('unable to save design file as txt: %s' % str(e)) def saveXml(self): """ Save to xml file """ fileName = QFileDialog.getSaveFileName( self, "Save XML file", "", "XML file (*.xml);;All Files (*.*)") # new in v17.1 if QtHelper.IS_QT5: _filename, _type = fileName else: _filename = fileName # end of new if _filename: try: f = open(_filename, 'w') f.write(self.txtEdit.text()) f.close() except Exception as e: self.error('unable to save design file as xml: %s' % str(e)) def saveHtml(self): """ Save to html file """ fileName = QFileDialog.getSaveFileName( self, "Save HTML file", "", "HTML file (*.html);;All Files (*.*)") # new in v17.1 if QtHelper.IS_QT5: _filename, _type = fileName else: _filename = fileName # end of new if _filename: try: f = open(_filename, 'w') f.write(self.txtEdit.toHtml()) f.close() except Exception as e: self.error('unable to save design file as html: %s' % str(e)) def savePdf(self): """ Save to pdf file """ fileName = QFileDialog.getSaveFileName( self, 'Save to PDF', "", "PDF file (*.pdf);;All Files (*.*)") # new in v17.1 if QtHelper.IS_QT5: _filename, _type = fileName else: _filename = fileName # end of new if _filename: printer = QPrinter(QPrinter.HighResolution) printer.setPageSize(QPrinter.A4) printer.setColorMode(QPrinter.Color) printer.setOutputFormat(QPrinter.PdfFormat) printer.setOutputFileName(_filename) doc = QTextDocument() if self.toXml: doc.setPlainText(self.txtEdit.text()) else: doc.setHtml(self.txtEdit.toHtml()) doc.print_(printer)
def __load_menubar(self, menubar): """ This method installs the menubar and toolbar, menus and QAction's, also connects to a slot each QAction. """ from src.gui import menu_actions from src import keymap # Keymap kmap = keymap.KEYMAP # Toolbar items toolbar_items = {} # Actions container = Pireal.get_service("container") for item in menu_actions.MENU: menubar_item = menu_actions.MENU[item] menu_name = menubar_item['name'] items = menubar_item['items'] menu = menubar.addMenu(menu_name) for menu_item in items: if isinstance(menu_item, str): # Is a separator menu.addSeparator() else: action = menu_item['name'] obj, connection = menu_item['slot'].split(':') obj = self if obj.startswith("pireal") else container qaction = menu.addAction(action) # Icon name is connection icon = QIcon(":img/%s" % connection) qaction.setIcon(icon) # Install shortcuts shortcut = kmap.get(connection, None) if shortcut is not None: qaction.setShortcut(shortcut) # Items for toolbar if connection in Pireal.TOOLBAR_ITEMS: toolbar_items[connection] = qaction # The name of QAction is the connection Pireal.load_action(connection, qaction) slot = getattr(obj, connection, None) if isinstance(slot, Callable): self.connect(qaction, SIGNAL("triggered()"), slot) # Install toolbar toolbar = QToolBar(self) for action in Pireal.TOOLBAR_ITEMS: qaction = toolbar_items.get(action, None) if qaction is not None: toolbar.addAction(qaction) else: toolbar.addSeparator() self.addToolBar(toolbar) self.enable_disable_db_actions(False) self.enable_disable_relation_actions(False) self.enable_disable_query_actions(False)
class bookmark(QWidget): def __init__(self, parent): QWidget.__init__(self) self.init(parent) self.initShape() def init(self, parent): self.heditor = parent self.items = [] self.selectedItem = -1 def initShape(self): self.vbox = QVBoxLayout() self.vbox.setSpacing(0) self.dialog = bookDiag(self) self.initFunctions() self.initTree() self.setLayout(self.vbox) def initFunctions(self): self.booktool = QToolBar() self.booktool.setObjectName("Hexedit bookmark toolbar") self.add = QAction(QIcon(":bookmark_add.png"), "Add bookmark", self.booktool) self.booktool.addAction(self.add) self.rm = QAction(QIcon(":bookmark_rm.png"), "Remove bookmark", self.booktool) self.booktool.addAction(self.rm) self.edit = QAction(QIcon(":bookmark_toolbar.png"), "Edit bookmark", self.booktool) self.booktool.addAction(self.edit) #Callbacks self.add.connect(self.add, SIGNAL("triggered()"), self.addbook) self.rm.connect(self.rm, SIGNAL("triggered()"), self.rmbook) self.edit.connect(self.edit, SIGNAL("triggered()"), self.editbook) self.vbox.addWidget(self.booktool) def initTree(self): self.tree = QTreeWidget() self.tree.setColumnCount(5) headerLabels = [ QApplication.translate("bookmark", "Address", None, QApplication.UnicodeUTF8), QApplication.translate("bookmark", "Length (dec)", None, QApplication.UnicodeUTF8), QApplication.translate("bookmark", "Length (hex)", None, QApplication.UnicodeUTF8), QApplication.translate("bookmark", "Hex value", None, QApplication.UnicodeUTF8), QApplication.translate("bookmark", "Ascii value", None, QApplication.UnicodeUTF8), QApplication.translate("bookmark", "Description", None, QApplication.UnicodeUTF8) ] self.tree.setHeaderLabels(headerLabels) self.tree.setAlternatingRowColors(True) self.connect(self.tree, SIGNAL("itemClicked(QTreeWidgetItem*,int)"), self.treeClicked) self.connect(self.tree, SIGNAL("itemDoubleClicked(QTreeWidgetItem*,int)"), self.treeDoubleClicked) self.vbox.addWidget(self.tree) #CALLBACKS def treeClicked(self, item, col): self.selectedItem = item def treeDoubleClicked(self, item, col): self.selectedItem = item add = QString(item.text(0)) off = add.toULongLong(16) if off[1]: self.heditor.readOffset(off[0]) # self.heditor.selection.offset = off[0] # self.heditor.whex.hexcursor.update() # self.heditor.whex.asciicursor.update() def getSelectedItemRow(self, address): cp = 0 for item in self.items: if item.text(0) == address: return cp cp += 1 return -1 def addbook(self): self.dialog.setInformations() ret = self.dialog.exec_() if ret == 1: #XXXCheck if offsetis present item = QTreeWidgetItem(self.tree) address = self.dialog.address.text() declen = self.dialog.lendec.text() hexlen = self.dialog.lenhex.text() hexval = self.dialog.hexvalue.text() asciival = self.dialog.asciivalue.text() description = self.dialog.description.text() item.setText(0, address) item.setText(1, declen) item.setText(2, hexlen) item.setText(3, hexval) item.setText(4, asciival) item.setText(5, description) self.items.append(item) def rmbook(self): if (self.selectedItem != -1) and len(self.items) > 0: row = self.getSelectedItemRow(self.selectedItem.text(0)) self.tree.takeTopLevelItem(row) self.items.remove(self.selectedItem) if len(self.items) > 0: if len(self.items) > row: self.selectedItem = self.items[row] else: self.selectedItem = self.items[row - 1] def editbook(self): print "edit"
class PythonConsoleWidget(QWidget): def __init__(self, parent=None): QWidget.__init__(self, parent) self.setWindowTitle(QCoreApplication.translate("PythonConsole", "Python Console")) self.settings = QSettings() self.shell = ShellScintilla(self) self.setFocusProxy(self.shell) self.shellOut = ShellOutputScintilla(self) self.tabEditorWidget = EditorTabWidget(self) ##------------ UI ------------------------------- self.splitterEditor = QSplitter(self) self.splitterEditor.setOrientation(Qt.Horizontal) self.splitterEditor.setHandleWidth(6) self.splitterEditor.setChildrenCollapsible(True) self.shellOutWidget = QWidget(self) self.shellOutWidget.setLayout(QVBoxLayout()) self.shellOutWidget.layout().setContentsMargins(0, 0, 0, 0) self.shellOutWidget.layout().addWidget(self.shellOut) self.splitter = QSplitter(self.splitterEditor) self.splitter.setOrientation(Qt.Vertical) self.splitter.setHandleWidth(3) self.splitter.setChildrenCollapsible(False) self.splitter.addWidget(self.shellOutWidget) self.splitter.addWidget(self.shell) #self.splitterEditor.addWidget(self.tabEditorWidget) self.splitterObj = QSplitter(self.splitterEditor) self.splitterObj.setHandleWidth(3) self.splitterObj.setOrientation(Qt.Horizontal) #self.splitterObj.setSizes([0, 0]) #self.splitterObj.setStretchFactor(0, 1) self.widgetEditor = QWidget(self.splitterObj) self.widgetFind = QWidget(self) self.listClassMethod = QTreeWidget(self.splitterObj) self.listClassMethod.setColumnCount(2) objInspLabel = QCoreApplication.translate("PythonConsole", "Object Inspector") self.listClassMethod.setHeaderLabels([objInspLabel, '']) self.listClassMethod.setColumnHidden(1, True) self.listClassMethod.setAlternatingRowColors(True) #self.splitterEditor.addWidget(self.widgetEditor) #self.splitterObj.addWidget(self.listClassMethod) #self.splitterObj.addWidget(self.widgetEditor) # Hide side editor on start up self.splitterObj.hide() self.listClassMethod.hide() # Hide search widget on start up self.widgetFind.hide() sizes = self.splitter.sizes() self.splitter.setSizes(sizes) ##----------------Restore Settings------------------------------------ self.restoreSettingsConsole() ##------------------Toolbar Editor------------------------------------- ## Action for Open File openFileBt = QCoreApplication.translate("PythonConsole", "Open file") self.openFileButton = QAction(self) self.openFileButton.setCheckable(False) self.openFileButton.setEnabled(True) self.openFileButton.setIcon(QgsApplication.getThemeIcon("console/iconOpenConsole.png")) self.openFileButton.setMenuRole(QAction.PreferencesRole) self.openFileButton.setIconVisibleInMenu(True) self.openFileButton.setToolTip(openFileBt) self.openFileButton.setText(openFileBt) openExtEditorBt = QCoreApplication.translate("PythonConsole", "Open in external editor") self.openInEditorButton = QAction(self) self.openInEditorButton.setCheckable(False) self.openInEditorButton.setEnabled(True) self.openInEditorButton.setIcon(QgsApplication.getThemeIcon("console/iconShowEditorConsole.png")) self.openInEditorButton.setMenuRole(QAction.PreferencesRole) self.openInEditorButton.setIconVisibleInMenu(True) self.openInEditorButton.setToolTip(openExtEditorBt) self.openInEditorButton.setText(openExtEditorBt) ## Action for Save File saveFileBt = QCoreApplication.translate("PythonConsole", "Save") self.saveFileButton = QAction(self) self.saveFileButton.setCheckable(False) self.saveFileButton.setEnabled(False) self.saveFileButton.setIcon(QgsApplication.getThemeIcon("console/iconSaveConsole.png")) self.saveFileButton.setMenuRole(QAction.PreferencesRole) self.saveFileButton.setIconVisibleInMenu(True) self.saveFileButton.setToolTip(saveFileBt) self.saveFileButton.setText(saveFileBt) ## Action for Save File As saveAsFileBt = QCoreApplication.translate("PythonConsole", "Save As...") self.saveAsFileButton = QAction(self) self.saveAsFileButton.setCheckable(False) self.saveAsFileButton.setEnabled(True) self.saveAsFileButton.setIcon(QgsApplication.getThemeIcon("console/iconSaveAsConsole.png")) self.saveAsFileButton.setMenuRole(QAction.PreferencesRole) self.saveAsFileButton.setIconVisibleInMenu(True) self.saveAsFileButton.setToolTip(saveAsFileBt) self.saveAsFileButton.setText(saveAsFileBt) ## Action Cut cutEditorBt = QCoreApplication.translate("PythonConsole", "Cut") self.cutEditorButton = QAction(self) self.cutEditorButton.setCheckable(False) self.cutEditorButton.setEnabled(True) self.cutEditorButton.setIcon(QgsApplication.getThemeIcon("console/iconCutEditorConsole.png")) self.cutEditorButton.setMenuRole(QAction.PreferencesRole) self.cutEditorButton.setIconVisibleInMenu(True) self.cutEditorButton.setToolTip(cutEditorBt) self.cutEditorButton.setText(cutEditorBt) ## Action Copy copyEditorBt = QCoreApplication.translate("PythonConsole", "Copy") self.copyEditorButton = QAction(self) self.copyEditorButton.setCheckable(False) self.copyEditorButton.setEnabled(True) self.copyEditorButton.setIcon(QgsApplication.getThemeIcon("console/iconCopyEditorConsole.png")) self.copyEditorButton.setMenuRole(QAction.PreferencesRole) self.copyEditorButton.setIconVisibleInMenu(True) self.copyEditorButton.setToolTip(copyEditorBt) self.copyEditorButton.setText(copyEditorBt) ## Action Paste pasteEditorBt = QCoreApplication.translate("PythonConsole", "Paste") self.pasteEditorButton = QAction(self) self.pasteEditorButton.setCheckable(False) self.pasteEditorButton.setEnabled(True) self.pasteEditorButton.setIcon(QgsApplication.getThemeIcon("console/iconPasteEditorConsole.png")) self.pasteEditorButton.setMenuRole(QAction.PreferencesRole) self.pasteEditorButton.setIconVisibleInMenu(True) self.pasteEditorButton.setToolTip(pasteEditorBt) self.pasteEditorButton.setText(pasteEditorBt) ## Action Run Script (subprocess) runScriptEditorBt = QCoreApplication.translate("PythonConsole", "Run script") self.runScriptEditorButton = QAction(self) self.runScriptEditorButton.setCheckable(False) self.runScriptEditorButton.setEnabled(True) self.runScriptEditorButton.setIcon(QgsApplication.getThemeIcon("console/iconRunScriptConsole.png")) self.runScriptEditorButton.setMenuRole(QAction.PreferencesRole) self.runScriptEditorButton.setIconVisibleInMenu(True) self.runScriptEditorButton.setToolTip(runScriptEditorBt) self.runScriptEditorButton.setText(runScriptEditorBt) ## Action Run Script (subprocess) commentEditorBt = QCoreApplication.translate("PythonConsole", "Comment") self.commentEditorButton = QAction(self) self.commentEditorButton.setCheckable(False) self.commentEditorButton.setEnabled(True) self.commentEditorButton.setIcon(QgsApplication.getThemeIcon("console/iconCommentEditorConsole.png")) self.commentEditorButton.setMenuRole(QAction.PreferencesRole) self.commentEditorButton.setIconVisibleInMenu(True) self.commentEditorButton.setToolTip(commentEditorBt) self.commentEditorButton.setText(commentEditorBt) ## Action Run Script (subprocess) uncommentEditorBt = QCoreApplication.translate("PythonConsole", "Uncomment") self.uncommentEditorButton = QAction(self) self.uncommentEditorButton.setCheckable(False) self.uncommentEditorButton.setEnabled(True) self.uncommentEditorButton.setIcon(QgsApplication.getThemeIcon("console/iconUncommentEditorConsole.png")) self.uncommentEditorButton.setMenuRole(QAction.PreferencesRole) self.uncommentEditorButton.setIconVisibleInMenu(True) self.uncommentEditorButton.setToolTip(uncommentEditorBt) self.uncommentEditorButton.setText(uncommentEditorBt) ## Action for Object browser objList = QCoreApplication.translate("PythonConsole", "Object Inspector") self.objectListButton = QAction(self) self.objectListButton.setCheckable(True) self.objectListButton.setEnabled(self.settings.value("pythonConsole/enableObjectInsp", False, type=bool)) self.objectListButton.setIcon(QgsApplication.getThemeIcon("console/iconClassBrowserConsole.png")) self.objectListButton.setMenuRole(QAction.PreferencesRole) self.objectListButton.setIconVisibleInMenu(True) self.objectListButton.setToolTip(objList) self.objectListButton.setText(objList) ## Action for Find text findText = QCoreApplication.translate("PythonConsole", "Find Text") self.findTextButton = QAction(self) self.findTextButton.setCheckable(True) self.findTextButton.setEnabled(True) self.findTextButton.setIcon(QgsApplication.getThemeIcon("console/iconSearchEditorConsole.png")) self.findTextButton.setMenuRole(QAction.PreferencesRole) self.findTextButton.setIconVisibleInMenu(True) self.findTextButton.setToolTip(findText) self.findTextButton.setText(findText) ##----------------Toolbar Console------------------------------------- ## Action Show Editor showEditor = QCoreApplication.translate("PythonConsole", "Show editor") self.showEditorButton = QAction(self) self.showEditorButton.setEnabled(True) self.showEditorButton.setCheckable(True) self.showEditorButton.setIcon(QgsApplication.getThemeIcon("console/iconShowEditorConsole.png")) self.showEditorButton.setMenuRole(QAction.PreferencesRole) self.showEditorButton.setIconVisibleInMenu(True) self.showEditorButton.setToolTip(showEditor) self.showEditorButton.setText(showEditor) ## Action for Clear button clearBt = QCoreApplication.translate("PythonConsole", "Clear console") self.clearButton = QAction(self) self.clearButton.setCheckable(False) self.clearButton.setEnabled(True) self.clearButton.setIcon(QgsApplication.getThemeIcon("console/iconClearConsole.png")) self.clearButton.setMenuRole(QAction.PreferencesRole) self.clearButton.setIconVisibleInMenu(True) self.clearButton.setToolTip(clearBt) self.clearButton.setText(clearBt) ## Action for settings optionsBt = QCoreApplication.translate("PythonConsole", "Settings") self.optionsButton = QAction(self) self.optionsButton.setCheckable(False) self.optionsButton.setEnabled(True) self.optionsButton.setIcon(QgsApplication.getThemeIcon("console/iconSettingsConsole.png")) self.optionsButton.setMenuRole(QAction.PreferencesRole) self.optionsButton.setIconVisibleInMenu(True) self.optionsButton.setToolTip(optionsBt) self.optionsButton.setText(optionsBt) ## Action menu for class actionClassBt = QCoreApplication.translate("PythonConsole", "Import Class") self.actionClass = QAction(self) self.actionClass.setCheckable(False) self.actionClass.setEnabled(True) self.actionClass.setIcon(QgsApplication.getThemeIcon("console/iconClassConsole.png")) self.actionClass.setMenuRole(QAction.PreferencesRole) self.actionClass.setIconVisibleInMenu(True) self.actionClass.setToolTip(actionClassBt) self.actionClass.setText(actionClassBt) ## Import Processing class loadProcessingBt = QCoreApplication.translate("PythonConsole", "Import Processing class") self.loadProcessingButton = QAction(self) self.loadProcessingButton.setCheckable(False) self.loadProcessingButton.setEnabled(True) self.loadProcessingButton.setIcon(QgsApplication.getThemeIcon("console/iconProcessingConsole.png")) self.loadProcessingButton.setMenuRole(QAction.PreferencesRole) self.loadProcessingButton.setIconVisibleInMenu(True) self.loadProcessingButton.setToolTip(loadProcessingBt) self.loadProcessingButton.setText(loadProcessingBt) ## Import QtCore class loadQtCoreBt = QCoreApplication.translate("PythonConsole", "Import PyQt.QtCore class") self.loadQtCoreButton = QAction(self) self.loadQtCoreButton.setCheckable(False) self.loadQtCoreButton.setEnabled(True) self.loadQtCoreButton.setIcon(QgsApplication.getThemeIcon("console/iconQtCoreConsole.png")) self.loadQtCoreButton.setMenuRole(QAction.PreferencesRole) self.loadQtCoreButton.setIconVisibleInMenu(True) self.loadQtCoreButton.setToolTip(loadQtCoreBt) self.loadQtCoreButton.setText(loadQtCoreBt) ## Import QtGui class loadQtGuiBt = QCoreApplication.translate("PythonConsole", "Import PyQt.QtGui class") self.loadQtGuiButton = QAction(self) self.loadQtGuiButton.setCheckable(False) self.loadQtGuiButton.setEnabled(True) self.loadQtGuiButton.setIcon(QgsApplication.getThemeIcon("console/iconQtGuiConsole.png")) self.loadQtGuiButton.setMenuRole(QAction.PreferencesRole) self.loadQtGuiButton.setIconVisibleInMenu(True) self.loadQtGuiButton.setToolTip(loadQtGuiBt) self.loadQtGuiButton.setText(loadQtGuiBt) ## Action for Run script runBt = QCoreApplication.translate("PythonConsole", "Run command") self.runButton = QAction(self) self.runButton.setCheckable(False) self.runButton.setEnabled(True) self.runButton.setIcon(QgsApplication.getThemeIcon("console/iconRunConsole.png")) self.runButton.setMenuRole(QAction.PreferencesRole) self.runButton.setIconVisibleInMenu(True) self.runButton.setToolTip(runBt) self.runButton.setText(runBt) ## Help action helpBt = QCoreApplication.translate("PythonConsole", "Help") self.helpButton = QAction(self) self.helpButton.setCheckable(False) self.helpButton.setEnabled(True) self.helpButton.setIcon(QgsApplication.getThemeIcon("console/iconHelpConsole.png")) self.helpButton.setMenuRole(QAction.PreferencesRole) self.helpButton.setIconVisibleInMenu(True) self.helpButton.setToolTip(helpBt) self.helpButton.setText(helpBt) self.toolBar = QToolBar() self.toolBar.setEnabled(True) self.toolBar.setFocusPolicy(Qt.NoFocus) self.toolBar.setContextMenuPolicy(Qt.DefaultContextMenu) self.toolBar.setLayoutDirection(Qt.LeftToRight) self.toolBar.setIconSize(QSize(16, 16)) self.toolBar.setMovable(False) self.toolBar.setFloatable(False) self.toolBar.addAction(self.clearButton) self.toolBar.addAction(self.actionClass) self.toolBar.addAction(self.runButton) self.toolBar.addSeparator() self.toolBar.addAction(self.showEditorButton) self.toolBar.addSeparator() self.toolBar.addAction(self.optionsButton) self.toolBar.addAction(self.helpButton) self.toolBarEditor = QToolBar() self.toolBarEditor.setEnabled(False) self.toolBarEditor.setFocusPolicy(Qt.NoFocus) self.toolBarEditor.setContextMenuPolicy(Qt.DefaultContextMenu) self.toolBarEditor.setLayoutDirection(Qt.LeftToRight) self.toolBarEditor.setIconSize(QSize(16, 16)) self.toolBarEditor.setMovable(False) self.toolBarEditor.setFloatable(False) self.toolBarEditor.addAction(self.openFileButton) self.toolBarEditor.addAction(self.openInEditorButton) self.toolBarEditor.addSeparator() self.toolBarEditor.addAction(self.saveFileButton) self.toolBarEditor.addAction(self.saveAsFileButton) self.toolBarEditor.addSeparator() self.toolBarEditor.addAction(self.runScriptEditorButton) self.toolBarEditor.addSeparator() self.toolBarEditor.addAction(self.findTextButton) self.toolBarEditor.addSeparator() self.toolBarEditor.addAction(self.cutEditorButton) self.toolBarEditor.addAction(self.copyEditorButton) self.toolBarEditor.addAction(self.pasteEditorButton) self.toolBarEditor.addSeparator() self.toolBarEditor.addAction(self.commentEditorButton) self.toolBarEditor.addAction(self.uncommentEditorButton) self.toolBarEditor.addSeparator() self.toolBarEditor.addAction(self.objectListButton) ## Menu Import Class self.classMenu = QMenu() self.classMenu.addAction(self.loadProcessingButton) self.classMenu.addAction(self.loadQtCoreButton) self.classMenu.addAction(self.loadQtGuiButton) cM = self.toolBar.widgetForAction(self.actionClass) cM.setMenu(self.classMenu) cM.setPopupMode(QToolButton.InstantPopup) self.widgetButton = QWidget() sizePolicy = QSizePolicy(QSizePolicy.Fixed, QSizePolicy.Preferred) sizePolicy.setHorizontalStretch(0) sizePolicy.setVerticalStretch(0) sizePolicy.setHeightForWidth(self.widgetButton.sizePolicy().hasHeightForWidth()) self.widgetButton.setSizePolicy(sizePolicy) self.widgetButtonEditor = QWidget(self.widgetEditor) sizePolicy = QSizePolicy(QSizePolicy.Fixed, QSizePolicy.Preferred) sizePolicy.setHorizontalStretch(0) sizePolicy.setVerticalStretch(0) sizePolicy.setHeightForWidth(self.widgetButtonEditor.sizePolicy().hasHeightForWidth()) self.widgetButtonEditor.setSizePolicy(sizePolicy) sizePolicy = QSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding) sizePolicy.setHorizontalStretch(0) sizePolicy.setVerticalStretch(0) sizePolicy.setHeightForWidth(self.shellOut.sizePolicy().hasHeightForWidth()) self.shellOut.setSizePolicy(sizePolicy) self.shellOut.setVerticalScrollBarPolicy(Qt.ScrollBarAsNeeded) self.shell.setVerticalScrollBarPolicy(Qt.ScrollBarAsNeeded) ##------------ Layout ------------------------------- self.mainLayout = QGridLayout(self) self.mainLayout.setMargin(0) self.mainLayout.setSpacing(0) self.mainLayout.addWidget(self.widgetButton, 0, 0, 1, 1) self.mainLayout.addWidget(self.splitterEditor, 0, 1, 1, 1) self.shellOutWidget.layout().insertWidget(0, self.toolBar) self.layoutEditor = QGridLayout(self.widgetEditor) self.layoutEditor.setMargin(0) self.layoutEditor.setSpacing(0) self.layoutEditor.addWidget(self.toolBarEditor, 0, 1, 1, 1) self.layoutEditor.addWidget(self.widgetButtonEditor, 1, 0, 2, 1) self.layoutEditor.addWidget(self.tabEditorWidget, 1, 1, 1, 1) self.layoutEditor.addWidget(self.widgetFind, 2, 1, 1, 1) ## Layout for the find widget self.layoutFind = QGridLayout(self.widgetFind) self.layoutFind.setContentsMargins(0, 0, 0, 0) self.lineEditFind = QgsFilterLineEdit() placeHolderTxt = QCoreApplication.translate("PythonConsole", "Enter text to find...") if pyqtconfig.Configuration().qt_version >= 0x40700: self.lineEditFind.setPlaceholderText(placeHolderTxt) else: self.lineEditFind.setToolTip(placeHolderTxt) self.findNextButton = QToolButton() self.findNextButton.setEnabled(False) toolTipfindNext = QCoreApplication.translate("PythonConsole", "Find Next") self.findNextButton.setToolTip(toolTipfindNext) self.findNextButton.setIcon(QgsApplication.getThemeIcon("console/iconSearchNextEditorConsole.png")) self.findNextButton.setIconSize(QSize(24, 24)) self.findNextButton.setAutoRaise(True) self.findPrevButton = QToolButton() self.findPrevButton.setEnabled(False) toolTipfindPrev = QCoreApplication.translate("PythonConsole", "Find Previous") self.findPrevButton.setToolTip(toolTipfindPrev) self.findPrevButton.setIcon(QgsApplication.getThemeIcon("console/iconSearchPrevEditorConsole.png")) self.findPrevButton.setIconSize(QSize(24, 24)) self.findPrevButton.setAutoRaise(True) self.caseSensitive = QCheckBox() caseSensTr = QCoreApplication.translate("PythonConsole", "Case Sensitive") self.caseSensitive.setText(caseSensTr) self.wholeWord = QCheckBox() wholeWordTr = QCoreApplication.translate("PythonConsole", "Whole Word") self.wholeWord.setText(wholeWordTr) self.wrapAround = QCheckBox() self.wrapAround.setChecked(True) wrapAroundTr = QCoreApplication.translate("PythonConsole", "Wrap Around") self.wrapAround.setText(wrapAroundTr) self.layoutFind.addWidget(self.lineEditFind, 0, 1, 1, 1) self.layoutFind.addWidget(self.findPrevButton, 0, 2, 1, 1) self.layoutFind.addWidget(self.findNextButton, 0, 3, 1, 1) self.layoutFind.addWidget(self.caseSensitive, 0, 4, 1, 1) self.layoutFind.addWidget(self.wholeWord, 0, 5, 1, 1) self.layoutFind.addWidget(self.wrapAround, 0, 6, 1, 1) ##------------ Add first Tab in Editor ------------------------------- #self.tabEditorWidget.newTabEditor(tabName='first', filename=None) ##------------ Signal ------------------------------- self.findTextButton.toggled.connect(self.findTextEditor) self.objectListButton.toggled.connect(self.toggleObjectListWidget) self.commentEditorButton.triggered.connect(self.commentCode) self.uncommentEditorButton.triggered.connect(self.uncommentCode) self.runScriptEditorButton.triggered.connect(self.runScriptEditor) self.cutEditorButton.triggered.connect(self.cutEditor) self.copyEditorButton.triggered.connect(self.copyEditor) self.pasteEditorButton.triggered.connect(self.pasteEditor) self.showEditorButton.toggled.connect(self.toggleEditor) self.clearButton.triggered.connect(self.shellOut.clearConsole) self.optionsButton.triggered.connect(self.openSettings) self.loadProcessingButton.triggered.connect(self.processing) self.loadQtCoreButton.triggered.connect(self.qtCore) self.loadQtGuiButton.triggered.connect(self.qtGui) self.runButton.triggered.connect(self.shell.entered) self.openFileButton.triggered.connect(self.openScriptFile) self.openInEditorButton.triggered.connect(self.openScriptFileExtEditor) self.saveFileButton.triggered.connect(self.saveScriptFile) self.saveAsFileButton.triggered.connect(self.saveAsScriptFile) self.helpButton.triggered.connect(self.openHelp) self.connect(self.listClassMethod, SIGNAL('itemClicked(QTreeWidgetItem*, int)'), self.onClickGoToLine) self.lineEditFind.returnPressed.connect(self._findText) self.findNextButton.clicked.connect(self._findNext) self.findPrevButton.clicked.connect(self._findPrev) self.lineEditFind.textChanged.connect(self._textFindChanged) def _findText(self): self.tabEditorWidget.currentWidget().newEditor.findText(True) def _findNext(self): self.tabEditorWidget.currentWidget().newEditor.findText(True) def _findPrev(self): self.tabEditorWidget.currentWidget().newEditor.findText(False) def _textFindChanged(self): if self.lineEditFind.text(): self.findNextButton.setEnabled(True) self.findPrevButton.setEnabled(True) else: self.lineEditFind.setStyleSheet('') self.findNextButton.setEnabled(False) self.findPrevButton.setEnabled(False) def onClickGoToLine(self, item, column): tabEditor = self.tabEditorWidget.currentWidget().newEditor if item.text(1) == 'syntaxError': check = tabEditor.syntaxCheck(fromContextMenu=False) if check and not tabEditor.isReadOnly(): self.tabEditorWidget.currentWidget().save() return linenr = int(item.text(1)) itemName = str(item.text(0)) charPos = itemName.find(' ') if charPos != -1: objName = itemName[0:charPos] else: objName = itemName tabEditor.goToLine(objName, linenr) def processing(self): self.shell.commandConsole('processing') def qtCore(self): self.shell.commandConsole('qtCore') def qtGui(self): self.shell.commandConsole('qtGui') def toggleEditor(self, checked): self.splitterObj.show() if checked else self.splitterObj.hide() if not self.tabEditorWidget: self.tabEditorWidget.enableToolBarEditor(checked) self.tabEditorWidget.restoreTabsOrAddNew() def toggleObjectListWidget(self, checked): self.listClassMethod.show() if checked else self.listClassMethod.hide() def findTextEditor(self, checked): self.widgetFind.show() if checked else self.widgetFind.hide() def pasteEditor(self): self.tabEditorWidget.currentWidget().newEditor.paste() def cutEditor(self): self.tabEditorWidget.currentWidget().newEditor.cut() def copyEditor(self): self.tabEditorWidget.currentWidget().newEditor.copy() def runScriptEditor(self): self.tabEditorWidget.currentWidget().newEditor.runScriptCode() def commentCode(self): self.tabEditorWidget.currentWidget().newEditor.commentEditorCode(True) def uncommentCode(self): self.tabEditorWidget.currentWidget().newEditor.commentEditorCode(False) def openScriptFileExtEditor(self): tabWidget = self.tabEditorWidget.currentWidget() path = tabWidget.path import subprocess try: subprocess.Popen([os.environ['EDITOR'], path]) except KeyError: QDesktopServices.openUrl(QUrl.fromLocalFile(path)) def openScriptFile(self): lastDirPath = self.settings.value("pythonConsole/lastDirPath", QDir.homePath()) openFileTr = QCoreApplication.translate("PythonConsole", "Open File") fileList = QFileDialog.getOpenFileNames( self, openFileTr, lastDirPath, "Script file (*.py)") if fileList: for pyFile in fileList: for i in range(self.tabEditorWidget.count()): tabWidget = self.tabEditorWidget.widget(i) if tabWidget.path == pyFile: self.tabEditorWidget.setCurrentWidget(tabWidget) break else: tabName = QFileInfo(pyFile).fileName() self.tabEditorWidget.newTabEditor(tabName, pyFile) lastDirPath = QFileInfo(pyFile).path() self.settings.setValue("pythonConsole/lastDirPath", pyFile) self.updateTabListScript(pyFile, action='append') def saveScriptFile(self): tabWidget = self.tabEditorWidget.currentWidget() try: tabWidget.save() except (IOError, OSError) as error: msgText = QCoreApplication.translate('PythonConsole', 'The file <b>{0}</b> could not be saved. Error: {1}').format(tabWidget.path, error.strerror) self.callWidgetMessageBarEditor(msgText, 2, False) def saveAsScriptFile(self, index=None): tabWidget = self.tabEditorWidget.currentWidget() if not index: index = self.tabEditorWidget.currentIndex() if not tabWidget.path: fileName = self.tabEditorWidget.tabText(index) + '.py' folder = self.settings.value("pythonConsole/lastDirPath", QDir.home()) pathFileName = os.path.join(folder, fileName) fileNone = True else: pathFileName = tabWidget.path fileNone = False saveAsFileTr = QCoreApplication.translate("PythonConsole", "Save File As") filename = QFileDialog.getSaveFileName(self, saveAsFileTr, pathFileName, "Script file (*.py)") if filename: try: tabWidget.save(filename) except (IOError, OSError) as error: msgText = QCoreApplication.translate('PythonConsole', 'The file <b>{0}</b> could not be saved. Error: {1}').format(tabWidget.path, error.strerror) self.callWidgetMessageBarEditor(msgText, 2, False) if fileNone: tabWidget.path = None else: tabWidget.path = pathFileName return if not fileNone: self.updateTabListScript(pathFileName, action='remove') def openHelp(self): QgsContextHelp.run("PythonConsole") def openSettings(self): if optionsDialog(self).exec_(): self.shell.refreshSettingsShell() self.shellOut.refreshSettingsOutput() self.tabEditorWidget.refreshSettingsEditor() def callWidgetMessageBar(self, text): self.shellOut.widgetMessageBar(iface, text) def callWidgetMessageBarEditor(self, text, level, timed): self.tabEditorWidget.widgetMessageBar(iface, text, level, timed) def updateTabListScript(self, script, action=None): if action == 'remove': self.tabListScript.remove(script) elif action == 'append': if not self.tabListScript: self.tabListScript = [] if script not in self.tabListScript: self.tabListScript.append(script) else: self.tabListScript = [] self.settings.setValue("pythonConsole/tabScripts", self.tabListScript) def saveSettingsConsole(self): self.settings.setValue("pythonConsole/splitterConsole", self.splitter.saveState()) self.settings.setValue("pythonConsole/splitterObj", self.splitterObj.saveState()) self.settings.setValue("pythonConsole/splitterEditor", self.splitterEditor.saveState()) self.shell.writeHistoryFile(True) def restoreSettingsConsole(self): storedTabScripts = self.settings.value("pythonConsole/tabScripts", []) self.tabListScript = storedTabScripts self.splitter.restoreState(self.settings.value("pythonConsole/splitterConsole", QByteArray())) self.splitterEditor.restoreState(self.settings.value("pythonConsole/splitterEditor", QByteArray())) self.splitterObj.restoreState(self.settings.value("pythonConsole/splitterObj", QByteArray()))
class MikiWindow(QMainWindow): def __init__(self, settings, parent=None): super(MikiWindow, self).__init__(parent) self.setObjectName("mikiWindow") self.settings = settings self.notePath = settings.notePath lockPath = os.path.join(settings.notebookPath, '.mikidown_lock') if not os.path.exists(lockPath): self.lockPathFH = os.open(lockPath, os.O_CREAT | os.O_EXCL | os.O_RDWR) ################ Setup core components ################ self.notesTree = MikiTree(self) self.quickNoteNav = QLineEdit() self.notesTab = QWidget() self.completer = SlashPleter() self.completer.setModel(self.notesTree.model()) self.quickNoteNav.setCompleter(self.completer) self.notesTree.setObjectName("notesTree") self.initTree(self.notePath, self.notesTree) self.notesTree.sortItems(0, Qt.AscendingOrder) self.ix = None self.setupWhoosh() self.viewedList = QToolBar(self.tr('Recently Viewed'), self) self.viewedList.setIconSize(QSize(16, 16)) self.viewedList.setToolButtonStyle(Qt.ToolButtonTextBesideIcon) self.viewedListActions = [] self.noteSplitter = QSplitter(Qt.Horizontal) self.dockIndex = QDockWidget(self.tr("Index")) self.dockSearch = QDockWidget(self.tr("Search")) self.searchEdit = QLineEdit() self.searchView = MikiSearch(self) self.searchTab = QWidget() self.dockToc = QDockWidget(self.tr("TOC")) self.tocTree = TocTree() self.dockAttachment = QDockWidget(self.tr("Attachment")) self.attachmentView = AttachmentView(self) self.notesEdit = MikiEdit(self) self.notesEdit.setObjectName(self.tr("notesEdit")) self.loadHighlighter() self.notesView = MikiView(self) self.findBar = QToolBar(self.tr('Find'), self) self.findBar.setFixedHeight(30) self.findEdit = QLineEdit(self.findBar) self.checkBox = QCheckBox(self.tr('Match case'), self.findBar) self.statusBar = QStatusBar(self) self.statusLabel = QLabel(self) self.altPressed = False ################ Setup actions ################ self.actions = dict() self.setupActions() ################ Setup mainwindow ################ self.setupMainWindow() # show changelogs after upgrade mikidown if self.settings.version < __version__ or Mikibook.settings.value( "version", defaultValue="0") < __version__: self.changelogHelp() self.settings.qsettings.setValue("version", __version__) Mikibook.settings.setValue("version", __version__) def loadHighlighter(self): fnt = Mikibook.settings.value('editorFont', defaultValue=None) fntsize = Mikibook.settings.value('editorFontSize', type=int, defaultValue=12) header_scales_font = Mikibook.settings.value('headerScaleFont', type=bool, defaultValue=True) if fnt is not None: self.notesEdit.setFontFamily(fnt) self.notesEdit.setFontPointSize(fntsize) h = MikiHighlighter(parent=self.notesEdit, scale_font_sizes=header_scales_font) tw = Mikibook.settings.value('tabWidth', type=int, defaultValue=4) qfm = QFontMetrics(h.patterns[0][1].font()) self.notesEdit.setTabStopWidth(tw * qfm.width(' ')) def setupActions(self): # Global Actions actTabIndex = self.act(self.tr('Switch to Index Tab'), lambda: self.raiseDock(self.dockIndex), self.tr('Ctrl+Shift+I')) actTabSearch = self.act(self.tr('Switch to Search Tab'), lambda: self.raiseDock(self.dockSearch), self.tr('Ctrl+Shift+F')) self.addAction(actTabIndex) self.addAction(actTabSearch) ################ Menu Actions ################ # actions in menuFile actionNewPage = self.act(self.tr('&New Page...'), self.notesTree.newPage, QKeySequence.New) self.actions.update(newPage=actionNewPage) actionNewSubpage = self.act(self.tr('New Sub&page...'), self.notesTree.newSubpage, self.tr('Ctrl+Shift+N')) self.actions.update(newSubpage=actionNewSubpage) actionImportPage = self.act(self.tr('&Import Page...'), self.importPage) self.actions.update(importPage=actionImportPage) actionNBSettings = self.act(self.tr('Notebook Set&tings...'), self.notebookSettings) self.actions.update(NBSettings=actionNBSettings) actionMDSettings = self.act(self.tr('&Mikidown Settings...'), self.mikidownSettings) self.actions.update(MDSettings=actionMDSettings) actionOpenNotebook = self.act(self.tr('&Open Notebook...'), self.openNotebook, QKeySequence.Open) self.actions.update(openNotebook=actionOpenNotebook) actionReIndex = self.act(self.tr('Re-index'), self.reIndex) self.actions.update(reIndex=actionReIndex) actionSave = self.act(self.tr('&Save'), self.saveCurrentNote, QKeySequence.Save) actionSave.setEnabled(False) self.actions.update(save=actionSave) actionSaveAs = self.act(self.tr('Save &As...'), self.saveNoteAs, QKeySequence.SaveAs) self.actions.update(saveAs=actionSaveAs) actionHtml = self.act(self.tr('to &HTML'), self.notesEdit.saveAsHtml) self.actions.update(html=actionHtml) actionPrint = self.act(self.tr('&Print'), self.printNote, QKeySequence.Print) self.actions.update(print_=actionPrint) actionRenamePage = self.act(self.tr('&Rename Page...'), self.notesTree.renamePage, 'F2') self.actions.update(renamePage=actionRenamePage) actionDelPage = self.act(self.tr('&Delete Page'), self.notesTree.delPageWrapper, QKeySequence.Delete) self.actions.update(delPage=actionDelPage) actionQuit = self.act(self.tr('&Quit'), self.close, QKeySequence.Quit) actionQuit.setMenuRole(QAction.QuitRole) self.actions.update(quit=actionQuit) # actions in menuEdit actionUndo = self.act(self.tr('&Undo'), lambda: self.notesEdit.undo(), QKeySequence.Undo) actionUndo.setEnabled(False) self.notesEdit.undoAvailable.connect(actionUndo.setEnabled) self.actions.update(undo=actionUndo) actionRedo = self.act(self.tr('&Redo'), lambda: self.notesEdit.redo(), QKeySequence.Redo) actionRedo.setEnabled(False) self.notesEdit.redoAvailable.connect(actionRedo.setEnabled) self.actions.update(redo=actionRedo) actionFindText = self.act(self.tr('&Find Text'), self.findBar.setVisible, QKeySequence.Find, True) self.actions.update(findText=actionFindText) actionFindRepl = self.act(self.tr('Find and Replace'), FindReplaceDialog(self.notesEdit).open, QKeySequence.Replace) self.actions.update(findRepl=actionFindRepl) actionFind = self.act(self.tr('Next'), self.findText, QKeySequence.FindNext) self.actions.update(find=actionFind) actionFindPrev = self.act(self.tr('Previous'), lambda: self.findText(back=True), QKeySequence.FindPrevious) self.actions.update(findPrev=actionFindPrev) actionSortLines = self.act(self.tr('&Sort Lines'), self.sortLines) self.actions.update(sortLines=actionSortLines) actionQuickNav = self.act(self.tr("&Quick Open Note"), self.quickNoteNav.setFocus, self.tr('Ctrl+G')) self.addAction(actionQuickNav) actionInsertImage = self.act(self.tr('&Insert Attachment'), self.notesEdit.insertAttachmentWrapper, self.tr('Ctrl+I')) actionInsertImage.setEnabled(False) self.actions.update(insertImage=actionInsertImage) # actions in menuView QIcon.setThemeName( Mikibook.settings.value('iconTheme', QIcon.themeName())) #print(QIcon.themeName()) actionEdit = self.act(self.tr('Edit'), self.edit, self.tr('Ctrl+E'), True, QIcon.fromTheme('document-edit'), self.tr('Edit mode (Ctrl+E)')) self.actions.update(edit=actionEdit) actionSplit = self.act(self.tr('Split'), self.liveView, self.tr('Ctrl+R'), True, QIcon.fromTheme('view-split-left-right'), self.tr('Split mode (Ctrl+R)')) self.actions.update(split=actionSplit) actionFlipEditAndView = self.act(self.tr('Flip Edit and View'), self.flipEditAndView) actionFlipEditAndView.setEnabled(False) self.actions.update(flipEditAndView=actionFlipEditAndView) #actionLeftAndRight = self.act( # self.tr('Split into Left and Right'), trig=self.leftAndRight) #actionUpAndDown = self.act( # self.tr('Split into Up and Down'), trig=self.upAndDown) # self.actionLeftAndRight.setEnabled(False) # self.actionUpAndDown.setEnabled(False) # actions in menuHelp actionReadme = self.act(self.tr('README'), self.readmeHelp) self.actions.update(readme=actionReadme) actionChangelog = self.act(self.tr('Changelog'), self.changelogHelp) self.actions.update(changelog=actionChangelog) actionAboutQt = self.act(self.tr('About Qt'), qApp.aboutQt) self.actions.update(aboutQt=actionAboutQt) def setupMainWindow(self): self.resize(800, 600) screen = QDesktopWidget().screenGeometry() size = self.geometry() self.move((screen.width() - size.width()) / 2, (screen.height() - size.height()) / 2) self.setWindowTitle('{} - {}'.format(self.settings.notebookName, __appname__)) self.viewedList.setFixedHeight(25) self.noteSplitter.addWidget(self.notesEdit) self.noteSplitter.addWidget(self.notesView) mainSplitter = QSplitter(Qt.Vertical) mainSplitter.setChildrenCollapsible(False) mainSplitter.addWidget(self.viewedList) mainSplitter.addWidget(self.noteSplitter) mainSplitter.addWidget(self.findBar) self.setCentralWidget(mainSplitter) self.searchEdit.returnPressed.connect(self.searchNote) self.quickNoteNav.returnPressed.connect(self.openFuncWrapper) searchLayout = QVBoxLayout() searchLayout.addWidget(self.searchEdit) searchLayout.addWidget(self.searchView) self.searchTab.setLayout(searchLayout) indexLayout = QVBoxLayout(self.notesTab) indexLayout.addWidget(self.quickNoteNav) indexLayout.addWidget(self.notesTree) self.dockIndex.setObjectName("Index") self.dockIndex.setWidget(self.notesTab) self.dockSearch.setObjectName("Search") self.dockSearch.setWidget(self.searchTab) self.dockToc.setObjectName("TOC") self.dockToc.setWidget(self.tocTree) self.dockAttachment.setObjectName("Attachment") self.dockAttachment.setWidget(self.attachmentView) self.setDockOptions(QMainWindow.VerticalTabs) self.addDockWidget(Qt.LeftDockWidgetArea, self.dockIndex) self.addDockWidget(Qt.LeftDockWidgetArea, self.dockSearch) self.addDockWidget(Qt.LeftDockWidgetArea, self.dockToc) self.addDockWidget(Qt.LeftDockWidgetArea, self.dockAttachment) self.tabifyDockWidget(self.dockIndex, self.dockSearch) self.tabifyDockWidget(self.dockSearch, self.dockToc) self.tabifyDockWidget(self.dockToc, self.dockAttachment) self.setTabPosition(Qt.LeftDockWidgetArea, QTabWidget.North) self.dockIndex.raise_() # Put dockIndex on top of the tab stack menuBar = QMenuBar(self) self.setMenuBar(menuBar) menuFile = menuBar.addMenu(self.tr('&File')) menuEdit = menuBar.addMenu(self.tr('&Edit')) menuView = menuBar.addMenu(self.tr('&View')) menuHelp = menuBar.addMenu(self.tr('&Help')) # menuFile menuFile.addAction(self.actions['newPage']) menuFile.addAction(self.actions['newSubpage']) menuFile.addAction(self.actions['NBSettings']) menuFile.addAction(self.actions['MDSettings']) menuFile.addAction(self.actions['importPage']) menuFile.addAction(self.actions['openNotebook']) menuFile.addAction(self.actions['reIndex']) menuFile.addSeparator() menuFile.addAction(self.actions['save']) menuFile.addAction(self.actions['saveAs']) menuFile.addAction(self.actions['print_']) menuExport = menuFile.addMenu(self.tr('&Export')) menuExport.addAction(self.actions['html']) menuFile.addSeparator() menuFile.addAction(self.actions['renamePage']) menuFile.addAction(self.actions['delPage']) menuFile.addSeparator() menuFile.addAction(self.actions['quit']) # menuEdit menuEdit.addAction(self.actions['undo']) menuEdit.addAction(self.actions['redo']) menuEdit.addAction(self.actions['findText']) menuEdit.addAction(self.actions['findRepl']) menuEdit.addSeparator() menuEdit.addAction(self.actions['sortLines']) menuEdit.addAction(self.actions['insertImage']) # menuView menuView.addAction(self.actions['edit']) menuView.addAction(self.actions['split']) menuView.addAction(self.actions['flipEditAndView']) menuShowHide = menuView.addMenu(self.tr('Show/Hide')) menuShowHide.addAction(self.dockIndex.toggleViewAction()) menuShowHide.addAction(self.dockSearch.toggleViewAction()) menuShowHide.addAction(self.dockToc.toggleViewAction()) menuShowHide.addAction(self.dockAttachment.toggleViewAction()) #menuMode = menuView.addMenu(self.tr('Mode')) #menuMode.addAction(self.actionLeftAndRight) #menuMode.addAction(self.actionUpAndDown) # menuHelp menuHelp.addAction(self.actions['readme']) menuHelp.addAction(self.actions['changelog']) menuHelp.addAction(self.actions['aboutQt']) toolBar = QToolBar(self.tr("toolbar"), self) toolBar.setObjectName("toolbar") # needed in saveState() #toolBar.setIconSize(QSize(16, 16)) toolBar.setToolButtonStyle(Qt.ToolButtonTextBesideIcon) self.addToolBar(Qt.TopToolBarArea, toolBar) toolBar.addAction(self.actions['edit']) toolBar.addAction(self.actions['split']) self.findEdit.returnPressed.connect(self.findText) self.findBar.addWidget(self.findEdit) self.findBar.addWidget(self.checkBox) self.findBar.addAction(self.actions['findPrev']) self.findBar.addAction(self.actions['find']) self.findBar.setVisible(False) self.findBar.visibilityChanged.connect(self.findBarVisibilityChanged) self.setStatusBar(self.statusBar) self.statusBar.addWidget(self.statusLabel, 1) self.notesTree.currentItemChanged.connect( self.currentItemChangedWrapper) self.notesTree.nvwCallback = self.newNoteDisplay self.notesTree.nvwtCallback = self.newPlainTextNoteDisplay self.tocTree.itemClicked.connect(self.tocNavigate) self.notesEdit.textChanged.connect(self.noteEditted) self.notesEdit.document().modificationChanged.connect( self.modificationChanged) self.updateRecentViewedNotes() notes = self.settings.recentViewedNotes() if len(notes) != 0: item = self.notesTree.pageToItem(notes[0]) self.notesTree.setCurrentItem(item) def newNoteDisplay(self, item, anchor=None): msn = MikiSepNote(self.settings, item.text(0), self.notesTree.itemToFile(item), plain_text=False, parent=self) if anchor: msn.note_view.page().mainFrame().scrollToAnchor(anchor) msn.show() def newPlainTextNoteDisplay(self, item, anchor=None): msn = MikiSepNote(self.settings, item.text(0), self.notesTree.itemToFile(item), plain_text=True, parent=self) if anchor: item = msn.findItemByAnchor(anchor)[0] msn.tocNavigate(item) msn.show() def openFuncWrapper(self): self.openFunction(self.quickNoteNav.text())() def setupWhoosh(self): # Initialize whoosh index, make sure notePath/.indexdir exists indexdir = self.settings.indexdir try: self.ix = open_dir(indexdir) except: QDir().mkpath(indexdir) self.ix = create_in(indexdir, self.settings.schema) # Fork a process to update index, which benefit responsiveness. p = Thread(target=self.whoosh_index, args=()) p.start() def restore(self): """ Restore saved geometry and state. Set the status of side panels in View Menu correspondently. """ if self.settings.geometry: self.restoreGeometry(self.settings.geometry) if self.settings.windowstate: self.restoreState(self.settings.windowstate) def initTree(self, notePath, parent): ''' When there exist foo.md, foo.mkd, foo.markdown, only one item will be shown in notesTree. ''' if not QDir(notePath).exists(): return notebookDir = QDir(notePath) notesList = notebookDir.entryInfoList(['*.md', '*.mkd', '*.markdown'], QDir.NoFilter, QDir.Name | QDir.IgnoreCase) nl = [note.completeBaseName() for note in notesList] noduplicate = list(set(nl)) for name in noduplicate: item = QTreeWidgetItem(parent, [name]) path = notePath + '/' + name self.initTree(path, item) def updateToc(self): ''' TOC is updated in `updateView` tocTree fields: [hdrText, hdrPosition, hdrAnchor] ''' root = self.notesTree.currentPage() strip_math_for_header_parsing = False strip_fence_for_header_parsing = False if 'asciimathml' in self.settings.extensions: strip_math_for_header_parsing = True if 'fenced_code' in self.settings.extensions or 'extra' in self.settings.extensions: strip_fence_for_header_parsing = True self.tocTree.updateToc( root, parseHeaders(self.notesEdit.toPlainText(), strip_fenced_block=strip_fence_for_header_parsing, strip_ascii_math=strip_math_for_header_parsing)) def updateAttachmentView(self): # Update attachmentView to show corresponding attachments. item = self.notesTree.currentItem() index = self.attachmentView.model.index( self.notesTree.itemToAttachmentDir(item)) self.attachmentView.setRootIndex(index) def openFile(self, filename): fh = QFile(filename) try: if not fh.open(QIODevice.ReadOnly): raise IOError(fh.errorString()) except IOError as e: QMessageBox.warning( self, self.tr('Read Error'), self.tr('Failed to open %s: %s') % (filename, e)) finally: if fh is not None: noteBody = QTextStream(fh).readAll() fh.close() self.notesEdit.setPlainText(noteBody) self.notesView.scrollPosition = QPoint(0, 0) # self.actionSave.setEnabled(False) self.notesEdit.document().setModified(False) self.notesView.updateView() self.setCurrentNote() self.updateRecentViewedNotes() #self.statusLabel.setText(noteFullName) def currentItemChangedWrapper(self, current, previous): if current is None: return #if previous != None and self.notesTree.pageExists(previous): prev = self.notesTree.itemToPage(previous) if self.notesTree.pageExists(prev): self.saveNote(previous) currentFile = self.notesTree.itemToFile(current) self.openFile(currentFile) # Update attachmentView to show corresponding attachments. index = self.attachmentView.model.index( self.notesTree.itemToAttachmentDir(current)) self.attachmentView.setRootIndex(index) def tocNavigate(self, current): ''' works for notesEdit now ''' if current is None: return pos = int(current.text(1)) link = "file://" + self.notePath + "/#" + current.text(2) # Move cursor to END first will ensure # header is positioned at the top of visual area. self.notesEdit.moveCursor(QTextCursor.End) cur = self.notesEdit.textCursor() cur.setPosition(pos, QTextCursor.MoveAnchor) self.notesEdit.setTextCursor(cur) self.notesView.load(QUrl(link)) def switchNote(self, num): if num < len(self.viewedListActions): self.viewedListActions[num].trigger() def saveCurrentNote(self): item = self.notesTree.currentItem() self.saveNote(item) def saveNote(self, item): if self.notesEdit.document().isModified(): self.notesEdit.document().setModified(False) else: return self.notesEdit.save(item) def saveNoteAs(self): self.saveCurrentNote() fileName = QFileDialog.getSaveFileName( self, self.tr('Save as'), '', '(*.md *.mkd *.markdown);;' + self.tr('All files(*)')) if fileName == '': return if not QFileInfo(fileName).suffix(): fileName += '.md' fh = QFile(fileName) fh.open(QIODevice.WriteOnly) savestream = QTextStream(fh) savestream << self.notesEdit.toPlainText() fh.close() def printNote(self): printer = QPrinter(QPrinter.HighResolution) printer.setCreator(__appname__ + ' ' + __version__) printer.setDocName(self.notesTree.currentItem().text(0)) printdialog = QPrintDialog(printer, self) if printdialog.exec() == QDialog.Accepted: self.notesView.print_(printer) def noteEditted(self): """ Continuously get fired while editing""" self.updateToc() self.notesView.updateLiveView() def modificationChanged(self, changed): """ Fired one time: modified or not """ self.actions['save'].setEnabled(changed) name = self.notesTree.currentPage() self.statusBar.clearMessage() if changed: self.statusLabel.setText(name + '*') else: self.statusLabel.setText(name) def importPage(self): filename = QFileDialog.getOpenFileName( self, self.tr('Import file'), '', '(*.md *.mkd *.markdown *.txt);;' + self.tr('All files(*)')) if filename == '': return self.importPageCore(filename) def importPageCore(self, filename): fh = QFile(filename) fh.open(QIODevice.ReadOnly) fileBody = QTextStream(fh).readAll() fh.close() page = QFileInfo(filename).completeBaseName() fh = QFile(self.notesTree.pageToFile(page)) if fh.exists(): QMessageBox.warning(self, self.tr("Import Error"), self.tr("Page already exists: %s") % page) dialog = LineEditDialog(self.notePath, self) if dialog.exec_(): page = dialog.editor.text() fh.close() fh = QFile(self.notesTree.pageToFile(page)) else: return fh.open(QIODevice.WriteOnly) savestream = QTextStream(fh) savestream << fileBody fh.close() item = QTreeWidgetItem(self.notesTree, [page]) self.notesTree.sortItems(0, Qt.AscendingOrder) self.notesTree.setCurrentItem(item) def openNotebook(self): dialog = NotebookListDialog(self) if dialog.exec_(): pass def notebookSettings(self): dialog = NotebookSettingsDialog(self) if dialog.exec_(): pass def mikidownSettings(self): dialog = MikidownCfgDialog(self) if dialog.exec_(): pass def reIndex(self): """ Whoosh index breaks for unknown reasons (sometimes) """ shutil.rmtree(self.settings.indexdir) self.setupWhoosh() def act(self, name, trig, shortcut=None, checkable=False, icon=None, tooltip=None): """ A wrapper to several QAction methods """ if icon: action = QAction(icon, name, self) else: action = QAction(name, self) if shortcut: action.setShortcut(QKeySequence(shortcut)) action.setCheckable(checkable) if tooltip: action.setToolTip(tooltip) action.triggered.connect(trig) return action def edit(self, viewmode): """ Switch between EDIT and VIEW mode. """ if self.actions['split'].isChecked(): self.actions['split'].setChecked(False) self.notesView.setVisible(not viewmode) self.notesEdit.setVisible(viewmode) # Gives the keyboard input focus to notesEdit/notesView. # Without this, keyboard input may change note text even when # notesEdit is invisible. if viewmode: self.notesEdit.setFocus() else: self.notesView.setFocus() self.saveCurrentNote() self.actions['insertImage'].setEnabled(viewmode) #self.actionLeftAndRight.setEnabled(True) #self.actionUpAndDown.setEnabled(True) # Render the note text as it is. self.notesView.updateView() def liveView(self, viewmode): """ Switch between VIEW and LIVE VIEW mode. """ self.actions['split'].setChecked(viewmode) sizes = self.noteSplitter.sizes() if self.actions['edit'].isChecked(): self.actions['edit'].setChecked(False) self.notesView.setVisible(viewmode) splitSize = [sizes[0] * 0.45, sizes[0] * 0.55] else: self.notesEdit.setVisible(viewmode) splitSize = [sizes[1] * 0.45, sizes[1] * 0.55] # setFocus for the same reason as in edit(self, viewmode) if viewmode: self.notesEdit.setFocus() else: self.notesView.setFocus() self.actions['flipEditAndView'].setEnabled(viewmode) #self.actionUpAndDown.setEnabled(viewmode) self.actions['insertImage'].setEnabled(viewmode) self.noteSplitter.setSizes(splitSize) self.saveCurrentNote() # Render the note text as it is. self.notesView.updateView() def findBarVisibilityChanged(self, visible): self.actions['findText'].setChecked(visible) if visible: self.findEdit.setFocus(Qt.ShortcutFocusReason) def findText(self, back=False): flags = 0 if back: flags = QTextDocument.FindBackward if self.checkBox.isChecked(): flags = flags | QTextDocument.FindCaseSensitively text = self.findEdit.text() if not self.findMain(text, flags): if text in self.notesEdit.toPlainText(): cursor = self.notesEdit.textCursor() if back: cursor.movePosition(QTextCursor.End) else: cursor.movePosition(QTextCursor.Start) self.notesEdit.setTextCursor(cursor) self.findMain(text, flags) # self.notesView.findText(text, flags) def findMain(self, text, flags): viewFlags = QWebPage.FindFlags( flags) | QWebPage.FindWrapsAroundDocument if flags: self.notesView.findText(text, viewFlags) return self.notesEdit.find(text, flags) else: self.notesView.findText(text) return self.notesEdit.find(text) def sortLines(self): ''' sort selected lines TODO: second sort reverse the order ''' cursor = self.notesEdit.textCursor() start = cursor.selectionStart() end = cursor.selectionEnd() cursor.setPosition(start) cursor.movePosition(QTextCursor.StartOfLine) cursor.setPosition(end, mode=QTextCursor.KeepAnchor) cursor.movePosition(QTextCursor.EndOfLine, mode=QTextCursor.KeepAnchor) text = cursor.selectedText() lines = text.split('\u2029') # '\u2029' is the line break sortedLines = sorted(lines) cursor.insertText('\n'.join(sortedLines)) def notesEditInFocus(self, e): if e.gotFocus: self.actions['insertImage'].setEnabled(True) # if e.lostFocus: # self.actionInsertImage.setEnabled(False) # QWidget.focusInEvent(self,f) def searchNote(self): """ Sorting criteria: "title > path > content" Search matches are organized into html source. """ pattern = self.searchEdit.text() if not pattern: return results = [] print("Searching using", pattern) with self.ix.searcher() as searcher: matches = [] queryp = QueryParser("content", self.ix.schema) #allow escaped qutoes when regex searching queryp.add_plugin( RegexPlugin(expr=r'r"(?P<text>[^"\\]*(\\.[^"\\]*)*)"')) # ~~r"pattern" is the desired regex term format~~ Don't autoforce regexing query = queryp.parse(pattern) #print("durp durp", query) ms = searcher.search(query, limit=None) # default limit is 10! for m in ms: #if not m in matches: matches.append(m) for r in matches: title = r['title'] path = r['path'] term = r.highlights("content") results.append([title, path, term]) html = "" for title, path, hi in results: html += ("<p><a href='" + path + "'>" + title + "</a><br/><span class='path'>" + path + "</span><br/>" + hi + "</p>") self.searchView.setHtml(html) print("Finished searching", pattern) def whoosh_index(self): it = QTreeWidgetItemIterator(self.notesTree, QTreeWidgetItemIterator.All) print("Starting complete indexing.") #writer = self.ix.writer() writer = AsyncWriter(self.ix) while it.value(): treeItem = it.value() name = self.notesTree.itemToPage(treeItem) path = os.path.join(self.notesTree.pageToFile(name)).replace( os.sep, '/') print(path) fileobj = open(path, 'r', encoding='utf-8') content = fileobj.read() fileobj.close() if METADATA_CHECKER.match( content) and 'meta' in self.settings.extensions: no_metadata_content = METADATA_CHECKER.sub("", content, count=1).lstrip() self.settings.md.reset().convert(content) writer.update_document( path=name, title=parseTitle(content, name), content=no_metadata_content, tags=','.join(self.settings.md.Meta.get('tags', [])).strip()) else: writer.add_document(path=name, title=parseTitle(content, name), content=content, tags='') it += 1 writer.commit() print("Finished completely reindexing.") def listItemChanged(self, row): if row != -1: item = self.searchList.currentItem().data(Qt.UserRole) self.notesTree.setCurrentItem(item) flags = QWebPage.HighlightAllOccurrences self.notesView.findText(self.searchEdit.text(), flags) def setCurrentNote(self): item = self.notesTree.currentItem() name = self.notesTree.itemToPage(item) # Current note is inserted to head of list. notes = self.settings.recentViewedNotes() for f in notes: if f == name: notes.remove(f) notes.insert(0, name) recent_notes_n = Mikibook.settings.value('recentNotesNumber', type=int, defaultValue=20) if len(notes) > recent_notes_n: del notes[recent_notes_n:] self.settings.updateRecentViewedNotes(notes) def updateRecentViewedNotes(self): """ Switching notes will trigger this. When Alt pressed, show note number. """ self.viewedList.clear() self.viewedListActions = [] # Check notes exists. viewedNotes = self.settings.recentViewedNotes() existedNotes = [] i = 0 for f in viewedNotes: if self.notesTree.pageExists(f): existedNotes.append(f) names = f.split('/') if self.altPressed and i in range(1, 10): action = self.act(names[-1], self.openFunction(f), 'Alt+' + str(i), True, ViewedNoteIcon(i), 'Alt+' + str(i)) else: action = self.act(names[-1], self.openFunction(f), None, True) self.viewedListActions.append(action) i += 1 if not self.altPressed: self.settings.updateRecentViewedNotes(existedNotes) for action in self.viewedListActions: self.viewedList.addAction(action) if len(self.viewedListActions): self.viewedListActions[0].setChecked(True) def openFunction(self, name): item = self.notesTree.pageToItem(name) return lambda: self.notesTree.setCurrentItem(item) def raiseDock(self, widget): if not widget.isVisible(): widget.show() if widget == self.dockSearch: self.searchEdit.setFocus() widget.raise_() def flipEditAndView(self): index = self.noteSplitter.indexOf(self.notesEdit) if index == 0: self.noteSplitter.insertWidget(1, self.notesEdit) else: self.noteSplitter.insertWidget(0, self.notesEdit) def leftAndRight(self): self.liveView(True) self.noteSplitter.setOrientation(Qt.Horizontal) #self.actionLeftAndRight.setEnabled(False) #self.actionUpAndDown.setEnabled(True) def upAndDown(self): self.liveView(True) self.noteSplitter.setOrientation(Qt.Vertical) #self.actionUpAndDown.setEnabled(False) #self.actionLeftAndRight.setEnabled(True) def readmeHelp(self): readmeFile = '/usr/share/mikidown/README.mkd' if not os.path.exists(readmeFile): readmeFile = os.path.join( os.path.dirname(os.path.dirname(__file__)), 'README.mkd').replace(os.sep, '/') self.importPageCore(readmeFile) def changelogHelp(self): changeLog = "/usr/share/mikidown/Changelog.md" if not os.path.exists(changeLog): changeLog = os.path.join( os.path.dirname(os.path.dirname(__file__)), 'Changelog.md').replace(os.sep, '/') self.importPageCore(changeLog) def keyPressEvent(self, event): """ When Alt pressed, note number will be shown in viewedList. """ if event.key() == Qt.Key_Alt: self.altPressed = True self.updateRecentViewedNotes() else: QMainWindow.keyPressEvent(self, event) def keyReleaseEvent(self, event): if event.key() == Qt.Key_Alt: self.altPressed = False self.updateRecentViewedNotes() else: QMainWindow.keyPressEvent(self, event) def closeEvent(self, event): """ saveGeometry: Saves the current geometry and state for top-level widgets saveState: Restores the state of this mainwindow's toolbars and dockwidgets """ self.saveCurrentNote() self.ix.close() self.notesEdit.ix.close() if hasattr(self.notesTree, 'ix'): self.notesTree.ix.close() self.settings.saveGeometry(self.saveGeometry()) self.settings.saveWindowState(self.saveState()) event.accept() os.close(self.lockPathFH) lockPath = os.path.join(self.settings.notebookPath, '.mikidown_lock') os.remove(lockPath)
class Viewer(ViewerBase, ViewerClass): trackingChanged = pyqtSignal(bool) setLocationTriggered = pyqtSignal() updateFeatures = pyqtSignal(bool) layerChanged = pyqtSignal(QgsMapLayer) clearLine = pyqtSignal() closed = pyqtSignal() def __init__(self, callbackobject, parent=None): """Constructor.""" super(Viewer, self).__init__(parent) self.setupUi(self) self.callbackobject = callbackobject self.frame = self.webview.page().mainFrame() self.actiongroup = QActionGroup(self) self.actiongroup.setExclusive(True) self.actiongroup.triggered.connect(self.action_triggered) self.measuredialog = MeasureDialog(self) self.toolbar = QToolBar() self.qgisTrackButton = self.toolbar.addAction("QGIS Track") self.qgisTrackButton.setIcon(QIcon(":/icons/track")) self.qgisTrackButton.setCheckable(True) self.qgisTrackButton.setChecked(True) self.qgisTrackButton.toggled.connect(self.trackingChanged.emit) self.setlocationaction = self.toolbar.addAction("Set location") self.setlocationaction.setIcon(QIcon(":/icons/location")) self.setlocationaction.triggered.connect( self.setLocationTriggered.emit) self.setlocationaction.setCheckable(True) self.viewfeatures = self.toolbar.addAction("Load QGIS Features") self.viewfeatures.setIcon(QIcon(":/icons/features")) self.viewfeatures.setCheckable(True) self.viewfeatures.setChecked(True) self.viewfeatures.toggled.connect(self.updateFeatures.emit) spacer = QWidget() spacer.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding) self.toolbar.addWidget(spacer) self.measureaction = self.toolbar.addAction("measure") self.measureaction.setObjectName("Measure") self.measureaction.setIcon(QIcon(":/icons/measure")) self.measureaction.setCheckable(True) self.infoaction = self.toolbar.addAction("Info") self.infoaction.setObjectName("Info") self.infoaction.setIcon(QIcon(":/icons/info")) self.infoaction.setCheckable(True) self.selectaction = self.toolbar.addAction("Select") self.selectaction.setObjectName("Select") self.selectaction.setIcon(QIcon(":/icons/select")) self.selectaction.setCheckable(True) self.toolbar.addSeparator() self.deleteaction = self.toolbar.addAction("Delete") self.deleteaction.setIcon(QIcon(":/icons/delete")) self.deleteaction.triggered.connect(self.delete_selected) self.deleteaction.setEnabled(False) self.addaction = self.toolbar.addAction("Add") self.addaction.setObjectName("Add") self.addaction.setIcon(QIcon(":/icons/add")) self.addaction.setCheckable(True) self.moveaction = self.toolbar.addAction("Move") self.moveaction.setObjectName("Move") self.moveaction.setIcon(QIcon(":/icons/move")) self.moveaction.setCheckable(True) self.actiongroup.addAction(self.moveaction) self.actiongroup.addAction(self.addaction) self.actiongroup.addAction(self.infoaction) self.actiongroup.addAction(self.measureaction) self.actiongroup.addAction(self.selectaction) self.activelayercombo = QgsMapLayerComboBox() self.activelayercombo.layerChanged.connect(self.layer_changed) self.activelayeraction = self.toolbar.addWidget(self.activelayercombo) self.activelayercombo.setSizeAdjustPolicy(QComboBox.AdjustToContents) self.activelayercombo.currentIndexChanged.connect(self.index_changed) self.zvaluecheck = QCheckBox() self.zvaluecheck.setChecked(True) self.zvaluecheck.setText("Copy Z value") self.zvaluecheck.setToolTip( "Copy Z value from viewer to new features in QGIS. Must have a field named Z to enable" ) self.zvalueaction = self.toolbar.addWidget(self.zvaluecheck) self.dockWidgetContents.layout().insertWidget(0, self.toolbar) self.webview.settings().setAttribute(QWebSettings.PluginsEnabled, True) self.webview.settings().setAttribute(QWebSettings.JavascriptEnabled, True) self.webview.settings().setAttribute( QWebSettings.DeveloperExtrasEnabled, True) self.frame.setScrollBarPolicy(Qt.Horizontal, Qt.ScrollBarAlwaysOff) self.frame.setScrollBarPolicy(Qt.Vertical, Qt.ScrollBarAlwaysOff) self.frame.javaScriptWindowObjectCleared.connect( self.addcallbackobject) self.measuredialog.modeCombo.currentIndexChanged.connect( self.action_triggered) self.measuredialog.clearButton.clicked.connect(self.clear_line) self.earthmine = EarthmineAPI(self.frame) def closeEvent(self, event): self.closed.emit() super(Viewer, self).closeEvent(event) def index_changed(self, index): if index == -1: self.set_button_states(False, False, False, False) def clear_line(self): self.clearLine.emit() self.earthmine.clearLine() @property def copyZvalue(self): layer = self.active_layer if not layer: return False if layer.type() == QgsMapLayer.VectorLayer and layer.geometryType( ) == QGis.Point: return self.zvaluecheck.isChecked() else: return False @property def geom(self): return self.measuredialog.geom @geom.setter def geom(self, value): self.measuredialog.geom = value self.measuredialog.update_geom_labels() @property def tracking(self): return self.qgisTrackButton.isChecked() @property def mode(self): return self.measuredialog.mode @property def active_layer(self): return self.activelayercombo.currentLayer() def layer_changed(self, layer): if not layer: self.set_button_states(False, False, False, False) return if layer.type() == QgsMapLayer.VectorLayer: enabledselecttools = layer.geometryType() in [ QGis.Line, QGis.Point ] enableedittools = layer.isEditable() enabledelete = layer.isEditable() and layer.selectedFeatureCount() enablemove = layer.geometryType( ) == QGis.Point and layer.isEditable() else: enabledselecttools = False enableedittools = False enabledelete = False enablemove = False self.set_button_states(enabledselecttools, enableedittools, enabledelete, enablemove) self.action_triggered() self.layerChanged.emit(layer) def selection_changed(self, layer): if layer == self.active_layer: enabledelete = layer.isEditable() and layer.selectedFeatureCount() self.deleteaction.setEnabled(enabledelete) def set_button_states(self, selecttools, edittools, deleteenabled, moveenabled): actions = [self.selectaction, self.infoaction] for action in actions: action.setEnabled(selecttools) editactions = [self.deleteaction, self.moveaction, self.addaction] for action in editactions: action.setEnabled(edittools) if edittools: self.deleteaction.setEnabled(deleteenabled) self.moveaction.setEnabled(moveenabled) for action in editactions: if action is self.actiongroup.checkedAction( ) and not action.isEnabled(): self.infoaction.toggle() break layer = self.active_layer if not layer: enablez = False else: enablez = layer.type( ) == QgsMapLayer.VectorLayer and layer.geometryType() == QGis.Point self.zvalueaction.setEnabled(enablez) @property def current_action_color(self): action = self.actiongroup.checkedAction() color = int("0x00ff00", 16) if action == self.measureaction: if self.mode == "Vertical": color = int("0x0000ff", 16) return color def action_triggered(self, *args): action = self.actiongroup.checkedAction() layer = self.activelayercombo.currentLayer() self.clear_line() if not action: return if not action == self.measureaction and ( not layer or not layer.type() == QgsMapLayer.VectorLayer): return color = self.current_action_color actiondata = {} if action == self.measureaction: self.measuredialog.show() actiondata['mode'] = self.mode geomtype = None layerid = None else: self.measuredialog.hide() geomtype = QGis.vectorGeometryType(layer.geometryType()) layerid = layer.id() data = dict(action=action.objectName(), layer=layerid, geom=geomtype, actiondata=actiondata, color=color) self.earthmine.updateAction(data) def active_tool(self): action = self.actiongroup.checkedAction() if not action: return None return action.objectName() def update_current_layer(self, layer): self.activelayercombo.setLayer(layer) def addcallbackobject(self): self.frame.addToJavaScriptWindowObject("qgis", self.callbackobject) def loadviewer(self, url): self.webview.load(url) self.frame.addToJavaScriptWindowObject("qgis", self.callbackobject) def startViewer(self, settings): self.earthmine.startViewer(settings) def set_location(self, point): # # NOTE Set location takes WGS84 make sure you have transformed it first before sending self.earthmine.setLocation(point.x(), point.y()) def clear_features(self): self.earthmine.clearFeatures() def clear_layer_features(self, layerid): self.earthmine.clearLayerObjects(layerid) def remove_feature(self, layerid, featureid): """ :param features: A dict of layerid, id, lat, lng :return: """ self.earthmine.removeFeature(layerid, featureid) def load_features(self, layerdata, features): """ :param features: A dict of layerid, id, lat, lng :return: """ self.earthmine.loadFeatures(layerdata, features) def layer_loaded(self, layerid): return self.earthmine.layerLoaded(layerid) def clear_selection(self, layerid): self.earthmine.clearSelection(layerid) def set_selection(self, layerid, featureids, clearlast=True): self.earthmine.setSelection(layerid, featureids, clearlast) def edit_feature(self, layerid, featureid, nodes): self.earthmine.editFeature(layerid, featureid, nodes) def delete_selected(self): layer = self.active_layer layer.deleteSelectedFeatures()
class __IDE(QMainWindow): ############################################################################### # SIGNALS # # goingDown() ############################################################################### def __init__(self, start_server=False): QMainWindow.__init__(self) self.setWindowTitle('NINJA-IDE {Ninja-IDE Is Not Just Another IDE}') self.setMinimumSize(700, 500) #Load the size and the position of the main window self.load_window_geometry() #Start server if needed self.s_listener = None if start_server: self.s_listener = QLocalServer() self.s_listener.listen("ninja_ide") self.connect(self.s_listener, SIGNAL("newConnection()"), self._process_connection) #Profile handler self.profile = None #Opacity self.opacity = settings.MAX_OPACITY #Define Actions object before the UI self.actions = actions.Actions() #StatusBar self.status = status_bar.StatusBar(self) self.status.hide() self.setStatusBar(self.status) #Main Widget - Create first than everything else self.central = central_widget.CentralWidget(self) self.load_ui(self.central) self.setCentralWidget(self.central) #ToolBar self.toolbar = QToolBar(self) self.toolbar.setToolTip(self.tr("Press and Drag to Move")) self.toolbar.setToolButtonStyle(Qt.ToolButtonIconOnly) self.addToolBar(settings.TOOLBAR_AREA, self.toolbar) if settings.HIDE_TOOLBAR: self.toolbar.hide() #Install Shortcuts after the UI has been initialized self.actions.install_shortcuts(self) self.connect(self.mainContainer, SIGNAL("currentTabChanged(QString)"), self.actions.update_explorer) #Menu menubar = self.menuBar() file_ = menubar.addMenu(self.tr("&File")) edit = menubar.addMenu(self.tr("&Edit")) view = menubar.addMenu(self.tr("&View")) source = menubar.addMenu(self.tr("&Source")) project = menubar.addMenu(self.tr("&Project")) self.pluginsMenu = menubar.addMenu(self.tr("&Addins")) about = menubar.addMenu(self.tr("Abou&t")) #The order of the icons in the toolbar is defined by this calls self._menuFile = menu_file.MenuFile(file_, self.toolbar, self) self._menuView = menu_view.MenuView(view, self.toolbar, self) self._menuEdit = menu_edit.MenuEdit(edit, self.toolbar) self._menuSource = menu_source.MenuSource(source) self._menuProject = menu_project.MenuProject(project, self.toolbar) self._menuPlugins = menu_plugins.MenuPlugins(self.pluginsMenu) self._menuAbout = menu_about.MenuAbout(about) self.load_toolbar() #Plugin Manager services = { 'editor': plugin_services.MainService(), 'toolbar': plugin_services.ToolbarService(self.toolbar), 'menuApp': plugin_services.MenuAppService(self.pluginsMenu), 'explorer': plugin_services.ExplorerService(), 'misc': plugin_services.MiscContainerService(self.misc) } serviceLocator = plugin_manager.ServiceLocator(services) self.plugin_manager = plugin_manager.PluginManager( resources.PLUGINS, serviceLocator) self.plugin_manager.discover() #load all plugins! self.plugin_manager.load_all() #Tray Icon self.trayIcon = updates.TrayIconUpdates(self) self.trayIcon.show() self.connect(self._menuFile, SIGNAL("openFile(QString)"), self.mainContainer.open_file) self.connect(self.mainContainer, SIGNAL("fileSaved(QString)"), self.show_status_message) self.connect(self.mainContainer, SIGNAL("recentTabsModified(QStringList)"), self._menuFile.update_recent_files) def _process_connection(self): connection = self.s_listener.nextPendingConnection() connection.waitForReadyRead() data = connection.readAll() connection.close() if data: files, projects = data.split(ipc.project_delimiter, 1) files = map(lambda x: (x.split(':')[0], int(x.split(':')[1])), files.split(ipc.file_delimiter)) projects = projects.split(ipc.project_delimiter) self.load_session_files_projects(files, [], projects, None) def load_toolbar(self): self.toolbar.clear() toolbar_items = {} toolbar_items.update(self._menuFile.toolbar_items) toolbar_items.update(self._menuView.toolbar_items) toolbar_items.update(self._menuEdit.toolbar_items) toolbar_items.update(self._menuSource.toolbar_items) toolbar_items.update(self._menuProject.toolbar_items) for item in settings.TOOLBAR_ITEMS: if item == 'separator': self.toolbar.addSeparator() else: tool_item = toolbar_items.get(item, None) if tool_item is not None: self.toolbar.addAction(tool_item) #load action added by plugins, This is a special case when reload #the toolbar after save the preferences widget for toolbar_action in settings.get_toolbar_item_for_plugins(): self.toolbar.addAction(toolbar_action) def load_external_plugins(self, paths): for path in paths: self.plugin_manager.add_plugin_dir(path) #load all plugins! self.plugin_manager.discover() self.plugin_manager.load_all() def show_status_message(self, message): self.status.showMessage(message, 2000) def load_ui(self, centralWidget): #Set Application Font for ToolTips QToolTip.setFont(QFont(settings.FONT_FAMILY, 10)) #Create Main Container to manage Tabs self.mainContainer = main_container.MainContainer(self) self.connect(self.mainContainer, SIGNAL("currentTabChanged(QString)"), self.change_window_title) self.connect(self.mainContainer, SIGNAL("locateFunction(QString, QString, bool)"), self.actions.locate_function) self.connect(self.mainContainer, SIGNAL("navigateCode(bool, int)"), self.actions.navigate_code_history) self.connect(self.mainContainer, SIGNAL("addBackItemNavigation()"), self.actions.add_back_item_navigation) self.connect(self.mainContainer, SIGNAL("updateFileMetadata()"), self.actions.update_explorer) self.connect(self.mainContainer, SIGNAL("updateLocator(QString)"), self.actions.update_explorer) self.connect(self.mainContainer, SIGNAL("openPreferences()"), self._show_preferences) self.connect(self.mainContainer, SIGNAL("dontOpenStartPage()"), self._dont_show_start_page_again) self.connect(self.mainContainer, SIGNAL("currentTabChanged(QString)"), self.status.handle_tab_changed) # Update symbols self.connect(self.mainContainer, SIGNAL("updateLocator(QString)"), self.status.explore_file_code) #Create Explorer Panel self.explorer = explorer_container.ExplorerContainer(self) self.connect(self.central, SIGNAL("splitterCentralRotated()"), self.explorer.rotate_tab_position) self.connect(self.explorer, SIGNAL("updateLocator()"), self.status.explore_code) self.connect(self.explorer, SIGNAL("goToDefinition(int)"), self.actions.editor_go_to_line) self.connect(self.explorer, SIGNAL("projectClosed(QString)"), self.actions.close_files_from_project) #Create Misc Bottom Container self.misc = misc_container.MiscContainer(self) self.connect(self.mainContainer, SIGNAL("findOcurrences(QString)"), self.misc.show_find_occurrences) centralWidget.insert_central_container(self.mainContainer) centralWidget.insert_lateral_container(self.explorer) centralWidget.insert_bottom_container(self.misc) self.connect(self.mainContainer, SIGNAL("cursorPositionChange(int, int)"), self.central.lateralPanel.update_line_col) # TODO: Change current symbol on move #self.connect(self.mainContainer, #SIGNAL("cursorPositionChange(int, int)"), #self.explorer.update_current_symbol) self.connect(self.mainContainer, SIGNAL("enabledFollowMode(bool)"), self.central.enable_follow_mode_scrollbar) if settings.SHOW_START_PAGE: self.mainContainer.show_start_page() def _show_preferences(self): pref = preferences.PreferencesWidget(self.mainContainer) pref.show() def _dont_show_start_page_again(self): settings.SHOW_START_PAGE = False qsettings = QSettings() qsettings.beginGroup('preferences') qsettings.beginGroup('general') qsettings.setValue('showStartPage', settings.SHOW_START_PAGE) qsettings.endGroup() qsettings.endGroup() self.mainContainer.actualTab.close_tab() def load_session_files_projects(self, filesTab1, filesTab2, projects, current_file, recent_files=None): self.mainContainer.open_files(filesTab1, notIDEStart=False) self.mainContainer.open_files(filesTab2, mainTab=False, notIDEStart=False) self.explorer.open_session_projects(projects, notIDEStart=False) if current_file: self.mainContainer.open_file(current_file, notStart=False) if recent_files is not None: self._menuFile.update_recent_files(recent_files) def open_file(self, filename): if filename: self.mainContainer.open_file(filename) def open_project(self, project): if project: self.actions.open_project(project) def __get_profile(self): return self.profile def __set_profile(self, profileName): self.profile = profileName if self.profile is not None: self.setWindowTitle('NINJA-IDE (PROFILE: %s)' % self.profile) else: self.setWindowTitle( 'NINJA-IDE {Ninja-IDE Is Not Just Another IDE}') Profile = property(__get_profile, __set_profile) def change_window_title(self, title): if self.profile is None: self.setWindowTitle('NINJA-IDE - %s' % title) else: self.setWindowTitle('NINJA-IDE (PROFILE: %s) - %s' % (self.profile, title)) currentEditor = self.mainContainer.get_actual_editor() if currentEditor is not None: line = currentEditor.textCursor().blockNumber() + 1 col = currentEditor.textCursor().columnNumber() self.central.lateralPanel.update_line_col(line, col) def wheelEvent(self, event): if event.modifiers() == Qt.ShiftModifier: if event.delta() == 120 and self.opacity < settings.MAX_OPACITY: self.opacity += 0.1 elif event.delta() == -120 and self.opacity > settings.MIN_OPACITY: self.opacity -= 0.1 self.setWindowOpacity(self.opacity) event.ignore() else: QMainWindow.wheelEvent(self, event) def save_settings(self): """Save the settings before the application is closed with QSettings. Info saved: Tabs and projects opened, windows state(size and position). """ qsettings = QSettings() editor_widget = self.mainContainer.get_actual_editor() current_file = '' if editor_widget is not None: current_file = editor_widget.ID if qsettings.value('preferences/general/loadFiles', 'true') == 'true': openedFiles = self.mainContainer.get_opened_documents() projects_obj = self.explorer.get_opened_projects() projects = [p.path for p in projects_obj] qsettings.setValue('openFiles/projects', projects) if len(openedFiles) > 0: qsettings.setValue('openFiles/mainTab', openedFiles[0]) if len(openedFiles) == 2: qsettings.setValue('openFiles/secondaryTab', openedFiles[1]) qsettings.setValue('openFiles/currentFile', current_file) qsettings.setValue( 'openFiles/recentFiles', self.mainContainer._tabMain.get_recent_files_list()) qsettings.setValue('preferences/editor/bookmarks', settings.BOOKMARKS) qsettings.setValue('preferences/editor/breakpoints', settings.BREAKPOINTS) qsettings.setValue('preferences/general/toolbarArea', self.toolBarArea(self.toolbar)) #Save if the windows state is maximixed if (self.isMaximized()): qsettings.setValue("window/maximized", True) else: qsettings.setValue("window/maximized", False) #Save the size and position of the mainwindow qsettings.setValue("window/size", self.size()) qsettings.setValue("window/pos", self.pos()) #Save the size of de splitters qsettings.setValue("window/central/areaSize", self.central.get_area_sizes()) qsettings.setValue("window/central/mainSize", self.central.get_main_sizes()) #Save the toolbar visibility qsettings.setValue("window/hide_toolbar", not self.toolbar.isVisible()) #Save Profiles if self.profile is not None: self.actions.save_profile(self.profile) else: qsettings.setValue('ide/profiles', settings.PROFILES) def load_window_geometry(self): """Load from QSettings the window size of de Ninja IDE""" qsettings = QSettings() if qsettings.value("window/maximized", 'true') == 'true': self.setWindowState(Qt.WindowMaximized) else: print dir(QSizeF) self.resize( qsettings.value("window/size", QSizeF(800, 600)).toSize()) self.move( qsettings.value("window/pos", QPointF(100, 100)).toPoint()) def closeEvent(self, event): if self.s_listener: self.s_listener.close() if settings.CONFIRM_EXIT and \ self.mainContainer.check_for_unsaved_tabs(): unsaved_files = self.mainContainer.get_unsaved_files() txt = '\n'.join(unsaved_files) val = QMessageBox.question( self, self.tr("Some changes were not saved"), self.tr("%s\n\nDo you want to exit anyway?" % txt), QMessageBox.Yes, QMessageBox.No) if val == QMessageBox.No: event.ignore() QApplication.instance().setCursorFlashTime(cursor_flash_time) self.emit(SIGNAL("goingDown()")) self.save_settings() completion_daemon.shutdown_daemon() #close python documentation server (if running) self.mainContainer.close_python_doc() #Shutdown PluginManager self.plugin_manager.shutdown() def notify_plugin_errors(self): errors = self.plugin_manager.errors if errors: plugin_error_dialog = traceback_widget.PluginErrorDialog() for err_tuple in errors: plugin_error_dialog.add_traceback(err_tuple[0], err_tuple[1]) #show the dialog plugin_error_dialog.exec_()
def setupMainWindow(self): self.resize(800, 600) screen = QDesktopWidget().screenGeometry() size = self.geometry() self.move((screen.width() - size.width()) / 2, (screen.height() - size.height()) / 2) self.setWindowTitle('{} - {}'.format(self.settings.notebookName, __appname__)) self.viewedList.setFixedHeight(25) self.noteSplitter.addWidget(self.notesEdit) self.noteSplitter.addWidget(self.notesView) mainSplitter = QSplitter(Qt.Vertical) mainSplitter.setChildrenCollapsible(False) mainSplitter.addWidget(self.viewedList) mainSplitter.addWidget(self.noteSplitter) mainSplitter.addWidget(self.findBar) self.setCentralWidget(mainSplitter) self.searchEdit.returnPressed.connect(self.searchNote) self.quickNoteNav.returnPressed.connect(self.openFuncWrapper) searchLayout = QVBoxLayout() searchLayout.addWidget(self.searchEdit) searchLayout.addWidget(self.searchView) self.searchTab.setLayout(searchLayout) indexLayout = QVBoxLayout(self.notesTab) indexLayout.addWidget(self.quickNoteNav) indexLayout.addWidget(self.notesTree) self.dockIndex.setObjectName("Index") self.dockIndex.setWidget(self.notesTab) self.dockSearch.setObjectName("Search") self.dockSearch.setWidget(self.searchTab) self.dockToc.setObjectName("TOC") self.dockToc.setWidget(self.tocTree) self.dockAttachment.setObjectName("Attachment") self.dockAttachment.setWidget(self.attachmentView) self.setDockOptions(QMainWindow.VerticalTabs) self.addDockWidget(Qt.LeftDockWidgetArea, self.dockIndex) self.addDockWidget(Qt.LeftDockWidgetArea, self.dockSearch) self.addDockWidget(Qt.LeftDockWidgetArea, self.dockToc) self.addDockWidget(Qt.LeftDockWidgetArea, self.dockAttachment) self.tabifyDockWidget(self.dockIndex, self.dockSearch) self.tabifyDockWidget(self.dockSearch, self.dockToc) self.tabifyDockWidget(self.dockToc, self.dockAttachment) self.setTabPosition(Qt.LeftDockWidgetArea, QTabWidget.North) self.dockIndex.raise_() # Put dockIndex on top of the tab stack menuBar = QMenuBar(self) self.setMenuBar(menuBar) menuFile = menuBar.addMenu(self.tr('&File')) menuEdit = menuBar.addMenu(self.tr('&Edit')) menuView = menuBar.addMenu(self.tr('&View')) menuHelp = menuBar.addMenu(self.tr('&Help')) # menuFile menuFile.addAction(self.actions['newPage']) menuFile.addAction(self.actions['newSubpage']) menuFile.addAction(self.actions['NBSettings']) menuFile.addAction(self.actions['MDSettings']) menuFile.addAction(self.actions['importPage']) menuFile.addAction(self.actions['openNotebook']) menuFile.addAction(self.actions['reIndex']) menuFile.addSeparator() menuFile.addAction(self.actions['save']) menuFile.addAction(self.actions['saveAs']) menuFile.addAction(self.actions['print_']) menuExport = menuFile.addMenu(self.tr('&Export')) menuExport.addAction(self.actions['html']) menuFile.addSeparator() menuFile.addAction(self.actions['renamePage']) menuFile.addAction(self.actions['delPage']) menuFile.addSeparator() menuFile.addAction(self.actions['quit']) # menuEdit menuEdit.addAction(self.actions['undo']) menuEdit.addAction(self.actions['redo']) menuEdit.addAction(self.actions['findText']) menuEdit.addAction(self.actions['findRepl']) menuEdit.addSeparator() menuEdit.addAction(self.actions['sortLines']) menuEdit.addAction(self.actions['insertImage']) # menuView menuView.addAction(self.actions['edit']) menuView.addAction(self.actions['split']) menuView.addAction(self.actions['flipEditAndView']) menuShowHide = menuView.addMenu(self.tr('Show/Hide')) menuShowHide.addAction(self.dockIndex.toggleViewAction()) menuShowHide.addAction(self.dockSearch.toggleViewAction()) menuShowHide.addAction(self.dockToc.toggleViewAction()) menuShowHide.addAction(self.dockAttachment.toggleViewAction()) #menuMode = menuView.addMenu(self.tr('Mode')) #menuMode.addAction(self.actionLeftAndRight) #menuMode.addAction(self.actionUpAndDown) # menuHelp menuHelp.addAction(self.actions['readme']) menuHelp.addAction(self.actions['changelog']) menuHelp.addAction(self.actions['aboutQt']) toolBar = QToolBar(self.tr("toolbar"), self) toolBar.setObjectName("toolbar") # needed in saveState() #toolBar.setIconSize(QSize(16, 16)) toolBar.setToolButtonStyle(Qt.ToolButtonTextBesideIcon) self.addToolBar(Qt.TopToolBarArea, toolBar) toolBar.addAction(self.actions['edit']) toolBar.addAction(self.actions['split']) self.findEdit.returnPressed.connect(self.findText) self.findBar.addWidget(self.findEdit) self.findBar.addWidget(self.checkBox) self.findBar.addAction(self.actions['findPrev']) self.findBar.addAction(self.actions['find']) self.findBar.setVisible(False) self.findBar.visibilityChanged.connect(self.findBarVisibilityChanged) self.setStatusBar(self.statusBar) self.statusBar.addWidget(self.statusLabel, 1) self.notesTree.currentItemChanged.connect( self.currentItemChangedWrapper) self.notesTree.nvwCallback = self.newNoteDisplay self.notesTree.nvwtCallback = self.newPlainTextNoteDisplay self.tocTree.itemClicked.connect(self.tocNavigate) self.notesEdit.textChanged.connect(self.noteEditted) self.notesEdit.document().modificationChanged.connect( self.modificationChanged) self.updateRecentViewedNotes() notes = self.settings.recentViewedNotes() if len(notes) != 0: item = self.notesTree.pageToItem(notes[0]) self.notesTree.setCurrentItem(item)