mirror of
https://github.com/levinsv/pgadmin3.git
synced 2026-05-15 14:15:49 -06:00
Add context help for PG functions.
Добавлен вызов контекстной помощи по именам функций Postgresql. Для этого требуется: 1. в параметрах указать путь к html файлам документации. 2. выполнить скрипт _extract_func_help.pl для генерации файла _func.txt 3. разместить файл _func.txt в каталоге с документацией. Для вызова помощи нужно выделить слово или выражение и нажать Ctrl+F1. Можно просто нажать Ctrl+F1 и тогда для слова слева от курсора будет выведена справка. Если слову соответсвует несколько функций они будут выведены в виде списка имен. Для навигации в окне контекстной помощи: - закрыть окно или переместиться назад - правая кнопка мыши - выделить текст + правая кнопка - копировать выделение в буфер и закрыть окно. - нажатие ESC - закрытие окна. Для отображения помощи используется wxHtmlWindow https://docs.wxwidgets.org/latest/overview_html.html.
This commit is contained in:
parent
9f3cfacf96
commit
2d3f87edaa
9 changed files with 678 additions and 2 deletions
139
include/utils/FunctionPGHelper.h
Normal file
139
include/utils/FunctionPGHelper.h
Normal file
|
|
@ -0,0 +1,139 @@
|
|||
|
||||
#ifndef FUNCTIONPGHELPER_H
|
||||
#define FUNCTIONPGHELPER_H
|
||||
#include <utils/sysSettings.h>
|
||||
#include <wx/regex.h>
|
||||
#include <map>
|
||||
#include <vector>
|
||||
#include <wx/stdpaths.h>
|
||||
#include <wx/textfile.h>
|
||||
#include <wx/filename.h>
|
||||
|
||||
extern sysSettings *settings;
|
||||
|
||||
class FunctionPGHelper
|
||||
{
|
||||
public:
|
||||
FunctionPGHelper() {};
|
||||
wxString getHelpString(wxString fnd, bool isPart = true) {
|
||||
if (!isValid()) return wxEmptyString;
|
||||
auto search = body.find(fnd);
|
||||
wxString txt;
|
||||
|
||||
if (search != body.end())
|
||||
txt = search->second;
|
||||
else
|
||||
{
|
||||
std::vector<wxString> list;
|
||||
int l = fnd.Len();
|
||||
wxString b;
|
||||
for (const auto& e : body) {
|
||||
if (e.first.Len() > l && e.first.StartsWith(fnd)) {
|
||||
list.push_back(e.first);
|
||||
b = e.second;
|
||||
}
|
||||
}
|
||||
if (list.size() == 1) txt = b;
|
||||
else {
|
||||
for (const auto& s : list) {
|
||||
txt += wxString::Format("<a href=\"%s\">%s</a><br>", s, s);
|
||||
}
|
||||
}
|
||||
}
|
||||
//if (i == wxNOT_FOUND) return wxEmptyString;
|
||||
return txt;
|
||||
}
|
||||
wxString getSqlCommandHelp(wxString fnd) {
|
||||
wxUniChar sep = wxFileName::GetPathSeparator();
|
||||
fnd.Replace(" ", "");
|
||||
wxString f = wxFindFirstFile(path + sep+"sql-"+fnd+"*.html");
|
||||
wxString last,txt;
|
||||
|
||||
int c = 0;
|
||||
while (!f.empty())
|
||||
{
|
||||
f = f.AfterLast(sep);
|
||||
last = f;
|
||||
txt += wxString::Format("<a href=\"%s\">%s</a><br>", f, f);
|
||||
f = wxFindNextFile();
|
||||
c++;
|
||||
}
|
||||
if (last.empty()) {
|
||||
return wxEmptyString;
|
||||
}
|
||||
else if (c==1) {
|
||||
return getHelpFile(last);
|
||||
}
|
||||
else {
|
||||
return txt;
|
||||
}
|
||||
|
||||
}
|
||||
wxString getHelpFile(wxString filename) {
|
||||
wxString tempDir = path + wxFileName::GetPathSeparator() + filename;
|
||||
if (!wxFileExists(tempDir)) return wxEmptyString;
|
||||
wxTextFile tfile;
|
||||
tfile.Open(tempDir);
|
||||
// read the first line
|
||||
wxString str, sbody;
|
||||
sbody = tfile.GetFirstLine();
|
||||
bool flag = true;
|
||||
wxRegEx b("(<body .*?>)");
|
||||
while (!tfile.Eof())
|
||||
{
|
||||
str = tfile.GetNextLine();
|
||||
if (flag && b.Matches(str)) {
|
||||
size_t start, len;
|
||||
b.GetMatch(&start, &len, 0);
|
||||
str = str.Mid(start + len);
|
||||
sbody = "<body>";
|
||||
flag = false;
|
||||
}
|
||||
sbody += str;
|
||||
}
|
||||
return sbody;
|
||||
|
||||
}
|
||||
bool isValid() {
|
||||
if (!isload) loadfile();
|
||||
return isload;
|
||||
}
|
||||
private:
|
||||
bool isload = false;
|
||||
wxString path;
|
||||
std::map<wxString, wxString> body;
|
||||
void loadfile() {
|
||||
if (isload) return;
|
||||
body.clear();
|
||||
path = settings->GetPgHelpPath();
|
||||
wxString tempDir = path + "_func.txt";
|
||||
//tempDir="C:\\Users\\lsv\\Source\\Repos\\wxHtmlhint\\1";
|
||||
if (!wxFileExists(tempDir)) return;
|
||||
wxTextFile tfile;
|
||||
tfile.Open(tempDir);
|
||||
|
||||
// read the first line
|
||||
wxString str, sbody;
|
||||
wxString name = tfile.GetFirstLine();
|
||||
|
||||
//wxSortedArrayString names;
|
||||
name = name.AfterFirst('#');
|
||||
// read all lines one by one
|
||||
// until the end of the file
|
||||
while (!tfile.Eof())
|
||||
{
|
||||
str = tfile.GetNextLine();
|
||||
if (str.Left(1) == '#') {
|
||||
body.emplace(name, sbody);
|
||||
sbody = "";
|
||||
name = str.AfterFirst('#');
|
||||
}
|
||||
else sbody += str;
|
||||
}
|
||||
body.emplace(name, sbody);
|
||||
isload = true;
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
#endif
|
||||
128
include/utils/popuphelp.h
Normal file
128
include/utils/popuphelp.h
Normal file
|
|
@ -0,0 +1,128 @@
|
|||
#ifndef POPUPHELP_H
|
||||
#define POPUPHELP_H
|
||||
|
||||
#include "wx/popupwin.h"
|
||||
#include <wx/html/htmlwin.h>
|
||||
#include "wx/clipbrd.h"
|
||||
#include "utils/FunctionPGHelper.h"
|
||||
#include <wx/regex.h>
|
||||
#include <map>
|
||||
#include <vector>
|
||||
|
||||
class popuphelp :
|
||||
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);
|
||||
if (txt.IsEmpty()) {
|
||||
|
||||
txt = hhelper->getSqlCommandHelp(keyword);
|
||||
if (txt.empty()) {
|
||||
isvalid = false;
|
||||
return;
|
||||
}
|
||||
}
|
||||
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->SetInitialSize(wxSize(htmlWindow->GetInternalRepresentation()->GetWidth(), htmlWindow->GetInternalRepresentation()->GetHeight()));
|
||||
|
||||
//SetSize(wxSize(300,150));
|
||||
topsizer->Add(htmlWindow, 1, wxALL, 1);
|
||||
|
||||
//wxButton* bu1 = new wxButton(this, wxID_OK, _("OK"));
|
||||
//bu1->SetDefault();
|
||||
|
||||
//topsizer->Add(bu1, 0, wxALL | wxALIGN_RIGHT, 15);
|
||||
|
||||
SetSizer(topsizer);
|
||||
topsizer->Fit(this);
|
||||
|
||||
//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());
|
||||
});
|
||||
htmlWindow->Bind(wxEVT_RIGHT_UP, [&](wxMouseEvent& event) {
|
||||
wxString name;
|
||||
//wxString body = this->hhelper->getHelpString(name);
|
||||
wxString ctext = htmlWindow->SelectionToText();
|
||||
if (!ctext.IsEmpty()) {
|
||||
wxClipboardLocker clip;
|
||||
if (!clip ||
|
||||
!wxTheClipboard->AddData(new wxTextDataObject(ctext)))
|
||||
{
|
||||
|
||||
}
|
||||
Hide();
|
||||
return;
|
||||
}
|
||||
this->SetPage("", true);
|
||||
//ctext=htmlWindow->SelectionToText();
|
||||
//wxString s = wxString::Format("cell = %s",ctext.c_str());
|
||||
});
|
||||
|
||||
}
|
||||
private:
|
||||
bool isvalid = true;
|
||||
wxHtmlWindow* htmlWindow;
|
||||
FunctionPGHelper* hhelper;
|
||||
std::vector<wxString> hist;
|
||||
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 (gethistory) {
|
||||
if (hist.size() < 2) {
|
||||
Hide();
|
||||
return;
|
||||
}
|
||||
hist.pop_back();
|
||||
h = hist[hist.size()-1];
|
||||
}
|
||||
else {
|
||||
hist.push_back(h);
|
||||
}
|
||||
htmlWindow->SetPage(h);
|
||||
}
|
||||
};
|
||||
#endif
|
||||
Loading…
Add table
Add a link
Reference in a new issue