mirror of
https://github.com/levinsv/pgadmin3.git
synced 2026-05-15 06:05:49 -06:00
546 lines
18 KiB
C++
546 lines
18 KiB
C++
#include "pgAdmin3.h"
|
|
|
|
|
|
#ifndef WX_PRECOMP
|
|
#include "wx/wx.h"
|
|
#endif
|
|
|
|
#include "wx/dataview.h"
|
|
#include "log/Storage.h"
|
|
#include "log/StorageModel.h"
|
|
#include "utils/utffile.h"
|
|
#include <wx/filename.h>
|
|
#include <wx/stdpaths.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;
|
|
wxColour quoteselcolor;
|
|
// 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;
|
|
wxColour textColour;
|
|
#ifdef __WXGTK__
|
|
textColour = wxSystemSettings::GetColour(wxSYS_COLOUR_HIGHLIGHTTEXT);
|
|
#else
|
|
textColour = wxSystemSettings::GetColour(wxSYS_COLOUR_LISTBOXTEXT);
|
|
#endif // __WXGTK__
|
|
if (ContrastColorBlackOrWhite(textColour) == "#000000") {
|
|
quoteselcolor = wxColour(wxString("#7f7f7f"));
|
|
}
|
|
else quoteselcolor = *wxYELLOW;
|
|
}
|
|
|
|
virtual bool Render(wxRect rect, wxDC* dc, int state) wxOVERRIDE
|
|
{
|
|
//dc->SetBrush( *wxLIGHT_GREY_BRUSH );
|
|
if (state & wxDATAVIEW_CELL_SELECTED)
|
|
dc->SetBrush(quoteselcolor);
|
|
else
|
|
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, rect, dc, state);
|
|
rect.y = rect.y + h.GetHeight() + 0;
|
|
rect.height = rect.height - (h.GetHeight() + 0);
|
|
ex = true;
|
|
}
|
|
if (!ex) RenderText(t, x, rect, dc, state);
|
|
|
|
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);
|
|
#ifdef __WXGTK__
|
|
wxSize charSize = GetTextExtent("H");
|
|
txtSize.SetHeight(txtSize.GetHeight() + charSize.GetHeight()/2);
|
|
#else
|
|
txtSize.SetHeight(txtSize.GetHeight() * lines + 1 * lines);
|
|
#endif
|
|
}
|
|
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_NOT,
|
|
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_NOT,
|
|
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_NOT,
|
|
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_NOT,
|
|
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_NOT,
|
|
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_NOT,
|
|
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_NOT,
|
|
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_NOT,
|
|
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_NOT,
|
|
wxDATAVIEW_COL_REORDERABLE | wxDATAVIEW_COL_RESIZABLE | wxDATAVIEW_COL_SORTABLE
|
|
));
|
|
colmap[StorageModel::Col_Message] = MyConst::colField::logMessage;
|
|
ctrl->AppendColumn(
|
|
new wxDataViewColumn("Server",
|
|
new MyCustomRendererText(wxDATAVIEW_CELL_EDITABLE, StorageModel::Col_Server),
|
|
StorageModel::Col_Server,
|
|
wxCOL_WIDTH_AUTOSIZE,
|
|
wxALIGN_NOT,
|
|
wxDATAVIEW_COL_REORDERABLE | wxDATAVIEW_COL_RESIZABLE | wxDATAVIEW_COL_SORTABLE
|
|
));
|
|
colmap[StorageModel::Col_Server] = MyConst::colField::logSERVER;
|
|
|
|
|
|
}
|
|
#include <wx/textfile.h>
|
|
#include "log/filter_xpm.xpm"
|
|
StorageModel::~StorageModel() {
|
|
delete store;
|
|
}
|
|
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);
|
|
m_view->UnselectAll();
|
|
Reset(store->getCountFilter());
|
|
if (col != -1) {
|
|
wxDataViewColumn* vc = view->GetColumn(col);
|
|
vc->SetBitmap(bitmapflt);
|
|
}
|
|
return r;
|
|
}
|
|
bool StorageModel::setFilterArray(std::deque<LineFilter> arr,MyDataViewCtrl* view) {
|
|
bool r=store->SetFilterArray(arr);
|
|
view->UnselectAll();
|
|
Reset(store->getCountFilter());
|
|
setIconFilter(view);
|
|
return r;
|
|
}
|
|
void StorageModel::setIconFilter(MyDataViewCtrl* view) {
|
|
bool yesfilter = false;
|
|
for (int j = 0; j < view->GetColumnCount(); j++) {
|
|
int colt = 0;
|
|
yesfilter = false;
|
|
wxDataViewColumn* vc = view->GetColumn(j);
|
|
while (colt != -1) {
|
|
colt = testFilter(j, colt);
|
|
if (colt >= 0) {
|
|
//m->DropColFilter(colt);
|
|
vc->SetBitmap(bitmapflt);
|
|
|
|
yesfilter = true;
|
|
colt++;
|
|
break;
|
|
}
|
|
}
|
|
if (!yesfilter) vc->SetBitmap(wxNullBitmap);
|
|
}
|
|
}
|
|
|
|
int StorageModel::testFilter(int col, int position = 0) {
|
|
int idx = 0;
|
|
idx = store->testFilter(colmap[col], position);
|
|
return idx;
|
|
}
|
|
void StorageModel::ApplyFilter() {
|
|
store->ApplyFilter();
|
|
m_view->UnselectAll();
|
|
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);
|
|
val = store->GetFieldStorage(row, MyConst::colField::logSERVER, false);
|
|
IncCountFreq(StorageModel::Col_Server, 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;
|
|
}
|