Subversion Repositories Projects

Rev

Rev 674 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | RSS feed

/***************************************************************************
 *   Copyright (C) 2009 by Manuel Schrape                                  *
 *   manuel.schrape@gmx.de                                                 *
 *                                                                         *
 *   This program is free software; you can redistribute it and/or modify  *
 *   it under the terms of the GNU General Public License as published by  *
 *   the Free Software Foundation; either version 2 of the License.        *
 *                                                                         *
 *   This program is distributed in the hope that it will be useful,       *
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
 *   GNU General Public License for more details.                          *
 *                                                                         *
 *   You should have received a copy of the GNU General Public License     *
 *   along with this program; if not, write to the                         *
 *   Free Software Foundation, Inc.,                                       *
 *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
 ***************************************************************************/


#include <QCryptographicHash>
#include <QMessageBox>
#include <QDomDocument>
#include <QFile>

#include "dlg_Main.h"
#include "dlg_MapPos.h"

// Konstruktor Main-Form
dlg_Main::dlg_Main()
{
    setupUi(this);

    o_Settings = new cSettings();

    o_Input = new Input();

    o_Map = new MapControl(QSize(25,25));
    l_RouteWP = new LineString();
    init_Directorys();
    init_GUI();
    init_Connections();
}

// Grafische Oberfläche initialisieren
void dlg_Main::init_GUI()
{
    setWindowTitle(QA_NAME + " " + QA_VERSION);

    resize(o_Settings->GUI.Size);
    move(o_Settings->GUI.Point);

    if (o_Settings->GUI.isMax)
    {
        showMaximized();
    }

    for(int z = 0; z < o_Settings->SERVER.IP_MAX; z++)
    {
        if (cb_Server->findText(o_Settings->SERVER.IP[z]) == -1)
        {
            cb_Server->addItem(o_Settings->SERVER.IP[z]);
        }
    }

    cb_Server->setCurrentIndex(o_Settings->SERVER.IP_ID);

    le_Password->setText(o_Settings->SERVER.Password);

    sb_Intervall->setValue(o_Settings->DATA.Intervall);

    cb_CenterPos->setChecked(o_Settings->CONFIG.cb_CenterPos);
    cb_ShowRoute->setChecked(o_Settings->CONFIG.cb_ShowRoute);
    cb_ShowWPs->setChecked(o_Settings->CONFIG.cb_ShowWPs);
    cb_Goto->setChecked(o_Settings->CONFIG.cb_Goto);

//    tb_More->addWidget(cb_Maps);
    cb_Maps->setVisible(false);

    ac_Toolbar->setChecked(o_Settings->GUI.Toolbar);

    if (ac_Toolbar->isChecked())
    {
        btn_Connect->setVisible(false);
    }
    else
    {
        ToolBar->setVisible(false);
        tb_More->setVisible(false);
    }
}

// Signale mit Slots verbinden
void dlg_Main::init_Connections()
{
    connect(ac_Connect, SIGNAL(triggered()), this, SLOT(slot_ac_Connect()));
    connect(ac_Toolbar, SIGNAL(triggered()), this, SLOT(slot_ac_Toolbar()));

    connect(sb_Intervall, SIGNAL(valueChanged(int)), this, SLOT(slot_sb_Intervall(int)));

    connect(sl_Zoom,   SIGNAL(valueChanged(int)), this, SLOT(slot_Zoom(int)));
    connect(cb_Maps,   SIGNAL(currentIndexChanged(int)), this, SLOT(slot_ChangeMap(int)));

    connect(cb_ShowWPs, SIGNAL(toggled(bool)), this, SLOT(slot_ShowWayPoints(bool)));

    connect(btn_WPAdd,    SIGNAL(clicked()), this, SLOT(slot_btn_WPAdd()));
    connect(btn_WPFly,    SIGNAL(clicked()), this, SLOT(slot_btn_WPFly()));
    connect(btn_WPDelete, SIGNAL(clicked()), this, SLOT(slot_btn_WPDelete()));

    connect(ac_LoadRoute, SIGNAL(triggered()), this, SLOT(slot_ac_LoadWayPoints()));
    connect(ac_SaveRoute, SIGNAL(triggered()), this, SLOT(slot_ac_SaveRoute()));

    connect(ac_LoadMap,     SIGNAL(triggered()), this, SLOT(slot_ac_LoadMapPic()));
    connect(ac_Record,      SIGNAL(triggered()), this, SLOT(slot_ac_Record()));
    connect(ac_RouteDelete, SIGNAL(triggered()), this, SLOT(slot_ac_RouteDelete()));

    // About QMK-Kernel & About-QT Dialog einfügen
    connect(ac_About, SIGNAL(triggered()), this, SLOT(slot_ac_About()));
    menu_Help->addAction(trUtf8("Über &Qt"), qApp, SLOT(aboutQt()));
}

void dlg_Main::init_Directorys()
{
    QDir *t_Dir = new QDir();

    s_Dir.MainData = QDir::homePath() + "/QMK-Data";
    if (!t_Dir->exists(s_Dir.MainData))
    {
        t_Dir->mkdir(s_Dir.MainData);
    }

    s_Dir.MapCache = s_Dir.MainData + "/Map-Cache";
    if (!t_Dir->exists(s_Dir.MapCache))
    {
        t_Dir->mkdir(s_Dir.MapCache);
    }

    s_Dir.WPRoutes = s_Dir.MainData + "/WP-Routes";
    if (!t_Dir->exists(s_Dir.WPRoutes))
    {
        t_Dir->mkdir(s_Dir.WPRoutes);
    }

    s_Dir.MapPics = s_Dir.MainData + "/Map-Pics";
    if (!t_Dir->exists(s_Dir.MapPics))
    {
        t_Dir->mkdir(s_Dir.MapPics);
    }

    s_Dir.Flights = s_Dir.MainData + "/Flights";
    if (!t_Dir->exists(s_Dir.Flights))
    {
        t_Dir->mkdir(s_Dir.Flights);
    }
}

void dlg_Main::parse_IP_Data(QString t_Data)
{
    QStringList Data;
    Data = t_Data.split(":");

    if (Data.count() > 1)
    {
        int CMD = Data[2].toInt();

        switch(CMD)
        {
            case 101 :
            {
                o_Input->send_Data(HandlerIP::make_Frame(ID_MAPS, 101, QA_NAME + " " + QA_VERSION));
            }
            break;
            case 502 :
            {
                switch (Data[3].toInt())
                {
                    case 105 :
                    {
                        QString s_MD5PW;
                        QByteArray a_MD5PW;

                        a_MD5PW = QCryptographicHash::hash(le_Password->text().toAscii(),QCryptographicHash::Md5);

                        s_MD5PW = QString(a_MD5PW.toHex().data());

                        o_Input->send_Data(HandlerIP::make_Frame(ID_MAPS, 105, s_MD5PW));
                    }
                    break;
                    case 106 :
                    {
                        o_Input->send_Data(HandlerIP::make_Frame(ID_MAPS, 106, DataFields));
                    }
                    break;
                }
            }
            break;
            case 505 :
            {
                if (Data[3] == "OK")
                {
                }
                else
                {
                    QMessageBox::warning(this, QA_NAME, trUtf8("Authentifizierung fehlgeschlagen. <br />Daten senden zum Mikrokopter nicht möglich."), QMessageBox::Ok);
                }
            }
            break;
        }
    }
}

// Eingangsdaten verarbeiten
void dlg_Main::parse_MK_Data(QString t_Data)
{
    unsigned char OutData[150];
    char *InData = t_Data.toLatin1().data();

    if (HandlerMK::Decode_64(InData, t_Data.length(), OutData) != 0)
    {

        switch(InData[2])
        {
            case 'V' : // Versions-Info
                {
                    o_Input->stop_Resend(DATA_VERSION);
                    VersionInfo = HandlerMK::parse_Version(OutData, InData[1] - 'a');
                    setWindowTitle(QA_NAME + " " + QA_VERSION + " - " + VersionInfo.Hardware + " " + VersionInfo.Version);

                    if (VersionInfo.ID == ADDRESS_NC)
                    {
                        c_Data[0] = sb_Intervall->value() / 10;
                        o_Input->send_Data(HandlerMK::make_Frame('o', ADDRESS_ALL, c_Data, 1).toLatin1().data());
                    }
                    else // TODO: Befehl wenden zum Wechseln auf Navi.
                    {
                    }
                }
            break;
            case 'O' : // Navi-OSD-Data
                {
                    if (InData[1] - 'a' == ADDRESS_NC)
                    {
                        s_MK_NaviData MK_NaviData;

                        memcpy((unsigned char *)&MK_NaviData, (unsigned char *)&OutData, sizeof(MK_NaviData));
                        if (MK_NaviData.Version == MK_VERSION_NAVI)
                        {
                            show_Data(MK_NaviData);
                            add_Position(MK_NaviData);
                        }
                    }
                }
            break;
            case 'W' : // WayPoints
                {
                    o_Input->stop_Resend(DATA_WRITE_WAYPOINT);

                    if (OutData[0] < l_WayPoints.count())
                    {
                        send_WayPoints(l_WayPoints, OutData[0] + 1);
                    }
                }
            break;
        }
    }
}

///////////////////////////////////////////////////////////////////
// QMK-Maps                                                      //
///////////////////////////////////////////////////////////////////

void dlg_Main::create_Map()
{
    o_Map->resize(w_Map->size() - QSize(25,50));
    o_Map->enablePersistentCache(s_Dir.MapCache);
    o_Map->showScale(true);

    o_Adapter = new OSMMapAdapter();

    o_Layer   = new MapLayer("MapLayer", o_Adapter);
    o_Click   = new GeometryLayer("Click", o_Adapter);
    o_Info    = new GeometryLayer("Poute", o_Adapter);
    o_RouteWP = new GeometryLayer("Route-WayPoint", o_Adapter);
    o_RouteFL = new GeometryLayer("Route-Flight", o_Adapter);

    o_Map->addLayer(o_Layer);
    o_Map->addLayer(o_Click);
    o_Map->addLayer(o_Info);
    o_Map->addLayer(o_RouteWP);
    o_Map->addLayer(o_RouteFL);

    o_Map->setZoom(17);
//    o_Map->setView(QPointF(o_Settings->NAVI.Longitude,o_Settings->NAVI.Latitude));
//    o_Map->setView(QPointF(13.5,52.5));
    o_Map->setView(QPointF(13.419805,52.431787));
    connect(o_Map, SIGNAL(mouseEventCoordinate(const QMouseEvent*, const QPointF)), this, SLOT(slot_Click(const QMouseEvent*, const QPointF)));

    l_Map->addWidget(o_Map);

    sl_Zoom->setValue(17);

    // Flight
    Pen[0] = new QPen(QColor(0,0,255,255));
    Pen[0]->setWidth(2);
    Pen[1] = new QPen(QColor(0,0,255,255));
    Pen[1]->setWidth(1);
    // WayPoint
    Pen[2] = new QPen(QColor(255,0,0,255));
    Pen[2]->setWidth(2);
    Pen[3] = new QPen(QColor(255,0,0,255));
    Pen[3]->setWidth(1);
    // Info
    Pen[4] = new QPen(QColor(0,128,128,255));
    Pen[4]->setWidth(2);
    Pen[5] = new QPen(QColor(0,128,128,255));
    Pen[5]->setWidth(1);
}

// auf Veränderung der Fenstergröße reagieren
void dlg_Main::resizeEvent ( QResizeEvent * event )
{
    event = event;
    o_Map->resize(w_Map->size() - QSize(25,25));
}

void dlg_Main::wheelEvent(QWheelEvent *event)
{
    int zoomValue = sl_Zoom->value();
    int numDegrees = event->delta() / 8;
    int numSteps = numDegrees / 15;
    zoomValue += numSteps;
    if (zoomValue < 0) { zoomValue = 0;}
    if (zoomValue > 17) { zoomValue = 17;}
    sl_Zoom->setValue(zoomValue);
}

QList<sWayPoint> dlg_Main::parse_WayPointKML(QString s_File)
{
    QList<sWayPoint> tmp_WayPoints;
    sWayPoint tmp_WayPoint;

    QFile f_KML(s_File);
    f_KML.open(QIODevice::ReadOnly | QIODevice::Text);

    QByteArray s_KML;

    while (!f_KML.atEnd())
    {
        s_KML.append(f_KML.readLine());
     }

    f_KML.close();

    QDomDocument *UserXML;
    UserXML = new QDomDocument;

    UserXML->setContent(s_KML);

    QDomElement Root       = UserXML->firstChildElement("kml");
    QDomElement Document   = Root.firstChildElement("Document");
    QDomElement Placemark  = Document.firstChildElement("Placemark");
    QDomElement Linestring = Placemark.firstChildElement("LineString");

    QString Name = Placemark.firstChildElement("name").toElement().text();

    QString Route = Linestring.firstChildElement("coordinates").toElement().text();

    QStringList s_Points = Route.split(" ");

    QStringList Position;

    for (int z = 0; z < s_Points.count() - 1; z++)
    {
        if (z != 20)
        {
           Position = s_Points[z].split(",");
           tmp_WayPoint.Longitude = Position[0].toDouble();
           tmp_WayPoint.Latitude  = Position[1].toDouble();
           tmp_WayPoint.Altitude  = Position[2].toDouble();
           tmp_WayPoint.Time      = sb_Time->value();

           tmp_WayPoints.append(tmp_WayPoint);
        }
        else
        {
            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);

            btn_WPAdd->setEnabled(false);

            z = s_Points.count();
        }
    }
    return tmp_WayPoints;
}

QList<sWayPoint> dlg_Main::parse_WayPointMKW(QString s_File)
{
    QList<sWayPoint> tmp_WayPoints;
    sWayPoint tmp_WayPoint;

    QFile f_MKW(s_File);
    f_MKW.open(QIODevice::ReadOnly | QIODevice::Text);

    QString s_MKW;

    while (!f_MKW.atEnd())
    {
        s_MKW.append(f_MKW.readLine());
     }

    f_MKW.close();

    QStringList s_Points = s_MKW.split(" ");

    QStringList Position;

    for (int z = 0; z < s_Points.count() - 1; z++)
    {
        if (z != 20)
        {
           Position = s_Points[z].split(",");
           tmp_WayPoint.Longitude = Position[0].toDouble();
           tmp_WayPoint.Latitude  = Position[1].toDouble();
           tmp_WayPoint.Altitude  = Position[2].toDouble();
           tmp_WayPoint.Time      = Position[3].toInt();

           tmp_WayPoints.append(tmp_WayPoint);
        }
        else
        {
            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);

            btn_WPAdd->setEnabled(false);

            z = s_Points.count();
        }
    }
    return tmp_WayPoints;
}

// Waypoint-Route anzeigen in Karte
void dlg_Main::show_WayPoints(QList<sWayPoint> WayPoints)
{
    Point* p_Point;

    o_RouteWP->removeGeometry(l_RouteWP);
    p_RouteWP.clear();
    l_WayPoints.clear();

    l_WayPoints = WayPoints;

    for (int z = 0; z < WayPoints.count(); z++)
    {
        p_Point = new Point(WayPoints[z].Longitude, WayPoints[z].Latitude);

        p_RouteWP.append(p_Point);
    }

    l_RouteWP = new LineString(p_RouteWP, "", Pen[3]);
    o_RouteWP->addGeometry(l_RouteWP);

    o_Map->setView(p_Point);

    o_Map->updateRequestNew();
}

// Waypoint-Liste speichern
void dlg_Main::save_WayPointsMKW(QString s_File)
{
    QFile *f_MKW = new QFile(s_File);

    f_MKW->open(QIODevice::ReadWrite | QIODevice::Text);

    QTextStream out(f_MKW);

    out.setRealNumberPrecision(9);

    for (int z = 0; z < l_WayPoints.count(); z++)
    {
        out << l_WayPoints[z].Longitude << "," << l_WayPoints[z].Latitude << "," << l_WayPoints[z].Altitude << "," << l_WayPoints[z].Time << " \n";
    }

    f_MKW->close();
}

void dlg_Main::show_Data(s_MK_NaviData t_NaviData)
{
    QString Mode = "NC-Flags : ";
    if (t_NaviData.NCFlags &  0x08) {le_Mode->setText(tr("Range Limit")); Mode += "R";}
    if (t_NaviData.NCFlags &  0x10) {le_Mode->setText(tr("Serial Error")); Mode += "S";}
    if (t_NaviData.NCFlags &  0x20) {le_Mode->setText(tr("Target reached")); Mode += "T";}
    if (t_NaviData.NCFlags &  0x40) {le_Mode->setText(tr("Manual Control")); Mode += "M";}
    if (t_NaviData.NCFlags &  0x01) {le_Mode->setText(tr("Free")); Mode += "F";}
    if (t_NaviData.NCFlags &  0x02) {le_Mode->setText(tr("Position Hold")); Mode += "P";}
    if (t_NaviData.NCFlags &  0x04) {le_Mode->setText(tr("Coming Home")); Mode += "C";}

    //qDebug(Mode.toLatin1().data());

    le_WP->setText(QString("%1/").arg(t_NaviData.WaypointIndex) + QString("%1").arg(t_NaviData.WaypointNumber));
    le_WPTime->setText(QString("%1:").arg(t_NaviData.TargetHoldTime / 60) + (QString("%1").arg(t_NaviData.TargetHoldTime % 60)).rightJustified(2, '0'));
    le_WPDist->setText(QString("%1m").arg(t_NaviData.TargetPositionDeviation.Distance / 10));
    le_HomeDist->setText(QString("%1m").arg(t_NaviData.HomePositionDeviation.Distance / 10));
}

// Aktuelle MK-Position hinzufügen
void dlg_Main::add_Position(s_MK_NaviData t_NaviData)
{
    sWayPoint WayPoint;

    WayPoint.Longitude = HandlerMK::Int2Double(t_NaviData.CurrentPosition.Longitude, 7);
    WayPoint.Latitude = HandlerMK::Int2Double(t_NaviData.CurrentPosition.Latitude, 7);
    WayPoint.Altitude = HandlerMK::Int2Double(t_NaviData.CurrentPosition.Altitude, 3);

    o_Settings->NAVI.Latitude  = WayPoint.Latitude;
    o_Settings->NAVI.Longitude = WayPoint.Longitude;

    l_Track.append(WayPoint);

    o_RouteFL->removeGeometry(l_RouteFL);
    p_RouteFL.append(new Point(WayPoint.Longitude, WayPoint.Latitude));

    o_Click->removeGeometry(LastPos);

    Point* P = new CirclePoint(WayPoint.Longitude, WayPoint.Latitude, "P1", Point::Middle, Pen[0]);
    LastPos = P;
//    P->setBaselevel(17);
    o_Click->addGeometry(P);

    // Target anzeigen
    o_Click->removeGeometry(Target);

    Target = new ImagePoint( HandlerMK::Int2Double(t_NaviData.TargetPosition.Longitude, 7), HandlerMK::Int2Double(t_NaviData.TargetPosition.Latitude, 7), ":/Flags/Global/Images/Flags/Target.png", "Start");
    Target->setBaselevel(o_Adapter->adaptedZoom());
    o_Click->addGeometry(Target);

    if (cb_CenterPos->isChecked())
    {
        o_Map->setView(QPointF(WayPoint.Longitude, WayPoint.Latitude));
    }

    if (cb_ShowRoute->isChecked())
    {
        l_RouteFL = new LineString(p_RouteFL, "", Pen[1]);

        o_RouteFL->addGeometry(l_RouteFL);
    }
    o_Map->updateRequestNew();

    if (ac_Record->isChecked())
    {
        QTextStream Out(o_Record);

        Out.setRealNumberPrecision(9);

        Out << WayPoint.Longitude << ", " << WayPoint.Latitude << ", " << WayPoint.Altitude << "\n";
    }
}

// Ein Ziel anfliegen.
// TODO: Check auf  Entfernung zur IST-Position.
void dlg_Main::send_Target(Point *t_Target)
{
    if (l_Track.count() > 0)
    {
        s_MK_WayPoint s_WayPoint;

        s_WayPoint.Position.Latitude  = int32_t(t_Target->latitude() * 10000000+0.5);
        s_WayPoint.Position.Longitude = int32_t(t_Target->longitude() * 10000000+0.5);
        s_WayPoint.Position.Altitude  = 0;
        s_WayPoint.Position.Status    = NEWDATA;
        s_WayPoint.Heading            = -1;
        s_WayPoint.ToleranceRadius    = 5;
        s_WayPoint.HoldTime           = sb_Time->value();
        s_WayPoint.Event_Flag         = 0;
        s_WayPoint.reserve[0]         = 0; // reserve
        s_WayPoint.reserve[1]         = 0; // reserve
        s_WayPoint.reserve[2]         = 0; // reserve
        s_WayPoint.reserve[3]         = 0;

        memcpy((unsigned char *)&c_Data, (unsigned char *)&s_WayPoint, sizeof(s_WayPoint));
        o_Input->send_Data(HandlerMK::make_Frame('s', ADDRESS_NC, c_Data, sizeof(s_WayPoint)).toLatin1().data());
    }
    else
    {
        QMessageBox::warning(this, QA_NAME,tr("Es wurden noch keine aktuellen Positionsdaten vom Mikrokopter empfangen."), QMessageBox::Ok);
    }
}

//Waypoint-Liste zum MK senden
void dlg_Main::send_WayPoints(QList<sWayPoint> t_WayPoints, int t_Pos)
{
    s_MK_WayPoint s_WayPoint;
    double Longitude, Latitude;

    if (t_Pos == 0)
    {   // Waypoint-Liste löschen
        s_WayPoint.Position.Status = INVALID;

        memcpy((unsigned char *)&c_Data, (unsigned char *)&s_WayPoint, sizeof(s_WayPoint));
        o_Input->send_Data(HandlerMK::make_Frame('w', ADDRESS_NC, c_Data, sizeof(s_WayPoint)).toLatin1().data(), DATA_WRITE_WAYPOINT);
    }
    else
    {
        int z = t_Pos - 1;
        Longitude = t_WayPoints[z].Longitude;
        Latitude  = t_WayPoints[z].Latitude;

        if (Longitude < 100)
            Longitude *= 10000000+0.5;

        if (Latitude < 100)
            Latitude *= 10000000+0.5;

        //fülle Wegpunkt-Daten
        s_WayPoint.Position.Altitude = 0;
        s_WayPoint.Position.Longitude = int32_t(Longitude);
        s_WayPoint.Position.Latitude =  int32_t(Latitude);
        s_WayPoint.Position.Status = NEWDATA;
        s_WayPoint.Heading = -1;
        s_WayPoint.ToleranceRadius = 5;
        s_WayPoint.HoldTime = t_WayPoints[z].Time;
        s_WayPoint.Event_Flag = 0;
        s_WayPoint.reserve[0] = 0; // reserve
        s_WayPoint.reserve[1] = 0; // reserve
        s_WayPoint.reserve[2] = 0; // reserve
        s_WayPoint.reserve[3] = 0; // reserve

        memcpy((unsigned char *)&c_Data, (unsigned char *)&s_WayPoint, sizeof(s_WayPoint));
        o_Input->send_Data(HandlerMK::make_Frame('w', ADDRESS_NC, c_Data, sizeof(s_WayPoint)).toLatin1().data(), DATA_WRITE_WAYPOINT);
    }
}

///////////
// Slots //
///////////

// About-Dialog
void dlg_Main::slot_ac_About()
{
    QMessageBox::about(this, trUtf8(("Über ")) + QA_NAME, QA_ABOUT);
}

void dlg_Main::slot_ac_Toolbar()
{
    if (ac_Toolbar->isChecked())
    {
        btn_Connect->setVisible(false);
        ToolBar->setVisible(true);
        tb_More->setVisible(true);
    }
    else
    {
        btn_Connect->setVisible(true);
        ToolBar->setVisible(false);
        tb_More->setVisible(false);
    }
}


// Datenintervall geändert.
void dlg_Main::slot_sb_Intervall(int t_Intervall)
{
    if (t_Intervall == 0)
    {
        c_Data[0] = 0;
    }
    else
    {
        c_Data[0] = t_Intervall / 10;
    }
    o_Input->send_Data(HandlerMK::make_Frame('o', ADDRESS_ALL, c_Data, 1).toLatin1().data());
}

// Verbindung zum Server auf    f_Settings = new wdg_Settings( this );bauen
void dlg_Main::slot_ac_Connect()
{
    if (!o_Input->IsOpen())
    {
        if (cb_Server->findText(cb_Server->currentText()) == -1)
        {
            cb_Server->addItem(cb_Server->currentText());
            cb_Server->setCurrentIndex(cb_Server->findText(cb_Server->currentText()));
        }

        cb_Server->setEnabled(false);
        le_Password->setEnabled(false);

        if (cb_Server->currentText().startsWith('/'))
        {
            o_Input = new Input_TTY();
            o_Input->Init();

            set_Input s_Input;
            s_Input.Main = cb_Server->currentText();

            if (o_Input->Open(s_Input) == true)
            {
                ac_Connect->setText(tr("Trennen"));
                connect(o_Input, SIGNAL(sig_NewData(QString)), this, SLOT(slot_Input_Data(QString)));

                o_Input->send_Data(HandlerMK::make_Frame('v', 0, c_Data, 0).toLatin1().data(), DATA_VERSION);
            }
            else
            {
                cb_Server->setEnabled(true);
                le_Password->setEnabled(true);
            }

        }
        else //  Connect über TCPIP
        {
            o_Input = new Input_TCP();
            o_Input->Init();

            set_Input s_Input;

            QStringList Server = cb_Server->currentText().split(":");

            s_Input.Main = Server[0];
            s_Input.Sub  = Server[1];

            if (o_Input->Open(s_Input) == true)
            {
                connect(o_Input, SIGNAL(sig_Disconnected(int)), this, SLOT(slot_Input_Disconnected(int)));
                connect(o_Input, SIGNAL(sig_Connected()), this, SLOT(slot_Input_Connected()));
            }
        }
    }
    else
    {
        cb_Server->setEnabled(true);
        le_Password->setEnabled(true);

        ac_Connect->setText(tr("Verbinden"));
        o_Input->Close();
        disconnect(o_Input, SIGNAL(sig_NewData(QString)), 0, 0);
        if (o_Input->Mode() == TCP)
        {
            disconnect(o_Input, SIGNAL(sig_Disconnected(int)), 0, 0);
            disconnect(o_Input, SIGNAL(sig_Connected()), 0, 0);
        }
    }
}

// Neue Daten empfangen.
void dlg_Main::slot_Input_Data(QString t_Data)
{
    if ((t_Data[0] == '#'))
    {
        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()))))
        {
            parse_MK_Data(t_Data);
        }
        else
        {
//            qDebug(QString("CRC-Error - " + t_Data).toLatin1().data());
        }
    }
    else if ((o_Input->Mode() == TCP) && (t_Data[0] == '$'))
    {
            parse_IP_Data(t_Data);
    }
}

// Serververbindung beendet
void dlg_Main::slot_Input_Disconnected(int Error)
{
    cb_Server->setEnabled(true);
    le_Password->setEnabled(true);

    disconnect(o_Input, SIGNAL(sig_NewData(QString)), 0, 0);
    disconnect(o_Input, SIGNAL(sig_Disconnected(int)), 0, 0);
    disconnect(o_Input, SIGNAL(sig_Connected()), 0, 0);

    ac_Connect->setChecked(false);
    ac_Connect->setText(tr("Verbinden"));
    btn_Connect->setChecked(false);

    switch (Error)
    {
        case REMOTECLOSED :
        {
//            lb_Status->setText(tr("Verbindung vom Server beendet."));
            QMessageBox::warning(this, QA_NAME,tr("QMK-Datenserver: Verbindung wurde vom Server beendet."), QMessageBox::Ok);
        }
        break;
        case REFUSED :
        {
//            lb_Status->setText(tr("Server nicht gefunden."));
            QMessageBox::warning(this, QA_NAME,tr("QMK-Datenserver: Kann nicht zum Server verbinden."), QMessageBox::Ok);
        }
        break;
        case 3 :
        {
//            lb_Status->setText(tr("Serververbindung getrennt. Logindaten falsch."));
            QMessageBox::warning(this, QA_NAME,tr("QMK-Datenserver: Loginname oder Password falsch."), QMessageBox::Ok);
        }
        break;
        default :
        {
//            lb_Status->setText(tr("Getrennt vom QMK-Datenserver."));
        }
        break;
    }

}

// Serververbindung hergestellt
void dlg_Main::slot_Input_Connected()
{
    connect(o_Input, SIGNAL(sig_NewData(QString)), this, SLOT(slot_Input_Data(QString)));

    o_Input->send_Data(HandlerMK::make_Frame('v', 0, c_Data, 0).toLatin1().data(), DATA_VERSION);
    ac_Connect->setText(tr("Trennen"));
}

///////////////////////////////////////////////////////////////////
// QMK-Maps                                                      //
///////////////////////////////////////////////////////////////////

// Zoom der Karte ändern
void dlg_Main::slot_Zoom(int t_Zoom)
{
    o_Map->setZoom(t_Zoom);
}

// Karte wechseln
void dlg_Main::slot_ChangeMap(int t_Set)
{
    int zoom = o_Adapter->adaptedZoom();
    QPointF a = o_Map->currentCoordinate();

    o_Map->setZoom(0);

    switch(t_Set)
    {
        case 0 : // OpenStreetMap
        {
            o_Adapter = new OSMMapAdapter();
        }
        break;
        case 1 : // Yahoo Sat
        {
            o_Adapter = new TileMapAdapter("tile.openaerialmap.org", "/tiles/1.0.0/openaerialmap-900913/%1/%2/%3.png", 256, 0, 17);
        }
        break;
        case 2 : // Google Maps
        {
            o_Adapter = new GoogleMapAdapter();
        }
        break;
        case 3 : // Google Sat
        {
            o_Adapter = new GoogleSatMapAdapter();
        }
        break;
        case 4 : // Yahoo Maps
        {
            o_Adapter = new YahooMapAdapter();
        }
        break;
        case 5 : // Yahoo Sat
        {
            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");
        }
        break;
    }

    o_Layer->setMapAdapter(o_Adapter);
    o_Click->setMapAdapter(o_Adapter);
    o_Info->setMapAdapter(o_Adapter);
    o_RouteWP->setMapAdapter(o_Adapter);
    o_RouteFL->setMapAdapter(o_Adapter);

    o_Map->updateRequestNew();
    o_Map->setZoom(zoom);
}

// Click in die Karte
void dlg_Main::slot_Click(const QMouseEvent* Event, const QPointF Coord)
{
    if ((Event->type() == QEvent::MouseButtonPress) && ((Event->button() == Qt::RightButton) || (Event->button() == Qt::MidButton)))
    {
        sl_Zoom->setValue(o_Adapter->adaptedZoom());
    }

    // Überwachen ob Karte verschoben wird
    if ((Event->type() == QEvent::MouseButtonPress) && (Event->button() == Qt::LeftButton))
    {
        MapCenter = o_Map->currentCoordinate();
    }

    // Nur wenn nicht Verschoben dann einen Punkt setzen
    if ((Event->type() == QEvent::MouseButtonRelease) && (Event->button() == Qt::LeftButton))
    {
        if (o_Map->currentCoordinate() == MapCenter)
        {
            if (l_WayPoints.count() < 20)
            {
                btn_WPAdd->setEnabled(true);
            }

            o_Click->removeGeometry(ClickPoint);

            ClickPoint = new CirclePoint(Coord.x(), Coord.y(), 6, "P1", Point::Middle, Pen[2]);


            LastClick = new Point(Coord.x(), Coord.y());

            ClickPoint->setBaselevel(o_Adapter->adaptedZoom());
            o_Click->addGeometry(ClickPoint);

//            o_Click->removeGeometry(Flag);
//            Flag = new ImagePoint(Coord.x(), Coord.y(), ":/Flags/Global/Images/Flags/Target.png", "Start");
//            Flag->setBaselevel(o_Adapter->adaptedZoom());
//            o_Click->addGeometry(Flag);


            if (cb_Goto->isChecked())
            {
                send_Target(LastClick);
            }
        }
    }

    o_Map->updateRequestNew();
//    qDebug(QString("%1").arg(Coord.x()).toLatin1().data());
//    qDebug(QString("%1").arg(Coord.y()).toLatin1().data());
}

// WayPoint zur Liste hinzufügen
void dlg_Main::slot_btn_WPAdd()
{
    cb_ShowWPs->setChecked(true);

    sWayPoint WayPoint;

    WayPoint.Longitude = LastClick->longitude();
    WayPoint.Latitude = LastClick->latitude();
    WayPoint.Time = sb_Time->value();

    l_WayPoints.append(WayPoint);

    o_RouteWP->removeGeometry(l_RouteWP);

    p_RouteWP.append(LastClick);
    l_RouteWP = new LineString(p_RouteWP, "", Pen[3]);

    o_RouteWP->addGeometry(l_RouteWP);
    o_Map->updateRequestNew();

    btn_WPFly->setEnabled(true);

    if (l_WayPoints.count() == 20)
    {
        QMessageBox::warning(this, QA_NAME,trUtf8("Wegpunkt-Liste ist voll. Es können maximal 20 Wegpunkte benutzt werden."), QMessageBox::Ok);
        btn_WPAdd->setEnabled(false);
    }
}

// WayPoint-Liste übertragen
void dlg_Main::slot_btn_WPFly()
{
    send_WayPoints(l_WayPoints, 0);
}

// WayPpoint-Liste löschen
void dlg_Main::slot_btn_WPDelete()
{
    p_RouteWP.clear();
    l_WayPoints.clear();
    o_RouteWP->clearGeometries();
    l_RouteWP = new LineString(p_RouteWP, "", Pen[0]);
//    o_RouteWP->addGeometry(l_RouteWP);
//    o_RouteWP->removeGeometry(l_RouteWP);

    o_Map->updateRequestNew();

    btn_WPFly->setEnabled(false);
    btn_WPAdd->setEnabled(true);
}

// WayPoint-Liste laden
void dlg_Main::slot_ac_LoadWayPoints()
{
    QString Filename = QFileDialog::getOpenFileName(this, "WayPoint-Route laden",  s_Dir.WPRoutes, "Mikrokopter WayPoints(*.mkw);;KML-Datei(*.kml);;Alle Dateien (*)");

    if (!Filename.isEmpty())
    {
        if (Filename.endsWith(".kml", Qt::CaseInsensitive))
        {
            cb_ShowWPs->setChecked(true);
            btn_WPFly->setEnabled(true);

            show_WayPoints(parse_WayPointKML(Filename));
        }
        if (Filename.endsWith(".mkw", Qt::CaseInsensitive))
        {
            cb_ShowWPs->setChecked(true);
            btn_WPFly->setEnabled(true);

            show_WayPoints(parse_WayPointMKW(Filename));
        }
    }
}

// WayPoint-Liste speichern
void dlg_Main::slot_ac_SaveRoute()
{
    QString Filename = QFileDialog::getSaveFileName(this, "WayPoint-Route speichern",  s_Dir.WPRoutes, "Mikrokopter WayPoints(*.mkw);;Alle Dateien (*)");

    if (!Filename.isEmpty())
    {
        if (!(Filename.endsWith(".mkw", Qt::CaseInsensitive)))
        {
            Filename = Filename + QString(".mkw");
        }

        save_WayPointsMKW(Filename);
    }
}

// Route anzeigen / ausblenden
void dlg_Main::slot_ShowWayPoints(bool Show)
{
    if (Show == true)
    {
        if (l_RouteWP->hasPoints())
        {
            o_RouteWP->addGeometry(l_RouteWP);
            o_Map->updateRequestNew();
        }
    }
    else
    {
        o_RouteWP->removeGeometry(l_RouteWP);
        o_Map->updateRequestNew();
    }
}

// Bilddatei als Karteladen.
void dlg_Main::slot_ac_LoadMapPic()
{
    QString Filename = QFileDialog::getOpenFileName(this, "Bild als Karte",  s_Dir.MapPics, "Bilddatei(*.jpg *.png *.gif);;Alle Dateien (*)");

    if (!Filename.isEmpty())
    {
        QFile *f_Points = new QFile(Filename + ".pos");

        if (f_Points->exists())
        {
            f_Points->open(QIODevice::ReadOnly | QIODevice::Text);

            QString s_Points;

            while (!f_Points->atEnd())
            {
                s_Points.append(f_Points->readLine());
            }

            f_Points->close();

            QStringList s_Pos = s_Points.split(",");

            FixedImageOverlay* fip = new FixedImageOverlay(s_Pos[0].toDouble(), s_Pos[1].toDouble(), s_Pos[2].toDouble(), s_Pos[3].toDouble(), Filename);

            o_Layer->addGeometry(fip);
            o_Map->setView(QPointF(((s_Pos[0].toDouble() + s_Pos[2].toDouble()) / 2),((s_Pos[1].toDouble() + s_Pos[3].toDouble()) / 2)));

            o_Map->updateRequestNew();
        }
        else
        {
            dlg_MapPos *f_MapPos = new dlg_MapPos(this);

            if (f_MapPos->exec()==QDialog::Accepted)
            {
                QString Data = f_MapPos->get_Data();

                f_Points->open(QIODevice::ReadWrite | QIODevice::Text);

                QTextStream out(f_Points);

                out.setRealNumberPrecision(9);

                out << Data << "\n";

                f_Points->close();

                QStringList s_Pos = Data.split(",");

                FixedImageOverlay* fip = new FixedImageOverlay(s_Pos[0].toDouble(), s_Pos[1].toDouble(), s_Pos[2].toDouble(), s_Pos[3].toDouble(), Filename);

                o_Layer->addGeometry(fip);
                o_Map->updateRequestNew();
            }

        }
    }
}

// Flug als KML aufzeichnen
void dlg_Main::slot_ac_Record()
{
    if (ac_Record->isChecked())
    {
        QString f_Name = s_Dir.Flights + "/" + QDate::currentDate().toString(("yyyy-MM-dd")) + "_" + QTime::currentTime().toString("hh-mm");

        ac_Record->setText(tr("Stoppen"));

        o_Record = new QFile(f_Name + ".kml");
        o_Record->open(QIODevice::Append | QIODevice::Text);

        QTextStream Out(o_Record);
        Out << HandlerKML::get_Header(tr("Mikrokopter Flugaufzeichnung")) << "\n";

    }
    else
    {
        QTextStream Out(o_Record);
        Out << HandlerKML::get_Footer() << "\n";
        o_Record->close();
        ac_Record->setText(tr("Aufzeichnen"));
    }
}

// WayPpoint-Liste löschen
void dlg_Main::slot_ac_RouteDelete()
{
    p_RouteFL.clear();
    l_Track.clear();
    o_RouteFL->clearGeometries();
    l_RouteFL = new LineString(p_RouteFL, "", Pen[0]);
//    o_RouteFL->removeGeometry(l_RouteFL);

    o_Map->updateRequestNew();
}

// Programm Ende
dlg_Main::~dlg_Main()
{
    o_Settings->GUI.isMax       = isMaximized();
    o_Settings->GUI.Size        = size();
    o_Settings->GUI.Point       = pos();
    o_Settings->GUI.Toolbar     = ac_Toolbar->isChecked();

    o_Settings->DATA.Intervall = sb_Intervall->value();

    o_Settings->SERVER.Password = le_Password->text();
    o_Settings->SERVER.IP_MAX  = cb_Server->count();
    o_Settings->SERVER.IP_ID   = cb_Server->currentIndex();

    for (int z = 0; z < cb_Server->count(); z++)
    {
        if (z < 10)
        {
            o_Settings->SERVER.IP[z] = cb_Server->itemText(z);
        }
    }

    o_Settings->CONFIG.cb_CenterPos = cb_CenterPos->isChecked();
    o_Settings->CONFIG.cb_ShowRoute = cb_ShowRoute->isChecked();
    o_Settings->CONFIG.cb_ShowWPs   = cb_ShowWPs->isChecked();
    o_Settings->CONFIG.cb_Goto      = cb_Goto->isChecked();

    o_Settings->NAVI.StayTime = sb_Time->value();

    o_Settings->write_Settings();
 
//    qDebug("Ende.");
}