Geoinformatica  0.90
New.pm
Go to the documentation of this file.
1 package Geo::Vector::Layer::Dialogs::New;
2 # @brief
3 
4 use strict;
5 use warnings;
6 use Carp;
7 use Glib qw/TRUE FALSE/;
8 use Gtk2::Ex::Geo::Dialogs qw/:all/;
9 use Geo::GDAL;
10 
11 ## @ignore
12 sub open {
13  my($gui) = @_;
14  my $self = { gui => $gui };
15 
16  # bootstrap:
17  my($dialog, $boot) = Gtk2::Ex::Geo::Layer::bootstrap_dialog
18  ($self, $gui, 'new_dialog', "Create new vector",
19  {
20  new_dialog => [delete_event => \&cancel_new_copy, $self],
21  new_vector_add_button => [clicked=>\&add_field_to_schema, $self],
22  new_vector_delete_button => [clicked=>\&delete_field_from_schema, $self],
23  new_vector_cancel_button => [clicked => \&cancel_new_vector, $self],
24  new_vector_ok_button => [clicked => \&ok_new_vector, $self],
25  },
26  [
27  'new_vector_class_combobox',
28  'new_vector_driver_combobox',
29  'new_vector_data_source_combobox',
30  'new_vector_geometry_type_combobox'
31  ]
32  );
33 
34  if ($boot) {
35  my $combo = $dialog->get_widget('new_vector_class_combobox');
36  my $model = $combo->get_model();
37  for my $n ('OGR Layer', 'Feature collection') {
38  $model->set ($model->append, 0, $n);
39  }
40  $combo->set_active(0);
41 
42  $combo = $dialog->get_widget('new_vector_driver_combobox');
43  $model = $combo->get_model();
44  $model->set ($model->append, 0, 'Memory');
45  for my $driver (Geo::OGR::Drivers()) {
46  my $n = $driver->FormatName;
47  $n = $driver->GetName unless $n;
48  $self->{drivers}{$n} = $driver;
49  next if $n eq 'Memory';
50  $model->set ($model->append, 0, $n);
51  }
52  $combo->set_active(0);
53 
54  $combo = $dialog->get_widget('new_vector_data_source_combobox');
55  $model = $combo->get_model();
56  $model->set ($model->append, 0, '');
57  for my $data_source (sort keys %{$gui->{resources}{datasources}}) {
58  $model->set ($model->append, 0, $data_source);
59  }
60  $combo->set_active(0);
61 
62  my $entry = $self->{new_dialog}->get_widget('new_vector_folder_entry');
63  $entry->set_text('.');
64 
65  # replace with @Geo::OGR::Geometry::GEOMETRY_TYPES
66  # when new GDAL comes out
67 
68  my @GEOMETRY_TYPES = qw/Unknown
69  Point LineString Polygon
70  MultiPoint MultiLineString MultiPolygon GeometryCollection
71  None LinearRing
72  Point25D LineString25D Polygon25D
73  MultiPoint25D MultiLineString25D MultiPolygon25D GeometryCollection25D/;
74 
75  $combo = $dialog->get_widget('new_vector_geometry_type_combobox');
76  $model = $combo->get_model();
77  for my $type (@GEOMETRY_TYPES) {
78  $model->set ($model->append, 0, $type);
79  }
80  $combo->set_active(0);
81  }
82 
83  $dialog->get_widget('new_vector_open_button')
84  ->signal_connect( clicked => sub {
85  my(undef, $self) = @_;
86  my $entry = $self->{new_dialog}->get_widget('new_vector_folder_entry');
87  file_chooser('Select folder', 'select_folder', $entry);
88  }, $self );
89 
90  my $name = 'a';
91  for my $n ('a'..'z') {
92  $name = $n, last unless $gui->layer($n);
93  }
94  $dialog->get_widget('new_vector_layer_entry')->set_text($name);
95  $self->{schema} = schema_to_treeview($self, $dialog->get_widget('new_vector_schema_treeview'), 1);
96  return $dialog->get_widget('new_dialog');
97 }
98 
99 sub schema_to_treeview {
100  my($self, $treeview, $editable, $schema) = @_;
101 
102  # remove existing columns from treeview first
103  my $column;
104  while ($column = $treeview->get_column(0)) {
105  $treeview->remove_column($column);
106  }
107 
108  my $model = Gtk2::TreeStore->new(qw/Glib::String Glib::String Glib::String Glib::Int Glib::Int/);
109  $treeview->set_model($model);
110 
111  my $i = 0;
112  my $cell = Gtk2::CellRendererText->new;
113  $cell->set(editable => $editable);
114  $cell->signal_connect(edited => \&schema_changed, [$self, $i]);
115  $column = Gtk2::TreeViewColumn->new_with_attributes('Name', $cell, text => $i++);
116  $treeview->append_column($column);
117 
118  # replace with @Geo::OGR::FieldDefn::FIELD_TYPES
119  # and @Geo::OGR::FieldDefn::JUSTIFY_TYPES
120  # when new GDAL comes out
121 
122  my @FIELD_TYPES = qw/Integer IntegerList Real RealList String StringList
123  WideString WideStringList Binary Date Time DateTime/;
124  my @JUSTIFY_TYPES = qw/Undefined Left Right/;
125 
126  $cell = Gtk2::CellRendererCombo->new;
127  $cell->set(editable => $editable);
128  $cell->set(text_column => 0);
129  $cell->set(has_entry => 0);
130  $cell->signal_connect(edited => \&schema_changed, [$self, $i]);
131  my $m = Gtk2::ListStore->new('Glib::String');
132  for my $type (@FIELD_TYPES) {
133  $m->set($m->append, 0, $type);
134  }
135  $cell->set(model=>$m);
136  $column = Gtk2::TreeViewColumn->new_with_attributes('Type', $cell, text => $i++);
137  $treeview->append_column($column);
138 
139  $cell = Gtk2::CellRendererCombo->new;
140  $cell->set(editable => $editable);
141  $cell->set(text_column => 0);
142  $cell->set(has_entry => 0);
143  $cell->signal_connect(edited => \&schema_changed, [$self, $i]);
144  $m = Gtk2::ListStore->new('Glib::String');
145  for my $type (@JUSTIFY_TYPES) {
146  $m->set($m->append, 0, $type);
147  }
148  $cell->set(model=>$m);
149  $column = Gtk2::TreeViewColumn->new_with_attributes('Justify', $cell, text => $i++);
150  $treeview->append_column($column);
151 
152  $cell = Gtk2::CellRendererText->new;
153  $cell->set(editable => $editable);
154  $cell->signal_connect(edited => \&schema_changed, [$self, $i]);
155  $column = Gtk2::TreeViewColumn->new_with_attributes('Width', $cell, text => $i++);
156  $treeview->append_column($column);
157 
158  $cell = Gtk2::CellRendererText->new;
159  $cell->set(editable => $editable);
160  $cell->signal_connect(edited => \&schema_changed, [$self, $i]);
161  $column = Gtk2::TreeViewColumn->new_with_attributes('Precision', $cell, text => $i++);
162  $treeview->append_column($column);
163 
164  if ($schema) {
165  for my $field ( $schema->fields ) {
166  next if $field->{Name} =~ /^\./;
167  my $iter = $model->append(undef);
168  my @set = ($iter);
169  my $i = 0;
170  push @set, ($i++, $field->{Name});
171  push @set, ($i++, $field->{Type});
172  push @set, ($i++, $field->{Justify});
173  push @set, ($i++, $field->{Width});
174  push @set, ($i++, $field->{Precision});
175  $model->set(@set);
176  }
177  }
178 
179  return $model;
180 }
181 
182 sub schema_changed {
183  my($cell, $path, $new_value, $data) = @_;
184  my($self, $column) = @$data;
185  my $iter = $self->{schema}->get_iter_from_string($path);
186  my @set = ($iter, $column, $new_value);
187  $self->{schema}->set(@set);
188 }
189 
190 ## @ignore
191 sub cancel_new_vector {
192  my $self = pop;
193  $self->{new_dialog}->get_widget('new_dialog')->destroy;
194 }
195 
196 ## @ignore
197 sub ok_new_vector {
198  my $self = pop;
199  my $d = $self->{new_dialog};
200  my $layer;
201  my $class = get_value_from_combo($d, 'new_vector_class_combobox');
202  my $name = $d->get_widget('new_vector_layer_entry')->get_text;
203  $name = 'x' unless $name;
204  if ($class eq 'Feature collection') {
205  $self->{gui}->add_layer(Geo::Vector->new(features=>[]), $name, 1);
206  $self->{new_dialog}->get_widget('new_dialog')->destroy;
207  return;
208  }
209  my $driver = get_value_from_combo($d, 'new_vector_driver_combobox');
210  $driver = $self->{drivers}{$driver};
211  my $create_options = $d->get_widget('new_vector_create_options_entry')->get_text;
212  $create_options = {split(/[(=>),]/,$create_options)};
213  my $data_source = get_value_from_combo($d, 'new_vector_data_source_combobox');
214  $data_source = $d->get_widget('new_vector_folder_entry')->get_text unless $data_source;
215  my $layer_options = $d->get_widget('new_vector_layer_options_entry')->get_text;
216  my $geometry_type = get_value_from_combo($d, 'new_vector_geometry_type_combobox') || 'Unknown';
217  my $srs = $d->get_widget('new_vector_srs_entry')->get_text;
218  my %schema = ( GeometryType => $geometry_type, Fields => [] );
219  $self->{schema}->foreach(sub {
220  my($model, $path, $iter) = @_;
221  my @row = $model->get($iter);
222  push @{$schema{Fields}},
223  { Name => $row[0],
224  Type => $row[1],
225  Justify => $row[2],
226  Width => $row[3],
227  Precision => $row[4]
228  };
229  0;
230  });
231  eval {
232  $layer = Geo::Vector::Layer->new
233  ( driver => $driver,
234  create_options => $create_options,
235  data_source => $data_source,
236  create => $name,
237  layer_options => $layer_options,
238  geometry_type => $geometry_type,
239  srs => $srs,
240  schema => \%schema
241  );
242  };
243  if ($@) {
244  my $err = $@;
245  if ($err) {
246  $err =~ s/\n/ /g;
247  $err =~ s/\s+$//;
248  $err =~ s/\s+/ /g;
249  $err =~ s/^\s+$//;
250  } else {
251  $err = "unknown error";
252  }
253  $self->{gui}->message("Could not create a vector layer: $err");
254  return;
255  }
256  $self->{gui}->add_layer($layer, $name, 1);
257  $self->{new_dialog}->get_widget('new_dialog')->destroy;
258 }
259 
260 ## @ignore
261 sub add_field_to_schema {
262  my $self = pop;
263  my $iter = $self->{schema}->append(undef);
264  my @set = ($iter);
265  my $i = 0;
266  push @set, ($i++, 'name');
267  push @set, ($i++, 'Integer');
268  push @set, ($i++, 'Undefined');
269  push @set, ($i++, 8);
270  push @set, ($i++, 0);
271  $self->{schema}->set(@set);
272 }
273 
274 ## @ignore
275 sub delete_field_from_schema {
276  my $self = pop;
277  my $treeview = $self->{new_dialog}->get_widget('new_vector_schema_treeview');
278  my($path, $focus_column) = $treeview->get_cursor;
279  return unless $path;
280  my $iter = $self->{schema}->get_iter($path);
281  $self->{schema}->remove($iter);
282 }
283 
284 1;
public method bootstrap_dialog()
public method new()
Upgrade Geo::Vector, feature and geometry objects to Geo::Vector::Layers.
Definition: Layer.pm:72
A geospatial layer that consists of Geo::OGR::Features.
Definition: Vector.pm:176