# custom_template_khmer/models/custom_theme_config.py from odoo import models, fields, api import base64 import io import logging _logger = logging.getLogger(__name__) try: from fontTools.ttLib import TTFont HAS_FONTTOOLS = True except ImportError: HAS_FONTTOOLS = False _logger.warning("fontTools library not installed. Auto-font-name detection will not work.") class CustomThemeConfig(models.Model): _name = 'custom.theme.config' _description = 'Custom Theme Configuration (Singleton)' name = fields.Char(default='Main Configuration') # Binary Fields font_file = fields.Binary(string="Custom Font File (.ttf)", attachment=True) menu_bg_image = fields.Binary(string="Menu Background Image", attachment=True) # Simple Fields font_name = fields.Char(string="Font Family Name") menu_bg_color = fields.Char(string="Menu Background Color", default="#714B67") is_responsive = fields.Boolean(string="Enable Mobile Responsiveness", default=True) @api.onchange('font_file') def _onchange_font_file(self): """Automatically extract font name when file is uploaded""" if self.font_file and HAS_FONTTOOLS: try: # Decode the base64 file font_data = base64.b64decode(self.font_file) font_io = io.BytesIO(font_data) # Open font with fontTools font = TTFont(font_io) # Get the 'name' table name_table = font['name'] # Try to find the PostScript Name (ID 6) or Full Name (ID 4) # Priority: PostScript Name > Full Name > Font Family font_name = None for record in name_table.names: # nameID 6 = PostScript Name (Best for CSS) if record.nameID == 6: font_name = str(record) break # nameID 4 = Full Name elif record.nameID == 4 and not font_name: font_name = str(record) # Fallback to Family Name (ID 1) if others missing if not font_name: for record in name_table.names: if record.nameID == 1: font_name = str(record) break if font_name: self.font_name = font_name return { 'notification': { 'type': 'success', 'message': f'Font detected: {font_name}', 'sticky': False, } } else: return { 'notification': { 'type': 'warning', 'message': 'Could not detect font name. Please enter manually.', 'sticky': True, } } except Exception as e: _logger.error(f"Error extracting font name: {e}") return { 'notification': { 'type': 'danger', 'message': f'Error reading font file: {str(e)}', 'sticky': True, } } elif not HAS_FONTTOOLS: return { 'notification': { 'type': 'warning', 'message': 'Install "fonttools" library to auto-detect font names.', 'sticky': True, } } @api.model def get_config(self): return self.search([], limit=1) # ✅ ADD THIS FIELD to store the original filename font_file_name = fields.Char(string="Original Filename", compute='_compute_font_file_name', store=True) font_file = fields.Binary(string="Custom Font File (.ttf)", attachment=True) @api.depends('font_file') def _compute_font_file_name(self): for record in self: if record.font_file: record.font_file_name = "font_uploaded.ttf" else: record.font_file_name = False