mirror of
https://github.com/levinsv/pgadmin3.git
synced 2026-05-15 06:05:49 -06:00
Улучшена поддержка клавиши для навигации в контекстной справке. Краткий список: PAGEDOWN,PAGEUP,UP,DOWN,HOME,END - скроллинг окна. + - увеличить размер окна. S - screenshot контекстной справки. C - копирование в html формате.
1511 lines
50 KiB
C++
1511 lines
50 KiB
C++
//////////////////////////////////////////////////////////////////////////
|
||
//
|
||
// pgAdmin III - PostgreSQL Tools
|
||
//
|
||
// Copyright (C) 2002 - 2016, The pgAdmin Development Team
|
||
// This software is released under the PostgreSQL Licence
|
||
//
|
||
// ctlSQLGrid.cpp - SQL Query result window
|
||
//
|
||
//////////////////////////////////////////////////////////////////////////
|
||
|
||
#include "pgAdmin3.h"
|
||
|
||
// wxWindows headers
|
||
#include <wx/wx.h>
|
||
#include <wx/clipbrd.h>
|
||
#include <wx/generic/gridctrl.h>
|
||
#include "db/pgConn.h"
|
||
#include "ctl/ctlSQLGrid.h"
|
||
#include "utils/sysSettings.h"
|
||
#include "frm/frmExport.h"
|
||
#include <wx/regex.h>
|
||
#include "ctl/ctlSQLResult.h"
|
||
#include "utils/misc.h"
|
||
#include "utils/FunctionPGHelper.h"
|
||
#include "utils/PreviewHtml.h"
|
||
|
||
#define EXTRAEXTENT_HEIGHT 6
|
||
#define EXTRAEXTENT_WIDTH 6
|
||
|
||
//DEFINE_EVENT_TYPE(myEVT_SHOW_POPUP)
|
||
|
||
BEGIN_EVENT_TABLE(ctlSQLGrid, wxGrid)
|
||
EVT_MOUSEWHEEL(ctlSQLGrid::OnMouseWheel)
|
||
//EVT_CUSTOM(wxID_ANY, myEVT_SHOW_POPUP,ctlSQLGrid::OnShowPopup)
|
||
EVT_GRID_COL_SIZE(ctlSQLGrid::OnGridColSize)
|
||
EVT_GRID_LABEL_LEFT_CLICK(ctlSQLGrid::OnLabelClick)
|
||
EVT_GRID_CELL_RIGHT_CLICK(ctlSQLGrid::OnCellRightClick)
|
||
EVT_GRID_SELECT_CELL(ctlSQLGrid::OnGridSelectCell)
|
||
//EVT_PAINT( ctlSQLGrid::OnPaint )
|
||
END_EVENT_TABLE()
|
||
|
||
IMPLEMENT_DYNAMIC_CLASS(ctlSQLGrid, wxGrid)
|
||
|
||
ctlSQLGrid::ctlSQLGrid()
|
||
{
|
||
}
|
||
|
||
void ctlSQLGrid::setresizedpi() {
|
||
// Set cells font
|
||
wxFont fntCells(settings->GetSQLFont());
|
||
SetDefaultCellFont(fntCells);
|
||
// Set labels font
|
||
wxFont fntLabel(settings->GetSystemFont());
|
||
fntLabel.SetWeight(wxFONTWEIGHT_BOLD);
|
||
SetLabelFont(fntLabel);
|
||
SetColLabelAlignment(wxALIGN_LEFT, wxALIGN_CENTRE);
|
||
SetDefaultCellAlignment(wxALIGN_LEFT, wxALIGN_TOP);
|
||
SetRowLabelSize(FromDIP(50));
|
||
SetDefaultRowSize(fntCells.GetPointSize() * 2 + 2);
|
||
SetColLabelSize(fntLabel.GetPointSize() * 4);
|
||
|
||
}
|
||
|
||
ctlSQLGrid::ctlSQLGrid(wxWindow* parent, wxWindowID id, const wxPoint& pos, const wxSize& size)
|
||
: wxGrid(parent, id, pos, size, wxWANTS_CHARS | wxVSCROLL | wxHSCROLL)
|
||
{
|
||
/*
|
||
Bind(wxEVT_DPI_CHANGED, [this](wxDPIChangedEvent& event) {
|
||
setresizedpi();
|
||
event.Skip();
|
||
});
|
||
*/
|
||
Bind(wxEVT_THREAD, &ctlSQLGrid::OnShowPopup, this);
|
||
setresizedpi();
|
||
SetDefaultCellOverflow(false);
|
||
// load pgadmin3opt.json
|
||
wxJSONValue def(wxJSONType::wxJSONTYPE_OBJECT);
|
||
wxJSONValue opt(wxJSONType::wxJSONTYPE_OBJECT);
|
||
int t_width=0;
|
||
def["thousandsWidthSeparator"]=t_width;
|
||
settings->ReloadJsonFileIfNeed();
|
||
settings->ReadJsonObect("ctlSQLGrid", opt, def);
|
||
if (!opt.IsNull()) { // check
|
||
int tmp=opt["thousandsWidthSeparator"].AsInt();
|
||
if (tmp<-15 || tmp>15) opt["thousandsWidthSeparator"]=def["thousandsWidthSeparator"];
|
||
}
|
||
else
|
||
opt = def;
|
||
int thousandsWidthSeparator = opt["thousandsWidthSeparator"].AsInt();
|
||
|
||
SetDefaultRenderer(new CursorCellRenderer(thousandsWidthSeparator));
|
||
//SetUseNativeColLabels(true);
|
||
//UseNativeColHeader(true);
|
||
SetCellHighlightColour(wxColor(0, 0, 0));
|
||
#ifdef __WXGTK__
|
||
wxColour selbg = GetSelectionBackground();
|
||
wxColour cbg = GetBackgroundColour();
|
||
wxColour labbg = GetLabelBackgroundColour();
|
||
wxString t1 = selbg.GetAsString();
|
||
wxString t2 = labbg.GetAsString();
|
||
wxColour cline = GetGridLineColour();
|
||
wxString t3 = cline.GetAsString();
|
||
if (labbg.GetRGB() == cline.GetRGB()) {
|
||
int min = wxMin(labbg.GetBlue(), labbg.GetGreen());
|
||
min = wxMin(min, labbg.GetRed());
|
||
if (min > 200) min = min - 30; else min = min + 30;
|
||
wxColour labbgn(min, min, min);
|
||
SetLabelBackgroundColour(labbgn);
|
||
}
|
||
if (cline.GetRGB() == cbg.GetRGB()) {
|
||
int min = wxMin(cline.GetBlue(), cline.GetGreen());
|
||
min = wxMin(min, cline.GetRed());
|
||
if (min > 200) min = min - 30; else min = min + 30;
|
||
wxColour newgridclr(min, min, min);
|
||
SetGridLineColour(newgridclr);
|
||
}
|
||
#endif
|
||
grp = NULL;
|
||
isSort = false;
|
||
searchStr = "";
|
||
Connect(wxID_ANY, wxEVT_GRID_LABEL_LEFT_DCLICK, wxGridEventHandler(ctlSQLGrid::OnLabelDoubleClick));
|
||
}
|
||
#include "wx/renderer.h"
|
||
#include "wx/headerctrl.h"
|
||
void ctlSQLGrid::OnGridSelectCell(wxGridEvent& evt) {
|
||
int row = evt.GetRow();
|
||
//int col = evt.GetCol();
|
||
wxGridCellCoords cr = GetGridCursorCoords();
|
||
if (cr.GetRow() != row && cr.GetRow() != -1) {
|
||
GetGridRowLabelWindow()->Refresh();
|
||
}
|
||
}
|
||
void ctlSQLGrid::DrawRowLabel(wxDC& dc, int row) {
|
||
int c = GetGridCursorRow();
|
||
if (c != row) wxGrid::DrawRowLabel(dc, row);
|
||
else {
|
||
//wxColour c = wxSystemSettings::GetColour(wxSYS_COLOUR_BTNHIGHLIGHT);
|
||
wxColour c = GetGridRowLabelWindow()->GetBackgroundColour();
|
||
int d = 20;
|
||
int r = c.GetRed() + d; int g = c.GetGreen() + d; int b = c.GetBlue() + d;
|
||
if (r > 255 || g > 255 || b > 255) {
|
||
r = r - 2 * d;
|
||
g = g - 2 * d;
|
||
b = b - 2 * d;
|
||
}
|
||
wxColour c3(r, g, b);
|
||
wxDCBrushChanger setBrush(dc, c3);
|
||
wxDCPenChanger setPen(dc, *wxTRANSPARENT_PEN);
|
||
wxRect rect(0, GetRowTop(row), GetRowLabelSize(), GetRowHeight(row));
|
||
dc.DrawRectangle(rect);
|
||
wxGrid::DrawRowLabel(dc, row);
|
||
}
|
||
|
||
}
|
||
void ctlSQLGrid::DrawColLabel(wxDC& dc, int col) {
|
||
wxGrid::DrawColLabel(dc, col);
|
||
if (!IsSort()) return;
|
||
int colLeft = GetColLeft(col);
|
||
|
||
wxRect rect(colLeft, 0, GetColWidth(col), m_colLabelHeight);
|
||
sqlResultTable* t = (sqlResultTable*)GetTable();
|
||
wxHeaderSortIconType sortArrow = t->getSortColumn(col) != 0
|
||
? t->getSortColumn(col) > 0
|
||
? wxHDR_SORT_ICON_UP
|
||
: wxHDR_SORT_ICON_DOWN
|
||
: wxHDR_SORT_ICON_NONE;
|
||
|
||
if (sortArrow != wxHDR_SORT_ICON_NONE)
|
||
{
|
||
wxRect ar = rect;
|
||
|
||
// make a rect for the arrow
|
||
ar.height = FromDIP(4);
|
||
ar.width = FromDIP(8);
|
||
ar.y += (rect.height - ar.height) / 2;
|
||
ar.x = ar.x + rect.width - 3 * ar.width / 2;
|
||
int arrowSpace = 0;
|
||
arrowSpace = 3 * ar.width / 2; // space to preserve when drawing the label
|
||
wxPoint triPt[3];
|
||
if (sortArrow & wxHDR_SORT_ICON_UP)
|
||
{
|
||
triPt[0].x = ar.width / 2;
|
||
triPt[0].y = 0;
|
||
triPt[1].x = ar.width;
|
||
triPt[1].y = ar.height;
|
||
triPt[2].x = 0;
|
||
triPt[2].y = ar.height;
|
||
}
|
||
else
|
||
{
|
||
triPt[0].x = 0;
|
||
triPt[0].y = 0;
|
||
triPt[1].x = ar.width;
|
||
triPt[1].y = 0;
|
||
triPt[2].x = ar.width / 2;
|
||
triPt[2].y = ar.height;
|
||
}
|
||
|
||
wxColour c;
|
||
|
||
c = wxSystemSettings::GetColour(wxSYS_COLOUR_3DSHADOW);
|
||
for (int k = 0; k < MAX_COL_SORT; k++) {
|
||
int cl = t->colsortnumber[k];
|
||
if (cl != -1) {
|
||
if (cl == col) {
|
||
if (k == 0) c = wxColor(155, 17, 48); // red
|
||
if (k == 1) c = wxColor(255, 255, 0); // yellow
|
||
if (k == 2) c = wxColor(34, 199, 76); // green
|
||
if (k == 3) c = wxColor(12, 38, 160); // blue
|
||
}
|
||
}
|
||
else break;
|
||
}
|
||
wxDCPenChanger setPen(dc, c);
|
||
wxDCBrushChanger setBrush(dc, c);
|
||
|
||
wxDCClipper clip(dc, rect);
|
||
dc.DrawPolygon(3, triPt, ar.x, ar.y);
|
||
}
|
||
|
||
//wxRendererNative::Get().DrawHeaderButton
|
||
// (m_colWindow,
|
||
// //GetColLabelWindow(),
|
||
// dc,
|
||
// rect,
|
||
// 0,
|
||
// IsSortingBy(col)
|
||
// ? IsSortOrderAscending()
|
||
// ? wxHDR_SORT_ICON_UP
|
||
// : wxHDR_SORT_ICON_DOWN
|
||
// : wxHDR_SORT_ICON_NONE
|
||
// );
|
||
|
||
|
||
}
|
||
void ctlSQLGrid::OnGridColSize(wxGridSizeEvent& event)
|
||
{
|
||
// Save key="index:label", value=size
|
||
int col = event.GetRowOrCol();
|
||
if (col < 0) return;
|
||
colSizes[GetColKeyValue(col)] = GetColSize(col);
|
||
|
||
}
|
||
void ctlSQLGrid::OnCopy(wxCommandEvent& ev)
|
||
{
|
||
Copy(false);
|
||
}
|
||
|
||
void ctlSQLGrid::OnMouseWheel(wxMouseEvent& event)
|
||
{
|
||
if (event.ControlDown() || event.CmdDown())
|
||
{
|
||
wxFont fontlabel = GetLabelFont();
|
||
wxFont fontcells = GetDefaultCellFont();
|
||
if (event.GetWheelRotation() > 0)
|
||
{
|
||
fontlabel.SetPointSize(fontlabel.GetPointSize() - 1);
|
||
fontcells.SetPointSize(fontcells.GetPointSize() - 1);
|
||
}
|
||
else
|
||
{
|
||
fontlabel.SetPointSize(fontlabel.GetPointSize() + 1);
|
||
fontcells.SetPointSize(fontcells.GetPointSize() + 1);
|
||
}
|
||
SetLabelFont(fontlabel);
|
||
SetDefaultCellFont(fontcells);
|
||
SetColLabelSize(fontlabel.GetPointSize() * 4);
|
||
SetDefaultRowSize(fontcells.GetPointSize() * 2);
|
||
for (int index = 0; index < GetNumberCols(); index++)
|
||
SetColSize(index, -1);
|
||
ForceRefresh();
|
||
}
|
||
else
|
||
event.Skip();
|
||
}
|
||
|
||
wxString ctlSQLGrid::GetExportLine(int row)
|
||
{
|
||
return GetExportLine(row, 0, GetNumberCols() - 1);
|
||
}
|
||
|
||
|
||
wxString ctlSQLGrid::GetExportLine(int row, int col1, int col2)
|
||
{
|
||
wxArrayInt cols;
|
||
wxString str;
|
||
int i;
|
||
|
||
if (col2 < col1)
|
||
return str;
|
||
|
||
cols.Alloc(col2 - col1 + 1);
|
||
for (i = col1; i <= col2; i++)
|
||
{
|
||
cols.Add(i);
|
||
}
|
||
|
||
return GetExportLine(row, cols);
|
||
}
|
||
|
||
wxString ctlSQLGrid::GetExportLine(int row, wxArrayInt cols)
|
||
{
|
||
wxString str;
|
||
unsigned int col;
|
||
|
||
if (GetNumberCols() == 0 || GetRowSize(row) == 0)
|
||
return str;
|
||
sqlResultTable *t=(sqlResultTable *)GetTable();
|
||
wxString colsep = settings->GetCopyColSeparator();
|
||
if (generatesql == 2 || generatesql == 1) colsep = wxT(",");
|
||
if (generatesql == 3) colsep = wxT(" and ");
|
||
wxString qtsimbol = settings->GetCopyQuoteChar();
|
||
if (generatesql > 0) qtsimbol = wxT("'");
|
||
wxString head = wxT("insert into tbl(");
|
||
if (cols.Count() > 1 && generatesql > 1) str.Append("(");
|
||
for (col = 0; col < cols.Count(); col++)
|
||
{
|
||
if (col > 0)
|
||
str.Append(colsep);
|
||
if (col > 0) head.Append(colsep);
|
||
head = head + GetColumnName(cols[col]);
|
||
wxString text;
|
||
bool isnull=false;
|
||
int pgtype=0;
|
||
if ( t && generatesql > 0)
|
||
{
|
||
// only insert , in_list and where list
|
||
text = t->GetValueWithNull( row, cols[col] , &isnull, &pgtype );
|
||
} else text = GetCellValue(row, cols[col]);
|
||
|
||
wxString cname = GetColumnName(cols[col]);
|
||
bool needQuote = false;
|
||
if (settings->GetCopyQuoting() == 1)
|
||
{
|
||
needQuote = IsColText(cols[col]);
|
||
}
|
||
else if (settings->GetCopyQuoting() == 2)
|
||
/* Quote everything */
|
||
needQuote = true;
|
||
if (isnull && generatesql > 0) { needQuote = false; }
|
||
else
|
||
if (generatesql > 0) needQuote = IsColText(cols[col]);
|
||
|
||
if (generatesql > 0) {
|
||
if (!isnull) {
|
||
text.Replace(wxT("'"), wxT("''"));
|
||
}
|
||
else
|
||
text = wxT("null");
|
||
|
||
}
|
||
if (generatesql == 3) {
|
||
if (isnull)
|
||
str.Append(cname).Append(" is ");
|
||
else
|
||
str.Append(cname).Append("=");
|
||
}
|
||
|
||
if (needQuote)
|
||
str.Append(qtsimbol);
|
||
str.Append(text);
|
||
if (needQuote)
|
||
str.Append(qtsimbol);
|
||
}
|
||
if (cols.Count() > 1 && generatesql > 1) str.Append(")");
|
||
if (generatesql == 1) str = head + wxT(") values (") + str + ");";
|
||
|
||
return str;
|
||
}
|
||
|
||
wxString ctlSQLGrid::GetColumnName(int colNum)
|
||
{
|
||
wxString columnName = GetColLabelValue(colNum);
|
||
columnName = columnName.Left(columnName.find(wxT("\n")));
|
||
return columnName;
|
||
}
|
||
|
||
void ctlSQLGrid::AppendColumnHeader(wxString& str, int start, int end)
|
||
{
|
||
size_t i, arrsize;
|
||
arrsize = (end - start + 1);
|
||
wxArrayInt columns;
|
||
|
||
for (i = 0; i < arrsize; i++)
|
||
{
|
||
columns.Add(start + i);
|
||
}
|
||
|
||
AppendColumnHeader(str, columns);
|
||
}
|
||
|
||
void ctlSQLGrid::AppendColumnHeader(wxString& str, wxArrayInt columns)
|
||
{
|
||
if (settings->GetColumnNames() || generatesql == 2)
|
||
{
|
||
bool CopyQuoting = (settings->GetCopyQuoting() == 1 || settings->GetCopyQuoting() == 2);
|
||
size_t i;
|
||
wxString fielddelim = ",";
|
||
if (generatesql == 3) return;
|
||
if (generatesql == 1) return;
|
||
for (i = 0; i < columns.Count(); i++)
|
||
{
|
||
long columnPos = columns.Item(i);
|
||
if (generatesql == 2) {
|
||
if (i > 0) str.Append(fielddelim);
|
||
if (i == 0 && columns.Count() > 1) str.Append("(");
|
||
str.Append(GetColumnName(columnPos));
|
||
if (i == columns.Count() - 1 && columns.Count() > 1 && generatesql == 2) str.Append(") in (");
|
||
if (columns.Count() == 1 && generatesql == 2) str.Append(" in (");
|
||
|
||
}
|
||
else
|
||
{
|
||
if (i > 0)
|
||
str.Append(settings->GetCopyColSeparator());
|
||
|
||
if (CopyQuoting)
|
||
str.Append(settings->GetCopyQuoteChar());
|
||
str.Append(GetColumnName(columnPos));
|
||
if (CopyQuoting)
|
||
str.Append(settings->GetCopyQuoteChar());
|
||
}
|
||
}
|
||
|
||
str.Append(END_OF_LINE);
|
||
}
|
||
}
|
||
int compare_int(int* a, int* b)
|
||
{
|
||
if (*a > *b) return 1;
|
||
else if (*a < *b) return -1;
|
||
else return 0;
|
||
}
|
||
#include <map>
|
||
class selMerge {
|
||
public:
|
||
std::map<int, std::map<int, int>> getmap() { return grid; }
|
||
void add(int row, int col);
|
||
void setArrayColumns(int row, wxArrayInt& columns);
|
||
void addRange(int r1, int r2, int c1, int c2) {
|
||
//std::map<int, int> v;
|
||
|
||
for (int r = r1; r <= r2; r++)
|
||
{
|
||
auto& v = grid[r];
|
||
for (int c = c1; c <= c2; c++) {
|
||
v[c] = c;
|
||
}
|
||
//grid[r].swap(v);
|
||
}
|
||
}
|
||
|
||
private:
|
||
std::map<int, std::map<int, int>> grid;
|
||
};
|
||
void selMerge::add(int row, int col) {
|
||
std::map<int, int> v;
|
||
v = grid[row];
|
||
v[col] = col;
|
||
}
|
||
|
||
void selMerge::setArrayColumns(int row, wxArrayInt& columns) {
|
||
auto& v = grid[row];
|
||
for (const auto& pair : v) {
|
||
//std::cout << pair.first << ": " << pair.second << '\n';
|
||
int k = pair.second;
|
||
columns.Add(k);
|
||
}
|
||
};
|
||
int ctlSQLGrid::CopyTableToHtml(wxString htmlquery) {
|
||
wxString htm = "<html>"
|
||
"<head>"
|
||
"<meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\"/>\n"
|
||
"<style type = \"text/css\">\n"
|
||
"#maket { width: 90%; border-collapse: collapse; table-layout: fixed;}\n"
|
||
"TD { vertical-align: top; border: 1px solid; padding: 2px; }\n"
|
||
|
||
;
|
||
int s = htmlquery.find('"');
|
||
int e = htmlquery.find('"', s + 1);
|
||
if (s > 0 && e > s) {
|
||
wxString fnt = htmlquery.SubString(s + 1, e - 1);
|
||
htm += "PRE { " + fnt + ";}\n";
|
||
}
|
||
wxArrayInt cols = GetSelectedCols();
|
||
if (cols.GetCount() == 0) {
|
||
for (int i = 0; i < GetNumberCols(); i++)
|
||
{
|
||
cols.Add(i);
|
||
}
|
||
}
|
||
wxArrayInt rows = GetSelectedRows();
|
||
size_t numRows = GetNumberRows();
|
||
bool isRowsArray = rows.GetCount() > 0;
|
||
if (isRowsArray) numRows = rows.GetCount();
|
||
wxString bg = GetGridRowLabelWindow()->GetBackgroundColour().GetAsString(wxC2S_HTML_SYNTAX);
|
||
wxString head;
|
||
head = wxString::Format("<tr style=\"font-weight: bold; background: %s;\">", bg);
|
||
htm += wxString::Format("TD#cn { width: %dpx;font-weight: bold; background: %s;}\n", GetRowLabelSize(), bg);
|
||
head += wxString::Format("<td id=\"cn\"></td>");
|
||
int sumWidth = GetRowLabelSize();
|
||
for (int i = 0; i < cols.Count(); i++)
|
||
{
|
||
long columnPos = cols.Item(i);
|
||
int w = GetColWidth(columnPos);
|
||
sumWidth += w + 2;
|
||
htm += wxString::Format("TD#c%d { width: %dpx;}\n", i, w);
|
||
head += wxString::Format("<td id=\"c%d\">%s</td>", i, GetColumnName(columnPos));
|
||
}
|
||
head += "</tr>\n";
|
||
htm += "</style></head><body>";
|
||
htm.Replace("90%", wxString::Format("%dpx", sumWidth));
|
||
|
||
htm += htmlquery;
|
||
htm += "<br><table cellspacing=\"0\" cellpadding=\"0\" id=\"maket\">";
|
||
// AppendColumnHeader(str, cols);
|
||
htm += head;
|
||
for (int i = 0; i < numRows; i++)
|
||
{
|
||
long rowPos = i;
|
||
if (isRowsArray) rowPos = rows.Item(i);
|
||
if (GetRowSize(rowPos) == 0) continue;
|
||
htm += "<tr>\n";
|
||
htm += wxString::Format("<td id=\"cn\"><pre>%ld</pre></td>", rowPos + 1);
|
||
for (int c = 0; c < cols.Count(); c++) {
|
||
wxString text = GetCellValue(rowPos, cols[c]);
|
||
htm += wxString::Format("<td id=\"c%d\"><pre>%s</pre></td>", c, escapeHtml(text, true));
|
||
}
|
||
htm += "</tr>\n";
|
||
//wxString cname = GetColumnName(cols[c]);
|
||
|
||
}
|
||
htm += "</table>";
|
||
|
||
if (wxTheClipboard->Open())
|
||
{
|
||
wxDataObjectComposite* dataobj = new wxDataObjectComposite();
|
||
dataobj->Add(new wxTextDataObject(htm));
|
||
dataobj->Add(new wxHTMLDataObject(htm));
|
||
wxTheClipboard->SetData(dataobj);
|
||
wxTheClipboard->Close();
|
||
}
|
||
return 0;
|
||
}
|
||
int ctlSQLGrid::Copy(int gensql)
|
||
{
|
||
wxString str, tmp, linedelim = "";
|
||
int copied = 0;
|
||
size_t i;
|
||
generatesql = gensql;
|
||
//sqlResultTable* t = (sqlResultTable*)GetTable();
|
||
wxString sql = sqlquerytext.Lower();
|
||
int j = 0;
|
||
wxChar c;
|
||
wxString tn = wxEmptyString;
|
||
while ((j = sql.find("from", j)) > -1) {
|
||
j = j + 4;
|
||
c = sql[j];
|
||
i = j;
|
||
while (c == ' ' || c == '\t' || c == '\n' || c == '\r') {
|
||
i++;
|
||
c = sql[i];
|
||
}
|
||
j = i;
|
||
if (c == '(') {
|
||
continue;
|
||
}
|
||
while (c != ' ' && c != '\t' && c != '\n' && c != '\r' && c != ',' && c != '(' && c != ')' && c != ';') {
|
||
j++;
|
||
if (sql.Len() == j) break;
|
||
c = sql[j];
|
||
}
|
||
tn = sql.SubString(i, j - 1); // table name
|
||
if (sql.Len() == j) break;
|
||
j = j + 1;
|
||
i = j;
|
||
if (sql.Len() == j) break;
|
||
c = sql[j];
|
||
while (c > ' ' && c != ',' && c != '(' && c != ')') {
|
||
j++;
|
||
if (sql.Len() == j) break;
|
||
c = sql[j];
|
||
}
|
||
if (j > i) {
|
||
wxString al = sql.SubString(i, j - 1); // alias name
|
||
if (al.StartsWith("where")
|
||
|| al.StartsWith("order")
|
||
|| al.StartsWith("limit")
|
||
) break;
|
||
tn = al;
|
||
}
|
||
break;
|
||
}
|
||
|
||
if (gensql == 2) linedelim = ",";
|
||
else if (gensql == 3) linedelim = " or ";
|
||
int lenrow = 0;
|
||
|
||
if (GetSelectedRows().GetCount())
|
||
{
|
||
AppendColumnHeader(str, 0, (GetNumberCols() - 1));
|
||
|
||
wxArrayInt rows = GetSelectedRows();
|
||
for (i = 0; i < rows.GetCount(); i++)
|
||
{
|
||
tmp = GetExportLine(rows.Item(i));
|
||
lenrow += tmp.Len() + linedelim.Len();
|
||
if (tmp.IsEmpty()) continue;
|
||
if (!tn.IsEmpty() && (generatesql == 1)) tmp.Replace("tbl", tn, false);
|
||
str.Append(tmp);
|
||
if (i < rows.GetCount() - 1 && (generatesql > 1)) str.Append(linedelim);
|
||
if (rows.GetCount() > 1)
|
||
{
|
||
bool delim = true;
|
||
if ((generatesql > 1) && (lenrow < 50))
|
||
delim = false;
|
||
else
|
||
{
|
||
lenrow = 0;
|
||
}
|
||
if (delim) str.Append(END_OF_LINE);
|
||
}
|
||
}
|
||
|
||
copied = rows.GetCount();
|
||
}
|
||
else if (GetSelectedCols().GetCount())
|
||
{
|
||
wxArrayInt cols = GetSelectedCols();
|
||
size_t numRows = GetNumberRows();
|
||
|
||
AppendColumnHeader(str, cols);
|
||
|
||
for (i = 0; i < numRows; i++)
|
||
{
|
||
tmp = GetExportLine(i, cols);
|
||
lenrow += tmp.Len() + linedelim.Len();
|
||
if (!tn.IsEmpty() && (generatesql == 1)) tmp.Replace("tbl", tn, false);
|
||
str.Append(tmp);
|
||
if (i < (numRows - 1) && (generatesql > 1)) str.Append(linedelim);
|
||
if (numRows > 1)
|
||
{
|
||
bool delim = true;
|
||
if ((generatesql > 1) && (lenrow < 50))
|
||
delim = false;
|
||
else
|
||
{
|
||
lenrow = 0;
|
||
}
|
||
if (delim) str.Append(END_OF_LINE);
|
||
}
|
||
}
|
||
copied = numRows;
|
||
}
|
||
else if (GetSelectionBlockTopLeft().GetCount() > 0 &&
|
||
GetSelectionBlockBottomRight().GetCount() > 0)
|
||
{
|
||
unsigned int x1, x2, y1, y2;
|
||
int count = GetSelectionBlockTopLeft().GetCount();
|
||
|
||
x1 = GetSelectionBlockTopLeft()[0].GetCol();
|
||
x2 = GetSelectionBlockBottomRight()[0].GetCol();
|
||
y1 = GetSelectionBlockTopLeft()[0].GetRow();
|
||
y2 = GetSelectionBlockBottomRight()[0].GetRow();
|
||
copied = 0;
|
||
AppendColumnHeader(str, x1, x2);
|
||
selMerge m;
|
||
for (size_t n = 0; n < count; n++)
|
||
{
|
||
x1 = GetSelectionBlockTopLeft()[n].GetCol();
|
||
x2 = GetSelectionBlockBottomRight()[n].GetCol();
|
||
y1 = GetSelectionBlockTopLeft()[n].GetRow();
|
||
y2 = GetSelectionBlockBottomRight()[n].GetRow();
|
||
if (generatesql > 1) {
|
||
m.addRange(y1, y2, x1, x2);
|
||
}
|
||
else
|
||
{
|
||
for (i = y1; i <= y2; i++)
|
||
{
|
||
tmp = GetExportLine(i, x1, x2);
|
||
lenrow += tmp.Len() + linedelim.Len();
|
||
if (!tn.IsEmpty() && (generatesql == 1)) tmp.Replace("tbl", tn, false);
|
||
str.Append(tmp);
|
||
if (i < y2 && (generatesql > 1)) str.Append(linedelim);
|
||
if (y2 > y1)
|
||
{
|
||
bool delim = true;
|
||
if ((generatesql > 1) && (lenrow < 50))
|
||
delim = false;
|
||
else
|
||
{
|
||
lenrow = 0;
|
||
}
|
||
if (delim) str.Append(END_OF_LINE);
|
||
}
|
||
}
|
||
|
||
}
|
||
copied = copied + (y2 - y1 + 1);
|
||
}
|
||
if (generatesql > 1) {
|
||
auto g = m.getmap();
|
||
wxArrayInt cols;
|
||
int maxr = g.size();
|
||
int i = 1;
|
||
for (const auto& pair : g) {
|
||
int r = pair.first;
|
||
cols.Clear();
|
||
m.setArrayColumns(r, cols);
|
||
str.Append(GetExportLine(r, cols));
|
||
if (i < maxr) str.Append(linedelim);
|
||
i++;
|
||
}
|
||
}
|
||
}
|
||
else
|
||
{
|
||
int row, col;
|
||
if (generatesql > 1) {
|
||
wxGridCellCoordsArray cord = GetSelectedCells();
|
||
int count = cord.GetCount();
|
||
int curr_row = 1000000000;
|
||
int next_row = 1000000000;
|
||
|
||
for (size_t n = 0; n < count; n++)
|
||
{
|
||
wxGridCellCoords& coords = cord[n];
|
||
if (coords.GetRow() < curr_row) curr_row = coords.GetRow();
|
||
}
|
||
while (curr_row != 1000000000)
|
||
{
|
||
wxArrayInt colsNum;
|
||
next_row = 1000000000;
|
||
for (size_t n = 0; n < count; n++)
|
||
{
|
||
wxGridCellCoords& coords = cord[n];
|
||
//wxString msg;
|
||
//msg.Printf(wxT("<22><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD> row=%d col=%d.\n"), coords.GetRow(), coords.GetCol());
|
||
//wxMessageBox(msg, wxT("About coord"), wxOK | wxICON_INFORMATION, this);
|
||
int r = coords.GetRow();
|
||
if (r == curr_row) {
|
||
colsNum.Add(coords.GetCol());
|
||
}
|
||
else if (r > curr_row && r < next_row) next_row = r;
|
||
|
||
}
|
||
colsNum.Sort(compare_int);
|
||
if (generatesql == 2) AppendColumnHeader(str, colsNum);
|
||
tmp = GetExportLine(curr_row, colsNum);
|
||
str.Append(tmp);
|
||
lenrow += tmp.Len() + linedelim.Len();
|
||
if ((next_row != 1000000000) && (generatesql == 3)) str.Append(linedelim);
|
||
if ((next_row != 1000000000) && (generatesql == 2)) str.Append(") or ");
|
||
{
|
||
bool delim = true;
|
||
if ((generatesql > 1) && (lenrow < 50))
|
||
delim = false;
|
||
else
|
||
{
|
||
lenrow = 0;
|
||
}
|
||
if (delim) str.Append(END_OF_LINE);
|
||
}
|
||
curr_row = next_row;
|
||
copied++;
|
||
}
|
||
}
|
||
else {
|
||
row = GetGridCursorRow();
|
||
col = GetGridCursorCol();
|
||
|
||
AppendColumnHeader(str, col, col);
|
||
tmp = GetExportLine(row, col, col);
|
||
if (!tn.IsEmpty() && (generatesql == 1)) tmp.Replace("tbl", tn, false);
|
||
str.Append(tmp);
|
||
copied = 1;
|
||
}
|
||
}
|
||
if (copied && (generatesql == 2)) str.Append(")");
|
||
if (copied && wxTheClipboard->Open())
|
||
{
|
||
wxTheClipboard->SetData(new wxTextDataObject(str));
|
||
wxTheClipboard->Close();
|
||
}
|
||
else
|
||
{
|
||
copied = 0;
|
||
}
|
||
|
||
return copied;
|
||
}
|
||
|
||
void ctlSQLGrid::OnLabelDoubleClick(wxGridEvent& event)
|
||
{
|
||
int maxHeight, maxWidth;
|
||
GetClientSize(&maxWidth, &maxHeight);
|
||
int row = event.GetRow();
|
||
int col = event.GetCol();
|
||
|
||
int extent, extentWant = 0;
|
||
|
||
if (row >= 0)
|
||
{
|
||
for (col = 0; col < GetNumberCols(); col++)
|
||
{
|
||
extent = GetBestSize(row, col).GetHeight();
|
||
if (extent > extentWant)
|
||
extentWant = extent;
|
||
}
|
||
|
||
extentWant += EXTRAEXTENT_HEIGHT;
|
||
extentWant = wxMax(extentWant, GetRowMinimalAcceptableHeight());
|
||
extentWant = wxMin(extentWant, maxHeight * 3 / 4);
|
||
int currentHeight = GetRowHeight(row);
|
||
|
||
if (currentHeight >= maxHeight * 3 / 4 || currentHeight == extentWant)
|
||
extentWant = GetRowMinimalAcceptableHeight();
|
||
else if (currentHeight < maxHeight / 4)
|
||
extentWant = wxMin(maxHeight / 4, extentWant);
|
||
else if (currentHeight < maxHeight / 2)
|
||
extentWant = wxMin(maxHeight / 2, extentWant);
|
||
else if (currentHeight < maxHeight * 3 / 4)
|
||
extentWant = wxMin(maxHeight * 3 / 4, extentWant);
|
||
|
||
if (extentWant != currentHeight)
|
||
{
|
||
BeginBatch();
|
||
if (IsCellEditControlShown())
|
||
{
|
||
HideCellEditControl();
|
||
SaveEditControlValue();
|
||
}
|
||
|
||
SetRowSize(row, extentWant);
|
||
EndBatch();
|
||
}
|
||
}
|
||
else if (col >= 0)
|
||
{
|
||
// Holding Ctrl or Meta switches back to automatic column's sizing
|
||
if (event.ControlDown() || event.CmdDown())
|
||
{
|
||
colSizes.erase(GetColKeyValue(col));
|
||
BeginBatch();
|
||
if (IsCellEditControlShown())
|
||
{
|
||
HideCellEditControl();
|
||
SaveEditControlValue();
|
||
}
|
||
AutoSizeColumn(col, false);
|
||
EndBatch();
|
||
}
|
||
else // toggle between some predefined sizes
|
||
{
|
||
|
||
if (col < (int)colMaxSizes.GetCount() && colMaxSizes[col] >= 0)
|
||
extentWant = colMaxSizes[col];
|
||
else
|
||
{
|
||
for (row = 0; row < GetNumberRows(); row++)
|
||
{
|
||
if (CheckRowPresent(row))
|
||
{
|
||
extent = GetBestSize(row, col).GetWidth();
|
||
if (extent > extentWant)
|
||
extentWant = extent;
|
||
}
|
||
}
|
||
}
|
||
|
||
extentWant += EXTRAEXTENT_WIDTH;
|
||
extentWant = wxMax(extentWant, GetColMinimalAcceptableWidth());
|
||
extentWant = wxMin(extentWant, maxWidth * 3 / 4);
|
||
int currentWidth = GetColSize(col);
|
||
|
||
if (currentWidth >= maxWidth * 3 / 4 || currentWidth == extentWant)
|
||
extentWant = GetColMinimalAcceptableWidth();
|
||
else if (currentWidth < maxWidth / 4)
|
||
extentWant = wxMin(maxWidth / 4, extentWant);
|
||
else if (currentWidth < maxWidth / 2)
|
||
extentWant = wxMin(maxWidth / 2, extentWant);
|
||
else if (currentWidth < maxWidth * 3 / 4)
|
||
extentWant = wxMin(maxWidth * 3 / 4, extentWant);
|
||
|
||
if (extentWant != currentWidth)
|
||
{
|
||
BeginBatch();
|
||
if (IsCellEditControlShown())
|
||
{
|
||
HideCellEditControl();
|
||
SaveEditControlValue();
|
||
}
|
||
SetColSize(col, extentWant);
|
||
EndBatch();
|
||
colSizes[GetColKeyValue(col)] = extentWant;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
void ctlSQLGrid::OnMouseEvent(wxMouseEvent& event)
|
||
{
|
||
if (event.RightDown()) {
|
||
wxGridEvent ev;
|
||
OnCellRightClick(ev);
|
||
return;
|
||
}
|
||
event.Skip();
|
||
}
|
||
void ctlSQLGrid::OnShowPopup(wxThreadEvent& event) {
|
||
// wxMessageBox("omshowpopup "+event.GetString(), "msg");
|
||
wxString s = event.GetString();
|
||
wxPoint p = rpos;
|
||
wxPoint p1(rpos);
|
||
wxString bg;
|
||
wxColour bgColor = settings->GetSQLBoxColourBackground();
|
||
if (settings->GetSQLBoxUseSystemBackground())
|
||
{
|
||
bgColor = wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW);
|
||
}
|
||
bg = bgColor.GetAsString(wxC2S_HTML_SYNTAX);
|
||
long long lenstr=s.Len();
|
||
bool bigtext=lenstr >MAX_TEXT_LEN_COLORIZE;
|
||
if (lenstr > MAX_TEXT_LEN_WARNING) {
|
||
wxString h = NumToStrHuman(wxLongLong(lenstr));
|
||
if (wxMessageBox(wxString::Format(_("The line size is [ %s ] characters, do you want to continue?"),h ), _("Confirm"), wxYES_NO, this)!=wxYES) return;
|
||
|
||
}
|
||
// parse context
|
||
wxRegEx r(L"(?im)(select|from|where|set|insert|into|delete)\\b", wxRE_NEWLINE);
|
||
int cnt = 0;
|
||
if (r.IsValid()) {
|
||
size_t start=0;
|
||
std::unordered_set<wxString> unic;
|
||
while (r.Matches(s.Mid(start))) {
|
||
size_t start2 = 0, len2 = 0;
|
||
r.GetMatch(&start2, &len2, 1);
|
||
unic.insert(s.Mid(start + start2,len2));
|
||
r.GetMatch(&start2, &len2, 0);
|
||
start = start + start2 + len2;
|
||
}
|
||
cnt = unic.size();
|
||
}
|
||
if (cnt >= 2 && !bigtext) {
|
||
wxString q = s;
|
||
wxString html;
|
||
ctlSQLBox* box = new ctlSQLBox((wxWindow*) winMain, CTL_SQLQUERY, wxDefaultPosition, wxSize(0, 0), wxTE_MULTILINE | wxTE_RICH2);
|
||
box->SetText(q);
|
||
int l = q.Length();
|
||
box->Colourise(0, box->GetLength());
|
||
//bg = box->SetSQLBoxColourBackground(false).GetAsString(wxC2S_CSS_SYNTAX);
|
||
html = box->TextToHtml(0, box->GetLength(),false);
|
||
delete box;
|
||
s = html;
|
||
s = "<html><body BGCOLOR=\"" + bg + "\">" + s + "</body></html>";
|
||
}
|
||
else {
|
||
//simple text
|
||
PreviewHtml v;
|
||
wxString tt=v.Preview(s,fmtpreview::AUTO);
|
||
s = tt;
|
||
}
|
||
delete m_Popup;
|
||
// screen size
|
||
wxPoint posScreen;
|
||
wxSize sizeScreen;
|
||
const int displayNum = wxDisplay::GetFromPoint(p);
|
||
if (displayNum != wxNOT_FOUND)
|
||
{
|
||
const wxRect rectScreen = wxDisplay(displayNum).GetGeometry();
|
||
posScreen = rectScreen.GetPosition();
|
||
sizeScreen = rectScreen.GetSize();
|
||
}
|
||
else // outside of any display?
|
||
{
|
||
// just use the primary one then
|
||
posScreen = wxPoint(0, 0);
|
||
sizeScreen = wxGetDisplaySize();
|
||
}
|
||
|
||
wxSize rr(350, 70);
|
||
|
||
if (bigtext) {
|
||
rr.x=(int) sizeScreen.x*0.8;rr.y=sizeScreen.y*0.7;
|
||
}
|
||
FunctionPGHelper fh(s);
|
||
wxString key = "content";
|
||
m_Popup = new popuphelp(this, key, &fh, p, rr);
|
||
if (m_Popup && m_Popup->IsValid() && rr != m_Popup->GetSizePopup() && !bigtext) {
|
||
// recreate with new size
|
||
rr = m_Popup->GetSizePopup();
|
||
delete m_Popup;
|
||
m_Popup = new popuphelp(this, key, &fh, p, rr);
|
||
|
||
}
|
||
if (m_Popup && m_Popup->IsValid()) {
|
||
//m_PopupHelp->UpdateWindowUI(true);
|
||
wxSize top_sz = m_Popup->GetSizePopup();
|
||
wxSize top_new(top_sz);
|
||
wxPoint oldp(p);
|
||
if (p.x + top_new.x > sizeScreen.x) p.x = sizeScreen.x - top_new.x - 20;
|
||
if (p.y + top_new.y > sizeScreen.y) p.y = sizeScreen.y - top_new.y - 20;
|
||
if (oldp == p) p.x = p.x + 20;
|
||
m_Popup->Move(p);
|
||
wxRect r = m_Popup->GetScreenRect();
|
||
if (r.Contains(p1)) {
|
||
//wxMouseEvent mv(wxEVT_MOTION,);
|
||
//wxGetMousePosition();
|
||
}
|
||
//m_PopupHelp->Position(p, wxSize(0, 17));
|
||
m_Popup->Popup();
|
||
//wxPopupTransientWindow
|
||
}
|
||
|
||
}
|
||
void ctlSQLGrid::OnCellRightClick(wxGridEvent& event)
|
||
{
|
||
int row = event.GetRow();
|
||
int col = event.GetCol();
|
||
wxPoint p;
|
||
if (row != -1 && col != -1) {
|
||
rrow = row;
|
||
rcol = col;
|
||
rpos = ClientToScreen(event.GetPosition());
|
||
wxThreadEvent e(wxEVT_THREAD);
|
||
//e.SetString(s);
|
||
e.SetString(GetCellValue(row, col));
|
||
//GetEventHandler()->AddPendingEvent(e);
|
||
wxPostEvent(this, e);
|
||
//event.Skip();
|
||
return;
|
||
}
|
||
else
|
||
{
|
||
row = rrow;
|
||
col = rcol;
|
||
p = rpos;
|
||
}
|
||
wxString s = GetCellValue(row, col);
|
||
}
|
||
void ctlSQLGrid::OnLabelClick(wxGridEvent& event)
|
||
{
|
||
int row = event.GetRow();
|
||
int col = event.GetCol();
|
||
if (row >= 0 && grp) {
|
||
grp->VisibleGroup(row, GetRowSize(row + 1) == 0);
|
||
Refresh();
|
||
return;
|
||
}
|
||
if (col >= 0 && (event.AltDown()))
|
||
{
|
||
// continue for sort event
|
||
if (IsSort()) {
|
||
sqlResultTable* t = (sqlResultTable*)GetTable();
|
||
t->setSortColumn(col);
|
||
return;
|
||
}
|
||
}
|
||
// add support for (de)selecting multiple rows and cols with Control pressed
|
||
else if (row >= 0 && (event.ControlDown() || event.CmdDown()))
|
||
{
|
||
if (GetSelectedRows().Index(row) == wxNOT_FOUND)
|
||
SelectRow(row, true);
|
||
else
|
||
DeselectRow(row);
|
||
}
|
||
else if (col >= 0 && (event.ControlDown() || event.CmdDown()))
|
||
{
|
||
if (GetSelectedCols().Index(col) == wxNOT_FOUND)
|
||
SelectCol(col, true);
|
||
else
|
||
DeselectCol(col);
|
||
event.Skip();
|
||
}
|
||
else
|
||
event.Skip();
|
||
}
|
||
|
||
void ctlSQLGrid::AutoSizeColumn(int col, bool setAsMin, bool doLimit)
|
||
{
|
||
ColKeySizeHashMap::iterator it = colSizes.find(GetColKeyValue(col));
|
||
if (it != colSizes.end()) // Restore user-specified size
|
||
SetColSize(col, it->second);
|
||
else
|
||
wxGrid::AutoSizeColumn(col, setAsMin);
|
||
|
||
if (doLimit)
|
||
{
|
||
int newSize, oldSize;
|
||
int maxSize, totalSize = 0, availSize;
|
||
|
||
oldSize = GetColSize(col);
|
||
availSize = GetClientSize().GetWidth() - GetRowLabelSize();
|
||
maxSize = availSize / 2;
|
||
for (int i = 0; i < GetNumberCols(); i++)
|
||
totalSize += GetColSize(i);
|
||
|
||
if (oldSize > maxSize && totalSize > availSize)
|
||
{
|
||
totalSize -= oldSize;
|
||
/* Shrink wide column to maxSize.
|
||
* If the rest of the columns are short, make sure to use all the remaining space,
|
||
* but no more than oldSize (which is enough according to AutoSizeColumns())
|
||
*/
|
||
newSize = wxMin(oldSize, wxMax(maxSize, availSize - totalSize));
|
||
SetColSize(col, newSize);
|
||
}
|
||
}
|
||
}
|
||
|
||
void ctlSQLGrid::AutoSizeColumns(bool setAsMin)
|
||
{
|
||
wxCoord newSize, oldSize, maxH = 0, newSizeH = 0;
|
||
wxCoord maxSize, totalSize = 0, availSize;
|
||
int col, nCols = GetNumberCols();
|
||
int row, nRows = GetNumberRows();
|
||
colMaxSizes.Empty();
|
||
|
||
/* We need to check each cell's width to choose best. wxGrid::AutoSizeColumns()
|
||
* is good, but looping through long result sets gives a noticeable slowdown.
|
||
* Thus we'll check every first 500 cells for each column.
|
||
*/
|
||
|
||
// First pass: auto-size columns
|
||
for (col = 0; col < nCols; col++)
|
||
{
|
||
ColKeySizeHashMap::iterator it = colSizes.find(GetColKeyValue(col));
|
||
if (it != colSizes.end()) // Restore user-specified size
|
||
{
|
||
newSize = it->second;
|
||
colMaxSizes.Add(-1);
|
||
}
|
||
else
|
||
{
|
||
wxClientDC dc(GetGridWindow());
|
||
newSize = 0;
|
||
// get cells's width
|
||
for (row = 0; row < wxMin(nRows, 500); row++)
|
||
{
|
||
wxSize size = GetBestSize(row, col);
|
||
if (size.x > newSize)
|
||
newSize = size.x;
|
||
if (size.y > newSizeH)
|
||
newSizeH = size.y;
|
||
}
|
||
// get column's label width
|
||
wxCoord w, h;
|
||
dc.SetFont(GetLabelFont());
|
||
dc.GetMultiLineTextExtent(GetColLabelValue(col), &w, &h);
|
||
if (GetColLabelTextOrientation() == wxVERTICAL)
|
||
w = h;
|
||
|
||
if (h > maxH)
|
||
maxH = h;
|
||
if (w > newSize)
|
||
newSize = w;
|
||
|
||
if (!newSize)
|
||
newSize = GetRowLabelSize();
|
||
else
|
||
// leave some space around text
|
||
newSize += FromDIP(EXTRAEXTENT_WIDTH);
|
||
|
||
colMaxSizes.Add(newSize);
|
||
}
|
||
SetColSize(col, newSize);
|
||
totalSize += newSize;
|
||
}
|
||
SetColLabelSize(maxH + FromDIP(EXTRAEXTENT_HEIGHT));
|
||
availSize = GetClientSize().GetWidth() - GetRowLabelSize();
|
||
//int newDef = GetDefaultRowSize()+FromDIP(1);
|
||
//SetDefaultRowSize(newDef, true);
|
||
// Second pass: shrink wide columns if exceeded available width
|
||
if (totalSize > availSize)
|
||
{
|
||
// A wide column shouldn't take up more than 50% of the visible space
|
||
maxSize = availSize / 2;
|
||
for (col = 0; col < nCols; col++)
|
||
{
|
||
oldSize = GetColSize(col);
|
||
// Is too wide and no user-specified size
|
||
if (oldSize > maxSize && !(col < (int)colMaxSizes.GetCount() && colMaxSizes[col] == -1))
|
||
{
|
||
totalSize -= oldSize;
|
||
/* Shrink wide column to maxSize.
|
||
* If the rest of the columns are short, make sure to use all the remaining space,
|
||
* but no more than oldSize (which is enough according to first pass)
|
||
*/
|
||
newSize = wxMin(oldSize, wxMax(maxSize, availSize - totalSize));
|
||
SetColSize(col, newSize);
|
||
totalSize += newSize;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
wxString ctlSQLGrid::GetColKeyValue(int col)
|
||
{
|
||
wxString colKey = wxString::Format(wxT("%d:"), col) + GetColLabelValue(col);
|
||
return colKey;
|
||
}
|
||
|
||
wxSize ctlSQLGrid::GetBestSize(int row, int col)
|
||
{
|
||
wxSize size;
|
||
|
||
wxGridCellAttr* attr = GetCellAttr(row, col);
|
||
wxGridCellRenderer* renderer = attr->GetRenderer(this, row, col);
|
||
if (renderer)
|
||
{
|
||
wxClientDC dc(GetGridWindow());
|
||
size = renderer->GetBestSize(*this, *attr, dc, row, col);
|
||
// int h = renderer->GetBestHeight(*this, *attr, dc, row, col, size.GetWidth())
|
||
size.SetHeight(size.GetHeight() + FromDIP(EXTRAEXTENT_HEIGHT));
|
||
renderer->DecRef();
|
||
}
|
||
|
||
attr->DecRef();
|
||
|
||
return size;
|
||
}
|
||
|
||
|
||
|
||
int recurse(ctlSQLGrid* g, int pos, int row, double& transfer) {
|
||
wxString text;
|
||
double leveltime = 0; //actual time level
|
||
double lastnode = 0;
|
||
while (row < g->GetNumberRows()) {
|
||
text = g->GetCellValue(row, 0);
|
||
int p = 0;
|
||
while (text.at(p) == ' ')
|
||
{
|
||
p++;
|
||
}
|
||
if (p == pos) {
|
||
//
|
||
lastnode = 0;
|
||
if (text.at(p) == '-') {
|
||
//
|
||
double m = 1;
|
||
// -> Nested Loop (cost=205.13..273.44 rows=4 width=188) (actual time=13.157..13.157 rows=0 loops=1)
|
||
bool isstd = false;
|
||
if (text.Contains("(never executed)")) {
|
||
isstd = true;
|
||
}
|
||
wxRegEx foundstr(wxT("actual time=.*?\\.\\.([0-9.]+).*?loops=([0-9]+)\\)"), wxRE_ADVANCED);
|
||
if (foundstr.Matches(text)) {
|
||
wxString v = foundstr.GetMatch(text, 1);
|
||
v.ToCDouble(&lastnode);
|
||
v = foundstr.GetMatch(text, 2);
|
||
v.ToDouble(&m);
|
||
lastnode = lastnode * m;
|
||
leveltime = leveltime + lastnode;
|
||
}
|
||
if (isstd)
|
||
g->grp->ColoriseRow(row, wxColour(224, 255, 224)); // green
|
||
else
|
||
g->grp->ColoriseRow(row, wxColour(248, 240, 130)); // yellow
|
||
|
||
}
|
||
else
|
||
{
|
||
g->grp->ColoriseRow(row, wxColour(224, 255, 224)); // green
|
||
g->GetTable()->SetRowLabelValue(row, wxEmptyString);
|
||
}
|
||
row++;
|
||
continue;
|
||
} if (p < pos) {
|
||
// end level
|
||
// leveltime <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||
transfer = leveltime;
|
||
return row;
|
||
} if (p > pos) {
|
||
// nested level
|
||
//g->SetRowGroup(row-1);
|
||
wxString s;
|
||
int newrow = recurse(g, p, row, transfer);
|
||
//
|
||
//leveltime=leveltime+transfer;
|
||
//GroupRows *u=g->getgroup();
|
||
double tt = lastnode - transfer;
|
||
text = g->GetCellValue(row - 1, 0);
|
||
if ((text.Find("Append") > 0)
|
||
|| (text.Find("Gather") > 0))
|
||
tt = lastnode;
|
||
g->grp->AddGroup(row - 1, newrow - 1, tt);
|
||
s << (tt);
|
||
s = s + wxT("-");
|
||
g->GetTable()->SetRowLabelValue(row - 1, s);
|
||
|
||
row = newrow;
|
||
}
|
||
|
||
}
|
||
return row;
|
||
}
|
||
void ctlSQLGrid::SetRowGroup(int row) { };
|
||
bool ctlSQLGrid::FullArrayCollapseRowsPlan(bool clear)
|
||
{
|
||
//wxString colKey = wxString::Format(wxT("%d:"), col) + GetColLabelValue(col);
|
||
wxString text;
|
||
//for(int row = 0; row < GetNumberRows(); ++row)
|
||
|
||
if (grp) { delete grp; }
|
||
if (clear) { grp = NULL; return true; }
|
||
grp = new GroupRows(this);
|
||
double transfersum = 0;
|
||
int r = recurse(this, 0, 0, transfersum);
|
||
grp->CalcTime();
|
||
//for(int row = 0; row < GetNumberRows(); ++row) {
|
||
// text = GetCellValue(row, 0);
|
||
// //if (row%2==0) SetRowAttr(row,pAttr);
|
||
|
||
//}
|
||
|
||
return true;
|
||
}
|
||
|
||
//// CursorCellRenderer
|
||
|
||
void CursorCellRenderer::Draw(wxGrid& grid, wxGridCellAttr& attr, wxDC& dc,
|
||
const wxRect& rect, int row, int col, bool isSelected)
|
||
{
|
||
int hAlign, vAlign;
|
||
int sPos = -1;
|
||
bool multiline = false;
|
||
attr.GetAlignment(&hAlign, &vAlign);
|
||
//////////////////////////////////////////////////////////////////////////////
|
||
//CursorCellRenderer::Draw(grid, attr, dc, rect, row, col, isSelected); //
|
||
dc.SetBackgroundMode(wxSOLID);
|
||
bool istruncateLine=false;
|
||
wxString text = grid.GetCellValue(row, col);
|
||
int len= text.length();
|
||
bool isfirst=true;
|
||
bool isnumber=(hAlign == wxALIGN_RIGHT && len<20 && text.IsNumber());
|
||
// grey out fields if the grid is disabled
|
||
retry:
|
||
if (grid.IsEnabled())
|
||
{
|
||
istruncateLine=text.Right(5)=="(...)";
|
||
if (isSelected)
|
||
{
|
||
wxColour clr;
|
||
if (wxWindow::FindFocus() == grid.GetGridWindow())
|
||
clr = grid.GetSelectionBackground();
|
||
else
|
||
clr = wxSystemSettings::GetColour(wxSYS_COLOUR_BTNSHADOW);
|
||
|
||
|
||
dc.SetBrush(*wxTheBrushList->FindOrCreateBrush(clr));
|
||
}
|
||
else
|
||
{
|
||
wxColor color;
|
||
color.Set(239, 228, 176);
|
||
if ((sPos = text.Find(wxT('\n'))) != wxNOT_FOUND) {
|
||
dc.SetBrush(*wxTheBrushList->FindOrCreateBrush(color));
|
||
multiline = true;
|
||
}
|
||
else
|
||
dc.SetBrush(*wxTheBrushList->FindOrCreateBrush(attr.GetBackgroundColour()));
|
||
}
|
||
// replace \t to u+2192
|
||
wxUniChar cc = 8594;
|
||
text.Replace("\t", cc);
|
||
}
|
||
else
|
||
{
|
||
dc.SetBrush(*wxTheBrushList->FindOrCreateBrush(wxSystemSettings::GetColour(wxSYS_COLOUR_BTNFACE)));
|
||
}
|
||
|
||
dc.SetPen(*wxTRANSPARENT_PEN);
|
||
dc.DrawRectangle(rect);
|
||
//////////////////////////////////////////////////////////////////////////////
|
||
SetTextColoursAndFont(grid, attr, dc, isSelected);
|
||
ctlSQLGrid* ctrl = static_cast<ctlSQLGrid*>(&grid);
|
||
if (!ctrl->searchStr.IsEmpty()) {
|
||
int pp;
|
||
pp = text.Find(ctrl->searchStr);
|
||
if (pp >= 0) {
|
||
wxArrayString lines;
|
||
grid.StringToLines(text, lines);
|
||
wxRect r;
|
||
r.y = rect.y;
|
||
dc.SetBrush(*wxYELLOW_BRUSH);
|
||
size_t nLines = lines.GetCount();
|
||
for (size_t l = 0; l < nLines; l++)
|
||
{
|
||
const wxString& line = lines[l];
|
||
pp = line.Find(ctrl->searchStr);
|
||
if (line.empty() || (pp == -1))
|
||
{
|
||
r.y += dc.GetCharHeight();
|
||
continue;
|
||
}
|
||
|
||
int lineWidth, lineWidthP, lineHeight, start = 0;
|
||
int dopx=0;
|
||
wxString pref;
|
||
if (hAlign == wxALIGN_RIGHT) {
|
||
start = pp + ctrl->searchStr.Len();
|
||
pref = line.substr(start);
|
||
if (isnumber) {
|
||
int ll=pref.length();
|
||
int num_sep=ll/3;
|
||
//if (ll % 3 == 0 && num_sep>0 ) num_sep--;
|
||
dopx=num_sep*thousands_pixel_sep;
|
||
}
|
||
}
|
||
else
|
||
pref = line.substr(start, pp);
|
||
|
||
dc.GetTextExtent(pref, &lineWidthP, &lineHeight);
|
||
lineWidthP+=dopx;
|
||
r.x = rect.x + lineWidthP;
|
||
pref = line.substr(pp, ctrl->searchStr.Len());
|
||
dc.GetTextExtent(pref, &lineWidth, &lineHeight);
|
||
r.width = lineWidth;
|
||
r.height = lineHeight;
|
||
if (hAlign == wxALIGN_RIGHT) r.x = rect.x + (rect.width - lineWidth - lineWidthP);
|
||
if (!(r.y < (rect.y + rect.height))) { r.y = rect.y + rect.height - 5; r.height = 5; }
|
||
if (!((r.x < (rect.x + rect.width)))) { r.x = rect.x + rect.width - 5; r.width = 5; }
|
||
dc.DrawRoundedRectangle(r, 3);
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
|
||
if (!multiline) {
|
||
//int textWidth = dc.GetTextExtent(text).GetWidth();
|
||
wxEllipsizeMode mode(wxELLIPSIZE_END);
|
||
if (hAlign == wxALIGN_RIGHT) mode = wxELLIPSIZE_START;
|
||
const wxString& ellipsizedText = wxControl::Ellipsize
|
||
(
|
||
text,
|
||
dc,
|
||
mode,
|
||
rect.GetWidth() - 2,
|
||
wxELLIPSIZE_FLAGS_NONE
|
||
);
|
||
if (ellipsizedText != text)
|
||
text = ellipsizedText; // small width
|
||
else
|
||
{
|
||
bool isDraw=false;
|
||
if (isnumber && isfirst)
|
||
/* Add thousands separator */
|
||
{
|
||
int pos = text.find('.');
|
||
if (pos == wxString::npos)
|
||
pos = len;
|
||
int x=rect.GetRight()-1;
|
||
int yb=rect.GetTop()+1; //GRID_TEXT_MARGIN
|
||
int c=0;
|
||
while (pos > 0)
|
||
{
|
||
pos -= 3;
|
||
wxString tri;
|
||
if (pos >= 0)
|
||
{
|
||
tri=text.substr(pos,3);
|
||
} else tri=text.substr(0,pos+3);
|
||
|
||
wxSize tripl=dc.GetTextExtent(tri);
|
||
x=x-tripl.GetX();
|
||
if (c>0) x-=thousands_pixel_sep;
|
||
dc.DrawText(tri,x,yb);
|
||
c++;
|
||
}
|
||
int new_width=rect.GetRight()-x;
|
||
isfirst=!isfirst;
|
||
if (new_width>=rect.GetWidth()) goto retry; // small width
|
||
isDraw=true;
|
||
}
|
||
if (isDraw) return;
|
||
}
|
||
|
||
} // this draw one line
|
||
|
||
grid.DrawTextRectangle(dc, text,
|
||
rect, hAlign, vAlign);
|
||
if (istruncateLine) {
|
||
dc.SetPen(*wxRED_PEN);
|
||
dc.DrawLine(wxPoint(rect.x,rect.y+rect.GetHeight()-2),wxPoint(rect.x+rect.width,rect.y+rect.GetHeight()-2));
|
||
}
|
||
}
|
||
|
||
CursorCellRenderer::CursorCellRenderer(int thous_pixel_sep):wxGridCellStringRenderer() {
|
||
thousands_pixel_sep=thous_pixel_sep;
|
||
}
|
||
wxSize CursorCellRenderer::GetBestSize(wxGrid& grid,
|
||
wxGridCellAttr& attr,
|
||
wxDC& dc,
|
||
int row, int col){
|
||
dc.SetFont(attr.GetFont());
|
||
const wxString text=grid.GetCellValue(row, col);
|
||
wxSize sz=dc.GetMultiLineTextExtent(text);
|
||
int len=text.length();
|
||
if (thousands_pixel_sep !=0 && len<20 && text.IsNumber()) {
|
||
if (text[0]=='-') len--;
|
||
int num_sep=len/3;
|
||
if (len % 3 == 0 && num_sep>0 ) num_sep--;
|
||
sz.x=sz.x+num_sep*thousands_pixel_sep +1;
|
||
|
||
}
|
||
return sz;
|
||
}
|
||
|
||
|