Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

accept all var type #55

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -113,3 +113,4 @@ venv.bak/

# mypy
.mypy_cache/
src/config/config.toml
2 changes: 1 addition & 1 deletion modules/CodeEditor/CodeEditor/editor.py
Original file line number Diff line number Diff line change
Expand Up @@ -360,7 +360,7 @@ def load(self, filename):

def save(self, filename):
"""Save the editor contents to the given filename."""
with open(filename, 'w', newline='') as outfile:
with open(filename, 'w', newline='', encoding="utf-8") as outfile:
# 不指定newline,则换行符为各系统默认的换行符(\n, \r, or \r\n, )
# newline=''表示不转换
outfile.write(self.text())
Expand Down
6 changes: 3 additions & 3 deletions requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ requests>=2.0
preimport>=1.1.0
toml>=0.10.0
tomlconfig>=1.2.1
PyQt5>=5.10.1,<5.14
PyQt5-sip>=12.7,<12.7.1
QScintilla==2.11.4
PyQt5
PyQt5-sip
QScintilla
CodeEditor>=1.1.0
64 changes: 50 additions & 14 deletions src/qss_template/qsst.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,41 @@
"""

import re
from dataclasses import dataclass
from PyQt5.QtGui import QColor


@dataclass
class Var:
value: str
key: str
_type: str = None

def __repr__(self):
return self.value

@property
def var(self):
return self.value.strip()

@property
def type(self):
if self.value in QColor.colorNames():
return "color"
elif self.var.startswith("#") or "rgb" in self.var or "rgba" in self.var:
return "color"

elif "px" in self.var:
return "px"
elif self.var.replace('.', '', 1).isdigit():
return "digit"

return "text"


class Qsst():
"""qss template"""

def __init__(self, qssFile=None):
if qssFile is None:
self.srctext = '' # qss template,qss with vars
Expand Down Expand Up @@ -40,20 +71,21 @@ def loadVars(self, qssStr=None):
for var, val in varsDefined:
if not valerr:
if val in QColor.colorNames():
self.varDict[var] = val
self.varDict[var] = Var(val, var)
else:
valerrind = re.match(
r'#[0-9A-Fa-f]{1,8}|rgb\(\s*[0-9]*\s*(,\s*[0-9]*\s*){2}\)|rgba\(\s*[0-9]*\s*(,\s*[0-9]*\s*){3}\)|[\w]*px',
val)
if not valerrind:
# valerrind = re.match(
# r'#[0-9A-Fa-f]{1,8}|rgb\(\s*[0-9]*\s*(,\s*[0-9]*\s*){2}\)|rgba\(\s*[0-9]*\s*(,\s*[0-9]*\s*){3}\)|[\w]*px',
# val)
v = Var(val, var)
if not v.type:
valerr = True
else:
self.varDict[var] = val
self.varDict[var] = v

self.varUndefined = []
for varused in self.varUsed:
if varused not in self.varDict.keys():
self.varDict[varused] = ''
self.varDict[varused] = Var('', varused)
self.varUndefined.append(varused)
return not valerr # 如果有变量的值格式不正确返回false

Expand All @@ -75,7 +107,7 @@ def addColorOpacity(self, color: str, opacity: str):
"""
if '#' not in color and len(color) not in [4, 7]:
return color

if len(color) == 4:
color = ''.join(item + item for item in color)[1:]

Expand All @@ -86,7 +118,7 @@ def addColorOpacity(self, color: str, opacity: str):
opacity = 255

return '#' + hex(opacity).replace('0x', '') + color[1:]

def convertQss(self):
"""根据varDict中变量的值,把模板文件中引用的变量用值替换,转换为qss文件。
"""
Expand All @@ -102,9 +134,11 @@ def convertQss(self):
if v in varDict.keys():
# opacity
qssStr = re.sub(r'[$](\w+)[%](\w+)([\s;]*)',
lambda m: '{}{}'.format(self.addColorOpacity(varDict[m.group(1)], m.group(2)), m.group(3)), qssStr)
lambda m: '{}{}'.format(self.addColorOpacity(varDict[m.group(1)].value, m.group(2)),
m.group(3)), qssStr)
# qssStr = qssStr.replace("$" + v, varDict[v])
qssStr = re.sub(r'[$](\w+)([\s;]*)', lambda m: '{}{}'.format(varDict[m.group(1)], m.group(2)), qssStr)
qssStr = re.sub(r'[$](\w+)([\s;]*)', lambda m: '{}{}'.format(varDict[m.group(1)].value, m.group(2)),
qssStr)
else:
self.varUndefined.append(v)
# qssStr = qssStr.replace("$" + v, ' ')
Expand All @@ -127,26 +161,28 @@ def writeVars(self):
self.loadVars()
if self.varDict: # 如果文件中变量不为空,更新变量值
self.srctext = re.sub(r'[$](\w+)\s*=[ \t]*([#(),.\w]*)[\t ]*[;]?',
lambda m: '${} = {};'.format(m.group(1), varDictNew.get(m.group(1), "")),
lambda m: '${} = {};'.format(m.group(1),
varDictNew.get(m.group(1), Var("", "")).value),
self.srctext)
if self.varUndefined: # 在第一的变量处插入多出来的变量,引用比定义的变量多的时候回出现这种情况
s = ''
for var, val in varDictNew.items():
if var in self.varUndefined:
s += "$" + var + " = " + val + ";\n"
s += "$" + var + " = " + val.value + ";\n"
self.srctext = re.sub(r'[$](\w+)\s*=[ \t]*([#(),.\w]*)[\t ]*[;]?', r'{}$\1 = \2;\n'.format(s),
self.srctext, 1)
else:
s = ''
for var, val in varDictNew.items():
s += "$" + var + " = " + val + ";\n"
s += "$" + var + " = " + val.value + ";\n"
s += '\n'
self.srctext = s + self.srctext
self.loadVars()


if __name__ == "__main__":
import os

os.chdir(os.path.dirname(__file__))
qssT = Qsst('default.qsst')
qssT.loadVars()
Expand Down
117 changes: 75 additions & 42 deletions src/ui/mainwin.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,14 @@
import sys

from PyQt5.QtWidgets import (qApp, QWidget, QLabel, QPushButton, QColorDialog, QFileDialog, QMessageBox, QFormLayout,
QVBoxLayout, QHBoxLayout)
QVBoxLayout, QHBoxLayout, QLineEdit)
from PyQt5.QtGui import QIcon, QColor, qGray, QFont
from PyQt5.QtCore import Qt, QSize, QTimer
# import sip

from config import Config, ConfDialog
from qss_template import Qsst
from qss_template.qsst import Var
from .mainwinbase import MainWinBase
from .palettedialog import PaletteDialog
from .recent import Recent
Expand Down Expand Up @@ -166,75 +167,75 @@ def uncommentcode(self):
lineto = linefrom
linetext = self.editor.text(linefrom)
linebytes = linetext.encode()
if len(linetext.encode()) < 4 or colcursor<2 or colcursor >len(linetext.encode())-2:
if len(linetext.encode()) < 4 or colcursor < 2 or colcursor > len(linetext.encode()) - 2:
return
for i in range(colcursor - 1, -1, -1):
if linebytes[i] == ord("*") and linebytes[i - 1] == ord("/"):
start = i - 1
break
for i in range(colcursor, len(linebytes) - 1):
if linebytes[i] == ord("*") and linebytes[i + 1] == ord("/"):
print(i, linebytes[i], linebytes[i+1])
print(i, linebytes[i], linebytes[i + 1])
end = i
break
else:
linestart = self.editor.text(linefrom).encode()
colend = len(linestart) if lineto>linefrom else colto
colend = len(linestart) if lineto > linefrom else colto
for i in range(colfrom, colend):
if linestart[i] == ord('/') and linestart[i+1] == ord('*'):
if linestart[i] == ord('/') and linestart[i + 1] == ord('*'):
start = i
break
if start == -1:
for i in range(colfrom, 0, -1):
if linestart[i] == ord('/') and linestart[i-1] == ord('*'):
if linestart[i] == ord('/') and linestart[i - 1] == ord('*'):
start = -2
break
elif linestart[i] == ord('*') and linestart[i-1] == ord('/'):
start = i-1
elif linestart[i] == ord('*') and linestart[i - 1] == ord('/'):
start = i - 1
break
if start ==-1 and linefrom > 0:
if start == -1 and linefrom > 0:
while linefrom > 0:
linefrom = linefrom -1
linefrom = linefrom - 1
if self.editor.text(linefrom).strip() != "":
break
linestart = self.editor.text(linefrom).encode()
for i in range(len(linestart)-1, 0, -1):
if linestart[i] == ord('/') and linestart[i-1] == ord('*'):
for i in range(len(linestart) - 1, 0, -1):
if linestart[i] == ord('/') and linestart[i - 1] == ord('*'):
break
elif linestart[i] == ord('*') and linestart[i-1] == ord('/'):
start = i-1
elif linestart[i] == ord('*') and linestart[i - 1] == ord('/'):
start = i - 1
break

if start > 0:
lineend = self.editor.text(lineto).encode()
colstart = 0 if lineto>linefrom else colfrom
colstart = 0 if lineto > linefrom else colfrom
for i in range(colto, colstart, -1):
if lineend[i] == ord('/') and lineend[i - 1] == ord('*'):
end = i
break
if end == -1:
for i in range(colto, len(lineend)-1):
for i in range(colto, len(lineend) - 1):
if lineend[i] == ord('/') and lineend[i + 1] == ord('*'):
end = -2
break
elif lineend[i] == ord('*') and lineend[i + 1] == ord('/'):
end = i
break
if end < 0 and lineto < self.editor.lines()-1:
while lineto < self.editor.lines()-1:
if end < 0 and lineto < self.editor.lines() - 1:
while lineto < self.editor.lines() - 1:
lineto = lineto + 1
if self.editor.text(lineto).strip() != "":
break
print(lineto)
lineend = self.editor.text(lineto).encode()
for i in range(len(lineend)-1):
for i in range(len(lineend) - 1):
if lineend[i] == ord('/') and lineend[i + 1] == ord('*'):
break
elif lineend[i] == ord('*') and lineend[i + 1] == ord('/'):
end = i
print(linefrom,start, lineto, end)
print(linefrom, start, lineto, end)

if start>=0 and end>=0:
if start >= 0 and end >= 0:
# try:
# self.editor.positionFromLineIndex(linefrom, lineto)
self.editor.setSelection(lineto, end, lineto, end + 2)
Expand Down Expand Up @@ -290,7 +291,7 @@ def renderStyle(self):
# self.statusbar.showMessage("")#不起作用
# except Exception:
# self.statusbar.showMessage("qss parse failed")
cstr = self.qsst.varDict.get("background", "")
cstr = self.qsst.varDict.get("background", Var("", "background")).value
if cstr:
try:
c = QColor()
Expand Down Expand Up @@ -338,31 +339,51 @@ def loadColorPanel(self):
# self.colorGridLayout.update() # 不起作用

# a,b=list(self.clrBtnDict.keys()),list(self.qsst.varDict.keys());a.sort();b.sort()
if sorted(list(self.clrBtnDict.keys())) != sorted(list(self.qsst.varDict.keys())):
if sorted(list(self.clrBtnDict.items())) != sorted(list(self.qsst.varDict.items())):
while self.colorPanelLayout.count() > 0:
self.colorPanelLayout.removeItem(self.colorPanelLayout.itemAt(0))
self.clrBtnDict = {}
self.varLinDict = {}
labels = {}
widLabel = 0
widBtn = 0
widLin = 0
for varName, clrStr in self.qsst.varDict.items():
label = QLabel(varName) # , contianerWidget)
btn = QPushButton(clrStr) # , contianerWidget)
if sys.platform.startswith("win"):
font1 = QFont("Arial", 10, QFont.Medium)
font2 = QFont("sans-serif", 9, QFont.Medium)
label.setFont(font1)
btn.setFont(font2)
self.clrBtnDict[varName] = btn
labels[varName] = label
label.adjustSize()
widLabel = label.width() if label.width() > widLabel else widLabel
btn.adjustSize()
widBtn = btn.width() if btn.width() > widBtn else widBtn
# label.move(5, 5)
# btn.move(100, 5)
btn.clicked.connect(lambda x, var=varName: self.chclr(var))
for name, btn in self.clrBtnDict.items():
if clrStr.type in ["color"]:
label = QLabel(varName) # , contianerWidget)
btn = QPushButton(clrStr.value) # , contianerWidget)
if sys.platform.startswith("win"):
font1 = QFont("Arial", 10, QFont.Medium)
font2 = QFont("sans-serif", 9, QFont.Medium)
label.setFont(font1)
btn.setFont(font2)
self.clrBtnDict[varName] = btn
labels[varName] = label
label.adjustSize()
widLabel = label.width() if label.width() > widLabel else widLabel
btn.adjustSize()
widBtn = btn.width() if btn.width() > widBtn else widBtn
# label.move(5, 5)
# btn.move(100, 5)
btn.clicked.connect(lambda x, var=varName: self.chclr(var))
elif clrStr.type:
label = QLabel(varName) # , contianerWidget)
line = QLineEdit(clrStr.value)
if sys.platform.startswith("win"):
font1 = QFont("Arial", 10, QFont.Medium)
font2 = QFont("sans-serif", 9, QFont.Medium)
label.setFont(font1)
line.setFont(font2)

self.varLinDict[varName] = line
labels[varName] = label
label.adjustSize()
widLabel = label.width() if label.width() > widLabel else widLabel
line.adjustSize()
widLin = line.width() if line.width() > widLin else widLin
line.textChanged.connect(lambda x, var=varName: self.chLine(var))

for name, btn in [*self.clrBtnDict.items(), *self.varLinDict.items()]:
contianerWidget = QWidget()
lay = QHBoxLayout()
labels[name].setFixedWidth(widLabel)
Expand All @@ -374,7 +395,7 @@ def loadColorPanel(self):
self.colorPanelLayout.addWidget(contianerWidget)

for varName, btn in self.clrBtnDict.items():
clrStr = self.qsst.varDict[varName]
clrStr = self.qsst.varDict[varName].value
btn.setText(clrStr)
if "rgb" in clrStr:
t = clrStr.strip(r" rgba()")
Expand All @@ -400,6 +421,18 @@ def loadColorPanel(self):

btn.setStyleSheet(s + "background:" + btn.text())

def chLine(self, var):
val = self.sender().text()
self.qsst.varDict[var] = Var(val, var)
self.qsst.writeVars()
# 用setText之后undo redo堆栈全部消失,所以暂时用这种方法
pos = self.editor.verticalScrollBar().sliderPosition()
self.editor.selectAll()
self.editor.replaceSelectedText(self.qsst.srctext) # setText(self.qsst.srctext)
# self.CodeEditor.setCursorPosition(xp,yp)
self.editor.verticalScrollBar().setSliderPosition(pos)
self.renderStyle()

def chclr(self, var):
c = QColor()
cstr = self.sender().text()
Expand All @@ -421,7 +454,7 @@ def chclr(self, var):
s += 'color:white;'
self.clrBtnDict[var].setText(clrstr)
self.clrBtnDict[var].setStyleSheet(s + "background:" + clrstr)
self.qsst.varDict[var] = clrstr
self.qsst.varDict[var] = Var(clrstr, var)
self.qsst.writeVars()
# 用setText之后undo redo堆栈全部消失,所以暂时用这种方法
pos = self.editor.verticalScrollBar().sliderPosition()
Expand Down