| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238 |
- '''
- ** By Cro-Ki l@b, 2017 **
- '''
- from timeit import timeit
- from PyQt5.Qt import Qt, QEvent, QRectF
- from PyQt5.QtCore import QPointF
- from PyQt5.QtGui import QPolygonF
- from PyQt5.QtWidgets import QMainWindow, \
- QApplication, QGraphicsScene, QGraphicsView
- import yaml
- from GridDialogBox import GridDialogBox
- from GridViewerCell import GridViewerCell
- from ListViewDialog import ListViewDialog
- from pypog.grid_objects import SquareGrid, FHexGrid, HexGrid, BaseGrid
- from qt_viewer import Ui_window
- class GridViewer(QMainWindow):
- def __init__(self):
- super (GridViewer, self).__init__()
- self.cells = {}
- self.selection = []
- self.job_index = 0
- self.job_results = []
- self.grid = BaseGrid(1, 1)
- self.createWidgets()
- # ## GUI related methods
- def createWidgets(self):
- self.ui = Ui_window()
- self.ui.setupUi(self)
- self.ui.btn_new_grid.clicked.connect(self.show_new_grid_dialog)
- self.ui.btn_list_view.clicked.connect(self.show_list_view_dialog)
- self.ui.btn_zoom_plus.clicked.connect(self.zoom_plus)
- self.ui.btn_zoom_minus.clicked.connect(self.zoom_minus)
- self.ui.btn_zoom_view.clicked.connect(self.fit_in_view)
- self.ui.chk_displayCoords.toggled.connect(self.update_cell_labels)
- self.ui.btn_run_job.clicked.connect(self.run_selected_job_clicked)
- self.ui.btn_job_next.clicked.connect(self.job_next_clicked)
- self.ui.btn_job_previous.clicked.connect(self.job_previous_clicked)
- self.ui.btn_job_validate.clicked.connect(self.job_validate_clicked)
- self.ui.view.setViewportUpdateMode(QGraphicsView.BoundingRectViewportUpdate)
- self.ui.view.setDragMode(QGraphicsView.NoDrag)
- self.ui.view.setTransformationAnchor(QGraphicsView.AnchorUnderMouse)
- self.ui.view.viewport().installEventFilter(self)
- self.ui.cb_jobs.insertItems(0, self.get_job_names())
- self._update_stack_job()
- def eventFilter(self, obj, event):
- if event.type() == QEvent.Wheel:
- if event.angleDelta().y() > 0:
- self.zoom_plus()
- elif event.angleDelta().y() < 0:
- self.zoom_minus()
- return True
- return False
- def fit_in_view(self):
- self.ui.view.fitInView(self._scene.sceneRect(), Qt.KeepAspectRatio)
- def zoom_plus(self):
- self.ui.view.scale(1.2, 1.2)
- def zoom_minus(self):
- self.ui.view.scale(0.8, 0.8)
- # ## Grid and selection
- def make_grid(self, grid):
- QApplication.setOverrideCursor(Qt.WaitCursor)
- self.grid = grid
- self.cells = {}
- self.selection = []
- self._scene = QGraphicsScene()
- self._scene.setItemIndexMethod(QGraphicsScene.BspTreeIndex)
- if len(grid) > 10000:
- self.ui.chk_displayCoords.setChecked(False)
- scale = 120
- margin = 2 * scale
- ratio = 0.866 if isinstance(grid, HexGrid) else 1
- self._scene.setSceneRect(0 - margin, 0 - margin, (ratio * scale * (grid.width + 2)) + margin, (scale * (grid.height + 2)) + margin)
- for x, y in grid:
- cell = GridViewerCell(self, x, y)
- cell.generate(grid.geometry.graphicsitem(x, y), show_label=self.ui.chk_displayCoords.isChecked())
- self._scene.addItem(cell)
- self.cells[(x, y)] = cell
- self.ui.view.setScene(self._scene)
- self.ui.view.centerOn(QPointF(0, 0))
- self.fit_in_view()
- self.grid = grid
- QApplication.restoreOverrideCursor()
- def add_to_selection(self, x, y):
- self.selection.append((x, y))
- def remove_from_selection(self, x, y):
- self.selection.remove((x, y))
- def update_selected_cells(self, new_selection):
- if not new_selection != self.selection:
- return
- QApplication.setOverrideCursor(Qt.WaitCursor)
- for x, y in tuple(self.selection):
- self.cells[(x, y)].unselect()
- for x, y in new_selection:
- if (x, y) in self.grid:
- self.cells[(x, y)].select()
- QApplication.restoreOverrideCursor()
- def update_cell_labels(self):
- for cell in self.cells.values():
- cell.show_label(bool(self.ui.chk_displayCoords.isChecked()))
- # ## Dialogs
- def show_new_grid_dialog(self):
- grid = GridDialogBox.get()
- if grid:
- self.make_grid(grid)
- def show_list_view_dialog(self):
- new_lst = ListViewDialog(self.selection).exec_()
- self.update_selected_cells(new_lst)
- # ## IT Jobs
- def run_selected_job_clicked(self):
- self.job_index = 0
- self.job_results = self.run_job(self.ui.cb_jobs.currentText())
- self._update_stack_job()
- def job_next_clicked(self):
- if self.job_index < (len(self.job_results) - 1):
- self.job_index += 1
- self._update_stack_job()
- def job_previous_clicked(self):
- if self.job_index > 0:
- self.job_index -= 1
- self._update_stack_job()
- def job_validate_clicked(self):
- self.save_result_for(*self.job_results[self.job_index])
- self._update_stack_job()
- def _update_stack_job(self):
- if not self.job_results:
- self.ui.stack_job.setCurrentIndex(0)
- return
- self.ui.stack_job.setCurrentIndex(1)
- self.ui.lbl_job_number.setText("Test {} / {}".format(self.job_index + 1, len(self.job_results)))
- gridstr, callstr, result, ittime = self.job_results[self.job_index]
- new_grid = eval(gridstr)
- if not (new_grid.__class__ == self.grid.__class__ and
- new_grid.width == self.grid.width and
- new_grid.height == self.grid.height):
- self.make_grid(new_grid)
- self.ui.txt_job_run.setText(callstr)
- self.update_selected_cells(result)
- saved = self.saved_result_for(callstr)
- if saved:
- self.ui.lbl_job_exectime.setText("Exec. in {0:.2f} ms. / Saved: {1:.2f} ms. / Same result: {2:}".format(ittime, saved[3], str(result) == saved[2]))
- else:
- self.ui.lbl_job_exectime.setText("Exec. in {0:.2f} ms.".format(ittime))
- @staticmethod
- def get_job_names():
- with open("jobs.yml", "r") as f:
- jobs = yaml.load(f)
- return jobs.keys()
- @staticmethod
- def run_job(job_name):
- with open("jobs.yml", "r") as f:
- jobs = yaml.load(f)
- callstrings = [(gridstr, "{}.{}".format(gridstr, funcstr)) for gridstr, calls in jobs[job_name].items() for funcstr in calls]
- return [(gridstr, callstr, eval(callstr), GridViewer.ittime(callstr)) for gridstr, callstr in callstrings]
- @staticmethod
- def ittime(callstr):
- """ returns the execution time in milli-seconds
- callstr has to be a string
- (ex: 'time.sleep(1)', which will return 1000)
- """
- number, t = 1, 0
- while t < 10 ** 8:
- t = timeit(lambda: eval(callstr), number=number)
- if t >= 0.001:
- return 1000 * t / number
- number *= 10
- else:
- return -1
- @staticmethod
- def saved_results():
- try:
- with open("results.yml", "r") as f:
- data = yaml.load(f)
- return dict(data)
- except (FileNotFoundError, TypeError):
- return {}
- @staticmethod
- def saved_result_for(callstr):
- try:
- return tuple(GridViewer.saved_results()[callstr])
- except (TypeError, KeyError):
- return None
- @staticmethod
- def save_result(gridstr, callstr, result, ittime):
- data = GridViewer.saved_results()
- data[callstr] = [gridstr, callstr, str(result), ittime]
- with open("results.yml", "w+") as f:
- yaml.dump(data, f)
|