Task 746: .UI File Format
Task 746: .UI File Format
.UI File Format Specifications
The .UI file format is an XML-based format utilized by Qt Designer to define and store user interface layouts, widgets, properties, and connections for Qt applications. It follows a structured XML schema that enables the representation of hierarchical UI elements, their attributes, and associated metadata. This format facilitates code generation in languages such as C++ through tools like uic (User Interface Compiler).
1. List of Properties Intrinsic to the .UI File Format
Based on the XML schema of the .UI format, the following properties represent the key structural elements and attributes intrinsic to the format. These are derived from the root <ui> element and its direct children, which define the core characteristics of the file. Properties include both attributes of the root element and top-level child elements, along with their primary sub-components where applicable:
- Version: The format version specified in the
<ui>attribute (e.g., "4.0"). - Language: The target programming language in the
<ui>attribute (e.g., "c++"). - Display Name: A human-readable name for the UI in the
<ui>attribute. - ID-Based Translation: A boolean flag in the
<ui>attribute indicating ID-based translation support. - Connect Slots by Name: A boolean flag in the
<ui>attribute for automatic slot connections. - Standard Set Default (Legacy): Integer values in
<ui>attributesstdsetdefandstdSetDeffor legacy compatibility. - Author: The author's name from the
<author>element. - Comment: Descriptive text from the
<comment>element. - Export Macro: A macro for exporting the UI class from the
<exportmacro>element. - Class Name: The name of the generated UI class from the
<class>element. - Root Widget: The primary widget defined in the
<widget>element, including its class (e.g., "QWidget") and name. - Layout Default: Default spacing and margins from the
<layoutdefault>element (attributes: spacing, margin). - Layout Function: Function names for spacing and margins from the
<layoutfunction>element. - Pixmap Function: A function for loading pixmaps from the
<pixmapfunction>element. - Custom Widgets: A list of custom widgets from the
<customwidgets>element, each including class, extends, header, and other details. - Tab Stops: A sequence of tab stop widget names from the
<tabstops>element. - Includes: A list of header includes from the
<includes>element, each with location and implementation declaration. - Resources: A list of resource files from the
<resources>element, each with location. - Connections: Signal-slot connections from the
<connections>element, each including sender, signal, receiver, slot, and optional hints. - Designer Data: Designer-specific properties from the
<designerdata>element. - Slots: Declarations of signals and slots from the
<slots>element. - Button Groups: Groups of buttons from the
<buttongroups>element, each with name and properties.
These properties encapsulate the format's structure, enabling parsing, modification, and code generation.
2. Two Direct Download Links for .UI Files
The following are direct download links to sample .UI files from public repositories:
- https://code.qt.io/cgit/qt/qttools.git/plain/examples/designer/calculatorform/calculatorform.ui
- https://raw.githubusercontent.com/benymaxparsa/Calculator-Qt/master/calculator.ui
3. HTML with Embedded JavaScript for Drag-and-Drop .UI File Dumper
The following is a self-contained HTML page with embedded JavaScript that allows users to drag and drop a .UI file. Upon dropping, it parses the XML and displays all the properties listed in section 1 on the screen.
Drag and Drop .UI File
4. Python Class for .UI File Handling
The following Python class uses the xml.etree.ElementTree module to open, parse (decode), read, modify (write), and print the properties from the list in section 1 to the console.
import xml.etree.ElementTree as ET
import sys
class UIFileHandler:
def __init__(self, filepath):
self.filepath = filepath
self.tree = None
self.root = None
self.load()
def load(self):
"""Load and parse the .UI file."""
try:
self.tree = ET.parse(self.filepath)
self.root = self.tree.getroot()
if self.root.tag != 'ui':
raise ValueError("Invalid .UI file.")
except Exception as e:
print(f"Error loading file: {e}")
sys.exit(1)
def print_properties(self):
"""Print all properties to console."""
print("Properties:")
# Version
print(f"Version: {self.root.get('version', 'N/A')}")
# Language
print(f"Language: {self.root.get('language', 'N/A')}")
# Display Name
print(f"Display Name: {self.root.get('displayname', 'N/A')}")
# ID-Based Translation
print(f"ID-Based Translation: {self.root.get('idbasedtr', 'N/A')}")
# Connect Slots by Name
print(f"Connect Slots by Name: {self.root.get('connectslotsbyname', 'N/A')}")
# Standard Set Default (Legacy)
print(f"stdsetdef: {self.root.get('stdsetdef', 'N/A')}")
print(f"stdSetDef: {self.root.get('stdSetDef', 'N/A')}")
# Author
print(f"Author: {self.root.findtext('author', 'N/A')}")
# Comment
print(f"Comment: {self.root.findtext('comment', 'N/A')}")
# Export Macro
print(f"Export Macro: {self.root.findtext('exportmacro', 'N/A')}")
# Class Name
print(f"Class Name: {self.root.findtext('class', 'N/A')}")
# Root Widget
widget = self.root.find('widget')
print(f"Root Widget: Class - {widget.get('class', 'N/A') if widget is not None else 'N/A'}, Name - {widget.get('name', 'N/A') if widget is not None else 'N/A'}")
# Layout Default
layout_default = self.root.find('layoutdefault')
print(f"Layout Default: Spacing - {layout_default.get('spacing', 'N/A') if layout_default is not None else 'N/A'}, Margin - {layout_default.get('margin', 'N/A') if layout_default is not None else 'N/A'}")
# Layout Function
layout_function = self.root.find('layoutfunction')
print(f"Layout Function: Spacing - {layout_function.get('spacing', 'N/A') if layout_function is not None else 'N/A'}, Margin - {layout_function.get('margin', 'N/A') if layout_function is not None else 'N/A'}")
# Pixmap Function
print(f"Pixmap Function: {self.root.findtext('pixmapfunction', 'N/A')}")
# Custom Widgets
print("Custom Widgets:")
custom_widgets = self.root.findall('.//customwidget')
if custom_widgets:
for i, cw in enumerate(custom_widgets, 1):
print(f" {i}. Class: {cw.findtext('class', 'N/A')}, Extends: {cw.findtext('extends', 'N/A')}")
else:
print(" N/A")
# Tab Stops
print("Tab Stops:")
tab_stops = self.root.findall('.//tabstop')
if tab_stops:
for i, ts in enumerate(tab_stops, 1):
print(f" {i}. {ts.text}")
else:
print(" N/A")
# Includes
print("Includes:")
includes = self.root.findall('.//include')
if includes:
for i, inc in enumerate(includes, 1):
print(f" {i}. Location: {inc.get('location', 'N/A')}")
else:
print(" N/A")
# Resources
print("Resources:")
resources = self.root.findall('.//resource')
if resources:
for i, res in enumerate(resources, 1):
print(f" {i}. Location: {res.get('location', 'N/A')}")
else:
print(" N/A")
# Connections
print("Connections:")
connections = self.root.findall('.//connection')
if connections:
for i, conn in enumerate(connections, 1):
print(f" {i}. Sender: {conn.findtext('sender', 'N/A')}, Signal: {conn.findtext('signal', 'N/A')}, Receiver: {conn.findtext('receiver', 'N/A')}, Slot: {conn.findtext('slot', 'N/A')}")
else:
print(" N/A")
# Designer Data
designer_data = self.root.find('designerdata')
print(f"Designer Data: {'Present' if designer_data is not None else 'N/A'}")
# Slots
print("Slots:")
slots_elem = self.root.find('slots')
if slots_elem is not None:
signals = slots_elem.findall('signal')
for i, sig in enumerate(signals, 1):
print(f" Signal {i}: {sig.text}")
slots = slots_elem.findall('slot')
for i, slt in enumerate(slots, 1):
print(f" Slot {i}: {slt.text}")
else:
print(" N/A")
# Button Groups
print("Button Groups:")
button_groups = self.root.findall('.//buttongroup')
if button_groups:
for i, bg in enumerate(button_groups, 1):
print(f" {i}. Name: {bg.get('name', 'N/A')}")
else:
print(" N/A")
def write(self, output_path=None):
"""Write the parsed .UI file back to disk (optionally to a new path)."""
if output_path is None:
output_path = self.filepath
try:
self.tree.write(output_path, encoding='utf-8', xml_declaration=True)
print(f"File written to {output_path}")
except Exception as e:
print(f"Error writing file: {e}")
# Example usage:
# handler = UIFileHandler('example.ui')
# handler.print_properties()
# handler.write('modified.ui')
5. Java Class for .UI File Handling
The following Java class uses javax.xml.parsers.DocumentBuilder to open, parse, read, modify, and print the properties to the console.
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import java.io.File;
public class UIFileHandler {
private String filepath;
private Document document;
public UIFileHandler(String filepath) {
this.filepath = filepath;
load();
}
private void load() {
try {
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
DocumentBuilder builder = factory.newDocumentBuilder();
document = builder.parse(new File(filepath));
if (!document.getDocumentElement().getTagName().equals("ui")) {
throw new Exception("Invalid .UI file.");
}
} catch (Exception e) {
System.out.println("Error loading file: " + e.getMessage());
System.exit(1);
}
}
public void printProperties() {
System.out.println("Properties:");
Element root = document.getDocumentElement();
// Version
System.out.println("Version: " + root.getAttribute("version"));
// Language
System.out.println("Language: " + root.getAttribute("language"));
// Display Name
System.out.println("Display Name: " + root.getAttribute("displayname"));
// ID-Based Translation
System.out.println("ID-Based Translation: " + root.getAttribute("idbasedtr"));
// Connect Slots by Name
System.out.println("Connect Slots by Name: " + root.getAttribute("connectslotsbyname"));
// Standard Set Default (Legacy)
System.out.println("stdsetdef: " + root.getAttribute("stdsetdef"));
System.out.println("stdSetDef: " + root.getAttribute("stdSetDef"));
// Author
System.out.println("Author: " + getTextContent("author"));
// Comment
System.out.println("Comment: " + getTextContent("comment"));
// Export Macro
System.out.println("Export Macro: " + getTextContent("exportmacro"));
// Class Name
System.out.println("Class Name: " + getTextContent("class"));
// Root Widget
Element widget = (Element) root.getElementsByTagName("widget").item(0);
String widgetClass = widget != null ? widget.getAttribute("class") : "N/A";
String widgetName = widget != null ? widget.getAttribute("name") : "N/A";
System.out.println("Root Widget: Class - " + widgetClass + ", Name - " + widgetName);
// Layout Default
Element layoutDefault = (Element) root.getElementsByTagName("layoutdefault").item(0);
String spacing = layoutDefault != null ? layoutDefault.getAttribute("spacing") : "N/A";
String margin = layoutDefault != null ? layoutDefault.getAttribute("margin") : "N/A";
System.out.println("Layout Default: Spacing - " + spacing + ", Margin - " + margin);
// Layout Function
Element layoutFunction = (Element) root.getElementsByTagName("layoutfunction").item(0);
String funcSpacing = layoutFunction != null ? layoutFunction.getAttribute("spacing") : "N/A";
String funcMargin = layoutFunction != null ? layoutFunction.getAttribute("margin") : "N/A";
System.out.println("Layout Function: Spacing - " + funcSpacing + ", Margin - " + funcMargin);
// Pixmap Function
System.out.println("Pixmap Function: " + getTextContent("pixmapfunction"));
// Custom Widgets
System.out.println("Custom Widgets:");
NodeList customWidgets = root.getElementsByTagName("customwidget");
if (customWidgets.getLength() > 0) {
for (int i = 0; i < customWidgets.getLength(); i++) {
Element cw = (Element) customWidgets.item(i);
System.out.println(" " + (i + 1) + ". Class: " + getTextContent(cw, "class") + ", Extends: " + getTextContent(cw, "extends"));
}
} else {
System.out.println(" N/A");
}
// Tab Stops
System.out.println("Tab Stops:");
NodeList tabStops = root.getElementsByTagName("tabstop");
if (tabStops.getLength() > 0) {
for (int i = 0; i < tabStops.getLength(); i++) {
System.out.println(" " + (i + 1) + ". " + tabStops.item(i).getTextContent());
}
} else {
System.out.println(" N/A");
}
// Includes
System.out.println("Includes:");
NodeList includes = root.getElementsByTagName("include");
if (includes.getLength() > 0) {
for (int i = 0; i < includes.getLength(); i++) {
Element inc = (Element) includes.item(i);
System.out.println(" " + (i + 1) + ". Location: " + inc.getAttribute("location"));
}
} else {
System.out.println(" N/A");
}
// Resources
System.out.println("Resources:");
NodeList resources = root.getElementsByTagName("resource");
if (resources.getLength() > 0) {
for (int i = 0; i < resources.getLength(); i++) {
Element res = (Element) resources.item(i);
System.out.println(" " + (i + 1) + ". Location: " + res.getAttribute("location"));
}
} else {
System.out.println(" N/A");
}
// Connections
System.out.println("Connections:");
NodeList connections = root.getElementsByTagName("connection");
if (connections.getLength() > 0) {
for (int i = 0; i < connections.getLength(); i++) {
Element conn = (Element) connections.item(i);
System.out.println(" " + (i + 1) + ". Sender: " + getTextContent(conn, "sender") + ", Signal: " + getTextContent(conn, "signal") +
", Receiver: " + getTextContent(conn, "receiver") + ", Slot: " + getTextContent(conn, "slot"));
}
} else {
System.out.println(" N/A");
}
// Designer Data
Element designerData = (Element) root.getElementsByTagName("designerdata").item(0);
System.out.println("Designer Data: " + (designerData != null ? "Present" : "N/A"));
// Slots
System.out.println("Slots:");
Element slotsElem = (Element) root.getElementsByTagName("slots").item(0);
if (slotsElem != null) {
NodeList signals = slotsElem.getElementsByTagName("signal");
for (int i = 0; i < signals.getLength(); i++) {
System.out.println(" Signal " + (i + 1) + ": " + signals.item(i).getTextContent());
}
NodeList slots = slotsElem.getElementsByTagName("slot");
for (int i = 0; i < slots.getLength(); i++) {
System.out.println(" Slot " + (i + 1) + ": " + slots.item(i).getTextContent());
}
} else {
System.out.println(" N/A");
}
// Button Groups
System.out.println("Button Groups:");
NodeList buttonGroups = root.getElementsByTagName("buttongroup");
if (buttonGroups.getLength() > 0) {
for (int i = 0; i < buttonGroups.getLength(); i++) {
Element bg = (Element) buttonGroups.item(i);
System.out.println(" " + (i + 1) + ". Name: " + bg.getAttribute("name"));
}
} else {
System.out.println(" N/A");
}
}
private String getTextContent(String tagName) {
Element elem = (Element) document.getElementsByTagName(tagName).item(0);
return elem != null ? elem.getTextContent() : "N/A";
}
private String getTextContent(Element parent, String tagName) {
Element elem = (Element) parent.getElementsByTagName(tagName).item(0);
return elem != null ? elem.getTextContent() : "N/A";
}
public void write(String outputPath) {
if (outputPath == null) {
outputPath = filepath;
}
try {
TransformerFactory transformerFactory = TransformerFactory.newInstance();
Transformer transformer = transformerFactory.newTransformer();
DOMSource source = new DOMSource(document);
StreamResult result = new StreamResult(new File(outputPath));
transformer.transform(source, result);
System.out.println("File written to " + outputPath);
} catch (Exception e) {
System.out.println("Error writing file: " + e.getMessage());
}
}
// Example usage:
// public static void main(String[] args) {
// UIFileHandler handler = new UIFileHandler("example.ui");
// handler.printProperties();
// handler.write("modified.ui");
// }
}
6. JavaScript Class for .UI File Handling
The following JavaScript class uses DOMParser to parse the .UI file (assuming Node.js with fs for file I/O) and print properties to the console. For write, it serializes back to XML.
const fs = require('fs');
class UIFileHandler {
constructor(filepath) {
this.filepath = filepath;
this.xmlDoc = null;
this.load();
}
load() {
try {
const data = fs.readFileSync(this.filepath, 'utf8');
const parser = new DOMParser();
this.xmlDoc = parser.parseFromString(data, 'application/xml');
if (this.xmlDoc.getElementsByTagName('parsererror').length > 0 || this.xmlDoc.getElementsByTagName('ui').length === 0) {
throw new Error('Invalid .UI file.');
}
} catch (e) {
console.log(`Error loading file: ${e.message}`);
process.exit(1);
}
}
printProperties() {
console.log('Properties:');
const ui = this.xmlDoc.getElementsByTagName('ui')[0];
// Version
console.log(`Version: ${ui.getAttribute('version') || 'N/A'}`);
// Language
console.log(`Language: ${ui.getAttribute('language') || 'N/A'}`);
// Display Name
console.log(`Display Name: ${ui.getAttribute('displayname') || 'N/A'}`);
// ID-Based Translation
console.log(`ID-Based Translation: ${ui.getAttribute('idbasedtr') || 'N/A'}`);
// Connect Slots by Name
console.log(`Connect Slots by Name: ${ui.getAttribute('connectslotsbyname') || 'N/A'}`);
// Standard Set Default (Legacy)
console.log(`stdsetdef: ${ui.getAttribute('stdsetdef') || 'N/A'}`);
console.log(`stdSetDef: ${ui.getAttribute('stdSetDef') || 'N/A'}`);
// Author
console.log(`Author: ${ui.getElementsByTagName('author')[0]?.textContent || 'N/A'}`);
// Comment
console.log(`Comment: ${ui.getElementsByTagName('comment')[0]?.textContent || 'N/A'}`);
// Export Macro
console.log(`Export Macro: ${ui.getElementsByTagName('exportmacro')[0]?.textContent || 'N/A'}`);
// Class Name
console.log(`Class Name: ${ui.getElementsByTagName('class')[0]?.textContent || 'N/A'}`);
// Root Widget
const widget = ui.getElementsByTagName('widget')[0];
console.log(`Root Widget: Class - ${widget?.getAttribute('class') || 'N/A'}, Name - ${widget?.getAttribute('name') || 'N/A'}`);
// Layout Default
const layoutDefault = ui.getElementsByTagName('layoutdefault')[0];
console.log(`Layout Default: Spacing - ${layoutDefault?.getAttribute('spacing') || 'N/A'}, Margin - ${layoutDefault?.getAttribute('margin') || 'N/A'}`);
// Layout Function
const layoutFunction = ui.getElementsByTagName('layoutfunction')[0];
console.log(`Layout Function: Spacing - ${layoutFunction?.getAttribute('spacing') || 'N/A'}, Margin - ${layoutFunction?.getAttribute('margin') || 'N/A'}`);
// Pixmap Function
console.log(`Pixmap Function: ${ui.getElementsByTagName('pixmapfunction')[0]?.textContent || 'N/A'}`);
// Custom Widgets
console.log('Custom Widgets:');
const customWidgets = ui.getElementsByTagName('customwidget');
if (customWidgets.length) {
Array.from(customWidgets).forEach((cw, i) => {
console.log(` ${i+1}. Class: ${cw.getElementsByTagName('class')[0]?.textContent || 'N/A'}, Extends: ${cw.getElementsByTagName('extends')[0]?.textContent || 'N/A'}`);
});
} else {
console.log(' N/A');
}
// Tab Stops
console.log('Tab Stops:');
const tabStops = ui.getElementsByTagName('tabstop');
if (tabStops.length) {
Array.from(tabStops).forEach((ts, i) => {
console.log(` ${i+1}. ${ts.textContent}`);
});
} else {
console.log(' N/A');
}
// Includes
console.log('Includes:');
const includes = ui.getElementsByTagName('include');
if (includes.length) {
Array.from(includes).forEach((inc, i) => {
console.log(` ${i+1}. Location: ${inc.getAttribute('location') || 'N/A'}`);
});
} else {
console.log(' N/A');
}
// Resources
console.log('Resources:');
const resources = ui.getElementsByTagName('resource');
if (resources.length) {
Array.from(resources).forEach((res, i) => {
console.log(` ${i+1}. Location: ${res.getAttribute('location') || 'N/A'}`);
});
} else {
console.log(' N/A');
}
// Connections
console.log('Connections:');
const connections = ui.getElementsByTagName('connection');
if (connections.length) {
Array.from(connections).forEach((conn, i) => {
console.log(` ${i+1}. Sender: ${conn.getElementsByTagName('sender')[0]?.textContent || 'N/A'}, Signal: ${conn.getElementsByTagName('signal')[0]?.textContent || 'N/A'}, Receiver: ${conn.getElementsByTagName('receiver')[0]?.textContent || 'N/A'}, Slot: ${conn.getElementsByTagName('slot')[0]?.textContent || 'N/A'}`);
});
} else {
console.log(' N/A');
}
// Designer Data
console.log(`Designer Data: ${ui.getElementsByTagName('designerdata')[0] ? 'Present' : 'N/A'}`);
// Slots
console.log('Slots:');
const slotsElem = ui.getElementsByTagName('slots')[0];
if (slotsElem) {
const signals = slotsElem.getElementsByTagName('signal');
Array.from(signals).forEach((sig, i) => {
console.log(` Signal ${i+1}: ${sig.textContent}`);
});
const slots = slotsElem.getElementsByTagName('slot');
Array.from(slots).forEach((slt, i) => {
console.log(` Slot ${i+1}: ${slt.textContent}`);
});
} else {
console.log(' N/A');
}
// Button Groups
console.log('Button Groups:');
const buttonGroups = ui.getElementsByTagName('buttongroup');
if (buttonGroups.length) {
Array.from(buttonGroups).forEach((bg, i) => {
console.log(` ${i+1}. Name: ${bg.getAttribute('name') || 'N/A'}`);
});
} else {
console.log(' N/A');
}
}
write(outputPath = null) {
if (outputPath === null) {
outputPath = this.filepath;
}
try {
const serializer = new XMLSerializer();
const xmlStr = serializer.serializeToString(this.xmlDoc);
fs.writeFileSync(outputPath, xmlStr, 'utf8');
console.log(`File written to ${outputPath}`);
} catch (e) {
console.log(`Error writing file: ${e.message}`);
}
}
}
// Example usage:
// const handler = new UIFileHandler('example.ui');
// handler.printProperties();
// handler.write('modified.ui');
7. C++ Class for .UI File Handling
The following C++ class uses TinyXML-2 (assuming inclusion of the library; for brevity, code assumes tinyxml2.h is available) to open, parse, read, modify, and print the properties to the console.
#include <iostream>
#include <string>
#include "tinyxml2.h" // Assume TinyXML-2 library is included
using namespace tinyxml2;
class UIFileHandler {
private:
std::string filepath;
XMLDocument doc;
public:
UIFileHandler(const std::string& filepath) : filepath(filepath) {
load();
}
void load() {
if (doc.LoadFile(filepath.c_str()) != XML_SUCCESS) {
std::cout << "Error loading file: " << doc.ErrorStr() << std::endl;
exit(1);
}
XMLElement* root = doc.FirstChildElement("ui");
if (!root) {
std::cout << "Invalid .UI file." << std::endl;
exit(1);
}
}
void printProperties() {
std::cout << "Properties:" << std::endl;
XMLElement* root = doc.FirstChildElement("ui");
// Version
std::cout << "Version: " << (root->Attribute("version") ? root->Attribute("version") : "N/A") << std::endl;
// Language
std::cout << "Language: " << (root->Attribute("language") ? root->Attribute("language") : "N/A") << std::endl;
// Display Name
std::cout << "Display Name: " << (root->Attribute("displayname") ? root->Attribute("displayname") : "N/A") << std::endl;
// ID-Based Translation
std::cout << "ID-Based Translation: " << (root->Attribute("idbasedtr") ? root->Attribute("idbasedtr") : "N/A") << std::endl;
// Connect Slots by Name
std::cout << "Connect Slots by Name: " << (root->Attribute("connectslotsbyname") ? root->Attribute("connectslotsbyname") : "N/A") << std::endl;
// Standard Set Default (Legacy)
std::cout << "stdsetdef: " << (root->Attribute("stdsetdef") ? root->Attribute("stdsetdef") : "N/A") << std::endl;
std::cout << "stdSetDef: " << (root->Attribute("stdSetDef") ? root->Attribute("stdSetDef") : "N/A") << std::endl;
// Author
std::cout << "Author: " << getTextContent(root, "author") << std::endl;
// Comment
std::cout << "Comment: " << getTextContent(root, "comment") << std::endl;
// Export Macro
std::cout << "Export Macro: " << getTextContent(root, "exportmacro") << std::endl;
// Class Name
std::cout << "Class Name: " << getTextContent(root, "class") << std::endl;
// Root Widget
XMLElement* widget = root->FirstChildElement("widget");
std::string widgetClass = widget ? (widget->Attribute("class") ? widget->Attribute("class") : "N/A") : "N/A";
std::string widgetName = widget ? (widget->Attribute("name") ? widget->Attribute("name") : "N/A") : "N/A";
std::cout << "Root Widget: Class - " << widgetClass << ", Name - " << widgetName << std::endl;
// Layout Default
XMLElement* layoutDefault = root->FirstChildElement("layoutdefault");
std::string spacing = layoutDefault ? (layoutDefault->Attribute("spacing") ? layoutDefault->Attribute("spacing") : "N/A") : "N/A";
std::string margin = layoutDefault ? (layoutDefault->Attribute("margin") ? layoutDefault->Attribute("margin") : "N/A") : "N/A";
std::cout << "Layout Default: Spacing - " << spacing << ", Margin - " << margin << std::endl;
// Layout Function
XMLElement* layoutFunction = root->FirstChildElement("layoutfunction");
std::string funcSpacing = layoutFunction ? (layoutFunction->Attribute("spacing") ? layoutFunction->Attribute("spacing") : "N/A") : "N/A";
std::string funcMargin = layoutFunction ? (layoutFunction->Attribute("margin") ? layoutFunction->Attribute("margin") : "N/A") : "N/A";
std::cout << "Layout Function: Spacing - " << funcSpacing << ", Margin - " << funcMargin << std::endl;
// Pixmap Function
std::cout << "Pixmap Function: " << getTextContent(root, "pixmapfunction") << std::endl;
// Custom Widgets
std::cout << "Custom Widgets:" << std::endl;
XMLElement* customWidgets = root->FirstChildElement("customwidgets");
if (customWidgets) {
XMLElement* cw = customWidgets->FirstChildElement("customwidget");
int i = 1;
while (cw) {
std::cout << " " << i << ". Class: " << getTextContent(cw, "class") << ", Extends: " << getTextContent(cw, "extends") << std::endl;
cw = cw->NextSiblingElement("customwidget");
i++;
}
} else {
std::cout << " N/A" << std::endl;
}
// Tab Stops
std::cout << "Tab Stops:" << std::endl;
XMLElement* tabStops = root->FirstChildElement("tabstops");
if (tabStops) {
XMLElement* ts = tabStops->FirstChildElement("tabstop");
int i = 1;
while (ts) {
std::cout << " " << i << ". " << (ts->GetText() ? ts->GetText() : "N/A") << std::endl;
ts = ts->NextSiblingElement("tabstop");
i++;
}
} else {
std::cout << " N/A" << std::endl;
}
// Includes
std::cout << "Includes:" << std::endl;
XMLElement* includes = root->FirstChildElement("includes");
if (includes) {
XMLElement* inc = includes->FirstChildElement("include");
int i = 1;
while (inc) {
std::cout << " " << i << ". Location: " << (inc->Attribute("location") ? inc->Attribute("location") : "N/A") << std::endl;
inc = inc->NextSiblingElement("include");
i++;
}
} else {
std::cout << " N/A" << std::endl;
}
// Resources
std::cout << "Resources:" << std::endl;
XMLElement* resources = root->FirstChildElement("resources");
if (resources) {
XMLElement* res = resources->FirstChildElement("include"); // Note: <include> under <resources>
int i = 1;
while (res) {
std::cout << " " << i << ". Location: " << (res->Attribute("location") ? res->Attribute("location") : "N/A") << std::endl;
res = res->NextSiblingElement("include");
i++;
}
} else {
std::cout << " N/A" << std::endl;
}
// Connections
std::cout << "Connections:" << std::endl;
XMLElement* connections = root->FirstChildElement("connections");
if (connections) {
XMLElement* conn = connections->FirstChildElement("connection");
int i = 1;
while (conn) {
std::cout << " " << i << ". Sender: " << getTextContent(conn, "sender") << ", Signal: " << getTextContent(conn, "signal")
<< ", Receiver: " << getTextContent(conn, "receiver") << ", Slot: " << getTextContent(conn, "slot") << std::endl;
conn = conn->NextSiblingElement("connection");
i++;
}
} else {
std::cout << " N/A" << std::endl;
}
// Designer Data
XMLElement* designerData = root->FirstChildElement("designerdata");
std::cout << "Designer Data: " << (designerData ? "Present" : "N/A") << std::endl;
// Slots
std::cout << "Slots:" << std::endl;
XMLElement* slotsElem = root->FirstChildElement("slots");
if (slotsElem) {
XMLElement* sig = slotsElem->FirstChildElement("signal");
int i = 1;
while (sig) {
std::cout << " Signal " << i << ": " << (sig->GetText() ? sig->GetText() : "N/A") << std::endl;
sig = sig->NextSiblingElement("signal");
i++;
}
XMLElement* slt = slotsElem->FirstChildElement("slot");
i = 1;
while (slt) {
std::cout << " Slot " << i << ": " << (slt->GetText() ? slt->GetText() : "N/A") << std::endl;
slt = slt->NextSiblingElement("slot");
i++;
}
} else {
std::cout << " N/A" << std::endl;
}
// Button Groups
std::cout << "Button Groups:" << std::endl;
XMLElement* buttonGroups = root->FirstChildElement("buttongroups");
if (buttonGroups) {
XMLElement* bg = buttonGroups->FirstChildElement("buttongroup");
int i = 1;
while (bg) {
std::cout << " " << i << ". Name: " << (bg->Attribute("name") ? bg->Attribute("name") : "N/A") << std::endl;
bg = bg->NextSiblingElement("buttongroup");
i++;
}
} else {
std::cout << " N/A" << std::endl;
}
}
std::string getTextContent(XMLElement* parent, const char* tag) {
XMLElement* elem = parent->FirstChildElement(tag);
return elem && elem->GetText() ? elem->GetText() : "N/A";
}
void write(const std::string& outputPath = "") {
std::string path = outputPath.empty() ? filepath : outputPath;
if (doc.SaveFile(path.c_str()) != XML_SUCCESS) {
std::cout << "Error writing file: " << doc.ErrorStr() << std::endl;
} else {
std::cout << "File written to " << path << std::endl;
}
}
};
// Example usage:
// int main() {
// UIFileHandler handler("example.ui");
// handler.printProperties();
// handler.write("modified.ui");
// return 0;
// }