fgmapping 1.0.1
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG +4 -0
- data/LICENSE +340 -0
- data/Manifest +22 -0
- data/README +40 -0
- data/Rakefile +13 -0
- data/bin/flightgear-mapping +18 -0
- data/fgmap.gemspec +32 -0
- data/fgmapping.gemspec +32 -0
- data/lib/LICENSE +340 -0
- data/lib/README +40 -0
- data/lib/bsearch.rb +120 -0
- data/lib/hud-impl.rb +20 -0
- data/lib/hud-widget.rb +172 -0
- data/lib/init.rb +18 -0
- data/lib/main-dlg-impl.rb +1117 -0
- data/lib/main-dlg.rb +224 -0
- data/lib/navaid.rb +177 -0
- data/lib/nodeinfo-impl.rb +46 -0
- data/lib/nodeinfo-widget.rb +152 -0
- data/lib/resources.rb +5206 -0
- data/lib/tile.rb +216 -0
- data/lib/waypoint.rb +29 -0
- metadata +106 -0
data/lib/hud-impl.rb
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
require "hud-widget"
|
2
|
+
|
3
|
+
# Class MainDlg ############################################
|
4
|
+
class HudWidget < Qt::Widget
|
5
|
+
attr_reader :w
|
6
|
+
|
7
|
+
def initialize parent=nil
|
8
|
+
super
|
9
|
+
@w=Ui::HudWidget.new
|
10
|
+
@w.setupUi(self)
|
11
|
+
@parent=parent
|
12
|
+
|
13
|
+
end
|
14
|
+
|
15
|
+
def pBexit_clicked()
|
16
|
+
p @w.pBexit.text
|
17
|
+
@parent.close
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
data/lib/hud-widget.rb
ADDED
@@ -0,0 +1,172 @@
|
|
1
|
+
=begin
|
2
|
+
** Form generated from reading ui file 'hud-widget.ui'
|
3
|
+
**
|
4
|
+
** Created: Fr. Jun 11 14:41:10 2010
|
5
|
+
** by: Qt User Interface Compiler version 4.6.2
|
6
|
+
**
|
7
|
+
** WARNING! All changes made in this file will be lost when recompiling ui file!
|
8
|
+
=end
|
9
|
+
|
10
|
+
class Ui_HudWidget
|
11
|
+
attr_reader :verticalLayout
|
12
|
+
attr_reader :lBspeed
|
13
|
+
attr_reader :lBdistance
|
14
|
+
attr_reader :gridLayout
|
15
|
+
attr_reader :label_4
|
16
|
+
attr_reader :lBalt
|
17
|
+
attr_reader :label_3
|
18
|
+
attr_reader :lBheading
|
19
|
+
attr_reader :label_6
|
20
|
+
attr_reader :lBlat
|
21
|
+
attr_reader :label_5
|
22
|
+
attr_reader :lBlon
|
23
|
+
|
24
|
+
def setupUi(hudWidget)
|
25
|
+
if hudWidget.objectName.nil?
|
26
|
+
hudWidget.objectName = "hudWidget"
|
27
|
+
end
|
28
|
+
hudWidget.resize(161, 130)
|
29
|
+
@sizePolicy = Qt::SizePolicy.new(Qt::SizePolicy::MinimumExpanding, Qt::SizePolicy::MinimumExpanding)
|
30
|
+
@sizePolicy.setHorizontalStretch(0)
|
31
|
+
@sizePolicy.setVerticalStretch(0)
|
32
|
+
@sizePolicy.heightForWidth = hudWidget.sizePolicy.hasHeightForWidth
|
33
|
+
hudWidget.sizePolicy = @sizePolicy
|
34
|
+
@palette = Qt::Palette.new
|
35
|
+
brush = Qt::Brush.new(Qt::Color.new(255, 255, 255, 255))
|
36
|
+
brush.style = Qt::SolidPattern
|
37
|
+
@palette.setBrush(Qt::Palette::Active, Qt::Palette::Base, brush)
|
38
|
+
brush1 = Qt::Brush.new(Qt::Color.new(224, 223, 222, 100))
|
39
|
+
brush1.style = Qt::SolidPattern
|
40
|
+
@palette.setBrush(Qt::Palette::Active, Qt::Palette::Window, brush1)
|
41
|
+
@palette.setBrush(Qt::Palette::Inactive, Qt::Palette::Base, brush)
|
42
|
+
@palette.setBrush(Qt::Palette::Inactive, Qt::Palette::Window, brush1)
|
43
|
+
@palette.setBrush(Qt::Palette::Disabled, Qt::Palette::Base, brush1)
|
44
|
+
@palette.setBrush(Qt::Palette::Disabled, Qt::Palette::Window, brush1)
|
45
|
+
hudWidget.palette = @palette
|
46
|
+
@verticalLayout = Qt::VBoxLayout.new(hudWidget)
|
47
|
+
@verticalLayout.objectName = "verticalLayout"
|
48
|
+
@lBspeed = Qt::Label.new(hudWidget)
|
49
|
+
@lBspeed.objectName = "lBspeed"
|
50
|
+
@sizePolicy1 = Qt::SizePolicy.new(Qt::SizePolicy::Preferred, Qt::SizePolicy::MinimumExpanding)
|
51
|
+
@sizePolicy1.setHorizontalStretch(0)
|
52
|
+
@sizePolicy1.setVerticalStretch(0)
|
53
|
+
@sizePolicy1.heightForWidth = @lBspeed.sizePolicy.hasHeightForWidth
|
54
|
+
@lBspeed.sizePolicy = @sizePolicy1
|
55
|
+
@font = Qt::Font.new
|
56
|
+
@font.pointSize = 18
|
57
|
+
@font.bold = true
|
58
|
+
@font.weight = 75
|
59
|
+
@font.styleStrategy = Qt::Font::PreferAntialias
|
60
|
+
@lBspeed.font = @font
|
61
|
+
@lBspeed.frameShape = Qt::Frame::Panel
|
62
|
+
@lBspeed.frameShadow = Qt::Frame::Sunken
|
63
|
+
@lBspeed.alignment = Qt::AlignCenter
|
64
|
+
|
65
|
+
@verticalLayout.addWidget(@lBspeed)
|
66
|
+
|
67
|
+
@lBdistance = Qt::Label.new(hudWidget)
|
68
|
+
@lBdistance.objectName = "lBdistance"
|
69
|
+
@sizePolicy1.heightForWidth = @lBdistance.sizePolicy.hasHeightForWidth
|
70
|
+
@lBdistance.sizePolicy = @sizePolicy1
|
71
|
+
@lBdistance.font = @font
|
72
|
+
@lBdistance.frameShape = Qt::Frame::Panel
|
73
|
+
@lBdistance.frameShadow = Qt::Frame::Sunken
|
74
|
+
@lBdistance.alignment = Qt::AlignCenter
|
75
|
+
|
76
|
+
@verticalLayout.addWidget(@lBdistance)
|
77
|
+
|
78
|
+
@gridLayout = Qt::GridLayout.new()
|
79
|
+
@gridLayout.objectName = "gridLayout"
|
80
|
+
@label_4 = Qt::Label.new(hudWidget)
|
81
|
+
@label_4.objectName = "label_4"
|
82
|
+
@font1 = Qt::Font.new
|
83
|
+
@font1.family = "DejaVu Sans"
|
84
|
+
@font1.pointSize = 9
|
85
|
+
@label_4.font = @font1
|
86
|
+
|
87
|
+
@gridLayout.addWidget(@label_4, 0, 0, 1, 1)
|
88
|
+
|
89
|
+
@lBalt = Qt::Label.new(hudWidget)
|
90
|
+
@lBalt.objectName = "lBalt"
|
91
|
+
@lBalt.font = @font1
|
92
|
+
@lBalt.frameShape = Qt::Frame::Panel
|
93
|
+
@lBalt.frameShadow = Qt::Frame::Sunken
|
94
|
+
|
95
|
+
@gridLayout.addWidget(@lBalt, 0, 1, 1, 1)
|
96
|
+
|
97
|
+
@label_3 = Qt::Label.new(hudWidget)
|
98
|
+
@label_3.objectName = "label_3"
|
99
|
+
@label_3.font = @font1
|
100
|
+
|
101
|
+
@gridLayout.addWidget(@label_3, 0, 2, 1, 1)
|
102
|
+
|
103
|
+
@lBheading = Qt::Label.new(hudWidget)
|
104
|
+
@lBheading.objectName = "lBheading"
|
105
|
+
@lBheading.font = @font1
|
106
|
+
@lBheading.frameShape = Qt::Frame::Panel
|
107
|
+
@lBheading.frameShadow = Qt::Frame::Sunken
|
108
|
+
|
109
|
+
@gridLayout.addWidget(@lBheading, 0, 3, 1, 1)
|
110
|
+
|
111
|
+
@label_6 = Qt::Label.new(hudWidget)
|
112
|
+
@label_6.objectName = "label_6"
|
113
|
+
@label_6.font = @font1
|
114
|
+
|
115
|
+
@gridLayout.addWidget(@label_6, 1, 0, 1, 1)
|
116
|
+
|
117
|
+
@lBlat = Qt::Label.new(hudWidget)
|
118
|
+
@lBlat.objectName = "lBlat"
|
119
|
+
@lBlat.font = @font1
|
120
|
+
@lBlat.frameShape = Qt::Frame::Panel
|
121
|
+
@lBlat.frameShadow = Qt::Frame::Sunken
|
122
|
+
|
123
|
+
@gridLayout.addWidget(@lBlat, 1, 1, 1, 1)
|
124
|
+
|
125
|
+
@label_5 = Qt::Label.new(hudWidget)
|
126
|
+
@label_5.objectName = "label_5"
|
127
|
+
@label_5.font = @font1
|
128
|
+
|
129
|
+
@gridLayout.addWidget(@label_5, 1, 2, 1, 1)
|
130
|
+
|
131
|
+
@lBlon = Qt::Label.new(hudWidget)
|
132
|
+
@lBlon.objectName = "lBlon"
|
133
|
+
@lBlon.font = @font1
|
134
|
+
@lBlon.frameShape = Qt::Frame::Panel
|
135
|
+
@lBlon.frameShadow = Qt::Frame::Sunken
|
136
|
+
|
137
|
+
@gridLayout.addWidget(@lBlon, 1, 3, 1, 1)
|
138
|
+
|
139
|
+
|
140
|
+
@verticalLayout.addLayout(@gridLayout)
|
141
|
+
|
142
|
+
|
143
|
+
retranslateUi(hudWidget)
|
144
|
+
|
145
|
+
Qt::MetaObject.connectSlotsByName(hudWidget)
|
146
|
+
end # setupUi
|
147
|
+
|
148
|
+
def setup_ui(hudWidget)
|
149
|
+
setupUi(hudWidget)
|
150
|
+
end
|
151
|
+
|
152
|
+
def retranslateUi(hudWidget)
|
153
|
+
hudWidget.windowTitle = Qt::Application.translate("HudWidget", "Form", nil, Qt::Application::UnicodeUTF8)
|
154
|
+
@lBspeed.text = ''
|
155
|
+
@lBdistance.text = ''
|
156
|
+
@label_4.text = Qt::Application.translate("HudWidget", "Alt:", nil, Qt::Application::UnicodeUTF8)
|
157
|
+
@label_3.text = Qt::Application.translate("HudWidget", "Head:", nil, Qt::Application::UnicodeUTF8)
|
158
|
+
@label_6.text = Qt::Application.translate("HudWidget", "Lat:", nil, Qt::Application::UnicodeUTF8)
|
159
|
+
@label_5.text = Qt::Application.translate("HudWidget", "Lon:", nil, Qt::Application::UnicodeUTF8)
|
160
|
+
end # retranslateUi
|
161
|
+
|
162
|
+
def retranslate_ui(hudWidget)
|
163
|
+
retranslateUi(hudWidget)
|
164
|
+
end
|
165
|
+
|
166
|
+
end
|
167
|
+
|
168
|
+
module Ui
|
169
|
+
class HudWidget < Ui_HudWidget
|
170
|
+
end
|
171
|
+
end # module Ui
|
172
|
+
|
data/lib/init.rb
ADDED
@@ -0,0 +1,18 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
##################################################
|
3
|
+
# Flightgear Mapping
|
4
|
+
#
|
5
|
+
# Provide a real-time map of flight position in Flightgear. It is based on tiles from Openstreetmap,
|
6
|
+
# downloads them in the background, provides navigation aids and runways, allows setting of waypoints
|
7
|
+
# and tracks the flight.
|
8
|
+
#
|
9
|
+
# License
|
10
|
+
# GPL V2
|
11
|
+
#
|
12
|
+
# Author Michael Meltner (mmeltner@gmail.com)
|
13
|
+
##################################################
|
14
|
+
|
15
|
+
Dir.chdir(File.dirname(__FILE__))
|
16
|
+
|
17
|
+
load "waypoint.rb"
|
18
|
+
|
@@ -0,0 +1,1117 @@
|
|
1
|
+
##################################################
|
2
|
+
# Flightgear Mapping
|
3
|
+
#
|
4
|
+
# Provide a real-time map of flight position in Flightgear. It is based on tiles from Openstreetmap,
|
5
|
+
# downloads them in the background, provides navigation aids and runways, allows setting of waypoints
|
6
|
+
# and tracks the flight.
|
7
|
+
#
|
8
|
+
# License
|
9
|
+
# GPL V2
|
10
|
+
#
|
11
|
+
# Author Michael Meltner (mmeltner@gmail.com)
|
12
|
+
##################################################
|
13
|
+
|
14
|
+
require 'net/http'
|
15
|
+
require "main-dlg"
|
16
|
+
require "tile"
|
17
|
+
require "resources"
|
18
|
+
require 'socket'
|
19
|
+
require "hud-impl"#
|
20
|
+
# Author Michael Meltner (mmeltner@gmail.com)
|
21
|
+
|
22
|
+
require "nodeinfo-impl"
|
23
|
+
require 'navaid.rb'
|
24
|
+
require "xml"
|
25
|
+
begin
|
26
|
+
require "ap"
|
27
|
+
rescue LoadError
|
28
|
+
def ap(*k)
|
29
|
+
p k
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
OFFSET_FLAG_X = 3
|
34
|
+
OFFSET_FLAG_Y = 21
|
35
|
+
OFFSET_PIN_X = 1
|
36
|
+
OFFSET_PIN_Y = 23
|
37
|
+
OFFSET_FLAG_COUNTER_X = 5
|
38
|
+
OFFSET_FLAG_COUNTER_Y = -8
|
39
|
+
ILSSIZE = 140 # in pixel
|
40
|
+
ILSCONEANGLE = 10 # in degree
|
41
|
+
ILSTEXTOFFSET = 10 # in pixel
|
42
|
+
|
43
|
+
Z_VALUE_TILES = 0
|
44
|
+
Z_VALUE_TRACK = 1
|
45
|
+
Z_VALUE_TRACK_COLORED = 2
|
46
|
+
Z_VALUE_WAYPOINT = 3
|
47
|
+
Z_VALUE_ORIGIN = 4
|
48
|
+
Z_VALUE_ROSE = 5
|
49
|
+
Z_VALUE_POINTERTOORIGIN = 6
|
50
|
+
Z_VALUE_POINTER = 7
|
51
|
+
Z_VALUE_NAV = 8
|
52
|
+
Z_VALUE_HUD = 10
|
53
|
+
SCALE_SVG = 0.3
|
54
|
+
|
55
|
+
COLORRANGE_DEG = 120.0
|
56
|
+
COLOROFFSET_DEG = 240.0
|
57
|
+
|
58
|
+
MINSPEED = 0.3 # minimum speed required for heading marker to appear, in m/s
|
59
|
+
FS_READ_INTERVAL = 100 # enter GUI refresh loop every 100ms
|
60
|
+
TICKSTOSKIP = 20
|
61
|
+
AUTOSAVE_INTERVAL = 10 * 60 * 1000 # autosave interval for tracks
|
62
|
+
HOVER_TIMER = 2000 # time until HUD widget disappears
|
63
|
+
MAXVORSTODISPLAY = 500 # maximum number of nav-aids to display on map
|
64
|
+
MAXILSTODISPLAY = 200
|
65
|
+
|
66
|
+
FS_PORT = 2948
|
67
|
+
|
68
|
+
|
69
|
+
#LATSTARTUP = 49.462126667
|
70
|
+
#LONSTARTUP = 11.121691667
|
71
|
+
LATSTARTUP = 50.0368400387281
|
72
|
+
LONSTARTUP = 8.55965957641601
|
73
|
+
|
74
|
+
MAPSDIR = ENV['HOME'] + "/.OpenstreetmapTiles"
|
75
|
+
|
76
|
+
#GC.disable
|
77
|
+
|
78
|
+
# Class MainDlg ############################################
|
79
|
+
class MainDlg < Qt::Widget
|
80
|
+
attr_reader :node, :scene_tiles, :scene, :toffset_x, :offset_y, :menu, :waypoints, \
|
81
|
+
:flag, :zoom, :mytracks, :mytrack_current, :w
|
82
|
+
attr_writer :node, :scene_tiles, :offset_x, :offset_y, :waypoints, :mytrack_current, :w
|
83
|
+
attr_accessor :metricUnit
|
84
|
+
|
85
|
+
slots "pBexit_clicked()", "pBdo_clicked()", "pBplus_clicked()", "pBminus_clicked()", \
|
86
|
+
"cBpointorigin_clicked()", "pBrecordTrack_toggled(bool)", "wakeupTimer()", "autosaveTimer()", \
|
87
|
+
'cBvor_clicked()', 'cBndb_clicked()', 'cBrw_clicked()'
|
88
|
+
|
89
|
+
def initialize(parent, arg)
|
90
|
+
super(parent)
|
91
|
+
@w=Ui::MainDlg.new
|
92
|
+
@w.setupUi(self)
|
93
|
+
@parent=parent
|
94
|
+
|
95
|
+
@cfg=Qt::Settings.new("MMeltnerSoft", "fg_map")
|
96
|
+
@metricUnit = @cfg.value("metricUnit",Qt::Variant.new(true)).toBool
|
97
|
+
@zoom = @cfg.value("zoom",Qt::Variant.new(13)).toInt
|
98
|
+
@lat = @cfg.value("lat",Qt::Variant.new(LATSTARTUP)).toDouble
|
99
|
+
@lon = @cfg.value("lon",Qt::Variant.new(LONSTARTUP)).toDouble
|
100
|
+
@w.cBrw.setChecked(@cfg.value("rwChecked",Qt::Variant.new(false)).toBool)
|
101
|
+
@w.cBndb.setChecked(@cfg.value("nbdChecked",Qt::Variant.new(false)).toBool)
|
102
|
+
@w.cBvor.setChecked(@cfg.value("vorChecked",Qt::Variant.new(true)).toBool)
|
103
|
+
|
104
|
+
@flag=Qt::Pixmap.new(":/icons/flag-blue.png")
|
105
|
+
@pin=Qt::Pixmap.new(":/icons/wpttemp-red.png")
|
106
|
+
@linepen = Qt::Pen.new
|
107
|
+
@linepen.setWidth(5)
|
108
|
+
@colors={:index => 0, :selection => ["Red", "Yellow", "Green"]}
|
109
|
+
@graphicsSceneFont = Qt::Font.new("Helvetica", 7)
|
110
|
+
@graphicsSceneBrush = Qt::Brush.new(Qt::Color.new(255, 255, 255, 150))
|
111
|
+
@ilsBrush = Qt::Brush.new(Qt::Color.new(0, 0, 0, 150))
|
112
|
+
@noPen = Qt::Pen.new(Qt::NoPen)
|
113
|
+
|
114
|
+
@wakeupTimer = Qt::Timer.new( self )
|
115
|
+
Qt::Object.connect( @wakeupTimer, SIGNAL('timeout()'), self, SLOT('wakeupTimer()') )
|
116
|
+
@wakeupTimer.start( FS_READ_INTERVAL )
|
117
|
+
@wakeupCounter = 0
|
118
|
+
@autosaveTimer = Qt::Timer.new( self )
|
119
|
+
Qt::Object.connect( @autosaveTimer, SIGNAL('timeout()'), self, SLOT('autosaveTimer()') )
|
120
|
+
@autosaveTimer.start( AUTOSAVE_INTERVAL )
|
121
|
+
|
122
|
+
@offset_x=@offset_y=0
|
123
|
+
@fs_ans=[]
|
124
|
+
@fs_queries=["/position/latitude-deg", "/position/longitude-deg", "/position/ground-elev-m",
|
125
|
+
"/orientation/heading-deg", "/velocities/groundspeed-kt"]
|
126
|
+
|
127
|
+
@waypoints=Way.new(nil,'user', Time.now, "Blue")
|
128
|
+
@mytracks=[]
|
129
|
+
@mytrack_current=-1
|
130
|
+
@prev_track_node = nil
|
131
|
+
@posnode = Node.new(1, Time.now, @lon, @lat)
|
132
|
+
|
133
|
+
@node = Node.new(1, Time.now, @lon, @lat, 0, @zoom)
|
134
|
+
@rot = 0
|
135
|
+
@remainingTiles = 0
|
136
|
+
@httpThreads = Array.new
|
137
|
+
|
138
|
+
@navs = Navaid.new(arg)
|
139
|
+
|
140
|
+
@httpMutex = Mutex.new
|
141
|
+
|
142
|
+
@scene=Qt::GraphicsScene.new()
|
143
|
+
@w.gVmap.setScene(@scene)
|
144
|
+
@w.lBzoom.setText(@zoom.to_s)
|
145
|
+
vorGraphic=Qt::GraphicsSvgItem.new(":/icons/vor.svg")
|
146
|
+
vorGraphic.setElementId("VOR")
|
147
|
+
boundingrect = vorGraphic.boundingRect
|
148
|
+
@vor_offsetx = boundingrect.right / 2
|
149
|
+
@vor_offsety = boundingrect.bottom / 2
|
150
|
+
|
151
|
+
begin
|
152
|
+
@fs_socket = TCPSocket.open('localhost', FS_PORT)
|
153
|
+
@fs_socket.puts "reset"
|
154
|
+
rescue
|
155
|
+
#swallow all errors
|
156
|
+
end
|
157
|
+
|
158
|
+
if FileTest.directory?(MAPSDIR) then
|
159
|
+
$MAPSHOME = MAPSDIR
|
160
|
+
else
|
161
|
+
resp = Qt::MessageBox::question(nil, "No local Map Directory found.", "Create one?", Qt::MessageBox::No, Qt::MessageBox::Yes)
|
162
|
+
if resp == Qt::MessageBox::Yes then
|
163
|
+
Dir.mkdir(MAPSDIR)
|
164
|
+
$MAPSHOME = MAPSDIR
|
165
|
+
else
|
166
|
+
$MAPSHOME = "./"
|
167
|
+
end
|
168
|
+
end
|
169
|
+
puts "Map Directory located here: \"#{$MAPSHOME}\""
|
170
|
+
end
|
171
|
+
|
172
|
+
def get_data(path)
|
173
|
+
r=@fs_ans.detect do |f|
|
174
|
+
f.include?(path)
|
175
|
+
end
|
176
|
+
r =~ /-?\d+\.\d+/
|
177
|
+
return $&.to_f
|
178
|
+
end
|
179
|
+
|
180
|
+
def putflag(x,y,i,node)
|
181
|
+
flag=FlagGraphicsPixmapItem.new(@flag)
|
182
|
+
flag.setOffset(x - OFFSET_FLAG_X, y - OFFSET_FLAG_Y)
|
183
|
+
t=Qt::GraphicsTextItem.new(i.to_s, flag)
|
184
|
+
t.setPos(x + OFFSET_FLAG_COUNTER_X, y + OFFSET_FLAG_COUNTER_Y)
|
185
|
+
flag.setZValue(Z_VALUE_WAYPOINT)
|
186
|
+
tooltip=("Lon: %.3f�"%node.lon)+("\nLat: %.3f�"%node.lat)
|
187
|
+
if node.elevation>0 then
|
188
|
+
tooltip += ("\nElevation: %.1fm" % node.elevation)
|
189
|
+
end
|
190
|
+
flag.setToolTip(tooltip)
|
191
|
+
@scene.addItem(flag)
|
192
|
+
end
|
193
|
+
|
194
|
+
def nextcolor
|
195
|
+
col=@colors[:selection][@colors[:index]]
|
196
|
+
if col.nil? then
|
197
|
+
col=@colors[:selection][0]
|
198
|
+
@colors[:index] = 0
|
199
|
+
else
|
200
|
+
@colors[:index] += 1
|
201
|
+
end
|
202
|
+
return col
|
203
|
+
end
|
204
|
+
|
205
|
+
def savetrack(items, warn=true)
|
206
|
+
if items[0].nil? or items[0].nodes.length == 0 then
|
207
|
+
Qt::MessageBox::warning(nil, "Warning", "No data recorded yet.") if warn
|
208
|
+
else
|
209
|
+
begin
|
210
|
+
Dir.mkdir($MAPSHOME + "/tracks")
|
211
|
+
rescue Errno::EEXIST
|
212
|
+
# just swallow error
|
213
|
+
end
|
214
|
+
|
215
|
+
doc = XML::Document.new()
|
216
|
+
doc.root = XML::Node.new('gpx')
|
217
|
+
doc.root["xmlns"] = "http://www.topografix.com/GPX/1/1"
|
218
|
+
doc.root["creator"] = "ruby-tracker"
|
219
|
+
doc.root["version"] = "1.1"
|
220
|
+
doc.root["xmlns:xsi"] = "http://www.w3.org/2001/XMLSchema-instance"
|
221
|
+
doc.root["xsi:schemaLocation"] = "http://www.topografix.com/GPX/1/1 http://www.topografix.com/GPX/1/1/gpx.xsd"
|
222
|
+
|
223
|
+
tracknode = XML::Node.new("trk")
|
224
|
+
doc.root << tracknode
|
225
|
+
items.each{|track|
|
226
|
+
segnode = XML::Node.new("trkseg")
|
227
|
+
tracknode << segnode
|
228
|
+
track.nodes.each{|n|
|
229
|
+
trackpoint = XML::Node.new("trkpt")
|
230
|
+
trackpoint["lat"] = n.lat.to_s.gsub(",",".")
|
231
|
+
trackpoint["lon"] = n.lon.to_s.gsub(",",".")
|
232
|
+
trackpoint << XML::Node.new("ele", n.elevation.to_s.gsub(",","."))
|
233
|
+
trackpoint << XML::Node.new("time", n.toGPStime)
|
234
|
+
segnode << trackpoint
|
235
|
+
}
|
236
|
+
}
|
237
|
+
File.open($MAPSHOME + "/tracks/" + items.first.nodes.first.toGPStime + ".gpx", "w+"){|f|
|
238
|
+
f.puts doc.inspect
|
239
|
+
}
|
240
|
+
end
|
241
|
+
end
|
242
|
+
|
243
|
+
def loadtrack(title)
|
244
|
+
fn=Qt::FileDialog::getOpenFileName(nil, title, $MAPSHOME + "/tracks/", "Track-Data (*.gpx *.log);;All (*)")
|
245
|
+
if !fn.nil? then
|
246
|
+
success = false
|
247
|
+
doc = XML::Document.file(fn)
|
248
|
+
doc.find('/ns:gpx/ns:trk', "ns:http://www.topografix.com/GPX/1/1").each{|trk|
|
249
|
+
@mytrack_current -= 1
|
250
|
+
trk.find("ns:trkseg", "ns:http://www.topografix.com/GPX/1/1").each{|seg|
|
251
|
+
ns = XML::Namespace.new(seg, 'ns', 'http://www.topografix.com/GPX/1/1')
|
252
|
+
seg.namespaces.namespace=ns
|
253
|
+
@mytrack_current += 1
|
254
|
+
if @mytracks[@mytrack_current].nil? then
|
255
|
+
@mytracks[@mytrack_current] = Way.new(1, 'user', Time.now, nextcolor)
|
256
|
+
@prev_track_node = nil
|
257
|
+
end
|
258
|
+
track=@mytracks[@mytrack_current]
|
259
|
+
track.nodes.clear
|
260
|
+
xpat_time = XML::XPath::Expression.new("ns:time")
|
261
|
+
xpat_elevation = XML::XPath::Expression.new("ns:ele")
|
262
|
+
seg.find("ns:trkpt", "ns:http://www.topografix.com/GPX/1/1").each{|tpt|
|
263
|
+
track << Node.new(nil, tpt.find_first(xpat_time).content, tpt["lon"].to_f, \
|
264
|
+
tpt["lat"].to_f, tpt.find_first(xpat_elevation).content.to_f)
|
265
|
+
success = true
|
266
|
+
}
|
267
|
+
}
|
268
|
+
}
|
269
|
+
if success then
|
270
|
+
movemap(@node, true)
|
271
|
+
else
|
272
|
+
Qt::MessageBox::warning(nil, "Warning", "No data found in file.")
|
273
|
+
end
|
274
|
+
return success
|
275
|
+
end
|
276
|
+
end
|
277
|
+
|
278
|
+
def loadwaypoint(title)
|
279
|
+
fn=Qt::FileDialog::getOpenFileName(nil, title, $MAPSHOME + "/waypoints/", "Waypoint-Data (*.gpx *.log);;All (*)")
|
280
|
+
if !fn.nil? then
|
281
|
+
success = false
|
282
|
+
doc = XML::Document.file(fn)
|
283
|
+
@waypoints = Way.new(nil,'user', Time.now, "Blue")
|
284
|
+
doc.find("/ns:gpx/ns:wpt", "ns:http://www.topografix.com/GPX/1/1").each{ |wpt|
|
285
|
+
ns = XML::Namespace.new(wpt, 'ns', 'http://www.topografix.com/GPX/1/1')
|
286
|
+
wpt.namespaces.namespace = ns
|
287
|
+
xpat_time = XML::XPath::Expression.new("ns:time")
|
288
|
+
xpat_elevation = XML::XPath::Expression.new("ns:ele")
|
289
|
+
@waypoints << Node.new(nil, wpt.find_first(xpat_time).content, wpt["lon"].to_f, \
|
290
|
+
wpt["lat"].to_f, wpt.find_first(xpat_elevation).content.to_f)
|
291
|
+
success = true
|
292
|
+
}
|
293
|
+
if success then
|
294
|
+
movemap(@node, true)
|
295
|
+
else
|
296
|
+
Qt::MessageBox::warning(nil, "Warning", "No data found in file.")
|
297
|
+
end
|
298
|
+
return success
|
299
|
+
end
|
300
|
+
end
|
301
|
+
|
302
|
+
def saveWaypoints(waypoints)
|
303
|
+
if waypoints.length == 0 then
|
304
|
+
Qt::MessageBox::warning(nil, "Warning", "No waypoints set yet.") if warn
|
305
|
+
else
|
306
|
+
begin
|
307
|
+
Dir.mkdir($MAPSHOME + "/waypoints")
|
308
|
+
rescue Errno::EEXIST
|
309
|
+
# just swallow error
|
310
|
+
end
|
311
|
+
|
312
|
+
doc = XML::Document.new()
|
313
|
+
doc.root = XML::Node.new('gpx')
|
314
|
+
doc.root["xmlns"] = "http://www.topografix.com/GPX/1/1"
|
315
|
+
doc.root["creator"] = "ruby-tracker"
|
316
|
+
doc.root["version"] = "1.1"
|
317
|
+
doc.root["xmlns:xsi"] = "http://www.w3.org/2001/XMLSchema-instance"
|
318
|
+
doc.root["xsi:schemaLocation"] = "http://www.topografix.com/GPX/1/1 http://www.topografix.com/GPX/1/1/gpx.xsd"
|
319
|
+
|
320
|
+
waypoints[0].nodes.each{|n|
|
321
|
+
if !n.nil? then
|
322
|
+
wpnode = XML::Node.new("wpt")
|
323
|
+
doc.root << wpnode
|
324
|
+
wpnode["lat"] = n.lat.to_s.gsub(",",".")
|
325
|
+
wpnode["lon"] = n.lon.to_s.gsub(",",".")
|
326
|
+
wpnode << XML::Node.new("ele", n.elevation.to_s.gsub(",","."))
|
327
|
+
wpnode << XML::Node.new("time", n.toGPStime)
|
328
|
+
end
|
329
|
+
}
|
330
|
+
fn=Qt::FileDialog::getSaveFileName(nil, "Save Waypoint File", $MAPSHOME + "/waypoints/", "Waypoint-Data (*.gpx *.log);;All (*)","*.gpx")
|
331
|
+
|
332
|
+
if !fn.nil? then
|
333
|
+
if fn !~ /\.gpx$/ then
|
334
|
+
fn += ".gpx"
|
335
|
+
end
|
336
|
+
File.open(fn, "w+"){|f|
|
337
|
+
f.puts doc.inspect
|
338
|
+
}
|
339
|
+
end
|
340
|
+
end
|
341
|
+
end
|
342
|
+
|
343
|
+
def zoomplus
|
344
|
+
@httpThreads.each do |th|
|
345
|
+
th.kill
|
346
|
+
end
|
347
|
+
@httpThreads = Array.new
|
348
|
+
@remainingTiles = 0
|
349
|
+
@scene.removeItem(@warningText)
|
350
|
+
|
351
|
+
@zoom += 1
|
352
|
+
@zoom=17 if @zoom>17
|
353
|
+
@zoom=3 if @zoom<3
|
354
|
+
@w.lBzoom.setText(@zoom.to_s)
|
355
|
+
@node.zoom(@zoom)
|
356
|
+
@offset_x *= 2
|
357
|
+
@offset_y *= 2
|
358
|
+
movemap(@node, true)
|
359
|
+
end
|
360
|
+
|
361
|
+
def zoomminus
|
362
|
+
@httpThreads.each do |th|
|
363
|
+
th.kill
|
364
|
+
end
|
365
|
+
@remainingTiles = 0
|
366
|
+
@httpThreads = Array.new
|
367
|
+
@scene.removeItem(@warningText)
|
368
|
+
|
369
|
+
@zoom -= 1
|
370
|
+
@zoom=17 if @zoom>17
|
371
|
+
@zoom=3 if @zoom<3
|
372
|
+
@w.lBzoom.setText(@zoom.to_s)
|
373
|
+
@node.zoom(@zoom)
|
374
|
+
@offset_x /= 2
|
375
|
+
@offset_y /= 2
|
376
|
+
movemap(@node, true)
|
377
|
+
end
|
378
|
+
|
379
|
+
def addTileToScene(f, origin_x, origin_y)
|
380
|
+
pmi=TileGraphicsPixmapItem.new(Qt::Pixmap.new(f))
|
381
|
+
@scene_tiles << f
|
382
|
+
f =~ /\/(\d*)\/(\d*)\/(\d*)/
|
383
|
+
x = $2.to_i
|
384
|
+
y = $3.to_i
|
385
|
+
# p x - origin_x,y - origin_y
|
386
|
+
pmi.setOffset((x - origin_x)*256, (y - origin_y)*256)
|
387
|
+
pmi.setZValue(Z_VALUE_TILES)
|
388
|
+
@scene.addItem(pmi)
|
389
|
+
end
|
390
|
+
|
391
|
+
def addNavToScene(vor, origin_x, origin_y)
|
392
|
+
vorGraphic = Qt::GraphicsSvgItem.new(":/icons/vor.svg")
|
393
|
+
vorGraphic.setElementId(vor.type)
|
394
|
+
vorGraphic.setTransform(Qt::Transform.new.translate(-@vor_offsetx, -@vor_offsety))
|
395
|
+
vorGraphic.setZValue(Z_VALUE_NAV)
|
396
|
+
@scene.addItem(vorGraphic)
|
397
|
+
vorNode = Node.new(0, nil, vor.lon.to_f, vor.lat.to_f)
|
398
|
+
vorGraphic.setPos((vorNode.toxtile - origin_x) * 256, (vorNode.toytile - origin_y) * 256)
|
399
|
+
vor.sceneItem = vorGraphic
|
400
|
+
|
401
|
+
# create text on Navaid
|
402
|
+
textString = vor.shortName + " " + vor.freq.to_s
|
403
|
+
text=Qt::GraphicsSimpleTextItem.new(textString)
|
404
|
+
text.setFont(@graphicsSceneFont)
|
405
|
+
bounding = text.boundingRect
|
406
|
+
background = Qt::GraphicsRectItem.new(bounding)
|
407
|
+
background.setBrush(@graphicsSceneBrush)
|
408
|
+
background.setPen(@noPen)
|
409
|
+
background.setToolTip(textString + "; " + vor.longName)
|
410
|
+
background.setPos(@vor_offsetx - bounding.width / 2, 2*@vor_offsety+3)
|
411
|
+
text.setParentItem(background)
|
412
|
+
background.setParentItem(vorGraphic)
|
413
|
+
end
|
414
|
+
|
415
|
+
def addRunwayToScene(rw, origin_x, origin_y)
|
416
|
+
rwNode = Node.new(0, nil, rw.lon.to_f, rw.lat.to_f)
|
417
|
+
|
418
|
+
# create text
|
419
|
+
textString = rw.airportName + " " + rw.freq.to_s
|
420
|
+
text=Qt::GraphicsSimpleTextItem.new(textString)
|
421
|
+
text.setFont(@graphicsSceneFont)
|
422
|
+
bounding = text.boundingRect
|
423
|
+
background = Qt::GraphicsRectItem.new(bounding)
|
424
|
+
background.setTransform(Qt::Transform.new.translate(-bounding.width / 2, ILSTEXTOFFSET))
|
425
|
+
background.setZValue(Z_VALUE_NAV)
|
426
|
+
background.setBrush(@graphicsSceneBrush)
|
427
|
+
background.setPen(@noPen)
|
428
|
+
background.setToolTip(textString)
|
429
|
+
text.setParentItem(background)
|
430
|
+
background.setPos((rwNode.toxtile - origin_x) * 256, (rwNode.toytile - origin_y) * 256)
|
431
|
+
|
432
|
+
rwGraphic = Qt::GraphicsEllipseItem.new(0,0,ILSSIZE,ILSSIZE)
|
433
|
+
rwGraphic.setStartAngle(ILSCONEANGLE*8)
|
434
|
+
rwGraphic.setSpanAngle(-ILSCONEANGLE*16)
|
435
|
+
rwGraphic.setTransform(Qt::Transform.new.translate(bounding.width/ 2, -ILSTEXTOFFSET).rotate(rw.direction + 90).translate(-ILSSIZE / 2, -ILSSIZE / 2))
|
436
|
+
rwGraphic.setPen(@noPen)
|
437
|
+
rwGraphic.setBrush(@ilsBrush)
|
438
|
+
rwGraphic.setFlag(Qt::GraphicsItem::ItemStacksBehindParent)
|
439
|
+
|
440
|
+
rwGraphic.setParentItem(background)
|
441
|
+
@scene.addItem(background)
|
442
|
+
rw.sceneItem = background
|
443
|
+
end
|
444
|
+
|
445
|
+
def movemap(node, repaint=false, downloadTiles=true)
|
446
|
+
origin_x=node.xtile
|
447
|
+
origin_y=node.ytile
|
448
|
+
|
449
|
+
if repaint then
|
450
|
+
@scene_tiles = []
|
451
|
+
@scene_navs = []
|
452
|
+
@scene_rws = []
|
453
|
+
@scene.clear
|
454
|
+
# 8 : 256 = 2**8
|
455
|
+
size = 2**(@zoom + 8)
|
456
|
+
sceneRect = Qt::RectF.new(0,0,size,size)
|
457
|
+
sceneRect.moveCenter(Qt::PointF.new(@node.xtile, @node.ytile))
|
458
|
+
@scene.setSceneRect(sceneRect)
|
459
|
+
end
|
460
|
+
|
461
|
+
vorsToDisplay = @navs.getVORs(node.getLatLonBox(@w.gVmap.size, @offset_x, @offset_y))
|
462
|
+
if vorsToDisplay.length < MAXVORSTODISPLAY then
|
463
|
+
vorsToDisplay.each do |vor|
|
464
|
+
if !@scene_navs.include?(vor)
|
465
|
+
if (@w.cBndb.isChecked and vor.type == "NDB") or
|
466
|
+
(@w.cBvor.isChecked and vor.type != "NDB") then
|
467
|
+
@scene_navs << vor
|
468
|
+
addNavToScene(vor, origin_x, origin_y)
|
469
|
+
end
|
470
|
+
end
|
471
|
+
end
|
472
|
+
elsif !@scene_navs.empty? then
|
473
|
+
repaint = true
|
474
|
+
@scene_tiles = []
|
475
|
+
@scene_navs = []
|
476
|
+
@scene_rws = []
|
477
|
+
@scene.clear
|
478
|
+
end
|
479
|
+
|
480
|
+
if @w.cBrw.isChecked then
|
481
|
+
runwaysToDisplay = @navs.getRunways(node.getLatLonBox(@w.gVmap.size, @offset_x, @offset_y))
|
482
|
+
if runwaysToDisplay.length < MAXILSTODISPLAY then
|
483
|
+
runwaysToDisplay.each do |runway|
|
484
|
+
if !@scene_rws.include?(runway)
|
485
|
+
@scene_rws << runway
|
486
|
+
addRunwayToScene(runway, origin_x, origin_y)
|
487
|
+
end
|
488
|
+
end
|
489
|
+
end
|
490
|
+
elsif !@scene_rws.empty? then
|
491
|
+
repaint = true
|
492
|
+
@scene_tiles = []
|
493
|
+
@scene_navs = []
|
494
|
+
@scene_rws = []
|
495
|
+
@scene.clear
|
496
|
+
end
|
497
|
+
|
498
|
+
fn = node.getfilenames(@w.gVmap.size, @offset_x, @offset_y)
|
499
|
+
|
500
|
+
fn.each{|f|
|
501
|
+
if !@scene_tiles.include?(f)
|
502
|
+
if FileTest.exist?(f+".png") then
|
503
|
+
addTileToScene(f, origin_x, origin_y)
|
504
|
+
elsif downloadTiles and (@timeNoInternet.nil? or (Time.now - @timeNoInternet) > 60) then
|
505
|
+
@httpThreads << Thread.new {
|
506
|
+
@remainingTiles += 1
|
507
|
+
@httpMutex.synchronize {
|
508
|
+
@warningText = Qt::GraphicsSimpleTextItem.new("#{@remainingTiles} remaining tiles")
|
509
|
+
@warningText.setBrush(Qt::Brush.new(Qt::Color.new("red")))
|
510
|
+
@scene.addItem(@warningText)
|
511
|
+
fontInfo = Qt::FontInfo.new(@warningText.font)
|
512
|
+
@warningText.setPos(@w.gVmap.mapToScene((@w.gVmap.size.width - @warningText.boundingRect.width)/2,
|
513
|
+
@w.gVmap.size.height - fontInfo.pixelSize - 10))
|
514
|
+
|
515
|
+
h = Net::HTTP.new('tile.openstreetmap.org')
|
516
|
+
f =~ /\/\d+\/\d+\/\d+$/
|
517
|
+
f = $&
|
518
|
+
resp, data = h.get(f + ".png", nil)
|
519
|
+
if resp.kind_of?(Net::HTTPOK) then
|
520
|
+
maindir = Dir.pwd
|
521
|
+
Dir.chdir($MAPSHOME)
|
522
|
+
f.split("/")[0..-2].each do |dir|
|
523
|
+
if !dir.empty? then
|
524
|
+
begin
|
525
|
+
Dir.mkdir(dir)
|
526
|
+
rescue Errno::EEXIST
|
527
|
+
# just swallow error
|
528
|
+
end
|
529
|
+
Dir.chdir(dir)
|
530
|
+
end
|
531
|
+
end
|
532
|
+
Dir.chdir(maindir)
|
533
|
+
File.open($MAPSHOME + f + ".png", "w") do |file|
|
534
|
+
file.write(data)
|
535
|
+
end
|
536
|
+
addTileToScene($MAPSHOME + f, origin_x, origin_y)
|
537
|
+
else
|
538
|
+
puts "Could not download tile. Internet connection alive?"
|
539
|
+
@timeNoInternet=Time.now
|
540
|
+
end
|
541
|
+
@scene.removeItem(@warningText)
|
542
|
+
}
|
543
|
+
@remainingTiles -= 1
|
544
|
+
}
|
545
|
+
else
|
546
|
+
puts "Internet timeout still running"
|
547
|
+
end
|
548
|
+
end
|
549
|
+
}
|
550
|
+
|
551
|
+
if repaint then
|
552
|
+
mainnode_x=node.toxtile
|
553
|
+
mainnode_y=node.toytile
|
554
|
+
|
555
|
+
# set waypoint flags
|
556
|
+
i=1
|
557
|
+
@waypoints.nodes.each {|node|
|
558
|
+
if !node.nil? then
|
559
|
+
putflag((node.toxtile - mainnode_x) * 256, (node.toytile - mainnode_y) * 256, i, node)
|
560
|
+
end
|
561
|
+
i+=1
|
562
|
+
}
|
563
|
+
# set origin pin
|
564
|
+
pmi=Qt::GraphicsPixmapItem.new(@pin)
|
565
|
+
pmi.setOffset(OFFSET_PIN_X, -OFFSET_PIN_Y)
|
566
|
+
pmi.setZValue(Z_VALUE_ORIGIN)
|
567
|
+
@scene.addItem(pmi)
|
568
|
+
|
569
|
+
# create hud display
|
570
|
+
# needs to be embedded in other graphics element to circumvent a bug if the position of
|
571
|
+
# the ProxyWidget is above, below 2**15 - 1, bug in QT
|
572
|
+
@hud=Qt::GraphicsRectItem.new(0,0,10,10)
|
573
|
+
@hud.setPen(@noPen)
|
574
|
+
hud=Qt::GraphicsProxyWidget.new(@hud)
|
575
|
+
@hud_widget = HudWidget.new()
|
576
|
+
hud.setWidget(@hud_widget)
|
577
|
+
@hud.setZValue(Z_VALUE_HUD)
|
578
|
+
@scene.addItem(@hud)
|
579
|
+
@hud.setPos(@w.gVmap.mapToScene(0,0))
|
580
|
+
|
581
|
+
# create rose
|
582
|
+
@rose=Qt::GraphicsSvgItem.new(":/icons/rose.svg")
|
583
|
+
@rose.setElementId("rose")
|
584
|
+
boundingrect = @rose.boundingRect
|
585
|
+
rose_offsetx = boundingrect.right / 2
|
586
|
+
rose_offsety = boundingrect.bottom / 2
|
587
|
+
@rose.setTransform(Qt::Transform.new.scale(SCALE_SVG,SCALE_SVG).translate(-rose_offsetx, -rose_offsety))
|
588
|
+
@rose.setZValue(Z_VALUE_ROSE)
|
589
|
+
@scene.addItem(@rose)
|
590
|
+
@rose.setPos((@posnode.toxtile - mainnode_x) * 256, (@posnode.toytile - mainnode_y) * 256)
|
591
|
+
|
592
|
+
# create bearing-pointer
|
593
|
+
@pointer=Qt::GraphicsSvgItem.new(":/icons/rose.svg")
|
594
|
+
@pointer.setElementId("zeiger")
|
595
|
+
boundingrect = @pointer.boundingRect
|
596
|
+
@pointer_offsetx = boundingrect.right / 2
|
597
|
+
@pointer.setTransform(Qt::Transform.new.scale(SCALE_SVG,SCALE_SVG).rotate(0).translate(-@pointer_offsetx, 0))
|
598
|
+
@pointer.setZValue(Z_VALUE_POINTER)
|
599
|
+
@scene.addItem(@pointer)
|
600
|
+
@pointer.setPos((@posnode.toxtile - mainnode_x) * 256, (@posnode.toytile - mainnode_y) * 256)
|
601
|
+
|
602
|
+
# create pointer to origin
|
603
|
+
@pointertoorigin=Qt::GraphicsSvgItem.new(":/icons/rose.svg")
|
604
|
+
@pointertoorigin.setElementId("zeigertoorigin")
|
605
|
+
boundingrect = @pointertoorigin.boundingRect
|
606
|
+
@pointertoorigin_offsetx = boundingrect.right / 2
|
607
|
+
@pointertoorigin.setTransform(Qt::Transform.new.scale(SCALE_SVG,SCALE_SVG).rotate(0).translate(-@pointertoorigin_offsetx, 0))
|
608
|
+
@pointertoorigin.setZValue(Z_VALUE_POINTERTOORIGIN)
|
609
|
+
@scene.addItem(@pointertoorigin)
|
610
|
+
@pointertoorigin.setPos((@posnode.toxtile - mainnode_x) * 256, (@posnode.toytile - mainnode_y) * 256)
|
611
|
+
|
612
|
+
# paint tracks
|
613
|
+
@mytracks.each {|track|
|
614
|
+
prev_node = nil
|
615
|
+
if !track.nil? then
|
616
|
+
@linepen.setColor(Qt::Color.new(track.color))
|
617
|
+
tck=nil
|
618
|
+
prev_node=false
|
619
|
+
track.nodes.each{|n|
|
620
|
+
if !prev_node then
|
621
|
+
tck=Qt::PainterPath.new(Qt::PointF.new((n.toxtile - mainnode_x) * 256, (n.toytile - mainnode_y) * 256))
|
622
|
+
else
|
623
|
+
tck.lineTo((n.toxtile - mainnode_x) * 256, (n.toytile - mainnode_y) * 256)
|
624
|
+
end
|
625
|
+
prev_node = true
|
626
|
+
}
|
627
|
+
track.path=TrackGraphicsPathItem.new(track)
|
628
|
+
track.path.setPath(tck)
|
629
|
+
track.path.setZValue(Z_VALUE_TRACK)
|
630
|
+
track.path.setPen(@linepen)
|
631
|
+
@scene.addItem(track.path)
|
632
|
+
end
|
633
|
+
}
|
634
|
+
if @w.pBrecordTrack.isChecked then
|
635
|
+
@tckpath=@mytracks[@mytrack_current].path.path
|
636
|
+
end
|
637
|
+
end
|
638
|
+
|
639
|
+
@w.gVmap.centerOn(@offset_x*256,@offset_y*256)
|
640
|
+
if !@hud.nil? then
|
641
|
+
@hud.setPos(@w.gVmap.mapToScene(0,0))
|
642
|
+
end
|
643
|
+
end
|
644
|
+
|
645
|
+
def wakeupTimer()
|
646
|
+
# p "wakeup in"
|
647
|
+
# have to do centering every time as QT will not scroll to scene coordinates which have no elements placed there yet
|
648
|
+
begin
|
649
|
+
@w.gVmap.centerOn(@offset_x*256,@offset_y*256)
|
650
|
+
rescue ArgumentError
|
651
|
+
# swallow
|
652
|
+
end
|
653
|
+
|
654
|
+
@wakeupCounter += 1
|
655
|
+
return if @wakeupCounter <= TICKSTOSKIP
|
656
|
+
@wakeupCounter = 0
|
657
|
+
|
658
|
+
if @fs_socket.nil? then
|
659
|
+
begin
|
660
|
+
@fs_socket = TCPSocket.open('localhost', FS_PORT)
|
661
|
+
movemap(@node, true)
|
662
|
+
rescue
|
663
|
+
#swallow all errors
|
664
|
+
puts "Non-critical socket error: #{$!}"
|
665
|
+
end
|
666
|
+
else
|
667
|
+
begin
|
668
|
+
@fs_queries.each do |q|
|
669
|
+
@fs_socket.print("get " + q + "\r\n")
|
670
|
+
s=""
|
671
|
+
while select([@fs_socket], nil, nil, 0.1 ) do
|
672
|
+
s += @fs_socket.read(1)
|
673
|
+
end
|
674
|
+
if s.include?(q) then
|
675
|
+
@fs_ans << s.split("\n")
|
676
|
+
@fs_ans.flatten!
|
677
|
+
end
|
678
|
+
end
|
679
|
+
rescue
|
680
|
+
puts "Warning: Can not communicate with Flightsimulator. Is Telnet interface configured?"
|
681
|
+
@scene.removeItem(@rose)
|
682
|
+
@scene.removeItem(@pointer)
|
683
|
+
@fs_socket = nil
|
684
|
+
@hud = nil
|
685
|
+
else # rescue
|
686
|
+
# p @fs_ans
|
687
|
+
if @fs_ans.length>0 then # check if any answer has been received yet.
|
688
|
+
if !@hud.nil? then
|
689
|
+
@posnode.lon = get_data("/position/longitude-deg")
|
690
|
+
@posnode.lat = get_data("/position/latitude-deg")
|
691
|
+
@rot = get_data("/orientation/heading-deg")
|
692
|
+
@alt = get_data("/position/ground-elev-m")
|
693
|
+
@speed = get_data("/velocities/groundspeed-kt") * 1.852
|
694
|
+
@hud_widget.w.lBlat.setText("%2.3f�" % @posnode.lat)
|
695
|
+
@hud_widget.w.lBlon.setText("%2.3f�" % @posnode.lon)
|
696
|
+
@speed=5.0;@alt=1000
|
697
|
+
conversion = @metricUnit ? 1 : 0.54
|
698
|
+
@hud_widget.w.lBspeed.setText("%3.1f" % (@speed*conversion) + @metricUnit ? " km/h" : "kt")
|
699
|
+
@hud_widget.w.lBheading.setText("%3.1f�" % (@rot))
|
700
|
+
conversion = @metricUnit ? 1 : 3.281
|
701
|
+
@hud_widget.w.lBalt.setText("%3.1f" % (@alt*conversion) + @metricUnit ? "m" : "ft")
|
702
|
+
mainnode_x=@node.toxtile
|
703
|
+
mainnode_y=@node.toytile
|
704
|
+
@rose.setPos((@posnode.toxtile - mainnode_x) * 256, (@posnode.toytile - mainnode_y) * 256)
|
705
|
+
|
706
|
+
@pointer.setTransform(Qt::Transform.new.scale(SCALE_SVG,SCALE_SVG).rotate(@rot+180.0) \
|
707
|
+
.translate(-@pointer_offsetx, -@pointer_offsetx))
|
708
|
+
@pointer.setPos((@posnode.toxtile - mainnode_x) * 256 ,(@posnode.toytile - mainnode_y) * 256)
|
709
|
+
|
710
|
+
to_x = mainnode_x
|
711
|
+
to_y = mainnode_y
|
712
|
+
to_lon = @node.lon
|
713
|
+
to_lat = @node.lat
|
714
|
+
if !@w.cBtoorigin.isChecked and !@waypoints.currentwp.nil? then
|
715
|
+
if !@waypoints.nodes[@waypoints.currentwp-1].nil? then
|
716
|
+
to_x = @waypoints.nodes[@waypoints.currentwp-1].toxtile
|
717
|
+
to_y = @waypoints.nodes[@waypoints.currentwp-1].toytile
|
718
|
+
to_lon = @waypoints.nodes[@waypoints.currentwp-1].lon
|
719
|
+
to_lat = @waypoints.nodes[@waypoints.currentwp-1].lat
|
720
|
+
end
|
721
|
+
end
|
722
|
+
@pointertoorigin.setTransform(Qt::Transform.new.scale(SCALE_SVG,SCALE_SVG).rotateRadians(Math::PI / 2 + \
|
723
|
+
Math.atan2((@posnode.toytile - to_y), (@posnode.toxtile - to_x))) \
|
724
|
+
.translate(-@pointertoorigin_offsetx, -@pointertoorigin_offsetx))
|
725
|
+
@pointertoorigin.setPos((@posnode.toxtile - mainnode_x) * 256 ,(@posnode.toytile - mainnode_y) * 256)
|
726
|
+
|
727
|
+
@hud_widget.w.lBdistance.text = @posnode.distanceto_str(to_lon, to_lat)
|
728
|
+
|
729
|
+
if @w.cBautocenter.isChecked then
|
730
|
+
@offset_x = @posnode.toxtile - mainnode_x
|
731
|
+
@offset_y = @posnode.toytile - mainnode_y
|
732
|
+
movemap(@node)
|
733
|
+
# @w.gVmap.centerOn(@offset_x*256,@offset_y*256)
|
734
|
+
# if !@hud.nil? then
|
735
|
+
# @hud.setPos(@w.gVmap.mapToScene(0,0))
|
736
|
+
# end
|
737
|
+
end
|
738
|
+
if @mytrack_current >= 0 and @w.pBrecordTrack.isChecked then
|
739
|
+
if @mytracks[@mytrack_current].nil? then
|
740
|
+
@mytracks[@mytrack_current] = Way.new(1, 'user', Time.now, nextcolor)
|
741
|
+
@linepen.setColor(Qt::Color.new(@mytracks[@mytrack_current].color))
|
742
|
+
@prev_track_node = false
|
743
|
+
end
|
744
|
+
@mytracks[@mytrack_current] << Node.new(nil, Time.now, @posnode.lon, @posnode.lat, @alt)
|
745
|
+
n = @mytracks[@mytrack_current].nodes.last
|
746
|
+
n.speed = @speed
|
747
|
+
if !@prev_track_node then
|
748
|
+
@tckpath = Qt::PainterPath.new(Qt::PointF.new((n.toxtile - mainnode_x) * 256, (n.toytile - mainnode_y) * 256))
|
749
|
+
@mytracks[@mytrack_current].path=TrackGraphicsPathItem.new(@mytracks[@mytrack_current])
|
750
|
+
@mytracks[@mytrack_current].path.setPath(@tckpath)
|
751
|
+
@mytracks[@mytrack_current].path.setZValue(Z_VALUE_TRACK)
|
752
|
+
@mytracks[@mytrack_current].path.setPen(@linepen)
|
753
|
+
@scene.addItem(@mytracks[@mytrack_current].path)
|
754
|
+
@prev_track_node = true
|
755
|
+
else
|
756
|
+
@tckpath.lineTo((n.toxtile - mainnode_x) * 256, (n.toytile - mainnode_y) * 256)
|
757
|
+
@mytracks[@mytrack_current].path.setPath(@tckpath)
|
758
|
+
end
|
759
|
+
end
|
760
|
+
|
761
|
+
end # if !@hud.nil?
|
762
|
+
end # if @fs_ans.length>0
|
763
|
+
end # rescue
|
764
|
+
@fs_ans=[]
|
765
|
+
end # socket nil
|
766
|
+
# p "wakeup out"
|
767
|
+
end
|
768
|
+
|
769
|
+
def autosaveTimer()
|
770
|
+
savetrack(@mytracks, false)
|
771
|
+
end
|
772
|
+
|
773
|
+
def pBrecordTrack_toggled(state)
|
774
|
+
if state
|
775
|
+
@mytrack_current += 1
|
776
|
+
@w.pBrecordTrack.text = "Recording Track #{@mytrack_current + 1}"
|
777
|
+
else
|
778
|
+
@w.pBrecordTrack.text = "Record Track #{@mytrack_current + 2}"
|
779
|
+
end
|
780
|
+
end
|
781
|
+
|
782
|
+
def cBpointorigin_clicked()
|
783
|
+
@w.fRcurrentwp.enabled = !@w.cBtoorigin.isChecked()
|
784
|
+
end
|
785
|
+
|
786
|
+
def pBminus_clicked()
|
787
|
+
zoomminus
|
788
|
+
end
|
789
|
+
|
790
|
+
def pBplus_clicked()
|
791
|
+
zoomplus
|
792
|
+
end
|
793
|
+
|
794
|
+
def pBexit_clicked()
|
795
|
+
puts "Syncing data and exiting."
|
796
|
+
@cfg.setValue("metricUnit", Qt::Variant.new(@metricUnit))
|
797
|
+
@cfg.setValue("zoom", Qt::Variant.new(@zoom))
|
798
|
+
@cfg.setValue("lat", Qt::Variant.new(@node.lat))
|
799
|
+
@cfg.setValue("lon", Qt::Variant.new(@node.lon))
|
800
|
+
@cfg.setValue("rwChecked", Qt::Variant.new(@w.cBrw.isChecked))
|
801
|
+
@cfg.setValue("nbdChecked", Qt::Variant.new(@w.cBndb.isChecked))
|
802
|
+
@cfg.setValue("vorChecked", Qt::Variant.new(@w.cBvor.isChecked))
|
803
|
+
@cfg.sync
|
804
|
+
@parent.close
|
805
|
+
end
|
806
|
+
|
807
|
+
def cBvor_clicked()
|
808
|
+
movemap(@node, true)
|
809
|
+
end
|
810
|
+
|
811
|
+
def cBndb_clicked()
|
812
|
+
movemap(@node, true)
|
813
|
+
end
|
814
|
+
|
815
|
+
def cBrw_clicked()
|
816
|
+
movemap(@node, true)
|
817
|
+
end
|
818
|
+
|
819
|
+
def resize(*k)
|
820
|
+
super
|
821
|
+
@hud.setPos(@w.gVmap.mapToScene(0,0)) if !@hud.nil?
|
822
|
+
end
|
823
|
+
|
824
|
+
def keyPressEvent(keyevent)
|
825
|
+
case keyevent.text
|
826
|
+
when "+"
|
827
|
+
zoomplus
|
828
|
+
when "-"
|
829
|
+
zoomminus
|
830
|
+
when " "
|
831
|
+
@w.pBrecordTrack.click
|
832
|
+
else # case
|
833
|
+
super
|
834
|
+
end # case
|
835
|
+
end
|
836
|
+
end
|
837
|
+
|
838
|
+
|
839
|
+
class FlagGraphicsPixmapItem < Qt::GraphicsPixmapItem
|
840
|
+
def initialize(*k)
|
841
|
+
super
|
842
|
+
end
|
843
|
+
|
844
|
+
def mousePressEvent(mouseEvent)
|
845
|
+
if mouseEvent.button == Qt::LeftButton then
|
846
|
+
dlg=mouseEvent.widget.parent.parent
|
847
|
+
dlg.waypoints.currentwp = childItems[0].toPlainText.to_i
|
848
|
+
dlg.w.lBcurrentwp.text = childItems[0].toPlainText
|
849
|
+
else
|
850
|
+
super
|
851
|
+
end
|
852
|
+
end
|
853
|
+
end
|
854
|
+
|
855
|
+
|
856
|
+
class TrackGraphicsPathItem < Qt::GraphicsPathItem
|
857
|
+
attr_reader :nodeinfo, :nodeinfo_widget
|
858
|
+
|
859
|
+
@@nodeinfo_array = Array.new
|
860
|
+
|
861
|
+
def initialize(parent)
|
862
|
+
super()
|
863
|
+
@parent=parent
|
864
|
+
@addToScene = true
|
865
|
+
|
866
|
+
# needs to be embedded in other graphics element to circumvent a bug if the position of
|
867
|
+
# the ProxyWidget is above, below 2**15 - 1, bug in QT
|
868
|
+
@nodeinfo = Qt::GraphicsRectItem.new(0,0,100,100)
|
869
|
+
@nodeinfo.setPen(Qt::Pen.new(Qt::NoPen))
|
870
|
+
|
871
|
+
@nodeinfow = Qt::GraphicsProxyWidget.new(@nodeinfo)
|
872
|
+
@nodeinfo_widget = NodeinfoWidget.new(@nodeinfo)
|
873
|
+
@nodeinfo_widget.setAttribute(Qt::WA_Hover)
|
874
|
+
@nodeinfow.setWidget(@nodeinfo_widget)
|
875
|
+
@nodeinfo.setZValue(Z_VALUE_HUD)
|
876
|
+
@nodeinfo.setAcceptHoverEvents(true)
|
877
|
+
@nodeinfo.setVisible(false)
|
878
|
+
setAcceptHoverEvents(true)
|
879
|
+
setHandlesChildEvents(true)
|
880
|
+
|
881
|
+
# store these elements in permanent arry
|
882
|
+
# otherwise GC will remove them and then causes core-dump in QT
|
883
|
+
@@nodeinfo_array << [@nodeinfow, @nodeinfo_widget]
|
884
|
+
end
|
885
|
+
|
886
|
+
def colorize(data, dlg)
|
887
|
+
scene=dlg.scene
|
888
|
+
prev_x = path.elementAt(0).x
|
889
|
+
prev_y = path.elementAt(0).y
|
890
|
+
group = Qt::GraphicsItemGroup.new
|
891
|
+
x = y = 0
|
892
|
+
pen=Qt::Pen.new
|
893
|
+
pen.setWidth(5)
|
894
|
+
line=nil
|
895
|
+
d=data.dup
|
896
|
+
d.delete_if{|e| e<=0.0 }
|
897
|
+
if d.length==0 then
|
898
|
+
Qt::MessageBox::warning(nil, "Warning", "No elevation/speed data found in track.")
|
899
|
+
return
|
900
|
+
end
|
901
|
+
max=d.max
|
902
|
+
min=d.min
|
903
|
+
delta=max-min
|
904
|
+
color=nil
|
905
|
+
1.upto(path.elementCount-2){|i|
|
906
|
+
color=Qt::Color.new
|
907
|
+
if data[i]>0.0 then
|
908
|
+
color.setHsv((data[i]-min)/delta * COLORRANGE_DEG + COLOROFFSET_DEG,255,255)
|
909
|
+
else
|
910
|
+
color.setRgb(100,100,100)
|
911
|
+
end
|
912
|
+
pen.setColor(color)
|
913
|
+
x = path.elementAt(i).x
|
914
|
+
y = path.elementAt(i).y
|
915
|
+
line = Qt::GraphicsLineItem.new(prev_x, prev_y, x, y)
|
916
|
+
line.setPen(pen)
|
917
|
+
line.setZValue(Z_VALUE_TRACK_COLORED)
|
918
|
+
group.addToGroup(line)
|
919
|
+
prev_x = x
|
920
|
+
prev_y = y
|
921
|
+
}
|
922
|
+
group.setZValue(Z_VALUE_TRACK_COLORED)
|
923
|
+
scene.addItem(group)
|
924
|
+
|
925
|
+
end
|
926
|
+
|
927
|
+
def contextMenuEvent(contextEvent)
|
928
|
+
dlg=contextEvent.widget.parent.parent
|
929
|
+
entries=["Colorize Altitude", "Colorize Speed"]
|
930
|
+
menu=Qt::Menu.new
|
931
|
+
entries.each{|e|
|
932
|
+
if e=="-" then
|
933
|
+
menu.addSeparator
|
934
|
+
else
|
935
|
+
menu.addAction(e)
|
936
|
+
end
|
937
|
+
}
|
938
|
+
sel=menu.exec(contextEvent.screenPos)
|
939
|
+
sel=sel.text if !sel.nil?
|
940
|
+
data=[]
|
941
|
+
case sel
|
942
|
+
when entries[0]
|
943
|
+
@parent.nodes.each{|n|
|
944
|
+
data << n.elevation
|
945
|
+
}
|
946
|
+
colorize(data, dlg)
|
947
|
+
|
948
|
+
when entries[1]
|
949
|
+
@parent.nodes.each{|n|
|
950
|
+
data << n.speed
|
951
|
+
}
|
952
|
+
colorize(data, dlg)
|
953
|
+
|
954
|
+
end # case
|
955
|
+
end
|
956
|
+
|
957
|
+
def hoverMoveEvent(hoverEvent)
|
958
|
+
# ap "hovermove in"
|
959
|
+
dlg=hoverEvent.widget.parent.parent
|
960
|
+
|
961
|
+
if @addToScene then
|
962
|
+
dlg.scene.addItem(@nodeinfo)
|
963
|
+
@addToScene = false
|
964
|
+
end
|
965
|
+
|
966
|
+
if !@nodeinfo_widget.hover_on then
|
967
|
+
@nodeinfo.setVisible(true)
|
968
|
+
@nodeinfo_widget.hover_on = true
|
969
|
+
end
|
970
|
+
x=hoverEvent.pos.x
|
971
|
+
y=hoverEvent.pos.y
|
972
|
+
e=nil
|
973
|
+
hit=nil
|
974
|
+
1.upto(self.path.elementCount-1){|i|
|
975
|
+
e=self.path.elementAt(i)
|
976
|
+
if ((e.x - x).abs < 3) and ((e.y - y).abs < 3)then
|
977
|
+
hit=i
|
978
|
+
break
|
979
|
+
end
|
980
|
+
}
|
981
|
+
|
982
|
+
if !hit.nil? and !@parent.nil? then
|
983
|
+
n=@parent.nodes[hit]
|
984
|
+
@nodeinfo_widget.w.lBlon.text="%.3f�" % n.lon
|
985
|
+
@nodeinfo_widget.w.lBlat.text="%.3f�" % n.lat
|
986
|
+
@nodeinfo_widget.w.lBalt.text="%.1fm" % n.elevation
|
987
|
+
@nodeinfo_widget.w.lBspeed.text="%.1fkm/h" % n.speed
|
988
|
+
pos = mapToScene(hoverEvent.pos)
|
989
|
+
if !@nodeinfo.isVisible or @nodeinfo_widget.hover_widget_pos.nil? or (!@nodeinfo_widget.hover_widget_pos.nil? \
|
990
|
+
and Qt::LineF.new(@nodeinfo_widget.hover_widget_pos, pos).length > 30) then
|
991
|
+
dlg.scene.items.each {|item|
|
992
|
+
if item.kind_of? Qt::GraphicsRectItem then
|
993
|
+
if item != @nodeinfo then
|
994
|
+
# item.setVisible(false)
|
995
|
+
end
|
996
|
+
end
|
997
|
+
}
|
998
|
+
@nodeinfo.setVisible(true)
|
999
|
+
@nodeinfo_widget.hover_widget_pos=pos
|
1000
|
+
@nodeinfo.setPos(pos)
|
1001
|
+
@nodeinfo_widget.hovertimer.stop
|
1002
|
+
end
|
1003
|
+
end
|
1004
|
+
# ap "hovermove out"
|
1005
|
+
end
|
1006
|
+
|
1007
|
+
def hoverLeaveEvent(hoverEvent)
|
1008
|
+
# ap "hoverleave in"
|
1009
|
+
if @nodeinfo_widget.hover_on then
|
1010
|
+
@nodeinfo_widget.hovertimer.start(HOVER_TIMER)
|
1011
|
+
end
|
1012
|
+
# ap "hoverleave out"
|
1013
|
+
end
|
1014
|
+
end
|
1015
|
+
|
1016
|
+
|
1017
|
+
class TileGraphicsPixmapItem < Qt::GraphicsPixmapItem
|
1018
|
+
def mousePressEvent(mouseEvent)
|
1019
|
+
pos = mouseEvent.scenePos
|
1020
|
+
dlg=mouseEvent.widget.parent.parent
|
1021
|
+
case mouseEvent.button
|
1022
|
+
when Qt::LeftButton
|
1023
|
+
dlg.offset_x = pos.x / 256.0
|
1024
|
+
dlg.offset_y = pos.y / 256.0
|
1025
|
+
dlg.movemap(dlg.node)
|
1026
|
+
when Qt::RightButton
|
1027
|
+
|
1028
|
+
end # case
|
1029
|
+
end
|
1030
|
+
|
1031
|
+
def contextMenuEvent(contextEvent)
|
1032
|
+
dlg=contextEvent.widget.parent.parent
|
1033
|
+
entries=["Set Waypoint", "Delete Waypoint", "Set Origin", "-", "Save Waypoints", "Save Track", "Load Waypoints",
|
1034
|
+
"Load Track", ["Metric Units", dlg.metricUnit]]
|
1035
|
+
menu=Qt::Menu.new
|
1036
|
+
entries.each{|e|
|
1037
|
+
if e.kind_of? Array then
|
1038
|
+
action = Qt::Action.new(e[0], nil)
|
1039
|
+
action.setCheckable(true)
|
1040
|
+
action.setChecked(e[1])
|
1041
|
+
menu.addAction(action)
|
1042
|
+
else
|
1043
|
+
if e=="-" then
|
1044
|
+
menu.addSeparator
|
1045
|
+
else
|
1046
|
+
menu.addAction(e)
|
1047
|
+
end
|
1048
|
+
end
|
1049
|
+
}
|
1050
|
+
sel=menu.exec(contextEvent.screenPos)
|
1051
|
+
sel=sel.text if !sel.nil?
|
1052
|
+
lon=dlg.node.tolon(dlg.node.xtile + contextEvent.scenePos.x / 256.0)
|
1053
|
+
lat=dlg.node.tolat(dlg.node.ytile + contextEvent.scenePos.y / 256.0)
|
1054
|
+
case sel
|
1055
|
+
when entries[0]
|
1056
|
+
i=dlg.waypoints << Node.new(nil, Time.now, lon, lat)
|
1057
|
+
dlg.putflag(contextEvent.scenePos.x, contextEvent.scenePos.y, i, dlg.waypoints.nodes.last)
|
1058
|
+
if i==1 and dlg.waypoints.nodes.length == 1 then
|
1059
|
+
dlg.w.lBcurrentwp.text="1"
|
1060
|
+
dlg.waypoints.currentwp=1
|
1061
|
+
end
|
1062
|
+
|
1063
|
+
when entries[1]
|
1064
|
+
d=dlg.waypoints.del(lon,lat)
|
1065
|
+
if dlg.w.lBcurrentwp.text.to_i == d then
|
1066
|
+
dlg.w.lBcurrentwp.text="-"
|
1067
|
+
end
|
1068
|
+
dlg.movemap(dlg.node, true)
|
1069
|
+
|
1070
|
+
when entries[2]
|
1071
|
+
dlg.node=Node.new(1, Time.now, lon, lat)
|
1072
|
+
dlg.movemap(dlg.node, true)
|
1073
|
+
|
1074
|
+
when entries[4]
|
1075
|
+
dlg.saveWaypoints([dlg.waypoints])
|
1076
|
+
|
1077
|
+
when entries[5]
|
1078
|
+
dlg.savetrack(dlg.mytracks)
|
1079
|
+
|
1080
|
+
when entries[6]
|
1081
|
+
savecurrent = dlg.waypoints.currentwp
|
1082
|
+
if dlg.loadwaypoint("Load Waypoints") then
|
1083
|
+
dlg.waypoints.currentwp = nil
|
1084
|
+
else
|
1085
|
+
dlg.waypoints.currentwp = savecurrent
|
1086
|
+
end
|
1087
|
+
|
1088
|
+
when entries[7]
|
1089
|
+
dlg.mytrack_current += (dlg.w.pBrecordTrack.isChecked ? 0 : 1)
|
1090
|
+
savewp=dlg.mytracks[dlg.mytrack_current]
|
1091
|
+
if dlg.mytracks[dlg.mytrack_current].nil? then
|
1092
|
+
dlg.mytracks[dlg.mytrack_current] = Way.new(1, 'user', Time.now, dlg.nextcolor)
|
1093
|
+
@prev_track_node = nil
|
1094
|
+
end
|
1095
|
+
if dlg.loadtrack("Load Track") then
|
1096
|
+
dlg.w.pBrecordTrack.text = "Record Track #{dlg.mytrack_current + 2}"
|
1097
|
+
dlg.w.pBrecordTrack.setChecked(false)
|
1098
|
+
else
|
1099
|
+
dlg.mytracks[dlg.mytrack_current]=savewp
|
1100
|
+
end
|
1101
|
+
|
1102
|
+
when entries[8][0]
|
1103
|
+
dlg.metricUnit = !dlg.metricUnit
|
1104
|
+
|
1105
|
+
end #case
|
1106
|
+
end
|
1107
|
+
end
|
1108
|
+
|
1109
|
+
|
1110
|
+
class Qt::GraphicsScene
|
1111
|
+
def mouseMoveEvent(mouseEvent)
|
1112
|
+
super
|
1113
|
+
# a=mouseEvent.scenePos()
|
1114
|
+
# p a.x
|
1115
|
+
end
|
1116
|
+
end
|
1117
|
+
|