|
"""
|
|
مولد الأيقونات لنظام إدارة المناقصات
|
|
"""
|
|
|
|
import os
|
|
import math
|
|
from PIL import Image, ImageDraw, ImageFont
|
|
|
|
class IconGenerator:
|
|
"""فئة مولد الأيقونات"""
|
|
|
|
def __init__(self):
|
|
"""تهيئة مولد الأيقونات"""
|
|
|
|
self.icons_dir = os.path.join(os.path.dirname(os.path.dirname(os.path.abspath(__file__))), "assets", "icons")
|
|
|
|
|
|
os.makedirs(self.icons_dir, exist_ok=True)
|
|
|
|
|
|
self.icon_size = (64, 64)
|
|
|
|
|
|
self.colors = {
|
|
"primary": "#2980B9",
|
|
"secondary": "#1ABC9C",
|
|
"accent": "#9B59B6",
|
|
"warning": "#F39C12",
|
|
"error": "#E74C3C",
|
|
"success": "#2ECC71",
|
|
"white": "#FFFFFF",
|
|
"black": "#333333",
|
|
"gray": "#95A5A6"
|
|
}
|
|
|
|
def generate_icon(self, name, color=None, background_color=None, size=None):
|
|
"""توليد أيقونة"""
|
|
|
|
if color is None:
|
|
color = self.colors["primary"]
|
|
|
|
if background_color is None:
|
|
background_color = self.colors["white"]
|
|
|
|
|
|
if size is None:
|
|
size = self.icon_size
|
|
|
|
|
|
icon = Image.new("RGBA", size, background_color)
|
|
draw = ImageDraw.Draw(icon)
|
|
|
|
|
|
if name == "dashboard":
|
|
self._draw_dashboard_icon(draw, size, color)
|
|
elif name == "projects":
|
|
self._draw_projects_icon(draw, size, color)
|
|
elif name == "documents":
|
|
self._draw_documents_icon(draw, size, color)
|
|
elif name == "pricing":
|
|
self._draw_pricing_icon(draw, size, color)
|
|
elif name == "resources":
|
|
self._draw_resources_icon(draw, size, color)
|
|
elif name == "risk":
|
|
self._draw_risk_icon(draw, size, color)
|
|
elif name == "reports":
|
|
self._draw_reports_icon(draw, size, color)
|
|
elif name == "ai":
|
|
self._draw_ai_icon(draw, size, color)
|
|
elif name == "settings":
|
|
self._draw_settings_icon(draw, size, color)
|
|
elif name == "logout":
|
|
self._draw_logout_icon(draw, size, color)
|
|
elif name == "search":
|
|
self._draw_search_icon(draw, size, color)
|
|
elif name == "add":
|
|
self._draw_add_icon(draw, size, color)
|
|
elif name == "upload":
|
|
self._draw_upload_icon(draw, size, color)
|
|
elif name == "import":
|
|
self._draw_import_icon(draw, size, color)
|
|
elif name == "export":
|
|
self._draw_export_icon(draw, size, color)
|
|
elif name == "save":
|
|
self._draw_save_icon(draw, size, color)
|
|
else:
|
|
|
|
self._draw_default_icon(draw, size, color)
|
|
|
|
|
|
icon_path = os.path.join(self.icons_dir, f"{name}.png")
|
|
icon.save(icon_path)
|
|
|
|
return icon_path
|
|
|
|
def _draw_dashboard_icon(self, draw, size, color):
|
|
"""رسم أيقونة لوحة التحكم"""
|
|
width, height = size
|
|
padding = width // 8
|
|
|
|
|
|
box_size = (width - 3 * padding) // 2
|
|
|
|
|
|
draw.rectangle(
|
|
[(padding, padding), (padding + box_size, padding + box_size)],
|
|
fill=color
|
|
)
|
|
|
|
|
|
draw.rectangle(
|
|
[(2 * padding + box_size, padding), (2 * padding + 2 * box_size, padding + box_size)],
|
|
fill=color
|
|
)
|
|
|
|
|
|
draw.rectangle(
|
|
[(padding, 2 * padding + box_size), (padding + box_size, 2 * padding + 2 * box_size)],
|
|
fill=color
|
|
)
|
|
|
|
|
|
draw.rectangle(
|
|
[(2 * padding + box_size, 2 * padding + box_size), (2 * padding + 2 * box_size, 2 * padding + 2 * box_size)],
|
|
fill=color
|
|
)
|
|
|
|
def _draw_projects_icon(self, draw, size, color):
|
|
"""رسم أيقونة المشاريع"""
|
|
width, height = size
|
|
padding = width // 8
|
|
|
|
|
|
folder_points = [
|
|
(padding, height // 3),
|
|
(width // 3, height // 3),
|
|
(width // 2, padding),
|
|
(width - padding, padding),
|
|
(width - padding, height - padding),
|
|
(padding, height - padding)
|
|
]
|
|
draw.polygon(folder_points, fill=color)
|
|
|
|
def _draw_documents_icon(self, draw, size, color):
|
|
"""رسم أيقونة المستندات"""
|
|
width, height = size
|
|
padding = width // 8
|
|
|
|
|
|
draw.rectangle(
|
|
[(padding, padding), (width - padding, height - padding)],
|
|
fill=color
|
|
)
|
|
|
|
|
|
line_padding = height // 8
|
|
line_height = height // 20
|
|
for i in range(4):
|
|
y = padding + line_padding + i * (line_height + line_padding)
|
|
draw.rectangle(
|
|
[(padding * 2, y), (width - padding * 2, y + line_height)],
|
|
fill=self.colors["white"]
|
|
)
|
|
|
|
def _draw_pricing_icon(self, draw, size, color):
|
|
"""رسم أيقونة التسعير"""
|
|
width, height = size
|
|
padding = width // 8
|
|
|
|
|
|
center_x = width // 2
|
|
center_y = height // 2
|
|
radius = min(width, height) // 3
|
|
|
|
|
|
draw.ellipse(
|
|
[(center_x - radius, center_y - radius), (center_x + radius, center_y + radius)],
|
|
fill=color
|
|
)
|
|
|
|
|
|
line_width = radius // 4
|
|
draw.rectangle(
|
|
[(center_x - line_width // 2, center_y - radius * 2 // 3), (center_x + line_width // 2, center_y + radius * 2 // 3)],
|
|
fill=self.colors["white"]
|
|
)
|
|
draw.rectangle(
|
|
[(center_x - radius * 2 // 3, center_y - line_width // 2), (center_x + radius * 2 // 3, center_y + line_width // 2)],
|
|
fill=self.colors["white"]
|
|
)
|
|
|
|
def _draw_resources_icon(self, draw, size, color):
|
|
"""رسم أيقونة الموارد"""
|
|
width, height = size
|
|
padding = width // 8
|
|
|
|
|
|
center_x = width // 2
|
|
center_y = height // 2
|
|
radius = min(width, height) // 10
|
|
|
|
|
|
head_center_y = center_y - radius * 2
|
|
draw.ellipse(
|
|
[(center_x - radius, head_center_y - radius), (center_x + radius, head_center_y + radius)],
|
|
fill=color
|
|
)
|
|
draw.polygon(
|
|
[
|
|
(center_x, head_center_y + radius),
|
|
(center_x - radius * 2, center_y + radius * 3),
|
|
(center_x + radius * 2, center_y + radius * 3)
|
|
],
|
|
fill=color
|
|
)
|
|
|
|
|
|
left_center_x = center_x - radius * 4
|
|
head_center_y = center_y - radius * 2
|
|
draw.ellipse(
|
|
[(left_center_x - radius, head_center_y - radius), (left_center_x + radius, head_center_y + radius)],
|
|
fill=color
|
|
)
|
|
draw.polygon(
|
|
[
|
|
(left_center_x, head_center_y + radius),
|
|
(left_center_x - radius * 2, center_y + radius * 3),
|
|
(left_center_x + radius * 2, center_y + radius * 3)
|
|
],
|
|
fill=color
|
|
)
|
|
|
|
|
|
right_center_x = center_x + radius * 4
|
|
head_center_y = center_y - radius * 2
|
|
draw.ellipse(
|
|
[(right_center_x - radius, head_center_y - radius), (right_center_x + radius, head_center_y + radius)],
|
|
fill=color
|
|
)
|
|
draw.polygon(
|
|
[
|
|
(right_center_x, head_center_y + radius),
|
|
(right_center_x - radius * 2, center_y + radius * 3),
|
|
(right_center_x + radius * 2, center_y + radius * 3)
|
|
],
|
|
fill=color
|
|
)
|
|
|
|
def _draw_risk_icon(self, draw, size, color):
|
|
"""رسم أيقونة المخاطر"""
|
|
width, height = size
|
|
padding = width // 8
|
|
|
|
|
|
draw.polygon(
|
|
[
|
|
(width // 2, padding),
|
|
(padding, height - padding),
|
|
(width - padding, height - padding)
|
|
],
|
|
fill=color
|
|
)
|
|
|
|
|
|
exclamation_width = width // 10
|
|
exclamation_height = height // 3
|
|
center_x = width // 2
|
|
center_y = height // 2
|
|
|
|
|
|
draw.rectangle(
|
|
[
|
|
(center_x - exclamation_width // 2, center_y - exclamation_height),
|
|
(center_x + exclamation_width // 2, center_y)
|
|
],
|
|
fill=self.colors["white"]
|
|
)
|
|
|
|
|
|
dot_radius = exclamation_width
|
|
draw.ellipse(
|
|
[
|
|
(center_x - dot_radius // 2, center_y + exclamation_height // 4),
|
|
(center_x + dot_radius // 2, center_y + exclamation_height // 4 + dot_radius)
|
|
],
|
|
fill=self.colors["white"]
|
|
)
|
|
|
|
def _draw_reports_icon(self, draw, size, color):
|
|
"""رسم أيقونة التقارير"""
|
|
width, height = size
|
|
padding = width // 8
|
|
|
|
|
|
draw.rectangle(
|
|
[(padding, padding), (width - padding, height - padding)],
|
|
fill=color
|
|
)
|
|
|
|
|
|
chart_padding = width // 6
|
|
chart_width = width - 2 * chart_padding
|
|
chart_height = height // 2
|
|
chart_bottom = height - chart_padding
|
|
|
|
|
|
bar_width = chart_width // 5
|
|
bar_spacing = bar_width // 2
|
|
|
|
for i in range(4):
|
|
bar_height = (i + 1) * chart_height // 4
|
|
bar_x = chart_padding + i * (bar_width + bar_spacing)
|
|
bar_y = chart_bottom - bar_height
|
|
|
|
draw.rectangle(
|
|
[(bar_x, bar_y), (bar_x + bar_width, chart_bottom)],
|
|
fill=self.colors["white"]
|
|
)
|
|
|
|
def _draw_ai_icon(self, draw, size, color):
|
|
"""رسم أيقونة الذكاء الاصطناعي"""
|
|
width, height = size
|
|
padding = width // 8
|
|
|
|
|
|
center_x = width // 2
|
|
center_y = height // 2
|
|
brain_width = width - 2 * padding
|
|
brain_height = height - 2 * padding
|
|
|
|
|
|
draw.ellipse(
|
|
[(center_x - brain_width // 2, center_y - brain_height // 2), (center_x + brain_width // 2, center_y + brain_height // 2)],
|
|
fill=color
|
|
)
|
|
|
|
|
|
line_width = brain_width // 10
|
|
line_spacing = brain_width // 8
|
|
|
|
for i in range(-2, 3):
|
|
y = center_y + i * line_spacing
|
|
draw.line(
|
|
[(center_x - brain_width // 3, y), (center_x + brain_width // 3, y)],
|
|
fill=self.colors["white"],
|
|
width=line_width
|
|
)
|
|
|
|
def _draw_settings_icon(self, draw, size, color):
|
|
"""رسم أيقونة الإعدادات"""
|
|
width, height = size
|
|
padding = width // 8
|
|
|
|
|
|
center_x = width // 2
|
|
center_y = height // 2
|
|
outer_radius = min(width, height) // 2 - padding
|
|
inner_radius = outer_radius * 2 // 3
|
|
|
|
|
|
draw.ellipse(
|
|
[(center_x - inner_radius, center_y - inner_radius), (center_x + inner_radius, center_y + inner_radius)],
|
|
fill=color
|
|
)
|
|
|
|
|
|
num_teeth = 8
|
|
tooth_width = outer_radius - inner_radius
|
|
|
|
for i in range(num_teeth):
|
|
angle = 2 * math.pi * i / num_teeth
|
|
tooth_center_x = center_x + (inner_radius + tooth_width // 2) * math.cos(angle)
|
|
tooth_center_y = center_y + (inner_radius + tooth_width // 2) * math.sin(angle)
|
|
|
|
draw.ellipse(
|
|
[
|
|
(tooth_center_x - tooth_width // 2, tooth_center_y - tooth_width // 2),
|
|
(tooth_center_x + tooth_width // 2, tooth_center_y + tooth_width // 2)
|
|
],
|
|
fill=color
|
|
)
|
|
|
|
def _draw_logout_icon(self, draw, size, color):
|
|
"""رسم أيقونة تسجيل الخروج"""
|
|
width, height = size
|
|
padding = width // 8
|
|
|
|
|
|
arrow_width = width - 2 * padding
|
|
arrow_height = height - 2 * padding
|
|
|
|
|
|
draw.rectangle(
|
|
[(padding, padding), (width // 2, height - padding)],
|
|
fill=color
|
|
)
|
|
|
|
|
|
arrow_points = [
|
|
(width // 2, height // 3),
|
|
(width - padding, height // 2),
|
|
(width // 2, height * 2 // 3),
|
|
(width // 2, height // 2 + height // 8),
|
|
(width // 2 + width // 4, height // 2 + height // 8),
|
|
(width // 2 + width // 4, height // 2 - height // 8),
|
|
(width // 2, height // 2 - height // 8)
|
|
]
|
|
draw.polygon(arrow_points, fill=color)
|
|
|
|
def _draw_search_icon(self, draw, size, color):
|
|
"""رسم أيقونة البحث"""
|
|
width, height = size
|
|
padding = width // 8
|
|
|
|
|
|
center_x = width // 2 - padding
|
|
center_y = height // 2 - padding
|
|
radius = min(width, height) // 3
|
|
|
|
draw.ellipse(
|
|
[(center_x - radius, center_y - radius), (center_x + radius, center_y + radius)],
|
|
outline=color,
|
|
width=radius // 3
|
|
)
|
|
|
|
|
|
handle_width = radius // 3
|
|
handle_length = radius
|
|
handle_angle = math.pi / 4
|
|
|
|
handle_start_x = center_x + radius * math.cos(handle_angle)
|
|
handle_start_y = center_y + radius * math.sin(handle_angle)
|
|
handle_end_x = handle_start_x + handle_length * math.cos(handle_angle)
|
|
handle_end_y = handle_start_y + handle_length * math.sin(handle_angle)
|
|
|
|
draw.line(
|
|
[(handle_start_x, handle_start_y), (handle_end_x, handle_end_y)],
|
|
fill=color,
|
|
width=handle_width
|
|
)
|
|
|
|
def _draw_add_icon(self, draw, size, color):
|
|
"""رسم أيقونة الإضافة"""
|
|
width, height = size
|
|
padding = width // 8
|
|
|
|
|
|
center_x = width // 2
|
|
center_y = height // 2
|
|
line_length = min(width, height) - 2 * padding
|
|
line_width = line_length // 5
|
|
|
|
|
|
draw.rectangle(
|
|
[
|
|
(center_x - line_length // 2, center_y - line_width // 2),
|
|
(center_x + line_length // 2, center_y + line_width // 2)
|
|
],
|
|
fill=color
|
|
)
|
|
|
|
|
|
draw.rectangle(
|
|
[
|
|
(center_x - line_width // 2, center_y - line_length // 2),
|
|
(center_x + line_width // 2, center_y + line_length // 2)
|
|
],
|
|
fill=color
|
|
)
|
|
|
|
def _draw_upload_icon(self, draw, size, color):
|
|
"""رسم أيقونة التحميل"""
|
|
width, height = size
|
|
padding = width // 8
|
|
|
|
|
|
center_x = width // 2
|
|
arrow_width = width // 3
|
|
arrow_height = height // 2
|
|
|
|
|
|
arrow_points = [
|
|
(center_x, padding),
|
|
(center_x + arrow_width, padding + arrow_height),
|
|
(center_x + arrow_width // 2, padding + arrow_height),
|
|
(center_x + arrow_width // 2, height - padding),
|
|
(center_x - arrow_width // 2, height - padding),
|
|
(center_x - arrow_width // 2, padding + arrow_height),
|
|
(center_x - arrow_width, padding + arrow_height)
|
|
]
|
|
draw.polygon(arrow_points, fill=color)
|
|
|
|
def _draw_import_icon(self, draw, size, color):
|
|
"""رسم أيقونة الاستيراد"""
|
|
width, height = size
|
|
padding = width // 8
|
|
|
|
|
|
center_y = height // 2
|
|
arrow_width = width // 2
|
|
arrow_height = height // 3
|
|
|
|
|
|
draw.rectangle(
|
|
[(width - padding - arrow_width // 2, padding), (width - padding, height - padding)],
|
|
fill=color
|
|
)
|
|
|
|
|
|
arrow_points = [
|
|
(padding, center_y),
|
|
(padding + arrow_width, center_y - arrow_height // 2),
|
|
(padding + arrow_width, center_y - arrow_height // 4),
|
|
(width - padding - arrow_width // 2, center_y - arrow_height // 4),
|
|
(width - padding - arrow_width // 2, center_y + arrow_height // 4),
|
|
(padding + arrow_width, center_y + arrow_height // 4),
|
|
(padding + arrow_width, center_y + arrow_height // 2)
|
|
]
|
|
draw.polygon(arrow_points, fill=color)
|
|
|
|
def _draw_export_icon(self, draw, size, color):
|
|
"""رسم أيقونة التصدير"""
|
|
width, height = size
|
|
padding = width // 8
|
|
|
|
|
|
center_y = height // 2
|
|
arrow_width = width // 2
|
|
arrow_height = height // 3
|
|
|
|
|
|
draw.rectangle(
|
|
[(padding, padding), (padding + arrow_width // 2, height - padding)],
|
|
fill=color
|
|
)
|
|
|
|
|
|
arrow_points = [
|
|
(width - padding, center_y),
|
|
(width - padding - arrow_width, center_y - arrow_height // 2),
|
|
(width - padding - arrow_width, center_y - arrow_height // 4),
|
|
(padding + arrow_width // 2, center_y - arrow_height // 4),
|
|
(padding + arrow_width // 2, center_y + arrow_height // 4),
|
|
(width - padding - arrow_width, center_y + arrow_height // 4),
|
|
(width - padding - arrow_width, center_y + arrow_height // 2)
|
|
]
|
|
draw.polygon(arrow_points, fill=color)
|
|
|
|
def _draw_save_icon(self, draw, size, color):
|
|
"""رسم أيقونة الحفظ"""
|
|
width, height = size
|
|
padding = width // 8
|
|
|
|
|
|
draw.rectangle(
|
|
[(padding, padding), (width - padding, height - padding)],
|
|
fill=color
|
|
)
|
|
|
|
|
|
draw.rectangle(
|
|
[(padding * 2, padding * 2), (width - padding * 2, padding * 4)],
|
|
fill=self.colors["white"]
|
|
)
|
|
|
|
|
|
draw.rectangle(
|
|
[(width // 3, height // 2), (width * 2 // 3, height - padding * 2)],
|
|
fill=self.colors["white"]
|
|
)
|
|
|
|
def _draw_default_icon(self, draw, size, color):
|
|
"""رسم أيقونة افتراضية"""
|
|
width, height = size
|
|
padding = width // 8
|
|
|
|
|
|
center_x = width // 2
|
|
center_y = height // 2
|
|
radius = min(width, height) // 2 - padding
|
|
|
|
draw.ellipse(
|
|
[(center_x - radius, center_y - radius), (center_x + radius, center_y + radius)],
|
|
fill=color
|
|
)
|
|
|
|
def generate_default_icons(self):
|
|
"""توليد الأيقونات الافتراضية"""
|
|
icons = [
|
|
"dashboard",
|
|
"projects",
|
|
"documents",
|
|
"pricing",
|
|
"resources",
|
|
"risk",
|
|
"reports",
|
|
"ai",
|
|
"settings",
|
|
"logout",
|
|
"search",
|
|
"add",
|
|
"upload",
|
|
"import",
|
|
"export",
|
|
"save"
|
|
]
|
|
|
|
for icon in icons:
|
|
self.generate_icon(icon)
|
|
|