Subversion Repositories Projects

Rev

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