Hi Dave,

As discussed, I am not confident about the Printing support on Mac OSX.
It is working well on other platforms. In fact, Print Preview is also
working good on OSX. But, It gives arbitrary results for the printing.. (The
main feature of this patch.) :-(

I will need some more time investigating the exact issue.

As discussed, I m taking of the save as an image functionality from the
patch and sending you the patch for the same with this.

I am feeling very disappointed, but I do not want to rush into the things
and do not want to do things in hurry.

--
Regards,

Ashesh Vashi
EnterpriseDB INDIA: Enterprise Postgres Company<http://www.enterprisedb.com>


On Mon, Apr 26, 2010 at 6:18 PM, Dave Page <[email protected]> wrote:

> Hi Ashesh,
>
> On Fri, Apr 23, 2010 at 10:44 PM, Ashesh Vashi
> <[email protected]> wrote:
> > PFA
>
> OK, this patch now compiles on the Mac. I think here are a few things
> that need work
>
> - The Save/Print options are not enabled when they should be. For
> example, if I open the query tool, and run an Explain, I have to click
> to the 'Data Output' tab and then back to the Explain tab before the
> Save/Print options get enabled.
>
> - Why are there separate options for Saving/Printing the EXPLAIN
> output and GQB? As only one can be displayed at a time, we should have
> just one set of options which apply to the visible image.
>
> - The borders on saved images seem somewhat arbitrary. It would be
> good to crop the image to a consistent border around the visible items
> (say 25 or 50 pixels for example).
>
> - If you click on a node in a plan and then save the image, the popup
> info box isn't included.
>
> FYI, I don't think the last two items are essential to fix before beta
> 1. The first two are though.
>
> --
> Dave Page
> EnterpriseDB UK: http://www.enterprisedb.com
> The Enterprise Postgres Company
>
Index: ctl/explainCanvas.cpp
===================================================================
--- ctl/explainCanvas.cpp	(revision 8307)
+++ ctl/explainCanvas.cpp	(working copy)
@@ -26,7 +26,6 @@
     SetDiagram(new wxDiagram);
     GetDiagram()->SetCanvas(this);
     SetBackgroundColour(*wxWHITE);
-    lastShape=0;
     popup = new ExplainPopup(this);
 }
 
@@ -39,7 +38,6 @@
 void ExplainCanvas::Clear()
 {
     GetDiagram()->DeleteAllShapes();
-    lastShape=0;
 }
 
 
@@ -183,6 +181,37 @@
 }
 
 
+void ExplainCanvas::SaveAsImage(const wxString& fileName, wxBitmapType imageType)
+{
+    if (GetDiagram()->GetCount() == 0)
+    {
+        wxMessageBox(_("Nothing to be saved!"), _("Save As an image"), wxOK | wxICON_INFORMATION);
+        return;
+    }
+
+    int width = 0, height = 0;
+    GetVirtualSize(&width, &height);
+    
+    /*
+    * Create the bitmap from the Explain window
+    */
+    wxMemoryDC memDC;
+    wxBitmap tempBitmap(width, height);
+    
+    memDC.SelectObject(tempBitmap);
+    memDC.Clear();
+    
+    // Draw the diagram on the bitmap (Memory Device Context)
+    GetDiagram()->Redraw(memDC);
+    
+    memDC.SelectObject(wxNullBitmap);
+
+    if (!tempBitmap.SaveFile(fileName, imageType))
+    {
+        wxLogError(_("Could not write the file %s: Errcode=%d."), fileName.c_str(), wxSysErrorCode());
+    }
+}
+
 class ExplainText : public wxWindow
 {
 public:
Index: include/ctl/explainCanvas.h
===================================================================
--- include/ctl/explainCanvas.h	(revision 8307)
+++ include/ctl/explainCanvas.h	(working copy)
@@ -33,10 +33,11 @@
     void ShowPopup(ExplainShape *s);
     void SetExplainString(const wxString &str);
     void Clear();
+    void SaveAsImage(const wxString& fileName, wxBitmapType imageType);
 
 private:
 
-    ExplainShape *rootShape, *lastShape;
+    ExplainShape *rootShape;
     ExplainPopup *popup;
 };
 
@@ -105,3 +106,4 @@
 };
 
 #endif
+
Index: include/ctl/ctlSQLBox.h
===================================================================
--- include/ctl/ctlSQLBox.h	(revision 8307)
+++ include/ctl/ctlSQLBox.h	(working copy)
@@ -58,7 +58,6 @@
     void SetAutoIndent(bool on) { m_autoIndent = on; }
     void EnableAutoComp(bool on) { m_autocompDisabled = on; }
     bool BlockComment(bool uncomment=false);
-
     void UpdateLineNumber();
 
     CharacterRange RegexFindText(int minPos, int maxPos, const wxString& text);
@@ -73,7 +72,9 @@
     dlgFindReplace* m_dlgFindReplace;
 	pgConn *m_database;
     bool m_autoIndent, m_autocompDisabled;
+
+    friend class QueryPrintout;
 };
 
+#endif
 
-#endif
Index: include/frm/menu.h
===================================================================
--- include/frm/menu.h	(revision 8307)
+++ include/frm/menu.h	(working copy)
@@ -19,6 +19,8 @@
     MNU_ADDSERVER = 101,
     MNU_SAVEDEFINITION,
     MNU_EXIT,
+    MNU_SAVEAS_IMAGE_GQB,
+    MNU_SAVEAS_IMAGE_EXPLAIN,
     MNU_CONTEXTMENU,
     MNU_SQLPANE,
     MNU_OBJECTBROWSER,
Index: include/frm/frmQuery.h
===================================================================
--- include/frm/frmQuery.h	(revision 8307)
+++ include/frm/frmQuery.h	(working copy)
@@ -154,6 +154,7 @@
     void OnOpen(wxCommandEvent& event);
     void OnSave(wxCommandEvent& event);
     void OnSaveAs(wxCommandEvent& event);
+    void SaveExplainAsImage(wxCommandEvent& event);
     void OnExport(wxCommandEvent& event);
     void OnExit(wxCommandEvent& event);
     void OnCut(wxCommandEvent& event);
@@ -226,6 +227,8 @@
     wxMenu *macrosMenu;
     wxMenu *lineEndMenu;
     wxMenu *formatMenu;
+    wxMenu *saveasImageMenu;
+
     wxString title;
     wxString lastFilename, lastDir;
 
Index: include/gqb/gqbGraphSimple.h
===================================================================
--- include/gqb/gqbGraphSimple.h	(revision 8307)
+++ include/gqb/gqbGraphSimple.h	(working copy)
@@ -23,10 +23,10 @@
 {
 public:
     gqbGraphSimple();
-    void drawTable(wxBufferedDC& bdc, wxPoint *origin, gqbQueryObject *queryTable);
-    void drawTempJoinLine(wxBufferedDC& bdc, wxPoint &origin, wxPoint &end);
+    void drawTable(wxMemoryDC& bdc, wxPoint *origin, gqbQueryObject *queryTable);
+    void drawTempJoinLine(wxMemoryDC& bdc, wxPoint &origin, wxPoint &end);
     void calcAnchorPoint(gqbQueryJoin *join);
-    void drawJoin(wxBufferedDC& bdc, wxPoint& origin, wxPoint& dest, wxPoint& anchorUsed, bool selected, type_Join joinKind);
+    void drawJoin(wxMemoryDC& bdc, wxPoint& origin, wxPoint& dest, wxPoint& anchorUsed, bool selected, type_Join joinKind);
     void UpdatePosObject(gqbQueryObject *queryTable, int x, int y, int cursorAdjustment);
     gqbColumn* getColumnAtPosition(wxPoint *clickPoint, gqbQueryObject *queryTable, int sensibility=17);
     bool clickOnJoin(gqbQueryJoin *join, wxPoint &pt, wxPoint &origin, wxPoint &dest);
Index: include/gqb/gqbViewController.h
===================================================================
--- include/gqb/gqbViewController.h	(revision 8307)
+++ include/gqb/gqbViewController.h	(working copy)
@@ -18,6 +18,9 @@
 #include <wx/dnd.h>
 #include <wx/dataobj.h>
 
+#define GQB_MIN_WIDTH  1280
+#define GQB_MIN_HEIGHT 800
+
 // App headers
 #include "gqb/gqbObject.h"
 #include "gqb/gqbModel.h"
@@ -109,7 +112,9 @@
 public:
     gqbView(wxWindow *gqbParent, wxNotebook *gridParent, wxSize size, gqbController *controller, gqbModel *model);
     ~gqbView();
-    void drawAll(wxBufferedDC& bdc);
+    void SaveAsImage(const wxString& path, wxBitmapType imgType);
+    bool canSaveAsImage();
+    void drawAll(wxMemoryDC& bdc, bool adjustScrolling);
     void setPointerMode(pointerMode pm);
 
 	// Events for wxScrolledWindow
@@ -186,4 +191,6 @@
 private:
     gqbBrowser *tree;
 };
+
 #endif
+
Index: include/gqb/gqbGraphBehavior.h
===================================================================
--- include/gqb/gqbGraphBehavior.h	(revision 8307)
+++ include/gqb/gqbGraphBehavior.h	(working copy)
@@ -23,9 +23,9 @@
 public:
     // Important: The drawTable function always should store the width & height of the graphic
     // representation of the table inside the gqbQueryObject for use of controller.
-    virtual void drawTable(wxBufferedDC& bdc, wxPoint *origin, gqbQueryObject *queryTable)=0;
-    virtual void drawTempJoinLine(wxBufferedDC& bdc, wxPoint &origin, wxPoint &end)=0;
-    virtual void drawJoin(wxBufferedDC& bdc, wxPoint& origin, wxPoint& dest, wxPoint& anchorUsed, bool selected, type_Join joinKind)=0;
+    virtual void drawTable(wxMemoryDC& bdc, wxPoint *origin, gqbQueryObject *queryTable)=0;
+    virtual void drawTempJoinLine(wxMemoryDC& bdc, wxPoint &origin, wxPoint &end)=0;
+    virtual void drawJoin(wxMemoryDC& bdc, wxPoint& origin, wxPoint& dest, wxPoint& anchorUsed, bool selected, type_Join joinKind)=0;
     virtual void calcAnchorPoint(gqbQueryJoin *join)=0;
     virtual void UpdatePosObject(gqbQueryObject *queryTable, int x, int y, int cursorAdjustment)=0;
     
Index: pgAdmin3.cpp
===================================================================
--- pgAdmin3.cpp	(revision 8307)
+++ pgAdmin3.cpp	(working copy)
@@ -297,9 +297,10 @@
         dialogTestMode = true;
 
     // Setup the image handlers and appearance factory before we do any GUI or config stuff
-    wxImage::AddHandler(new wxJPEGHandler());
-    wxImage::AddHandler(new wxPNGHandler());
-    wxImage::AddHandler(new wxGIFHandler());
+    ::wxInitAllImageHandlers();
+    // wxImage::AddHandler(new wxJPEGHandler());
+    // wxImage::AddHandler(new wxPNGHandler());
+    // wxImage::AddHandler(new wxGIFHandler());
 
     appearanceFactory = new pgAppearanceFactory();
 
Index: frm/frmQuery.cpp
===================================================================
--- frm/frmQuery.cpp	(revision 8307)
+++ frm/frmQuery.cpp	(working copy)
@@ -101,6 +101,8 @@
 EVT_MENU(MNU_SAVE,              frmQuery::OnSave)
 EVT_MENU(MNU_SAVEAS,            frmQuery::OnSaveAs)
 EVT_MENU(MNU_EXPORT,            frmQuery::OnExport)
+EVT_MENU(MNU_SAVEAS_IMAGE_GQB,     frmQuery::SaveExplainAsImage)
+EVT_MENU(MNU_SAVEAS_IMAGE_EXPLAIN, frmQuery::SaveExplainAsImage)
 EVT_MENU(MNU_EXIT,              frmQuery::OnExit)
 EVT_MENU(MNU_CUT,               frmQuery::OnCut)
 EVT_MENU(MNU_COPY,              frmQuery::OnCopy)
@@ -223,6 +225,8 @@
     recentKey = wxT("RecentFiles");
     RestorePosition(100, 100, 600, 500, 450, 300);
 
+    explainCanvas = NULL;
+
     // notify wxAUI which frame to use
     manager.SetManagedWindow(this);
     manager.SetFlags(wxAUI_MGR_DEFAULT | wxAUI_MGR_TRANSPARENT_DRAG);
@@ -238,7 +242,11 @@
     fileMenu->Append(MNU_NEW, _("&New window\tCtrl-N"), _("Open a new query window"));
     fileMenu->Append(MNU_OPEN, _("&Open...\tCtrl-O"),   _("Open a query file"));
     fileMenu->Append(MNU_SAVE, _("&Save\tCtrl-S"),      _("Save current file"));
-    fileMenu->Append(MNU_SAVEAS, _("Save &as..."),      _("Save file under new name"));
+    saveasImageMenu = new wxMenu();
+    saveasImageMenu->Append(MNU_SAVEAS, _("Query (text)"), _("Save file under new name"));
+    saveasImageMenu->Append(MNU_SAVEAS_IMAGE_GQB, _("Graphical Query (image)"), _("Save Graphical Query as an image"));
+    saveasImageMenu->Append(MNU_SAVEAS_IMAGE_EXPLAIN, _("Explain (image)"), _("Save output of Explain as an image"));
+    fileMenu->Append(wxID_ANY, _("Save as"), saveasImageMenu);
     fileMenu->AppendSeparator();
     fileMenu->Append(MNU_EXPORT, _("&Export..."),  _("Export data to file"));
     fileMenu->Append(MNU_QUICKREPORT, _("&Quick report..."),  _("Run a quick report..."));
@@ -1335,6 +1343,8 @@
     bool canClear=false;
     bool canFind=false;
     bool canAddFavourite=false;
+    bool canSaveExplain=false;
+    bool canSaveGQB=false;
 
     wxAuiFloatingFrame *fp = wxDynamicCastThis(wxAuiFloatingFrame);
     if (fp)
@@ -1362,6 +1372,9 @@
         canClear = true;
     }
 
+    canSaveExplain = explainCanvas->GetDiagram()->GetCount() > 0;
+    canSaveGQB = controller->getView()->canSaveAsImage();
+
     toolBar->EnableTool(MNU_UNDO, canUndo);
     editMenu->Enable(MNU_UNDO, canUndo);
 
@@ -1381,6 +1394,7 @@
     editMenu->Enable(MNU_FIND, canFind);
 
     favouritesMenu->Enable(MNU_FAVOURITES_ADD, canAddFavourite);
+
 }
 
 
@@ -1923,7 +1937,7 @@
         resultToRetrieve++;
     }
     sql += wxT("EXPLAIN ");
-    if (conn->BackendMinimumVersion(8, 5))
+    if (conn->BackendMinimumVersion(9, 0))
     {
         bool costs=queryMenu->IsChecked(MNU_COSTS);
         bool buffers=queryMenu->IsChecked(MNU_BUFFERS);
@@ -1986,6 +2000,7 @@
     // Make sure this doesn't get call recursively through an event
     if (gqbUpdateRunning)
         return false;
+    updateMenu();
 
     gqbUpdateRunning = true;
 
@@ -2628,6 +2643,7 @@
             explainCanvas->SetExplainString(str);
             outputPane->SetSelection(1);
         }
+        updateMenu();
     }
 
     sqlQuery->SetFocus();
@@ -3147,6 +3163,50 @@
     return view->HasInsertRule();
 }
 
+void frmQuery::SaveExplainAsImage(wxCommandEvent& ev)
+{
+    wxFileDialog *dlg=new wxFileDialog(this, _("Save Explain As image file"), lastDir, lastFilename,
+           wxT("Bitmap files (*.bmp)|*.bmp|JPEG files (*.jpeg)|*.jpeg|PNG files (*.png)|*.png"), wxFD_SAVE|wxFD_OVERWRITE_PROMPT);
+    if (dlg->ShowModal() == wxID_OK)
+    {
+        lastFilename=dlg->GetFilename();
+        lastDir = dlg->GetDirectory();
+        lastPath = dlg->GetPath();
+        int index = dlg->GetFilterIndex();
+
+        wxString     strType;
+        wxBitmapType imgType;
+        switch (index)
+        {
+        // bmp
+        case 0:
+            strType = wxT(".bmp");
+            imgType = wxBITMAP_TYPE_BMP;
+            break;
+        // jpeg
+        case 1:
+            strType = wxT(".jpeg");
+            imgType = wxBITMAP_TYPE_JPEG;
+            break;
+        // default (png)
+        default:
+        // png
+        case 2:
+            strType = wxT(".png");
+            imgType = wxBITMAP_TYPE_PNG;
+            break;
+        }
+
+        if (!lastPath.Contains(wxT(".")))
+            lastPath += strType;
+
+        if (ev.GetId() == MNU_SAVEAS_IMAGE_GQB)
+            controller->getView()->SaveAsImage(lastPath, imgType);
+        else if (ev.GetId() == MNU_SAVEAS_IMAGE_EXPLAIN)
+            explainCanvas->SaveAsImage(lastPath, imgType);
+    }
+}
+
 ///////////////////////////////////////////////////////
 
 pgScriptTimer::pgScriptTimer(frmQuery * parent) :
Index: gqb/gqbView.cpp
===================================================================
--- gqb/gqbView.cpp	(revision 8307)
+++ gqb/gqbView.cpp	(working copy)
@@ -138,14 +138,14 @@
 {
     wxPaintDC dcc(this);                          // Prepare Context for Buffered Draw
     wxBufferedDC dc(&dcc, canvasSize);
-    drawAll(dc);                                  // Call Function to draw all
+    drawAll(dc, true);                            // Call Function to draw all
 }
 
 
 // GQB-TODO: remove all possible modification to model from here to controller.
 void gqbView::onRightClick(wxMouseEvent& event)
 {
-// GQB-TODO: Validate Alias
+    // GQB-TODO: Validate Alias
     gqbObject *anySelected=NULL;
     wxPoint pdc=event.GetPosition();
     pdc.x=event.GetPosition().x;
@@ -502,8 +502,9 @@
                 {
                     this->Refresh();
                     refresh=1;
-                }else
-                refresh++;
+                }
+                else
+                    refresh++;
 
             }
         }
@@ -542,7 +543,7 @@
 }
 
 
-void gqbView::drawAll(wxBufferedDC& bdc)
+void gqbView::drawAll(wxMemoryDC& bdc, bool adjustScrolling)
 {
     bdc.Clear();
     if(!iterator)
@@ -558,8 +559,11 @@
         wxPoint pt = wxPoint(tmp->position);      // Use a copy because I don't want to store the modified 
 		                                          // version of point after CalcScrolledPosition was called
 
-		// adjust coordinates
-        this->CalcScrolledPosition(pt.x,pt.y,&pt.x,&pt.y);
+        if (adjustScrolling)
+        {
+            // adjust coordinates
+            this->CalcScrolledPosition(pt.x,pt.y,&pt.x,&pt.y);
+        }
         graphBehavior->drawTable(bdc,&pt,tmp);    // graph table
     }
 
@@ -578,11 +582,14 @@
                 wxPoint o = join->getSourceAnchor();
                 wxPoint d = join->getDestAnchor();
 
-                // adjust coordinates origin
-                this->CalcScrolledPosition(o.x,o.y,&o.x,&o.y);
-
-                // adjust coordinates destination
-                this->CalcScrolledPosition(d.x,d.y,&d.x,&d.y);
+                if (adjustScrolling)
+                {
+                    // adjust coordinates origin
+                    this->CalcScrolledPosition(o.x,o.y,&o.x,&o.y);
+    
+                    // adjust coordinates destination
+                    this->CalcScrolledPosition(d.x,d.y,&d.x,&d.y);
+                }
                 graphBehavior->drawJoin(bdc,o,d,join->getAnchorsUsed(), join->getSelected(), join->getKindofJoin());
             }
             delete joinsIterator;
@@ -596,8 +603,11 @@
         // Draw temporary line while creating a join
         wxPoint source=jpos;
         wxPoint destination=pos;
-        this->CalcScrolledPosition(source.x,source.y,&source.x,&source.y);
-        this->CalcScrolledPosition(destination.x,destination.y,&destination.x,&destination.y);
+        if(adjustScrolling)
+        {
+            this->CalcScrolledPosition(source.x,source.y,&source.x,&source.y);
+            this->CalcScrolledPosition(destination.x,destination.y,&destination.x,&destination.y);
+        }
         graphBehavior->drawTempJoinLine(bdc,source,destination);
     }
 }
@@ -750,3 +760,46 @@
     }
 }
 
+
+bool gqbView::canSaveAsImage()
+{
+    updateModelSize(NULL, true);
+    return !(modelSize.GetWidth() == 0 || modelSize.GetHeight() == 0);
+}
+
+void gqbView::SaveAsImage(const wxString& fileName, wxBitmapType imgType)
+{
+
+    updateModelSize(NULL, true);
+
+    if (modelSize.GetWidth() == 0 || modelSize.GetHeight() == 0)
+    {
+        wxMessageBox(_("Nothing to be saved!"), _("Save As an image"), wxOK | wxICON_INFORMATION);
+        return;
+    }
+
+    int width = 0, height = 0;
+    GetVirtualSize(&width, &height);
+    
+    /*
+    * Create the bitmap from the Explain window
+    */
+    wxMemoryDC memDC;
+    wxBitmap tempBitmap(width, height);
+    
+    memDC.SelectObject(tempBitmap);
+    memDC.Clear();
+    
+    // Draw the diagram on the bitmap (Memory Device Context)
+    drawAll(memDC, false);
+    
+    memDC.SelectObject(wxNullBitmap);
+    
+    if (!tempBitmap.SaveFile(fileName, imgType))
+    {
+        wxLogError(_("Could not write the file %s: Errcode=%d."), fileName.c_str(), wxSysErrorCode());
+    }
+}
+
+
+
Index: gqb/gqbGraphSimple.cpp
===================================================================
--- gqb/gqbGraphSimple.cpp	(revision 8307)
+++ gqb/gqbGraphSimple.cpp	(working copy)
@@ -49,7 +49,7 @@
 
 // NOTES:(1) store values of width & height at queryTable.
 // (2)Need to set a font for the device context before get font metrics with GetTextExtent
-void gqbGraphSimple::drawTable(wxBufferedDC& bdc, wxPoint *origin, gqbQueryObject *queryTable)
+void gqbGraphSimple::drawTable(wxMemoryDC& bdc, wxPoint *origin, gqbQueryObject *queryTable)
 {
     long  w=0,h=0,height=0,width=0,margin=5;
 
@@ -188,7 +188,7 @@
 }
 
 
-void gqbGraphSimple::drawTempJoinLine(wxBufferedDC& bdc, wxPoint &origin, wxPoint &end)
+void gqbGraphSimple::drawTempJoinLine(wxMemoryDC& bdc, wxPoint &origin, wxPoint &end)
 {
     wxPoint anchorsUsed = wxPoint(0,0);
 
@@ -207,7 +207,7 @@
 }
 
 
-void gqbGraphSimple::drawJoin(wxBufferedDC& bdc, wxPoint& origin, wxPoint& dest, wxPoint& anchorUsed, bool selected=false, type_Join joinKind=_equally)
+void gqbGraphSimple::drawJoin(wxMemoryDC& bdc, wxPoint& origin, wxPoint& dest, wxPoint& anchorUsed, bool selected=false, type_Join joinKind=_equally)
 {
     wxPoint origin2=origin;
     wxPoint dest2=dest;
@@ -451,8 +451,11 @@
 {
     x-=cursorAdjustment;                          // Move Pointer to a better Position;
     y-=rowHeight/2;
-    queryTable->position.x=x;                     // Update position of table
-    queryTable->position.y=y;
+    
+    // Update position of table
+    // Do not allow table/view moved/repositioned less than (0, 0) cordinates
+    queryTable->position.x= x > 0 ? x : 0;
+    queryTable->position.y= y > 0 ? y : 0;
 
     // Update position of anchor points of Joins that origin from this table
     if(queryTable->getHaveJoins())
-- 
Sent via pgadmin-hackers mailing list ([email protected])
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgadmin-hackers

Reply via email to