mirror of
https://github.com/levinsv/pgadmin3.git
synced 2026-05-15 14:15:49 -06:00
Add Log view in CSV mode
Добавлено окно просмотра лога БД в CSV формате с фильтрами, группами. Описание в Readme.md
This commit is contained in:
parent
50f53a96bb
commit
4b240f8cc0
30 changed files with 3155 additions and 14 deletions
39
README.md
39
README.md
|
|
@ -164,6 +164,43 @@ This text Russian language.
|
|||
Размер icon 32х32
|
||||
2. Задать для сервера цвет. Фон icon будет окрашен в цвет сервера.
|
||||
|
||||
|
||||
19.08.2021
|
||||
- добавлено окно просмотра CSV лога базы.
|
||||
Окно вызывается из контекстного меню сервера "Log view ...".
|
||||
|
||||
После открытия окна читается непосредственно файл лога функцией pg_read_binary_file
|
||||
Выбирается файл с самой свежей датой изменения. Проверка новых сообщений проводиться каждые 5 секунд.
|
||||
Можно добавить другие сервера на панели "Settings". Настройки применяются после закрытия окна и повторного его открытия.
|
||||
Если окно лога не активное и приходит сообщения уровня Error и выше, то иконка отмечается красным квадратом.
|
||||
Если на заладке "Settings" выбрано несколько серверов, то происходить автоматическое подключение к ним.
|
||||
После подключения все открытые сервера в дереве объектов можно закрыть одной командой контекстного меню
|
||||
"Disconnect all servers".
|
||||
ВНИМАНИЕ: память требуемая для хранения логов ни чем не ограничивается (кроме фильтрации на этапе загрузки лога) и
|
||||
возможно выделения большого количества памяти.
|
||||
Отображаются строки лога в двух режимах:
|
||||
* Простой. Отобразаются все полученные строки лога
|
||||
* Групповой. Строки с похожими сообщениями объединяются в группу и видимой строкой является самая последняя строка
|
||||
в группе. Для просмотра всех строк группы нужно установить флаг "View detail group".
|
||||
Сообщения будут похожими если они отличаются только числами и если они не в двойных кавычках.
|
||||
В групповом режиме в поле host показываются счетчик свежих сообщений попавших в группу. Счетчик сбрасывается при
|
||||
установке курсора на строку группы.
|
||||
Для исключения из просмотра ненужных строк используются поколоночные фильтры. Для включения фильтра нужно:
|
||||
* Щелкнуть правой кнопкой мыши по полю. Для инверсии фильтра нужно удерживать Ctrl.
|
||||
* Выбрать значение в контекстном меню заголовка колонки. Там отображаются 20 самых частых значения в колонке с указанием
|
||||
количества этих значений.
|
||||
* Ввести в поле значения для фильтра, выделить это значение и нажать Enter. Для фильтра используется только выделенный
|
||||
текст. Такой фильтр будет работать на поиск выделенного вхождения в поле. Если в выделенной строке
|
||||
первым символом будет "!" то фильтер инверсируется.
|
||||
* каждое отдельное значение фильтра можно удалить через контекстное меню заголовка колонки.
|
||||
Для более высокой производительности рекомендуется проводить загрузку логов с включенным "Mode group".
|
||||
Или сбрасывать "Mode group", но при установленных фильтрах.
|
||||
Отображение большого число строк (более 10000 ) происходит несколько секунд и более.
|
||||
* Есть возможность отсеять строки на этапе загрузки. Для этого установите фильтры на строки и нажмите
|
||||
"Add Filter Ignore" этот фильтр будет записан в файл filter_load.txt.
|
||||
|
||||
13.09.2021
|
||||
- Добавлено меню закрытия всех открытых серверов "Disconnect all servers"
|
||||
-
|
||||
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -548,7 +548,8 @@ bool pgConn::HasFeature(int featureNo, bool forceCheck)
|
|||
wxT(" WHERE proname IN ('pg_tablespace_size', 'pg_file_read', 'pg_logfile_rotate',")
|
||||
wxT( " 'pg_postmaster_starttime', 'pg_terminate_backend', 'pg_reload_conf',")
|
||||
wxT( " 'pgstattuple', 'pgstatindex','bt_index_parent_check')\n")
|
||||
wxT(" AND nspname IN ('pg_catalog', 'public')");
|
||||
wxT(" AND nspname IN ('pg_catalog', 'public')")
|
||||
wxT(" union all select current_setting('log_destination'),555,null,null,null");
|
||||
|
||||
pgSet *set = ExecuteSet(sql);
|
||||
|
||||
|
|
@ -579,7 +580,8 @@ bool pgConn::HasFeature(int featureNo, bool forceCheck)
|
|||
features[FEATURE_PGSTATINDEX] = true;
|
||||
else if (proname == wxT("bt_index_parent_check") && pronargs == 2 )
|
||||
features[FEATURE_PGCHECKINDEX] = true;
|
||||
|
||||
else if (proname == wxT("csvlog") && pronargs == 555)
|
||||
features[FEATURE_CSVLOG] = true;
|
||||
set->MoveNext();
|
||||
}
|
||||
delete set;
|
||||
|
|
|
|||
638
frm/frmLog.cpp
Normal file
638
frm/frmLog.cpp
Normal file
|
|
@ -0,0 +1,638 @@
|
|||
|
||||
#include "pgAdmin3.h"
|
||||
|
||||
// wxWindows headers
|
||||
#include <wx/wx.h>
|
||||
#include <wx/regex.h>
|
||||
#include <wx/xrc/xmlres.h>
|
||||
#include <wx/image.h>
|
||||
#include <wx/textbuf.h>
|
||||
#include <wx/sysopt.h>
|
||||
|
||||
// wxAUI
|
||||
#include <wx/aui/aui.h>
|
||||
|
||||
// App headers
|
||||
#include "frm/frmMain.h"
|
||||
#include "frm/frmLog.h"
|
||||
#include "db/pgConn.h"
|
||||
#include "utils/pgfeatures.h"
|
||||
#include "schema/pgServer.h"
|
||||
#include "schema/pgUser.h"
|
||||
#include "ctl/ctlMenuToolbar.h"
|
||||
#include "ctl/ctlAuiNotebook.h"
|
||||
#include "utils/csvfiles.h"
|
||||
#include "log/StorageModel.h"
|
||||
|
||||
#include <wx/arrimpl.cpp>
|
||||
|
||||
|
||||
|
||||
|
||||
WX_DEFINE_OBJARRAY(RemoteConnArray2);
|
||||
|
||||
|
||||
wxBEGIN_EVENT_TABLE(frmLog, pgFrame)
|
||||
// test
|
||||
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_SET_FOCUS(frmLog::OnSetFocus)
|
||||
EVT_KILL_FOCUS(frmLog::OnKillFocus)
|
||||
EVT_ACTIVATE(frmLog::OnActivate)
|
||||
wxEND_EVENT_TABLE()
|
||||
|
||||
//#include <wx/arrimpl.cpp>
|
||||
//WX_DEFINE_OBJARRAY(RemoteConnArray);
|
||||
|
||||
|
||||
void frmLog::OnActivate(wxActivateEvent& event) {
|
||||
m_storage_model->getStorage()->SetErrMsgFlag(false);
|
||||
seticon(false);
|
||||
event.Skip();
|
||||
}
|
||||
void frmLog::OnSetFocus(wxFocusEvent& event) {
|
||||
m_storage_model->getStorage()->SetErrMsgFlag(false);
|
||||
seticon(false);
|
||||
}
|
||||
void frmLog::OnKillFocus(wxFocusEvent& event) {
|
||||
m_storage_model->getStorage()->SetErrMsgFlag(false);
|
||||
seticon(false);
|
||||
|
||||
}
|
||||
|
||||
// Class declarations
|
||||
void frmLog::OnClearAllFilter(wxCommandEvent& event) {
|
||||
|
||||
my_view->ClearAllFilter();
|
||||
}
|
||||
void frmLog::OnAddFilterIgnore(wxCommandEvent& event) {
|
||||
|
||||
my_view->AddFilterIgnore();
|
||||
}
|
||||
void frmLog::OnSetGroup(wxCommandEvent& event)
|
||||
{
|
||||
//wxDataViewColumn* const col = m_ctrl[Page_List]->GetColumn(0);
|
||||
if (event.IsChecked())
|
||||
{
|
||||
//wxLogMessage("Group set check");
|
||||
my_view->setGroupMode(true);
|
||||
detail->SetValue(false);
|
||||
}
|
||||
else {
|
||||
//wxLogMessage("Group unset check");
|
||||
my_view->setGroupMode(false);
|
||||
}
|
||||
detail->Enable(event.IsChecked());
|
||||
}
|
||||
bool frmLog::CheckConn(wxString host,int port) {
|
||||
for (size_t i = 0; i < conArray.GetCount(); i++)
|
||||
{
|
||||
if ((conArray[i].conn->GetHostName() == host)&&(conArray[i].conn->GetPort() == port))
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
pgConn* frmLog::createConn(pgServer* srv) {
|
||||
pgConn* conn;
|
||||
|
||||
if (!srv->GetConnected()) mainForm->ReconnectServer(srv, false);
|
||||
conn = srv->CreateConn(wxEmptyString, 0, "Log conn");
|
||||
|
||||
return conn;
|
||||
}
|
||||
void frmLog::AddNewConn(pgConn* con) {
|
||||
if (con != NULL) {
|
||||
if (!con->HasFeature(FEATURE_CSVLOG)) return;
|
||||
logfileName.Add("");
|
||||
savedPartialLine.Add("");
|
||||
logfileLength.Add(0);
|
||||
len.Add(0);
|
||||
conArray.Add(new RemoteConn2(con));
|
||||
}
|
||||
}
|
||||
void frmLog::OnSetDetailGroup(wxCommandEvent& event)
|
||||
{
|
||||
//wxDataViewColumn* const col = m_ctrl[Page_List]->GetColumn(0);
|
||||
if (event.IsChecked())
|
||||
{
|
||||
my_view->ViewGroup(true);
|
||||
|
||||
}
|
||||
else {
|
||||
my_view->ViewGroup(false);
|
||||
}
|
||||
}
|
||||
|
||||
void frmLog::getFilename() {
|
||||
pgSet* set;
|
||||
wxString namepage;
|
||||
for (size_t i = 0;i< conArray.GetCount(); i++) {
|
||||
|
||||
|
||||
if (!conArray[i].conn->IsAlive()) continue;
|
||||
set = conArray[i].conn->ExecuteSet(
|
||||
wxT("select current_setting('log_directory')||'/'||name filename,modification filetime,size len\n")
|
||||
wxT(" FROM pg_ls_logdir() where name ~ '.csv' ORDER BY modification DESC"));
|
||||
if (set)
|
||||
{
|
||||
|
||||
//logfileTimestamp = set->GetDateTime(wxT("filetime"));
|
||||
len[i] = set->GetLong(wxT("len"));
|
||||
if (!namepage.IsEmpty()) namepage += ",";
|
||||
namepage += conArray[i].conn->GetDbname();
|
||||
m_storage_model->getStorage()->SetHost(conArray[i].conn->GetHostName());
|
||||
|
||||
wxString fn = set->GetVal(wxT("filename"));
|
||||
if (fn != logfileName[i]) {
|
||||
logfileLength[i] = 0;
|
||||
logfileName[i] = fn;
|
||||
|
||||
}
|
||||
/// addLogFile(logfileName, logfileTimestamp, len, logfileLength, skipFirst);
|
||||
|
||||
delete set;
|
||||
readLogFile(logfileName[i],len[i],logfileLength[i],savedPartialLine[i],conArray[i].conn);
|
||||
}
|
||||
}
|
||||
if (namepage.IsEmpty()) namepage = "not connect";
|
||||
if (m_notebook->GetPageText(0) != namepage) m_notebook->SetPageText(0, namepage);
|
||||
}
|
||||
void frmLog::readLogFile(wxString logfileName,long& lenfile,long& logfileLength,wxString& savedPartialLine,pgConn* conn) {
|
||||
wxString line;
|
||||
|
||||
// If GPDB 3.3 and later, log is normally in CSV format. Let's get a whole log line before calling addLogLine,
|
||||
// so we can do things smarter.
|
||||
|
||||
// PostgreSQL can log in CSV format, as well as regular format. Normally, we'd only see
|
||||
// the regular format logs here, because pg_logdir_ls only returns those. But if pg_logdir_ls is
|
||||
// changed to return the csv format log files, we should handle it.
|
||||
|
||||
bool csv_log_format = logfileName.Right(4) == wxT(".csv");
|
||||
|
||||
if (csv_log_format && savedPartialLine.length() > 0)
|
||||
{
|
||||
if (logfileLength == 0) // Starting at beginning of log file
|
||||
savedPartialLine.clear();
|
||||
else
|
||||
line = savedPartialLine;
|
||||
}
|
||||
wxString funcname = "pg_read_binary_file(";
|
||||
while (lenfile > logfileLength)
|
||||
{
|
||||
//statusBar->SetStatusText(_("Reading log from server..."));
|
||||
pgSet* set = conn->ExecuteSet(wxT("SELECT ") + funcname +
|
||||
conn->qtDbString(logfileName) + wxT(", ") + NumToStr(logfileLength) + wxT(", 50000)"));
|
||||
if (!set)
|
||||
{
|
||||
conn->IsAlive();
|
||||
return;
|
||||
}
|
||||
char* raw1 = set->GetCharPtr(0);
|
||||
|
||||
if (!raw1 || !*raw1)
|
||||
{
|
||||
delete set;
|
||||
break;
|
||||
}
|
||||
char* raw;
|
||||
unsigned char m[50001];
|
||||
if (settings->GetASUTPstyle()) {
|
||||
|
||||
raw = (char*)&m[0];
|
||||
unsigned char c;
|
||||
unsigned char* startChar;
|
||||
int pos = 0;
|
||||
raw1 = raw1 + 2;
|
||||
int utf8charLen = 0;
|
||||
while (*raw1 != 0) {
|
||||
c = *raw1;
|
||||
c = c - '0';
|
||||
if (c > 9) c = *raw1 - 'a' + 10;
|
||||
raw1++;
|
||||
m[pos] = c << 4;
|
||||
c = *raw1 - '0';
|
||||
if (c > 9) c = *raw1 - 'a' + 10;
|
||||
c = c | m[pos];
|
||||
m[pos] = c;
|
||||
// check utf-8 char
|
||||
if (utf8charLen == 0) {
|
||||
startChar = &m[pos];
|
||||
if (c >> 7 == 0)
|
||||
utf8charLen = 1;
|
||||
else if (c >> 5 == 0x6)
|
||||
utf8charLen = 2;
|
||||
else if (c >> 4 == 0xE)
|
||||
utf8charLen = 3;
|
||||
else if (c >> 5 == 0x1E)
|
||||
utf8charLen = 4;
|
||||
else
|
||||
utf8charLen = 0;
|
||||
// bad utf8 format
|
||||
}
|
||||
pos++;
|
||||
raw1++;
|
||||
utf8charLen--;
|
||||
}
|
||||
//
|
||||
if (utf8charLen != 0) {
|
||||
//read = startChar - &m[0];
|
||||
// remove bad utf-8 char
|
||||
*startChar = 0;
|
||||
}
|
||||
else
|
||||
m[pos] = 0;
|
||||
}
|
||||
else {
|
||||
raw = raw1;
|
||||
}
|
||||
int l= strlen(raw);
|
||||
logfileLength += l;
|
||||
status->SetLabelText(wxString::Format("Load bytes %ld", logfileLength));
|
||||
wxString str;
|
||||
str = line + wxTextBuffer::Translate(wxString(raw, set->GetConversion()), wxTextFileType_Unix);
|
||||
//if (wxString(wxString(raw, wxConvLibc).wx_str(), wxConvUTF8).Len() > 0)
|
||||
// str = line + wxString(wxString(raw, wxConvLibc).wx_str(), wxConvUTF8);
|
||||
//else {
|
||||
// str = line + wxTextBuffer::Translate(wxString(raw, set->GetConversion()), wxTextFileType_Unix);
|
||||
//}
|
||||
|
||||
|
||||
delete set;
|
||||
|
||||
if (str.Len() == 0)
|
||||
{
|
||||
wxString msgstr = _("The server log contains entries in multiple encodings and cannot be displayed by pgAdmin.");
|
||||
wxMessageBox(msgstr);
|
||||
return;
|
||||
}
|
||||
|
||||
if (csv_log_format)
|
||||
{
|
||||
// This will work for any DB using CSV format logs
|
||||
|
||||
|
||||
CSVLineTokenizer tk(str);
|
||||
|
||||
|
||||
my_view->Freeze();
|
||||
while (tk.HasMoreLines())
|
||||
{
|
||||
line.Clear();
|
||||
|
||||
bool partial;
|
||||
str = tk.GetNextLine(partial);
|
||||
if (partial)
|
||||
{
|
||||
line = str; // Start of a log line, but not complete. Loop back, Read more data.
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
// Looks like we have a good complete CSV log record.
|
||||
|
||||
//addLogLine(str.Trim(), true, true);
|
||||
my_view->AddRow(str.Trim());
|
||||
}
|
||||
|
||||
my_view->Thaw();
|
||||
}
|
||||
else
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
savedPartialLine.clear();
|
||||
|
||||
if (!line.IsEmpty())
|
||||
{
|
||||
// We finished reading to the end of the log file, but still have some data left
|
||||
if (csv_log_format)
|
||||
{
|
||||
savedPartialLine = line; // Save partial log line for next read of the data file.
|
||||
line.Clear();
|
||||
}
|
||||
else
|
||||
my_view->AddRow(line.Trim());
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
void frmLog::OnTimer(wxTimerEvent& event) {
|
||||
Storage* st = m_storage_model->getStorage();
|
||||
//int rows = st->getCountStore();
|
||||
int ra, ri;
|
||||
st->ClearRowsStat();
|
||||
getFilename();
|
||||
st->GetRowsStat(ra, ri);
|
||||
//int newrows = st->getCountStore();
|
||||
//if (loglen !=logfileLength)
|
||||
if (m_storage_model->getStorage()->GetErrMsgFlag()) {
|
||||
seticon(true);
|
||||
}
|
||||
status->SetLabelText(wxString::Format("Add rows %d ignore %d. View rows %d", ra,ri, m_storage_model->GetRowCount()) );
|
||||
|
||||
}
|
||||
#include "log/log_xpm.xpm"
|
||||
#include "log/log_red_xpm.xpm"
|
||||
void frmLog::seticon(bool errflag) {
|
||||
//wxImage img = *sql_32_png_img;
|
||||
if (errflag) {
|
||||
SetIcon(idefRed);
|
||||
}
|
||||
else {
|
||||
SetIcon(idef);
|
||||
}
|
||||
return;
|
||||
|
||||
wxBitmap* b = new wxBitmap(log_xpm);
|
||||
|
||||
//wxIcon ico=img.
|
||||
wxMemoryDC dc(*b);
|
||||
dc.SetBrush(*wxYELLOW_BRUSH);
|
||||
|
||||
//dc.SetBackground(*wxYELLOW_BRUSH);
|
||||
dc.SetBackground(*wxRED_BRUSH);
|
||||
dc.SetBrush(*wxRED_BRUSH);
|
||||
|
||||
//dc.SetPen(*wxTRANSPARENT_PEN);
|
||||
dc.SetTextForeground(*wxRED);
|
||||
dc.SetPen(*wxRED_PEN);
|
||||
wxRect rect(7,4,7, 7);
|
||||
|
||||
if (errflag) dc.DrawRoundedRectangle(rect, 0);
|
||||
|
||||
// wxFont font = wxFont(5, wxFONTFAMILY_DEFAULT, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_NORMAL);
|
||||
// wxFontStyle s;
|
||||
// font.SetStyle(wxFONTFLAG_ANTIALIASED);
|
||||
// dc.SetFont(font);
|
||||
|
||||
wxImage img = b->ConvertToImage();
|
||||
dc.SelectObject(wxNullBitmap);
|
||||
int w = img.GetWidth();
|
||||
int h = img.GetHeight();
|
||||
wxColor p;
|
||||
wxColor c= wxColor(0,255,0);
|
||||
for (int y = 0; y < h; y++)
|
||||
for (int x = 0; x < w; x++) {
|
||||
p = wxColour(img.GetRed(x, y),
|
||||
img.GetGreen(x, y),
|
||||
img.GetBlue(x, y));
|
||||
//if (img.IsTransparent(x, y)) img.SetRGB(x, y, 255, 255, 255);
|
||||
if (p == c) {
|
||||
//img.SetTra
|
||||
img.SetAlpha(x, y, 255);
|
||||
img.SetRGB(x, y, img.GetMaskRed(), img.GetMaskGreen(), img.GetMaskBlue());
|
||||
;
|
||||
};
|
||||
}
|
||||
|
||||
//wxIcon* ico = new wxIcon();
|
||||
wxIcon ico=GetIcon();
|
||||
wxBitmap* bmp = new wxBitmap(img);
|
||||
ico.CopyFromBitmap(*bmp);
|
||||
//SetIcon(*sql_32_png_ico);
|
||||
|
||||
SetIcon(ico);
|
||||
|
||||
|
||||
}
|
||||
frmLog::frmLog(frmMain *form, const wxString &_title, pgServer *srv) : pgFrame(NULL, _title)
|
||||
{
|
||||
|
||||
dlgName = wxT("frmLog");
|
||||
RestorePosition(-1, -1, 700, 500, 700, 500);
|
||||
//SetIcon(wxIcon(log_xpm));
|
||||
idef = wxIcon(log_xpm);
|
||||
idefRed = wxIcon(log_red_xpm);
|
||||
seticon(false);
|
||||
mainForm = form;
|
||||
|
||||
m_notebook = new wxNotebook( this, wxID_ANY );
|
||||
|
||||
wxPanel* testPanel = new wxPanel(m_notebook, wxID_ANY);
|
||||
//BuildDataViewCtrl(testPanel, Page_Test);
|
||||
my_view = new MyDataViewCtrl(testPanel, wxID_ANY, wxDefaultPosition,
|
||||
wxDefaultSize, wxDV_VARIABLE_LINE_HEIGHT | wxDV_HORIZ_RULES | wxDV_VERT_RULES);
|
||||
my_view->GetMainWindow()->Bind(wxEVT_MOTION, &MyDataViewCtrl::OnMouseMove, my_view);
|
||||
my_view->GetMainWindow()->Bind(wxEVT_KEY_DOWN, &MyDataViewCtrl::OnKEY_DOWN, my_view);
|
||||
my_view->GetMainWindow()->Bind(wxEVT_KEY_UP, &MyDataViewCtrl::OnKEY_DOWN, my_view);
|
||||
my_view->Bind(wxEVT_DATAVIEW_COLUMN_HEADER_CLICK, &MyDataViewCtrl::OnEVT_DATAVIEW_COLUMN_HEADER_CLICK, my_view);
|
||||
my_view->Bind(wxEVT_DATAVIEW_SELECTION_CHANGED, &MyDataViewCtrl::OnEVT_DATAVIEW_SELECTION_CHANGED, my_view);
|
||||
my_view->Bind(wxEVT_DATAVIEW_ITEM_CONTEXT_MENU, &MyDataViewCtrl::OnContextMenu, my_view);
|
||||
|
||||
// my_view->Bind(wxEVT_DATAVIEW_ITEM_CONTEXT_MENU, &MyDataViewCtrl::OnContextMenu, my_view);
|
||||
|
||||
m_timer.Bind(wxEVT_TIMER, &frmLog::OnTimer, this);
|
||||
|
||||
|
||||
|
||||
|
||||
my_view->Bind(wxEVT_MENU, &MyDataViewCtrl::OnEVT_DATAVIEW_CONTEXT_MENU, my_view);
|
||||
m_storage_model = new StorageModel(my_view);
|
||||
my_view->AssociateModel(m_storage_model.get());
|
||||
|
||||
m_storage_model->BuildColumns(my_view);
|
||||
wxString s;
|
||||
s=settings->Read(dlgName + "/ColsWidth","");
|
||||
if (s.Len()>0) my_view->setSettingString(s);
|
||||
//settings->Write(dlgName + "/ColsWidth", s);
|
||||
|
||||
wxSizer* zeroPanelSz = new wxBoxSizer(wxVERTICAL);
|
||||
my_view->SetMinSize(wxSize(-1, 200));
|
||||
zeroPanelSz->Add(my_view, 1, wxGROW | wxALL, 5);
|
||||
|
||||
status = new wxStaticText(testPanel, wxID_ANY, "status text");
|
||||
zeroPanelSz->Add(
|
||||
status,
|
||||
0, wxGROW | wxALL, 5);
|
||||
//zeroPanelSz->Add(button_sizer);
|
||||
//zeroPanelSz->Add(sizerCurrent);
|
||||
my_view->setStatusObj(status);
|
||||
wxBoxSizer* sSizer = new wxBoxSizer(wxHORIZONTAL);
|
||||
group = new wxCheckBox(testPanel, ID_SET_GROUP, "Mode group");
|
||||
sSizer->Add(group,
|
||||
wxSizerFlags().Centre().DoubleBorder());
|
||||
detail = new wxCheckBox(testPanel, ID_SET_DETAILGROUP, "View detail group");
|
||||
sSizer->Add(detail,
|
||||
wxSizerFlags().Centre().DoubleBorder());
|
||||
const wxSizerFlags border1 = wxSizerFlags().DoubleBorder();
|
||||
|
||||
//wxBoxSizer* button_sizer = new wxBoxSizer(wxHORIZONTAL);
|
||||
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);
|
||||
|
||||
|
||||
zeroPanelSz->Add(sSizer);
|
||||
testPanel->SetSizerAndFit(zeroPanelSz);
|
||||
|
||||
m_notebook->AddPage(testPanel, "Log");
|
||||
wxPanel* settingPanel = new wxPanel(m_notebook, wxID_ANY);
|
||||
lb = new wxCheckListBox(settingPanel,wxID_ANY);
|
||||
wxTreeItemIdValue foldercookie, servercookie;
|
||||
wxTreeItemId folderitem, serveritem;
|
||||
pgObject* object;
|
||||
pgServer* server;
|
||||
std::vector<wxString> vec;
|
||||
folderitem = mainForm->GetBrowser()->GetFirstChild(mainForm->GetBrowser()->GetRootItem(), foldercookie);
|
||||
while (folderitem)
|
||||
{
|
||||
if (mainForm->GetBrowser()->ItemHasChildren(folderitem))
|
||||
{
|
||||
serveritem = mainForm->GetBrowser()->GetFirstChild(folderitem, servercookie);
|
||||
while (serveritem)
|
||||
{
|
||||
object = mainForm->GetBrowser()->GetObject(serveritem);
|
||||
if (object && object->IsCreatedBy(serverFactory))
|
||||
{
|
||||
server = (pgServer*)object;
|
||||
wxString srvname = wxString::Format("%s:%d", server->GetName(), server->GetPort());
|
||||
vec.push_back(srvname);
|
||||
|
||||
}
|
||||
serveritem = mainForm->GetBrowser()->GetNextChild(folderitem, servercookie);
|
||||
}
|
||||
}
|
||||
folderitem = mainForm->GetBrowser()->GetNextChild(mainForm->GetBrowser()->GetRootItem(), foldercookie);
|
||||
}
|
||||
lb->Append(vec);
|
||||
wxString srvs;
|
||||
wxString srvname = wxString::Format("%s:%d", srv->GetName(), srv->GetPort());
|
||||
settings->Read(dlgName + "/AutoConnect", &srvs, "");
|
||||
if (!srvs.IsEmpty()) srvs += ";";
|
||||
srvs += srvname;
|
||||
wxStringTokenizer tk(srvs, ";", wxTOKEN_RET_EMPTY_ALL);
|
||||
while (tk.HasMoreTokens())
|
||||
{
|
||||
wxString l = tk.GetNextToken();
|
||||
pgServer* s = getServer(l);
|
||||
if (s != NULL) {
|
||||
if (!CheckConn(s->GetName(), s->GetPort())) {
|
||||
pgConn* conn = createConn(s);
|
||||
AddNewConn(conn);
|
||||
for (unsigned int x = 0; x < lb->GetCount(); x++)
|
||||
if (l==lb->GetString(x)) lb->Check(x, true);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
wxSizer* zeroPanelSz2 = new wxBoxSizer(wxVERTICAL);
|
||||
lb->SetMinSize(wxSize(-1, 200));
|
||||
zeroPanelSz2->Add(lb, 1, wxGROW | wxALL, 5);
|
||||
settingPanel->SetSizerAndFit(zeroPanelSz2);
|
||||
m_notebook->AddPage(settingPanel, "Settings");
|
||||
|
||||
bool b=true;
|
||||
settings->Read(dlgName + "/Mode",&b, false);
|
||||
group->SetValue(b);
|
||||
my_view->setGroupMode(b);
|
||||
// if (mainForm) getFilename();
|
||||
m_timer.Start(timerInterval);
|
||||
}
|
||||
pgServer* frmLog::getServer(wxString& strserver) {
|
||||
wxTreeItemIdValue foldercookie, servercookie;
|
||||
wxTreeItemId folderitem, serveritem;
|
||||
pgObject* object;
|
||||
pgServer* server;
|
||||
folderitem = mainForm->GetBrowser()->GetFirstChild(mainForm->GetBrowser()->GetRootItem(), foldercookie);
|
||||
while (folderitem)
|
||||
{
|
||||
if (mainForm->GetBrowser()->ItemHasChildren(folderitem))
|
||||
{
|
||||
serveritem = mainForm->GetBrowser()->GetFirstChild(folderitem, servercookie);
|
||||
while (serveritem)
|
||||
{
|
||||
object = mainForm->GetBrowser()->GetObject(serveritem);
|
||||
if (object && object->IsCreatedBy(serverFactory))
|
||||
{
|
||||
server = (pgServer*)object;
|
||||
wxString srvname = wxString::Format("%s:%d", server->GetName(), server->GetPort());
|
||||
if (srvname == strserver) {
|
||||
return server;
|
||||
}
|
||||
}
|
||||
serveritem = mainForm->GetBrowser()->GetNextChild(folderitem, servercookie);
|
||||
}
|
||||
}
|
||||
folderitem = mainForm->GetBrowser()->GetNextChild(mainForm->GetBrowser()->GetRootItem(), foldercookie);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
frmLog::~frmLog()
|
||||
{
|
||||
// If the status window wasn't launched in standalone mode...
|
||||
if (mainForm)
|
||||
mainForm->RemoveFrame(this);
|
||||
|
||||
|
||||
// If connection is still available, delete it
|
||||
SavePosition();
|
||||
wxString srvs;
|
||||
for (unsigned int x = 0; x < lb->GetCount(); x++)
|
||||
if (lb->IsChecked(x)) {
|
||||
if (!srvs.IsEmpty()) srvs += ";";
|
||||
srvs += lb->GetString(x);
|
||||
}
|
||||
settings->Write(dlgName + "/AutoConnect", srvs);
|
||||
wxString s = my_view->getSettingString();
|
||||
settings->Write(dlgName+"/ColsWidth",s);
|
||||
settings->WriteBool(dlgName + "/Mode", group->IsChecked());
|
||||
Storage *st=m_storage_model->getStorage();
|
||||
st->saveFilters();
|
||||
mainForm->Logfrm = NULL;
|
||||
}
|
||||
void frmLog::Go()
|
||||
{
|
||||
// Show the window
|
||||
Show(true);
|
||||
}
|
||||
LogFactory::LogFactory(menuFactoryList* list, wxMenu* mnu, ctlMenuToolbar* toolbar) : contextActionFactory(list)
|
||||
{
|
||||
mnu->Append(id, _("Log view..."), _("Log view CSV format"));
|
||||
}
|
||||
|
||||
|
||||
wxWindow* LogFactory::StartDialog(frmMain* form, pgObject* obj)
|
||||
{
|
||||
pgServer* srv = (pgServer *) obj;
|
||||
wxString txt = "";
|
||||
if (form->Logfrm != NULL) {
|
||||
if (!form->Logfrm->CheckConn(srv->GetName(), srv->GetPort())) {
|
||||
pgConn* conn = form->Logfrm->createConn(srv);
|
||||
form->Logfrm->AddNewConn(conn);
|
||||
}
|
||||
}
|
||||
else {
|
||||
form->Logfrm = new frmLog(form, txt, srv);
|
||||
if (form->Logfrm!=NULL)
|
||||
form->AddFrame(form->Logfrm);
|
||||
|
||||
}
|
||||
//frmLog* frm = new frmLog(form, obj);
|
||||
|
||||
form->Logfrm->Go();
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
bool LogFactory::CheckEnable(pgObject* obj)
|
||||
{
|
||||
if (!obj)
|
||||
return false;
|
||||
|
||||
if (obj->GetMetaType() == PGM_SERVER) {
|
||||
// if (!((pgServer*)obj)->GetConnected())
|
||||
// return false;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
@ -63,6 +63,7 @@
|
|||
#include "frm/frmReport.h"
|
||||
#include "frm/frmMaintenance.h"
|
||||
#include "frm/frmStatus.h"
|
||||
#include "frm/frmLog.h"
|
||||
#include "frm/frmPassword.h"
|
||||
#ifdef DATABASEDESIGNER
|
||||
#include "frm/frmDatabaseDesigner.h"
|
||||
|
|
@ -109,7 +110,7 @@ frmMain::frmMain(const wxString &title)
|
|||
lastPluginUtility = NULL;
|
||||
pluginUtilityCount = 0;
|
||||
m_refreshing = false;
|
||||
|
||||
Logfrm = NULL;
|
||||
dlgName = wxT("frmMain");
|
||||
SetMinSize(wxSize(600, 450));
|
||||
RestorePosition(50, 50, 750, 550, 600, 450);
|
||||
|
|
@ -375,6 +376,7 @@ void frmMain::CreateMenus()
|
|||
|
||||
new connectServerFactory(menuFactories, toolsMenu, 0);
|
||||
new disconnectServerFactory(menuFactories, toolsMenu, 0);
|
||||
new disconnectServerFactoryAll(menuFactories, toolsMenu, 0);
|
||||
new disconnectDatabaseFactory(menuFactories, toolsMenu, 0);
|
||||
|
||||
new startServiceFactory(menuFactories, toolsMenu, 0);
|
||||
|
|
@ -448,6 +450,7 @@ void frmMain::CreateMenus()
|
|||
|
||||
new backupFactory(menuFactories, toolsMenu, 0);
|
||||
new backupGlobalsFactory(menuFactories, toolsMenu, 0);
|
||||
new LogFactory(menuFactories, cfgMenu, 0);
|
||||
new backupServerFactory(menuFactories, toolsMenu, 0);
|
||||
new restoreFactory(menuFactories, toolsMenu, 0);
|
||||
new importFactory(menuFactories, toolsMenu, 0);
|
||||
|
|
|
|||
134
include/frm/frmLog.h
Normal file
134
include/frm/frmLog.h
Normal file
|
|
@ -0,0 +1,134 @@
|
|||
//////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// pgAdmin III - PostgreSQL Tools
|
||||
//
|
||||
// Copyright (C) 2002 - 2016, The pgAdmin Development Team
|
||||
// This software is released under the PostgreSQL Licence
|
||||
//
|
||||
// frmStatus.h - Status Screen
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef __FRMLOG_H
|
||||
#define __FRMLOG_H
|
||||
|
||||
// wxWindows headers
|
||||
#include <wx/wx.h>
|
||||
#include <wx/image.h>
|
||||
#include <wx/listctrl.h>
|
||||
#include <wx/notebook.h>
|
||||
#include <wx/notebook.h>
|
||||
#include <wx/dynarray.h>
|
||||
|
||||
|
||||
// wxAUI
|
||||
#include <wx/aui/aui.h>
|
||||
|
||||
#include "dlg/dlgClasses.h"
|
||||
#include "utils/factory.h"
|
||||
#include "ctl/ctlAuiNotebook.h"
|
||||
#include "log/StorageModel.h"
|
||||
#include "log/MyDataViewCtrl.h"
|
||||
|
||||
class RemoteConn2
|
||||
{
|
||||
public:
|
||||
RemoteConn2(pgConn* c)
|
||||
{
|
||||
conn = c;
|
||||
}
|
||||
~RemoteConn2()
|
||||
{
|
||||
if (conn) delete conn;
|
||||
}
|
||||
|
||||
pgConn* conn;
|
||||
};
|
||||
|
||||
WX_DECLARE_OBJARRAY(RemoteConn2, RemoteConnArray2);
|
||||
|
||||
enum
|
||||
{
|
||||
ID_SET_GROUP = 207,
|
||||
ID_CLEAR_ALL_FILTER = 208,
|
||||
ID_SET_DETAILGROUP = 209,
|
||||
ID_ADD_FILTER = 210,
|
||||
ID_NEXT_MAX
|
||||
};
|
||||
|
||||
|
||||
|
||||
//
|
||||
// This number MUST be incremented if changing any of the default perspectives
|
||||
//
|
||||
#define FRMLOG_PERSPECTIVE_VER wxT("8274")
|
||||
|
||||
#ifdef __WXMAC__
|
||||
#define FRMLOG_DEFAULT_PERSPECTIVE wxT("layout2|name=Activity;caption=Activity;state=6293500;dir=4;layer=0;row=0;pos=0;prop=100000;bestw=321;besth=244;minw=-1;minh=-1;maxw=-1;maxh=-1;floatx=462;floaty=165;floatw=595;floath=282|name=Locks;caption=Locks;state=6293500;dir=4;layer=0;row=0;pos=1;prop=100000;bestw=321;besth=244;minw=-1;minh=-1;maxw=-1;maxh=-1;floatx=-231;floaty=235;floatw=595;floath=282|name=Transactions;caption=Transactions;state=6293500;dir=4;layer=0;row=0;pos=2;prop=100000;bestw=0;besth=0;minw=-1;minh=-1;maxw=-1;maxh=-1;floatx=461;floaty=527;floatw=595;floath=282|name=Logfile;caption=Logfile;state=6293500;dir=5;layer=0;row=0;pos=0;prop=100000;bestw=0;besth=0;minw=-1;minh=-1;maxw=-1;maxh=-1;floatx=-103;floaty=351;floatw=595;floath=282|name=toolBar;caption=Tool bar;state=2124528;dir=1;layer=10;row=0;pos=0;prop=100000;bestw=808;besth=33;minw=-1;minh=-1;maxw=-1;maxh=-1;floatx=888;floaty=829;floatw=558;floath=49|dock_size(4,0,0)=583|dock_size(5,0,0)=10|dock_size(1,10,0)=35|")
|
||||
#else
|
||||
#ifdef __WXGTK__
|
||||
#define FRMLOG_DEFAULT_PERSPECTIVE wxT("layout2|name=Activity;caption=Activity;state=6293500;dir=4;layer=0;row=1;pos=0;prop=100000;bestw=20;besth=20;minw=-1;minh=-1;maxw=-1;maxh=-1;floatx=174;floaty=216;floatw=578;floath=282|name=Locks;caption=Locks;state=6293500;dir=4;layer=0;row=1;pos=2;prop=100000;bestw=20;besth=20;minw=-1;minh=-1;maxw=-1;maxh=-1;floatx=136;floaty=339;floatw=576;floath=283|name=Transactions;caption=Transactions;state=6293500;dir=4;layer=0;row=1;pos=3;prop=100000;bestw=20;besth=20;minw=-1;minh=-1;maxw=-1;maxh=-1;floatx=133;floaty=645;floatw=577;floath=283|name=Querystate;caption=Query State;state=6309884;dir=4;layer=0;row=1;pos=1;prop=100000;bestw=20;besth=20;minw=-1;minh=-1;maxw=-1;maxh=-1;floatx=154;floaty=255;floatw=1360;floath=751|name=Logfile;caption=Logfile;state=6293500;dir=5;layer=0;row=0;pos=0;prop=100000;bestw=20;besth=20;minw=-1;minh=-1;maxw=-1;maxh=-1;floatx=-1;floaty=-1;floatw=-1;floath=-1|name=toolBar;caption=toolBar;state=2108144;dir=1;layer=10;row=0;pos=0;prop=100000;bestw=716;besth=23;minw=-1;minh=-1;maxw=-1;maxh=-1;floatx=586;floaty=525;floatw=483;floath=49|dock_size(1,10,0)=25|dock_size(4,0,1)=1115|dock_size(5,0,0)=22|")
|
||||
#else
|
||||
#define FRMLOG_DEFAULT_PERSPECTIVE wxT("layout2|name=Activity;caption=Activity;state=6293500;dir=4;layer=0;row=1;pos=0;prop=100000;bestw=20;besth=20;minw=-1;minh=-1;maxw=-1;maxh=-1;floatx=174;floaty=216;floatw=578;floath=282|name=Locks;caption=Locks;state=6293500;dir=4;layer=0;row=1;pos=2;prop=100000;bestw=20;besth=20;minw=-1;minh=-1;maxw=-1;maxh=-1;floatx=136;floaty=339;floatw=576;floath=283|name=Transactions;caption=Transactions;state=6293500;dir=4;layer=0;row=1;pos=3;prop=100000;bestw=20;besth=20;minw=-1;minh=-1;maxw=-1;maxh=-1;floatx=133;floaty=645;floatw=577;floath=283|name=Querystate;caption=Query State;state=6309884;dir=4;layer=0;row=1;pos=1;prop=100000;bestw=20;besth=20;minw=-1;minh=-1;maxw=-1;maxh=-1;floatx=154;floaty=255;floatw=1360;floath=751|name=Logfile;caption=Logfile;state=6293500;dir=5;layer=0;row=0;pos=0;prop=100000;bestw=20;besth=20;minw=-1;minh=-1;maxw=-1;maxh=-1;floatx=-1;floaty=-1;floatw=-1;floath=-1|name=toolBar;caption=toolBar;state=2108144;dir=1;layer=10;row=0;pos=0;prop=100000;bestw=716;besth=23;minw=-1;minh=-1;maxw=-1;maxh=-1;floatx=586;floaty=525;floatw=483;floath=49|dock_size(1,10,0)=25|dock_size(4,0,1)=1115|dock_size(5,0,0)=22|")
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
|
||||
class frmLog : public pgFrame
|
||||
{
|
||||
public:
|
||||
frmLog(frmMain *form, const wxString &_title, pgServer *srv);
|
||||
~frmLog();
|
||||
void Go();
|
||||
void getFilename();
|
||||
void readLogFile(wxString logfileName, long& lenfile, long& logfileLength, wxString& savedPartialLine, pgConn* conn);
|
||||
void AddNewConn(pgConn* con);
|
||||
pgServer* getServer(wxString& strserver);
|
||||
pgConn* createConn(pgServer* srv);
|
||||
bool CheckConn(wxString host, int port);
|
||||
private:
|
||||
static const int timerInterval = 5000; // 1000 ms
|
||||
wxTimer m_timer;
|
||||
wxAuiManager manager;
|
||||
|
||||
frmMain *mainForm;
|
||||
pgConn *connection;
|
||||
RemoteConnArray2 conArray;
|
||||
MyDataViewCtrl* my_view;
|
||||
wxNotebook* m_notebook;
|
||||
wxStaticText* status;
|
||||
wxCheckBox *group, *detail;
|
||||
wxCheckListBox* lb;
|
||||
wxObjectDataPtr<StorageModel> m_storage_model;
|
||||
wxArrayString logfileName;
|
||||
wxArrayString savedPartialLine;
|
||||
wxArrayLong logfileLength;
|
||||
wxArrayLong len;
|
||||
void OnSetGroup(wxCommandEvent& event);
|
||||
void OnSetDetailGroup(wxCommandEvent& event);
|
||||
void OnClearAllFilter(wxCommandEvent& event);
|
||||
void OnAddFilterIgnore(wxCommandEvent& event);
|
||||
void OnSetFocus(wxFocusEvent& event);
|
||||
void OnKillFocus(wxFocusEvent& event);
|
||||
void OnActivate(wxActivateEvent& event);
|
||||
void OnTimer(wxTimerEvent& event);
|
||||
void seticon(bool errflag);
|
||||
|
||||
wxIcon idef;
|
||||
wxIcon idefRed;
|
||||
|
||||
DECLARE_EVENT_TABLE()
|
||||
};
|
||||
|
||||
class LogFactory : public contextActionFactory
|
||||
{
|
||||
public:
|
||||
LogFactory(menuFactoryList* list, wxMenu* mnu, ctlMenuToolbar* toolbar);
|
||||
wxWindow* StartDialog(frmMain* form, pgObject* obj);
|
||||
bool CheckEnable(pgObject* obj);
|
||||
};
|
||||
|
||||
|
||||
#endif
|
||||
|
|
@ -24,6 +24,7 @@
|
|||
#include "frm/frmQuery.h"
|
||||
#include "dlg/dlgClasses.h"
|
||||
#include "utils/factory.h"
|
||||
#include "frm/frmLog.h"
|
||||
|
||||
//
|
||||
// This number MUST be incremented if changing any of the default perspectives
|
||||
|
|
@ -41,6 +42,7 @@
|
|||
#endif
|
||||
#endif
|
||||
class pgServer;
|
||||
class Logfrm;
|
||||
class pgServerCollection;
|
||||
class ctlSQLBox;
|
||||
class ctlTree;
|
||||
|
|
@ -94,7 +96,6 @@ class frmMain : public pgFrame
|
|||
public:
|
||||
frmMain(const wxString &title);
|
||||
~frmMain();
|
||||
|
||||
void OnAction(wxCommandEvent &ev);
|
||||
void OnReport(wxCommandEvent &ev);
|
||||
wxString GetHelpPage() const;
|
||||
|
|
@ -191,12 +192,14 @@ public:
|
|||
void ObjectBrowserRefreshing(bool refresh)
|
||||
{
|
||||
m_refreshing = refresh;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
#if defined(HAVE_OPENSSL_CRYPTO) || defined(HAVE_GCRYPT)
|
||||
void OnSSHTunnelEvent(wxCommandEvent &event);
|
||||
#endif
|
||||
|
||||
public:
|
||||
frmLog* Logfrm;
|
||||
private:
|
||||
wxAuiManager manager;
|
||||
ctlTree *browser;
|
||||
|
|
|
|||
53
include/log/MyDataViewCtrl.h
Normal file
53
include/log/MyDataViewCtrl.h
Normal file
|
|
@ -0,0 +1,53 @@
|
|||
#pragma once
|
||||
#include "wx\dataview.h"
|
||||
#include "wx/wx.h"
|
||||
#include "Storage.h"
|
||||
class MyDataViewCtrl :
|
||||
public wxDataViewCtrl
|
||||
{
|
||||
public:
|
||||
MyDataViewCtrl(wxWindow* parent, wxWindowID id,
|
||||
const wxPoint& pos = wxDefaultPosition,
|
||||
const wxSize& size = wxDefaultSize, long style = 0,
|
||||
const wxValidator& validator = wxDefaultValidator,
|
||||
const wxString& name = wxASCII_STR(wxDataViewCtrlNameStr)
|
||||
) : wxDataViewCtrl(parent, id, pos, size, style, validator, name)
|
||||
{
|
||||
|
||||
|
||||
}
|
||||
void setStatusObj(wxStaticText* o) {
|
||||
st = o;
|
||||
}
|
||||
int GetLastMouseRow() { return lastrow; };
|
||||
int GetLastMouseCol() { return lastcol; };
|
||||
wxString getSettingString();
|
||||
void setSettingString(wxString setstr);
|
||||
void setGroupMode(bool mode);
|
||||
void ViewGroup(bool view);
|
||||
void ClearAllFilter();
|
||||
void AddFilterIgnore();
|
||||
void AddRow(wxString csvtext);
|
||||
void OnMouseMove(wxMouseEvent& event);
|
||||
void OnKEY_DOWN(wxKeyEvent& event);
|
||||
#ifdef MYTEST
|
||||
void OnTimer(wxTimerEvent& event);
|
||||
#endif
|
||||
|
||||
void OnEVT_DATAVIEW_COLUMN_HEADER_CLICK(wxDataViewEvent& event);
|
||||
void OnEVT_DATAVIEW_CONTEXT_MENU(wxCommandEvent& event);
|
||||
void OnEVT_DATAVIEW_SELECTION_CHANGED(wxDataViewEvent& event);
|
||||
void OnContextMenu(wxDataViewEvent& event);
|
||||
DECLARE_EVENT_TABLE()
|
||||
|
||||
private:
|
||||
int lastrow = -1, lastcol = 1;
|
||||
wxDataViewItem selectRowGroup;
|
||||
bool modctrl = false;
|
||||
wxStaticText* st;
|
||||
//bool visibleEndLine = false;
|
||||
#ifdef MYTEST
|
||||
int linenumber = -1;
|
||||
wxArrayString logadd;
|
||||
#endif
|
||||
};
|
||||
183
include/log/Storage.h
Normal file
183
include/log/Storage.h
Normal file
|
|
@ -0,0 +1,183 @@
|
|||
#pragma once
|
||||
#include <deque>
|
||||
#include <wx/wx.h>
|
||||
#include "wx/hashmap.h"
|
||||
#include "utils/csvfiles.h"
|
||||
#define MYTEST 1
|
||||
|
||||
#define FL_REVERSE 1
|
||||
#define FL_CONTAINS 2
|
||||
|
||||
WX_DECLARE_HASH_MAP(int, int, wxIntegerHash, wxIntegerEqual, MyHashToRow);
|
||||
|
||||
namespace MyConst {
|
||||
enum colField {
|
||||
logtime,
|
||||
loguser,
|
||||
logdb,
|
||||
logpid,
|
||||
loghost,
|
||||
logtag,
|
||||
logSessiontime,
|
||||
logSeverity,
|
||||
logSqlstate,
|
||||
logMessage,
|
||||
logDetail,
|
||||
logHint,
|
||||
logappname,
|
||||
logbtype,
|
||||
Col_Max
|
||||
};
|
||||
enum iconIndex {
|
||||
log,
|
||||
war,
|
||||
user,
|
||||
error,
|
||||
fatal,
|
||||
panic,
|
||||
MAX_COL
|
||||
};
|
||||
enum ltype {
|
||||
SIMPLE_TEXT,
|
||||
InGroup,
|
||||
Group
|
||||
};
|
||||
}
|
||||
struct ps {
|
||||
unsigned short int s;
|
||||
unsigned short int l;
|
||||
};
|
||||
struct Line {
|
||||
unsigned short type : 3;
|
||||
unsigned short icon : 3;
|
||||
unsigned short visible : 1;
|
||||
int prevRowGroup = -1;
|
||||
int hash;
|
||||
ps logtime = { 0,0 };
|
||||
ps loguser = { 0,0 };
|
||||
ps logdb = { 0,0 };
|
||||
ps logpid = { 0,0 };
|
||||
ps loghost = { 0,0 };
|
||||
ps logtag = { 0,0 };
|
||||
ps logSessiontime = { 0,0 };
|
||||
ps logSeverity = { 0,0 };
|
||||
ps logSqlstate = { 0,0 };
|
||||
ps logMessage = { 0,0 };
|
||||
ps logDetail = { 0,0 };
|
||||
ps logHint = { 0,0 };
|
||||
ps logappname = { 0,0 };
|
||||
ps logbtype = { 0,0 };
|
||||
wxString text;
|
||||
};
|
||||
struct LineFilter {
|
||||
int col;
|
||||
int flags;
|
||||
wxString val;
|
||||
};
|
||||
|
||||
class Storage
|
||||
{
|
||||
public:
|
||||
bool AddLineTextCSV(const wxString& strcsv);
|
||||
wxString GetField(int row, MyConst::colField col);
|
||||
wxString GetFieldStorage(int row, MyConst::colField col, bool filter);
|
||||
Storage();
|
||||
int GetSeverityIndex(int row);
|
||||
void SetHost(wxString& host) { currhost = host; };
|
||||
wxString GetHost() { return currhost; };
|
||||
void SetErrMsgFlag(bool flag) { err_msg = flag; };
|
||||
bool GetErrMsgFlag() { return err_msg; };
|
||||
void GetRowsStat(int& Rowsadd, int& Rowsignore) {
|
||||
Rowsadd=rowsadd;
|
||||
Rowsignore=rowsignore;
|
||||
};
|
||||
void ClearRowsStat() {
|
||||
rowsadd = 0;
|
||||
rowsignore = 0;
|
||||
};
|
||||
wxColor& GetBgColorLine(int row);
|
||||
// óñòàíîâêà ôèëüòðà íà êîëîíêó
|
||||
int SetFilter(int colfld, wxString& val, int flags);
|
||||
// ïðèìèíèòü ôèëüòð äëÿ ñòðîêè èëè äëÿ âñå ñòðîê õðàíèëèùà
|
||||
// true åñëè ñòðîêà íå îòôèëüòðîâàëàñü (âèäíà)
|
||||
bool ApplyFilter(int row = -1);
|
||||
wxString getStrGroup(wxString source);
|
||||
int testFilter(MyConst::colField col, int position);
|
||||
wxString GetStringFilterExpr(int positionArrayFilter,bool addNumCol=false);
|
||||
void addLineFilterStr(wxString strflt);
|
||||
wxString _strwhere(int flags);
|
||||
void saveFilters();
|
||||
wxString LineFilterToStr(LineFilter& lf);
|
||||
//
|
||||
int getHashString(wxString str) {
|
||||
std::hash<wxString> string_hash;
|
||||
return string_hash(str);
|
||||
}
|
||||
void DropColFilter(int index);
|
||||
void setDetailGroupRow(int rowGroup);
|
||||
bool IsGroupFilter() {
|
||||
return groupFilterUse;
|
||||
};
|
||||
bool IsFilter() {
|
||||
return fCol.size() > 0 || IsGroupFilter();
|
||||
};
|
||||
void setGroupFilter(bool val) {
|
||||
detailGroup = -1;
|
||||
groupFilterUse = val;
|
||||
MyHashToRow::iterator it;
|
||||
for (it = hashKeyToCount.begin(); it != hashKeyToCount.end(); ++it)
|
||||
{
|
||||
int keyhash = it->first, lastrow = it->second;
|
||||
// do something useful with key and value
|
||||
it->second = 0;
|
||||
}
|
||||
m_cacheIndex = -1;
|
||||
frows.clear();
|
||||
}
|
||||
void ClearCount(int rowfilter);
|
||||
bool IsAddGroupNew() {
|
||||
return faddgroup;
|
||||
};
|
||||
int getLastRowIndex() { return m_cacheIndex; }
|
||||
// âñåãî ñòðîê â õðàíèëèùå
|
||||
int getCountStore();
|
||||
int getCountFilter();
|
||||
int getCountGroup(int row);
|
||||
int GetTotalCountGroup(int rowfilter);
|
||||
|
||||
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);
|
||||
void getLineToCache(int row, bool filter = true);
|
||||
bool CompareFilterLine(int row, bool filter);
|
||||
|
||||
std::deque<Line> storage;
|
||||
std::deque<LineFilter> filterload;
|
||||
// hash Group to row
|
||||
MyHashToRow hashKeyToRow;
|
||||
MyHashToRow hashKeyToCount;
|
||||
MyHashToRow hashKeyTotal;
|
||||
//filter setting
|
||||
std::deque<int> frows;
|
||||
wxArrayInt fCol;
|
||||
wxArrayInt fFlags;
|
||||
wxArrayString fVal;
|
||||
// ïðèçíàê îøèáîê.
|
||||
bool err_msg;
|
||||
// ðåæèì ãðóïïèðîâêè
|
||||
bool groupFilterUse = false;
|
||||
bool faddgroup = false;
|
||||
int prevRow = -1;
|
||||
int detailGroup = -1;
|
||||
//
|
||||
int m_cacheIndex = -1;
|
||||
Line m_cacheLine;
|
||||
//
|
||||
int rowsadd;
|
||||
int rowsignore;
|
||||
wxColor bgErr[MyConst::iconIndex::MAX_COL];
|
||||
wxString currhost;
|
||||
};
|
||||
|
||||
101
include/log/StorageModel.h
Normal file
101
include/log/StorageModel.h
Normal file
|
|
@ -0,0 +1,101 @@
|
|||
#pragma once
|
||||
#include "pgAdmin3.h"
|
||||
#include "wx/hashmap.h"
|
||||
#include "wx/vector.h"
|
||||
#include "Storage.h"
|
||||
#include "MyDataViewCtrl.h"
|
||||
|
||||
|
||||
WX_DECLARE_STRING_HASH_MAP(int, MyHashCount);
|
||||
|
||||
class StorageModel : public wxDataViewVirtualListModel
|
||||
{
|
||||
public:
|
||||
enum cols
|
||||
{
|
||||
Col_ToggleIconText,
|
||||
Col_LogTime,
|
||||
Col_User,
|
||||
Col_Db,
|
||||
Col_PID,
|
||||
Col_Host,
|
||||
Col_App,
|
||||
Col_Hint,
|
||||
Col_Detail,
|
||||
Col_Message,
|
||||
Col_Max
|
||||
};
|
||||
|
||||
StorageModel(MyDataViewCtrl* view);
|
||||
|
||||
// helper methods to change the model
|
||||
|
||||
bool Prepend(const wxString& text);
|
||||
void DeleteItem(const wxDataViewItem& item);
|
||||
void DeleteItems(const wxDataViewItemArray& items);
|
||||
void AddMany();
|
||||
bool setFilter(int col, wxString val, int flags, MyDataViewCtrl* view);
|
||||
void DropColFilter(int index);
|
||||
int testFilter(int col, int position);
|
||||
void ApplyFilter();
|
||||
bool getGroupFilter()
|
||||
{
|
||||
return store->IsGroupFilter();
|
||||
}
|
||||
void setGroupFilter(bool val)
|
||||
{
|
||||
store->setGroupFilter(val);
|
||||
ApplyFilter();
|
||||
}
|
||||
void BuildColumns(MyDataViewCtrl* ctrl);
|
||||
void IncCountFreq(int col, wxString &val) {
|
||||
MyHashCount::const_iterator it = freqValues[col].find(val);
|
||||
int cnt=0;
|
||||
if (it != freqValues[col].end())
|
||||
cnt = it->second;
|
||||
cnt++;
|
||||
freqValues[col][val] = cnt;
|
||||
}
|
||||
|
||||
// implementation of base class virtuals to define model
|
||||
|
||||
virtual unsigned int GetColumnCount() const wxOVERRIDE
|
||||
{
|
||||
return Col_Max;
|
||||
}
|
||||
|
||||
unsigned int GetRowCount() const
|
||||
{
|
||||
return store->getCountFilter();
|
||||
}
|
||||
|
||||
virtual wxString GetColumnType(unsigned int col) const wxOVERRIDE
|
||||
{
|
||||
if (col == Col_ToggleIconText)
|
||||
return wxDataViewCheckIconTextRenderer::GetDefaultType();
|
||||
|
||||
return "string";
|
||||
}
|
||||
Storage* getStorage() {
|
||||
return store;
|
||||
}
|
||||
virtual void GetValueByRow(wxVariant& variant,
|
||||
unsigned int row, unsigned int col) const wxOVERRIDE;
|
||||
virtual bool GetAttrByRow(unsigned int row, unsigned int col,
|
||||
wxDataViewItemAttr& attr) const wxOVERRIDE;
|
||||
virtual bool SetValueByRow(const wxVariant& variant,
|
||||
unsigned int row, unsigned int col) wxOVERRIDE;
|
||||
MyHashCount freqValues[Col_Max];
|
||||
wxBitmap bitmapflt;
|
||||
unsigned int lastrow;
|
||||
MyDataViewCtrl* m_view;
|
||||
private:
|
||||
///IntToStringMap m_customColValues;
|
||||
wxIcon m_icon[MyConst::iconIndex::MAX_COL];
|
||||
|
||||
Storage* store;
|
||||
MyConst::colField colmap[Col_Max];
|
||||
|
||||
|
||||
};
|
||||
|
||||
25
include/log/error_xpm.xpm
Normal file
25
include/log/error_xpm.xpm
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
/* XPM */
|
||||
static char *error_xpm[] = {
|
||||
"16 16 5 1 0 0",
|
||||
" c #000000",
|
||||
"! c #FF0000",
|
||||
"# c #333333",
|
||||
"$ c #FF8080",
|
||||
"% c None",
|
||||
"################",
|
||||
"#%%%%%%%%%%%%%%#",
|
||||
"#%%!!!!!!%%%%%%#",
|
||||
"#%%!!!!!!%%%%%%#",
|
||||
"#%%!!$%%%%%%%%%#",
|
||||
"#%%!!%%%%%%%%%%#",
|
||||
"#%%!!%%%%%%%%%%#",
|
||||
"#%%!!!!!%%%%%%%#",
|
||||
"#%%!!!!!%%%%%%%#",
|
||||
"#%%!!$%%%%%%%%%#",
|
||||
"#%%!!%%%%%%%%%%#",
|
||||
"#%%!!%%%%%%%%%%#",
|
||||
"#%%!!!!!!%%%%%%#",
|
||||
"#%%!!!!!!%%%%%%#",
|
||||
"#%%%%%%%%%%%%%%#",
|
||||
"################"
|
||||
};
|
||||
25
include/log/errorl_xpm.xpm
Normal file
25
include/log/errorl_xpm.xpm
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
/* XPM */
|
||||
static char *errorl_xpm[] = {
|
||||
"16 16 5 1 0 0",
|
||||
" c #000000",
|
||||
"! c #FF0000",
|
||||
"# c #333333",
|
||||
"$ c #FF8080",
|
||||
"% c None",
|
||||
"################",
|
||||
"#%%%%%%%%%%%%%%#",
|
||||
"#%%!!!!!!%%%%%%#",
|
||||
"#%%!!!!!!%%%%%%#",
|
||||
"#%%!!$%%%%%%%%%#",
|
||||
"#%%!!%%%%%%%%%%#",
|
||||
"#%%!!%%%%%%%%%%#",
|
||||
"#%%!!!!!%%%%%%%#",
|
||||
"#%%!!!!!%%%%%%%#",
|
||||
"#%%!!$%%%%%%%%%#",
|
||||
"#%%!!%%%%%%%%%%#",
|
||||
"#%%!!%%%%%%%%%%#",
|
||||
"#%%!!!!!!%%%%%%#",
|
||||
"#%%!!!!!!%%%%%%#",
|
||||
"#%%%%%%%%%%%%%%#",
|
||||
"################"
|
||||
};
|
||||
26
include/log/fatal_xpm.xpm
Normal file
26
include/log/fatal_xpm.xpm
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
/* XPM */
|
||||
static char *fatal_xpm[] = {
|
||||
"16 16 6 1 0 0",
|
||||
" c #000000",
|
||||
"! c #FF0000",
|
||||
"# c #333333",
|
||||
"$ c #FF8080",
|
||||
"% c #FFFFFF",
|
||||
"& c None",
|
||||
"################",
|
||||
"#&%%%%%%%%&&&&&#",
|
||||
"#&%!!!!!!%&&&&&#",
|
||||
"#&%!!!!!!%&&&&&#",
|
||||
"#&%!!$%%%%&&&&&#",
|
||||
"#&%!!%&&&&&&&&&#",
|
||||
"#&%!!%%%%&&&&&&#",
|
||||
"#&%!!!!!%&&&&&&#",
|
||||
"#&%!!!!!%&&&&&&#",
|
||||
"#&%!!$%%%&&&&&&#",
|
||||
"#&%!!%&&&&&&&&&#",
|
||||
"#&%!!%&&&&&&&&&#",
|
||||
"#&%!!%&&&&&&&&&#",
|
||||
"#&%!!%&&&&&&&&&#",
|
||||
"#&%%%%&&&&&&&&&#",
|
||||
"################"
|
||||
};
|
||||
34
include/log/filter_xpm.xpm
Normal file
34
include/log/filter_xpm.xpm
Normal file
|
|
@ -0,0 +1,34 @@
|
|||
/* XPM */
|
||||
static char *filter_xpm[] = {
|
||||
"16 16 14 1 0 0",
|
||||
" c #000000",
|
||||
"! c #151515",
|
||||
"# c #181818",
|
||||
"$ c #202020",
|
||||
"% c #242424",
|
||||
"& c #2C2C2C",
|
||||
"' c #323232",
|
||||
"( c #333333",
|
||||
") c #474747",
|
||||
"* c #848484",
|
||||
"+ c #898989",
|
||||
", c #929292",
|
||||
"- c #FFFFFF",
|
||||
". c None",
|
||||
"................",
|
||||
"..)&((((((((#!..",
|
||||
"..* ........ ..",
|
||||
".. %,...... ...",
|
||||
"... '..... ....",
|
||||
"....$+.... .....",
|
||||
".... ... .....",
|
||||
"..... ... ......",
|
||||
"...... .. ......",
|
||||
"...... .. ......",
|
||||
"...... .. ......",
|
||||
"...... .. ......",
|
||||
"...... .. ......",
|
||||
"...... .. ......",
|
||||
"...... ......",
|
||||
"................"
|
||||
};
|
||||
27
include/log/log_red_xpm.xpm
Normal file
27
include/log/log_red_xpm.xpm
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
/* XPM */
|
||||
static char *log_red_xpm[] = {
|
||||
"16 16 7 1 0 0",
|
||||
" c #000000",
|
||||
"! c #FF0000",
|
||||
"# c #2B2B2B",
|
||||
"$ c #4E4E4E",
|
||||
"% c #717171",
|
||||
"& c #FFFFFF",
|
||||
"' c None",
|
||||
" ",
|
||||
" '''''''''''''' ",
|
||||
" '& %''''''''' ",
|
||||
" '& #''''''''' ",
|
||||
" '& #'!!!!!!'' ",
|
||||
" '& #'!!!!!!'' ",
|
||||
" '& #'!!!!!!'' ",
|
||||
" '& #'!!!!!!'' ",
|
||||
" '& #'!!!!!!'' ",
|
||||
" '& #'!!!!!!'' ",
|
||||
" '& #''''''''' ",
|
||||
" '& #''''''''' ",
|
||||
" '& $''' ",
|
||||
" '& $''' ",
|
||||
" '&&&&&&&&&'''' ",
|
||||
" "
|
||||
};
|
||||
26
include/log/log_xpm.xpm
Normal file
26
include/log/log_xpm.xpm
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
/* XPM */
|
||||
static char *log_xpm[] = {
|
||||
"16 16 6 1 0 0",
|
||||
" c #000000",
|
||||
"! c #2B2B2B",
|
||||
"# c #4E4E4E",
|
||||
"$ c #717171",
|
||||
"% c #FFFFFF",
|
||||
"& c None",
|
||||
" ",
|
||||
" &&&&&&&&&&&&&& ",
|
||||
" &% $&&&&&&&&& ",
|
||||
" &% !&&&&&&&&& ",
|
||||
" &% !&&&&&&&&& ",
|
||||
" &% !&&&&&&&&& ",
|
||||
" &% !&&&&&&&&& ",
|
||||
" &% !&&&&&&&&& ",
|
||||
" &% !&&&&&&&&& ",
|
||||
" &% !&&&&&&&&& ",
|
||||
" &% !&&&&&&&&& ",
|
||||
" &% !&&&&&&&&& ",
|
||||
" &% #&&& ",
|
||||
" &% #&&& ",
|
||||
" &%%%%%%%%%&&&& ",
|
||||
" "
|
||||
};
|
||||
30
include/log/null.xpm
Normal file
30
include/log/null.xpm
Normal file
|
|
@ -0,0 +1,30 @@
|
|||
/* XPM */
|
||||
static const char *const null_xpm[] = {
|
||||
"16 16 11 1",
|
||||
" c None",
|
||||
". c #000000",
|
||||
"+ c #FFFFFF",
|
||||
"@ c #FDE4E4",
|
||||
"# c #F45C5C",
|
||||
"$ c #EF0B0B",
|
||||
"% c #F12727",
|
||||
"& c #F67878",
|
||||
"* c #FAAEAE",
|
||||
"= c #FBC9C9",
|
||||
"- c #F89393",
|
||||
"................",
|
||||
".++++++++++++++.",
|
||||
".++++++++++++++.",
|
||||
".++++@#$$%&++++.",
|
||||
".+++@%$$$$$&+++.",
|
||||
".+++&$$#*%$$+++.",
|
||||
".+++=-#+@%$%+++.",
|
||||
".++++++@%$$*+++.",
|
||||
".++++++%$%@++++.",
|
||||
".+++++*$$*+++++.",
|
||||
".+++++@**@+++++.",
|
||||
".+++++*$$*+++++.",
|
||||
".+++++*$$*+++++.",
|
||||
".+++++@**@+++++.",
|
||||
".++++++++++++++.",
|
||||
"................"};
|
||||
26
include/log/panic_xpm.xpm
Normal file
26
include/log/panic_xpm.xpm
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
/* XPM */
|
||||
static char *panic_xpm[] = {
|
||||
"16 16 6 1 0 0",
|
||||
" c #000000",
|
||||
"! c #FF0000",
|
||||
"# c #333333",
|
||||
"$ c #FF8080",
|
||||
"% c #FFFFFF",
|
||||
"& c None",
|
||||
"################",
|
||||
"#&%%%%%%%%%&&&&#",
|
||||
"#&%!!!!!!!!%%&&#",
|
||||
"#&%!!!!!!!!!%&&#",
|
||||
"#&%!!$%%%%!!%&&#",
|
||||
"#&%!!$%&&%!!%&&#",
|
||||
"#&%!!$%&&%!!%&&#",
|
||||
"#&%!!$%%%!!!%&&#",
|
||||
"#&%!!!!!!!!%%&&#",
|
||||
"#&%!!!!!!!%%&&&#",
|
||||
"#&%!!$%%%%%&&&&#",
|
||||
"#&%!!$%&&&&&&&&#",
|
||||
"#&%!!$%&&&&&&&&#",
|
||||
"#&%!!$%&&&&&&&&#",
|
||||
"#&%%%%&&&&&&&&&#",
|
||||
"################"
|
||||
};
|
||||
23
include/log/user_xpm.xpm
Normal file
23
include/log/user_xpm.xpm
Normal file
|
|
@ -0,0 +1,23 @@
|
|||
/* XPM */
|
||||
static char *user_xpm[] = {
|
||||
"16 16 3 1 0 0",
|
||||
" c #000000",
|
||||
"! c #3F28D9",
|
||||
"# c None",
|
||||
" ",
|
||||
" ############## ",
|
||||
" ############## ",
|
||||
" ##!!###!!##### ",
|
||||
" ##!!###!!##### ",
|
||||
" ##!!###!!##### ",
|
||||
" ##!!###!!##### ",
|
||||
" ##!!###!!##### ",
|
||||
" ##!!###!!##### ",
|
||||
" ##!!###!!##### ",
|
||||
" ##!!###!!##### ",
|
||||
" ##!!###!!##### ",
|
||||
" ###!!!!!###### ",
|
||||
" ############## ",
|
||||
" ############## ",
|
||||
" "
|
||||
};
|
||||
23
include/log/war_xpm.xpm
Normal file
23
include/log/war_xpm.xpm
Normal file
|
|
@ -0,0 +1,23 @@
|
|||
/* XPM */
|
||||
static char *war_xpm[] = {
|
||||
"16 16 3 1 0 0",
|
||||
" c #000000",
|
||||
"! c #C0C0C0",
|
||||
"# c None",
|
||||
" ",
|
||||
" ############## ",
|
||||
" ############## ",
|
||||
" ############## ",
|
||||
" ### ### ! ",
|
||||
" !## ### ! ",
|
||||
" # !# ! !#! !! ",
|
||||
" # !! ! # !# ",
|
||||
" # ! ! # !# ",
|
||||
" # ! !# # !# ",
|
||||
" ## ! !!# ! !!# ",
|
||||
" ## !## !## ",
|
||||
" ## !## !## ",
|
||||
" ## !## !## ",
|
||||
" ############## ",
|
||||
" "
|
||||
};
|
||||
28
include/log/wx_small.xpm
Normal file
28
include/log/wx_small.xpm
Normal file
|
|
@ -0,0 +1,28 @@
|
|||
/* XPM */
|
||||
static const char *wx_small_xpm[] = {
|
||||
/* columns rows colors chars-per-pixel */
|
||||
"16 16 6 1",
|
||||
". c Black",
|
||||
"o c #FFFFFF",
|
||||
"X c #000080",
|
||||
"O c #FFFF00",
|
||||
" c None",
|
||||
"+ c #FF0000",
|
||||
/* pixels */
|
||||
" ",
|
||||
" ",
|
||||
" ",
|
||||
" ....... ",
|
||||
" .XXXXX. ",
|
||||
" .oXXXX. ",
|
||||
" .oXXX.......",
|
||||
".....oXXX.OOOOO.",
|
||||
".+++.XXXX.oOOOO.",
|
||||
".o++......oOOOO.",
|
||||
".o++++. .oOOOO.",
|
||||
".o++++. .OOOOO.",
|
||||
".+++++. .......",
|
||||
"....... ",
|
||||
" ",
|
||||
" "
|
||||
};
|
||||
|
|
@ -666,12 +666,19 @@ public:
|
|||
};
|
||||
|
||||
|
||||
class disconnectServerFactoryAll : public contextActionFactory
|
||||
{
|
||||
public:
|
||||
disconnectServerFactoryAll(menuFactoryList *list, wxMenu *mnu, ctlMenuToolbar *toolbar);
|
||||
wxWindow *StartDialog(frmMain *form, pgObject *obj);
|
||||
bool CheckEnable(pgObject *obj);
|
||||
};
|
||||
class disconnectServerFactory : public contextActionFactory
|
||||
{
|
||||
public:
|
||||
disconnectServerFactory(menuFactoryList *list, wxMenu *mnu, ctlMenuToolbar *toolbar);
|
||||
wxWindow *StartDialog(frmMain *form, pgObject *obj);
|
||||
bool CheckEnable(pgObject *obj);
|
||||
disconnectServerFactory(menuFactoryList* list, wxMenu* mnu, ctlMenuToolbar* toolbar);
|
||||
wxWindow* StartDialog(frmMain* form, pgObject* obj);
|
||||
bool CheckEnable(pgObject* obj);
|
||||
};
|
||||
|
||||
class reloadconfServiceFactory : public contextActionFactory
|
||||
|
|
|
|||
|
|
@ -26,6 +26,7 @@ enum
|
|||
FEATURE_PGSTATINDEX,
|
||||
FEATURE_PGCHECKINDEX,
|
||||
FEATURE_FUNCTION_DEFAULTS,
|
||||
FEATURE_CSVLOG,
|
||||
FEATURE_LAST
|
||||
};
|
||||
|
||||
|
|
|
|||
19
pgAdmin3.cpp
19
pgAdmin3.cpp
|
|
@ -54,6 +54,7 @@
|
|||
#include "frm/frmConfig.h"
|
||||
#include "frm/frmQuery.h"
|
||||
#include "frm/frmStatus.h"
|
||||
#include "frm/frmLog.h"
|
||||
#ifdef DATABASEDESIGNER
|
||||
#include "frm/frmDatabaseDesigner.h"
|
||||
#endif
|
||||
|
|
@ -281,6 +282,7 @@ bool pgAdmin3::OnInit()
|
|||
{wxCMD_LINE_SWITCH, "h", "help", _("show this help message, and quit"), wxCMD_LINE_VAL_NONE, wxCMD_LINE_OPTION_HELP },
|
||||
{wxCMD_LINE_OPTION, "s", "server", _("auto-connect to specified server"), wxCMD_LINE_VAL_STRING},
|
||||
{wxCMD_LINE_SWITCH, "S", "serverstatus", _("open server status window"), wxCMD_LINE_VAL_NONE},
|
||||
{wxCMD_LINE_SWITCH, "L", "log window", _("open server log window"), wxCMD_LINE_VAL_NONE},
|
||||
{wxCMD_LINE_OPTION, "Sc", "serverstatusconnect", _("connect server status window to database"), wxCMD_LINE_VAL_STRING},
|
||||
{wxCMD_LINE_SWITCH, "q", "query", _("open query tool"), wxCMD_LINE_VAL_NONE},
|
||||
{wxCMD_LINE_OPTION, "qc", "queryconnect", _("connect query tool to database"), wxCMD_LINE_VAL_STRING},
|
||||
|
|
@ -575,10 +577,11 @@ bool pgAdmin3::OnInit()
|
|||
}
|
||||
if (!conn)
|
||||
return false;
|
||||
|
||||
wxString txt = _("Server Status - ") + conn->GetName();
|
||||
frmStatus *fq = new frmStatus(NULL, txt, conn);
|
||||
fq->Go();
|
||||
|
||||
wxString txt = _("Server Status - ") + conn->GetName();
|
||||
frmStatus* fq = new frmStatus(NULL, txt, conn);
|
||||
fq->Go();
|
||||
|
||||
}
|
||||
|
||||
#ifdef DATABASEDESIGNER
|
||||
|
|
@ -793,6 +796,14 @@ bool pgAdmin3::OnInit()
|
|||
if (cmdParser.Found(wxT("s"), &str))
|
||||
{
|
||||
pgServer *srv = winMain->ConnectToServer(str, !cmdParser.Found(wxT("q")));
|
||||
if (srv && cmdParser.Found(wxT("L"))) {
|
||||
//PgConn* newcon = srv->GetConnection()->Duplicate("Log conn");
|
||||
wxString txt = _("Log - ") + srv->GetConnection()->GetName();
|
||||
winMain->Logfrm = new frmLog(winMain, txt, srv);
|
||||
winMain->Logfrm->Go();
|
||||
|
||||
}
|
||||
|
||||
if (srv && cmdParser.Found(wxT("q")))
|
||||
{
|
||||
pgConn *conn;
|
||||
|
|
|
|||
|
|
@ -905,6 +905,7 @@
|
|||
<ClCompile Include="frm\frmHbaConfig.cpp" />
|
||||
<ClCompile Include="frm\frmHint.cpp" />
|
||||
<ClCompile Include="frm\frmImport.cpp" />
|
||||
<ClCompile Include="frm\frmLog.cpp" />
|
||||
<ClCompile Include="frm\frmMain.cpp" />
|
||||
<ClCompile Include="frm\frmMainConfig.cpp" />
|
||||
<ClCompile Include="frm\frmMaintenance.cpp" />
|
||||
|
|
@ -1012,6 +1013,9 @@
|
|||
<ClCompile Include="utils\diff_match_patch.cc" />
|
||||
<ClCompile Include="utils\factory.cpp" />
|
||||
<ClCompile Include="utils\favourites.cpp" />
|
||||
<ClCompile Include="utils\log\MyDataViewCtrl.cpp" />
|
||||
<ClCompile Include="utils\log\Storage.cpp" />
|
||||
<ClCompile Include="utils\log\StorageModel.cpp" />
|
||||
<ClCompile Include="utils\macros.cpp" />
|
||||
<ClCompile Include="utils\misc.cpp" />
|
||||
<ClCompile Include="utils\pgconfig.cpp" />
|
||||
|
|
@ -1353,6 +1357,16 @@
|
|||
<None Include="db\module.mk" />
|
||||
<None Include="dlg\module.mk" />
|
||||
<None Include="frm\module.mk" />
|
||||
<None Include="include\log\errorl_xpm.xpm" />
|
||||
<None Include="include\log\error_xpm.xpm" />
|
||||
<None Include="include\log\fatal_xpm.xpm" />
|
||||
<None Include="include\log\filter_xpm.xpm" />
|
||||
<None Include="include\log\log_xpm.xpm" />
|
||||
<None Include="include\log\null.xpm" />
|
||||
<None Include="include\log\panic_xpm.xpm" />
|
||||
<None Include="include\log\user_xpm.xpm" />
|
||||
<None Include="include\log\war_xpm.xpm" />
|
||||
<None Include="include\log\wx_small.xpm" />
|
||||
<None Include="include\module.mk" />
|
||||
<None Include="include\utils\module.mk" />
|
||||
<None Include="include\ctl\module.mk" />
|
||||
|
|
@ -1528,6 +1542,10 @@
|
|||
<ClInclude Include="include\copyright.h" />
|
||||
<ClInclude Include="include\dlg\dlgProJob.h" />
|
||||
<ClInclude Include="include\dlg\dlgResourceGroup.h" />
|
||||
<ClInclude Include="include\frm\frmLog.h" />
|
||||
<ClInclude Include="include\log\MyDataViewCtrl.h" />
|
||||
<ClInclude Include="include\log\Storage.h" />
|
||||
<ClInclude Include="include\log\StorageModel.h" />
|
||||
<ClInclude Include="include\pgAdmin3.h" />
|
||||
<ClInclude Include="include\postgres.h" />
|
||||
<ClInclude Include="include\precomp.h" />
|
||||
|
|
|
|||
|
|
@ -251,6 +251,9 @@
|
|||
<Filter Include="include\pro_scheduler">
|
||||
<UniqueIdentifier>{bc8bb60a-46b2-4f26-b86f-f711fcc2a385}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="include\log">
|
||||
<UniqueIdentifier>{e2f5428c-112b-47e2-8394-cf4a5c1a8d8a}</UniqueIdentifier>
|
||||
</Filter>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="agent\dlgJob.cpp">
|
||||
|
|
@ -1635,6 +1638,18 @@
|
|||
<ClCompile Include="dlg\dlgProJob.cpp">
|
||||
<Filter>dlg</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="frm\frmLog.cpp">
|
||||
<Filter>frm</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="utils\log\Storage.cpp">
|
||||
<Filter>utils</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="utils\log\StorageModel.cpp">
|
||||
<Filter>utils</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="utils\log\MyDataViewCtrl.cpp">
|
||||
<Filter>utils</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="agent\module.mk">
|
||||
|
|
@ -2154,6 +2169,36 @@
|
|||
<None Include="ui\dlgMoveTablespace.xrc">
|
||||
<Filter>ui</Filter>
|
||||
</None>
|
||||
<None Include="include\log\error_xpm.xpm">
|
||||
<Filter>include\log</Filter>
|
||||
</None>
|
||||
<None Include="include\log\errorl_xpm.xpm">
|
||||
<Filter>include\log</Filter>
|
||||
</None>
|
||||
<None Include="include\log\fatal_xpm.xpm">
|
||||
<Filter>include\log</Filter>
|
||||
</None>
|
||||
<None Include="include\log\filter_xpm.xpm">
|
||||
<Filter>include\log</Filter>
|
||||
</None>
|
||||
<None Include="include\log\log_xpm.xpm">
|
||||
<Filter>include\log</Filter>
|
||||
</None>
|
||||
<None Include="include\log\null.xpm">
|
||||
<Filter>include\log</Filter>
|
||||
</None>
|
||||
<None Include="include\log\panic_xpm.xpm">
|
||||
<Filter>include\log</Filter>
|
||||
</None>
|
||||
<None Include="include\log\user_xpm.xpm">
|
||||
<Filter>include\log</Filter>
|
||||
</None>
|
||||
<None Include="include\log\war_xpm.xpm">
|
||||
<Filter>include\log</Filter>
|
||||
</None>
|
||||
<None Include="include\log\wx_small.xpm">
|
||||
<Filter>include\log</Filter>
|
||||
</None>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="include\copyright.h">
|
||||
|
|
@ -3491,6 +3536,18 @@
|
|||
<ClInclude Include="include\dlg\dlgProJob.h">
|
||||
<Filter>include\dlg</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="include\frm\frmLog.h">
|
||||
<Filter>include\frm</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="include\log\Storage.h">
|
||||
<Filter>include\log</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="include\log\StorageModel.h">
|
||||
<Filter>include\log</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="include\log\MyDataViewCtrl.h">
|
||||
<Filter>include\log</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<png2c Include="include\images\aggregate-sm.png">
|
||||
|
|
|
|||
|
|
@ -2170,6 +2170,67 @@ bool disconnectServerFactory::CheckEnable(pgObject *obj)
|
|||
return false;
|
||||
}
|
||||
|
||||
disconnectServerFactoryAll::disconnectServerFactoryAll(menuFactoryList* list, wxMenu* mnu, ctlMenuToolbar* toolbar) : contextActionFactory(list)
|
||||
{
|
||||
mnu->Append(id, _("Disconnec&t all servers"), _("Disconnect from all servers."));
|
||||
}
|
||||
|
||||
|
||||
wxWindow* disconnectServerFactoryAll::StartDialog(frmMain* form, pgObject* obj)
|
||||
{
|
||||
|
||||
wxTreeItemIdValue foldercookie, servercookie;
|
||||
wxTreeItemId folderitem, serveritem;
|
||||
pgObject* object;
|
||||
pgServer* server;
|
||||
folderitem = form->GetBrowser()->GetFirstChild(form->GetBrowser()->GetRootItem(), foldercookie);
|
||||
while (folderitem)
|
||||
{
|
||||
if (form->GetBrowser()->ItemHasChildren(folderitem))
|
||||
{
|
||||
serveritem = form->GetBrowser()->GetFirstChild(folderitem, servercookie);
|
||||
while (serveritem)
|
||||
{
|
||||
object = form->GetBrowser()->GetObject(serveritem);
|
||||
if (object && object->IsCreatedBy(serverFactory))
|
||||
{
|
||||
if (CheckEnable(object)) {
|
||||
if (object->CheckOpenDialogs(form->GetBrowser(), serveritem))
|
||||
{
|
||||
wxString msg = _("There are properties dialogues open for one or more objects belonging to a database which will be disconnected. Please close the properties dialogues and try again.");
|
||||
wxMessageBox(msg, _("Cannot disconnect database"), wxICON_WARNING | wxOK);
|
||||
}
|
||||
else
|
||||
{
|
||||
server = (pgServer*)object;
|
||||
server->Disconnect(form);
|
||||
server->UpdateIcon(form->GetBrowser());
|
||||
form->GetBrowser()->DeleteChildren(object->GetId());
|
||||
form->execSelChange(object->GetId(), true);
|
||||
}
|
||||
}
|
||||
}
|
||||
serveritem = form->GetBrowser()->GetNextChild(folderitem, servercookie);
|
||||
}
|
||||
}
|
||||
folderitem = form->GetBrowser()->GetNextChild(form->GetBrowser()->GetRootItem(), foldercookie);
|
||||
}
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
bool disconnectServerFactoryAll::CheckEnable(pgObject* obj)
|
||||
{
|
||||
if (obj && obj->IsCreatedBy(serverFactory))
|
||||
return ((pgServer*)obj)->GetConnected();
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
|
||||
reloadconfServiceFactory::reloadconfServiceFactory(menuFactoryList *list, wxMenu *mnu, ctlMenuToolbar *toolbar) : contextActionFactory(list)
|
||||
{
|
||||
mnu->Append(id, _("Reload configuration"), _("Reload configuration"));
|
||||
|
|
|
|||
470
utils/log/MyDataViewCtrl.cpp
Normal file
470
utils/log/MyDataViewCtrl.cpp
Normal file
|
|
@ -0,0 +1,470 @@
|
|||
#include "pgAdmin3.h"
|
||||
|
||||
#include "log/MyDataViewCtrl.h"
|
||||
#include "log/StorageModel.h"
|
||||
#include "wx/headerctrl.h"
|
||||
#include "wx/itemattr.h"
|
||||
#include "wx/dataview.h"
|
||||
//#include <map>
|
||||
#include <set>
|
||||
|
||||
|
||||
BEGIN_EVENT_TABLE(MyDataViewCtrl, wxDataViewCtrl)
|
||||
EVT_MOTION(MyDataViewCtrl::OnMouseMove)
|
||||
|
||||
END_EVENT_TABLE()
|
||||
|
||||
#ifdef MYTEST
|
||||
#include <wx/textfile.h>
|
||||
void MyDataViewCtrl::OnTimer(wxTimerEvent& event) {
|
||||
// wxLogMessage("OnTimer called.");
|
||||
if (linenumber == -1) {
|
||||
wxTextFile tfile;
|
||||
wxString str;
|
||||
tfile.Open("logAdd.csv");
|
||||
|
||||
// read the first line
|
||||
str = tfile.GetFirstLine() + "\n";
|
||||
|
||||
// read all lines one by one
|
||||
// until the end of the file
|
||||
while (!tfile.Eof())
|
||||
{
|
||||
str += tfile.GetNextLine() + "\n";
|
||||
}
|
||||
tfile.Close();
|
||||
CSVLineTokenizer tk(str);
|
||||
wxString line;
|
||||
while (tk.HasMoreLines())
|
||||
{
|
||||
line.Clear();
|
||||
|
||||
bool partial;
|
||||
line = tk.GetNextLine(partial);
|
||||
if (partial)
|
||||
{
|
||||
break;
|
||||
}
|
||||
//Prepend(line);
|
||||
logadd.Add(line);
|
||||
|
||||
}
|
||||
linenumber = 0;
|
||||
}
|
||||
if (logadd.GetCount() > linenumber) {
|
||||
StorageModel* m = dynamic_cast<StorageModel*>(GetModel());
|
||||
//m->Prepend(logadd[linenumber++]);
|
||||
AddRow(logadd[linenumber++]);
|
||||
wxString l = wxString::Format("rows %d", m->GetCount());
|
||||
st->SetLabelText(l);
|
||||
if (m->getGroupFilter()) Refresh();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
void MyDataViewCtrl::setSettingString(wxString setstr) {
|
||||
wxString s;
|
||||
wxStringTokenizer tokenizer(setstr, ";");
|
||||
|
||||
for (int i = 0; i < GetColumnCount(); i++) {
|
||||
if (!tokenizer.HasMoreTokens()) break;
|
||||
wxString token = tokenizer.GetNextToken();
|
||||
wxDataViewColumn* vc = GetColumn(i);
|
||||
int w;
|
||||
w = wxAtoi(token);
|
||||
vc->SetWidth(w);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
wxString MyDataViewCtrl::getSettingString() {
|
||||
wxString s;
|
||||
for (int i = 0; i < GetColumnCount(); i++) {
|
||||
wxDataViewColumn* vc = GetColumn(i);
|
||||
int width = vc->GetWidth();
|
||||
if (!s.IsEmpty()) s = s + ";";
|
||||
s = s + wxString::Format("%d", width);
|
||||
}
|
||||
//s = s + wxString::Format(";%d", modeGroup);
|
||||
return s;
|
||||
}
|
||||
void MyDataViewCtrl::setGroupMode(bool mode) {
|
||||
StorageModel* m = dynamic_cast<StorageModel*>(GetModel());
|
||||
m->setGroupFilter(mode);
|
||||
wxItemAttr attr;
|
||||
if (m->getGroupFilter())
|
||||
{
|
||||
//attr.SetTextColour(*wxRED);
|
||||
//attr.GetFont().Underlined();
|
||||
attr.SetFont(attr.GetFont().Underlined());
|
||||
//attr.GetFont().
|
||||
//wxFontStyle s=attr.GetFont().GetStyle();
|
||||
//attr.SetFont(attr.GetFont().Strikethrough());
|
||||
}
|
||||
//else: leave it as default to disable custom header attributes
|
||||
wxString l = wxString::Format("rows %d", m->GetRowCount());
|
||||
st->SetLabelText(l);
|
||||
|
||||
if (!SetHeaderAttr(attr))
|
||||
wxLogMessage("Sorry, header attributes not supported on this platform");
|
||||
|
||||
}
|
||||
void MyDataViewCtrl::ViewGroup(bool view) {
|
||||
StorageModel* m = dynamic_cast<StorageModel*>(GetModel());
|
||||
Storage* sta = m->getStorage();
|
||||
if (view) {
|
||||
selectRowGroup = GetSelection();
|
||||
if (!selectRowGroup.IsOk()) return;
|
||||
int rowselectGroup = m->GetRow(selectRowGroup);
|
||||
sta->setDetailGroupRow(rowselectGroup);
|
||||
|
||||
}
|
||||
else sta->setDetailGroupRow(-1);
|
||||
m->ApplyFilter();
|
||||
if (!view) {
|
||||
SetCurrentItem(selectRowGroup);
|
||||
EnsureVisible(selectRowGroup);
|
||||
}
|
||||
wxString l = wxString::Format("rows %d", m->GetRowCount());
|
||||
st->SetLabelText(l);
|
||||
|
||||
|
||||
}
|
||||
void MyDataViewCtrl::AddRow(wxString csvtext) {
|
||||
StorageModel* m = dynamic_cast<StorageModel*>(GetModel());
|
||||
wxDataViewItem select;
|
||||
if (HasSelection()) select = GetSelection();
|
||||
|
||||
|
||||
if (m->Prepend(csvtext)) {
|
||||
if (!select.IsOk()) return;
|
||||
int rowselect = m->GetRow(select);
|
||||
// add visible row
|
||||
int rowlast = m->GetRowCount() - 1;
|
||||
if ((rowlast - 1) == rowselect) {
|
||||
//m->GetItem();
|
||||
select = m->GetItem(rowlast);
|
||||
SetCurrentItem(select);
|
||||
EnsureVisible(select);
|
||||
ScrollPages(1);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
void MyDataViewCtrl::OnEVT_DATAVIEW_SELECTION_CHANGED(wxDataViewEvent& event) {
|
||||
StorageModel* m = dynamic_cast<StorageModel*>(GetModel());
|
||||
int r = m->GetRow(event.GetItem());
|
||||
if (m->getGroupFilter() && r != -1) {
|
||||
Storage* sta = m->getStorage();
|
||||
sta->ClearCount(r);
|
||||
int a=sta->GetTotalCountGroup(r);
|
||||
|
||||
wxString l = wxString::Format("Total rows in group %d", a);
|
||||
st->SetLabelText(l);
|
||||
|
||||
//EnsureVisible(event.GetItem());
|
||||
}
|
||||
|
||||
//wxLogMessage("wxEVT_DATAVIEW_SELECTION_CHANGED, First selected Item row: %d", r);
|
||||
|
||||
}
|
||||
void MyDataViewCtrl::ClearAllFilter() {
|
||||
int colt = 0;
|
||||
int col = 0;
|
||||
bool all = false;
|
||||
bool clear = false;
|
||||
wxArrayInt fCol;
|
||||
StorageModel* m = dynamic_cast<StorageModel*>(GetModel());
|
||||
for (int j = 0; j < GetColumnCount(); j++) {
|
||||
col = j;
|
||||
clear = false;
|
||||
colt = 0;
|
||||
while (colt != -1) {
|
||||
colt = m->testFilter(col, colt);
|
||||
if (colt >= 0) {
|
||||
m->DropColFilter(colt);
|
||||
clear = true;
|
||||
all = true;
|
||||
colt++;
|
||||
}
|
||||
}
|
||||
if (clear) {
|
||||
// m->ApplyFilter();
|
||||
fCol.Add(col);
|
||||
// wxDataViewColumn* vc = GetColumn(col);
|
||||
// vc->SetBitmap(wxNullBitmap);
|
||||
}
|
||||
}
|
||||
if (all) {
|
||||
m->ApplyFilter();
|
||||
for (auto i : fCol) {
|
||||
wxDataViewColumn* vc = GetColumn(i);
|
||||
vc->SetBitmap(wxNullBitmap);
|
||||
}
|
||||
}
|
||||
wxString l = wxString::Format("rows %d", m->GetRowCount());
|
||||
st->SetLabelText(l);
|
||||
}
|
||||
void MyDataViewCtrl::AddFilterIgnore() {
|
||||
int colt = 0;
|
||||
int col = 0;
|
||||
bool all = false;
|
||||
bool clear = false;
|
||||
wxArrayInt fCol;
|
||||
StorageModel* m = dynamic_cast<StorageModel*>(GetModel());
|
||||
Storage* st = m->getStorage();
|
||||
wxString text;
|
||||
for (int j = 0; j < GetColumnCount(); j++) {
|
||||
col = j;
|
||||
clear = false;
|
||||
colt = 0;
|
||||
while (colt != -1) {
|
||||
colt = m->testFilter(col, colt);
|
||||
if (colt >= 0) {
|
||||
//m->DropColFilter(colt);
|
||||
wxString expr=st->GetStringFilterExpr(colt,true);
|
||||
st->addLineFilterStr(expr);
|
||||
text = text + expr + "\r\n";
|
||||
all = true;
|
||||
colt++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (all) {
|
||||
st->addLineFilterStr("");
|
||||
wxMessageBox("Create load filter\r\n\r\n"+text, _("Warning"), wxICON_INFORMATION | wxOK);
|
||||
|
||||
}
|
||||
else {
|
||||
wxMessageBox("Filter empty.", _("Warning"), wxICON_INFORMATION | wxOK);
|
||||
}
|
||||
|
||||
}
|
||||
void MyDataViewCtrl::OnEVT_DATAVIEW_CONTEXT_MENU(wxCommandEvent& event) {
|
||||
int id = event.GetId();
|
||||
wxMenu* mi = static_cast<wxMenu*>(event.GetEventObject());
|
||||
wxString label = mi->GetLabelText(id);
|
||||
StorageModel* m = dynamic_cast<StorageModel*>(GetModel());
|
||||
|
||||
int col = (int)mi->GetClientData();
|
||||
if (id > 100) {
|
||||
int colt = 0;
|
||||
bool clear = false;
|
||||
//int pos = 0;
|
||||
bool all = (label == "Clear All");
|
||||
Storage* stor = m->getStorage();
|
||||
wxString expr;
|
||||
while (colt != -1) {
|
||||
colt = m->testFilter(col, colt);
|
||||
if (colt >= 0) {
|
||||
expr = stor->GetStringFilterExpr(colt);
|
||||
if (expr == label || all) {
|
||||
m->DropColFilter(colt);
|
||||
clear = true;
|
||||
}
|
||||
colt++;
|
||||
}
|
||||
}
|
||||
if (clear) {
|
||||
m->ApplyFilter();
|
||||
if (m->testFilter(col, 0) == -1) {
|
||||
wxDataViewColumn* vc = GetColumn(col);
|
||||
vc->SetBitmap(wxNullBitmap);
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
m->setFilter(col, label.AfterFirst(' '), 0, this);
|
||||
//wxDataViewColumn* vc=GetColumn(col);
|
||||
//vc->SetBitmap(m->bitmapflt);
|
||||
|
||||
}
|
||||
wxString l = wxString::Format("rows %d", m->GetRowCount());
|
||||
st->SetLabelText(l);
|
||||
|
||||
if (col == StorageModel::Col_User) {
|
||||
|
||||
|
||||
//m->setFilter(col, label.AfterFirst(' '));
|
||||
// wxMessageBox("You have selected Item 1", "Your selection", wxOK | wxICON_INFORMATION);
|
||||
}
|
||||
if (event.GetId() == 2) {
|
||||
// wxMessageBox("You have selected Item 2", "Your selection", wxOK | wxICON_INFORMATION);
|
||||
}
|
||||
|
||||
}
|
||||
// ïðàâàÿ êíîïêà íà ÿ÷åéêå
|
||||
void MyDataViewCtrl::OnContextMenu(wxDataViewEvent& event) {
|
||||
//wxString title = m_music_model->GetTitle(event.GetItem());
|
||||
//wxLogMessage("wxEVT_DATAVIEW_ITEM_CONTEXT_MENU, Item: %s", title);
|
||||
StorageModel* m = dynamic_cast<StorageModel*>(GetModel());
|
||||
int row = m->GetRow(event.GetItem());
|
||||
int ncol;
|
||||
wxVariant vr;
|
||||
if (row >= 0)
|
||||
{
|
||||
|
||||
//int ncol = GetColumn(event.GetColumn())->GetModelColumn();
|
||||
ncol = event.GetColumn();
|
||||
m->GetValueByRow(vr, row, ncol);
|
||||
if (ncol == 0) {
|
||||
wxDataViewIconText ic;
|
||||
ic << vr;
|
||||
wxString str = ic.GetText();
|
||||
vr = str;
|
||||
}
|
||||
}
|
||||
int pos = GetColumnPosition(event.GetDataViewColumn());
|
||||
|
||||
wxString str = wxString::Format("col: %d row: %d val: %s", pos, row, vr.GetString());
|
||||
int flags = 0;
|
||||
if (modctrl) flags = FL_REVERSE;
|
||||
m->setFilter(ncol, vr.GetString(), flags, this);
|
||||
//wxDataViewColumn* vc = GetColumn(event.GetColumn());
|
||||
//vc->SetBitmap(m->bitmapflt);
|
||||
|
||||
//wxMessageBox(str, "Your selection", wxOK | wxICON_INFORMATION);
|
||||
|
||||
|
||||
}
|
||||
auto cmp = [](std::pair<std::string, int> const& a, std::pair<std::string, int> const& b)
|
||||
{
|
||||
return a.second != b.second ? a.second < b.second : a.first < b.first;
|
||||
};
|
||||
void MyDataViewCtrl::OnEVT_DATAVIEW_COLUMN_HEADER_CLICK(wxDataViewEvent& event) {
|
||||
StorageModel* m = dynamic_cast<StorageModel*>(GetModel());
|
||||
int col = event.GetColumn();
|
||||
if (event.GetColumn() == StorageModel::Col_User)
|
||||
{
|
||||
}
|
||||
const int rowChanged = m->GetRow(event.GetItem());
|
||||
wxMenu menu;
|
||||
//menu.SetTitle(event.GetDataViewColumn()->GetTitle());
|
||||
int i = 1;
|
||||
int colt = m->testFilter(col, 0);
|
||||
if (colt >= 0) {
|
||||
wxMenu* menus = new wxMenu();
|
||||
menus->SetClientData((void*)col);
|
||||
Storage* stor = m->getStorage();
|
||||
menus->Append(101 + i++, "Clear All");
|
||||
wxString expr;
|
||||
while (colt != -1) {
|
||||
expr = stor->GetStringFilterExpr(colt);
|
||||
menus->Append(101 + i++, expr);
|
||||
colt = m->testFilter(col, colt + 1);
|
||||
}
|
||||
menu.AppendSubMenu(menus, "Clear filters");
|
||||
}
|
||||
std::set<std::pair<int, std::string>> items;
|
||||
std::pair<int, std::string> v;
|
||||
int cc = 0;
|
||||
MyHashCount::iterator it;
|
||||
for (it = m->freqValues[col].begin(); it != m->freqValues[col].end(); ++it)
|
||||
{
|
||||
v = std::make_pair(it->second, it->first.ToStdString());
|
||||
items.emplace(v);
|
||||
//ma.emplace(it->first.ToStdString(), it->second);
|
||||
cc++;
|
||||
}
|
||||
//std::sort(items.begin(), items.end(),cmp);
|
||||
cc = cc - 20;
|
||||
int cc0 = 0;
|
||||
for (auto const& vk : items) {
|
||||
cc0++;
|
||||
if (cc0 < cc) continue;
|
||||
wxString key = wxString(vk.second);
|
||||
int value = vk.first;
|
||||
wxString str = wxString::Format("%d %s", value, key);
|
||||
menu.Append(i++, str);
|
||||
|
||||
}
|
||||
|
||||
//for (it = m->freqValues[col].begin(); it != m->freqValues[col].end(); ++it)
|
||||
//{
|
||||
// wxString key = it->first;
|
||||
// int value = it->second;
|
||||
// wxString str = wxString::Format("%d %s",value,key);
|
||||
// menu.Append(i++, str);
|
||||
//}
|
||||
|
||||
menu.SetClientData((void*)col);
|
||||
this->PopupMenu(&menu);
|
||||
event.Skip(false);
|
||||
return;
|
||||
|
||||
event.Skip(true);
|
||||
}
|
||||
void MyDataViewCtrl::OnKEY_DOWN(wxKeyEvent& event) {
|
||||
if ((event.GetModifiers() & wxMOD_CONTROL) == wxMOD_CONTROL) {
|
||||
modctrl = true;
|
||||
}
|
||||
else modctrl = false;
|
||||
event.Skip(true);
|
||||
|
||||
}
|
||||
void MyDataViewCtrl::OnMouseMove(wxMouseEvent& event) {
|
||||
|
||||
//event.Skip(true);
|
||||
if (event.Dragging())
|
||||
return;
|
||||
|
||||
wxClientDC dc(GetMainWindow());
|
||||
PrepareDC(dc);
|
||||
|
||||
//wxPoint logPos(event.GetLogicalPosition(dc));
|
||||
//wxPoint mc= GetMainWindow()->ScreenToClient(event.GetPosition());
|
||||
wxPoint mc = event.GetPosition();
|
||||
wxString position;
|
||||
//position = wxString::Format("x=%d y=%d", logPos.x, logPos.y);
|
||||
//wxLogMessage("Mouse pos %s", position);
|
||||
wxHeaderCtrl* const header = GenericGetHeader();
|
||||
int dy = 0;
|
||||
wxSize sz;
|
||||
if (header) {
|
||||
sz = header->GetSize();
|
||||
//header->Refresh();
|
||||
dy = sz.GetHeight();
|
||||
}
|
||||
mc.y += dy;
|
||||
wxDataViewItem item;
|
||||
wxDataViewColumn* column;
|
||||
|
||||
HitTest(mc, item, column);
|
||||
if (item != NULL && column != NULL)
|
||||
{
|
||||
StorageModel* m;
|
||||
m = dynamic_cast<StorageModel*>(GetModel());
|
||||
|
||||
int row = m->GetRow(item);
|
||||
|
||||
if (row >= 0)
|
||||
{
|
||||
wxVariant vr;
|
||||
int ncol = column->GetModelColumn();
|
||||
if ((lastcol != ncol) || (lastrow != row)) {
|
||||
m->GetValueByRow(vr, row, ncol);
|
||||
wxSize szext = dc.GetTextExtent(vr.GetString());
|
||||
int w = column->GetWidth();
|
||||
if (szext.GetWidth() > w)
|
||||
{
|
||||
GetMainWindow()->SetToolTip(vr.GetString());
|
||||
}
|
||||
else
|
||||
GetMainWindow()->UnsetToolTip();
|
||||
lastrow = row;
|
||||
lastcol = ncol;
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
GetMainWindow()->UnsetToolTip();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
GetMainWindow()->UnsetToolTip();
|
||||
}
|
||||
}
|
||||
583
utils/log/Storage.cpp
Normal file
583
utils/log/Storage.cpp
Normal file
|
|
@ -0,0 +1,583 @@
|
|||
#include "pgAdmin3.h"
|
||||
#include "log/Storage.h"
|
||||
#include "utils/utffile.h"
|
||||
#include <wx/filename.h>
|
||||
#include <wx/stdpaths.h>
|
||||
|
||||
int Storage::getCountStore() {
|
||||
return storage.size();
|
||||
}
|
||||
int Storage::getCountFilter() {
|
||||
int cnt = frows.size();
|
||||
if (cnt == 0 && !IsFilter()) cnt = getCountStore();
|
||||
return cnt;
|
||||
}
|
||||
LineFilter Storage::getLineFilter(wxString strflt) {
|
||||
LineFilter lf;
|
||||
lf.col = -1;
|
||||
if (strflt.IsEmpty()) {
|
||||
return lf;
|
||||
}
|
||||
int col = wxAtoi(strflt.BeforeFirst(':'));
|
||||
lf.col = col;
|
||||
wxString l = strflt.AfterFirst(':');
|
||||
wxString val = l.AfterFirst(' ');
|
||||
int flags = 0;
|
||||
int i = 0;
|
||||
if (l[i] == '!') { flags = FL_REVERSE; i++; }
|
||||
if (l[i] == '~') flags = flags | FL_CONTAINS;
|
||||
lf.flags = flags;
|
||||
lf.val = val;
|
||||
return lf;
|
||||
}
|
||||
wxString Storage::_strwhere(int flags) {
|
||||
wxString expr = "= ";
|
||||
if ((flags & FL_CONTAINS) == FL_CONTAINS) expr = "~ ";
|
||||
if ((flags & FL_REVERSE) == FL_REVERSE) expr = "!" + expr;
|
||||
return expr;
|
||||
}
|
||||
wxString Storage::LineFilterToStr(LineFilter& lf) {
|
||||
if (lf.col == -1) {
|
||||
return "";
|
||||
}
|
||||
wxString expr = _strwhere(lf.flags)+lf.val;
|
||||
expr = wxString::Format("%d:%s", lf.col, expr);
|
||||
return expr;
|
||||
}
|
||||
|
||||
void Storage::addLineFilterStr(wxString strflt) {
|
||||
LineFilter lf = getLineFilter(strflt);
|
||||
filterload.push_back(lf);
|
||||
}
|
||||
Storage::Storage() {
|
||||
|
||||
bgErr[MyConst::iconIndex::log] = wxNullColour;
|
||||
bgErr[MyConst::iconIndex::war] = wxNullColour;
|
||||
bgErr[MyConst::iconIndex::user] = wxColor(250, 196, 186);
|
||||
bgErr[MyConst::iconIndex::error] = wxColor(220, 150, 150);
|
||||
bgErr[MyConst::iconIndex::fatal] = wxColor(209, 100, 100);
|
||||
bgErr[MyConst::iconIndex::panic] = wxColor(246, 10, 10);
|
||||
|
||||
// load filter
|
||||
wxString tempDir = wxStandardPaths::Get().GetUserConfigDir() + wxT("\\postgresql\\");
|
||||
|
||||
wxString f = tempDir + "filter_load.txt";
|
||||
if (wxFileExists(f)) {
|
||||
wxString str;
|
||||
wxUtfFile file(f, wxFile::read, wxFONTENCODING_UTF8);
|
||||
if (file.IsOpened()) {
|
||||
file.Read(str);
|
||||
file.Close();
|
||||
wxStringTokenizer tk(str, "\n", wxTOKEN_RET_EMPTY_ALL);
|
||||
|
||||
bool end = false;
|
||||
LineFilter lf;
|
||||
while (tk.HasMoreTokens())
|
||||
{
|
||||
wxString l = tk.GetNextToken();
|
||||
if (end && l.IsEmpty()) continue;
|
||||
addLineFilterStr(l);
|
||||
end = l.IsEmpty();
|
||||
}
|
||||
if (!end) addLineFilterStr("");
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
void Storage::saveFilters() {
|
||||
if (filterload.size() == 0) return;
|
||||
wxString tempDir = wxStandardPaths::Get().GetUserConfigDir() + wxT("\\postgresql\\");
|
||||
wxString f = tempDir + "filter_load.txt";
|
||||
wxUtfFile file(f, wxFile::write, wxFONTENCODING_UTF8);
|
||||
if (file.IsOpened())
|
||||
{
|
||||
wxString text;
|
||||
for (auto lf:filterload) {
|
||||
wxString s = LineFilterToStr(lf);
|
||||
|
||||
if (!s.IsEmpty()) text.Append(s);
|
||||
text.Append("\n");
|
||||
}
|
||||
if ((file.Write(text) == 0))
|
||||
wxMessageBox(_("Query text incomplete.\nQuery contained characters that could not be converted to the local charset.\nPlease correct the data or try using UTF8 instead."));
|
||||
file.Close();
|
||||
}
|
||||
|
||||
}
|
||||
void Storage::getLineToCache(int row, bool filter) {
|
||||
int r = row;
|
||||
if (filter && IsFilter()) row = frows[row];
|
||||
m_cacheLine = storage.at(row);
|
||||
m_cacheIndex = r;
|
||||
}
|
||||
int Storage::GetSeverityIndex(int rowvisual) {
|
||||
if (rowvisual != m_cacheIndex) getLineToCache(rowvisual, true);
|
||||
return m_cacheLine.icon;
|
||||
}
|
||||
wxColor& Storage::GetBgColorLine(int rowvisual) {
|
||||
if (rowvisual != m_cacheIndex) getLineToCache(rowvisual, true);
|
||||
int i = m_cacheLine.icon;
|
||||
return bgErr[i];
|
||||
}
|
||||
void Storage::DropColFilter(int index) {
|
||||
fCol.RemoveAt(index);
|
||||
fVal.RemoveAt(index);
|
||||
fFlags.RemoveAt(index);
|
||||
// îñòàâøèåñÿ ôèëüòðû áóäóò ïðèìåíåíû ïî âñåìó storage
|
||||
frows.clear();
|
||||
}
|
||||
wxString Storage::GetStringFilterExpr(int positionArrayFilter,bool addNumCol) {
|
||||
wxString expr;
|
||||
expr = _strwhere(fFlags[positionArrayFilter]);
|
||||
expr = expr + fVal[positionArrayFilter];
|
||||
if (addNumCol) {
|
||||
expr = wxString::Format("%d:%s", fCol[positionArrayFilter], expr);
|
||||
return expr;
|
||||
}
|
||||
if (expr.Len() > 50) expr = expr.substr(0, 50);
|
||||
return expr;
|
||||
}
|
||||
int Storage::testFilter(MyConst::colField col, int position) {
|
||||
int k = 0;
|
||||
for (auto i : fCol) {
|
||||
if (i == col && (position <= k)) return k;
|
||||
k++;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
bool Storage::CompareFilterLine(int row, bool filter) {
|
||||
int c = 0;
|
||||
MyConst::colField f;
|
||||
wxString valFlt;
|
||||
wxString valField;
|
||||
bool reverse = false;
|
||||
bool rez = false;
|
||||
int flags = 0;
|
||||
for (auto i : fCol) {
|
||||
flags = fFlags[c];
|
||||
reverse = (flags & FL_REVERSE) == FL_REVERSE;
|
||||
valFlt = fVal[c++];
|
||||
f = (MyConst::colField) i;
|
||||
valField = GetFieldStorage(row, f, filter);
|
||||
if ((flags & FL_CONTAINS) == 0) rez = valField != valFlt;
|
||||
else
|
||||
rez = !valField.Contains(valFlt);
|
||||
if (reverse) rez = !rez;
|
||||
if (rez) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
// Ïîêàçûâàåì ñòðîêó òîëüêî åñëè îíà ñòàëà íîâîé ãðóïïîé
|
||||
if (IsGroupFilter())
|
||||
{
|
||||
// åñëè ïðîâåðÿåì íå äîáàâëåííóþ ñòðîêó òî íèêàèõ ïðîâåðîê
|
||||
if (filter) return true;
|
||||
|
||||
// â äåòàëüíîì ðåæèìå íîâûå ãðóïïû íå ïîêàçûâàåì
|
||||
if (faddgroup && detailGroup != -1) return false;
|
||||
// Åñëè ýòî íå äåòàëüíàÿ èíôîðìàöèÿ òî òîæå íå ïîêàçûâàåì
|
||||
if (detailGroup != -1 && detailGroup == prevRow && !filter) {
|
||||
// íîâàÿ ñòðîêà ïîïàäàåò â äåòàëüíóþ ãðóïïó
|
||||
// ñäâèíåì âåðøèíó íà íîâóþ ñòðîêó
|
||||
detailGroup = row;
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!faddgroup) return false;
|
||||
|
||||
}
|
||||
return true;
|
||||
}
|
||||
//íîìåð ñòðîêà èç èç îòôèëüòðîâàííûõ
|
||||
void Storage::setDetailGroupRow(int rowGroup) {
|
||||
if (IsGroupFilter()) {
|
||||
//
|
||||
if (rowGroup != -1) detailGroup = frows[rowGroup]; else detailGroup = -1;
|
||||
}
|
||||
else detailGroup = -1;
|
||||
}
|
||||
// äëÿ óêàçàííîé ñòðîêè ïðîâåðÿåì èç strage (áåç ôèëüòðà)
|
||||
bool Storage::ApplyFilter(int row) {
|
||||
//if (!IsFilter()) return true;
|
||||
if (row != -1) {
|
||||
// verify row
|
||||
if (!IsFilter()) return true;
|
||||
// filter enable
|
||||
if (CompareFilterLine(row, false)) {
|
||||
frows.push_back(row);
|
||||
faddgroup = false;
|
||||
return true;
|
||||
}
|
||||
if (detailGroup != -1) return false;
|
||||
if (IsGroupFilter()) {
|
||||
// ïîäìåíèòü â ôèëüòðå ñòðîê íà íîâóþ
|
||||
for (int i = 0; i < frows.size(); i++) {
|
||||
// òóò ïîòåíöèàëüíàÿ ïðîáëåìà ïðîèçâîäèòåëüíîñòè
|
||||
if (frows[i] != prevRow) continue;
|
||||
frows[i] = row;
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
// no visible
|
||||
return false;
|
||||
}
|
||||
if (!IsFilter()) { frows.clear(); return true; }
|
||||
|
||||
bool f = false;
|
||||
faddgroup = true;
|
||||
if (IsGroupFilter()) {
|
||||
// ïðè âêëþ÷åííîì GroupFilter ñìîòðèì òîëüêî ñòðîêè hashKeyToRow
|
||||
frows.clear();
|
||||
MyHashToRow::iterator it;
|
||||
for (it = hashKeyToRow.begin(); it != hashKeyToRow.end(); ++it)
|
||||
{
|
||||
int keyhash = it->first, lastrow = it->second;
|
||||
// do something useful with key and value
|
||||
if (detailGroup != -1) {
|
||||
if (detailGroup == lastrow)
|
||||
{
|
||||
int l = lastrow;
|
||||
while (l != -1) {
|
||||
frows.push_back(l);
|
||||
if (l != m_cacheIndex) getLineToCache(l, false);
|
||||
l = m_cacheLine.prevRowGroup;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
frows.push_back(lastrow);
|
||||
//frows.push_back(keyhash);
|
||||
}
|
||||
sort(frows.begin(), frows.end());
|
||||
|
||||
}
|
||||
if (frows.size() > 0) {
|
||||
// íàáîð ôèëüòðà èçìåíèëñÿ ïåðåïðîâåðèì îòôèëüòðîâàííûå ñòðîêè åù¸ ðàç
|
||||
std::deque<int> tmp;
|
||||
for (int i = 0; i < frows.size(); i++) {
|
||||
if (CompareFilterLine(i, true)) {
|
||||
|
||||
tmp.push_back(frows[i]);
|
||||
f = true;
|
||||
};
|
||||
|
||||
}
|
||||
if (f) frows = tmp;
|
||||
else frows.clear();
|
||||
}
|
||||
else
|
||||
{
|
||||
// íàáîð ôèëüòðîûâííûõ ñòðîê ïóñòîé ïðîâåðèì âñå ñòðîêè íà ñîîòâåòñòâèå ôèëüòðó
|
||||
for (int i = 0; i < storage.size(); i++) {
|
||||
if (CompareFilterLine(i, false)) {
|
||||
frows.push_back(i);
|
||||
f = true;
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
faddgroup = false;
|
||||
return f;
|
||||
}
|
||||
|
||||
int Storage::SetFilter(int col, wxString& val, int flags) {
|
||||
fCol.Add(col);
|
||||
fVal.Add(val);
|
||||
fFlags.Add(flags);
|
||||
ApplyFilter();
|
||||
return frows.size();
|
||||
}
|
||||
wxString Storage::GetField(int row, MyConst::colField col) {
|
||||
return GetFieldStorage(row, col, IsFilter());
|
||||
}
|
||||
wxString Storage::get_field(Line& l, MyConst::colField col) {
|
||||
wxString val;
|
||||
switch (col)
|
||||
{
|
||||
case MyConst::colField::logtime:
|
||||
return l.text.substr(l.logtime.s, l.logtime.l);
|
||||
break;
|
||||
case MyConst::colField::loguser:
|
||||
return l.text.substr(l.loguser.s, l.loguser.l);
|
||||
break;
|
||||
case MyConst::colField::logdb:
|
||||
return l.text.substr(l.logdb.s, l.logdb.l);
|
||||
break;
|
||||
case MyConst::colField::logpid:
|
||||
return l.text.substr(l.logpid.s, l.logpid.l);
|
||||
break;
|
||||
case MyConst::colField::loghost:
|
||||
return l.text.substr(l.loghost.s, l.loghost.l);
|
||||
break;
|
||||
case MyConst::colField::logtag:
|
||||
return l.text.substr(l.logtag.s, l.logtag.l);
|
||||
break;
|
||||
case MyConst::colField::logSessiontime:
|
||||
return l.text.substr(l.logSessiontime.s, l.logSessiontime.l);
|
||||
break;
|
||||
case MyConst::colField::logSeverity:
|
||||
return l.text.substr(l.logSeverity.s, l.logSeverity.l);
|
||||
break;
|
||||
case MyConst::colField::logSqlstate:
|
||||
return l.text.substr(l.logSqlstate.s, l.logSqlstate.l);
|
||||
break;
|
||||
case MyConst::colField::logMessage:
|
||||
return l.text.substr(l.logMessage.s, l.logMessage.l);
|
||||
break;
|
||||
case MyConst::colField::logDetail:
|
||||
return l.text.substr(l.logDetail.s, l.logDetail.l);
|
||||
break;
|
||||
case MyConst::colField::logHint:
|
||||
return l.text.substr(l.logHint.s, l.logHint.l);
|
||||
break;
|
||||
case MyConst::colField::logappname:
|
||||
val = l.text.substr(l.logappname.s, l.logappname.l);
|
||||
if (val.IsEmpty()) val = l.text.substr(l.logbtype.s, l.logbtype.l);
|
||||
return val;
|
||||
break;
|
||||
case MyConst::colField::logbtype:
|
||||
return l.text.substr(l.logbtype.s, l.logbtype.l);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return "bad";
|
||||
|
||||
}
|
||||
wxString Storage::GetFieldStorage(int row, MyConst::colField col, bool filter) {
|
||||
if (row != m_cacheIndex) getLineToCache(row, filter);
|
||||
return get_field(m_cacheLine, col);
|
||||
}
|
||||
Line Storage::getLineParse(const wxString& str, bool csv) {
|
||||
Line st;
|
||||
if (csv) {
|
||||
CSVTokenizer tk(str);
|
||||
// Get the fields from the CSV log.
|
||||
|
||||
wxString t;
|
||||
wxString logTime = tk.GetNextToken();
|
||||
//fields.Add(logTime);
|
||||
st.logtime = { 0,static_cast<unsigned short int>(logTime.Len()) };
|
||||
wxString logUser = tk.GetNextToken();
|
||||
t = logTime;
|
||||
st.loguser = { static_cast<unsigned short int>(t.Len()),static_cast<unsigned short int>(logUser.Len()) };
|
||||
t += logUser;
|
||||
wxString logDatabase = tk.GetNextToken();
|
||||
if (logDatabase.IsEmpty()) logDatabase = GetHost();
|
||||
st.logdb = { static_cast<unsigned short int>(t.Len()),static_cast<unsigned short int>(logDatabase.Len()) };
|
||||
|
||||
t += logDatabase;
|
||||
wxString logPid = tk.GetNextToken();
|
||||
st.logpid = { static_cast<unsigned short int>(t.Len()),static_cast<unsigned short int>(logPid.Len()) };
|
||||
t += logPid;
|
||||
wxString logSession;
|
||||
wxString logCmdcount;
|
||||
wxString logSegment;
|
||||
wxString logHost = tk.GetNextToken(); // Postgres puts port with Hostname
|
||||
// delete port
|
||||
logHost = logHost.BeforeFirst(':');
|
||||
st.loghost = { static_cast<unsigned short int>(t.Len()),static_cast<unsigned short int>(logHost.Len()) };
|
||||
t += logHost;
|
||||
|
||||
logSession = tk.GetNextToken();
|
||||
|
||||
wxString logLineNumber = tk.GetNextToken();
|
||||
wxString logTag = tk.GetNextToken();
|
||||
st.logtag = { static_cast<unsigned short int>(t.Len()),static_cast<unsigned short int>(logTag.Len()) };
|
||||
t += logTag;
|
||||
wxString logSessiontime = tk.GetNextToken();
|
||||
st.loghost = { static_cast<unsigned short int>(t.Len()),static_cast<unsigned short int>(logHost.Len()) };
|
||||
t += logHost;
|
||||
|
||||
wxString logVXid = tk.GetNextToken();
|
||||
wxString logTransaction = tk.GetNextToken();
|
||||
wxString logSeverity = tk.GetNextToken();
|
||||
//fields.Add(logSeverity);
|
||||
st.logSeverity = { static_cast<unsigned short int>(t.Len()),static_cast<unsigned short int>(logSeverity.Len()) };
|
||||
t += logSeverity;
|
||||
|
||||
wxString logState = tk.GetNextToken();
|
||||
//fields.Add(logState);
|
||||
st.logSqlstate = { static_cast<unsigned short int>(t.Len()),static_cast<unsigned short int>(logState.Len()) };
|
||||
t += logState;
|
||||
|
||||
wxString logMessage = tk.GetNextToken();
|
||||
//fields.Add(logMessage);
|
||||
wxString logDetail = tk.GetNextToken();
|
||||
//fields.Add(logDetail);
|
||||
st.logDetail = { static_cast<unsigned short int>(t.Len()),static_cast<unsigned short int>(logDetail.Len()) };
|
||||
t += logDetail;
|
||||
wxString logHint = tk.GetNextToken();
|
||||
//fields.Add(logHint);
|
||||
wxString logQuery = tk.GetNextToken();
|
||||
wxString logQuerypos = tk.GetNextToken();
|
||||
wxString logContext = tk.GetNextToken();
|
||||
wxString logDebug = tk.GetNextToken();
|
||||
wxString logCursorpos = tk.GetNextToken();
|
||||
if (!logDebug.IsEmpty() && logHint.IsEmpty())
|
||||
logHint = logDebug;
|
||||
st.logHint = { static_cast<unsigned short int>(t.Len()),static_cast<unsigned short int>(logHint.Len()) };
|
||||
t += logHint;
|
||||
st.logMessage = { static_cast<unsigned short int>(t.Len()),static_cast<unsigned short int>(logMessage.Len()) };
|
||||
t += logMessage;
|
||||
|
||||
//location
|
||||
logCursorpos = tk.GetNextToken();
|
||||
|
||||
wxString logApp = tk.GetNextToken();
|
||||
//fields.Add(logApp);
|
||||
st.logappname = { static_cast<unsigned short int>(t.Len()),static_cast<unsigned short int>(logApp.Len()) };
|
||||
t += logApp;
|
||||
wxString logType = tk.GetNextToken();
|
||||
st.logbtype = { static_cast<unsigned short int>(t.Len()),static_cast<unsigned short int>(logType.Len()) };
|
||||
t += logType;
|
||||
//fields.Add(logType);
|
||||
//st.logType = { t.Len(),logType.Len() };
|
||||
//t += logType;
|
||||
st.type = MyConst::ltype::SIMPLE_TEXT;
|
||||
int i = MyConst::iconIndex::log;
|
||||
if (logSeverity == "WARNING") i = MyConst::iconIndex::war;
|
||||
if (logSeverity == "ERROR") i = MyConst::iconIndex::error;
|
||||
if (logSeverity == "FATAL") i = MyConst::iconIndex::fatal;
|
||||
if (logSeverity == "PANIC") i = MyConst::iconIndex::panic;
|
||||
st.icon = i;
|
||||
st.visible = 1;
|
||||
st.text = t;
|
||||
|
||||
}
|
||||
return st;
|
||||
}
|
||||
// ïîëó÷åíèå îáîáùåííîé êëþ÷åâîé ñòðîêè
|
||||
wxString Storage::getStrGroup(wxString source) {
|
||||
int i = 0;
|
||||
int l = source.Length();
|
||||
wxString n;
|
||||
bool quote = false;
|
||||
while (i < l) {
|
||||
char c = source[i++];
|
||||
if (c >= '0' && c <= '9' && !quote) continue;
|
||||
if (c == '"') {
|
||||
|
||||
if ((i < l) && source[i] == c) {
|
||||
n.Append(c, 2);
|
||||
//n.Append(c);
|
||||
i++;
|
||||
continue;
|
||||
}
|
||||
else
|
||||
quote = !quote;
|
||||
}
|
||||
n.Append(c);
|
||||
}
|
||||
return n;
|
||||
}
|
||||
int Storage::GetTotalCountGroup(int rowfilter) {
|
||||
if (rowfilter != m_cacheIndex) getLineToCache(rowfilter, true);
|
||||
MyHashToRow::const_iterator it = hashKeyTotal.find(m_cacheLine.hash);
|
||||
int a = 0;
|
||||
if (it != hashKeyTotal.end())
|
||||
{
|
||||
a = hashKeyTotal[m_cacheLine.hash];
|
||||
}
|
||||
if (a==0) {
|
||||
int h = m_cacheLine.hash;
|
||||
int lastrow=hashKeyToRow[h];
|
||||
a = 0;
|
||||
m_cacheIndex = -1;
|
||||
while (lastrow!=-1) {
|
||||
getLineToCache(lastrow, false);
|
||||
lastrow = m_cacheLine.prevRowGroup;
|
||||
a++;
|
||||
}
|
||||
hashKeyTotal[h]=a;
|
||||
m_cacheIndex = -1;
|
||||
}
|
||||
return a;
|
||||
}
|
||||
void Storage::ClearCount(int rowfilter) {
|
||||
if (rowfilter != m_cacheIndex) getLineToCache(rowfilter, true);
|
||||
MyHashToRow::const_iterator it = hashKeyTotal.find(m_cacheLine.hash);
|
||||
int cnt = hashKeyToCount[m_cacheLine.hash];
|
||||
int a = 0;
|
||||
if (it != hashKeyTotal.end())
|
||||
{
|
||||
a = hashKeyTotal[m_cacheLine.hash];
|
||||
}
|
||||
hashKeyTotal[m_cacheLine.hash] = a + cnt;
|
||||
hashKeyToCount[m_cacheLine.hash] = 0;
|
||||
}
|
||||
int Storage::getCountGroup(int row) {
|
||||
|
||||
wxString valField = GetFieldStorage(row, MyConst::colField::logtime, false);
|
||||
int h = m_cacheLine.hash;
|
||||
int c = hashKeyToCount[h];
|
||||
return c;
|
||||
}
|
||||
bool Storage::checkFilter(Line& l) {
|
||||
|
||||
if (filterload.size() > 0) {
|
||||
wxString sf;
|
||||
bool rez=true;
|
||||
int last = filterload.size() - 1;
|
||||
int i = 0;
|
||||
for (auto fl:filterload) {
|
||||
if (fl.col == -1) {
|
||||
if (rez || (last==i)) break;
|
||||
rez = true;
|
||||
}
|
||||
else {
|
||||
if (rez) {
|
||||
sf = get_field(l, (MyConst::colField)fl.col);
|
||||
int flags = fl.flags;
|
||||
bool reverse = (flags & FL_REVERSE) == FL_REVERSE;
|
||||
|
||||
if ((flags & FL_CONTAINS) == 0) rez = sf == fl.val;
|
||||
else
|
||||
rez = sf.Contains(fl.val);
|
||||
if (reverse) rez = !rez;
|
||||
}
|
||||
}
|
||||
i++;
|
||||
|
||||
}
|
||||
return rez;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
bool Storage::AddLineTextCSV(const wxString& strcsv) {
|
||||
Line st = getLineParse(strcsv, true);
|
||||
|
||||
if (checkFilter(st)) {
|
||||
rowsignore++;
|
||||
return false;
|
||||
}
|
||||
rowsadd++;
|
||||
wxString msg = st.text.substr(st.logMessage.s, st.logMessage.l);
|
||||
if (st.icon > MyConst::iconIndex::war) SetErrMsgFlag(true);
|
||||
|
||||
wxString gstr = getStrGroup(msg);
|
||||
int h = getHashString(gstr);
|
||||
MyHashToRow::const_iterator it = hashKeyToRow.find(h);
|
||||
prevRow = -1;
|
||||
int cnt = 1;
|
||||
faddgroup = true;
|
||||
if (it != hashKeyToRow.end())
|
||||
{
|
||||
faddgroup = false;
|
||||
prevRow = it->second;
|
||||
cnt = hashKeyToCount[h];
|
||||
cnt++;
|
||||
}
|
||||
int nextrow = storage.size();
|
||||
st.prevRowGroup = prevRow;
|
||||
st.hash = h;
|
||||
hashKeyToRow[h] = nextrow;
|
||||
hashKeyToCount[h] = cnt;
|
||||
storage.push_back(st);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
486
utils/log/StorageModel.cpp
Normal file
486
utils/log/StorageModel.cpp
Normal file
|
|
@ -0,0 +1,486 @@
|
|||
#include "pgAdmin3.h"
|
||||
|
||||
|
||||
#ifndef WX_PRECOMP
|
||||
#include "wx/wx.h"
|
||||
#endif
|
||||
|
||||
#include "wx/dataview.h"
|
||||
#include "log/Storage.h"
|
||||
#include "log/StorageModel.h"
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// resources
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
#include "log/null.xpm"
|
||||
#include "log/log_xpm.xpm"
|
||||
#include "log/war_xpm.xpm"
|
||||
#include "log/errorl_xpm.xpm"
|
||||
#include "log/fatal_xpm.xpm"
|
||||
#include "log/panic_xpm.xpm"
|
||||
#include "log/user_xpm.xpm"
|
||||
#include "log/wx_small.xpm"
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// MyCustomRendererText
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
class MyCustomRendererText : public wxDataViewCustomRenderer
|
||||
{
|
||||
public:
|
||||
StorageModel::cols col;
|
||||
Storage* st;
|
||||
int row;
|
||||
int countRows = 0;
|
||||
// This renderer can be either activatable or editable, for demonstration
|
||||
// purposes. In real programs, you should select whether the user should be
|
||||
// able to activate or edit the cell and it doesn't make sense to switch
|
||||
// between the two -- but this is just an example, so it doesn't stop us.
|
||||
explicit MyCustomRendererText(wxDataViewCellMode mode, StorageModel::cols column)
|
||||
: wxDataViewCustomRenderer("string", mode, wxALIGN_LEFT)
|
||||
{
|
||||
EnableEllipsize(wxELLIPSIZE_END);
|
||||
col = column;
|
||||
st = NULL;
|
||||
}
|
||||
|
||||
virtual bool Render(wxRect rect, wxDC* dc, int state) wxOVERRIDE
|
||||
{
|
||||
//dc->SetBrush( *wxLIGHT_GREY_BRUSH );
|
||||
dc->SetBrush(*wxYELLOW_BRUSH);
|
||||
dc->SetPen(*wxTRANSPARENT_PEN);
|
||||
rect.Deflate(2);
|
||||
wxRect orig = rect;
|
||||
|
||||
//dc->DrawRoundedRectangle( rect, 3 );
|
||||
|
||||
wxString s = m_value, t;
|
||||
wxString rest;
|
||||
wxString* pointer = &rest;
|
||||
int x = 0, y = 0;
|
||||
//dc->GetMultiLineTextExtent(m_value);
|
||||
wxArrayInt arr;
|
||||
wxSize h = dc->GetTextExtent("H");
|
||||
dc->GetPartialTextExtents(m_value, arr);
|
||||
bool ex = false;
|
||||
int i = 0;
|
||||
int startX = 0;
|
||||
|
||||
wxRect rectCol;
|
||||
|
||||
while (i < s.Len()) {
|
||||
|
||||
t = "";
|
||||
x = 0;
|
||||
bool inquote = false;
|
||||
rectCol.x = rect.x;
|
||||
rectCol.y = rect.y;
|
||||
rectCol.height = h.GetHeight();
|
||||
rectCol.width = 0;
|
||||
while (i < s.Len())
|
||||
{
|
||||
if (s[i] == '\n') {
|
||||
startX = arr[i];
|
||||
i++;
|
||||
break;
|
||||
}
|
||||
if (s[i] == '"') {
|
||||
if (inquote) {
|
||||
// çàêðûòèå êàâû÷åê
|
||||
rectCol.width = arr[i] - rectCol.x;
|
||||
rectCol.x = rectCol.x - startX + rect.x;
|
||||
dc->DrawRoundedRectangle(rectCol, 3);
|
||||
rectCol.x = arr[i];
|
||||
rectCol.width = 0;
|
||||
}
|
||||
else
|
||||
rectCol.x = arr[i];
|
||||
|
||||
inquote = !inquote;
|
||||
}
|
||||
t += s[i];
|
||||
i++;
|
||||
}
|
||||
RenderText(t,
|
||||
x, // no offset
|
||||
//wxRect(dc->GetTextExtent(m_value)).CentreIn(rect),
|
||||
rect,
|
||||
dc,
|
||||
state);
|
||||
rect.y = rect.y + h.GetHeight() + 0;
|
||||
rect.height = rect.height - (h.GetHeight() + 0);
|
||||
|
||||
}
|
||||
|
||||
if (countRows > 0 && col == StorageModel::cols::Col_Host) {
|
||||
dc->SetBrush(*wxGREEN_BRUSH);
|
||||
wxString str = wxString::Format("%d", countRows);
|
||||
wxSize sz = dc->GetTextExtent(str);
|
||||
sz.SetWidth(sz.GetX() + 3);
|
||||
orig.SetLeft(orig.GetLeft() + (orig.GetWidth() - sz.GetWidth()));
|
||||
orig.SetHeight(sz.GetHeight());
|
||||
orig.SetWidth(sz.GetWidth());
|
||||
dc->DrawRoundedRectangle(orig, 2);
|
||||
RenderText(str,
|
||||
1, // no offset
|
||||
//wxRect(dc->GetTextExtent(m_value)).CentreIn(rect),
|
||||
orig,
|
||||
dc,
|
||||
state);
|
||||
|
||||
|
||||
}
|
||||
|
||||
return true;
|
||||
|
||||
RenderText(m_value,
|
||||
0, // no offset
|
||||
//wxRect(dc->GetTextExtent(m_value)).CentreIn(rect),
|
||||
rect,
|
||||
dc,
|
||||
state);
|
||||
return true;
|
||||
}
|
||||
|
||||
virtual bool ActivateCell(const wxRect& WXUNUSED(cell),
|
||||
wxDataViewModel* WXUNUSED(model),
|
||||
const wxDataViewItem& WXUNUSED(item),
|
||||
unsigned int WXUNUSED(col),
|
||||
const wxMouseEvent* mouseEvent) wxOVERRIDE
|
||||
{
|
||||
wxString position;
|
||||
if (mouseEvent)
|
||||
position = wxString::Format("via mouse at %d, %d", mouseEvent->m_x, mouseEvent->m_y);
|
||||
else
|
||||
position = "from keyboard";
|
||||
wxLogMessage("MyCustomRendererText ActivateCell() %s", position);
|
||||
return false;
|
||||
}
|
||||
|
||||
virtual wxSize GetSize() const wxOVERRIDE
|
||||
{
|
||||
wxSize txtSize = GetTextExtent(m_value);
|
||||
//wxSize txtSize = GetDC()->GetMultiLineTextExtent(GetMultiLineTextExtent);
|
||||
//wxSize txtSize = wxDataViewRenderer::GetDC()->GetMultiLineTextExtent(m_value);
|
||||
int lines = m_value.Freq('\n') + 1;
|
||||
if (lines > 1) {
|
||||
wxString position;
|
||||
position = wxString::Format("lines %d,hieght 1 row %d full h=%d", lines, txtSize.GetHeight(), txtSize.GetHeight() * lines + 1 * lines);
|
||||
// wxLogMessage("MyCustomRendererText GetSize() %s", position);
|
||||
txtSize.SetHeight(txtSize.GetHeight() * lines + 1 * lines);
|
||||
}
|
||||
else
|
||||
txtSize.SetHeight(-1);
|
||||
txtSize.SetWidth(-1);
|
||||
return txtSize;
|
||||
|
||||
//return GetView()->FromDIP(wxSize(60, 20));
|
||||
}
|
||||
|
||||
virtual bool SetValue(const wxVariant& value) wxOVERRIDE
|
||||
{
|
||||
m_value = value.GetString();
|
||||
if (!st) {
|
||||
StorageModel* m = dynamic_cast<StorageModel*>(GetView()->GetModel());
|
||||
st = m->getStorage();
|
||||
}
|
||||
if (st->IsGroupFilter()) {
|
||||
row = st->getLastRowIndex();
|
||||
countRows = st->getCountGroup(row);
|
||||
}
|
||||
else countRows = -1;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
virtual bool GetValue(wxVariant& WXUNUSED(value)) const wxOVERRIDE { return true; }
|
||||
|
||||
#if wxUSE_ACCESSIBILITY
|
||||
virtual wxString GetAccessibleDescription() const wxOVERRIDE
|
||||
{
|
||||
return m_value;
|
||||
}
|
||||
#endif // wxUSE_ACCESSIBILITY
|
||||
|
||||
virtual bool HasEditorCtrl() const wxOVERRIDE { return true; }
|
||||
|
||||
virtual wxWindow*
|
||||
CreateEditorCtrl(wxWindow* parent,
|
||||
wxRect labelRect,
|
||||
const wxVariant& value) wxOVERRIDE
|
||||
{
|
||||
wxTextCtrl* text = new wxTextCtrl(parent, wxID_ANY, value,
|
||||
labelRect.GetPosition(),
|
||||
labelRect.GetSize(),
|
||||
wxTE_PROCESS_ENTER);
|
||||
text->SetInsertionPointEnd();
|
||||
|
||||
return text;
|
||||
}
|
||||
|
||||
virtual bool
|
||||
GetValueFromEditorCtrl(wxWindow* ctrl, wxVariant& value) wxOVERRIDE
|
||||
{
|
||||
wxTextCtrl* text = wxDynamicCast(ctrl, wxTextCtrl);
|
||||
if (!text)
|
||||
return false;
|
||||
wxString sel = text->GetStringSelection();
|
||||
if (sel.IsEmpty()) return false;
|
||||
value = sel;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private:
|
||||
wxString m_value;
|
||||
};
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// StorageModel
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
static int my_sort_reverse(int* v1, int* v2)
|
||||
{
|
||||
return *v2 - *v1;
|
||||
}
|
||||
|
||||
static int my_sort(int* v1, int* v2)
|
||||
{
|
||||
return *v1 - *v2;
|
||||
}
|
||||
|
||||
#define INITIAL_NUMBER_OF_ITEMS 0
|
||||
|
||||
void StorageModel::BuildColumns(MyDataViewCtrl* ctrl) {
|
||||
wxDataViewColumn* const colIconText = new wxDataViewColumn
|
||||
(
|
||||
"Severity",
|
||||
new wxDataViewIconTextRenderer(),
|
||||
StorageModel::Col_ToggleIconText,
|
||||
wxCOL_WIDTH_AUTOSIZE, wxALIGN_CENTER_VERTICAL
|
||||
);
|
||||
colmap[StorageModel::Col_ToggleIconText] = MyConst::colField::logSqlstate;
|
||||
ctrl->AppendColumn(colIconText);
|
||||
|
||||
ctrl->AppendColumn(
|
||||
new wxDataViewColumn("logTime",
|
||||
new MyCustomRendererText(wxDATAVIEW_CELL_EDITABLE, StorageModel::Col_LogTime),
|
||||
StorageModel::Col_LogTime,
|
||||
wxCOL_WIDTH_AUTOSIZE,
|
||||
wxALIGN_LEFT,
|
||||
wxDATAVIEW_COL_REORDERABLE | wxDATAVIEW_COL_RESIZABLE | wxDATAVIEW_COL_SORTABLE
|
||||
));
|
||||
colmap[StorageModel::Col_LogTime] = MyConst::colField::logtime;
|
||||
|
||||
ctrl->AppendColumn(
|
||||
new wxDataViewColumn("UserName",
|
||||
new MyCustomRendererText(wxDATAVIEW_CELL_EDITABLE, StorageModel::Col_User),
|
||||
StorageModel::Col_User,
|
||||
wxCOL_WIDTH_AUTOSIZE,
|
||||
wxALIGN_LEFT,
|
||||
wxDATAVIEW_COL_REORDERABLE | wxDATAVIEW_COL_RESIZABLE | wxDATAVIEW_COL_SORTABLE
|
||||
));
|
||||
colmap[StorageModel::Col_User] = MyConst::colField::loguser;
|
||||
ctrl->AppendColumn(
|
||||
new wxDataViewColumn("DbName",
|
||||
new MyCustomRendererText(wxDATAVIEW_CELL_EDITABLE, StorageModel::Col_Db),
|
||||
StorageModel::Col_Db,
|
||||
30,
|
||||
wxALIGN_LEFT,
|
||||
wxDATAVIEW_COL_REORDERABLE | wxDATAVIEW_COL_RESIZABLE | wxDATAVIEW_COL_SORTABLE
|
||||
));
|
||||
colmap[StorageModel::Col_Db] = MyConst::colField::logdb;
|
||||
ctrl->AppendColumn(
|
||||
new wxDataViewColumn("Pid",
|
||||
new MyCustomRendererText(wxDATAVIEW_CELL_EDITABLE, StorageModel::Col_PID),
|
||||
StorageModel::Col_PID,
|
||||
60,
|
||||
wxALIGN_LEFT,
|
||||
wxDATAVIEW_COL_REORDERABLE | wxDATAVIEW_COL_RESIZABLE | wxDATAVIEW_COL_SORTABLE
|
||||
));
|
||||
colmap[StorageModel::Col_PID] = MyConst::colField::logpid;
|
||||
ctrl->AppendColumn(
|
||||
new wxDataViewColumn("Host",
|
||||
new MyCustomRendererText(wxDATAVIEW_CELL_EDITABLE, StorageModel::Col_Host),
|
||||
StorageModel::Col_Host,
|
||||
90,
|
||||
wxALIGN_LEFT,
|
||||
wxDATAVIEW_COL_REORDERABLE | wxDATAVIEW_COL_RESIZABLE | wxDATAVIEW_COL_SORTABLE
|
||||
));
|
||||
colmap[StorageModel::Col_Host] = MyConst::colField::loghost;
|
||||
ctrl->AppendColumn(
|
||||
new wxDataViewColumn("AppName",
|
||||
new MyCustomRendererText(wxDATAVIEW_CELL_EDITABLE, StorageModel::Col_App),
|
||||
StorageModel::Col_App,
|
||||
100,
|
||||
wxALIGN_LEFT,
|
||||
wxDATAVIEW_COL_REORDERABLE | wxDATAVIEW_COL_RESIZABLE | wxDATAVIEW_COL_SORTABLE
|
||||
));
|
||||
colmap[StorageModel::Col_App] = MyConst::colField::logappname;
|
||||
ctrl->AppendColumn(
|
||||
new wxDataViewColumn("Hint",
|
||||
new MyCustomRendererText(wxDATAVIEW_CELL_EDITABLE, StorageModel::Col_Hint),
|
||||
StorageModel::Col_Hint,
|
||||
90,
|
||||
wxALIGN_LEFT,
|
||||
wxDATAVIEW_COL_REORDERABLE | wxDATAVIEW_COL_RESIZABLE | wxDATAVIEW_COL_SORTABLE
|
||||
));
|
||||
colmap[StorageModel::Col_Hint] = MyConst::colField::logHint;
|
||||
ctrl->AppendColumn(
|
||||
new wxDataViewColumn("Detail",
|
||||
new MyCustomRendererText(wxDATAVIEW_CELL_EDITABLE, StorageModel::Col_Detail),
|
||||
StorageModel::Col_Detail,
|
||||
60,
|
||||
wxALIGN_LEFT,
|
||||
wxDATAVIEW_COL_REORDERABLE | wxDATAVIEW_COL_RESIZABLE | wxDATAVIEW_COL_SORTABLE
|
||||
));
|
||||
colmap[StorageModel::Col_Detail] = MyConst::colField::logDetail;
|
||||
|
||||
ctrl->AppendColumn(
|
||||
new wxDataViewColumn("Message",
|
||||
new MyCustomRendererText(wxDATAVIEW_CELL_EDITABLE, StorageModel::Col_Message),
|
||||
StorageModel::Col_Message,
|
||||
wxCOL_WIDTH_AUTOSIZE,
|
||||
wxALIGN_LEFT,
|
||||
wxDATAVIEW_COL_REORDERABLE | wxDATAVIEW_COL_RESIZABLE | wxDATAVIEW_COL_SORTABLE
|
||||
));
|
||||
colmap[StorageModel::Col_Message] = MyConst::colField::logMessage;
|
||||
|
||||
|
||||
}
|
||||
#include <wx/textfile.h>
|
||||
#include "log/filter_xpm.xpm"
|
||||
StorageModel::StorageModel(MyDataViewCtrl* view) :
|
||||
wxDataViewVirtualListModel(INITIAL_NUMBER_OF_ITEMS)
|
||||
{
|
||||
m_view = view;
|
||||
//m_icon[0] = wxIcon(null_xpm);
|
||||
m_icon[MyConst::iconIndex::log] = wxIcon(log_xpm);
|
||||
m_icon[MyConst::iconIndex::war] = wxIcon(war_xpm);
|
||||
m_icon[MyConst::iconIndex::user] = wxIcon(user_xpm);
|
||||
m_icon[MyConst::iconIndex::error] = wxIcon(errorl_xpm);
|
||||
m_icon[MyConst::iconIndex::fatal] = wxIcon(fatal_xpm);
|
||||
m_icon[MyConst::iconIndex::panic] = wxIcon(panic_xpm);
|
||||
bitmapflt = wxBitmap((wxIcon(filter_xpm)));
|
||||
store = new Storage();
|
||||
}
|
||||
bool StorageModel::setFilter(int col, wxString val, int flags, MyDataViewCtrl* view) {
|
||||
|
||||
bool r = store->SetFilter(colmap[col], val, flags);
|
||||
Reset(store->getCountFilter());
|
||||
if (col != -1) {
|
||||
wxDataViewColumn* vc = view->GetColumn(col);
|
||||
vc->SetBitmap(bitmapflt);
|
||||
}
|
||||
return r;
|
||||
}
|
||||
int StorageModel::testFilter(int col, int position = 0) {
|
||||
int idx = 0;
|
||||
idx = store->testFilter(colmap[col], position);
|
||||
return idx;
|
||||
}
|
||||
void StorageModel::ApplyFilter() {
|
||||
store->ApplyFilter();
|
||||
Reset(store->getCountFilter());
|
||||
}
|
||||
|
||||
void StorageModel::DropColFilter(int index) {
|
||||
if (index >= 0) store->DropColFilter(index);
|
||||
}
|
||||
bool StorageModel::Prepend(const wxString& text)
|
||||
{
|
||||
//m_toggleColValues.insert(m_toggleColValues.begin(), 0);
|
||||
//m_textColValues.Insert(text, 0);
|
||||
bool add=store->AddLineTextCSV(text);
|
||||
if (!add) return false;
|
||||
int row = store->getCountStore() - 1;
|
||||
wxString val = store->GetFieldStorage(row, MyConst::colField::loguser, false);
|
||||
IncCountFreq(StorageModel::Col_User, val);
|
||||
IncCountFreq(StorageModel::Col_Db, store->GetFieldStorage(row, MyConst::colField::logdb, false));
|
||||
IncCountFreq(StorageModel::Col_Host, store->GetFieldStorage(row, MyConst::colField::loghost, false));
|
||||
val = store->GetFieldStorage(row, MyConst::colField::logappname, false);
|
||||
//if (val.IsEmpty()) val = store->GetFieldStorage((int)row, MyConst::colField::logbtype,false);
|
||||
IncCountFreq(StorageModel::Col_App, val);
|
||||
IncCountFreq(StorageModel::Col_PID, store->GetFieldStorage(row, MyConst::colField::logpid, false));
|
||||
IncCountFreq(StorageModel::Col_Hint, store->GetFieldStorage(row, MyConst::colField::logHint, false));
|
||||
val = store->GetFieldStorage(row, MyConst::colField::logSqlstate, false);
|
||||
IncCountFreq(StorageModel::Col_ToggleIconText, val);
|
||||
|
||||
|
||||
if (store->ApplyFilter(row)) {
|
||||
RowAppended();
|
||||
//RowPrepended();
|
||||
return true;
|
||||
}
|
||||
if (store->IsGroupFilter()) {
|
||||
|
||||
}
|
||||
return false;
|
||||
|
||||
}
|
||||
void StorageModel::DeleteItem(const wxDataViewItem& item)
|
||||
{
|
||||
unsigned int row = GetRow(item);
|
||||
|
||||
RowDeleted(row);
|
||||
}
|
||||
|
||||
void StorageModel::DeleteItems(const wxDataViewItemArray& items)
|
||||
{
|
||||
unsigned i;
|
||||
wxArrayInt rows;
|
||||
}
|
||||
|
||||
void StorageModel::AddMany()
|
||||
{
|
||||
Reset(GetCount() + 1000);
|
||||
}
|
||||
|
||||
void StorageModel::GetValueByRow(wxVariant& variant,
|
||||
unsigned int row, unsigned int col) const
|
||||
{
|
||||
MyConst::colField fldcsv = colmap[col];
|
||||
wxString val;
|
||||
val = store->GetField((int)row, fldcsv);
|
||||
if (col == StorageModel::Col_ToggleIconText) {
|
||||
int i = store->GetSeverityIndex((int)row);
|
||||
variant << wxDataViewIconText(val, m_icon[i]);
|
||||
return;
|
||||
}
|
||||
else if (col == StorageModel::Col_App) {
|
||||
//if (val.IsEmpty()) val = store->GetField((int)row, MyConst::colField::logbtype);
|
||||
}
|
||||
else if (col == StorageModel::Col_User) {
|
||||
|
||||
};
|
||||
|
||||
variant = val;
|
||||
}
|
||||
|
||||
bool StorageModel::GetAttrByRow(unsigned int row, unsigned int col,
|
||||
wxDataViewItemAttr& attr) const
|
||||
{
|
||||
|
||||
//attr.SetBackgroundColour(*wxLIGHT_GREY);
|
||||
wxColor c = store->GetBgColorLine((int)row);
|
||||
if (c.IsOk()) {
|
||||
attr.SetBackgroundColour(c);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool StorageModel::SetValueByRow(const wxVariant& variant,
|
||||
unsigned int row, unsigned int col)
|
||||
{
|
||||
wxString flt = variant.GetString();
|
||||
int flags = FL_CONTAINS;
|
||||
if (flt[0] == '!') {
|
||||
flags = flags | FL_REVERSE;
|
||||
flt = flt.substr(1);
|
||||
}
|
||||
setFilter(col, flt, flags, m_view);
|
||||
|
||||
return false;
|
||||
}
|
||||
Binary file not shown.
Loading…
Add table
Add a link
Reference in a new issue