def windowLauncher(): app = QApplication(argv) loop = QEventLoop(app) w = Main() w.show() loop.run_forever()
def windowLauncher(): app = QApplication(sys.argv) app.setWindowIcon(QIcon('Files/incubus.png')) app.setStyleSheet(css.window()) loop = QEventLoop(app) asyncio.set_event_loop(loop) w = MainWindow0() w.show() loop.run_forever()
def maintcp(): app = QApplication(sys.argv) loop = QEventLoop(app) asyncio.set_event_loop(loop) form = MyApp() form.show() with loop: coro = asyncio.start_server(form.handle_echo, '', 5000, loop=loop) loop.run_until_complete(coro) try: loop.run_forever() except Exception as ex: print("maintcp error: ",str(ex))
def __init__(self): # QT app = QApplication(sys.argv) loop = QEventLoop(app) asyncio.set_event_loop(loop) self.running = True # com self.com_plug_event = asyncio.Event() self.com = com_connect.Comports(RS_Devices, self.com_plug_event) asyncio.create_task(self.comport_cb()) # processes self.stop_flag = Value('i', 0) self.par_p, self.chi_p = Pipe() c = Process(target=cameras.Cameras, args=(self.chi_p, self.stop_flag, 0, 1)) c.start() # loops self.duration = 4 self.value = 0 self.close_event = asyncio.Event() self.mw = MainWindow(self.close_event) self.mw.show() asyncio.create_task(self.handle_close_event()) # --tasks asyncio.create_task(self.handle_frames()) # asyncio.create_task(self.send_stop()) # loops here... with loop: sys.exit(loop.run_forever())
async def main(): QApplication.setAttribute(Qt.AA_EnableHighDpiScaling, True) app = QApplication(sys.argv) app_loop = QEventLoop(app) set_event_loop(app_loop) controller = AppController( ) # Need reference else garbage collector has too much fun with app_loop: sys.exit(app_loop.run_forever())
def main(): global loop app = QApplication(sys.argv) loop = QEventLoop(app) asyncio.set_event_loop(loop) mainWindow = MainWindow() mainWindow.show() with loop: sys.exit(loop.run_forever())
class App(Observation): def __init__(self, subject): Observation.__init__(self, subject) self.subject = subject self.loop = None self.backend = None self.app = QApplication(sys.argv) self.app.setApplicationName(ApplicationInfo.name) self.app.setApplicationDisplayName(ApplicationInfo.name) Fonts.initDb() self.main = Main(subject) self._init_responders() def document_new_responder(self, e): self.subject = Subject() self._init_responders() self.main.close() self.main.deleteLater() self.main = Main(self.subject) self.backend.delete() self.backend = BackendRouter(self.loop, self.subject) self.main.show() def _init_responders(self): self.add_responder(events.view.main.FileNew, self.document_new_responder) def run(self): self.loop = QEventLoop(self.app) self.backend = BackendRouter(self.loop, self.subject) asyncio.set_event_loop(self.loop) self.main.show() with self.loop: code = self.loop.run_forever() pending = asyncio.Task.all_tasks() self.notify(events.app.Quit()) try: self.loop.run_until_complete( asyncio.wait_for(asyncio.gather(*pending), 10)) except asyncio.futures.TimeoutError as e: print(e) sys.exit(code)
def main(): app = QtWidgets.QApplication(sys.argv) icon_file = pkg_resources.resource_filename("pypod_launcher", "icon.ico") app.setWindowIcon(QtGui.QIcon(icon_file)) loop = QEventLoop(app) asyncio.set_event_loop(loop) ui_file = pkg_resources.resource_filename("pypod_launcher", "main.ui") ui = QtUiTools.QUiLoader().load(ui_file) ui.setWindowTitle("pypod-launcher [v{}]".format(version)) config_logging(ui) launcher = Launcher(ui) launcher.center() ui.show() with loop: sys.exit(loop.run_forever())
class PlotWindow(QtCore.QObject): def __init__(self): super().__init__() topics = { 'Projection.0.Out': '_auto_Projection.0.Out', 'Projection.1.Out': '_auto_Projection.1.Out' } # Use the same topics for multiple traces in a plot # AsyncFetcher deduplicate and only makes as many sockets as needed terms = { 'X': 'Projection.0.Out', 'Y': 'Projection.1.Out', 'X.1': 'Projection.1.Out', 'Y.1': 'Projection.0.Out' } self.app = QtGui.QApplication([]) self.loop = QEventLoop(self.app) asyncio.set_event_loop(self.loop) self.win = QtGui.QMainWindow() addr = Addr('graph', 'tcp://127.0.0.1:5557') self.widget = ScatterWidget(topics, terms, addr, parent=self.win) self.task = asyncio.ensure_future(self.widget.update()) self.win.setCentralWidget(self.widget) self.win.show() try: self.loop.run_forever() finally: if not self.task.done(): self.task.cancel() self.widget.close()
class WavemeterChannelMonitor(WavemeterClient): """ Connects to a :class:`WavemeterServer` to monitor a channel wavelength, temperature or pressure. There are three available GUI elements: a stripchart plot, a scalable number display, and an interferogram plot. :param host: the address at which the :class:`WavemeterServer` publisher is running :param channel: wavemeter channel (can be either <n>, '<n>', 'ch<n>', 'T' or 'p') :param port: port of the publisher :param rpc_host: host of the wavemeter server (only needed for interferograms, default = same as publisher) :param rpc_port: port of the wavemeter server rpc target (only needed for interferograms) :param rpc_target: target name for rpcs (only needed for interferograms) :param title: the window title (generated from the server details by default) :param window_width: initial width of the window in pixels :param window_x: initial x position of the window in pixels :param window_y: initial y position of the window in pixels :param enable_stripchart: show the stripchart :param stripchart_height: initial stripchart height in pixels :param stripchart_num_points: number of data points displayed in the stripchart :param plot_freq: True for frequency plot, False for wavelength plot :param plot_offset: y offset of the plot (unit is MHz for frequencies and nm for wavelengths) :param plot_pen: pen specification for the plot trace (see pyqtgraph documentation) :param plot_symbol: symbol specification for the plot points :param plot_bgr: bgr color of the plot :param enable_lcd: show the current value (wavelength or frequency) as a scalable number :param lcd_height: lcd height in pixels :param lcd_ndigits: number of digits in the lcd :param lcd_freq: start with the number display showing the frequency (default is wavelength) :param enable_interferograms: display the interferograms :param interferogram_update_interval: number of values after which to update the interferograms :param show_interferogram_update_control: show the spinbox to adjust interferogram update rate :param if0_pen: pen specification for the 1st interferogram :param if1_pen: pen specification for the 2nd interferogram :param interferogram_bgr: bgr color of the interferogram plot :param interferogram_height: initial height of the interferogram plot in pixels :param interferogram_exposure_control: enable control of wavemeter exposure times """ def __init__(self, host: str = "::1", channel: str = "ch1", port: int = 3281, rpc_host: str = "", rpc_port: int = 3280, rpc_target="wavemeter_server", title: str = None, window_width: int = 611, window_x: int = 0, window_y: int = 0, enable_stripchart: bool = True, stripchart_height: int = 350, stripchart_num_points: int = 100, plot_freq: bool = True, plot_offset: float = 0., plot_pen: Any = pyqtgraph.mkPen(color="k", width=3), plot_symbol: Any = None, plot_bgr: str = "w", enable_lcd: bool = True, lcd_height: int = 160, lcd_ndigits: int = 10, lcd_freq: bool = False, enable_interferograms: bool = False, interferogram_update_interval: int = 1, show_interferogram_update_control: bool = False, if0_pen: Any = pyqtgraph.mkPen(color="g", width=1), if1_pen: Any = pyqtgraph.mkPen(color="b", width=1), interferogram_bgr: str = "w", interferogram_height: int = 150, interferogram_exposure_control: bool = False): # user interface components self._enable_stripchart = enable_stripchart self._enable_lcd = enable_lcd self._enable_interferograms = enable_interferograms self.lcd_ndigits = lcd_ndigits self.stripchart_pen = plot_pen self.stripchart_symbol = plot_symbol self.stripchart_bgr = plot_bgr self._app = QApplication(sys.argv) self._loop = QEventLoop(self._app) asyncio.set_event_loop(self._loop) self.plot_freq = plot_freq self.plot_offset = plot_offset self.lcd_freq = lcd_freq try: # accept integer (or string lacking the "ch" prefix) as channel argument self.channel = "ch{}".format(int(channel)) except ValueError: self.channel = channel self.not_a_wavelength = (self.channel in ["T", "p"]) # disable frequency conversion options for T and p if self.not_a_wavelength: self.plot_freq = False self.lcd_freq = False self._enable_interferograms = False self.title = title if title is not None else "{} monitor ({}:{})".format(channel, host, port) if self._enable_interferograms and not self.not_a_wavelength: channel_id = int(self.channel[2:]) self.interferograms = InterferogramWidget(rpc_host=rpc_host, rpc_port=rpc_port, rpc_target=rpc_target, channel_id=channel_id, if0_pen=if0_pen, if1_pen=if1_pen, bgr_color=interferogram_bgr, update_interval=interferogram_update_interval, show_interval_spinbox=show_interferogram_update_control, show_exposure_ctrl=interferogram_exposure_control) self._build_ui(window_width, window_x, window_y, stripchart_height, stripchart_num_points, lcd_height, interferogram_height) super().__init__(self.channel, host, port, self._loop) def _build_ui(self, window_width, window_x, window_y, stripchart_height, stripchart_num_points, lcd_height, interferogram_height): self.window = QWidget() self.window.setWindowTitle(self.title) window_height = stripchart_height * self._enable_stripchart \ + lcd_height * self._enable_lcd \ + interferogram_height * self._enable_interferograms self.window.resize(window_width, window_height) self.window.move(window_x, window_y) # The layout only contains one element (the splitter), but it is needed to rescale widgets as window is rescaled self.v_layout = QVBoxLayout() self.v_splitter = QSplitter(Qt.Vertical) self.v_layout.addWidget(self.v_splitter) self.window.setLayout(self.v_layout) self.v_layout.addWidget(self.v_splitter) splitter_sizes = [] if self._enable_stripchart: self._build_stripchart(stripchart_num_points) splitter_sizes.append(stripchart_height) if self._enable_lcd: self._build_lcd() splitter_sizes.append(lcd_height) if self._enable_interferograms: self.v_splitter.addWidget(self.interferograms) splitter_sizes.append(interferogram_height) self.v_splitter.setSizes(splitter_sizes) def _build_stripchart(self, num_points): plot_title = "" if self.plot_freq: plot_y_label = "frequency (MHz)" if self.plot_offset != 0: plot_title = "offset: {:11} THz".format(self.plot_offset * 1e-6) else: if self.channel == "T": plot_y_label = "temperature (degrees C)" if self.plot_offset != 0: plot_title = "offset: {:5} degrees C".format(self.plot_offset) elif self.channel == "p": plot_y_label = "pressure (mbar)" if self.plot_offset != 0: plot_title = "offset: {:6} mbar".format(self.plot_offset) else: plot_y_label = "vac. wavelength (nm)" if self.plot_offset != 0: plot_title = "offset: {:10} nm".format(self.plot_offset) self.stripchart = Stripchart(num_points=num_points, xvalues=True, offset=self.plot_offset, plot_title=plot_title, plot_pen=self.stripchart_pen, plot_symbol=self.stripchart_symbol, plot_bgr=self.stripchart_bgr, x_label="wavemeter time stamp (s)", y_label=plot_y_label, y_grid=True) clear_button = QPushButton("&Clear") clear_button.clicked.connect(self.stripchart.clear_data) layout = QVBoxLayout() layout.addWidget(self.stripchart) layout.addWidget(clear_button) widget = QWidget() widget.setLayout(layout) self.v_splitter.addWidget(widget) def _add_stripchart_point(self): if self.value < 0: # ignore error codes return if self.plot_freq: # plot frequency in MHz self.stripchart.add_point(self.timestamp * 1e-3, 299792456e3 / self.value) else: # plot wavelength in nm self.stripchart.add_point(self.timestamp * 1e-3, self.value) def _build_lcd(self): layout = QVBoxLayout() self.lcd = QLCDNumber() self.lcd.setSmallDecimalPoint(True) self.lcd.setDigitCount(self.lcd_ndigits) freq_checkbox = QCheckBox("Display frequency") freq_checkbox.setChecked(self.lcd_freq) def switch_wl_freq(): self.lcd_freq = freq_checkbox.isChecked() self._update_lcd() freq_checkbox.clicked.connect(switch_wl_freq) layout.addWidget(self.lcd) if not self.not_a_wavelength: layout.addWidget(freq_checkbox) widget = QWidget() widget.setLayout(layout) self.v_splitter.addWidget(widget) def _update_lcd(self): if self.value > 0: value = 299792456e-3 / self.value if self.lcd_freq else self.value # next line is to keep number of decimals constant (i.e. display trailing zeros) self.lcd.display("{{:.0{}f}}".format(self.lcd_ndigits-len(str(int(value)))).format(value)) elif self.value == -2: # bad signal self.lcd.display("b") elif self.value == -3: # underexposed self.lcd.display("u") elif self.value == -4: # overexposed self.lcd.display("o") else: self.lcd.display(self.value) def _init_callback(self): if self._enable_lcd: self._update_lcd() if self._enable_interferograms: self.interferograms.update_data() def _new_value_callback(self): if self._enable_stripchart: self._add_stripchart_point() if self._enable_lcd: self._update_lcd() if self._enable_interferograms: self.interferograms.update_data() def run(self): self.window.show() self._loop.run_forever() if self._subscriber is not None: self._loop.run_until_complete(self._subscriber.close())
def main(gamePath: Optional[str] = None, configPath: Optional[str] = None, startupMode: StartupMode = StartupMode.Main) -> NoReturn: from w3modmanager.util.util import getRuntimePath from w3modmanager.core.model import Model from w3modmanager.core.errors import OtherInstanceError, InvalidGamePath, InvalidConfigPath from w3modmanager.ui.graphical.mainwindow import MainWindow from w3modmanager.domain.system.permissions import \ getWritePermissions, setWritePermissions from PySide2.QtCore import Qt, QSettings from PySide2.QtWidgets import QApplication, QMessageBox from PySide2.QtGui import QIcon, QPalette, QFont from asyncqt import QEventLoop # noqa QApplication.setOrganizationName(w3modmanager.ORG_NAME) QApplication.setOrganizationDomain(w3modmanager.ORG_URL) QApplication.setApplicationName(w3modmanager.TITLE) QApplication.setApplicationVersion(w3modmanager.VERSION) QApplication.setApplicationDisplayName('') QApplication.setAttribute(Qt.AA_NativeWindows) QApplication.setAttribute(Qt.AA_DisableWindowContextHelpButton) QApplication.setAttribute(Qt.AA_EnableHighDpiScaling) QApplication.setAttribute(Qt.AA_UseHighDpiPixmaps) QApplication.setHighDpiScaleFactorRoundingPolicy( Qt.HighDpiScaleFactorRoundingPolicy.RoundPreferFloor) app = QApplication(sys.argv) app.setStyleSheet(''' Link { text-decoration: none; } ''') eventloop = QEventLoop(app) asyncio.set_event_loop(eventloop) palette = QPalette(QApplication.palette()) palette.setColor(QPalette.Link, Qt.red) palette.setColor(QPalette.LinkVisited, Qt.red) app.setPalette(palette) font = QFont('Segoe UI') font.setStyleHint(QFont.System) font.setWeight(QFont.Normal) font.setStyleStrategy(QFont.PreferDevice) font.setPointSize(9) app.setFont(font) icon = QIcon() icon.addFile(str(getRuntimePath('resources/icons/w3b.ico'))) app.setWindowIcon(icon) # configure startup overrides settings = QSettings() if gamePath: settings.setValue('gamePath', gamePath) if configPath: settings.setValue('configPath', configPath) if startupMode == StartupMode.About: MainWindow.showAboutDialog(None).exec_() sys.exit() if startupMode == StartupMode.Settings: MainWindow.showSettingsDialog(None).exec_() sys.exit() def createModel(ignorelock: bool = False) -> Model: nonlocal settings return Model( Path(str(settings.value('gamePath'))), Path(str(settings.value('configPath'))), Path( appdirs.user_data_dir(w3modmanager.NAME, w3modmanager.ORG_NAME)), ignorelock) try: # try to initialize the mod management model try: model = createModel() # if another instance is already open, inform and ask to open anyway except OtherInstanceError as e: if MainWindow.showOtherInstanceDialog( None).exec_() == QMessageBox.Yes: model = createModel(True) else: raise e # if game path or config path is invalid or not set, # show a special settings dialog and retry except (InvalidGamePath, InvalidConfigPath): MainWindow.showSettingsDialog(None, True).exec_() model = createModel() # check for write access to the game and config directories for path in ( model.gamepath, model.configpath, model.cachepath, ): if not getWritePermissions(path): if MainWindow.showInvalidPermissionsDialog(None, path).exec_() != QMessageBox.Yes \ or not setWritePermissions(path): raise PermissionError(f'Not enough permissions for {path}') window = MainWindow(model) app.setActiveWindow(window) def show_exception_hook(exctype, value, tb) -> None: # noqa nonlocal window MainWindow.showCritcalErrorDialog( window, value, ''.join(traceback.format_exception(exctype, value, tb))).exec_() exception_hook(exctype, value, tb) sys.excepthook = show_exception_hook with eventloop: sys.exit(eventloop.run_forever()) except OtherInstanceError as e: sys.exit(f'error: {str(e)}') except (InvalidGamePath, InvalidConfigPath) as e: MainWindow.showInvalidConfigErrorDialog(None).exec_() sys.exit(f'error: {str(e)}') except PermissionError as e: MainWindow.showInvalidPermissionsErrorDialog(None).exec_() sys.exit(f'error: {str(e)}') except Exception as e: MainWindow.showCritcalErrorDialog(None, str(e)).exec_() raise e sys.exit()
if __name__ == "__main__": # asyncio debugging # https://docs.python.org/3.6/library/asyncio-dev.html # https://docs.python.org/3/using/cmdline.html#environment-variables os.environ['PYTHONASYNCIODEBUG'] = "1" os.environ['DEBUG'] = "1" warnings.warn("always", ResourceWarning) basename = os.path.splitext(os.path.basename(__file__))[0] # global app app = QApplication(sys.argv) eventloop = QEventLoop(app) asyncio.set_event_loop(eventloop) eventloop.set_debug(True) # executor = concurrent.futures.ThreadPoolExecutor(5) # eventloop.set_default_executor(executor) setup_logging() window = MainWindow() window.show() with eventloop: eventloop.create_task(new_browsertab(9232, eventloop)) sys.exit(eventloop.run_forever()) pass pass
class WavemeterLoggingClientGUI: """ As above, but with a GUI. """ def __init__(self, host: str = "::1", port: int = 3280, target: str = "wavemeter_server"): self._app = QApplication(sys.argv) self._loop = QEventLoop(self._app) asyncio.set_event_loop(self._loop) self.logging_client = WavemeterLoggingClient(host=host, port=port, target=target, event_loop=self._loop) self.title = "Wavelength logging client, {} at {}:{}". format(target, host, port) self._ui_input_elements = dict() self.latest_line_label = QLabel("") def label_cb(line): timestring = time.asctime(time.localtime(time.time())) filename = self.logging_client.filename self.latest_line_label.setText("At {}, added line to file {}:\n{}".format(timestring, filename, line)) self.logging_client._output_cb = label_cb self._build_ui() def _build_ui(self): self.window = QWidget() self.window.setWindowTitle(self.title) self.v_layout = QVBoxLayout() self.window.setLayout(self.v_layout) options_gb = QGroupBox("Log file options") options_gb_layout = QFormLayout() options_gb.setLayout(options_gb_layout) self._ui_input_elements.update({"path": QLineEdit(os.getcwd())}) options_gb_layout.addRow("Path", self._ui_input_elements["path"]) self._ui_input_elements.update({"file": QLineEdit("wavelength_log.txt")}) options_gb_layout.addRow("File (overwrites without asking)", self._ui_input_elements["file"]) self._ui_input_elements.update({"append": QCheckBox()}) self._ui_input_elements["append"].setChecked(True) options_gb_layout.addRow("Append", self._ui_input_elements["append"]) channels = "" for chan in set(self.logging_client.wm_server.get_active_channels()): channels += "{},".format(chan) channels = channels[:-1] if self.logging_client.wm_server.get_temperature() != -1: channels += ",T" if self.logging_client.wm_server.get_pressure() != -1: channels += ",p" self._ui_input_elements.update({"channels": QLineEdit(channels)}) options_gb_layout.addRow("Channels (comma separated)", self._ui_input_elements["channels"]) self._ui_input_elements.update({"add_param": QLineEdit("")}) options_gb_layout.addRow("Additional parameter header entry (optional)", self._ui_input_elements["add_param"]) self.v_layout.addWidget(options_gb) command_layout = QGridLayout() auto_log_gb = QGroupBox("Automated logging") auto_log_gb_layout = QFormLayout() auto_log_gb.setLayout(auto_log_gb_layout) self._ui_input_elements.update({"interval": QDoubleSpinBox()}) self._ui_input_elements["interval"].setDecimals(1) self._ui_input_elements["interval"].setRange(0.1, 1e5) self._ui_input_elements["interval"].setSingleStep(0.1) self._ui_input_elements["interval"].setSuffix(" s") self._ui_input_elements["interval"].setValue(10) auto_log_gb_layout.addRow("Interval", self._ui_input_elements["interval"]) auto_log_button = QPushButton("Start automated &logging") def get_logging_parameters(): channel_list = self._ui_input_elements["channels"].text().split(",") for i in range(len(channel_list)): try: channel_list[i] = int(channel_list[i]) except ValueError: pass interval = self._ui_input_elements["interval"].value() filename = os.path.join(self._ui_input_elements["path"].text(), self._ui_input_elements["file"].text()) append = self._ui_input_elements["append"].isChecked() return channel_list, interval, filename, append def start_auto_logging(): channel_list, interval, filename, append = get_logging_parameters() logger.info("Calling start_logging_timed({}, {}, {}, {})".format(channel_list, interval, filename, append)) self.logging_client.start_logging_timed(channel_list, interval, filename, append) auto_log_button.clicked.connect(start_auto_logging) auto_log_gb_layout.addWidget(auto_log_button) command_layout.addWidget(auto_log_gb, 0, 0) start_manual_button = QPushButton("Start &manual log") def start_manual_log(): channel_list, _, filename, append = get_logging_parameters() additional_parameter = self._ui_input_elements["add_param"].text() logger.info("Calling start_manual_log({}, {}, {}, {})".format(channel_list, filename, additional_parameter, append)) self.logging_client.start_manual_log(channel_list, filename, additional_parameter, append) start_manual_button.clicked.connect(start_manual_log) command_layout.addWidget(start_manual_button, 0, 1) stop_logging_button = QPushButton("S&top logging") stop_logging_button.clicked.connect(self.logging_client.stop_logging) command_layout.addWidget(stop_logging_button, 1, 0) self.v_layout.addLayout(command_layout) add_entry_gb = QGroupBox("Manual entry") add_entry_gb_layout = QFormLayout() add_entry_gb.setLayout(add_entry_gb_layout) self._ui_input_elements.update({"extra_value": QLineEdit()}) add_entry_gb_layout.addRow("Additional parameter value (optional)", self._ui_input_elements["extra_value"]) add_log_entry_button = QPushButton("&Add log entry") def add_log_entry(): value = self._ui_input_elements["extra_value"].text() self.logging_client.add_entry(value) add_log_entry_button.clicked.connect(add_log_entry) add_entry_gb_layout.addWidget(add_log_entry_button) self.v_layout.addWidget(add_entry_gb) self.v_layout.addWidget(self.latest_line_label) def run(self): self.window.show() self._loop.run_forever() self.logging_client.wm_server.close_rpc()
class Application: """cRIO GUI application class. Parses command line arguments. Runs application including splash screen (can be disabled by command line option). Splash screen is shown during SAL initialization. Parameters ---------- eui_class : `class` Class, ideally child of QMainWindow, which will be instantiated after wait for SAL/DDS initialization. It's parameters are SALComm created with addComm method. Usage ----- .. code-block:: python from PySide2.QtWidgets import QApplication class EUI(QMainWindow): ... if __name__ == "__main__": app = Application(EUI) app.addComm("MTM1M3") app.addComm("MTMount", include=["azimuth", "elevation"]) app.run() """ def __init__(self, eui_class): self._eui_class = eui_class self._app = QApplication(sys.argv) parser = QCommandLineParser() parser.addHelpOption() parser.addVersionOption() noSplash = QCommandLineOption(["n", "no-splash"], "don't show splash screen") parser.addOption(noSplash) parser.process(self._app) self._loop = QEventLoop(self._app) asyncio.set_event_loop(self._loop) self._comms = [] self._splash = not (parser.isSet(noSplash)) self._eui = None def addComm(self, name, manual=None, **kwargs): """Adds SALComm object to parameters of QMainWindow class. Parameters ---------- name : `str` Remote name. manual : `hash` Events and telemetry topics created with optional arguments. Keys are events and telemetry names, values is a hash of additional arguments. **kwargs : `dict` Optional parameters passed to remote. """ self._comms.append(create(name, manual=manual, **kwargs)) def run(self): """Runs the application. Creates splash screen, display it if requested. Creates and display main window after SAL/DDS is initialized.""" class AppSplashScreen(SplashScreen): def started(splash, *comms): self._eui = self._eui_class(*comms) splash.finish(self._eui) self._eui.show() splash = AppSplashScreen(*self._comms, show=self._splash) if self._splash: splash.show() def handler(signum, frame): print(f"Catching signal {signum}, exiting") self._loop.call_soon(splash.stop) self._loop.call_soon(self._app.closeAllWindows) for signum in [signal.SIGINT, signal.SIGHUP, signal.SIGTERM]: signal.signal(signum, handler) # Run the main Qt loop with self._loop: self._loop.run_forever()
class Application(QtApplication): """ Add asyncio support . Seems like a complete hack compared to twisted but whatever. """ loop = Instance(QEventLoop) def __init__(self): super().__init__() #: Set event loop policy for windows if sys.platform == 'win32': asyncio.set_event_loop_policy( asyncio.WindowsSelectorEventLoopPolicy()) self.loop = QEventLoop(self._qapp) asyncio.set_event_loop(self.loop) for name in ('asyncqt._unix._Selector', 'asyncqt._QEventLoop', 'asyncqt._SimpleTimer'): log = logging.getLogger(name) log.setLevel(logging.WARN) def start(self): """ Run using the event loop """ log.info("Application starting") with self.loop: self.loop.run_forever() def deferred_call(self, callback, *args, **kwargs): """ Invoke a callable on the next cycle of the main event loop thread. Parameters ---------- callback : callable The callable object to execute at some point in the future. args, kwargs Any additional positional and keyword arguments to pass to the callback. """ if asyncio.iscoroutinefunction(callback): task = lambda: asyncio.ensure_future(callback(*args, **kwargs)) return self.loop.call_soon(task) return super().deferred_call(callback, *args, **kwargs) def timed_call(self, ms, callback, *args, **kwargs): """ Invoke a callable on the main event loop thread at a specified time in the future. Parameters ---------- ms : int The time to delay, in milliseconds, before executing the callable. callback : callable The callable object to execute at some point in the future. args, kwargs Any additional positional and keyword arguments to pass to the callback. """ if asyncio.iscoroutinefunction(callback): task = lambda: asyncio.ensure_future(callback(*args, **kwargs)) return self.loop.call_later(ms / 1000, task) return super().timed_call(ms, callback, *args, **kwargs)
logger = logging.getLogger(__name__) logger.debug("Geo sources: %s" % QGeoPositionInfoSource.availableSources()) QGuiApplication.setAttribute(Qt.AA_DisableHighDpiScaling) QGuiApplication.setAttribute(Qt.AA_Use96Dpi) QGuiApplication.setAttribute(Qt.AA_ShareOpenGLContexts) # Create the application instance. app = QGuiApplication(sys.argv) loop = QEventLoop(app) asyncio.set_event_loop(loop) touchscreens = list( filter(lambda d: d.type() == QTouchDevice.TouchScreen, QTouchDevice.devices())) if touchscreens: logger.info("touchscreens detected, disabling mouse %s" % touchscreens) app.setOverrideCursor(QCursor(Qt.BlankCursor)) # Create a QML engine. engine = QQmlApplicationEngine() engine.load('./ui/main.qml') win = engine.rootObjects()[0] win.show() with loop: ## context manager calls .close() when loop completes, and releases all resources sys.exit(loop.run_forever())
self.message_input.clear() self.protocol.send_data(message_text) def append_text(self, content: str): self.message_box.appendPlainText(content) def buid_protocol(self): self.protocol = ClientProtocol(self) return self.protocol async def start(self): self.show() event_loop = asyncio.get_running_loop() coroutine = event_loop.create_connection(self.buid_protocol, "127.0.0.1", 8000) await asyncio.wait_for(coroutine, 1000) app = QtWidgets.QApplication() loop = QEventLoop(app) asyncio.set_event_loop(loop) window = MainWindow() window.show() loop.create_task(window.start()) loop.run_forever()
class WavemeterRemote: """ Simple remote control for a :class:`WavemeterServer`, providing controls to start and stop the measurement, calibrate, control autocalibration and displaying the timestamp of the latest successful calibration as well as the autocalibration countdown. :param host: the address at which the :class:`WavemeterServer` RPC server and Publisher are running :param rpc_target: name of the RPC target :param rpc_port: port of the RPC server :param notifier_port: port of the publisher (notifier "status", containing the calibration timestamp and countdown) :param title: the window title (generated from the RPC target name by default) :param window_x: initial x position of the window in pixels :param window_y: initial y position of the window in pixels :param cal_channel: startup entry for the calibration channel :param cal_wl: startup entry for the calibration wavelength (in nm) :param cal_threshold: startup entry for the autocalibration threshold (in nm) :param cal_interval: startup entry for the autocalibration interval (in s) :param cal_retry_interval: startup entry for the autocalibration retry interval (in s) :param start_autocal: set to start autocalibration on startup """ def __init__(self, host: str = "::1", rpc_target: str = "wavemeter_server", rpc_port: int = 3280, notifier_port: int = 3281, title: str = None, window_x: int = 0, window_y: int = 0, cal_channel: int = 1, cal_wl: float = 633., cal_threshold: float = 0.00005, cal_interval: int = 600, cal_retry_interval: int = 10, start_autocal: bool = False): self._app = QApplication(sys.argv) self._loop = QEventLoop(self._app) asyncio.set_event_loop(self._loop) self.wm_status_dict = { "autocal_countdown": 0, "calibration_timestamp": -1 } self._subscriber = Subscriber("status", self._subscriber_init_cb, self._subscriber_mod_cb) logger.info( "Connecting to publisher at {}:{}, notifier name: status".format( host, notifier_port)) self._loop.run_until_complete( self._subscriber.connect(host, notifier_port)) logger.info( "Connecting to RPC server at {}:{}, target name: {}".format( host, rpc_port, rpc_target)) self._rpc_client = BestEffortClient(host, rpc_port, rpc_target) self._loop.create_task(self.keepalive_loop()) self.title = title if title is not None else "Wavemeter remote control ({} at {})".format( rpc_target, host) self._ui_input_elements = dict( ) # stores all input elements, used on function calls to retrieve their values self._build_ui(window_x, window_y, cal_channel, cal_wl, cal_threshold, cal_interval, cal_retry_interval) if start_autocal and self._rpc_client is not None: self._rpc_client.start_autocalibration(cal_channel, cal_wl, cal_threshold, cal_interval, cal_retry_interval) def _build_ui(self, window_x, window_y, cal_channel, cal_wl, cal_threshold, cal_interval, cal_retry_interval): self.window = QWidget() self.window.setWindowTitle(self.title) self.window.move(window_x, window_y) self.v_layout = QVBoxLayout() self.window.setLayout(self.v_layout) indicator_font = QFont() indicator_font.setPointSize(18) self.calibration_timestamp_display = QLabel() self.calibration_timestamp_display.setFont(indicator_font) self.calibration_countdown_display = QLabel() self.calibration_countdown_display.setFont(indicator_font) startstop_gb = QGroupBox("Measurement") startstop_gb_layout = QHBoxLayout() startstop_gb.setLayout(startstop_gb_layout) start_button = QPushButton("&Start measurement") def start(): if self._rpc_client is not None: logger.info("sending RPC start_measurement()") self._rpc_client.start_measurement() start_button.clicked.connect(start) startstop_gb_layout.addWidget(start_button) stop_button = QPushButton("S&top measurement") def stop(): if self._rpc_client is not None: logger.info("sending RPC stop_measurement()") self._rpc_client.stop_measurement() stop_button.clicked.connect(stop) startstop_gb_layout.addWidget(stop_button) self.v_layout.addWidget(startstop_gb) cal_gb = QGroupBox("Calibration") cal_gb_outer_layout = QVBoxLayout() cal_gb_outer_layout.addWidget(self.calibration_timestamp_display) cal_gb_outer_layout.addWidget(self.calibration_countdown_display) cal_gb_layout = QHBoxLayout() cal_gb_outer_layout.addLayout(cal_gb_layout) cal_gb.setLayout(cal_gb_outer_layout) calibrate_gb = QGroupBox("Calibrate") calibrate_gb_layout = QFormLayout() calibrate_gb.setLayout(calibrate_gb_layout) calibrate_button = QPushButton("&Calibrate") def calibrate(): ch = int(self._ui_input_elements["cal_channel"].value()) wl = self._ui_input_elements["cal_wl"].value() if self._rpc_client is not None: logger.info( "sending RPC calibrate(channel={}, wavelength={})".format( ch, wl)) self._rpc_client.calibrate(ch, wl) calibrate_button.clicked.connect(calibrate) calibrate_gb_layout.addRow("", calibrate_button) self._ui_input_elements.update({"cal_channel": QDoubleSpinBox()}) self._ui_input_elements["cal_channel"].setRange(1, 100) self._ui_input_elements["cal_channel"].setSingleStep(1) self._ui_input_elements["cal_channel"].setDecimals(0) self._ui_input_elements["cal_channel"].setValue(cal_channel) calibrate_gb_layout.addRow("Channel", self._ui_input_elements["cal_channel"]) self._ui_input_elements.update({"cal_wl": QDoubleSpinBox()}) self._ui_input_elements["cal_wl"].setRange(1., 10000.) self._ui_input_elements["cal_wl"].setSingleStep(1e-10) self._ui_input_elements["cal_wl"].setDecimals(10) self._ui_input_elements["cal_wl"].setSuffix(" nm") self._ui_input_elements["cal_wl"].setValue(cal_wl) calibrate_gb_layout.addRow("Wavelength", self._ui_input_elements["cal_wl"]) cal_gb_layout.addWidget(calibrate_gb) autocalibration_gb = QGroupBox("Autocalibration") autocalibration_gb_layout = QFormLayout() autocalibration_gb.setLayout(autocalibration_gb_layout) start_autocalibration_button = QPushButton("Start &autocalibration") def start_autocalibration(): ch = int(self._ui_input_elements["autocal_channel"].value()) wl = self._ui_input_elements["autocal_wl"].value() thr = self._ui_input_elements["autocal_threshold"].value() interval = int(self._ui_input_elements["autocal_interval"].value()) retry_interval = int( self._ui_input_elements["autocal_retry_interval"].value()) if self._rpc_client is not None: logger.info( "sending RPC start_autocalibration(channel={}, wavelength={}, threshold={}, " "interval={}, retry_interval={})".format( ch, wl, thr, interval, retry_interval)) self._rpc_client.start_autocalibration(ch, wl, thr, interval, retry_interval) start_autocalibration_button.clicked.connect(start_autocalibration) autocalibration_gb_layout.addRow("", start_autocalibration_button) self._ui_input_elements.update({"autocal_channel": QDoubleSpinBox()}) self._ui_input_elements["autocal_channel"].setRange(1, 100) self._ui_input_elements["autocal_channel"].setSingleStep(1) self._ui_input_elements["autocal_channel"].setDecimals(0) self._ui_input_elements["autocal_channel"].setValue(cal_channel) autocalibration_gb_layout.addRow( "Channel", self._ui_input_elements["autocal_channel"]) self._ui_input_elements.update({"autocal_wl": QDoubleSpinBox()}) self._ui_input_elements["autocal_wl"].setRange(1., 10000.) self._ui_input_elements["autocal_wl"].setSingleStep(1e-10) self._ui_input_elements["autocal_wl"].setDecimals(10) self._ui_input_elements["autocal_wl"].setSuffix(" nm") self._ui_input_elements["autocal_wl"].setValue(cal_wl) autocalibration_gb_layout.addRow("Wavelength", self._ui_input_elements["autocal_wl"]) self._ui_input_elements.update({"autocal_threshold": QDoubleSpinBox()}) self._ui_input_elements["autocal_threshold"].setRange(1e-10, 10000.) self._ui_input_elements["autocal_threshold"].setSingleStep(1e-10) self._ui_input_elements["autocal_threshold"].setDecimals(10) self._ui_input_elements["autocal_threshold"].setSuffix(" nm") self._ui_input_elements["autocal_threshold"].setValue(cal_threshold) autocalibration_gb_layout.addRow( "Threshold", self._ui_input_elements["autocal_threshold"]) self._ui_input_elements.update({"autocal_interval": QDoubleSpinBox()}) self._ui_input_elements["autocal_interval"].setRange(1, 100000) self._ui_input_elements["autocal_interval"].setSingleStep(1) self._ui_input_elements["autocal_interval"].setDecimals(0) self._ui_input_elements["autocal_interval"].setSuffix(" s") self._ui_input_elements["autocal_interval"].setValue(cal_interval) autocalibration_gb_layout.addRow( "Interval", self._ui_input_elements["autocal_interval"]) self._ui_input_elements.update( {"autocal_retry_interval": QDoubleSpinBox()}) self._ui_input_elements["autocal_retry_interval"].setRange(1, 100000) self._ui_input_elements["autocal_retry_interval"].setSingleStep(1) self._ui_input_elements["autocal_retry_interval"].setDecimals(0) self._ui_input_elements["autocal_retry_interval"].setSuffix(" s") self._ui_input_elements["autocal_retry_interval"].setValue( cal_retry_interval) autocalibration_gb_layout.addRow( "Retry interval", self._ui_input_elements["autocal_retry_interval"]) stop_autocalibration_button = QPushButton("St&op autocalibration") def stop_autocalibration(): if self._rpc_client is not None: logger.info("sending RPC stop_autocalibration()") self._rpc_client.stop_autocalibration() stop_autocalibration_button.clicked.connect(stop_autocalibration) autocalibration_gb_layout.addRow("", stop_autocalibration_button) cal_gb_layout.addWidget(autocalibration_gb) self.v_layout.addWidget(cal_gb) exposure_gb = QGroupBox("Exposure") exposure_gb_layout = QHBoxLayout() exposure_gb.setLayout(exposure_gb_layout) control_form = QFormLayout() self._ui_input_elements.update({"exp_channel": QDoubleSpinBox()}) self._ui_input_elements["exp_channel"].setRange(1, 100) self._ui_input_elements["exp_channel"].setSingleStep(1) self._ui_input_elements["exp_channel"].setDecimals(0) self._ui_input_elements["exp_channel"].setValue(1) control_form.addRow("Channel", self._ui_input_elements["exp_channel"]) self._ui_input_elements.update({"exp_time1": QDoubleSpinBox()}) self._ui_input_elements["exp_time1"].setRange(1, 2000) self._ui_input_elements["exp_time1"].setSingleStep(1) self._ui_input_elements["exp_time1"].setDecimals(0) self._ui_input_elements["exp_time1"].setSuffix(" ms") self._ui_input_elements["exp_time1"].setValue(1) control_form.addRow("Time 1", self._ui_input_elements["exp_time1"]) self._ui_input_elements.update({"exp_time2": QDoubleSpinBox()}) self._ui_input_elements["exp_time2"].setRange(0, 2000) self._ui_input_elements["exp_time2"].setSingleStep(1) self._ui_input_elements["exp_time2"].setDecimals(0) self._ui_input_elements["exp_time2"].setSuffix(" ms") self._ui_input_elements["exp_time2"].setValue(1) control_form.addRow("Time 2", self._ui_input_elements["exp_time2"]) self._ui_input_elements.update({"exp_auto": QCheckBox()}) control_form.addRow("Auto adjust", self._ui_input_elements["exp_auto"]) exposure_gb_layout.addLayout(control_form) exposure_button_layout = QVBoxLayout() exposure_get_button = QPushButton("&Get") def exposure_get(): channel = int(self._ui_input_elements["exp_channel"].value()) if self._rpc_client is not None: logger.info( "sending RPC get_exposure_time({}, 1)".format(channel)) time1 = self._rpc_client.get_exposure_time(channel, 1) logger.info( "sending RPC get_exposure_time({}, 2)".format(channel)) time2 = self._rpc_client.get_exposure_time(channel, 2) logger.info( "sending RPC get_exposure_auto_adjust({})".format(channel)) auto = self._rpc_client.get_exposure_auto_adjust(channel) self._ui_input_elements["exp_time1"].setValue(time1) self._ui_input_elements["exp_time2"].setValue(time2) self._ui_input_elements["exp_auto"].setChecked(auto) exposure_get_button.clicked.connect(exposure_get) exposure_button_layout.addWidget(exposure_get_button) exposure_set_button = QPushButton("S&et") def exposure_set(): channel = int(self._ui_input_elements["exp_channel"].value()) time1 = int(self._ui_input_elements["exp_time1"].value()) time2 = int(self._ui_input_elements["exp_time2"].value()) auto = bool(self._ui_input_elements["exp_auto"].isChecked()) if self._rpc_client is not None: logger.info("sending RPC set_exposure_time({}, 1, {})".format( channel, time1)) self._rpc_client.set_exposure_time(channel, 1, time1) logger.info("sending RPC set_exposure_time({}, 2, {})".format( channel, time2)) self._rpc_client.set_exposure_time(channel, 2, time2) logger.info( "sending RPC set_exposure_auto_adjust({}, {})".format( channel, auto)) self._rpc_client.set_exposure_auto_adjust(channel, auto) exposure_set_button.clicked.connect(exposure_set) exposure_button_layout.addWidget(exposure_set_button) exposure_gb_layout.addLayout(exposure_button_layout) self.v_layout.addWidget(exposure_gb) def _update_cal_timestamp(self): self.calibration_timestamp_display.setText( "Last successful" " calibration:\n{}".format( time.asctime( time.localtime( self.wm_status_dict["calibration_timestamp"])))) def _update_cal_countdown(self): self.calibration_countdown_display.setText( "Next autocalibration attempt in {:.0f} s".format( self.wm_status_dict["autocal_countdown"])) def _subscriber_init_cb(self, data): self.wm_status_dict = data self._update_cal_timestamp() self._update_cal_countdown() return data def _subscriber_mod_cb(self, mod): try: if mod["key"] == "calibration_timestamp": self._update_cal_timestamp() elif mod["key"] == "autocal_countdown": self._update_cal_countdown() except KeyError: pass keepalive_interval = 3600. # ping RPC server after this interval to keep the connection alive async def keepalive_loop(self): """Keep the RPC connection alive""" while True: logger.info("Pinging the RPC server to keep the connection alive") self._rpc_client.ping() await asyncio.sleep(self.keepalive_interval) def run(self): self.window.show() self._loop.run_forever() if self._subscriber is not None: self._loop.run_until_complete(self._subscriber.close()) if self._rpc_client is not None: self._rpc_client.close_rpc()