def pixel_ratio(): """Get the pixel ratio.""" from mne.viz.backends.tests._utils import (has_mayavi, has_pyvista, has_pyqt5) if not (has_mayavi() or has_pyvista()) or not has_pyqt5(): return 1. from PyQt5.QtWidgets import QApplication, QMainWindow _ = QApplication.instance() or QApplication([]) window = QMainWindow() ratio = float(window.devicePixelRatio()) window.close() return ratio
class ventanaPrincipal(QMainWindow): def __init__(self, parent=None): super().__init__(parent) self.mainWidget = App(self) self.mainWidget.llenaDiccionario() self.setCentralWidget(self.mainWidget) self.setFixedSize(1190, 670) menubar = QMenuBar() fileMenu = menubar.addMenu('Opciones') impMenu = QAction('Cargar Archivo', self) fileMenu.addAction(impMenu) impMenu.triggered.connect(self.abrirVentana) self.setMenuBar(menubar) qtRectangle = self.frameGeometry() centerPoint = QDesktopWidget().availableGeometry().center() qtRectangle.moveCenter(centerPoint) self.move(qtRectangle.topLeft()) menubar.setStyleSheet("font-size: 13px;font-weight: bold;selection-background-color: #c2185b") fileMenu.setStyleSheet("font-size: 13px;font-weight: bold;") def abrirVentana(self): self.vencar2 = QMainWindow() self.vencar2.setWindowTitle("Direccion carga") buttonY = QPushButton('Ok') labelY = QLabel() labelY.setText('Direccion de Carga: ') self.cajaY = QLineEdit() widY = QWidget() self.cajaY.setText("0000") self.cajaY.alignment() self.cajaY.setInputMask(">HHHH") layY = QBoxLayout(3) layY.addWidget(buttonY) layY.addWidget(self.cajaY) layY.addWidget(labelY) widY.setLayout(layY) self.vencar2.setCentralWidget(widY) buttonY.pressed.connect(self.obtenArchivo) self.vencar2.setStyleSheet("background-color: #90caf9") labelY.setStyleSheet("font-size: 13px;font-weight: bold") self.cajaY.setStyleSheet("background-color: #8bc34a;padding:10px 7px;border-radius: 15px;margin: 5px;font-size: 13px;font-weight: bold") buttonY.setStyleSheet("background-color: #8bc34a;border: none; border-radius: 18px;font-size: 12px;font-weight: bold;padding:10px 7px;border-radius: 15px") self.vencar2.show() def obtenArchivo(self): self.vencar2.close() dircarga = self.cajaY.text().zfill(4) options = QFileDialog.Options() options |= QFileDialog.DontUseNativeDialog files, _ = QFileDialog.getOpenFileNames( self, "QFileDialog.getOpenFileName()", "", "hex (*.HEX)", options=options) if len(files) != 0: self.mainWidget.cargaMemoria(dircarga, files[0])
def _unittest_value_display_widget_comment(): import time from PyQt5.QtWidgets import QApplication, QMainWindow, QGroupBox app = QApplication([]) win = QMainWindow() container = QGroupBox(win) layout = QVBoxLayout() layout.addStretch(1) # noinspection PyArgumentList def let_there_be_icon(text, icon_name): s = _Comment(container) s.set_text(text) s.set_icon(icon_name) layout.addWidget(s) return s a = let_there_be_icon("Cold", "cold") b = let_there_be_icon(None, None) c = let_there_be_icon(None, "info") let_there_be_icon("No icon", None) let_there_be_icon("Fire", "fire") let_there_be_icon("Error", "error") let_there_be_icon("Warning", "warning") let_there_be_icon("Ok", "ok") layout.addStretch(1) container.setLayout(layout) win.setCentralWidget(container) win.show() def run_a_bit(): for _ in range(1000): time.sleep(0.005) app.processEvents() run_a_bit() a.set_icon("fire") b.set_text("Text") c.set_text("New icon") c.set_icon("guru") run_a_bit() c.set_icon(None) b.set_text("Text") a.set_text("New icon") a.set_icon(None) run_a_bit() win.close()
def _unittest_icons(): import math import glob from PyQt5.QtWidgets import ( QApplication, QMainWindow, QGroupBox, QGridLayout, QLabel, QSizePolicy, ) from PyQt5.QtGui import QFont, QFontMetrics app = QApplication([]) all_icons = list( map( lambda x: os.path.splitext(os.path.basename(x))[0], glob.glob(os.path.join(get_absolute_path("view", "icons"), "*")), )) print("All icons:", len(all_icons), all_icons) grid_size = int(math.ceil(math.sqrt(len(all_icons)))) icon_size = QFontMetrics(QFont()).height() def render_icon(name: str, row: int, col: int): icon = get_icon(name) icon_label = QLabel() icon_label.setAlignment(Qt.AlignCenter) icon_label.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding) icon_label.setPixmap(icon.pixmap(icon_size, icon_size)) layout.addWidget(icon_label, row, col) win = QMainWindow() container = QGroupBox(win) layout = QGridLayout() for idx, ic in enumerate(all_icons): render_icon(ic, idx // grid_size, idx % grid_size) container.setLayout(layout) win.setCentralWidget(container) win.show() for _ in range(1000): time.sleep(0.005) app.processEvents() win.close()
def _unittest_value_display_widget_comment(): import time from PyQt5.QtWidgets import QApplication, QMainWindow, QGroupBox app = QApplication([]) win = QMainWindow() container = QGroupBox(win) layout = QVBoxLayout() layout.addStretch(1) # noinspection PyArgumentList def let_there_be_icon(text, icon_name): s = _Comment(container) s.set_text(text) s.set_icon(icon_name) layout.addWidget(s) return s a = let_there_be_icon('Cold', 'cold') b = let_there_be_icon(None, None) c = let_there_be_icon(None, 'info') let_there_be_icon('No icon', None) let_there_be_icon('Fire', 'fire') let_there_be_icon('Error', 'error') let_there_be_icon('Warning', 'warning') let_there_be_icon('Ok', 'ok') layout.addStretch(1) container.setLayout(layout) win.setCentralWidget(container) win.show() def run_a_bit(): for _ in range(1000): time.sleep(0.005) app.processEvents() run_a_bit() a.set_icon('fire') b.set_text('Text') c.set_text('New icon') c.set_icon('guru') run_a_bit() c.set_icon(None) b.set_text('Text') a.set_text('New icon') a.set_icon(None) run_a_bit() win.close()
def _unittest_monitored_quantity_presenter(): import time from PyQt5.QtWidgets import QApplication, QMainWindow, QGroupBox, QHBoxLayout app = QApplication([]) win = QMainWindow() container = QGroupBox(win) layout = QHBoxLayout() a = ValueDisplayWidget( container, "Raskolnikov", "N/A", tooltip="This is Rodion", with_comment=True ) layout.addWidget(a) container.setLayout(layout) win.setCentralWidget(container) win.show() mqp = MonitoredQuantityPresenter( a, "%.1f \u00B0C", params_default=MonitoredQuantityPresenter.DisplayParameters( comment="OK", icon_name="ok" ), params_when_low=MonitoredQuantityPresenter.DisplayParameters( comment="Cold", icon_name="cold" ), params_when_high=MonitoredQuantityPresenter.DisplayParameters( comment="Hot", icon_name="fire" ), ) def run_a_bit(): for _ in range(1000): time.sleep(0.005) app.processEvents() run_a_bit() mqp.display(MonitoredQuantity(123.456, MonitoredQuantity.Alert.NONE)) run_a_bit() mqp.display(MonitoredQuantity(123456, MonitoredQuantity.Alert.TOO_HIGH)) run_a_bit() mqp.display(MonitoredQuantity(-123.456, MonitoredQuantity.Alert.TOO_LOW)) run_a_bit() win.close()
class UpdaterUI(object): def __init__(self): self.window = QMainWindow() self.ui = Ui_MainWindow() self.ui.setupUi(self.window) def show(self): self.window.show() def hide(self): self.window.close() def check_for_update(self): pass def run_update(self): pass def restart_app(self): pass
def _unittest_spinbox_linked_with_slider(): import time from PyQt5.QtWidgets import QApplication, QMainWindow, QLayout from kucher.view.utils import lay_out_horizontally, lay_out_vertically app = QApplication([]) instances: typing.List[SpinboxLinkedWithSlider] = [] def make(minimum: float, maximum: float, step: float) -> QLayout: o = SpinboxLinkedWithSlider( widget, minimum=minimum, maximum=maximum, step=step, slider_orientation=SpinboxLinkedWithSlider.SliderOrientation. HORIZONTAL, ) instances.append(o) return lay_out_horizontally((o.slider, 1), o.spinbox) win = QMainWindow() widget = QWidget(win) widget.setLayout( lay_out_vertically(make(0, 100, 1), make(-10, 10, 0.01), make(-99999, 100, 100))) win.setCentralWidget(widget) win.show() def run_a_bit(): for _ in range(1000): time.sleep(0.005) app.processEvents() run_a_bit() instances[0].minimum = -1000 instances[2].step = 10 run_a_bit() win.close()
def _unittest_value_display_widget_main(): import time from PyQt5.QtWidgets import QApplication, QMainWindow, QGroupBox app = QApplication([]) win = QMainWindow() container = QGroupBox(win) layout = QVBoxLayout() a = ValueDisplayWidget(container, 'Vladimir', 'N/A', tooltip='This is Vladimir') layout.addWidget(a) b = ValueDisplayWidget(container, 'Dmitri', with_comment=True) b.set('123.4 \u00B0C', comment='Init', icon_name='info') layout.addWidget(b) container.setLayout(layout) win.setCentralWidget(container) win.show() def run_a_bit(): for _ in range(1000): time.sleep(0.005) app.processEvents() run_a_bit() b.set('12.3 \u00B0C', comment='OK', icon_name='ok') run_a_bit() b.set('123.4 \u00B0C') run_a_bit() b.set('-45.6 \u00B0C', comment='Cold', icon_name='cold') run_a_bit() win.close()
def _unittest_task_statistics_table_model(): import time from PyQt5.QtWidgets import QApplication, QMainWindow app = QApplication([]) win = QMainWindow() win.resize(800, 600) model = _TableModel(win) view = QTableView(win) view.setModel(model) view.setSortingEnabled(True) hh = QHeaderView(Qt.Horizontal, view) hh.setModel(model) hh.setVisible(True) view.setHorizontalHeader(hh) win.setCentralWidget(view) win.show() def go_go_go(): for _ in range(1000): time.sleep(0.001) app.processEvents() go_go_go() model.set_data(_make_test_data()) for _ in range(5): go_go_go() win.close()
class AnimateXY(AbstractTool): def __init__(self, parent): super(AnimateXY, self).__init__(parent) self._name = "Animate X-Y" self._parent = parent self._filename = "" self._settings = {} # --- Initialize the GUI --- # self._animateWindow = QMainWindow() self._animateGUI = Ui_Animate() self._animateGUI.setupUi(self._animateWindow) self._animateGUI.buttonBox.accepted.connect(self.callback_apply) self._animateGUI.buttonBox.rejected.connect(self._animateWindow.close) self._has_gui = True self._need_selection = True self._min_selections = 1 self._max_selections = 3 self._redraw_on_exit = False def apply_settings(self): self._settings["local"] = self._animateGUI.radioButton.isChecked() self._settings["global"] = self._animateGUI.radioButton_2.isChecked() self._settings["lim"] = float(self._animateGUI.lim.text()) self._settings["fps"] = int(self._animateGUI.fps.text()) @staticmethod def get_bunch_in_local_frame(datasource, step): x = np.array(datasource["Step#{}".format(step)]["x"]) y = np.array(datasource["Step#{}".format(step)]["y"]) x_mean = np.mean(x) y_mean = np.mean(y) px_mean = np.mean(np.array(datasource["Step#{}".format(step)]["px"])) py_mean = np.mean(np.array(datasource["Step#{}".format(step)]["py"])) theta = np.arccos(py_mean / np.sqrt(np.square(px_mean) + np.square(py_mean))) if px_mean < 0: theta = -theta # Center the beam x -= x_mean y -= y_mean # Rotate the beam and return temp_x = x temp_y = y return temp_x * np.cos(theta) - temp_y * np.sin( theta), temp_x * np.sin(theta) + temp_y * np.cos(theta) def callback_apply(self): self.apply_settings() self._animateWindow.close() self.run_animation() def run_animation(self): self._parent.send_status("Setting up animation...") plt.rc('font', **{'family': 'serif', 'serif': ['Computer Modern']}) plt.rc('text', usetex=True) plt.rc('grid', linestyle=':') animate_all = [] for dataset in self._selections: # dataset = self._selections[0] datasource = dataset.get_datasource() nsteps = dataset.get_nsteps() # TODO: Total hack, but I want to tag certain particles RIGHT NOW -DW # tag_step = 568 # tag_y_lim = 5.0 * 1.0e-3 # m # _x, _y = self.get_bunch_in_local_frame(datasource, tag_step) # tag_idx = np.where(_y >= tag_y_lim) # pids = np.array(datasource["Step#{}".format(tag_step)]["id"][tag_idx]) animate = {} for step in range(nsteps): animate["Step#{}".format(step)] = { "x": np.array(datasource["Step#{}".format(step)]["x"]), "y": np.array(datasource["Step#{}".format(step)]["y"]), "id": np.array(datasource["Step#{}".format(step)]["id"]) } if self._settings["local"]: animate["Step#{}".format(step)]["x"], animate["Step#{}".format(step)]["y"] = \ self.get_bunch_in_local_frame(datasource, step) animate_all.append(animate) n_ds = len(animate_all) # Handle animations # fig = plt.figure() fig, ax = plt.subplots(1, n_ds) if n_ds == 1: ax = [ax] lines = [] j = 0 for _ax in ax: _ax.set_xlim(-self._settings["lim"], self._settings["lim"]) _ax.set_ylim(-self._settings["lim"], self._settings["lim"]) # ax = plt.axes(xlim=(-self._settings["lim"], self._settings["lim"]), # ylim=(-self._settings["lim"], self._settings["lim"])) line1, = _ax.plot([], [], 'ko', ms=0.1, alpha=0.8) # line2, = ax.plot([], [], 'ko', ms=0.1, alpha=0.8, color='red') # Tagging lines.append(line1) # plt.grid() _ax.grid() _ax.set_aspect('equal') if self._settings["local"]: _ax.set_xlabel("Horizontal (mm)") _ax.set_ylabel("Longitudinal (mm)") else: _ax.set_xlabel("X (mm)") _ax.set_ylabel("Y (mm)") _ax.set_title(r"{}: Step \#0".format( self._selections[j].get_name())) _ax.get_xaxis().set_major_locator(LinearLocator(numticks=13)) _ax.get_yaxis().set_major_locator(LinearLocator(numticks=13)) plt.tight_layout() j += 1 def init(): for _line in lines: _line.set_data([], []) # line2.set_data([], []) return lines, # line2, def update(i): k = 0 for _animate, _line in zip(animate_all, lines): # tags = np.isin(animate["Step#{}".format(i)]["id"], pids) tags = np.zeros(len(_animate["Step#{}".format(i)]["x"]), dtype=bool) # Regular Data x = 1000.0 * _animate["Step#{}".format(i)]["x"][np.invert( tags.astype(bool))] y = 1000.0 * _animate["Step#{}".format(i)]["y"][np.invert( tags.astype(bool))] # Tagged Data xt = 1000.0 * _animate["Step#{}".format(i)]["x"][tags.astype( bool)] yt = 1000.0 * _animate["Step#{}".format(i)]["y"][tags.astype( bool)] _line.set_data(x, y) # line2.set_data(xt, yt) ax[k].set_title(r"{}: Step \#{}".format( self._selections[k].get_name(), i)) k += 1 completed = int(100 * (i / (nsteps - 1))) self._parent.send_status( "Animation progress: {}% complete".format(completed)) # return line1, line2, ax return lines, ax ani = animation.FuncAnimation(fig, update, frames=nsteps, init_func=init, repeat=False) # Save animation writer1 = animation.writers['ffmpeg'] writer2 = writer1(fps=self._settings["fps"], bitrate=1800) ani.save(self._filename[0] + ".mp4", writer=writer2) ani._stop() self._parent.send_status("Animation saved successfully!") def run(self): # --- Calculate the positions to center the window --- # screen_size = self._parent.screen_size() _x = 0.5 * (screen_size.width() - self._animateWindow.width()) _y = 0.5 * (screen_size.height() - self._animateWindow.height()) # --- Show the GUI --- # self._animateWindow.show() self._animateWindow.move(_x, _y) def open_gui(self): options = QFileDialog.Options() options |= QFileDialog.DontUseNativeDialog self._filename = QFileDialog.getSaveFileName( caption="Saving animation...", options=options, filter="Video (*.mp4)") self.run()
class GameWindow: setup_ui = Ui_GameWindow() def __init__(self, y, x, mine, min_width, min_height, max_width, max_height, size_width, size_height, main_window, level): self.count = 0 self.game_map = [] self.y = y self.x = x self.mine = mine self.mainWindow = main_window self.level = level self.field = Matrix(y, x, mine) self.win = QMainWindow() self.setup_ui.setupUi(self.win, min_width, min_height, max_width, max_height, size_width, size_height) self.win.setWindowTitle("Penguin Minesweeper") self.win.setWindowIcon(QIcon("penguin_mine_icon.png")) # Connect self.setup_ui.newGameButton.clicked.connect(self.newGame) self.setup_ui.difficultyButton.clicked.connect(self.changeDifficulty) # Fill grid layout with buttons for row in range(y): button_row = [] for col in range(x): game_button = Button(row, col, self) button_row.append(game_button) self.setup_ui.gridLayout.addWidget(game_button, row, col) self.game_map.append(button_row) def revealAnswer(self, row, col): button = self.game_map[row][col] if not button.isEnabled(): return self.count += 1 button.setText(str(self.field.matrix[row][col])) button.setStyleSheet( "background-color: #e9e3f4; color: black; font-weight: bold; font-size: 20px" ) button.setEnabled(False) if self.count == (self.y * self.x) - self.mine: end = QMessageBox.question(self.win, "Game Over", "Do you want to play again?", QMessageBox.Yes, QMessageBox.No) if end == QMessageBox.No: self.win.close() if end == QMessageBox.Yes: self.newGame() if self.field.matrix[row][col] == 0: button.setStyleSheet("background-color: #c5d5ea") if self.field.matrix[row][col] == 0: button.setText(" ") if row < self.y - 1: self.revealAnswer(row + 1, col) if row > 0: self.revealAnswer(row - 1, col) if col < self.x - 1: self.revealAnswer(row, col + 1) if col > 0: self.revealAnswer(row, col - 1) if row < self.y - 1 and col < self.x - 1: self.revealAnswer(row + 1, col + 1) if row > 0 and col > 0: self.revealAnswer(row - 1, col - 1) if row < self.y - 1 and col > 0: self.revealAnswer(row + 1, col - 1) if row > 0 and col < self.x - 1: self.revealAnswer(row - 1, col + 1) if self.field.matrix[row][col] == "X": self.makeIcon(row, col) def actionButtonClick(self, target): row = target.row col = target.column self.revealAnswer(row, col) def show(self): self.win.show() def newGame(self): self.field = Matrix(self.y, self.x, self.mine) self.count = 0 for i in range(self.y): for j in range(self.x): button = self.game_map[i][j] button.setText(" ") button.setStyleSheet("background-color: #4e4f59") button.setSizePolicy( QSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)) button.setIcon(QIcon("")) button.setEnabled(True) def changeDifficulty(self): self.mainWindow.show() self.win.close() def makeIcon(self, row, col): self.button = self.game_map[row][col] self.button.setText(" ") self.size = self.setSize() self.pixmap_red = QPixmap("penguin_red_icon.png") self.pixmap_blue = QPixmap("penguin_blue_icon.png") self.icon_red = QIcon() self.icon_red.addPixmap(self.pixmap_red, QIcon.Disabled, QIcon.Off) self.icon_blue = QIcon() self.icon_blue.addPixmap(self.pixmap_blue, QIcon.Disabled, QIcon.On) for i in range(self.y): for j in range(self.x): buttons = self.game_map[i][j] if self.field.matrix[i][j] == "X": buttons.setText(" ") buttons.setIcon(self.icon_blue) buttons.setIconSize(self.size) buttons.setEnabled(False) self.button.setIcon(self.icon_red) def setSize(self): if self.level == "easy": self.size = QSize(30, 30) if self.level == "mid": self.size = QSize(24, 24) if self.level == "hard": self.size = QSize(22, 22) if self.level == "custom": width_size = 38 - self.y height_size = 38 - self.x self.size = QSize(width_size, height_size) return self.size
class BrowserWindow(object): def __init__(self, configs: dict): self._configs = {**g_default_configs, **configs} self._menus = [] self._actions = [] self._setup_ui() def _setup_ui(self) -> NoReturn: self._setup_main_window() self._setup_menus() self._setup_status_bar() self._setup_web_engine_view() self._setup_shortcut_keys() def _setup_main_window(self) -> NoReturn: self._main_window = QMainWindow() if self._configs['frameless']: self._main_window.setWindowFlags(QtCore.Qt.FramelessWindowHint) self._widget_ui = Ui_WebViewWindowUI() self._widget_ui.setupUi(self._main_window) self._main_window.setWindowTitle(self._configs['title']) if self._configs['width'] != -1 and self._configs['height'] != -1: self._main_window.resize(self._configs['width'], self._configs['height']) def get_main_window(self): return self._main_window def _setup_menus(self) -> NoReturn: app_menu = self._configs['menu'] if app_menu: menubar = self._widget_ui.menubar qt_menu = QtWidgets.QMenu(menubar) qt_menu.setObjectName("test menu") qt_menu.setTitle("test menu") for menu in app_menu.children(): qt_menu = QtWidgets.QMenu(menubar) qt_menu.setObjectName(menu.title) qt_menu.setTitle(menu.title) menubar.addAction(qt_menu.menuAction()) self._menus.append(qt_menu) for sub_menu in menu.children(): if sub_menu.on_click: qt_action = QtWidgets.QAction(self._main_window) qt_action.setObjectName(sub_menu.title) qt_action.setText(sub_menu.title) qt_action.triggered.connect(sub_menu.on_click) self._actions.append(qt_action) qt_menu.addAction(qt_action) elif type(sub_menu) == MenuSeparator: qt_menu.addSeparator() self._main_window.setMenuBar(menubar) else: self._main_window.setMenuBar(None) def _find_action(self, title): for action in self._actions: print("menu loop", action.objectName()) if action.objectName() == title: return action return None def set_menu_visible(self, menu_title, visible): action = self._find_action(menu_title) if action: action.setVisible(visible) def _setup_status_bar(self) -> NoReturn: if not self._configs['statusbar']: self._main_window.setStatusBar(None) def _setup_web_engine_view(self) -> NoReturn: self.webview = WebView(self._main_window, "webEngineView", self._configs['dev_mode']) self._widget_ui.verticalLayout.addWidget(self.webview.get_widget_view()) if self._configs['dev_mode']: self._devtools_web_view = WebView(self._main_window, "webDevEngineView", False) self._widget_ui.verticalLayout_3.addWidget(self._devtools_web_view.get_widget_view()) self.webview.set_web_dev_tools_page(self._devtools_web_view.get_web_engine_view_page()) # bind webEngineView with devTools self._widget_ui.consoleLogDockWidget.setVisible(True) else: self._widget_ui.consoleLogDockWidget.setVisible(False) def _setup_shortcut_keys(self): self._shortcut_refresh = QShortcut(QKeySequence('Ctrl+R'), self._main_window) self._shortcut_refresh.activated.connect(self._on_refresh_shortcut_key_pressed) self._shortcut_refresh2 = QShortcut(QKeySequence('F5'), self._main_window) self._shortcut_refresh2.activated.connect(self._on_refresh_shortcut_key_pressed) self._shortcut_fullscreen = QShortcut(QKeySequence('F11'), self._main_window) self._shortcut_fullscreen.activated.connect(self._on_fullscreen_shortcut_key_pressed) self._shortcut_devtools = QShortcut(QKeySequence('F12'), self._main_window) self._shortcut_devtools.activated.connect(self._on_devtools_shortcut_key_pressed) def _on_refresh_shortcut_key_pressed(self): self.webview.reload() def _on_devtools_shortcut_key_pressed(self): if self._widget_ui.consoleLogDockWidget.isVisible(): self._widget_ui.consoleLogDockWidget.hide() else: self._widget_ui.consoleLogDockWidget.show() def _on_fullscreen_shortcut_key_pressed(self): if self._main_window.isFullScreen(): self._main_window.showNormal() else: self._main_window.showFullScreen() def show(self) -> NoReturn: if self._configs['width'] != -1 and self._configs['height'] != -1: self._main_window.show() else: self._main_window.showMaximized() def show_maximized(self) -> NoReturn: self._main_window.showMaximized() def show_minimized(self) -> NoReturn: self._main_window.showMinimized() def show_normal(self) -> NoReturn: self._main_window.showNormal() def show_full_screen(self) -> NoReturn: self._main_window.showFullScreen() def is_maximized(self) -> bool: return self._main_window.windowState() == QtCore.Qt.WindowMaximized def is_full_screen(self) -> bool: return self._main_window.windowState() == QtCore.Qt.WindowFullScreen def move(self, x, y): self._main_window.move(x, y) def move_by(self, dx, dy): cur_pos: QPoint = self._main_window.pos() self._main_window.move(cur_pos.x() + dx, cur_pos.y() + dy) def close(self) -> NoReturn: if self.webview: self.webview.destroy() self._main_window.close() def show_alert_dialog(self, title: str, msg: str, cancelable: bool = True) -> bool: message_box = QMessageBox() message_box.setWindowTitle(title) message_box.setIcon(QMessageBox.Question) message_box.setText(msg) message_box.setStandardButtons((QMessageBox.Yes | QMessageBox.Cancel) if cancelable else QMessageBox.Yes) result = message_box.exec() return result == QMessageBox.Yes def show_file_dialog_for_save_file(self, filename: str, msg: str, filter: str) -> list: options = QFileDialog.Options() files = QFileDialog.getSaveFileName(None, msg, filename, filter=filter, options=options) return files def show_file_dialog_for_file(self, title: str, filter: str) -> list: options = QFileDialog.Options() files, _ = QFileDialog.getOpenFileNames(None, title, directory=QDir.homePath(), filter=filter, options=options) return files def show_file_dialog_for_dir(self, title: str) -> str: options = QFileDialog.Options() choose_dir = QFileDialog.getExistingDirectory(None, title, directory=QDir.homePath(), options=options) return choose_dir
class CoordinatorCanvasTest(CoordinatorTestCase): def setUp(self): super().setUp() global CANVAS, IFACE QGIS_APP, IFACE, CANVAS = get_qgis_app() if isinstance(IFACE, QgisStubInterface): self.window = QMainWindow() self.window.resize(QSize(800, 400)) self.window.setCentralWidget(CANVAS) else: self.window = None # try to get the current instance of coordinator: try: self.coordinator = qgis.utils.plugins['coordinator'] except KeyError: self.coordinator = Coordinator(IFACE, self.window) self.pluginWasOpen = self.coordinator.pluginIsActive if not self.coordinator.pluginIsActive: self.coordinator.run() self.coordinator.reset() self.coordinator.captureCoordsButtonToggled(False) self.dw = self.coordinator.dockwidget if self.window: self.window.show() self.addEuropeLayer() QTest.qWait(50) def clickCanvasCoordinate(self, coordinatePointXY): mapToPixel = CANVAS.getCoordinateTransform() testPositionPixels = mapToPixel.transform(coordinatePointXY) QTest.mouseClick(CANVAS.viewport(), Qt.LeftButton, pos=testPositionPixels.toQPointF().toPoint()) def tearDown(self): super().tearDown() self.project.clear() if not self.pluginWasOpen: self.dw.close() else: self.coordinator.reset() QTest.qWait(200) try: self.window.close() except: pass def testMarkerGeographicOnGeodesic(self): CANVAS.setDestinationCrs(QgsCoordinateReferenceSystem("EPSG:32632")) QTest.qWait(100) CANVAS.zoomToFeatureExtent( QgsRectangle(150000, 4800000, 850000, 5500000)) QTest.qWait(100) QTest.mouseClick(self.dw.inputAsDec, Qt.LeftButton) marker = self.coordinator.marker mapToPixel = CANVAS.getCoordinateTransform() # set point to 8°E but 0°N QTest.keyClicks(self.dw.inLeftDec, "8") QTest.qWait(1000) # check non visible self.assertFalse(CANVAS.sceneRect().contains(marker.scenePos())) self.assertTrue(self.dw.messageIcon.isVisible()) # add 45°N QTest.keyClicks(self.dw.inRightDec, "45") QTest.qWait(200) # now point should be visible self.assertTrue(CANVAS.sceneRect().contains(marker.scenePos())) self.assertFalse(self.dw.messageIcon.isVisible()) # check the actual position on the map coords = mapToPixel.toMapCoordinates(marker.pos().x(), marker.pos().y()) expectedPixelPos = mapToPixel.transform(QgsPointXY(421184, 4983436)) self.assertAlmostEqual(expectedPixelPos.x(), marker.pos().x(), 0) self.assertAlmostEqual(expectedPixelPos.y(), marker.pos().y(), 0) # remove latitude coordinates QTest.mouseDClick(self.dw.inRightDec, Qt.LeftButton) QTest.keyClick(self.dw.inRightDec, Qt.Key_Delete) QTest.qWait(200) self.assertFalse(CANVAS.sceneRect().contains(marker.scenePos())) self.assertTrue(self.dw.messageIcon.isVisible()) # set 80°N QTest.keyClicks(self.dw.inRightDec, "80") QTest.qWait(200) # check non visible self.assertFalse(CANVAS.sceneRect().contains(marker.scenePos())) self.assertTrue(self.dw.messageIcon.isVisible()) # clear input and set coordinates on western hemisphere but with correct Latitude QTest.mouseClick(self.dw.clearInput, Qt.LeftButton) QTest.mouseClick(self.dw.leftDirButton, Qt.LeftButton) QTest.keyClicks(self.dw.inLeftDec, "8") QTest.keyClicks(self.dw.inRightDec, "45") # check non visible self.assertFalse(CANVAS.sceneRect().contains(marker.scenePos())) self.assertTrue(self.dw.messageIcon.isVisible()) def testCaptureWest4326(self): CANVAS.setDestinationCrs(QgsCoordinateReferenceSystem("EPSG:4326")) #self.dw.setMinimumWidth(self.dw.width() + 50) QTest.qWait(100) CANVAS.zoomToFeatureExtent(QgsRectangle(-99.7, 70.3, -99.3, 70.7)) QTest.qWait(100) QTest.mouseClick(self.dw.captureCoordButton, Qt.LeftButton) QTest.qWait(100) testPosition = QgsPointXY(-99.5, 70.5) self.clickCanvasCoordinate(testPosition) QTest.qWait(100) # recalculate and click again, because the GUI might have moved a bit: self.clickCanvasCoordinate(testPosition) QTest.qWait(100) self.assertEqual("99", self.dw.inLeft.text()) self.assertTextFieldBetween(28, 31, self.dw.inLeftMin) #self.assertEqual(helperFormatCoordinates("0.00"), self.dw.inLeftSec.text()) self.assertEqual("W", self.dw.leftDirButton.text()) self.assertEqual("70", self.dw.inRight.text()) self.assertTextFieldBetween(28, 31, self.dw.inRightMin) #self.assertEqual(helperFormatCoordinates("0.00"), self.dw.inRightSec.text()) self.assertEqual("N", self.dw.rightDirButton.text()) QTest.mouseClick(self.dw.inputAsDec, Qt.LeftButton) self.assertAlmostEqual(99.5, QLocale().toFloat(self.dw.inLeftDec.text())[0], places=2) self.assertEqual("W", self.dw.leftDirButton.text()) self.assertAlmostEqual(70.5, QLocale().toFloat(self.dw.inRightDec.text())[0], places=2) self.assertEqual("N", self.dw.rightDirButton.text()) # repeat test while in decimal mode: self.clickCanvasCoordinate(testPosition) QTest.qWait(100) self.assertAlmostEqual(99.5, QLocale().toFloat(self.dw.inLeftDec.text())[0], places=2) self.assertEqual("W", self.dw.leftDirButton.text()) self.assertAlmostEqual(70.5, QLocale().toFloat(self.dw.inRightDec.text())[0], places=2) self.assertEqual("N", self.dw.rightDirButton.text()) def testMapToolChange(self): if isinstance(IFACE, QgisStubInterface): advDigitizeWidget = QgsAdvancedDigitizingDockWidget(CANVAS, CANVAS) if (version.parse(QtCore.qVersion()) < version.parse("5.11.0")): toolMode = QgsMapToolCapture.CaptureLine else: toolMode = QgsMapToolCapture.CaptureMode.CaptureLine captureMapTool = QgsMapToolCapture(CANVAS, advDigitizeWidget, toolMode) self.coordinator.reset() CANVAS.setMapTool(QgsMapToolPan(CANVAS)) self.assertFalse(self.dw.addFeatureButton.isEnabled()) QTest.keyClicks(self.dw.inLeft, "8") self.assertFalse(self.dw.addFeatureButton.isEnabled()) CANVAS.setMapTool(captureMapTool) self.assertTrue(self.dw.addFeatureButton.isEnabled()) CANVAS.setMapTool(QgsMapToolPan(CANVAS)) self.assertFalse(self.dw.addFeatureButton.isEnabled()) self.coordinator.reset() self.assertFalse(self.dw.addFeatureButton.isEnabled()) CANVAS.setMapTool(captureMapTool) # add Feature Button should not be enabled when there is no input self.assertFalse(self.dw.addFeatureButton.isEnabled()) else: self.skipTest("not yet implemented for QGIS GUI tests") def testGeodeticNegative(self): """[GITHUB #12] Negative Values in Geodetic CRS""" crsIn = QgsCoordinateReferenceSystem("EPSG:31254") self.coordinator.setInputCrs(crsIn) CANVAS.setDestinationCrs(crsIn) QTest.qWait(100) CANVAS.zoomToFeatureExtent(QgsRectangle(-80000, 200000, 80000, 250000)) QTest.qWait(100) QTest.mouseClick(self.dw.captureCoordButton, Qt.LeftButton) QTest.qWait(100) testPosition = QgsPointXY(50000, 230000) self.clickCanvasCoordinate(testPosition) QTest.qWait(500) self.assertTextFieldCloseTo(230000, self.dw.inRightDec, 300) self.assertTextFieldCloseTo(50000, self.dw.inLeftDec, 300) testPosition = QgsPointXY(-50000, 230000) self.clickCanvasCoordinate(testPosition) QTest.qWait(500) self.assertTextFieldCloseTo(230000, self.dw.inRightDec, 300) self.assertTextFieldCloseTo(-50000, self.dw.inLeftDec, 300)
def _unittest_register_tree_model(): import gc from PyQt5.QtWidgets import ( QApplication, QMainWindow, QTreeView, QHeaderView, QStyleOptionViewItem, ) from ._mock_registers import get_mock_registers from .editor_delegate import EditorDelegate from .style_option_modifying_delegate import StyleOptionModifyingDelegate app = QApplication([]) win = QMainWindow() tw = QTreeView(win) tw.setItemDelegate(EditorDelegate(tw, lambda s: print("Editor display:", s))) tw.setItemDelegateForColumn( 0, StyleOptionModifyingDelegate( tw, decoration_position=QStyleOptionViewItem.Right ), ) tw.setStyleSheet( """ QTreeView::item { padding: 0 5px; } """ ) header: QHeaderView = tw.header() header.setSectionResizeMode(QHeaderView.ResizeToContents) header.setStretchLastSection( False ) # Horizontal scroll bar doesn't work if this is enabled registers = get_mock_registers() for r in registers: assert r.update_event.num_handlers == 0 model = Model(win, registers) tw.setModel(model) for r in registers: assert r.update_event.num_handlers == 1 win.setCentralWidget(tw) win.show() good_night_sweet_prince = False async def run_events(): while not good_night_sweet_prince: app.processEvents() await asyncio.sleep(0.01) async def walk(): nonlocal good_night_sweet_prince await asyncio.sleep(5) good_night_sweet_prince = True asyncio.get_event_loop().run_until_complete(asyncio.gather(run_events(), walk())) win.close() # At the very end, making sure that our registers do not keep the model alive via weak callback references del tw del win del app gc.collect() print("Model references:", gc.get_referrers(model)) del model gc.collect() for r in registers: assert r.update_event.num_handlers == 1 r.update_event.emit(r) assert r.update_event.num_handlers == 0
def roi_visualiser(self, roi_field): # Start the stack visualiser and ensure that it uses the ROI from here in the rest of this try: images = self.presenter.stack.presenter.get_image( self.presenter.model.preview_image_idx) except Exception: # Happens if nothing has been loaded, so do nothing as nothing can't be visualised return window = QMainWindow(self) window.setWindowTitle("Select ROI") window.setMinimumHeight(600) window.setMinimumWidth(600) self.roi_view = MIImageView(window) window.setCentralWidget(self.roi_view) self.roi_view.setWindowTitle("Select ROI for operation") def set_averaged_image(): averaged_images = np.sum( self.presenter.stack.presenter.images.data, axis=0) self.roi_view.setImage( averaged_images.reshape( (1, averaged_images.shape[0], averaged_images.shape[1]))) self.roi_view_averaged = True def toggle_average_images(images_): if self.roi_view_averaged: self.roi_view.setImage(images_.data) self.roi_view_averaged = False else: set_averaged_image() self.roi_view.roi.show() self.roi_view.ui.roiPlot.hide() # Add context menu bits: menu = QMenu(self.roi_view) toggle_show_averaged_image = QAction("Toggle show averaged image", menu) toggle_show_averaged_image.triggered.connect( lambda: toggle_average_images(images)) menu.addAction(toggle_show_averaged_image) menu.addSeparator() self.roi_view.imageItem.menu = menu set_averaged_image() def roi_changed_callback(callback): roi_field.setText(callback.to_list_string()) roi_field.editingFinished.emit() self.roi_view.roi_changed_callback = lambda callback: roi_changed_callback( callback) # prep the MIImageView to display in this context self.roi_view.ui.roiBtn.hide() self.roi_view.ui.histogram.hide() self.roi_view.ui.menuBtn.hide() self.roi_view.ui.roiPlot.hide() self.roi_view.roi.show() self.roi_view.ui.gridLayout.setRowStretch(1, 5) self.roi_view.ui.gridLayout.setRowStretch(0, 95) self.roi_view.button_stack_right.hide() self.roi_view.button_stack_left.hide() button = QPushButton("OK", window) button.clicked.connect(lambda: window.close()) self.roi_view.ui.gridLayout.addWidget(button) window.show()
def exit(self) -> None: # log.debug("LogWindow: exit") self.may_close = True # closed = QMainWindow.close(self) # log.debug("closed: {}".format(closed)) QMainWindow.close(self)
def run(self): QMainWindow.close(self)
class GameWindow: game_ui = Ui_MainWindow() player_map = [] ai_map = [] def __init__(self, player_map): self.win = QMainWindow() self.game_ui.setupUi(self.win) self.win.setWindowTitle("Battleship Game") # Set player map self.player_map = player_map # Generate AI Map and add cells to the grid pane for row in range(10): ai_map_row = [] for column in range(10): # Create AI cell aiButton = Cell(row, column, self) ai_map_row.append(aiButton) self.game_ui.aiGrid.addWidget(aiButton, row, column) # Get player cell from player map playerButton = player_map[row][column] playerButton.setNeutral() self.game_ui.playerGrid.addWidget(playerButton, row, column) self.ai_map.append(ai_map_row) # Init game self.game = BattleShipGame(self.player_map, self.ai_map) # Init AI self.ai = BattleshipAI(self.game) self.ai.placeShips() # Triggered when a cell on a AI Map clicked by player def actionCellClick(self, target_cell): # Get target location row = target_cell.row column = target_cell.column print(self.game.current_player, " makes a shot to: ", row, column) # Shot a cell on game object hit_ship = self.game.shotACell(row, column) if hit_ship: # Hit a ship print("Player shot a ", hit_ship) # Change cell color style target_cell.setHit() # Update remaining ships panel self.updateShipPanel() # Check if game is over self.isGameOver() else: print("Player missed") target_cell.setMiss() # If player missed shot, current player is set to the ai # AI makes shot if self.game.current_player == "ai": self.ai.aiShot() self.updateShipPanel() self.isGameOver() def isGameOver(self): # Check if all ships are sank for any player if len(self.game.player_ships) == 0: reply = QMessageBox.warning(self.win, "Error", "AI Won the game!", QMessageBox.Ok) if reply == QMessageBox.Ok: self.win.close() elif len(self.game.ai_ships) == 0: reply = QMessageBox.warning(self.win, "Error", "Player Won the game!", QMessageBox.Ok) if reply == QMessageBox.Ok: self.win.close() # Disable the sank ship images def updateShipPanel(self): p_ships = self.game.player_ships.keys() a_ships = self.game.ai_ships.keys() if "carrier" not in p_ships: self.game_ui.playerCarrier.setEnabled(False) if "battleship" not in p_ships: self.game_ui.playerBattleship.setEnabled(False) if "cruiser" not in p_ships: self.game_ui.playerCruiser.setEnabled(False) if "submarine" not in p_ships: self.game_ui.playerSubmarine.setEnabled(False) if "destroyer" not in p_ships: self.game_ui.playerDestroyer.setEnabled(False) if "carrier" not in a_ships: self.game_ui.aiCarrier.setEnabled(False) if "battleship" not in a_ships: self.game_ui.aiBattleship.setEnabled(False) if "cruiser" not in a_ships: self.game_ui.aiCruiser.setEnabled(False) if "submarine" not in a_ships: self.game_ui.aiSubmarine.setEnabled(False) if "destroyer" not in a_ships: self.game_ui.aiDestroyer.setEnabled(False) def show(self): self.win.show()
class _WebEngineRendererHelper(QObject): """ This helper class is doing the real work. It is required to allow WebEngineRenderer.render() to be called "asynchronously" (but always from Qt's GUI thread). """ def __init__(self, parent): """ Copies the properties from the parent (WebEngineRenderer) object, creates the required instances of QWebPage, QWebView and QMainWindow and registers some Slots. """ QObject.__init__(self) # Copy properties from parent for key, value in parent.__dict__.items(): setattr(self, key, value) # Determine Proxy settings proxy = QNetworkProxy(QNetworkProxy.NoProxy) if 'http_proxy' in os.environ: proxy_url = QUrl(os.environ['http_proxy']) if proxy_url.scheme().startswith('http'): protocol = QNetworkProxy.HttpProxy else: protocol = QNetworkProxy.Socks5Proxy proxy = QNetworkProxy(protocol, proxy_url.host(), proxy_url.port(), proxy_url.userName(), proxy_url.password()) # Create and connect required PyQt5 objects self._page = CustomWebPage(logger=self.logger, ignore_alert=self.ignoreAlert, ignore_confirm=self.ignoreConfirm, ignore_prompt=self.ignorePrompt, interrupt_js=self.interruptJavaScript) self._qt_proxy = QNetworkProxy() self._qt_proxy.setApplicationProxy(proxy) self._view = QWebEngineView() self._view.setPage(self._page) _window_flags = Qt.WindowFlags() self._window = QMainWindow(flags=_window_flags) self._window.setCentralWidget(self._view) self._qt_network_access_manager = QNetworkAccessManager() # Import QWebSettings for key, value in self.qWebSettings.items(): self._page.settings().setAttribute(key, value) # Connect required event listeners # assert False, "Not finish" self._page.loadFinished.connect(self._on_load_finished) self._page.loadStarted.connect(self._on_load_started) self._qt_network_access_manager.sslErrors.connect(self._on_ssl_errors) self._qt_network_access_manager.finished.connect(self._on_each_reply) # The way we will use this, it seems to be unnecessary to have Scrollbars enabled self._scroll_area = QAbstractScrollArea() self._scroll_area.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff) self._scroll_area.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOff) # Show this widget self._window.show() def __del__(self): """ Clean up Qt5 objects. """ self._window.close() del self._window del self._view del self._page def render(self, res): """ The real worker. Loads the page (_load_page) and awaits the end of the given 'delay'. While it is waiting outstanding QApplication events are processed. After the given delay, the Window or Widget (depends on the value of 'grabWholeWindow' is drawn into a QScreen and post processed (_post_process_image). """ self._load_page(res, self.width, self.height, self.timeout) # Wait for end of timer. In this time, process # other outstanding Qt events. if self.wait > 0: if self.logger: self.logger.debug("Waiting {} seconds ".format(self.wait)) wait_to_time = time.time() + self.wait while time.time() < wait_to_time: if self.app.hasPendingEvents(): self.app.processEvents() if self.renderTransparentBackground: # Another possible drawing solution image = QImage(self._page.viewportSize(), QImage.Format_ARGB32) image.fill(QColor(255, 0, 0, 0).rgba()) # http://ariya.blogspot.com/2009/04/transparent-qwebview-and-qwebpage.html palette = self._view.palette() palette.setBrush(QPalette.Base, Qt.transparent) self._page.setPalette(palette) self._view.setAttribute(Qt.WA_OpaquePaintEvent, False) painter = QPainter(image) painter.setBackgroundMode(Qt.TransparentMode) self._window.render(painter) painter.end() else: if self.grabWholeWindow: # Note that this does not fully ensure that the # window still has the focus when the screen is # grabbed. This might result in a race condition. self._view.activateWindow() qt_screen = self.app.primaryScreen() image = qt_screen.grabWindow(sip.voidptr(0)) else: image = self._window.grab() return self._post_process_image(image) def _load_page(self, res, width, height, timeout): """ This method implements the logic for retrieving and displaying the requested page. """ # This is an event-based application. So we have to wait until # "loadFinished(bool)" raised. cancel_at = time.time() + timeout self.__loading = True self.__loadingResult = False # Default # When "res" is of type tuple, it has two elements where the first # element is the HTML code to render and the second element is a string # setting the base URL for the interpreted HTML code. # When resource is of type str or unicode, it is handled as URL which # shall be loaded if type(res) == tuple: url = res[1] else: url = res if self.encodedUrl: qt_url = QUrl().fromEncoded(url) else: qt_url = QUrl(url) # Set the required cookies, if any self.cookieJar = CookieJar(self.cookies, qt_url) self._qt_network_access_manager.setCookieJar(self.cookieJar) # Load the page if type(res) == tuple: self._page.setHtml(res[0], qt_url) # HTML, baseUrl else: self._page.load(qt_url) while self.__loading: if timeout > 0 and time.time() >= cancel_at: raise RuntimeError("Request timed out on {}".format(res)) while self.app.hasPendingEvents() and self.__loading: self.app.processEvents() if self.logger: self.logger.debug("Processing result") if not self.__loading_result: if self.logger: self.logger.warning("Failed to load {}".format(res)) # Set initial viewport (the size of the "window") size = self._page.contentsSize() if self.logger: self.logger.debug("contentsSize: %s", size) if width > 0: size.setWidth(width) if height > 0: size.setHeight(height) self._window.resize(size.toSize()) def _post_process_image(self, q_image): """ If 'scaleToWidth' or 'scaleToHeight' are set to a value greater than zero this method will scale the image using the method defined in 'scaleRatio'. """ if self.scaleToWidth > 0 or self.scaleToHeight > 0: # Scale this image if self.scaleRatio == 'keep': ratio = Qt.KeepAspectRatio elif self.scaleRatio in ['expand', 'crop']: ratio = Qt.KeepAspectRatioByExpanding else: # 'ignore' ratio = Qt.IgnoreAspectRatio q_image = q_image.scaled(self.scaleToWidth, self.scaleToHeight, ratio, Qt.SmoothTransformation) if self.scaleRatio == 'crop': q_image = q_image.copy(0, 0, self.scaleToWidth, self.scaleToHeight) return q_image @pyqtSlot(QNetworkReply, name='finished') def _on_each_reply(self, reply): """ Logs each requested uri """ self.logger.debug("Received {}".format(reply.url().toString())) # Event for "loadStarted()" signal @pyqtSlot(name='loadStarted') def _on_load_started(self): """ Slot that sets the '__loading' property to true """ if self.logger: self.logger.debug("loading started") self.__loading = True # Event for "loadFinished(bool)" signal @pyqtSlot(bool, name='loadFinished') def _on_load_finished(self, result): """ Slot that sets the '__loading' property to false and stores the result code in '__loading_result'. """ if self.logger: self.logger.debug("loading finished with result %s", result) self.__loading = False self.__loading_result = result # Event for "sslErrors(QNetworkReply *,const QList<QSslError>&)" signal @pyqtSlot('QNetworkReply*', 'QList<QSslError>', name='sslErrors') def _on_ssl_errors(self, reply, errors): """ Slot that writes SSL warnings into the log but ignores them. """ for e in errors: if self.logger: self.logger.warn("SSL: " + e.errorString()) reply.ignoreSslErrors() @property def window(self): return self._window
class SetupWindow: setup_ui = Ui_SetupWindow() placement_mode = None player_map = [] ships = { "carrier": 5, "battleship": 4, "cruiser": 3, "submarine": 3, "destroyer": 2 } rotate = "Horizontal" remained_ships = 5 def __init__(self): self.win = QMainWindow() self.setup_ui.setupUi(self.win) self.win.setWindowTitle("Battleship Game") self.setup_ui.readyButton.clicked.connect(self.actionReadyButton) self.setup_ui.carrierButton.clicked.connect(self.actionCarrierButton) self.setup_ui.battleshipButton.clicked.connect( self.actionBattleshipButton) self.setup_ui.cruiserButton.clicked.connect(self.actionCruiserButton) self.setup_ui.submarineButton.clicked.connect( self.actionSubmarineButton) self.setup_ui.destroyerButton.clicked.connect( self.actionDestroyerButton) self.setup_ui.rotateButton.clicked.connect(self.actionRotateButton) # Fill setup grid with cells for row in range(10): cells_row = [] for column in range(10): setup_cell = Cell(row, column, self) cells_row.append(setup_cell) self.setup_ui.setupGrid.addWidget(setup_cell, row, column) self.player_map.append(cells_row) # Show window def show(self): self.win.show() # Triggered when a cell clicked def actionCellClick(self, target): # If a ship is selected for placement, place ship to the target cell. if self.placement_mode: self.placeShips(self.placement_mode, target) print(self.placement_mode) def actionReadyButton(self): # Create a new game window self.game_window = GameWindow(self.player_map) self.game_window.show() # Close this window self.win.close() # Set placement mode to carrier, which indicates the carrier ship is going to be placed. def actionCarrierButton(self): self.placement_mode = "carrier" self.ship_button = self.setup_ui.carrierButton def actionBattleshipButton(self): self.placement_mode = "battleship" self.ship_button = self.setup_ui.battleshipButton def actionCruiserButton(self): self.placement_mode = "cruiser" self.ship_button = self.setup_ui.cruiserButton def actionSubmarineButton(self): self.placement_mode = "submarine" self.ship_button = self.setup_ui.submarineButton def actionDestroyerButton(self): self.placement_mode = "destroyer" self.ship_button = self.setup_ui.destroyerButton def buttonDisabled(self): self.ship_button.setEnabled(False) self.ship_button.setStyleSheet("background-color : white") self.remained_ships += -1 def actionRotateButton(self): if self.rotate == "Horizontal": self.rotate = "Vertical" self.setup_ui.directionLabel.setText("Vertical") else: self.rotate = "Horizontal" self.setup_ui.directionLabel.setText("Horizontal") def placeShips(self, ship_name, target): # Get target cell location row = target.row column = target.column # Get length of the ship ship_length = self.ships[ship_name] # Check if target has a valid position if self.rotate == "Horizontal": if column > 10 - ship_length: QMessageBox.warning(self.win, "Error", "Can't place this ship here", QMessageBox.Ok) return for i in range(ship_length): neighbor = self.player_map[row][column + i] if not neighbor.isEnabled(): # Collides with another ship QMessageBox.warning(self.win, "Error", "Colliding with another ship", QMessageBox.Ok) return else: if row > 10 - ship_length: QMessageBox.warning(self.win, "Error", "Can't place this ship here", QMessageBox.Ok) return for i in range(ship_length): neighbor = self.player_map[row + i][column] if not neighbor.isEnabled(): # Collides with another ship QMessageBox.warning(self.win, "Error", "Colliding with another ship", QMessageBox.Ok) return # The position is valid, place ship if self.rotate == "Horizontal": # Set cells occupied according to the size of the selected ship. for length in range(ship_length): neighbor = self.player_map[row][column + length] neighbor.setHit() neighbor.setOccupiedShip(ship_name) self.buttonDisabled() print("Player placed" + ship_name + " (H): ", row, column) else: # Set cells occupied according to the size of the selected ship. for length in range(ship_length): neighbor = self.player_map[row + length][column] neighbor.setHit() neighbor.setOccupiedShip(ship_name) self.buttonDisabled() print("Player placed" + ship_name + " (V): ", row, column) print(self.remained_ships) # If all ships are placed, activate ready button if self.remained_ships == 0: self.setup_ui.readyButton.setEnabled(True) self.setup_ui.readyButton.setStyleSheet("background-color: green") self.setup_ui.titleLabel.setText("Your ships are ready!") # When a ship is placed clear placement mode for another ship self.placement_mode = None
from model.Login import Login from module.g_Top import * import module.g_Top as g_Top from PyQt5.QtWidgets import QApplication, QMainWindow import sys if __name__ == '__main__': try: if not g_DB.ConnectFormFile(g_Data.path + g_Data.data + g_Data.MySqlConfigFileName): g_Log.LogError('数据库连接失败') g_Log.LogDebug('失败原因:' + g_DB.Error) sys.exit() app = QApplication(sys.argv) logWindow = QMainWindow() ui = Login(logWindow) logWindow.show() status = app.exec() if g_Top.g_UserName != '': g_Log.LogInfo(g_UserName + ':登录成功') logWindow.close() mainWindow = QMainWindow() ui = MainWindow(mainWindow) mainWindow.show() status = app.exec() g_Log.LogInfo(g_UserName + ':退出') sys.exit(status) finally: if g_DB: g_DB.close()
class MyWindow(QMainWindow): def __init__(self, parent=None): print("MyWindow __init__ called!") super(MyWindow, self).__init__(parent) self.ui = Ui_MainWindow() self.ui.setupUi(self) self.process_list_set() self.ui.pushButton_hook.clicked.connect(self.hook_btn_clicked) self.ui.pushButton_refresh.clicked.connect(self.process_list_set) # Open Process self.ui.pushButton_openProcess.clicked.connect(self.openProcess) self.ui.pushButton_go.clicked.connect(self.intercept_go_button) self.ui.pushButton_interceptToggle.toggled.connect( self.toggle_intercept_on) # 아래 4 줄은 헥스뷰와 스트링뷰를 연동하기 위한 것. self.ui.tableWidget_hexTable.cellChanged.connect( self.intercept_hexTable_changed) self.ui.tableWidget_stringTable.cellChanged.connect( self.intercept_strTable_changed) self.ui.tableWidget_hexTable.itemSelectionChanged.connect( self.hexTable_itemSelected) self.ui.tableWidget_stringTable.itemSelectionChanged.connect( self.strTable_itemSelected) # ikeeby # Repeater HEX, String VIEW # Repeater REQUEST 만 바꾸기 이벤트 self.ui.tableWidget_hexTable_3.cellChanged.connect( self.intercept_hexTable_changed_3) self.ui.tableWidget_hexTable_3.itemSelectionChanged.connect( self.hexTable_itemSelected_3) self.ui.tableWidget_stringTable_3.cellChanged.connect( self.intercept_strTable_changed_3) self.ui.tableWidget_stringTable_3.itemSelectionChanged.connect( self.strTable_itemSelected_3) # Repeater RESPONSE 는 바꾸지 못하도록 self.ui.tableWidget_hexTable_2.setEditTriggers( QAbstractItemView.NoEditTriggers) self.ui.tableWidget_stringTable_2.setEditTriggers( QAbstractItemView.NoEditTriggers) # Repeater go button self.ui.pushButton_go_2.clicked.connect(self.repeater_go_button) # custom mouse right click event init self.tableWidget_proxyHistory_right_click() # history detail self.ui.tableWidget_proxyHistory.verticalHeader().setVisible(False) self.ui.tableWidget_proxyHistory.cellClicked.connect( self.history_detail) # idx self.idx = 0 # Core Frida Agent 클래스 생성 self.frida_agent = FridaAgent(self) self.ui.textBrowser_log.append("[#] Create Frdia Agent") ################################################# self.match_and_replace = Match_and_Replace( self.ui.tableWidget_MatchAndReplace) ################################################# # Core Frida Agent로 부터 넘어오는 시그널 연결 self.make_connection(self.frida_agent) self.make_connection_err(self.frida_agent) # Process Open을 위한 [+] 버튼 누르면 나오는 창 만들기 self.open_process_window = QMainWindow() self.open_process_ui = open_process_Ui_MainWindow() self.open_process_ui.setupUi(self.open_process_window) self.open_process_window.setWindowFlags(Qt.FramelessWindowHint) self.open_process_ui.pushButton_start.clicked.connect( self.gui_start_process) self.open_process_ui.pushButton_cancleProcOpen.clicked.connect( self.closeOpenProc) # Option - hook checkbox self.ui.checkBox_send.stateChanged.connect(self.click_hook_send) self.ui.checkBox_recv.stateChanged.connect(self.click_hook_recv) self.ui.checkBox_sendto.stateChanged.connect(self.click_hook_sendto) self.ui.checkBox_recvfrom.stateChanged.connect( self.click_hook_recvfrom) self.ui.checkBox_wsasend.stateChanged.connect(self.click_hook_wsasend) self.ui.checkBox_wsarecv.stateChanged.connect(self.click_hook_wsarecv) self.ui.checkBox_encryptmessage.stateChanged.connect( self.click_hook_encryptmessage) self.ui.checkBox_decryptmessage.stateChanged.connect( self.click_hook_decryptmessage) self.ui.pushButton_refreshAgetnt.clicked.connect( self.refreshFridaAgent) def refreshFridaAgent(self): self.frida_agent.init_fridaAgent() def click_hook_send(self, state): print("MyWindow click_hook_send called!") if state == Qt.Checked: #hook self.frida_agent.hook_js("send") else: #unhook self.frida_agent.unhook_js("send") def click_hook_recv(self, state): print("MyWindow click_hook_recv called!") if state == Qt.Checked: #hook self.frida_agent.hook_js("recv") else: #unhook self.frida_agent.unhook_js("recv") def click_hook_sendto(self, state): print("MyWindow click_hook_sendto called!") if state == Qt.Checked: #hook self.frida_agent.hook_js("sendto") else: #unhook self.frida_agent.unhook_js("sendto") def click_hook_recvfrom(self, state): print("MyWindow click_hook_recvfrom called!") if state == Qt.Checked: #hook self.frida_agent.hook_js("recvfrom") else: #unhook self.frida_agent.unhook_js("recvfrom") def click_hook_wsasend(self, state): print("MyWindow click_hook_wsasend called!") if state == Qt.Checked: #hook self.frida_agent.hook_js("WSASend") else: #unhook self.frida_agent.unhook_js("WSASend") def click_hook_wsarecv(self, state): print("MyWindow click_hook_wsarecv called!") if state == Qt.Checked: #hook self.frida_agent.hook_js("WSARecv") else: #unhook self.frida_agent.unhook_js("WSARecv") def click_hook_encryptmessage(self, state): print("MyWindow click_hook_encryptmessage called!") if state == Qt.Checked: #hook self.frida_agent.hook_js("EncryptMessage") else: #unhook self.frida_agent.unhook_js("EncryptMessage") def click_hook_decryptmessage(self, state): print("MyWindow click_hook_decryptmessage called!") if state == Qt.Checked: #hook self.frida_agent.hook_js("DecryptMessage") else: #unhook self.frida_agent.unhook_js("DecryptMessage") ################################################# def resizeEvent(self, event): print("MyWindow resizeEvent called!") #print("resize") size = self.ui.tabWidget_tab.width() - 60 #size2 = self.ui.tableWidget_MatchAndReplace.width() #size = max(size1,size2) self.match_and_replace.resize(size) self.proxyHistory_resize(size) ################################################# def proxyHistory_resize(self, size): print("this is proxyHistory resize..") #size = self.tableWidget_proxyHistory.width() # history column size init # size = self.ui.tableWidget_proxyHistory.width() if (size < 978): size = 978 print(size) self.ui.tableWidget_proxyHistory.setColumnWidth(0, size / 3 / 6 * 2) self.ui.tableWidget_proxyHistory.setColumnWidth(1, size / 3 / 6 * 2) self.ui.tableWidget_proxyHistory.setColumnWidth(2, size / 3 / 6 * 2) self.ui.tableWidget_proxyHistory.setColumnWidth(3, size / 3 / 6 * 2) self.ui.tableWidget_proxyHistory.setColumnWidth(4, size / 3 / 6 * 2) self.ui.tableWidget_proxyHistory.setColumnWidth(5, size / 3 / 6 * 2) self.ui.tableWidget_proxyHistory.setColumnWidth(6, size / 3 / 1) #return size # openProcess Click 하면 실행되는 함수 def openProcess(self): print("MyWindow openProcess called!") self.open_process_window.show() # 아래 있는 코드들은 실제 실행 되는 코드 #self.frida_agent.inject_script(pid) #self.frida_agent.resume_process(int(pid)) def closeOpenProc(self): print("MyWindow closeOpenProc called!") self.open_process_window.close() def gui_start_process(self): print("MyWindow gui_start_process called!") filePath = self.open_process_ui.lineEdit_filePath.text() argument = self.open_process_ui.lineEdit_arg.text() pid = self.frida_agent.start_process(filePath, argument) self.open_alert_window(pid, True) # 위에 openProcess 랑 연결할 것임. 지금은 윈도우 창 닫는걸로 테스트 self.open_process_window.close() def close_alertwindow(self): print("MyWindow close_alertwindow called!") self.alert_window.close() # 두번째 proxy 탭으로 이동 self.ui.tabWidget_tab.setCurrentIndex(1) # customs context menu @pyqtSlot(QPoint) def custom_context_menu(self, position): main_menu = QMenu() send_repeater = main_menu.addAction("Send to Repeater") main_menu.addAction(send_repeater) send_repeater.triggered.connect( self.tableWidget_proxyHistory_right_click_repeater_event) remove = main_menu.addAction("Remove") main_menu.addAction(remove) remove.triggered.connect( self.tableWidget_proxyHistory_right_click_remove_event) highlight = QMenu("Highlight") main_menu.addMenu(highlight) white = QAction("White", highlight) highlight.addAction(white) red = QAction("Red", highlight) highlight.addAction(red) orange = QAction("Orange", highlight) highlight.addAction(orange) yellow = QAction("Yellow", highlight) highlight.addAction(yellow) green = QAction("Green", highlight) highlight.addAction(green) blue = QAction("Blue", highlight) highlight.addAction(blue) darkblue = QAction("DarkBlue", highlight) highlight.addAction(darkblue) purple = QAction("Purple", highlight) highlight.addAction(purple) black = QAction("Black", highlight) highlight.addAction(black) white.triggered.connect( lambda: self.tableWidget_proxyHistory_right_click_highlight_event( QColor(255, 255, 255), QColor(0, 0, 0))) red.triggered.connect( lambda: self.tableWidget_proxyHistory_right_click_highlight_event( QColor(255, 0, 0), QColor(0, 0, 0))) orange.triggered.connect( lambda: self.tableWidget_proxyHistory_right_click_highlight_event( QColor(255, 170, 0), QColor(0, 0, 0))) yellow.triggered.connect( lambda: self.tableWidget_proxyHistory_right_click_highlight_event( QColor(255, 255, 0), QColor(0, 0, 0))) green.triggered.connect( lambda: self.tableWidget_proxyHistory_right_click_highlight_event( QColor(0, 255, 0), QColor(0, 0, 0))) blue.triggered.connect( lambda: self.tableWidget_proxyHistory_right_click_highlight_event( QColor(0, 0, 255), QColor(255, 255, 255))) darkblue.triggered.connect( lambda: self.tableWidget_proxyHistory_right_click_highlight_event( QColor(0, 0, 127), QColor(255, 255, 255))) purple.triggered.connect( lambda: self.tableWidget_proxyHistory_right_click_highlight_event( QColor(170, 0, 255), QColor(255, 255, 255))) black.triggered.connect( lambda: self.tableWidget_proxyHistory_right_click_highlight_event( QColor(0, 0, 0), QColor(255, 255, 255))) action = main_menu.exec_(QCursor.pos()) def tableWidget_proxyHistory_right_click(self): print("MyWindow tableWidget_proxyHistory_right_click called!") self.ui.tableWidget_proxyHistory.setSelectionBehavior( QTableView.SelectRows) # select column? then select all column! #self.ui.tableWidget_proxyHistory.setContextMenuPolicy(Qt.ActionsContextMenu) self.ui.tableWidget_proxyHistory.setContextMenuPolicy( Qt.CustomContextMenu) self.ui.tableWidget_proxyHistory.customContextMenuRequested.connect( self.custom_context_menu) def packet_highlight(self, rowIndex, background_color, font_color): for j in range(self.ui.tableWidget_proxyHistory.columnCount()): self.ui.tableWidget_proxyHistory.item( rowIndex, j).setBackground(background_color) self.ui.tableWidget_proxyHistory.item(rowIndex, j).setForeground(font_color) def tableWidget_proxyHistory_right_click_highlight_event( self, background_color, font_color): print( "MyWindow tableWidget_proxyHistory_right_click_highlight_event called!" ) index_list = [] for model_index in self.ui.tableWidget_proxyHistory.selectionModel( ).selectedRows(): index = QPersistentModelIndex(model_index) index_list.append(index) if (len(index_list) > 0): #print(index_list[0].row()) for index in index_list: self.packet_highlight(index.row(), background_color, font_color) #self.ui.tabWidget_tab.setCurrentIndex(2) def tableWidget_proxyHistory_right_click_repeater_event(self): print( "MyWindow tableWidget_proxyHistory_right_click_repeater_event called!" ) ''' # get mouse pos pos = QCursor.pos() # PyQt5.QtCore.QPoint(262, 215) # get proxyHistory row row = self.ui.tableWidget_proxyHistory.rowAt(self.ui.tableWidget_proxyHistory.viewport().mapFromGlobal(pos).y()) print(row) if(row>-1): self.send_packet_to_Repeater(row) self.ui.tabWidget_tab.setCurrentIndex(2) ''' index_list = [] for model_index in self.ui.tableWidget_proxyHistory.selectionModel( ).selectedRows(): index = QPersistentModelIndex(model_index) index_list.append(index) if (len(index_list) > 0): #print(index_list[0].row()) self.send_packet_to_Repeater(index_list[0].row()) self.ui.tabWidget_tab.setCurrentIndex(2) def tableWidget_proxyHistory_right_click_remove_event(self): index_list = [] for model_index in self.ui.tableWidget_proxyHistory.selectionModel( ).selectedRows(): index = QPersistentModelIndex(model_index) index_list.append(index) for index in index_list: #self.remove(index.row()) #remove internal data in list self.ui.tableWidget_proxyHistory.removeRow( index.row()) #remove gui ############ikeeby def process_list_set(self): print("MyWindow process_list_set called!") header = self.ui.tableWidget_procList.horizontalHeader() header.setSectionResizeMode(0, QHeaderView.ResizeToContents) header.setSectionResizeMode(1, QHeaderView.Stretch) process_list = get_process_list() self.ui.tableWidget_procList.setRowCount(len(process_list)) c = 0 for proc in process_list: self.ui.tableWidget_procList.setItem( c, 0, QTableWidgetItem(str(proc[0]))) self.ui.tableWidget_procList.setItem(c, 1, QTableWidgetItem(proc[1])) c += 1 self.ui.tableWidget_procList.cellClicked.connect(self.process_clicked) self.ui.tableWidget_procList.cellDoubleClicked.connect( self.hook_btn_clicked) def process_clicked(self, row, col): print("MyWindow process_clicked called!") proc_pid = self.ui.tableWidget_procList.item(row, 0).text() proc_name = self.ui.tableWidget_procList.item(row, 1).text() self.ui.lineEdit_pid_input.setText(proc_pid) # 상태바에 선택한 프로세스 정보 보여주기 message = "PID : {} / Process Name : {}".format(proc_pid, proc_name) self.ui.statusbar.showMessage(message) def hook_btn_clicked(self): print("MyWindow hook_btn_clicked called!") user_input_pid = self.ui.lineEdit_pid_input.text() self.open_alert_window(user_input_pid) #hook_function(pid) def open_alert_window(self, pid, start_process_flag=False): print("MyWindow open_alert_window called!") self.hook_pid = pid self.alert_window = QMainWindow() self.alert_ui = hook_alert_Ui_MainWindow() self.alert_ui.setupUi(self.alert_window) self.alert_window.setWindowFlags(Qt.FramelessWindowHint) self.alert_window.show() if (start_process_flag == False): self.frida_agent.inject_frida_agent(pid) self.frida_agent.inject_script(pid) self.alert_ui.pushButton_gogo.clicked.connect(self.close_alertwindow) def close_alertwindow(self): print("MyWindow close_alertwindow called!") self.alert_window.close() # 두번째 proxy 탭으로 이동 self.ui.tabWidget_tab.setCurrentIndex(1) def make_connection(self, class_object): print("MyWindow make_connection called!") class_object.from_agent_data.connect(self.from_fridaJS) def make_connection_err(self, class_object): print("MyWindow make_connection_err called!") class_object.error_signal.connect(self.error_message_box) @pyqtSlot(str) def from_fridaJS(self, data): print("MyWindow from_fridaJS called!") if (data.startswith("[PROXY]")): func_name, ip_info, port_info = parsing_info(data) pid = parsing_pid(data) hex_data = parsing_hex(data) self.idx += 1 # packet이 들어오면 먼저 match_and_replace ! change_flag, hex_data = self.match_and_replace_func( self.idx, pid, func_name, ip_info, port_info, hex_data) # 인터셉트 모드일 경우 if (self.frida_agent.intercept_on): #self.frida_agent.current_isIntercept = True self.intercept_view(pid, func_name, ip_info, port_info, hex_data) self.ui.tabWidget_proxyTab.setCurrentIndex(0) # 클릭을 연결해두기. (go button) else: # 빈 문자 전송 if (change_flag): self.frida_agent.send_spoofData(pid, func_name, hex_data) else: self.frida_agent.send_spoofData(pid, func_name, []) self.history_addRow(self.idx, pid, func_name, ip_info, port_info, hex_data) # 전송 후, 히스토리에 기록 #self.history_addRow(pid, func_name, ip_info, port_info, hex_data) def match_and_replace_func(self, idx, pid, func_name, ip_info, port_info, hex_data): print("MyWindow match_and_replace_func called!") strHex = "" change_flag = False if (len(hex_data) > 0 and len(self.match_and_replace.enabled_list) > 0): for hex in hex_data: strHex += hex + " " strHex = strHex[:-1] # remove " " for enabled_data in self.match_and_replace.enabled_list: filter_ip = enabled_data["ip"] filter_port = enabled_data["port"] filter_function = enabled_data["function"] print(filter_function) print(func_name) if ((filter_ip == ip_info or filter_ip == "*") and (filter_port == port_info or filter_port == "*") and (filter_function == func_name or filter_function == "ANY")): print("match and replace start") # match and replace start! match_data = enabled_data["match"] replace_data = enabled_data["replace"] ''' idx = strHex.find(match_data) if(idx > -1): strHex = strHex[:idx] + replace_data + strHex[idx+len(match_data):] hex_data = strHex.split(' ') change_flag = True ''' flag = strHex.find(match_data) if (flag > -1): print("match find! replace complete") newHex = strHex.replace(match_data, replace_data) hex_data = newHex.split(' ') change_flag = True self.ui.textBrowser_log.append( "[#] Match And Replace >") self.ui.textBrowser_log.append("idx: " + str(idx) + " pid : " + pid + ", func_name : " + func_name + ", ip_info : " + ip_info + ", port_info : " + port_info) self.ui.textBrowser_log.append("match_data : " + match_data + ", replace_data : " + replace_data) self.ui.textBrowser_log.append("origin_data : " + strHex) self.ui.textBrowser_log.append("modified_data : " + newHex) #print(hex_data) return change_flag, hex_data #def history_addRow(self,history_item): def history_addRow(self, idx, pid, func_name, ip_info, port_info, hex_data): print("MyWindow history_addRow called!") #pid = parsing_pid(history_item) proc_name = get_process_name(pid) #func_name, ip_info, port_info = parsing_info(history_item) #hex_data = parsing_hex(history_item) hex_text, str_text = hexDump2Str(hex_data) append_data = { "idx": idx, "pid": pid, "proc_name": proc_name, "func_name": func_name, "ip": ip_info, "port": port_info, "hex_data": hex_data, "hex_text": hex_text, "str_text": str_text } # History 기록 self.frida_agent.proxy_history.append(append_data) numRows = self.ui.tableWidget_proxyHistory.rowCount() self.ui.tableWidget_proxyHistory.insertRow(numRows) add_item = self.frida_agent.proxy_history[-1] self.ui.tableWidget_proxyHistory.setItem(numRows, 0, QTableWidgetItem(str(idx))) self.ui.tableWidget_proxyHistory.setItem( numRows, 1, QTableWidgetItem(add_item['pid'])) self.ui.tableWidget_proxyHistory.setItem( numRows, 2, QTableWidgetItem(add_item["proc_name"])) self.ui.tableWidget_proxyHistory.setItem( numRows, 3, QTableWidgetItem(add_item["func_name"])) self.ui.tableWidget_proxyHistory.setItem( numRows, 4, QTableWidgetItem(add_item["ip"])) self.ui.tableWidget_proxyHistory.setItem( numRows, 5, QTableWidgetItem(add_item["port"])) self.ui.tableWidget_proxyHistory.setItem( numRows, 6, QTableWidgetItem(add_item["str_text"])) if (self.ui.checkBox_autoScroll.isChecked()): current_item = self.ui.tableWidget_proxyHistory.item(numRows, 0) self.ui.tableWidget_proxyHistory.scrollToItem( current_item, QAbstractItemView.PositionAtBottom) #self.ui.tableWidget_proxyHistory.selectRow(numRows) def history_detail(self, row, col): print("MyWindow history_detail called!") hex_text = self.frida_agent.proxy_history[row]['hex_text'] str_text = self.frida_agent.proxy_history[row]['str_text'] self.ui.textBrowser_hexData.setText(hex_text) self.ui.textBrowser_stringData.setText(str_text) # test용 self.ui.statusbar.showMessage("PID : {} / Process Name : {}".format( self.frida_agent.proxy_history[row]['pid'], self.frida_agent.proxy_history[row]['proc_name'])) #ikeeby def send_packet_to_Repeater(self, row): print("MyWindow send_packet_to_Repeater called!") self.ui.tableWidget_hexTable_3.cellChanged.disconnect() self.ui.tableWidget_stringTable_3.cellChanged.disconnect() # 기존 데이터 초기화 self.ui.tableWidget_hexTable_3.setRowCount(0) self.ui.tableWidget_stringTable_3.setRowCount(0) # # Destination IP, PORT Setting ip = self.frida_agent.proxy_history[row]['ip'] port = self.frida_agent.proxy_history[row]['port'] self.ui.repeater_ip_box.setText(ip) self.ui.repeater_port_box.setText(port) # Hex, String View Setting hex_text = self.frida_agent.proxy_history[row]['hex_text'] str_text = self.frida_agent.proxy_history[row]['str_text'] hex_data = hex_text.split(' ')[:-1] # 기존 intercept_view function pid 부분 빼고 복붙 need_row_num = int(len(hex_data) / 16) #self.ui.tableWidget_hexTable.clearContents() for row in range(need_row_num + 1): numRows = self.ui.tableWidget_hexTable_3.rowCount() self.ui.tableWidget_hexTable_3.insertRow(numRows) self.ui.tableWidget_stringTable_3.insertRow(numRows) if (row < need_row_num): # 16번 반복 for i in range(16): self.ui.tableWidget_hexTable_3.setItem( row, i, QTableWidgetItem(hex_data[(16 * row) + i])) self.ui.tableWidget_hexTable_3.item( numRows, i).setTextAlignment(Qt.AlignVCenter | Qt.AlignHCenter) self.ui.tableWidget_stringTable_3.setItem( row, i, QTableWidgetItem(chr(int(hex_data[(16 * row) + i], 16)))) self.ui.tableWidget_stringTable_3.item( numRows, i).setTextAlignment(Qt.AlignVCenter | Qt.AlignHCenter) else: # total_length - (need_row_num * 16) for i in range((len(hex_data) - (need_row_num * 16))): self.ui.tableWidget_hexTable_3.setItem( row, i, QTableWidgetItem(hex_data[(16 * row) + i])) self.ui.tableWidget_hexTable_3.item( numRows, i).setTextAlignment(Qt.AlignVCenter | Qt.AlignHCenter) self.ui.tableWidget_stringTable_3.setItem( row, i, QTableWidgetItem(chr(int(hex_data[(16 * row) + i], 16)))) self.ui.tableWidget_stringTable_3.item( numRows, i).setTextAlignment(Qt.AlignVCenter | Qt.AlignHCenter) self.ui.tableWidget_hexTable_3.cellChanged.connect( self.intercept_hexTable_changed_3) self.ui.tableWidget_stringTable_3.cellChanged.connect( self.intercept_strTable_changed_3) def recv_packet_to_Repeater(self, packet): print("MyWindow recv_packet_to_Repeater called!") # 기존 데이터 초기화 self.ui.tableWidget_hexTable_2.setRowCount(0) self.ui.tableWidget_stringTable_2.setRowCount(0) # Hex, String View Setting #hex_text = packet hex_data = packet #print(hex_data) # 기존 intercept_view function pid 부분 빼고 복붙 need_row_num = int(len(hex_data) / 16) #self.ui.tableWidget_hexTable.clearContents() for row in range(need_row_num + 1): numRows = self.ui.tableWidget_hexTable_2.rowCount() self.ui.tableWidget_hexTable_2.insertRow(numRows) self.ui.tableWidget_stringTable_2.insertRow(numRows) if (row < need_row_num): # 16번 반복 for i in range(16): self.ui.tableWidget_hexTable_2.setItem( row, i, QTableWidgetItem(hex_data[(16 * row) + i])) self.ui.tableWidget_hexTable_2.item( numRows, i).setTextAlignment(Qt.AlignVCenter | Qt.AlignHCenter) self.ui.tableWidget_stringTable_2.setItem( row, i, QTableWidgetItem(chr(int(hex_data[(16 * row) + i], 16)))) self.ui.tableWidget_stringTable_2.item( numRows, i).setTextAlignment(Qt.AlignVCenter | Qt.AlignHCenter) else: # total_length - (need_row_num * 16) for i in range((len(hex_data) - (need_row_num * 16))): self.ui.tableWidget_hexTable_2.setItem( row, i, QTableWidgetItem(hex_data[(16 * row) + i])) self.ui.tableWidget_hexTable_2.item( numRows, i).setTextAlignment(Qt.AlignVCenter | Qt.AlignHCenter) self.ui.tableWidget_stringTable_2.setItem( row, i, QTableWidgetItem(chr(int(hex_data[(16 * row) + i], 16)))) self.ui.tableWidget_stringTable_2.item( numRows, i).setTextAlignment(Qt.AlignVCenter | Qt.AlignHCenter) ######### ikeeby #"[PROXY][FUNC_NAME]"+hook_function_name+" [IP]"+socket_address.ip+" [PORT]"+socket_address.port+" "+"[HEXDUMP]"+buf_length+" " + res def intercept_view(self, pid, func_name, ip_info, port_info, hex_data): print("MyWindow intercept_view called!") self.ui.tableWidget_hexTable.cellChanged.disconnect() self.ui.tableWidget_stringTable.cellChanged.disconnect() proc_name = get_process_name(pid) self.ui.lineEdit_intercept_info.setText( "PID : {} / Process Name : {} / FUNCTION : {} / ADDRESS : {}:{}". format(pid, proc_name, func_name, ip_info, port_info)) need_row_num = int(len(hex_data) / 16) #self.ui.tableWidget_hexTable.clearContents() for row in range(need_row_num + 1): numRows = self.ui.tableWidget_hexTable.rowCount() self.ui.tableWidget_hexTable.insertRow(numRows) self.ui.tableWidget_stringTable.insertRow(numRows) if (row < need_row_num): # 16번 반복 for i in range(16): self.ui.tableWidget_hexTable.setItem( row, i, QTableWidgetItem(hex_data[(16 * row) + i])) self.ui.tableWidget_hexTable.item( numRows, i).setTextAlignment(Qt.AlignVCenter | Qt.AlignHCenter) self.ui.tableWidget_stringTable.setItem( row, i, QTableWidgetItem(chr(int(hex_data[(16 * row) + i], 16)))) self.ui.tableWidget_stringTable.item( numRows, i).setTextAlignment(Qt.AlignVCenter | Qt.AlignHCenter) else: # total_length - (need_row_num * 16) for i in range((len(hex_data) - (need_row_num * 16))): self.ui.tableWidget_hexTable.setItem( row, i, QTableWidgetItem(hex_data[(16 * row) + i])) self.ui.tableWidget_hexTable.item( numRows, i).setTextAlignment(Qt.AlignVCenter | Qt.AlignHCenter) self.ui.tableWidget_stringTable.setItem( row, i, QTableWidgetItem(chr(int(hex_data[(16 * row) + i], 16)))) self.ui.tableWidget_stringTable.item( numRows, i).setTextAlignment(Qt.AlignVCenter | Qt.AlignHCenter) self.ui.tableWidget_hexTable.cellChanged.connect( self.intercept_hexTable_changed) self.ui.tableWidget_stringTable.cellChanged.connect( self.intercept_strTable_changed) def hexTableToList(self): print("MyWindow hexTableToList called!") hexTable = self.ui.tableWidget_hexTable hexList = [] numRows = hexTable.rowCount() for i in range(numRows): for j in range(16): hexDataItem = hexTable.item(i, j) if hexDataItem != None: hexList.append(hexDataItem.text()) return hexList def intercept_go_button(self): print("MyWindow intercept_go_button called!") #self.ui.textBrowser_hexData.setText(str(hexList)) intercept_info = self.ui.lineEdit_intercept_info.text().split() #print("intercept_info!") #print(intercept_info) try: pid = intercept_info[2] func_name = intercept_info[11] ip_info, port_info = intercept_info[-1].split(":") except Exception as e: return if (self.frida_agent.current_isIntercept): hex_data = self.hexTableToList() self.frida_agent.send_spoofData(pid, func_name, hex_data) self.history_addRow(self.idx, pid, func_name, ip_info, port_info, hex_data) for i in reversed(range(self.ui.tableWidget_hexTable.rowCount())): self.ui.tableWidget_hexTable.removeRow(i) for i in reversed(range( self.ui.tableWidget_stringTable.rowCount())): self.ui.tableWidget_stringTable.removeRow(i) self.ui.lineEdit_intercept_info.setText("") self.ui.tableWidget_hexTable.setRowCount(0) self.ui.tableWidget_stringTable.setRowCount(0) def repeater_hexTableToList(self): print("MyWindow repeater_hexTableToList called!") hexTable = self.ui.tableWidget_hexTable_3 hexList = [] numRows = hexTable.rowCount() for i in range(numRows): for j in range(16): hexDataItem = hexTable.item(i, j) if hexDataItem != None: hexList.append(hexDataItem.text()) return hexList def repeater_go_button(self): print("MyWindow repeater_go_button called!") hexList = self.repeater_hexTableToList() # change hexlist to byte array data = bytes([int(x, 16) for x in hexList]) try: sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) sock.connect((self.ui.repeater_ip_box.text(), int(self.ui.repeater_port_box.text()))) sock.settimeout(1) # timeout 설정 sock.send(data) recv_data = sock.recv(1024) recv_data2 = recv_data.hex() recv_data_list = [] for i in range(0, len(recv_data2), 2): recv_data_list.append(recv_data2[i:i + 2]) #print(recv_data_list) self.recv_packet_to_Repeater(recv_data_list) except socket.timeout: print("repeater_go_button: ") print("timeout error") except Exception as e: print("repeater_go_button: ") print(e) finally: sock.close() def toggle_intercept_on(self): print("MyWindow toggle_intercept_on called!") self.frida_agent.intercept_on = self.ui.pushButton_interceptToggle.isChecked( ) """ if(self.frida_agent.current_isIntercept): # 현재 인터셉트 중인지 확인, 인터셉트 중이라면 intercept_go 버튼 클릭 self.intercept_go_button() """ if (self.frida_agent.intercept_on): self.ui.pushButton_interceptToggle.setText("Intercept ON") else: self.ui.pushButton_interceptToggle.setText("Intercept OFF") try: pid = intercept_info[2] self.intercept_go_button() except Exception as e: pass def intercept_hexTable_changed(self, row, col): print("MyWindow intercept_hexTable_changed called!") changed_data = self.ui.tableWidget_hexTable.item(row, col).text() print(changed_data) try: tmp = int(changed_data, 16) except Exception as e: print("exception") print(e) changed_data = "00" if (len(changed_data) != 2): changed_data = "0" + changed_data if (self.ui.tableWidget_hexTable.item(row, col) != None): self.ui.tableWidget_hexTable.item(row, col).setText(changed_data) if (self.ui.tableWidget_stringTable.item(row, col) != None): self.ui.tableWidget_stringTable.item(row, col).setText( chr(int(changed_data, 16))) def hexTable_itemSelected(self): print("MyWindow hexTable_itemSelected called!") for sel_item in self.ui.tableWidget_hexTable.selectedItems(): row = sel_item.row() col = sel_item.column() self.ui.tableWidget_stringTable.setCurrentCell(row, col) def intercept_strTable_changed(self, row, col): print("MyWindow intercept_strTable_changed called!") changed_data = self.ui.tableWidget_stringTable.item(row, col).text() print(changed_data) if (len(changed_data) != 1): changed_data = " " self.ui.tableWidget_hexTable.item(row, col).setText( hex(ord(changed_data))[2:]) self.ui.tableWidget_stringTable.item(row, col).setText(changed_data) def strTable_itemSelected(self): print("MyWindow strTable_itemSelected called!") for sel_item in self.ui.tableWidget_stringTable.selectedItems(): row = sel_item.row() col = sel_item.column() self.ui.tableWidget_hexTable.setCurrentCell(row, col) # ikeeby def intercept_hexTable_changed_3(self, row, col): print("MyWindow intercept_hexTable_changed_3 called!") changed_data = self.ui.tableWidget_hexTable_3.item(row, col).text() try: tmp = int(changed_data, 16) except Exception: changed_data = "00" if (len(changed_data) != 2): changed_data = "0" + changed_data if (self.ui.tableWidget_hexTable_3.item(row, col) != None): self.ui.tableWidget_hexTable_3.item(row, col).setText(changed_data) if (self.ui.tableWidget_stringTable_3.item(row, col) != None): self.ui.tableWidget_stringTable_3.item(row, col).setText( chr(int(changed_data, 16))) # ikeeby def hexTable_itemSelected_3(self): print("MyWindow hexTable_itemSelected_3 called!") for sel_item in self.ui.tableWidget_hexTable_3.selectedItems(): row = sel_item.row() col = sel_item.column() self.ui.tableWidget_stringTable_3.setCurrentCell(row, col) # ikeeby def intercept_strTable_changed_3(self, row, col): print("MyWindow intercept_strTable_changed_3 called!") changed_data = self.ui.tableWidget_stringTable_3.item(row, col).text() if (len(changed_data) != 1): changed_data = " " self.ui.tableWidget_hexTable_3.item(row, col).setText( hex(ord(changed_data))[2:]) self.ui.tableWidget_stringTable_3.item(row, col).setText(changed_data) # ikeeby def strTable_itemSelected_3(self): print("MyWindow strTable_itemSelected_3 called!") for sel_item in self.ui.tableWidget_stringTable_3.selectedItems(): row = sel_item.row() col = sel_item.column() self.ui.tableWidget_hexTable_3.setCurrentCell(row, col) @pyqtSlot(str) def error_message_box(self, data): print("MyWindow error_message_box called!") # 에러 메시지 박스 오픈 # 임시로 아래 상태바에 출력 self.ui.statusbar.showMessage(data) self.ui.textBrowser_log.append("[*] Error : " + str(data))
def close_window(self): QMainWindow.close(self)
import window try: file_line = linecache.getline("settings.txt", 3) if file_line == "First start = 1\n": old_file = open("settings.txt").read() old_file = old_file.replace('First start = 1', 'First start = 0') new_file = open("settings.txt", 'w') new_file.write(old_file) new_file.close() app1 = QApplication(sys.argv) MainWindow1 = QMainWindow() window1 = window.firstConfiguration() window1.contain(MainWindow1) window1.start_button.clicked.connect(lambda: MainWindow1.close()) MainWindow1.show() sys.exit(app1.exec_()) finally: linecache.clearcache() app2 = QApplication(sys.argv) """ Set font and theme in main window """ font_line = linecache.getline("settings.txt", 7) theme_line = linecache.getline("settings.txt", 8) if not theme_line[theme_line.find("=") + 2:-1] == "Default": style_css = "Theme/%s.qss" % theme_line[theme_line.find("=") + 2:-1] style = open(style_css, "r") app2.setStyleSheet(style.read() + "* {font-family: %s;}" % font_line[font_line.find("=") + 2:-1])
class BeamChar(AbstractTool): def __init__(self, parent): super(BeamChar, self).__init__(parent) self._name = "Beam Characteristics" self._parent = parent self._filename = "" self._settings = {} # --- Initialize the GUI --- # self._beamCharWindow = QMainWindow() self._beamCharGUI = Ui_BeamChar() self._beamCharGUI.setupUi(self._beamCharWindow) self._beamCharGUI.buttonBox.accepted.connect(self.callback_apply) self._beamCharGUI.buttonBox.rejected.connect( self._beamCharWindow.close) self._has_gui = True self._need_selection = True self._min_selections = 1 self._max_selections = None self._redraw_on_exit = False def apply_settings(self): self._settings["rms"] = self._beamCharGUI.rms.isChecked() self._settings["halo"] = self._beamCharGUI.halo.isChecked() self._settings["centroid"] = self._beamCharGUI.centroid.isChecked() self._settings["turnsep"] = self._beamCharGUI.turnsep.isChecked() self._settings["energyHist"] = self._beamCharGUI.ehist.isChecked() self._settings["intensity"] = self._beamCharGUI.intens.isChecked() self._settings["xz"] = self._beamCharGUI.xz.isChecked() def callback_apply(self): self.apply_settings() self._beamCharWindow.close() self._parent.send_status("Creating plot(s)...") plots = {} num = 0 largepos = 1.0e36 for dataset in self._selections: corrected = {} name = dataset.get_name() nsteps, npart = dataset.get_nsteps(), dataset.get_npart() plot_data = { "name": name, "xRMS": np.array([]), "yRMS": np.array([]), "zRMS": np.array([]), "xHalo": np.array([]), "yHalo": np.array([]), "zHalo": np.array([]), "xCentroid": np.ones(nsteps) * largepos, "yCentroid": np.ones(nsteps) * largepos, "turnSep": np.array([]), "R": np.array([]), "energy": np.array([]), "power": np.array([]), "coords": [] } azimuths = np.ones(nsteps) * largepos r_temps = np.ones(nsteps) * largepos datasource = dataset.get_datasource() index = 0 save_r = True r_tsep = [] # --- Try to find the .o file corresponding to the dataset # Hardcoded defaults q_macro = 1.353 * 1.0e-15 # fC --> C (1e5 particles @ 6.65 mA and f_cyclo below) f_cyclo = 49.16 * 1.0e6 # MHz --> Hz duty_factor = 0.9 # assumed IsoDAR has 90% duty factor self._parent.send_status( "Attempting to read frequency and macro-charge from .o file..." ) _fn = dataset.get_filename() path = os.path.split(_fn)[0] # Let's be lazy and find the .o file automatically using regex template = re.compile('[.]o[0-9]{8}') _fns = [ f for f in os.listdir(path) if os.path.isfile(os.path.join(path, f)) and template.search(f) ] if len(_fns) > 0: _fn = _fns[0] with open(os.path.join(path, _fn), 'r') as infile: lines = infile.readlines() have_charge = False have_freq = False for line in lines: if "Qi" in line: _, _, _, _, _, _, _, _, qi, unit = line.strip().split() q_macro = float(qi) * 1.0e-15 # fC --> C # TODO Check for unit, if exception is thrown, need to allow for different units -DW assert unit == "[fC]", "Expected units of fC, got {}. Aborting!".format( unit) have_charge = True if "FREQUENCY" in line: _, _, _, freq, unit = line.strip().split() f_cyclo = float(freq) * 1.0e6 # MHz --> Hz # TODO Check for unit, if exception is thrown, need to allow for different units -DW assert unit == "MHz", "Expected units of MHz, got {}. Aborting!".format( unit) have_freq = True if have_charge and have_freq: break assert have_charge and have_freq, "Found .o file, but couldn't determine frequency and/or macrocharge!" self._parent.send_status( "Found f = {:.4f} MHz and Qi = {:.4f} fC in file {}". format(f_cyclo * 1e-6, q_macro * 1e15, _fn)) print("Found f = {:.4f} MHz and Qi = {:.4f} fC in file {}". format(f_cyclo * 1e-6, q_macro * 1e15, _fn)) else: self._parent.send_status( "Couldn't find .o file in dataset folder! Falling back to hardcoded values." ) print( "Couldn't find .o file in dataset folder! Falling back to hardcoded values." ) spt = 1 for step in range(int(nsteps / spt)): step *= spt m_amu = 2.01510 # Rest mass of individual H2+, in amu m_mev = 1876.9729554 # Rest mass of individual H2+, in MeV/c^2 if self._settings["rms"] or self._settings["halo"]: px_val = np.array(datasource["Step#{}".format(step)]["px"]) py_val = np.array(datasource["Step#{}".format(step)]["py"]) pz_val = np.array(datasource["Step#{}".format(step)]["pz"]) betagamma = np.sqrt( np.square(px_val) + np.square(py_val) + np.square(pz_val)) energy = np.mean((np.sqrt( np.square(betagamma * m_mev) + np.square(m_mev)) - m_mev) / m_amu) plot_data["energy"] = np.append(plot_data["energy"], energy) if nsteps > 1: completed = int(100 * (step / (nsteps - 1))) self._parent.send_status( "Plotting progress: {}% complete".format(completed)) corrected["Step#{}".format(step)] = {} x_val = np.array(datasource["Step#{}".format(step)]["x"]) y_val = np.array(datasource["Step#{}".format(step)]["y"]) z_val = np.array(datasource["Step#{}".format(step)]["z"]) if self._settings["xz"]: r = np.sqrt(np.square(x_val) + np.square(y_val)) plot_data["coords"] = np.append(plot_data["coords"], z_val) plot_data["R"] = np.append(plot_data["R"], r) px_mean = np.mean( np.array(datasource["Step#{}".format(step)]["px"])) py_mean = np.mean( np.array(datasource["Step#{}".format(step)]["py"])) theta = np.arccos(py_mean / np.linalg.norm([px_mean, py_mean])) if px_mean < 0: theta = -theta # Center the beam corrected["Step#{}".format(step)]["x"] = x_val - np.mean(x_val) corrected["Step#{}".format(step)]["y"] = y_val - np.mean(y_val) corrected["Step#{}".format(step)]["z"] = z_val - np.mean(z_val) # Rotate the beam temp_x = corrected["Step#{}".format(step)]["x"] temp_y = corrected["Step#{}".format(step)]["y"] corrected["Step#{}".format(step)][ "x"] = temp_x * np.cos(theta) - temp_y * np.sin(theta) corrected["Step#{}".format(step)][ "y"] = temp_x * np.sin(theta) + temp_y * np.cos(theta) # Calculate RMS if self._settings["rms"]: plot_data["xRMS"] = np.append( plot_data["xRMS"], 1000.0 * self.rms(corrected["Step#{}".format(step)]["x"])) plot_data["yRMS"] = np.append( plot_data["yRMS"], 1000.0 * self.rms(corrected["Step#{}".format(step)]["y"])) plot_data["zRMS"] = np.append( plot_data["zRMS"], 1000.0 * self.rms(corrected["Step#{}".format(step)]["z"])) # Calculate halo parameter if self._settings["halo"]: plot_data["xHalo"] = np.append( plot_data["xHalo"], self.halo(corrected["Step#{}".format(step)]["x"])) plot_data["yHalo"] = np.append( plot_data["yHalo"], self.halo(corrected["Step#{}".format(step)]["y"])) plot_data["zHalo"] = np.append( plot_data["zHalo"], self.halo(corrected["Step#{}".format(step)]["z"])) # Calculate energy if self._settings["energyHist"] or self._settings["intensity"]: m_amu = 2.01510 # Rest mass of individual H2+, in amu m_mev = 1876.9729554 # Rest mass of individual H2+, in MeV/c^2 px_val = np.array(datasource["Step#{}".format(step)]["px"]) py_val = np.array(datasource["Step#{}".format(step)]["py"]) pz_val = np.array(datasource["Step#{}".format(step)]["pz"]) betagamma = np.sqrt( np.square(px_val) + np.square(py_val) + np.square(pz_val)) energy = (np.sqrt( np.square(betagamma * m_mev) + np.square(m_mev)) - m_mev) / m_amu # MeV/amu plot_data["energy"] = np.append(plot_data["energy"], energy) if self._settings["intensity"]: # Power deposition of a single h2+ particle (need to use full energy here!) (W) power = q_macro * f_cyclo * energy * 1e6 * m_amu * duty_factor plot_data["power"] = np.append(plot_data["power"], power) # Radii (m) r = np.sqrt(np.square(x_val) + np.square(y_val)) plot_data["R"] = np.append(plot_data["R"], r) # Add centroid coordinates if self._settings["centroid"] or self._settings["turnsep"]: plot_data["xCentroid"][step] = np.mean(x_val) plot_data["yCentroid"][step] = np.mean(y_val) # Calculate turn separation (as close as possible to pos x-axis for now, arbitrary angle later? -DW) if self._settings["turnsep"]: azimuth = np.rad2deg( np.arctan2(plot_data["yCentroid"][step], plot_data["xCentroid"][step])) azimuths[step] = azimuth r_temp = np.sqrt( np.square(plot_data["xCentroid"][step]) + np.square(plot_data["yCentroid"][step])) r_temps[step] = r_temp if azimuth > 0 and save_r: save_r = False r_tsep.append(r_temp) if azimuth < 0: save_r = True # if step >= (16 * 95) + 6 and step % 16 == 6 and self._settings["turnsep"]: # r = np.sqrt(np.square(np.mean(x_val)) + np.square(np.mean(y_val))) # plot_data["R"] = np.append(plot_data["R"], r) # if step > (16 * 95) + 6 and step % 16 == 6 and self._settings["turnsep"]: # index += 1 # difference = np.abs(plot_data["R"][index-1] - plot_data["R"][index]) # plot_data["turnSep"] = np.append(plot_data["turnSep"], difference) plots["plot_data{}".format(num)] = plot_data num += 1 self._parent.send_status("Saving plot(s)...") # Save plots as separate images, with appropriate titles if self._settings["rms"]: _xlim = 62.2 _ylim = 6.0 _figsize = (7, 5) _fs = 12 fig = plt.figure(figsize=_figsize) plt.rc( 'font', **{ 'family': 'serif', 'serif': ['Computer Modern'], 'weight': 100, 'size': _fs }) plt.rc('text', usetex=True) plt.rc('grid', linestyle=':') plt.rc('ytick', labelsize=_fs) plt.rc('xtick', labelsize=_fs) ax1 = plt.subplot(311) plt.title("RMS Beam Size (mm)") for n in range(num): plt.plot(plots["plot_data{}".format(n)]["energy"], plots["plot_data{}".format(n)]["xRMS"], lw=0.8, label=plots["plot_data{}".format(n)]["name"]) # print("Mean x RMS: {}".format(np.mean(plots["plot_data{}".format(n)]["xRMS"][40:]))) ax1.get_yaxis().set_major_locator(LinearLocator(numticks=5)) ax1.get_yaxis().set_major_formatter(FormatStrFormatter('%.1f')) ax1.tick_params(labelbottom=False) ax1.set_xlim([0, _xlim]) # ax1.set_ylim([0, _ylim]) ax1.set_ylim([0, 4.0]) plt.grid() plt.ylabel("Transversal") ax2 = plt.subplot(312, sharex=ax1) for n in range(num): plt.plot(plots["plot_data{}".format(n)]["energy"], plots["plot_data{}".format(n)]["yRMS"], lw=0.8, label=plots["plot_data{}".format(n)]["name"]) # print("Mean y RMS: {}".format(np.mean(plots["plot_data{}".format(n)]["yRMS"][40:]))) plt.legend(loc=9) ax2.get_yaxis().set_major_locator(LinearLocator(numticks=5)) ax2.get_yaxis().set_major_formatter(FormatStrFormatter('%.1f')) ax2.tick_params(labelbottom=False) ax2.set_xlim([0, _xlim]) ax2.set_ylim([0, _ylim]) plt.grid() plt.ylabel("Longitudinal") ax3 = plt.subplot(313, sharex=ax1) for n in range(num): plt.plot(plots["plot_data{}".format(n)]["energy"], plots["plot_data{}".format(n)]["zRMS"], lw=0.8, label=plots["plot_data{}".format(n)]["name"]) # print("Mean z RMS: {}".format(np.mean(plots["plot_data{}".format(n)]["zRMS"][40:]))) ax3.get_yaxis().set_major_locator(LinearLocator(numticks=5)) ax3.get_yaxis().set_major_formatter(FormatStrFormatter('%.1f')) ax3.set_xlim([0, _xlim]) ax3.set_ylim([0, _ylim]) plt.grid() plt.xlabel("Energy (MeV/amu)") plt.ylabel("Vertical") # fig.tight_layout() fig.savefig(self._filename[0] + '_rmsBeamSize.png', dpi=1200, bbox_inches='tight') if self._settings["halo"]: _xlim = 62.2 _ylim = 7.0 _figsize = (7, 5) _fs = 12 fig = plt.figure(figsize=_figsize) plt.rc( 'font', **{ 'family': 'serif', 'serif': ['Computer Modern'], 'weight': 100, 'size': _fs }) plt.rc('text', usetex=True) plt.rc('grid', linestyle=':') plt.rc('ytick', labelsize=_fs) plt.rc('xtick', labelsize=_fs) ax1 = plt.subplot(311) plt.title("Halo Parameter") for n in range(num): plt.plot(plots["plot_data{}".format(n)]["energy"], plots["plot_data{}".format(n)]["xHalo"], lw=0.8, label=plots["plot_data{}".format(n)]["name"]) ax1.get_yaxis().set_major_locator(LinearLocator(numticks=5)) ax1.tick_params(labelbottom=False) ax1.set_ylim([0, _ylim]) ax1.set_xlim([0, _xlim]) plt.grid() plt.ylabel("Transversal") ax2 = plt.subplot(312, sharex=ax1) for n in range(num): plt.plot(plots["plot_data{}".format(n)]["energy"], plots["plot_data{}".format(n)]["yHalo"], lw=0.8, label=plots["plot_data{}".format(n)]["name"]) plt.legend(loc=9) ax2.get_yaxis().set_major_locator(LinearLocator(numticks=5)) ax2.tick_params(labelbottom=False) ax2.set_ylim([0, _ylim]) ax2.set_xlim([0, _xlim]) plt.grid() plt.ylabel("Longitudinal") ax3 = plt.subplot(313, sharex=ax1) for n in range(num): plt.plot(plots["plot_data{}".format(n)]["energy"], plots["plot_data{}".format(n)]["zHalo"], lw=0.8, label=plots["plot_data{}".format(n)]["name"]) ax3.get_yaxis().set_major_locator(LinearLocator(numticks=5)) ax3.set_ylim([0, _ylim]) ax3.set_xlim([0, _xlim]) plt.grid() plt.xlabel("Energy (MeV/amu)") plt.ylabel("Vertical") # fig.tight_layout() fig.savefig(self._filename[0] + '_haloParameter.png', bbox_inches='tight', dpi=1200) if self._settings["centroid"]: fig = plt.figure() plt.rc('font', **{'family': 'serif', 'serif': ['Computer Modern']}) plt.rc('text', usetex=True) plt.rc('grid', linestyle=':') plt.title("Top-down view of Centroid Position") for n in range(num): plt.plot(plots["plot_data{}".format(n)]["xCentroid"], plots["plot_data{}".format(n)]["yCentroid"], 'o', ms=0.5, label=plots["plot_data{}".format(n)]["name"]) plt.legend() ax = plt.gca() ax.set_aspect('equal') plt.grid() plt.xlabel("Horizontal (m)") plt.ylabel("Longitudinal (m)") fig.tight_layout() fig.savefig(self._filename[0] + '_centroidPosition.png', bbox_inches='tight', dpi=1200) # TODO: Fix turn separation to allow any number of steps if self._settings["turnsep"]: fig = plt.figure() plt.rc('font', **{'family': 'serif', 'serif': ['Computer Modern']}) plt.rc('text', usetex=True) plt.rc('grid', linestyle=':') plt.title("Turn Separation") plt.plot(1000.0 * np.diff(r_tsep)) # plt.plot(range(96, 105), 1000.0 * plot_data["turnSep"], 'k', lw=0.8) plt.grid() plt.xlabel("Turn Number") plt.ylabel("Separation (mm)") fig.savefig(self._filename[0] + '_turnSeparation.png', bbox_inches='tight', dpi=1200) if self._settings["energyHist"]: fig = plt.figure() plt.rc('font', **{'family': 'serif', 'serif': ['Computer Modern']}) plt.rc('text', usetex=True) plt.rc('grid', linestyle=':') plt.title("Particle Energy") for n in range(num): plt.hist( plots["plot_data{}".format(n)]["energy"], bins=100, histtype='step', # weights=np.full_like(plots["plot_data{}".format(n)]["energy"], 6348), label="{}, total particles = {}".format( plots["plot_data{}".format(n)]["name"], len(plots["plot_data{}".format(n)]["energy"]))) plt.legend() plt.grid() plt.xlabel("Energy (MeV/amu)") plt.ylabel(r"Particle Density (a.u.)") fig.tight_layout() fig.savefig(self._filename[0] + '_energy.png', bbox_inches='tight', dpi=1200) if self._settings["intensity"]: fig = plt.figure() plt.rc('font', **{'family': 'serif', 'serif': ['Computer Modern']}) plt.rc('text', usetex=True) plt.rc('grid', linestyle=':') plt.title("Histogram of the Beam Power (0.5 mm Bins)") bin_width = 0.5 # mm for n in range(num): radii = plots["plot_data{}".format(n)]["R"] * 1.0e3 # m --> mm r_len = radii.max() - radii.min() n_bins = int(np.round(r_len / bin_width, 0)) print("Numerical bin width = {:.4f} mm".format(r_len / n_bins)) power, bins = np.histogram( radii, bins=n_bins, weights=plots["plot_data{}".format(n)]["power"]) # temp_bins = bins[200:-1] # temp_power = power[200:] # # idx = np.where(temp_bins <= 1935) # 1940 for Probe25 # # temp_bins = temp_bins[idx] # temp_power = temp_power[idx] # # print("Min R =", temp_bins[np.where(temp_power == np.min(temp_power))], "mm\n") # print("Min P =", temp_power[np.where(temp_power == np.min(temp_power))], "W\n") plt.hist(bins[:-1], bins, weights=power, label=plots["plot_data{}".format(n)]["name"], alpha=0.3, log=True) plt.gca().axhline(200.0, linestyle="--", color="black", linewidth=1.0, label="200 W Limit") plt.legend(loc=2) plt.grid() plt.xlabel("Radius (mm)") plt.ylabel("Beam Power (W)") fig.tight_layout() fig.savefig(self._filename[0] + '_power.png', bbox_inches='tight', dpi=1200) if self._settings["xz"]: fig = plt.figure() plt.rc('font', **{'family': 'serif', 'serif': ['Computer Modern']}) plt.rc('text', usetex=True) plt.rc('grid', linestyle=':') plt.title("Probe Scatter Plot") ax = plt.gca() for n in range(num): plt.plot( plots["plot_data{}".format(n)]["R"] * 1000.0, # m --> mm plots["plot_data{}".format(n)]["coords"] * 1000.0, # m --> mm 'o', alpha=0.6, markersize=0.005, label=plots["plot_data{}".format(n)]["name"]) plt.grid() ax.set_aspect('equal') plt.xlabel("Radius (mm)") plt.ylabel("Vertical (mm)") fig.tight_layout() fig.savefig(self._filename[0] + '_RZ.png', bbox_inches='tight', dpi=1200) self._parent.send_status("Plot(s) saved successfully!") @staticmethod def rms(nparray): mean_sqrd = np.mean(np.square(nparray)) return np.sqrt(mean_sqrd) @staticmethod def halo(nparray): mean_sqrd = np.mean(np.square(nparray)) mean_frth = np.mean(np.square(np.square(nparray))) return mean_frth / (np.square(mean_sqrd)) - 1.0 def run(self): # --- Calculate the positions to center the window --- # screen_size = self._parent.screen_size() _x = 0.5 * (screen_size.width() - self._beamCharWindow.width()) _y = 0.5 * (screen_size.height() - self._beamCharWindow.height()) # --- Show the GUI --- # self._beamCharWindow.show() self._beamCharWindow.move(_x, _y) def open_gui(self): options = QFileDialog.Options() options |= QFileDialog.DontUseNativeDialog self._filename = QFileDialog.getSaveFileName(caption="Saving plots...", options=options, filter="Image (*.png)") self.run()
class easyInput: _display = Display(os.environ['DISPLAY']) def __init__(self): self.app = QApplication(sys.argv) self.mainWindow = QMainWindow() self.ui = Ui_mainWindow() self.ui.setupUi(self.mainWindow) self.mainWindow.setWindowTitle("方便输入") self.config_init() def config_init(self): '''与配置文件有关的初始化''' self.config = configparser.ConfigParser() self.config.read('.easy_input_rc') self.ui.lineEdit.mouseDoubleClickEvent = self.config_panel # 加载设置窗口 self.Dialog = QMainWindow() self.ui2 = Ui_config_panel() self.ui2.setupUi(self.Dialog) self.Dialog.setWindowTitle("设置") self.test_text = "我能吞下玻璃,而不伤身体" self.tmpText = "我能吞下玻璃,而不伤身体" def value_change(self): '''当设置的值改变的时候获取改变 并从新加载输入窗口设置''' self.font_size = self.ui2.font_size.value() self.windowW = self.ui2.windowW.value() self.windowH = self.ui2.windowH.value() self.windowOpacity = self.ui2.windowOpacity.value() self.font_color = self.ui2.font_color.text() self.background = self.ui2.background.text() self._lodeconfig() def save(self): ''' 点击设置中的保存键后 配置写入文件 关闭设置''' self._writeconfig() self.Dialog.close() def close(self, close_even): ''' 设置界面关闭后 恢复输入框的状态 即打开设置之前的状态''' if close_even.isAccepted() is True: # 设置输入框可操作 self.ui.lineEdit.setEnabled(True) # 恢复输入框里面的文字 self.ui.lineEdit.setText(self.tmpText) def close_back(self): '''没有保存设置恢复配置文件中的设置''' self._getconfig() self._lodeconfig() self.Dialog.close() def ch_backcolor(self): col = QColorDialog.getColor() if col.isValid(): self.ui2.background.setText(col.name()) def ch_font_color(self): col = QColorDialog.getColor() if col.isValid(): self.ui2.font_color.setText(col.name()) def config_panel(self, *kw): '''显示面板''' self.ui2.font_size.setValue(self.font_size) self.ui2.windowW.setValue(self.windowW) self.ui2.windowH.setValue(self.windowH) self.ui2.windowOpacity.setValue(self.windowOpacity) self.ui2.font_color.setText(self.font_color) self.ui2.background.setText(self.background) self.ui2.font_size.valueChanged.connect(self.value_change) self.ui2.windowW.valueChanged.connect(self.value_change) self.ui2.windowH.valueChanged.connect(self.value_change) self.ui2.windowOpacity.valueChanged.connect(self.value_change) self.ui2.font_color.textChanged.connect(self.value_change) self.ui2.background.textChanged.connect(self.value_change) self.ui2.save.clicked.connect(self.save) self.ui2.close.clicked.connect(self.close_back) self.ui2.ch_backcolor.clicked.connect(self.ch_backcolor) self.ui2.ch_font_color.clicked.connect(self.ch_font_color) self.Dialog.closeEvent = self.close self.Dialog.show() def _getconfig(self): '''获取配置文件''' self.font_size = 23 # 字体大小 self.windowW = 450 self.windowH = 60 # 窗口大小 self.windowOpacity = 0.7 # 窗口透明度 self.background = "#2F4F4F" # 背景颜色 self.font_color = "rgb(230,230,250)" # 字体颜色 if 'info' in self.config.sections(): self.font_size = int(self.config.get("info", "font_size")) self.windowW = int(self.config.get("info", "windowW")) self.windowH = int(self.config.get("info", "windowH")) self.windowOpacity = float(self.config.get("info", "windowOpacity")) self.background = self.config.get("info", "background") self.font_color = self.config.get("info", "font_color") else: self.config.add_section("info") def _writeconfig(self): '''写入配置文件''' self.config.set("info", "font_size", str(self.font_size)) self.config.set("info", "windowW", str(self.windowW)) self.config.set("info", "windowH", str(self.windowH)) self.config.set("info", "windowOpacity", str(self.windowOpacity)) self.config.set("info", "background", self.background) self.config.set("info", "font_color", self.font_color) self.config.write(open(".easy_input_rc", "w")) def _lodeconfig(self): '''根据配置文件重新设置界面''' self.mainWindow.resize(self.windowW, self.windowH) self.mainWindow.setMinimumSize(QtCore.QSize(self.windowW, self.windowH)) self.mainWindow.setMaximumSize(QtCore.QSize(self.windowW, self.windowH)) self.ui.lineEdit.setGeometry( QtCore.QRect(0, 0, self.windowW, self.windowH)) self.ui.lineEdit.setMinimumSize( QtCore.QSize(self.windowW, self.windowH)) self.ui.lineEdit.setMaximumSize( QtCore.QSize(self.windowW, self.windowH)) font = QtGui.QFont() font.setPointSize(self.font_size) self.ui.lineEdit.setFont(font) self.mainWindow.setWindowOpacity(self.windowOpacity) self.ui.lineEdit.setStyleSheet("background:{};color:{};".format( self.background, self.font_color)) self.ui2.ch_font_color.setStyleSheet("background:{}".format( self.font_color)) self.ui2.ch_backcolor.setStyleSheet("background:{};".format( self.background)) def run(self): '''运行并显示窗口''' self.mainWindow.move(*self._position()) # 输入结束信号连接run槽 self.ui.lineEdit.editingFinished.connect(self.call_action) # 重写keyPressEvent self.ui.lineEdit.keyPressEvent = self.keypressevent( self.ui.lineEdit.keyPressEvent) # 去除顶栏 和 一直在顶部 self.mainWindow.setWindowFlags(QtCore.Qt.FramelessWindowHint | QtCore.Qt.WindowStaysOnTopHint) self._getconfig() self._lodeconfig() self._writeconfig() self.mainWindow.show() sys.exit(self.app.exec_()) @classmethod def _position(cls): '''获取鼠标的绝对位置''' pos_info = cls._display.screen().root.query_pointer()._data return pos_info['root_x'], pos_info['root_y'] def call_action(self): ''' 输入窗口认为自己输入结束后的动作 用户按下回车 输入框失去焦点''' # 如果是因为设置界面弹出的话 if self.Dialog.isVisible(): # 设置输入框不可操作 self.ui.lineEdit.setDisabled(True) self.tmpText = self.ui.lineEdit.text() self.ui.lineEdit.setText(self.test_text) else: text = self.ui.lineEdit.text() self.write_paste(text) self.app.exit() def keypressevent(self, fun): def warr(event): if event.key() == QtCore.Qt.Key_Escape: self.call_action() else: fun(event) return warr @staticmethod def write_paste(text): pyperclip.copy(text) print("假设我已经写入到了剪切板")
class SettingsUI(object): def __init__(self): pygame.init() pygame.joystick.init() self.window = QMainWindow() self.ui = Ui_MainWindow() self.ui.setupUi(self.window) self.detection_thread = None # Register actions self.ui.b_refreshImage.clicked.connect(self.fill_screen_cap) self.ui.b_save.clicked.connect(self.save_settings) self.ui.b_refreshDevices.clicked.connect(self.fill_device_list) self.ui.slider_left.valueChanged.connect(self.modify_border) self.ui.slider_right.valueChanged.connect(self.modify_border) self.ui.slider_top.valueChanged.connect(self.modify_border) self.ui.slider_bottom.valueChanged.connect(self.modify_border) self.ui.cb_screen.currentIndexChanged.connect(self.select_screen) self.ui.b_refreshDevices.clicked.connect(self.fill_device_list) self.ui.b_setLeftIndicator.clicked.connect(lambda: self.start_detection_thread(self.ui.e_leftIndicator)) self.ui.b_setRightIndicator.clicked.connect(lambda: self.start_detection_thread(self.ui.e_rightIndicator)) self.ui.b_setAutopilot.clicked.connect(lambda: self.start_detection_thread(self.ui.e_autopilot)) self.ui.b_setSteering.clicked.connect(lambda: self.start_detection_thread(self.ui.e_steering)) self.ui.b_setThrottle.clicked.connect(lambda: self.start_detection_thread(self.ui.e_throttle)) def show(self): self._load_settings() self.window.show() def hide(self): self.window.close() def _load_settings(self): settings = Settings() # Screen data image_front_border_left = settings.get_value(settings.IMAGE_FRONT_BORDER_LEFT) image_front_border_right = settings.get_value(settings.IMAGE_FRONT_BORDER_RIGHT) image_front_border_top = settings.get_value(settings.IMAGE_FRONT_BORDER_TOP) image_front_border_bottom = settings.get_value(settings.IMAGE_FRONT_BORDER_BOTTOM) # Controller binding vjoy = settings.get_value(settings.VJOY_DEVICE) autopilot = settings.get_value(settings.AUTOPILOT) left_indicator = settings.get_value(settings.LEFT_INDICATOR) right_indicator = settings.get_value(settings.RIGHT_INDICATOR) steering_axis = settings.get_value(settings.STEERING_AXIS) throttle_axis = settings.get_value(settings.THROTTLE_AXIS) self.fill_screen_list() self.fill_device_list() self.select_screen() # Set scrollbar values if image_front_border_right is not None: self.ui.slider_right.setValue(int(image_front_border_right)) else: self.ui.slider_right.setValue(self.ui.slider_right.maximum()) if image_front_border_left is not None: self.ui.slider_left.setValue(int(image_front_border_left)) else: self.ui.slider_left.setValue(self.ui.slider_left.minimum()) if image_front_border_bottom is not None: self.ui.slider_bottom.setValue(int(image_front_border_bottom)) else: self.ui.slider_bottom.setValue(self.ui.slider_bottom.maximum()) if image_front_border_top is not None: self.ui.slider_top.setValue(int(image_front_border_top)) else: self.ui.slider_top.setValue(self.ui.slider_top.minimum()) # Display key bindings if vjoy is not None: self.ui.e_vjoy.setText(str(vjoy)) if autopilot is not None: self.ui.e_autopilot.setText(str(autopilot)) if left_indicator is not None: self.ui.e_leftIndicator.setText(str(left_indicator)) if right_indicator is not None: self.ui.e_rightIndicator.setText(str(right_indicator)) if steering_axis is not None: self.ui.e_steering.setText(str(steering_axis)) if throttle_axis is not None: self.ui.e_throttle.setText(str(throttle_axis)) self.fill_screen_cap() def fill_device_list(self): if pygame.joystick.get_init(): pygame.joystick.quit() pygame.joystick.init() self.ui.cb_devices.clear() joystick_count = pygame.joystick.get_count() if joystick_count > 0: for i in range(joystick_count): self.ui.cb_devices.addItem(pygame.joystick.Joystick(i).get_name()) device = Settings().get_value(Settings.CONTROLLER) if device is not None and int(device) < joystick_count: self.ui.cb_devices.setCurrentIndex(int(device)) def fill_screen_list(self): # TODO: SCREEN settings value gets overwritten self.ui.cb_screen.clear() for i in range(len(QApplication.screens())): self.ui.cb_screen.addItem("Screen %d" % (i+1)) screen = Settings().get_value(Settings.SCREEN) if screen is not None: self.ui.cb_screen.setCurrentIndex(int(screen)) def select_screen(self): screen_id = self.ui.cb_screen.currentIndex() screen_res = QApplication.desktop().screenGeometry(screen_id) Settings().set_value(Settings.SCREEN, screen_id) self.ui.slider_left.setMaximum(screen_res.width()) self.ui.slider_right.setMaximum(screen_res.width()) self.ui.slider_top.setMaximum(screen_res.height()) self.ui.slider_bottom.setMaximum(screen_res.height()) def save_settings(self): settings = Settings() settings.set_value(settings.IMAGE_FRONT_BORDER_LEFT, self.ui.slider_left.value()) settings.set_value(settings.IMAGE_FRONT_BORDER_RIGHT, self.ui.slider_right.value()) settings.set_value(settings.IMAGE_FRONT_BORDER_TOP, self.ui.slider_top.value()) settings.set_value(settings.IMAGE_FRONT_BORDER_BOTTOM, self.ui.slider_bottom.value()) settings.set_value(settings.SCREEN, self.ui.cb_screen.currentIndex()) settings.set_value(settings.CONTROLLER, self.ui.cb_devices.currentIndex()) settings.set_value(settings.VJOY_DEVICE, self.ui.e_vjoy.text()) settings.set_value(settings.AUTOPILOT, self.ui.e_autopilot.text()) settings.set_value(settings.LEFT_INDICATOR, self.ui.e_leftIndicator.text()) settings.set_value(settings.RIGHT_INDICATOR, self.ui.e_rightIndicator.text()) settings.set_value(settings.STEERING_AXIS, self.ui.e_steering.text()) settings.set_value(settings.THROTTLE_AXIS, self.ui.e_throttle.text()) self.hide() def fill_screen_cap(self): # TODO: Screen 2 shows black image slider_left = self.ui.slider_left.value() slider_right = self.ui.slider_right.value() slider_top = self.ui.slider_top.value() slider_bottom = self.ui.slider_bottom.value() frame_raw = ImageGrab.grab(bbox=functions.get_screen_bbox()) frame = np.uint8(frame_raw) frame = cv2.rectangle(frame, (slider_left, slider_top), (slider_right, slider_bottom), (255, 0, 0), 4) qimg = QtGui.QImage(frame, frame.shape[1], frame.shape[0], frame.strides[0], QtGui.QImage.Format_RGB888) pixmap = QtGui.QPixmap(qimg) pixmap = pixmap.scaledToHeight(self.ui.screen_cap.height()) self.ui.screen_cap.setPixmap(pixmap) def modify_border(self): slider_left = self.ui.slider_left.value() slider_right = self.ui.slider_right.value() slider_top = self.ui.slider_top.value() slider_bottom = self.ui.slider_bottom.value() if slider_left > slider_right: self.ui.slider_left.setValue(slider_right) if slider_top > slider_bottom: self.ui.slider_top.setValue(slider_bottom) self.fill_screen_cap() def start_detection_thread(self, field): if self.detection_thread is not None and self.detection_thread.is_alive(): self.detection_thread.stop() self.detection_thread = DetectorThread(self.ui.cb_devices.currentIndex(), field) self.detection_thread.start()
class Plotter(BasePlotter): def __init__(self, n_rows=1, n_cols=1, try_qt=True, offscreen=None, **kwargs): if offscreen is None: self.offscreen = OFF_SCREEN else: self.offscreen = offscreen self.try_qt = try_qt self.use_qt = has_pyqt and try_qt and offscreen is not True # Prepare qt iren = None ren_win = None if self.use_qt: self.app = _get_qt_app() self.app_window = QMainWindow() self.frame = QFrame() self.frame.setFrameStyle(QFrame.NoFrame) self.qt_ren = QVTKRenderWindowInteractor(parent=self.frame) self.vlayout = QVBoxLayout() self.vlayout.addWidget(self.qt_ren) self.frame.setLayout(self.vlayout) self.app_window.setCentralWidget(self.frame) ren_win = wrap_vtk(self.qt_ren.GetRenderWindow()) iren = ren_win.GetInteractor() super().__init__(n_rows=n_rows, n_cols=n_cols, ren_win=ren_win, iren=iren, offscreen=offscreen, **kwargs) # Exit with 'q' and 'e' self.iren.AddObserver("KeyPressEvent", self.key_quit) def show(self, interactive=True, embed_nb=False, scale=None, transparent_bg=True, as_mpl=False): embed_nb = embed_nb and in_notebook() if embed_nb and interactive and not has_panel: interactive = False if self.use_qt and not as_mpl and not embed_nb and \ self.offscreen is not True: self.iren.Initialize() if not interactive: self.iren.SetInteractorStyle(None) self.app_window.show() self.qt_ren.show() else: return super().show(interactive=interactive, embed_nb=embed_nb, scale=scale, transparent_bg=transparent_bg, as_mpl=as_mpl) def key_quit(self, obj=None, event=None): try: key = self.iren.GetKeySym().lower() if key in ['q', 'e']: self.close() except: pass def close(self, *args): super().close() if self.use_qt: self.app_window.close()
fbfoo = utilities.path_to_output(foo_path) assert fbfoo.filename() == f_foo fbfoo.writeLine('some data') assert os.path.isfile(foo_path) fbbar = utilities.related_output(fbfoo,'bar') assert fbbar.filename() == f_bar fbbar.writeLine('some data') assert os.path.isfile(bar_path) # Message routines utilities.info_msg('About to beep', 'When you dismiss this message') utilities.beep() assert utilities.ok_cancel_msg('Did you hear a beep?', 'OK for yes, Cancel for no',parent=mw) utilities.warning_msg('This is a warning','the very last warning',parent=mw) assert utilities.save_discard_cancel_msg('Click SAVE','no parent argument') assert not utilities.save_discard_cancel_msg('Click DISCARD (dont save?)','does have parent',parent=mw) assert utilities.save_discard_cancel_msg('Click CANCEL','no parent') is None (tf, str) = utilities.get_find_string('Press CANCEL','preptext',mw) assert not tf (tf, str) = utilities.get_find_string('Press Find','REPLACE-WITH-FOO',mw) assert tf assert str == 'FOO' mw.close() app.quit() os.remove(foo_path) os.remove(bar_path) # idle a bit after quit to let garbage be collected from PyQt5.QtTest import QTest QTest.qWait(300)
class GeneratorGUI(object): def __init__(self, parent): self._parent = parent # Initialize GUI self._generate_main = QMainWindow() self._generate_mainGUI = Ui_Generate_Main() self._generate_mainGUI.setupUi(self._generate_main) self._generate_envelope = QMainWindow() self._generate_envelopeGUI = Ui_Generate_Envelope() self._generate_envelopeGUI.setupUi(self._generate_envelope) self._generate_twiss = QMainWindow() self._generate_twissGUI = Ui_Generate_Twiss() self._generate_twissGUI.setupUi(self._generate_twiss) self._generate_error = QMainWindow() self._generate_errorGUI = Ui_Generate_Error() self._generate_errorGUI.setupUi(self._generate_error) # Connect buttons and signals self._settings = {} self.apply_settings_main() self._generate_mainGUI.buttonBox.accepted.connect(self.callback_ok_main) self._generate_mainGUI.buttonBox.rejected.connect(self._generate_main.close) self._generate_envelopeGUI.buttonBox.accepted.connect(self.callback_ok_envelope) self._generate_envelopeGUI.buttonBox.rejected.connect(self._generate_envelope.close) self._generate_twissGUI.buttonBox.accepted.connect(self.callback_ok_twiss) self._generate_twissGUI.buttonBox.rejected.connect(self._generate_twiss.close) self._generate_errorGUI.buttonBox.accepted.connect(self._generate_error.close) self._generate_envelopeGUI.zpos.currentIndexChanged.connect(self.change_zpos_envelope) self._generate_envelopeGUI.zmom.currentIndexChanged.connect(self.change_zmom_envelope) self._generate_envelopeGUI.xydist.currentIndexChanged.connect(self.change_xy_envelope) self._generate_twissGUI.zpos.currentIndexChanged.connect(self.change_zpos_twiss) self._generate_twissGUI.zmom.currentIndexChanged.connect(self.change_zmom_twiss) self._generate_twissGUI.xydist.currentIndexChanged.connect(self.change_xy_twiss) self._generate_envelopeGUI.checkBox.stateChanged.connect(self.sym_envelope) self._generate_twissGUI.checkBox.stateChanged.connect(self.sym_twiss) self.data = {} def apply_settings_main(self): # Number of particles: self._settings["numpart"] = self._generate_mainGUI.lineEdit.text() # Species: info = str(self._generate_mainGUI.comboBox.currentText()) if info == "Proton": self._settings["species"] = "proton" elif info == "Electron": self._settings["species"] = "electron" elif info == "Dihydrogen cation": self._settings["species"] = "H2_1+" elif info == "Alpha particle": self._settings["species"] = "4He_2+" # Energy: self._settings["energy"] = self._generate_mainGUI.energy.text() # Input parameter type: self._settings["type"] = str(self._generate_mainGUI.comboBox_2.currentText()) def apply_settings_envelope(self): # Longitudinal parameters self._settings["zpos"] = str(self._generate_envelopeGUI.zpos.currentText()) self._settings["zmom"] = str(self._generate_envelopeGUI.zmom.currentText()) self._settings["ze"] = self._generate_envelopeGUI.ze.text() self._settings["zr"] = self._generate_envelopeGUI.zr.text() self._settings["zstddev"] = [self._generate_envelopeGUI.zpstddev.text(), self._generate_envelopeGUI.zmstddev.text()] # Transverse parameters self._settings["xydist"] = str(self._generate_envelopeGUI.xydist.currentText()) self._settings["eps"] = [self._generate_envelopeGUI.xe.text(), self._generate_envelopeGUI.ye.text()] self._settings["r"] = [self._generate_envelopeGUI.xr.text(), self._generate_envelopeGUI.yr.text()] self._settings["rp"] = [self._generate_envelopeGUI.xrp.text(), self._generate_envelopeGUI.yrp.text()] self._settings["xystddev"] = [self._generate_envelopeGUI.xstddev.text(), self._generate_envelopeGUI.xpstddev.text(), self._generate_envelopeGUI.ystddev.text(), self._generate_envelopeGUI.ypstddev.text()] def apply_settings_twiss(self): # Convert from Twiss to envelope zp_beta = self._generate_twissGUI.zpb.text() ze = self._generate_twissGUI.ze.text() if zp_beta != "" and ze != "": zp_beta = float(zp_beta) ze = float(ze) rz = np.sqrt(zp_beta * ze) else: rz = float(self._generate_twissGUI.length.text()) xa = float(self._generate_twissGUI.xa.text()) xb = float(self._generate_twissGUI.xb.text()) xe = float(self._generate_twissGUI.xe.text()) rx = np.sqrt(xb * xe) rxp = -xa * rx / xb ya = float(self._generate_twissGUI.ya.text()) yb = float(self._generate_twissGUI.yb.text()) ye = float(self._generate_twissGUI.ye.text()) ry = np.sqrt(yb * ye) ryp = -ya * ry / yb # Longitudinal parameters self._settings["zpos"] = str(self._generate_twissGUI.zpos.currentText()) self._settings["zmom"] = str(self._generate_twissGUI.zmom.currentText()) self._settings["ze"] = ze self._settings["zr"] = rz self._settings["zstddev"] = [self._generate_envelopeGUI.zpstddev.text(), self._generate_envelopeGUI.zmstddev.text()] # Transverse parameters self._settings["xydist"] = str(self._generate_twissGUI.xydist.currentText()) self._settings["eps"] = [xe, ye] self._settings["r"] = [rx, ry] self._settings["rp"] = [rxp, ryp] if self._generate_twissGUI.xydist.currentText() == "Gaussian": self._settings["xystddev"] = [self._generate_twissGUI.xstddev.text(), self._generate_twissGUI.xpstddev.text(), self._generate_twissGUI.ystddev.text(), self._generate_twissGUI.ypstddev.text()] def callback_ok_main(self): self.apply_settings_main() if self._settings["numpart"] == "" or self._settings["energy"] == "": self.run_error() else: # Open either Twiss or Envelope menu if self._settings["type"] == "Envelope": self.run_envelope() elif self._settings["type"] == "Twiss": self.run_twiss() self._generate_main.close() def callback_ok_envelope(self): self.apply_settings_envelope() if self._settings["eps"] == ["", ""] or self._settings["r"] == ["", ""] or self._settings["rp"] == ["", ""]: self.run_error() else: if self._settings["zpos"] == "Constant" and self._settings["zmom"] == "Constant": g = GenerateDistribution(self._settings["numpart"], self._settings["species"], self._settings["energy"], self._settings["zpos"], self._settings["zmom"], self._settings["zr"]) elif self._settings["zpos"] == "Gaussian on ellipse" or self._settings["zmom"] == "Gaussian on ellipse": g = GenerateDistribution(self._settings["numpart"], self._settings["species"], self._settings["energy"], self._settings["zpos"], self._settings["zmom"], self._settings["zr"], self._settings["ze"], self._settings["zstddev"]) else: g = GenerateDistribution(self._settings["numpart"], self._settings["species"], self._settings["energy"], self._settings["zpos"], self._settings["zmom"], self._settings["zr"], self._settings["ze"]) if self._settings["xydist"] == "Uniform": self.data = g.generate_uniform(self._settings["r"], self._settings["rp"], self._settings["eps"]) elif self._settings["xydist"] == "Gaussian": self.data = g.generate_gaussian(self._settings["r"], self._settings["rp"], self._settings["eps"], self._settings["xystddev"]) elif self._settings["xydist"] == "Waterbag": self.data = g.generate_waterbag(self._settings["r"], self._settings["rp"], self._settings["eps"]) elif self._settings["xydist"] == "Parabolic": self.data = g.generate_parabolic(self._settings["r"], self._settings["rp"], self._settings["eps"]) self._generate_envelope.close() self._parent.add_generated_dataset(data=self.data, settings=self._settings) def callback_ok_twiss(self): self.apply_settings_twiss() if self._settings["eps"] == ["", ""] or self._settings["r"] == ["", ""] or self._settings["rp"] == ["", ""]: self.run_error() else: if self._settings["zpos"] == "Constant" and self._settings["zmom"] == "Constant": g = GenerateDistribution(self._settings["numpart"], self._settings["species"], self._settings["energy"], self._settings["zpos"], self._settings["zmom"], self._settings["zr"]) elif self._settings["zpos"] == "Gaussian on ellipse" or self._settings["zmom"] == "Gaussian on ellipse": g = GenerateDistribution(self._settings["numpart"], self._settings["species"], self._settings["energy"], self._settings["zpos"], self._settings["zmom"], self._settings["zr"], self._settings["ze"], self._settings["zstddev"]) else: g = GenerateDistribution(self._settings["numpart"], self._settings["species"], self._settings["energy"], self._settings["zpos"], self._settings["zmom"], self._settings["zr"], self._settings["ze"]) if self._settings["xydist"] == "Uniform": self.data = g.generate_uniform(self._settings["r"], self._settings["rp"], self._settings["eps"]) elif self._settings["xydist"] == "Gaussian": self.data = g.generate_gaussian(self._settings["r"], self._settings["rp"], self._settings["eps"], self._settings["xystddev"]) elif self._settings["xydist"] == "Waterbag": self.data = g.generate_waterbag(self._settings["r"], self._settings["rp"], self._settings["eps"]) elif self._settings["xydist"] == "Parabolic": self.data = g.generate_parabolic(self._settings["r"], self._settings["rp"], self._settings["eps"]) self._generate_twiss.close() self._parent.add_generated_dataset(data=self.data, settings=self._settings) def change_zpos_envelope(self): info = str(self._generate_envelopeGUI.zpos.currentText()) if info != "Constant" and info != "Uniform along length": self._generate_envelopeGUI.ze.setEnabled(True) if info == "Gaussian on ellipse": self._generate_envelopeGUI.zpstddev.setEnabled(True) else: self._generate_envelopeGUI.zpstddev.setDisabled(True) else: self._generate_envelopeGUI.ze.setDisabled(True) self._generate_envelopeGUI.zpstddev.setDisabled(True) def change_zmom_envelope(self): info = str(self._generate_envelopeGUI.zmom.currentText()) if info != "Constant" and info != "Uniform along length": self._generate_envelopeGUI.ze.setEnabled(True) if info == "Gaussian on ellipse": self._generate_envelopeGUI.zmstddev.setEnabled(True) else: self._generate_envelopeGUI.zmstddev.setDisabled(True) else: self._generate_envelopeGUI.ze.setDisabled(True) self._generate_envelopeGUI.zmstddev.setDisabled(True) def change_xy_envelope(self): info = str(self._generate_envelopeGUI.xydist.currentText()) if info == "Gaussian": self._generate_envelopeGUI.xstddev.setEnabled(True) self._generate_envelopeGUI.xpstddev.setEnabled(True) self._generate_envelopeGUI.ystddev.setEnabled(True) self._generate_envelopeGUI.ypstddev.setEnabled(True) else: self._generate_envelopeGUI.xstddev.setDisabled(True) self._generate_envelopeGUI.xpstddev.setDisabled(True) self._generate_envelopeGUI.ystddev.setDisabled(True) self._generate_envelopeGUI.ypstddev.setDisabled(True) def change_zpos_twiss(self): info = str(self._generate_twissGUI.zpos.currentText()) if info != "Constant" and info != "Uniform along length": self._generate_twissGUI.ze.setEnabled(True) self._generate_twissGUI.zpa.setEnabled(True) self._generate_twissGUI.zpb.setEnabled(True) self._generate_twissGUI.length.setDisabled(True) if info == "Gaussian on ellipse": self._generate_twissGUI.zpstddev.setEnabled(True) else: self._generate_twissGUI.zpstddev.setDisabled(True) else: self._generate_twissGUI.ze.setDisabled(True) self._generate_twissGUI.zpa.setDisabled(True) self._generate_twissGUI.zpb.setDisabled(True) self._generate_twissGUI.length.setEnabled(True) self._generate_twissGUI.zpstddev.setDisabled(True) def change_zmom_twiss(self): info = str(self._generate_twissGUI.zmom.currentText()) if info != "Constant" and info != "Uniform along length": self._generate_twissGUI.ze.setEnabled(True) if info == "Gaussian on ellipse": self._generate_twissGUI.zmstddev.setEnabled(True) else: self._generate_twissGUI.zmstddev.setDisabled(True) else: self._generate_twissGUI.ze.setDisabled(True) self._generate_twissGUI.zmstddev.setDisabled(True) def change_xy_twiss(self): info = str(self._generate_twissGUI.xydist.currentText()) if info == "Gaussian": self._generate_twissGUI.xstddev.setEnabled(True) self._generate_twissGUI.xpstddev.setEnabled(True) self._generate_twissGUI.ystddev.setEnabled(True) self._generate_twissGUI.ypstddev.setEnabled(True) else: self._generate_twissGUI.xstddev.setDisabled(True) self._generate_twissGUI.xpstddev.setDisabled(True) self._generate_twissGUI.ystddev.setDisabled(True) self._generate_twissGUI.ypstddev.setDisabled(True) def sym_envelope(self): info = self._generate_envelopeGUI.checkBox.isChecked() if info: self.apply_settings_envelope() self._generate_envelopeGUI.yr.setText(self._settings["r"][0]) self._generate_envelopeGUI.yrp.setText(self._settings["rp"][0]) self._generate_envelopeGUI.ye.setText(self._settings["eps"][0]) else: self._generate_envelopeGUI.yr.setText("") self._generate_envelopeGUI.yrp.setText("") self._generate_envelopeGUI.ye.setText("") def sym_twiss(self): info = self._generate_twissGUI.checkBox.isChecked() if info: xa = self._generate_twissGUI.xa.text() self._generate_twissGUI.ya.setText(xa) xb = self._generate_twissGUI.xb.text() self._generate_twissGUI.yb.setText(xb) xe = self._generate_twissGUI.xe.text() self._generate_twissGUI.ye.setText(xe) else: self._generate_twissGUI.ya.setText("") self._generate_twissGUI.yb.setText("") self._generate_twissGUI.ye.setText("") def run(self): # --- Calculate the positions to center the window --- # screen_size = self._parent.screen_size() _x = 0.5 * (screen_size.width() - self._generate_main.width()) _y = 0.5 * (screen_size.height() - self._generate_main.height()) # --- Show the GUI --- # self._generate_main.show() self._generate_main.move(_x, _y) def run_error(self): # --- Calculate the positions to center the window --- # screen_size = self._parent.screen_size() _x = 0.5 * (screen_size.width() - self._generate_error.width()) _y = 0.5 * (screen_size.height() - self._generate_error.height()) # --- Show the GUI --- # self._generate_error.show() self._generate_error.move(_x, _y) def run_envelope(self): # --- Calculate the positions to center the window --- # screen_size = self._parent.screen_size() _x = 0.5 * (screen_size.width() - self._generate_envelope.width()) _y = 0.5 * (screen_size.height() - self._generate_envelope.height()) # --- Show the GUI --- # self._generate_envelope.show() self._generate_envelope.move(_x, _y) def run_twiss(self): # --- Calculate the positions to center the window --- # screen_size = self._parent.screen_size() _x = 0.5 * (screen_size.width() - self._generate_twiss.width()) _y = 0.5 * (screen_size.height() - self._generate_twiss.height()) # --- Show the GUI --- # self._generate_twiss.show() self._generate_twiss.move(_x, _y)
class Tasks_Tab(QWidget): def __init__(self): super(QWidget, self).__init__() self.ui = Ui_Tasks_Tab(DB) self.ui.setupUi(self) @pyqtSlot() def edit_description(self): self.descr_edit_window = QMainWindow(self) self.descr_edit_window.resize(300, 300) self.descr_edit_window.setWindowTitle("Edit_Discription") # self.descr_edit_window.setWindowIcon("447logoicon.png") self.descr_edit_widget = QWidget(self.descr_edit_window) self.descr_edit_layout = QVBoxLayout() self.descr_edit_widget.setLayout(self.descr_edit_layout) ############################################################ self.descr_label = QLabel("Edit Task") self.descr_label.setAlignment(Qt.AlignCenter) self.descr_edit = QTextEdit() self.descr_edit.setPlaceholderText("Enter a new description.") self.descr_layout_button_accept = QPushButton("Save Task") self.descr_layout_button_accept.clicked.connect(self.accept_edit_window) self.descr_layout_button_cancel = QPushButton("Cancel") self.descr_layout_button_cancel.clicked.connect(self.cancel_edit_window) ############################################################ self.descr_edit_buttons_widget = QWidget(self.descr_edit_window) self.descr_edit_buttons_layout = QHBoxLayout() self.descr_edit_buttons_widget.setLayout(self.descr_edit_buttons_layout) self.descr_edit_buttons_layout.addWidget(self.descr_layout_button_accept) self.descr_edit_buttons_layout.addWidget(self.descr_layout_button_cancel) ############################################################ self.descr_edit_layout.addWidget(self.descr_label) self.descr_edit_layout.addWidget(self.descr_edit) self.descr_edit_layout.addWidget(self.descr_edit_buttons_widget) self.descr_edit_window.setCentralWidget(self.descr_edit_widget) self.descr_edit_window.show() @pyqtSlot() def get_task_from_tree(self): pass @pyqtSlot() def cancel_edit_window(self): self.descr_edit_window.close() @pyqtSlot() def accept_edit_window(self): # get task id # save the new description for the task self.descr_edit_window.close() @pyqtSlot() def add_board(self): if self.add_board_edit.text() == '': print("empty board") pass @pyqtSlot() def delete_board(self): if self.add_board_edit.text() == '': print("empty board") pass @pyqtSlot() def add_list(self): pass @pyqtSlot() def delete_list(self): pass @pyqtSlot() def add_task(self): pass @pyqtSlot() def delete_task(self): pass @pyqtSlot() def boards_combo(self): pass @pyqtSlot() def lists_combo(self): pass @pyqtSlot() def update_trello(self): pass # Update the tree view with boards def updateTreeView(self): pass # Get value for the item being clicked def getValueTree(self, val): print(val.data()) print(val.row()) print(val.column()) # insert boards into tree view def insertBoard(self): pass