A parser Python to Qt Style Sheets (QSS)
Project description
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.
Project details
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file qss_parser-0.2.1.tar.gz.
File metadata
- Download URL: qss_parser-0.2.1.tar.gz
- Upload date:
- Size: 40.4 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.1.0 CPython/3.12.10
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
86215490a0a6167d9f249f3f4dd50f718f972c64b573ca4a73abb57c572cf318
|
|
| MD5 |
7b9631358b54d492571459c15009c936
|
|
| BLAKE2b-256 |
0d1d868c19f56c88bcefb0ffdb45581a5f02b2642374e30d190bd28c124ba94d
|
File details
Details for the file qss_parser-0.2.1-py3-none-any.whl.
File metadata
- Download URL: qss_parser-0.2.1-py3-none-any.whl
- Upload date:
- Size: 19.6 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.1.0 CPython/3.12.10
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
7e571b308365e898f41a79a60bd5b8ef76ac550840aa7780922f3d0090e24185
|
|
| MD5 |
400a7bcd7e143508f11690eaebcd8833
|
|
| BLAKE2b-256 |
c62edb5fd469a52f4b98b23049344668226e77ca94c08a96bcccfd7e3f21b6fc
|