Task 590: .QSS File Format
Task 590: .QSS File Format
File Format Specifications for the .QSS File Format
The .QSS file format is associated with Qt Style Sheets, a text-based format used to define the visual style of Qt applications. It is analogous to CSS for HTML, allowing customization of widget appearance through selectors, properties, and values. The format is not binary but plain text, typically encoded in UTF-8. The official specifications are documented in the Qt documentation, including the syntax rules and supported elements. For detailed reference, consult the Qt Style Sheet Syntax at https://doc.qt.io/qt-6/stylesheet-syntax.html and the property reference at https://doc.qt.io/qt-6/stylesheet-reference.html.
1. List of All Properties of This File Format Intrinsic to Its File System
In the context of the .QSS file format, the properties refer to the supported style properties that can be defined within the file to customize widget appearance. These properties are intrinsic to the format's structure as a styling language. The following table lists all supported properties, along with their types and brief descriptions where applicable (based on Qt 6 documentation).
| Property Name | Type | Description |
|---|---|---|
| accent-color | Brush | Sets the accent color for emphasizing interactive UI elements; defaults to highlight color. |
| alternate-background-color | Brush | Alternate background color for item views; defaults to palette's AlternateBase. |
| background | Shorthand | Shorthand for background-color, background-image, background-repeat, and background-position. |
| background-attachment | Attachment | Determines if background-image scrolls or is fixed in scroll areas; defaults to scroll. |
| background-clip | Origin | Rectangle to which background is clipped; defaults to border. |
| background-color | Brush | Background color of the widget. |
| background-image | Url | Background image; semi-transparent parts show background-color. |
| background-origin | Origin | Background rectangle for positioning; defaults to padding. |
| background-position | Alignment | Alignment of background image; defaults to top left. |
| background-repeat | Repeat | How background image is repeated; defaults to repeat. |
| border | Shorthand | Shorthand for border-color, border-style, and border-width. |
| border-bottom | Shorthand | Shorthand for bottom border. |
| border-bottom-color | Brush | Color of bottom border edge. |
| border-bottom-left-radius | Radius | Radius of bottom-left border corner. |
| border-bottom-right-radius | Radius | Radius of bottom-right border corner. |
| border-bottom-style | Style | Style of bottom border edge. |
| border-bottom-width | Length | Width of bottom border edge. |
| border-color | Brush | Color of all border edges; defaults to color property. |
| border-image | Image | Image for border, sliced into nine parts. |
| border-left | Shorthand | Shorthand for left border. |
| border-left-color | Brush | Color of left border edge. |
| border-left-style | Style | Style of left border edge. |
| border-left-width | Length | Width of left border edge. |
| border-radius | Radius | Radius of all border corners. |
| border-right | Shorthand | Shorthand for right border. |
| border-right-color | Brush | Color of right border edge. |
| border-right-style | Style | Style of right border edge. |
| border-right-width | Length | Width of right border edge. |
| border-style | Style | Style of all border edges; defaults to none. |
| border-top | Shorthand | Shorthand for top border. |
| border-top-color | Brush | Color of top border edge. |
| border-top-left-radius | Radius | Radius of top-left border corner. |
| border-top-right-radius | Radius | Radius of top-right border corner. |
| border-top-style | Style | Style of top border edge. |
| border-top-width | Length | Width of top border edge. |
| bottom | Length | Offset for subcontrol positioning. |
| button-layout | Number | Layout of buttons in dialog boxes; defaults to style hint. |
| color | Brush | Text color; defaults to palette foreground. |
| dialogbuttonbox-buttons-have-icons | Boolean | Whether dialog buttons show icons. |
| font | Shorthand | Shorthand for font-family, font-size, font-style, font-weight. |
| font-family | String | Font family name. |
| font-size | Size | Font size. |
| font-style | Style | Font style (e.g., normal, italic). |
| font-weight | Weight | Font weight. |
| gridline-color | Color | Color of grid lines in item views. |
| height | Length | Height of widget or subcontrol. |
| image | Url | Image for subcontrols like indicators. |
| image-position | Alignment | Position of subcontrol image. |
| left | Length | Offset for subcontrol positioning. |
| lineedit-password-character | Number | Unicode character for password masking. |
| lineedit-password-mask-delay | Number | Delay before masking password characters. |
| margin | Box | Shorthand for margins. |
| margin-bottom | Length | Bottom margin. |
| margin-left | Length | Left margin. |
| margin-right | Length | Right margin. |
| margin-top | Length | Top margin. |
| max-height | Length | Maximum height. |
| max-width | Length | Maximum width. |
| messagebox-text-interaction-flags | Flags | Interaction flags for message box text. |
| min-height | Length | Minimum height. |
| min-width | Length | Minimum width. |
| opacity | Number | Widget opacity (0.0 to 1.0). |
| outline | Shorthand | Shorthand for outline-color, outline-style. |
| outline-color | Color | Outline color. |
| outline-offset | Length | Outline offset. |
| outline-radius | Radius | Outline corner radius. |
| outline-bottom-left-radius | Radius | Bottom-left outline radius. |
| outline-bottom-right-radius | Radius | Bottom-right outline radius. |
| outline-style | Style | Outline style. |
| outline-top-left-radius | Radius | Top-left outline radius. |
| outline-top-right-radius | Radius | Top-right outline radius. |
| padding | Box | Shorthand for padding. |
| padding-bottom | Length | Bottom padding. |
| padding-left | Length | Left padding. |
| padding-right | Length | Right padding. |
| padding-top | Length | Top padding. |
| paint-alternating-row-colors-for-empty-area | Boolean | Whether to paint alternating colors for empty areas in item views. |
| position | Position | Positioning mode for subcontrols (relative or absolute). |
| selection-background-color | Brush | Background color for selected text/items. |
| selection-color | Brush | Foreground color for selected text/items. |
| show-decoration-selected | Boolean | Whether selection decorates full row in item views. |
| spacing | Length | Spacing between subcontrols or items. |
| subcontrol-origin | Origin | Origin rectangle for subcontrol positioning. |
| subcontrol-position | Alignment | Position of subcontrol. |
| text-align | Alignment | Text alignment. |
| text-decoration | Decoration | Text decoration (e.g., underline). |
| titletext-align | Alignment | Alignment of title text in group boxes. |
| top | Length | Offset for subcontrol positioning. |
| width | Length | Width of widget or subcontrol. |
2. Two Direct Download Links for Files of Format .QSS
- https://raw.githubusercontent.com/GTRONICK/QSS/master/MaterialDark.qss
- https://raw.githubusercontent.com/GTRONICK/QSS/master/ElegantDark.qss
3. Ghost Blog Embedded HTML JavaScript for Drag and Drop .QSS File
The following is a complete HTML document with embedded JavaScript that allows a user to drag and drop a .QSS file. It validates the file extension, reads the content, parses the properties (extracting property names from the style declarations using a regular expression), and displays them on the screen. Only properties matching the list above are displayed if found.
4. Python Class for .QSS File Handling
The following Python class can open a .QSS file, parse (decode) its content to extract supported properties and their values, print them to the console, and write a new .QSS file with specified properties.
import re
import os
class QSSHandler:
def __init__(self):
self.supported_properties = {
'accent-color', 'alternate-background-color', 'background', 'background-attachment', 'background-clip',
'background-color', 'background-image', 'background-origin', 'background-position', 'background-repeat',
'border', 'border-bottom', 'border-bottom-color', 'border-bottom-left-radius', 'border-bottom-right-radius',
'border-bottom-style', 'border-bottom-width', 'border-color', 'border-image', 'border-left', 'border-left-color',
'border-left-style', 'border-left-width', 'border-radius', 'border-right', 'border-right-color', 'border-right-style',
'border-right-width', 'border-style', 'border-top', 'border-top-color', 'border-top-left-radius', 'border-top-right-radius',
'border-top-style', 'border-top-width', 'bottom', 'button-layout', 'color', 'dialogbuttonbox-buttons-have-icons',
'font', 'font-family', 'font-size', 'font-style', 'font-weight', 'gridline-color', 'height', 'image', 'image-position',
'left', 'lineedit-password-character', 'lineedit-password-mask-delay', 'margin', 'margin-bottom', 'margin-left',
'margin-right', 'margin-top', 'max-height', 'max-width', 'messagebox-text-interaction-flags', 'min-height', 'min-width',
'opacity', 'outline', 'outline-color', 'outline-offset', 'outline-radius', 'outline-bottom-left-radius',
'outline-bottom-right-radius', 'outline-style', 'outline-top-left-radius', 'outline-top-right-radius', 'padding',
'padding-bottom', 'padding-left', 'padding-right', 'padding-top', 'paint-alternating-row-colors-for-empty-area',
'position', 'selection-background-color', 'selection-color', 'show-decoration-selected', 'spacing', 'subcontrol-origin',
'subcontrol-position', 'text-align', 'text-decoration', 'titletext-align', 'top', 'width'
}
self.properties = {}
def open_and_decode(self, filepath):
if not filepath.endswith('.qss'):
raise ValueError("File must have .qss extension.")
if not os.path.exists(filepath):
raise FileNotFoundError("File not found.")
with open(filepath, 'r', encoding='utf-8') as f:
content = f.read()
regex = r'([\w-]+)\s*:\s*([^;]+);'
matches = re.findall(regex, content)
self.properties = {prop: value for prop, value in matches if prop in self.supported_properties}
def print_properties(self):
for prop, value in self.properties.items():
print(f"{prop}: {value}")
def write(self, filepath, selector='*', new_properties=None):
if new_properties:
self.properties.update({k: v for k, v in new_properties.items() if k in self.supported_properties})
with open(filepath, 'w', encoding='utf-8') as f:
f.write(f"{selector} {{\n")
for prop, value in self.properties.items():
f.write(f" {prop}: {value};\n")
f.write("}\n")
5. Java Class for .QSS File Handling
The following Java class can open a .QSS file, parse its content to extract supported properties and their values, print them to the console, and write a new .QSS file with specified properties.
import java.io.*;
import java.util.*;
import java.util.regex.*;
public class QSSHandler {
private Set<String> supportedProperties = new HashSet<>(Arrays.asList(
"accent-color", "alternate-background-color", "background", "background-attachment", "background-clip",
"background-color", "background-image", "background-origin", "background-position", "background-repeat",
"border", "border-bottom", "border-bottom-color", "border-bottom-left-radius", "border-bottom-right-radius",
"border-bottom-style", "border-bottom-width", "border-color", "border-image", "border-left", "border-left-color",
"border-left-style", "border-left-width", "border-radius", "border-right", "border-right-color", "border-right-style",
"border-right-width", "border-style", "border-top", "border-top-color", "border-top-left-radius", "border-top-right-radius",
"border-top-style", "border-top-width", "bottom", "button-layout", "color", "dialogbuttonbox-buttons-have-icons",
"font", "font-family", "font-size", "font-style", "font-weight", "gridline-color", "height", "image", "image-position",
"left", "lineedit-password-character", "lineedit-password-mask-delay", "margin", "margin-bottom", "margin-left",
"margin-right", "margin-top", "max-height", "max-width", "messagebox-text-interaction-flags", "min-height", "min-width",
"opacity", "outline", "outline-color", "outline-offset", "outline-radius", "outline-bottom-left-radius",
"outline-bottom-right-radius", "outline-style", "outline-top-left-radius", "outline-top-right-radius", "padding",
"padding-bottom", "padding-left", "padding-right", "padding-top", "paint-alternating-row-colors-for-empty-area",
"position", "selection-background-color", "selection-color", "show-decoration-selected", "spacing", "subcontrol-origin",
"subcontrol-position", "text-align", "text-decoration", "titletext-align", "top", "width"
));
private Map<String, String> properties = new HashMap<>();
public void openAndDecode(String filepath) throws IOException {
if (!filepath.endsWith(".qss")) {
throw new IllegalArgumentException("File must have .qss extension.");
}
File file = new File(filepath);
if (!file.exists()) {
throw new FileNotFoundException("File not found.");
}
StringBuilder content = new StringBuilder();
try (BufferedReader reader = new BufferedReader(new FileReader(file))) {
String line;
while ((line = reader.readLine()) != null) {
content.append(line).append("\n");
}
}
Pattern pattern = Pattern.compile("([\\w-]+)\\s*:\\s*([^;]+);");
Matcher matcher = pattern.matcher(content.toString());
while (matcher.find()) {
String prop = matcher.group(1).trim();
if (supportedProperties.contains(prop)) {
properties.put(prop, matcher.group(2).trim());
}
}
}
public void printProperties() {
for (Map.Entry<String, String> entry : properties.entrySet()) {
System.out.println(entry.getKey() + ": " + entry.getValue());
}
}
public void write(String filepath, String selector, Map<String, String> newProperties) throws IOException {
if (newProperties != null) {
newProperties.forEach((k, v) -> {
if (supportedProperties.contains(k)) {
properties.put(k, v);
}
});
}
try (BufferedWriter writer = new BufferedWriter(new FileWriter(filepath))) {
writer.write(selector + " {\n");
for (Map.Entry<String, String> entry : properties.entrySet()) {
writer.write(" " + entry.getKey() + ": " + entry.getValue() + ";\n");
}
writer.write("}\n");
}
}
}
6. JavaScript Class for .QSS File Handling
The following JavaScript class (Node.js compatible) can open a .QSS file, parse its content to extract supported properties and their values, print them to the console, and write a new .QSS file with specified properties.
const fs = require('fs');
class QSSHandler {
constructor() {
this.supportedProperties = new Set([
'accent-color', 'alternate-background-color', 'background', 'background-attachment', 'background-clip',
'background-color', 'background-image', 'background-origin', 'background-position', 'background-repeat',
'border', 'border-bottom', 'border-bottom-color', 'border-bottom-left-radius', 'border-bottom-right-radius',
'border-bottom-style', 'border-bottom-width', 'border-color', 'border-image', 'border-left', 'border-left-color',
'border-left-style', 'border-left-width', 'border-radius', 'border-right', 'border-right-color', 'border-right-style',
'border-right-width', 'border-style', 'border-top', 'border-top-color', 'border-top-left-radius', 'border-top-right-radius',
'border-top-style', 'border-top-width', 'bottom', 'button-layout', 'color', 'dialogbuttonbox-buttons-have-icons',
'font', 'font-family', 'font-size', 'font-style', 'font-weight', 'gridline-color', 'height', 'image', 'image-position',
'left', 'lineedit-password-character', 'lineedit-password-mask-delay', 'margin', 'margin-bottom', 'margin-left',
'margin-right', 'margin-top', 'max-height', 'max-width', 'messagebox-text-interaction-flags', 'min-height', 'min-width',
'opacity', 'outline', 'outline-color', 'outline-offset', 'outline-radius', 'outline-bottom-left-radius',
'outline-bottom-right-radius', 'outline-style', 'outline-top-left-radius', 'outline-top-right-radius', 'padding',
'padding-bottom', 'padding-left', 'padding-right', 'padding-top', 'paint-alternating-row-colors-for-empty-area',
'position', 'selection-background-color', 'selection-color', 'show-decoration-selected', 'spacing', 'subcontrol-origin',
'subcontrol-position', 'text-align', 'text-decoration', 'titletext-align', 'top', 'width'
]);
this.properties = new Map();
}
openAndDecode(filepath) {
if (!filepath.endsWith('.qss')) {
throw new Error('File must have .qss extension.');
}
if (!fs.existsSync(filepath)) {
throw new Error('File not found.');
}
const content = fs.readFileSync(filepath, 'utf-8');
const regex = /([\w-]+)\s*:\s*([^;]+);/g;
let match;
while ((match = regex.exec(content)) !== null) {
const prop = match[1].trim();
if (this.supportedProperties.has(prop)) {
this.properties.set(prop, match[2].trim());
}
}
}
printProperties() {
for (const [prop, value] of this.properties) {
console.log(`${prop}: ${value}`);
}
}
write(filepath, selector = '*', newProperties = {}) {
for (const [k, v] of Object.entries(newProperties)) {
if (this.supportedProperties.has(k)) {
this.properties.set(k, v);
}
}
let output = `${selector} {\n`;
for (const [prop, value] of this.properties) {
output += ` ${prop}: ${value};\n`;
}
output += '}\n';
fs.writeFileSync(filepath, output, 'utf-8');
}
}
7. C++ Class for .QSS File Handling
The following C++ class can open a .QSS file, parse its content to extract supported properties and their values, print them to the console, and write a new .QSS file with specified properties. (Note: Requires <regex> support; compile with C++11 or later.)
#include <iostream>
#include <fstream>
#include <string>
#include <regex>
#include <unordered_set>
#include <unordered_map>
class QSSHandler {
private:
std::unordered_set<std::string> supported_properties = {
"accent-color", "alternate-background-color", "background", "background-attachment", "background-clip",
"background-color", "background-image", "background-origin", "background-position", "background-repeat",
"border", "border-bottom", "border-bottom-color", "border-bottom-left-radius", "border-bottom-right-radius",
"border-bottom-style", "border-bottom-width", "border-color", "border-image", "border-left", "border-left-color",
"border-left-style", "border-left-width", "border-radius", "border-right", "border-right-color", "border-right-style",
"border-right-width", "border-style", "border-top", "border-top-color", "border-top-left-radius", "border-top-right-radius",
"border-top-style", "border-top-width", "bottom", "button-layout", "color", "dialogbuttonbox-buttons-have-icons",
"font", "font-family", "font-size", "font-style", "font-weight", "gridline-color", "height", "image", "image-position",
"left", "lineedit-password-character", "lineedit-password-mask-delay", "margin", "margin-bottom", "margin-left",
"margin-right", "margin-top", "max-height", "max-width", "messagebox-text-interaction-flags", "min-height", "min-width",
"opacity", "outline", "outline-color", "outline-offset", "outline-radius", "outline-bottom-left-radius",
"outline-bottom-right-radius", "outline-style", "outline-top-left-radius", "outline-top-right-radius", "padding",
"padding-bottom", "padding-left", "padding-right", "padding-top", "paint-alternating-row-colors-for-empty-area",
"position", "selection-background-color", "selection-color", "show-decoration-selected", "spacing", "subcontrol-origin",
"subcontrol-position", "text-align", "text-decoration", "titletext-align", "top", "width"
};
std::unordered_map<std::string, std::string> properties;
public:
void openAndDecode(const std::string& filepath) {
if (filepath.substr(filepath.find_last_of(".") + 1) != "qss") {
throw std::invalid_argument("File must have .qss extension.");
}
std::ifstream file(filepath);
if (!file.is_open()) {
throw std::runtime_error("File not found.");
}
std::string content((std::istreambuf_iterator<char>(file)), std::istreambuf_iterator<char>());
file.close();
std::regex regex(R"(([\w-]+)\s*:\s*([^;]+);)");
std::sregex_iterator iter(content.begin(), content.end(), regex);
std::sregex_iterator end;
for (; iter != end; ++iter) {
std::string prop = iter->str(1);
if (supported_properties.count(prop)) {
properties[prop] = iter->str(2);
}
}
}
void printProperties() const {
for (const auto& pair : properties) {
std::cout << pair.first << ": " << pair.second << std::endl;
}
}
void write(const std::string& filepath, const std::string& selector = "*", const std::unordered_map<std::string, std::string>& new_properties = {}) {
for (const auto& pair : new_properties) {
if (supported_properties.count(pair.first)) {
properties[pair.first] = pair.second;
}
}
std::ofstream file(filepath);
if (!file.is_open()) {
throw std::runtime_error("Unable to write file.");
}
file << selector << " {\n";
for (const auto& pair : properties) {
file << " " << pair.first << ": " << pair.second << ";\n";
}
file << "}\n";
file.close();
}
};