summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPaweł Redman <pawel.redman@gmail.com>2019-05-03 14:40:08 +0200
committerPaweł Redman <pawel.redman@gmail.com>2019-05-03 14:40:08 +0200
commit5a952899e095c82ff706449ee4d3f8c5eaac7911 (patch)
tree493ca4750349d70c5b6fccfafee92b4234241406
parent3d2e11a1eba4e8b5ff411c9d1e4be61f2c6321e8 (diff)
Start reworking the layout using a QTableWidget
-rw-r--r--src/main.py13
-rw-r--r--src/ui.py403
-rw-r--r--src/ui_table.py222
-rw-r--r--src/ui_widgets.py5
4 files changed, 344 insertions, 299 deletions
diff --git a/src/main.py b/src/main.py
index ea1122c..ce3a9ff 100644
--- a/src/main.py
+++ b/src/main.py
@@ -5,15 +5,10 @@ from PyQt5.QtCore import *
import ui, phys, file
-system = phys.System()
-
-class Window(QMainWindow):
- def __init__(self):
- super().__init__()
- self.statusBar()
- self.setWindowTitle("Polarizzazione italiana")
- ui.setup(self, system)
+#system = phys.System()
+system = file.open_system("4.woz")
app = QApplication(sys.argv)
-win = Window()
+win = ui.MainWindow(system)
+win.show()
sys.exit(app.exec_())
diff --git a/src/ui.py b/src/ui.py
index f54134f..fb0932a 100644
--- a/src/ui.py
+++ b/src/ui.py
@@ -9,7 +9,6 @@ import phys, file
# global GUI-related shit
class GUI:
table = None
- table_rows = list()
monospace = QFont("monospace")
bigfont = QFont("sans-serif", pointSize=10, weight=1000)
@@ -38,213 +37,7 @@ class Pens:
radii.setStyle(Qt.DashDotLine)
from ui_widgets import *
-
-
-
-class ElementEditorWindow(QMainWindow):
- windows = list()
-
- @staticmethod
- def open(pol):
- win = ElementEditorWindow(pol)
- win.show()
- ElementEditorWindow.windows.append(win)
-
- @staticmethod
- def close_all(pol=None):
- for win in ElementEditorWindow.windows:
- if pol is None or pol == win.pol:
- win.close()
- del(win)
-
- def __init__(self, pol):
- super().__init__(flags=Qt.Dialog)
- self.pol = pol
-
- self.setWindowTitle("Element editor")
- root = QVBoxLayout()
- root_fucking_random_container = QWidget()
- root_fucking_random_container.setLayout(root)
- self.setCentralWidget(root_fucking_random_container)
-
- # Name
- box = QHBoxLayout()
- root.addLayout(box)
- box.addWidget(QLabel("Name"))
- self.name = QLineEdit(self.pol.name)
- self.name.textChanged.connect(self.change_name)
- box.addWidget(self.name)
-
- # OPTICS
- root.addWidget(MeinGroßLabel("Optics"))
-
- # Type combo
- self.type = QComboBox()
- self.type.addItem("Linear", "linear",)
- self.type.addItem("Quarterwave plate", "quarterwave")
- self.type.setCurrentIndex(0 if pol.type == "linear" else 1)
- self.type.currentIndexChanged.connect(self.change_type)
- root.addWidget(self.type)
-
- # TRANSMITTANCE
- root.addWidget(MeinGroßLabel("Transmittance"))
-
- box = QHBoxLayout()
- root.addLayout(box)
-
- box.addWidget(QLabel("T"))
- self.t1 = QLineEdit("%g" % self.pol.t1)
- self.t1.textChanged.connect(self.change_t)
- box.addWidget(self.t1)
- self.t2 = QLineEdit("%g" % self.pol.t2)
- self.t2.textChanged.connect(self.change_t)
- box.addWidget(self.t2)
-
- # ARRANGEMENT
- root.addWidget(MeinGroßLabel("Arrangement"))
-
- # Angle reference
- self.ref = QComboBox()
- self.populate_ref()
- self.ref.currentIndexChanged.connect(update)
- root.addWidget(self.ref)
-
- # Delta angle
- self.delta = AngleSlider("Delta")
- self.delta.on_change = self.change_delta
- root.addLayout(self.delta)
-
- root.addItem(ExpandingSpacer())
-
- # Done
- self.done = QPushButton("Done")
- self.done.pressed.connect(self.close)
- root.addWidget(self.done)
-
- def change_name(self):
- self.pol.name = self.name.text()
- self.pol.row.optbox.name.setText(self.pol.name)
-
- def change_type(self):
- self.pol.set_type(self.type.currentData())
- update()
-
- def change_delta(self):
- try:
- self.pol.delta = self.delta.angle / 180 * np.pi
- update()
- except ValueError:
- pass
-
- def change_t(self):
- try:
- self.pol.t1 = float(self.t1.text())
- self.pol.t2 = float(self.t2.text())
- update()
- except ValueError:
- pass
-
- def populate_ref(self):
- self.ref.addItem("Absolute", False)
- for i, _ in enumerate(system.elements):
- if i >= self.pol.rownum - 1:
- continue
- self.ref.addItem("Relative to #%d" % (i + 1), i)
-
- if self.pol.ref is not False and i == self.pol.ref:
- self.ref.setCurrentIndex(self.pol.ref + 1)
-
-
-
-class OptBox(QVBoxLayout):
- def __init__(self, row, pol, rownum):
- super().__init__()
- self.row = row
- self.rownum = rownum
-
- # Name
- self.name = MeinGroßLabel(pol.name)
- self.name.setContextMenuPolicy(Qt.CustomContextMenu)
- self.name.customContextMenuRequested.connect(lambda pos: OptBox.open_menu(self, pos))
- self.addWidget(self.name)
-
- # Enable checkbox
- self.enable = QCheckBox("Enable")
- self.enable.setChecked(True)
- self.enable.stateChanged.connect(self.change_enable)
- self.addWidget(self.enable)
-
- # Angle
- self.angle = AngleSlider()
- self.angle.setValue(pol.angle * 180 / np.pi)
- self.angle.on_change = lambda: TableRow.angle_change(row)
- self.addLayout(self.angle)
- self.addItem(ExpandingSpacer())
-
- def open_menu(self, pos):
- menu = QMenu()
- menu.addAction("Edit", lambda: ElementEditorWindow.open(self.row.pol))
- menu.addAction("Insert before", lambda: half_assed_element_creation(self.rownum - 1))
- menu.addAction("Insert after", lambda: half_assed_element_creation(self.rownum))
- menu.addAction("Delete", lambda: half_assed_element_deletion(self.rownum - 1))
- menu.exec_(self.name.mapToGlobal(pos))
-
- def change_enable(self):
- self.row.pol.enable = self.enable.isChecked()
- update()
-
-
-class TableRow:
- def __init__(self, pol, grid, rownum):
- self.pol = pol
- pol.row = self
- pol.rownum = rownum
- self.grid = grid
- self.rownum = rownum
- self.angle = pol.angle
- self.delta = pol.delta
- self.ref = pol.ref
-
- self.optbox = OptBox(self, pol, rownum)
- grid.addLayout(self.optbox, rownum, 1)
-
- self.ellipse = EllipseWidget(pol)
- grid.addWidget(self.ellipse, rownum, 2)
-
- self.info = QVBoxLayout()
- self.info_angle = MeinLabel()
- self.info_angle.setAlignment(Qt.AlignLeft)
- self.info.addWidget(self.info_angle)
- self.info.addWidget(QLabel("Polarization state"))
- self.info_jones = MeinLabel()
- self.info_jones.setAlignment(Qt.AlignLeft)
- self.info.addWidget(self.info_jones)
- self.info.addItem(ExpandingSpacer())
- grid.addLayout(self.info, rownum, 3)
-
- @staticmethod
- def angle_change(row):
- row.angle = row.optbox.angle.angle / 180 * np.pi
- row.pol.angle = row.angle
- update()
-
-
-
-def populate_table():
- GUI.input_intensity.setText("%g" % system.input_intensity)
-
- GUI.table = QGridLayout()
- GUI.table.setColumnStretch(1, 1)
- GUI.table.setColumnStretch(2, 2)
- GUI.table.setColumnStretch(3, 5)
-
- while GUI.opt_operand.count() > 0: # FIXME
- GUI.opt_operand.removeItem(0)
-
- GUI.table_rows = list()
- for i, pol in enumerate(system.elements):
- GUI.table_rows.append(TableRow(pol, GUI.table, i + 1))
- GUI.opt_operand.addItem("Element #%d" % (i + 1), i)
+from ui_table import *
def update():
for i, pol in enumerate(system.elements):
@@ -406,96 +199,126 @@ def setup_menubar(win):
win.statusBar()
# FIXME: refactor
-def optimize(which):
- if len(system.elements) == 0:
- return
-
- op_idx = GUI.opt_operand.currentData()
- op = system.elements[op_idx]
+#def optimize(which):
+# if len(system.elements) == 0:
+# return
+#
+# op_idx = GUI.opt_operand.currentData()
+# op = system.elements[op_idx]
+#
+# def I(theta):
+# op.angle = theta
+# if op.ref is not False:
+# op.angle += system.elements[op.ref].angle
+#
+# state = None
+# for i, pol in enumerate(system.elements):
+# if i >= len(system.ignore) or not system.ignore[i]:
+# state = pol.mul(state)
+# if state is None:
+# return 1
+# else:
+# return float(np.abs(state[0] * state[0].conjugate() \
+# + state[1] * state[1].conjugate()))
+#
+# if which == "min":
+# f = I
+# else:
+# f = lambda theta: -I(theta)
+#
+# opt = scipy.optimize.minimize_scalar(f, bounds=[0, np.pi], method="bounded")
+# GUI.table_rows[op_idx].optbox.angle.edit.setText("%g" % round(opt.x * 180 / np.pi, 3))
+
+class MainWindow(QMainWindow):
+ def __init__(self, system_):
+ super().__init__()
+ self.statusBar()
+ self.setWindowTitle("Polarizzazione italiana")
+
+ global system
+ system = system_
+
+ ## Needless to say, I'm getting real tired of this whole Layout/Widget
+ ## clusterfuck in Qt
+ #root = QVBoxLayout()
+ #root_fucking_random_container = QWidget()
+ #root_fucking_random_container.setLayout(root)
+ #self.setCentralWidget(root_fucking_random_container)
+ #
+ ## Top bar (input intensity)
+ #box = QHBoxLayout()
+ #root.addLayout(box)
+ #
+ #box.addWidget(QLabel("Input intensity"))
+ #GUI.input_intensity = QLineEdit("1")
+ #GUI.input_intensity.textChanged.connect(self.change_input_intensity)
+ #box.addWidget(GUI.input_intensity)
+ #
+ #hbox = QHBoxLayout()
+ #root.addLayout(hbox)
+ #
+ #rhs = QVBoxLayout()
+ #
+ #Widocques.image = QImage("jones.jpg")
+ #GUI.widok = Widocques()
+ #rhs.addWidget(GUI.widok)
+ #
+ #optbox = QHBoxLayout()
+ #rhs.addLayout(optbox)
+ #
+ #GUI.opt_operand = QComboBox()
+ #optbox.addWidget(GUI.opt_operand)
+ #button = QPushButton("Find a minimum")
+ #button.pressed.connect(lambda: optimize("min"))
+ #optbox.addWidget(button)
+ #button = QPushButton("Find a maximum")
+ #button.pressed.connect(lambda: optimize("max"))
+ #optbox.addWidget(button)
+ #
+ #GUI.table = QTableWidget()
+ #populate_table()
+ #
+ #hbox.addWidget(GUI.scroll)
+ #hbox.addLayout(rhs)
+
+ setup_menubar(self)
- def I(theta):
- op.angle = theta
- if op.ref is not False:
- op.angle += system.elements[op.ref].angle
+ root = QVBoxLayout()
+ self.setCentralWidget(LayoutWrapper(root))
- state = None
- for i, pol in enumerate(system.elements):
- if i >= len(system.ignore) or not system.ignore[i]:
- state = pol.mul(state)
- if state is None:
- return 1
- else:
- return float(np.abs(state[0] * state[0].conjugate() \
- + state[1] * state[1].conjugate()))
+ box = QHBoxLayout()
+ root.addLayout(box)
- if which == "min":
- f = I
- else:
- f = lambda theta: -I(theta)
+ # Top bar
+ box.addWidget(QLabel("Input intensity"))
+ GUI.input_intensity = QLineEdit("%g" % system.input_intensity)
+ GUI.input_intensity.textChanged.connect(self.change_input_intensity)
+ box.addWidget(GUI.input_intensity)
- opt = scipy.optimize.minimize_scalar(f, bounds=[0, np.pi], method="bounded")
- GUI.table_rows[op_idx].optbox.angle.edit.setText("%g" % round(opt.x * 180 / np.pi, 3))
+ # Splitter
+ split = QSplitter()
+ root.addWidget(split)
+ # Table (LHS)
+ GUI.table = SystemTable()
+ split.addWidget(GUI.table)
+ # Splitter RHS
+ rhs = QVBoxLayout()
+ split.addWidget(LayoutWrapper(rhs))
-def change_input_intensity():
- try:
- system.input_intensity = float(GUI.input_intensity.text())
- update()
- except ValueError:
- pass
+ Widocques.image = QImage("jones.jpg")
+ GUI.widok = Widocques()
+ rhs.addWidget(GUI.widok)
-def setup(win, system_):
- global system
- system = system_
-
- # Needless to say, I'm getting real tired of this whole Layout/Widget
- # clusterfuck in Qt
- root = QVBoxLayout()
- root_fucking_random_container = QWidget()
- root_fucking_random_container.setLayout(root)
- win.setCentralWidget(root_fucking_random_container)
-
- # Top bar (input intensity)
- box = QHBoxLayout()
- root.addLayout(box)
-
- box.addWidget(QLabel("Input intensity"))
- GUI.input_intensity = QLineEdit("1")
- GUI.input_intensity.textChanged.connect(change_input_intensity)
- box.addWidget(GUI.input_intensity)
-
- hbox = QHBoxLayout()
- root.addLayout(hbox)
-
- rhs = QVBoxLayout()
-
- Widocques.image = QImage("jones.jpg")
- GUI.widok = Widocques()
- rhs.addWidget(GUI.widok)
-
- optbox = QHBoxLayout()
- rhs.addLayout(optbox)
-
- GUI.opt_operand = QComboBox()
- optbox.addWidget(GUI.opt_operand)
- button = QPushButton("Find a minimum")
- button.pressed.connect(lambda: optimize("min"))
- optbox.addWidget(button)
- button = QPushButton("Find a maximum")
- button.pressed.connect(lambda: optimize("max"))
- optbox.addWidget(button)
-
- GUI.scroll = QScrollArea()
- populate_table()
- GUI.table_frame = QFrame()
- GUI.table_frame.setLayout(GUI.table)
- GUI.scroll.setWidget(GUI.table_frame)
+ GUI.table.populate(system)
- hbox.addWidget(GUI.scroll)
- hbox.addLayout(rhs)
+ #update()
- setup_menubar(win)
+ def change_input_intensity(self):
+ try:
+ system.input_intensity = float(GUI.input_intensity.text())
+ update()
+ except ValueError:
+ pass
- update()
- win.show() \ No newline at end of file
diff --git a/src/ui_table.py b/src/ui_table.py
new file mode 100644
index 0000000..3d9a6fa
--- /dev/null
+++ b/src/ui_table.py
@@ -0,0 +1,222 @@
+import numpy as np
+from PyQt5.QtWidgets import *
+from PyQt5.QtGui import *
+from PyQt5.QtCore import *
+
+from ui import GUI, Pens
+from ui_widgets import *
+
+
+
+class ElementEditorWindow(QMainWindow):
+ windows = list()
+
+ @staticmethod
+ def open(pol):
+ win = ElementEditorWindow(pol)
+ win.show()
+ ElementEditorWindow.windows.append(win)
+
+ @staticmethod
+ def close_all(pol=None):
+ for win in ElementEditorWindow.windows:
+ if pol is None or pol == win.pol:
+ win.close()
+ del(win)
+
+ def __init__(self, pol):
+ super().__init__(flags=Qt.Dialog)
+ self.pol = pol
+
+ self.setWindowTitle("Element editor")
+ root = QVBoxLayout()
+ root_fucking_random_container = QWidget()
+ root_fucking_random_container.setLayout(root)
+ self.setCentralWidget(root_fucking_random_container)
+
+ # Name
+ box = QHBoxLayout()
+ root.addLayout(box)
+ box.addWidget(QLabel("Name"))
+ self.name = QLineEdit(self.pol.name)
+ self.name.textChanged.connect(self.change_name)
+ box.addWidget(self.name)
+
+ # OPTICS
+ root.addWidget(MeinGroßLabel("Optics"))
+
+ # Type combo
+ self.type = QComboBox()
+ self.type.addItem("Linear", "linear",)
+ self.type.addItem("Quarterwave plate", "quarterwave")
+ self.type.setCurrentIndex(0 if pol.type == "linear" else 1)
+ self.type.currentIndexChanged.connect(self.change_type)
+ root.addWidget(self.type)
+
+ # TRANSMITTANCE
+ root.addWidget(MeinGroßLabel("Transmittance"))
+
+ box = QHBoxLayout()
+ root.addLayout(box)
+
+ box.addWidget(QLabel("T"))
+ self.t1 = QLineEdit("%g" % self.pol.t1)
+ self.t1.textChanged.connect(self.change_t)
+ box.addWidget(self.t1)
+ self.t2 = QLineEdit("%g" % self.pol.t2)
+ self.t2.textChanged.connect(self.change_t)
+ box.addWidget(self.t2)
+
+ # ARRANGEMENT
+ root.addWidget(MeinGroßLabel("Arrangement"))
+
+ # Angle reference
+ self.ref = QComboBox()
+ self.populate_ref()
+ self.ref.currentIndexChanged.connect(update)
+ root.addWidget(self.ref)
+
+ # Delta angle
+ self.delta = AngleSlider("Delta")
+ self.delta.on_change = self.change_delta
+ root.addLayout(self.delta)
+
+ root.addItem(ExpandingSpacer())
+
+ # Done
+ self.done = QPushButton("Done")
+ self.done.pressed.connect(self.close)
+ root.addWidget(self.done)
+
+ def change_name(self):
+ self.pol.name = self.name.text()
+ self.pol.row.optbox.name.setText(self.pol.name)
+
+ def change_type(self):
+ self.pol.set_type(self.type.currentData())
+ update()
+
+ def change_delta(self):
+ try:
+ self.pol.delta = self.delta.angle / 180 * np.pi
+ update()
+ except ValueError:
+ pass
+
+ def change_t(self):
+ try:
+ self.pol.t1 = float(self.t1.text())
+ self.pol.t2 = float(self.t2.text())
+ update()
+ except ValueError:
+ pass
+
+ def populate_ref(self):
+ self.ref.addItem("Absolute", False)
+ for i, _ in enumerate(system.elements):
+ if i >= self.pol.rownum - 1:
+ continue
+ self.ref.addItem("Relative to #%d" % (i + 1), i)
+
+ if self.pol.ref is not False and i == self.pol.ref:
+ self.ref.setCurrentIndex(self.pol.ref + 1)
+
+
+
+class OptBox(QVBoxLayout):
+ def __init__(self, row, pol):
+ super().__init__()
+ self.row = row
+
+ # Name
+ self.name = MeinGroßLabel(pol.name)
+ self.name.setContextMenuPolicy(Qt.CustomContextMenu)
+ self.name.customContextMenuRequested.connect(lambda pos: OptBox.open_menu(self, pos))
+ self.addWidget(self.name)
+
+ # Enable checkbox
+ self.enable = QCheckBox("Enable")
+ self.enable.setChecked(True)
+ self.enable.stateChanged.connect(self.change_enable)
+ self.addWidget(self.enable)
+
+ # Angle
+ self.angle = AngleSlider()
+ self.angle.setValue(pol.angle * 180 / np.pi)
+ self.angle.on_change = lambda: TableRow.angle_change(row)
+ self.addLayout(self.angle)
+ self.addItem(ExpandingSpacer())
+
+ def open_menu(self, pos):
+ menu = QMenu()
+ menu.addAction("Edit", lambda: ElementEditorWindow.open(self.row.pol))
+ menu.addAction("Insert before", lambda: half_assed_element_creation(self.rownum - 1))
+ menu.addAction("Insert after", lambda: half_assed_element_creation(self.rownum))
+ menu.addAction("Delete", lambda: half_assed_element_deletion(self.rownum - 1))
+ menu.exec_(self.name.mapToGlobal(pos))
+
+ def change_enable(self):
+ self.row.pol.enable = self.enable.isChecked()
+ update()
+
+
+
+class SystemTableRow:
+ def __init__(self, parent, pol, row_number):
+ self.parent = parent
+ self.pol = pol
+ pol.row = self
+
+ self.angle = pol.angle
+ self.delta = pol.delta
+ self.ref = pol.ref
+
+ self.optbox = OptBox(self, pol)
+ parent.setCellWidget(row_number, 0, LayoutWrapper(self.optbox))
+
+ self.ellipse = EllipseWidget(pol)
+ parent.setCellWidget(row_number, 1, self.ellipse)
+
+ self.info = QVBoxLayout()
+ self.info_angle = MeinLabel()
+ self.info_angle.setAlignment(Qt.AlignLeft)
+ self.info.addWidget(self.info_angle)
+ self.info.addWidget(QLabel("Polarization state"))
+ self.info_jones = MeinLabel()
+ self.info_jones.setAlignment(Qt.AlignLeft)
+ self.info.addWidget(self.info_jones)
+ self.info.addItem(ExpandingSpacer())
+ parent.setCellWidget(row_number, 2, LayoutWrapper(self.info))
+
+ @staticmethod
+ def angle_change(row):
+ row.angle = row.optbox.angle.angle / 180 * np.pi
+ row.pol.angle = row.angle
+ update()
+
+
+
+class SystemTable(QTableWidget):
+ def __init__(self):
+ super().__init__()
+ self.rows = list()
+
+ self.setColumnCount(3) # this won't change
+
+ self.hh = self.horizontalHeader()
+ self.hh.setSectionResizeMode(QHeaderView.ResizeToContents)
+ #self.hh.hide()
+
+ self.vh = self.verticalHeader()
+ self.vh.setSectionResizeMode(QHeaderView.ResizeToContents)
+
+ def populate(self, system):
+ self.system = system
+
+ self.rows = list()
+ self.clearContents()
+ self.setRowCount(len(system.elements))
+
+ for i, pol in enumerate(system.elements):
+ self.rows.append(SystemTableRow(self, pol, i))
+
diff --git a/src/ui_widgets.py b/src/ui_widgets.py
index 9eabd2e..3babfa6 100644
--- a/src/ui_widgets.py
+++ b/src/ui_widgets.py
@@ -21,6 +21,11 @@ class MeinGroßLabel(QLabel):
self.setFont(GUI.bigfont)
self.setAlignment(Qt.AlignHCenter)
+class LayoutWrapper(QWidget):
+ def __init__(self, layout):
+ super().__init__()
+ self.setLayout(layout)
+
class EllipseWidget(QWidget):
def __init__(self, pol):
QWidget.__init__(self)