mirror of
https://github.com/levinsv/pgadmin3.git
synced 2026-05-15 14:15:49 -06:00
Extended hints
В результатах запроса, нажатием правой кнопки мыши можно вызвать окно подсказки, с возможностью выделения содержимого и его копирования (Rbutton).
This commit is contained in:
parent
c2c44c18f1
commit
077de1ad7c
17 changed files with 4789 additions and 3946 deletions
|
|
@ -9,12 +9,27 @@
|
|||
#include <wx/textfile.h>
|
||||
#include <wx/filename.h>
|
||||
|
||||
extern sysSettings *settings;
|
||||
extern sysSettings* settings;
|
||||
|
||||
class FunctionPGHelper
|
||||
{
|
||||
public:
|
||||
FunctionPGHelper() {};
|
||||
/// <summary>
|
||||
/// Создать только переданный в конструкторе html текст с именем "content"
|
||||
/// </summary>
|
||||
/// <param name="content"></param>
|
||||
FunctionPGHelper(const wxString& content) {
|
||||
body.clear();
|
||||
Add("content", content);
|
||||
isload = true;
|
||||
};
|
||||
int Size() {
|
||||
return body.size();
|
||||
}
|
||||
void SetTimerClose(int ms) { m_interval = ms; }
|
||||
int GetTimerClose() { return m_interval; }
|
||||
void Add(const wxString& key, const wxString& v) { body.emplace(key, v); }
|
||||
wxString getHelpString(wxString fnd, bool isPart = true) {
|
||||
if (!isValid()) return wxEmptyString;
|
||||
auto search = body.find(fnd);
|
||||
|
|
@ -46,9 +61,9 @@ public:
|
|||
wxString getSqlCommandHelp(wxString fnd) {
|
||||
wxUniChar sep = wxFileName::GetPathSeparator();
|
||||
fnd.Replace(" ", "");
|
||||
wxString f = wxFindFirstFile(path + sep+"sql-"+fnd+"*.html");
|
||||
wxString last,txt;
|
||||
|
||||
wxString f = wxFindFirstFile(path + sep + "sql-" + fnd + "*.html");
|
||||
wxString last, txt;
|
||||
|
||||
int c = 0;
|
||||
while (!f.empty())
|
||||
{
|
||||
|
|
@ -61,7 +76,7 @@ public:
|
|||
if (last.empty()) {
|
||||
return wxEmptyString;
|
||||
}
|
||||
else if (c==1) {
|
||||
else if (c == 1) {
|
||||
return getHelpFile(last);
|
||||
}
|
||||
else {
|
||||
|
|
@ -100,6 +115,7 @@ public:
|
|||
}
|
||||
private:
|
||||
bool isload = false;
|
||||
int m_interval = -1;
|
||||
wxString path;
|
||||
std::map<wxString, wxString> body;
|
||||
void loadfile() {
|
||||
|
|
|
|||
149
include/utils/PreviewHtml.h
Normal file
149
include/utils/PreviewHtml.h
Normal file
|
|
@ -0,0 +1,149 @@
|
|||
#pragma once
|
||||
#include <wx/wx.h>
|
||||
|
||||
#define PREVIEW_SEP 1
|
||||
#define PREVIEW_DIGITS 2
|
||||
#define PREVIEW_WORD 4
|
||||
#define PREVIEW_SPACE 8
|
||||
#define PREVIEW_ENDFIELD 16
|
||||
#define PREVIEW_ENDROW 32
|
||||
#define PREVIEW_QUOTE 64
|
||||
#define CHKFLAG(val,par) ((val & par)>0)
|
||||
enum class fmtpreview {
|
||||
AUTO, AUTOVACCUM,CSV
|
||||
};
|
||||
|
||||
struct Element {
|
||||
wxString src;
|
||||
wxString html;
|
||||
int flags = 0;
|
||||
|
||||
} ;
|
||||
static wxString titles_log[] = {
|
||||
L"log_time",
|
||||
L"user_name",
|
||||
L"database_name",
|
||||
L"process_id",
|
||||
L"connection_from",
|
||||
L"session_id",
|
||||
L"session_line_num",
|
||||
L"command_tag",
|
||||
L"session_start_time",
|
||||
L"virtual_transaction_id",
|
||||
L"transaction_id",
|
||||
L"error_severity",
|
||||
L"sql_state_code",
|
||||
L"message",
|
||||
L"detail",
|
||||
L"hint",
|
||||
L"internal_query",
|
||||
L"internal_query_pos",
|
||||
L"context",
|
||||
L"query",
|
||||
L"query_pos",
|
||||
L"location",
|
||||
L"application_name",
|
||||
L"backend_type",
|
||||
L"leader_pid",
|
||||
L"query_id"
|
||||
};
|
||||
|
||||
class PreviewHtml
|
||||
{
|
||||
public:
|
||||
//void SetColors();
|
||||
PreviewHtml() { InitColor(); };
|
||||
wxString Preview(const wxString& txt, fmtpreview type);
|
||||
private:
|
||||
void InitColor();
|
||||
bool saveTokenIfNotEmpty(wxString& savestr, int flag) {
|
||||
if (savestr.Length() > 0) {
|
||||
wxString tmp = savestr;
|
||||
tmp=escapeHtml(tmp,true);
|
||||
tmp.Replace(" ", " ");
|
||||
if (CHKFLAG(flag, PREVIEW_ENDROW)) tmp = "<br>";
|
||||
if (CHKFLAG(flag, PREVIEW_DIGITS)) {
|
||||
int l = savestr.Length();
|
||||
if (l > 4 && !savestr.Contains('.')) {
|
||||
int dl = 3;
|
||||
wxString fmt;
|
||||
std::vector<wxString> dd;
|
||||
bool smalll = true;
|
||||
while (l > 0) {
|
||||
l = l - dl;
|
||||
if (l < 0) {
|
||||
dl = dl + l;
|
||||
l = 0;
|
||||
}
|
||||
wxString d3 = savestr.Mid(l, dl);
|
||||
if (smalll)
|
||||
dd.push_back("<font size=+1>" + d3 + "</font>");
|
||||
else
|
||||
dd.push_back(d3);
|
||||
smalll = !smalll;
|
||||
}
|
||||
for (auto i = dd.rbegin(); i != dd.rend(); i++)
|
||||
{
|
||||
fmt += *i;
|
||||
}
|
||||
tmp = fmt;
|
||||
}
|
||||
wxString t = wxString::Format("<font color=\"%s\">%s</font>", numcolor, tmp);
|
||||
tmp = t;
|
||||
|
||||
}
|
||||
if (CHKFLAG(flag, PREVIEW_QUOTE)) {
|
||||
wxString t = wxString::Format("<font color=\"%s\">%s</font>",quotecolor,tmp);
|
||||
tmp = t;
|
||||
}
|
||||
tokens.push_back({savestr,tmp,flag});
|
||||
savestr = "";
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
int FindElement(int start_pos, int flag_find, wxString& value_find, int is_what_find) {
|
||||
int p = start_pos;
|
||||
int rez = -1;
|
||||
while (p < tokens.size()) {
|
||||
Element t = tokens[p];
|
||||
bool f1 = is_what_find & 1;
|
||||
bool f2 = is_what_find & 2;
|
||||
bool r1 = false;
|
||||
bool r2 = false;
|
||||
if (f1 && CHKFLAG(t.flags, flag_find)) {
|
||||
r1 = true;
|
||||
}
|
||||
if (f2 && t.src==value_find ) {
|
||||
r2 = true;
|
||||
}
|
||||
if ((is_what_find == 3 && r1 && r2)
|
||||
|| (is_what_find == 2 && r2)
|
||||
|| (is_what_find == 1 && r1)
|
||||
) {
|
||||
rez = p;
|
||||
break;
|
||||
}
|
||||
p++;
|
||||
}
|
||||
return rez;
|
||||
}
|
||||
wxString generateHtml() {
|
||||
wxString s;
|
||||
for (size_t i = 0; i < tokens.size(); i++) {
|
||||
Element t = tokens[i];
|
||||
s += t.html;
|
||||
}
|
||||
// s = "<html><body BGCOLOR=\"" + bgcolor + "\">" + s + "</body></html>";
|
||||
// s=wxString::Format("<html><body BGCOLOR=\"%s\" FGCOLOR=\"%s\"><font face=\"%s\" size=\"%d\">%s</font></body></html>", bgcolor,fgcolor,fname,fsize, s);
|
||||
|
||||
|
||||
return s;
|
||||
}
|
||||
std::vector<Element> tokens;
|
||||
// colors
|
||||
wxString bgcolor, numcolor, fgcolor, quotecolor;
|
||||
wxString fname;
|
||||
int fsize;
|
||||
};
|
||||
|
||||
|
|
@ -8,27 +8,58 @@
|
|||
#include <wx/regex.h>
|
||||
#include <map>
|
||||
#include <vector>
|
||||
#include "wx/display.h"
|
||||
|
||||
class popuphelp :
|
||||
public wxPopupTransientWindow
|
||||
public wxPopupTransientWindow
|
||||
{
|
||||
public:
|
||||
//popuphelp(wxWindow* parent);
|
||||
bool ProcessLeftDown(wxMouseEvent& event)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
bool IsValid() {
|
||||
return isvalid;
|
||||
}
|
||||
popuphelp(wxWindow* parent,wxString keyword, FunctionPGHelper *hhelper) : wxPopupTransientWindow(parent) {
|
||||
SetSize(450,370);
|
||||
this->hhelper = hhelper;
|
||||
SetBackgroundColour(*wxBLACK);
|
||||
htmlWindow = new wxHtmlWindow(this, -1, wxDefaultPosition,GetSize());
|
||||
htmlWindow->SetRelatedStatusBar(0);
|
||||
//htmlWindow->SetPage("<html><body><h1>TEST</h1><span fgcolor=\"#332233\">Set Page Works</span></body></hmtl>");
|
||||
wxString txt = hhelper->getHelpString(keyword);
|
||||
~popuphelp() {
|
||||
delete closeTimer;
|
||||
}
|
||||
//popuphelp(wxWindow* parent);
|
||||
bool ProcessLeftDown(wxMouseEvent& event)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
bool IsValid() {
|
||||
return isvalid;
|
||||
}
|
||||
void SetSizePopup(const wxSize& sz) {
|
||||
SetSize(sz);
|
||||
Layout();
|
||||
Fit();
|
||||
sizew = sz;
|
||||
}
|
||||
wxSize GetSizePopup() { return sizew; }
|
||||
popuphelp(wxWindow* parent,wxString keyword, FunctionPGHelper *hhelper,wxPoint &posit,wxSize &newSz) : wxPopupTransientWindow(parent) {
|
||||
wxSize top_sz(newSz);
|
||||
sizew = top_sz;
|
||||
//SetSize(top_sz);
|
||||
this->hhelper = hhelper;
|
||||
SetBackgroundColour(*wxBLACK);
|
||||
extern sysSettings* settings;
|
||||
wxFont fnt = settings->GetSQLFont();
|
||||
int size = fnt.GetPointSize();
|
||||
SetFont(fnt);
|
||||
htmlWindow = new wxHtmlWindow(this, -1, wxDefaultPosition, sizew);
|
||||
|
||||
wxFont font(size, wxFontFamily::wxFONTFAMILY_MODERN, wxFontStyle::wxFONTSTYLE_NORMAL, wxFONTWEIGHT_NORMAL);
|
||||
wxString fixf = font.GetFaceName();
|
||||
wxString scalf = fnt.GetFaceName();
|
||||
int f_sizes[7];
|
||||
f_sizes[0] = int(size -4);
|
||||
f_sizes[1] = int(size -2);
|
||||
f_sizes[2] = size;
|
||||
f_sizes[3] = int(size +1);
|
||||
f_sizes[4] = int(size +3);
|
||||
f_sizes[5] = int(size +5);
|
||||
f_sizes[6] = int(size +7);
|
||||
htmlWindow->SetFonts(scalf, fixf, f_sizes);
|
||||
|
||||
htmlWindow->SetRelatedStatusBar(0);
|
||||
//htmlWindow->SetPage("<html><body><h1>TEST</h1><span fgcolor=\"#332233\">Set Page Works</span></body></hmtl>");
|
||||
wxString txt = hhelper->getHelpString(keyword);
|
||||
if (txt.IsEmpty()) {
|
||||
|
||||
txt = hhelper->getSqlCommandHelp(keyword);
|
||||
|
|
@ -38,47 +69,80 @@ public:
|
|||
}
|
||||
}
|
||||
SetPage(txt);
|
||||
//wxSize sz= htmlWindow->GetSize();
|
||||
//sz = htmlWindow->GetBestSize();
|
||||
//htmlWindow->SetHTMLBackgroundImage(wxBitmapBundle::FromSVGFile("data/bg.svg", wxSize(65, 45)));
|
||||
wxBoxSizer* topsizer;
|
||||
topsizer = new wxBoxSizer(wxVERTICAL);
|
||||
//htmlWindow->SetSize(htmlWindow->GetInternalRepresentation()->GetWidth(), htmlWindow->GetInternalRepresentation()->GetHeight());
|
||||
//wxSize sz= htmlWindow->GetSize();
|
||||
//sz = htmlWindow->GetBestSize();
|
||||
//htmlWindow->SetHTMLBackgroundImage(wxBitmapBundle::FromSVGFile("data/bg.svg", wxSize(65, 45)));
|
||||
wxBoxSizer* topsizer;
|
||||
topsizer = new wxBoxSizer(wxVERTICAL);
|
||||
|
||||
//htmlWindow->SetInitialSize(wxSize(htmlWindow->GetInternalRepresentation()->GetWidth(), htmlWindow->GetInternalRepresentation()->GetHeight()));
|
||||
//htmlWindow->SetInitialSize(wxSize(htmlWindow->GetInternalRepresentation()->GetWidth(), htmlWindow->GetInternalRepresentation()->GetHeight()));
|
||||
|
||||
//SetSize(wxSize(300,150));
|
||||
topsizer->Add(htmlWindow, 1, wxALL, 1);
|
||||
//SetSize(wxSize(300,150));
|
||||
topsizer->Add(htmlWindow, 1, wxALL, 1);
|
||||
|
||||
//wxButton* bu1 = new wxButton(this, wxID_OK, _("OK"));
|
||||
//bu1->SetDefault();
|
||||
//wxButton* bu1 = new wxButton(this, wxID_OK, _("OK"));
|
||||
//bu1->SetDefault();
|
||||
|
||||
//topsizer->Add(bu1, 0, wxALL | wxALIGN_RIGHT, 15);
|
||||
//topsizer->Add(bu1, 0, wxALL | wxALIGN_RIGHT, 15);
|
||||
|
||||
SetSizer(topsizer);
|
||||
topsizer->Fit(this);
|
||||
SetSizer(topsizer);
|
||||
topsizer->Fit(this);
|
||||
int xx, yy;
|
||||
htmlWindow->GetVirtualSize(&xx, &yy);
|
||||
//wxSize sz = GetSize();
|
||||
wxPoint posScreen;
|
||||
wxSize sizeScreen;
|
||||
const int displayNum = wxDisplay::GetFromPoint(posit);
|
||||
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 top_new(top_sz);
|
||||
|
||||
//this->Bind(wxEVT_HTML_CELL_CLICKED, [&](wxHtmlCellEvent& event) {
|
||||
// wxHtmlCell* c = event.GetCell();
|
||||
//
|
||||
// wxString ctext=c->ConvertToText(NULL);
|
||||
// ctext=htmlWindow->SelectionToText();
|
||||
// wxString s = wxString::Format("cell = %s",ctext.c_str());
|
||||
// wxMessageBox(s, "cell", wxOK | wxICON_INFORMATION);
|
||||
if (xx > sizeScreen.x) xx = sizeScreen.x - 120;
|
||||
if (yy > sizeScreen.y) yy = sizeScreen.y - 120;
|
||||
|
||||
// });
|
||||
this->Bind(wxEVT_HTML_LINK_CLICKED, [&](wxHtmlLinkEvent& event) {
|
||||
wxHtmlLinkInfo i = event.GetLinkInfo();
|
||||
wxString name = i.GetHref();
|
||||
wxString body=this->hhelper->getHelpString(name);
|
||||
|
||||
if (xx > top_sz.x || yy > top_sz.y) {
|
||||
int dx = 0;
|
||||
if (htmlWindow->IsScrollbarShown(wxHORIZONTAL)) dx=htmlWindow->GetScrollThumb(wxHORIZONTAL);
|
||||
SetSizePopup(wxSize(xx+dx, yy+5));
|
||||
}
|
||||
|
||||
//this->Bind(wxEVT_HTML_CELL_CLICKED, [&](wxHtmlCellEvent& event) {
|
||||
// wxHtmlCell* c = event.GetCell();
|
||||
//
|
||||
// wxString ctext=c->ConvertToText(NULL);
|
||||
// ctext=htmlWindow->SelectionToText();
|
||||
// wxString s = wxString::Format("cell = %s",ctext.c_str());
|
||||
// wxMessageBox(s, "cell", wxOK | wxICON_INFORMATION);
|
||||
|
||||
// });
|
||||
this->Bind(wxEVT_HTML_LINK_CLICKED, [&](wxHtmlLinkEvent& event) {
|
||||
wxHtmlLinkInfo i = event.GetLinkInfo();
|
||||
wxString name = i.GetHref();
|
||||
wxString body=this->hhelper->getHelpString(name);
|
||||
if (body.IsEmpty()) {
|
||||
body = this->hhelper->getHelpFile(name);
|
||||
}
|
||||
SetPage(body);
|
||||
//ctext=htmlWindow->SelectionToText();
|
||||
//wxString s = wxString::Format("cell = %s",ctext.c_str());
|
||||
});
|
||||
SetPage(body);
|
||||
//ctext=htmlWindow->SelectionToText();
|
||||
//wxString s = wxString::Format("cell = %s",ctext.c_str());
|
||||
});
|
||||
htmlWindow->Bind(wxEVT_RIGHT_UP, [&](wxMouseEvent& event) {
|
||||
wxString name;
|
||||
wxLongLong e = wxGetLocalTimeMillis();
|
||||
if (e - startTimeWin < 150)
|
||||
return;
|
||||
//wxString body = this->hhelper->getHelpString(name);
|
||||
wxString ctext = htmlWindow->SelectionToText();
|
||||
if (!ctext.IsEmpty()) {
|
||||
|
|
@ -88,6 +152,17 @@ public:
|
|||
{
|
||||
|
||||
}
|
||||
wxString wname = GetParent()->GetName();
|
||||
if (wname == "frmStatus") {
|
||||
//CMD_EVENT_FIND_STR
|
||||
wxCommandEvent event(wxEVT_MENU, 281);
|
||||
event.SetEventObject(this);
|
||||
// Give it some contents
|
||||
event.SetString(ctext);
|
||||
// Do send it
|
||||
GetParent()->ProcessWindowEvent(event);
|
||||
}
|
||||
//statusBar->SetStatusText(wxString::Format(" TIMER COUNT %d x:%d,y:%d", count, m.x, m.y));
|
||||
Hide();
|
||||
return;
|
||||
}
|
||||
|
|
@ -95,21 +170,43 @@ public:
|
|||
//ctext=htmlWindow->SelectionToText();
|
||||
//wxString s = wxString::Format("cell = %s",ctext.c_str());
|
||||
});
|
||||
|
||||
}
|
||||
startTimeWin = wxGetLocalTimeMillis();
|
||||
int inter = hhelper->GetTimerClose();
|
||||
if (inter != -1) {
|
||||
closeTimer = new wxTimer(this);
|
||||
Bind(wxEVT_TIMER, [&](wxTimerEvent& event) {
|
||||
closeTimer->Stop();
|
||||
wxPoint pm = this->GetScreenPosition();
|
||||
wxRect rc = this->GetSize();
|
||||
wxPoint m = wxGetMousePosition();
|
||||
rc.x = pm.x;
|
||||
rc.y = pm.y;
|
||||
if (!rc.Contains(m)) {
|
||||
Hide();
|
||||
return;
|
||||
}
|
||||
});
|
||||
closeTimer->StartOnce(inter);
|
||||
}
|
||||
}
|
||||
private:
|
||||
bool isvalid = true;
|
||||
wxHtmlWindow* htmlWindow;
|
||||
FunctionPGHelper* hhelper;
|
||||
bool isvalid = true;
|
||||
wxHtmlWindow* htmlWindow;
|
||||
wxLongLong startTimeWin;
|
||||
wxSize sizew;
|
||||
FunctionPGHelper* hhelper;
|
||||
std::vector<wxString> hist;
|
||||
void SetPage(wxString innerbody,bool gethistory=false) {
|
||||
void SetPage(wxString innerbody,bool gethistory=false) {
|
||||
wxString h;
|
||||
int p = innerbody.Find("<body>");
|
||||
if (p > -1) {
|
||||
innerbody.Replace("<body>", "<html><body TEXT=\"#000000\" BGCOLOR=\"#FFFFA0\" LINK=\"#0000FF\" VLINK=\"#FF0000\" ALINK=\"#000088\">", false);
|
||||
h = "" + innerbody + "";
|
||||
} else
|
||||
h = "<html><body TEXT=\"#000000\" BGCOLOR=\"#FFFFA0\" LINK=\"#0000FF\" VLINK=\"#FF0000\" ALINK=\"#000088\">" + innerbody + "</body></hmtl>";
|
||||
if (innerbody.Find("<html>")>=0) h = innerbody;
|
||||
else
|
||||
if (p > -1) {
|
||||
innerbody.Replace("<body>", "<html><body TEXT=\"#000000\" BGCOLOR=\"#FFFFE0\" LINK=\"#0000FF\" VLINK=\"#FF0000\" ALINK=\"#000088\">", false);
|
||||
h = "" + innerbody + "";
|
||||
}
|
||||
else
|
||||
h = "<html><body TEXT=\"#000000\" BGCOLOR=\"#FFFFE0\" LINK=\"#0000FF\" VLINK=\"#FF0000\" ALINK=\"#000088\">" + innerbody + "</body></hmtl>";
|
||||
|
||||
if (gethistory) {
|
||||
if (hist.size() < 2) {
|
||||
|
|
@ -122,7 +219,9 @@ private:
|
|||
else {
|
||||
hist.push_back(h);
|
||||
}
|
||||
htmlWindow->SetPage(h);
|
||||
}
|
||||
htmlWindow->SetPage(h);
|
||||
}
|
||||
private:
|
||||
wxTimer *closeTimer=NULL;
|
||||
};
|
||||
#endif
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue