Skip to content

Commit

Permalink
Merge pull request #294 from zxcalc/settings
Browse files Browse the repository at this point in the history
Refactoring settings
  • Loading branch information
boldar99 authored Jul 9, 2024
2 parents 1be3b0e + 4b72320 commit a65faf7
Show file tree
Hide file tree
Showing 10 changed files with 486 additions and 409 deletions.
11 changes: 6 additions & 5 deletions zxlive/commands.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,8 @@
from pyzx.symbolic import Poly
from pyzx.utils import EdgeType, VertexType, get_w_partner, vertex_is_w, get_w_io, get_z_box_label, set_z_box_label

from .common import ET, VT, W_INPUT_OFFSET, GraphT, setting
from .common import ET, VT, W_INPUT_OFFSET, GraphT
from .settings import display_setting
from .eitem import EItem
from .graphview import GraphView
from .proof import ProofModel, ProofStepView, Rewrite
Expand Down Expand Up @@ -202,8 +203,8 @@ def undo(self) -> None:
self.update_graph_view()

def redo(self) -> None:
y = round(self.y * setting.SNAP_DIVISION) / setting.SNAP_DIVISION
x = round(self.x * setting.SNAP_DIVISION) / setting.SNAP_DIVISION
y = round(self.y * display_setting.SNAP_DIVISION) / display_setting.SNAP_DIVISION
x = round(self.x * display_setting.SNAP_DIVISION) / display_setting.SNAP_DIVISION
self._added_vert = self.g.add_vertex(self.vty, y,x)
self.update_graph_view()

Expand All @@ -224,8 +225,8 @@ def undo(self) -> None:
self.update_graph_view()

def redo(self) -> None:
y = round(self.y * setting.SNAP_DIVISION) / setting.SNAP_DIVISION
x = round(self.x * setting.SNAP_DIVISION) / setting.SNAP_DIVISION
y = round(self.y * display_setting.SNAP_DIVISION) / display_setting.SNAP_DIVISION
x = round(self.x * display_setting.SNAP_DIVISION) / display_setting.SNAP_DIVISION
self._added_input_vert = self.g.add_vertex(VertexType.W_INPUT, y - W_INPUT_OFFSET, self.x)
self._added_output_vert = self.g.add_vertex(VertexType.W_OUTPUT, y, x)
self.g.add_edge((self._added_input_vert, self._added_output_vert), EdgeType.W_IO)
Expand Down
200 changes: 16 additions & 184 deletions zxlive/common.py
Original file line number Diff line number Diff line change
@@ -1,22 +1,34 @@
from __future__ import annotations

import os
from enum import IntEnum
from typing import Final, Dict, Any, Optional
from typing import Final, Optional, TypeVar, Type

from pyzx import EdgeType
from typing_extensions import TypeAlias

from PySide6.QtCore import QSettings
from PySide6.QtGui import QColor
from PySide6.QtWidgets import QTabWidget

import pyzx

_ROOT = os.path.abspath(os.path.dirname(__file__))


T = TypeVar('T')


def get_data(path: str) -> str:
return os.path.join(os.environ.get("_MEIPASS", _ROOT), path)


def get_settings_value(arg: str, _type: Type[T], default: T | None = None, settings: QSettings | None = None) -> T:
_settings = settings or QSettings("zxlive", "zxlive")
if not isinstance(val := _settings.value(arg, default), _type):
if default is not None:
return default
raise ValueError(f"Unexpected type for {val}: expected {_type}, got {type(val)}")
return val

def get_custom_rules_path() -> str:
settings = QSettings("zxlive", "zxlive")
return str(settings.value('path/custom-rules'))
Expand All @@ -25,6 +37,7 @@ def get_custom_rules_path() -> str:
VT: TypeAlias = int
ET: TypeAlias = tuple[int, int, EdgeType]
GraphT: TypeAlias = pyzx.graph.multigraph.Multigraph

def new_graph() -> GraphT:
g = GraphT()
g.set_auto_simplify(False)
Expand All @@ -37,86 +50,6 @@ class ToolType(IntEnum):

SCALE: Final = 64.0


defaults: Dict[str,Any] = {
"path/custom-rules": "lemmas/",
"color-scheme": "modern-red-green",
"tab-bar-location": QTabWidget.TabPosition.North,
"snap-granularity": '4',
"input-circuit-format": 'openqasm',

"tikz/boundary-export": pyzx.settings.tikz_classes['boundary'],
"tikz/Z-spider-export": pyzx.settings.tikz_classes['Z'],
"tikz/X-spider-export": pyzx.settings.tikz_classes['X'],
"tikz/Z-phase-export": pyzx.settings.tikz_classes['Z phase'],
"tikz/X-phase-export": pyzx.settings.tikz_classes['X phase'],
"tikz/z-box-export": pyzx.settings.tikz_classes['Z box'],
"tikz/Hadamard-export": pyzx.settings.tikz_classes['H'],
"tikz/w-output-export": pyzx.settings.tikz_classes['W'],
"tikz/w-input-export": pyzx.settings.tikz_classes['W input'],
"tikz/edge-export": pyzx.settings.tikz_classes['edge'],
"tikz/edge-H-export": pyzx.settings.tikz_classes['H-edge'],
"tikz/edge-W-export": pyzx.settings.tikz_classes['W-io-edge'],

"tikz/boundary-import": ", ".join(pyzx.tikz.synonyms_boundary),
"tikz/Z-spider-import": ", ".join(pyzx.tikz.synonyms_z),
"tikz/X-spider-import": ", ".join(pyzx.tikz.synonyms_x),
"tikz/Hadamard-import": ", ".join(pyzx.tikz.synonyms_hadamard),
"tikz/w-input-import": ", ".join(pyzx.tikz.synonyms_w_input),
"tikz/w-output-import": ", ".join(pyzx.tikz.synonyms_w_output),
"tikz/z-box-import": ", ".join(pyzx.tikz.synonyms_z_box),
"tikz/edge-import": ", ".join(pyzx.tikz.synonyms_edge),
"tikz/edge-H-import": ", ".join(pyzx.tikz.synonyms_hedge),
"tikz/edge-W-import": ", ".join(pyzx.tikz.synonyms_wedge),

"tikz/layout/hspace": 2.0,
"tikz/layout/vspace": 2.0,
"tikz/layout/max-width": 10.0,

"tikz/names/fuse spiders": "f",
"tikz/names/bialgebra": "b",
"tikz/names/change color to Z": "cc",
"tikz/names/change color to X": "cc",
"tikz/names/remove identity": "id",
"tikz/names/Add Z identity": "id",
"tikz/names/copy 0/pi spider": "cp",
"tikz/names/push Pauli": "pi",
"tikz/names/decompose hadamard": "eu",
}

color_schemes = {
'modern-red-green': "Modern Red & Green",
'classic-red-green': "Classic Red & Green",
'white-grey': "Dodo book White & Grey",
'gidney': "Gidney's Black & White",
}

input_circuit_formats = {
'openqasm': "standard OpenQASM",
'sqasm': "Spider QASM",
'sqasm-no-simplification': "Spider QASM (no simplification)",
}

# Initialise settings
settings = QSettings("zxlive", "zxlive")
for key, value in defaults.items():
if not settings.contains(key):
settings.setValue(key, value)


class Settings(object):
SNAP_DIVISION = 4 # Should be an integer dividing SCALE

def __init__(self) -> None:
self.update()

def update(self) -> None:
settings = QSettings("zxlive", "zxlive")
self.SNAP_DIVISION = int(settings.value("snap-granularity"))
self.SNAP = SCALE / self.SNAP_DIVISION

setting = Settings()

# Offsets should be a multiple of SCALE for grid snapping to work properly
OFFSET_X: Final = 300 * SCALE
OFFSET_Y: Final = 300 * SCALE
Expand Down Expand Up @@ -144,107 +77,6 @@ def pos_from_view_int(x:float,y: float) -> tuple[int, int]:
def view_to_length(width:float,height:float)-> tuple[float, float]:
return (width / SCALE, height / SCALE)


class Colors(object):
z_spider: QColor = QColor("#ccffcc")
z_spider_pressed: QColor = QColor("#64BC90")
x_spider: QColor = QColor("#ff8888")
x_spider_pressed: QColor = QColor("#bb0f0f")
hadamard: QColor = QColor("#ffff00")
hadamard_pressed: QColor = QColor("#f1c232")
boundary: QColor = QColor("#000000")
boundary_pressed: QColor = QColor("#444444")
w_input: QColor = QColor("#000000")
w_input_pressed: QColor = QColor("#444444")
w_output: QColor = QColor("#000000")
w_output_pressed: QColor = QColor("#444444")
outline: QColor = QColor("#000000")

def __init__(self, color_scheme:str):
self.set_color_scheme(color_scheme)

def set_color_scheme(self, color_scheme: str) -> None:
if color_scheme == 'modern-red-green':
self.z_spider = QColor("#ccffcc")
self.z_spider_pressed = QColor("#64BC90")
self.x_spider = QColor("#ff8888")
self.x_spider_pressed = QColor("#bb0f0f")
self.hadamard = QColor("#ffff00")
self.hadamard_pressed = QColor("#f1c232")
self.boundary = QColor("#000000")
elif color_scheme == 'classic-red-green':
self.z_spider = QColor("#00ff00")
self.z_spider_pressed = QColor("#00dd00")
self.x_spider = QColor("#ff0d00")
self.x_spider_pressed = QColor("#dd0b00")
self.hadamard = QColor("#ffff00")
self.hadamard_pressed = QColor("#f1c232")
self.boundary = QColor("#000000")
elif color_scheme == 'white-grey':
self.z_spider = QColor("#ffffff")
self.z_spider_pressed = QColor("#eeeeee")
self.x_spider = QColor("#b4b4b4")
self.x_spider_pressed = QColor("#a0a0a0")
self.hadamard = QColor("#ffffff")
self.hadamard_pressed = QColor("#dddddd")
self.boundary = QColor("#000000")
elif color_scheme == 'gidney':
self.z_spider = QColor("#000000")
self.z_spider_pressed = QColor("#222222")
self.x_spider = QColor("#ffffff")
self.x_spider_pressed = QColor("#dddddd")
self.hadamard = QColor("#ffffff")
self.hadamard_pressed = QColor("#dddddd")
self.boundary = QColor("#000000")
else:
raise ValueError(f"Unknown colour scheme {color_scheme}")


settings = QSettings("zxlive", "zxlive")
color_scheme = settings.value("color-scheme")
if color_scheme is None: color_scheme = str(defaults["color-scheme"])
else: color_scheme = str(color_scheme)
colors = Colors(color_scheme)


def set_pyzx_tikz_settings() -> None:
tikz_classes = {
'boundary': str(settings.value('tikz/boundary-export') or pyzx.settings.tikz_classes['boundary']),
'Z': str(settings.value('tikz/Z-spider-export') or pyzx.settings.tikz_classes['Z']),
'X': str(settings.value('tikz/X-spider-export') or pyzx.settings.tikz_classes['X']),
'Z phase': str(settings.value('tikz/Z-phase-export') or pyzx.settings.tikz_classes['Z phase']),
'X phase': str(settings.value('tikz/X-phase-export') or pyzx.settings.tikz_classes['X phase']),
'Z box': str(settings.value('tikz/Z-box-export') or pyzx.settings.tikz_classes['Z box']),
'H': str(settings.value('tikz/Hadamard-export') or pyzx.settings.tikz_classes['H']),
'W': str(settings.value('tikz/W-output-export') or pyzx.settings.tikz_classes['W']),
'W input': str(settings.value('tikz/W-input-export') or pyzx.settings.tikz_classes['W input']),
'edge': str(settings.value('tikz/edge-export') or pyzx.settings.tikz_classes['edge']),
'H-edge': str(settings.value('tikz/edge-H-export') or pyzx.settings.tikz_classes['H-edge']),
'W-io-edge': str(settings.value('tikz/edge-W-export') or pyzx.settings.tikz_classes['W-io-edge']),
}

def _get_synonyms(key: str, default: list[str]) -> list[str]:
val: object = settings.value(key)
if not val:
return default
return [s.strip().lower() for s in str(val).split(',')]

pyzx.settings.tikz_classes = tikz_classes
pyzx.tikz.synonyms_boundary = _get_synonyms('tikz/boundary-import', pyzx.tikz.synonyms_boundary)
pyzx.tikz.synonyms_z = _get_synonyms('tikz/Z-spider-import', pyzx.tikz.synonyms_z)
pyzx.tikz.synonyms_x = _get_synonyms('tikz/X-spider-import', pyzx.tikz.synonyms_x)
pyzx.tikz.synonyms_hadamard = _get_synonyms('tikz/Hadamard-import', pyzx.tikz.synonyms_hadamard)
pyzx.tikz.synonyms_w_input = _get_synonyms('tikz/W-input-import', pyzx.tikz.synonyms_w_input)
pyzx.tikz.synonyms_w_output = _get_synonyms('tikz/W-output-import', pyzx.tikz.synonyms_w_output)
pyzx.tikz.synonyms_z_box = _get_synonyms('tikz/Z-box-import', pyzx.tikz.synonyms_z_box)
pyzx.tikz.synonyms_edge = _get_synonyms('tikz/edge-import', pyzx.tikz.synonyms_edge)
pyzx.tikz.synonyms_hedge = _get_synonyms('tikz/edge-H-import', pyzx.tikz.synonyms_hedge)
pyzx.tikz.synonyms_wedge = _get_synonyms('tikz/edge-W-import', pyzx.tikz.synonyms_wedge)


set_pyzx_tikz_settings() # Call it once on startup


def to_tikz(g: GraphT) -> str:
return pyzx.tikz.to_tikz(g) # type: ignore

Expand Down
3 changes: 2 additions & 1 deletion zxlive/edit_panel.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,12 @@

from .base_panel import ToolbarSection
from .commands import UpdateGraph
from .common import GraphT, input_circuit_formats
from .common import GraphT
from .dialogs import show_error_msg, create_circuit_dialog
from .editor_base_panel import EditorBasePanel
from .graphscene import EditGraphScene
from .graphview import GraphView
from .settings_dialog import input_circuit_formats


class GraphEditPanel(EditorBasePanel):
Expand Down
15 changes: 8 additions & 7 deletions zxlive/editor_base_panel.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,11 @@
from .commands import (AddEdge, AddNode, AddWNode, ChangeEdgeColor,
ChangeNodeType, ChangePhase, MoveNode, SetGraph,
UpdateGraph)
from .common import VT, GraphT, ToolType, get_data, colors
from .common import VT, GraphT, ToolType, get_data
from .dialogs import show_error_msg
from .eitem import HAD_EDGE_BLUE
from .graphscene import EditGraphScene
from .settings import display_setting
from .vitem import BLACK


Expand All @@ -40,12 +41,12 @@ class DrawPanelNodeType(TypedDict):

def vertices_data() -> dict[VertexType, DrawPanelNodeType]:
return {
VertexType.Z: {"text": "Z spider", "icon": (ShapeType.CIRCLE, colors.z_spider)},
VertexType.X: {"text": "X spider", "icon": (ShapeType.CIRCLE, colors.x_spider)},
VertexType.H_BOX: {"text": "H box", "icon": (ShapeType.SQUARE, colors.hadamard)},
VertexType.Z_BOX: {"text": "Z box", "icon": (ShapeType.SQUARE, colors.z_spider)},
VertexType.W_OUTPUT: {"text": "W node", "icon": (ShapeType.TRIANGLE, colors.w_output)},
VertexType.BOUNDARY: {"text": "boundary", "icon": (ShapeType.CIRCLE, colors.w_input)},
VertexType.Z: {"text": "Z spider", "icon": (ShapeType.CIRCLE, display_setting.colors["z_spider"])},
VertexType.X: {"text": "X spider", "icon": (ShapeType.CIRCLE, display_setting.colors["x_spider"])},
VertexType.H_BOX: {"text": "H box", "icon": (ShapeType.SQUARE, display_setting.colors["hadamard"])},
VertexType.Z_BOX: {"text": "Z box", "icon": (ShapeType.SQUARE, display_setting.colors["z_spider"])},
VertexType.W_OUTPUT: {"text": "W node", "icon": (ShapeType.TRIANGLE, display_setting.colors["w_output"])},
VertexType.BOUNDARY: {"text": "boundary", "icon": (ShapeType.CIRCLE, display_setting.colors["w_input"])},
}

def edges_data() -> dict[EdgeType, DrawPanelNodeType]:
Expand Down
28 changes: 28 additions & 0 deletions zxlive/icons/folder.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
5 changes: 3 additions & 2 deletions zxlive/proof.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,8 @@
QStyle, QStyledItemDelegate,
QStyleOptionViewItem, QWidget)

from .common import GraphT, colors
from .common import GraphT
from .settings import display_setting


class Rewrite(NamedTuple):
Expand Down Expand Up @@ -354,7 +355,7 @@ def paint(self, painter: QPainter, option: QStyleOptionViewItem, index: Union[QM

# Draw circle
painter.setPen(QPen(Qt.GlobalColor.black, self.circle_outline_width))
painter.setBrush(colors.z_spider)
painter.setBrush(display_setting.colors["z_spider"])
circle_radius = self.circle_radius_selected if option.state & QStyle.StateFlag.State_Selected else self.circle_radius
painter.drawEllipse(
QPointF(self.line_padding + self.line_width / 2, option.rect.y() + option.rect.height() / 2),
Expand Down
Loading

0 comments on commit a65faf7

Please sign in to comment.