diff --git a/DataViewer/OGRTable.cpp b/DataViewer/OGRTable.cpp index 10df8cf47..95bae1028 100644 --- a/DataViewer/OGRTable.cpp +++ b/DataViewer/OGRTable.cpp @@ -50,8 +50,10 @@ OGRTable::OGRTable(int n_rows) //table_state->registerObserver(this); } -OGRTable::OGRTable(OGRLayerProxy* _ogr_layer, GdaConst::DataSourceType ds_type, - TableState* table_state, TimeState* time_state, +OGRTable::OGRTable(OGRLayerProxy* _ogr_layer, + GdaConst::DataSourceType ds_type, + TableState* table_state, + TimeState* time_state, const VarOrderPtree& var_order_ptree) : TableInterface(table_state, time_state), ogr_layer(_ogr_layer), var_order(var_order_ptree), datasource_type(ds_type) @@ -63,7 +65,9 @@ ogr_layer(_ogr_layer), var_order(var_order_ptree), datasource_type(ds_type) // create in memory OGRColumns, read var_map for (size_t i=0; ifields.size(); ++i) { AddOGRColumn(ogr_layer, i); - var_map[columns[i]->GetName()] = i; + // deprecated in 1.8 + //var_map[columns[i]->GetName()] = i; + org_var_names.push_back(columns[i]->GetName()); } /* @@ -216,7 +220,10 @@ void OGRTable::AddOGRColumn(OGRColumn* ogr_col) columns.push_back(ogr_col); - var_map[ogr_col->GetName()] = pos; + + // deprecated in 1.8 + //var_map[ogr_col->GetName()] = pos; + org_var_names.push_back(ogr_col->GetName()); } @@ -358,19 +365,29 @@ int OGRTable::FindColId(const wxString& name) return var_order.GetColId(c_name); } + int OGRTable::GetColIdx(const wxString& name) { wxString c_name = name; c_name.Trim(false); c_name.Trim(true); - + + // update it if different in real data. E.g. user may create a column + // with name in lowercase, however, it is forced to uppercase in real table + + /* + // deprecated in 1.8.8 std::map::iterator i; if ( (i=var_map.find(name)) != var_map.end() || (i=var_map.find(name.Upper())) != var_map.end() || (i=var_map.find(name.Lower())) != var_map.end() ) { return i->second; } - + */ + for (size_t i=0; i::iterator i; if ( (i=var_map.find(name_in_project)) != var_map.end() || (i=var_map.find(name_in_project.Upper())) != var_map.end() || (i=var_map.find(name_in_project.Lower())) != var_map.end() ) { + OGRColumn* ogr_col = columns[i->second]; if (name_in_project != ogr_col->GetName() ) { name_in_project = ogr_col->GetName(); var_order.FindVarGroup(col).name = name_in_project; } } + */ + return name_in_project; } @@ -942,10 +966,12 @@ bool OGRTable::RenameSimpleCol(int col, int time, const wxString& new_name) { if (!PermitRenameSimpleCol()) return false; if (col < 0 || col >= GetNumberCols()) return false; + int ogr_col_id = FindOGRColId(col, time); if (ogr_col_id == wxNOT_FOUND) return false; wxString old_name = GetColName(col, time); + OGRColumn* cur_col = columns[ogr_col_id]; operations_queue.push(new OGRTableOpRenameColumn(cur_col, cur_col->GetName(), @@ -953,15 +979,19 @@ bool OGRTable::RenameSimpleCol(int col, int time, const wxString& new_name) cur_col->Rename(new_name); //update var_map + /* + //deprecated in 1.8.8 map::iterator it = var_map.find(old_name); if ( it == var_map.end()) it = var_map.find(old_name.Upper()); if ( it == var_map.end()) it = var_map.find(old_name.Lower()); if ( it == var_map.end()) return false; - int ogr_col_idx = it->second; var_map[new_name] = ogr_col_idx; var_map.erase(it); + */ + org_var_names[ogr_col_id] = new_name; + // update variable parameters var_order.SetGroupName(col, new_name); @@ -1031,18 +1061,29 @@ bool OGRTable::SetCellFromString(int row, int col, int time, int OGRTable::InsertCol(GdaConst::FieldType type, const wxString& name, int pos, int time_steps, int field_len, int decimals) { - using namespace std; - if (pos > GetNumberCols()) return -1; - // this case if for appending new column at the end of table - if (pos < 0) pos = GetNumberCols(); - LOG_MSG(wxString::Format("Inserting column into table at postion %d",pos)); - if (time_steps < 0) return -1; - if (type != GdaConst::double_type) decimals = 0; + if (pos > GetNumberCols() || time_steps < 0 ) { + return -1; + } + + // don't support the following column type if (field_len == -1 && (type == GdaConst::placeholder_type || type == GdaConst::unknown_type || - type == GdaConst::date_type)){ + type == GdaConst::date_type)) + { return -1; } + + // if for appending new column at the end of table + if (pos < 0) { + pos = GetNumberCols(); + } + + LOG_MSG(wxString::Format("Inserting column into table at postion %d",pos)); + + if (type != GdaConst::double_type) { + decimals = 0; + } + if (field_len == -1) { if (type == GdaConst::double_type) { field_len = GdaConst::default_dbf_double_len; @@ -1052,6 +1093,7 @@ int OGRTable::InsertCol(GdaConst::FieldType type, const wxString& name, int pos, field_len = GdaConst::default_dbf_string_len; } } + if (decimals < 0) { if (type == GdaConst::double_type) { decimals = GdaConst::default_display_decimals; @@ -1062,16 +1104,19 @@ int OGRTable::InsertCol(GdaConst::FieldType type, const wxString& name, int pos, // note the differences between "Group/Ungroup" and "Append new column" // (new field always added to the end of existing columns) + vector names(SuggestDBColNames(name, name, time_steps)); + // return could be group of names (e.g. pop2001, pop2002, pop2003) for (size_t t=0; t::iterator iter = org_var_names.begin() + pos; + org_var_names.insert(iter, names[t]); } - var_map.clear(); + + /* + // deprecated in 1.8.8, see ogr_var_names in the above code + var_map.clear(); for (size_t i=0; iGetName()] = i; } + */ VarGroup g(name, decimals); - if (time_steps > 1) g.vars = names; + if (time_steps > 1) { + g.vars = names; + } var_order.InsertVarGroup(g, pos); SetChangedSinceLastSave(true); @@ -1107,11 +1161,14 @@ int OGRTable::InsertCol(GdaConst::FieldType type, const wxString& name, int pos, bool OGRTable::DeleteCol(int pos) { - using namespace std; LOG_MSG("Inside OGRTable::DeleteCol"); LOG_MSG(wxString::Format("Deleting column from table at postion %d", pos)); - if (pos < 0 || pos >= var_order.GetNumVarGroups() || - var_order.GetNumVarGroups() == 0) return false; + if (pos < 0 || + pos >= var_order.GetNumVarGroups() || + var_order.GetNumVarGroups() == 0) + { + return false; + } // Must remove all items from var_map first VarGroup vg = var_order.FindVarGroup(pos); @@ -1121,18 +1178,23 @@ bool OGRTable::DeleteCol(int pos) if (s != "") { for( size_t i=0; iGetName().CmpNoCase(s) == 0) { - operations_queue.push( - new OGRTableOpDeleteColumn(columns[i])); + operations_queue.push(new OGRTableOpDeleteColumn(columns[i])); columns.erase(columns.begin()+i); break; } } } } + + /* + // depcrecated in 1.8.8 var_map.clear(); for (int i=0; iGetName()] = i; } + */ + vector::iterator iter = org_var_names.begin() + pos; + org_var_names.erase(iter); wxString name = var_order.GetGroupName(pos); var_order.RemoveVarGroup(pos); @@ -1151,7 +1213,6 @@ bool OGRTable::DeleteCol(int pos) void OGRTable::UngroupCol(int col) { - using namespace std; LOG_MSG("Inside OGRTable::UngroupCol"); if (col < 0 || col >= var_order.GetNumVarGroups()) return; if (GetColTimeSteps(col) <= 1) return; @@ -1192,7 +1253,6 @@ void OGRTable::UngroupCol(int col) void OGRTable::GroupCols(const std::vector& cols, const wxString& name, int pos) { - using namespace std; LOG_MSG("Inside OGRTable::GroupCols"); if (pos < 0 || pos > var_order.GetNumVarGroups()) return; if (cols.size() <= 1) return; @@ -1327,12 +1387,21 @@ int OGRTable::FindOGRColId(int wxgrid_col_pos, int time) int OGRTable::FindOGRColId(const wxString& name) { + for (size_t i=0; i < org_var_names.size(); i++ ) { + if (name == org_var_names[i]) { + return i; + } + } + return -1; + /* + // deprecated in 1.8.8 std::map::iterator i = var_map.find(name); if ( i == var_map.end()) i = var_map.find(name.Upper()); if ( i == var_map.end()) i = var_map.find(name.Lower()); if ( i == var_map.end()) return -1; return i->second; + */ } OGRColumn* OGRTable::FindOGRColumn(int col, int time) @@ -1345,12 +1414,22 @@ OGRColumn* OGRTable::FindOGRColumn(int col, int time) OGRColumn* OGRTable::FindOGRColumn(const wxString& name) { if (name.IsEmpty()) return NULL; + + for (size_t i=0; i::iterator i =var_map.find(name); if ( i == var_map.end()) i = var_map.find(name.Upper()); if ( i == var_map.end()) i = var_map.find(name.Lower()); if ( i == var_map.end()) return NULL; return columns[i->second]; + */ } bool OGRTable::IsValidDBColName(const wxString& col_nm, diff --git a/DataViewer/OGRTable.h b/DataViewer/OGRTable.h index 547ca6cef..d7286dbf4 100644 --- a/DataViewer/OGRTable.h +++ b/DataViewer/OGRTable.h @@ -51,7 +51,11 @@ class OGRTable : public TableInterface, TableStateObserver OGRLayerProxy* ogr_layer; vector columns; VarOrderMapper var_order; + // var_map will be deprecate in 1.8.8, and replace by _var_names map var_map; + vector org_var_names; + vector new_var_names; + // queues of table operations queue operations_queue; stack completed_stack; diff --git a/DialogTools/FieldNameCorrectionDlg.cpp b/DialogTools/FieldNameCorrectionDlg.cpp index a684c8178..e47a12cde 100644 --- a/DialogTools/FieldNameCorrectionDlg.cpp +++ b/DialogTools/FieldNameCorrectionDlg.cpp @@ -44,28 +44,38 @@ ScrolledWidgetsPane::ScrolledWidgetsPane(wxWindow* parent, wxWindowID id, { vector merged_field_names; set bad_fnames, dup_fname, uniq_upper_fname; + + vector bad_fname_idx_s, dup_fname_idx_s; for (int i=0; i < all_fname.size(); i++) { wxString field_name = all_fname[i]; - field_names_dict[field_name] = field_name; + + old_field_names.push_back(field_name); + new_field_names.push_back(field_name); + + field_names_dict[field_name] = field_name; bool isValid = true; if (!IsFieldNameValid(field_name) ) { bad_fnames.insert(field_name); + bad_fname_idx_s.push_back(i); isValid = false; } else if (uniq_upper_fname.find(field_name.Upper()) != uniq_upper_fname.end()) { dup_fname.insert(field_name); + dup_fname_idx_s.push_back(i); isValid = false; } + uniq_upper_fname.insert(field_name.Upper()); if (isValid) merged_field_names.push_back(field_name); } - if (!bad_fnames.empty() || !dup_fname.empty()) { + if (!dup_fname_idx_s.empty() || !bad_fname_idx_s.empty()) { need_correction = true; - Init(merged_field_names, dup_fname, bad_fnames); + //Init(merged_field_names, dup_fname, bad_fnames); + Init(dup_fname_idx_s, bad_fname_idx_s); } } @@ -91,6 +101,106 @@ ScrolledWidgetsPane::~ScrolledWidgetsPane() } } +void ScrolledWidgetsPane::Init(vector& dup_fname_idx_s, + vector& bad_fname_idx_s) +{ + // the sizer will take care of determining the needed scroll size + // (if you don't use sizers you will need to manually set the viewport size) + + // build a dict for searching duplicated field + for (size_t i=0; iAdd(txt_oname, 0, wxALIGN_LEFT|wxALL, 15); + wxStaticText* txt_newname=new wxStaticText(this,wxID_ANY,"New field name:"); + sizer->Add(txt_newname, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL|wxALL, 15); + wxStaticText* txt_orest=new wxStaticText(this, wxID_ANY, "Field restrictions:"); + sizer->Add(txt_orest, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL|wxALL, 15); + + size_t ctrl_cnt = 0; + + for (size_t i=0; i < dup_fname_idx_s.size(); i++) + { + int fname_idx = dup_fname_idx_s[i]; + wxString field_name = old_field_names[fname_idx]; + warn_msg=DUP_WARN; + + wxString id_name1, id_name2, id_name3; + id_name1 << "ID_FNAME_STAT_TXT_BASE" << ctrl_cnt; + id_name2 << "ID_INPUT_TXT_CTRL_BASE" << ctrl_cnt; + id_name3 << "ID_INFO_STAT_TXT_BASE" << ctrl_cnt; + + wxString user_field_name = GetSuggestFieldName(fname_idx); + txt_fname.push_back(new wxStaticText(this, XRCID(id_name1), field_name)); + sizer->Add(txt_fname[ctrl_cnt], 0, wxALIGN_LEFT|wxALL, 5); + txt_input.push_back(new wxTextCtrl(this, XRCID(id_name2), user_field_name, wxDefaultPosition,wxSize(240,-1))); + sizer->Add(txt_input[ctrl_cnt], 0, wxALIGN_LEFT|wxALL, 5); + txt_info.push_back(new wxStaticText(this, XRCID(id_name3), warn_msg)); + sizer->Add(txt_info[ctrl_cnt], 0, wxALIGN_LEFT|wxALL, 5); + + ++ctrl_cnt; + } + + for (size_t i=0; i < bad_fname_idx_s.size(); i++) + { + int fname_idx = bad_fname_idx_s[i]; + wxString field_name = old_field_names[fname_idx]; + warn_msg=INV_WARN; + + wxString id_name1, id_name2, id_name3; + id_name1 << "ID_FNAME_STAT_TXT_BASE" << ctrl_cnt; + id_name2 << "ID_INPUT_TXT_CTRL_BASE" << ctrl_cnt; + id_name3 << "ID_INFO_STAT_TXT_BASE" << ctrl_cnt; + + wxString user_field_name = GetSuggestFieldName(fname_idx); + txt_fname.push_back(new wxStaticText(this, XRCID(id_name1), field_name)); + sizer->Add(txt_fname[ctrl_cnt], 0, wxALIGN_LEFT|wxALL, 5); + txt_input.push_back(new wxTextCtrl(this, XRCID(id_name2), user_field_name, wxDefaultPosition,wxSize(240,-1))); + sizer->Add(txt_input[ctrl_cnt], 0, wxALIGN_LEFT|wxALL, 5); + txt_info.push_back(new wxStaticText(this, XRCID(id_name3), warn_msg)); + sizer->Add(txt_info[ctrl_cnt], 0, wxALIGN_LEFT|wxALL, 5); + + ++ctrl_cnt; + } + + // buttons + wxStaticText* txt_dummy = new wxStaticText(this, wxID_ANY, ""); + sizer->Add(txt_dummy, 0, wxALIGN_LEFT | wxALL, 5); + wxBoxSizer* btnSizer = new wxBoxSizer(wxHORIZONTAL); + wxButton* ok_btn = new wxButton(this, wxID_OK, "OK"); + btnSizer->Add(ok_btn, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL|wxALL,15); + wxButton* exit_btn = new wxButton(this, wxID_CANCEL, "Cancel"); + btnSizer->Add(exit_btn, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL|wxALL,15); + sizer->Add(btnSizer, 0, wxALIGN_LEFT | wxALL, 15); + + this->SetSizer(sizer); + // this part makes the scrollbars show up + this->FitInside(); // ask the sizer about the needed size + this->SetScrollRate(5, 5); + +} + void ScrolledWidgetsPane::Init(vector& merged_field_names, set& dup_fname, set& bad_fname) @@ -176,33 +286,6 @@ void ScrolledWidgetsPane::Init(vector& merged_field_names, ++ctrl_cnt; } - /* - for (size_t i=0; iAdd(txt_fname[ctrl_cnt], 0, wxALIGN_LEFT|wxALL, 5); - txt_input.push_back(new wxTextCtrl(this, XRCID(id_name2), user_field_name, wxDefaultPosition,wxSize(240,-1))); - sizer->Add(txt_input[ctrl_cnt], 0, wxALIGN_LEFT|wxALL, 5); - txt_info.push_back(new wxStaticText(this, XRCID(id_name3), warn_msg)); - sizer->Add(txt_info[ctrl_cnt], 0, wxALIGN_LEFT|wxALL, 5); - - ++ctrl_cnt; - } - */ // buttons wxStaticText* txt_dummy = new wxStaticText(this, wxID_ANY, ""); @@ -221,8 +304,30 @@ void ScrolledWidgetsPane::Init(vector& merged_field_names, } - // give suggested field name based on GdaConst::DataSourceType +wxString ScrolledWidgetsPane::GetSuggestFieldName(int field_idx) +{ + wxString old_name = old_field_names[field_idx]; + wxString new_name(old_name); + + // if illegal name + new_name = RemoveIllegalChars(new_name); + + // if name too long + new_name = TruncateFieldName(new_name); + + // check duplicate name + new_name = RenameDupFieldName(new_name); + + // put it to new field name list + new_field_names[field_idx] = new_name; + + // add any new suggest name to search dict + field_dict[new_name] = true; + + return new_name; +} + wxString ScrolledWidgetsPane::GetSuggestFieldName(const wxString& old_name) { wxString new_name(old_name); @@ -415,6 +520,11 @@ map ScrolledWidgetsPane::GetMergedFieldNameDict() return field_names_dict; } +vector ScrolledWidgetsPane::GetNewFieldNames() +{ + return new_field_names; +} + //////////////////////////////////////////////////////////////////////////////// // // Main FieldNameCorrectionDlg @@ -425,7 +535,7 @@ FieldNameCorrectionDlg:: FieldNameCorrectionDlg(GdaConst::DataSourceType ds_type, vector& all_fname, wxString title) -: wxDialog(NULL, -1, title, wxDefaultPosition, wxSize(600,300)) +: wxDialog(NULL, -1, title, wxDefaultPosition, wxSize(680,300)) { diff --git a/DialogTools/FieldNameCorrectionDlg.h b/DialogTools/FieldNameCorrectionDlg.h index b22a588e8..0e49e79de 100644 --- a/DialogTools/FieldNameCorrectionDlg.h +++ b/DialogTools/FieldNameCorrectionDlg.h @@ -39,6 +39,9 @@ class ScrolledWidgetsPane : public wxScrolledWindow map field_names_dict; map field_dict; vector merged_field_names; + + vector old_field_names; + vector new_field_names; public: // Variable number of controls @@ -67,15 +70,18 @@ class ScrolledWidgetsPane : public wxScrolledWindow virtual ~ScrolledWidgetsPane(); wxString GetSuggestFieldName(const wxString& old_name); + wxString GetSuggestFieldName(int field_idx); wxString RenameDupFieldName(const wxString& old_name); wxString RemoveIllegalChars(const wxString& old_name); wxString TruncateFieldName(const wxString& old_name, int max_len=0); bool IsFieldNameValid(const wxString& col_name); map GetMergedFieldNameDict(); + vector GetNewFieldNames(); void Init(vector& merged_field_names, set& dup_fname, set& bad_fname); + void Init(vector& dup_fname_idx_s, vector& bad_fname_idx_s); bool CheckUserInput(); @@ -105,6 +111,10 @@ class FieldNameCorrectionDlg: public wxDialog map GetMergedFieldNameDict(){ return fieldPane->GetMergedFieldNameDict(); } + + vector GetNewFieldNames() { + return fieldPane->GetNewFieldNames(); + } void OnOkClick(wxCommandEvent& event); void OnCancelClick(wxCommandEvent& event); diff --git a/Explore/MapNewView.cpp b/Explore/MapNewView.cpp index 5c5dab871..6581ea2a1 100644 --- a/Explore/MapNewView.cpp +++ b/Explore/MapNewView.cpp @@ -1721,6 +1721,125 @@ void MapFrame::closeObserver(boost::uuids::uuid id) } } +void MapFrame::OnCopyImageToClipboard(wxCommandEvent& event) +{ + LOG_MSG("Entering TemplateFrame::OnCopyImageToClipboard"); + if (!template_canvas) return; + wxSize sz = template_canvas->GetVirtualSize(); + + wxBitmap bitmap( sz.x, sz.y ); + + wxMemoryDC dc; + dc.SelectObject( bitmap ); + + dc.SetBrush(template_canvas->canvas_background_color); + dc.DrawRectangle(wxPoint(0,0), sz); + + if (((MapCanvas*) template_canvas)->isDrawBasemap) { + dc.DrawBitmap(*template_canvas->GetBaseLayer(), 0, 0, true); + } + dc.DrawBitmap(*template_canvas->GetLayer0(), 0, 0, true); + dc.DrawBitmap(*template_canvas->GetLayer1(), 0, 0, true); + dc.DrawBitmap(*template_canvas->GetLayer2(), 0, 0, true); + + dc.SelectObject( wxNullBitmap ); + + if ( !wxTheClipboard->Open() ) { + wxMessageBox("Can't open clipboard."); + } else { + wxTheClipboard->AddData(new wxBitmapDataObject(bitmap)); + wxTheClipboard->Close(); + } + LOG_MSG("Exiting TemplateFrame::OnCopyImageToClipboard"); +} + +void MapFrame::ExportImage(TemplateCanvas* canvas, const wxString& type) +{ + LOG_MSG("Entering TemplateFrame::ExportImage"); + + wxString default_fname(project->GetProjectTitle() + type); + wxString filter("BMP|*.bmp|PNG|*.png"); + int filter_index = 1; + // + wxFileDialog dialog(canvas, "Save Image to File", wxEmptyString, + default_fname, filter, + wxFD_SAVE | wxFD_OVERWRITE_PROMPT); + dialog.SetFilterIndex(filter_index); + + if (dialog.ShowModal() != wxID_OK) return; + + wxSize sz = canvas->GetVirtualSize(); + + wxFileName fname = wxFileName(dialog.GetPath()); + wxString str_fname = fname.GetPathWithSep() + fname.GetName(); + + switch (dialog.GetFilterIndex()) { + case 0: + { + LOG_MSG("BMP selected"); + wxBitmap bitmap( sz.x, sz.y ); + wxMemoryDC dc; + dc.SelectObject(bitmap); + + //dc.SetBrush(template_canvas->canvas_background_color); + //dc.DrawRectangle(wxPoint(0,0), sz); + + if (((MapCanvas*) template_canvas)->isDrawBasemap) { + dc.DrawBitmap(*template_canvas->GetBaseLayer(), 0, 0, true); + } + dc.DrawBitmap(*template_canvas->GetLayer0(), 0, 0, true); + dc.DrawBitmap(*template_canvas->GetLayer1(), 0, 0, true); + dc.DrawBitmap(*template_canvas->GetLayer2(), 0, 0, true); + dc.SelectObject( wxNullBitmap ); + + wxImage image = bitmap.ConvertToImage(); + + if ( !image.SaveFile( str_fname + ".bmp", wxBITMAP_TYPE_BMP )) { + wxMessageBox("GeoDa was unable to save the file."); + } + image.Destroy(); + } + break; + case 1: + { + LOG_MSG("PNG selected"); + wxBitmap bitmap( sz.x, sz.y ); + wxMemoryDC dc(bitmap); + //dc.SelectObject(bitmap); + + dc.SetBrush(template_canvas->canvas_background_color); + dc.DrawRectangle(wxPoint(0,0), sz); + + if (((MapCanvas*) template_canvas)->isDrawBasemap) { + dc.DrawBitmap(*template_canvas->GetBaseLayer(), 0, 0, true); + } + dc.DrawBitmap(*template_canvas->GetLayer0(), 0, 0, true); + dc.DrawBitmap(*template_canvas->GetLayer1(), 0, 0, true); + dc.DrawBitmap(*template_canvas->GetLayer2(), 0, 0, true); + //dc.SelectObject( wxNullBitmap ); + + wxImage image = bitmap.ConvertToImage(); + + if ( !image.SaveFile( str_fname + ".png", wxBITMAP_TYPE_PNG )) { + wxMessageBox("GeoDa was unable to save the file."); + } + + image.Destroy(); + } + break; + + default: + { + LOG_MSG("Error: A non-recognized type selected."); + } + break; + } + return; + + LOG_MSG("Exiting MapFrame::ExportImage"); +} + + void MapFrame::OnNewCustomCatClassifA() { ((MapCanvas*) template_canvas)->NewCustomCatClassif(); diff --git a/Explore/MapNewView.h b/Explore/MapNewView.h index ff1291d59..6b9a21906 100644 --- a/Explore/MapNewView.h +++ b/Explore/MapNewView.h @@ -232,6 +232,9 @@ class MapFrame : public TemplateFrame, public WeightsManStateObserver virtual int numMustCloseToRemove(boost::uuids::uuid id) const; virtual void closeObserver(boost::uuids::uuid id); + virtual void OnCopyImageToClipboard(wxCommandEvent& event); + virtual void ExportImage(TemplateCanvas* canvas, const wxString& type); + virtual void OnNewCustomCatClassifA(); virtual void OnCustomCatClassifA(const wxString& cc_title); virtual void OnThemelessMap(); diff --git a/GdaConst.cpp b/GdaConst.cpp index ec483dfee..486f00d6e 100644 --- a/GdaConst.cpp +++ b/GdaConst.cpp @@ -621,6 +621,16 @@ void GdaConst::init() datasrc_field_illegal_regex[ds_xls] = default_field_name_illegal_regex; datasrc_field_casesensitive[ds_xls] = false; + datasrc_str_to_type["XLSX"] = ds_xlsx; + datasrc_type_to_prefix[ds_xlsx] = ""; + datasrc_type_to_fullname[ds_xlsx] = "Microsoft Excel Extensions"; + datasrc_table_lens[ds_xlsx] = 128; + datasrc_field_lens[ds_xlsx] = 10; + datasrc_field_warning[ds_xlsx] = default_field_warning; + datasrc_field_regex[ds_xlsx] = default_field_name_regex; + datasrc_field_illegal_regex[ds_xlsx] = default_field_name_illegal_regex; + datasrc_field_casesensitive[ds_xlsx] = false; + datasrc_str_to_type["ODS"] = ds_ods; datasrc_type_to_prefix[ds_ods] = ""; datasrc_type_to_fullname[ds_ods] = "Open Office Spreadsheet"; diff --git a/ShapeOperations/OGRDataAdapter.cpp b/ShapeOperations/OGRDataAdapter.cpp index 2f66b092d..1ecf79f72 100644 --- a/ShapeOperations/OGRDataAdapter.cpp +++ b/ShapeOperations/OGRDataAdapter.cpp @@ -297,7 +297,10 @@ OGRDataAdapter::ExportDataSource(string o_ds_format, // field identifier: a pair value to indicate how to // retreive real field name and cell value for time-enabled table typedef pair field_idn; - map field_dict; + + vector field_idn_s; + vector field_name_s; + // check field names first if ( table != NULL ) { @@ -316,7 +319,8 @@ OGRDataAdapter::ExportDataSource(string o_ds_format, throw GdaException(msg.mb_str(), GdaException::FIELD_NAME_EMPTY); } all_fnames.push_back(fname); - field_dict[fname] = make_pair(id, t); + field_idn_s.push_back(make_pair(id, t)); + field_name_s.push_back(fname); } } else { wxString fname = table->GetColName(id); @@ -326,7 +330,8 @@ OGRDataAdapter::ExportDataSource(string o_ds_format, throw GdaException(msg.mb_str(), GdaException::FIELD_NAME_EMPTY); } all_fnames.push_back(fname); - field_dict[fname] = make_pair(id, 0); + field_idn_s.push_back(make_pair(id, 0)); + field_name_s.push_back(fname); } } @@ -337,24 +342,20 @@ OGRDataAdapter::ExportDataSource(string o_ds_format, // cancel at Field Name Correction return NULL; } - // record which field name needs to be updated - map modified_field_dict; - map::iterator iter; - modified_field_dict = fname_correct_dlg.GetMergedFieldNameDict(); - // update changed fields - for (iter = modified_field_dict.begin(); - iter != modified_field_dict.end(); ++iter ) - { - wxString old_name = iter->first; - wxString new_name = iter->second; - if ( old_name == new_name ) + + vector new_field_name_s = fname_correct_dlg.GetNewFieldNames(); + + for (size_t i=0; iRenameSimpleCol(fld_id.first, fld_id.second, new_name); + } + field_idn fld_idn = field_idn_s[i]; + table->RenameSimpleCol(fld_idn.first, fld_idn.second, new_fname); } } - // clean field_dict if any field name changed - field_dict.clear(); } // create new OGRLayerProxy @@ -365,16 +366,16 @@ OGRDataAdapter::ExportDataSource(string o_ds_format, export_ds = new OGRDatasourceProxy(o_ds_name, ds_type, true); new_layer_proxy = export_ds->CreateLayer( o_layer_name, geom_type, ogr_geometries, table, - field_dict, selected_rows, spatial_ref); + selected_rows, spatial_ref); } else { export_ds = new OGRDatasourceProxy(o_ds_format, o_ds_name); new_layer_proxy = export_ds->CreateLayer( o_layer_name, geom_type, ogr_geometries, table, - field_dict, selected_rows, spatial_ref); + selected_rows, spatial_ref); } export_thread = new boost::thread(boost::bind(&OGRLayerProxy::AddFeatures, - new_layer_proxy, ogr_geometries, table, field_dict, selected_rows)); + new_layer_proxy, ogr_geometries, table, selected_rows)); return new_layer_proxy; } diff --git a/ShapeOperations/OGRDatasourceProxy.cpp b/ShapeOperations/OGRDatasourceProxy.cpp index 3af96a247..52fea4e4a 100644 --- a/ShapeOperations/OGRDatasourceProxy.cpp +++ b/ShapeOperations/OGRDatasourceProxy.cpp @@ -326,7 +326,6 @@ OGRDatasourceProxy::CreateLayer(string layer_name, OGRwkbGeometryType eGType, vector& geometries, TableInterface* table, - map >& field_dict, vector& selected_rows, OGRSpatialReference* spatial_ref) { @@ -342,7 +341,7 @@ OGRDatasourceProxy::CreateLayer(string layer_name, // PRECISION is for database e.g. MSSQL // LAUNDER is for database: rename desired field name - char* papszLCO[50] = {"OVERWRITE=yes", "PRECISION=no", "LAUNDER=no"}; + char* papszLCO[50] = {"OVERWRITE=yes", "PRECISION=no", "LAUNDER=yes"}; OGRLayer *poDstLayer = ds->CreateLayer(layer_name.c_str(), poOutputSRS, eGType, papszLCO); @@ -361,49 +360,46 @@ OGRDatasourceProxy::CreateLayer(string layer_name, table->FillColIdMap(col_id_map); int time_steps = table->GetTimeSteps(); + for ( int id=0; id < table->GetNumberCols(); id++ ) { + for ( int t=0; t < time_steps; t++ ) { + wxString fname = table->GetColName(col_id_map[id], t); if (fname.empty()) { error_message << "Can't create layer \"" << layer_name << "\" with empty field name."; throw GdaException(error_message.str().c_str()); } - field_it = field_dict.find(fname); - if (field_it == field_dict.end()) { - // a unique field - OGRFieldType ogr_type; - int ogr_fwidth = table->GetColLength(col_id_map[id], t); - int ogr_fprecision = table->GetColDecimals(col_id_map[id], t); - GdaConst::FieldType ftype = table->GetColType(col_id_map[id], t); - if (ftype == GdaConst::string_type){ - ogr_type = OFTString; - } else if (ftype == GdaConst::long64_type){ - ogr_type = OFTInteger64; - } else if (ftype == GdaConst::double_type){ - ogr_type = OFTReal; - } else if (ftype == GdaConst::date_type){ - ogr_type = OFTDate; - } else { - ogr_type = OFTString; - } - OGRFieldDefn oField(fname, ogr_type); - oField.SetWidth(ogr_fwidth); - if ( ogr_fprecision>0 ) { - oField.SetPrecision(ogr_fprecision); - } - if( poDstLayer->CreateField( &oField ) != OGRERR_NONE ) { - error_message << "Creating a field failed.\n\nDetails:" << CPLGetLastErrorMsg(); - throw GdaException(error_message.str().c_str()); - } - // record in field_dict - field_dict[fname] = make_pair(col_id_map[id], t); + + OGRFieldType ogr_type; + int ogr_fwidth = table->GetColLength(col_id_map[id], t); + int ogr_fprecision = table->GetColDecimals(col_id_map[id], t); + GdaConst::FieldType ftype = table->GetColType(col_id_map[id], t); + if (ftype == GdaConst::string_type){ + ogr_type = OFTString; + } else if (ftype == GdaConst::long64_type){ + ogr_type = OFTInteger64; + } else if (ftype == GdaConst::double_type){ + ogr_type = OFTReal; + } else if (ftype == GdaConst::date_type){ + ogr_type = OFTDate; + } else { + ogr_type = OFTString; + } + OGRFieldDefn oField(fname, ogr_type); + oField.SetWidth(ogr_fwidth); + if ( ogr_fprecision>0 ) { + oField.SetPrecision(ogr_fprecision); + } + if( poDstLayer->CreateField( &oField ) != OGRERR_NONE ) { + error_message << "Creating a field failed.\n\nDetails:" << CPLGetLastErrorMsg(); + throw GdaException(error_message.str().c_str()); } } } } OGRLayerProxy* layer = new OGRLayerProxy(poDstLayer, ds_type, eGType); - //layer->AddFeatures(geometries, table, field_dict, selected_rows); layer_pool[layer_name] = layer; return layer; diff --git a/ShapeOperations/OGRDatasourceProxy.h b/ShapeOperations/OGRDatasourceProxy.h index 303312ff7..f0a536b7f 100644 --- a/ShapeOperations/OGRDatasourceProxy.h +++ b/ShapeOperations/OGRDatasourceProxy.h @@ -119,7 +119,6 @@ class OGRDatasourceProxy { OGRwkbGeometryType eGType, vector& geometries, TableInterface* table, - map >& field_dict, vector& selected_rows, OGRSpatialReference* spatial_ref); diff --git a/ShapeOperations/OGRLayerProxy.cpp b/ShapeOperations/OGRLayerProxy.cpp index ab687df3e..866b149c2 100644 --- a/ShapeOperations/OGRLayerProxy.cpp +++ b/ShapeOperations/OGRLayerProxy.cpp @@ -41,9 +41,11 @@ using namespace std; /** * Create a OGRLayerProxy from an existing OGRLayer */ -OGRLayerProxy::OGRLayerProxy(string layer_name, OGRLayer* _layer, - GdaConst::DataSourceType _ds_type, bool isNew) -: n_rows(0), n_cols(0), name(layer_name), ds_type(_ds_type), layer(_layer), +OGRLayerProxy::OGRLayerProxy(string layer_name, + OGRLayer* _layer, + GdaConst::DataSourceType _ds_type, + bool isNew) +: n_rows(0), n_cols(0), name(layer_name),ds_type(_ds_type), layer(_layer), load_progress(0), stop_reading(false), export_progress(0) { if (!isNew) n_rows = layer->GetFeatureCount(); @@ -365,49 +367,63 @@ bool OGRLayerProxy::UpdateColumn(int col_idx, vector &vals) void OGRLayerProxy::AddFeatures(vector& geometries, TableInterface* table, - map >& field_dict, vector& selected_rows) { export_progress = 0; stop_exporting = false; - map >::iterator field_it; + // Create features in memory first for (size_t i=0; iSetGeometryDirectly( geometries[i] ); } data.push_back(poFeature); } + int export_size = data.size()==0 ? table->GetNumberRows() : data.size(); export_progress = export_size / 4; - // set other data + // Fill the feature with content if (table != NULL) { + // fields already have been created by OGRDatasourceProxy::CreateLayer() for (size_t j=0; j< fields.size(); j++) { + wxString fname = fields[j]->GetName(); - pair field_idn = field_dict[fname]; - int col_pos = field_idn.first; - int time_step = field_idn.second; - GdaConst::FieldType ftype = table->GetColType(col_pos, time_step); + GdaConst::FieldType ftype = fields[j]->GetType(); + + // get underneath column position (no group and time =0) + int col_pos = table->GetColIdx(fname); + int time_step = 0; + if ( ftype == GdaConst::long64_type) { + vector col_data; table->GetColData(col_pos, time_step, col_data); + for (size_t k=0; kSetField(j, (GIntBig)(col_data[selected_rows[k]])); if (stop_exporting) return; } + } else if (ftype == GdaConst::double_type) { + vector col_data; table->GetColData(col_pos, time_step, col_data); + for (size_t k=0; kSetField(j, col_data[ selected_rows[k] ]); if (stop_exporting) return; } + } else if (ftype == GdaConst::date_type) { + vector col_data; table->GetColData(col_pos, time_step, col_data); + for (size_t k=0; k& geometries, data[k]->SetField(j, year, month, day); if (stop_exporting) return; } + } else if (ftype == GdaConst::placeholder_type) { // KML case: there are by default two fields: // [Name, Description], so if placeholder that // means table is empty. Then do nothing + } else { // others are treated as string_type // XXX encodings vector col_data; table->GetColData(col_pos, time_step, col_data); + if (ds_type == GdaConst::ds_csv) { for (int m=0; mSetField(j, col_data[ selected_rows[k] ].mb_str()); if (stop_exporting) return; diff --git a/ShapeOperations/OGRLayerProxy.h b/ShapeOperations/OGRLayerProxy.h index a0e44d897..bb49a45fa 100644 --- a/ShapeOperations/OGRLayerProxy.h +++ b/ShapeOperations/OGRLayerProxy.h @@ -135,7 +135,6 @@ class OGRLayerProxy { */ void AddFeatures(std::vector& geometries, TableInterface* table, - std::map >& field_dict, std::vector& selected_rows); /** * Read geometries and save to Shapefile::Main data structure. diff --git a/TemplateCanvas.h b/TemplateCanvas.h index e19a3a814..e0c6d6a46 100644 --- a/TemplateCanvas.h +++ b/TemplateCanvas.h @@ -385,6 +385,8 @@ class TemplateCanvas : public wxScrolledWindow, public HighlightStateObserver public: void RenderToDC(wxDC &dc, bool disable_crosshatch_brush = true); + const wxBitmap* GetBaseLayer() { return basemap_bm; } + const wxBitmap* GetLayer0() { return layer0_bm; } const wxBitmap* GetLayer1() { return layer1_bm; } const wxBitmap* GetLayer2() { return layer2_bm; } void deleteLayerBms(); diff --git a/version.h b/version.h index e98aa7c7b..8b0ad9a8f 100644 --- a/version.h +++ b/version.h @@ -1,11 +1,11 @@ namespace Gda { const int version_major = 1; const int version_minor = 8; - const int version_build = 7; - const int version_subbuild = 11; + const int version_build = 9; + const int version_subbuild = 1; const int version_year = 2016; - const int version_month = 5; - const int version_day = 26; + const int version_month = 7; + const int version_day = 8; const int version_night = 0; const int version_type = 1; // 0: alpha, 1: beta, 2: release }