#!/usr/bin/env python3 from xasyqtui.labelTextEditor import Ui_Dialog import PySide6.QtWidgets as QtWidgets import PySide6.QtSvg as QtSvg import PySide6.QtGui as QtGui import PySide6.QtCore as QtCore import xasyArgs as xasyArgs import xasyOptions as xasyOptions import xasyUtils as xasyUtils import subprocess import tempfile import uuid import os class labelEditor(QtWidgets.QDialog): def __init__(self, text=''): super().__init__() self.ui = Ui_Dialog() self.ui.setupUi(self) self.ui.btnAccept.clicked.connect(self.accept) self.ui.btnCancel.clicked.connect(self.reject) self.ui.chkMathMode.stateChanged.connect(self.chkMathModeChecked) self.ui.btnPreview.clicked.connect(self.btnPreviewOnClick) self.ui.btnGetText.clicked.connect(self.btnGetTextOnClick) self.svgPreview = None self.initializeText(text) def initializeText(self, text: str): if text[0] == '$' and text[-1] == '$': self.ui.chkMathMode.setChecked(True) text = text.strip('$') if text.startswith('\\displaystyle{'): self.ui.cmbMathStyle.setCurrentText('Display Style') text = text.rstrip('}') text = text.replace('\\displaystyle{', '', 1) elif text.startswith('\\scriptstyle{'): self.ui.cmbMathStyle.setCurrentText('Script Style') text = text.rstrip('}') text = text.replace('\\scriptstyle{', '', 1) self.ui.txtLabelEdit.setPlainText(text) def chkMathModeChecked(self, checked): self.ui.cmbMathStyle.setEnabled(checked) def getText(self): rawText = self.ui.txtLabelEdit.toPlainText() rawText.replace('\n', ' ') if self.ui.chkMathMode.isChecked(): prefix = '' suffix = '' if self.ui.cmbMathStyle.currentText() == 'Display Style': prefix = '\\displaystyle{' suffix = '}' elif self.ui.cmbMathStyle.currentText() == 'Script Style': prefix = '\\scriptstyle{' suffix = '}' return '${0}{1}{2}$'.format(prefix, rawText, suffix) else: return rawText def btnPreviewOnClick(self): path = xasyArgs.getArgs().asypath if path is None: opt = xasyOptions.BasicConfigs.defaultOpt path = opt['asyPath'] asyInput = """ frame f; label(f, "{0}"); write(min(f), newl); write(max(f), newl); shipout(f); """ self.svgPreview = QtSvg.QSvgRenderer() with tempfile.TemporaryDirectory(prefix='xasylbl_') as tmpdir: random_id = str(uuid.uuid4()) tmpFile = os.path.join(tmpdir, 'lbl-{0}.svg'.format(random_id)) with subprocess.Popen(args=[path, '-fsvg', '-o', tmpFile, '-'], encoding='utf-8', stdin=subprocess.PIPE, stdout=subprocess.PIPE) as asy: asy.stdin.write(asyInput.format(self.getText())) asy.stdin.close() out = asy.stdout.read() raw_array = out.splitlines() bounds_1, bounds_2 = [val.strip() for val in raw_array] min_bounds = xasyUtils.listize(bounds_1, (float, float)) max_bounds = xasyUtils.listize(bounds_2, (float, float)) new_rect = self.processBounds(min_bounds, max_bounds) self.svgPreview.load(tmpFile) self.drawPreview(new_rect) def drawPreview(self, naturalBounds): img = QtGui.QPixmap(self.ui.lblLabelPreview.size()) img.fill(QtGui.QColor.fromRgbF(1, 1, 1, 1)) if self.svgPreview is None: pass else: with QtGui.QPainter(img) as pnt: scale_ratio = self.getIdealScaleRatio(naturalBounds, self.ui.lblLabelPreview.rect()) pnt.translate(self.ui.lblLabelPreview.rect().center()) pnt.scale(scale_ratio, scale_ratio) self.svgPreview.render(pnt, naturalBounds) self.ui.lblLabelPreview.setPixmap(img) def getIdealScaleRatio(self, rect, boundsRect): assert isinstance(rect, (QtCore.QRect, QtCore.QRectF)) assert isinstance(rect, (QtCore.QRect, QtCore.QRectF)) magic_ratio = 0.50 idealRatioHeight = (magic_ratio * boundsRect.height()) / rect.height() magicRatioWidth = 0.50 if idealRatioHeight * rect.width() > magicRatioWidth * boundsRect.width(): idealRatioWidth = (magicRatioWidth * boundsRect.width()) / rect.width() idealRatio = min(idealRatioHeight, idealRatioWidth) else: idealRatio = idealRatioHeight return idealRatio def processBounds(self, minPt, maxPt): p1x, p1y = minPt p2x, p2y = maxPt minPt = QtCore.QPointF(p1x, p1y) maxPt = QtCore.QPointF(p2x, p2y) newRect = QtCore.QRectF(minPt, maxPt) return newRect def btnGetTextOnClick(self): msgbox = QtWidgets.QMessageBox() msgbox.setText('Text Preview:\n' + self.getText()) msgbox.setWindowTitle('Text preview') msgbox.show() return msgbox.exec_()