mirror of
https://github.com/levinsv/pgadmin3.git
synced 2026-05-15 06:05:49 -06:00
New control ctlTreeJSON
Добавлен новый элемент для редактирования JSON файла pgadmin3opt.json Этот файл используется для хранения настроек навигационной панели лог файла(ctlNavigatePanel), хранения конфигураций диалога трансформации текста(dlgTransformText), настройки событий ожиданий(WaitSample).
This commit is contained in:
parent
b7f29f10d1
commit
c981b6b84f
6 changed files with 813 additions and 5 deletions
705
ctl/ctlTreeJSON.cpp
Normal file
705
ctl/ctlTreeJSON.cpp
Normal file
|
|
@ -0,0 +1,705 @@
|
|||
#include "pgAdmin3.h"
|
||||
#include "ctl/ctlTreeJSON.h"
|
||||
#include <wx/wx.h>
|
||||
#include <wx/event.h>
|
||||
#include <map>
|
||||
#include <wx/colordlg.h>
|
||||
|
||||
|
||||
|
||||
BEGIN_EVENT_TABLE(ctlTreeJSON, wxTreeCtrl)
|
||||
EVT_CHAR(ctlTreeJSON::OnChar)
|
||||
//EVT_MOUSE_EVENTS(ctlTreeJSON::OnMouse)
|
||||
EVT_TREE_BEGIN_LABEL_EDIT(wxID_ANY, ctlTreeJSON::OnBeginEdit)
|
||||
EVT_TREE_END_LABEL_EDIT(wxID_ANY, ctlTreeJSON::OnEndEdit)
|
||||
EVT_LEFT_DCLICK(ctlTreeJSON::OnDoubleClick)
|
||||
EVT_TREE_DELETE_ITEM(wxID_ANY, ctlTreeJSON::OnDeleteItem)
|
||||
END_EVENT_TABLE()
|
||||
IMPLEMENT_DYNAMIC_CLASS(ctlTreeJSON, wxTreeCtrl)
|
||||
|
||||
void ctlTreeJSON::OnChar(wxKeyEvent& event) {
|
||||
wxTreeItemId id = GetSelection();
|
||||
if (!id.IsOk()) return;
|
||||
if (event.GetKeyCode() == WXK_INSERT) {
|
||||
CopyNode(id);
|
||||
return;
|
||||
}
|
||||
if (event.GetKeyCode() == WXK_DELETE) {
|
||||
if (HasChildren(id)) DeleteChildren(id);
|
||||
Delete(id);
|
||||
return;
|
||||
}
|
||||
if (event.GetKeyCode() == WXK_CONTROL_Z) {
|
||||
if (GetItemBackgroundColour(id) != GetBackgroundColour()) {
|
||||
if (orig.find(id) != orig.end()) {
|
||||
conf[id] = orig[id];
|
||||
wxString t = GetItemText(id);
|
||||
wxString newtext = orig[id].AsString();
|
||||
wxString key = t.BeforeFirst(':');
|
||||
if (key !=t) {
|
||||
newtext = key + ":" + newtext;
|
||||
}
|
||||
SetItemText(id, newtext);
|
||||
SetItemBackgroundColour(id, GetBackgroundColour());
|
||||
wxColour empty;
|
||||
int rez = 0;
|
||||
if (newtext != t && newtext.length() > 0)
|
||||
rez=RefreshImages(id, empty, newtext);
|
||||
if (rez!=1) orig.erase(id);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
if (event.GetKeyCode() == WXK_CONTROL_F) {
|
||||
wxTextEntryDialog dialog(this,
|
||||
wxT("Please enter find string\n")
|
||||
,
|
||||
wxT("Find"),
|
||||
m_FindString,
|
||||
wxOK | wxCANCEL); //setName( dlg.GetValue().wc_str() );
|
||||
if (dialog.ShowModal() == wxID_OK) {
|
||||
m_FindString = dialog.GetValue();
|
||||
BuildFind();
|
||||
}
|
||||
return;
|
||||
}
|
||||
int find_next = 0;
|
||||
if (event.GetKeyCode() == WXK_F3) {
|
||||
find_next = 1;
|
||||
}
|
||||
if (event.GetKeyCode() == WXK_F3 && event.ShiftDown()) {
|
||||
find_next = -1;
|
||||
}
|
||||
if ((find_next == 1 || find_next == -1) && findsId.size() > 0) {
|
||||
wxTreeItemId sel, next, item = GetRootItem();
|
||||
while (item.IsOk()) {
|
||||
item = nextTreeItem(item);
|
||||
if (item.IsOk()) {
|
||||
if (id == item) {
|
||||
sel = id;
|
||||
if (find_next == -1 && next.IsOk()) {
|
||||
SelectItem(next);
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (findsId.count(item) > 0) {
|
||||
next = item;
|
||||
if (sel.IsOk() && find_next == 1 && id != item) {
|
||||
SelectItem(next);
|
||||
return;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
event.Skip();
|
||||
};
|
||||
void ctlTreeJSON::BuildFind() {
|
||||
for (const auto& [id, tmp] : findsId) {
|
||||
SetItemBackgroundColour(id, GetBackgroundColour());
|
||||
}
|
||||
findsId.clear();
|
||||
wxTreeItemId item;
|
||||
wxTreeItemId sel;
|
||||
wxTreeItemIdValue cookie;
|
||||
if (m_FindString.IsEmpty()) return;
|
||||
sel = GetSelection();
|
||||
item = GetFirstChild(GetRootItem(), cookie);
|
||||
if (!GetCount()) return; // empty tree control - i.e. just cleared it?
|
||||
wxString searchtext = m_FindString.Lower();
|
||||
wxTreeItemId last;
|
||||
bool flag = false;
|
||||
while (item.IsOk()) {
|
||||
wxString itemtext = GetItemText(item).Lower();
|
||||
if (sel == item) flag = true;
|
||||
if (itemtext.Contains(searchtext)) {
|
||||
//findsId.push_back(item);
|
||||
findsId.emplace(item, 0);
|
||||
SetItemBackgroundColour(item, wxColour("#FFFF00"));
|
||||
if (flag)
|
||||
{
|
||||
last = item;
|
||||
flag = false;
|
||||
}
|
||||
}
|
||||
item = nextTreeItem(item);
|
||||
}
|
||||
if (findsId.size() > 0)
|
||||
if (last.IsOk())SelectItem(last);
|
||||
else
|
||||
wxBell();
|
||||
}
|
||||
wxTreeItemId ctlTreeJSON::nextTreeItem(const wxTreeItemId& item) {
|
||||
wxTreeItemId child;
|
||||
wxTreeItemIdValue cookie;
|
||||
if (HasChildren(item))
|
||||
child = GetFirstChild(item, cookie);
|
||||
else
|
||||
{
|
||||
// Try a sibling of this or ancestor instead
|
||||
wxTreeItemId p = item;
|
||||
wxTreeItemId toFind;
|
||||
do
|
||||
{
|
||||
toFind = GetNextSibling(p);
|
||||
p = GetItemParent(p);
|
||||
if (GetRootItem() == p && !toFind.IsOk()) {
|
||||
return child;
|
||||
}
|
||||
} while (p.IsOk() && !toFind.IsOk());
|
||||
child = toFind;
|
||||
}
|
||||
return child;
|
||||
}
|
||||
wxTreeItemId ctlTreeJSON::findTreeItem(const wxTreeItemId& root, const wxString& text, bool bCaseSensitive, bool bExactMatch)
|
||||
{
|
||||
wxTreeItemId item = root, child;
|
||||
wxTreeItemIdValue cookie;
|
||||
wxString findtext(text), itemtext;
|
||||
bool bFound;
|
||||
if (!bCaseSensitive) findtext.MakeLower();
|
||||
while (item.IsOk())
|
||||
{
|
||||
itemtext = GetItemText(item);
|
||||
if (!bCaseSensitive) itemtext.MakeLower();
|
||||
bFound = bExactMatch ? (itemtext == findtext) : itemtext.Contains(findtext);
|
||||
if (bFound) return item;
|
||||
child = GetFirstChild(item, cookie);
|
||||
if (child.IsOk()) child = findTreeItem(child, text, bCaseSensitive, bExactMatch);
|
||||
if (child.IsOk()) return child;
|
||||
item = GetNextSibling(item);
|
||||
|
||||
} // while(item.IsOk())
|
||||
|
||||
return item;
|
||||
}
|
||||
void ctlTreeJSON::OnDeleteItem(wxTreeEvent& event) {
|
||||
wxTreeItemId id = event.GetItem();
|
||||
if (colors.find(id) != colors.end()) {
|
||||
colors.erase(id);
|
||||
}
|
||||
if (conf.find(id) != conf.end()) {
|
||||
conf.erase(id);
|
||||
m_change = true;
|
||||
}
|
||||
|
||||
};
|
||||
wxColour getColorFromString(const wxString& str) {
|
||||
wxString strcolor = str.AfterFirst('#');
|
||||
wxColour empty;
|
||||
if (!strcolor.IsEmpty() && strcolor.length() > 5) {
|
||||
wxString strc = "#" + strcolor.Mid(0, 6);
|
||||
unsigned long tmp;
|
||||
int scanned = wxSscanf(strcolor, "%lx", &tmp);
|
||||
if (scanned == 1) {
|
||||
wxColour c(strc);
|
||||
if (c.IsOk()) return c;
|
||||
}
|
||||
}
|
||||
return empty;
|
||||
}
|
||||
int ctlTreeJSON::RefreshImages(const wxTreeItemId& id, wxColour newColour, wxString textLabel) {
|
||||
//SetIma
|
||||
int rez = 0;
|
||||
if (colors.find(id) != colors.end()) {
|
||||
rez = -1;
|
||||
auto old_color = colors.at(id);
|
||||
if (textLabel.length() > 0) {
|
||||
// change label
|
||||
newColour = getColorFromString(textLabel);
|
||||
if (!newColour.IsOk()) return rez;
|
||||
}
|
||||
if (old_color.GetRGB() != newColour.GetRGB()) {
|
||||
colors.erase(id);
|
||||
colors[id] = newColour;
|
||||
wxString oldt = GetItemText(id);
|
||||
wxString newtextcolor = newColour.GetAsString(wxC2S_HTML_SYNTAX);
|
||||
int pos = oldt.Find('#');
|
||||
if (pos < 0) {
|
||||
pos = 0;
|
||||
}
|
||||
wxString newlabel = oldt.Left(pos) + newtextcolor;
|
||||
SetItemText(id, newlabel);
|
||||
wxJSONValue v = conf[id];
|
||||
conf[id] = newtextcolor;
|
||||
m_change = true;
|
||||
if (orig.find(id) != orig.end()) {
|
||||
if (conf[id].AsString() == orig[id].AsString()) {
|
||||
SetItemBackgroundColour(id, GetBackgroundColour());
|
||||
orig.erase(id);
|
||||
}
|
||||
}
|
||||
else {
|
||||
// save original value
|
||||
orig[id] = v;
|
||||
SetItemBackgroundColour(id, wxColour("#c0ffff"));
|
||||
}
|
||||
|
||||
RefreshImageList();
|
||||
rez = 1;
|
||||
}
|
||||
}
|
||||
return rez;
|
||||
}
|
||||
void ctlTreeJSON::OnDoubleClick(wxMouseEvent& event) {
|
||||
wxPoint p = event.GetPosition();
|
||||
int flags;
|
||||
wxTreeItemId id = HitTest(p, flags);
|
||||
wxString s;
|
||||
wxJSONValue v;
|
||||
if (id.IsOk()) {
|
||||
s = GetItemText(id);
|
||||
|
||||
if (conf.count(id) > 0) v = conf[id];
|
||||
}
|
||||
|
||||
if (flags & wxTREE_HITTEST_ONITEMLABEL) {
|
||||
wxString s = GetItemText(id);
|
||||
wxString str = s.AfterFirst(':');
|
||||
wxString key = s.BeforeFirst(':');
|
||||
if (str.IsEmpty()) str = s;
|
||||
int im = GetItemImage(id);
|
||||
s = wxString::Format("val=%s n_image=%d", str, im);
|
||||
if (key!=s) {
|
||||
if (v.GetType() == wxJSONTYPE_BOOL) {
|
||||
bool b = !v.AsBool();
|
||||
wxString newstr = "true";
|
||||
if (!b) newstr = "false";
|
||||
wxTreeEvent e;
|
||||
wxString nv = key + ":" + newstr;
|
||||
e.SetLabel(nv);
|
||||
e.SetItem(id);
|
||||
e.Allow();
|
||||
OnEndEdit(e);
|
||||
if (e.IsAllowed()) {
|
||||
SetItemText(id, nv);
|
||||
}
|
||||
}
|
||||
}
|
||||
//wxMessageBox(s);
|
||||
}
|
||||
else if (flags & wxTREE_HITTEST_ONITEMICON) {
|
||||
//if (v.AsString())
|
||||
|
||||
if (colors.find(id) != colors.end()) {
|
||||
wxColourData data;
|
||||
wxColour initialColourToUse = colors.at(id);
|
||||
data.SetColour(initialColourToUse);
|
||||
wxColourDialog dlg(this, &data);
|
||||
dlg.Bind(wxEVT_COLOUR_CHANGED, [](wxColourDialogEvent& event) {
|
||||
//Redraw(event.GetColour());
|
||||
});
|
||||
if (dlg.ShowModal() == wxID_OK) {
|
||||
// Colour did change.
|
||||
RefreshImages(id, dlg.GetColourData().GetColour(), "");
|
||||
}
|
||||
else {
|
||||
// Colour didn't change.
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
void ctlTreeJSON::OnBeginEdit(wxTreeEvent& event) {
|
||||
//wxTrap();
|
||||
};
|
||||
void ctlTreeJSON::OnEndEdit(wxTreeEvent& event) {
|
||||
if (event.IsEditCancelled()) return;
|
||||
wxString newtext = event.GetLabel();
|
||||
auto id = event.GetItem();
|
||||
wxString oldtext = GetItemText(id);
|
||||
auto parent_id = GetItemParent(id);
|
||||
wxString name;
|
||||
wxJSONValue v = conf[id];
|
||||
if (v.IsArray() || v.IsObject()) {
|
||||
event.Veto();
|
||||
return;
|
||||
}
|
||||
if (parent_id.IsOk()) {
|
||||
wxJSONValue p = conf[parent_id];
|
||||
wxString newvaluetext = newtext;
|
||||
wxString n; // name parameter
|
||||
int idx = -1; // index array
|
||||
if (p.IsObject()) {
|
||||
n = oldtext.BeforeFirst(':');
|
||||
if (!(n.length() > 0 && p.HasMember(n))) {
|
||||
event.Veto();
|
||||
return;
|
||||
}
|
||||
//
|
||||
if (!(n.length() > 0 && newtext.StartsWith(n + ":"))) {
|
||||
// name need equals
|
||||
event.Veto();
|
||||
return;
|
||||
}
|
||||
newvaluetext = newtext.Mid(n.length() + 1);
|
||||
}
|
||||
else if (p.IsArray()) {
|
||||
for (int j = 0; j < conf[parent_id].Size(); ++j) {
|
||||
if (conf[parent_id][j].GetRefData() == conf[id].GetRefData()) { idx = j; break; }
|
||||
}
|
||||
if (idx == -1) {
|
||||
// wxTrap();
|
||||
}
|
||||
}
|
||||
|
||||
//change jsonvalue
|
||||
if (v.IsBool()) {
|
||||
bool bb = false;
|
||||
if (newvaluetext == "true") bb = true;
|
||||
//if (n.IsEmpty()) p[idx] = bb; else p[n] = bb;
|
||||
conf[id] = bb;
|
||||
m_change = true;
|
||||
}
|
||||
else if (v.IsInt()) {
|
||||
int ii = 0;
|
||||
int scaned = wxSscanf(newvaluetext, "%d", &ii);
|
||||
if (scaned != 1) {
|
||||
event.Veto();
|
||||
return;
|
||||
}
|
||||
//if (n.IsEmpty()) p[idx] = ii; else p[n] = ii;
|
||||
conf[id] = ii;
|
||||
m_change = true;
|
||||
}
|
||||
else {
|
||||
// string value
|
||||
//if (n.IsEmpty()) p[idx] = newvaluetext; else p[n] = newvaluetext;
|
||||
conf[id] = newvaluetext;
|
||||
m_change = true;
|
||||
//if (n.IsEmpty()) conf[parent_id][idx] = conf[id]; else conf[parent_id][n] = conf[id];
|
||||
}
|
||||
//p[n] = newtext.Mid(n.length());
|
||||
if (orig.find(id) != orig.end()) {
|
||||
if (conf[id].AsString() == orig[id].AsString()) {
|
||||
SetItemBackgroundColour(id, GetBackgroundColour());
|
||||
orig.erase(id);
|
||||
}
|
||||
}
|
||||
else {
|
||||
// save original value
|
||||
orig[id] = v;
|
||||
SetItemBackgroundColour(id, wxColour("#c0ffff"));
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
wxColour empty;
|
||||
if (newtext != oldtext && newtext.length() > 0) {
|
||||
int rez = RefreshImages(id, empty, newtext);
|
||||
if (rez > 0) return;
|
||||
if (rez < 0)event.Veto(); // bad colour
|
||||
else
|
||||
{
|
||||
// no colour
|
||||
|
||||
}
|
||||
}
|
||||
};
|
||||
wxTreeItemId ctlTreeJSON::NodeToJSON(const wxTreeItemId& id, wxJSONValue& newjson) {
|
||||
wxTreeItemId item = id, child;
|
||||
wxTreeItemIdValue cookie;
|
||||
wxString itemtext;
|
||||
int i = 0;
|
||||
while (item.IsOk())
|
||||
{
|
||||
itemtext = GetItemText(item);
|
||||
wxJSONValue j = conf.at(item);
|
||||
wxJSONValue n;
|
||||
n.SetType(j.GetType());
|
||||
// wxJSONValue v = conf.at(item);
|
||||
// j = v;
|
||||
//wxJSONType t = v.GetType();
|
||||
child = GetFirstChild(item, cookie);
|
||||
|
||||
if (child.IsOk()) child = NodeToJSON(child, n);
|
||||
if (newjson.IsObject()) {
|
||||
wxString key = itemtext.BeforeFirst(':');
|
||||
if (key.Right(2) == "{}" || key.Right(2) == "[]") key = key.Left(key.length() - 2);
|
||||
wxString vl = itemtext.AfterFirst(':');
|
||||
if (n.IsArray() || n.IsObject()) newjson[key] = n;
|
||||
else
|
||||
newjson[key] = j;
|
||||
}
|
||||
else if (newjson.IsArray()) {
|
||||
if (n.IsArray() || n.IsObject()) newjson[i] = n;
|
||||
else
|
||||
newjson[i] = j;
|
||||
i++;
|
||||
}
|
||||
|
||||
//if (child.IsOk()) return child;
|
||||
item = GetNextSibling(item);
|
||||
} // while(item.IsOk())
|
||||
|
||||
return item;
|
||||
}
|
||||
wxJSONValue ctlTreeJSON::copyjson(wxJSONValue& src) {
|
||||
wxJSONValue v;
|
||||
v.SetType(src.GetType());
|
||||
if (src.IsArray()) {
|
||||
for (int j = 0; j < src.Size(); ++j) {
|
||||
wxJSONValue m = copyjson(src[j]);
|
||||
v.Append(m);
|
||||
}
|
||||
}
|
||||
else if (src.IsObject()) {
|
||||
wxArrayString arr = src.GetMemberNames();
|
||||
for (int j = 0; j < arr.Count(); ++j) {
|
||||
v[arr[j]] = copyjson(src[arr[j]]);
|
||||
}
|
||||
}
|
||||
else {
|
||||
bool b = false;
|
||||
int i = 0;
|
||||
wxString s;
|
||||
src.AsBool(b);
|
||||
src.AsInt(i);
|
||||
src.AsString(s);
|
||||
if (src.IsBool()) v = b;
|
||||
if (src.IsInt())
|
||||
v = i;
|
||||
if (src.IsString()) v = s;
|
||||
}
|
||||
return v;
|
||||
}
|
||||
void ctlTreeJSON::CopyNode(const wxTreeItemId& idSource) {
|
||||
wxJSONValue v = conf[idSource];
|
||||
wxTreeItemId pid = GetItemParent(idSource);
|
||||
wxJSONValue pv = conf.at(pid);
|
||||
wxJSONValue n = copyjson(conf[idSource]);
|
||||
|
||||
wxTreeItemId nid;
|
||||
if (pv.IsArray()) {
|
||||
//if (v.IsObject()) nid = NodeToJSON(idSource, n);
|
||||
int vsize = pv.Size();
|
||||
wxString label = wxString::Format("[%d]", vsize);
|
||||
if (n.IsObject() || n.IsArray()) {
|
||||
nid = addtree(pid, label, &n);
|
||||
conf[nid] = n;
|
||||
LoadInTree(n, nid);
|
||||
SelectItem(nid);
|
||||
//EnsureVisible(nid);
|
||||
m_change = true;
|
||||
}
|
||||
else {
|
||||
//conf[pid][vsize]=n;
|
||||
//LoadInTree(conf[pid], pid);
|
||||
nid = addtree(pid, n.AsString(), &n);
|
||||
conf[nid] = n;
|
||||
|
||||
m_change = true;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
else if (pv.IsObject()) {
|
||||
wxString label = GetItemText(idSource);
|
||||
wxString suf = label.Right(2);
|
||||
label = label.Mid(0, label.length() - 2);
|
||||
int vsize = v.Size();
|
||||
label = wxString::Format("%s%d", label, vsize);
|
||||
label += suf;
|
||||
if (v.IsObject() || v.IsArray()) {
|
||||
//nid = NodeToJSON(idSource, n);
|
||||
if (vsize == 0) {
|
||||
//copy empty array
|
||||
wxJSONValue newString;
|
||||
wxString text = "new string value";
|
||||
newString = text;
|
||||
newString = conf[idSource].Append(newString);
|
||||
nid = addtree(idSource, text, &newString);
|
||||
conf[nid] = newString;
|
||||
m_change = true;
|
||||
return;
|
||||
}
|
||||
else {
|
||||
if (v.IsObject() || v.IsArray()) return;
|
||||
nid = addtree(pid, label, &n);
|
||||
conf[nid] = n;
|
||||
LoadInTree(n, nid);
|
||||
m_change = true;
|
||||
}
|
||||
}
|
||||
else {
|
||||
//wxString key = GetItemText(idSource).BeforeFirst(':');
|
||||
|
||||
return;
|
||||
}
|
||||
// copy only Object or Array
|
||||
nid = addtree(pid, label, &n);
|
||||
LoadInTree(n, nid);
|
||||
}
|
||||
else {
|
||||
return;
|
||||
}
|
||||
RefreshImageList();
|
||||
}
|
||||
//void ctlTreeJSON::AddJSONValue(const wxJSONValue& parent, const wxJSONValue& jval);
|
||||
wxTreeItemId ctlTreeJSON::addtree(const wxTreeItemId& idParent, wxString text, wxJSONValue* jval) {
|
||||
wxTreeItemId item;
|
||||
if (idParent.IsOk()) {
|
||||
item = AppendItem(idParent, text, -1, -1, 0);
|
||||
}
|
||||
else {
|
||||
item = AddRoot(text, -1, -1, 0);
|
||||
}
|
||||
if (m_root == idParent) {
|
||||
SetItemBackgroundColour(item, *wxLIGHT_GREY);
|
||||
}
|
||||
if (text.length() >= 7) {
|
||||
wxColour c = getColorFromString(text);
|
||||
if (c.IsOk()) {
|
||||
colors[item] = c;
|
||||
}
|
||||
}
|
||||
return item;
|
||||
};
|
||||
void ctlTreeJSON::RefreshImageList() {
|
||||
auto it = GetFirstVisibleItem();
|
||||
wxRect r;
|
||||
wxSize sz(15, 15);
|
||||
if (GetBoundingRect(it, r)) {
|
||||
sz.x = r.height - 2;
|
||||
sz.y = r.height - 2;
|
||||
}
|
||||
//else return;
|
||||
wxVector<wxBitmapBundle> images;
|
||||
int n = 0;
|
||||
for (const auto& [item, color] : colors) {
|
||||
wxMemoryDC dc;
|
||||
wxBitmap bmp(sz.x, sz.y);
|
||||
wxMask* mask = new wxMask();
|
||||
int w = sz.x, h = sz.y;
|
||||
bmp.SetMask(mask);
|
||||
dc.SelectObject(bmp);
|
||||
if (color == wxNullColour)
|
||||
dc.SetBrush(wxBrush(wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW)));
|
||||
else
|
||||
dc.SetBrush(wxBrush(color));
|
||||
|
||||
dc.DrawRectangle(0, 0, w, h);
|
||||
images.push_back(wxBitmapBundle(bmp));
|
||||
SetItemImage(item, n);
|
||||
wxString s = GetItemText(item);
|
||||
n++;
|
||||
}
|
||||
if (images.size() > 0) {
|
||||
SetImages(images);
|
||||
}
|
||||
}
|
||||
void ctlTreeJSON::LoadInTree(wxJSONValue& jval, const wxTreeItemId& idParent) {
|
||||
wxJSONValue def;
|
||||
if (jval.AsArray()) {
|
||||
for (int i = 0; i < jval.Size(); ++i) {
|
||||
wxString key = "";
|
||||
wxJSONValue jv = jval.Item(i);
|
||||
wxTreeItemId item;
|
||||
if (!(jv.IsObject() || jv.IsArray())) key += "" + jv.AsString();
|
||||
else
|
||||
key = wxString::Format("[%d]", i);
|
||||
item = addtree(idParent, key, &jv);
|
||||
conf[item] = jv;
|
||||
if ((jv.IsObject() || jv.IsArray()))
|
||||
LoadInTree(jv, item);
|
||||
}
|
||||
}
|
||||
else
|
||||
if (jval.IsObject()) {
|
||||
wxArrayString arr = jval.GetMemberNames();
|
||||
// sort
|
||||
struct ss {
|
||||
int sort_id;
|
||||
wxString key;
|
||||
};
|
||||
std::vector<ss> ord;
|
||||
for (int i = 0; i < arr.Count(); ++i) {
|
||||
const wxJSONValue& jv = jval.Get(arr[i], def);
|
||||
if (jv.AsArray()) ord.push_back({ 5000,arr[i] });
|
||||
else if (jv.IsObject()) ord.push_back({ 4000,arr[i] });
|
||||
else ord.push_back({ 3000,arr[i] });
|
||||
}
|
||||
std::sort(ord.begin(), ord.end(),
|
||||
[](const ss& lhs, const ss& rhs) {return std::tie(lhs.sort_id, lhs.key) < std::tie(rhs.sort_id, rhs.key); });
|
||||
// append tree
|
||||
for (const auto& j : ord) {
|
||||
wxJSONValue jv = jval.Item(j.key);
|
||||
wxTreeItemId item;
|
||||
wxString key = j.key;
|
||||
if (!(jv.IsObject() || jv.IsArray())) key += ":" + jv.AsString();
|
||||
if ((jv.IsArray())) key += "[]";
|
||||
if ((jv.IsObject())) key += "{}";
|
||||
item = addtree(idParent, key, &jv);
|
||||
conf[item] = jv;
|
||||
if ((jv.IsObject() || jv.IsArray())) LoadInTree(jv, item);
|
||||
}
|
||||
}
|
||||
else {
|
||||
wxTreeItemId item;
|
||||
wxJSONValue* vv = &jval;
|
||||
wxString text = jval.AsString();
|
||||
item = addtree(idParent, text, vv);
|
||||
conf[item] = jval;
|
||||
}
|
||||
};
|
||||
|
||||
//ctlTreeJSON::ctlTreeJSON(wxWindow* parent, wxWindowID id, const wxPoint& pos, const wxSize& size, long style): wxTreeCtrl(parent, id, pos, size, style) {};
|
||||
|
||||
void ctlTreeJSON::InitMy() {
|
||||
//ReadJSON();
|
||||
settings->ReloadJsonFileIfNeed();
|
||||
|
||||
wxJSONValue r(wxJSONTYPE_NULL);
|
||||
DeleteAllItems();
|
||||
m_change = false;
|
||||
colors.clear();
|
||||
conf.clear();
|
||||
orig.clear();
|
||||
findsId.clear();
|
||||
m_FindString = "";
|
||||
m_tree =settings->jsoncfg;
|
||||
if (m_tree.IsNull()) return;
|
||||
m_root = addtree(m_root, "root", &r);
|
||||
LoadInTree(m_tree, m_root);
|
||||
RefreshImageList();
|
||||
#ifdef __WXMSW__
|
||||
// GTK 3 bug visualization
|
||||
ExpandAll();
|
||||
#endif // __WXMSW__
|
||||
}
|
||||
void ctlTreeJSON::Save() {
|
||||
if (m_change) {
|
||||
wxTreeItemId item = m_root, child;
|
||||
wxTreeItemIdValue cookie, cookie2;
|
||||
wxJSONValue v(wxJSONTYPE_OBJECT);
|
||||
wxString itemtext;
|
||||
int i = 0;
|
||||
child = GetFirstChild(m_root, cookie);
|
||||
while (child.IsOk())
|
||||
{
|
||||
wxString name = GetItemText(child);
|
||||
name = name.Left(name.length() - 2);
|
||||
wxJSONValue v2(wxJSONTYPE_OBJECT);
|
||||
child = GetFirstChild(child, cookie2);
|
||||
NodeToJSON(child, v2);
|
||||
v[name] = v2;
|
||||
settings->WriteJsonObect(name, v2);
|
||||
child = GetNextChild(m_root, cookie);
|
||||
}
|
||||
settings->WriteJsonFile();
|
||||
m_change = false;
|
||||
}
|
||||
|
||||
}
|
||||
ctlTreeJSON::~ctlTreeJSON()
|
||||
{
|
||||
// Save();
|
||||
}
|
||||
|
||||
|
|
@ -52,6 +52,7 @@
|
|||
#define QUERYTOOL_HISTORYFILE_ITEM _("History file")
|
||||
#define DATABASEDESIGNER_ITEM _("Database Designer")
|
||||
#define SERVERSTATUS_ITEM _("Server status")
|
||||
#define TREEJSON_ITEM _("PgAdmin3opt settings")
|
||||
#define MISC_ITEM _("Miscellaneous")
|
||||
#define MISC_UI_ITEM _("User Interface")
|
||||
#define MISC_HELPPATH_ITEM _("Help paths")
|
||||
|
|
@ -137,6 +138,7 @@
|
|||
#define chkJumpRoot CTRL_CHECKBOX("chkJumpRoot")
|
||||
#define menus CTRL_TREE("menus")
|
||||
#define pnlBrowserDisplay CTRL_PANEL("pnlBrowserDisplay")
|
||||
#define pnlTreeJSON CTRL_PANEL("pnlTreeJSON")
|
||||
#define pnlBrowserProperties CTRL_PANEL("pnlBrowserProperties")
|
||||
#define pnlBrowserBinPath CTRL_PANEL("pnlBrowserBinPath")
|
||||
#define pnlBrowserMisc CTRL_PANEL("pnlBrowserMisc")
|
||||
|
|
@ -155,7 +157,7 @@
|
|||
#define pnlMiscLogging CTRL_PANEL("pnlMiscLogging")
|
||||
#define cbRefreshOnClick CTRL_COMBOBOX("cbRefreshOnClick")
|
||||
#define pickerFontDD CTRL_FONTPICKER("pickerFontDD")
|
||||
|
||||
#define treeJSON CTRL_TREEJSON("treeJSON")
|
||||
|
||||
BEGIN_EVENT_TABLE(frmOptions, pgDialog)
|
||||
EVT_MENU(MNU_HELP, frmOptions::OnHelp)
|
||||
|
|
@ -282,6 +284,14 @@ frmOptions::frmOptions(frmMain *parent)
|
|||
wxAcceleratorTable accel(1, entries);
|
||||
SetAcceleratorTable(accel);
|
||||
|
||||
|
||||
//wxPanel* parentForTree = XRCCTRL(*this, "pnlTreeJSON", wxPanel);
|
||||
//m_jsontree = new ctlTreeJSON();
|
||||
//m_jsontree->Create(parentForTree, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTR_HAS_BUTTONS | wxSIMPLE_BORDER | wxTR_EDIT_LABELS | wxTR_FULL_ROW_HIGHLIGHT | wxTR_NO_LINES | wxTR_HIDE_ROOT);
|
||||
//m_jsontree->InitMy();
|
||||
//wxXmlResource::Get()->AttachUnknownControl("treeJSON", m_jsontree);
|
||||
treeJSON->InitMy();
|
||||
|
||||
wxTextValidator numval(wxFILTER_NUMERIC);
|
||||
txtMaxRows->SetValidator(numval);
|
||||
txtMaxColSize->SetValidator(numval);
|
||||
|
|
@ -475,6 +485,8 @@ frmOptions::frmOptions(frmMain *parent)
|
|||
menus->AppendItem(node, MISC_GURUHINTS_ITEM);
|
||||
menus->AppendItem(node, MISC_LOGGING_ITEM);
|
||||
|
||||
node = menus->AppendItem(root, TREEJSON_ITEM);
|
||||
|
||||
menus->ExpandAllChildren(root);
|
||||
|
||||
menuSelection = settings->GetOptionsLastTreeItem();
|
||||
|
|
@ -927,7 +939,8 @@ void frmOptions::OnOK(wxCommandEvent &ev)
|
|||
// in the selected language.
|
||||
if (changed)
|
||||
wxMessageBox(_("Changes to the display options may not be visible until the browser tree is refreshed."), _("Display options"), wxICON_INFORMATION | wxOK);
|
||||
|
||||
treeJSON->Save();
|
||||
//m_jsontree->Save();
|
||||
Destroy();
|
||||
}
|
||||
|
||||
|
|
@ -990,6 +1003,7 @@ void frmOptions::ShowPanel(const wxTreeItemId &menuItem)
|
|||
{
|
||||
// Hide everything
|
||||
pnlBrowserDisplay->Show(false);
|
||||
pnlTreeJSON->Show(false);
|
||||
pnlBrowserProperties->Show(false);
|
||||
pnlBrowserBinPath->Show(false);
|
||||
pnlBrowserMisc->Show(false);
|
||||
|
|
@ -1050,6 +1064,8 @@ void frmOptions::ShowPanel(const wxTreeItemId &menuItem)
|
|||
|
||||
else if (menuSelection == DATABASEDESIGNER_ITEM)
|
||||
pnlDatabaseDesigner->Show(true);
|
||||
else if (menuSelection == TREEJSON_ITEM)
|
||||
pnlTreeJSON->Show(true);
|
||||
|
||||
else if (menuSelection == SERVERSTATUS_ITEM)
|
||||
{
|
||||
|
|
|
|||
57
include/ctl/ctlTreeJSON.h
Normal file
57
include/ctl/ctlTreeJSON.h
Normal file
|
|
@ -0,0 +1,57 @@
|
|||
#ifndef CTLTREEJSON_H
|
||||
#define CTLTREEJSON_H
|
||||
|
||||
|
||||
|
||||
#include <wx/wx.h>
|
||||
#include <wx/treectrl.h>
|
||||
#include <wx/timer.h>
|
||||
#include "utils/json/jsonval.h"
|
||||
#include <map>
|
||||
class ctlTreeJSON : public wxTreeCtrl
|
||||
{
|
||||
public:
|
||||
ctlTreeJSON() :wxTreeCtrl(){};
|
||||
// ctlTreeJSON(wxWindow* parent, wxWindowID id, const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxDefaultSize, long style = wxTR_HAS_BUTTONS);
|
||||
virtual ~ctlTreeJSON();
|
||||
void ReadJSON();
|
||||
void AddJSONValue(const wxJSONValue& parent, const wxJSONValue& jval);
|
||||
void LoadInTree(wxJSONValue& jval, const wxTreeItemId& idParent);
|
||||
void Save();
|
||||
void InitMy();
|
||||
DECLARE_DYNAMIC_CLASS(ctlTreeJSON)
|
||||
DECLARE_EVENT_TABLE()
|
||||
private:
|
||||
wxTreeItemId addtree(const wxTreeItemId& idParent, wxString text, wxJSONValue* jval);
|
||||
void RefreshImageList();
|
||||
/// <summary>
|
||||
///
|
||||
/// -1 bad color
|
||||
/// 0 other element
|
||||
/// 1 - colour change
|
||||
/// </summary>
|
||||
/// <param name="newColour"> new color or empty</param>
|
||||
/// <param name="textLabel"> new text label or empty</param>
|
||||
int RefreshImages(const wxTreeItemId& id, wxColour newColour, wxString textLabel);
|
||||
void OnChar(wxKeyEvent& event);
|
||||
void OnDeleteItem(wxTreeEvent& event);
|
||||
void OnBeginEdit(wxTreeEvent& event);
|
||||
void OnEndEdit(wxTreeEvent& event);
|
||||
void OnDoubleClick(wxMouseEvent& event);
|
||||
void CopyNode(const wxTreeItemId& idSource);
|
||||
void BuildFind();
|
||||
wxTreeItemId NodeToJSON(const wxTreeItemId& id, wxJSONValue& newjson);
|
||||
wxTreeItemId findTreeItem(const wxTreeItemId& root, const wxString& text, bool bCaseSensitive, bool bExactMatch);
|
||||
wxTreeItemId nextTreeItem(const wxTreeItemId& item);
|
||||
wxJSONValue copyjson(wxJSONValue& src);
|
||||
std::map<wxTreeItemId, wxJSONValue> conf;
|
||||
std::map<wxTreeItemId, wxJSONValue> orig;
|
||||
std::map<wxTreeItemId, wxColour> colors;
|
||||
wxJSONValue m_tree;
|
||||
wxTreeItemId m_root;
|
||||
wxString m_FindString;
|
||||
std::map<wxTreeItemId, int> findsId;
|
||||
bool m_change = false;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
@ -27,6 +27,7 @@
|
|||
|
||||
#include "utils/misc.h"
|
||||
#include <ctl/ctlTree.h>
|
||||
#include <ctl/ctlTreeJSON.h>
|
||||
#include "ctl/ctlSQLBox.h"
|
||||
#include "ctl/ctlListView.h"
|
||||
#include "ctl/ctlComboBox.h"
|
||||
|
|
|
|||
|
|
@ -22,6 +22,7 @@
|
|||
// Class declarations
|
||||
class sysSettings : private wxConfig
|
||||
{
|
||||
friend class ctlTreeJSON;
|
||||
public:
|
||||
sysSettings(const wxString &name);
|
||||
~sysSettings();
|
||||
|
|
|
|||
|
|
@ -22,11 +22,11 @@
|
|||
<border>3</border>
|
||||
</object>
|
||||
<object class="sizeritem">
|
||||
<object class="wxFlexGridSizer">
|
||||
<object class="wxFlexGridSizer">
|
||||
<cols>1</cols>
|
||||
<vgap>5</vgap>
|
||||
<hgap>5</hgap>
|
||||
<growablerows>0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15</growablerows>
|
||||
<growablerows>0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17</growablerows>
|
||||
<growablecols>0</growablecols>
|
||||
<object class="sizeritem">
|
||||
<object class="wxPanel" name="pnlMiscHelpPath">
|
||||
|
|
@ -166,7 +166,35 @@
|
|||
<flag>wxEXPAND|wxTOP|wxLEFT|wxRIGHT</flag>
|
||||
<border>4</border>
|
||||
</object>
|
||||
<object class="sizeritem">
|
||||
<object class="sizeritem">
|
||||
<object class="wxPanel" name="pnlTreeJSON">
|
||||
<hidden>1</hidden>
|
||||
<object class="wxFlexGridSizer">
|
||||
<cols>1</cols>
|
||||
<vgap>5</vgap>
|
||||
<hgap>5</hgap>
|
||||
<growablerows>1</growablerows>
|
||||
<growablecols>0</growablecols>
|
||||
<object class="sizeritem">
|
||||
<object class="wxStaticText" name="stTreeJSON">
|
||||
<label>Options extended JSON:</label>
|
||||
</object>
|
||||
<flag>wxEXPAND|wxTOP|wxLEFT|wxRIGHT</flag>
|
||||
<border>4</border>
|
||||
</object>
|
||||
<object class="sizeritem">
|
||||
<object class="wxTreeCtrl" name="treeJSON" subclass="ctlTreeJSON">
|
||||
<style>wxTR_HAS_BUTTONS|wxSIMPLE_BORDER|wxTR_EDIT_LABELS|wxTR_FULL_ROW_HIGHLIGHT|wxTR_NO_LINES|wxTR_HIDE_ROOT</style>
|
||||
</object>
|
||||
<flag>wxEXPAND|wxTOP|wxLEFT|wxRIGHT</flag>
|
||||
<border>4</border>
|
||||
</object>
|
||||
</object>
|
||||
</object>
|
||||
<flag>wxEXPAND|wxTOP|wxLEFT|wxRIGHT</flag>
|
||||
<border>4</border>
|
||||
</object>
|
||||
<object class="sizeritem">
|
||||
<object class="wxPanel" name="pnlBrowserProperties">
|
||||
<hidden>1</hidden>
|
||||
<object class="wxFlexGridSizer">
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue