QSS Parser
Table of Contents
- Features
- Installation
- Usage
- API Reference
- Contributing
- Testing
- License
- Support
- Donate
- Acknowledgements
Features
- Comprehensive QSS Validation: Detects syntax errors including missing semicolons, unclosed braces, properties outside blocks, invalid selectors, and unsupported pseudo-states or pseudo-elements.
- Variable Support: Parses
@variablesblocks, resolves variable references (e.g.,var(--primary-color)), and handles nested variables with circular reference detection. - Structured Parsing: Converts QSS into
QSSRuleandQSSPropertyobjects for easy programmatic manipulation of selectors and properties. - Style Extraction: Retrieves styles for Qt widgets based on object names, class names, attribute selectors (e.g.,
[data-value="complex string"]), pseudo-states (e.g.,:hover), and pseudo-elements (e.g.,::handle). - Advanced Selector Handling: Supports complex selectors, including attribute selectors with spaces or special characters, composite selectors (e.g.,
QPushButton#myButton), and duplicate selector filtering with error reporting. - Pseudo-State and Pseudo-Element Validation: Ensures pseudo-states (e.g.,
:hover,:focus) and pseudo-elements (e.g.,::tab,::indicator) conform to Qt's supported list, with detailed error messages. - Lightweight and Dependency-Free: Requires no external dependencies, ensuring seamless integration into any Python project.
- Plugin-Based Architecture: Extensible design with plugins for selectors, properties, and variables, enabling custom parsing logic.
- Robust Testing: Includes a comprehensive test suite covering validation, parsing, style extraction, variable resolution, and edge cases like duplicate selectors.
Installation
Install qss-parser using pip:
pip install qss-parser
Requirements
- Python 3.6 or higher
- No external dependencies for core functionality.
- For Qt integration, install
PyQt5,PyQt6,PySide2, orPySide6(not included in package dependencies).
To install with Qt support (e.g., PyQt5):
pip install qss-parser PyQt5
Usage
The qss-parser library offers an intuitive API for validating, parsing, and applying QSS styles. Below are examples showcasing its capabilities.
Complete Example
Explore a complete example in the examples directory.
Basic Example
Validate and parse a QSS string, then retrieve styles for a mock widget.
from qss_parser import QSSParser
from unittest.mock import Mock
# Mock widget setup
widget = Mock()
widget.objectName.return_value = "myButton"
widget.metaObject.return_value.className.return_value = "QPushButton"
# Initialize parser
parser = QSSParser()
# Sample QSS
qss = """
#myButton {
color: red;
}
QPushButton {
background: blue;
}
"""
# Validate QSS
errors = parser.check_format(qss)
if errors:
print("Invalid QSS:")
for error in errors:
print(error)
else:
# Parse and extract styles
parser.parse(qss)
styles = parser.get_styles_for(widget)
print("Styles for widget:")
print(styles)
Output:
Styles for widget:
#myButton {
color: red;
}
QPushButton {
background: blue;
}
Validating QSS Syntax
Use check_format to validate QSS syntax and report errors.
from qss_parser import QSSParser
parser = QSSParser()
qss = """
QPushButton {
color: blue
}
"""
errors = parser.check_format(qss)
for error in errors:
print(error)
Output:
Error on line 3: Property missing ';': color: blue
Parsing QSS with Attribute Selectors
Parse QSS with complex attribute selectors and extract styles.
from qss_parser import QSSParser
from unittest.mock import Mock
# Mock widget
widget = Mock()
widget.objectName.return_value = "myButton"
widget.metaObject.return_value.className.return_value = "QPushButton"
parser = QSSParser()
qss = """
QPushButton[data-value="complex string with spaces"] {
color: blue;
}
"""
parser.parse(qss)
styles = parser.get_styles_for(widget)
print("Styles for widget:")
print(styles)
Output:
Styles for widget:
QPushButton[data-value="complex string with spaces"] {
color: blue;
}
Parsing QSS with Variables
Parse QSS with a @variables block, including nested variables.
from qss_parser import QSSParser
from unittest.mock import Mock
# Mock widget
widget = Mock()
widget.objectName.return_value = "myButton"
widget.metaObject.return_value.className.return_value = "QPushButton"
parser = QSSParser()
qss = """
@variables {
--base-color: #0000ff;
--primary-color: var(--base-color);
--font-size: 14px;
}
#myButton {
color: var(--primary-color);
font-size: var(--font-size);
background: white;
}
"""
# Validate QSS
errors = parser.check_format(qss)
if errors:
print("Invalid QSS:")
for error in errors:
print(error)
else:
parser.parse(qss)
styles = parser.get_styles_for(widget)
print("Styles for widget:")
print(styles)
Output:
Styles for widget:
#myButton {
color: #0000ff;
font-size: 14px;
background: white;
}
Integration with Qt Applications
Apply parsed QSS styles to a PyQt5 widget.
from PyQt5.QtWidgets import QApplication, QPushButton
from qss_parser import QSSParser
import sys
# Initialize Qt application
app = QApplication(sys.argv)
# Initialize parser
parser = QSSParser()
# Load QSS from file
with open("styles.qss", "r", encoding="utf-8") as f:
qss = f.read()
# Validate QSS
errors = parser.check_format(qss)
if errors:
print("Invalid QSS:")
for error in errors:
print(error)
sys.exit(1)
# Parse QSS
parser.parse(qss)
# Create button
button = QPushButton("Click Me")
button.setObjectName("myButton")
# Apply styles
styles = parser.get_styles_for(button, include_class_if_object_name=True)
button.setStyleSheet(styles)
# Show button
button.show()
# Run application
sys.exit(app.exec_())
API Reference
QSSParser Class
Main class for parsing and managing QSS.
- Methods:
check_format(qss_text: str) -> List[str]: Validates QSS syntax, returning error messages.parse(qss_text: str) -> None: Parses QSS intoQSSRuleobjects.get_styles_for(widget: WidgetProtocol, fallback_class: Optional[str] = None, additional_selectors: Optional[List[str]] = None, include_class_if_object_name: bool = False) -> str: Retrieves QSS styles for a widget.on(event: ParserEvent, handler: Callable[..., None]) -> None: Registers handlers for events (rule_added,error_found,variable_defined,parse_completed).to_string() -> str: Returns formatted QSS for all parsed rules.
QSSRule Class
Represents a QSS rule with selector and properties.
-
Attributes:
selector: str: Selector (e.g.,#myButton,QPushButton[data-value="value"]).properties: List[QSSProperty]: List of properties.object_name: Optional[str]: Object name (e.g.,myButtonfor#myButton).class_name: Optional[str]: Class name (e.g.,QPushButton).attributes: List[str]: Attribute selectors (e.g.,[data-value="value"]).pseudo_states: List[str]: Pseudo-states (e.g.,:hover).
-
Methods:
add_property(name: str, value: str) -> None: Adds a property.clone_without_pseudo_elements() -> QSSRule: Returns a copy without pseudo-elements.
QSSProperty Class
Represents a QSS property.
-
Attributes:
name: str: Property name (e.g.,color).value: str: Property value (e.g.,blue).
-
Methods:
to_dict() -> QSSPropertyDict: Converts to dictionary.
SelectorUtils Class
Utility for selector parsing and validation.
- Static Methods:
is_complete_rule(line: str) -> bool: Checks if a line is a complete rule.extract_attributes(selector: str) -> List[str]: Extracts attribute selectors.normalize_selector(selector: str) -> str: Normalizes selector formatting.parse_selector(selector: str) -> Tuple[Optional[str], Optional[str], List[str], List[str]]: Parses selector components.validate_selector_syntax(selector: str, line_num: int) -> List[str]: Validates selector syntax.
VariableManager Class
Manages QSS variables.
- Methods:
parse_variables(block: str, start_line: int = 1, on_variable_defined: Optional[Callable[[str, str], None]] = None) -> List[str]: Parses variable block.resolve_variable(value: str) -> Tuple[str, Optional[str]]: Resolves variable references.
QSSStyleSelector Class
Selects styles for widgets.
- Methods:
get_styles_for(rules: List[QSSRule], widget: WidgetProtocol, ...) -> str: Retrieves styles for a widget.
QSSParserPlugin and Derived Plugins
QSSParserPlugin: Abstract base class for plugins.SelectorPlugin: Handles selectors and rules, including duplicate selector filtering.PropertyPlugin: Processes property declarations.VariablePlugin: Manages@variablesblocks.
Contributing
Contributions are welcome! To contribute:
- Fork the repository.
- Create a branch (
git checkout -b feature/my-feature). - Implement changes, adhering to the coding style.
- Run tests (
python -m unittest discover tests). - Submit a pull request with a clear description.
See CONTRIBUTING.md for details.
Code Style
- Adhere to PEP 8.
- Use type hints per PEP 484.
- Provide clear, concise docstrings for public methods and classes.
Testing
The test suite in tests/ covers validation, parsing, style extraction, and variable resolution. Run tests with:
python -m unittest discover tests
For multi-version testing, use tox:
pip install tox
tox
Ensure all tests pass before submitting pull requests.
License
Licensed under the MIT License. See LICENSE for details.
Support
For issues or questions:
Donate
🌟 Support QSS Parser with a Donation! 🌟
If you find QSS Parser helpful and want to support its development, consider making a donation via Web3 wallets. Your contributions help maintain and improve this open-source project! 🙏
| Blockchain | Address | QR Code |
|---|---|---|
0xD42f8604634d3882b3CeCB4408c10ae745182dEF |
||
3fFV5c3pnp9zG81Q3wNsteCPN4zJkpBd3Gm5X2iQ6MK8 |
||
bc1pde34mu568t8sqph708huu7z5p4ecgxv7g90vv0wq72spxrlzuz9s3ge2h5 |
How to Donate:
- Copy the wallet address for your preferred blockchain.
- Send your donation using a Web3 wallet (e.g., MetaMask, Trust Wallet).
- Include a note with your GitHub username (optional) for a shoutout in our Acknowledgements!
⚠️ Important: Always verify wallet addresses before sending funds. We are not responsible for transactions sent to incorrect addresses.
Thank you for supporting QSS Parser! 💖
Acknowledgements
- Gratitude to the Qt community for QSS documentation.
- Inspired by the need for programmatic QSS handling in PyQt/PySide.
- Thanks to contributors and users for feedback and enhancements.
Metadata
Release files for qss-parser 0.2.1
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| qss_parser-0.2.1.tar.gz | 40.4 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| qss_parser-0.2.1-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 60.0 kB
Release files / qss_parser-0.2.1.tar.gz
| Download URL | qss_parser-0.2.1.tar.gz |
|---|---|
| Size | 40.4 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
86215490a0a6167d9f249f3f4dd50f718f972c64b573ca4a73abb57c572cf318
|
|
BLAKE2b-256 checksum How to use checksums |
0d1d868c19f56c88bcefb0ffdb45581a5f02b2642374e30d190bd28c124ba94d
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.1.0 CPython/3.12.10
|
Release files / qss_parser-0.2.1-py3-none-any.whl
| Download URL | qss_parser-0.2.1-py3-none-any.whl |
|---|---|
| Size | 19.6 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
7e571b308365e898f41a79a60bd5b8ef76ac550840aa7780922f3d0090e24185
|
|
BLAKE2b-256 checksum How to use checksums |
c62edb5fd469a52f4b98b23049344668226e77ca94c08a96bcccfd7e3f21b6fc
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.1.0 CPython/3.12.10
|