diff --git a/CMakeLists.txt b/CMakeLists.txt index 8eceb87..841ea23 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -79,6 +79,15 @@ file(GLOB_RECURSE SOURCES ########################################################## add_executable(${PROJECT_NAME} ) +# После сборки — разделить символы и приложение +add_custom_command(TARGET ${PROJECT_NAME} POST_BUILD + COMMAND ${CMAKE_COMMAND} -E echo "Extracting debug symbols..." + COMMAND objcopy --only-keep-debug ${PROJECT_NAME} ${PROJECT_NAME}.debug + COMMAND objcopy --strip-debug ${PROJECT_NAME} + COMMAND objcopy --add-gnu-debuglink=${PROJECT_NAME}.debug ${PROJECT_NAME} + COMMENT "Split debug symbols into separate .debug file" + VERBATIM +) target_compile_definitions(${PROJECT_NAME} PRIVATE $<$:_DEBUG>) target_sources(${PROJECT_NAME} PUBLIC pgAdmin3.cpp ${SOURCES}) if(CROSS_COMPILE STREQUAL "Windows") diff --git a/ctl/ctlSQLBox.cpp b/ctl/ctlSQLBox.cpp index 15b3b2b..deb38ed 100644 --- a/ctl/ctlSQLBox.cpp +++ b/ctl/ctlSQLBox.cpp @@ -1498,7 +1498,7 @@ std::pair ctlSQLBox::SelectQuery(int startposition) int st = GetStyleAt(pos - 1); int endPos = GetLength(); int pend=endPos; - int pstart=0; + int pstart=pos; if (ch == ';') { pend=pos; @@ -1521,7 +1521,9 @@ std::pair ctlSQLBox::SelectQuery(int startposition) int i=IsDBCSLeadByte(ch)? 2 : 1; #else int i=1; - if (ch>255) i=2; + if (ch>255*255) i=3; + else if (ch>255) i=2; + #endif pos=pos+i; } @@ -1547,7 +1549,8 @@ std::pair ctlSQLBox::SelectQuery(int startposition) int i=IsDBCSLeadByte(ch)? 2 : 1; #else int i=1; - if (ch>255) i=2; + if (ch>255*255) i=3; + else if (ch>255) i=2; #endif pos=pos-i; diff --git a/ctl/ctlSQLGrid.cpp b/ctl/ctlSQLGrid.cpp index 88acb20..c83856a 100644 --- a/ctl/ctlSQLGrid.cpp +++ b/ctl/ctlSQLGrid.cpp @@ -522,7 +522,7 @@ int ctlSQLGrid::CopyTableToHtml(wxString htmlquery) { if (isRowsArray) rowPos = rows.Item(i); if (GetRowSize(rowPos) == 0) continue; htm += "\n"; - htm += wxString::Format("
%d
", rowPos + 1); + htm += wxString::Format("
%ld
", rowPos + 1); for (int c = 0; c < cols.Count(); c++) { wxString text = GetCellValue(rowPos, cols[c]); htm += wxString::Format("
%s
", c, escapeHtml(text, true)); @@ -1452,7 +1452,7 @@ retry: if (pos == wxString::npos) pos = len; int x=rect.GetRight()-1; - int yb=rect.GetTop(); + int yb=rect.GetTop()+1; //GRID_TEXT_MARGIN int c=0; while (pos > 0) { diff --git a/ctl/ctlTreeJSON.cpp b/ctl/ctlTreeJSON.cpp index 9f16051..7dfb264 100644 --- a/ctl/ctlTreeJSON.cpp +++ b/ctl/ctlTreeJSON.cpp @@ -53,11 +53,32 @@ void ctlTreeJSON::OnChar(wxKeyEvent& event) { } } + if (event.GetKeyCode() == WXK_F1) { + int x=50; + int y=50; + this->ClientToScreen(&x,&y); + wxPoint screenPos(x,y); + wxString helpstr=R"( + + + + +

Ctrl-F - find and colorize nodes

+

F3 - next find node

+

Shift-F3 - previos find node

+

Insert - copy select node

+

Delete - delete select node

+

Ctrl-Z - Return source context node.

+ +)"; + showHelpHtml((wxWindow *)winMain,helpstr,screenPos, wxSize(450,300)); + return; + } if (event.GetKeyCode() == WXK_CONTROL_F) { wxTextEntryDialog dialog(this, - wxT("Please enter find string\n") + _("Please enter find string\n") , - wxT("Find"), + _("Find"), m_FindString, wxOK | wxCANCEL); //setName( dlg.GetValue().wc_str() ); if (dialog.ShowModal() == wxID_OK) { diff --git a/frm/frmLog.cpp b/frm/frmLog.cpp index ccddaf4..c6a532d 100644 --- a/frm/frmLog.cpp +++ b/frm/frmLog.cpp @@ -393,7 +393,7 @@ void MyThread::getFilename() { wxString sql = wxString::Format( "select * from ( \ select current_setting('log_directory') || '/' || name filename, modification filetime, size len \ - FROM pg_ls_logdir() where name ~ %s ORDER BY modification DESC limit %d) l order by filetime ASC", po->conn->qtDbString(mask), limitfiles + FROM pg_ls_logdir() where name ~ %s and name !~'db.csv$' ORDER BY modification DESC limit %d) l order by filetime ASC", po->conn->qtDbString(mask), limitfiles ); diff --git a/include/utils/PreviewHtml.h b/include/utils/PreviewHtml.h index fa14a7d..f95a682 100644 --- a/include/utils/PreviewHtml.h +++ b/include/utils/PreviewHtml.h @@ -10,6 +10,8 @@ #define PREVIEW_ENDFIELD 16 #define PREVIEW_ENDROW 32 #define PREVIEW_QUOTE 64 +#define PREVIEW_RAWHTML 128 + #define CHKFLAG2(val,par) ((val & par)>0) enum class fmtpreview { AUTO, AUTOVACCUM,CSV,SIMPLE_TEXT @@ -61,8 +63,12 @@ private: bool saveTokenIfNotEmpty(wxString& savestr, int flag) { if (savestr.Length() > 0) { wxString tmp = savestr; - tmp=escapeHtml(tmp,true); - tmp.Replace(" ", " "); + if (CHKFLAG2(flag, PREVIEW_RAWHTML)) { + // nothing + } else { + tmp=escapeHtml(tmp,true); + tmp.Replace(" ", " "); + } if (CHKFLAG2(flag, PREVIEW_ENDROW)) tmp = "
"; if (CHKFLAG2(flag, PREVIEW_DIGITS)) { int l = savestr.Length(); diff --git a/include/utils/misc.h b/include/utils/misc.h index 06f379d..7b93cac 100644 --- a/include/utils/misc.h +++ b/include/utils/misc.h @@ -280,6 +280,8 @@ wxString qtIdent(const wxString &value); // add " if necessary wxString qtTypeIdent(const wxString &value); // add " if necessary bool make_identifier(const wxString &strname, wxString &s, wxString &n, bool islower); +wxSize getScreenSizeForPoint(const wxPoint screenPos); +void showHelpHtml(wxWindow *parent, const wxString &htmlHelp,wxPoint screenPos, wxSize size); #endif diff --git a/include/utils/popuphelp.h b/include/utils/popuphelp.h index 03bc928..0a7517b 100644 --- a/include/utils/popuphelp.h +++ b/include/utils/popuphelp.h @@ -27,6 +27,10 @@ public: return isvalid; } void SetSizePopup(const wxSize& sz) { + //wxPoint p=this->GetScreenPosition(); + //p.x=p.x-50; + //p.y=p.y-50; + //SetSize(p.x,p.y, sz.x,sz.y,wxSIZE_FORCE); SetSize(sz); Layout(); Fit(); @@ -84,7 +88,7 @@ public: //htmlWindow->SetInitialSize(wxSize(htmlWindow->GetInternalRepresentation()->GetWidth(), htmlWindow->GetInternalRepresentation()->GetHeight())); //SetSize(wxSize(300,150)); - topsizer->Add(htmlWindow, 1, wxALL, 1); + topsizer->Add(htmlWindow, 1, wxEXPAND|wxALL, 1); //wxButton* bu1 = new wxButton(this, wxID_OK, _("OK")); //bu1->SetDefault(); @@ -157,21 +161,30 @@ public: htmlWindow->Bind(wxEVT_KEY_DOWN, [&](wxKeyEvent& event) { if (event.GetKeyCode() == WXK_ESCAPE) { Hide(); + event.Skip(); return; } if (event.GetKeyCode() == WXK_NUMPAD_ADD) { wxSize sz=this->GetSize(); wxSize szh=htmlWindow->GetSize(); - szh.IncBy(50,50); - htmlWindow->SetSize(szh); - std::cout << sz.GetWidth() << "," << sz.GetHeight() << std::endl; - sz.IncBy(50,50); - this->SetSizePopup(sz); - wxPoint p; - p=this->GetScreenPosition(); - p.x=p.x-50; - p.y=p.y-50; - //this->Move(p); + int xx, yy; + htmlWindow->GetVirtualSize(&xx, &yy); + wxPoint p=GetScreenPosition(); + wxSize sizeScreen=getScreenSizeForPoint(p); + if (yy>szh.y) { + if (p.y+sz.y +50 50) {p.y=p.y-50; sz.y+=50;} + } + if (p.x+sz.x +50 50) {p.x=p.x-50; sz.x+=50;} + SetSize(p.x,p.y,sz.x,sz.y,wxSIZE_USE_EXISTING); + Layout(); + wxSize newsz=GetSize(); + //std::cout << sz.GetWidth() << "," << sz.GetHeight() << " new: " << newsz.GetWidth() << "," << newsz.GetHeight() << std::endl; } if (event.GetKeyCode() == WXK_PAGEDOWN) htmlWindow->ScrollPages(1); if (event.GetKeyCode() == WXK_PAGEUP) htmlWindow->ScrollPages(-1); @@ -179,6 +192,59 @@ public: if (event.GetKeyCode() == WXK_UP) htmlWindow->ScrollLines(-1); if (event.GetKeyCode() == WXK_HOME) htmlWindow->ScrollPages(-1000); if (event.GetKeyCode() == WXK_END) htmlWindow->ScrollPages(1000); + //std::cout << "key code " << event.GetKeyCode() << " " << std::endl; + if (event.GetKeyCode() == 'C' && hist.size()>0) { + + if (wxTheClipboard->Open()) + { + wxString h=hist[hist.size()-1]; + // Добавляем данные (можно добавить несколько форматов, если нужно) + wxDataObjectComposite* dataobj = new wxDataObjectComposite(); + dataobj->Add(new wxHTMLDataObject(h)); + wxTheClipboard->SetData(dataobj); + wxTheClipboard->Close(); + } + else + { + wxLogError("No open clipboard."); + } + + } + if (event.GetKeyCode() == 'S') { + wxSize clientSize = this->GetClientSize(); + // Создаём битмап того же размера + wxBitmap bitmap(clientSize.x, clientSize.y, -1); // -1 — лучший формат для экрана + + // Создаём DC для рисования в битмап + wxMemoryDC memDC; + memDC.SelectObject(bitmap); + + // Очищаем фон (опционально, если окно не полностью перерисовано) + memDC.SetBackground(*wxWHITE_BRUSH); + memDC.Clear(); + + // Используем wxClientDC для чтения содержимого окна + wxClientDC clientDC(this); + // Переносим данные с clientDC в memDC (копируем прямоугольник) + // Важно: координаты — относительно окна! + memDC.Blit(0, 0, clientSize.x, clientSize.y, &clientDC, 0, 0); + + // Освобождаем DC + memDC.SelectObject(wxNullBitmap); + // Открываем буфер обмена + if (wxTheClipboard->Open()) + { + // Добавляем данные (можно добавить несколько форматов, если нужно) + wxDataObjectComposite* dataobj = new wxDataObjectComposite(); + dataobj->Add(new wxBitmapDataObject(bitmap)); + wxTheClipboard->SetData(dataobj); + wxTheClipboard->Close(); + } + else + { + wxLogError("No open clipboard."); + } + } }); diff --git a/pgAdmin3.cpp b/pgAdmin3.cpp index 5d98b2e..711d391 100644 --- a/pgAdmin3.cpp +++ b/pgAdmin3.cpp @@ -429,7 +429,7 @@ bool pgAdmin3::OnInit() dialogTestMode = true; // Setup the image handlers and appearance factory before we do any GUI or config stuff - ::wxInitAllImageHandlers(); + //::wxInitAllImageHandlers(); appearanceFactory = new pgAppearanceFactory(); diff --git a/utils/FunctionPGHelper.cpp b/utils/FunctionPGHelper.cpp index ef24e09..f0ba3f4 100644 --- a/utils/FunctionPGHelper.cpp +++ b/utils/FunctionPGHelper.cpp @@ -231,6 +231,10 @@ order by objname; item = browser->GetNextChild(dbssId, cookie2); } // next + } else { + // brower->db close + //return wxEmptyString; + def=_("'The database is closed in the object browser.'"); } goto exitloop; diff --git a/utils/PreviewHtml.cpp b/utils/PreviewHtml.cpp index d12bf2a..72b7c0c 100644 --- a/utils/PreviewHtml.cpp +++ b/utils/PreviewHtml.cpp @@ -117,7 +117,7 @@ wxString PreviewHtml::Preview(const wxString& txt, fmtpreview type) { int flag = 0; tokens.clear(); bool quote = false; - wxUniChar prevchar; + wxUniChar prevchar,quotechar; int startstr = -1; while (pos < len) { c = tmpstr[pos++]; @@ -130,18 +130,20 @@ wxString PreviewHtml::Preview(const wxString& txt, fmtpreview type) { html+=c; continue; } - bool isquote = c == '"'; + if (!quote && (c=='"' || c=='\'')) quotechar = c; + bool isquote = c == quotechar; if (quote) { if (prevchar == c && isquote) { // repeat quote prevchar = '\0'; continue; } - if (prevchar == '"' && !isquote) { + if (prevchar == quotechar && !isquote) { // end quote string wxString tmp = tmpstr.Mid(startstr, pos - startstr - 1); saveTokenIfNotEmpty(tmp, PREVIEW_QUOTE); quote = false; + quotechar='\0'; } else { prevchar = c; @@ -214,7 +216,19 @@ wxString PreviewHtml::Preview(const wxString& txt, fmtpreview type) { saveTokenIfNotEmpty(currWord, PREVIEW_WORD); saveTokenIfNotEmpty(currDigits, PREVIEW_DIGITS); saveTokenIfNotEmpty(currSep, PREVIEW_SEP); + if (fmt == fmtpreview::AUTO && txt.Len()<256) { + if (txt.IsNumber()) { + wxLongLong l = StrToLongLong(txt); + wxString newtxt; + if ((l>999 || l<-999)) { + newtxt="
"; + saveTokenIfNotEmpty(newtxt, PREVIEW_RAWHTML); + newtxt=NumToStrHuman(l); + saveTokenIfNotEmpty(newtxt, PREVIEW_WORD); + } + } + } // Additonal styled wxString findstr = ""; diff --git a/utils/misc.cpp b/utils/misc.cpp index 9af20da..f842c8f 100644 --- a/utils/misc.cpp +++ b/utils/misc.cpp @@ -1483,28 +1483,57 @@ bool make_identifier(const wxString &strname, wxString &s, wxString &n, bool isl } else {if (islower) s=s.MakeLower();} return true; } -/* -class DirCopyTraverser: public wxDirTraverser { -public: - DirCopyTraverser(const wxString &destBase): m_destBase(destBase) {} - virtual wxDirTraverseResult OnFile(const wxString &file) wxOVERRIDE { - wxFileName srcFile(file); - //wxString relativePath=srcFile.GetPath(wxPATH_DOS,true); - srcFile.MakeRelativeTo(m_destBase); - wxString destFile=m_destBase+wxFileName::GetPathSeparator()+srcFile.GetFullName(); - wxFileName destDir(destFile); - destDir.RemoveLastDir(); - if (!destDir.DirExists()) destDir.Mkdir(wxS_DIR_DEFAULT,wxPATH_MKDIR_FULL); - if (!wxCopyFile(file,destFile,true)) { - wxLogError("Error copy file %s",file); - return wxDIR_STOP; + +// Get display for ScreenPoint +wxSize getScreenSizeForPoint(const wxPoint screenPos) { + // screen size + wxPoint posScreen; + wxSize sizeScreen; + const int displayNum = wxDisplay::GetFromPoint(screenPos); + if (displayNum != wxNOT_FOUND) + { + const wxRect rectScreen = wxDisplay(displayNum).GetGeometry(); + posScreen = rectScreen.GetPosition(); + sizeScreen = rectScreen.GetSize(); } - return wxDIR_CONTINUE; - } - virtual wxDirTraverseResult OnDir(const wxString &file) wxOVERRIDE { - return 0; - } -private: - wxString m_destBase; + else // outside of any display? + { + // just use the primary one then + posScreen = wxPoint(0, 0); + sizeScreen = wxGetDisplaySize(); + } + return sizeScreen; } -*/ \ No newline at end of file +//show help window +void showHelpHtml(wxWindow *parent, const wxString &htmlHelp,wxPoint screenPos, wxSize size) { + FunctionPGHelper fh(htmlHelp); + wxString key = "content"; + + wxSize sizeScreen=getScreenSizeForPoint(screenPos); + wxSize rr(350, 70); + if (size.x!=-1) rr=size; + popuphelp *m_Popup = new popuphelp(parent, key, &fh, screenPos, rr); + if (m_Popup && m_Popup->IsValid() && rr != m_Popup->GetSizePopup()) { + // recreate with new size + rr = m_Popup->GetSizePopup(); + delete m_Popup; + m_Popup = new popuphelp((wxWindow*)winMain, key, &fh, screenPos, rr); + } + if (m_Popup && m_Popup->IsValid()) { + wxSize top_sz = m_Popup->GetSizePopup(); + wxSize top_new(top_sz); + wxPoint p(screenPos); + wxPoint oldp(p); + if (p.x + top_new.x > sizeScreen.x) p.x = sizeScreen.x - top_new.x - 20; + if (p.y + top_new.y > sizeScreen.y) p.y = sizeScreen.y - top_new.y - 20; + if (oldp == p) p.x = p.x + 20; + m_Popup->Move(p); + wxRect r = m_Popup->GetScreenRect(); + m_Popup->Popup(); + } + //m_Popup->SetFocus(); + +} + + + diff --git a/x64/Release/pgAdmin3.exe b/x64/Release/pgAdmin3.exe index e50e89f..6875db1 100644 Binary files a/x64/Release/pgAdmin3.exe and b/x64/Release/pgAdmin3.exe differ