Geoinformatica  0.90
Copy.pm
Go to the documentation of this file.
1 package Geo::Vector::Layer::Dialogs::Copy;
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::Vector::Layer::Dialogs qw/:all/;
10 use Geo::Raster::Layer qw /:all/;
11 
12 ## @ignore
13 # copy dialog
14 sub open {
15  my($self, $gui) = @_;
16 
17  # bootstrap:
18  my($dialog, $boot) = $self->bootstrap_dialog
19  ($gui, 'copy_dialog', "Copy from ".$self->name,
20  {
21  copy_dialog => [delete_event => \&cancel_copy, [$self, $gui]],
22  copy_cancel_button => [clicked => \&cancel_copy, [$self, $gui]],
23  copy_ok_button => [clicked => \&do_copy, [$self, $gui, 1]],
24  from_EPSG_entry => [changed => \&Geo::Raster::Layer::epsg_help],
25  to_EPSG_entry => [changed => \&Geo::Raster::Layer::epsg_help],
26  copy_add_button => [clicked => \&add_to_mappings, $self],
27  copy_delete_button => [clicked => \&delete_from_mappings, $self],
28  copy_driver_combobox => [changed => \&copy_driver_changed, $self],
29  copy_name_comboboxentry => [changed => \&copy_into_changed, [$self, $gui]],
30  },
31  [
32  'copy_driver_combobox',
33  'copy_datasource_combobox',
34  'copy_name_comboboxentry'
35  ]
36  );
37 
38  if ($boot) {
39  my $from = $dialog->get_widget('from_EPSG_entry');
40  my $auto = Gtk2::EntryCompletion->new;
41  $auto->set_match_func(sub {1});
42  my $list = Gtk2::ListStore->new('Glib::String');
43  $auto->set_model($list);
44  $auto->set_text_column(0);
45  $from->set_completion($auto);
46 
47  my $to = $dialog->get_widget('to_EPSG_entry');
48  $auto = Gtk2::EntryCompletion->new;
49  $auto->set_match_func(sub {1});
50  $list = Gtk2::ListStore->new('Glib::String');
51  $auto->set_model($list);
52  $auto->set_text_column(0);
53  $to->set_completion($auto);
54 
55  $dialog->get_widget('copy_datasource_button')
56  ->signal_connect( clicked=> sub {
57  my(undef, $self) = @_;
58  my $entry = $self->{copy_dialog}->get_widget('copy_datasource_entry');
59  file_chooser('Select folder', 'select_folder', $entry);
60  }, $self);
61  }
62 
63  my $from = $dialog->get_widget('from_EPSG_entry');
64  my $srs = $self->GetSpatialRef;
65  if ($srs) {
66  my $code = $srs->GetAuthorityCode(undef);
67  my $name = $srs->GetAuthorityName(undef);
68  if ($code and $name eq 'EPSG') {
70  $from->set_text($Geo::Raster::Layer::EPSG{$code});
71  }
72  }
73 
74  my $combo = $dialog->get_widget('copy_driver_combobox');
75  my $model = $combo->get_model();
76  $model->clear;
77  my $i = 1;
78  my $active = 0;
79  $model->set($model->append, 0, ''); # create into existing data source
80  for my $driver (Geo::OGR::Drivers) {
81  next unless $driver->TestCapability('CreateDataSource');
82  my $name = $driver->GetName;
83  $active = $i if $name eq 'Memory';
84  $model->set($model->append, 0, $name);
85  $i++;
86  }
87  $combo->set_active($active);
88  copy_driver_changed($combo, $self);
89 
90  $combo = $dialog->get_widget('copy_datasource_combobox');
91  $model = $combo->get_model();
92  $model->clear;
93  $model->set($model->append, 0, '');
94  for my $data_source (sort keys %{$self->{gui}{resources}{datasources}}) {
95  $model->set ($model->append, 0, $data_source);
96  }
97  $combo->set_active(0);
98 
99  $combo = $dialog->get_widget('copy_name_comboboxentry');
100  $model = $combo->get_model();
101  $model->clear;
102  for my $layer (@{$gui->{overlay}->{layers}}) {
103  my $n = $layer->name();
104  next unless $layer->isa('Geo::Vector');
105  next unless $layer->{update};
106  next if $n eq $self->name();
107  $model->set($model->append, 0, $n);
108  }
109  $combo->child->set_text('copy');
110  $combo->set_text_column(0);
111 
112  $dialog->get_widget('copy_datasource_entry')->set_text('');
113  my $s = $self->selected_features;
114  $dialog->get_widget('copy_count_label')->set_label($#$s+1);
115 
116  copy_into_changed(undef, [$self, $gui]);
117 }
118 
119 ## @ignore
120 sub copy_driver_changed {
121  my($combo, $self) = @_;
122  my $dialog = $self->{copy_dialog};
123  my $active = $combo->get_active();
124  return if $active < 0;
125  my $model = $combo->get_model;
126  my $iter = $model->get_iter_from_string($active);
127  my $name = $model->get($iter, 0);
128  for my $w ('copy_datasource_combobox','copy_datasource_button',
129  'copy_file_source_label','copy_non_file_source_label',
130  'copy_datasource_entry') {
131  $dialog->get_widget($w)->set_sensitive($name ne 'Memory');
132  }
133 }
134 
135 ##@ignore
136 sub do_copy {
137  my($self, $gui) = @{$_[1]};
138  my $dialog = $self->{copy_dialog};
139 
140  my %params = ( selected_features => $self->selected_features )
141  unless $dialog->get_widget('copy_all_checkbutton')->get_active;
142 
143  my $into = $dialog->get_widget('copy_name_comboboxentry')->get_active_text;
144  croak "Store into?" unless $into;
145  my $into_layer = $gui->layer($into);
146  if ($into_layer) {
147  croak $into_layer->name." is not a vector layer" unless $into_layer->isa('Geo::Vector');
148  } else {
149  my $combo = $dialog->get_widget('copy_datasource_combobox');
150  my $active = $combo->get_active();
151  if ($active > 0) {
152  my $model = $combo->get_model;
153  my $iter = $model->get_iter_from_string($active);
154  my $store = $model->get($iter, 0);
155  $params{data_source} = $self->{gui}{resources}{datasources}{$store};
156  } else {
157  $params{data_source} = $dialog->get_widget('copy_datasource_entry')->get_text;
158  $params{driver} = $dialog->get_widget('copy_driver_combobox')->get_active_text;
159  }
160  $params{create} = $into;
161  my $layers;
162  $params{data_source} = 'mem' if $params{driver} eq 'Memory';
163  eval {
164  $layers = Geo::Vector::layers($params{driver}, $params{data_source});
165  };
166  if ($layers) {
167  for my $l (@$layers) {
168  croak "Data source '$params{data_source}' already contains a layer with name '$params{create}'."
169  if ($l->{Name} eq $params{create});
170  }
171  }
172  }
173 
174  my $from = $1 if $dialog->get_widget('from_EPSG_entry')->get_text =~ /\[(\d+)\]/;
175  my $to = $1 if $dialog->get_widget('to_EPSG_entry')->get_text =~ /\[(\d+)\]/;
176  my $ct;
177  my $p = $dialog->get_widget('copy_projection_checkbutton')->get_active;
178  #print STDERR "do proj: $p\n";
179  if ($p) {
180  if ($Geo::Raster::Layer::EPSG{$from} and $Geo::Raster::Layer::EPSG{$to}) {
181  my $src = Geo::OSR::SpatialReference->create( EPSG => $from );
182  my $dst = Geo::OSR::SpatialReference->create( EPSG => $to );
183  eval {
184  $ct = Geo::OSR::CoordinateTransformation->new($src, $dst);
185  };
186  }
187  #print STDERR "ct=$ct\n";
188  if ($@ or !$ct) {
189  $@ = '' unless $@;
190  $@ = ": $@" if $@;
191  $gui->message("can't create coordinate transformation from $from to $to: $@");
192  return;
193  }
194  $params{transformation} = $ct;
195  }
196 
197  unless ($into_layer) {
198 
199  my $new_layer;
200  eval {
201  $new_layer = $self->copy(%params);
202  };
203  if ($@ or !$new_layer) {
204  $gui->message("can't copy: $@");
205  return;
206  }
207  $gui->add_layer($new_layer, $params{create}, 1);
208  #$gui->set_layer($new_layer);
209  #$gui->{overlay}->render;
210 
211  } else {
212 
213  $into_layer->add($self, %params);
214 
215  }
216 
217  $self->hide_dialog('copy_dialog');
218  $gui->{overlay}->render;
219 }
220 
221 sub mappings_changed {
222  my($cell, $path, $new_value, $data) = @_;
223  my($self, $column) = @$data;
224  my $iter = $self->{mappings}->get_iter_from_string($path);
225  my @set = ($iter, $column, $new_value);
226  $self->{mappings}->set(@set);
227 }
228 
229 ##@ignore
230 sub cancel_copy {
231  my($self, $gui);
232  for (@_) {
233  next unless ref eq 'ARRAY';
234  ($self, $gui) = @{$_};
235  }
236  $self->hide_dialog('copy_dialog');
237  1;
238 }
239 
240 ##@ignore
241 sub copy_data_source_changed {
242  my $entry = $_[0];
243  my($self, $gui) = @{$_[1]};
244  my $text = $entry->get_text();
245  my $ds;
246  eval {
247  $ds = Geo::OGR::Open($text);
248  };
249  if ($@) {
250  $gui->message("error opening data_source: '$text': $@");
251  return;
252  }
253  return unless $ds; # can't be opened as a data_source
254  my $driver = $ds->GetDriver; # default driver
255  if ($driver) {
256  my $name = $driver->GetName;
257  # get from combo
258  my $combo = $self->{copy_dialog}->get_widget('copy_driver_combobox');
259  my $model = $combo->get_model;
260  my $i = 0;
261  my $iter = $model->get_iter_first;
262  LOOP: {
263  do {
264  my $d = $model->get_value($iter);
265  if ($d eq $name) {
266  $combo->set_active($i);
267  last;
268  }
269  $i++;
270  } while ($iter = $model->iter_next($iter));
271  }
272  }
273 }
274 
275 ## @ignore
276 sub copy_into_changed {
277  my($combo) = @_;
278  my($self, $gui) = @{$_[1]};
279  my $dialog = $self->{copy_dialog};
280  my $into = get_value_from_combo($dialog, 'copy_name_comboboxentry') if $combo;
281  my $into_layer;
282  if ($into) {
283  for my $layer (@{$gui->{overlay}->{layers}}) {
284  my $n = $layer->name();
285  next unless $layer->isa('Geo::Vector');
286  if ($into eq $layer->name()) {
287  $into_layer = $layer;
288  last;
289  }
290  }
291  }
292 
293  my $treeview = $dialog->get_widget('copy_mappings_treeview');
294  my $model = Gtk2::TreeStore->new(qw/Glib::String Glib::String/);
295  $self->{mappings} = $model;
296  $treeview->set_model($model);
297  for ($treeview->get_columns) {
298  $treeview->remove_column($_);
299  }
300 
301  my $i = 0;
302  my $cell = Gtk2::CellRendererCombo->new;
303  $cell->set(editable => 1);
304  $cell->set(text_column => 0);
305  $cell->set(has_entry => 0);
306  $cell->signal_connect(edited => \&mappings_changed, [$self, $i]);
307  my $m = Gtk2::ListStore->new('Glib::String');
308  my $schema = $self->schema;
309  if ($schema) {
310  for my $name ($schema->field_names) {
311  next if $name =~ /^\./;
312  $m->set($m->append, 0, $name);
313  }
314  }
315  $cell->set(model=>$m);
316  my $column = Gtk2::TreeViewColumn->new_with_attributes('From', $cell, text => $i++);
317  $treeview->append_column($column);
318 
319  $cell = Gtk2::CellRendererCombo->new;
320  $cell->set(editable => 1);
321  $cell->set(text_column => 0);
322  $cell->set(has_entry => 1);
323  $cell->signal_connect(edited => \&mappings_changed, [$self, $i]);
324  $m = Gtk2::ListStore->new('Glib::String');
325  if ($into_layer) {
326  my $schema = $into_layer->schema;
327  if ($schema) {
328  for my $name ($schema->field_names) {
329  next if $name =~ /^\./;
330  $m->set($m->append, 0, $name);
331  }
332  }
333  }
334  $cell->set(model=>$m);
335  $column = Gtk2::TreeViewColumn->new_with_attributes('To', $cell, text => $i++);
336  $treeview->append_column($column);
337 
338 }
339 
340 ## @ignore
341 sub add_to_mappings {
342  my $self = pop;
343  my $iter = $self->{mappings}->append(undef);
344  my @set = ($iter);
345  my $i = 0;
346  push @set, ($i++, '');
347  push @set, ($i++, '');
348  $self->{mappings}->set(@set);
349 }
350 
351 ## @ignore
352 sub delete_from_mappings {
353  my $self = pop;
354  my $treeview = $self->{copy_dialog}->get_widget('copy_mappings_treeview');
355  my($path, $focus_column) = $treeview->get_cursor;
356  return unless $path;
357  my $iter = $self->{mappings}->get_iter($path);
358  $self->{mappings}->remove($iter);
359 }
360 
361 1;
A subclass of Gtk2::Ex::Geo::Layer and Geo::Raster.
Definition: Layer.pm:27
public method bootstrap_dialog()
public method epsg_help()
A geospatial layer that consists of Geo::OGR::Features.
Definition: Vector.pm:176