////////////////////////////////////////////////////////////////////////// // // pgAdmin III - PostgreSQL Tools // // Copyright (C) 2002 - 2016, The pgAdmin Development Team // This software is released under the PostgreSQL Licence // // frmReport.cpp - The report file dialogue // ////////////////////////////////////////////////////////////////////////// // App headers #include "pgAdmin3.h" #include #include "frm/frmMain.h" #include "frm/frmReport.h" #include "utils/sysSettings.h" #include "utils/misc.h" #include "ctl/ctlListView.h" #include "schema/pgObject.h" #include "schema/pgCollection.h" #include "schema/pgServer.h" #include "schema/pgDatabase.h" #include "schema/pgSchema.h" #include "schema/pgTable.h" #include "schema/pgColumn.h" #include "schema/pgConstraints.h" #include "agent/pgaJob.h" #include "schema/pgForeignKey.h" #include "schema/pgIndexConstraint.h" #include "schema/pgCheck.h" // XML2/XSLT headers #include #include #define txtTitle CTRL_TEXT("txtTitle") #define txtNotes CTRL_TEXT("txtNotes") #define txtHtmlFile CTRL_TEXT("txtHtmlFile") #define txtXmlFile CTRL_TEXT("txtXmlFile") #define txtHtmlStylesheet CTRL_TEXT("txtHtmlStylesheet") #define txtXmlStylesheet CTRL_TEXT("txtXmlStylesheet") #define btnOK CTRL_BUTTON("wxID_OK") #define btnFile CTRL_BUTTON("btnFile") #define btnStylesheet CTRL_BUTTON("btnStylesheet") #define rbHtml CTRL_RADIOBUTTON("rbHtml") #define rbXml CTRL_RADIOBUTTON("rbXml") #define rbHtmlBuiltin CTRL_RADIOBUTTON("rbHtmlBuiltin") #define rbHtmlEmbed CTRL_RADIOBUTTON("rbHtmlEmbed") #define rbHtmlLink CTRL_RADIOBUTTON("rbHtmlLink") #define rbXmlPlain CTRL_RADIOBUTTON("rbXmlPlain") #define rbXmlLink CTRL_RADIOBUTTON("rbXmlLink") #define rbXmlProcess CTRL_RADIOBUTTON("rbXmlProcess") #define chkSql CTRL_CHECKBOX("chkSql") #define chkBrowser CTRL_CHECKBOX("chkBrowser") BEGIN_EVENT_TABLE(frmReport, pgDialog) EVT_RADIOBUTTON(XRCID("rbHtml"), frmReport::OnChange) EVT_RADIOBUTTON(XRCID("rbXml"), frmReport::OnChange) EVT_RADIOBUTTON(XRCID("rbHtmlBuiltin"), frmReport::OnChange) EVT_RADIOBUTTON(XRCID("rbHtmlEmbed"), frmReport::OnChange) EVT_RADIOBUTTON(XRCID("rbHtmlLink"), frmReport::OnChange) EVT_RADIOBUTTON(XRCID("rbXmlPlain"), frmReport::OnChange) EVT_RADIOBUTTON(XRCID("rbXmlLink"), frmReport::OnChange) EVT_RADIOBUTTON(XRCID("rbXmlProcess"), frmReport::OnChange) EVT_TEXT(XRCID("txtHtmlFile"), frmReport::OnChange) EVT_TEXT(XRCID("txtXmlFile"), frmReport::OnChange) EVT_TEXT(XRCID("txtHtmlStylesheet"), frmReport::OnChange) EVT_TEXT(XRCID("txtXmlStylesheet"), frmReport::OnChange) EVT_BUTTON(XRCID("btnFile"), frmReport::OnBrowseFile) EVT_BUTTON(XRCID("btnStylesheet"), frmReport::OnBrowseStylesheet) EVT_BUTTON(wxID_HELP, frmReport::OnHelp) EVT_BUTTON(wxID_OK, frmReport::OnOK) EVT_BUTTON(wxID_CANCEL, frmReport::OnCancel) END_EVENT_TABLE() frmReport::frmReport(wxWindow *p) { parent = p; header = wxT(""); SetFont(settings->GetSystemFont()); LoadResource(p, wxT("frmReport")); // Icon appearanceFactory->SetIcons(this); RestorePosition(); btnOK->Disable(); wxString val; bool bVal; // Output format settings->Read(wxT("Reports/ReportFormat"), &val, wxT("h")); if (val == wxT("x")) { rbHtml->SetValue(false); rbXml->SetValue(true); } else { rbHtml->SetValue(true); rbXml->SetValue(false); } // HTML Stylesheet settings->Read(wxT("Reports/HtmlStylesheetMode"), &val, wxT("b")); if (val == wxT("e")) { rbHtmlBuiltin->SetValue(false); rbHtmlEmbed->SetValue(true); rbHtmlLink->SetValue(false); } else if (val == wxT("l")) { rbHtmlBuiltin->SetValue(false); rbHtmlEmbed->SetValue(false); rbHtmlLink->SetValue(true); } else { rbHtmlBuiltin->SetValue(true); rbHtmlEmbed->SetValue(false); rbHtmlLink->SetValue(false); } // XML Stylesheet settings->Read(wxT("Reports/XmlStylesheetMode"), &val, wxT("p")); if (val == wxT("l")) { rbXmlPlain->SetValue(false); rbXmlLink->SetValue(true); rbXmlProcess->SetValue(false); } else if (val == wxT("r")) { rbXmlPlain->SetValue(false); rbXmlLink->SetValue(false); rbXmlProcess->SetValue(true); } else { rbXmlPlain->SetValue(true); rbXmlLink->SetValue(false); rbXmlProcess->SetValue(false); } // Default values settings->Read(wxT("Reports/LastNotes"), &val, wxT("")); txtNotes->SetValue(val); settings->Read(wxT("Reports/LastHtmlStylesheet"), &val, wxEmptyString); txtHtmlStylesheet->SetValue(val); settings->Read(wxT("Reports/LastXmlStylesheet"), &val, wxEmptyString); txtXmlStylesheet->SetValue(val); settings->Read(wxT("Reports/LastHtmlFile"), &val, wxEmptyString); txtHtmlFile->SetValue(val); settings->Read(wxT("Reports/LastXmlFile"), &val, wxEmptyString); txtXmlFile->SetValue(val); settings->Read(wxT("Reports/IncludeSQL"), &bVal, true); chkSql->SetValue(bVal); chkSql->Disable(); settings->Read(wxT("Reports/OpenInBrowser"), &bVal, true); chkBrowser->SetValue(bVal); wxCommandEvent ev; OnChange(ev); txtTitle->SetFocus(); } frmReport::~frmReport() { SavePosition(); } void frmReport::OnHelp(wxCommandEvent &ev) { DisplayHelp(wxT("reports"), HELP_PGADMIN); } void frmReport::OnChange(wxCommandEvent &ev) { bool enable = true; if (rbHtml->GetValue()) { // Show/hide the appropriate controls rbHtmlBuiltin->Show(true); rbHtmlEmbed->Show(true); rbHtmlLink->Show(true); txtHtmlStylesheet->Show(true); txtHtmlFile->Show(true); rbXmlPlain->Show(false); rbXmlLink->Show(false); rbXmlProcess->Show(false); txtXmlStylesheet->Show(false); txtXmlFile->Show(false); // Enable/disable as appropriate if (txtHtmlFile->GetValue().IsEmpty()) enable = false; if (rbHtmlBuiltin->GetValue()) { txtHtmlStylesheet->Disable(); btnStylesheet->Disable(); } else { txtHtmlStylesheet->Enable(); btnStylesheet->Enable(); } if (rbHtmlEmbed->GetValue()) { if (!wxFile::Exists(txtHtmlStylesheet->GetValue())) enable = false; } } else { // Show/hide the appropriate controls rbHtmlBuiltin->Show(false); rbHtmlEmbed->Show(false); rbHtmlLink->Show(false); txtHtmlStylesheet->Show(false); txtHtmlFile->Show(false); rbXmlPlain->Show(true); rbXmlLink->Show(true); rbXmlProcess->Show(true); txtXmlStylesheet->Show(true); txtXmlFile->Show(true); // Enable/disable as appropriate if (txtXmlFile->GetValue().IsEmpty()) enable = false; if (rbXmlPlain->GetValue()) { txtXmlStylesheet->Disable(); btnStylesheet->Disable(); } else { txtXmlStylesheet->Enable(); btnStylesheet->Enable(); } if (rbXmlProcess->GetValue()) { if (!wxFile::Exists(txtXmlStylesheet->GetValue())) enable = false; } } btnOK->Enable(enable); } void frmReport::OnOK(wxCommandEvent &ev) { wxString filename; if (rbHtml->GetValue()) filename = txtHtmlFile->GetValue(); else filename = txtXmlFile->GetValue(); wxFileName fn(filename); fn.MakeAbsolute(); // Check if the file exsits, and if so, whether to overwrite it if (wxFileExists(fn.GetFullPath())) { wxString msg; msg.Printf(_("The file: \n\n%s\n\nalready exists. Do you want to overwrite it?"), fn.GetFullPath().c_str()); if (wxMessageBox(msg, _("Overwrite file?"), wxYES_NO | wxICON_QUESTION) != wxYES) { if (rbHtml->GetValue()) txtHtmlFile->SetFocus(); else txtXmlFile->SetFocus(); return; } } // Yield, to allow the messagebox to go wxTheApp->Yield(true); // Add the title, notes and SQL if (txtTitle->GetValue() != wxT("")) XmlAddHeaderValue(wxT("title"), txtTitle->GetValue()); if (txtNotes->GetValue() != wxT("")) XmlAddHeaderValue(wxT("notes"), txtNotes->GetValue()); // Generate the report data wxString report; if (rbHtml->GetValue()) { if (rbHtmlBuiltin->GetValue()) { wxString xml = GetXmlReport(wxEmptyString); wxString xsl = GetDefaultXsl(GetEmbeddedCss(GetDefaultCss())); report = XslProcessReport(xml, xsl); } else if (rbHtmlEmbed->GetValue()) { wxString xml = GetXmlReport(wxEmptyString); wxString css = FileRead(txtHtmlStylesheet->GetValue()); if (css.IsEmpty()) { wxLogError(_("No stylesheet data could be read from the file %s: Errcode=%d."), txtHtmlStylesheet->GetValue().c_str(), wxSysErrorCode()); return; } wxString xsl = GetDefaultXsl(GetEmbeddedCss(css)); report = XslProcessReport(xml, xsl); } else { wxString xml = GetXmlReport(wxEmptyString); wxString xsl = GetDefaultXsl(GetCssLink(txtHtmlStylesheet->GetValue())); report = XslProcessReport(xml, xsl); } } else { if (rbXmlPlain->GetValue()) { report = GetXmlReport(wxEmptyString); } else if (rbXmlLink->GetValue()) { report = GetXmlReport(txtXmlStylesheet->GetValue()); } else { wxString xml = GetXmlReport(wxEmptyString); wxString xsl = FileRead(txtXmlStylesheet->GetValue()); if (xsl.IsEmpty()) { wxLogError(_("No stylesheet data could be read from the file %s: Errcode=%d."), txtXmlStylesheet->GetValue().c_str(), wxSysErrorCode()); return; } report = XslProcessReport(xml, xsl); } } // If report is empty, an error must have occurred if (report.IsEmpty()) return; // Save it to disk wxFile file(fn.GetFullPath(), wxFile::write); if (!file.IsOpened()) { wxLogError(_("Failed to open file %s."), fn.GetFullPath().c_str()); return; } file.Write(report, wxConvUTF8); file.Close(); // Open the file in the default browser if required if (chkBrowser->GetValue()) #ifdef __WXMSW__ wxLaunchDefaultBrowser(fn.GetFullPath()); #else wxLaunchDefaultBrowser(wxT("file://") + fn.GetFullPath()); #endif // Save the settings for next time round settings->Write(wxT("Reports/LastNotes"), txtNotes->GetValue()); if (rbHtml->GetValue()) settings->Write(wxT("Reports/ReportFormat"), wxT("h")); else settings->Write(wxT("Reports/ReportFormat"), wxT("x")); if (rbHtmlBuiltin->GetValue()) settings->Write(wxT("Reports/HtmlStylesheetMode"), wxT("b")); else if (rbHtmlEmbed->GetValue()) settings->Write(wxT("Reports/HtmlStylesheetMode"), wxT("e")); else settings->Write(wxT("Reports/HtmlStylesheetMode"), wxT("l")); if (rbXmlPlain->GetValue()) settings->Write(wxT("Reports/XmlStylesheetMode"), wxT("p")); else if (rbXmlLink->GetValue()) settings->Write(wxT("Reports/XmlStylesheetMode"), wxT("l")); else settings->Write(wxT("Reports/XmlStylesheetMode"), wxT("r")); settings->Write(wxT("Reports/LastHtmlStylesheet"), txtHtmlStylesheet->GetValue()); settings->Write(wxT("Reports/LastXmlStylesheet"), txtXmlStylesheet->GetValue()); settings->Write(wxT("Reports/LastHtmlFile"), txtHtmlFile->GetValue()); settings->Write(wxT("Reports/LastXmlFile"), txtXmlFile->GetValue()); settings->WriteBool(wxT("Reports/IncludeSQL"), chkSql->GetValue()); settings->WriteBool(wxT("Reports/OpenInBrowser"), chkBrowser->GetValue()); // Now go away if (IsModal()) EndModal(wxID_OK); else Destroy(); } void frmReport::OnCancel(wxCommandEvent &ev) { if (IsModal()) EndModal(wxID_CANCEL); else Destroy(); } void frmReport::OnBrowseStylesheet(wxCommandEvent &ev) { if (rbHtml->GetValue()) { wxString def = txtHtmlStylesheet->GetValue(); if (!wxFile::Exists(def)) def.Empty(); #ifdef __WXMSW__ wxFileDialog file(this, _("Select stylesheet filename"), wxGetHomeDir(), def, _("HTML Stylesheet files (*.css)|*.css|All files (*.*)|*.*"), wxFD_OPEN); #else wxFileDialog file(this, _("Select stylesheet filename"), wxGetHomeDir(), def, _("HTML Stylesheet files (*.css)|*.css|All files (*)|*"), wxFD_OPEN); #endif if (file.ShowModal() == wxID_OK) { txtHtmlStylesheet->SetValue(file.GetPath()); OnChange(ev); } } else { wxString def = txtXmlStylesheet->GetValue(); if (!wxFile::Exists(def)) def.Empty(); #ifdef __WXMSW__ wxFileDialog file(this, _("Select stylesheet filename"), wxGetHomeDir(), def, _("XML Stylesheet files (*.xsl)|*.xsl|All files (*.*)|*.*"), wxFD_OPEN); #else wxFileDialog file(this, _("Select stylesheet filename"), wxGetHomeDir(), def, _("XML Stylesheet files (*.xsl)|*.xsl|All files (*)|*"), wxFD_OPEN); #endif if (file.ShowModal() == wxID_OK) { txtXmlStylesheet->SetValue(file.GetPath()); OnChange(ev); } } } void frmReport::OnBrowseFile(wxCommandEvent &ev) { if (rbHtml->GetValue()) { #ifdef __WXMSW__ wxFileDialog file(this, _("Select output filename"), wxGetHomeDir(), txtHtmlFile->GetValue(), _("HTML files (*.html)|*.html|All files (*.*)|*.*"), wxFD_SAVE | wxFD_OVERWRITE_PROMPT); #else wxFileDialog file(this, _("Select output filename"), wxGetHomeDir(), txtHtmlFile->GetValue(), _("HTML files (*.html)|*.html|All files (*)|*"), wxFD_SAVE | wxFD_OVERWRITE_PROMPT); #endif if (file.ShowModal() == wxID_OK) { txtHtmlFile->SetValue(file.GetPath()); OnChange(ev); } } else { #ifdef __WXMSW__ wxFileDialog file(this, _("Select output filename"), wxGetHomeDir(), txtXmlFile->GetValue(), _("XML files (*.xml)|*.xml|All files (*.*)|*.*"), wxFD_SAVE | wxFD_OVERWRITE_PROMPT); #else wxFileDialog file(this, _("Select output filename"), wxGetHomeDir(), txtXmlFile->GetValue(), _("XML files (*.xml)|*.xml|All files (*)|*"), wxFD_SAVE | wxFD_OVERWRITE_PROMPT); #endif if (file.ShowModal() == wxID_OK) { txtXmlFile->SetValue(file.GetPath()); OnChange(ev); } } } void frmReport::SetReportTitle(const wxString &t) { txtTitle->SetValue(t); } ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // START STYLESHEET FUNCTIONS ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// wxString frmReport::GetCssLink(const wxString &file) { wxString data; data = wxT(" \n"); return data; } wxString frmReport::GetEmbeddedCss(const wxString &css) { wxString data; data = wxT(" \n"); return data; } const wxString frmReport::GetDefaultCss() { wxString data; data = wxT(" body { font-family: verdana, helvetica, sans-serif; margin: 0px; padding: 0; }\n") wxT(" h1 { font-weight: bold; font-size: 150%; border-bottom-style: solid; border-bottom-width: 2px; margin-top: 0px; padding-bottom: 0.5ex; color: #eeeeee; overflow: hidden; text-overflow: ellipsis; }\n") wxT(" h2 { font-size: 130%; padding-bottom: 0.5ex; color: ") + appearanceFactory->GetReportKeyColour().GetAsString(wxC2S_HTML_SYNTAX) + wxT("; border-bottom-style: solid; border-bottom-width: 2px; }\n") wxT(" h3 { font-size: 110%; padding-bottom: 0.5ex; color: #000000; }\n") wxT(" th { text-align: left; background-color: ") + appearanceFactory->GetReportKeyColour().GetAsString(wxC2S_HTML_SYNTAX) + wxT("; color: #eeeeee; }\n") wxT(" #ReportHeader { padding: 10px; background-color: ") + appearanceFactory->GetReportKeyColour().GetAsString(wxC2S_HTML_SYNTAX) + wxT("; color: #eeeeee; border-bottom-style: solid; border-bottom-width: 2px; border-color: #999999; }\n") wxT(" #ReportHeader th { width: 25%; white-space: nowrap; vertical-align: top; }\n") wxT(" #ReportHeader td { vertical-align: top; color: #eeeeee; }\n") wxT(" #ReportNotes { padding: 10px; background-color: #eeeeee; font-size: 80%; border-bottom-style: solid; border-bottom-width: 2px; border-color: #999999; }\n") wxT(" .ReportSQL { margin-bottom: 10px; padding: 10px; display: block; background-color: #eeeeee; font-family: monospace; }\n") wxT(" #ReportDetails { margin-left: 10px; margin-right: 10px; margin-bottom: 10px; }\n") wxT(" #ReportDetails td, th { font-size: 80%; margin-left: 2px; margin-right: 2px; }\n") wxT(" #ReportDetails th { border-bottom-color: #777777; border-bottom-style: solid; border-bottom-width: 2px; }\n") wxT(" .ReportDetailsOddDataRow { background-color: #dddddd; }\n") wxT(" .ReportDetailsEvenDataRow { background-color: #eeeeee; }\n") wxT(" .ReportTableHeaderCell { background-color: #dddddd; color: ") + appearanceFactory->GetReportKeyColour().GetAsString(wxC2S_HTML_SYNTAX) + wxT("; vertical-align: top; font-size: 80%; white-space: nowrap; }\n") wxT(" .ReportTableValueCell { vertical-align: top; font-size: 80%; white-space: nowrap; }\n") wxT(" .ReportTableInfo { font-size: 80%; font-style: italic; }\n") wxT(" #ReportFooter { font-weight: bold; font-size: 80%; text-align: right; background-color: ") + appearanceFactory->GetReportKeyColour().GetAsString(wxC2S_HTML_SYNTAX) + wxT("; color: #eeeeee; margin-top: 10px; padding: 2px; border-bottom-style: solid; border-bottom-width: 2px; border-top-style: solid; border-top-width: 2px; border-color: #999999; }\n") wxT(" #ReportFooter a { color: #ffffff; text-decoration: none; }\n"); return data; } wxString frmReport::GetDefaultXsl(const wxString &css) { wxString data; data = wxT("\n") wxT("\n") wxT("\n") wxT("\n") wxT("\n") wxT("\n") wxT(" \n") wxT(" \n") wxT(" <xsl:value-of select=\"header/title\" />\n") wxT(" \n") wxT(" \n"); data += css; data += wxT(" \n") wxT("\n") wxT(" \n") wxT("
\n") wxT("\n") wxT(" \n") wxT("

\n") wxT("
\n") wxT("\n") wxT(" \n") wxT(" "); data += _("Generated"); data += wxT(":
\n") wxT("
\n") wxT("\n") wxT(" \n") wxT(" "); data += _("Server"); data += wxT(":
\n") wxT("
\n") wxT("\n") wxT(" \n") wxT(" "); data += _("Database"); data += wxT(":
\n") wxT("
\n") wxT("\n") wxT(" \n") wxT(" "); data += _("Catalog"); data += wxT(":
\n") wxT("
\n") wxT("\n") wxT(" \n") wxT(" "); data += _("Schema"); data += wxT(":
\n") wxT("
\n") wxT("\n") wxT(" \n") wxT(" "); data += _("Table"); data += wxT(":
\n") wxT("
\n") wxT("\n") wxT(" \n") wxT(" "); data += _("Job"); data += wxT(":
\n") wxT("
\n") wxT("\n") wxT("
\n") wxT("\n") wxT(" \n") wxT("
\n") wxT(" "); data += _("Notes"); data += wxT(":

\n") wxT(" \n") wxT(" \n") wxT(" \n") wxT("
\n") wxT("
\n") wxT("\n") wxT("
\n") wxT(" \n") wxT(" \n") wxT(" \n") wxT("
\n") wxT("\n") wxT(" \n") wxT("\n") wxT("
\n") wxT(" \n") wxT("\n") wxT("\n") wxT("
\n") wxT("\n") wxT("\n") wxT(" \n") wxT("

\n") wxT("
\n") wxT("\n") wxT(" 0\">\n") wxT("
\n") wxT(" \n") wxT(" \n") wxT(" \n") wxT(" \n") wxT(" \n") wxT(" \n") wxT(" \n") wxT(" \n") wxT(" \n") wxT(" \n") wxT(" \n") wxT("
\n") wxT("
\n") wxT("
\n") wxT(" \n") wxT("

\n") wxT("
\n") wxT("
\n") wxT("\n") wxT(" \n") wxT("
\n")
	        wxT("      \n")
	        wxT("         \n")
	        wxT("      \n")
	        wxT("    
\n") wxT("
\n") wxT("
\n") wxT("\n") wxT("\n") wxT(" \n") wxT(" \n") wxT(" %\n") wxT(" \n") wxT(" \n") wxT(" \n") wxT(" \n") wxT("\n") wxT("\n") wxT("\n") wxT(" \n") wxT(" \n") wxT(" \n") wxT(" \n") wxT(" ReportDetailsOddDataRow\n") wxT(" \n") wxT(" \n") wxT(" ReportDetailsEvenDataRow\n") wxT(" \n") wxT(" \n") wxT(" \n") wxT(" \n") wxT(" \n") wxT(" \n") wxT("\n") wxT("\n") wxT("\n") wxT(" \n") wxT(" \n") wxT(" \n") wxT(" \n") wxT(" \n") wxT(" \n") wxT(" \n") wxT(" \n") wxT(" \n") wxT(" \n") wxT(" \n") wxT(" \n") wxT(" \n") wxT("\n") wxT("\n") wxT("\n") wxT(" \n") wxT(" \n") wxT(" \n") wxT("
\n") wxT("
\n") wxT(" \n") wxT(" \n") wxT(" \n") wxT(" \n") wxT(" \n") wxT(" \n") wxT(" \n") wxT(" \n") wxT(" \n") wxT(" \n") wxT(" \n") wxT(" \n") wxT(" \n") wxT(" \n") wxT("
\n") wxT("\n") wxT("
\n"); return data; } ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // END STYLESHEET FUNCTIONS ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // START XML FUNCTIONS ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// void frmReport::XmlAddHeaderValue(const wxString &name, const wxString &value) { header += wxT(" <") + HtmlEntities(name) + wxT(">") + HtmlEntities(value) + wxT("\n"); } int frmReport::XmlCreateSection(const wxString &name) { int ind = sectionName.Add(HtmlEntities(name)); sectionData.Add(wxT("")); sectionTableHeader.Add(wxT("")); sectionTableRows.Add(wxT("")); sectionTableInfo.Add(wxT("")); sectionSql.Add(wxT("")); return ind + 1; } void frmReport::XmlSetSectionTableHeader(const int section, int columns, const wxChar *name, ...) { va_list ap; const wxChar *p = name; wxString data; va_start(ap, name); for (int x = 0; x < columns; x++) { data += wxT(" \n"); p = va_arg(ap, wxChar *); } va_end(ap); sectionTableHeader[section - 1] = data; } void frmReport::XmlAddSectionTableRow(const int section, int number, int columns, const wxChar *value, ...) { va_list ap; const wxChar *p = value; wxString data; va_start(ap, value); data = wxT(" \n"); va_end(ap); sectionTableRows[section - 1] += data; } void frmReport::XmlAddSectionTableFromListView(const int section, ctlListView *list) { // Get the column headers int cols = list->GetColumnCount(); wxString data; wxListItem itm; // Build the columns for (int x = 0; x < cols; x++) { itm.SetMask(wxLIST_MASK_TEXT); list->GetColumn(x, itm); wxString label = itm.GetText(); data += wxT(" \n"); } sectionTableHeader[section - 1] = data; // Build the rows int rows = list->GetItemCount(); for (int y = 0; y < rows; y++) { data = wxT(" GetText(y, x)); data += wxT("\""); } data += wxT(" />\n"); sectionTableRows[section - 1] += data; } } void frmReport::XmlAddSectionTableFromGrid(const int section, ctlSQLResult *grid) { // Get the column headers int cols = grid->GetNumberCols(); int shift = 0; wxString data; wxListItem itm; if (grid->GetRowCountSuppressed()) shift = 1; for (int x = 1; x <= cols; x++) { wxString label = grid->OnGetItemText(-1, x - shift); data += wxT(" \n"); } sectionTableHeader[section - 1] = data; // Build the rows int rows = grid->NumRows(); for (int y = 0; y < rows; y++) { data = wxT(" OnGetItemText(y, x - shift)); data += wxT("\""); } data += wxT(" />\n"); sectionTableRows[section - 1] += data; } } void frmReport::XmlSetSectionSql(int section, const wxString &sql) { sectionSql[section - 1] = HtmlEntities(sql); if (!sectionSql[section - 1].IsEmpty()) chkSql->Enable(); else chkSql->Disable(); } void frmReport::XmlAddSectionValue(const int section, const wxString &name, const wxString &value) { sectionData[section - 1] += wxT(" <") + HtmlEntities(name) + wxT(">") + HtmlEntities(value) + wxT("\n"); } wxString frmReport::GetSectionTableColumns(const int section) { wxString data; data = wxT(" \n"); data += sectionTableHeader[section - 1]; data += wxT(" \n"); return data; } wxString frmReport::GetSectionTableRows(const int section) { wxString data; data = wxT(" \n"); data += sectionTableRows[section - 1]; data += wxT(" \n"); return data; } wxString frmReport::GetSectionTable(const int section) { wxString data; data = wxT(" \n"); data += GetSectionTableColumns(section); data += GetSectionTableRows(section); if (!sectionTableInfo[section - 1].IsEmpty()) { data += wxT(" "); data += sectionTableInfo[section - 1]; data += wxT("\n"); } data += wxT("
\n"); return data; } wxString frmReport::GetSection(const int section) { wxString data; data = wxT("
\n"); data += GetSectionTable(section); if (chkSql->GetValue() && !sectionSql[section - 1].IsEmpty()) { data += wxT(" "); data += sectionSql[section - 1]; data += wxT("\n"); } data += sectionData[section - 1]; data += wxT("
\n"); return data; } wxString frmReport::GetXmlReport(const wxString &stylesheet = wxT("")) { wxString data; data = wxT("\n"); if (!stylesheet.IsEmpty()) { data += wxT("\n"); } data += wxT("\n"); data += wxT("\n\n"); data += wxT("
\n"); data += header; data += wxT("
\n\n"); for (unsigned int x = 1; x <= sectionName.GetCount(); x++ ) { data += GetSection(x); data += wxT("\n"); } data += wxT("
\n"); return data; } // // libxml convenience macros // #define XML_FROM_WXSTRING(s) ((xmlChar *)(const char *)s.mb_str(wxConvUTF8)) #define WXSTRING_FROM_XML(s) wxString((char *)s, wxConvUTF8) wxString frmReport::XslProcessReport(const wxString &xml, const wxString &xsl) { xmlChar *output = 0; xmlDocPtr ssDoc = 0, xmlDoc = 0, resDoc = 0; xsltStylesheetPtr ssPtr = 0; int length; wxBeginBusyCursor(); // Apply the stylesheet xmlSubstituteEntitiesDefault (1); // Substitute entities xmlLoadExtDtdDefaultValue = 1; // Load external entities // Parse the stylesheet ssDoc = xmlParseDoc(XML_FROM_WXSTRING(xsl)); if (!ssDoc) { wxEndBusyCursor(); wxLogError(_("Failed to parse the XML stylesheet!")); goto cleanup; } ssPtr = xsltParseStylesheetDoc(ssDoc); if (!ssPtr) { wxEndBusyCursor(); wxLogError(_("Failed to parse the XSL stylesheet!")); goto cleanup; } // Parse the data xmlDoc = xmlParseDoc(XML_FROM_WXSTRING(xml)); if (!xmlDoc) { wxEndBusyCursor(); wxLogError(_("Failed to parse the XML document!")); goto cleanup; } // Apply the stylesheet resDoc = xsltApplyStylesheet(ssPtr, xmlDoc, NULL); if (!resDoc) { wxEndBusyCursor(); wxLogError(_("Failed to apply the XSL stylesheet to the XML document!")); goto cleanup; } // Get the result xsltSaveResultToString (&output, &length, resDoc, ssPtr); if (!resDoc) { wxEndBusyCursor(); wxLogError(_("Failed to read the processed document!")); goto cleanup; } cleanup: // Cleanup if (resDoc) xmlFreeDoc(resDoc); if (xmlDoc) xmlFreeDoc(xmlDoc); if (ssPtr) xsltFreeStylesheet(ssPtr); // This crashes - dunno why :-( // if (ssDoc) // xmlFreeDoc(ssDoc); xsltCleanupGlobals(); wxEndBusyCursor(); if (output) return WXSTRING_FROM_XML(output); else return wxEmptyString; } ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // END XML FUNCTIONS ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////// // Report base /////////////////////////////////////////////////////// wxWindow *reportBaseFactory::StartDialog(frmMain *form, pgObject *obj) { parent = form; wxBeginBusyCursor(); frmReport *report = new frmReport(GetFrmMain()); // Generate the report header wxDateTime now = wxDateTime::Now(); report->XmlAddHeaderValue(wxT("generated"), now.Format(wxT("%c"))); if (obj->GetServer()) report->XmlAddHeaderValue(wxT("server"), obj->GetServer()->GetFullIdentifier()); if (obj->GetDatabase()) report->XmlAddHeaderValue(wxT("database"), obj->GetDatabase()->GetName()); if (obj->GetSchema()) { if (obj->GetSchema()->GetMetaType() == PGM_CATALOG) report->XmlAddHeaderValue(wxT("catalog"), obj->GetSchema()->GetDisplayName()); else report->XmlAddHeaderValue(wxT("schema"), obj->GetSchema()->GetName()); } if (obj->GetJob()) report->XmlAddHeaderValue(wxT("job"), obj->GetJob()->GetName()); if (obj->GetTable()) report->XmlAddHeaderValue(wxT("table"), obj->GetTable()->GetName()); GenerateReport(report, obj); wxEndBusyCursor(); report->ShowModal(); return 0; } /////////////////////////////////////////////////////// // Properties report /////////////////////////////////////////////////////// reportObjectPropertiesFactory::reportObjectPropertiesFactory(menuFactoryList *list, wxMenu *mnu, ctlMenuToolbar *toolbar) : reportBaseFactory(list) { mnu->Append(id, _("&Properties Report"), _("Generate a Properties report for this object.")); } bool reportObjectPropertiesFactory::CheckEnable(pgObject *obj) { if (obj) { if (obj->IsCollection()) return false; else return true; } return false; } void reportObjectPropertiesFactory::GenerateReport(frmReport *report, pgObject *object) { report->SetReportTitle(object->GetTranslatedMessage(PROPERTIESREPORT)); int section = report->XmlCreateSection(object->GetTranslatedMessage(PROPERTIES)); ctlListView *list = GetFrmMain()->GetProperties(); object->ShowProperties(); report->XmlAddSectionTableFromListView(section, list); report->XmlSetSectionSql(section, object->GetSql(NULL)); } /////////////////////////////////////////////////////// // DDL report /////////////////////////////////////////////////////// reportObjectDdlFactory::reportObjectDdlFactory(menuFactoryList *list, wxMenu *mnu, ctlMenuToolbar *toolbar) : reportBaseFactory(list) { mnu->Append(id, _("&DDL Report"), _("Generate a DDL report for this object.")); } bool reportObjectDdlFactory::CheckEnable(pgObject *obj) { if (obj) { if (obj->GetMetaType() == PGM_SERVER || obj->GetMetaType() == PGM_CATALOGOBJECT || obj->IsCollection()) return false; else return true; } return false; } void reportObjectDdlFactory::GenerateReport(frmReport *report, pgObject *object) { report->SetReportTitle(object->GetTranslatedMessage(DDLREPORT)); int section = report->XmlCreateSection(object->GetTranslatedMessage(DDL)); report->XmlSetSectionSql(section, object->GetSql(NULL)); } /////////////////////////////////////////////////////// // Data dictionary report /////////////////////////////////////////////////////// reportObjectDataDictionaryFactory::reportObjectDataDictionaryFactory(menuFactoryList *list, wxMenu *mnu, ctlMenuToolbar *toolbar) : reportBaseFactory(list) { mnu->Append(id, _("&Data Dictionary Report"), _("Generate a Data Dictionary report for this object.")); } bool reportObjectDataDictionaryFactory::CheckEnable(pgObject *obj) { if (obj) { if ((obj->GetMetaType() == PGM_TABLE || obj->GetMetaType() == GP_PARTITION) && !obj->IsCollection()) return true; else return false; } return false; } void reportObjectDataDictionaryFactory::GenerateReport(frmReport *report, pgObject *object) { pgTable *table = (pgTable *)object; report->SetReportTitle(object->GetTranslatedMessage(DATADICTIONNARYREPORT)); // Columns int section = report->XmlCreateSection(_("Columns")); report->XmlSetSectionTableHeader(section, 6, (const wxChar *) _("Name"), (const wxChar *) _("Data type"), (const wxChar *) _("Not Null?"), (const wxChar *) _("Primary key?"), (const wxChar *) _("Default"), (const wxChar *) _("Comment")); ctlTree *browser = GetFrmMain()->GetBrowser(); pgCollection *columns = table->GetColumnCollection(browser); treeObjectIterator colIt(browser, columns); pgColumn *column; bool haveInherit = false; wxString colName; while ((column = (pgColumn *)colIt.GetNextObject()) != 0) { column->ShowTreeDetail(browser); if (column->GetColNumber() > 0) { colName = column->GetName(); if (column->GetInheritedCount() > 0) { colName += _("*"); haveInherit = true; } report->XmlAddSectionTableRow(section, column->GetColNumber(), 6, (const wxChar *) colName, (const wxChar *) column->GetVarTypename(), (const wxChar *) BoolToYesNo(column->GetNotNull()), (const wxChar *) BoolToYesNo(column->GetIsPK()), (const wxChar *) column->GetDefault(), (const wxChar *) column->GetComment()); } } if (haveInherit) { wxString info; info.Printf(_("* Inherited columns from %s."), table->GetInheritedTables().c_str()); report->XmlSetSectionTableInfo(section, info); } // Constraints pgCollection *constraints = table->GetConstraintCollection(browser); treeObjectIterator conIt(browser, constraints); pgObject *constraint; long x = 1; wxString definition, type; while ((constraint = (pgObject *)conIt.GetNextObject()) != 0) { if (x == 1) { section = report->XmlCreateSection(_("Constraints")); report->XmlSetSectionTableHeader(section, 4, (const wxChar *) _("Name"), (const wxChar *) _("Type"), (const wxChar *) _("Definition"), (const wxChar *) _("Comment")); } constraint->ShowTreeDetail(browser); switch (constraint->GetMetaType()) { case PGM_PRIMARYKEY: type = _("Primary key"); definition = ((pgIndexConstraint *)constraint)->GetDefinition(); break; case PGM_UNIQUE: type = _("Unique"); definition = ((pgIndexConstraint *)constraint)->GetDefinition(); break; case PGM_FOREIGNKEY: type = _("Foreign key"); definition = ((pgForeignKey *)constraint)->GetDefinition(); break; case PGM_EXCLUDE: type = _("Exclude"); definition = ((pgIndexConstraint *)constraint)->GetDefinition(); break; case PGM_CHECK: type = _("Check"); definition = wxT("(") + ((pgCheck *)constraint)->GetDefinition() + wxT(")"); break; } report->XmlAddSectionTableRow(section, x, 4, (const wxChar *) constraint->GetName(), (const wxChar *) type, (const wxChar *) definition, (const wxChar *) constraint->GetComment()); x++; } } /////////////////////////////////////////////////////// // Statistics report /////////////////////////////////////////////////////// reportObjectStatisticsFactory::reportObjectStatisticsFactory(menuFactoryList *list, wxMenu *mnu, ctlMenuToolbar *toolbar) : reportBaseFactory(list) { mnu->Append(id, _("&Statistics Report"), _("Generate a Statistics report for this object.")); } bool reportObjectStatisticsFactory::CheckEnable(pgObject *obj) { if (obj) { if (!obj->HasStats()) { if (obj->IsCollection()) { pgaFactory *f = obj->GetFactory(); if (f) { if (f->GetMetaType() == PGM_TABLE || f->GetMetaType() == GP_PARTITION || f->GetMetaType() == PGM_TABLESPACE || f->GetMetaType() == PGM_DATABASE) return true; } else { return false; } } else { return false; } } else { return true; } } return false; } void reportObjectStatisticsFactory::GenerateReport(frmReport *report, pgObject *object) { report->SetReportTitle(object->GetTranslatedMessage(STATISTICSREPORT)); int section = report->XmlCreateSection(object->GetTranslatedMessage(OBJSTATISTICS)); ctlListView *list = GetFrmMain()->GetStatistics(); object->ShowStatistics(GetFrmMain(), list); report->XmlAddSectionTableFromListView(section, list); } /////////////////////////////////////////////////////// // Dependencies report /////////////////////////////////////////////////////// reportObjectDependenciesFactory::reportObjectDependenciesFactory(menuFactoryList *list, wxMenu *mnu, ctlMenuToolbar *toolbar) : reportBaseFactory(list) { mnu->Append(id, _("&Dependencies Report"), _("Generate a Dependencies report for this object.")); } bool reportObjectDependenciesFactory::CheckEnable(pgObject *obj) { if (obj) { if (!obj->HasDepends()) return false; else return true; } return false; } void reportObjectDependenciesFactory::GenerateReport(frmReport *report, pgObject *object) { report->SetReportTitle(object->GetTranslatedMessage(DEPENDENCIESREPORT)); int section = report->XmlCreateSection(object->GetTranslatedMessage(DEPENDENCIES)); ctlListView *list = GetFrmMain()->GetDependencies(); object->ShowDependencies(parent, list); report->XmlAddSectionTableFromListView(section, list); } /////////////////////////////////////////////////////// // Dependents report /////////////////////////////////////////////////////// reportObjectDependentsFactory::reportObjectDependentsFactory(menuFactoryList *list, wxMenu *mnu, ctlMenuToolbar *toolbar) : reportBaseFactory(list) { mnu->Append(id, _("&Dependents Report"), _("Generate a Dependents report for this object.")); } bool reportObjectDependentsFactory::CheckEnable(pgObject *obj) { if (obj) { if (!obj->HasReferences()) return false; else return true; } return false; } void reportObjectDependentsFactory::GenerateReport(frmReport *report, pgObject *object) { report->SetReportTitle(object->GetTranslatedMessage(DEPENDENTSREPORT)); int section = report->XmlCreateSection(object->GetTranslatedMessage(DEPENDENTS)); ctlListView *list = GetFrmMain()->GetReferencedBy(); object->ShowDependents(parent, list); report->XmlAddSectionTableFromListView(section, list); } /////////////////////////////////////////////////////// // Object list report /////////////////////////////////////////////////////// reportObjectListFactory::reportObjectListFactory(menuFactoryList *list, wxMenu *mnu, ctlMenuToolbar *toolbar) : reportBaseFactory(list) { mnu->Append(id, _("&Object List Report"), _("Generate an Object List report for this collection.")); } bool reportObjectListFactory::CheckEnable(pgObject *obj) { if (obj) { if (!obj->IsCollection()) { return false; } else { pgaFactory *f = obj->GetFactory(); if (obj) { if (f->GetMetaType() == PGM_SERVER) return false; } else return false; return true; } } return false; } void reportObjectListFactory::GenerateReport(frmReport *report, pgObject *object) { report->SetReportTitle(object->GetTranslatedMessage(OBJECTSLISTREPORT)); int section = report->XmlCreateSection(object->GetFullIdentifier()); ctlListView *list = GetFrmMain()->GetProperties(); object->ShowProperties(); report->XmlAddSectionTableFromListView(section, list); }