update databasing system with minimum API, schema parsing and FreeCAD
integration
8
pkg/freecad/Init.py
Normal file
@@ -0,0 +1,8 @@
|
||||
"""Silo FreeCAD Workbench - Console initialization.
|
||||
|
||||
This file is loaded when FreeCAD starts (even in console mode).
|
||||
The GUI-specific initialization is in InitGui.py.
|
||||
"""
|
||||
|
||||
# No console-only initialization needed for Silo workbench
|
||||
# All functionality requires the GUI
|
||||
109
pkg/freecad/InitGui.py
Normal file
@@ -0,0 +1,109 @@
|
||||
"""Silo FreeCAD Workbench - Item database integration."""
|
||||
|
||||
import os
|
||||
|
||||
import FreeCAD
|
||||
import FreeCADGui
|
||||
|
||||
FreeCAD.Console.PrintMessage("Silo InitGui.py loading...\n")
|
||||
|
||||
|
||||
class SiloWorkbench(FreeCADGui.Workbench):
|
||||
"""Silo workbench for item database integration."""
|
||||
|
||||
MenuText = "Silo"
|
||||
ToolTip = "Item database and part management"
|
||||
Icon = ""
|
||||
|
||||
def __init__(self):
|
||||
# Find icon path
|
||||
try:
|
||||
locations = [
|
||||
os.path.join(FreeCAD.getUserAppDataDir(), "Mod", "Silo"),
|
||||
os.path.join(FreeCAD.getResourceDir(), "Mod", "Silo"),
|
||||
os.path.expanduser(
|
||||
"~/.var/app/org.freecad.FreeCAD/data/FreeCAD/Mod/Silo"
|
||||
),
|
||||
os.path.expanduser("~/.FreeCAD/Mod/Silo"),
|
||||
]
|
||||
for silo_dir in locations:
|
||||
icon_path = os.path.join(silo_dir, "resources", "icons", "silo.svg")
|
||||
if os.path.exists(icon_path):
|
||||
self.__class__.Icon = icon_path
|
||||
FreeCAD.Console.PrintMessage("Silo icon: " + icon_path + "\n")
|
||||
break
|
||||
except Exception as e:
|
||||
FreeCAD.Console.PrintWarning("Silo icon error: " + str(e) + "\n")
|
||||
|
||||
def Initialize(self):
|
||||
"""Called when workbench is first activated."""
|
||||
import silo_commands
|
||||
|
||||
self.toolbar_commands = [
|
||||
"Silo_Open",
|
||||
"Silo_New",
|
||||
"Silo_Save",
|
||||
"Silo_Commit",
|
||||
"Silo_Pull",
|
||||
"Silo_Push",
|
||||
"Silo_Info",
|
||||
]
|
||||
|
||||
self.appendToolbar("Silo", self.toolbar_commands)
|
||||
self.appendMenu("Silo", self.toolbar_commands)
|
||||
|
||||
def Activated(self):
|
||||
"""Called when workbench is activated."""
|
||||
FreeCAD.Console.PrintMessage("Silo workbench activated\n")
|
||||
FreeCAD.Console.PrintMessage(
|
||||
" API: SILO_API_URL (default: http://localhost:8080/api)\n"
|
||||
)
|
||||
FreeCAD.Console.PrintMessage(
|
||||
" Projects: SILO_PROJECTS_DIR (default: ~/projects)\n"
|
||||
)
|
||||
self._show_shortcut_recommendations()
|
||||
|
||||
def Deactivated(self):
|
||||
pass
|
||||
|
||||
def GetClassName(self):
|
||||
return "Gui::PythonWorkbench"
|
||||
|
||||
def _show_shortcut_recommendations(self):
|
||||
"""Show keyboard shortcut recommendations dialog on first activation."""
|
||||
try:
|
||||
param_group = FreeCAD.ParamGet(
|
||||
"User parameter:BaseApp/Preferences/Mod/Silo"
|
||||
)
|
||||
if param_group.GetBool("ShortcutsShown", False):
|
||||
return
|
||||
param_group.SetBool("ShortcutsShown", True)
|
||||
|
||||
from PySide import QtGui
|
||||
|
||||
msg = """<h3>Welcome to Silo Workbench!</h3>
|
||||
<p>For the best experience, set up these keyboard shortcuts:</p>
|
||||
<table style="margin: 10px 0;">
|
||||
<tr><td><b>Ctrl+O</b></td><td> - </td><td>Silo_Open (Search & Open)</td></tr>
|
||||
<tr><td><b>Ctrl+N</b></td><td> - </td><td>Silo_New (Register new item)</td></tr>
|
||||
<tr><td><b>Ctrl+S</b></td><td> - </td><td>Silo_Save (Save & upload)</td></tr>
|
||||
<tr><td><b>Ctrl+Shift+S</b></td><td> - </td><td>Silo_Commit (Save with comment)</td></tr>
|
||||
</table>
|
||||
<p><b>To set shortcuts:</b> Tools > Customize > Keyboard</p>
|
||||
<p style="color: #888;">This message appears once.</p>"""
|
||||
|
||||
dialog = QtGui.QMessageBox()
|
||||
dialog.setWindowTitle("Silo Keyboard Shortcuts")
|
||||
dialog.setTextFormat(QtGui.Qt.RichText)
|
||||
dialog.setText(msg)
|
||||
dialog.setIcon(QtGui.QMessageBox.Information)
|
||||
dialog.addButton("Set Up Now", QtGui.QMessageBox.AcceptRole)
|
||||
dialog.addButton("Later", QtGui.QMessageBox.RejectRole)
|
||||
if dialog.exec_() == 0:
|
||||
FreeCADGui.runCommand("Std_DlgCustomize", 0)
|
||||
except Exception as e:
|
||||
FreeCAD.Console.PrintWarning("Silo shortcuts dialog: " + str(e) + "\n")
|
||||
|
||||
|
||||
FreeCADGui.addWorkbench(SiloWorkbench())
|
||||
FreeCAD.Console.PrintMessage("Silo workbench registered\n")
|
||||
15
pkg/freecad/package.xml
Normal file
@@ -0,0 +1,15 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<package format="1" xmlns="https://wiki.freecad.org/Package_Metadata">
|
||||
<name>Silo</name>
|
||||
<description>Item database and part management workbench</description>
|
||||
<version>0.1.0</version>
|
||||
<maintainer email="info@kindredsystems.io">Kindred Systems</maintainer>
|
||||
<license file="LICENSE">MIT</license>
|
||||
<url type="repository">https://github.com/kindredsystems/silo</url>
|
||||
<content>
|
||||
<workbench>
|
||||
<classname>SiloWorkbench</classname>
|
||||
<subdirectory>./</subdirectory>
|
||||
</workbench>
|
||||
</content>
|
||||
</package>
|
||||
8
pkg/freecad/resources/icons/silo-commit.svg
Normal file
@@ -0,0 +1,8 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="#cba6f7" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
||||
<!-- Git commit style -->
|
||||
<circle cx="12" cy="12" r="4" fill="#313244" stroke="#a6e3a1"/>
|
||||
<line x1="12" y1="2" x2="12" y2="8" stroke="#cba6f7"/>
|
||||
<line x1="12" y1="16" x2="12" y2="22" stroke="#cba6f7"/>
|
||||
<!-- Checkmark inside -->
|
||||
<polyline points="9.5 12 11 13.5 14.5 10" stroke="#a6e3a1" stroke-width="1.5" fill="none"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 493 B |
6
pkg/freecad/resources/icons/silo-info.svg
Normal file
@@ -0,0 +1,6 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="#cba6f7" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
||||
<!-- Info circle -->
|
||||
<circle cx="12" cy="12" r="10" fill="#313244"/>
|
||||
<line x1="12" y1="16" x2="12" y2="12" stroke="#89dceb" stroke-width="2"/>
|
||||
<circle cx="12" cy="8" r="0.5" fill="#89dceb" stroke="#89dceb"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 377 B |
8
pkg/freecad/resources/icons/silo-new.svg
Normal file
@@ -0,0 +1,8 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="#cba6f7" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
||||
<!-- Document with plus -->
|
||||
<path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z" fill="#313244"/>
|
||||
<polyline points="14 2 14 8 20 8" fill="#45475a" stroke="#cba6f7"/>
|
||||
<!-- Plus sign -->
|
||||
<line x1="12" y1="11" x2="12" y2="17" stroke="#a6e3a1" stroke-width="2"/>
|
||||
<line x1="9" y1="14" x2="15" y2="14" stroke="#a6e3a1" stroke-width="2"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 521 B |
8
pkg/freecad/resources/icons/silo-open.svg
Normal file
@@ -0,0 +1,8 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="#cba6f7" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
||||
<!-- Folder open icon -->
|
||||
<path d="M22 19a2 2 0 0 1-2 2H4a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h5l2 3h9a2 2 0 0 1 2 2z" fill="#313244"/>
|
||||
<path d="M2 10h20" stroke="#6c7086"/>
|
||||
<!-- Search magnifier -->
|
||||
<circle cx="17" cy="15" r="3" fill="#1e1e2e" stroke="#a6e3a1" stroke-width="1.5"/>
|
||||
<line x1="19.5" y1="17.5" x2="22" y2="20" stroke="#a6e3a1" stroke-width="1.5"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 529 B |
7
pkg/freecad/resources/icons/silo-pull.svg
Normal file
@@ -0,0 +1,7 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="#cba6f7" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
||||
<!-- Cloud -->
|
||||
<path d="M18 10h-1.26A8 8 0 1 0 9 20h9a5 5 0 0 0 0-10z" fill="#313244"/>
|
||||
<!-- Download arrow -->
|
||||
<path d="M12 13v5m0 0l-2-2m2 2l2-2" stroke="#89b4fa" stroke-width="2"/>
|
||||
<line x1="12" y1="9" x2="12" y2="13" stroke="#89b4fa" stroke-width="2"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 428 B |
7
pkg/freecad/resources/icons/silo-push.svg
Normal file
@@ -0,0 +1,7 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="#cba6f7" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
||||
<!-- Cloud -->
|
||||
<path d="M18 10h-1.26A8 8 0 1 0 9 20h9a5 5 0 0 0 0-10z" fill="#313244"/>
|
||||
<!-- Upload arrow -->
|
||||
<path d="M12 18v-5m0 0l-2 2m2-2l2 2" stroke="#a6e3a1" stroke-width="2"/>
|
||||
<line x1="12" y1="13" x2="12" y2="9" stroke="#a6e3a1" stroke-width="2"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 427 B |
8
pkg/freecad/resources/icons/silo-save.svg
Normal file
@@ -0,0 +1,8 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="#cba6f7" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
||||
<!-- Floppy disk -->
|
||||
<path d="M19 21H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h11l5 5v11a2 2 0 0 1-2 2z" fill="#313244"/>
|
||||
<polyline points="17 21 17 13 7 13 7 21" fill="#45475a" stroke="#cba6f7"/>
|
||||
<polyline points="7 3 7 8 15 8" fill="#45475a" stroke="#6c7086"/>
|
||||
<!-- Upload arrow -->
|
||||
<path d="M12 17v-4m0 0l-2 2m2-2l2 2" stroke="#a6e3a1" stroke-width="1.5"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 523 B |
28
pkg/freecad/resources/icons/silo.svg
Normal file
@@ -0,0 +1,28 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 64 64" fill="none">
|
||||
<!-- Silo icon - grain silo with database/sync symbolism -->
|
||||
<!-- Uses Catppuccin Mocha colors -->
|
||||
|
||||
<!-- Silo body (cylindrical tower) -->
|
||||
<path d="M16 20 L16 52 Q16 56 32 56 Q48 56 48 52 L48 20"
|
||||
fill="#313244" stroke="#cba6f7" stroke-width="2"/>
|
||||
|
||||
<!-- Silo dome/roof -->
|
||||
<ellipse cx="32" cy="20" rx="16" ry="6" fill="#45475a" stroke="#cba6f7" stroke-width="2"/>
|
||||
<path d="M24 14 Q32 4 40 14" fill="none" stroke="#cba6f7" stroke-width="2" stroke-linecap="round"/>
|
||||
<line x1="32" y1="6" x2="32" y2="14" stroke="#cba6f7" stroke-width="2" stroke-linecap="round"/>
|
||||
|
||||
<!-- Horizontal bands (like database rows / silo rings) -->
|
||||
<ellipse cx="32" cy="28" rx="15" ry="4" fill="none" stroke="#6c7086" stroke-width="1.5"/>
|
||||
<ellipse cx="32" cy="36" rx="15" ry="4" fill="none" stroke="#6c7086" stroke-width="1.5"/>
|
||||
<ellipse cx="32" cy="44" rx="15" ry="4" fill="none" stroke="#6c7086" stroke-width="1.5"/>
|
||||
|
||||
<!-- Base ellipse -->
|
||||
<ellipse cx="32" cy="52" rx="16" ry="4" fill="none" stroke="#cba6f7" stroke-width="2"/>
|
||||
|
||||
<!-- Sync arrows (circular) - represents upload/download -->
|
||||
<g transform="translate(44, 8)">
|
||||
<circle cx="8" cy="8" r="7" fill="#1e1e2e" stroke="#a6e3a1" stroke-width="1.5"/>
|
||||
<path d="M5 6 L8 3 L11 6 M8 3 L8 10" stroke="#a6e3a1" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
<path d="M11 10 L8 13 L5 10 M8 13 L8 10" stroke="#a6e3a1" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round" opacity="0.6"/>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.5 KiB |