diff --git a/CMakeLists.txt b/CMakeLists.txt index a9e68dc1aa..9cbf373c90 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -48,17 +48,37 @@ 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) -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) +# 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 "0") +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 "") # either "dev" for development snapshot or "" (empty string) +set(PACKAGE_BUILD_VERSION "0") # used when the same version will be re-released 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/banner-logo-light.png b/banner-logo-light.png new file mode 100644 index 0000000000..92a005ef1b Binary files /dev/null and b/banner-logo-light.png differ 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/kindred-create.desktop b/resources/kindred-create.desktop new file mode 100644 index 0000000000..c3b942a39d --- /dev/null +++ b/resources/kindred-create.desktop @@ -0,0 +1,13 @@ +[Desktop Entry] +Name=Kindred Create +GenericName=CAD Application +Comment=Parametric 3D CAD modeler based on FreeCAD +Exec=kindred-create %F +Icon=kindred-create +Terminal=false +Type=Application +Categories=Graphics;Science;Engineering; +MimeType=application/x-extension-fcstd; +Keywords=CAD;3D;modeling;engineering;design;parametric; +StartupNotify=true +StartupWMClass=KindredCreate diff --git a/resources/kindred-create.xml b/resources/kindred-create.xml new file mode 100644 index 0000000000..8f310e4097 --- /dev/null +++ b/resources/kindred-create.xml @@ -0,0 +1,11 @@ + + + + Kindred Create Document + Kindred Create Document + + + + + + 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