1 //////////////////////////////////////////////////////////////////////////
2 //
3 // pgAdmin III - PostgreSQL Tools
4 //
5 // Copyright (C) 2002 - 2016, The pgAdmin Development Team
6 // This software is released under the PostgreSQL Licence
7 //
8 // gqbGridProjTable.cpp - Table implementation for Projection Panel Grid
9 //
10 //////////////////////////////////////////////////////////////////////////
11 
12 // App headers
13 #include "pgAdmin3.h"
14 
15 // wxWindows headers
16 #include <wx/wx.h>
17 #include <wx/settings.h>
18 #include <wx/utils.h>
19 #include <wx/notebook.h>
20 #include <wx/regex.h>
21 
22 // App headers
23 #include "gqb/gqbGridProjTable.h"
24 #include "gqb/gqbColumn.h"
25 #include "gqb/gqbQueryObjs.h"
26 
gqbGridProjTable(gqbObjsArray * position,gqbObjsArray * parent,wxArrayString * alias)27 gqbGridProjTable::gqbGridProjTable(gqbObjsArray *position, gqbObjsArray *parent, wxArrayString *alias):
28 	wxGridTableBase()
29 {
30 	colsPosition = position;
31 	colsParents = parent;
32 	columnsAlias = alias;
33 	// GQB-TODO: replace above pointers array with local variable if possible or research what it's causing bug in destructor???
34 }
35 
36 
~gqbGridProjTable()37 gqbGridProjTable::~gqbGridProjTable()
38 {
39 }
40 
41 
GetNumberRows()42 int gqbGridProjTable::GetNumberRows()
43 {
44 	return (colsPosition->GetCount());
45 }
46 
47 
GetNumberCols()48 int gqbGridProjTable::GetNumberCols()
49 {
50 
51 	return 3;
52 }
53 
54 
IsEmptyCell(int row,int col)55 bool gqbGridProjTable::IsEmptyCell( int row, int col )
56 {
57 
58 	int count = colsParents->GetCount();
59 	if(row + 1 <= count)
60 		return false;
61 	else
62 		return true;
63 }
64 
65 
GetValue(int row,int col)66 wxString gqbGridProjTable::GetValue( int row, int col )
67 {
68 	switch(col)
69 	{
70 		case 0:
71 			if(((gqbQueryObject *)colsParents->Item(row))->getAlias().length() > 0)
72 			{
73 				return ((gqbQueryObject *)colsParents->Item(row))->getAlias();
74 			}
75 			else
76 			{
77 				return ((gqbQueryObject *)colsParents->Item(row))->getName();
78 			}
79 			break;
80 		case 1:
81 			return ((gqbColumn *)colsPosition->Item(row))->getName();
82 			break;
83 		case 2:
84 			return columnsAlias->Item(row);
85 			break;
86 	};
87 	return wxT("");
88 }
89 
90 
GetColLabelValue(int col)91 wxString gqbGridProjTable::GetColLabelValue( int col)
92 {
93 	switch(col)
94 	{
95 		case 0:
96 			return _("Relation");
97 			break;
98 		case 1:
99 			return _("Column");
100 			break;
101 		case 2:
102 			return _("Alias");
103 			break;
104 	};
105 	return wxT("");
106 }
107 
108 
SetValue(int row,int col,const wxString & value)109 void gqbGridProjTable::SetValue( int row, int col, const wxString &value )
110 {
111 	// Do nothing on values that cannot be edited on this model [Column & Relation Name]
112 	switch(col)
113 	{
114 		case 2:
115 			columnsAlias->Item(row) = value;
116 			break;
117 	};
118 }
119 
GetValueAsCustom(int row,int col,const wxString & typeName)120 void *gqbGridProjTable::GetValueAsCustom( int row, int col, const wxString &typeName )
121 {
122 	switch(col)
123 	{
124 		case 0:
125 			return (void *)&colsParents->Item(row);
126 			break;
127 		case 1:
128 			return (void *)&colsPosition->Item(row);
129 			break;
130 		case 2:
131 			break;
132 	};
133 	return NULL;
134 }
135 
136 
SetValueAsCustom(int row,int col,const wxString & typeName,void * value)137 void  gqbGridProjTable::SetValueAsCustom( int row, int col, const wxString &typeName, void *value )
138 {
139 	switch(col)
140 	{
141 		case 0:
142 			colsParents->Add(((gqbQueryObject *)value));
143 			break;
144 		case 1:
145 			colsPosition->Add(((gqbColumn *)value));
146 	};
147 }
148 
149 
AppendItem(int col,gqbObject * item)150 void gqbGridProjTable::AppendItem(int col, gqbObject *item)
151 {
152 	bool notify = false;
153 	switch(col)
154 	{
155 		case 0:
156 			colsParents->Add(item);
157 			break;
158 		case 1:
159 			colsPosition->Add(item);
160 			notify = true;
161 			break;
162 		case 2:
163 			columnsAlias->Add(wxT(""));
164 			break;
165 	};
166 
167 	if (notify && GetView() )
168 	{
169 		wxGridTableMessage msg( this,
170 		                        wxGRIDTABLE_NOTIFY_ROWS_INSERTED,
171 		                        (colsParents->GetCount() - 1),
172 		                        1 );
173 		GetView()->ProcessTableMessage( msg );
174 
175 		// Set the cells read-only
176 		GetView()->SetReadOnly(GetView()->GetNumberRows() - 1, 0);
177 		GetView()->SetReadOnly(GetView()->GetNumberRows() - 1, 1);
178 	}
179 
180 }
181 
182 // Remove a column at the grid
removeRow(gqbObject * itemTable,gqbObject * itemColumn)183 bool gqbGridProjTable::removeRow(gqbObject *itemTable, gqbObject *itemColumn)
184 {
185 	bool found = false;
186 	int i, size = colsPosition->GetCount();
187 
188 	for(i = 0; i < size; i++)
189 	{
190 		if (colsParents->Item(i) == itemTable && colsPosition->Item(i) == itemColumn)
191 		{
192 			found = true;
193 			break;
194 		}
195 	}
196 
197 	if(found)
198 	{
199 		colsParents->RemoveAt(i);
200 		colsPosition->RemoveAt(i);
201 		columnsAlias->RemoveAt(i);
202 
203 		if ( GetView() )                          // Notify Grid about the change
204 		{
205 			wxGridTableMessage msg( this,
206 			                        wxGRIDTABLE_NOTIFY_ROWS_DELETED,
207 			                        i + 1,
208 			                        1 );
209 			GetView()->ProcessTableMessage( msg );
210 		}
211 	}
212 
213 	return found;
214 }
215 
216 
removeAllRows(gqbObject * itemTable)217 void gqbGridProjTable::removeAllRows(gqbObject *itemTable)
218 {
219 
220 	int size = colsParents->GetCount();
221 	for(int i = (size - 1); i >= 0; i--)
222 	{
223 		if (colsParents->Item(i) == itemTable)
224 		{
225 			colsParents->RemoveAt(i);
226 			colsPosition->RemoveAt(i);
227 			columnsAlias->RemoveAt(i);
228 
229 			// Notify Grid about the change
230 			if ( GetView() )
231 			{
232 				wxGridTableMessage msg( this,
233 				                        wxGRIDTABLE_NOTIFY_ROWS_DELETED,
234 				                        i + 1,
235 				                        1 );
236 				GetView()->ProcessTableMessage( msg );
237 			}
238 		}
239 	}
240 }
241 
242 
changesPositions(int sPos,int dPos)243 void gqbGridProjTable::changesPositions(int sPos, int dPos)
244 {
245 
246 	int size = colsPosition->GetCount();
247 	gqbObject *tmpTable = NULL, *tmpColumn = NULL;
248 	wxString tmpAlias = wxT("");
249 
250 	if( (sPos >= 0 && sPos < size) && (dPos >= 0 && dPos < size) )
251 	{
252 		tmpTable = colsParents->Item(sPos);
253 		tmpColumn = colsPosition->Item(sPos);
254 		tmpAlias = columnsAlias->Item(sPos);
255 
256 		colsParents->Item(sPos) = colsParents->Item(dPos);
257 		colsPosition->Item(sPos) = colsPosition->Item(dPos);
258 		columnsAlias->Item(sPos) = columnsAlias->Item(dPos);
259 		colsParents->Item(dPos) = tmpTable;
260 		colsPosition->Item(dPos) = tmpColumn;
261 		columnsAlias->Item(dPos) = tmpAlias;
262 	}
263 
264 	wxGridTableMessage msg( this,
265 	                        wxGRIDTABLE_REQUEST_VIEW_GET_VALUES,
266 	                        sPos,
267 	                        1 );
268 	GetView()->ProcessTableMessage( msg );
269 
270 }
271 
272 
273 // GQB-TODO: optimize this functions & related buttons events at gqbView because works but are a mess.
274 // Change a single row or a range to one pos up or down (but no more than one position)
changesRangeOnePos(int topPos,int bottomPos,int newTop)275 void gqbGridProjTable::changesRangeOnePos(int topPos, int bottomPos, int newTop)
276 {
277 	// Eliminate side effect of zero base array on calculations, but careful newTop still it's zero based
278 	topPos++;
279 	bottomPos++;
280 	int sizeRange = bottomPos - (topPos - 1), size = GetNumberRows();
281 	if(topPos > newTop)                           // Go Down
282 	{
283 		// Only if the movement don't create an overflow
284 		if( (topPos > 1) && ((newTop + sizeRange) <  size)  )
285 		{
286 			for(int i = newTop ; i < (newTop + sizeRange) ; i++)
287 			{
288 				changesPositions(i, i + 1);
289 			}
290 		}
291 
292 	}                                             // Go Up
293 	else
294 	{
295 		// Only if the movement don't create an overflow
296 		if( (bottomPos < size) && ((newTop + sizeRange) <=  size)  )
297 		{
298 			// Go Up Down
299 			for(int i = (newTop + sizeRange - 1) ; i >= newTop  ; i--)
300 			{
301 				changesPositions(i - 1, i);
302 			}
303 		}
304 	}
305 }
306 
307 
308 // Removes all items from gqbGridProjTable
emptyTableData()309 void gqbGridProjTable::emptyTableData()
310 {
311 
312 	int count = colsPosition->GetCount();
313 	colsPosition->Empty();
314 	colsParents->Empty();
315 	columnsAlias->Empty();
316 
317 	// Notify Grid about the change
318 	if ( GetView() )
319 	{
320 		wxGridTableMessage msg( this,
321 		                        wxGRIDTABLE_NOTIFY_ROWS_DELETED,
322 		                        1,
323 		                        count);
324 		GetView()->ProcessTableMessage( msg );
325 	}
326 }
327 
328