mirror of
https://github.com/levinsv/pgadmin3.git
synced 2026-05-15 06:05:49 -06:00
Стандартные иконки можно заменить на SVG иконки. Которые находятся в каталоге include/images. ВАЖНО: иконки для COMMIT и ROLLBACK поменяны местами, зеленая это commit красная rollback (как в PL/SQL Developer). Если это вам не подходит следует изменить имена файлов (query_commit.svg и query_rollback.svg). SVG файлы должны быть размещены: Windos - %APPDATA%/postgresql/svg LINUX - ~/.local/share/pgadmin3/svg
5292 lines
154 KiB
C++
5292 lines
154 KiB
C++
//////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// pgAdmin III - PostgreSQL Tools
|
|
//
|
|
// Copyright (C) 2002 - 2016, The pgAdmin Development Team
|
|
// This software is released under the PostgreSQL Licence
|
|
//
|
|
// frmQuery.cpp - SQL Query Box
|
|
//
|
|
//////////////////////////////////////////////////////////////////////////
|
|
|
|
#include "pgAdmin3.h"
|
|
|
|
// wxWindows headers
|
|
#include <wx/wx.h>
|
|
#include <wx/busyinfo.h>
|
|
#include <wx/clipbrd.h>
|
|
#include <wx/dcbuffer.h>
|
|
#include <wx/dnd.h>
|
|
#include <wx/filename.h>
|
|
#include <wx/regex.h>
|
|
#include <wx/textctrl.h>
|
|
#include <wx/timer.h>
|
|
#include <wx/aui/aui.h>
|
|
#include <wx/bmpcbox.h>
|
|
#include <wx/filefn.h>
|
|
#include <wx/stdpaths.h>
|
|
// App headers
|
|
#include "frm/frmAbout.h"
|
|
#include "frm/frmMain.h"
|
|
#include "frm/frmQuery.h"
|
|
#include "frm/menu.h"
|
|
#include "ctl/explainCanvas.h"
|
|
#include "db/pgConn.h"
|
|
|
|
#include "ctl/ctlMenuToolbar.h"
|
|
#include "ctl/ctlSQLResult.h"
|
|
#include "dlg/dlgSelectConnection.h"
|
|
#include "dlg/dlgAddFavourite.h"
|
|
#include "dlg/dlgManageFavourites.h"
|
|
#include "dlg/dlgManageMacros.h"
|
|
#include "dlg/dlgFunction.h"
|
|
#include "frm/frmReport.h"
|
|
#include "gqb/gqbViewController.h"
|
|
#include "gqb/gqbModel.h"
|
|
#include "gqb/gqbViewPanels.h"
|
|
#include "gqb/gqbEvents.h"
|
|
#include "schema/pgDatabase.h"
|
|
#include "schema/pgFunction.h"
|
|
#include "schema/pgTable.h"
|
|
#include "schema/pgForeignTable.h"
|
|
#include "schema/pgView.h"
|
|
#include "schema/gpExtTable.h"
|
|
#include "schema/pgServer.h"
|
|
#include "utils/favourites.h"
|
|
#include "utils/sysLogger.h"
|
|
#include "utils/sysSettings.h"
|
|
#include "utils/utffile.h"
|
|
#include "utils/misc.h"
|
|
#include "pgscript/pgsApplication.h"
|
|
#include "schema/pgPartition.h"
|
|
#include "dlg/dlgVariable.h"
|
|
// Icons
|
|
#include "images/sql-32.pngc"
|
|
|
|
// Bitmaps
|
|
#include "images/file_new.pngc"
|
|
#include "images/file_open.pngc"
|
|
#include "images/file_save.pngc"
|
|
#include "images/clip_cut.pngc"
|
|
#include "images/clip_copy.pngc"
|
|
#include "images/clip_paste.pngc"
|
|
#include "images/edit_clear.pngc"
|
|
#include "images/edit_find.pngc"
|
|
#include "images/edit_undo.pngc"
|
|
#include "images/edit_redo.pngc"
|
|
#include "images/query_execute.pngc"
|
|
#include "images/query_pgscript.pngc"
|
|
#include "images/query_execfile.pngc"
|
|
#include "images/query_explain.pngc"
|
|
#include "images/query_cancel.pngc"
|
|
#include "images/query_commit.pngc"
|
|
#include "images/query_rollback.pngc"
|
|
#include "images/mode_transaction.pngc"
|
|
#include "images/mode_autocommit.pngc"
|
|
#include "images/help.pngc"
|
|
#include "images/gqbJoin.pngc"
|
|
#include <map>
|
|
#define CTRLID_CONNECTION 4200
|
|
#define CTRLID_DATABASELABEL 4201
|
|
#define CTL_SQLQUERYBOOK 4202
|
|
#define CTL_BUTTONTRANSACTION 4203
|
|
|
|
#define XML_FROM_WXSTRING(s) ((const xmlChar *)(const char *)s.mb_str(wxConvUTF8))
|
|
#define WXSTRING_FROM_XML(s) wxString((char *)s, wxConvUTF8)
|
|
#define XML_STR(s) ((const xmlChar *)s)
|
|
extern wxString dataDir;
|
|
// Initialize execution 'mutex'. As this will always run in the
|
|
// main thread, there aren't any real concurrency issues, so
|
|
// a simple flag will suffice.
|
|
// Required because the pgScript parser isn't currently thread-safe :-(
|
|
bool frmQuery::ms_pgScriptRunning = false;
|
|
BEGIN_EVENT_TABLE(frmQuery, pgFrame)
|
|
EVT_ERASE_BACKGROUND( frmQuery::OnEraseBackground)
|
|
EVT_SIZE( frmQuery::OnSize)
|
|
EVT_COMBOBOX(CTRLID_CONNECTION, frmQuery::OnChangeConnection)
|
|
EVT_COMBOBOX(CTL_SQLQUERYCBOX, frmQuery::OnChangeQuery)
|
|
EVT_CLOSE( frmQuery::OnClose)
|
|
EVT_SET_FOCUS( frmQuery::OnSetFocus)
|
|
EVT_MENU(MNU_NEW, frmQuery::OnNew)
|
|
EVT_MENU(MNU_OPEN, frmQuery::OnOpen)
|
|
EVT_MENU(MNU_SAVE, frmQuery::OnSave)
|
|
EVT_MENU(MNU_SAVEAS, frmQuery::OnSaveAs)
|
|
EVT_MENU(MNU_NEWSQLTAB, frmQuery::OnSqlBookAddPage)
|
|
EVT_MENU(MNU_EXPORT, frmQuery::OnExport)
|
|
EVT_MENU(MNU_SAVEAS_IMAGE_GQB, frmQuery::SaveExplainAsImage)
|
|
EVT_MENU(MNU_SAVEAS_IMAGE_EXPLAIN, frmQuery::SaveExplainAsImage)
|
|
EVT_MENU(MNU_EXIT, frmQuery::OnExit)
|
|
EVT_MENU(MNU_CUT, frmQuery::OnCut)
|
|
EVT_MENU(MNU_COPY, frmQuery::OnCopy)
|
|
EVT_MENU(MNU_PASTE, frmQuery::OnPaste)
|
|
EVT_MENU(MNU_CLEAR, frmQuery::OnClear)
|
|
EVT_MENU(MNU_SUMMARY_COL, frmQuery::OnSummary_Column)
|
|
EVT_MENU(MNU_COMPARE_2CELL, frmQuery::OnCompare_2Cell)
|
|
EVT_MENU(MNU_COPY_INSERT, frmQuery::OnCopy_Insert)
|
|
EVT_MENU(MNU_COPY_INLIST, frmQuery::OnCopy_InList)
|
|
EVT_MENU(MNU_COPY_WHERELIST, frmQuery::OnCopy_WhereList)
|
|
EVT_MENU(MNU_COPY_TABLEHTML, frmQuery::OnCopy_TableToHtml)
|
|
EVT_MENU(MNU_CLEAR_FILTER, frmQuery::OnClear_Filter)
|
|
EVT_MENU(MNU_CHECK_COLUMN_DATE, frmQuery::OnCheck_Column_Date)
|
|
EVT_MENU(MNU_COPY_LISTCOLTYPE, frmQuery::OnCopy_NameTypeCols)
|
|
EVT_MENU(MNU_AUTOCOLSPLOT, frmQuery::OnAutoColsPlot)
|
|
EVT_MENU(MNU_FIND, frmQuery::OnSearchReplace)
|
|
EVT_MENU(MNU_TRANSFORM, frmQuery::OnTransformText)
|
|
EVT_MENU(MNU_UNDO, frmQuery::OnUndo)
|
|
EVT_MENU(MNU_REDO, frmQuery::OnRedo)
|
|
EVT_MENU(MNU_EXECUTE, frmQuery::OnExecute)
|
|
EVT_MENU(MNU_EXECUTE_2, frmQuery::OnExecuteShift)
|
|
EVT_MENU(MNU_EXECPGS, frmQuery::OnExecScript)
|
|
EVT_MENU(MNU_EXECFILE, frmQuery::OnExecFile)
|
|
EVT_MENU(MNU_EXPLAIN, frmQuery::OnExplain)
|
|
EVT_MENU(MNU_EXPLAINANALYZE, frmQuery::OnExplain)
|
|
EVT_MENU(MNU_DOCOMMIT, frmQuery::OnCommit)
|
|
EVT_MENU(MNU_DOROLLBACK, frmQuery::OnRollback)
|
|
EVT_MENU(MNU_CANCEL, frmQuery::OnCancel)
|
|
EVT_MENU(MNU_AUTOSELECTQUERY, frmQuery::OnAutoSelectQuery)
|
|
EVT_MENU(MNU_AUTOROLLBACK, frmQuery::OnAutoRollback)
|
|
EVT_MENU(MNU_AUTOCOMMIT, frmQuery::OnAutoCommit)
|
|
EVT_MENU(MNU_MODE_TRANSACTION, frmQuery::OnModeTransaction)
|
|
EVT_MENU(MNU_CONTENTS, frmQuery::OnContents)
|
|
EVT_MENU(MNU_HELP, frmQuery::OnHelp)
|
|
EVT_MENU(MNU_CLEARHISTORY, frmQuery::OnClearHistory)
|
|
EVT_MENU(MNU_SAVEHISTORY, frmQuery::OnSaveHistory)
|
|
EVT_MENU(MNU_SELECTALL, frmQuery::OnSelectAll)
|
|
EVT_MENU(MNU_QUICKREPORT, frmQuery::OnQuickReport)
|
|
EVT_MENU(MNU_AUTOINDENT, frmQuery::OnAutoIndent)
|
|
EVT_MENU(MNU_WORDWRAP, frmQuery::OnWordWrap)
|
|
EVT_MENU(MNU_SHOWINDENTGUIDES, frmQuery::OnShowIndentGuides)
|
|
EVT_MENU(MNU_SHOWWHITESPACE, frmQuery::OnShowWhitespace)
|
|
EVT_MENU(MNU_SHOWLINEENDS, frmQuery::OnShowLineEnds)
|
|
EVT_MENU(MNU_SHOWLINENUMBER, frmQuery::OnShowLineNumber)
|
|
EVT_MENU(MNU_FAVOURITES_ADD, frmQuery::OnAddFavourite)
|
|
EVT_MENU(MNU_FAVOURITES_INJECT, frmQuery::OnInjectFavourite)
|
|
EVT_MENU(MNU_FAVOURITES_MANAGE, frmQuery::OnManageFavourites)
|
|
EVT_MENU(MNU_MACROS_MANAGE, frmQuery::OnMacroManage)
|
|
EVT_MENU(MNU_AUTOREPLACE_MANAGE,frmQuery::OnAutoReplaceManage)
|
|
EVT_MENU(MNU_DATABASEBAR, frmQuery::OnToggleDatabaseBar)
|
|
EVT_MENU(MNU_TOOLBAR, frmQuery::OnToggleToolBar)
|
|
EVT_MENU(MNU_SCRATCHPAD, frmQuery::OnToggleScratchPad)
|
|
EVT_MENU(MNU_OUTPUTPANE, frmQuery::OnToggleOutputPane)
|
|
EVT_MENU(MNU_DEFAULTVIEW, frmQuery::OnDefaultView)
|
|
EVT_MENU(MNU_BLOCK_INDENT, frmQuery::OnBlockIndent)
|
|
EVT_MENU(MNU_BLOCK_OUTDENT, frmQuery::OnBlockOutDent)
|
|
EVT_MENU(MNU_UPPER_CASE, frmQuery::OnChangeToUpperCase)
|
|
EVT_MENU(MNU_LOWER_CASE, frmQuery::OnChangeToLowerCase)
|
|
EVT_MENU(MNU_COMMENT_TEXT, frmQuery::OnCommentText)
|
|
EVT_MENU(MNU_UNCOMMENT_TEXT, frmQuery::OnUncommentText)
|
|
EVT_MENU(MNU_DOUBLEQUOTE_TEXT, frmQuery::OnDoubleText)
|
|
EVT_MENU(MNU_UNDOUBLEQUOTE_TEXT,frmQuery::OnUnDoubleText)
|
|
EVT_MENU(MNU_EXTERNALFORMAT, frmQuery::OnExternalFormat)
|
|
EVT_MENU(MNU_EXTERNALALIGN, frmQuery::OnExternalAlign)
|
|
EVT_MENU(MNU_LF, frmQuery::OnSetEOLMode)
|
|
EVT_MENU(MNU_CRLF, frmQuery::OnSetEOLMode)
|
|
EVT_MENU(MNU_CR, frmQuery::OnSetEOLMode)
|
|
EVT_MENU(MNU_AUTOEDITOBJECT, frmQuery::OnAutoEditObject)
|
|
EVT_MENU_RANGE(MNU_FAVOURITES_MANAGE + 1, MNU_FAVOURITES_MANAGE + 999, frmQuery::OnSelectFavourite)
|
|
EVT_MENU_RANGE(MNU_MACROS_MANAGE + 1, MNU_MACROS_MANAGE + 99, frmQuery::OnMacroInvoke)
|
|
EVT_MENU_RANGE(MNU_GENERATESQL + 1, MNU_GENERATESQL + 199, frmQuery::OnGenerateInvoke)
|
|
EVT_ACTIVATE( frmQuery::OnActivate)
|
|
EVT_STC_MODIFIED(CTL_SQLQUERY, frmQuery::OnChangeStc)
|
|
EVT_STC_UPDATEUI(CTL_SQLQUERY, frmQuery::OnPositionStc)
|
|
EVT_GRID_LABEL_RIGHT_CLICK( frmQuery::OnLabelRightClick)
|
|
EVT_GRID_CELL_LEFT_DCLICK( frmQuery::OnCellLeftDClick)
|
|
EVT_AUI_PANE_CLOSE( frmQuery::OnAuiUpdate)
|
|
EVT_TIMER(CTL_TIMERSIZES, frmQuery::OnAdjustSizesTimer)
|
|
EVT_TIMER(CTL_TIMERFRM, frmQuery::OnTimer)
|
|
// These fire when the queries complete
|
|
EVT_PGQUERYRESULT(QUERY_COMPLETE, frmQuery::OnQueryComplete)
|
|
EVT_MENU(PGSCRIPT_COMPLETE, frmQuery::OnScriptComplete)
|
|
EVT_AUINOTEBOOK_PAGE_CHANGED(CTL_NTBKCENTER, frmQuery::OnChangeNotebook)
|
|
EVT_AUINOTEBOOK_PAGE_CHANGED(CTL_NTBKGQB, frmQuery::OnChangeNotebookOutpane)
|
|
EVT_AUINOTEBOOK_TAB_RIGHT_DOWN(CTL_NTBKGQB, frmQuery::OnNotebookOutpaneTabRDown)
|
|
EVT_AUINOTEBOOK_PAGE_CHANGED(CTL_SQLQUERYBOOK, frmQuery::OnSqlBookPageChanged)
|
|
EVT_AUINOTEBOOK_PAGE_CHANGING(CTL_SQLQUERYBOOK, frmQuery::OnSqlBookPageChanging)
|
|
EVT_AUINOTEBOOK_PAGE_CLOSE(CTL_SQLQUERYBOOK, frmQuery::OnSqlBookPageClose)
|
|
EVT_AUINOTEBOOK_TAB_RIGHT_DOWN(CTL_SQLQUERYBOOK, frmQuery::OnSqlBookTabRDown)
|
|
EVT_AUINOTEBOOK_PAGE_CLOSED(CTL_SQLQUERYBOOK, frmQuery::OnSqlBookPageClosed)
|
|
EVT_SPLITTER_SASH_POS_CHANGED(GQB_HORZ_SASH, frmQuery::OnResizeHorizontally)
|
|
EVT_BUTTON(CTL_DELETECURRENTBTN, frmQuery::OnDeleteCurrent)
|
|
EVT_BUTTON(CTL_DELETEALLBTN, frmQuery::OnDeleteAll)
|
|
EVT_BUTTON(CTL_BUTTONTRANSACTION,frmQuery::OnModeTransaction)
|
|
END_EVENT_TABLE()
|
|
|
|
class DnDFile : public wxFileDropTarget
|
|
{
|
|
public:
|
|
DnDFile(frmQuery *fquery)
|
|
{
|
|
m_fquery = fquery;
|
|
}
|
|
|
|
virtual bool OnDropFiles(wxCoord x, wxCoord y, const wxArrayString &filenames)
|
|
{
|
|
size_t nFiles = filenames.GetCount();
|
|
if ((int) nFiles > 1)
|
|
wxLogError(_("Drag one file at a time"));
|
|
else if ((int) nFiles == 1)
|
|
{
|
|
wxString str;
|
|
bool modeUnicode = settings->GetUnicodeFile();
|
|
wxUtfFile file(filenames[0], wxFile::read, modeUnicode ? wxFONTENCODING_UTF8 : wxFONTENCODING_DEFAULT);
|
|
|
|
if (file.IsOpened())
|
|
file.Read(str);
|
|
|
|
if (!str.IsEmpty() && !m_fquery->CheckChanged(true))
|
|
{
|
|
m_fquery->SetLastPath(filenames[0]);
|
|
m_fquery->SetQueryText(str);
|
|
m_fquery->ColouriseQuery(0, str.Length());
|
|
wxSafeYield(); // needed to process sqlQuery modify event
|
|
m_fquery->SetChanged(false);
|
|
m_fquery->SetOrigin(ORIGIN_FILE);
|
|
m_fquery->setExtendedTitle();
|
|
m_fquery->SetLineEndingStyle();
|
|
m_fquery->UpdateRecentFiles(true);
|
|
m_fquery->UpdateAllRecentFiles();
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
|
|
private:
|
|
frmQuery *m_fquery;
|
|
};
|
|
|
|
void frmQuery::seticon()
|
|
{
|
|
wxString str;
|
|
wxString filename;
|
|
|
|
wxString tempDir = dataDir+wxFileName::GetPathSeparator()+"icons"+wxFileName::GetPathSeparator();
|
|
wxString db = conn->GetDbname();
|
|
wxString host = conn->GetHostName();
|
|
|
|
|
|
wxString f = tempDir + host+"_"+db+wxT(".png");
|
|
if (!wxFileExists(f)) {
|
|
f = tempDir + host + wxT(".png");
|
|
if (!wxFileExists(f)) {
|
|
f = tempDir + db + wxT(".png");
|
|
if (!wxFileExists(f)) f = "";
|
|
}
|
|
}
|
|
if (f.empty()) {
|
|
f = tempDir + host + "_" + db + wxT(".svg");
|
|
if (!wxFileExists(f)) {
|
|
f = tempDir + host + wxT(".svg");
|
|
if (!wxFileExists(f)) {
|
|
f = tempDir + db + wxT(".svg");
|
|
if (!wxFileExists(f)) f = "";
|
|
}
|
|
}
|
|
}
|
|
while (!f.empty())
|
|
{
|
|
wxIcon* ico = new wxIcon();
|
|
wxBitmapBundle bb = GetBundleSVG(NULL, f, wxSize(32, 32));
|
|
wxBitmap bitmap = bb.GetBitmap(wxSize(32, 32));
|
|
|
|
//wxBitmap bitmap(f, wxBITMAP_TYPE_PNG);
|
|
|
|
if (!bitmap.Ok())
|
|
{
|
|
wxMessageBox(wxT("Sorry, could not load png file.\n")+f);
|
|
}
|
|
ico->CopyFromBitmap(bitmap);
|
|
//SetIcon(*sql_32_png_ico);
|
|
SetIcon(*ico);
|
|
delete ico;
|
|
return;
|
|
//f = wxFindNextFile();
|
|
}
|
|
|
|
wxColor cl=GetServerColour(conn);
|
|
int rgb = cl.GetRGB();
|
|
int b = (rgb >> 16) & 255;
|
|
int g = (rgb >> 8) & 255;
|
|
int r = rgb & 255;
|
|
if (r == 255 && g == 255 && b == 255) {
|
|
//SetBitmapBundle()
|
|
SetIcon(*sql_32_png_ico);
|
|
|
|
}
|
|
else {
|
|
|
|
wxImage img = *sql_32_png_img;
|
|
int w = img.GetWidth();
|
|
int h = img.GetHeight();
|
|
for (int y = 0; y < h; y++)
|
|
for (int x = 0; x < w; x++) {
|
|
if (img.IsTransparent(x, y)) img.SetRGB(x, y, r, g, b);
|
|
}
|
|
//wxIcon ico=img.
|
|
wxIcon* ico = new wxIcon();
|
|
wxBitmap* bmp = new wxBitmap(img);
|
|
ico->CopyFromBitmap(*bmp);
|
|
//SetIcon(*sql_32_png_ico);
|
|
SetIcon(*ico);
|
|
delete ico;
|
|
delete bmp;
|
|
}
|
|
}
|
|
frmQuery::frmQuery(frmMain *form, const wxString &_title, pgConn *_conn, const wxString &query, const wxString &file)
|
|
: pgFrame(NULL, _title),
|
|
timer(this, CTL_TIMERFRM),
|
|
pgScript(new pgsApplication(_conn)),
|
|
pgsStringOutput(&pgsOutputString),
|
|
pgsOutput(pgsStringOutput, wxEOL_UNIX),
|
|
pgsTimer(new pgScriptTimer(this)),
|
|
m_loadingfile(false)
|
|
{
|
|
pgScript->SetCaller(this, PGSCRIPT_COMPLETE);
|
|
|
|
mainForm = form;
|
|
conn = _conn;
|
|
autoSave = settings->GetAutosaveQuery();
|
|
loading = true;
|
|
closing = false;
|
|
|
|
dlgName = wxT("frmQuery");
|
|
recentKey = wxT("RecentFiles");
|
|
RestorePosition(100, 100, 600, 500, 450, 300);
|
|
wxLogInfo(wxT("frmQuery::Create window"));
|
|
explainCanvas = NULL;
|
|
|
|
// notify wxAUI which frame to use
|
|
manager.SetManagedWindow(this);
|
|
manager.SetFlags(wxAUI_MGR_DEFAULT | wxAUI_MGR_TRANSPARENT_DRAG);
|
|
|
|
SetMinSize(FromDIP(wxSize(450, 300)));
|
|
//seticon();
|
|
SetFont(settings->GetSystemFont());
|
|
menuBar = new wxMenuBar();
|
|
|
|
fileMenu = new wxMenu();
|
|
recentFileMenu = new wxMenu();
|
|
fileMenu->Append(MNU_NEW, _("&New window\tCtrl-N"), _("Open a new query window"));
|
|
fileMenu->Append(MNU_OPEN, _("&Open...\tCtrl-O"), _("Open a query file"));
|
|
fileMenu->Append(MNU_SAVE, _("&Save\tCtrl-S"), _("Save current file"));
|
|
saveasImageMenu = new wxMenu();
|
|
saveasImageMenu->Append(MNU_SAVEAS, _("Query (text)"), _("Save file under new name"));
|
|
saveasImageMenu->Append(MNU_SAVEAS_IMAGE_GQB, _("Graphical Query (image)"), _("Save Graphical Query as an image"));
|
|
saveasImageMenu->Append(MNU_SAVEAS_IMAGE_EXPLAIN, _("Explain (image)"), _("Save output of Explain as an image"));
|
|
fileMenu->Append(wxID_ANY, _("Save as"), saveasImageMenu);
|
|
|
|
// SQL tabs related menu items
|
|
fileMenu->AppendSeparator();
|
|
fileMenu->Append(MNU_NEWSQLTAB, _("New SQL &tab\tCtrl-T"), _("Open a new query tab"));
|
|
|
|
fileMenu->AppendSeparator();
|
|
fileMenu->Append(MNU_EXPORT, _("&Export...\tAlt+E"), _("Export data to file"));
|
|
fileMenu->Append(MNU_QUICKREPORT, _("&Quick report..."), _("Run a quick report..."));
|
|
fileMenu->AppendSeparator();
|
|
fileMenu->Append(MNU_RECENT, _("&Recent files"), recentFileMenu);
|
|
fileMenu->Append(MNU_EXIT, _("E&xit\tCtrl-W"), _("Exit query window"));
|
|
|
|
menuBar->Append(fileMenu, _("&File"));
|
|
|
|
lineEndMenu = new wxMenu();
|
|
lineEndMenu->AppendRadioItem(MNU_LF, _("Unix (LF)"), _("Use Unix style line endings"));
|
|
lineEndMenu->AppendRadioItem(MNU_CRLF, _("DOS (CRLF)"), _("Use DOS style line endings"));
|
|
lineEndMenu->AppendRadioItem(MNU_CR, _("Mac (CR)"), _("Use Mac style line endings"));
|
|
|
|
editMenu = new wxMenu();
|
|
editMenu->Append(MNU_UNDO, _("&Undo\tCtrl-Z"), _("Undo last action"), wxITEM_NORMAL);
|
|
editMenu->Append(MNU_REDO, _("&Redo\tCtrl-Y"), _("Redo last action"), wxITEM_NORMAL);
|
|
editMenu->AppendSeparator();
|
|
editMenu->Append(MNU_CUT, _("Cu&t\tCtrl-X"), _("Cut selected text to clipboard"), wxITEM_NORMAL);
|
|
editMenu->Append(MNU_COPY, _("&Copy\tCtrl-C"), _("Copy selected text to clipboard"), wxITEM_NORMAL);
|
|
editMenu->Append(MNU_PASTE, _("&Paste\tCtrl-V"), _("Paste selected text from clipboard"), wxITEM_NORMAL);
|
|
editMenu->Append(MNU_CLEAR, _("C&lear window"), _("Clear edit window"), wxITEM_NORMAL);
|
|
editMenu->AppendSeparator();
|
|
editMenu->Append(MNU_FIND, _("&Find and Replace\tCtrl-F"), _("Find and replace text"), wxITEM_NORMAL);
|
|
editMenu->AppendSeparator();
|
|
editMenu->Append(MNU_AUTOINDENT, _("&Auto indent"), _("Automatically indent text to the same level as the preceding line"), wxITEM_CHECK);
|
|
|
|
// editMenu->AppendSeparator();
|
|
formatMenu = new wxMenu();
|
|
formatMenu->Append(MNU_UPPER_CASE, _("&Upper case\tCtrl-U"), _("Change the selected text to upper case"));
|
|
formatMenu->Append(MNU_LOWER_CASE, _("&Lower case\tCtrl-Shift-U"), _("Change the selected text to lower case"));
|
|
formatMenu->AppendSeparator();
|
|
formatMenu->Append(MNU_BLOCK_INDENT, _("Block &Indent\tTab"), _("Indent the selected block"));
|
|
formatMenu->Append(MNU_BLOCK_OUTDENT, _("Block &Outdent\tShift-Tab"), _("Outdent the selected block"));
|
|
formatMenu->Append(MNU_COMMENT_TEXT, _("Co&mment Text\tCtrl-K"), _("Comment out the selected text"));
|
|
formatMenu->Append(MNU_UNCOMMENT_TEXT, _("Uncomme&nt Text\tCtrl-Shift-K"), _("Uncomment the selected text"));
|
|
formatMenu->Append(MNU_DOUBLEQUOTE_TEXT, _("Double the single quote\tCtrl-'"), _("Double the single quote"));
|
|
formatMenu->Append(MNU_UNDOUBLEQUOTE_TEXT, _("Undouble the single quote\tCtrl-Shift-'"), _("Undouble the single quote"));
|
|
formatMenu->AppendSeparator();
|
|
formatMenu->Append(MNU_EXTERNALFORMAT, _("External Format\tCtrl-Shift-F"), _("Call external formatting command"));
|
|
formatMenu->Append(MNU_EXTERNALALIGN, _("External Align...\tCtrl-Shift-A"), _("Call external align command"));
|
|
editMenu->AppendSubMenu(formatMenu, _("F&ormat"));
|
|
editMenu->Append(MNU_LINEENDS, _("&Line ends"), lineEndMenu);
|
|
editMenu->Append(MNU_AUTOREPLACE_MANAGE, _("Manage autoreplace..."), _("Edit and delete autoreplace strings"));
|
|
editMenu->Append(MNU_AUTOEDITOBJECT, _("Open object\tF4"), _("Open object in brouser tree"));
|
|
editMenu->Append(MNU_TRANSFORM, _("Text transform...\tCtrl+M"), _("Open dialog transform"));
|
|
|
|
autoreplace = queryMacroFileProvider::LoadAutoReplace(true);
|
|
|
|
menuBar->Append(editMenu, _("&Edit"));
|
|
|
|
queryMenu = new wxMenu();
|
|
queryMenu->Append(MNU_EXECUTE, _("&Execute\tF8"), _("Execute query"));
|
|
queryMenu->Append(MNU_EXECUTE_2, _("&Execute new output\tShift-F8"), _("Execute query in new output"));
|
|
queryMenu->Append(MNU_EXECPGS, _("Execute &pgScript\tF6"), _("Execute pgScript"));
|
|
queryMenu->Append(MNU_EXECFILE, _("Execute to file\tF5"), _("Execute query, write result to file"));
|
|
queryMenu->Append(MNU_EXPLAIN, _("E&xplain\tF7"), _("Explain query"));
|
|
queryMenu->Append(MNU_EXPLAINANALYZE, _("Explain analyze\tShift-F7"), _("Explain and analyze query"));
|
|
|
|
|
|
wxMenu *eo = new wxMenu();
|
|
eo->Append(MNU_VERBOSE, _("Verbose"), _("Explain verbose query"), wxITEM_CHECK);
|
|
eo->Append(MNU_COSTS, _("Costs"), _("Explain analyze query with (or without) costs"), wxITEM_CHECK);
|
|
eo->Append(MNU_BUFFERS, _("Buffers"), _("Explain analyze query with (or without) buffers"), wxITEM_CHECK);
|
|
eo->Append(MNU_TIMING, _("Timing"), _("Explain analyze query with (or without) timing"), wxITEM_CHECK);
|
|
queryMenu->Append(MNU_EXPLAINOPTIONS, _("Explain &options"), eo, _("Options modifying Explain output"));
|
|
queryMenu->AppendSeparator();
|
|
queryMenu->Append(MNU_SAVEHISTORY, _("Save history"), _("Save history of executed commands."));
|
|
queryMenu->Append(MNU_CLEARHISTORY, _("Clear history"), _("Clear history window."));
|
|
queryMenu->AppendSeparator();
|
|
queryMenu->Append(MNU_AUTOSELECTQUERY, _("&Auto-Select"), _("Auto select query"), wxITEM_CHECK);
|
|
queryMenu->Append(MNU_AUTOROLLBACK, _("&Auto-Rollback"), _("Rollback the current transaction if an error is detected"), wxITEM_CHECK);
|
|
queryMenu->Append(MNU_AUTOCOMMIT, _("&Auto-Commit"), _("Auto commit the cuurent transaction"), wxITEM_CHECK);
|
|
queryMenu->AppendSeparator();
|
|
queryMenu->Append(MNU_CANCEL, _("&Cancel\tAlt-Break"), _("Cancel query"));
|
|
queryMenu->AppendSeparator();
|
|
queryMenu->Append(MNU_DOCOMMIT, _("Commit\tF10"), _("Commit"));
|
|
queryMenu->Append(MNU_DOROLLBACK, _("Rollback\tShift-F10"), _("Rollback"));
|
|
menuBar->Append(queryMenu, _("&Query"));
|
|
|
|
favouritesMenu = new wxMenu();
|
|
favouritesMenu->Append(MNU_FAVOURITES_ADD, _("Add favourite..."), _("Add current query to favourites"));
|
|
favouritesMenu->Append(MNU_FAVOURITES_INJECT, _("Inject\tF2"), _("Replace a word under cursor with a favourite with same name"));
|
|
favouritesMenu->Append(MNU_FAVOURITES_MANAGE, _("Manage favourites..."), _("Edit and delete favourites"));
|
|
favouritesMenu->AppendSeparator();
|
|
favourites = 0L;
|
|
UpdateFavouritesList();
|
|
menuBar->Append(favouritesMenu, _("Fav&ourites"));
|
|
|
|
macrosMenu = new wxMenu();
|
|
macrosMenu->Append(MNU_MACROS_MANAGE, _("Manage macros..."), _("Edit and delete macros"));
|
|
macrosMenu->AppendSeparator();
|
|
macros = 0L;
|
|
UpdateMacrosList();
|
|
menuBar->Append(macrosMenu, _("&Macros"));
|
|
|
|
// View menu
|
|
viewMenu = new wxMenu();
|
|
viewMenu->Append(MNU_DATABASEBAR, _("&Connection bar\tCtrl-Alt-B"), _("Show or hide the database selection bar."), wxITEM_CHECK);
|
|
viewMenu->Append(MNU_OUTPUTPANE, _("&Output pane\tCtrl-Alt-O"), _("Show or hide the output pane."), wxITEM_CHECK);
|
|
viewMenu->Append(MNU_SCRATCHPAD, _("S&cratch pad\tCtrl-Alt-S"), _("Show or hide the scratch pad."), wxITEM_CHECK);
|
|
viewMenu->Append(MNU_TOOLBAR, _("&Tool bar\tCtrl-Alt-T"), _("Show or hide the tool bar."), wxITEM_CHECK);
|
|
viewMenu->AppendSeparator();
|
|
viewMenu->Append(MNU_SHOWINDENTGUIDES, _("&Indent guides"), _("Enable or disable display of indent guides"), wxITEM_CHECK);
|
|
viewMenu->Append(MNU_SHOWLINEENDS, _("&Line ends"), _("Enable or disable display of line ends"), wxITEM_CHECK);
|
|
viewMenu->Append(MNU_SHOWWHITESPACE, _("&Whitespace"), _("Enable or disable display of whitespaces"), wxITEM_CHECK);
|
|
viewMenu->Append(MNU_WORDWRAP, _("&Word wrap"), _("Enable or disable word wrapping"), wxITEM_CHECK);
|
|
viewMenu->Append(MNU_SHOWLINENUMBER, _("&Line number"), _("Enable or disable display of line number"), wxITEM_CHECK);
|
|
viewMenu->AppendSeparator();
|
|
viewMenu->Append(MNU_DEFAULTVIEW, _("&Default view\tCtrl-Alt-V"), _("Restore the default view."));
|
|
|
|
menuBar->Append(viewMenu, _("&View"));
|
|
|
|
wxMenu *helpMenu = new wxMenu();
|
|
helpMenu->Append(MNU_CONTENTS, _("&Help"), _("Open the helpfile."));
|
|
helpMenu->Append(MNU_HELP, _("&SQL Help\tF1"), _("Display help on SQL commands."));
|
|
|
|
#ifdef __WXMAC__
|
|
menuFactories = new menuFactoryList();
|
|
aboutFactory *af = new aboutFactory(menuFactories, helpMenu, 0);
|
|
wxApp::s_macAboutMenuItemId = af->GetId();
|
|
menuFactories->RegisterMenu(this, wxCommandEventHandler(pgFrame::OnAction));
|
|
#endif
|
|
|
|
menuBar->Append(helpMenu, _("&Help"));
|
|
|
|
SetMenuBar(menuBar);
|
|
|
|
queryMenu->Check(MNU_VERBOSE, settings->GetExplainVerbose());
|
|
queryMenu->Check(MNU_COSTS, settings->GetExplainCosts());
|
|
queryMenu->Check(MNU_BUFFERS, settings->GetExplainBuffers());
|
|
queryMenu->Check(MNU_TIMING, settings->GetExplainTiming());
|
|
|
|
UpdateRecentFiles();
|
|
#define USER_KEY_DEF 15
|
|
wxAcceleratorEntry entries[16+ USER_KEY_DEF];
|
|
std::map<std::string, int> mapping;
|
|
mapping["MNU_EXECFILE"] = MNU_EXECFILE;
|
|
mapping["MNU_EXECPGS"] = MNU_EXECPGS;
|
|
mapping["MNU_EXECUTE"] = MNU_EXECUTE;
|
|
mapping["MNU_EXECUTE_2"] = MNU_EXECUTE_2;
|
|
mapping["MNU_EXPLAIN"] = MNU_EXPLAIN;
|
|
mapping["MNU_NEWSQLTAB"] = MNU_NEWSQLTAB;
|
|
mapping["MNU_EXPLAINANALYZE"] = MNU_EXPLAINANALYZE;
|
|
mapping["MNU_EXIT"] = MNU_EXIT;
|
|
mapping["MNU_EXPORT"] = MNU_EXPORT;
|
|
mapping["MNU_EXTERNALFORMAT"] = MNU_EXTERNALFORMAT;
|
|
mapping["MNU_COMMENT_TEXT"] = MNU_COMMENT_TEXT;
|
|
mapping["MNU_UNCOMMENT_TEXT"] = MNU_UNCOMMENT_TEXT;
|
|
mapping["MNU_DOROLLBACK"] = MNU_DOROLLBACK;
|
|
mapping["MNU_DOCOMMIT"] = MNU_DOCOMMIT;
|
|
wxString tempDir = dataDir+wxFileName::GetPathSeparator()+"keymap.txt";
|
|
wxLogInfo(wxT("frmQuery::Create key map ..."));
|
|
int idx = 0;
|
|
if (wxFileName::FileExists(tempDir) )
|
|
{
|
|
wxUtfFile filer(tempDir, wxFile::read, wxFONTENCODING_UTF8);
|
|
filer.IsOpened();
|
|
wxString str = "";
|
|
filer.Read(str);
|
|
filer.Close();
|
|
#ifdef WIN32
|
|
wxStringTokenizer tk(str, "\n\r", wxTOKEN_DEFAULT);
|
|
#else
|
|
wxStringTokenizer tk(str, "\n", wxTOKEN_DEFAULT);
|
|
#endif
|
|
int d = 0;
|
|
while (tk.HasMoreTokens())
|
|
{
|
|
d++;
|
|
wxString l = tk.GetNextToken();
|
|
wxString mnu = l.BeforeFirst(' ');
|
|
wxString cmdkey = l.AfterLast(' ');
|
|
if (l.IsEmpty()) continue;
|
|
if (idx >= (USER_KEY_DEF)) break;
|
|
int imnu = 0;
|
|
auto f = mapping.find(std::string(mnu.mb_str()));
|
|
if (f== mapping.end()) {
|
|
std::string s="";
|
|
for (auto& t : mapping)
|
|
s += t.first + ",";
|
|
wxLogError(wxT("frmQuery::keymap.txt file : line=[%d] menu=[%s] bad menu name. Possible value(%s) "), d, mnu,wxString(s) );
|
|
continue;
|
|
}
|
|
imnu = f->second;
|
|
if (entries[idx].FromString(cmdkey)) {
|
|
entries[idx].Set(entries[idx].GetFlags(), entries[idx].GetKeyCode(), imnu);
|
|
wxLogInfo(wxT("frmQuery::keymap.txt file : line=[%d] menu=[%d] key=[%s] "), d, imnu, entries[idx].ToString());
|
|
}
|
|
else
|
|
{
|
|
wxLogError(wxT("frmQuery::keymap.txt file : line=[%d] menu=[%s] key=[%s] bad key. Ignore this line"), d, mnu, cmdkey);
|
|
continue;
|
|
}
|
|
idx++;
|
|
}
|
|
}
|
|
entries[idx++].Set(wxACCEL_CTRL, (int)'E', MNU_EXECUTE);
|
|
entries[idx++].Set(wxACCEL_CTRL, (int)'O', MNU_OPEN);
|
|
entries[idx++].Set(wxACCEL_CTRL, (int)'S', MNU_SAVE);
|
|
entries[idx++].Set(wxACCEL_CTRL, (int)'F', MNU_FIND);
|
|
entries[idx++].Set(wxACCEL_CTRL, (int)'R', MNU_REPLACE);
|
|
entries[idx++].Set(wxACCEL_NORMAL, WXK_F8, MNU_EXECUTE);
|
|
entries[idx++].Set(wxACCEL_NORMAL, WXK_F7, MNU_EXPLAIN);
|
|
entries[idx++].Set(wxACCEL_ALT, WXK_PAUSE, MNU_CANCEL);
|
|
entries[idx++].Set(wxACCEL_CTRL, (int)'A', MNU_SELECTALL);
|
|
entries[idx++].Set(wxACCEL_NORMAL, WXK_F1, MNU_HELP);
|
|
entries[idx++].Set(wxACCEL_CTRL, (int)'N', MNU_NEW);
|
|
entries[idx++].Set(wxACCEL_NORMAL, WXK_F6, MNU_EXECPGS);
|
|
entries[idx++].Set(wxACCEL_NORMAL, WXK_F5, MNU_EXECFILE);
|
|
entries[idx++].Set(wxACCEL_CTRL, (int)'T', MNU_NEWSQLTAB);
|
|
|
|
entries[idx++].Set(wxACCEL_CTRL, (int)'1', MNU_GENERATESQL+1);
|
|
entries[idx++].Set(wxACCEL_CTRL, (int)'2', MNU_GENERATESQL+2);
|
|
|
|
|
|
wxAcceleratorTable accel(idx, entries);
|
|
SetAcceleratorTable(accel);
|
|
wxLogInfo(wxT("frmQuery::Create key map Ok"));
|
|
queryMenu->Enable(MNU_CANCEL, false);
|
|
|
|
int iWidths[7] = {0, -1, 40, 250, 80, 80, 80};
|
|
statusBar = CreateStatusBar(7);
|
|
SetStatusBarPane(-1);
|
|
SetStatusWidths(7, iWidths);
|
|
SetStatusText(_("ready"), STATUSPOS_MSGS);
|
|
|
|
toolBar = new ctlMenuToolbar(this, -1, wxDefaultPosition, wxDefaultSize, wxTB_FLAT | wxTB_NODIVIDER);
|
|
wxSize tbsz((32), (32));
|
|
toolBar->SetToolBitmapSize(FromDIP(wxSize(32, 32)));
|
|
wxLogInfo(wxT("frmQuery::Create tool bar .."));
|
|
toolBar->AddTool(MNU_NEWSQLTAB, wxEmptyString, GetBundleSVG(file_new_png_bmp, "file_new.svg", tbsz), _("New SQL tab"), wxITEM_NORMAL);
|
|
toolBar->AddTool(MNU_OPEN, wxEmptyString, GetBundleSVG(file_open_png_bmp, "file_open.svg", tbsz) , _("Open file"), wxITEM_NORMAL);
|
|
toolBar->AddTool(MNU_SAVE, wxEmptyString, GetBundleSVG(file_save_png_bmp, "file_save.svg", tbsz) , _("Save file"), wxITEM_NORMAL);
|
|
toolBar->AddSeparator();
|
|
toolBar->AddTool(MNU_CUT, wxEmptyString, GetBundleSVG(clip_cut_png_bmp, "clip_cut.svg", tbsz) , _("Cut selected text to clipboard"), wxITEM_NORMAL);
|
|
toolBar->AddTool(MNU_COPY, wxEmptyString, GetBundleSVG(clip_copy_png_bmp, "clip_copy.svg", tbsz), _("Copy selected text to clipboard"), wxITEM_NORMAL);
|
|
toolBar->AddTool(MNU_PASTE, wxEmptyString, GetBundleSVG(clip_paste_png_bmp, "clip_paste.svg", tbsz), _("Paste selected text from clipboard"), wxITEM_NORMAL);
|
|
toolBar->AddTool(MNU_CLEAR, wxEmptyString, GetBundleSVG(edit_clear_png_bmp, "edit_clear.svg", tbsz), _("Clear edit window"), wxITEM_NORMAL);
|
|
toolBar->AddSeparator();
|
|
toolBar->AddTool(MNU_UNDO, wxEmptyString, GetBundleSVG(edit_undo_png_bmp, "edit_undo.svg", tbsz), _("Undo last action"), wxITEM_NORMAL);
|
|
toolBar->AddTool(MNU_REDO, wxEmptyString, GetBundleSVG(edit_redo_png_bmp, "edit_redo.svg", tbsz), _("Redo last action"), wxITEM_NORMAL);
|
|
toolBar->AddSeparator();
|
|
toolBar->AddTool(MNU_FIND, wxEmptyString, GetBundleSVG(edit_find_png_bmp, "edit_find.svg", tbsz), _("Find and replace text"), wxITEM_NORMAL);
|
|
toolBar->AddSeparator();
|
|
|
|
toolBar->AddTool(MNU_EXECUTE, wxEmptyString, GetBundleSVG(query_execute_png_bmp, "query_execute.svg", tbsz), _("Execute query"), wxITEM_NORMAL);
|
|
toolBar->AddTool(MNU_EXECPGS, wxEmptyString, GetBundleSVG(query_pgscript_png_bmp, "query_pgscript.svg", tbsz), _("Execute pgScript"), wxITEM_NORMAL);
|
|
toolBar->AddTool(MNU_EXECFILE, wxEmptyString, GetBundleSVG(query_execfile_png_bmp, "query_execfile.svg", tbsz), _("Execute query, write result to file"), wxITEM_NORMAL);
|
|
toolBar->AddTool(MNU_EXPLAIN, wxEmptyString, GetBundleSVG(query_explain_png_bmp, "query_explain.svg", tbsz), _("Explain query"), wxITEM_NORMAL);
|
|
toolBar->AddTool(MNU_CANCEL, wxEmptyString, GetBundleSVG(query_cancel_png_bmp, "query_cancel.svg", tbsz), _("Cancel query"), wxITEM_NORMAL);
|
|
toolBar->AddSeparator();
|
|
|
|
toolBar->AddTool(MNU_DOCOMMIT, wxEmptyString, GetBundleSVG(query_commit_png_bmp, "query_commit.svg", tbsz), _("Commit"), wxITEM_NORMAL);
|
|
toolBar->AddTool(MNU_DOROLLBACK, wxEmptyString, GetBundleSVG(query_rollback_png_bmp, "query_rollback.svg", tbsz), _("Rollback"), wxITEM_NORMAL);
|
|
bool chk = settings->GetAutoCommit();
|
|
mode_a = GetBundleSVG(mode_autocommit_png_bmp, "mode_autocommit.svg", tbsz);
|
|
mode_t = GetBundleSVG(mode_transaction_png_bmp, "mode_transaction.svg", tbsz);
|
|
if (chk)
|
|
toolBar->AddTool(MNU_MODE_TRANSACTION, wxEmptyString, mode_a, _("Mode transaction"), wxITEM_NORMAL);
|
|
else
|
|
toolBar->AddTool(MNU_MODE_TRANSACTION, wxEmptyString, mode_t, _("Mode transaction"), wxITEM_NORMAL);
|
|
|
|
toolBar->AddSeparator();
|
|
|
|
toolBar->AddTool(MNU_HELP, wxEmptyString, GetBundleSVG(help_png_bmp, "help.svg", tbsz), _("Display help on SQL commands."), wxITEM_NORMAL);
|
|
|
|
toolBar->Realize();
|
|
wxLogInfo(wxT("frmQuery::Create tool bar Ok"));
|
|
wxSize toolw = toolBar->GetBestSize();
|
|
// Add the database selection bar
|
|
cbConnection = new wxBitmapComboBox(this, CTRLID_CONNECTION, wxEmptyString, wxDefaultPosition, wxSize(-1, -1), wxArrayString(), wxCB_READONLY | wxCB_DROPDOWN);
|
|
cbConnection->Append(conn->GetName(), CreateBitmap(GetServerColour(conn)), (void *)conn);
|
|
cbConnection->Append(_("<new connection>"), wxNullBitmap, (void *) NULL);
|
|
|
|
//Create SQL editor notebook
|
|
sqlNotebook = new ctlAuiNotebook(this, CTL_NTBKCENTER, wxDefaultPosition, wxDefaultSize, wxAUI_NB_TOP | wxAUI_NB_TAB_SPLIT | wxAUI_NB_TAB_MOVE | wxAUI_NB_SCROLL_BUTTONS | wxAUI_NB_WINDOWLIST_BUTTON);
|
|
|
|
// Create panel for query
|
|
wxPanel *pnlQuery = new wxPanel(sqlNotebook);
|
|
|
|
// Create the outer box sizer
|
|
wxBoxSizer *boxQuery = new wxBoxSizer(wxVERTICAL);
|
|
|
|
// Create the inner box sizer
|
|
// This one will contain the label, the combobox, and the two buttons
|
|
wxBoxSizer *boxHistory = new wxBoxSizer(wxHORIZONTAL);
|
|
|
|
// Label
|
|
wxStaticText *label = new wxStaticText(pnlQuery, 0, _("Previous queries"));
|
|
boxHistory->Add(label, 0, wxALL | wxALIGN_CENTER_VERTICAL, 1);
|
|
|
|
// Query combobox
|
|
sqlQueries = new wxComboBox(pnlQuery, CTL_SQLQUERYCBOX, wxT(""), wxDefaultPosition, wxDefaultSize, wxArrayString(), wxCB_DROPDOWN | wxCB_READONLY);
|
|
sqlQueries->SetToolTip(_("Previous queries"));
|
|
LoadQueries();
|
|
boxHistory->Add(sqlQueries, 1, wxEXPAND | wxALL , 1);
|
|
|
|
// Delete Current button
|
|
btnDeleteCurrent = new wxButton(pnlQuery, CTL_DELETECURRENTBTN, _("Delete"));
|
|
btnDeleteCurrent->Enable(false);
|
|
boxHistory->Add(btnDeleteCurrent, 0, wxALL | wxALIGN_CENTER_VERTICAL, 1);
|
|
|
|
// Delete All button
|
|
btnDeleteAll = new wxButton(pnlQuery, CTL_DELETEALLBTN, _("Delete All"));
|
|
btnDeleteAll->Enable(sqlQueries->GetCount() > 0);
|
|
boxHistory->Add(btnDeleteAll, 0, wxALL | wxALIGN_CENTER_VERTICAL, 1);
|
|
boxQuery->Add(boxHistory, 0, wxEXPAND | wxALL, 1);
|
|
boxHistory->ShowItems(!settings->GetHideQueryHistory());
|
|
// Create the other inner box sizer
|
|
// This one will contain the SQL box
|
|
wxBoxSizer *boxSQL = new wxBoxSizer(wxHORIZONTAL);
|
|
|
|
// Use sqlQueryBook instead of sqlQuery and put the book inside boxSQL sizer.
|
|
// We don't add any SQL tabs until all menu items are initialized from settings.
|
|
sqlQueryBook = new ctlAuiNotebook(pnlQuery, CTL_SQLQUERYBOOK, wxDefaultPosition, wxDefaultSize, wxAUI_NB_TOP | wxAUI_NB_TAB_SPLIT | wxAUI_NB_TAB_MOVE | wxAUI_NB_SCROLL_BUTTONS | wxAUI_NB_CLOSE_ON_ACTIVE_TAB | wxAUI_NB_WINDOWLIST_BUTTON);
|
|
sqlQueryCounter = 0;
|
|
sqlQueryExec = NULL;
|
|
sqlQueryExecLast = NULL;
|
|
|
|
boxSQL->Add(sqlQueryBook, 1, wxEXPAND | wxRIGHT | wxLEFT | wxBOTTOM, 1);
|
|
|
|
boxQuery->Add(boxSQL, 1, wxEXPAND | wxRIGHT | wxLEFT | wxBOTTOM, 1);
|
|
|
|
// Auto-sizing
|
|
pnlQuery->SetSizer(boxQuery);
|
|
boxQuery->Fit(pnlQuery);
|
|
|
|
// Results pane
|
|
outputPane = new ctlAuiNotebook(this, CTL_NTBKGQB, wxDefaultPosition, wxSize(500, 300), wxAUI_NB_TOP | wxAUI_NB_TAB_SPLIT | wxAUI_NB_TAB_MOVE | wxAUI_NB_SCROLL_BUTTONS | wxAUI_NB_WINDOWLIST_BUTTON);
|
|
sqlResult = new ctlSQLResult(outputPane, conn, CTL_SQLRESULT, wxDefaultPosition, wxDefaultSize);
|
|
|
|
int len = sizeof(ctlSQL) / sizeof(ctlSQL[0]);
|
|
for (int i=0;i<len;i++) ctlSQL[i]=NULL;
|
|
for (int i=0;i<len;i++) ctlSBox[i]=NULL;
|
|
ctlSQL[0] = sqlResult;
|
|
indexResult=0;
|
|
explainCanvas = new ExplainCanvas(outputPane);
|
|
msgResult = new wxTextCtrl(outputPane, CTL_MSGRESULT, wxT(""), wxDefaultPosition, wxDefaultSize, wxTE_MULTILINE | wxTE_READONLY | wxTE_DONTWRAP);
|
|
msgResult->SetFont(settings->GetSQLFont());
|
|
msgHistory = new wxTextCtrl(outputPane, CTL_MSGHISTORY, wxT(""), wxDefaultPosition, wxDefaultSize, wxTE_MULTILINE | wxTE_READONLY | wxTE_DONTWRAP);
|
|
msgHistory->SetFont(settings->GetSQLFont());
|
|
// Graphical Canvas
|
|
// initialize values
|
|
model = new gqbModel();
|
|
controller = new gqbController(model, sqlNotebook, outputPane, wxSize(GQB_MIN_WIDTH, GQB_MIN_HEIGHT));
|
|
firstTime = true; // Inform to GQB that the tree of table haven't filled.
|
|
gqbUpdateRunning = false; // Are we already updating the SQL query - event recursion protection.
|
|
adjustSizesTimer = NULL; // Timer used to avoid a bug when close outputPane
|
|
|
|
// Setup SQL editor notebook NBP_SQLEDTR
|
|
sqlNotebook->AddPage(pnlQuery, _("SQL Editor"));
|
|
sqlNotebook->AddPage(controller->getViewContainer(), _("Graphical Query Builder"));
|
|
sqlNotebook->SetSelection(0);
|
|
|
|
outputPane->AddPage(sqlResult, _("Data Output"));
|
|
outputPane->AddPage(explainCanvas, _("Explain"));
|
|
outputPane->AddPage(msgResult, _("Messages"));
|
|
outputPane->AddPage(msgHistory, _("History"));
|
|
|
|
sqlResult->Connect(wxID_ANY, wxEVT_SET_FOCUS, wxFocusEventHandler(frmQuery::OnFocus));
|
|
msgResult->Connect(wxID_ANY, wxEVT_SET_FOCUS, wxFocusEventHandler(frmQuery::OnFocus));
|
|
msgHistory->Connect(wxID_ANY, wxEVT_SET_FOCUS, wxFocusEventHandler(frmQuery::OnFocus));
|
|
|
|
// Now, the scratchpad
|
|
scratchPad = new wxTextCtrl(this, CTL_SCRATCHPAD, wxT(""), wxDefaultPosition, wxDefaultSize, wxTE_MULTILINE | wxHSCROLL);
|
|
wxSize w1 = cbConnection->GetBestSize();
|
|
// Kickstart wxAUI
|
|
manager.AddPane(toolBar, wxAuiPaneInfo().Name(wxT("toolBar")).Caption(_("Tool bar")).ToolbarPane().Top().LeftDockable(false).RightDockable(false));
|
|
manager.AddPane(cbConnection, wxAuiPaneInfo().Name(wxT("databaseBar")).Caption(_("Connection bar")).ToolbarPane().Top().LeftDockable(false).RightDockable(false));
|
|
|
|
manager.AddPane(outputPane, wxAuiPaneInfo().Name(wxT("outputPane")).Caption(_("Output pane")).Bottom().MinSize(wxSize(200, 100)).BestSize(wxSize(550, 300)));
|
|
manager.AddPane(scratchPad, wxAuiPaneInfo().Name(wxT("scratchPad")).Caption(_("Scratch pad")).Right().MinSize(wxSize(100, 100)).BestSize(wxSize(250, 200)));
|
|
manager.AddPane(sqlNotebook, wxAuiPaneInfo().Name(wxT("sqlQuery")).Caption(_("SQL query")).Center().CaptionVisible(false).CloseButton(false).MinSize(wxSize(200, 100)).BestSize(wxSize(350, 200)));
|
|
|
|
// Now load the layout
|
|
wxString perspective;
|
|
settings->Read(wxT("frmQuery/Perspective-") + wxString(FRMQUERY_PERSPECTIVE_VER), &perspective, FRMQUERY_DEFAULT_PERSPECTIVE);
|
|
manager.LoadPerspective(perspective, true);
|
|
outputPaneInfo = manager.SavePerspective();
|
|
// and reset the captions for the current language
|
|
manager.GetPane(wxT("toolBar")).Caption(_("Tool bar"));
|
|
manager.GetPane(wxT("databaseBar")).BestSize(w1);
|
|
manager.GetPane(wxT("toolBar")).BestSize(toolw);
|
|
manager.GetPane(wxT("databaseBar")).Caption(_("Connection bar"));
|
|
manager.GetPane(wxT("sqlQuery")).Caption(_("SQL query"));
|
|
manager.GetPane(wxT("outputPane")).Caption(_("Output pane"));
|
|
manager.GetPane(wxT("scratchPad")).Caption(_("Scratch pad"));
|
|
|
|
|
|
// Sync the View menu options
|
|
viewMenu->Check(MNU_DATABASEBAR, manager.GetPane(wxT("databaseBar")).IsShown());
|
|
viewMenu->Check(MNU_TOOLBAR, manager.GetPane(wxT("toolBar")).IsShown());
|
|
viewMenu->Check(MNU_OUTPUTPANE, manager.GetPane(wxT("outputPane")).IsShown());
|
|
viewMenu->Check(MNU_SCRATCHPAD, manager.GetPane(wxT("scratchPad")).IsShown());
|
|
wxAuiPaneInfo &pn = manager.GetPane(wxT("outputPane"));
|
|
if (!pn.HasMaximizeButton()) {
|
|
pn.MaximizeButton(true);
|
|
}
|
|
// tell the manager to "commit" all the changes just made
|
|
manager.Update();
|
|
|
|
bool bVal;
|
|
|
|
|
|
// Auto-Select
|
|
bVal = settings->GetAutoSelectQuery();
|
|
queryMenu->Check(MNU_AUTOSELECTQUERY, bVal);
|
|
|
|
// Auto-rollback
|
|
bVal = settings->GetAutoRollback();
|
|
queryMenu->Check(MNU_AUTOROLLBACK, bVal);
|
|
|
|
// Auto-commit
|
|
bVal = settings->GetAutoCommit();
|
|
queryMenu->Check(MNU_AUTOCOMMIT, bVal);
|
|
|
|
// Auto indent
|
|
settings->Read(wxT("frmQuery/AutoIndent"), &bVal, true);
|
|
editMenu->Check(MNU_AUTOINDENT, bVal);
|
|
|
|
// Word wrap
|
|
settings->Read(wxT("frmQuery/WordWrap"), &bVal, false);
|
|
viewMenu->Check(MNU_WORDWRAP, bVal);
|
|
|
|
// Indent Guides
|
|
settings->Read(wxT("frmQuery/ShowIndentGuides"), &bVal, false);
|
|
viewMenu->Check(MNU_SHOWINDENTGUIDES, bVal);
|
|
|
|
// Whitespace
|
|
settings->Read(wxT("frmQuery/ShowWhitespace"), &bVal, false);
|
|
viewMenu->Check(MNU_SHOWWHITESPACE, bVal);
|
|
|
|
// Line ends
|
|
settings->Read(wxT("frmQuery/ShowLineEnds"), &bVal, false);
|
|
viewMenu->Check(MNU_SHOWLINEENDS, bVal);
|
|
|
|
// Line number
|
|
settings->Read(wxT("frmQuery/ShowLineNumber"), &bVal, false);
|
|
viewMenu->Check(MNU_SHOWLINENUMBER, bVal);
|
|
|
|
// Create the SQL box. After this, sqlQuery variable can be used.
|
|
|
|
if (!file.IsEmpty() && wxFileName::FileExists(file))
|
|
{
|
|
wxString t = wxEmptyString;
|
|
SqlBookAddPage(t);
|
|
wxFileName fn = file;
|
|
lastFilename = fn.GetFullName();
|
|
lastDir = fn.GetPath();
|
|
lastPath = fn.GetFullPath();
|
|
OpenLastFile();
|
|
sqlQuery->Colourise(0, sqlQuery->GetLength());
|
|
}
|
|
else if (!query.IsNull())
|
|
{
|
|
wxString t = wxEmptyString;
|
|
SqlBookAddPage(t);
|
|
sqlQuery->SetText(query);
|
|
SetLineEndingStyle();
|
|
sqlQuery->Colourise(0, sqlQuery->GetLength());
|
|
wxSafeYield(); // needed to process sqlQuery modify event
|
|
sqlQuery->SetChanged(false);
|
|
sqlQuery->SetOrigin(ORIGIN_INITIAL);
|
|
/* _title if not empty should contain displayName of base object for the query.
|
|
It's pretty good for a proposed filename if the user chooses to Save As. */
|
|
lastFilename = _title;
|
|
setExtendedTitle();
|
|
SqlBookUpdatePageTitle();
|
|
} else
|
|
{
|
|
// load temp file
|
|
wxString str;
|
|
wxString filename;
|
|
tempDir = dataDir;
|
|
if (!wxDirExists(tempDir)) {
|
|
wxMkdir(tempDir);
|
|
}
|
|
tempDir=tempDir+wxFileName::GetPathSeparator()+"recovery"+wxFileName::GetPathSeparator();
|
|
if (!wxDirExists(tempDir)) {
|
|
wxMkdir(tempDir);
|
|
}
|
|
|
|
wxString pref=_conn->GetDbname();
|
|
|
|
bool modeUnicode = settings->GetUnicodeFile();
|
|
wxArrayString activePage;
|
|
wxString f = wxFindFirstFile(tempDir + wxT("*.a"));
|
|
while (!f.empty())
|
|
{
|
|
if (autoSave) {
|
|
filename = f.AfterLast(sepPath).BeforeLast('.');
|
|
if (filename.BeforeFirst('.') == "_active") {
|
|
activePage.Add(filename.AfterFirst('.'));
|
|
wxLogInfo(wxT("frmQuery::_active file marker: name=[%s] pref=[%s]"), filename.AfterFirst('.'), pref);
|
|
}
|
|
}
|
|
else {
|
|
wxRemoveFile(f);
|
|
}
|
|
f = wxFindNextFile();
|
|
}
|
|
f = wxFindFirstFile(tempDir+wxT("*.a"));
|
|
while ( !f.empty() )
|
|
{
|
|
filename=f.AfterLast(sepPath).BeforeLast('.');
|
|
if ((f.AfterLast(sepPath).StartsWith(pref+wxT("."))||(filename.BeforeLast('.').IsEmpty()))) {
|
|
wxUtfFile file(f, wxFile::read, modeUnicode ? wxFONTENCODING_UTF8 : wxFONTENCODING_DEFAULT);
|
|
if (file.IsOpened()) {
|
|
file.Read(str);
|
|
file.Close();
|
|
}
|
|
if (!str.IsEmpty())
|
|
{
|
|
wxString fline=str.BeforeFirst('@');
|
|
int l=fline.Length();
|
|
if (fline.Find('\n')>=0) l=0;
|
|
long nl=0;
|
|
if (l>0) fline.ToLong(&nl);
|
|
if (l>0) {
|
|
fline=str.Mid(l+1);
|
|
str=fline;
|
|
}
|
|
SqlBookAddPage(filename);
|
|
//SqlBookAddPage(true);
|
|
sqlQuery->SetText(str);
|
|
sqlQuery->Colourise(0, sqlQuery->GetLength());
|
|
sqlQuery->EmptyUndoBuffer();
|
|
|
|
sqlQuery->GotoPos(nl);
|
|
//wxSafeYield(); // needed to process sqlQuery modify event
|
|
sqlQuery->SetOrigin(ORIGIN_INITIAL);
|
|
sqlQuery->SetChanged(false);
|
|
|
|
setExtendedTitle();
|
|
SqlBookUpdatePageTitle();
|
|
SaveTempFile();
|
|
wxLogInfo(wxT("frmQuery::Create tab name=[%s]"), filename);
|
|
}
|
|
|
|
}
|
|
f = wxFindNextFile();
|
|
}
|
|
wxString t = wxEmptyString;
|
|
if (sqlQueryCounter==0) SqlBookAddPage(t);
|
|
if (!activePage.IsEmpty()) {
|
|
//activePage
|
|
//outputPane->GetPageText(curpage) == _("History");
|
|
|
|
int ii = -1;
|
|
for (int i = 0; i < sqlQueryBook->GetPageCount(); i++) {
|
|
wxString textpage = sqlQueryBook->GetPageText(i);
|
|
if (wxNOT_FOUND !=activePage.Index(textpage)) {
|
|
if (textpage.BeforeFirst('.') == pref) {
|
|
ii = i;
|
|
break;
|
|
}
|
|
else
|
|
ii = i;
|
|
//sqlQueryBook->ChangeSelection(i);
|
|
//if (sqlQueryBook->GetSelection()!=i) sqlQueryBook->SetSelection(i);
|
|
}
|
|
}
|
|
if (ii!=-1) sqlQueryBook->SetSelection(ii);
|
|
//wxLogInfo(wxT("frmQuery::select tab: name=[%s] index=[%d]"), sqlQueryBook->GetPageText(ii), ii);
|
|
}
|
|
//for (int i=1;i<15;i++)
|
|
//{
|
|
//filename=wxString::Format(_("Query %i"), i);
|
|
|
|
//if (!wxFileName::FileExists(tempDir+filename)) continue;
|
|
//wxUtfFile file(tempDir+filename, wxFile::read, modeUnicode ? wxFONTENCODING_UTF8 : wxFONTENCODING_DEFAULT);
|
|
|
|
//if (file.IsOpened())
|
|
//{ file.Read(str); file.Close(); }
|
|
////QFile::remove(tempDir+wxT("\\")+filename);
|
|
//wxRemoveFile(tempDir+filename);
|
|
//if (!str.IsEmpty())
|
|
//{
|
|
// sqlQuery->SetText(str);
|
|
// sqlQuery->Colourise(0, str.Length());
|
|
// sqlQuery->EmptyUndoBuffer();
|
|
// wxSafeYield(); // needed to process sqlQuery modify event
|
|
// //sqlQuery->SetFilename(lastPath);
|
|
// sqlQuery->SetChanged(true);
|
|
// //sqlQuery->SetOrigin(ORIGIN_INITIAL);
|
|
// setExtendedTitle();
|
|
// SqlBookUpdatePageTitle();
|
|
// //SetLineEndingStyle();
|
|
// SaveTempFile();
|
|
// SqlBookAddPage();
|
|
|
|
//}
|
|
//// for end
|
|
//}
|
|
|
|
}
|
|
//sqlQuery->SetAutoReplaceList(autoreplace);
|
|
updateMenu();
|
|
queryMenu->Enable(MNU_SAVEHISTORY, false);
|
|
queryMenu->Enable(MNU_CLEARHISTORY, false);
|
|
setTools(false);
|
|
lastFileFormat = settings->GetUnicodeFile();
|
|
// Load function name
|
|
pgSet *functions;
|
|
wxString def_f;
|
|
wxString def_name;
|
|
functions = conn->ExecuteSet(wxT("select pg_get_function_arguments(oid) def,proname,pronargs nargs from pg_proc where pronargs>=0 order by proname,pronargs"));
|
|
if (functions)
|
|
{
|
|
//name_func.Init(true);
|
|
while (!functions->Eof())
|
|
{
|
|
def_f = functions->GetVal(wxT("def"));
|
|
def_name = functions->GetVal(wxT("proname"));
|
|
def_func.Add(def_f);
|
|
name_func.Add(def_name);
|
|
functions->MoveNext();
|
|
}
|
|
name_func.Sort();
|
|
delete functions;
|
|
}
|
|
// Note that under GTK+, SetMaxLength() function may only be used with single line text controls.
|
|
// (see http://docs.wxwidgets.org/2.8/wx_wxtextctrl.html#wxtextctrlsetmaxlength)
|
|
#ifndef __WXGTK__
|
|
msgResult->SetMaxLength(0L);
|
|
msgHistory->SetMaxLength(0L);
|
|
#endif
|
|
}
|
|
|
|
|
|
frmQuery::~frmQuery()
|
|
{
|
|
closing = true;
|
|
if (!name_func.IsEmpty()) name_func.Clear();
|
|
if (!def_func.IsEmpty()) def_func.Clear();
|
|
// Save frmQuery Perspective
|
|
settings->Write(wxT("frmQuery/Perspective-") + wxString(FRMQUERY_PERSPECTIVE_VER), manager.SavePerspective());
|
|
|
|
// Uninitialize wxAUIManager
|
|
manager.UnInit();
|
|
|
|
if(sqlNotebook)
|
|
{
|
|
delete sqlNotebook;
|
|
sqlNotebook = NULL;
|
|
}
|
|
if(controller)
|
|
{
|
|
delete controller;
|
|
controller = NULL;
|
|
}
|
|
if(model)
|
|
{
|
|
delete model;
|
|
model = NULL;
|
|
}
|
|
if(adjustSizesTimer)
|
|
{
|
|
delete adjustSizesTimer;
|
|
adjustSizesTimer = NULL;
|
|
}
|
|
|
|
while (cbConnection->GetCount() > 1)
|
|
{
|
|
delete (pgConn *)cbConnection->GetClientData(0);
|
|
cbConnection->Delete(0);
|
|
}
|
|
|
|
if (favourites)
|
|
{
|
|
delete favourites;
|
|
favourites = NULL;
|
|
}
|
|
|
|
if (pgsTimer)
|
|
{
|
|
delete pgsTimer;
|
|
pgsTimer = NULL;
|
|
}
|
|
|
|
if (pgScript)
|
|
{
|
|
delete pgScript;
|
|
pgScript = NULL;
|
|
}
|
|
|
|
if (mainForm)
|
|
mainForm->RemoveFrame(this);
|
|
|
|
if (macros)
|
|
delete macros;
|
|
if (autoreplace)
|
|
delete autoreplace;
|
|
}
|
|
|
|
|
|
void frmQuery::OnExit(wxCommandEvent &event)
|
|
{
|
|
closing = true;
|
|
Close();
|
|
}
|
|
|
|
|
|
void frmQuery::OnEraseBackground(wxEraseEvent &event)
|
|
{
|
|
event.Skip();
|
|
}
|
|
|
|
|
|
void frmQuery::OnSize(wxSizeEvent &event)
|
|
{
|
|
event.Skip();
|
|
}
|
|
|
|
|
|
void frmQuery::OnToggleScratchPad(wxCommandEvent &event)
|
|
{
|
|
if (viewMenu->IsChecked(MNU_SCRATCHPAD))
|
|
manager.GetPane(wxT("scratchPad")).Show(true);
|
|
else
|
|
manager.GetPane(wxT("scratchPad")).Show(false);
|
|
manager.Update();
|
|
}
|
|
|
|
|
|
void frmQuery::OnToggleDatabaseBar(wxCommandEvent &event)
|
|
{
|
|
if (viewMenu->IsChecked(MNU_DATABASEBAR))
|
|
manager.GetPane(wxT("databaseBar")).Show(true);
|
|
else
|
|
manager.GetPane(wxT("databaseBar")).Show(false);
|
|
manager.Update();
|
|
}
|
|
|
|
|
|
void frmQuery::OnToggleToolBar(wxCommandEvent &event)
|
|
{
|
|
if (viewMenu->IsChecked(MNU_TOOLBAR))
|
|
manager.GetPane(wxT("toolBar")).Show(true);
|
|
else
|
|
manager.GetPane(wxT("toolBar")).Show(false);
|
|
manager.Update();
|
|
}
|
|
|
|
|
|
void frmQuery::OnToggleOutputPane(wxCommandEvent &event)
|
|
{
|
|
if (viewMenu->IsChecked(MNU_OUTPUTPANE))
|
|
{
|
|
manager.GetPane(wxT("outputPane")).Show(true);
|
|
manager.LoadPerspective(outputPaneInfo);
|
|
}
|
|
else
|
|
{
|
|
outputPaneInfo = manager.SavePerspective();
|
|
manager.GetPane(wxT("outputPane")).Show(false);
|
|
}
|
|
manager.Update();
|
|
adjustGQBSizes();
|
|
}
|
|
|
|
|
|
void frmQuery::OnAuiUpdate(wxAuiManagerEvent &event)
|
|
{
|
|
if(event.pane->name == wxT("databaseBar"))
|
|
{
|
|
viewMenu->Check(MNU_DATABASEBAR, false);
|
|
}
|
|
else if(event.pane->name == wxT("toolBar"))
|
|
{
|
|
viewMenu->Check(MNU_TOOLBAR, false);
|
|
}
|
|
else if(event.pane->name == wxT("outputPane"))
|
|
{
|
|
viewMenu->Check(MNU_OUTPUTPANE, false);
|
|
if(!adjustSizesTimer)
|
|
adjustSizesTimer = new wxTimer(this, CTL_TIMERSIZES);
|
|
adjustSizesTimer->Start(500);
|
|
}
|
|
else if(event.pane->name == wxT("scratchPad"))
|
|
{
|
|
viewMenu->Check(MNU_SCRATCHPAD, false);
|
|
}
|
|
event.Skip();
|
|
}
|
|
|
|
|
|
void frmQuery::OnDefaultView(wxCommandEvent &event)
|
|
{
|
|
// Reset captions to whatever AuiManager expects in perspective
|
|
BeginPerspectiveChange();
|
|
|
|
manager.LoadPerspective(FRMQUERY_DEFAULT_PERSPECTIVE, true);
|
|
|
|
// Reset the captions for the current language
|
|
manager.GetPane(wxT("toolBar")).Caption(_("Tool bar"));
|
|
manager.GetPane(wxT("databaseBar")).Caption(_("Connection bar"));
|
|
manager.GetPane(wxT("sqlQuery")).Caption(_("SQL query"));
|
|
manager.GetPane(wxT("outputPane")).Caption(_("Output pane"));
|
|
manager.GetPane(wxT("scratchPad")).Caption(_("Scratch pad"));
|
|
|
|
EndPerspectiveChange(false);
|
|
|
|
manager.Update();
|
|
|
|
// Sync the View menu options
|
|
viewMenu->Check(MNU_DATABASEBAR, manager.GetPane(wxT("databaseBar")).IsShown());
|
|
viewMenu->Check(MNU_TOOLBAR, manager.GetPane(wxT("toolBar")).IsShown());
|
|
viewMenu->Check(MNU_OUTPUTPANE, manager.GetPane(wxT("outputPane")).IsShown());
|
|
viewMenu->Check(MNU_SCRATCHPAD, manager.GetPane(wxT("scratchPad")).IsShown());
|
|
}
|
|
|
|
void frmQuery::OnAutoSelectQuery(wxCommandEvent &event)
|
|
{
|
|
queryMenu->Check(MNU_AUTOSELECTQUERY, event.IsChecked());
|
|
|
|
settings->WriteBool(wxT("frmQuery/AutoSelectQuery"), queryMenu->IsChecked(MNU_AUTOSELECTQUERY));
|
|
}
|
|
|
|
void frmQuery::OnAutoRollback(wxCommandEvent &event)
|
|
{
|
|
queryMenu->Check(MNU_AUTOROLLBACK, event.IsChecked());
|
|
|
|
settings->WriteBool(wxT("frmQuery/AutoRollback"), queryMenu->IsChecked(MNU_AUTOROLLBACK));
|
|
}
|
|
|
|
void frmQuery::OnAutoCommit(wxCommandEvent &event)
|
|
{
|
|
bool chk=queryMenu->IsChecked(MNU_AUTOCOMMIT);
|
|
queryMenu->Check(MNU_AUTOCOMMIT, chk);
|
|
if (chk)
|
|
toolBar->SetToolNormalBitmap(MNU_MODE_TRANSACTION, mode_a.GetBitmap(wxDefaultSize));
|
|
else
|
|
toolBar->SetToolNormalBitmap(MNU_MODE_TRANSACTION, mode_t.GetBitmap(wxDefaultSize));
|
|
toolBar->Realize();
|
|
|
|
if(chk && conn->GetTxStatus() != PQTRANS_IDLE)
|
|
wxMessageBox(
|
|
_("The current transaction is still in progess.\n\nIn order to take the effect of AUTOCOMMIT mode, please complete the transaction by executing COMMIT, or ROLLBACK statement."),
|
|
_("Warning - Transaction in progress"), wxICON_INFORMATION | wxOK, this);
|
|
settings->WriteBool(wxT("frmQuery/AutoCommit"), queryMenu->IsChecked(MNU_AUTOCOMMIT));
|
|
}
|
|
|
|
void frmQuery::OnAutoIndent(wxCommandEvent &event)
|
|
{
|
|
editMenu->Check(MNU_AUTOINDENT, event.IsChecked());
|
|
|
|
settings->WriteBool(wxT("frmQuery/AutoIndent"), editMenu->IsChecked(MNU_AUTOINDENT));
|
|
|
|
SqlBookSetAutoIndent(event.IsChecked());
|
|
}
|
|
|
|
|
|
void frmQuery::OnWordWrap(wxCommandEvent &event)
|
|
{
|
|
viewMenu->Check(MNU_WORDWRAP, event.IsChecked());
|
|
|
|
settings->WriteBool(wxT("frmQuery/WordWrap"), viewMenu->IsChecked(MNU_WORDWRAP));
|
|
|
|
SqlBookSetWrapMode(event.IsChecked());
|
|
}
|
|
|
|
|
|
void frmQuery::OnShowIndentGuides(wxCommandEvent &event)
|
|
{
|
|
viewMenu->Check(MNU_SHOWINDENTGUIDES, event.IsChecked());
|
|
|
|
settings->WriteBool(wxT("frmQuery/ShowIndentGuides"), viewMenu->IsChecked(MNU_SHOWINDENTGUIDES));
|
|
|
|
SqlBookSetIndentGuides(event.IsChecked());
|
|
}
|
|
|
|
|
|
void frmQuery::OnShowWhitespace(wxCommandEvent &event)
|
|
{
|
|
viewMenu->Check(MNU_SHOWWHITESPACE, event.IsChecked());
|
|
|
|
settings->WriteBool(wxT("frmQuery/ShowWhitespace"), viewMenu->IsChecked(MNU_SHOWWHITESPACE));
|
|
|
|
SqlBookSetViewWhiteSpace(event.IsChecked());
|
|
}
|
|
|
|
|
|
void frmQuery::OnShowLineEnds(wxCommandEvent &event)
|
|
{
|
|
viewMenu->Check(MNU_SHOWLINEENDS, event.IsChecked());
|
|
|
|
settings->WriteBool(wxT("frmQuery/ShowLineEnds"), viewMenu->IsChecked(MNU_SHOWLINEENDS));
|
|
|
|
SqlBookSetViewEOL(event.IsChecked());
|
|
}
|
|
|
|
|
|
void frmQuery::OnShowLineNumber(wxCommandEvent &event)
|
|
{
|
|
viewMenu->Check(MNU_SHOWLINENUMBER, event.IsChecked());
|
|
|
|
settings->WriteBool(wxT("frmQuery/ShowLineNumber"), viewMenu->IsChecked(MNU_SHOWLINENUMBER));
|
|
|
|
SqlBookSetViewLineNumbers(event.IsChecked());
|
|
}
|
|
|
|
void frmQuery::OnActivate(wxActivateEvent &event)
|
|
{
|
|
if (event.GetActive())
|
|
updateMenu();
|
|
event.Skip();
|
|
}
|
|
|
|
|
|
void frmQuery::OnExport(wxCommandEvent &ev)
|
|
{
|
|
sqlResult->Export();
|
|
}
|
|
|
|
|
|
void frmQuery::Go()
|
|
{
|
|
cbConnection->SetSelection(0L);
|
|
wxCommandEvent ev;
|
|
OnChangeConnection(ev);
|
|
|
|
Show(true);
|
|
sqlQuery->SetFocus();
|
|
loading = false;
|
|
}
|
|
|
|
|
|
typedef struct __sqltokenhelp
|
|
{
|
|
const wxChar *token;
|
|
const wxChar *page;
|
|
int type;
|
|
} SqlTokenHelp;
|
|
|
|
SqlTokenHelp sqlTokenHelp[] =
|
|
{
|
|
{ wxT("ABORT"), 0, 0},
|
|
{ wxT("ALTER"), 0, 2},
|
|
{ wxT("ANALYZE"), 0, 0},
|
|
{ wxT("BEGIN"), 0, 0},
|
|
{ wxT("CHECKPOINT"), 0, 0},
|
|
{ wxT("CLOSE"), 0, 0},
|
|
{ wxT("CLUSTER"), 0, 0},
|
|
{ wxT("COMMENT"), 0, 0},
|
|
{ wxT("COMMIT"), 0, 0},
|
|
{ wxT("COPY"), 0, 0},
|
|
{ wxT("CREATE"), 0, 1},
|
|
{ wxT("DEALLOCATE"), 0, 0},
|
|
{ wxT("DECLARE"), 0, 0},
|
|
{ wxT("DELETE"), 0, 0},
|
|
{ wxT("DROP"), 0, 1},
|
|
{ wxT("END"), 0, 0},
|
|
{ wxT("EXECUTE"), 0, 0},
|
|
{ wxT("EXPLAIN"), 0, 0},
|
|
{ wxT("FETCH"), 0, 0},
|
|
{ wxT("GRANT"), 0, 0},
|
|
{ wxT("INSERT"), 0, 0},
|
|
{ wxT("LISTEN"), 0, 0},
|
|
{ wxT("LOAD"), 0, 0},
|
|
{ wxT("LOCK"), 0, 0},
|
|
{ wxT("MOVE"), 0, 0},
|
|
{ wxT("NOTIFY"), 0, 0},
|
|
{ wxT("END"), 0, 0},
|
|
// { wxT("PREPARE"), 0, 0}, handled individually
|
|
{ wxT("REINDEX"), 0, 0},
|
|
{ wxT("RELEASE"), wxT("pg/sql-release-savepoint"), 0},
|
|
{ wxT("RESET"), 0, 0},
|
|
{ wxT("REVOKE"), 0, 0},
|
|
// { wxT("ROLLBACK"), 0, 0}, handled individually
|
|
{ wxT("SAVEPOINT"), 0, 0},
|
|
{ wxT("SELECT"), 0, 0},
|
|
{ wxT("SET"), 0, 0},
|
|
{ wxT("SHOW"), 0, 0},
|
|
{ wxT("START"), wxT("pg/sql-start-transaction"), 0},
|
|
{ wxT("TRUNCATE"), 0, 0},
|
|
{ wxT("UNLISTEN"), 0, 0},
|
|
{ wxT("UPDATE"), 0, 0},
|
|
{ wxT("VACUUM"), 0, 0},
|
|
|
|
{ wxT("AGGREGATE"), 0, 11},
|
|
{ wxT("CAST"), 0, 11},
|
|
{ wxT("CONSTRAINT"), 0, 11},
|
|
{ wxT("CONVERSION"), 0, 11},
|
|
{ wxT("DATABASE"), 0, 12},
|
|
{ wxT("DOMAIN"), 0, 11},
|
|
{ wxT("FUNCTION"), 0, 11},
|
|
{ wxT("GROUP"), 0, 12},
|
|
{ wxT("INDEX"), 0, 11},
|
|
{ wxT("LANGUAGE"), 0, 11},
|
|
{ wxT("OPERATOR"), 0, 11},
|
|
{ wxT("ROLE"), 0, 11},
|
|
{ wxT("RULE"), 0, 11},
|
|
{ wxT("SCHEMA"), 0, 11},
|
|
{ wxT("SEQUENCE"), 0, 11},
|
|
{ wxT("TABLE"), 0, 12},
|
|
{ wxT("TABLESPACE"), 0, 12},
|
|
{ wxT("TRIGGER"), 0, 12},
|
|
{ wxT("TYPE"), 0, 11},
|
|
{ wxT("USER"), 0, 12},
|
|
{ wxT("VIEW"), 0, 11},
|
|
{ wxT("EXTTABLE"), 0, 12},
|
|
{ 0, 0 }
|
|
};
|
|
|
|
void frmQuery::OnContents(wxCommandEvent &event)
|
|
{
|
|
DisplayHelp(wxT("query"), HELP_PGADMIN);
|
|
}
|
|
|
|
|
|
void frmQuery::OnChangeConnection(wxCommandEvent &ev)
|
|
{
|
|
// 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(conn, cbConnection);
|
|
if (rc == wxID_OK)
|
|
{
|
|
bool createdNewConn;
|
|
wxString usr=wxEmptyString;
|
|
wxGetEnv(wxT("USERNAME"),&usr);
|
|
|
|
wxString applicationname = appearanceFactory->GetLongAppName() + wxT(" - query ")+usr;
|
|
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(ev);
|
|
}
|
|
else
|
|
rc = wxID_CANCEL;
|
|
}
|
|
if (rc != wxID_OK)
|
|
{
|
|
unsigned int i;
|
|
for (i = 0 ; i < sel ; i++)
|
|
{
|
|
if (cbConnection->GetClientData(i) == conn)
|
|
{
|
|
cbConnection->SetSelection(i);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
conn = (pgConn *)cbConnection->GetClientData(sel);
|
|
SqlBookSetDatabase(conn);
|
|
int len = sizeof(ctlSQL) / sizeof(ctlSQL[0]);
|
|
for (int i=0;i<len;i++) if (ctlSQL[i]!=NULL) ctlSQL[i]->SetConnection(conn);
|
|
//sqlResult->SetConnection(conn);
|
|
pgScript->SetConnection(conn);
|
|
title = wxT("") + cbConnection->GetValue();
|
|
setExtendedTitle();
|
|
seticon();
|
|
//Refresh GQB Tree if used
|
|
if(conn && !firstTime)
|
|
{
|
|
controller->getTablesBrowser()->refreshTables(conn);
|
|
controller->getView()->Refresh();
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
void frmQuery::OnHelp(wxCommandEvent &event)
|
|
{
|
|
wxString page;
|
|
wxString query = sqlQuery->GetSelectedText();
|
|
if (query.IsNull())
|
|
query = sqlQuery->GetText();
|
|
|
|
query.Trim(false);
|
|
|
|
if (!query.IsEmpty())
|
|
{
|
|
wxStringTokenizer tokens(query);
|
|
query = tokens.GetNextToken();
|
|
|
|
if (query.IsSameAs(wxT("PREPARE"), false))
|
|
{
|
|
if (tokens.GetNextToken().IsSameAs(wxT("TRANSACTION"), false))
|
|
page = wxT("sql-prepare-transaction");
|
|
else
|
|
page = wxT("sql-prepare");
|
|
}
|
|
else if (query.IsSameAs(wxT("ROLLBACK"), false))
|
|
{
|
|
if (tokens.GetNextToken().IsSameAs(wxT("PREPARED"), false))
|
|
page = wxT("sql-rollback-prepared");
|
|
else
|
|
page = wxT("sql-rollback");
|
|
}
|
|
else
|
|
{
|
|
SqlTokenHelp *sth = sqlTokenHelp;
|
|
while (sth->token)
|
|
{
|
|
if (sth->type < 10 && query.IsSameAs(sth->token, false))
|
|
{
|
|
if (sth->page)
|
|
page = sth->page;
|
|
else
|
|
page = wxT("sql-") + query.Lower();
|
|
|
|
if (sth->type)
|
|
{
|
|
int type = sth->type + 10;
|
|
|
|
query = tokens.GetNextToken();
|
|
sth = sqlTokenHelp;
|
|
while (sth->token)
|
|
{
|
|
if (sth->type >= type && query.IsSameAs(sth->token, false))
|
|
{
|
|
if (sth->page)
|
|
page += sth->page;
|
|
else
|
|
page += query.Lower();
|
|
break;
|
|
}
|
|
sth++;
|
|
}
|
|
if (!sth->token)
|
|
page = wxT("sql-commands");
|
|
}
|
|
break;
|
|
}
|
|
sth++;
|
|
}
|
|
}
|
|
}
|
|
if (page.IsEmpty())
|
|
page = wxT("sql-commands");
|
|
|
|
if (conn->GetIsEdb())
|
|
DisplayHelp(page, HELP_ENTERPRISEDB);
|
|
else if (conn->GetIsGreenplum())
|
|
DisplayHelp(page, HELP_GREENPLUM);
|
|
else
|
|
DisplayHelp(page, HELP_POSTGRESQL);
|
|
}
|
|
|
|
|
|
void frmQuery::OnSaveHistory(wxCommandEvent &event)
|
|
{
|
|
#ifdef __WXMSW__
|
|
wxFileDialog *dlg = new wxFileDialog(this, _("Save history"), lastDir, wxEmptyString,
|
|
_("Log files (*.log)|*.log|All files (*.*)|*.*"), wxFD_SAVE | wxFD_OVERWRITE_PROMPT);
|
|
#else
|
|
wxFileDialog *dlg = new wxFileDialog(this, _("Save history"), lastDir, wxEmptyString,
|
|
_("Log files (*.log)|*.log|All files (*)|*"), wxFD_SAVE | wxFD_OVERWRITE_PROMPT);
|
|
#endif
|
|
if (dlg->ShowModal() == wxID_OK)
|
|
{
|
|
if (!FileWrite(dlg->GetPath(), msgHistory->GetValue(), false))
|
|
{
|
|
wxLogError(__("Could not write the file %s: Errcode=%d."), dlg->GetPath().c_str(), wxSysErrorCode());
|
|
}
|
|
}
|
|
delete dlg;
|
|
|
|
}
|
|
void frmQuery::OnChangeNotebookOutpane(wxAuiNotebookEvent &event)
|
|
{
|
|
if (outputPane->GetPageCount() > 0)
|
|
{
|
|
size_t curpage = outputPane->GetSelection();
|
|
if (wxDynamicCast(outputPane->GetPage(curpage), wxTextCtrl))
|
|
{
|
|
|
|
wxTextCtrl *hist = wxDynamicCast(outputPane->GetPage(curpage), wxTextCtrl);
|
|
//hist->SetInsertionPointEnd();
|
|
//outputPane->Get
|
|
if (outputPane->GetPageText(curpage)==_("History")) {
|
|
///showMessage(hist->GetName());
|
|
hist->ShowPosition(99999999);
|
|
}
|
|
//showMessage();
|
|
}
|
|
if (wxDynamicCast(outputPane->GetPage(curpage), ctlSQLResult))
|
|
{
|
|
ctlSQLResult *c=wxDynamicCast(outputPane->GetPage(curpage), ctlSQLResult);
|
|
int len = sizeof(ctlSQL) / sizeof(ctlSQL[0]);
|
|
for (int i=0;i<len;i++)
|
|
if (ctlSQL[i]!=NULL && c==ctlSQL[i])
|
|
{
|
|
sqlResult=ctlSQL[i];
|
|
indexResult=i;
|
|
break;
|
|
}
|
|
}
|
|
//hist->CmdKeyExecute(wxSTC_CMD_TAB);
|
|
}
|
|
|
|
}
|
|
void frmQuery::OnChangeNotebook(wxAuiNotebookEvent &event)
|
|
{
|
|
// A bug in wxGTK prevents us to show a modal dialog within a
|
|
// EVT_AUINOTEBOOK_PAGE_CHANGED event
|
|
// So, we need these three lines of code to work-around it
|
|
wxWindow *win = wxWindow::GetCapture();
|
|
if (win)
|
|
win->ReleaseMouse();
|
|
|
|
if(sqlNotebook && sqlNotebook->GetPageCount() >= 2)
|
|
{
|
|
|
|
if (event.GetSelection() == 0)
|
|
{
|
|
queryMenu->SetHelpString(MNU_EXECUTE, _("Execute query"));
|
|
queryMenu->SetHelpString(MNU_EXECFILE, _("Execute query, write result to file"));
|
|
toolBar->SetToolShortHelp(MNU_EXECUTE, _("Execute query"));
|
|
toolBar->SetToolShortHelp(MNU_EXECFILE, _("Execute query, write result to file"));
|
|
viewMenu->Enable(MNU_OUTPUTPANE, true);
|
|
viewMenu->Enable(MNU_SCRATCHPAD, true);
|
|
|
|
// Reset the panes
|
|
if (viewMenu->IsChecked(MNU_OUTPUTPANE))
|
|
manager.GetPane(wxT("outputPane")).Show(true);
|
|
if (viewMenu->IsChecked(MNU_SCRATCHPAD))
|
|
manager.GetPane(wxT("scratchPad")).Show(true);
|
|
manager.Update();
|
|
|
|
updateFromGqb(false);
|
|
}
|
|
else
|
|
{
|
|
manager.GetPane(wxT("outputPane")).Show(false);
|
|
manager.GetPane(wxT("scratchPad")).Show(false);
|
|
manager.Update();
|
|
viewMenu->Enable(MNU_OUTPUTPANE, false);
|
|
viewMenu->Enable(MNU_SCRATCHPAD, false);
|
|
|
|
if(firstTime) //Things that should be done on first click on GQB
|
|
{
|
|
// Menu
|
|
queryMenu->Append(MNU_EXECUTE, _("Generate SQL from Graphical Query Builder Model"));
|
|
queryMenu->SetHelpString(MNU_EXECFILE, _("Generate SQL from Graphical Query Builder Model"));
|
|
toolBar->SetToolShortHelp(MNU_EXECUTE, _("Generate SQL from Graphical Query Builder Model"));
|
|
toolBar->SetToolShortHelp(MNU_EXECFILE, _("Generate SQL from Graphical Query Builder Model"));
|
|
|
|
// Size, and pause to allow the window to draw
|
|
adjustGQBSizes();
|
|
wxTheApp->Yield(true);
|
|
|
|
// Database related Stuffs.
|
|
// Create a server object and connect it.
|
|
controller->getTablesBrowser()->refreshTables(conn);
|
|
firstTime = false;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
void frmQuery::OnSetFocus(wxFocusEvent &event)
|
|
{
|
|
sqlQuery->SetFocus();
|
|
event.Skip();
|
|
}
|
|
|
|
|
|
void frmQuery::OnClearHistory(wxCommandEvent &event)
|
|
{
|
|
queryMenu->Enable(MNU_SAVEHISTORY, false);
|
|
queryMenu->Enable(MNU_CLEARHISTORY, false);
|
|
msgHistory->Clear();
|
|
msgHistory->SetFont(settings->GetSQLFont());
|
|
}
|
|
|
|
|
|
void frmQuery::OnFocus(wxFocusEvent &ev)
|
|
{
|
|
if (wxDynamicCast(this, wxFrame))
|
|
updateMenu();
|
|
else
|
|
{
|
|
frmQuery *wnd = (frmQuery *)GetParent();
|
|
|
|
if (wnd)
|
|
wnd->OnFocus(ev);
|
|
}
|
|
ev.Skip();
|
|
}
|
|
|
|
|
|
void frmQuery::OnCut(wxCommandEvent &ev)
|
|
{
|
|
if (currentControl() == sqlQuery)
|
|
{
|
|
sqlQuery->Cut();
|
|
updateMenu();
|
|
}
|
|
}
|
|
|
|
|
|
wxWindow *frmQuery::currentControl()
|
|
{
|
|
wxWindow *wnd = FindFocus();
|
|
if (wnd == outputPane)
|
|
{
|
|
wnd = sqlResult;
|
|
switch (outputPane->GetSelection())
|
|
{
|
|
case 0:
|
|
wnd = sqlResult;
|
|
break;
|
|
case 1:
|
|
wnd = explainCanvas;
|
|
break;
|
|
case 2:
|
|
wnd = msgResult;
|
|
break;
|
|
case 3:
|
|
wnd = msgHistory;
|
|
break;
|
|
}
|
|
}
|
|
return wnd;
|
|
|
|
}
|
|
|
|
|
|
void frmQuery::OnCopy(wxCommandEvent &ev)
|
|
{
|
|
wxWindow *wnd = currentControl();
|
|
|
|
if (wnd == sqlQuery) {
|
|
sqlQuery->Copy();
|
|
SetStatusText("Select query copy.", STATUSPOS_MSGS);
|
|
}
|
|
else if (wnd == msgResult) {
|
|
msgResult->Copy();
|
|
SetStatusText("select msgResult copy.", STATUSPOS_MSGS);
|
|
}
|
|
else if (wnd == msgHistory)
|
|
msgHistory->Copy();
|
|
else if (wnd == scratchPad)
|
|
scratchPad->Copy();
|
|
else
|
|
{
|
|
wxWindow *obj = wnd;
|
|
|
|
while (obj != NULL)
|
|
{
|
|
if (obj == sqlResult)
|
|
{
|
|
sqlResult->Copy(0);
|
|
SetStatusText("Result query copy.", STATUSPOS_MSGS);
|
|
break;
|
|
}
|
|
obj = obj->GetParent();
|
|
}
|
|
}
|
|
updateMenu();
|
|
}
|
|
|
|
|
|
void frmQuery::OnPaste(wxCommandEvent &ev)
|
|
{
|
|
if (currentControl() == sqlQuery)
|
|
sqlQuery->Paste();
|
|
else if (currentControl() == scratchPad)
|
|
scratchPad->Paste();
|
|
}
|
|
|
|
|
|
void frmQuery::OnClear(wxCommandEvent &ev)
|
|
{
|
|
wxWindow *wnd = currentControl();
|
|
|
|
if (wnd == sqlQuery)
|
|
sqlQuery->ClearAll();
|
|
else if (wnd == msgResult)
|
|
{
|
|
msgResult->Clear();
|
|
msgResult->SetFont(settings->GetSQLFont());
|
|
}
|
|
else if (wnd == msgHistory)
|
|
{
|
|
msgHistory->Clear();
|
|
msgHistory->SetFont(settings->GetSQLFont());
|
|
}
|
|
else if (wnd == scratchPad)
|
|
scratchPad->Clear();
|
|
}
|
|
|
|
|
|
void frmQuery::OnSelectAll(wxCommandEvent &ev)
|
|
{
|
|
wxWindow *wnd = currentControl();
|
|
|
|
if (wnd == sqlQuery)
|
|
sqlQuery->SelectAll();
|
|
else if (wnd == msgResult)
|
|
msgResult->SelectAll();
|
|
else if (wnd == msgHistory)
|
|
msgHistory->SelectAll();
|
|
else if (wnd == sqlResult)
|
|
sqlResult->SelectAll();
|
|
else if (wnd == scratchPad)
|
|
scratchPad->SelectAll();
|
|
else if (wnd->GetParent() == sqlResult)
|
|
sqlResult->SelectAll();
|
|
}
|
|
|
|
|
|
void frmQuery::OnSearchReplace(wxCommandEvent &ev)
|
|
{
|
|
sqlQuery->OnSearchReplace(ev);
|
|
}
|
|
void frmQuery::OnTransformText(wxCommandEvent& ev)
|
|
{
|
|
sqlQuery->OnTransformText(ev);
|
|
}
|
|
|
|
|
|
void frmQuery::OnUndo(wxCommandEvent &ev)
|
|
{
|
|
sqlQuery->Undo();
|
|
}
|
|
|
|
|
|
void frmQuery::OnRedo(wxCommandEvent &ev)
|
|
{
|
|
sqlQuery->Redo();
|
|
}
|
|
|
|
|
|
void frmQuery::setExtendedTitle()
|
|
{
|
|
wxString chgStr;
|
|
if (sqlQuery->IsChanged())
|
|
chgStr = wxT(" *");
|
|
|
|
wxString filename = sqlQuery->GetFilename();
|
|
if (filename.IsNull())
|
|
SetTitle(title + chgStr);
|
|
else
|
|
{
|
|
SetTitle(title + wxT(" - [") + filename + wxT("]") + chgStr);
|
|
}
|
|
// Allow to save initial queries though they are not changed
|
|
bool enableSave = sqlQuery->IsChanged() || (sqlQuery->GetOrigin() == ORIGIN_INITIAL);
|
|
toolBar->EnableTool(MNU_SAVE, enableSave);
|
|
fileMenu->Enable(MNU_SAVE, enableSave);
|
|
}
|
|
|
|
bool frmQuery::relatesToWindow(wxWindow *which, wxWindow *related)
|
|
{
|
|
while (which != NULL)
|
|
{
|
|
if (which == related)
|
|
return true;
|
|
else
|
|
which = which->GetParent();
|
|
}
|
|
return false;
|
|
}
|
|
|
|
void frmQuery::updateMenu(bool allowUpdateModelSize)
|
|
{
|
|
bool canCut = false;
|
|
bool canCopy = false;
|
|
bool canPaste = false;
|
|
bool canUndo = false;
|
|
bool canRedo = false;
|
|
bool canClear = false;
|
|
bool canFind = false;
|
|
bool canAddFavourite = false;
|
|
bool canManageFavourite = false;
|
|
bool canSaveExplain = false;
|
|
bool canSaveGQB = false;
|
|
|
|
wxAuiFloatingFrame *fp = wxDynamicCastThis(wxAuiFloatingFrame);
|
|
if (fp)
|
|
return;
|
|
|
|
if (closing)
|
|
return;
|
|
|
|
canSaveExplain = explainCanvas->GetDiagram()->GetCount() > 0;
|
|
|
|
if (allowUpdateModelSize)
|
|
{
|
|
canSaveGQB = controller->getView() != NULL && controller->getView()->canSaveAsImage();
|
|
}
|
|
|
|
saveasImageMenu->Enable(MNU_SAVEAS_IMAGE_GQB, canSaveGQB);
|
|
saveasImageMenu->Enable(MNU_SAVEAS_IMAGE_EXPLAIN, canSaveExplain);
|
|
|
|
wxWindow *wnd = currentControl();
|
|
if (wnd == NULL)
|
|
return;
|
|
|
|
if (relatesToWindow(wnd, sqlQuery)
|
|
|| relatesToWindow(wnd, sqlResult)
|
|
|| relatesToWindow(wnd, msgResult)
|
|
|| relatesToWindow(wnd, msgHistory)
|
|
|| relatesToWindow(wnd, scratchPad))
|
|
{
|
|
if (relatesToWindow(wnd, sqlQuery))
|
|
{
|
|
canUndo = sqlQuery->CanUndo();
|
|
canRedo = sqlQuery->CanRedo();
|
|
canPaste = sqlQuery->CanPaste();
|
|
canFind = true;
|
|
canAddFavourite = (sqlQuery->GetLength() > 0) && (settings->GetFavouritesFile().Length() > 0);
|
|
canManageFavourite = (settings->GetFavouritesFile().Length() > 0);
|
|
}
|
|
else if (relatesToWindow(wnd, scratchPad))
|
|
{
|
|
canPaste = true;
|
|
}
|
|
canCopy = true;
|
|
canCut = true;
|
|
canClear = true;
|
|
}
|
|
|
|
toolBar->EnableTool(MNU_UNDO, canUndo);
|
|
editMenu->Enable(MNU_UNDO, canUndo);
|
|
|
|
toolBar->EnableTool(MNU_REDO, canRedo);
|
|
editMenu->Enable(MNU_REDO, canRedo);
|
|
|
|
toolBar->EnableTool(MNU_COPY, canCopy);
|
|
editMenu->Enable(MNU_COPY, canCopy);
|
|
|
|
toolBar->EnableTool(MNU_PASTE, canPaste);
|
|
editMenu->Enable(MNU_PASTE, canPaste);
|
|
|
|
toolBar->EnableTool(MNU_CUT, canCut);
|
|
editMenu->Enable(MNU_CUT, canCut);
|
|
|
|
toolBar->EnableTool(MNU_CLEAR, canClear);
|
|
editMenu->Enable(MNU_CLEAR, canClear);
|
|
|
|
toolBar->EnableTool(MNU_FIND, canFind);
|
|
editMenu->Enable(MNU_FIND, canFind);
|
|
|
|
favouritesMenu->Enable(MNU_FAVOURITES_ADD, canAddFavourite);
|
|
favouritesMenu->Enable(MNU_FAVOURITES_INJECT, canAddFavourite); // these two use the same criteria
|
|
favouritesMenu->Enable(MNU_FAVOURITES_MANAGE, canManageFavourite);
|
|
}
|
|
|
|
|
|
void frmQuery::UpdateFavouritesList()
|
|
{
|
|
if (IsVisible() && menuBar->FindMenu(_("Fav&ourites")) == wxNOT_FOUND)
|
|
return;
|
|
|
|
if (favourites)
|
|
delete favourites;
|
|
|
|
favourites = queryFavouriteFileProvider::LoadFavourites(true);
|
|
|
|
while (favouritesMenu->GetMenuItemCount() > 4) // there are 3 static items + separator above
|
|
{
|
|
favouritesMenu->Destroy(favouritesMenu->GetMenuItems()[4]);
|
|
}
|
|
|
|
favourites->AppendAllToMenu(favouritesMenu, MNU_FAVOURITES_MANAGE + 1);
|
|
}
|
|
|
|
|
|
void frmQuery::UpdateMacrosList()
|
|
{
|
|
if (IsVisible() && menuBar->FindMenu(_("&Macros")) == wxNOT_FOUND)
|
|
return;
|
|
|
|
if (macros)
|
|
delete macros;
|
|
|
|
macros = queryMacroFileProvider::LoadMacros(true);
|
|
|
|
while (macrosMenu->GetMenuItemCount() > 2)
|
|
{
|
|
macrosMenu->Destroy(macrosMenu->GetMenuItems()[2]);
|
|
}
|
|
|
|
macros->AppendAllToMenu(macrosMenu, MNU_MACROS_MANAGE + 1);
|
|
}
|
|
|
|
|
|
void frmQuery::OnAddFavourite(wxCommandEvent &event)
|
|
{
|
|
if (sqlQuery->GetText().Trim().IsEmpty())
|
|
return;
|
|
int r = dlgAddFavourite(this, favourites).AddFavourite(sqlQuery->GetText());
|
|
if (r == 1)
|
|
{
|
|
// Added a favourite, so save
|
|
queryFavouriteFileProvider::SaveFavourites(favourites);
|
|
}
|
|
if (r == 1 || r == -1)
|
|
{
|
|
// Changed something requiring rollback
|
|
mainForm->UpdateAllFavouritesList();
|
|
}
|
|
}
|
|
|
|
|
|
void frmQuery::OnInjectFavourite(wxCommandEvent &event)
|
|
{
|
|
queryFavouriteItem *fav;
|
|
bool selected = true;
|
|
int startPos, endPos;
|
|
wxString name = sqlQuery->GetSelectedText();
|
|
|
|
if (name.IsEmpty())
|
|
{
|
|
// get the word under cursor:
|
|
int curPos = sqlQuery->GetCurrentPos();
|
|
startPos = sqlQuery->WordStartPosition(curPos, true);
|
|
endPos = sqlQuery->WordEndPosition(curPos, true);
|
|
name = sqlQuery->GetTextRange(startPos, endPos);
|
|
selected = false;
|
|
}
|
|
name.Trim(false).Trim(true);
|
|
if (name.IsEmpty())
|
|
return;
|
|
|
|
// search for favourite with this name
|
|
fav = favourites->FindFavourite(name);
|
|
if (!fav)
|
|
return;
|
|
|
|
// replace selection (or current word) with it's contents
|
|
//wxLogInfo(wxT("frmQuery::OnReplaceFavourite(): name=[%s] contents=[%s]"), name, fav->GetContents());
|
|
sqlQuery->BeginUndoAction();
|
|
if (!selected)
|
|
sqlQuery->SetSelection(startPos, endPos);
|
|
sqlQuery->ReplaceSelection(fav->GetContents());
|
|
sqlQuery->EndUndoAction();
|
|
}
|
|
|
|
|
|
void frmQuery::OnManageFavourites(wxCommandEvent &event)
|
|
{
|
|
int r = dlgManageFavourites(this, favourites).ManageFavourites();
|
|
if (r == 1)
|
|
{
|
|
// Changed something, so save
|
|
queryFavouriteFileProvider::SaveFavourites(favourites);
|
|
}
|
|
if (r == 1 || r == -1)
|
|
{
|
|
// Changed something requiring rollback
|
|
mainForm->UpdateAllFavouritesList();
|
|
}
|
|
}
|
|
|
|
|
|
void frmQuery::OnSelectFavourite(wxCommandEvent &event)
|
|
{
|
|
queryFavouriteItem *fav;
|
|
|
|
fav = favourites->FindFavourite(event.GetId());
|
|
if (!fav)
|
|
return;
|
|
|
|
if (!sqlQuery->GetText().Trim().IsEmpty())
|
|
{
|
|
int r = wxMessageDialog(this, _("Replace current query?"), _("Confirm replace"), wxYES_NO | wxCANCEL | wxICON_QUESTION).ShowModal();
|
|
if (r == wxID_CANCEL)
|
|
return;
|
|
else if (r == wxID_YES)
|
|
sqlQuery->ClearAll();
|
|
else
|
|
{
|
|
if (sqlQuery->GetText().Last() != '\n')
|
|
sqlQuery->AddText(wxT("\n")); // Add a newline after the last query
|
|
}
|
|
}
|
|
sqlQuery->AddText(fav->GetContents());
|
|
}
|
|
|
|
|
|
bool frmQuery::CheckChanged(bool canVeto)
|
|
{
|
|
if (sqlQuery->IsChanged() && settings->GetAskSaveConfirmation())
|
|
{
|
|
wxString fn, filename;
|
|
filename = sqlQuery->GetFilename();
|
|
if (!filename.IsNull())
|
|
fn = wxString::Format(_("The text in file %s has changed.\nDo you want to save changes?"), filename.c_str());
|
|
else
|
|
fn = _("The text has changed.\nDo you want to save changes?");
|
|
wxMessageDialog msg(this, fn, _("Query"),
|
|
wxYES_NO | wxICON_EXCLAMATION |
|
|
(canVeto ? wxCANCEL : 0));
|
|
|
|
wxCommandEvent noEvent;
|
|
switch (msg.ShowModal())
|
|
{
|
|
case wxID_YES:
|
|
if (filename.IsNull())
|
|
OnSaveAs(noEvent);
|
|
else
|
|
OnSave(noEvent);
|
|
|
|
return sqlQuery->IsChanged();
|
|
|
|
case wxID_CANCEL:
|
|
return true;
|
|
}
|
|
|
|
}
|
|
return false;
|
|
}
|
|
|
|
|
|
void frmQuery::OnClose(wxCloseEvent &event)
|
|
{
|
|
if (queryMenu->IsEnabled(MNU_CANCEL))
|
|
{
|
|
if (event.CanVeto())
|
|
{
|
|
wxMessageDialog msg(this, _("A query is running. Do you wish to cancel it?"), _("Query"),
|
|
wxYES_NO | wxNO_DEFAULT | wxICON_EXCLAMATION);
|
|
|
|
if (msg.ShowModal() != wxID_YES)
|
|
{
|
|
event.Veto();
|
|
return;
|
|
}
|
|
}
|
|
|
|
wxCommandEvent ev;
|
|
OnCancel(ev);
|
|
}
|
|
|
|
while (sqlResult->RunStatus() == CTLSQL_RUNNING)
|
|
{
|
|
wxLogInfo(wxT("SQL Query box: Waiting for query to abort"));
|
|
wxSleep(1);
|
|
}
|
|
|
|
if (m_loadingfile && event.CanVeto())
|
|
{
|
|
wxMessageBox(_("The query tool cannot be closed whilst a file is loading."), _("Warning"), wxICON_INFORMATION | wxOK);
|
|
event.Veto();
|
|
|
|
return;
|
|
}
|
|
|
|
if (SqlBookClose(event.CanVeto()) && event.CanVeto())
|
|
{
|
|
event.Veto();
|
|
return;
|
|
}
|
|
|
|
closing = true;
|
|
|
|
// Reset the panes
|
|
if (viewMenu->IsChecked(MNU_OUTPUTPANE))
|
|
manager.GetPane(wxT("outputPane")).Show(true);
|
|
if (viewMenu->IsChecked(MNU_SCRATCHPAD))
|
|
manager.GetPane(wxT("scratchPad")).Show(true);
|
|
manager.Update();
|
|
|
|
Hide();
|
|
int len = sizeof(ctlSQL) / sizeof(ctlSQL[0]);
|
|
for (int i=0;i<len;i++) if (ctlSQL[i]!=NULL) ctlSQL[i]->Disconnect(wxID_ANY, wxEVT_SET_FOCUS, wxFocusEventHandler(frmQuery::OnFocus));
|
|
|
|
// sqlResult->Disconnect(wxID_ANY, wxEVT_SET_FOCUS, wxFocusEventHandler(frmQuery::OnFocus));
|
|
msgResult->Disconnect(wxID_ANY, wxEVT_SET_FOCUS, wxFocusEventHandler(frmQuery::OnFocus));
|
|
msgHistory->Disconnect(wxID_ANY, wxEVT_SET_FOCUS, wxFocusEventHandler(frmQuery::OnFocus));
|
|
|
|
controller->nullView(); //to avoid bug on *nix when deleting controller
|
|
|
|
settings->SetExplainVerbose(queryMenu->IsChecked(MNU_VERBOSE));
|
|
settings->SetExplainCosts(queryMenu->IsChecked(MNU_COSTS));
|
|
settings->SetExplainBuffers(queryMenu->IsChecked(MNU_BUFFERS));
|
|
settings->SetExplainTiming(queryMenu->IsChecked(MNU_TIMING));
|
|
|
|
for (int i=0;i<len;i++) if (ctlSQL[i]!=NULL) ctlSQL[i]->Abort();
|
|
|
|
// sqlResult->Abort(); // to make sure conn is unused
|
|
|
|
Destroy();
|
|
|
|
}
|
|
|
|
|
|
void frmQuery::OnChangeStc(wxStyledTextEvent &event)
|
|
{
|
|
// The STC seems to fire this event even if it loses focus. Fortunately,
|
|
// that seems to be m_modificationType == 512.
|
|
// 0x4010 - SC_MOD_CHANGEINDICATOR | SC_PERFORMED_USER
|
|
if ((event.m_modificationType != 512 && event.m_modificationType != 0x4010)&&
|
|
// Sometimes there come events 20 and 520 AFTER the initial query was set by constructor.
|
|
// Their occurrence is related to query's size and possibly international characters in it (??)
|
|
// Filter them out to keep "initial" origin of query text.
|
|
(sqlQuery->GetOrigin() != ORIGIN_INITIAL || (event.m_modificationType != 20 && event.m_modificationType != 520)))
|
|
{
|
|
// This is the default change origin.
|
|
// In other cases the changer function will reset it after this event.
|
|
sqlQuery->SetOrigin(ORIGIN_MANUAL);
|
|
if (!sqlQuery->IsChanged())
|
|
{
|
|
sqlQuery->SetChanged(true);
|
|
setExtendedTitle();
|
|
//SqlBookUpdatePageTitle();
|
|
CallAfter(&frmQuery::SqlBookUpdatePageTitle);
|
|
}
|
|
}
|
|
// do not allow update of model size of GQB on input (key press) of each
|
|
// character of the query in Query Tool
|
|
updateMenu(false);
|
|
}
|
|
void frmQuery::OnLabelRightClick(wxGridEvent &event)
|
|
{
|
|
wxMenu *xmenu = new wxMenu();
|
|
wxArrayInt rows = sqlResult->GetSelectedRows();
|
|
xmenu->Append(MNU_COPY, _("&Copy"), _("Copy selected cells to clipboard."));
|
|
xmenu->Append(MNU_PASTE, _("&Paste"), _("Paste data from the clipboard."));
|
|
xmenu->Append(MNU_DELETE, _("&Delete"), _("Delete selected rows."));
|
|
xmenu->AppendSeparator();
|
|
xmenu->Append(MNU_COPY_INSERT, _("Copy Insert format"), _("Copy Insert format."));
|
|
xmenu->Append(MNU_COPY_LISTCOLTYPE, _("List columns header"), _("Copy list columns header"));
|
|
xmenu->Append(MNU_COPY_INLIST, _("IN list format copy"), _("Copy In list format."));
|
|
xmenu->Append(MNU_COPY_WHERELIST, _("WHERE list format copy"), _("Copy where list format."));
|
|
xmenu->Append(MNU_COPY_TABLEHTML, _("Copy table html format"), _("Copy table html format."));
|
|
if (body_template.Count()>0) {
|
|
//MNU_GENERATE_TEMPLATE
|
|
wxMenu *submenu = NULL;
|
|
//wxString t="begin @obj_id@ end";
|
|
int cnt=0;
|
|
for(int i=0;i<body_template.Count();i++) {
|
|
wxString s=sqlResult->GenerateTemplate(body_template[i],1);
|
|
if (s=="OK")
|
|
{
|
|
if (submenu==NULL) submenu = new wxMenu();
|
|
cnt++;
|
|
submenu->Append(MNU_GENERATESQL+cnt,title_template[i],body_template[i]);
|
|
} else
|
|
SetStatusText(s, STATUSPOS_MSGS);
|
|
}
|
|
|
|
if (cnt>0) xmenu->Append(MNU_GENERATESQL,"Generate",submenu);
|
|
}
|
|
xmenu->AppendSeparator();
|
|
xmenu->Append(MNU_AUTOCOLSPLOT, _("Draw plot LY(bar) or LXY or XYYY..."), _("Draw plot LY(bar) LXY or XYYY..."));
|
|
xmenu->Append(MNU_SUMMARY_COL, _("Summary"), _("Summary selected cells."));
|
|
xmenu->Append(MNU_COMPARE_2CELL, _("Compare 2 Cells"), _("Compare 2 selected cells."));
|
|
xmenu->Append(MNU_CHECK_COLUMN_DATE, _("Check the sequence of dates"), _("Check the sequence of dates"));
|
|
xmenu->Append(MNU_CLEAR_FILTER, _("Clear filter"), _("Clear filter"));
|
|
bool selcol = sqlResult->GetSelectedCols().GetCount() > 0;
|
|
xmenu->Enable(MNU_CHECK_COLUMN_DATE, selcol);
|
|
xmenu->Enable(MNU_COPY_LISTCOLTYPE, selcol);
|
|
xmenu->Enable(MNU_COPY_TABLEHTML, selcol|| rows.GetCount()>0);
|
|
xmenu->Enable(MNU_AUTOCOLSPLOT, sqlResult->IsSelection());
|
|
xmenu->Enable(MNU_SUMMARY_COL, sqlResult->IsSelection());
|
|
xmenu->Enable(MNU_COMPARE_2CELL, sqlResult->IsSelection());
|
|
xmenu->Enable(MNU_COPY_INLIST, sqlResult->IsSelection());
|
|
|
|
xmenu->Enable(MNU_COPY_WHERELIST, sqlResult->IsSelection());
|
|
|
|
if ((rows.GetCount()))
|
|
{
|
|
xmenu->Enable(MNU_COPY, true);
|
|
xmenu->Enable(MNU_DELETE, true);
|
|
xmenu->Enable(MNU_PASTE, true);
|
|
|
|
}
|
|
else
|
|
{
|
|
xmenu->Enable(MNU_COPY, false);
|
|
xmenu->Enable(MNU_DELETE, false);
|
|
xmenu->Enable(MNU_PASTE, false);
|
|
}
|
|
xmenu->Enable(MNU_CLEAR_FILTER, isfilterresult);
|
|
sqlResult->PopupMenu(xmenu);
|
|
}
|
|
void frmQuery::OnCopy_Insert(wxCommandEvent &ev)
|
|
{
|
|
// if (currentControl() == sqlResult)
|
|
{
|
|
wxString s=wxT("Insert into format copy buffer.");
|
|
sqlResult->Copy(1);
|
|
SetStatusText(s, STATUSPOS_MSGS);
|
|
}
|
|
}
|
|
void frmQuery::OnCopy_InList(wxCommandEvent& ev)
|
|
{
|
|
// if (currentControl() == sqlResult)
|
|
{
|
|
wxString s = wxT("In list format copy buffer.");
|
|
sqlResult->Copy(2);
|
|
SetStatusText(s, STATUSPOS_MSGS);
|
|
}
|
|
}
|
|
void frmQuery::OnCopy_WhereList(wxCommandEvent& ev)
|
|
{
|
|
// if (currentControl() == sqlResult)
|
|
{
|
|
wxString s = wxT("Where list format copy buffer.");
|
|
sqlResult->Copy(3);
|
|
SetStatusText(s, STATUSPOS_MSGS);
|
|
}
|
|
}
|
|
|
|
void frmQuery::OnGenerateInvoke(wxCommandEvent& ev)
|
|
{
|
|
// if (currentControl() == sqlResult)
|
|
int id=ev.GetId()-MNU_GENERATESQL-1;
|
|
wxString s = _("No template generate.");
|
|
//wxMenu* mi = static_cast<wxMenu*>(ev.GetEventObject());
|
|
if (id>=0 && id<body_template.Count() ) {
|
|
{
|
|
wxString templ = body_template[id];
|
|
s=sqlResult->GenerateTemplate(templ,0);
|
|
|
|
SetStatusText(s.substr(0,200), STATUSPOS_MSGS);
|
|
}
|
|
} else
|
|
SetStatusText(s, STATUSPOS_MSGS);
|
|
}
|
|
void frmQuery::OnCopy_TableToHtml(wxCommandEvent& ev)
|
|
{
|
|
// if (currentControl() == sqlResult)
|
|
{
|
|
wxString s = wxT("Query and table HTML format copy.");
|
|
bool press = wxGetKeyState(WXK_CONTROL);
|
|
wxString q = sqlResult->sqlquerytext;
|
|
wxString html;
|
|
if (!press) {
|
|
if (q.IsEmpty()) {
|
|
SetStatusText("Problem: Query not found.", STATUSPOS_MSGS);
|
|
return;
|
|
}
|
|
ctlSQLBox* box = new ctlSQLBox(sqlNotebook, CTL_SQLQUERY, wxDefaultPosition, wxSize(0, 0), wxTE_MULTILINE | wxTE_RICH2);
|
|
box->SetText(q);
|
|
box->Colourise(0, box->GetLength());
|
|
html = box->TextToHtml(0, box->GetLength());
|
|
delete box;
|
|
}
|
|
else {
|
|
html = "";
|
|
s = wxT("ONLY table HTML format copy.");
|
|
}
|
|
sqlResult->CopyTableToHtml(html);
|
|
|
|
SetStatusText(s, STATUSPOS_MSGS);
|
|
}
|
|
}
|
|
void frmQuery::OnCellLeftDClick(wxGridEvent &event)
|
|
{
|
|
int row=event.GetRow();
|
|
int col=event.GetCol();
|
|
bool reverse=event.AltDown();
|
|
wxString s=wxEmptyString;
|
|
s.Printf("wait ...",row,col);
|
|
SetStatusText(s, STATUSPOS_MSGS);
|
|
s=sqlResult->SetFilter(row,col,reverse);
|
|
isfilterresult=true;
|
|
SetStatusText(s, STATUSPOS_MSGS);
|
|
}
|
|
void frmQuery::OnClear_Filter(wxCommandEvent &ev)
|
|
{
|
|
// if (currentControl() == sqlResult)
|
|
{
|
|
wxString s=wxT("Clear filter");
|
|
sqlResult->ClearFilter();
|
|
SetStatusText(s, STATUSPOS_MSGS);
|
|
isfilterresult=false;
|
|
}
|
|
}
|
|
|
|
void frmQuery::OnCopy_NameTypeCols(wxCommandEvent& ev)
|
|
{
|
|
// if (currentControl() == sqlResult)
|
|
{
|
|
bool press=wxGetKeyState(WXK_CONTROL);
|
|
wxString s = sqlResult->CopySelColumnNameType(press);
|
|
SetStatusText(s, STATUSPOS_MSGS);
|
|
}
|
|
}
|
|
void frmQuery::OnCheck_Column_Date(wxCommandEvent& ev)
|
|
{
|
|
// if (currentControl() == sqlResult)
|
|
{
|
|
wxString s = sqlResult->CheckSelColumnDate();
|
|
SetStatusText(s, STATUSPOS_MSGS);
|
|
}
|
|
}
|
|
|
|
void frmQuery::OnAutoColsPlot(wxCommandEvent& ev)
|
|
{
|
|
// if (currentControl() == sqlResult)
|
|
{
|
|
frmQuery* q = this;
|
|
wxString s = sqlResult->AutoColsPlot(0, q);
|
|
SetStatusText(s, STATUSPOS_MSGS);
|
|
}
|
|
}
|
|
|
|
void frmQuery::OnCompare_2Cell(wxCommandEvent& ev)
|
|
{
|
|
wxString s = sqlResult->CompareSelectCells();
|
|
SetStatusText(s, STATUSPOS_MSGS);
|
|
}
|
|
|
|
void frmQuery::OnSummary_Column(wxCommandEvent &ev)
|
|
{
|
|
// if (currentControl() == sqlResult)
|
|
{
|
|
wxString s=sqlResult->SummaryColumn();
|
|
SetStatusText(s, STATUSPOS_POS);
|
|
}
|
|
}
|
|
void frmQuery::DoUpdatePositionStc(const wxStyledTextEvent &event)
|
|
{
|
|
int selFrom, selTo, selCount;
|
|
sqlQuery->GetSelection(&selFrom, &selTo);
|
|
selCount = selTo - selFrom;
|
|
editMenu->Enable(MNU_AUTOEDITOBJECT, selCount > 0);
|
|
wxString pos;
|
|
wxUniChar ch=0;
|
|
int p = sqlQuery->GetCurrentPos();
|
|
wxString simbol;
|
|
if (p < sqlQuery->GetLength()) {
|
|
simbol = sqlQuery->GetTextRange(p, sqlQuery->PositionRelative(p, 1));
|
|
}
|
|
if (!simbol.IsEmpty()) ch = simbol[0];
|
|
pos.Printf(_("Ln %d, Col %d, Ch %d"), sqlQuery->LineFromPosition(p) + 1, sqlQuery->GetColumn(p) + 1, ch);
|
|
//pos.Printf(_("Ln %d, Col %d, Ch %d, st %d"), sqlQuery->LineFromPosition(sqlQuery->GetCurrentPos()) + 1, sqlQuery->GetColumn(sqlQuery->GetCurrentPos()) + 1, sqlQuery->GetCurrentPos() + 1,sqlQuery->GetStyleAt(sqlQuery->GetCurrentPos() - 1));
|
|
if (pos.length() > 24) {
|
|
pos.Printf("L %d,C %d,Ch %d", sqlQuery->LineFromPosition(p) + 1, sqlQuery->GetColumn(p) + 1, ch);
|
|
|
|
}
|
|
SetStatusText(pos, STATUSPOS_POS);
|
|
if (selCount < 1)
|
|
pos = wxEmptyString;
|
|
else
|
|
pos.Printf(wxPLURAL("%d char", "%d chars", selCount), selCount);
|
|
SetStatusText(pos, STATUSPOS_SEL);
|
|
|
|
}
|
|
void frmQuery::OnPositionStc(wxStyledTextEvent &event)
|
|
{
|
|
CallAfter(&frmQuery::DoUpdatePositionStc,event);
|
|
}
|
|
|
|
|
|
void frmQuery::OpenLastFile()
|
|
{
|
|
wxString str;
|
|
bool modeUnicode = settings->GetUnicodeFile();
|
|
wxUtfFile file(lastPath, wxFile::read, modeUnicode ? wxFONTENCODING_UTF8 : wxFONTENCODING_DEFAULT);
|
|
|
|
m_loadingfile = true;
|
|
if (file.IsOpened())
|
|
file.Read(str);
|
|
|
|
if (!str.IsEmpty())
|
|
{
|
|
sqlQuery->SetText(str);
|
|
sqlQuery->Colourise(0, sqlQuery->GetLength());
|
|
sqlQuery->EmptyUndoBuffer();
|
|
wxSafeYield(); // needed to process sqlQuery modify event
|
|
sqlQuery->SetFilename(lastPath);
|
|
sqlQuery->SetChanged(false);
|
|
sqlQuery->SetOrigin(ORIGIN_FILE);
|
|
setExtendedTitle();
|
|
SqlBookUpdatePageTitle();
|
|
SetLineEndingStyle();
|
|
UpdateRecentFiles(true);
|
|
if(mainForm != NULL)
|
|
{
|
|
mainForm->UpdateAllRecentFiles();
|
|
}
|
|
}
|
|
sqlQuery->SetFocus();
|
|
m_loadingfile = false;
|
|
}
|
|
|
|
|
|
void frmQuery::UpdateAllRecentFiles()
|
|
{
|
|
mainForm->UpdateAllRecentFiles();
|
|
}
|
|
|
|
void frmQuery::OnNew(wxCommandEvent &event)
|
|
{
|
|
frmQuery *fq = new frmQuery(mainForm, wxEmptyString, conn->Duplicate(), wxEmptyString);
|
|
if (mainForm)
|
|
mainForm->AddFrame(fq);
|
|
fq->Go();
|
|
}
|
|
|
|
|
|
void frmQuery::OnOpen(wxCommandEvent &event)
|
|
{
|
|
if (CheckChanged(true))
|
|
return;
|
|
|
|
#ifdef __WXMSW__
|
|
wxFileDialog dlg(this, _("Open query file"), lastDir, wxT(""),
|
|
_("Query files (*.sql)|*.sql|pgScript files (*.pgs)|*.pgs|All files (*.*)|*.*"), wxFD_OPEN);
|
|
#else
|
|
wxFileDialog dlg(this, _("Open query file"), lastDir, wxT(""),
|
|
_("Query files (*.sql)|*.sql|pgScript files (*.pgs)|*.pgs|All files (*)|*"), wxFD_OPEN);
|
|
#endif
|
|
|
|
if (dlg.ShowModal() == wxID_OK)
|
|
{
|
|
lastFilename = dlg.GetFilename();
|
|
lastDir = dlg.GetDirectory();
|
|
lastPath = dlg.GetPath();
|
|
OpenLastFile();
|
|
}
|
|
}
|
|
|
|
void frmQuery::SaveTempFile()
|
|
{
|
|
bool modeUnicode = settings->GetUnicodeFile();
|
|
wxString filename = sqlQuery->GetFilename();
|
|
if (!filename.IsNull())
|
|
{
|
|
return;
|
|
}
|
|
filename=sqlQuery->GetTitle(false);
|
|
wxString pref=conn->GetDbname();
|
|
//if (filename.StartsWith(pref))
|
|
filename+=wxT(".a");
|
|
wxString tempDir = dataDir+wxFileName::GetPathSeparator()+"recovery"+wxFileName::GetPathSeparator();
|
|
if (autoSave) {
|
|
wxUtfFile file(tempDir + filename, wxFile::write, modeUnicode ? wxFONTENCODING_UTF8 : wxFONTENCODING_DEFAULT);
|
|
if (file.IsOpened())
|
|
{
|
|
int nl = sqlQuery->GetCurrentPos();
|
|
wxString strnl;
|
|
strnl = wxString::Format(_("%i@"), nl);
|
|
file.Write(strnl);
|
|
if ((file.Write(sqlQuery->GetText()) == 0) && (!modeUnicode))
|
|
wxMessageBox(_("Query text incomplete.\nQuery contained characters that could not be converted to the local charset.\nPlease correct the data or try using UTF8 instead."));
|
|
file.Close();
|
|
sqlQuery->SetChanged(false);
|
|
SqlBookUpdatePageTitle();
|
|
}
|
|
else
|
|
{
|
|
wxLogError(__("Could not write the file %s: Errcode=%d."), filename.c_str(), wxSysErrorCode());
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
void frmQuery::OnSave(wxCommandEvent &event)
|
|
{
|
|
bool modeUnicode = settings->GetUnicodeFile();
|
|
wxString filename = sqlQuery->GetFilename();
|
|
|
|
if (filename.IsNull())
|
|
{
|
|
OnSaveAs(event);
|
|
return;
|
|
}
|
|
|
|
wxUtfFile file(filename, wxFile::write, modeUnicode ? wxFONTENCODING_UTF8 : wxFONTENCODING_DEFAULT);
|
|
if (file.IsOpened())
|
|
{
|
|
if ((file.Write(sqlQuery->GetText()) == 0) && (!modeUnicode))
|
|
wxMessageBox(_("Query text incomplete.\nQuery contained characters that could not be converted to the local charset.\nPlease correct the data or try using UTF8 instead."));
|
|
file.Close();
|
|
sqlQuery->SetChanged(false);
|
|
setExtendedTitle();
|
|
UpdateRecentFiles();
|
|
SqlBookUpdatePageTitle();
|
|
sqlQuery->SetFilename(filename);
|
|
}
|
|
else
|
|
{
|
|
wxLogError(__("Could not write the file %s: Errcode=%d."), filename.c_str(), wxSysErrorCode());
|
|
}
|
|
}
|
|
|
|
|
|
// Set the line ending style based on the current document.
|
|
void frmQuery::SetLineEndingStyle()
|
|
{
|
|
// Detect the file mode
|
|
wxRegEx *reLF = new wxRegEx(wxT("[^\r]\n"), wxRE_NEWLINE);
|
|
wxRegEx *reCRLF = new wxRegEx(wxT("\r\n"), wxRE_NEWLINE);
|
|
wxRegEx *reCR = new wxRegEx(wxT("\r[^\n]"), wxRE_NEWLINE);
|
|
|
|
bool haveLF = reLF->Matches(sqlQuery->GetText());
|
|
bool haveCRLF = reCRLF->Matches(sqlQuery->GetText());
|
|
bool haveCR = reCR->Matches(sqlQuery->GetText());
|
|
int mode = GetLineEndingStyle();
|
|
|
|
if ((haveLF && haveCR) ||
|
|
(haveLF && haveCRLF) ||
|
|
(haveCR && haveCRLF))
|
|
{
|
|
wxMessageBox(_("This file contains mixed line endings. They will be converted to the current setting."), _("Warning"), wxICON_INFORMATION | wxOK);
|
|
sqlQuery->ConvertEOLs(mode);
|
|
sqlQuery->SetChanged(true);
|
|
setExtendedTitle();
|
|
updateMenu();
|
|
}
|
|
else
|
|
{
|
|
if (haveLF)
|
|
mode = wxSTC_EOL_LF;
|
|
else if (haveCRLF)
|
|
mode = wxSTC_EOL_CRLF;
|
|
else if (haveCR)
|
|
mode = wxSTC_EOL_CR;
|
|
}
|
|
|
|
// Now set the status text, menu options, and the mode
|
|
sqlQuery->SetEOLMode(mode);
|
|
SetEOLModeDisplay(mode);
|
|
|
|
delete reCRLF;
|
|
delete reCR;
|
|
delete reLF;
|
|
}
|
|
|
|
|
|
// Get the line ending style
|
|
int frmQuery::GetLineEndingStyle()
|
|
{
|
|
if (lineEndMenu->IsChecked(MNU_LF))
|
|
return wxSTC_EOL_LF;
|
|
else if (lineEndMenu->IsChecked(MNU_CRLF))
|
|
return wxSTC_EOL_CRLF;
|
|
else if (lineEndMenu->IsChecked(MNU_CR))
|
|
return wxSTC_EOL_CR;
|
|
else
|
|
return sqlQuery->GetEOLMode();
|
|
}
|
|
|
|
void frmQuery::OnAutoEditObject(wxCommandEvent &event)
|
|
{
|
|
if (!mainForm) return;
|
|
//parent->SetCurrentNode(parent->GetBrowser()->GetRootItem(), path);
|
|
pgObject *obj = mainForm->GetBrowser()->GetObject(mainForm->GetBrowser()->GetSelection());
|
|
if (!obj) return;
|
|
pgFunction *fun=(pgFunction *)obj;//obj->Show
|
|
//mainForm.propFactory->StartDialog(mainForm, obj);
|
|
//showMessage(obj->GetTypeName());
|
|
//return;
|
|
if (obj->GetTypeName()==wxT("Servers")||obj->GetTypeName()==wxT("Server")||obj->GetTypeName()==wxT("Databases")
|
|
||obj->GetTypeName()==wxT("Tablespaces")||obj->GetTypeName()==wxT("Group Roles")
|
|
||obj->GetTypeName()==wxT("Login Roles")
|
|
) return;
|
|
wxString databasePath = mainForm->GetNodePath(obj->GetDatabase()->GetId());
|
|
//showMessage(databasePath);
|
|
wxString selText = sqlQuery->GetSelectedText();
|
|
if (!selText.IsNull()) {
|
|
databasePath =databasePath +wxT("/")+ _("Schemas");
|
|
if(!mainForm->SetCurrentNode(mainForm->GetBrowser()->GetRootItem(), databasePath))
|
|
{
|
|
wxMessageBox(_("The specified object couldn't be found in the tree.") + databasePath);
|
|
}
|
|
//int n=mainForm->GetBrowser()->GetChildrenCount(mainForm->GetBrowser()->GetSelection(),false);
|
|
wxTreeItemId matchItem = mainForm->GetBrowser()->FindItem(obj->GetId(),selText,true);
|
|
|
|
if (matchItem.IsOk()) {
|
|
wxString findtext= mainForm->GetBrowser()->GetItemText(matchItem);
|
|
pgObject *o=mainForm->GetBrowser()->GetObject(matchItem);
|
|
//mainForm->GetBrowser()->SelectItem(o->GetId());
|
|
//showMessage(o->GetName().Lower());
|
|
if (!o) return;
|
|
if (o->GetName().Lower()==selText.Lower()) {
|
|
|
|
//obj = mainForm->GetBrowser()->GetObject(mainForm->GetBrowser()->GetSelection());
|
|
mainForm->execSelChange(matchItem,false);
|
|
//obj=o;
|
|
obj = mainForm->GetBrowser()->GetObject(matchItem);
|
|
if (!dlgProperty::EditObjectDialog(mainForm, 0, obj))
|
|
mainForm->CheckAlive();
|
|
|
|
}
|
|
}
|
|
}
|
|
|
|
}
|
|
// User-set the current EOL mode for the form
|
|
void frmQuery::OnSetEOLMode(wxCommandEvent &event)
|
|
{
|
|
int mode = GetLineEndingStyle();
|
|
sqlQuery->ConvertEOLs(mode);
|
|
sqlQuery->SetEOLMode(mode);
|
|
settings->SetLineEndingType(mode);
|
|
|
|
SetEOLModeDisplay(mode);
|
|
|
|
if (!sqlQuery->IsChanged())
|
|
{
|
|
sqlQuery->SetChanged(true);
|
|
setExtendedTitle();
|
|
}
|
|
setExtendedTitle();
|
|
|
|
// TODO: Figure out why this is here?
|
|
pgScript->SetConnection(conn);
|
|
}
|
|
|
|
|
|
// Display the EOL mode settings on the form
|
|
void frmQuery::SetEOLModeDisplay(int mode)
|
|
{
|
|
switch(mode)
|
|
{
|
|
|
|
case wxSTC_EOL_LF:
|
|
lineEndMenu->Check(MNU_LF, true);
|
|
SetStatusText(_("Unix"), STATUSPOS_FORMAT);
|
|
break;
|
|
|
|
case wxSTC_EOL_CRLF:
|
|
lineEndMenu->Check(MNU_CRLF, true);
|
|
SetStatusText(_("DOS"), STATUSPOS_FORMAT);
|
|
break;
|
|
|
|
case wxSTC_EOL_CR:
|
|
lineEndMenu->Check(MNU_CR, true);
|
|
SetStatusText(_("Mac"), STATUSPOS_FORMAT);
|
|
break;
|
|
|
|
default:
|
|
wxLogError(wxT("Someone created a new line ending style! Run, run for your lives!!"));
|
|
}
|
|
}
|
|
|
|
|
|
void frmQuery::OnSaveAs(wxCommandEvent &event)
|
|
{
|
|
wxString filename;
|
|
filename = sqlQuery->GetFilename();
|
|
if (filename.IsNull())
|
|
filename = lastFilename;
|
|
|
|
#ifdef __WXMSW__
|
|
wxFileDialog *dlg = new wxFileDialog(this, _("Save query file as"), lastDir, filename, /*lastFilename,*/
|
|
_("Query files (*.sql)|*.sql|All files (*.*)|*.*"), wxFD_SAVE | wxFD_OVERWRITE_PROMPT);
|
|
#else
|
|
wxFileDialog *dlg = new wxFileDialog(this, _("Save query file as"), lastDir, filename, /*lastFilename,*/
|
|
_("Query files (*.sql)|*.sql|All files (*)|*"), wxFD_SAVE | wxFD_OVERWRITE_PROMPT);
|
|
#endif
|
|
if (dlg->ShowModal() == wxID_OK)
|
|
{
|
|
lastFilename = dlg->GetFilename();
|
|
lastDir = dlg->GetDirectory();
|
|
lastPath = dlg->GetPath();
|
|
switch (dlg->GetFilterIndex())
|
|
{
|
|
case 0:
|
|
#ifdef __WXMAC__
|
|
if (!lastPath.Contains(wxT(".")))
|
|
lastPath += wxT(".sql");
|
|
#endif
|
|
break;
|
|
case 1:
|
|
#ifdef __WXMAC__
|
|
if (!lastPath.Contains(wxT(".")))
|
|
lastPath += wxT(".sql");
|
|
#endif
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
|
|
lastFileFormat = settings->GetUnicodeFile();
|
|
|
|
wxUtfFile file(lastPath, wxFile::write, lastFileFormat ? wxFONTENCODING_UTF8 : wxFONTENCODING_DEFAULT);
|
|
if (file.IsOpened())
|
|
{
|
|
if ((file.Write(sqlQuery->GetText()) == 0) && (!lastFileFormat))
|
|
wxMessageBox(_("Query text incomplete.\nQuery contained characters that could not be converted to the local charset.\nPlease correct the data or try using UTF8 instead."));
|
|
file.Close();
|
|
sqlQuery->SetChanged(false);
|
|
sqlQuery->SetFilename(lastPath);
|
|
|
|
// Forget about Initial origin thus making "Save" button behave as usual
|
|
// (be enabled/disabled according to dirty flag only).
|
|
if (sqlQuery->GetOrigin() == ORIGIN_INITIAL)
|
|
sqlQuery->SetOrigin(ORIGIN_FILE);
|
|
|
|
setExtendedTitle();
|
|
SqlBookUpdatePageTitle();
|
|
SetOutputPaneCaption(true);
|
|
UpdateRecentFiles();
|
|
fileMenu->Enable(MNU_RECENT, (recentFileMenu->GetMenuItemCount() > 0));
|
|
}
|
|
else
|
|
{
|
|
wxLogError(__("Could not write the file %s: Errcode=%d."), lastPath.c_str(), wxSysErrorCode());
|
|
}
|
|
}
|
|
delete dlg;
|
|
}
|
|
|
|
|
|
void frmQuery::OnQuickReport(wxCommandEvent &event)
|
|
{
|
|
wxDateTime now = wxDateTime::Now();
|
|
|
|
frmReport *rep = new frmReport(this);
|
|
|
|
rep->XmlAddHeaderValue(wxT("generated"), now.Format(wxT("%c")));
|
|
rep->XmlAddHeaderValue(wxT("database"), conn->GetName());
|
|
|
|
rep->SetReportTitle(_("Quick report"));
|
|
|
|
int section = rep->XmlCreateSection(_("Query results"));
|
|
|
|
rep->XmlAddSectionTableFromGrid(section, sqlResult);
|
|
|
|
wxString stats;
|
|
stats.Printf(wxT("%ld rows with %d columns retrieved."), sqlResult->NumRows(), sqlResult->GetNumberCols());
|
|
|
|
rep->XmlSetSectionTableInfo(section, stats);
|
|
|
|
wxString query = sqlQuery->GetSelectedText();
|
|
if (query.IsNull())
|
|
query = sqlQuery->GetText();
|
|
|
|
rep->XmlSetSectionSql(section, query);
|
|
|
|
rep->ShowModal();
|
|
}
|
|
|
|
|
|
void frmQuery::OnCancel(wxCommandEvent &event)
|
|
{
|
|
toolBar->EnableTool(MNU_CANCEL, false);
|
|
queryMenu->Enable(MNU_CANCEL, false);
|
|
SetStatusText(_("Cancelling."), STATUSPOS_MSGS);
|
|
|
|
if (sqlResult->RunStatus() == CTLSQL_RUNNING)
|
|
sqlResult->Abort();
|
|
else if (pgScript->IsRunning())
|
|
pgScript->Terminate();
|
|
|
|
QueryExecInfo *qi = (QueryExecInfo *)event.GetClientData();
|
|
if (qi)
|
|
delete qi;
|
|
|
|
aborted = true;
|
|
}
|
|
|
|
|
|
void frmQuery::OnExplain(wxCommandEvent &event)
|
|
{
|
|
if(sqlNotebook->GetSelection() == 1)
|
|
{
|
|
if (!updateFromGqb(true))
|
|
return;
|
|
}
|
|
|
|
wxString query = sqlQuery->GetSelectedText();
|
|
if (query.IsNull()) {
|
|
if (queryMenu->IsChecked(MNU_AUTOSELECTQUERY)) {
|
|
// Auto-select
|
|
SelectQuery();
|
|
query = sqlQuery->GetSelectedText();
|
|
} else
|
|
query = sqlQuery->GetText();
|
|
}
|
|
if (query.IsNull())
|
|
return;
|
|
wxString sql;
|
|
int resultToRetrieve = 1;
|
|
bool verbose = queryMenu->IsChecked(MNU_VERBOSE);
|
|
bool analyze = event.GetId() == MNU_EXPLAINANALYZE;
|
|
|
|
if (analyze)
|
|
{
|
|
sql += wxT("\nBEGIN;\n");
|
|
resultToRetrieve++;
|
|
}
|
|
sql += wxT("EXPLAIN ");
|
|
if (conn->BackendMinimumVersion(9, 0))
|
|
{
|
|
bool costs = queryMenu->IsChecked(MNU_COSTS);
|
|
bool buffers = queryMenu->IsChecked(MNU_BUFFERS) && analyze;
|
|
bool timing = queryMenu->IsChecked(MNU_TIMING) && analyze;
|
|
|
|
sql += wxT("(");
|
|
if (analyze)
|
|
sql += wxT("ANALYZE on, ");
|
|
else
|
|
sql += wxT("ANALYZE off, ");
|
|
if (verbose)
|
|
sql += wxT("VERBOSE on, ");
|
|
else
|
|
sql += wxT("VERBOSE off, ");
|
|
if (costs)
|
|
sql += wxT("COSTS on, ");
|
|
else
|
|
sql += wxT("COSTS off, ");
|
|
if (conn->BackendMinimumVersion(13, 0))
|
|
{
|
|
sql += wxT("SUMMARY on, ");
|
|
}
|
|
|
|
if (buffers)
|
|
sql += wxT("BUFFERS on");
|
|
else
|
|
sql += wxT("BUFFERS off");
|
|
if (conn->BackendMinimumVersion(9, 2))
|
|
{
|
|
if (timing)
|
|
sql += wxT(", TIMING on ");
|
|
else
|
|
sql += wxT(", TIMING off ");
|
|
}
|
|
sql += wxT(")");
|
|
}
|
|
else
|
|
{
|
|
if (analyze)
|
|
sql += wxT("ANALYZE ");
|
|
if (verbose)
|
|
sql += wxT("VERBOSE ");
|
|
}
|
|
|
|
int offset = sql.Length();
|
|
|
|
sql += query;
|
|
|
|
if (analyze)
|
|
{
|
|
// Bizarre bug fix - if we append a rollback directly after -- it'll crash!!
|
|
// Add a \n first.
|
|
sql += wxT("\n;\nROLLBACK;");
|
|
}
|
|
sqlQuery->MarkerDeleteAll(1);
|
|
execQuery(sql, resultToRetrieve, true, offset, false, true, verbose);
|
|
}
|
|
|
|
void frmQuery::OnCommit(wxCommandEvent &event)
|
|
{
|
|
execQuery(wxT("COMMIT;"));
|
|
}
|
|
|
|
void frmQuery::OnRollback(wxCommandEvent &event)
|
|
{
|
|
execQuery(wxT("ROLLBACK;"));
|
|
}
|
|
|
|
// Update the main SQL query from the GQB if desired
|
|
bool frmQuery::updateFromGqb(bool executing)
|
|
{
|
|
if (closing)
|
|
return false;
|
|
|
|
// Make sure this doesn't get call recursively through an event
|
|
if (gqbUpdateRunning)
|
|
return false;
|
|
updateMenu();
|
|
|
|
gqbUpdateRunning = true;
|
|
|
|
// Execute Generation of SQL sentence from GQB
|
|
bool canGenerate = false;
|
|
wxString newQuery = controller->generateSQL();
|
|
|
|
// If the new query is empty, don't do anything
|
|
if (newQuery.IsEmpty())
|
|
{
|
|
if (controller->getTableCount() > 0)
|
|
{
|
|
wxMessageBox(_("No SQL query was generated."), _("Graphical Query Builder"), wxICON_INFORMATION | wxOK);
|
|
}
|
|
gqbUpdateRunning = false;
|
|
return false;
|
|
}
|
|
|
|
// Only prompt the user if the dirty flag is set, and last modification wasn't from GQB,
|
|
// and the textbox is not empty, and the new query is different.
|
|
if (sqlQuery->IsChanged() && sqlQuery->GetOrigin() != ORIGIN_GQB &&
|
|
!sqlQuery->GetText().Trim().IsEmpty() && sqlQuery->GetText() != newQuery + wxT("\n"))
|
|
{
|
|
wxString fn;
|
|
if (executing)
|
|
fn = _("The generated SQL query has changed.\nDo you want to update it and execute the query?");
|
|
else
|
|
fn = _("The generated SQL query has changed.\nDo you want to update it?");
|
|
|
|
wxMessageDialog msg(this, fn, _("Query"), wxYES_NO | wxICON_EXCLAMATION);
|
|
if(msg.ShowModal() == wxID_YES && sqlQuery->IsChanged())
|
|
{
|
|
canGenerate = true;
|
|
}
|
|
else
|
|
{
|
|
gqbUpdateRunning = false;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
canGenerate = true;
|
|
}
|
|
|
|
if(canGenerate)
|
|
{
|
|
sqlQuery->SetText(newQuery + wxT("\n"));
|
|
sqlQuery->Colourise(0, sqlQuery->GetLength());
|
|
wxSafeYield(); // needed to process sqlQuery modify event
|
|
sqlNotebook->SetSelection(0);
|
|
sqlQuery->SetChanged(true);
|
|
sqlQuery->SetOrigin(ORIGIN_GQB);
|
|
setExtendedTitle();
|
|
|
|
gqbUpdateRunning = false;
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
void frmQuery::SelectQuery() {
|
|
long p;
|
|
bool selected = false;
|
|
//sqlQuery->GetSelection();
|
|
wxString name = sqlQuery->GetSelectedText();
|
|
int s,e,i=0;
|
|
if (!name.IsEmpty())
|
|
{
|
|
// never execute
|
|
//name = sqlQuery->GetTextRange(startPos, endPos);
|
|
//selected = false;
|
|
} else {
|
|
int curPos = sqlQuery->GetCurrentPos();
|
|
auto [s,e] = sqlQuery->SelectQuery(curPos);
|
|
// группы серверов/Серверы/serverN/Datebases/dbname
|
|
sqlQuery->SetSelection(s,e);
|
|
}
|
|
|
|
}
|
|
void frmQuery::OnExecuteShift(wxCommandEvent &event)
|
|
{
|
|
//add new page outpane
|
|
int len = sizeof(ctlSQL) / sizeof(ctlSQL[0]);
|
|
wxString titlename;
|
|
for (int i=0;i<len;i++) if (ctlSQL[i]==NULL) {
|
|
|
|
sqlResult = new ctlSQLResult(outputPane, conn, CTL_SQLRESULT, wxDefaultPosition, wxDefaultSize);
|
|
titlename=wxString::Format(_("Out %i"), i);
|
|
outputPane->AddPage(sqlResult, titlename);
|
|
sqlResult->Connect(wxID_ANY, wxEVT_SET_FOCUS, wxFocusEventHandler(frmQuery::OnFocus));
|
|
indexResult=i;
|
|
ctlSQL[i]=sqlResult;
|
|
ctlSBox[i]=sqlQuery;
|
|
break;
|
|
};
|
|
OnExecute(event);
|
|
}
|
|
void frmQuery::OnExecute(wxCommandEvent &event)
|
|
{
|
|
if(sqlNotebook->GetSelection() == 1)
|
|
{
|
|
if (!updateFromGqb(true))
|
|
return;
|
|
}
|
|
CheckModificationFile();
|
|
SaveTempFile();
|
|
wxString query = sqlQuery->GetSelectedText();
|
|
if (query.IsNull()) {
|
|
if (queryMenu->IsChecked(MNU_AUTOSELECTQUERY)) {
|
|
// Auto-select
|
|
SelectQuery();
|
|
query = sqlQuery->GetSelectedText();
|
|
} else
|
|
query = sqlQuery->GetText();
|
|
}
|
|
if (query.IsNull())
|
|
return;
|
|
// set marker sqlQueryExec->MarkerAdd(line, 0); // wxSTC_MARK_CIRCLE
|
|
int en=sqlQuery->GetSelectionEnd();
|
|
int st=-1;
|
|
if (sqlQueryExecLast==sqlQuery) sqlQuery->MarkerDeleteAll(1);
|
|
|
|
if (en>=0) {
|
|
st=sqlQuery->GetSelectionStart();
|
|
int hline=sqlQuery->LineFromPosition(st);
|
|
int eline=sqlQuery->LineFromPosition(en);
|
|
for (int i=hline;i<=eline;i++) {
|
|
sqlQuery->MarkerAdd(i,1);
|
|
}
|
|
//sqlResult->SetRangeLineExecuteSQL(hline,eline);
|
|
}
|
|
if (settings->GetReplaceVars()) {
|
|
//check replace parameters
|
|
FSQL::FormatterSQL f(query);
|
|
FSQL::view_item v;
|
|
bool isddm = false;
|
|
std::vector<var_query> v_list;
|
|
body_template.Clear();
|
|
title_template.Clear();
|
|
while (f.GetNextPositionSqlParse() < query.length() && f.ParseSql(0) >= 0) { // many querys
|
|
|
|
int i = 0;
|
|
int n_check = 0;
|
|
while (f.GetItem(i++, v)) {
|
|
if (n_check == 0 && v.type == FSQL::type_item::keyword) {
|
|
wxString kw = v.txt.Upper();
|
|
if (kw == "WITH" || kw == "SELECT" || kw == "UPDATE" || kw == "INSERT" || kw == "DELETE") {
|
|
isddm = true;
|
|
}
|
|
n_check++;
|
|
}
|
|
if (v.type == FSQL::type_item::comment) {
|
|
wxString kw = v.txt;
|
|
if (kw.Find("@gen:")>0) {
|
|
wxString t=kw.AfterFirst(':');
|
|
body_template.Add(t.AfterFirst(':'));
|
|
title_template.Add(t.BeforeFirst(':'));
|
|
}
|
|
}
|
|
// check bindarg
|
|
if (n_check == 1 && v.type == FSQL::type_item::bindarg) {
|
|
if (!isddm) break;
|
|
|
|
v_list.push_back({ v.srcpos,v.txt,"" });
|
|
}
|
|
}
|
|
|
|
if (isddm && v_list.size() > 0 && f.GetNextPositionSqlParse() >= query.length()) {
|
|
dlgVariable* m_dlgVar = new dlgVariable(sqlQuery, query, v_list);
|
|
int rez = m_dlgVar->ShowModal();
|
|
if (rez == wxID_OK) {
|
|
query = m_dlgVar->GetQuery();
|
|
}
|
|
else if (rez == wxID_IGNORE) {
|
|
|
|
}
|
|
else {
|
|
}
|
|
m_dlgVar->Destroy();
|
|
if (rez == wxID_CANCEL) { return; }
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
execQuery(query);
|
|
sqlQuery->SetFocus();
|
|
}
|
|
|
|
|
|
void frmQuery::OnExecScript(wxCommandEvent &event)
|
|
{
|
|
// Get the script
|
|
wxString query = sqlQuery->GetSelectedText();
|
|
if (query.IsNull())
|
|
query = sqlQuery->GetText();
|
|
if (query.IsNull())
|
|
return;
|
|
|
|
// Make sure pgScript is not already running
|
|
// Required because the pgScript parser isn't currently thread-safe :-(
|
|
if (frmQuery::ms_pgScriptRunning == true)
|
|
{
|
|
wxMessageBox(_("pgScript already running."), _("Concurrent execution of pgScripts is not supported at this time."), wxICON_WARNING | wxOK);
|
|
return;
|
|
}
|
|
frmQuery::ms_pgScriptRunning = true;
|
|
|
|
// Clear markers and indicators
|
|
sqlQuery->MarkerDeleteAll(0);
|
|
sqlQuery->StartStyling(0);
|
|
sqlQuery->SetStyling(sqlQuery->GetText().Length(), 0);
|
|
|
|
// Menu stuff to initialize
|
|
setTools(true);
|
|
queryMenu->Enable(MNU_SAVEHISTORY, true);
|
|
queryMenu->Enable(MNU_CLEARHISTORY, true);
|
|
|
|
// Window stuff
|
|
explainCanvas->Clear();
|
|
msgResult->Clear();
|
|
msgResult->SetFont(settings->GetSQLFont());
|
|
outputPane->SetSelection(2);
|
|
|
|
// Status text
|
|
SetStatusText(wxT(""), STATUSPOS_SECS);
|
|
SetStatusText(_("pgScript is running."), STATUSPOS_MSGS);
|
|
SetStatusText(wxT(""), STATUSPOS_ROWS);
|
|
|
|
// History
|
|
msgHistory->AppendText(_("-- Executing pgScript\n"));
|
|
Update();
|
|
wxTheApp->Yield(true);
|
|
|
|
// Timer
|
|
startTimeQuery = wxGetLocalTimeMillis();
|
|
timer.Start(10);
|
|
|
|
// Delete previous variables
|
|
pgScript->ClearSymbols();
|
|
|
|
// Parse script. Note that we add \n so the parse can correctly identify
|
|
// a comment on the last line of the query.
|
|
pgScript->ParseString(query + wxT("\n"), pgsOutput);
|
|
pgsTimer->Start(20);
|
|
aborted = false;
|
|
}
|
|
|
|
|
|
|
|
void frmQuery::OnExecFile(wxCommandEvent &event)
|
|
{
|
|
if(sqlNotebook->GetSelection() == 1)
|
|
{
|
|
if (!updateFromGqb(true))
|
|
return;
|
|
}
|
|
|
|
wxString query = sqlQuery->GetSelectedText();
|
|
if (query.IsNull())
|
|
query = sqlQuery->GetText();
|
|
|
|
if (query.IsNull())
|
|
return;
|
|
|
|
execQuery(query, 0, false, 0, true);
|
|
sqlQuery->SetFocus();
|
|
}
|
|
void frmQuery::OnAutoReplaceManage(wxCommandEvent &event)
|
|
{
|
|
//if (autoreplace) delete
|
|
//macros = queryMacroFileProvider::LoadMacros(true);
|
|
int r = dlgManageMacros(this, mainForm, autoreplace).ManageMacros();
|
|
if (r == 1)
|
|
{
|
|
// Changed something, so save
|
|
queryMacroFileProvider::SaveAutoReplace(autoreplace);
|
|
}
|
|
|
|
}
|
|
|
|
void frmQuery::OnMacroManage(wxCommandEvent &event)
|
|
{
|
|
int r = dlgManageMacros(this, mainForm, macros).ManageMacros();
|
|
if (r == 1)
|
|
{
|
|
// Changed something, so save
|
|
queryMacroFileProvider::SaveMacros(macros);
|
|
}
|
|
if (r == -1 || r == 1)
|
|
{
|
|
// Changed something requiring rollback
|
|
mainForm->UpdateAllMacrosList();
|
|
}
|
|
|
|
}
|
|
|
|
|
|
void frmQuery::OnMacroInvoke(wxCommandEvent &event)
|
|
{
|
|
queryMacroItem *mac;
|
|
|
|
mac = macros->FindMacro(event.GetId());
|
|
if (!mac)
|
|
return;
|
|
|
|
wxString query = mac->GetQuery();
|
|
if (query.IsEmpty())
|
|
return; // do not execute empty query
|
|
|
|
if (query.Find(wxT("$SELECTION$")) != wxNOT_FOUND)
|
|
{
|
|
wxString selection = sqlQuery->GetSelectedText();
|
|
if (selection.IsEmpty())
|
|
{
|
|
wxMessageBox(_("This macro includes a text substitution. Please select some text in the SQL pane and re-run the macro."), _("Execute macro"), wxICON_EXCLAMATION | wxOK);
|
|
return;
|
|
}
|
|
query.Replace(wxT("$SELECTION$"), selection);
|
|
}
|
|
|
|
execQuery(query);
|
|
sqlQuery->SetFocus();
|
|
}
|
|
|
|
|
|
void frmQuery::setTools(const bool running)
|
|
{
|
|
bool canEndTransaction = (!running && conn->GetTxStatus() != PQTRANS_IDLE);
|
|
|
|
toolBar->EnableTool(MNU_EXECUTE, !running);
|
|
toolBar->EnableTool(MNU_EXECUTE_2, !running);
|
|
toolBar->EnableTool(MNU_EXECPGS, !running);
|
|
toolBar->EnableTool(MNU_EXECFILE, !running);
|
|
toolBar->EnableTool(MNU_EXPLAIN, !running);
|
|
toolBar->EnableTool(MNU_CANCEL, running);
|
|
toolBar->EnableTool(MNU_DOCOMMIT, canEndTransaction);
|
|
toolBar->EnableTool(MNU_DOROLLBACK, canEndTransaction);
|
|
queryMenu->Enable(MNU_EXECUTE, !running);
|
|
queryMenu->Enable(MNU_EXECUTE_2, !running);
|
|
queryMenu->Enable(MNU_EXECPGS, !running);
|
|
queryMenu->Enable(MNU_EXECFILE, !running);
|
|
queryMenu->Enable(MNU_EXPLAIN, !running);
|
|
queryMenu->Enable(MNU_EXPLAINANALYZE, !running);
|
|
queryMenu->Enable(MNU_CANCEL, running);
|
|
queryMenu->Enable(MNU_DOCOMMIT, canEndTransaction);
|
|
queryMenu->Enable(MNU_DOROLLBACK, canEndTransaction);
|
|
fileMenu->Enable(MNU_EXPORT, sqlResult->CanExport());
|
|
fileMenu->Enable(MNU_QUICKREPORT, sqlResult->CanExport());
|
|
fileMenu->Enable(MNU_RECENT, (recentFileMenu->GetMenuItemCount() > 0));
|
|
sqlQuery->EnableAutoComp(running);
|
|
sqlQuery->SetSQLBoxColourBackground(canEndTransaction);
|
|
}
|
|
|
|
|
|
void frmQuery::showMessage(const wxString &msg, const wxString &msgShort)
|
|
{
|
|
msgResult->AppendText(msg + wxT("\n"));
|
|
msgHistory->AppendText(msg + wxT("\n"));
|
|
wxString str;
|
|
if (msgShort.IsNull())
|
|
str = msg;
|
|
else
|
|
str = msgShort;
|
|
str.Replace(wxT("\n"), wxT(" "));
|
|
SetStatusText(str, STATUSPOS_MSGS);
|
|
}
|
|
|
|
|
|
void frmQuery::execQuery(const wxString &query, int resultToRetrieve, bool singleResult, const int queryOffset, bool toFile, bool explain, bool verbose)
|
|
{
|
|
setTools(true);
|
|
queryMenu->Enable(MNU_SAVEHISTORY, true);
|
|
queryMenu->Enable(MNU_CLEARHISTORY, true);
|
|
|
|
explainCanvas->Clear();
|
|
|
|
// Clear markers and indicators
|
|
sqlQuery->MarkerDeleteAll(0);
|
|
//sqlQuery->StartStyling(0);
|
|
//sqlQuery->SetStyling(sqlQuery->GetText().Length(), 0);
|
|
|
|
int i=sqlQueryBook->GetSelection();
|
|
sqlQueryBook->SetPageBitmap(i,CreateBitmap(wxColour(255,0,0)));
|
|
|
|
if (!sqlQuery->IsChanged())
|
|
setExtendedTitle();
|
|
|
|
aborted = false;
|
|
isfilterresult=false;
|
|
|
|
sqlResult=ctlSQL[indexResult];
|
|
sqlResult->ClearFilter();
|
|
ctlSBox[indexResult]=sqlQuery;
|
|
//
|
|
int idx=outputPane->GetPageIndex(sqlResult);
|
|
outputPane->SetPageBitmap(idx,CreateBitmap(wxNullColour));
|
|
|
|
QueryExecInfo *qi = new QueryExecInfo();
|
|
qi->queryOffset = queryOffset;
|
|
qi->toFileExportForm = NULL;
|
|
qi->singleResult = singleResult;
|
|
qi->explain = explain;
|
|
qi->verbose = verbose;
|
|
|
|
if (toFile)
|
|
{
|
|
qi->toFileExportForm = new frmExport(this);
|
|
if (qi->toFileExportForm->ShowModal() != wxID_OK)
|
|
{
|
|
delete qi;
|
|
setTools(false);
|
|
aborted = true;
|
|
return;
|
|
}
|
|
}
|
|
|
|
// Remember the tab from which execute was called. By the time query completes, SQL tab selection may change.
|
|
sqlQueryExec = sqlQuery;
|
|
// Because the output pane is clear during query execution, we clear the result source title on Output Pane.
|
|
sqlQueryExecLast = NULL;
|
|
SetOutputPaneCaption(true);
|
|
|
|
// We must do this lot before the query starts, otherwise
|
|
// it might not happen once the main thread gets busy with
|
|
// other stuff.
|
|
SetStatusText(wxT(""), STATUSPOS_SECS);
|
|
SetStatusText(_("Query is running."), STATUSPOS_MSGS);
|
|
SetStatusText(wxT(""), STATUSPOS_ROWS);
|
|
msgResult->Clear();
|
|
msgResult->SetFont(settings->GetSQLFont());
|
|
|
|
msgHistory->AppendText(wxString::Format(_("-- Executing query [%s]:\n"), sqlQueryExec->GetTitle(false).c_str()));
|
|
msgHistory->AppendText(query);
|
|
msgHistory->AppendText(wxT("\n"));
|
|
Update();
|
|
wxTheApp->Yield(true);
|
|
|
|
startTimeQuery = wxGetLocalTimeMillis();
|
|
timer.Start(10);
|
|
|
|
if (!queryMenu->IsChecked(MNU_AUTOCOMMIT) && conn->GetTxStatus() == PQTRANS_IDLE && !isBeginNotRequired(query))
|
|
conn->ExecuteVoid(wxT("BEGIN;"));
|
|
|
|
if (sqlResult->Execute(query, resultToRetrieve, this, QUERY_COMPLETE, qi) >= 0)
|
|
{
|
|
// Return and wait for the result
|
|
return;
|
|
}
|
|
|
|
completeQuery(false, false, false);
|
|
}
|
|
|
|
bool frmQuery::isBeginNotRequired(wxString query)
|
|
{
|
|
int wordlen = 0;
|
|
|
|
query = query.Trim(false);
|
|
size_t queryLen = query.Len();
|
|
|
|
/*
|
|
* Check word length (since "beginx" is not "begin").
|
|
*/
|
|
while((size_t)wordlen < queryLen && wxIsalpha(query.GetChar(wordlen)))
|
|
wordlen++;
|
|
|
|
/*
|
|
* Transaction control commands. These should include every keyword that
|
|
* gives rise to a TransactionStmt in the backend grammar, except for the
|
|
* savepoint-related commands.
|
|
*
|
|
* (We assume that START must be START TRANSACTION, since there is
|
|
* presently no other "START foo" command.)
|
|
*/
|
|
wxString keyword = query.SubString(0, wordlen - 1);
|
|
|
|
if (wordlen == 5 && keyword.CmpNoCase(wxT("abort")) == 0)
|
|
return true;
|
|
if (wordlen == 5 && keyword.CmpNoCase(wxT("begin")) == 0)
|
|
return true;
|
|
if (wordlen == 5 && keyword.CmpNoCase(wxT("start")) == 0)
|
|
return true;
|
|
if (wordlen == 6 && keyword.CmpNoCase(wxT("commit")) == 0)
|
|
return true;
|
|
if (wordlen == 3 && keyword.CmpNoCase(wxT("end")) == 0)
|
|
return true;
|
|
if (wordlen == 8 && keyword.CmpNoCase(wxT("rollback")) == 0)
|
|
return true;
|
|
if (wordlen == 7 && keyword.CmpNoCase(wxT("prepare")) == 0)
|
|
{
|
|
/* PREPARE TRANSACTION is a TC command, PREPARE foo is not */
|
|
query = query.SubString(wordlen, queryLen - 1);
|
|
query = query.Trim(false);
|
|
queryLen = query.Len();
|
|
wordlen = 0;
|
|
|
|
while((size_t)wordlen < queryLen && wxIsalpha(query.GetChar(wordlen)))
|
|
wordlen++;
|
|
keyword = query.SubString(0, wordlen - 1);
|
|
|
|
if (wordlen == 11 && keyword.CmpNoCase(wxT("transaction")) == 0)
|
|
return true;
|
|
return false;
|
|
}
|
|
|
|
/*
|
|
* Commands not allowed within transactions. The statements checked for
|
|
* here should be exactly those that call PreventTransactionChain() in the
|
|
* backend.
|
|
*/
|
|
if (wordlen == 6 && keyword.CmpNoCase(wxT("vacuum")) == 0)
|
|
return true;
|
|
if (wordlen == 7 && keyword.CmpNoCase(wxT("cluster")) == 0)
|
|
{
|
|
/* CLUSTER with any arguments is allowed in transactions */
|
|
query = query.SubString(wordlen, queryLen - 1);
|
|
query = query.Trim(false);
|
|
queryLen = query.Len();
|
|
|
|
if(wxIsalpha(((wxChar)query.at(0))))
|
|
return false; /* has additional words */
|
|
return true; /* it's CLUSTER without arguments */
|
|
}
|
|
|
|
if (wordlen == 6 && keyword.CmpNoCase(wxT("create")) == 0)
|
|
{
|
|
query = query.SubString(wordlen, queryLen - 1);
|
|
query = query.Trim(false);
|
|
queryLen = query.Len();
|
|
wordlen = 0;
|
|
|
|
while((size_t)wordlen < queryLen && wxIsalpha(query.GetChar(wordlen)))
|
|
wordlen++;
|
|
|
|
keyword = query.SubString(0, wordlen - 1);
|
|
|
|
if (wordlen == 8 && keyword.CmpNoCase(wxT("database")) == 0)
|
|
return true;
|
|
if (wordlen == 10 && keyword.CmpNoCase(wxT("tablespace")) == 0)
|
|
return true;
|
|
|
|
/* CREATE [UNIQUE] INDEX CONCURRENTLY isn't allowed in xacts */
|
|
if (wordlen == 6 && keyword.CmpNoCase(wxT("cluster")) == 0)
|
|
{
|
|
query = query.SubString(wordlen, queryLen - 1);
|
|
query = query.Trim(false);
|
|
queryLen = query.Len();
|
|
wordlen = 0;
|
|
|
|
while((size_t)wordlen < queryLen && wxIsalpha(query.GetChar(wordlen)))
|
|
wordlen++;
|
|
keyword = query.SubString(0, wordlen - 1);
|
|
}
|
|
|
|
if (wordlen == 5 && keyword.CmpNoCase(wxT("index")) == 0)
|
|
{
|
|
query = query.SubString(wordlen, queryLen - 1);
|
|
query = query.Trim(false);
|
|
queryLen = query.Len();
|
|
wordlen = 0;
|
|
|
|
while((size_t)wordlen < queryLen && wxIsalpha(query.GetChar(wordlen)))
|
|
wordlen++;
|
|
keyword = query.SubString(0, wordlen - 1);
|
|
|
|
if (wordlen == 12 && keyword.CmpNoCase(wxT("concurrently")) == 0)
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
if (wordlen == 5 && keyword.CmpNoCase(wxT("alter")) == 0)
|
|
{
|
|
query = query.SubString(wordlen, queryLen - 1);
|
|
query = query.Trim(false);
|
|
queryLen = query.Len();
|
|
wordlen = 0;
|
|
|
|
while((size_t)wordlen < queryLen && wxIsalpha(query.GetChar(wordlen)))
|
|
wordlen++;
|
|
keyword = query.SubString(0, wordlen - 1);
|
|
|
|
/* ALTER SYSTEM isn't allowed in xacts */
|
|
if (wordlen == 6 && keyword.CmpNoCase(wxT("system")) == 0)
|
|
return true;
|
|
|
|
return false;
|
|
}
|
|
|
|
/*
|
|
* Note: these tests will match DROP SYSTEM and REINDEX TABLESPACE, which
|
|
* aren't really valid commands so we don't care much. The other four
|
|
* possible matches are correct.
|
|
*/
|
|
if ((wordlen == 4 && keyword.CmpNoCase(wxT("drop")) == 0) ||
|
|
(wordlen == 7 && keyword.CmpNoCase(wxT("reindex")) == 0))
|
|
{
|
|
query = query.SubString(wordlen , queryLen - 1);
|
|
query = query.Trim(false);
|
|
queryLen = query.Len();
|
|
wordlen = 0;
|
|
|
|
while((size_t)wordlen < queryLen && wxIsalpha(query.GetChar(wordlen)))
|
|
wordlen++;
|
|
keyword = query.SubString(0, wordlen - 1);
|
|
|
|
if (wordlen == 8 && keyword.CmpNoCase(wxT("database")) == 0)
|
|
return true;
|
|
if (wordlen == 6 && keyword.CmpNoCase(wxT("system")) == 0)
|
|
return true;
|
|
if (wordlen == 10 && keyword.CmpNoCase(wxT("tablespace")) == 0)
|
|
return true;
|
|
return false;
|
|
}
|
|
|
|
/* DISCARD ALL isn't allowed in xacts, but other variants are allowed. */
|
|
if (wordlen == 7 && keyword.CmpNoCase(wxT("discard")) == 0)
|
|
{
|
|
query = query.SubString(wordlen, queryLen - 1);
|
|
query = query.Trim(false);
|
|
queryLen = query.Len();
|
|
wordlen = 0;
|
|
|
|
while((size_t)wordlen < queryLen && wxIsalpha(query.GetChar(wordlen)))
|
|
wordlen++;
|
|
keyword = query.SubString(0, wordlen - 1);
|
|
|
|
if (wordlen == 3 && keyword.CmpNoCase(wxT("all")) == 0)
|
|
return true;
|
|
return false;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
// When the query completes, it raises an event which we process here.
|
|
void frmQuery::OnQueryComplete(pgQueryResultEvent &ev)
|
|
{
|
|
QueryExecInfo *qi = (QueryExecInfo *)ev.GetClientData();
|
|
|
|
bool done = false;
|
|
|
|
while (sqlResult->RunStatus() == CTLSQL_RUNNING)
|
|
{
|
|
wxTheApp->Yield(true);
|
|
}
|
|
|
|
while (pgScript->IsRunning())
|
|
{
|
|
wxLogInfo(wxT("SQL Query box: Waiting for script to abort"));
|
|
wxSleep(1);
|
|
}
|
|
|
|
timer.Stop();
|
|
|
|
wxString str;
|
|
str = sqlResult->GetMessagesAndClear();
|
|
//if (!str.IsEmpty())
|
|
//{
|
|
// wxString msg;
|
|
// msgHistory->AppendText(str + wxT("\n"));
|
|
// wxRegEx multilf(wxT("(CONTEXT:.*$)"));
|
|
// multilf.ReplaceAll(&str, wxT(""));
|
|
//
|
|
//}
|
|
|
|
msgResult->AppendText(str);
|
|
msgHistory->AppendText(str);
|
|
|
|
elapsedQuery = wxGetLocalTimeMillis() - startTimeQuery;
|
|
SetStatusText(ElapsedTimeToStr(elapsedQuery), STATUSPOS_SECS);
|
|
|
|
if (sqlResult->RunStatus() != PGRES_TUPLES_OK)
|
|
{
|
|
outputPane->SetSelection(2);
|
|
if (sqlResult->RunStatus() == PGRES_COMMAND_OK)
|
|
{
|
|
done = true;
|
|
|
|
int insertedCount = sqlResult->InsertedCount();
|
|
OID insertedOid = sqlResult->InsertedOid();
|
|
if (insertedCount < 0)
|
|
{
|
|
showMessage(
|
|
wxString::Format(
|
|
_("Query returned successfully with no result in %s."),
|
|
ElapsedTimeToStr(elapsedQuery).c_str()
|
|
),
|
|
_("OK.")
|
|
);
|
|
}
|
|
else if (insertedCount == 1)
|
|
{
|
|
if (insertedOid)
|
|
{
|
|
showMessage(
|
|
wxString::Format(
|
|
_("Query returned successfully: one row with OID %ld inserted, %s execution time."),
|
|
(long)insertedOid,
|
|
ElapsedTimeToStr(elapsedQuery).c_str()),
|
|
wxString::Format(
|
|
_("One row with OID %ld inserted."),
|
|
(long)insertedOid
|
|
)
|
|
);
|
|
}
|
|
else
|
|
{
|
|
showMessage(
|
|
wxString::Format(
|
|
_("Query returned successfully: one row affected, %s execution time."),
|
|
ElapsedTimeToStr(elapsedQuery).c_str()),
|
|
wxString::Format(_("One row affected."))
|
|
);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
showMessage(
|
|
wxString::Format(
|
|
_("Query returned successfully: %d rows affected, %s execution time."),
|
|
insertedCount,
|
|
ElapsedTimeToStr(elapsedQuery).c_str()
|
|
),
|
|
wxString::Format(
|
|
_("%d rows affected."), insertedCount
|
|
)
|
|
);
|
|
}
|
|
}
|
|
else if (sqlResult->RunStatus() == PGRES_EMPTY_QUERY)
|
|
{
|
|
showMessage(_("Empty query, no results."));
|
|
}
|
|
else if (ev.GetInt() == pgQueryResultEvent::PGQ_EXECUTION_CANCELLED)
|
|
{
|
|
showMessage(_("Execution Cancelled!"));
|
|
}
|
|
else
|
|
{
|
|
wxString errMsg, errMsg2;
|
|
long errPos;
|
|
|
|
pgError err = sqlResult->GetResultError();
|
|
errMsg = err.formatted_msg;
|
|
wxLogQuietError(wxT("%s"), conn->GetLastError().Trim().c_str());
|
|
err.statement_pos.ToLong(&errPos);
|
|
|
|
if (err.sql_state.IsEmpty())
|
|
{
|
|
if (wxMessageBox(_("Do you want to attempt to reconnect to the database?"),
|
|
wxString::Format(_("Connection to database %s lost."), conn->GetDbname().c_str()),
|
|
wxICON_EXCLAMATION | wxYES_NO) == wxYES)
|
|
{
|
|
conn->Reset();
|
|
errMsg2 = _("Connection reset.");
|
|
}
|
|
}
|
|
|
|
showMessage(wxString::Format(wxT("********** %s **********\n"), _("Error")));
|
|
showMessage(errMsg);
|
|
if (!errMsg2.IsEmpty())
|
|
showMessage(errMsg2);
|
|
|
|
if (errPos > 0 && sqlQueryExec != NULL)
|
|
{
|
|
int selStart = sqlQueryExec->GetSelectionStart(), selEnd = sqlQueryExec->GetSelectionEnd();
|
|
if (selStart == selEnd)
|
|
selStart = 0;
|
|
|
|
errPos -= qi->queryOffset; // do not count EXPLAIN or similar
|
|
// if exists UNICODE correct errPos
|
|
errPos = sqlQueryExec->PositionRelative(selStart, errPos - 1);
|
|
//if () errPos
|
|
// Set an indicator on the error word (break on any kind of bracket, a space or full stop)
|
|
int sPos = errPos, wEnd = 1;
|
|
//sqlQueryExec->StartStyling(sPos, wxSTC_INDICS_MASK);
|
|
int c = sqlQueryExec->GetCharAt(sPos + wEnd);
|
|
size_t len = sqlQueryExec->GetLength();
|
|
while(c != ' ' && c != '(' && c != '{' && c != '[' && c != '.' &&
|
|
(unsigned int)(sPos + wEnd) < len)
|
|
{
|
|
wEnd++;
|
|
c = sqlQueryExec->GetCharAt(sPos + wEnd);
|
|
}
|
|
//sqlQueryExec->SetStyling(wEnd, wxSTC_INDIC0_MASK);
|
|
|
|
int line = 0, maxLine = sqlQueryExec->GetLineCount();
|
|
while (line < maxLine && sqlQueryExec->GetLineEndPosition(line) < errPos + 1)
|
|
line++;
|
|
if (line < maxLine)
|
|
{
|
|
sqlQueryExec->GotoPos(sPos);
|
|
// wxSTC_MARK_ARROW = 2
|
|
sqlQueryExec->MarkerAdd(line, 0); // wxSTC_MARK_CIRCLE
|
|
|
|
if (!sqlQueryExec->IsChanged())
|
|
setExtendedTitle();
|
|
|
|
sqlQueryExec->EnsureVisible(line);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
done = true;
|
|
for(int i=0;i<outputPane->GetPageCount();i++)
|
|
{
|
|
if (wxDynamicCast(outputPane->GetPage(i), ctlSQLResult)==sqlResult) {
|
|
outputPane->SetSelection(i);
|
|
}
|
|
}
|
|
|
|
long rowsTotal = sqlResult->NumRows();
|
|
|
|
if (qi->toFileExportForm)
|
|
{
|
|
SetStatusText(wxString::Format(wxPLURAL("%d row.", "%d rows.", rowsTotal), rowsTotal), STATUSPOS_ROWS);
|
|
|
|
if (rowsTotal)
|
|
{
|
|
SetStatusText(_("Writing data."), STATUSPOS_MSGS);
|
|
|
|
toolBar->EnableTool(MNU_CANCEL, false);
|
|
queryMenu->Enable(MNU_CANCEL, false);
|
|
SetCursor(*wxHOURGLASS_CURSOR);
|
|
|
|
if (sqlResult->ToFile(qi->toFileExportForm))
|
|
SetStatusText(_("Data written to file."), STATUSPOS_MSGS);
|
|
else
|
|
SetStatusText(_("Data export aborted."), STATUSPOS_MSGS);
|
|
SetCursor(wxNullCursor);
|
|
}
|
|
else
|
|
SetStatusText(_("No data to export."), STATUSPOS_MSGS);
|
|
}
|
|
else
|
|
{
|
|
if (qi->singleResult)
|
|
{
|
|
sqlResult->DisplayData(true);
|
|
|
|
showMessage(wxString::Format(
|
|
wxPLURAL("%ld row retrieved.", "%ld rows retrieved.",
|
|
sqlResult->NumRows()), sqlResult->NumRows()),
|
|
_("OK."));
|
|
}
|
|
else
|
|
{
|
|
SetStatusText(
|
|
wxString::Format(
|
|
wxPLURAL(
|
|
"Retrieving data: %d row.",
|
|
"Retrieving data: %d rows.",
|
|
(int)rowsTotal), (int)rowsTotal),
|
|
STATUSPOS_MSGS);
|
|
wxTheApp->Yield(true);
|
|
|
|
sqlResult->DisplayData();
|
|
|
|
SetStatusText(
|
|
ElapsedTimeToStr(elapsedQuery),
|
|
STATUSPOS_SECS
|
|
);
|
|
|
|
str = wxString::Format(
|
|
_("Total query runtime: %s\n"),
|
|
ElapsedTimeToStr(elapsedQuery).c_str()
|
|
);
|
|
msgResult->AppendText(str);
|
|
msgHistory->AppendText(str);
|
|
|
|
showMessage(
|
|
wxString::Format(
|
|
wxPLURAL(
|
|
"%d row retrieved.",
|
|
"%d rows retrieved.",
|
|
(int)sqlResult->NumRows()
|
|
),
|
|
(int)sqlResult->NumRows()
|
|
),
|
|
_("OK.")
|
|
);
|
|
}
|
|
SetStatusText(
|
|
wxString::Format(
|
|
wxPLURAL(
|
|
"%ld row.",
|
|
"%ld rows.",
|
|
rowsTotal
|
|
),
|
|
rowsTotal
|
|
),
|
|
STATUSPOS_ROWS
|
|
);
|
|
}
|
|
}
|
|
|
|
if (sqlResult->RunStatus() == PGRES_TUPLES_OK || sqlResult->RunStatus() == PGRES_COMMAND_OK)
|
|
{
|
|
// Get the executed query
|
|
wxString executedQuery = sqlQueryExec->GetSelectedText();
|
|
if (executedQuery.IsNull())
|
|
executedQuery = sqlQueryExec->GetText();
|
|
|
|
// Same query, but without return feeds and carriage returns
|
|
wxString executedQueryWithoutReturns = executedQuery;
|
|
executedQueryWithoutReturns.Replace(wxT("\n"), wxT(" "));
|
|
executedQueryWithoutReturns.Replace(wxT("\r"), wxT(" "));
|
|
executedQueryWithoutReturns = executedQueryWithoutReturns.Trim();
|
|
|
|
if (executedQuery.Len() < (unsigned int)settings->GetHistoryMaxQuerySize())
|
|
{
|
|
// We put in the combo box the query without returns...
|
|
sqlQueries->Append(executedQueryWithoutReturns);
|
|
|
|
// .. but we save the query with returns in the array
|
|
// (so that we have the real query in the file)
|
|
histoQueries.Add(executedQuery);
|
|
|
|
// Finally, we save the queries
|
|
SaveQueries();
|
|
}
|
|
|
|
// Search a matching old query
|
|
unsigned int index = 0;
|
|
bool found = false;
|
|
while (!found && index < sqlQueries->GetCount())
|
|
{
|
|
found = sqlQueries->GetString(index) == executedQueryWithoutReturns;
|
|
if (!found)
|
|
index++;
|
|
}
|
|
|
|
// If we found one, delete it from the combobox and the array
|
|
if (found && index < (unsigned int)sqlQueries->GetCount() - 1)
|
|
{
|
|
histoQueries.RemoveAt(index);
|
|
sqlQueries->Delete(index);
|
|
}
|
|
}
|
|
|
|
// Make sure only the maximum query number is enforced
|
|
while (sqlQueries->GetCount() > (unsigned int)settings->GetHistoryMaxQueries())
|
|
{
|
|
histoQueries.RemoveAt(0);
|
|
sqlQueries->Delete(0);
|
|
}
|
|
|
|
SaveQueries();
|
|
|
|
completeQuery(done, qi->explain, qi->verbose);
|
|
delete qi;
|
|
}
|
|
|
|
|
|
void frmQuery::OnScriptComplete(wxCommandEvent &ev)
|
|
{
|
|
// Stop timers
|
|
timer.Stop();
|
|
pgsTimer->Stop();
|
|
|
|
// Write output
|
|
writeScriptOutput();
|
|
|
|
// Reset tools
|
|
setTools(false);
|
|
|
|
// Unlock our pseudo-mutex thingy
|
|
frmQuery::ms_pgScriptRunning = false;
|
|
|
|
// Manage timer
|
|
elapsedQuery = wxGetLocalTimeMillis() - startTimeQuery;
|
|
wxString fmtExecTime = ElapsedTimeToStr(elapsedQuery);
|
|
SetStatusText(fmtExecTime, STATUSPOS_SECS);
|
|
SetStatusText(_("pgScript completed."), STATUSPOS_MSGS);
|
|
msgHistory->AppendText(
|
|
wxString::Format(
|
|
_("Total pgScript runtime: %s\n\n"),
|
|
fmtExecTime.c_str()
|
|
)
|
|
);
|
|
// Check whether there was an error/exception
|
|
if (pgScript->errorOccurred() && pgScript->errorLine() >= 1)
|
|
{
|
|
// Find out what the line number is
|
|
int selStart = sqlQuery->GetSelectionStart(), selEnd = sqlQuery->GetSelectionEnd();
|
|
if (selStart == selEnd)
|
|
selStart = 0;
|
|
int line = 0, maxLine = sqlQuery->GetLineCount();
|
|
while (line < maxLine && sqlQuery->GetLineEndPosition(line) < selStart)
|
|
line++;
|
|
line += pgScript->errorLine() - 1;
|
|
|
|
// Mark the line where the error occurred
|
|
sqlQuery->MarkerAdd(line, 0);
|
|
|
|
// Go to that line
|
|
sqlQuery->GotoPos(sqlQuery->GetLineEndPosition(line));
|
|
}
|
|
}
|
|
|
|
void frmQuery::writeScriptOutput()
|
|
{
|
|
pgScript->LockOutput();
|
|
|
|
wxString output(pgsOutputString);
|
|
pgsOutputString.Clear();
|
|
msgResult->AppendText(output);
|
|
|
|
pgScript->UnlockOutput();
|
|
}
|
|
|
|
// Complete the processing of a query
|
|
void frmQuery::completeQuery(bool done, bool explain, bool verbose)
|
|
{
|
|
// Display async notifications
|
|
pgNotification *notify;
|
|
int notifies = 0;
|
|
notify = conn->GetNotification();
|
|
while (notify)
|
|
{
|
|
wxString notifyStr;
|
|
notifies++;
|
|
|
|
if (notify->data.IsEmpty())
|
|
notifyStr.Printf(_("\nAsynchronous notification of '%s' received from backend pid %d"), notify->name.c_str(), notify->pid);
|
|
else
|
|
notifyStr.Printf(_("\nAsynchronous notification of '%s' received from backend pid %d\n Data: %s"), notify->name.c_str(), notify->pid, notify->data.c_str());
|
|
|
|
msgResult->AppendText(notifyStr);
|
|
msgHistory->AppendText(notifyStr);
|
|
|
|
notify = conn->GetNotification();
|
|
}
|
|
|
|
if (notifies)
|
|
{
|
|
wxString statusMsg = statusBar->GetStatusText(STATUSPOS_MSGS);
|
|
if (statusMsg.Last() == '.')
|
|
statusMsg = statusMsg.Left(statusMsg.Length() - 1);
|
|
|
|
SetStatusText(wxString::Format(
|
|
wxPLURAL("%s (%d asynchronous notification received).", "%s (%d asynchronous notifications received).", notifies),
|
|
statusMsg.c_str(), notifies), STATUSPOS_MSGS);
|
|
}
|
|
|
|
msgResult->AppendText(wxT("\n"));
|
|
msgResult->ShowPosition(0);
|
|
msgHistory->AppendText(wxT("\n"));
|
|
msgHistory->ShowPosition(0);
|
|
|
|
// If the transaction aborted for some reason, issue a rollback to cleanup.
|
|
if (queryMenu->IsChecked(MNU_AUTOROLLBACK) && conn->GetTxStatus() == PGCONN_TXSTATUS_INERROR)
|
|
conn->ExecuteVoid(wxT("ROLLBACK;"));
|
|
|
|
setTools(false);
|
|
fileMenu->Enable(MNU_EXPORT, sqlResult->CanExport());
|
|
|
|
if ((!IsActive() || IsIconized())|| (elapsedQuery>120*1000))
|
|
RequestUserAttention();
|
|
|
|
if (!viewMenu->IsChecked(MNU_OUTPUTPANE))
|
|
{
|
|
viewMenu->Check(MNU_OUTPUTPANE, true);
|
|
manager.GetPane(wxT("outputPane")).Show(true);
|
|
manager.Update();
|
|
}
|
|
|
|
// If this was an EXPLAIN query, process the results
|
|
if (done && explain)
|
|
{
|
|
if (!verbose || conn->BackendMinimumVersion(8, 4))
|
|
{
|
|
int i;
|
|
wxString str;
|
|
if (sqlResult->NumRows() == 1)
|
|
{
|
|
// Avoid shared storage issues with strings
|
|
str.Append(sqlResult->OnGetItemText(0, 0).c_str());
|
|
}
|
|
else
|
|
{
|
|
for (i = 0 ; i < sqlResult->NumRows() ; i++)
|
|
{
|
|
if (i)
|
|
str.Append(wxT("\n"));
|
|
str.Append(sqlResult->OnGetItemText(i, 0));
|
|
}
|
|
}
|
|
explainCanvas->SetExplainString(str);
|
|
outputPane->SetSelection(1);
|
|
}
|
|
updateMenu();
|
|
}
|
|
|
|
// Change the output pane caption so the user knows which tab the result came from
|
|
sqlQueryExecLast = sqlQueryExec;
|
|
SetOutputPaneCaption(true);
|
|
for (int i=0;i<sqlQueryBook->GetPageCount();i++)
|
|
if ((sqlQueryBook->GetPageBitmap(i)).IsOk()) sqlQueryBook->SetPageBitmap(i,wxNullBitmap);
|
|
//int i=sqlQueryBook->GetPageCount()-1;
|
|
//sqlQueryBook->SetPageBitmap(i,CreateBitmap(wxNullColour));
|
|
|
|
//int i=sqlQueryBook->GetSelection() if ();
|
|
|
|
|
|
sqlQueryExec = NULL;
|
|
sqlQuery->SetFocus();
|
|
|
|
}
|
|
|
|
|
|
void frmQuery::OnTimer(wxTimerEvent &event)
|
|
{
|
|
elapsedQuery = wxGetLocalTimeMillis() - startTimeQuery;
|
|
SetStatusText(ElapsedTimeToStr(elapsedQuery), STATUSPOS_SECS);
|
|
|
|
wxString str = sqlResult->GetMessagesAndClear();
|
|
if (!str.IsEmpty())
|
|
{
|
|
// wxString msg;
|
|
// msgHistory->AppendText(str + wxT("\n"));
|
|
// wxRegEx multilf(wxT("(CONTEXT:.*$)"));
|
|
// multilf.ReplaceAll(&str, wxT(""));
|
|
// msgResult->AppendText(str + wxT("\n"));
|
|
//
|
|
msgHistory->AppendText(str + wxT("\n"));
|
|
msgResult->AppendText(str + wxT("\n"));
|
|
}
|
|
|
|
// Increase the granularity for longer running queries
|
|
if (timer.IsRunning())
|
|
{
|
|
// Set timer to fire every 100 ms if >200 ms elapsed
|
|
if (elapsedQuery > 200 && timer.GetInterval() < 100)
|
|
{
|
|
timer.Stop();
|
|
timer.Start(100);
|
|
}
|
|
// Set timer to fire every 1000 ms if >60 seconds elapsed
|
|
else if (elapsedQuery > 60 * 1000 && timer.GetInterval() < 1000)
|
|
{
|
|
timer.Stop();
|
|
timer.Start(1000);
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
// Adjust sizes of GQB components, Located here because need to
|
|
// avoid some issues when implementing inside controller/view Classes
|
|
void frmQuery::adjustGQBSizes()
|
|
{
|
|
// Get Size (only height) from main Tab with GQB and SQL Editor and adjust the width
|
|
// to desiree, then set [Sash of tablesBrowser | GQB_Canvas]
|
|
manager.Update();
|
|
sqlNotebook->Refresh();
|
|
wxSize s = sqlNotebook->GetSize();
|
|
s.SetWidth(200);
|
|
s.SetHeight(s.GetHeight() - 180); //re-adjust weight eliminating Horz Sash Position
|
|
controller->getTablesBrowser()->SetSize(s);
|
|
controller->setSashVertPosition(controller->getTablesBrowser()->GetSize().GetWidth());
|
|
|
|
// Now Adjust Sash Horizontal
|
|
s = sqlNotebook->GetSize();
|
|
controller->setSashHorizPosition(s.GetHeight() - 150);
|
|
|
|
// Adjust GQB grids internal columns sizes
|
|
controller->calcGridColsSizes();
|
|
}
|
|
|
|
|
|
// Adjust sizes of GQB components after vertical sash adjustment,
|
|
// Located here because need to avoid some issues when implementing
|
|
// inside controller/view Classes
|
|
void frmQuery::OnResizeHorizontally(wxSplitterEvent &event)
|
|
{
|
|
int y = event.GetSashPosition();
|
|
wxSize s = controller->getTablesBrowser()->GetSize();
|
|
s.SetHeight(y); // re-adjust weight eliminating Horz Sash Position
|
|
controller->getTablesBrowser()->SetSize(s);
|
|
}
|
|
|
|
|
|
|
|
// This function adjust the GQB Components after an event on the wxAui
|
|
// event, it's a workaround because need event finish to work properly
|
|
void frmQuery::OnAdjustSizesTimer(wxTimerEvent &event)
|
|
{
|
|
adjustGQBSizes();
|
|
adjustSizesTimer->Stop();
|
|
}
|
|
|
|
void frmQuery::OnBlockIndent(wxCommandEvent &event)
|
|
{
|
|
if (FindFocus()->GetId() == CTL_SQLQUERY)
|
|
sqlQuery->CmdKeyExecute(wxSTC_CMD_TAB);
|
|
else if (FindFocus()->GetId() == CTL_SCRATCHPAD)
|
|
scratchPad->WriteText(wxT("\t"));
|
|
}
|
|
|
|
void frmQuery::OnBlockOutDent(wxCommandEvent &event)
|
|
{
|
|
if (FindFocus()->GetId() == CTL_SQLQUERY)
|
|
sqlQuery->CmdKeyExecute(wxSTC_CMD_BACKTAB);
|
|
}
|
|
|
|
void frmQuery::OnChangeToUpperCase(wxCommandEvent &event)
|
|
{
|
|
if (FindFocus()->GetId() == CTL_SQLQUERY)
|
|
sqlQuery->UpperCase();
|
|
}
|
|
|
|
void frmQuery::OnChangeToLowerCase(wxCommandEvent &event)
|
|
{
|
|
if (FindFocus()->GetId() == CTL_SQLQUERY)
|
|
sqlQuery->LowerCase();
|
|
}
|
|
|
|
void frmQuery::OnCommentText(wxCommandEvent &event)
|
|
{
|
|
if (FindFocus()->GetId() == CTL_SQLQUERY)
|
|
sqlQuery->BlockComment(false);
|
|
}
|
|
|
|
void frmQuery::OnUncommentText(wxCommandEvent &event)
|
|
{
|
|
if (FindFocus()->GetId() == CTL_SQLQUERY)
|
|
sqlQuery->BlockComment(true);
|
|
}
|
|
void frmQuery::OnDoubleText(wxCommandEvent& event)
|
|
{
|
|
if (FindFocus()->GetId() == CTL_SQLQUERY)
|
|
sqlQuery->BlockDouble(false);
|
|
}
|
|
|
|
void frmQuery::OnUnDoubleText(wxCommandEvent& event)
|
|
{
|
|
if (FindFocus()->GetId() == CTL_SQLQUERY)
|
|
sqlQuery->BlockDouble(true);
|
|
}
|
|
|
|
void frmQuery::OnExternalFormat(wxCommandEvent &event)
|
|
{
|
|
if (FindFocus()->GetId() == CTL_SQLQUERY)
|
|
{
|
|
wxBusyCursor wait;
|
|
SetStatusText(_("Running formatting command..."), STATUSPOS_MSGS);
|
|
SetStatusText(sqlQuery->ExternalFormat(), STATUSPOS_MSGS);
|
|
sqlQuery->SetFocus(); // could loose focus after running formatting process
|
|
}
|
|
}
|
|
void frmQuery::OnExternalAlign(wxCommandEvent& event)
|
|
{
|
|
if (FindFocus()->GetId() == CTL_SQLQUERY)
|
|
{
|
|
wxBusyCursor wait;
|
|
SetStatusText(_("Running aligning command..."), STATUSPOS_MSGS);
|
|
SetStatusText(sqlQuery->ExternalFormat(1), STATUSPOS_MSGS);
|
|
sqlQuery->SetFocus(); // could loose focus after running formatting process
|
|
}
|
|
}
|
|
|
|
wxBitmap frmQuery::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;
|
|
}
|
|
|
|
wxColour frmQuery::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;
|
|
}
|
|
|
|
void frmQuery::LoadQueries()
|
|
{
|
|
xmlDocPtr doc;
|
|
xmlNodePtr cur;
|
|
xmlChar *key;
|
|
|
|
if (!wxFile::Access(settings->GetHistoryFile(), wxFile::read))
|
|
return;
|
|
|
|
doc = xmlParseFile((const char *)settings->GetHistoryFile().mb_str(wxConvUTF8));
|
|
if (doc == NULL)
|
|
{
|
|
wxMessageBox(_("Failed to load the history file!"));
|
|
::wxRemoveFile(settings->GetHistoryFile());
|
|
return;
|
|
}
|
|
|
|
cur = xmlDocGetRootElement(doc);
|
|
if (cur == NULL)
|
|
{
|
|
xmlFreeDoc(doc);
|
|
return;
|
|
}
|
|
|
|
if (xmlStrcmp(cur->name, (const xmlChar *) "histoqueries"))
|
|
{
|
|
wxMessageBox(_("Failed to load the history file!"));
|
|
xmlFreeDoc(doc);
|
|
::wxRemoveFile(settings->GetHistoryFile());
|
|
return;
|
|
}
|
|
|
|
cur = cur->xmlChildrenNode;
|
|
while (cur != NULL)
|
|
{
|
|
if ((!xmlStrcmp(cur->name, (const xmlChar *)"histoquery")))
|
|
{
|
|
key = xmlNodeListGetString(doc, cur->xmlChildrenNode, 1);
|
|
|
|
if (key)
|
|
{
|
|
if (WXSTRING_FROM_XML(key) != wxT(""))
|
|
{
|
|
wxString query = WXSTRING_FROM_XML(key);
|
|
wxString tmp = query;
|
|
tmp.Replace(wxT("\n"), wxT(" "));
|
|
tmp.Replace(wxT("\r"), wxT(" "));
|
|
sqlQueries->Append(tmp);
|
|
histoQueries.Add(query);
|
|
}
|
|
xmlFree(key);
|
|
}
|
|
}
|
|
|
|
cur = cur->next;
|
|
}
|
|
|
|
xmlFreeDoc(doc);
|
|
|
|
// Make sure only the maximum query number is enforced
|
|
if (sqlQueries->GetCount() > (unsigned int)settings->GetHistoryMaxQueries())
|
|
{
|
|
while (sqlQueries->GetCount() > (unsigned int)settings->GetHistoryMaxQueries())
|
|
{
|
|
histoQueries.RemoveAt(0);
|
|
sqlQueries->Delete(0);
|
|
}
|
|
SaveQueries();
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
|
|
void frmQuery::SaveQueries()
|
|
{
|
|
size_t i;
|
|
xmlTextWriterPtr writer;
|
|
|
|
writer = xmlNewTextWriterFilename((const char *)settings->GetHistoryFile().mb_str(wxConvUTF8), 0);
|
|
if (!writer)
|
|
{
|
|
wxMessageBox(_("Failed to write to history file!"));
|
|
return;
|
|
}
|
|
xmlTextWriterSetIndent(writer, 1);
|
|
|
|
if ((xmlTextWriterStartDocument(writer, NULL, "UTF-8", NULL) < 0) ||
|
|
(xmlTextWriterStartElement(writer, XML_STR("histoqueries")) < 0))
|
|
{
|
|
wxMessageBox(_("Failed to write to history file!"));
|
|
xmlFreeTextWriter(writer);
|
|
return;
|
|
}
|
|
|
|
for (i = 0; i < histoQueries.GetCount(); i++)
|
|
{
|
|
xmlTextWriterStartElement(writer, XML_STR("histoquery"));
|
|
xmlTextWriterWriteString(writer, XML_FROM_WXSTRING(histoQueries.Item(i)));
|
|
xmlTextWriterEndElement(writer);
|
|
}
|
|
|
|
if (xmlTextWriterEndDocument(writer) < 0)
|
|
{
|
|
wxMessageBox(_("Failed to write to history file!"));
|
|
}
|
|
|
|
xmlFreeTextWriter(writer);
|
|
}
|
|
|
|
|
|
void frmQuery::OnChangeQuery(wxCommandEvent &event)
|
|
{
|
|
wxString query = histoQueries.Item(sqlQueries->GetSelection());
|
|
if (query.Length() > 0)
|
|
{
|
|
sqlQuery->SetText(query);
|
|
sqlQuery->Colourise(0, sqlQuery->GetLength());
|
|
wxSafeYield(); // needed to process sqlQuery modify event
|
|
sqlQuery->SetChanged(true);
|
|
sqlQuery->SetOrigin(ORIGIN_HISTORY);
|
|
setExtendedTitle();
|
|
SetLineEndingStyle();
|
|
btnDeleteCurrent->Enable(true);
|
|
}
|
|
btnDeleteAll->Enable(sqlQueries->GetCount() > 0);
|
|
}
|
|
|
|
|
|
void frmQuery::OnDeleteCurrent(wxCommandEvent &event)
|
|
{
|
|
|
|
if ( wxMessageDialog(this,
|
|
_("Delete current query from history?"),
|
|
_("Confirm deletion"),
|
|
wxYES_NO | wxNO_DEFAULT | wxICON_EXCLAMATION).ShowModal() == wxID_YES )
|
|
{
|
|
histoQueries.RemoveAt(sqlQueries->GetSelection());
|
|
sqlQueries->Delete(sqlQueries->GetSelection());
|
|
sqlQueries->SetValue(wxT(""));
|
|
btnDeleteCurrent->Enable(false);
|
|
btnDeleteAll->Enable(sqlQueries->GetCount() > 0);
|
|
SaveQueries();
|
|
}
|
|
}
|
|
void frmQuery::OnModeTransaction(wxCommandEvent &event)
|
|
{
|
|
queryMenu->Check(MNU_AUTOCOMMIT, !queryMenu->IsChecked(MNU_AUTOCOMMIT));
|
|
OnAutoCommit(event);
|
|
}
|
|
void frmQuery::OnDeleteAll(wxCommandEvent &event)
|
|
{
|
|
|
|
if ( wxMessageDialog(this,
|
|
_("Delete all queries from history?"),
|
|
_("Confirm deletion"),
|
|
wxYES_NO | wxNO_DEFAULT | wxICON_EXCLAMATION).ShowModal() == wxID_YES )
|
|
{
|
|
histoQueries.Clear();
|
|
sqlQueries->Clear();
|
|
sqlQueries->SetValue(wxT(""));
|
|
btnDeleteCurrent->Enable(false);
|
|
btnDeleteAll->Enable(false);
|
|
SaveQueries();
|
|
}
|
|
}
|
|
|
|
void frmQuery::BeginPerspectiveChange()
|
|
{
|
|
manager.GetPane(_("outputPane")).Caption(_("Output pane"));
|
|
}
|
|
|
|
void frmQuery::EndPerspectiveChange(bool update)
|
|
{
|
|
SetOutputPaneCaption(update);
|
|
}
|
|
|
|
void frmQuery::SetOutputPaneCaption(bool update)
|
|
{
|
|
wxString caption;
|
|
wxString title;
|
|
|
|
if (sqlQueryExecLast == NULL)
|
|
caption = _("Output pane");
|
|
else
|
|
{
|
|
// We don't want to make it look like Output Pane has been changed,
|
|
// so request the title without the change indicator
|
|
title = sqlQueryExecLast->GetTitle(false);
|
|
caption = wxString::Format(_("Output pane [%s]"), title.c_str());
|
|
}
|
|
|
|
manager.GetPane(wxT("outputPane")).Caption(caption);
|
|
|
|
if (update)
|
|
manager.Update();
|
|
}
|
|
|
|
// Methods related to SQL tabs //
|
|
void frmQuery::fileMarkerActive(bool addOrRemove, const wxString &sqlTabName) {
|
|
wxString tempDir = dataDir+wxFileName::GetPathSeparator()+"recovery"+wxFileName::GetPathSeparator();
|
|
|
|
wxString tabname = sqlTabName;
|
|
if (sqlTabName.Find("*")>=0) tabname = sqlTabName.BeforeLast('*');
|
|
|
|
wxString fn = tempDir + wxT("_active.") + tabname + ".a";
|
|
//if (sqlTabName.Right(1)=='*' ) tabname=
|
|
if (addOrRemove && autoSave)
|
|
{
|
|
//wxUtfFile file(fn, wxFile::write, wxFONTENCODING_UTF8);
|
|
wxFile file(fn, wxFile::write);
|
|
// remove any ohher files
|
|
|
|
for (int i = 0; i < sqlQueryBook->GetPageCount(); i++) {
|
|
wxString textpage = sqlQueryBook->GetPageText(i);
|
|
if (tabname != textpage)
|
|
{
|
|
textpage = tempDir + "_active." + textpage + ".a";
|
|
if (wxFileName::FileExists(textpage)) wxRemoveFile(textpage);
|
|
}
|
|
}
|
|
}
|
|
else
|
|
if (wxFileName::FileExists(fn)) wxRemoveFile(fn);
|
|
|
|
}
|
|
void frmQuery::CheckModificationFile() {
|
|
if (sqlQuery!=NULL && sqlQuery->IsFileModification()) {
|
|
if (wxMessageBox("File " + sqlQuery->GetFilename() + " has been changed.\nReload file?",
|
|
"Reload sql file",
|
|
wxICON_EXCLAMATION | wxYES_NO) == wxYES)
|
|
OpenLastFile();
|
|
|
|
}
|
|
}
|
|
void frmQuery::OnSqlBookPageChanged(wxAuiNotebookEvent &event)
|
|
{
|
|
// Try to always keep sqlQuery variable pointing to the currently selected SQLBox.
|
|
// When closing and removing all tabs, page count may be zero.
|
|
if (sqlQueryBook->GetPageCount() > 0)
|
|
{
|
|
size_t curpage = sqlQueryBook->GetSelection();
|
|
sqlQuery = wxDynamicCast(sqlQueryBook->GetPage(curpage), ctlSQLBox);
|
|
if (sqlQuery != NULL)
|
|
{
|
|
// Update UI with chosen query's info
|
|
SetEOLModeDisplay(sqlQuery->GetEOLMode());
|
|
setExtendedTitle();
|
|
curpage = outputPane->GetSelection();
|
|
ctlSQLResult *r;
|
|
r=NULL;
|
|
if (wxDynamicCast(outputPane->GetPage(curpage), ctlSQLResult)) {
|
|
ctlSQLResult *r = wxDynamicCast(outputPane->GetPage(curpage), ctlSQLResult);
|
|
}
|
|
int pos=-1;
|
|
//if (r!=NULL) for (int i=0;i<MAX_RESULT_COUNT;i++) if (ctlSQL[i]==r && ctlSBox[i]==sqlQuery) pos=i;
|
|
if (pos==-1) {
|
|
for (int i=0;i<MAX_RESULT_COUNT;i++)
|
|
{
|
|
if (ctlSQL[i]==NULL) continue;
|
|
int idx=outputPane->GetPageIndex(ctlSQL[i]);
|
|
|
|
if (ctlSBox[i]==sqlQuery) {
|
|
outputPane->SetPageBitmap(idx,CreateBitmap(wxNullColour));
|
|
pos=i;
|
|
} else
|
|
{
|
|
outputPane->SetPageBitmap(idx,wxNullBitmap);
|
|
}
|
|
}
|
|
}
|
|
|
|
sqlQuery->SetFocus();
|
|
if (sqlQueryBook->GetPageCount() > 1) fileMarkerActive(true, sqlQueryBook->GetPageText(sqlQueryBook->GetSelection()));
|
|
//wxMessageBox(wxT("OnSqlBookPageChanged "));
|
|
|
|
CheckModificationFile();
|
|
|
|
updateMenu(false);
|
|
wxTheApp->Yield(true);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// This should help us find bugs (such as using sqlQuery after closing all tabs) much faster.
|
|
sqlQuery = NULL;
|
|
}
|
|
}
|
|
|
|
void frmQuery::OnSqlBookPageChanging(wxAuiNotebookEvent& event)
|
|
{
|
|
// Veto event while page change is prohibited.
|
|
if (!SqlBookCanChangePage())
|
|
{
|
|
event.Veto();
|
|
wxMessageBox(_("Cannot change to selected SQL tab now. Try again a bit later."));
|
|
}
|
|
if (sqlQueryBook->GetPageCount() > 1)
|
|
{
|
|
int curpage = sqlQueryBook->GetSelection();
|
|
if (curpage!=wxNOT_FOUND) {
|
|
sqlQuery = wxDynamicCast(sqlQueryBook->GetPage(curpage), ctlSQLBox);
|
|
if (sqlQuery != NULL)
|
|
{
|
|
//wxString activePage = sqlNotebook->GetPageText(curpage);
|
|
wxString activePage = sqlQuery->GetTitle(false);
|
|
fileMarkerActive(false, activePage);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
void frmQuery::OnSqlBookAddPage(wxCommandEvent &event)
|
|
{
|
|
if (SqlBookCanChangePage()) {
|
|
wxString t = wxEmptyString;
|
|
SqlBookAddPage(t);
|
|
}
|
|
else
|
|
wxMessageBox(_("Cannot add a new SQL tab now. Try again a bit later."));
|
|
}
|
|
void frmQuery::OnSqlBookPageClosed(wxAuiNotebookEvent &event)
|
|
{
|
|
//OnSqlBookPageChanged(event);
|
|
|
|
//wxSleep(5);
|
|
// wxMessageBox(wxT("OnSqlBookPageClosed end"));
|
|
}
|
|
|
|
void frmQuery::OnNotebookOutpaneTabRDown(wxAuiNotebookEvent &event) {
|
|
//ctlSQL
|
|
size_t curpage = outputPane->GetSelection();
|
|
if ( event.GetSelection()!=curpage) return;
|
|
wxBitmap b=outputPane->GetPageBitmap(curpage);
|
|
if (b.IsOk()) {
|
|
if (sqlQuery!=NULL) {
|
|
wxString sql=sqlResult->sqlquerytext;
|
|
if (sql.StartsWith("EXPLAIN")) sql=sql.AfterFirst(')');
|
|
if (sql.StartsWith("\nBEGIN;\nEXPLAIN")) {
|
|
sql=sql.AfterFirst(')');
|
|
//"\n;\nROLLBACK;"
|
|
sql=sql.Mid(0,sql.Length()-12);
|
|
}
|
|
if (!sqlQuery->Find(sql,false,false,false,true,false,true)) {
|
|
wxString t=sqlQuery->GetText();
|
|
if (t.Find(sql)>-1) {
|
|
SetStatusText("Found",1);
|
|
}
|
|
}
|
|
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (wxDynamicCast(outputPane->GetPage(curpage), ctlSQLResult))
|
|
{
|
|
ctlSQLResult* c = wxDynamicCast(outputPane->GetPage(curpage), ctlSQLResult);
|
|
int len = MAX_RESULT_COUNT;
|
|
for (int i = 0; i < len; i++)
|
|
if (ctlSQL[i] != NULL && c == ctlSQL[i])
|
|
{
|
|
ctlSQLResult *sqlRes = ctlSQL[i];
|
|
ctlSQLBox *box= ctlSBox[i];
|
|
int querypage= sqlQueryBook->GetPageIndex(box);
|
|
if (querypage >= 0) {
|
|
sqlQueryBook->SetSelection(querypage);
|
|
}
|
|
|
|
break;
|
|
}
|
|
}
|
|
|
|
}
|
|
}
|
|
void frmQuery::OnSqlBookTabRDown (wxAuiNotebookEvent &event) {
|
|
size_t curpage = sqlQueryBook->GetSelection();
|
|
ctlSQLBox *sqlQuery = wxDynamicCast(sqlQueryBook->GetPage(curpage), ctlSQLBox);
|
|
wxString pref=conn->GetDbname()+wxT(".nametab");
|
|
|
|
wxTextEntryDialog dialog(this,
|
|
wxT("Please enter name string with prefix dbname\n")
|
|
,
|
|
wxT("Name autosave tab window."),
|
|
pref,
|
|
wxOK | wxCANCEL); //setName( dlg.GetValue().wc_str() );
|
|
if (dialog.ShowModal() == wxID_OK) {
|
|
wxString tempDir = dataDir+wxFileName::GetPathSeparator()+"recovery"+wxFileName::GetPathSeparator();
|
|
wxString filename=sqlQuery->GetTitle(false);
|
|
wxString tf=tempDir+filename+".a";
|
|
if (wxFileName::FileExists(tf)) wxRemoveFile(tf);
|
|
tf=tempDir + "_active."+filename + ".a";
|
|
if (wxFileName::FileExists(tf)) wxRemoveFile(tf);
|
|
wxString nt=dialog.GetValue();
|
|
sqlQuery->SetTitle(nt);
|
|
SqlBookUpdatePageTitle();
|
|
fileMarkerActive(true, nt);
|
|
//sqlQueryBook->GetPage(curpage)->
|
|
SaveTempFile();
|
|
}
|
|
|
|
}
|
|
void frmQuery::OnSqlBookPageClose(wxAuiNotebookEvent &event)
|
|
{
|
|
// Don't allow removal of the last SQL box via user generated event
|
|
size_t pagecnt = sqlQueryBook->GetPageCount();
|
|
if (pagecnt == 1)
|
|
{
|
|
event.Veto();
|
|
wxMessageBox(_("Cannot remove the last SQL tab"));
|
|
return;
|
|
}
|
|
|
|
// Prevent removing the page that is currently being executed
|
|
if (sqlQueryExec != NULL && sqlQueryExec == sqlQuery)
|
|
{
|
|
event.Veto();
|
|
wxMessageBox(_("The query on this SQL tab is still running.\nWait for it to finish or cancel it before closing the tab."));
|
|
return;
|
|
}
|
|
|
|
if (CheckChanged(true))
|
|
{
|
|
event.Veto();
|
|
return;
|
|
}
|
|
|
|
// If removing the tab for which results are displayed, reset the output pane's caption
|
|
if (sqlQuery == sqlQueryExecLast)
|
|
{
|
|
sqlQueryExecLast = NULL;
|
|
SetOutputPaneCaption(true);
|
|
}
|
|
|
|
SqlBookDisconnectPage();
|
|
//drop temp file
|
|
wxString tempDir = dataDir+wxFileName::GetPathSeparator()+"recovery"+wxFileName::GetPathSeparator();
|
|
wxString filename=sqlQuery->GetTitle(false)+wxT(".a");
|
|
if (wxFileName::FileExists(tempDir+filename)) wxRemoveFile(tempDir+filename);
|
|
fileMarkerActive(false, sqlQuery->GetTitle(false));
|
|
}
|
|
|
|
bool frmQuery::SqlBookCanChangePage()
|
|
{
|
|
return !(m_loadingfile || ms_pgScriptRunning);
|
|
}
|
|
|
|
void frmQuery::SqlBookAddPage(wxString& title)
|
|
{
|
|
ctlSQLBox *box;
|
|
wxString caption;
|
|
bool bVal;
|
|
|
|
// All SQL boxes use the same wxID, CTL_SQLQUERY.
|
|
// This should probably be changed, but it works for now and has minimal impact on existing code.
|
|
box = new ctlSQLBox(sqlQueryBook, CTL_SQLQUERY, wxDefaultPosition, wxDefaultSize, wxTE_MULTILINE | wxSIMPLE_BORDER | wxTE_RICH2);
|
|
box->SetDatabase(conn);
|
|
box->SetMarginWidth(1, 16);
|
|
box->SetDropTarget(new DnDFile(this));
|
|
box->SetChanged(false);
|
|
box->SetOrigin(ORIGIN_MANUAL);
|
|
box->SetQueryBook(sqlQueryBook);
|
|
bVal = editMenu->IsChecked(MNU_AUTOINDENT);
|
|
box->SetAutoIndent(bVal);
|
|
|
|
bVal = viewMenu->IsChecked(MNU_WORDWRAP);
|
|
box->SetWrapMode(bVal ? wxSTC_WRAP_WORD : wxSTC_WRAP_NONE);
|
|
|
|
bVal = viewMenu->IsChecked(MNU_SHOWINDENTGUIDES);
|
|
box->SetIndentationGuides(bVal);
|
|
|
|
bVal = viewMenu->IsChecked(MNU_SHOWWHITESPACE);
|
|
box->SetViewWhiteSpace(bVal ? wxSTC_WS_VISIBLEALWAYS : wxSTC_WS_INVISIBLE);
|
|
|
|
bVal = viewMenu->IsChecked(MNU_SHOWLINEENDS);
|
|
box->SetViewEOL(bVal ? 1 : 0);
|
|
|
|
box->Connect(wxID_ANY, wxEVT_SET_FOCUS, wxFocusEventHandler(frmQuery::OnFocus));
|
|
box->Connect(wxID_ANY, wxEVT_KILL_FOCUS, wxFocusEventHandler(frmQuery::OnFocus));
|
|
|
|
if (title.BeforeFirst(' ')=="Query") {
|
|
wxString np = title.AfterFirst(' ');
|
|
long nl = 0;
|
|
if (np.ToLong(&nl)) {
|
|
if (sqlQueryCounter < nl) sqlQueryCounter = nl;
|
|
}
|
|
|
|
}
|
|
if (title.IsEmpty()) sqlQueryCounter ++;
|
|
int ll = sqlQueryCounter;
|
|
caption = wxString::Format(_("Query %d"), ll);
|
|
|
|
bool select = title.IsEmpty();
|
|
if (!select) caption = title;
|
|
select = true;
|
|
box->SetTitle(caption);
|
|
sqlQueryBook->AddPage(box, caption, select);
|
|
|
|
// Probably not needed, as the line above should trigger the PageChange event
|
|
sqlQuery = box;
|
|
sqlQuery->SetAutoReplaceList(autoreplace);
|
|
sqlQuery->SetDefFunction(name_func, def_func);
|
|
}
|
|
|
|
void frmQuery::SqlBookDisconnectPage(ctlSQLBox *box)
|
|
{
|
|
if (box == NULL)
|
|
box = sqlQuery;
|
|
|
|
if (box != NULL)
|
|
{
|
|
box->Disconnect(wxID_ANY, wxEVT_SET_FOCUS, wxFocusEventHandler(frmQuery::OnFocus));
|
|
box->Disconnect(wxID_ANY, wxEVT_KILL_FOCUS, wxFocusEventHandler(frmQuery::OnFocus));
|
|
for (int k=0;k<MAX_RESULT_COUNT;k++) if (ctlSBox[k]==box) ctlSBox[k]=NULL;
|
|
|
|
}
|
|
}
|
|
|
|
bool frmQuery::SqlBookRemovePage()
|
|
{
|
|
size_t pageidx;
|
|
if (sqlQueryBook->GetPageCount() > 0)
|
|
{
|
|
// If removing the tab for which results are displayed, reset the output pane's caption
|
|
if (sqlQuery == sqlQueryExecLast)
|
|
{
|
|
sqlQueryExecLast = NULL;
|
|
SetOutputPaneCaption(true);
|
|
}
|
|
|
|
SqlBookDisconnectPage();
|
|
pageidx = sqlQueryBook->GetSelection();
|
|
wxString tempDir = dataDir+wxFileName::GetPathSeparator()+"recovery"+wxFileName::GetPathSeparator();
|
|
ctlSQLBox *box;
|
|
box = wxDynamicCast(sqlQueryBook->GetPage(pageidx), ctlSQLBox);
|
|
wxString filename=box->GetTitle(false);
|
|
|
|
wxRemoveFile(tempDir+filename+wxT(".a"));
|
|
return sqlQueryBook->DeletePage(pageidx);
|
|
}
|
|
return false;
|
|
}
|
|
|
|
void frmQuery::SqlBookSetAutoIndent(bool b)
|
|
{
|
|
size_t i, cnt;
|
|
ctlSQLBox *box;
|
|
|
|
for (i = 0, cnt = sqlQueryBook->GetPageCount(); i < cnt; ++i)
|
|
{
|
|
box = wxDynamicCast(sqlQueryBook->GetPage(i), ctlSQLBox);
|
|
if (box != NULL)
|
|
box->SetAutoIndent(b);
|
|
}
|
|
}
|
|
|
|
void frmQuery::SqlBookSetWrapMode(bool b)
|
|
{
|
|
size_t i, cnt;
|
|
ctlSQLBox *box;
|
|
|
|
for (i = 0, cnt = sqlQueryBook->GetPageCount(); i < cnt; ++i)
|
|
{
|
|
box = wxDynamicCast(sqlQueryBook->GetPage(i), ctlSQLBox);
|
|
if (box != NULL)
|
|
box->SetWrapMode(b ? wxSTC_WRAP_WORD : wxSTC_WRAP_NONE);
|
|
}
|
|
}
|
|
|
|
void frmQuery::SqlBookSetIndentGuides(bool b)
|
|
{
|
|
size_t i, cnt;
|
|
ctlSQLBox *box;
|
|
|
|
for (i = 0, cnt = sqlQueryBook->GetPageCount(); i < cnt; ++i)
|
|
{
|
|
box = wxDynamicCast(sqlQueryBook->GetPage(i), ctlSQLBox);
|
|
if (box != NULL)
|
|
box->SetIndentationGuides(b);
|
|
}
|
|
}
|
|
|
|
void frmQuery::SqlBookSetViewWhiteSpace(bool b)
|
|
{
|
|
size_t i, cnt;
|
|
ctlSQLBox *box;
|
|
|
|
for (i = 0, cnt = sqlQueryBook->GetPageCount(); i < cnt; ++i)
|
|
{
|
|
box = wxDynamicCast(sqlQueryBook->GetPage(i), ctlSQLBox);
|
|
if (box != NULL)
|
|
box->SetViewWhiteSpace(b ? wxSTC_WS_VISIBLEALWAYS : wxSTC_WS_INVISIBLE);
|
|
}
|
|
}
|
|
|
|
void frmQuery::SqlBookSetViewEOL(bool b)
|
|
{
|
|
size_t i, cnt;
|
|
ctlSQLBox *box;
|
|
|
|
for (i = 0, cnt = sqlQueryBook->GetPageCount(); i < cnt; ++i)
|
|
{
|
|
box = wxDynamicCast(sqlQueryBook->GetPage(i), ctlSQLBox);
|
|
if (box != NULL)
|
|
box->SetViewEOL(b ? 1 : 0);
|
|
}
|
|
}
|
|
|
|
void frmQuery::SqlBookSetViewLineNumbers(bool b)
|
|
{
|
|
size_t i, cnt;
|
|
ctlSQLBox *box;
|
|
|
|
for (i = 0, cnt = sqlQueryBook->GetPageCount(); i < cnt; ++i)
|
|
{
|
|
box = wxDynamicCast(sqlQueryBook->GetPage(i), ctlSQLBox);
|
|
if (box != NULL)
|
|
box->UpdateLineNumber();
|
|
}
|
|
}
|
|
|
|
void frmQuery::SqlBookSetDatabase(pgConn *con)
|
|
{
|
|
size_t i, cnt;
|
|
ctlSQLBox *box;
|
|
|
|
for (i = 0, cnt = sqlQueryBook->GetPageCount(); i < cnt; ++i)
|
|
{
|
|
box = wxDynamicCast(sqlQueryBook->GetPage(i), ctlSQLBox);
|
|
if (box != NULL)
|
|
box->SetDatabase(con);
|
|
}
|
|
}
|
|
|
|
void frmQuery::SqlBookUpdatePageTitle()
|
|
{
|
|
size_t index;
|
|
wxString title;
|
|
|
|
if (sqlQueryBook->GetPageCount() > 0 && sqlQuery != NULL)
|
|
{
|
|
index = sqlQueryBook->GetPageIndex(sqlQuery);
|
|
if (index == wxNOT_FOUND)
|
|
return;
|
|
|
|
title = sqlQuery->GetTitle();
|
|
if (sqlQueryBook->GetPageText(index) != title)
|
|
sqlQueryBook->SetPageText(index, title);
|
|
}
|
|
}
|
|
|
|
// Returns true if any SQL tab attempts to veto the closing, false otherwise.
|
|
bool frmQuery::SqlBookClose(bool canVeto)
|
|
{
|
|
size_t i = 0;
|
|
size_t cnt = sqlQueryBook->GetPageCount();
|
|
ctlSQLBox *box;
|
|
|
|
// See if we have any unsaved changes and prompt to save them
|
|
for (i = 0; i < cnt; ++i)
|
|
{
|
|
box = wxDynamicCast(sqlQueryBook->GetPage(i), ctlSQLBox);
|
|
if (box != NULL && box->IsChanged())
|
|
{
|
|
sqlQueryBook->SetSelection(i);
|
|
if (CheckChanged(canVeto))
|
|
return true;
|
|
}
|
|
}
|
|
|
|
// If we got here, the window will be closed
|
|
for (i = 0; i < cnt; ++i)
|
|
{
|
|
box = wxDynamicCast(sqlQueryBook->GetPage(i), ctlSQLBox);
|
|
if (box != NULL)
|
|
SqlBookDisconnectPage(box);
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
|
|
///////////////////////////////////////////////////////
|
|
|
|
wxWindow *queryToolBaseFactory::StartDialogSql(frmMain *form, pgObject *obj, const wxString &sql)
|
|
{
|
|
pgDatabase *db = obj->GetDatabase();
|
|
wxString usr=wxEmptyString;
|
|
wxGetEnv(wxT("USERNAME"),&usr);
|
|
wxString applicationname = appearanceFactory->GetLongAppName() + wxT(" - query ")+usr;
|
|
pgConn *conn = db->CreateConn(applicationname);
|
|
if (conn)
|
|
{
|
|
frmQuery *fq = new frmQuery(form, obj->GetDisplayName(), conn, sql);
|
|
fq->Go();
|
|
return fq;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
|
|
bool queryToolBaseFactory::CheckEnable(pgObject *obj)
|
|
{
|
|
return obj && obj->GetDatabase() && obj->GetDatabase()->GetConnected();
|
|
}
|
|
|
|
|
|
bool queryToolDataFactory::CheckEnable(pgObject *obj)
|
|
{
|
|
return queryToolBaseFactory::CheckEnable(obj) && !obj->IsCollection() &&
|
|
(obj->IsCreatedBy(tableFactory) || obj->IsCreatedBy(pg_partitionFactory) || obj->IsCreatedBy(viewFactory));
|
|
}
|
|
|
|
|
|
queryToolFactory::queryToolFactory(menuFactoryList *list, wxMenu *mnu, ctlMenuToolbar *toolbar) : queryToolBaseFactory(list)
|
|
{
|
|
mnu->Append(id, _("&Query tool\tCtrl-E"), _("Execute arbitrary SQL queries."));
|
|
toolbar->AddTool(id, wxEmptyString, GetBundleSVG(sql_32_png_bmp, "sql_32.svg", wxSize(32, 32)), _("Execute arbitrary SQL queries."), wxITEM_NORMAL);
|
|
//toolbar->AddTool(id, wxEmptyString, GetBundleSVG(sql_32_png_bmp, "plugins.svg", wxSize(32, 32)), _("Execute arbitrary SQL queries."), wxITEM_NORMAL);
|
|
}
|
|
|
|
|
|
wxWindow *queryToolFactory::StartDialog(frmMain *form, pgObject *obj)
|
|
{
|
|
wxString qry;
|
|
if (settings->GetStickySql())
|
|
qry = obj->GetSql(form->GetBrowser());
|
|
return StartDialogSql(form, obj, qry);
|
|
}
|
|
|
|
|
|
queryToolSqlFactory::queryToolSqlFactory(menuFactoryList *list, wxMenu *mnu, ctlMenuToolbar *toolbar) : queryToolBaseFactory(list)
|
|
{
|
|
mnu->Append(id, _("CREATE Script"), _("Start Query tool with CREATE script."));
|
|
if (toolbar)
|
|
toolbar->AddTool(id, wxEmptyString, GetBundleSVG(sql_32_png_bmp, "sql_32.svg", wxSize(32, 32)), _("Start query tool with CREATE script."), wxITEM_NORMAL);
|
|
}
|
|
|
|
|
|
wxWindow *queryToolSqlFactory::StartDialog(frmMain *form, pgObject *obj)
|
|
{
|
|
return StartDialogSql(form, obj, obj->GetSql(form->GetBrowser()));
|
|
}
|
|
|
|
|
|
bool queryToolSqlFactory::CheckEnable(pgObject *obj)
|
|
{
|
|
return queryToolBaseFactory::CheckEnable(obj) && obj->CanCreate() && !obj->IsCollection();
|
|
}
|
|
|
|
|
|
queryToolSelectFactory::queryToolSelectFactory(menuFactoryList *list, wxMenu *mnu, ctlMenuToolbar *toolbar) : queryToolDataFactory(list)
|
|
{
|
|
mnu->Append(id, _("SELECT Script"), _("Start query tool with SELECT script."));
|
|
}
|
|
|
|
bool queryToolSelectFactory::CheckEnable(pgObject *obj)
|
|
{
|
|
return queryToolBaseFactory::CheckEnable(obj) && !obj->IsCollection() &&
|
|
(obj->IsCreatedBy(tableFactory) || obj->IsCreatedBy(foreignTableFactory) || obj->IsCreatedBy(viewFactory) || obj->IsCreatedBy(functionFactory) || obj->IsCreatedBy(pg_partitionFactory));
|
|
}
|
|
|
|
wxWindow *queryToolSelectFactory::StartDialog(frmMain *form, pgObject *obj)
|
|
{
|
|
if (obj->IsCreatedBy(tableFactory)||(obj->IsCreatedBy(pg_partitionFactory)))
|
|
{
|
|
pgTable *table = (pgTable *)obj;
|
|
return StartDialogSql(form, obj, table->GetSelectSql(form->GetBrowser()));
|
|
}
|
|
else if (obj->IsCreatedBy(viewFactory))
|
|
{
|
|
pgView *view = (pgView *)obj;
|
|
return StartDialogSql(form, obj, view->GetSelectSql(form->GetBrowser()));
|
|
}
|
|
else if (obj->IsCreatedBy(extTableFactory))
|
|
{
|
|
gpExtTable *exttable = (gpExtTable *)obj;
|
|
return StartDialogSql(form, obj, exttable->GetSelectSql(form->GetBrowser()));
|
|
}
|
|
else if (obj->IsCreatedBy(functionFactory))
|
|
{
|
|
pgFunction *function = (pgFunction *)obj;
|
|
return StartDialogSql(form, obj, function->GetSelectSql(form->GetBrowser()));
|
|
}
|
|
else if (obj->IsCreatedBy(foreignTableFactory))
|
|
{
|
|
pgForeignTable *foreigntable = (pgForeignTable *)obj;
|
|
return StartDialogSql(form, obj, foreigntable->GetSelectSql(form->GetBrowser()));
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
queryToolExecFactory::queryToolExecFactory(menuFactoryList *list, wxMenu *mnu, ctlMenuToolbar *toolbar) : queryToolDataFactory(list)
|
|
{
|
|
mnu->Append(id, _("EXEC Script"), _("Start query tool with EXEC script."));
|
|
}
|
|
|
|
bool queryToolExecFactory::CheckEnable(pgObject *obj)
|
|
{
|
|
return queryToolBaseFactory::CheckEnable(obj) && !obj->IsCollection() && obj->IsCreatedBy(procedureFactory);
|
|
}
|
|
|
|
wxWindow *queryToolExecFactory::StartDialog(frmMain *form, pgObject *obj)
|
|
{
|
|
if (obj->IsCreatedBy(procedureFactory))
|
|
{
|
|
pgProcedure *procedure = (pgProcedure *)obj;
|
|
return StartDialogSql(form, obj, procedure->GetExecSql(form->GetBrowser()));
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
queryToolDeleteFactory::queryToolDeleteFactory(menuFactoryList *list, wxMenu *mnu, ctlMenuToolbar *toolbar) : queryToolDataFactory(list)
|
|
{
|
|
mnu->Append(id, _("DELETE Script"), _("Start query tool with DELETE script."));
|
|
}
|
|
|
|
|
|
bool queryToolDeleteFactory::CheckEnable(pgObject *obj)
|
|
{
|
|
if (!queryToolDataFactory::CheckEnable(obj))
|
|
return false;
|
|
if (obj->IsCreatedBy(tableFactory)||obj->IsCreatedBy(pg_partitionFactory))
|
|
return true;
|
|
return false;
|
|
}
|
|
|
|
|
|
wxWindow *queryToolDeleteFactory::StartDialog(frmMain *form, pgObject *obj)
|
|
{
|
|
if (obj->IsCreatedBy(tableFactory))
|
|
{
|
|
pgTable *table = (pgTable *)obj;
|
|
return StartDialogSql(form, obj, table->GetDeleteSql(form->GetBrowser()));
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
|
|
queryToolCreateCascadeFactory::queryToolCreateCascadeFactory(menuFactoryList *list, wxMenu *mnu, ctlMenuToolbar *toolbar) : queryToolDataFactory(list)
|
|
{
|
|
mnu->Append(id, _("Script Recreate Cascade"), _("Start query tool with recreate cascade script."));
|
|
}
|
|
|
|
//wxArrayString queryToolCreateCascadeFactory::GetArrayList(wxString *strobj)
|
|
//{
|
|
// wxString *databasePath=new wxString(strobj);
|
|
// pgSet *set;
|
|
// set = connection->ExecuteSet(
|
|
// wxT("SELECT relname FROM pg_class, pg_index WHERE pg_class.oid=indexrelid AND indrelid=") + table->GetOidStr());
|
|
// if (set)
|
|
// {
|
|
// while (!set->Eof())
|
|
// {
|
|
// cbIndex->Append(set->GetVal(0));
|
|
// set->MoveNext();
|
|
// }
|
|
// delete set;
|
|
// }
|
|
//
|
|
// wxStringTokenizer tkz(databasePath, wxT("/"));
|
|
// while(tkz.HasMoreTokens())
|
|
// {
|
|
// wxString token = tkz.GetNextToken();
|
|
// if(token == _("Databases"))
|
|
// break;
|
|
// //ItemPath += token + wxT("/");
|
|
// }
|
|
//
|
|
// return 0;
|
|
//}
|
|
wxWindow *queryToolCreateCascadeFactory::StartDialog(frmMain *form, pgObject *obj)
|
|
{
|
|
|
|
if (obj->IsCreatedBy(tableFactory)||obj->IsCreatedBy(pg_partitionFactory))
|
|
{
|
|
pgTable *table = (pgTable *)obj;
|
|
return StartDialogSql(form, obj, table->GetSqlReCreate(form,obj));
|
|
}
|
|
else if (obj->IsCreatedBy(viewFactory))
|
|
{
|
|
pgView *view = (pgView *)obj;
|
|
return StartDialogSql(form, obj, view->GetSqlReCreate(form,obj));
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
bool queryToolCreateCascadeFactory::CheckEnable(pgObject *obj)
|
|
{
|
|
if (!queryToolDataFactory::CheckEnable(obj))
|
|
return false;
|
|
if (obj->IsCreatedBy(tableFactory)||obj->IsCreatedBy(pg_partitionFactory))
|
|
return true;
|
|
pgView *view = (pgView *)obj;
|
|
|
|
return true;
|
|
}
|
|
|
|
queryToolUpdateFactory::queryToolUpdateFactory(menuFactoryList *list, wxMenu *mnu, ctlMenuToolbar *toolbar) : queryToolDataFactory(list)
|
|
{
|
|
mnu->Append(id, _("UPDATE Script"), _("Start query tool with UPDATE script."));
|
|
}
|
|
|
|
|
|
wxWindow *queryToolUpdateFactory::StartDialog(frmMain *form, pgObject *obj)
|
|
{
|
|
if (obj->IsCreatedBy(tableFactory)||obj->IsCreatedBy(pg_partitionFactory))
|
|
{
|
|
pgTable *table = (pgTable *)obj;
|
|
return StartDialogSql(form, obj, table->GetUpdateSql(form->GetBrowser()));
|
|
}
|
|
else if (obj->IsCreatedBy(viewFactory))
|
|
{
|
|
pgView *view = (pgView *)obj;
|
|
return StartDialogSql(form, obj, view->GetUpdateSql(form->GetBrowser()));
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
bool queryToolUpdateFactory::CheckEnable(pgObject *obj)
|
|
{
|
|
if (!queryToolDataFactory::CheckEnable(obj))
|
|
return false;
|
|
if (obj->IsCreatedBy(tableFactory)||obj->IsCreatedBy(pg_partitionFactory))
|
|
return true;
|
|
pgView *view = (pgView *)obj;
|
|
|
|
return view->HasUpdateRule();
|
|
}
|
|
|
|
|
|
queryToolInsertFactory::queryToolInsertFactory(menuFactoryList *list, wxMenu *mnu, ctlMenuToolbar *toolbar) : queryToolDataFactory(list)
|
|
{
|
|
mnu->Append(id, _("INSERT Script"), _("Start query tool with INSERT script."));
|
|
}
|
|
|
|
|
|
wxWindow *queryToolInsertFactory::StartDialog(frmMain *form, pgObject *obj)
|
|
{
|
|
if (obj->IsCreatedBy(tableFactory)||obj->IsCreatedBy(pg_partitionFactory))
|
|
{
|
|
pgTable *table = (pgTable *)obj;
|
|
return StartDialogSql(form, obj, table->GetInsertSql(form->GetBrowser()));
|
|
}
|
|
else if (obj->IsCreatedBy(viewFactory))
|
|
{
|
|
pgView *view = (pgView *)obj;
|
|
return StartDialogSql(form, obj, view->GetInsertSql(form->GetBrowser()));
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
bool queryToolInsertFactory::CheckEnable(pgObject *obj)
|
|
{
|
|
if (!queryToolDataFactory::CheckEnable(obj))
|
|
return false;
|
|
if (obj->IsCreatedBy(tableFactory)||obj->IsCreatedBy(pg_partitionFactory))
|
|
return true;
|
|
pgView *view = (pgView *)obj;
|
|
|
|
return view->HasInsertRule();
|
|
}
|
|
|
|
void frmQuery::SaveExplainAsImage(wxCommandEvent &ev)
|
|
{
|
|
wxFileDialog *dlg = new wxFileDialog(this, _("Save Explain As image file"), lastDir, lastFilename,
|
|
wxT("Bitmap files (*.bmp)|*.bmp|JPEG files (*.jpeg)|*.jpeg|PNG files (*.png)|*.png"), wxFD_SAVE | wxFD_OVERWRITE_PROMPT);
|
|
if (dlg->ShowModal() == wxID_OK)
|
|
{
|
|
lastFilename = dlg->GetFilename();
|
|
lastDir = dlg->GetDirectory();
|
|
lastPath = dlg->GetPath();
|
|
int index = dlg->GetFilterIndex();
|
|
|
|
wxString strType;
|
|
wxBitmapType imgType;
|
|
switch (index)
|
|
{
|
|
// bmp
|
|
case 0:
|
|
strType = wxT(".bmp");
|
|
imgType = wxBITMAP_TYPE_BMP;
|
|
break;
|
|
// jpeg
|
|
case 1:
|
|
strType = wxT(".jpeg");
|
|
imgType = wxBITMAP_TYPE_JPEG;
|
|
break;
|
|
// default (png)
|
|
default:
|
|
// png
|
|
case 2:
|
|
strType = wxT(".png");
|
|
imgType = wxBITMAP_TYPE_PNG;
|
|
break;
|
|
}
|
|
|
|
if (!lastPath.Contains(wxT(".")))
|
|
lastPath += strType;
|
|
|
|
if (ev.GetId() == MNU_SAVEAS_IMAGE_GQB)
|
|
controller->getView()->SaveAsImage(lastPath, imgType);
|
|
else if (ev.GetId() == MNU_SAVEAS_IMAGE_EXPLAIN)
|
|
explainCanvas->SaveAsImage(lastPath, imgType);
|
|
}
|
|
}
|
|
|
|
///////////////////////////////////////////////////////
|
|
|
|
pgScriptTimer::pgScriptTimer(frmQuery *parent) :
|
|
m_parent(parent)
|
|
{
|
|
|
|
}
|
|
|
|
void pgScriptTimer::Notify()
|
|
{
|
|
// Write script output
|
|
m_parent->writeScriptOutput();
|
|
}
|
|
|