Added Data menu
This commit is contained in:
@@ -22,17 +22,20 @@ def _asset_path(relative_path: str) -> str:
|
||||
if bundle_dir is not None:
|
||||
candidates.append(Path(bundle_dir) / path)
|
||||
|
||||
candidates.extend((
|
||||
Path.cwd() / path,
|
||||
Path(__file__).resolve().parents[2] / path,
|
||||
))
|
||||
candidates.extend(
|
||||
(
|
||||
Path.cwd() / path,
|
||||
Path(__file__).resolve().parents[2] / path,
|
||||
)
|
||||
)
|
||||
|
||||
for candidate in candidates:
|
||||
if candidate.exists():
|
||||
return str(candidate)
|
||||
|
||||
searched = ", ".join(str(candidate) for candidate in candidates)
|
||||
raise FileNotFoundError(f"Missing asset {relative_path!r}. Searched: {searched}")
|
||||
raise FileNotFoundError(
|
||||
f"Missing asset {relative_path!r}. Searched: {searched}")
|
||||
|
||||
|
||||
def run() -> None:
|
||||
@@ -50,13 +53,16 @@ def run() -> None:
|
||||
dataflux.config.MAP_IMAGE_HEIGHT = height
|
||||
|
||||
with dpg.texture_registry(show=False):
|
||||
dpg.add_static_texture(width=width, height=height, default_value=data, tag="texture_tab")
|
||||
dpg.add_static_texture(
|
||||
width=width, height=height, default_value=data, tag="texture_tab"
|
||||
)
|
||||
|
||||
dpg.create_viewport(title='DataFlux', width=600, height=600)
|
||||
dpg.create_viewport(title="DataFlux", width=600, height=600)
|
||||
|
||||
# Add Inter font to registry and bind as main app font
|
||||
with dpg.font_registry():
|
||||
app_font = dpg.add_font(_asset_path("assets/fonts/Inter-Regular.ttf"), 18*2)
|
||||
app_font = dpg.add_font(_asset_path(
|
||||
"assets/fonts/Inter-Regular.ttf"), 18 * 2)
|
||||
dpg.bind_font(app_font)
|
||||
|
||||
dataflux.ui.windows.build_windows(state)
|
||||
@@ -64,22 +70,23 @@ def run() -> None:
|
||||
dpg.setup_dearpygui()
|
||||
dpg.show_viewport()
|
||||
|
||||
|
||||
vp_w = dpg.get_viewport_client_width()
|
||||
vp_h = dpg.get_viewport_client_height()
|
||||
dpg.configure_item("main_window", pos=(0, 0), width=vp_w, height=vp_h)
|
||||
dpg.set_primary_window("main_window", True)
|
||||
|
||||
state.ui_worker_thread = Thread(target=dataflux.ui.worker.ui_worker, args=(state,), daemon=True)
|
||||
state.ui_worker_thread = Thread(
|
||||
target=dataflux.ui.worker.ui_worker, args=(state,), daemon=True
|
||||
)
|
||||
state.ui_worker_thread.start()
|
||||
|
||||
state.telemetry_thread_running = True
|
||||
state.telemetry_thread = Thread(target=dataflux.services.telemetry.telemetry_worker, args=(state, ), daemon=True)
|
||||
state.telemetry_thread = Thread(
|
||||
target=dataflux.services.telemetry.telemetry_worker, args=(
|
||||
state,), daemon=True
|
||||
)
|
||||
state.telemetry_thread.start()
|
||||
|
||||
dpg.start_dearpygui()
|
||||
|
||||
dpg.destroy_context()
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -13,21 +13,29 @@ import dataflux.services.telemetry
|
||||
|
||||
from dataflux.tags import WINDOW_CONNECTION_MENU, WINDOW_FILE_DIALOG_DUMP_BUFFERS
|
||||
|
||||
|
||||
def open_connection_window(sender, app_data, user_data) -> None:
|
||||
dataflux.ui.routines.windows.update_window_connection_menu_combo()
|
||||
dataflux.ui.routines.windows.update_window_connection_menu_combo()
|
||||
dpg.show_item(WINDOW_CONNECTION_MENU)
|
||||
|
||||
|
||||
def menu_file_disconnect(sender, app_data, user_data) -> None:
|
||||
dataflux.services.serial.disconnect_serial(user_data)
|
||||
update_global_connection_status(user_data)
|
||||
|
||||
|
||||
def menu_file_dump_buffers(sender, app_data, user_data: AppState) -> None:
|
||||
dpg.show_item(WINDOW_FILE_DIALOG_DUMP_BUFFERS)
|
||||
|
||||
|
||||
def window_file_dialog_dump_buffers_ok(sender, app_data, user_data: AppState) -> None:
|
||||
user_data.buffer_dump_thread = Thread(target=dataflux.services.telemetry.buffer_dump, args=(user_data, app_data["file_path_name"]), daemon=True)
|
||||
user_data.buffer_dump_thread = Thread(
|
||||
target=dataflux.services.telemetry.buffer_dump,
|
||||
args=(user_data, app_data["file_path_name"]),
|
||||
daemon=True,
|
||||
)
|
||||
user_data.buffer_dump_thread.start()
|
||||
|
||||
|
||||
def menu_window_select(sender, app_data, user_data: str) -> None:
|
||||
dataflux.ui.routines.windows.toggle_window(user_data)
|
||||
|
||||
|
||||
@@ -1 +1 @@
|
||||
/Users/hector/Projects/Exergie/TelemetryCommon/python
|
||||
/home/hector/projects/Exergie/TelemetryCommon/python/
|
||||
@@ -7,9 +7,40 @@ import dataflux.callbacks.menu
|
||||
import dataflux.callbacks.serial
|
||||
|
||||
from dataflux.state import AppState
|
||||
from dataflux.tags import GRAPH_SERIES_SPEED, GRAPH_SERIES_TENG, GRAPH_SERIES_VBAT, GRAPH_X_AXIS_SPEED, GRAPH_X_AXIS_TENG, GRAPH_X_AXIS_VBAT, GRAPH_Y_AXIS_SPEED, GRAPH_Y_AXIS_TENG, GRAPH_Y_AXIS_VBAT, LIVE_DATA_TENG_VALUE, LIVE_DATA_UTC_TIME_VALUE, LIVE_DATA_VBAT_VALUE, LIVE_DATA_VEHICLE_TIME_VALUE, LIVE_DATA_SPEED_VALUE, MENU_FILE_CONNECT, MENU_FILE_DISCONNECT, MENU_FILE_DUMP_BUFFERS, PAGE_LAP_RECAP, PAGE_LIVE_DATA, STATUS_SERIAL_STATUS_BOX, STATUS_SERIAL_STATUS_TEXT, SUB_PAGE_DATA_GRAPHS, SUB_PAGE_MAP, THEME_STATUS_CONNECTED, THEME_STATUS_CONNECTED_BRIGHT, THEME_STATUS_DISCONNECTED, WINDOW_CONNECTION_MENU, WINDOW_CONNECTION_MENU_COMBO, WINDOW_FILE_DIALOG_DUMP_BUFFERS
|
||||
from dataflux.tags import (
|
||||
GRAPH_SERIES_SPEED,
|
||||
GRAPH_SERIES_TENG,
|
||||
GRAPH_SERIES_VBAT,
|
||||
GRAPH_X_AXIS_SPEED,
|
||||
GRAPH_X_AXIS_TENG,
|
||||
GRAPH_X_AXIS_VBAT,
|
||||
GRAPH_Y_AXIS_SPEED,
|
||||
GRAPH_Y_AXIS_TENG,
|
||||
GRAPH_Y_AXIS_VBAT,
|
||||
LIVE_DATA_TENG_VALUE,
|
||||
LIVE_DATA_UTC_TIME_VALUE,
|
||||
LIVE_DATA_VBAT_VALUE,
|
||||
LIVE_DATA_VEHICLE_TIME_VALUE,
|
||||
LIVE_DATA_SPEED_VALUE,
|
||||
MENU_FILE_CONNECT,
|
||||
MENU_FILE_DISCONNECT,
|
||||
MENU_FILE_DUMP_BUFFERS,
|
||||
PAGE_LAP_RECAP,
|
||||
PAGE_LIVE_DATA,
|
||||
STATUS_SERIAL_STATUS_BOX,
|
||||
STATUS_SERIAL_STATUS_TEXT,
|
||||
SUB_PAGE_DATA_GRAPHS,
|
||||
SUB_PAGE_MAP,
|
||||
THEME_STATUS_CONNECTED,
|
||||
THEME_STATUS_CONNECTED_BRIGHT,
|
||||
THEME_STATUS_DISCONNECTED,
|
||||
WINDOW_CONNECTION_MENU,
|
||||
WINDOW_CONNECTION_MENU_COMBO,
|
||||
WINDOW_FILE_DIALOG_DUMP_BUFFERS,
|
||||
)
|
||||
from dataflux.ui.colors import STATUS_GREEN_BRIGHT, STATUS_GREEN_DARK, STATUS_RED_DARK
|
||||
|
||||
|
||||
def _add_live_data_row(label: str, value: str, tag: str, units: str) -> None:
|
||||
with dpg.table_row():
|
||||
with dpg.table_cell():
|
||||
@@ -19,62 +50,168 @@ def _add_live_data_row(label: str, value: str, tag: str, units: str) -> None:
|
||||
with dpg.table_cell():
|
||||
dpg.add_text(units)
|
||||
|
||||
|
||||
def build_windows(state: AppState) -> None:
|
||||
|
||||
with dpg.window(label='DataFlux',tag="main_window", no_collapse=True):
|
||||
|
||||
with dpg.window(label="DataFlux", tag="main_window", no_collapse=True):
|
||||
dpg.set_global_font_scale(0.5)
|
||||
with dpg.menu_bar():
|
||||
with dpg.menu(label='File'):
|
||||
dpg.add_menu_item(label="Connect", enabled=True, tag=MENU_FILE_CONNECT, callback=dataflux.callbacks.menu.open_connection_window)
|
||||
dpg.add_menu_item(label="Disonnect", enabled=False, tag=MENU_FILE_DISCONNECT, callback=dataflux.callbacks.menu.menu_file_disconnect, user_data=state)
|
||||
dpg.add_menu_item(label="Dump Buffers", enabled=True, tag=MENU_FILE_DUMP_BUFFERS, callback=dataflux.callbacks.menu.menu_file_dump_buffers)
|
||||
with dpg.menu(label="File"):
|
||||
dpg.add_menu_item(
|
||||
label="Connect",
|
||||
enabled=True,
|
||||
tag=MENU_FILE_CONNECT,
|
||||
callback=dataflux.callbacks.menu.open_connection_window,
|
||||
)
|
||||
dpg.add_menu_item(
|
||||
label="Disonnect",
|
||||
enabled=False,
|
||||
tag=MENU_FILE_DISCONNECT,
|
||||
callback=dataflux.callbacks.menu.menu_file_disconnect,
|
||||
user_data=state,
|
||||
)
|
||||
dpg.add_menu_item(
|
||||
label="Dump Buffers",
|
||||
enabled=True,
|
||||
tag=MENU_FILE_DUMP_BUFFERS,
|
||||
callback=dataflux.callbacks.menu.menu_file_dump_buffers,
|
||||
)
|
||||
dpg.add_menu_item(label="Quit")
|
||||
with dpg.menu(label='Window'):
|
||||
dpg.add_menu_item(label="Live Graphs", user_data=SUB_PAGE_DATA_GRAPHS, callback=dataflux.callbacks.menu.menu_window_select)
|
||||
dpg.add_menu_item(label="Live Map", user_data=SUB_PAGE_MAP, callback=dataflux.callbacks.menu.menu_window_select )
|
||||
dpg.add_menu_item(label="Lap Recap", user_data=PAGE_LAP_RECAP, callback=dataflux.callbacks.menu.menu_window_select)
|
||||
with dpg.menu(label="Window"):
|
||||
dpg.add_menu_item(
|
||||
label="Live Graphs",
|
||||
user_data=SUB_PAGE_DATA_GRAPHS,
|
||||
callback=dataflux.callbacks.menu.menu_window_select,
|
||||
)
|
||||
dpg.add_menu_item(
|
||||
label="Live Map",
|
||||
user_data=SUB_PAGE_MAP,
|
||||
callback=dataflux.callbacks.menu.menu_window_select,
|
||||
)
|
||||
dpg.add_menu_item(
|
||||
label="Lap Recap",
|
||||
user_data=PAGE_LAP_RECAP,
|
||||
callback=dataflux.callbacks.menu.menu_window_select,
|
||||
)
|
||||
with dpg.menu(label="Data"):
|
||||
with dpg.menu(label="Timeframe"):
|
||||
dpg.add_menu_item(label="30s")
|
||||
dpg.add_menu_item(label="60s")
|
||||
|
||||
with dpg.child_window(tag="content_area", autosize_x=True, height=-32, border=False):
|
||||
with dpg.child_window(
|
||||
tag="content_area", autosize_x=True, height=-32, border=False
|
||||
):
|
||||
with dpg.group(tag=PAGE_LIVE_DATA, show=True):
|
||||
with dpg.group(horizontal=True):
|
||||
with dpg.child_window(tag="realtime_stats", width=260, autosize_y=True, border=True):
|
||||
with dpg.table(header_row=False, resizable=False, policy=dpg.mvTable_SizingFixedFit, borders_innerH=False, borders_innerV=False, borders_outerH=False, borders_outerV=False, no_host_extendX=True):
|
||||
with dpg.child_window(
|
||||
tag="realtime_stats", width=260, autosize_y=True, border=True
|
||||
):
|
||||
with dpg.table(
|
||||
header_row=False,
|
||||
resizable=False,
|
||||
policy=dpg.mvTable_SizingFixedFit,
|
||||
borders_innerH=False,
|
||||
borders_innerV=False,
|
||||
borders_outerH=False,
|
||||
borders_outerV=False,
|
||||
no_host_extendX=True,
|
||||
):
|
||||
dpg.add_table_column(width_fixed=True)
|
||||
dpg.add_table_column(width_stretch=True, init_width_or_weight=1.0)
|
||||
dpg.add_table_column(
|
||||
width_stretch=True, init_width_or_weight=1.0
|
||||
)
|
||||
dpg.add_table_column(width_fixed=True)
|
||||
_add_live_data_row("UTC Time", "no_data", LIVE_DATA_UTC_TIME_VALUE,"")
|
||||
_add_live_data_row("Vehicle Time", "no_data", LIVE_DATA_VEHICLE_TIME_VALUE,"")
|
||||
_add_live_data_row("Speed", "no_data", LIVE_DATA_SPEED_VALUE,"km/h")
|
||||
_add_live_data_row("Battery Voltage", "no_data", LIVE_DATA_VBAT_VALUE,"V")
|
||||
_add_live_data_row("Engine Temp", "no_data", LIVE_DATA_TENG_VALUE,"°C")
|
||||
_add_live_data_row(
|
||||
"UTC Time", "no_data", LIVE_DATA_UTC_TIME_VALUE, ""
|
||||
)
|
||||
_add_live_data_row(
|
||||
"Vehicle Time",
|
||||
"no_data",
|
||||
LIVE_DATA_VEHICLE_TIME_VALUE,
|
||||
"",
|
||||
)
|
||||
_add_live_data_row(
|
||||
"Speed", "no_data", LIVE_DATA_SPEED_VALUE, "km/h"
|
||||
)
|
||||
_add_live_data_row(
|
||||
"Battery Voltage", "no_data", LIVE_DATA_VBAT_VALUE, "V"
|
||||
)
|
||||
_add_live_data_row(
|
||||
"Engine Temp", "no_data", LIVE_DATA_TENG_VALUE, "°C"
|
||||
)
|
||||
|
||||
with dpg.child_window(tag=SUB_PAGE_DATA_GRAPHS, autosize_x=True, autosize_y=True, border=True, show=True):
|
||||
with dpg.plot(label="Speed", height=250, width=-1, no_inputs=True):
|
||||
with dpg.child_window(
|
||||
tag=SUB_PAGE_DATA_GRAPHS,
|
||||
autosize_x=True,
|
||||
autosize_y=True,
|
||||
border=True,
|
||||
show=True,
|
||||
):
|
||||
with dpg.plot(
|
||||
label="Speed", height=250, width=-1, no_inputs=True
|
||||
):
|
||||
dpg.add_plot_legend()
|
||||
dpg.add_plot_axis(dpg.mvXAxis, label="Time", tag=GRAPH_X_AXIS_SPEED)
|
||||
y_axis_speed = dpg.add_plot_axis(dpg.mvYAxis, label="Speed", tag=GRAPH_Y_AXIS_SPEED)
|
||||
dpg.add_plot_axis(
|
||||
dpg.mvXAxis, label="Time", tag=GRAPH_X_AXIS_SPEED
|
||||
)
|
||||
y_axis_speed = dpg.add_plot_axis(
|
||||
dpg.mvYAxis, label="Speed", tag=GRAPH_Y_AXIS_SPEED
|
||||
)
|
||||
dpg.set_axis_limits(GRAPH_Y_AXIS_SPEED, ymin=0, ymax=50)
|
||||
dpg.set_axis_limits(GRAPH_X_AXIS_SPEED, ymin=-30, ymax=0)
|
||||
dpg.add_line_series([], [], parent=y_axis_speed, tag=GRAPH_SERIES_SPEED)
|
||||
with dpg.plot(label="Battery Voltage", height=250, width=-1, no_inputs=True):
|
||||
dpg.add_line_series(
|
||||
[], [], parent=y_axis_speed, tag=GRAPH_SERIES_SPEED
|
||||
)
|
||||
with dpg.plot(
|
||||
label="Battery Voltage",
|
||||
height=250,
|
||||
width=-1,
|
||||
no_inputs=True,
|
||||
):
|
||||
dpg.add_plot_legend()
|
||||
dpg.add_plot_axis(dpg.mvXAxis, label="Time", tag=GRAPH_X_AXIS_VBAT)
|
||||
y_axis_vbat = dpg.add_plot_axis(dpg.mvYAxis, label="Voltage", tag=GRAPH_Y_AXIS_VBAT)
|
||||
dpg.add_plot_axis(
|
||||
dpg.mvXAxis, label="Time", tag=GRAPH_X_AXIS_VBAT
|
||||
)
|
||||
y_axis_vbat = dpg.add_plot_axis(
|
||||
dpg.mvYAxis, label="Voltage", tag=GRAPH_Y_AXIS_VBAT
|
||||
)
|
||||
dpg.set_axis_limits(GRAPH_Y_AXIS_VBAT, ymin=0, ymax=20)
|
||||
dpg.set_axis_limits(GRAPH_X_AXIS_VBAT, ymin=-30, ymax=0)
|
||||
dpg.add_line_series([], [], parent=y_axis_vbat, tag=GRAPH_SERIES_VBAT)
|
||||
with dpg.plot(label="Engine Temp", height=250, width=-1, no_inputs=True):
|
||||
dpg.add_line_series(
|
||||
[], [], parent=y_axis_vbat, tag=GRAPH_SERIES_VBAT
|
||||
)
|
||||
with dpg.plot(
|
||||
label="Engine Temp", height=250, width=-1, no_inputs=True
|
||||
):
|
||||
dpg.add_plot_legend()
|
||||
dpg.add_plot_axis(dpg.mvXAxis, label="Time", tag=GRAPH_X_AXIS_TENG)
|
||||
y_axis_teng = dpg.add_plot_axis(dpg.mvYAxis, label="Temperature", tag=GRAPH_Y_AXIS_TENG)
|
||||
dpg.add_plot_axis(
|
||||
dpg.mvXAxis, label="Time", tag=GRAPH_X_AXIS_TENG
|
||||
)
|
||||
y_axis_teng = dpg.add_plot_axis(
|
||||
dpg.mvYAxis, label="Temperature", tag=GRAPH_Y_AXIS_TENG
|
||||
)
|
||||
dpg.set_axis_limits(GRAPH_Y_AXIS_TENG, ymin=0, ymax=120)
|
||||
dpg.set_axis_limits(GRAPH_X_AXIS_TENG, ymin=-30, ymax=0)
|
||||
dpg.add_line_series([], [], parent=y_axis_teng, tag=GRAPH_SERIES_TENG)
|
||||
dpg.add_line_series(
|
||||
[], [], parent=y_axis_teng, tag=GRAPH_SERIES_TENG
|
||||
)
|
||||
|
||||
with dpg.child_window(tag=SUB_PAGE_MAP, autosize_x=True, autosize_y=True, border=True, show=False, no_scrollbar=True):
|
||||
with dpg.child_window(
|
||||
tag=SUB_PAGE_MAP,
|
||||
autosize_x=True,
|
||||
autosize_y=True,
|
||||
border=True,
|
||||
show=False,
|
||||
no_scrollbar=True,
|
||||
):
|
||||
with dpg.drawlist(width=500, height=500, tag="map_drawlist"):
|
||||
dpg.draw_image("texture_tab", (0, 0), (500, 500))
|
||||
dpg.draw_circle((0, 0), 10, color=(255, 0, 0, 255), fill=(255, 0, 0, 255))
|
||||
dpg.draw_circle(
|
||||
(0, 0),
|
||||
10,
|
||||
color=(255, 0, 0, 255),
|
||||
fill=(255, 0, 0, 255),
|
||||
)
|
||||
|
||||
with dpg.group(tag=PAGE_LAP_RECAP, show=False):
|
||||
dpg.add_text("Lap Recap")
|
||||
@@ -92,10 +229,28 @@ def build_windows(state: AppState) -> None:
|
||||
with dpg.theme_component(dpg.mvChildWindow):
|
||||
dpg.add_theme_color(dpg.mvThemeCol_ChildBg, STATUS_RED_DARK)
|
||||
|
||||
with dpg.child_window(tag="footer_bar", autosize_x=True, height=28, border=False, no_scrollbar=True):
|
||||
with dpg.child_window(
|
||||
tag="footer_bar",
|
||||
autosize_x=True,
|
||||
height=28,
|
||||
border=False,
|
||||
no_scrollbar=True,
|
||||
):
|
||||
with dpg.group(horizontal=True):
|
||||
with dpg.child_window(width=200, height=28, border=False, tag=STATUS_SERIAL_STATUS_BOX):
|
||||
with dpg.table(header_row=False, resizable=False, policy=dpg.mvTable_SizingStretchProp, borders_innerV=False, borders_innerH=False, borders_outerH=False, borders_outerV=False, no_host_extendX=False, no_pad_innerX=True):
|
||||
with dpg.child_window(
|
||||
width=200, height=28, border=False, tag=STATUS_SERIAL_STATUS_BOX
|
||||
):
|
||||
with dpg.table(
|
||||
header_row=False,
|
||||
resizable=False,
|
||||
policy=dpg.mvTable_SizingStretchProp,
|
||||
borders_innerV=False,
|
||||
borders_innerH=False,
|
||||
borders_outerH=False,
|
||||
borders_outerV=False,
|
||||
no_host_extendX=False,
|
||||
no_pad_innerX=True,
|
||||
):
|
||||
dpg.add_table_column(init_width_or_weight=1.0)
|
||||
dpg.add_table_column(width_fixed=True)
|
||||
dpg.add_table_column(init_width_or_weight=1.0)
|
||||
@@ -104,16 +259,30 @@ def build_windows(state: AppState) -> None:
|
||||
pass
|
||||
|
||||
with dpg.table_cell():
|
||||
dpg.add_text("Serial: Disconnected", tag=STATUS_SERIAL_STATUS_TEXT)
|
||||
dpg.add_text(
|
||||
"Serial: Disconnected",
|
||||
tag=STATUS_SERIAL_STATUS_TEXT,
|
||||
)
|
||||
|
||||
with dpg.table_cell():
|
||||
pass
|
||||
|
||||
dpg.bind_item_theme(STATUS_SERIAL_STATUS_BOX, THEME_STATUS_DISCONNECTED)
|
||||
|
||||
with dpg.window(label="Connection Menu", tag=WINDOW_CONNECTION_MENU, show=False, modal=True, no_collapse=True, width=300):
|
||||
with dpg.window(
|
||||
label="Connection Menu",
|
||||
tag=WINDOW_CONNECTION_MENU,
|
||||
show=False,
|
||||
modal=True,
|
||||
no_collapse=True,
|
||||
width=300,
|
||||
):
|
||||
dpg.add_combo([], tag=WINDOW_CONNECTION_MENU_COMBO)
|
||||
dpg.add_button(label="Connect", callback=dataflux.callbacks.serial.connection_window_connect_serial, user_data=state)
|
||||
dpg.add_button(
|
||||
label="Connect",
|
||||
callback=dataflux.callbacks.serial.connection_window_connect_serial,
|
||||
user_data=state,
|
||||
)
|
||||
|
||||
with dpg.file_dialog(
|
||||
directory_selector=False,
|
||||
@@ -123,6 +292,6 @@ def build_windows(state: AppState) -> None:
|
||||
height=400,
|
||||
modal=True,
|
||||
callback=dataflux.callbacks.menu.window_file_dialog_dump_buffers_ok,
|
||||
user_data=state
|
||||
user_data=state,
|
||||
):
|
||||
dpg.add_file_extension(".csv")
|
||||
|
||||
Reference in New Issue
Block a user