pgadmin3/frm/frmMain.cpp

1644 lines
50 KiB
C++

//////////////////////////////////////////////////////////////////////////
//
// pgAdmin III - PostgreSQL Tools
//
// Copyright (C) 2002 - 2016, The pgAdmin Development Team
// This software is released under the PostgreSQL Licence
//
// frmMain.cpp - The main form
//
// Note: Due to the size of frmMain, event handler, browser and statistics
// functions are in events.cpp.
//
//////////////////////////////////////////////////////////////////////////
#include "pgAdmin3.h"
#ifndef WIN32
#include <unistd.h>
#endif
// wxWindows headers
#include <wx/wx.h>
#include <wx/settings.h>
#include <wx/treectrl.h>
#include <wx/listctrl.h>
#include <wx/notebook.h>
#include <wx/toolbar.h>
#include <wx/imaglist.h>
#include <wx/busyinfo.h>
#include <wx/sysopt.h>
#include <wx/textbuf.h>
#include <wx/clipbrd.h>
// wxAUI
#include <wx/aui/aui.h>
// App headers
#include "utils/misc.h"
#include "frm/menu.h"
#include "utils/pgfeatures.h"
#include "debugger/debugger.h"
#include "frm/frmMain.h"
#include "ctl/ctlMenuToolbar.h"
#include "ctl/ctlSQLBox.h"
#include "db/pgConn.h"
#include "db/pgSet.h"
#include "agent/pgaJob.h"
#include "schema/pgDatabase.h"
#include "schema/pgServer.h"
#include "schema/pgObject.h"
#include "schema/pgCollection.h"
#include "frm/frmOptions.h"
#include "frm/frmAbout.h"
#include "frm/frmHint.h"
#include "frm/frmGrantWizard.h"
#include "frm/frmMainConfig.h"
#include "frm/frmHbaConfig.h"
#include "frm/frmPgpassConfig.h"
#include "frm/frmBackup.h"
#include "frm/frmBackupGlobals.h"
#include "frm/frmBackupServer.h"
#include "frm/frmRestore.h"
#include "frm/frmReport.h"
#include "frm/frmMaintenance.h"
#include "frm/frmStatus.h"
#include "frm/frmLog.h"
#include "frm/frmAwr.h"
#include "frm/frmPassword.h"
#ifdef DATABASEDESIGNER
#include "frm/frmDatabaseDesigner.h"
#endif
#include "frm/frmQuery.h"
#include "frm/frmEditGrid.h"
#include "frm/frmImport.h"
#include "dlg/dlgServer.h"
#include "dlg/dlgDatabase.h"
#include "dlg/dlgSearchObject.h"
#include "schema/pgTable.h"
#include "schema/pgView.h"
#include "schema/pgFunction.h"
#include "schema/pgIndex.h"
#include "schema/pgTrigger.h"
#include "pro_scheduler/pgproJob.h"
#include "schema/pgRole.h"
#include "schema/pgRule.h"
#include "schema/pgServer.h"
#include "schema/pgTablespace.h"
#include "slony/slCluster.h"
#include "slony/slSet.h"
#include "schema/pgForeignKey.h"
#include "schema/pgCheck.h"
#include "schema/pgDomain.h"
#include "schema/pgEventTrigger.h"
#include "ctl/ctlShortCut.h"
#ifdef WIN32
#include <wx/msw/ole/automtn.h>
#endif
#include "utils/utffile.h"
#if defined(HAVE_OPENSSL_CRYPTO) || defined(HAVE_GCRYPT)
#include "utils/sshTunnel.h"
#endif
#if wxDIALOG_UNIT_COMPATIBILITY
#error wxWindows must be compiled with wxDIALOG_UNIT_COMPATIBILITY=0!
#endif
#if defined(HAVE_OPENSSL_CRYPTO) || defined(HAVE_GCRYPT)
DEFINE_EVENT_TYPE(SSH_TUNNEL_ERROR_EVENT);
#endif
frmMain::frmMain(const wxString &title)
: pgFrame((wxFrame *)NULL, title)
{
msgLevel = 0;
lastPluginUtility = NULL;
pluginUtilityCount = 0;
m_refreshing = false;
Logfrm = NULL;
dlgName = wxT("frmMain");
SetMinSize(wxSize(600, 450));
RestorePosition(50, 50, 750, 550, 600, 450);
SetFont(settings->GetSystemFont());
{
wxLogInfo(wxT("Using fontmetrics %d/%d, %d Point"), GetCharWidth(), GetCharHeight(), GetFont().GetPointSize());
wxLogInfo(wxT("Native Description '%s'"), GetFont().GetNativeFontInfoDesc().c_str());
wxWindowDC dc(this);
dc.SetFont(GetFont());
wxCoord w, h, d, e;
dc.GetTextExtent(wxT("M"), &w, &h, &d, &e);
wxLogInfo(wxT("Draw size of 'M': w=%d, h=%d, descent %d, external lead %d."), w, h, d, e);
dc.GetTextExtent(wxT("g"), &w, &h, &d, &e);
wxLogInfo(wxT("Draw size of 'g': w=%d, h=%d, descent %d, external lead %d."), w, h, d, e);
dc.GetTextExtent(wxT("Mg"), &w, &h, &d, &e);
wxLogInfo(wxT("Draw size of 'Mg': w=%d, h=%d, descent %d, external lead %d."), w, h, d, e);
}
// Current database
denyCollapseItem = wxTreeItemId();
currentObject = 0;
appearanceFactory->SetIcons(this);
// notify wxAUI which frame to use
manager.SetManagedWindow(this);
manager.SetFlags(wxAUI_MGR_DEFAULT | wxAUI_MGR_TRANSPARENT_DRAG | wxAUI_MGR_ALLOW_ACTIVE_PANE);
// wxGTK needs this deferred
pgaFactory::RealizeImages();
CreateMenus();
// Setup the object browser
browser = new ctlTree(this, CTL_BROWSER, wxDefaultPosition, wxDefaultSize, wxTR_HAS_BUTTONS | wxSIMPLE_BORDER);
browser->SetImageList(imageList);
// Setup the listview
listViews = new ctlAuiNotebook(this, CTL_NOTEBOOK, wxDefaultPosition, wxDefaultSize, wxAUI_NB_TOP | wxAUI_NB_TAB_SPLIT | wxAUI_NB_TAB_MOVE | wxAUI_NB_TAB_EXTERNAL_MOVE | wxAUI_NB_SCROLL_BUTTONS | wxAUI_NB_WINDOWLIST_BUTTON);
// Switch to the generic list control. Native doesn't play well with
// multi-row select on Mac.
#ifdef __WXMAC__
wxSystemOptions::SetOption(wxT("mac.listctrl.always_use_generic"), true);
#endif
properties = new ctlListView(listViews, CTL_PROPVIEW, wxDefaultPosition, wxDefaultSize, wxSIMPLE_BORDER);
statistics = new ctlListView(listViews, CTL_STATVIEW, wxDefaultPosition, wxDefaultSize, wxSIMPLE_BORDER);
dependencies = new ctlListView(listViews, CTL_DEPVIEW, wxDefaultPosition, wxDefaultSize, wxSIMPLE_BORDER);
dependents = new ctlListView(listViews, CTL_REFVIEW, wxDefaultPosition, wxDefaultSize, wxSIMPLE_BORDER);
#if !defined(NO_WXJSON_GIT)
#if wxUSE_WEBREQUEST
git = NULL;
wxJSONValue cfg=ctlGitPanel::GetConfig();
if (!cfg.IsNull()) git = new ctlGitPanel(listViews, this,cfg);
#endif
#endif
// Switch back to the native list control.
#ifdef __WXMAC__
wxSystemOptions::SetOption(wxT("mac.listctrl.always_use_generic"), false);
#endif
listViews->AddPage(properties, _("Properties")); // NBP_PROPERTIES
listViews->AddPage(statistics, _("Statistics")); // NBP_STATISTICS
listViews->AddPage(dependencies, _("Dependencies")); // NBP_DEPENDENCIES
listViews->AddPage(dependents, _("Dependents")); // NBP_DEPENDENTS
#if !defined(NO_WXJSON_GIT)
#if wxUSE_WEBREQUEST
if (git) {
listViews->AddPage(git, _("Git")); //
}
#endif
#endif
properties->SetImageList(imageList, wxIMAGE_LIST_SMALL);
statistics->SetImageList(imageList, wxIMAGE_LIST_SMALL);
dependencies->SetImageList(imageList, wxIMAGE_LIST_SMALL);
dependents->SetImageList(imageList, wxIMAGE_LIST_SMALL);
wxColour background;
background = wxSystemSettings::GetColour(wxSYS_COLOUR_BTNFACE);
statistics->SetBackgroundColour(background);
dependencies->SetBackgroundColour(background);
dependents->SetBackgroundColour(background);
// Setup the SQL pane
sqlPane = new ctlSQLBox(this, CTL_SQLPANE, wxDefaultPosition, wxDefaultSize, wxTE_MULTILINE | wxSIMPLE_BORDER | wxTE_READONLY | wxTE_RICH2);
sqlPane->SetBackgroundColour(background);
// Setup menus
pgaFactory::RegisterMenu(this, wxCommandEventHandler(frmMain::OnNew));
menuFactories->RegisterMenu(this, wxCommandEventHandler(frmMain::OnAction));
menuFactories->CheckMenu(0, menuBar, toolBar);
wxSize toolw = toolBar->GetBestSize();
// Kickstart wxAUI
manager.AddPane(browser, wxAuiPaneInfo().Name(wxT("objectBrowser")).Caption(_("Object browser")).Left().MinSize(wxSize(100, 200)).BestSize(wxSize(200, 450)));
manager.AddPane(listViews, wxAuiPaneInfo().Name(wxT("listViews")).Caption(_("Info pane")).Center().CaptionVisible(false).CloseButton(false).MinSize(wxSize(200, 100)).BestSize(wxSize(400, 200)));
manager.AddPane(sqlPane, wxAuiPaneInfo().Name(wxT("sqlPane")).Caption(_("SQL pane")).Bottom().MinSize(wxSize(200, 100)).BestSize(wxSize(400, 200)));
manager.AddPane(toolBar, wxAuiPaneInfo().Name(wxT("toolBar")).Caption(_("Tool bar")).ToolbarPane().Top().LeftDockable(false).RightDockable(false));
// Now load the layout
wxString perspective;
settings->Read(wxT("frmMain/Perspective-") + wxString(FRMMAIN_PERSPECTIVE_VER), &perspective, FRMMAIN_DEFAULT_PERSPECTIVE);
manager.LoadPerspective(perspective, true);
// and reset the captions for the current language
manager.GetPane(wxT("objectBrowser")).Caption(_("Object browser"));
manager.GetPane(wxT("listViews")).Caption(_("Info pane"));
manager.GetPane(wxT("sqlPane")).Caption(_("SQL pane"));
manager.GetPane(wxT("toolBar")).Caption(_("Tool bar"));
manager.GetPane(wxT("toolBar")).BestSize(toolw);
// Sync the View menu options
viewMenu->Check(MNU_SQLPANE, manager.GetPane(wxT("sqlPane")).IsShown());
viewMenu->Check(MNU_OBJECTBROWSER, manager.GetPane(wxT("objectBrowser")).IsShown());
viewMenu->Check(MNU_TOOLBAR, manager.GetPane(wxT("toolBar")).IsShown());
ResetLists();
// tell the manager to "commit" all the changes just made
manager.Update();
// Add the root node
serversObj = new pgServerCollection(serverFactory.GetCollectionFactory());
wxTreeItemId root = browser->AddRoot(_("Server Groups"), serversObj->GetIconId(), -1, serversObj);
// Work around a bug in the generic tree control in wxWidgets,
// Per http://trac.wxwidgets.org/ticket/10085
browser->SetItemText(root, _("Server Groups"));
// Load servers
RetrieveServers();
#ifndef WIN32
if (!currentObject) currentObject=serversObj;
#endif
browser->Expand(root);
browser->SortChildren(root);
browser->SetFocus();
wxString selServerName=settings->Read(wxT("Servers/SelectItem"), "");
if (selServerName.Len()>0) {
wxTreeItemId sel=browser->FindItem(root,selServerName,false);
if (sel.IsOk()) {
browser->SelectItem(sel);
currentObject=browser->GetObject(sel);
//execSelChange(sel, true);
}
}
}
frmMain::~frmMain()
{
// Store the servers, to ensure we store the last database/schema etc
if (settings) {
StoreServers();
settings->Write(wxT("frmMain/Perspective-") + wxString(FRMMAIN_PERSPECTIVE_VER), manager.SavePerspective());
}
manager.UnInit();
// Clear the treeview
browser->DeleteAllItems();
if (treeContextMenu)
delete treeContextMenu;
#if defined(HAVE_OPENSSL_CRYPTO) || defined(HAVE_GCRYPT)
if(pgadminTunnelThread && pgadminTunnelThread->IsAlive())
{
pgadminTunnelThread->Cleanup();
pgadminTunnelThread = NULL;
}
#endif
}
#include <wx/hashmap.h>
WX_DECLARE_HASH_MAP(wxString, wxBitmapBundle, wxStringHash, wxStringEqual, MyHash1);
MyHash1 bundleHash;
wxBitmapBundle GetBundleSVG(wxBitmap* std, wxString name, wxSize sz) {
wxBitmapBundle bb;
wxBitmapBundle *b=NULL;
bb = bundleHash[name];
if (bb.IsOk()) return bb;
extern wxString dataDir;
wxString fullpath=dataDir+ sepPath +"svg" + sepPath + name; // 1. local data application
if (!wxFile::Exists(fullpath)) fullpath=loadPath + sepPath +"svg" + sepPath + name; // 2. execute path
if (wxFile::Exists(fullpath)) { // name only filename.svg
bb=wxBitmapBundle::FromSVGFile(fullpath, sz);
}
else if (wxFile::Exists(name)) { // name = fullpath
if (name.AfterLast('.') == "png") {
wxBitmap bitmap(name, wxBITMAP_TYPE_PNG);
if (!bitmap.Ok())
{
wxMessageBox(wxT("Sorry, could not load png file.\n") + name);
}
else {
bb = wxBitmapBundle::FromBitmap(bitmap);
}
}
else if (name.AfterLast('.') == "svg") {
bb = wxBitmapBundle::FromSVGFile(name, sz);
}
}
if (!bb.IsOk() && std){
// file not found use standart bitmap
bb = wxBitmapBundle::FromBitmap(*std);
}
if (bb.IsOk()) bundleHash[name] = bb; else {
wxLogError("Empty bundle for %s",name);
}
return bb;
}
void frmMain::CreateMenus()
{
// to add a new menu or context menu to the main window, i.e. define a possible
// action on a pgObject, everything has to go into this method. Doing menu related
// stuff elsewhere is plain wrong!
// Create a proper actionFactory (or contextActionFactory) for each of your new actions
// in the new frmXXX.cpp and register it here.
fileMenu = new wxMenu();
pluginsMenu = new wxMenu();
viewMenu = new wxMenu();
editMenu = new wxMenu();
newMenu = new wxMenu();
toolsMenu = new wxMenu();
slonyMenu = new wxMenu();
scriptingMenu = new wxMenu();
viewDataMenu = new wxMenu();
debuggingMenu = new wxMenu();
serverMenu = new wxMenu();
reportMenu = new wxMenu();
wxMenu *cfgMenu = new wxMenu();
helpMenu = new wxMenu();
newContextMenu = new wxMenu();
toolBar = new ctlMenuToolbar(this, -1, wxDefaultPosition, wxDefaultSize, wxTB_FLAT | wxTB_NODIVIDER );
//toolBar->SetToolBitmapSize(wxSize(32, 32));
menuFactories = new menuFactoryList();
// Load plugins - must do this after creating the menus and the factories
LoadPluginUtilities();
//--------------------------
fileMenu->Append(MNU_SAVEDEFINITION, _("&Save Definition..."), _("Save the SQL definition of the selected object."));
fileMenu->AppendSeparator();
new addServerFactory(menuFactories, fileMenu, toolBar);
viewMenu->Append(MNU_OBJECTBROWSER, _("&Object browser\tCtrl-Alt-O"), _("Show or hide the object browser."), wxITEM_CHECK);
viewMenu->Append(MNU_SQLPANE, _("&SQL pane\tCtrl-Alt-S"), _("Show or hide the SQL pane."), wxITEM_CHECK);
viewMenu->Append(MNU_TOOLBAR, _("&Tool bar\tCtrl-Alt-T"), _("Show or hide the tool bar."), wxITEM_CHECK);
viewMenu->AppendSeparator();
viewMenu->Append(MNU_DEFAULTVIEW, _("&Default view\tCtrl-Alt-V"), _("Restore the default view."));
viewMenu->AppendSeparator();
actionFactory *refFact = new refreshFactory(menuFactories, viewMenu, toolBar);
new countRowsFactory(menuFactories, viewMenu, 0);
new refreshMatViewFactory(menuFactories, viewMenu, 0);
new refreshConcurrentlyMatViewFactory(menuFactories, viewMenu, 0);
new executePgstattupleFactory(menuFactories, viewMenu, 0);
new executePgstatindexFactory(menuFactories, viewMenu, 0);
new resetIndexStatsFactory(menuFactories, viewMenu, 0);
new executePgcheckindexFactory(menuFactories, viewMenu, 0);
new enabledisableRuleFactory(menuFactories, toolsMenu, 0);
new enabledisableTriggerFactory(menuFactories, toolsMenu, 0);
new enabledisableEventTriggerFactory(menuFactories, toolsMenu, 0);
new enabledisableJobFactory(menuFactories, toolsMenu, 0);
new disableAllTriggersFactory(menuFactories, toolsMenu, 0);
new enableAllTriggersFactory(menuFactories, toolsMenu, 0);
new validateForeignKeyFactory(menuFactories, toolsMenu, 0);
new validateCheckFactory(menuFactories, toolsMenu, 0);
new validateDomainCheckFactory(menuFactories, toolsMenu, 0);
toolsMenu->AppendSeparator();
//--------------------------
new separatorFactory(menuFactories);
toolBar->AddSeparator();
new passwordFactory(menuFactories, fileMenu, 0);
fileMenu->AppendSeparator();
optionsFactory *optFact = new optionsFactory(menuFactories, fileMenu, 0);
fileMenu->AppendSeparator();
new mainConfigFileFactory(menuFactories, fileMenu, 0);
new hbaConfigFileFactory(menuFactories, fileMenu, 0);
new pgpassConfigFileFactory(menuFactories, fileMenu, 0);
fileMenu->AppendSeparator();
fileMenu->Append(MNU_EXIT, _("E&xit\tCtrl-Q"), _("Quit this program."));
new slonyRestartFactory(menuFactories, slonyMenu, 0);
new slonyUpgradeFactory(menuFactories, slonyMenu, 0);
new slonyFailoverFactory(menuFactories, slonyMenu, 0);
new slonyLockSetFactory(menuFactories, slonyMenu, 0);
new slonyUnlockSetFactory(menuFactories, slonyMenu, 0);
new slonyMergeSetFactory(menuFactories, slonyMenu, 0);
new slonyMoveSetFactory(menuFactories, slonyMenu, 0);
toolsMenu->Append(MNU_SLONY_SUBMENU, _("Slony Replication"), slonyMenu);
propFactory = new propertyFactory(menuFactories, 0, toolBar);
new separatorFactory(menuFactories);
// -------------------------
editMenu->Append(MNU_COPY, _("&Copy\tCtrl-C"), _("Copy selected text to clipboard"));
editMenu->AppendSeparator();
// -------------------------
//--------------------------
newMenuFactory = new submenuFactory(menuFactories); // placeholder where "New objects" submenu will be inserted
editMenu->Append(newMenuFactory->GetId(), _("New &Object"), newMenu, _("Create a new object."));
editMenu->AppendSeparator();
//--------------------------
serverMenuFactory = new submenuFactory(menuFactories);
toolsMenu->Append(serverMenuFactory->GetId(), _("&Server"), serverMenu, _("Server menu commands."));
new connectServerFactory(menuFactories, serverMenu, 0);
new disconnectServerFactory(menuFactories, serverMenu, 0);
new disconnectServerFactoryAll(menuFactories, serverMenu, 0);
new disconnectDatabaseFactory(menuFactories, serverMenu, 0);
new startServiceFactory(menuFactories, serverMenu, 0);
new stopServiceFactory(menuFactories, serverMenu, 0);
new reloadconfServiceFactory(menuFactories, serverMenu, 0);
new pausereplayServiceFactory(menuFactories, serverMenu, 0);
new resumereplayServiceFactory(menuFactories, serverMenu, 0);
new addnamedrestorepointServiceFactory(menuFactories, serverMenu, 0);
new keywordsServerFactory(menuFactories, serverMenu, 0);
new createFactory(menuFactories, editMenu, toolBar);
new dropFactory(menuFactories, editMenu, toolBar);
new dropCascadedFactory(menuFactories, editMenu, 0);
new truncateFactory(menuFactories, editMenu, 0);
new truncateCascadedFactory(menuFactories, editMenu, 0);
new resetTableStatsFactory(menuFactories, editMenu, 0);
new resetFunctionStatsFactory(menuFactories, editMenu, 0);
new reassignDropOwnedFactory(menuFactories, editMenu, 0);
new moveTablespaceFactory(menuFactories, editMenu, 0);
new searchObjectFactory(menuFactories, editMenu, 0);
editMenu->AppendSeparator();
new separatorFactory(menuFactories);
toolBar->AddSeparator();
toolsMenu->AppendSeparator();
debuggingMenuFactory = new submenuFactory(menuFactories); // placeholder where "Debugging" submenu will be inserted
toolsMenu->Append(debuggingMenuFactory->GetId(), _("&Debugging"), debuggingMenu, _("Debugging options for the selected item."));
new debuggerFactory(menuFactories, debuggingMenu, 0);
new breakpointFactory(menuFactories, debuggingMenu, 0);
new queryToolFactory(menuFactories, toolsMenu, toolBar);
scriptingMenuFactory = new submenuFactory(menuFactories); // placeholder where "Query Template" submenu will be inserted
toolsMenu->Append(scriptingMenuFactory->GetId(), _("Scripts"), scriptingMenu, _("Start Query Tool with scripted query."));
new queryToolSqlFactory(menuFactories, scriptingMenu, 0);
new queryToolCreateCascadeFactory(menuFactories, scriptingMenu, 0);
new queryToolSelectFactory(menuFactories, scriptingMenu, 0);
new queryToolExecFactory(menuFactories, scriptingMenu, 0);
new queryToolInsertFactory(menuFactories, scriptingMenu, 0);
new queryToolUpdateFactory(menuFactories, scriptingMenu, 0);
new queryToolDeleteFactory(menuFactories, scriptingMenu, 0);
#ifdef DATABASEDESIGNER
new databaseDesignerFactory(menuFactories, toolsMenu, toolBar);
#endif
viewdataMenuFactory = new submenuFactory(menuFactories); // placeholder where "View data" submenu will be inserted
toolsMenu->Append(viewdataMenuFactory->GetId(), _("View &Data"), viewDataMenu, _("View data."));
reportMenuFactory = new submenuFactory(menuFactories); // placeholder where "Reports" submenu will be inserted
toolsMenu->Append(reportMenuFactory->GetId(), _("&Reports"), reportMenu, _("Create reports about the selected item."));
new reportObjectPropertiesFactory(menuFactories, reportMenu, 0);
new reportObjectDdlFactory(menuFactories, reportMenu, 0);
new reportObjectDataDictionaryFactory(menuFactories, reportMenu, 0);
new reportObjectStatisticsFactory(menuFactories, reportMenu, 0);
new reportObjectDependenciesFactory(menuFactories, reportMenu, 0);
new reportObjectDependentsFactory(menuFactories, reportMenu, 0);
new reportObjectListFactory(menuFactories, reportMenu, 0);
new reportCompareFactory(menuFactories, reportMenu, 0);
new reportAwrFactory(menuFactories, reportMenu, 0);
choiceSelectOpts.Add(0);
choiceSelectOpts.Add(1);
toolsMenu->AppendSeparator();
new editGridLimitedFactory(menuFactories, viewDataMenu, toolBar, 100, true);
new editGridLimitedFactory(menuFactories, viewDataMenu, toolBar, 100, false);
new editGridFactory(menuFactories, viewDataMenu, toolBar);
new editGridFilteredFactory(menuFactories, viewDataMenu, toolBar);
new maintenanceFactory(menuFactories, toolsMenu, toolBar);
new backupFactory(menuFactories, toolsMenu, 0);
new backupGlobalsFactory(menuFactories, toolsMenu, 0);
new LogFactory(menuFactories, cfgMenu, 0);
new backupServerFactory(menuFactories, toolsMenu, 0);
new restoreFactory(menuFactories, toolsMenu, 0);
new importFactory(menuFactories, toolsMenu, 0);
new grantWizardFactory(menuFactories, toolsMenu, 0);
new mainConfigFactory(menuFactories, cfgMenu, 0);
new hbaConfigFactory(menuFactories, cfgMenu, 0);
toolsMenu->Append(MNU_CONFIGSUBMENU, _("Server Configuration"), cfgMenu);
toolsMenu->AppendSeparator();
new runNowFactory(menuFactories, toolsMenu, 0);
toolsMenu->AppendSeparator();
new separatorFactory(menuFactories);
new propertyFactory(menuFactories, editMenu, 0);
new serverStatusFactory(menuFactories, toolsMenu, 0);
// Add the plugin toolbar button/menu
new pluginButtonMenuFactory(menuFactories, pluginsMenu, toolBar, pluginUtilityCount);
//--------------------------
toolBar->AddSeparator();
actionFactory *helpFact = new contentsFactory(menuFactories, helpMenu, 0);
new hintFactory(menuFactories, helpMenu, toolBar, true);
new faqFactory(menuFactories, helpMenu, 0);
new bugReportFactory(menuFactories, helpMenu, 0);
helpMenu->AppendSeparator();
new pgsqlHelpFactory(menuFactories, helpMenu, toolBar, true);
if (!appearanceFactory->GetHideEnterprisedbHelp())
new edbHelpFactory(menuFactories, helpMenu, toolBar, true);
if (!appearanceFactory->GetHideGreenplumHelp())
new greenplumHelpFactory(menuFactories, helpMenu, toolBar, true);
new slonyHelpFactory(menuFactories, helpMenu, toolBar, true);
// Don't include this seperator on Mac, because the only option
// under it will be moved to the application menu.
#ifndef __WXMAC__
helpMenu->AppendSeparator();
#endif
actionFactory *abFact = new aboutFactory(menuFactories, helpMenu, 0);
#ifdef __WXMAC__
wxApp::s_macPreferencesMenuItemId = optFact->GetId();
wxApp::s_macExitMenuItemId = MNU_EXIT;
wxApp::s_macAboutMenuItemId = abFact->GetId();
#else
(void)optFact;
(void)abFact;
#endif
menuBar = new wxMenuBar();
menuBar->Append(fileMenu, _("&File"));
menuBar->Append(editMenu, _("&Edit"));
// Changing the caption of the plugins menu also needs a similar change below
menuBar->Append(pluginsMenu, _("&Plugins"));
menuBar->Append(viewMenu, _("&View"));
menuBar->Append(toolsMenu, _("&Tools"));
menuBar->Append(helpMenu, _("&Help"));
SetMenuBar(menuBar);
// Disable the plugins menu if there aren't any.
if (!pluginUtilityCount)
{
pluginsMenu->Append(MNU_DUMMY, _("No plugins installed"));
pluginsMenu->Enable(MNU_DUMMY, false);
}
treeContextMenu = 0;
// Status bar
statusBar = CreateStatusBar(4);
int iWidths[4] = {0, -1, 400, 100};
SetStatusWidths(4, iWidths);
SetStatusBarPane(-1);
statusBar->SetStatusText(wxT(""), 0);
statusBar->SetStatusText(_("Ready."), 1);
statusBar->SetStatusText(_("0 Secs"), 3);
wxAcceleratorEntry entries[5];
entries[0].Set(wxACCEL_NORMAL, WXK_F5, refFact->GetId());
entries[1].Set(wxACCEL_NORMAL, WXK_DELETE, MNU_DELETE);
entries[2].Set(wxACCEL_NORMAL, WXK_F1, helpFact->GetId());
entries[3].Set(wxACCEL_SHIFT, WXK_F10, MNU_CONTEXTMENU);
entries[4].Set(wxACCEL_NORMAL, WXK_F4, MNU_SHORTCUT);
wxAcceleratorTable accel(5, entries);
SetAcceleratorTable(accel);
// Display the bar and configure buttons.
toolBar->Realize();
}
void frmMain::Refresh(pgObject *data)
{
bool done = false;
pgObject *obj = NULL;
StartMsg(data->GetTranslatedMessage(REFRESHINGDETAILS));
browser->Freeze();
wxTreeItemId currentItem = data->GetId();
if (currentItem)
obj = browser->GetObject(currentItem);
if (obj && obj->CheckOpenDialogs(browser, currentItem))
{
wxString msg = _("There are properties dialogues open for one or more objects that would be refreshed. Please close the properties dialogues and try again.");
wxMessageBox(msg, _("Cannot refresh browser"), wxICON_WARNING | wxOK);
}
else
{
if (data->GetMetaType() == PGM_SCHEMA && !data->IsCollection() && data->GetConnection()->BackendMinimumVersion(9, 3))
{
// Event triggers backend functions are at schema level.
// Hence, we can consider that Event Triggers at schema level and partly at database.
// So, if any schema is refreshed, we need to the event trigger collection as well.
// It's a special case, which effects the schema operations on the event triggers as well.
// To solve this, we are navigating to the parent node (database node), and then locating event trigger collections.
// Once we've found the event triggers collection, we refresh it.
//
wxTreeItemId dbItem = browser->GetItemParent(browser->GetItemParent(browser->GetSelection()));
pgCollection *eventTrgCol = browser->FindCollection(eventTriggerFactory, dbItem);
if(eventTrgCol)
Refresh(eventTrgCol);
}
// Scan the child nodes and make a list of those that are expanded
// This is not an exact science as node names may change etc.
wxArrayString expandedNodes;
GetExpandedChildNodes(currentItem, expandedNodes);
browser->DeleteChildren(currentItem);
// refresh information about the object
data->SetDirty();
pgObject *newData = data->Refresh(browser, currentItem);
done = !data->GetConnection() || data->GetConnection()->GetStatus() == PGCONN_OK;
if (newData != data)
{
wxLogInfo(wxT("Deleting %s %s for refresh"), data->GetTypeName().c_str(), data->GetQuotedFullIdentifier().c_str());
if (data == currentObject)
currentObject = newData;
if (newData)
{
wxLogInfo(wxT("Replacing with new node %s %s for refresh"), newData->GetTypeName().c_str(), newData->GetQuotedFullIdentifier().c_str());
newData->SetId(currentItem); // not done automatically
browser->SetItemData(currentItem, newData);
// Update the node text if this is an object, as it may have been renamed
if (!newData->IsCollection())
browser->SetItemText(currentItem, newData->GetDisplayName());
delete data;
data = NULL;
}
else
{
wxLogInfo(wxT("No object to replace: vanished after refresh."));
// If the connection is dead, just return here
if (data->GetConnection()->GetStatus() != PGCONN_OK)
{
CheckAlive();
browser->Thaw();
return;
}
wxTreeItemId delItem = currentItem;
currentItem = browser->GetItemParent(currentItem);
browser->SelectItem(currentItem);
browser->Delete(delItem);
}
}
if (currentItem)
{
// Select the current node
execSelChange(currentItem, currentItem == browser->GetSelection());
// Attempt to expand any child nodes that were previously expanded
ExpandChildNodes(currentItem, expandedNodes);
}
}
browser->Thaw();
EndMsg(done);
}
void frmMain::OnCopy(wxCommandEvent &ev)
{
wxString text;
// Attempt to copy from the current object
// Listview
ctlListView *lv = dynamic_cast<ctlListView *>(currentControl);
if (lv)
{
int row = lv->GetFirstSelected();
while (row >= 0)
{
for (int col = 0; col < lv->GetColumnCount(); col++)
{
text.Append(lv->GetText(row, col) + wxT("\t"));
}
text.Append(wxT("\n"));
row = lv->GetNextSelected(row);
}
text = text.Trim();
}
// ctlSQLBox
ctlSQLBox *sb = dynamic_cast<ctlSQLBox *>(currentControl);
if (sb)
{
text = sb->GetSelectedText();
}
// Set the clipboard text
if (text.Length() > 0 && wxTheClipboard->Open())
{
wxTheClipboard->SetData(new wxTextDataObject(wxTextBuffer::Translate(text)));
wxTheClipboard->Close();
}
}
void frmMain::GetExpandedChildNodes(wxTreeItemId node, wxArrayString &expandedNodes)
{
wxTreeItemIdValue cookie;
wxTreeItemId child = browser->GetFirstChild(node, cookie);
while (child.IsOk())
{
if (browser->IsExpanded(child))
{
GetExpandedChildNodes(child, expandedNodes);
expandedNodes.Add(GetNodePath(child));
}
child = browser->GetNextChild(node, cookie);
}
}
void frmMain::ExpandChildNodes(wxTreeItemId node, wxArrayString &expandedNodes)
{
wxTreeItemIdValue cookie;
wxTreeItemId child = browser->GetFirstChild(node, cookie);
while (child.IsOk())
{
if (expandedNodes.Index(GetNodePath(child)) != wxNOT_FOUND)
{
browser->Expand(child);
ExpandChildNodes(child, expandedNodes);
}
child = browser->GetNextChild(node, cookie);
}
}
wxString frmMain::GetNodePath(wxTreeItemId node)
{
wxString path;
path = browser->GetItemText(node).BeforeFirst('(').Trim();
wxTreeItemId parent = browser->GetItemParent(node);
while (parent.IsOk())
{
path = browser->GetItemText(parent).BeforeFirst('(').Trim() + wxT("/") + path;
parent = browser->GetItemParent(parent);
}
return path;
}
// Return the path for the current node
wxString frmMain::GetCurrentNodePath()
{
return GetNodePath(currentObject->GetId());
}
// Attempt to reselect the node with the given path
bool frmMain::SetCurrentNode(wxTreeItemId node, const wxString &origPath)
{
wxString path = origPath.Lower();
wxTreeItemIdValue cookie;
wxTreeItemId child = browser->GetFirstChild(node, cookie);
while (child.IsOk())
{
wxString actNodePath = GetNodePath(child).Lower();
if(path.StartsWith(actNodePath))
{
if(!browser->IsExpanded(child))
{
browser->SelectItem(child, true);
browser->Expand(child);
}
if (actNodePath == path)
{
browser->SelectItem(child, true);
return true;
}
else if (SetCurrentNode(child, path))
return true;
}
child = browser->GetNextChild(node, cookie);
}
return false;
}
void frmMain::ShowObjStatistics(pgObject *data, wxWindow *ctrl)
{
// Refresh panes if they're currently shown on screen, unless
// they've been specifically requested (eg. a notebook
// event is telling us they're about to become visible).
if ((!ctrl && statistics->IsShownOnScreen()) || ctrl == statistics)
{
statistics->Freeze();
data->ShowStatistics(this, statistics);
statistics->Thaw();
}
if ((!ctrl && dependencies->IsShownOnScreen()) || ctrl == dependencies)
{
dependencies->Freeze();
data->ShowDependencies(this, dependencies);
dependencies->Thaw();
}
if ((!ctrl && dependents->IsShownOnScreen()) || ctrl == dependents)
{
dependents->Freeze();
data->ShowDependents(this, dependents);
dependents->Thaw();
}
#if !defined(NO_WXJSON_GIT)
#if wxUSE_WEBREQUEST
if ((!ctrl && git && git->IsShownOnScreen()) || ctrl == git)
{
//data->ShowDependents(this, dependents);
if (git && data) git->ShowPage(data);
}
#endif
#endif
}
// Ensure we show the data in any tabs that become visible
void frmMain::OnPageChange(wxAuiNotebookEvent &event)
{
pgObject *data = browser->GetObject(browser->GetSelection());
if (!data)
return;
ShowObjStatistics(data, ((wxAuiNotebook *)event.GetEventObject())->GetPage(event.GetSelection()));
}
ctlListView *frmMain::GetStatistics()
{
return statistics;
}
ctlListView *frmMain::GetDependencies()
{
return dependencies;
}
ctlListView *frmMain::GetReferencedBy()
{
return dependents;
}
bool frmMain::CheckAlive()
{
bool userInformed = false;
bool closeIt = false;
wxTreeItemIdValue foldercookie;
wxTreeItemId folderitem = browser->GetFirstChild(browser->GetRootItem(), foldercookie);
while (folderitem)
{
if (browser->ItemHasChildren(folderitem))
{
wxCookieType cookie;
wxTreeItemId serverItem = browser->GetFirstChild(folderitem, cookie);
while (serverItem)
{
pgServer *server = (pgServer *)browser->GetObject(serverItem);
if (server && server->IsCreatedBy(serverFactory) && server->connection())
{
if (server->connection()->IsAlive())
{
wxCookieType cookie2;
wxTreeItemId item = browser->GetFirstChild(serverItem, cookie2);
while (item)
{
pgObject *obj = browser->GetObject(item);
if (obj && obj->IsCreatedBy(databaseFactory.GetCollectionFactory()))
{
wxCookieType cookie3;
item = browser->GetFirstChild(obj->GetId(), cookie3);
while (item)
{
pgDatabase *db = (pgDatabase *)browser->GetObject(item);
if (db && db->IsCreatedBy(databaseFactory))
{
pgConn *conn = db->GetConnection();
if (conn)
{
if (!conn->IsAlive() && (conn->GetStatus() == PGCONN_BROKEN || conn->GetStatus() == PGCONN_BAD))
{
conn->Close();
if (!userInformed)
{
wxMessageDialog dlg(this, _("Do you want to attempt to reconnect to the database?"),
wxString::Format(_("Connection to database %s lost."), db->GetName().c_str()),
wxICON_EXCLAMATION | wxYES_NO | wxYES_DEFAULT);
closeIt = (dlg.ShowModal() != wxID_YES);
userInformed = true;
}
if (closeIt)
{
db->Disconnect();
browser->DeleteChildren(db->GetId());
db->UpdateIcon(browser);
}
else
{
// Create a server object and connect it.
wxBusyInfo waiting(wxString::Format(_("Reconnecting to database %s"),
db->GetName().c_str()), this);
// Give the UI a chance to redraw
wxSafeYield();
wxMilliSleep(100);
wxSafeYield();
if (!conn->Reconnect())
{
db->Disconnect();
browser->DeleteChildren(db->GetId());
db->UpdateIcon(browser);
}
else
// Indicate things are back to normal
userInformed = false;
}
}
}
}
item = browser->GetNextChild(obj->GetId(), cookie3);
}
}
item = browser->GetNextChild(serverItem, cookie2);
}
}
else
{
if (server->connection()->GetStatus() == PGCONN_BROKEN || server->connection()->GetStatus() == PGCONN_BAD)
{
server->connection()->Close();
if (!userInformed)
{
wxMessageDialog dlg(this, _("Do you want to attempt to reconnect to the server?"),
wxString::Format(_("Connection to server %s lost."), server->GetName().c_str()),
wxICON_EXCLAMATION | wxYES_NO | wxYES_DEFAULT);
closeIt = (dlg.ShowModal() != wxID_YES);
userInformed = true;
}
if (closeIt)
{
server->Disconnect(this);
browser->SelectItem(serverItem);
execSelChange(serverItem, true);
browser->DeleteChildren(serverItem);
}
else
{
// Create a server object and connect it.
wxBusyInfo waiting(wxString::Format(_("Reconnecting to server %s (%s:%d)"),
server->GetDescription().c_str(), server->GetName().c_str(), server->GetPort()), this);
// Give the UI a chance to redraw
wxSafeYield();
wxMilliSleep(100);
wxSafeYield();
if (!server->connection()->Reconnect())
{
server->Disconnect(this);
browser->SelectItem(serverItem);
execSelChange(serverItem, true);
browser->DeleteChildren(serverItem);
}
else
// Indicate things are back to normal
userInformed = false;
}
}
}
}
serverItem = browser->GetNextChild(folderitem, cookie);
}
}
folderitem = browser->GetNextChild(browser->GetRootItem(), foldercookie);
}
return userInformed;
}
wxTreeItemId frmMain::RestoreEnvironment(pgServer *server)
{
wxTreeItemId item, lastItem;
wxString lastDatabase = server->GetLastDatabase();
if (lastDatabase.IsNull())
return item;
wxCookieType cookie;
pgObject *data = 0;
item = browser->GetFirstChild(server->GetId(), cookie);
while (item)
{
data = browser->GetObject(item);
if (data && data->IsCreatedBy(databaseFactory.GetCollectionFactory()))
break;
// Get the next item
item = browser->GetNextChild(server->GetId(), cookie);
}
if (!item)
return item;
// found DATABASES item
listViews->SetSelection(NBP_PROPERTIES);
data->ShowTree(this, browser, 0, 0);
lastItem = item;
item = browser->GetFirstChild(lastItem, cookie);
while (item)
{
data = browser->GetObject(item);
if (data && data->IsCreatedBy(databaseFactory) && data->GetName() == lastDatabase)
break;
// Get the next item
item = browser->GetNextChild(lastItem, cookie);
}
if (!item)
return lastItem;
// found last DATABASE
data->ShowTree(this, browser, 0, 0);
lastItem = item;
wxString lastSchema = server->GetLastSchema();
if (lastSchema.IsNull())
return lastItem;
item = browser->GetFirstChild(lastItem, cookie);
while (item)
{
data = browser->GetObject(item);
if (data && data->GetMetaType() == PGM_SCHEMA)
break;
// Get the next item
item = browser->GetNextChild(lastItem, cookie);
}
if (!item)
return lastItem;
// found SCHEMAS item
data->ShowTree(this, browser, 0, 0);
lastItem = item;
item = browser->GetFirstChild(lastItem, cookie);
while (item)
{
data = browser->GetObject(item);
if (data && data->GetMetaType() == PGM_SCHEMA && data->GetName() == lastSchema)
break;
// Get the next item
item = browser->GetNextChild(lastItem, cookie);
}
return (item ? item : lastItem);
}
int frmMain::ReconnectServer(pgServer *server, bool restore)
{
if (server->GetPuttyTunnel()) {
// check open port
int port=server->GetPort();
wxString localhost=server->GetName(); // localhost
if (!isPortOpen(localhost,port,500)) {
server->GetPuttyTunnel()->StartDialog(winMain, server); // execute plugin
int count=0;
do {
wxMilliSleep(200);
count++;
} while (!isPortOpen(localhost,port,500) && count<20); // wait create putty tunnel
if (count>=20) {
StartMsg(_("Create putty tunnel error."));
EndMsg(true);
return -1;
}
}
}
// Create a server object and connect it.
wxBusyInfo waiting(wxString::Format(_("Connecting to server %s (%s:%d)"),
server->GetDescription().c_str(), server->GetName().c_str(), server->GetPort()), this);
// Give the UI a chance to redraw
wxSafeYield();
wxMilliSleep(100);
wxSafeYield();
int res = server->Connect(this, true, wxEmptyString, false, true);
// Check the result, and handle it as appropriate
wxTreeItemId item;
switch (res)
{
case PGCONN_OK:
{
if (restore && server->GetRestore())
StartMsg(_("Restoring previous environment"));
else
StartMsg(_("Establishing connection"));
wxLogInfo(wxT("pgServer object initialised as required."));
server->ShowTreeDetail(browser);
browser->Freeze();
if (restore && server->GetRestore())
item = RestoreEnvironment(server);
else
item = server->GetId();
browser->Thaw();
if (item)
{
browser->SelectItem(item);
wxSafeYield();
browser->Expand(item);
browser->EnsureVisible(item);
}
if (item)
EndMsg(true);
else
{
if (restore && server->GetRestore())
EndMsg(false);
else
EndMsg(true);
}
if (item)
GetMenuFactories()->CheckMenu((pgObject *)browser->GetItemData(item), GetMenuBar(), (ctlMenuToolbar *)GetToolBar());
else
GetMenuFactories()->CheckMenu(server, GetMenuBar(), (ctlMenuToolbar *)GetToolBar());
browser->SetFocus();
return res;
}
case PGCONN_DNSERR:
/*
// looks strange to me. Shouldn_t server be removed from the tree as well?
delete server;
OnAddServer(wxCommandEvent());
break;
*/
case PGCONN_BAD:
ReportConnError(server);
break;
default:
wxLogInfo(wxT("pgServer object didn't initialise because the user aborted."));
break;
}
server->Disconnect(this);
return res;
}
bool frmMain::reportError(const wxString &error, const wxString &msgToIdentify, const wxString &hint)
{
bool identified = false;
wxString translated = wxGetTranslation(msgToIdentify);
if (translated != msgToIdentify)
{
identified = (error.Find(translated) >= 0);
}
if (!identified)
{
if (msgToIdentify.Left(20) == wxT("Translator attention"))
identified = (error.Find(msgToIdentify.Mid(msgToIdentify.Find('!') + 1)) >= 0);
else
identified = (error.Find(msgToIdentify) >= 0);
}
if (identified)
{
if (frmHint::WantHint(hint))
frmHint::ShowHint(this, hint, error);
}
return identified;
}
void frmMain::ReportConnError(pgServer *server)
{
wxString error = server->GetLastError();
bool wantHint = false;
wantHint = reportError(error, __("Translator attention: must match libpq translation!Is the server running on host"), HINT_CONNECTSERVER);
if (!wantHint)
{
wantHint = reportError(error, __("Translator attention: must match backend translation!no pg_hba.conf entry for"), HINT_MISSINGHBA);
}
if (!wantHint)
{
wantHint = reportError(error, __("Translator attention: must match backend translation!Ident authentication failed"), HINT_MISSINGIDENT);
}
if (!wantHint)
{
wxLogError(__("Error connecting to the server: %s"), error.c_str());
}
}
void frmMain::StoreServers()
{
wxLogInfo(wxT("Storing listed servers for later..."));
// Store the currently listed servers for later retrieval.
pgServer *server;
int numServers = 0;
// Get the hostname for later...
char buf[255];
gethostname(buf, 255);
wxString hostname = wxString(buf, wxConvUTF8);
wxTreeItemIdValue foldercookie;
wxTreeItemId folderitem = browser->GetFirstChild(browser->GetRootItem(), foldercookie);
wxTreeItemId cursoritem = browser->GetSelection();
while (cursoritem.IsOk()) {
server = (pgServer *)browser->GetItemData(cursoritem);
if (server != NULL && server->IsCreatedBy(serverFactory)) {
break;
}
cursoritem=browser->GetItemParent(cursoritem);
}
wxString selServerName;
while (folderitem)
{
if (browser->ItemHasChildren(folderitem))
{
wxTreeItemIdValue servercookie;
wxTreeItemId serveritem = browser->GetFirstChild(folderitem, servercookie);
while (serveritem)
{
server = (pgServer *)browser->GetItemData(serveritem);
if (server != NULL && server->IsCreatedBy(serverFactory))
{
wxString key;
++numServers;
if (cursoritem==serveritem) selServerName=browser->GetItemText((serveritem));
key.Printf(wxT("Servers/%d/"), numServers);
settings->Write(key + wxT("Server"), server->GetName());
settings->Write(key + wxT("HostAddr"), server->GetHostAddr());
settings->Write(key + wxT("Description"), server->GetDescription());
settings->Write(key + wxT("Keywords"), server->GetKeywords());
settings->Write(key + wxT("Service"), server->GetService());
settings->Write(key + wxT("ServiceID"), server->GetServiceID());
settings->Write(key + wxT("DiscoveryID"), server->GetDiscoveryID());
settings->WriteInt(key + wxT("Port"), server->GetPort());
settings->WriteBool(key + wxT("StorePwd"), server->GetStorePwd());
settings->Write(key + wxT("Rolename"), server->GetRolename());
settings->Write(key + wxT("ConnStr"), server->GetConnStr());
settings->WriteBool(key + wxT("Restore"), server->GetRestore());
settings->Write(key + wxT("Database"), server->GetDatabaseName());
settings->Write(key + wxT("Username"), server->GetUsername());
settings->Write(key + wxT("LastDatabase"), server->GetLastDatabase());
settings->Write(key + wxT("LastSchema"), server->GetLastSchema());
settings->Write(key + wxT("DbRestriction"), server->GetDbRestriction());
settings->Write(key + wxT("Colour"), server->GetColour());
settings->WriteInt(key + wxT("SSL"), server->GetSSL());
settings->Write(key + wxT("Group"), server->GetGroup());
settings->Write(key + wxT("SSLCert"), server->GetSSLCert());
settings->Write(key + wxT("SSLKey"), server->GetSSLKey());
settings->Write(key + wxT("SSLRootCert"), server->GetSSLRootCert());
settings->Write(key + wxT("SSLCrl"), server->GetSSLCrl());
settings->WriteBool(key + wxT("SSLCompression"), server->GetSSLCompression());
#if defined(HAVE_OPENSSL_CRYPTO) || defined(HAVE_GCRYPT)
settings->WriteBool(key + wxT("SSHTunnel"), server->GetSSHTunnel());
settings->Write(key + wxT("TunnelHost"), server->GetTunnelHost());
settings->Write(key + wxT("TunnelUserName"), server->GetTunnelUserName());
settings->WriteBool(key + wxT("TunnelModePwd"), server->GetAuthModePwd());
settings->Write(key + wxT("PublicKeyFile"), server->GetPublicKeyFile());
settings->Write(key + wxT("IdentityFile"), server->GetIdentityFile());
settings->WriteInt(key + wxT("TunnelPort"), server->GetTunnelPort());
#endif
pgCollection *coll = browser->FindCollection(databaseFactory, server->GetId());
if (coll)
{
treeObjectIterator dbs(browser, coll);
pgDatabase *db;
while ((db = (pgDatabase *)dbs.GetNextObject()) != 0)
settings->Write(key + wxT("Databases/") + db->GetName() + wxT("/SchemaRestriction"), db->GetSchemaRestriction());
}
}
serveritem = browser->GetNextChild(folderitem, servercookie);
}
}
folderitem = browser->GetNextChild(browser->GetRootItem(), foldercookie);
}
// Write the server count
settings->WriteInt(wxT("Servers/Count"), numServers);
settings->Write(wxT("Servers/SelectItem"), selServerName);
settings->FlushChanges();
wxLogInfo(wxT("Stored %d servers."), numServers);
}
void frmMain::RetrieveServers()
{
wxString label;
int total = 0;
wxTreeItemIdValue groupcookie;
wxTreeItemId groupitem;
// Retrieve previously stored servers
wxLogInfo(wxT("Reloading servers..."));
// Create all servers' nodes
serverFactory.CreateObjects(serversObj, browser);
// Count number of servers and groups
groupitem = browser->GetFirstChild(browser->GetRootItem(), groupcookie);
while (groupitem)
{
total = browser->GetChildrenCount(groupitem, false);
label = browser->GetItemText(groupitem) + wxT(" (") + NumToStr((long)total) + wxT(")");
browser->SetItemText(groupitem, label);
browser->SortChildren(groupitem);
browser->Expand(groupitem);
groupitem = browser->GetNextChild(browser->GetRootItem(), groupcookie);
}
}
pgServer *frmMain::ConnectToServer(const wxString &servername, bool restore)
{
wxTreeItemIdValue foldercookie, servercookie;
wxTreeItemId folderitem, serveritem;
pgObject *object;
pgServer *server;
folderitem = browser->GetFirstChild(browser->GetRootItem(), foldercookie);
while (folderitem)
{
if (browser->ItemHasChildren(folderitem))
{
serveritem = browser->GetFirstChild(folderitem, servercookie);
while (serveritem)
{
object = browser->GetObject(serveritem);
if (object && object->IsCreatedBy(serverFactory))
{
server = (pgServer *)object;
if (server->GetDescription() == servername)
{
ReconnectServer(server, restore);
return server;
}
}
serveritem = browser->GetNextChild(folderitem, servercookie);
}
}
folderitem = browser->GetNextChild(browser->GetRootItem(), foldercookie);
}
return 0;
}
void frmMain::StartMsg(const wxString &msg)
{
if (msgLevel++)
return;
timermsg.Printf(wxT("%s..."), msg.c_str());
wxBeginBusyCursor();
stopwatch.Start(0);
// Create a copy of the message, with %'s escaped for wxLogStatus
wxString logmsg = timermsg;
logmsg.Replace(wxT("%"), wxT("%%"));
wxLogStatus(logmsg);
statusBar->SetStatusText(timermsg, 1);
statusBar->SetStatusText(wxT(""), 2);
}
void frmMain::EndMsg(bool done)
{
msgLevel--;
if (!msgLevel)
{
// Get the execution time & display it
float timeval = stopwatch.Time();
statusBar->SetStatusText(ElapsedTimeToStr(timeval), 3);
// Display the name of the connection for currently selected object
wxString connection;
if (currentObject)
{
pgConn *conn = currentObject->GetConnection();
if (conn)
connection = conn->GetName();
}
statusBar->SetStatusText(connection, 2);
// Display the 'Done' message
if (done)
statusBar->SetStatusText(timermsg + _(" Done."), 1);
else
statusBar->SetStatusText(timermsg + _(" Failed."), 1);
wxLogStatus(
wxT("%s (%s)"), timermsg.c_str(),
ElapsedTimeToStr(timeval).c_str()
);
wxEndBusyCursor();
}
}
void frmMain::SetStatusText(const wxString &msg)
{
statusBar->SetStatusText(msg, 1);
statusBar->SetStatusText(wxEmptyString, 2);
}
void frmMain::SetItemBackgroundColour(wxTreeItemId item, wxColour colour)
{
wxTreeItemIdValue cookie;
browser->SetItemBackgroundColour(item, wxColour(colour));
if (browser->ItemHasChildren(item))
{
wxTreeItemId childitem = browser->GetFirstChild(item, cookie);
while (childitem)
{
SetItemBackgroundColour(childitem, colour);
childitem = browser->GetNextChild(item, cookie);
}
}
}
#if defined(HAVE_OPENSSL_CRYPTO) || defined(HAVE_GCRYPT)
void frmMain::OnSSHTunnelEvent(wxCommandEvent &event)
{
wxLogError(event.GetString());
}
#endif
/////////////////////////////////////////
contentsFactory::contentsFactory(menuFactoryList *list, wxMenu *mnu, ctlMenuToolbar *toolbar) : actionFactory(list)
{
mnu->Append(id, _("&Help contents"), _("Open the helpfile."));
}
wxWindow *contentsFactory::StartDialog(frmMain *form, pgObject *obj)
{
DisplayHelp(wxT("index"), HELP_PGADMIN);
return 0;
}
faqFactory::faqFactory(menuFactoryList *list, wxMenu *mnu, ctlMenuToolbar *toolbar) : actionFactory(list)
{
mnu->Append(id, _("&FAQ"), _("Frequently asked questions."));
}
wxWindow *faqFactory::StartDialog(frmMain *form, pgObject *obj)
{
wxLaunchDefaultBrowser(wxT("https://github.com/levinsv/pgadmin3/issues"));
return 0;
}
#include "images/help.pngc"
#include "images/help2.pngc"
pgsqlHelpFactory::pgsqlHelpFactory(menuFactoryList *list, wxMenu *mnu, ctlMenuToolbar *toolbar, bool bigIcon) : actionFactory(list)
{
mnu->Append(id, _("&PostgreSQL Help"), _("Display help on the PostgreSQL database system."));
if (toolbar)
{
if (bigIcon)
toolbar->AddTool(id, wxEmptyString, GetBundleSVG(help2_png_bmp, "help2.svg", wxSize(32, 32)), _("Display help on SQL commands."));
else
toolbar->AddTool(id, wxEmptyString, *help_png_bmp, _("Display help on SQL commands."));
}
}
wxWindow *pgsqlHelpFactory::StartDialog(frmMain *form, pgObject *obj)
{
DisplayHelp(wxT("index"), HELP_POSTGRESQL);
return 0;
}
edbHelpFactory::edbHelpFactory(menuFactoryList *list, wxMenu *mnu, ctlMenuToolbar *toolbar, bool bigIcon) : actionFactory(list)
{
mnu->Append(id, _("&EnterpriseDB Help"), _("Display help on the EnterpriseDB database system."));
}
wxWindow *edbHelpFactory::StartDialog(frmMain *form, pgObject *obj)
{
DisplayHelp(wxT("index"), HELP_ENTERPRISEDB);
return 0;
}
greenplumHelpFactory::greenplumHelpFactory(menuFactoryList *list, wxMenu *mnu, ctlMenuToolbar *toolbar, bool bigIcon) : actionFactory(list)
{
mnu->Append(id, _("&Greenplum Database Help"), _("Display help on the Greenplum Database system."));
}
wxWindow *greenplumHelpFactory::StartDialog(frmMain *form, pgObject *obj)
{
DisplayHelp(wxT("index"), HELP_GREENPLUM);
return 0;
}
slonyHelpFactory::slonyHelpFactory(menuFactoryList *list, wxMenu *mnu, ctlMenuToolbar *toolbar, bool bigIcon) : actionFactory(list)
{
mnu->Append(id, _("&Slony Help"), _("Display help on the Slony replication system."));
}
wxWindow *slonyHelpFactory::StartDialog(frmMain *form, pgObject *obj)
{
DisplayHelp(wxT("index"), HELP_SLONY);
return 0;
}
bugReportFactory::bugReportFactory(menuFactoryList *list, wxMenu *mnu, ctlMenuToolbar *toolbar) : actionFactory(list)
{
mnu->Append(id, _("&Bug Report"), _("How to send a bugreport to the pgAdmin Development Team."));
}
wxWindow *bugReportFactory::StartDialog(frmMain *form, pgObject *obj)
{
DisplayHelp(wxT("bugreport"), HELP_PGADMIN);
return 0;
}