mirror of
https://github.com/levinsv/pgadmin3.git
synced 2026-05-15 06:05:49 -06:00
При открытии таблицы на редактирование с фильтром, значение заданного фильтра сохраняется в pgadmin3opt.json. Мелкие правки dlgTransformText
957 lines
No EOL
29 KiB
C++
957 lines
No EOL
29 KiB
C++
#include "pgAdmin3.h"
|
||
#include "utils/dlgTransformText.h"
|
||
#include "frm/frmMain.h"
|
||
#include "ctl/ctlStyledText.h"
|
||
#include "utils/sysSettings.h"
|
||
#include <wx/log.h>
|
||
#include <limits>
|
||
|
||
BEGIN_EVENT_TABLE(dlgTransformText, pgDialog)
|
||
//EVT_KEY_DOWN(dlgTransformText::OnKeyDown)
|
||
//EVT_BUTTON(XRCID("btnCancel"), dlgTransformText::OnCancel)
|
||
EVT_BUTTON(wxID_CANCEL, dlgTransformText::OnCancel)
|
||
|
||
EVT_BUTTON(XRCID("btnOk"), dlgTransformText::OnOk)
|
||
EVT_BUTTON(XRCID("btnSave"), dlgTransformText::OnSave)
|
||
|
||
EVT_CHECKBOX(XRCID("chkHighLight"), dlgTransformText::OnChangeOnline)
|
||
//EVT_TEXT(XRCID("LimitCharsText"), dlgTransformText::OnChange)
|
||
//EVT_TEXT(XRCID("LimitRowsText"), dlgTransformText::OnChange)
|
||
EVT_COMBOBOX(XRCID("beforeRowCB"), dlgTransformText::OnChange)
|
||
EVT_COMBOBOX(XRCID("sepFieldCB"), dlgTransformText::OnChange)
|
||
EVT_COMBOBOX(XRCID("afterRowCB"), dlgTransformText::OnChange)
|
||
//EVT_COMBOBOX(XRCID("afterFieldCB"), dlgTransformText::OnChange)
|
||
EVT_COMBOBOX(XRCID("optionsLoadCB"), dlgTransformText::OnLoad)
|
||
EVT_TEXT(XRCID("beforeRowCB"), dlgTransformText::OnChange)
|
||
EVT_TEXT(XRCID("sepFieldCB"), dlgTransformText::OnChange)
|
||
EVT_TEXT(XRCID("afterRowCB"), dlgTransformText::OnChange)
|
||
//EVT_TEXT(XRCID("afterFieldCB"), dlgTransformText::OnChange)
|
||
EVT_TEXT(XRCID("LimitRowsText"), dlgTransformText::OnChangeLimit)
|
||
EVT_TEXT(XRCID("LimitCharsText"), dlgTransformText::OnChangeLimit)
|
||
//EVT_KILL_FOCUS(dlgTransformText::OnKillFocus)
|
||
|
||
//EVT_STC_MODIFIED(XRCID("RegText"), dlgTransformText::OnChangeRegEx)
|
||
//EVT_STC_MODIFIED(XRCID("ReplaceText"), dlgTransformText::OnChangeRegEx)
|
||
EVT_STC_UPDATEUI(XRCID("RegText"), dlgTransformText::OnChangeRegEx2)
|
||
EVT_STC_UPDATEUI(XRCID("ReplaceText"), dlgTransformText::OnChangeRegEx2)
|
||
//EVT_COMMAND_KILL_FOCUS(XRCID("RegText"), dlgTransformText::OnKillFocusRegEx)
|
||
//EVT_TEXT(XRCID("RegText"), dlgTransformText::OnChangeRegEx)
|
||
EVT_IDLE(dlgTransformText::OnIdle)
|
||
|
||
EVT_CLOSE(dlgTransformText::OnClose)
|
||
|
||
END_EVENT_TABLE()
|
||
|
||
|
||
#define btnOK CTRL_BUTTON("wxID_OK")
|
||
#define btnCancel CTRL_BUTTON("wxID_CANCEL")
|
||
#define btnSave CTRL_BUTTON("btnSave")
|
||
#define m_msg CTRL_STATIC("m_msg")
|
||
//#define afterFieldCB CTRL_COMBOBOX1("afterFieldCB")
|
||
|
||
#define srcText CTRL_STYLEDTEXT("srcText")
|
||
#define trgText CTRL_STYLEDTEXT("trgText")
|
||
#define LimitCharsText CTRL_TEXT("LimitCharsText")
|
||
#define LimitRowsText CTRL_TEXT("LimitRowsText")
|
||
#define chkHighLight CTRL_CHECKBOX("chkHighLight")
|
||
|
||
#define beforeRowCB CTRL_COMBOBOX1("beforeRowCB")
|
||
#define afterRowCB CTRL_COMBOBOX1("afterRowCB")
|
||
#define sepFieldCB CTRL_COMBOBOX1("sepFieldCB")
|
||
//#define afterFieldCB CTRL_COMBOBOX1("afterFieldCB")
|
||
|
||
#define optionsLoadCB CTRL_COMBOBOX1("optionsLoadCB")
|
||
|
||
#define txtField CTRL_STYLEDTEXT("RegText")
|
||
#define trgField CTRL_STYLEDTEXT("ReplaceText")
|
||
|
||
|
||
|
||
dlgTransformText::dlgTransformText(ctlSQLBox* form,const wxString source) : pgDialog()
|
||
{
|
||
this->inizialize = true;
|
||
SetFont(settings->GetSystemFont());
|
||
LoadResource(form, wxT("dlgTransformText"));
|
||
RestorePosition();
|
||
SetTitle(_("Transformation text"));
|
||
LoadOptions();
|
||
//srcText->Set
|
||
//extern sysSettings* settings;
|
||
SetDecoration(srcText);
|
||
SetDecoration(trgText);
|
||
SetDecoration(txtField);
|
||
|
||
SetDecoration(trgField);
|
||
txtField->setRegExphighlight(true);
|
||
|
||
wxAcceleratorEntry entries[1];
|
||
entries[0].Set(wxACCEL_NORMAL, WXK_ESCAPE, wxID_CANCEL);
|
||
wxAcceleratorTable accel(1, entries);
|
||
SetAcceleratorTable(accel);
|
||
//optionsLoadCB->Connect(wxID_ANY, wxEVT_KILL_FOCUS, wxFocusEventHandler(dlgTransformText::OnKillFocus),this);
|
||
|
||
}
|
||
void dlgTransformText::SetDecoration(ctlStyledText *s) {
|
||
wxFont fntSQLBox = settings->GetSQLFont();
|
||
//srcText->StyleSetForeground(wxSTC_STYLE_DEFAULT, frColor);
|
||
s->StyleSetFont(wxSTC_STYLE_DEFAULT, fntSQLBox);
|
||
|
||
s->SetSelBackground(true, wxSystemSettings::GetColour(wxSYS_COLOUR_HIGHLIGHT));
|
||
s->SetSelForeground(true, wxSystemSettings::GetColour(wxSYS_COLOUR_HIGHLIGHTTEXT));
|
||
|
||
}
|
||
dlgTransformText::~dlgTransformText()
|
||
{
|
||
SavePosition();
|
||
}
|
||
void dlgTransformText::SetSource(const wxString& src) {
|
||
//
|
||
//srcText->SetValue(src);
|
||
this->src = src;
|
||
showNumber(srcText, true);
|
||
showNumber(trgText, true);
|
||
this->inizialize = false;
|
||
wxStyledTextEvent ev;
|
||
strResult = wxEmptyString;
|
||
strReg = wxEmptyString;
|
||
//OnChangeRegEx2(ev);
|
||
isNeedTransform = true;
|
||
}
|
||
|
||
void dlgTransformText::showNumber(ctlStyledText* text, bool visible)
|
||
{
|
||
if (visible) {
|
||
long int width = text->TextWidth(wxSTC_STYLE_LINENUMBER,
|
||
wxT(" ") + wxString::Format("%ld", (long int)limitLine) + wxT(" "));
|
||
if (width != text->GetMarginWidth(0))
|
||
{
|
||
text->SetMarginWidth(0, width);
|
||
text->Update();
|
||
}
|
||
text->SetViewWhiteSpace(wxSTC_WS_VISIBLEALWAYS);
|
||
text->SetViewEOL(true);
|
||
}
|
||
else {
|
||
text->SetMarginWidth(0, 0);
|
||
text->Update();
|
||
}
|
||
}
|
||
wxJSONValue dlgTransformText::LoadConfig(const wxString confname) {
|
||
wxJSONValue conf(wxJSONType::wxJSONTYPE_OBJECT);
|
||
wxString n;
|
||
if (confname.IsEmpty()) n = "last"; else n = confname;
|
||
bool ischange = false;
|
||
bool t_inizialize = inizialize;
|
||
inizialize = true;
|
||
conf = opt["configurations"][n];
|
||
bool islastconf=false;
|
||
if (!conf.IsNull() && lastconf.Size() > 0) islastconf = true;
|
||
if (!conf.IsNull()) {
|
||
wxString s;
|
||
s = conf["beforeRow"].AsString();
|
||
if (islastconf && s != lastconf["beforeRow"].AsString()) {
|
||
s = lastconf["beforeRow"].AsString();
|
||
ischange = true;
|
||
}
|
||
beforeRowCB->SetValue(s);
|
||
s = conf["afterRow"].AsString();
|
||
if (islastconf && s != lastconf["afterRow"].AsString()) {
|
||
s = lastconf["afterRow"].AsString();
|
||
ischange = true;
|
||
}
|
||
afterRowCB->SetValue(s);
|
||
s = conf["sepField"].AsString();
|
||
if (islastconf && s != lastconf["sepField"].AsString()) {
|
||
s = lastconf["sepField"].AsString();
|
||
ischange = true;
|
||
}
|
||
sepFieldCB->SetValue(s);
|
||
s = conf["regexp"].AsString();
|
||
if (islastconf && s != lastconf["regexp"].AsString()) {
|
||
s = lastconf["regexp"].AsString();
|
||
ischange = true;
|
||
}
|
||
txtField->SetText(s);
|
||
s = conf["replace"].AsString();
|
||
if (islastconf && s != lastconf["replace"].AsString()) {
|
||
s = lastconf["replace"].AsString();
|
||
ischange = true;
|
||
}
|
||
trgField->SetText(s);
|
||
//afterFieldCB->SetValue(conf["fieldSeparator"].AsString());
|
||
if (islastconf) {
|
||
opt["currentConfingName"] = n;
|
||
}
|
||
if (ischange) n = '*' + n;
|
||
optionsLoadCB->SetValue(n);
|
||
isChange = ischange;
|
||
lastconf = conf;
|
||
}
|
||
inizialize = t_inizialize;
|
||
return lastconf;
|
||
}
|
||
void dlgTransformText::LoadOptions() {
|
||
|
||
wxJSONValue def(wxJSONType::wxJSONTYPE_OBJECT);
|
||
//wxJSONValue confArray(wxJSONType::wxJSONTYPE_ARRAY);
|
||
wxJSONValue confs(wxJSONType::wxJSONTYPE_OBJECT);
|
||
wxJSONValue grpArray(wxJSONType::wxJSONTYPE_ARRAY);
|
||
opt.SetType(wxJSONType::wxJSONTYPE_OBJECT);
|
||
lastconf.SetType(wxJSONType::wxJSONTYPE_OBJECT);
|
||
const wxString clrgroup[] = { "#ffff00"
|
||
,"#c4e8ac","#f7d6a6","#c7c7fc","#f1cdfd","#ffc6be"
|
||
,"#cae7d6" ,"#c4e7ab" ,"#f4d7a5" ,"#c7c8fe","#f2cffd"
|
||
,"#ffc4bd", "#c7e7d4" };
|
||
for (int k = 0; k < sizeof(clrgroup) / sizeof(clrgroup[0]); k++) {
|
||
//wxJSONValue grp(wxJSONType::wxJSONTYPE_OBJECT);
|
||
//grp["number"] = k;
|
||
//grp["color"] = clrgroup[k];
|
||
|
||
grpArray.Append(clrgroup[k]);
|
||
}
|
||
def["colorGroup"] = grpArray;
|
||
def["newLineSeparator"] = wxString("\\r\\n|\\r[^\\n]|\\n");
|
||
def["bgErrorColor"] = wxString("#f4dcdc");
|
||
wxJSONValue conf(wxJSONType::wxJSONTYPE_OBJECT);
|
||
//conf["name"] = wxString("last");
|
||
wxString name = "last";
|
||
//conf["name"] = wxString("last");
|
||
def["currentConfingName"] = wxString("");
|
||
conf["regexp"] = wxString("\\d+");
|
||
conf["replace"] = wxString("\\g{0}");
|
||
conf["beforeRow"] = wxString("");
|
||
conf["afterRow"] = wxString("");
|
||
conf["sepField"] = wxString(",");
|
||
conf["afterField"] = wxString("");
|
||
conf["fieldSeparator"] = wxString("");
|
||
confs[name] = conf;
|
||
def["configurations"] = confs;
|
||
def["onLineRefresh"] = true;
|
||
int limline = 50;
|
||
def["LimitShowLine"] = limline;
|
||
int limchar = 50000;
|
||
def["LimitShowChar"] = limchar;
|
||
settings->ReloadJsonFileIfNeed();
|
||
settings->ReadJsonObect(dlgName, opt, def);
|
||
if (!opt.IsNull()) {
|
||
wxString strcolor = opt["bgErrorColor"].AsString();
|
||
wxColour cc(strcolor);
|
||
if (!cc.IsOk()) opt["bgErrorColor"] = def["bgErrorColor"];
|
||
|
||
}
|
||
else opt = def;
|
||
bgerror = wxColour(opt["bgErrorColor"].AsString());
|
||
lastconf = opt["configurations"][name];
|
||
wxArrayString ar = opt["configurations"].GetMemberNames();
|
||
for (int i = 0; i < ar.Count(); i++) {
|
||
wxString s;
|
||
wxJSONValue cf= opt["configurations"][ar[i]];
|
||
wxString s2;
|
||
if (ar[i] == "last") continue;
|
||
s2 = cf["beforeRow"].AsString();
|
||
beforeRowCB->Append(s2);
|
||
s2 = cf["afterRow"].AsString();
|
||
afterRowCB->Append(s2);
|
||
s2 = cf["sepField"].AsString();
|
||
sepFieldCB->Append(s2);
|
||
// s2 = cf["afterField"].AsString();
|
||
// afterFieldCB->Append(s2);
|
||
s2 = ar[i];
|
||
optionsLoadCB->Append(s2);
|
||
}
|
||
wxString s=opt["currentConfingName"].AsString();
|
||
if (opt["LimitShowLine"].IsInt()) limline= opt["LimitShowLine"].AsInt();
|
||
if (opt["LimitShowChar"].IsInt()) limchar = opt["LimitShowChar"].AsInt();
|
||
limitLine = limline;
|
||
limitChar = limchar;
|
||
srcRowSep = opt["newLineSeparator"].AsString();
|
||
wxRegEx RegNewLine(srcRowSep, wxRE_NEWLINE);
|
||
if (!RegNewLine.IsValid()) srcRowSep= def["newLineSeparator"].AsString();
|
||
LimitRowsText->SetValue(opt["LimitShowLine"].AsString());
|
||
LimitCharsText->SetValue(opt["LimitShowChar"].AsString());
|
||
isOnline = chkHighLight->IsChecked();
|
||
LoadConfig(s);
|
||
wxCommandEvent ev;
|
||
OnCheckUI(ev);
|
||
}
|
||
|
||
int str_to_int(const wxString& s) {
|
||
int ii = INT_MAX;
|
||
int scanned = wxSscanf(s, "%d", &ii);
|
||
return ii;
|
||
}
|
||
void dlgTransformText::CheckLimits() {
|
||
wxString s = LimitRowsText->GetValue();
|
||
int l;
|
||
l = str_to_int(s);
|
||
if (s.length() == 0|| l==0) {
|
||
l = INT_MAX; // unlimited
|
||
}
|
||
else {
|
||
if (l == INT_MAX) l = 50;
|
||
}
|
||
limitLine = l;
|
||
s = LimitCharsText->GetValue();
|
||
l = str_to_int(s);
|
||
if (s.length() == 0|| l==0) {
|
||
l = INT_MAX; // unlimited
|
||
}
|
||
else {
|
||
|
||
if (l == INT_MAX) l = 50000;
|
||
}
|
||
limitChar = l;
|
||
|
||
}
|
||
std::vector<dlgTransformText::replace_opt> dlgTransformText::BuildString(const wxString repstr) {
|
||
std::vector<replace_opt> rez;
|
||
bool isback = false;
|
||
wxString a;
|
||
wxString e;
|
||
for (int i = 0; i < repstr.length(); i++) {
|
||
wxChar c = repstr[i];
|
||
if (c == '\n'|| c=='\r') continue;
|
||
if (!isback && c == '\\') {
|
||
isback = true;
|
||
continue;
|
||
}
|
||
if (isback) {
|
||
if (c == 'r') c = '\r';
|
||
else if (c == 'n') c = '\n';
|
||
else if (c == 't') c = '\t';
|
||
else if (c == 'g'|| c=='G') {
|
||
int l = repstr.length();
|
||
if (l - i > 2) {
|
||
int pos = repstr.find_first_of('}', i);
|
||
int flags = 0;
|
||
if (pos >= 0) {
|
||
wxString ngrp = repstr.substr(i + 2, pos - i - 2);
|
||
int ngroup = -1;
|
||
int scanned = wxSscanf(ngrp, "%d", &ngroup);
|
||
if (scanned == 1) {
|
||
if (a.length() > 0) rez.push_back({ false,(int)eTypeGroup::SIMPLE_TEXT,a });
|
||
a.clear();
|
||
if (c == 'G') flags |= 1;
|
||
rez.push_back({ true,ngroup,wxEmptyString,flags,i-1,pos-i+2 });
|
||
i = pos;
|
||
isback = false;
|
||
continue;
|
||
}
|
||
}
|
||
}
|
||
e = wxString::Format("\\g{n} incorrect in pos %d", i);
|
||
}
|
||
isback = false;
|
||
}
|
||
else if (c == '[') {
|
||
if (a.length() > 0) rez.push_back({ false,(int)eTypeGroup::SIMPLE_TEXT,a });
|
||
a.clear();
|
||
rez.push_back({ true,(int)eTypeGroup::USER_GROUP_START,wxEmptyString });
|
||
continue;
|
||
}
|
||
else if (c == ']') {
|
||
if (a.length() > 0) rez.push_back({ false,(int)eTypeGroup::SIMPLE_TEXT,a });
|
||
a.clear();
|
||
rez.push_back({ true,(int)eTypeGroup::USER_GROUP_END,wxEmptyString });
|
||
continue;
|
||
}
|
||
a.Append(c);
|
||
if (e.length() > 0) break;
|
||
}
|
||
if (a.length() > 0) rez.push_back({ false,(int)eTypeGroup::SIMPLE_TEXT,a });
|
||
return rez;
|
||
}
|
||
void dlgTransformText::AppendTextControl(ctlStyledText* ctrl, const wxString appendtext, bool isnewline) {
|
||
bool isLimit = limitLine <= 0 || limitChar <= 0;
|
||
if (ctrl == srcText) {
|
||
// control limit
|
||
if (isnewline)
|
||
if (limitLine > 0)
|
||
limitLine--;
|
||
else
|
||
isLimit = true;
|
||
if (limitChar > 0)
|
||
limitChar -= appendtext.length();
|
||
else
|
||
isLimit = true;
|
||
if (!isLimit) ctrl->AppendText(appendtext);
|
||
}
|
||
else {
|
||
strResult.Append(appendtext);
|
||
ctrl->AppendText(appendtext);
|
||
}
|
||
}
|
||
wxJSONValue dlgTransformText::FillConfig() {
|
||
wxString s;
|
||
wxJSONValue n(wxJSONType::wxJSONTYPE_OBJECT);
|
||
s=beforeRowCB->GetValue();
|
||
n["beforeRow"]=s;
|
||
s = afterRowCB->GetValue();
|
||
n["afterRow"] = s;
|
||
s = sepFieldCB->GetValue();
|
||
n["sepField"] = s;
|
||
// s= afterFieldCB->GetValue();
|
||
// n["afterField"] = s;
|
||
// s=beforeFieldCB->GetValue();
|
||
// n["beforeField"] = s;
|
||
s= txtField->GetText();
|
||
n["regexp"] = s;
|
||
s= trgField->GetText();
|
||
n["replace"] = s;
|
||
return n;
|
||
};
|
||
void dlgTransformText::OnChange(wxCommandEvent& ev) {
|
||
OnComboSelect(ev);
|
||
isNeedTransform = true;
|
||
}
|
||
void dlgTransformText::OnChangeLimit(wxCommandEvent& ev) {
|
||
CheckLimits();
|
||
isNeedTransform = true;
|
||
}
|
||
void dlgTransformText::OnChangeOnline(wxCommandEvent& ev) {
|
||
isOnline = chkHighLight->IsChecked();
|
||
}
|
||
|
||
void dlgTransformText::OnLoad(wxCommandEvent& ev) {
|
||
wxString s = optionsLoadCB->GetValue();
|
||
//lastconf.Clear();
|
||
for (auto key: lastconf.GetMemberNames())
|
||
lastconf.Remove(key);
|
||
LoadConfig(s);
|
||
OnCheckUI(ev);
|
||
}
|
||
void dlgTransformText::OnComboSelect(wxCommandEvent& ev) {
|
||
//compare lastconf
|
||
if (inizialize) return;
|
||
wxJSONValue formconf = FillConfig();
|
||
wxArrayString ar;
|
||
ar=formconf.GetMemberNames();
|
||
isChange = false;
|
||
for (auto s:ar) {
|
||
wxString ls = lastconf[s].AsString();
|
||
wxString form = formconf[s].AsString();
|
||
if (form == ls) continue;
|
||
isChange = true;
|
||
//
|
||
if (s == "regexp") {
|
||
|
||
}
|
||
break;
|
||
}
|
||
wxString s = optionsLoadCB->GetValue();
|
||
bool isSimbol = s.length() > 1 && s.Mid(0, 1) == '*';
|
||
wxString name;
|
||
if (isSimbol) name = s.Mid(1); else name = s;
|
||
if (optionsLoadCB->FindString(name) < 0) {
|
||
isChange = false; // new config
|
||
|
||
}
|
||
if (isChange && !isSimbol) {
|
||
//wxString s = optionsLoadCB->GetValue();
|
||
if (!isSimbol) {
|
||
s = '*' + name;
|
||
optionsLoadCB->SetValue(s);
|
||
}
|
||
}
|
||
if (!isChange && isSimbol && ev.GetEventObject() != optionsLoadCB) optionsLoadCB->SetValue(name);
|
||
OnCheckUI(ev);
|
||
|
||
}
|
||
void dlgTransformText::OnSave(wxCommandEvent& ev) {
|
||
wxString s= optionsLoadCB->GetValue();
|
||
|
||
if (s.length() > 1 && s.Mid(0, 1) == '*') {
|
||
s = s.Mid(1);
|
||
}
|
||
else {
|
||
if (optionsLoadCB->FindString(s)<0) optionsLoadCB->Append(s);
|
||
}
|
||
|
||
opt["currentConfingName"] = s;
|
||
wxJSONValue formconf = FillConfig();
|
||
lastconf = formconf;
|
||
opt["configurations"][s] = formconf;
|
||
opt["configurations"]["last"] = formconf;
|
||
settings->WriteJsonObect(dlgName, opt);
|
||
settings->WriteJsonFile();
|
||
isChange = false;
|
||
optionsLoadCB->SetValue(s);
|
||
OnCheckUI(ev);
|
||
}
|
||
|
||
void dlgTransformText::OnCheckUI(wxCommandEvent& ev) {
|
||
wxString s = optionsLoadCB->GetValue();
|
||
bool issave = false;
|
||
if (s.length() > 1 && s.Mid(0, 1) == '*') issave = true;
|
||
if (s.length() > 0 && s.Mid(0, 1) != '*') {
|
||
if (optionsLoadCB->FindString(s) < 0) issave = true;;
|
||
|
||
}
|
||
btnSave->Enable(issave && isChange);
|
||
bool iscopy = strResult.length() > 0;
|
||
if (strResult.length()>0) btnSave->Enable(iscopy);
|
||
}
|
||
void dlgTransformText::OnIdle(wxIdleEvent& ev) {
|
||
if (inizialize) return;
|
||
if (!isOnline) return;
|
||
// int u = ev.GetUpdated();
|
||
// if (!(u & wxSTC_UPDATE_CONTENT)) return;
|
||
wxRegEx regfld;
|
||
wxString v = txtField->GetText();
|
||
wxString r = trgField->GetText();
|
||
if (v.length() == 0 || src.length() == 0 || r.length() == 0) return;
|
||
if (!isNeedTransform) return;
|
||
|
||
wxCommandEvent evt;
|
||
strResult = wxEmptyString;
|
||
bool fieldexp = false;
|
||
//if (v == strReg && strRep == r) return;
|
||
{
|
||
wxLogNull logNo;
|
||
fieldexp = regfld.Compile(v, wxRE_NEWLINE);
|
||
if (!fieldexp) {
|
||
if (trgText->GetTextLength() > 0)
|
||
toplineTrg = trgText->GetFirstVisibleLine();
|
||
|
||
trgText->ClearAll();
|
||
m_msg->SetLabelText(wxString::Format("Error regexp compile!!!"));
|
||
}
|
||
}
|
||
if (fieldexp) {
|
||
//txtField->SetBackgroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW));
|
||
|
||
//txtField->StyleSetBackground(wxSTC_STYLE_DEFAULT, wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW));
|
||
}
|
||
else {
|
||
|
||
//txtField->SetBackgroundColour(bgerror);
|
||
//txtField->StyleSetBackground(wxSTC_STYLE_DEFAULT, bgerror);
|
||
//srcText->ClearAll();
|
||
//int ls = srcText->GetText().length();
|
||
//if ((ls> limitChar )ls!=src.length())
|
||
//srcText->SetText(src.Mid(0, limitChar));
|
||
srcText->ClearDocumentStyle();
|
||
|
||
|
||
}
|
||
//txtField->Update();
|
||
if (fieldexp) {
|
||
TransformText(regfld);
|
||
strRep = r;
|
||
strReg = v;
|
||
|
||
OnComboSelect(evt);
|
||
}
|
||
else
|
||
{
|
||
strReg = "";
|
||
strRep = "";
|
||
}
|
||
OnCheckUI(evt);
|
||
isNeedTransform = false;
|
||
ev.Skip();
|
||
}
|
||
void dlgTransformText::OnChangeRegEx2(wxStyledTextEvent& ev) {
|
||
int u = ev.GetUpdated();
|
||
if ((u & wxSTC_UPDATE_CONTENT)) isNeedTransform = true;
|
||
|
||
}
|
||
void dlgTransformText::OnClose(wxCloseEvent& ev) {
|
||
this->Hide();
|
||
if (ev.CanVeto())
|
||
ev.Veto();
|
||
}
|
||
void dlgTransformText::OnCancel(wxCommandEvent& ev)
|
||
{
|
||
//SaveSettings();
|
||
this->Hide();
|
||
}
|
||
|
||
void dlgTransformText::OnOk(wxCommandEvent& ev) {
|
||
wxCloseEvent event;
|
||
if (strResult.length() > 0) {
|
||
|
||
|
||
//pgDialog::OnClose(event);
|
||
if (wxTheClipboard->Open())
|
||
{
|
||
wxDataObjectComposite* dataobj = new wxDataObjectComposite();
|
||
dataobj->Add(new wxTextDataObject(strResult));
|
||
wxTheClipboard->SetData(dataobj);
|
||
wxTheClipboard->Close();
|
||
}
|
||
}
|
||
this->Hide();
|
||
}
|
||
void dlgTransformText::SetStyled(ctlStyledText* s) {
|
||
int regstyle = wxSTC_STYLE_LASTPREDEFINED + 1;
|
||
s->StyleClearAll();
|
||
s->ClearDocumentStyle();
|
||
countGroupColor = opt["colorGroup"].Size();
|
||
for (int i = regstyle; i < regstyle + countGroupColor; i++) {
|
||
wxString strcl = opt["colorGroup"][i - regstyle].AsString();
|
||
wxColour clr(strcl);
|
||
if (clr.IsOk())
|
||
{
|
||
s->StyleSetBackground(i, clr);
|
||
}
|
||
else {
|
||
s->StyleSetBackground(i, wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW));
|
||
}
|
||
s->StyleSetForeground(i, *wxBLACK);
|
||
}
|
||
|
||
}
|
||
|
||
wxString dlgTransformText::ReplaceFormatting(
|
||
const wxString &src,
|
||
const wxRegEx &r,
|
||
const std::vector<dlgTransformText::replace_opt> st,
|
||
int &position,
|
||
interval m2[],
|
||
int maxsizeintervalarray,
|
||
int &currindex,
|
||
size_t &start_frame)
|
||
{
|
||
bool isEmptyGroup = true;
|
||
int maxgroup = r.GetMatchCount();
|
||
wxString replstr;
|
||
int ci=currindex;
|
||
size_t sf = start_frame;
|
||
while (position<st.size()) {
|
||
auto& j = st[position++];
|
||
wxString s;
|
||
if (j.isGroup && j.nGroup >= 0 && j.nGroup < maxgroup) {
|
||
s = r.GetMatch(src, j.nGroup);
|
||
if (ci >= maxsizeintervalarray) break;
|
||
if (s.length() > 0) isEmptyGroup = false;
|
||
// verify flags
|
||
if (j.flags & 1) {
|
||
// no print group
|
||
s = wxEmptyString;
|
||
}
|
||
m2[ci++] = { sf ,s.length(),j.nGroup };
|
||
replstr.Append(s);
|
||
}
|
||
else if (j.nGroup == (int)eTypeGroup::SIMPLE_TEXT) {
|
||
s = j.text;
|
||
replstr.Append(s);
|
||
}
|
||
else if (j.nGroup == (int)eTypeGroup::USER_GROUP_START) {
|
||
s = ReplaceFormatting(src, r, st, position, m2, 100, ci, sf);
|
||
if (s.length() > 0) {
|
||
isEmptyGroup = false;
|
||
}
|
||
replstr.Append(s);
|
||
continue;
|
||
}
|
||
else if (j.nGroup == (int)eTypeGroup::USER_GROUP_END) {
|
||
break;
|
||
}
|
||
sf += s.length();
|
||
}
|
||
if (isEmptyGroup) {
|
||
|
||
return wxEmptyString;
|
||
}
|
||
else {
|
||
// OK. save current posintion
|
||
currindex = ci;
|
||
start_frame = sf;
|
||
return replstr;
|
||
}
|
||
|
||
}
|
||
void dlgTransformText::TransformText(const wxRegEx ®fld) {
|
||
// Check params
|
||
interval m[100];
|
||
wxRegEx RegNewLine(srcRowSep, wxRE_NEWLINE);
|
||
if (trgText->GetTextLength()>0)
|
||
toplineTrg=trgText->GetFirstVisibleLine();
|
||
if (srcText->GetTextLength()>0)
|
||
toplineSrc = srcText->GetFirstVisibleLine();
|
||
srcText->StyleClearAll();
|
||
//srcText->SetText(src);
|
||
srcText->ClearAll();
|
||
trgText->StyleClearAll();
|
||
trgText->ClearAll();
|
||
strResult = wxEmptyString;
|
||
|
||
wxString c = opt["bgErrorColor"].AsString();
|
||
wxColour red(c);
|
||
//c = opt["colorGroup"][0].AsString();
|
||
wxColour sel("#ffff00");
|
||
int regstyle = wxSTC_STYLE_LASTPREDEFINED + 1;
|
||
SetStyled(srcText);
|
||
SetStyled(trgText);
|
||
SetStyled(trgField);
|
||
//bool fieldexp = regfld.Compile(v, wxRE_NEWLINE);
|
||
if (regfld.IsValid()) {
|
||
int sstart = 0;
|
||
//int s_indicHighlight = 20;
|
||
//srcText->IndicatorSetForeground(s_indicHighlight, wxColour(80, 236, 120));
|
||
//srcText->IndicatorSetForeground(s_indicHighlight, *wxBLUE);
|
||
//srcText->IndicatorSetStyle(s_indicHighlight, wxSTC_INDIC_DASH);
|
||
wxString tmp = src;
|
||
int numLine = 0;
|
||
bool isnewline = false;
|
||
// wxString sepRows = txtSepRows->GetValue();
|
||
// wxString sepField = txtSepField->GetValue();
|
||
wxString trgFieldReg = trgField->GetText();
|
||
std::vector<replace_opt> repArray;
|
||
std::vector<int> colorizetrgField(countGroupColor,-1);
|
||
repArray = BuildString(trgFieldReg);
|
||
if (repArray.size() == 0) {
|
||
trgField->SetBackgroundColour(red);
|
||
}
|
||
else {
|
||
trgField->SetBackgroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW));
|
||
}
|
||
wxString sepRbegin, sepRend, sepF;
|
||
sepRbegin=beforeRowCB->GetValue();
|
||
sepRend= afterRowCB->GetValue();
|
||
sepF = sepFieldCB->GetValue();
|
||
//sepFend = afterFieldCB->GetValue();
|
||
|
||
// build Rows separator
|
||
std::vector<replace_opt> sepRowEndArray;
|
||
sepRowEndArray = BuildString(sepRend);
|
||
if (sepRowEndArray.size() == 0) {
|
||
afterRowCB->SetBackgroundColour(red);
|
||
}
|
||
else {
|
||
afterRowCB->SetBackgroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW));
|
||
}
|
||
bool isSepRowEndConst = true;
|
||
wxString SepRowEndConst;
|
||
for (auto& j : sepRowEndArray) {
|
||
if (j.isGroup && j.nGroup>=0) {
|
||
isSepRowEndConst = false;
|
||
break;
|
||
}
|
||
else {
|
||
SepRowEndConst.Append(j.text);
|
||
}
|
||
}
|
||
// Matchs regexpp
|
||
wxString sepLine = "";
|
||
int numField = 0;
|
||
int cntMathes = 0;
|
||
int cntLines = 0;
|
||
int tmp_limitChar = limitChar;
|
||
int tmp_limitLine = limitLine;
|
||
while (regfld.Matches(tmp)) {
|
||
size_t start, len;
|
||
int lastBytePosition = srcText->GetLastPosition();
|
||
int lastCharPosition = srcText->GetTextLength();
|
||
regfld.GetMatch(&start, &len, 0);
|
||
if (len == 0) break;
|
||
cntMathes++;
|
||
wxString no_match = tmp.Mid(0, start);
|
||
int maxgroup = regfld.GetMatchCount();
|
||
// build sepLine string dynamic for next line
|
||
sepRend = wxEmptyString;
|
||
if (isSepRowEndConst) {
|
||
sepRend = SepRowEndConst;
|
||
}
|
||
else
|
||
for (auto& j : sepRowEndArray) {
|
||
if (j.isGroup && j.nGroup >= 0) {
|
||
if (j.nGroup >= 0 && j.nGroup < maxgroup) {
|
||
wxString s = regfld.GetMatch(tmp, j.nGroup);
|
||
sepRend.Append(s);
|
||
}
|
||
}
|
||
else {
|
||
sepRend.Append(j.text);
|
||
}
|
||
}
|
||
// end build
|
||
if (no_match.length() > 0) {
|
||
isnewline = RegNewLine.Matches(no_match);
|
||
//srcText->AddText(no_match);
|
||
AppendTextControl(srcText, no_match, isnewline);
|
||
if (isnewline) AppendTextControl(trgText, sepRend + sepLine);
|
||
if (isnewline) cntLines++;
|
||
|
||
}
|
||
wxString fnd = tmp.Mid(start, len);
|
||
if (isnewline) {
|
||
//trgText->AddText(sepRbegin );
|
||
AppendTextControl(trgText, sepRbegin);
|
||
numLine++;
|
||
numField = 0;
|
||
isnewline = false;
|
||
}
|
||
else {
|
||
if (numField > 0) AppendTextControl(trgText, sepF);
|
||
}
|
||
if (numLine == 0 && numField == 0) AppendTextControl(trgText, sepRbegin);
|
||
|
||
//srcText->AddText(fnd);
|
||
|
||
AppendTextControl(srcText, fnd);
|
||
numField++;
|
||
if (maxgroup > 0) {
|
||
// colorer groups
|
||
size_t start1, len1;
|
||
size_t start_frame = start;
|
||
int currentIdx = 0;
|
||
for (int i = 0; i < maxgroup; i++)
|
||
{
|
||
regfld.GetMatch(&start1, &len1, i);
|
||
if (i == 0) m[currentIdx++] = { start1, len1,0 + regstyle };
|
||
if (i == 0 || len1 == 0) continue;
|
||
// group color
|
||
// разделение отрезков
|
||
int maxSizeArray = sizeof(m) / sizeof(m[0]);
|
||
bool isApeendInterval = false;
|
||
int shiftcount = 0;
|
||
for (int idx = 0; idx < currentIdx; idx++) {
|
||
interval ii = m[idx];
|
||
int nextinterval = ii.start + ii.len;
|
||
if (nextinterval < start1 || ii.len == 0) continue; // предудущие интервалы
|
||
//nextinterval < start1 + len1 &&
|
||
if (nextinterval < start1 + len1) {
|
||
if (currentIdx - 1 != idx) continue; // только в конеч добавляем.
|
||
//следующие интеравлы, добавим сюда наш новый интервал
|
||
|
||
shiftcount = 1;
|
||
isApeendInterval = true;
|
||
if (currentIdx + shiftcount >= maxSizeArray) {
|
||
// переполнение массива
|
||
break;
|
||
}
|
||
if (shiftcount > 0) for (int j = currentIdx - 1; j > idx; j--) m[j + shiftcount] = m[j];
|
||
m[idx + 1] = { start1,len1,i + regstyle };
|
||
break;
|
||
}
|
||
// попали в текущий интервал, разделим его
|
||
// сдвинем элементы на два,один или ноль вправо
|
||
shiftcount = 2;
|
||
int oldleftidx = idx;
|
||
int oldrightidx = idx + 2;
|
||
int newcenter = idx + 1;
|
||
if (start1 == ii.start) {
|
||
shiftcount--; oldleftidx = -1; newcenter = idx; oldrightidx--;
|
||
}; // левая часть полностью замещается, стыковака к левой границе
|
||
|
||
if (nextinterval == start1 + len1) {
|
||
oldrightidx = -1; newcenter = idx + 1;
|
||
shiftcount--; // правая часть не нужна стыкова к правой границе
|
||
// сдвиг на shiftcount элементов
|
||
if (shiftcount == 0) newcenter = idx;
|
||
}
|
||
if (currentIdx + shiftcount >= maxSizeArray) {
|
||
// переполнение массива
|
||
isApeendInterval = true;
|
||
break;
|
||
}
|
||
if (shiftcount > 0) for (int j = currentIdx - 1; j > idx; j--) m[j + shiftcount] = m[j];
|
||
currentIdx += shiftcount;
|
||
if (oldleftidx != -1) m[idx].len = start1 - ii.start; // правая часть старого интеравла корректируется по длине
|
||
m[newcenter] = { start1,len1,i + regstyle }; // новый интервал в конец массива
|
||
if (oldrightidx != -1)
|
||
m[oldrightidx] = { start1 + len1,ii.len - (start1 - ii.start) - len1 ,ii.style }; // вторая часть старого интервала в конец массива
|
||
isApeendInterval = true;
|
||
break;
|
||
}
|
||
if (!isApeendInterval) m[currentIdx++] = { start1,len1,i + regstyle };
|
||
}
|
||
// set style for text
|
||
int maxchar = srcText->GetTextLength();
|
||
|
||
for (auto& ii : m) {
|
||
if (--currentIdx < 0) break;
|
||
if (sstart + ii.start + ii.len > maxchar) break;
|
||
int CharPos = srcText->PositionRelative(0, sstart+ii.start);
|
||
if (CharPos == 0 && sstart>1000) {
|
||
//wxTrap();
|
||
continue;
|
||
}
|
||
srcText->StartStyling(CharPos);
|
||
if (ii.style - regstyle > countGroupColor) ii.style = countGroupColor + regstyle - 1;
|
||
int CharPosEnd = srcText->PositionRelative(CharPos, ii.len);
|
||
srcText->SetStyling(CharPosEnd - CharPos, ii.style);
|
||
}
|
||
|
||
// build replace string
|
||
interval m2[100];
|
||
currentIdx = 0;
|
||
start_frame = 0;
|
||
int pos = 0;
|
||
wxString replstr = ReplaceFormatting(tmp, regfld,repArray, pos, m2, 100, currentIdx, start_frame);
|
||
//trgText->AddText(replstr);
|
||
//AppendTextControl(trgText, );
|
||
int start2 = trgText->GetTextLength();
|
||
AppendTextControl(trgText, replstr);
|
||
maxchar = trgText->GetTextLength();
|
||
for (auto& ii : m2) {
|
||
if (--currentIdx < 0) break;
|
||
if (start2 + ii.start + ii.len > maxchar) break;
|
||
int CharPos = trgText->PositionRelative(start2, ii.start);
|
||
if (CharPos < start2 ) {
|
||
//wxTrap();
|
||
continue;
|
||
}
|
||
trgText->StartStyling(CharPos);
|
||
if (ii.style >= countGroupColor) ii.style = countGroupColor - 1;
|
||
int CharPosEnd = trgText->PositionRelative(CharPos, ii.len);
|
||
trgText->SetStyling(CharPosEnd - CharPos, ii.style + regstyle);
|
||
// colorize wxString trgFieldReg = trgField->GetText();
|
||
if (ii.style < colorizetrgField.size() && colorizetrgField[ii.style]==-1) {
|
||
colorizetrgField[ii.style] = ii.style;
|
||
}
|
||
}
|
||
|
||
|
||
}
|
||
else {
|
||
AppendTextControl(trgText, fnd);
|
||
}
|
||
|
||
//if (sstart == -1) sstart = 0;
|
||
|
||
sstart += start + len;
|
||
tmp = tmp.Mid(start + len);
|
||
}
|
||
if (numField > 0) AppendTextControl(trgText, sepRend);
|
||
|
||
if (sstart == 0) {
|
||
srcText->SetText(src.Mid(0, limitChar));
|
||
}
|
||
else if (tmp.length() > 0 && limitChar>0 ) AppendTextControl(srcText, tmp.Mid(0, limitChar)); // no_match
|
||
limitChar = tmp_limitChar;
|
||
limitLine = tmp_limitLine;
|
||
int srcl = src.length();
|
||
m_msg->SetLabelText(wxString::Format("Lines %d Char %d Matches %d", cntLines, srcl, cntMathes));
|
||
// colorize wxString trgFieldReg = trgField->GetText();
|
||
int pp = -1;
|
||
for (auto &stl: colorizetrgField) {
|
||
if (stl == -1) continue;
|
||
for (auto& j : repArray) {
|
||
|
||
if (j.isGroup && j.nGroup >= 0 && stl== j.nGroup) {
|
||
int CharPos = trgField->PositionRelative(0, j.start);
|
||
trgField->StartStyling(CharPos);
|
||
|
||
int CharPosEnd = trgField->PositionRelative(CharPos, j.len);
|
||
trgField->SetStyling(CharPosEnd - CharPos, stl + regstyle);
|
||
|
||
}
|
||
}
|
||
}
|
||
}
|
||
else
|
||
{
|
||
//txtField->SetBackgroundColour(red);
|
||
srcText->SetText(src.Mid(0, limitChar));
|
||
}
|
||
if (srcText->GetTextLength()>= limitChar) srcText->AppendText("\n...");
|
||
if (srcText->GetTextLength() > 0) srcText->SetFirstVisibleLine(toplineSrc);
|
||
if (trgText->GetTextLength() > 0) trgText->SetFirstVisibleLine(toplineTrg);
|
||
|
||
srcText->Update();
|
||
txtField->Refresh();
|
||
trgField->Update();
|
||
} |