Filter examples (#1868)

* Allows filtering of examples

* For some reason, the ui designer ignored the courier font family so I manually inserted it into the .ui file

* Allows filtering by file content, too

* Respects dark mode (maybe?), fixes policy setting on code layout

* Prevents "run edited code" from showing unless the actual content changes

* Looks like black font is always best against highlight background

* Left test code in commit...

* Fix broken highlighting on PyQt6

* Address #133

* Better highlighting for both dark and light mode

* Minor refactoring/cleanup, uses combo box instead of checkbox

* Combo box below text edit to avoid clipping

Co-authored-by: njessurun <ntjessu@gmail.com>
This commit is contained in:
ntjess 2021-06-26 20:51:34 -04:00 committed by GitHub
parent e79dacf805
commit 4a921ddf71
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 463 additions and 215 deletions

View File

@ -4,10 +4,12 @@ import re
import sys
import subprocess
from argparse import Namespace
import pyqtgraph as pg
from pyqtgraph.Qt import QtGui, QtCore, QT_LIB
from pyqtgraph.Qt import QtWidgets, QtGui, QtCore, QT_LIB
from collections import OrderedDict
from .utils import examples
from .utils import examples_
from functools import lru_cache
path = os.path.abspath(os.path.dirname(__file__))
sys.path.insert(0, path)
@ -28,7 +30,7 @@ QTextCharFormat = QtGui.QTextCharFormat
QSyntaxHighlighter = QtGui.QSyntaxHighlighter
def format(color, style=''):
def charFormat(color, style='', background=None):
"""
Return a QTextCharFormat with the given attributes.
"""
@ -44,6 +46,8 @@ def format(color, style=''):
_format.setFontWeight(QFont.Weight.Bold)
if 'italic' in style:
_format.setFontItalic(True)
if background is not None:
_format.setBackground(pg.mkColor(background))
return _format
@ -95,28 +99,28 @@ class DarkThemeColors:
LIGHT_STYLES = {
'keyword': format(LightThemeColors.Blue, 'bold'),
'operator': format(LightThemeColors.Red, 'bold'),
'brace': format(LightThemeColors.Purple),
'defclass': format(LightThemeColors.Indigo, 'bold'),
'string': format(LightThemeColors.Amber),
'string2': format(LightThemeColors.DeepPurple),
'comment': format(LightThemeColors.Green, 'italic'),
'self': format(LightThemeColors.Blue, 'bold'),
'numbers': format(LightThemeColors.Teal),
'keyword': charFormat(LightThemeColors.Blue, 'bold'),
'operator': charFormat(LightThemeColors.Red, 'bold'),
'brace': charFormat(LightThemeColors.Purple),
'defclass': charFormat(LightThemeColors.Indigo, 'bold'),
'string': charFormat(LightThemeColors.Amber),
'string2': charFormat(LightThemeColors.DeepPurple),
'comment': charFormat(LightThemeColors.Green, 'italic'),
'self': charFormat(LightThemeColors.Blue, 'bold'),
'numbers': charFormat(LightThemeColors.Teal),
}
DARK_STYLES = {
'keyword': format(DarkThemeColors.Blue, 'bold'),
'operator': format(DarkThemeColors.Red, 'bold'),
'brace': format(DarkThemeColors.Purple),
'defclass': format(DarkThemeColors.Indigo, 'bold'),
'string': format(DarkThemeColors.Amber),
'string2': format(DarkThemeColors.DeepPurple),
'comment': format(DarkThemeColors.Green, 'italic'),
'self': format(DarkThemeColors.Blue, 'bold'),
'numbers': format(DarkThemeColors.Teal),
'keyword': charFormat(DarkThemeColors.Blue, 'bold'),
'operator': charFormat(DarkThemeColors.Red, 'bold'),
'brace': charFormat(DarkThemeColors.Purple),
'defclass': charFormat(DarkThemeColors.Indigo, 'bold'),
'string': charFormat(DarkThemeColors.Amber),
'string2': charFormat(DarkThemeColors.DeepPurple),
'comment': charFormat(DarkThemeColors.Green, 'italic'),
'self': charFormat(DarkThemeColors.Blue, 'bold'),
'numbers': charFormat(DarkThemeColors.Teal),
}
@ -145,7 +149,7 @@ class PythonHighlighter(QSyntaxHighlighter):
]
def __init__(self, document):
QSyntaxHighlighter.__init__(self, document)
super().__init__(document)
# Multi-line strings (expression, flag, style)
self.tri_single = (QRegularExpression("'''"), 1, 'string2')
@ -185,17 +189,19 @@ class PythonHighlighter(QSyntaxHighlighter):
(r'#[^\n]*', 0, 'comment'),
]
self.rules = rules
self.searchText = None
@property
def styles(self):
app = QtGui.QApplication.instance()
app = QtWidgets.QApplication.instance()
return DARK_STYLES if app.property('darkMode') else LIGHT_STYLES
def highlightBlock(self, text):
"""Apply syntax highlighting to the given block of text.
"""
# Do other syntax formatting
for expression, nth, format in self.rules:
rules = self.rules.copy()
for expression, nth, format in rules:
format = self.styles[format]
for n, match in enumerate(re.finditer(expression, text)):
@ -204,6 +210,8 @@ class PythonHighlighter(QSyntaxHighlighter):
start = match.start()
length = match.end() - start
self.setFormat(start, length, format)
self.applySearchHighlight(text)
self.setCurrentBlockState(0)
# Do multi-line strings
@ -249,39 +257,85 @@ class PythonHighlighter(QSyntaxHighlighter):
length = len(text) - start + add
# Apply formatting
self.setFormat(start, length, self.styles[style])
# Highlighting sits on top of this formatting
# Look for the next match
match = delimiter.match(text, start + length)
start = match.capturedStart()
self.applySearchHighlight(text)
# Return True if still inside a multi-line string, False otherwise
if self.currentBlockState() == in_state:
return True
else:
return False
def applySearchHighlight(self, text):
if not self.searchText:
return
expr = f'(?i){self.searchText}'
palette: QtGui.QPalette = app.palette()
color = palette.highlight().color()
fgndColor = palette.color(palette.ColorGroup.Current,
palette.ColorRole.Text).name()
style = charFormat(fgndColor, background=color.name())
for match in re.finditer(expr, text):
start = match.start()
length = match.end() - start
self.setFormat(start, length, style)
class ExampleLoader(QtGui.QMainWindow):
def unnestedDict(exDict):
"""Converts a dict-of-dicts to a singly nested dict for non-recursive parsing"""
out = {}
for kk, vv in exDict.items():
if isinstance(vv, dict):
out.update(unnestedDict(vv))
else:
out[kk] = vv
return out
class ExampleLoader(QtWidgets.QMainWindow):
def __init__(self):
QtGui.QMainWindow.__init__(self)
QtWidgets.QMainWindow.__init__(self)
self.ui = ui_template.Ui_Form()
self.cw = QtGui.QWidget()
self.cw = QtWidgets.QWidget()
self.setCentralWidget(self.cw)
self.ui.setupUi(self.cw)
self.setWindowTitle("PyQtGraph Examples")
self.codeBtn = QtGui.QPushButton('Run Edited Code')
self.codeLayout = QtGui.QGridLayout()
self.codeBtn = QtWidgets.QPushButton('Run Edited Code')
self.codeLayout = QtWidgets.QGridLayout()
self.ui.codeView.setLayout(self.codeLayout)
self.hl = PythonHighlighter(self.ui.codeView.document())
app = QtGui.QApplication.instance()
app = QtWidgets.QApplication.instance()
app.paletteChanged.connect(self.updateTheme)
self.codeLayout.addItem(QtGui.QSpacerItem(100,100,QtGui.QSizePolicy.Policy.Expanding,QtGui.QSizePolicy.Policy.Expanding), 0, 0)
policy = QtWidgets.QSizePolicy.Policy.Expanding
self.codeLayout.addItem(QtWidgets.QSpacerItem(100,100, policy, policy), 0, 0)
self.codeLayout.addWidget(self.codeBtn, 1, 1)
self.codeBtn.hide()
global examples
textFil = self.ui.exampleFilter
self.curListener = None
def onComboChanged(searchType):
if self.curListener is not None:
self.curListener.disconnect()
self.curListener = textFil.textChanged
if searchType == 'Content Search':
self.curListener.connect(self.filterByContent)
else:
self.hl.searchText = None
self.curListener.connect(self.filterByTitle)
# Fire on current text, too
self.curListener.emit(textFil.text())
self.ui.searchFiles.currentTextChanged.connect(onComboChanged)
onComboChanged(self.ui.searchFiles.currentText())
self.itemCache = []
self.populateTree(self.ui.exampleTree.invisibleRootItem(), examples)
self.populateTree(self.ui.exampleTree.invisibleRootItem(), examples_)
self.ui.exampleTree.expandAll()
self.resize(1000,500)
@ -290,9 +344,76 @@ class ExampleLoader(QtGui.QMainWindow):
self.ui.loadBtn.clicked.connect(self.loadFile)
self.ui.exampleTree.currentItemChanged.connect(self.showFile)
self.ui.exampleTree.itemDoubleClicked.connect(self.loadFile)
self.ui.codeView.textChanged.connect(self.codeEdited)
# textChanged fires when the highlighter is reassigned the same document. Prevent this
# from showing "run edited code" by checking for actual content change
oldText = self.ui.codeView.toPlainText()
def onTextChange():
nonlocal oldText
newText = self.ui.codeView.toPlainText()
if newText != oldText:
oldText = newText
self.codeEdited()
self.ui.codeView.textChanged.connect(onTextChange)
self.codeBtn.clicked.connect(self.runEditedCode)
def filterByTitle(self, text):
self.showExamplesByTitle(self.getMatchingTitles(text))
self.hl.setDocument(self.ui.codeView.document())
def filterByContent(self, text=None):
# Don't filter very short strings
checkDict = unnestedDict(examples_)
self.hl.searchText = text
# Need to reapply to current document
self.hl.setDocument(self.ui.codeView.document())
titles = []
text = text.lower()
for kk, vv in checkDict.items():
if isinstance(vv, Namespace):
vv = vv.filename
filename = os.path.join(path, vv)
contents = self.getExampleContent(filename).lower()
if text in contents:
titles.append(kk)
self.showExamplesByTitle(titles)
def getMatchingTitles(self, text, exDict=None, acceptAll=False):
if exDict is None:
exDict = examples_
text = text.lower()
titles = []
for kk, vv in exDict.items():
matched = acceptAll or text in kk.lower()
if isinstance(vv, dict):
titles.extend(self.getMatchingTitles(text, vv, acceptAll=matched))
elif matched:
titles.append(kk)
return titles
def showExamplesByTitle(self, titles):
QTWI = QtWidgets.QTreeWidgetItemIterator
flag = QTWI.IteratorFlag.NoChildren
treeIter = QTWI(self.ui.exampleTree, flag)
item = treeIter.value()
while item is not None:
parent = item.parent()
show = (item.childCount() or item.text(0) in titles)
item.setHidden(not show)
# If all children of a parent are gone, hide it
if parent:
hideParent = True
for ii in range(parent.childCount()):
if not parent.child(ii).isHidden():
hideParent = False
break
parent.setHidden(hideParent)
treeIter += 1
item = treeIter.value()
def simulate_black_mode(self):
"""
used to simulate MacOS "black mode" on other platforms
@ -309,7 +430,7 @@ class ExampleLoader(QtGui.QMainWindow):
f.setForeground(QtGui.QColor('white'))
self.ui.codeView.setCurrentCharFormat(f)
# finally, override application automatic detection
app = QtGui.QApplication.instance()
app = QtWidgets.QApplication.instance()
app.setProperty('darkMode', True)
def updateTheme(self):
@ -318,7 +439,7 @@ class ExampleLoader(QtGui.QMainWindow):
def populateTree(self, root, examples):
bold_font = None
for key, val in examples.items():
item = QtGui.QTreeWidgetItem([key])
item = QtWidgets.QTreeWidgetItem([key])
self.itemCache.append(item) # PyQt 4.9.6 no longer keeps references to these wrappers,
# so we need to make an explicit reference or else the .file
# attribute will disappear.
@ -338,7 +459,6 @@ class ExampleLoader(QtGui.QMainWindow):
def currentFile(self):
item = self.ui.exampleTree.currentItem()
if hasattr(item, 'file'):
global path
return os.path.join(path, item.file)
return None
@ -364,27 +484,55 @@ class ExampleLoader(QtGui.QMainWindow):
def showFile(self):
fn = self.currentFile()
if fn is None:
self.ui.codeView.clear()
return
if os.path.isdir(fn):
fn = os.path.join(fn, '__main__.py')
with open(fn, "r") as currentFile:
text = currentFile.read()
text = self.getExampleContent(fn)
self.ui.codeView.setPlainText(text)
self.ui.loadedFileLabel.setText(fn)
self.codeBtn.hide()
@lru_cache(100)
def getExampleContent(self, filename):
if filename is None:
self.ui.codeView.clear()
return
if os.path.isdir(filename):
filename = os.path.join(filename, '__main__.py')
with open(filename, "r") as currentFile:
text = currentFile.read()
return text
def codeEdited(self):
self.codeBtn.show()
def runEditedCode(self):
self.loadFile(edited=True)
def keyPressEvent(self, event):
ret = super().keyPressEvent(event)
if not QtCore.Qt.KeyboardModifier.ControlModifier & event.modifiers():
return ret
key = event.key()
Key = QtCore.Qt.Key
if key not in [Key.Key_Plus, Key.Key_Minus, Key.Key_Underscore, Key.Key_Equal, Key.Key_0]:
return ret
font = self.ui.codeView.font()
oldSize = font.pointSize()
if key == Key.Key_Plus or key == Key.Key_Equal:
font.setPointSize(oldSize + max(oldSize*.15, 1))
elif key == Key.Key_Minus or key == Key.Key_Underscore:
newSize = oldSize - max(oldSize*.15, 1)
font.setPointSize(max(newSize, 1))
elif key == Key.Key_0:
# Reset to original size
font.setPointSize(10)
self.ui.codeView.setFont(font)
return event.accept()
def main():
app = pg.mkQApp()
loader = ExampleLoader()
loader.ui.exampleTree.setCurrentIndex(
loader.ui.exampleTree.model().index(0,0)
)
pg.exec()
if __name__ == '__main__':

View File

@ -14,26 +14,14 @@
<string>PyQtGraph</string>
</property>
<layout class="QGridLayout" name="gridLayout_2">
<item row="0" column="0">
<item row="1" column="0">
<widget class="QSplitter" name="splitter">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<widget class="QWidget" name="">
<widget class="QWidget" name="layoutWidget">
<layout class="QGridLayout" name="gridLayout">
<item row="0" column="0" colspan="2">
<widget class="QTreeWidget" name="exampleTree">
<attribute name="headerVisible">
<bool>false</bool>
</attribute>
<column>
<property name="text">
<string notr="true">1</string>
</property>
</column>
</widget>
</item>
<item row="1" column="1">
<item row="4" column="1">
<widget class="QComboBox" name="qtLibCombo">
<item>
<property name="text">
@ -62,23 +50,56 @@
</item>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="label">
<property name="text">
<string>Qt Library:</string>
</property>
</widget>
</item>
<item row="3" column="1">
<item row="6" column="1">
<widget class="QPushButton" name="loadBtn">
<property name="text">
<string>Run Example</string>
</property>
</widget>
</item>
<item row="3" column="0" colspan="2">
<widget class="QTreeWidget" name="exampleTree">
<attribute name="headerVisible">
<bool>false</bool>
</attribute>
<column>
<property name="text">
<string notr="true">1</string>
</property>
</column>
</widget>
</item>
<item row="4" column="0">
<widget class="QLabel" name="label">
<property name="text">
<string>Qt Library:</string>
</property>
</widget>
</item>
<item row="0" column="0" colspan="2">
<widget class="QLineEdit" name="exampleFilter">
<property name="placeholderText">
<string>Type to filter...</string>
</property>
</widget>
</item>
<item row="1" column="0" colspan="2">
<widget class="QComboBox" name="searchFiles">
<item>
<property name="text">
<string>Title Search</string>
</property>
</item>
<item>
<property name="text">
<string>Content Search</string>
</property>
</item>
</widget>
</item>
</layout>
</widget>
<widget class="QWidget" name="">
<widget class="QWidget" name="layoutWidget">
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QLabel" name="loadedFileLabel">

View File

@ -1,10 +1,11 @@
# -*- coding: utf-8 -*-
# Form implementation generated from reading ui file 'exampleLoaderTemplate.ui'
# Form implementation generated from reading ui file 'examples/exampleLoaderTemplate.ui'
#
# Created by: PyQt5 UI code generator 5.12.3
# Created by: PyQt5 UI code generator 5.15.4
#
# WARNING! All changes made in this file will be lost!
# WARNING: Any manual changes made to this file will be lost when pyuic5 is
# run again. Do not edit this file unless you know what you are doing.
from PyQt5 import QtCore, QtGui, QtWidgets
@ -19,36 +20,44 @@ class Ui_Form(object):
self.splitter = QtWidgets.QSplitter(Form)
self.splitter.setOrientation(QtCore.Qt.Horizontal)
self.splitter.setObjectName("splitter")
self.widget = QtWidgets.QWidget(self.splitter)
self.widget.setObjectName("widget")
self.gridLayout = QtWidgets.QGridLayout(self.widget)
self.layoutWidget = QtWidgets.QWidget(self.splitter)
self.layoutWidget.setObjectName("layoutWidget")
self.gridLayout = QtWidgets.QGridLayout(self.layoutWidget)
self.gridLayout.setContentsMargins(0, 0, 0, 0)
self.gridLayout.setObjectName("gridLayout")
self.exampleTree = QtWidgets.QTreeWidget(self.widget)
self.exampleTree.setObjectName("exampleTree")
self.exampleTree.headerItem().setText(0, "1")
self.exampleTree.header().setVisible(False)
self.gridLayout.addWidget(self.exampleTree, 0, 0, 1, 2)
self.qtLibCombo = QtWidgets.QComboBox(self.widget)
self.qtLibCombo = QtWidgets.QComboBox(self.layoutWidget)
self.qtLibCombo.setObjectName("qtLibCombo")
self.qtLibCombo.addItem("")
self.qtLibCombo.addItem("")
self.qtLibCombo.addItem("")
self.qtLibCombo.addItem("")
self.qtLibCombo.addItem("")
self.gridLayout.addWidget(self.qtLibCombo, 1, 1, 1, 1)
self.label = QtWidgets.QLabel(self.widget)
self.label.setObjectName("label")
self.gridLayout.addWidget(self.label, 1, 0, 1, 1)
self.loadBtn = QtWidgets.QPushButton(self.widget)
self.gridLayout.addWidget(self.qtLibCombo, 4, 1, 1, 1)
self.loadBtn = QtWidgets.QPushButton(self.layoutWidget)
self.loadBtn.setObjectName("loadBtn")
self.gridLayout.addWidget(self.loadBtn, 3, 1, 1, 1)
self.widget1 = QtWidgets.QWidget(self.splitter)
self.widget1.setObjectName("widget1")
self.verticalLayout = QtWidgets.QVBoxLayout(self.widget1)
self.gridLayout.addWidget(self.loadBtn, 6, 1, 1, 1)
self.exampleTree = QtWidgets.QTreeWidget(self.layoutWidget)
self.exampleTree.setObjectName("exampleTree")
self.exampleTree.headerItem().setText(0, "1")
self.exampleTree.header().setVisible(False)
self.gridLayout.addWidget(self.exampleTree, 3, 0, 1, 2)
self.label = QtWidgets.QLabel(self.layoutWidget)
self.label.setObjectName("label")
self.gridLayout.addWidget(self.label, 4, 0, 1, 1)
self.exampleFilter = QtWidgets.QLineEdit(self.layoutWidget)
self.exampleFilter.setObjectName("exampleFilter")
self.gridLayout.addWidget(self.exampleFilter, 0, 0, 1, 2)
self.searchFiles = QtWidgets.QComboBox(self.layoutWidget)
self.searchFiles.setObjectName("searchFiles")
self.searchFiles.addItem("")
self.searchFiles.addItem("")
self.gridLayout.addWidget(self.searchFiles, 1, 0, 1, 2)
self.layoutWidget1 = QtWidgets.QWidget(self.splitter)
self.layoutWidget1.setObjectName("layoutWidget1")
self.verticalLayout = QtWidgets.QVBoxLayout(self.layoutWidget1)
self.verticalLayout.setContentsMargins(0, 0, 0, 0)
self.verticalLayout.setObjectName("verticalLayout")
self.loadedFileLabel = QtWidgets.QLabel(self.widget1)
self.loadedFileLabel = QtWidgets.QLabel(self.layoutWidget1)
font = QtGui.QFont()
font.setBold(True)
self.loadedFileLabel.setFont(font)
@ -56,13 +65,13 @@ class Ui_Form(object):
self.loadedFileLabel.setAlignment(QtCore.Qt.AlignCenter)
self.loadedFileLabel.setObjectName("loadedFileLabel")
self.verticalLayout.addWidget(self.loadedFileLabel)
self.codeView = QtWidgets.QPlainTextEdit(self.widget1)
self.codeView = QtWidgets.QPlainTextEdit(self.layoutWidget1)
font = QtGui.QFont()
font.setFamily("Courier New")
self.codeView.setFont(font)
self.codeView.setObjectName("codeView")
self.verticalLayout.addWidget(self.codeView)
self.gridLayout_2.addWidget(self.splitter, 0, 0, 1, 1)
self.gridLayout_2.addWidget(self.splitter, 1, 0, 1, 1)
self.retranslateUi(Form)
QtCore.QMetaObject.connectSlotsByName(Form)
@ -75,5 +84,8 @@ class Ui_Form(object):
self.qtLibCombo.setItemText(2, _translate("Form", "PySide2"))
self.qtLibCombo.setItemText(3, _translate("Form", "PySide6"))
self.qtLibCombo.setItemText(4, _translate("Form", "PyQt6"))
self.label.setText(_translate("Form", "Qt Library:"))
self.loadBtn.setText(_translate("Form", "Run Example"))
self.label.setText(_translate("Form", "Qt Library:"))
self.exampleFilter.setPlaceholderText(_translate("Form", "Type to filter..."))
self.searchFiles.setItemText(0, _translate("Form", "Title Search"))
self.searchFiles.setItemText(1, _translate("Form", "Content Search"))

View File

@ -1,6 +1,6 @@
# Form implementation generated from reading ui file 'examples/exampleLoaderTemplate.ui'
#
# Created by: PyQt6 UI code generator 6.1.0
# Created by: PyQt6 UI code generator 6.1.1
#
# WARNING: Any manual changes made to this file will be lost when pyuic6 is
# run again. Do not edit this file unless you know what you are doing.
@ -18,36 +18,44 @@ class Ui_Form(object):
self.splitter = QtWidgets.QSplitter(Form)
self.splitter.setOrientation(QtCore.Qt.Orientation.Horizontal)
self.splitter.setObjectName("splitter")
self.widget = QtWidgets.QWidget(self.splitter)
self.widget.setObjectName("widget")
self.gridLayout = QtWidgets.QGridLayout(self.widget)
self.layoutWidget = QtWidgets.QWidget(self.splitter)
self.layoutWidget.setObjectName("layoutWidget")
self.gridLayout = QtWidgets.QGridLayout(self.layoutWidget)
self.gridLayout.setContentsMargins(0, 0, 0, 0)
self.gridLayout.setObjectName("gridLayout")
self.exampleTree = QtWidgets.QTreeWidget(self.widget)
self.exampleTree.setObjectName("exampleTree")
self.exampleTree.headerItem().setText(0, "1")
self.exampleTree.header().setVisible(False)
self.gridLayout.addWidget(self.exampleTree, 0, 0, 1, 2)
self.qtLibCombo = QtWidgets.QComboBox(self.widget)
self.qtLibCombo = QtWidgets.QComboBox(self.layoutWidget)
self.qtLibCombo.setObjectName("qtLibCombo")
self.qtLibCombo.addItem("")
self.qtLibCombo.addItem("")
self.qtLibCombo.addItem("")
self.qtLibCombo.addItem("")
self.qtLibCombo.addItem("")
self.gridLayout.addWidget(self.qtLibCombo, 1, 1, 1, 1)
self.label = QtWidgets.QLabel(self.widget)
self.label.setObjectName("label")
self.gridLayout.addWidget(self.label, 1, 0, 1, 1)
self.loadBtn = QtWidgets.QPushButton(self.widget)
self.gridLayout.addWidget(self.qtLibCombo, 4, 1, 1, 1)
self.loadBtn = QtWidgets.QPushButton(self.layoutWidget)
self.loadBtn.setObjectName("loadBtn")
self.gridLayout.addWidget(self.loadBtn, 3, 1, 1, 1)
self.widget1 = QtWidgets.QWidget(self.splitter)
self.widget1.setObjectName("widget1")
self.verticalLayout = QtWidgets.QVBoxLayout(self.widget1)
self.gridLayout.addWidget(self.loadBtn, 6, 1, 1, 1)
self.exampleTree = QtWidgets.QTreeWidget(self.layoutWidget)
self.exampleTree.setObjectName("exampleTree")
self.exampleTree.headerItem().setText(0, "1")
self.exampleTree.header().setVisible(False)
self.gridLayout.addWidget(self.exampleTree, 3, 0, 1, 2)
self.label = QtWidgets.QLabel(self.layoutWidget)
self.label.setObjectName("label")
self.gridLayout.addWidget(self.label, 4, 0, 1, 1)
self.exampleFilter = QtWidgets.QLineEdit(self.layoutWidget)
self.exampleFilter.setObjectName("exampleFilter")
self.gridLayout.addWidget(self.exampleFilter, 0, 0, 1, 2)
self.searchFiles = QtWidgets.QComboBox(self.layoutWidget)
self.searchFiles.setObjectName("searchFiles")
self.searchFiles.addItem("")
self.searchFiles.addItem("")
self.gridLayout.addWidget(self.searchFiles, 1, 0, 1, 2)
self.layoutWidget1 = QtWidgets.QWidget(self.splitter)
self.layoutWidget1.setObjectName("layoutWidget1")
self.verticalLayout = QtWidgets.QVBoxLayout(self.layoutWidget1)
self.verticalLayout.setContentsMargins(0, 0, 0, 0)
self.verticalLayout.setObjectName("verticalLayout")
self.loadedFileLabel = QtWidgets.QLabel(self.widget1)
self.loadedFileLabel = QtWidgets.QLabel(self.layoutWidget1)
font = QtGui.QFont()
font.setBold(True)
self.loadedFileLabel.setFont(font)
@ -55,13 +63,13 @@ class Ui_Form(object):
self.loadedFileLabel.setAlignment(QtCore.Qt.AlignmentFlag.AlignCenter)
self.loadedFileLabel.setObjectName("loadedFileLabel")
self.verticalLayout.addWidget(self.loadedFileLabel)
self.codeView = QtWidgets.QPlainTextEdit(self.widget1)
self.codeView = QtWidgets.QPlainTextEdit(self.layoutWidget1)
font = QtGui.QFont()
font.setFamily("Courier New")
self.codeView.setFont(font)
self.codeView.setObjectName("codeView")
self.verticalLayout.addWidget(self.codeView)
self.gridLayout_2.addWidget(self.splitter, 0, 0, 1, 1)
self.gridLayout_2.addWidget(self.splitter, 1, 0, 1, 1)
self.retranslateUi(Form)
QtCore.QMetaObject.connectSlotsByName(Form)
@ -74,5 +82,8 @@ class Ui_Form(object):
self.qtLibCombo.setItemText(2, _translate("Form", "PySide2"))
self.qtLibCombo.setItemText(3, _translate("Form", "PySide6"))
self.qtLibCombo.setItemText(4, _translate("Form", "PyQt6"))
self.label.setText(_translate("Form", "Qt Library:"))
self.loadBtn.setText(_translate("Form", "Run Example"))
self.label.setText(_translate("Form", "Qt Library:"))
self.exampleFilter.setPlaceholderText(_translate("Form", "Type to filter..."))
self.searchFiles.setItemText(0, _translate("Form", "Title Search"))
self.searchFiles.setItemText(1, _translate("Form", "Content Search"))

View File

@ -1,79 +1,120 @@
# -*- coding: utf-8 -*-
# Form implementation generated from reading ui file 'exampleLoaderTemplate.ui',
# licensing of 'exampleLoaderTemplate.ui' applies.
#
# Created: Mon Feb 22 18:33:36 2021
# by: pyside2-uic running on PySide2 5.12.6
#
# WARNING! All changes made in this file will be lost!
################################################################################
## Form generated from reading UI file 'exampleLoaderTemplate.ui'
##
## Created by: Qt User Interface Compiler version 5.15.2
##
## WARNING! All changes made in this file will be lost when recompiling UI file!
################################################################################
from PySide2.QtCore import *
from PySide2.QtGui import *
from PySide2.QtWidgets import *
from PySide2 import QtCore, QtGui, QtWidgets
class Ui_Form(object):
def setupUi(self, Form):
Form.setObjectName("Form")
if not Form.objectName():
Form.setObjectName(u"Form")
Form.resize(846, 552)
self.gridLayout_2 = QtWidgets.QGridLayout(Form)
self.gridLayout_2.setObjectName("gridLayout_2")
self.splitter = QtWidgets.QSplitter(Form)
self.splitter.setOrientation(QtCore.Qt.Horizontal)
self.splitter.setObjectName("splitter")
self.widget = QtWidgets.QWidget(self.splitter)
self.widget.setObjectName("widget")
self.gridLayout = QtWidgets.QGridLayout(self.widget)
self.gridLayout_2 = QGridLayout(Form)
self.gridLayout_2.setObjectName(u"gridLayout_2")
self.splitter = QSplitter(Form)
self.splitter.setObjectName(u"splitter")
self.splitter.setOrientation(Qt.Horizontal)
self.layoutWidget = QWidget(self.splitter)
self.layoutWidget.setObjectName(u"layoutWidget")
self.gridLayout = QGridLayout(self.layoutWidget)
self.gridLayout.setObjectName(u"gridLayout")
self.gridLayout.setContentsMargins(0, 0, 0, 0)
self.gridLayout.setObjectName("gridLayout")
self.exampleTree = QtWidgets.QTreeWidget(self.widget)
self.exampleTree.setObjectName("exampleTree")
self.exampleTree.headerItem().setText(0, "1")
self.qtLibCombo = QComboBox(self.layoutWidget)
self.qtLibCombo.addItem("")
self.qtLibCombo.addItem("")
self.qtLibCombo.addItem("")
self.qtLibCombo.addItem("")
self.qtLibCombo.addItem("")
self.qtLibCombo.setObjectName(u"qtLibCombo")
self.gridLayout.addWidget(self.qtLibCombo, 4, 1, 1, 1)
self.loadBtn = QPushButton(self.layoutWidget)
self.loadBtn.setObjectName(u"loadBtn")
self.gridLayout.addWidget(self.loadBtn, 6, 1, 1, 1)
self.exampleTree = QTreeWidget(self.layoutWidget)
__qtreewidgetitem = QTreeWidgetItem()
__qtreewidgetitem.setText(0, u"1");
self.exampleTree.setHeaderItem(__qtreewidgetitem)
self.exampleTree.setObjectName(u"exampleTree")
self.exampleTree.header().setVisible(False)
self.gridLayout.addWidget(self.exampleTree, 0, 0, 1, 2)
self.qtLibCombo = QtWidgets.QComboBox(self.widget)
self.qtLibCombo.setObjectName("qtLibCombo")
self.qtLibCombo.addItem("")
self.qtLibCombo.addItem("")
self.qtLibCombo.addItem("")
self.qtLibCombo.addItem("")
self.qtLibCombo.addItem("")
self.gridLayout.addWidget(self.qtLibCombo, 1, 1, 1, 1)
self.label = QtWidgets.QLabel(self.widget)
self.label.setObjectName("label")
self.gridLayout.addWidget(self.label, 1, 0, 1, 1)
self.loadBtn = QtWidgets.QPushButton(self.widget)
self.loadBtn.setObjectName("loadBtn")
self.gridLayout.addWidget(self.loadBtn, 3, 1, 1, 1)
self.widget1 = QtWidgets.QWidget(self.splitter)
self.widget1.setObjectName("widget1")
self.verticalLayout = QtWidgets.QVBoxLayout(self.widget1)
self.gridLayout.addWidget(self.exampleTree, 3, 0, 1, 2)
self.label = QLabel(self.layoutWidget)
self.label.setObjectName(u"label")
self.gridLayout.addWidget(self.label, 4, 0, 1, 1)
self.exampleFilter = QLineEdit(self.layoutWidget)
self.exampleFilter.setObjectName(u"exampleFilter")
self.gridLayout.addWidget(self.exampleFilter, 0, 0, 1, 2)
self.searchFiles = QComboBox(self.layoutWidget)
self.searchFiles.addItem("")
self.searchFiles.addItem("")
self.searchFiles.setObjectName(u"searchFiles")
self.gridLayout.addWidget(self.searchFiles, 1, 0, 1, 2)
self.splitter.addWidget(self.layoutWidget)
self.layoutWidget1 = QWidget(self.splitter)
self.layoutWidget1.setObjectName(u"layoutWidget1")
self.verticalLayout = QVBoxLayout(self.layoutWidget1)
self.verticalLayout.setObjectName(u"verticalLayout")
self.verticalLayout.setContentsMargins(0, 0, 0, 0)
self.verticalLayout.setObjectName("verticalLayout")
self.loadedFileLabel = QtWidgets.QLabel(self.widget1)
font = QtGui.QFont()
self.loadedFileLabel = QLabel(self.layoutWidget1)
self.loadedFileLabel.setObjectName(u"loadedFileLabel")
font = QFont()
font.setBold(True)
self.loadedFileLabel.setFont(font)
self.loadedFileLabel.setText("")
self.loadedFileLabel.setAlignment(QtCore.Qt.AlignCenter)
self.loadedFileLabel.setObjectName("loadedFileLabel")
self.loadedFileLabel.setAlignment(Qt.AlignCenter)
self.verticalLayout.addWidget(self.loadedFileLabel)
self.codeView = QtWidgets.QPlainTextEdit(self.widget1)
font = QtGui.QFont()
font.setFamily("Courier New")
self.codeView.setFont(font)
self.codeView.setObjectName("codeView")
self.codeView = QPlainTextEdit(self.layoutWidget1)
self.codeView.setObjectName(u"codeView")
font1 = QFont()
font1.setFamily(u"Courier New")
self.codeView.setFont(font1)
self.verticalLayout.addWidget(self.codeView)
self.gridLayout_2.addWidget(self.splitter, 0, 0, 1, 1)
self.splitter.addWidget(self.layoutWidget1)
self.gridLayout_2.addWidget(self.splitter, 1, 0, 1, 1)
self.retranslateUi(Form)
QtCore.QMetaObject.connectSlotsByName(Form)
QMetaObject.connectSlotsByName(Form)
# setupUi
def retranslateUi(self, Form):
Form.setWindowTitle(QtWidgets.QApplication.translate("Form", "PyQtGraph", None, -1))
self.qtLibCombo.setItemText(0, QtWidgets.QApplication.translate("Form", "default", None, -1))
self.qtLibCombo.setItemText(1, QtWidgets.QApplication.translate("Form", "PyQt5", None, -1))
self.qtLibCombo.setItemText(2, QtWidgets.QApplication.translate("Form", "PySide2", None, -1))
self.qtLibCombo.setItemText(3, QtWidgets.QApplication.translate("Form", "PySide6", None, -1))
self.qtLibCombo.setItemText(4, QtWidgets.QApplication.translate("Form", "PyQt6", None, -1))
self.label.setText(QtWidgets.QApplication.translate("Form", "Qt Library:", None, -1))
self.loadBtn.setText(QtWidgets.QApplication.translate("Form", "Run Example", None, -1))
Form.setWindowTitle(QCoreApplication.translate("Form", u"PyQtGraph", None))
self.qtLibCombo.setItemText(0, QCoreApplication.translate("Form", u"default", None))
self.qtLibCombo.setItemText(1, QCoreApplication.translate("Form", u"PyQt5", None))
self.qtLibCombo.setItemText(2, QCoreApplication.translate("Form", u"PySide2", None))
self.qtLibCombo.setItemText(3, QCoreApplication.translate("Form", u"PySide6", None))
self.qtLibCombo.setItemText(4, QCoreApplication.translate("Form", u"PyQt6", None))
self.loadBtn.setText(QCoreApplication.translate("Form", u"Run Example", None))
self.label.setText(QCoreApplication.translate("Form", u"Qt Library:", None))
self.exampleFilter.setPlaceholderText(QCoreApplication.translate("Form", u"Type to filter...", None))
self.searchFiles.setItemText(0, QCoreApplication.translate("Form", u"Title Search", None))
self.searchFiles.setItemText(1, QCoreApplication.translate("Form", u"Content Search", None))
self.loadedFileLabel.setText("")
# retranslateUi

View File

@ -3,14 +3,14 @@
################################################################################
## Form generated from reading UI file 'exampleLoaderTemplate.ui'
##
## Created by: Qt User Interface Compiler version 6.1.0
## Created by: Qt User Interface Compiler version 6.1.1
##
## WARNING! All changes made in this file will be lost when recompiling UI file!
################################################################################
from PySide6.QtCore import *
from PySide6.QtGui import *
from PySide6.QtWidgets import *
from PySide6.QtCore import * # type: ignore
from PySide6.QtGui import * # type: ignore
from PySide6.QtWidgets import * # type: ignore
class Ui_Form(object):
@ -23,21 +23,12 @@ class Ui_Form(object):
self.splitter = QSplitter(Form)
self.splitter.setObjectName(u"splitter")
self.splitter.setOrientation(Qt.Horizontal)
self.widget = QWidget(self.splitter)
self.widget.setObjectName(u"widget")
self.gridLayout = QGridLayout(self.widget)
self.layoutWidget = QWidget(self.splitter)
self.layoutWidget.setObjectName(u"layoutWidget")
self.gridLayout = QGridLayout(self.layoutWidget)
self.gridLayout.setObjectName(u"gridLayout")
self.gridLayout.setContentsMargins(0, 0, 0, 0)
self.exampleTree = QTreeWidget(self.widget)
__qtreewidgetitem = QTreeWidgetItem()
__qtreewidgetitem.setText(0, u"1");
self.exampleTree.setHeaderItem(__qtreewidgetitem)
self.exampleTree.setObjectName(u"exampleTree")
self.exampleTree.header().setVisible(False)
self.gridLayout.addWidget(self.exampleTree, 0, 0, 1, 2)
self.qtLibCombo = QComboBox(self.widget)
self.qtLibCombo = QComboBox(self.layoutWidget)
self.qtLibCombo.addItem("")
self.qtLibCombo.addItem("")
self.qtLibCombo.addItem("")
@ -45,25 +36,46 @@ class Ui_Form(object):
self.qtLibCombo.addItem("")
self.qtLibCombo.setObjectName(u"qtLibCombo")
self.gridLayout.addWidget(self.qtLibCombo, 1, 1, 1, 1)
self.gridLayout.addWidget(self.qtLibCombo, 4, 1, 1, 1)
self.label = QLabel(self.widget)
self.label.setObjectName(u"label")
self.gridLayout.addWidget(self.label, 1, 0, 1, 1)
self.loadBtn = QPushButton(self.widget)
self.loadBtn = QPushButton(self.layoutWidget)
self.loadBtn.setObjectName(u"loadBtn")
self.gridLayout.addWidget(self.loadBtn, 3, 1, 1, 1)
self.gridLayout.addWidget(self.loadBtn, 6, 1, 1, 1)
self.splitter.addWidget(self.widget)
self.widget1 = QWidget(self.splitter)
self.widget1.setObjectName(u"widget1")
self.verticalLayout = QVBoxLayout(self.widget1)
self.exampleTree = QTreeWidget(self.layoutWidget)
__qtreewidgetitem = QTreeWidgetItem()
__qtreewidgetitem.setText(0, u"1");
self.exampleTree.setHeaderItem(__qtreewidgetitem)
self.exampleTree.setObjectName(u"exampleTree")
self.exampleTree.header().setVisible(False)
self.gridLayout.addWidget(self.exampleTree, 3, 0, 1, 2)
self.label = QLabel(self.layoutWidget)
self.label.setObjectName(u"label")
self.gridLayout.addWidget(self.label, 4, 0, 1, 1)
self.exampleFilter = QLineEdit(self.layoutWidget)
self.exampleFilter.setObjectName(u"exampleFilter")
self.gridLayout.addWidget(self.exampleFilter, 0, 0, 1, 2)
self.searchFiles = QComboBox(self.layoutWidget)
self.searchFiles.addItem("")
self.searchFiles.addItem("")
self.searchFiles.setObjectName(u"searchFiles")
self.gridLayout.addWidget(self.searchFiles, 1, 0, 1, 2)
self.splitter.addWidget(self.layoutWidget)
self.layoutWidget1 = QWidget(self.splitter)
self.layoutWidget1.setObjectName(u"layoutWidget1")
self.verticalLayout = QVBoxLayout(self.layoutWidget1)
self.verticalLayout.setObjectName(u"verticalLayout")
self.verticalLayout.setContentsMargins(0, 0, 0, 0)
self.loadedFileLabel = QLabel(self.widget1)
self.loadedFileLabel = QLabel(self.layoutWidget1)
self.loadedFileLabel.setObjectName(u"loadedFileLabel")
font = QFont()
font.setBold(True)
@ -72,7 +84,7 @@ class Ui_Form(object):
self.verticalLayout.addWidget(self.loadedFileLabel)
self.codeView = QPlainTextEdit(self.widget1)
self.codeView = QPlainTextEdit(self.layoutWidget1)
self.codeView.setObjectName(u"codeView")
font1 = QFont()
font1.setFamilies([u"Courier New"])
@ -80,9 +92,9 @@ class Ui_Form(object):
self.verticalLayout.addWidget(self.codeView)
self.splitter.addWidget(self.widget1)
self.splitter.addWidget(self.layoutWidget1)
self.gridLayout_2.addWidget(self.splitter, 0, 0, 1, 1)
self.gridLayout_2.addWidget(self.splitter, 1, 0, 1, 1)
self.retranslateUi(Form)
@ -98,8 +110,11 @@ class Ui_Form(object):
self.qtLibCombo.setItemText(3, QCoreApplication.translate("Form", u"PySide6", None))
self.qtLibCombo.setItemText(4, QCoreApplication.translate("Form", u"PyQt6", None))
self.label.setText(QCoreApplication.translate("Form", u"Qt Library:", None))
self.loadBtn.setText(QCoreApplication.translate("Form", u"Run Example", None))
self.loadedFileLabel.setText("")
# retranslateUi
self.label.setText(QCoreApplication.translate("Form", u"Qt Library:", None))
self.exampleFilter.setPlaceholderText(QCoreApplication.translate("Form", u"Type to filter...", None))
self.searchFiles.setItemText(0, QCoreApplication.translate("Form", u"Title Search", None))
self.searchFiles.setItemText(1, QCoreApplication.translate("Form", u"Content Search", None))
self.loadedFileLabel.setText("")
# retranslateUi

View File

@ -32,7 +32,7 @@ def buildFileList(examples, files=None):
path = os.path.abspath(os.path.dirname(__file__))
files = [("Example App", "RunExampleApp.py")]
for ex in [utils.examples, utils.others]:
for ex in [utils.examples_, utils.others]:
files = buildFileList(ex, files)
files = sorted(set(files))
frontends = {

View File

@ -1,8 +1,8 @@
from collections import OrderedDict
from argparse import Namespace
examples = OrderedDict([
# Avoid clash with module name
examples_ = OrderedDict([
('Command-line usage', 'CLIexample.py'),
('Basic Plotting', Namespace(filename='Plotting.py', recommended=True)),
('ImageView', 'ImageView.py'),