mirror of
https://github.com/levinsv/pgadmin3.git
synced 2026-06-30 06:12:11 -06:00
Improved the dialog for comparing two cells.
1. Устранена проблема с отображением номеров строк. 2. Добавлена опция "Cleanup semantic" для более красивого отображения различий. 3. Добавлена кнопка "Copy diff to HTML" копирования правого окна с объединением различий левого. Жёлтым фоном выделяются добавления и изменения, красным удаленные элементы левого. Могут быть артефакты и искажения в каких то экзотических случаях. 4. Добавлена кнопка "Copy Left/Right to HTML" в зависимости от фокуса копируется левая или правая часть.
This commit is contained in:
parent
2bcd61f10c
commit
814731a6df
4 changed files with 162 additions and 31 deletions
|
|
@ -95,6 +95,7 @@ ctlSQLBox::ctlSQLBox(wxWindow *parent, wxWindowID id, const wxPoint &pos, const
|
|||
process = 0;
|
||||
processID = 0;
|
||||
m_hint_mode = false;
|
||||
issimple=false;
|
||||
Create(parent, id, pos, size, style);
|
||||
}
|
||||
//void ctlSQLBox::OnBackGround(wxEraseEvent &event) {
|
||||
|
|
@ -317,7 +318,9 @@ wxString ctlSQLBox::GetFilename()
|
|||
{
|
||||
return m_filename;
|
||||
}
|
||||
|
||||
void ctlSQLBox::SetSimpleMode(bool issimplemode) {
|
||||
issimple=issimplemode;
|
||||
}
|
||||
void ctlSQLBox::SetTitle(wxString &title)
|
||||
{
|
||||
m_title = title;
|
||||
|
|
@ -1281,7 +1284,7 @@ void ctlSQLBox::OnKillFocus(wxFocusEvent &event)
|
|||
void ctlSQLBox::UpdateLineNumber()
|
||||
{
|
||||
bool showlinenumber;
|
||||
|
||||
if (GetSimpleMode()) return;
|
||||
settings->Read(wxT("frmQuery/ShowLineNumber"), &showlinenumber, false);
|
||||
if (showlinenumber)
|
||||
{
|
||||
|
|
@ -1825,6 +1828,7 @@ wxString ctlSQLBox::TextToHtml(int start, int end,bool isAddNewLine, const std::
|
|||
str = wxString::Format("<div style=\"font-family: %s; font-size: %spx\"><span>", fontName, sz);
|
||||
int k = 0;
|
||||
int l = 1;
|
||||
int indic=9;
|
||||
wxString newline = "<br>";
|
||||
if (isAddNewLine) newline = L"\u2936<br>";
|
||||
//if (isAddNewLine) newline = L"⤶<br>";
|
||||
|
|
@ -1834,7 +1838,10 @@ wxString ctlSQLBox::TextToHtml(int start, int end,bool isAddNewLine, const std::
|
|||
int pos=999999999;
|
||||
wxString obj;
|
||||
int lenobj;
|
||||
if (listobj.size()>0) {pos=listobj[IndexObj].startIndex; obj=listobj[IndexObj].table;lenobj=obj.Len();}
|
||||
if (listobj.size()>0) {
|
||||
pos=listobj[IndexObj].startIndex; obj=listobj[IndexObj].table;lenobj=obj.Len();
|
||||
if (GetSimpleMode()) indic=listobj[IndexObj].level;
|
||||
}
|
||||
wxString lstr;
|
||||
wxString bgclr="";
|
||||
// find Indicator bookmark
|
||||
|
|
@ -1843,30 +1850,31 @@ wxString ctlSQLBox::TextToHtml(int start, int end,bool isAddNewLine, const std::
|
|||
int tmppos=0;
|
||||
int textlen=GetTextLength();
|
||||
while (tmppos<textlen) {
|
||||
tmppos=IndicatorEnd(9,tmppos);
|
||||
tmppos=IndicatorEnd(indic,tmppos);
|
||||
if (tmppos==0 || tmppos==textlen) break;
|
||||
if (tmppos>0 && tmppos!=textlen) {
|
||||
spos=tmppos;
|
||||
epos=IndicatorEnd(9,tmppos);
|
||||
epos=IndicatorEnd(indic,tmppos);
|
||||
if (epos>=start) break;
|
||||
tmppos=epos;
|
||||
spos=epos=-1;
|
||||
} else break;
|
||||
}
|
||||
bool refreshgbcolor=false;
|
||||
bool newlineadd=false;
|
||||
while (k<lenstr) {
|
||||
int st = GetStyleAt(startp);
|
||||
if (st < 34) tColor = frColor[st].GetAsString(wxC2S_HTML_SYNTAX);
|
||||
if (startp>=spos && spos!=-1) {
|
||||
refreshgbcolor=true;
|
||||
bgclr="#ffff00";
|
||||
tmppos=IndicatorEnd(9,epos);
|
||||
tmppos=IndicatorEnd(indic,epos);
|
||||
if (tmppos==textlen) spos=-1;
|
||||
else spos=tmppos;
|
||||
} else if (startp>=epos && epos!=-1) {
|
||||
bgclr="";
|
||||
refreshgbcolor=true;
|
||||
tmppos=IndicatorEnd(9,spos);
|
||||
tmppos=IndicatorEnd(indic,spos);
|
||||
if (tmppos==textlen) epos=-1;
|
||||
else epos=tmppos;
|
||||
}
|
||||
|
|
@ -1886,28 +1894,55 @@ wxString ctlSQLBox::TextToHtml(int start, int end,bool isAddNewLine, const std::
|
|||
//wxUniChar c = selText[k].GetValue();
|
||||
if (c == '\r') { k++; continue; };
|
||||
|
||||
if (c == '\n') { lstr += newline; k++; continue; };
|
||||
if (c == '\n') {
|
||||
lstr += newline; newlineadd=true; k++;
|
||||
continue;
|
||||
};
|
||||
if (c == 9) s = 5;
|
||||
if (c == 32) s = 1;
|
||||
if (c == '<') { lstr+="<"; k++; continue; };
|
||||
if (c == '>') { lstr+=">"; k++; continue; };
|
||||
if (c == '&') { lstr+="&"; k++; continue; };
|
||||
if (s > 0) for (int tt = 0; tt < s; tt++) lstr += " ";
|
||||
if (s > 0)
|
||||
for (int tt = 0; tt < s; tt++) lstr += " ";
|
||||
else lstr += c;
|
||||
k++;
|
||||
if ((k-1)>=pos) {
|
||||
lenobj--;
|
||||
if (lenobj==0) {
|
||||
wxString s,n;
|
||||
make_identifier(obj,s,n,true);
|
||||
if (!s.IsEmpty()) obj=s+'.'+n; else obj=n;
|
||||
lstr=wxString::Format("<a href=\"%s\">%s</a>", obj, lstr);
|
||||
IndexObj++;
|
||||
if (listobj.size()>IndexObj) { pos=listobj[IndexObj].startIndex; obj=listobj[IndexObj].table; lenobj=obj.Len();}
|
||||
else pos=999999999;
|
||||
} else
|
||||
continue; // link not ready
|
||||
if (GetSimpleMode()) {
|
||||
// this compare dialog Append Delete text
|
||||
wxString bgclrDel="#ebb1c4";
|
||||
if (newlineadd) {
|
||||
size_t p44=0,p45=0;
|
||||
wxString searchStr = "<br>";
|
||||
p44=lstr.Find('<',true);
|
||||
if (p44!=-1) {
|
||||
p45=p44;
|
||||
p44++;
|
||||
}
|
||||
wxString lleft=lstr.Left(p45+4);
|
||||
wxString rright=lstr.Mid(p45+4);
|
||||
lstr=wxString::Format("%s<span style=\"background-color: %s\">%s</span>%s",lleft,bgclrDel, obj,rright);
|
||||
}
|
||||
else
|
||||
//lstr=wxString::Format("%s<span style=\"background-color: %s\">%s</span>",lstr,bgclrDel, obj);
|
||||
lstr=wxString::Format("<span style=\"background-color: %s\">%s</span>%s",bgclrDel, obj,lstr);
|
||||
} else {
|
||||
// links
|
||||
lenobj--;
|
||||
if (lenobj==0) {
|
||||
wxString s,n;
|
||||
make_identifier(obj,s,n,true);
|
||||
if (!s.IsEmpty()) obj=s+'.'+n; else obj=n;
|
||||
lstr=wxString::Format("<a href=\"%s\">%s</a>", obj, lstr);
|
||||
} else
|
||||
continue; // link not ready
|
||||
}
|
||||
IndexObj++;
|
||||
if (listobj.size()>IndexObj) { pos=listobj[IndexObj].startIndex; obj=listobj[IndexObj].table; lenobj=obj.Len();}
|
||||
else pos=999999999;
|
||||
|
||||
}
|
||||
newlineadd=false;
|
||||
str += lstr;
|
||||
lstr="";
|
||||
}
|
||||
|
|
|
|||
|
|
@ -10,11 +10,18 @@ class SourceViewDialog : public wxFrame
|
|||
wxCheckBox* m_visibleSpace;
|
||||
wxCheckBox* m_showNumber;
|
||||
wxCheckBox* m_linescompare;
|
||||
wxCheckBox* m_symantecclean;
|
||||
wxButton* m_btn_next;
|
||||
wxButton* m_btn_html;
|
||||
wxButton* m_btn_htmlcopy;
|
||||
wxWindow* lastfocus=NULL;
|
||||
int s_indicHighlight;
|
||||
bool isdiff=false;
|
||||
int pos = 0;
|
||||
int prev_line = -1;
|
||||
wxString sqlr;
|
||||
wxString sqll;
|
||||
std::vector<FSQL::complite_element> listdelete;
|
||||
public:
|
||||
~SourceViewDialog() {
|
||||
//delete m_text1;
|
||||
|
|
@ -36,6 +43,7 @@ public:
|
|||
text->SetMarginWidth(0, width);
|
||||
text->Update();
|
||||
}
|
||||
|
||||
}
|
||||
else {
|
||||
text->SetMarginWidth(0, 0);
|
||||
|
|
@ -50,10 +58,8 @@ public:
|
|||
// text->StyleSetForeground(wxSTC_STYLE_LINENUMBER, wxColour(75, 75, 75));
|
||||
// text->StyleSetBackground(wxSTC_STYLE_LINENUMBER, wxColour(220, 220, 220));
|
||||
// text->SetMarginType(MARGIN_LINE_NUMBERS, wxSTC_MARGIN_NUMBER);
|
||||
text->SetSimpleMode(true);
|
||||
text->SetEOLMode(2);
|
||||
|
||||
showNumber(text, true);
|
||||
|
||||
//text->StyleSetForeground(wxSTC_H_DOUBLESTRING, wxColour(255, 0, 0));
|
||||
//text->StyleSetForeground(wxSTC_H_SINGLESTRING, wxColour(255, 0, 0));
|
||||
//text->StyleSetForeground(wxSTC_H_ENTITY, wxColour(255, 0, 0));
|
||||
|
|
@ -70,7 +76,7 @@ public:
|
|||
int start=ctl->GetLength();
|
||||
ctl->AddText(t);
|
||||
if (indic > 0) {
|
||||
|
||||
isdiff=true;
|
||||
ctl->IndicatorFillRange(start, ctl->GetLength()-start);
|
||||
}
|
||||
};
|
||||
|
|
@ -79,6 +85,13 @@ public:
|
|||
//Match_Threshold = 0.5;
|
||||
//Match_Distance = 1000;
|
||||
diff_match_patch dmp(4, 0.5, 1000);
|
||||
listdelete.clear();
|
||||
ctlL->ClearAll();
|
||||
ctlR->ClearAll();
|
||||
isdiff=false;
|
||||
m_btn_next->Disable();
|
||||
m_btn_html->Disable();
|
||||
m_btn_htmlcopy->Disable();
|
||||
std::list<Diff> diffs;
|
||||
if (sL == sR) {
|
||||
return;
|
||||
|
|
@ -93,6 +106,7 @@ public:
|
|||
dmp.diff_charsToLines(diffs, lineArray);
|
||||
} else
|
||||
diffs = dmp.diff_main(sL.wc_str(), sR.wc_str(), true);
|
||||
if (m_symantecclean && m_symantecclean->IsChecked()) dmp.diff_cleanupSemantic(diffs);
|
||||
int nstart = 0;
|
||||
int pos = 0;
|
||||
std::wstring cur_l;
|
||||
|
|
@ -136,6 +150,21 @@ public:
|
|||
cur_r += L"<span class=\"differencei\">" + t + L"</span>"; addIndicText(ctlR, t, s_indicHighlight);
|
||||
}
|
||||
if (aDiff.operation == 0) {
|
||||
FSQL::complite_element cl={};
|
||||
cl.table=escapeHtml(t,false);
|
||||
cl.table.Replace("\t"," ");
|
||||
cl.level=s_indicHighlight;
|
||||
cl.startIndex=ctlR->GetTextLength();
|
||||
FSQL::complite_element prev;
|
||||
if (listdelete.size()>0) {
|
||||
prev=listdelete[listdelete.size()-1];
|
||||
if (prev.startIndex==cl.startIndex) {
|
||||
prev.table+=cl.table;
|
||||
listdelete[listdelete.size()-1]=prev;
|
||||
} else
|
||||
listdelete.push_back(cl);
|
||||
} else
|
||||
listdelete.push_back(cl);
|
||||
cur_l += L"<span class=\"differenced\">" + t + L"</span>"; addIndicText(ctlL, t, s_indicHighlight);
|
||||
}
|
||||
if (aDiff.operation == Operation::EQUAL) {
|
||||
|
|
@ -160,6 +189,20 @@ public:
|
|||
std::wstring t_cur_r = cur_r;
|
||||
if (aDiff.operation == 0) {
|
||||
t_cur_r = L"";
|
||||
FSQL::complite_element cl={};
|
||||
cl.table=escapeHtml("\n",false);
|
||||
cl.level=s_indicHighlight;
|
||||
cl.startIndex=ctlR->GetTextLength();
|
||||
FSQL::complite_element prev;
|
||||
if (listdelete.size()>0) {
|
||||
prev=listdelete[listdelete.size()-1];
|
||||
if (prev.startIndex==cl.startIndex) {
|
||||
prev.table+=cl.table;
|
||||
listdelete[listdelete.size()-1]=prev;
|
||||
} else
|
||||
listdelete.push_back(cl);
|
||||
} else
|
||||
listdelete.push_back(cl);
|
||||
addIndicText(ctlL, L"\n", s_indicHighlight);
|
||||
ncur_l = std::to_wstring(lline);
|
||||
modify = true;
|
||||
|
|
@ -210,6 +253,9 @@ public:
|
|||
} // <20><><EFBFBD><EFBFBD> <20><> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> Diff
|
||||
++it;
|
||||
}
|
||||
m_btn_next->Enable(isdiff);
|
||||
m_btn_html->Enable(isdiff);
|
||||
m_btn_htmlcopy->Enable(isdiff);
|
||||
|
||||
}
|
||||
SourceViewDialog(wxWindow* parent, wxString sqlL, wxString sqlR, wxString title) :
|
||||
|
|
@ -229,11 +275,14 @@ public:
|
|||
//m_text1->SetText(sqlL);
|
||||
|
||||
m_text2 = createSTC(m_panelSql);
|
||||
//m_text2->Bind(wxID_ANY, wxEVT_SET_FOCUS, wxFocusEventHandler(OnFocus));
|
||||
m_text2->Bind(wxEVT_SET_FOCUS, &SourceViewDialog::OnFocus, this);
|
||||
m_text1->Bind(wxEVT_SET_FOCUS, &SourceViewDialog::OnFocus, this);
|
||||
//m_text2->SetText(sqlR);
|
||||
sqll=sqlL;
|
||||
sqlr=sqlR;
|
||||
m_linescompare=NULL;
|
||||
difftext(m_text1, m_text2, sqll, sqlr);
|
||||
m_symantecclean=NULL;
|
||||
|
||||
bSizer2->Add(m_text1, 1, wxEXPAND, 5);
|
||||
|
||||
|
|
@ -255,10 +304,17 @@ public:
|
|||
m_showNumber = new wxCheckBox(m_panelOpt, wxID_ANY, wxT("Show number line"), wxDefaultPosition, wxDefaultSize, 0);
|
||||
bSizer4->Add(m_showNumber, 0, wxALL, 5);
|
||||
m_linescompare = new wxCheckBox(m_panelOpt, wxID_ANY, wxT("Words compare"), wxDefaultPosition, wxDefaultSize, 0);
|
||||
|
||||
m_symantecclean= new wxCheckBox(m_panelOpt, wxID_ANY, wxT("Cleanup semantic"), wxDefaultPosition, wxDefaultSize, 0);
|
||||
bSizer4->Add(m_linescompare, 0, wxALL, 5);
|
||||
wxButton* m_btn_next = new wxButton(m_panelOpt, wxID_ANY, wxT("Next"), wxDefaultPosition, wxDefaultSize, 0);
|
||||
bSizer4->Add(m_symantecclean, 0, wxALL, 5);
|
||||
m_btn_next = new wxButton(m_panelOpt, wxID_ANY, wxT("Next"), wxDefaultPosition, wxDefaultSize, 0);
|
||||
m_btn_html = new wxButton(m_panelOpt, wxID_ANY, wxT("Copy diff to HTML"), wxDefaultPosition, wxDefaultSize, 0);
|
||||
m_btn_htmlcopy = new wxButton(m_panelOpt, wxID_ANY, wxT("Copy to HTML"), wxDefaultPosition, wxDefaultSize, 0);
|
||||
|
||||
bSizer4->Add(m_btn_next, 0, wxALL, 5);
|
||||
bSizer4->Add(m_btn_html, 0, wxALL, 5);
|
||||
bSizer4->Add(m_btn_htmlcopy, 0, wxALL, 5);
|
||||
|
||||
bSizer4->Add(0, 0, 1, wxEXPAND, 5);
|
||||
|
||||
|
|
@ -268,7 +324,7 @@ public:
|
|||
// wxButton *m_btn_cancel = new wxButton(m_panelOpt, wxID_ANY, wxT("Cancel"), wxDefaultPosition, wxDefaultSize, 0);
|
||||
// bSizer4->Add(m_btn_cancel, 0, wxALL, 5);
|
||||
|
||||
|
||||
difftext(m_text1, m_text2, sqll, sqlr);
|
||||
m_panelOpt->SetSizer(bSizer4);
|
||||
m_panelOpt->Layout();
|
||||
bSizer4->Fit(m_panelOpt);
|
||||
|
|
@ -282,10 +338,13 @@ public:
|
|||
|
||||
m_visibleSpace->Bind(wxEVT_CHECKBOX, &SourceViewDialog::OnShowCheckBoxSpace, this);
|
||||
m_linescompare->Bind(wxEVT_CHECKBOX, &SourceViewDialog::OnLinesCompare, this);
|
||||
m_symantecclean->Bind(wxEVT_CHECKBOX, &SourceViewDialog::OnLinesCompare, this);
|
||||
|
||||
m_showNumber->Bind(wxEVT_CHECKBOX, &SourceViewDialog::OnShowCheckShowNumber, this);
|
||||
m_btn_close->Bind(wxEVT_BUTTON, &SourceViewDialog::onClose2, this);
|
||||
m_btn_next->Bind(wxEVT_BUTTON, &SourceViewDialog::onNext, this);
|
||||
m_btn_html->Bind(wxEVT_BUTTON, &SourceViewDialog::onHtmlDiff, this);
|
||||
m_btn_htmlcopy->Bind(wxEVT_BUTTON, &SourceViewDialog::onHtmlCopy, this);
|
||||
//Connect(wxEVT_CLOSE_WINDOW, wxCloseEventHandler(SourceViewDialog::onClose), NULL, this);
|
||||
//m_text1->Connect(wxEVT_STC_PAINTED, wxStyledTextEventHandler(SourceViewDialog::onScrollLeft), NULL, this);
|
||||
//m_text2->Connect(wxEVT_STC_PAINTED, wxStyledTextEventHandler(SourceViewDialog::onScrollRight), NULL, this);
|
||||
|
|
@ -355,12 +414,16 @@ public:
|
|||
prev_line = -1;
|
||||
}
|
||||
}
|
||||
void OnLinesCompare(wxCommandEvent& evt) {
|
||||
bool bVal = m_linescompare->IsChecked();
|
||||
void Recompare()
|
||||
{
|
||||
m_text1->ClearAll();
|
||||
m_text2->ClearAll();
|
||||
difftext(m_text1, m_text2, sqll, sqlr);
|
||||
}
|
||||
void OnLinesCompare(wxCommandEvent& evt) {
|
||||
Recompare();
|
||||
OnShowCheckShowNumber(evt);
|
||||
}
|
||||
|
||||
void OnShowCheckBoxSpace(wxCommandEvent& evt) {
|
||||
bool bVal = m_visibleSpace->IsChecked();
|
||||
|
|
@ -405,4 +468,35 @@ public:
|
|||
|
||||
m_changing_values = false;
|
||||
}
|
||||
void onHtmlDiff(wxCommandEvent& evt) {
|
||||
if (m_text2->GetLength()>0) {
|
||||
wxString html=m_text2->TextToHtml(0,m_text2->GetLength(),false,listdelete);
|
||||
if (wxTheClipboard->Open())
|
||||
{
|
||||
wxTheClipboard->SetData(new wxHTMLDataObject(html));
|
||||
wxTheClipboard->Close();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
void onHtmlCopy(wxCommandEvent& evt) {
|
||||
wxWindow *wnd = lastfocus;
|
||||
wxString html;
|
||||
if (wnd) {
|
||||
if (m_text2==wnd) html=m_text2->TextToHtml(0,m_text2->GetLength(),false);
|
||||
if (m_text1==wnd) html=m_text1->TextToHtml(0,m_text1->GetLength(),false);
|
||||
if (html.Length()>0 && wxTheClipboard->Open())
|
||||
{
|
||||
wxTheClipboard->SetData(new wxHTMLDataObject(html));
|
||||
wxTheClipboard->Close();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
void OnFocus(wxFocusEvent &ev) {
|
||||
lastfocus = FindFocus();
|
||||
if (m_text2==lastfocus) m_btn_htmlcopy->SetLabelText("Copy Right to HTML");
|
||||
if (m_text1==lastfocus) m_btn_htmlcopy->SetLabelText("Copy Left to HTML");
|
||||
}
|
||||
};
|
||||
|
|
|
|||
|
|
@ -100,6 +100,8 @@ public:
|
|||
int GetOrigin();
|
||||
void SetFilename(wxString &filename);
|
||||
bool IsFileModification();
|
||||
void SetSimpleMode(bool issimplemode);
|
||||
bool GetSimpleMode() {return issimple;};
|
||||
wxString GetFilename();
|
||||
void SetTitle(wxString &title);
|
||||
wxString GetTitle(bool withChangeInd = true);
|
||||
|
|
@ -152,7 +154,7 @@ private:
|
|||
bool m_changed;
|
||||
int m_origin;
|
||||
int fix_pos;
|
||||
|
||||
bool issimple=false;
|
||||
friend class QueryPrintout;
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -89,7 +89,7 @@ wxString escapeHtml(wxString text, bool pre) {
|
|||
text.Replace("&", "&");
|
||||
text.Replace("<", "<");
|
||||
text.Replace(">", ">");
|
||||
if (!pre) text.Replace("\n", "¶<br>");
|
||||
if (!pre) text.Replace("\n", "<br>");
|
||||
return text;
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue