-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathmain.py
More file actions
208 lines (185 loc) · 7.06 KB
/
main.py
File metadata and controls
208 lines (185 loc) · 7.06 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
import flet as ft
from app.core.database import init_db
from app.core.db_service import get_active_account
from app.gui.views.dashboard import get_dashboard_view
from app.gui.views.positions import get_positions_view
from app.gui.views.providers import get_providers_view
from app.gui.views.settings import get_settings_view
from app.integration.mql_api import start_mql_api_server
def main(page: ft.Page):
# Set page general settings
page.title = "SignalTrader Premium"
page.theme_mode = ft.ThemeMode.DARK
page.padding = 0
page.spacing = 0
page.window.width = 1100
page.window.height = 750
page.window.min_width = 950
page.window.min_height = 650
page.bgcolor = "#0d0f17" # Slate Darkest Background
# Initialize Database
try:
init_db()
except Exception as ex:
print(f"Error initializing DB: {ex}")
# Start Local MQL5 Bridge API Server on startup
# Whenever MQL5 EA confirms a trade execution, we tell Flet to refresh the page thread-safely!
try:
start_mql_api_server(
host="127.0.0.1",
port=8000,
callback=lambda: page.run_task(async_refresh)
)
except Exception as ex:
print(f"Error starting MQL5 API: {ex}")
# Active view state tracking
active_view = "dashboard"
# Main content container
content_area = ft.Container(
content=get_dashboard_view(page),
expand=True,
padding=30,
bgcolor="#0d0f17"
)
async def async_refresh():
nonlocal active_view
# Trigger page update safely from background thread
switch_view(active_view)
def switch_view(view_name: str):
nonlocal active_view
active_view = view_name
# Update view controls
if view_name == "dashboard":
content_area.content = get_dashboard_view(page)
elif view_name == "positions":
content_area.content = get_positions_view(page)
elif view_name == "providers":
content_area.content = get_providers_view(page)
elif view_name == "settings":
content_area.content = get_settings_view(page)
# Re-render UI components
update_sidebar()
page.update()
# Sidebar logo/header
sidebar_header = ft.Container(
content=ft.Column(
controls=[
ft.Row(
controls=[
ft.Icon(name=ft.icons.BOLT_ROUNDED, color=ft.colors.INDIGO_400, size=28),
ft.Text("SIGNALTRADER", size=18, weight=ft.FontWeight.BOLD, color=ft.colors.WHITE),
],
alignment=ft.MainAxisAlignment.START,
spacing=8
),
ft.Container(height=1, bgcolor="#2e3347", margin=ft.margin.only(top=10))
]
),
padding=ft.padding.only(left=20, right=20, top=25, bottom=15)
)
# Sidebar custom navigation buttons
nav_buttons = {}
def create_nav_item(name: str, label: str, icon: str):
def on_click(e):
switch_view(name)
container = ft.Container(
content=ft.Row(
controls=[
ft.Icon(name=icon, size=20),
ft.Text(label, size=13, weight=ft.FontWeight.W_500),
],
spacing=12
),
padding=ft.padding.symmetric(horizontal=15, vertical=12),
border_radius=8,
on_click=on_click
)
nav_buttons[name] = container
return container
sidebar_nav = ft.Container(
content=ft.Column(
controls=[
create_nav_item("dashboard", "Dashboard", ft.icons.GRID_VIEW_ROUNDED),
create_nav_item("positions", "Active Trades", ft.icons.TRENDING_UP_ROUNDED),
create_nav_item("providers", "Signal Providers", ft.icons.CELL_TOWER_ROUNDED),
create_nav_item("settings", "Settings", ft.icons.SETTINGS_ROUNDED),
],
spacing=8
),
padding=ft.padding.symmetric(horizontal=15)
)
# Sidebar footer with dynamic status lights
status_connection_text = ft.Text("MT5 Account: Offline", size=11, color=ft.colors.BLUE_GREY_300)
status_connection_light = ft.Container(bgcolor=ft.colors.RED_500, width=8, height=8, border_radius=4)
def update_sidebar():
# Update nav buttons visual states
for name, btn in nav_buttons.items():
if name == active_view:
btn.bgcolor = ft.colors.with_opacity(0.15, ft.colors.INDIGO_400)
btn.content.controls[0].color = ft.colors.INDIGO_300
btn.content.controls[1].color = ft.colors.WHITE
btn.border = ft.border.only(left=ft.BorderSide(3, ft.colors.INDIGO_400))
else:
btn.bgcolor = ft.colors.TRANSPARENT
btn.content.controls[0].color = ft.colors.BLUE_GREY_400
btn.content.controls[1].color = ft.colors.BLUE_GREY_200
btn.border = None
# Load active MT5 account state dynamically
acc = get_active_account()
if acc:
status_connection_text.value = f"MT5 Account: {acc.login}"
status_connection_light.bgcolor = ft.colors.GREEN_500
else:
status_connection_text.value = "MT5 Account: Offline"
status_connection_light.bgcolor = ft.colors.RED_500
# Initial sidebar state render
update_sidebar()
sidebar_footer = ft.Container(
content=ft.Column(
controls=[
ft.Container(height=1, bgcolor="#2e3347", margin=ft.margin.only(bottom=15)),
ft.Row(
controls=[
status_connection_light,
status_connection_text,
],
spacing=8
),
ft.Row(
controls=[
ft.Container(bgcolor=ft.colors.RED_500, width=8, height=8, border_radius=4),
ft.Text("Central Server: Offline", size=11, color=ft.colors.BLUE_GREY_300),
],
spacing=8
),
ft.Container(ft.Text("v1.0.0 (Flet Premium)", size=10, color=ft.colors.BLUE_GREY_500), margin=ft.margin.only(top=10)),
]
),
padding=ft.padding.only(left=20, right=20, bottom=25, top=10)
)
# Sidebar Container
sidebar = ft.Container(
content=ft.Column(
controls=[
sidebar_header,
ft.Container(content=sidebar_nav, expand=True),
sidebar_footer
],
spacing=0
),
width=250,
bgcolor="#141722", # Sidebar darker slate color
border=ft.border.only(right=ft.BorderSide(1, "#2e3347"))
)
# Core Page Scaffold Layout
main_layout = ft.Row(
controls=[
sidebar,
content_area
],
spacing=0,
expand=True
)
page.add(main_layout)
if __name__ == "__main__":
ft.app(target=main)