diff --git a/CMakeLists.txt b/CMakeLists.txt
index 879b69d29a..70901a3ab5 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -48,18 +48,38 @@ if(FREECAD_USE_CCACHE)
endif()
endif()
-project(FreeCAD)
+project(KindredCreate)
-set(PACKAGE_VERSION_MAJOR "1")
-set(PACKAGE_VERSION_MINOR "2")
-set(PACKAGE_VERSION_PATCH "0") # number of patch release (e.g. "4" for the 0.18.4 release)
+# Kindred Create version
+set(KINDRED_CREATE_VERSION_MAJOR "0")
+set(KINDRED_CREATE_VERSION_MINOR "1")
+set(KINDRED_CREATE_VERSION_PATCH "0")
+set(KINDRED_CREATE_VERSION "${KINDRED_CREATE_VERSION_MAJOR}.${KINDRED_CREATE_VERSION_MINOR}.${KINDRED_CREATE_VERSION_PATCH}")
+
+# Underlying FreeCAD version
+set(FREECAD_VERSION_MAJOR "1")
+set(FREECAD_VERSION_MINOR "2")
+set(FREECAD_VERSION_PATCH "0")
+set(FREECAD_VERSION "${FREECAD_VERSION_MAJOR}.${FREECAD_VERSION_MINOR}.${FREECAD_VERSION_PATCH}")
+
+# Package version (used for build system compatibility)
+set(PACKAGE_VERSION_MAJOR ${KINDRED_CREATE_VERSION_MAJOR})
+set(PACKAGE_VERSION_MINOR ${KINDRED_CREATE_VERSION_MINOR})
+set(PACKAGE_VERSION_PATCH ${KINDRED_CREATE_VERSION_PATCH})
set(PACKAGE_VERSION_SUFFIX "dev") # either "dev" for development snapshot or "" (empty string)
-set(PACKAGE_BUILD_VERSION "0") # used when the same FreeCAD version will be re-released (for example using an updated LibPack)
+set(PACKAGE_BUILD_VERSION "0") # used when the same version will be re-released
string(TIMESTAMP PACKAGE_COPYRIGHT_YEAR "%Y")
set(PACKAGE_VERSION "${PACKAGE_VERSION_MAJOR}.${PACKAGE_VERSION_MINOR}.${PACKAGE_VERSION_PATCH}")
set(PACKAGE_STRING "${PROJECT_NAME} ${PACKAGE_VERSION}")
+# Pass Kindred Create version to compiler
+add_definitions(-DKINDRED_CREATE_VERSION="${KINDRED_CREATE_VERSION}")
+add_definitions(-DKINDRED_CREATE_VERSION_MAJOR=${KINDRED_CREATE_VERSION_MAJOR})
+add_definitions(-DKINDRED_CREATE_VERSION_MINOR=${KINDRED_CREATE_VERSION_MINOR})
+add_definitions(-DKINDRED_CREATE_VERSION_PATCH=${KINDRED_CREATE_VERSION_PATCH})
+add_definitions(-DFREECAD_VERSION="${FREECAD_VERSION}")
+
# include local modules
include(CheckCXXCompilerFlag)
include(AddFileDependencies)
diff --git a/kindred-logo.svg b/kindred-logo.svg
new file mode 100644
index 0000000000..64d4ea8d9a
--- /dev/null
+++ b/kindred-logo.svg
@@ -0,0 +1,106 @@
+
+
+
+
diff --git a/resources/branding/generate-icons.sh b/resources/branding/generate-icons.sh
new file mode 100755
index 0000000000..ce8a2937bb
--- /dev/null
+++ b/resources/branding/generate-icons.sh
@@ -0,0 +1,98 @@
+#!/bin/bash
+# generate-icons.sh - Generate application icons for Kindred Create
+#
+# This script generates icon files for all platforms from the source SVG.
+# Prerequisites:
+# - Inkscape (SVG to PNG conversion)
+# - ImageMagick (ICO generation for Windows)
+# - png2icns or iconutil (ICNS generation for macOS)
+#
+# Usage: ./generate-icons.sh
+
+set -e
+
+SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
+SVG_SOURCE="$SCRIPT_DIR/kindred-logo.svg"
+OUTPUT_DIR="$SCRIPT_DIR/../icons"
+
+# Check for source file
+if [ ! -f "$SVG_SOURCE" ]; then
+ echo "Error: Source SVG not found at $SVG_SOURCE"
+ echo "Please place kindred-logo.svg in the branding directory."
+ exit 1
+fi
+
+# Check for Inkscape
+if ! command -v inkscape &> /dev/null; then
+ echo "Error: Inkscape is required but not installed."
+ echo "Install with: sudo apt install inkscape (Debian/Ubuntu)"
+ exit 1
+fi
+
+echo "Generating icons from $SVG_SOURCE..."
+
+# Generate PNGs for Linux/hicolor icon theme
+for size in 16 24 32 48 64 128 256 512; do
+ dir="$OUTPUT_DIR/hicolor/${size}x${size}/apps"
+ mkdir -p "$dir"
+ echo " Generating ${size}x${size} PNG..."
+ inkscape -w $size -h $size "$SVG_SOURCE" -o "$dir/kindred-create.png" 2>/dev/null
+done
+
+# Copy SVG for scalable
+mkdir -p "$OUTPUT_DIR/hicolor/scalable/apps"
+cp "$SVG_SOURCE" "$OUTPUT_DIR/hicolor/scalable/apps/kindred-create.svg"
+echo " Copied scalable SVG"
+
+# Generate Windows ICO (requires ImageMagick)
+if command -v convert &> /dev/null; then
+ echo " Generating Windows ICO..."
+ convert \
+ "$OUTPUT_DIR/hicolor/16x16/apps/kindred-create.png" \
+ "$OUTPUT_DIR/hicolor/24x24/apps/kindred-create.png" \
+ "$OUTPUT_DIR/hicolor/32x32/apps/kindred-create.png" \
+ "$OUTPUT_DIR/hicolor/48x48/apps/kindred-create.png" \
+ "$OUTPUT_DIR/hicolor/64x64/apps/kindred-create.png" \
+ "$OUTPUT_DIR/hicolor/128x128/apps/kindred-create.png" \
+ "$OUTPUT_DIR/hicolor/256x256/apps/kindred-create.png" \
+ "$OUTPUT_DIR/kindred-create.ico"
+ echo " Created kindred-create.ico"
+else
+ echo " Warning: ImageMagick not found, skipping ICO generation."
+ echo " Install with: sudo apt install imagemagick"
+fi
+
+# Generate macOS ICNS (requires png2icns or iconutil)
+if command -v png2icns &> /dev/null; then
+ echo " Generating macOS ICNS..."
+ png2icns "$OUTPUT_DIR/kindred-create.icns" \
+ "$OUTPUT_DIR/hicolor/16x16/apps/kindred-create.png" \
+ "$OUTPUT_DIR/hicolor/32x32/apps/kindred-create.png" \
+ "$OUTPUT_DIR/hicolor/128x128/apps/kindred-create.png" \
+ "$OUTPUT_DIR/hicolor/256x256/apps/kindred-create.png" \
+ "$OUTPUT_DIR/hicolor/512x512/apps/kindred-create.png"
+ echo " Created kindred-create.icns"
+elif command -v iconutil &> /dev/null; then
+ echo " Generating macOS ICNS using iconutil..."
+ ICONSET_DIR="$OUTPUT_DIR/kindred-create.iconset"
+ mkdir -p "$ICONSET_DIR"
+ cp "$OUTPUT_DIR/hicolor/16x16/apps/kindred-create.png" "$ICONSET_DIR/icon_16x16.png"
+ cp "$OUTPUT_DIR/hicolor/32x32/apps/kindred-create.png" "$ICONSET_DIR/icon_16x16@2x.png"
+ cp "$OUTPUT_DIR/hicolor/32x32/apps/kindred-create.png" "$ICONSET_DIR/icon_32x32.png"
+ cp "$OUTPUT_DIR/hicolor/64x64/apps/kindred-create.png" "$ICONSET_DIR/icon_32x32@2x.png"
+ cp "$OUTPUT_DIR/hicolor/128x128/apps/kindred-create.png" "$ICONSET_DIR/icon_128x128.png"
+ cp "$OUTPUT_DIR/hicolor/256x256/apps/kindred-create.png" "$ICONSET_DIR/icon_128x128@2x.png"
+ cp "$OUTPUT_DIR/hicolor/256x256/apps/kindred-create.png" "$ICONSET_DIR/icon_256x256.png"
+ cp "$OUTPUT_DIR/hicolor/512x512/apps/kindred-create.png" "$ICONSET_DIR/icon_256x256@2x.png"
+ cp "$OUTPUT_DIR/hicolor/512x512/apps/kindred-create.png" "$ICONSET_DIR/icon_512x512.png"
+ iconutil -c icns "$ICONSET_DIR" -o "$OUTPUT_DIR/kindred-create.icns"
+ rm -rf "$ICONSET_DIR"
+ echo " Created kindred-create.icns"
+else
+ echo " Warning: Neither png2icns nor iconutil found, skipping ICNS generation."
+ echo " Install png2icns with: sudo apt install icnsutils"
+fi
+
+echo ""
+echo "Icon generation complete!"
+echo "Output directory: $OUTPUT_DIR"
diff --git a/resources/branding/generate-splash.py b/resources/branding/generate-splash.py
new file mode 100755
index 0000000000..7df5e67109
--- /dev/null
+++ b/resources/branding/generate-splash.py
@@ -0,0 +1,214 @@
+#!/usr/bin/env python3
+"""
+Generate Kindred Create splash screen and about images.
+
+This script creates branded splash screens with:
+- Rounded dark rectangle background (Catppuccin Mocha base #1e1e2e)
+- Kindred logo centered
+- "Kindred Create" title text
+- Version string
+
+Requirements:
+ pip install Pillow cairosvg
+
+Usage:
+ python generate-splash.py [--version VERSION] [--freecad-version FREECAD_VERSION]
+"""
+
+import argparse
+import os
+import sys
+from pathlib import Path
+
+try:
+ from PIL import Image, ImageDraw, ImageFont
+except ImportError:
+ print("Error: Pillow is required. Install with: pip install Pillow")
+ sys.exit(1)
+
+try:
+ import cairosvg
+except ImportError:
+ print("Warning: cairosvg not found. Will try alternative SVG conversion.")
+ cairosvg = None
+
+# Catppuccin Mocha colors
+COLORS = {
+ 'base': '#1e1e2e',
+ 'surface0': '#313244',
+ 'text': '#cdd6f4',
+ 'subtext0': '#a6adc8',
+ 'blue': '#89b4fa',
+ 'lavender': '#b4befe',
+}
+
+def hex_to_rgb(hex_color):
+ """Convert hex color to RGB tuple."""
+ hex_color = hex_color.lstrip('#')
+ return tuple(int(hex_color[i:i+2], 16) for i in (0, 2, 4))
+
+def create_rounded_rectangle(draw, bbox, radius, fill):
+ """Draw a rounded rectangle."""
+ x1, y1, x2, y2 = bbox
+ draw.rounded_rectangle(bbox, radius=radius, fill=fill)
+
+def load_svg_as_image(svg_path, width, height):
+ """Load an SVG file and convert to PIL Image at specified size."""
+ if cairosvg:
+ import io
+ png_data = cairosvg.svg2png(url=str(svg_path), output_width=width, output_height=height)
+ return Image.open(io.BytesIO(png_data)).convert('RGBA')
+ else:
+ # Fallback: try using inkscape command line
+ import subprocess
+ import tempfile
+ with tempfile.NamedTemporaryFile(suffix='.png', delete=False) as tmp:
+ tmp_path = tmp.name
+ try:
+ subprocess.run([
+ 'inkscape', '-w', str(width), '-h', str(height),
+ str(svg_path), '-o', tmp_path
+ ], check=True, capture_output=True)
+ img = Image.open(tmp_path).convert('RGBA')
+ return img
+ finally:
+ if os.path.exists(tmp_path):
+ os.unlink(tmp_path)
+
+def get_font(size, bold=False):
+ """Get a font, falling back to default if not available."""
+ font_names = [
+ '/usr/share/fonts/truetype/dejavu/DejaVuSans-Bold.ttf' if bold else '/usr/share/fonts/truetype/dejavu/DejaVuSans.ttf',
+ '/usr/share/fonts/truetype/liberation/LiberationSans-Bold.ttf' if bold else '/usr/share/fonts/truetype/liberation/LiberationSans-Regular.ttf',
+ '/usr/share/fonts/TTF/DejaVuSans-Bold.ttf' if bold else '/usr/share/fonts/TTF/DejaVuSans.ttf',
+ ]
+ for font_name in font_names:
+ if os.path.exists(font_name):
+ return ImageFont.truetype(font_name, size)
+ # Fallback to default
+ return ImageFont.load_default()
+
+def create_splash(output_path, logo_path, width, height, version, freecad_version, scale=1):
+ """Create a splash screen image."""
+ # Scale dimensions
+ w = int(width * scale)
+ h = int(height * scale)
+ radius = int(16 * scale)
+ padding = int(30 * scale)
+
+ # Create image with transparent background
+ img = Image.new('RGBA', (w, h), (0, 0, 0, 0))
+ draw = ImageDraw.Draw(img)
+
+ # Draw rounded rectangle background
+ bg_color = hex_to_rgb(COLORS['base'])
+ create_rounded_rectangle(draw, (padding, padding, w - padding, h - padding), radius, bg_color)
+
+ # Load and place logo
+ logo_max_width = int(300 * scale)
+ logo_max_height = int(150 * scale)
+
+ try:
+ logo = load_svg_as_image(logo_path, logo_max_width, logo_max_height)
+ # Center logo horizontally, place in upper portion
+ logo_x = (w - logo.width) // 2
+ logo_y = int(80 * scale)
+ img.paste(logo, (logo_x, logo_y), logo)
+ except Exception as e:
+ print(f"Warning: Could not load logo: {e}")
+ logo_y = int(80 * scale)
+
+ # Draw "Kindred Create" title
+ title_font = get_font(int(24 * scale), bold=True)
+ title = "Kindred Create"
+ title_bbox = draw.textbbox((0, 0), title, font=title_font)
+ title_width = title_bbox[2] - title_bbox[0]
+ title_x = (w - title_width) // 2
+ title_y = int(250 * scale)
+ draw.text((title_x, title_y), title, fill=hex_to_rgb(COLORS['text']), font=title_font)
+
+ # Draw version string
+ version_font = get_font(int(12 * scale))
+ version_str = f"v{version} (FreeCAD {freecad_version})"
+ version_bbox = draw.textbbox((0, 0), version_str, font=version_font)
+ version_width = version_bbox[2] - version_bbox[0]
+ version_x = (w - version_width) // 2
+ version_y = title_y + int(35 * scale)
+ draw.text((version_x, version_y), version_str, fill=hex_to_rgb(COLORS['subtext0']), font=version_font)
+
+ # Save
+ img.save(output_path, 'PNG')
+ print(f"Created: {output_path}")
+
+def create_about(output_path, logo_path, width, height, scale=1):
+ """Create an about dialog image."""
+ # Scale dimensions
+ w = int(width * scale)
+ h = int(height * scale)
+
+ # Create image
+ img = Image.new('RGBA', (w, h), hex_to_rgb(COLORS['base']) + (255,))
+ draw = ImageDraw.Draw(img)
+
+ # Load and place logo
+ logo_max_width = int(200 * scale)
+ logo_max_height = int(100 * scale)
+
+ try:
+ logo = load_svg_as_image(logo_path, logo_max_width, logo_max_height)
+ logo_x = (w - logo.width) // 2
+ logo_y = int(30 * scale)
+ img.paste(logo, (logo_x, logo_y), logo)
+ except Exception as e:
+ print(f"Warning: Could not load logo: {e}")
+
+ # Save
+ img.save(output_path, 'PNG')
+ print(f"Created: {output_path}")
+
+def main():
+ parser = argparse.ArgumentParser(description='Generate Kindred Create splash screens')
+ parser.add_argument('--version', default='0.1.0', help='Kindred Create version')
+ parser.add_argument('--freecad-version', default='1.0.0', help='FreeCAD version')
+ args = parser.parse_args()
+
+ script_dir = Path(__file__).parent
+ logo_path = script_dir / 'kindred-logo.svg'
+ icons_dir = script_dir.parent.parent / 'src' / 'Gui' / 'Icons'
+
+ if not logo_path.exists():
+ print(f"Error: Logo not found at {logo_path}")
+ sys.exit(1)
+
+ # Create splash screens (600x400 as per spec)
+ create_splash(
+ icons_dir / 'kindredcreatesplash.png',
+ logo_path,
+ 600, 400,
+ args.version,
+ args.freecad_version,
+ scale=1
+ )
+
+ # Create 2x version for HiDPI
+ create_splash(
+ icons_dir / 'kindredcreatesplash_2x.png',
+ logo_path,
+ 600, 400,
+ args.version,
+ args.freecad_version,
+ scale=2
+ )
+
+ # Create about image
+ create_about(
+ icons_dir / 'kindredcreateabout.png',
+ logo_path,
+ 400, 200,
+ scale=1
+ )
+
+ print("\nSplash screen generation complete!")
+
+if __name__ == '__main__':
+ main()
diff --git a/resources/branding/kindred-logo.svg b/resources/branding/kindred-logo.svg
new file mode 100644
index 0000000000..64d4ea8d9a
--- /dev/null
+++ b/resources/branding/kindred-logo.svg
@@ -0,0 +1,106 @@
+
+
+
+
diff --git a/resources/icons/hicolor/128x128/apps/kindred-create.png b/resources/icons/hicolor/128x128/apps/kindred-create.png
new file mode 100644
index 0000000000..a80ca78828
Binary files /dev/null and b/resources/icons/hicolor/128x128/apps/kindred-create.png differ
diff --git a/resources/icons/hicolor/16x16/apps/kindred-create.png b/resources/icons/hicolor/16x16/apps/kindred-create.png
new file mode 100644
index 0000000000..aa20ea7c30
Binary files /dev/null and b/resources/icons/hicolor/16x16/apps/kindred-create.png differ
diff --git a/resources/icons/hicolor/24x24/apps/kindred-create.png b/resources/icons/hicolor/24x24/apps/kindred-create.png
new file mode 100644
index 0000000000..e353d527c5
Binary files /dev/null and b/resources/icons/hicolor/24x24/apps/kindred-create.png differ
diff --git a/resources/icons/hicolor/256x256/apps/kindred-create.png b/resources/icons/hicolor/256x256/apps/kindred-create.png
new file mode 100644
index 0000000000..dc45e5090c
Binary files /dev/null and b/resources/icons/hicolor/256x256/apps/kindred-create.png differ
diff --git a/resources/icons/hicolor/32x32/apps/kindred-create.png b/resources/icons/hicolor/32x32/apps/kindred-create.png
new file mode 100644
index 0000000000..852acb2719
Binary files /dev/null and b/resources/icons/hicolor/32x32/apps/kindred-create.png differ
diff --git a/resources/icons/hicolor/48x48/apps/kindred-create.png b/resources/icons/hicolor/48x48/apps/kindred-create.png
new file mode 100644
index 0000000000..5151c6602a
Binary files /dev/null and b/resources/icons/hicolor/48x48/apps/kindred-create.png differ
diff --git a/resources/icons/hicolor/512x512/apps/kindred-create.png b/resources/icons/hicolor/512x512/apps/kindred-create.png
new file mode 100644
index 0000000000..8769c584cc
Binary files /dev/null and b/resources/icons/hicolor/512x512/apps/kindred-create.png differ
diff --git a/resources/icons/hicolor/64x64/apps/kindred-create.png b/resources/icons/hicolor/64x64/apps/kindred-create.png
new file mode 100644
index 0000000000..9ee90de051
Binary files /dev/null and b/resources/icons/hicolor/64x64/apps/kindred-create.png differ
diff --git a/resources/icons/hicolor/scalable/apps/kindred-create.svg b/resources/icons/hicolor/scalable/apps/kindred-create.svg
new file mode 100644
index 0000000000..64d4ea8d9a
--- /dev/null
+++ b/resources/icons/hicolor/scalable/apps/kindred-create.svg
@@ -0,0 +1,106 @@
+
+
+
+
diff --git a/resources/icons/kindred-create.icns b/resources/icons/kindred-create.icns
new file mode 100644
index 0000000000..0f544abcbc
Binary files /dev/null and b/resources/icons/kindred-create.icns differ
diff --git a/resources/icons/kindred-create.ico b/resources/icons/kindred-create.ico
new file mode 100644
index 0000000000..d8df13ebe7
Binary files /dev/null and b/resources/icons/kindred-create.ico differ
diff --git a/resources/preferences/KindredCreate/KindredCreate.cfg b/resources/preferences/KindredCreate/KindredCreate.cfg
new file mode 100644
index 0000000000..5714f860f7
--- /dev/null
+++ b/resources/preferences/KindredCreate/KindredCreate.cfg
@@ -0,0 +1,109 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ KindredCreate.qss
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/resources/preferences/KindredCreate/KindredCreate.qss b/resources/preferences/KindredCreate/KindredCreate.qss
new file mode 100644
index 0000000000..6ce5343d31
--- /dev/null
+++ b/resources/preferences/KindredCreate/KindredCreate.qss
@@ -0,0 +1,1229 @@
+
+/* =============================================================================
+ Catppuccin Mocha Theme for FreeCAD
+ Bundled with ztools addon
+ https://catppuccin.com/
+ ============================================================================= */
+
+/* =============================================================================
+ Global Defaults
+ ============================================================================= */
+
+* {
+ color: #cdd6f4;
+ font-family: "Segoe UI", "Ubuntu", "Noto Sans", sans-serif;
+}
+
+QWidget {
+ background-color: #1e1e2e;
+ color: #cdd6f4;
+ selection-background-color: #585b70;
+ selection-color: #cdd6f4;
+}
+
+/* =============================================================================
+ Main Window and MDI Area
+ ============================================================================= */
+
+QMainWindow {
+ background-color: #181825;
+}
+
+QMainWindow::separator {
+ background-color: #313244;
+ width: 4px;
+ height: 4px;
+}
+
+QMainWindow::separator:hover {
+ background-color: #cba6f7;
+}
+
+QMdiArea {
+ background-color: #11111b;
+}
+
+QMdiSubWindow {
+ background-color: #1e1e2e;
+ border: 1px solid #45475a;
+}
+
+QMdiSubWindow > QWidget {
+ background-color: #1e1e2e;
+}
+
+/* =============================================================================
+ Menu Bar
+ ============================================================================= */
+
+QMenuBar {
+ background-color: #181825;
+ color: #cdd6f4;
+ border-bottom: 1px solid #313244;
+ padding: 2px;
+}
+
+QMenuBar::item {
+ background-color: transparent;
+ padding: 4px 8px;
+ border-radius: 4px;
+}
+
+QMenuBar::item:selected {
+ background-color: #313244;
+}
+
+QMenuBar::item:pressed {
+ background-color: #45475a;
+}
+
+/* =============================================================================
+ Menus
+ ============================================================================= */
+
+QMenu {
+ background-color: #313244;
+ color: #cdd6f4;
+ border: 1px solid #45475a;
+ border-radius: 6px;
+ padding: 4px;
+}
+
+QMenu::item {
+ padding: 6px 24px 6px 8px;
+ border-radius: 4px;
+}
+
+QMenu::item:selected {
+ background-color: #45475a;
+ color: #cdd6f4;
+}
+
+QMenu::item:disabled {
+ color: #6c7086;
+}
+
+QMenu::separator {
+ height: 1px;
+ background-color: #45475a;
+ margin: 4px 8px;
+}
+
+QMenu::icon {
+ margin-left: 8px;
+}
+
+QMenu::indicator {
+ width: 16px;
+ height: 16px;
+ margin-left: 4px;
+}
+
+/* =============================================================================
+ Toolbars
+ ============================================================================= */
+
+QToolBar {
+ background-color: #181825;
+ border: none;
+ spacing: 2px;
+ padding: 2px;
+}
+
+QToolBar::handle {
+ background-color: #45475a;
+ width: 8px;
+ margin: 2px;
+ border-radius: 2px;
+}
+
+QToolBar::handle:horizontal {
+ width: 8px;
+}
+
+QToolBar::handle:vertical {
+ height: 8px;
+}
+
+QToolBar::separator {
+ background-color: #45475a;
+ width: 1px;
+ margin: 4px 2px;
+}
+
+/* =============================================================================
+ Tool Buttons (Toolbar icons)
+ ============================================================================= */
+
+QToolButton {
+ background-color: transparent;
+ border: 1px solid transparent;
+ border-radius: 4px;
+ padding: 4px;
+ margin: 1px;
+}
+
+QToolButton:hover {
+ background-color: #313244;
+ border: 1px solid #45475a;
+}
+
+QToolButton:pressed {
+ background-color: #45475a;
+}
+
+QToolButton:checked {
+ background-color: #45475a;
+ border: 1px solid #cba6f7;
+}
+
+QToolButton:disabled {
+ color: #6c7086;
+}
+
+QToolButton[popupMode="1"] {
+ padding-right: 16px;
+}
+
+QToolButton::menu-button {
+ border: none;
+ width: 14px;
+}
+
+QToolButton::menu-arrow {
+ width: 10px;
+ height: 10px;
+}
+
+/* =============================================================================
+ Push Buttons
+ ============================================================================= */
+
+QPushButton {
+ background-color: #313244;
+ color: #cdd6f4;
+ border: 1px solid #45475a;
+ border-radius: 6px;
+ padding: 6px 16px;
+ min-height: 20px;
+}
+
+QPushButton:hover {
+ background-color: #45475a;
+ border-color: #585b70;
+}
+
+QPushButton:pressed {
+ background-color: #585b70;
+}
+
+QPushButton:checked {
+ background-color: #cba6f7;
+ color: #11111b;
+ border-color: #cba6f7;
+}
+
+QPushButton:disabled {
+ background-color: #313244;
+ color: #6c7086;
+ border-color: #313244;
+}
+
+QPushButton:default {
+ border: 2px solid #cba6f7;
+}
+
+/* =============================================================================
+ Dock Widgets
+ ============================================================================= */
+
+QDockWidget {
+ background-color: #1e1e2e;
+ color: #cdd6f4;
+ titlebar-close-icon: none;
+ titlebar-normal-icon: none;
+}
+
+QDockWidget::title {
+ background-color: #181825;
+ color: #cdd6f4;
+ padding: 6px;
+ border-bottom: 1px solid #313244;
+}
+
+QDockWidget::close-button,
+QDockWidget::float-button {
+ background-color: transparent;
+ border: none;
+ padding: 2px;
+}
+
+QDockWidget::close-button:hover,
+QDockWidget::float-button:hover {
+ background-color: #313244;
+ border-radius: 4px;
+}
+
+/* =============================================================================
+ Tab Widgets
+ ============================================================================= */
+
+QTabWidget::pane {
+ background-color: #1e1e2e;
+ border: 1px solid #45475a;
+ border-radius: 4px;
+ top: -1px;
+}
+
+QTabBar {
+ background-color: transparent;
+}
+
+QTabBar::tab {
+ background-color: #313244;
+ color: #bac2de;
+ border: 1px solid #45475a;
+ padding: 6px 12px;
+ margin-right: 2px;
+ border-top-left-radius: 6px;
+ border-top-right-radius: 6px;
+}
+
+QTabBar::tab:selected {
+ background-color: #1e1e2e;
+ color: #cdd6f4;
+ border-bottom-color: #1e1e2e;
+}
+
+QTabBar::tab:hover:!selected {
+ background-color: #45475a;
+ color: #cdd6f4;
+}
+
+QTabBar::tab:disabled {
+ color: #6c7086;
+}
+
+QTabBar::close-button {
+ margin-left: 4px;
+}
+
+QTabBar::close-button:hover {
+ background-color: #f38ba8;
+ border-radius: 2px;
+}
+
+/* =============================================================================
+ Scroll Bars
+ ============================================================================= */
+
+QScrollBar:horizontal {
+ background-color: #181825;
+ height: 12px;
+ margin: 0 12px 0 12px;
+ border-radius: 6px;
+}
+
+QScrollBar:vertical {
+ background-color: #181825;
+ width: 12px;
+ margin: 12px 0 12px 0;
+ border-radius: 6px;
+}
+
+QScrollBar::handle:horizontal {
+ background-color: #45475a;
+ min-width: 20px;
+ border-radius: 5px;
+ margin: 1px;
+}
+
+QScrollBar::handle:vertical {
+ background-color: #45475a;
+ min-height: 20px;
+ border-radius: 5px;
+ margin: 1px;
+}
+
+QScrollBar::handle:horizontal:hover,
+QScrollBar::handle:vertical:hover {
+ background-color: #585b70;
+}
+
+QScrollBar::add-line:horizontal,
+QScrollBar::sub-line:horizontal,
+QScrollBar::add-line:vertical,
+QScrollBar::sub-line:vertical {
+ width: 12px;
+ height: 12px;
+ background-color: #313244;
+ border-radius: 6px;
+}
+
+QScrollBar::add-line:horizontal:hover,
+QScrollBar::sub-line:horizontal:hover,
+QScrollBar::add-line:vertical:hover,
+QScrollBar::sub-line:vertical:hover {
+ background-color: #45475a;
+}
+
+QScrollBar::add-page:horizontal,
+QScrollBar::sub-page:horizontal,
+QScrollBar::add-page:vertical,
+QScrollBar::sub-page:vertical {
+ background-color: transparent;
+}
+
+/* =============================================================================
+ Input Fields
+ ============================================================================= */
+
+QLineEdit {
+ background-color: #313244;
+ color: #cdd6f4;
+ border: 1px solid #45475a;
+ border-radius: 4px;
+ padding: 4px 8px;
+ selection-background-color: #cba6f7;
+ selection-color: #11111b;
+}
+
+QLineEdit:focus {
+ border-color: #cba6f7;
+}
+
+QLineEdit:disabled {
+ background-color: #181825;
+ color: #6c7086;
+}
+
+QLineEdit:read-only {
+ background-color: #181825;
+}
+
+QTextEdit, QPlainTextEdit {
+ background-color: #313244;
+ color: #cdd6f4;
+ border: 1px solid #45475a;
+ border-radius: 4px;
+ selection-background-color: #cba6f7;
+ selection-color: #11111b;
+}
+
+QTextEdit:focus, QPlainTextEdit:focus {
+ border-color: #cba6f7;
+}
+
+/* =============================================================================
+ Spin Boxes
+ ============================================================================= */
+
+QSpinBox, QDoubleSpinBox {
+ background-color: #313244;
+ color: #cdd6f4;
+ border: 1px solid #45475a;
+ border-radius: 4px;
+ padding: 4px;
+ padding-right: 20px;
+}
+
+QSpinBox:focus, QDoubleSpinBox:focus {
+ border-color: #cba6f7;
+}
+
+QSpinBox:disabled, QDoubleSpinBox:disabled {
+ background-color: #181825;
+ color: #6c7086;
+}
+
+QSpinBox::up-button, QDoubleSpinBox::up-button {
+ subcontrol-origin: border;
+ subcontrol-position: top right;
+ width: 16px;
+ border-left: 1px solid #45475a;
+ border-top-right-radius: 4px;
+ background-color: #45475a;
+}
+
+QSpinBox::down-button, QDoubleSpinBox::down-button {
+ subcontrol-origin: border;
+ subcontrol-position: bottom right;
+ width: 16px;
+ border-left: 1px solid #45475a;
+ border-bottom-right-radius: 4px;
+ background-color: #45475a;
+}
+
+QSpinBox::up-button:hover, QDoubleSpinBox::up-button:hover,
+QSpinBox::down-button:hover, QDoubleSpinBox::down-button:hover {
+ background-color: #585b70;
+}
+
+QSpinBox::up-button:pressed, QDoubleSpinBox::up-button:pressed,
+QSpinBox::down-button:pressed, QDoubleSpinBox::down-button:pressed {
+ background-color: #cba6f7;
+}
+
+QSpinBox::up-arrow, QDoubleSpinBox::up-arrow {
+ width: 8px;
+ height: 8px;
+}
+
+QSpinBox::down-arrow, QDoubleSpinBox::down-arrow {
+ width: 8px;
+ height: 8px;
+}
+
+/* =============================================================================
+ Combo Boxes
+ ============================================================================= */
+
+QComboBox {
+ background-color: #313244;
+ color: #cdd6f4;
+ border: 1px solid #45475a;
+ border-radius: 4px;
+ padding: 4px 8px;
+ padding-right: 24px;
+ min-height: 20px;
+}
+
+QComboBox:hover {
+ border-color: #585b70;
+}
+
+QComboBox:focus {
+ border-color: #cba6f7;
+}
+
+QComboBox:disabled {
+ background-color: #181825;
+ color: #6c7086;
+}
+
+QComboBox::drop-down {
+ subcontrol-origin: padding;
+ subcontrol-position: top right;
+ width: 20px;
+ border-left: 1px solid #45475a;
+ border-top-right-radius: 4px;
+ border-bottom-right-radius: 4px;
+ background-color: #45475a;
+}
+
+QComboBox::drop-down:hover {
+ background-color: #585b70;
+}
+
+QComboBox::down-arrow {
+ width: 10px;
+ height: 10px;
+}
+
+QComboBox QAbstractItemView {
+ background-color: #313244;
+ color: #cdd6f4;
+ border: 1px solid #45475a;
+ border-radius: 4px;
+ selection-background-color: #45475a;
+ selection-color: #cdd6f4;
+ outline: none;
+}
+
+QComboBox QAbstractItemView::item {
+ padding: 4px 8px;
+ min-height: 24px;
+}
+
+QComboBox QAbstractItemView::item:hover {
+ background-color: #45475a;
+}
+
+QComboBox QAbstractItemView::item:selected {
+ background-color: #585b70;
+}
+
+/* =============================================================================
+ Check Boxes
+ ============================================================================= */
+
+QCheckBox {
+ spacing: 8px;
+ color: #cdd6f4;
+}
+
+QCheckBox:disabled {
+ color: #6c7086;
+}
+
+QCheckBox::indicator {
+ width: 18px;
+ height: 18px;
+ border: 2px solid #585b70;
+ border-radius: 4px;
+ background-color: #313244;
+}
+
+QCheckBox::indicator:hover {
+ border-color: #cba6f7;
+}
+
+QCheckBox::indicator:checked {
+ background-color: #cba6f7;
+ border-color: #cba6f7;
+}
+
+QCheckBox::indicator:checked:disabled {
+ background-color: #6c7086;
+ border-color: #6c7086;
+}
+
+QCheckBox::indicator:disabled {
+ background-color: #181825;
+ border-color: #45475a;
+}
+
+/* =============================================================================
+ Radio Buttons
+ ============================================================================= */
+
+QRadioButton {
+ spacing: 8px;
+ color: #cdd6f4;
+}
+
+QRadioButton:disabled {
+ color: #6c7086;
+}
+
+QRadioButton::indicator {
+ width: 18px;
+ height: 18px;
+ border: 2px solid #585b70;
+ border-radius: 9px;
+ background-color: #313244;
+}
+
+QRadioButton::indicator:hover {
+ border-color: #cba6f7;
+}
+
+QRadioButton::indicator:checked {
+ background-color: #cba6f7;
+ border-color: #cba6f7;
+}
+
+QRadioButton::indicator:checked:disabled {
+ background-color: #6c7086;
+ border-color: #6c7086;
+}
+
+QRadioButton::indicator:disabled {
+ background-color: #181825;
+ border-color: #45475a;
+}
+
+/* =============================================================================
+ Sliders
+ ============================================================================= */
+
+QSlider::groove:horizontal {
+ height: 6px;
+ background-color: #45475a;
+ border-radius: 3px;
+}
+
+QSlider::groove:vertical {
+ width: 6px;
+ background-color: #45475a;
+ border-radius: 3px;
+}
+
+QSlider::handle:horizontal {
+ width: 16px;
+ height: 16px;
+ margin: -5px 0;
+ background-color: #cba6f7;
+ border-radius: 8px;
+}
+
+QSlider::handle:vertical {
+ width: 16px;
+ height: 16px;
+ margin: 0 -5px;
+ background-color: #cba6f7;
+ border-radius: 8px;
+}
+
+QSlider::handle:horizontal:hover,
+QSlider::handle:vertical:hover {
+ background-color: #b4befe;
+}
+
+QSlider::handle:horizontal:pressed,
+QSlider::handle:vertical:pressed {
+ background-color: #f5c2e7;
+}
+
+QSlider::sub-page:horizontal {
+ background-color: #cba6f7;
+ border-radius: 3px;
+}
+
+QSlider::add-page:vertical {
+ background-color: #cba6f7;
+ border-radius: 3px;
+}
+
+/* =============================================================================
+ Progress Bars
+ ============================================================================= */
+
+QProgressBar {
+ background-color: #313244;
+ color: #cdd6f4;
+ border: 1px solid #45475a;
+ border-radius: 4px;
+ text-align: center;
+ height: 20px;
+}
+
+QProgressBar::chunk {
+ background-color: #cba6f7;
+ border-radius: 3px;
+}
+
+/* =============================================================================
+ Group Boxes
+ ============================================================================= */
+
+QGroupBox {
+ background-color: #1e1e2e;
+ border: 1px solid #45475a;
+ border-radius: 6px;
+ margin-top: 12px;
+ padding-top: 8px;
+}
+
+QGroupBox::title {
+ subcontrol-origin: margin;
+ subcontrol-position: top left;
+ left: 12px;
+ padding: 0 4px;
+ color: #bac2de;
+ background-color: #1e1e2e;
+}
+
+/* =============================================================================
+ Tree View
+ ============================================================================= */
+
+QTreeView {
+ background-color: #1e1e2e;
+ color: #cdd6f4;
+ border: 1px solid #45475a;
+ border-radius: 4px;
+ outline: none;
+ show-decoration-selected: 1;
+}
+
+QTreeView::item {
+ padding: 4px;
+ border-radius: 2px;
+}
+
+QTreeView::item:hover {
+ background-color: #313244;
+}
+
+QTreeView::item:selected {
+ background-color: #45475a;
+ color: #cdd6f4;
+}
+
+QTreeView::item:selected:active {
+ background-color: #585b70;
+}
+
+QTreeView::branch {
+ background-color: transparent;
+}
+
+QTreeView::branch:hover {
+ background-color: #313244;
+}
+
+QTreeView::branch:selected {
+ background-color: #45475a;
+}
+
+/* =============================================================================
+ List View
+ ============================================================================= */
+
+QListView {
+ background-color: #1e1e2e;
+ color: #cdd6f4;
+ border: 1px solid #45475a;
+ border-radius: 4px;
+ outline: none;
+}
+
+QListView::item {
+ padding: 4px;
+ border-radius: 2px;
+}
+
+QListView::item:hover {
+ background-color: #313244;
+}
+
+QListView::item:selected {
+ background-color: #45475a;
+ color: #cdd6f4;
+}
+
+/* =============================================================================
+ Table View
+ ============================================================================= */
+
+QTableView {
+ background-color: #1e1e2e;
+ color: #cdd6f4;
+ border: 1px solid #45475a;
+ border-radius: 4px;
+ gridline-color: #313244;
+ outline: none;
+}
+
+QTableView::item {
+ padding: 4px;
+}
+
+QTableView::item:hover {
+ background-color: #313244;
+}
+
+QTableView::item:selected {
+ background-color: #45475a;
+ color: #cdd6f4;
+}
+
+QTableView QTableCornerButton::section {
+ background-color: #313244;
+ border: 1px solid #45475a;
+}
+
+/* =============================================================================
+ Header Views (for Tables/Trees)
+ ============================================================================= */
+
+QHeaderView {
+ background-color: #313244;
+ border: none;
+}
+
+QHeaderView::section {
+ background-color: #313244;
+ color: #bac2de;
+ border: none;
+ border-right: 1px solid #45475a;
+ border-bottom: 1px solid #45475a;
+ padding: 6px 8px;
+}
+
+QHeaderView::section:hover {
+ background-color: #45475a;
+ color: #cdd6f4;
+}
+
+QHeaderView::section:checked {
+ background-color: #45475a;
+}
+
+QHeaderView::down-arrow {
+ width: 10px;
+ height: 10px;
+}
+
+QHeaderView::up-arrow {
+ width: 10px;
+ height: 10px;
+}
+
+/* =============================================================================
+ Splitters
+ ============================================================================= */
+
+QSplitter::handle {
+ background-color: #313244;
+}
+
+QSplitter::handle:horizontal {
+ width: 4px;
+}
+
+QSplitter::handle:vertical {
+ height: 4px;
+}
+
+QSplitter::handle:hover {
+ background-color: #cba6f7;
+}
+
+/* =============================================================================
+ Status Bar
+ ============================================================================= */
+
+QStatusBar {
+ background-color: #181825;
+ color: #bac2de;
+ border-top: 1px solid #313244;
+}
+
+QStatusBar::item {
+ border: none;
+}
+
+QStatusBar QLabel {
+ padding: 2px 8px;
+}
+
+/* =============================================================================
+ Tooltips
+ ============================================================================= */
+
+QToolTip {
+ background-color: #313244;
+ color: #cdd6f4;
+ border: 1px solid #45475a;
+ border-radius: 4px;
+ padding: 4px 8px;
+}
+
+/* =============================================================================
+ Labels
+ ============================================================================= */
+
+QLabel {
+ color: #cdd6f4;
+ background-color: transparent;
+}
+
+QLabel:disabled {
+ color: #6c7086;
+}
+
+/* =============================================================================
+ Frames
+ ============================================================================= */
+
+QFrame {
+ border: none;
+}
+
+QFrame[frameShape="4"] {
+ /* HLine */
+ background-color: #45475a;
+ max-height: 1px;
+}
+
+QFrame[frameShape="5"] {
+ /* VLine */
+ background-color: #45475a;
+ max-width: 1px;
+}
+
+/* =============================================================================
+ Tool Box (Collapsible sections)
+ ============================================================================= */
+
+QToolBox {
+ background-color: #1e1e2e;
+ border: 1px solid #45475a;
+ border-radius: 4px;
+}
+
+QToolBox::tab {
+ background-color: #313244;
+ color: #cdd6f4;
+ border: 1px solid #45475a;
+ border-radius: 4px;
+ padding: 8px;
+}
+
+QToolBox::tab:selected {
+ background-color: #45475a;
+ border-color: #cba6f7;
+}
+
+QToolBox::tab:hover {
+ background-color: #45475a;
+}
+
+/* =============================================================================
+ Dialog Buttons
+ ============================================================================= */
+
+QDialogButtonBox {
+ button-layout: 0;
+}
+
+/* =============================================================================
+ Date/Time Edits
+ ============================================================================= */
+
+QDateEdit, QTimeEdit, QDateTimeEdit {
+ background-color: #313244;
+ color: #cdd6f4;
+ border: 1px solid #45475a;
+ border-radius: 4px;
+ padding: 4px;
+}
+
+QDateEdit:focus, QTimeEdit:focus, QDateTimeEdit:focus {
+ border-color: #cba6f7;
+}
+
+QDateEdit::drop-down, QTimeEdit::drop-down, QDateTimeEdit::drop-down {
+ subcontrol-origin: padding;
+ subcontrol-position: top right;
+ width: 20px;
+ border-left: 1px solid #45475a;
+ border-top-right-radius: 4px;
+ border-bottom-right-radius: 4px;
+ background-color: #45475a;
+}
+
+QCalendarWidget {
+ background-color: #1e1e2e;
+}
+
+QCalendarWidget QToolButton {
+ background-color: #313244;
+ color: #cdd6f4;
+ border: 1px solid #45475a;
+ border-radius: 4px;
+ margin: 2px;
+}
+
+QCalendarWidget QToolButton:hover {
+ background-color: #45475a;
+}
+
+QCalendarWidget QMenu {
+ background-color: #313244;
+}
+
+QCalendarWidget QSpinBox {
+ background-color: #313244;
+}
+
+QCalendarWidget QAbstractItemView {
+ background-color: #1e1e2e;
+ selection-background-color: #cba6f7;
+ selection-color: #11111b;
+}
+
+/* =============================================================================
+ Wizard
+ ============================================================================= */
+
+QWizard {
+ background-color: #1e1e2e;
+}
+
+QWizard QLabel {
+ color: #cdd6f4;
+}
+
+/* =============================================================================
+ FreeCAD Specific Widgets
+ ============================================================================= */
+
+/* Property Editor */
+Gui--PropertyEditor--PropertyEditor {
+ background-color: #1e1e2e;
+ color: #cdd6f4;
+ border: 1px solid #45475a;
+ qproperty-groupBackground: #313244;
+ qproperty-groupTextColor: #bac2de;
+ qproperty-itemBackground: #1e1e2e;
+}
+
+Gui--PropertyEditor--PropertyEditor QLineEdit {
+ background-color: #313244;
+ border: 1px solid #45475a;
+}
+
+Gui--PropertyEditor--PropertyEditor QComboBox {
+ background-color: #313244;
+}
+
+/* Color Button */
+Gui--ColorButton {
+ background-color: #313244;
+ border: 1px solid #45475a;
+ border-radius: 4px;
+ padding: 2px;
+}
+
+Gui--ColorButton:hover {
+ border-color: #cba6f7;
+}
+
+/* Workbench Selector */
+Gui--WorkbenchComboBox {
+ background-color: #313244;
+ color: #cdd6f4;
+ border: 1px solid #45475a;
+ border-radius: 4px;
+ padding: 4px 8px;
+}
+
+Gui--WorkbenchComboBox:hover {
+ border-color: #585b70;
+}
+
+Gui--WorkbenchComboBox::drop-down {
+ background-color: #45475a;
+ border-left: 1px solid #45475a;
+ border-radius: 0 4px 4px 0;
+}
+
+/* Task Panel */
+QSint--ActionGroup {
+ background-color: #313244;
+ border: 1px solid #45475a;
+ border-radius: 6px;
+}
+
+QSint--ActionGroup QToolButton {
+ background-color: #313244;
+ color: #cdd6f4;
+ border: none;
+ border-radius: 4px;
+ padding: 6px;
+}
+
+QSint--ActionGroup QToolButton:hover {
+ background-color: #45475a;
+}
+
+QSint--ActionGroup QFrame {
+ background-color: #1e1e2e;
+ border: none;
+ border-radius: 4px;
+}
+
+/* Input Field */
+Gui--InputField {
+ background-color: #313244;
+ color: #cdd6f4;
+ border: 1px solid #45475a;
+ border-radius: 4px;
+}
+
+Gui--InputField:focus {
+ border-color: #cba6f7;
+}
+
+/* Expression Completer */
+Gui--ExpressionCompleter {
+ background-color: #313244;
+ color: #cdd6f4;
+ border: 1px solid #45475a;
+}
+
+/* Spreadsheet */
+SpreadsheetGui--SheetTableView {
+ background-color: #1e1e2e;
+ color: #cdd6f4;
+ gridline-color: #45475a;
+ selection-background-color: #45475a;
+ selection-color: #cdd6f4;
+}
+
+SpreadsheetGui--SheetTableView QHeaderView::section {
+ background-color: #313244;
+ color: #bac2de;
+ border: 1px solid #45475a;
+ padding: 4px;
+}
+
+/* Python Console */
+Gui--PythonConsole {
+ background-color: #11111b;
+ color: #cdd6f4;
+ font-family: "JetBrains Mono", "Fira Code", "Consolas", monospace;
+ selection-background-color: #45475a;
+}
+
+/* Python Editor */
+Gui--PythonEditor {
+ background-color: #11111b;
+ color: #cdd6f4;
+ font-family: "JetBrains Mono", "Fira Code", "Consolas", monospace;
+ selection-background-color: #cba6f7;
+ selection-color: #11111b;
+}
+
+/* Report View */
+Gui--DockWnd--ReportOutput {
+ background-color: #11111b;
+ color: #cdd6f4;
+ font-family: "JetBrains Mono", "Fira Code", "Consolas", monospace;
+}
+
+/* DAG View */
+Gui--DAG--Model {
+ background-color: #1e1e2e;
+}
+
+/* =============================================================================
+ Sketcher Specific Styles
+ ============================================================================= */
+
+/* Sketcher constraint colors are handled via preferences, not QSS */
+
+/* =============================================================================
+ Syntax Highlighting Colors (Python Editor)
+ Note: These are typically set via FreeCAD preferences, but we define them here
+ for reference and any widgets that support them.
+ ============================================================================= */
+
+/*
+ Python Editor Syntax Colors (Catppuccin Mocha):
+ - Comment: #7f849c
+ - Number: #fab387
+ - String: #a6e3a1
+ - Keyword: #cba6f7
+ - Class/Def name: #89b4fa
+ - Operator: #89dceb
+ - Output: #cdd6f4
+ - Error: #f38ba8
+*/
+
+/* =============================================================================
+ Custom Color Accents by Context
+ ============================================================================= */
+
+/* Success states */
+*[state="success"] {
+ color: #a6e3a1;
+}
+
+/* Warning states */
+*[state="warning"] {
+ color: #f9e2af;
+}
+
+/* Error states */
+*[state="error"] {
+ color: #f38ba8;
+}
+
+/* Info states */
+*[state="info"] {
+ color: #89b4fa;
+}
diff --git a/resources/preferences/package.xml b/resources/preferences/package.xml
new file mode 100644
index 0000000000..263ed8059c
--- /dev/null
+++ b/resources/preferences/package.xml
@@ -0,0 +1,18 @@
+
+
+
+ Kindred Create Preference Packs
+ Default preference packs for Kindred Create, featuring the Catppuccin Mocha color theme.
+ 0.1.0
+ Kindred Systems LLC
+ LGPL-2.1-or-later
+ https://kindredsystems.net
+
+
+
+ KindredCreate
+ The default Kindred Create theme based on Catppuccin Mocha - a soothing dark color palette.
+
+
+
+
diff --git a/src/Gui/Dialogs/DlgAbout.cpp b/src/Gui/Dialogs/DlgAbout.cpp
index 4b173a69f7..2dc0d31f1c 100644
--- a/src/Gui/Dialogs/DlgAbout.cpp
+++ b/src/Gui/Dialogs/DlgAbout.cpp
@@ -328,9 +328,14 @@ void AboutDialog::showCredits()
//: Header for the Credits tab of the About screen
QString creditsHTML
- = QStringLiteral("
%1
%2
%3
")
+ = QStringLiteral("%1
"
+ "Kindred Systems LLC
"
+ "Kindred Create is developed by Kindred Systems LLC, Kansas City, Missouri.
"
+ "Website: https://kindredsystems.net
"
+ "FreeCAD Project
"
+ "%2
%3
")
.arg(tr("Credits", "Header for the Credits tab of the About screen"))
- .arg(tr("FreeCAD would not be possible without the contributions of:"))
+ .arg(tr("Kindred Create is based on FreeCAD and would not be possible without the contributions of:"))
.arg(tr("Individuals", "Header for the list of individual people in the Credits list."));
QTextStream stream(&creditsFile);
diff --git a/src/Gui/Icons/resource.qrc b/src/Gui/Icons/resource.qrc
index 8f0c617fed..490b3c1ffa 100644
--- a/src/Gui/Icons/resource.qrc
+++ b/src/Gui/Icons/resource.qrc
@@ -122,6 +122,10 @@
freecadsplash8.png
freecadsplash9_2x.png
freecadsplash9.png
+ kindred-create.svg
+ kindredcreateabout.png
+ kindredcreatesplash.png
+ kindredcreatesplash_2x.png
Geoassembly.svg
Geofeaturegroup.svg
Group.svg
diff --git a/src/Gui/PreferencePacks/CMakeLists.txt b/src/Gui/PreferencePacks/CMakeLists.txt
index c0d86a98e9..64f2092426 100644
--- a/src/Gui/PreferencePacks/CMakeLists.txt
+++ b/src/Gui/PreferencePacks/CMakeLists.txt
@@ -3,6 +3,7 @@ SET(PreferencePacks_Files
)
SET(PreferencePacks_Directories
+ "KindredCreate"
"FreeCAD Classic"
"Dark behave"
"FreeCAD Light"
diff --git a/src/Gui/PreferencePacks/KindredCreate/KindredCreate.qss b/src/Gui/PreferencePacks/KindredCreate/KindredCreate.qss
new file mode 100644
index 0000000000..6ce5343d31
--- /dev/null
+++ b/src/Gui/PreferencePacks/KindredCreate/KindredCreate.qss
@@ -0,0 +1,1229 @@
+
+/* =============================================================================
+ Catppuccin Mocha Theme for FreeCAD
+ Bundled with ztools addon
+ https://catppuccin.com/
+ ============================================================================= */
+
+/* =============================================================================
+ Global Defaults
+ ============================================================================= */
+
+* {
+ color: #cdd6f4;
+ font-family: "Segoe UI", "Ubuntu", "Noto Sans", sans-serif;
+}
+
+QWidget {
+ background-color: #1e1e2e;
+ color: #cdd6f4;
+ selection-background-color: #585b70;
+ selection-color: #cdd6f4;
+}
+
+/* =============================================================================
+ Main Window and MDI Area
+ ============================================================================= */
+
+QMainWindow {
+ background-color: #181825;
+}
+
+QMainWindow::separator {
+ background-color: #313244;
+ width: 4px;
+ height: 4px;
+}
+
+QMainWindow::separator:hover {
+ background-color: #cba6f7;
+}
+
+QMdiArea {
+ background-color: #11111b;
+}
+
+QMdiSubWindow {
+ background-color: #1e1e2e;
+ border: 1px solid #45475a;
+}
+
+QMdiSubWindow > QWidget {
+ background-color: #1e1e2e;
+}
+
+/* =============================================================================
+ Menu Bar
+ ============================================================================= */
+
+QMenuBar {
+ background-color: #181825;
+ color: #cdd6f4;
+ border-bottom: 1px solid #313244;
+ padding: 2px;
+}
+
+QMenuBar::item {
+ background-color: transparent;
+ padding: 4px 8px;
+ border-radius: 4px;
+}
+
+QMenuBar::item:selected {
+ background-color: #313244;
+}
+
+QMenuBar::item:pressed {
+ background-color: #45475a;
+}
+
+/* =============================================================================
+ Menus
+ ============================================================================= */
+
+QMenu {
+ background-color: #313244;
+ color: #cdd6f4;
+ border: 1px solid #45475a;
+ border-radius: 6px;
+ padding: 4px;
+}
+
+QMenu::item {
+ padding: 6px 24px 6px 8px;
+ border-radius: 4px;
+}
+
+QMenu::item:selected {
+ background-color: #45475a;
+ color: #cdd6f4;
+}
+
+QMenu::item:disabled {
+ color: #6c7086;
+}
+
+QMenu::separator {
+ height: 1px;
+ background-color: #45475a;
+ margin: 4px 8px;
+}
+
+QMenu::icon {
+ margin-left: 8px;
+}
+
+QMenu::indicator {
+ width: 16px;
+ height: 16px;
+ margin-left: 4px;
+}
+
+/* =============================================================================
+ Toolbars
+ ============================================================================= */
+
+QToolBar {
+ background-color: #181825;
+ border: none;
+ spacing: 2px;
+ padding: 2px;
+}
+
+QToolBar::handle {
+ background-color: #45475a;
+ width: 8px;
+ margin: 2px;
+ border-radius: 2px;
+}
+
+QToolBar::handle:horizontal {
+ width: 8px;
+}
+
+QToolBar::handle:vertical {
+ height: 8px;
+}
+
+QToolBar::separator {
+ background-color: #45475a;
+ width: 1px;
+ margin: 4px 2px;
+}
+
+/* =============================================================================
+ Tool Buttons (Toolbar icons)
+ ============================================================================= */
+
+QToolButton {
+ background-color: transparent;
+ border: 1px solid transparent;
+ border-radius: 4px;
+ padding: 4px;
+ margin: 1px;
+}
+
+QToolButton:hover {
+ background-color: #313244;
+ border: 1px solid #45475a;
+}
+
+QToolButton:pressed {
+ background-color: #45475a;
+}
+
+QToolButton:checked {
+ background-color: #45475a;
+ border: 1px solid #cba6f7;
+}
+
+QToolButton:disabled {
+ color: #6c7086;
+}
+
+QToolButton[popupMode="1"] {
+ padding-right: 16px;
+}
+
+QToolButton::menu-button {
+ border: none;
+ width: 14px;
+}
+
+QToolButton::menu-arrow {
+ width: 10px;
+ height: 10px;
+}
+
+/* =============================================================================
+ Push Buttons
+ ============================================================================= */
+
+QPushButton {
+ background-color: #313244;
+ color: #cdd6f4;
+ border: 1px solid #45475a;
+ border-radius: 6px;
+ padding: 6px 16px;
+ min-height: 20px;
+}
+
+QPushButton:hover {
+ background-color: #45475a;
+ border-color: #585b70;
+}
+
+QPushButton:pressed {
+ background-color: #585b70;
+}
+
+QPushButton:checked {
+ background-color: #cba6f7;
+ color: #11111b;
+ border-color: #cba6f7;
+}
+
+QPushButton:disabled {
+ background-color: #313244;
+ color: #6c7086;
+ border-color: #313244;
+}
+
+QPushButton:default {
+ border: 2px solid #cba6f7;
+}
+
+/* =============================================================================
+ Dock Widgets
+ ============================================================================= */
+
+QDockWidget {
+ background-color: #1e1e2e;
+ color: #cdd6f4;
+ titlebar-close-icon: none;
+ titlebar-normal-icon: none;
+}
+
+QDockWidget::title {
+ background-color: #181825;
+ color: #cdd6f4;
+ padding: 6px;
+ border-bottom: 1px solid #313244;
+}
+
+QDockWidget::close-button,
+QDockWidget::float-button {
+ background-color: transparent;
+ border: none;
+ padding: 2px;
+}
+
+QDockWidget::close-button:hover,
+QDockWidget::float-button:hover {
+ background-color: #313244;
+ border-radius: 4px;
+}
+
+/* =============================================================================
+ Tab Widgets
+ ============================================================================= */
+
+QTabWidget::pane {
+ background-color: #1e1e2e;
+ border: 1px solid #45475a;
+ border-radius: 4px;
+ top: -1px;
+}
+
+QTabBar {
+ background-color: transparent;
+}
+
+QTabBar::tab {
+ background-color: #313244;
+ color: #bac2de;
+ border: 1px solid #45475a;
+ padding: 6px 12px;
+ margin-right: 2px;
+ border-top-left-radius: 6px;
+ border-top-right-radius: 6px;
+}
+
+QTabBar::tab:selected {
+ background-color: #1e1e2e;
+ color: #cdd6f4;
+ border-bottom-color: #1e1e2e;
+}
+
+QTabBar::tab:hover:!selected {
+ background-color: #45475a;
+ color: #cdd6f4;
+}
+
+QTabBar::tab:disabled {
+ color: #6c7086;
+}
+
+QTabBar::close-button {
+ margin-left: 4px;
+}
+
+QTabBar::close-button:hover {
+ background-color: #f38ba8;
+ border-radius: 2px;
+}
+
+/* =============================================================================
+ Scroll Bars
+ ============================================================================= */
+
+QScrollBar:horizontal {
+ background-color: #181825;
+ height: 12px;
+ margin: 0 12px 0 12px;
+ border-radius: 6px;
+}
+
+QScrollBar:vertical {
+ background-color: #181825;
+ width: 12px;
+ margin: 12px 0 12px 0;
+ border-radius: 6px;
+}
+
+QScrollBar::handle:horizontal {
+ background-color: #45475a;
+ min-width: 20px;
+ border-radius: 5px;
+ margin: 1px;
+}
+
+QScrollBar::handle:vertical {
+ background-color: #45475a;
+ min-height: 20px;
+ border-radius: 5px;
+ margin: 1px;
+}
+
+QScrollBar::handle:horizontal:hover,
+QScrollBar::handle:vertical:hover {
+ background-color: #585b70;
+}
+
+QScrollBar::add-line:horizontal,
+QScrollBar::sub-line:horizontal,
+QScrollBar::add-line:vertical,
+QScrollBar::sub-line:vertical {
+ width: 12px;
+ height: 12px;
+ background-color: #313244;
+ border-radius: 6px;
+}
+
+QScrollBar::add-line:horizontal:hover,
+QScrollBar::sub-line:horizontal:hover,
+QScrollBar::add-line:vertical:hover,
+QScrollBar::sub-line:vertical:hover {
+ background-color: #45475a;
+}
+
+QScrollBar::add-page:horizontal,
+QScrollBar::sub-page:horizontal,
+QScrollBar::add-page:vertical,
+QScrollBar::sub-page:vertical {
+ background-color: transparent;
+}
+
+/* =============================================================================
+ Input Fields
+ ============================================================================= */
+
+QLineEdit {
+ background-color: #313244;
+ color: #cdd6f4;
+ border: 1px solid #45475a;
+ border-radius: 4px;
+ padding: 4px 8px;
+ selection-background-color: #cba6f7;
+ selection-color: #11111b;
+}
+
+QLineEdit:focus {
+ border-color: #cba6f7;
+}
+
+QLineEdit:disabled {
+ background-color: #181825;
+ color: #6c7086;
+}
+
+QLineEdit:read-only {
+ background-color: #181825;
+}
+
+QTextEdit, QPlainTextEdit {
+ background-color: #313244;
+ color: #cdd6f4;
+ border: 1px solid #45475a;
+ border-radius: 4px;
+ selection-background-color: #cba6f7;
+ selection-color: #11111b;
+}
+
+QTextEdit:focus, QPlainTextEdit:focus {
+ border-color: #cba6f7;
+}
+
+/* =============================================================================
+ Spin Boxes
+ ============================================================================= */
+
+QSpinBox, QDoubleSpinBox {
+ background-color: #313244;
+ color: #cdd6f4;
+ border: 1px solid #45475a;
+ border-radius: 4px;
+ padding: 4px;
+ padding-right: 20px;
+}
+
+QSpinBox:focus, QDoubleSpinBox:focus {
+ border-color: #cba6f7;
+}
+
+QSpinBox:disabled, QDoubleSpinBox:disabled {
+ background-color: #181825;
+ color: #6c7086;
+}
+
+QSpinBox::up-button, QDoubleSpinBox::up-button {
+ subcontrol-origin: border;
+ subcontrol-position: top right;
+ width: 16px;
+ border-left: 1px solid #45475a;
+ border-top-right-radius: 4px;
+ background-color: #45475a;
+}
+
+QSpinBox::down-button, QDoubleSpinBox::down-button {
+ subcontrol-origin: border;
+ subcontrol-position: bottom right;
+ width: 16px;
+ border-left: 1px solid #45475a;
+ border-bottom-right-radius: 4px;
+ background-color: #45475a;
+}
+
+QSpinBox::up-button:hover, QDoubleSpinBox::up-button:hover,
+QSpinBox::down-button:hover, QDoubleSpinBox::down-button:hover {
+ background-color: #585b70;
+}
+
+QSpinBox::up-button:pressed, QDoubleSpinBox::up-button:pressed,
+QSpinBox::down-button:pressed, QDoubleSpinBox::down-button:pressed {
+ background-color: #cba6f7;
+}
+
+QSpinBox::up-arrow, QDoubleSpinBox::up-arrow {
+ width: 8px;
+ height: 8px;
+}
+
+QSpinBox::down-arrow, QDoubleSpinBox::down-arrow {
+ width: 8px;
+ height: 8px;
+}
+
+/* =============================================================================
+ Combo Boxes
+ ============================================================================= */
+
+QComboBox {
+ background-color: #313244;
+ color: #cdd6f4;
+ border: 1px solid #45475a;
+ border-radius: 4px;
+ padding: 4px 8px;
+ padding-right: 24px;
+ min-height: 20px;
+}
+
+QComboBox:hover {
+ border-color: #585b70;
+}
+
+QComboBox:focus {
+ border-color: #cba6f7;
+}
+
+QComboBox:disabled {
+ background-color: #181825;
+ color: #6c7086;
+}
+
+QComboBox::drop-down {
+ subcontrol-origin: padding;
+ subcontrol-position: top right;
+ width: 20px;
+ border-left: 1px solid #45475a;
+ border-top-right-radius: 4px;
+ border-bottom-right-radius: 4px;
+ background-color: #45475a;
+}
+
+QComboBox::drop-down:hover {
+ background-color: #585b70;
+}
+
+QComboBox::down-arrow {
+ width: 10px;
+ height: 10px;
+}
+
+QComboBox QAbstractItemView {
+ background-color: #313244;
+ color: #cdd6f4;
+ border: 1px solid #45475a;
+ border-radius: 4px;
+ selection-background-color: #45475a;
+ selection-color: #cdd6f4;
+ outline: none;
+}
+
+QComboBox QAbstractItemView::item {
+ padding: 4px 8px;
+ min-height: 24px;
+}
+
+QComboBox QAbstractItemView::item:hover {
+ background-color: #45475a;
+}
+
+QComboBox QAbstractItemView::item:selected {
+ background-color: #585b70;
+}
+
+/* =============================================================================
+ Check Boxes
+ ============================================================================= */
+
+QCheckBox {
+ spacing: 8px;
+ color: #cdd6f4;
+}
+
+QCheckBox:disabled {
+ color: #6c7086;
+}
+
+QCheckBox::indicator {
+ width: 18px;
+ height: 18px;
+ border: 2px solid #585b70;
+ border-radius: 4px;
+ background-color: #313244;
+}
+
+QCheckBox::indicator:hover {
+ border-color: #cba6f7;
+}
+
+QCheckBox::indicator:checked {
+ background-color: #cba6f7;
+ border-color: #cba6f7;
+}
+
+QCheckBox::indicator:checked:disabled {
+ background-color: #6c7086;
+ border-color: #6c7086;
+}
+
+QCheckBox::indicator:disabled {
+ background-color: #181825;
+ border-color: #45475a;
+}
+
+/* =============================================================================
+ Radio Buttons
+ ============================================================================= */
+
+QRadioButton {
+ spacing: 8px;
+ color: #cdd6f4;
+}
+
+QRadioButton:disabled {
+ color: #6c7086;
+}
+
+QRadioButton::indicator {
+ width: 18px;
+ height: 18px;
+ border: 2px solid #585b70;
+ border-radius: 9px;
+ background-color: #313244;
+}
+
+QRadioButton::indicator:hover {
+ border-color: #cba6f7;
+}
+
+QRadioButton::indicator:checked {
+ background-color: #cba6f7;
+ border-color: #cba6f7;
+}
+
+QRadioButton::indicator:checked:disabled {
+ background-color: #6c7086;
+ border-color: #6c7086;
+}
+
+QRadioButton::indicator:disabled {
+ background-color: #181825;
+ border-color: #45475a;
+}
+
+/* =============================================================================
+ Sliders
+ ============================================================================= */
+
+QSlider::groove:horizontal {
+ height: 6px;
+ background-color: #45475a;
+ border-radius: 3px;
+}
+
+QSlider::groove:vertical {
+ width: 6px;
+ background-color: #45475a;
+ border-radius: 3px;
+}
+
+QSlider::handle:horizontal {
+ width: 16px;
+ height: 16px;
+ margin: -5px 0;
+ background-color: #cba6f7;
+ border-radius: 8px;
+}
+
+QSlider::handle:vertical {
+ width: 16px;
+ height: 16px;
+ margin: 0 -5px;
+ background-color: #cba6f7;
+ border-radius: 8px;
+}
+
+QSlider::handle:horizontal:hover,
+QSlider::handle:vertical:hover {
+ background-color: #b4befe;
+}
+
+QSlider::handle:horizontal:pressed,
+QSlider::handle:vertical:pressed {
+ background-color: #f5c2e7;
+}
+
+QSlider::sub-page:horizontal {
+ background-color: #cba6f7;
+ border-radius: 3px;
+}
+
+QSlider::add-page:vertical {
+ background-color: #cba6f7;
+ border-radius: 3px;
+}
+
+/* =============================================================================
+ Progress Bars
+ ============================================================================= */
+
+QProgressBar {
+ background-color: #313244;
+ color: #cdd6f4;
+ border: 1px solid #45475a;
+ border-radius: 4px;
+ text-align: center;
+ height: 20px;
+}
+
+QProgressBar::chunk {
+ background-color: #cba6f7;
+ border-radius: 3px;
+}
+
+/* =============================================================================
+ Group Boxes
+ ============================================================================= */
+
+QGroupBox {
+ background-color: #1e1e2e;
+ border: 1px solid #45475a;
+ border-radius: 6px;
+ margin-top: 12px;
+ padding-top: 8px;
+}
+
+QGroupBox::title {
+ subcontrol-origin: margin;
+ subcontrol-position: top left;
+ left: 12px;
+ padding: 0 4px;
+ color: #bac2de;
+ background-color: #1e1e2e;
+}
+
+/* =============================================================================
+ Tree View
+ ============================================================================= */
+
+QTreeView {
+ background-color: #1e1e2e;
+ color: #cdd6f4;
+ border: 1px solid #45475a;
+ border-radius: 4px;
+ outline: none;
+ show-decoration-selected: 1;
+}
+
+QTreeView::item {
+ padding: 4px;
+ border-radius: 2px;
+}
+
+QTreeView::item:hover {
+ background-color: #313244;
+}
+
+QTreeView::item:selected {
+ background-color: #45475a;
+ color: #cdd6f4;
+}
+
+QTreeView::item:selected:active {
+ background-color: #585b70;
+}
+
+QTreeView::branch {
+ background-color: transparent;
+}
+
+QTreeView::branch:hover {
+ background-color: #313244;
+}
+
+QTreeView::branch:selected {
+ background-color: #45475a;
+}
+
+/* =============================================================================
+ List View
+ ============================================================================= */
+
+QListView {
+ background-color: #1e1e2e;
+ color: #cdd6f4;
+ border: 1px solid #45475a;
+ border-radius: 4px;
+ outline: none;
+}
+
+QListView::item {
+ padding: 4px;
+ border-radius: 2px;
+}
+
+QListView::item:hover {
+ background-color: #313244;
+}
+
+QListView::item:selected {
+ background-color: #45475a;
+ color: #cdd6f4;
+}
+
+/* =============================================================================
+ Table View
+ ============================================================================= */
+
+QTableView {
+ background-color: #1e1e2e;
+ color: #cdd6f4;
+ border: 1px solid #45475a;
+ border-radius: 4px;
+ gridline-color: #313244;
+ outline: none;
+}
+
+QTableView::item {
+ padding: 4px;
+}
+
+QTableView::item:hover {
+ background-color: #313244;
+}
+
+QTableView::item:selected {
+ background-color: #45475a;
+ color: #cdd6f4;
+}
+
+QTableView QTableCornerButton::section {
+ background-color: #313244;
+ border: 1px solid #45475a;
+}
+
+/* =============================================================================
+ Header Views (for Tables/Trees)
+ ============================================================================= */
+
+QHeaderView {
+ background-color: #313244;
+ border: none;
+}
+
+QHeaderView::section {
+ background-color: #313244;
+ color: #bac2de;
+ border: none;
+ border-right: 1px solid #45475a;
+ border-bottom: 1px solid #45475a;
+ padding: 6px 8px;
+}
+
+QHeaderView::section:hover {
+ background-color: #45475a;
+ color: #cdd6f4;
+}
+
+QHeaderView::section:checked {
+ background-color: #45475a;
+}
+
+QHeaderView::down-arrow {
+ width: 10px;
+ height: 10px;
+}
+
+QHeaderView::up-arrow {
+ width: 10px;
+ height: 10px;
+}
+
+/* =============================================================================
+ Splitters
+ ============================================================================= */
+
+QSplitter::handle {
+ background-color: #313244;
+}
+
+QSplitter::handle:horizontal {
+ width: 4px;
+}
+
+QSplitter::handle:vertical {
+ height: 4px;
+}
+
+QSplitter::handle:hover {
+ background-color: #cba6f7;
+}
+
+/* =============================================================================
+ Status Bar
+ ============================================================================= */
+
+QStatusBar {
+ background-color: #181825;
+ color: #bac2de;
+ border-top: 1px solid #313244;
+}
+
+QStatusBar::item {
+ border: none;
+}
+
+QStatusBar QLabel {
+ padding: 2px 8px;
+}
+
+/* =============================================================================
+ Tooltips
+ ============================================================================= */
+
+QToolTip {
+ background-color: #313244;
+ color: #cdd6f4;
+ border: 1px solid #45475a;
+ border-radius: 4px;
+ padding: 4px 8px;
+}
+
+/* =============================================================================
+ Labels
+ ============================================================================= */
+
+QLabel {
+ color: #cdd6f4;
+ background-color: transparent;
+}
+
+QLabel:disabled {
+ color: #6c7086;
+}
+
+/* =============================================================================
+ Frames
+ ============================================================================= */
+
+QFrame {
+ border: none;
+}
+
+QFrame[frameShape="4"] {
+ /* HLine */
+ background-color: #45475a;
+ max-height: 1px;
+}
+
+QFrame[frameShape="5"] {
+ /* VLine */
+ background-color: #45475a;
+ max-width: 1px;
+}
+
+/* =============================================================================
+ Tool Box (Collapsible sections)
+ ============================================================================= */
+
+QToolBox {
+ background-color: #1e1e2e;
+ border: 1px solid #45475a;
+ border-radius: 4px;
+}
+
+QToolBox::tab {
+ background-color: #313244;
+ color: #cdd6f4;
+ border: 1px solid #45475a;
+ border-radius: 4px;
+ padding: 8px;
+}
+
+QToolBox::tab:selected {
+ background-color: #45475a;
+ border-color: #cba6f7;
+}
+
+QToolBox::tab:hover {
+ background-color: #45475a;
+}
+
+/* =============================================================================
+ Dialog Buttons
+ ============================================================================= */
+
+QDialogButtonBox {
+ button-layout: 0;
+}
+
+/* =============================================================================
+ Date/Time Edits
+ ============================================================================= */
+
+QDateEdit, QTimeEdit, QDateTimeEdit {
+ background-color: #313244;
+ color: #cdd6f4;
+ border: 1px solid #45475a;
+ border-radius: 4px;
+ padding: 4px;
+}
+
+QDateEdit:focus, QTimeEdit:focus, QDateTimeEdit:focus {
+ border-color: #cba6f7;
+}
+
+QDateEdit::drop-down, QTimeEdit::drop-down, QDateTimeEdit::drop-down {
+ subcontrol-origin: padding;
+ subcontrol-position: top right;
+ width: 20px;
+ border-left: 1px solid #45475a;
+ border-top-right-radius: 4px;
+ border-bottom-right-radius: 4px;
+ background-color: #45475a;
+}
+
+QCalendarWidget {
+ background-color: #1e1e2e;
+}
+
+QCalendarWidget QToolButton {
+ background-color: #313244;
+ color: #cdd6f4;
+ border: 1px solid #45475a;
+ border-radius: 4px;
+ margin: 2px;
+}
+
+QCalendarWidget QToolButton:hover {
+ background-color: #45475a;
+}
+
+QCalendarWidget QMenu {
+ background-color: #313244;
+}
+
+QCalendarWidget QSpinBox {
+ background-color: #313244;
+}
+
+QCalendarWidget QAbstractItemView {
+ background-color: #1e1e2e;
+ selection-background-color: #cba6f7;
+ selection-color: #11111b;
+}
+
+/* =============================================================================
+ Wizard
+ ============================================================================= */
+
+QWizard {
+ background-color: #1e1e2e;
+}
+
+QWizard QLabel {
+ color: #cdd6f4;
+}
+
+/* =============================================================================
+ FreeCAD Specific Widgets
+ ============================================================================= */
+
+/* Property Editor */
+Gui--PropertyEditor--PropertyEditor {
+ background-color: #1e1e2e;
+ color: #cdd6f4;
+ border: 1px solid #45475a;
+ qproperty-groupBackground: #313244;
+ qproperty-groupTextColor: #bac2de;
+ qproperty-itemBackground: #1e1e2e;
+}
+
+Gui--PropertyEditor--PropertyEditor QLineEdit {
+ background-color: #313244;
+ border: 1px solid #45475a;
+}
+
+Gui--PropertyEditor--PropertyEditor QComboBox {
+ background-color: #313244;
+}
+
+/* Color Button */
+Gui--ColorButton {
+ background-color: #313244;
+ border: 1px solid #45475a;
+ border-radius: 4px;
+ padding: 2px;
+}
+
+Gui--ColorButton:hover {
+ border-color: #cba6f7;
+}
+
+/* Workbench Selector */
+Gui--WorkbenchComboBox {
+ background-color: #313244;
+ color: #cdd6f4;
+ border: 1px solid #45475a;
+ border-radius: 4px;
+ padding: 4px 8px;
+}
+
+Gui--WorkbenchComboBox:hover {
+ border-color: #585b70;
+}
+
+Gui--WorkbenchComboBox::drop-down {
+ background-color: #45475a;
+ border-left: 1px solid #45475a;
+ border-radius: 0 4px 4px 0;
+}
+
+/* Task Panel */
+QSint--ActionGroup {
+ background-color: #313244;
+ border: 1px solid #45475a;
+ border-radius: 6px;
+}
+
+QSint--ActionGroup QToolButton {
+ background-color: #313244;
+ color: #cdd6f4;
+ border: none;
+ border-radius: 4px;
+ padding: 6px;
+}
+
+QSint--ActionGroup QToolButton:hover {
+ background-color: #45475a;
+}
+
+QSint--ActionGroup QFrame {
+ background-color: #1e1e2e;
+ border: none;
+ border-radius: 4px;
+}
+
+/* Input Field */
+Gui--InputField {
+ background-color: #313244;
+ color: #cdd6f4;
+ border: 1px solid #45475a;
+ border-radius: 4px;
+}
+
+Gui--InputField:focus {
+ border-color: #cba6f7;
+}
+
+/* Expression Completer */
+Gui--ExpressionCompleter {
+ background-color: #313244;
+ color: #cdd6f4;
+ border: 1px solid #45475a;
+}
+
+/* Spreadsheet */
+SpreadsheetGui--SheetTableView {
+ background-color: #1e1e2e;
+ color: #cdd6f4;
+ gridline-color: #45475a;
+ selection-background-color: #45475a;
+ selection-color: #cdd6f4;
+}
+
+SpreadsheetGui--SheetTableView QHeaderView::section {
+ background-color: #313244;
+ color: #bac2de;
+ border: 1px solid #45475a;
+ padding: 4px;
+}
+
+/* Python Console */
+Gui--PythonConsole {
+ background-color: #11111b;
+ color: #cdd6f4;
+ font-family: "JetBrains Mono", "Fira Code", "Consolas", monospace;
+ selection-background-color: #45475a;
+}
+
+/* Python Editor */
+Gui--PythonEditor {
+ background-color: #11111b;
+ color: #cdd6f4;
+ font-family: "JetBrains Mono", "Fira Code", "Consolas", monospace;
+ selection-background-color: #cba6f7;
+ selection-color: #11111b;
+}
+
+/* Report View */
+Gui--DockWnd--ReportOutput {
+ background-color: #11111b;
+ color: #cdd6f4;
+ font-family: "JetBrains Mono", "Fira Code", "Consolas", monospace;
+}
+
+/* DAG View */
+Gui--DAG--Model {
+ background-color: #1e1e2e;
+}
+
+/* =============================================================================
+ Sketcher Specific Styles
+ ============================================================================= */
+
+/* Sketcher constraint colors are handled via preferences, not QSS */
+
+/* =============================================================================
+ Syntax Highlighting Colors (Python Editor)
+ Note: These are typically set via FreeCAD preferences, but we define them here
+ for reference and any widgets that support them.
+ ============================================================================= */
+
+/*
+ Python Editor Syntax Colors (Catppuccin Mocha):
+ - Comment: #7f849c
+ - Number: #fab387
+ - String: #a6e3a1
+ - Keyword: #cba6f7
+ - Class/Def name: #89b4fa
+ - Operator: #89dceb
+ - Output: #cdd6f4
+ - Error: #f38ba8
+*/
+
+/* =============================================================================
+ Custom Color Accents by Context
+ ============================================================================= */
+
+/* Success states */
+*[state="success"] {
+ color: #a6e3a1;
+}
+
+/* Warning states */
+*[state="warning"] {
+ color: #f9e2af;
+}
+
+/* Error states */
+*[state="error"] {
+ color: #f38ba8;
+}
+
+/* Info states */
+*[state="info"] {
+ color: #89b4fa;
+}
diff --git a/src/Gui/PreferencePacks/package.xml b/src/Gui/PreferencePacks/package.xml
index 3ecbc6b807..eacd80cc72 100644
--- a/src/Gui/PreferencePacks/package.xml
+++ b/src/Gui/PreferencePacks/package.xml
@@ -1,12 +1,23 @@
Built-In Preference Packs
- Preference Packs included with the FreeCAD distribution
+ Preference Packs included with the Kindred Create distribution
1.0.0
- MisterMaker
+ Kindred Systems LLC
LGPL2
- https://github.com/FreeCAD/FreeCAD
+ https://github.com/kindredsystems/create
+
+ KindredCreate
+ Theme
+ The default Kindred Create theme based on Catppuccin Mocha - a soothing dark color palette with carefully chosen colors for optimal readability.
+ 1.0.0
+ built-in
+ default
+ dark
+ catppuccin
+ mocha
+
FreeCAD Classic
Theme
@@ -17,8 +28,8 @@
no stylesheet
classic theme
-
- FreeCAD Light
+
+ FreeCAD Light
Theme
Applies a basic light theme.
1.0.0
@@ -26,8 +37,8 @@
background
light
-
- FreeCAD Dark
+
+ FreeCAD Dark
Theme
Applies a basic dark theme.
1.0.0
diff --git a/src/Gui/SplashScreen.cpp b/src/Gui/SplashScreen.cpp
index 7006911058..656cb64fb2 100644
--- a/src/Gui/SplashScreen.cpp
+++ b/src/Gui/SplashScreen.cpp
@@ -360,8 +360,8 @@ QPixmap SplashScreen::splashImage()
fontExe.setPointSizeF(20.0);
QFontMetrics metricExe(fontExe);
int l = QtTools::horizontalAdvance(metricExe, title);
- if (title == QLatin1String("FreeCAD")) {
- l = 0.0; // "FreeCAD" text is already part of the splashscreen, version goes below it
+ if (title == QLatin1String("Kindred Create")) {
+ // For Kindred Create splash, we draw the title as part of the dynamic rendering
}
int w = splash_image.width();
int h = splash_image.height();
diff --git a/src/Gui/Stylesheets/CMakeLists.txt b/src/Gui/Stylesheets/CMakeLists.txt
index 717aef4da8..104ff80ae2 100644
--- a/src/Gui/Stylesheets/CMakeLists.txt
+++ b/src/Gui/Stylesheets/CMakeLists.txt
@@ -1,5 +1,6 @@
SET(Stylesheets_Files
+ "KindredCreate.qss"
"FreeCAD.qss"
"defaults.qss"
)
diff --git a/src/Main/FreeCADGuiPy.cpp b/src/Main/FreeCADGuiPy.cpp
index 583ac6722b..120aa2754c 100644
--- a/src/Main/FreeCADGuiPy.cpp
+++ b/src/Main/FreeCADGuiPy.cpp
@@ -338,11 +338,11 @@ PyMOD_INIT_FUNC(FreeCADGui)
try {
// clang-format off
Base::Interpreter().loadModule("FreeCAD");
- App::Application::Config()["AppIcon"] = "freecad";
- App::Application::Config()["SplashScreen"] = "freecadsplash";
- App::Application::Config()["CopyrightInfo"] = fmt::format("\xc2\xa9 Juergen Riegel, Werner Mayer, Yorik van Havre and others 2001-{}\n", FCCopyrightYear);
- App::Application::Config()["LicenseInfo"] = "FreeCAD is free and open-source software licensed under the terms of LGPL2+ license.\n";
- App::Application::Config()["CreditsInfo"] = "FreeCAD would not be possible without the FreeCAD community.\n";
+ App::Application::Config()["AppIcon"] = "kindred-create";
+ App::Application::Config()["SplashScreen"] = "kindredcreatesplash";
+ App::Application::Config()["CopyrightInfo"] = "\xc2\xa9 2025 Kindred Systems LLC\n";
+ App::Application::Config()["LicenseInfo"] = "Kindred Create is licensed under LGPL-3.0-or-later.\nBased on FreeCAD, licensed under LGPL-2.0-or-later.\n";
+ App::Application::Config()["CreditsInfo"] = "Kindred Create is based on FreeCAD and would not be possible without the FreeCAD community.\n";
// clang-format on
// it's possible that the GUI is already initialized when the Gui version of the executable
diff --git a/src/Main/MainCmd.cpp b/src/Main/MainCmd.cpp
index f12fb4d12b..30b3dc1fb2 100644
--- a/src/Main/MainCmd.cpp
+++ b/src/Main/MainCmd.cpp
@@ -46,11 +46,10 @@
using App::Application;
using Base::Console;
-const auto sBanner = fmt::format(
- "(C) 2001-{} FreeCAD contributors\n"
- "FreeCAD is free and open-source software licensed under the terms of LGPL2+ license.\n\n",
- FCCopyrightYear
-);
+const char sBanner[]
+ = "(C) 2025 Kindred Systems LLC\n"
+ "Kindred Create is licensed under LGPL-3.0-or-later.\n"
+ "Based on FreeCAD (C) 2001-2025 FreeCAD contributors, licensed under LGPL-2.0-or-later.\n\n";
int main(int argc, char** argv)
{
@@ -67,12 +66,13 @@ int main(int argc, char** argv)
#endif
// Name and Version of the Application
- App::Application::Config()["ExeName"] = "FreeCAD";
- App::Application::Config()["ExeVendor"] = "FreeCAD";
+ App::Application::Config()["ExeName"] = "Kindred Create";
+ App::Application::Config()["ExeVendor"] = "Kindred Systems LLC";
App::Application::Config()["AppDataSkipVendor"] = "true";
// set the banner (for logging and console)
App::Application::Config()["CopyrightInfo"] = sBanner;
+ App::Application::Config()["MaintainerUrl"] = "https://kindredsystems.net";
try {
// Init phase ===========================================================
@@ -147,7 +147,7 @@ int main(int argc, char** argv)
}
// Destruction phase ===========================================================
- Console().log("FreeCAD terminating...\n");
+ Console().log("Kindred Create terminating...\n");
try {
// close open documents
@@ -159,7 +159,7 @@ int main(int argc, char** argv)
// cleans up
Application::destruct();
- Console().log("FreeCAD completely terminated\n");
+ Console().log("Kindred Create completely terminated\n");
return 0;
}
diff --git a/src/Main/MainGui.cpp b/src/Main/MainGui.cpp
index 43dd556818..9a371f7687 100644
--- a/src/Main/MainGui.cpp
+++ b/src/Main/MainGui.cpp
@@ -54,11 +54,10 @@
void PrintInitHelp();
-const auto sBanner = fmt::format(
- "(C) 2001-{} FreeCAD contributors\n"
- "FreeCAD is free and open-source software licensed under the terms of LGPL2+ license.\n\n",
- FCCopyrightYear
-);
+const char sBanner[]
+ = "(C) 2025 Kindred Systems LLC\n"
+ "Kindred Create is licensed under LGPL-3.0-or-later.\n"
+ "Based on FreeCAD (C) 2001-2025 FreeCAD contributors, licensed under LGPL-2.0-or-later.\n\n";
#if defined(_MSC_VER)
void InitMiniDumpWriter(const std::string&);
@@ -188,26 +187,25 @@ int main(int argc, char** argv)
#endif
// Name and Version of the Application
- App::Application::Config()["ExeName"] = "FreeCAD";
- App::Application::Config()["ExeVendor"] = "FreeCAD";
+ App::Application::Config()["ExeName"] = "Kindred Create";
+ App::Application::Config()["ExeVendor"] = "Kindred Systems LLC";
App::Application::Config()["AppDataSkipVendor"] = "true";
- App::Application::Config()["MaintainerUrl"] = "https://freecad.org";
+ App::Application::Config()["MaintainerUrl"] = "https://kindredsystems.net";
// set the banner (for logging and console)
App::Application::Config()["CopyrightInfo"] = sBanner;
- App::Application::Config()["AppIcon"] = "freecad";
- App::Application::Config()["SplashScreen"] = "freecadsplash";
- App::Application::Config()["AboutImage"] = App::Application::isDevelopmentVersion()
- ? "freecadaboutdev"
- : "freecadabout";
+ App::Application::Config()["AppIcon"] = "kindred-create";
+ App::Application::Config()["SplashScreen"] = "kindredcreatesplash";
+ App::Application::Config()["AboutImage"] = "kindredcreateabout";
+ App::Application::Config()["StyleSheet"] = "KindredCreate.qss";
App::Application::Config()["StartWorkbench"] = "PartDesignWorkbench";
// App::Application::Config()["HiddenDockWindow"] = "Property editor";
App::Application::Config()["SplashAlignment"] = "Bottom|Left";
- App::Application::Config()["SplashTextColor"] = "#418FDE";
- App::Application::Config()["SplashWarningColor"] = "#CA333B";
- App::Application::Config()["SplashInfoColor"] = "#000000";
+ App::Application::Config()["SplashTextColor"] = "#cdd6f4"; // Catppuccin Mocha text
+ App::Application::Config()["SplashWarningColor"] = "#f38ba8"; // Catppuccin Mocha red
+ App::Application::Config()["SplashInfoColor"] = "#a6adc8"; // Catppuccin Mocha subtext0
App::Application::Config()["SplashInfoPosition"] = "6,75";
- App::Application::Config()["DesktopFileName"] = "org.freecad.FreeCAD";
+ App::Application::Config()["DesktopFileName"] = "net.kindredsystems.KindredCreate";
try {
// Init phase ===========================================================
diff --git a/src/Main/MainPy.cpp b/src/Main/MainPy.cpp
index 1be1d0d364..c6cffd2369 100644
--- a/src/Main/MainPy.cpp
+++ b/src/Main/MainPy.cpp
@@ -80,8 +80,8 @@ BOOL APIENTRY DllMain(HANDLE hModule, DWORD ul_reason_for_call, LPVOID /*lpReser
PyMOD_INIT_FUNC(FreeCAD)
{
// Init phase ===========================================================
- App::Application::Config()["ExeName"] = "FreeCAD";
- App::Application::Config()["ExeVendor"] = "FreeCAD";
+ App::Application::Config()["ExeName"] = "Kindred Create";
+ App::Application::Config()["ExeVendor"] = "Kindred Systems LLC";
App::Application::Config()["AppDataSkipVendor"] = "true";
QByteArray path;
diff --git a/src/Main/freecad.rc.cmake b/src/Main/freecad.rc.cmake
index d0ab6d261f..467d4dbf92 100644
--- a/src/Main/freecad.rc.cmake
+++ b/src/Main/freecad.rc.cmake
@@ -11,7 +11,7 @@
// remains consistent on all systems.
IDI_ICON1 ICON DISCARDABLE "icon.ico"
-// File info for the FreeCAD.exe
+// File info for the kindred-create.exe
//
1 VERSIONINFO
FILEVERSION ${PACKAGE_VERSION_MAJOR},${PACKAGE_VERSION_MINOR},${PACKAGE_VERSION_PATCH},${PACKAGE_BUILD_VERSION}
@@ -20,12 +20,12 @@ BEGIN
BEGIN
BLOCK "040904b0" // 409 stands for US English
BEGIN
- VALUE "CompanyName", "${PROJECT_NAME} Team"
- VALUE "FileDescription", "${PROJECT_NAME} main executable"
- VALUE "InternalName", "FreeCAD.exe"
- VALUE "LegalCopyright", "Copyright (C) 2022"
- VALUE "OriginalFilename", "FreeCAD.exe"
- VALUE "ProductName", "${PROJECT_NAME}"
+ VALUE "CompanyName", "Kindred Systems LLC"
+ VALUE "FileDescription", "Kindred Create - Parametric 3D CAD modeler"
+ VALUE "InternalName", "kindred-create.exe"
+ VALUE "LegalCopyright", "Copyright (C) 2025 Kindred Systems LLC"
+ VALUE "OriginalFilename", "kindred-create.exe"
+ VALUE "ProductName", "Kindred Create"
VALUE "ProductVersion", "${PACKAGE_VERSION}${PACKAGE_VERSION_SUFFIX}"
END
END
diff --git a/src/Main/freecadCmd.rc.cmake b/src/Main/freecadCmd.rc.cmake
index bc0d408d73..c62d2cdea7 100644
--- a/src/Main/freecadCmd.rc.cmake
+++ b/src/Main/freecadCmd.rc.cmake
@@ -11,7 +11,7 @@
// remains consistent on all systems.
IDI_ICON1 ICON DISCARDABLE "icon.ico"
-// File info for the FreeCADCmd.exe
+// File info for the kindred-create-cmd.exe
//
1 VERSIONINFO
FILEVERSION ${PACKAGE_VERSION_MAJOR},${PACKAGE_VERSION_MINOR},${PACKAGE_VERSION_PATCH},${PACKAGE_BUILD_VERSION}
@@ -20,12 +20,12 @@ BEGIN
BEGIN
BLOCK "040904b0" // 409 stands for US English
BEGIN
- VALUE "CompanyName", "${PROJECT_NAME} Team"
- VALUE "FileDescription", "${PROJECT_NAME} command line executable"
- VALUE "InternalName", "FreeCADCmd.exe"
- VALUE "LegalCopyright", "Copyright (C) 2022"
- VALUE "OriginalFilename", "FreeCADCmd.exe"
- VALUE "ProductName", "${PROJECT_NAME}"
+ VALUE "CompanyName", "Kindred Systems LLC"
+ VALUE "FileDescription", "Kindred Create command line executable"
+ VALUE "InternalName", "kindred-create-cmd.exe"
+ VALUE "LegalCopyright", "Copyright (C) 2025 Kindred Systems LLC"
+ VALUE "OriginalFilename", "kindred-create-cmd.exe"
+ VALUE "ProductName", "Kindred Create"
VALUE "ProductVersion", "${PACKAGE_VERSION}${PACKAGE_VERSION_SUFFIX}"
END
END
diff --git a/src/Mod/Assembly/App/AssemblyObject.cpp b/src/Mod/Assembly/App/AssemblyObject.cpp
index 42baf4469d..95e49d6c6f 100644
--- a/src/Mod/Assembly/App/AssemblyObject.cpp
+++ b/src/Mod/Assembly/App/AssemblyObject.cpp
@@ -165,9 +165,8 @@ int AssemblyObject::solve(bool enableRedo, bool updateJCS)
jointParts(joints);
- if (enableRedo) {
- savePlacementsForUndo();
- }
+ // Always save placements to enable orientation flip detection
+ savePlacementsForUndo();
try {
mbdAssembly->runPreDrag();
@@ -186,8 +185,22 @@ int AssemblyObject::solve(bool enableRedo, bool updateJCS)
return -1;
}
+ // Validate that the solve didn't cause any parts to flip orientation
+ if (!validateNewPlacements()) {
+ // Restore previous placements - the solve found an invalid configuration
+ undoSolve();
+ lastSolverStatus = -2;
+ updateSolveStatus();
+ return -2;
+ }
+
setNewPlacements();
+ // Clear undo history if the caller didn't want redo capability
+ if (!enableRedo) {
+ clearUndo();
+ }
+
redrawJointPlacements(joints);
updateSolveStatus();
@@ -480,8 +493,56 @@ bool AssemblyObject::validateNewPlacements()
}
}
- // TODO: We could do further tests
- // For example check if the joints connectors are correctly aligned.
+ // Check if any part has flipped orientation (rotation > 90 degrees from original)
+ // This prevents joints from "breaking" when the solver finds an alternate configuration
+ for (const auto& savedPair : previousPositions) {
+ App::DocumentObject* obj = savedPair.first;
+ if (!obj) {
+ continue;
+ }
+
+ auto it = objectPartMap.find(obj);
+ if (it == objectPartMap.end()) {
+ continue;
+ }
+
+ std::shared_ptr mbdPart = it->second.part;
+ if (!mbdPart) {
+ continue;
+ }
+
+ Base::Placement newPlacement = getMbdPlacement(mbdPart);
+ if (!it->second.offsetPlc.isIdentity()) {
+ newPlacement = newPlacement * it->second.offsetPlc;
+ }
+
+ const Base::Placement& oldPlc = savedPair.second;
+
+ // Calculate the rotation difference between old and new orientations
+ Base::Rotation oldRot = oldPlc.getRotation();
+ Base::Rotation newRot = newPlacement.getRotation();
+
+ // Get the relative rotation: how much did the part rotate?
+ Base::Rotation relativeRot = newRot * oldRot.inverse();
+
+ // Get the angle of this rotation
+ Base::Vector3d axis;
+ double angle;
+ relativeRot.getRawValue(axis, angle);
+
+ // If the part rotated more than 90 degrees, consider it a flip
+ // Use 91 degrees to allow for small numerical errors
+ constexpr double maxAngle = 91.0 * M_PI / 180.0;
+ if (std::abs(angle) > maxAngle) {
+ Base::Console().warning(
+ "Assembly : Ignoring bad solve, part (%s) flipped orientation (%.1f degrees).\n",
+ obj->getFullLabel(),
+ std::abs(angle) * 180.0 / M_PI
+ );
+ return false;
+ }
+ }
+
return true;
}
diff --git a/tests/assytest.20260126-040101.FCBak b/tests/assytest.20260126-040101.FCBak
new file mode 100644
index 0000000000..7d6bc0404f
Binary files /dev/null and b/tests/assytest.20260126-040101.FCBak differ
diff --git a/tests/assytest.FCStd b/tests/assytest.FCStd
new file mode 100644
index 0000000000..204b7f24b5
Binary files /dev/null and b/tests/assytest.FCStd differ
diff --git a/tests/assytestpart.FCStd b/tests/assytestpart.FCStd
new file mode 100644
index 0000000000..a51de66e30
Binary files /dev/null and b/tests/assytestpart.FCStd differ