Browse Source

made the different parts kinda independent, communications now happens with signals.

It's harder now to crash the app ^^
Still work to be done here. keyboard and mouse status isn't up to snuff!
master
Christian Voigt 1 year ago
parent
commit
2fc8624d1b
  1. 65
      main.py
  2. 112
      world_regions_widget/__init__.py
  3. 39
      world_regions_widget/region_label.py
  4. 113
      world_regions_widget/region_label_collection.py
  5. 32
      world_regions_widget/tools.py

65
main.py

@ -1,22 +1,32 @@
import sys
from PyQt5.QtCore import (
Qt, QSettings, QByteArray, QSize, QObject, pyqtSignal
Qt, QSettings, QByteArray, QSize, QObject, pyqtSignal, QPoint
)
from PyQt5.QtGui import QCursor
from PyQt5.QtWidgets import (
QMainWindow, QApplication, QWidget,
QHBoxLayout, QVBoxLayout,
QProgressBar
)
from cursors import ChraniCursors
from world_regions_widget import WorldRegionsWidget
from tools import shift_is_pressed, control_is_pressed
from region_label import RegionLabel
class ProgressBarHelper(QObject):
progress_bar_percentage_signal = pyqtSignal(int)
class GuiTest(QMainWindow):
class MouseCursorHelper(QObject):
mouse_cursor_change_signal = pyqtSignal(object)
hovered_label_signal = pyqtSignal(RegionLabel)
center_label_signal = pyqtSignal()
class GuiTest(QMainWindow, ChraniCursors):
setting = QSettings
def __init__(self):
@ -58,11 +68,18 @@ class GuiTest(QMainWindow):
general_progress_bar.setValue(0)
general_progress_bar.setAlignment(Qt.AlignCenter)
general_progress_bar.setMaximumWidth(staging_view_width)
mouse_cursor_helper = MouseCursorHelper()
mouse_cursor_helper.mouse_cursor_change_signal.connect(self.mouse_cursor_change_slot)
mouse_cursor_helper.hovered_label_signal.connect(self.hovered_label_slot)
mouse_cursor_helper.center_label_signal.connect(self.center_label_slot)
progress_bar_helper = ProgressBarHelper()
progress_bar_helper.progress_bar_percentage_signal.connect(self.progress_bar_percentage_slot)
self.general_progress_bar = general_progress_bar
world_regions_widget = WorldRegionsWidget(progress_bar=progress_bar_helper)
world_regions_widget = WorldRegionsWidget(
progress_bar_helper=progress_bar_helper, mouse_cursor_helper=mouse_cursor_helper
)
region_view_layout.addWidget(
world_regions_widget
)
@ -80,9 +97,51 @@ class GuiTest(QMainWindow):
self.setCentralWidget(application_frame)
def center_label_slot(self):
QCursor.setPos(self.currently_hovered_label.mapToGlobal(QPoint(
int(self.currently_hovered_label.width() / 2),
int(self.currently_hovered_label.height() / 2)
)))
def progress_bar_percentage_slot(self, percentage: int):
self.general_progress_bar.setValue(percentage)
def hovered_label_slot(self, region_label: RegionLabel):
self.currently_hovered_label = region_label
def mouse_cursor_change_slot(self, key_event: object = None):
if control_is_pressed(key_event=key_event):
try:
if self.currently_hovered_label.is_region:
if not self.currently_hovered_label.is_marked:
self.setCursor(self.cursor_add_region)
else:
self.setCursor(self.cursor_remove_region)
else:
self.setCursor(self.cursor_blank)
# all possible eventualities covered!
return
except AttributeError:
pass
elif shift_is_pressed(key_event=key_event):
try:
if self.currently_hovered_label.is_region:
self.setCursor(self.cursor_region_context)
else:
self.setCursor(self.cursor_blank)
return
except AttributeError:
pass
# sets the default, if none of the above applies
self.setCursor(self.cursor_hover_region)
def read_window_settings(self):
geometry = self.settings.value("windowGeometry", QByteArray())
if not geometry.isEmpty():

112
world_regions_widget/__init__.py

@ -3,25 +3,33 @@ import pathlib
import numpy as np
from PyQt5.QtCore import (
Qt, QPoint
Qt, QPoint, QObject, pyqtSignal
)
from PyQt5.QtGui import (
QKeySequence
)
from PyQt5.QtWidgets import (
QWidget, QAction,
QScrollArea, QFrame, QApplication,
QScrollArea, QFrame,
QFileDialog
)
from einops import rearrange
from cursors import ChraniCursors
from region_label import RegionLabel
from .region_label_collection import RegionLabelCollection
from tools import create_grid_index_from_region_string
from tools import (
create_grid_index_from_region_string,
shift_is_pressed, control_is_pressed
)
class RegionLabelHelper(QObject):
change_region_label_region_raw_data_signal = pyqtSignal(np.ndarray)
change_region_label_toggle_marked_signal = pyqtSignal(RegionLabel)
class WorldRegionsWidget(QScrollArea, ChraniCursors):
class WorldRegionsWidget(QScrollArea):
root_dir = str
min_zoom_factor = float
@ -35,13 +43,17 @@ class WorldRegionsWidget(QScrollArea, ChraniCursors):
world_label_region_size = float
region_label_collection = RegionLabelCollection
currently_hovered_label = RegionLabel
action_open_world_file = QAction
action_save_world_file = QAction
world_regions_image_raw_data = np.array
def __init__(self, zoom_factor=1.0, min_zoom_factor=0.5, max_zoom_factor=24.0, region_size=48, progress_bar=None):
def __init__(
self, zoom_factor=1.0, min_zoom_factor=1.0, max_zoom_factor=32.0, region_size=16,
progress_bar_helper=None, mouse_cursor_helper=None
):
super().__init__()
self.world_loaded = False
self.min_zoom_factor = min_zoom_factor
@ -53,24 +65,34 @@ class WorldRegionsWidget(QScrollArea, ChraniCursors):
self.drag_in_progress = False
self.drag_start = QPoint(0, 0)
region_label_helper = RegionLabelHelper()
self.region_label_collection = RegionLabelCollection(
world_regions=self,
zoom_adjusted_label_size=self.world_label_zoom_factor * self.world_label_region_size,
progress_bar=progress_bar
progress_bar_helper=progress_bar_helper, mouse_cursor_helper=mouse_cursor_helper,
region_label_helper=region_label_helper
)
self.progress_bar_helper = progress_bar_helper
self.mouse_cursor_helper = mouse_cursor_helper
self.region_label_helper = region_label_helper
self.region_label_collection.setSpacing(0)
self.region_label_collection.setContentsMargins(0, 0, 0, 0)
region_label_collection_wrapper_widget = QWidget()
region_label_collection_wrapper_widget.setLayout(self.region_label_collection)
mouse_cursor_helper.hovered_label_signal.connect(self.hovered_label_slot)
self.setAlignment(Qt.AlignCenter)
self.setFrameShape(QFrame.NoFrame)
self.setWidget(region_label_collection_wrapper_widget)
self.init_actions()
def hovered_label_slot(self, region_label: RegionLabel):
self.currently_hovered_label = region_label
def init_actions(self):
open_world_file = QAction()
open_world_file.setShortcut(
@ -98,7 +120,7 @@ class WorldRegionsWidget(QScrollArea, ChraniCursors):
self.world_label_zoom_factor * self.world_label_region_size
)
self.adjust_scrollbar_positions()
self.region_label_collection.center_mouse_on_hovered_label()
self.mouse_cursor_helper.center_label_signal.emit()
def action_zoom_out(self):
self.world_label_zoom_factor -= self.min_zoom_factor
@ -110,12 +132,12 @@ class WorldRegionsWidget(QScrollArea, ChraniCursors):
self.world_label_zoom_factor * self.world_label_region_size
)
self.adjust_scrollbar_positions()
self.region_label_collection.center_mouse_on_hovered_label()
self.mouse_cursor_helper.center_label_signal.emit()
def adjust_scrollbar_positions(self):
size = (self.region_label_collection.currently_hovered_label.width())
size = (self.world_label_zoom_factor * self.world_label_region_size)
widget_index_x, widget_index_y = create_grid_index_from_region_string(
self.region_label_collection.currently_hovered_label.region_string
self.currently_hovered_label.region_string
)
widget_position_x = int((widget_index_x + 1) * size)
@ -128,63 +150,14 @@ class WorldRegionsWidget(QScrollArea, ChraniCursors):
int(widget_position_y - size / 2 - self.height() / 2)
)
@staticmethod
def control_is_pressed(key_event=None) -> bool:
modifiers = QApplication.keyboardModifiers()
return any([
modifiers == Qt.ControlModifier,
key_event is not None and key_event.key() in (16777249, 16777250)
])
@staticmethod
def shift_is_pressed(key_event=None) -> bool:
modifiers = QApplication.keyboardModifiers()
return any([
modifiers == Qt.ShiftModifier,
key_event is not None and key_event.key() == 16777248
])
def trigger_cursor_change(self, key_event=None):
if self.control_is_pressed(key_event=key_event):
try:
if self.region_label_collection.currently_hovered_label.is_region:
if not self.region_label_collection.currently_hovered_label.is_marked:
self.setCursor(self.cursor_add_region)
else:
self.setCursor(self.cursor_remove_region)
else:
self.setCursor(self.cursor_blank)
# all possible eventualities covered!
return
except AttributeError:
pass
elif self.shift_is_pressed(key_event=key_event):
try:
if self.region_label_collection.currently_hovered_label.is_region:
self.setCursor(self.cursor_region_context)
else:
self.setCursor(self.cursor_blank)
return
except AttributeError:
pass
# sets the default, if none of the above applies
self.setCursor(self.cursor_hover_region)
""" altering class functions """
def mousePressEvent(self, mouse_event):
if mouse_event.button() == Qt.LeftButton:
self.trigger_cursor_change()
self.mouse_cursor_helper.mouse_cursor_change_signal.emit(None)
if mouse_event.button() == Qt.RightButton and all([
not self.shift_is_pressed(),
not self.control_is_pressed()
not shift_is_pressed(),
not control_is_pressed()
]):
self.drag_in_progress = True
self.drag_start.setX(mouse_event.x())
@ -199,7 +172,7 @@ class WorldRegionsWidget(QScrollArea, ChraniCursors):
self.drag_in_progress = False
if mouse_event.button() == Qt.RightButton:
self.trigger_cursor_change()
self.mouse_cursor_helper.mouse_cursor_change_signal.emit(None)
super().mouseReleaseEvent(mouse_event)
@ -229,15 +202,15 @@ class WorldRegionsWidget(QScrollArea, ChraniCursors):
def keyPressEvent(self, key_event):
if any([
self.shift_is_pressed(key_event=key_event),
self.control_is_pressed(key_event=key_event)
shift_is_pressed(key_event=key_event),
control_is_pressed(key_event=key_event)
]):
self.trigger_cursor_change(key_event)
self.mouse_cursor_helper.mouse_cursor_change_signal.emit(key_event)
super().keyPressEvent(key_event)
def keyReleaseEvent(self, key_event):
self.setCursor(self.cursor_hover_region)
self.mouse_cursor_helper.mouse_cursor_change_signal.emit(key_event)
super().keyReleaseEvent(key_event)
@ -254,6 +227,7 @@ class WorldRegionsWidget(QScrollArea, ChraniCursors):
def load_world_file(self, file_name):
length = int(math.sqrt(pathlib.Path(file_name).stat().st_size / 2))
self.regions_per_row = int(length / 512)
offset = int(32 / 2) - int(self.regions_per_row / 2)
with open(file_name, 'r') as raw_file:

39
world_regions_widget/region_label.py

@ -1,6 +1,5 @@
import math
import pathlib
from typing import TYPE_CHECKING
import numpy as np
from PyQt5.QtCore import (
@ -13,17 +12,15 @@ from PyQt5.QtWidgets import (
QLabel, QGraphicsColorizeEffect, QApplication, QMenu, QAction, QWidgetAction, QFileDialog
)
if TYPE_CHECKING:
from world_regions_widget import RegionLabelCollection
from tools import create_region_string_from_grid_index
from tools import (
create_region_string_from_grid_index, toggle_open_in_context_menu
)
class RegionLabel(QLabel):
dimensions = QSize
raw_data_array = np.array
parent_collection = 'RegionLabelCollection'
region_string = str
is_marked = bool
@ -34,10 +31,17 @@ class RegionLabel(QLabel):
adjacent_marked_region_labels = dict
def __init__(self, collection: 'RegionLabelCollection', x=None, y=None, dimensions=QSize(512, 512)):
def __init__(
self,
x=None, y=None, dimensions=QSize(512, 512),
mouse_cursor_helper=None,
region_label_helper=None
):
super(RegionLabel, self).__init__()
self.x, self.y = x, y
self.dimensions = dimensions
self.mouse_cursor_helper = mouse_cursor_helper
self.region_label_helper = region_label_helper
pixmap = QPixmap(dimensions)
@ -46,7 +50,6 @@ class RegionLabel(QLabel):
self.context_menu_is_shown = False
self.is_selected = False
self.parent_collection = collection
self.region_string = create_region_string_from_grid_index(x=x, y=y)
self.setStatusTip(self.region_string)
@ -108,11 +111,11 @@ class RegionLabel(QLabel):
def on_context_menu(self, point):
modifiers = QApplication.keyboardModifiers()
if modifiers == Qt.ShiftModifier and self.is_region:
self.parent_collection.toggle_open_in_context_menu(self)
toggle_open_in_context_menu(self)
self.context_menu.exec_(self.mapToGlobal(point))
def on_context_menu_close(self, point):
self.parent_collection.toggle_open_in_context_menu(self)
toggle_open_in_context_menu(self)
""" visual stuff"""
@staticmethod
@ -175,19 +178,17 @@ class RegionLabel(QLabel):
raw_data_array = np.fromfile(raw_file, dtype=np.uint16)
self.set_raw_data_array(np.flipud(np.reshape(raw_data_array, (length, length))))
index_x, index_y = create_grid_index_from_region_string(self.region_string)
offset = int(32 / 2) - int(self.parent_collection.world_regions.regions_per_row / 2)
self.parent_collection.blockshaped_map_data[index_y - offset][index_x - offset] = self.raw_data_array
chunk = QImage(self.raw_data_array.copy(), 512, 512, QImage.Format_Grayscale16)
self.set_label_pixmap(chunk)
self.region_label_helper.change_region_label_region_raw_data_signal.emit(self.raw_data_array)
""" altering class functions """
def mouse_any_click_event(self, event):
modifiers = QApplication.keyboardModifiers()
if modifiers == Qt.ControlModifier and self.is_region:
if event.buttons() == Qt.LeftButton:
self.parent_collection.toggle_marked(self)
self.region_label_helper.change_region_label_toggle_marked_signal.emit(self)
def mousePressEvent(self, event):
self.mouse_any_click_event(event)
@ -199,16 +200,16 @@ class RegionLabel(QLabel):
def enterEvent(self, event) -> None:
self.is_selected = True
self.parent_collection.set_currently_hovered_label(self)
self.parent_collection.trigger_cursor_change(self)
self.mouse_cursor_helper.hovered_label_signal.emit(self)
self.mouse_cursor_helper.mouse_cursor_change_signal.emit(None)
super().enterEvent(event)
def leaveEvent(self, event) -> None:
self.is_selected = False
self.parent_collection.trigger_cursor_change(self)
self.mouse_cursor_helper.mouse_cursor_change_signal.emit(None)
super().leaveEvent(event)
def wheelEvent(self, event):
self.parent_collection.set_currently_hovered_label(self)
self.mouse_cursor_helper.hovered_label_signal.emit(self)

113
world_regions_widget/region_label_collection.py

@ -1,8 +1,9 @@
import numpy as np
from PyQt5.QtCore import QPoint, QThread, pyqtSignal
from PyQt5.QtCore import (
QThread, pyqtSignal
)
from PyQt5.QtGui import (
QImage, QCursor
QImage
)
from PyQt5.QtWidgets import (
QGridLayout
@ -11,7 +12,9 @@ from PyQt5.QtWidgets import (
from einops import rearrange
from .region_label import RegionLabel
from tools import create_grid_index_from_region_string, create_region_string_from_grid_index
from tools import (
create_grid_index_from_region_string, create_region_string_from_grid_index
)
class WorkerUpdateLabelCollection(QThread):
@ -57,29 +60,58 @@ class RegionLabelCollection(QGridLayout):
currently_hovered_label = RegionLabel
blockshaped_map_data = np.array
def __init__(self, world_regions=None, zoom_adjusted_label_size=None, progress_bar=None):
def __init__(
self, zoom_adjusted_label_size=None,
progress_bar_helper=None, mouse_cursor_helper=None,
region_label_helper=None
):
super().__init__()
if world_regions is not None:
self.world_regions = world_regions
self.label_collection = {}
self.create_label_collection(zoom_adjusted_label_size)
self.progress_bar = progress_bar
def set_currently_hovered_label(self, region_label):
self.currently_hovered_label = region_label
self.label_collection = {}
self.progress_bar_helper = progress_bar_helper
self.mouse_cursor_helper = mouse_cursor_helper
self.region_label_helper = region_label_helper
mouse_cursor_helper.hovered_label_signal.connect(self.hovered_label_slot)
region_label_helper.change_region_label_region_raw_data_signal.connect(
self.change_region_label_region_raw_data_slot
)
region_label_helper.change_region_label_toggle_marked_signal.connect(
self.change_region_label_toggle_marked_slot
)
self.create_label_collection(zoom_adjusted_label_size)
def hovered_label_slot(self, region_label):
for index, label in self.label_collection.items():
if region_label is not label:
label.is_selected = False
label.remove_graphics_effects()
if region_label is not None:
self.currently_hovered_label = region_label
region_label.update_graphics_effect()
def center_mouse_on_hovered_label(self):
QCursor.setPos(self.currently_hovered_label.mapToGlobal(QPoint(
int(self.currently_hovered_label.width() / 2),
int(self.currently_hovered_label.height() / 2)
)))
def change_region_label_region_raw_data_slot(self, raw_region_data: np.ndarray):
index_x, index_y = create_grid_index_from_region_string(
self.currently_hovered_label.region_string
)
offset = int(32 / 2) - int(self.blockshaped_map_data.shape[0] / 2)
self.blockshaped_map_data[index_y - offset][index_x - offset] = raw_region_data
def change_region_label_toggle_marked_slot(self, region_label: RegionLabel):
if region_label is not None:
region_label.is_marked = not region_label.is_marked
adjacent_marked_region_labels = self.get_adjacent_marked_region_labels(region_label)
region_label.set_adjacent_marked_region_labels(adjacent_marked_region_labels)
region_label.update_style_effects()
for direction, adjacent_marked_region_label in adjacent_marked_region_labels.items():
neighbors_adjacent_marked_region_labels = self.get_adjacent_marked_region_labels(
adjacent_marked_region_label
)
adjacent_marked_region_label.set_adjacent_marked_region_labels(neighbors_adjacent_marked_region_labels)
adjacent_marked_region_label.update_style_effects()
def get_adjacent_marked_region_labels(self, region_label: RegionLabel):
index_x, index_y = create_grid_index_from_region_string(region_label.region_string)
@ -104,39 +136,22 @@ class RegionLabelCollection(QGridLayout):
return adjacent_marked_region_labels
def toggle_marked(self, region_label=None):
if region_label is not None:
region_label.is_marked = not region_label.is_marked
adjacent_marked_region_labels = self.get_adjacent_marked_region_labels(region_label)
region_label.set_adjacent_marked_region_labels(adjacent_marked_region_labels)
region_label.update_style_effects()
for direction, adjacent_marked_region_label in adjacent_marked_region_labels.items():
neighbors_adjacent_marked_region_labels = self.get_adjacent_marked_region_labels(
adjacent_marked_region_label
)
adjacent_marked_region_label.set_adjacent_marked_region_labels(neighbors_adjacent_marked_region_labels)
adjacent_marked_region_label.update_style_effects()
@staticmethod
def toggle_open_in_context_menu(region_label=None):
if region_label is not None:
region_label.context_menu_is_shown = not region_label.context_menu_is_shown
region_label.update_graphics_effect()
def trigger_cursor_change(self, region_label=None):
if region_label is not None:
self.world_regions.trigger_cursor_change()
def create_label_collection(self, label_size):
for y in range(0, 32):
for x in range(0, 32):
self.create_label(x, y, label_size)
self.create_label(
x=x, y=y,
dimensions=label_size, mouse_cursor_helper=self.mouse_cursor_helper,
region_label_helper=self.region_label_helper
)
def create_label(self, x, y, size):
label = RegionLabel(self, x, y)
label.setFixedSize(size, size)
def create_label(self, x=None, y=None, dimensions=None, mouse_cursor_helper=None, region_label_helper=None):
label = RegionLabel(
x=x, y=y,
mouse_cursor_helper=mouse_cursor_helper,
region_label_helper=region_label_helper
)
label.setFixedSize(dimensions, dimensions)
index = create_region_string_from_grid_index(x=x, y=y)
self.addWidget(label, y, x)
self.label_collection.update({index: label})
@ -177,7 +192,7 @@ class RegionLabelCollection(QGridLayout):
)
def update_label_collection_with_raw_map_data_progress(self, percentage):
self.progress_bar.progress_bar_percentage_signal.emit(percentage)
self.progress_bar_helper.progress_bar_percentage_signal.emit(percentage)
def update_label_collection_with_raw_map_data_done(self):
self.progress_bar.progress_bar_percentage_signal.emit(0)
self.progress_bar_helper.progress_bar_percentage_signal.emit(0)

32
world_regions_widget/tools.py

@ -1,3 +1,7 @@
from PyQt5.QtGui import QGuiApplication
from PyQt5.QtCore import Qt
def create_grid_index_from_region_string(region_string: str) -> tuple:
split_string = region_string.split(".")
index_x = int(split_string[1]) + 16
@ -13,3 +17,31 @@ def create_region_string_from_grid_index(x=0, y=0) -> str:
x=int(x - 16),
y=int((y - 16) + 1) * -1
)
def control_is_pressed(key_event=None) -> bool:
modifiers = QGuiApplication.keyboardModifiers()
return any([
all([
modifiers == Qt.ControlModifier,
key_event is not None
]),
key_event is not None and key_event.key() in (16777249, 16777250)
])
def shift_is_pressed(key_event=None) -> bool:
modifiers = QGuiApplication.keyboardModifiers()
return any([
all([
modifiers == Qt.ShiftModifier,
key_event is not None
]),
key_event is not None and key_event.key() == 16777248
])
def toggle_open_in_context_menu(region_label=None):
if region_label is not None:
region_label.context_menu_is_shown = not region_label.context_menu_is_shown
region_label.update_graphics_effect()

Loading…
Cancel
Save