diff options
25 files changed, 2616 insertions, 400 deletions
diff --git a/lib/postrunner/ActivitiesDB.rb b/lib/postrunner/ActivitiesDB.rb index f63e30a..b6516e7 100644 --- a/lib/postrunner/ActivitiesDB.rb +++ b/lib/postrunner/ActivitiesDB.rb @@ -18,12 +18,13 @@ require 'postrunner/BackedUpFile' require 'postrunner/Activity' require 'postrunner/PersonalRecords' require 'postrunner/ActivityListView' +require 'postrunner/ViewButtons' module PostRunner class ActivitiesDB - attr_reader :db_dir, :cfg, :fit_dir, :activities, :records + attr_reader :db_dir, :cfg, :fit_dir, :activities, :records, :views def initialize(db_dir, cfg) @db_dir = db_dir @@ -59,6 +60,14 @@ module PostRunner sync_needed |= !a.fit_activity.nil? end + # Define which View objects the HTML output will contain off. This + # doesn't really belong in ActivitiesDB but for now it's the best place + # to put it. + @views = ViewButtons.new([ + NavButtonDef.new('activities.png', 'index.html'), + NavButtonDef.new('record.png', "records-0.html") + ]) + @records = PersonalRecords.new(self) sync if sync_needed end @@ -164,12 +173,12 @@ module PostRunner def check @records.delete_all_records - @activities.sort! do |a1, a2| + @activities.sort do |a1, a2| a1.timestamp <=> a2.timestamp end.each { |a| a.check } @records.sync # Ensure that HTML index is up-to-date. - ActivityListView.new(self).update_html_index + ActivityListView.new(self).update_index_pages end def ref_by_fit_file(fit_file) @@ -265,7 +274,7 @@ module PostRunner # Show the activity list in a web browser. def show_list_in_browser - ActivityListView.new(self).update_html_index + ActivityListView.new(self).update_index_pages show_in_browser(File.join(@cfg[:html_dir], 'index.html')) end @@ -300,7 +309,7 @@ module PostRunner @activities.each { |a| a.generate_html_view } Log.info "All HTML report files have been re-generated." # (Re-)generate index files. - ActivityListView.new(self).update_html_index + ActivityListView.new(self).update_index_pages Log.info "HTML index files have been updated." end @@ -332,7 +341,7 @@ module PostRunner end @records.sync - ActivityListView.new(self).update_html_index + ActivityListView.new(self).update_index_pages end def create_directory(dir, name) diff --git a/lib/postrunner/Activity.rb b/lib/postrunner/Activity.rb index e0e1e06..b4a38f4 100644 --- a/lib/postrunner/Activity.rb +++ b/lib/postrunner/Activity.rb @@ -312,8 +312,7 @@ module PostRunner def generate_html_view @fit_activity = load_fit_file unless @fit_activity - ActivityView.new(self, @db.cfg[:unit_system], @db.predecessor(self), - @db.successor(self)) + ActivityView.new(self, @db.cfg[:unit_system]) end def activity_type diff --git a/lib/postrunner/ActivityLink.rb b/lib/postrunner/ActivityLink.rb new file mode 100644 index 0000000..9c368b0 --- /dev/null +++ b/lib/postrunner/ActivityLink.rb @@ -0,0 +1,59 @@ +#!/usr/bin/env ruby -w +# encoding: UTF-8 +# +# = ActivityLink.rb -- PostRunner - Manage the data from your Garmin sport devices. +# +# Copyright (c) 2014, 2015 by Chris Schlaeger <cs@taskjuggler.org> +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of version 2 of the GNU General Public License as +# published by the Free Software Foundation. +# + +require 'postrunner/HTMLBuilder' + +module PostRunner + + # Generates the name of an Activity with a link to the ActivityReport. + # Optionally, an icon can be shown for Activities that contain a current + # personal record. + class ActivityLink + + def initialize(activity, show_record_icon = false) + @activity = activity + @show_record_icon = show_record_icon + end + + # Add the ActivityLink as HTML Elements to the document. + # @param doc [HTMLBuilder] XML Document + def to_html(doc) + doc.unique(:activitylink_style) { doc.style(style) } + + doc.a(@activity.name, { :class => 'activity_link', + :href => @activity.fit_file[0..-5] + '.html' }) + if @show_record_icon && @activity.has_records? + doc.img(nil, { :src => 'icons/record-small.png', + :style => 'vertical-align:middle' }) + end + end + + # Convert the ActivityLink into a plain text form. Return the first 20 + # characters of the Activity name. + def to_s + @activity.name[0..19] + end + + private + + def style + <<EOT +.activity_link { + padding: 0px 3px 0px 3px; +} +EOT + end + + end + +end + diff --git a/lib/postrunner/ActivityListView.rb b/lib/postrunner/ActivityListView.rb index 643754b..8027cb0 100644 --- a/lib/postrunner/ActivityListView.rb +++ b/lib/postrunner/ActivityListView.rb @@ -14,35 +14,15 @@ require 'fit4ruby' require 'postrunner/FlexiTable' require 'postrunner/HTMLBuilder' -require 'postrunner/ViewWidgets' +require 'postrunner/ActivityLink' module PostRunner + # Generates a paged list of all Activity objects in the database. HTML and + # plain text output are supported. class ActivityListView - class ActivityLink - - def initialize(activity) - @activity = activity - end - - def to_html(doc) - doc.a(@activity.name, { :class => 'activity_link', - :href => @activity.fit_file[0..-5] + '.html' }) - if @activity.has_records? - doc.img(nil, { :src => 'icons/record-small.png', - :style => 'vertical-align:middle' }) - end - end - - def to_s - @activity.name[0..19] - end - - end - include Fit4Ruby::Converters - include ViewWidgets def initialize(db) @db = db @@ -52,85 +32,42 @@ module PostRunner @last_page = (@db.activities.length - 1) / @page_size end - def update_html_index + def update_index_pages 0.upto(@last_page) do |page_no| @page_no = page_no - generate_html_index_page + generate_html_index_page(page_no) end end - def to_html(doc) - generate_table.to_html(doc) - end - def to_s generate_table.to_s end private - def generate_html_index_page - doc = HTMLBuilder.new + def generate_html_index_page(page_index) + views = @db.views + views.current_page = 'index.html' - doc.html { - head(doc) - body(doc) - } - - write_file(doc) - end + pages = PagingButtons.new((0..@last_page).map do |i| + "index#{i == 0 ? '' : "-#{i}"}.html" + end) + pages.current_page = + "index#{page_index == 0 ? '' : "-#{page_index}"}.html" + @view = View.new("PostRunner Activities", views, pages) - def head(doc) - doc.head { - doc.meta({ 'http-equiv' => 'Content-Type', - 'content' => 'text/html; charset=utf-8' }) - doc.title("PostRunner Activities") - style(doc) - } - end + @view.doc.head { @view.doc.style(style) } + body(@view.doc) - def style(doc) - view_widgets_style(doc) - doc.style(<<EOT -body { - font-family: verdana,arial,sans-serif; - margin: 0px; -} -.main { - text-align: center; -} -.widget_frame { - width: 900px; -} -.activity_link { - padding: 0px 3px 0px 3px; -} -.ft_cell { - height: 30px -} -EOT - ) + output_file = File.join(@db.cfg[:html_dir], pages.current_page) + @view.write(output_file) end def body(doc) - doc.body { - first_page = @page_no == 0 ? nil: 'index.html' - prev_page = @page_no == 0 ? nil : - @page_no == 1 ? 'index.html' : - "index#{@page_no - 1}.html" - prev_page = @page_no == 0 ? nil : - @page_no == 1 ? 'index.html' : - "index#{@page_no - 1}.html" - next_page = @page_no < @last_page ? "index#{@page_no + 1}.html" : nil - last_page = @page_no == @last_page ? nil : "index#{@last_page}.html" - titlebar(doc, first_page, prev_page, nil, next_page, last_page) - + @view.body { doc.div({ :class => 'main' }) { - frame(doc, 'Activities') { - generate_table.to_html(doc) - } + ViewFrame.new('Activities', 900, generate_table).to_html(doc) } - footer(doc) } end @@ -154,7 +91,7 @@ EOT activities.each do |a| t.row([ i += 1, - ActivityLink.new(a), + ActivityLink.new(a, true), a.activity_type, a.timestamp.strftime("%a, %Y %b %d %H:%M"), local_value(a.total_distance, 'm', '%.2f', @@ -168,14 +105,19 @@ EOT t end - def write_file(doc) - output_file = File.join(@db.cfg[:html_dir], - "index#{@page_no == 0 ? '' : @page_no}.html") - begin - File.write(output_file, doc.to_html) - rescue IOError - Log.fatal "Cannot write activity index file '#{output_file}: #{$!}" - end + def style + <<EOT +body { + font-family: verdana,arial,sans-serif; + margin: 0px; +} +.main { + text-align: center; +} +.ft_cell { + height: 30px +} +EOT end def local_value(value, from_unit, format, units) diff --git a/lib/postrunner/ActivitySummary.rb b/lib/postrunner/ActivitySummary.rb index ab283cb..ffb0901 100644 --- a/lib/postrunner/ActivitySummary.rb +++ b/lib/postrunner/ActivitySummary.rb @@ -13,14 +13,13 @@ require 'fit4ruby' require 'postrunner/FlexiTable' -require 'postrunner/ViewWidgets' +require 'postrunner/ViewFrame' module PostRunner class ActivitySummary include Fit4Ruby::Converters - include ViewWidgets def initialize(fit_activity, unit_system, custom_fields) @fit_activity = fit_activity @@ -35,12 +34,9 @@ module PostRunner end def to_html(doc) - frame(doc, "Activity: #{@name}") { - summary.to_html(doc) - } - frame(doc, 'Laps') { - laps.to_html(doc) - } + width = 600 + ViewFrame.new("Activity: #{@name}", width, summary).to_html(doc) + ViewFrame.new('Laps', width, laps).to_html(doc) end private diff --git a/lib/postrunner/ActivityView.rb b/lib/postrunner/ActivityView.rb index fa05e4c..bba1ec7 100644 --- a/lib/postrunner/ActivityView.rb +++ b/lib/postrunner/ActivityView.rb @@ -3,7 +3,7 @@ # # = ActivityView.rb -- PostRunner - Manage the data from your Garmin sport devices. # -# Copyright (c) 2014 by Chris Schlaeger <cs@taskjuggler.org> +# Copyright (c) 2014, 2015 by Chris Schlaeger <cs@taskjuggler.org> # # This program is free software; you can redistribute it and/or modify # it under the terms of version 2 of the GNU General Public License as @@ -12,70 +12,75 @@ require 'fit4ruby' -require 'postrunner/HTMLBuilder' +require 'postrunner/View' require 'postrunner/ActivitySummary' require 'postrunner/DeviceList' require 'postrunner/UserProfileView' -require 'postrunner/ViewWidgets' require 'postrunner/TrackView' require 'postrunner/ChartView' module PostRunner - class ActivityView + class ActivityView < View - include ViewWidgets - - def initialize(activity, unit_system, predecessor, successor) + def initialize(activity, unit_system) @activity = activity + db = @activity.db @unit_system = unit_system - @predecessor = predecessor - @successor = successor - @output_dir = activity.db.cfg[:html_dir] - @output_file = nil - @doc = HTMLBuilder.new + views = db.views + views.current_page = nil + + # Sort activities in reverse order so the newest one is considered the + # last report by the pagin buttons. + activities = db.activities.sort do |a1, a2| + a1.timestamp <=> a2.timestamp + end + + pages = PagingButtons.new(activities.map do |a| + "#{a.fit_file[0..-5]}.html" + end, false) + pages.current_page = "#{@activity.fit_file[0..-5]}.html" + + super("PostRunner Activity: #{@activity.name}", views, pages) generate_html(@doc) - write_file + write(File.join(db.cfg[:html_dir], pages.current_page)) end private def generate_html(doc) - @report = ActivitySummary.new(@activity.fit_activity, @unit_system, - { :name => @activity.name, - :type => @activity.activity_type, - :sub_type => @activity.activity_sub_type - }) - @device_list = DeviceList.new(@activity.fit_activity) - @user_profile = UserProfileView.new(@activity.fit_activity, @unit_system) - @track_view = TrackView.new(@activity) - @chart_view = ChartView.new(@activity, @unit_system) - - doc.html { - head(doc) - body(doc) - } - end - - def head(doc) - doc.head { - doc.meta({ 'http-equiv' => 'Content-Type', - 'content' => 'text/html; charset=utf-8' }) - doc.meta({ 'name' => 'viewport', - 'content' => 'width=device-width, ' + - 'initial-scale=1.0, maximum-scale=1.0, ' + - 'user-scalable=0' }) - doc.title("PostRunner Activity: #{@activity.name}") - view_widgets_style(doc) - @chart_view.head(doc) - @track_view.head(doc) - style(doc) + doc.head { doc.style(style) } + #doc.meta({ 'name' => 'viewport', + # 'content' => 'width=device-width, ' + + # 'initial-scale=1.0, maximum-scale=1.0, ' + + # 'user-scalable=0' }) + + body { + doc.body({ :onload => 'init()' }) { + # The main area with the 2 column layout. + doc.div({ :class => 'main' }) { + doc.div({ :class => 'left_col' }) { + ActivitySummary.new(@activity.fit_activity, @unit_system, + { :name => @activity.name, + :type => @activity.activity_type, + :sub_type => @activity.activity_sub_type + }).to_html(doc) + TrackView.new(@activity).to_html(doc) + DeviceList.new(@activity.fit_activity).to_html(doc) + UserProfileView.new(@activity.fit_activity, @unit_system). + to_html(doc) + } + doc.div({ :class => 'right_col' }) { + ChartView.new(@activity, @unit_system).to_html(doc) + } + } + } } end - def style(doc) - doc.style(<<EOT + def style + <<EOT body { font-family: verdana,arial,sans-serif; margin: 0px; @@ -93,37 +98,6 @@ body { width: 600px; } EOT - ) - end - - def body(doc) - doc.body({ :onload => 'init()' }) { - prev_page = @predecessor ? @predecessor.fit_file[0..-5] + '.html' : nil - next_page = @successor ? @successor.fit_file[0..-5] + '.html' : nil - titlebar(doc, nil, prev_page, 'index.html', next_page) - # The main area with the 2 column layout. - doc.div({ :class => 'main' }) { - doc.div({ :class => 'left_col' }) { - @report.to_html(doc) - @track_view.div(doc) - @device_list.to_html(doc) - @user_profile.to_html(doc) - } - doc.div({ :class => 'right_col' }) { - @chart_view.div(doc) - } - } - footer(doc) - } - end - - def write_file - @output_file = File.join(@output_dir, "#{@activity.fit_file[0..-5]}.html") - begin - File.write(@output_file, @doc.to_html) - rescue IOError - Log.fatal "Cannot write activity view file '#{@output_file}: #{$!}" - end end end diff --git a/lib/postrunner/ChartView.rb b/lib/postrunner/ChartView.rb index 1aa6039..33e413d 100644 --- a/lib/postrunner/ChartView.rb +++ b/lib/postrunner/ChartView.rb @@ -9,14 +9,10 @@ # published by the Free Software Foundation. # -require 'postrunner/ViewWidgets' - module PostRunner class ChartView - include ViewWidgets - def initialize(activity, unit_system) @activity = activity @sport = activity.fit_activity.sessions[0].sport @@ -24,17 +20,19 @@ module PostRunner @empty_charts = {} end - def head(doc) - [ 'jquery/jquery-2.1.1.min.js', 'flot/jquery.flot.js', - 'flot/jquery.flot.time.js' ].each do |js| - doc.script({ 'language' => 'javascript', 'type' => 'text/javascript', - 'src' => js }) - end - doc.style(style) - doc.script(java_script) - end + def to_html(doc) + doc.unique(:chartview_style) { + doc.head { + [ 'jquery/jquery-2.1.1.min.js', 'flot/jquery.flot.js', + 'flot/jquery.flot.time.js' ].each do |js| + doc.script({ 'language' => 'javascript', + 'type' => 'text/javascript', 'src' => js }) + end + doc.style(style) + } + } - def div(doc) + doc.script(java_script) if @sport == 'running' chart_div(doc, 'pace', "Pace (#{select_unit('min/km')})") else @@ -274,9 +272,9 @@ EOT # Don't plot frame for graph without data. return if @empty_charts[field] - frame(doc, title) { + ViewFrame.new(title) { doc.div({ 'id' => "#{field}_chart", 'class' => 'chart-placeholder'}) - } + }.to_html(doc) end def hover_function(chart_id, y_label, y_unit) diff --git a/lib/postrunner/DeviceList.rb b/lib/postrunner/DeviceList.rb index 3316dde..6ab63f2 100644 --- a/lib/postrunner/DeviceList.rb +++ b/lib/postrunner/DeviceList.rb @@ -3,7 +3,7 @@ # # = DeviceList.rb -- PostRunner - Manage the data from your Garmin sport devices. # -# Copyright (c) 2014 by Chris Schlaeger <cs@taskjuggler.org> +# Copyright (c) 2014, 2015 by Chris Schlaeger <cs@taskjuggler.org> # # This program is free software; you can redistribute it and/or modify # it under the terms of version 2 of the GNU General Public License as @@ -12,22 +12,18 @@ require 'fit4ruby' -require 'postrunner/ViewWidgets' +require 'postrunner/ViewFrame' module PostRunner class DeviceList - include ViewWidgets - def initialize(fit_activity) @fit_activity = fit_activity end def to_html(doc) - frame(doc, 'Devices') { - devices.each { |d| d.to_html(doc) } - } + ViewFrame.new('Devices', 600, devices).to_html(doc) end def to_s diff --git a/lib/postrunner/FlexiTable.rb b/lib/postrunner/FlexiTable.rb index 7385db7..8113cc1 100644 --- a/lib/postrunner/FlexiTable.rb +++ b/lib/postrunner/FlexiTable.rb @@ -3,7 +3,7 @@ # # = FlexiTable.rb -- PostRunner - Manage the data from your Garmin sport devices. # -# Copyright (c) 2014 by Chris Schlaeger <cs@taskjuggler.org> +# Copyright (c) 2014, 2015 by Chris Schlaeger <cs@taskjuggler.org> # # This program is free software; you can redistribute it and/or modify # it under the terms of version 2 of the GNU General Public License as @@ -252,6 +252,9 @@ module PostRunner def to_html(doc) index_table + doc.unique(:flexitable_style) { + doc.head { doc.style(style) } + } doc.table(@html_attrs) { @head_rows.each { |r| r.to_html(doc) } @body_rows.each { |r| r.to_html(doc) } @@ -318,6 +321,30 @@ module PostRunner s + "\n" end + def style + <<EOT +.flexitable { + width: 100%; + border: 2px solid #545454; + border-collapse: collapse; + font-size:11pt; +} +.ft_head_row { + background-color: #DEDEDE +} +.ft_even_row { + background-color: #FCFCFC +} +.ft_odd_row { + background-color: #F1F1F1 +} +.ft_cell { + border: 1px solid #CCCCCC; + padding: 1px 3px; +} +EOT + end + end end diff --git a/lib/postrunner/HTMLBuilder.rb b/lib/postrunner/HTMLBuilder.rb index c9212fe..8c53f2f 100644 --- a/lib/postrunner/HTMLBuilder.rb +++ b/lib/postrunner/HTMLBuilder.rb @@ -19,18 +19,79 @@ module PostRunner class HTMLBuilder # Create a new HTMLBuilder object. - def initialize + def initialize(title) # This is the Nokogiri Document that will store all the data. @doc = Nokogiri::HTML::Document.new # We only need to keep a stack of the currently edited nodes so we know # where we are in the node tree. @node_stack = [] + @tags = [] + + @html = create_node('html') { + @head = create_node('head') { + create_node('meta', { 'http-equiv' => 'Content-Type', + 'content' => 'text/html; charset=utf-8' }) + create_node('title', title) + } + @body = create_node('body') + } + @node_stack << @html + @node_stack << @body + end + + # Append nodes provided in block to head section of HTML document. + def head + @node_stack.push(@head) + yield if block_given? + unless @node_stack.pop == @head + raise ArgumentError, "node_stack corrupted in head" + end + end + + # Append nodes provided in block to body section of HTML document. + def body(*args) + @node_stack.push(@body) + args.each do |arg| + if arg.is_a?(Hash) + arg.each { |k, v| @body[k] = v } + end + end + yield if block_given? + unless @node_stack.pop == @body + raise ArgumentError, "node_stack corrupted in body" + end + end + + # Only execute the passed block if the provided tag has not been added + # yet. + def unique(tag) + unless @tags.include?(tag) + @tags << tag + yield if block_given? + end end # Any call to an undefined method will create a HTML node of the same # name. - def method_missing(method_name, *args) - node = Nokogiri::XML::Node.new(method_name.to_s, @doc) + def method_missing(method_name, *args, &block) + create_node(method_name.to_s, *args, &block) + end + + # Only needed to comply with style guides. This all calls to unknown + # method will be handled properly. So, we always return true. + def respond_to?(method) + true + end + + # Dump the HTML document as HTML formatted String. + def to_html + @doc.to_html + end + + private + + def create_node(name, *args) + node = Nokogiri::XML::Node.new(name, @doc) if (parent = @node_stack.last) parent.add_child(node) else @@ -52,19 +113,6 @@ module PostRunner @node_stack.pop end - # Only needed to comply with style guides. This all calls to unknown - # method will be handled properly. So, we always return true. - def respond_to?(method) - true - end - - # Dump the HTML document as HTML formatted String. - def to_html - @doc.to_html - end - - private - def add_child(parent, node) if parent parent.add_child(node) diff --git a/lib/postrunner/NavButtonRow.rb b/lib/postrunner/NavButtonRow.rb new file mode 100644 index 0000000..7e1ea06 --- /dev/null +++ b/lib/postrunner/NavButtonRow.rb @@ -0,0 +1,103 @@ +#!/usr/bin/env ruby -w +# encoding: UTF-8 +# +# = NavButtonRow.rb -- PostRunner - Manage the data from your Garmin sport devices. +# +# Copyright (c) 2015 by Chris Schlaeger <cs@taskjuggler.org> +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of version 2 of the GNU General Public License as +# published by the Free Software Foundation. +# + +require 'postrunner/HTMLBuilder' + +module PostRunner + + # Auxilliary class that stores the name of an icon file and a URL as a + # String. It is used to describe a NavButtonRow button. + class NavButtonDef < Struct.new(:icon, :url) + end + + # A NavButtonRow is a row of buttons used to navigate between HTML pages. + class NavButtonRow + + # A class to store the icon and URL of a button in the NavButtonRow + # objects. + class Button + + # Create a Button object. + # @param icon [String] File name of the icon file + # @param url [String] URL of the page to change to + def initialize(icon, url = nil) + @icon = icon + @url = url + end + + # Add the object as HTML Elements to the document. + # @param doc [HTMLBuilder] XML Document + def to_html(doc) + if @url + doc.a({ :href => @url }) { + doc.img({ :src => "icons/#{@icon}", :class => 'active_button' }) + } + else + doc.img({ :src => "icons/#{@icon}", :class => 'inactive_button' }) + end + end + + end + + # Create a new NavButtonRow object. + # @param float [String, Nil] specifies if the HTML representation should + # be a floating object that floats left or right. + def initialize(float = nil) + unless float.nil? || %w( left right ).include?(float) + raise ArgumentError "float argument must be nil, 'left' or 'right'" + end + + @float = float + @buttons = [] + end + + # Add a new button to the NavButtonRow object. + # @param icon [String] File name of the icon file + # @param url [String] URL of the page to change to + def addButton(icon, url = nil) + @buttons << Button.new(icon, url) + end + + # Add the object as HTML Elements to the document. + # @param doc [HTMLBuilder] XML Document + def to_html(doc) + doc.unique(:nav_button_row_style) { + doc.head { doc.style(style) } + } + doc.div({ :class => 'nav_button_row', + :style => "width: #{@buttons.length * (32 + 10)}px; " + + "#{@float ? "float: #{@float};" : + 'margin-left: auto; margin-right: auto'}"}) { + @buttons.each { |btn| btn.to_html(doc) } + } + end + + private + + def style + <<"EOT" +.nav_button_row { + padding: 3px 30px; +} +.active_button { + padding: 5px; +} +.inactive_button { + padding: 5px; + opacity: 0.4; +} +EOT + end + + end + +end diff --git a/lib/postrunner/PagingButtons.rb b/lib/postrunner/PagingButtons.rb new file mode 100644 index 0000000..aa1f5f2 --- /dev/null +++ b/lib/postrunner/PagingButtons.rb @@ -0,0 +1,77 @@ +#!/usr/bin/env ruby -w +# encoding: UTF-8 +# +# = PagingButtons.rb -- PostRunner - Manage the data from your Garmin sport devices. +# +# Copyright (c) 2015 by Chris Schlaeger <cs@taskjuggler.org> +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of version 2 of the GNU General Public License as +# published by the Free Software Foundation. +# + +require 'postrunner/NavButtonRow' + +module PostRunner + + # A class to generate a set of forward/backward buttons for an HTML page. It + # can also include jump to first/last buttons. + class PagingButtons + + # Create a new PagingButtons object. + # @param page_urls [Array of String] Sorted list of all possible pages + # @param end_buttons [Boolean] If true jump to first/last buttons are + # included + def initialize(page_urls, end_buttons = true) + if page_urls.empty? + raise ArgumentError.new("'page_urls' must not be empty") + end + @pages = page_urls + @current_page_index = 0 + @end_buttons = end_buttons + end + + # Return the URL of the current page + def current_page + @pages[@current_page_index] + end + + # Set the URL for the current page. It must be included in the URL set + # passed at creation time. The forward/backward links will be derived from + # the setting of the current page. + # @param page_url [String] URL of the page + def current_page=(page_url) + unless (@current_page_index = @pages.index(page_url)) + raise ArgumentError.new("URL #{page_url} is not a known page URL") + end + end + + # Iterate over all buttons. A NavButtonDef object is passed to the block + # that contains the icon and URL for the button. If no URL is set, the + # button is inactive. + def each + %w( first back forward last ).each do |button_name| + button = NavButtonDef.new + button.icon = button_name + '.png' + button.url = + case button_name + when 'first' + @current_page_index == 0 || !@end_buttons ? nil : @pages.first + when 'back' + @current_page_index == 0 ? nil : + @pages[@current_page_index - 1] + when 'forward' + @current_page_index == @pages.length - 1 ? nil : + @pages[@current_page_index + 1] + when 'last' + @current_page_index == @pages.length - 1 || + !@end_buttons ? nil : @pages.last + end + + yield(button) + end + end + + end + +end diff --git a/lib/postrunner/PersonalRecords.rb b/lib/postrunner/PersonalRecords.rb index aba2f6a..7f69529 100644 --- a/lib/postrunner/PersonalRecords.rb +++ b/lib/postrunner/PersonalRecords.rb @@ -15,6 +15,8 @@ require 'yaml' require 'fit4ruby' require 'postrunner/BackedUpFile' +require 'postrunner/RecordListPageView' +require 'postrunner/ActivityLink' module PostRunner @@ -89,7 +91,8 @@ module PostRunner secsToHMS(@duration), speedToPace(@distance / @duration) ]) + [ @activity.db.ref_by_fit_file(@activity.fit_file), - @activity.name, @start_time.strftime("%Y-%m-%d") ]) + ActivityLink.new(@activity, false), + @start_time.strftime("%Y-%m-%d") ]) end end @@ -171,6 +174,16 @@ module PostRunner def to_s return '' if empty? + generate_table.to_s + "\n" + end + + def to_html(doc) + generate_table.to_html(doc) + end + + private + + def generate_table t = FlexiTable.new t.head t.row([ 'Record', 'Time/Dist.', 'Avg. Pace', 'Ref.', 'Activity', @@ -192,13 +205,17 @@ module PostRunner records.sort { |r1, r2| r1.distance <=> r2.distance }.each do |r| r.to_table_row(t) end - t.to_s + "\n" + + t end + end class SportRecords + attr_reader :sport, :all_time, :yearly + def initialize(sport) @sport = sport @all_time = RecordSet.new(@sport, nil) @@ -251,6 +268,22 @@ module PostRunner str end + def to_html(doc) + return nil if empty? + + doc.div { + doc.h3('All-time records') + @all_time.to_html(doc) + @yearly.values.sort{ |r1, r2| r2.year <=> r1.year }.each do |record| + puts record.year + unless record.empty? + doc.h3("Records of #{record.year}") + record.to_html(doc) + end + end + } + end + end def initialize(activities) @@ -286,6 +319,16 @@ module PostRunner def sync save_records + + non_empty_records = @sport_records.select { |s, r| !r.empty? } + max = non_empty_records.length + i = 0 + non_empty_records.each do |sport, record| + output_file = File.join(@activities.cfg[:html_dir], + "records-#{i}.html") + RecordListPageView.new(@activities, record, max, i). + write(output_file) + end end def to_s diff --git a/lib/postrunner/RecordListPageView.rb b/lib/postrunner/RecordListPageView.rb new file mode 100644 index 0000000..f1de004 --- /dev/null +++ b/lib/postrunner/RecordListPageView.rb @@ -0,0 +1,69 @@ +#!/usr/bin/env ruby -w +# encoding: UTF-8 +# +# = RecordListPageView.rb -- PostRunner - Manage the data from your Garmin sport devices. +# +# Copyright (c) 2015 by Chris Schlaeger <cs@taskjuggler.org> +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of version 2 of the GNU General Public License as +# published by the Free Software Foundation. +# + +require 'fit4ruby' + +require 'postrunner/FlexiTable' +require 'postrunner/View' +require 'postrunner/ViewFrame' +require 'postrunner/ViewButtons' +require 'postrunner/PagingButtons' + +module PostRunner + + # Generates an HTML page with all personal records for a particular sport + # type. + class RecordListPageView < View + + include Fit4Ruby::Converters + + # Create a RecordListPageView object. + # @param db [ActivityDB] Activity database + # @param records [PersonalRecords] Database with personal records + # @param page_count [Fixnum] Number of total pages + # @param page_index [Fixnum] Index of the page + def initialize(db, records, page_count, page_index) + @db = db + @unit_system = @db.cfg[:unit_system] + @records = records + + views = @db.views + views.current_page = "records-0.html" + + pages = PagingButtons.new((0..(page_count - 1)).map do |i| + "records-#{i}.html" + end) + pages.current_page = + "records-#{page_index}.html" + + @sport_name = Activity::ActivityTypes[@records.sport] + super("#{@sport_name} Records", views, pages) + + body { + frame_width = 800 + + @doc.div({ :class => 'main' }) { + ViewFrame.new("All-time #{@sport_name} Records", + frame_width, @records.all_time).to_html(@doc) + + @records.yearly.each do |year, record| + next if record.empty? + ViewFrame.new("#{year} #{@sport_name} Records", + frame_width, record).to_html(@doc) + end + } + } + end + + end + +end diff --git a/lib/postrunner/TrackView.rb b/lib/postrunner/TrackView.rb index 7171706..fc7bc21 100644 --- a/lib/postrunner/TrackView.rb +++ b/lib/postrunner/TrackView.rb @@ -12,37 +12,35 @@ require 'fit4ruby' -require 'postrunner/ViewWidgets' +require 'postrunner/ViewFrame' module PostRunner class TrackView - include ViewWidgets - def initialize(activity) @activity = activity @session = @activity.fit_activity.sessions[0] @has_geo_data = @session.has_geo_data? end - def head(doc) + def to_html(doc) return unless @has_geo_data - doc.link({ 'rel' => 'stylesheet', - 'href' => 'openlayers/theme/default/style.css', - 'type' => 'text/css' }) - doc.style(style) - doc.script({ 'src' => 'openlayers/OpenLayers.js' }) - doc.script(java_script) - end - - def div(doc) - return unless @has_geo_data + doc.head { + doc.unique(:trackview_style) { + doc.style(style) + doc.link({ 'rel' => 'stylesheet', + 'href' => 'openlayers/theme/default/style.css', + 'type' => 'text/css' }) + doc.script({ 'src' => 'openlayers/OpenLayers.js' }) + } + doc.script(java_script) + } - frame(doc, 'Map') { + ViewFrame.new('Map', 600) { doc.div({ 'id' => 'map', 'class' => 'trackmap' }) - } + }.to_html(doc) end private diff --git a/lib/postrunner/UserProfileView.rb b/lib/postrunner/UserProfileView.rb index 3ff4341..c89216b 100644 --- a/lib/postrunner/UserProfileView.rb +++ b/lib/postrunner/UserProfileView.rb @@ -12,14 +12,12 @@ require 'fit4ruby' -require 'postrunner/ViewWidgets' +require 'postrunner/ViewFrame' module PostRunner class UserProfileView - include ViewWidgets - def initialize(fit_activity, unit_system) @fit_activity = fit_activity @unit_system = unit_system @@ -28,9 +26,7 @@ module PostRunner def to_html(doc) return nil if @fit_activity.user_profiles.empty? - frame(doc, 'User Profile') { - profile.to_html(doc) - } + ViewFrame.new('User Profile', 600, profile).to_html(doc) end def to_s diff --git a/lib/postrunner/View.rb b/lib/postrunner/View.rb new file mode 100644 index 0000000..acfd258 --- /dev/null +++ b/lib/postrunner/View.rb @@ -0,0 +1,97 @@ +#!/usr/bin/env ruby -w +# encoding: UTF-8 +# +# = View.rb -- PostRunner - Manage the data from your Garmin sport devices. +# +# Copyright (c) 2015 by Chris Schlaeger <cs@taskjuggler.org> +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of version 2 of the GNU General Public License as +# published by the Free Software Foundation. +# + +require 'postrunner/HTMLBuilder' +require 'postrunner/ViewTop' +require 'postrunner/ViewBottom' + +module PostRunner + + # Base class for all generated HTML pages. + class View + + attr_reader :doc + + # Create a new View object. + # @param title [String] The title of the HTML page + # @param views [ViewButtons] List of all cross referenced View objects + # @param pages [PagingButtons] List of all pages of this View + def initialize(title, views, pages) + @doc = HTMLBuilder.new(title) + @views = views + @pages = pages + + @doc.unique(:view_style) { + style + } + end + + # Create the body section of the HTML document. + def body + ViewTop.new(@views, @pages).to_html(@doc) + yield if block_given? + ViewBottom.new.to_html(@doc) + + self + end + + # Convert the View into an HTML document. + def to_html + @doc.to_html + end + + # Write the HTML document to a file + # @param file_name [String] Name of the file to write + def write(file_name) + begin + File.write(file_name, to_html) + rescue IOError + Log.fatal "Cannot write file '#{file_name}: #{$!}" + end + end + + private + + def style + @doc.head { + @doc.style(<<"EOT" +body { + font-family: verdana,arial,sans-serif; + margin: 0px; +} +.flexitable { + width: 100%; + border: 2px solid #545454; + border-collapse: collapse; + font-size:11pt; +} +.ft_head_row { + background-color: #DEDEDE +} +.ft_even_row { + background-color: #FCFCFC +} +.ft_odd_row { + background-color: #F1F1F1 +} +.ft_cell { + border: 1px solid #CCCCCC; + padding: 1px 3px; +} +EOT + ) + } + end + + end + +end diff --git a/lib/postrunner/ViewBottom.rb b/lib/postrunner/ViewBottom.rb new file mode 100644 index 0000000..3812919 --- /dev/null +++ b/lib/postrunner/ViewBottom.rb @@ -0,0 +1,54 @@ +#!/usr/bin/env ruby -w +# encoding: UTF-8 +# +# = ViewBottom.rb -- PostRunner - Manage the data from your Garmin sport devices. +# +# Copyright (c) 2015 by Chris Schlaeger <cs@taskjuggler.org> +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of version 2 of the GNU General Public License as +# published by the Free Software Foundation. +# + +require 'postrunner/HTMLBuilder' +require 'postrunner/version' + +module PostRunner + + # This class generates the footer of a HTML page. + class ViewBottom + + # Generate the HTML code to that describes the foot section. + # @param doc [HTMLBuilder] Reference to the HTML document to add to. + def to_html(doc) + doc.unique(:viewbottom_style) { + doc.head { doc.style(style) } + } + doc.div({ :class => 'footer' }){ + doc.hr + doc.div({ :class => 'copyright' }) { + doc.text("Generated by ") + doc.a('PostRunner', + { :href => 'https://github.com/scrapper/postrunner' }) + doc.text(" #{VERSION} on #{Time.now}") + } + } + end + + private + + def style + <<EOT +.footer { + clear: both; + width: 100%; + height: 30px; + padding: 15px 0px; + text-align: center; + font-size: 9pt; +} +EOT + end + end + +end diff --git a/lib/postrunner/ViewButtons.rb b/lib/postrunner/ViewButtons.rb new file mode 100644 index 0000000..4c95162 --- /dev/null +++ b/lib/postrunner/ViewButtons.rb @@ -0,0 +1,68 @@ +#!/usr/bin/env ruby -w +# encoding: UTF-8 +# +# = ViewButtons.rb -- PostRunner - Manage the data from your Garmin sport devices. +# +# Copyright (c) 2015 by Chris Schlaeger <cs@taskjuggler.org> +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of version 2 of the GNU General Public License as +# published by the Free Software Foundation. +# + +module PostRunner + + # This class generates a simple icon menue to select from a set of HTML + # pages (called views). The current page is represented as an inactive icon. + # All other icons are buttons that contain links to other pages. + class ViewButtons + + # Create a ViewButtons object. + # @params views [Array of NavButtonDef] icons and URLs for all pages. + def initialize(views) + if views.empty? + raise ArgumentError.new("'views' must not be empty") + end + @views = views + self.current_page = views[0].url + end + + # Get the URL of the current page + # @return [String] + def current_page + @current_view_url + end + + # Set the the current page. + # @param page_url [String] URL of the current page. This must either be + # nil or a URL in the predefined set. + def current_page=(page_url) + unless page_url + @current_view_url = nil + return + end + + if (current = @views.find { |v| v.url == page_url }) + @current_view_url = current.url + else + raise ArgumentError.new("#{page_url} is not a URL of a known view") + end + end + + # Iterate over all buttons. A NavButtonDef object is passed to the block + # that contains the icon and URL for the button. If no URL is set, the + # button is inactive. + def each + @views.each do |view| + view = view.clone + if @current_view_url == view.url + view.url = nil + end + yield(view) + end + + end + + end + +end diff --git a/lib/postrunner/ViewFrame.rb b/lib/postrunner/ViewFrame.rb new file mode 100644 index 0000000..863ad2a --- /dev/null +++ b/lib/postrunner/ViewFrame.rb @@ -0,0 +1,93 @@ +#!/usr/bin/env ruby -w +# encoding: UTF-8 +# +# = ViewFrame.rb -- PostRunner - Manage the data from your Garmin sport devices. +# +# Copyright (c) 2015 by Chris Schlaeger <cs@taskjuggler.org> +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of version 2 of the GNU General Public License as +# published by the Free Software Foundation. +# + +module PostRunner + + # Creates an HTML frame around the passed object or HTML block. + class ViewFrame + + # Create a ViewFrame object. + # @param title [String] Title/heading of the framed box + # @param width [Fixnum or nil] Width of the frame. Use nil to set no + # width. + # @param content [Any object that respons to to_html] Object to frame + # @param &block [HTMLBuilder actions] + def initialize(title, width = 600, content = nil, &block) + @title = title + @content = content + @block = block + @width = width + end + + # Generate the HTML code for the frame and the enclosing content. + # @param doc [HTMLBuilder] HTML document + def to_html(doc) + doc.unique(:viewframe_style) { + # Add the necessary style sheet snippets to the document head. + doc.head { doc.style(style) } + } + + attr = { 'class' => 'widget_frame' } + attr['style'] = "width: #{@width}px" if @width + doc.div(attr) { + doc.div({ 'class' => 'widget_frame_title' }) { + doc.b(@title) + } + doc.div { + # The @content holds an object that must respond to to_html to + # generate the HTML code. + if @content + if @content.is_a?(Array) + @content.each { |c| c.to_html(doc) } + else + @content.to_html(doc) + end + end + # The block generates HTML code directly + @block.yield if @block + } + } + end + + private + + def style + <<EOT +.widget_frame { + box-sizing: border-box; + padding: 10px 15px 15px 15px; + margin: 15px auto 15px auto; + border: 1px solid #ddd; + background: #fff; + background: linear-gradient(#f6f6f6 0, #fff 50px); + background: -o-linear-gradient(#f6f6f6 0, #fff 50px); + background: -ms-linear-gradient(#f6f6f6 0, #fff 50px); + background: -moz-linear-gradient(#f6f6f6 0, #fff 50px); + background: -webkit-linear-gradient(#f6f6f6 0, #fff 50px); + box-shadow: 0 3px 10px rgba(0,0,0,0.15); + -o-box-shadow: 0 3px 10px rgba(0,0,0,0.1); + -ms-box-shadow: 0 3px 10px rgba(0,0,0,0.1); + -moz-box-shadow: 0 3px 10px rgba(0,0,0,0.1); + -webkit-box-shadow: 0 3px 10px rgba(0,0,0,0.1); +} +.widget_frame_title { + font-size:13pt; + padding-bottom: 5px; + text-align: left; +} +EOT + end + + end + +end + diff --git a/lib/postrunner/ViewTop.rb b/lib/postrunner/ViewTop.rb new file mode 100644 index 0000000..c79d0ea --- /dev/null +++ b/lib/postrunner/ViewTop.rb @@ -0,0 +1,80 @@ +#!/usr/bin/env ruby -w +# encoding: UTF-8 +# +# = ViewTop.rb -- PostRunner - Manage the data from your Garmin sport devices. +# +# Copyright (c) 2015 by Chris Schlaeger <cs@taskjuggler.org> +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of version 2 of the GNU General Public License as +# published by the Free Software Foundation. +# + +require 'postrunner/HTMLBuilder' +require 'postrunner/NavButtonRow' + +module PostRunner + + # This class generates the top part of the HTML page. It contains the logo + # and the menu and navigation buttons. + class ViewTop + + # Create a ViewTop object. + # @param views [Array of NavButtonDef] icons and URLs for views + # @param pages [Array of NavButtonDef] Full list of pages of this view. + def initialize(views, pages) + @views = views + @pages = pages + end + + # Generate the HTML code to that describes the top section. + # @param doc [HTMLBuilder] Reference to the HTML document to add to. + def to_html(doc) + doc.unique(:viewtop_style) { + doc.head { doc.style(style) } + } + doc.div({ :class => 'titlebar' }) { + doc.div('PostRunner', { :class => 'title' }) + + page_selector = NavButtonRow.new('right') + @pages.each do |p| + page_selector.addButton(p.icon, p.url) + end + page_selector.to_html(doc) + + view_selector = NavButtonRow.new + @views.each do |v| + view_selector.addButton(v.icon, v.url) + end + view_selector.to_html(doc) + } + end + + private + + def style + <<EOT +.titlebar { + width: 100%; + height: 50px; + margin: 0px; + background: linear-gradient(#7FA1FF 0, #002EAC 50px); +} +.title { + float: left; + font-size: 24pt; + font-style: italic; + font-weight: bold; + color: #F8F8F8; + text-shadow: -1px -1px 0 #5C5C5C, + 1px -1px 0 #5C5C5C, + -1px 1px 0 #5C5C5C, + 1px 1px 0 #5C5C5C; + padding: 3px 30px; +} +EOT + end + + end + +end diff --git a/lib/postrunner/ViewWidgets.rb b/lib/postrunner/ViewWidgets.rb deleted file mode 100644 index b4b4207..0000000 --- a/lib/postrunner/ViewWidgets.rb +++ /dev/null @@ -1,153 +0,0 @@ -#!/usr/bin/env ruby -w -# encoding: UTF-8 -# -# = ViewWidgets.rb -- PostRunner - Manage the data from your Garmin sport devices. -# -# Copyright (c) 2014 by Chris Schlaeger <cs@taskjuggler.org> -# -# This program is free software; you can redistribute it and/or modify -# it under the terms of version 2 of the GNU General Public License as -# published by the Free Software Foundation. -# - -module PostRunner - - module ViewWidgets - - def view_widgets_style(doc) - doc.style(<<EOT -.titlebar { - width: 100%; - height: 50px; - margin: 0px; - background: linear-gradient(#7FA1FF 0, #002EAC 50px); -} -.title { - float: left; - font-size: 24pt; - font-style: italic; - font-weight: bold; - color: #F8F8F8; - text-shadow: -1px -1px 0 #5C5C5C, - 1px -1px 0 #5C5C5C, - -1px 1px 0 #5C5C5C, - 1px 1px 0 #5C5C5C; - padding: 3px 30px; -} -.navigator { - float: right; - padding: 3px 30px; -} -.active_button { - padding: 5px; -} -.inactive_button { - padding: 5px; - opacity: 0.4; -} -.widget_frame { - box-sizing: border-box; - width: 600px; - padding: 10px 15px 15px 15px; - margin: 15px auto 15px auto; - border: 1px solid #ddd; - background: #fff; - background: linear-gradient(#f6f6f6 0, #fff 50px); - background: -o-linear-gradient(#f6f6f6 0, #fff 50px); - background: -ms-linear-gradient(#f6f6f6 0, #fff 50px); - background: -moz-linear-gradient(#f6f6f6 0, #fff 50px); - background: -webkit-linear-gradient(#f6f6f6 0, #fff 50px); - box-shadow: 0 3px 10px rgba(0,0,0,0.15); - -o-box-shadow: 0 3px 10px rgba(0,0,0,0.1); - -ms-box-shadow: 0 3px 10px rgba(0,0,0,0.1); - -moz-box-shadow: 0 3px 10px rgba(0,0,0,0.1); - -webkit-box-shadow: 0 3px 10px rgba(0,0,0,0.1); -} -.widget_frame_title { - font-size:13pt; - padding-bottom: 5px; - text-align: left; -} -.flexitable { - width: 100%; - border: 2px solid #545454; - border-collapse: collapse; - font-size:11pt; -} -.ft_head_row { - background-color: #DEDEDE -} -.ft_even_row { - background-color: #FCFCFC -} -.ft_odd_row { - background-color: #F1F1F1 -} -.ft_cell { - border: 1px solid #CCCCCC; - padding: 1px 3px; -} -.footer { - clear: both; - width: 100%; - height: 30px; - padding: 15px; - text-align: center; - font-size: 9pt; -} -EOT - ) - end - - def frame(doc, title) - doc.div({ 'class' => 'widget_frame' }) { - doc.div({ 'class' => 'widget_frame_title' }) { - doc.b(title) - } - doc.div { - yield if block_given? - } - } - end - - def titlebar(doc, first_page = nil, prev_page = nil, home_page = nil, - next_page = nil, last_page = nil) - # The top title bar. - doc.div({ :class => 'titlebar' }) { - doc.div('PostRunner', { :class => 'title' }) - doc.div({ :class => 'navigator' }) { - button(doc, first_page, 'first.png') - button(doc, prev_page, 'back.png') - button(doc, home_page, 'home.png') - button(doc, next_page, 'forward.png') - button(doc, last_page, 'last.png') - } - } - end - - def button(doc, link, icon) - if link - doc.a({ :href => link }) { - doc.img({ :src => "icons/#{icon}", :class => 'active_button' }) - } - else - doc.img({ :src => "icons/#{icon}", :class => 'inactive_button' }) - end - end - - def footer(doc) - doc.div({ :class => 'footer' }){ - doc.hr - doc.div({ :class => 'copyright' }) { - doc.text("Generated by ") - doc.a('PostRunner', - { :href => 'https://github.com/scrapper/postrunner' }) - doc.text(" #{VERSION} on #{Time.now}") - } - } - end - - end - -end - diff --git a/misc/icons/activities.png b/misc/icons/activities.png Binary files differnew file mode 100644 index 0000000..87b1c38 --- /dev/null +++ b/misc/icons/activities.png diff --git a/misc/icons/activities.svg b/misc/icons/activities.svg new file mode 100644 index 0000000..010749a --- /dev/null +++ b/misc/icons/activities.svg @@ -0,0 +1,1582 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<!-- Created with Inkscape (http://www.inkscape.org/) --> +<svg + xmlns:dc="http://purl.org/dc/elements/1.1/" + xmlns:cc="http://creativecommons.org/ns#" + xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:svg="http://www.w3.org/2000/svg" + xmlns="http://www.w3.org/2000/svg" + xmlns:xlink="http://www.w3.org/1999/xlink" + xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" + xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" + width="128" + height="128" + id="svg3669" + sodipodi:version="0.32" + inkscape:version="0.46" + sodipodi:docbase="/home/david/sandbox/split/dolphin file views/32x32" + sodipodi:docname="view-list-text.svgz" + version="1.0" + inkscape:output_extension="org.inkscape.output.svgz.inkscape" + inkscape:export-filename="/home/pinheiro/pics/oxygen/scalable/actions/view-list-text.png" + inkscape:export-xdpi="90" + inkscape:export-ydpi="90"> + <defs + id="defs3671"> + <linearGradient + inkscape:collect="always" + id="linearGradient3487"> + <stop + style="stop-color:#535353;stop-opacity:1;" + offset="0" + id="stop3489" /> + <stop + style="stop-color:#535353;stop-opacity:0;" + offset="1" + id="stop3491" /> + </linearGradient> + <inkscape:perspective + sodipodi:type="inkscape:persp3d" + inkscape:vp_x="0 : 64 : 1" + inkscape:vp_y="0 : 1000 : 0" + inkscape:vp_z="128 : 64 : 1" + inkscape:persp3d-origin="64 : 42.666667 : 1" + id="perspective307" /> + <linearGradient + id="linearGradient3437"> + <stop + id="stop3439" + offset="0" + style="stop-color:#cdcdcf;stop-opacity:1" /> + <stop + id="stop3441" + offset="1" + style="stop-color:#cdcdcf;stop-opacity:1" /> + </linearGradient> + <linearGradient + id="linearGradient3417"> + <stop + style="stop-color:#b3b3b6;stop-opacity:1;" + offset="0" + id="stop3419" /> + <stop + style="stop-color:#cecece;stop-opacity:1;" + offset="1" + id="stop3421" /> + </linearGradient> + <linearGradient + id="linearGradient4711"> + <stop + style="stop-color:#ffffff;stop-opacity:1;" + offset="0" + id="stop4713" /> + <stop + id="stop4715" + offset="0.49140647" + style="stop-color:#ffffff;stop-opacity:1;" /> + <stop + style="stop-color:#dcdcdc;stop-opacity:1;" + offset="1" + id="stop4717" /> + </linearGradient> + <linearGradient + id="linearGradient7422"> + <stop + id="stop7424" + offset="0" + style="stop-color:#cbcbcd;stop-opacity:1;" /> + <stop + style="stop-color:#e0e0e2;stop-opacity:1;" + offset="0.5" + id="stop7426" /> + <stop + id="stop7428" + offset="1" + style="stop-color:#f2f2f2;stop-opacity:1;" /> + </linearGradient> + <linearGradient + id="linearGradient7244"> + <stop + style="stop-color:#6f6f6f;stop-opacity:1;" + offset="0" + id="stop7246" /> + <stop + style="stop-color:#ffffff;stop-opacity:1;" + offset="1" + id="stop7248" /> + </linearGradient> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient4711" + id="linearGradient7843" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(0.121457,0,0,0.1756605,195.18891,503.66043)" + x1="-333.0289" + y1="-1473.6504" + x2="-333.0289" + y2="-776.61371" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient7422" + id="linearGradient7912" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(0.121457,0,0,0.1756605,75.745932,148.34634)" + x1="399.77466" + y1="727.07941" + x2="399.77466" + y2="480.60214" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient7244" + id="linearGradient12912" + x1="1055.3002" + y1="-468.66934" + x2="1055.3002" + y2="-481.76657" + gradientUnits="userSpaceOnUse" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient3437" + id="linearGradient3423" + x1="109.25784" + y1="260.75122" + x2="109.25784" + y2="312.87741" + gradientUnits="userSpaceOnUse" /> + <filter + inkscape:collect="always" + id="filter4400"> + <feGaussianBlur + inkscape:collect="always" + stdDeviation="1.177891" + id="feGaussianBlur4402" /> + </filter> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient3487" + id="linearGradient3493" + x1="68" + y1="156" + x2="68" + y2="4" + gradientUnits="userSpaceOnUse" /> + </defs> + <sodipodi:namedview + inkscape:document-units="px" + pagecolor="#ffffff" + bordercolor="#666666" + borderopacity="1.0" + inkscape:pageopacity="0.0" + inkscape:pageshadow="2" + inkscape:zoom="2.8284271" + inkscape:cx="131.36231" + inkscape:cy="36.250876" + inkscape:current-layer="layer1" + id="namedview3673" + inkscape:window-width="937" + inkscape:window-height="696" + inkscape:window-x="1028" + inkscape:window-y="368" + showgrid="true" + showguides="true" + inkscape:guide-bbox="true" + width="128px" + height="128px" + grid_units="px" + inkscape:grid-points="true" + gridtolerance="10000"> + <inkscape:grid + id="GridFromPre046Settings" + type="xygrid" + originx="0px" + originy="0px" + spacingx="4px" + spacingy="4px" + color="#0000ff" + empcolor="#0000ff" + opacity="0.2" + empopacity="0.4" + empspacing="0" /> + </sodipodi:namedview> + <metadata + id="metadata3675"> + <rdf:RDF> + <cc:Work + rdf:about=""> + <dc:format>image/svg+xml</dc:format> + <dc:type + rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> + </cc:Work> + </rdf:RDF> + </metadata> + <g + inkscape:label="Layer 1" + inkscape:groupmode="layer" + id="layer1" + transform="translate(-79.62865,-236.8761)"> + <rect + inkscape:export-ydpi="90" + inkscape:export-xdpi="90" + inkscape:export-filename="/home/pinheiro/Desktop/mock2.png" + style="opacity:0.4;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:4;stroke-opacity:1;filter:url(#filter4400)" + id="rect2448" + width="124" + height="111.6" + x="81.628647" + y="239.27611" + inkscape:r_cx="true" + inkscape:r_cy="true" + ry="2.5302498" + rx="2.1433532" + transform="matrix(1,0,0,1.0035842,0,2.7423747)" /> + <path + sodipodi:nodetypes="ccc" + id="path2276" + d="M 124.00035,-57.652544 L 124.00035,-60.488828 L 124.00035,-57.652544 z " + style="fill:#ffffff;fill-opacity:0.75688076;fill-rule:nonzero;stroke:none;stroke-width:0.5;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:4;stroke-opacity:1" /> + <path + sodipodi:nodetypes="ccc" + id="path3242" + d="M -10.967378,-50.02293 L -10.967378,-52.859211 L -10.967378,-50.02293 z " + style="fill:#ffffff;fill-opacity:0.75688076;fill-rule:nonzero;stroke:none;stroke-width:0.5;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:4;stroke-opacity:1" /> + <path + sodipodi:nodetypes="ccc" + id="path2985" + d="M -170.31138,-120.69393 L -170.31138,-123.53021 L -170.31138,-120.69393 z " + style="fill:#ffffff;fill-opacity:0.75688076;fill-rule:nonzero;stroke:none;stroke-width:0.5;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:4;stroke-opacity:1" /> + <path + sodipodi:nodetypes="ccc" + id="path3206" + d="M -291.59132,-208.61291 L -291.59132,-211.4492 L -291.59132,-208.61291 z " + style="fill:#ffffff;fill-opacity:0.75688076;fill-rule:nonzero;stroke:none;stroke-width:0.5;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:4;stroke-opacity:1" /> + <g + id="layer4" + inkscape:label="box" + style="display:inline" + transform="matrix(1.0148767,0,0,1.0148767,-105.918,-61.880454)" /> + <g + id="layer5" + inkscape:label="zip_app" + style="display:inline" + transform="matrix(1.0148767,0,0,1.0148767,-105.918,-61.880454)" /> + <path + sodipodi:nodetypes="ccc" + id="path3946" + d="M -41.331563,-141.87945 L -41.331563,-144.71574 L -41.331563,-141.87945 z " + style="fill:#ffffff;fill-opacity:0.75688076;fill-rule:nonzero;stroke:none;stroke-width:0.5;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:4;stroke-opacity:1" /> + <path + sodipodi:nodetypes="ccc" + id="path1561" + d="M -135.33391,-66.886514 L -135.33391,-68.43596 L -135.33391,-66.886514 z " + style="fill:#ffffff;fill-opacity:0.75688076;fill-rule:nonzero;stroke:none;stroke-width:0.5;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:4;stroke-opacity:1" /> + <rect + style="opacity:0.57786889;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:3.63199997;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:4;stroke-opacity:1" + id="rect1327" + width="1.0148762" + height="0" + x="-193.67381" + y="-124.32849" /> + <rect + style="opacity:0.57786889;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:3.63199997;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:4;stroke-opacity:1" + id="rect2482" + width="1.0148762" + height="0" + x="-229.3232" + y="-152.26562" /> + <path + sodipodi:nodetypes="ccc" + id="path2494" + d="M -390.62499,-226.57087 L -390.62499,-229.40715 L -390.62499,-226.57087 z " + style="fill:#ffffff;fill-opacity:0.75688076;fill-rule:nonzero;stroke:none;stroke-width:0.5;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:4;stroke-opacity:1" /> + <g + style="opacity:0.40163933" + transform="matrix(-0.7946432,0,0,0.6605615,-2748.0383,470.15972)" + id="g4640" /> + <g + id="g4646" + transform="matrix(-0.7946432,0,0,0.6605615,-2748.0383,470.15972)" + style="opacity:0.40163933" /> + <g + id="g4730" + transform="matrix(1.0148767,0,0,0.6605615,500.54238,477.59645)" + style="opacity:0.40163933" /> + <g + style="opacity:0.40163933" + transform="matrix(1.0148767,0,0,0.6605615,500.54238,477.59645)" + id="g4748" /> + <path + sodipodi:nodetypes="ccc" + id="path6923" + d="M 131.54671,109.09814 L 131.54671,106.26186 L 131.54671,109.09814 z " + style="fill:#ffffff;fill-opacity:0.75688076;fill-rule:nonzero;stroke:none;stroke-width:0.5;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:4;stroke-opacity:1" /> + <path + sodipodi:nodetypes="ccc" + id="path6925" + d="M -27.797286,38.427136 L -27.797286,35.59084 L -27.797286,38.427136 z " + style="fill:#ffffff;fill-opacity:0.75688076;fill-rule:nonzero;stroke:none;stroke-width:0.5;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:4;stroke-opacity:1" /> + <path + sodipodi:nodetypes="ccc" + id="path6927" + d="M -149.07723,-49.491843 L -149.07723,-52.328139 L -149.07723,-49.491843 z " + style="fill:#ffffff;fill-opacity:0.75688076;fill-rule:nonzero;stroke:none;stroke-width:0.5;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:4;stroke-opacity:1" /> + <g + id="g6929" + inkscape:label="box" + style="display:inline" + transform="matrix(1.0148767,0,0,1.0148767,36.596,97.240605)" /> + <g + id="g6931" + inkscape:label="zip_app" + style="display:inline" + transform="matrix(1.0148767,0,0,1.0148767,36.596,97.240605)" /> + <path + sodipodi:nodetypes="ccc" + id="path6933" + d="M 101.18252,17.241605 L 101.18252,14.405323 L 101.18252,17.241605 z " + style="fill:#ffffff;fill-opacity:0.75688076;fill-rule:nonzero;stroke:none;stroke-width:0.5;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:4;stroke-opacity:1" /> + <path + sodipodi:nodetypes="ccc" + id="path6935" + d="M 7.1801708,92.234553 L 7.1801708,90.685107 L 7.1801708,92.234553 z " + style="fill:#ffffff;fill-opacity:0.75688076;fill-rule:nonzero;stroke:none;stroke-width:0.5;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:4;stroke-opacity:1" /> + <rect + style="opacity:0.57786889;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:3.63199997;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:4;stroke-opacity:1" + id="rect6937" + width="1.0148762" + height="0" + x="-51.159706" + y="34.792564" /> + <rect + style="opacity:0.57786889;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:3.63199997;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:4;stroke-opacity:1" + id="rect6939" + width="1.0148762" + height="0" + x="-86.809097" + y="6.8554554" /> + <path + sodipodi:nodetypes="ccc" + id="path6941" + d="M -248.1109,-67.4498 L -248.1109,-70.286084 L -248.1109,-67.4498 z " + style="fill:#ffffff;fill-opacity:0.75688076;fill-rule:nonzero;stroke:none;stroke-width:0.5;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:4;stroke-opacity:1" /> + <g + style="opacity:0.40163933" + transform="matrix(-0.7946432,0,0,0.6605615,-2605.5245,629.28073)" + id="g6943" /> + <g + id="g6945" + transform="matrix(-0.7946432,0,0,0.6605615,-2605.5245,629.28073)" + style="opacity:0.40163933" /> + <g + id="g6947" + transform="matrix(1.0148767,0,0,0.6605615,643.05646,636.7176)" + style="opacity:0.40163933" /> + <g + style="opacity:0.40163933" + transform="matrix(1.0148767,0,0,0.6605615,643.05646,636.7176)" + id="g6949" /> + <path + sodipodi:nodetypes="ccc" + id="path7559" + d="M 81.310335,56.324571 L 81.310335,53.48829 L 81.310335,56.324571 z " + style="fill:#ffffff;fill-opacity:0.75688076;fill-rule:nonzero;stroke:none;stroke-width:0.5;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:4;stroke-opacity:1" /> + <path + sodipodi:nodetypes="ccc" + id="path7561" + d="M -78.033659,-14.346435 L -78.033659,-17.182717 L -78.033659,-14.346435 z " + style="fill:#ffffff;fill-opacity:0.75688076;fill-rule:nonzero;stroke:none;stroke-width:0.5;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:4;stroke-opacity:1" /> + <path + sodipodi:nodetypes="ccc" + id="path7563" + d="M -199.31361,-102.26541 L -199.31361,-105.1017 L -199.31361,-102.26541 z " + style="fill:#ffffff;fill-opacity:0.75688076;fill-rule:nonzero;stroke:none;stroke-width:0.5;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:4;stroke-opacity:1" /> + <g + id="g7565" + inkscape:label="box" + style="display:inline" + transform="matrix(1.0148767,0,0,1.0148767,-13.640366,44.467018)" /> + <g + id="g7567" + inkscape:label="zip_app" + style="display:inline" + transform="matrix(1.0148767,0,0,1.0148767,-13.640366,44.467018)" /> + <path + sodipodi:nodetypes="ccc" + id="path7569" + d="M 50.946152,-35.531953 L 50.946152,-38.368234 L 50.946152,-35.531953 z " + style="fill:#ffffff;fill-opacity:0.75688076;fill-rule:nonzero;stroke:none;stroke-width:0.5;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:4;stroke-opacity:1" /> + <path + sodipodi:nodetypes="ccc" + id="path7571" + d="M -43.056203,39.460982 L -43.056203,37.911535 L -43.056203,39.460982 z " + style="fill:#ffffff;fill-opacity:0.75688076;fill-rule:nonzero;stroke:none;stroke-width:0.5;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:4;stroke-opacity:1" /> + <rect + style="opacity:0.57786889;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:3.63199997;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:4;stroke-opacity:1" + id="rect7573" + width="1.0148762" + height="0" + x="-101.39607" + y="-17.980991" /> + <rect + style="opacity:0.57786889;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:3.63199997;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:4;stroke-opacity:1" + id="rect7575" + width="1.0148762" + height="0" + x="-137.04547" + y="-45.918106" /> + <path + sodipodi:nodetypes="ccc" + id="path7577" + d="M -298.34728,-120.22337 L -298.34728,-123.05965 L -298.34728,-120.22337 z " + style="fill:#ffffff;fill-opacity:0.75688076;fill-rule:nonzero;stroke:none;stroke-width:0.5;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:4;stroke-opacity:1" /> + <g + style="opacity:0.40163933" + transform="matrix(-0.7946432,0,0,0.6605615,-2655.7605,576.50714)" + id="g7579" /> + <g + id="g7581" + transform="matrix(-0.7946432,0,0,0.6605615,-2655.7605,576.50714)" + style="opacity:0.40163933" /> + <g + id="g7583" + transform="matrix(1.0148767,0,0,0.6605615,592.81999,583.94401)" + style="opacity:0.40163933" /> + <g + style="opacity:0.40163933" + transform="matrix(1.0148767,0,0,0.6605615,592.81999,583.94401)" + id="g7585" /> + <path + sodipodi:nodetypes="ccc" + id="path8394" + d="M -311.70048,181.91552 L -311.70048,179.07922 L -311.70048,181.91552 z " + style="fill:#ffffff;fill-opacity:0.75688076;fill-rule:nonzero;stroke:none;stroke-width:0.5;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:4;stroke-opacity:1" /> + <path + sodipodi:nodetypes="ccc" + id="path8396" + d="M -471.0445,111.2445 L -471.0445,108.40822 L -471.0445,111.2445 z " + style="fill:#ffffff;fill-opacity:0.75688076;fill-rule:nonzero;stroke:none;stroke-width:0.5;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:4;stroke-opacity:1" /> + <path + sodipodi:nodetypes="ccc" + id="path8398" + d="M -592.32444,23.325521 L -592.32444,20.489239 L -592.32444,23.325521 z " + style="fill:#ffffff;fill-opacity:0.75688076;fill-rule:nonzero;stroke:none;stroke-width:0.5;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:4;stroke-opacity:1" /> + <g + id="g8400" + inkscape:label="box" + style="display:inline" + transform="matrix(1.0148767,0,0,1.0148767,-406.65121,170.05797)" /> + <g + id="g8402" + inkscape:label="zip_app" + style="display:inline" + transform="matrix(1.0148767,0,0,1.0148767,-406.65121,170.05797)" /> + <path + sodipodi:nodetypes="ccc" + id="path8404" + d="M -342.06469,90.058982 L -342.06469,87.222701 L -342.06469,90.058982 z " + style="fill:#ffffff;fill-opacity:0.75688076;fill-rule:nonzero;stroke:none;stroke-width:0.5;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:4;stroke-opacity:1" /> + <path + sodipodi:nodetypes="ccc" + id="path8406" + d="M -436.06704,165.05193 L -436.06704,163.50247 L -436.06704,165.05193 z " + style="fill:#ffffff;fill-opacity:0.75688076;fill-rule:nonzero;stroke:none;stroke-width:0.5;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:4;stroke-opacity:1" /> + <rect + style="opacity:0.57786889;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:3.63199997;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:4;stroke-opacity:1" + id="rect8408" + width="1.0148762" + height="0" + x="-494.40692" + y="107.60993" /> + <rect + style="opacity:0.57786889;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:3.63199997;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:4;stroke-opacity:1" + id="rect8410" + width="1.0148762" + height="0" + x="-530.05627" + y="79.672829" /> + <path + sodipodi:nodetypes="ccc" + id="path8412" + d="M -691.35811,5.367577 L -691.35811,2.5312809 L -691.35811,5.367577 z " + style="fill:#ffffff;fill-opacity:0.75688076;fill-rule:nonzero;stroke:none;stroke-width:0.5;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:4;stroke-opacity:1" /> + <g + style="opacity:0.40163933" + transform="matrix(-0.7946432,0,0,0.6605615,-3048.7709,702.09809)" + id="g8414" /> + <g + id="g8416" + transform="matrix(-0.7946432,0,0,0.6605615,-3048.7709,702.09809)" + style="opacity:0.40163933" /> + <g + id="g8418" + transform="matrix(1.0148767,0,0,0.6605615,199.80926,709.53496)" + style="opacity:0.40163933" /> + <g + style="opacity:0.40163933" + transform="matrix(1.0148767,0,0,0.6605615,199.80926,709.53496)" + id="g8420" /> + <path + sodipodi:nodetypes="ccc" + id="path9104" + d="M -55.553696,360.93168 L -55.553696,358.09539 L -55.553696,360.93168 z " + style="fill:#ffffff;fill-opacity:0.75688076;fill-rule:nonzero;stroke:none;stroke-width:0.5;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:4;stroke-opacity:1" /> + <path + sodipodi:nodetypes="ccc" + id="path9106" + d="M -214.89769,290.26066 L -214.89769,287.42437 L -214.89769,290.26066 z " + style="fill:#ffffff;fill-opacity:0.75688076;fill-rule:nonzero;stroke:none;stroke-width:0.5;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:4;stroke-opacity:1" /> + <path + sodipodi:nodetypes="ccc" + id="path9108" + d="M -336.17763,202.34167 L -336.17763,199.50539 L -336.17763,202.34167 z " + style="fill:#ffffff;fill-opacity:0.75688076;fill-rule:nonzero;stroke:none;stroke-width:0.5;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:4;stroke-opacity:1" /> + <g + id="g9110" + inkscape:label="box" + style="display:inline" + transform="matrix(1.0148767,0,0,1.0148767,-150.50435,349.07409)" /> + <g + id="g9112" + inkscape:label="zip_app" + style="display:inline" + transform="matrix(1.0148767,0,0,1.0148767,-150.50435,349.07409)" /> + <path + sodipodi:nodetypes="ccc" + id="path9114" + d="M -85.917879,269.07514 L -85.917879,266.23885 L -85.917879,269.07514 z " + style="fill:#ffffff;fill-opacity:0.75688076;fill-rule:nonzero;stroke:none;stroke-width:0.5;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:4;stroke-opacity:1" /> + <path + sodipodi:nodetypes="ccc" + id="path9116" + d="M -179.92023,344.06809 L -179.92023,342.51863 L -179.92023,344.06809 z " + style="fill:#ffffff;fill-opacity:0.75688076;fill-rule:nonzero;stroke:none;stroke-width:0.5;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:4;stroke-opacity:1" /> + <rect + style="opacity:0.57786889;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:3.63199997;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:4;stroke-opacity:1" + id="rect9118" + width="1.0148762" + height="0" + x="-238.26013" + y="286.62607" /> + <rect + style="opacity:0.57786889;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:3.63199997;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:4;stroke-opacity:1" + id="rect9120" + width="1.0148762" + height="0" + x="-273.90948" + y="258.68896" /> + <path + sodipodi:nodetypes="ccc" + id="path9122" + d="M -435.2113,184.38373 L -435.2113,181.54743 L -435.2113,184.38373 z " + style="fill:#ffffff;fill-opacity:0.75688076;fill-rule:nonzero;stroke:none;stroke-width:0.5;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:4;stroke-opacity:1" /> + <g + style="opacity:0.40163933" + transform="matrix(-0.7946432,0,0,0.6605615,-2792.6249,881.11422)" + id="g9124" /> + <g + id="g9126" + transform="matrix(-0.7946432,0,0,0.6605615,-2792.6249,881.11422)" + style="opacity:0.40163933" /> + <g + id="g9128" + transform="matrix(1.0148767,0,0,0.6605615,455.95601,888.55109)" + style="opacity:0.40163933" /> + <g + style="opacity:0.40163933" + transform="matrix(1.0148767,0,0,0.6605615,455.95601,888.55109)" + id="g9130" /> + <path + sodipodi:nodetypes="ccc" + id="path3633" + d="M -157.70057,123.8935 L -157.70057,121.0572 L -157.70057,123.8935 z " + style="fill:#ffffff;fill-opacity:0.75688076;fill-rule:nonzero;stroke:none;stroke-width:0.5;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:4;stroke-opacity:1" /> + <path + sodipodi:nodetypes="ccc" + id="path3635" + d="M -317.04457,53.222473 L -317.04457,50.386192 L -317.04457,53.222473 z " + style="fill:#ffffff;fill-opacity:0.75688076;fill-rule:nonzero;stroke:none;stroke-width:0.5;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:4;stroke-opacity:1" /> + <path + sodipodi:nodetypes="ccc" + id="path3637" + d="M -438.32452,-34.696491 L -438.32452,-37.532787 L -438.32452,-34.696491 z " + style="fill:#ffffff;fill-opacity:0.75688076;fill-rule:nonzero;stroke:none;stroke-width:0.5;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:4;stroke-opacity:1" /> + <g + id="g3639" + inkscape:label="box" + style="display:inline" + transform="matrix(1.0148767,0,0,1.0148767,-252.6514,112.03596)" /> + <g + id="g3641" + inkscape:label="zip_app" + style="display:inline" + transform="matrix(1.0148767,0,0,1.0148767,-252.6514,112.03596)" /> + <path + sodipodi:nodetypes="ccc" + id="path3643" + d="M -188.06476,32.036956 L -188.06476,29.200675 L -188.06476,32.036956 z " + style="fill:#ffffff;fill-opacity:0.75688076;fill-rule:nonzero;stroke:none;stroke-width:0.5;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:4;stroke-opacity:1" /> + <path + sodipodi:nodetypes="ccc" + id="path3645" + d="M -282.06711,107.02991 L -282.06711,105.48044 L -282.06711,107.02991 z " + style="fill:#ffffff;fill-opacity:0.75688076;fill-rule:nonzero;stroke:none;stroke-width:0.5;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:4;stroke-opacity:1" /> + <rect + style="opacity:0.57786889;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:3.63199997;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:4;stroke-opacity:1" + id="rect3647" + width="1.0148762" + height="0" + x="-340.40701" + y="49.587921" /> + <rect + style="opacity:0.57786889;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:3.63199997;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:4;stroke-opacity:1" + id="rect3649" + width="1.0148762" + height="0" + x="-376.0564" + y="21.650791" /> + <path + sodipodi:nodetypes="ccc" + id="path3651" + d="M -537.35819,-52.65445 L -537.35819,-55.490731 L -537.35819,-52.65445 z " + style="fill:#ffffff;fill-opacity:0.75688076;fill-rule:nonzero;stroke:none;stroke-width:0.5;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:4;stroke-opacity:1" /> + <g + style="opacity:0.40163933" + transform="matrix(-0.7946432,0,0,0.6605615,-2894.7709,644.07608)" + id="g3653" /> + <g + id="g3655" + transform="matrix(-0.7946432,0,0,0.6605615,-2894.7709,644.07608)" + style="opacity:0.40163933" /> + <g + id="g3657" + transform="matrix(1.0148767,0,0,0.6605615,353.80908,651.51294)" + style="opacity:0.40163933" /> + <g + style="opacity:0.40163933" + transform="matrix(1.0148767,0,0,0.6605615,353.80908,651.51294)" + id="g3659" /> + <rect + rx="2.0742123" + ry="2.4486284" + inkscape:r_cy="true" + inkscape:r_cx="true" + y="244.87613" + x="83.628647" + height="107.99998" + width="119.99998" + id="rect2894" + style="fill:url(#linearGradient7912);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:4;stroke-opacity:1" + inkscape:export-filename="/home/pinheiro/Desktop/mock2.png" + inkscape:export-xdpi="90" + inkscape:export-ydpi="90" /> + <path + sodipodi:nodetypes="ccc" + id="path10461" + d="M -155.66325,122.95497 L -155.66325,120.11867 L -155.66325,122.95497 z " + style="fill:#ffffff;fill-opacity:0.75688076;fill-rule:nonzero;stroke:none;stroke-width:0.5;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:4;stroke-opacity:1" /> + <path + sodipodi:nodetypes="ccc" + id="path10463" + d="M -315.00724,52.283945 L -315.00724,49.447664 L -315.00724,52.283945 z " + style="fill:#ffffff;fill-opacity:0.75688076;fill-rule:nonzero;stroke:none;stroke-width:0.5;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:4;stroke-opacity:1" /> + <path + sodipodi:nodetypes="ccc" + id="path10465" + d="M -436.28719,-35.635034 L -436.28719,-38.471315 L -436.28719,-35.635034 z " + style="fill:#ffffff;fill-opacity:0.75688076;fill-rule:nonzero;stroke:none;stroke-width:0.5;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:4;stroke-opacity:1" /> + <g + id="g10467" + inkscape:label="box" + style="display:inline" + transform="matrix(1.0148767,0,0,1.0148767,-250.61396,111.0974)" /> + <g + id="g10469" + inkscape:label="zip_app" + style="display:inline" + transform="matrix(1.0148767,0,0,1.0148767,-250.61396,111.0974)" /> + <path + sodipodi:nodetypes="ccc" + id="path10471" + d="M -186.02744,31.098428 L -186.02744,28.262146 L -186.02744,31.098428 z " + style="fill:#ffffff;fill-opacity:0.75688076;fill-rule:nonzero;stroke:none;stroke-width:0.5;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:4;stroke-opacity:1" /> + <path + sodipodi:nodetypes="ccc" + id="path10473" + d="M -280.02978,106.09138 L -280.02978,104.54192 L -280.02978,106.09138 z " + style="fill:#ffffff;fill-opacity:0.75688076;fill-rule:nonzero;stroke:none;stroke-width:0.5;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:4;stroke-opacity:1" /> + <rect + style="opacity:0.57786889;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:3.63199997;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:4;stroke-opacity:1" + id="rect10475" + width="1.0148762" + height="0" + x="-338.36966" + y="48.64938" /> + <rect + style="opacity:0.57786889;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:3.63199997;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:4;stroke-opacity:1" + id="rect10477" + width="1.0148762" + height="0" + x="-374.01904" + y="20.712275" /> + <path + sodipodi:nodetypes="ccc" + id="path10479" + d="M -535.32086,-53.592984 L -535.32086,-56.429268 L -535.32086,-53.592984 z " + style="fill:#ffffff;fill-opacity:0.75688076;fill-rule:nonzero;stroke:none;stroke-width:0.5;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:4;stroke-opacity:1" /> + <g + style="opacity:0.40163933" + transform="matrix(-0.7946432,0,0,0.6605615,-2892.7339,643.13752)" + id="g10481" /> + <g + id="g10483" + transform="matrix(-0.7946432,0,0,0.6605615,-2892.7339,643.13752)" + style="opacity:0.40163933" /> + <g + id="g10485" + transform="matrix(1.0148767,0,0,0.6605615,355.84651,650.57439)" + style="opacity:0.40163933" /> + <g + style="opacity:0.40163933" + transform="matrix(1.0148767,0,0,0.6605615,355.84651,650.57439)" + id="g10487" /> + <g + id="g10952" + transform="matrix(1.4999999,0,0,1.4999997,-39.814316,-120.43796)"> + <path + inkscape:export-ydpi="90" + inkscape:export-xdpi="90" + inkscape:export-filename="/home/pinheiro/Desktop/mock2.png" + sodipodi:type="arc" + style="opacity:1;fill:url(#linearGradient12912);fill-opacity:1;stroke:none;stroke-width:3.82999992;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:0.1375" + id="path2972" + sodipodi:cx="1055.3002" + sodipodi:cy="-478.60516" + sodipodi:rx="5.0602889" + sodipodi:ry="5.0602889" + d="M 1060.3605 -478.60516 A 5.0602889 5.0602889 0 1 1 1050.2399,-478.60516 A 5.0602889 5.0602889 0 1 1 1060.3605 -478.60516 z" + transform="matrix(0.7904687,0,0,0.7904687,-678.5531,631.1985)" /> + </g> + <path + sodipodi:nodetypes="ccc" + id="path2875" + d="M 148.21519,68.932055 L 148.21519,66.095774 L 148.21519,68.932055 z " + style="fill:#ffffff;fill-opacity:0.75688076;fill-rule:nonzero;stroke:none;stroke-width:0.5;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:4;stroke-opacity:1" /> + <path + sodipodi:nodetypes="ccc" + id="path2879" + d="M 13.247467,76.561684 L 13.247467,73.725388 L 13.247467,76.561684 z " + style="fill:#ffffff;fill-opacity:0.75688076;fill-rule:nonzero;stroke:none;stroke-width:0.5;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:4;stroke-opacity:1" /> + <path + sodipodi:nodetypes="ccc" + id="path2881" + d="M -146.09653,5.8906629 L -146.09653,3.0543815 L -146.09653,5.8906629 z " + style="fill:#ffffff;fill-opacity:0.75688076;fill-rule:nonzero;stroke:none;stroke-width:0.5;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:4;stroke-opacity:1" /> + <path + sodipodi:nodetypes="ccc" + id="path2883" + d="M -267.37648,-82.028304 L -267.37648,-84.864599 L -267.37648,-82.028304 z " + style="fill:#ffffff;fill-opacity:0.75688076;fill-rule:nonzero;stroke:none;stroke-width:0.5;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:4;stroke-opacity:1" /> + <g + id="g2885" + inkscape:label="box" + style="display:inline" + transform="matrix(1.0148767,0,0,1.0148767,-81.703147,64.704175)" /> + <g + id="g2887" + inkscape:label="zip_app" + style="display:inline" + transform="matrix(1.0148767,0,0,1.0148767,-81.703147,64.704175)" /> + <path + sodipodi:nodetypes="ccc" + id="path2889" + d="M -17.116717,-15.294854 L -17.116717,-18.131136 L -17.116717,-15.294854 z " + style="fill:#ffffff;fill-opacity:0.75688076;fill-rule:nonzero;stroke:none;stroke-width:0.5;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:4;stroke-opacity:1" /> + <path + sodipodi:nodetypes="ccc" + id="path2891" + d="M -111.11908,59.698095 L -111.11908,58.148648 L -111.11908,59.698095 z " + style="fill:#ffffff;fill-opacity:0.75688076;fill-rule:nonzero;stroke:none;stroke-width:0.5;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:4;stroke-opacity:1" /> + <rect + style="opacity:0.57786889;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:3.63199997;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:4;stroke-opacity:1" + id="rect2893" + width="1.0148762" + height="0" + x="-169.45897" + y="2.2560859" /> + <rect + style="opacity:0.57786889;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:3.63199997;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:4;stroke-opacity:1" + id="rect2895" + width="1.0148762" + height="0" + x="-205.10835" + y="-25.681009" /> + <path + sodipodi:nodetypes="ccc" + id="path2897" + d="M -366.41015,-99.98626 L -366.41015,-102.82255 L -366.41015,-99.98626 z " + style="fill:#ffffff;fill-opacity:0.75688076;fill-rule:nonzero;stroke:none;stroke-width:0.5;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:4;stroke-opacity:1" /> + <g + style="opacity:0.40163933" + transform="matrix(-0.7946432,0,0,0.6605615,-2723.823,596.7443)" + id="g2899" /> + <g + id="g2901" + transform="matrix(-0.7946432,0,0,0.6605615,-2723.823,596.7443)" + style="opacity:0.40163933" /> + <g + id="g2903" + transform="matrix(1.0148767,0,0,0.6605615,524.75712,604.18101)" + style="opacity:0.40163933" /> + <g + style="opacity:0.40163933" + transform="matrix(1.0148767,0,0,0.6605615,524.75712,604.18101)" + id="g2905" /> + <path + sodipodi:nodetypes="ccc" + id="path2907" + d="M 155.76156,235.68274 L 155.76156,232.84646 L 155.76156,235.68274 z " + style="fill:#ffffff;fill-opacity:0.75688076;fill-rule:nonzero;stroke:none;stroke-width:0.5;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:4;stroke-opacity:1" /> + <path + sodipodi:nodetypes="ccc" + id="path2909" + d="M -3.5824389,165.01172 L -3.5824389,162.17545 L -3.5824389,165.01172 z " + style="fill:#ffffff;fill-opacity:0.75688076;fill-rule:nonzero;stroke:none;stroke-width:0.5;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:4;stroke-opacity:1" /> + <path + sodipodi:nodetypes="ccc" + id="path2911" + d="M -124.86239,77.092757 L -124.86239,74.256475 L -124.86239,77.092757 z " + style="fill:#ffffff;fill-opacity:0.75688076;fill-rule:nonzero;stroke:none;stroke-width:0.5;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:4;stroke-opacity:1" /> + <g + id="g2913" + inkscape:label="box" + style="display:inline" + transform="matrix(1.0148767,0,0,1.0148767,60.810854,223.82517)" /> + <g + id="g2915" + inkscape:label="zip_app" + style="display:inline" + transform="matrix(1.0148767,0,0,1.0148767,60.810854,223.82517)" /> + <path + sodipodi:nodetypes="ccc" + id="path2917" + d="M 125.39737,143.8262 L 125.39737,140.98993 L 125.39737,143.8262 z " + style="fill:#ffffff;fill-opacity:0.75688076;fill-rule:nonzero;stroke:none;stroke-width:0.5;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:4;stroke-opacity:1" /> + <path + sodipodi:nodetypes="ccc" + id="path2919" + d="M 31.395018,218.81915 L 31.395018,217.26971 L 31.395018,218.81915 z " + style="fill:#ffffff;fill-opacity:0.75688076;fill-rule:nonzero;stroke:none;stroke-width:0.5;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:4;stroke-opacity:1" /> + <rect + style="opacity:0.57786889;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:3.63199997;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:4;stroke-opacity:1" + id="rect2921" + width="1.0148762" + height="0" + x="-26.94486" + y="161.37717" /> + <rect + style="opacity:0.57786889;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:3.63199997;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:4;stroke-opacity:1" + id="rect2923" + width="1.0148762" + height="0" + x="-62.594242" + y="133.44006" /> + <path + sodipodi:nodetypes="ccc" + id="path2925" + d="M -223.89606,59.134798 L -223.89606,56.298517 L -223.89606,59.134798 z " + style="fill:#ffffff;fill-opacity:0.75688076;fill-rule:nonzero;stroke:none;stroke-width:0.5;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:4;stroke-opacity:1" /> + <g + style="opacity:0.40163933" + transform="matrix(-0.7946432,0,0,0.6605615,-2581.3092,755.8653)" + id="g2927" /> + <g + id="g2929" + transform="matrix(-0.7946432,0,0,0.6605615,-2581.3092,755.8653)" + style="opacity:0.40163933" /> + <g + id="g2931" + transform="matrix(1.0148767,0,0,0.6605615,667.2712,763.30217)" + style="opacity:0.40163933" /> + <g + style="opacity:0.40163933" + transform="matrix(1.0148767,0,0,0.6605615,667.2712,763.30217)" + id="g2933" /> + <path + style="fill:url(#linearGradient7843);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:4;stroke-opacity:1" + d="M 85.69115,244.87613 C 84.542036,244.87613 83.62865,245.95709 83.62865,247.31362 L 83.62865,350.4386 C 83.62865,351.79515 84.542036,352.8761 85.69115,352.8761 L 201.56615,352.8761 C 202.71528,352.8761 203.62865,351.79515 203.62865,350.4386 L 203.62865,247.31362 C 203.62865,245.95709 202.71528,244.87613 201.56615,244.87613 L 85.69115,244.87613 z M 87.0974,248.53238 L 200.1599,248.53238 C 201.25156,248.53238 202.12865,249.55644 202.12865,250.82926 L 202.12865,349.07923 C 202.12865,350.35203 201.25156,351.3761 200.1599,351.3761 L 87.0974,351.3761 C 86.005743,351.3761 85.12865,350.35203 85.12865,349.07923 L 85.12865,250.82926 C 85.12865,249.55644 86.005743,248.53238 87.0974,248.53238 z " + id="rect3821" + sodipodi:nodetypes="cccccccccccccccccc" /> + <path + sodipodi:nodetypes="ccc" + id="path4109" + d="M -221.04685,-183.3058 L -221.04685,-187.15627 L -221.04685,-183.3058 z " + style="fill:#ffffff;fill-opacity:0.75688076;fill-rule:nonzero;stroke:none;stroke-width:0.5;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:4;stroke-opacity:1" /> + <path + sodipodi:nodetypes="ccc" + id="path4111" + d="M -404.27583,-172.94801 L -404.27583,-176.79848 L -404.27583,-172.94801 z " + style="fill:#ffffff;fill-opacity:0.75688076;fill-rule:nonzero;stroke:none;stroke-width:0.5;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:4;stroke-opacity:1" /> + <path + sodipodi:nodetypes="ccc" + id="path4113" + d="M -620.59744,-268.8893 L -620.59744,-272.73977 L -620.59744,-268.8893 z " + style="fill:#ffffff;fill-opacity:0.75688076;fill-rule:nonzero;stroke:none;stroke-width:0.5;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:4;stroke-opacity:1" /> + <path + sodipodi:nodetypes="ccc" + id="path4115" + d="M -785.24423,-388.246 L -785.24423,-392.09649 L -785.24423,-388.246 z " + style="fill:#ffffff;fill-opacity:0.75688076;fill-rule:nonzero;stroke:none;stroke-width:0.5;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:4;stroke-opacity:1" /> + <g + id="g4117" + inkscape:label="box" + style="display:inline" + transform="matrix(1.3777714,0,0,1.3777714,-533.1785,-189.04551)" /> + <g + id="g4119" + inkscape:label="zip_app" + style="display:inline" + transform="matrix(1.3777714,0,0,1.3777714,-533.1785,-189.04551)" /> + <path + sodipodi:nodetypes="ccc" + id="path4121" + d="M -445.49752,-297.65025 L -445.49752,-301.50073 L -445.49752,-297.65025 z " + style="fill:#ffffff;fill-opacity:0.75688076;fill-rule:nonzero;stroke:none;stroke-width:0.5;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:4;stroke-opacity:1" /> + <path + sodipodi:nodetypes="ccc" + id="path4123" + d="M -573.11289,-195.84162 L -573.11289,-197.94512 L -573.11289,-195.84162 z " + style="fill:#ffffff;fill-opacity:0.75688076;fill-rule:nonzero;stroke:none;stroke-width:0.5;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:4;stroke-opacity:1" /> + <rect + style="opacity:0.57786889;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:3.63199997;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:4;stroke-opacity:1" + id="rect4125" + width="1.377772" + height="0" + x="-652.31372" + y="-273.82349" /> + <rect + style="opacity:0.57786889;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:3.63199997;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:4;stroke-opacity:1" + id="rect4127" + width="1.377772" + height="0" + x="-700.71045" + y="-311.75027" /> + <path + sodipodi:nodetypes="ccc" + id="path4129" + d="M -919.69,-412.62529 L -919.69,-416.47578 L -919.69,-412.62529 z " + style="fill:#ffffff;fill-opacity:0.75688076;fill-rule:nonzero;stroke:none;stroke-width:0.5;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:4;stroke-opacity:1" /> + <g + style="opacity:0.40163933" + transform="matrix(-1.078788,0,0,0.8967627,-4120.0585,533.23945)" + id="g4131" /> + <g + id="g4133" + transform="matrix(-1.078788,0,0,0.8967627,-4120.0585,533.23945)" + style="opacity:0.40163933" /> + <g + id="g4135" + transform="matrix(1.3777714,0,0,0.8967627,290.13757,543.33536)" + style="opacity:0.40163933" /> + <g + style="opacity:0.40163933" + transform="matrix(1.3777714,0,0,0.8967627,290.13757,543.33536)" + id="g4137" /> + <path + sodipodi:nodetypes="ccc" + id="path4139" + d="M -210.80207,43.070976 L -210.80207,39.220511 L -210.80207,43.070976 z " + style="fill:#ffffff;fill-opacity:0.75688076;fill-rule:nonzero;stroke:none;stroke-width:0.5;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:4;stroke-opacity:1" /> + <path + sodipodi:nodetypes="ccc" + id="path4141" + d="M -427.1237,-52.870316 L -427.1237,-56.720788 L -427.1237,-52.870316 z " + style="fill:#ffffff;fill-opacity:0.75688076;fill-rule:nonzero;stroke:none;stroke-width:0.5;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:4;stroke-opacity:1" /> + <path + sodipodi:nodetypes="ccc" + id="path4143" + d="M -591.77047,-172.22704 L -591.77047,-176.07751 L -591.77047,-172.22704 z " + style="fill:#ffffff;fill-opacity:0.75688076;fill-rule:nonzero;stroke:none;stroke-width:0.5;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:4;stroke-opacity:1" /> + <g + id="g4145" + inkscape:label="box" + style="display:inline" + transform="matrix(1.3777714,0,0,1.3777714,-339.70493,26.973349)" /> + <g + id="g4147" + inkscape:label="zip_app" + style="display:inline" + transform="matrix(1.3777714,0,0,1.3777714,-339.70493,26.973349)" /> + <path + sodipodi:nodetypes="ccc" + id="path4149" + d="M -252.02378,-81.631278 L -252.02378,-85.48175 L -252.02378,-81.631278 z " + style="fill:#ffffff;fill-opacity:0.75688076;fill-rule:nonzero;stroke:none;stroke-width:0.5;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:4;stroke-opacity:1" /> + <path + sodipodi:nodetypes="ccc" + id="path4151" + d="M -379.63914,20.177365 L -379.63914,18.073877 L -379.63914,20.177365 z " + style="fill:#ffffff;fill-opacity:0.75688076;fill-rule:nonzero;stroke:none;stroke-width:0.5;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:4;stroke-opacity:1" /> + <rect + style="opacity:0.57786889;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:3.63199997;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:4;stroke-opacity:1" + id="rect4153" + width="1.377772" + height="0" + x="-458.84" + y="-57.804516" /> + <rect + style="opacity:0.57786889;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:3.63199997;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:4;stroke-opacity:1" + id="rect4155" + width="1.377772" + height="0" + x="-507.23672" + y="-95.731277" /> + <path + sodipodi:nodetypes="ccc" + id="path4157" + d="M -726.21624,-196.60632 L -726.21624,-200.4568 L -726.21624,-196.60632 z " + style="fill:#ffffff;fill-opacity:0.75688076;fill-rule:nonzero;stroke:none;stroke-width:0.5;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:4;stroke-opacity:1" /> + <g + style="opacity:0.40163933" + transform="matrix(-1.078788,0,0,0.8967627,-3926.5854,749.25849)" + id="g4159" /> + <g + id="g4161" + transform="matrix(-1.078788,0,0,0.8967627,-3926.5854,749.25849)" + style="opacity:0.40163933" /> + <g + id="g4163" + transform="matrix(1.3777714,0,0,0.8967627,483.61129,759.35456)" + style="opacity:0.40163933" /> + <g + style="opacity:0.40163933" + transform="matrix(1.3777714,0,0,0.8967627,483.61129,759.35456)" + id="g4165" /> + <path + sodipodi:nodetypes="ccc" + id="path4167" + d="M -279.00178,-28.573161 L -279.00178,-32.42364 L -279.00178,-28.573161 z " + style="fill:#ffffff;fill-opacity:0.75688076;fill-rule:nonzero;stroke:none;stroke-width:0.5;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:4;stroke-opacity:1" /> + <path + sodipodi:nodetypes="ccc" + id="path4169" + d="M -495.32341,-124.51446 L -495.32341,-128.36493 L -495.32341,-124.51446 z " + style="fill:#ffffff;fill-opacity:0.75688076;fill-rule:nonzero;stroke:none;stroke-width:0.5;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:4;stroke-opacity:1" /> + <path + sodipodi:nodetypes="ccc" + id="path4171" + d="M -659.97018,-243.87117 L -659.97018,-247.72165 L -659.97018,-243.87117 z " + style="fill:#ffffff;fill-opacity:0.75688076;fill-rule:nonzero;stroke:none;stroke-width:0.5;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:4;stroke-opacity:1" /> + <g + id="g4173" + inkscape:label="box" + style="display:inline" + transform="matrix(1.3777714,0,0,1.3777714,-407.90465,-44.670655)" /> + <g + id="g4175" + inkscape:label="zip_app" + style="display:inline" + transform="matrix(1.3777714,0,0,1.3777714,-407.90465,-44.670655)" /> + <path + sodipodi:nodetypes="ccc" + id="path4177" + d="M -320.22348,-153.27542 L -320.22348,-157.12589 L -320.22348,-153.27542 z " + style="fill:#ffffff;fill-opacity:0.75688076;fill-rule:nonzero;stroke:none;stroke-width:0.5;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:4;stroke-opacity:1" /> + <path + sodipodi:nodetypes="ccc" + id="path4179" + d="M -447.83885,-51.466781 L -447.83885,-53.570274 L -447.83885,-51.466781 z " + style="fill:#ffffff;fill-opacity:0.75688076;fill-rule:nonzero;stroke:none;stroke-width:0.5;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:4;stroke-opacity:1" /> + <rect + style="opacity:0.57786889;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:3.63199997;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:4;stroke-opacity:1" + id="rect4181" + width="1.377772" + height="0" + x="-527.03967" + y="-129.44864" /> + <rect + style="opacity:0.57786889;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:3.63199997;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:4;stroke-opacity:1" + id="rect4184" + width="1.377772" + height="0" + x="-575.43646" + y="-167.37541" /> + <path + sodipodi:nodetypes="ccc" + id="path4186" + d="M -794.41595,-268.25047 L -794.41595,-272.10094 L -794.41595,-268.25047 z " + style="fill:#ffffff;fill-opacity:0.75688076;fill-rule:nonzero;stroke:none;stroke-width:0.5;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:4;stroke-opacity:1" /> + <g + style="opacity:0.40163933" + transform="matrix(-1.078788,0,0,0.8967627,-3994.7851,677.61424)" + id="g4188" /> + <g + id="g4190" + transform="matrix(-1.078788,0,0,0.8967627,-3994.7851,677.61424)" + style="opacity:0.40163933" /> + <g + id="g4192" + transform="matrix(1.3777714,0,0,0.8967627,415.41173,687.71031)" + style="opacity:0.40163933" /> + <g + style="opacity:0.40163933" + transform="matrix(1.3777714,0,0,0.8967627,415.41173,687.71031)" + id="g4194" /> + <path + sodipodi:nodetypes="ccc" + id="path4196" + d="M -812.54397,141.92612 L -812.54397,138.07564 L -812.54397,141.92612 z " + style="fill:#ffffff;fill-opacity:0.75688076;fill-rule:nonzero;stroke:none;stroke-width:0.5;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:4;stroke-opacity:1" /> + <path + sodipodi:nodetypes="ccc" + id="path4198" + d="M -1028.8656,45.984831 L -1028.8656,42.134352 L -1028.8656,45.984831 z " + style="fill:#ffffff;fill-opacity:0.75688076;fill-rule:nonzero;stroke:none;stroke-width:0.5;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:4;stroke-opacity:1" /> + <path + sodipodi:nodetypes="ccc" + id="path4200" + d="M -1193.5124,-73.371901 L -1193.5124,-77.222373 L -1193.5124,-73.371901 z " + style="fill:#ffffff;fill-opacity:0.75688076;fill-rule:nonzero;stroke:none;stroke-width:0.5;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:4;stroke-opacity:1" /> + <g + id="g4202" + inkscape:label="box" + style="display:inline" + transform="matrix(1.3777714,0,0,1.3777714,-941.44678,125.82854)" /> + <g + id="g4204" + inkscape:label="zip_app" + style="display:inline" + transform="matrix(1.3777714,0,0,1.3777714,-941.44678,125.82854)" /> + <path + sodipodi:nodetypes="ccc" + id="path4206" + d="M -853.76566,17.223876 L -853.76566,13.373397 L -853.76566,17.223876 z " + style="fill:#ffffff;fill-opacity:0.75688076;fill-rule:nonzero;stroke:none;stroke-width:0.5;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:4;stroke-opacity:1" /> + <path + sodipodi:nodetypes="ccc" + id="path4208" + d="M -981.38102,119.03251 L -981.38102,116.92901 L -981.38102,119.03251 z " + style="fill:#ffffff;fill-opacity:0.75688076;fill-rule:nonzero;stroke:none;stroke-width:0.5;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:4;stroke-opacity:1" /> + <rect + style="opacity:0.57786889;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:3.63199997;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:4;stroke-opacity:1" + id="rect4210" + width="1.377772" + height="0" + x="-1060.5818" + y="41.050621" /> + <rect + style="opacity:0.57786889;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:3.63199997;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:4;stroke-opacity:1" + id="rect4212" + width="1.377772" + height="0" + x="-1108.9786" + y="3.1238759" /> + <path + sodipodi:nodetypes="ccc" + id="path4214" + d="M -1327.9581,-97.75119 L -1327.9581,-101.60167 L -1327.9581,-97.75119 z " + style="fill:#ffffff;fill-opacity:0.75688076;fill-rule:nonzero;stroke:none;stroke-width:0.5;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:4;stroke-opacity:1" /> + <g + style="opacity:0.40163933" + transform="matrix(-1.078788,0,0,0.8967627,-4528.3268,848.11353)" + id="g4216" /> + <g + id="g4218" + transform="matrix(-1.078788,0,0,0.8967627,-4528.3268,848.11353)" + style="opacity:0.40163933" /> + <g + id="g4220" + transform="matrix(1.3777714,0,0,0.8967627,-118.13056,858.20959)" + style="opacity:0.40163933" /> + <g + style="opacity:0.40163933" + transform="matrix(1.3777714,0,0,0.8967627,-118.13056,858.20959)" + id="g4222" /> + <path + sodipodi:nodetypes="ccc" + id="path4224" + d="M -464.80515,384.9542 L -464.80515,381.10373 L -464.80515,384.9542 z " + style="fill:#ffffff;fill-opacity:0.75688076;fill-rule:nonzero;stroke:none;stroke-width:0.5;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:4;stroke-opacity:1" /> + <path + sodipodi:nodetypes="ccc" + id="path4226" + d="M -681.12676,289.01289 L -681.12676,285.16244 L -681.12676,289.01289 z " + style="fill:#ffffff;fill-opacity:0.75688076;fill-rule:nonzero;stroke:none;stroke-width:0.5;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:4;stroke-opacity:1" /> + <path + sodipodi:nodetypes="ccc" + id="path4228" + d="M -845.77355,169.65618 L -845.77355,165.80572 L -845.77355,169.65618 z " + style="fill:#ffffff;fill-opacity:0.75688076;fill-rule:nonzero;stroke:none;stroke-width:0.5;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:4;stroke-opacity:1" /> + <g + id="g4230" + inkscape:label="box" + style="display:inline" + transform="matrix(1.3777714,0,0,1.3777714,-593.70797,368.85658)" /> + <g + id="g4232" + inkscape:label="zip_app" + style="display:inline" + transform="matrix(1.3777714,0,0,1.3777714,-593.70797,368.85658)" /> + <path + sodipodi:nodetypes="ccc" + id="path4234" + d="M -506.02685,260.25196 L -506.02685,256.40147 L -506.02685,260.25196 z " + style="fill:#ffffff;fill-opacity:0.75688076;fill-rule:nonzero;stroke:none;stroke-width:0.5;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:4;stroke-opacity:1" /> + <path + sodipodi:nodetypes="ccc" + id="path4236" + d="M -633.64221,362.06058 L -633.64221,359.95708 L -633.64221,362.06058 z " + style="fill:#ffffff;fill-opacity:0.75688076;fill-rule:nonzero;stroke:none;stroke-width:0.5;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:4;stroke-opacity:1" /> + <rect + style="opacity:0.57786889;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:3.63199997;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:4;stroke-opacity:1" + id="rect4238" + width="1.377772" + height="0" + x="-712.84308" + y="284.07864" /> + <rect + style="opacity:0.57786889;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:3.63199997;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:4;stroke-opacity:1" + id="rect4240" + width="1.377772" + height="0" + x="-761.23975" + y="246.1519" /> + <path + sodipodi:nodetypes="ccc" + id="path4242" + d="M -980.21932,145.27689 L -980.21932,141.42643 L -980.21932,145.27689 z " + style="fill:#ffffff;fill-opacity:0.75688076;fill-rule:nonzero;stroke:none;stroke-width:0.5;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:4;stroke-opacity:1" /> + <g + style="opacity:0.40163933" + transform="matrix(-1.078788,0,0,0.8967627,-4180.588,1091.1417)" + id="g4244" /> + <g + id="g4246" + transform="matrix(-1.078788,0,0,0.8967627,-4180.588,1091.1417)" + style="opacity:0.40163933" /> + <g + id="g4248" + transform="matrix(1.3777714,0,0,0.8967627,229.60826,1101.2376)" + style="opacity:0.40163933" /> + <g + style="opacity:0.40163933" + transform="matrix(1.3777714,0,0,0.8967627,229.60826,1101.2376)" + id="g4250" /> + <path + sodipodi:nodetypes="ccc" + id="path4252" + d="M -603.47732,63.156795 L -603.47732,59.306316 L -603.47732,63.156795 z " + style="fill:#ffffff;fill-opacity:0.75688076;fill-rule:nonzero;stroke:none;stroke-width:0.5;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:4;stroke-opacity:1" /> + <path + sodipodi:nodetypes="ccc" + id="path4254" + d="M -819.79895,-32.784494 L -819.79895,-36.634972 L -819.79895,-32.784494 z " + style="fill:#ffffff;fill-opacity:0.75688076;fill-rule:nonzero;stroke:none;stroke-width:0.5;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:4;stroke-opacity:1" /> + <path + sodipodi:nodetypes="ccc" + id="path4256" + d="M -984.44573,-152.14121 L -984.44573,-155.99168 L -984.44573,-152.14121 z " + style="fill:#ffffff;fill-opacity:0.75688076;fill-rule:nonzero;stroke:none;stroke-width:0.5;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:4;stroke-opacity:1" /> + <g + id="g4258" + inkscape:label="box" + style="display:inline" + transform="matrix(1.3777714,0,0,1.3777714,-732.38027,47.059197)" /> + <g + id="g4260" + inkscape:label="zip_app" + style="display:inline" + transform="matrix(1.3777714,0,0,1.3777714,-732.38027,47.059197)" /> + <path + sodipodi:nodetypes="ccc" + id="path4262" + d="M -644.69902,-61.545463 L -644.69902,-65.395935 L -644.69902,-61.545463 z " + style="fill:#ffffff;fill-opacity:0.75688076;fill-rule:nonzero;stroke:none;stroke-width:0.5;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:4;stroke-opacity:1" /> + <path + sodipodi:nodetypes="ccc" + id="path4264" + d="M -772.31439,40.263185 L -772.31439,38.159681 L -772.31439,40.263185 z " + style="fill:#ffffff;fill-opacity:0.75688076;fill-rule:nonzero;stroke:none;stroke-width:0.5;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:4;stroke-opacity:1" /> + <rect + style="opacity:0.57786889;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:3.63199997;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:4;stroke-opacity:1" + id="rect4266" + width="1.377772" + height="0" + x="-851.51532" + y="-37.718704" /> + <rect + style="opacity:0.57786889;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:3.63199997;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:4;stroke-opacity:1" + id="rect4268" + width="1.377772" + height="0" + x="-899.91205" + y="-75.645462" /> + <path + sodipodi:nodetypes="ccc" + id="path4270" + d="M -1118.8915,-176.52051 L -1118.8915,-180.37098 L -1118.8915,-176.52051 z " + style="fill:#ffffff;fill-opacity:0.75688076;fill-rule:nonzero;stroke:none;stroke-width:0.5;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:4;stroke-opacity:1" /> + <g + style="opacity:0.40163933" + transform="matrix(-1.078788,0,0,0.8967627,-4319.2592,769.34433)" + id="g4272" /> + <g + id="g4274" + transform="matrix(-1.078788,0,0,0.8967627,-4319.2592,769.34433)" + style="opacity:0.40163933" /> + <g + id="g4276" + transform="matrix(1.3777714,0,0,0.8967627,90.936098,779.4404)" + style="opacity:0.40163933" /> + <g + style="opacity:0.40163933" + transform="matrix(1.3777714,0,0,0.8967627,90.936098,779.4404)" + id="g4278" /> + <path + sodipodi:nodetypes="ccc" + id="path4284" + d="M -600.7115,61.88267 L -600.7115,58.032192 L -600.7115,61.88267 z " + style="fill:#ffffff;fill-opacity:0.75688076;fill-rule:nonzero;stroke:none;stroke-width:0.5;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:4;stroke-opacity:1" /> + <path + sodipodi:nodetypes="ccc" + id="path4286" + d="M -817.03314,-34.058632 L -817.03314,-37.909104 L -817.03314,-34.058632 z " + style="fill:#ffffff;fill-opacity:0.75688076;fill-rule:nonzero;stroke:none;stroke-width:0.5;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:4;stroke-opacity:1" /> + <path + sodipodi:nodetypes="ccc" + id="path4288" + d="M -981.67991,-153.41535 L -981.67991,-157.26582 L -981.67991,-153.41535 z " + style="fill:#ffffff;fill-opacity:0.75688076;fill-rule:nonzero;stroke:none;stroke-width:0.5;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:4;stroke-opacity:1" /> + <g + id="g4290" + inkscape:label="box" + style="display:inline" + transform="matrix(1.3777714,0,0,1.3777714,-729.61435,45.785103)" /> + <g + id="g4292" + inkscape:label="zip_app" + style="display:inline" + transform="matrix(1.3777714,0,0,1.3777714,-729.61435,45.785103)" /> + <path + sodipodi:nodetypes="ccc" + id="path4294" + d="M -641.93321,-62.819593 L -641.93321,-66.670065 L -641.93321,-62.819593 z " + style="fill:#ffffff;fill-opacity:0.75688076;fill-rule:nonzero;stroke:none;stroke-width:0.5;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:4;stroke-opacity:1" /> + <path + sodipodi:nodetypes="ccc" + id="path4296" + d="M -769.54857,38.98906 L -769.54857,36.885557 L -769.54857,38.98906 z " + style="fill:#ffffff;fill-opacity:0.75688076;fill-rule:nonzero;stroke:none;stroke-width:0.5;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:4;stroke-opacity:1" /> + <rect + style="opacity:0.57786889;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:3.63199997;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:4;stroke-opacity:1" + id="rect4298" + width="1.377772" + height="0" + x="-848.74945" + y="-38.992832" /> + <rect + style="opacity:0.57786889;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:3.63199997;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:4;stroke-opacity:1" + id="rect4300" + width="1.377772" + height="0" + x="-897.14618" + y="-76.919586" /> + <path + sodipodi:nodetypes="ccc" + id="path4302" + d="M -1116.1257,-177.79464 L -1116.1257,-181.64512 L -1116.1257,-177.79464 z " + style="fill:#ffffff;fill-opacity:0.75688076;fill-rule:nonzero;stroke:none;stroke-width:0.5;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:4;stroke-opacity:1" /> + <g + style="opacity:0.40163933" + transform="matrix(-1.078788,0,0,0.8967627,-4316.4943,768.07009)" + id="g4304" /> + <g + id="g4306" + transform="matrix(-1.078788,0,0,0.8967627,-4316.4943,768.07009)" + style="opacity:0.40163933" /> + <g + id="g4308" + transform="matrix(1.3777714,0,0,0.8967627,93.701877,778.16616)" + style="opacity:0.40163933" /> + <g + style="opacity:0.40163933" + transform="matrix(1.3777714,0,0,0.8967627,93.701877,778.16616)" + id="g4310" /> + <path + sodipodi:nodetypes="cccc" + id="path4356" + d="M -188.17335,-11.457543 L -188.17335,-24.027191 L -188.17335,-15.308022 L -188.17335,-11.457543 z " + style="fill:#ffffff;fill-opacity:0.75688076;fill-rule:nonzero;stroke:none;stroke-width:0.5;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:4;stroke-opacity:1" /> + <path + sodipodi:nodetypes="ccc" + id="path4358" + d="M -371.40232,-1.0997485 L -371.40232,-4.9502274 L -371.40232,-1.0997485 z " + style="fill:#ffffff;fill-opacity:0.75688076;fill-rule:nonzero;stroke:none;stroke-width:0.5;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:4;stroke-opacity:1" /> + <path + sodipodi:nodetypes="ccc" + id="path4360" + d="M -587.72396,-97.04105 L -587.72396,-100.89152 L -587.72396,-97.04105 z " + style="fill:#ffffff;fill-opacity:0.75688076;fill-rule:nonzero;stroke:none;stroke-width:0.5;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:4;stroke-opacity:1" /> + <path + sodipodi:nodetypes="ccc" + id="path4362" + d="M -752.37073,-216.39776 L -752.37073,-220.24824 L -752.37073,-216.39776 z " + style="fill:#ffffff;fill-opacity:0.75688076;fill-rule:nonzero;stroke:none;stroke-width:0.5;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:4;stroke-opacity:1" /> + <g + id="g4364" + inkscape:label="box" + style="display:inline" + transform="matrix(1.3777714,0,0,1.3777714,-500.30506,-17.197346)" /> + <g + id="g4366" + inkscape:label="zip_app" + style="display:inline" + transform="matrix(1.3777714,0,0,1.3777714,-500.30506,-17.197346)" /> + <path + sodipodi:nodetypes="ccc" + id="path4368" + d="M -412.62402,-125.802 L -412.62402,-129.65248 L -412.62402,-125.802 z " + style="fill:#ffffff;fill-opacity:0.75688076;fill-rule:nonzero;stroke:none;stroke-width:0.5;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:4;stroke-opacity:1" /> + <path + sodipodi:nodetypes="ccc" + id="path4370" + d="M -540.23937,-23.993359 L -540.23937,-26.096862 L -540.23937,-23.993359 z " + style="fill:#ffffff;fill-opacity:0.75688076;fill-rule:nonzero;stroke:none;stroke-width:0.5;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:4;stroke-opacity:1" /> + <rect + style="opacity:0.57786889;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:3.63199997;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:4;stroke-opacity:1" + id="rect4372" + width="1.377772" + height="0" + x="-619.44025" + y="-101.97524" /> + <rect + style="opacity:0.57786889;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:3.63199997;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:4;stroke-opacity:1" + id="rect4374" + width="1.377772" + height="0" + x="-667.83704" + y="-139.90201" /> + <path + sodipodi:nodetypes="ccc" + id="path4376" + d="M -886.81649,-240.77705 L -886.81649,-244.62753 L -886.81649,-240.77705 z " + style="fill:#ffffff;fill-opacity:0.75688076;fill-rule:nonzero;stroke:none;stroke-width:0.5;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:4;stroke-opacity:1" /> + <g + style="opacity:0.40163933" + transform="matrix(-1.078788,0,0,0.8967627,-4087.1854,705.08781)" + id="g4378" /> + <g + id="g4380" + transform="matrix(-1.078788,0,0,0.8967627,-4087.1854,705.08781)" + style="opacity:0.40163933" /> + <g + id="g4382" + transform="matrix(1.3777714,0,0,0.8967627,323.01116,715.18372)" + style="opacity:0.40163933" /> + <g + style="opacity:0.40163933" + transform="matrix(1.3777714,0,0,0.8967627,323.01116,715.18372)" + id="g4384" /> + <path + sodipodi:nodetypes="ccc" + id="path4386" + d="M -177.92858,214.91924 L -177.92858,211.06876 L -177.92858,214.91924 z " + style="fill:#ffffff;fill-opacity:0.75688076;fill-rule:nonzero;stroke:none;stroke-width:0.5;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:4;stroke-opacity:1" /> + <path + sodipodi:nodetypes="ccc" + id="path4388" + d="M -394.2502,118.97794 L -394.2502,115.12747 L -394.2502,118.97794 z " + style="fill:#ffffff;fill-opacity:0.75688076;fill-rule:nonzero;stroke:none;stroke-width:0.5;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:4;stroke-opacity:1" /> + <path + sodipodi:nodetypes="ccc" + id="path4390" + d="M -558.89698,-0.3787802 L -558.89698,-4.2292443 L -558.89698,-0.3787802 z " + style="fill:#ffffff;fill-opacity:0.75688076;fill-rule:nonzero;stroke:none;stroke-width:0.5;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:4;stroke-opacity:1" /> + <g + id="g4392" + inkscape:label="box" + style="display:inline" + transform="matrix(1.3777714,0,0,1.3777714,-306.83133,198.82157)" /> + <g + id="g4394" + inkscape:label="zip_app" + style="display:inline" + transform="matrix(1.3777714,0,0,1.3777714,-306.83133,198.82157)" /> + <path + sodipodi:nodetypes="ccc" + id="path4396" + d="M -219.15028,90.216979 L -219.15028,86.366515 L -219.15028,90.216979 z " + style="fill:#ffffff;fill-opacity:0.75688076;fill-rule:nonzero;stroke:none;stroke-width:0.5;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:4;stroke-opacity:1" /> + <path + sodipodi:nodetypes="ccc" + id="path4398" + d="M -346.76564,192.02563 L -346.76564,189.92213 L -346.76564,192.02563 z " + style="fill:#ffffff;fill-opacity:0.75688076;fill-rule:nonzero;stroke:none;stroke-width:0.5;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:4;stroke-opacity:1" /> + <rect + style="opacity:0.57786889;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:3.63199997;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:4;stroke-opacity:1" + id="rect4400" + width="1.377772" + height="0" + x="-425.96643" + y="114.04373" /> + <rect + style="opacity:0.57786889;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:3.63199997;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:4;stroke-opacity:1" + id="rect4402" + width="1.377772" + height="0" + x="-474.36322" + y="76.116974" /> + <path + sodipodi:nodetypes="ccc" + id="path4404" + d="M -693.34274,-24.758066 L -693.34274,-28.608545 L -693.34274,-24.758066 z " + style="fill:#ffffff;fill-opacity:0.75688076;fill-rule:nonzero;stroke:none;stroke-width:0.5;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:4;stroke-opacity:1" /> + <g + style="opacity:0.40163933" + transform="matrix(-1.078788,0,0,0.8967627,-3893.7122,921.10671)" + id="g4406" /> + <g + id="g4408" + transform="matrix(-1.078788,0,0,0.8967627,-3893.7122,921.10671)" + style="opacity:0.40163933" /> + <g + id="g4410" + transform="matrix(1.3777714,0,0,0.8967627,516.48488,931.20277)" + style="opacity:0.40163933" /> + <g + style="opacity:0.40163933" + transform="matrix(1.3777714,0,0,0.8967627,516.48488,931.20277)" + id="g4412" /> + <path + style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.67876971;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dashoffset:4;stroke-opacity:1" + d="M 83.62865,276.8761 L 203.62865,276.8761 L 203.62865,352.8761 L 83.62865,352.8761 L 83.62865,276.8761 z " + id="rect8568" /> + <use + x="0" + y="0" + xlink:href="#g10952" + id="use10958" + transform="translate(-16,-2.4e-6)" + width="96" + height="96" /> + <use + x="0" + y="0" + xlink:href="#g10952" + id="use10968" + transform="translate(-32,-2.4e-6)" + width="96" + height="96" /> + <use + x="0" + y="0" + xlink:href="#g10952" + id="use10972" + transform="translate(-96,-2.4e-6)" + width="96" + height="96" /> + <path + style="opacity:1;fill:url(#linearGradient3493);fill-opacity:1;stroke:none;stroke-width:1.10000001999999997;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" + d="M 10 52 C 8.892 52 8.0000002 52.891999 8 54 C 8 55.108 8.8919997 55.999999 10 56 L 70 56 C 71.108 56 71.999997 55.107999 72 54 C 72 52.892 71.107997 51.999999 70 52 L 10 52 z M 86 52 C 84.892 52 83.999997 52.557499 84 53.25 L 84 54.75 C 84 55.4425 84.891997 55.999999 86 56 L 94 56 C 95.108 56 96 55.442499 96 54.75 L 96 53.25 C 96 52.5575 95.108 51.999999 94 52 L 86 52 z M 110 52 C 108.892 52 108 52.557499 108 53.25 L 108 54.75 C 108 55.4425 108.892 55.999999 110 56 L 118 56 C 119.108 56 120 55.442499 120 54.75 L 120 53.25 C 120 52.5575 119.108 51.999999 118 52 L 110 52 z M 10 68 C 8.892 68 8.0000002 68.891999 8 70 C 8 71.108 8.8919997 71.999999 10 72 L 70 72 C 71.108 72 71.999997 71.107999 72 70 C 72 68.892 71.107997 67.999999 70 68 L 10 68 z M 86 68 C 84.892 68 83.999997 68.557499 84 69.25 L 84 70.75 C 84 71.4425 84.891997 71.999999 86 72 L 94 72 C 95.108 72 96 71.442499 96 70.75 L 96 69.25 C 96 68.5575 95.108 67.999999 94 68 L 86 68 z M 110 68 C 108.892 68 108 68.557499 108 69.25 L 108 70.75 C 108 71.4425 108.892 71.999999 110 72 L 118 72 C 119.108 72 120 71.442499 120 70.75 L 120 69.25 C 120 68.5575 119.108 67.999999 118 68 L 110 68 z M 10 84 C 8.892 84 8.0000002 84.891999 8 86 C 8 87.108 8.8919997 87.999999 10 88 L 58 88 C 59.108 88 60.000001 87.107999 60 86 C 60 84.892 59.108001 83.999999 58 84 L 10 84 z M 86 84 C 84.892 84 83.999997 84.891999 84 86 C 84 87.108 84.891997 87.999999 86 88 L 90 88 C 91.108 88 92 87.107999 92 86 C 92 84.892 91.108 83.999999 90 84 L 86 84 z M 110 84 C 108.892 84 108 84.557499 108 85.25 L 108 86.75 C 108 87.4425 108.892 87.999999 110 88 L 118 88 C 119.108 88 120 87.442499 120 86.75 L 120 85.25 C 120 84.5575 119.108 83.999999 118 84 L 110 84 z M 10 100 C 8.892 100 8.0000002 100.892 8 102 C 8 103.108 8.8919997 104 10 104 L 70 104 C 71.108 104 71.999997 103.108 72 102 C 72 100.892 71.107997 99.999999 70 100 L 10 100 z M 86 100 C 84.892 100 83.999997 100.5575 84 101.25 L 84 102.75 C 84 103.4425 84.891997 104 86 104 L 94 104 C 95.108 104 96 103.4425 96 102.75 L 96 101.25 C 96 100.5575 95.108 99.999999 94 100 L 86 100 z M 110 100 C 108.892 100 108 100.5575 108 101.25 L 108 102.75 C 108 103.4425 108.892 104 110 104 L 118 104 C 119.108 104 120 103.4425 120 102.75 L 120 101.25 C 120 100.5575 119.108 99.999999 118 100 L 110 100 z " + transform="translate(79.62865,236.8761)" + id="rect2692" /> + </g> +</svg> diff --git a/spec/View_spec.rb b/spec/View_spec.rb new file mode 100644 index 0000000..7a90a01 --- /dev/null +++ b/spec/View_spec.rb @@ -0,0 +1,61 @@ +#!/usr/bin/env ruby -w +# encoding: UTF-8 +# +# = View_spec.rb -- PostRunner - Manage the data from your Garmin sport devices. +# +# Copyright (c) 2015 by Chris Schlaeger <cs@taskjuggler.org> +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of version 2 of the GNU General Public License as +# published by the Free Software Foundation. +# + +require 'postrunner/View' +require 'postrunner/ViewButtons' +require 'postrunner/PagingButtons' + +module PostRunner + + describe PostRunner::View do + + before(:all) do + @view_names = %w( activities record ) + delete_files + end + + after(:all) do + delete_files + end + + def delete_files + @view_names.each do |vn| + page_files(vn).each do |pf| + File.delete(pf) if File.exists?(pf) + end + end + end + + def page_files(vn) + 1.upto(vn == 'record' ? 5 : 3).map { |i| "#{vn}-page#{i}.html" } + end + + it 'should generate view files with multiple pages' do + views = ViewButtons.new( + @view_names.map{ |vn| NavButtonDef. + new("#{vn}.png", "#{vn}-page1.html") } + ) + @view_names.each do |vn| + views.current_page = vn + '-page1.html' + pages = PagingButtons.new(page_files(vn)) + page_files(vn).each do |file| + pages.current_page = file + PostRunner::View.new("Test File: #{file}", views, pages).body. + write(file) + File.exists?(file).should be true + end + end + end + + end + +end |