File: dlgEditGridOptions.cpp

package info (click to toggle)
pgadmin3 1.20.0~beta2-1
  • links: PTS, VCS
  • area: main
  • in suites: jessie, jessie-kfreebsd
  • size: 73,704 kB
  • ctags: 18,591
  • sloc: cpp: 193,786; ansic: 18,736; sh: 5,154; pascal: 1,120; yacc: 927; makefile: 516; lex: 421; xml: 126; perl: 40
file content (391 lines) | stat: -rw-r--r-- 10,692 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
//////////////////////////////////////////////////////////////////////////
//
// pgAdmin III - PostgreSQL Tools
//
// Copyright (C) 2002 - 2014, The pgAdmin Development Team
// This software is released under the PostgreSQL Licence
//
// dlgEditGridOptions.cpp - Edit Grid Box Options
//
//////////////////////////////////////////////////////////////////////////

// wxWindows headers
#include <wx/wx.h>
#include <wx/grid.h>
#include <wx/settings.h>

#include <wx/generic/gridctrl.h>

// App headers
#include "pgAdmin3.h"
#include "utils/pgDefs.h"
#include "frm/frmMain.h"

#include "frm/frmEditGrid.h"
#include "dlg/dlgEditGridOptions.h"
#include "schema/pgTable.h"
#include "schema/pgView.h"

// Icons
#include "images/sortfilter.pngc"

#define nbOptions                   CTRL_NOTEBOOK("nbOptions")
#define btnAsc                      CTRL_BUTTON("btnAsc")
#define btnDesc                     CTRL_BUTTON("btnDesc")
#define btnRemove                   CTRL_BUTTON("wxID_REMOVE")
#define btnValidate                 CTRL_BUTTON("btnValidate")
#define cboColumns                  CTRL_COMBOBOX("cboColumns")
#define lstSortCols                 CTRL_LISTVIEW("lstSortCols")
#define pnlSort                     CTRL_PANEL("pnlSort")
#define pnlFilter                   CTRL_PANEL("pnlFilter")
#define filter                      CTRL_SQLBOX("sqlFilter")

BEGIN_EVENT_TABLE(dlgEditGridOptions, pgDialog)
	EVT_CLOSE(                                      dlgEditGridOptions::OnClose)
	EVT_BUTTON               (wxID_OK,              dlgEditGridOptions::OnOK)
	EVT_BUTTON               (wxID_CANCEL,          dlgEditGridOptions::OnCancel)
	EVT_BUTTON               (wxID_REMOVE,          dlgEditGridOptions::OnRemove)
	EVT_BUTTON               (XRCID("btnAsc"),      dlgEditGridOptions::OnAsc)
	EVT_BUTTON               (XRCID("btnDesc"),     dlgEditGridOptions::OnDesc)
	EVT_BUTTON               (XRCID("btnValidate"), dlgEditGridOptions::OnValidate)
	EVT_COMBOBOX             (XRCID("cboColumns"),  dlgEditGridOptions::OnCboColumnsChange)
	EVT_LIST_ITEM_SELECTED   (XRCID("lstSortCols"), dlgEditGridOptions::OnLstSortColsChange)
	EVT_LIST_ITEM_DESELECTED (XRCID("lstSortCols"), dlgEditGridOptions::OnLstSortColsChange)
	EVT_STC_MODIFIED		 (XRCID("sqlFilter"),   dlgEditGridOptions::OnFilterChange)
#ifdef __WXMAC__
	EVT_SIZE(                                       dlgEditGridOptions::OnChangeSize)
#endif
END_EVENT_TABLE()

dlgEditGridOptions::dlgEditGridOptions(frmEditGrid *win, pgConn *conn, const wxString &rel, ctlSQLEditGrid *grid)
{
	editGrid = grid;
	connection = conn;
	relation = rel;
	parent = win;
	SetFont(settings->GetSystemFont());
	LoadResource(win, wxT("dlgEditGridOptions"));
	conv = conn->GetConv();

	// Icon
	SetIcon(*sortfilter_png_ico);
	RestorePosition();

	int cols = grid->GetNumberCols();
	long x;

	for (x = 0; x < cols; x++)
		cboColumns->Append(grid->GetColLabelValue(x).BeforeFirst('\n'));

	// Setup the buttons
	wxCommandEvent nullEvent;
	OnCboColumnsChange(nullEvent);
	wxListEvent nullLstEvent;
	OnLstSortColsChange(nullLstEvent);

	// Setup the list box
	int leftSize = 140, rightSize;
	leftSize = ConvertDialogToPixels(wxPoint(leftSize, 0)).x;
	rightSize = lstSortCols->GetClientSize().GetWidth() - leftSize;
	// This check is to work around a bug in wxGTK that doesn't set
	// appropriately the GetClientSize().
	// Without this workaround, we have an invisible second column.
	if (rightSize < leftSize)
		rightSize = leftSize + 1;
	lstSortCols->InsertColumn(0, _("Column name"), wxLIST_FORMAT_LEFT, leftSize);
	lstSortCols->InsertColumn(1, _("Sort order"), wxLIST_FORMAT_LEFT, rightSize);

	// Setup the filter SQL box. This is an XRC 'unknown' control so must
	// be manually created and attache to the XRC global resource.
	filter->SetText(parent->GetFilter());

	// Get the current sort columns, and populate the listbox.
	// The current columns will be parsed char by char to allow us
	// to cope with quoted column names with commas in them (let's hope
	// noone ever does that, but sod's law etc....)
	bool inColumn = true, inQuote = false;
	wxString sortCols = parent->GetSortCols();
	wxString col, dir;
	size_t pos, len = sortCols.Length();
	int itm = 0;

	for (pos = 0; pos < len; pos++)
	{
		if (inColumn)
		{
			if (sortCols.GetChar(pos) == '"') inQuote = !inQuote;
			if (!inQuote && (sortCols.GetChar(pos) == ' ' || sortCols.GetChar(pos) == ','))
				inColumn = false;
			else if (sortCols.GetChar(pos) != '"') col += sortCols.GetChar(pos);
		}
		else
		{
			if (sortCols.GetChar(pos - 1) == ',')
			{
				inColumn = true;
				lstSortCols->InsertItem(itm, col);
				if (dir.GetChar(0) == 'D')
				{
					lstSortCols->SetItem(itm, 1, _("Descending"));
					lstSortCols->SetItemData(itm, 0);
				}
				else
				{
					lstSortCols->SetItem(itm, 1, _("Ascending"));
					lstSortCols->SetItemData(itm, 1);
				}
				col = wxT("");
				dir = wxT("");
				++itm;
			}
			else
			{
				dir += sortCols.GetChar(pos);
			}
		}
	}

	// Insert the last column
	if (col.Length() > 0)
	{
		lstSortCols->InsertItem(itm, col);
		if (dir.GetChar(0) == 'D')
		{
			lstSortCols->SetItem(itm, 1, _("Descending"));
			lstSortCols->SetItemData(itm, 0);
		}
		else
		{
			lstSortCols->SetItem(itm, 1, _("Ascending"));
			lstSortCols->SetItemData(itm, 1);
		}
	}

	// Finally (phew!) remove all columns we're already sorting on from the list.
	long count = lstSortCols->GetItemCount();

	for (x = 0; x < count; x++)
	{
		int idx = cboColumns->FindString(lstSortCols->GetItemText(x));
		if (idx >= 0)
			cboColumns->Delete(idx);
	}

	// Display the appropriate tab. If the EditGrid is not shown, we must be
	// doing a View Filtered Data.
	if (!parent->IsShown())
		nbOptions->DeletePage(0);

	btnValidate->Disable();
	filter->SetFocus();
}

dlgEditGridOptions::~dlgEditGridOptions()
{
	SavePosition();
}

// Enable/disable the validation button
void dlgEditGridOptions::OnFilterChange(wxStyledTextEvent &ev)
{
	btnValidate->Enable(!filter->GetText().Trim().IsEmpty());
}

void dlgEditGridOptions::OnRemove(wxCommandEvent &ev)
{
	long itm = -1;
	itm = lstSortCols->GetNextItem(itm, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED);
	cboColumns->Append(lstSortCols->GetItemText(itm));
	lstSortCols->DeleteItem(itm);
	if (lstSortCols->GetItemCount() > 0)
	{
		if (lstSortCols->GetItemCount() < itm + 1)
			lstSortCols->SetItemState(lstSortCols->GetItemCount() - 1, wxLIST_STATE_SELECTED, wxLIST_STATE_SELECTED);
		else
			lstSortCols->SetItemState(itm, wxLIST_STATE_SELECTED, wxLIST_STATE_SELECTED);
	}
	wxListEvent nullLstEvent;
	OnLstSortColsChange(nullLstEvent);
}


void dlgEditGridOptions::OnAsc(wxCommandEvent &ev)
{
	long itm = lstSortCols->GetItemCount();
	lstSortCols->InsertItem(itm, cboColumns->GetValue());
	lstSortCols->SetItem(itm, 1, _("Ascending"));
	lstSortCols->SetItemData(itm, 1);
	cboColumns->Delete(cboColumns->GetCurrentSelection());

	// Setup the buttons
	OnCboColumnsChange(ev);
	wxListEvent nullLstEvent;
	OnLstSortColsChange(nullLstEvent);
}

void dlgEditGridOptions::OnDesc(wxCommandEvent &ev)
{
	long itm = lstSortCols->GetItemCount();
	lstSortCols->InsertItem(itm, cboColumns->GetValue());
	lstSortCols->SetItem(itm, 1, _("Descending"));
	lstSortCols->SetItemData(itm, 0);
	cboColumns->Delete(cboColumns->GetCurrentSelection());

	// Setup the buttons
	OnCboColumnsChange(ev);
	wxListEvent nullLstEvent;
	OnLstSortColsChange(nullLstEvent);
}

#ifdef __WXMAC__
void dlgEditGridOptions::OnChangeSize(wxSizeEvent &ev)
{
	if (lstSortCols)
		lstSortCols->SetSize(wxDefaultCoord, wxDefaultCoord,
		                     ev.GetSize().GetWidth(), ev.GetSize().GetHeight() - 350);
	if (GetAutoLayout())
	{
		Layout();
	}
}
#endif

void dlgEditGridOptions::OnValidate(wxCommandEvent &ev)
{
	if (Validate())
		wxMessageBox(_("Filter string syntax validates OK!"), _("Syntax Validation"), wxICON_INFORMATION | wxOK);
}

void dlgEditGridOptions::OnCboColumnsChange(wxCommandEvent &ev)
{
	// Set the command buttons appropriately
	if (cboColumns->GetCurrentSelection() == wxNOT_FOUND)
	{
		btnAsc->Enable(false);
		btnDesc->Enable(false);
	}
	else
	{
		btnAsc->Enable(true);
		btnDesc->Enable(true);
	}
}

void dlgEditGridOptions::OnLstSortColsChange(wxListEvent &ev)
{
	// Set the command buttons appropriately
	if (lstSortCols->GetSelectedItemCount() == 0)
		btnRemove->Enable(false);
	else
		btnRemove->Enable(true);
}

void dlgEditGridOptions::OnCancel(wxCommandEvent &ev)
{
	EndModal(false);
}


void dlgEditGridOptions::OnClose(wxCloseEvent &ev)
{
	EndModal(false);
}

void dlgEditGridOptions::OnOK(wxCommandEvent &ev)
{
#ifdef __WXGTK__
	if (!btnOK->IsEnabled())
		return;
#endif
	// Check the filter syntax
	if (!Validate()) return;

	if (nbOptions->GetPageCount() > 1)
	{
		wxString sortCols;
		long x, count = lstSortCols->GetItemCount();

		for (x = 0; x < count; x++)
		{
			sortCols += qtIdent(lstSortCols->GetItemText(x));
			if (lstSortCols->GetItemData(x) == 0)
				sortCols += wxT(" DESC");
			else
				sortCols += wxT(" ASC");
			sortCols += wxT(", ");
		}

		if (sortCols.Length() > 2)
		{
			sortCols.RemoveLast();
			sortCols.RemoveLast();
		}

		parent->SetSortCols(sortCols);
	}

	parent->SetFilter(filter->GetText().Trim());
	EndModal(true);
}

bool dlgEditGridOptions::Validate()
{
	winMain->StartMsg(_("Validating filter string"));
	filter->MarkerDeleteAll(0);
	if (!filter->GetText().Trim().Length())
	{
		winMain->EndMsg();
		return true;
	}

	wxString sql = wxT("EXPLAIN SELECT * FROM ") + relation + wxT(" WHERE ");
	int queryOffset = sql.Length();
	sql += filter->GetText();

	PGresult *qryRes;
	qryRes = PQexec(connection->connection(), sql.mb_str(*conv));
	int res = PQresultStatus(qryRes);

	// Check for errors
	if (res == PGRES_TUPLES_OK ||
	        res == PGRES_COMMAND_OK)
	{
		// No errors, all OK!
		winMain->EndMsg();
		return true;
	}

	// Figure out where the error is
	wxString errMsg = connection->GetLastError();

	wxString atChar = wxT(" at character ");
	int chp = errMsg.Find(atChar);

	if (chp > 0)
	{
		int selStart = filter->GetSelectionStart(), selEnd = filter->GetSelectionEnd();
		if (selStart == selEnd)
			selStart = 0;

		long errPos = 0;
		errMsg.Mid(chp + atChar.Length()).ToLong(&errPos);
		errPos -= queryOffset;  // do not count EXPLAIN or similar
		wxLogError(wxT("%s"), _("ERROR: Syntax error at character %d!"), errPos);

		int line = 0, maxLine = filter->GetLineCount();
		while (line < maxLine && filter->GetLineEndPosition(line) < errPos + selStart + 1)
			line++;
		if (line < maxLine)
		{
			filter->MarkerAdd(line, 0);
			filter->EnsureVisible(line);
		}
	}
	else
		wxLogError(wxT("%s"), errMsg.BeforeFirst('\n').c_str());

	// Cleanup
	PQclear(qryRes);
	winMain->EndMsg();
	return false;
}