#!/usr/bin/perl # # This script is currently deprecated. # But we will keep it for now, since one might be able to use # part of the code to write a checker to show newly added icons. # exit -1 ##################################################################### # # This script handles the XML-Files for the POI-Types in gpsdrive. # It has to be run from the data directory. # # Default actions, when no options are given: # - Create basic XML-File if none is available # - Search icons directories for PNG files # - Add those files as new POI-Types if they are not yet existent # - Create overview.html from the XML-File to show all # available poi_types and icons. # ##################################################################### # # Scheme for the entries (only poi_type relevant elements are shown): # # # # $SCALE_MIN # $SCALE_MAX # $TITLE # $DESCRIPTION # # ##################################################################### #use diagnostics; use strict; use warnings; use utf8; use IO::File; use File::Find; use File::Copy; use XML::Twig; use Getopt::Std; use Pod::Usage; use Image::Magick; use File::Slurp; use File::Basename; use File::Path; use Data::Dumper; our ($opt_v, $opt_f, $opt_h, $opt_i, $opt_n, $opt_r,$opt_s) = 0; getopts('hvinrsf:') or $opt_h = 1; pod2usage( -exitval => '1', -verbose => '1') if $opt_h; my $file_xml = './icons.xml'; my %ICONS = ('',''); my $i = 0; my $j = 0; my $default_scale_min = 1; my $default_scale_max = 100000; my $default_title_en = ''; my $default_desc_en = ''; my $VERBOSE = $opt_v; my @ALL_TYPES = qw(square.big square.small classic.big classic.small svg svg-twotone japan ); ##################################################################### # # M A I N # # chdir('./map-icons'); unless (-e $file_xml) { create_xml(); # Create a new XML-File if none exists } get_icons(); # read available icons from dirs update_xml(); # parse and update contents of XML-File chdir('..'); exit (0); ##################################################################### # # Parse available XML-File aund update with contents from icons dirs # # sub update_xml { print STDOUT "\n----- Parsing and updating '$file_xml' -----\n"; # Parse XML-File and look for already existing POI-Type entries # my $twig= new XML::Twig ( pretty_print => 'indented', empty_tags => 'normal', comments => 'keep', TwigHandlers => { condition => \&sub_condition # also deletes the entry from %ICONS } ); $twig->parsefile( "$file_xml"); # build the twig my $rules= $twig->root; # get the root of the twig (rules) # Insert new POI-Type entries from hash of available icons # $i = 0; my @tmp_icons = sort(keys(%ICONS)); for my $icon (@tmp_icons) { insert_poi_type($icon,\$rules); $i++; } print STDOUT " New POI-Types added:\t$i\n"; # Print Status for poi_type_ids # my @rule= $rules->children; # get the updated rule list $i = $j = 0; foreach my $entry (@rule) { my $condition=$entry->last_child('condition'); if ( $condition && $condition->{'att'}->{'k'} eq 'poi' ) { $i++; } if ( $condition && $condition->{'att'}->{'k'} eq 'rendering') { $j++; } } print STDOUT " Defined Points of Interest :\t$i\n"; print STDOUT " Defined Map Rendering Icons :\t$j\n"; # Write XML-File containing modified contents # open TMPFILE,">:utf8","./icons.tmp"; select TMPFILE; print "\n"; print "\n"; my $j=1; sub entry_name($){ my $entry = shift; my $condition = $entry->last_child('condition'); return '' if not(defined($condition)); if (($condition->{'att'}->{'k'} eq 'poi') || ($condition->{'att'}->{'k'} eq 'rendering')) { return $condition->{'att'}->{'v'}; } } foreach my $entry (sort {entry_name($a) cmp entry_name($b) } @rule) { my $name = 'unknown'; my $condition=$entry->last_child('condition'); next if not(defined($condition)); if (($condition->{'att'}->{'k'} eq 'poi') || ($condition->{'att'}->{'k'} eq 'rendering')) { $name = $condition->{'att'}->{'v'}; } next if not($opt_i) && $name =~ m/^incomming/; $entry->print; print "\n"; } print "\n"; close TMPFILE; # Create backup copy of old XML-File # #move("$file_xml","$file_xml.bak") or die (" Couldn't create backup file!"); move("./icons.tmp","$file_xml") or die (" Couldn't remove temp file!"); print STDOUT "\n XML-File successfully updated!\n"; $twig->purge; return; # look, if POI-Type already exists in the file by checking for a # known name inside the condition tag. If true, kick it from the icons # hash, because it's not needed anymore. sub sub_condition { my( $twig, $condition)= @_; if (($condition->{'att'}->{'k'} eq 'poi') || ($condition->{'att'}->{'k'} eq 'rendering')) { my $name = $condition->{'att'}->{'v'}; if (exists $ICONS{$name}) { print STDOUT " o \t$name\n" if $VERBOSE; delete $ICONS{"$name"}; } } } } ##################################################################### # # Insert new POI-Type into the file # # sub insert_poi_type { my $name = shift(@_); my $twig_root = shift(@_); my $new_rule = new XML::Twig::Elt( 'rule'); my $new_condition = new XML::Twig::Elt('condition'); if ($name =~ m/^rendering/) { $new_condition->set_att(k=>'rendering'); } else { $new_condition->set_att(k=>'poi'); } $new_condition->set_att(v=>"$name"); my $new_title_en = new XML::Twig::Elt('title',$default_title_en); $new_title_en->set_att(lang=>'en'); my $new_desc_en = new XML::Twig::Elt('description',$default_desc_en); $new_desc_en->set_att(lang=>'en'); my $new_scale_min = new XML::Twig::Elt('scale_min',$default_scale_min); my $new_scale_max = new XML::Twig::Elt('scale_max',$default_scale_max); $new_desc_en->paste('first_child',$new_rule); $new_title_en->paste('first_child',$new_rule); $new_scale_max->paste('first_child',$new_rule); $new_scale_min->paste('first_child',$new_rule); $new_condition->paste('first_child',$new_rule); $new_rule->paste('last_child',$$twig_root); print STDOUT " + \t$name\n" if $VERBOSE; } ##################################################################### # # Get all the available icons in data/icons # # sub get_icons { print STDOUT "\n----- Looking for available icons -----\n"; $i = 0; find( \&format_icons, @ALL_TYPES ); sub format_icons() { my $icon_file = $File::Find::name; if ( $icon_file =~ m/\.svn/ ) { } elsif ( not($opt_i) && $icon_file =~ m/incomming/ ) { print STDOUT "ignore incomming: $icon_file\n" if $VERBOSE; } elsif ( $icon_file =~ m/\.(png|svg)$/ && $icon_file !~ m/empty\.(png|svg)$/ ) { $i++; print STDOUT " Found icon:\t$i\t$icon_file\n" if $VERBOSE; for my $type ( @ALL_TYPES ) { $icon_file =~ s,^$type/,,g; } $icon_file =~ s,\.(png|svg)$,,g; $icon_file =~ s,/,.,g; $ICONS{"$icon_file"} = '1'; } } delete $ICONS{''} if (exists $ICONS{''}); print STDOUT " $i icons for ".keys(%ICONS)." POI-Types found in data/map-icons\n"; } ##################################################################### # # Create a new XML File and fill it with the basic POI-Types # # sub create_xml { print STDOUT "\n----- Creating new basic XML-File \"$file_xml\" -----\n"; print STDOUT "\n ATTENTION: It is possible, that the IDs will change,\n"; print STDOUT "\n so it would be better, if you update an existing icons.xml!\n"; my @poi_types = ( { name => 'unknown', scale_min => '1', scale_max => '50000', description_en => 'Unassigned POI', description_de => 'Nicht zugewiesener POI', title_en => 'Unknown', title_de => 'Unbekannt', }, { name => 'accommodation', scale_min => '1', scale_max => '50000', description_en => 'Places to stay', description_de => 'Hotels, Jugendherbergen, Campingplätze', title_en => 'Accommodation', title_de => 'Unterkunft', }, { name => 'education', scale_min => '1', scale_max => '25000', description_en => 'Schools and other educational facilities', description_de => 'Schulen und andere Bildungseinrichtungen', title_en => 'Education', title_de => 'Bildung', }, { name => 'food', scale_min => '1', scale_max => '25000', description_en => 'Restaurants, Bars, and so on...', description_de => 'Restaurants, Bars, usw.', title_en => 'Food', title_de => 'Speiselokal', }, { name => 'geocache', scale_min => '1', scale_max => '50000', description_en => 'Geocaches', description_de => 'Geocaches', title_en => 'Geocache', title_de => 'Geocache', }, { name => 'health', scale_min => '1', scale_max => '25000', description_en => 'Hospital, Doctor, Pharmacy, etc.', description_de => 'Krankenhäuser, Ärzte, Apotheken', title_en => 'Health', title_de => 'Gesundheit', }, { name => 'money', scale_min => '1', scale_max => '25000', description_en => 'Bank, ATMs, and other money-related places', description_de => 'Banken, Geldautomaten, und ähnliches', title_en => 'Money', title_de => 'Geld', }, { name => 'nautical', scale_min => '1', scale_max => '50000', description_en => 'Special aeronautical Points', description_de => 'Spezielle aeronautische Punkte', title_en => 'aeronautical', title_de => 'aeronautisch', }, { name => 'people', scale_min => '1', scale_max => '50000', description_en => 'Your home, work, friends, and other people', description_de => 'Dein Zuhause, die Arbeitsstelle, Freunde, und andere Personen', title_en => 'People', title_de => 'Person', }, { name => 'places', scale_min => '10000', scale_max => '500000', description_en => 'Settlements, Mountains, and other geographical stuff', description_de => 'Siedlungen, Berggipfel, und anderes geografisches Zeug', title_en => 'Place', title_de => 'Ort', }, { name => 'public', scale_min => '1', scale_max => '25000', description_en => 'Public facilities and Administration', description_de => 'Verwaltung und andere öffentliche Einrichtungen', title_en => 'Public', title_de => 'Öffentlich', }, { name => 'recreation', scale_min => '1', scale_max => '25000', description_en => 'Places used for recreation (no sports)', description_de => 'Freizeiteinrichtungen (kein Sport)', title_en => 'Recreation', title_de => 'Freizeit', }, { name => 'religion', scale_min => '1', scale_max => '25000', description_en => 'Places and facilities related to religion', description_de => 'Kirchen und andere religiöse Einrichtungen', title_en => 'Religion', title_de => 'Religion', }, { name => 'shopping', scale_min => '1', scale_max => '25000', description_en => 'All the places, where you can buy something', description_de => 'Orte, an denen man etwas käuflich erwerben kann', title_en => 'Shopping', title_de => 'Einkaufen', }, { name => 'sightseeing', scale_min => '1', scale_max => '25000', description_en => 'Historic places and other interesting buildings', description_de => 'Historische Orte und andere interessante Bauwerke', title_en => 'Sightseeing', title_de => 'Sehenswürdigkeit', }, { name => 'sports', scale_min => '1', scale_max => '25000', description_en => 'Sports clubs, stadiums, and other sports facilities', description_de => 'Sportplätze und andere sportliche Einrichtungen', title_en => 'Sports', title_de => 'Sport', }, { name => 'transport', scale_min => '1', scale_max => '25000', description_en => 'Airports and public transportation', description_de => 'Flughäfen und öffentliche Transportmittel', title_en => 'Public Transport', title_de => 'Öffentliches Transportmittel', }, { name => 'vehicle', scale_min => '1', scale_max => '25000', description_en => 'Facilites for drivers, like gas stations or parking places', description_de => 'Dinge für Selbstfahrer, z.B. Tankstellen oder Parkplätze', title_en => 'Vehicle', title_de => 'Fahrzeug', }, { name => 'wlan', scale_min => '1', scale_max => '25000', description_en => 'WiFi-related points (Kismet)', description_de => 'Accesspoints und andere WLAN-Einrichtungen (Kismet)', title_en => 'WLAN', title_de => 'WLAN', }, { name => 'misc', scale_min => '1', scale_max => '25000', description_en => 'POIs not suitable for another category, and custom types', description_de => 'Eigenkreationen, und Punkte, die in keine der anderen Kategorien passen', title_en => 'Miscellaneous', title_de => 'Verschiedenes', }, { name => 'waypoint', scale_min => '1', scale_max => '50000', description_en => 'Waypoints, for example to temporarily mark several places', description_de => 'Wegpunkte, um z.B. temporäre Punkte zu markieren', title_en => 'Waypoint', title_de => 'Wegpunkt', }, ); open NEWFILE,">:utf8","./$file_xml"; select NEWFILE; print"\n"; print"\n\n"; foreach (@poi_types) { print" \n"; print" \n"; print" $$_{'scale_min'}\n"; print" $$_{'scale_max'}\n"; print" $$_{'title_de'}\n"; print" $$_{'title_en'}\n"; print" $$_{'description_de'}\n"; print" $$_{'description_en'}\n"; print" \n\n"; print STDOUT " + \t$$_{'name'}\n" if $VERBOSE; } print "\n"; close NEWFILE; if (-e $file_xml) { print STDOUT " New XML-File \"$file_xml\" successfully created!\n"; } else { die " ERROR: Failed in creating new XML-File \"$file_xml\" !\n"; } } __END__ =head1 SYNOPSIS update_icons.pl [-h] [-v] [-i] [-r] [-f XML-FILE] =head1 OPTIONS =over 2 =item B<--h> Show this help =item B<-f> XML-FILE Set file, that holds all the necessary icon and poi_type information. The default file is 'icons.xml'. =item B<-v> Enable verbose output =back