GridViewer.py 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204
  1. '''
  2. ** By Cro-Ki l@b, 2017 **
  3. '''
  4. if __name__ == "__main__":
  5. import os, sys
  6. pypog_path = (os.path.abspath(".."))
  7. sys.path.append(pypog_path)
  8. import json
  9. import time
  10. from PyQt5.Qt import QFileDialog, Qt, QRectF
  11. from PyQt5.QtCore import QPointF, QMimeData
  12. from PyQt5.QtWidgets import QMainWindow, \
  13. QApplication, QGraphicsScene, QGraphicsView, QMessageBox
  14. import ipdb # until I find another way to print traceback with pyqt5
  15. from gridviewer.GridViewerCell import GridViewerCell
  16. from gridviewer.viewer import Ui_window
  17. from pypog import geometry
  18. class GridViewer(QMainWindow):
  19. def __init__(self):
  20. super (GridViewer, self).__init__()
  21. self.cells = {}
  22. self.selection = []
  23. self.createWidgets()
  24. def createWidgets(self):
  25. self.ui = Ui_window()
  26. self.ui.setupUi(self)
  27. self._scene = QGraphicsScene()
  28. self.ui.view.setScene(self._scene)
  29. self.ui.view.scale(0.5, 0.5)
  30. self.ui.view.centerOn(QPointF(0, 0))
  31. self.ui.view.setDragMode(QGraphicsView.NoDrag)
  32. self.ui.txt_coords.setPlainText("[]")
  33. self.ui.btn_make.clicked.connect(self.make_grid)
  34. self.ui.btn_updateSelection.clicked.connect(self.update_selected_cells)
  35. self.ui.btn_toClipboard.clicked.connect(self.to_clipboard)
  36. self.ui.btn_zoom_plus.clicked.connect(self.zoom_plus)
  37. self.ui.btn_zoom_minus.clicked.connect(self.zoom_minus)
  38. self.ui.chk_displayCoords.toggled.connect(self.update_cell_labels)
  39. self.ui.txt_stdin.returnPressed.connect(self.run_stdin)
  40. self.ui.btn_load_tipog.clicked.connect(self.tipog_load)
  41. self.ui.btn_tipog_previous.clicked.connect(self.tipog_previous)
  42. self.ui.btn_tipog_next.clicked.connect(self.tipog_next)
  43. self.make_grid()
  44. def current_shape(self):
  45. return geometry.FLAT_HEX if self.ui.opt_hex.isChecked() else geometry.SQUARE
  46. def make_grid(self):
  47. shape = self.current_shape()
  48. width = self.ui.spb_width.value()
  49. height = self.ui.spb_height.value()
  50. self._update_grid(shape, 0, width, 0, height)
  51. def _update_grid(self, cell_shape, min_x, max_x, min_y, max_y):
  52. QApplication.setOverrideCursor(Qt.WaitCursor)
  53. self.cells = {}
  54. self.selection = []
  55. self._scene.clear()
  56. if (max_x - min_x) * (max_y - min_y) > 10000:
  57. self.ui.chk_displayCoords.setChecked(False)
  58. for x in range(min_x, max_x):
  59. for y in range(min_y, max_y):
  60. cell = GridViewerCell(self, x, y)
  61. cell.generate(cell_shape, show_label=self.ui.chk_displayCoords.isChecked())
  62. self._scene.addItem(cell)
  63. self.cells[(x, y)] = cell
  64. self.ui.txt_stdout.setText(str(self.cells))
  65. # rect = self._scene.sceneRect()
  66. # margin = 240
  67. # new_rect = QRectF(rect.x() - margin, rect.y() - margin, rect.width() + (2 * margin), rect.height() + (2 * margin))
  68. # self._scene.setSceneRect(new_rect)
  69. self.ui.view.centerOn(QPointF(0, 0))
  70. # self.ui.view.centerOn(QPointF(rect.x() - margin, rect.y() - margin))
  71. QApplication.restoreOverrideCursor()
  72. def add_to_selection(self, x, y):
  73. self.selection.append((x, y))
  74. self.ui.txt_coords.setText(str(self.selection))
  75. def remove_from_selection(self, x, y):
  76. self.selection.remove((x, y))
  77. self.ui.txt_coords.setText(str(self.selection))
  78. def update_selected_cells(self):
  79. QApplication.setOverrideCursor(Qt.WaitCursor)
  80. try:
  81. new_selection = list(eval(self.ui.txt_coords.toPlainText()))
  82. except SyntaxError:
  83. QMessageBox.warning(self, "Error", "Invalid string")
  84. return
  85. for x, y in tuple(self.selection):
  86. self.cells[(x, y)].unselect()
  87. for x, y in new_selection:
  88. self.cells[(x, y)].select()
  89. QApplication.restoreOverrideCursor()
  90. def to_clipboard(self):
  91. data = QMimeData()
  92. data.setText(self.ui.txt_coords.toPlainText())
  93. app.clipboard().setMimeData(data)
  94. def update_cell_labels(self):
  95. for cell in self.cells.values():
  96. cell.show_label(bool(self.ui.chk_displayCoords.isChecked()))
  97. def zoom_plus(self):
  98. self.ui.view.scale(1.1, 1.1)
  99. def zoom_minus(self):
  100. self.ui.view.scale(0.9, 0.9)
  101. def run_stdin(self):
  102. stdin = self.ui.txt_stdin.text()
  103. try:
  104. t0 = time.time()
  105. result = eval("geometry." + stdin)
  106. self.ui.txt_coords.setText(str(result))
  107. self.update_selected_cells()
  108. self.ui.txt_stdout.setText("{} ms.".format(int(1000 * (time.time() - t0))))
  109. except Exception as e:
  110. self.ui.txt_stdout.setText("{} : {}".format(e.__class__name__, e))
  111. def tipog_load(self):
  112. filepath = QFileDialog.getOpenFileName(self, "Select the Tipog results file", ".")[0]
  113. try:
  114. with open(filepath, "r") as f:
  115. results = json.load(f)
  116. except:
  117. print("unreadable file: {}".format(filepath))
  118. if not results:
  119. print("empty results file")
  120. return
  121. self.tipog_results = results
  122. self.tipog_current = 0
  123. self.ui.btn_tipog_next.setEnabled(True)
  124. self.ui.btn_tipog_previous.setEnabled(True)
  125. self.tipog_update()
  126. def tipog_next(self):
  127. if self.tipog_current > (len(self.tipog_results) - 1):
  128. return
  129. self.tipog_current += 1
  130. self.tipog_update()
  131. def tipog_previous(self):
  132. if self.tipog_current < 1:
  133. return
  134. self.tipog_current -= 1
  135. self.tipog_update()
  136. def tipog_update(self):
  137. res = self.tipog_results[self.tipog_current]
  138. xs = [x for x, _ in res["result"]]
  139. ys = [y for _, y in res["result"]]
  140. min_x = min(xs) - 5
  141. max_x = max(xs) + 5
  142. min_y = min(ys) - 5
  143. max_y = max(ys) + 5
  144. self._update_grid(int(res["cell_shape"]), min_x, max_x, min_y, max_y)
  145. self.ui.lbl_tipog_counter.setText("{} on {}".format(self.tipog_current + 1, len(self.tipog_results)))
  146. formatted_result = [(x, y) for x, y in res["result"]]
  147. self.ui.txt_coords.setText(str(formatted_result))
  148. self.update_selected_cells()
  149. self.ui.txt_stdout.setText("{}\nExecuted in {} ms.".format(res["call"], res["exectime"]))
  150. if __name__ == "__main__":
  151. app = QApplication(sys.argv)
  152. gv = GridViewer()
  153. gv.show()
  154. r = app.exec_()
  155. exit(r)