diff --git a/db/pgConn.cpp b/db/pgConn.cpp index f99a8a6..b460841 100644 --- a/db/pgConn.cpp +++ b/db/pgConn.cpp @@ -976,13 +976,20 @@ void pgConn::LogError(const bool quiet) { if (conn) { - if (quiet) + bool abnormal_termination = false; + wxString err = GetLastError().Trim(); + if (err.Find("server closed the connection unexpectedly") >= 0) { + //Close(); + //connStatus = PGCONN_BROKEN; + abnormal_termination = true; + } + if (quiet || abnormal_termination) { - wxLogQuietError(wxT("%s"), GetLastError().Trim().c_str()); + wxLogQuietError(wxT("%s"), err.c_str()); } else { - wxLogError(wxT("%s"), GetLastError().Trim().c_str()); + wxLogError(wxT("%s"), err.c_str()); IsAlive(); } } diff --git a/frm/frmLog.cpp b/frm/frmLog.cpp index 495bf86..e9a9e28 100644 --- a/frm/frmLog.cpp +++ b/frm/frmLog.cpp @@ -23,9 +23,10 @@ #include "ctl/ctlAuiNotebook.h" #include "utils/csvfiles.h" #include "log/StorageModel.h" +#include "utils/utffile.h" #include - +#include @@ -34,10 +35,16 @@ WX_DEFINE_OBJARRAY(RemoteConnArray2); wxBEGIN_EVENT_TABLE(frmLog, pgFrame) // test +EVT_MENU(MNU_FIND_TEXT, frmLog::OnFind) +EVT_MENU(MNU_SEND_MAIL, frmLog::OnSendMail) EVT_CHECKBOX(ID_SET_GROUP, frmLog::OnSetGroup) EVT_CHECKBOX(ID_SET_DETAILGROUP, frmLog::OnSetDetailGroup) EVT_BUTTON(ID_CLEAR_ALL_FILTER, frmLog::OnClearAllFilter) EVT_BUTTON(ID_ADD_FILTER, frmLog::OnAddFilterIgnore) +EVT_BUTTON(ID_ADD_UFilter, frmLog::OnAddUFilter) +EVT_BUTTON(ID_DEL_UFilter, frmLog::OnDelUFilter) +EVT_COMBOBOX(ID_CBOX_UFilter, frmLog::OnChangeUFilter) +EVT_COMBOBOX(ID_CBOX_SMART, frmLog::OnChangeSmart) EVT_SET_FOCUS(frmLog::OnSetFocus) EVT_KILL_FOCUS(frmLog::OnKillFocus) EVT_ACTIVATE(frmLog::OnActivate) @@ -65,11 +72,120 @@ void frmLog::OnKillFocus(wxFocusEvent& event) { // Class declarations void frmLog::OnClearAllFilter(wxCommandEvent& event) { - my_view->ClearAllFilter(); + my_view->ClearAllFilter(false); } void frmLog::OnAddFilterIgnore(wxCommandEvent& event) { + wxString Fname = "LoadSkip"; + my_view->ModUserFilter(Fname, "AddUserFilter", listUserFilter, contentFilter); + //my_view->AddFilterIgnore(Fname); +} +void frmLog::OnAddUFilter(wxCommandEvent& event) { + wxString txt = listUserFilter->GetValue(); + my_view->ModUserFilter(txt, "AddUserFilter", listUserFilter, contentFilter); + +} +void frmLog::OnDelUFilter(wxCommandEvent& event) { + my_view->ModUserFilter("", "RemoveFilter", listUserFilter, contentFilter); +} +void frmLog::OnChangeUFilter(wxCommandEvent& event) { + if (event.GetSelection() >= 0) { + my_view->ModUserFilter("", "ChangeFilter", listUserFilter, contentFilter); + } +} +void frmLog::OnChangeSmart(wxCommandEvent& event) { + int n = event.GetSelection(); + if (n >= 0) { + listUserFilter->SetSelection(n); + my_view->ModUserFilter("", "ChangeFilter", listUserFilter, contentFilter); + } +} +wxString escapeHtml(wxString text) { + text.Replace("&", "&"); + text.Replace("<", "<"); + text.Replace(">", ">"); + text.Replace("\n", "¶
"); + return text; +} +void frmLog::OnSendMail(wxCommandEvent& event) { + //wxMessageBox("send mail"); + wxDataViewItem item; + item = my_view->GetCurrentItem(); + if (!item.IsOk() ) { + return; + } + wxVariant v, t; + StorageModel* m = dynamic_cast(my_view->GetModel()); + Storage* st = m->getStorage(); + wxArrayString a; + int r = m->GetRow(item); + if (r != -1) { + a=st->GetAllFields(r, st->IsFilter()); + } + else return; + + wxString str = ""; +#ifdef DEBUG + wxString fn = "C:\\Users\\lsv\\Source\\Repos\\pgadmin64\\pgadmin\\x64\\Debug_(3.0)\\testhtml.txt" ; +#else + wxString fn = "testhtml.txt"; +#endif // DEBUG + wxUtfFile file(fn, wxFile::read, wxFONTENCODING_UTF8); + if (file.IsOpened()) + { + file.Read(str); + file.Close(); + wxStringTokenizer tk(str, "\n", wxTOKEN_DEFAULT); + wxString cc; + wxString to; + wxString html; + wxString templat; + while (tk.HasMoreTokens()) + { + wxString l = tk.GetNextToken(); + if (l.StartsWith("Cc=")) { cc = l.After('='); continue; } + if (l.StartsWith("To=")) { to = l.After('='); continue; } + if (l.StartsWith("")) { + wxString le; + wxString r; + for (int i = 0; i < a.Count(); i++) { + templat = l; + le = escapeHtml(a[i++]); + r = escapeHtml(a[i]); + int co = templat.Replace("$1", le); + co += templat.Replace("$2", r); + html.Append(templat); + } + continue; + } + html.Append(l); + } + wxAutomationObject oObject; + if (oObject.GetInstance("Outlook.Application")) { + wxAutomationObject msg; + wxVariant n[1]; + wxString strI; + int i = 0; + strI << i; + n[0] = wxVariant(strI); + bool rez = oObject.GetObject(msg, "CreateItem", 1, n); + if (rez) { + //oObject.PutProperty("Visible", true); + msg.PutProperty("Subject", "Ошибка "); + msg.PutProperty("BodyFormat", 2); + msg.PutProperty("To", to); + //msg.PutProperty("BCC", "Балашов Игорь Николаевич ; Иванов Артем Геннадьевич "); + msg.PutProperty("Cc", cc); + msg.PutProperty("HTMLBody", html); + msg.CallMethod("Display"); + } + //oObject.PutProperty("ActiveCell.Font.Bold", @true); + + } + + } +} +void frmLog::OnFind(wxCommandEvent& event) { - my_view->AddFilterIgnore(); } void frmLog::OnSetGroup(wxCommandEvent& event) { @@ -133,8 +249,22 @@ void frmLog::getFilename() { if (!namepage.IsEmpty()) namepage += ","; if (!conArray[i].conn->IsAlive()) { - namepage += "-"+conArray[i].conn->GetDbname(); - continue; + wxDateTime n = wxDateTime::Now(); + if (conArray[i].nextrun < n) { + if (!conArray[i].conn->Reconnect()) + { + wxTimeSpan sp(0, 5); + conArray[i].nextrun = wxDateTime::Now() + sp; + namepage += "-" + conArray[i].conn->GetDbname(); + continue; + } + } + else { + namepage += "?" + conArray[i].conn->GetDbname(); + continue; + } + + } set = conArray[i].conn->ExecuteSet( wxT("select current_setting('log_directory')||'/'||name filename,modification filetime,size len\n") @@ -252,7 +382,8 @@ void frmLog::readLogFile(wxString logfileName,long& lenfile,long& logfileLength, } int l= strlen(raw); logfileLength += l; - status->SetLabelText(wxString::Format("Load bytes %ld", logfileLength)); + wxString host = conn->GetHostName(); + status->SetLabelText(wxString::Format("%s Load bytes %ld", host,logfileLength)); wxString str; str = line + wxTextBuffer::Translate(wxString(raw, set->GetConversion()), wxTextFileType_Unix); //if (wxString(wxString(raw, wxConvLibc).wx_str(), wxConvUTF8).Len() > 0) @@ -411,7 +542,13 @@ frmLog::frmLog(frmMain *form, const wxString &_title, pgServer *srv) : pgFrame(N idefRed = wxIcon(log_red_xpm); seticon(false); mainForm = form; - + // Setup accelerators + wxAcceleratorEntry entries[2]; + entries[0].Set(wxACCEL_CTRL, (int)'F', MNU_FIND); + entries[1].Set(wxACCEL_CTRL, (int)'S', MNU_SEND_MAIL); + wxAcceleratorTable accel(2, entries); + SetAcceleratorTable(accel); + m_notebook = new wxNotebook( this, wxID_ANY ); wxPanel* testPanel = new wxPanel(m_notebook, wxID_ANY); @@ -466,12 +603,21 @@ frmLog::frmLog(frmMain *form, const wxString &_title, pgServer *srv) : pgFrame(N sSizer->Add(new wxButton(testPanel, ID_CLEAR_ALL_FILTER, "Clear All Filter"), border1); //sSizer->Add(new wxButton(testPanel, ID_DELETE_SEL, "Delete selected"), border); sSizer->Add(new wxButton(testPanel, ID_ADD_FILTER, "Add Filter Ignore"), border1); + smart = new wxComboBox(testPanel, ID_CBOX_SMART, wxT(""), wxDefaultPosition, wxDefaultSize, 0, NULL, 0); + //smart->SetWindowStyle(smart->GetWindowStyle()|wxCB_READONLY); + smart->SetMinSize(wxSize(300,-1)); + //listUserFilter = new wxComboBox(testPanel, ID_CBOX_UFilter, wxT("Combo!"), wxDefaultPosition, wxDefaultSize, 0, NULL, 0); + sSizer->Add(smart, border1); + my_view->smart = smart; zeroPanelSz->Add(sSizer); testPanel->SetSizerAndFit(zeroPanelSz); m_notebook->AddPage(testPanel, "Log"); + wxBoxSizer* setingSZ = new wxBoxSizer(wxHORIZONTAL); + setingSZ->Add(m_notebook); + wxPanel* settingPanel = new wxPanel(m_notebook, wxID_ANY); lb = new wxCheckListBox(settingPanel,wxID_ANY); wxTreeItemIdValue foldercookie, servercookie; @@ -523,9 +669,39 @@ frmLog::frmLog(frmMain *form, const wxString &_title, pgServer *srv) : pgFrame(N } - wxSizer* zeroPanelSz2 = new wxBoxSizer(wxVERTICAL); + wxSizer* zeroPanelSz2 = new wxBoxSizer(wxHORIZONTAL); lb->SetMinSize(wxSize(-1, 200)); zeroPanelSz2->Add(lb, 1, wxGROW | wxALL, 5); + + wxPanel *m_panel2 = new wxPanel(settingPanel, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL); + + zeroPanelSz2->Add(m_panel2, 1, wxEXPAND | wxALL, 5); + + wxBoxSizer* bSizer3; + bSizer3 = new wxBoxSizer(wxVERTICAL); + + wxBoxSizer* bSizer2; + bSizer2 = new wxBoxSizer(wxHORIZONTAL); + listUserFilter = new wxComboBox(m_panel2, ID_CBOX_UFilter, wxT("Combo!"), wxDefaultPosition, wxDefaultSize, 0, NULL, 0); + bSizer2->Add(listUserFilter, 1, wxALL | wxEXPAND, 2); + wxButton *m_button1 = new wxButton(m_panel2, ID_ADD_UFilter, wxT("Add"), wxDefaultPosition, wxDefaultSize, 0); + m_button1->SetMaxSize(wxSize(30, -1)); + bSizer2->Add(m_button1, 0, wxALL, 2); + wxButton *m_button2 = new wxButton(m_panel2, ID_DEL_UFilter, wxT("Del"), wxDefaultPosition, wxDefaultSize, 0); + m_button2->SetMaxSize(wxSize(30, -1)); + bSizer2->Add(m_button2, 0, wxALL, 2); + bSizer3->Add(bSizer2, 0, wxEXPAND, 5); + + wxBoxSizer* bSizer5; + bSizer5 = new wxBoxSizer(wxVERTICAL); + + contentFilter = new wxTextCtrl(m_panel2, ID_TEXT_UFilter, wxEmptyString, wxDefaultPosition, wxDefaultSize, wxTE_MULTILINE); + bSizer5->Add(contentFilter, 1, wxALL | wxEXPAND, 2); + bSizer3->Add(bSizer5, 1, wxEXPAND, 2); + m_panel2->SetSizer(bSizer3); + + //listUserFilter->Bind(); + settingPanel->SetSizerAndFit(zeroPanelSz2); m_notebook->AddPage(settingPanel, "Settings"); @@ -533,6 +709,7 @@ frmLog::frmLog(frmMain *form, const wxString &_title, pgServer *srv) : pgFrame(N settings->Read(dlgName + "/Mode",&b, false); group->SetValue(b); my_view->setGroupMode(b); + my_view->ModUserFilter("","Init", listUserFilter, contentFilter); // if (mainForm) getFilename(); m_timer.Start(timerInterval); } diff --git a/frm/frmMain.cpp b/frm/frmMain.cpp index fd73a37..7466155 100644 --- a/frm/frmMain.cpp +++ b/frm/frmMain.cpp @@ -90,6 +90,8 @@ #include "schema/pgCheck.h" #include "schema/pgDomain.h" #include "schema/pgEventTrigger.h" +#include +#include "utils/utffile.h" #if defined(HAVE_OPENSSL_CRYPTO) || defined(HAVE_GCRYPT) #include "utils/sshTunnel.h" @@ -241,6 +243,10 @@ frmMain::frmMain(const wxString &title) browser->Expand(root); browser->SortChildren(root); browser->SetFocus(); + + + + } diff --git a/frm/frmQuery.cpp b/frm/frmQuery.cpp index d7de274..7e8cb17 100644 --- a/frm/frmQuery.cpp +++ b/frm/frmQuery.cpp @@ -692,7 +692,10 @@ frmQuery::frmQuery(frmMain *form, const wxString &_title, pgConn *_conn, const w viewMenu->Check(MNU_TOOLBAR, manager.GetPane(wxT("toolBar")).IsShown()); viewMenu->Check(MNU_OUTPUTPANE, manager.GetPane(wxT("outputPane")).IsShown()); viewMenu->Check(MNU_SCRATCHPAD, manager.GetPane(wxT("scratchPad")).IsShown()); - + wxAuiPaneInfo &pn = manager.GetPane(wxT("outputPane")); + if (!pn.HasMaximizeButton()) { + pn.MaximizeButton(true); + } // tell the manager to "commit" all the changes just made manager.Update(); diff --git a/frm/frmStatus.cpp b/frm/frmStatus.cpp index 7812d5a..595f1ac 100644 --- a/frm/frmStatus.cpp +++ b/frm/frmStatus.cpp @@ -210,14 +210,12 @@ frmStatus::frmStatus(frmMain *form, const wxString &_title, pgConn *conn) : pgFr logFormatKnown = false; // Only superusers can set these parameters... - pgUser *user = new pgUser(connection->GetUser()); - if (user) - { - if (user->GetSuperuser()) + + if (connection->IsSuperuser()) { // Make the connection quiet on the logs if (connection->BackendMinimumVersion(8, 0)) - initquery = wxT("SET log_statement='none';SET log_duration='off';SET log_min_duration_statement=-1;"); + initquery = wxT("SET log_statement='none';SET log_duration='off';SET log_min_duration_statement=-1;SET statement_timeout=10000;"); else initquery = wxT("SET log_statement='off';SET log_duration='off';SET log_min_duration_statement=-1;"); #ifndef _DEBUG @@ -232,8 +230,7 @@ frmStatus::frmStatus(frmMain *form, const wxString &_title, pgConn *conn) : pgFr isrecovery = (v == wxT("t")); v = connection->ExecuteScalar(wxT("select current_setting('track_commit_timestamp')")); track_commit_timestamp = (v == wxT("on")); - delete user; - } + // Notify wxAUI which frame to use manager.SetManagedWindow(this); diff --git a/include/frm/frmLog.h b/include/frm/frmLog.h index fd856db..e88ed8e 100644 --- a/include/frm/frmLog.h +++ b/include/frm/frmLog.h @@ -43,6 +43,7 @@ public: } pgConn* conn; + wxDateTime nextrun; }; WX_DECLARE_OBJARRAY(RemoteConn2, RemoteConnArray2); @@ -53,6 +54,13 @@ enum ID_CLEAR_ALL_FILTER = 208, ID_SET_DETAILGROUP = 209, ID_ADD_FILTER = 210, + ID_ADD_UFilter=211, + ID_DEL_UFilter = 212, + ID_CBOX_UFilter = 213, + ID_TEXT_UFilter = 214, + ID_CBOX_SMART = 215, + MNU_SEND_MAIL=216, + MNU_FIND_TEXT=217, ID_NEXT_MAX }; @@ -101,6 +109,9 @@ private: wxStaticText* status; wxCheckBox *group, *detail; wxCheckListBox* lb; + wxComboBox* listUserFilter; + wxComboBox* smart; + wxTextCtrl* contentFilter; wxObjectDataPtr m_storage_model; wxArrayString logfileName; wxArrayString savedPartialLine; @@ -110,6 +121,13 @@ private: void OnSetDetailGroup(wxCommandEvent& event); void OnClearAllFilter(wxCommandEvent& event); void OnAddFilterIgnore(wxCommandEvent& event); + void OnAddUFilter(wxCommandEvent& event); + void OnDelUFilter(wxCommandEvent& event); + void OnChangeUFilter(wxCommandEvent& event); + void OnChangeSmart(wxCommandEvent& event); + void OnSendMail(wxCommandEvent& event); + void OnFind(wxCommandEvent& event); + void OnSetFocus(wxFocusEvent& event); void OnKillFocus(wxFocusEvent& event); void OnActivate(wxActivateEvent& event); diff --git a/include/log/MyDataViewCtrl.h b/include/log/MyDataViewCtrl.h index 773b7a7..f3e83cf 100644 --- a/include/log/MyDataViewCtrl.h +++ b/include/log/MyDataViewCtrl.h @@ -25,8 +25,10 @@ public: void setSettingString(wxString setstr); void setGroupMode(bool mode); void ViewGroup(bool view); - void ClearAllFilter(); - void AddFilterIgnore(); + void ClearAllFilter(bool no_apply); + + void ModUserFilter(wxString FilterName, wxString wxOper, wxComboBox* combo, wxTextCtrl* textctrl); + void AddFilterIgnore(wxString Fname); void AddRow(wxString csvtext); void OnMouseMove(wxMouseEvent& event); void OnKEY_DOWN(wxKeyEvent& event); @@ -39,6 +41,7 @@ public: void OnEVT_DATAVIEW_CONTEXT_MENU(wxCommandEvent& event); void OnEVT_DATAVIEW_SELECTION_CHANGED(wxDataViewEvent& event); void OnContextMenu(wxDataViewEvent& event); + wxComboBox* smart; DECLARE_EVENT_TABLE() private: @@ -46,6 +49,7 @@ private: wxDataViewItem selectRowGroup; bool modctrl = false; wxStaticText* st; + //bool visibleEndLine = false; #ifdef MYTEST int linenumber = -1; diff --git a/include/log/Storage.h b/include/log/Storage.h index af11ab8..4f797a2 100644 --- a/include/log/Storage.h +++ b/include/log/Storage.h @@ -75,6 +75,7 @@ struct LineFilter { int col; int flags; wxString val; + wxString NameFilter; }; class Storage @@ -103,10 +104,11 @@ public: // приминить фильтр для строки или для все строк хранилища // true если строка не отфильтровалась (видна) bool ApplyFilter(int row = -1); + int SetFilterArray(std::deque arr); wxString getStrGroup(wxString source); int testFilter(MyConst::colField col, int position); wxString GetStringFilterExpr(int positionArrayFilter,bool addNumCol=false); - void addLineFilterStr(wxString strflt); + void addLineFilterStr(wxString strflt,wxString fn); wxString _strwhere(int flags); void saveFilters(); wxString LineFilterToStr(LineFilter& lf); @@ -140,18 +142,23 @@ public: bool IsAddGroupNew() { return faddgroup; }; + std::deque getFilter(wxString FilterName); + wxString getFilterString(std::deque arr); + int getFilterNames(wxArrayString& arr); + void removeFilter(wxString FilterName); + int getLastRowIndex() { return m_cacheIndex; } // всего строк в хранилище int getCountStore(); int getCountFilter(); int getCountGroup(int row); int GetTotalCountGroup(int rowfilter); - + wxArrayString GetAllFields(int row, bool isfilter); private: bool checkFilter(Line& l); Line getLineParse(const wxString& str, bool csv = false); wxString get_field(Line& l, MyConst::colField col); - LineFilter getLineFilter(wxString strflt); + LineFilter getLineFilter(wxString strflt,wxString fn); void getLineToCache(int row, bool filter = true); bool CompareFilterLine(int row, bool filter); @@ -180,6 +187,7 @@ private: int rowsadd; int rowsignore; wxColor bgErr[MyConst::iconIndex::MAX_COL]; + wxString colname[MyConst::colField::Col_Max]; wxString currhost; }; diff --git a/include/log/StorageModel.h b/include/log/StorageModel.h index e9ad1b5..7e1ecaf 100644 --- a/include/log/StorageModel.h +++ b/include/log/StorageModel.h @@ -38,6 +38,8 @@ public: bool setFilter(int col, wxString val, int flags, MyDataViewCtrl* view); void DropColFilter(int index); int testFilter(int col, int position); + bool setFilterArray(std::deque arr, MyDataViewCtrl* view); + void setIconFilter(MyDataViewCtrl* view); void ApplyFilter(); bool getGroupFilter() { diff --git a/utils/log/MyDataViewCtrl.cpp b/utils/log/MyDataViewCtrl.cpp index d4b6346..605d459 100644 --- a/utils/log/MyDataViewCtrl.cpp +++ b/utils/log/MyDataViewCtrl.cpp @@ -176,7 +176,7 @@ void MyDataViewCtrl::OnEVT_DATAVIEW_SELECTION_CHANGED(wxDataViewEvent& event) { //wxLogMessage("wxEVT_DATAVIEW_SELECTION_CHANGED, First selected Item row: %d", r); } -void MyDataViewCtrl::ClearAllFilter() { +void MyDataViewCtrl::ClearAllFilter(bool no_apply) { int colt = 0; int col = 0; bool all = false; @@ -193,7 +193,7 @@ void MyDataViewCtrl::ClearAllFilter() { m->DropColFilter(colt); clear = true; all = true; - colt++; + // colt++; } } if (clear) { @@ -204,16 +204,85 @@ void MyDataViewCtrl::ClearAllFilter() { } } if (all) { - m->ApplyFilter(); + if (!no_apply) m->ApplyFilter(); for (auto i : fCol) { wxDataViewColumn* vc = GetColumn(i); vc->SetBitmap(wxNullBitmap); } } - wxString l = wxString::Format("rows %d", m->GetRowCount()); - st->SetLabelText(l); + if (!no_apply) { + wxString l = wxString::Format("rows %d", m->GetRowCount()); + st->SetLabelText(l); + } } -void MyDataViewCtrl::AddFilterIgnore() { +void MyDataViewCtrl::ModUserFilter(wxString FilterName, wxString wxOper, wxComboBox *combo,wxTextCtrl *textctrl) { + StorageModel* m = dynamic_cast(GetModel()); + Storage* st = m->getStorage(); + if (wxOper == "ChangeFilter") { + int n= combo->GetSelection(); + wxString fn = combo->GetString(n); + std::deque rez = st->getFilter(fn); + textctrl->Clear(); + if (rez.size() > 0) { + wxString listflt; + listflt = st->getFilterString(rez); + smart->SetSelection(n); + textctrl->AppendText(listflt); + if (FilterName != "skipapply") { + ClearAllFilter(true); + m->setFilterArray(rez, this); + } + } + else { + textctrl->AppendText(""); + ClearAllFilter(false); + } + + } + if (wxOper == "RemoveFilter") { + wxString txt = combo->GetValue(); + if (!txt.IsEmpty()) { + st->removeFilter(txt); + textctrl->Clear(); + int n = combo->GetSelection(); + combo->Delete(n); + combo->SetValue(""); + ClearAllFilter(false); + + } + } + if (wxOper == "AddUserFilter") { + if (!FilterName.IsEmpty()) { + + AddFilterIgnore(FilterName); + st->saveFilters(); + wxOper = "Init"; + } + + } + if (wxOper == "Init") { + wxArrayString arr; + + int j = st->getFilterNames(arr); + if (j > 0) { + combo->Clear(); + combo->Append(arr); + smart->Append(arr); + combo->SelectNone(); + if (!FilterName.IsEmpty()) { + int n = combo->FindString(FilterName); + if (n >= 0) { + combo->SetSelection(n); + smart->SetSelection(n); + ModUserFilter("skipapply", "ChangeFilter", combo, textctrl); + } + } + } + } + + +} +void MyDataViewCtrl::AddFilterIgnore(wxString Fname) { int colt = 0; int col = 0; bool all = false; @@ -222,6 +291,7 @@ void MyDataViewCtrl::AddFilterIgnore() { StorageModel* m = dynamic_cast(GetModel()); Storage* st = m->getStorage(); wxString text; + for (int j = 0; j < GetColumnCount(); j++) { col = j; clear = false; @@ -231,7 +301,8 @@ void MyDataViewCtrl::AddFilterIgnore() { if (colt >= 0) { //m->DropColFilter(colt); wxString expr=st->GetStringFilterExpr(colt,true); - st->addLineFilterStr(expr); + st->addLineFilterStr(expr,Fname); + Fname = ""; text = text + expr + "\r\n"; all = true; colt++; @@ -240,8 +311,8 @@ void MyDataViewCtrl::AddFilterIgnore() { } if (all) { - st->addLineFilterStr(""); - wxMessageBox("Create load filter\r\n\r\n"+text, _("Warning"), wxICON_INFORMATION | wxOK); + st->addLineFilterStr("",""); + wxMessageBox("Create filter\r\n\r\n"+text, _("Warning"), wxICON_INFORMATION | wxOK); } else { @@ -270,8 +341,8 @@ void MyDataViewCtrl::OnEVT_DATAVIEW_CONTEXT_MENU(wxCommandEvent& event) { if (expr == label || all) { m->DropColFilter(colt); clear = true; - } - colt++; + } else + colt++; } } if (clear) { @@ -405,6 +476,7 @@ void MyDataViewCtrl::OnEVT_DATAVIEW_COLUMN_HEADER_CLICK(wxDataViewEvent& event) } void MyDataViewCtrl::OnKEY_UP(wxKeyEvent& event) { // goto next state code + modctrl = false; int go = 0; if (event.GetKeyCode() == WXK_DOWN) { go = 1; diff --git a/utils/log/Storage.cpp b/utils/log/Storage.cpp index e6f64dd..0cc82b1 100644 --- a/utils/log/Storage.cpp +++ b/utils/log/Storage.cpp @@ -12,7 +12,7 @@ int Storage::getCountFilter() { if (cnt == 0 && !IsFilter()) cnt = getCountStore(); return cnt; } -LineFilter Storage::getLineFilter(wxString strflt) { +LineFilter Storage::getLineFilter(wxString strflt,wxString fn) { LineFilter lf; lf.col = -1; if (strflt.IsEmpty()) { @@ -28,6 +28,7 @@ LineFilter Storage::getLineFilter(wxString strflt) { if (l[i] == '~') flags = flags | FL_CONTAINS; lf.flags = flags; lf.val = val; + lf.NameFilter = fn; return lf; } wxString Storage::_strwhere(int flags) { @@ -44,9 +45,17 @@ wxString Storage::LineFilterToStr(LineFilter& lf) { expr = wxString::Format("%d:%s", lf.col, expr); return expr; } +wxString Storage::getFilterString(std::deque arr) { + wxString str; + for (auto fl : arr) { + if (!str.IsEmpty()) str += "\n"; + if (fl.col != -1) str += LineFilterToStr(fl); + } + return str; +} -void Storage::addLineFilterStr(wxString strflt) { - LineFilter lf = getLineFilter(strflt); +void Storage::addLineFilterStr(wxString strflt,wxString fn) { + LineFilter lf = getLineFilter(strflt,fn); filterload.push_back(lf); } Storage::Storage() { @@ -57,6 +66,22 @@ Storage::Storage() { bgErr[MyConst::iconIndex::error] = wxColor(220, 150, 150); bgErr[MyConst::iconIndex::fatal] = wxColor(209, 100, 100); bgErr[MyConst::iconIndex::panic] = wxColor(246, 10, 10); + colname[MyConst::colField::logappname] = "Application Name"; + colname[MyConst::colField::loguser] = "User db"; + colname[MyConst::colField::logbtype] = "Backend Type"; + colname[MyConst::colField::logdb] = "Db name"; + colname[MyConst::colField::logDetail] = "Detail"; + colname[MyConst::colField::logHint] = "Hint"; + colname[MyConst::colField::loghost] = "Client Host"; + colname[MyConst::colField::logpid] = "Pid Server process"; + colname[MyConst::colField::logMessage] = "Message"; + colname[MyConst::colField::logSERVER] = "DB host"; + colname[MyConst::colField::logSessiontime] = "Session time"; + colname[MyConst::colField::logSeverity] = "Severity"; + colname[MyConst::colField::logSqlstate] = "Sql state"; + colname[MyConst::colField::logtag] = "Tag"; + colname[MyConst::colField::logtime] = "Time"; + // load filter wxString tempDir = wxStandardPaths::Get().GetUserConfigDir() + wxT("\\postgresql\\"); @@ -69,22 +94,86 @@ Storage::Storage() { file.Read(str); file.Close(); wxStringTokenizer tk(str, "\n", wxTOKEN_RET_EMPTY_ALL); - + wxString Fname = wxEmptyString; bool end = false; LineFilter lf; + int cc = 1; while (tk.HasMoreTokens()) { wxString l = tk.GetNextToken(); - if (end && l.IsEmpty()) continue; - addLineFilterStr(l); - end = l.IsEmpty(); + if (end && l.IsEmpty()) { continue; }; + if ((!l.IsEmpty()) && (l[0] == '#')) { + Fname = l.substr(1); + if (Fname.Contains("LoadSkip")) Fname = wxString::Format("LoadSkip %d", cc++); + continue; + } + if (end && Fname.IsEmpty()) Fname = wxString::Format("LoadSkip %d",cc++); + addLineFilterStr(l,Fname); + Fname = wxEmptyString; + end = l.IsEmpty(); } - if (!end) addLineFilterStr(""); + if (!end) addLineFilterStr("",""); } } } +void Storage::removeFilter(wxString FilterName) { + + bool add = false; + int j = 0; + int p = 0; + for (auto fl : filterload) { + if (!fl.NameFilter.IsEmpty()) + if (fl.NameFilter == FilterName) + { + add = true; + } + if (add) j++; + if (add && fl.col == -1) break; + if (!add) p++; + } + int l = 0; + for (auto i = filterload.begin(); i != filterload.end(); ) + { + if (l == p) { + for (int y = 0; y < j; y++) i = filterload.erase(i); + break; + } + l++; + + } +} +std::deque Storage::getFilter(wxString FilterName) { + std::deque rez; + bool add = false; + for (auto fl : filterload) { + if (add && fl.col == -1) break; + + if (!fl.NameFilter.IsEmpty()) + if (fl.NameFilter==FilterName) + { + add = true; + } + if (add) rez.push_back(fl); + + } + return rez; +} +int Storage::getFilterNames(wxArrayString& arr) { + std::deque rez; + bool add = false; + int i = 0; + for (auto fl : filterload) { + + if (!fl.NameFilter.IsEmpty()) + { + arr.Add(fl.NameFilter); + i++; + } + } + return i; +} void Storage::saveFilters() { if (filterload.size() == 0) return; wxString tempDir = wxStandardPaths::Get().GetUserConfigDir() + wxT("\\postgresql\\"); @@ -94,6 +183,9 @@ void Storage::saveFilters() { { wxString text; for (auto lf:filterload) { + if (!lf.NameFilter.IsEmpty()) { + text.Append("#"+lf.NameFilter+"\n"); + } wxString s = LineFilterToStr(lf); if (!s.IsEmpty()) text.Append(s); @@ -121,9 +213,16 @@ wxColor& Storage::GetBgColorLine(int rowvisual) { return bgErr[i]; } void Storage::DropColFilter(int index) { - fCol.RemoveAt(index); - fVal.RemoveAt(index); - fFlags.RemoveAt(index); + if (index == -1) { + fCol.Clear(); + fVal.Clear(); + fFlags.Clear(); + } + else { + fCol.RemoveAt(index); + fVal.RemoveAt(index); + fFlags.RemoveAt(index); + } // оставшиеся фильтры будут применены по всему storage frows.clear(); } @@ -184,7 +283,7 @@ bool Storage::CompareFilterLine(int row, bool filter) { return true; } - if (!faddgroup) return false; +if (!faddgroup) return false; } return true; @@ -282,7 +381,19 @@ bool Storage::ApplyFilter(int row) { faddgroup = false; return f; } +int Storage::SetFilterArray(std::deque arr) { + for (auto fl: arr) { + if (fl.col != -1) { + fCol.Add(fl.col); + fVal.Add(fl.val); + fFlags.Add(fl.flags); + } + } + ApplyFilter(); + return frows.size(); + +} int Storage::SetFilter(int col, wxString& val, int flags) { fCol.Add(col); fVal.Add(val); @@ -293,6 +404,17 @@ int Storage::SetFilter(int col, wxString& val, int flags) { wxString Storage::GetField(int row, MyConst::colField col) { return GetFieldStorage(row, col, IsFilter()); } +wxArrayString Storage::GetAllFields(int row,bool isfilter) { + wxArrayString a; + wxString f; + for (int i = 0; i < MyConst::colField::Col_Max;i++) { + f= GetFieldStorage(row, (MyConst::colField) i, isfilter); + a.Add(colname[i]); + a.Add(f); + } + return a; +} + wxString Storage::get_field(Line& l, MyConst::colField col) { wxString val; switch (col) @@ -392,8 +514,8 @@ Line Storage::getLineParse(const wxString& str, bool csv) { st.logtag = { static_cast(t.Len()),static_cast(logTag.Len()) }; t += logTag; wxString logSessiontime = tk.GetNextToken(); - st.loghost = { static_cast(t.Len()),static_cast(logHost.Len()) }; - t += logHost; + st.logSessiontime = { static_cast(t.Len()),static_cast(logSessiontime.Len()) }; + t += logSessiontime; wxString logVXid = tk.GetNextToken(); wxString logTransaction = tk.GetNextToken(); @@ -529,7 +651,14 @@ bool Storage::checkFilter(Line& l) { bool rez=true; int last = filterload.size() - 1; int i = 0; + int cc = 0; + //int line = 0; + //bool skip = false; for (auto fl:filterload) { + if (!fl.NameFilter.IsEmpty()) + if (!fl.NameFilter.Contains("LoadSkip")) rez= false; + + if (fl.col == -1) { if (rez || (last==i)) break; rez = true; @@ -544,11 +673,13 @@ bool Storage::checkFilter(Line& l) { else rez = sf.Contains(fl.val); if (reverse) rez = !rez; + cc++; } } i++; } + if (cc == 0) return false; return rez; } return false; diff --git a/utils/log/StorageModel.cpp b/utils/log/StorageModel.cpp index 897542f..8999a85 100644 --- a/utils/log/StorageModel.cpp +++ b/utils/log/StorageModel.cpp @@ -8,6 +8,9 @@ #include "wx/dataview.h" #include "log/Storage.h" #include "log/StorageModel.h" +#include "utils/utffile.h" +#include +#include // ---------------------------------------------------------------------------- // resources @@ -385,6 +388,34 @@ bool StorageModel::setFilter(int col, wxString val, int flags, MyDataViewCtrl* v } return r; } +bool StorageModel::setFilterArray(std::deque arr,MyDataViewCtrl* view) { + bool r=store->SetFilterArray(arr); + view->UnselectAll(); + Reset(store->getCountFilter()); + setIconFilter(view); + return r; +} +void StorageModel::setIconFilter(MyDataViewCtrl* view) { + bool yesfilter = false; + for (int j = 0; j < view->GetColumnCount(); j++) { + int colt = 0; + yesfilter = false; + wxDataViewColumn* vc = view->GetColumn(j); + while (colt != -1) { + colt = testFilter(j, colt); + if (colt >= 0) { + //m->DropColFilter(colt); + vc->SetBitmap(bitmapflt); + + yesfilter = true; + colt++; + break; + } + } + if (!yesfilter) vc->SetBitmap(wxNullBitmap); + } +} + int StorageModel::testFilter(int col, int position = 0) { int idx = 0; idx = store->testFilter(colmap[col], position);