1
2 ///////////////////////////////////////////////////////////
3 // //
4 // SAGA //
5 // //
6 // System for Automated Geoscientific Analyses //
7 // //
8 // User Interface //
9 // //
10 // Program: SAGA //
11 // //
12 //-------------------------------------------------------//
13 // //
14 // VIEW_Table_Data.cpp //
15 // //
16 // Copyright (C) 2021 by Olaf Conrad //
17 // //
18 //-------------------------------------------------------//
19 // //
20 // This file is part of 'SAGA - System for Automated //
21 // Geoscientific Analyses'. SAGA is free software; you //
22 // can redistribute it and/or modify it under the terms //
23 // of the GNU General Public License as published by the //
24 // Free Software Foundation, either version 2 of the //
25 // License, or (at your option) any later version. //
26 // //
27 // SAGA is distributed in the hope that it will be //
28 // useful, but WITHOUT ANY WARRANTY; without even the //
29 // implied warranty of MERCHANTABILITY or FITNESS FOR A //
30 // PARTICULAR PURPOSE. See the GNU General Public //
31 // License for more details. //
32 // //
33 // You should have received a copy of the GNU General //
34 // Public License along with this program; if not, see //
35 // <http://www.gnu.org/licenses/>. //
36 // //
37 //-------------------------------------------------------//
38 // //
39 // contact: Olaf Conrad //
40 // Institute of Geography //
41 // University of Hamburg //
42 // Germany //
43 // //
44 // e-mail: oconrad@saga-gis.org //
45 // //
46 ///////////////////////////////////////////////////////////
47
48 //---------------------------------------------------------
49 #include <wx/window.h>
50 #include <wx/filename.h>
51 #include <wx/clipbrd.h>
52
53 #include <saga_api/saga_api.h>
54
55 #include "res_commands.h"
56 #include "res_dialogs.h"
57
58 #include "helper.h"
59
60 #include "wksp_data_manager.h"
61
62 #include "view_table_data.h"
63
64
65 ///////////////////////////////////////////////////////////
66 // //
67 // //
68 // //
69 ///////////////////////////////////////////////////////////
70
71 //---------------------------------------------------------
CVIEW_Table_Data(CSG_Table * pTable)72 CVIEW_Table_Data::CVIEW_Table_Data(CSG_Table *pTable)
73 {
74 m_pTable = pTable;
75
76 m_bSelection = false;
77 m_bRowLabels = false;
78 }
79
80 //---------------------------------------------------------
~CVIEW_Table_Data(void)81 CVIEW_Table_Data::~CVIEW_Table_Data(void)
82 {
83 // nop
84 }
85
86
87 ///////////////////////////////////////////////////////////
88 // //
89 ///////////////////////////////////////////////////////////
90
91 //---------------------------------------------------------
InsertRows(size_t Position,size_t Number)92 bool CVIEW_Table_Data::InsertRows (size_t Position, size_t Number)
93 {
94 wxGridTableMessage msg(this, wxGRIDTABLE_NOTIFY_ROWS_INSERTED, Position, Number);
95
96 return( GetView()->ProcessTableMessage(msg) );
97 }
98
99 //---------------------------------------------------------
AppendRows(size_t Number)100 bool CVIEW_Table_Data::AppendRows ( size_t Number)
101 {
102 wxGridTableMessage msg(this, wxGRIDTABLE_NOTIFY_ROWS_APPENDED, Number);
103
104 return( GetView()->ProcessTableMessage(msg) );
105 }
106
107 //---------------------------------------------------------
DeleteRows(size_t Position,size_t Number)108 bool CVIEW_Table_Data::DeleteRows (size_t Position, size_t Number)
109 {
110 wxGridTableMessage msg(this, wxGRIDTABLE_NOTIFY_ROWS_DELETED , Position, Number);
111
112 return( GetView()->ProcessTableMessage(msg) );
113 }
114
115 //---------------------------------------------------------
InsertCols(size_t Position,size_t Number)116 bool CVIEW_Table_Data::InsertCols (size_t Position, size_t Number)
117 {
118 wxGridTableMessage msg(this, wxGRIDTABLE_NOTIFY_COLS_INSERTED, Position, Number);
119
120 return( GetView()->ProcessTableMessage(msg) );
121 }
122
123 //---------------------------------------------------------
AppendCols(size_t Number)124 bool CVIEW_Table_Data::AppendCols ( size_t Number)
125 {
126 wxGridTableMessage msg(this, wxGRIDTABLE_NOTIFY_COLS_APPENDED, Number);
127
128 return( GetView()->ProcessTableMessage(msg) );
129 }
130
131 //---------------------------------------------------------
DeleteCols(size_t Position,size_t Number)132 bool CVIEW_Table_Data::DeleteCols (size_t Position, size_t Number)
133 {
134 wxGridTableMessage msg(this, wxGRIDTABLE_NOTIFY_COLS_DELETED , Position, Number);
135
136 return( GetView()->ProcessTableMessage(msg) );
137 }
138
139
140 ///////////////////////////////////////////////////////////
141 // //
142 ///////////////////////////////////////////////////////////
143
144 //---------------------------------------------------------
SetValue(int iRecord,int iField,const wxString & Value)145 void CVIEW_Table_Data::SetValue(int iRecord, int iField, const wxString &Value)
146 {
147 CSG_Table_Record *pRecord = Get_Field(iField) ? Get_Record(iRecord, iField) : NULL;
148
149 if( pRecord )
150 {
151 if( Value.IsEmpty() )
152 {
153 pRecord->Set_NoData(iField);
154 }
155 else switch( m_pTable->Get_Field_Type(iField) )
156 {
157 default:
158 {
159 pRecord->Set_Value(iField, &Value);
160 }
161 break;
162
163 case SG_DATATYPE_Color:
164 {
165 if( Value[0] == '#' )
166 {
167 wxColour Color; Color.Set(Value);
168
169 pRecord->Set_Value(iField, Get_Color_asInt(Color));
170 }
171 else
172 {
173 pRecord->Set_Value(iField, &Value);
174 }
175 }
176 break;
177 }
178 }
179 }
180
181 //---------------------------------------------------------
SetValueAsLong(int iRecord,int iField,long Value)182 void CVIEW_Table_Data::SetValueAsLong(int iRecord, int iField, long Value)
183 {
184 CSG_Table_Record *pRecord = Get_Field(iField) ? Get_Record(iRecord, iField) : NULL;
185
186 if( pRecord ) { pRecord->Set_Value(iField, Value); }
187 }
188
189 //---------------------------------------------------------
SetValueAsDouble(int iRecord,int iField,double Value)190 void CVIEW_Table_Data::SetValueAsDouble(int iRecord, int iField, double Value)
191 {
192 CSG_Table_Record *pRecord = Get_Field(iField) ? Get_Record(iRecord, iField) : NULL;
193
194 if( pRecord ) { pRecord->Set_Value(iField, Value); }
195 }
196
197 //---------------------------------------------------------
SetValueAsBool(int iRecord,int iField,bool Value)198 void CVIEW_Table_Data::SetValueAsBool(int iRecord, int iField, bool Value)
199 {
200 CSG_Table_Record *pRecord = Get_Field(iField) ? Get_Record(iRecord, iField) : NULL;
201
202 if( pRecord ) { pRecord->Set_Value(iField, Value); }
203 }
204
205 ///////////////////////////////////////////////////////////
206 // //
207 ///////////////////////////////////////////////////////////
208
209 //---------------------------------------------------------
On_Changed(int iRecord,int iField)210 bool CVIEW_Table_Data::On_Changed(int iRecord, int iField)
211 {
212 CSG_Table_Record *pRecord = Get_Field(iField) ? Get_Record(iRecord, iField) : NULL;
213
214 if( pRecord && GetView() )
215 {
216 switch( m_pTable->Get_Field_Type(iField) )
217 {
218 default:
219 {
220 // nop
221 }
222 break;
223
224 case SG_DATATYPE_Color:
225 {
226 wxColour Colour(Get_Color_asWX(pRecord->asInt(iField)));
227
228 GetView()->SetCellBackgroundColour(iRecord, iField, Colour);
229 GetView()->SetCellTextColour (iRecord, iField, Colour);
230 }
231 break;
232 }
233 }
234
235 return( true );
236 }
237
238 //---------------------------------------------------------
Sort_Parameter_Changed(CSG_Parameter * pParameter,int Flags)239 int Sort_Parameter_Changed(CSG_Parameter *pParameter, int Flags)
240 {
241 CSG_String ID(pParameter->Get_Identifier());
242
243 if( ID.Find("ORDER") == 0 )
244 {
245 pParameter->Set_Children_Enabled(pParameter->asInt() > 0);
246 }
247
248 return( 1 );
249 }
250
251 //---------------------------------------------------------
On_Sort(void)252 bool CVIEW_Table_Data::On_Sort(void)
253 {
254 CSG_String Fields, Order;
255
256 for(int i=0; i<m_pTable->Get_Field_Count(); i++)
257 {
258 Fields += m_pTable->Get_Field_Name(i) + CSG_String("|");
259 }
260
261 Order.Printf("%s|%s|%s",
262 _TL("do not sort"),
263 _TL("ascending"),
264 _TL("descending")
265 );
266
267 //-----------------------------------------------------
268 CSG_Parameters P(_TL("Sort Table"));
269
270 P.Set_Callback_On_Parameter_Changed(Sort_Parameter_Changed);
271
272 P.Add_Choice("" , "ORDER_1", _TL("Sorting Order" ), _TL(""), Order , !m_pTable->is_Indexed() ? 1 : m_pTable->Get_Index_Order(0));
273 P.Add_Choice("ORDER_1", "FIELD_1", _TL("Field" ), _TL(""), Fields, !m_pTable->is_Indexed() ? 0 : m_pTable->Get_Index_Field(0));
274
275 P.Add_Choice("ORDER_1", "ORDER_2", _TL("2nd Sorting Order"), _TL(""), Order , !m_pTable->is_Indexed() ? 0 : m_pTable->Get_Index_Order(1));
276 P.Add_Choice("ORDER_2", "FIELD_2", _TL("2nd Field" ), _TL(""), Fields, !m_pTable->is_Indexed() ? 0 : m_pTable->Get_Index_Field(1));
277
278 P.Add_Choice("ORDER_2", "ORDER_3", _TL("3rd Sorting Order"), _TL(""), Order , !m_pTable->is_Indexed() ? 0 : m_pTable->Get_Index_Order(2));
279 P.Add_Choice("ORDER_3", "FIELD_3", _TL("3rd Field" ), _TL(""), Fields, !m_pTable->is_Indexed() ? 0 : m_pTable->Get_Index_Field(2));
280
281 //-----------------------------------------------------
282 if( DLG_Parameters(&P) )
283 {
284 m_pTable->Set_Index(
285 P("FIELD_1")->asInt(), P("ORDER_1")->asInt() == 1 ? TABLE_INDEX_Ascending : P("ORDER_1")->asInt() == 2 ? TABLE_INDEX_Descending : TABLE_INDEX_None,
286 P("FIELD_2")->asInt(), P("ORDER_2")->asInt() == 1 ? TABLE_INDEX_Ascending : P("ORDER_2")->asInt() == 2 ? TABLE_INDEX_Descending : TABLE_INDEX_None,
287 P("FIELD_3")->asInt(), P("ORDER_3")->asInt() == 1 ? TABLE_INDEX_Ascending : P("ORDER_3")->asInt() == 2 ? TABLE_INDEX_Descending : TABLE_INDEX_None
288 );
289
290 return( true );
291 }
292
293 return( false );
294 }
295
296
297 ///////////////////////////////////////////////////////////
298 // //
299 ///////////////////////////////////////////////////////////
300
301 //---------------------------------------------------------
Sort(int iField,int Direction)302 bool CVIEW_Table_Data::Sort(int iField, int Direction)
303 {
304 if( iField >= 0 && iField < GetNumberCols() )
305 {
306 switch( Direction )
307 {
308 default: m_pTable->Toggle_Index(iField ); break;
309 case 0: m_pTable-> Set_Index(iField, TABLE_INDEX_None ); break;
310 case 1: m_pTable-> Set_Index(iField, TABLE_INDEX_Ascending ); break;
311 case 2: m_pTable-> Set_Index(iField, TABLE_INDEX_Descending); break;
312 }
313
314 return( true );
315 }
316
317 return( false );
318 }
319
320 //---------------------------------------------------------
To_Clipboard(void)321 bool CVIEW_Table_Data::To_Clipboard(void)
322 {
323 if( wxTheClipboard->Open() )
324 {
325 wxString Data;
326
327 for(int iField=0; iField<m_pTable->Get_Field_Count(); iField++)
328 {
329 Data += m_pTable->Get_Field_Name(iField);
330 Data += 1 + iField < m_pTable->Get_Field_Count() ? '\t' : '\n';
331 }
332
333 int nRecords = m_pTable->Get_Selection_Count()
334 ? (int)m_pTable->Get_Selection_Count() : m_pTable->Get_Count();
335
336 for(int iRecord=0; iRecord<nRecords; iRecord++)
337 {
338 CSG_Table_Record *pRecord = m_pTable->Get_Selection_Count()
339 ? m_pTable->Get_Selection(iRecord) : m_pTable->Get_Record_byIndex(iRecord);
340
341 for(int iField=0; iField<m_pTable->Get_Field_Count(); iField++)
342 {
343 Data += pRecord->asString(iField);
344 Data += 1 + iField < m_pTable->Get_Field_Count() ? '\t' : '\n';
345 }
346 }
347
348 wxTheClipboard->SetData(new wxTextDataObject(Data));
349 wxTheClipboard->Close();
350
351 return( true );
352 }
353
354 return( false );
355 }
356
357 //---------------------------------------------------------
is_DataSource(wxString & Source)358 bool CVIEW_Table_Data::is_DataSource(wxString &Source)
359 {
360 if( Source.Find("PGSQL:" ) == 0
361 || Source.Find("ftp://" ) == 0
362 || Source.Find("http://" ) == 0
363 || Source.Find("https://") == 0
364 || Source.Find("file://" ) == 0
365 || wxFileExists(Source) )
366 {
367 return( true );
368 }
369
370 if( m_pTable->Get_File_Name(false) )
371 {
372 wxFileName fn(Source), dir(m_pTable->Get_File_Name(false));
373
374 if( fn.MakeAbsolute(dir.GetPath()) && fn.Exists() )
375 {
376 Source = fn.GetFullPath();
377
378 return( true );
379 }
380 }
381
382 return( false );
383 }
384
385
386 ///////////////////////////////////////////////////////////
387 // //
388 // //
389 // //
390 ///////////////////////////////////////////////////////////
391
392 //---------------------------------------------------------
393