Subversion Repositories Projects

Rev

Rev 711 | Go to most recent revision | Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
674 KeyOz 1
/***************************************************************************
2
 *   Copyright (C) 2009 by Manuel Schrape                                  *
3
 *   manuel.schrape@gmx.de                                                 *
4
 *                                                                         *
5
 *   This program is free software; you can redistribute it and/or modify  *
6
 *   it under the terms of the GNU General Public License as published by  *
7
 *   the Free Software Foundation; either version 2 of the License.        *
8
 *                                                                         *
9
 *   This program is distributed in the hope that it will be useful,       *
10
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
11
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
12
 *   GNU General Public License for more details.                          *
13
 *                                                                         *
14
 *   You should have received a copy of the GNU General Public License     *
15
 *   along with this program; if not, write to the                         *
16
 *   Free Software Foundation, Inc.,                                       *
17
 *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
18
 ***************************************************************************/
19
 
20
#include <QMessageBox>
21
#include <QDomDocument>
22
#include <QFile>
23
 
24
#include "dlg_Main.h"
25
#include "dlg_MapPos.h"
26
 
27
// Konstruktor Main-Form
28
dlg_Main::dlg_Main()
29
{
30
    setupUi(this);
31
 
32
    o_Settings = new cSettings();
33
 
34
    o_Input = new Input();
35
 
36
    o_Map = new MapControl(QSize(25,25));
37
    l_RouteWP = new LineString();
38
    init_Directorys();
39
    init_GUI();
40
    init_Connections();
41
}
42
 
43
// Grafische Oberfläche initialisieren
44
void dlg_Main::init_GUI()
45
{
46
    setWindowTitle(QA_NAME + " " + QA_VERSION);
47
 
48
    resize(o_Settings->GUI.Size);
49
    move(o_Settings->GUI.Point);
50
 
51
    if (o_Settings->GUI.isMax)
52
    {
53
        showMaximized();
54
    }
55
 
56
    for(int z = 0; z < o_Settings->SERVER.IP_MAX; z++)
57
    {
58
        if (cb_Server->findText(o_Settings->SERVER.IP[z]) == -1)
59
        {
60
            cb_Server->addItem(o_Settings->SERVER.IP[z]);
61
        }
62
    }
63
 
64
    cb_Server->setCurrentIndex(o_Settings->SERVER.IP_ID);
65
 
66
    le_Password->setText(o_Settings->SERVER.Password);
67
 
68
    sb_Intervall->setValue(o_Settings->DATA.Intervall);
69
 
70
    cb_CenterPos->setChecked(o_Settings->CONFIG.cb_CenterPos);
71
    cb_ShowRoute->setChecked(o_Settings->CONFIG.cb_ShowRoute);
72
    cb_ShowWPs->setChecked(o_Settings->CONFIG.cb_ShowWPs);
73
    cb_Goto->setChecked(o_Settings->CONFIG.cb_Goto);
74
 
75
//    tb_More->addWidget(cb_Maps);
76
    cb_Maps->setVisible(false);
77
 
78
    ac_Toolbar->setChecked(o_Settings->GUI.Toolbar);
79
 
80
    if (ac_Toolbar->isChecked())
81
    {
82
        btn_Connect->setVisible(false);
83
    }
84
    else
85
    {
86
        ToolBar->setVisible(false);
87
        tb_More->setVisible(false);
88
    }
89
}
90
 
91
// Signale mit Slots verbinden
92
void dlg_Main::init_Connections()
93
{
94
    connect(ac_Connect, SIGNAL(triggered()), this, SLOT(slot_ac_Connect()));
95
    connect(ac_Toolbar, SIGNAL(triggered()), this, SLOT(slot_ac_Toolbar()));
96
 
97
    // About QMK-Kernel & About-QT Dialog einfügen
98
    connect(ac_About, SIGNAL(triggered()), this, SLOT(slot_ac_About()));
99
    menu_Help->addAction(trUtf8("Über &Qt"), qApp, SLOT(aboutQt()));
100
 
101
    connect(sb_Intervall, SIGNAL(valueChanged(int)), this, SLOT(slot_sb_Intervall(int)));
102
 
103
    connect(sl_Zoom,   SIGNAL(valueChanged(int)), this, SLOT(slot_Zoom(int)));
104
    connect(cb_Maps,   SIGNAL(currentIndexChanged(int)), this, SLOT(slot_ChangeMap(int)));
105
 
106
    connect(cb_ShowWPs, SIGNAL(toggled(bool)), this, SLOT(slot_ShowWayPoints(bool)));
107
 
108
    connect(btn_WPAdd,    SIGNAL(clicked()), this, SLOT(slot_btn_WPAdd()));
109
    connect(btn_WPFly,    SIGNAL(clicked()), this, SLOT(slot_btn_WPFly()));
110
    connect(btn_WPDelete, SIGNAL(clicked()), this, SLOT(slot_btn_WPDelete()));
111
 
112
    connect(ac_LoadRoute, SIGNAL(triggered()), this, SLOT(slot_ac_LoadWayPoints()));
113
    connect(ac_SaveRoute, SIGNAL(triggered()), this, SLOT(slot_ac_SaveRoute()));
114
 
115
    connect(ac_LoadMap,     SIGNAL(triggered()), this, SLOT(slot_ac_LoadMapPic()));
116
    connect(ac_Record,      SIGNAL(triggered()), this, SLOT(slot_ac_Record()));
117
    connect(ac_RouteDelete, SIGNAL(triggered()), this, SLOT(slot_ac_RouteDelete()));
118
}
119
 
120
void dlg_Main::init_Directorys()
121
{
122
    QDir *t_Dir = new QDir();
123
 
124
    s_Dir.MainData = QDir::homePath() + "/QMK-Data";
125
    if (!t_Dir->exists(s_Dir.MainData))
126
    {
127
        t_Dir->mkdir(s_Dir.MainData);
128
    }
129
 
130
    s_Dir.MapCache = s_Dir.MainData + "/Map-Cache";
131
    if (!t_Dir->exists(s_Dir.MapCache))
132
    {
133
        t_Dir->mkdir(s_Dir.MapCache);
134
    }
135
 
136
    s_Dir.WPRoutes = s_Dir.MainData + "/WP-Routes";
137
    if (!t_Dir->exists(s_Dir.WPRoutes))
138
    {
139
        t_Dir->mkdir(s_Dir.WPRoutes);
140
    }
141
 
142
    s_Dir.MapPics = s_Dir.MainData + "/Map-Pics";
143
    if (!t_Dir->exists(s_Dir.MapPics))
144
    {
145
        t_Dir->mkdir(s_Dir.MapPics);
146
    }
147
 
148
    s_Dir.Flights = s_Dir.MainData + "/Flights";
149
    if (!t_Dir->exists(s_Dir.Flights))
150
    {
151
        t_Dir->mkdir(s_Dir.Flights);
152
    }
153
}
154
 
155
void dlg_Main::parse_IP_Data(QString t_Data)
156
{
157
    QStringList Data;
158
    Data = t_Data.split(":");
159
 
160
    if (Data.count() > 1)
161
    {
162
        int CMD = Data[2].toInt();
163
 
164
        switch(CMD)
165
        {
166
            case 501 :
167
            {
168
                o_Input->send_Data(HandlerIP::make_Frame(0, 105, le_Password->text()));
169
            }
170
            break;
171
            case 505 :
172
            {
173
                if (Data[3] == "OK")
174
                {
175
                }
176
                else
177
                {
178
                    QMessageBox::warning(this, QA_NAME, trUtf8("Authentifizierung fehlgeschlagen. <br />Daten senden zum Mikrokopter nicht möglich."), QMessageBox::Ok);
179
                }
180
            }
181
            break;
182
        }
183
    }
184
}
185
 
186
// Eingangsdaten verarbeiten
187
void dlg_Main::parse_MK_Data(QString t_Data)
188
{
189
    unsigned char OutData[150];
190
    char *InData = t_Data.toLatin1().data();
191
 
192
    if (HandlerMK::Decode_64(InData, t_Data.length(), OutData) != 0)
193
    {
194
 
195
        switch(InData[2])
196
        {
197
            case 'V' : // Versions-Info
198
                {
199
                    o_Input->stop_Resend(DATA_VERSION);
200
                    VersionInfo = HandlerMK::parse_Version(OutData, InData[1] - 'a');
201
                    setWindowTitle(QA_NAME + " " + QA_VERSION + " - " + VersionInfo.Hardware + " " + VersionInfo.Version);
202
 
203
                    if (VersionInfo.ID == ADDRESS_NC)
204
                    {
205
                        c_Data[0] = sb_Intervall->value() / 10;
206
                        o_Input->send_Data(HandlerMK::make_Frame('o', ADDRESS_ALL, c_Data, 1).toLatin1().data());
207
                    }
208
                    else // TODO: Befehl wenden zum Wechseln auf Navi.
209
                    {
210
                    }
211
                }
212
            break;
213
            case 'O' : // Navi-OSD-Data
214
                {
215
                    if (InData[1] - 'a' == ADDRESS_NC)
216
                    {
217
                        s_MK_NaviData MK_NaviData;
218
 
219
                        memcpy((unsigned char *)&MK_NaviData, (unsigned char *)&OutData, sizeof(MK_NaviData));
220
                        if (MK_NaviData.Version == MK_VERSION_NAVI)
221
                        {
222
                            show_Data(MK_NaviData);
223
                            add_Position(MK_NaviData);
224
                        }
225
                    }
226
                }
227
            break;
228
            case 'W' : // WayPoints
229
                {
230
                    o_Input->stop_Resend(DATA_WRITE_WAYPOINT);
231
 
232
                    if (OutData[0] < l_WayPoints.count())
233
                    {
234
                        send_WayPoints(l_WayPoints, OutData[0] + 1);
235
                    }
236
                }
237
            break;
238
        }
239
    }
240
}
241
 
242
///////////////////////////////////////////////////////////////////
243
// QMK-Maps                                                      //
244
///////////////////////////////////////////////////////////////////
245
 
246
void dlg_Main::create_Map()
247
{
248
    o_Map->resize(w_Map->size() - QSize(25,50));
249
    o_Map->enablePersistentCache(s_Dir.MapCache);
250
    o_Map->showScale(true);
251
 
252
    o_Adapter = new OSMMapAdapter();
253
 
254
    o_Layer   = new MapLayer("MapLayer", o_Adapter);
255
    o_Click   = new GeometryLayer("Click", o_Adapter);
256
    o_Info    = new GeometryLayer("Poute", o_Adapter);
257
    o_RouteWP = new GeometryLayer("Route-WayPoint", o_Adapter);
258
    o_RouteFL = new GeometryLayer("Route-Flight", o_Adapter);
259
 
260
    o_Map->addLayer(o_Layer);
261
    o_Map->addLayer(o_Click);
262
    o_Map->addLayer(o_Info);
263
    o_Map->addLayer(o_RouteWP);
264
    o_Map->addLayer(o_RouteFL);
265
 
266
    o_Map->setZoom(17);
267
//    o_Map->setView(QPointF(o_Settings->NAVI.Longitude,o_Settings->NAVI.Latitude));
268
//    o_Map->setView(QPointF(13.5,52.5));
269
    o_Map->setView(QPointF(13.419805,52.431787));
270
    connect(o_Map, SIGNAL(mouseEventCoordinate(const QMouseEvent*, const QPointF)), this, SLOT(slot_Click(const QMouseEvent*, const QPointF)));
271
 
272
    l_Map->addWidget(o_Map);
273
 
274
    sl_Zoom->setValue(17);
275
 
276
    // Flight
277
    Pen[0] = new QPen(QColor(0,0,255,255));
278
    Pen[0]->setWidth(2);
279
    Pen[1] = new QPen(QColor(0,0,255,255));
280
    Pen[1]->setWidth(1);
281
    // WayPoint
282
    Pen[2] = new QPen(QColor(255,0,0,255));
283
    Pen[2]->setWidth(2);
284
    Pen[3] = new QPen(QColor(255,0,0,255));
285
    Pen[3]->setWidth(1);
286
    // Info
287
    Pen[4] = new QPen(QColor(0,128,128,255));
288
    Pen[4]->setWidth(2);
289
    Pen[5] = new QPen(QColor(0,128,128,255));
290
    Pen[5]->setWidth(1);
291
}
292
 
293
// auf Veränderung der Fenstergröße reagieren
294
void dlg_Main::resizeEvent ( QResizeEvent * event )
295
{
296
    event = event;
297
    o_Map->resize(w_Map->size() - QSize(25,25));
298
}
299
 
300
void dlg_Main::wheelEvent(QWheelEvent *event)
301
{
302
    int zoomValue = sl_Zoom->value();
303
    int numDegrees = event->delta() / 8;
304
    int numSteps = numDegrees / 15;
305
    zoomValue += numSteps;
306
    if (zoomValue < 0) { zoomValue = 0;}
307
    if (zoomValue > 17) { zoomValue = 17;}
308
    sl_Zoom->setValue(zoomValue);
309
}
310
 
311
QList<sWayPoint> dlg_Main::parse_WayPointKML(QString s_File)
312
{
313
    QList<sWayPoint> tmp_WayPoints;
314
    sWayPoint tmp_WayPoint;
315
 
316
    QFile f_KML(s_File);
317
    f_KML.open(QIODevice::ReadOnly | QIODevice::Text);
318
 
319
    QByteArray s_KML;
320
 
321
    while (!f_KML.atEnd())
322
    {
323
        s_KML.append(f_KML.readLine());
324
     }
325
 
326
    f_KML.close();
327
 
328
    QDomDocument *UserXML;
329
    UserXML = new QDomDocument;
330
 
331
    UserXML->setContent(s_KML);
332
 
333
    QDomElement Root       = UserXML->firstChildElement("kml");
334
    QDomElement Document   = Root.firstChildElement("Document");
335
    QDomElement Placemark  = Document.firstChildElement("Placemark");
336
    QDomElement Linestring = Placemark.firstChildElement("LineString");
337
 
338
    QString Name = Placemark.firstChildElement("name").toElement().text();
339
 
340
    QString Route = Linestring.firstChildElement("coordinates").toElement().text();
341
 
342
    QStringList s_Points = Route.split(" ");
343
 
344
    QStringList Position;
345
 
346
    for (int z = 0; z < s_Points.count() - 1; z++)
347
    {
348
        if (z != 20)
349
        {
350
           Position = s_Points[z].split(",");
351
           tmp_WayPoint.Longitude = Position[0].toDouble();
352
           tmp_WayPoint.Latitude  = Position[1].toDouble();
353
           tmp_WayPoint.Altitude  = Position[2].toDouble();
354
           tmp_WayPoint.Time      = sb_Time->value();
355
 
356
           tmp_WayPoints.append(tmp_WayPoint);
357
        }
358
        else
359
        {
360
            QMessageBox::warning(this, QA_NAME,trUtf8("Die Wegpunkt-Liste umfasst mehr als 20 Einträge. Es werden nur die ersten 20 Einträge übernommen."), QMessageBox::Ok);
361
 
362
            btn_WPAdd->setEnabled(false);
363
 
364
            z = s_Points.count();
365
        }
366
    }
367
    return tmp_WayPoints;
368
}
369
 
370
QList<sWayPoint> dlg_Main::parse_WayPointMKW(QString s_File)
371
{
372
    QList<sWayPoint> tmp_WayPoints;
373
    sWayPoint tmp_WayPoint;
374
 
375
    QFile f_MKW(s_File);
376
    f_MKW.open(QIODevice::ReadOnly | QIODevice::Text);
377
 
378
    QString s_MKW;
379
 
380
    while (!f_MKW.atEnd())
381
    {
382
        s_MKW.append(f_MKW.readLine());
383
     }
384
 
385
    f_MKW.close();
386
 
387
    QStringList s_Points = s_MKW.split(" ");
388
 
389
    QStringList Position;
390
 
391
    for (int z = 0; z < s_Points.count() - 1; z++)
392
    {
393
        if (z != 20)
394
        {
395
           Position = s_Points[z].split(",");
396
           tmp_WayPoint.Longitude = Position[0].toDouble();
397
           tmp_WayPoint.Latitude  = Position[1].toDouble();
398
           tmp_WayPoint.Altitude  = Position[2].toDouble();
399
           tmp_WayPoint.Time      = Position[3].toInt();
400
 
401
           tmp_WayPoints.append(tmp_WayPoint);
402
        }
403
        else
404
        {
405
            QMessageBox::warning(this, QA_NAME,trUtf8("Die Wegpunkt-Liste umfasst mehr als 20 Einträge. Es werden nur die ersten 20 Einträge übernommen."), QMessageBox::Ok);
406
 
407
            btn_WPAdd->setEnabled(false);
408
 
409
            z = s_Points.count();
410
        }
411
    }
412
    return tmp_WayPoints;
413
}
414
 
415
// Waypoint-Route anzeigen in Karte
416
void dlg_Main::show_WayPoints(QList<sWayPoint> WayPoints)
417
{
418
    Point* p_Point;
419
 
420
    o_RouteWP->removeGeometry(l_RouteWP);
421
    p_RouteWP.clear();
422
    l_WayPoints.clear();
423
 
424
    l_WayPoints = WayPoints;
425
 
426
    for (int z = 0; z < WayPoints.count(); z++)
427
    {
428
        p_Point = new Point(WayPoints[z].Longitude, WayPoints[z].Latitude);
429
 
430
        p_RouteWP.append(p_Point);
431
    }
432
 
433
    l_RouteWP = new LineString(p_RouteWP, "", Pen[3]);
434
    o_RouteWP->addGeometry(l_RouteWP);
435
 
436
    o_Map->setView(p_Point);
437
 
438
    o_Map->updateRequestNew();
439
}
440
 
441
// Waypoint-Liste speichern
442
void dlg_Main::save_WayPointsMKW(QString s_File)
443
{
444
    QFile *f_MKW = new QFile(s_File);
445
 
446
    f_MKW->open(QIODevice::ReadWrite | QIODevice::Text);
447
 
448
    QTextStream out(f_MKW);
449
 
450
    out.setRealNumberPrecision(9);
451
 
452
    for (int z = 0; z < l_WayPoints.count(); z++)
453
    {
454
        out << l_WayPoints[z].Longitude << "," << l_WayPoints[z].Latitude << "," << l_WayPoints[z].Altitude << "," << l_WayPoints[z].Time << " \n";
455
    }
456
 
457
    f_MKW->close();
458
}
459
 
460
void dlg_Main::show_Data(s_MK_NaviData t_NaviData)
461
{
462
    QString Mode = "NC-Flags : ";
463
    if (t_NaviData.NCFlags &  0x08) {le_Mode->setText(tr("Range Limit")); Mode += "R";}
464
    if (t_NaviData.NCFlags &  0x10) {le_Mode->setText(tr("Serial Error")); Mode += "S";}
465
    if (t_NaviData.NCFlags &  0x20) {le_Mode->setText(tr("Target reached")); Mode += "T";}
466
    if (t_NaviData.NCFlags &  0x40) {le_Mode->setText(tr("Manual Control")); Mode += "M";}
467
    if (t_NaviData.NCFlags &  0x01) {le_Mode->setText(tr("Free")); Mode += "F";}
468
    if (t_NaviData.NCFlags &  0x02) {le_Mode->setText(tr("Position Hold")); Mode += "P";}
469
    if (t_NaviData.NCFlags &  0x04) {le_Mode->setText(tr("Coming Home")); Mode += "C";}
470
 
471
    //qDebug(Mode.toLatin1().data());
472
 
473
    le_WP->setText(QString("%1/").arg(t_NaviData.WaypointIndex) + QString("%1").arg(t_NaviData.WaypointNumber));
474
    le_WPTime->setText(QString("%1:").arg(t_NaviData.TargetHoldTime / 60) + (QString("%1").arg(t_NaviData.TargetHoldTime % 60)).rightJustified(2, '0'));
475
    le_WPDist->setText(QString("%1m").arg(t_NaviData.TargetPositionDeviation.Distance / 10));
476
    le_HomeDist->setText(QString("%1m").arg(t_NaviData.HomePositionDeviation.Distance / 10));
477
}
478
 
479
// Aktuelle MK-Position hinzufügen
480
void dlg_Main::add_Position(s_MK_NaviData t_NaviData)
481
{
482
    sWayPoint WayPoint;
483
 
484
    WayPoint.Longitude = HandlerMK::Int2Double(t_NaviData.CurrentPosition.Longitude, 7);
485
    WayPoint.Latitude = HandlerMK::Int2Double(t_NaviData.CurrentPosition.Latitude, 7);
486
    WayPoint.Altitude = HandlerMK::Int2Double(t_NaviData.CurrentPosition.Altitude, 3);
487
 
488
    o_Settings->NAVI.Latitude  = WayPoint.Latitude;
489
    o_Settings->NAVI.Longitude = WayPoint.Longitude;
490
 
491
    l_Track.append(WayPoint);
492
 
493
    o_RouteFL->removeGeometry(l_RouteFL);
494
    p_RouteFL.append(new Point(WayPoint.Longitude, WayPoint.Latitude));
495
 
496
    o_Click->removeGeometry(LastPos);
497
 
498
    Point* P = new CirclePoint(WayPoint.Longitude, WayPoint.Latitude, "P1", Point::Middle, Pen[0]);
499
    LastPos = P;
500
//    P->setBaselevel(17);
501
    o_Click->addGeometry(P);
502
 
503
    // Target anzeigen
504
    o_Click->removeGeometry(Target);
505
 
506
    Target = new ImagePoint( HandlerMK::Int2Double(t_NaviData.TargetPosition.Longitude, 7), HandlerMK::Int2Double(t_NaviData.TargetPosition.Latitude, 7), ":/Flags/Global/Images/Flags/Target.png", "Start");
507
    Target->setBaselevel(o_Adapter->adaptedZoom());
508
    o_Click->addGeometry(Target);
509
 
510
    if (cb_CenterPos->isChecked())
511
    {
512
        o_Map->setView(QPointF(WayPoint.Longitude, WayPoint.Latitude));
513
    }
514
 
515
    if (cb_ShowRoute->isChecked())
516
    {
517
        l_RouteFL = new LineString(p_RouteFL, "", Pen[1]);
518
 
519
        o_RouteFL->addGeometry(l_RouteFL);
520
    }
521
    o_Map->updateRequestNew();
522
 
523
    if (ac_Record->isChecked())
524
    {
525
        QTextStream Out(o_Record);
526
 
527
        Out.setRealNumberPrecision(9);
528
 
529
        Out << WayPoint.Longitude << ", " << WayPoint.Latitude << ", " << WayPoint.Altitude << "\n";
530
    }
531
}
532
 
533
// Ein Ziel anfliegen.
534
// TODO: Check auf  Entfernung zur IST-Position.
535
void dlg_Main::send_Target(Point *t_Target)
536
{
537
    if (l_Track.length() > 0)
538
    {
539
        s_MK_WayPoint s_WayPoint;
540
 
541
        s_WayPoint.Position.Latitude  = int32_t(t_Target->latitude() * 10000000+0.5);
542
        s_WayPoint.Position.Longitude = int32_t(t_Target->longitude() * 10000000+0.5);
543
        s_WayPoint.Position.Altitude  = 0;
544
        s_WayPoint.Position.Status    = NEWDATA;
545
        s_WayPoint.Heading            = -1;
546
        s_WayPoint.ToleranceRadius    = 5;
547
        s_WayPoint.HoldTime           = sb_Time->value();
548
        s_WayPoint.Event_Flag         = 0;
549
        s_WayPoint.reserve[0]         = 0; // reserve
550
        s_WayPoint.reserve[1]         = 0; // reserve
551
        s_WayPoint.reserve[2]         = 0; // reserve
552
        s_WayPoint.reserve[3]         = 0;
553
 
554
        memcpy((unsigned char *)&c_Data, (unsigned char *)&s_WayPoint, sizeof(s_WayPoint));
555
        o_Input->send_Data(HandlerMK::make_Frame('s', ADDRESS_NC, c_Data, sizeof(s_WayPoint)).toLatin1().data());
556
    }
557
    else
558
    {
559
        QMessageBox::warning(this, QA_NAME,tr("Es wurden noch keine aktuellen Positionsdaten vom Mikrokopter empfangen."), QMessageBox::Ok);
560
    }
561
}
562
 
563
//Waypoint-Liste zum MK senden
564
void dlg_Main::send_WayPoints(QList<sWayPoint> t_WayPoints, int t_Pos)
565
{
566
    s_MK_WayPoint s_WayPoint;
567
    double Longitude, Latitude;
568
 
569
    if (t_Pos == 0)
570
    {   // Waypoint-Liste löschen
571
        s_WayPoint.Position.Status = INVALID;
572
 
573
        memcpy((unsigned char *)&c_Data, (unsigned char *)&s_WayPoint, sizeof(s_WayPoint));
574
        o_Input->send_Data(HandlerMK::make_Frame('w', ADDRESS_NC, c_Data, sizeof(s_WayPoint)).toLatin1().data(), DATA_WRITE_WAYPOINT);
575
    }
576
    else
577
    {
578
        int z = t_Pos - 1;
579
        Longitude = t_WayPoints[z].Longitude;
580
        Latitude  = t_WayPoints[z].Latitude;
581
 
582
        if (Longitude < 100)
583
            Longitude *= 10000000+0.5;
584
 
585
        if (Latitude < 100)
586
            Latitude *= 10000000+0.5;
587
 
588
        //fülle Wegpunkt-Daten
589
        s_WayPoint.Position.Altitude = 0;
590
        s_WayPoint.Position.Longitude = int32_t(Longitude);
591
        s_WayPoint.Position.Latitude =  int32_t(Latitude);
592
        s_WayPoint.Position.Status = NEWDATA;
593
        s_WayPoint.Heading = -1;
594
        s_WayPoint.ToleranceRadius = 5;
595
        s_WayPoint.HoldTime = t_WayPoints[z].Time;
596
        s_WayPoint.Event_Flag = 0;
597
        s_WayPoint.reserve[0] = 0; // reserve
598
        s_WayPoint.reserve[1] = 0; // reserve
599
        s_WayPoint.reserve[2] = 0; // reserve
600
        s_WayPoint.reserve[3] = 0; // reserve
601
 
602
        memcpy((unsigned char *)&c_Data, (unsigned char *)&s_WayPoint, sizeof(s_WayPoint));
603
        o_Input->send_Data(HandlerMK::make_Frame('w', ADDRESS_NC, c_Data, sizeof(s_WayPoint)).toLatin1().data(), DATA_WRITE_WAYPOINT);
604
    }
605
}
606
 
607
///////////
608
// Slots //
609
///////////
610
 
611
// About-Dialog
612
void dlg_Main::slot_ac_About()
613
{
614
    QMessageBox::about(this, trUtf8(("Über ")) + QA_NAME, QA_ABOUT);
615
}
616
 
617
void dlg_Main::slot_ac_Toolbar()
618
{
619
    if (ac_Toolbar->isChecked())
620
    {
621
        btn_Connect->setVisible(false);
622
        ToolBar->setVisible(true);
623
        tb_More->setVisible(true);
624
    }
625
    else
626
    {
627
        btn_Connect->setVisible(true);
628
        ToolBar->setVisible(false);
629
        tb_More->setVisible(false);
630
    }
631
}
632
 
633
 
634
// Datenintervall geändert.
635
void dlg_Main::slot_sb_Intervall(int t_Intervall)
636
{
637
    if (t_Intervall == 0)
638
    {
639
        c_Data[0] = 0;
640
    }
641
    else
642
    {
643
        c_Data[0] = t_Intervall / 10;
644
    }
645
    o_Input->send_Data(HandlerMK::make_Frame('o', ADDRESS_ALL, c_Data, 1).toLatin1().data());
646
}
647
 
648
// Verbindung zum Server auf    f_Settings = new wdg_Settings( this );bauen
649
void dlg_Main::slot_ac_Connect()
650
{
651
    if (!o_Input->IsOpen())
652
    {
653
        if (cb_Server->findText(cb_Server->currentText()) == -1)
654
        {
655
            cb_Server->addItem(cb_Server->currentText());
656
            cb_Server->setCurrentIndex(cb_Server->findText(cb_Server->currentText()));
657
        }
658
 
659
        cb_Server->setEnabled(false);
660
        le_Password->setEnabled(false);
661
 
662
        if (cb_Server->currentText().startsWith('/'))
663
        {
664
            o_Input = new Input_TTY();
665
            o_Input->Init();
666
 
667
            set_Input s_Input;
668
            s_Input.Main = cb_Server->currentText();
669
 
670
            if (o_Input->Open(s_Input) == true)
671
            {
672
                ac_Connect->setText(tr("Trennen"));
673
                connect(o_Input, SIGNAL(sig_NewData(QString)), this, SLOT(slot_Input_Data(QString)));
674
 
675
                o_Input->send_Data(HandlerMK::make_Frame('v', 0, c_Data, 0).toLatin1().data(), DATA_VERSION);
676
            }
677
            else
678
            {
679
                cb_Server->setEnabled(true);
680
                le_Password->setEnabled(true);
681
            }
682
 
683
        }
684
        else
685
        {
686
            o_Input = new Input_TCP();
687
            o_Input->Init();
688
 
689
            set_Input s_Input;
690
 
691
            QStringList Server = cb_Server->currentText().split(":");
692
 
693
            s_Input.Main = Server[0];
694
            s_Input.Sub  = Server[1];
695
 
696
            if (o_Input->Open(s_Input) == true)
697
            {
698
                connect(o_Input, SIGNAL(sig_Disconnected(int)), this, SLOT(slot_Input_Disconnected(int)));
699
                connect(o_Input, SIGNAL(sig_Connected()), this, SLOT(slot_Input_Connected()));
700
            }
701
        }
702
    }
703
    else
704
    {
705
        cb_Server->setEnabled(true);
706
        le_Password->setEnabled(true);
707
 
708
        ac_Connect->setText(tr("Verbinden"));
709
        o_Input->Close();
710
        disconnect(o_Input, SIGNAL(sig_NewData(QString)), 0, 0);
711
        if (o_Input->Mode() == TCP)
712
        {
713
            disconnect(o_Input, SIGNAL(sig_Disconnected(int)), 0, 0);
714
            disconnect(o_Input, SIGNAL(sig_Connected()), 0, 0);
715
        }
716
    }
717
}
718
 
719
// Neue Daten empfangen.
720
void dlg_Main::slot_Input_Data(QString t_Data)
721
{
722
    if ((t_Data[0] == '#'))
723
    {
724
        if ((HandlerMK::Check_CRC(t_Data.toLatin1().data(), t_Data.length() - 1)) || ((o_Input->Mode() == TTY) && (HandlerMK::Check_CRC(t_Data.toLatin1().data(), t_Data.length()))))
725
        {
726
            parse_MK_Data(t_Data);
727
        }
728
        else
729
        {
730
//            qDebug(QString("CRC-Error - " + t_Data).toLatin1().data());
731
        }
732
    }
733
    else if (o_Input->Mode() == TCP)
734
    {
735
            parse_IP_Data(t_Data);
736
    }
737
}
738
 
739
// Serververbindung beendet
740
void dlg_Main::slot_Input_Disconnected(int Error)
741
{
742
    cb_Server->setEnabled(true);
743
    le_Password->setEnabled(true);
744
 
745
//    qDebug("Close");
746
    disconnect(o_Input, SIGNAL(sig_NewData(QString)), 0, 0);
747
    if (o_Input->Mode() == TCP)
748
    {
749
        disconnect(o_Input, SIGNAL(sig_Disconnected(int)), 0, 0);
750
        disconnect(o_Input, SIGNAL(sig_Connected()), 0, 0);
751
    }
752
    ac_Connect->setChecked(false);
753
    ac_Connect->setText(tr("Verbinden"));
754
    btn_Connect->setChecked(false);
755
 
756
    switch (Error)
757
    {
758
        case REMOTECLOSED :
759
        {
760
//            lb_Status->setText(tr("Verbindung vom Server beendet."));
761
            QMessageBox::warning(this, QA_NAME,tr("QMK-Datenserver: Verbindung wurde vom Server beendet."), QMessageBox::Ok);
762
        }
763
        break;
764
        case REFUSED :
765
        {
766
//            lb_Status->setText(tr("Server nicht gefunden."));
767
            QMessageBox::warning(this, QA_NAME,tr("QMK-Datenserver: Kann nicht zum Server verbinden."), QMessageBox::Ok);
768
        }
769
        break;
770
        case 3 :
771
        {
772
//            lb_Status->setText(tr("Serververbindung getrennt. Logindaten falsch."));
773
            QMessageBox::warning(this, QA_NAME,tr("QMK-Datenserver: Loginname oder Password falsch."), QMessageBox::Ok);
774
        }
775
        break;
776
        default :
777
        {
778
//            lb_Status->setText(tr("Getrennt vom QMK-Datenserver."));
779
        }
780
        break;
781
    }
782
 
783
}
784
 
785
// Serververbindung hergestellt
786
void dlg_Main::slot_Input_Connected()
787
{
788
    connect(o_Input, SIGNAL(sig_NewData(QString)), this, SLOT(slot_Input_Data(QString)));
789
 
790
    o_Input->send_Data(HandlerIP::make_Frame(0, 101, QA_NAME + " " + QA_VERSION));
791
    o_Input->send_Data(HandlerMK::make_Frame('v', 0, c_Data, 0).toLatin1().data(), DATA_VERSION);
792
    ac_Connect->setText(tr("Trennen"));
793
}
794
 
795
///////////////////////////////////////////////////////////////////
796
// QMK-Maps                                                      //
797
///////////////////////////////////////////////////////////////////
798
 
799
// Zoom der Karte ändern
800
void dlg_Main::slot_Zoom(int t_Zoom)
801
{
802
    o_Map->setZoom(t_Zoom);
803
}
804
 
805
// Karte wechseln
806
void dlg_Main::slot_ChangeMap(int t_Set)
807
{
808
    int zoom = o_Adapter->adaptedZoom();
809
    QPointF a = o_Map->currentCoordinate();
810
 
811
    o_Map->setZoom(0);
812
 
813
    switch(t_Set)
814
    {
815
        case 0 : // OpenStreetMap
816
        {
817
            o_Adapter = new OSMMapAdapter();
818
        }
819
        break;
820
        case 1 : // Yahoo Sat
821
        {
822
            o_Adapter = new TileMapAdapter("tile.openaerialmap.org", "/tiles/1.0.0/openaerialmap-900913/%1/%2/%3.png", 256, 0, 17);
823
        }
824
        break;
825
        case 2 : // Google Maps
826
        {
827
            o_Adapter = new GoogleMapAdapter();
828
        }
829
        break;
830
        case 3 : // Google Sat
831
        {
832
            o_Adapter = new GoogleSatMapAdapter();
833
        }
834
        break;
835
        case 4 : // Yahoo Maps
836
        {
837
            o_Adapter = new YahooMapAdapter();
838
        }
839
        break;
840
        case 5 : // Yahoo Sat
841
        {
842
            o_Adapter = new YahooMapAdapter("us.maps3.yimg.com", "/aerial.maps.yimg.com/png?v=1.7&t=a&s=256&x=%2&y=%3&z=%1");
843
        }
844
        break;
845
    }
846
 
847
    o_Layer->setMapAdapter(o_Adapter);
848
    o_Click->setMapAdapter(o_Adapter);
849
    o_Info->setMapAdapter(o_Adapter);
850
    o_RouteWP->setMapAdapter(o_Adapter);
851
    o_RouteFL->setMapAdapter(o_Adapter);
852
 
853
    o_Map->updateRequestNew();
854
    o_Map->setZoom(zoom);
855
}
856
 
857
// Click in die Karte
858
void dlg_Main::slot_Click(const QMouseEvent* Event, const QPointF Coord)
859
{
860
    if ((Event->type() == QEvent::MouseButtonPress) && ((Event->button() == Qt::RightButton) || (Event->button() == Qt::MidButton)))
861
    {
862
        sl_Zoom->setValue(o_Adapter->adaptedZoom());
863
    }
864
 
865
    // Überwachen ob Karte verschoben wird
866
    if ((Event->type() == QEvent::MouseButtonPress) && (Event->button() == Qt::LeftButton))
867
    {
868
        MapCenter = o_Map->currentCoordinate();
869
    }
870
 
871
    // Nur wenn nicht Verschoben dann einen Punkt setzen
872
    if ((Event->type() == QEvent::MouseButtonRelease) && (Event->button() == Qt::LeftButton))
873
    {
874
        if (o_Map->currentCoordinate() == MapCenter)
875
        {
876
            if (l_WayPoints.count() < 20)
877
            {
878
                btn_WPAdd->setEnabled(true);
879
            }
880
 
881
            o_Click->removeGeometry(ClickPoint);
882
 
883
            ClickPoint = new CirclePoint(Coord.x(), Coord.y(), 6, "P1", Point::Middle, Pen[2]);
884
 
885
 
886
            LastClick = new Point(Coord.x(), Coord.y());
887
 
888
            ClickPoint->setBaselevel(o_Adapter->adaptedZoom());
889
            o_Click->addGeometry(ClickPoint);
890
 
891
//            o_Click->removeGeometry(Flag);
892
//            Flag = new ImagePoint(Coord.x(), Coord.y(), ":/Flags/Global/Images/Flags/Target.png", "Start");
893
//            Flag->setBaselevel(o_Adapter->adaptedZoom());
894
//            o_Click->addGeometry(Flag);
895
 
896
 
897
            if (cb_Goto->isChecked())
898
            {
899
                send_Target(LastClick);
900
            }
901
        }
902
    }
903
 
904
    o_Map->updateRequestNew();
905
//    qDebug(QString("%1").arg(Coord.x()).toLatin1().data());
906
//    qDebug(QString("%1").arg(Coord.y()).toLatin1().data());
907
}
908
 
909
// WayPoint zur Liste hinzufügen
910
void dlg_Main::slot_btn_WPAdd()
911
{
912
    cb_ShowWPs->setChecked(true);
913
 
914
    sWayPoint WayPoint;
915
 
916
    WayPoint.Longitude = LastClick->longitude();
917
    WayPoint.Latitude = LastClick->latitude();
918
    WayPoint.Time = sb_Time->value();
919
 
920
    l_WayPoints.append(WayPoint);
921
 
922
    o_RouteWP->removeGeometry(l_RouteWP);
923
 
924
    p_RouteWP.append(LastClick);
925
    l_RouteWP = new LineString(p_RouteWP, "", Pen[3]);
926
 
927
    o_RouteWP->addGeometry(l_RouteWP);
928
    o_Map->updateRequestNew();
929
 
930
    btn_WPFly->setEnabled(true);
931
 
932
    if (l_WayPoints.count() == 20)
933
    {
934
        QMessageBox::warning(this, QA_NAME,trUtf8("Wegpunkt-Liste ist voll. Es können maximal 20 Wegpunkte benutzt werden."), QMessageBox::Ok);
935
        btn_WPAdd->setEnabled(false);
936
    }
937
}
938
 
939
// WayPoint-Liste übertragen
940
void dlg_Main::slot_btn_WPFly()
941
{
942
    send_WayPoints(l_WayPoints, 0);
943
}
944
 
945
// WayPpoint-Liste löschen
946
void dlg_Main::slot_btn_WPDelete()
947
{
948
    p_RouteWP.clear();
949
    l_WayPoints.clear();
950
    o_RouteWP->clearGeometries();
951
    l_RouteWP = new LineString(p_RouteWP, "", Pen[0]);
952
//    o_RouteWP->addGeometry(l_RouteWP);
953
//    o_RouteWP->removeGeometry(l_RouteWP);
954
 
955
    o_Map->updateRequestNew();
956
 
957
    btn_WPFly->setEnabled(false);
958
    btn_WPAdd->setEnabled(true);
959
}
960
 
961
// WayPoint-Liste laden
962
void dlg_Main::slot_ac_LoadWayPoints()
963
{
964
    QString Filename = QFileDialog::getOpenFileName(this, "WayPoint-Route laden",  s_Dir.WPRoutes, "Mikrokopter WayPoints(*.mkw);;KML-Datei(*.kml);;Alle Dateien (*)");
965
 
966
    if (!Filename.isEmpty())
967
    {
968
        if (Filename.endsWith(".kml", Qt::CaseInsensitive))
969
        {
970
            cb_ShowWPs->setChecked(true);
971
            btn_WPFly->setEnabled(true);
972
 
973
            show_WayPoints(parse_WayPointKML(Filename));
974
        }
975
        if (Filename.endsWith(".mkw", Qt::CaseInsensitive))
976
        {
977
            cb_ShowWPs->setChecked(true);
978
            btn_WPFly->setEnabled(true);
979
 
980
            show_WayPoints(parse_WayPointMKW(Filename));
981
        }
982
    }
983
}
984
 
985
// WayPoint-Liste speichern
986
void dlg_Main::slot_ac_SaveRoute()
987
{
988
    QString Filename = QFileDialog::getSaveFileName(this, "WayPoint-Route speichern",  s_Dir.WPRoutes, "Mikrokopter WayPoints(*.mkw);;Alle Dateien (*)");
989
 
990
    if (!Filename.isEmpty())
991
    {
992
        if (!(Filename.endsWith(".mkw", Qt::CaseInsensitive)))
993
        {
994
            Filename = Filename + QString(".mkw");
995
        }
996
 
997
        save_WayPointsMKW(Filename);
998
    }
999
}
1000
 
1001
// Route anzeigen / ausblenden
1002
void dlg_Main::slot_ShowWayPoints(bool Show)
1003
{
1004
    if (Show == true)
1005
    {
1006
//        qDebug("Error 1");
1007
        if (l_RouteWP->hasPoints())
1008
        {
1009
//        qDebug("Error 2");
1010
            o_RouteWP->addGeometry(l_RouteWP);
1011
//        qDebug("Error 3");
1012
            o_Map->updateRequestNew();
1013
//        qDebug("Error 4");
1014
        }
1015
    }
1016
    else
1017
    {
1018
        o_RouteWP->removeGeometry(l_RouteWP);
1019
        o_Map->updateRequestNew();
1020
    }
1021
}
1022
 
1023
// Bilddatei als Karteladen.
1024
void dlg_Main::slot_ac_LoadMapPic()
1025
{
1026
    QString Filename = QFileDialog::getOpenFileName(this, "Bild als Karte",  s_Dir.MapPics, "Bilddatei(*.jpg *.png *.gif);;Alle Dateien (*)");
1027
 
1028
    if (!Filename.isEmpty())
1029
    {
1030
        QFile *f_Points = new QFile(Filename + ".pos");
1031
 
1032
        if (f_Points->exists())
1033
        {
1034
            f_Points->open(QIODevice::ReadOnly | QIODevice::Text);
1035
 
1036
            QString s_Points;
1037
 
1038
            while (!f_Points->atEnd())
1039
            {
1040
                s_Points.append(f_Points->readLine());
1041
            }
1042
 
1043
            f_Points->close();
1044
 
1045
            QStringList s_Pos = s_Points.split(",");
1046
 
1047
            FixedImageOverlay* fip = new FixedImageOverlay(s_Pos[0].toDouble(), s_Pos[1].toDouble(), s_Pos[2].toDouble(), s_Pos[3].toDouble(), Filename);
1048
 
1049
            o_Layer->addGeometry(fip);
1050
            o_Map->setView(QPointF(((s_Pos[0].toDouble() + s_Pos[2].toDouble()) / 2),((s_Pos[1].toDouble() + s_Pos[3].toDouble()) / 2)));
1051
 
1052
            o_Map->updateRequestNew();
1053
        }
1054
        else
1055
        {
1056
            dlg_MapPos *f_MapPos = new dlg_MapPos(this);
1057
 
1058
            if (f_MapPos->exec()==QDialog::Accepted)
1059
            {
1060
                QString Data = f_MapPos->get_Data();
1061
 
1062
                f_Points->open(QIODevice::ReadWrite | QIODevice::Text);
1063
 
1064
                QTextStream out(f_Points);
1065
 
1066
                out.setRealNumberPrecision(9);
1067
 
1068
                out << Data << "\n";
1069
 
1070
                f_Points->close();
1071
 
1072
                QStringList s_Pos = Data.split(",");
1073
 
1074
                FixedImageOverlay* fip = new FixedImageOverlay(s_Pos[0].toDouble(), s_Pos[1].toDouble(), s_Pos[2].toDouble(), s_Pos[3].toDouble(), Filename);
1075
 
1076
                o_Layer->addGeometry(fip);
1077
                o_Map->updateRequestNew();
1078
            }
1079
 
1080
        }
1081
    }
1082
}
1083
 
1084
// Flug als KML aufzeichnen
1085
void dlg_Main::slot_ac_Record()
1086
{
1087
    if (ac_Record->isChecked())
1088
    {
1089
        QString f_Name = s_Dir.Flights + "/" + QDate::currentDate().toString(("yyyy-MM-dd")) + "_" + QTime::currentTime().toString("hh-mm");
1090
 
1091
        ac_Record->setText(tr("Stoppen"));
1092
 
1093
        o_Record = new QFile(f_Name + ".kml");
1094
        o_Record->open(QIODevice::Append | QIODevice::Text);
1095
 
1096
        QTextStream Out(o_Record);
1097
        Out << HandlerKML::get_Header(tr("Mikrokopter Flugaufzeichnung")) << "\n";
1098
 
1099
    }
1100
    else
1101
    {
1102
        QTextStream Out(o_Record);
1103
        Out << HandlerKML::get_Footer() << "\n";
1104
        o_Record->close();
1105
        ac_Record->setText(tr("Aufzeichnen"));
1106
    }
1107
}
1108
 
1109
// WayPpoint-Liste löschen
1110
void dlg_Main::slot_ac_RouteDelete()
1111
{
1112
    p_RouteFL.clear();
1113
    l_Track.clear();
1114
    o_RouteFL->clearGeometries();
1115
    l_RouteFL = new LineString(p_RouteFL, "", Pen[0]);
1116
//    o_RouteFL->removeGeometry(l_RouteFL);
1117
 
1118
    o_Map->updateRequestNew();
1119
}
1120
 
1121
// Programm Ende
1122
dlg_Main::~dlg_Main()
1123
{
1124
    o_Settings->GUI.isMax       = isMaximized();
1125
    o_Settings->GUI.Size        = size();
1126
    o_Settings->GUI.Point       = pos();
1127
    o_Settings->GUI.Toolbar     = ac_Toolbar->isChecked();
1128
 
1129
    o_Settings->DATA.Intervall = sb_Intervall->value();
1130
 
1131
    o_Settings->SERVER.Password = le_Password->text();
1132
    o_Settings->SERVER.IP_MAX  = cb_Server->count();
1133
    o_Settings->SERVER.IP_ID   = cb_Server->currentIndex();
1134
 
1135
    for (int z = 0; z < cb_Server->count(); z++)
1136
    {
1137
        if (z < 10)
1138
        {
1139
            o_Settings->SERVER.IP[z] = cb_Server->itemText(z);
1140
        }
1141
    }
1142
 
1143
    o_Settings->CONFIG.cb_CenterPos = cb_CenterPos->isChecked();
1144
    o_Settings->CONFIG.cb_ShowRoute = cb_ShowRoute->isChecked();
1145
    o_Settings->CONFIG.cb_ShowWPs   = cb_ShowWPs->isChecked();
1146
    o_Settings->CONFIG.cb_Goto      = cb_Goto->isChecked();
1147
 
1148
    o_Settings->NAVI.StayTime = sb_Time->value();
1149
 
1150
    o_Settings->write_Settings();
1151
 
1152
//    qDebug("Ende.");
1153
}