kopia lustrzana https://github.com/corrscope/corrscope
Merge pull request #219 from nyanpasu64/remove-ui-xml
Replace XML .ui files with stack-based Python codepull/357/head
commit
6c3bd82f58
|
|
@ -3,6 +3,7 @@ import os
|
||||||
import shutil
|
import shutil
|
||||||
import subprocess
|
import subprocess
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
from typing import List, Tuple
|
||||||
|
|
||||||
from PyInstaller.building.api import PYZ, EXE, COLLECT
|
from PyInstaller.building.api import PYZ, EXE, COLLECT
|
||||||
from PyInstaller.building.build_main import Analysis
|
from PyInstaller.building.build_main import Analysis
|
||||||
|
|
@ -19,10 +20,12 @@ def keep(dir, wildcard):
|
||||||
return [(include, dir) for include in includes]
|
return [(include, dir) for include in includes]
|
||||||
|
|
||||||
|
|
||||||
datas = keep("corrscope/gui", "*.ui")
|
InFile = str
|
||||||
|
OutFolder = str
|
||||||
|
datas: List[Tuple[InFile, OutFolder]] = []
|
||||||
|
|
||||||
version = v.pyinstaller_write_version()
|
version = v.pyinstaller_write_version()
|
||||||
datas.append((v.version_txt, "."))
|
datas += [(str(v.version_txt), ".")]
|
||||||
|
|
||||||
app_name = "corrscope"
|
app_name = "corrscope"
|
||||||
app_name_version = f"{app_name}-{version}"
|
app_name_version = f"{app_name}-{version}"
|
||||||
|
|
|
||||||
|
|
@ -9,7 +9,6 @@ from typing import Optional, List, Any, Tuple, Callable, Union, Dict, Sequence
|
||||||
import PyQt5.QtCore as qc
|
import PyQt5.QtCore as qc
|
||||||
import PyQt5.QtWidgets as qw
|
import PyQt5.QtWidgets as qw
|
||||||
import attr
|
import attr
|
||||||
from PyQt5 import uic
|
|
||||||
from PyQt5.QtCore import QModelIndex, Qt
|
from PyQt5.QtCore import QModelIndex, Qt
|
||||||
from PyQt5.QtCore import QVariant
|
from PyQt5.QtCore import QVariant
|
||||||
from PyQt5.QtGui import QKeySequence, QFont, QCloseEvent
|
from PyQt5.QtGui import QKeySequence, QFont, QCloseEvent
|
||||||
|
|
@ -21,7 +20,7 @@ from corrscope import cli
|
||||||
from corrscope.channel import ChannelConfig
|
from corrscope.channel import ChannelConfig
|
||||||
from corrscope.config import CorrError, copy_config, yaml
|
from corrscope.config import CorrError, copy_config, yaml
|
||||||
from corrscope.corrscope import CorrScope, Config, Arguments, default_config
|
from corrscope.corrscope import CorrScope, Config, Arguments, default_config
|
||||||
from corrscope.gui.data_bind import (
|
from corrscope.gui.model_bind import (
|
||||||
PresentationModel,
|
PresentationModel,
|
||||||
map_gui,
|
map_gui,
|
||||||
behead,
|
behead,
|
||||||
|
|
@ -34,6 +33,7 @@ from corrscope.gui.history_file_dlg import (
|
||||||
get_open_file_list,
|
get_open_file_list,
|
||||||
get_save_file_path,
|
get_save_file_path,
|
||||||
)
|
)
|
||||||
|
from corrscope.gui.view_mainwindow import MainWindow as Ui_MainWindow
|
||||||
from corrscope.gui.util import color2hex, Locked, find_ranges, TracebackDialog
|
from corrscope.gui.util import color2hex, Locked, find_ranges, TracebackDialog
|
||||||
from corrscope.layout import Orientation, StereoOrientation
|
from corrscope.layout import Orientation, StereoOrientation
|
||||||
from corrscope.outputs import IOutputConfig, FFplayOutputConfig, FFmpegOutputConfig
|
from corrscope.outputs import IOutputConfig, FFplayOutputConfig, FFmpegOutputConfig
|
||||||
|
|
@ -74,7 +74,7 @@ def gui_main(cfg_or_path: Union[Config, Path]):
|
||||||
sys.exit(app.exec_())
|
sys.exit(app.exec_())
|
||||||
|
|
||||||
|
|
||||||
class MainWindow(qw.QMainWindow):
|
class MainWindow(qw.QMainWindow, Ui_MainWindow):
|
||||||
"""
|
"""
|
||||||
Main window.
|
Main window.
|
||||||
|
|
||||||
|
|
@ -94,7 +94,7 @@ class MainWindow(qw.QMainWindow):
|
||||||
self.pref = gp.load_prefs()
|
self.pref = gp.load_prefs()
|
||||||
|
|
||||||
# Load UI.
|
# Load UI.
|
||||||
uic.loadUi(res("mainwindow.ui"), self) # sets windowTitle
|
self.setupUi(self) # sets windowTitle
|
||||||
|
|
||||||
# Bind UI buttons, etc. Functions block main thread, avoiding race conditions.
|
# Bind UI buttons, etc. Functions block main thread, avoiding race conditions.
|
||||||
self.master_audio_browse.clicked.connect(self.on_master_audio_browse)
|
self.master_audio_browse.clicked.connect(self.on_master_audio_browse)
|
||||||
|
|
@ -151,7 +151,7 @@ class MainWindow(qw.QMainWindow):
|
||||||
self._update_unsaved_title()
|
self._update_unsaved_title()
|
||||||
|
|
||||||
# GUI layout widgets
|
# GUI layout widgets
|
||||||
tabWidget: qw.QTabWidget
|
left_tabs: qw.QTabWidget
|
||||||
|
|
||||||
# Config models
|
# Config models
|
||||||
model: Optional["ConfigModel"] = None
|
model: Optional["ConfigModel"] = None
|
||||||
|
|
@ -232,7 +232,7 @@ class MainWindow(qw.QMainWindow):
|
||||||
self._cfg_path = cfg_path
|
self._cfg_path = cfg_path
|
||||||
self._any_unsaved = False
|
self._any_unsaved = False
|
||||||
self.load_title()
|
self.load_title()
|
||||||
self.tabWidget.setCurrentIndex(0)
|
self.left_tabs.setCurrentIndex(0)
|
||||||
|
|
||||||
if self.model is None:
|
if self.model is None:
|
||||||
self.model = ConfigModel(cfg)
|
self.model = ConfigModel(cfg)
|
||||||
|
|
|
||||||
|
|
@ -1,795 +0,0 @@
|
||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<ui version="4.0">
|
|
||||||
<class>MainWindow</class>
|
|
||||||
<widget class="QMainWindow" name="MainWindow">
|
|
||||||
<property name="geometry">
|
|
||||||
<rect>
|
|
||||||
<x>0</x>
|
|
||||||
<y>0</y>
|
|
||||||
<width>1160</width>
|
|
||||||
<height>0</height>
|
|
||||||
</rect>
|
|
||||||
</property>
|
|
||||||
<property name="windowTitle">
|
|
||||||
<string>MainWindow</string>
|
|
||||||
</property>
|
|
||||||
<widget class="QWidget" name="centralWidget">
|
|
||||||
<layout class="QHBoxLayout" name="horizontalLayout" stretch="0,1">
|
|
||||||
<item>
|
|
||||||
<widget class="QTabWidget" name="tabWidget">
|
|
||||||
<property name="sizePolicy">
|
|
||||||
<sizepolicy hsizetype="Fixed" vsizetype="Expanding">
|
|
||||||
<horstretch>0</horstretch>
|
|
||||||
<verstretch>0</verstretch>
|
|
||||||
</sizepolicy>
|
|
||||||
</property>
|
|
||||||
<property name="currentIndex">
|
|
||||||
<number>0</number>
|
|
||||||
</property>
|
|
||||||
<widget class="QWidget" name="tabGeneral">
|
|
||||||
<attribute name="title">
|
|
||||||
<string>&General</string>
|
|
||||||
</attribute>
|
|
||||||
<layout class="QVBoxLayout" name="verticalLayout_2">
|
|
||||||
<item>
|
|
||||||
<widget class="QGroupBox" name="optionGlobal">
|
|
||||||
<property name="title">
|
|
||||||
<string>Global</string>
|
|
||||||
</property>
|
|
||||||
<layout class="QFormLayout" name="formLayout">
|
|
||||||
<item row="0" column="0">
|
|
||||||
<widget class="QLabel" name="fpsL">
|
|
||||||
<property name="text">
|
|
||||||
<string>FPS</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="0" column="1">
|
|
||||||
<widget class="BoundSpinBox" name="fps">
|
|
||||||
<property name="minimum">
|
|
||||||
<number>1</number>
|
|
||||||
</property>
|
|
||||||
<property name="maximum">
|
|
||||||
<number>999</number>
|
|
||||||
</property>
|
|
||||||
<property name="singleStep">
|
|
||||||
<number>10</number>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="1" column="0">
|
|
||||||
<widget class="QLabel" name="trigger_msL">
|
|
||||||
<property name="text">
|
|
||||||
<string>Trigger Width</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="1" column="1">
|
|
||||||
<widget class="BoundSpinBox" name="trigger_ms">
|
|
||||||
<property name="minimum">
|
|
||||||
<number>5</number>
|
|
||||||
</property>
|
|
||||||
<property name="singleStep">
|
|
||||||
<number>5</number>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="2" column="0">
|
|
||||||
<widget class="QLabel" name="render_msL">
|
|
||||||
<property name="text">
|
|
||||||
<string>Render Width</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="2" column="1">
|
|
||||||
<widget class="BoundSpinBox" name="render_ms">
|
|
||||||
<property name="minimum">
|
|
||||||
<number>5</number>
|
|
||||||
</property>
|
|
||||||
<property name="singleStep">
|
|
||||||
<number>5</number>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="3" column="0">
|
|
||||||
<widget class="QLabel" name="amplificationL">
|
|
||||||
<property name="text">
|
|
||||||
<string>Amplification</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="3" column="1">
|
|
||||||
<widget class="BoundDoubleSpinBox" name="amplification">
|
|
||||||
<property name="singleStep">
|
|
||||||
<double>0.100000000000000</double>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="4" column="0">
|
|
||||||
<widget class="QLabel" name="begin_timeL">
|
|
||||||
<property name="text">
|
|
||||||
<string>Begin Time</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="4" column="1">
|
|
||||||
<widget class="BoundDoubleSpinBox" name="begin_time">
|
|
||||||
<property name="maximum">
|
|
||||||
<double>9999.000000000000000</double>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
</layout>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<widget class="QGroupBox" name="optionAppear">
|
|
||||||
<property name="title">
|
|
||||||
<string>Appearance</string>
|
|
||||||
</property>
|
|
||||||
<layout class="QFormLayout" name="formLayout_4">
|
|
||||||
<item row="0" column="0">
|
|
||||||
<widget class="QLabel" name="render_resolutionL">
|
|
||||||
<property name="text">
|
|
||||||
<string>Resolution</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="0" column="1">
|
|
||||||
<widget class="BoundLineEdit" name="render_resolution">
|
|
||||||
<property name="text">
|
|
||||||
<string>vs</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="1" column="0">
|
|
||||||
<widget class="QLabel" name="render__bg_colorL">
|
|
||||||
<property name="text">
|
|
||||||
<string>Background</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="1" column="1">
|
|
||||||
<widget class="BoundColorWidget" name="render__bg_color" native="true"/>
|
|
||||||
</item>
|
|
||||||
<item row="2" column="0">
|
|
||||||
<widget class="QLabel" name="render__init_line_colorL">
|
|
||||||
<property name="text">
|
|
||||||
<string>Line Color</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="2" column="1">
|
|
||||||
<widget class="BoundColorWidget" name="render__init_line_color" native="true"/>
|
|
||||||
</item>
|
|
||||||
<item row="3" column="0">
|
|
||||||
<widget class="QLabel" name="render__line_widthL">
|
|
||||||
<property name="text">
|
|
||||||
<string>Line Width</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="3" column="1">
|
|
||||||
<widget class="BoundDoubleSpinBox" name="render__line_width">
|
|
||||||
<property name="minimum">
|
|
||||||
<double>0.500000000000000</double>
|
|
||||||
</property>
|
|
||||||
<property name="singleStep">
|
|
||||||
<double>0.500000000000000</double>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="4" column="0">
|
|
||||||
<widget class="QLabel" name="render__grid_colorL">
|
|
||||||
<property name="text">
|
|
||||||
<string>Grid Color</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="4" column="1">
|
|
||||||
<widget class="OptionalColorWidget" name="render__grid_color" native="true"/>
|
|
||||||
</item>
|
|
||||||
<item row="5" column="0">
|
|
||||||
<widget class="QLabel" name="render__midline_colorL">
|
|
||||||
<property name="text">
|
|
||||||
<string>Midline Color</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="5" column="1">
|
|
||||||
<widget class="OptionalColorWidget" name="render__midline_color" native="true"/>
|
|
||||||
</item>
|
|
||||||
<item row="6" column="0">
|
|
||||||
<widget class="BoundCheckBox" name="render__v_midline">
|
|
||||||
<property name="text">
|
|
||||||
<string>Vertical</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="6" column="1">
|
|
||||||
<widget class="BoundCheckBox" name="render__h_midline">
|
|
||||||
<property name="text">
|
|
||||||
<string>Horizontal Midline</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
</layout>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<widget class="QGroupBox" name="optionLayout">
|
|
||||||
<property name="title">
|
|
||||||
<string>Layout</string>
|
|
||||||
</property>
|
|
||||||
<layout class="QFormLayout" name="formLayout_2">
|
|
||||||
<item row="0" column="0">
|
|
||||||
<widget class="QLabel" name="layout__orientationL">
|
|
||||||
<property name="text">
|
|
||||||
<string>Orientation</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="0" column="1">
|
|
||||||
<widget class="BoundComboBox" name="layout__orientation"/>
|
|
||||||
</item>
|
|
||||||
<item row="1" column="0">
|
|
||||||
<widget class="QLabel" name="layout__ncolsL">
|
|
||||||
<property name="text">
|
|
||||||
<string>Columns</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="1" column="1">
|
|
||||||
<layout class="QHBoxLayout" name="layoutDims">
|
|
||||||
<item>
|
|
||||||
<widget class="BoundSpinBox" name="layout__ncols">
|
|
||||||
<property name="specialValueText">
|
|
||||||
<string notr="true"> </string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<widget class="QLabel" name="layout__nrowsL">
|
|
||||||
<property name="text">
|
|
||||||
<string>Rows</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<widget class="BoundSpinBox" name="layout__nrows">
|
|
||||||
<property name="specialValueText">
|
|
||||||
<string notr="true"> </string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
</layout>
|
|
||||||
</item>
|
|
||||||
</layout>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<spacer name="verticalSpacer_2">
|
|
||||||
<property name="orientation">
|
|
||||||
<enum>Qt::Vertical</enum>
|
|
||||||
</property>
|
|
||||||
<property name="sizeHint" stdset="0">
|
|
||||||
<size>
|
|
||||||
<width>20</width>
|
|
||||||
<height>40</height>
|
|
||||||
</size>
|
|
||||||
</property>
|
|
||||||
</spacer>
|
|
||||||
</item>
|
|
||||||
</layout>
|
|
||||||
</widget>
|
|
||||||
<widget class="QWidget" name="tabStereo">
|
|
||||||
<attribute name="title">
|
|
||||||
<string>&Stereo</string>
|
|
||||||
</attribute>
|
|
||||||
<layout class="QVBoxLayout" name="verticalLayout_3">
|
|
||||||
<item>
|
|
||||||
<widget class="QGroupBox" name="optionStereo">
|
|
||||||
<property name="title">
|
|
||||||
<string>Stereo Enable</string>
|
|
||||||
</property>
|
|
||||||
<layout class="QFormLayout" name="formLayout_8">
|
|
||||||
<item row="0" column="0">
|
|
||||||
<widget class="QLabel" name="trigger_stereoL">
|
|
||||||
<property name="text">
|
|
||||||
<string>Trigger Stereo</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="0" column="1">
|
|
||||||
<widget class="BoundComboBox" name="trigger_stereo"/>
|
|
||||||
</item>
|
|
||||||
<item row="1" column="0">
|
|
||||||
<widget class="QLabel" name="render_stereoL">
|
|
||||||
<property name="text">
|
|
||||||
<string>Render Stereo</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="1" column="1">
|
|
||||||
<widget class="BoundComboBox" name="render_stereo"/>
|
|
||||||
</item>
|
|
||||||
</layout>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<widget class="QGroupBox" name="dockStereo_2">
|
|
||||||
<property name="title">
|
|
||||||
<string>Stereo Appearance</string>
|
|
||||||
</property>
|
|
||||||
<layout class="QFormLayout" name="formLayout_7">
|
|
||||||
<item row="0" column="0">
|
|
||||||
<widget class="QLabel" name="layout__stereo_orientationL">
|
|
||||||
<property name="text">
|
|
||||||
<string>Stereo Orientation</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="0" column="1">
|
|
||||||
<widget class="BoundComboBox" name="layout__stereo_orientation"/>
|
|
||||||
</item>
|
|
||||||
<item row="1" column="0">
|
|
||||||
<widget class="QLabel" name="render__stereo_grid_opacityL">
|
|
||||||
<property name="text">
|
|
||||||
<string>Grid Opacity</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="1" column="1">
|
|
||||||
<widget class="BoundDoubleSpinBox" name="render__stereo_grid_opacity">
|
|
||||||
<property name="maximum">
|
|
||||||
<double>1.000000000000000</double>
|
|
||||||
</property>
|
|
||||||
<property name="singleStep">
|
|
||||||
<double>0.250000000000000</double>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
</layout>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<spacer name="verticalSpacer_3">
|
|
||||||
<property name="orientation">
|
|
||||||
<enum>Qt::Vertical</enum>
|
|
||||||
</property>
|
|
||||||
<property name="sizeHint" stdset="0">
|
|
||||||
<size>
|
|
||||||
<width>20</width>
|
|
||||||
<height>40</height>
|
|
||||||
</size>
|
|
||||||
</property>
|
|
||||||
</spacer>
|
|
||||||
</item>
|
|
||||||
</layout>
|
|
||||||
</widget>
|
|
||||||
<widget class="QWidget" name="tabPerf">
|
|
||||||
<attribute name="title">
|
|
||||||
<string>&Performance</string>
|
|
||||||
</attribute>
|
|
||||||
<layout class="QVBoxLayout" name="verticalLayout">
|
|
||||||
<item>
|
|
||||||
<widget class="QGroupBox" name="perfAll">
|
|
||||||
<property name="title">
|
|
||||||
<string>Preview and Render</string>
|
|
||||||
</property>
|
|
||||||
<layout class="QFormLayout" name="formLayout_5">
|
|
||||||
<item row="0" column="0">
|
|
||||||
<widget class="QLabel" name="trigger_subsamplingL">
|
|
||||||
<property name="text">
|
|
||||||
<string>Trigger Subsampling</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="0" column="1">
|
|
||||||
<widget class="BoundSpinBox" name="trigger_subsampling">
|
|
||||||
<property name="minimum">
|
|
||||||
<number>1</number>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="1" column="0">
|
|
||||||
<widget class="QLabel" name="render_subsamplingL">
|
|
||||||
<property name="text">
|
|
||||||
<string>Render Subsampling</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="1" column="1">
|
|
||||||
<widget class="BoundSpinBox" name="render_subsampling">
|
|
||||||
<property name="minimum">
|
|
||||||
<number>1</number>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
</layout>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<widget class="QGroupBox" name="perfPreview">
|
|
||||||
<property name="title">
|
|
||||||
<string>Preview Only</string>
|
|
||||||
</property>
|
|
||||||
<layout class="QFormLayout" name="formLayout_3">
|
|
||||||
<item row="0" column="0">
|
|
||||||
<widget class="QLabel" name="render_subfpsL">
|
|
||||||
<property name="text">
|
|
||||||
<string>Render FPS Divisor</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="0" column="1">
|
|
||||||
<widget class="BoundSpinBox" name="render_subfps">
|
|
||||||
<property name="minimum">
|
|
||||||
<number>1</number>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="1" column="0">
|
|
||||||
<widget class="QLabel" name="render__res_divisorL">
|
|
||||||
<property name="text">
|
|
||||||
<string>Resolution Divisor</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="1" column="1">
|
|
||||||
<widget class="BoundDoubleSpinBox" name="render__res_divisor">
|
|
||||||
<property name="minimum">
|
|
||||||
<double>1.000000000000000</double>
|
|
||||||
</property>
|
|
||||||
<property name="singleStep">
|
|
||||||
<double>0.500000000000000</double>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
</layout>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<spacer name="verticalSpacer">
|
|
||||||
<property name="orientation">
|
|
||||||
<enum>Qt::Vertical</enum>
|
|
||||||
</property>
|
|
||||||
<property name="sizeHint" stdset="0">
|
|
||||||
<size>
|
|
||||||
<width>20</width>
|
|
||||||
<height>40</height>
|
|
||||||
</size>
|
|
||||||
</property>
|
|
||||||
</spacer>
|
|
||||||
</item>
|
|
||||||
</layout>
|
|
||||||
</widget>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<layout class="QVBoxLayout" name="audioColumn">
|
|
||||||
<item>
|
|
||||||
<layout class="QHBoxLayout" name="horizontalLayout_4">
|
|
||||||
<item>
|
|
||||||
<widget class="QGroupBox" name="audioGroup">
|
|
||||||
<property name="title">
|
|
||||||
<string>Master Audio</string>
|
|
||||||
</property>
|
|
||||||
<layout class="QHBoxLayout" name="horizontalLayout_3">
|
|
||||||
<item>
|
|
||||||
<widget class="BoundLineEdit" name="master_audio">
|
|
||||||
<property name="text">
|
|
||||||
<string>/</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<widget class="QPushButton" name="master_audio_browse">
|
|
||||||
<property name="text">
|
|
||||||
<string>&Browse...</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
</layout>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<widget class="QGroupBox" name="optionAudio">
|
|
||||||
<property name="sizePolicy">
|
|
||||||
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
|
|
||||||
<horstretch>0</horstretch>
|
|
||||||
<verstretch>0</verstretch>
|
|
||||||
</sizepolicy>
|
|
||||||
</property>
|
|
||||||
<property name="title">
|
|
||||||
<string>Trigger</string>
|
|
||||||
</property>
|
|
||||||
<layout class="QGridLayout" name="gridLayout">
|
|
||||||
<item row="0" column="1">
|
|
||||||
<widget class="QLabel" name="trigger__edge_strengthL">
|
|
||||||
<property name="text">
|
|
||||||
<string>Edge Strength</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="0" column="2">
|
|
||||||
<widget class="QLabel" name="trigger__responsivenessL">
|
|
||||||
<property name="text">
|
|
||||||
<string>Responsiveness</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="0" column="3">
|
|
||||||
<widget class="QLabel" name="trigger__buffer_falloffL">
|
|
||||||
<property name="text">
|
|
||||||
<string>Buffer Falloff</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="1" column="1">
|
|
||||||
<widget class="BoundDoubleSpinBox" name="trigger__edge_strength">
|
|
||||||
<property name="minimum">
|
|
||||||
<double>0.000000000000000</double>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="1" column="2">
|
|
||||||
<widget class="BoundDoubleSpinBox" name="trigger__responsiveness">
|
|
||||||
<property name="maximum">
|
|
||||||
<double>1.000000000000000</double>
|
|
||||||
</property>
|
|
||||||
<property name="singleStep">
|
|
||||||
<double>0.100000000000000</double>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="1" column="3">
|
|
||||||
<widget class="BoundDoubleSpinBox" name="trigger__buffer_falloff">
|
|
||||||
<property name="singleStep">
|
|
||||||
<double>0.500000000000000</double>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="0" column="4" rowspan="2">
|
|
||||||
<widget class="BoundCheckBox" name="trigger__pitch_tracking">
|
|
||||||
<property name="text">
|
|
||||||
<string>Pitch Tracking</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="0" column="0">
|
|
||||||
<widget class="QLabel" name="trigger__edge_directionL">
|
|
||||||
<property name="text">
|
|
||||||
<string>Edge Direction</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="1" column="0">
|
|
||||||
<widget class="BoundComboBox" name="trigger__edge_direction"/>
|
|
||||||
</item>
|
|
||||||
</layout>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
</layout>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<widget class="QGroupBox" name="channelsGroup">
|
|
||||||
<property name="title">
|
|
||||||
<string>Oscilloscope Channels</string>
|
|
||||||
</property>
|
|
||||||
<layout class="QVBoxLayout" name="verticalLayout_4">
|
|
||||||
<item>
|
|
||||||
<layout class="QHBoxLayout" name="channelBar">
|
|
||||||
<item>
|
|
||||||
<spacer name="horizontalSpacer">
|
|
||||||
<property name="orientation">
|
|
||||||
<enum>Qt::Horizontal</enum>
|
|
||||||
</property>
|
|
||||||
<property name="sizeHint" stdset="0">
|
|
||||||
<size>
|
|
||||||
<width>40</width>
|
|
||||||
<height>20</height>
|
|
||||||
</size>
|
|
||||||
</property>
|
|
||||||
</spacer>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<widget class="ShortcutButton" name="channelAdd">
|
|
||||||
<property name="text">
|
|
||||||
<string>&Add...</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<widget class="ShortcutButton" name="channelDelete">
|
|
||||||
<property name="text">
|
|
||||||
<string>&Delete</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<widget class="ShortcutButton" name="channelUp">
|
|
||||||
<property name="text">
|
|
||||||
<string>Up</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<widget class="ShortcutButton" name="channelDown">
|
|
||||||
<property name="text">
|
|
||||||
<string>Down</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
</layout>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<widget class="ChannelTableView" name="channel_view"/>
|
|
||||||
</item>
|
|
||||||
</layout>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
</layout>
|
|
||||||
</item>
|
|
||||||
</layout>
|
|
||||||
</widget>
|
|
||||||
<widget class="QMenuBar" name="menuBar">
|
|
||||||
<widget class="QMenu" name="menuFile">
|
|
||||||
<property name="title">
|
|
||||||
<string>&File</string>
|
|
||||||
</property>
|
|
||||||
<addaction name="actionNew"/>
|
|
||||||
<addaction name="actionOpen"/>
|
|
||||||
<addaction name="actionSave"/>
|
|
||||||
<addaction name="actionSaveAs"/>
|
|
||||||
<addaction name="separator"/>
|
|
||||||
<addaction name="actionPreview"/>
|
|
||||||
<addaction name="actionRender"/>
|
|
||||||
<addaction name="separator"/>
|
|
||||||
<addaction name="actionExit"/>
|
|
||||||
</widget>
|
|
||||||
<widget class="QMenu" name="menuTools">
|
|
||||||
<property name="title">
|
|
||||||
<string>&Tools</string>
|
|
||||||
</property>
|
|
||||||
<addaction name="action_separate_render_dir"/>
|
|
||||||
</widget>
|
|
||||||
<addaction name="menuFile"/>
|
|
||||||
<addaction name="menuTools"/>
|
|
||||||
</widget>
|
|
||||||
<widget class="QToolBar" name="toolBar">
|
|
||||||
<property name="windowTitle">
|
|
||||||
<string>toolBar</string>
|
|
||||||
</property>
|
|
||||||
<attribute name="toolBarArea">
|
|
||||||
<enum>TopToolBarArea</enum>
|
|
||||||
</attribute>
|
|
||||||
<attribute name="toolBarBreak">
|
|
||||||
<bool>false</bool>
|
|
||||||
</attribute>
|
|
||||||
<addaction name="actionNew"/>
|
|
||||||
<addaction name="actionOpen"/>
|
|
||||||
<addaction name="actionSave"/>
|
|
||||||
<addaction name="actionSaveAs"/>
|
|
||||||
<addaction name="separator"/>
|
|
||||||
<addaction name="actionPreview"/>
|
|
||||||
<addaction name="actionRender"/>
|
|
||||||
</widget>
|
|
||||||
<action name="actionOpen">
|
|
||||||
<property name="text">
|
|
||||||
<string>&Open</string>
|
|
||||||
</property>
|
|
||||||
<property name="shortcut">
|
|
||||||
<string>Ctrl+O</string>
|
|
||||||
</property>
|
|
||||||
</action>
|
|
||||||
<action name="actionSave">
|
|
||||||
<property name="text">
|
|
||||||
<string>&Save</string>
|
|
||||||
</property>
|
|
||||||
<property name="shortcut">
|
|
||||||
<string>Ctrl+S</string>
|
|
||||||
</property>
|
|
||||||
</action>
|
|
||||||
<action name="actionNew">
|
|
||||||
<property name="text">
|
|
||||||
<string>&New</string>
|
|
||||||
</property>
|
|
||||||
<property name="shortcut">
|
|
||||||
<string>Ctrl+N</string>
|
|
||||||
</property>
|
|
||||||
</action>
|
|
||||||
<action name="actionSaveAs">
|
|
||||||
<property name="text">
|
|
||||||
<string>Save &As</string>
|
|
||||||
</property>
|
|
||||||
<property name="shortcut">
|
|
||||||
<string>Ctrl+Shift+S</string>
|
|
||||||
</property>
|
|
||||||
</action>
|
|
||||||
<action name="actionExit">
|
|
||||||
<property name="text">
|
|
||||||
<string>E&xit</string>
|
|
||||||
</property>
|
|
||||||
<property name="shortcut">
|
|
||||||
<string>Ctrl+Q</string>
|
|
||||||
</property>
|
|
||||||
</action>
|
|
||||||
<action name="actionPreview">
|
|
||||||
<property name="text">
|
|
||||||
<string>&Preview</string>
|
|
||||||
</property>
|
|
||||||
<property name="shortcut">
|
|
||||||
<string>Ctrl+P</string>
|
|
||||||
</property>
|
|
||||||
</action>
|
|
||||||
<action name="actionRender">
|
|
||||||
<property name="text">
|
|
||||||
<string>&Render to Video</string>
|
|
||||||
</property>
|
|
||||||
<property name="shortcut">
|
|
||||||
<string>Ctrl+R</string>
|
|
||||||
</property>
|
|
||||||
</action>
|
|
||||||
<action name="action_separate_render_dir">
|
|
||||||
<property name="checkable">
|
|
||||||
<bool>true</bool>
|
|
||||||
</property>
|
|
||||||
<property name="text">
|
|
||||||
<string>&Separate Render Folder</string>
|
|
||||||
</property>
|
|
||||||
</action>
|
|
||||||
</widget>
|
|
||||||
<layoutdefault spacing="6" margin="11"/>
|
|
||||||
<customwidgets>
|
|
||||||
<customwidget>
|
|
||||||
<class>BoundLineEdit</class>
|
|
||||||
<extends>QLineEdit</extends>
|
|
||||||
<header>corrscope/gui/data_bind.h</header>
|
|
||||||
</customwidget>
|
|
||||||
<customwidget>
|
|
||||||
<class>BoundSpinBox</class>
|
|
||||||
<extends>QSpinBox</extends>
|
|
||||||
<header>corrscope/gui/data_bind.h</header>
|
|
||||||
</customwidget>
|
|
||||||
<customwidget>
|
|
||||||
<class>BoundDoubleSpinBox</class>
|
|
||||||
<extends>QDoubleSpinBox</extends>
|
|
||||||
<header>corrscope/gui/data_bind.h</header>
|
|
||||||
</customwidget>
|
|
||||||
<customwidget>
|
|
||||||
<class>BoundComboBox</class>
|
|
||||||
<extends>QComboBox</extends>
|
|
||||||
<header>corrscope/gui/data_bind.h</header>
|
|
||||||
</customwidget>
|
|
||||||
<customwidget>
|
|
||||||
<class>BoundCheckBox</class>
|
|
||||||
<extends>QCheckBox</extends>
|
|
||||||
<header>corrscope/gui/data_bind.h</header>
|
|
||||||
</customwidget>
|
|
||||||
<customwidget>
|
|
||||||
<class>ShortcutButton</class>
|
|
||||||
<extends>QPushButton</extends>
|
|
||||||
<header>corrscope/gui/__init__.h</header>
|
|
||||||
</customwidget>
|
|
||||||
<customwidget>
|
|
||||||
<class>ChannelTableView</class>
|
|
||||||
<extends>QTableView</extends>
|
|
||||||
<header>corrscope/gui/__init__.h</header>
|
|
||||||
</customwidget>
|
|
||||||
<customwidget>
|
|
||||||
<class>BoundColorWidget</class>
|
|
||||||
<extends>QWidget</extends>
|
|
||||||
<header>corrscope/gui/data_bind.h</header>
|
|
||||||
<container>1</container>
|
|
||||||
</customwidget>
|
|
||||||
<customwidget>
|
|
||||||
<class>OptionalColorWidget</class>
|
|
||||||
<extends>QWidget</extends>
|
|
||||||
<header>corrscope/gui/data_bind.h</header>
|
|
||||||
<container>1</container>
|
|
||||||
</customwidget>
|
|
||||||
</customwidgets>
|
|
||||||
<resources/>
|
|
||||||
<connections/>
|
|
||||||
</ui>
|
|
||||||
|
|
@ -71,6 +71,9 @@ class PresentationModel(qc.QObject):
|
||||||
updater()
|
updater()
|
||||||
|
|
||||||
|
|
||||||
|
SKIP_BINDING = "skip"
|
||||||
|
|
||||||
|
|
||||||
def map_gui(view: "MainWindow", model: PresentationModel) -> None:
|
def map_gui(view: "MainWindow", model: PresentationModel) -> None:
|
||||||
"""
|
"""
|
||||||
Binding:
|
Binding:
|
||||||
|
|
@ -90,7 +93,8 @@ def map_gui(view: "MainWindow", model: PresentationModel) -> None:
|
||||||
# Exclude nameless ColorText inside BoundColorWidget wrapper,
|
# Exclude nameless ColorText inside BoundColorWidget wrapper,
|
||||||
# since bind_widget(path="") will crash.
|
# since bind_widget(path="") will crash.
|
||||||
# BoundColorWidget.bind_widget() handles binding children.
|
# BoundColorWidget.bind_widget() handles binding children.
|
||||||
if path:
|
if path != SKIP_BINDING:
|
||||||
|
assert path != ""
|
||||||
widget.bind_widget(model, path)
|
widget.bind_widget(model, path)
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -366,6 +370,7 @@ class _ColorText(BoundLineEdit):
|
||||||
|
|
||||||
def __init__(self, parent: QWidget, optional: bool):
|
def __init__(self, parent: QWidget, optional: bool):
|
||||||
super().__init__(parent)
|
super().__init__(parent)
|
||||||
|
self.setObjectName(SKIP_BINDING)
|
||||||
self.optional = optional
|
self.optional = optional
|
||||||
|
|
||||||
hex_color = qc.pyqtSignal(str)
|
hex_color = qc.pyqtSignal(str)
|
||||||
|
|
@ -0,0 +1,2 @@
|
||||||
|
SOURCES += view_mainwindow.py
|
||||||
|
TRANSLATIONS += corrscope_xa.ts
|
||||||
|
|
@ -0,0 +1,402 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
|
from PyQt5.QtCore import *
|
||||||
|
from PyQt5.QtWidgets import *
|
||||||
|
|
||||||
|
from corrscope.gui.view_stack import (
|
||||||
|
LayoutStack,
|
||||||
|
set_layout,
|
||||||
|
central_widget,
|
||||||
|
append_widget,
|
||||||
|
add_row,
|
||||||
|
add_tab,
|
||||||
|
set_attr_objectName,
|
||||||
|
append_stretch,
|
||||||
|
add_grid_col,
|
||||||
|
Both,
|
||||||
|
set_menu_bar,
|
||||||
|
append_menu,
|
||||||
|
add_toolbar,
|
||||||
|
)
|
||||||
|
|
||||||
|
NBSP = "\xa0"
|
||||||
|
|
||||||
|
|
||||||
|
def fixed_size_policy():
|
||||||
|
return QSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed)
|
||||||
|
|
||||||
|
|
||||||
|
# noinspection PyAttributeOutsideInit
|
||||||
|
class MainWindow(QWidget):
|
||||||
|
@staticmethod
|
||||||
|
def tr(*args, **kwargs) -> str:
|
||||||
|
"""Only at runtime, not at pylupdate5 time."""
|
||||||
|
# noinspection PyCallByClass,PyTypeChecker
|
||||||
|
return QCoreApplication.translate("MainWindow", *args, **kwargs)
|
||||||
|
|
||||||
|
def setupUi(self, MainWindow: QMainWindow):
|
||||||
|
MainWindow.resize(1160, 0)
|
||||||
|
|
||||||
|
s = LayoutStack(MainWindow)
|
||||||
|
|
||||||
|
# Window contents
|
||||||
|
with central_widget(s, QWidget) as self.centralWidget:
|
||||||
|
horizontalLayout = set_layout(s, QHBoxLayout)
|
||||||
|
|
||||||
|
# Left-hand config tabs
|
||||||
|
with append_widget(s, QTabWidget) as self.left_tabs:
|
||||||
|
self.tabGeneral = self.add_general_tab(s)
|
||||||
|
self.tabStereo = self.add_stereo_tab(s)
|
||||||
|
self.tabPerf = self.add_performance_tab(s)
|
||||||
|
|
||||||
|
# Right-hand channel list
|
||||||
|
with append_widget(s, QVBoxLayout) as self.audioColumn:
|
||||||
|
|
||||||
|
# Top bar (master audio, trigger)
|
||||||
|
self.add_top_bar(s)
|
||||||
|
|
||||||
|
# Channel list (group box)
|
||||||
|
self.channelsGroup = self.add_channels_list(s)
|
||||||
|
|
||||||
|
# Right-hand channel list expands to fill space.
|
||||||
|
horizontalLayout.setStretch(1, 1)
|
||||||
|
|
||||||
|
self.add_actions(s, MainWindow)
|
||||||
|
|
||||||
|
# Creates references to labels
|
||||||
|
set_attr_objectName(self, s)
|
||||||
|
|
||||||
|
# Initializes labels by reference
|
||||||
|
self.retranslateUi(MainWindow)
|
||||||
|
self.left_tabs.setCurrentIndex(0)
|
||||||
|
|
||||||
|
# Depends on objectName
|
||||||
|
QMetaObject.connectSlotsByName(MainWindow)
|
||||||
|
|
||||||
|
def add_general_tab(self, s: LayoutStack) -> QWidget:
|
||||||
|
tr = self.tr
|
||||||
|
with self._add_tab(s, tr("&General")) as tab:
|
||||||
|
set_layout(s, QVBoxLayout)
|
||||||
|
|
||||||
|
# Global group
|
||||||
|
with append_widget(s, QGroupBox) as self.optionGlobal:
|
||||||
|
set_layout(s, QFormLayout)
|
||||||
|
|
||||||
|
with add_row(s, BoundSpinBox) as self.fps:
|
||||||
|
self.fps.setMinimum(1)
|
||||||
|
self.fps.setMaximum(999)
|
||||||
|
self.fps.setSingleStep(10)
|
||||||
|
|
||||||
|
with add_row(s, BoundSpinBox) as self.trigger_ms:
|
||||||
|
self.trigger_ms.setMinimum(5)
|
||||||
|
self.trigger_ms.setSingleStep(5)
|
||||||
|
|
||||||
|
with add_row(s, BoundSpinBox) as self.render_ms:
|
||||||
|
self.render_ms.setMinimum(5)
|
||||||
|
self.render_ms.setSingleStep(5)
|
||||||
|
|
||||||
|
with add_row(s, BoundDoubleSpinBox) as self.amplification:
|
||||||
|
self.amplification.setSingleStep(0.1)
|
||||||
|
|
||||||
|
with add_row(s, BoundDoubleSpinBox) as self.begin_time:
|
||||||
|
self.begin_time.setMaximum(9999.0)
|
||||||
|
|
||||||
|
with append_widget(s, QGroupBox) as self.optionAppearance:
|
||||||
|
set_layout(s, QFormLayout)
|
||||||
|
|
||||||
|
with add_row(s, BoundLineEdit) as self.render_resolution:
|
||||||
|
pass
|
||||||
|
|
||||||
|
with add_row(s, BoundColorWidget) as self.render__bg_color:
|
||||||
|
pass
|
||||||
|
|
||||||
|
with add_row(s, BoundColorWidget) as self.render__init_line_color:
|
||||||
|
pass
|
||||||
|
|
||||||
|
with add_row(s, BoundDoubleSpinBox) as self.render__line_width:
|
||||||
|
self.render__line_width.setMinimum(0.5)
|
||||||
|
self.render__line_width.setSingleStep(0.5)
|
||||||
|
|
||||||
|
with add_row(s, OptionalColorWidget) as self.render__grid_color:
|
||||||
|
pass
|
||||||
|
|
||||||
|
with add_row(s, OptionalColorWidget) as self.render__midline_color:
|
||||||
|
pass
|
||||||
|
|
||||||
|
with add_row(s, BoundCheckBox, BoundCheckBox) as (
|
||||||
|
self.render__v_midline,
|
||||||
|
self.render__h_midline,
|
||||||
|
):
|
||||||
|
pass
|
||||||
|
|
||||||
|
with append_widget(s, QGroupBox) as self.optionLayout:
|
||||||
|
set_layout(s, QFormLayout)
|
||||||
|
|
||||||
|
with add_row(s, BoundComboBox) as self.layout__orientation:
|
||||||
|
pass
|
||||||
|
|
||||||
|
with add_row(s, QLabel, QHBoxLayout) as (
|
||||||
|
self.layout__ncolsL,
|
||||||
|
self.layoutDims,
|
||||||
|
):
|
||||||
|
with append_widget(s, BoundSpinBox) as self.layout__ncols:
|
||||||
|
self.layout__ncols.setSpecialValueText(NBSP)
|
||||||
|
|
||||||
|
with append_widget(s, QLabel) as self.layout__nrowsL:
|
||||||
|
pass
|
||||||
|
|
||||||
|
with append_widget(s, BoundSpinBox) as self.layout__nrows:
|
||||||
|
self.layout__nrows.setSpecialValueText(NBSP)
|
||||||
|
|
||||||
|
append_stretch(s)
|
||||||
|
|
||||||
|
return tab
|
||||||
|
|
||||||
|
def add_stereo_tab(self, s: LayoutStack) -> QWidget:
|
||||||
|
tr = self.tr
|
||||||
|
with self._add_tab(s, tr("&Stereo")) as tab:
|
||||||
|
set_layout(s, QVBoxLayout)
|
||||||
|
|
||||||
|
with append_widget(s, QGroupBox) as self.optionStereo:
|
||||||
|
set_layout(s, QFormLayout)
|
||||||
|
with add_row(s, BoundComboBox) as self.trigger_stereo:
|
||||||
|
pass
|
||||||
|
|
||||||
|
with add_row(s, BoundComboBox) as self.render_stereo:
|
||||||
|
pass
|
||||||
|
|
||||||
|
with append_widget(s, QGroupBox) as self.dockStereo_2:
|
||||||
|
set_layout(s, QFormLayout)
|
||||||
|
|
||||||
|
with add_row(s, BoundComboBox) as self.layout__stereo_orientation:
|
||||||
|
pass
|
||||||
|
|
||||||
|
with add_row(s, BoundDoubleSpinBox) as (
|
||||||
|
self.render__stereo_grid_opacity
|
||||||
|
):
|
||||||
|
self.render__stereo_grid_opacity.setMaximum(1.0)
|
||||||
|
self.render__stereo_grid_opacity.setSingleStep(0.25)
|
||||||
|
|
||||||
|
append_stretch(s)
|
||||||
|
|
||||||
|
return tab
|
||||||
|
|
||||||
|
def add_performance_tab(self, s: LayoutStack) -> QWidget:
|
||||||
|
tr = self.tr
|
||||||
|
with self._add_tab(s, tr("&Performance")) as tab:
|
||||||
|
set_layout(s, QVBoxLayout)
|
||||||
|
|
||||||
|
with append_widget(s, QGroupBox) as self.perfAll:
|
||||||
|
set_layout(s, QFormLayout)
|
||||||
|
|
||||||
|
with add_row(s, BoundSpinBox) as self.trigger_subsampling:
|
||||||
|
self.trigger_subsampling.setMinimum(1)
|
||||||
|
|
||||||
|
with add_row(s, BoundSpinBox) as self.render_subsampling:
|
||||||
|
self.render_subsampling.setMinimum(1)
|
||||||
|
|
||||||
|
with append_widget(s, QGroupBox) as self.perfPreview:
|
||||||
|
set_layout(s, QFormLayout)
|
||||||
|
|
||||||
|
with add_row(s, BoundSpinBox) as self.render_subfps:
|
||||||
|
self.render_subfps.setMinimum(1)
|
||||||
|
|
||||||
|
with add_row(s, BoundDoubleSpinBox) as self.render__res_divisor:
|
||||||
|
self.render__res_divisor.setMinimum(1.0)
|
||||||
|
self.render__res_divisor.setSingleStep(0.5)
|
||||||
|
|
||||||
|
append_stretch(s)
|
||||||
|
|
||||||
|
return tab
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def _add_tab(s: LayoutStack, label: str = ""):
|
||||||
|
return add_tab(s, QWidget, label)
|
||||||
|
|
||||||
|
def add_top_bar(self, s):
|
||||||
|
with append_widget(s, QHBoxLayout):
|
||||||
|
# Master audio
|
||||||
|
with append_widget(s, QGroupBox) as self.masterAudioGroup:
|
||||||
|
set_layout(s, QHBoxLayout)
|
||||||
|
with append_widget(s, BoundLineEdit) as self.master_audio:
|
||||||
|
pass
|
||||||
|
with append_widget(s, QPushButton) as self.master_audio_browse:
|
||||||
|
pass
|
||||||
|
|
||||||
|
# Trigger config
|
||||||
|
with append_widget(s, QGroupBox) as self.optionAudio:
|
||||||
|
# Prevent expansion (does nothing even if removed :| )
|
||||||
|
self.optionAudio.setSizePolicy(fixed_size_policy())
|
||||||
|
|
||||||
|
set_layout(s, QGridLayout)
|
||||||
|
|
||||||
|
with add_grid_col(s, BoundComboBox) as (self.trigger__edge_direction):
|
||||||
|
pass
|
||||||
|
|
||||||
|
with add_grid_col(s, BoundDoubleSpinBox) as (
|
||||||
|
self.trigger__edge_strength
|
||||||
|
):
|
||||||
|
self.trigger__edge_strength.setMinimum(0.0)
|
||||||
|
|
||||||
|
with add_grid_col(s, BoundDoubleSpinBox) as (
|
||||||
|
self.trigger__responsiveness
|
||||||
|
):
|
||||||
|
self.trigger__responsiveness.setMaximum(1.0)
|
||||||
|
self.trigger__responsiveness.setSingleStep(0.1)
|
||||||
|
|
||||||
|
with add_grid_col(s, BoundDoubleSpinBox) as (
|
||||||
|
self.trigger__buffer_falloff
|
||||||
|
):
|
||||||
|
self.trigger__buffer_falloff.setSingleStep(0.5)
|
||||||
|
|
||||||
|
with add_grid_col(s, BoundCheckBox, Both) as (
|
||||||
|
self.trigger__pitch_tracking
|
||||||
|
):
|
||||||
|
assert isinstance(self.trigger__pitch_tracking, QWidget)
|
||||||
|
|
||||||
|
def add_channels_list(self, s):
|
||||||
|
with append_widget(s, QGroupBox) as group:
|
||||||
|
set_layout(s, QVBoxLayout)
|
||||||
|
|
||||||
|
# Button toolbar
|
||||||
|
with append_widget(s, QHBoxLayout) as self.channelBar:
|
||||||
|
append_stretch(s)
|
||||||
|
|
||||||
|
with append_widget(s, ShortcutButton) as self.channelAdd:
|
||||||
|
pass
|
||||||
|
with append_widget(s, ShortcutButton) as self.channelDelete:
|
||||||
|
pass
|
||||||
|
with append_widget(s, ShortcutButton) as self.channelUp:
|
||||||
|
pass
|
||||||
|
with append_widget(s, ShortcutButton) as self.channelDown:
|
||||||
|
pass
|
||||||
|
|
||||||
|
# Spreadsheet grid
|
||||||
|
with append_widget(s, ChannelTableView) as self.channel_view:
|
||||||
|
pass
|
||||||
|
|
||||||
|
return group
|
||||||
|
|
||||||
|
def add_actions(self, s: LayoutStack, MainWindow):
|
||||||
|
# Setup actions
|
||||||
|
self.actionOpen = QAction(MainWindow)
|
||||||
|
self.actionSave = QAction(MainWindow)
|
||||||
|
self.actionNew = QAction(MainWindow)
|
||||||
|
self.actionSaveAs = QAction(MainWindow)
|
||||||
|
self.actionExit = QAction(MainWindow)
|
||||||
|
self.actionPreview = QAction(MainWindow)
|
||||||
|
self.actionRender = QAction(MainWindow)
|
||||||
|
self.action_separate_render_dir = QAction(MainWindow)
|
||||||
|
self.action_separate_render_dir.setCheckable(True)
|
||||||
|
|
||||||
|
# Setup menu_bar
|
||||||
|
assert s.widget is MainWindow
|
||||||
|
with set_menu_bar(s) as self.menuBar:
|
||||||
|
with append_menu(s) as self.menuFile:
|
||||||
|
self.menuFile.addAction(self.actionNew)
|
||||||
|
self.menuFile.addAction(self.actionOpen)
|
||||||
|
self.menuFile.addAction(self.actionSave)
|
||||||
|
self.menuFile.addAction(self.actionSaveAs)
|
||||||
|
self.menuFile.addSeparator()
|
||||||
|
self.menuFile.addAction(self.actionPreview)
|
||||||
|
self.menuFile.addAction(self.actionRender)
|
||||||
|
self.menuFile.addSeparator()
|
||||||
|
self.menuFile.addAction(self.actionExit)
|
||||||
|
|
||||||
|
with append_menu(s) as self.menuTools:
|
||||||
|
self.menuTools.addAction(self.action_separate_render_dir)
|
||||||
|
|
||||||
|
# Setup toolbar
|
||||||
|
with add_toolbar(s, Qt.TopToolBarArea) as self.toolBar:
|
||||||
|
self.toolBar.addAction(self.actionNew)
|
||||||
|
self.toolBar.addAction(self.actionOpen)
|
||||||
|
self.toolBar.addAction(self.actionSave)
|
||||||
|
self.toolBar.addAction(self.actionSaveAs)
|
||||||
|
self.toolBar.addSeparator()
|
||||||
|
self.toolBar.addAction(self.actionPreview)
|
||||||
|
self.toolBar.addAction(self.actionRender)
|
||||||
|
|
||||||
|
# noinspection PyUnresolvedReferences
|
||||||
|
def retranslateUi(self, MainWindow):
|
||||||
|
tr = self.tr
|
||||||
|
|
||||||
|
MainWindow.setWindowTitle(tr("MainWindow"))
|
||||||
|
|
||||||
|
self.optionGlobal.setTitle(tr("Global"))
|
||||||
|
self.fpsL.setText(tr("FPS"))
|
||||||
|
self.trigger_msL.setText(tr("Trigger Width"))
|
||||||
|
self.render_msL.setText(tr("Render Width"))
|
||||||
|
self.amplificationL.setText(tr("Amplification"))
|
||||||
|
self.begin_timeL.setText(tr("Begin Time"))
|
||||||
|
self.optionAppearance.setTitle(tr("Appearance"))
|
||||||
|
self.render_resolutionL.setText(tr("Resolution"))
|
||||||
|
self.render_resolution.setText(tr("vs"))
|
||||||
|
self.render__bg_colorL.setText(tr("Background"))
|
||||||
|
self.render__init_line_colorL.setText(tr("Line Color"))
|
||||||
|
self.render__line_widthL.setText(tr("Line Width"))
|
||||||
|
self.render__grid_colorL.setText(tr("Grid Color"))
|
||||||
|
self.render__midline_colorL.setText(tr("Midline Color"))
|
||||||
|
self.render__v_midline.setText(tr("Vertical"))
|
||||||
|
self.render__h_midline.setText(tr("Horizontal Midline"))
|
||||||
|
self.optionLayout.setTitle(tr("Layout"))
|
||||||
|
self.layout__orientationL.setText(tr("Orientation"))
|
||||||
|
self.layout__ncolsL.setText(tr("Columns"))
|
||||||
|
self.layout__nrowsL.setText(tr("Rows"))
|
||||||
|
self.optionStereo.setTitle(tr("Stereo Enable"))
|
||||||
|
self.trigger_stereoL.setText(tr("Trigger Stereo"))
|
||||||
|
self.render_stereoL.setText(tr("Render Stereo"))
|
||||||
|
self.dockStereo_2.setTitle(tr("Stereo Appearance"))
|
||||||
|
self.layout__stereo_orientationL.setText(tr("Stereo Orientation"))
|
||||||
|
self.render__stereo_grid_opacityL.setText(tr("Grid Opacity"))
|
||||||
|
|
||||||
|
self.perfAll.setTitle(tr("Preview and Render"))
|
||||||
|
self.trigger_subsamplingL.setText(tr("Trigger Subsampling"))
|
||||||
|
self.render_subsamplingL.setText(tr("Render Subsampling"))
|
||||||
|
self.perfPreview.setTitle(tr("Preview Only"))
|
||||||
|
self.render_subfpsL.setText(tr("Render FPS Divisor"))
|
||||||
|
self.render__res_divisorL.setText(tr("Resolution Divisor"))
|
||||||
|
self.masterAudioGroup.setTitle(tr("Master Audio"))
|
||||||
|
self.master_audio.setText(tr("/"))
|
||||||
|
self.master_audio_browse.setText(tr("&Browse..."))
|
||||||
|
self.optionAudio.setTitle(tr("Trigger"))
|
||||||
|
self.trigger__edge_strengthL.setText(tr("Edge Strength"))
|
||||||
|
self.trigger__responsivenessL.setText(tr("Responsiveness"))
|
||||||
|
self.trigger__buffer_falloffL.setText(tr("Buffer Falloff"))
|
||||||
|
self.trigger__pitch_tracking.setText(tr("Pitch Tracking"))
|
||||||
|
self.trigger__edge_directionL.setText(tr("Edge Direction"))
|
||||||
|
|
||||||
|
self.channelsGroup.setTitle(tr("Oscilloscope Channels"))
|
||||||
|
self.channelAdd.setText(tr("&Add..."))
|
||||||
|
self.channelDelete.setText(tr("&Delete"))
|
||||||
|
self.channelUp.setText(tr("Up"))
|
||||||
|
self.channelDown.setText(tr("Down"))
|
||||||
|
self.menuFile.setTitle(tr("&File"))
|
||||||
|
self.menuTools.setTitle(tr("&Tools"))
|
||||||
|
self.toolBar.setWindowTitle(tr("toolBar"))
|
||||||
|
self.actionOpen.setText(tr("&Open"))
|
||||||
|
self.actionOpen.setShortcut(tr("Ctrl+O"))
|
||||||
|
self.actionSave.setText(tr("&Save"))
|
||||||
|
self.actionSave.setShortcut(tr("Ctrl+S"))
|
||||||
|
self.actionNew.setText(tr("&New"))
|
||||||
|
self.actionNew.setShortcut(tr("Ctrl+N"))
|
||||||
|
self.actionSaveAs.setText(tr("Save &As"))
|
||||||
|
self.actionSaveAs.setShortcut(tr("Ctrl+Shift+S"))
|
||||||
|
self.actionExit.setText(tr("E&xit"))
|
||||||
|
self.actionExit.setShortcut(tr("Ctrl+Q"))
|
||||||
|
self.actionPreview.setText(tr("&Preview"))
|
||||||
|
self.actionPreview.setShortcut(tr("Ctrl+P"))
|
||||||
|
self.actionRender.setText(tr("&Render to Video"))
|
||||||
|
self.actionRender.setShortcut(tr("Ctrl+R"))
|
||||||
|
self.action_separate_render_dir.setText(tr("&Separate Render Folder"))
|
||||||
|
|
||||||
|
|
||||||
|
from corrscope.gui.__init__ import ChannelTableView, ShortcutButton
|
||||||
|
from corrscope.gui.model_bind import (
|
||||||
|
BoundCheckBox,
|
||||||
|
BoundColorWidget,
|
||||||
|
BoundComboBox,
|
||||||
|
BoundDoubleSpinBox,
|
||||||
|
BoundLineEdit,
|
||||||
|
BoundSpinBox,
|
||||||
|
OptionalColorWidget,
|
||||||
|
)
|
||||||
|
|
@ -0,0 +1,280 @@
|
||||||
|
from contextlib import contextmanager
|
||||||
|
from typing import *
|
||||||
|
|
||||||
|
import attr
|
||||||
|
from PyQt5.QtCore import QObject, Qt
|
||||||
|
from PyQt5.QtWidgets import *
|
||||||
|
|
||||||
|
from corrscope.util import obj_name
|
||||||
|
|
||||||
|
T = TypeVar("T")
|
||||||
|
ctx = Iterator
|
||||||
|
SomeQW = TypeVar("SomeQW", bound=QWidget)
|
||||||
|
WidgetOrLayout = TypeVar("WidgetOrLayout", bound=Union[QWidget, QLayout])
|
||||||
|
|
||||||
|
|
||||||
|
def new_widget_or_layout(
|
||||||
|
item_type: Type[WidgetOrLayout], parent: QWidget
|
||||||
|
) -> WidgetOrLayout:
|
||||||
|
"""Creates a widget or layout, for insertion into an existing layout.
|
||||||
|
Do NOT use for filling a widget with a layout!"""
|
||||||
|
if issubclass(item_type, QWidget):
|
||||||
|
right = item_type(parent)
|
||||||
|
else:
|
||||||
|
right = item_type(None)
|
||||||
|
return right
|
||||||
|
|
||||||
|
|
||||||
|
@attr.dataclass
|
||||||
|
class StackFrame:
|
||||||
|
widget: Optional[QWidget]
|
||||||
|
layout: Optional[QLayout] = None
|
||||||
|
|
||||||
|
def with_layout(self, layout: Optional[QLayout]):
|
||||||
|
return attr.evolve(self, layout=layout)
|
||||||
|
|
||||||
|
|
||||||
|
class LayoutStack:
|
||||||
|
def __init__(self, root: Optional[QWidget]):
|
||||||
|
self._items = [StackFrame(root)]
|
||||||
|
self.widget_to_label: Dict[QWidget, QLabel] = {}
|
||||||
|
|
||||||
|
@contextmanager
|
||||||
|
def push(self, item: T) -> ctx[T]:
|
||||||
|
if isinstance(item, StackFrame):
|
||||||
|
frame = item
|
||||||
|
elif isinstance(item, QWidget):
|
||||||
|
frame = StackFrame(item)
|
||||||
|
elif isinstance(item, QLayout):
|
||||||
|
frame = self.peek().with_layout(item)
|
||||||
|
else:
|
||||||
|
raise TypeError(obj_name(item))
|
||||||
|
|
||||||
|
self._items.append(frame)
|
||||||
|
|
||||||
|
try:
|
||||||
|
yield item
|
||||||
|
finally:
|
||||||
|
self._items.pop()
|
||||||
|
|
||||||
|
def peek(self) -> StackFrame:
|
||||||
|
return self._items[-1]
|
||||||
|
|
||||||
|
@property
|
||||||
|
def widget(self):
|
||||||
|
return self.peek().widget
|
||||||
|
|
||||||
|
@property
|
||||||
|
def layout(self):
|
||||||
|
return self.peek().layout
|
||||||
|
|
||||||
|
|
||||||
|
def set_layout(stack: LayoutStack, layout_type: Type[QLayout]) -> QLayout:
|
||||||
|
layout = layout_type(stack.peek().widget)
|
||||||
|
stack.peek().layout = layout
|
||||||
|
return layout
|
||||||
|
|
||||||
|
|
||||||
|
def assert_peek(stack: LayoutStack, cls):
|
||||||
|
assert isinstance(stack.widget, cls)
|
||||||
|
|
||||||
|
|
||||||
|
def central_widget(stack: LayoutStack, widget_type: Type[SomeQW] = QWidget):
|
||||||
|
assert_peek(stack, QMainWindow)
|
||||||
|
# do NOT orphan=True
|
||||||
|
return _add_widget(stack, widget_type, exit_action="setCentralWidget")
|
||||||
|
|
||||||
|
|
||||||
|
def orphan_widget(stack: LayoutStack, widget_type: Type[SomeQW] = QWidget):
|
||||||
|
return _add_widget(stack, widget_type, orphan=True)
|
||||||
|
|
||||||
|
|
||||||
|
@contextmanager
|
||||||
|
def append_widget(
|
||||||
|
stack: LayoutStack, item_type: Type[WidgetOrLayout]
|
||||||
|
) -> ctx[WidgetOrLayout]:
|
||||||
|
with _add_widget(stack, item_type) as item:
|
||||||
|
yield item
|
||||||
|
add_widget_or_layout(stack.layout, item)
|
||||||
|
|
||||||
|
|
||||||
|
# noinspection PyArgumentList
|
||||||
|
def add_widget_or_layout(layout: QLayout, item: WidgetOrLayout, *args, **kwargs):
|
||||||
|
if isinstance(item, QWidget):
|
||||||
|
layout.addWidget(item, *args, **kwargs)
|
||||||
|
elif isinstance(item, QLayout):
|
||||||
|
# QLayout and some subclasses (like QFormLayout) omit this method,
|
||||||
|
# and will crash at runtime.
|
||||||
|
layout.addLayout(item, *args, **kwargs)
|
||||||
|
else:
|
||||||
|
raise TypeError(item)
|
||||||
|
|
||||||
|
|
||||||
|
# Main window toolbars/menus
|
||||||
|
|
||||||
|
|
||||||
|
def set_menu_bar(stack: LayoutStack):
|
||||||
|
assert_peek(stack, QMainWindow)
|
||||||
|
return _add_widget(stack, QMenuBar, exit_action="setMenuBar")
|
||||||
|
|
||||||
|
|
||||||
|
# won't bother adding type hints that pycharm is too dumb to understand
|
||||||
|
def append_menu(stack: LayoutStack):
|
||||||
|
assert_peek(stack, QMenuBar)
|
||||||
|
return _add_widget(stack, QMenu, exit_action="addMenu")
|
||||||
|
|
||||||
|
|
||||||
|
def add_toolbar(stack: LayoutStack, area=Qt.TopToolBarArea):
|
||||||
|
assert_peek(stack, QMainWindow)
|
||||||
|
|
||||||
|
def _add_toolbar(parent: QMainWindow, toolbar):
|
||||||
|
parent.addToolBar(area, toolbar)
|
||||||
|
|
||||||
|
return _add_widget(stack, QToolBar, exit_action=_add_toolbar)
|
||||||
|
|
||||||
|
|
||||||
|
# Implementation
|
||||||
|
|
||||||
|
|
||||||
|
@contextmanager
|
||||||
|
def _add_widget(
|
||||||
|
stack: LayoutStack,
|
||||||
|
item_type: Type[WidgetOrLayout],
|
||||||
|
orphan=False,
|
||||||
|
exit_action: Union[Callable[[Any, Any], Any], str] = "",
|
||||||
|
) -> ctx[WidgetOrLayout]:
|
||||||
|
"""
|
||||||
|
- Constructs item_type using parent.
|
||||||
|
- Yields item_type.
|
||||||
|
"""
|
||||||
|
|
||||||
|
if not orphan:
|
||||||
|
parent = stack.widget
|
||||||
|
else:
|
||||||
|
parent = None
|
||||||
|
|
||||||
|
with stack.push(new_widget_or_layout(item_type, parent)) as item:
|
||||||
|
yield item
|
||||||
|
|
||||||
|
real_parent = stack.widget
|
||||||
|
if callable(exit_action):
|
||||||
|
exit_action(real_parent, item)
|
||||||
|
elif exit_action:
|
||||||
|
getattr(real_parent, exit_action)(item)
|
||||||
|
|
||||||
|
|
||||||
|
def append_stretch(stack: LayoutStack):
|
||||||
|
cast(QBoxLayout, stack.layout).addStretch()
|
||||||
|
|
||||||
|
|
||||||
|
Left = TypeVar("Left", bound=QWidget)
|
||||||
|
Right = TypeVar("Right", bound=Union[QWidget, QLayout]) # same as WidgetOrLayout
|
||||||
|
|
||||||
|
|
||||||
|
Both = object()
|
||||||
|
|
||||||
|
|
||||||
|
def widget_pair_inserter(append_widgets: Callable):
|
||||||
|
@contextmanager
|
||||||
|
def add_row_col(stack: LayoutStack, arg1, arg2=None):
|
||||||
|
left_type: Type[Left]
|
||||||
|
right_type: Type[Right]
|
||||||
|
if arg2 is None:
|
||||||
|
left_type, right_type = QLabel, arg1
|
||||||
|
auto_left_label = True
|
||||||
|
else:
|
||||||
|
left_type, right_type = arg1, arg2
|
||||||
|
auto_left_label = False
|
||||||
|
|
||||||
|
parent = stack.widget
|
||||||
|
left = new_widget_or_layout(left_type, parent) # TODO support str
|
||||||
|
|
||||||
|
if right_type is Both:
|
||||||
|
right = Both
|
||||||
|
push = left
|
||||||
|
else:
|
||||||
|
right = new_widget_or_layout(right_type, parent)
|
||||||
|
push = right
|
||||||
|
|
||||||
|
with stack.push(push):
|
||||||
|
if right is Both:
|
||||||
|
yield left
|
||||||
|
elif auto_left_label:
|
||||||
|
yield right
|
||||||
|
else:
|
||||||
|
yield left, right
|
||||||
|
|
||||||
|
append_widgets(stack.layout, left, right)
|
||||||
|
if auto_left_label:
|
||||||
|
assert isinstance(left, QLabel)
|
||||||
|
stack.widget_to_label[right] = left
|
||||||
|
|
||||||
|
return add_row_col
|
||||||
|
|
||||||
|
|
||||||
|
def _add_row(layout: QFormLayout, left, right):
|
||||||
|
assert isinstance(layout, QFormLayout), layout
|
||||||
|
if right is Both:
|
||||||
|
raise TypeError("Cannot add_row(QFormLayout, span=Both)")
|
||||||
|
return layout.addRow(left, right)
|
||||||
|
|
||||||
|
|
||||||
|
add_row = widget_pair_inserter(_add_row)
|
||||||
|
|
||||||
|
|
||||||
|
def _add_grid_col(layout: QGridLayout, up, down):
|
||||||
|
assert isinstance(layout, QGridLayout), layout
|
||||||
|
col = layout.columnCount()
|
||||||
|
|
||||||
|
"""
|
||||||
|
void QGridLayout::addWidget(
|
||||||
|
QWidget *widget,
|
||||||
|
int fromRow, int fromColumn, [int rowSpan, int columnSpan],
|
||||||
|
Qt::Alignment alignment = Qt::Alignment()
|
||||||
|
)
|
||||||
|
"""
|
||||||
|
if down is Both:
|
||||||
|
shape = lambda: [0, col, -1, 1]
|
||||||
|
add_widget_or_layout(layout, up, *shape())
|
||||||
|
else:
|
||||||
|
shape = lambda row: [row, col]
|
||||||
|
add_widget_or_layout(layout, up, *shape(0))
|
||||||
|
add_widget_or_layout(layout, down, *shape(1))
|
||||||
|
|
||||||
|
|
||||||
|
add_grid_col = widget_pair_inserter(_add_grid_col)
|
||||||
|
|
||||||
|
|
||||||
|
@contextmanager
|
||||||
|
def add_tab(stack, widget_type: Type[SomeQW] = QWidget, label: str = "") -> ctx[SomeQW]:
|
||||||
|
"""
|
||||||
|
- Constructs widget using parent.
|
||||||
|
- Yields widget.
|
||||||
|
"""
|
||||||
|
tabs: QTabWidget = stack.widget
|
||||||
|
assert isinstance(tabs, QTabWidget), tabs
|
||||||
|
|
||||||
|
with orphan_widget(stack, widget_type) as w:
|
||||||
|
yield w
|
||||||
|
tabs.addTab(w, label)
|
||||||
|
|
||||||
|
|
||||||
|
# After building a tree...
|
||||||
|
def set_attr_objectName(ui, stack: LayoutStack):
|
||||||
|
"""
|
||||||
|
- Set objectName of all objects referenced by ui.
|
||||||
|
- For all object $name added by add_row() or add_grid_col(),
|
||||||
|
if $label was generated but not yielded
|
||||||
|
setattr(ui.$name + "L" = $label)
|
||||||
|
"""
|
||||||
|
widget_to_label = stack.widget_to_label
|
||||||
|
|
||||||
|
for name, obj in dict(ui.__dict__).items():
|
||||||
|
if not isinstance(obj, QObject):
|
||||||
|
continue
|
||||||
|
obj.setObjectName(name)
|
||||||
|
if obj in widget_to_label:
|
||||||
|
label = widget_to_label[obj]
|
||||||
|
label_name = name + "L"
|
||||||
|
label.setObjectName(label_name)
|
||||||
|
ui.__dict__[label_name] = label
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
import pytest
|
import pytest
|
||||||
|
|
||||||
from corrscope.gui.data_bind import rgetattr, rsetattr, rhasattr, flatten_attr
|
from corrscope.gui.model_bind import rgetattr, rsetattr, rhasattr, flatten_attr
|
||||||
|
|
||||||
|
|
||||||
class Person(object):
|
class Person(object):
|
||||||
Ładowanie…
Reference in New Issue