pgadmin3/dlg/dlgSelectConnection.cpp
lsv 81a8417e77 Server groups have been added to the connection selection dialog.
Добавлен список групп серверов, для упрощения поиска нужного соединения.
2026-03-18 15:17:27 +05:00

434 lines
12 KiB
C++

//////////////////////////////////////////////////////////////////////////
//
// pgAdmin III - PostgreSQL Tools
//
// Copyright (C) 2002 - 2016, The pgAdmin Development Team
// This software is released under the PostgreSQL Licence
//
// dlgSelectConnection.cpp - Connect to a database
//
//////////////////////////////////////////////////////////////////////////
// App headers
#include "pgAdmin3.h"
// wxWindows headers
#include <wx/wx.h>
#include <wx/bmpcbox.h>
// App headers
#include "frm/frmMain.h"
#include "dlg/dlgSelectConnection.h"
#include "dlg/dlgConnect.h"
#include "schema/pgServer.h"
#include "images/connect.pngc"
#define CTRLID_CBSERVER 4242
#define CTRLID_CBDATABASE 4243
#define CTRLID_CBUSERNAME 4244
#define CTRLID_CBROLENAME 4245
#define CTRLID_CBGROUP 4246
BEGIN_EVENT_TABLE(dlgSelectConnection, DialogWithHelp)
EVT_COMBOBOX(CTRLID_CBGROUP, dlgSelectConnection::OnChangeGroup)
EVT_COMBOBOX(CTRLID_CBSERVER, dlgSelectConnection::OnChangeServer)
EVT_COMBOBOX(CTRLID_CBDATABASE, dlgSelectConnection::OnChangeDatabase)
EVT_TEXT(CTRLID_CBSERVER, dlgSelectConnection::OnTextChange)
EVT_TEXT(CTRLID_CBDATABASE, dlgSelectConnection::OnTextChange)
EVT_TEXT(CTRLID_CBUSERNAME, dlgSelectConnection::OnTextChange)
EVT_BUTTON (wxID_OK, dlgSelectConnection::OnOK)
EVT_BUTTON (wxID_CANCEL, dlgSelectConnection::OnCancel)
END_EVENT_TABLE()
#define stUsername CTRL_STATIC("stUsername")
dlgSelectConnection::dlgSelectConnection(wxWindow *parent, frmMain *form) :
DialogWithHelp(form)
{
long style = wxCB_DROPDOWN;
remoteServer = NULL;
SetFont(settings->GetSystemFont());
LoadResource(parent, wxT("dlgSelectConnection"));
SetIcon(*connect_png_ico);
RestorePosition();
if (form != NULL)
style |= wxCB_READONLY;
cbGroup = new wxComboBox(this, CTRLID_CBGROUP, wxEmptyString, ConvertDialogToPixels(wxPoint(70, 5)), ConvertDialogToPixels(wxSize(135, 12)), wxArrayString(), style);
cbServer = new ctlComboBoxFix(this, CTRLID_CBSERVER, ConvertDialogToPixels(wxPoint(70, 20)), ConvertDialogToPixels(wxSize(135, 12)), style);
cbDatabase = new wxComboBox(this, CTRLID_CBDATABASE, wxEmptyString, ConvertDialogToPixels(wxPoint(70, 35)), ConvertDialogToPixels(wxSize(135, 12)), wxArrayString(), style);
cbUsername = new wxComboBox(this, CTRLID_CBUSERNAME, wxEmptyString, ConvertDialogToPixels(wxPoint(70, 50)), ConvertDialogToPixels(wxSize(135, 12)), wxArrayString(), style);
cbRolename = new wxComboBox(this, CTRLID_CBROLENAME, wxEmptyString, ConvertDialogToPixels(wxPoint(70, 75)), ConvertDialogToPixels(wxSize(135, 12)), wxArrayString(), style);
if (form == NULL)
{
cbServer->SetValue(settings->Read(wxT("QuickConnect/server"), wxEmptyString));
cbGroup->SetValue(settings->Read(wxT("QuickConnect/group"), wxEmptyString));
cbDatabase->SetValue(settings->Read(wxT("QuickConnect/database"), wxEmptyString));
cbUsername->SetValue(settings->Read(wxT("QuickConnect/username"), wxEmptyString));
cbRolename->SetValue(settings->Read(wxT("QuickConnect/rolename"), wxEmptyString));
} else {
wxTreeItemIdValue foldercookie, servercookie;
wxTreeItemId folderitem, serveritem;
ctlTree *browser = mainForm->GetBrowser();
folderitem = browser->GetFirstChild(browser->GetRootItem(), foldercookie);
cbGroup->Append("");
while (folderitem)
{
wxString grp=browser->GetItemText(folderitem);
cbGroup->Append(grp);
folderitem = browser->GetNextChild(browser->GetRootItem(), foldercookie);
}
}
btnOK->Enable(cbServer->GetValue().Length() > 0 && cbDatabase->GetValue().Length() > 0 && cbUsername->GetValue().Length() > 0);
}
dlgSelectConnection::~dlgSelectConnection()
{
SavePosition();
}
wxString dlgSelectConnection::GetHelpPage() const
{
return wxT("connect");
}
void dlgSelectConnection::OnChangeGroup(wxCommandEvent &ev)
{
int sel = cbGroup->GetCurrentSelection();
if (sel >= 0)
{
bool found=BuildServerCombo(currconn);
if (!found) cbServer->SetSelection(0);
OnChangeServer(ev);
}
}
void dlgSelectConnection::OnChangeServer(wxCommandEvent &ev)
{
int item;
wxString olddatabase, oldusername;
if (!GetServer())
return;
// Keep old value for these comboboxes so that we can restore them if needed
olddatabase = cbDatabase->GetValue();
oldusername = cbUsername->GetValue();
// Clear the comboboxes
cbDatabase->Clear();
cbUsername->Clear();
cbRolename->Clear();
int sel = cbServer->GetCurrentSelection();
if (sel >= 0)
{
remoteServer = (pgServer *)cbServer->wxItemContainer::GetClientData(sel);
if (!remoteServer->GetConnected())
{
remoteServer->Connect(mainForm, remoteServer->GetStorePwd());
if (!remoteServer->GetConnected())
{
wxLogError(wxT("%s"), remoteServer->GetLastError().c_str());
return;
}
}
if (remoteServer->GetConnected())
{
pgSetIterator set1(remoteServer->GetConnection(),
wxT("SELECT DISTINCT datname\n")
wxT(" FROM pg_database db\n")
wxT(" WHERE datallowconn ORDER BY datname"));
item = 0;
int item2 = -1;
wxString v;
while(set1.RowsLeft())
{
v = set1.GetVal(wxT("datname"));
cbDatabase->Append(v);
if (v == olddatabase)
item = cbDatabase->GetCount() - 1;
else if (v.StartsWith("template") || v == "postgres")
continue;
else if (item2 == -1)
item2 = cbDatabase->GetCount() - 1;
}
if (cbDatabase->GetCount())
if (item2>=0)
{cbDatabase->SetSelection(item2);}
else
{cbDatabase->SetSelection(item);}
pgSetIterator set2(remoteServer->GetConnection(),
wxT("SELECT DISTINCT usename\n")
wxT("FROM pg_user db\n")
wxT("ORDER BY usename"));
item = 0;
while(set2.RowsLeft())
{
cbUsername->Append(set2.GetVal(wxT("usename")));
if (set2.GetVal(wxT("usename")) == oldusername)
item = cbUsername->GetCount() - 1;
}
if (cbUsername->GetCount())
cbUsername->SetSelection(item);
if (remoteServer->GetConnection()->BackendMinimumVersion(8, 1))
{
pgSetIterator set3(remoteServer->GetConnection(),
wxT("SELECT DISTINCT rolname\n")
wxT("FROM pg_roles db\n")
wxT("ORDER BY rolname"));
cbRolename->Append(wxEmptyString);
while(set3.RowsLeft())
cbRolename->Append(set3.GetVal(wxT("rolname")));
cbRolename->Enable(true);
}
else
cbRolename->Disable();
cbRolename->SetValue(wxEmptyString);
}
}
OnChangeDatabase(ev);
}
wxString dlgSelectConnection::GetDatabase()
{
return cbDatabase->GetValue();
}
wxString dlgSelectConnection::GetServerName()
{
return cbServer->GetValue();
}
void dlgSelectConnection::OnChangeDatabase(wxCommandEvent &ev)
{
btnOK->Enable(cbServer->GetValue().Length() > 0 && cbDatabase->GetValue().Length() > 0 && cbUsername->GetValue().Length() > 0);
}
void dlgSelectConnection::OnTextChange(wxCommandEvent &ev)
{
btnOK->Enable(cbServer->GetValue().Length() > 0 && cbDatabase->GetValue().Length() > 0 && cbUsername->GetValue().Length() > 0);
}
void dlgSelectConnection::OnOK(wxCommandEvent &ev)
{
#ifdef __WXGTK__
if (!btnOK->IsEnabled())
return;
#endif
if (cbDatabase->GetCurrentSelection() == wxNOT_FOUND ||
cbServer->GetCurrentSelection() == wxNOT_FOUND)
remoteServer = NULL;
EndModal(wxID_OK);
}
void dlgSelectConnection::OnCancel(wxCommandEvent &ev)
{
EndModal(wxID_CANCEL);
}
pgConn *dlgSelectConnection::CreateConn(wxString &applicationname, bool &createdNew)
{
/* gcc requires that we store this in temporary variables for some reason... */
wxString serv = cbServer->GetValue();
wxString db = cbDatabase->GetValue();
createdNew = true;
long port = 0;
if (serv.Find(':') > 0)
{
if (!serv.Mid(serv.Find(':') + 1).ToLong(&port))
{
wxMessageBox(_("Invalid port number specified."));
return NULL;
}
serv = serv.Mid(0, serv.Find(':'));
}
wxString user = cbUsername->GetValue();
wxString role = cbRolename->GetValue();
if (cbConnection)
{
/* Check if selected combination already exists */
for (unsigned int index = 0; index < cbConnection->GetCount() - 1; index++)
{
pgConn *conn = (pgConn *)cbConnection->GetClientData(index);
if (conn &&
conn->GetHost() == serv &&
conn->GetPort() == port &&
conn->GetUser() == user &&
conn->GetRole() == role &&
conn->GetDbname() == db)
{
createdNew = false;
return conn;
}
}
}
int sslmode = remoteServer ? remoteServer->GetSSL() : 0;
wxString addconnstr;
if (remoteServer) {
addconnstr = remoteServer->GetConnStr();
}
return CreateConn(serv, db, user, port, role, addconnstr, sslmode, applicationname, true);
}
pgConn *dlgSelectConnection::CreateConn(wxString &server, wxString &dbname, wxString &username, int port, wxString &rolename, wxString &addconnstr, int sslmode, wxString &applicationname, bool writeMRU)
{
pgConn *newconn;
newconn = new pgConn(server, wxEmptyString, wxEmptyString, dbname, username, wxT(""), port, rolename, addconnstr, sslmode, 0, applicationname);
if (newconn->GetStatus() != PGCONN_OK &&
newconn->GetLastError().Cmp(wxString(PQnoPasswordSupplied, wxConvUTF8)) == 0)
{
/* Needs password */
delete newconn;
newconn = NULL;
wxString txt;
txt.Printf(_("Please enter password for user %s\non server %s"), username.c_str(), server.c_str());
dlgConnect dlg(NULL, txt, false);
if (dlg.Go() != wxID_OK)
return NULL;
newconn = new pgConn(server, wxEmptyString, wxEmptyString, dbname, username, dlg.GetPassword(), port, rolename, addconnstr, sslmode, 0, applicationname);
}
if (newconn)
{
if (newconn->GetStatus() != PGCONN_OK)
{
wxMessageBox(wxT("Connection failed: ") + newconn->GetLastError());
return NULL;
}
if (writeMRU)
{
settings->Write(wxT("QuickConnect/server"), cbServer->GetValue());
settings->Write(wxT("QuickConnect/group"), cbGroup->GetValue());
settings->Write(wxT("QuickConnect/database"), cbDatabase->GetValue());
settings->Write(wxT("QuickConnect/username"), cbUsername->GetValue());
settings->Write(wxT("QuickConnect/rolename"), cbRolename->GetValue());
}
}
return newconn;
}
bool dlgSelectConnection::BuildServerCombo(pgConn *conn) {
bool foundServer = false;
if (mainForm != NULL)
{
ctlTree *browser = mainForm->GetBrowser();
wxTreeItemIdValue foldercookie, servercookie;
wxTreeItemId folderitem, serveritem;
pgObject *object;
pgServer *server;
wxString grp;
cbServer->Clear();
if (cbGroup->GetCurrentSelection() != wxNOT_FOUND) {
grp=cbGroup->GetValue();
}
folderitem = browser->GetFirstChild(browser->GetRootItem(), foldercookie);
while (folderitem)
{
bool isGroup=true;
if (grp.Length()>0)
if (browser->GetItemText(folderitem)!=grp ) isGroup=false;
if (browser->ItemHasChildren(folderitem) && isGroup)
{
serveritem = browser->GetFirstChild(folderitem, servercookie);
while (serveritem)
{
object = browser->GetObject(serveritem);
if (object && object->IsCreatedBy(serverFactory))
{
server = (pgServer *)object;
cbServer->Append(server->GetIdentifier(), (void *)server);
if (server->GetConnected() &&
server->GetConnection()->GetHost() == conn->GetHost() &&
server->GetConnection()->GetPort() == conn->GetPort())
{
cbServer->SetSelection(cbServer->GetCount() - 1);
remoteServer = server;
foundServer = true;
}
}
serveritem = browser->GetNextChild(folderitem, servercookie);
}
}
folderitem = browser->GetNextChild(browser->GetRootItem(), foldercookie);
}
}
cbServer->SetFocus();
wxCommandEvent ev;
OnChangeServer(ev);
if (foundServer)
{
unsigned int index = 0;
for (; index < cbDatabase->GetCount(); index++)
{
if (cbDatabase->GetString(index) == conn->GetDbname())
{
cbDatabase->SetSelection(index);
break;
}
}
for (index = 0; index < cbUsername->GetCount(); index++)
{
if (cbUsername->GetString(index) == conn->GetUser())
{
cbUsername->SetSelection(index);
break;
}
}
for (index = 0; index < cbRolename->GetCount(); index++)
{
if (cbRolename->GetString(index) == conn->GetRole())
{
cbRolename->SetSelection(index);
break;
}
}
}
return foundServer;
}
int dlgSelectConnection::Go(pgConn *conn, wxBitmapComboBox *cb)
{
bool foundServer = false;
cbConnection = cb;
currconn=conn;
foundServer = BuildServerCombo(conn);
return ShowModal();
}