A computational geometry learning and experimentation tool.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

151 lines
5.7 KiB

from enum import Enum
from functools import partial
import os
from PyQt5.QtCore import Qt
from PyQt5.QtGui import QCursor
from PyQt5 import QtWidgets, uic
from clusterview.exceptions import handle_exceptions, InvalidModeError
from clusterview.mode import Mode
from clusterview.mode_handlers import MODE_HANDLER_MAP, ogl_keypress_handler
from clusterview.opengl_widget import (clear_selection, initialize_gl,
paint_gl, resize_gl,
set_drawing_mode, set_drawing_context)
from clusterview_ui import Ui_MainWindow
class MainWindow(QtWidgets.QMainWindow, Ui_MainWindow):
"""
A wrapper class for handling creating a window based
on the `clusterview_ui.py` code generated from
`clusterview.ui`.
"""
__mode = Mode.OFF
def __init__(self, parent=None):
super(MainWindow, self).__init__(parent)
self.setupUi(self)
# We only need to set the context in our OpenGL state machine
# wrapper once here since the window is fixed size.
# If we allow resizing of the window, the context must be updated
# each resize so that coordinates are converted from screen (x, y)
# to OpenGL coordinates properly.
set_drawing_context(self.opengl_widget)
# Enables mouse tracking on the viewport so mouseMoveEvents are
# tracked and fired properly.
self.opengl_widget.setMouseTracking(True)
# Here we partially apply the key press handler with self to
# create a new function that only expects the event `keyPressEvent`
# expects. In this way, we've snuck the state of the opengl_widget
# into the function so that we can modify it as we please.
self.opengl_widget.keyPressEvent = partial(ogl_keypress_handler, self)
#-----------------------------------------------
# OpenGL Graphics Handlers are set
# here and defined in clusterview.opengl_widget.
#-----------------------------------------------
self.opengl_widget.initializeGL = initialize_gl
self.opengl_widget.paintGL = paint_gl
self.opengl_widget.resizeGL = resize_gl
# -------------------------------------
# UI Handlers
# -------------------------------------
self.action_add_points.triggered.connect(self.__add_points)
self.action_edit_points.triggered.connect(self.__edit_points)
self.action_delete_points.triggered.connect(self.__delete_points)
self.action_move_points.triggered.connect(self.__move_points)
self.action_solve.triggered.connect(self.__solve_launcher)
# Override handler for mouse press so we can draw points based on
# the OpenGL coordinate system inside of the OpenGL Widget.
self.opengl_widget.mousePressEvent = self.__ogl_click_dispatcher
self.opengl_widget.mouseMoveEvent = self.__ogl_click_dispatcher
self.opengl_widget.mouseReleaseEvent = self.__ogl_click_dispatcher
#-----------------------------------------------------------------
# Mode changers - these will be used to signal the action in the
# OpenGL Widget.
#-----------------------------------------------------------------
def __off_mode(self):
self.opengl_widget.setCursor(QCursor(Qt.CursorShape.ArrowCursor))
self.status_bar.showMessage("")
clear_selection()
self.opengl_widget.update()
def __add_points(self):
self.__mode = Mode.ADD
set_drawing_mode(self.__mode)
self.opengl_widget.setCursor(QCursor(Qt.CursorShape.CrossCursor))
self.status_bar.showMessage("ADD MODE")
clear_selection()
self.opengl_widget.update()
def __edit_points(self):
self.__mode = Mode.EDIT
set_drawing_mode(self.__mode)
self.opengl_widget.setCursor(QCursor(Qt.CursorShape.CrossCursor))
self.status_bar.showMessage("EDIT MODE")
clear_selection()
self.opengl_widget.update()
def __delete_points(self):
self.__mode = Mode.DELETE
set_drawing_mode(self.__mode)
self.opengl_widget.setCursor(QCursor(Qt.CursorShape.PointingHandCursor))
self.status_bar.showMessage("DELETE MODE")
clear_selection()
self.opengl_widget.update()
def __move_points(self):
self.__mode = Mode.MOVE
set_drawing_mode(self.__mode)
self.opengl_widget.setCursor(QCursor(Qt.CursorShape.SizeAllCursor))
self.status_bar.showMessage("MOVE MODE")
clear_selection()
self.opengl_widget.update()
@property
def mode(self):
"""
Function designed to be used from a context
to get the current mode.
"""
return self.__mode
@mode.setter
def mode(self, mode):
self.__mode = mode
@handle_exceptions
def __solve_launcher(self):
"""
Launched the solve menu. This function will call into a subclass
of the solve dialog widget from the UI.
TODO: Write the subclass once you know the parameters for the
solve window.
"""
print("LAUNCHING SOLVE DIALOG...")
@handle_exceptions
def __ogl_click_dispatcher(self, event):
"""
Mode dispatcher for click actions on the OpenGL widget.
"""
if self.__mode is not Mode.OFF:
# Map from Mode -> function
# where the function is a handler for the
# OpenGL event. The context passed to these functions allows
# them to modify on screen widgets such as the QOpenGLWidget and
# QListWidget.
MODE_HANDLER_MAP[self.__mode](self, event)
else:
# Go back to the base state
self.__off_mode()