Index: pgadmin/ctl/explainPrintout.cpp
===================================================================
--- pgadmin/ctl/explainPrintout.cpp	(revision 0)
+++ pgadmin/ctl/explainPrintout.cpp	(revision 0)
@@ -0,0 +1,672 @@
+//////////////////////////////////////////////////////////////////////////
+//
+// pgAdmin III - PostgreSQL Tools
+// RCS-ID:      $Id: $
+// Copyright (C) 2002 - 2009, The pgAdmin Development Team
+// This software is released under the BSD Licence
+//
+// explainPrintout.cpp - Explain Printout class
+//
+//////////////////////////////////////////////////////////////////////////
+
+
+// wxWindows headers
+#include <wx/wx.h>
+
+// App headers
+#include "pgAdmin3.h"
+
+#include "ctl/explainCanvas.h"
+
+#if wxUSE_PRINTING_ARCHITECTURE
+
+//! global print data, to remember settings
+extern wxPrintData *g_explainGQBPrintData;
+extern wxPageSetupData *g_explainGQBPageSetupData;
+
+void ExplainCanvas::PrintPreview()
+{
+    wxPrintDialogData printDialogData(* g_explainGQBPrintData);
+    wxPrintPreview *preview = new wxPrintPreview(new ExplainPrintout(this), new ExplainPrintout(this), &printDialogData);
+    if (!preview->Ok())
+    {
+        delete preview;
+        wxMessageBox(_T("There was a problem previewing.\nPerhaps your current printer is not set correctly?"), _T("Previewing"), wxOK);
+        return;
+    }
+    
+    wxPreviewFrame *frame = new wxPreviewFrame(preview, this, _T("Print Preview - Explain"), wxDefaultPosition, wxSize(600, 650));
+    frame->Centre(wxBOTH);
+    frame->Initialize();
+    frame->Show();
+}
+
+void ExplainCanvas::Print()
+{
+    wxPrintDialogData printDialogData( *g_explainGQBPrintData);
+    wxPrinter printer(&printDialogData);
+    ExplainPrintout printout(this);
+    if (!printer.Print(this, &printout, true)) 
+    {
+        if (wxPrinter::GetLastError() == wxPRINTER_ERROR)
+        {
+            wxMessageBox (
+              _("There was a problem with printing.\nPerhaps your current printer is not correctly?"),
+              _("Printing"), wxOK);
+            return;
+        }
+    }
+    (*g_explainGQBPrintData) = printer.GetPrintDialogData().GetPrintData();
+
+}
+
+ExplainPrintout::ExplainPrintout (ExplainCanvas* explain, wxString title)
+: wxPrintout(title), m_printBitmap(NULL)
+{
+    m_explain = explain;
+}
+
+ExplainPrintout::~ExplainPrintout()
+{
+    m_explain = NULL;
+    if (m_printBitmap)
+    {
+        delete m_printBitmap;
+        m_printBitmap = NULL;
+    }
+}
+
+bool ExplainPrintout::OnPrintPage (int page)
+{
+    if (page > m_noPages)
+        return false;
+
+    wxDC *dc = GetDC();
+    if (!dc)
+        return false;
+    PrintScaling (dc);
+
+    int width = 0, height = 0;
+    m_explain->GetVirtualSize(&width, &height);
+
+    /*
+    * Create a temporary bitmap from the Explain window
+    */
+    if (!m_printBitmap)
+    {
+        wxMemoryDC memDC;
+        m_printBitmap = new wxBitmap(width, height);
+
+        memDC.SelectObject(*m_printBitmap);
+        memDC.Clear();
+
+        // Draw the diagram on the bitmap (Memory Device Context)
+        m_explain->GetDiagram()->Redraw(memDC);
+
+        memDC.SelectObject(wxNullBitmap);
+    }
+
+    int posX = 0, posY = 0;
+    int current_page = 1;
+
+    /*
+    * Calculate the starting cordinates (x, y) for the given page
+    */
+    while(current_page != page)
+    {
+        posX += m_pageRect.width;
+        if (posX >= width)
+        {
+            posY += m_pageRect.height;
+            posX = 0;    
+        }
+        current_page++;
+    };
+
+    /*
+    * Create the bitmap of the required size from the stored whole window bitmap
+    */
+    wxBitmap newBitmap = m_printBitmap->GetSubBitmap(wxRect(posX, posY,
+      posX + m_pageRect.width  >= width ? width - posX : m_pageRect.width,
+      posY + m_pageRect.height >= height ? height - posY : m_pageRect.height));
+
+    dc->DrawBitmap(newBitmap, m_pageRect.x, m_pageRect.y, true);
+
+    return true;
+}
+
+bool ExplainPrintout::OnBeginDocument (int startPage, int endPage)
+{
+    return wxPrintout::OnBeginDocument(startPage, endPage);
+}
+
+// Print Functions
+bool ExplainPrintout::HasPage (int page)
+{
+    if (page <= m_noPages)
+        return true;
+    return false;
+}
+
+void ExplainPrintout::GetPageInfo (int *minPage, int *maxPage, int *selPageFrom, int *selPageTo)
+{
+    // initialize values
+    *minPage = 0;
+    *maxPage = 0;
+    *selPageFrom = 0;
+    *selPageTo = 0;
+    
+    // scale DC if possible
+    wxDC *dc = GetDC();
+    if (!dc)
+        return;
+    PrintScaling (dc);
+    
+    m_pageRect = GetLogicalPageMarginsRect(*g_explainGQBPageSetupData);
+    
+    int width = 0, height = 0;
+    m_explain->GetVirtualSize(&width, &height);
+
+    m_noPages = 1;
+    int posX = 0, posY = 0;
+    while (true)
+    {
+        if (posX + m_pageRect.width  >= width &&
+            posY + m_pageRect.height >= height)
+            break;
+        posX += m_pageRect.width;
+        if (posX >= width)
+        {
+            posY += m_pageRect.height;
+            posX = 0;    
+        }    
+        m_noPages++;
+    };
+
+    *minPage = 1;
+    *maxPage = m_noPages;
+    *selPageFrom = 1;
+    *selPageTo = 1;
+}
+
+bool ExplainPrintout::PrintScaling (wxDC *dc)
+{
+    // check for dc, return if none
+    if (!dc)
+        return false;
+    
+    // get printer and screen sizing values
+    wxSize ppiScr;
+    GetPPIScreen (&ppiScr.x, &ppiScr.y);
+    if (ppiScr.x == 0) { // most possible guess 96 dpi
+        ppiScr.x = 96;
+        ppiScr.y = 96;
+    }
+    wxSize ppiPrt;
+    GetPPIPrinter (&ppiPrt.x, &ppiPrt.y);
+    if (ppiPrt.x == 0) { // scaling factor to 1
+        ppiPrt.x = ppiScr.x;
+        ppiPrt.y = ppiScr.y;
+    }
+    wxSize dcSize = dc->GetSize();
+    wxSize pageSize;
+    GetPageSizePixels (&pageSize.x, &pageSize.y);
+    
+    // set user scale
+    float scale_x = (float)(ppiPrt.x * dcSize.x) / (float)(ppiScr.x * pageSize.x);
+    float scale_y = (float)(ppiPrt.y * dcSize.y) / (float)(ppiScr.y * pageSize.y);
+    dc->SetUserScale (scale_x , scale_y);
+
+    return true;
+}
+
+#endif // wxUSE_PRINTING_ARCHITECTURE
+
+//////////////////////////////////////////////////////////////////////////
+//
+// pgAdmin III - PostgreSQL Tools
+// RCS-ID:      $Id: $
+// Copyright (C) 2002 - 2009, The pgAdmin Development Team
+// This software is released under the BSD Licence
+//
+// explainPrintout.cpp - Explain Printout class
+//
+//////////////////////////////////////////////////////////////////////////
+
+
+// wxWindows headers
+#include <wx/wx.h>
+
+// App headers
+#include "pgAdmin3.h"
+
+#include "ctl/explainCanvas.h"
+
+#if wxUSE_PRINTING_ARCHITECTURE
+
+//! global print data, to remember settings
+extern wxPrintData *g_explainGQBPrintData;
+extern wxPageSetupData *g_explainGQBPageSetupData;
+
+void ExplainCanvas::PrintPreview()
+{
+    wxPrintDialogData printDialogData(* g_explainGQBPrintData);
+    wxPrintPreview *preview = new wxPrintPreview(new ExplainPrintout(this), new ExplainPrintout(this), &printDialogData);
+    if (!preview->Ok())
+    {
+        delete preview;
+        wxMessageBox(_T("There was a problem previewing.\nPerhaps your current printer is not set correctly?"), _T("Previewing"), wxOK);
+        return;
+    }
+    
+    wxPreviewFrame *frame = new wxPreviewFrame(preview, this, _T("Print Preview - Explain"), wxDefaultPosition, wxSize(600, 650));
+    frame->Centre(wxBOTH);
+    frame->Initialize();
+    frame->Show();
+}
+
+void ExplainCanvas::Print()
+{
+    wxPrintDialogData printDialogData( *g_explainGQBPrintData);
+    wxPrinter printer(&printDialogData);
+    ExplainPrintout printout(this);
+    if (!printer.Print(this, &printout, true)) 
+    {
+        if (wxPrinter::GetLastError() == wxPRINTER_ERROR)
+        {
+            wxMessageBox (
+              _("There was a problem with printing.\nPerhaps your current printer is not correctly?"),
+              _("Printing"), wxOK);
+            return;
+        }
+    }
+    (*g_explainGQBPrintData) = printer.GetPrintDialogData().GetPrintData();
+
+}
+
+ExplainPrintout::ExplainPrintout (ExplainCanvas* explain, wxString title)
+: wxPrintout(title), m_printBitmap(NULL)
+{
+    m_explain = explain;
+}
+
+ExplainPrintout::~ExplainPrintout()
+{
+    m_explain = NULL;
+    if (m_printBitmap)
+    {
+        delete m_printBitmap;
+        m_printBitmap = NULL;
+    }
+}
+
+bool ExplainPrintout::OnPrintPage (int page)
+{
+    if (page > m_noPages)
+        return false;
+
+    wxDC *dc = GetDC();
+    if (!dc)
+        return false;
+    PrintScaling (dc);
+
+    int width = 0, height = 0;
+    m_explain->GetVirtualSize(&width, &height);
+
+    /*
+    * Create a temporary bitmap from the Explain window
+    */
+    if (!m_printBitmap)
+    {
+        wxMemoryDC memDC;
+        m_printBitmap = new wxBitmap(width, height);
+
+        memDC.SelectObject(*m_printBitmap);
+        memDC.Clear();
+
+        // Draw the diagram on the bitmap (Memory Device Context)
+        m_explain->GetDiagram()->Redraw(memDC);
+
+        memDC.SelectObject(wxNullBitmap);
+    }
+
+    int posX = 0, posY = 0;
+    int current_page = 1;
+
+    /*
+    * Calculate the starting cordinates (x, y) for the given page
+    */
+    while(current_page != page)
+    {
+        posX += m_pageRect.width;
+        if (posX >= width)
+        {
+            posY += m_pageRect.height;
+            posX = 0;    
+        }
+        current_page++;
+    };
+
+    /*
+    * Create the bitmap of the required size from the stored whole window bitmap
+    */
+    wxBitmap newBitmap = m_printBitmap->GetSubBitmap(wxRect(posX, posY,
+      posX + m_pageRect.width  >= width ? width - posX : m_pageRect.width,
+      posY + m_pageRect.height >= height ? height - posY : m_pageRect.height));
+
+    dc->DrawBitmap(newBitmap, m_pageRect.x, m_pageRect.y, true);
+
+    return true;
+}
+
+bool ExplainPrintout::OnBeginDocument (int startPage, int endPage)
+{
+    return wxPrintout::OnBeginDocument(startPage, endPage);
+}
+
+// Print Functions
+bool ExplainPrintout::HasPage (int page)
+{
+    if (page <= m_noPages)
+        return true;
+    return false;
+}
+
+void ExplainPrintout::GetPageInfo (int *minPage, int *maxPage, int *selPageFrom, int *selPageTo)
+{
+    // initialize values
+    *minPage = 0;
+    *maxPage = 0;
+    *selPageFrom = 0;
+    *selPageTo = 0;
+    
+    // scale DC if possible
+    wxDC *dc = GetDC();
+    if (!dc)
+        return;
+    PrintScaling (dc);
+    
+    m_pageRect = GetLogicalPageMarginsRect(*g_explainGQBPageSetupData);
+    
+    int width = 0, height = 0;
+    m_explain->GetVirtualSize(&width, &height);
+
+    m_noPages = 1;
+    int posX = 0, posY = 0;
+    while (true)
+    {
+        if (posX + m_pageRect.width  >= width &&
+            posY + m_pageRect.height >= height)
+            break;
+        posX += m_pageRect.width;
+        if (posX >= width)
+        {
+            posY += m_pageRect.height;
+            posX = 0;    
+        }    
+        m_noPages++;
+    };
+
+    *minPage = 1;
+    *maxPage = m_noPages;
+    *selPageFrom = 1;
+    *selPageTo = 1;
+}
+
+bool ExplainPrintout::PrintScaling (wxDC *dc)
+{
+    // check for dc, return if none
+    if (!dc)
+        return false;
+    
+    // get printer and screen sizing values
+    wxSize ppiScr;
+    GetPPIScreen (&ppiScr.x, &ppiScr.y);
+    if (ppiScr.x == 0) { // most possible guess 96 dpi
+        ppiScr.x = 96;
+        ppiScr.y = 96;
+    }
+    wxSize ppiPrt;
+    GetPPIPrinter (&ppiPrt.x, &ppiPrt.y);
+    if (ppiPrt.x == 0) { // scaling factor to 1
+        ppiPrt.x = ppiScr.x;
+        ppiPrt.y = ppiScr.y;
+    }
+    wxSize dcSize = dc->GetSize();
+    wxSize pageSize;
+    GetPageSizePixels (&pageSize.x, &pageSize.y);
+    
+    // set user scale
+    float scale_x = (float)(ppiPrt.x * dcSize.x) / (float)(ppiScr.x * pageSize.x);
+    float scale_y = (float)(ppiPrt.y * dcSize.y) / (float)(ppiScr.y * pageSize.y);
+    dc->SetUserScale (scale_x , scale_y);
+
+    return true;
+}
+
+#endif // wxUSE_PRINTING_ARCHITECTURE
+
+//////////////////////////////////////////////////////////////////////////
+//
+// pgAdmin III - PostgreSQL Tools
+// RCS-ID:      $Id: $
+// Copyright (C) 2002 - 2009, The pgAdmin Development Team
+// This software is released under the BSD Licence
+//
+// explainPrintout.cpp - Explain Printout class
+//
+//////////////////////////////////////////////////////////////////////////
+
+
+// wxWindows headers
+#include <wx/wx.h>
+
+// App headers
+#include "pgAdmin3.h"
+
+#include "ctl/explainCanvas.h"
+
+#if wxUSE_PRINTING_ARCHITECTURE
+
+//! global print data, to remember settings
+extern wxPrintData *g_explainGQBPrintData;
+extern wxPageSetupData *g_explainGQBPageSetupData;
+
+void ExplainCanvas::PrintPreview()
+{
+    wxPrintDialogData printDialogData(* g_explainGQBPrintData);
+    wxPrintPreview *preview = new wxPrintPreview(new ExplainPrintout(this), new ExplainPrintout(this), &printDialogData);
+    if (!preview->Ok())
+    {
+        delete preview;
+        wxMessageBox(_T("There was a problem previewing.\nPerhaps your current printer is not set correctly?"), _T("Previewing"), wxOK);
+        return;
+    }
+    
+    wxPreviewFrame *frame = new wxPreviewFrame(preview, this, _T("Print Preview - Explain"), wxDefaultPosition, wxSize(600, 650));
+    frame->Centre(wxBOTH);
+    frame->Initialize();
+    frame->Show();
+}
+
+void ExplainCanvas::Print()
+{
+    wxPrintDialogData printDialogData( *g_explainGQBPrintData);
+    wxPrinter printer(&printDialogData);
+    ExplainPrintout printout(this);
+    if (!printer.Print(this, &printout, true)) 
+    {
+        if (wxPrinter::GetLastError() == wxPRINTER_ERROR)
+        {
+            wxMessageBox (
+              _("There was a problem with printing.\nPerhaps your current printer is not correctly?"),
+              _("Printing"), wxOK);
+            return;
+        }
+    }
+    (*g_explainGQBPrintData) = printer.GetPrintDialogData().GetPrintData();
+
+}
+
+ExplainPrintout::ExplainPrintout (ExplainCanvas* explain, wxString title)
+: wxPrintout(title), m_printBitmap(NULL)
+{
+    m_explain = explain;
+}
+
+ExplainPrintout::~ExplainPrintout()
+{
+    m_explain = NULL;
+    if (m_printBitmap)
+    {
+        delete m_printBitmap;
+        m_printBitmap = NULL;
+    }
+}
+
+bool ExplainPrintout::OnPrintPage (int page)
+{
+    if (page > m_noPages)
+        return false;
+
+    wxDC *dc = GetDC();
+    if (!dc)
+        return false;
+    PrintScaling (dc);
+
+    int width = 0, height = 0;
+    m_explain->GetVirtualSize(&width, &height);
+
+    /*
+    * Create a temporary bitmap from the Explain window
+    */
+    if (!m_printBitmap)
+    {
+        wxMemoryDC memDC;
+        m_printBitmap = new wxBitmap(width, height);
+
+        memDC.SelectObject(*m_printBitmap);
+        memDC.Clear();
+
+        // Draw the diagram on the bitmap (Memory Device Context)
+        m_explain->GetDiagram()->Redraw(memDC);
+
+        memDC.SelectObject(wxNullBitmap);
+    }
+
+    int posX = 0, posY = 0;
+    int current_page = 1;
+
+    /*
+    * Calculate the starting cordinates (x, y) for the given page
+    */
+    while(current_page != page)
+    {
+        posX += m_pageRect.width;
+        if (posX >= width)
+        {
+            posY += m_pageRect.height;
+            posX = 0;    
+        }
+        current_page++;
+    };
+
+    /*
+    * Create the bitmap of the required size from the stored whole window bitmap
+    */
+    wxBitmap newBitmap = m_printBitmap->GetSubBitmap(wxRect(posX, posY,
+      posX + m_pageRect.width  >= width ? width - posX : m_pageRect.width,
+      posY + m_pageRect.height >= height ? height - posY : m_pageRect.height));
+
+    dc->DrawBitmap(newBitmap, m_pageRect.x, m_pageRect.y, true);
+
+    return true;
+}
+
+bool ExplainPrintout::OnBeginDocument (int startPage, int endPage)
+{
+    return wxPrintout::OnBeginDocument(startPage, endPage);
+}
+
+// Print Functions
+bool ExplainPrintout::HasPage (int page)
+{
+    if (page <= m_noPages)
+        return true;
+    return false;
+}
+
+void ExplainPrintout::GetPageInfo (int *minPage, int *maxPage, int *selPageFrom, int *selPageTo)
+{
+    // initialize values
+    *minPage = 0;
+    *maxPage = 0;
+    *selPageFrom = 0;
+    *selPageTo = 0;
+    
+    // scale DC if possible
+    wxDC *dc = GetDC();
+    if (!dc)
+        return;
+    PrintScaling (dc);
+    
+    m_pageRect = GetLogicalPageMarginsRect(*g_explainGQBPageSetupData);
+    
+    int width = 0, height = 0;
+    m_explain->GetVirtualSize(&width, &height);
+
+    m_noPages = 1;
+    int posX = 0, posY = 0;
+    while (true)
+    {
+        if (posX + m_pageRect.width  >= width &&
+            posY + m_pageRect.height >= height)
+            break;
+        posX += m_pageRect.width;
+        if (posX >= width)
+        {
+            posY += m_pageRect.height;
+            posX = 0;    
+        }    
+        m_noPages++;
+    };
+
+    *minPage = 1;
+    *maxPage = m_noPages;
+    *selPageFrom = 1;
+    *selPageTo = 1;
+}
+
+bool ExplainPrintout::PrintScaling (wxDC *dc)
+{
+    // check for dc, return if none
+    if (!dc)
+        return false;
+    
+    // get printer and screen sizing values
+    wxSize ppiScr;
+    GetPPIScreen (&ppiScr.x, &ppiScr.y);
+    if (ppiScr.x == 0) { // most possible guess 96 dpi
+        ppiScr.x = 96;
+        ppiScr.y = 96;
+    }
+    wxSize ppiPrt;
+    GetPPIPrinter (&ppiPrt.x, &ppiPrt.y);
+    if (ppiPrt.x == 0) { // scaling factor to 1
+        ppiPrt.x = ppiScr.x;
+        ppiPrt.y = ppiScr.y;
+    }
+    wxSize dcSize = dc->GetSize();
+    wxSize pageSize;
+    GetPageSizePixels (&pageSize.x, &pageSize.y);
+    
+    // set user scale
+    float scale_x = (float)(ppiPrt.x * dcSize.x) / (float)(ppiScr.x * pageSize.x);
+    float scale_y = (float)(ppiPrt.y * dcSize.y) / (float)(ppiScr.y * pageSize.y);
+    dc->SetUserScale (scale_x , scale_y);
+
+    return true;
+}
+
+#endif // wxUSE_PRINTING_ARCHITECTURE
+
Index: pgadmin/ctl/queryPrintout.cpp
===================================================================
--- pgadmin/ctl/queryPrintout.cpp	(revision 0)
+++ pgadmin/ctl/queryPrintout.cpp	(revision 0)
@@ -0,0 +1,597 @@
+//////////////////////////////////////////////////////////////////////////
+//
+// pgAdmin III - PostgreSQL Tools
+// RCS-ID:      $Id: $
+// Copyright (C) 2002 - 2009, The pgAdmin Development Team
+// This software is released under the BSD Licence
+//
+// queryPrintout.cpp - Query Editor Printout class
+//
+//////////////////////////////////////////////////////////////////////////
+
+
+// wxWindows headers
+#include <wx/wx.h>
+
+// App headers
+#include "pgAdmin3.h"
+
+#include "ctl/ctlSQLBox.h"
+
+#if wxUSE_PRINTING_ARCHITECTURE
+
+//! global print data, to remember settings
+extern wxPrintData *g_queryPrintData;
+extern wxPageSetupData *g_queryPageSetupData;
+
+void ctlSQLBox::PrintPreview()
+{
+    wxPrintDialogData printDialogData(*g_queryPrintData);
+    wxPrintPreview *preview = new wxPrintPreview(new QueryPrintout(this), new QueryPrintout(this), &printDialogData);
+    if (!preview->Ok())
+    {
+        delete preview;
+        wxMessageBox(_T("There was a problem previewing.\nPerhaps your current printer is not set correctly?"), _T("Previewing"), wxOK);
+        return;
+    }
+    
+    wxPreviewFrame *frame = new wxPreviewFrame(preview, this, _T("Print Preview - Query Editor"), wxDefaultPosition, wxSize(600, 650));
+    frame->Centre(wxBOTH);
+    frame->Initialize();
+    frame->Show();
+}
+
+void ctlSQLBox::Print()
+{
+    wxPrintDialogData printDialogData(*g_queryPrintData);
+    wxPrinter printer(&printDialogData);
+    QueryPrintout printout(this);
+    if (!printer.Print(this, &printout, true)) 
+    {
+        if (wxPrinter::GetLastError() == wxPRINTER_ERROR)
+        {
+            wxMessageBox (
+              _("There was a problem with printing.\nPerhaps your current printer is not correctly?"),
+              _("Printing"), wxOK);
+            return;
+        }
+    }
+    (*g_queryPrintData) = printer.GetPrintDialogData().GetPrintData();
+
+}
+
+//----------------------------------------------------------------------------
+// QueryPrintout
+//----------------------------------------------------------------------------
+
+QueryPrintout::QueryPrintout (ctlSQLBox *queryeditor, wxString title)
+: wxPrintout(title)
+{
+    m_queryEditor = queryeditor;
+    m_printed = 0;
+
+}
+
+bool QueryPrintout::OnPrintPage (int page)
+{
+
+    wxDC *dc = GetDC();
+    if (!dc) return false;
+
+    // scale DC
+    PrintScaling (dc);
+
+    // print page
+    if (page == 1) m_printed = 0;
+    m_printed = m_queryEditor->FormatRange (1, m_printed, m_queryEditor->GetLength(),
+                                     dc, dc, m_printRect, m_pageRect);
+
+    return true;
+}
+
+bool QueryPrintout::OnBeginDocument (int startPage, int endPage) {
+
+    if (!wxPrintout::OnBeginDocument (startPage, endPage)) {
+        return false;
+    }
+
+    return true;
+}
+
+void QueryPrintout::GetPageInfo (int *minPage, int *maxPage, int *selPageFrom, int *selPageTo) {
+
+    // initialize values
+    *minPage = 0;
+    *maxPage = 0;
+    *selPageFrom = 0;
+    *selPageTo = 0;
+
+    // scale DC if possible
+    wxDC *dc = GetDC();
+    if (!dc) return;
+    PrintScaling (dc);
+
+    // get print page informations and convert to printer pixels
+    wxSize ppiScr;
+    GetPPIScreen (&ppiScr.x, &ppiScr.y);
+    
+    wxSize page = g_queryPageSetupData->GetPaperSize();
+    page.x = static_cast<int> (page.x * ppiScr.x / 25.4);
+    page.y = static_cast<int> (page.y * ppiScr.y / 25.4);
+    m_pageRect = wxRect (0,
+                         0,
+                         page.x,
+                         page.y);
+
+    // get margins informations and convert to printer pixels
+    wxPoint pt = g_queryPageSetupData->GetMarginTopLeft();
+    int left = pt.x;
+    int top = pt.y;
+    pt = g_queryPageSetupData->GetMarginBottomRight();
+    int right = pt.x;
+    int bottom = pt.y;
+
+    top = static_cast<int> (top * ppiScr.y / 25.4);
+    bottom = static_cast<int> (bottom * ppiScr.y / 25.4);
+    left = static_cast<int> (left * ppiScr.x / 25.4);
+    right = static_cast<int> (right * ppiScr.x / 25.4);
+
+    m_printRect = wxRect (left,
+                          top,
+                          page.x - (left + right),
+                          page.y - (top + bottom));
+
+    // count pages
+    while (HasPage (*maxPage)) {
+        m_printed = m_queryEditor->FormatRange (0, m_printed, m_queryEditor->GetLength(),
+                                       dc, dc, m_printRect, m_pageRect);
+        *maxPage += 1;
+    }
+    if (*maxPage > 0) *minPage = 1;
+    *selPageFrom = *minPage;
+    *selPageTo = *maxPage;
+}
+
+bool QueryPrintout::HasPage (int WXUNUSED(page)) {
+
+    return (m_printed < m_queryEditor->GetLength());
+}
+
+bool QueryPrintout::PrintScaling (wxDC *dc){
+
+    // check for dc, return if none
+    if (!dc) return false;
+
+    // get printer and screen sizing values
+    wxSize ppiScr;
+    GetPPIScreen (&ppiScr.x, &ppiScr.y);
+    if (ppiScr.x == 0) { // most possible guess 96 dpi
+        ppiScr.x = 96;
+        ppiScr.y = 96;
+    }
+    wxSize ppiPrt;
+    GetPPIPrinter (&ppiPrt.x, &ppiPrt.y);
+    if (ppiPrt.x == 0) { // scaling factor to 1
+        ppiPrt.x = ppiScr.x;
+        ppiPrt.y = ppiScr.y;
+    }
+    wxSize dcSize = dc->GetSize();
+    wxSize pageSize;
+    GetPageSizePixels (&pageSize.x, &pageSize.y);
+
+    // set user scale
+    float scale_x = (float)(ppiPrt.x * dcSize.x) /
+                    (float)(ppiScr.x * pageSize.x);
+    float scale_y = (float)(ppiPrt.y * dcSize.y) /
+                    (float)(ppiScr.y * pageSize.y);
+    dc->SetUserScale (scale_x, scale_y);
+
+    return true;
+}
+
+
+QueryPrintout::~QueryPrintout()
+{
+    m_queryEditor = NULL;
+}
+
+#endif // wxUSE_PRINTING_ARCHITECTURE
+
+//////////////////////////////////////////////////////////////////////////
+//
+// pgAdmin III - PostgreSQL Tools
+// RCS-ID:      $Id: $
+// Copyright (C) 2002 - 2009, The pgAdmin Development Team
+// This software is released under the BSD Licence
+//
+// queryPrintout.cpp - Query Editor Printout class
+//
+//////////////////////////////////////////////////////////////////////////
+
+
+// wxWindows headers
+#include <wx/wx.h>
+
+// App headers
+#include "pgAdmin3.h"
+
+#include "ctl/ctlSQLBox.h"
+
+#if wxUSE_PRINTING_ARCHITECTURE
+
+//! global print data, to remember settings
+extern wxPrintData *g_queryPrintData;
+extern wxPageSetupData *g_queryPageSetupData;
+
+void ctlSQLBox::PrintPreview()
+{
+    wxPrintDialogData printDialogData(*g_queryPrintData);
+    wxPrintPreview *preview = new wxPrintPreview(new QueryPrintout(this), new QueryPrintout(this), &printDialogData);
+    if (!preview->Ok())
+    {
+        delete preview;
+        wxMessageBox(_T("There was a problem previewing.\nPerhaps your current printer is not set correctly?"), _T("Previewing"), wxOK);
+        return;
+    }
+    
+    wxPreviewFrame *frame = new wxPreviewFrame(preview, this, _T("Print Preview - Query Editor"), wxDefaultPosition, wxSize(600, 650));
+    frame->Centre(wxBOTH);
+    frame->Initialize();
+    frame->Show();
+}
+
+void ctlSQLBox::Print()
+{
+    wxPrintDialogData printDialogData(*g_queryPrintData);
+    wxPrinter printer(&printDialogData);
+    QueryPrintout printout(this);
+    if (!printer.Print(this, &printout, true)) 
+    {
+        if (wxPrinter::GetLastError() == wxPRINTER_ERROR)
+        {
+            wxMessageBox (
+              _("There was a problem with printing.\nPerhaps your current printer is not correctly?"),
+              _("Printing"), wxOK);
+            return;
+        }
+    }
+    (*g_queryPrintData) = printer.GetPrintDialogData().GetPrintData();
+
+}
+
+//----------------------------------------------------------------------------
+// QueryPrintout
+//----------------------------------------------------------------------------
+
+QueryPrintout::QueryPrintout (ctlSQLBox *queryeditor, wxString title)
+: wxPrintout(title)
+{
+    m_queryEditor = queryeditor;
+    m_printed = 0;
+
+}
+
+bool QueryPrintout::OnPrintPage (int page)
+{
+
+    wxDC *dc = GetDC();
+    if (!dc) return false;
+
+    // scale DC
+    PrintScaling (dc);
+
+    // print page
+    if (page == 1) m_printed = 0;
+    m_printed = m_queryEditor->FormatRange (1, m_printed, m_queryEditor->GetLength(),
+                                     dc, dc, m_printRect, m_pageRect);
+
+    return true;
+}
+
+bool QueryPrintout::OnBeginDocument (int startPage, int endPage) {
+
+    if (!wxPrintout::OnBeginDocument (startPage, endPage)) {
+        return false;
+    }
+
+    return true;
+}
+
+void QueryPrintout::GetPageInfo (int *minPage, int *maxPage, int *selPageFrom, int *selPageTo) {
+
+    // initialize values
+    *minPage = 0;
+    *maxPage = 0;
+    *selPageFrom = 0;
+    *selPageTo = 0;
+
+    // scale DC if possible
+    wxDC *dc = GetDC();
+    if (!dc) return;
+    PrintScaling (dc);
+
+    // get print page informations and convert to printer pixels
+    wxSize ppiScr;
+    GetPPIScreen (&ppiScr.x, &ppiScr.y);
+    
+    wxSize page = g_queryPageSetupData->GetPaperSize();
+    page.x = static_cast<int> (page.x * ppiScr.x / 25.4);
+    page.y = static_cast<int> (page.y * ppiScr.y / 25.4);
+    m_pageRect = wxRect (0,
+                         0,
+                         page.x,
+                         page.y);
+
+    // get margins informations and convert to printer pixels
+    wxPoint pt = g_queryPageSetupData->GetMarginTopLeft();
+    int left = pt.x;
+    int top = pt.y;
+    pt = g_queryPageSetupData->GetMarginBottomRight();
+    int right = pt.x;
+    int bottom = pt.y;
+
+    top = static_cast<int> (top * ppiScr.y / 25.4);
+    bottom = static_cast<int> (bottom * ppiScr.y / 25.4);
+    left = static_cast<int> (left * ppiScr.x / 25.4);
+    right = static_cast<int> (right * ppiScr.x / 25.4);
+
+    m_printRect = wxRect (left,
+                          top,
+                          page.x - (left + right),
+                          page.y - (top + bottom));
+
+    // count pages
+    while (HasPage (*maxPage)) {
+        m_printed = m_queryEditor->FormatRange (0, m_printed, m_queryEditor->GetLength(),
+                                       dc, dc, m_printRect, m_pageRect);
+        *maxPage += 1;
+    }
+    if (*maxPage > 0) *minPage = 1;
+    *selPageFrom = *minPage;
+    *selPageTo = *maxPage;
+}
+
+bool QueryPrintout::HasPage (int WXUNUSED(page)) {
+
+    return (m_printed < m_queryEditor->GetLength());
+}
+
+bool QueryPrintout::PrintScaling (wxDC *dc){
+
+    // check for dc, return if none
+    if (!dc) return false;
+
+    // get printer and screen sizing values
+    wxSize ppiScr;
+    GetPPIScreen (&ppiScr.x, &ppiScr.y);
+    if (ppiScr.x == 0) { // most possible guess 96 dpi
+        ppiScr.x = 96;
+        ppiScr.y = 96;
+    }
+    wxSize ppiPrt;
+    GetPPIPrinter (&ppiPrt.x, &ppiPrt.y);
+    if (ppiPrt.x == 0) { // scaling factor to 1
+        ppiPrt.x = ppiScr.x;
+        ppiPrt.y = ppiScr.y;
+    }
+    wxSize dcSize = dc->GetSize();
+    wxSize pageSize;
+    GetPageSizePixels (&pageSize.x, &pageSize.y);
+
+    // set user scale
+    float scale_x = (float)(ppiPrt.x * dcSize.x) /
+                    (float)(ppiScr.x * pageSize.x);
+    float scale_y = (float)(ppiPrt.y * dcSize.y) /
+                    (float)(ppiScr.y * pageSize.y);
+    dc->SetUserScale (scale_x, scale_y);
+
+    return true;
+}
+
+
+QueryPrintout::~QueryPrintout()
+{
+    m_queryEditor = NULL;
+}
+
+#endif // wxUSE_PRINTING_ARCHITECTURE
+
+//////////////////////////////////////////////////////////////////////////
+//
+// pgAdmin III - PostgreSQL Tools
+// RCS-ID:      $Id: $
+// Copyright (C) 2002 - 2009, The pgAdmin Development Team
+// This software is released under the BSD Licence
+//
+// queryPrintout.cpp - Query Editor Printout class
+//
+//////////////////////////////////////////////////////////////////////////
+
+
+// wxWindows headers
+#include <wx/wx.h>
+
+// App headers
+#include "pgAdmin3.h"
+
+#include "ctl/ctlSQLBox.h"
+
+#if wxUSE_PRINTING_ARCHITECTURE
+
+//! global print data, to remember settings
+extern wxPrintData *g_queryPrintData;
+extern wxPageSetupData *g_queryPageSetupData;
+
+void ctlSQLBox::PrintPreview()
+{
+    wxPrintDialogData printDialogData(*g_queryPrintData);
+    wxPrintPreview *preview = new wxPrintPreview(new QueryPrintout(this), new QueryPrintout(this), &printDialogData);
+    if (!preview->Ok())
+    {
+        delete preview;
+        wxMessageBox(_T("There was a problem previewing.\nPerhaps your current printer is not set correctly?"), _T("Previewing"), wxOK);
+        return;
+    }
+    
+    wxPreviewFrame *frame = new wxPreviewFrame(preview, this, _T("Print Preview - Query Editor"), wxDefaultPosition, wxSize(600, 650));
+    frame->Centre(wxBOTH);
+    frame->Initialize();
+    frame->Show();
+}
+
+void ctlSQLBox::Print()
+{
+    wxPrintDialogData printDialogData(*g_queryPrintData);
+    wxPrinter printer(&printDialogData);
+    QueryPrintout printout(this);
+    if (!printer.Print(this, &printout, true)) 
+    {
+        if (wxPrinter::GetLastError() == wxPRINTER_ERROR)
+        {
+            wxMessageBox (
+              _("There was a problem with printing.\nPerhaps your current printer is not correctly?"),
+              _("Printing"), wxOK);
+            return;
+        }
+    }
+    (*g_queryPrintData) = printer.GetPrintDialogData().GetPrintData();
+
+}
+
+//----------------------------------------------------------------------------
+// QueryPrintout
+//----------------------------------------------------------------------------
+
+QueryPrintout::QueryPrintout (ctlSQLBox *queryeditor, wxString title)
+: wxPrintout(title)
+{
+    m_queryEditor = queryeditor;
+    m_printed = 0;
+
+}
+
+bool QueryPrintout::OnPrintPage (int page)
+{
+
+    wxDC *dc = GetDC();
+    if (!dc) return false;
+
+    // scale DC
+    PrintScaling (dc);
+
+    // print page
+    if (page == 1) m_printed = 0;
+    m_printed = m_queryEditor->FormatRange (1, m_printed, m_queryEditor->GetLength(),
+                                     dc, dc, m_printRect, m_pageRect);
+
+    return true;
+}
+
+bool QueryPrintout::OnBeginDocument (int startPage, int endPage) {
+
+    if (!wxPrintout::OnBeginDocument (startPage, endPage)) {
+        return false;
+    }
+
+    return true;
+}
+
+void QueryPrintout::GetPageInfo (int *minPage, int *maxPage, int *selPageFrom, int *selPageTo) {
+
+    // initialize values
+    *minPage = 0;
+    *maxPage = 0;
+    *selPageFrom = 0;
+    *selPageTo = 0;
+
+    // scale DC if possible
+    wxDC *dc = GetDC();
+    if (!dc) return;
+    PrintScaling (dc);
+
+    // get print page informations and convert to printer pixels
+    wxSize ppiScr;
+    GetPPIScreen (&ppiScr.x, &ppiScr.y);
+    
+    wxSize page = g_queryPageSetupData->GetPaperSize();
+    page.x = static_cast<int> (page.x * ppiScr.x / 25.4);
+    page.y = static_cast<int> (page.y * ppiScr.y / 25.4);
+    m_pageRect = wxRect (0,
+                         0,
+                         page.x,
+                         page.y);
+
+    // get margins informations and convert to printer pixels
+    wxPoint pt = g_queryPageSetupData->GetMarginTopLeft();
+    int left = pt.x;
+    int top = pt.y;
+    pt = g_queryPageSetupData->GetMarginBottomRight();
+    int right = pt.x;
+    int bottom = pt.y;
+
+    top = static_cast<int> (top * ppiScr.y / 25.4);
+    bottom = static_cast<int> (bottom * ppiScr.y / 25.4);
+    left = static_cast<int> (left * ppiScr.x / 25.4);
+    right = static_cast<int> (right * ppiScr.x / 25.4);
+
+    m_printRect = wxRect (left,
+                          top,
+                          page.x - (left + right),
+                          page.y - (top + bottom));
+
+    // count pages
+    while (HasPage (*maxPage)) {
+        m_printed = m_queryEditor->FormatRange (0, m_printed, m_queryEditor->GetLength(),
+                                       dc, dc, m_printRect, m_pageRect);
+        *maxPage += 1;
+    }
+    if (*maxPage > 0) *minPage = 1;
+    *selPageFrom = *minPage;
+    *selPageTo = *maxPage;
+}
+
+bool QueryPrintout::HasPage (int WXUNUSED(page)) {
+
+    return (m_printed < m_queryEditor->GetLength());
+}
+
+bool QueryPrintout::PrintScaling (wxDC *dc){
+
+    // check for dc, return if none
+    if (!dc) return false;
+
+    // get printer and screen sizing values
+    wxSize ppiScr;
+    GetPPIScreen (&ppiScr.x, &ppiScr.y);
+    if (ppiScr.x == 0) { // most possible guess 96 dpi
+        ppiScr.x = 96;
+        ppiScr.y = 96;
+    }
+    wxSize ppiPrt;
+    GetPPIPrinter (&ppiPrt.x, &ppiPrt.y);
+    if (ppiPrt.x == 0) { // scaling factor to 1
+        ppiPrt.x = ppiScr.x;
+        ppiPrt.y = ppiScr.y;
+    }
+    wxSize dcSize = dc->GetSize();
+    wxSize pageSize;
+    GetPageSizePixels (&pageSize.x, &pageSize.y);
+
+    // set user scale
+    float scale_x = (float)(ppiPrt.x * dcSize.x) /
+                    (float)(ppiScr.x * pageSize.x);
+    float scale_y = (float)(ppiPrt.y * dcSize.y) /
+                    (float)(ppiScr.y * pageSize.y);
+    dc->SetUserScale (scale_x, scale_y);
+
+    return true;
+}
+
+
+QueryPrintout::~QueryPrintout()
+{
+    m_queryEditor = NULL;
+}
+
+#endif // wxUSE_PRINTING_ARCHITECTURE
+
Index: pgadmin/ctl/module.mk
===================================================================
--- pgadmin/ctl/module.mk	(revision 8080)
+++ pgadmin/ctl/module.mk	(working copy)
@@ -16,11 +16,13 @@
         $(srcdir)/ctl/ctlMenuToolbar.cpp \
         $(srcdir)/ctl/ctlSQLBox.cpp \
         $(srcdir)/ctl/ctlSQLGrid.cpp \
+        $(srcdir)/ctl/queryPrintout.cpp \
         $(srcdir)/ctl/ctlSQLResult.cpp \
         $(srcdir)/ctl/ctlSecurityPanel.cpp \
         $(srcdir)/ctl/ctlTree.cpp \
         $(srcdir)/ctl/explainCanvas.cpp \
         $(srcdir)/ctl/explainShape.cpp \
+        $(srcdir)/ctl/explainPrintout.cpp \
         $(srcdir)/ctl/timespin.cpp \
         $(srcdir)/ctl/xh_calb.cpp \
         $(srcdir)/ctl/xh_ctlcombo.cpp \
Index: pgadmin/ctl/explainCanvas.cpp
===================================================================
--- pgadmin/ctl/explainCanvas.cpp	(revision 8080)
+++ pgadmin/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)
+{
+    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, wxBITMAP_TYPE_BMP))
+    {
+        wxLogError(__("Could not write the file %s: Errcode=%d."), fileName.c_str(), wxSysErrorCode());
+    }
+}
+
 class ExplainText : public wxWindow
 {
 public:
Index: pgadmin/pgAdmin3.cpp
===================================================================
--- pgadmin/pgAdmin3.cpp	(revision 8080)
+++ pgadmin/pgAdmin3.cpp	(working copy)
@@ -110,6 +110,16 @@
 
 #define LANG_FILE   wxT("pgadmin3.lng")
 
+#if wxUSE_PRINTING_ARCHITECTURE
+
+//! global print data, to remember settings
+wxPrintData *g_explainGQBPrintData = NULL;
+wxPageSetupDialogData *g_explainGQBPageSetupData = NULL;
+wxPrintData *g_queryPrintData = NULL;
+wxPageSetupDialogData *g_queryPageSetupData = NULL;
+
+#endif // wxUSE_PRINTING_ARCHITECTURE
+
 IMPLEMENT_APP(pgAdmin3)
 
 #ifdef __WXGTK__
@@ -295,9 +305,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();
 
@@ -397,6 +408,26 @@
     wxSleep(2);
 #endif
 
+#if wxUSE_PRINTING_ARCHITECTURE
+    // initialize print data and setup
+    g_explainGQBPrintData = new wxPrintData;
+    g_explainGQBPrintData->SetPaperId(settings->GetExplainGQBPrinterPaperId());
+    g_explainGQBPrintData->SetOrientation(settings->GetExplainGQBPrinterOrientation());
+    g_explainGQBPageSetupData = new wxPageSetupDialogData;
+    g_explainGQBPageSetupData->SetMarginTopLeft(settings->GetExplainGQBPageMarginTopLeft());
+    g_explainGQBPageSetupData->SetMarginBottomRight(settings->GetExplainGQBPageMarginBottomRight());
+    g_explainGQBPageSetupData->SetPaperSize(settings->GetExplainGQBPaperSize());
+
+    g_queryPrintData = new wxPrintData;
+    g_queryPrintData->SetPaperId(settings->GetQueryPrinterPaperId());
+    g_queryPrintData->SetOrientation(settings->GetQueryPrinterOrientation());
+    g_queryPageSetupData = new wxPageSetupDialogData;
+    g_queryPageSetupData->SetMarginTopLeft(settings->GetQueryPageMarginTopLeft());
+    g_queryPageSetupData->SetMarginBottomRight(settings->GetQueryPageMarginBottomRight());
+    g_queryPageSetupData->SetPaperSize(settings->GetQueryPaperSize());
+#endif // wxUSE_PRINTING_ARCHITECTURE
+
+
     if (configMode)
     {
         if (configMode == frmConfig::ANYFILE && wxDir::Exists(configFile))
@@ -669,7 +700,32 @@
 
     // Delete the settings object to ensure settings are saved.
     delete settings;
+    
+#if wxUSE_PRINTING_ARCHITECTURE
+    // delete global print data and setup
+    if (g_explainGQBPrintData)
+    {
+        delete g_explainGQBPrintData;
+        g_explainGQBPrintData = NULL;
+    }
+    if (g_explainGQBPageSetupData) 
+    {
+        delete g_explainGQBPageSetupData;
+        g_explainGQBPageSetupData = NULL;
+    }
+    if (g_queryPrintData)
+    {
+        delete g_queryPrintData;
+        g_queryPrintData = NULL;
+    }
+    if (g_queryPageSetupData) 
+    {
+        delete g_queryPageSetupData;
+        g_queryPageSetupData = NULL;
+    }
+#endif // wxUSE_PRINTING_ARCHITECTURE
 
+
 #ifdef __WXMSW__
     WSACleanup();
 #endif
Index: pgadmin/include/ctl/explainCanvas.h
===================================================================
--- pgadmin/include/ctl/explainCanvas.h	(revision 8080)
+++ pgadmin/include/ctl/explainCanvas.h	(working copy)
@@ -14,6 +14,13 @@
 
 #include <wx/ogl/ogl.h>
 
+#if wxUSE_PRINTING_ARCHITECTURE
+#include "wx/print.h"
+#include "wx/printdlg.h"
+#ifdef __WXMAC__
+#include "wx/mac/printdlg.h"
+#endif
+#endif // wxUSE_PRINTING_ARCHITECTURE
 
 #if wxUSE_DEPRECATED
 #error wxUSE_DEPRECATED should be 0!
@@ -33,10 +40,15 @@
     void ShowPopup(ExplainShape *s);
     void SetExplainString(const wxString &str);
     void Clear();
+#if wxUSE_PRINTING_ARCHITECTURE
+    void PrintPreview();
+    void Print();
+#endif //wxUSE_PRINTING_ARCHITECTURE
+    void SaveAsImage(const wxString& fileName);
 
 private:
 
-    ExplainShape *rootShape, *lastShape;
+    ExplainShape *rootShape;
     ExplainPopup *popup;
 };
 
@@ -104,4 +116,34 @@
     DECLARE_EVENT_TABLE()
 };
 
+
+#if wxUSE_PRINTING_ARCHITECTURE
+//----------------------------------------------------------------------------
+// ExplainPrintout
+class ExplainPrintout : public wxPrintout {
+
+public:
+    // Constructor
+    ExplainPrintout (ExplainCanvas *explain, wxString title = _T(""));
+    ~ExplainPrintout ();
+    
+    //! Event Handlers
+    bool OnPrintPage (int page);
+    bool OnBeginDocument (int startPage, int endPage);
+    
+    // Print Functions
+    bool HasPage (int page);
+    void GetPageInfo (int *minPage, int *maxPage, int *selPageFrom, int *selPageTo);
+    
+private:
+    ExplainCanvas *m_explain;
+    int            m_noPages;
+    wxRect         m_pageRect;
+    wxBitmap      *m_printBitmap;
+    
+    bool PrintScaling (wxDC *dc);
+};
+#endif // wxUSE_PRINTING_ARCHITECTURE
+
+
 #endif
Index: pgadmin/include/ctl/ctlSQLBox.h
===================================================================
--- pgadmin/include/ctl/ctlSQLBox.h	(revision 8080)
+++ pgadmin/include/ctl/ctlSQLBox.h	(working copy)
@@ -17,6 +17,15 @@
 #include <wx/stc/stc.h>
 #include <wx/fdrepdlg.h>
 
+#if wxUSE_PRINTING_ARCHITECTURE
+#include "wx/print.h"
+#include "wx/printdlg.h"
+#ifdef __WXMAC__
+#include "wx/mac/printdlg.h"
+#endif
+#endif // wxUSE_PRINTING_ARCHITECTURE
+
+
 #include "db/pgConn.h"
 #include "dlg/dlgFindReplace.h"
 
@@ -58,6 +67,10 @@
     void SetAutoIndent(bool on) { m_autoIndent = on; }
     void EnableAutoComp(bool on) { m_autocompDisabled = on; }
     bool BlockComment(bool uncomment=false);
+#if wxUSE_PRINTING_ARCHITECTURE
+    void Print();
+    void PrintPreview();
+#endif // wxUSE_PRINTING_ARCHITECTURE
 
     CharacterRange RegexFindText(int minPos, int maxPos, const wxString& text);
 
@@ -71,7 +84,38 @@
     dlgFindReplace* m_dlgFindReplace;
 	pgConn *m_database;
     bool m_autoIndent, m_autocompDisabled;
+
+    friend class QueryPrintout;
 };
 
+#if wxUSE_PRINTING_ARCHITECTURE
+//----------------------------------------------------------------------------
+// QueryPrintout
+class QueryPrintout : public wxPrintout
+{
 
+public:
+    // Constructor
+    QueryPrintout (ctlSQLBox *queryeditor, wxString title = _(""));
+    ~QueryPrintout ();
+    
+    //! Event Handlers
+    bool OnPrintPage (int page);
+    bool OnBeginDocument (int startPage, int endPage);
+    
+    // Print Functions
+    bool HasPage (int page);
+    void GetPageInfo (int *minPage, int *maxPage, int *selPageFrom, int *selPageTo);
+    
+private:
+    ctlSQLBox     *m_queryEditor;
+    int m_printed;
+    wxRect m_pageRect;
+    wxRect m_printRect;
+    
+    bool PrintScaling (wxDC *dc);
+};
+#endif // wxUSE_PRINTING_ARCHITECTURE
+
 #endif
+
Index: pgadmin/include/frm/menu.h
===================================================================
--- pgadmin/include/frm/menu.h	(revision 8080)
+++ pgadmin/include/frm/menu.h	(working copy)
@@ -19,6 +19,18 @@
     MNU_ADDSERVER = 101,
     MNU_SAVEDEFINITION,
     MNU_EXIT,
+    MNU_PAGESETUP_QUERY,
+    MNU_PAGESETUP_EXPLAINGQB,
+    MNU_PAGEMARGINS_QUERY,
+    MNU_PAGEMARGINS_EXPLAINGQB,
+    MNU_PRINTPREVIEW_QUERY,
+    MNU_PRINTPREVIEW_GQB,
+    MNU_PRINTPREVIEW_EXPLAIN,
+    MNU_PRINT_QUERY,
+    MNU_PRINT_GQB,
+    MNU_PRINT_EXPLAIN,
+    MNU_SAVEAS_IMAGE_GQB,
+    MNU_SAVEAS_IMAGE_EXPLAIN,
     MNU_CONTEXTMENU,
     MNU_SQLPANE,
     MNU_OBJECTBROWSER,
Index: pgadmin/include/frm/frmQuery.h
===================================================================
--- pgadmin/include/frm/frmQuery.h	(revision 8080)
+++ pgadmin/include/frm/frmQuery.h	(working copy)
@@ -132,6 +132,15 @@
     void OnOpen(wxCommandEvent& event);
     void OnSave(wxCommandEvent& event);
     void OnSaveAs(wxCommandEvent& event);
+#ifdef wxUSE_PRINTING_ARCHITECTURE
+    void OnPageSetup(wxCommandEvent& ev);
+#ifdef __WXMAC__
+    void OnPageMargins(wxCommandEvent& ev);
+#endif
+    void OnPrintPreview(wxCommandEvent& ev);
+    void OnPrint(wxCommandEvent& ev);
+#endif //wxUSE_PRINTING_ARCHITECTURE
+    void SaveExplainAsImage(wxCommandEvent& event);
     void OnExport(wxCommandEvent& event);
     void OnExit(wxCommandEvent& event);
     void OnCut(wxCommandEvent& event);
Index: pgadmin/include/utils/sysSettings.h
===================================================================
--- pgadmin/include/utils/sysSettings.h	(revision 8080)
+++ pgadmin/include/utils/sysSettings.h	(working copy)
@@ -119,8 +119,31 @@
 	wxFont GetSQLFont();
     void SetSQLFont(const wxFont &font);
     int GetLineEndingType() const { int i; Read(wxT("LineEndingType"), &i, 2); return i; }
-	void SetLineEndingType(const int newval) { Write(wxT("LineEndingType"), newval); }
+    void SetLineEndingType(const int newval) { Write(wxT("LineEndingType"), newval); }
 
+    // Printer Support
+    wxPaperSize GetQueryPrinterPaperId() const { long l; l = Read(wxT("frmQuery/QueryPrinter/PaperId"), wxPAPER_A4); return (wxPaperSize)l; }
+    void SetQueryPrinterPaperId(wxPaperSize paperId) { Write(wxT("frmQuery/QueryPrinter/PaperId"), (long)paperId); }
+    long GetQueryPrinterOrientation() const { long l; l = Read(wxT("frmQuery/QueryPrinter/Orientation"), wxPORTRAIT); return l; }
+    void SetQueryPrinterOrientation(long orientation) { Write(wxT("frmQuery/QueryPrinter/Orientation"), orientation); }
+    void SetQueryPageMarginTopLeft(const wxPoint& topleft) { Write(wxT("frmQuery/QueryPrinter/Page/TopLeft"), topleft); } 
+    wxPoint GetQueryPageMarginTopLeft() const { wxPoint p; p = Read(wxT("frmQuery/QueryPrinter/Page/TopLeft"), wxPoint(10, 10)); return p; } 
+    wxPoint GetQueryPageMarginBottomRight () const { wxPoint p; p = Read(wxT("frmQuery/QueryPrinter/Page/BottomRight"), wxPoint(10, 10)); return p; } 
+    void SetQueryPageMarginBottomRight (const wxPoint& bottomright) { Write(wxT("frmQuery/QueryPrinter/Page/BottomRight"), bottomright); }
+    wxSize GetQueryPaperSize() const { wxSize s; s = Read(wxT("frmQuery/QueryPrinter/PaperSize"), wxSize(210, 297)); return s; }
+    void SetQueryPaperSize(const wxSize& size) { Write(wxT("frmQuery/QueryPrinter/PaperSize"), size); }
+
+    wxPaperSize GetExplainGQBPrinterPaperId() const { long l; l = Read(wxT("frmQuery/ExplaingGQBPrinter/PaperId"), wxPAPER_A4); return (wxPaperSize)l; }
+    void SetExplainGQBPrinterPaperId(wxPaperSize paperId) { Write(wxT("frmQuery/ExplaingGQBPrinter/PaperId"), (long)paperId); }
+    long GetExplainGQBPrinterOrientation() const { long l; l = Read(wxT("frmQuery/ExplaingGQBPrinter/Orientation"), wxLANDSCAPE); return l; }
+    void SetExplainGQBPrinterOrientation(long orientation) { Write(wxT("frmQuery/ExplaingGQBPrinter/Orientation"), orientation); }
+    void SetExplainGQBPageMarginTopLeft(const wxPoint& topleft) { Write(wxT("frmQuery/ExplaingGQBPrinter/Page/TopLeft"), topleft); } 
+    wxPoint GetExplainGQBPageMarginTopLeft() const { wxPoint p; p = Read(wxT("frmQuery/ExplaingGQBPrinter/Page/TopLeft"), wxPoint(5, 5)); return p; } 
+    wxPoint GetExplainGQBPageMarginBottomRight () const { wxPoint p; p = Read(wxT("frmQuery/ExplaingGQBPrinter/Page/BottomRight"), wxPoint(5, 5)); return p; } 
+    void SetExplainGQBPageMarginBottomRight (const wxPoint& bottomright) { Write(wxT("frmQuery/ExplaingGQBPrinter/Page/BottomRight"), bottomright); } 
+    wxSize GetExplainGQBPaperSize() const { wxSize s; s = Read(wxT("frmQuery/ExplainGQBPrinter/PaperSize"), wxSize(210, 297)); return s; }
+    void SetExplainGQBPaperSize(const wxSize& size) { Write(wxT("frmQuery/ExplainGQBPrinter/PaperSize"), size); }
+
     // Status Colours options
     wxString GetIdleProcessColour() const { wxString s; Read(wxT("IdleProcessColour"), &s, wxT("#5fa4d9")); return s; }
 	void SetIdleProcessColour(const wxString &newval) { Write(wxT("IdleProcessColour"), newval); }
Index: pgadmin/include/gqb/gqbEvents.h
===================================================================
--- pgadmin/include/gqb/gqbEvents.h	(revision 8080)
+++ pgadmin/include/gqb/gqbEvents.h	(working copy)
@@ -24,6 +24,7 @@
     GQB_RMJ_DELETE = 2000,
     GQB_RMJ_SETTYPE,
     GQB_RMT_DELETE,
-    GQB_RMT_SETALIAS
+    GQB_RMT_SETALIAS,
+    GQB_REFRESH
 };
 #endif
Index: pgadmin/include/gqb/gqbGraphSimple.h
===================================================================
--- pgadmin/include/gqb/gqbGraphSimple.h	(revision 8080)
+++ pgadmin/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: pgadmin/include/gqb/gqbViewController.h
===================================================================
--- pgadmin/include/gqb/gqbViewController.h	(revision 8080)
+++ pgadmin/include/gqb/gqbViewController.h	(working copy)
@@ -18,6 +18,23 @@
 #include <wx/dnd.h>
 #include <wx/dataobj.h>
 
+#if wxUSE_PRINTING_ARCHITECTURE
+#include "wx/print.h"
+#include "wx/printdlg.h"
+#ifdef __WXMAC__
+#include "wx/mac/printdlg.h"
+#endif
+ 
+#if wxUSE_LIBGNOMEPRINT
+#include "wx/html/forcelnk.h"
+FORCE_LINK(gnome_print)
+#endif
+#endif // wxUSE_PRINTING_ARCHITECTURE
+
+#define GQB_MIN_WIDTH  1280
+#define GQB_MIN_HEIGHT 800
+
+
 // App headers
 #include "gqb/gqbObject.h"
 #include "gqb/gqbModel.h"
@@ -106,7 +123,12 @@
 public:
     gqbView(wxWindow *gqbParent, wxNotebook *gridParent, wxSize size, gqbController *controller, gqbModel *model);
     ~gqbView();
-    void drawAll(wxBufferedDC& bdc);
+#if wxUSE_PRINTING_ARCHITECTURE
+    void PrintPreview();
+    void Print();
+#endif //wxUSE_PRINTING_ARCHITECTURE
+    void SaveAsImage(const wxString& path);
+    void drawAll(wxMemoryDC& bdc, bool adjustScrolling);
     void setPointerMode(pointerMode pm);
 
 	// Events for wxScrolledWindow
@@ -121,9 +143,11 @@
     wxPanel* getCriteriaPanel(){ return (wxPanel*)criteriaPanel; };
     wxPanel* getOrderPanel(){ return (wxPanel*)orderPanel; };
     wxPanel* getJoinsPanel() { return joinsPanel; }
+    const wxSize& getCanvasSize() { return canvasSize; }
     void newTableAdded(gqbQueryObject *item);
     bool clickOnJoin (gqbQueryJoin *join, wxPoint &pt, wxPoint &origin, wxPoint &dest);
     void updateTable(gqbQueryObject *table);
+    const wxSize& getModelSize() { return modelSize; }
 
 	// Functions for all gqb extra Panels (projection, criteria..)
     void emptyPanelsData();
@@ -144,6 +168,7 @@
                           
     gqbGridOrderTable *orderByLGridTable, *orderByRGridTable;	// Data model for order by grid internals
     wxSize canvasSize;
+    wxSize modelSize;
     bool changeTOpressed;
     
 	// just a point to the selected item on the collection, shouldn't be destroy inside this class
@@ -155,10 +180,13 @@
     pointerMode mode;             // pointer is used as normally or as in joins by example
     wxImage joinCursorImage;
     wxCursor joinCursor;
-    wxMenu *m_rightJoins, *m_rightTables;
+    wxMenu *m_rightJoins, *m_rightTables, *m_gqbPopup;
     void OnMenuJoinDelete(wxCommandEvent& event);
     void OnMenuTableDelete(wxCommandEvent& event);
     void OnMenuTableSetAlias(wxCommandEvent& event);
+    void OnRefresh(wxCommandEvent& ev);
+    void updateModelSize(gqbQueryObject* obj, bool updateAnyWay);
+
     wxArrayString joinTypeChoices;
     DECLARE_EVENT_TABLE()
 };
@@ -177,4 +205,34 @@
 private:
     gqbBrowser *tree;
 };
+
+#if wxUSE_PRINTING_ARCHITECTURE
+//----------------------------------------------------------------------------
+// GQBPrintout
+class GQBPrintout : public wxPrintout {
+
+public:
+
+    // Constructor
+    GQBPrintout (gqbView *view, wxString title = _T(""));
+    ~GQBPrintout ();
+
+    //! Event Handlers
+    bool OnPrintPage (int page);
+    bool OnBeginDocument (int startPage, int endPage);
+
+    // Print Functions
+    bool HasPage (int page);
+    void GetPageInfo (int *minPage, int *maxPage, int *selPageFrom, int *selPageTo);
+
+private:
+    gqbView  *m_view;
+    int       m_noPage;
+    wxRect    m_pageRect;
+    wxBitmap *m_printBitmap;
+
+    bool PrintScaling (wxDC *dc);
+};
+#endif // wxUSE_PRINTING_ARCHITECTURE
+
 #endif
Index: pgadmin/include/gqb/gqbGraphBehavior.h
===================================================================
--- pgadmin/include/gqb/gqbGraphBehavior.h	(revision 8080)
+++ pgadmin/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: pgadmin/frm/frmQuery.cpp
===================================================================
--- pgadmin/frm/frmQuery.cpp	(revision 8080)
+++ pgadmin/frm/frmQuery.cpp	(working copy)
@@ -23,6 +23,14 @@
 #include <wx/timer.h>
 #include <wx/aui/aui.h>
 
+#if wxUSE_PRINTING_ARCHITECTURE
+#include "wx/print.h"
+#include "wx/printdlg.h"
+#ifdef __WXMAC__
+#include "wx/mac/printdlg.h"
+#endif
+#endif // wxUSE_PRINTING_ARCHITECTURE
+
 // App headers
 #include "frm/frmMain.h"
 #include "frm/frmQuery.h"
@@ -95,6 +103,23 @@
 EVT_MENU(MNU_SAVE,              frmQuery::OnSave)
 EVT_MENU(MNU_SAVEAS,            frmQuery::OnSaveAs)
 EVT_MENU(MNU_EXPORT,            frmQuery::OnExport)
+#ifdef wxUSE_PRINTING_ARCHITECTURE
+EVT_MENU(MNU_PAGESETUP_EXPLAINGQB, frmQuery::OnPageSetup)
+#ifdef __WXMAC__
+EVT_MENU(MNU_PAGEMARGINS_EXPLAINGQB, frmQuery::OnPageMargins)
+#endif // __WXMAC__
+EVT_MENU(MNU_PRINTPREVIEW_GQB,     frmQuery::OnPrintPreview)
+EVT_MENU(MNU_PRINTPREVIEW_EXPLAIN, frmQuery::OnPrintPreview)
+#ifndef __WXMAC__
+EVT_MENU(MNU_PRINTPREVIEW_QUERY,   frmQuery::OnPrintPreview)
+EVT_MENU(MNU_PAGESETUP_QUERY,      frmQuery::OnPageSetup)
+EVT_MENU(MNU_PRINT_QUERY,          frmQuery::OnPrint)
+#endif
+EVT_MENU(MNU_PRINT_GQB,            frmQuery::OnPrint)
+EVT_MENU(MNU_PRINT_EXPLAIN,        frmQuery::OnPrint)
+#endif //wxUSE_PRINTING_ARCHITECTURE
+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)
@@ -211,6 +236,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);
@@ -231,6 +258,47 @@
     fileMenu->Append(MNU_EXPORT, _("&Export..."),  _("Export data to file"));
     fileMenu->Append(MNU_QUICKREPORT, _("&Quick report..."),  _("Run a quick report..."));
     fileMenu->AppendSeparator();
+#ifdef wxUSE_PRINTING_ARCHITECTURE
+    wxMenu *pageSetupMenu = new wxMenu();
+#ifndef __WXMAC__
+    pageSetupMenu->Append(MNU_PAGESETUP_QUERY,      _("Q&uery"),       _("Page setup for the Query Editor"));
+#endif
+    pageSetupMenu->Append(MNU_PAGESETUP_EXPLAINGQB, _("Exp&lain/GQB"), _("Page setup for the Explain & Graphical Query Builder"));
+
+#if __WXMAC__
+    wxMenu *pageMarginsMenu = new wxMenu();
+    pageMarginsMenu->Append(MNU_PAGEMARGINS_EXPLAINGQB, _("Exp&lain/GQB"), _("Page margins for the Explain & Graphical Query Builder"));
+#endif
+
+    wxMenu *printMenu = new wxMenu();
+#ifndef __WXMAC__
+    printMenu->Append(MNU_PRINT_QUERY,    _("&Query"),                   _("Take print out of Query..."));
+#endif
+    printMenu->Append(MNU_PRINT_GQB,      _("&Graphical Query Builder"), _("Take print out of Graphical Query Builder..."));
+    printMenu->Append(MNU_PRINT_EXPLAIN,  _("&Explain"),                 _("Take print out of Explain..."));
+
+    wxMenu *printPreviewMenu = new wxMenu();
+#ifndef __WXMAC__
+    printPreviewMenu->Append(MNU_PRINTPREVIEW_QUERY,   _("&Query"),                   _("Show the print preview for Query Editor..."));
+#endif
+    printPreviewMenu->Append(MNU_PRINTPREVIEW_GQB,     _("&Graphical Query Builder"), _("Show the print preview for Graphical Query Builder..."));
+    printPreviewMenu->Append(MNU_PRINTPREVIEW_EXPLAIN, _("&Explain"),                 _("Show the print preview for Explain..."));
+
+    fileMenu->Append(wxID_ANY, _("Pa&ge Setup"),    pageSetupMenu);
+#if __WXMAC__
+    fileMenu->Append(wxID_ANY, _("Page &Margins"),    pageMarginsMenu);
+#endif
+    fileMenu->Append(wxID_ANY, _("Print Pre&view"), printPreviewMenu);
+    fileMenu->Append(wxID_ANY, _("&Print"),         printMenu);
+
+    fileMenu->AppendSeparator();
+#endif //wxUSE_PRINTING_ARCHITECTURE
+    wxMenu *saveasImageMenu = new wxMenu();
+    saveasImageMenu->Append(MNU_SAVEAS_IMAGE_EXPLAIN, _("&Explain"), _("Save Explain as an image"));
+    saveasImageMenu->Append(MNU_SAVEAS_IMAGE_GQB,     _("&GQB"), _("Save Graphical Query Builder (GQB) as an image"));
+    fileMenu->Append(wxID_ANY, _("SaveAs &Image"), saveasImageMenu);
+    
+    fileMenu->AppendSeparator();
     fileMenu->Append(MNU_RECENT, _("&Recent files"), recentFileMenu);
     fileMenu->Append(MNU_EXIT, _("E&xit\tAlt-F4"), _("Exit query window"));
 
@@ -414,7 +482,7 @@
     // Graphical Canvas
     // initialize values
     model=new gqbModel();
-    controller = new gqbController(model,sqlNotebook, outputPane, wxSize(1280,800));
+    controller = new gqbController(model,sqlNotebook, outputPane, wxSize(GQB_MIN_WIDTH, GQB_MIN_HEIGHT));
     firstTime=true;                               // Inform to GQB that the tree of table haven't filled.
     gqbUpdateRunning = false;                      // Are we already updating the SQL query - event recursion protection.
     adjustSizesTimer=NULL;                        // Timer used to avoid a bug when close outputPane
@@ -1862,6 +1930,7 @@
     // Make sure this doesn't get call recursively through an event
     if (gqbUpdateRunning)
         return false;
+    updateMenu();
 
     gqbUpdateRunning = true;
 
@@ -2550,6 +2619,119 @@
     sqlQuery->BlockComment(true);
 }
 
+#ifdef wxUSE_PRINTING_ARCHITECTURE
+extern wxPrintData *g_explainGQBPrintData;
+extern wxPageSetupDialogData *g_explainGQBPageSetupData;
+extern wxPrintData *g_queryPrintData;
+extern wxPageSetupDialogData *g_queryPageSetupData;
+
+void frmQuery::OnPageSetup(wxCommandEvent& ev)
+{
+    if (ev.GetId() == MNU_PAGESETUP_QUERY)
+    {
+        (*g_queryPageSetupData) = * g_queryPrintData;
+        wxPageSetupDialog pageSetupDialog(this, g_queryPageSetupData);
+        pageSetupDialog.ShowModal();
+        (*g_queryPrintData) = pageSetupDialog.GetPageSetupData().GetPrintData();
+        (*g_queryPageSetupData) = pageSetupDialog.GetPageSetupData();
+
+        settings->SetQueryPrinterPaperId(g_queryPrintData->GetPaperId());
+        settings->SetQueryPrinterOrientation(g_queryPrintData->GetOrientation());
+        settings->SetQueryPageMarginTopLeft(g_queryPageSetupData->GetMarginTopLeft());
+        settings->SetQueryPageMarginBottomRight(g_queryPageSetupData->GetMarginBottomRight());
+        settings->SetQueryPaperSize(g_queryPageSetupData->GetPaperSize());
+    }
+    else if (ev.GetId() == MNU_PAGESETUP_EXPLAINGQB)
+    {
+        (*g_explainGQBPageSetupData) = * g_explainGQBPrintData;
+        wxPageSetupDialog pageSetupDialog(this, g_explainGQBPageSetupData);
+        pageSetupDialog.ShowModal();
+        (*g_explainGQBPrintData) = pageSetupDialog.GetPageSetupData().GetPrintData();
+        (*g_explainGQBPageSetupData) = pageSetupDialog.GetPageSetupData();
+
+        settings->SetExplainGQBPrinterPaperId(g_explainGQBPrintData->GetPaperId());
+        settings->SetExplainGQBPrinterOrientation(g_explainGQBPrintData->GetOrientation());
+        settings->SetExplainGQBPageMarginTopLeft(g_explainGQBPageSetupData->GetMarginTopLeft());
+        settings->SetExplainGQBPageMarginBottomRight(g_explainGQBPageSetupData->GetMarginBottomRight());
+        settings->SetExplainGQBPaperSize(g_explainGQBPageSetupData->GetPaperSize());
+    }
+}
+
+#ifdef __WXMAC__
+void frmQuery::OnPageMargins(wxCommandEvent& ev)
+{
+    if (ev.GetId() == MNU_PAGEMARGINS_QUERY)
+    {
+        (*g_queryPageSetupData) = *g_queryPrintData;
+    
+        wxMacPageMarginsDialog pageMarginsDialog(this, g_queryPageSetupData);
+        pageMarginsDialog.ShowModal();
+    
+        (*g_queryPrintData) = pageMarginsDialog.GetPageSetupDialogData().GetPrintData();
+        (*g_queryPageSetupData) = pageMarginsDialog.GetPageSetupDialogData();
+
+        settings->SetQueryPageMarginTopLeft(g_queryPageSetupData->GetMarginTopLeft());
+        settings->SetQueryPageMarginBottomRight(g_queryPageSetupData->GetMarginBottomRight());
+        settings->SetQueryPaperSize(g_queryPageSetupData->GetPaperSize());
+    }
+    else if (ev.GetId() == MNU_PAGEMARGINS_EXPLAINGQB)
+    {
+        (*g_explainGQBPageSetupData) = *g_explainGQBPrintData;
+    
+        wxMacPageMarginsDialog pageMarginsDialog(this, g_explainGQBPageSetupData);
+        pageMarginsDialog.ShowModal();
+    
+        (*g_explainGQBPrintData) = pageMarginsDialog.GetPageSetupDialogData().GetPrintData();
+        (*g_explainGQBPageSetupData) = pageMarginsDialog.GetPageSetupDialogData();
+
+        settings->SetExplainGQBPageMarginTopLeft(g_explainGQBPageSetupData->GetMarginTopLeft());
+        settings->SetExplainGQBPageMarginBottomRight(g_explainGQBPageSetupData->GetMarginBottomRight());
+        settings->SetExplainGQBPaperSize(g_explainGQBPageSetupData->GetPaperSize());
+    }
+}
+#endif // __WXMAC__
+
+void frmQuery::OnPrintPreview(wxCommandEvent& ev)
+{
+    if (ev.GetId() == MNU_PRINTPREVIEW_QUERY)
+        sqlQuery->PrintPreview();
+    else if (ev.GetId() == MNU_PRINTPREVIEW_GQB)
+        controller->getView()->PrintPreview();
+    else if (ev.GetId() == MNU_PRINTPREVIEW_EXPLAIN)
+        explainCanvas->PrintPreview();
+}
+
+void frmQuery::OnPrint(wxCommandEvent& ev)
+{
+    if (ev.GetId() == MNU_PRINT_QUERY)
+        sqlQuery->Print();
+    else if (ev.GetId() == MNU_PRINT_GQB)
+        controller->getView()->Print();
+    else if (ev.GetId() == MNU_PRINT_EXPLAIN)
+        explainCanvas->Print();
+}
+#endif // wxUSE_PRINTING_ARCHITECTURE
+
+void frmQuery::SaveExplainAsImage(wxCommandEvent& ev)
+{
+    wxFileDialog *dlg=new wxFileDialog(this, _("Save Explain As image file"), lastDir, lastFilename,
+           _("Bitmap files (*.bmp)|*.bmp"), wxFD_SAVE|wxFD_OVERWRITE_PROMPT);
+    if (dlg->ShowModal() == wxID_OK)
+    {
+        lastFilename=dlg->GetFilename();
+        lastDir = dlg->GetDirectory();
+        lastPath = dlg->GetPath();
+
+        if (!lastPath.Contains(wxT(".")))
+            lastPath += wxT(".bmp");
+
+        if (ev.GetId() == MNU_SAVEAS_IMAGE_GQB)
+            controller->getView()->SaveAsImage(lastPath);
+        else if (ev.GetId() == MNU_SAVEAS_IMAGE_EXPLAIN)
+            explainCanvas->SaveAsImage(lastPath);
+    }
+}
+
 ///////////////////////////////////////////////////////
 
 wxWindow *queryToolBaseFactory::StartDialogSql(frmMain *form, pgObject *obj, const wxString &sql)
Index: pgadmin/pgAdmin3.vcproj
===================================================================
--- pgadmin/pgAdmin3.vcproj	(revision 8080)
+++ pgadmin/pgAdmin3.vcproj	(working copy)
@@ -416,6 +416,14 @@
 				>
 			</File>
 			<File
+				RelativePath=".\ctl\explainPrintout.cpp"
+				>
+			</File>
+			<File
+				RelativePath=".\ctl\queryPrintout.cpp"
+				>
+			</File>
+			<File
 				RelativePath=".\ctl\explainShape.cpp"
 				>
 			</File>
@@ -3952,6 +3960,10 @@
 				>
 			</File>
 			<File
+				RelativePath=".\gqb\gqbPrintout.cpp"
+				>
+			</File>
+			<File
 				RelativePath=".\gqb\gqbViewPanels.cpp"
 				>
 			</File>
Index: pgadmin/gqb/gqbView.cpp
===================================================================
--- pgadmin/gqb/gqbView.cpp	(revision 8080)
+++ pgadmin/gqb/gqbView.cpp	(working copy)
@@ -47,6 +47,7 @@
 EVT_MENU(GQB_RMJ_DELETE,	gqbView::OnMenuJoinDelete)
 EVT_MENU(GQB_RMT_DELETE,	gqbView::OnMenuTableDelete)
 EVT_MENU(GQB_RMT_SETALIAS,	gqbView::OnMenuTableSetAlias)
+EVT_MENU(GQB_REFRESH,	    gqbView::OnRefresh)
 END_EVENT_TABLE()
 
 gqbView::gqbView(wxWindow *gqbParent, wxNotebook *gridParent, wxSize size, gqbController *controller, gqbModel *model)
@@ -72,6 +73,7 @@
     joinCursor= wxCursor(joinCursorImage);
     m_rightJoins=NULL;
     m_rightTables=NULL;
+    m_gqbPopup=NULL;
     jTempSelected=NULL;
     cTempSelected=NULL;
 
@@ -117,6 +119,9 @@
 
     if(m_rightJoins)
         delete m_rightJoins;
+    
+    if(m_gqbPopup)
+        delete m_gqbPopup;
 }
 
 
@@ -131,14 +136,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;
@@ -154,6 +159,8 @@
                 m_rightTables = new wxMenu;
                 m_rightTables->Append(GQB_RMT_SETALIAS, _("&Set Alias for table"));
                 m_rightTables->Append(GQB_RMT_DELETE, _("&Delete Table"));
+                m_rightTables->AppendSeparator();
+                m_rightTables->Append(GQB_REFRESH, _("&Refresh"));
             }
             cTempSelected=(gqbQueryObject *) (gqbObjectCollection *) anySelected;
             jTempSelected=NULL;
@@ -166,12 +173,23 @@
             {
                 m_rightJoins = new wxMenu;
                 m_rightJoins->Append(GQB_RMJ_DELETE, _("&Delete Join"));
+                m_rightJoins->AppendSeparator();
+                m_rightJoins->Append(GQB_REFRESH, _("&Refresh"));
             }
             cTempSelected=NULL;
             jTempSelected=(gqbQueryJoin *) anySelected;;
             PopupMenu(m_rightJoins, event.GetPosition());
         }
     }
+    else
+    {
+        if(!m_gqbPopup)
+        {
+            m_gqbPopup = new wxMenu;
+            m_gqbPopup->Append(GQB_REFRESH, _("&Refresh"));
+        }
+        PopupMenu(m_gqbPopup, event.GetPosition());
+    }
 }
 
 
@@ -481,8 +499,9 @@
                 {
                     this->Refresh();
                     refresh=1;
-                }else
-                refresh++;
+                }
+                else
+                    refresh++;
 
             }
         }
@@ -521,7 +540,7 @@
 }
 
 
-void gqbView::drawAll(wxBufferedDC& bdc)
+void gqbView::drawAll(wxMemoryDC& bdc, bool adjustScrolling)
 {
     bdc.Clear();
     if(!iterator)
@@ -537,8 +556,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
     }
 
@@ -557,11 +579,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;
@@ -575,8 +600,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);
     }
 }
@@ -645,3 +673,125 @@
     this->Refresh();
 }
 
+
+void gqbView::OnRefresh(wxCommandEvent& ev)
+{
+    updateModelSize(NULL, true);
+    this->Update();
+}
+
+
+/*
+*  updateModelSize
+*     - Update the model size.
+*     - Calculate the maximum width and maximum height of the model
+*  * When added a new table/view, the obj parameter must not be null,
+*    otherwise it should be null
+*  * When removed a table/view from model, the obj parameter must be null,
+*    and update parameter should be true, otherwise update parameter should
+*    be false (Dragging event)
+*/
+void gqbView::updateModelSize(gqbQueryObject* obj, bool updateAnyWay)
+{
+    static int callCount = 0;
+    callCount++;
+    if (!obj)
+    {
+        // Do not update model size, everytime it gets called
+        // Update the size once in 10 times
+        // Update the size only if update flag is true
+        if (callCount < 10 && !updateAnyWay)
+            return;
+        callCount = 0;
+        // Figure out the actual model size.
+        // Remove table
+        int w = 0, h = 0, maxW = 0, maxH = 0;
+        if(!iterator)
+            // Get an iterator for the objects (tables/views) in the model.
+            iterator = this->model->createQueryIterator();
+        else
+            iterator->ResetIterator();
+    
+        while (iterator->HasNext())
+        {
+            gqbQueryObject *tmp= (gqbQueryObject *)iterator->Next();;
+            w = tmp->position.x + tmp->getWidth();
+            h = tmp->position.y + tmp->getHeight();
+    
+            if (maxW < w)
+                maxW = w;
+            if (maxH < h)
+                maxH = h;
+        }
+ 
+        // Reset Model size
+        modelSize.Set(maxW, maxH);
+    }
+    else
+    {
+        int w = 0, h = 0;
+        w = obj->position.x + obj->getWidth();
+        h = obj->position.y + obj->getHeight();
+
+        if (w > modelSize.GetWidth())
+            modelSize.SetWidth(w);
+        if (h > modelSize.GetHeight())
+            modelSize.SetHeight(h);
+    }
+    bool updateView = false;
+
+    if ((modelSize.GetWidth() > GQB_MIN_WIDTH || canvasSize.GetWidth() > GQB_MIN_WIDTH) &&
+         modelSize.GetWidth() != canvasSize.GetWidth())
+    {
+        canvasSize.SetWidth((modelSize.GetWidth() > GQB_MIN_WIDTH ? modelSize.GetWidth() : GQB_MIN_WIDTH));
+        updateView = true;
+    }
+    if ((modelSize.GetHeight() > GQB_MIN_HEIGHT || canvasSize.GetHeight() > GQB_MIN_HEIGHT) &&
+         modelSize.GetHeight() != canvasSize.GetHeight())
+    {
+        canvasSize.SetHeight((modelSize.GetHeight() > GQB_MIN_HEIGHT ? modelSize.GetHeight() : GQB_MIN_HEIGHT));
+        updateView = true;
+    }
+
+    if (updateView)
+    {
+        SetVirtualSize(canvasSize);
+    }
+}
+
+void gqbView::SaveAsImage(const wxString& fileName)
+{
+
+    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, wxBITMAP_TYPE_BMP))
+    {
+        wxLogError(__("Could not write the file %s: Errcode=%d."), fileName.c_str(), wxSysErrorCode());
+    }
+}
+
+
+
Index: pgadmin/gqb/gqbGraphSimple.cpp
===================================================================
--- pgadmin/gqb/gqbGraphSimple.cpp	(revision 8080)
+++ pgadmin/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())
Index: pgadmin/gqb/module.mk
===================================================================
--- pgadmin/gqb/module.mk	(revision 8080)
+++ pgadmin/gqb/module.mk	(working copy)
@@ -20,7 +20,7 @@
 	$(srcdir)/gqb/gqbGridOrderTable.cpp \
 	$(srcdir)/gqb/gqbGridProjTable.cpp \
 	$(srcdir)/gqb/gqbGridRestTable.cpp \
-        $(srcdir)/gqb/gqbGridJoinTable.cpp \
+	$(srcdir)/gqb/gqbGridJoinTable.cpp \
 	$(srcdir)/gqb/gqbModel.cpp \
 	$(srcdir)/gqb/gqbObject.cpp \
 	$(srcdir)/gqb/gqbObjectCollection.cpp \
@@ -28,7 +28,8 @@
 	$(srcdir)/gqb/gqbSchema.cpp \
 	$(srcdir)/gqb/gqbTable.cpp \
 	$(srcdir)/gqb/gqbViewPanels.cpp \
-	$(srcdir)/gqb/gqbView.cpp
+	$(srcdir)/gqb/gqbView.cpp \
+	$(srcdir)/gqb/gqbPrintout.cpp
 
 EXTRA_DIST += \
     $(srcdir)/gqb/module.mk
Index: pgadmin/gqb/gqbController.cpp
===================================================================
--- pgadmin/gqb/gqbController.cpp	(revision 8080)
+++ pgadmin/gqb/gqbController.cpp	(working copy)
@@ -29,7 +29,7 @@
 
 wxWindowID CTL_NTBKPANELS = ::wxNewId();
 
-gqbController::gqbController(gqbModel *_model, wxWindow *gqbParent, wxNotebook *gridParent, wxSize size=wxSize(800,1280))
+gqbController::gqbController(gqbModel *_model, wxWindow *gqbParent, wxNotebook *gridParent, wxSize size=wxSize(GQB_MIN_WIDTH, GQB_MIN_HEIGHT))
 : wxObject()
 {
     pparent = gqbParent;
Index: pgadmin/gqb/gqbPrintout.cpp
===================================================================
--- pgadmin/gqb/gqbPrintout.cpp	(revision 0)
+++ pgadmin/gqb/gqbPrintout.cpp	(revision 0)
@@ -0,0 +1,722 @@
+//////////////////////////////////////////////////////////////////////////
+//
+// pgAdmin III - PostgreSQL Tools
+// RCS-ID:      $Id: $
+// Copyright (C) 2002 - 2009, The pgAdmin Development Team
+// This software is released under the BSD Licence
+//
+// gqbPrintout.cpp - Graphical Query Builder (GQB) Printout class
+//
+//////////////////////////////////////////////////////////////////////////
+
+
+// wxWindows headers
+#include <wx/wx.h>
+
+// App headers
+#include "pgAdmin3.h"
+
+#include "gqb/gqbViewController.h"
+
+#if wxUSE_PRINTING_ARCHITECTURE
+
+//! global print data, to remember settings
+extern wxPrintData *g_explainGQBPrintData;
+extern wxPageSetupData *g_explainGQBPageSetupData;
+
+void gqbView::Print()
+{
+    updateModelSize(NULL, true);
+    
+	if (modelSize.GetWidth() == 0 || modelSize.GetHeight() == 0)
+	{
+		wxMessageBox(_("Nothing to print/show print-preview."), _("Print"),
+			wxOK | wxICON_INFORMATION);
+		return;
+	}
+
+    wxPrintDialogData printDialogData(*g_explainGQBPrintData);
+    wxPrinter printer(&printDialogData);
+    GQBPrintout printout(this);
+    if (!printer.Print(this, &printout, true))
+    {
+        if (wxPrinter::GetLastError() == wxPRINTER_ERROR)
+        {
+            wxMessageBox(
+              _("There was a problem with printing.\nPerhaps your current printer is not correctly?"),
+              _("Printing"), wxOK);
+            return;
+        }
+    }
+    (*g_explainGQBPrintData) = printer.GetPrintDialogData().GetPrintData();
+}
+
+void gqbView::PrintPreview()
+{
+	updateModelSize(NULL, true);
+
+	if (modelSize.GetWidth() == 0 || modelSize.GetHeight() == 0)
+	{
+		wxMessageBox(_("Nothing to print/show print-preview."), _("Preview"),
+			wxOK | wxICON_INFORMATION);
+		return;
+	}
+    wxPrintDialogData printDialogData(* g_explainGQBPrintData);
+    wxPrintPreview *preview = new wxPrintPreview(new GQBPrintout(this), new GQBPrintout(this), &printDialogData);
+    if (!preview->Ok())
+    {
+        delete preview;
+        wxMessageBox(
+			_("There was a problem previewing.\nPerhaps your current printer is not set correctly?"),
+			_("Preview"),
+			wxOK | wxICON_ERROR);
+        return;
+    }
+    
+    wxPreviewFrame *frame = new wxPreviewFrame(preview, this, _T("Print Preview - Graphical Query Builder (GQB)"), wxDefaultPosition, wxSize(600, 650));
+    frame->Centre(wxBOTH);
+    frame->Initialize();
+    frame->Show();
+}
+
+// Constructor
+GQBPrintout::GQBPrintout (gqbView *view, wxString title)
+: wxPrintout(title)
+{
+    m_view = view;
+    m_printBitmap = NULL;
+}
+
+GQBPrintout::~GQBPrintout()
+{
+    m_view = NULL;
+    if (m_printBitmap)
+    {
+        delete m_printBitmap;
+        m_printBitmap = NULL;
+    }
+}
+
+//! Event Handlers
+bool GQBPrintout::OnPrintPage (int page)
+{
+    if (page > m_noPage)
+        return false;
+
+    wxDC *dc = GetDC();
+    if (!dc)
+        return false;
+    PrintScaling (dc);
+
+    wxMemoryDC memDC;
+    wxSize gqbCanvasSize(m_view->getModelSize());
+
+    if (!m_printBitmap)
+    {
+        m_printBitmap = 
+            new wxBitmap(gqbCanvasSize.GetWidth(), gqbCanvasSize.GetHeight());
+
+        memDC.SelectObject(*m_printBitmap);
+        memDC.SetBackground(*wxWHITE_BRUSH);
+        memDC.Clear();
+
+        m_view->drawAll(memDC, false);
+        memDC.SelectObject(wxNullBitmap);
+    }
+
+    int posX = 0, posY = 0;
+    int current_page = 1;
+
+    while(current_page != page)
+    {
+        posX += m_pageRect.width;
+        if (posX >= gqbCanvasSize.GetWidth())
+        {
+            posY += m_pageRect.height;
+            posX = 0;    
+        }
+        current_page++;
+    };
+
+    wxBitmap newBitmap
+      = m_printBitmap->GetSubBitmap(
+        wxRect( posX, posY,
+          posX + m_pageRect.width  >= gqbCanvasSize.GetWidth() ?
+            gqbCanvasSize.GetWidth() - posX : m_pageRect.width,
+          posY + m_pageRect.height >= gqbCanvasSize.GetHeight() ?
+            gqbCanvasSize.GetHeight() - posY : m_pageRect.height));
+
+    dc->DrawBitmap(newBitmap, m_pageRect.x, m_pageRect.y, true);
+
+    return true;
+}
+
+bool GQBPrintout::OnBeginDocument (int startPage, int endPage)
+{
+    return wxPrintout::OnBeginDocument(startPage, endPage);
+}
+
+// Print Functions
+bool GQBPrintout::HasPage (int page)
+{
+    if (page <= m_noPage)
+        return true;
+    return false;
+}
+
+
+void GQBPrintout::GetPageInfo (int *minPage, int *maxPage, int *selPageFrom, int *selPageTo)
+{
+    // initialize values
+    *minPage = 0;
+    *maxPage = 0;
+    *selPageFrom = 0;
+    *selPageTo = 0;
+    
+    // scale DC if possible
+    wxDC *dc = GetDC();
+    if (!dc)
+        return;
+    PrintScaling (dc);
+    
+    m_pageRect = GetLogicalPageMarginsRect(*g_explainGQBPageSetupData);
+    wxSize gqbCanvasSize(m_view->getModelSize());
+
+    m_noPage = 1;
+    int posX = 0, posY = 0;
+    while (true)
+    {
+        if (posX + m_pageRect.width  >= gqbCanvasSize.GetWidth() &&
+            posY + m_pageRect.height >= gqbCanvasSize.GetHeight())
+            break;
+        posX += m_pageRect.width;
+        if (posX >= gqbCanvasSize.GetWidth())
+        {
+            posY += m_pageRect.height;
+            posX = 0;    
+        }    
+        m_noPage++;
+    };
+
+    *minPage = 1;
+    *maxPage = m_noPage;
+    *selPageFrom = 1;
+    *selPageTo = 1;
+}
+
+bool GQBPrintout::PrintScaling (wxDC *dc)
+{
+    // check for dc, return if none
+    if (!dc)
+        return false;
+    
+    // get printer and screen sizing values
+    wxSize ppiScr;
+    GetPPIScreen (&ppiScr.x, &ppiScr.y);
+    if (ppiScr.x == 0) { // most possible guess 96 dpi
+        ppiScr.x = 96;
+        ppiScr.y = 96;
+    }
+    wxSize ppiPrt;
+    GetPPIPrinter (&ppiPrt.x, &ppiPrt.y);
+    if (ppiPrt.x == 0) { // scaling factor to 1
+        ppiPrt.x = ppiScr.x;
+        ppiPrt.y = ppiScr.y;
+    }
+    wxSize dcSize = dc->GetSize();
+    wxSize pageSize;
+    GetPageSizePixels (&pageSize.x, &pageSize.y);
+
+    // set user scale
+    float scale_x = (float)(ppiPrt.x * dcSize.x) / (float)(ppiScr.x * pageSize.x);
+    float scale_y = (float)(ppiPrt.y * dcSize.y) / (float)(ppiScr.y * pageSize.y);
+
+    dc->SetUserScale (scale_x , scale_y);
+
+    return true;
+}
+
+#endif // wxUSE_PRINTING_ARCHITECTURE
+
+
+//////////////////////////////////////////////////////////////////////////
+//
+// pgAdmin III - PostgreSQL Tools
+// RCS-ID:      $Id: $
+// Copyright (C) 2002 - 2009, The pgAdmin Development Team
+// This software is released under the BSD Licence
+//
+// gqbPrintout.cpp - Graphical Query Builder (GQB) Printout class
+//
+//////////////////////////////////////////////////////////////////////////
+
+
+// wxWindows headers
+#include <wx/wx.h>
+
+// App headers
+#include "pgAdmin3.h"
+
+#include "gqb/gqbViewController.h"
+
+#if wxUSE_PRINTING_ARCHITECTURE
+
+//! global print data, to remember settings
+extern wxPrintData *g_explainGQBPrintData;
+extern wxPageSetupData *g_explainGQBPageSetupData;
+
+void gqbView::Print()
+{
+    updateModelSize(NULL, true);
+    
+	if (modelSize.GetWidth() == 0 || modelSize.GetHeight() == 0)
+	{
+		wxMessageBox(_("Nothing to print/show print-preview."), _("Print"),
+			wxOK | wxICON_INFORMATION);
+		return;
+	}
+
+    wxPrintDialogData printDialogData(*g_explainGQBPrintData);
+    wxPrinter printer(&printDialogData);
+    GQBPrintout printout(this);
+    if (!printer.Print(this, &printout, true))
+    {
+        if (wxPrinter::GetLastError() == wxPRINTER_ERROR)
+        {
+            wxMessageBox(
+              _("There was a problem with printing.\nPerhaps your current printer is not correctly?"),
+              _("Printing"), wxOK);
+            return;
+        }
+    }
+    (*g_explainGQBPrintData) = printer.GetPrintDialogData().GetPrintData();
+}
+
+void gqbView::PrintPreview()
+{
+	updateModelSize(NULL, true);
+
+	if (modelSize.GetWidth() == 0 || modelSize.GetHeight() == 0)
+	{
+		wxMessageBox(_("Nothing to print/show print-preview."), _("Preview"),
+			wxOK | wxICON_INFORMATION);
+		return;
+	}
+    wxPrintDialogData printDialogData(* g_explainGQBPrintData);
+    wxPrintPreview *preview = new wxPrintPreview(new GQBPrintout(this), new GQBPrintout(this), &printDialogData);
+    if (!preview->Ok())
+    {
+        delete preview;
+        wxMessageBox(
+			_("There was a problem previewing.\nPerhaps your current printer is not set correctly?"),
+			_("Preview"),
+			wxOK | wxICON_ERROR);
+        return;
+    }
+    
+    wxPreviewFrame *frame = new wxPreviewFrame(preview, this, _T("Print Preview - Graphical Query Builder (GQB)"), wxDefaultPosition, wxSize(600, 650));
+    frame->Centre(wxBOTH);
+    frame->Initialize();
+    frame->Show();
+}
+
+// Constructor
+GQBPrintout::GQBPrintout (gqbView *view, wxString title)
+: wxPrintout(title)
+{
+    m_view = view;
+    m_printBitmap = NULL;
+}
+
+GQBPrintout::~GQBPrintout()
+{
+    m_view = NULL;
+    if (m_printBitmap)
+    {
+        delete m_printBitmap;
+        m_printBitmap = NULL;
+    }
+}
+
+//! Event Handlers
+bool GQBPrintout::OnPrintPage (int page)
+{
+    if (page > m_noPage)
+        return false;
+
+    wxDC *dc = GetDC();
+    if (!dc)
+        return false;
+    PrintScaling (dc);
+
+    wxMemoryDC memDC;
+    wxSize gqbCanvasSize(m_view->getModelSize());
+
+    if (!m_printBitmap)
+    {
+        m_printBitmap = 
+            new wxBitmap(gqbCanvasSize.GetWidth(), gqbCanvasSize.GetHeight());
+
+        memDC.SelectObject(*m_printBitmap);
+        memDC.SetBackground(*wxWHITE_BRUSH);
+        memDC.Clear();
+
+        m_view->drawAll(memDC, false);
+        memDC.SelectObject(wxNullBitmap);
+    }
+
+    int posX = 0, posY = 0;
+    int current_page = 1;
+
+    while(current_page != page)
+    {
+        posX += m_pageRect.width;
+        if (posX >= gqbCanvasSize.GetWidth())
+        {
+            posY += m_pageRect.height;
+            posX = 0;    
+        }
+        current_page++;
+    };
+
+    wxBitmap newBitmap
+      = m_printBitmap->GetSubBitmap(
+        wxRect( posX, posY,
+          posX + m_pageRect.width  >= gqbCanvasSize.GetWidth() ?
+            gqbCanvasSize.GetWidth() - posX : m_pageRect.width,
+          posY + m_pageRect.height >= gqbCanvasSize.GetHeight() ?
+            gqbCanvasSize.GetHeight() - posY : m_pageRect.height));
+
+    dc->DrawBitmap(newBitmap, m_pageRect.x, m_pageRect.y, true);
+
+    return true;
+}
+
+bool GQBPrintout::OnBeginDocument (int startPage, int endPage)
+{
+    return wxPrintout::OnBeginDocument(startPage, endPage);
+}
+
+// Print Functions
+bool GQBPrintout::HasPage (int page)
+{
+    if (page <= m_noPage)
+        return true;
+    return false;
+}
+
+
+void GQBPrintout::GetPageInfo (int *minPage, int *maxPage, int *selPageFrom, int *selPageTo)
+{
+    // initialize values
+    *minPage = 0;
+    *maxPage = 0;
+    *selPageFrom = 0;
+    *selPageTo = 0;
+    
+    // scale DC if possible
+    wxDC *dc = GetDC();
+    if (!dc)
+        return;
+    PrintScaling (dc);
+    
+    m_pageRect = GetLogicalPageMarginsRect(*g_explainGQBPageSetupData);
+    wxSize gqbCanvasSize(m_view->getModelSize());
+
+    m_noPage = 1;
+    int posX = 0, posY = 0;
+    while (true)
+    {
+        if (posX + m_pageRect.width  >= gqbCanvasSize.GetWidth() &&
+            posY + m_pageRect.height >= gqbCanvasSize.GetHeight())
+            break;
+        posX += m_pageRect.width;
+        if (posX >= gqbCanvasSize.GetWidth())
+        {
+            posY += m_pageRect.height;
+            posX = 0;    
+        }    
+        m_noPage++;
+    };
+
+    *minPage = 1;
+    *maxPage = m_noPage;
+    *selPageFrom = 1;
+    *selPageTo = 1;
+}
+
+bool GQBPrintout::PrintScaling (wxDC *dc)
+{
+    // check for dc, return if none
+    if (!dc)
+        return false;
+    
+    // get printer and screen sizing values
+    wxSize ppiScr;
+    GetPPIScreen (&ppiScr.x, &ppiScr.y);
+    if (ppiScr.x == 0) { // most possible guess 96 dpi
+        ppiScr.x = 96;
+        ppiScr.y = 96;
+    }
+    wxSize ppiPrt;
+    GetPPIPrinter (&ppiPrt.x, &ppiPrt.y);
+    if (ppiPrt.x == 0) { // scaling factor to 1
+        ppiPrt.x = ppiScr.x;
+        ppiPrt.y = ppiScr.y;
+    }
+    wxSize dcSize = dc->GetSize();
+    wxSize pageSize;
+    GetPageSizePixels (&pageSize.x, &pageSize.y);
+
+    // set user scale
+    float scale_x = (float)(ppiPrt.x * dcSize.x) / (float)(ppiScr.x * pageSize.x);
+    float scale_y = (float)(ppiPrt.y * dcSize.y) / (float)(ppiScr.y * pageSize.y);
+
+    dc->SetUserScale (scale_x , scale_y);
+
+    return true;
+}
+
+#endif // wxUSE_PRINTING_ARCHITECTURE
+
+
+//////////////////////////////////////////////////////////////////////////
+//
+// pgAdmin III - PostgreSQL Tools
+// RCS-ID:      $Id: $
+// Copyright (C) 2002 - 2009, The pgAdmin Development Team
+// This software is released under the BSD Licence
+//
+// gqbPrintout.cpp - Graphical Query Builder (GQB) Printout class
+//
+//////////////////////////////////////////////////////////////////////////
+
+
+// wxWindows headers
+#include <wx/wx.h>
+
+// App headers
+#include "pgAdmin3.h"
+
+#include "gqb/gqbViewController.h"
+
+#if wxUSE_PRINTING_ARCHITECTURE
+
+//! global print data, to remember settings
+extern wxPrintData *g_explainGQBPrintData;
+extern wxPageSetupData *g_explainGQBPageSetupData;
+
+void gqbView::Print()
+{
+    updateModelSize(NULL, true);
+    
+	if (modelSize.GetWidth() == 0 || modelSize.GetHeight() == 0)
+	{
+		wxMessageBox(_("Nothing to print/show print-preview."), _("Print"),
+			wxOK | wxICON_INFORMATION);
+		return;
+	}
+
+    wxPrintDialogData printDialogData(*g_explainGQBPrintData);
+    wxPrinter printer(&printDialogData);
+    GQBPrintout printout(this);
+    if (!printer.Print(this, &printout, true))
+    {
+        if (wxPrinter::GetLastError() == wxPRINTER_ERROR)
+        {
+            wxMessageBox(
+              _("There was a problem with printing.\nPerhaps your current printer is not correctly?"),
+              _("Printing"), wxOK);
+            return;
+        }
+    }
+    (*g_explainGQBPrintData) = printer.GetPrintDialogData().GetPrintData();
+}
+
+void gqbView::PrintPreview()
+{
+	updateModelSize(NULL, true);
+
+	if (modelSize.GetWidth() == 0 || modelSize.GetHeight() == 0)
+	{
+		wxMessageBox(_("Nothing to print/show print-preview."), _("Preview"),
+			wxOK | wxICON_INFORMATION);
+		return;
+	}
+    wxPrintDialogData printDialogData(* g_explainGQBPrintData);
+    wxPrintPreview *preview = new wxPrintPreview(new GQBPrintout(this), new GQBPrintout(this), &printDialogData);
+    if (!preview->Ok())
+    {
+        delete preview;
+        wxMessageBox(
+			_("There was a problem previewing.\nPerhaps your current printer is not set correctly?"),
+			_("Preview"),
+			wxOK | wxICON_ERROR);
+        return;
+    }
+    
+    wxPreviewFrame *frame = new wxPreviewFrame(preview, this, _T("Print Preview - Graphical Query Builder (GQB)"), wxDefaultPosition, wxSize(600, 650));
+    frame->Centre(wxBOTH);
+    frame->Initialize();
+    frame->Show();
+}
+
+// Constructor
+GQBPrintout::GQBPrintout (gqbView *view, wxString title)
+: wxPrintout(title)
+{
+    m_view = view;
+    m_printBitmap = NULL;
+}
+
+GQBPrintout::~GQBPrintout()
+{
+    m_view = NULL;
+    if (m_printBitmap)
+    {
+        delete m_printBitmap;
+        m_printBitmap = NULL;
+    }
+}
+
+//! Event Handlers
+bool GQBPrintout::OnPrintPage (int page)
+{
+    if (page > m_noPage)
+        return false;
+
+    wxDC *dc = GetDC();
+    if (!dc)
+        return false;
+    PrintScaling (dc);
+
+    wxMemoryDC memDC;
+    wxSize gqbCanvasSize(m_view->getModelSize());
+
+    if (!m_printBitmap)
+    {
+        m_printBitmap = 
+            new wxBitmap(gqbCanvasSize.GetWidth(), gqbCanvasSize.GetHeight());
+
+        memDC.SelectObject(*m_printBitmap);
+        memDC.SetBackground(*wxWHITE_BRUSH);
+        memDC.Clear();
+
+        m_view->drawAll(memDC, false);
+        memDC.SelectObject(wxNullBitmap);
+    }
+
+    int posX = 0, posY = 0;
+    int current_page = 1;
+
+    while(current_page != page)
+    {
+        posX += m_pageRect.width;
+        if (posX >= gqbCanvasSize.GetWidth())
+        {
+            posY += m_pageRect.height;
+            posX = 0;    
+        }
+        current_page++;
+    };
+
+    wxBitmap newBitmap
+      = m_printBitmap->GetSubBitmap(
+        wxRect( posX, posY,
+          posX + m_pageRect.width  >= gqbCanvasSize.GetWidth() ?
+            gqbCanvasSize.GetWidth() - posX : m_pageRect.width,
+          posY + m_pageRect.height >= gqbCanvasSize.GetHeight() ?
+            gqbCanvasSize.GetHeight() - posY : m_pageRect.height));
+
+    dc->DrawBitmap(newBitmap, m_pageRect.x, m_pageRect.y, true);
+
+    return true;
+}
+
+bool GQBPrintout::OnBeginDocument (int startPage, int endPage)
+{
+    return wxPrintout::OnBeginDocument(startPage, endPage);
+}
+
+// Print Functions
+bool GQBPrintout::HasPage (int page)
+{
+    if (page <= m_noPage)
+        return true;
+    return false;
+}
+
+
+void GQBPrintout::GetPageInfo (int *minPage, int *maxPage, int *selPageFrom, int *selPageTo)
+{
+    // initialize values
+    *minPage = 0;
+    *maxPage = 0;
+    *selPageFrom = 0;
+    *selPageTo = 0;
+    
+    // scale DC if possible
+    wxDC *dc = GetDC();
+    if (!dc)
+        return;
+    PrintScaling (dc);
+    
+    m_pageRect = GetLogicalPageMarginsRect(*g_explainGQBPageSetupData);
+    wxSize gqbCanvasSize(m_view->getModelSize());
+
+    m_noPage = 1;
+    int posX = 0, posY = 0;
+    while (true)
+    {
+        if (posX + m_pageRect.width  >= gqbCanvasSize.GetWidth() &&
+            posY + m_pageRect.height >= gqbCanvasSize.GetHeight())
+            break;
+        posX += m_pageRect.width;
+        if (posX >= gqbCanvasSize.GetWidth())
+        {
+            posY += m_pageRect.height;
+            posX = 0;    
+        }    
+        m_noPage++;
+    };
+
+    *minPage = 1;
+    *maxPage = m_noPage;
+    *selPageFrom = 1;
+    *selPageTo = 1;
+}
+
+bool GQBPrintout::PrintScaling (wxDC *dc)
+{
+    // check for dc, return if none
+    if (!dc)
+        return false;
+    
+    // get printer and screen sizing values
+    wxSize ppiScr;
+    GetPPIScreen (&ppiScr.x, &ppiScr.y);
+    if (ppiScr.x == 0) { // most possible guess 96 dpi
+        ppiScr.x = 96;
+        ppiScr.y = 96;
+    }
+    wxSize ppiPrt;
+    GetPPIPrinter (&ppiPrt.x, &ppiPrt.y);
+    if (ppiPrt.x == 0) { // scaling factor to 1
+        ppiPrt.x = ppiScr.x;
+        ppiPrt.y = ppiScr.y;
+    }
+    wxSize dcSize = dc->GetSize();
+    wxSize pageSize;
+    GetPageSizePixels (&pageSize.x, &pageSize.y);
+
+    // set user scale
+    float scale_x = (float)(ppiPrt.x * dcSize.x) / (float)(ppiScr.x * pageSize.x);
+    float scale_y = (float)(ppiPrt.y * dcSize.y) / (float)(ppiScr.y * pageSize.y);
+
+    dc->SetUserScale (scale_x , scale_y);
+
+    return true;
+}
+
+#endif // wxUSE_PRINTING_ARCHITECTURE
+
Index: xtra/wx-build/build-wxgtk
===================================================================
--- xtra/wx-build/build-wxgtk	(revision 8080)
+++ xtra/wx-build/build-wxgtk	(working copy)
@@ -13,7 +13,7 @@
 make clean
 cd ..
 make clean
-./configure --with-gtk --enable-gtk2 --enable-unicode --enable-mimetype=no --enable-shared --enable-debug
+./configure --with-gtk --enable-gtk2 --enable-unicode --enable-mimetype=no --enable-shared --enable-debug --enable-printarch --with-gnomeprint
 make all
 make install
 cd contrib
@@ -24,7 +24,7 @@
 make clean
 cd .. 
 make clean
-./configure --with-gtk --enable-gtk2 --enable-unicode --enable-mimetype=no --enable-shared --disable-debug
+./configure --with-gtk --enable-gtk2 --enable-unicode --enable-mimetype=no --enable-shared --disable-debug --enable-printarch --with-gnomeprint
 make all
 make install
 cd contrib
@@ -35,7 +35,7 @@
 make clean
 cd ..
 make clean
-./configure --with-gtk --enable-gtk2 --enable-unicode --enable-mimetype=no --disable-shared --enable-debug
+./configure --with-gtk --enable-gtk2 --enable-unicode --enable-mimetype=no --disable-shared --enable-debug --enable-printarch --with-gnomeprint
 make all
 make install
 cd contrib
@@ -46,7 +46,7 @@
 make clean
 cd ..
 make clean
-./configure --with-gtk --enable-gtk2 --enable-unicode --enable-mimetype=no --disable-shared --disable-debug
+./configure --with-gtk --enable-gtk2 --enable-unicode --enable-mimetype=no --disable-shared --disable-debug --enable-printarch --with-gnomeprint
 make all
 make install
 cd contrib
