/***************************************************************************
                          cumulusapp.cpp  -  main application object
                             -------------------
    begin                : Sun Jul 21 2002
    copyright            : (C) 2002 by Andre Somers
    email                : andre@kflog.org

     This file is distributed under the terms of the General Public
     Licence. See the file COPYING for more information.

     $Id: cumulusapp.cpp,v 1.157 2005/02/28 10:23:51 andre Exp $

****************************************************************************/

/***************************************************************************
 *                                                                         *
 *   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, or     *
 *   (at your option) any later version.                                   *
 *                                                                         *
 ***************************************************************************/

#include "targets.h"

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <signal.h>
#include <sys/ioctl.h>

#include <qfile.h>
#include <qdatetime.h>
#include <qdir.h>
#include <qevent.h>
#include <qlist.h>
#include <qmessagebox.h>
#include <qfocusdata.h>
#include <qsound.h>

#include <qpe/global.h>
#include <qpe/resource.h>
#include <qpe/sound.h>
#include <qpe/qpeapplication.h>
#include <qpe/qcopenvelope_qws.h>
#include <qpe/sound.h>

#include "generalconfig.h"
#include "cumulusapp.h"
#include "translationlist.h"
#include "airport.h"
#include "mapconfig.h"
#include "mapcontents.h"
#include "mapmatrix.h"
#include "cucalc.h"
#include "igclogger.h"
#include "windanalyser.h"
#include "configdialog.h"
#include "wpeditdialog.h"
#include "preflightdialog.h"
#include "wgspoint.h"
#include "wp.h"
#include "hwinfo.h"
#include "gliderlist.h"
#include "gpsstatusdialog.h"

TranslationList surfaces;

TranslationList waypointTypes;

IgcLogger * logger=0;

/**
 * Used for transforming the mapitems.
 */
MapMatrix * _globalMapMatrix=0;

/**
 * Contains all mapelements and takes control over drawing or printing
 * the elements.
 */
MapContents * _globalMapContents=0;

/**
 * Contains all configuration-info for drawing and printing the elements.
 */
MapConfig * _globalMapConfig=0;

//* @ee if we have a cf card receiver, it must be resumed after the
//* Zaurus has been resumed from sleep */


static void resumeCF (int sig) // @AP: no need for global scope
{
  // let's get rid of that shell script system ("cfgps");
  // we can do it internally
  // resume card and do stty if neccesary

  system(
     "READY=`cardctl status 0 | grep ready | wc -l`;"
     "if [ $READY -gt 0 ];"
     "then"
     "  echo \"Cumulus: CF-Card ready\";"
     "else"
     "  echo \"Cumulus: Executing CF cardctl resume\";"
     "  cardctl resume;"
     "fi;");

  if (sig)
  {
    gps->forceReset();
    // @ee reinstall signal handler
    // signal (SIGCONT, resumeCF);
  }
}


/** As the name tells ...
  * 
  */
void CumulusApp::playSound(const QString *name)
{
  GeneralConfig *conf = GeneralConfig::instance();

  if( ! conf->getAlarmSoundOn() )
    {
      return;
    }
  else
    {
      if( name )
        {
          Sound sound( *name );
          sound.play();
        }
      else
        {
          Sound::soundAlarm();
        }
    }
}


void CumulusApp::airspaceWarning (const QString& msg)
{
  if (msg.isEmpty())
    setCaption ("Cumulus " + calculator->gliderType());
  else
  {
    playSound();
    setCaption (msg + " ");
  }
}


CumulusApp::CumulusApp(QWidget *parent, const char *name )
: QMainWindow(parent,name)
{
  GeneralConfig *conf = GeneralConfig::instance();

  // @AP: Display some environment variables, to get more clearness
  // about their settings during process startup
  char *pwd     = getenv("PWD");
  char *user    = getenv("USER");
  char *home    = getenv("HOME");
  char *ldpath  = getenv("LD_LIBRARY_PATH");
  char *qtdir   = getenv("QTDIR");
  char *qpedir  = getenv("QPEDIR");
  char *opiedir = getenv("OPIEDIR");

  qDebug("PWD=%s", pwd ? pwd : "NULL" );
  qDebug("USER=%s", user ? user : "NULL" );
  qDebug("HOME=%s", home ? home : "NULL" );
  qDebug("LD_LIBRARY_PATH=%s", ldpath ? ldpath : "NULL" );
  qDebug("QTDIR=%s", qtdir ? qtdir : "NULL" );
  qDebug("QPEDIR=%s", qpedir ? qpedir : "NULL" );
  qDebug("OPIEDIR=%s", opiedir ? opiedir : "NULL" );
  qDebug("QDir::homeDirPath()=%s", QDir::homeDirPath().latin1() );

  // @AS: Grab the keyboard to get all hardware keys (f1..f12) too
  QPEApplication::grabKeyboard();
  setFocusPolicy(QWidget::StrongFocus);
  setFocus();
  this->installEventFilter(this);

  // @AP: The QPE server on a z5500, maybe also on other devices, has setup a
  // notification, if memory will going low. This notification will popup the
  // low on memory box of the Qtopia desktop. But it seems that the
  // notification comes to early, so that cumulus is terminated if it needs
  // more memory and the memory is still available. With the following lines
  // of code we will switch off this handling. It will be restored in the
  // destructor.

  freepgContentLen = 0;
  freepgContent[0] = '\0';

  QFile freepgFile( "/proc/sys/vm/freepg_signal_proc");

  if( freepgFile.open(IO_ReadOnly) )
    {
      freepgContentLen = freepgFile.readBlock( freepgContent, sizeof(freepgContent) );
      freepgFile.close();

      qDebug("%d bytes read from freepg_signal_proc", freepgContentLen );

      // reset signal emitting to QPE server
      FILE *fo = fopen("/proc/sys/vm/freepg_signal_proc", "w");
      if(fo)
        {
          qDebug("Content of /proc/sys/vm/freepg_signal_proc file will be reset");
          fprintf(fo, "\n");
          fclose(fo);
        }
    }

  setIcon(Resource::loadPixmap( "system_icon" ));
  setCaption("Cumulus ");

  showMaximized();
  qApp->processEvents();

  // @AP: Note: needs to be encased in { } so that it deconstructs and
  // sends immediately Don't change the order of the two following
  // statements! Otherwise screensaver will not work properly.
  {
    // disables only "power off" according to Opie sources
    // this seems to work on older Zaurus devices
    QCopEnvelope("QPE/System","setScreenSaverMode(int)") << QPEApplication::Disable;
  }

  // @AP: Note: needs to be encased in { } so that it deconstructs and sends immediately
  {
    // @AP: In qtopia sources I found the following to switch off screensaver
    QCopEnvelope disableScreenSaver( "QPE/System", "setScreenSaverIntervals(int,int,int)" );
    disableScreenSaver << 0 << 0 << 0;
  }

  ws=new WaitScreen(this,"Waitscreen");
  ws->show();
  ws->slot_SetText1(tr("Creating map matrix..."));
  _globalMapMatrix= new MapMatrix(this);
  ws->slot_SetText1(tr("Loading map contents..."));
  //delete ws;
  _globalMapContents= new MapContents(this, ws);
  ws->slot_SetText1(tr("Loading map config..."));
  _globalMapConfig=new MapConfig(this);
  ws->slot_SetText1(tr("Initializing..."));

  BaseMapElement::initMapElement(_globalMapMatrix, _globalMapConfig);

  initSurfaces();
  initTypes();
  
  calculator = new CuCalc(this);

  ws->slot_SetText1(tr("Creating views..."));
  ws->show();
  connect(_globalMapMatrix, SIGNAL(displayMatrixValues(int, bool)),
          _globalMapConfig, SLOT(slotSetMatrixValues(int, bool)));

  connect(_globalMapConfig, SIGNAL(configChanged()), 
          _globalMapMatrix, SLOT(slotInitMatrix()));

  _globalMapConfig->slotReadConfig();
  _altimeterModeDlg = new AltimeterModeDialog(this);
  _varioModeDlg = new VarioModeDialog(this);

  ws->show();
  WpCatalog=new WaypointCatalog;
  viewMap=new MapView(this, "mapview");

  setCentralWidget(viewMap);
  listViewTabs=new QTabWidget(this, "listviewtabs");
  listViewTabs->resize(this->size());
  QFont fnt( "Helvetica", 12, QFont::Bold  );
 
  viewWP=new WaypointListView(this, "waypointlistview");
  viewAP=new AirfieldListView(this, "airfieldlistview");
  viewRP=new ReachpointListView(this, "reachpointlistview");
  viewTP=new TaskListView(this, "tasklistview");
  viewWP->setFont(fnt);
  viewAP->setFont(fnt);
  viewRP->setFont(fnt);
  viewTP->setFont(fnt);
  
  //listViewTabs->addTab(viewTP, tr("Task"));  --> This page is only added if a task has been selected.
  _taskListVisible=false;
  listViewTabs->addTab(viewWP, tr("Waypoints"));
  listViewTabs->addTab(viewRP, tr("Reachable"));
  listViewTabs->addTab(viewAP, tr("Airfields"));
  viewInfo=new WPInfoWidget(this, "infoview");
  
  QString catalogfile( conf->getWaypointFile() );
  WpCatalog->read(catalogfile);
  qDebug("Waypoints read (%d items)",WpCatalog->wpList->count());
  viewMap->_theMap->slotWaypointCatalogChanged(WpCatalog);
  viewWP->fillWpList(WpCatalog);

  //create global objects
  gps = new GPSNMEA(this);
  gps->blockSignals(true);
  logger = IgcLogger::instance();
  _preFlightDialog = 0;
  _gliderFlightDlg = NULL;

  initActions();
  initMenuBar();
  
  ws->show();
  // set dynamical Info
  viewMap->getAltitudeWidget()->setPreText( _altimeterModeDlg->Pretext() );

  //create connections between the components
  connect(_globalMapMatrix, SIGNAL(matrixChanged()), viewMap->_theMap, SLOT(slotRedraw()));
  connect(_globalMapMatrix, SIGNAL(projectionChanged()), _globalMapContents, SLOT(slotReloadMapData()) );
  connect(_globalMapContents, SIGNAL(mapDataReloaded()), viewMap->_theMap, SLOT(slotRedraw()));
  connect(_altimeterModeDlg, SIGNAL(newAltimeterMode()),this, SLOT(slotNewAltimeterMode()));
  connect(_altimeterModeDlg, SIGNAL(settingsChanged()),calculator, SLOT(slot_settingschanged()));
  connect(_varioModeDlg, SIGNAL( newVarioTime(int)), calculator->getVario(), SLOT(slotNewVarioTime(int)));
  connect(_varioModeDlg, SIGNAL( newTEKMode(bool)), calculator->getVario(), SLOT(slotNewTEKMode(bool)));
  connect(_varioModeDlg, SIGNAL( newTEKAdjust(int)), calculator->getVario(), SLOT(slotNewTEKAdjust(int)));
  connect(calculator, SIGNAL( newAirspeed(const Speed&)), calculator->getVario(), SLOT(slotNewAirspeed(const Speed&)));

  connect(gps, SIGNAL(statusChange(GPSNMEA::connectedStatus)), viewMap, SLOT(slotGPSStatus(GPSNMEA::connectedStatus)));
  connect(gps, SIGNAL(newSatConstellation()), viewMap, SLOT(slotSatConstellation()));
  connect(gps, SIGNAL(statusChange(GPSNMEA::connectedStatus)), this, SLOT(slotGpsStatus(GPSNMEA::connectedStatus)));
  connect(gps, SIGNAL(newSatConstellation()), logger, SLOT(slotConstellation()));
  connect(gps, SIGNAL(newSatConstellation()), calculator->getWindAnalyser(), SLOT(slot_newConstellation()));
  connect(gps, SIGNAL(newSpeed()), calculator, SLOT(slot_Speed()));
  connect(gps, SIGNAL(newPosition()), calculator, SLOT(slot_Position()));
  connect(gps, SIGNAL(newAltitude()), calculator, SLOT(slot_Altitude()));
  connect(gps, SIGNAL(newHeading()), calculator, SLOT(slot_Heading()));
  connect(gps, SIGNAL(newFix()), calculator, SLOT(slot_newFix()));
  connect(gps, SIGNAL(statusChange(GPSNMEA::connectedStatus)), calculator, SLOT(slot_GpsStatus(GPSNMEA::connectedStatus)));
  
  connect(viewWP, SIGNAL(newWaypoint(wayPoint*)), calculator, SLOT(slot_WaypointChange(wayPoint*)));
  connect(viewWP, SIGNAL(deleteWaypoint(wayPoint*)), calculator, SLOT(slot_WaypointDelete(wayPoint*)));
  connect(viewWP, SIGNAL(done()), this, SLOT(slotSwitchToMapView()));
  connect(viewWP, SIGNAL(info(wayPoint*)), this, SLOT(slotSwitchToInfoView(wayPoint*)));
  connect(viewWP, SIGNAL(newHomePosition(const QPoint*)),  _globalMapMatrix, SLOT(slotSetNewHome(const QPoint*)) );
  
  connect(viewAP, SIGNAL(newWaypoint(wayPoint*)), calculator, SLOT(slot_WaypointChange(wayPoint*)));
  connect(viewAP, SIGNAL(done()), this, SLOT(slotSwitchToMapView()));
  connect(viewAP, SIGNAL(info(wayPoint*)), this, SLOT(slotSwitchToInfoView(wayPoint*)));
  connect(viewAP, SIGNAL(newHomePosition(const QPoint*)),  _globalMapMatrix, SLOT(slotSetNewHome(const QPoint*)) );

  connect(viewRP, SIGNAL(newWaypoint(wayPoint*)), calculator, SLOT(slot_WaypointChange(wayPoint*)));
  connect(viewRP, SIGNAL(done()), this, SLOT(slotSwitchToMapView()));
  connect(viewRP, SIGNAL(info(wayPoint*)), this, SLOT(slotSwitchToInfoView(wayPoint*)));

  connect(viewTP, SIGNAL(newWaypoint(wayPoint*)), calculator, SLOT(slot_WaypointChange(wayPoint*)));
  connect(viewTP, SIGNAL(done()), this, SLOT(slotSwitchToMapView()));
  connect(viewTP, SIGNAL(info(wayPoint*)), this, SLOT(slotSwitchToInfoView(wayPoint*)));
  
  connect(viewMap->_theMap, SIGNAL(waypointSelected(wayPoint*)), this, SLOT(slotSwitchToInfoView(wayPoint*)));
  connect(viewMap->_theMap, SIGNAL(airspaceWarning(const QString&)), this, SLOT(airspaceWarning(const QString&)));

  connect(viewInfo, SIGNAL(waypointAdded(wayPoint*)), viewWP, SLOT(slot_wpAdded(wayPoint*)));
  connect(viewInfo, SIGNAL(waypointSelected(wayPoint*)), calculator, SLOT(slot_WaypointChange(wayPoint*)));
  connect(viewInfo, SIGNAL(newHomePosition(const QPoint*)),  _globalMapMatrix, SLOT(slotSetNewHome(const QPoint*)) );

  connect(listViewTabs, SIGNAL(currentChanged(QWidget*)), this, SLOT(slot_tabChanged(QWidget*)));
  
  connect(calculator, SIGNAL(newWaypoint(const QString&)), viewMap, SLOT(slot_Waypoint(const QString&)));
  connect(calculator, SIGNAL(newBearing(int)), viewMap, SLOT(slot_Bearing(int)));
  connect(calculator, SIGNAL(newRelBearing(int)), viewMap, SLOT(slot_RelBearing(int)));
  connect(calculator, SIGNAL(newDistance(const Distance&)), viewMap, SLOT(slot_Distance(const Distance&)));
  connect(calculator, SIGNAL(newETA(const QTime&)), viewMap, SLOT(slot_ETA(const QTime&)));
  connect(calculator, SIGNAL(newHeading(int)), viewMap, SLOT(slot_Heading(int)));
  connect(calculator, SIGNAL(newSpeed(const Speed&)), viewMap, SLOT(slot_Speed(const Speed&)));
  connect(calculator, SIGNAL(newAltitude(const Altitude&)), viewMap, SLOT(slot_Altitude(const Altitude&)));
  connect(calculator, SIGNAL(newPosition(const QPoint&)), viewMap, SLOT(slot_Position(const QPoint&)));
  connect(calculator, SIGNAL(newPosition(const QPoint&)), viewMap->_theMap, SLOT(slot_position(const QPoint&)));
  connect(calculator, SIGNAL(glidePath(const Altitude&)), viewMap, SLOT(slot_GlidePath(const Altitude&)));
  connect(calculator, SIGNAL(bestSpeed(const Speed&)), viewMap, SLOT(slot_bestSpeed(const Speed&)));
  connect(calculator, SIGNAL(newMc(const Speed&)), viewMap, SLOT(slot_Mc(const Speed&)));
  connect(calculator, SIGNAL(newVario(const Speed&)), viewMap, SLOT(slot_vario(const Speed&)));
  connect(calculator, SIGNAL(newWind(Vector&)), viewMap, SLOT(slot_wind(Vector&)));
  connect(calculator, SIGNAL(flightModeChanged(CuCalc::flightmode)), viewMap, SLOT(setFlightStatus()));
  connect(calculator, SIGNAL(flightModeChanged(CuCalc::flightmode)), logger, SLOT(slotFlightMode(CuCalc::flightmode)));

  connect((QObject*)calculator->getReachList(), SIGNAL(newReachList()), this, SLOT(slot_newReachList()));

  connect(logger, SIGNAL(logging(bool)), viewMap, SLOT(setFlightStatus()));
  connect(logger, SIGNAL(logging(bool)), this, SLOT(slot_Logging(bool)));
  connect(logger, SIGNAL(madeEntry()), viewMap, SLOT(slot_LogEntry()));

  ws->slot_SetText1(tr("Setting up accelerators..."));
  ws->show();

  //create the keyboard accelerators
  accApView=new QAccel(this);
  accInfoView=new QAccel(this);
  accManualNav=new QAccel(this);
  accGpsNav=new QAccel(this);
  //accMcSet=new QAccel(this);
  accRpView=new QAccel(this);
  accTpView=new QAccel(this);
  accWpView=new QAccel(this);

  // most accelerators are now QActions these could also go as
  // QAction, even when not in a menu
 
  //WaypointListView accelerators
  accApView->connectItem(accApView->insertItem(Key_Space), viewAP, SLOT(slot_Select()));
  accRpView->connectItem(accRpView->insertItem(Key_Space), viewRP, SLOT(slot_Select()));
  accTpView->connectItem(accTpView->insertItem(Key_Space), viewTP, SLOT(slot_Select()));
  accWpView->connectItem(accWpView->insertItem(Key_Space), viewWP, SLOT(slot_Select()));

  //InfoView accelerators
  accInfoView->connectItem(accInfoView->insertItem(Key_Space), viewInfo, SLOT(slotSwitchBack()));
  accInfoView->connectItem(accInfoView->insertItem(Key_I), viewInfo, SLOT(slot_KeepOpen()));
  accInfoView->connectItem(accInfoView->insertItem(Key_K), viewInfo, SLOT(slot_KeepOpen()));

  //Manual navigation accelerators. These are only available if there is no GPS connection
  accManualNav->connectItem(accManualNav->insertItem(Key_Up), calculator, SLOT(slot_changePositionN()));
  accManualNav->connectItem(accManualNav->insertItem(Key_Right), calculator, SLOT(slot_changePositionE()));
  accManualNav->connectItem(accManualNav->insertItem(Key_Down), calculator, SLOT(slot_changePositionS()));
  accManualNav->connectItem(accManualNav->insertItem(Key_Left), calculator, SLOT(slot_changePositionW()));
  accManualNav->connectItem(accManualNav->insertItem(Key_H), calculator, SLOT(slot_changePositionHome()));
  accManualNav->connectItem(accManualNav->insertItem(Key_C), calculator, SLOT(slot_changePositionWp()));

  accManualNav->connectItem(accManualNav->insertItem(Key_F9), this, SLOT(slotSwitchToWPListView()));

  //setting of McCready value
  accGpsNav->connectItem(accGpsNav->insertItem(Key_Up), calculator, SLOT(slot_McUp()));
  accGpsNav->connectItem(accGpsNav->insertItem(Key_Down), calculator, SLOT(slot_McDown()));
  accGpsNav->connectItem(accGpsNav->insertItem(Key_H), this, SLOT(slotNavigateHome()));
  
  calculator->setPosition(_globalMapMatrix->getMapCenter(false));
  
  ws->slot_SetText1(tr("Starting views..."));
  slot_readconfig();
  setView(mapView);

  // set the default glider to be the last one selected.
  calculator->setGlider(GliderList::getStoredSelection());
  QString gt=calculator->gliderType();

  if (!gt.isEmpty()) setCaption ("Cumulus - " + gt);
  viewMap->_theMap->setDrawing(true);
  viewMap->_theMap->draw();
  ws->hide();
  ws->setScreenUsage(false);
  calculator->newSites();  // New sites have been loaded in map draw
  gps->blockSignals(false);

  qDebug("End startup cumulusapp");
}


CumulusApp::~CumulusApp()
{
  // qDebug ("CumulusApp::~CumulusApp()");

  // @AP: Note: needs to be encased in { } so that it deconstructs and sends immediately
  // re-enables only "power off" according to Opie sources (older devices)
  {
    QCopEnvelope("QPE/System","setScreenSaverMode(int)") << QPEApplication::Enable;
  }

  // @AP: Note: needs to be encased in { } so that it deconstructs and sends immediately
  // @AP: In qtopia sources I found the following to switch on screensaver
  {
    QCopEnvelope enableScreenSaver( "QPE/System", "setScreenSaverIntervals(int,int,int)" );
    enableScreenSaver << -1 << -1 << -1;
  }

  // @AS: Un-Grab the keyboard
  QPEApplication::ungrabKeyboard();

  // @AP: check, if freepg_signal must be restored
  if( freepgContentLen  > 0 )
    {
      FILE *fo = fopen("/proc/sys/vm/freepg_signal_proc", "w");

      if(fo)
        {
          qDebug("Content of /proc/sys/vm/freepg_signal_proc file will be restored");
          fwrite(freepgContent, sizeof(char), freepgContentLen, fo);
          fclose(fo);
        }
    }

  delete WpCatalog;
  delete logger;
}


void CumulusApp::initMenuBar()
{
  fileMenu=new QPopupMenu(this);
  actionFileQuit->addTo(fileMenu);

  viewMenu=new QPopupMenu(this);
  actionViewTaskpoints->addTo(viewMenu);
  actionViewTaskpoints->setEnabled(false);
  actionViewWaypoints->addTo(viewMenu);
  actionViewAirports->addTo(viewMenu);
  actionViewReachpoints->addTo(viewMenu);
  actionViewInfo->addTo(viewMenu);
  viewMenu->insertSeparator();
  actionToggleStatusbar->addTo(viewMenu);
  actionToggleMenu->addTo(viewMenu);
  actionToggleWpLabels->addTo(viewMenu);
  actionToggleWpLabelsEI->addTo(viewMenu);
  viewMenu->insertSeparator();
  actionViewGPSStatus->addTo(viewMenu);
    
  mapMenu=new QPopupMenu(this);
  actionToggleLogging->addTo(mapMenu);
  actionRememberWaypoint->addTo(mapMenu);
  actionSelectTask->addTo(mapMenu);
  mapMenu->insertSeparator();
  actionEnsureVisible->addTo(mapMenu);
  actionZoomInZ->addTo(mapMenu);
  actionZoomOutZ->addTo(mapMenu);
    
  setupMenu=new QPopupMenu(this);
  actionSetupConfig->addTo(setupMenu);
  actionPreFlight->addTo(setupMenu);
  actionSetupInFlight->addTo(setupMenu);

  helpMenu=new QPopupMenu(this);
//  actionHelp->addTo(helpMenu);
  actionWhatsThis->addTo(helpMenu);
  actionHelpAboutApp->addTo(helpMenu);

  menuBar()->insertItem(tr("&File"), fileMenu);
  menuBar()->insertItem(tr("&View"), viewMenu);
  menuBar()->insertItem(tr("&Map"), mapMenu);
  menuBar()->insertItem(tr("&Setup"), setupMenu);
  menuBar()->insertSeparator();
  menuBar()->insertItem(tr("&Help"), helpMenu);
  menuBar()->hide();
}


/** initializes all QActions of the application */
void CumulusApp::initActions()
{
  // the F11 key is the menu button on the Zaurus
  enum Key Key_Menu;
  switch( HWINFO->getType())
  {
    case HwInfo::ipaq:
      Key_Menu = Key_Space;
      break;
    case HwInfo::sharp:
      Key_Menu = Key_F11;
      break;
    default:
      Key_Menu = Key_F11;
      break;
  }
    
  actionToggleMenu = new QAction (tr("Menu"), tr("&Menu"), Key_Menu, this, 0, true);
  connect (actionToggleMenu, SIGNAL(toggled(bool)), this, SLOT(slotToggleMenu(bool)));

  actionFileQuit = new QAction(tr("Exit"), tr("E&xit"), 0, this);
  connect(actionFileQuit, SIGNAL(activated()), this, SLOT(slotFileQuit()));

  actionViewWaypoints = new QAction (tr("Waypoints"), tr("&Waypoints"), Key_W, this);
  actionViewAirports = new QAction (tr("Airports"), tr("&Airports"), Key_O, this);
  actionViewReachpoints = new QAction (tr("Rechable Points"), tr("&Rechable Points"), Key_E, this);
  actionViewTaskpoints = new QAction (tr("Task"), tr("&Task"), Key_T, this);
  connect(actionViewAirports, SIGNAL(activated()), this, SLOT(slotSwitchToAPListView()));
  connect(actionViewWaypoints, SIGNAL(activated()), this, SLOT(slotSwitchToWPListView()));
  connect(actionViewReachpoints, SIGNAL(activated()), this, SLOT(slotSwitchToReachListView()));
  connect(actionViewTaskpoints, SIGNAL(activated()), this, SLOT(slotSwitchToTaskListView()));
  actionViewInfo = new QAction(tr("Info"), tr("&Info"), Key_I, this);
  connect(actionViewInfo, SIGNAL(activated()), this, SLOT(slotSwitchToInfoView()));
  actionToggleStatusbar = new QAction(tr("Statusbar"), tr("&Statusbar"), 0, this, 0, true);
  connect(actionToggleStatusbar, SIGNAL(toggled(bool)), this, SLOT(slotViewStatusBar(bool)));
  actionToggleStatusbar->setOn(true);
  actionViewGPSStatus = new QAction(tr("GPS Status"), tr("GPS Status"), Key_G, this);
  connect(actionViewGPSStatus, SIGNAL(activated()), this, SLOT(slotGpsStatusDialog()));
  
  actionZoomInZ = new QAction (tr("Zoom in"), tr("Zoom in"), Key_Z, this);
  connect (actionZoomInZ, SIGNAL(activated()), viewMap->_theMap , SLOT(slotZoomIn()));
  actionZoomOutZ = new QAction (tr("Zoom out"), tr("Zoom out"), Key_X, this);
  connect (actionZoomOutZ, SIGNAL(activated()), viewMap->_theMap , SLOT(slotZoomOut()));
  
  actionZoomIn = new QAction (tr("Zoom in"), tr("Zoom in"), Key_Right, this);
  connect (actionZoomIn, SIGNAL(activated()), viewMap->_theMap , SLOT(slotZoomIn()));
  actionZoomOut = new QAction (tr("Zoom out"), tr("Zoom out"), Key_Left, this);
  connect (actionZoomOut, SIGNAL(activated()), viewMap->_theMap , SLOT(slotZoomOut()));
  
  actionToggleWpLabels = new QAction (tr("Waypoint labels"), tr("Waypoint labels"), Key_A, this, 0, true);
  actionToggleWpLabels->setOn(_globalMapConfig->getShowWpLabels());
  connect(actionToggleWpLabels, SIGNAL(toggled(bool)), this, SLOT(slotToggleWpLabels(bool)));
  actionToggleWpLabelsEI = new QAction (tr("Waypoint extra info"), tr("Waypoint extra info"), Key_S, this, 0, true);
  actionToggleWpLabelsEI->setOn(_globalMapConfig->getShowWpLabelsExtraInfo());
  connect(actionToggleWpLabelsEI, SIGNAL(toggled(bool)), this, SLOT(slotToggleWpLabelsExtraInfo(bool)));
  actionToggleLogging = new QAction(tr("IGC Logging"), tr("Logging"), Key_L, this, 0, true);
  connect (actionToggleLogging,SIGNAL(activated()),logger, SLOT(slotToggleLogging()));
  actionEnsureVisible = new QAction (tr("Ensure waypoint visible"), tr("Ensure waypoint visible"), Key_V, this);
  connect (actionEnsureVisible,SIGNAL(activated()), this, SLOT(slotEnsureVisible()));
  actionSelectTask = new QAction(tr("Select task"), tr("Select task"), Key_T+SHIFT, this);
  connect (actionSelectTask,SIGNAL(activated()), this, SLOT(slotSelectTask()));
  actionPreFlight = new QAction(tr("Pre Flight"), tr("Pre Flight"), Key_P, this);
  connect (actionPreFlight,SIGNAL(activated()), this, SLOT(slotPreFlight()));
  actionRememberWaypoint = new QAction(tr("Remember waypoint"), tr("Remember waypoint"), Key_R, this);
  connect(actionRememberWaypoint,SIGNAL(activated()), this, SLOT(slotRememberWaypoint()));

  actionSetupConfig = new QAction(tr("General Setup"), tr ("General &Setup"), Key_S+SHIFT, this);
  connect (actionSetupConfig, SIGNAL(activated()), this, SLOT(slotConfig()));
  actionSetupInFlight = new QAction(tr("In Flight"), tr ("In &Flight"), Key_F, this);
  connect (actionSetupInFlight, SIGNAL(activated()), this, SLOT(slotGliderFlight()));
  
//  actionHelp = new QAction (tr("Help"), tr("&Help"), Key_H, this);
//  connect(actionHelp, SIGNAL(activated()),this,SLOT(slotHelp()));
  actionWhatsThis = new QAction(tr("What's this ?"), tr("What's this ?"), 0, this);
  connect (actionWhatsThis, SIGNAL(activated()), this, SLOT(whatsThis()));
  actionHelpAboutApp = new QAction(tr("About Cumulus"), tr("About Cumulus"), Key_V+SHIFT, this);
  connect(actionHelpAboutApp, SIGNAL(activated()), this, SLOT(slotVersion()));
}

 
void CumulusApp::slotFileQuit ()
{
  close();
}


/** Make sure the user really wants to quit
  */
void CumulusApp::closeEvent (QCloseEvent* evt)
{
  playSound();

  QMessageBox mb( tr("Are you sure?"),
    tr("<qt><b>Cumulus will be terminated.<br>Are you sure?</b></qt>"),
    QMessageBox::Warning,
    QMessageBox::Yes | QMessageBox::Default,
    QMessageBox::No,
    QMessageBox::NoButton );
  
#ifdef take_bold_font
  QFont fnt( "Helvetica", 12, QFont::Bold  );
  mb.setFont(fnt);
#endif

  switch( mb.exec() )
    {
    case QMessageBox::Yes:
      // save and exit
      evt->accept();
      break;
    case QMessageBox::No:
      // exit without saving
      evt->ignore();
      break;
    case QMessageBox::Cancel:
      // don't save and don't exit
      evt->ignore();
      break;
    }
}


void CumulusApp::slotToggleMenu(bool toggle)
{
  if (toggle)
    menuBar()->show();
  else
    menuBar()->hide();
}


void CumulusApp::slotToggleWpLabels(bool toggle)
{
  _globalMapConfig->setShowWpLabels(toggle);
  viewMap->_theMap->quickDraw();
}


void CumulusApp::slotToggleWpLabelsExtraInfo(bool toggle)
{
  _globalMapConfig->setShowWpLabelsExtraInfo(toggle);
  viewMap->_theMap->quickDraw();
}


void CumulusApp::slotViewStatusBar(bool toggle)
{
  if (toggle)
    viewMap->statusBar()->show();
  else
    viewMap->statusBar()->hide();
}


/** Called if the logging is actually toggled */
void CumulusApp::slot_Logging (bool logging)
{
  actionToggleLogging->blockSignals (true);
  actionToggleLogging->setOn (logging);
  actionToggleLogging->blockSignals (false);
}


void CumulusApp::initSurfaces()
{
  surfaces.setAutoDelete(true);

  surfaces.append(new TranslationElement(Airport::NotSet, tr("Unknown")));
  surfaces.append(new TranslationElement(Airport::Grass, tr("Grass")));
  surfaces.append(new TranslationElement(Airport::Asphalt, tr("Asphalt")));
  surfaces.append(new TranslationElement(Airport::Concrete, tr("Concrete")));

  surfaces.sort();
}


void CumulusApp::initTypes()
{
  waypointTypes.setAutoDelete(true);

  // don't know if we really need all of them
  waypointTypes.append(new TranslationElement(BaseMapElement::AerialRailway, tr("Aerial railway")));
  waypointTypes.append(new TranslationElement(BaseMapElement::Airfield, tr("Airfield")));
  waypointTypes.append(new TranslationElement(BaseMapElement::Airport, tr("Airport")));
  waypointTypes.append(new TranslationElement(BaseMapElement::AmbHeliport, tr("Ambul. Airport")));
  waypointTypes.append(new TranslationElement(BaseMapElement::Ballon, tr("Balloon")));
  waypointTypes.append(new TranslationElement(BaseMapElement::City, tr("City")));
  waypointTypes.append(new TranslationElement(BaseMapElement::CivHeliport, tr("Civil Heliport")));
  waypointTypes.append(new TranslationElement(BaseMapElement::IntAirport, tr("Int. Airport")));
  waypointTypes.append(new TranslationElement(BaseMapElement::MilAirport, tr("Mil. Airport")));
  waypointTypes.append(new TranslationElement(BaseMapElement::CivMilAirport, tr("Civil/Mil. Airport")));
  waypointTypes.append(new TranslationElement(BaseMapElement::ClosedAirfield, tr("Closed Airfield")));
  waypointTypes.append(new TranslationElement(BaseMapElement::Glidersite, tr("Glider site")));
  waypointTypes.append(new TranslationElement(BaseMapElement::HangGlider, tr("Hang glider")));
  waypointTypes.append(new TranslationElement(BaseMapElement::Landmark, tr("Landmark")));
  waypointTypes.append(new TranslationElement(BaseMapElement::MilHeliport, tr("Mil. Heliport")));
  waypointTypes.append(new TranslationElement(BaseMapElement::UltraLight, tr("Ultralight")));
  waypointTypes.append(new TranslationElement(BaseMapElement::Parachute, tr("Parachute")));
  waypointTypes.append(new TranslationElement(BaseMapElement::Outlanding, tr("Outlanding")));
  waypointTypes.append(new TranslationElement(BaseMapElement::Obstacle, tr("Obstacle")));
  waypointTypes.append(new TranslationElement(BaseMapElement::ObstacleGroup, tr("Obstacle group")));
  waypointTypes.append(new TranslationElement(BaseMapElement::LightObstacleGroup, tr("Obstacle group (lighted)")));
  waypointTypes.append(new TranslationElement(BaseMapElement::LightObstacle, tr("Obstacle (lighted)")));
  waypointTypes.append(new TranslationElement(BaseMapElement::Railway, tr("Railway")));
  waypointTypes.append(new TranslationElement(BaseMapElement::Road, tr("Road")));
  waypointTypes.append(new TranslationElement(BaseMapElement::Village, tr("Village")));
  waypointTypes.append(new TranslationElement(BaseMapElement::Turnpoint, tr("Turnpoint")));
  waypointTypes.append(new TranslationElement(BaseMapElement::Thermal, tr("Thermal")));

  waypointTypes.sort();
}


/** Read property of enum view. */
const CumulusApp::appView CumulusApp::getView()
{
  return view;
}


/** Called if the user clicks a tab with a list-type view */
void CumulusApp::slot_tabChanged(QWidget * w)
{
  //switch to the correct view
  if (w==viewWP) 
  {
    setView(wpView);
  }
  else if (w==viewTP) 
  {
    setView(tpView);
  }
  else if (w==viewRP) 
  {
    setView(rpView);
  }
  else if (w==viewAP) 
  {
    setView(apView);
  }
}


/** Write property of int view. */
void CumulusApp::setView(const appView& _newVal, const wayPoint* wp)
{
  appView old=view;
  view = _newVal;
 // qDebug("setView called with argument %d",_newVal);

#warning "FIXME: It would be better to group actions in actiongroups, so we don't need to enable and"
  /*  disable them all seperately. */
  switch (view)
  {
    case mapView:
      // @AP: set focus to cumulus widget, otherwise F-Key events will
      // not routed to it under Opie
      setFocus();
      viewMap->show();
      setCentralWidget(viewMap);
      //viewWP->hide();
      //viewAP->hide();
      //viewRP->hide();
      listViewTabs->hide();
      viewInfo->hide();
      accApView->setEnabled(false);
      accRpView->setEnabled(false);
      accTpView->setEnabled(false);
      accWpView->setEnabled(false);
      accInfoView->setEnabled(false);
      accManualNav->setEnabled(!gps->getConnected());
      accGpsNav->setEnabled(gps->getConnected());

      mapMenu->setEnabled(true);
      actionViewWaypoints->setEnabled(true);
      actionViewAirports->setEnabled(true);
      actionViewReachpoints->setEnabled(true);
      actionViewInfo->setEnabled(true);
      actionViewInfo->setAccel(Key_I); //re-enable acceleraror keys
      //actionSelectTask->setAccel(Key_T);
      actionViewGPSStatus->setEnabled(true);
      actionSelectTask->setEnabled(true);
      actionRememberWaypoint->setEnabled(true);
      actionToggleMenu->setEnabled(true);
      actionToggleStatusbar->setEnabled(true);
      actionZoomIn->setEnabled(true);
      actionZoomInZ->setEnabled(true);
      actionZoomOut->setEnabled(true);
      actionZoomOutZ->setEnabled(true);
      actionEnsureVisible->setEnabled(true);
      actionPreFlight->setEnabled(true);
      actionSetupInFlight->setEnabled(true);
      actionToggleLogging->setEnabled(true);
      viewMap->statusBar()->clear(); // remove temporary statusbar messages
      actionToggleWpLabels->setEnabled(true);
      break;
    case wpView:
      viewMap->hide();
      //viewWP->show();
      //viewRP->hide();
      listViewTabs->show();
      setCentralWidget(listViewTabs);
      //setCentralWidget(listViewTabs);
      listViewTabs->showPage(viewWP);
      viewInfo->hide();
      accApView->setEnabled(false);
      accWpView->setEnabled(true);
      accRpView->setEnabled(false);
      accTpView->setEnabled(false);
      accInfoView->setEnabled(false);
      accManualNav->setEnabled(false);
      accGpsNav->setEnabled(false);

      mapMenu->setEnabled(false);
      actionViewWaypoints->setEnabled(false);
      actionViewAirports->setEnabled(false);
      actionViewReachpoints->setEnabled(false);
      actionViewInfo->setEnabled(true);
      actionViewInfo->setAccel(0); //we need to disable the accelerator key, because we can't jump to waypoints with an I otherwise.
      //actionSelectTask->setAccel(0);
      actionViewGPSStatus->setEnabled(false);
      actionSelectTask->setEnabled(false);
      actionRememberWaypoint->setEnabled(false);
      actionToggleMenu->setEnabled(false);
      actionToggleStatusbar->setEnabled(false);
      actionZoomIn->setEnabled(false);
      actionZoomInZ->setEnabled(false);
      actionZoomOut->setEnabled(false);
      actionZoomOutZ->setEnabled(false);
      actionEnsureVisible->setEnabled(false);
      actionToggleLogging->setEnabled(false);
      actionPreFlight->setEnabled(false);
      actionSetupInFlight->setEnabled(false);
      actionToggleWpLabels->setEnabled(false);
      break;
   case rpView:
      viewMap->hide();
      //viewWP->hide();
      //viewRP->show();
      //viewAP->hide();
      //setCentralWidget(viewWP);
      listViewTabs->show();
      setCentralWidget(listViewTabs);
      listViewTabs->showPage(viewRP);
      viewInfo->hide();
      accApView->setEnabled(false);
      accRpView->setEnabled(true);
      accWpView->setEnabled(false);
      accTpView->setEnabled(false);
      accInfoView->setEnabled(false);
      accManualNav->setEnabled(false);
      accGpsNav->setEnabled(false);

      mapMenu->setEnabled(false);
      actionViewWaypoints->setEnabled(false);
      actionViewAirports->setEnabled(false);
      actionViewReachpoints->setEnabled(false);
      actionViewInfo->setEnabled(true);
      actionViewInfo->setAccel(0); //we need to disable the accelerator key, because we can't jump to waypoints with an I otherwise.
      //actionSelectTask->setAccel(0);
      actionViewGPSStatus->setEnabled(false);
      actionSelectTask->setEnabled(false);
      actionRememberWaypoint->setEnabled(false);
      actionToggleMenu->setEnabled(false);
      actionToggleStatusbar->setEnabled(false);
      actionZoomIn->setEnabled(false);
      actionZoomInZ->setEnabled(false);
      actionZoomOut->setEnabled(false);
      actionZoomOutZ->setEnabled(false);
      actionEnsureVisible->setEnabled(false);
      actionToggleLogging->setEnabled(false);
      actionPreFlight->setEnabled(false);
      actionSetupInFlight->setEnabled(false);
      actionToggleWpLabels->setEnabled(false);
      break;
    case apView:
      viewMap->hide();
      //viewWP->hide();
      //viewAP->show();
      //viewRP->hide();
      viewAP->fillWpList();
      //setCentralWidget(viewAP);
      listViewTabs->show();
      setCentralWidget(listViewTabs);
      listViewTabs->showPage(viewAP);
      viewInfo->hide();
      accApView->setEnabled(true);
      accRpView->setEnabled(false);
      accWpView->setEnabled(false);
      accTpView->setEnabled(false);
      accInfoView->setEnabled(false);
      accManualNav->setEnabled(false);
      accGpsNav->setEnabled(false);

      mapMenu->setEnabled(false);
      actionViewWaypoints->setEnabled(false);
      actionViewAirports->setEnabled(false);
      actionViewReachpoints->setEnabled(false);
      actionViewInfo->setEnabled(true);
      actionViewInfo->setAccel(0); //we need to disable the accelerator key, because we can't jump to waypoints with an I otherwise.
      //actionSelectTask->setAccel(0);
      actionViewGPSStatus->setEnabled(false);
      actionSelectTask->setEnabled(false);
      actionRememberWaypoint->setEnabled(false);
      actionToggleMenu->setEnabled(false);
      actionToggleStatusbar->setEnabled(false);
      actionZoomIn->setEnabled(false);
      actionZoomInZ->setEnabled(false);
      actionZoomOut->setEnabled(false);
      actionZoomOutZ->setEnabled(false);
      actionEnsureVisible->setEnabled(false);
      actionToggleLogging->setEnabled(false);
      actionPreFlight->setEnabled(false);
      actionSetupInFlight->setEnabled(false);
      actionToggleWpLabels->setEnabled(false);
      break;
    case tpView:
      //only allow switching to this view if there is anything to see
      if (_globalMapContents->getCurrentTask()==0) 
        return;
        
      viewMap->hide();
      //viewWP->hide();
      //viewAP->show();
      //viewRP->hide();
      viewAP->fillWpList();
      //setCentralWidget(viewAP);
      listViewTabs->show();
      setCentralWidget(listViewTabs);
      listViewTabs->showPage(viewTP);
      viewInfo->hide();
      accApView->setEnabled(false);
      accRpView->setEnabled(false);
      accWpView->setEnabled(false);
      accTpView->setEnabled(true);
      accInfoView->setEnabled(false);
      accManualNav->setEnabled(false);
      accGpsNav->setEnabled(false);

      mapMenu->setEnabled(false);
      actionViewWaypoints->setEnabled(false);
      actionViewAirports->setEnabled(false);
      actionViewReachpoints->setEnabled(false);
      actionViewInfo->setEnabled(true);
      actionViewInfo->setAccel(0); //we need to disable the accelerator key, because we can't jump to waypoints with an I otherwise.
      //actionSelectTask->setAccel(0);
      actionViewGPSStatus->setEnabled(false);
      actionSelectTask->setEnabled(false);
      actionRememberWaypoint->setEnabled(false);
      actionToggleMenu->setEnabled(false);
      actionToggleStatusbar->setEnabled(false);
      actionZoomIn->setEnabled(false);
      actionZoomInZ->setEnabled(false);
      actionZoomOut->setEnabled(false);
      actionZoomOutZ->setEnabled(false);
      actionEnsureVisible->setEnabled(false);
      actionToggleLogging->setEnabled(false);
      actionPreFlight->setEnabled(false);
      actionSetupInFlight->setEnabled(false);
      actionToggleWpLabels->setEnabled(false);
      break;
    case infoView:
      if (viewInfo->showWP(old, wp))
      {
        viewMap->hide();
        //viewWP->hide();
        //viewRP->hide();
        //viewAP->hide();
        listViewTabs->hide();
        viewInfo->show();
        setCentralWidget(viewInfo);
        accApView->setEnabled(false);
        accRpView->setEnabled(false);
        accTpView->setEnabled(false);
        accWpView->setEnabled(false);
        accInfoView->setEnabled(true);
        accManualNav->setEnabled(false);
        accGpsNav->setEnabled(false);

        mapMenu->setEnabled(false);
        actionViewWaypoints->setEnabled(true);
        actionViewAirports->setEnabled(true);
        actionViewReachpoints->setEnabled(true);
        actionViewInfo->setEnabled(false);
        actionViewInfo->setAccel(Key_I); //re-enable acceleraror key
        //actionSelectTask->setAccel(Key_T);
        actionViewGPSStatus->setEnabled(false);
        actionSelectTask->setEnabled(false);
        actionRememberWaypoint->setEnabled(false);
        actionToggleMenu->setEnabled(false);
        actionToggleStatusbar->setEnabled(false);
        actionZoomIn->setEnabled(false);
        actionZoomInZ->setEnabled(false);
        actionZoomOut->setEnabled(false);
        actionZoomOutZ->setEnabled(false);
        actionEnsureVisible->setEnabled(false);
        actionToggleLogging->setEnabled(false);
        actionPreFlight->setEnabled(false);
        actionSetupInFlight->setEnabled(false);
        actionToggleWpLabels->setEnabled(false);
      }
  }
}


/** Switches to mapview. */
void CumulusApp::slotSwitchToMapView(){
  setView(mapView);
}


/** Switches to the WaypointList View */
void CumulusApp::slotSwitchToWPListView(){
  setView(wpView);
}


/** Switches to the AirportList View */
void CumulusApp::slotSwitchToAPListView(){
  setView(apView);
}


/** Switches to the WaypointList View */
void CumulusApp::slotSwitchToReachListView(){
  setView(rpView);
}


/** Switches to the WaypointList View */
void CumulusApp::slotSwitchToTaskListView(){
  setView(tpView);
}


/** This slot is called to switch to the info view. */
void CumulusApp::slotSwitchToInfoView()
{
  //qDebug("CumulusApp::slotSwitchToInfoView()");
  if (view==wpView)
  {
      setView(infoView, viewWP->getSelectedWaypoint());
  }
  if (view==rpView)
  {
      setView(infoView, viewRP->getSelectedWaypoint());
  }
  if (view==apView)
  {
      setView(infoView, viewAP->getSelectedAirfield());
  }
  if (view==tpView)
  {
      setView(infoView, viewTP->getSelectedWaypoint());
  }
  else
  {
    setView(infoView, calculator->getselectedWp());
  }
}


/** @ee This slot is called to switch to the info view with selected waypoint. */
void CumulusApp::slotSwitchToInfoView(wayPoint* wp)
{
  setView(infoView, wp);
}


/** Opens the configdialog. */
void CumulusApp::slotConfig()
{
  ConfigDialog * dlg = new ConfigDialog (this);
  connect(dlg, SIGNAL(settingsChanged()), this, SLOT(slot_readconfig()));

// slot_readconfig already calls calculator->slot_settingschanged
//  connect(dlg, SIGNAL(settingsChanged()), calculator, SLOT(slot_settingschanged()));
  
  dlg->show();
}


/** Opens the inflight glider settings dialog. */
void CumulusApp::slotGliderFlight()
{
  if (_gliderFlightDlg == NULL)
    _gliderFlightDlg = new GliderFlightDialog (this);
  connect(_gliderFlightDlg, SIGNAL(settingsChanged()),calculator, SLOT(slot_settingschanged()));
  _gliderFlightDlg->load();
  _gliderFlightDlg->show();
}


void CumulusApp::slotAltimeterMode()
{
  _altimeterModeDlg->work();
  // qDebug("slotAltimeterMode");
}


void CumulusApp::slotNewAltimeterMode()
{
  viewMap->getAltitudeWidget()->setPreText( _altimeterModeDlg->Pretext() );
  // qDebug("newAltimeterMode");
}


void CumulusApp::slotVarioMode()
{
  _varioModeDlg->load();
  // qDebug("slotVarioMode");
}


/** Shows version and copyright information */
void CumulusApp::slotVersion()
{
  QMessageBox::about (this,
    "Cumulus",
    tr(
    "<qt>"
      "<table cellspacing=0 cellpadding=0 border=0>"
        "<tr>"
          "<th>Cumulus version %1</th>"
        "</tr>"
        "<tr>"
          "<td><font size=-1>(compiled: %2)</font></td>"
        "</tr>"
        "<tr>"
          "<td>&copy; 2002-2005 by</td>"
        "</tr>"
        "<tr>"
          "<td>Andr&eacute; Somers, Eggert Ehmke</td>"
        "</tr>"
        "<tr>"
          "<td>Axel Pauli, Eckhard V&ouml;llm</td>"
        "</tr>"
        "<tr>"
          "<td>Hendrik M&uuml;ller, Florian Ehinger</td>"
        "</tr>"
        "<tr>"
          "<td>Heiner Lamprecht</td>"
        "</tr>"
        "<tr>"
          "<td>"
            "<a href=\"http://cumulus.kflog.org\">http://cumulus.kflog.org</a><br/>"
          "</td>"
        "</tr>"
        "<tr>"
          "<td>Published under the GPL</td>"
        "</tr>"
      "</table>"
    "</qt>").arg(CU_VERSION).arg(QString(__DATE__)));
}


void CumulusApp::slotRememberWaypoint ()
{
  static uint count = 1;
  QString name;

  if (gps->getConnected())
    name = tr("WP%1 %2").arg(count).arg(gps->getLastTime().toString().left(5));
  else
    name = tr("WP%1 %2").arg(count).arg(QTime::currentTime().toString().left(5));

  // @AP: let us check, if user waypoint is already known from its
  // position. In this case we will reject the insertion to avoid senseless
  // duplicates.

  QPoint pos = calculator->getlastPosition();
  QList<wayPoint>* wpList = _globalMapContents->getWaypointList();

  for( uint i=0; i < wpList->count(); i++ )
    {
      wayPoint *wpElem = wpList->at(i);

      if( wpElem->origP == pos )
	{
	  return; // we have it already
	}
    }

  count++;
  wayPoint* wp = new wayPoint;
  wp->name = name;
  wp->origP = calculator->getlastPosition();
  wp->projP = _globalMapMatrix->wgsToMap(wp->origP);
  wp->description = tr("created by user");
  wp->importance = 2; // high to make sure it is visible
  wp->frequency = 0.0;
  wp->runway = 0;
  wp->length = 0;
  AltitudeCollection alt = calculator->getAltitudeCollection();
  wp->elevation = int ((alt.gpsAltitude - alt.gndAltitude).getMeters());
  wp->type = OUTLANDING;
  wp->isLandable = false;
  
  viewWP->slot_wpAdded(wp);
}


/** This slot is called if the configuration has changed and at the start of the program to read the initial configuration. */
void CumulusApp::slot_readconfig()
{
  // @AP: WARNING POPUP crash test statement, please let it commented out here
  // viewMap->_theMap->checkAirspace(calculator->getlastPosition());

  GeneralConfig *conf = GeneralConfig::instance();

  // configure units
  Distance::setUnit( Distance::distanceUnit( conf->getUnitDist() ));
  Speed::setHorizontalUnit( Speed::speedUnit( conf->getUnitSpeed() ));
  Speed::setVerticalUnit( Speed::speedUnit( conf->getUnitVario() ));
  Altitude::setUnit( Altitude::altitude( conf->getUnitAlt() ));
  WGSPoint::setFormat( WGSPoint::Format( conf->getUnitPos() ));

  // other config changes
  viewMap->slot_settingschange();
  calculator->slot_settingschanged();
  _globalMapConfig->slotReadConfig();

  // configure GPS
  QString device = conf->getGpsDevice();

  // @ee we assume only cf card receivers have this device
  if (device == "/dev/ttyS3" || device == "/dev/ttySA3")
  {
    resumeCF (0);
    // @ee install signal handler
    signal (SIGCONT, resumeCF); 
  }

  GPSNMEA::DeliveredAltitude altRef = (GPSNMEA::DeliveredAltitude) conf->getGpsAltitude();
  gps->setDeliveredAltitude( altRef );
  gps->slot_reset();
}


/** Called if the status of the GPS changes, and controls the availability of manual navigation. */
void CumulusApp::slotGpsStatus(GPSNMEA::connectedStatus status)
{
  switch (status) {
    case GPSNMEA::validFix:
      Global::statusMessage(tr("GPS fix established"));
      break;
    case GPSNMEA::noFix:
      Global::statusMessage(tr("GPS connection - no fix"));
      break;
    default:
      Global::statusMessage(tr("GPS lost"));
  }

  playSound();

  if( (status<GPSNMEA::validFix) && (view==mapView) )
    {  // no GPS data
       accManualNav->setEnabled(true);
       accGpsNav->setEnabled(false);
       //actionZoomIn->removeFrom(mapMenu);
       //actionZoomOut->removeFrom(mapMenu);
       //actionZoomInZ->addTo(mapMenu);
       //actionZoomOutZ->addTo(mapMenu);
    }
    else
    {  // GPS data valid
       accManualNav->setEnabled(false);
       accGpsNav->setEnabled(true);
       //actionZoomInZ->removeFrom(mapMenu);
       //actionZoomOutZ->removeFrom(mapMenu);
       //actionZoomIn->addTo(mapMenu);
       //actionZoomOut->addTo(mapMenu);
    }
}


/** This slot is called if the user presses C in manual navigation mode. It centers
  * the map on the current waypoint. */
void CumulusApp::slotCenterToWaypoint(){
  
  if (calculator->getselectedWp()!=0) {
    _globalMapMatrix->centerToLatLon(calculator->getselectedWp()->origP);
    viewMap->_theMap->sceduleRedraw();
    
  }
}


/** Called if the user pressed V in mapview.
  * Adjusts the zoomfactor so that the currently selected waypoint
  * is displayed as good as possible. */
void CumulusApp::slotEnsureVisible(){
  if (calculator->getselectedWp()!=0) {
    double newScale=_globalMapMatrix->ensureVisible(calculator->getselectedWp()->origP);
    if (newScale>0) {
      viewMap->_theMap->slotSetScale(newScale);
    } else {
      Global::statusMessage(tr("Waypoint out of map range."));
    }
  }
}


/** Opens the preflight dialog */
void CumulusApp::slotPreFlight()
{
  _preFlightDialog = new PreFlightDialog(this,"preflightdialog");
  connect( _preFlightDialog, SIGNAL(settingsChanged() ),
           this, SLOT(slotPreFlightDataChanged()) );

  _preFlightDialog->show();
}


/** Opens the gps status dialog */
void CumulusApp::slotGpsStatusDialog()
{
  GpsStatusDialog * gpsd = new GpsStatusDialog(this);

  gpsd->show();
  //delete gpsd;
}


/** Opens the taskselection dialog */
void CumulusApp::slotSelectTask()
{
  _preFlightDialog = new PreFlightDialog(this,"taskselection");

  connect( _preFlightDialog, SIGNAL(settingsChanged() ),
           this, SLOT(slotPreFlightDataChanged()) );

  _preFlightDialog->show();
}


void CumulusApp::slotPreFlightDataChanged()
{
  qDebug("CumulusApp::slotPreFlightDataChanged()");
  viewMap->_theMap->sceduleRedraw();
  setCaption ("Cumulus - " + calculator->gliderType());
  if (_globalMapContents->getCurrentTask()==0)
  {
    listViewTabs->removePage(viewTP);
    actionViewTaskpoints->setEnabled(false);
    _taskListVisible=false;
  }
  else
  {
    if (!_taskListVisible)
    {
      listViewTabs->insertTab(viewTP,tr("Task"),0);
      _taskListVisible=true;
    }
    viewTP->slot_setTask(_globalMapContents->getCurrentTask());
    actionViewTaskpoints->setEnabled(true);
  }
}


/** dynamicly updates view for rechable list */
void CumulusApp::slot_newReachList(){
  //viewRP->fillRpList();
  viewRP->slot_newList(); //let the view know we have a new list
  viewMap->_theMap->quickDraw();
}


bool CumulusApp::eventFilter(QObject *o , QEvent *e) {
  // qDebug("CumulusApp::eventFilter() is called with event type %d", e->type());

  if (e->type() == QEvent::KeyPress)
    {
      QKeyEvent *k=(QKeyEvent*)e;
      qDebug("Keycode of pressed key: %d, %%%X", k->key(), k->key());
      
      // Key_F12 Home (helps ipaq bring up the menu)
      // @AP: Key_F11 for Z under Opie as workaround
      if( k->key() == 4155 || k->key() == Key_M || k->key() == Key_F11 )
        {
          menuBar()->isVisible() ? menuBar()->hide() : menuBar()->show(); 
          return true;
        }
//      if( k->key() == 4152 ) // Key Caleandar 
//        ;
      if( k->key() == 4153 ) // Key Addressbook 
        {
          slotSwitchToWPListView();
          return true;
        }
//      if( k->key() == 4156 ) // Key Mail 
//        ;
  }

  return QWidget::eventFilter( o, e ); // standard event processing;
}


void CumulusApp::slotNavigateHome() {
  calculator->slot_WaypointChange( GeneralConfig::instance()->getHomeWp() );
}
