class CalculateVolumeWidget(QWidget): def __init__(self, parent): super(QWidget, self).__init__(parent) self.layout = QVBoxLayout(self) self.parent = parent # Array of indices of tabs with plots (for making updates when switching to them) self.tabsWithPlots = [0,1] # Initialize tab screen self.tabs = QTabWidget() self.tab1 = DiskMethodWidget(self) self.tab2 = DefiniteIntegralWidget(self) # Add tabs self.tabs.addTab(self.tab1,"Método de discos") self.tabs.addTab(self.tab2,"Integral definida") # Function whenever a new tab is clicked self.tabs.currentChanged.connect(self.updatePlot) # Add tabs to widget self.layout.addWidget(self.tabs) self.setLayout(self.layout) # Update plot subtab def updatePlot(self): if(self.tabs.currentIndex() in self.tabsWithPlots): self.tabs.currentWidget().updatePlot()
class Window(QMainWindow): def __init__(self): super(Window, self).__init__(flags=Qt.Window) self.index_page = 0 self.valid_players = player_store.players self.setWindowTitle("Business FUT") self.setWindowIcon(QIcon("img/fut_icon.ico")) self.tab_widgets = QTabWidget() self.tab_widgets.setStyleSheet(QTabWidget_stylesheet) self.tab_widgets.blockSignals(True) self.tab_widgets.currentChanged.connect(self.on_tab_changed) self.buy_tab = BuyTab() self.favorite_tab = FavoriteTab() self.sell_tab = SellTab() self.tab_widgets.addTab(self.buy_tab, "Achats") self.tab_widgets.addTab(self.favorite_tab, "Favoris") self.tab_widgets.addTab(self.sell_tab, "Ventes") self.setCentralWidget(self.tab_widgets) self.tab_widgets.blockSignals(False) def on_tab_changed(self): self.tab_widgets.currentWidget().update_table() def keyPressEvent(self, e): if type(e) == QKeyEvent and e.key() == Qt.Key_F1: c.ech += 1 if c.ech > 3: c.ech = 1 from model.database import Database db = Database() db.update_constant(c.ech) self.close()
class QualifyingParams(QWidget): def __init__(self, parent=None): super().__init__(parent) self.vbox = QVBoxLayout(self) self.modetab = QTabWidget() self.vbox.addWidget(self.modetab) self.complaps = CompLaps() self.modetab.addTab(self.complaps, self.tr('Laps')) self.comptime = CompTime() self.modetab.addTab(self.comptime, self.tr('Time')) self.sequential = QCheckBox() self.sequential.setText(self.tr('Sequential')) self.vbox.addWidget(self.sequential) self.setLayout(self.vbox) def getCompMode(self): if self.modetab.currentWidget() == self.complaps: if self.sequential.isChecked(): return COMP_MODE__QUALIFYING_LAPS_SEQ return COMP_MODE__QUALIFYING_LAPS if self.modetab.currentWidget() == self.comptime: if self.sequential.isChecked(): return COMP_MODE__QUALIFYING_TIME_SEQ return COMP_MODE__QUALIFYING_TIME def getDuration(self): if self.modetab.currentWidget() == self.complaps: return self.complaps.duration.value() if self.modetab.currentWidget() == self.comptime: return self.comptime.duration.value()
class ViewSourceDialogTabber(QMainWindow): def __init__(self, parent=None, title="Source"): super(ViewSourceDialogTabber, self).__init__(parent) self.setWindowTitle(title) self.tabs = QTabWidget(self) self.tabs.setElideMode(Qt.ElideRight) self.tabs.setTabsClosable(True) self.tabs.tabCloseRequested.connect(self.removeTab) self.setCentralWidget(self.tabs) self.tabs.currentChanged.connect(self.updateWindowTitle) def sizeHint(self): return QSize(640, 480) def removeTab(self): self.tabs.removeTab(self.tabs.currentIndex()) def addTab(self, title="New Tab", data=""): vsd = ViewSourceDialog(self, str(title)) vsd.setPlainText(data) self.tabs.addTab(vsd, tr("Source of %s") % (title,)) self.tabs.setCurrentIndex(self.tabs.count()-1) self.raise_() self.activateWindow() def updateWindowTitle(self): try: self.setWindowTitle(tr("Source of %s") % (self.tabs.currentWidget().windowTitle(),)) except: pass if self.tabs.count() == 0: self.hide()
class ViewSourceDialogTabber(QMainWindow): def __init__(self, parent=None, title="Source"): super(ViewSourceDialogTabber, self).__init__(parent) self.setWindowTitle(title) self.tabs = QTabWidget(self) self.tabs.setElideMode(Qt.ElideRight) self.tabs.setTabsClosable(True) self.tabs.tabCloseRequested.connect(self.removeTab) self.setCentralWidget(self.tabs) self.tabs.currentChanged.connect(self.updateWindowTitle) def sizeHint(self): return QSize(640, 480) def removeTab(self): self.tabs.removeTab(self.tabs.currentIndex()) def addTab(self, title="New Tab", data=""): vsd = ViewSourceDialog(self, str(title)) vsd.setPlainText(data) self.tabs.addTab(vsd, tr("Source of %s") % (title, )) self.tabs.setCurrentIndex(self.tabs.count() - 1) self.raise_() self.activateWindow() def updateWindowTitle(self): try: self.setWindowTitle( tr("Source of %s") % (self.tabs.currentWidget().windowTitle(), )) except: pass if self.tabs.count() == 0: self.hide()
def main(): app = QApplication(sys.argv) QApplication.setStyle(QStyleFactory.create('Fusion')) technics_tab = technics.Widget() departments_tab = departments.Widget() rooms_tab = rooms.Widget() employees_tab = employees.Widget() transfers_tab = transfers.Widget() technicsView_tab = technicsView.Widget() roomsView_tab = roomsView.Widget() responsibleView_tab = responsibleView.Widget() tabs = QTabWidget() tabs.addTab(technics_tab, 'Technics') tabs.addTab(departments_tab, 'Departments') tabs.addTab(rooms_tab, 'Rooms') tabs.addTab(employees_tab, 'Employees') tabs.addTab(transfers_tab, 'Transers') tabs.addTab(technicsView_tab, 'Technics View') tabs.addTab(roomsView_tab, 'Rooms View') tabs.addTab(responsibleView_tab, 'Responsible View') tabs.setFixedWidth(750) tabs.setFixedHeight(600) tabs.setWindowTitle('Office Equipment') tabs.show() tabs.currentChanged.connect(lambda x: tabs.currentWidget().refresh()) sys.exit(app.exec_())
class Window(QMainWindow): def __init__(self, dataManager, parent=None): super(Window, self).__init__(parent) self.setWindowTitle("python-aptly GUI") main_widget = QWidget(self) layout = QGridLayout() self.tabs = QTabWidget() self.tabs.addTab(SnapshotTab(dataManager), "Snapshot management") self.tabs.addTab(RepositoryTab(dataManager), "Repository management") self.tabs.addTab(PackagePromotion(dataManager), "Package Promotion") self.tabs.addTab(ComponentPromotion(dataManager), "Component Promotion") main_widget.setLayout(layout) layout.addWidget(self.tabs) self.tabs.currentChanged.connect(self.foo) self.setCentralWidget(main_widget) menubar = QMenuBar() menubar.addMenu('shit') menubar.addMenu('shit2') def foo(self, item): t = self.tabs.currentWidget() t.reload_component()
class MainWidget(QWidget): def __init__( self, parent, ): super(QWidget, self).__init__(parent) self.layout = QVBoxLayout(self) self.ini = QSettings(SETTINGS_PATH, QSettings.IniFormat) self.ini.setIniCodec("utf-8") # tabs for application self.tabs = QTabWidget() self.mainTab = ConnectionPanel(settings=SETTINGS_PATH) self.serversTab = ServersTable(settings=SETTINGS_PATH) self.tabs.resize(300, 200) # Add tabs self.tabs.addTab(self.mainTab, "Main") self.tabs.addTab(self.serversTab, "Servers") self.tabs.currentChanged.connect(self.tab_changed) self.layout.addWidget(self.tabs) self.setLayout(self.layout) def tab_changed(self): if self.tabs.currentWidget() == self.mainTab: if self.serversTab.save_settings_change_tab() == "Value Error": self.tabs.setCurrentIndex(2) self.mainTab.reload_servers()
class SearchMusic(ScrollArea): def __init__(self, parent=None): super().__init__(self) self.parent = parent self.setObjectName("SearchMusic") self.searchText = "" self.frame.setContentsMargins(0, 0, 0, 0) self.tabWidget = QTabWidget() self.tabWidget.setObjectName("tabWidget") self.mainLayout = QVBoxLayout() # self.mainLayout.setSpacing(0) self.mainLayout.setContentsMargins(0, 0, 0, 0) self.titleLabel = QLabel() self.mainLayout.addWidget(self.titleLabel) self.mainLayout.addWidget(self.tabWidget) self.frame.setLayout(self.mainLayout) self.addSearchMusicTabs() self.tabWidget.currentChanged.connect(self.tabChanged) def addSearchMusicTabs(self): tab = SearchMusicNetEase(self.parent) self.addTab(tab, "网易云") tab = SearchMusicQQ(self.parent) self.addTab(tab, "QQ") def addTab(self, widget, name=''): self.tabWidget.addTab(widget, name) def search(self, text): self.searchText = text self.titleLabel.setText( "搜索<font color='#23518F'>“{0}”</font><br>".format(self.searchText)) tab = self.tabWidget.currentWidget() tab.search(self.searchText) def tabChanged(self, index): if self.searchText: tab = self.tabWidget.currentWidget() if self.searchText != tab.searchText: tab.search(self.searchText)
class PreferencesDialog(QDialog): """ This dialog adjusts preferences """ def __init__(self, *args, **kwargs): super(PreferencesDialog, self).__init__(*args, **kwargs) self.appctx = self.parent().appctx # Setup UI self.setup_ui() def setup_ui(self): # TODO: Add preferences settings self.setWindowTitle(f"CLARITE Preferences") self.setMinimumWidth(500) self.setModal(True) layout = QVBoxLayout() # Tabs self.tabs = QTabWidget(self) self.tabs.setTabPosition(QTabWidget.North) self.tab_display = DisplayTab(self) self.tabs.addTab(self.tab_display, "Display") layout.addWidget(self.tabs) # Bottom row of buttons bottom_layout = QHBoxLayout() layout.addLayout(bottom_layout) # Reset self.default_btn = QPushButton("Default") self.default_btn.clicked.connect(self.use_default_settings) bottom_layout.addWidget(self.default_btn) # Spacer bottom_layout.addStretch() # Ok/Cancel QBtn = QDialogButtonBox.Ok | QDialogButtonBox.Cancel self.buttonBox = QDialogButtonBox(QBtn) bottom_layout.addWidget(self.buttonBox) self.buttonBox.accepted.connect(self.submit) self.buttonBox.rejected.connect(self.reject) # Set Layout self.setLayout(layout) def submit(self): # Write settings from each tab self.tab_display.write_settings() # Refresh the display self.appctx.data_model.refresh() # Close the dialog self.accept() def use_default_settings(self): # Reset the current tab to default settings w = self.tabs.currentWidget() w.load_default_settings() w.refresh_ui()
class SesionTab(QWidget): def __init__(self, conn, confName, holder=None, parent=None): super(SesionTab, self).__init__(parent) self.conn = conn self.confName = confName self.holder = holder self.tabQueries = QTabWidget() self.tabQueries.setTabShape(QTabWidget.Triangular) meatLayout = QVBoxLayout() meatLayout.addWidget(self.tabQueries) self.setLayout(meatLayout) self.addQuery() def addQuery(self): #self.tabQueries.addTab(QueryTab(self.conn,self.confName,holder=self.holder),"{}:{}".format(self.confName, self.tabQueries.count() +1)) self.tabQueries.addTab( myQueryTab(self.conn, holder=self.holder), "{}:{}".format(self.confName, self.tabQueries.count() + 1)) self.tabQueries.setCurrentIndex(self.tabQueries.count() - 1) def openQuery(self): #self.tabQueries.addTab(QueryTab(self.conn,self.confName,holder=self.holder),"{}:{}".format(self.confName, #self.tabQueries.count() +1)) #self.tabQueries.setCurrentIndex(self.tabQueries.count() -1) self.tabQueries.currentWidget().readQuery() def saveQuery(self): self.tabQueries.currentWidget().writeQuery() def saveAsQuery(self): self.tabQueries.currentWidget().writeQuery(True) def closeQuery(self): tabId = self.tabQueries.currentIndex() self.tabQueries.removeTab(tabId) def execute(self): self.tabQueries.currentWidget().execute() def reformat(self): self.tabQueries.currentWidget().reformat()
class solar_spectrum_gen_window(QWidget): update = pyqtSignal() def __init__(self): self.export_file_name="data.dat"#os.path.join(self.path,"spectra.inp") super().__init__() self.resize(1200,600) self.setWindowIcon(icon_get("weather-few-clouds")) self.vbox=QVBoxLayout() self.ribbon = ribbon_solar() self.vbox.addWidget(self.ribbon) self.ribbon.run.clicked.connect(self.callback_run) #self.ribbon.export.triggered.connect(self.callback_export) self.setWindowTitle(_("Solar Spectrum Generator")+" (https://www.gpvdm.com)") self.notebook = QTabWidget() self.vbox.addWidget(self.notebook) self.spectral2_gui=spectral2_gui() self.notebook.addTab(self.spectral2_gui,"SPECTRAL2") self.setLayout(self.vbox) def callback_run(self): tab = self.notebook.currentWidget() tab.calculate() def save(self): self.notebook.currentWidget().save() def copy(self): self.notebook.currentWidget().copy2clip()
class TabTable(QWidget): """ This is the base widget for tab table """ def __init__(self, parent=None, **kwargs): super(TabTable, self).__init__(parent) self.layout = QVBoxLayout(self) # Initialize tab screen self.tabs = QTabWidget() self.tabs.resize(300, 200) # Add tabs for i in kwargs: self.tabs.addTab(kwargs[i], i) # Add tabs to widget self.layout.addWidget(self.tabs) self.setLayout(self.layout) def New(self): self.tabs.currentWidget().New()
class SessionDetails(QWidget): def __init__(self, parent=None): super(SessionDetails, self).__init__(parent) self.tabs = QTabWidget(self) layout = QVBoxLayout(self) layout.addWidget(self.tabs) self.setMinimumSize(600, 600) self.tabs.currentChanged.connect(self.selectInterval) self.session = None def setSession(self, session): self.session = session self.tabs.clear() self.tabs.addTab(IntervalPage(session, self), str(session.start_time)) self.selectInterval(0) if not session.waypoints(): self.parent().map_holder.hide_map() else: self.parent().map_holder.show_map() def setTab(self, tab): t = self.tabs.currentWidget() t.setTab(tab) def addInterval(self, interval): self.tabs.addTab(IntervalPage(interval, self), str(interval.timestamp)) if interval.waypoints(): self.parent().map.draw_segment(interval.timestamp, interval.duration) def selectInterval(self, ix): if self.session.waypoints(): if ix == 0: self.parent().map.draw_map(self.session) # pass elif ix > 0: page = self.tabs.currentWidget() self.parent().map.draw_segment(page.interval.timestamp, page.interval.duration)
class RaceParams(QWidget): def __init__(self, parent=None): super().__init__(parent) self.vbox = QVBoxLayout(self) self.modetab = QTabWidget() self.vbox.addWidget(self.modetab) self.complaps = CompLaps() self.modetab.addTab(self.complaps, self.tr('Laps')) self.comptime = CompTime() self.modetab.addTab(self.comptime, self.tr('Time')) self.setLayout(self.vbox) def getCompMode(self): if self.modetab.currentWidget() == self.complaps: return COMP_MODE__RACE_LAPS if self.modetab.currentWidget() == self.comptime: return COMP_MODE__RACE_TIME def getDuration(self): if self.modetab.currentWidget() == self.complaps: return self.complaps.duration.value() if self.modetab.currentWidget() == self.comptime: return self.comptime.duration.value()
class AnalysisSettingsDock(AnalysisSettingsCreator, QDockWidget): def __init__(self, parent: QWidget, cellSelector: CellSelector, erManager): super().__init__("Settings", parent=parent) self._erManager = erManager self.setStyleSheet( "QDockWidget > QWidget { border: 1px solid lightgray; }") self._selector = cellSelector self.setObjectName( 'AnalysisSettingsDock') # needed for restore state to work widg = QWidget() widg.setLayout(QVBoxLayout()) self._settingsTabWidget = QTabWidget(self) self._PWSSettingsFrame = PWSSettingsFrame(self._erManager, cellSelector) self._settingsTabWidget.addTab(self._PWSSettingsFrame, "PWS") self._DynSettingsFrame = DynamicsSettingsFrame(self._erManager, cellSelector) self._settingsTabWidget.addTab(self._DynSettingsFrame, "Dynamics") widg.layout().addWidget(self._settingsTabWidget) self.addAnalysisButton = QPushButton("Add Analysis") widg.layout().addWidget(self.addAnalysisButton) self._analysesQueue = QueuedAnalysesFrame(self) widg.layout().addWidget(self._analysesQueue) self._analysesQueue.setFixedHeight(50) widg.setMinimumHeight(200) widg.setMinimumWidth(self._PWSSettingsFrame.minimumWidth() + 10) self.addAnalysisButton.released.connect(self._addAnalysis) self.setWidget(widg) def _addAnalysis(self): settingsWidget: AbstractSettingsFrame = self._settingsTabWidget.currentWidget( ) try: settings = settingsWidget.getSettings() except Exception as e: QMessageBox.information(self, 'Hold on', str(e)) return self._analysesQueue.addAnalysis(settings) def getListedAnalyses( self) -> typing.List[AbstractRuntimeAnalysisSettings]: return self._analysesQueue.analyses
class EvalWindow(QMainWindow): def __init__(self): super(EvalWindow, self).__init__() self.tab_widget = QTabWidget() self.tab_widget.setTabsClosable(True) self.tab_widget.setTabShape(1) self.tab_widget.tabCloseRequested.connect(self.on_close_tab) self.tab_widget.currentChanged.connect(self.tab_changed) self.setCentralWidget(self.tab_widget) self.data_editor_dock = QDockWidget("Data Inspection", self) self.data_editor_dock.setAllowedAreas(Qt.LeftDockWidgetArea | Qt.RightDockWidgetArea | Qt.BottomDockWidgetArea) self.addDockWidget(Qt.BottomDockWidgetArea, self.data_editor_dock) self.data_editor = DataEditor() self.data_editor_dock.setWidget(self.data_editor) self.navigation_dock = QDockWidget("Navigation Stack", self) self.navigation_dock.setAllowedAreas(Qt.LeftDockWidgetArea | Qt.RightDockWidgetArea | Qt.BottomDockWidgetArea) self.addDockWidget(Qt.BottomDockWidgetArea, self.navigation_dock) self.last_tab_widget = None self.resize(1000, 700) def add_eval(self, gui_eval): self.show() self.activateWindow() self.tab_widget.addTab(gui_eval, gui_eval.view.scene.workflow.name) def tab_changed(self, index): curr_widget = self.tab_widget.currentWidget() curr_widget.view.scene.on_selection_changed() self.navigation_dock.setWidget(curr_widget.navigation) self.last_tab_widget = curr_widget def on_close_tab(self, index): self.tab_widget.removeTab(index)
class AutoPickerSettingDialog(QDialog): applySignal = QtCore.pyqtSignal(object) def __init__(self, parent=None): super(AutoPickerSettingDialog, self).__init__(parent) self.tabWidget = QTabWidget() self.tabWidget.addTab(StaLtaTab(self), "STA/LTA") #tabWidget.addTab(ArAicTab(), "AR-AIC") defaultButton = QPushButton(' Restore Defaults ') spacer1 = QSpacerItem(20,20, QSizePolicy.Minimum) applyButton = QPushButton('Apply') buttonBox = QDialogButtonBox(QDialogButtonBox.Ok | QDialogButtonBox.Cancel) buttonBox.accepted.connect(self.accept) buttonBox.rejected.connect(self.reject) applyButton.clicked.connect(self.onApplyClicked) hbl = QHBoxLayout() hbl.addWidget(defaultButton) hbl.addItem(spacer1) hbl.addWidget(applyButton) hbl.addWidget(buttonBox) mainLayout = QVBoxLayout() mainLayout.addWidget(self.tabWidget) mainLayout.addLayout(hbl) self.setLayout(mainLayout) self.setWindowTitle("AutoPicker Settings") def onApplyClicked(self): configDict = self.tabWidget.currentWidget().getConfig() self.applySignal.emit(configDict)
class ConnectionEditWindow(QWidget): MAVLinkConnectedSignal = pyqtSignal(object) cancelConnectionSignal = pyqtSignal() def __init__(self, parent=None): super().__init__(parent) self.tabs = QTabWidget(self) self._createTabs() l = QVBoxLayout() l.setContentsMargins(0, 0, 0, 0) l.addWidget(self.tabs) l.addWidget(self.__createActionButtons()) self.setLayout(l) def _createTabs(self): self.serialConnTab = SerialConnectionEditTab(parent=self) self.logReplayTab = LogFileReplayEditTab(self) self.tabs.addTab(self.serialConnTab, 'Serial Link') self.tabs.addTab(self.logReplayTab, 'Log File Replay') def __createActionButtons(self): l = QHBoxLayout() l.setContentsMargins(5, 0, 5, 5) self.connectButton = QPushButton('Connect') self.closeButton = QPushButton('Close') self.connectButton.clicked.connect(self._doConnect) self.closeButton.clicked.connect(self.close) l.addWidget(self.connectButton) l.addWidget(self.closeButton) self.actionButtonWidget = QWidget() self.actionButtonWidget.setLayout(l) return self.actionButtonWidget def closeEvent(self, event): self.cancelConnectionSignal.emit() super().closeEvent(event) def _doConnect(self): currTab = self.tabs.currentWidget() if hasattr(currTab, 'doConnect'): if currTab.doConnect(): self.close()
class chessTabs(QWidget): def __init__(self, parent, chess_db, engines): super(QWidget, self).__init__(parent) self.tabs = QTabWidget() viewer_tab = ViewerTab(self, chess_db) player_tab = PlayerTab(self, engines) self.tabs.addTab(viewer_tab, "Viewer") self.tabs.addTab(player_tab, "Player") layout = QGridLayout(self) layout.addWidget(self.tabs) self.setLayout(layout) def wheelEvent(self, event: QWheelEvent): tab = self.tabs.currentWidget() if event.angleDelta().y() > 0: tab.fwd_btn_click() elif event.angleDelta().y() < 0: tab.back_btn_click()
class MainWindow(QMainWindow): connect_to_yadisk_signal = pyqtSignal() get_yadisk_listdir = pyqtSignal(str) get_local_listdir = pyqtSignal(str) get_bublic_listdir = pyqtSignal(str) move_file_signal = pyqtSignal(str, str) download_from_auth_yadisk = pyqtSignal(str, str, dict) download_from_bublic_yadisk = pyqtSignal(str, str, dict) upload_to_auth_yadisk = pyqtSignal(str, str, dict) open_link_signal = pyqtSignal() local_browse_clicked = pyqtSignal(KeyType, SecurityAlgorithm) yadisk_browse_clicked = pyqtSignal(KeyType, SecurityAlgorithm) local_algorithm_changed = pyqtSignal(SecurityAlgorithm, KeyType) yadisk_algorithm_changed = pyqtSignal(SecurityAlgorithm, KeyType) set_media_folder = pyqtSignal(str) def __init__(self): super(MainWindow, self).__init__() uic.loadUi("forms/mainwindow.ui", self) self.local_files = QTabWidget() #FileSystem() self.add_local_file_system() self.yadisk_files = QTabWidget() self.h_layout.layout().addWidget(self.local_files) self.h_layout.layout().addWidget(self.yadisk_files) self.connect_to_actions() self.show_status("Not connected") self.local_files.show() self.icon = QIcon(":/img/images/icon.png") self.setWindowIcon(self.icon) def connect_to_actions(self): self.connect_to_yadisk_action.triggered.connect(self.connect_to_yadisk) self.open_link_action.triggered.connect(self.open_link) self.yadisk_files.currentChanged.connect(self.yadisk_tab_changed) def get_local_system(self): return self.local_files.currentWidget() def get_yadisk(self): return self.yadisk_files.currentWidget() def add_local_file_system(self): file_system = FileSystem(magic_const.LOCAL_FILE_SYSTEM_LABELS, "local") file_system.double_clicked.connect(self.get_local_listdir) file_system.move_clicked.connect(self.move_file_from_local) file_system.browse_clicked.connect(self.local_browse_clicked) file_system.algorithm_changed.connect(self.local_algorithm_changed) self.local_files.addTab(file_system, "Local file system") file_system.set_load_button_enable(False) def add_authorized_yadisk_tab(self): file_system = FileSystem(magic_const.YADISK_FILE_SYSTEM_LABELS, "yadisk_auth") file_system.double_clicked.connect(self.get_yadisk_listdir) file_system.move_clicked.connect(self.move_file_from_yadisk) file_system.browse_clicked.connect(self.yadisk_browse_clicked) file_system.algorithm_changed.connect(self.yadisk_algorithm_changed) file_system.set_media_folder.connect(self.set_media_folder) self.yadisk_files.addTab(file_system, "YaDisk") self.yadisk_files.setCurrentWidget(file_system) def add_bublic_yadisk_tab(self, name="name"): file_system = BublicFileSystem(magic_const.YADISK_FILE_SYSTEM_LABELS, "bublic") file_system.double_clicked.connect(self.get_bublic_listdir) file_system.move_clicked.connect(self.move_file_from_bublic_yadisk) file_system.algorithm_changed.connect(self.yadisk_algorithm_changed) self.yadisk_files.addTab(file_system, name) self.yadisk_files.setCurrentWidget(file_system) def connect_to_yadisk(self): self.connect_to_yadisk_signal.emit() #self.yadisk_files.addTab(FileSystem(), "name") #self.connect_to_yadisk_signal.emit() def open_link(self): #self.add_yadisk_tab() self.open_link_signal.emit() def show_status(self, message): self.statusBar().showMessage(message) def show_local_listdir(self, listdir, path): #print("show local listdir", path) self.get_local_system().show_listdir(listdir, path) def show_yadisk_listdir(self, listdir, path): self.get_yadisk().show_listdir(listdir, path) def get_crypto_data(self, file_system): result = { "algorithm": file_system.get_algorithm(), "key_type": file_system.get_key_type(), "key": file_system.get_key().encode("utf-8"), "media_path": file_system.get_file_path(), "take_file_from_yadisk": file_system.take_file_from_yadisk(), "media_type": file_system.get_media_type() } return result def move_file_from_yadisk(self): local_system = self.get_local_system() yadisk_files = self.get_yadisk() from_folder = Path(yadisk_files.get_folder_path()) to_folder = Path(local_system.get_folder_path()) file_name = yadisk_files.get_file_name() from_path = from_folder / file_name to_path = to_folder / file_name encryption_data = self.get_crypto_data(yadisk_files) self.download_from_auth_yadisk.emit(from_path.as_posix(), to_path.as_posix(), encryption_data) #self.move_file_signal.emit(from_path.as_posix(), to_path.as_posix()) def move_file_from_local(self): # TODO : add algorithm and key type local_system = self.get_local_system() yadisk_files = self.get_yadisk() from_folder = Path(local_system.get_folder_path()) to_folder = Path(yadisk_files.get_folder_path()) file_name = local_system.get_file_name() from_path = from_folder / file_name to_path = to_folder / file_name encryption_data = self.get_crypto_data(local_system) self.upload_to_auth_yadisk.emit(from_path.as_posix(), to_path.as_posix(), encryption_data) def move_file_from_bublic_yadisk(self): local_system = self.get_local_system() yadisk_files = self.get_yadisk() from_url = yadisk_files.get_folder_path() to_folder = Path(local_system.get_folder_path()) file_name = yadisk_files.get_file_name() to_path = to_folder / file_name encryption_data = self.get_crypto_data(yadisk_files) self.download_from_bublic_yadisk.emit(from_url, to_path.as_posix(), encryption_data) def get_yadisk_folder_name(self): return self.yadisk_files.currentWidget().get_folder_path() def get_local_folder_name(self): return self.local_files.currentWidget().get_folder_path() def browse(self, filesystem, result): #filesystem.put_key("") filesystem.put_file_path("") if result["action"] == "get_save_filename": path = QFileDialog.getSaveFileName(self, "Create file", "new", result["limits"]) filesystem.put_file_path(path[0]) elif result["action"] == "get_open_filename": path = QFileDialog.getOpenFileName(self, "Open file", "", result["limits"]) filesystem.put_file_path(path[0]) else: pass def local_browse(self, result): filesystem = self.get_local_system() self.browse(filesystem, result) def yadisk_browse(self, result): filesystem = self.get_yadisk() self.browse(filesystem, result) def put_local_key(self, key): filesystem = self.get_local_system() filesystem.put_key(key) def put_yadisk_key(self, key): filesystem = self.get_yadisk() filesystem.put_key(key) def yadisk_tab_changed(self): yadisk_filesystem = self.yadisk_files.currentWidget() local_filesystem = self.local_files.currentWidget() if yadisk_filesystem.system_type == "yadisk_auth": local_filesystem.set_load_button_enable(True) elif yadisk_filesystem.system_type == "bublic": local_filesystem.set_load_button_enable(False) else: logger.error("In yadisk tab wrong system type") def show_progress_dialog(self, message, value=0, minmax=None): if minmax == None: minmax = (0, 0) self.progress = QProgressDialog(self) self.progress.setWindowTitle("Please, wait") self.progress.setLabelText(message) self.progress.setRange(*minmax) self.progress.setValue(value) self.progress.setCancelButton(None) self.progress.show() logger.info("Progress bar is opened") def close_progress_dialog(self): self.progress.close() logger.info("Progress bar is closed")
class MainWindow(QMainWindow): def __init__(self, filename): super().__init__() self.setGeometry(20, 20, 1324, 1068) self.setWindowTitle('qt-Notepad') self.setStyleSheet('font-size: 14pt; font-family: Courier;') self.show() self.init_ui() centralWidget = QWidget() self.tabs = QTabWidget(centralWidget) self.setCentralWidget(self.tabs) self.tabs.setTabsClosable(True) self.tabs.setMovable(True) self.tabs.tabCloseRequested.connect(self.closeTab) if filename: f = open(filename, 'r') filedata = f.read() f.close() newfile = QTextEdit() newfile.setText(filedata) i = self.tabs.addTab(newfile, filename) self.tabs.setCurrentIndex(i) else: self.open_file() def init_ui(self): new_action = QAction('New File', self) new_action.setShortcut('Ctrl+N') new_action.setStatusTip('Create new file') new_action.triggered.connect(self.new_file) open_action = QAction('Open...', self) open_action.setShortcut('Ctrl+O') open_action.setStatusTip('Open a file') open_action.triggered.connect(self.open_file) save_action = QAction('Save File', self) save_action.setShortcut('Ctrl+S') save_action.setStatusTip('Save current file') save_action.triggered.connect(self.save_file) new_save_action = QAction('Save File As...', self) new_save_action.setShortcut('Shift+Ctrl+S') new_save_action.setStatusTip('Save current file') new_save_action.triggered.connect(self.save_file_as) close_action = QAction('Close File', self) close_action.setShortcut('Ctrl+W') close_action.setStatusTip('Close file and exit tab') close_action.triggered.connect(self.close_file) exit_action = QAction('Exit qt-Notepad', self) exit_action.setShortcut('Ctrl+Q') exit_action.setStatusTip('Close Notepad') exit_action.triggered.connect(self.close) undo_action = QAction('Undo', self) undo_action.setShortcut('Ctrl+Z') copy_action = QAction('Copy', self) copy_action.setShortcut('Ctrl+C') cut_action = QAction('Cut', self) cut_action.setShortcut('Ctrl+X') paste_action = QAction('Paste', self) paste_action.setShortcut('Ctrl+V') minimize_action = QAction('Minimize', self) minimize_action.setShortcut('Ctrl+M') view_action = QAction('Show', self) view_action.setShortcut('Ctrl+/') menubar = self.menuBar() file_menu = menubar.addMenu('&File') edit_menu = menubar.addMenu('&Edit') view_menu = menubar.addMenu('&View') window_menu = menubar.addMenu('&Window') file_menu.addAction(new_action) file_menu.addAction(open_action) file_menu.addAction(save_action) file_menu.addAction(new_save_action) file_menu.addAction(close_action) file_menu.addAction(exit_action) edit_menu.addAction(undo_action) edit_menu.addAction(copy_action) edit_menu.addAction(cut_action) edit_menu.addAction(paste_action) view_menu.addAction(view_action) window_menu.addAction(minimize_action) def closeTab(self, currentIndex): currentQWidget = self.tabs.currentWidget() currentQWidget.deleteLater() self.tabs.removeTab(currentIndex) def new_file(self): newfile = QTextEdit() i = self.tabs.addTab(newfile, 'New Document') self.tabs.setCurrentIndex(i) def save_file(self): editor = self.tabs.currentWidget() filename = self.tabs.tabText(self.tabs.currentIndex()) if filename != 'New Document': f = open(filename, 'w') filedata = editor.toPlainText() f.write(filedata) f.close() else: self.save_file_as() def save_file_as(self): filename = QFileDialog.getSaveFileName(self, 'Save File', os.getenv('HOME'))[0] print(filename) if filename != ('', ''): f = open(filename, 'w') filedata = self.text.toPlainText() f.write(filedata) f.close() def open_file(self): filename = QFileDialog.getOpenFileName(self, 'Open File', os.getenv('HOME'))[0] f = open(filename, 'r') filedata = f.read() f.close() newfile = QTextEdit() newfile.setText(filedata) i = self.tabs.addTab(newfile, filename) self.tabs.setCurrentIndex(i) def close_file(self): self.save_file() currentIndex = self.tabs.currentIndex() self.tabs.removeTab(currentIndex)
class MainWindow(QMainWindow): def __init__(self): super(MainWindow, self).__init__() fileMenu = QMenu("&File", self) newAction = fileMenu.addAction("&New...") newAction.setShortcut("Ctrl+N") self.printAction = fileMenu.addAction("&Print...", self.printFile) self.printAction.setShortcut("Ctrl+P") self.printAction.setEnabled(False) quitAction = fileMenu.addAction("&Exit") quitAction.setShortcut("Ctrl+Q") helpMenu = QMenu("&Help", self) aboutAction = helpMenu.addAction("&About") self.menuBar().addMenu(fileMenu) self.menuBar().addMenu(helpMenu) self.solvers = QTabWidget() self.solvers.setTabsClosable(True) self.solvers.tabCloseRequested.connect(self.closeTab) newAction.triggered.connect(self.openDialog) quitAction.triggered.connect(self.close) aboutAction.triggered.connect(self.openAbout) self.setCentralWidget(self.solvers) self.setWindowTitle("Pulppy Software") def printFile(self): editor = self.solvers.currentWidget() if type(editor) == QTextEdit: printer = QPrinter() dialog = QPrintDialog(printer, self) dialog.setWindowTitle("Print Document") if dialog.exec_() != QDialog.Accepted: return editor.print_(printer) else: answer = QMessageBox.warning(self, "Not Print Image", "Dont print graph.", QMessageBox.Ok) def closeTab (self, currentIndex): currentQWidget = self.solvers.widget(currentIndex) currentQWidget.deleteLater() self.solvers.removeTab(currentIndex) def openDialog(self): inputProblemDialog = InputProblem(self) if inputProblemDialog.exec_() == QDialog.Accepted: inputTable = InputTableModel(inputProblemDialog.title , inputProblemDialog.numVar, inputProblemDialog.numCons , inputProblemDialog.typeVar, inputProblemDialog.objCrit, self) if inputTable.exec_() == QDialog.Accepted: self.createTabSolver(inputTable.problem) if inputTable.numVariables == 2: self.createTabGraph(inputTable.canvas) def createTabGraph(self, canvas): self.main_widget = QWidget(self) vbox = QVBoxLayout(self.main_widget) vbox.addWidget(canvas.mpl_toolbar) vbox.addWidget(canvas) tabIndex = self.solvers.addTab(self.main_widget, "Graph - "+canvas.title) self.solvers.setCurrentIndex(tabIndex) def createTabSolver(self, problem): editor = QTextEdit() tabIndex = self.solvers.addTab(editor, problem.name) self.solvers.setCurrentIndex(tabIndex) cursor = editor.textCursor() cursor.movePosition(QTextCursor.Start) topFrame = cursor.currentFrame() topFrameFormat = topFrame.frameFormat() topFrameFormat.setPadding(16) topFrame.setFrameFormat(topFrameFormat) textFormat = QTextCharFormat() boldFormat = QTextCharFormat() boldFormat.setFontWeight(QFont.Bold) referenceFrameFormat = QTextFrameFormat() referenceFrameFormat.setBorder(1) referenceFrameFormat.setPadding(8) referenceFrameFormat.setPosition(QTextFrameFormat.FloatLeft) referenceFrameFormat.setWidth(QTextLength(QTextLength.PercentageLength, 100)) cursor.insertFrame(referenceFrameFormat) cursor.insertText("Title Problem: ", boldFormat) cursor.insertText(problem.name+"\n", textFormat) cursor.insertText("Criterion: ", boldFormat) if problem.sense == 1: cursor.insertText("Minimize\n",textFormat) else: cursor.insertText("Maximize\n",textFormat) WasNone, dummyVar = problem.fixObjective() cursor.insertText("Status: ", boldFormat) cursor.insertText(str(LpStatus[problem.status])+"\n", textFormat) cursor.insertText("Value Function Objetive: ", boldFormat) cursor.insertText(str(value(problem.objective))+"\n", textFormat) cursor.insertBlock() cursor.insertText("Objective\n", boldFormat) cursor.insertText(str(problem.objective)+"\n", textFormat) cursor.insertBlock() cursor.insertText("Subject To\n", boldFormat) ks = list(problem.constraints.keys()) ks.sort() for k in ks: constraint = problem.constraints[k] print constraint if not list(constraint.keys()): #empty constraint add the dummyVar dummyVar = problem.get_dummyVar() constraint += dummyVar #set this dummyvar to zero so infeasible problems are not made #feasible cursor.insertText((dummyVar == 0.0).asCplexLpConstraint("_dummy") , textFormat) cursor.insertBlock() cursor.insertText(str(k)+" : ", boldFormat) cursor.insertText(str(constraint), textFormat) cursor.insertBlock() vs = problem.variables() cursor.insertBlock() # Bounds on non-"positive" variables # Note: XPRESS and CPLEX do not interpret integer variables without # explicit bounds mip=1 if mip: vg=[v for v in vs if not (v.isPositive() and v.cat==LpContinuous) \ and not v.isBinary()] else: vg = [v for v in vs if not v.isPositive()] if vg: cursor.insertText("Bounds\n", boldFormat) for v in vg: cursor.insertText("%s, " % v.asCplexLpVariable(), textFormat) # Integer non-binary variables if mip: vg = [v for v in vs if v.cat == LpInteger and not v.isBinary()] if vg: cursor.insertText("Generals\n", boldFormat) for v in vg: cursor.insertText("%s, " % v.name, textFormat) # Binary variables vg = [v for v in vs if v.isBinary()] if vg: cursor.insertText("Binaries\n",boldFormat) for v in vg: cursor.insertText("%s, " % v.name, textFormat) cursor.setPosition(topFrame.lastPosition()) bodyFrameFormat = QTextFrameFormat() bodyFrameFormat.setWidth(QTextLength(QTextLength.PercentageLength, 100)) cursor.insertBlock() cursor.insertFrame(bodyFrameFormat) cursor.insertBlock() orderTableFormat = QTextTableFormat() orderTableFormat.setAlignment(Qt.AlignHCenter) orderTable = cursor.insertTable(1, 3, orderTableFormat) orderFrameFormat = cursor.currentFrame().frameFormat() orderFrameFormat.setBorder(1) cursor.currentFrame().setFrameFormat(orderFrameFormat) cursor = orderTable.cellAt(0, 0).firstCursorPosition() cursor.insertText("Variable", boldFormat) cursor = orderTable.cellAt(0, 1).firstCursorPosition() cursor.insertText("Value", boldFormat) cursor = orderTable.cellAt(0, 2).firstCursorPosition() cursor.insertText("Reduced Cost", boldFormat) for v in problem.variables(): row = orderTable.rows() orderTable.insertRows(row, 1) #Name variable cursor = orderTable.cellAt(row, 0).firstCursorPosition() cursor.insertText(v.name, textFormat) #Value variable cursor = orderTable.cellAt(row, 1).firstCursorPosition() cursor.insertText(str(v.varValue), textFormat) #Cost Reduced variable cursor = orderTable.cellAt(row, 2).firstCursorPosition() cursor.insertText(str(v.dj), textFormat) cursor.setPosition(topFrame.lastPosition()) cursor.insertBlock() orderTableFormat = QTextTableFormat() orderTableFormat.setAlignment(Qt.AlignHCenter) orderTable = cursor.insertTable(1, 3, orderTableFormat) orderFrameFormat = cursor.currentFrame().frameFormat() orderFrameFormat.setBorder(1) cursor.currentFrame().setFrameFormat(orderFrameFormat) cursor = orderTable.cellAt(0, 0).firstCursorPosition() cursor.insertText("Constraint", boldFormat) cursor = orderTable.cellAt(0, 1).firstCursorPosition() cursor.insertText("Slack", boldFormat) cursor = orderTable.cellAt(0, 2).firstCursorPosition() cursor.insertText("Shadow Price", boldFormat) for m in range(problem.numConstraints()): row = orderTable.rows() orderTable.insertRows(row, 1) #Name Constraint cursor = orderTable.cellAt(row, 0).firstCursorPosition() cursor.insertText("C"+ str(m+1), textFormat) #Slack Constraint cursor = orderTable.cellAt(row, 1).firstCursorPosition() cursor.insertText(str(problem.constraints.get("_C"+str(m+1)).slack) , textFormat) cursor = orderTable.cellAt(row, 2).firstCursorPosition() cursor.insertText(str(problem.constraints.get("_C"+str(m+1)).pi) , textFormat) self.printAction.setEnabled(True) def openAbout(self): about = AboutDialog(self) about.show()
class ObserverWindow(QMainWindow): messageReceived = pyqtSignal(str, str, str, str, str) newFilterSettingsApplied = pyqtSignal(str) resetDisplays = pyqtSignal() #__________________________________________________________________ def __init__(self, client, logger): super(ObserverWindow, self).__init__() self._connectionState = None self._countUntitledDisplay = 0 self._displays = [] self._session = 'Default session' self._host = 'localhost' self._port = 1883 self._rootTopic = '' self._logger = logger self._logger.info(self.tr("Started")) reg = QSettings() if "current session" in reg.childKeys() and reg.value( "current session", '').strip() and reg.value( "current session", '').strip() in reg.childGroups(): self._session = reg.value("current session") self._logger.info(self.tr("Current session : ") + self._session) if self._session not in reg.childGroups(): reg.beginGroup(self._session) reg.setValue("host", self._host) reg.setValue("port", self._port) reg.setValue("root topic", self._rootTopic) reg.endGroup() else: reg.beginGroup(self._session) self._host = reg.value("host", 'localhost') try: self._port = reg.value("port", 1883, type=int) except: pass self._rootTopic = reg.value("root topic", '') reg.endGroup() if "current session" in reg.childKeys() and not reg.value( "current session", '') in reg.childGroups(): reg.remove("current session") self._mqttSwitchingConnection = False self._mqttClient = client self._mqttServerHost = self._host self._mqttServerPort = self._port self._mqttRootTopic = self._rootTopic self._mqttSubTopic = '#' if self._rootTopic: self._mqttSubTopic = self._rootTopic + '/#' QApplication.desktop().screenCountChanged.connect(self.restoreWindow) QApplication.desktop().resized.connect(self.restoreWindow) self.setWindowTitle(self._session) self.setWindowIcon(QIcon(':/view-eye.svg')) self._tabWidget = QTabWidget() self._cloudLabel = QLabel() self._connectionStateLabel = QLabel() self.builUi() reg.beginGroup(self._session) inbox = reg.value("param inbox", 'inbox') outbox = reg.value("param outbox", 'outbox') regexInbox = reg.value("regex inbox", r'^%ROOT%/(?P<correspondent>.+)/%INBOX%$') regexOutbox = reg.value("regex outbox", r'^%ROOT%/(?P<correspondent>.+)/%OUTBOX%$') regexDefault = reg.value("regex default", r'.*/(?P<correspondent>[^/]+)/[^/]+$') reg.endGroup() regexInbox = regexInbox.replace("%ROOT%", self._rootTopic).replace( "%INBOX%", inbox) regexOutbox = regexOutbox.replace("%ROOT%", self._rootTopic).replace( "%OUTBOX%", outbox) self._topicRegexInbox = None try: self._topicRegexInbox = re.compile(regexInbox) except Exception as e: self._logger.error(self.tr("Failed to compile inbox regex")) self._logger.debug(e) self._topicRegexOutbox = None try: self._topicRegexOutbox = re.compile(regexOutbox) except Exception as e: self._logger.error(self.tr("Failed to compile outbox regex")) self._logger.debug(e) self._topicRegexDefault = None try: self._topicRegexDefault = re.compile(regexDefault) except Exception as e: self._logger.error( self.tr("Failed to compile topic default regex")) self._logger.debug(e) self.addDisplay(self.tr("All messsages")) reg.beginGroup(self._session) for i in reg.childGroups(): self.addDisplay(i) reg.endGroup() self.changeConnectionState(ConnectionState.DISCONNECTED) self._logger.info("{0} : {1}".format(self.tr("MQTT server host"), self._mqttServerHost)) self._logger.info("{0} : {1}".format(self.tr("MQTT server port"), self._mqttServerPort)) self._logger.info("{0} : {1}".format( self.tr("MQTT clientid"), self._mqttClient._client_id.decode("latin1"))) Timer(0, self.layoutLoadSettings).start() Timer(0, self.start).start() #__________________________________________________________________ @pyqtSlot() def addDisplay(self, title=None): if not title: if self._countUntitledDisplay: title = "{0} ({1})".format(self.tr("New observation"), self._countUntitledDisplay) else: title = self.tr("New observation") self._countUntitledDisplay = self._countUntitledDisplay + 1 reg = QSettings() reg.beginGroup(self._session) if title not in reg.childGroups(): reg.beginGroup(title) reg.setValue("display", int(TopicDisplay.EMPHASIZEDCORRESPONDENT)) reg.endGroup() reg.endGroup() reg.sync() root_observation = not len(self._displays) new_display = ObserverDisplayWidget(title, self._logger, self._session, self._mqttServerHost, self._mqttServerPort, self._mqttRootTopic, remove=not root_observation, filter=not root_observation) new_display.addObservation.connect(self.addDisplay) new_display.delObservation.connect(self.removeCurrentDisplay) self.newFilterSettingsApplied.connect(new_display.applyFilterSettings) self._displays.append(new_display) self._tabWidget.addTab(new_display, title) self.resetDisplays.connect(new_display.reset) self.messageReceived.connect(new_display.processMessage) new_display.newFilterSettings.connect(self.applyFilterSettings) new_display.resetWills.connect(self.applyResetWills) self._tabWidget.setCurrentWidget(new_display) self._logger.info("{0} : {1}".format(self.tr("Added observation"), title)) dspmsg = '' for d in self._displays: if dspmsg: dspmsg += ' | ' else: dspmsg = 'Displays : ' dspmsg += d.title() self._logger.debug(dspmsg) #__________________________________________________________________ @pyqtSlot(dict) def applyFilterSettings(self, filter): try: display = None for d in self._displays: if d.title() == filter["observation"]: display = d if not display: self._logger.error( self.tr("Observation not found in displays : ") + filter["observation"]) else: if filter["name"] != filter["observation"]: for d in self._displays: if d.title() == filter["name"]: self._logger.warning( self.tr("Can't rename observation '") + filter["observation"] + self.tr("' : '") + filter["name"] + self.tr("' already exists")) msgbox = QMessageBox() msgbox.setWindowTitle(self.tr("Observer")) msgbox.setWindowIcon( QIcon(':/magnifier-black.svg')) msgbox.setText( self.tr("Ignore apply filter !") + "<br><br><i>" + self. tr("Can't rename observation (name already in use)." ) + "</i><br>") msgbox.setStandardButtons(QMessageBox.Close) msgbox.setAttribute(Qt.WA_DeleteOnClose) msgbox.setWindowFlags( msgbox.windowFlags() & ~Qt.WindowContextHelpButtonHint) msgbox.button(QMessageBox.Close).setText( self.tr("Close")) msgbox.move(self.pos() + QPoint(40, 40)) msgbox.exec() return display.setTitle(filter["name"]) self._tabWidget.setTabText(self._tabWidget.currentIndex(), filter["name"]) reg = QSettings() reg.beginGroup(self._session) reg.remove(filter["observation"]) reg.endGroup() reg = QSettings() reg.beginGroup(self._session) reg.beginGroup(filter["name"]) reg.setValue("display", int(filter["display"])) reg.setValue("filter 1", filter["filter 1"]) reg.setValue("filter 2", filter["filter 2"]) reg.setValue("filter 3", filter["filter 3"]) reg.setValue("filter 4", filter["filter 4"]) reg.setValue("buffer size", filter["buffer size"]) reg.remove("Hidden correspondents") reg.beginGroup("Hidden correspondents") for p in filter["hidden correspondents"]: reg.setValue(p.replace('/', '\\'), '') reg.endGroup() reg.remove("Hidden topics") reg.beginGroup("Hidden topics") for t in filter["hidden topics"]: reg.setValue(t.replace('/', '\\'), '') reg.endGroup() reg.endGroup() reg.endGroup() reg.sync() self.newFilterSettingsApplied.emit(filter["name"]) except Exception as e: self._logger.error("Failed to apply filter settings") self._logger.debug(e) #__________________________________________________________________ @pyqtSlot(list) def applyResetWills(self, topics): for topic in topics: if self._connectionState == ConnectionState.CONNECTED: try: (result, mid) = self._mqttClient.publish(topic, '', qos=0, retain=True) self._logger.info("{0} {1} (mid={2})".format( self.tr("MQTT sending '' to clear will for "), topic, mid)) except Exception as e: self._logger.info("{0} {1} (mid={2})".format( self.tr("MQTT failed to send '' to clear will for "), topic, mid)) self._logger.debug(e) else: self._logger.info("{0} {1}".format( self.tr("MQTT failed to reset will (disconnected) for "), topic)) #__________________________________________________________________ def builUi(self): mw = QWidget() self.setCentralWidget(mw) main_layout = QVBoxLayout(mw) main_layout.setSpacing(12) cloud_image = QLabel() cloud_image.setPixmap(QIcon(":/cloud-data.svg").pixmap(QSize(36, 36))) cloud_image.setSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed) cloud = self._mqttServerHost + ':' + str(self._mqttServerPort) if self._mqttRootTopic: cloud += '/' + self._mqttRootTopic + '/#' else: cloud += '/#' self._cloudLabel.setText(cloud) font = self._cloudLabel.font() font.setPixelSize(12) font.setBold(True) self._cloudLabel.setFont(font) settings_button = QPushButton() settings_button.setIcon(QIcon(":/settings.svg")) settings_button.setFlat(True) settings_button.setToolTip(self.tr("Settings")) settings_button.setIconSize(QSize(16, 16)) settings_button.setFixedSize(QSize(24, 24)) settings_button.setStyleSheet("QPushButton { padding-bottom: 4px }") self._connectionStateLabel = QLabel() self._connectionStateLabel.setPixmap( QIcon(":/led-circle-grey.svg").pixmap(QSize(24, 24))) self._connectionStateLabel.setSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed) header_layout = QHBoxLayout() header_layout.addWidget(cloud_image) header_layout.addWidget(self._cloudLabel) header_layout.addStretch() header_layout.addWidget(settings_button) header_layout.addWidget(self._connectionStateLabel) main_layout.addLayout(header_layout) main_layout.addWidget(self._tabWidget) settings_button.pressed.connect(self.settings) #__________________________________________________________________ def changeConnectionState(self, state): self._connectionState = state if state == ConnectionState.CONNECTED: self._connectionStateLabel.setPixmap( QIcon(":/led-circle-green.svg").pixmap(QSize(24, 24))) self._connectionStateLabel.setToolTip(self.tr("Connected")) elif state == ConnectionState.CONNECTING: self._connectionStateLabel.setPixmap( QIcon(":/led-circle-yellow.svg").pixmap(QSize(24, 24))) self._connectionStateLabel.setToolTip(self.tr("Connecting")) elif state == ConnectionState.DISCONNECTED: self._connectionStateLabel.setPixmap( QIcon(":/led-circle-red.svg").pixmap(QSize(24, 24))) self._connectionStateLabel.setToolTip(self.tr("Disconnected")) else: self._connectionStateLabel.setPixmap( QIcon(":/led-circle-grey.svg").pixmap(QSize(24, 24))) self._connectionStateLabel.setToolTip("") #__________________________________________________________________ def closeEvent(self, event): self._logger.info(self.tr("Done")) #__________________________________________________________________ def layoutLoadSettings(self): reg = QSettings() pos = reg.value("position", QPoint(200, 200)) size = reg.value("size", QSize(400, 400)) self.move(pos) self.resize(size) #__________________________________________________________________ def layoutSaveSettings(self): reg = QSettings() reg.setValue("position", self.pos()) reg.setValue("size", self.size()) reg.sync() #__________________________________________________________________ def moveEvent(self, event): if self.isVisible(): Timer(0, self.layoutSaveSettings).start() #__________________________________________________________________ def mqttConnect(self): self._logger.info(self.tr("May connect to MQTT server...")) if self._mqttSwitchingConnection and self._connectionState == ConnectionState.DISCONNECTED: self._mqttServerHost = self._host self._mqttServerPort = self._port self._mqttRootTopic = self._rootTopic if self._rootTopic: self._mqttSubTopic = self._rootTopic + '/#' else: self._mqttSubTopic = '#' cloud = self._mqttServerHost + ':' + str(self._mqttServerPort) if self._mqttRootTopic: cloud += '/' + self._mqttRootTopic + '/#' else: cloud += '/#' self._cloudLabel.setText(cloud) clientid = "Observer/" + QUuid.createUuid().toString() self._logger.debug("MQTT clientid %s", clientid) self._mqttClient.reinitialise(client_id=clientid, clean_session=True, userdata=None) self._logger.info(self.tr("MQTT client reinitialised")) self._logger.info("{0} : {1}".format(self.tr("MQTT server host"), self._mqttServerHost)) self._logger.info("{0} : {1}".format(self.tr("MQTT server port"), self._mqttServerPort)) self._logger.info("{0} : {1}".format( self.tr("MQTT clientid"), self._mqttClient._client_id.decode("latin1"))) self._mqttClient.on_connect = self.mqttOnConnect self._mqttClient.on_disconnect = self.mqttOnDisconnect self._mqttClient.on_log = self.mqttOnLog self._mqttClient.on_message = self.mqttOnMessage self._mqttClient.on_publish = self.mqttOnPublish self._mqttClient.on_subscribe = self.mqttOnSubscribe self._mqttClient.on_unsubscribe = self.mqttOnUnsubscribe self._mqttSwitchingConnection = False self._mqttClient.loop_start() if self._connectionState == ConnectionState.CONNECTED or self._connectionState == ConnectionState.CONNECTING: self._logger.info( self.tr("MQTT connect ignored (already ongoing)")) else: self._logger.info(self.tr("Connect to MQTT server")) try: self._mqttClient.connect(self._mqttServerHost, port=self._mqttServerPort, keepalive=MQTT_KEEPALIVE) self.changeConnectionState(ConnectionState.CONNECTING) self._logger.info(self.tr("MQTT connecting")) except Exception as e: self.changeConnectionState(ConnectionState.DISCONNECTED) self._logger.warning( self.tr("Failed to connect to MQTT server")) self._logger.debug(e) Timer(15.000, self.mqttConnect).start() self._logger.debug("Connection state = " + str(self._connectionState)) #__________________________________________________________________ def mqttDisconnect(self): try: self._mqttClient.disconnect() except Exception as e: self._logger.error(self.tr("MQTT disconnection call failed")) self._logger.debug(e) #__________________________________________________________________ def mqttOnConnect(self, client, userdata, flags, rc): self._logger.debug("Connected to MQTT server with result code: " + str(rc) + " and flags: ", flags) # flags is dict if rc == 0: self._logger.info(self.tr("MQTT connected")) self.changeConnectionState(ConnectionState.CONNECTED) mydata = { 'host': self._mqttServerHost, 'port': self._mqttServerPort } self._mqttClient.user_data_set(str(mydata)) try: (result, mid) = self._mqttClient.subscribe(self._mqttSubTopic) self._logger.info("{0} {1} : {2}".format( self.tr("MQTT subscribing to"), mid, self._mqttSubTopic)) except Exception as e: self._logger.error(self.tr("MQTT subscribe call failed")) self._logger.debug(e) elif rc == 1: self._logger.warning( self. tr("MQTT failed to connect : connection refused - incorrect protocol version" )) elif rc == 2: self._logger.warning( self. tr("MQTT failed to connect : connection refused - invalid client identifier" )) elif rc == 3: self._logger.warning( self. tr("MQTT failed to connect : connection refused - server unavailable" )) elif rc == 4: self._logger.warning( self. tr("MQTT failed to connect : connection refused - bad username or password" )) elif rc == 5: self._logger.warning( self. tr("MQTT failed to connect : connection refused - not authorised" )) else: self._logger.warning("{0} : {1}".format( self.tr("MQTT failed to connect : return code"), rc)) self._logger.debug("Connection state = " + str(self._connectionState)) #__________________________________________________________________ def mqttOnDisconnect(self, client, userdata, rc): self.changeConnectionState(ConnectionState.DISCONNECTED) if self._mqttSwitchingConnection: self._logger.info( self.tr( "Disconnected from MQTT server (switching connection)")) Timer(0, self.mqttConnect).start() return else: self._logger.info(self.tr("Disconnected from MQTT server")) serv = '' if isinstance(userdata, str): try: mydata = eval(userdata) if isinstance(mydata, dict) and 'host' in mydata and 'port' in mydata: serv = mydata['host'] + ':' + str(mydata['port']) except Exception as e: self._logger.info( self.tr("MQTT client userdata not as expected")) self._logger.debug(e) if rc == 0: if serv: self._logger.info("{0} {1}".format( self.tr("MQTT disconnected on request from"), serv)) else: self._logger.info(self.tr("MQTT disconnected on request")) else: Timer(15.000, self.mqttConnect).start() if serv: self._logger.warning("{0}{1} {2} {3}".format( self.tr("MQTT disconnected with rc="), rc, self.tr("from"), serv)) else: self._logger.warning("{0}{1}".format( self.tr("MQTT disconnected with rc="), rc)) self._logger.debug("Connection state = " + str(self._connectionState)) #__________________________________________________________________ def mqttOnLog(self, client, userdata, level, buf): self._logger.debug("MQTT log level {0} : {1}".format(level, buf)) #__________________________________________________________________ def mqttOnMessage(self, client, userdata, msg): if self._mqttSwitchingConnection: self._logger.info( self.tr("Ignore MQTT message (switching connection)")) return message = None try: message = msg.payload.decode(encoding="utf-8", errors="strict") except: pass if not message: self._logger.warning("{0} {1}".format( self.tr("MQTT message decoding failed on"), msg.topic)) return self._logger.debug('Message: ' + message + ' in ' + msg.topic) direction = "—" correspondent = None if self._topicRegexInbox: if "correspondent" in self._topicRegexInbox.pattern: try: m = re.match(self._topicRegexInbox, msg.topic) if m: match = m.groupdict() if match["correspondent"]: correspondent = match["correspondent"] direction = "→" except Exception as e: self._logger.debug(e) else: self._logger.warning( self.tr("No 'correspondent' field in inbox regex : ") + self._topicRegexInbox.pattern) if not correspondent and self._topicRegexOutbox: if "correspondent" in self._topicRegexOutbox.pattern: try: m = re.match(self._topicRegexOutbox, msg.topic) if m: match = m.groupdict() if match["correspondent"]: correspondent = match["correspondent"] direction = "←" except Exception as e: self._logger.debug(e) else: self._logger.warning( self.tr("No 'correspondent' field in outbox regex : ") + self._topicRegexInbox.pattern) if not correspondent and self._topicRegexDefault: if "correspondent" in self._topicRegexDefault.pattern: try: m = re.match(self._topicRegexDefault, msg.topic) if m: match = m.groupdict() if match["correspondent"]: correspondent = match["correspondent"] except Exception as e: self._logger.debug(e) else: self._logger.warning( self.tr("No 'correspondent' field in default regex : ") + self._topicRegexInbox.pattern) if not correspondent: self._logger.warning( self.tr("No correspondent defined for topic : ") + msg.topic) now = time.time() msec = repr(now).split('.')[1][:3] timestamp = time.strftime("[%d/%m/%Y %H:%M:%S.{}]".format(msec), time.localtime(now)) self.messageReceived.emit(correspondent, msg.topic, message, timestamp, direction) #__________________________________________________________________ def mqttOnPublish(self, client, userdata, mid): self._logger.debug("userdata=%s mid=%s", userdata, mid) self._logger.info("{0} : mid={1}".format( self.tr("MQTT published"), mid)) # mid is a number (message id) #__________________________________________________________________ def mqttOnSubscribe(self, client, userdata, mid, granted_qos): self._logger.debug("mid=%s granted_qos=%s", mid, granted_qos) # granted_qos is (2,) self._logger.info("{0} : {1} {2} {3}".format( self.tr("MQTT susbcribed to"), mid, self.tr("with QoS"), granted_qos)) # mid is a number (count) #__________________________________________________________________ def mqttOnUnsubscribe(self, client, userdata, mid): self._logger.debug("mid=%s", mid) self._logger.info( "{0} : {1}".format(self.tr("MQTT unsusbcribed from"), mid)) # mid is a number (message id) if self._mqttSwitchingConnection: Timer(0, self.mqttDisconnect).start() #__________________________________________________________________ def mqttReconnect(self): self._logger.info(self.tr("MQTT reconnecting")) if self._mqttSwitchingConnection: self._logger.info( self.tr("Ignore MQTT reconnecting (switching connection)")) return try: self._mqttClient.reconnect() except Exception as e: self._logger.error(self.tr("MQTT reconnection call failed")) Timer(15.000, self.mqttConnect).start() self._logger.debug(e) #__________________________________________________________________ @pyqtSlot() def reload(self): reg = QSettings() if "current session" in reg.childKeys() and reg.value( "current session", '').strip() and reg.value( "current session", '').strip() in reg.childGroups(): self._session = reg.value("current session") self._logger.info(self.tr("Current session : ") + self._session) self.setWindowTitle(self._session) if self._session not in reg.childGroups(): reg.beginGroup(self._session) reg.setValue("host", self._host) reg.setValue("port", self._port) reg.setValue("root topic", self._rootTopic) reg.endGroup() else: reg.beginGroup(self._session) self._host = reg.value("host", 'localhost') try: self._port = reg.value("port", 1883, type=int) except: pass self._rootTopic = reg.value("root topic", '') reg.endGroup() if "current session" in reg.childKeys() and not reg.value( "current session", '') in reg.childGroups(): reg.remove("current session") self._mqttSwitchingConnection = False self._mqttSwitchingSubscription = False if self._host != self._mqttServerHost or self._port != self._mqttServerPort: self._mqttSwitchingConnection = True elif self._rootTopic != self._mqttRootTopic: self._mqttSwitchingSubscription = True self._mqttServerHost = self._host self._mqttServerPort = self._port self._mqttRootTopic = self._rootTopic self._mqttSubTopic = '#' if self._rootTopic: self._mqttSubTopic = self._rootTopic + '/#' reg.beginGroup(self._session) inbox = reg.value("param inbox", 'inbox') outbox = reg.value("param outbox", 'outbox') regexInbox = reg.value("regex inbox", r'^%ROOT%/(?P<correspondent>.+)/%INBOX%$') regexOutbox = reg.value("regex outbox", r'^%ROOT%/(?P<correspondent>.+)/%OUTBOX%$') regexDefault = reg.value("regex default", r'.*/(?P<correspondent>[^/]+)/[^/]+$') reg.endGroup() regexInbox = regexInbox.replace("%ROOT%", self._rootTopic).replace( "%INBOX%", inbox) regexOutbox = regexOutbox.replace("%ROOT%", self._rootTopic).replace( "%OUTBOX%", outbox) self._topicRegexInbox = None try: self._topicRegexInbox = re.compile(regexInbox) except Exception as e: self._logger.error(self.tr("Failed to compile inbox regex")) self._logger.debug(e) self._topicRegexOutbox = None try: self._topicRegexOutbox = re.compile(regexOutbox) except Exception as e: self._logger.error(self.tr("Failed to compile outbox regex")) self._logger.debug(e) self._topicRegexDefault = None try: self._topicRegexDefault = re.compile(regexDefault) except Exception as e: self._logger.error( self.tr("Failed to compile topic default regex")) self._logger.debug(e) index = self._tabWidget.currentIndex() current = self._tabWidget.currentWidget() for index in (1, self._tabWidget.count()): try: self._displays.remove(self._tabWidget.widget(index)) self._tabWidget.widget(index).deleteLater() self._tabWidget.removeTab(index) except Exception as e: self._logger.error( self. tr("Failed to remove observation : not in display list (index=" ) + str(index) + self.tr(")")) self._logger.debug(e) dspmsg = '' for d in self._displays: if dspmsg: dspmsg += ' | ' else: dspmsg = 'Displays : ' dspmsg += d.title() self._logger.debug(dspmsg) reg.beginGroup(self._session) for i in reg.childGroups(): self.addDisplay(i) reg.endGroup() QCoreApplication.processEvents() if self._mqttSwitchingConnection: self.switchConnection() elif self._mqttSwitchingSubscription: self.switchSubscription() #__________________________________________________________________ @pyqtSlot() def removeCurrentDisplay(self): index = self._tabWidget.currentIndex() current = self._tabWidget.currentWidget() if index > 0 and current == self.sender(): try: title = self._tabWidget.tabText(index) self._tabWidget.removeTab(index) if current in self._displays: self._displays.remove(self.sender()) self.sender().deleteLater() self._logger.info("{0} : {1}".format( self.tr("Remove observation"), title)) reg = QSettings() reg.beginGroup(self._session) reg.remove(title) reg.endGroup() reg.sync() else: self._logger.warning( self. tr("Failed to remove observation : not in display list (index=" ) + str(index) + self.tr(")")) except Exception as e: self._logger.error( self. tr("Failed to remove observation : not in display list (index=" ) + str(index) + self.tr(")")) self._logger.debug(e) dspmsg = '' for d in self._displays: if dspmsg: dspmsg += ' | ' else: dspmsg = 'Displays : ' dspmsg += d.title() self._logger.debug(dspmsg) #__________________________________________________________________ @pyqtSlot() def restoreWindow(self): self.resize(QSize(400, 400)) self.move(QPoint(200, 200)) #__________________________________________________________________ def resizeEvent(self, event): if self.isVisible(): Timer(0, self.layoutSaveSettings).start() #__________________________________________________________________ @pyqtSlot() def settings(self): dlg = ObserverSettingsDialog(self._logger, self._session) dlg.move(self.pos() + QPoint(20, 20)) dlg.correspondentRegex.connect(self.settingsRegex) dlg.reloadSession.connect(self.reload) dlg.exec() reg = QSettings() reg.beginGroup(self._session) self._host = reg.value("host", 'localhost') try: self._port = reg.value("port", 1883, type=int) except: self._port = 1883 self._rootTopic = reg.value("root topic", '') reg.endGroup() if self._host != self._mqttServerHost or self._port != self._mqttServerPort: self.switchConnection() elif self._rootTopic != self._mqttRootTopic: self.switchSubscription() #__________________________________________________________________ @pyqtSlot() def settingsRegex(self): dlg = ObserverRegexDialog(self._logger, self._session) dlg.move(self.pos() + QPoint(20, 20)) dlg.exec() reg = QSettings() reg.beginGroup(self._session) inbox = reg.value("param inbox", 'inbox') outbox = reg.value("param outbox", 'outbox') regexInbox = reg.value("regex inbox", r'^%ROOT%/(?P<correspondent>.+)/%INBOX%$') regexOutbox = reg.value("regex outbox", r'^%ROOT%/(?P<correspondent>.+)/%OUTBOX%$') regexDefault = reg.value("regex default", r'.*/(?P<correspondent>[^/]+)/[^/]+$') reg.endGroup() regexInbox = regexInbox.replace("%ROOT%", self._rootTopic).replace( "%INBOX%", inbox) regexOutbox = regexOutbox.replace("%ROOT%", self._rootTopic).replace( "%OUTBOX%", outbox) self._topicRegexInbox = None try: self._topicRegexInbox = re.compile(regexInbox) except Exception as e: self._logger.error( self.tr("Failed to compile inbox regex :") + regexInbox) self._logger.debug(e) self._topicRegexOutbox = None try: self._topicRegexOutbox = re.compile(regexOutbox) except Exception as e: self._logger.error( self.tr("Failed to compile outbox regex :") + regexOutbox) self._logger.debug(e) self._topicRegexDefault = None try: self._topicRegexDefault = re.compile(regexDefault) except Exception as e: self._logger.error( self.tr("Failed to compile topic default regex :") + regexDefault) self._logger.debug(e) #__________________________________________________________________ def start(self): try: self._mqttClient.on_connect = self.mqttOnConnect self._mqttClient.on_disconnect = self.mqttOnDisconnect self._mqttClient.on_log = self.mqttOnLog self._mqttClient.on_message = self.mqttOnMessage self._mqttClient.on_publish = self.mqttOnPublish self._mqttClient.on_subscribe = self.mqttOnSubscribe self._mqttClient.on_unsubscribe = self.mqttOnUnsubscribe Timer(0, self.mqttConnect).start() except: self._logger.error( self.tr("Can't start MQTT (check definitions in .INI)")) msgbox = QMessageBox() msgbox.setWindowTitle(self.tr("Observer")) msgbox.setWindowIcon(QIcon(':/view-eye.svg')) msgbox.setText( self.tr("Failed to set MQTT client !") + "<br><br><i>" + self.tr("Application will be closed.") + "</i><br>") msgbox.setStandardButtons(QMessageBox.Close) msgbox.setAttribute(Qt.WA_DeleteOnClose) msgbox.setWindowFlags(msgbox.windowFlags() & ~Qt.WindowContextHelpButtonHint) msgbox.button(QMessageBox.Close).setText(self.tr("Close")) msgbox.resize(QSize(400, 300)) msgbox.exec() self._logger.info(self.tr("Done")) Timer(0, QCoreApplication.quit).start() self._logger.debug("Connection state = " + str(self._connectionState)) #__________________________________________________________________ def switchConnection(self): self._mqttSwitchingConnection = True self.resetDisplays.emit() current_topic = self._mqttSubTopic if self._connectionState == ConnectionState.CONNECTED or self._connectionState == ConnectionState.CONNECTING: try: (result, mid) = self._mqttClient.unsubscribe(current_topic) self._logger.info("{0} {1} : {2}".format( self.tr("MQTT unsubscribing from"), mid, current_topic)) except Exception as e: self._logger.debug(e) Timer(0, self.mqttDisconnect).start() else: Timer(0, self.mqttConnect).start() self._logger.debug("Connection state = " + str(self._connectionState)) #__________________________________________________________________ def switchSubscription(self): self.resetDisplays.emit() current_topic = self._mqttSubTopic self._mqttRootTopic = self._rootTopic if self._rootTopic: self._mqttSubTopic = self._rootTopic + '/#' else: self._mqttSubTopic = '#' cloud = self._mqttServerHost + ':' + str(self._mqttServerPort) if self._mqttRootTopic: cloud += '/' + self._mqttRootTopic + '/#' else: cloud += '/#' self._cloudLabel.setText(cloud) self.resetDisplays.emit() if self._connectionState == ConnectionState.CONNECTED: try: (result, mid) = self._mqttClient.unsubscribe(current_topic) self._logger.info("{0} {1} : {2}".format( self.tr("MQTT unsubscribing from"), mid, current_topic)) (result, mid) = self._mqttClient.subscribe(self._mqttSubTopic) self._logger.info("{0} {1} : {2}".format( self.tr("MQTT subscribing to"), mid, self._mqttSubTopic)) except Exception as e: self._logger.debug(e) else: Timer(0, self.mqttReconnect).start() self._logger.debug("Connection state = " + str(self._connectionState))
class ImageToolWindow(QMainWindow, _AbstractWindowMixin): """ImageToolWindow class. This is the second Main GUI which focuses on manipulating the image , e.g. selecting ROI, masking, normalization, for different data analysis scenarios. """ _title = "Image tool" _root_dir = osp.dirname(osp.abspath(__file__)) _WIDTH, _HEIGHT = config['GUI_IMAGE_TOOL_SIZE'] mask_file_path_sgn = pyqtSignal(str) class TabIndex(IntEnum): OVERVIEW = 0 GAIN_OFFSET = 1 REFERENCE = 2 AZIMUTHAL_INTEG_1D = 3 GEOMETRY = 4 IMAGE_TRANSFORM = 5 def __init__(self, queue, *, pulse_resolved=True, require_geometry=True, parent=None): """Initialization. :param deque queue: data queue. :param bool pulse_resolved: whether the related data is pulse-resolved or not. :param bool require_geometry: whether the detector requires a geometry to assemble its modules. """ super().__init__(parent=parent) self._queue = queue self._pulse_resolved = pulse_resolved self._require_geometry = require_geometry self._mediator = Mediator() try: title = parent.title + " - " + self._title except AttributeError: title = self._title # for unit test where parent is None self.setWindowTitle(title) self._ctrl_widgets = [] # ----------------------------- # ctrl panel # ----------------------------- self._bulletin_view = self.createView(BulletinView) self._image_ctrl_widget = self.createCtrlWidget(ImageCtrlWidget) self._mask_ctrl_widget = self.createCtrlWidget(MaskCtrlWidget) # ----------------------------- # view panel # ----------------------------- self._views_tab = QTabWidget() self._corrected_view = self.createView(CorrectedView) self._calibration_view = self.createView(CalibrationView) self._reference_view = self.createView(ReferenceView) self._azimuthal_integ_1d_view = self.createView(AzimuthalInteg1dView) self._geometry_view = self.createView(GeometryView) self._transform_view = self.createView(TransformView) # Whether the view is updated automatically self._auto_update = True self._cw = QWidget() self.setCentralWidget(self._cw) self.initUI() self.initConnections() self.updateMetaData() self.resize(self._WIDTH, self._HEIGHT) def initUI(self): """Override.""" corrected_tab_idx = self._views_tab.addTab(self._corrected_view, "Overview") cali_idx = self._views_tab.addTab(self._calibration_view, "Gain / offset") ref_idx = self._views_tab.addTab(self._reference_view, "Reference") azimuthal_integ_tab_idx = self._views_tab.addTab( self._azimuthal_integ_1d_view, "Azimuthal integration 1D") geom_idx = self._views_tab.addTab(self._geometry_view, "Geometry") if not self._require_geometry: self._views_tab.setTabEnabled(geom_idx, False) transform_idx = self._views_tab.addTab(self._transform_view, "Feature extraction") assert (corrected_tab_idx == self.TabIndex.OVERVIEW) assert (cali_idx == self.TabIndex.GAIN_OFFSET) assert (ref_idx == self.TabIndex.REFERENCE) assert (azimuthal_integ_tab_idx == self.TabIndex.AZIMUTHAL_INTEG_1D) assert (geom_idx == self.TabIndex.GEOMETRY) assert (transform_idx == self.TabIndex.IMAGE_TRANSFORM) ctrl_panel = QWidget() ctrl_panel_layout = QVBoxLayout() ctrl_panel_layout.addWidget(self._bulletin_view) ctrl_panel_layout.addWidget(self._image_ctrl_widget) ctrl_panel_layout.addWidget(self._mask_ctrl_widget) ctrl_panel_layout.addStretch(1) ctrl_panel.setLayout(ctrl_panel_layout) ctrl_panel.setFixedWidth(ctrl_panel.minimumSizeHint().width() + 10) layout = QHBoxLayout() layout.addWidget(self._views_tab) layout.addWidget(ctrl_panel) self._cw.setLayout(layout) self.layout().setContentsMargins(0, 0, 0, 0) def initConnections(self): self._image_ctrl_widget.auto_update_cb.toggled.connect( self.onAutoUpdateToggled) mediator = self._mediator self._image_ctrl_widget.update_image_btn.clicked.connect( self.onUpdateWidgets) self._image_ctrl_widget.auto_level_btn.clicked.connect( mediator.reset_image_level_sgn) self._image_ctrl_widget.save_image_btn.clicked.connect( self._corrected_view.onSaveImage) self._mask_ctrl_widget.draw_mask_btn.toggled.connect( self._corrected_view.onDrawMask) self._mask_ctrl_widget.erase_mask_btn.toggled.connect( self._corrected_view.onEraseMask) self._mask_ctrl_widget.remove_btn.clicked.connect( self._corrected_view.onRemoveMask) self._mask_ctrl_widget.load_btn.clicked.connect( self._corrected_view.onLoadMask) self._mask_ctrl_widget.save_btn.clicked.connect( self._corrected_view.onSaveMask) self._mask_ctrl_widget.mask_save_in_modules_cb.toggled.connect( self._corrected_view.onMaskSaveInModulesChange) self._views_tab.tabBarClicked.connect(self.onViewsTabClicked) self._views_tab.currentChanged.connect(self.onViewsTabChanged) self._transform_view.transform_type_changed_sgn.connect( self._onTransformViewTypeChanged) def onStart(self): for widget in self._ctrl_widgets: widget.onStart() def onStop(self): for widget in self._ctrl_widgets: widget.onStop() def createView(self, view_class): return view_class(pulse_resolved=self._pulse_resolved, parent=self) def createCtrlWidget(self, widget_class, *args, **kwargs): """Register a ctrl widget. Ctrl widgets reside in (views of) ImageToolWindow should explicitly call this method to be registered. """ widget = widget_class(*args, pulse_resolved=self._pulse_resolved, require_geometry=self._require_geometry, **kwargs) self._ctrl_widgets.append(widget) return widget def updateMetaData(self): """Update metadata from all the ctrl widgets. :returns bool: True if all metadata successfully parsed and emitted, otherwise False. """ for widget in self._ctrl_widgets: if not widget.updateMetaData(): return False return True def loadMetaData(self): """Load metadata from Redis and set child control widgets.""" for widget in self._ctrl_widgets: widget.loadMetaData() def reset(self): """Override.""" pass @pyqtSlot() def onUpdateWidgets(self): """Used for updating manually.""" self._updateWidgets(True) def updateWidgetsF(self): """Override.""" self._updateWidgets(self._auto_update) def _updateWidgets(self, auto_update): if len(self._queue) == 0: return data = self._queue[0] # update bulletin self._bulletin_view.updateF(data, auto_update) # update other ImageView/PlotWidget in the activated tab self._views_tab.currentWidget().updateF(data, auto_update) @pyqtSlot(int) def onViewsTabClicked(self, idx): if self._views_tab.currentIndex() == idx: return self._views_tab.currentWidget().onDeactivated() @pyqtSlot(int) def onViewsTabChanged(self, idx): self._views_tab.currentWidget().onActivated() if self._views_tab.currentIndex() != self.TabIndex.IMAGE_TRANSFORM: self._updateWidgets(True) # force update self._mask_ctrl_widget.setInteractiveButtonsEnabled( self._views_tab.currentIndex() == self.TabIndex.OVERVIEW) @pyqtSlot(bool) def onAutoUpdateToggled(self, state): self._auto_update = state @pyqtSlot(int) def _onTransformViewTypeChanged(self, tp): if self._views_tab.currentIndex() == self.TabIndex.IMAGE_TRANSFORM: self._updateWidgets(True)
class Main(QMainWindow): def __init__(self): global downloads_list_file QMainWindow.__init__(self) self.setWindowIcon(QIcon(":/quartz.png")) self.setWindowTitle("Quartz Browser - "+__version__) # Window Properties self.history = [] self.downloads = [] self.confirm_before_quit = True # Create required directories for folder in [configdir, icon_dir, thumbnails_dir]: if not os.path.exists(folder): os.mkdir(folder) # Import and Apply Settings self.setAttribute(Qt.WA_DeleteOnClose) self.settings = QSettings(1, 0, "quartz-browser","Quartz", self) self.opensettings() self.websettings = QWebSettings.globalSettings() self.websettings.setAttribute(QWebSettings.DnsPrefetchEnabled, True) self.websettings.setMaximumPagesInCache(10) self.websettings.setIconDatabasePath(icon_dir) self.websettings.setAttribute(QWebSettings.JavascriptCanOpenWindows, True) self.websettings.setAttribute(QWebSettings.JavascriptCanCloseWindows, True) if webkit.enable_adblock: self.websettings.setUserStyleSheetUrl(QUrl.fromLocalFile(program_dir + 'userContent.css')) # Import Downloads and Bookmarks self.dwnldsmodel = DownloadsModel(self.downloads, QApplication.instance()) self.dwnldsmodel.deleteDownloadsRequested.connect(self.deleteDownloads) imported_downloads = importDownloads(downloads_list_file) for [filepath, url, totalsize, timestamp] in imported_downloads: try : # Check if downloads.txt is valid tymstamp = float(timestamp) except : self.downloads = [] exportDownloads(downloads_list_file, []) print("Error in importing Downloads.") break old_download = Download(networkmanager) old_download.loadDownload(filepath, url, totalsize, timestamp) old_download.datachanged.connect(self.dwnldsmodel.datachanged) self.downloads.append(old_download) self.bookmarks = importBookmarks(configdir+"bookmarks.txt") self.favourites = importFavourites(configdir + 'favourites.txt') # Find and set icon theme name for theme_name in ['Adwaita', 'Gnome', 'Tango']: if os.path.exists('/usr/share/icons/' + theme_name): QIcon.setThemeName(theme_name) break self.initUI() self.resize(1024,714) def initUI(self): ############################### Create Actions ############################## self.loadimagesaction = QAction("Load Images",self) self.loadimagesaction.setCheckable(True) self.loadimagesaction.triggered.connect(self.loadimages) self.javascriptmode = QAction("Enable Javascript",self) self.javascriptmode.setCheckable(True) self.javascriptmode.triggered.connect(self.setjavascript) self.useragent_mode_desktop = QAction("Desktop",self) self.useragent_mode_desktop.setCheckable(True) self.useragent_mode_desktop.triggered.connect(self.setUserAgentDesktop) self.useragent_mode_mobile = QAction("Mobile",self) self.useragent_mode_mobile.setCheckable(True) self.useragent_mode_mobile.triggered.connect(self.setUserAgentMobile) self.useragent_mode_custom = QAction("Custom",self) self.useragent_mode_custom.setCheckable(True) self.useragent_mode_custom.triggered.connect(self.setUserAgentCustom) ################ Add Actions to Menu #################### # This sub-menu sets useragent mode to desktop/mobile/custom self.useragentMenu = QMenu('UserAgent', self) self.useragentMenu.setIcon(QIcon(":/computer.png")) self.useragentMenu.addAction(self.useragent_mode_desktop) self.useragentMenu.addAction(self.useragent_mode_mobile) self.useragentMenu.addAction(self.useragent_mode_custom) # This is main menu self.menu = QMenu(self) self.menu.addAction(QIcon(":/edit-find.png"), "Find Text", self.findmode, "Ctrl+F") self.menu.addAction(QIcon(":/list-add.png"), "Zoom In", self.zoomin, "Ctrl++") self.menu.addAction(QIcon(":/list-remove.png"), "Zoom Out", self.zoomout, "Ctrl+-") self.menu.addAction(QIcon(":/view-fullscreen.png"), "Toggle Fullscreen", self.fullscreenmode, "F11") self.menu.addSeparator() self.menu.addAction(self.loadimagesaction) self.menu.addAction(self.javascriptmode) self.menu.addMenu(self.useragentMenu) self.menu.addAction(QIcon(":/applications-system.png"), "Settings", self.settingseditor, "Ctrl+,") self.menu.addSeparator() self.menu.addAction(QIcon(":/image-x-generic.png"), "Save as Image", self.saveAsImage, "Shift+Ctrl+S") self.menu.addAction(QIcon(":/text-html.png"), "Save as HTML", self.saveashtml, "Ctrl+S") self.menu.addAction(QIcon(":/document-print.png"), "Print to PDF", self.printpage, "Ctrl+P") self.menu.addSeparator() self.menu.addAction(QIcon(":/process-stop.png"), "Quit", self.forceClose, "Ctrl+Q") self.bmk_menu = QMenu(self) self.bmk_menu.addAction(QIcon(':/add-bookmark.png'), 'Add Bookmark', self.addbookmark) self.bmk_menu.addAction(QIcon(':/favourites.png'), 'Add to Home', self.addToFavourites) ############################### Create Gui Parts ############################## self.centralwidget = QWidget(self) self.setCentralWidget(self.centralwidget) grid = QGridLayout(self.centralwidget) grid.setSpacing(1) grid.setContentsMargins(0,2,0,0) self.toolBar = QWidget(self) horLayout = QHBoxLayout(self.toolBar) horLayout.setSpacing(1) horLayout.setContentsMargins(0,2,0,0) self.addtabBtn = QPushButton(QIcon(":/add-tab.png"), "",self) self.addtabBtn.setToolTip("New Tab\n[Ctrl+Tab]") self.addtabBtn.setShortcut("Ctrl+Tab") self.addtabBtn.clicked.connect(self.addTab) self.reload = QPushButton(QIcon(":/refresh.png"), "",self) self.reload.setMinimumSize(35,26) self.reload.setToolTip("Reload/Stop\n [Space]") self.reload.setShortcut("Space") self.reload.clicked.connect(self.Reload) self.back = QPushButton(QIcon(":/prev.png"), "", self) self.back.setToolTip("Previous Page") self.back.setMinimumSize(35,26) self.back.clicked.connect(self.Back) self.forw = QPushButton(QIcon(":/next.png"), "",self) self.forw.setToolTip("Next Page") self.forw.setMinimumSize(35,26) self.forw.clicked.connect(self.Forward) self.homeBtn = QPushButton(QIcon(":/home.png"), "",self) self.homeBtn.setToolTip("Go Home") self.homeBtn.clicked.connect(self.goToHome) self.videoDownloadButton = QPushButton(QIcon(":/video-dwnld.png"), "", self) self.videoDownloadButton.setToolTip("Download this Video") self.videoDownloadButton.clicked.connect(self.downloadVideo) self.videoDownloadButton.hide() self.addbookmarkBtn = QToolButton(self) self.addbookmarkBtn.setIcon(QIcon(":/add-bookmark.png")) self.addbookmarkBtn.setToolTip("Add Bookmark") self.addbookmarkBtn.setMenu(self.bmk_menu) self.addbookmarkBtn.setPopupMode(QToolButton.InstantPopup) self.menuBtn = QToolButton(self) self.menuBtn.setIcon(QIcon(":/menu.png")) self.menuBtn.setMenu(self.menu) self.menuBtn.setPopupMode(QToolButton.InstantPopup) self.bookmarkBtn = QPushButton(QIcon(":/bookmarks.png"), "", self) self.bookmarkBtn.setToolTip("Manage Bookmarks\n [Alt+B]") self.bookmarkBtn.setShortcut("Alt+B") self.bookmarkBtn.clicked.connect(self.managebookmarks) self.historyBtn = QPushButton(QIcon(":/history.png"), "", self) self.historyBtn.setShortcut("Alt+H") self.historyBtn.setToolTip("View History\n [Alt+H]") self.historyBtn.clicked.connect(self.viewhistory) self.downloadsBtn = QPushButton(QIcon(":/download.png"), "", self) self.downloadsBtn.setToolTip("Download Manager") self.downloadsBtn.clicked.connect(self.download_manager) self.find = QPushButton(self) self.find.setText("Find/Next") self.find.clicked.connect(self.findnext) self.find.hide() self.findprev = QPushButton(self) self.findprev.setText("Backward") self.findprev.clicked.connect(self.findback) self.findprev.hide() self.cancelfind = QPushButton(self) self.cancelfind.setText("Cancel") self.cancelfind.clicked.connect(self.cancelfindmode) self.cancelfind.hide() self.pbar = QProgressBar(self) self.pbar.setTextVisible(False) self.pbar.setStyleSheet("QProgressBar::chunk { background-color: #bad8ff; }") pbarLayout = QGridLayout(self.pbar) pbarLayout.setContentsMargins(0,0,0,0) self.line = webkit.UrlEdit(self.pbar) self.line.openUrlRequested.connect(self.Enter) self.line.textEdited.connect(self.urlsuggestions) self.line.downloadRequested.connect(self.download_requested_file) pbarLayout.addWidget(self.line) self.listmodel = QStringListModel(self) self.completer = QCompleter(self.listmodel, self.line) self.completer.setCompletionMode(1) self.completer.setMaxVisibleItems(10) self.line.setCompleter(self.completer) self.statusbar = QLabel(self) self.statusbar.setStyleSheet("QLabel { font-size: 12px; border-radius: 2px; padding: 2px; background: palette(highlight); color: palette(highlighted-text); }") self.statusbar.setMaximumHeight(16) self.statusbar.hide() self.tabWidget = QTabWidget(self) self.tabWidget.setTabsClosable(True) self.tabWidget.setDocumentMode(True) self.tabWidget.tabBar().setExpanding(True) self.tabWidget.tabBar().setElideMode(Qt.ElideMiddle) self.tabWidget.currentChanged.connect(self.onTabSwitch) self.tabWidget.tabCloseRequested.connect(self.closeTab) self.addTab() self.applysettings() # grid.addWidget(self.toolBar, 0,0, 1,1) for widget in [self.addtabBtn, self.back, self.forw, self.reload, self.homeBtn, self.videoDownloadButton, self.pbar, self.find, self.findprev, self.cancelfind, self.addbookmarkBtn, self.menuBtn, self.bookmarkBtn, self.historyBtn, self.downloadsBtn]: horLayout.addWidget(widget) grid.addWidget(self.tabWidget, 1, 0, 1, 1) #------------------------------------------------------------------------------------------ # Must be at the end, otherwise cause segmentation fault # self.status = self.statusBar() def addTab(self, webview_tab=None): """ Creates a new tab and add to QTabWidget applysettings() must be called after adding each tab""" if not webview_tab: webview_tab = webkit.MyWebView(self.tabWidget, networkmanager) webview_tab.windowCreated.connect(self.addTab) webview_tab.loadStarted.connect(self.onLoadStart) webview_tab.loadFinished.connect(self.onLoadFinish) webview_tab.loadProgress.connect(self.onProgress) webview_tab.urlChanged.connect(self.onUrlChange) webview_tab.titleChanged.connect(self.onTitleChange) webview_tab.iconChanged.connect(self.onIconChange) webview_tab.videoListRequested.connect(self.getVideos) webview_tab.page().printRequested.connect(self.printpage) webview_tab.page().downloadRequested.connect(self.download_requested_file) webview_tab.page().unsupportedContent.connect(self.handleUnsupportedContent) webview_tab.page().linkHovered.connect(self.onLinkHover) webview_tab.page().windowCloseRequested.connect(self.closeRequestedTab) self.tabWidget.addTab(webview_tab, "( Untitled )") if self.tabWidget.count()==1: self.tabWidget.tabBar().hide() else: self.tabWidget.tabBar().show() self.tabWidget.setCurrentIndex(self.tabWidget.count()-1) def closeTab(self, index=None): """ Closes tab, hides tabbar if only one tab remains""" if index==None: index = self.tabWidget.currentIndex() widget = self.tabWidget.widget(index) self.tabWidget.removeTab(index) widget.deleteLater() # Auto hide tab bar, when no. of tab widget is one if self.tabWidget.count()==1: self.tabWidget.tabBar().hide() def closeRequestedTab(self): """ Close tab requested by the page """ webview = self.sender().view() index = self.tabWidget.indexOf(webview) self.closeTab(index) def Enter(self): url = self.line.text() if url == 'about:home': self.goToHome() else: self.GoTo(url) def GoTo(self, url): URL = QUrl.fromUserInput(url) self.tabWidget.currentWidget().openLink(URL) self.line.setText(url) self.tabWidget.currentWidget().setFocus() def goToHome(self): self.GoTo(homepage) loop = QEventLoop() QTimer.singleShot(10, loop.quit) loop.exec_() document = self.tabWidget.currentWidget().page().mainFrame().documentElement() gallery = document.findFirst('div') for i, fav in enumerate(self.favourites): title, url, img = fav[0], fav[1], thumbnails_dir+fav[2] child = '<div class="photo"> <a href="{}"><img src="{}"></a><div class="desc">{}</div></div>'.format(url, img, title) gallery.appendInside(child) def onLoadStart(self): webview = self.sender() if webview is self.tabWidget.currentWidget(): self.reload.setIcon(QIcon(":/stop.png")) def onProgress(self, progress): webview = self.sender() if webview is self.tabWidget.currentWidget() and webview.loading: self.pbar.setValue(progress) def onLoadFinish(self, ok): webview = self.sender() if webview is self.tabWidget.currentWidget(): self.reload.setIcon(QIcon(":/refresh.png")) self.pbar.reset() url = self.line.text() self.handleVideoButton(url) def onTabSwitch(self, index): """ Updates urlbox, refresh icon, progress bar on switching tab""" webview = self.tabWidget.currentWidget() if webview.loading == True: self.reload.setIcon(QIcon(":/stop.png")) self.pbar.setValue(webview.progressVal) else: self.reload.setIcon(QIcon(":/refresh.png")) self.pbar.reset() url = webview.url().toString() if url == homepage : url = 'about:home' self.line.setText(url) self.statusbar.hide() self.onIconChange(webview) self.handleVideoButton(url) def onUrlChange(self,url): url = url.toString() if url == homepage : url = 'about:home' webview = self.sender() if webview is self.tabWidget.currentWidget(): self.line.setText(url) self.onIconChange(webview) self.handleVideoButton(url) def onTitleChange(self, title): webview = self.sender() index = self.tabWidget.indexOf(webview) if not title == '': self.tabWidget.tabBar().setTabText(index, title) url = webview.url().toString() for item in self.history: # Removes the old item, inserts new same item on the top if url == item[1]: self.history.remove(item) self.history.insert(0, [title, url]) def onIconChange(self, webview=None): if not webview: webview = self.sender() icon = webview.icon() if icon.isNull(): icon = QIcon(':/quartz.png') if webview is self.tabWidget.currentWidget(): self.line.setIcon(icon) index = self.tabWidget.indexOf(webview) self.tabWidget.setTabIcon(index, icon) def onLinkHover(self, url): if url=="": self.statusbar.hide() return self.statusbar.setText(url) self.statusbar.adjustSize() self.statusbar.show() self.statusbar.move(QPoint(0, self.height()-self.statusbar.height())) def Back(self): self.tabWidget.currentWidget().back() def Forward(self): self.tabWidget.currentWidget().forward() def Reload(self): if self.tabWidget.currentWidget().loading: self.tabWidget.currentWidget().stop() else: if self.line.text() == 'about:home': self.goToHome() else: self.tabWidget.currentWidget().reload() def urlsuggestions(self, text): """ Creates the list of url suggestions for URL box """ suggestions = [] if not webkit.find_mode_on: for [title, url] in self.history: if text in url: suggestions.insert(0, url) for [title, address] in self.bookmarks: if text in address: suggestions.insert(0, address) self.listmodel.setStringList( suggestions ) def handleVideoButton(self, url): if youtube.validYoutubeUrl(url): self.videoDownloadButton.show() return frames = [self.tabWidget.currentWidget().page().mainFrame()] frames += frames[0].childFrames() for frame in frames: video = frame.findFirstElement('video') if not video.isNull(): self.videoDownloadButton.show() return self.videoDownloadButton.hide() ##################### Downloading and Printing ######################## def download_requested_file(self, networkrequest): """ Gets called when the page requests a file to be downloaded """ reply = networkmanager.get(networkrequest) self.handleUnsupportedContent(reply) def handleUnsupportedContent(self, reply, preset_filename=None, page_url=None): """ This is called when url content is a downloadable file. e.g- pdf,mp3,mp4 """ if reply.rawHeaderList() == []: loop = QEventLoop() reply.metaDataChanged.connect(loop.quit) QTimer.singleShot(5000, loop.quit) loop.exec_() if reply.hasRawHeader(b'Location'): URL = QUrl.fromUserInput(str_(reply.rawHeader(b'Location'))) reply.abort() reply = networkmanager.get(QNetworkRequest(URL)) self.handleUnsupportedContent(reply, preset_filename) return for (title, header) in reply.rawHeaderPairs(): print( str_(title) + "-> " + str_(header) ) # copy url to clipboard QApplication.clipboard().setText(reply.url().toString()) # Get filename and mimetype mimetype = None if reply.hasRawHeader(b'Content-Type'): mimetype = str_(reply.rawHeader(b'Content-Type')).split(';')[0] # eg - audio/mpeg; name="" content_name = str_(reply.rawHeader(b'Content-Disposition')) if preset_filename: filename = preset_filename else: filename = filenameFromHeader(content_name) if filename == '': filename = filenameFromUrl(reply.url().toString()) filename = validateFileName(filename, mimetype) # Create downld Confirmation dialog dlDialog = DownloadDialog(self) dlDialog.filenameEdit.setText(filename) # Get filesize if reply.hasRawHeader(b'Content-Length'): filesize = reply.header(1) if filesize >= 1048576 : file_size = "{} M".format(round(float(filesize)/1048576, 2)) elif 1023 < filesize < 1048576 : file_size = "{} k".format(round(float(filesize)/1024, 1)) else: file_size = "{} B".format(filesize) dlDialog.labelFileSize.setText(file_size) # Get filetype and resume support info if mimetype: dlDialog.labelFileType.setText(mimetype) if reply.hasRawHeader(b'Accept-Ranges') or reply.hasRawHeader(b'Content-Range'): dlDialog.labelResume.setText("True") # Execute dialog and show confirmation if dlDialog.exec_()== QDialog.Accepted: filepath = dlDialog.folder + dlDialog.filenameEdit.text() url = reply.url().toString() if self.useexternaldownloader: download_externally(url, self.externaldownloader) reply.abort() reply.deleteLater() return global downloads_list_file newdownload = Download(networkmanager, page_url) newdownload.startDownload(reply, filepath) newdownload.datachanged.connect(self.dwnldsmodel.datachanged) self.downloads.insert(0, newdownload) imported_downloads = importDownloads(downloads_list_file) imported_downloads.insert(0, [filepath, url, str(newdownload.totalsize), newdownload.timestamp]) exportDownloads(downloads_list_file, imported_downloads) else: reply.abort() reply.deleteLater() def download_manager(self): """ Opens download manager dialog """ dialog = QDialog(self) downloads_dialog = Downloads_Dialog() downloads_dialog.setupUi(dialog, self.dwnldsmodel) dialog.exec_() def deleteDownloads(self, timestamps): global downloads_list_file imported_downloads = importDownloads(downloads_list_file) exported_downloads = [] for download in imported_downloads: if download[-1] not in timestamps: exported_downloads.append(download) exportDownloads(downloads_list_file, exported_downloads) def downloadVideo(self): url = self.tabWidget.currentWidget().url().toString() # For youtube videos, parse youtube links in separate thread if youtube.validYoutubeUrl(url): vid_id = parse_qs(urlparse(url).query)['v'][0] ytThread = youtube.YoutubeThread(self) ytThread.ytParseFailed.connect(self.onYtParseFail) ytThread.ytVideoParsed.connect(self.onYtVideoParse) ytThread.finished.connect(ytThread.deleteLater) ytThread.vid_id = vid_id ytThread.start() return # For embeded HTML5 videos self.getVideos() def onYtVideoParse(self, videos): dialog = youtube.YoutubeDialog(videos, self) if dialog.exec_() == 1 : index = abs(dialog.buttonGroup.checkedId())-2 vid = videos[index] reply = networkmanager.get( QNetworkRequest(QUrl.fromUserInput(vid.url)) ) self.handleUnsupportedContent(reply, vid.filename + '.' + vid.extension) def onYtParseFail(self): # Show error on fail to parse youtube QMessageBox.warning(self, "Download Failed !","This Video can not be downloaded") def getVideos(self): dialog = youtube.Media_Dialog(self, self.tabWidget.currentWidget().page(), networkmanager) dialog.downloadRequested.connect(self.handleUnsupportedContent) dialog.exec_() def saveAsImage(self): """ Saves the whole page as PNG/JPG image""" title = self.tabWidget.currentWidget().page().mainFrame().title() title == validateFileName(title) filename = QFileDialog.getSaveFileName(self, "Select Image to Save", downloaddir + title +".jpg", "JPEG Image (*.jpg);;PNG Image (*.png)" )[0] if filename == '': return viewportsize = self.tabWidget.currentWidget().page().viewportSize() contentsize = self.tabWidget.currentWidget().page().mainFrame().contentsSize() self.tabWidget.currentWidget().page().setViewportSize(contentsize) img = QPixmap(contentsize) painter = QPainter(img) self.tabWidget.currentWidget().page().mainFrame().render(painter) painter.end() if img.save(filename): QMessageBox.information(self, "Successful !","Page has been successfully saved as\n"+filename) else: QMessageBox.warning(self, "Saving Failed !","Exporting page to Image hasbeen failed") self.tabWidget.currentWidget().page().setViewportSize(viewportsize) def saveashtml(self): """ Saves current page as HTML , bt does not saves any content (e.g images)""" title = self.tabWidget.currentWidget().page().mainFrame().title() title = validateFileName(title) filename = QFileDialog.getSaveFileName(self, "Enter HTML File Name", downloaddir + title +".html", "HTML Document (*.html)" )[0] if filename == '': return #html = self.tabWidget.currentWidget().page().mainFrame().toHtml() page_URL = self.tabWidget.currentWidget().url() useragent = self.tabWidget.currentWidget().page().userAgentForUrl(page_URL) doc = self.tabWidget.currentWidget().page().mainFrame().documentElement().clone() #doc.setInnerXml(html) SaveAsHtml(networkmanager, doc, filename, page_URL, useragent) def printpage(self, page=None): """ Prints current/requested page """ if not page: page = self.tabWidget.currentWidget().page().currentFrame() printer = QPrinter(QPrinter.HighResolution) printer.setPaperSize(QPrinter.A4) printer.setPageSize(QPrinter.A4) printer.setColorMode(QPrinter.Color) printer.setCreator("Quartz Browser") title = self.tabWidget.currentWidget().page().mainFrame().title() title = validateFileName(title) printer.setDocName(title) printer.setOutputFileName(docdir + title + ".pdf") #printer.setOutputFormat(QPrinter.PdfFormat) print_dialog = QPrintPreviewDialog(printer, self) print_dialog.paintRequested.connect(page.print_) print_dialog.exec_() ################################################################################################## def addToFavourites(self): dialog = QDialog(self) addbmkdialog = Add_Bookmark_Dialog() addbmkdialog.setupUi(dialog) dialog.setWindowTitle('Add to HomePage') addbmkdialog.titleEdit.setMaxLength(31) addbmkdialog.titleEdit.setText(self.tabWidget.currentWidget().page().mainFrame().title()) addbmkdialog.addressEdit.setText(self.line.text()) if (dialog.exec_() == QDialog.Accepted): title = addbmkdialog.titleEdit.text() addr = addbmkdialog.addressEdit.text() imgfile = str(time.time()) + '.jpg' viewportsize = self.tabWidget.currentWidget().page().viewportSize() contentsize = QSize(640, 640) self.tabWidget.currentWidget().page().setViewportSize(contentsize) img = QPixmap(contentsize) painter = QPainter(img) self.tabWidget.currentWidget().page().mainFrame().render(painter, QWebFrame.AllLayers) painter.end() self.tabWidget.currentWidget().page().setViewportSize(viewportsize) icon = img.scaledToWidth(184, 1).copy(0,0, 180, 120) icon.save(thumbnails_dir + imgfile) self.favourites = importFavourites(configdir + 'favourites.txt') self.favourites.append([title, addr, imgfile]) exportFavourites(configdir + 'favourites.txt', self.favourites) def addbookmark(self): """ Opens add bookmark dialog and gets url from url box""" dialog = QDialog(self) addbmkdialog = Add_Bookmark_Dialog() addbmkdialog.setupUi(dialog) addbmkdialog.titleEdit.setText(self.tabWidget.currentWidget().page().mainFrame().title()) addbmkdialog.addressEdit.setText(self.line.text()) if (dialog.exec_() == QDialog.Accepted): url = addbmkdialog.addressEdit.text() bmk = [addbmkdialog.titleEdit.text(), url] self.bookmarks = importBookmarks(configdir+"bookmarks.txt") self.bookmarks.insert(0, bmk) exportBookmarks(configdir+"bookmarks.txt", self.bookmarks) icon = self.tabWidget.currentWidget().icon() if not icon.isNull(): icon.pixmap(16, 16).save(icon_dir + url.split('/')[2] + '.png') def managebookmarks(self): """ Opens Bookmarks dialog """ dialog = QDialog(self) bmk_dialog = Bookmarks_Dialog() bmk_dialog.setupUi(dialog, self.bookmarks, self.favourites) bmk_dialog.bookmarks_table.doubleclicked.connect(self.GoTo) bmk_dialog.favs_table.doubleclicked.connect(self.GoTo) dialog.exec_() if bmk_dialog.bookmarks_table.data_changed: self.bookmarks = bmk_dialog.bookmarks_table.data exportBookmarks(configdir+"bookmarks.txt", self.bookmarks) if bmk_dialog.favs_table.data_changed: self.favourites = bmk_dialog.favs_table.data exportFavourites(configdir+"favourites.txt", self.favourites) def viewhistory(self): """ Open history dialog """ dialog = QDialog(self) history_dialog = History_Dialog() history_dialog.setupUi(dialog, self.history) history_dialog.tableView.doubleclicked.connect(self.GoTo) dialog.exec_() def findmode(self): """ Starts find mode and unhides find buttons""" webkit.find_mode_on = True self.line.clear() self.find.show() self.findprev.show() self.cancelfind.show() self.line.setFocus() def cancelfindmode(self): """ Hides the find buttons, updates urlbox""" webkit.find_mode_on = False self.tabWidget.currentWidget().findText("") self.find.hide() self.findprev.hide() self.cancelfind.hide() self.line.setText(self.tabWidget.currentWidget().url().toString()) def findnext(self): text = self.line.text() self.tabWidget.currentWidget().findText(text) def findback(self): text = self.line.text() self.tabWidget.currentWidget().findText(text, QWebPage.FindBackward) ##################### View Settings ################### def zoomin(self): zoomlevel = self.tabWidget.currentWidget().zoomFactor() self.tabWidget.currentWidget().setZoomFactor(zoomlevel+0.1) # Use setZoomFactor() to zoom text and images def zoomout(self): zoomlevel = self.tabWidget.currentWidget().zoomFactor() self.tabWidget.currentWidget().setZoomFactor(zoomlevel-0.1) def fullscreenmode(self): if self.isFullScreen(): self.showNormal() else: self.showFullScreen() def loadimages(self, state): """ TOggles image loading on/off""" self.websettings.setAttribute(QWebSettings.AutoLoadImages, state) self.loadimagesval = bool(state) def setjavascript(self, state): """ Toggles js on/off """ self.websettings.setAttribute(QWebSettings.JavascriptEnabled, state) self.javascriptenabledval = bool(state) def setUserAgentDesktop(self, checked): if bool(checked): webkit.useragent_mode = 'Desktop' self.useragent_mode_mobile.setChecked(False) self.useragent_mode_custom.setChecked(False) def setUserAgentMobile(self, checked): if bool(checked): webkit.useragent_mode = 'Mobile' self.useragent_mode_desktop.setChecked(False) self.useragent_mode_custom.setChecked(False) def setUserAgentCustom(self, checked): if bool(checked): webkit.useragent_mode = 'Custom' self.useragent_mode_mobile.setChecked(False) self.useragent_mode_desktop.setChecked(False) ########################## Settings Portion ######################### def settingseditor(self): """ Opens the settings manager dialog, then applies the change""" dialog = QDialog(self) websettingsdialog = Ui_SettingsDialog() websettingsdialog.setupUi(dialog) # Enable AdBlock websettingsdialog.checkAdBlock.setChecked(webkit.enable_adblock) # Fonts blocking websettingsdialog.checkFontLoad.setChecked(webkit.block_fonts) # Popups blocking websettingsdialog.checkBlockPopups.setChecked(webkit.block_popups) # Custom user agent websettingsdialog.useragentEdit.setText(webkit.useragent_custom) # External download manager websettingsdialog.checkDownMan.setChecked(self.useexternaldownloader) websettingsdialog.downManEdit.setText(self.externaldownloader) # RTSP media player command websettingsdialog.mediaPlayerEdit.setText(webkit.video_player_command) websettingsdialog.mediaPlayerEdit.setCursorPosition(0) # Font settings websettingsdialog.spinFontSize.setValue(self.minfontsizeval) websettingsdialog.standardfontCombo.setCurrentFont(QFont(self.standardfontval)) websettingsdialog.sansfontCombo.setCurrentFont(QFont(self.sansfontval)) websettingsdialog.seriffontCombo.setCurrentFont(QFont(self.seriffontval)) websettingsdialog.fixedfontCombo.setCurrentFont(QFont(self.fixedfontval)) # Clear Data buttons websettingsdialog.clearCacheButton.clicked.connect(self.websettings.clearMemoryCaches) websettingsdialog.cookiesButton.clicked.connect(cookiejar.clearCookies) websettingsdialog.iconDBButton.clicked.connect(self.websettings.clearIconDatabase) if dialog.exec_() == QDialog.Accepted: # Enable AdBlock webkit.enable_adblock = websettingsdialog.checkAdBlock.isChecked() # Block Fonts webkit.block_fonts = websettingsdialog.checkFontLoad.isChecked() # Block Popups webkit.block_popups = websettingsdialog.checkBlockPopups.isChecked() # User Agent webkit.useragent_custom = websettingsdialog.useragentEdit.text() # Download Manager self.useexternaldownloader = websettingsdialog.checkDownMan.isChecked() self.externaldownloader = websettingsdialog.downManEdit.text() # Media Player Command webkit.video_player_command = websettingsdialog.mediaPlayerEdit.text() self.minfontsizeval = websettingsdialog.spinFontSize.value() self.standardfontval = websettingsdialog.standardfontCombo.currentText() self.sansfontval = websettingsdialog.sansfontCombo.currentText() self.seriffontval = websettingsdialog.seriffontCombo.currentText() self.fixedfontval = websettingsdialog.fixedfontCombo.currentText() self.applysettings() self.savesettings() def opensettings(self): """ Reads settings file in ~/.config/quartz-browser/ directory and saves values in settings variables""" webkit.enable_adblock = _bool(self.settings.value('EnableAdblock', True)) self.loadimagesval = _bool(self.settings.value('LoadImages', True)) self.javascriptenabledval = _bool(self.settings.value('JavaScriptEnabled', True)) webkit.block_fonts = _bool(self.settings.value('BlockFontLoading', False)) webkit.block_popups = _bool(self.settings.value('BlockPopups', False)) webkit.useragent_mode = self.settings.value('UserAgentMode', webkit.useragent_mode) webkit.useragent_custom = self.settings.value('UserAgent', webkit.useragent_custom) self.useexternaldownloader = _bool(self.settings.value('UseExternalDownloader', False)) self.externaldownloader = self.settings.value('ExternalDownloader', "x-terminal-emulator wget -c %u") webkit.video_player_command = self.settings.value('MediaPlayerCommand', webkit.video_player_command) self.maximize_window = _bool(self.settings.value('MaximizeWindow', False)) self.minfontsizeval = int(self.settings.value('MinFontSize', 11)) self.standardfontval = self.settings.value('StandardFont', 'Sans') self.sansfontval = self.settings.value('SansFont', 'Sans') self.seriffontval = self.settings.value('SerifFont', 'Serif') self.fixedfontval = self.settings.value('FixedFont', 'Monospace') def savesettings(self): """ Writes setings to disk in ~/.config/quartz-browser/ directory""" self.settings.setValue('EnableAdblock', webkit.enable_adblock) self.settings.setValue('LoadImages', self.loadimagesval) self.settings.setValue('JavaScriptEnabled', self.javascriptenabledval) self.settings.setValue('BlockFontLoading', webkit.block_fonts) self.settings.setValue('BlockPopups', webkit.block_popups) self.settings.setValue('UserAgent', webkit.useragent_custom) self.settings.setValue('UserAgentMode', webkit.useragent_mode) self.settings.setValue('UseExternalDownloader', self.useexternaldownloader) self.settings.setValue('ExternalDownloader', self.externaldownloader) self.settings.setValue('MediaPlayerCommand', webkit.video_player_command) self.settings.setValue('MaximizeWindow', self.isMaximized()) self.settings.setValue('MinFontSize', self.minfontsizeval) self.settings.setValue('StandardFont', self.standardfontval) self.settings.setValue('SansFont', self.sansfontval) self.settings.setValue('SerifFont', self.seriffontval) self.settings.setValue('FixedFont', self.fixedfontval) def applysettings(self): """ Reads settings variables, and changes browser settings.This is run after changing settings by Settings Dialog""" if webkit.enable_adblock: self.websettings.setUserStyleSheetUrl(QUrl.fromLocalFile(program_dir + 'userContent.css')) else: self.websettings.setUserStyleSheetUrl(QUrl('')) self.websettings.setAttribute(QWebSettings.AutoLoadImages, self.loadimagesval) self.loadimagesaction.setChecked(self.loadimagesval) self.websettings.setAttribute(QWebSettings.JavascriptEnabled, self.javascriptenabledval) self.javascriptmode.setChecked(self.javascriptenabledval) if webkit.useragent_mode == 'Mobile': self.useragent_mode_mobile.setChecked(True) elif webkit.useragent_mode == 'Custom': self.useragent_mode_custom.setChecked(True) else: self.useragent_mode_desktop.setChecked(True) self.websettings.setFontSize(QWebSettings.MinimumFontSize, self.minfontsizeval) self.websettings.setFontFamily(QWebSettings.StandardFont, self.standardfontval) self.websettings.setFontFamily(QWebSettings.SansSerifFont, self.sansfontval) self.websettings.setFontFamily(QWebSettings.SerifFont, self.seriffontval) self.websettings.setFontFamily(QWebSettings.FixedFont, self.fixedfontval) # self.websettings.setFontSize(QWebSettings.DefaultFontSize, 14) def enableKiosk(self): webkit.KIOSK_MODE = True self.menu.clear() self.toolBar.hide() self.showFullScreen() def forceClose(self): self.confirm_before_quit = False self.close() def closeEvent(self, event): """This saves all settings, bookmarks, cookies etc. during window close""" if self.confirm_before_quit: confirm = QMessageBox.warning(self, 'Quit Browser ?', 'Are you sure to close the Browser', QMessageBox.Yes|QMessageBox.No, QMessageBox.Yes) if confirm == QMessageBox.No : event.ignore() return self.savesettings() cookiejar.exportCookies() # Delete excess thumbnails thumbnails = [ x for x in os.listdir(thumbnails_dir) ] for fav in self.favourites: if fav[2] in thumbnails: thumbnails.remove(fav[2]) for f in thumbnails: os.remove(thumbnails_dir + f) # Delete excess icons icons = [ x for x in os.listdir(icon_dir) if x.endswith('.png') ] for bmk in self.bookmarks: host = QUrl(bmk[1]).host() if host + '.png' in icons: icons.remove(host + '.png') for f in icons: os.remove( icon_dir + f ) super(Main, self).closeEvent(event)
class EditorMainWindow(QMainWindow): def __init__(self, parent=None): QMainWindow.__init__(self, parent) self.ui = Ui_ScriptEditor() self.ui.setupUi(self) #self.ui.actionExit.triggered.connect(self.exit) self.splitter = QSplitter(Qt.Vertical, self) self.setCentralWidget(self.splitter) self.edit_tab = QTabWidget(self.splitter) self.console_tab = QTabWidget(self.splitter) self.py_console = PythonConsole(self.console_tab) self.console_tab.addTab(self.py_console, "&Python console") self.js_console = QtQmlConsole(self.console_tab) self.console_tab.addTab(self.js_console, "&QtQml console") self.editors = [] self.on_actionNewPython_triggered() @pyqtSlot() def closeEvent(self, event): while(self.editors.__len__()): edit = self.edit_tab.currentWidget() if edit: if(edit.isModified()): saveBox = SaveDialog("You have unsaved script. Save it now?") prompt = saveBox.exec_() if(prompt == QMessageBox.Save): event.ignore() self.save(True) elif(prompt == QMessageBox.Cancel): event.ignore() return elif(prompt == QMessageBox.Discard): event.accept() i = self.edit_tab.indexOf(edit) self.edit_tab.removeTab(i) self.editors.remove(edit) event.accept() @pyqtSlot() def on_actionExit_triggered(self): while(self.editors.__len__()): edit = self.edit_tab.currentWidget() if edit: if(edit.isModified()): saveBox = SaveDialog("You have unsaved script. Save it now?") prompt = saveBox.exec_() if(prompt == QMessageBox.Save): self.save(True) elif(prompt == QMessageBox.Cancel): return elif(prompt == QMessageBox.Discard): pass i = self.edit_tab.indexOf(edit) self.edit_tab.removeTab(i) self.editors.remove(edit) self.close() @pyqtSlot() def on_actionNewPython_triggered(self): pyedit = PythonEditorWidget(self.edit_tab) pyedit.setPlainText(template_py) self.edit_tab.addTab(pyedit, "Python") self.edit_tab.setCurrentWidget(pyedit) self.editors.append(pyedit) self.py_console.attach() self.console_tab.setCurrentIndex(0) pyedit.setFocus() pyedit.view.setFocus() @pyqtSlot() def on_actionNewQtQml_triggered(self): jsedit = QtQmlEditorWidget(self.edit_tab) self.edit_tab.addTab(jsedit, "QtQml") self.edit_tab.setCurrentWidget(jsedit) self.editors.append(jsedit) self.js_console.attach() self.console_tab.setCurrentIndex(1) @pyqtSlot() def on_actionClose_triggered(self): edit = self.edit_tab.currentWidget() if edit: if(edit.isModified()): saveBox = SaveDialog("Do you want to save this Script?") prompt = saveBox.exec_() if(prompt == QMessageBox.Save): self.save(True) elif(prompt == QMessageBox.Cancel): return elif(prompt == QMessageBox.Discard): pass i = self.edit_tab.indexOf(edit) self.edit_tab.removeTab(i) self.editors.remove(edit) @pyqtSlot() def on_actionClear_triggered(self): #edit = self.edit_tab.currentWidget() #edit.setPlainText(template_py) self.py_console.clear() @pyqtSlot() def on_actionSave_As_triggered(self): self.save() @pyqtSlot() def on_actionSave_triggered(self): self.save(True) #Path of the script file in each tab will be stored in tabToolTip def save(self, Update = False): edit = self.edit_tab.currentWidget() contents = str(edit.toPlainText()) if((Update == False) or (self.edit_tab.tabText(self.edit_tab.currentIndex()) == "Python") ): #Save in its first invocation and Save As will enter filename = QFileDialog.getSaveFileName(self, "Save File", "", "*.spy") fil = open(filename , 'w') if(filename and self.edit_tab.tabText(self.edit_tab.currentIndex()) == "Python"): #Script hasn't been saved before and user specifies a valid filename self.edit_tab.setTabToolTip(self.edit_tab.currentIndex(), filename+'.spy') self.edit_tab.setTabText(self.edit_tab.currentIndex(), os.path.basename(str(filename+'.spy'))) else: #filename = self.edit_tab.tabText(self.edit_tab.currentIndex()) filename = self.edit_tab.tabToolTip(self.edit_tab.currentIndex()) fil = open( filename , 'w') fil.write(contents) fil.close() edit.setModified(False) @pyqtSlot() def on_actionOpen_triggered(self): filename = QFileDialog.getOpenFileName(self,"Open File","","*.spy") try: fil = open(filename , 'r') except IOError: return code = fil.read() edit = self.edit_tab.currentWidget() self.edit_tab.setTabText(self.edit_tab.currentIndex(), os.path.basename(str(filename))) self.edit_tab.setTabToolTip(self.edit_tab.currentIndex(), filename) edit.setPlainText(code) fil.close() @pyqtSlot() def on_actionRun_triggered(self): self.run() @pyqtSlot() def on_actionRunConsole_triggered(self): self.run(True) def run(self, console=False): edit = self.edit_tab.currentWidget() code = str(edit.toPlainText()) if isinstance(edit, PythonEditorWidget): self.py_console.attach() self.console_tab.setCurrentIndex(0) if console: namespace = self.py_console.namespace else: namespace = {} try: exec code in namespace except Exception as e: traceback.print_exc() try: Scripter.activeWindow.redraw = True Scripter.activeWindow.update() except: pass else: self.js_console.attach() self.console_tab.setCurrentIndex(1) if console: self.js_console.inter.execute(code) else: self.js_console.inter.execute_code(code)
class ScoreWizardDialog(QDialog): pitchLanguageChanged = pyqtSignal(str) def __init__(self, mainwindow): super(ScoreWizardDialog, self).__init__(mainwindow) self.addAction(mainwindow.actionCollection.help_whatsthis) self._pitchLanguage = None layout = QVBoxLayout() self.setLayout(layout) self.tabs = QTabWidget() b = self.dialogButtons = QDialogButtonBox() b.setStandardButtons( QDialogButtonBox.Reset | QDialogButtonBox.Ok | QDialogButtonBox.Cancel) b.accepted.connect(self.accept) b.rejected.connect(self.reject) userguide.addButton(b, "scorewiz") b.button(QDialogButtonBox.Reset).clicked.connect(self.reset) self.previewButton = b.addButton('', QDialogButtonBox.ActionRole) self.previewButton.clicked.connect(self.showPreview) layout.addWidget(self.tabs) layout.addWidget(b) self.header = Header(self) self.tabs.addTab(self.header, '') self.parts = Parts(self) self.tabs.addTab(self.parts, '') self.settings = Settings(self) self.tabs.addTab(self.settings, '') self.tabs.setCurrentIndex(0) self.tabs.widget(0).widget() # activate it self.tabs.currentChanged.connect(self.slotCurrentChanged) qutil.saveDialogSize(self, "scorewiz/dialog/size") app.translateUI(self) self.accepted.connect(self.slotAccepted) def translateUI(self): self.setWindowTitle(app.caption(_("Score Setup Wizard"))) for i in range(self.tabs.count()): self.tabs.setTabText(i, self.tabs.widget(i).title()) self.dialogButtons.button(QDialogButtonBox.Reset).setText(_("Clear")) self.dialogButtons.button(QDialogButtonBox.Reset).setToolTip(_( "Clears the current page of the Score Wizard.")) self.previewButton.setText(_("Preview")) def slotCurrentChanged(self, i): """Lazy-loads the tab's page if shown for the first time.""" self.tabs.widget(i).widget() def reset(self): self.tabs.currentWidget().widget().clear() def setPitchLanguage(self, language): if language != self._pitchLanguage: self._pitchLanguage = language self.pitchLanguageChanged.emit(language) def pitchLanguage(self): if self._pitchLanguage is None: # load setting; saving occurs in .settings.py lang = QSettings().value('scorewiz/lilypond/pitch_language', '', str) from .scoreproperties import keyNames if lang not in keyNames: lang = '' self._pitchLanguage = lang return self._pitchLanguage def slotAccepted(self): """Makes the score and puts it in the editor.""" from . import build builder = build.Builder(self) # get the builder text = builder.text() # get the source text lydoc = ly.document.Document(text) # temporarily store it in a lydoc cursor = ly.document.Cursor(lydoc) # make a cursor selecting it indent.indenter().indent(cursor) # indent it according to user prefs doc = app.openUrl(QUrl()) # get a new Frescobaldi document doc.setPlainText(lydoc.plaintext()) # write the text in it doc.setModified(False) # make it "not modified" self.parent().setCurrentDocument(doc) def showPreview(self): """Shows a preview.""" # get the document and fill in some example music from . import preview, build builder = build.Builder(self) doc = builder.document() preview.examplify(doc) # preview it import musicpreview dlg = musicpreview.MusicPreviewDialog(self) dlg.preview(builder.text(doc), _("Score Preview")) dlg.exec_() dlg.cleanup()
class PreferencesDialogBase(QDialog): def __init__(self, parent, app, **kwargs): flags = Qt.CustomizeWindowHint | Qt.WindowTitleHint | Qt.WindowSystemMenuHint super().__init__(parent, flags, **kwargs) self.app = app all_languages = get_langnames() self.supportedLanguages = sorted(SUPPORTED_LANGUAGES, key=lambda lang: all_languages[lang]) self._setupUi() self.filterHardnessSlider.valueChanged["int"].connect( self.filterHardnessLabel.setNum) self.buttonBox.clicked.connect(self.buttonClicked) self.buttonBox.accepted.connect(self.accept) self.buttonBox.rejected.connect(self.reject) def _setupFilterHardnessBox(self): self.filterHardnessHLayout = QHBoxLayout() self.filterHardnessLabel = QLabel(self) self.filterHardnessLabel.setText(tr("Filter Hardness:")) self.filterHardnessLabel.setMinimumSize(QSize(0, 0)) self.filterHardnessHLayout.addWidget(self.filterHardnessLabel) self.filterHardnessVLayout = QVBoxLayout() self.filterHardnessVLayout.setSpacing(0) self.filterHardnessHLayoutSub1 = QHBoxLayout() self.filterHardnessHLayoutSub1.setSpacing(12) self.filterHardnessSlider = QSlider(self) sizePolicy = QSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed) sizePolicy.setHorizontalStretch(0) sizePolicy.setVerticalStretch(0) sizePolicy.setHeightForWidth( self.filterHardnessSlider.sizePolicy().hasHeightForWidth()) self.filterHardnessSlider.setSizePolicy(sizePolicy) self.filterHardnessSlider.setMinimum(1) self.filterHardnessSlider.setMaximum(100) self.filterHardnessSlider.setTracking(True) self.filterHardnessSlider.setOrientation(Qt.Horizontal) self.filterHardnessHLayoutSub1.addWidget(self.filterHardnessSlider) self.filterHardnessLabel = QLabel(self) self.filterHardnessLabel.setText("100") self.filterHardnessLabel.setMinimumSize(QSize(21, 0)) self.filterHardnessHLayoutSub1.addWidget(self.filterHardnessLabel) self.filterHardnessVLayout.addLayout(self.filterHardnessHLayoutSub1) self.filterHardnessHLayoutSub2 = QHBoxLayout() self.filterHardnessHLayoutSub2.setContentsMargins(-1, 0, -1, -1) self.moreResultsLabel = QLabel(self) self.moreResultsLabel.setText(tr("More Results")) self.filterHardnessHLayoutSub2.addWidget(self.moreResultsLabel) spacerItem = QSpacerItem(40, 20, QSizePolicy.Expanding, QSizePolicy.Minimum) self.filterHardnessHLayoutSub2.addItem(spacerItem) self.fewerResultsLabel = QLabel(self) self.fewerResultsLabel.setText(tr("Fewer Results")) self.filterHardnessHLayoutSub2.addWidget(self.fewerResultsLabel) self.filterHardnessVLayout.addLayout(self.filterHardnessHLayoutSub2) self.filterHardnessHLayout.addLayout(self.filterHardnessVLayout) def _setupBottomPart(self): # The bottom part of the pref panel is always the same in all editions. self.copyMoveLabel = QLabel(self) self.copyMoveLabel.setText(tr("Copy and Move:")) self.widgetsVLayout.addWidget(self.copyMoveLabel) self.copyMoveDestinationComboBox = QComboBox(self) self.copyMoveDestinationComboBox.addItem(tr("Right in destination")) self.copyMoveDestinationComboBox.addItem(tr("Recreate relative path")) self.copyMoveDestinationComboBox.addItem(tr("Recreate absolute path")) self.widgetsVLayout.addWidget(self.copyMoveDestinationComboBox) self.customCommandLabel = QLabel(self) self.customCommandLabel.setText( tr("Custom Command (arguments: %d for dupe, %r for ref):")) self.widgetsVLayout.addWidget(self.customCommandLabel) self.customCommandEdit = QLineEdit(self) self.widgetsVLayout.addWidget(self.customCommandEdit) def _setupDisplayPage(self): self.ui_groupbox = QGroupBox("&General Interface") layout = QVBoxLayout() self.languageLabel = QLabel(tr("Language:"), self) self.languageComboBox = QComboBox(self) for lang in self.supportedLanguages: self.languageComboBox.addItem(get_langnames()[lang]) layout.addLayout( horizontalWrap([self.languageLabel, self.languageComboBox, None])) self._setupAddCheckbox( "tabs_default_pos", tr("Use default position for tab bar (requires restart)")) self.tabs_default_pos.setToolTip( tr("Place the tab bar below the main menu instead of next to it\n\ On MacOS, the tab bar will fill up the window's width instead.")) layout.addWidget(self.tabs_default_pos) self.ui_groupbox.setLayout(layout) self.displayVLayout.addWidget(self.ui_groupbox) gridlayout = QFormLayout() result_groupbox = QGroupBox("&Result Table") self.fontSizeSpinBox = QSpinBox() self.fontSizeSpinBox.setMinimum(5) gridlayout.addRow(tr("Font size:"), self.fontSizeSpinBox) self._setupAddCheckbox("reference_bold_font", tr("Use bold font for references")) gridlayout.addRow(self.reference_bold_font) self.result_table_ref_foreground_color = ColorPickerButton(self) gridlayout.addRow(tr("Reference foreground color:"), self.result_table_ref_foreground_color) self.result_table_ref_background_color = ColorPickerButton(self) gridlayout.addRow(tr("Reference background color:"), self.result_table_ref_background_color) self.result_table_delta_foreground_color = ColorPickerButton(self) gridlayout.addRow(tr("Delta foreground color:"), self.result_table_delta_foreground_color) gridlayout.setLabelAlignment(Qt.AlignLeft) # Keep same vertical spacing as parent layout for consistency gridlayout.setVerticalSpacing(self.displayVLayout.spacing()) result_groupbox.setLayout(gridlayout) self.displayVLayout.addWidget(result_groupbox) details_groupbox = QGroupBox("&Details Window") self.details_groupbox_layout = QVBoxLayout() self._setupAddCheckbox("details_dialog_titlebar_enabled", tr("Show the title bar and can be docked")) self.details_dialog_titlebar_enabled.setToolTip( tr("While the title bar is hidden, \ use the modifier key to drag the floating window around") if ISLINUX else tr("The title bar can only be disabled while the window is docked" )) self.details_groupbox_layout.addWidget( self.details_dialog_titlebar_enabled) self._setupAddCheckbox("details_dialog_vertical_titlebar", tr("Vertical title bar")) self.details_dialog_vertical_titlebar.setToolTip( tr("Change the title bar from horizontal on top, to vertical on the left side" )) self.details_groupbox_layout.addWidget( self.details_dialog_vertical_titlebar) self.details_dialog_vertical_titlebar.setEnabled( self.details_dialog_titlebar_enabled.isChecked()) self.details_dialog_titlebar_enabled.stateChanged.connect( self.details_dialog_vertical_titlebar.setEnabled) gridlayout = QGridLayout() self.details_table_delta_foreground_color_label = QLabel( tr("Delta foreground color:")) gridlayout.addWidget(self.details_table_delta_foreground_color_label, 4, 0) self.details_table_delta_foreground_color = ColorPickerButton(self) gridlayout.addWidget(self.details_table_delta_foreground_color, 4, 2, 1, 1, Qt.AlignLeft) gridlayout.setColumnStretch(1, 1) gridlayout.setColumnStretch(3, 4) self.details_groupbox_layout.addLayout(gridlayout) details_groupbox.setLayout(self.details_groupbox_layout) self.displayVLayout.addWidget(details_groupbox) def _setupAddCheckbox(self, name, label, parent=None): if parent is None: parent = self cb = QCheckBox(parent) cb.setText(label) setattr(self, name, cb) def _setupPreferenceWidgets(self): # Edition-specific pass def _setupUi(self): self.setWindowTitle(tr("Options")) self.setSizeGripEnabled(False) self.setModal(True) self.mainVLayout = QVBoxLayout(self) self.tabwidget = QTabWidget() self.page_general = QWidget() self.page_display = QWidget() self.widgetsVLayout = QVBoxLayout() self.page_general.setLayout(self.widgetsVLayout) self.displayVLayout = QVBoxLayout() self.displayVLayout.setSpacing( 5) # arbitrary value, might conflict with style self.page_display.setLayout(self.displayVLayout) self._setupPreferenceWidgets() self._setupDisplayPage() # self.mainVLayout.addLayout(self.widgetsVLayout) self.buttonBox = QDialogButtonBox(self) self.buttonBox.setStandardButtons(QDialogButtonBox.Cancel | QDialogButtonBox.Ok | QDialogButtonBox.RestoreDefaults) self.mainVLayout.addWidget(self.tabwidget) self.mainVLayout.addWidget(self.buttonBox) self.layout().setSizeConstraint(QLayout.SetFixedSize) self.tabwidget.addTab(self.page_general, "General") self.tabwidget.addTab(self.page_display, "Display") self.displayVLayout.addStretch(0) self.widgetsVLayout.addStretch(0) def _load(self, prefs, setchecked, section): # Edition-specific pass def _save(self, prefs, ischecked): # Edition-specific pass def load(self, prefs=None, section=Sections.ALL): if prefs is None: prefs = self.app.prefs setchecked = lambda cb, b: cb.setCheckState(Qt.Checked if b else Qt.Unchecked) if section & Sections.GENERAL: self.filterHardnessSlider.setValue(prefs.filter_hardness) self.filterHardnessLabel.setNum(prefs.filter_hardness) setchecked(self.mixFileKindBox, prefs.mix_file_kind) setchecked(self.useRegexpBox, prefs.use_regexp) setchecked(self.removeEmptyFoldersBox, prefs.remove_empty_folders) setchecked(self.ignoreHardlinkMatches, prefs.ignore_hardlink_matches) setchecked(self.debugModeBox, prefs.debug_mode) self.copyMoveDestinationComboBox.setCurrentIndex( prefs.destination_type) self.customCommandEdit.setText(prefs.custom_command) if section & Sections.DISPLAY: setchecked(self.reference_bold_font, prefs.reference_bold_font) setchecked(self.tabs_default_pos, prefs.tabs_default_pos) setchecked(self.details_dialog_titlebar_enabled, prefs.details_dialog_titlebar_enabled) setchecked(self.details_dialog_vertical_titlebar, prefs.details_dialog_vertical_titlebar) self.fontSizeSpinBox.setValue(prefs.tableFontSize) self.details_table_delta_foreground_color.setColor( prefs.details_table_delta_foreground_color) self.result_table_ref_foreground_color.setColor( prefs.result_table_ref_foreground_color) self.result_table_ref_background_color.setColor( prefs.result_table_ref_background_color) self.result_table_delta_foreground_color.setColor( prefs.result_table_delta_foreground_color) try: langindex = self.supportedLanguages.index( self.app.prefs.language) except ValueError: langindex = 0 self.languageComboBox.setCurrentIndex(langindex) self._load(prefs, setchecked, section) def save(self): prefs = self.app.prefs prefs.filter_hardness = self.filterHardnessSlider.value() ischecked = lambda cb: cb.checkState() == Qt.Checked prefs.mix_file_kind = ischecked(self.mixFileKindBox) prefs.use_regexp = ischecked(self.useRegexpBox) prefs.remove_empty_folders = ischecked(self.removeEmptyFoldersBox) prefs.ignore_hardlink_matches = ischecked(self.ignoreHardlinkMatches) prefs.debug_mode = ischecked(self.debugModeBox) prefs.reference_bold_font = ischecked(self.reference_bold_font) prefs.details_dialog_titlebar_enabled = ischecked( self.details_dialog_titlebar_enabled) prefs.details_dialog_vertical_titlebar = ischecked( self.details_dialog_vertical_titlebar) prefs.details_table_delta_foreground_color = self.details_table_delta_foreground_color.color prefs.result_table_ref_foreground_color = self.result_table_ref_foreground_color.color prefs.result_table_ref_background_color = self.result_table_ref_background_color.color prefs.result_table_delta_foreground_color = self.result_table_delta_foreground_color.color prefs.destination_type = self.copyMoveDestinationComboBox.currentIndex( ) prefs.custom_command = str(self.customCommandEdit.text()) prefs.tableFontSize = self.fontSizeSpinBox.value() prefs.tabs_default_pos = ischecked(self.tabs_default_pos) lang = self.supportedLanguages[self.languageComboBox.currentIndex()] oldlang = self.app.prefs.language if oldlang not in self.supportedLanguages: oldlang = "en" if lang != oldlang: QMessageBox.information( self, "", tr("dupeGuru has to restart for language changes to take effect." ), ) self.app.prefs.language = lang self._save(prefs, ischecked) def resetToDefaults(self, section_to_update): self.load(Preferences(), section_to_update) # --- Events def buttonClicked(self, button): role = self.buttonBox.buttonRole(button) if role == QDialogButtonBox.ResetRole: current_tab = self.tabwidget.currentWidget() section_to_update = Sections.ALL if current_tab is self.page_general: section_to_update = Sections.GENERAL if current_tab is self.page_display: section_to_update = Sections.DISPLAY self.resetToDefaults(section_to_update)
class SimulatorWindow(QMainWindow): def __init__(self, argv): QMainWindow.__init__(self) self.setWindowTitle("SimSo: Real-Time Scheduling Simulator") # Possible actions: style = QApplication.style() # New self._newAction = QAction( style.standardIcon(QStyle.SP_FileDialogNewFolder), '&New', None) self._newAction.setShortcut(Qt.CTRL + Qt.Key_N) self._newAction.triggered.connect(self.fileNew) # Open self._openAction = QAction( style.standardIcon(QStyle.SP_DialogOpenButton), '&Open', None) self._openAction.setShortcut(Qt.CTRL + Qt.Key_O) self._openAction.triggered.connect(self.fileOpen) # Save self._saveAction = QAction( style.standardIcon(QStyle.SP_DialogSaveButton), '&Save', None) self._saveAction.setShortcut(Qt.CTRL + Qt.Key_S) self._saveAction.triggered.connect(self.fileSave) # Save As self._saveAsAction = QAction( style.standardIcon(QStyle.SP_DialogSaveButton), 'Save &As', None) self._saveAsAction.setShortcut(Qt.CTRL + Qt.SHIFT + Qt.Key_S) self._saveAsAction.triggered.connect(self.fileSaveAs) # Run self._runAction = QAction( style.standardIcon(QStyle.SP_MediaPlay), '&Run', None) self._runAction.setShortcut(Qt.CTRL + Qt.Key_R) self._runAction.triggered.connect(self.fileRun) # Show Model data self._modelAction = QAction('&Model data', None) self._modelAction.setShortcut(Qt.CTRL + Qt.Key_M) #self._ganttAction.setCheckable(True) self._modelAction.triggered.connect(self.showModelWindow) # Show Gantt self._ganttAction = QAction('&Gantt', None) self._ganttAction.setShortcut(Qt.CTRL + Qt.Key_G) self._ganttAction.setEnabled(False) #self._ganttAction.setCheckable(True) self._ganttAction.triggered.connect(self.showGantt) # Show Results self._metricsAction = QAction('&Results', None) self._metricsAction.setShortcut(Qt.CTRL + Qt.Key_I) self._metricsAction.setEnabled(False) #self._metricsAction.setCheckable(True) self._metricsAction.triggered.connect(self.showResults) # Show Doc self._docAction = QAction('&Documentation', None) self._docAction.triggered.connect(self.showDocumentation) self._aboutAction = QAction('&About SimSo', None) self._aboutAction.triggered.connect(self.showAbout) # Recent files self._recentFileActions = [] for i in range(5): act = QAction(self) act.setVisible(False) act.triggered.connect(self.openRecentFile) self._recentFileActions.append(act) # File Menu: file_menu = QMenu('&File', self) file_menu.addAction(self._newAction) file_menu.addAction(self._openAction) file_menu.addAction(self._saveAction) file_menu.addAction(self._saveAsAction) file_menu.addAction(self._runAction) file_menu.addSeparator() for act in self._recentFileActions: file_menu.addAction(act) file_menu.addSeparator() file_menu.addAction('&Quit', self.fileQuit, Qt.CTRL + Qt.Key_Q) self.updateRecentFileActions() # View Menu: view_menu = QMenu('&View', self) view_menu.addAction(self._modelAction) view_menu.addAction(self._ganttAction) view_menu.addAction(self._metricsAction) # Help Menu: help_menu = QMenu('&Help', self) help_menu.addAction(self._docAction) help_menu.addAction(self._aboutAction) # Add menus to menuBar: self.menuBar().addMenu(file_menu) self.menuBar().addMenu(view_menu) self.menuBar().addMenu(help_menu) # ToolBar: self.toolBar = QToolBar("Main ToolBar") self.addToolBar(self.toolBar) self.toolBar.addAction(self._newAction) self.toolBar.addAction(self._openAction) self.toolBar.addAction(self._saveAction) self.toolBar.addAction(self._runAction) self.toolBar.addAction(self._ganttAction) self.toolBar.addAction(self._metricsAction) # Tab: self.main_tab = QTabWidget() self.main_tab.setTabsClosable(True) self.main_tab.setMovable(True) self.main_tab.tabCloseRequested.connect(self.tabCloseRequested) self.main_tab.currentChanged.connect(self.tabChanged) self.setCentralWidget(self.main_tab) # Init statusBar: self.statusBar().showMessage("", 2000) self._documentation = None if argv: for arg in argv: try: self.open_file(arg) except Exception as e: print(e) else: self.fileNew() def openRecentFile(self): try: self.open_file(self.sender().data().toString()) except AttributeError: self.open_file(self.sender().data()) def updateRecentFileActions(self): settings = QSettings() files = settings.value("recentFileList", defaultValue=[], type='QString') for i in range(5): if i < len(files): text = "&{} {}".format(i + 1, QFileInfo(files[i]).fileName()) self._recentFileActions[i].setText(text) self._recentFileActions[i].setData(files[i]) self._recentFileActions[i].setVisible(True) else: self._recentFileActions[i].setVisible(False) def setCurrentFile(self, filename): filename = QFileInfo(filename).absoluteFilePath() settings = QSettings() files = settings.value("recentFileList", defaultValue=[], type='QString') if filename in files: files.remove(filename) files.insert(0, filename) while len(files) > 5: del files[-1] settings.setValue("recentFileList", files) self.updateRecentFileActions() def showAbout(self): QMessageBox.about( self, "About SimSo", "<b>SimSo - Simulation of Multiprocessor Scheduling with Overheads</b><br/><br/>" "Version: SimSo {}, Graphical User Interface {}<br/><br/>" "SimSo is a free software developed by Maxime Cheramy (LAAS-CNRS).<br/>" "This software is distributed under the <a href='http://www.cecill.info'>CECILL license</a>, " "compatible with the GNU GPL.<br/><br/>" "Contact: <a href='mailto:[email protected]'>[email protected]</a>".format(simso.__version__, simsogui.__version__) ) def showDocumentation(self): if self._documentation is None: doc = QWebView(self) doc.load(QUrl("doc/html/index.html")) self._documentation = QDockWidget("Documentation", self) self._documentation.setWidget(doc) self._documentation.closeEvent = lambda _: self.hide_documentation() self.addDockWidget(Qt.LeftDockWidgetArea, self._documentation) def showGantt(self): self.main_tab.currentWidget().showGantt() def showModelWindow(self): self.main_tab.currentWidget().showModelWindow() def showResults(self): self.main_tab.currentWidget().showResults() def hide_documentation(self): self._documentation = None def fileNew(self): self.main_tab.addTab(SimulationTab(self), 'Unsaved') def fileOpen(self): simulation_file = QFileDialog.getOpenFileName( filter="*.xml", caption="Open XML simulation file.")[0] if simulation_file: self.open_file(simulation_file) def open_file(self, simulation_file): try: simulation_file = unicode(simulation_file) except NameError: pass try: self.setCurrentFile(simulation_file) sim = SimulationTab(self, simulation_file) if (self.main_tab.currentWidget() and not self.main_tab.currentWidget().simulation_file and self.main_tab.currentWidget().configuration.is_saved() and self.main_tab.count() == 1): self.main_tab.removeTab(0) self.main_tab.addTab(sim, os.path.split(simulation_file)[1]) self.main_tab.setCurrentWidget(sim) self.updateMenus() except Exception: QMessageBox.critical( self, "Could not open file", "The file {} could not be opened.".format(simulation_file)) print(traceback.format_exc()) def fileSave(self): try: self.main_tab.currentWidget().save() except: self.fileSaveAs() def fileSaveAs(self): simulation_file = QFileDialog.getSaveFileName( filter="*.xml", caption="Save XML simulation file.")[0] try: simulation_file = unicode(simulation_file) except NameError: pass if simulation_file: if simulation_file[-4:] != '.xml': simulation_file += '.xml' self.main_tab.currentWidget().save_as(simulation_file) self.setCurrentFile(simulation_file) def fileRun(self): self._runAction.setEnabled(False) self.main_tab.currentWidget().run() def fileQuit(self): self.close() def setTabText(self, tab, text): self.main_tab.setTabText(self.main_tab.indexOf(tab), text) def tabChanged(self, index): self.updateMenus() def tabCloseRequested(self, index): if self.main_tab.widget(index).close(): self.main_tab.removeTab(index) self.updateMenus() def closeEvent(self, event): while self.main_tab.count() > 0: if self.main_tab.widget(0).close(): self.main_tab.removeTab(0) else: event.ignore() return def updateMenus(self): if self.main_tab.count() > 0: widget = self.main_tab.currentWidget() self._runAction.setEnabled(True) self._modelAction.setEnabled(True) self._ganttAction.setEnabled(widget._model is not None) self._metricsAction.setEnabled(widget._model is not None) else: self._runAction.setEnabled(False) self._modelAction.setEnabled(False) self._ganttAction.setEnabled(False) self._metricsAction.setEnabled(False)
class UIDocumentTools(object): def __init__(self): self.mainDialog = documenttoolsdialog.DocumentToolsDialog() self.mainLayout = QVBoxLayout(self.mainDialog) self.formLayout = QFormLayout() self.documentLayout = QVBoxLayout() self.refreshButton = QPushButton(i18n("Refresh")) self.widgetDocuments = QListWidget() self.tabTools = QTabWidget() self.buttonBox = QDialogButtonBox(QDialogButtonBox.Ok | QDialogButtonBox.Cancel) self.kritaInstance = krita.Krita.instance() self.documentsList = [] self.refreshButton.clicked.connect(self.refreshButtonClicked) self.buttonBox.accepted.connect(self.confirmButton) self.buttonBox.rejected.connect(self.mainDialog.close) self.mainDialog.setWindowModality(Qt.NonModal) self.widgetDocuments.setSelectionMode(QAbstractItemView.MultiSelection) self.widgetDocuments.setSizeAdjustPolicy( QAbstractScrollArea.AdjustToContents) def initialize(self): self.loadDocuments() self.loadTools() self.documentLayout.addWidget(self.widgetDocuments) self.documentLayout.addWidget(self.refreshButton) self.formLayout.addRow(i18n("Documents:"), self.documentLayout) self.formLayout.addRow(self.tabTools) self.line = QFrame() self.line.setFrameShape(QFrame.HLine) self.line.setFrameShadow(QFrame.Sunken) self.mainLayout.addLayout(self.formLayout) self.mainLayout.addWidget(self.line) self.mainLayout.addWidget(self.buttonBox) self.mainDialog.resize(500, 300) self.mainDialog.setWindowTitle(i18n("Document Tools")) self.mainDialog.setSizeGripEnabled(True) self.mainDialog.show() self.mainDialog.activateWindow() def loadTools(self): modulePath = 'documenttools.tools' toolsModule = importlib.import_module(modulePath) modules = [] for classPath in toolsModule.ToolClasses: _module = classPath[:classPath.rfind(".")] _klass = classPath[classPath.rfind(".") + 1:] modules.append( dict(module='{0}.{1}'.format(modulePath, _module), klass=_klass)) for module in modules: m = importlib.import_module(module['module']) toolClass = getattr(m, module['klass']) obj = toolClass(self.mainDialog) self.tabTools.addTab(obj, obj.objectName()) def loadDocuments(self): self.widgetDocuments.clear() self.documentsList = [ document for document in self.kritaInstance.documents() if document.fileName() ] for document in self.documentsList: self.widgetDocuments.addItem(document.fileName()) def refreshButtonClicked(self): self.loadDocuments() def confirmButton(self): selectedPaths = [ item.text() for item in self.widgetDocuments.selectedItems() ] selectedDocuments = [ document for document in self.documentsList for path in selectedPaths if path == document.fileName() ] self.msgBox = QMessageBox(self.mainDialog) if selectedDocuments: widget = self.tabTools.currentWidget() widget.adjust(selectedDocuments) self.msgBox.setText( i18n("The selected documents has been modified.")) else: self.msgBox.setText(i18n("Select at least one document.")) self.msgBox.exec_()
class MainWindow(QMainWindow): def __init__(self, filename): super().__init__() self.setGeometry(20, 20, 1324, 1068) self.setWindowTitle('qt-Notepad') self.setStyleSheet('font-size: 14pt; font-family: Courier;') self.show() self.init_ui() centralWidget = QWidget() self.tabs = QTabWidget(centralWidget) self.setCentralWidget(self.tabs) self.tabs.setTabsClosable(True) self.tabs.setMovable(True) self.tabs.tabCloseRequested.connect(self.closeTab) if filename: f = open(filename, 'r') filedata = f.read() f.close() newfile = QTextEdit() newfile.setText(filedata) i = self.tabs.addTab(newfile, filename) self.tabs.setCurrentIndex(i) else: self.open_file() def init_ui(self): new_action = QAction('New File', self) new_action.setShortcut('Ctrl+N') new_action.setStatusTip('Create new file') new_action.triggered.connect(self.new_file) open_action = QAction('Open...', self) open_action.setShortcut('Ctrl+O') open_action.setStatusTip('Open a file') open_action.triggered.connect(self.open_file) save_action = QAction('Save File', self) save_action.setShortcut('Ctrl+S') save_action.setStatusTip('Save current file') save_action.triggered.connect(self.save_file) new_save_action = QAction('Save File As...', self) new_save_action.setShortcut('Shift+Ctrl+S') new_save_action.setStatusTip('Save current file') new_save_action.triggered.connect(self.save_file_as) close_action = QAction('Close File', self) close_action.setShortcut('Ctrl+W') close_action.setStatusTip('Close file and exit tab') close_action.triggered.connect(self.close_file) exit_action = QAction('Exit qt-Notepad', self) exit_action.setShortcut('Ctrl+Q') exit_action.setStatusTip('Close Notepad') exit_action.triggered.connect(self.close) undo_action = QAction('Undo', self) undo_action.setShortcut('Ctrl+Z') copy_action = QAction('Copy', self) copy_action.setShortcut('Ctrl+C') cut_action = QAction('Cut', self) cut_action.setShortcut('Ctrl+X') paste_action = QAction('Paste', self) paste_action.setShortcut('Ctrl+V') minimize_action = QAction('Minimize', self) minimize_action.setShortcut('Ctrl+M') view_action = QAction('Show', self) view_action.setShortcut('Ctrl+/') menubar = self.menuBar() file_menu = menubar.addMenu('&File') edit_menu = menubar.addMenu('&Edit') view_menu = menubar.addMenu('&View') window_menu = menubar.addMenu('&Window') file_menu.addAction(new_action) file_menu.addAction(open_action) file_menu.addAction(save_action) file_menu.addAction(new_save_action) file_menu.addAction(close_action) file_menu.addAction(exit_action) edit_menu.addAction(undo_action) edit_menu.addAction(copy_action) edit_menu.addAction(cut_action) edit_menu.addAction(paste_action) view_menu.addAction(view_action) window_menu.addAction(minimize_action) def closeTab(self, currentIndex): currentQWidget = self.tabs.currentWidget() currentQWidget.deleteLater() self.tabs.removeTab(currentIndex) def new_file(self): newfile = QTextEdit() i = self.tabs.addTab(newfile, 'New Document') self.tabs.setCurrentIndex(i) def save_file(self): editor = self.tabs.currentWidget() filename = self.tabs.tabText(self.tabs.currentIndex()) if filename != 'New Document': f = open(filename, 'w') filedata = editor.toPlainText() f.write(filedata) f.close() else: self.save_file_as() def save_file_as(self): filename = QFileDialog.getSaveFileName( self, 'Save File', os.getenv('HOME'))[0] print(filename) if filename != ('', ''): f = open(filename, 'w') filedata = self.text.toPlainText() f.write(filedata) f.close() def open_file(self): filename = QFileDialog.getOpenFileName( self, 'Open File', os.getenv('HOME'))[0] f = open(filename, 'r') filedata = f.read() f.close() newfile = QTextEdit() newfile.setText(filedata) i = self.tabs.addTab(newfile, filename) self.tabs.setCurrentIndex(i) def close_file(self): self.save_file() currentIndex = self.tabs.currentIndex() self.tabs.removeTab(currentIndex)
class Window(QDialog): def __init__(self, parent=None): super(Window, self).__init__(parent) self.setGeometry(75, 75, 1800, 900) self.figure = plt.figure() self.canvas = FigureCanvas(self.figure) self.toolbar = NavigationToolbar(self.canvas, self) self.figure2 = plt.figure() self.canvas2 = FigureCanvas(self.figure2) self.toolbar2 = NavigationToolbar(self.canvas2, self) # Just some button connected to `plot` method self.button = QPushButton('Plot') self.button.clicked.connect(self.plot) # set the layout hlayout = QHBoxLayout() vlayout1 = QVBoxLayout() vlayout1.addWidget(self.toolbar) vlayout1.addWidget(self.canvas) vlayout2 = QVBoxLayout() vlayout2.addWidget(self.toolbar2) vlayout2.addWidget(self.canvas2) hlayout.addLayout(vlayout1) hlayout.addLayout(vlayout2) self.tab1 = QWidget() self.tab2 = QWidget() self.tab1.setObjectName("1") self.tab2.setObjectName("2") self.tabs = QTabWidget() mainlayout = QVBoxLayout() mainlayout.addLayout(hlayout) self.tab1UI() self.tab2UI() self.tabs.addTab(self.tab1, "Равномерное распределение") self.tabs.addTab(self.tab2, "Распределение Эрланга") mainlayout.addWidget(self.tabs) mainlayout.addWidget(self.button) self.setLayout(mainlayout) self.is_show = False def tab1UI(self): layout = QFormLayout() self.a = QDoubleSpinBox() self.b = QDoubleSpinBox() self.start_x = QDoubleSpinBox() self.stop_x = QDoubleSpinBox() self.a.setRange(-1e6, 1e6) self.b.setRange(-1e6, 1e6) self.start_x.setRange(-1e6, 1e6) self.stop_x.setRange(-1e6, 1e6) self.a.setValue(3) self.b.setValue(6) self.start_x.setValue(1) self.stop_x.setValue(10) layout.addRow("a", self.a) layout.addRow("b", self.b) layout.addRow("x start", self.start_x) layout.addRow("x end", self.stop_x) self.tab1.setLayout(layout) def tab2UI(self): layout = QFormLayout() self.lmbd = QDoubleSpinBox() self.n = QDoubleSpinBox() self.k_start = QDoubleSpinBox() self.k_stop = QDoubleSpinBox() self.lmbd.setRange(-1e6, 1e6) self.n.setRange(-1e-6, 1e6) self.k_start.setRange(-1e6, 1e6) self.k_stop.setRange(-1e6, 1e6) self.lmbd.setValue(10) self.n.setValue(2.00) self.k_start.setValue(-1.00) self.k_stop.setValue(20.00) layout.addRow("λ", self.lmbd) layout.addRow("n", self.n) layout.addRow("x start", self.k_start) layout.addRow("x end", self.k_stop) self.tab2.setLayout(layout) def show_warning(self): msg = QMessageBox(parent=self) msg.setIcon(QMessageBox.Warning) msg.setText("Некорректные данные") msg.setStandardButtons(QMessageBox.Ok) msg.exec() def getdata_uniform(self, foo): start = self.start_x.value() end = self.stop_x.value() N = self.N = 100 a = self.a.value() b = self.b.value() if (a >= b) or (start >= end): self.show_warning() return None, None h = (end - start) / N X = [start + h * i for i in range(N)] Y = [foo(a, b, x) for x in X] return X, Y def getdata_Erlang(self, foo): k_start = self.k_start.value() k_stop = self.k_stop.value() lmbd = self.lmbd.value() n = self.n.value() N = self.N = 100 h = (k_stop - k_start) / N if (k_start >= k_stop): self.show_warning() return None, None X = [k_start + h * i for i in range(N)] Y = [foo(lmbd, n, k) for k in X] return X, Y def get_status(self, type): tabname = self.tabs.currentWidget().objectName() type.append(tabname) X_d, Y_d = None, None X_f, Y_f = None, None if tabname == "1": X_d, Y_d = self.getdata_uniform(uniform_density) if X_d is None: return (None, None, None, None) X_f, Y_f = self.getdata_uniform(uniform_function) else: X_d, Y_d = self.getdata_Erlang(Erlang_density) if X_d is None: return (None, None, None, None) X_f, Y_f = self.getdata_Erlang(Erlang_function) return (X_f, Y_f, X_d, Y_d) def plot(self): type = [] X_f, Y_f, X_d, Y_d = self.get_status(type) if X_f is None: return self.figure.clear() self.figure2.clear() ax = self.figure.add_subplot(111) ax2 = self.figure2.add_subplot(111) ax.grid(True) ax2.grid(True) if type[0] == '1': ax.plot(X_d, Y_d) ax2.plot(X_f, Y_f) else: ax.plot(X_d, Y_d) ax2.plot(X_f, Y_f) ax.legend(['Пл-ть распр.']) ax2.legend(['Ф-ция распр.']) self.canvas.draw() self.canvas2.draw()
class SquidGui( QMainWindow ): defaults = {} defaults.update(SquidAxon.defaults) defaults.update(ClampCircuit.defaults) defaults.update({'runtime': 50.0, 'simdt': 0.01, 'plotdt': 0.1, 'vclamp.holdingV': 0.0, 'vclamp.holdingT': 10.0, 'vclamp.prepulseV': 0.0, 'vclamp.prepulseT': 0.0, 'vclamp.clampV': 50.0, 'vclamp.clampT': 20.0, 'iclamp.baseI': 0.0, 'iclamp.firstI': 0.1, 'iclamp.firstT': 40.0, 'iclamp.firstD': 5.0, 'iclamp.secondI': 0.0, 'iclamp.secondT': 0.0, 'iclamp.secondD': 0.0 }) def __init__(self, *args): QMainWindow.__init__(self, *args) self.squid_setup = SquidSetup() self._plotdt = SquidGui.defaults['plotdt'] self._plot_dict = defaultdict(list) self.setWindowTitle('Squid Axon simulation') self.setDockNestingEnabled(True) self._createRunControl() self.addDockWidget(QtCore.Qt.LeftDockWidgetArea, self._runControlDock) self._runControlDock.setFeatures(QDockWidget.AllDockWidgetFeatures) self._createChannelControl() self._channelCtrlBox.setWindowTitle('Channel properties') self._channelControlDock.setFeatures(QDockWidget.AllDockWidgetFeatures) self.addDockWidget(QtCore.Qt.LeftDockWidgetArea, self._channelControlDock) self._createElectronicsControl() self._electronicsDock.setFeatures(QDockWidget.AllDockWidgetFeatures) self._electronicsDock.setWindowTitle('Electronics') self.addDockWidget(QtCore.Qt.LeftDockWidgetArea, self._electronicsDock) self._createPlotWidget() self.setCentralWidget(self._plotWidget) self._createStatePlotWidget() self._createHelpMessage() self._helpWindow.setVisible(False) self._statePlotWidget.setWindowFlags(QtCore.Qt.Window) self._statePlotWidget.setWindowTitle('State plot') self._initActions() self._createRunToolBar() self._createPlotToolBar() def getFloatInput(self, widget, name): try: return float(str(widget.text())) except ValueError: QMessageBox.critical(self, 'Invalid input', 'Please enter a valid number for {}'.format(name)) raise def _createPlotWidget(self): self._plotWidget = QWidget() self._plotFigure = Figure() self._plotCanvas = FigureCanvas(self._plotFigure) self._plotCanvas.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding) self._plotCanvas.updateGeometry() self._plotCanvas.setParent(self._plotWidget) self._plotCanvas.mpl_connect('scroll_event', self._onScroll) self._plotFigure.set_canvas(self._plotCanvas) # Vm and command voltage go in the same subplot self._vm_axes = self._plotFigure.add_subplot(2,2,1, title='Membrane potential') self._vm_axes.set_ylim(-20.0, 120.0) # Channel conductances go to the same subplot self._g_axes = self._plotFigure.add_subplot(2,2,2, title='Channel conductance') self._g_axes.set_ylim(0.0, 0.5) # Injection current for Vclamp/Iclamp go to the same subplot self._im_axes = self._plotFigure.add_subplot(2,2,3, title='Injection current') self._im_axes.set_ylim(-0.5, 0.5) # Channel currents go to the same subplot self._i_axes = self._plotFigure.add_subplot(2,2,4, title='Channel current') self._i_axes.set_ylim(-10, 10) for axis in self._plotFigure.axes: axis.set_autoscale_on(False) layout = QVBoxLayout() layout.addWidget(self._plotCanvas) self._plotNavigator = NavigationToolbar(self._plotCanvas, self._plotWidget) layout.addWidget(self._plotNavigator) self._plotWidget.setLayout(layout) def _createStatePlotWidget(self): self._statePlotWidget = QWidget() self._statePlotFigure = Figure() self._statePlotCanvas = FigureCanvas(self._statePlotFigure) self._statePlotCanvas.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding) self._statePlotCanvas.updateGeometry() self._statePlotCanvas.setParent(self._statePlotWidget) self._statePlotFigure.set_canvas(self._statePlotCanvas) self._statePlotFigure.subplots_adjust(hspace=0.5) self._statePlotAxes = self._statePlotFigure.add_subplot(2,1,1, title='State plot') self._state_plot, = self._statePlotAxes.plot([], [], label='state') self._activationParamAxes = self._statePlotFigure.add_subplot(2,1,2, title='H-H activation parameters vs time') self._activationParamAxes.set_xlabel('Time (ms)') #for axis in self._plotFigure.axes: # axis.autoscale(False) self._stateplot_xvar_label = QLabel('Variable on X-axis') self._stateplot_xvar_combo = QComboBox() self._stateplot_xvar_combo.addItems(['V', 'm', 'n', 'h']) self._stateplot_xvar_combo.setCurrentText('V') self._stateplot_xvar_combo.setEditable(False) self._stateplot_xvar_combo.currentIndexChanged[str].connect( self._statePlotXSlot ) self._stateplot_yvar_label = QLabel('Variable on Y-axis') self._stateplot_yvar_combo = QComboBox() self._stateplot_yvar_combo.addItems(['V', 'm', 'n', 'h']) self._stateplot_yvar_combo.setCurrentIndex(2) self._stateplot_yvar_combo.setEditable(False) self._stateplot_yvar_combo.currentIndexChanged[str].connect(self._statePlotYSlot) self._statePlotNavigator = NavigationToolbar(self._statePlotCanvas, self._statePlotWidget) frame = QFrame() frame.setFrameStyle(QFrame.StyledPanel + QFrame.Raised) layout = QHBoxLayout() layout.addWidget(self._stateplot_xvar_label) layout.addWidget(self._stateplot_xvar_combo) layout.addWidget(self._stateplot_yvar_label) layout.addWidget(self._stateplot_yvar_combo) frame.setLayout(layout) self._closeStatePlotAction = QAction('Close', self) self._closeStatePlotAction.triggered.connect(self._statePlotWidget.close) self._closeStatePlotButton = QToolButton() self._closeStatePlotButton.setDefaultAction(self._closeStatePlotAction) layout = QVBoxLayout() layout.addWidget(frame) layout.addWidget(self._statePlotCanvas) layout.addWidget(self._statePlotNavigator) layout.addWidget(self._closeStatePlotButton) self._statePlotWidget.setLayout(layout) # Setting the close event so that when the help window is # closed the ``State plot`` button becomes unchecked self._statePlotWidget.closeEvent = lambda event: self._showStatePlotAction.setChecked(False) def _createRunControl(self): self._runControlBox = QGroupBox(self) self._runControlBox.setSizePolicy(QSizePolicy.Preferred, QSizePolicy.Preferred) self._runTimeLabel = QLabel("Run time (ms)", self._runControlBox) self._simTimeStepLabel = QLabel("Simulation time step (ms)", self._runControlBox) self._runTimeEdit = QLineEdit('%g' % (SquidGui.defaults['runtime']), self._runControlBox) set_default_line_edit_size(self._runTimeEdit) self._simTimeStepEdit = QLineEdit('%g' % (SquidGui.defaults['simdt']), self._runControlBox) set_default_line_edit_size(self._simTimeStepEdit) layout = QGridLayout() layout.addWidget(self._runTimeLabel, 0, 0) layout.addWidget(self._runTimeEdit, 0, 1) layout.addWidget(self._simTimeStepLabel, 1, 0) layout.addWidget(self._simTimeStepEdit, 1, 1) layout.setColumnStretch(2, 1.0) layout.setRowStretch(2, 1.0) self._runControlBox.setLayout(layout) self._runControlDock = QDockWidget('Simulation', self) self._runControlDock.setWidget(self._runControlBox) def _createChannelControl(self): self._channelControlDock = QDockWidget('Channels', self) self._channelCtrlBox = QGroupBox(self) self._naConductanceToggle = QCheckBox('Block Na+ channel', self._channelCtrlBox) self._naConductanceToggle.setToolTip('<html>%s</html>' % (tooltip_NaChan)) self._kConductanceToggle = QCheckBox('Block K+ channel', self._channelCtrlBox) self._kConductanceToggle.setToolTip('<html>%s</html>' % (tooltip_KChan)) self._kOutLabel = QLabel('[K+]out (mM)', self._channelCtrlBox) self._kOutEdit = QLineEdit('%g' % (self.squid_setup.squid_axon.K_out), self._channelCtrlBox) self._kOutLabel.setToolTip('<html>%s</html>' % (tooltip_Nernst)) self._kOutEdit.setToolTip('<html>%s</html>' % (tooltip_Nernst)) set_default_line_edit_size(self._kOutEdit) self._naOutLabel = QLabel('[Na+]out (mM)', self._channelCtrlBox) self._naOutEdit = QLineEdit('%g' % (self.squid_setup.squid_axon.Na_out), self._channelCtrlBox) self._naOutLabel.setToolTip('<html>%s</html>' % (tooltip_Nernst)) self._naOutEdit.setToolTip('<html>%s</html>' % (tooltip_Nernst)) set_default_line_edit_size(self._naOutEdit) self._kInLabel = QLabel('[K+]in (mM)', self._channelCtrlBox) self._kInEdit = QLineEdit('%g' % (self.squid_setup.squid_axon.K_in), self._channelCtrlBox) self._kInEdit.setToolTip(tooltip_Nernst) self._naInLabel = QLabel('[Na+]in (mM)', self._channelCtrlBox) self._naInEdit = QLineEdit('%g' % (self.squid_setup.squid_axon.Na_in), self._channelCtrlBox) self._naInEdit.setToolTip('<html>%s</html>' % (tooltip_Nernst)) self._temperatureLabel = QLabel('Temperature (C)', self._channelCtrlBox) self._temperatureEdit = QLineEdit('%g' % (self.defaults['temperature'] - CELSIUS_TO_KELVIN), self._channelCtrlBox) self._temperatureEdit.setToolTip('<html>%s</html>' % (tooltip_Nernst)) set_default_line_edit_size(self._temperatureEdit) for child in self._channelCtrlBox.children(): if isinstance(child, QLineEdit): set_default_line_edit_size(child) layout = QGridLayout(self._channelCtrlBox) layout.addWidget(self._naConductanceToggle, 0, 0) layout.addWidget(self._kConductanceToggle, 1, 0) layout.addWidget(self._naOutLabel, 2, 0) layout.addWidget(self._naOutEdit, 2, 1) layout.addWidget(self._naInLabel, 3, 0) layout.addWidget(self._naInEdit, 3, 1) layout.addWidget(self._kOutLabel, 4, 0) layout.addWidget(self._kOutEdit, 4, 1) layout.addWidget(self._kInLabel, 5, 0) layout.addWidget(self._kInEdit, 5, 1) layout.addWidget(self._temperatureLabel, 6, 0) layout.addWidget(self._temperatureEdit, 6, 1) layout.setRowStretch(7, 1.0) self._channelCtrlBox.setLayout(layout) self._channelControlDock.setWidget(self._channelCtrlBox) return self._channelCtrlBox def __get_stateplot_data(self, name): data = [] if name == 'V': data = self.squid_setup.vm_table.vector elif name == 'm': data = self.squid_setup.m_table.vector elif name == 'h': data = self.squid_setup.h_table.vector elif name == 'n': data = self.squid_setup.n_table.vector else: raise ValueError('Unrecognized selection: %s' % name ) return numpy.asarray(data) def _statePlotYSlot(self, selectedItem): ydata = self.__get_stateplot_data(str(selectedItem)) self._state_plot.set_ydata(ydata) self._statePlotAxes.set_ylabel(selectedItem) if str(selectedItem) == 'V': self._statePlotAxes.set_ylim(-20, 120) else: self._statePlotAxes.set_ylim(0, 1) self._statePlotCanvas.draw() def _statePlotXSlot(self, selectedItem): xdata = self.__get_stateplot_data(str(selectedItem)) self._state_plot.set_xdata(xdata) self._statePlotAxes.set_xlabel(selectedItem) if str(selectedItem) == 'V': self._statePlotAxes.set_xlim(-20, 120) else: self._statePlotAxes.set_xlim(0, 1) self._statePlotCanvas.draw() def _createElectronicsControl(self): """Creates a tabbed widget of voltage clamp and current clamp controls""" self._electronicsTab = QTabWidget(self) self._electronicsTab.addTab(self._getIClampCtrlBox(), 'Current clamp') self._electronicsTab.addTab(self._getVClampCtrlBox(), 'Voltage clamp') self._electronicsDock = QDockWidget(self) self._electronicsDock.setWidget(self._electronicsTab) def _getVClampCtrlBox(self): vClampPanel = QGroupBox(self) self._vClampCtrlBox = vClampPanel self._holdingVLabel = QLabel("Holding Voltage (mV)", vClampPanel) self._holdingVEdit = QLineEdit('%g' % (SquidGui.defaults['vclamp.holdingV']), vClampPanel) self._holdingTimeLabel = QLabel("Holding Time (ms)", vClampPanel) self._holdingTimeEdit = QLineEdit('%g' % (SquidGui.defaults['vclamp.holdingT']), vClampPanel) self._prePulseVLabel = QLabel("Pre-pulse Voltage (mV)", vClampPanel) self._prePulseVEdit = QLineEdit('%g' % (SquidGui.defaults['vclamp.prepulseV']), vClampPanel) self._prePulseTimeLabel = QLabel("Pre-pulse Time (ms)", vClampPanel) self._prePulseTimeEdit = QLineEdit('%g' % (SquidGui.defaults['vclamp.prepulseT']), vClampPanel) self._clampVLabel = QLabel("Clamp Voltage (mV)", vClampPanel) self._clampVEdit = QLineEdit('%g' % (SquidGui.defaults['vclamp.clampV']), vClampPanel) self._clampTimeLabel = QLabel("Clamp Time (ms)", vClampPanel) self._clampTimeEdit = QLineEdit('%g' % (SquidGui.defaults['vclamp.clampT']), vClampPanel) for child in vClampPanel.children(): if isinstance(child, QLineEdit): set_default_line_edit_size(child) layout = QGridLayout(vClampPanel) layout.addWidget(self._holdingVLabel, 0, 0) layout.addWidget(self._holdingVEdit, 0, 1) layout.addWidget(self._holdingTimeLabel, 1, 0) layout.addWidget(self._holdingTimeEdit, 1, 1) layout.addWidget(self._prePulseVLabel, 2, 0) layout.addWidget(self._prePulseVEdit, 2, 1) layout.addWidget(self._prePulseTimeLabel,3,0) layout.addWidget(self._prePulseTimeEdit, 3, 1) layout.addWidget(self._clampVLabel, 4, 0) layout.addWidget(self._clampVEdit, 4, 1) layout.addWidget(self._clampTimeLabel, 5, 0) layout.addWidget(self._clampTimeEdit, 5, 1) layout.setRowStretch(6, 1.0) vClampPanel.setLayout(layout) return self._vClampCtrlBox def _getIClampCtrlBox(self): iClampPanel = QGroupBox(self) self._iClampCtrlBox = iClampPanel self._baseCurrentLabel = QLabel("Base Current Level (uA)",iClampPanel) self._baseCurrentEdit = QLineEdit('%g' % (SquidGui.defaults['iclamp.baseI']),iClampPanel) self._firstPulseLabel = QLabel("First Pulse Current (uA)", iClampPanel) self._firstPulseEdit = QLineEdit('%g' % (SquidGui.defaults['iclamp.firstI']), iClampPanel) self._firstDelayLabel = QLabel("First Onset Delay (ms)", iClampPanel) self._firstDelayEdit = QLineEdit('%g' % (SquidGui.defaults['iclamp.firstD']),iClampPanel) self._firstPulseWidthLabel = QLabel("First Pulse Width (ms)", iClampPanel) self._firstPulseWidthEdit = QLineEdit('%g' % (SquidGui.defaults['iclamp.firstT']), iClampPanel) self._secondPulseLabel = QLabel("Second Pulse Current (uA)", iClampPanel) self._secondPulseEdit = QLineEdit('%g' % (SquidGui.defaults['iclamp.secondI']), iClampPanel) self._secondDelayLabel = QLabel("Second Onset Delay (ms)", iClampPanel) self._secondDelayEdit = QLineEdit('%g' % (SquidGui.defaults['iclamp.secondD']),iClampPanel) self._secondPulseWidthLabel = QLabel("Second Pulse Width (ms)", iClampPanel) self._secondPulseWidthEdit = QLineEdit('%g' % (SquidGui.defaults['iclamp.secondT']), iClampPanel) self._pulseMode = QComboBox(iClampPanel) self._pulseMode.addItem("Single Pulse") self._pulseMode.addItem("Pulse Train") for child in iClampPanel.children(): if isinstance(child, QLineEdit): set_default_line_edit_size(child) layout = QGridLayout(iClampPanel) layout.addWidget(self._baseCurrentLabel, 0, 0) layout.addWidget(self._baseCurrentEdit, 0, 1) layout.addWidget(self._firstPulseLabel, 1, 0) layout.addWidget(self._firstPulseEdit, 1, 1) layout.addWidget(self._firstDelayLabel, 2, 0) layout.addWidget(self._firstDelayEdit, 2, 1) layout.addWidget(self._firstPulseWidthLabel, 3, 0) layout.addWidget(self._firstPulseWidthEdit, 3, 1) layout.addWidget(self._secondPulseLabel, 4, 0) layout.addWidget(self._secondPulseEdit, 4, 1) layout.addWidget(self._secondDelayLabel, 5, 0) layout.addWidget(self._secondDelayEdit, 5, 1) layout.addWidget(self._secondPulseWidthLabel, 6, 0) layout.addWidget(self._secondPulseWidthEdit, 6, 1) layout.addWidget(self._pulseMode, 7, 0, 1, 2) layout.setRowStretch(8, 1.0) # layout.setSizeConstraint(QLayout.SetFixedSize) iClampPanel.setLayout(layout) return self._iClampCtrlBox def _overlayPlots(self, overlay): if not overlay: for axis in (self._plotFigure.axes + self._statePlotFigure.axes): title = axis.get_title() axis.clear() axis.set_title(title) suffix = '' else: suffix = '_%d' % (len(self._plot_dict['vm'])) self._vm_axes.set_xlim(0.0, self._runtime) self._g_axes.set_xlim(0.0, self._runtime) self._im_axes.set_xlim(0.0, self._runtime) self._i_axes.set_xlim(0.0, self._runtime) self._vm_plot, = self._vm_axes.plot([], [], label='Vm%s'%(suffix)) self._plot_dict['vm'].append(self._vm_plot) self._command_plot, = self._vm_axes.plot([], [], label='command%s'%(suffix)) self._plot_dict['command'].append(self._command_plot) # Channel conductances go to the same subplot self._gna_plot, = self._g_axes.plot([], [], label='Na%s'%(suffix)) self._plot_dict['gna'].append(self._gna_plot) self._gk_plot, = self._g_axes.plot([], [], label='K%s'%(suffix)) self._plot_dict['gk'].append(self._gk_plot) # Injection current for Vclamp/Iclamp go to the same subplot self._iclamp_plot, = self._im_axes.plot([], [], label='Iclamp%s'%(suffix)) self._vclamp_plot, = self._im_axes.plot([], [], label='Vclamp%s'%(suffix)) self._plot_dict['iclamp'].append(self._iclamp_plot) self._plot_dict['vclamp'].append(self._vclamp_plot) # Channel currents go to the same subplot self._ina_plot, = self._i_axes.plot([], [], label='Na%s'%(suffix)) self._plot_dict['ina'].append(self._ina_plot) self._ik_plot, = self._i_axes.plot([], [], label='K%s'%(suffix)) self._plot_dict['ik'].append(self._ik_plot) # self._i_axes.legend() # State plots self._state_plot, = self._statePlotAxes.plot([], [], label='state%s'%(suffix)) self._plot_dict['state'].append(self._state_plot) self._m_plot, = self._activationParamAxes.plot([],[], label='m%s'%(suffix)) self._h_plot, = self._activationParamAxes.plot([], [], label='h%s'%(suffix)) self._n_plot, = self._activationParamAxes.plot([], [], label='n%s'%(suffix)) self._plot_dict['m'].append(self._m_plot) self._plot_dict['h'].append(self._h_plot) self._plot_dict['n'].append(self._n_plot) if self._showLegendAction.isChecked(): for axis in (self._plotFigure.axes + self._statePlotFigure.axes): axis.legend() def _updateAllPlots(self): self._updatePlots() self._updateStatePlot() def _updatePlots(self): if len(self.squid_setup.vm_table.vector) <= 0: return vm = numpy.asarray(self.squid_setup.vm_table.vector) cmd = numpy.asarray(self.squid_setup.cmd_table.vector) ik = numpy.asarray(self.squid_setup.ik_table.vector) ina = numpy.asarray(self.squid_setup.ina_table.vector) iclamp = numpy.asarray(self.squid_setup.iclamp_table.vector) vclamp = numpy.asarray(self.squid_setup.vclamp_table.vector) gk = numpy.asarray(self.squid_setup.gk_table.vector) gna = numpy.asarray(self.squid_setup.gna_table.vector) time_series = numpy.linspace(0, self._plotdt * len(vm), len(vm)) self._vm_plot.set_data(time_series, vm) time_series = numpy.linspace(0, self._plotdt * len(cmd), len(cmd)) self._command_plot.set_data(time_series, cmd) time_series = numpy.linspace(0, self._plotdt * len(ik), len(ik)) self._ik_plot.set_data(time_series, ik) time_series = numpy.linspace(0, self._plotdt * len(ina), len(ina)) self._ina_plot.set_data(time_series, ina) time_series = numpy.linspace(0, self._plotdt * len(iclamp), len(iclamp)) self._iclamp_plot.set_data(time_series, iclamp) time_series = numpy.linspace(0, self._plotdt * len(vclamp), len(vclamp)) self._vclamp_plot.set_data(time_series, vclamp) time_series = numpy.linspace(0, self._plotdt * len(gk), len(gk)) self._gk_plot.set_data(time_series, gk) time_series = numpy.linspace(0, self._plotdt * len(gna), len(gna)) self._gna_plot.set_data(time_series, gna) # self._vm_axes.margins(y=0.1) # self._g_axes.margin(y=0.1) # self._im_axes.margins(y=0.1) # self._i_axes.margins(y=0.1) if self._autoscaleAction.isChecked(): for axis in self._plotFigure.axes: axis.relim() axis.margins(0.1, 0.1) axis.autoscale_view(tight=True) else: self._vm_axes.set_ylim(-20.0, 120.0) self._g_axes.set_ylim(0.0, 0.5) self._im_axes.set_ylim(-0.5, 0.5) self._i_axes.set_ylim(-10, 10) self._vm_axes.set_xlim(0.0, time_series[-1]) self._g_axes.set_xlim(0.0, time_series[-1]) self._im_axes.set_xlim(0.0, time_series[-1]) self._i_axes.set_xlim(0.0, time_series[-1]) self._plotCanvas.draw() def _updateStatePlot(self): if len(self.squid_setup.vm_table.vector) <= 0: return sx = str(self._stateplot_xvar_combo.currentText()) sy = str(self._stateplot_yvar_combo.currentText()) xdata = self.__get_stateplot_data(sx) ydata = self.__get_stateplot_data(sy) minlen = min(len(xdata), len(ydata)) self._state_plot.set_data(xdata[:minlen], ydata[:minlen]) self._statePlotAxes.set_xlabel(sx) self._statePlotAxes.set_ylabel(sy) if sx == 'V': self._statePlotAxes.set_xlim(-20, 120) else: self._statePlotAxes.set_xlim(0, 1) if sy == 'V': self._statePlotAxes.set_ylim(-20, 120) else: self._statePlotAxes.set_ylim(0, 1) self._activationParamAxes.set_xlim(0, self._runtime) m = self.__get_stateplot_data('m') n = self.__get_stateplot_data('n') h = self.__get_stateplot_data('h') time_series = numpy.linspace(0, self._plotdt*len(m), len(m)) self._m_plot.set_data(time_series, m) time_series = numpy.linspace(0, self._plotdt*len(h), len(h)) self._h_plot.set_data(time_series, h) time_series = numpy.linspace(0, self._plotdt*len(n), len(n)) self._n_plot.set_data(time_series, n) if self._autoscaleAction.isChecked(): for axis in self._statePlotFigure.axes: axis.relim() axis.set_autoscale_on(True) axis.autoscale_view(True) self._statePlotCanvas.draw() def _runSlot(self): if moose.isRunning(): print('Stopping simulation in progress ...') moose.stop() self._runtime = self.getFloatInput(self._runTimeEdit, self._runTimeLabel.text()) self._overlayPlots(self._overlayAction.isChecked()) self._simdt = self.getFloatInput(self._simTimeStepEdit, self._simTimeStepLabel.text()) clampMode = None singlePulse = True if self._electronicsTab.currentWidget() == self._vClampCtrlBox: clampMode = 'vclamp' baseLevel = self.getFloatInput(self._holdingVEdit, self._holdingVLabel.text()) firstDelay = self.getFloatInput(self._holdingTimeEdit, self._holdingTimeLabel.text()) firstWidth = self.getFloatInput(self._prePulseTimeEdit, self._prePulseTimeLabel.text()) firstLevel = self.getFloatInput(self._prePulseVEdit, self._prePulseVLabel.text()) secondDelay = firstWidth secondWidth = self.getFloatInput(self._clampTimeEdit, self._clampTimeLabel.text()) secondLevel = self.getFloatInput(self._clampVEdit, self._clampVLabel.text()) if not self._autoscaleAction.isChecked(): self._im_axes.set_ylim(-10.0, 10.0) else: clampMode = 'iclamp' baseLevel = self.getFloatInput(self._baseCurrentEdit, self._baseCurrentLabel.text()) firstDelay = self.getFloatInput(self._firstDelayEdit, self._firstDelayLabel.text()) firstWidth = self.getFloatInput(self._firstPulseWidthEdit, self._firstPulseWidthLabel.text()) firstLevel = self.getFloatInput(self._firstPulseEdit, self._firstPulseLabel.text()) secondDelay = self.getFloatInput(self._secondDelayEdit, self._secondDelayLabel.text()) secondLevel = self.getFloatInput(self._secondPulseEdit, self._secondPulseLabel.text()) secondWidth = self.getFloatInput(self._secondPulseWidthEdit, self._secondPulseWidthLabel.text()) singlePulse = (self._pulseMode.currentIndex() == 0) if not self._autoscaleAction.isChecked(): self._im_axes.set_ylim(-0.4, 0.4) self.squid_setup.clamp_ckt.configure_pulses(baseLevel=baseLevel, firstDelay=firstDelay, firstWidth=firstWidth, firstLevel=firstLevel, secondDelay=secondDelay, secondWidth=secondWidth, secondLevel=secondLevel, singlePulse=singlePulse) if self._kConductanceToggle.isChecked(): self.squid_setup.squid_axon.specific_gK = 0.0 else: self.squid_setup.squid_axon.specific_gK = SquidAxon.defaults['specific_gK'] if self._naConductanceToggle.isChecked(): self.squid_setup.squid_axon.specific_gNa = 0.0 else: self.squid_setup.squid_axon.specific_gNa = SquidAxon.defaults['specific_gNa'] self.squid_setup.squid_axon.celsius = self.getFloatInput(self._temperatureEdit, self._temperatureLabel.text()) self.squid_setup.squid_axon.K_out = self.getFloatInput(self._kOutEdit, self._kOutLabel.text()) self.squid_setup.squid_axon.Na_out = self.getFloatInput(self._naOutEdit, self._naOutLabel.text()) self.squid_setup.squid_axon.K_in = self.getFloatInput(self._kInEdit, self._kInLabel.text()) self.squid_setup.squid_axon.Na_in = self.getFloatInput(self._naInEdit, self._naInLabel.text()) self.squid_setup.squid_axon.updateEk() self.squid_setup.schedule(self._simdt, self._plotdt, clampMode) # The following line is for use with Qthread self.squid_setup.run(self._runtime) self._updateAllPlots() def _toggleDocking(self, on): self._channelControlDock.setFloating(on) self._electronicsDock.setFloating(on) self._runControlDock.setFloating(on) def _restoreDocks(self): self._channelControlDock.setVisible(True) self._electronicsDock.setVisible(True) self._runControlDock.setVisible(True) def _initActions(self): self._runAction = QAction(self.tr('Run'), self) self._runAction.setShortcut(self.tr('F5')) self._runAction.setToolTip('Run simulation (F5)') self._runAction.triggered.connect( self._runSlot) self._resetToDefaultsAction = QAction(self.tr('Restore defaults'), self) self._resetToDefaultsAction.setToolTip('Reset all settings to their default values') self._resetToDefaultsAction.triggered.connect( self._useDefaults) self._showLegendAction = QAction(self.tr('Display legend'), self) self._showLegendAction.setCheckable(True) self._showLegendAction.toggled.connect(self._showLegend) self._showStatePlotAction = QAction(self.tr('State plot'), self) self._showStatePlotAction.setCheckable(True) self._showStatePlotAction.setChecked(False) self._showStatePlotAction.toggled.connect(self._statePlotWidget.setVisible) self._autoscaleAction = QAction(self.tr('Auto-scale plots'), self) self._autoscaleAction.setCheckable(True) self._autoscaleAction.setChecked(False) self._autoscaleAction.toggled.connect(self._autoscale) self._overlayAction = QAction('Overlay plots', self) self._overlayAction.setCheckable(True) self._overlayAction.setChecked(False) self._dockAction = QAction('Undock all', self) self._dockAction.setCheckable(True) self._dockAction.setChecked(False) # self._dockAction.toggle.connect( self._toggleDocking) self._restoreDocksAction = QAction('Show all', self) self._restoreDocksAction.triggered.connect( self._restoreDocks) self._quitAction = QAction(self.tr('&Quit'), self) self._quitAction.setShortcut(self.tr('Ctrl+Q')) self._quitAction.triggered.connect(qApp.closeAllWindows) def _createRunToolBar(self): self._simToolBar = self.addToolBar(self.tr('Simulation control')) self._simToolBar.addAction(self._quitAction) self._simToolBar.addAction(self._runAction) self._simToolBar.addAction(self._resetToDefaultsAction) self._simToolBar.addAction(self._dockAction) self._simToolBar.addAction(self._restoreDocksAction) def _createPlotToolBar(self): self._plotToolBar = self.addToolBar(self.tr('Plotting control')) self._plotToolBar.addAction(self._showLegendAction) self._plotToolBar.addAction(self._autoscaleAction) self._plotToolBar.addAction(self._overlayAction) self._plotToolBar.addAction(self._showStatePlotAction) self._plotToolBar.addAction(self._helpAction) self._plotToolBar.addAction(self._helpBiophysicsAction) def _showLegend(self, on): if on: for axis in (self._plotFigure.axes + self._statePlotFigure.axes): axis.legend().set_visible(True) else: for axis in (self._plotFigure.axes + self._statePlotFigure.axes): axis.legend().set_visible(False) self._plotCanvas.draw() self._statePlotCanvas.draw() def _autoscale(self, on): if on: for axis in (self._plotFigure.axes + self._statePlotFigure.axes): axis.relim() axis.set_autoscale_on(True) axis.autoscale_view(True) else: for axis in self._plotFigure.axes: axis.set_autoscale_on(False) self._vm_axes.set_ylim(-20.0, 120.0) self._g_axes.set_ylim(0.0, 0.5) self._im_axes.set_ylim(-0.5, 0.5) self._i_axes.set_ylim(-10, 10) self._plotCanvas.draw() self._statePlotCanvas.draw() def _useDefaults(self): self._runTimeEdit.setText('%g' % (self.defaults['runtime'])) self._simTimeStepEdit.setText('%g' % (self.defaults['simdt'])) self._overlayAction.setChecked(False) self._naConductanceToggle.setChecked(False) self._kConductanceToggle.setChecked(False) self._kOutEdit.setText('%g' % (SquidGui.defaults['K_out'])) self._naOutEdit.setText('%g' % (SquidGui.defaults['Na_out'])) self._kInEdit.setText('%g' % (SquidGui.defaults['K_in'])) self._naInEdit.setText('%g' % (SquidGui.defaults['Na_in'])) self._temperatureEdit.setText('%g' % (SquidGui.defaults['temperature'] - CELSIUS_TO_KELVIN)) self._holdingVEdit.setText('%g' % (SquidGui.defaults['vclamp.holdingV'])) self._holdingTimeEdit.setText('%g' % (SquidGui.defaults['vclamp.holdingT'])) self._prePulseVEdit.setText('%g' % (SquidGui.defaults['vclamp.prepulseV'])) self._prePulseTimeEdit.setText('%g' % (SquidGui.defaults['vclamp.prepulseT'])) self._clampVEdit.setText('%g' % (SquidGui.defaults['vclamp.clampV'])) self._clampTimeEdit.setText('%g' % (SquidGui.defaults['vclamp.clampT'])) self._baseCurrentEdit.setText('%g' % (SquidGui.defaults['iclamp.baseI'])) self._firstPulseEdit.setText('%g' % (SquidGui.defaults['iclamp.firstI'])) self._firstDelayEdit.setText('%g' % (SquidGui.defaults['iclamp.firstD'])) self._firstPulseWidthEdit.setText('%g' % (SquidGui.defaults['iclamp.firstT'])) self._secondPulseEdit.setText('%g' % (SquidGui.defaults['iclamp.secondI'])) self._secondDelayEdit.setText('%g' % (SquidGui.defaults['iclamp.secondD'])) self._secondPulseWidthEdit.setText('%g' % (SquidGui.defaults['iclamp.secondT'])) self._pulseMode.setCurrentIndex(0) def _onScroll(self, event): if event.inaxes is None: return axes = event.inaxes zoom = 0.0 if event.button == 'up': zoom = -1.0 elif event.button == 'down': zoom = 1.0 if zoom != 0.0: self._plotNavigator.push_current() axes.get_xaxis().zoom(zoom) axes.get_yaxis().zoom(zoom) self._plotCanvas.draw() def closeEvent(self, event): qApp.closeAllWindows() def _showBioPhysicsHelp(self): self._createHelpMessage() self._helpMessageText.setText('<html><p>%s</p><p>%s</p><p>%s</p><p>%s</p><p>%s</p></html>' % (tooltip_Nernst, tooltip_Erest, tooltip_KChan, tooltip_NaChan, tooltip_Im)) self._helpWindow.setVisible(True) def _showRunningHelp(self): self._createHelpMessage() self._helpMessageText.setSource(QtCore.QUrl(self._helpBaseURL)) self._helpWindow.setVisible(True) def _createHelpMessage(self): if hasattr(self, '_helpWindow'): return self._helpWindow = QWidget() self._helpWindow.setWindowFlags(QtCore.Qt.Window) layout = QVBoxLayout() self._helpWindow.setLayout(layout) self._helpMessageArea = QScrollArea() self._helpMessageText = QTextBrowser() self._helpMessageText.setOpenExternalLinks(True) self._helpMessageArea.setWidget(self._helpMessageText) layout.addWidget(self._helpMessageText) self._squidGuiPath = os.path.dirname(os.path.abspath(__file__)) self._helpBaseURL = os.path.join(self._squidGuiPath,'help.html') self._helpMessageText.setSource(QtCore.QUrl(self._helpBaseURL)) self._helpMessageText.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding) self._helpMessageArea.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding) self._helpMessageText.setMinimumSize(800, 600) self._closeHelpAction = QAction('Close', self) self._closeHelpAction.triggered.connect(self._helpWindow.close) # Setting the close event so that the ``Help`` button is # unchecked when the help window is closed self._helpWindow.closeEvent = lambda event: self._helpAction.setChecked(False) self._helpTOCAction = QAction('Help running demo', self) self._helpTOCAction.triggered.connect( self._jumpToHelpTOC) # This panel is for putting two buttons using horizontal # layout panel = QFrame() panel.setFrameStyle(QFrame.StyledPanel + QFrame.Raised) layout.addWidget(panel) layout = QHBoxLayout() panel.setLayout(layout) self._helpAction = QAction('Help running', self) self._helpAction.triggered.connect(self._showRunningHelp) self._helpBiophysicsAction = QAction('Help biophysics', self) self._helpBiophysicsAction.triggered.connect(self._showBioPhysicsHelp) self._helpTOCButton = QToolButton() self._helpTOCButton.setDefaultAction(self._helpTOCAction) self._helpBiophysicsButton = QToolButton() self._helpBiophysicsButton.setDefaultAction(self._helpBiophysicsAction) layout.addWidget(self._helpTOCButton) layout.addWidget(self._helpBiophysicsButton) self._closeHelpButton = QToolButton() self._closeHelpButton.setDefaultAction(self._closeHelpAction) layout.addWidget(self._closeHelpButton) def _jumpToHelpTOC(self): self._helpMessageText.setSource(QtCore.QUrl(self._helpBaseURL))
class QueryUI(QWidget): def __init__(self): super().__init__() try: self.keyValues = getOfficialKeys() except RequestException: logging.warning( "There was a problem with the internet connection. You will not be able to see the existing keys." ) self.onClearPolygonF = lambda: None self.onPolygonEnabledF = lambda: None self.onPolygonDisabledF = lambda: None self.currentHtml = EMPTY_HTML self.initUI() def initUI(self): self.layout = QVBoxLayout() self.layout.setContentsMargins(0, 0, 0, 0) self.requestAreaWidget = QToolBox() self.requestAreaWidget.layout().setSpacing(1) self.requestTabs = QTabWidget() self.requestTabs.setUsesScrollButtons(True) self.requestTabs.currentChanged.connect(self.__updateTabSizes__) self.requestAreaWidget.addItem(self.requestTabs, "Requests") self.requestOps = RequestsOperations(self) self.requestAreaWidget.addItem(self.requestOps, "Operations") self.generalConfig = GlobalOverpassSettingUI(self) self.requestAreaWidget.addItem(self.generalConfig, "General") self.disambiguationWidget = DisambiguationWidget( self.__getRequestByName__, self.__applyTableRow__, self) self.requestAreaWidget.addItem(self.disambiguationWidget, "Disambiguation") self.headers = self.requestAreaWidget.findChildren( QAbstractButton, "qt_toolbox_toolboxbutton") self.requestAreaWidget.currentChanged.connect( self.__onToolTabChanged__) self.headers[0].setIcon(QIcon(os.path.join(picturesDir, "arrowUp.png"))) for i in range(1, len(self.headers)): self.headers[i].setIcon( QIcon(os.path.join(picturesDir, "arrowDown.png"))) self.layout.addWidget(self.requestAreaWidget) self.setLayout(self.layout) def __getRequestByName__(self, requestName): for requestWidget in self.findChildren(RequestWidget): if requestWidget.getName() == requestName: return requestWidget.getRequest() return None def __applyTableRow__(self, name, data): filters, ids = data for requestWidget in self.findChildren(RequestWidget): if requestWidget.getName() == name: for newFilter in filters: requestWidget.addFilter(newFilter) break if len(ids) > 0: idsRequestName = SetNameManagement.getUniqueSetName() request = OverpassRequest(OsmType.WAYS, Surround.NONE, idsRequestName) request.setIds(ids) self.addRequest(request) differenceOpName = SetNameManagement.getUniqueSetName() self.requestOps.addOp(OverpassDiff(name, differenceOpName), [idsRequestName]) self.requestOps.setOutputSet(differenceOpName) logging.info("Configuration from the table row has been applied.") def __onToolTabChanged__(self, i): for h in range(len(self.headers)): if h == i: self.headers[h].setIcon( QIcon(os.path.join(picturesDir, "arrowUp.png"))) else: self.headers[h].setIcon( QIcon(os.path.join(picturesDir, "arrowDown.png"))) def __updateTabSizes__(self, index): for i in range(self.requestTabs.count()): if i != index: self.requestTabs.widget(i).setSizePolicy( QSizePolicy.Ignored, QSizePolicy.Ignored) if index >= 0: self.requestTabs.widget(index).setSizePolicy( QSizePolicy.Preferred, QSizePolicy.Preferred) self.requestTabs.widget(index).resize( self.requestTabs.widget(index).minimumSizeHint()) self.requestTabs.widget(index).adjustSize() def setOnRequestChanged(self, f): self.requestTabs.currentChanged.connect(f) def addRequestByFilters(self, filters=None): requestWidget = RequestWidget(self, self.keyValues) setName = requestWidget.requestName requestWidget.changePage(self.currentHtml) self.requestTabs.addTab(requestWidget, setName) self.requestOps.addRequest(setName) self.disambiguationWidget.addSet(setName) if filters is not None: for filter in filters: requestWidget.addFilter(filter) def addRequest(self, request): if not SetNameManagement.isAvailable(request.name): raise ValueError("There is another request with the same name.") else: SetNameManagement.assign(request.name) requestWidget = RequestWidget(self, self.keyValues, request) requestWidget.changePage(self.currentHtml) self.requestTabs.addTab(requestWidget, request.name) self.requestOps.addRequest(request.name) self.disambiguationWidget.addSet(request.name) def removeRequest(self): requestName = self.requestTabs.currentWidget().getName() self.requestOps.removeSetAndDependencies(requestName) self.disambiguationWidget.removeSet(requestName) currentRequestWidget = self.requestTabs.currentWidget() SetNameManagement.releaseName(currentRequestWidget.requestName) self.requestTabs.removeTab(self.requestTabs.currentIndex()) currentRequestWidget.deleteLater() def requestsCount(self): return self.requestTabs.count() def getQuery(self): query = OverpassQuery(self.requestOps.outputSet()) query.addDate(self.generalConfig.getDate()) for i in range(self.requestTabs.count()): query.addRequest(self.requestTabs.widget(i).getRequest()) for op in self.requestOps.ops: query.addSetsOp(op) return query def setQuery(self, query): self.reset() for request in query.requests: self.addRequest(request) for op in query.ops: self.requestOps.addOp(op) if query.config.get("date") is not None: self.generalConfig.setDate( datetime.strptime(query.config["date"], "%Y-%m-%dT00:00:00Z")) else: self.generalConfig.setDate() self.requestOps.setOutputSet(query.outputSet) def reset(self): while self.requestTabs.count() > 0: self.removeRequest() self.generalConfig.setDate() def updateMaps(self, html): self.currentHtml = html for requestWidget in self.findChildren(RequestWidget): requestWidget.changePage(html) return self.getCurrentMap() def updateMapFromRow(self): return self.updateMaps( self.disambiguationWidget.getHtmlFromSelectedRow()) def getCurrentMap(self): if self.requestTabs.currentWidget() is None: return None else: return self.requestTabs.currentWidget().getMap()
class ReTextWindow(QMainWindow): def __init__(self, parent=None): QMainWindow.__init__(self, parent) self.resize(950, 700) screenRect = QDesktopWidget().screenGeometry() if globalSettings.windowGeometry: self.restoreGeometry(globalSettings.windowGeometry) else: self.move((screenRect.width()-self.width())/2, (screenRect.height()-self.height())/2) if not screenRect.contains(self.geometry()): self.showMaximized() if globalSettings.iconTheme: QIcon.setThemeName(globalSettings.iconTheme) if QIcon.themeName() in ('hicolor', ''): if not QFile.exists(icon_path + 'document-new.png'): QIcon.setThemeName(get_icon_theme()) if QFile.exists(icon_path+'retext.png'): self.setWindowIcon(QIcon(icon_path+'retext.png')) elif QFile.exists('/usr/share/pixmaps/retext.png'): self.setWindowIcon(QIcon('/usr/share/pixmaps/retext.png')) else: self.setWindowIcon(QIcon.fromTheme('retext', QIcon.fromTheme('accessories-text-editor'))) self.tabWidget = QTabWidget(self) self.initTabWidget() self.setCentralWidget(self.tabWidget) self.tabWidget.currentChanged.connect(self.changeIndex) self.tabWidget.tabCloseRequested.connect(self.closeTab) toolBar = QToolBar(self.tr('File toolbar'), self) self.addToolBar(Qt.TopToolBarArea, toolBar) self.editBar = QToolBar(self.tr('Edit toolbar'), self) self.addToolBar(Qt.TopToolBarArea, self.editBar) self.searchBar = QToolBar(self.tr('Search toolbar'), self) self.addToolBar(Qt.BottomToolBarArea, self.searchBar) toolBar.setVisible(not globalSettings.hideToolBar) self.editBar.setVisible(not globalSettings.hideToolBar) self.actionNew = self.act(self.tr('New'), 'document-new', self.createNew, shct=QKeySequence.New) self.actionNew.setPriority(QAction.LowPriority) self.actionOpen = self.act(self.tr('Open'), 'document-open', self.openFile, shct=QKeySequence.Open) self.actionOpen.setPriority(QAction.LowPriority) self.actionSetEncoding = self.act(self.tr('Set encoding'), trig=self.showEncodingDialog) self.actionSetEncoding.setEnabled(False) self.actionReload = self.act(self.tr('Reload'), 'view-refresh', lambda: self.currentTab.readTextFromFile()) self.actionReload.setEnabled(False) self.actionSave = self.act(self.tr('Save'), 'document-save', self.saveFile, shct=QKeySequence.Save) self.actionSave.setEnabled(False) self.actionSave.setPriority(QAction.LowPriority) self.actionSaveAs = self.act(self.tr('Save as'), 'document-save-as', self.saveFileAs, shct=QKeySequence.SaveAs) self.actionNextTab = self.act(self.tr('Next tab'), 'go-next', lambda: self.switchTab(1), shct=Qt.CTRL+Qt.Key_PageDown) self.actionPrevTab = self.act(self.tr('Previous tab'), 'go-previous', lambda: self.switchTab(-1), shct=Qt.CTRL+Qt.Key_PageUp) self.actionPrint = self.act(self.tr('Print'), 'document-print', self.printFile, shct=QKeySequence.Print) self.actionPrint.setPriority(QAction.LowPriority) self.actionPrintPreview = self.act(self.tr('Print preview'), 'document-print-preview', self.printPreview) self.actionViewHtml = self.act(self.tr('View HTML code'), 'text-html', self.viewHtml) self.actionChangeEditorFont = self.act(self.tr('Change editor font'), trig=self.changeEditorFont) self.actionChangePreviewFont = self.act(self.tr('Change preview font'), trig=self.changePreviewFont) self.actionSearch = self.act(self.tr('Find text'), 'edit-find', shct=QKeySequence.Find) self.actionSearch.setCheckable(True) self.actionSearch.triggered[bool].connect(self.searchBar.setVisible) self.searchBar.visibilityChanged.connect(self.searchBarVisibilityChanged) self.actionPreview = self.act(self.tr('Preview'), shct=Qt.CTRL+Qt.Key_E, trigbool=self.preview) if QIcon.hasThemeIcon('document-preview'): self.actionPreview.setIcon(QIcon.fromTheme('document-preview')) elif QIcon.hasThemeIcon('preview-file'): self.actionPreview.setIcon(QIcon.fromTheme('preview-file')) elif QIcon.hasThemeIcon('x-office-document'): self.actionPreview.setIcon(QIcon.fromTheme('x-office-document')) else: self.actionPreview.setIcon(QIcon(icon_path+'document-preview.png')) self.actionLivePreview = self.act(self.tr('Live preview'), shct=Qt.CTRL+Qt.Key_L, trigbool=self.enableLivePreview) menuPreview = QMenu() menuPreview.addAction(self.actionLivePreview) self.actionPreview.setMenu(menuPreview) self.actionTableMode = self.act(self.tr('Table mode'), shct=Qt.CTRL+Qt.Key_T, trigbool=lambda x: self.currentTab.editBox.enableTableMode(x)) if ReTextFakeVimHandler: self.actionFakeVimMode = self.act(self.tr('FakeVim mode'), shct=Qt.CTRL+Qt.ALT+Qt.Key_V, trigbool=self.enableFakeVimMode) if globalSettings.useFakeVim: self.actionFakeVimMode.setChecked(True) self.enableFakeVimMode(True) self.actionFullScreen = self.act(self.tr('Fullscreen mode'), 'view-fullscreen', shct=Qt.Key_F11, trigbool=self.enableFullScreen) self.actionFullScreen.setPriority(QAction.LowPriority) self.actionConfig = self.act(self.tr('Preferences'), icon='preferences-system', trig=self.openConfigDialog) self.actionConfig.setMenuRole(QAction.PreferencesRole) self.actionSaveHtml = self.act('HTML', 'text-html', self.saveFileHtml) self.actionPdf = self.act('PDF', 'application-pdf', self.savePdf) self.actionOdf = self.act('ODT', 'x-office-document', self.saveOdf) self.getExportExtensionsList() self.actionQuit = self.act(self.tr('Quit'), 'application-exit', shct=QKeySequence.Quit) self.actionQuit.setMenuRole(QAction.QuitRole) self.actionQuit.triggered.connect(self.close) self.actionUndo = self.act(self.tr('Undo'), 'edit-undo', lambda: self.currentTab.editBox.undo(), shct=QKeySequence.Undo) self.actionRedo = self.act(self.tr('Redo'), 'edit-redo', lambda: self.currentTab.editBox.redo(), shct=QKeySequence.Redo) self.actionCopy = self.act(self.tr('Copy'), 'edit-copy', lambda: self.currentTab.editBox.copy(), shct=QKeySequence.Copy) self.actionCut = self.act(self.tr('Cut'), 'edit-cut', lambda: self.currentTab.editBox.cut(), shct=QKeySequence.Cut) self.actionPaste = self.act(self.tr('Paste'), 'edit-paste', lambda: self.currentTab.editBox.paste(), shct=QKeySequence.Paste) self.actionUndo.setEnabled(False) self.actionRedo.setEnabled(False) self.actionCopy.setEnabled(False) self.actionCut.setEnabled(False) qApp = QApplication.instance() qApp.clipboard().dataChanged.connect(self.clipboardDataChanged) self.clipboardDataChanged() if enchant_available: self.actionEnableSC = self.act(self.tr('Enable'), trigbool=self.enableSpellCheck) self.actionSetLocale = self.act(self.tr('Set locale'), trig=self.changeLocale) self.actionWebKit = self.act(self.tr('Use WebKit renderer'), trigbool=self.enableWebKit) self.actionWebKit.setChecked(globalSettings.useWebKit) self.actionShow = self.act(self.tr('Show directory'), 'system-file-manager', self.showInDir) self.actionFind = self.act(self.tr('Next'), 'go-next', self.find, shct=QKeySequence.FindNext) self.actionFindPrev = self.act(self.tr('Previous'), 'go-previous', lambda: self.find(back=True), shct=QKeySequence.FindPrevious) self.actionCloseSearch = self.act(self.tr('Close'), 'window-close', lambda: self.searchBar.setVisible(False)) self.actionCloseSearch.setPriority(QAction.LowPriority) self.actionHelp = self.act(self.tr('Get help online'), 'help-contents', self.openHelp) self.aboutWindowTitle = self.tr('About ReText') self.actionAbout = self.act(self.aboutWindowTitle, 'help-about', self.aboutDialog) self.actionAbout.setMenuRole(QAction.AboutRole) self.actionAboutQt = self.act(self.tr('About Qt')) self.actionAboutQt.setMenuRole(QAction.AboutQtRole) self.actionAboutQt.triggered.connect(qApp.aboutQt) availableMarkups = markups.get_available_markups() if not availableMarkups: print('Warning: no markups are available!') self.defaultMarkup = availableMarkups[0] if availableMarkups else None if globalSettings.defaultMarkup: mc = markups.find_markup_class_by_name(globalSettings.defaultMarkup) if mc and mc.available(): self.defaultMarkup = mc if len(availableMarkups) > 1: self.chooseGroup = QActionGroup(self) markupActions = [] for markup in availableMarkups: markupAction = self.act(markup.name, trigbool=self.markupFunction(markup)) if markup == self.defaultMarkup: markupAction.setChecked(True) self.chooseGroup.addAction(markupAction) markupActions.append(markupAction) self.actionBold = self.act(self.tr('Bold'), shct=QKeySequence.Bold, trig=lambda: self.insertFormatting('bold')) self.actionItalic = self.act(self.tr('Italic'), shct=QKeySequence.Italic, trig=lambda: self.insertFormatting('italic')) self.actionUnderline = self.act(self.tr('Underline'), shct=QKeySequence.Underline, trig=lambda: self.insertFormatting('underline')) self.usefulTags = ('header', 'italic', 'bold', 'underline', 'numbering', 'bullets', 'image', 'link', 'inline code', 'code block', 'blockquote') self.usefulChars = ('deg', 'divide', 'dollar', 'hellip', 'laquo', 'larr', 'lsquo', 'mdash', 'middot', 'minus', 'nbsp', 'ndash', 'raquo', 'rarr', 'rsquo', 'times') self.formattingBox = QComboBox(self.editBar) self.formattingBox.addItem(self.tr('Formatting')) self.formattingBox.addItems(self.usefulTags) self.formattingBox.activated[str].connect(self.insertFormatting) self.symbolBox = QComboBox(self.editBar) self.symbolBox.addItem(self.tr('Symbols')) self.symbolBox.addItems(self.usefulChars) self.symbolBox.activated.connect(self.insertSymbol) self.updateStyleSheet() menubar = self.menuBar() menuFile = menubar.addMenu(self.tr('File')) menuEdit = menubar.addMenu(self.tr('Edit')) menuHelp = menubar.addMenu(self.tr('Help')) menuFile.addAction(self.actionNew) menuFile.addAction(self.actionOpen) self.menuRecentFiles = menuFile.addMenu(self.tr('Open recent')) self.menuRecentFiles.aboutToShow.connect(self.updateRecentFiles) menuFile.addAction(self.actionShow) menuFile.addAction(self.actionSetEncoding) menuFile.addAction(self.actionReload) menuFile.addSeparator() menuFile.addAction(self.actionSave) menuFile.addAction(self.actionSaveAs) menuFile.addSeparator() menuFile.addAction(self.actionNextTab) menuFile.addAction(self.actionPrevTab) menuFile.addSeparator() menuExport = menuFile.addMenu(self.tr('Export')) menuExport.addAction(self.actionSaveHtml) menuExport.addAction(self.actionOdf) menuExport.addAction(self.actionPdf) if self.extensionActions: menuExport.addSeparator() for action, mimetype in self.extensionActions: menuExport.addAction(action) menuExport.aboutToShow.connect(self.updateExtensionsVisibility) menuFile.addAction(self.actionPrint) menuFile.addAction(self.actionPrintPreview) menuFile.addSeparator() menuFile.addAction(self.actionQuit) menuEdit.addAction(self.actionUndo) menuEdit.addAction(self.actionRedo) menuEdit.addSeparator() menuEdit.addAction(self.actionCut) menuEdit.addAction(self.actionCopy) menuEdit.addAction(self.actionPaste) menuEdit.addSeparator() if enchant_available: menuSC = menuEdit.addMenu(self.tr('Spell check')) menuSC.addAction(self.actionEnableSC) menuSC.addAction(self.actionSetLocale) menuEdit.addAction(self.actionSearch) menuEdit.addAction(self.actionChangeEditorFont) menuEdit.addAction(self.actionChangePreviewFont) menuEdit.addSeparator() if len(availableMarkups) > 1: self.menuMode = menuEdit.addMenu(self.tr('Default markup')) for markupAction in markupActions: self.menuMode.addAction(markupAction) menuFormat = menuEdit.addMenu(self.tr('Formatting')) menuFormat.addAction(self.actionBold) menuFormat.addAction(self.actionItalic) menuFormat.addAction(self.actionUnderline) menuEdit.addAction(self.actionWebKit) menuEdit.addSeparator() menuEdit.addAction(self.actionViewHtml) menuEdit.addAction(self.actionPreview) menuEdit.addAction(self.actionTableMode) if ReTextFakeVimHandler: menuEdit.addAction(self.actionFakeVimMode) menuEdit.addSeparator() menuEdit.addAction(self.actionFullScreen) menuEdit.addAction(self.actionConfig) menuHelp.addAction(self.actionHelp) menuHelp.addSeparator() menuHelp.addAction(self.actionAbout) menuHelp.addAction(self.actionAboutQt) toolBar.setToolButtonStyle(Qt.ToolButtonTextBesideIcon) toolBar.addAction(self.actionNew) toolBar.addSeparator() toolBar.addAction(self.actionOpen) toolBar.addAction(self.actionSave) toolBar.addAction(self.actionPrint) toolBar.addSeparator() toolBar.addAction(self.actionPreview) toolBar.addAction(self.actionFullScreen) self.editBar.addAction(self.actionUndo) self.editBar.addAction(self.actionRedo) self.editBar.addSeparator() self.editBar.addAction(self.actionCut) self.editBar.addAction(self.actionCopy) self.editBar.addAction(self.actionPaste) self.editBar.addSeparator() self.editBar.addWidget(self.formattingBox) self.editBar.addWidget(self.symbolBox) self.searchEdit = QLineEdit(self.searchBar) self.searchEdit.setPlaceholderText(self.tr('Search')) self.searchEdit.returnPressed.connect(self.find) self.csBox = QCheckBox(self.tr('Case sensitively'), self.searchBar) self.searchBar.addWidget(self.searchEdit) self.searchBar.addSeparator() self.searchBar.addWidget(self.csBox) self.searchBar.addAction(self.actionFindPrev) self.searchBar.addAction(self.actionFind) self.searchBar.addAction(self.actionCloseSearch) self.searchBar.setToolButtonStyle(Qt.ToolButtonTextBesideIcon) self.searchBar.setVisible(False) self.autoSaveEnabled = globalSettings.autoSave if self.autoSaveEnabled: timer = QTimer(self) timer.start(60000) timer.timeout.connect(self.saveAll) self.ind = None if enchant_available: self.sl = globalSettings.spellCheckLocale if self.sl: try: enchant.Dict(self.sl) except Exception as e: print(e, file=sys.stderr) self.sl = None if globalSettings.spellCheck: self.actionEnableSC.setChecked(True) self.fileSystemWatcher = QFileSystemWatcher() self.fileSystemWatcher.fileChanged.connect(self.fileChanged) def iterateTabs(self): for i in range(self.tabWidget.count()): yield self.tabWidget.widget(i).tab def updateStyleSheet(self): if globalSettings.styleSheet: sheetfile = QFile(globalSettings.styleSheet) sheetfile.open(QIODevice.ReadOnly) self.ss = QTextStream(sheetfile).readAll() sheetfile.close() else: palette = QApplication.palette() self.ss = 'html { color: %s; }\n' % palette.color(QPalette.WindowText).name() self.ss += 'td, th { border: 1px solid #c3c3c3; padding: 0 3px 0 3px; }\n' self.ss += 'table { border-collapse: collapse; }\n' def initTabWidget(self): def dragEnterEvent(e): e.acceptProposedAction() def dropEvent(e): fn = bytes(e.mimeData().data('text/plain')).decode().rstrip() if fn.startswith('file:'): fn = QUrl(fn).toLocalFile() self.openFileWrapper(fn) self.tabWidget.setTabsClosable(True) self.tabWidget.setAcceptDrops(True) self.tabWidget.setMovable(True) self.tabWidget.dragEnterEvent = dragEnterEvent self.tabWidget.dropEvent = dropEvent def act(self, name, icon=None, trig=None, trigbool=None, shct=None): if not isinstance(shct, QKeySequence): shct = QKeySequence(shct) if icon: action = QAction(self.actIcon(icon), name, self) else: action = QAction(name, self) if trig: action.triggered.connect(trig) elif trigbool: action.setCheckable(True) action.triggered[bool].connect(trigbool) if shct: action.setShortcut(shct) return action def actIcon(self, name): return QIcon.fromTheme(name, QIcon(icon_path+name+'.png')) def printError(self): import traceback print('Exception occured while parsing document:', file=sys.stderr) traceback.print_exc() def createTab(self, fileName): self.currentTab = ReTextTab(self, fileName, previewState=int(globalSettings.livePreviewByDefault)) self.tabWidget.addTab(self.currentTab.getSplitter(), self.tr("New document")) def closeTab(self, ind): if self.maybeSave(ind): if self.tabWidget.count() == 1: self.createTab("") currentWidget = self.tabWidget.widget(ind) if currentWidget.tab.fileName: self.fileSystemWatcher.removePath(currentWidget.tab.fileName) del currentWidget.tab self.tabWidget.removeTab(ind) def docTypeChanged(self): markupClass = self.currentTab.getMarkupClass() if type(self.currentTab.markup) != markupClass: self.currentTab.setMarkupClass(markupClass) self.currentTab.updatePreviewBox() dtMarkdown = (markupClass == markups.MarkdownMarkup) dtMkdOrReST = dtMarkdown or (markupClass == markups.ReStructuredTextMarkup) self.formattingBox.setEnabled(dtMarkdown) self.symbolBox.setEnabled(dtMarkdown) self.actionUnderline.setEnabled(dtMarkdown) self.actionBold.setEnabled(dtMkdOrReST) self.actionItalic.setEnabled(dtMkdOrReST) canReload = bool(self.currentTab.fileName) and not self.autoSaveActive() self.actionSetEncoding.setEnabled(canReload) self.actionReload.setEnabled(canReload) def changeIndex(self, ind): self.currentTab = self.tabWidget.currentWidget().tab editBox = self.currentTab.editBox previewState = self.currentTab.previewState self.actionUndo.setEnabled(editBox.document().isUndoAvailable()) self.actionRedo.setEnabled(editBox.document().isRedoAvailable()) self.actionCopy.setEnabled(editBox.textCursor().hasSelection()) self.actionCut.setEnabled(editBox.textCursor().hasSelection()) self.actionPreview.setChecked(previewState >= PreviewLive) self.actionLivePreview.setChecked(previewState == PreviewLive) self.actionTableMode.setChecked(editBox.tableModeEnabled) self.editBar.setEnabled(previewState < PreviewNormal) self.ind = ind if self.currentTab.fileName: self.setCurrentFile() else: self.setWindowTitle(self.tr('New document') + '[*]') self.docTypeChanged() self.modificationChanged(editBox.document().isModified()) editBox.setFocus(Qt.OtherFocusReason) def changeEditorFont(self): font, ok = QFontDialog.getFont(globalSettings.editorFont, self) if ok: globalSettings.editorFont = font for tab in self.iterateTabs(): tab.editBox.updateFont() def changePreviewFont(self): font, ok = QFontDialog.getFont(globalSettings.font, self) if ok: globalSettings.font = font for tab in self.iterateTabs(): tab.updatePreviewBox() def preview(self, viewmode): self.currentTab.previewState = viewmode * 2 self.actionLivePreview.setChecked(False) self.editBar.setDisabled(viewmode) self.currentTab.updateBoxesVisibility() if viewmode: self.currentTab.updatePreviewBox() def enableLivePreview(self, livemode): self.currentTab.previewState = int(livemode) self.actionPreview.setChecked(livemode) self.editBar.setEnabled(True) self.currentTab.updateBoxesVisibility() if livemode: self.currentTab.updatePreviewBox() def enableWebKit(self, enable): globalSettings.useWebKit = enable for i in range(self.tabWidget.count()): splitter = self.tabWidget.widget(i) tab = splitter.tab tab.previewBox.disconnectExternalSignals() tab.previewBox.setParent(None) tab.previewBox.deleteLater() tab.previewBox = tab.createPreviewBox(tab.editBox) tab.previewBox.setMinimumWidth(125) splitter.addWidget(tab.previewBox) splitter.setSizes((50, 50)) tab.updatePreviewBox() tab.updateBoxesVisibility() def enableCopy(self, copymode): self.actionCopy.setEnabled(copymode) self.actionCut.setEnabled(copymode) def enableFullScreen(self, yes): if yes: self.showFullScreen() else: self.showNormal() def openConfigDialog(self): dlg = ConfigDialog(self) dlg.setWindowTitle(self.tr('Preferences')) dlg.show() def enableFakeVimMode(self, yes): globalSettings.useFakeVim = yes if yes: FakeVimMode.init(self) for tab in self.iterateTabs(): tab.installFakeVimHandler() else: FakeVimMode.exit(self) def enableSpellCheck(self, yes): if yes: self.setAllDictionaries(enchant.Dict(self.sl or None)) else: self.setAllDictionaries(None) globalSettings.spellCheck = yes def setAllDictionaries(self, dictionary): for tab in self.iterateTabs(): hl = tab.highlighter hl.dictionary = dictionary hl.rehighlight() def changeLocale(self): if self.sl: localedlg = LocaleDialog(self, defaultText=self.sl) else: localedlg = LocaleDialog(self) if localedlg.exec() != QDialog.Accepted: return sl = localedlg.localeEdit.text() setdefault = localedlg.checkBox.isChecked() if sl: try: sl = str(sl) enchant.Dict(sl) except Exception as e: QMessageBox.warning(self, '', str(e)) else: self.sl = sl self.enableSpellCheck(self.actionEnableSC.isChecked()) else: self.sl = None self.enableSpellCheck(self.actionEnableSC.isChecked()) if setdefault: globalSettings.spellCheckLocale = sl def searchBarVisibilityChanged(self, visible): self.actionSearch.setChecked(visible) if visible: self.searchEdit.setFocus(Qt.ShortcutFocusReason) def find(self, back=False): flags = QTextDocument.FindFlags() if back: flags |= QTextDocument.FindBackward if self.csBox.isChecked(): flags |= QTextDocument.FindCaseSensitively text = self.searchEdit.text() editBox = self.currentTab.editBox cursor = editBox.textCursor() newCursor = editBox.document().find(text, cursor, flags) if not newCursor.isNull(): editBox.setTextCursor(newCursor) return self.setSearchEditColor(True) cursor.movePosition(QTextCursor.End if back else QTextCursor.Start) newCursor = editBox.document().find(text, cursor, flags) if not newCursor.isNull(): editBox.setTextCursor(newCursor) return self.setSearchEditColor(True) self.setSearchEditColor(False) def setSearchEditColor(self, found): palette = self.searchEdit.palette() palette.setColor(QPalette.Active, QPalette.Base, Qt.white if found else QColor(255, 102, 102)) self.searchEdit.setPalette(palette) def showInDir(self): if self.currentTab.fileName: path = QFileInfo(self.currentTab.fileName).path() QDesktopServices.openUrl(QUrl.fromLocalFile(path)) else: QMessageBox.warning(self, '', self.tr("Please, save the file somewhere.")) def setCurrentFile(self): self.setWindowTitle("") self.tabWidget.setTabText(self.ind, self.currentTab.getDocumentTitle(baseName=True)) self.tabWidget.setTabToolTip(self.ind, self.currentTab.fileName or '') self.setWindowFilePath(self.currentTab.fileName) files = readListFromSettings("recentFileList") while self.currentTab.fileName in files: files.remove(self.currentTab.fileName) files.insert(0, self.currentTab.fileName) if len(files) > 10: del files[10:] writeListToSettings("recentFileList", files) QDir.setCurrent(QFileInfo(self.currentTab.fileName).dir().path()) self.docTypeChanged() def createNew(self, text=None): self.createTab("") self.ind = self.tabWidget.count()-1 self.tabWidget.setCurrentIndex(self.ind) if text: self.currentTab.editBox.textCursor().insertText(text) def switchTab(self, shift=1): self.tabWidget.setCurrentIndex((self.ind + shift) % self.tabWidget.count()) def updateRecentFiles(self): self.menuRecentFiles.clear() self.recentFilesActions = [] filesOld = readListFromSettings("recentFileList") files = [] for f in filesOld: if QFile.exists(f): files.append(f) self.recentFilesActions.append(self.act(f, trig=self.openFunction(f))) writeListToSettings("recentFileList", files) for action in self.recentFilesActions: self.menuRecentFiles.addAction(action) def markupFunction(self, markup): return lambda: self.setDefaultMarkup(markup) def openFunction(self, fileName): return lambda: self.openFileWrapper(fileName) def extensionFunction(self, data): return lambda: \ self.runExtensionCommand(data['Exec'], data['FileFilter'], data['DefaultExtension']) def getExportExtensionsList(self): extensions = [] for extsprefix in datadirs: extsdir = QDir(extsprefix+'/export-extensions/') if extsdir.exists(): for fileInfo in extsdir.entryInfoList(['*.desktop', '*.ini'], QDir.Files | QDir.Readable): extensions.append(self.readExtension(fileInfo.filePath())) locale = QLocale.system().name() self.extensionActions = [] for extension in extensions: try: if ('Name[%s]' % locale) in extension: name = extension['Name[%s]' % locale] elif ('Name[%s]' % locale.split('_')[0]) in extension: name = extension['Name[%s]' % locale.split('_')[0]] else: name = extension['Name'] data = {} for prop in ('FileFilter', 'DefaultExtension', 'Exec'): if 'X-ReText-'+prop in extension: data[prop] = extension['X-ReText-'+prop] elif prop in extension: data[prop] = extension[prop] else: data[prop] = '' action = self.act(name, trig=self.extensionFunction(data)) if 'Icon' in extension: action.setIcon(self.actIcon(extension['Icon'])) mimetype = extension['MimeType'] if 'MimeType' in extension else None except KeyError: print('Failed to parse extension: Name is required', file=sys.stderr) else: self.extensionActions.append((action, mimetype)) def updateExtensionsVisibility(self): markupClass = self.currentTab.getMarkupClass() for action in self.extensionActions: if markupClass is None: action[0].setEnabled(False) continue mimetype = action[1] if mimetype == None: enabled = True elif markupClass == markups.MarkdownMarkup: enabled = (mimetype in ("text/x-retext-markdown", "text/x-markdown")) elif markupClass == markups.ReStructuredTextMarkup: enabled = (mimetype in ("text/x-retext-rst", "text/x-rst")) else: enabled = False action[0].setEnabled(enabled) def readExtension(self, fileName): extFile = QFile(fileName) extFile.open(QIODevice.ReadOnly) extension = {} stream = QTextStream(extFile) while not stream.atEnd(): line = stream.readLine() if '=' in line: index = line.index('=') extension[line[:index].rstrip()] = line[index+1:].lstrip() extFile.close() return extension def openFile(self): supportedExtensions = ['.txt'] for markup in markups.get_all_markups(): supportedExtensions += markup.file_extensions fileFilter = ' (' + str.join(' ', ['*'+ext for ext in supportedExtensions]) + ');;' fileNames = QFileDialog.getOpenFileNames(self, self.tr("Select one or several files to open"), "", self.tr("Supported files") + fileFilter + self.tr("All files (*)")) for fileName in fileNames[0]: self.openFileWrapper(fileName) def openFileWrapper(self, fileName): if not fileName: return fileName = QFileInfo(fileName).canonicalFilePath() exists = False for i, tab in enumerate(self.iterateTabs()): if tab.fileName == fileName: exists = True ex = i if exists: self.tabWidget.setCurrentIndex(ex) elif QFile.exists(fileName): noEmptyTab = ( (self.ind is None) or self.currentTab.fileName or self.currentTab.editBox.toPlainText() or self.currentTab.editBox.document().isModified() ) if noEmptyTab: self.createTab(fileName) self.ind = self.tabWidget.count()-1 self.tabWidget.setCurrentIndex(self.ind) if fileName: self.fileSystemWatcher.addPath(fileName) self.currentTab.fileName = fileName self.currentTab.readTextFromFile() editBox = self.currentTab.editBox self.setCurrentFile() self.setWindowModified(editBox.document().isModified()) def showEncodingDialog(self): if not self.maybeSave(self.ind): return encoding, ok = QInputDialog.getItem(self, '', self.tr('Select file encoding from the list:'), [bytes(b).decode() for b in QTextCodec.availableCodecs()], 0, False) if ok: self.currentTab.readTextFromFile(encoding) def saveFile(self): self.saveFileMain(dlg=False) def saveFileAs(self): self.saveFileMain(dlg=True) def saveAll(self): for tab in self.iterateTabs(): if tab.fileName and QFileInfo(tab.fileName).isWritable(): tab.saveTextToFile() tab.editBox.document().setModified(False) def saveFileMain(self, dlg): if (not self.currentTab.fileName) or dlg: markupClass = self.currentTab.getMarkupClass() if (markupClass is None) or not hasattr(markupClass, 'default_extension'): defaultExt = self.tr("Plain text (*.txt)") ext = ".txt" else: defaultExt = self.tr('%s files', 'Example of final string: Markdown files') \ % markupClass.name + ' (' + str.join(' ', ('*'+extension for extension in markupClass.file_extensions)) + ')' if markupClass == markups.MarkdownMarkup: ext = globalSettings.markdownDefaultFileExtension elif markupClass == markups.ReStructuredTextMarkup: ext = globalSettings.restDefaultFileExtension else: ext = markupClass.default_extension newFileName = QFileDialog.getSaveFileName(self, self.tr("Save file"), "", defaultExt)[0] if newFileName: if not QFileInfo(newFileName).suffix(): newFileName += ext if self.currentTab.fileName: self.fileSystemWatcher.removePath(self.currentTab.fileName) self.currentTab.fileName = newFileName self.actionSetEncoding.setDisabled(self.autoSaveActive()) if self.currentTab.fileName: if self.currentTab.saveTextToFile(): self.setCurrentFile() self.currentTab.editBox.document().setModified(False) self.setWindowModified(False) return True else: QMessageBox.warning(self, '', self.tr("Cannot save to file because it is read-only!")) return False def saveHtml(self, fileName): if not QFileInfo(fileName).suffix(): fileName += ".html" try: htmltext = self.currentTab.getHtml(includeStyleSheet=False, webenv=True) except Exception: return self.printError() htmlFile = QFile(fileName) htmlFile.open(QIODevice.WriteOnly) html = QTextStream(htmlFile) if globalSettings.defaultCodec: html.setCodec(globalSettings.defaultCodec) html << htmltext htmlFile.close() def textDocument(self): td = QTextDocument() td.setMetaInformation(QTextDocument.DocumentTitle, self.currentTab.getDocumentTitle()) if self.ss: td.setDefaultStyleSheet(self.ss) td.setHtml(self.currentTab.getHtml()) td.setDefaultFont(globalSettings.font) return td def saveOdf(self): try: document = self.textDocument() except Exception: return self.printError() fileName = QFileDialog.getSaveFileName(self, self.tr("Export document to ODT"), "", self.tr("OpenDocument text files (*.odt)"))[0] if not QFileInfo(fileName).suffix(): fileName += ".odt" writer = QTextDocumentWriter(fileName) writer.setFormat(b"odf") writer.write(document) def saveFileHtml(self): fileName = QFileDialog.getSaveFileName(self, self.tr("Save file"), "", self.tr("HTML files (*.html *.htm)"))[0] if fileName: self.saveHtml(fileName) def getDocumentForPrint(self): if globalSettings.useWebKit: return self.currentTab.previewBox try: return self.textDocument() except Exception: self.printError() def standardPrinter(self): printer = QPrinter(QPrinter.HighResolution) printer.setDocName(self.currentTab.getDocumentTitle()) printer.setCreator('ReText %s' % app_version) return printer def savePdf(self): self.currentTab.updatePreviewBox() fileName = QFileDialog.getSaveFileName(self, self.tr("Export document to PDF"), "", self.tr("PDF files (*.pdf)"))[0] if fileName: if not QFileInfo(fileName).suffix(): fileName += ".pdf" printer = self.standardPrinter() printer.setOutputFormat(QPrinter.PdfFormat) printer.setOutputFileName(fileName) document = self.getDocumentForPrint() if document != None: document.print(printer) def printFile(self): self.currentTab.updatePreviewBox() printer = self.standardPrinter() dlg = QPrintDialog(printer, self) dlg.setWindowTitle(self.tr("Print document")) if (dlg.exec() == QDialog.Accepted): document = self.getDocumentForPrint() if document != None: document.print(printer) def printPreview(self): document = self.getDocumentForPrint() if document == None: return printer = self.standardPrinter() preview = QPrintPreviewDialog(printer, self) preview.paintRequested.connect(document.print) preview.exec() def runExtensionCommand(self, command, filefilter, defaultext): of = ('%of' in command) html = ('%html' in command) if of: if defaultext and not filefilter: filefilter = '*'+defaultext fileName = QFileDialog.getSaveFileName(self, self.tr('Export document'), '', filefilter)[0] if not fileName: return if defaultext and not QFileInfo(fileName).suffix(): fileName += defaultext basename = '.%s.retext-temp' % self.currentTab.getDocumentTitle(baseName=True) if html: tmpname = basename+'.html' self.saveHtml(tmpname) else: tmpname = basename + self.currentTab.getMarkupClass().default_extension self.currentTab.saveTextToFile(fileName=tmpname, addToWatcher=False) command = command.replace('%of', '"out'+defaultext+'"') command = command.replace('%html' if html else '%if', '"'+tmpname+'"') try: Popen(str(command), shell=True).wait() except Exception as error: errorstr = str(error) QMessageBox.warning(self, '', self.tr('Failed to execute the command:') + '\n' + errorstr) QFile(tmpname).remove() if of: QFile('out'+defaultext).rename(fileName) def autoSaveActive(self, ind=None): tab = self.currentTab if ind is None else self.tabWidget.widget(ind).tab return (self.autoSaveEnabled and tab.fileName and QFileInfo(tab.fileName).isWritable()) def modificationChanged(self, changed): if self.autoSaveActive(): changed = False self.actionSave.setEnabled(changed) self.setWindowModified(changed) def clipboardDataChanged(self): mimeData = QApplication.instance().clipboard().mimeData() if mimeData is not None: self.actionPaste.setEnabled(mimeData.hasText()) def insertFormatting(self, formatting): cursor = self.currentTab.editBox.textCursor() text = cursor.selectedText() moveCursorTo = None def c(cursor): nonlocal moveCursorTo moveCursorTo = cursor.position() def ensurenl(cursor): if not cursor.atBlockStart(): cursor.insertText('\n\n') toinsert = { 'header': (ensurenl, '# ', text), 'italic': ('*', text, c, '*'), 'bold': ('**', text, c, '**'), 'underline': ('<u>', text, c, '</u>'), 'numbering': (ensurenl, ' 1. ', text), 'bullets': (ensurenl, ' * ', text), 'image': ('![', text or self.tr('Alt text'), c, '](', self.tr('URL'), ')'), 'link': ('[', text or self.tr('Link text'), c, '](', self.tr('URL'), ')'), 'inline code': ('`', text, c, '`'), 'code block': (ensurenl, ' ', text), 'blockquote': (ensurenl, '> ', text), } if formatting not in toinsert: return cursor.beginEditBlock() for token in toinsert[formatting]: if callable(token): token(cursor) else: cursor.insertText(token) cursor.endEditBlock() self.formattingBox.setCurrentIndex(0) # Bring back the focus on the editor self.currentTab.editBox.setFocus(Qt.OtherFocusReason) if moveCursorTo: cursor.setPosition(moveCursorTo) self.currentTab.editBox.setTextCursor(cursor) def insertSymbol(self, num): if num: self.currentTab.editBox.insertPlainText('&'+self.usefulChars[num-1]+';') self.symbolBox.setCurrentIndex(0) def fileChanged(self, fileName): ind = None for testind, tab in enumerate(self.iterateTabs()): if tab.fileName == fileName: ind = testind if ind is None: self.fileSystemWatcher.removePath(fileName) self.tabWidget.setCurrentIndex(ind) if not QFile.exists(fileName): self.currentTab.editBox.document().setModified(True) QMessageBox.warning(self, '', self.tr( 'This file has been deleted by other application.\n' 'Please make sure you save the file before exit.')) elif not self.currentTab.editBox.document().isModified(): # File was not modified in ReText, reload silently self.currentTab.readTextFromFile() self.currentTab.updatePreviewBox() else: text = self.tr( 'This document has been modified by other application.\n' 'Do you want to reload the file (this will discard all ' 'your changes)?\n') if self.autoSaveEnabled: text += self.tr( 'If you choose to not reload the file, auto save mode will ' 'be disabled for this session to prevent data loss.') messageBox = QMessageBox(QMessageBox.Warning, '', text) reloadButton = messageBox.addButton(self.tr('Reload'), QMessageBox.YesRole) messageBox.addButton(QMessageBox.Cancel) messageBox.exec() if messageBox.clickedButton() is reloadButton: self.currentTab.readTextFromFile() self.currentTab.updatePreviewBox() else: self.autoSaveEnabled = False self.currentTab.editBox.document().setModified(True) if fileName not in self.fileSystemWatcher.files(): # https://github.com/retext-project/retext/issues/137 self.fileSystemWatcher.addPath(fileName) def maybeSave(self, ind): tab = self.tabWidget.widget(ind).tab if self.autoSaveActive(ind): tab.saveTextToFile() return True if not tab.editBox.document().isModified(): return True self.tabWidget.setCurrentIndex(ind) ret = QMessageBox.warning(self, '', self.tr("The document has been modified.\nDo you want to save your changes?"), QMessageBox.Save | QMessageBox.Discard | QMessageBox.Cancel) if ret == QMessageBox.Save: return self.saveFileMain(False) elif ret == QMessageBox.Cancel: return False return True def closeEvent(self, closeevent): for ind in range(self.tabWidget.count()): if not self.maybeSave(ind): return closeevent.ignore() if globalSettings.saveWindowGeometry and not self.isMaximized(): globalSettings.windowGeometry = self.saveGeometry() closeevent.accept() def viewHtml(self): htmlDlg = HtmlDialog(self) try: htmltext = self.currentTab.getHtml(includeStyleSheet=False) except Exception: return self.printError() winTitle = self.currentTab.getDocumentTitle(baseName=True) htmlDlg.setWindowTitle(winTitle+" ("+self.tr("HTML code")+")") htmlDlg.textEdit.setPlainText(htmltext.rstrip()) htmlDlg.hl.rehighlight() htmlDlg.show() htmlDlg.raise_() htmlDlg.activateWindow() def openHelp(self): QDesktopServices.openUrl(QUrl('https://github.com/retext-project/retext/wiki')) def aboutDialog(self): QMessageBox.about(self, self.aboutWindowTitle, '<p><b>' + (self.tr('ReText %s (using PyMarkups %s)') % (app_version, markups.__version__)) +'</b></p>' + self.tr('Simple but powerful editor' ' for Markdown and reStructuredText') +'</p><p>'+self.tr('Author: Dmitry Shachnev, 2011').replace('2011', '2011–2016') +'<br><a href="https://github.com/retext-project/retext">'+self.tr('Website') +'</a> | <a href="http://daringfireball.net/projects/markdown/syntax">' +self.tr('Markdown syntax') +'</a> | <a href="http://docutils.sourceforge.net/docs/user/rst/quickref.html">' +self.tr('reStructuredText syntax')+'</a></p>') def setDefaultMarkup(self, markupClass): self.defaultMarkup = markupClass defaultName = markups.get_available_markups()[0].name writeToSettings('defaultMarkup', markupClass.name, defaultName) for tab in self.iterateTabs(): if not tab.fileName: tab.setMarkupClass(markupClass) tab.updatePreviewBox() self.docTypeChanged()
class MainWindow(QMainWindow): def __init__(self, *args, **kwargs): url = "http://127.0.0.1:43110/1HeLLo4uzjaLetFx6NH3PMwFP3qbRbTf3D/" if "url" in kwargs: url = kwargs["url"] del kwargs["url"] if "zeronet_path" in kwargs: self.zeronet_path = kwargs["zeronet_path"] del kwargs["zeronet_path"] super(MainWindow, self).__init__(*args, **kwargs) # Tabs self.tabs = QTabWidget() self.tabs.setTabsClosable(True) self.tabs.tabCloseRequested.connect(self.close_tab) # New tab button #self.tab_add_button_index = self.tabs.addTab(QWidget(), '+') self.add_tab_button = QToolButton() self.add_tab_button.setText('+') self.add_tab_button.setStyleSheet( 'QToolButton {border: none; margin: 4px 20px 4px 0px; height: 480px; border-left: 1px solid lightgrey; padding: 0px 4px 0px 4px; font-weight: bold; color: #5d5b59}' 'QToolButton:hover { background-color: lightgrey }' 'QToolButton:pressed { background-color: grey }') self.add_tab_button.clicked.connect(self.new_tab_clicked) self.tabs.setCornerWidget(self.add_tab_button) # Navigation bar self.navigation = NavigationBar() self.navigation.url_bar.returnPressed.connect(self.navigate_to_url) # Back self.navigation.back_btn.triggered.connect( lambda: self.tabs.currentWidget().back()) # Next self.navigation.next_btn.triggered.connect( lambda: self.tabs.currentWidget().forward()) # Reload self.navigation.reload_btn.triggered.connect( lambda: self.tabs.currentWidget().reload()) self.navigation.shortcut_reload.activated.connect( lambda: self.tabs.currentWidget().reload()) self.navigation.shortcut_reload_f5.activated.connect( lambda: self.tabs.currentWidget().reload()) # Home self.navigation.home_btn.triggered.connect(self.go_home) # Menu: Edit config action self.navigation.edit_config_action.triggered.connect( self.edit_zeronet_config_file) # Add new tab self.add_new_tab(url, "Home") # Get everything fitting in the main window self.addToolBar(self.navigation) self.setCentralWidget(self.tabs) self.show() self.setWindowTitle("ZeroNet Browser") self.setWindowIcon(QIcon("icons/zeronet-logo.svg")) self.showMaximized() def contextMenuEvent(self, event): print(event) def update_url_bar(self, q, browser=None): if browser != self.tabs.currentWidget(): # If this signal is not from the current tab, ignore return url_array = q.toString().split('/')[3:] formatted_url = '/'.join(str(x) for x in url_array) self.navigation.url_bar.setText('zero://' + formatted_url) self.navigation.url_bar.setCursorPosition(0) if (self.tabs.currentWidget().can_go_back()): self.navigation.back_btn.setDisabled(False) else: self.navigation.back_btn.setDisabled(True) if (self.tabs.currentWidget().can_go_forward()): self.navigation.next_btn.setDisabled(False) else: self.navigation.next_btn.setDisabled(True) def navigate_to_url(self): # Get url url = self.navigation.url_bar.text() if url.startswith('zero://'): # ZeroNet protocol url_array = url.split('/') url = 'http://127.0.0.1:43110/' + url_array[2] elif url.startswith('http://'): # http protocol pass else: # Nothing mentionned url = 'http://127.0.0.1:43110/' + url self.tabs.currentWidget().setUrl(QUrl(url)) def go_home(self): self.tabs.currentWidget().setUrl( QUrl("http://127.0.0.1:43110/1HeLLo4uzjaLetFx6NH3PMwFP3qbRbTf3D/")) def new_tab_clicked(self): self.add_new_tab( "http://127.0.0.1:43110/1HeLLo4uzjaLetFx6NH3PMwFP3qbRbTf3D/", "Home") def get_link_url_from_context_menu(self): tab = self.tabs.currentWidget() page = tab.page() context = page.contextMenuData() qurl = context.linkUrl() return qurl.url() def open_in_new_tab(self): url = self.get_link_url_from_context_menu() self.add_new_tab(url, "Home") # Doesnt feel right to have it here but it is working def open_in_new_window(self): url = self.get_link_url_from_context_menu() kwargs = {"url": url} self.window = self.__class__(**kwargs) def add_new_tab(self, qurl, label): # Instead of browser it should be called WebView ! browser = Browser() # Triggered open in new tab openLinkInNewTabAction = browser.pageAction( QWebEnginePage.OpenLinkInNewTab) openLinkInNewWindowAction = browser.pageAction( QWebEnginePage.OpenLinkInNewWindow) openLinkInNewTabAction.triggered.connect(self.open_in_new_tab) openLinkInNewWindowAction.triggered.connect(self.open_in_new_window) self.addAction(openLinkInNewTabAction) browser.urlChanged.connect( lambda qurl, browser=browser: self.update_url_bar(qurl, browser)) indexTab = self.tabs.addTab(browser, label) # Maybe change current index after loading? self.tabs.setCurrentIndex(indexTab) # We need to update the url ! if qurl.startswith('zero://'): # ZeroNet protocol url_array = qurl.split('/') qurl = 'http://127.0.0.1:43110/' + url_array[2] elif qurl.startswith('http://'): # http protocol pass else: # Nothing mentionned qurl = 'http://127.0.0.1:43110/' + qurl currentTab = self.tabs.currentWidget() currentTab.loadFinished.connect(self.page_loaded) index = self.tabs.currentIndex() currentTab.titleChanged.connect( lambda title, index=index: self.tabs.setTabText(index, title)) currentTab.iconChanged.connect( lambda icon, index=index: self.tabs.setTabIcon(index, icon)) currentTab.setUrl(QUrl(qurl)) return indexTab def page_loaded(self, ok): if ok: currentTab = self.tabs.currentWidget() index = self.tabs.currentIndex() label = currentTab.title() icon = currentTab.icon() self.tabs.setTabIcon(index, icon) self.tabs.setTabText(index, label) def close_tab(self, index): if self.tabs.count() == 1: self.tabs.currentWidget().setUrl( QUrl( "http://127.0.0.1:43110/1HeLLo4uzjaLetFx6NH3PMwFP3qbRbTf3D/" )) return self.tabs.removeTab(index) def edit_zeronet_config_file(self): filepath = os.path.join(os.sep, self.zeronet_path, "zeronet.conf") if sys.platform.startswith('darwin'): # macOS subprocess.run(['open', filepath]) elif sys.platform.startswith('win'): # Windows os.startfile(filepath) else: # linux variants subprocess.run(['xdg-open', filepath])
class MainWindow(QMainWindow): def __init__(self): super().__init__() self.setUI() def setUI(self): self.setWindowTitle('Browser') self.urlBar = QLineEdit() self.urlBar.returnPressed.connect(self.navigatorToUrl) self.tabs = QTabWidget() self.tabs.setDocumentMode(True) self.tabs.tabBarDoubleClicked.connect(self.tabOpenDoubleClick) self.tabs.currentChanged.connect(self.currentTabChanged) self.tabs.setTabsClosable(True) self.tabs.tabCloseRequested.connect(self.closeCurrentTab) self.addNewTab(QUrl('https://baidu.com'), 'Homepage') self.setCentralWidget(self.tabs) navigationBar = QToolBar('Navigation') navigationBar.setIconSize(QSize(16, 16)) self.addToolBar(navigationBar) backButton = QAction(QIcon('icons/back.png'), 'Back', self) nextButton = QAction(QIcon('icons/next.png'), 'Forward', self) stopButton = QAction(QIcon('icons/cross.png'), 'Stop', self) reloadButton = QAction(QIcon('icons/renew.png'), 'Reload', self) backButton.triggered.connect(self.tabs.currentWidget().back) nextButton.triggered.connect(self.tabs.currentWidget().forward) stopButton.triggered.connect(self.tabs.currentWidget().stop) reloadButton.triggered.connect(self.tabs.currentWidget().reload) navigationBar.addAction(backButton) navigationBar.addAction(nextButton) navigationBar.addAction(stopButton) navigationBar.addAction(reloadButton) navigationBar.addSeparator() navigationBar.addWidget(self.urlBar) self.resize(1500, 900) self.show() def addNewTab(self, qurl=QUrl(''), label='blank'): browser = QWebEngineView() browser.load(qurl) i = self.tabs.addTab(browser, label) self.tabs.setCurrentIndex(i) browser.urlChanged.connect( lambda qurl, browser=browser: self.reNewUrlBar(qurl, browser)) self.urlBar.setText(qurl.toString()) browser.loadFinished.connect(lambda _, i=i, browser=browser: self.tabs. setTabText(i, browser.page().title())) def navigatorToUrl(self): self.tabs.currentWidget().load(QUrl(self.urlBar.text())) def closeCurrentTab(self, i): if self.tabs.count() < 2: return self.tabs.removeTab(i) def currentTabChanged(self, i): qurl = self.tabs.currentWidget().url() self.reNewUrlBar(qurl, self.tabs.currentWidget()) def tabOpenDoubleClick(self, i): if i == -1: self.addNewTab(QUrl("https://baidu.com")) def reNewUrlBar(self, q, browser=None): if browser != self.tabs.currentWidget(): return self.urlBar.setText(q.toString()) self.urlBar.setCursorPosition(0)
class RGui(QMainWindow): def __init__(self): super().__init__() self.initUI() def initUI(self): # Main window set up self.setAttribute(Qt.WA_DeleteOnClose) self.setWindowTitle("RGui") # File menu self.fileMenu = self.menuBar().addMenu('&File') self.fileMenu.addAction('&Open', self.openFile, Qt.CTRL + Qt.Key_O) self.fileMenu.addAction('&Save figure', self.saveFigure, Qt.SHIFT + Qt.CTRL + Qt.Key_S) # Main widget and its layout # subWidget is embedded in the right half of mainWidget self.mainWidget = QSplitter(Qt.Horizontal, self) self.subWidget = QSplitter(Qt.Vertical, self) # Plot canvas set up, added to layout self.canvas = CanvasWidget(self, width = 10, height = 8, dpi = 100) # Set up the control panel self.ctrPane = QTabWidget(self) self.initCtrPane() # List widget embedded in Tab widget self.selectPane = QTabWidget(self.subWidget) listWidget = QListWidget(self.selectPane) listWidget.setSelectionMode(QAbstractItemView.ExtendedSelection) self.selectPane.addTab(listWidget, 'Untitled') self.firstPlot = True self.spec = [] # Set up the layouts self.mainWidget.addWidget(self.canvas) self.subWidget.addWidget(self.ctrPane) self.subWidget.addWidget(self.selectPane) self.mainWidget.addWidget(self.subWidget) # Set up the MainWindow self.mainWidget.setFocus() self.setCentralWidget(self.mainWidget) self.setGeometry(300, 300, 500, 400) self.statusBar() def initCtrPane(self): # main control set up mainCtr = QFrame(self.ctrPane) mainCtr.setFrameShape(QFrame.StyledPanel) mainCtr.setFrameShadow(QFrame.Sunken) # buttons and controls backSubButton = QPushButton('Background Subtraction', mainCtr) backSubButton.clicked.connect(self.backSub) plotButton = QPushButton('Plot', mainCtr) plotButton.clicked.connect(self.updatePlot1) newTabButton = QPushButton('New tab', mainCtr) newTabButton.clicked.connect(self.addTab) self.plotPeak = QCheckBox('Plot fitted peak', mainCtr) holdPlot = QCheckBox('Hold plot', mainCtr) holdPlot.stateChanged.connect(self.canvas.toggleHold) # layout mainLayout = QGridLayout(mainCtr) mainLayout.addWidget(backSubButton, 0, 0) mainLayout.addWidget(plotButton, 0, 1) mainLayout.addWidget(newTabButton, 1, 0) mainLayout.addWidget(self.plotPeak, 2, 0) mainLayout.addWidget(holdPlot, 2, 1) mainCtr.setLayout(mainLayout) self.ctrPane.addTab(mainCtr, 'Main Control') # NMF control set up NMFCtr = QFrame(self.ctrPane) NMFCtr.setFrameShape(QFrame.StyledPanel) NMFCtr.setFrameShadow(QFrame.Sunken) # input & buttons self.alphaBox = MyDoubleBox(NMFCtr) self.l1RatioBox = MyDoubleBox(NMFCtr) self.loadSettings() NMFButton = QPushButton('NMF', NMFCtr) NMFButton.clicked.connect(self.NMF) # layout NMFLayout = QGridLayout(NMFCtr) NMFLayout.addWidget(QLabel('α'), 0, 0) NMFLayout.addWidget(QLabel('l1 ratio'), 1, 0) NMFLayout.addWidget(self.alphaBox, 0, 1) NMFLayout.addWidget(self.l1RatioBox, 1, 1) NMFLayout.addWidget(NMFButton, 2, 0, 1, 2) NMFCtr.setLayout(NMFLayout) self.ctrPane.addTab(NMFCtr, 'NMF Control') # slots def openFile(self): fileName = QFileDialog.getOpenFileName(self, "Open file") if fileName[0]: self.addSpec(fileName[0], os.path.basename(fileName[0])) def saveFigure(self): fileName = QFileDialog.getSaveFileName(self, "Save current figure") if fileName[0]: self.canvas.saveFigure(fileName) def addSpec(self, fileName, title): # import spectra from file j = self.selectPane.currentIndex() l = self.spec[j].nSpec() listWidget = self.selectPane.currentWidget() self.selectPane.setTabText(j, title) self.spec[j].addSpec(fileName, np.array([[0, 0, 0]])) for i in range(l + 1, self.spec[j]._coord.shape[0]): newItem = QListWidgetItem("[%d %d %d]" % \ tuple(self.spec[j]._coord[i]), listWidget) newItem.setData(Qt.UserRole, QVariant([j, i])) listWidget.addItem(newItem) listWidget.itemDoubleClicked.connect(self.updatePlot2) def addTab(self): listWidget = QListWidget(self.selectPane) listWidget.setSelectionMode(QAbstractItemView.ExtendedSelection) self.selectPane.addTab(listWidget, 'Untitled') self.spec.append(rd.SpecData()) # defines two update plot slots def updatePlot1(self): # slot for multiple items items = self.selectPane.currentWidget().selectedItems() if not items: pass # raise error bArray = items[0].data(Qt.UserRole) n = int(bArray[0]) use = [] for item in items: bArray = item.data(Qt.UserRole) use.append(int(bArray[1])) use = np.array(use).reshape(-1) self.canvas.updatePlot(self.spec[n], use, self.plotPeak.isChecked()) def updatePlot2(self, item): # slot for a single item bArray = item.data(Qt.UserRole) n = int(bArray[0]) i = int(bArray[1]) use = np.array(i).reshape(-1) self.canvas.updatePlot(self.spec[n], use, self.plotPeak.isChecked()) # Here comes the data analysis operations def backSub(self): if self.firstPlot: pass # raise an error fileName = QFileDialog.getOpenFileName(self, "Open background file") if fileName[0]: bg = rd.SpecData(fileName[0]) listWidget = self.selectPane.currentWidget() item = listWidget.item(0) n = item.data(Qt.UserRole)[0] newSpec = self.spec[n].backSub(bg.getSpec(0)) self.addSpec(newSpec, self.currentTabTitle() + '_subtracted') def NMF(self): if self.firstPlot: pass # raise an error item = self.selectPane.currentWidget().item(0) n = item.data(Qt.UserRole)[0] alpha = float(self.alphaBox.text()) l1Ratio = float(self.l1RatioBox.text()) model = self.spec[n].NMF(n_components = 3, init = 'nndsvd', alpha = alpha, l1_ratio = l1Ratio, sparseness = 'data') newSpec = rd.SpecData() newSpec._data = np.append(self.spec[n]._data[[0]], model.components_, axis = 0) newSpec._coord = np.array([[0, 0, 0], [0, 0, 1], [0, 0, 2]]) newSpec._dim = np.array([1, 1, 3]) self.addSpec(newSpec, self.currentTabTitle() + '_NMF') # save settings self.saveSettings() def saveSettings(self): settings = QSettings(QSettings.UserScope, 'Georgia Tech', 'RamanGui', self) settings.setValue('alpha', self.alphaBox.text()) settings.setValue('l1Ratio', self.l1RatioBox.text()) def loadSettings(self): settings = QSettings(QSettings.UserScope, 'Georgia Tech', 'RamanGui', self) if settings.contains('alpha'): self.alphaBox.setText(settings.value('alpha')) if settings.contains('l1Ratio'): self.l1RatioBox.setText(settings.value('l1Ratio')) def currentTabTitle(self): return self.selectPane.tabText(self.selectPane.currentIndex())
class MainWindow(QMainWindow): def __init__(self): super(MainWindow, self).__init__() fileMenu = QMenu("&File", self) newAction = fileMenu.addAction("&New...") newAction.setShortcut("Ctrl+N") self.printAction = fileMenu.addAction("&Print...", self.printFile) self.printAction.setShortcut("Ctrl+P") self.printAction.setEnabled(False) quitAction = fileMenu.addAction("E&xit") quitAction.setShortcut("Ctrl+Q") self.menuBar().addMenu(fileMenu) self.letters = QTabWidget() newAction.triggered.connect(self.openDialog) quitAction.triggered.connect(self.close) self.setCentralWidget(self.letters) self.setWindowTitle("Order Form") def createLetter(self, name, address, orderItems, sendOffers): editor = QTextEdit() tabIndex = self.letters.addTab(editor, name) self.letters.setCurrentIndex(tabIndex) cursor = editor.textCursor() cursor.movePosition(QTextCursor.Start) topFrame = cursor.currentFrame() topFrameFormat = topFrame.frameFormat() topFrameFormat.setPadding(16) topFrame.setFrameFormat(topFrameFormat) textFormat = QTextCharFormat() boldFormat = QTextCharFormat() boldFormat.setFontWeight(QFont.Bold) referenceFrameFormat = QTextFrameFormat() referenceFrameFormat.setBorder(1) referenceFrameFormat.setPadding(8) referenceFrameFormat.setPosition(QTextFrameFormat.FloatRight) referenceFrameFormat.setWidth(QTextLength(QTextLength.PercentageLength, 40)) cursor.insertFrame(referenceFrameFormat) cursor.insertText("A company", boldFormat) cursor.insertBlock() cursor.insertText("321 City Street") cursor.insertBlock() cursor.insertText("Industry Park") cursor.insertBlock() cursor.insertText("Another country") cursor.setPosition(topFrame.lastPosition()) cursor.insertText(name, textFormat) for line in address.split("\n"): cursor.insertBlock() cursor.insertText(line) cursor.insertBlock() cursor.insertBlock() date = QDate.currentDate() cursor.insertText("Date: %s" % date.toString('d MMMM yyyy'), textFormat) cursor.insertBlock() bodyFrameFormat = QTextFrameFormat() bodyFrameFormat.setWidth(QTextLength(QTextLength.PercentageLength, 100)) cursor.insertFrame(bodyFrameFormat) cursor.insertText("I would like to place an order for the following " "items:", textFormat) cursor.insertBlock() cursor.insertBlock() orderTableFormat = QTextTableFormat() orderTableFormat.setAlignment(Qt.AlignHCenter) orderTable = cursor.insertTable(1, 2, orderTableFormat) orderFrameFormat = cursor.currentFrame().frameFormat() orderFrameFormat.setBorder(1) cursor.currentFrame().setFrameFormat(orderFrameFormat) cursor = orderTable.cellAt(0, 0).firstCursorPosition() cursor.insertText("Product", boldFormat) cursor = orderTable.cellAt(0, 1).firstCursorPosition() cursor.insertText("Quantity", boldFormat) for text, quantity in orderItems: row = orderTable.rows() orderTable.insertRows(row, 1) cursor = orderTable.cellAt(row, 0).firstCursorPosition() cursor.insertText(text, textFormat) cursor = orderTable.cellAt(row, 1).firstCursorPosition() cursor.insertText(str(quantity), textFormat) cursor.setPosition(topFrame.lastPosition()) cursor.insertBlock() cursor.insertText("Please update my records to take account of the " "following privacy information:") cursor.insertBlock() offersTable = cursor.insertTable(2, 2) cursor = offersTable.cellAt(0, 1).firstCursorPosition() cursor.insertText("I want to receive more information about your " "company's products and special offers.", textFormat) cursor = offersTable.cellAt(1, 1).firstCursorPosition() cursor.insertText("I do not want to receive any promotional " "information from your company.", textFormat) if sendOffers: cursor = offersTable.cellAt(0, 0).firstCursorPosition() else: cursor = offersTable.cellAt(1, 0).firstCursorPosition() cursor.insertText('X', boldFormat) cursor.setPosition(topFrame.lastPosition()) cursor.insertBlock() cursor.insertText("Sincerely,", textFormat) cursor.insertBlock() cursor.insertBlock() cursor.insertBlock() cursor.insertText(name) self.printAction.setEnabled(True) def createSample(self): dialog = DetailsDialog('Dialog with default values', self) self.createLetter('Mr Smith', '12 High Street\nSmall Town\nThis country', dialog.orderItems(), True) def openDialog(self): dialog = DetailsDialog("Enter Customer Details", self) if dialog.exec_() == QDialog.Accepted: self.createLetter(dialog.senderName(), dialog.senderAddress(), dialog.orderItems(), dialog.sendOffers()) def printFile(self): editor = self.letters.currentWidget() printer = QPrinter() dialog = QPrintDialog(printer, self) dialog.setWindowTitle("Print Document") if editor.textCursor().hasSelection(): dialog.addEnabledOption(QAbstractPrintDialog.PrintSelection) if dialog.exec_() != QDialog.Accepted: return editor.print_(printer)