def __init__(self, *args): PluginBase.__init__(self, BrickMaster, *args) self.setupUi(self) self.master = self.device # the firmware version of a Brick can (under common circumstances) not # change during the lifetime of a Brick plugin. therefore, it's okay to # make final decisions based on it here self.has_status_led = self.firmware_version >= (2, 3, 2) self.update_timer = QTimer(self) self.update_timer.timeout.connect(self.update_data) self.extension_type = None self.extensions = [] self.num_extensions = 0 self.wifi2_ext = None self.wifi2_firmware_version = None self.wifi_update_button = IconButton(QIcon(load_pixmap('update-icon-normal.png')), QIcon(load_pixmap('update-icon-hover.png')), self.tab_widget) self.wifi_update_button.setToolTip('Update available') self.wifi_update_button.clicked.connect(lambda: get_main_window().show_extension_update(self.device_info.uid)) self.wifi_update_button.hide() self.wifi_update_available = False self.wifi_tab_idx = None self.extension_label.setText("None Present") self.tab_widget.removeTab(0) self.tab_widget.hide() self.check_extensions = True self.extension_type_button.clicked.connect(self.extension_clicked) if self.has_status_led: self.status_led_action = QAction('Status LED', self) self.status_led_action.setCheckable(True) self.status_led_action.toggled.connect(lambda checked: self.master.enable_status_led() if checked else self.master.disable_status_led()) self.set_configs([(0, None, [self.status_led_action])]) else: self.status_led_action = None reset = QAction('Reset', self) reset.triggered.connect(self.master.reset) self.set_actions([(0, None, [reset])]) self.extension_type_preset = [None, # None False, # Chibi False, # RS485 False, # WIFI False, # Ethernet False] # WIFI 2.0 self.update_extensions_in_device_info()
def __init__(self, tab_widget, name, button_handler, parent=None): super(TabWindow, self).__init__(parent) self.tab_widget = tab_widget self.name = name self.button = None # see tab() self.button_handler = button_handler self.button_icon_default = QIcon(load_pixmap('tab-default-icon.png')) self.button_icon_mouse_over = QIcon(load_pixmap('tab-mouse-over-icon.png')) self.cb_on_tab = None self.cb_on_untab = None
def __init__(self, tab_widget, name, button_handler, parent=None): super().__init__(parent) self.tab_widget = tab_widget self.name = name self.button = None # see tab() self.button_handler = button_handler self.button_icon_normal = QIcon(load_pixmap('untab-icon-normal.png')) self.button_icon_hover = QIcon(load_pixmap('untab-icon-hover.png')) self.cb_on_tab = {} self.cb_on_untab = {} self.cb_post_tab = {} self.cb_post_untab = {} self.parent_dialog = None
def show_update_tab_button(self, tool_tip, clicked_fn): if not self.tabbed: return self.update_button = IconButton( QIcon(load_pixmap('update-icon-normal.png')), QIcon(load_pixmap('update-icon-hover.png'))) self.update_button.setToolTip(tool_tip) self.update_button.clicked.connect(clicked_fn) tab_idx = self.tab_widget.indexOf(self) self.tab_widget.tabBar().setTabButton(tab_idx, QTabBar.RightSide, self.update_button)
def btn_start_logging_clicked(self): """ Start/Stop of the logging process """ if (self.data_logger_thread is not None) and (not self.data_logger_thread.stopped): self.btn_start_logging.clicked.disconnect() self.data_logger_thread.stop() self._reset_stop() elif self.data_logger_thread is None: from brickv.data_logger import main self._gui_job = GuiDataJob(name="GuiData-Writer") self.connect(self._gui_job, QtCore.SIGNAL(GuiDataJob.SIGNAL_NEW_DATA), self.table_add_row) self.data_logger_thread = main.main(None, GuiConfigHandler.create_config(self), self._gui_job) if self.data_logger_thread is not None: self.btn_start_logging.setText("Stop Logging") self.btn_start_logging.setIcon(QIcon(load_pixmap('data_logger/stop-icon.png'))) self.tab_devices.setEnabled(False) self.tab_setup.setEnabled(False) self.tab_widget.setCurrentIndex(self.tab_widget.indexOf(self.tab_data)) self.tab_reset_warning()
def __init__(self, tab_widget, name, button_handler, parent=None): super().__init__(parent) self.tab_widget = tab_widget self.name = name self.button = None # see tab() self.button_handler = button_handler self.button_icon_normal = QIcon(load_pixmap('untab-icon-normal.png')) self.button_icon_hover = QIcon(load_pixmap('untab-icon-hover.png')) self.cb_on_tab = {} self.cb_on_untab = {} self.cb_post_tab = {} self.cb_post_untab = {} self.toplevel_window = None self.update_button = None self.tabbed = True
def btn_start_logging_clicked(self): """ Start/Stop of the logging process """ if (self.data_logger_thread is not None) and (not self.data_logger_thread.stopped): self.btn_start_logging.clicked.disconnect() self.data_logger_thread.stop() self._reset_stop() elif self.data_logger_thread is None: from brickv.data_logger import main self._gui_job = GuiDataJob(name="GuiData-Writer") self.connect(self._gui_job, QtCore.SIGNAL(GuiDataJob.SIGNAL_NEW_DATA), self.table_add_row) self.data_logger_thread = main.main( None, GuiConfigHandler.create_config(self), self._gui_job) if self.data_logger_thread is not None: self.btn_start_logging.setText("Stop Logging") self.btn_start_logging.setIcon( QIcon(load_pixmap('data_logger/stop-icon.png'))) self.tab_devices.setEnabled(False) self.tab_setup.setEnabled(False) self.tab_widget.setCurrentIndex( self.tab_widget.indexOf(self.tab_data)) self.tab_reset_warning()
def __init__(self, context, update_main_ui_state, set_widget_enabled, is_alive, show_upload_files_wizard, show_download_wizard): QWidget.__init__(self) self.setupUi(self) self.session = context.session self.script_manager = context.script_manager self.program = context.program self.update_main_ui_state = update_main_ui_state self.set_widget_enabled = set_widget_enabled self.is_alive = is_alive self.show_download_wizard = show_download_wizard self.bin_directory = posixpath.join(self.program.root_directory, 'bin') self.refresh_in_progress = False self.any_refresh_in_progress = False # set from ProgramInfoMain.update_ui_state self.available_files = [] self.available_directories = [] self.folder_icon = QIcon(load_pixmap('folder-icon.png')) self.file_icon = QIcon(load_pixmap('file-icon.png')) self.tree_files_model = QStandardItemModel(self) self.tree_files_model_header = ['Name', 'Size', 'Last Modified'] self.tree_files_proxy_model = FilesProxyModel(self) self.last_download_directory = get_home_path() self.tree_files_model.setHorizontalHeaderLabels( self.tree_files_model_header) self.tree_files_proxy_model.setSourceModel(self.tree_files_model) self.tree_files.setModel(self.tree_files_model) self.tree_files.setModel(self.tree_files_proxy_model) self.tree_files.setColumnWidth(0, 210) self.tree_files.setColumnWidth(1, 85) self.tree_files.selectionModel().selectionChanged.connect( self.update_ui_state) self.tree_files.activated.connect(self.rename_activated_file) self.button_upload_files.clicked.connect(show_upload_files_wizard) self.button_download_files.clicked.connect( self.download_selected_files) self.button_rename_file.clicked.connect(self.rename_selected_file) self.button_change_file_permissions.clicked.connect( self.change_permissions_of_selected_file) self.button_delete_files.clicked.connect(self.delete_selected_files) self.label_error.setVisible(False)
def error_report_main(): error_message = sys.stdin.read() label_suffix, error_message = error_message.split('!!!') error_message = "<pre>{}</pre>".format(html.escape(error_message).replace("\n", "<br>")) app = QApplication(sys.argv) if sys.platform == 'darwin': # workaround macOS QTBUG-61562 from brickv.mac_pasteboard_mime_fixed import MacPasteboardMimeFixed mac_pasteboard_mime_fixed = MacPasteboardMimeFixed() window = QMainWindow() window.setWindowTitle('Error - Brick Viewer ' + config.BRICKV_VERSION) window.setWindowIcon(QIcon(load_pixmap('brickv-icon.png'))) widget = QWidget() window.setCentralWidget(widget) widget.setLayout(QHBoxLayout()) icon = QLabel() icon.setPixmap(QMessageBox.standardIcon(QMessageBox.Critical)) icon.setAlignment(Qt.AlignHCenter | Qt.AlignTop) widget.layout().addWidget(icon) right_widget = QWidget() right_widget.setLayout(QVBoxLayout()) right_widget.layout().setContentsMargins(0, 0, 0, 0) label = QLabel("Please report this error to <a href='mailto:[email protected]'>[email protected]</a>.<br/>" + "Please also report what you tried to do, when the error was reported.<br/><br/>" + "If you know what caused the error and could work around it, please report it anyway. This allows us to improve the error messages.{}".format(label_suffix)) label.setWordWrap(True) label.setOpenExternalLinks(True) right_widget.layout().addWidget(label) tb = QTextBrowser() tb.setHtml(error_message) right_widget.layout().addWidget(tb) cbox = QCheckBox("Show this message again") cbox.setChecked(True) right_widget.layout().addWidget(cbox) btn = QPushButton("Close") btn.clicked.connect(lambda event: app.exit()) right_widget.layout().addWidget(btn) widget.layout().addWidget(right_widget) window.setMinimumSize(640, 400) window.resize(950, 600) window.show() app.exec_() return int(cbox.isChecked())
def device_infos_changed(self, uid): if uid != self.device_info.uid: return if self.extension_type_preset[self.master.EXTENSION_TYPE_WIFI2]: try: wifi_info = next(ext for ext in self.device_info.extensions.values() if ext.extension_type == self.master.EXTENSION_TYPE_WIFI2) wifi_update_avail = wifi_info.firmware_version_installed != (0, 0, 0) and wifi_info.firmware_version_installed < wifi_info.firmware_version_latest except StopIteration: wifi_update_avail = False else: wifi_update_avail = False brick_update_avail = self.device_info.firmware_version_installed < self.device_info.firmware_version_latest tab_idx = get_main_window().tab_widget.indexOf(self.device_info.tab_window) if not brick_update_avail and not wifi_update_avail: if self.device_info.tab_window is not None: self.device_info.tab_window.button_update.hide() get_main_window().tab_widget.tabBar().setTabButton(tab_idx, QTabBar.RightSide, None) if self.wifi_tab_idx is not None: self.tab_widget.tabBar().setTabButton(self.wifi_tab_idx, QTabBar.LeftSide, None) if self.wifi_update_button is not None: self.wifi_update_button.hide() return self.update_tab_button = IconButton(QIcon(load_pixmap('update-icon-normal.png')), QIcon(load_pixmap('update-icon-hover.png'))) if brick_update_avail: if self.device_info.tab_window is not None: self.device_info.tab_window.button_update.show() self.update_tab_button.setToolTip('Update available') self.update_tab_button.clicked.connect(lambda: get_main_window().show_brick_update(self.device_info.url_part)) if self.wifi_tab_idx is not None: self.tab_widget.tabBar().setTabButton(self.wifi_tab_idx, QTabBar.LeftSide, None) if self.wifi_update_button is not None: self.wifi_update_button.hide() # Intentionally override possible Master Brick update notification: The Extension update is easier for users # so they are more likely to update at least the Extension. Also when the Extension is updated, device_infos_changed # will be called again, then notifying the user of the Master Brick update. if wifi_update_avail: self.update_tab_button.setToolTip('WIFI Extension 2.0 Update available') self.update_tab_button.clicked.connect(lambda: get_main_window().show_extension_update(self.device_info.uid)) if self.wifi_tab_idx is not None: self.tab_widget.tabBar().setTabButton(self.wifi_tab_idx, QTabBar.LeftSide, self.wifi_update_button) self.wifi_update_button.show() get_main_window().tab_widget.tabBar().setTabButton(tab_idx, QTabBar.RightSide, self.update_tab_button)
def __init__(self, title_prefix='', last_directory=None): ProgramPage.__init__(self) self.setupUi(self) self.edit_mode = False self.folder_icon = QIcon(load_pixmap('folder-icon.png')) self.file_icon = QIcon(load_pixmap('file-icon.png')) if last_directory != None: self.last_directory = last_directory else: self.last_directory = get_home_path() self.setTitle(title_prefix + 'Files') self.list_files.itemSelectionChanged.connect(self.update_ui_state) self.button_add_files.clicked.connect(self.show_add_files_dialog) self.button_add_directory.clicked.connect(self.show_add_directory_dialog) self.button_remove_selected_files.clicked.connect(self.remove_selected_files)
def _reset_stop(self): self.tab_devices.setEnabled(True) self.tab_setup.setEnabled(True) self.btn_start_logging.setText("Start Logging") self.btn_start_logging.setIcon(QIcon(load_pixmap('data_logger/start-icon.png'))) self.disconnect(self._gui_job, QtCore.SIGNAL(GuiDataJob.SIGNAL_NEW_DATA), self.table_add_row) self.data_logger_thread = None self._gui_job = None self.btn_start_logging.clicked.connect(self.btn_start_logging_clicked)
def error_report_main(): error_message = sys.stdin.read() error_message = "<pre>{}</pre>".format(html.escape(error_message).replace("\n", "<br>")) app = QApplication(sys.argv) if sys.platform == 'darwin': # workaround macOS QTBUG-61562 from brickv.mac_pasteboard_mime_fixed import MacPasteboardMimeFixed mac_pasteboard_mime_fixed = MacPasteboardMimeFixed() window = QMainWindow() window.setWindowTitle('Error - Brick Viewer ' + config.BRICKV_VERSION) window.setWindowIcon(QIcon(load_pixmap('brickv-icon.png'))) widget = QWidget() window.setCentralWidget(widget) widget.setLayout(QHBoxLayout()) icon = QLabel() icon.setPixmap(QMessageBox.standardIcon(QMessageBox.Critical)) icon.setAlignment(Qt.AlignHCenter | Qt.AlignTop) widget.layout().addWidget(icon) right_widget = QWidget() right_widget.setLayout(QVBoxLayout()) right_widget.layout().setContentsMargins(0, 0, 0, 0) label = QLabel("Please report this error to <a href='mailto:[email protected]'>[email protected]</a>.<br/><br/>" + "If you know what caused the error and could work around it, please report it anyway. This allows us to improve the error messages.") label.setWordWrap(True) label.setOpenExternalLinks(True) right_widget.layout().addWidget(label) tb = QTextBrowser() tb.setHtml(error_message) right_widget.layout().addWidget(tb) cbox = QCheckBox("Show this message again") cbox.setChecked(True) right_widget.layout().addWidget(cbox) btn = QPushButton("Close") btn.clicked.connect(lambda event: app.exit()) right_widget.layout().addWidget(btn) widget.layout().addWidget(right_widget) window.setMinimumSize(640, 400) window.resize(950, 600) window.show() app.exec_() return int(cbox.isChecked())
def _reset_stop(self): self.tab_devices.setEnabled(True) self.tab_setup.setEnabled(True) self.btn_start_logging.setText("Start Logging") self.btn_start_logging.setIcon( QIcon(load_pixmap('data_logger/start-icon.png'))) self._gui_job.signalNewData.disconnect(self.table_add_row) self.data_logger_thread = None self._gui_job = None self.btn_start_logging.clicked.connect(self.btn_start_logging_clicked)
def _reset_stop(self): self.tab_devices.setEnabled(True) self.tab_setup.setEnabled(True) self.btn_start_logging.setText("Start Logging") self.btn_start_logging.setIcon(QIcon(load_pixmap('data_logger/start-icon.png'))) self._gui_job.signalNewData.disconnect(self.table_add_row) self.data_logger_thread = None self._gui_job = None self.btn_start_logging.clicked.connect(self.btn_start_logging_clicked)
def __init__(self, context, update_main_ui_state, set_widget_enabled, is_alive, show_upload_files_wizard, show_download_wizard): QWidget.__init__(self) self.setupUi(self) self.session = context.session self.script_manager = context.script_manager self.program = context.program self.update_main_ui_state = update_main_ui_state self.set_widget_enabled = set_widget_enabled self.is_alive = is_alive self.show_download_wizard = show_download_wizard self.bin_directory = posixpath.join(self.program.root_directory, 'bin') self.refresh_in_progress = False self.any_refresh_in_progress = False # set from ProgramInfoMain.update_ui_state self.available_files = [] self.available_directories = [] self.folder_icon = QIcon(load_pixmap('folder-icon.png')) self.file_icon = QIcon(load_pixmap('file-icon.png')) self.tree_files_model = QStandardItemModel(self) self.tree_files_model_header = ['Name', 'Size', 'Last Modified'] self.tree_files_proxy_model = FilesProxyModel(self) self.last_download_directory = get_home_path() self.tree_files_model.setHorizontalHeaderLabels(self.tree_files_model_header) self.tree_files_proxy_model.setSourceModel(self.tree_files_model) self.tree_files.setModel(self.tree_files_model) self.tree_files.setModel(self.tree_files_proxy_model) self.tree_files.setColumnWidth(0, 210) self.tree_files.setColumnWidth(1, 85) self.tree_files.selectionModel().selectionChanged.connect(self.update_ui_state) self.tree_files.activated.connect(self.rename_activated_file) self.button_upload_files.clicked.connect(show_upload_files_wizard) self.button_download_files.clicked.connect(self.download_selected_files) self.button_rename_file.clicked.connect(self.rename_selected_file) self.button_change_file_permissions.clicked.connect(self.change_permissions_of_selected_file) self.button_delete_files.clicked.connect(self.delete_selected_files) self.label_error.setVisible(False)
def __init__(self, title_prefix='', last_directory=None): ProgramPage.__init__(self) self.setupUi(self) self.edit_mode = False self.folder_icon = QIcon(load_pixmap('folder-icon.png')) self.file_icon = QIcon(load_pixmap('file-icon.png')) if last_directory != None: self.last_directory = last_directory else: self.last_directory = get_home_path() self.setTitle(title_prefix + 'Files') self.list_files.itemSelectionChanged.connect(self.update_ui_state) self.button_add_files.clicked.connect(self.show_add_files_dialog) self.button_add_directory.clicked.connect( self.show_add_directory_dialog) self.button_remove_selected_files.clicked.connect( self.remove_selected_files)
def __init__(self, download_kind, download_directory, downloads, title_prefix=''): ProgramPage.__init__(self) self.setupUi(self) self.download_kind = download_kind # 'logs' or 'files' self.download_directory = download_directory # absolute path on host in host format self.conflict_resolution_in_progress = False self.auto_conflict_resolution = None self.download_successful = False self.root_directory = None self.remaining_downloads = downloads self.download = None self.created_directories = set() self.target_path = None # abolsute path on host in host format self.chunked_downloader = None self.replace_help_template = self.label_replace_help.text() self.canceled = False self.setTitle(title_prefix + 'Download') self.progress_file.setVisible(False) self.check_rename_new_file.stateChanged.connect(self.update_ui_state) self.edit_new_name.textChanged.connect(self.check_new_name) self.button_reset_new_name.clicked.connect(self.reset_new_name) self.button_replace.clicked.connect(self.resolve_conflict_by_replace) self.button_rename.clicked.connect(self.resolve_conflict_by_rename) self.button_skip.clicked.connect(self.skip_conflict) self.button_start_download.clicked.connect(self.start_download) self.label_replace_icon.clear() self.label_replace_icon.setPixmap(load_pixmap('warning-icon.png')) self.edit_new_name_checker = MandatoryLineEditChecker( self, self.label_new_name, self.edit_new_name) self.log(u'Going to download {0} to {1}'.format( self.download_kind, self.download_directory)) self.edit_log.moveCursor(QTextCursor.StartOfLine)
def show_status(self, message, icon='warning', message_id=''): self.setStatusBar(None) if icon != 'none': icon_dict = { 'warning': 'warning-icon-16.png', } icon_label = QLabel() icon_label.setPixmap(load_pixmap(icon_dict[icon])) self.statusBar().addWidget(icon_label) message_label = QLabel(message) message_label.setOpenExternalLinks(True) self.statusBar().addWidget(message_label, 1) self.last_status_message_id = message_id
def __init__(self, title_prefix=''): ProgramPage.__init__(self) self.setupUi(self) self.edit_mode = False self.conflict_resolution_in_progress = False self.auto_conflict_resolution = None self.upload_successful = False self.language_api_name = None self.program = None self.program_defined = False self.root_directory = None self.remaining_uploads = None self.upload = None self.command = None self.created_directories = set() self.target_path = None # abolsute path on RED Brick in POSIX format self.chunked_uploader = None self.replace_help_template = self.label_replace_help.text() self.warnings = 0 self.canceled = False self.setTitle(title_prefix + 'Upload') self.progress_file.setVisible(False) self.check_rename_new_file.stateChanged.connect(self.update_ui_state) self.edit_new_name.textChanged.connect(self.check_new_name) self.button_reset_new_name.clicked.connect(self.reset_new_name) self.button_replace.clicked.connect(self.resolve_conflict_by_replace) self.button_rename.clicked.connect(self.resolve_conflict_by_rename) self.button_skip.clicked.connect(self.skip_conflict) self.button_start_upload.clicked.connect(self.start_upload) self.label_replace_icon.clear() self.label_replace_icon.setPixmap(load_pixmap('warning-icon.png')) self.edit_new_name_checker = MandatoryLineEditChecker( self, self.label_new_name, self.edit_new_name)
def __init__(self, title_prefix=''): ProgramPage.__init__(self) self.setupUi(self) self.edit_mode = False self.conflict_resolution_in_progress = False self.auto_conflict_resolution = None self.upload_successful = False self.language_api_name = None self.program = None self.program_defined = False self.root_directory = None self.remaining_uploads = None self.upload = None self.command = None self.created_directories = set() self.target_path = None # abolsute path on RED Brick in POSIX format self.chunked_uploader = None self.replace_help_template = self.label_replace_help.text() self.warnings = 0 self.canceled = False self.setTitle(title_prefix + 'Upload') self.progress_file.setVisible(False) self.check_rename_new_file.stateChanged.connect(self.update_ui_state) self.edit_new_name.textChanged.connect(self.check_new_name) self.button_reset_new_name.clicked.connect(self.reset_new_name) self.button_replace.clicked.connect(self.resolve_conflict_by_replace) self.button_rename.clicked.connect(self.resolve_conflict_by_rename) self.button_skip.clicked.connect(self.skip_conflict) self.button_start_upload.clicked.connect(self.start_upload) self.label_replace_icon.clear() self.label_replace_icon.setPixmap(load_pixmap('warning-icon-44.png')) self.edit_new_name_checker = MandatoryLineEditChecker(self, self.label_new_name, self.edit_new_name)
def __init__(self, context, update_main_ui_state, set_widget_enabled, is_alive, show_download_wizard, set_program_callbacks_enabled): QWidget.__init__(self) self.setupUi(self) self.session = context.session self.script_manager = context.script_manager self.program = context.program self.update_main_ui_state = update_main_ui_state self.set_widget_enabled = set_widget_enabled self.is_alive = is_alive self.show_download_wizard = show_download_wizard self.set_program_callbacks_enabled = set_program_callbacks_enabled self.log_directory = posixpath.join(self.program.root_directory, 'log') self.refresh_in_progress = False self.any_refresh_in_progress = False # set from ProgramInfoMain.update_ui_state self.view_dialog = None self.file_icon = QIcon(load_pixmap('file-icon.png')) self.tree_logs_model = QStandardItemModel(self) self.tree_logs_model_header = ['Date/Time', 'Size'] self.tree_logs_proxy_model = LogsProxyModel(self) self.last_download_directory = get_home_path() self.tree_logs_model.setHorizontalHeaderLabels( self.tree_logs_model_header) self.tree_logs_proxy_model.setSourceModel(self.tree_logs_model) self.tree_logs.setModel(self.tree_logs_proxy_model) self.tree_logs.setColumnWidth(0, 250) self.tree_logs.selectionModel().selectionChanged.connect( self.update_ui_state) self.tree_logs.activated.connect(self.view_activated_log) self.button_download_logs.clicked.connect(self.download_selected_logs) self.button_view_log.clicked.connect(self.view_selected_log) self.button_delete_logs.clicked.connect(self.delete_selected_logs) self.label_error.setVisible(False)
def __init__(self, download_kind, download_directory, downloads, title_prefix=''): ProgramPage.__init__(self) self.setupUi(self) self.download_kind = download_kind # 'logs' or 'files' self.download_directory = download_directory # absolute path on host in host format self.conflict_resolution_in_progress = False self.auto_conflict_resolution = None self.download_successful = False self.root_directory = None self.remaining_downloads = downloads self.download = None self.created_directories = set() self.target_path = None # abolsute path on host in host format self.chunked_downloader = None self.replace_help_template = self.label_replace_help.text() self.canceled = False self.setTitle(title_prefix + 'Download') self.progress_file.setVisible(False) self.check_rename_new_file.stateChanged.connect(self.update_ui_state) self.edit_new_name.textChanged.connect(self.check_new_name) self.button_reset_new_name.clicked.connect(self.reset_new_name) self.button_replace.clicked.connect(self.resolve_conflict_by_replace) self.button_rename.clicked.connect(self.resolve_conflict_by_rename) self.button_skip.clicked.connect(self.skip_conflict) self.button_start_download.clicked.connect(self.start_download) self.label_replace_icon.clear() self.label_replace_icon.setPixmap(load_pixmap('warning-icon-44.png')) self.edit_new_name_checker = MandatoryLineEditChecker(self, self.label_new_name, self.edit_new_name) self.log('Going to download {0} to {1}'.format(self.download_kind, self.download_directory)) self.edit_log.moveCursor(QTextCursor.StartOfLine)
def __init__(self, context, update_main_ui_state, set_widget_enabled, is_alive, show_download_wizard, set_program_callbacks_enabled): QWidget.__init__(self) self.setupUi(self) self.session = context.session self.script_manager = context.script_manager self.program = context.program self.update_main_ui_state = update_main_ui_state self.set_widget_enabled = set_widget_enabled self.is_alive = is_alive self.show_download_wizard = show_download_wizard self.set_program_callbacks_enabled = set_program_callbacks_enabled self.log_directory = posixpath.join(self.program.root_directory, 'log') self.refresh_in_progress = False self.any_refresh_in_progress = False # set from ProgramInfoMain.update_ui_state self.view_dialog = None self.file_icon = QIcon(load_pixmap('file-icon.png')) self.tree_logs_model = QStandardItemModel(self) self.tree_logs_model_header = ['Date/Time', 'Size'] self.tree_logs_proxy_model = LogsProxyModel(self) self.last_download_directory = get_home_path() self.tree_logs_model.setHorizontalHeaderLabels(self.tree_logs_model_header) self.tree_logs_proxy_model.setSourceModel(self.tree_logs_model) self.tree_logs.setModel(self.tree_logs_proxy_model) self.tree_logs.setColumnWidth(0, 250) self.tree_logs.selectionModel().selectionChanged.connect(self.update_ui_state) self.tree_logs.activated.connect(self.view_activated_log) self.button_download_logs.clicked.connect(self.download_selected_logs) self.button_view_log.clicked.connect(self.view_selected_log) self.button_delete_logs.clicked.connect(self.delete_selected_logs) self.label_error.setVisible(False)
def __init__(self, parent, host_infos): QDialog.__init__(self, parent, get_modeless_dialog_flags()) self._gui_logger = GUILogger("GUILogger", logging.INFO) self._gui_job = None EventLogger.add_logger(self._gui_logger) self.data_logger_thread = None self.tab_debug_warning = False self.device_dialog = None self.last_host_index = -1 self.setupUi(self) self.model_data = QStandardItemModel(self) self.model_data.setHorizontalHeaderLabels(['Time', 'Name', 'UID', 'Var', 'Raw', 'Unit']) self.table_data.setModel(self.model_data) self.table_data.setColumnWidth(0, 160) self.table_data.setColumnWidth(1, 170) self.table_data.setColumnWidth(2, 50) self.table_data.setColumnWidth(3, 110) self.table_data.setColumnWidth(4, 70) self.table_data.setColumnWidth(5, 100) self.model_devices = QStandardItemModel(self) self.model_devices.setHorizontalHeaderLabels(['Device', 'Value']) self.tree_devices.setModel(self.model_devices) self.tree_devices.setColumnWidth(0, 300) self.signal_initialization() self.check_authentication.stateChanged.connect(self.authentication_state_changed) self.label_secret.hide() self.edit_secret.hide() self.edit_secret.setEchoMode(QLineEdit.Password) self.check_secret_show.hide() self.check_secret_show.stateChanged.connect(self.secret_show_state_changed) self.btn_start_logging.setIcon(QIcon(load_pixmap('data_logger/start-icon.png'))) self.example_timestamp = time.time() self.edit_csv_file_name.setText(os.path.join(get_home_path(), 'logger_data_{0}.csv'.format(int(self.example_timestamp)))) self.edit_log_file_name.setText(os.path.join(get_home_path(), 'logger_debug_{0}.log'.format(int(self.example_timestamp)))) self.combo_data_time_format.addItem(utils.timestamp_to_de(self.example_timestamp) + ' (DD.MM.YYYY HH:MM:SS)', 'de') self.combo_data_time_format.addItem(utils.timestamp_to_de_msec(self.example_timestamp) + ' (DD.MM.YYYY HH:MM:SS,000)', 'de-msec') self.combo_data_time_format.insertSeparator(self.combo_data_time_format.count()) self.combo_data_time_format.addItem(utils.timestamp_to_us(self.example_timestamp) + ' (MM/DD/YYYY HH:MM:SS)', 'us') self.combo_data_time_format.addItem(utils.timestamp_to_us_msec(self.example_timestamp) + ' (MM/DD/YYYY HH:MM:SS.000)', 'us-msec') self.combo_data_time_format.insertSeparator(self.combo_data_time_format.count()) self.combo_data_time_format.addItem(utils.timestamp_to_iso(self.example_timestamp) + ' (ISO 8601)', 'iso') self.combo_data_time_format.addItem(utils.timestamp_to_iso_msec(self.example_timestamp) + ' (ISO 8601 + Milliseconds)', 'iso-msec') self.combo_data_time_format.insertSeparator(self.combo_data_time_format.count()) self.combo_data_time_format.addItem(utils.timestamp_to_unix(self.example_timestamp) + ' (Unix)', 'unix') self.combo_data_time_format.addItem(utils.timestamp_to_unix_msec(self.example_timestamp) + ' (Unix + Milliseconds)', 'unix-msec') self.combo_data_time_format.insertSeparator(self.combo_data_time_format.count()) t = utils.timestamp_to_strftime(self.example_timestamp, self.edit_data_time_format_strftime.text()) if len(t) == 0: t = '<empty>' self.combo_data_time_format.addItem((t + ' (strftime)'), 'strftime') self.combo_debug_time_format.addItem(utils.timestamp_to_de(self.example_timestamp) + ' (DD.MM.YYYY HH:MM:SS)', 'de') self.combo_debug_time_format.addItem(utils.timestamp_to_us(self.example_timestamp) + ' (MM/DD/YYYY HH:MM:SS)', 'us') self.combo_debug_time_format.addItem(utils.timestamp_to_iso(self.example_timestamp) + ' (ISO 8601)', 'iso') self.combo_debug_time_format.addItem(utils.timestamp_to_unix(self.example_timestamp) + ' (Unix)', 'unix') self.combo_log_level.addItem('Debug', 'debug') self.combo_log_level.addItem('Info', 'info') self.combo_log_level.addItem('Warning', 'warning') self.combo_log_level.addItem('Error', 'error') self.combo_log_level.addItem('Critical', 'critical') self.combo_log_level.setCurrentIndex(0) # debug self.combo_debug_level.addItem('Debug', logging.DEBUG) self.combo_debug_level.addItem('Info', logging.INFO) self.combo_debug_level.addItem('Warning', logging.WARNING) self.combo_debug_level.addItem('Error', logging.ERROR) self.combo_debug_level.addItem('Critical', logging.CRITICAL) self.combo_debug_level.setCurrentIndex(1) # info for host_info in host_infos: self.combo_host.addItem(host_info.host, (host_info.port, host_info.use_authentication, host_info.secret)) self._host_index_changed(0) self.update_ui_state()
def __init__(self, parent): QDialog.__init__(self, parent) self._gui_logger = GUILogger("GUILogger", logging.INFO) self._gui_job = None EventLogger.add_logger(self._gui_logger) # FIXME better way to find interval and uids in tree_widget?! self.__tree_interval_tooltip = "Update interval in seconds" self.__tree_uid_tooltip = "UID cannot be empty" self.data_logger_thread = None self.tab_debug_warning = False self.device_dialog = None self.host_infos = None self.last_host = None self.host_index_changing = None self.setupUi(self) self.model_data = QStandardItemModel(self) self.model_data.setHorizontalHeaderLabels(['Time', 'Name', 'UID', 'Var', 'Raw', 'Unit']) self.table_data.setModel(self.model_data) self.table_data.setColumnWidth(0, 160) self.table_data.setColumnWidth(1, 170) self.table_data.setColumnWidth(2, 50) self.table_data.setColumnWidth(3, 110) self.table_data.setColumnWidth(4, 70) self.table_data.setColumnWidth(5, 100) self.model_devices = QStandardItemModel(self) self.model_devices.setHorizontalHeaderLabels(['Device', 'Value']) self.tree_devices.setModel(self.model_devices) self.tree_devices.setColumnWidth(0, 300) self.widget_initialization() self.btn_start_logging.setIcon(QIcon(load_pixmap('data_logger/start-icon.png'))) timestamp = int(time.time()) self.edit_csv_file_name.setText(os.path.join(get_home_path(), 'logger_data_{0}.csv'.format(timestamp))) self.edit_log_file_name.setText(os.path.join(get_home_path(), 'logger_debug_{0}.log'.format(timestamp))) self.combo_data_time_format.addItem(utils.timestamp_to_de(timestamp) + ' (DD.MM.YYYY HH:MM:SS)', 'de') self.combo_data_time_format.addItem(utils.timestamp_to_us(timestamp) + ' (MM/DD/YYYY HH:MM:SS)', 'us') self.combo_data_time_format.addItem(utils.timestamp_to_iso(timestamp) + ' (ISO 8601)', 'iso') self.combo_data_time_format.addItem(utils.timestamp_to_unix(timestamp) + ' (Unix)', 'unix') self.combo_debug_time_format.addItem(utils.timestamp_to_de(timestamp) + ' (DD.MM.YYYY HH:MM:SS)', 'de') self.combo_debug_time_format.addItem(utils.timestamp_to_us(timestamp) + ' (MM/DD/YYYY HH:MM:SS)', 'us') self.combo_debug_time_format.addItem(utils.timestamp_to_iso(timestamp) + ' (ISO 8601)', 'iso') self.combo_debug_time_format.addItem(utils.timestamp_to_unix(timestamp) + ' (Unix)', 'unix') self.combo_log_level.addItem('Debug', 'debug') self.combo_log_level.addItem('Info', 'info') self.combo_log_level.addItem('Warning', 'warning') self.combo_log_level.addItem('Error', 'error') self.combo_log_level.addItem('Critical', 'critical') self.combo_log_level.setCurrentIndex(0) # debug self.combo_debug_level.addItem('Debug', logging.DEBUG) self.combo_debug_level.addItem('Info', logging.INFO) self.combo_debug_level.addItem('Warning', logging.WARNING) self.combo_debug_level.addItem('Error', logging.ERROR) self.combo_debug_level.addItem('Critical', logging.CRITICAL) self.combo_debug_level.setCurrentIndex(1) # info self.update_ui_state()
def __init__(self, parent, host_infos): QDialog.__init__(self, parent, get_modeless_dialog_flags()) self._gui_logger = GUILogger("GUILogger", logging.INFO) self._gui_job = None EventLogger.add_logger(self._gui_logger) self.data_logger_thread = None self.tab_debug_warning = False self.device_dialog = None self.last_host_index = -1 self.setupUi(self) self.model_data = QStandardItemModel(self) self.model_data.setHorizontalHeaderLabels( ['Time', 'Name', 'UID', 'Var', 'Raw', 'Unit']) self.table_data.setModel(self.model_data) self.table_data.setColumnWidth(0, 160) self.table_data.setColumnWidth(1, 170) self.table_data.setColumnWidth(2, 50) self.table_data.setColumnWidth(3, 110) self.table_data.setColumnWidth(4, 70) self.table_data.setColumnWidth(5, 100) self.model_devices = QStandardItemModel(self) self.model_devices.setHorizontalHeaderLabels(['Device', 'Value']) self.tree_devices.setModel(self.model_devices) self.tree_devices.setColumnWidth(0, 300) self.signal_initialization() self.check_authentication.stateChanged.connect( self.authentication_state_changed) self.label_secret.hide() self.edit_secret.hide() self.edit_secret.setEchoMode(QLineEdit.Password) self.check_secret_show.hide() self.check_secret_show.stateChanged.connect( self.secret_show_state_changed) self.btn_start_logging.setIcon( QIcon(load_pixmap('data_logger/start-icon.png'))) self.example_timestamp = time.time() self.edit_csv_file_name.setText( os.path.join( get_home_path(), 'logger_data_{0}.csv'.format(int(self.example_timestamp)))) self.edit_log_file_name.setText( os.path.join( get_home_path(), 'logger_debug_{0}.log'.format(int(self.example_timestamp)))) self.combo_data_time_format.addItem( utils.timestamp_to_de(self.example_timestamp) + ' (DD.MM.YYYY HH:MM:SS)', 'de') self.combo_data_time_format.addItem( utils.timestamp_to_de_msec(self.example_timestamp) + ' (DD.MM.YYYY HH:MM:SS,000)', 'de-msec') self.combo_data_time_format.insertSeparator( self.combo_data_time_format.count()) self.combo_data_time_format.addItem( utils.timestamp_to_us(self.example_timestamp) + ' (MM/DD/YYYY HH:MM:SS)', 'us') self.combo_data_time_format.addItem( utils.timestamp_to_us_msec(self.example_timestamp) + ' (MM/DD/YYYY HH:MM:SS.000)', 'us-msec') self.combo_data_time_format.insertSeparator( self.combo_data_time_format.count()) self.combo_data_time_format.addItem( utils.timestamp_to_iso(self.example_timestamp) + ' (ISO 8601)', 'iso') self.combo_data_time_format.addItem( utils.timestamp_to_iso_msec(self.example_timestamp) + ' (ISO 8601 + Milliseconds)', 'iso-msec') self.combo_data_time_format.insertSeparator( self.combo_data_time_format.count()) self.combo_data_time_format.addItem( utils.timestamp_to_unix(self.example_timestamp) + ' (Unix)', 'unix') self.combo_data_time_format.addItem( utils.timestamp_to_unix_msec(self.example_timestamp) + ' (Unix + Milliseconds)', 'unix-msec') self.combo_data_time_format.insertSeparator( self.combo_data_time_format.count()) t = utils.timestamp_to_strftime( self.example_timestamp, self.edit_data_time_format_strftime.text()) if len(t) == 0: t = '<empty>' self.combo_data_time_format.addItem((t + ' (strftime)'), 'strftime') self.combo_debug_time_format.addItem( utils.timestamp_to_de(self.example_timestamp) + ' (DD.MM.YYYY HH:MM:SS)', 'de') self.combo_debug_time_format.addItem( utils.timestamp_to_us(self.example_timestamp) + ' (MM/DD/YYYY HH:MM:SS)', 'us') self.combo_debug_time_format.addItem( utils.timestamp_to_iso(self.example_timestamp) + ' (ISO 8601)', 'iso') self.combo_debug_time_format.addItem( utils.timestamp_to_unix(self.example_timestamp) + ' (Unix)', 'unix') self.combo_log_level.addItem('Debug', 'debug') self.combo_log_level.addItem('Info', 'info') self.combo_log_level.addItem('Warning', 'warning') self.combo_log_level.addItem('Error', 'error') self.combo_log_level.addItem('Critical', 'critical') self.combo_log_level.setCurrentIndex(0) # debug self.combo_debug_level.addItem('Debug', logging.DEBUG) self.combo_debug_level.addItem('Info', logging.INFO) self.combo_debug_level.addItem('Warning', logging.WARNING) self.combo_debug_level.addItem('Error', logging.ERROR) self.combo_debug_level.addItem('Critical', logging.CRITICAL) self.combo_debug_level.setCurrentIndex(1) # info for host_info in host_infos: self.combo_host.addItem( host_info.host, (host_info.port, host_info.use_authentication, host_info.secret)) self._host_index_changed(0) self.update_ui_state()
def __init__(self, *args): PluginBase.__init__(self, BrickMaster, *args) self.setupUi(self) self.master = self.device # the firmware version of a Brick can (under common circumstances) not # change during the lifetime of a Brick plugin. therefore, it's okay to # make final decisions based on it here self.has_status_led = self.firmware_version >= (2, 3, 2) self.update_timer = QTimer(self) self.update_timer.timeout.connect(self.update_data) self.extension_type = None self.extension_tabs = [] self.wifi2_firmware_version = None self.wifi2_update_button = IconButton( QIcon(load_pixmap('update-icon-normal.png')), QIcon(load_pixmap('update-icon-hover.png')), self.tab_widget) self.wifi2_update_button.setToolTip('Update available') self.wifi2_update_button.clicked.connect(lambda: get_main_window( ).show_extension_update(self.device_info.uid)) self.wifi2_update_button.hide() self.wifi2_tab_idx = None self.wifi2_start_done = False self.extension_label.setText("None Present") self.tab_widget.removeTab(0) self.tab_widget.hide() self.start_extensions = True self.extension_type_button.clicked.connect(self.extension_clicked) if self.has_status_led: self.status_led_action = QAction('Status LED', self) self.status_led_action.setCheckable(True) self.status_led_action.toggled.connect( lambda checked: self.master.enable_status_led() if checked else self.master.disable_status_led()) self.set_configs([(0, None, [self.status_led_action])]) else: self.status_led_action = None reset = QAction('Reset', self) reset.triggered.connect(self.master.reset) self.set_actions([(0, None, [reset])]) self.extension_type_present = [ None, # None False, # Chibi False, # RS485 False, # WIFI False, # Ethernet False ] # WIFI 2.0 self.query_extensions()
def __init__(self, parent=None): QMainWindow.__init__(self, parent) self.setupUi(self) # Setting the minimum width of the setup tab ensures, that other tabs can grow # the window if more space is required, but we have a sane default for status # messages. Setting the minimum width of the main window itself would enfoce # it, even if children (i.e. tabs) need more space. self.tab_setup.setMinimumWidth(550) signal.signal(signal.SIGINT, self.exit_brickv) signal.signal(signal.SIGTERM, self.exit_brickv) self.async_thread = async_start_thread(self) title = 'Brick Viewer ' + config.BRICKV_FULL_VERSION self.setWindowTitle(title) self.delayed_update_tree_view_timer = QTimer(self) self.delayed_update_tree_view_timer.timeout.connect( self.update_tree_view) self.delayed_update_tree_view_timer.setInterval(100) self.tree_view_model_labels = ['Name', 'UID', 'Position', 'FW Version'] self.tree_view_model = QStandardItemModel(self) self.tree_view_proxy_model = DevicesProxyModel(self) self.tree_view_proxy_model.setSourceModel(self.tree_view_model) self.tree_view.setModel(self.tree_view_proxy_model) self.tree_view.activated.connect(self.item_activated) self.set_tree_view_defaults() inventory.info_changed.connect( lambda: self.delayed_update_tree_view_timer.start()) self.tab_widget.removeTab(1) # remove dummy tab self.tab_widget.setUsesScrollButtons(True) # force scroll buttons self.update_tab_button = IconButton( QIcon(load_pixmap('update-icon-normal.png')), QIcon(load_pixmap('update-icon-hover.png')), parent=self.tab_setup) self.update_tab_button.setToolTip('Updates available') self.update_tab_button.clicked.connect(self.flashing_clicked) self.update_tab_button.hide() self.name = '<unknown>' self.uid = '<unknown>' self.version = (0, 0, 0) self.disconnect_times = [] self.qtcb_enumerate.connect(self.cb_enumerate) self.qtcb_connected.connect(self.cb_connected) self.qtcb_disconnected.connect(self.cb_disconnected) self.ipcon = IPConnection() self.ipcon.register_callback(IPConnection.CALLBACK_ENUMERATE, self.qtcb_enumerate.emit) self.ipcon.register_callback(IPConnection.CALLBACK_CONNECTED, self.qtcb_connected.emit) self.ipcon.register_callback(IPConnection.CALLBACK_DISCONNECTED, self.qtcb_disconnected.emit) self.current_device_info = None self.flashing_window = None self.advanced_window = None self.data_logger_window = None self.delayed_refresh_updates_timer = QTimer(self) self.delayed_refresh_updates_timer.timeout.connect( self.delayed_refresh_updates) self.delayed_refresh_updates_timer.setInterval(100) self.reset_view() self.button_advanced.setDisabled(True) self.fw_version_fetcher = LatestFWVersionFetcher() self.fw_version_fetcher.fw_versions_avail.connect( self.fw_versions_fetched) self.fw_version_fetcher_thread = QThread(self) self.fw_version_fetcher_thread.setObjectName( "fw_version_fetcher_thread") if config.get_auto_search_for_updates(): self.enable_auto_search_for_updates() else: self.disable_auto_search_for_updates() self.tab_widget.currentChanged.connect(self.tab_changed) self.tab_widget.setMovable(True) self.tab_widget.tabBar().installEventFilter(self) self.button_connect.clicked.connect(self.connect_clicked) self.button_flashing.clicked.connect(self.flashing_clicked) self.button_advanced.clicked.connect(self.advanced_clicked) self.button_data_logger.clicked.connect(self.data_logger_clicked) self.plugin_manager = PluginManager() # host info self.host_infos = config.get_host_infos(config.HOST_INFO_COUNT) self.host_index_changing = True for host_info in self.host_infos: self.combo_host.addItem(host_info.host) self.last_host = None self.combo_host.installEventFilter(self) self.combo_host.currentIndexChanged.connect(self.host_index_changed) self.spinbox_port.setValue(self.host_infos[0].port) self.spinbox_port.valueChanged.connect(self.port_changed) self.spinbox_port.installEventFilter(self) self.checkbox_authentication.stateChanged.connect( self.authentication_state_changed) self.label_secret.hide() self.edit_secret.hide() self.edit_secret.setEchoMode(QLineEdit.Password) self.edit_secret.textEdited.connect(self.secret_changed) self.edit_secret.installEventFilter(self) self.checkbox_secret_show.hide() self.checkbox_secret_show.stateChanged.connect( self.secret_show_state_changed) self.checkbox_remember_secret.hide() self.checkbox_remember_secret.stateChanged.connect( self.remember_secret_state_changed) self.checkbox_authentication.setChecked( self.host_infos[0].use_authentication) self.edit_secret.setText(self.host_infos[0].secret) self.checkbox_remember_secret.setChecked( self.host_infos[0].remember_secret) self.host_index_changing = False # auto-reconnect self.label_auto_reconnects.hide() self.auto_reconnects = 0 # RED Session losts self.label_red_session_losts.hide() self.red_session_losts = 0 # fusion style self.check_fusion_gui_style.setChecked( config.get_use_fusion_gui_style()) self.check_fusion_gui_style.stateChanged.connect( self.gui_style_changed) self.checkbox_auto_search_for_updates.setChecked( config.get_auto_search_for_updates()) self.checkbox_auto_search_for_updates.stateChanged.connect( self.auto_search_for_updates_changed) self.button_update_pixmap_normal = load_pixmap( 'update-icon-normal.png') self.button_update_pixmap_hover = load_pixmap('update-icon-hover.png') self.last_status_message_id = ''
def __init__(self, wifi2_firmware_version, parent): QWidget.__init__(self) self.setupUi(self) self.parent = parent self.master = parent.master self.wifi2_status = None if parent.firmware_version < (2, 4, 0): # This should not be possible return self.wifi2_firmware_version = wifi2_firmware_version self.wifi_update_firmware_button.setIcon( QIcon(load_pixmap('update-icon-normal.png'))) self.wifi_update_firmware_button.clicked.connect( lambda: get_main_window().show_extension_update(parent.device_info. uid)) self.wifi_update_firmware_button.hide() self.wifi_firmware_version_label.setText( get_version_string( wifi2_firmware_version, replace_unknown='Waiting for WIFI Extension 2.0 FW Version...') ) self.general_group = [ self.wifi_port_label, self.wifi_port, self.wifi_websocket_port_label, self.wifi_websocket_port, self.wifi_website_port_label, self.wifi_website_port, self.wifi_disable_web_interface, self.wifi_phy_mode_label, self.wifi_phy_mode, self.wifi_use_auth, self.wifi_secret_label, self.wifi_secret, self.wifi_show_characters ] self.authentication_group = [ self.wifi_secret_label, self.wifi_secret, self.wifi_show_characters ] self.client_ip_group = [ self.wifi_client_ip_label, self.wifi_client_sub_label, self.wifi_client_gw_label, self.wifi_client_ip4, self.wifi_client_ip3, self.wifi_client_ip2, self.wifi_client_ip1, self.wifi_client_sub4, self.wifi_client_sub3, self.wifi_client_sub2, self.wifi_client_sub1, self.wifi_client_gw4, self.wifi_client_gw3, self.wifi_client_gw2, self.wifi_client_gw1, self.wifi_client_dot1, self.wifi_client_dot2, self.wifi_client_dot3, self.wifi_client_dot4, self.wifi_client_dot5, self.wifi_client_dot6, self.wifi_client_dot7, self.wifi_client_dot8, self.wifi_client_dot9 ] self.client_bssid_group = [ self.wifi_client_bssid_label, self.wifi_client_bssid6, self.wifi_client_bssid5, self.wifi_client_bssid4, self.wifi_client_bssid3, self.wifi_client_bssid2, self.wifi_client_bssid1, self.wifi_client_bssid_dot1, self.wifi_client_bssid_dot2, self.wifi_client_bssid_dot3, self.wifi_client_bssid_dot4, self.wifi_client_bssid_dot5 ] self.client_mac_group = [ self.wifi_client_mac_label, self.wifi_client_mac6, self.wifi_client_mac5, self.wifi_client_mac4, self.wifi_client_mac3, self.wifi_client_mac2, self.wifi_client_mac1, self.wifi_client_mac_dot1, self.wifi_client_mac_dot2, self.wifi_client_mac_dot3, self.wifi_client_mac_dot4, self.wifi_client_mac_dot5 ] self.client_enc_group = [ self.wifi_client_password_label, self.wifi_client_change_password, self.wifi_client_password, self.wifi_client_password_show ] self.ap_ip_group = [ self.wifi_ap_ip_label, self.wifi_ap_sub_label, self.wifi_ap_gw_label, self.wifi_ap_ip4, self.wifi_ap_ip3, self.wifi_ap_ip2, self.wifi_ap_ip1, self.wifi_ap_sub4, self.wifi_ap_sub3, self.wifi_ap_sub2, self.wifi_ap_sub1, self.wifi_ap_gw4, self.wifi_ap_gw3, self.wifi_ap_gw2, self.wifi_ap_gw1, self.wifi_ap_dot1, self.wifi_ap_dot2, self.wifi_ap_dot3, self.wifi_ap_dot4, self.wifi_ap_dot5, self.wifi_ap_dot6, self.wifi_ap_dot7, self.wifi_ap_dot8, self.wifi_ap_dot9 ] self.ap_mac_group = [ self.wifi_ap_mac_label, self.wifi_ap_mac6, self.wifi_ap_mac5, self.wifi_ap_mac4, self.wifi_ap_mac3, self.wifi_ap_mac2, self.wifi_ap_mac1, self.wifi_ap_mac_dot1, self.wifi_ap_mac_dot2, self.wifi_ap_mac_dot3, self.wifi_ap_mac_dot4, self.wifi_ap_mac_dot5 ] self.ap_enc_group = [ self.wifi_ap_password_label, self.wifi_ap_change_password, self.wifi_ap_password, self.wifi_ap_password_show ] self.mesh_router_enc_group = [ self.wifi_mesh_router_password_label, self.wifi_mesh_router_change_password, self.wifi_mesh_router_password, self.wifi_mesh_router_password_show ] self.mesh_root_static_ip_group = [ self.wifi_mesh_root_ip_label, self.wifi_mesh_root_sub_label, self.wifi_mesh_root_gw_label, self.wifi_mesh_root_ip1, self.wifi_mesh_root_ip2, self.wifi_mesh_root_ip3, self.wifi_mesh_root_ip4, self.wifi_mesh_root_sub1, self.wifi_mesh_root_sub2, self.wifi_mesh_root_sub3, self.wifi_mesh_root_sub4, self.wifi_mesh_root_gw1, self.wifi_mesh_root_gw2, self.wifi_mesh_root_gw3, self.wifi_mesh_root_gw4, self.wifi_mesh_dot1, self.wifi_mesh_dot2, self.wifi_mesh_dot3, self.wifi_mesh_dot4, self.wifi_mesh_dot5, self.wifi_mesh_dot6, self.wifi_mesh_dot7, self.wifi_mesh_dot8, self.wifi_mesh_dot9 ] self.mesh_router_bssid_group = [ self.wifi_mesh_router_bssid_label, self.wifi_mesh_router_bssid1, self.wifi_mesh_router_bssid2, self.wifi_mesh_router_bssid3, self.wifi_mesh_router_bssid4, self.wifi_mesh_router_bssid5, self.wifi_mesh_router_bssid6, self.wifi_mesh_colon1, self.wifi_mesh_colon2, self.wifi_mesh_colon3, self.wifi_mesh_colon4, self.wifi_mesh_colon5 ] # Enable/disable web interface self.wifi_disable_web_interface.stateChanged.connect( self.wifi_disable_web_interface_state_changed) # Passwords self.wifi_secret_show_state_changed(Qt.Unchecked) self.wifi_client_show_state_changed(Qt.Unchecked) self.wifi_mesh_router_password_show_state_change(Qt.Unchecked) self.wifi_ap_password_show_state_changed(Qt.Unchecked) self.wifi_show_characters.stateChanged.connect( self.wifi_secret_show_state_changed) self.wifi_client_password_show.stateChanged.connect( self.wifi_client_show_state_changed) self.wifi_ap_password_show.stateChanged.connect( self.wifi_ap_password_show_state_changed) self.wifi_mesh_router_password_show.stateChanged.connect( self.wifi_mesh_router_password_show_state_change) self.wifi_client_change_password.stateChanged.connect( self.wifi_client_change_password_changed) self.wifi_ap_change_password.stateChanged.connect( self.wifi_ap_change_password_changed) self.wifi_mesh_router_change_password.stateChanged.connect( self.wifi_mesh_router_change_password_changed) # Use passwords self.wifi_client_encryption_changed(1) self.wifi_ap_encryption_changed(3) self.wifi_mesh_router_encryption_changed(1) self.wifi_use_auth_state_changed(Qt.Unchecked) self.wifi_mesh_router_encryption_changed(0) self.wifi_client_encryption.currentIndexChanged.connect( self.wifi_client_encryption_changed) self.wifi_ap_encryption.currentIndexChanged.connect( self.wifi_ap_encryption_changed) self.wifi_use_auth.stateChanged.connect( self.wifi_use_auth_state_changed) self.wifi_mesh_router_encryption.currentIndexChanged.connect( self.wifi_mesh_router_encryption_changed) # MACs self.wifi_client_use_bssid_state_changed(Qt.Unchecked) self.wifi_client_use_mac_state_changed(Qt.Unchecked) self.wifi_ap_use_mac_state_changed(Qt.Unchecked) self.wifi_client_use_bssid.stateChanged.connect( self.wifi_client_use_bssid_state_changed) self.wifi_client_use_mac.stateChanged.connect( self.wifi_client_use_mac_state_changed) self.wifi_ap_use_mac.stateChanged.connect( self.wifi_ap_use_mac_state_changed) self.wifi_mesh_use_router_bssid_state_changed(Qt.Unchecked) self.wifi_mesh_router_use_bssid.stateChanged.connect( self.wifi_mesh_use_router_bssid_state_changed) # IP Configuration self.wifi_client_ip_configuration_changed(0) self.wifi_ap_ip_configuration_changed(0) self.wifi_mesh_root_ip_configuration_changed(0) self.wifi_client_ip_configuration.currentIndexChanged.connect( self.wifi_client_ip_configuration_changed) self.wifi_ap_ip_configuration.currentIndexChanged.connect( self.wifi_ap_ip_configuration_changed) self.wifi_mesh_root_ip_configuration.currentIndexChanged.connect( self.wifi_mesh_root_ip_configuration_changed) # Mode self.wifi_mode_changed(0) self.wifi_mode.currentIndexChanged.connect(self.wifi_mode_changed) # Save/Status self.wifi_save.clicked.connect(self.save_clicked) self.wifi_show_status.clicked.connect(self.show_status_clicked) self.client_enable = False self.ap_enable = False self.mesh_enable = False # Check if the master brick and WIFI extension 2 firmware versions # support mesh networking feature if self.wifi2_firmware_version >= ( 2, 1, 0) and self.parent.firmware_version >= (2, 4, 2): self.wifi_mode.addItem('Mesh') self.label_mesh_hint.hide()
def main(): try: locale.setlocale(locale.LC_ALL, '') except locale.Error: pass # ignore this as it might fail on macOS, we'll fallback to UTF-8 in that case if config.get_use_fusion_gui_style(): sys.argv += ['-style', 'fusion'] if '--error-report' in sys.argv: sys.exit(error_report_main()) # Catch all uncaught exceptions and show an error message for them. # PyQt5 does not silence exceptions in slots (as did PyQt4), so there # can be slots which try to (for example) send requests but don't wrap # them in an async call with error handling. argv = deepcopy(sys.argv) # Deep copy because QApplication (i.e. BrickViewer) constructor parses away Qt args and we want to know the style. if '--no-error-reporter' not in sys.argv: ExceptionReporter(argv) # Exceptions that happen before the event loop runs (f.e. syntax errors) kill the brickv so fast, that the error reporter thread # (which is daemonized) can not report the error before it is killed. Report them manually. try: # importing the MainWindow after creating the QApplication instance triggers this warning # # Qt WebEngine seems to be initialized from a plugin. Please set Qt::AA_ShareOpenGLContexts # using QCoreApplication::setAttribute before constructing QGuiApplication. # # do what the warnings says to avoid it QApplication.setAttribute(Qt.AA_ShareOpenGLContexts) brick_viewer = BrickViewer(sys.argv) if sys.platform == 'darwin': # workaround macOS QTBUG-61562 from brickv.mac_pasteboard_mime_fixed import MacPasteboardMimeFixed mac_pasteboard_mime_fixed = MacPasteboardMimeFixed() splash = QSplashScreen(load_pixmap('splash.png'), Qt.WindowStaysOnTopHint) splash.show() message = 'Starting Brick Viewer ' + config.BRICKV_FULL_VERSION splash.showMessage(message, Qt.AlignHCenter | Qt.AlignBottom, Qt.white) brick_viewer.processEvents() from brickv.mainwindow import MainWindow main_window = MainWindow() main_window.show() splash.finish(main_window) except: if '--no-error-reporter' in sys.argv: raise etype, value, tb = sys.exc_info() error = "".join(traceback.format_exception(etype, value, tb)) error = "The following error is fatal. Exiting now.\n\n" + error traceback.print_exception(etype, value, tb) try: splash.close() except: pass # Either sys.executable is /path/to/python, then run calls /path/to/python /path/to/main.py --error-report, # or sys.executable is brickv[.exe], then the --error-report flag ensures, that the path to main.py is ignored. subprocess.run([sys.executable, os.path.realpath(__file__), "--error-report"] + argv, input=error, universal_newlines=True) sys.exit(1) sys.exit(brick_viewer.exec_())
def __init__(self, parent): QDialog.__init__(self, parent) self._gui_logger = GUILogger("GUILogger", logging.INFO) self._gui_job = None EventLogger.add_logger(self._gui_logger) # FIXME better way to find interval and uids in tree_widget?! self.__tree_interval_tooltip = "Update interval in seconds" self.__tree_uid_tooltip = "UID cannot be empty" self.data_logger_thread = None self.tab_debug_warning = False self.device_dialog = None self.host_infos = None self.last_host = None self.host_index_changing = None self.setupUi(self) self.model_data = QStandardItemModel(self) self.model_data.setHorizontalHeaderLabels( ['Time', 'Name', 'UID', 'Var', 'Raw', 'Unit']) self.table_data.setModel(self.model_data) self.table_data.setColumnWidth(0, 160) self.table_data.setColumnWidth(1, 170) self.table_data.setColumnWidth(2, 50) self.table_data.setColumnWidth(3, 110) self.table_data.setColumnWidth(4, 70) self.table_data.setColumnWidth(5, 100) self.model_devices = QStandardItemModel(self) self.model_devices.setHorizontalHeaderLabels(['Device', 'Value']) self.tree_devices.setModel(self.model_devices) self.tree_devices.setColumnWidth(0, 300) self.widget_initialization() self.btn_start_logging.setIcon( QIcon(load_pixmap('data_logger/start-icon.png'))) timestamp = int(time.time()) self.edit_csv_file_name.setText( os.path.join(get_home_path(), 'logger_data_{0}.csv'.format(timestamp))) self.edit_log_file_name.setText( os.path.join(get_home_path(), 'logger_debug_{0}.log'.format(timestamp))) self.combo_data_time_format.addItem( utils.timestamp_to_de(timestamp) + ' (DD.MM.YYYY HH:MM:SS)', 'de') self.combo_data_time_format.addItem( utils.timestamp_to_us(timestamp) + ' (MM/DD/YYYY HH:MM:SS)', 'us') self.combo_data_time_format.addItem( utils.timestamp_to_iso(timestamp) + ' (ISO 8601)', 'iso') self.combo_data_time_format.addItem( utils.timestamp_to_unix(timestamp) + ' (Unix)', 'unix') self.combo_debug_time_format.addItem( utils.timestamp_to_de(timestamp) + ' (DD.MM.YYYY HH:MM:SS)', 'de') self.combo_debug_time_format.addItem( utils.timestamp_to_us(timestamp) + ' (MM/DD/YYYY HH:MM:SS)', 'us') self.combo_debug_time_format.addItem( utils.timestamp_to_iso(timestamp) + ' (ISO 8601)', 'iso') self.combo_debug_time_format.addItem( utils.timestamp_to_unix(timestamp) + ' (Unix)', 'unix') self.combo_log_level.addItem('Debug', 'debug') self.combo_log_level.addItem('Info', 'info') self.combo_log_level.addItem('Warning', 'warning') self.combo_log_level.addItem('Error', 'error') self.combo_log_level.addItem('Critical', 'critical') self.combo_log_level.setCurrentIndex(0) # debug self.combo_debug_level.addItem('Debug', logging.DEBUG) self.combo_debug_level.addItem('Info', logging.INFO) self.combo_debug_level.addItem('Warning', logging.WARNING) self.combo_debug_level.addItem('Error', logging.ERROR) self.combo_debug_level.addItem('Critical', logging.CRITICAL) self.combo_debug_level.setCurrentIndex(1) # info self.update_ui_state()
def __init__(self, parent=None): QMainWindow.__init__(self, parent) self.setupUi(self) # Setting the minimum width of the setup tab ensures, that other tabs can grow # the window if more space is required, but we have a sane default for status # messages. Setting the minimum width of the main window itself would enfoce # it, even if children (i.e. tabs) need more space. self.tab_setup.setMinimumWidth(550) signal.signal(signal.SIGINT, self.exit_brickv) signal.signal(signal.SIGTERM, self.exit_brickv) self.async_thread = async_start_thread(self) title = 'Brick Viewer ' + config.BRICKV_VERSION if config.INTERNAL != None: title += '~{}'.format(config.INTERNAL) self.setWindowTitle(title) self.tree_view_model_labels = ['Name', 'UID', 'Position', 'FW Version'] self.tree_view_model = QStandardItemModel(self) self.tree_view_proxy_model = DevicesProxyModel(self) self.tree_view_proxy_model.setSourceModel(self.tree_view_model) self.tree_view.setModel(self.tree_view_proxy_model) self.tree_view.activated.connect(self.item_activated) self.set_tree_view_defaults() self.tab_widget.removeTab(1) # remove dummy tab self.tab_widget.setUsesScrollButtons(True) # force scroll buttons self.update_tab_button = IconButton(QIcon(load_pixmap('update-icon-normal.png')), QIcon(load_pixmap('update-icon-hover.png')), parent=self.tab_setup) self.update_tab_button.setToolTip('Updates available') self.update_tab_button.clicked.connect(self.flashing_clicked) self.update_tab_button.hide() self.name = '<unknown>' self.uid = '<unknown>' self.version = (0, 0, 0) self.disconnect_times = [] self.qtcb_enumerate.connect(self.cb_enumerate) self.qtcb_connected.connect(self.cb_connected) self.qtcb_disconnected.connect(self.cb_disconnected) self.ipcon = IPConnection() self.ipcon.register_callback(IPConnection.CALLBACK_ENUMERATE, self.qtcb_enumerate.emit) self.ipcon.register_callback(IPConnection.CALLBACK_CONNECTED, self.qtcb_connected.emit) self.ipcon.register_callback(IPConnection.CALLBACK_DISCONNECTED, self.qtcb_disconnected.emit) self.current_device_info = None self.flashing_window = None self.advanced_window = None self.data_logger_window = None self.delayed_refresh_updates_timer = QTimer(self) self.delayed_refresh_updates_timer.timeout.connect(self.delayed_refresh_updates) self.delayed_refresh_updates_timer.setInterval(100) self.reset_view() self.button_advanced.setDisabled(True) self.fw_version_fetcher = LatestFWVersionFetcher() self.fw_version_fetcher.fw_versions_avail.connect(self.fw_versions_fetched) self.fw_version_fetcher_thread = QThread() self.fw_version_fetcher_thread.setObjectName("fw_version_fetcher_thread") if config.get_auto_search_for_updates(): self.enable_auto_search_for_updates() else: self.disable_auto_search_for_updates() self.tab_widget.currentChanged.connect(self.tab_changed) self.tab_widget.setMovable(True) self.tab_widget.tabBar().installEventFilter(self) self.button_connect.clicked.connect(self.connect_clicked) self.button_flashing.clicked.connect(self.flashing_clicked) self.button_advanced.clicked.connect(self.advanced_clicked) self.button_data_logger.clicked.connect(self.data_logger_clicked) self.plugin_manager = PluginManager() # host info self.host_infos = config.get_host_infos(config.HOST_INFO_COUNT) self.host_index_changing = True for host_info in self.host_infos: self.combo_host.addItem(host_info.host) self.last_host = None self.combo_host.installEventFilter(self) self.combo_host.currentIndexChanged.connect(self.host_index_changed) self.spinbox_port.setValue(self.host_infos[0].port) self.spinbox_port.valueChanged.connect(self.port_changed) self.spinbox_port.installEventFilter(self) self.checkbox_authentication.stateChanged.connect(self.authentication_state_changed) self.label_secret.hide() self.edit_secret.hide() self.edit_secret.setEchoMode(QLineEdit.Password) self.edit_secret.textEdited.connect(self.secret_changed) self.edit_secret.installEventFilter(self) self.checkbox_secret_show.hide() self.checkbox_secret_show.stateChanged.connect(self.secret_show_state_changed) self.checkbox_remember_secret.hide() self.checkbox_remember_secret.stateChanged.connect(self.remember_secret_state_changed) self.checkbox_authentication.setChecked(self.host_infos[0].use_authentication) self.edit_secret.setText(self.host_infos[0].secret) self.checkbox_remember_secret.setChecked(self.host_infos[0].remember_secret) self.host_index_changing = False # auto-reconnect self.label_auto_reconnects.hide() self.auto_reconnects = 0 # RED Session losts self.label_red_session_losts.hide() self.red_session_losts = 0 # fusion style self.check_fusion_gui_style.setChecked(config.get_use_fusion_gui_style()) self.check_fusion_gui_style.stateChanged.connect(self.gui_style_changed) self.checkbox_auto_search_for_updates.setChecked(config.get_auto_search_for_updates()) self.checkbox_auto_search_for_updates.stateChanged.connect(self.auto_search_for_updates_changed) self.button_update_pixmap_normal = load_pixmap('update-icon-normal.png') self.button_update_pixmap_hover = load_pixmap('update-icon-hover.png') self.last_status_message_id = '' infos.get_infos_changed_signal().connect(self.update_red_brick_version)
def __init__(self, *args, **kwargs): QApplication.__init__(self, *args, **kwargs) self.object_creator_signal.connect(self.object_creator_slot) self.setWindowIcon(QIcon(load_pixmap('brickv-icon.png')))
def main(): try: locale.setlocale(locale.LC_ALL, '') except locale.Error: pass # ignore this as it might fail on macOS, we'll fallback to UTF-8 in that case if config.get_use_fusion_gui_style(): sys.argv += ['-style', 'fusion'] if '--error-report' in sys.argv: sys.exit(error_report_main()) # Catch all uncaught exceptions and show an error message for them. # PyQt5 does not silence exceptions in slots (as did PyQt4), so there # can be slots which try to (for example) send requests but don't wrap # them in an async call with error handling. argv = deepcopy(sys.argv) # Deep copy because QApplication (i.e. BrickViewer) constructor parses away Qt args and we want to know the style. if '--no-error-reporter' not in sys.argv: ExceptionReporter(argv) # Exceptions that happen before the event loop runs (f.e. syntax errors) kill the brickv so fast, that the error reporter thread # (which is daemonized) can not report the error before it is killed. Report them manually. try: # importing the MainWindow after creating the QApplication instance triggers this warning # # Qt WebEngine seems to be initialized from a plugin. Please set Qt::AA_ShareOpenGLContexts # using QCoreApplication::setAttribute before constructing QGuiApplication. # # do what the warnings says to avoid it QApplication.setAttribute(Qt.AA_ShareOpenGLContexts) brick_viewer = BrickViewer(sys.argv) if sys.platform == 'darwin': # workaround macOS QTBUG-61562 from brickv.mac_pasteboard_mime_fixed import MacPasteboardMimeFixed mac_pasteboard_mime_fixed = MacPasteboardMimeFixed() splash = QSplashScreen(load_pixmap('splash.png'), Qt.WindowStaysOnTopHint) splash.show() message = 'Starting Brick Viewer ' + config.BRICKV_VERSION if config.INTERNAL != None: message += '~{}'.format(config.INTERNAL) splash.showMessage(message, Qt.AlignHCenter | Qt.AlignBottom, Qt.white) brick_viewer.processEvents() from brickv.mainwindow import MainWindow main_window = MainWindow() main_window.show() splash.finish(main_window) except: if '--no-error-reporter' in sys.argv: raise etype, value, tb = sys.exc_info() error = "".join(traceback.format_exception(etype, value, tb)) error = "The following error is fatal. Exiting now.\n\n" + error traceback.print_exception(etype, value, tb) try: splash.close() except: pass # Either sys.executable is /path/to/python, then run calls /path/to/python /path/to/main.py --error-report, # or sys.executable is brickv[.exe], then the --error-report flag ensures, that the path to main.py is ignored. subprocess.run([sys.executable, os.path.realpath(__file__), "--error-report"] + argv, input=error, universal_newlines=True) sys.exit(1) sys.exit(brick_viewer.exec_())
def error_report_main(): error_message = sys.stdin.read() if len(error_message) == 0: # FIXME: for some unknown reason it can happen that stdin is empty label_suffix = '' error_message = 'An unknown error occurred!' elif '!!!' in error_message: label_suffix, error_message = error_message.split('!!!') formatted_error_message = "<pre>{}</pre>".format( html.escape(error_message).replace("\n", "<br>")) app = QApplication(sys.argv) if sys.platform == 'darwin': # workaround macOS QTBUG-61562 from brickv.mac_pasteboard_mime_fixed import MacPasteboardMimeFixed mac_pasteboard_mime_fixed = MacPasteboardMimeFixed() window = ErrorReporter() window.setupUi(window) window.setWindowTitle('Error - Brick Viewer ' + config.BRICKV_VERSION) window.setWindowIcon(QIcon(load_pixmap('brickv-icon.png'))) mail_url = 'mailto:[email protected]?subject=Brickv Error Report&body=PLEASE ALSO DESCRIBE WHAT YOU TRIED TO DO AT THE TIME THE ERROR OCCURRED.{}'.format( urllib.parse.quote("\n\n" + error_message)) title = "<b>Please report this error to <a href='{}'>[email protected]</a>.<b>".format( mail_url) description = "You can either save the report to a text file by clicking the <b>Save</b> button below and email the file to us or you can click the <b>Email</b> button below to prepopulate an email in your email program.<br><br>" + \ "Please also describe what you tried to do at the time the error occurred.<br/><br/>" + \ "If you know what caused the error and could work around it, please tell us anyway. This allows us to improve the robustness of Brick Viewer.{}".format(label_suffix) window.label_title.setText(title) window.label_description.setText(description) def save(): date = datetime.datetime.now().replace( microsecond=0).isoformat().replace('T', '_').replace(':', '-') filename = get_save_file_name( window, 'Save Report To File', os.path.join(get_home_path(), 'brickv_error_report_{}.txt'.format(date))) if len(filename) == 0: return try: with open(filename, 'w') as f: f.write(error_message) except Exception as e: QMessageBox.critical(window, 'Save Report To File', 'Could not save report to file:\n\n' + str(e), QMessageBox.Ok) window.button_save.clicked.connect(save) window.button_email.clicked.connect( lambda: QDesktopServices.openUrl(QUrl(mail_url))) window.text_error.setHtml(formatted_error_message) window.check_show_again.setChecked(True) window.button_close.clicked.connect( lambda event: app.exit(int(window.check_show_again.isChecked()))) def close_and_exit(): app.exit(int(window.check_show_again.isChecked()) + 2) window.button_close_and_exit.clicked.connect( lambda event: close_and_exit()) window.setMinimumSize(640, 400) window.resize(800, 800) window.show() return app.exec_()