fgmapping 1.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -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
+
@@ -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
+
@@ -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
+