pgadmin3/frm/frmDatabaseDesigner.cpp
2020-07-07 22:19:12 +05:00

929 lines
28 KiB
C++

//////////////////////////////////////////////////////////////////////////
//
// pgAdmin III - PostgreSQL Tools
//
// Copyright (C) 2002 - 2016, The pgAdmin Development Team
// This software is released under the PostgreSQL Licence
//
// frmDatabaseDesigner.cpp - The database designer form
//
//////////////////////////////////////////////////////////////////////////
#include "pgAdmin3.h"
// wxWindows headers
#include <wx/wx.h>
#include <wx/dcbuffer.h>
#include <wx/aui/aui.h>
#include <wx/splitter.h>
#include <wx/filename.h>
// App headers
#include "frm/frmMain.h"
#include "frm/frmDatabaseDesigner.h"
#include "ctl/ctlMenuToolbar.h"
#include "schema/pgObject.h"
#include "schema/pgDatabase.h"
#include "ctl/ctlSQLBox.h"
#include "dlg/dlgSelectConnection.h"
#include "utils/sysSettings.h"
// Designer headers
#include "dd/dditems/figures/ddColumnKindIcon.h"
#include "hotdraw/figures/hdPolyLineFigure.h"
#include "hotdraw/figures/hdSimpleTextFigure.h"
#include "dd/dditems/figures/ddTableFigure.h"
#include "hotdraw/figures/hdRectangleFigure.h"
#include "hotdraw/figures/hdBitmapFigure.h"
#include "hotdraw/tools/hdConnectionCreationTool.h"
#include "dd/ddmodel/ddModelBrowser.h"
#include "dd/ddmodel/ddDBReverseEngineering.h"
#include "dd/ddmodel/ddGenerationWizard.h"
#include "dd/ddmodel/ddDatabaseDesign.h"
#include "dd/ddmodel/ddDrawingView.h"
#include "dd/dditems/figures/ddTextTableItemFigure.h"
#include "dd/dditems/figures/ddColumnFigure.h"
#include "dd/dditems/figures/ddTableFigure.h"
#include "dd/dditems/utilities/ddTableNameDialog.h"
#include "dd/dditems/figures/xml/ddXmlStorage.h"
// Icons
#include "images/ddmodel-32.pngc"
#include "images/file_new.pngc"
#include "images/table.pngc"
#include "images/ddRemoveTable2.pngc"
#include "images/continue.pngc"
#include "images/ddnewdiagram.pngc"
#include "images/ddgendiagram.pngc"
#include "images/help.pngc"
#include "images/file_save.pngc"
#include "images/file_open.pngc"
#include "images/conversion.pngc"
BEGIN_EVENT_TABLE(frmDatabaseDesigner, pgFrame)
EVT_COMBOBOX(CTL_DDCONNECTION, frmDatabaseDesigner::OnChangeConnection)
EVT_MENU(MNU_NEW, frmDatabaseDesigner::OnNewModel)
EVT_MENU(MNU_ADDTABLE, frmDatabaseDesigner::OnAddTable)
EVT_MENU(MNU_DELETETABLE, frmDatabaseDesigner::OnDeleteTable)
EVT_MENU(MNU_ADDCOLUMN, frmDatabaseDesigner::OnAddColumn)
EVT_MENU(MNU_GENERATEDIAGRAM, frmDatabaseDesigner::OnDiagramGeneration)
EVT_MENU(MNU_GENERATEMODEL, frmDatabaseDesigner::OnModelGeneration)
EVT_MENU(MNU_SAVEMODEL, frmDatabaseDesigner::OnModelSave)
EVT_MENU(MNU_SAVEMODELAS, frmDatabaseDesigner::OnModelSaveAs)
EVT_MENU(MNU_LOADMODEL, frmDatabaseDesigner::OnModelLoad)
EVT_MENU(MNU_NEWDIAGRAM, frmDatabaseDesigner::OnAddDiagram)
EVT_MENU(MNU_DELDIAGRAM, frmDatabaseDesigner::OnDeleteDiagram)
EVT_MENU(MNU_RENDIAGRAM, frmDatabaseDesigner::OnRenameDiagram)
EVT_MENU(MNU_TOGGLEDDSQL, frmDatabaseDesigner::OnToggleSQLWindow)
EVT_MENU(MNU_TOGGLEMBROWSER, frmDatabaseDesigner::OnToggleModelBrowser)
EVT_MENU(CTL_IMPSCHEMA, frmDatabaseDesigner::OnImportSchema)
EVT_AUINOTEBOOK_PAGE_CLOSE(CTL_DDNOTEBOOK, frmDatabaseDesigner::OnDeleteDiagramTab)
EVT_AUINOTEBOOK_PAGE_CLOSED(CTL_DDNOTEBOOK, frmDatabaseDesigner::OnDeletedDiagramTab)
EVT_AUINOTEBOOK_BUTTON(CTL_DDNOTEBOOK, frmDatabaseDesigner::OnClickDiagramTab)
EVT_AUINOTEBOOK_BG_DCLICK(CTL_DDNOTEBOOK, frmDatabaseDesigner::OnAddDiagram2)
EVT_CLOSE( frmDatabaseDesigner::OnClose)
END_EVENT_TABLE()
frmDatabaseDesigner::frmDatabaseDesigner(frmMain *form, const wxString &_title, pgConn *conn)
: pgFrame(NULL, _title)
{
mainForm = form;
SetTitle(wxT("Database Designer"));
SetIcon(wxIcon(*ddmodel_32_png_ico));
loading = true;
closing = false;
RestorePosition(100, 100, 600, 500, 450, 300);
SetMinSize(wxSize(450, 300));
// connection
connection = conn;
// notify wxAUI which frame to use
manager.SetManagedWindow(this);
manager.SetFlags(wxAUI_MGR_DEFAULT | wxAUI_MGR_TRANSPARENT_DRAG);
SetFont(settings->GetSystemFont());
// Set File menu
fileMenu = new wxMenu();
fileMenu->Append(MNU_NEW, _("&New database design\tCtrl-N"), _("Create a new database design"));
fileMenu->AppendSeparator();
fileMenu->Append(MNU_LOADMODEL, _("&Open Model..."), _("Open an existing database design from a file"));
fileMenu->Append(MNU_SAVEMODEL, _("&Save Model"), _("Save changes at database design"));
fileMenu->Append(MNU_SAVEMODELAS, _("&Save Model As..."), _("Save database design at new file"));
fileMenu->AppendSeparator();
fileMenu->Append(CTL_IMPSCHEMA, _("&Import Tables..."), _("Import tables from database schema to database designer model"));
fileMenu->AppendSeparator();
fileMenu->Append(MNU_EXIT, _("E&xit\tCtrl-W"), _("Exit database designer window"));
// Set Diagram menu
diagramMenu = new wxMenu();
diagramMenu->Append(MNU_NEWDIAGRAM, _("&New model diagram"), _("Create a new diagram"));
diagramMenu->Append(MNU_DELDIAGRAM, _("&Delete selected model diagram..."), _("Delete selected diagram"));
diagramMenu->Append(MNU_RENDIAGRAM, _("&Rename selected model diagram..."), _("Rename selected diagram"));
// Set View menu
viewMenu = new wxMenu();
viewMenu->AppendCheckItem(MNU_TOGGLEMBROWSER, _("&Model Browser"), _("Show / Hide Model Browser Window"));
viewMenu->AppendCheckItem(MNU_TOGGLEDDSQL, _("&SQL Window"), _("Show / Hide SQL Window"));
viewMenu->Check(MNU_TOGGLEDDSQL, true);
viewMenu->Check(MNU_TOGGLEMBROWSER, true);
// Set Help menu
helpMenu = new wxMenu();
helpMenu->Append(MNU_CONTENTS, _("&Help"), _("Open the helpfile."));
helpMenu->Append(MNU_HELP, _("&SQL Help\tF1"), _("Display help on SQL commands."));
// Set menu bar
menuBar = new wxMenuBar();
menuBar->Append(fileMenu, _("&File"));
menuBar->Append(diagramMenu, _("&Diagram"));
menuBar->Append(viewMenu, _("&View"));
menuBar->Append(helpMenu, _("&Help"));
SetMenuBar(menuBar);
// Set status bar
int iWidths[6] = {0, -1, 40, 150, 80, 80};
CreateStatusBar(6);
SetStatusBarPane(-1);
SetStatusWidths(6, iWidths);
// Set toolbar
toolBar = new ctlMenuToolbar(this, -1, wxDefaultPosition, wxDefaultSize, wxTB_FLAT | wxTB_NODIVIDER);
toolBar->SetToolBitmapSize(wxSize(16, 16));
toolBar->AddTool(MNU_NEW, _("New Model"), *file_new_png_bmp, _("Create new model"), wxITEM_NORMAL);
toolBar->AddTool(MNU_NEWDIAGRAM, _("New Diagram"), *ddnewdiagram_png_bmp, _("Add new diagram"), wxITEM_NORMAL);
toolBar->AddSeparator();
toolBar->AddTool(MNU_LOADMODEL, _("Open Model"), *file_open_png_bmp, _("Open existing model"), wxITEM_NORMAL);
toolBar->AddTool(MNU_SAVEMODEL, _("Save Model"), *file_save_png_bmp, _("Save current model"), wxITEM_NORMAL);
toolBar->AddSeparator();
toolBar->AddTool(MNU_ADDTABLE, _("Add Table"), *table_png_bmp, _("Add empty table to the current model"), wxITEM_NORMAL);
toolBar->AddTool(MNU_DELETETABLE, _("Delete Table"), wxBitmap(*ddRemoveTable2_png_img), _("Delete selected table"), wxITEM_NORMAL);
toolBar->AddTool(MNU_ADDCOLUMN, _("Add Column"), *table_png_bmp, _("Add new column to the selected table"), wxITEM_NORMAL);
toolBar->AddSeparator();
toolBar->AddTool(MNU_GENERATEMODEL, _("Generate Model"), *continue_png_bmp, _("Generate SQL for the current model"), wxITEM_NORMAL);
toolBar->AddTool(MNU_GENERATEDIAGRAM, _("Generate Diagram"), *ddgendiagram_png_bmp, _("Generate SQL for the current diagram"), wxITEM_NORMAL);
toolBar->AddSeparator();
toolBar->AddTool(CTL_IMPSCHEMA, _("Import Tables from database..."), *conversion_png_ico, _("Import tables from database schema to database designer model"), wxITEM_NORMAL);
toolBar->AddSeparator();
toolBar->AddTool(MNU_HELP, _("Help"), *help_png_bmp, _("Display help"), wxITEM_NORMAL);
toolBar->Realize();
// Create notebook for diagrams
diagrams = new ctlAuiNotebook(this, CTL_DDNOTEBOOK, wxDefaultPosition, wxDefaultSize, wxAUI_NB_TOP | wxAUI_NB_TAB_SPLIT | wxAUI_NB_TAB_MOVE | wxAUI_NB_SCROLL_BUTTONS | wxAUI_NB_WINDOWLIST_BUTTON | wxAUI_NB_CLOSE_ON_ALL_TABS);
// Now, the scratchpad
sqltext = new ctlSQLBox(this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTE_MULTILINE | wxSIMPLE_BORDER | wxTE_RICH2);
//Now, the Objects Browser
wxSizer *browserSizer = new wxBoxSizer(wxHORIZONTAL);
browserPanel = new wxPanel(this, wxID_ANY, wxDefaultPosition, wxDefaultSize);
// Add the database designer
design = new ddDatabaseDesign(diagrams, this);
// Create database model browser
modelBrowser = new ddModelBrowser(browserPanel, DD_BROWSER, wxDefaultPosition, wxDefaultSize, wxTR_HAS_BUTTONS | wxSIMPLE_BORDER, design);
design->registerBrowser(modelBrowser);
// Set browser Sizers
browserSizer->Add(modelBrowser, 1, wxEXPAND);
browserPanel->SetSizer(browserSizer);
browserSizer->SetSizeHints(browserPanel);
// Add view to notebook
diagrams->AddPage(design->createDiagram(diagrams, _("unnamed"), false)->getView(), _("unnamed"));
// Add the database selection bar and schema selector
wxSizer *connectionSizer = new wxBoxSizer(wxHORIZONTAL);
connectionPanel = new wxPanel(this, wxID_ANY, wxDefaultPosition, wxSize(-1, -1));
cbConnection = new wxBitmapComboBox(connectionPanel, CTL_DDCONNECTION, wxEmptyString, wxDefaultPosition, wxSize(-1, -1), wxArrayString(), wxCB_READONLY | wxCB_DROPDOWN);
if(conn)
cbConnection->Append(conn->GetName(), CreateBitmap(GetServerColour(conn)), (void *)conn);
cbConnection->Append(_("<new connection>"), wxNullBitmap, (void *) NULL);
connectionSizer->Add(cbConnection, 0, wxALIGN_LEFT | wxALIGN_CENTER_VERTICAL, 1);
connectionSizer->AddSpacer(5);
connectionPanel->SetSizer(connectionSizer);
connectionSizer->SetSizeHints(connectionPanel);
// Add the panes
manager.AddPane(diagrams,
wxAuiPaneInfo().Center().
Name(wxT("sqlQuery")).Caption(_("Database Designer")).
CaptionVisible(true).CloseButton(false).MaximizeButton(true).
Dockable(true).Movable(true));
manager.AddPane(browserPanel,
wxAuiPaneInfo().Left().
Name(wxT("ModelBrowser")).Caption(_("Model Browser")).
CaptionVisible(true).CloseButton(true).MinimizeButton(true).
MinSize(wxSize(140, 100)).BestSize(wxSize(200, 200)));
manager.AddPane(sqltext,
wxAuiPaneInfo().Bottom().
Name(wxT("sqlText")).Caption(_("SQL query")).
CaptionVisible(true).CloseButton(true).MaximizeButton(true).MinimizeButton(true).
MinSize(wxSize(200, 100)).BestSize(wxSize(350, 150)));
manager.AddPane(toolBar,
wxAuiPaneInfo().Top().
Name(wxT("toolBar")).Caption(_("Tool bar")).
ToolbarPane().
LeftDockable(false).RightDockable(false));
manager.AddPane(connectionPanel, wxAuiPaneInfo().Name(wxT("databaseBar"))
.Caption(_("Connection bar")).ToolbarPane().Top().
LeftDockable(false).RightDockable(false));
// Update the AUI manager
manager.Update();
//Update browser info
modelBrowser->SetSize(browserPanel->GetSize());
previousChanged = true;
setModelChanged(false);
SetStatusText(wxString(wxT("Ready")), 1);
}
frmDatabaseDesigner::~frmDatabaseDesigner()
{
closing = true;
// Save form's position
SavePosition();
// Uninitialize wxAUIManager
manager.UnInit();
if (mainForm)
mainForm->RemoveFrame(this);
if(modelBrowser)
delete modelBrowser;
if(browserPanel)
delete browserPanel;
if(diagrams)
delete diagrams;
if(design)
delete design;
if (connection)
{
if (connection->IsAlive())
delete connection;
}
}
void frmDatabaseDesigner::Go()
{
cbConnection->SetSelection(0L);
if (connection)
{
wxCommandEvent event;
OnChangeConnection(event);
}
loading = false;
Show(true);
}
void frmDatabaseDesigner::setModelChanged(bool value)
{
previousChanged = changed;
changed = value;
// optimization to avoid unneeded operations
// false changed for false don't trigger it, but false changed to true trigger it.
if (previousChanged != changed)
{
wxMenuItem *itemMenu = fileMenu->FindItem(MNU_SAVEMODEL);
if (value)
{
itemMenu->Enable(true);
toolBar->EnableTool(MNU_SAVEMODEL, true);
setExtendedTitle();
}
else
{
itemMenu->Enable(false);
toolBar->EnableTool(MNU_SAVEMODEL, false);
setExtendedTitle();
}
}
}
void frmDatabaseDesigner::OnClose(wxCloseEvent &event)
{
closing = true;
// Ask what to do with old model
if (changed)
{
int answer = wxMessageBox(_("Save model changes?"), _("Confirm"), wxYES_NO | wxCANCEL);
if (answer == wxYES)
{
if (lastFile.IsEmpty())
{
wxFileDialog openFileDialog( this, _("Save model"), wxT(""), wxT(""), wxT("*.pgd"),
wxFD_SAVE | wxFD_OVERWRITE_PROMPT, wxDefaultPosition);
if (openFileDialog.ShowModal() == wxID_OK)
{
wxString path;
path.append(openFileDialog.GetDirectory());
path.append(wxFileName::GetPathSeparator());
path.append(openFileDialog.GetFilename());
if(!path.Lower().Matches(wxT("*.pgd")))
path.append(wxT(".pgd"));
lastFile = path;
}
}
if (!lastFile.IsEmpty())
{
design->writeXmlModel(lastFile);
setModelChanged(false);
setExtendedTitle();
}
}
else if (answer == wxCANCEL)
{
event.Veto();
return;
}
}
Hide();
Destroy();
}
void frmDatabaseDesigner::setExtendedTitle()
{
wxString title = wxT("Database Design");
wxString chgStr;
if (changed)
chgStr = wxT(" *");
if (lastFile.IsEmpty())
SetTitle(title + chgStr);
else
SetTitle(title + wxT(" - [") + lastFile + wxT("]") + chgStr);
}
void frmDatabaseDesigner::OnAddTable(wxCommandEvent &event)
{
if (diagrams->GetPageCount() > 0)
{
hdDrawingView *view = (hdDrawingView *) diagrams->GetPage(diagrams->GetSelection());
ddTableNameDialog *newTableDialog = new ddTableNameDialog(
this,
wxEmptyString,
wxEmptyString,
NULL
);
bool done = false, existsTable;
int answer;
do
{
answer = newTableDialog->ShowModal();
existsTable = design->getTable(newTableDialog->GetValue1()) != NULL;
if (answer == wxID_OK && !newTableDialog->GetValue1().IsEmpty() && !existsTable)
{
ddTableFigure *newTable = new ddTableFigure(newTableDialog->GetValue1(),
view->getIdx(),
rand() % 90 + 200,
rand() % 90 + 140);
design->addTableToView(view->getIdx(), newTable);
design->refreshDraw(view->getIdx());
setModelChanged(true);
setExtendedTitle();
done = true;
}
else if(existsTable && answer == wxID_OK)
{
wxMessageBox(_("You have to change the table name because there is already a table with that name in this model."), _("Table already existing"), wxICON_EXCLAMATION | wxOK);
}
}
while (answer != wxID_CANCEL && !done);
delete newTableDialog;
}
}
void frmDatabaseDesigner::OnDeleteTable(wxCommandEvent &event)
{
if (diagrams->GetPageCount() > 0)
{
hdDrawingView *view = (hdDrawingView *) diagrams->GetPage(diagrams->GetSelection());
view->getDrawing()->deleteSelectedFigures();
setModelChanged(true);
setExtendedTitle();
}
}
void frmDatabaseDesigner::OnAddColumn(wxCommandEvent &event)
{
if (diagrams->GetPageCount() > 0)
{
hdDrawingView *view = (hdDrawingView *) diagrams->GetPage(diagrams->GetSelection());
ddTableFigure *table = design->getSelectedTable(view->getIdx());
wxTextEntryDialog nameDialog (this, wxT("New column name"), wxT("Add a column"), wxT("NewColumn"));
int answer;
wxString tmpString;
if (table)
{
bool again;
do
{
again = false;
answer = nameDialog.ShowModal();
if (answer == wxID_OK)
{
tmpString = nameDialog.GetValue();
if(table->getColByName(tmpString) == NULL)
{
table->addColumn(view->getIdx(), new ddColumnFigure(tmpString, table));
setModelChanged(true);
setExtendedTitle();
}
else
{
wxString msg(wxT("Error trying to add new column '"));
msg.Append(tmpString);
msg.Append(wxT("' column name already in use"));
wxMessageDialog info( this, msg ,
wxT("Column name already in use"),
wxNO_DEFAULT | wxOK | wxICON_EXCLAMATION);
again = true;
info.ShowModal();
}
}
}
while(again);
}
view->Refresh();
}
else
{
wxMessageBox(_("Warning about adding a column to a table without a diagram"), _("Please create a model diagram first"), wxICON_EXCLAMATION | wxOK);
}
}
void frmDatabaseDesigner::OnNewModel(wxCommandEvent &event)
{
hdDrawingView *view = (hdDrawingView *) diagrams->GetPage(diagrams->GetSelection());
if (changed)
{
// Ask what to do with old model
int answer = wxMessageBox(_("Save model changes?"), _("Confirm"), wxYES_NO | wxCANCEL);
if (answer == wxYES)
{
if (!lastFile.IsEmpty())
OnModelSave(event);
else
OnModelSaveAs(event);
}
else if (answer == wxCANCEL)
return;
}
// Clean treeview, notebook, and sql pane
design->emptyModel();
while (diagrams->GetPageCount() > 0)
{
diagrams->RemovePage(0);
design->deleteDiagram(0);
}
sqltext->SetText(wxEmptyString);
// Add new diagram
diagrams->AddPage(design->createDiagram(diagrams, _("unnamed"), false)->getView(), _("unnamed"));
// Misc
lastFile = wxEmptyString;
setModelChanged(false);
setExtendedTitle();
UpdateToolbar();
}
void frmDatabaseDesigner::OnDiagramGeneration(wxCommandEvent &event)
{
wxString errors;
if(!design->validateModel(errors))
{
wxMessageDialog dialog(this, errors , wxT("Errors detected in the database model"), wxOK | wxICON_EXCLAMATION | wxSTAY_ON_TOP);
dialog.ShowModal();
}
else
{
hdDrawingView *view = (hdDrawingView *) diagrams->GetPage(diagrams->GetSelection());
ddGenerationWizard *generationWizard = new ddGenerationWizard(this, design, connection);
//Set pre-select tables [diagram]
generationWizard->preSelTables = design->getDiagramTables(view->getIdx());
//Call generation wizard
generationWizard->RunWizard(generationWizard->GetFirstPage());
sqltext->SetText(generationWizard->DDL);
delete generationWizard;
}
}
void frmDatabaseDesigner::OnModelGeneration(wxCommandEvent &event)
{
wxString errors;
if(!design->validateModel(errors))
{
wxMessageDialog dialog(this, errors , wxT("Errors detected in the database model"), wxOK | wxICON_EXCLAMATION | wxSTAY_ON_TOP);
dialog.ShowModal();
}
else
{
ddGenerationWizard *generationWizard = new ddGenerationWizard(this, design, connection);
//Set pre-select tables [model] disable
//generationWizard->preSelTables = design->getModelTables();
//Call generation wizard
generationWizard->RunWizard(generationWizard->GetFirstPage());
sqltext->SetText(generationWizard->DDL);
delete generationWizard;
}
}
void frmDatabaseDesigner::OnModelSaveAs(wxCommandEvent &event)
{
wxFileDialog openFileDialog( this, _("Save model"), wxT(""), wxT(""), wxT("*.pgd"),
wxFD_SAVE | wxFD_OVERWRITE_PROMPT, wxDefaultPosition);
if (openFileDialog.ShowModal() == wxID_OK)
{
wxString path;
path.append( openFileDialog.GetDirectory() );
path.append( wxFileName::GetPathSeparator() );
path.append( openFileDialog.GetFilename() );
if(!path.Lower().Matches(wxT("*.pgd")))
path.append(wxT(".pgd"));
lastFile = path;
setModelChanged(false);
setExtendedTitle();
design->writeXmlModel(path);
}
}
void frmDatabaseDesigner::OnModelSave(wxCommandEvent &event)
{
if (lastFile != wxEmptyString)
{
design->writeXmlModel(lastFile);
setModelChanged(false);
setExtendedTitle();
}
else
{
OnModelSaveAs(event);
}
}
void frmDatabaseDesigner::OnModelLoad(wxCommandEvent &event)
{
if(changed)
{
// Ask what to do with old model
int answer = wxMessageBox(_("Save model changes?"), _("Confirm"), wxYES_NO | wxCANCEL);
if (answer == wxYES)
{
if (lastFile != wxEmptyString)
OnModelSave(event);
else
OnModelSaveAs(event);
}
if(answer == wxCANCEL)
return;
}
//Open Model
wxFileDialog openFileDialog(this, _("Open model"), wxT(""), wxT(""), wxT("*.pgd"),
wxFD_OPEN | wxFD_FILE_MUST_EXIST, wxDefaultPosition);
if (openFileDialog.ShowModal() == wxID_OK)
{
wxString path;
path.append(openFileDialog.GetDirectory());
path.append(wxFileName::GetPathSeparator());
path.append(openFileDialog.GetFilename());
if(!path.Lower().Matches(wxT("*.pgd")))
path.append(wxT(".pgd"));
lastFile = path;
// Clean treeview, notebook, and sql pane
design->emptyModel();
while(diagrams->GetPageCount() > 0)
{
diagrams->RemovePage(0);
design->deleteDiagram(0);
}
sqltext->SetText(wxEmptyString);
// Read model from xml file
design->readXmlModel(path, diagrams);
setModelChanged(false);
setExtendedTitle();
}
}
void frmDatabaseDesigner::OnAddDiagram(wxCommandEvent &event)
{
wxString newName = wxGetTextFromUser(_("New Diagram Name"), _("Diagram Name"), _("unnamed"), this);
if (!newName.IsEmpty())
{
diagrams->AddPage(design->createDiagram(diagrams, newName, false)->getView(), newName);
setModelChanged(true);
}
UpdateToolbar();
}
void frmDatabaseDesigner::OnAddDiagram2(wxAuiNotebookEvent &event)
{
wxCommandEvent evt;
OnAddDiagram(evt);
}
void frmDatabaseDesigner::OnDeleteDiagram(wxCommandEvent &event)
{
hdDrawingView *view = (hdDrawingView *) diagrams->GetPage(diagrams->GetSelection());
int diagramIndex = view->getIdx();
diagrams->RemovePage(diagrams->GetSelection());
design->deleteDiagram(diagramIndex);
setModelChanged(true);
UpdateToolbar();
}
void frmDatabaseDesigner::OnRenameDiagram(wxCommandEvent &event)
{
hdDrawingView *view = (hdDrawingView *) diagrams->GetPage(diagrams->GetSelection());
int diagramIndex = view->getIdx();
wxString msg;
msg.Printf(_("Rename diagram %s to:"), diagrams->GetPageText(diagramIndex).c_str());
wxString name = wxGetTextFromUser(msg, _("Rename diagram..."), diagrams->GetPageText(diagramIndex), this);
if(!name.IsEmpty() && !name.IsSameAs(diagrams->GetPageText(diagramIndex), false))
{
view->getDrawing()->setName(name);
diagrams->SetPageText(diagramIndex, name);
setModelChanged(true);
}
}
void frmDatabaseDesigner::OnDeleteDiagramTab(wxAuiNotebookEvent &event)
{
deletedTab = event.GetSelection();
wxAuiNotebook *ctrl = (wxAuiNotebook *)event.GetEventObject();
hdDrawingView *view = (hdDrawingView *) ctrl->GetPage(event.GetSelection());
wxString msg;
msg.Printf(_("Are you sure you want to delete diagram \"%s\" from model?"), view->getDrawing()->getName().c_str());
int res = wxMessageBox(msg,
wxT("Delete diagram?"),
wxYES_NO | wxNO_DEFAULT,
this);
if (res != wxYES)
{
event.Veto();
}
else
{
setModelChanged(true);
}
UpdateToolbar();
}
void frmDatabaseDesigner::OnDeletedDiagramTab(wxAuiNotebookEvent &event)
{
//don't delete view when deleting diagram because it was deleted before by EVT_AUINOTEBOOK_PAGE_CLOSE event
//option possible will be wxAuiPaneInfo().DestroyOnClose(false) but should be tried in a future
design->deleteDiagram(deletedTab, false);
UpdateToolbar();
}
void frmDatabaseDesigner::OnClickDiagramTab(wxAuiNotebookEvent &event)
{
//This event is not working by unknown reason right now.
wxLogError(wxT("WTF?"));
}
void frmDatabaseDesigner::UpdateToolbar()
{
toolBar->EnableTool(MNU_ADDTABLE, diagrams->GetPageCount() > 0);
toolBar->EnableTool(MNU_DELETETABLE, diagrams->GetPageCount() > 0);
if (diagrams->GetPageCount() > 0)
{
hdDrawingView *view = (hdDrawingView *) diagrams->GetPage(diagrams->GetSelection());
ddTableFigure *table = design->getSelectedTable(view->getIdx());
toolBar->EnableTool(MNU_ADDCOLUMN, table != NULL);
}
toolBar->EnableTool(MNU_GENERATEMODEL, diagrams->GetPageCount() > 0);
toolBar->EnableTool(MNU_GENERATEDIAGRAM, diagrams->GetPageCount() > 0);
}
wxColour frmDatabaseDesigner::GetServerColour(pgConn *connection)
{
wxColour tmp = wxNullColour;
if (mainForm != NULL)
{
ctlTree *browser = mainForm->GetBrowser();
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->GetConnected() &&
server->GetConnection()->GetHost() == connection->GetHost() &&
server->GetConnection()->GetPort() == connection->GetPort())
{
tmp = wxColour(server->GetColour());
}
}
serveritem = browser->GetNextChild(folderitem, servercookie);
}
}
folderitem = browser->GetNextChild(browser->GetRootItem(), foldercookie);
}
}
return tmp;
}
wxBitmap frmDatabaseDesigner::CreateBitmap(const wxColour &colour)
{
const int w = 10, h = 10;
wxMemoryDC dc;
wxBitmap bmp(w, h);
dc.SelectObject(bmp);
if (colour == wxNullColour)
dc.SetBrush(wxBrush(wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW)));
else
dc.SetBrush(wxBrush(colour));
dc.DrawRectangle(0, 0, w, h);
return bmp;
}
void frmDatabaseDesigner::OnChangeConnection(wxCommandEvent &event)
{
// On Solaris, this event seems to get fired when the form closes(!!)
if(!IsVisible() && !loading)
return;
unsigned int sel = cbConnection->GetSelection();
if (sel == cbConnection->GetCount() - 1)
{
// new Connection
dlgSelectConnection dlg(this, mainForm);
int rc = dlg.Go(connection, cbConnection);
if (rc == wxID_OK)
{
bool createdNewConn;
wxString applicationname = appearanceFactory->GetLongAppName() + _(" - Database Designer");
pgConn *newconn = dlg.CreateConn(applicationname, createdNewConn);
if (newconn && createdNewConn)
{
cbConnection->Insert(newconn->GetName(), CreateBitmap(GetServerColour(newconn)), sel);
cbConnection->SetClientData(sel, (void *)newconn);
cbConnection->SetSelection(sel);
OnChangeConnection(event);
}
else
rc = wxID_CANCEL;
}
if (rc != wxID_OK)
{
unsigned int i;
for (i = 0 ; i < sel ; i++)
{
if (cbConnection->GetClientData(i) == connection)
{
cbConnection->SetSelection(i);
break;
}
}
}
}
else
{
connection = (pgConn *)cbConnection->GetClientData(sel);
setExtendedTitle();
}
}
void frmDatabaseDesigner::OnImportSchema(wxCommandEvent &WXUNUSED(event))
{
ddDBReverseEngineering *importTableWizard = new ddDBReverseEngineering(this, design, connection);
importTableWizard->RunWizard(importTableWizard->GetFirstPage());
delete importTableWizard;
}
void frmDatabaseDesigner::OnToggleModelBrowser(wxCommandEvent &event)
{
if (viewMenu->IsChecked(MNU_TOGGLEMBROWSER))
manager.GetPane(wxT("ModelBrowser")).Show(true);
else
manager.GetPane(wxT("ModelBrowser")).Show(false);
manager.Update();
}
void frmDatabaseDesigner::OnToggleSQLWindow(wxCommandEvent &event)
{
if (viewMenu->IsChecked(MNU_TOGGLEDDSQL))
manager.GetPane(wxT("sqlText")).Show(true);
else
manager.GetPane(wxT("sqlText")).Show(false);
manager.Update();
}
///////////////////////////////////////////////////////
bool databaseDesignerBaseFactory::CheckEnable(pgObject *obj)
{
return obj && obj->GetDatabase() && obj->GetDatabase()->GetConnected();
}
wxWindow *databaseDesignerBaseFactory::StartDialogDesigner(frmMain *form, pgObject *obj, const wxString &sql)
{
if(obj)
{
pgDatabase *db = obj->GetDatabase();
wxString applicationname = appearanceFactory->GetLongAppName() + _(" - Database designer");
pgConn *conn = NULL;
if(db)
{
conn = db->CreateConn(applicationname);
if (conn)
{
frmDatabaseDesigner *fd = new frmDatabaseDesigner(form, wxEmptyString, conn);
fd->Go();
return fd;
}
}
}
frmDatabaseDesigner *fd = new frmDatabaseDesigner(form, wxEmptyString, NULL);
fd->Go();
return fd;
}
databaseDesignerFactory::databaseDesignerFactory(menuFactoryList *list, wxMenu *mnu, ctlMenuToolbar *toolbar) : databaseDesignerBaseFactory(list)
{
mnu->Append(id, _("&Database Designer\tCtrl-F"), _("Create database designs"));
toolbar->AddTool(id, _("Database Designer\tCtrl-F"), wxBitmap(*ddmodel_32_png_img), _("Create database designs."), wxITEM_NORMAL);
}
wxWindow *databaseDesignerFactory::StartDialog(frmMain *form, pgObject *obj)
{
wxString qry;
if (settings->GetStickySql())
qry = obj->GetSql(form->GetBrowser());
return StartDialogDesigner(form, obj, qry);
}