//+------------------------------------------------------------------+ //| Main.mqh | //| Copyright 2025, Niquel Mendoza. | //| https://www.mql5.com/es/users/nique_372 | //+------------------------------------------------------------------+ #property copyright "Copyright 2025, Niquel Mendoza." #property link "https://www.mql5.com/es/users/nique_372" #property strict #ifndef AIDATATASKRUNER_UI_TABWORKFLOWS_MAIN_MQH #define AIDATATASKRUNER_UI_TABWORKFLOWS_MAIN_MQH //+------------------------------------------------------------------+ //| Include | //+------------------------------------------------------------------+ //--- Defines basicos para lagui #include "..\\Defines.mqh" //--- Epxert para le ejeucion del ea #include //--- Funciones extra (shell execute) #include //--- Backend protocolo de comuniacion con el runner #include "..\\..\\Backend\\Workflows\\Protocol\\Def.mqh" //--- Reciclamos las imagenes de state para este tab (osea agarremos las imagenes de data generation) #include "..\\DataGenerationTab\\Def.mqh" //+------------------------------------------------------------------+ //| Defines \ Enums \ Arrs | //+------------------------------------------------------------------+ //--- Estado enum ENUM_TABWF_STATE { WF_STATE_ESPERANDO_RUNNER = 0, WF_STATE_ESPERANDO_EJECUTANDO = 1, WF_STATE_ESPERANDO_NADA = 2 }; //--- Tabla #define TABWF_TABLERES_TOTAL_COLS (4) #define TABWF_TABLERES_COL_NAME (0) #define TABWF_TABLERES_COL_RES (1) #define TABWF_TABLERES_COL_STATE (2) #define TABWF_TABLERES_COL_TIME (3) //--- Imagenes const string g_aitaskruner_wf_img[4] { "res\\circle_amarillo.bmp", "res\\circle_gris.bmp", "res\\circle_verde.bmp", "Images\\EasyAndFastGUI\\Controls\\Close_red.bmp" }; //--- Img idx #define TABWF_IMAGE_EN_EJECUCION (0) #define TABWF_IMAGE_EN_PENDIENTE (1) #define TABWF_IMAGE_EN_EXTIO (2) #define TABWF_IMAGE_EN_FALLO (3) //+------------------------------------------------------------------+ //| Tab de workflows | //+------------------------------------------------------------------+ class CTabWorkflows : public CGuiBaseComponent { private: CTabs m_tabs; ENUM_TABWF_STATE m_state; //--- Tab [Run] // Sec de configuracion del archivo yml CTextLabel m_label_tit_workflows; CTextLabel m_label_selec_wf; CTextLabel m_label_selec_val_wf; CButton m_btn_browse_wf; CButton m_btn_template_wf; CButton m_btn_open_wf; // Sep CSeparateLine m_sep_line_one; // Nombre del yml CTextLabel m_label_wf_name; CTextLabel m_label_the_wf_name; // Botones CButton m_btn_run_wf; CButton m_btn_relanzar_ea; //--- Tab [View] CTextLabel m_label_tit_execution; CTable m_table_results; // CButton m_btn_cancel; //--- Variables string m_path_to_wf_temp; string m_path_ea; long m_last_runner_chart_id; string m_arr_names_tables[4]; // 4 //--- Run void RunWF(); //--- Eventos void OnWfStart(); void OnWfStep(const string& sparam); void OnWfEnd(const string& sparam); //--- Creacion bool CreateRunTab(CWndCreate *p, CWindow &main_window, int top_gap, int left_gap, int right_gap, int bottom_gap); bool CreateViewTab(CWndCreate *p, CWindow &main_window, int top_gap, int left_gap, int right_gap, int bottom_gap); public: CTabWorkflows(void); ~CTabWorkflows(void) { if(m_last_runner_chart_id != -1) ::ChartClose(m_last_runner_chart_id); } //--- void Init(const string &path_ea); //--- Creacion bool Create(CWndCreate* p, CWindow& main_window, int top_gap, int left_gap, int right_gap, int bottom_gap); //--- Eventos bool OnClickButtom(const long lparam); //--- Evento especial void ChartEvent(const int32_t id, const long& lparam, const double& dparam, const string& sparam); //--- Cambio de lenguaje void OnLenguajeChange() override final; //--- Corre el 4 hilo bool RunEA(); }; //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ CTabWorkflows::CTabWorkflows(void) : CGuiBaseComponent("CTabWorkflows"), m_state(WF_STATE_ESPERANDO_NADA), m_path_to_wf_temp(NULL), m_path_ea(NULL), m_last_runner_chart_id(-1) { } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ void CTabWorkflows::Init(const string &path_ea) { //--- Cache m_path_to_wf_temp = AIDATATASKRUNER_PATH_WORKFLOWS + "Temp\\wf_data.temp"; m_path_ea = path_ea; } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ bool CTabWorkflows::Create(CWndCreate *p, CWindow &main_window, int top_gap, int left_gap, int right_gap, int bottom_gap) { //--- if(StringSplit(m_language[GUIBASE_COMPONENT_NAME(m_arr_names_tables)], '|', m_arr_names_tables) != 4) { LogFatalError("No se pudo hacer split a los nombres de los estados", FUNCION_ACTUAL); return false; } //--- string txt[2] = {m_language[GUIBASE_COMPONENT_NAME(m_tabs) + "_0"], m_language[GUIBASE_COMPONENT_NAME(m_tabs) + "_1"]}; int width[2] = {70, 80}; color clrs_tab_label[2] = {AIDATATASKRUNER_COLOR_TEXT_SECONDARY, AIDATATASKRUNER_COLOR_TEXT_SECONDARY}; color clrs_tab_label_pressed[2] = {AIDATATASKRUNER_COLOR_ACCENT, AIDATATASKRUNER_COLOR_ACCENT}; top_gap += 24; left_gap += 4; right_gap += 4; bottom_gap += 4; //--- m_tabs.BackColor(AIDATATASKRUNER_COLOR_FONDO_SUBTAB); m_tabs.BackColorHover(AIDATATASKRUNER_COLOR_FONDO_SUBTAB_HOVER); m_tabs.BackColorPressed(AIDATATASKRUNER_COLOR_FONDO_SUBTAB_PRESSED); m_tabs.BackColorLocked(AIDATATASKRUNER_COLOR_FONDO_SUBTAB_LOCKED); m_tabs.BorderColor(AIDATATASKRUNER_COLOR_BORDER); m_tabs.BorderColorHover(AIDATATASKRUNER_COLOR_BORDER_HOVER); m_tabs.BorderColorPressed(AIDATATASKRUNER_COLOR_BORDER_HOVER); m_tabs.BorderColorLocked(AIDATATASKRUNER_COLOR_BORDER); if(!p.CreateTabs(m_tabs, main_window, 0, m_base_tab, m_base_tab_idx, left_gap, top_gap, 0, 0, txt, width, clrs_tab_label, clrs_tab_label_pressed, TABS_TOP, true, true, right_gap, bottom_gap)) { GUIBASE_ERROR_CREATION(m_tabs); return false; } //--- if(!CreateRunTab(p, main_window, top_gap, left_gap, right_gap, bottom_gap)) return false; //--- if(!CreateViewTab(p, main_window, top_gap, left_gap, right_gap, bottom_gap)) return false; //--- return true; } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ bool CTabWorkflows::CreateRunTab(CWndCreate *p, CWindow &main_window, int top_gap, int left_gap, int right_gap, int bottom_gap) { //--- const int initial_x = left_gap + 5; int x = initial_x; int y = top_gap + 10; //--- Titulo m_label_tit_workflows.FontSize(14); m_label_tit_workflows.Font("Arial"); m_label_tit_workflows.LabelColor(AIDATATASKRUNER_COLOR_TEXT_PRIMARY); m_label_tit_workflows.BackColor(AIDATATASKRUNER_COLOR_FONDO_SUBTAB_PRESSED); if(!p.CreateTextLabel(m_label_tit_workflows, m_language[GUIBASE_COMPONENT_NAME(m_label_tit_workflows)], main_window, 0, m_tabs, 0, x, y, 200)) { GUIBASE_ERROR_CREATION(m_label_tit_workflows); return false; } y += m_label_tit_workflows.YSize() + 10; //--- Label selec m_label_selec_wf.FontSize(10); m_label_selec_wf.Font("Arial"); m_label_selec_wf.LabelColor(AIDATATASKRUNER_COLOR_TEXT_SECONDARY); m_label_selec_wf.BackColor(AIDATATASKRUNER_COLOR_FONDO_SUBTAB_PRESSED); if(!p.CreateTextLabel(m_label_selec_wf, m_language[GUIBASE_COMPONENT_NAME(m_label_selec_wf)], main_window, 0, m_tabs, 0, x, y, 100, 25)) { GUIBASE_ERROR_CREATION(m_label_selec_wf); return false; } x += m_label_selec_wf.XSize() + 5; //--- Label val m_label_selec_val_wf.FontSize(10); m_label_selec_val_wf.Font("Arial"); m_label_selec_val_wf.LabelColor(AIDATATASKRUNER_COLOR_TEXT_PRIMARY); m_label_selec_val_wf.BackColor(AIDATATASKRUNER_COLOR_EDIT_BACK); m_label_selec_val_wf.LabelXGap(5); m_label_selec_val_wf.LabelYGap(3); m_label_selec_val_wf.Tooltip(m_language.Tooltip(GUIBASE_COMPONENT_NAME(m_label_selec_val_wf))); if(!p.CreateTextLabel(m_label_selec_val_wf, "", main_window, 0, m_tabs, 0, x, y, 400, 25)) { GUIBASE_ERROR_CREATION(m_label_selec_val_wf); return false; } x = initial_x; y += m_label_selec_val_wf.YSize() + 8; //--- Browse m_btn_browse_wf.AddImagesGroup(5, 2, g_eafmod_ic_arr_folderw10_image); m_btn_browse_wf.ChangeImage(0, 0); m_btn_browse_wf.LabelXGap(22); m_btn_browse_wf.FontSize(10); m_btn_browse_wf.Font("Arial"); m_btn_browse_wf.BackColor(AIDATATASKRUNER_COLOR_BTN_BACK); m_btn_browse_wf.LabelColor(AIDATATASKRUNER_COLOR_TEXT_SECONDARY); m_btn_browse_wf.BorderColor(AIDATATASKRUNER_COLOR_BTN_BORDER); m_btn_browse_wf.Tooltip(m_language.Tooltip(GUIBASE_COMPONENT_NAME(m_btn_browse_wf))); if(!p.CreateButton(m_btn_browse_wf, m_language[GUIBASE_COMPONENT_NAME(m_btn_browse_wf)], main_window, 0, m_tabs, 0, x, y, 100)) { GUIBASE_ERROR_CREATION(m_btn_browse_wf); return false; } x += m_btn_browse_wf.XSize() + 5; //--- Template m_btn_template_wf.AddImagesGroup(5, 2, g_eafmod_ic_arr_help_image); m_btn_template_wf.ChangeImage(0, 0); m_btn_template_wf.FontSize(10); m_btn_template_wf.Font("Arial"); m_btn_template_wf.BackColor(AIDATATASKRUNER_COLOR_FONDO_SUBTAB_PRESSED); m_btn_template_wf.LabelColor(AIDATATASKRUNER_COLOR_TEXT_SECONDARY); m_btn_template_wf.BorderColor(AIDATATASKRUNER_COLOR_FONDO_SUBTAB_PRESSED); m_btn_template_wf.Tooltip(m_language.Tooltip(GUIBASE_COMPONENT_NAME(m_btn_template_wf))); if(!p.CreateButton(m_btn_template_wf, "", main_window, 0, m_tabs, 0, x, y, 30)) { GUIBASE_ERROR_CREATION(m_btn_template_wf); return false; } x += m_btn_template_wf.XSize() + 5; //--- Open m_btn_open_wf.FontSize(10); m_btn_open_wf.Font("Arial"); m_btn_open_wf.BackColor(AIDATATASKRUNER_COLOR_BTN_BACK); m_btn_open_wf.LabelColor(AIDATATASKRUNER_COLOR_TEXT_SECONDARY); m_btn_open_wf.BorderColor(AIDATATASKRUNER_COLOR_BTN_BORDER); m_btn_open_wf.Tooltip(m_language.Tooltip(GUIBASE_COMPONENT_NAME(m_btn_open_wf))); if(!p.CreateButton(m_btn_open_wf, m_language[GUIBASE_COMPONENT_NAME(m_btn_open_wf)], main_window, 0, m_tabs, 0, x, y, 100)) { GUIBASE_ERROR_CREATION(m_btn_open_wf); return false; } x = initial_x; y += m_btn_open_wf.YSize() + 10; //--- const int xsize = main_window.X2() - initial_x - initial_x; if(!p.CreateSepLine(m_sep_line_one, main_window, 0, initial_x, y, xsize, (9 + 25 + 8 + 7), AIDATATASKRUNER_COLOR_BTN_BORDER, AIDATATASKRUNER_COLOR_BTN_BORDER, H_SEP_LINE)) { GUIBASE_ERROR_CREATION(m_sep_line_one); return false; } y += 2 + 7; //--- Label wf name m_label_wf_name.FontSize(10); m_label_wf_name.Font("Arial"); m_label_wf_name.LabelColor(AIDATATASKRUNER_COLOR_TEXT_SECONDARY); m_label_wf_name.BackColor(AIDATATASKRUNER_COLOR_FONDO_SUBTAB_PRESSED); if(!p.CreateTextLabel(m_label_wf_name, m_language[GUIBASE_COMPONENT_NAME(m_label_wf_name)], main_window, 0, m_tabs, 0, x, y, 100, 25)) { GUIBASE_ERROR_CREATION(m_label_wf_name); return false; } x += m_label_wf_name.XSize() + 5; //--- Label the wf name val m_label_the_wf_name.FontSize(10); m_label_the_wf_name.Font("Arial"); m_label_the_wf_name.LabelColor(AIDATATASKRUNER_COLOR_TEXT_PRIMARY); m_label_the_wf_name.BackColor(AIDATATASKRUNER_COLOR_FONDO_SUBTAB_PRESSED); m_label_the_wf_name.Tooltip(m_language.Tooltip(GUIBASE_COMPONENT_NAME(m_label_the_wf_name))); if(!p.CreateTextLabel(m_label_the_wf_name, m_language[GUIBASE_COMPONENT_NAME(m_label_the_wf_name) + "_nada"], main_window, 0, m_tabs, 0, x, y, 300, 25)) { GUIBASE_ERROR_CREATION(m_label_the_wf_name); return false; } x = initial_x; y += m_label_the_wf_name.YSize() + 15; //--- Run m_btn_run_wf.FontSize(10); m_btn_run_wf.Font("Arial"); m_btn_run_wf.BackColor(AIDATATASKRUNER_COLOR_BTN_BACK); m_btn_run_wf.LabelColor(AIDATATASKRUNER_COLOR_TEXT_SECONDARY); m_btn_run_wf.BorderColor(AIDATATASKRUNER_COLOR_BTN_BORDER); m_btn_run_wf.Tooltip(m_language.Tooltip(GUIBASE_COMPONENT_NAME(m_btn_run_wf))); if(!p.CreateButton(m_btn_run_wf, m_language[GUIBASE_COMPONENT_NAME(m_btn_run_wf)], main_window, 0, m_tabs, 0, x, y, 120)) { GUIBASE_ERROR_CREATION(m_btn_run_wf); return false; } //--- x += m_btn_run_wf.XSize() + 5; //--- Run m_btn_relanzar_ea.FontSize(10); m_btn_relanzar_ea.Font("Arial"); m_btn_relanzar_ea.BackColor(AIDATATASKRUNER_COLOR_BTN_BACK); m_btn_relanzar_ea.LabelColor(AIDATATASKRUNER_COLOR_TEXT_SECONDARY); m_btn_relanzar_ea.BorderColor(AIDATATASKRUNER_COLOR_BTN_BORDER); m_btn_relanzar_ea.Tooltip(m_language.Tooltip(GUIBASE_COMPONENT_NAME(m_btn_relanzar_ea))); if(!p.CreateButton(m_btn_relanzar_ea, m_language[GUIBASE_COMPONENT_NAME(m_btn_relanzar_ea)], main_window, 0, m_tabs, 0, x, y, 120)) { GUIBASE_ERROR_CREATION(m_btn_run_wf); return false; } //--- return true; } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ bool CTabWorkflows::CreateViewTab(CWndCreate *p, CWindow &main_window, int top_gap, int left_gap, int right_gap, int bottom_gap) { //--- const int initial_x = left_gap + 5; int x = initial_x; int y = top_gap + 10; //--- Titulo m_label_tit_execution.FontSize(14); m_label_tit_execution.Font("Arial"); m_label_tit_execution.LabelColor(AIDATATASKRUNER_COLOR_TEXT_PRIMARY); m_label_tit_execution.BackColor(AIDATATASKRUNER_COLOR_FONDO_SUBTAB_PRESSED); if(!p.CreateTextLabel(m_label_tit_execution, m_language[GUIBASE_COMPONENT_NAME(m_label_tit_execution)], main_window, 0, m_tabs, 1, x, y, 200)) { GUIBASE_ERROR_CREATION(m_label_tit_execution); return false; } y += m_label_tit_execution.YSize() + 10; //--- Tabla string headers[]; const string header_str = m_language[GUIBASE_COMPONENT_NAME(m_table_results) + "_header"]; if(!StrTo::CstArray(headers, header_str, '|', true)) { LogError(StringFormat("Fallo al hacer str to array str, str = %s", header_str), FUNCION_ACTUAL); return false; } ArrayResize(headers, TABWF_TABLERES_TOTAL_COLS); //--- m_table_results.HeadersColor(C'0x2A,0x4A,0x6A'); m_table_results.HeadersColorHover(AIDATATASKRUNER_COLOR_ACCENT); m_table_results.HeadersColorPressed(C'0x1E,0x38,0x52'); m_table_results.HeadersTextColor(AIDATATASKRUNER_COLOR_TEXT_PRIMARY); m_table_results.CellColor(AIDATATASKRUNER_COLOR_FONDO_WIN); m_table_results.CellColorHover(AIDATATASKRUNER_COLOR_EDIT_BACK); m_table_results.CElement::BackColor(AIDATATASKRUNER_COLOR_FONDO_WIN); m_table_results.GridColor(AIDATATASKRUNER_COLOR_BORDER); m_table_results.m_label_color = AIDATATASKRUNER_COLOR_TEXT_SECONDARY; //--- CScrollH *sh = m_table_results.GetScrollHPointer(); sh.BackColor(AIDATATASKRUNER_COLOR_FONDO_TAB); sh.ThumbColor(AIDATATASKRUNER_COLOR_BORDER); sh.ThumbColorHover(AIDATATASKRUNER_COLOR_BORDER_HOVER); sh.ThumbColorPressed(AIDATATASKRUNER_COLOR_ACCENT); sh.IncFile((string)RESOURCE_SCROLL_LEFT_WHITE); sh.IncFileLocked((string)RESOURCE_SCROLL_LEFT_WHITE); sh.IncFilePressed((string)RESOURCE_SCROLL_LEFT_WHITE); sh.DecFile((string)RESOURCE_SCROLL_RIGHT_WHITE); sh.DecFileLocked((string)RESOURCE_SCROLL_RIGHT_WHITE); sh.DecFilePressed((string)RESOURCE_SCROLL_RIGHT_WHITE); //--- m_table_results.CellYSize(30); m_table_results.FontSize(10); m_table_results.HeaderYSize(25); m_table_results.IsSortMode(true); m_table_results.DefaultTextAlign(ALIGN_LEFT); m_table_results.TableSize(TABWF_TABLERES_TOTAL_COLS, 1); //--- m_table_results.DataType(TABWF_TABLERES_COL_NAME, TYPE_STRING); m_table_results.SetValue(TABWF_TABLERES_COL_NAME, 0, ""); m_table_results.DataType(TABWF_TABLERES_COL_RES, TYPE_STRING); m_table_results.SetValue(TABWF_TABLERES_COL_RES, 0, ""); m_table_results.DataType(TABWF_TABLERES_COL_STATE, TYPE_STRING); m_table_results.SetValue(TABWF_TABLERES_COL_STATE, 0, ""); m_table_results.DataType(TABWF_TABLERES_COL_TIME, TYPE_STRING); m_table_results.SetValue(TABWF_TABLERES_COL_TIME, 0, ""); //--- int widths[TABWF_TABLERES_TOTAL_COLS]; widths[TABWF_TABLERES_COL_NAME] = 332; widths[TABWF_TABLERES_COL_RES] = 100; widths[TABWF_TABLERES_COL_STATE] = 100; widths[TABWF_TABLERES_COL_TIME] = 75; m_table_results.ColumnsWidth(widths); //--- int arr_offset_image_x[TABWF_TABLERES_TOTAL_COLS]; int arr_offset_image_y[TABWF_TABLERES_TOTAL_COLS]; ArrayFill(arr_offset_image_x, 0, TABWF_TABLERES_TOTAL_COLS, 0); ArrayFill(arr_offset_image_y, 0, TABWF_TABLERES_TOTAL_COLS, 0); arr_offset_image_y[TABWF_TABLERES_COL_STATE] = 5; arr_offset_image_x[TABWF_TABLERES_COL_STATE] = 5; m_table_results.ImageXOffset(arr_offset_image_x); m_table_results.ImageYOffset(arr_offset_image_y); //--- int text_x_offset[TABWF_TABLERES_TOTAL_COLS]; ArrayInitialize(text_x_offset, 10); text_x_offset[TABWF_TABLERES_COL_STATE] += 15; m_table_results.TextXOffset(text_x_offset); //--- if(!p.CreateTable(m_table_results, main_window, 0, m_tabs, 1, TABWF_TABLERES_TOTAL_COLS, 1, headers, x, y, 0, 0, false, false, right_gap + 5, bottom_gap + 5)) { GUIBASE_ERROR_CREATION(m_table_results); return false; } //--- return true; } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ void CTabWorkflows::OnLenguajeChange(void) { //--- Tab string txt[2] = {m_language[GUIBASE_COMPONENT_NAME(m_tabs) + "_0"], m_language[GUIBASE_COMPONENT_NAME(m_tabs) + "_1"]}; for(int i = 0; i < 2; i++) { m_tabs.Text(i, txt[i]); } m_tabs.Update(); //--- Tab 0 //- Titulo UpdateTBasic(m_label_tit_workflows, GUIBASE_COMPONENT_NAME(m_label_tit_workflows), false); //- Label selec UpdateTBasic(m_label_selec_wf, GUIBASE_COMPONENT_NAME(m_label_selec_wf)); //- Label val m_label_selec_val_wf.Tooltip(m_language.Tooltip(GUIBASE_COMPONENT_NAME(m_label_selec_val_wf))); //- UpdateTBasic(m_btn_browse_wf, GUIBASE_COMPONENT_NAME(m_btn_browse_wf)); UpdateTBasic(m_btn_template_wf, GUIBASE_COMPONENT_NAME(m_btn_template_wf)); UpdateTBasic(m_btn_open_wf, GUIBASE_COMPONENT_NAME(m_btn_open_wf)); //- Label wf name UpdateTBasic(m_label_wf_name, GUIBASE_COMPONENT_NAME(m_label_wf_name), false); m_label_the_wf_name.Tooltip(m_language.Tooltip(GUIBASE_COMPONENT_NAME(m_label_the_wf_name))); if(m_state == WF_STATE_ESPERANDO_RUNNER) { m_label_the_wf_name.LabelText(m_language[GUIBASE_COMPONENT_NAME(m_label_the_wf_name) + "_esperar_runer"]); m_label_the_wf_name.Update(true); } else if(m_state == WF_STATE_ESPERANDO_NADA) { m_label_the_wf_name.LabelText(m_language[GUIBASE_COMPONENT_NAME(m_label_the_wf_name) + "_nada"]); m_label_the_wf_name.Update(true); } //- UpdateTBasic(m_btn_run_wf, GUIBASE_COMPONENT_NAME(m_btn_run_wf)); UpdateTBasic(m_btn_relanzar_ea, GUIBASE_COMPONENT_NAME(m_btn_relanzar_ea)); //--- Tabla UpdateTBasic(m_label_tit_execution, GUIBASE_COMPONENT_NAME(m_label_tit_execution), false); // Headers string headers[]; const string header_str = m_language[GUIBASE_COMPONENT_NAME(m_table_results) + "_header"]; if(!StrTo::CstArray(headers, header_str, '|', true)) { LogError(StringFormat("Fallo al hacer str to array str, str = %s", header_str), FUNCION_ACTUAL); return; } ArrayResize(headers, TABWF_TABLERES_TOTAL_COLS); for(int i = 0; i < TABWF_TABLERES_TOTAL_COLS; i++) { m_table_results.SetHeaderText(i, headers[i]); } // Names if(StringSplit(m_language[GUIBASE_COMPONENT_NAME(m_arr_names_tables)], '|', m_arr_names_tables) != 4) { LogFatalError("No se pudo hacer split a los nombres de los estados", FUNCION_ACTUAL); return; } const int t = (int)m_table_results.RowsTotal(); if(m_table_results.GetValue(0, 0) != "") // Hay contenido { for(int i = 0; i < t; i++) { m_table_results.SetValue(TABWF_TABLERES_COL_STATE, i, m_arr_names_tables[TABWF_IMAGE_EN_PENDIENTE]); } } m_table_results.Update(true); } //+------------------------------------------------------------------+ //| Ejecucino del ea base | //+------------------------------------------------------------------+ bool CTabWorkflows::RunEA() { //--- const long current_chart_id = ChartID(); m_last_runner_chart_id = OpenChartAndDevoler(current_chart_id, _Symbol, _Period, 250); if(m_last_runner_chart_id == -1) { MessageBox(GUIBASE_MSG("err_open_chart"), GUIBASE_COMMON("error"), MB_OK); return false; } //--- Parametros MqlParam params[4]; params[0].type = TYPE_STRING; params[0].string_value = "Experts\\" + m_path_ea; //- Chart id params[1].type = TYPE_LONG; params[1].integer_value = current_chart_id; //- Temp wf file params[2].type = TYPE_STRING; params[2].string_value = m_path_to_wf_temp; //- Common flag params[3].type = TYPE_BOOL; params[3].integer_value = AIDATATASK_RUNNER_COMON_FLAG_VAL; //--- if(!EXPERT::Run(m_last_runner_chart_id, params, EXPERT_PERMISOS_FLAG_DLL)) { ::ChartClose(m_last_runner_chart_id); MessageBox(GUIBASE_MSG("err_run"), GUIBASE_COMMON("error"), MB_OK); LogError("EA Params: ", FUNCION_ACTUAL); ArrayPrint(params, 4, "|"); return false; } else { LogCaution("EA runnner wf ejeuctado correctamente", FUNCION_ACTUAL); } //--- Escribimos la info que enviaremos (inicial) ::ResetLastError(); const int fh = FileOpen(m_path_to_wf_temp, FILE_WRITE | AIDATATASK_RUNNER_COMON_FLAG | FILE_TXT); if(fh == INVALID_HANDLE) { ::ChartClose(m_last_runner_chart_id); LogFatalError(StringFormat("No se pudo escribir los datos iniciales para el runner, fallo al abrir el archivo:\n%s", m_path_to_wf_temp), FUNCION_ACTUAL); return false; } // Escribimos los datos iniciales // Datos iniciales (nunca cambian) FileWrite(fh, AIDATATASKRUNER_PATH_TEMPLATES); // Path templates FileWrite(fh, AIDATATASKRUNER_PATH_TASK); // Path task FileWrite(fh, AIDATATASKRUNER_BASE_FOLDER); // Base folder FileClose(fh); //--- Comando de iniciar // Internamete el runner creara las varialbes basicas para el YML if(!EventChartCustom(m_last_runner_chart_id, AIDATATASKRUNER_RUNNER_WF_EVENT_INIT, 0, 0.00, "")) { ::ChartClose(m_last_runner_chart_id); LogFatalError("No se pudo enviar el evento de inicio al runner", FUNCION_ACTUAL); return false; // ya no se inicia el bot } //--- return true; } //+------------------------------------------------------------------+ //| Run WF | //+------------------------------------------------------------------+ void CTabWorkflows::RunWF() { //--- Check yml file const string label_wf_text = m_label_selec_val_wf.LabelText(); if(label_wf_text.Length() < 4) // .yml { MessageBox(GUIBASE_MSG("err_invalid_yml_file"), GUIBASE_COMMON("error"), MB_OK); return; } //--- Mandamos el evento de inicio ::ResetLastError(); if(!::EventChartCustom(m_last_runner_chart_id, AIDATATASKRUNER_RUNNER_WF_EVENT_ON_NEW_WF, 0, 0.00, label_wf_text)) { MessageBox(StringFormat(GUIBASE_MSG("err_cannot_init"), ::GetLastError()), GUIBASE_COMMON("error"), MB_OK); return; } //--- Cambiamso el texto a uno que diga esperando como "Workflow: Esperando al runner ..." m_state = WF_STATE_ESPERANDO_RUNNER; m_label_the_wf_name.LabelText(m_language[GUIBASE_COMPONENT_NAME(m_label_the_wf_name) + "_esperar_runer"]); m_label_the_wf_name.Update(true); } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ bool CTabWorkflows::OnClickButtom(const long lparam) { //--- if(m_tabs.SelectedTab() != 0) return true; // Si es la otra salimos de inmediato no hace falta ni revisar //--- if(m_btn_browse_wf.Id() == lparam) { //--- string arr[]; if(FileSelectDialog(GUIBASE_MSG("flselect_run_yml"), AIDATATASKRUNER_PATH_WORKFLOWS, "YML Files (*.yml)|*.yml|YAML Files (*.yaml)|*.yaml", AIDATATASK_RUNNER_FSD_COMON_FLAG, arr, NULL) != 1) { MessageBox(GUIBASE_MSG("error_select_file"), GUIBASE_COMMON("error"), MB_ICONERROR | MB_OK); return true; } //--- m_label_selec_val_wf.LabelText(arr[0]); // ruta completa aqui m_label_selec_val_wf.Update(true); //--- return true; } if(m_btn_template_wf.Id() == lparam) { //--- string arr[]; if(FileSelectDialog(GUIBASE_MSG("flselect_run_yml"), AIDATATASKRUNER_PATH_TEMPLATES, "YML Files (*.yml)|*.yml|YAML Files (*.yaml)|*.yaml", AIDATATASK_RUNNER_FSD_COMON_FLAG, arr, AIDATATASKRUNER_FILE_NAME_WORKFLOWS_BASICGENERATION) != 1) { MessageBox(GUIBASE_MSG("error_select_file"), GUIBASE_COMMON("error"), MB_ICONERROR | MB_OK); return true; } //--- m_label_selec_val_wf.LabelText(arr[0]); // ruta completa aqui m_label_selec_val_wf.Update(true); //--- return true; } if(m_btn_open_wf.Id() == lparam) { const string full_path = (AIDATATASK_RUNNER_COMON_FLAG_VAL ? TERMINAL_MT5_COMMON_PATH : (TERMINAL_MT5_DATA_PAH + "\\MQL5")) + "\\Files\\" + m_label_selec_val_wf.LabelText(); ShellExecuteW(0, "open", full_path, NULL, NULL, SW_SHOW); // no verificamos noe s critrico return true; } //--- if(m_btn_run_wf.Id() == lparam) { RunWF(); return true; } if(m_btn_relanzar_ea.Id() == lparam) { // Si el grafico existe (osea ya se lanzo se quiere un relanze entonces quitamos) if(::ChartSymbol(m_last_runner_chart_id) != "") { ::ChartClose(m_last_runner_chart_id); m_last_runner_chart_id = -1; } // Lanzamos RunEA(); return true; // Volvemos a correr el EA } //--- return false; } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ void CTabWorkflows::OnWfStart(void) { //--- ::ResetLastError(); const int fh = FileOpen(m_path_to_wf_temp, FILE_READ | FILE_TXT | AIDATATASK_RUNNER_COMON_FLAG); if(fh == INVALID_HANDLE) { LogFatalError(StringFormat("Fallo al abrir el archivo = %s, ultimo err = %d, cancelando wf", m_path_to_wf_temp, ::GetLastError()), FUNCION_ACTUAL); //--- Cerramos el grafico (se sale el ea) y le decimso al usario el error y que lo relanze ::ChartClose(m_last_runner_chart_id); MessageBox(GUIBASE_MSG("err_read_data"), GUIBASE_MSG("error"), MB_OK | MB_ICONERROR); return; } //--- Nombre del wf m_label_the_wf_name.LabelText(FileReadString(fh)); m_label_the_wf_name.Update(true); //--- Tabla const int t_wf = int(FileReadString(fh)); m_table_results.ResizeRows(t_wf, false); for(int i = 0; i < t_wf; i++) { //--- m_table_results.SetValue(TABWF_TABLERES_COL_NAME, i, FileReadString(fh), 0); m_table_results.SetValue(TABWF_TABLERES_COL_RES, i); m_table_results.SetValue(TABWF_TABLERES_COL_TIME, i, "?s"); //--- State cambiamos valor e imagen m_table_results.SetValue(TABWF_TABLERES_COL_STATE, i, m_arr_names_tables[TABWF_IMAGE_EN_PENDIENTE]); m_table_results.SetImages(TABWF_TABLERES_COL_STATE, i, g_aitaskruner_wf_img); m_table_results.ChangeImage(TABWF_TABLERES_COL_STATE, i, TABWF_IMAGE_EN_PENDIENTE); } if(t_wf) // Al menos 1 { // 0 en ejeucion m_table_results.ChangeImage(TABWF_TABLERES_COL_STATE, 0, TABWF_IMAGE_EN_EJECUCION); m_table_results.SetValue(TABWF_TABLERES_COL_STATE, 0, m_arr_names_tables[TABWF_IMAGE_EN_EJECUCION]); //--- m_table_results.Update(true); } //--- FileClose(fh); m_state = WF_STATE_ESPERANDO_EJECUTANDO; } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ void CTabWorkflows::OnWfStep(const string &sparam) { //--- // stepindex | code static string arr[3]; const int t = StringSplit(sparam, AIDATATASKRUNER_RUNNER_WF_SEP, arr); if(t != 3) { LogFatalError("Formato incorrecto de sparam", FUNCION_ACTUAL); return; } //--- const int r = int(arr[0]); //--- Current row pasedd m_table_results.SetValue(TABWF_TABLERES_COL_RES, r, (arr[1])); m_table_results.SetValue(TABWF_TABLERES_COL_STATE, r, m_arr_names_tables[TABWF_IMAGE_EN_EXTIO]); m_table_results.ChangeImage(TABWF_TABLERES_COL_STATE, r, TABWF_IMAGE_EN_EXTIO); m_table_results.SetValue(TABWF_TABLERES_COL_TIME, r, arr[2]); //--- Siguiente row la ponemos en ejeuccion m_table_results.ChangeImage(TABWF_TABLERES_COL_STATE, r + 1, TABWF_IMAGE_EN_EJECUCION); m_table_results.SetValue(TABWF_TABLERES_COL_STATE, r + 1, m_arr_names_tables[TABWF_IMAGE_EN_EJECUCION]); //--- Update m_table_results.Update(true); } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ void CTabWorkflows::OnWfEnd(const string &sparam) { //--- LogCaution(StringFormat("Wf ha terminado, sparam:\n%s", sparam), FUNCION_ACTUAL); m_state = WF_STATE_ESPERANDO_NADA; //--- // stepindex | code static string arr[3]; const int t = StringSplit(sparam, AIDATATASKRUNER_RUNNER_WF_SEP, arr); if(t != 3) { LogFatalError("Formato incorrecto de sparam", FUNCION_ACTUAL); return; } //--- const int r = int(arr[0]); const int code = int(arr[1]); //--- Current row pasedd m_table_results.SetValue(TABWF_TABLERES_COL_RES, r, arr[1]); const int idx = code == 0 ? TABWF_IMAGE_EN_EXTIO : TABWF_IMAGE_EN_FALLO; m_table_results.SetValue(TABWF_TABLERES_COL_STATE, r, m_arr_names_tables[idx]); m_table_results.ChangeImage(TABWF_TABLERES_COL_STATE, r, idx); m_table_results.SetValue(TABWF_TABLERES_COL_TIME, r, arr[2]); //--- Update table m_table_results.Update(true); //--- Label m_label_the_wf_name.LabelText(m_language[GUIBASE_COMPONENT_NAME(m_label_the_wf_name) + "_nada"]); m_label_the_wf_name.Update(true); } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ void CTabWorkflows::ChartEvent(const int id, const long &lparam, const double &dparam, const string &sparam) { //--- if(m_state == WF_STATE_ESPERANDO_NADA) // En caso se este esperando nada salimos return; //--- if(id == CHARTEVENT_CUSTOM + AIDATATASKRUNER_RUNNER_WF_ON_EVENT) { const uint8_t ei = uint8_t(lparam); switch(ei) { case AIDATATASKRUNER_RUNNER_WF_E_ON_STEP: { OnWfStep(sparam); break; } case AIDATATASKRUNER_RUNNER_WF_E_ON_END: { OnWfEnd(sparam); break; } case AIDATATASKRUNER_RUNNER_WF_E_ON_START: { OnWfStart(); break; } case AIDATATASKRUNER_RUNNER_WF_E_ON_END_CRITICAL: { //--- ERn caso de que ni siquiera se haya ejetudado start LogError("No se pudo ejeuctar el wf, error critico en su ejecucion", FUNCION_ACTUAL); LogError(StringFormat("val:\n%s", sparam), FUNCION_ACTUAL); m_state = WF_STATE_ESPERANDO_NADA; //::ChartClose(m_last_runner_chart_id); no cerramos solo hubo un error se puede reejecutar m_label_the_wf_name.LabelText(m_language[GUIBASE_COMPONENT_NAME(m_label_the_wf_name) + "_nada"]); m_label_the_wf_name.Update(true); break; } } } } //+------------------------------------------------------------------+ #endif // AIDATATASKRUNER_UI_TABWORKFLOWS_MAIN_MQH