There was some talk a while back about being able to save the explain
output graphically, and I've taken a stab at it. Attached patch appears
to be working for me, but I had a lot of trouble getting things to work
properly before I found the right track. Specifically, I got the wrong
size of the image all the time.
So if some people could test the patch with a bunch of different queries
and strange explain outputs, to see if you get proper size images out of
it, that would be great :-)
Thanks!
//Magnus
Index: ctl/explainCanvas.cpp
===================================================================
--- ctl/explainCanvas.cpp (revision 6992)
+++ ctl/explainCanvas.cpp (working copy)
@@ -163,6 +163,9 @@
int h=(rootShape->totalShapes * yoffs + y0*2 + PIXPERUNIT - 1) / PIXPERUNIT;
SetScrollbars(PIXPERUNIT, PIXPERUNIT, w, h);
+
+ graphWidth = maxLevel * xoffs + x0;
+ graphHeight = rootShape->totalShapes * yoffs + y0;
}
@@ -182,7 +185,34 @@
popup->Move(ClientToScreen(wxPoint(sx, sy)));
}
+bool ExplainCanvas::CanSave()
+{
+ return (GetDiagram()->GetCount() > 0);
+}
+bool ExplainCanvas::SaveToFile(const wxString& filename)
+{
+ wxBitmap bmp(graphWidth, graphHeight);
+ wxMemoryDC *mem = new wxMemoryDC();
+
+ mem->SelectObject(bmp);
+ mem->Clear();
+
+ GetDiagram()->Redraw(*mem);
+
+ if (!bmp.SaveFile(filename, wxBITMAP_TYPE_PNG))
+ {
+ wxLogError(__("Could not write the file %s."), filename.c_str());
+ delete mem;
+ return false;
+ }
+
+ delete mem;
+
+ return true;
+}
+
+
class ExplainText : public wxWindow
{
public:
Index: pgAdmin3.cpp
===================================================================
--- pgAdmin3.cpp (revision 6992)
+++ pgAdmin3.cpp (working copy)
@@ -183,6 +183,9 @@
// Force logging off until we're ready
wxLog *seLog=new wxLogStderr();
wxLog::SetActiveTarget(seLog);
+
+ // Initialize image formats
+ ::wxInitAllImageHandlers();
static const wxCmdLineEntryDesc cmdLineDesc[] =
{
Index: include/ctl/explainCanvas.h
===================================================================
--- include/ctl/explainCanvas.h (revision 6992)
+++ include/ctl/explainCanvas.h (working copy)
@@ -33,11 +33,14 @@
void ShowPopup(ExplainShape *s);
void SetExplainString(const wxString &str);
void Clear();
+ bool CanSave();
+ bool SaveToFile(const wxString &filename);
private:
ExplainShape *rootShape, *lastShape;
ExplainPopup *popup;
+ int graphHeight, graphWidth;
};
Index: include/frm/menu.h
===================================================================
--- include/frm/menu.h (revision 6992)
+++ include/frm/menu.h (working copy)
@@ -62,6 +62,7 @@
MNU_ANALYZE,
MNU_CLEARHISTORY,
MNU_SAVEHISTORY,
+ MNU_SAVEEXPLAIN,
MNU_CHECKALIVE,
MNU_SELECTALL,
Index: include/frm/frmQuery.h
===================================================================
--- include/frm/frmQuery.h (revision 6992)
+++ include/frm/frmQuery.h (working copy)
@@ -105,6 +105,7 @@
void OnSaveHistory(wxCommandEvent& event);
void OnChangeConnection(wxCommandEvent &ev);
void OnClearHistory(wxCommandEvent& event);
+ void OnSaveExplain(wxCommandEvent& event);
void OnActivate(wxActivateEvent& event);
void OnFocus(wxFocusEvent& event);
void OnSelectAll(wxCommandEvent& event);
Index: frm/frmQuery.cpp
===================================================================
--- frm/frmQuery.cpp (revision 6992)
+++ frm/frmQuery.cpp (working copy)
@@ -92,6 +92,7 @@
EVT_MENU(MNU_HELP, frmQuery::OnHelp)
EVT_MENU(MNU_CLEARHISTORY, frmQuery::OnClearHistory)
EVT_MENU(MNU_SAVEHISTORY, frmQuery::OnSaveHistory)
+ EVT_MENU(MNU_SAVEEXPLAIN, frmQuery::OnSaveExplain)
EVT_MENU(MNU_SELECTALL, frmQuery::OnSelectAll)
EVT_MENU(MNU_QUICKREPORT, frmQuery::OnQuickReport)
EVT_MENU(MNU_AUTOINDENT, frmQuery::OnAutoIndent)
@@ -195,6 +196,7 @@
queryMenu->AppendSeparator();
queryMenu->Append(MNU_SAVEHISTORY, _("Save history"), _("Save history of executed commands."));
queryMenu->Append(MNU_CLEARHISTORY, _("Clear history"), _("Clear history window."));
+ queryMenu->Append(MNU_SAVEEXPLAIN, _("Save explain"), _("Save explain output image."));
queryMenu->AppendSeparator();
queryMenu->Append(MNU_CANCEL, _("&Cancel\tAlt-Break"), _("Cancel query"));
menuBar->Append(queryMenu, _("&Query"));
@@ -856,7 +858,17 @@
}
+void frmQuery::OnSaveExplain(wxCommandEvent& event)
+{
+ wxFileDialog *dlg = new wxFileDialog(this, _("Save explain"), lastDir, wxEmptyString,
+ _("Image files (*.png)|*.png|All files (*.*)|*.*)"), wxFD_SAVE|wxFD_OVERWRITE_PROMPT);
+ if (dlg->ShowModal() == wxID_OK)
+ {
+ explainCanvas->SaveToFile(dlg->GetPath());
+ }
+}
+
void frmQuery::OnSetFocus(wxFocusEvent& event)
{
sqlQuery->SetFocus();
@@ -1548,6 +1560,7 @@
return;
explainCanvas->SetExplainString(str);
+ setTools(false);
outputPane->SetSelection(1);
sqlQuery->SetFocus();
}
@@ -1632,6 +1645,7 @@
queryMenu->Enable(MNU_EXECFILE, !running);
queryMenu->Enable(MNU_EXPLAIN, !running);
queryMenu->Enable(MNU_CANCEL, running);
+ queryMenu->Enable(MNU_SAVEEXPLAIN, explainCanvas->CanSave());
fileMenu->Enable(MNU_EXPORT, sqlResult->CanExport());
fileMenu->Enable(MNU_QUICKREPORT, sqlResult->CanExport());
fileMenu->Enable(MNU_RECENT, (recentFileMenu->GetMenuItemCount() > 0));
@@ -1653,12 +1667,12 @@
void frmQuery::execQuery(const wxString &query, int resultToRetrieve, bool singleResult, const int queryOffset, bool
toFile,bool explain, bool verbose)
{
+ explainCanvas->Clear();
+
setTools(true);
queryMenu->Enable(MNU_SAVEHISTORY, true);
queryMenu->Enable(MNU_CLEARHISTORY, true);
- explainCanvas->Clear();
-
// Clear markers and indicators
sqlQuery->MarkerDeleteAll(0);
sqlQuery->StartStyling(0, wxSTC_INDICS_MASK);
@@ -1933,6 +1947,7 @@
}
}
explainCanvas->SetExplainString(str);
+ setTools(false);
outputPane->SetSelection(1);
}
}