def createToolBar(self, title, name=""): """ Public method to create a custom toolbar. @param title title to be used for the toolbar (string) @param name optional name for the new toolbar (string) @return reference to the created toolbar (QToolBar) """ if self.__mainWindow is None: return None toolBar = QToolBar(title, self.__mainWindow) toolBar.setToolTip(title) if not name: index = 1 customPrefix = "__CustomPrefix__" name = "{0}{1:d}".format(customPrefix, index) while self.__toolBarByName(name) is not None: index += 1 name = "{0}{1:d}".format(customPrefix, index) toolBar.setObjectName(name) self.__mainWindow.addToolBar(toolBar) tbID = id(toolBar) self.__customToolBars.append(toolBar) self.__allToolBars[tbID] = toolBar self.__toolBars[tbID] = [] self.__toolBarsWithSeparators[tbID] = [] if self.__ui is not None: toolBar.setIconSize(self.__ui.getToolBarIconSize()) self.__ui.registerToolbar(name, title, toolBar) return toolBar
class BufferSelectToolbar(object): def __init__(self, selectTool): super(BufferSelectToolbar, self).__init__() # references self.selectTool = selectTool self.result = None self.debug = self.selectTool.debug self.id = id self.config = self.selectTool.config self.info = Info(self) try: self.gtomain = self.selectTool.gtomain self.helper = self.gtomain.helper self.metadata = self.gtomain.metadata self.iface = self.gtomain.iface self.canvas = self.iface.mapCanvas() # tool data self.toolbar_dock = self.config.get("toolbar_dock", 4) self.toolbar_height = self.gtomain.toolbar_height # widget self.toolbar = None # load toolbar objName = "gtoTB_" + __name__ + str(id) self.toolbar = self.gtomain.helper.findToolbar(self.iface, objName) if self.toolbar is None: if self.debug: self.info.log("load", objName) self.toolbar = QToolBar() self.toolbar.setObjectName(objName) self.toolbar.setWindowTitle(u'GTO Buffer Selection') self.toolbar.setAllowedAreas(Qt.BottomToolBarArea | Qt.TopToolBarArea) self.iface.mainWindow().addToolBarBreak(self.toolbar_dock) self.iface.addToolBar(self.toolbar, self.toolbar_dock) # set the iconsize=> changed when self.iface.addToolBar :S if self.toolbar_height is not None: self.toolbar.setMaximumHeight(self.gtomain.toolbar_height) self.toolbar.setMinimumHeight(self.gtomain.toolbar_height) else: self.toolbar.clear() self.wid = Widget(self) self.toolbar.addWidget(self.wid) self.wid.setIconSizes(self.iface.iconSize(False)) self.wid.geometry_changed.connect(self.getGeometry) self.toolbar.setHidden(False) except Exception as e: self.info.err(e) # from mActionbufferselectxy def setHidden(self, a0): self.toolbar.setHidden(a0) def setGeometry(self, geo, isValid, isCircle=False, isRectangle=False): self.toolbar.setHidden(False) if self.debug: self.info.log("setGeometry", geo.isEmpty(), isValid, isCircle, isRectangle) self.wid.setOriginalGeometry(geo, isValid, isCircle, isRectangle) def getGeometry(self, geo): self.selectTool.setGeometryToMapTool(geo)
def init_menu(self): load_rom = self.create_action('載入Rom', self.load_rom) save_rom = self.create_action('保存Rom', self.save_rom) save_rom.setEnabled(False) save_as = self.create_action('另存為', self.save_as) save_as.setEnabled(False) close_child = self.create_action('關閉窗口', self.close_child) exit_editor = self.create_action('退出', self.close) file_menu = self.create_menu( '文件(&F)', None, [load_rom, save_rom, save_as, close_child, exit_editor]) value_editors = [ self.create_action(editor_name, self.open_editor_frame) for editor_name in CHILD_MAPPING ] edit_menu = self.create_menu('編輯(&E)', None, value_editors) edit_menu.setEnabled(False) self.menuBar().addMenu(file_menu) self.menuBar().addMenu(edit_menu) tool_bar = QToolBar('顯示標籤') tool_bar.setObjectName('工具') tool_bar.addActions(value_editors) tool_bar.setEnabled(False) tool_bar.setMovable(False) tool_bar.setVisible(False) self.addToolBar(tool_bar) action_group = QActionGroup(self) [(action_group.addAction(i), i.setCheckable(True)) for i in value_editors] action_group.setExclusive(True)
class run(QObject): # gtoAction def __init__(self, id, gtoTool, config, debug): super(run, self).__init__() # references self.debug = debug self.id = id self.config = config self.info = gtoTool.info try: self.action = gtoTool.action self.action.setCheckable(True) self.gtomain = gtoTool.gtomain self.helper = self.gtomain.helper self.metadata = self.gtomain.metadata self.iface = self.gtomain.iface self.canvas = self.iface.mapCanvas() if not self.config.get("is_widgetaction", False): # tool data self.toolbar_dock = self.config.get("toolbar_dock", 4) # widget self.toolbar = None # load toolbar self.objName = "gtoTB_" + gtoTool.action.objectName() + str(id) self.toolbar = self.gtomain.helper.findToolbar(self.iface, self.objName) if self.toolbar is None: if self.debug: self.info.log("load", self.objName) self.toolbar = QToolBar() self.toolbar.setObjectName(self.objName) self.toolbar.setWindowTitle(u'GTO Coordinate') self.toolbar.setAllowedAreas(Qt.BottomToolBarArea | Qt.TopToolBarArea) self.iface.mainWindow().addToolBarBreak(self.toolbar_dock) self.iface.addToolBar(self.toolbar, self.toolbar_dock) else: self.toolbar.clear() self.wid = GTOPointWidget(self.gtomain, self.toolbar) self.toolbar.addWidget(self.wid) if self.config.get("spacer", False): spacer = QWidget() spacer.setObjectName('spacer') spacer.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding) spacer.setStyleSheet("QWidget{background: transparent;}") self.toolbar.addWidget(spacer) self.wid.set_parent_widget(self) self.wid.isActive.connect(self.set_status) # not always(?) working? self.wid.setConfig(self.config) self.wid.added() self.wid.setMapTool() self.toolbar.show() except Exception as e: self.info.err(e) def set_status(self, isActive): try: self.action.setChecked(isActive) self.toolbar.setHidden(not isActive) except Exception as e: self.info.err(e)
def setupModelBar(self): """ Add a tool bar to the GUI for selecting which model to display """ leftToolBar = QToolBar() leftToolBar.setStyleSheet("background-color: rgb(60, 63, 65);") leftToolBar.setObjectName('lefttoolbar') leftToolBar.addWidget(self.modelButtonGroup()) self.addToolBar(Qt.LeftToolBarArea, leftToolBar)
def create_button_panel(self, horizontal): toolbar = QToolBar() if horizontal: toolbar.setObjectName("button_panel") else: toolbar.setObjectName("toolbox") if horizontal: self.window.addToolBar(Qt.TopToolBarArea, toolbar) else: self.window.addToolBar(Qt.LeftToolBarArea, toolbar) return ButtonPanel(toolbar)
def gui(self): self.systray = QSystemTrayIcon() self.icon = QIcon(':/sansimera.png') self.systray.setIcon(self.icon) self.systray.setToolTip('Σαν σήμερα...') self.menu = QMenu() self.exitAction = QAction('&Έξοδος', self) self.refreshAction = QAction('&Ανανέωση', self) self.aboutAction = QAction('&Σχετικά', self) self.notification_interval = QAction('Ει&δοποίηση εορταζόντων', self) self.menu.addAction(self.notification_interval) self.menu.addAction(self.refreshAction) self.menu.addAction(self.aboutAction) self.menu.addAction(self.exitAction) self.systray.setContextMenu(self.menu) self.notification_interval.triggered.connect(self.interval_namedays) self.exitAction.triggered.connect(exit) self.refreshAction.triggered.connect(self.refresh) self.aboutAction.triggered.connect(self.about) self.browser = QTextBrowser() self.browser.setOpenExternalLinks(True) self.setGeometry(600, 500, 400, 300) self.setWindowIcon(self.icon) self.setWindowTitle('Σαν σήμερα...') self.setCentralWidget(self.browser) self.systray.show() self.systray.activated.connect(self.activate) self.browser.append('Λήψη...') nicon = QIcon(':/next') picon = QIcon(':/previous') ricon = QIcon(':/refresh') iicon = QIcon(':/info') qicon = QIcon(':/exit') inicon = QIcon(':/notifications') self.nextAction = QAction('Επόμενο', self) self.nextAction.setIcon(nicon) self.previousAction = QAction('Προηγούμενο', self) self.refreshAction.triggered.connect(self.refresh) self.nextAction.triggered.connect(self.nextItem) self.previousAction.triggered.connect(self.previousItem) self.previousAction.setIcon(picon) self.refreshAction.setIcon(ricon) self.exitAction.setIcon(qicon) self.aboutAction.setIcon(iicon) self.notification_interval.setIcon(inicon) controls = QToolBar() self.addToolBar(Qt.BottomToolBarArea, controls) controls.setObjectName('Controls') controls.addAction(self.previousAction) controls.addAction(self.nextAction) controls.addAction(self.refreshAction) self.restoreState(self.settings.value("MainWindow/State", QByteArray())) self.refresh()
class run(object): def __init__(self, id, gtoTool, config, debug): super(run, self).__init__() try: # references self.result = None self.debug = debug self.id = id self.config = config self.info = gtoTool.info self.gtomain = gtoTool.gtomain self.helper = self.gtomain.helper self.metadata = self.gtomain.metadata self.iface = self.gtomain.iface # tool data widegt self.toolbar_dock = self.config.get("toolbar_dock", None) # widget self.toolbar = None self.wid = Widget(self, self.iface.mainWindow()) if self.toolbar_dock is not None: # load toolbar objName = "gtoTB_" + gtoTool.action.objectName() self.toolbar = self.gtomain.helper.findToolbar( self.iface, objName) if self.toolbar is None: if self.debug: self.info.log("load", objName) self.toolbar = QToolBar() self.toolbar.setObjectName(objName) self.toolbar.setWindowTitle(u'GTO Suche') self.toolbar.setAllowedAreas(Qt.BottomToolBarArea | Qt.TopToolBarArea) self.iface.mainWindow().addToolBarBreak(self.toolbar_dock) self.iface.addToolBar(self.toolbar, self.toolbar_dock) else: self.toolbar.clear() self.toolbar.setHidden(False) else: self.toolbar = self.gtomain.gtotb self.toolbar.addWidget(self.wid) if self.config.get("show_hide_button", False): self.helper.addToolbarClose(self.toolbar) self.toolbar.visibilityChanged.connect(self.reset) except Exception as e: self.info.err(e) def reset(self, *args): # from (gto)toolbar hidden/shown try: if self.debug: self.info.log("gtoAction reset") self.wid.reset() except Exception as e: self.info.err(e)
def init_bar(self) -> None: """ Init function bar, set to right side of widget :return: """ toolbar = QToolBar() toolbar.setObjectName('MapToolbar') self.mainWindow.addToolBar(Qt.RightToolBarArea, toolbar) # ------------------------------- Open map ---------------------------------- self.openMap_action = QAction(QIcon('resources/icons/openMap.png'), TR().tr('Open_map'), self.mainWindow, triggered=self.open_map_action, enabled=False) toolbar.addAction(self.openMap_action) # ------------------------------- Zoom in ---------------------------------- self.zoomIn_action = QAction(QIcon('resources/icons/zoomIn.png'), TR().tr('Zoom_in'), self.mainWindow, triggered=self.zoom_in_action, shortcut='Ctrl++', enabled=False) toolbar.addAction(self.zoomIn_action) # ------------------------------- Zoom out ---------------------------------- self.zoomOut_action = QAction(QIcon('resources/icons/zoomOut.png'), TR().tr('Zoom_out'), self.mainWindow, triggered=self.zoom_out_action, shortcut='Ctrl++', enabled=False) toolbar.addAction(self.zoomOut_action) # ------------------------------- Edit info ---------------------------------- self.info_action = QAction(QIcon('resources/icons/scroll.png'), TR().tr('Edit_info'), self.mainWindow, triggered=self.edit_info_action, shortcut='Ctrl+P', enabled=False) toolbar.addAction(self.info_action) toolbar.addSeparator() # ------------------------------- Add monster ---------------------------------- self.addMonster_action = QAction(QIcon('resources/icons/addMonster.png'), TR().tr('Add_monster'), self.mainWindow, triggered=self.add_monster_action, shortcut='Ctrl+M', enabled=False) toolbar.addAction(self.addMonster_action) # ------------------------------- Add item ---------------------------------- self.addItem_action = QAction(QIcon('resources/icons/addItem.png'), TR().tr('Add_item'), self.mainWindow, triggered=self.add_item_action, enabled=False) toolbar.addAction(self.addItem_action) # ------------------------------- Add room ---------------------------------- self.addRoom_action = QAction(QIcon('resources/icons/addRoom.png'), TR().tr('Add_room'), self.mainWindow, triggered=self.add_room_action, enabled=False) toolbar.addAction(self.addRoom_action) # ------------------------------- Add object ---------------------------------- self.addObject_action = QAction(QIcon('resources/icons/addObject.png'), TR().tr('Add_object_map'), self.mainWindow, triggered=self.add_object_action, enabled=False) toolbar.addAction(self.addObject_action)
def setup_toolbar(self): toolbar = QToolBar("Main Toolbar") toolbar.setObjectName("main-toolbar") toolbar.addAction(self.start_listening_action) toolbar.addAction(self.stop_listening_action) toolbar.addSeparator() toolbar.addAction(self.stop_debug_action) toolbar.addAction(self.detach_debug_action) toolbar.addSeparator() toolbar.addAction(self.run_debug_action) toolbar.addAction(self.step_over_action) toolbar.addAction(self.step_into_action) toolbar.addAction(self.step_out_action) self.addToolBar(toolbar)
class IPythonWorkspaceViewer(QMainWindow): """Class for workspace viewer controlled by IPython """ def __init__(self, parent=None): """ initialization including setting up UI :param parent: """ super(IPythonWorkspaceViewer, self).__init__(parent) # set up self.setObjectName(_fromUtf8("MainWindow")) self.resize(1600, 1200) self.centralwidget = QWidget(self) self.centralwidget.setObjectName(_fromUtf8("centralwidget")) self.gridLayout = QGridLayout(self.centralwidget) self.gridLayout.setObjectName(_fromUtf8("gridLayout")) self.widget = WorkspaceViewWidget(self) sizePolicy = QSizePolicy(QSizePolicy.Preferred, QSizePolicy.Expanding) sizePolicy.setHorizontalStretch(0) sizePolicy.setVerticalStretch(0) sizePolicy.setHeightForWidth( self.widget.sizePolicy().hasHeightForWidth()) self.widget.setSizePolicy(sizePolicy) self.widget.setObjectName(_fromUtf8("widget")) self.gridLayout.addWidget(self.widget, 1, 0, 1, 1) self.label = QLabel(self.centralwidget) self.label.setObjectName(_fromUtf8("label")) self.gridLayout.addWidget(self.label, 0, 0, 1, 1) self.setCentralWidget(self.centralwidget) self.menubar = QMenuBar(self) self.menubar.setGeometry(QtCore.QRect(0, 0, 1005, 25)) self.menubar.setObjectName(_fromUtf8("menubar")) self.setMenuBar(self.menubar) self.statusbar = QStatusBar(self) self.statusbar.setObjectName(_fromUtf8("statusbar")) self.setStatusBar(self.statusbar) self.toolBar = QToolBar(self) self.toolBar.setObjectName(_fromUtf8("toolBar")) self.addToolBar(QtCore.Qt.TopToolBarArea, self.toolBar) # self.retranslateUi(self) QtCore.QMetaObject.connectSlotsByName(self) return
def add_toolbar(self, name: str, toolbar: QToolBar, text: str = 'untitled toolbar'): b = self.top_toolbar_tab.add_button(text) toolbar.tab_button = b b.clicked.connect(lambda: self.switch_toolbar(name)) self.addToolBarBreak(Qt.TopToolBarArea) self.addToolBar(toolbar) toolbar.setObjectName(name) self.toolbars[name] = toolbar toolbar.setMovable(False) toolbar.setFloatable(False) if self._current_toolbar_name != '': self.refresh_toolbar_appearance()
def initBasicToolbar(self, ui, toolbarManager): """ Public slot to initialize the basic VCS toolbar. @param ui reference to the main window (UserInterface) @param toolbarManager reference to a toolbar manager object (E5ToolBarManager) @return the toolbar generated (QToolBar) """ tb = QToolBar(self.tr("VCS"), ui) tb.setIconSize(UI.Config.ToolBarIconSize) tb.setObjectName("VersionControlToolbar") tb.setToolTip(self.tr('VCS')) tb.addAction(self.vcsNewAct) tb.addAction(self.vcsExportAct) tb.addSeparator() tb.addAction(self.vcsAddAct) toolbarManager.addToolBar(tb, tb.windowTitle()) return tb
def add_toolbar(self, name: str, toolbar: QToolBar, text: str = 'untitled toolbar'): """ 添加一个工具栏。 """ b = self.top_toolbar_tab.add_button(text) toolbar.tab_button = b b.clicked.connect(lambda: self.on_toolbar_switch_button_clicked(name)) if hasattr(self, 'toolbar_path'): self.insertToolBar(self.toolbar_path, toolbar) self.insertToolBarBreak(self.toolbar_path) else: self.addToolBarBreak(Qt.TopToolBarArea) self.addToolBar(toolbar) toolbar.setObjectName(name) self.toolbars[name] = toolbar toolbar.setMovable(False) toolbar.setFloatable(False) if self._current_toolbar_name != '': self.refresh_toolbar_appearance()
def initToolbar(self, toolbarManager): """ Public slot to initialize the multi project toolbar. @param toolbarManager reference to a toolbar manager object (E5ToolBarManager) @return the toolbar generated (QToolBar) """ tb = QToolBar(self.tr("Multiproject"), self.ui) tb.setIconSize(UI.Config.ToolBarIconSize) tb.setObjectName("MultiProjectToolbar") tb.setToolTip(self.tr('Multiproject')) tb.addActions(self.actGrp1.actions()) tb.addAction(self.closeAct) tb.addSeparator() tb.addAction(self.saveAct) tb.addAction(self.saveasAct) toolbarManager.addToolBar(tb, tb.windowTitle()) toolbarManager.addAction(self.addProjectAct, tb.windowTitle()) toolbarManager.addAction(self.propsAct, tb.windowTitle()) return tb
class SMLSurveyor(object): def __init__(self, iface): # save reference to the QGIS interface self.iface = iface # get plugin directory self.plugin_dir = os.path.dirname(os.path.realpath(__file__)) self.uri = None self.connection = None self.crs = None self.database = None self.datetime = datetime.now() self.required_layers = [] # 1. beacons # 2. parcels self.required_layers.append( RequiredLayer('Beacon', 'Beacons', 'beacons', 'gid', 'points')) self.required_layers.append( RequiredLayer('Parcel', 'Parcels', 'parcels', 'parcel_id', 'polygons')) def initGui(self): """ Initialize gui """ # create plugin toolbar self.create_plugin_toolbar() def unload(self): """ Uninitialize gui """ # remove plugin toolbar self.remove_plugin_toolbar() # remove layers self.refresh_layers() for l in self.required_layers: if bool(l.layer): QgsProject.instance().removeMapLayers([l.layer.id()]) def create_plugin_toolbar(self): """ Create plugin toolbar to house buttons """ # create plugin toolbar self.plugin_toolbar = QToolBar('Parcel Plugin') self.plugin_toolbar.setObjectName('Parcel Plugin') # create Database Selection button self.select_database_action = QAction( QIcon(os.path.join(self.plugin_dir, "images", "database.png")), "Select Database Connection", self.iface.mainWindow()) self.select_database_action.setWhatsThis("Select database connection") self.select_database_action.setStatusTip("Select database connection") self.select_database_action.triggered.connect( self.manage_database_connection) # create Beardist button self.bearing_distance_action = QAction( QIcon(os.path.join(self.plugin_dir, "images", "beardist.png")), "Manage Bearings and Distances", self.iface.mainWindow()) self.bearing_distance_action.setWhatsThis( "Manage bearings and distances") self.bearing_distance_action.setStatusTip( "Manage bearings and distances") self.bearing_distance_action.triggered.connect( self.manage_bearing_distance) # create Beacons button self.beacons_action = QAction( QIcon(os.path.join(self.plugin_dir, "images", "beacon.gif")), "Manage Beacons", self.iface.mainWindow()) self.beacons_action.setWhatsThis("Manage beacons") self.beacons_action.setStatusTip("Manage beacons") self.beacons_action.triggered.connect(self.manage_beacons) # create Parcels button self.parcels_action = QAction( QIcon(os.path.join(self.plugin_dir, "images", "parcel.png")), "Manage Parcels", self.iface.mainWindow()) self.parcels_action.setWhatsThis("Manage parcels") self.parcels_action.setStatusTip("Manage parcels") self.parcels_action.triggered.connect(self.manage_parcels) # populate plugin toolbar self.plugin_toolbar.addAction(self.select_database_action) self.plugin_toolbar.addAction(self.bearing_distance_action) self.plugin_toolbar.addAction(self.beacons_action) self.plugin_toolbar.addAction(self.parcels_action) # add plugin toolbar to gui self.iface.mainWindow().addToolBar(self.plugin_toolbar) def remove_plugin_toolbar(self): """ Remove plugin toolbar which houses buttons """ # remove app toolbar from gui if hasattr(self, "pluginToolBar"): self.iface.mainWindow().removeToolBar(self.plugin_toolbar) self.plugin_toolbar.hide() def set_database_connection(self, connection=None, crs=None): """ Create a database connection """ # fetch settings settings_plugin = QSettings() settings_postgis = QSettings() settings_plugin.beginGroup('CoGo Plugin') settings_postgis.beginGroup('PostgreSQL/connections') self.connection = connection if not bool(self.connection): # fetch pre-chosen database connection self.connection = settings_plugin.value("DatabaseConnection", None) # check if still exists if bool(self.connection): if self.connection not in settings_postgis.childGroups(): settings_plugin.setValue("DatabaseConnection", "") self.connection = None # fetch from user if necessary if not bool(self.connection): dialog = DatabaseConnectionDialog() dialog.show() if bool(dialog.exec_()): self.connection = dialog.get_database_connection() if dialog.get_crs(): self.crs = QgsCoordinateReferenceSystem( dialog.get_crs().get('auth_id')) settings_plugin.setValue("DatabaseConnection", self.connection) # validate database connection if bool(self.connection): db_service = settings_postgis.value(self.connection + '/service') db_host = settings_postgis.value(self.connection + '/host') db_port = settings_postgis.value(self.connection + '/port') db_name = settings_postgis.value(self.connection + '/database') db_username = settings_postgis.value(self.connection + '/username') db_password = settings_postgis.value(self.connection + '/password') max_attempts = 3 self.uri = QgsDataSourceUri() self.uri.setConnection(db_host, db_port, db_name, db_username, db_password) if db_username and db_password: for i in range(max_attempts): error_message = self.connect_to_db(db_service, db_host, db_port, db_name, db_username, db_password) if error_message: ok, db_username, db_password = ( QgsCredentials.instance().get( self.uri.connectionInfo(), db_username, db_password, error_message)) if not ok: break else: break else: msg = "Please enter the username and password." for i in range(max_attempts): ok, db_username, db_password = ( QgsCredentials.instance().get( self.uri.connectionInfo(), db_username, db_password, msg)) if not ok: break error_message = self.connect_to_db(db_service, db_host, db_port, db_name, db_username, db_password) if not error_message: break settings_plugin.endGroup() settings_postgis.endGroup() def connect_to_db(self, service, host, port, name, username, password): username.replace(" ", "") password.replace(" ", "") try: self.database = database.Manager({ "CONNECTION": self.connection, "SERVICE": service, "HOST": host, "NAME": name, "PORT": port, "USER": username, "PASSWORD": password }) self.uri.setConnection(host, port, name, username, password) self.datetime = datetime.now() return None except Exception as e: self.database = None msg = "Invalid username and password." return msg def refresh_layers(self): """ Ensure all required layers exist """ if bool(self.database): # Comment out below section because connection name is better # to be a group name than crs name IMHO. # # first, we need to check the layer group for the crs used by # # current database # query = "SELECT Find_SRID('public', 'beacons', 'the_geom');" # self.database.connect(self.database.parameters) # cursor = self.database.cursor # cursor.execute(query) # crs_id = int(cursor.fetchall()[0][0]) # del cursor # group_name = None # for key, value in crs_options.iteritems(): # if value == crs_id: # group_name = key group_name = self.connection root = QgsProject.instance().layerTreeRoot() target_group = root.findGroup(group_name) if not bool(target_group): target_group = root.insertGroup(0, group_name) target_group.setItemVisibilityChecked(Qt.Checked) for required_layer in reversed(self.required_layers): for layer_node in target_group.findLayers(): layer = layer_node.layer() if required_layer.name_plural.lower() == \ layer.name().lower(): target_group.removeLayer(layer) for required_layer in self.required_layers: self.uri.setDataSource(required_layer.schema, required_layer.table, required_layer.geometry_column, '', required_layer.primary_key) added_layer = QgsVectorLayer(self.uri.uri(), required_layer.name_plural, "postgres") QgsProject.instance().addMapLayer(added_layer, False) target_group.addLayer(added_layer) for layer_node in target_group.findLayers(): layer = layer_node.layer() if required_layer.name_plural == layer.name(): required_layer.layer = layer layer_node.setItemVisibilityChecked(Qt.Checked) if self.crs: layer.setCrs(self.crs) self.iface.zoomToActiveLayer() def manage_beacons(self): """ Portal which enables the management of beacons """ if self.datetime.date() != datetime.now().date(): self.database = None if self.database is None: self.set_database_connection() if self.database is None: return BeaconManager(self.iface, self.database, self.required_layers) validate_plugin_actions(self, self.database) self.iface.mapCanvas().refresh() def manage_parcels(self): """ Portal which enables the management of parcels """ if self.datetime.date() != datetime.now().date(): self.database = None if self.database is None: self.set_database_connection() if self.database is None: return ParcelManager(self.iface, self.database, self.required_layers) validate_plugin_actions(self, self.database) self.iface.mapCanvas().refresh() def manage_bearing_distance(self): """ Portal which enables the management of bearings and distances """ if self.datetime.date() != datetime.now().date(): self.database = None if self.database is None: self.set_database_connection() if self.database is None: return result = validate_plugin_actions(self, self.database) if not result: QMessageBox.warning( None, "SML Surveyor", ("No Beacons available in the table. " "Please use Beacon Manager tool to create a Beacon.")) else: BearDistManager(self.iface, self.database, self.required_layers) self.iface.mapCanvas().refresh() def manage_database_connection(self): """ Action to select the db connection to work with. """ database_manager = DatabaseManager() connection = database_manager.get_current_connection() crs = database_manager.get_current_crs() if connection: self.set_database_connection(connection=connection, crs=crs) self.refresh_layers() if self.database: validate_plugin_actions(self, self.database)
class MainWindow(QMainWindow): """This is the main application window class it defines the GUI window for the browser """ def parse_config(self, file_config, options): self.config = {} options = vars(options) for key, metadata in CONFIG_OPTIONS.items(): options_val = options.get(key) file_val = file_config.get(key) env_val = os.environ.get(metadata.get("env", '')) default_val = metadata.get("default") vals = metadata.get("values") debug("key: {}, default: {}, file: {}, options: {}".format( key, default_val, file_val, options_val)) if vals: options_val = (options_val in vals and options_val) or None file_val = (file_val in vals and file_val) or None env_val = (env_val in vals and env_val) or None if metadata.get("is_file"): filename = options_val or env_val if not filename: self.config[key] = default_val else: try: with open(filename, 'r') as fh: self.config[key] = fh.read() except IOError: debug("Could not open file {} for reading.".format( filename)) self.config[key] = default_val else: set_values = [ val for val in (options_val, env_val, file_val) if val is not None ] if len(set_values) > 0: self.config[key] = set_values[0] else: self.config[key] = default_val if metadata.get("type") and self.config[key]: debug("{} cast to {}".format(key, metadata.get("type"))) self.config[key] = metadata.get("type")(self.config[key]) debug(repr(self.config)) def createAction(self, text, slot=None, shortcut=None, icon=None, tip=None, checkable=False, signal="triggered"): """Return a QAction given a number of common QAction attributes Just a shortcut function Originally 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(":/{}.png".format(icon)))) if shortcut is not None and not shortcut.isEmpty(): action.setShortcut(shortcut) tip += " ({})".format(shortcut.toString()) if tip is not None: action.setToolTip(tip) action.setStatusTip(tip) if slot is not None: action.__getattr__(signal).connect(slot) if checkable: action.setCheckable() return action def __init__(self, options, parent=None): """Construct a MainWindow Object.""" super(MainWindow, self).__init__(parent) # Load config file self.setWindowTitle("Browser") debug("loading configuration from '{}'".format(options.config_file)) configfile = {} if options.config_file: configfile = yaml.safe_load(open(options.config_file, 'r')) self.parse_config(configfile, options) # self.popup will hold a reference to the popup window # if it gets opened self.popup = None # Stylesheet support if self.config.get("stylesheet"): try: with open(self.config.get("stylesheet")) as ss: self.setStyleSheet(ss.read()) except: debug(('Problem loading stylesheet file "{}", ' 'using default style.').format( self.config.get("stylesheet"))) self.setObjectName("global") # Set proxy server environment variable before creating web views if self.config.get("proxy_server"): os.environ["http_proxy"] = self.config.get("proxy_server") os.environ["https_proxy"] = self.config.get("proxy_server") # If the whitelist is activated, add the bookmarks and start_url if self.config.get("whitelist"): # we can just specify whitelist = True, # which should whitelist just the start_url and bookmark urls. if type(self.config.get("whitelist")) is not list: self.whitelist = [] self.whitelist.append( str(QUrl(self.config.get("start_url")).host())) bookmarks = self.config.get("bookmarks") if bookmarks: self.whitelist += [ str(QUrl(b.get("url")).host()) for k, b in bookmarks.items() ] self.whitelist = set(self.whitelist) # uniquify and optimize debug("Generated whitelist: " + str(self.whitelist)) # create the web engine profile self.create_webprofile() # Now construct the UI self.build_ui() # ## END OF CONSTRUCTOR ## # def create_webprofile(self): """Create a webengineprofile to use in all views.""" if self.config.get("privacy_mode"): webprofile = QWebEngineProfile() else: webprofile = QWebEngineProfile.defaultProfile() debug("Browser session is private: {}".format( webprofile.isOffTheRecord())) if self.config.get("user_agent"): webprofile.setHttpUserAgent(self.config["user_agent"]) debug('Set user agent to "{}"'.format(webprofile.httpUserAgent())) self.webprofile = webprofile def build_ui(self): """Set up the user interface for the main window. Unlike the constructor, this method is re-run whenever the browser is "reset" by the user. """ debug("build_ui") inactivity_timeout = self.config.get("timeout") quit_button_tooltip = ("Click here to quit" if self.config.get('quit_button_mode') == 'close' else "Click here when you are done" "\nIt will clear your browsing history" " and return you to the start page.") qb_mode_callbacks = {'close': self.close, 'reset': self.reset_browser} to_mode_callbacks = { 'close': self.close, 'reset': self.reset_browser, 'screensaver': self.screensaver } self.screensaver_active = False # ##Start GUI configuration## # self.browser_window = AdmWebView(self.config, webprofile=self.webprofile) self.browser_window.setObjectName("web_content") self.setCentralWidget(self.browser_window) # Icon theme setting QIcon.setThemeName(self.config.get("icon_theme")) self.setCentralWidget(self.browser_window) debug("loading {}".format(self.config.get("start_url"))) self.browser_window.setUrl(QUrl(self.config.get("start_url"))) # Window size settings window_size = self.config.get("window_size", '').lower() if window_size == 'full': self.showFullScreen() elif window_size == 'max': self.showMaximized() elif window_size: size = re.match(r"(\d+)x(\d+)", window_size) if size: width, height = size.groups() self.setFixedSize(int(width), int(height)) else: debug('Ignoring invalid window size "{}"'.format(window_size)) # Set up the top navigation bar if it's configured to exist if self.config.get("navigation"): 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 = { "back": self.browser_window.pageAction(AdmWebPage.Back), "forward": self.browser_window.pageAction(AdmWebPage.Forward), "refresh": self.browser_window.pageAction(AdmWebPage.Reload), "stop": self.browser_window.pageAction(AdmWebPage.Stop), "quit": self.createAction( self.config.get("quit_button_text"), qb_mode_callbacks.get(self.config.get("quit_button_mode"), self.reset_browser), QKeySequence("Alt+F"), None, quit_button_tooltip), "zoom_in": self.createAction( "Zoom In", self.zoom_in, QKeySequence("Alt++"), "zoom-in", "Increase the size of the text and images on the page"), "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.config.get("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.config.get("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 = [] for bookmark in self.config.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.event_filter.timeout.connect( to_mode_callbacks.get(self.config.get("timeout_mode"), self.reset_browser)) else: self.event_filter = None # ##END OF UI SETUP## # def screensaver(self): """Enter "screensaver" mode This method puts the browser in screensaver mode, where a URL is displayed while the browser is idle. Activity causes the browser to return to the home screen. """ debug("screensaver started") self.screensaver_active = True if self.popup: self.popup.close() if self.config.get("navigation"): self.navigation_bar.hide() self.browser_window.setZoomFactor(self.config.get("zoom_factor")) self.browser_window.load(QUrl(self.config.get("screensaver_url"))) self.event_filter.timeout.disconnect() self.event_filter.activity.connect(self.reset_browser) def reset_browser(self): """Clear the history and reset the UI. Called whenever the inactivity filter times out, or when the user clicks the "finished" button in 'reset' mode. """ # Clear out the memory cache #QWebEngineSettings.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.event_filter.activity.disconnect() if self.event_filter: self.event_filter.blockSignals(False) if hasattr(self, "navigation_bar"): self.removeToolBar(self.navigation_bar) self.build_ui() def zoom_in(self): """Zoom in action callback. 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): """Zoom out action callback. 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)
class Ui_MainWindow(QMainWindow): def __init__(self): super().__init__() # self.initUI() self.init_ui() self.generateData() self.UI_style() def init_ui(self): self.setFixedSize(1200, 700) self.setWindowTitle('STalking') self.setWindowIcon(QIcon("icon/stlogo.ico")) self.main_widget = QtWidgets.QWidget() # 创建窗口主部件 self.main_widget.setObjectName('main_widget') self.main_layout = QtWidgets.QGridLayout() # 创建主部件的网格布局 self.main_widget.setLayout(self.main_layout) # 设置窗口主部件布局为网格布局 self.left_widget = QtWidgets.QWidget() # 创建左侧部件 左侧为功能按钮 self.left_widget.setObjectName('left_widget') self.left_layout = QtWidgets.QGridLayout() # 创建左侧部件的网格布局层 self.left_widget.setLayout(self.left_layout) # 设置左侧部件布局为网格 self.center_Splitter = QSplitter(Qt.Horizontal) self.center_Splitter.setObjectName('center_Splitter') self.center_layout = QtWidgets.QGridLayout() self.center_Splitter.setLayout(self.center_layout) # 设置右侧部件布局为网格 self.main_layout.addWidget(self.left_widget, 0, 0, 16, 3) # 左侧部件在第0行第0列,占8行3列 # self.main_layout.addWidget(self.center_QWidget, 0, 3, 16, 17) # 左侧部件在第0行第3列,占8行3列 self.main_layout.addWidget(self.center_Splitter, 0, 3, 16, 17) # 左侧部件在第0行第3列,占8行3列 self.setCentralWidget(self.main_widget) # 设置窗口主部件 self.icon_button = QtWidgets.QToolButton() self.icon_button.setIcon(QtGui.QIcon('icon/stlogo.ico')) # 设置按钮图标 self.icon_button.setIconSize(QtCore.QSize(150, 100)) # 设置图标大小 self.left_label_1 = QtWidgets.QPushButton("模型选择") self.left_label_1.setObjectName('left_label') self.left_label_2 = QtWidgets.QPushButton("保存与设置") self.left_label_2.setObjectName('left_label') self.left_label_3 = QtWidgets.QPushButton("其他") self.left_label_3.setObjectName('left_label') self.left_button_1 = QtWidgets.QPushButton( qtawesome.icon('fa.database', color='gray'), "选择GMM") self.left_button_1.setObjectName('left_button') self.left_button_2 = QtWidgets.QPushButton( qtawesome.icon('fa.file', color='gray'), "选择UBM") self.left_button_2.setObjectName('left_button') self.left_button_3 = QtWidgets.QPushButton( qtawesome.icon('fa.plus-circle', color='gray'), "选择视频") self.left_button_3.setObjectName('left_button') self.left_button_4 = QtWidgets.QPushButton( qtawesome.icon('fa.save', color='gray'), "保存模型") self.left_button_4.setObjectName('left_button') self.left_button_5 = QtWidgets.QPushButton( qtawesome.icon('fa.file', color='gray'), "模型路径") self.left_button_5.setObjectName('left_button') self.left_button_6 = QtWidgets.QPushButton( qtawesome.icon('fa.folder-open', color='gray'), "文件路径") self.left_button_6.setObjectName('left_button') self.left_button_7 = QtWidgets.QPushButton( qtawesome.icon('fa.comment', color='gray'), "使用向导") self.left_button_7.setObjectName('left_button') self.left_button_8 = QtWidgets.QPushButton( qtawesome.icon('fa.star', color='gray'), "版权说明") self.left_button_8.setObjectName('left_button') self.left_button_9 = QtWidgets.QPushButton( qtawesome.icon('fa.question', color='gray'), "关于我们") self.left_button_9.setObjectName('left_button') self.left_xxx = QtWidgets.QPushButton(" ") self.left_layout.addWidget(self.icon_button, 0, 0.5, 1, 3) self.left_layout.addWidget(self.left_label_1, 1, 0, 1, 3) self.left_layout.addWidget(self.left_button_1, 2, 0, 1, 3) self.left_layout.addWidget(self.left_button_2, 3, 0, 1, 3) self.left_layout.addWidget(self.left_button_3, 4, 0, 1, 3) self.left_layout.addWidget(self.left_label_2, 5, 0, 1, 3) self.left_layout.addWidget(self.left_button_4, 6, 0, 1, 3) self.left_layout.addWidget(self.left_button_5, 7, 0, 1, 3) self.left_layout.addWidget(self.left_button_6, 8, 0, 1, 3) self.left_layout.addWidget(self.left_label_3, 9, 0, 1, 3) self.left_layout.addWidget(self.left_button_7, 10, 0, 1, 3) self.left_layout.addWidget(self.left_button_8, 11, 0, 1, 3) self.left_layout.addWidget(self.left_button_9, 12, 0, 1, 3) self.model_list_widget = QtWidgets.QWidget() self.model_list_widget.setObjectName('model_widget') self.model_list_layout = QtWidgets.QGridLayout() # 创建左侧部件的网格布局层 self.model_list_widget.setLayout(self.model_list_layout) # 设置左侧部件布局为网格 self.model_list_label = QtWidgets.QLabel("模型列表") self.model_list_label.setObjectName('my_lable') self.model_view_list = QListWidget() # 文件列表 self.model_view_list.setObjectName('my_list') # self.model_view_list.setFixedWidth(200) self.right_Splitter = QSplitter(Qt.Vertical) self.right_Splitter.setObjectName('right_Splitter') self.model_list_layout.addWidget(self.model_list_label, 0, 0, 1, 1) self.model_list_layout.addWidget(self.model_view_list, 1, 0, 9, 1) self.center_Splitter.addWidget(self.model_list_widget) self.center_Splitter.addWidget(self.right_Splitter) self.center_Splitter.setStretchFactor(0, 2) self.center_Splitter.setStretchFactor(1, 8) self.result_label = QtWidgets.QLabel("数据分析") self.result_label.setFixedHeight(80) self.result_label.setObjectName('my_lable') self.right_html_page_TabWidget = QtWidgets.QTabWidget() self.right_html_page_TabWidget.setObjectName( 'right_html_page_TabWidget') self.right_log_widget = QtWidgets.QWidget() # log 框 = button + log self.right_log_widget.setObjectName('right_log_widget') self.right_log_layout = QtWidgets.QGridLayout() self.right_log_widget.setLayout(self.right_log_layout) # 设置右侧部件布局为网格 self.right_Splitter.addWidget(self.result_label) self.right_Splitter.addWidget(self.right_html_page_TabWidget) self.right_Splitter.addWidget(self.right_log_widget) self.right_Splitter.setStretchFactor(0, 1) self.right_Splitter.setStretchFactor(1, 9) self.right_Splitter.setStretchFactor(2, 1) self.right_log_toolbar = QToolBar() self.right_log_toolbar.setObjectName('right_log_toolbar') self.right_log_toolbar.setOrientation(Qt.Vertical) # self.right_button_layout.addWidget(self.toolbarGmm) delete_action = QAction(QIcon('icon/delete-gray.png'), '清空日志', self) self.right_log_toolbar.addAction(delete_action) export_action = QAction(QIcon('icon/save_m.png'), '导出日志', self) self.right_log_toolbar.addAction(export_action) # self.right_log_layout.setSpacing(0) self.right_log_contend = QListWidget() # self.right_log_contend.setFixedHeight(100) self.right_log_contend.setObjectName('my_list') self.right_log_layout.addWidget(self.right_log_toolbar, 0, 0, 1, 3) self.right_log_layout.addWidget(self.right_log_contend, 0, 1, 1, 18) # 定义 css def UI_style(self): self.main_widget.setStyleSheet(''' QWidget#main_widget{ background:#EBEBEB; border-top:1px solid #EBEBEB; border-bottom:1px solid #EBEBEB; border-left:1px solid #EBEBEB; border-top-left-radius:10px; border-bottom-left-radius:10px; } ''') self.result_label.setStyleSheet(''' QLabel{ border:none; background:#EBEBEB; font-size:20px; font-weight:900; font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; } ''') self.model_list_label.setStyleSheet(''' QLabel{ border:none; background:#EBEBEB; font-size:20px; font-weight:900; font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; } ''') self.icon_button.setStyleSheet(''' QToolButton{ border:none; background:#EBEBEB; } ''') self.main_widget.setStyleSheet(''' QWidget#center_QWidget{ color:#232C51; background:#EBEBEB; border-top:1px solid #EBEBEB; border-bottom:1px solid #EBEBEB; border-right:1px solid #EBEBEB; border-top-right-radius:10px; border-bottom-right-radius:10px; } QWidget#left_widget{ background:#EBEBEB; border-top:1px solid #EBEBEB; border-bottom:1px solid #EBEBEB; border-left:1px solid #EBEBEB; border-top-left-radius:10px; border-bottom-left-radius:10px; } ''') self.model_list_widget.setStyleSheet(''' QListWidget#my_list{ background:light white; border:none; width:300px; border-radius:10px; padding:2px 4px; } ''') self.left_widget.setStyleSheet(''' QPushButton{border:none;color:gray;font-size:18px;font-weight:700;} QPushButton#left_label{ border:none; border-bottom:1px solid dark gray; font-size:20px; font-weight:900; font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; } QPushButton#left_button:hover{border-left:4px solid red;font-weight:700;} ''') self.center_Splitter.setStyleSheet(''' QSplitter#center_Splitter{ background:#EBEBEB; } QSplitter#right_Splitter{ background:#EBEBEB; } QTabWidget#right_html_page_TabWidget{ width:300px; border-radius:10px; padding:2px 4px; border:none; font-size:16px; font-weight:700; font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; } } QLabel#my_lable{ background-color:#EBEBEB; border:none; font-size:20px; font-weight:bold; font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; } QToolBar#right_log_toolbar{ border:none; background-color: #EBEBEB; } QListWidget#my_list{ background:light white; border:none; width:300px; border-radius:10px; padding:2px 4px; } ''') self.model_list_label.setAlignment(Qt.AlignCenter) self.result_label.setAlignment(Qt.AlignCenter) self.model_list_label.setStyleSheet(''' QLabel{ background-color:light gray; border:none; font-size:20px; font-weight:bold; font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; } ''') self.right_log_widget.setStyleSheet(''' QListWidget#right_log_widget{ width:300px; border-radius:10px; padding:2px 4px; } QToolBar#right_log_toolbar{ border:none; background-color: light gray; } QListWidget#right_log_contend{ background:#EBEBEB; border:none; border:1px solid gray; width:300px; border-radius:10px; padding:2px 4px; } ''') # self.setWindowOpacity(1) # 设置窗口透明度 # self.setAttribute(QtCore.Qt.WA_TranslucentBackground) # 设置窗口背景透明 # self.setWindowFlag(QtCore.Qt.FramelessWindowHint) # 隐藏边框 # self.main_layout.setSpacing(0) def generateData(self): for group in range(1, 100): self.model_view_list.addItem("model_{0}".format(group)) for group in range(1, 100): self.right_log_contend.addItem( (datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S') + " : operation_{0}").format(group)) for group in range(1, 4): self.tabItem = QTextBrowser() self.right_html_page_TabWidget.addTab(self.tabItem, "page_{0}".format(group)) self.tabItem.setHtml("""<table bgcolor=yellow> <tr><td>Groups:</td><td>comp.lang.python.announce</td></tr> <tr><td>From:</td><td>"Fuzzyman" <[email protected]></td></tr> <tr><td>Subject:</td><td><b>[ANN] Movable Python 2.0.0 Final Available</b></td></tr> </table> <h3>Movable Python 2.0.0 Final</h3> <p> <a href="http://www.voidspace.org.uk/python/movpy/"> http://www.voidspace.org.uk/python/movpy/</a> is now available. <p> The new binaries are available for download from the groups page : <p>Movable Python Groups Page <a href="http://voidspace.tradebit.com/groups.php"> http://voidspace.tradebit.com/groups.php</a> <p> Binaries are uploaded for Python 2.2.3, 2.3.5, 2.4.4, 2.5 and the MegaPack <a href="http://www.voidspace.org.uk/python/movpy/megapack.html"> http://www.voidspace.org.uk/python/movpy/megapack.html</a>. <p> There is also a fresh version of the free demo, based on Python 2.3.5: <p>Movable Python Trial Version <a href="http://voidspace.tradebit.com/files.php/7007"> http://voidspace.tradebit.com/files.php/7007</a> <h3>What is Movable Python</h3> <p> <b><i>Movable Python</i></b> is a distribution of Python, for Windows, that can run without being installed. It means you can carry a full development environment round on a USB stick. <p> It is also useful for testing programs with a 'clean Python install', and testing programs with multiple versions of Python. <p> The GUI program launcher makes it a useful programmers tool, including features like : <ul> <li>Log the output of all Python scripts run <li>Enable Psyco for all scripts <li>Quick Launch buttons for commonly used programs <li>Configure multiple interpreters for use from a single interface </ul> <p> It comes with the Pythonwin IDE and works fine with other IDEs like SPE <a href="http://developer.berlios.de/projects/python/"> http://developer.berlios.de/projects/python/</a>. <p> Plus many other features and bundled libraries.""")
class GUI(QMainWindow): def __init__(self, config, app, splash): super().__init__() self.config = config self.app = app self.splash = splash log.set_up(logger, verbose=config.VERBOSE, logfile=config.LOG_FILE) self.resize(1024, 680) self.setWindowTitle(tr("Zuul GUI")) icon = QtGui.QIcon('assets/zuul.icns') self.setWindowIcon(icon) self.app.setWindowIcon(icon) def openPreference(): if self.config.initialize(openDialog=True): self.loadPlugins() # Add Preferences menu mainMenuBar = QMenuBar() newAct = QAction(tr("Preferences..."), self) newAct.triggered.connect(openPreference) fileMenu = mainMenuBar.addMenu(tr("Zuul GUI")) fileMenu.addAction(newAct) self.setMenuBar(mainMenuBar) self.currentBlock = None if self.refreshStatus(): self.loadPlugins() timer = QtCore.QTimer(self) timer.timeout.connect(self.refreshStatus) timer.start(self.config.POLL_INTERVAL) self.show() # init clientapi def initXcpApi(self): if hasattr(self, 'zulApi') and isinstance(self.zulApi, ZuuldAPI): return True else: try: self.zulApi = ZuuldAPI(self.config) return True except ConfigurationError as e: self.show() msgBox = QMessageBox(self) msgBox.setText(str(e)) msgBox.setModal(True) msgBox.show() return False def refreshStatus(self): if not self.initXcpApi(): return False try: serverInfo = self.zulApi.call( { 'method': 'get_running_info', 'params': [] }, return_dict=True) zuulLastBlock = serverInfo['last_block']['block_index'] walletLastBlock = self.zulApi.call( { 'method': 'wallet_last_block', 'params': {} }, return_dict=True) message = 'Server Last Block: {} | Wallet Last Block: {}' self.statusBar().showMessage( message.format(zuulLastBlock, walletLastBlock)) if self.currentBlock is not None and self.currentBlock != zuulLastBlock: self.notifyPlugins('new_block', {'block_index': zuulLastBlock}) self.currentBlock = zuulLastBlock return True # TODO except Exception as e: # if application startup then open preference dialog and exit if not hasattr(self, 'plugins'): if self.splash: self.splash.hide() self.config.initialize(openDialog=True) exit() # else fails silently, error are already shown by `api.ZuuldRPCError` # and refreshStatus is executed each self.config.POLL_INTERVAL second return False def notifyPlugins(self, messageName, messageData): logger.debug('Notify plugins `{}`: {}'.format(messageName, messageData)) if hasattr(self, 'plugins'): for plugin in self.plugins: if hasattr(plugin, 'onMessage'): plugin.onMessage(messageName, messageData) self.refreshToolbar() def refreshToolbar(self): pluginIndex = self.currentMenuItem.property('pluginIndex') actionValue = self.currentMenuItem.property('actionValue') self.initToolbar(selectedPluginIndex=pluginIndex, selectedActionValue=actionValue) self.currentMenuItem.setProperty('active', 'true') self.refreshStyleSheet() def initPlugins(self): # init QML plugin container if hasattr(self, 'stackedWidget'): del (self.stackedWidget) self.stackedWidget = QStackedWidget(self) self.plugins = [] for pluginName in self.config.PLUGINS: view = QQuickView() view.setFlags(Qt.SubWindow) # add clientapi into the plugin context context = view.rootContext() context.setContextProperty('zulApi', self.zulApi) context.setContextProperty('GUI', self) # load plugin translations if i18n subfolder exists i18nDir = 'plugins/{}/i18n'.format(pluginName) if os.path.exists(i18nDir): translator = QtCore.QTranslator() fileName = 'send_'.format(QtCore.QLocale.system().name()) #fileName = 'send_fr' translator.load(fileName, i18nDir) self.app.installTranslator(translator) # load QML file plugin_index_path = 'plugins/{}/index.qml'.format(pluginName) view.setSource(QUrl(plugin_index_path)) plugin = view.rootObject() self.plugins.append(plugin) # call plugin init callback plugin.init() # add the plugin in the container container = QWidget.createWindowContainer(view, self) self.stackedWidget.addWidget(container) def initToolbar(self, selectedPluginIndex=None, selectedActionValue=None): # init toolbar if hasattr(self, 'toolbar'): self.removeToolBar(self.toolbar) del (self.toolbar) self.toolbar = QToolBar() self.toolbar.setAutoFillBackground(True) self.toolbar.setObjectName('menu') self.toolbar.setMovable(False) self.toolbar.setFloatable(False) self.toolbar.setToolButtonStyle(Qt.ToolButtonTextBesideIcon | Qt.AlignLeft) self.addToolBar(Qt.LeftToolBarArea, self.toolbar) self.currentMenuItem = None pluginIndex = 0 for plugin in self.plugins: # generate the left menu menu = plugin.property('menu') if isinstance(menu, QJSValue): menu = menu.toVariant() if menu and isinstance(menu, dict) and 'items' in menu and isinstance( menu['items'], list): # menu title if 'groupLabel' in menu: menuGroupLabel = QLabel(menu['groupLabel']) menuGroupLabel.setProperty('isGroupLabel', 'true') self.toolbar.addWidget(menuGroupLabel) # menu item items = [] for menuItem in menu['items']: if isinstance( menuItem, dict ) and 'label' in menuItem and 'value' in menuItem: items.append(MenuItem(menuItem['label'], self)) items[-1].setProperty('pluginIndex', pluginIndex) items[-1].setProperty('actionValue', menuItem['value']) items[-1].setProperty('isAction', 'true') self.toolbar.addWidget(items[-1]) if self.currentMenuItem is None or ( selectedPluginIndex == pluginIndex and selectedActionValue == menuItem['value']): self.currentMenuItem = items[-1] pluginIndex += 1 self.currentMenuItem.activate() def loadPlugins(self): if not self.initXcpApi(): return self.initPlugins() self.initToolbar() # display the plugin container self.refreshStyleSheet() self.setCentralWidget(self.stackedWidget) def refreshStyleSheet(self): self.setStyleSheet(''' QWidget, QQuickView, QToolBar, QMainWindow { font-size:14pt } QToolBar#menu { background-color: #ececec; border: 1px solid #ececec; border-right-color: #000; } QToolBar#menu QLabel { width:100%; text-align:left; padding:3px; margin:0; } QToolBar#menu QLabel[isAction="true"]:hover { background-color:#CCC; } QToolBar#menu QLabel[active="true"] { background-color:#CCC; } QToolBar#menu QLabel[isAction="true"] { padding-left: 15px; } QToolBar#menu QLabel[isGroupLabel="true"] { color:#888888; text-transform:uppercase; } ''') # used in QML to display a confirm dialog @pyqtSlot(QVariant, QVariant, result=QVariant) def confirm(self, title, text): result = QMessageBox.question(self, title, text) if result == QMessageBox.Yes: return True else: return False # used in QML to display a message dialog @pyqtSlot(QVariant, QVariant) def alert(self, title, text): QMessageBox.information(self, title, text) @pyqtSlot(QVariant) def copyToClipboard(self, text): clipboard = QApplication.clipboard() clipboard.setText(text)
class MainWindow(QMainWindow): """ Main UI window Class creates window elements, fills main menu with items. If you need to access to some existing menu items - check action path in the class constructor, than use next code: :: core.actionManager().action("mFile/aOpen").setEnabled(True) core.actionManager().action("mFile/aOpen").triggered.connect(self.myCoolMethod) MainWindow instance is accessible as: :: from enki.core.core import core core.mainwindow() Created by the core """ hideAllWindows = pyqtSignal() """ hideAllWindows() **Signal** emitted, when user toggled "Hide all" . Dock widgets are closed automatically, but other widgets, i.e. search widget, must catch this signal and close themselves. """ # pylint: disable=W0105 directoryDropt = pyqtSignal(str) """ directoryDropt() **Signal** emitted, when user drag-n-dropt directory to main windowd. FileBrowser shows directory """ # pylint: disable=W0105 _STATE_FILE = os.path.join(enki.core.defines.CONFIG_DIR, "main_window_state.bin") _GEOMETRY_FILE = os.path.join(enki.core.defines.CONFIG_DIR, "main_window_geometry.bin") def __init__(self): QMainWindow.__init__(self) self._queuedMessageToolBar = None self._createdMenuPathes = [] self._createdActions = [] self._addedDockWidgets = [] if hasattr(self, 'setUnifiedTitleAndToolBarOnMac' ): # missing on some PyQt5 versions self.setUnifiedTitleAndToolBarOnMac(True) self.setIconSize(QSize(16, 16)) self.setAcceptDrops(True) # Set corner settings for dock widgets self.setCorner(Qt.TopLeftCorner, Qt.LeftDockWidgetArea) self.setCorner(Qt.TopRightCorner, Qt.RightDockWidgetArea) self.setCorner(Qt.BottomLeftCorner, Qt.LeftDockWidgetArea) self.setCorner(Qt.BottomRightCorner, Qt.RightDockWidgetArea) self.setWindowTitle(self.defaultTitle( )) # overwriten by workspace when file or it's modified state changes self.setWindowIcon(QIcon(':/enkiicons/logo/enki.svg')) # Create top tool bar self._topToolBar = QToolBar("topToolBar") self._topToolBar.setObjectName("topToolBar") self._topToolBar.setMovable(False) self._topToolBar.setIconSize(QSize(16, 16)) self._topToolBar.setContextMenuPolicy( Qt.PreventContextMenu) # to avoid possibility to hide the toolbar # Create menu bar self._menuBar = ActionMenuBar(self, core.actionManager()) self._initMenubarAndStatusBarLayout() # create central layout widget = QWidget(self) self._centralLayout = QVBoxLayout(widget) self._centralLayout.setContentsMargins(0, 0, 0, 0) self.setCentralWidget(widget) self.setStyleSheet('QMainWindow::separator{width: 4px}') def _initActions(self): """ Public method for actionManager. """ self._createMenuStructure() core.actionManager().action('mView/aOpenMainMenu').triggered.connect( self._openMainMenu) core.actionManager().action('mFile/aQuit').triggered.connect( self.onQuit) def terminate(self): """Explicitly called destructor """ if self._queuedMessageToolBar: self.removeToolBar(self._queuedMessageToolBar) del self._queuedMessageToolBar for act in self._createdActions: core.actionManager().removeAction(act) for menuPath in self._createdMenuPathes[::-1]: core.actionManager().removeMenu(menuPath) @staticmethod def _isMenuEmbeddedToTaskBar(): """On Unity (Ubuntu) and MacOS menu bar is embedded to task bar """ return 'UBUNTU_MENUPROXY' in os.environ or \ os.environ.get('XDG_CURRENT_DESKTOP') == 'Unity' or \ 'darwin' == sys.platform def _initMenubarAndStatusBarLayout(self): """Create top widget and put it on its place """ if not 'darwin' == sys.platform: # on Ubuntu toolbar, docs and editor area look as one widget. Ugly # Therefore it is separated with line. On Mac seems OK # I can't predict, how it will look on other platforms, therefore line is used for all, except Mac toolBarStyleSheet = "QToolBar {border: 0; border-bottom-width: 1; border-bottom-style: solid}" "" self._topToolBar.setStyleSheet(toolBarStyleSheet) area = Qt.BottomToolBarArea if self._isMenuEmbeddedToTaskBar( ) else Qt.TopToolBarArea self.addToolBar(area, self._topToolBar) if self._isMenuEmbeddedToTaskBar(): # separate menu bar self.setMenuBar(self._menuBar) else: # menubar, statusbar and editor tool bar on one line self._menuBar.setAutoFillBackground(False) menuBarStyleSheet = """ QMenuBar {background-color: transparent; color: %s} QMenuBar::item:!selected {background: transparent;} """ % self.palette().color(QPalette.WindowText).name() self._menuBar.setStyleSheet(menuBarStyleSheet) self._menuBar.setSizePolicy(QSizePolicy.MinimumExpanding, QSizePolicy.Minimum) self._topToolBar.addWidget(self._menuBar) # Create status bar self._statusBar = _StatusBar(self) self._topToolBar.addWidget(self._statusBar) def _initQueuedMessageToolBar(self): from enki.core.queued_msg_tool_bar import QueuedMessageToolBar self._queuedMessageToolBar = QueuedMessageToolBar(self) area = Qt.TopToolBarArea if self._isMenuEmbeddedToTaskBar( ) else Qt.BottomToolBarArea self.addToolBar(area, self._queuedMessageToolBar) self._queuedMessageToolBar.setVisible(False) def _createMenuStructure(self): """Fill menu bar with items. The majority of items are not connected to the slots, Connections made by module, which implements menu item functionality, but, all items are in one place, because it's easier to create clear menu layout """ # create menubar menus and actions def menu(path, name, icon, visible=True): """Subfunction for create a menu in the main menu""" menuObject = core.actionManager().addMenu(path, name) if icon: menuObject.setIcon(QIcon(':/enkiicons/' + icon)) self._createdMenuPathes.append(path) if not visible: menuObject.setVisible(False) def action(path, name, icon, shortcut, tooltip, enabled, checkable=False): # pylint: disable=R0913 """Subfunction for create an action in the main menu""" if icon: # has icon actObject = core.actionManager().addAction( path, name, QIcon(':/enkiicons/' + icon), shortcut) else: actObject = core.actionManager().addAction(path, name, shortcut=shortcut) if tooltip: actObject.setStatusTip(tooltip) actObject.setEnabled(enabled) actObject.setCheckable(checkable) self._createdActions.append(actObject) def separator(menu): """Subfunction for insert separator to the menu""" core.actionManager().action(menu).menu().addSeparator() # pylint: disable=C0301 # enable long lines for menu items # Menu or action path Name Icon Shortcut Hint enabled checkable menu("mFile", "File", "") action("mFile/aOpenProject", "Open Pro&ject...", "open.png", "Shift+Ctrl+O", "Open a project", True) separator("mFile") menu("mFile/mUndoClose", "Undo Close", "recents.png") separator("mFile") action("mFile/aNew", "&New file...", "new.png", 'Ctrl+N', "New file", True) action("mFile/aOpen", "&Open...", "open.png", "Ctrl+O", "Open a file", True) menu("mFile/mSave", "&Save", "save.png") action("mFile/mSave/aCurrent", "&Save", "save.png", "Ctrl+S", "Save the current file", False) action("mFile/mSave/aSaveAs", "Save As...", "save.png", "Ctrl+Alt+S", "", False) action("mFile/mSave/aAll", "Save &All", "saveall.png", 'Shift+Ctrl+S', "Save all files", False) menu("mFile/mReload", "&Reload", "reload.png") action("mFile/mReload/aCurrent", "Reload", "reload.png", 'F5', "Reload the current file", False) action("mFile/mReload/aAll", "Reload All", "reload.png", 'Shift+F5', "Reload all files", True) menu("mFile/mClose", "&Close", "close.png") action("mFile/mClose/aCurrent", "&Close", "close.png", "Ctrl+W", "Close the current file", False) action("mFile/mClose/aAll", "Close &All", "closeall.png", 'Shift+Ctrl+W', "Close all files", False) menu("mFile/mFileSystem", "File System", "filesystem.png") action("mFile/mFileSystem/aRename", "Rename", "edit.png", '', "Rename current file", False) if platform.system() != 'Windows': action("mFile/mFileSystem/aToggleExecutable", "Make executable", "", '', "Toggle executable mode", False) separator("mFile") action("mFile/aQuit", "Quit", "quit.png", 'Ctrl+Q', "Quit", True) separator("mFile") menu("mView", "View", "") action("mView/aShowIncorrectIndentation", "Show incorrect indentation", "", "", "", False, True) action("mView/aShowAnyWhitespaces", "Show any whitespace", "", "", "", False, True) separator("mView") action("mView/aHideAll", "Hide all / Restore", "", "Shift+Esc", "Hide all widgets", True) action("mView/aOpenMainMenu", "Open main menu", "", "F10", "", True) separator("mView") menu("mEdit", "Edit", "") action("mEdit/aStripTrailingWhitespace", "Strip trailing whitespace when saving", "", "", "", True, True) separator("mEdit") menu("mEdit/mCopyPasteLines", "Copy-paste lines", "") menu("mEdit/mIndentation", "Indentation", "") separator("mEdit") action("mEdit/aEnableVimMode", "Enable Vim mode", "", "", "", False, True) menu("mNavigation", "Navigation", "") action("mNavigation/aFocusCurrentDocument", "Focus to editor", "text.png", "Ctrl+Return", "Focus current document", False) menu("mNavigation/mSearchReplace", "&Search && Replace", "search-replace-directory.png") menu("mNavigation/mBookmarks", "&Bookmarks", "bookmark.png") separator("mNavigation"), action("mNavigation/aNext", "&Next file", "next.png", "Ctrl+PgDown", "Next file", False) action("mNavigation/aPrevious", "&Previous file", "previous.png", "Ctrl+PgUp", "Previous file", False) separator("mNavigation") action("mNavigation/aGoto", "Go go line...", "goto.png", "Ctrl+G", "Go to line...", False) menu("mNavigation/mFileBrowser", "File browser", ':/enkiicons/open.png', visible=False) menu("mNavigation/mScroll", "Scroll file", '') menu("mSettings", "Settings", "") menu("mTools", "Tools", "") menu("mHelp", "Help", "") @pyqtSlot() def _openMainMenu(self): fileMenu = core.actionManager().menu('mFile') self._menuBar.setActiveAction(fileMenu.menuAction()) def menuBar(self): """Reference to menuBar """ return self._menuBar def topToolBar(self): """Top tool bar. Contains main menu, position indicator, etc """ return self._topToolBar def statusBar(self): """Return main window status bar. It is located on the top tool bar """ return self._statusBar def setWorkspace(self, workspace): """Set central widget of the main window. Normally called only by core when initializing system """ self._centralLayout.addWidget(workspace) self.setFocusProxy(workspace) def defaultTitle(self): """Default title. Contains name and version """ return "%s v.%s" % (enki.core.defines.PACKAGE_NAME, enki.core.defines.PACKAGE_VERSION) def centralLayout(self): """Layout of the central widget. Contains Workspace and search widget """ return self._centralLayout def appendMessage(self, text, timeoutMs=10000): """Append message to the queue. It will be shown as non-modal at the bottom of the window. Use such notifications, which are too long or too important for status bar but, not so important, to interrupt an user with QMessageBox """ if self._queuedMessageToolBar is None: self._initQueuedMessageToolBar() self._queuedMessageToolBar.appendMessage(text, timeoutMs) def closeEvent(self, event): """NOT A PUBLIC API Close event handler. Shows save files dialog. Cancels close, if dialog was rejected """ # saving geometry BEFORE closing widgets, because state might be changed, when docks are closed self._saveState() self._saveGeometry() # request close all documents if not core.workspace().askToCloseAll(): event.ignore() return core.aboutToTerminate.emit() self.hide() core.workspace().forceCloseAllDocuments() return QMainWindow.closeEvent(self, event) def onQuit(self): # saving geometry BEFORE closing widgets, because state might be changed, when docks are closed self._saveState() self._saveGeometry() # request close all documents if not core.workspace().askToCloseAll(): return core.aboutToTerminate.emit() self.hide() core.workspace().forceCloseAllDocuments() return QApplication.quit() def _saveByteArray(self, path, title, data): """Load data, show error and return None if failed""" try: with open(path, 'wb') as f: f.write(data) except (OSError, IOError) as ex: error = str(ex) QMessageBox.critical( None, self.tr("Cannot save {}".format(title)), self.tr("Cannot create file '%s'\nError: %s" % (path, error))) return def _loadByteArray(self, path, title): """Load data, show error and return None if failed""" if os.path.exists(path): try: with open(path, 'rb') as f: return f.read() except (OSError, IOError) as ex: error = str(ex) QMessageBox.critical( None, self.tr("Cannot restore {}".format(title)), self.tr("Cannot read file '%s'\nError: %s" % (path, error))) return None def _saveState(self): """Save window state to main_window_state.bin file in the config directory """ self._saveByteArray(self._STATE_FILE, "main window state", self.saveState()) def loadState(self): """Restore window state from main_window_state.bin and config. Called by the core after all plugins had been initialized """ self._restoreGeometry() state = self._loadByteArray(self._STATE_FILE, "main window state") if state is not None: self.restoreState(state) else: # no state, first start self.showMaximized() for dock in self.findChildren(DockWidget): dock.show() def _saveGeometry(self): """Save window geometry to the config file """ self._saveByteArray(self._GEOMETRY_FILE, "main window geometry", self.saveGeometry()) def _restoreGeometry(self): """Restore window geometry to the config file """ geometry = self._loadByteArray(self._GEOMETRY_FILE, "main window geometry") if geometry is not None: self.restoreGeometry(geometry) def sizeHint(self): return QSize(900, 560) def dragEnterEvent(self, event): """QMainWindow method reimplementation. Say, that we are ready to accept dragged urls """ if event.mimeData().hasUrls(): # accept drag event.acceptProposedAction() # default handler QMainWindow.dragEnterEvent(self, event) def dropEvent(self, event): """QMainWindow method reimplementation. Open dropt files """ if event.mimeData().hasUrls(): for url in event.mimeData().urls(): localFile = url.toLocalFile() if os.path.isfile(localFile): core.workspace().openFile(localFile) elif os.path.isdir(localFile): self.directoryDropt.emit(localFile) # default handler QMainWindow.dropEvent(self, event) def addDockWidget(self, area, dock): pass # not a plugin API method """Add dock widget to previous position, if known. Otherwise add to specified area """ assert not dock in self._addedDockWidgets self._addedDockWidgets.append(dock) if not self.restoreDockWidget(dock): QMainWindow.addDockWidget(self, area, dock) """ Scroll view to make the cursor visible. Otherwise cursor can disappear from the viewport. QTimer is used because ensureCursorVisible works only after the dock has been drawn. A bad fix for #319 """ QTimer.singleShot(0, self._ensureCursorVisible) def _ensureCursorVisible(self): # When the timer fires, first check that there's still a workspace/document. if core.workspace() is not None: document = core.workspace().currentDocument() if document is not None: document.qutepart.ensureCursorVisible def removeDockWidget(self, dock): pass # not a plugin API method """Remove dock widget""" assert dock in self._addedDockWidgets self._addedDockWidgets.remove(dock) QMainWindow.removeDockWidget(self, dock) def restoreState(self, state): pass # not a plugin API method """Restore state shows widgets, which exist but shall not be installed on main window """ QMainWindow.restoreState(self, state) for dock in self.findChildren(DockWidget): if not dock in self._addedDockWidgets: dock.hide()
class UIController(object): documentModifiedText = "" documentStatusBarText = "untitled" def __init__(self): self.mainWidget = scripterdialog.ScripterDialog(self) self.actionToolbar = QToolBar('toolBar', self.mainWidget) self.menu_bar = QMenuBar(self.mainWidget) self.actionToolbar.setObjectName('toolBar') self.menu_bar.setObjectName('menuBar') self.actions = [] self.mainWidget.setWindowModality(Qt.NonModal) def initialize(self, scripter): self.editor = pythoneditor.CodeEditor(scripter) self.tabWidget = QTabWidget() self.statusBar = Elided_Text_Label() self.statusBar.setMainText('untitled') self.splitter = QSplitter() self.splitter.setOrientation(Qt.Vertical) self.highlight = syntax.PythonHighlighter( self.editor.document(), syntaxstyles.DefaultSyntaxStyle()) p = self.editor.palette() p.setColor( QPalette.Base, syntaxstyles.DefaultSyntaxStyle() ['background'].foreground().color()) p.setColor( QPalette.Text, syntaxstyles.DefaultSyntaxStyle() ['foreground'].foreground().color()) self.editor.setPalette(p) self.scripter = scripter self.loadMenus() self.loadWidgets() self.loadActions() self._readSettings() # sets window size vbox = QVBoxLayout(self.mainWidget) vbox.addWidget(self.menu_bar) vbox.addWidget(self.actionToolbar) self.splitter.addWidget(self.editor) self.splitter.addWidget(self.tabWidget) vbox.addWidget(self.splitter) vbox.addWidget(self.statusBar) self.mainWidget.setWindowTitle(i18n("Scripter")) self.mainWidget.setSizeGripEnabled(True) self.mainWidget.show() self.mainWidget.activateWindow() self.editor.undoAvailable.connect(self.setStatusModified) def loadMenus(self): self.addMenu(i18n('File'), i18n('File')) def addMenu(self, menuName, parentName): parent = self.menu_bar.findChild(QObject, parentName) self.newMenu = None if parent: self.newMenu = parent.addMenu(menuName) else: self.newMenu = self.menu_bar.addMenu(menuName) self.newMenu.setObjectName(menuName) return self.newMenu def loadActions(self): module_path = 'scripter.ui_scripter.actions' actions_module = importlib.import_module(module_path) modules = [] for class_path in actions_module.action_classes: _module = class_path[:class_path.rfind(".")] _klass = class_path[class_path.rfind(".") + 1:] modules.append( dict(module='{0}.{1}'.format(module_path, _module), klass=_klass)) for module in modules: m = importlib.import_module(module['module']) action_class = getattr(m, module['klass']) obj = action_class(self.scripter) obj_parent = obj.parent for name in obj_parent: parent = self.mainWidget.findChild(QObject, i18n(name)) self.actions.append(dict(action=obj, parent=parent)) for action in self.actions: action['parent'].addAction(action['action']) def loadWidgets(self): modulePath = 'scripter.ui_scripter.tabwidgets' widgetsModule = importlib.import_module(modulePath) modules = [] for class_path in widgetsModule.widgetClasses: _module = class_path[:class_path.rfind(".")] _klass = class_path[class_path.rfind(".") + 1:] modules.append( dict(module='{0}.{1}'.format(modulePath, _module), klass=_klass)) for module in modules: m = importlib.import_module(module['module']) widgetClass = getattr(m, module['klass']) obj = widgetClass(self.scripter) self.tabWidget.addTab(obj, obj.objectName()) def invokeAction(self, actionName): for action in self.actions: if action['action'].objectName() == actionName: method = getattr(action['action'], actionName) if method: return method() def findTabWidget(self, widgetName, childName=''): for index in range(self.tabWidget.count()): widget = self.tabWidget.widget(index) if widget.objectName() == widgetName: if childName: widget = widget.findChild(QObject, childName) return widget def showException(self, exception): QMessageBox.critical(self.editor, i18n("Error Running Script"), str(exception)) def setDocumentEditor(self, document): self.editor.clear() self.editor.moveCursor(QTextCursor.Start) self.editor._documentModified = False self.editor.setPlainText(document.data) self.editor.moveCursor(QTextCursor.End) def setStatusBar(self, value='untitled'): self.documentStatusBarText = value self.statusBar.setMainText(self.documentStatusBarText + self.documentModifiedText) def setStatusModified(self): self.documentModifiedText = "" if (self.editor._documentModified is True): self.documentModifiedText = " [Modified]" self.statusBar.setMainText(self.documentStatusBarText + self.documentModifiedText) def setActiveWidget(self, widgetName): widget = self.findTabWidget(widgetName) if widget: self.tabWidget.setCurrentWidget(widget) def setStepped(self, status): self.editor.setStepped(status) def clearEditor(self): self.editor.clear() def repaintDebugArea(self): self.editor.repaintDebugArea() def closeScripter(self): self.mainWidget.close() def _writeSettings(self): """ _writeSettings is a method invoked when the scripter starts, making control inversion. Actions can implement a writeSettings method to save your own settings without this method to know about it. """ self.scripter.settings.beginGroup('scripter') document = self.scripter.documentcontroller.activeDocument if document: self.scripter.settings.setValue('activeDocumentPath', document.filePath) else: self.scripter.settings.setValue('activeDocumentPath', '') self.scripter.settings.setValue('editorFontSize', self.editor.fontInfo().pointSize()) for action in self.actions: writeSettings = getattr(action['action'], "writeSettings", None) if callable(writeSettings): writeSettings() # Window Geometry rect = self.mainWidget.geometry() self.scripter.settings.setValue(KEY_GEOMETRY, rect) self.scripter.settings.endGroup() def _readSettings(self): """ It's similar to _writeSettings, but reading the settings when the ScripterDialog is closed. """ self.scripter.settings.beginGroup('scripter') activeDocumentPath = self.scripter.settings.value( 'activeDocumentPath', '') if activeDocumentPath: if QFileInfo(activeDocumentPath).exists(): document = self.scripter.documentcontroller.openDocument( activeDocumentPath) self.setStatusBar(document.filePath) self.setDocumentEditor(document) for action in self.actions: readSettings = getattr(action['action'], "readSettings", None) if callable(readSettings): readSettings() pointSize = self.scripter.settings.value( 'editorFontSize', str(self.editor.fontInfo().pointSize())) self.editor.setFontSize(int(pointSize)) # Window Geometry rect = self.scripter.settings.value(KEY_GEOMETRY, DEFAULT_GEOMETRY) self.mainWidget.setGeometry(rect) self.scripter.settings.endGroup() def _saveSettings(self): self.scripter.settings.sync()
class MainWindow(QMainWindow): """ Main UI window Class creates window elements, fills main menu with items. If you need to access to some existing menu items - check action path in the class constructor, than use next code: :: core.actionManager().action("mFile/aOpen").setEnabled(True) core.actionManager().action("mFile/aOpen").triggered.connect(self.myCoolMethod) MainWindow instance is accessible as: :: from enki.core.core import core core.mainwindow() Created by the core """ hideAllWindows = pyqtSignal() """ hideAllWindows() **Signal** emitted, when user toggled "Hide all" . Dock widgets are closed automatically, but other widgets, i.e. search widget, must catch this signal and close themselves. """ # pylint: disable=W0105 directoryDropt = pyqtSignal(str) """ directoryDropt() **Signal** emitted, when user drag-n-dropt directory to main windowd. FileBrowser shows directory """ # pylint: disable=W0105 _STATE_FILE = os.path.join(enki.core.defines.CONFIG_DIR, "main_window_state.bin") _GEOMETRY_FILE = os.path.join(enki.core.defines.CONFIG_DIR, "main_window_geometry.bin") def __init__(self): QMainWindow.__init__(self) self._queuedMessageToolBar = None self._createdMenuPathes = [] self._createdActions = [] self._addedDockWidgets = [] if hasattr(self, 'setUnifiedTitleAndToolBarOnMac'): # missing on some PyQt5 versions self.setUnifiedTitleAndToolBarOnMac(True) self.setIconSize(QSize(16, 16)) self.setAcceptDrops(True) # Set corner settings for dock widgets self.setCorner(Qt.TopLeftCorner, Qt.LeftDockWidgetArea) self.setCorner(Qt.TopRightCorner, Qt.RightDockWidgetArea) self.setCorner(Qt.BottomLeftCorner, Qt.LeftDockWidgetArea) self.setCorner(Qt.BottomRightCorner, Qt.RightDockWidgetArea) self.setWindowTitle(self.defaultTitle()) # overwriten by workspace when file or it's modified state changes self.setWindowIcon(QIcon(':/enkiicons/logo/enki.svg')) # Create top tool bar self._topToolBar = QToolBar("topToolBar") self._topToolBar.setObjectName("topToolBar") self._topToolBar.setMovable(False) self._topToolBar.setIconSize(QSize(16, 16)) self._topToolBar.setContextMenuPolicy(Qt.PreventContextMenu) # to avoid possibility to hide the toolbar # Create menu bar self._menuBar = ActionMenuBar(self, core.actionManager()) self._initMenubarAndStatusBarLayout() # create central layout widget = QWidget(self) self._centralLayout = QVBoxLayout(widget) self._centralLayout.setContentsMargins(0, 0, 0, 0) self.setCentralWidget(widget) self.setStyleSheet('QMainWindow::separator{width: 4px}') def _initActions(self): """ Public method for actionManager. """ self._createMenuStructure() core.actionManager().action('mView/aOpenMainMenu').triggered.connect(self._openMainMenu) core.actionManager().action('mFile/aQuit').triggered.connect(self.onQuit) def terminate(self): """Explicitly called destructor """ if self._queuedMessageToolBar: self.removeToolBar(self._queuedMessageToolBar) del self._queuedMessageToolBar for act in self._createdActions: core.actionManager().removeAction(act) for menuPath in self._createdMenuPathes[::-1]: core.actionManager().removeMenu(menuPath) @staticmethod def _isMenuEmbeddedToTaskBar(): """On Unity (Ubuntu) and MacOS menu bar is embedded to task bar """ return 'UBUNTU_MENUPROXY' in os.environ or \ os.environ.get('XDG_CURRENT_DESKTOP') == 'Unity' or \ 'darwin' == sys.platform def _initMenubarAndStatusBarLayout(self): """Create top widget and put it on its place """ if not 'darwin' == sys.platform: # on Ubuntu toolbar, docs and editor area look as one widget. Ugly # Therefore it is separated with line. On Mac seems OK # I can't predict, how it will look on other platforms, therefore line is used for all, except Mac toolBarStyleSheet = "QToolBar {border: 0; border-bottom-width: 1; border-bottom-style: solid}""" self._topToolBar.setStyleSheet(toolBarStyleSheet) area = Qt.BottomToolBarArea if self._isMenuEmbeddedToTaskBar() else Qt.TopToolBarArea self.addToolBar(area, self._topToolBar) if self._isMenuEmbeddedToTaskBar(): # separate menu bar self.setMenuBar(self._menuBar) else: # menubar, statusbar and editor tool bar on one line self._menuBar.setAutoFillBackground(False) menuBarStyleSheet = """ QMenuBar {background-color: transparent; color: %s} QMenuBar::item:!selected {background: transparent;} """ % self.palette().color(QPalette.WindowText).name() self._menuBar.setStyleSheet(menuBarStyleSheet) self._menuBar.setSizePolicy(QSizePolicy.MinimumExpanding, QSizePolicy.Minimum) self._topToolBar.addWidget(self._menuBar) # Create status bar self._statusBar = _StatusBar(self) self._topToolBar.addWidget(self._statusBar) def _initQueuedMessageToolBar(self): from enki.core.queued_msg_tool_bar import QueuedMessageToolBar self._queuedMessageToolBar = QueuedMessageToolBar(self) area = Qt.TopToolBarArea if self._isMenuEmbeddedToTaskBar() else Qt.BottomToolBarArea self.addToolBar(area, self._queuedMessageToolBar) self._queuedMessageToolBar.setVisible(False) def _createMenuStructure(self): """Fill menu bar with items. The majority of items are not connected to the slots, Connections made by module, which implements menu item functionality, but, all items are in one place, because it's easier to create clear menu layout """ # create menubar menus and actions def menu(path, name, icon, visible=True): """Subfunction for create a menu in the main menu""" menuObject = core.actionManager().addMenu(path, name) if icon: menuObject.setIcon(QIcon(':/enkiicons/' + icon)) self._createdMenuPathes.append(path) if not visible: menuObject.setVisible(False) def action(path, name, icon, shortcut, tooltip, enabled, checkable=False): # pylint: disable=R0913 """Subfunction for create an action in the main menu""" if icon: # has icon actObject = core.actionManager().addAction(path, name, QIcon(':/enkiicons/' + icon), shortcut) else: actObject = core.actionManager().addAction(path, name, shortcut=shortcut) if tooltip: actObject.setStatusTip(tooltip) actObject.setEnabled(enabled) actObject.setCheckable(checkable) self._createdActions.append(actObject) def separator(menu): """Subfunction for insert separator to the menu""" core.actionManager().action(menu).menu().addSeparator() # pylint: disable=C0301 # enable long lines for menu items # Menu or action path Name Icon Shortcut Hint enabled checkable menu ("mFile", "File" , "" ) action("mFile/aOpenProject", "Open Pro&ject..." , "open.png", "Shift+Ctrl+O" ,"Open a project" , True) separator("mFile") menu ("mFile/mUndoClose", "Undo Close" , "recents.png") separator("mFile") action("mFile/aNew", "&New file..." , "new.png", 'Ctrl+N', "New file" , True) action("mFile/aOpen", "&Open..." , "open.png", "Ctrl+O" , "Open a file" , True) menu ("mFile/mSave", "&Save" , "save.png" ) action("mFile/mSave/aCurrent", "&Save" , "save.png" , "Ctrl+S" , "Save the current file" , False) action("mFile/mSave/aSaveAs", "Save As..." , "save.png" , "Ctrl+Alt+S" , "" , False) action("mFile/mSave/aAll", "Save &All" , "saveall.png", 'Shift+Ctrl+S', "Save all files" , False) menu ("mFile/mReload", "&Reload" , "reload.png" ) action("mFile/mReload/aCurrent", "Reload" , "reload.png" , 'F5', "Reload the current file", False) action("mFile/mReload/aAll", "Reload All" , "reload.png" , 'Shift+F5', "Reload all files" , True) menu ("mFile/mClose", "&Close" , "close.png" ) action("mFile/mClose/aCurrent", "&Close" , "close.png", "Ctrl+W", "Close the current file" , False) action("mFile/mClose/aAll", "Close &All" , "closeall.png", 'Shift+Ctrl+W', "Close all files" , False) menu ("mFile/mFileSystem", "File System" , "filesystem.png") action("mFile/mFileSystem/aRename", "Rename" , "edit.png", '', "Rename current file" , False) if platform.system() != 'Windows': action("mFile/mFileSystem/aToggleExecutable", "Make executable" , "", '', "Toggle executable mode" , False) separator("mFile") action("mFile/aQuit", "Quit" , "quit.png", 'Ctrl+Q', "Quit" , True) separator("mFile") menu ("mView", "View" , "" ) action("mView/aShowIncorrectIndentation", "Show incorrect indentation", "", "", "" , False, True) action("mView/aShowAnyWhitespaces", "Show any whitespace", "", "", "" , False, True) separator("mView") action("mView/aHideAll", "Hide all / Restore" , "", "Shift+Esc", "Hide all widgets" , True) action("mView/aOpenMainMenu", "Open main menu" , "", "F10", "" , True) separator("mView") menu ("mEdit", "Edit" , "" ) action("mEdit/aStripTrailingWhitespace", "Strip trailing whitespace when saving", "", "", "" , True, True) separator("mEdit") menu ("mEdit/mCopyPasteLines", "Copy-paste lines" , "" ) menu ("mEdit/mIndentation", "Indentation" , "" ) separator("mEdit") action("mEdit/aEnableVimMode", "Enable Vim mode" , "", "", "" , False, True) menu ("mNavigation", "Navigation" , "" ) action("mNavigation/aFocusCurrentDocument", "Focus to editor" , "text.png", "Ctrl+Return", "Focus current document" , False) menu ("mNavigation/mSearchReplace", "&Search && Replace" , "search-replace-directory.png") menu ("mNavigation/mBookmarks", "&Bookmarks" , "bookmark.png") separator("mNavigation"), action("mNavigation/aNext", "&Next file" , "next.png", "Ctrl+PgDown", "Next file" , False) action("mNavigation/aPrevious", "&Previous file" , "previous.png", "Ctrl+PgUp", "Previous file" , False) separator("mNavigation") action("mNavigation/aGoto", "Go go line..." , "goto.png", "Ctrl+G", "Go to line..." , False) menu ("mNavigation/mFileBrowser", "File browser" , ':/enkiicons/open.png', visible=False) menu ("mNavigation/mScroll", "Scroll file" , '') menu ("mSettings", "Settings" , "" ) menu ("mTools", "Tools" , "" ) menu ("mHelp", "Help" , "" ) @pyqtSlot() def _openMainMenu(self): fileMenu = core.actionManager().menu('mFile') self._menuBar.setActiveAction(fileMenu.menuAction()) def menuBar(self): """Reference to menuBar """ return self._menuBar def topToolBar(self): """Top tool bar. Contains main menu, position indicator, etc """ return self._topToolBar def statusBar(self): """Return main window status bar. It is located on the top tool bar """ return self._statusBar def setWorkspace(self, workspace): """Set central widget of the main window. Normally called only by core when initializing system """ self._centralLayout.addWidget(workspace) self.setFocusProxy(workspace) def defaultTitle(self): """Default title. Contains name and version """ return "%s v.%s" % (enki.core.defines.PACKAGE_NAME, enki.core.defines.PACKAGE_VERSION) def centralLayout(self): """Layout of the central widget. Contains Workspace and search widget """ return self._centralLayout def appendMessage(self, text, timeoutMs=10000): """Append message to the queue. It will be shown as non-modal at the bottom of the window. Use such notifications, which are too long or too important for status bar but, not so important, to interrupt an user with QMessageBox """ if self._queuedMessageToolBar is None: self._initQueuedMessageToolBar() self._queuedMessageToolBar.appendMessage(text, timeoutMs) def closeEvent(self, event): """NOT A PUBLIC API Close event handler. Shows save files dialog. Cancels close, if dialog was rejected """ # saving geometry BEFORE closing widgets, because state might be changed, when docks are closed self._saveState() self._saveGeometry() # request close all documents if not core.workspace().askToCloseAll(): event.ignore() return core.aboutToTerminate.emit() self.hide() core.workspace().forceCloseAllDocuments() return QMainWindow.closeEvent(self, event) def onQuit(self): # saving geometry BEFORE closing widgets, because state might be changed, when docks are closed self._saveState() self._saveGeometry() # request close all documents if not core.workspace().askToCloseAll(): return core.aboutToTerminate.emit() self.hide() core.workspace().forceCloseAllDocuments() return QApplication.quit() def _saveByteArray(self, path, title, data): """Load data, show error and return None if failed""" try: with open(path, 'wb') as f: f.write(data) except (OSError, IOError) as ex: error = str(ex) QMessageBox.critical(None, self.tr("Cannot save {}".format(title)), self.tr("Cannot create file '%s'\nError: %s" % (path, error))) return def _loadByteArray(self, path, title): """Load data, show error and return None if failed""" if os.path.exists(path): try: with open(path, 'rb') as f: return f.read() except (OSError, IOError) as ex: error = str(ex) QMessageBox.critical(None, self.tr("Cannot restore {}".format(title)), self.tr("Cannot read file '%s'\nError: %s" % (path, error))) return None def _saveState(self): """Save window state to main_window_state.bin file in the config directory """ self._saveByteArray(self._STATE_FILE, "main window state", self.saveState()) def loadState(self): """Restore window state from main_window_state.bin and config. Called by the core after all plugins had been initialized """ self._restoreGeometry() state = self._loadByteArray(self._STATE_FILE, "main window state") if state is not None: self.restoreState(state) else: # no state, first start self.showMaximized() for dock in self.findChildren(DockWidget): dock.show() def _saveGeometry(self): """Save window geometry to the config file """ self._saveByteArray(self._GEOMETRY_FILE, "main window geometry", self.saveGeometry()) def _restoreGeometry(self): """Restore window geometry to the config file """ geometry = self._loadByteArray(self._GEOMETRY_FILE, "main window geometry") if geometry is not None: self.restoreGeometry(geometry) def sizeHint(self): return QSize(900, 560) def dragEnterEvent(self, event): """QMainWindow method reimplementation. Say, that we are ready to accept dragged urls """ if event.mimeData().hasUrls(): # accept drag event.acceptProposedAction() # default handler QMainWindow.dragEnterEvent(self, event) def dropEvent(self, event): """QMainWindow method reimplementation. Open dropt files """ if event.mimeData().hasUrls(): for url in event.mimeData().urls(): localFile = url.toLocalFile() if os.path.isfile(localFile): core.workspace().openFile(localFile) elif os.path.isdir(localFile): self.directoryDropt.emit(localFile) # default handler QMainWindow.dropEvent(self, event) def addDockWidget(self, area, dock): pass # not a plugin API method """Add dock widget to previous position, if known. Otherwise add to specified area """ assert not dock in self._addedDockWidgets self._addedDockWidgets.append(dock) if not self.restoreDockWidget(dock): QMainWindow.addDockWidget(self, area, dock) """ Scroll view to make the cursor visible. Otherwise cursor can disappear from the viewport. QTimer is used because ensureCursorVisible works only after the dock has been drawn. A bad fix for #319 """ QTimer.singleShot(0, self._ensureCursorVisible) def _ensureCursorVisible(self): # When the timer fires, first check that there's still a workspace/document. if core.workspace() is not None: document = core.workspace().currentDocument() if document is not None: document.qutepart.ensureCursorVisible def removeDockWidget(self, dock): pass # not a plugin API method """Remove dock widget""" assert dock in self._addedDockWidgets self._addedDockWidgets.remove(dock) QMainWindow.removeDockWidget(self, dock) def restoreState(self, state): pass # not a plugin API method """Restore state shows widgets, which exist but shall not be installed on main window """ QMainWindow.restoreState(self, state) for dock in self.findChildren(DockWidget): if not dock in self._addedDockWidgets: dock.hide()
class _ToolsDock(QWidget): """Former Miscellaneous, contains all the widgets in the bottom area.""" findStarted = pyqtSignal() splitEditor = pyqtSignal(QWidget, QWidget, bool) closeSplit = pyqtSignal(QWidget) def __init__(self, parent=None): super(_ToolsDock, self).__init__(parent) #Register signals connections connections = ( { 'target': 'main_container', 'signal_name': "findOcurrences", #(QString) 'slot': self.show_find_occurrences }, { 'target': 'main_container', 'signal_name': "runFile", #(QString) 'slot': self.execute_file }, ) IDE.register_signals('tools_dock', connections) IDE.register_service("tools_dock", self) def setup_ui(self): """Load all the components of the ui during the install process.""" vbox = QVBoxLayout(self) vbox.setContentsMargins(0, 0, 0, 0) vbox.setSpacing(0) self.__toolbar = QToolBar() self.__toolbar.setObjectName('custom') hbox = QHBoxLayout() vbox.addLayout(hbox) self.stack = StackedWidget() vbox.addWidget(self.stack) self._console = console_widget.ConsoleWidget() self._runWidget = run_widget.RunWidget() self._web = web_render.WebRender() self._findInFilesWidget = find_in_files.FindInFilesWidget( self.parent()) # Not Configurable Shortcuts shortEscMisc = QShortcut(QKeySequence(Qt.Key_Escape), self) shortEscMisc.activated.connect(self.hide) #Toolbar hbox.addWidget(self.__toolbar) self.add_to_stack(self._console, ":img/console", translations.TR_CONSOLE) self.add_to_stack(self._runWidget, ":img/play", translations.TR_OUTPUT) self.add_to_stack(self._web, ":img/web", translations.TR_WEB_PREVIEW) self.add_to_stack(self._findInFilesWidget, ":img/find", translations.TR_FIND_IN_FILES) #Last Element in the Stacked widget self._results = results.Results(self) self.stack.addWidget(self._results) # self.__toolbar.addSeparator() hbox.addSpacerItem(QSpacerItem(1, 0, QSizePolicy.Expanding)) btn_close = QPushButton( self.style().standardIcon(QStyle.SP_DialogCloseButton), '') btn_close.setIconSize(QSize(24, 24)) btn_close.setObjectName('navigation_button') btn_close.setToolTip('F4: ' + translations.TR_ALL_VISIBILITY) hbox.addWidget(btn_close) btn_close.clicked['bool'].connect(self.hide) def install(self): """Install triggered by the ide.""" self.setup_ui() ninjaide = IDE.getInstance() ninjaide.place_me_on("tools_dock", self, "central") ui_tools.install_shortcuts(self, actions.ACTIONS, ninjaide) ninjaide.goingDown.connect(self.save_configuration) qsettings = IDE.ninja_settings() value = qsettings.value("tools_dock/visible", True, type=bool) self.setVisible(value) print("\ninstall") def save_configuration(self): qsettings = IDE.ninja_settings() qsettings.setValue("tools_dock/visible", self.isVisible()) def change_visibility(self): """Change tools dock visibility.""" print("change_visibility22", self.isVisible()) if self.isVisible(): self.hide() else: self.show() def add_project_to_console(self, projectFolder): """Add the namespace of the project received into the ninja-console.""" self._console.load_project_into_console(projectFolder) def remove_project_from_console(self, projectFolder): """Remove the namespace of the project received from the console.""" self._console.unload_project_from_console(projectFolder) def _item_changed(self, val): """Change the current item.""" print("_item_changed", val) if not self.isVisible(): self.show() self.stack.show_display(val) def show_find_in_files_widget(self): """Show the Find In Files widget.""" index_of = self.stack.indexOf(self._findInFilesWidget) self._item_changed(index_of) self._findInFilesWidget.open() self._findInFilesWidget.setFocus() def show_find_occurrences(self, word): """Show Find In Files widget in find occurrences mode.""" index_of = self.stack.indexOf(self._findInFilesWidget) self._item_changed(index_of) self._findInFilesWidget.find_occurrences(word) self._findInFilesWidget.setFocus() def execute_file(self): """Execute the current file.""" main_container = IDE.get_service('main_container') if not main_container: return editorWidget = main_container.get_current_editor() if editorWidget: #emit a signal for plugin! self.fileExecuted.emit(editorWidget.file_path) main_container.save_file(editorWidget) ext = file_manager.get_file_extension(editorWidget.file_path) #TODO: Remove the IF statment and use Handlers if ext == 'py': self._run_application(editorWidget.file_path) elif ext == 'html': self.render_web_page(editorWidget.file_path) def execute_project(self): """Execute the project marked as Main Project.""" projects_explorer = IDE.get_service('projects_explorer') if projects_explorer is None: return nproject = projects_explorer.current_project if nproject: main_file = nproject.main_file if not main_file and projects_explorer.current_tree: projects_explorer.current_tree.open_project_properties() elif main_file: projects_explorer.save_project() #emit a signal for plugin! self.projectExecuted.emit(nproject.path) main_file = file_manager.create_path(nproject.path, nproject.main_file) self._run_application(main_file, pythonExec=nproject.python_exec_command, PYTHONPATH=nproject.python_path, programParams=nproject.program_params, preExec=nproject.pre_exec_script, postExec=nproject.post_exec_script) else: QMessageBox.information( self, translations.TR_INFO_TITLE_PROJECT_PROPERTIES, translations.TR_INFO_MESSAGE_PROJECT_PROPERTIES) def _run_application(self, fileName, pythonExec=False, PYTHONPATH=None, programParams='', preExec='', postExec=''): """Execute the process to run the application.""" self._item_changed(1) self.show() self._runWidget.start_process(fileName, pythonExec, PYTHONPATH, programParams, preExec, postExec) self._runWidget.input.setFocus() def show_results(self, items): """Show Results of Navigate to for several occurrences.""" index_of = self.stack.indexOf(self._results) self._item_changed(index_of) self.show() self._results.update_result(items) self._results._tree.setFocus() self._results.setFocus() def kill_application(self): """Kill the process of the application being executed.""" self._runWidget.kill_process() def render_web_page(self, url): """Render a webpage from the url path.""" index_of = self.stack.indexOf(self._web) self._item_changed(index_of) self.show() self._web.render_page(url) if settings.SHOW_WEB_INSPECTOR: web_inspector = IDE.get_service('web_inspector') if web_inspector: web_inspector.set_inspection_page(self._web.webFrame.page()) self._web.webFrame.triggerPageAction(QWebPage.InspectElement, True) web_inspector.refresh_inspector() self._web.setFocus() def add_to_stack(self, widget, icon_path, description): """ Add a widget to the container and an button(with icon))to the toolbar to show the widget """ #add the widget self.stack.addWidget(widget) #create a button in the toolbar to show the widget button = QPushButton(QIcon(icon_path), '') button.setIconSize(QSize(16, 16)) button.setToolTip(description) index = self.stack.count() - 1 button.clicked['bool'].connect( lambda s, i=index: self._item_changed(i)) self.__toolbar.addWidget(button) def showEvent(self, event): super(_ToolsDock, self).showEvent(event) widget = self.stack.currentWidget() if widget: widget.setFocus()
class SvnProjectHelper(VcsProjectHelper): """ Class implementing the VCS project helper for Subversion. """ def __init__(self, vcsObject, projectObject, parent=None, name=None): """ Constructor @param vcsObject reference to the vcs object @param projectObject reference to the project object @param parent parent widget (QWidget) @param name name of this object (string) """ VcsProjectHelper.__init__(self, vcsObject, projectObject, parent, name) def getActions(self): """ Public method to get a list of all actions. @return list of all actions (list of E5Action) """ return self.actions[:] def initActions(self): """ Public method to generate the action objects. """ self.vcsNewAct = E5Action(self.tr('New from repository'), UI.PixmapCache.getIcon("vcsCheckout.png"), self.tr('&New from repository...'), 0, 0, self, 'subversion_new') self.vcsNewAct.setStatusTip( self.tr('Create a new project from the VCS repository')) self.vcsNewAct.setWhatsThis( self.tr("""<b>New from repository</b>""" """<p>This creates a new local project from the VCS""" """ repository.</p>""")) self.vcsNewAct.triggered.connect(self._vcsCheckout) self.actions.append(self.vcsNewAct) self.vcsUpdateAct = E5Action(self.tr('Update from repository'), UI.PixmapCache.getIcon("vcsUpdate.png"), self.tr('&Update from repository'), 0, 0, self, 'subversion_update') self.vcsUpdateAct.setStatusTip( self.tr('Update the local project from the VCS repository')) self.vcsUpdateAct.setWhatsThis( self.tr("""<b>Update from repository</b>""" """<p>This updates the local project from the VCS""" """ repository.</p>""")) self.vcsUpdateAct.triggered.connect(self._vcsUpdate) self.actions.append(self.vcsUpdateAct) self.vcsCommitAct = E5Action( self.tr('Commit changes to repository'), UI.PixmapCache.getIcon("vcsCommit.png"), self.tr('&Commit changes to repository...'), 0, 0, self, 'subversion_commit') self.vcsCommitAct.setStatusTip( self.tr( 'Commit changes to the local project to the VCS repository')) self.vcsCommitAct.setWhatsThis( self.tr( """<b>Commit changes to repository</b>""" """<p>This commits changes to the local project to the VCS""" """ repository.</p>""")) self.vcsCommitAct.triggered.connect(self._vcsCommit) self.actions.append(self.vcsCommitAct) self.svnLogBrowserAct = E5Action(self.tr('Show log browser'), UI.PixmapCache.getIcon("vcsLog.png"), self.tr('Show log browser'), 0, 0, self, 'subversion_log_browser') self.svnLogBrowserAct.setStatusTip( self.tr('Show a dialog to browse the log of the local project')) self.svnLogBrowserAct.setWhatsThis( self. tr("""<b>Show log browser</b>""" """<p>This shows a dialog to browse the log of the local""" """ project. A limited number of entries is shown first. More""" """ can be retrieved later on.</p>""")) self.svnLogBrowserAct.triggered.connect(self._vcsLogBrowser) self.actions.append(self.svnLogBrowserAct) self.vcsDiffAct = E5Action(self.tr('Show differences'), UI.PixmapCache.getIcon("vcsDiff.png"), self.tr('Show &difference'), 0, 0, self, 'subversion_diff') self.vcsDiffAct.setStatusTip( self.tr( 'Show the difference of the local project to the repository')) self.vcsDiffAct.setWhatsThis( self.tr("""<b>Show differences</b>""" """<p>This shows differences of the local project to the""" """ repository.</p>""")) self.vcsDiffAct.triggered.connect(self._vcsDiff) self.actions.append(self.vcsDiffAct) self.svnExtDiffAct = E5Action(self.tr('Show differences (extended)'), UI.PixmapCache.getIcon("vcsDiff.png"), self.tr('Show differences (extended)'), 0, 0, self, 'subversion_extendeddiff') self.svnExtDiffAct.setStatusTip( self. tr('Show the difference of revisions of the project to the repository' )) self.svnExtDiffAct.setWhatsThis( self.tr("""<b>Show differences (extended)</b>""" """<p>This shows differences of selectable revisions of""" """ the project.</p>""")) self.svnExtDiffAct.triggered.connect(self.__svnExtendedDiff) self.actions.append(self.svnExtDiffAct) self.svnUrlDiffAct = E5Action(self.tr('Show differences (URLs)'), UI.PixmapCache.getIcon("vcsDiff.png"), self.tr('Show differences (URLs)'), 0, 0, self, 'subversion_urldiff') self.svnUrlDiffAct.setStatusTip( self. tr('Show the difference of the project between two repository URLs' )) self.svnUrlDiffAct.setWhatsThis( self.tr("""<b>Show differences (URLs)</b>""" """<p>This shows differences of the project between""" """ two repository URLs.</p>""")) self.svnUrlDiffAct.triggered.connect(self.__svnUrlDiff) self.actions.append(self.svnUrlDiffAct) self.vcsStatusAct = E5Action(self.tr('Show status'), UI.PixmapCache.getIcon("vcsStatus.png"), self.tr('Show &status'), 0, 0, self, 'subversion_status') self.vcsStatusAct.setStatusTip( self.tr('Show the status of the local project')) self.vcsStatusAct.setWhatsThis( self.tr("""<b>Show status</b>""" """<p>This shows the status of the local project.</p>""")) self.vcsStatusAct.triggered.connect(self._vcsStatus) self.actions.append(self.vcsStatusAct) self.svnChangeListsAct = E5Action( self.tr('Show change lists'), UI.PixmapCache.getIcon("vcsChangeLists.png"), self.tr('Show change lists'), 0, 0, self, 'subversion_changelists') self.svnChangeListsAct.setStatusTip( self. tr('Show the change lists and associated files of the local project' )) self.svnChangeListsAct.setWhatsThis( self. tr("""<b>Show change lists</b>""" """<p>This shows the change lists and associated files of the""" """ local project.</p>""")) self.svnChangeListsAct.triggered.connect(self.__svnChangeLists) self.actions.append(self.svnChangeListsAct) self.vcsTagAct = E5Action(self.tr('Tag in repository'), UI.PixmapCache.getIcon("vcsTag.png"), self.tr('&Tag in repository...'), 0, 0, self, 'subversion_tag') self.vcsTagAct.setStatusTip( self.tr('Tag the local project in the repository')) self.vcsTagAct.setWhatsThis( self.tr( """<b>Tag in repository</b>""" """<p>This tags the local project in the repository.</p>""")) self.vcsTagAct.triggered.connect(self._vcsTag) self.actions.append(self.vcsTagAct) self.vcsExportAct = E5Action(self.tr('Export from repository'), UI.PixmapCache.getIcon("vcsExport.png"), self.tr('&Export from repository...'), 0, 0, self, 'subversion_export') self.vcsExportAct.setStatusTip( self.tr('Export a project from the repository')) self.vcsExportAct.setWhatsThis( self.tr("""<b>Export from repository</b>""" """<p>This exports a project from the repository.</p>""")) self.vcsExportAct.triggered.connect(self._vcsExport) self.actions.append(self.vcsExportAct) self.vcsPropsAct = E5Action(self.tr('Command options'), self.tr('Command &options...'), 0, 0, self, 'subversion_options') self.vcsPropsAct.setStatusTip(self.tr('Show the VCS command options')) self.vcsPropsAct.setWhatsThis( self. tr("""<b>Command options...</b>""" """<p>This shows a dialog to edit the VCS command options.</p>""" )) self.vcsPropsAct.triggered.connect(self._vcsCommandOptions) self.actions.append(self.vcsPropsAct) self.vcsRevertAct = E5Action(self.tr('Revert changes'), UI.PixmapCache.getIcon("vcsRevert.png"), self.tr('Re&vert changes'), 0, 0, self, 'subversion_revert') self.vcsRevertAct.setStatusTip( self.tr('Revert all changes made to the local project')) self.vcsRevertAct.setWhatsThis( self. tr("""<b>Revert changes</b>""" """<p>This reverts all changes made to the local project.</p>""" )) self.vcsRevertAct.triggered.connect(self._vcsRevert) self.actions.append(self.vcsRevertAct) self.vcsMergeAct = E5Action(self.tr('Merge'), UI.PixmapCache.getIcon("vcsMerge.png"), self.tr('Mer&ge changes...'), 0, 0, self, 'subversion_merge') self.vcsMergeAct.setStatusTip( self.tr('Merge changes of a tag/revision into the local project')) self.vcsMergeAct.setWhatsThis( self.tr( """<b>Merge</b>""" """<p>This merges changes of a tag/revision into the local""" """ project.</p>""")) self.vcsMergeAct.triggered.connect(self._vcsMerge) self.actions.append(self.vcsMergeAct) self.vcsSwitchAct = E5Action(self.tr('Switch'), UI.PixmapCache.getIcon("vcsSwitch.png"), self.tr('S&witch...'), 0, 0, self, 'subversion_switch') self.vcsSwitchAct.setStatusTip( self.tr('Switch the local copy to another tag/branch')) self.vcsSwitchAct.setWhatsThis( self. tr("""<b>Switch</b>""" """<p>This switches the local copy to another tag/branch.</p>""" )) self.vcsSwitchAct.triggered.connect(self._vcsSwitch) self.actions.append(self.vcsSwitchAct) self.vcsResolveAct = E5Action(self.tr('Conflicts resolved'), self.tr('Con&flicts resolved'), 0, 0, self, 'subversion_resolve') self.vcsResolveAct.setStatusTip( self.tr('Mark all conflicts of the local project as resolved')) self.vcsResolveAct.setWhatsThis( self.tr("""<b>Conflicts resolved</b>""" """<p>This marks all conflicts of the local project as""" """ resolved.</p>""")) self.vcsResolveAct.triggered.connect(self.__svnResolve) self.actions.append(self.vcsResolveAct) self.vcsCleanupAct = E5Action(self.tr('Cleanup'), self.tr('Cleanu&p'), 0, 0, self, 'subversion_cleanup') self.vcsCleanupAct.setStatusTip(self.tr('Cleanup the local project')) self.vcsCleanupAct.setWhatsThis( self.tr( """<b>Cleanup</b>""" """<p>This performs a cleanup of the local project.</p>""")) self.vcsCleanupAct.triggered.connect(self._vcsCleanup) self.actions.append(self.vcsCleanupAct) self.vcsCommandAct = E5Action(self.tr('Execute command'), self.tr('E&xecute command...'), 0, 0, self, 'subversion_command') self.vcsCommandAct.setStatusTip( self.tr('Execute an arbitrary VCS command')) self.vcsCommandAct.setWhatsThis( self. tr("""<b>Execute command</b>""" """<p>This opens a dialog to enter an arbitrary VCS command.</p>""" )) self.vcsCommandAct.triggered.connect(self._vcsCommand) self.actions.append(self.vcsCommandAct) self.svnTagListAct = E5Action(self.tr('List tags'), self.tr('List tags...'), 0, 0, self, 'subversion_list_tags') self.svnTagListAct.setStatusTip(self.tr('List tags of the project')) self.svnTagListAct.setWhatsThis( self.tr("""<b>List tags</b>""" """<p>This lists the tags of the project.</p>""")) self.svnTagListAct.triggered.connect(self.__svnTagList) self.actions.append(self.svnTagListAct) self.svnBranchListAct = E5Action(self.tr('List branches'), self.tr('List branches...'), 0, 0, self, 'subversion_list_branches') self.svnBranchListAct.setStatusTip( self.tr('List branches of the project')) self.svnBranchListAct.setWhatsThis( self.tr("""<b>List branches</b>""" """<p>This lists the branches of the project.</p>""")) self.svnBranchListAct.triggered.connect(self.__svnBranchList) self.actions.append(self.svnBranchListAct) self.svnListAct = E5Action(self.tr('List repository contents'), self.tr('List repository contents...'), 0, 0, self, 'subversion_contents') self.svnListAct.setStatusTip( self.tr('Lists the contents of the repository')) self.svnListAct.setWhatsThis( self.tr("""<b>List repository contents</b>""" """<p>This lists the contents of the repository.</p>""")) self.svnListAct.triggered.connect(self.__svnTagList) self.actions.append(self.svnListAct) self.svnPropSetAct = E5Action(self.tr('Set Property'), self.tr('Set Property...'), 0, 0, self, 'subversion_property_set') self.svnPropSetAct.setStatusTip( self.tr('Set a property for the project files')) self.svnPropSetAct.setWhatsThis( self.tr("""<b>Set Property</b>""" """<p>This sets a property for the project files.</p>""")) self.svnPropSetAct.triggered.connect(self.__svnPropSet) self.actions.append(self.svnPropSetAct) self.svnPropListAct = E5Action(self.tr('List Properties'), self.tr('List Properties...'), 0, 0, self, 'subversion_property_list') self.svnPropListAct.setStatusTip( self.tr('List properties of the project files')) self.svnPropListAct.setWhatsThis( self.tr( """<b>List Properties</b>""" """<p>This lists the properties of the project files.</p>""")) self.svnPropListAct.triggered.connect(self.__svnPropList) self.actions.append(self.svnPropListAct) self.svnPropDelAct = E5Action(self.tr('Delete Property'), self.tr('Delete Property...'), 0, 0, self, 'subversion_property_delete') self.svnPropDelAct.setStatusTip( self.tr('Delete a property for the project files')) self.svnPropDelAct.setWhatsThis( self.tr( """<b>Delete Property</b>""" """<p>This deletes a property for the project files.</p>""")) self.svnPropDelAct.triggered.connect(self.__svnPropDel) self.actions.append(self.svnPropDelAct) self.svnRelocateAct = E5Action(self.tr('Relocate'), UI.PixmapCache.getIcon("vcsSwitch.png"), self.tr('Relocate...'), 0, 0, self, 'subversion_relocate') self.svnRelocateAct.setStatusTip( self.tr('Relocate the working copy to a new repository URL')) self.svnRelocateAct.setWhatsThis( self.tr( """<b>Relocate</b>""" """<p>This relocates the working copy to a new repository""" """ URL.</p>""")) self.svnRelocateAct.triggered.connect(self.__svnRelocate) self.actions.append(self.svnRelocateAct) self.svnRepoBrowserAct = E5Action( self.tr('Repository Browser'), UI.PixmapCache.getIcon("vcsRepoBrowser.png"), self.tr('Repository Browser...'), 0, 0, self, 'subversion_repo_browser') self.svnRepoBrowserAct.setStatusTip( self.tr('Show the Repository Browser dialog')) self.svnRepoBrowserAct.setWhatsThis( self.tr("""<b>Repository Browser</b>""" """<p>This shows the Repository Browser dialog.</p>""")) self.svnRepoBrowserAct.triggered.connect(self.__svnRepoBrowser) self.actions.append(self.svnRepoBrowserAct) self.svnConfigAct = E5Action(self.tr('Configure'), self.tr('Configure...'), 0, 0, self, 'subversion_configure') self.svnConfigAct.setStatusTip( self. tr('Show the configuration dialog with the Subversion page selected' )) self.svnConfigAct.setWhatsThis( self.tr( """<b>Configure</b>""" """<p>Show the configuration dialog with the Subversion page""" """ selected.</p>""")) self.svnConfigAct.triggered.connect(self.__svnConfigure) self.actions.append(self.svnConfigAct) self.svnUpgradeAct = E5Action(self.tr('Upgrade'), self.tr('Upgrade...'), 0, 0, self, 'subversion_upgrade') self.svnUpgradeAct.setStatusTip( self.tr('Upgrade the working copy to the current format')) self.svnUpgradeAct.setWhatsThis( self.tr( """<b>Upgrade</b>""" """<p>Upgrades the working copy to the current format.</p>""")) self.svnUpgradeAct.triggered.connect(self.__svnUpgrade) self.actions.append(self.svnUpgradeAct) def initMenu(self, menu): """ Public method to generate the VCS menu. @param menu reference to the menu to be populated (QMenu) """ menu.clear() act = menu.addAction( UI.PixmapCache.getIcon( os.path.join("VcsPlugins", "vcsSubversion", "icons", "subversion.png")), self.vcs.vcsName(), self._vcsInfoDisplay) font = act.font() font.setBold(True) act.setFont(font) menu.addSeparator() menu.addAction(self.vcsUpdateAct) menu.addAction(self.vcsCommitAct) menu.addSeparator() menu.addAction(self.vcsTagAct) if self.vcs.otherData["standardLayout"]: menu.addAction(self.svnTagListAct) menu.addAction(self.svnBranchListAct) else: menu.addAction(self.svnListAct) menu.addSeparator() menu.addAction(self.svnLogBrowserAct) menu.addSeparator() menu.addAction(self.vcsStatusAct) menu.addAction(self.svnChangeListsAct) menu.addSeparator() menu.addAction(self.vcsDiffAct) menu.addAction(self.svnExtDiffAct) menu.addAction(self.svnUrlDiffAct) menu.addSeparator() menu.addAction(self.vcsRevertAct) menu.addAction(self.vcsMergeAct) menu.addAction(self.vcsResolveAct) menu.addSeparator() menu.addAction(self.svnRelocateAct) menu.addAction(self.vcsSwitchAct) menu.addSeparator() menu.addAction(self.svnPropSetAct) menu.addAction(self.svnPropListAct) menu.addAction(self.svnPropDelAct) menu.addSeparator() menu.addAction(self.vcsCleanupAct) menu.addSeparator() menu.addAction(self.vcsCommandAct) menu.addAction(self.svnRepoBrowserAct) menu.addAction(self.svnUpgradeAct) menu.addSeparator() menu.addAction(self.vcsPropsAct) menu.addSeparator() menu.addAction(self.svnConfigAct) menu.addSeparator() menu.addAction(self.vcsNewAct) menu.addAction(self.vcsExportAct) def initToolbar(self, ui, toolbarManager): """ Public slot to initialize the VCS toolbar. @param ui reference to the main window (UserInterface) @param toolbarManager reference to a toolbar manager object (E5ToolBarManager) """ self.__toolbar = QToolBar(self.tr("Subversion (svn)"), ui) self.__toolbar.setIconSize(UI.Config.ToolBarIconSize) self.__toolbar.setObjectName("SubversionToolbar") self.__toolbar.setToolTip(self.tr('Subversion (svn)')) self.__toolbar.addAction(self.svnLogBrowserAct) self.__toolbar.addAction(self.vcsStatusAct) self.__toolbar.addSeparator() self.__toolbar.addAction(self.vcsDiffAct) self.__toolbar.addSeparator() self.__toolbar.addAction(self.svnRepoBrowserAct) self.__toolbar.addAction(self.vcsNewAct) self.__toolbar.addAction(self.vcsExportAct) self.__toolbar.addSeparator() title = self.__toolbar.windowTitle() toolbarManager.addToolBar(self.__toolbar, title) toolbarManager.addAction(self.vcsUpdateAct, title) toolbarManager.addAction(self.vcsCommitAct, title) toolbarManager.addAction(self.svnExtDiffAct, title) toolbarManager.addAction(self.svnUrlDiffAct, title) toolbarManager.addAction(self.svnChangeListsAct, title) toolbarManager.addAction(self.vcsTagAct, title) toolbarManager.addAction(self.vcsRevertAct, title) toolbarManager.addAction(self.vcsMergeAct, title) toolbarManager.addAction(self.vcsSwitchAct, title) toolbarManager.addAction(self.svnRelocateAct, title) self.__toolbar.setEnabled(False) self.__toolbar.setVisible(False) ui.registerToolbar("subversion", self.__toolbar.windowTitle(), self.__toolbar) ui.addToolBar(self.__toolbar) def removeToolbar(self, ui, toolbarManager): """ Public method to remove a toolbar created by initToolbar(). @param ui reference to the main window (UserInterface) @param toolbarManager reference to a toolbar manager object (E5ToolBarManager) """ ui.removeToolBar(self.__toolbar) ui.unregisterToolbar("subversion") title = self.__toolbar.windowTitle() toolbarManager.removeCategoryActions(title) toolbarManager.removeToolBar(self.__toolbar) self.__toolbar.deleteLater() self.__toolbar = None def __svnResolve(self): """ Private slot used to resolve conflicts of the local project. """ self.vcs.svnResolve(self.project.ppath) def __svnPropList(self): """ Private slot used to list the properties of the project files. """ self.vcs.svnListProps(self.project.ppath, True) def __svnPropSet(self): """ Private slot used to set a property for the project files. """ self.vcs.svnSetProp(self.project.ppath, True) def __svnPropDel(self): """ Private slot used to delete a property for the project files. """ self.vcs.svnDelProp(self.project.ppath, True) def __svnTagList(self): """ Private slot used to list the tags of the project. """ self.vcs.svnListTagBranch(self.project.ppath, True) def __svnBranchList(self): """ Private slot used to list the branches of the project. """ self.vcs.svnListTagBranch(self.project.ppath, False) def __svnExtendedDiff(self): """ Private slot used to perform a svn diff with the selection of revisions. """ self.vcs.svnExtendedDiff(self.project.ppath) def __svnUrlDiff(self): """ Private slot used to perform a svn diff with the selection of repository URLs. """ self.vcs.svnUrlDiff(self.project.ppath) def __svnRelocate(self): """ Private slot used to relocate the working copy to a new repository URL. """ self.vcs.svnRelocate(self.project.ppath) def __svnRepoBrowser(self): """ Private slot to open the repository browser. """ self.vcs.svnRepoBrowser(projectPath=self.project.ppath) def __svnConfigure(self): """ Private slot to open the configuration dialog. """ e5App().getObject("UserInterface").showPreferences( "zzz_subversionPage") def __svnChangeLists(self): """ Private slot used to show a list of change lists. """ self.vcs.svnShowChangelists(self.project.ppath) def __svnUpgrade(self): """ Private slot used to upgrade the working copy format. """ self.vcs.svnUpgrade(self.project.ppath)
class SvnProjectHelper(VcsProjectHelper): """ Class implementing the VCS project helper for Subversion. """ def __init__(self, vcsObject, projectObject, parent=None, name=None): """ Constructor @param vcsObject reference to the vcs object @param projectObject reference to the project object @param parent parent widget (QWidget) @param name name of this object (string) """ VcsProjectHelper.__init__(self, vcsObject, projectObject, parent, name) def getActions(self): """ Public method to get a list of all actions. @return list of all actions (list of E5Action) """ return self.actions[:] def initActions(self): """ Public method to generate the action objects. """ self.vcsNewAct = E5Action( self.tr('New from repository'), UI.PixmapCache.getIcon("vcsCheckout.png"), self.tr('&New from repository...'), 0, 0, self, 'subversion_new') self.vcsNewAct.setStatusTip(self.tr( 'Create a new project from the VCS repository' )) self.vcsNewAct.setWhatsThis(self.tr( """<b>New from repository</b>""" """<p>This creates a new local project from the VCS""" """ repository.</p>""" )) self.vcsNewAct.triggered.connect(self._vcsCheckout) self.actions.append(self.vcsNewAct) self.vcsUpdateAct = E5Action( self.tr('Update from repository'), UI.PixmapCache.getIcon("vcsUpdate.png"), self.tr('&Update from repository'), 0, 0, self, 'subversion_update') self.vcsUpdateAct.setStatusTip(self.tr( 'Update the local project from the VCS repository' )) self.vcsUpdateAct.setWhatsThis(self.tr( """<b>Update from repository</b>""" """<p>This updates the local project from the VCS""" """ repository.</p>""" )) self.vcsUpdateAct.triggered.connect(self._vcsUpdate) self.actions.append(self.vcsUpdateAct) self.vcsCommitAct = E5Action( self.tr('Commit changes to repository'), UI.PixmapCache.getIcon("vcsCommit.png"), self.tr('&Commit changes to repository...'), 0, 0, self, 'subversion_commit') self.vcsCommitAct.setStatusTip(self.tr( 'Commit changes to the local project to the VCS repository' )) self.vcsCommitAct.setWhatsThis(self.tr( """<b>Commit changes to repository</b>""" """<p>This commits changes to the local project to the VCS""" """ repository.</p>""" )) self.vcsCommitAct.triggered.connect(self._vcsCommit) self.actions.append(self.vcsCommitAct) self.vcsLogAct = E5Action( self.tr('Show log'), UI.PixmapCache.getIcon("vcsLog.png"), self.tr('Show &log'), 0, 0, self, 'subversion_log') self.vcsLogAct.setStatusTip(self.tr( 'Show the log of the local project' )) self.vcsLogAct.setWhatsThis(self.tr( """<b>Show log</b>""" """<p>This shows the log of the local project.</p>""" )) self.vcsLogAct.triggered.connect(self._vcsLog) self.actions.append(self.vcsLogAct) self.svnLogBrowserAct = E5Action( self.tr('Show log browser'), UI.PixmapCache.getIcon("vcsLog.png"), self.tr('Show log browser'), 0, 0, self, 'subversion_log_browser') self.svnLogBrowserAct.setStatusTip(self.tr( 'Show a dialog to browse the log of the local project' )) self.svnLogBrowserAct.setWhatsThis(self.tr( """<b>Show log browser</b>""" """<p>This shows a dialog to browse the log of the local""" """ project. A limited number of entries is shown first. More""" """ can be retrieved later on.</p>""" )) self.svnLogBrowserAct.triggered.connect(self._vcsLogBrowser) self.actions.append(self.svnLogBrowserAct) self.vcsDiffAct = E5Action( self.tr('Show differences'), UI.PixmapCache.getIcon("vcsDiff.png"), self.tr('Show &difference'), 0, 0, self, 'subversion_diff') self.vcsDiffAct.setStatusTip(self.tr( 'Show the difference of the local project to the repository' )) self.vcsDiffAct.setWhatsThis(self.tr( """<b>Show differences</b>""" """<p>This shows differences of the local project to the""" """ repository.</p>""" )) self.vcsDiffAct.triggered.connect(self._vcsDiff) self.actions.append(self.vcsDiffAct) self.svnExtDiffAct = E5Action( self.tr('Show differences (extended)'), UI.PixmapCache.getIcon("vcsDiff.png"), self.tr('Show differences (extended)'), 0, 0, self, 'subversion_extendeddiff') self.svnExtDiffAct.setStatusTip(self.tr( 'Show the difference of revisions of the project to the repository' )) self.svnExtDiffAct.setWhatsThis(self.tr( """<b>Show differences (extended)</b>""" """<p>This shows differences of selectable revisions of""" """ the project.</p>""" )) self.svnExtDiffAct.triggered.connect(self.__svnExtendedDiff) self.actions.append(self.svnExtDiffAct) self.svnUrlDiffAct = E5Action( self.tr('Show differences (URLs)'), UI.PixmapCache.getIcon("vcsDiff.png"), self.tr('Show differences (URLs)'), 0, 0, self, 'subversion_urldiff') self.svnUrlDiffAct.setStatusTip(self.tr( 'Show the difference of the project between two repository URLs' )) self.svnUrlDiffAct.setWhatsThis(self.tr( """<b>Show differences (URLs)</b>""" """<p>This shows differences of the project between""" """ two repository URLs.</p>""" )) self.svnUrlDiffAct.triggered.connect(self.__svnUrlDiff) self.actions.append(self.svnUrlDiffAct) self.vcsStatusAct = E5Action( self.tr('Show status'), UI.PixmapCache.getIcon("vcsStatus.png"), self.tr('Show &status'), 0, 0, self, 'subversion_status') self.vcsStatusAct.setStatusTip(self.tr( 'Show the status of the local project' )) self.vcsStatusAct.setWhatsThis(self.tr( """<b>Show status</b>""" """<p>This shows the status of the local project.</p>""" )) self.vcsStatusAct.triggered.connect(self._vcsStatus) self.actions.append(self.vcsStatusAct) self.svnChangeListsAct = E5Action( self.tr('Show change lists'), UI.PixmapCache.getIcon("vcsChangeLists.png"), self.tr('Show change lists'), 0, 0, self, 'subversion_changelists') self.svnChangeListsAct.setStatusTip(self.tr( 'Show the change lists and associated files of the local project' )) self.svnChangeListsAct.setWhatsThis(self.tr( """<b>Show change lists</b>""" """<p>This shows the change lists and associated files of the""" """ local project.</p>""" )) self.svnChangeListsAct.triggered.connect(self.__svnChangeLists) self.actions.append(self.svnChangeListsAct) self.vcsTagAct = E5Action( self.tr('Tag in repository'), UI.PixmapCache.getIcon("vcsTag.png"), self.tr('&Tag in repository...'), 0, 0, self, 'subversion_tag') self.vcsTagAct.setStatusTip(self.tr( 'Tag the local project in the repository' )) self.vcsTagAct.setWhatsThis(self.tr( """<b>Tag in repository</b>""" """<p>This tags the local project in the repository.</p>""" )) self.vcsTagAct.triggered.connect(self._vcsTag) self.actions.append(self.vcsTagAct) self.vcsExportAct = E5Action( self.tr('Export from repository'), UI.PixmapCache.getIcon("vcsExport.png"), self.tr('&Export from repository...'), 0, 0, self, 'subversion_export') self.vcsExportAct.setStatusTip(self.tr( 'Export a project from the repository' )) self.vcsExportAct.setWhatsThis(self.tr( """<b>Export from repository</b>""" """<p>This exports a project from the repository.</p>""" )) self.vcsExportAct.triggered.connect(self._vcsExport) self.actions.append(self.vcsExportAct) self.vcsPropsAct = E5Action( self.tr('Command options'), self.tr('Command &options...'), 0, 0, self, 'subversion_options') self.vcsPropsAct.setStatusTip(self.tr( 'Show the VCS command options')) self.vcsPropsAct.setWhatsThis(self.tr( """<b>Command options...</b>""" """<p>This shows a dialog to edit the VCS command options.</p>""" )) self.vcsPropsAct.triggered.connect(self._vcsCommandOptions) self.actions.append(self.vcsPropsAct) self.vcsRevertAct = E5Action( self.tr('Revert changes'), UI.PixmapCache.getIcon("vcsRevert.png"), self.tr('Re&vert changes'), 0, 0, self, 'subversion_revert') self.vcsRevertAct.setStatusTip(self.tr( 'Revert all changes made to the local project' )) self.vcsRevertAct.setWhatsThis(self.tr( """<b>Revert changes</b>""" """<p>This reverts all changes made to the local project.</p>""" )) self.vcsRevertAct.triggered.connect(self._vcsRevert) self.actions.append(self.vcsRevertAct) self.vcsMergeAct = E5Action( self.tr('Merge'), UI.PixmapCache.getIcon("vcsMerge.png"), self.tr('Mer&ge changes...'), 0, 0, self, 'subversion_merge') self.vcsMergeAct.setStatusTip(self.tr( 'Merge changes of a tag/revision into the local project' )) self.vcsMergeAct.setWhatsThis(self.tr( """<b>Merge</b>""" """<p>This merges changes of a tag/revision into the local""" """ project.</p>""" )) self.vcsMergeAct.triggered.connect(self._vcsMerge) self.actions.append(self.vcsMergeAct) self.vcsSwitchAct = E5Action( self.tr('Switch'), UI.PixmapCache.getIcon("vcsSwitch.png"), self.tr('S&witch...'), 0, 0, self, 'subversion_switch') self.vcsSwitchAct.setStatusTip(self.tr( 'Switch the local copy to another tag/branch' )) self.vcsSwitchAct.setWhatsThis(self.tr( """<b>Switch</b>""" """<p>This switches the local copy to another tag/branch.</p>""" )) self.vcsSwitchAct.triggered.connect(self._vcsSwitch) self.actions.append(self.vcsSwitchAct) self.vcsResolveAct = E5Action( self.tr('Conflicts resolved'), self.tr('Con&flicts resolved'), 0, 0, self, 'subversion_resolve') self.vcsResolveAct.setStatusTip(self.tr( 'Mark all conflicts of the local project as resolved' )) self.vcsResolveAct.setWhatsThis(self.tr( """<b>Conflicts resolved</b>""" """<p>This marks all conflicts of the local project as""" """ resolved.</p>""" )) self.vcsResolveAct.triggered.connect(self.__svnResolve) self.actions.append(self.vcsResolveAct) self.vcsCleanupAct = E5Action( self.tr('Cleanup'), self.tr('Cleanu&p'), 0, 0, self, 'subversion_cleanup') self.vcsCleanupAct.setStatusTip(self.tr( 'Cleanup the local project' )) self.vcsCleanupAct.setWhatsThis(self.tr( """<b>Cleanup</b>""" """<p>This performs a cleanup of the local project.</p>""" )) self.vcsCleanupAct.triggered.connect(self._vcsCleanup) self.actions.append(self.vcsCleanupAct) self.vcsCommandAct = E5Action( self.tr('Execute command'), self.tr('E&xecute command...'), 0, 0, self, 'subversion_command') self.vcsCommandAct.setStatusTip(self.tr( 'Execute an arbitrary VCS command' )) self.vcsCommandAct.setWhatsThis(self.tr( """<b>Execute command</b>""" """<p>This opens a dialog to enter an arbitrary VCS command.</p>""" )) self.vcsCommandAct.triggered.connect(self._vcsCommand) self.actions.append(self.vcsCommandAct) self.svnTagListAct = E5Action( self.tr('List tags'), self.tr('List tags...'), 0, 0, self, 'subversion_list_tags') self.svnTagListAct.setStatusTip(self.tr( 'List tags of the project' )) self.svnTagListAct.setWhatsThis(self.tr( """<b>List tags</b>""" """<p>This lists the tags of the project.</p>""" )) self.svnTagListAct.triggered.connect(self.__svnTagList) self.actions.append(self.svnTagListAct) self.svnBranchListAct = E5Action( self.tr('List branches'), self.tr('List branches...'), 0, 0, self, 'subversion_list_branches') self.svnBranchListAct.setStatusTip(self.tr( 'List branches of the project' )) self.svnBranchListAct.setWhatsThis(self.tr( """<b>List branches</b>""" """<p>This lists the branches of the project.</p>""" )) self.svnBranchListAct.triggered.connect(self.__svnBranchList) self.actions.append(self.svnBranchListAct) self.svnListAct = E5Action( self.tr('List repository contents'), self.tr('List repository contents...'), 0, 0, self, 'subversion_contents') self.svnListAct.setStatusTip(self.tr( 'Lists the contents of the repository' )) self.svnListAct.setWhatsThis(self.tr( """<b>List repository contents</b>""" """<p>This lists the contents of the repository.</p>""" )) self.svnListAct.triggered.connect(self.__svnTagList) self.actions.append(self.svnListAct) self.svnPropSetAct = E5Action( self.tr('Set Property'), self.tr('Set Property...'), 0, 0, self, 'subversion_property_set') self.svnPropSetAct.setStatusTip(self.tr( 'Set a property for the project files' )) self.svnPropSetAct.setWhatsThis(self.tr( """<b>Set Property</b>""" """<p>This sets a property for the project files.</p>""" )) self.svnPropSetAct.triggered.connect(self.__svnPropSet) self.actions.append(self.svnPropSetAct) self.svnPropListAct = E5Action( self.tr('List Properties'), self.tr('List Properties...'), 0, 0, self, 'subversion_property_list') self.svnPropListAct.setStatusTip(self.tr( 'List properties of the project files' )) self.svnPropListAct.setWhatsThis(self.tr( """<b>List Properties</b>""" """<p>This lists the properties of the project files.</p>""" )) self.svnPropListAct.triggered.connect(self.__svnPropList) self.actions.append(self.svnPropListAct) self.svnPropDelAct = E5Action( self.tr('Delete Property'), self.tr('Delete Property...'), 0, 0, self, 'subversion_property_delete') self.svnPropDelAct.setStatusTip(self.tr( 'Delete a property for the project files' )) self.svnPropDelAct.setWhatsThis(self.tr( """<b>Delete Property</b>""" """<p>This deletes a property for the project files.</p>""" )) self.svnPropDelAct.triggered.connect(self.__svnPropDel) self.actions.append(self.svnPropDelAct) self.svnRelocateAct = E5Action( self.tr('Relocate'), UI.PixmapCache.getIcon("vcsSwitch.png"), self.tr('Relocate...'), 0, 0, self, 'subversion_relocate') self.svnRelocateAct.setStatusTip(self.tr( 'Relocate the working copy to a new repository URL' )) self.svnRelocateAct.setWhatsThis(self.tr( """<b>Relocate</b>""" """<p>This relocates the working copy to a new repository""" """ URL.</p>""" )) self.svnRelocateAct.triggered.connect(self.__svnRelocate) self.actions.append(self.svnRelocateAct) self.svnRepoBrowserAct = E5Action( self.tr('Repository Browser'), UI.PixmapCache.getIcon("vcsRepoBrowser.png"), self.tr('Repository Browser...'), 0, 0, self, 'subversion_repo_browser') self.svnRepoBrowserAct.setStatusTip(self.tr( 'Show the Repository Browser dialog' )) self.svnRepoBrowserAct.setWhatsThis(self.tr( """<b>Repository Browser</b>""" """<p>This shows the Repository Browser dialog.</p>""" )) self.svnRepoBrowserAct.triggered.connect(self.__svnRepoBrowser) self.actions.append(self.svnRepoBrowserAct) self.svnConfigAct = E5Action( self.tr('Configure'), self.tr('Configure...'), 0, 0, self, 'subversion_configure') self.svnConfigAct.setStatusTip(self.tr( 'Show the configuration dialog with the Subversion page selected' )) self.svnConfigAct.setWhatsThis(self.tr( """<b>Configure</b>""" """<p>Show the configuration dialog with the Subversion page""" """ selected.</p>""" )) self.svnConfigAct.triggered.connect(self.__svnConfigure) self.actions.append(self.svnConfigAct) self.svnUpgradeAct = E5Action( self.tr('Upgrade'), self.tr('Upgrade...'), 0, 0, self, 'subversion_upgrade') self.svnUpgradeAct.setStatusTip(self.tr( 'Upgrade the working copy to the current format' )) self.svnUpgradeAct.setWhatsThis(self.tr( """<b>Upgrade</b>""" """<p>Upgrades the working copy to the current format.</p>""" )) self.svnUpgradeAct.triggered.connect(self.__svnUpgrade) self.actions.append(self.svnUpgradeAct) def initMenu(self, menu): """ Public method to generate the VCS menu. @param menu reference to the menu to be populated (QMenu) """ menu.clear() act = menu.addAction( UI.PixmapCache.getIcon( os.path.join("VcsPlugins", "vcsSubversion", "icons", "subversion.png")), self.vcs.vcsName(), self._vcsInfoDisplay) font = act.font() font.setBold(True) act.setFont(font) menu.addSeparator() menu.addAction(self.vcsUpdateAct) menu.addAction(self.vcsCommitAct) menu.addSeparator() menu.addAction(self.vcsTagAct) if self.vcs.otherData["standardLayout"]: menu.addAction(self.svnTagListAct) menu.addAction(self.svnBranchListAct) else: menu.addAction(self.svnListAct) menu.addSeparator() menu.addAction(self.vcsLogAct) menu.addAction(self.svnLogBrowserAct) menu.addSeparator() menu.addAction(self.vcsStatusAct) menu.addAction(self.svnChangeListsAct) menu.addSeparator() menu.addAction(self.vcsDiffAct) menu.addAction(self.svnExtDiffAct) menu.addAction(self.svnUrlDiffAct) menu.addSeparator() menu.addAction(self.vcsRevertAct) menu.addAction(self.vcsMergeAct) menu.addAction(self.vcsResolveAct) menu.addSeparator() menu.addAction(self.svnRelocateAct) menu.addAction(self.vcsSwitchAct) menu.addSeparator() menu.addAction(self.svnPropSetAct) menu.addAction(self.svnPropListAct) menu.addAction(self.svnPropDelAct) menu.addSeparator() menu.addAction(self.vcsCleanupAct) menu.addSeparator() menu.addAction(self.vcsCommandAct) menu.addAction(self.svnRepoBrowserAct) menu.addAction(self.svnUpgradeAct) menu.addSeparator() menu.addAction(self.vcsPropsAct) menu.addSeparator() menu.addAction(self.svnConfigAct) menu.addSeparator() menu.addAction(self.vcsNewAct) menu.addAction(self.vcsExportAct) def initToolbar(self, ui, toolbarManager): """ Public slot to initialize the VCS toolbar. @param ui reference to the main window (UserInterface) @param toolbarManager reference to a toolbar manager object (E5ToolBarManager) """ self.__toolbar = QToolBar(self.tr("Subversion (svn)"), ui) self.__toolbar.setIconSize(UI.Config.ToolBarIconSize) self.__toolbar.setObjectName("SubversionToolbar") self.__toolbar.setToolTip(self.tr('Subversion (svn)')) self.__toolbar.addAction(self.svnLogBrowserAct) self.__toolbar.addAction(self.vcsStatusAct) self.__toolbar.addSeparator() self.__toolbar.addAction(self.vcsDiffAct) self.__toolbar.addSeparator() self.__toolbar.addAction(self.svnRepoBrowserAct) self.__toolbar.addAction(self.vcsNewAct) self.__toolbar.addAction(self.vcsExportAct) self.__toolbar.addSeparator() title = self.__toolbar.windowTitle() toolbarManager.addToolBar(self.__toolbar, title) toolbarManager.addAction(self.vcsUpdateAct, title) toolbarManager.addAction(self.vcsCommitAct, title) toolbarManager.addAction(self.vcsLogAct, title) toolbarManager.addAction(self.svnExtDiffAct, title) toolbarManager.addAction(self.svnUrlDiffAct, title) toolbarManager.addAction(self.svnChangeListsAct, title) toolbarManager.addAction(self.vcsTagAct, title) toolbarManager.addAction(self.vcsRevertAct, title) toolbarManager.addAction(self.vcsMergeAct, title) toolbarManager.addAction(self.vcsSwitchAct, title) toolbarManager.addAction(self.svnRelocateAct, title) self.__toolbar.setEnabled(False) self.__toolbar.setVisible(False) ui.registerToolbar("subversion", self.__toolbar.windowTitle(), self.__toolbar) ui.addToolBar(self.__toolbar) def removeToolbar(self, ui, toolbarManager): """ Public method to remove a toolbar created by initToolbar(). @param ui reference to the main window (UserInterface) @param toolbarManager reference to a toolbar manager object (E5ToolBarManager) """ ui.removeToolBar(self.__toolbar) ui.unregisterToolbar("subversion") title = self.__toolbar.windowTitle() toolbarManager.removeCategoryActions(title) toolbarManager.removeToolBar(self.__toolbar) self.__toolbar.deleteLater() self.__toolbar = None def __svnResolve(self): """ Private slot used to resolve conflicts of the local project. """ self.vcs.svnResolve(self.project.ppath) def __svnPropList(self): """ Private slot used to list the properties of the project files. """ self.vcs.svnListProps(self.project.ppath, True) def __svnPropSet(self): """ Private slot used to set a property for the project files. """ self.vcs.svnSetProp(self.project.ppath, True) def __svnPropDel(self): """ Private slot used to delete a property for the project files. """ self.vcs.svnDelProp(self.project.ppath, True) def __svnTagList(self): """ Private slot used to list the tags of the project. """ self.vcs.svnListTagBranch(self.project.ppath, True) def __svnBranchList(self): """ Private slot used to list the branches of the project. """ self.vcs.svnListTagBranch(self.project.ppath, False) def __svnExtendedDiff(self): """ Private slot used to perform a svn diff with the selection of revisions. """ self.vcs.svnExtendedDiff(self.project.ppath) def __svnUrlDiff(self): """ Private slot used to perform a svn diff with the selection of repository URLs. """ self.vcs.svnUrlDiff(self.project.ppath) def __svnRelocate(self): """ Private slot used to relocate the working copy to a new repository URL. """ self.vcs.svnRelocate(self.project.ppath) def __svnRepoBrowser(self): """ Private slot to open the repository browser. """ self.vcs.svnRepoBrowser(projectPath=self.project.ppath) def __svnConfigure(self): """ Private slot to open the configuration dialog. """ e5App().getObject("UserInterface")\ .showPreferences("zzz_subversionPage") def __svnChangeLists(self): """ Private slot used to show a list of change lists. """ self.vcs.svnShowChangelists(self.project.ppath) def __svnUpgrade(self): """ Private slot used to upgrade the working copy format. """ self.vcs.svnUpgrade(self.project.ppath)
class _s_MiscContainer(QWidget): """From Miscellaneous, contains all the widgets in the bottom area.""" #Miscellaneous was to long and dificult to write :P def __init__(self, parent=None): super(_s_MiscContainer, self).__init__(parent) vbox = QVBoxLayout(self) vbox.setContentsMargins(0, 0, 0, 0) vbox.setSpacing(0) self.__toolbar = QToolBar() self.__toolbar.setObjectName('custom') hbox = QHBoxLayout() vbox.addLayout(hbox) self.stack = StackedWidget() vbox.addWidget(self.stack) self._console = console_widget.ConsoleWidget() self.stack.addWidget(self._console) self._runWidget = run_widget.RunWidget() self.stack.addWidget(self._runWidget) self._web = web_render.WebRender() self.stack.addWidget(self._web) self._findInFilesWidget = find_in_files.FindInFilesWidget( self.parent()) self.stack.addWidget(self._findInFilesWidget) #Last Element in the Stacked widget self._results = results.Results(self) self.stack.addWidget(self._results) self._btnConsole = QPushButton(QIcon(resources.IMAGES['console']), '') self._btnConsole.setToolTip(_translate("_s_MiscContainer", "Console")) self._btnRun = QPushButton(QIcon(resources.IMAGES['play']), '') self._btnRun.setToolTip(_translate("_s_MiscContainer", "Output")) self._btnWeb = QPushButton(QIcon(resources.IMAGES['web']), '') self._btnWeb.setToolTip(_translate("_s_MiscContainer", "Web Preview")) self._btnFind = QPushButton(QIcon(resources.IMAGES['find']), '') self._btnFind.setToolTip(_translate("_s_MiscContainer", "Find in Files")) #Toolbar hbox.addWidget(self.__toolbar) self.__toolbar.addWidget(self._btnConsole) self.__toolbar.addWidget(self._btnRun) self.__toolbar.addWidget(self._btnWeb) self.__toolbar.addWidget(self._btnFind) self.__toolbar.addSeparator() hbox.addSpacerItem(QSpacerItem(1, 0, QSizePolicy.Expanding)) btn_close = QPushButton( self.style().standardIcon(QStyle.SP_DialogCloseButton), '') btn_close.setObjectName('navigation_button') btn_close.setToolTip(_translate("_s_MiscContainer", 'F4: Show/Hide')) hbox.addWidget(btn_close) self._btnConsole.clicked['bool'].connect(lambda: self._item_changed(0)) self._btnRun.clicked['bool'].connect(lambda: self._item_changed(1)) self._btnWeb.clicked['bool'].connect(lambda: self._item_changed(2)) self._btnFind.clicked['bool'].connect(lambda: self._item_changed(3)) btn_close.clicked['bool'].connect(self.hide) def gain_focus(self): self._console.setFocus() def _item_changed(self, val): if not self.isVisible(): self.show() self.stack.show_display(val) def show_find_in_files_widget(self): index_of = self.stack.indexOf(self._findInFilesWidget) self._item_changed(index_of) self._findInFilesWidget.open() def show_find_occurrences(self, word): index_of = self.stack.indexOf(self._findInFilesWidget) self._item_changed(index_of) self._findInFilesWidget.find_occurrences(word) def load_toolbar(self, toolbar): toolbar.addWidget(self._combo) toolbar.addSeparator() def run_application(self, fileName, pythonPath=False, PYTHONPATH=None, programParams='', preExec='', postExec=''): self._item_changed(1) self.show() self._runWidget.start_process(fileName, pythonPath, PYTHONPATH, programParams, preExec, postExec) self._runWidget.input.setFocus() def show_results(self, items): self._item_changed(4) self.show() self._results.update_result(items) self._results._tree.setFocus() def kill_application(self): self._runWidget.kill_process() def render_web_page(self, url): self._item_changed(2) self.show() self._web.render_page(url) if settings.SHOW_WEB_INSPECTOR: explorer_container.ExplorerContainer().set_inspection_page( self._web.webFrame.page()) self._web.webFrame.triggerPageAction( QWebPage.InspectElement, True) explorer_container.ExplorerContainer().refresh_inspector() def add_to_stack(self, widget, icon_path, description): """ Add a widget to the container and an button(with icon))to the toolbar to show the widget """ #add the widget self.stack.addWidget(widget) #create a button in the toolbar to show the widget button = QPushButton(QIcon(icon_path), '') button.setToolTip(description) #index = self.stack.count() - 1 #func = lambda: self._item_changed(index) button.clicked['bool'].connect(lambda: self._item_changed(self.stack.count() - 1))#func self.__toolbar.addWidget(button)
class ToolbarController: def __init__(self, parent_window, app): self.parent = parent_window self.toolbar = QToolBar() self.app = app self.populating_tools = True def __get_combo_box(self, action_name) -> QComboBox: toolbar_actions = self.toolbar.actions() tags_list_action = next(act for act in toolbar_actions if act.text() == action_name) return tags_list_action.defaultWidget() def init(self): tools_combo = self.__get_combo_box(DEVTOOLS_COMBO_NAME) tools_combo.clear() for ek, ev in tool_plugins.items(): tools_combo.addItem(ev.tool.name, ek) # To avoid creating any view while we are populating tools in the combo box self.populating_tools = False selected_tool = self.app.data.get_selected_tool() found = tools_combo.findData(selected_tool) tools_combo.setCurrentIndex(found if found > 0 else 0) # Manually triggering to render the view as the index is not changing if found <= 0: self.on_toolbar_tool_changed(selected_tool) def on_toolbar_tool_changed(self, _): if self.populating_tools: return tools_combo = self.__get_combo_box("DevTools") current_tool = tools_combo.currentData() self.app.data.update_selected_tool(current_tool) def focus_on_devtools_combo_box(self): tools_combo = self.__get_combo_box("DevTools") tools_combo.setFocus(True) tools_combo.showPopup() def init_items(self): self.toolbar.setObjectName("maintoolbar") self.parent.addToolBar(Qt.TopToolBarArea, self.toolbar) self.toolbar.setMovable(False) self.toolbar.addSeparator() toolbar_ctx_list = QComboBox(self.parent) toolbar_ctx_list.setDuplicatesEnabled(False) toolbar_ctx_list.setEditable(True) toolbar_ctx_list.currentIndexChanged[str].connect( lambda new_tool: self.on_toolbar_tool_changed(new_tool)) toolbar_ctx_list_action = QWidgetAction(self.parent) toolbar_ctx_list_action.setText(DEVTOOLS_COMBO_NAME) toolbar_ctx_list_action.setDefaultWidget(toolbar_ctx_list) self.toolbar.addAction(toolbar_ctx_list_action) spacer = QWidget(self.parent) spacer.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding) self.toolbar.addWidget(spacer) toolbar_configure_action = QAction(QIcon(":/images/configure-48.png"), "Settings", self.parent) toolbar_configure_action.triggered.connect( self.parent.config_controller.show_dialog) self.toolbar.addAction(toolbar_configure_action)
class Window(QMainWindow): def __init__(self, *args, **kwds): super().__init__(*args, **kwds) # TODO: save state in settings file on exit self.setMinimumSize(1000, 600) # self.resize(QDesktopWidget().availableGeometry(self).size() * 0.7) self.set_title() self.main_grid = GridEditor(INIT_ROWS, INIT_COLS, self) self.setCentralWidget(self.main_grid) self.text_editor = CodeEditor() self.text_editor_dock = QDockWidget("Code Editor", self) self.text_editor_dock.setObjectName("CodeEditor") self.text_editor_dock.setAllowedAreas(Qt.RightDockWidgetArea) self.text_editor_dock.setWidget(self.text_editor) self.addDockWidget(Qt.RightDockWidgetArea, self.text_editor_dock) self.console_panel = ConsolePanel() self.console_panel_dock = QDockWidget("Console", self) self.console_panel_dock.setObjectName("Console") self.console_panel_dock.setAllowedAreas(Qt.RightDockWidgetArea) self.console_panel_dock.setWidget(self.console_panel) self.addDockWidget(Qt.RightDockWidgetArea, self.console_panel_dock) self.stdout_queue = Queue() sys.stdout = QueueWriteStream(self.stdout_queue) self.stdout_broadcaster = QueueBroadcaster(self.stdout_queue) self.stdout_broadcaster.new_queue_item.connect( partial(self.console_panel.append_to_log, "black")) self.stdout_queue_thread = QThread() self.stdout_broadcaster.moveToThread(self.stdout_queue_thread) self.stdout_queue_thread.started.connect(self.stdout_broadcaster.loop) self.stdout_queue_thread.start() self.stderr_queue = Queue() sys.stderr = QueueWriteStream(self.stderr_queue) self.stderr_broadcaster = QueueBroadcaster(self.stderr_queue) self.stderr_broadcaster.new_queue_item.connect( partial(self.console_panel.append_to_log, "red")) self.stderr_queue_thread = QThread() self.stderr_broadcaster.moveToThread(self.stderr_queue_thread) self.stderr_queue_thread.started.connect(self.stderr_broadcaster.loop) self.stderr_queue_thread.start() self.toolbar = QToolBar("Main toolbar") self.toolbar.setObjectName("MainToolbar") self.toolbar.setIconSize(QSize(16, 16)) self.toolbar.setToolButtonStyle(Qt.ToolButtonTextUnderIcon) self.toolbar_controls = dict() # standard icons from https://joekuan.wordpress.com/2015/09/23/list-of-qt-icons/ # theme icons from https://specifications.freedesktop.org/icon-naming-spec/icon-naming-spec-latest.html for tb_config in [ # fmt: off [ "button", "open", "Open", "document-open", "Click to open.", self.open_file_dialog, False ], [ "button", "save", "Save As", "document-save-as", "Click to save.", self.save_file_dialog, False ], [ "button", "new", "New", "document-new", "Click to clear and start new sheet.", self.new_sheet, False ], ["separator"], [ "button", "calculate", "Calculate", "media-playback-start", "Click to calculate sheet.", self.calculate, False ], [ "button", "resize_all", "Resize", "zoom-fit-best", "Click to resize columns and rows to fit.", self.main_grid.resize_all, False ], ["separator"], ["label", "Cell: "], [ "button", "invalidate", "Invalidate", QStyle.SP_TrashIcon, "Click to invalidate selected cells.", self.main_grid.invalidate_cell, False ], [ "button", "copy_values", "Copy Values", "edit-copy", "Click to copy selected cell values.", partial(self.main_grid.copy_cell, "value"), False ], [ "button", "paste", "Paste", "edit-paste", "Click to paste.", self.main_grid.paste_cell, False ], [ "button", "clear", "Clear", "edit-clear", "Click to clear selected cells.", self.main_grid.clear_cell, False ], [ "textfield", "format", "Format Spec..", 100, self.main_grid.format_cell ], ["separator"], [ "button", "show_editor", "Editor", "accessories-text-editor", "Click to show editor.", self.text_editor_dock.show, False ], [ "button", "show_console", "Console", "utilities-terminal", "Click to show console.", self.console_panel_dock.show, False ], ["separator"], [ "button", "exit", "Exit", "application-exit", "Click to exit.", self.close, False ], ["separator"], [ "button", "help", "Help", "help-about", "Click for help and about.", self.show_help_dialog, False ], # fmt: on ]: if tb_config[0] == "button": name, label, icon, status, func, checkable = tb_config[1:] if isinstance(icon, QStyle.StandardPixmap): icon = QIcon(QApplication.style().standardIcon(icon)) else: icon = QIcon.fromTheme(icon) button = QAction( icon, label, self, ) button.setStatusTip(status) button.triggered.connect(func) button.setCheckable(checkable) self.toolbar_controls[f"button_{name}"] = button self.toolbar.addAction(button) elif tb_config[0] == "separator": self.toolbar.addSeparator() elif tb_config[0] == "textfield": name, placeholder, max_width, func = tb_config[1:] line_edit = QLineEdit(self) line_edit.setPlaceholderText(placeholder) line_edit.setMaximumWidth(max_width) line_edit.returnPressed.connect(func) self.toolbar_controls[f"textfield_{name}"] = line_edit self.toolbar.addWidget(line_edit) elif tb_config[0] == "label": (label, ) = tb_config[1:] self.toolbar.addWidget(QLabel(label)) self.addToolBar(self.toolbar) self.status_bar = QStatusBar(self) self.setStatusBar(self.status_bar) self.read_settings() # event filter needs to be in top level thread self.main_grid.installEventFilter(self.main_grid) # clear all sets up namespace self.clear_all() def set_title(self, label=None): self.setWindowTitle("Simple Spreadsheet" + (f" - {label}" if label else "")) def calculate(self, s): self.main_grid.calculate() self.text_editor.execute_code() def new_sheet(self, s): self.clear_all() def clear_all(self): self.main_grid.clear() self.text_editor.clear() NAME_SPACE.clear() NAME_SPACE.update(new_name_space()) NAME_SPACE["WINDOW"] = self NAME_SPACE["GRID"] = self.main_grid def show_help_dialog(self, s): detail = dedent("""\ Keyboard shortcuts: CTRL + D: Fill down. CTRL + R: Fill right. CTRL + C: Copy cell formulas. CTRL + X: Cut cell formulas. CTRL + V: Paste cell formulas. For license information please see LICENSE text file included with this distribution. """) msg = QMessageBox(self) msg.setIcon(QMessageBox.Information) msg.setText( f"Copyright © {datetime.date.today().year} Blair Azzopardi.") msg.setWindowTitle("About Simple Spreadsheet") msg.setDetailedText(detail) msg.setStandardButtons(QMessageBox.Ok) msg.exec_() def save_file_dialog(self, s): options = QFileDialog.Options() options |= QFileDialog.DontUseNativeDialog file_name, _ = QFileDialog.getSaveFileName( self, "Save sheet data", "", "All Files (*);;Text Files (*.json)", options=options, ) if file_name: self.save_file(file_name) def save_file(self, file): try: file = Path(file) file_data = { "data": self.main_grid.export_data(), "code": self.text_editor.export_code(), "grid_state": self.main_grid.state, } file.write_text(json.dumps(file_data, cls=JSONEncoder)) self.set_title(file.name) except Exception as exc: show_exception(exc, self) def open_file_dialog(self, s): options = QFileDialog.Options() options |= QFileDialog.DontUseNativeDialog file_name, _ = QFileDialog.getOpenFileName( self, "Load sheet data", "", "All Files (*);;Text Files (*.json)", options=options, ) if file_name: self.open_file(file_name) def open_file(self, file): self.clear_all() file = Path(file) file_data = json.loads(file.read_text(), cls=JSONDecoder) # load & exec code, useful to load json importers self.text_editor.import_code(file_data["code"]) self.text_editor.execute_code() # load grid data - do not calc self.main_grid.import_data(file_data["data"]) self.set_title(file.name) # load grid state if "grid_state" in file_data: self.main_grid.state = file_data["grid_state"] def closeEvent(self, event): settings = QSettings("BlairAzzopardi", "SimpleSpreadSheet") settings.setValue("geometry", self.saveGeometry()) settings.setValue("windowState", self.saveState()) super().closeEvent(event) def read_settings(self): settings = QSettings("BlairAzzopardi", "SimpleSpreadSheet") if settings.value("geometry"): self.restoreGeometry(settings.value("geometry")) if settings.value("windowState"): self.restoreState(settings.value("windowState"))
class PluginLiteUI(QObject): def __init__(self, ui): super(PluginLiteUI, self).__init__(ui) self.__ui = ui self.__toolbars = e5App().getObject("ToolbarManager") self.__sourcesBrowser = e5App().getObject( "ProjectBrowser").getProjectBrowser("sources") # override window loaded event self.__oldShowEvent = self.__ui.showEvent self.__ui.showEvent = self.__windowLoaded self.__ui._UserInterface__populateToolbarsMenu = self.__populateToolbarsMenu # override source browser createPythonPopupMenus self.__oldCreatePythonPopupMenus = self.__sourcesBrowser._ProjectSourcesBrowser__createPythonPopupMenus self.__sourcesBrowser._ProjectSourcesBrowser__createPythonPopupMenus = self.__createPythonPopupMenus def activate(self): """ Public method to activate this plugin. @return tuple of None and activation status (boolean) """ return None, True def deactivate(self): """ Public method to deactivate this plugin. """ pass def __windowLoaded(self, event): """ Private method that gets called when the main window gets visible. """ # remove preferences items self.__simplifyPreferences() self.__setupMenus() self.__oldShowEvent(event) self.__setupSidebars() self.__hideStatusBar() self.__setupToolbars() e5App().getObject("ViewManager").editorOpenedEd.connect( self.__on_new_editor) # I must run only once self.__ui.showEvent = self.__oldShowEvent self.__showInitialTip() def __setupMenus(self): """ Private method that hides engineer-level menus and makes the others non-detachable. """ # hide unused menus for menu in ["view", "extras", "window", "bookmarks", "plugins"]: UiHelper.hideUnusedMenu(self.__ui, menu) toRemove = { "file": [ "Open &Bookmarked Files", "Search &File...", "Save &Copy...", "Export as", "Print Preview", "&Print" ], "edit": [ "Re&vert to last saved state", "&Indent", "U&nindent", "Toggle Comment", "Convert selection to upper case", "Convert selection to lower case", "Sort", "Complete", "&Calltip", "&Goto Line...", "Goto &Brace", "Goto Last &Edit Location", "Goto Previous Method or Class", "Goto Next Method or Class", "Select to &brace", "&Deselect all", "Shorten empty lines", "Convert &Line End Characters" ], "project": [ "Session", "Add &translation...", "&Diagrams", "Chec&k", "Sho&w", "Source &Documentation", "Pac&kagers", "&Properties...", "&User Properties...", "Filetype Associations...", "Lexer Associations..." ], "settings": [ "E&xport Preferences...", "I&mport Preferences...", "Tool&bars...", "Keyboard &Shortcuts...", "&Export Keyboard Shortcuts...", "&Import Keyboard Shortcuts...", "Show external &tools" ], "help": [ "Show &Versions", "Show &downloadable versions...", "Show Error &Log..." ] } for menu, items in toRemove.iteritems(): UiHelper.removeWidgetActions(self.__ui.getMenu(menu), items) removeFromSearch = [ "&Quicksearch", "Quicksearch &backwards", "Search current word forward", "Search current word backward", "Clear search markers", "Search in &Files...", "Replace in F&iles...", "Search in Open Files...", "Replace in Open Files..." ] for el in self.__ui.getMenu("edit").actions(): if el.text() == self.__ui.tr("&Search"): UiHelper.removeWidgetActions(el.menu(), removeFromSearch) break def __initLiteToolbar(self, ui, toolbarManager): # find first toolbar firstToolbar = None for toolbar in ui.findChildren(QToolBar): if toolbar.isVisible(): firstToolbar = toolbar break toCopy = [ ['file', ["&Save", "&Open...", "&New"]], ['project', ["&Save", "&Open...", "&New..."]], ] self.__toolbar = QToolBar(self.tr("Lite tools"), ui) self.__toolbar.setIconSize(UI.Config.ToolBarIconSize) self.__toolbar.setObjectName("LiteUI") self.__toolbar.setToolTip(self.tr('Pymakr lite tools')) title = self.__toolbar.windowTitle() toolbarManager.addToolBar(self.__toolbar, title) # load new toolbar actions for bar in toCopy: if self.__ui.getToolbar(bar[0]) != None and self.__ui.getToolbar( bar[0])[1] != None: for el in self.__ui.getToolbar(bar[0])[1].actions(): if el.text() in bar[1]: self.__toolbar.addAction(el) toolbarManager.addAction(el, title) try: ui.registerToolbar("lite", title, self.__toolbar) if firstToolbar: ui.insertToolBar(firstToolbar, self.__toolbar) else: ui.addToolBar(self.__toolbar) except KeyError: pass # happens when toolbar is already registered self.__toolbar.setIconSize(QSize(32, 32)) def __setupToolbars(self): self.__initLiteToolbar(self.__ui, self.__toolbars) for toolbar in [ "project", "edit", "file", "quicksearch", "search", "spelling" ]: UiHelper.hideToolbar(self.__ui, toolbar) self.__fixToolbars() def __setupSidebars(self): """ Private method that hides the pro-level sidebars """ allLeftTabs = { "File-Browser", "Project-Viewer", "Multiproject-Viewer", "Template-Viewer", "Symbols", "File-Browser" } allBottomTabs = { "Pycom Console", "Shell", "Task-Viewer", "Numbers", "Translator", "Local Shell", "Log-Viewer" } toHideBottom = list(allBottomTabs - bottomTabsToShow) toHideLeft = list(allLeftTabs - leftTabsToShow) try: UiHelper.hideItemsSidebar(self.__ui.leftSidebar, toHideLeft) except AttributeError: # most likely the leftSidebar is not initialized, which can happen on windows sometimes pass UiHelper.hideItemsSidebar(self.__ui.bottomSidebar, toHideBottom) def __fixToolbars(self): self.__toolbars._fixedToolbars = True # ask future toolbars to be fixed for toolbar in self.__ui.findChildren(QToolBar): toolbar.setMovable(False) def __hideStatusBar(self): self.__ui.statusBar().hide() def __populateToolbarsMenu(self, menu): menu.clear() def __on_new_editor(self, editor): itemstoHide = [ "Autosave enabled", "Typing aids enabled", "Automatic Completion enabled", "Complete", "Calltip", "Check", "Show", "Diagrams", "Tools", "New Document View", "New Document View (with new split)", "Close", "Re-Open With Encoding", "Save", "Save As...", "Save Copy..." ] UiHelper.hideWidgetActions(editor.menu, itemstoHide) def __createPythonPopupMenus(self): itemsToRemove = [ "Run unittest...", "Diagrams", "Check", "Show", "Configure..." ] self.__oldCreatePythonPopupMenus() UiHelper.removeWidgetActions(self.__sourcesBrowser.sourceMenu, itemsToRemove) def __simplifyPreferences(self): toDeleteTxt = [ 'Shell', 'Tasks', 'Interface', 'Editor/Autocompletion', 'Editor/Calltips', 'Editor/Code Checkers', 'Editor/Exporters', 'Editor/Filehandling', 'Editor/Highlighters/Properties', 'Editor/Searching', 'Editor/Spell checking', 'Editor/Typing' ] FullUI.PreferencesDialog.SimplifyPreferences.toDeleteExtend( toDeleteTxt) def __showInitialTip(self): if Preferences.Prefs.settings.value("UI/AdvancedInterfaceTipShown", False) != "true": E5MessageBox.information( self.__ui, self.__ui.tr("Pymakr hint"), self.__ui. tr("<b>Hint</b><br><br>If you're an expert, you can always switch to the full interface by selecting<i>Settings > Switch to expert interface</i> in the main menu." )) Preferences.Prefs.settings.setValue("UI/AdvancedInterfaceTipShown", "true")
class MainWindow(QMainWindow): """This is the main application window class it defines the GUI window for the browser """ def parse_config(self, file_config, options): self.config = {} options = vars(options) for key, metadata in CONFIG_OPTIONS.items(): options_val = options.get(key) file_val = file_config.get(key) env_val = os.environ.get(metadata.get("env", '')) default_val = metadata.get("default") vals = metadata.get("values") debug("key: {}, default: {}, file: {}, options: {}".format( key, default_val, file_val, options_val )) if vals: options_val = (options_val in vals and options_val) or None file_val = (file_val in vals and file_val) or None env_val = (env_val in vals and env_val) or None if metadata.get("is_file"): filename = options_val or env_val if not filename: self.config[key] = default_val else: try: with open(filename, 'r') as fh: self.config[key] = fh.read() except IOError: debug("Could not open file {} for reading.".format( filename) ) self.config[key] = default_val else: set_values = [ val for val in (options_val, env_val, file_val) if val is not None ] if len(set_values) > 0: self.config[key] = set_values[0] else: self.config[key] = default_val if metadata.get("type") and self.config[key]: debug("{} cast to {}".format(key, metadata.get("type"))) self.config[key] = metadata.get("type")(self.config[key]) debug(repr(self.config)) def createAction(self, text, slot=None, shortcut=None, icon=None, tip=None, checkable=False, signal="triggered"): """Return a QAction given a number of common QAction attributes Just a shortcut function Originally 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(":/{}.png".format(icon)) )) if shortcut is not None and not shortcut.isEmpty(): action.setShortcut(shortcut) tip += " ({})".format(shortcut.toString()) if tip is not None: action.setToolTip(tip) action.setStatusTip(tip) if slot is not None: action.__getattr__(signal).connect(slot) if checkable: action.setCheckable() return action def __init__(self, options, parent=None): """Construct a MainWindow Object.""" super(MainWindow, self).__init__(parent) # Load config file self.setWindowTitle("Browser") debug("loading configuration from '{}'".format(options.config_file)) configfile = {} if options.config_file: configfile = yaml.safe_load(open(options.config_file, 'r')) self.parse_config(configfile, options) # self.popup will hold a reference to the popup window # if it gets opened self.popup = None # Stylesheet support if self.config.get("stylesheet"): try: with open(self.config.get("stylesheet")) as ss: self.setStyleSheet(ss.read()) except: debug( """Problem loading stylesheet file "{}", """ """using default style.""" .format(self.config.get("stylesheet")) ) self.setObjectName("global") # If the whitelist is activated, add the bookmarks and start_url if self.config.get("whitelist"): # we can just specify whitelist = True, # which should whitelist just the start_url and bookmark urls. whitelist = self.config.get("whitelist") if type(whitelist) is not list: whitelist = [] whitelist.append(str(QUrl( self.config.get("start_url") ).host())) bookmarks = self.config.get("bookmarks") if bookmarks: whitelist += [ str(QUrl(b.get("url")).host()) for k, b in bookmarks.items() ] self.config["whitelist"] = set(whitelist) # uniquify and optimize debug("Generated whitelist: " + str(whitelist)) # If diagnostic is enabled, connect CTRL+ALT+? to show some diagnistic info if (self.config.get("enable_diagnostic")): self.diagnostic_action = self.createAction( "Show Diagnostic", self.show_diagnostic, QKeySequence("Ctrl+Alt+/"), tip='' ) self.addAction(self.diagnostic_action) self.build_ui() # ## END OF CONSTRUCTOR ## # def build_ui(self): """Set up the user interface for the main window. Unlike the constructor, this method is re-run whenever the browser is "reset" by the user. """ debug("build_ui") inactivity_timeout = self.config.get("timeout") quit_button_tooltip = ( self.config.get("quit_button_mode") == 'close' and "Click here to quit the browser." or """Click here when you are done. It will clear your browsing history""" """ and return you to the start page.""") qb_mode_callbacks = {'close': self.close, 'reset': self.reset_browser} to_mode_callbacks = {'close': self.close, 'reset': self.reset_browser, 'screensaver': self.screensaver} self.screensaver_active = False # ##Start GUI configuration## # self.browser_window = WcgWebView(self.config) self.browser_window.setObjectName("web_content") if ( self.config.get("icon_theme") is not None and QT_VERSION_STR > '4.6' ): QIcon.setThemeName(self.config.get("icon_theme")) self.setCentralWidget(self.browser_window) debug("loading {}".format(self.config.get("start_url"))) self.browser_window.setUrl(QUrl(self.config.get("start_url"))) if self.config.get("fullscreen"): self.showFullScreen() elif ( self.config.get("window_size") and self.config.get("window_size").lower() == 'max' ): self.showMaximized() elif self.config.get("window_size"): size = re.match(r"(\d+)x(\d+)", self.config.get("window_size")) if size: width, height = size.groups() self.setFixedSize(int(width), int(height)) else: debug('Ignoring invalid window size "{}"'.format( self.config.get("window_size") )) # Set up the top navigation bar if it's configured to exist if self.config.get("navigation"): 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.config.get("quit_button_text"), qb_mode_callbacks.get(self.config.get("quit_button_mode"), self.reset_browser), QKeySequence("Alt+F"), None, 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.config.get("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.config.get("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 = [] for bookmark in self.config.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.event_filter.timeout.connect( to_mode_callbacks.get(self.config.get("timeout_mode"), self.reset_browser)) else: self.event_filter = None # ##END OF UI SETUP## # def screensaver(self): """Enter "screensaver" mode This method puts the browser in screensaver mode, where a URL is displayed while the browser is idle. Activity causes the browser to return to the home screen. """ debug("screensaver started") self.screensaver_active = True if self.popup: self.popup.close() if self.config.get("navigation"): self.navigation_bar.hide() self.browser_window.setZoomFactor(self.config.get("zoom_factor")) self.browser_window.load(QUrl(self.config.get("screensaver_url"))) self.event_filter.timeout.disconnect() self.event_filter.activity.connect(self.reset_browser) def reset_browser(self): """Clear the history and reset the UI. Called whenever the inactivity filter times out, or when the user clicks the "finished" button 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.event_filter.activity.disconnect() if self.event_filter: self.event_filter.blockSignals(False) if hasattr(self, "navigation_bar"): self.removeToolBar(self.navigation_bar) self.build_ui() def zoom_in(self): """Zoom in action callback. 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): """Zoom out action callback. 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 show_diagnostic(self): "Display a dialog box with some diagnostic info" data = { "OS": os.uname(), "USER": (os.environ.get("USER") or os.environ.get("USERNAME")), "Python": sys.version, "Qt": QT_VERSION_STR, "Script Date": ( datetime.datetime.fromtimestamp( os.stat(__file__).st_mtime).isoformat() ) } html = "\n".join([ "<h1>System Information</h1>", "<h2>Please click "", self.config.get("quit_button_text").replace("&", ''), "" when you are finished.</h2>", "<ul>", "\n".join([ "<li><b>{}</b>: {}</li>".format(k, v) for k, v in data.items() ]), "</ul>" ]) self.browser_window.setHtml(html)
class MainWindowUI(object): title = "Synspy Launcher" def __init__(self, MainWin): super(MainWindow).__init__() # Main Window MainWin.setObjectName("MainWindow") MainWin.setWindowTitle( MainWin.tr("%s %s" % (self.title, synspy_version))) MainWin.resize(800, 600) self.centralWidget = QWidget(MainWin) self.centralWidget.setObjectName("centralWidget") MainWin.setCentralWidget(self.centralWidget) self.verticalLayout = QVBoxLayout(self.centralWidget) self.verticalLayout.setContentsMargins(11, 11, 11, 11) self.verticalLayout.setSpacing(6) self.verticalLayout.setObjectName("verticalLayout") # Splitter for Worklist/Log self.splitter = QSplitter(Qt.Vertical) # Table View (Work list) self.workList = TableWidget(self.centralWidget) self.workList.setObjectName("tableWidget") self.workList.setStyleSheet(""" QTableWidget { border: 2px solid grey; border-radius: 5px; } """) self.workList.setEditTriggers( QAbstractItemView.NoEditTriggers ) # use NoEditTriggers to disable editing self.workList.setAlternatingRowColors(True) self.workList.setSelectionBehavior(QAbstractItemView.SelectRows) self.workList.setSelectionMode(QAbstractItemView.SingleSelection) self.workList.verticalHeader().setDefaultSectionSize( 18) # tighten up the row size self.workList.horizontalHeader().setStretchLastSection(True) # self.workList.horizontalHeader().setSectionResizeMode(QHeaderView.Stretch) self.workList.setSortingEnabled(True) # allow sorting self.workList.setContextMenuPolicy(Qt.ActionsContextMenu) self.workList.doubleClicked.connect(MainWin.on_actionLaunch_triggered) self.splitter.addWidget(self.workList) # Log Widget self.logTextBrowser = QPlainTextEditLogger(self.centralWidget) self.logTextBrowser.widget.setObjectName("logTextBrowser") self.logTextBrowser.widget.setStyleSheet(""" QPlainTextEdit { border: 2px solid grey; border-radius: 5px; background-color: lightgray; } """) self.splitter.addWidget(self.logTextBrowser.widget) # add splitter self.splitter.setSizes([600, 100]) self.verticalLayout.addWidget(self.splitter) # Actions # Launch self.actionLaunch = QAction(MainWin) self.actionLaunch.setObjectName("actionLaunch") self.actionLaunch.setText(MainWin.tr("Launch Analysis")) self.actionLaunch.setToolTip( MainWin.tr("Launch the synspy-viewer process")) self.actionLaunch.setShortcut(MainWin.tr("Ctrl+L")) # Refresh self.actionRefresh = QAction(MainWin) self.actionRefresh.setObjectName("actionRefresh") self.actionRefresh.setText(MainWin.tr("Refresh Work List")) self.actionRefresh.setToolTip(MainWin.tr("Refresh the work list")) self.actionRefresh.setShortcut(MainWin.tr("Ctrl+R")) # Options self.actionOptions = QAction(MainWin) self.actionOptions.setObjectName("actionOptions") self.actionOptions.setText(MainWin.tr("Options")) self.actionOptions.setToolTip(MainWin.tr("Configuration Options")) self.actionOptions.setShortcut(MainWin.tr("Ctrl+P")) # Login self.actionLogin = QAction(MainWin) self.actionLogin.setObjectName("actionLogin") self.actionLogin.setText(MainWin.tr("Login")) self.actionLogin.setToolTip(MainWin.tr("Login to the server")) self.actionLogin.setShortcut(MainWin.tr("Ctrl+G")) # Logout self.actionLogout = QAction(MainWin) self.actionLogout.setObjectName("actionLogout") self.actionLogout.setText(MainWin.tr("Logout")) self.actionLogout.setToolTip(MainWin.tr("Logout of the server")) self.actionLogout.setShortcut(MainWin.tr("Ctrl+O")) # Exit self.actionExit = QAction(MainWin) self.actionExit.setObjectName("actionExit") self.actionExit.setText(MainWin.tr("Exit")) self.actionExit.setToolTip(MainWin.tr("Exit the application")) self.actionExit.setShortcut(MainWin.tr("Ctrl+Z")) # Help self.actionHelp = QAction(MainWin) self.actionHelp.setObjectName("actionHelp") self.actionHelp.setText(MainWin.tr("Help")) self.actionHelp.setToolTip(MainWin.tr("Help")) self.actionHelp.setShortcut(MainWin.tr("Ctrl+H")) # Mark Incomplete self.markIncompleteAction = QAction('Mark Incomplete', self.workList) self.markIncompleteAction.triggered.connect(MainWin.markIncomplete) # Tool Bar self.mainToolBar = QToolBar(MainWin) self.mainToolBar.setObjectName("mainToolBar") self.mainToolBar.setToolButtonStyle(Qt.ToolButtonTextUnderIcon) MainWin.addToolBar(Qt.TopToolBarArea, self.mainToolBar) # Launch self.mainToolBar.addAction(self.actionLaunch) self.actionLaunch.setIcon(qApp.style().standardIcon( QStyle.SP_MediaPlay)) # Reload self.mainToolBar.addAction(self.actionRefresh) self.actionRefresh.setIcon(qApp.style().standardIcon( QStyle.SP_BrowserReload)) # Options self.mainToolBar.addAction(self.actionOptions) self.actionOptions.setIcon(qApp.style().standardIcon( QStyle.SP_FileDialogDetailedView)) # this spacer right justifies everything that comes after it spacer = QWidget() spacer.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding) self.mainToolBar.addWidget(spacer) # Login self.mainToolBar.addAction(self.actionLogin) self.actionLogin.setIcon(qApp.style().standardIcon( QStyle.SP_DialogApplyButton)) # Logout self.mainToolBar.addAction(self.actionLogout) self.actionLogout.setIcon(qApp.style().standardIcon( QStyle.SP_DialogOkButton)) # Help #self.mainToolBar.addAction(self.actionHelp) self.actionHelp.setIcon(qApp.style().standardIcon( QStyle.SP_MessageBoxQuestion)) # Exit self.mainToolBar.addAction(self.actionExit) self.actionExit.setIcon(qApp.style().standardIcon( QStyle.SP_DialogCancelButton)) # Status Bar self.statusBar = QStatusBar(MainWin) self.statusBar.setToolTip("") self.statusBar.setStatusTip("") self.statusBar.setObjectName("statusBar") MainWin.setStatusBar(self.statusBar) # finalize UI setup QMetaObject.connectSlotsByName(MainWin)
class ToolbarUI(object): def __init__(self, main_window: QMainWindow): """ 工具导航 外观模式 :param main_window: """ self.main_window = main_window self.toolbar = QToolBar(self.main_window) # 子类 self.ui_list = [] self.server_start_ui = ServerStartUI(self.toolbar) # 服务器开关 self.file_manager_ui = FileManagerUI(self.toolbar) # 文件管理 self.terminal_ui = TerminalUI(self.toolbar) # 远程终端 self.remote_control_ui = RemoteControlUI(self.toolbar) # 远程控制 self.video_monitor_ui = VideoMonitorUI(self.toolbar) # 视频监控 self.voice_monitor_ui = VoiceMonitorUI(self.toolbar) # 语音监控 self.keyboard_ui = KeyboardUI(self.toolbar) # 键盘记录 self.make_client_ui = MakeClientUI(self.toolbar) # 创建客户端 self.service_manager_ui = ServiceManagerUI(self.toolbar) # 服务管理 self.exit_ui = ExitUI(self.toolbar, self.main_window) # 退出程序 # 子类信号 self.connect_list = [] self.server_start_connect = ServerStartConnect(self.server_start_ui) def options(self) -> None: """ 参数设置 :return: """ self.toolbar.setObjectName("toolBar") # 设置是否可以移动 self.toolbar.setMovable(True) # 设置是否可以悬浮在主窗口 self.toolbar.setFloatable(True) # 设置图标尺寸 self.toolbar.setIconSize(QSize(25, 25)) # 字体在右边 # self.tools_main.setToolButtonStyle(Qt.ToolButtonTextBesideIcon) # 字体在下面 if settings.LOAD_EFFECT_ON: self.toolbar.setToolButtonStyle(Qt.ToolButtonTextUnderIcon) load_animation.load_animation(self.toolbar) # 窗口添加工具导航栏 self.main_window.addToolBar(Qt.TopToolBarArea, self.toolbar) def setup_ui(self) -> None: self.options() if not settings.TOOLBAR_SHOW: self.toolbar.hide() self.load_ui() self.load_connect() self.show_ui() # QDockWidget 位置发生变动 self.toolbar.orientationChanged.connect(self.orientation_changed) def orientation_changed(self, event) -> None: """ 位置变动事件 :param event: :return: """ if event: pass if settings.LOAD_EFFECT_ON: load_animation.load_animation(self.toolbar) # noinspection PyArgumentList def retranslate_ui(self) -> None: self.toolbar.setWindowTitle(_translate("ToolbarUI", "工具导航")) def load_ui(self) -> None: """ 加载模块 :return: """ self.ui_list.append(self.server_start_ui) self.ui_list.append(self.file_manager_ui) self.ui_list.append(self.terminal_ui) self.ui_list.append(self.remote_control_ui) self.ui_list.append(self.video_monitor_ui) self.ui_list.append(self.voice_monitor_ui) self.ui_list.append(self.keyboard_ui) self.ui_list.append(self.make_client_ui) self.ui_list.append(self.service_manager_ui) self.ui_list.append(self.exit_ui) def load_connect(self) -> None: """ 加载 链接信号 :return: """ self.connect_list.append(self.server_start_connect) def show_ui(self) -> None: """ 显示数据 :return: """ all_list = self.ui_list + self.connect_list for item in all_list: item.setup_ui() item.retranslate_ui()
class UMC(QMainWindow): def __init__(self): super().__init__() self.initUI() def initUI(self): #TODO: Move actions somewhere else? Seems like this could get cluttered quickly ### ACTIONS ### menuHelpAboutAct = QAction('&About UMC', self) menuHelpAboutAct.triggered.connect(self.showDialogAbout) menuFileExitAct = QAction('&Exit', self) #QIcon('img/icon.png'), menuFileExitAct.setShortcut('Ctrl+Q') menuFileExitAct.setStatusTip('Exit application') menuFileExitAct.triggered.connect(qApp.quit) menuViewThemeLightAct = QAction('Light', self, checkable=True) menuViewThemeLightAct.setChecked(True) menuViewThemeLightAct.triggered.connect(self.toggleTheme) menuViewThemeDarkAct = QAction('Dark', self, checkable=True) menuViewThemeDarkAct.triggered.connect(self.toggleTheme) tabMarketAct = QAction(QIcon('img/tab-bitcoin.png'), 'Loot', self) tabMarketAct.triggered.connect(self.switchAppTab) tabManualAct = QAction(QIcon('img/tab-muscle.png'), 'John Henry Mode', self) tabManualAct.triggered.connect(self.switchAppTab) tabNetworkAct = QAction(QIcon('img/tab-network.png'), 'Network', self) tabNetworkAct.triggered.connect(self.switchAppTab) tabOverviewAct = QAction(QIcon('img/tab-home.png'), 'Overview', self) tabOverviewAct.triggered.connect(self.switchAppTab) tabSettingsAct = QAction(QIcon('img/tab-settings.png'), 'Settings', self) tabSettingsAct.triggered.connect(self.switchAppTab) tabStatsAct = QAction(QIcon('img/tab-graph.png'), 'Statistics', self) tabStatsAct.triggered.connect(self.switchAppTab) tabStatusAct = QAction(QIcon('img/tab-status-ok.png'), 'Status', self) tabStatusAct.triggered.connect(self.switchAppTab) ### MENU BAR ### menubar = self.menuBar() fileMenu = menubar.addMenu('&File') fileMenu.addAction(menuFileExitAct) themesMenu = QMenu('Theme', self) ag = QActionGroup(self, exclusive=True) themesMenu.addAction(ag.addAction(menuViewThemeLightAct)) themesMenu.addAction(ag.addAction(menuViewThemeDarkAct)) viewMenu = menubar.addMenu('&View') viewMenu.addMenu(themesMenu) helpMenu = menubar.addMenu('&Help') helpMenu.addAction(menuHelpAboutAct) ### TOOLBAR ### toolbarFont = QFont('Helvetica', 10, QFont.Bold) self.toolbar = QToolBar(self) self.toolbar.setStyleSheet('QToolBar QToolButton,QToolBar QLabel { padding: 4; color: #555;}') self.toolbar.setIconSize(QSize(24, 24)) self.toolbar.setObjectName("toolBar") self.toolbar.setMovable( False ) self.addToolBar(Qt.ToolBarArea(Qt.TopToolBarArea), self.toolbar) self.toolbar.addAction(tabOverviewAct) self.toolbar.addAction(tabStatsAct) self.toolbar.addAction(tabNetworkAct) self.toolbar.addAction(tabMarketAct) self.toolbar.addAction(tabSettingsAct) self.toolbar.addSeparator() self.toolbar.addAction(tabManualAct) spacer = QWidget() spacer.setSizePolicy(QSizePolicy.Expanding,QSizePolicy.Expanding) self.toolbar.addWidget(spacer) self.btcLbl = QLabel("0.003007 BTC ($41.50 USD)/Day") self.btcLbl.setFont(toolbarFont) self.toolbar.addWidget(self.btcLbl) self.hashLbl = QLabel("2763.45 MH/s") self.hashLbl.setFont(toolbarFont) self.toolbar.addWidget(self.hashLbl) self.toolbar.addAction(tabStatusAct) ### BODY ### self.Stack = QStackedWidget (self) self.Stack.addWidget(UMCOverview(self)) self.Stack.addWidget(UMCStats(self)) self.Stack.addWidget(UMCNetwork(self)) self.Stack.addWidget(UMCLoot(self)) self.Stack.addWidget(UMCSettings(self)) self.Stack.addWidget(UMCManual(self)) self.setCentralWidget(self.Stack) ### MAIN WINDOW ### self.setWindowTitle('Univeral Mining Control') self.setStyleSheet("QMainWindow {background: '#FFF';}") self.setWindowIcon(QIcon('img/icon.png')) self.resize(800, 600) self.center() self.show() def center(self): qr = self.frameGeometry() cp = QDesktopWidget().availableGeometry().center() qr.moveCenter(cp) self.move(qr.topLeft()) # TODO this keypress is pretty handy for testing, probably needs to go away though def keyPressEvent(self, e): if e.key() == Qt.Key_Escape: self.close() def showDialogAbout(self): msgBox = QMessageBox() msgBox.setText("Look! I made this!") msgBox.setWindowIcon(QIcon('img/qmessagebox-info.png')) msgBox.setWindowTitle("About Universal Mining Control") msgBox.exec_() def switchAppTab(self): #TODO attach index to widget so the order can change without breaking things.. if self.sender().text() == "Overview": self.Stack.setCurrentIndex(0) elif self.sender().text() == "Statistics": self.Stack.setCurrentIndex(1) elif self.sender().text() == "Network": self.Stack.setCurrentIndex(2) elif self.sender().text() == "Loot": self.Stack.setCurrentIndex(3) elif self.sender().text() == "Settings": self.Stack.setCurrentIndex(4) elif self.sender().text() == "John Henry Mode": self.Stack.setCurrentIndex(5) def toggleTheme(self): # I know I know, this isn't pretty, just throwing some ideas around... if self.sender().text() == "Dark": self.setStyleSheet("QMainWindow {background: '#666';}") else: self.setStyleSheet("QMainWindow {background: '#FFF';}")
def __init__(self): super().__init__() # settings file self.settings = QSettings('martinopilia', 'wikied') # label for the permanent message in the status bar self.permanentMessage = QLabel('Disconnected') # window for the regex sandbox self.regexSandbox = RegexSandbox() # object for the connection to the site self.connection = Connection(self.settings) self.connection.statusMessage.connect(self.statusBar().showMessage) self.connection.permanentMessage.connect(self.permanentMessage.setText) # window for the account settings self.accountDialog = AccountDialog(self.settings) # add permanent widget to the status bar self.statusBar().addPermanentWidget(self.permanentMessage) # actions # quit exitAction = QAction( QIcon('icons/window-close'), 'Exit', self) exitAction.setStatusTip('Quit the application (Ctrl+Q)') exitAction.setShortcut('Ctrl+Q') exitAction.triggered.connect(self.close) # open RegexSandbox sandboxAction = QAction( QIcon('icons/code-context'), 'Regex sandbox', self) sandboxAction.setStatusTip( 'Open the regex test environment (Ctrl+Shif+S)') sandboxAction.setShortcut('Ctrl+Shift+S') sandboxAction.triggered.connect(self.regexSandbox.show) # connect connectAction = QAction( QIcon('icons/network-connect'), 'Connect', self) connectAction.setStatusTip('Connect to the project') connectAction.triggered.connect(self.connection.connect) # disconnect disconnectAction = QAction( QIcon('icons/network-disconnect'), 'Disconnect', self) disconnectAction.setStatusTip('Disconnect from the project') disconnectAction.triggered.connect(self.connection.disconnect) # set account setAccountAction = QAction( QIcon('icons/user-identity'), 'Set account', self) setAccountAction.setStatusTip('Manage the account settings') setAccountAction.triggered.connect(self.accountDialog.exec_) # central widget and docks diff = Diff() diff.setObjectName('Diff') diff.setVisible(False) self.addDockWidget(Qt.TopDockWidgetArea, diff) editorWidget = VoiceEditor(self.connection, diff) self.setCentralWidget(editorWidget) substWidget = FindAndReplace(editorWidget.pageContent) substWidget.setObjectName('Find and replace') substWidget.statusMessage.connect(self.statusBar().showMessage) self.addDockWidget(Qt.BottomDockWidgetArea, substWidget) voiceSelector = VoiceSelector(self.connection, editorWidget) voiceSelector.setObjectName('Select voices') voiceSelector.statusMessage.connect(self.statusBar().showMessage) self.addDockWidget(Qt.LeftDockWidgetArea, voiceSelector) # toolbars # Connection connectionToolbar = QToolBar('Connection') connectionToolbar.setObjectName('connectionToolbar') connectionToolbar.addActions( [connectAction, disconnectAction, setAccountAction]) self.addToolBar(connectionToolbar) # menu bar # File fileMenu = self.menuBar().addMenu('File') fileMenu.addAction(connectAction) fileMenu.addAction(disconnectAction) fileMenu.addAction(setAccountAction) fileMenu.addSeparator() fileMenu.addAction(exitAction) # Tools toolsMenu = self.menuBar().addMenu('Tools') toolsMenu.addAction(sandboxAction) # View viewMenu = self.menuBar().addMenu('View') viewMenu.addAction(voiceSelector.toggleViewAction()) viewMenu.addAction(substWidget.toggleViewAction()) viewMenu.addAction(connectionToolbar.toggleViewAction()) viewMenu.addAction(editorWidget.actionsToolbar.toggleViewAction()) viewMenu.addAction(diff.toggleViewAction()) viewMenu.addAction(editorWidget.editToolbar.toggleViewAction()) # view details self.setGeometry(200, 200, 1000, 800) self.setWindowTitle('WikiEd') self.setWindowIcon(QIcon('')) editorWidget.pageContent.setFocus() # restore state and geometry (lazy initialization) if (not self.settings.value('window/geometry') or not self.settings.value('window/state')): self.saveWindow() self.restoreGeometry(self.settings.value('window/geometry')) self.restoreState(self.settings.value('window/state')) self.show()
class AuthWindowUI(object): def __init__(self, MainWin): # Main Window MainWin.setObjectName("AuthWindow") MainWin.setWindowIcon(MainWin.window_icon) MainWin.setWindowTitle(MainWin.tr(MainWin.window_title)) MainWin.resize(1024, 860) self.config = MainWin.config self.centralWidget = QWidget(MainWin) self.centralWidget.setObjectName("centralWidget") MainWin.setCentralWidget(self.centralWidget) self.verticalLayout = QVBoxLayout(self.centralWidget) self.verticalLayout.setContentsMargins(11, 11, 11, 11) self.verticalLayout.setSpacing(6) self.verticalLayout.setObjectName("verticalLayout") self.tabWidget = QTabWidget(MainWin) self.tabWidget.currentChanged.connect(MainWin.onTabChanged) self.tabWidget.tabCloseRequested.connect(MainWin.onTabClosed) self.tabWidget.setTabsClosable(True) # workaround for https://bugreports.qt.io/browse/QTBUG-58267 if "darwin" in sys.platform: self.tabWidget.setDocumentMode(True) # Splitter for log self.splitter = QSplitter(Qt.Vertical) self.splitter.addWidget(self.tabWidget) # Log Widget self.logTextBrowser = QPlainTextEditLogger(self.centralWidget) self.logTextBrowser.widget.setObjectName("logTextBrowser") self.logTextBrowser.widget.setStyleSheet(""" QPlainTextEdit { border: 2px solid grey; border-radius: 5px; background-color: lightgray; } """) self.splitter.addWidget(self.logTextBrowser.widget) # add splitter self.splitter.setSizes([800, 100]) self.verticalLayout.addWidget(self.splitter) # Tool Bar self.mainToolBar = QToolBar(MainWin) self.mainToolBar.setObjectName("mainToolBar") self.mainToolBar.setToolButtonStyle(Qt.ToolButtonTextUnderIcon) self.mainToolBar.setContextMenuPolicy(Qt.PreventContextMenu) MainWin.addToolBar(Qt.TopToolBarArea, self.mainToolBar) # Servers self.serverWidget = QWidget(MainWin) self.serverLayout = QHBoxLayout() self.serverLabel = QLabel("Server:") self.serverLayout.addWidget(self.serverLabel) self.serverComboBox = QComboBox() self.serverComboBox.setEditable(True) self.serverComboBox.setDuplicatesEnabled(False) self.serverComboBox.setMinimumContentsLength(50) self.serverComboBox.currentIndexChanged.connect( MainWin.onServerListChanged) lineEdit = self.serverComboBox.lineEdit() lineEdit.returnPressed.connect(MainWin.on_actionAdd_triggered) self.serverLayout.addWidget(self.serverComboBox) self.serverWidget.setLayout(self.serverLayout) self.mainToolBar.addWidget(self.serverWidget) # Add self.actionAdd = QAction(MainWin) self.actionAdd.setObjectName("actionAdd") self.actionAdd.setText(MainWin.tr("Add")) self.actionAdd.setToolTip(MainWin.tr("Add to server list")) self.actionAdd.setShortcut(MainWin.tr("Ctrl+A")) # Remove self.actionRemove = QAction(MainWin) self.actionRemove.setObjectName("actionRemove") self.actionRemove.setText(MainWin.tr("Remove")) self.actionRemove.setToolTip(MainWin.tr("Remove from server list")) self.actionRemove.setShortcut(MainWin.tr("Ctrl+X")) # Show Token self.actionShowToken = QAction(MainWin) self.actionShowToken.setEnabled(False) self.actionShowToken.setObjectName("actionShowToken") self.actionShowToken.setText(MainWin.tr("Show Token")) self.actionShowToken.setToolTip( MainWin.tr("Display the current authentication token")) self.actionShowToken.setShortcut(MainWin.tr("Ctrl+S")) # Login self.actionLogin = QAction(MainWin) self.actionLogin.setObjectName("actionLogin") self.actionLogin.setText(MainWin.tr("Login")) self.actionLogin.setToolTip( MainWin.tr("Login to the currently selected server")) self.actionLogin.setShortcut(MainWin.tr("Ctrl+L")) # Logout self.actionLogout = QAction(MainWin) self.actionLogout.setObjectName("actionLogout") self.actionLogout.setText(MainWin.tr("Logout")) self.actionLogout.setToolTip( MainWin.tr("Logout of the currently selected server")) self.actionLogout.setShortcut(MainWin.tr("Ctrl+O")) # Add self.mainToolBar.addAction(self.actionAdd) self.actionAdd.setIcon(qApp.style().standardIcon( QStyle.SP_FileDialogNewFolder)) # Remove self.mainToolBar.addAction(self.actionRemove) self.actionRemove.setIcon(qApp.style().standardIcon( QStyle.SP_DialogDiscardButton)) # Show Token self.mainToolBar.addAction(self.actionShowToken) self.actionShowToken.setIcon(qApp.style().standardIcon( QStyle.SP_FileDialogInfoView)) self.mainToolBar.addSeparator() # this spacer right justifies everything that comes after it spacer = QWidget() spacer.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding) self.mainToolBar.addWidget(spacer) # Login self.mainToolBar.addSeparator() self.mainToolBar.addAction(self.actionLogin) self.actionLogin.setIcon(qApp.style().standardIcon( QStyle.SP_DialogApplyButton)) # Logout self.mainToolBar.addSeparator() self.mainToolBar.addAction(self.actionLogout) self.actionLogout.setIcon(qApp.style().standardIcon( QStyle.SP_DialogOkButton)) # Status Bar self.statusBar = QStatusBar(MainWin) self.statusBar.setToolTip("") self.statusBar.setStatusTip("") self.statusBar.setObjectName("statusBar") MainWin.setStatusBar(self.statusBar) # configure logging self.logTextBrowser.widget.log_update_signal.connect(MainWin.updateLog) self.logTextBrowser.setFormatter( logging.Formatter("%(asctime)s - %(levelname)s - %(message)s")) logging.getLogger().addHandler(self.logTextBrowser) logging.getLogger().setLevel(logging.INFO) # finalize UI setup QMetaObject.connectSlotsByName(MainWin)
class UIController(object): def __init__(self): self.mainWidget = scripterdialog.ScripterDialog(self) self.actionToolbar = QToolBar('toolBar', self.mainWidget) self.menu_bar = QMenuBar(self.mainWidget) self.actionToolbar.setObjectName('toolBar') self.menu_bar.setObjectName('menuBar') self.actions = [] self.mainWidget.setWindowModality(Qt.NonModal) def initialize(self, scripter): self.editor = pythoneditor.CodeEditor(scripter) self.tabWidget = QTabWidget() self.statusBar = QLabel('untitled') self.splitter = QSplitter() self.splitter.setOrientation(Qt.Vertical) self.highlight = syntax.PythonHighlighter( self.editor.document(), syntaxstyles.DefaultSyntaxStyle()) self.scripter = scripter self.loadMenus() self.loadWidgets() self.loadActions() self._readSettings() vbox = QVBoxLayout(self.mainWidget) vbox.addWidget(self.menu_bar) vbox.addWidget(self.actionToolbar) self.splitter.addWidget(self.editor) self.splitter.addWidget(self.tabWidget) vbox.addWidget(self.splitter) vbox.addWidget(self.statusBar) self.mainWidget.resize(400, 500) self.mainWidget.setWindowTitle("Scripter") self.mainWidget.setSizeGripEnabled(True) self.mainWidget.show() self.mainWidget.activateWindow() def loadMenus(self): self.addMenu('File', 'File') def addMenu(self, menuName, parentName): parent = self.menu_bar.findChild(QObject, parentName) self.newMenu = None if parent: self.newMenu = parent.addMenu(menuName) else: self.newMenu = self.menu_bar.addMenu(menuName) self.newMenu.setObjectName(menuName) return self.newMenu def loadActions(self): module_path = 'scripter.ui_scripter.actions' actions_module = importlib.import_module(module_path) modules = [] for class_path in actions_module.action_classes: _module, _klass = class_path.rsplit('.', maxsplit=1) modules.append( dict(module='{0}.{1}'.format(module_path, _module), klass=_klass)) for module in modules: m = importlib.import_module(module['module']) action_class = getattr(m, module['klass']) obj = action_class(self.scripter) parent = self.mainWidget.findChild(QObject, obj.parent) self.actions.append(dict(action=obj, parent=parent)) for action in self.actions: action['parent'].addAction(action['action']) def loadWidgets(self): modulePath = 'scripter.ui_scripter.tabwidgets' widgetsModule = importlib.import_module(modulePath) modules = [] for classPath in widgetsModule.widgetClasses: _module, _klass = classPath.rsplit('.', maxsplit=1) modules.append( dict(module='{0}.{1}'.format(modulePath, _module), klass=_klass)) for module in modules: m = importlib.import_module(module['module']) widgetClass = getattr(m, module['klass']) obj = widgetClass(self.scripter) self.tabWidget.addTab(obj, obj.objectName()) def invokeAction(self, actionName): for action in self.actions: if action['action'].objectName() == actionName: method = getattr(action['action'], actionName) if method: return method() def findTabWidget(self, widgetName, childName=''): for index in range(self.tabWidget.count()): widget = self.tabWidget.widget(index) if widget.objectName() == widgetName: if childName: widget = widget.findChild(QObject, childName) return widget def showException(self, exception): QMessageBox.critical(self.editor, "Error running script", str(exception)) def setDocumentEditor(self, document): self.editor.clear() self.editor.moveCursor(QTextCursor.Start) self.editor.insertPlainText(document.data) self.editor.moveCursor(QTextCursor.End) def setStatusBar(self, value='untitled'): self.statusBar.setText(value) def setActiveWidget(self, widgetName): widget = self.findTabWidget(widgetName) if widget: self.tabWidget.setCurrentWidget(widget) def setStepped(self, status): self.editor.setStepped(status) def clearEditor(self): self.editor.clear() def repaintDebugArea(self): self.editor.repaintDebugArea() def closeScripter(self): self.mainWidget.close() def _writeSettings(self): """ _writeSettings is a method invoked when the scripter starts, making control inversion. Actions can implement a writeSettings method to save your own settings without this method to know about it. """ self.scripter.settings.beginGroup('scripter') document = self.scripter.documentcontroller.activeDocument if document: self.scripter.settings.setValue('activeDocumentPath', document.filePath) for action in self.actions: writeSettings = getattr(action['action'], "writeSettings", None) if callable(writeSettings): writeSettings() self.scripter.settings.endGroup() def _readSettings(self): """ It's similar to _writeSettings, but reading the settings when the ScripterDialog is closed. """ self.scripter.settings.beginGroup('scripter') activeDocumentPath = self.scripter.settings.value( 'activeDocumentPath', '') if activeDocumentPath: document = self.scripter.documentcontroller.openDocument( activeDocumentPath) self.setStatusBar(document.filePath) self.setDocumentEditor(document) for action in self.actions: readSettings = getattr(action['action'], "readSettings", None) if callable(readSettings): readSettings() self.scripter.settings.endGroup() def _saveSettings(self): self.scripter.settings.sync()
class _ToolsDock(QWidget): """Former Miscellaneous, contains all the widgets in the bottom area.""" findStarted = pyqtSignal() splitEditor = pyqtSignal(QWidget, QWidget, bool) closeSplit = pyqtSignal(QWidget) def __init__(self, parent=None): super(_ToolsDock, self).__init__(parent) #Register signals connections connections = ( {'target': 'main_container', 'signal_name': "findOcurrences",#(QString) 'slot': self.show_find_occurrences}, {'target': 'main_container', 'signal_name': "runFile",#(QString) 'slot': self.execute_file}, ) IDE.register_signals('tools_dock', connections) IDE.register_service("tools_dock", self) def setup_ui(self): """Load all the components of the ui during the install process.""" vbox = QVBoxLayout(self) vbox.setContentsMargins(0, 0, 0, 0) vbox.setSpacing(0) self.__toolbar = QToolBar() self.__toolbar.setObjectName('custom') hbox = QHBoxLayout() vbox.addLayout(hbox) self.stack = StackedWidget() vbox.addWidget(self.stack) self._console = console_widget.ConsoleWidget() self._runWidget = run_widget.RunWidget() self._web = web_render.WebRender() self._findInFilesWidget = find_in_files.FindInFilesWidget( self.parent()) # Not Configurable Shortcuts shortEscMisc = QShortcut(QKeySequence(Qt.Key_Escape), self) shortEscMisc.activated.connect(self.hide) #Toolbar hbox.addWidget(self.__toolbar) self.add_to_stack(self._console, ":img/console", translations.TR_CONSOLE) self.add_to_stack(self._runWidget, ":img/play", translations.TR_OUTPUT) self.add_to_stack(self._web, ":img/web", translations.TR_WEB_PREVIEW) self.add_to_stack(self._findInFilesWidget, ":img/find", translations.TR_FIND_IN_FILES) #Last Element in the Stacked widget self._results = results.Results(self) self.stack.addWidget(self._results) self.__toolbar.addSeparator() hbox.addSpacerItem(QSpacerItem(1, 0, QSizePolicy.Expanding)) btn_close = QPushButton( self.style().standardIcon(QStyle.SP_DialogCloseButton), '') btn_close.setIconSize(QSize(24, 24)) btn_close.setObjectName('navigation_button') btn_close.setToolTip('F4: ' + translations.TR_ALL_VISIBILITY) hbox.addWidget(btn_close) btn_close.clicked['bool'].connect(self.hide) def install(self): """Install triggered by the ide.""" self.setup_ui() ninjaide = IDE.getInstance() ninjaide.place_me_on("tools_dock", self, "central") ui_tools.install_shortcuts(self, actions.ACTIONS, ninjaide) ninjaide.goingDown.connect(self.save_configuration) qsettings = IDE.ninja_settings() value = qsettings.value("tools_dock/visible", True, type=bool) self.setVisible(value) print("\ninstall") def save_configuration(self): qsettings = IDE.ninja_settings() qsettings.setValue("tools_dock/visible", self.isVisible()) def change_visibility(self): """Change tools dock visibility.""" print("change_visibility22",self.isVisible()) if self.isVisible(): self.hide() else: self.show() def add_project_to_console(self, projectFolder): """Add the namespace of the project received into the ninja-console.""" self._console.load_project_into_console(projectFolder) def remove_project_from_console(self, projectFolder): """Remove the namespace of the project received from the console.""" self._console.unload_project_from_console(projectFolder) def _item_changed(self, val): """Change the current item.""" print("_item_changed", val) if not self.isVisible(): self.show() self.stack.show_display(val) def show_find_in_files_widget(self): """Show the Find In Files widget.""" index_of = self.stack.indexOf(self._findInFilesWidget) self._item_changed(index_of) self._findInFilesWidget.open() self._findInFilesWidget.setFocus() def show_find_occurrences(self, word): """Show Find In Files widget in find occurrences mode.""" index_of = self.stack.indexOf(self._findInFilesWidget) self._item_changed(index_of) self._findInFilesWidget.find_occurrences(word) self._findInFilesWidget.setFocus() def execute_file(self): """Execute the current file.""" main_container = IDE.get_service('main_container') if not main_container: return editorWidget = main_container.get_current_editor() if editorWidget: #emit a signal for plugin! self.fileExecuted.emit(editorWidget.file_path) main_container.save_file(editorWidget) ext = file_manager.get_file_extension(editorWidget.file_path) #TODO: Remove the IF statment and use Handlers if ext == 'py': self._run_application(editorWidget.file_path) elif ext == 'html': self.render_web_page(editorWidget.file_path) def execute_project(self): """Execute the project marked as Main Project.""" projects_explorer = IDE.get_service('projects_explorer') if projects_explorer is None: return nproject = projects_explorer.current_project if nproject: main_file = nproject.main_file if not main_file and projects_explorer.current_tree: projects_explorer.current_tree.open_project_properties() elif main_file: projects_explorer.save_project() #emit a signal for plugin! self.projectExecuted.emit(nproject.path) main_file = file_manager.create_path(nproject.path, nproject.main_file) self._run_application( main_file, pythonExec=nproject.python_exec_command, PYTHONPATH=nproject.python_path, programParams=nproject.program_params, preExec=nproject.pre_exec_script, postExec=nproject.post_exec_script) else: QMessageBox.information(self, translations.TR_INFO_TITLE_PROJECT_PROPERTIES, translations.TR_INFO_MESSAGE_PROJECT_PROPERTIES) def _run_application(self, fileName, pythonExec=False, PYTHONPATH=None, programParams='', preExec='', postExec=''): """Execute the process to run the application.""" self._item_changed(1) self.show() self._runWidget.start_process(fileName, pythonExec, PYTHONPATH, programParams, preExec, postExec) self._runWidget.input.setFocus() def show_results(self, items): """Show Results of Navigate to for several occurrences.""" index_of = self.stack.indexOf(self._results) self._item_changed(index_of) self.show() self._results.update_result(items) self._results._tree.setFocus() self._results.setFocus() def kill_application(self): """Kill the process of the application being executed.""" self._runWidget.kill_process() def render_web_page(self, url): """Render a webpage from the url path.""" index_of = self.stack.indexOf(self._web) self._item_changed(index_of) self.show() self._web.render_page(url) if settings.SHOW_WEB_INSPECTOR: web_inspector = IDE.get_service('web_inspector') if web_inspector: web_inspector.set_inspection_page(self._web.webFrame.page()) self._web.webFrame.triggerPageAction( QWebPage.InspectElement, True) web_inspector.refresh_inspector() self._web.setFocus() def add_to_stack(self, widget, icon_path, description): """ Add a widget to the container and an button(with icon))to the toolbar to show the widget """ #add the widget self.stack.addWidget(widget) #create a button in the toolbar to show the widget button = QPushButton(QIcon(icon_path), '') button.setIconSize(QSize(16, 16)) button.setToolTip(description) index = self.stack.count() - 1 button.clicked['bool'].connect(lambda s, i=index: self._item_changed(i)) self.__toolbar.addWidget(button) def showEvent(self, event): super(_ToolsDock, self).showEvent(event) widget = self.stack.currentWidget() if widget: widget.setFocus()