Subversion Repositories public

Rev

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

//
// C++ Implementation:
//
// Description:
//
//
// Author: Andreas Theofilu <andreas@theosys.at>, (C) 2009
//
// Copyright: See COPYING file that comes with this distribution
//
//

#include <iostream>

#include <QPixmap>
#include <QBitmap>
#include <QDir>
#include <QFile>
#include <QImage>
#include <QtNetwork>
#include <QListWidget>
#include <QPainter>
#include <QCheckBox>
#include <QSlider>
#include <KStandardDirs>
#include <KConfig>
#include <KLocale>
#include <KMessageBox>
#include <KGlobalSettings>
#include <KConfigGroup>
#include <KIconLoader>
#include <KUrl>
#include <KUrlRequester>
#include <KFile>

#include "config.h"

#if defined HAVE_GDAL
   #include <gdal/gdal_priv.h>
   #include <gdal/ogr_spatialref.h>
   #include <gdal/ogrsf_frmts.h>
   #include <gdal/gdalwarper.h>
   #include <gdal/ogrsf_frmts.h>
   #include "GDALError.h"
#endif

#include "wmsselectorwidget.h"
#include "ui_authenticationdialog.h"
#include "wmscapabilitieswidget.h"

// The capital cities from all countries of the world
// Source: Wikipedia, Google
CITIES Cities[] = {
        { " - - - - - - -", 0.0, 0.0 },
        { "Abidjan", 5.3363, -4.0277 },
        { "Abu Dhabi", 24.4758, 54.3714 },
        { "Abuja", 9.0578, 7.4892 },
        { "Accora", 5.5555, -0.196 },
        { "Addis Abeba", 9.0164, 38.7579 },
        { "Algier", 36.7527, 3.0422 },
        { "Amman", 31.9565, 35.9457 },
        { "Amsterdam", 52.3737, 4.8911 },
        { "Andorra la Vella", 42.5074, 1.5219 },
        { "Ankara", 39.9438, 32.856 },
        { "Antananarivo", -18.915, 47.5318 },
        { "Apia", -13.8314, -171.7516 },
        { "Aschgabat", 37.9501, 58.3802 },
        { "Asmara", 15.3324, 38.9261 },
        { "Astana", 51.1798, 71.4466 },
        { "Asuncion", -25.3003, -57.6363 },
        { "Athen", 37.9792, 23.7166 },
        { "Bagdad", 33.3158, 44.3921 },
        { "Baku", 40.4167, 49.8236 },
        { "Bamako", 12.6529, -7.9865 },
        { "Bandar Seri Begawan", 4.9431, 114.9424 },
        { "Bankok", 13.7211, 100.4765 },
        { "Bangui", 4.3616, 18.556 },
        { "Banjul", 13.4548, -16.579 },
        { "Basseterre", 17.2968, -62.7137 },
        { "Beirut", 33.8886, 35.4954 },
        { "Belgrad", 44.8024, 20.4651 },
        { "Belmopan", 17.2617, -88.7785 },
        { "Berlin", 52.5234, 13.4105 },
        { "Bern", 46.9479, 7.4479 },
        { "Bratislava", 48.1483, 17.1068 },
        { "Bridgetown", 13.0935, -59.6106 },
        { "Bruessel", 50.8462, 4.3545 },
        { "Budapest", 47.4984, 19.0403 },
        { "Buenos Aires", -34.6084, -58.3733 },
        { "Bukarest", 44.4304, 26.1225 },
        { "Den Haag", 52.0782, 4.3134 },
        { "Dublin", 53.3441, -6.2677 },
        { "Helsinki", 60.1698, 24.9379 },
        { "Kopenhagen", 55.6762, 12.5678 },
        { "Lissabon", 38.7071, -9.1357 },
        { "Ljubljana", 46.0514, 14.5055 },
        { "London", 51.5001, -0.1262 },
        { "Luxemburg", 49.8152, 6.1286 },
        { "Madrid", 40.4167, -3.7036 },
        { "Mexiko City", 19.427, -99.128 },
        { "Minsk", 53.8996, 27.5753 },
        { "Monaco", 43.7326, 7.4189 },
        { "Moskau", 55.7554, 37.6203 },
        { "Oslo", 59.9136, 10.7394 },
        { "Ottawa", 45.4218, -75.6964 },
        { "Paris", 48.856, 2.3515 },
        { "Peking", 39.9077, 116.3994 },
        { "Prag", 50.088, 14.4217 },
        { "Reykjavik", 64.1352, -21.8951 },
        { "Riga", 56.9462, 24.1049 },
        { "Rom", 41.8945, 12.4826 },
        { "San Marino", 43.9322, 12.4484 },
        { "Sofia", 42.6963, 23.3236 },
        { "Stockholm", 59.3329, 18.0652 },
        { "Tirana", 41.3309, 19.8325 },
        { "Tokio", 35.688, 139.6932 },
        { "Vaduz", 47.1407, 9.5218 },
        { "Valletta", 35.9009, 14.5154 },
        { "Vilnius", 54.6888, 25.2801 },
        { "Warschau", 52.2291, 21.0123 },
        { "Washington D.C.", 38.8917, -77.0239 },
        { "Wien", 48.2091, 16.3727 },
        { "Zagreb", 45.8149, 15.9784 },
        { "", 0.0, 0.0 }
};

ZOOM zoom[] = {
        { 0.014108, 0.003554 },
        { 0.028216, 0.007108 },
        { 0.056432, 0.014216 },
        { 0.112864, 0.028432 },
        { 0.225728, 0.056864 },
        { 0.451456, 0.113728 },
        { 0.902912, 0.227456 },
        { 1.805824, 0.454912 },
        { 3.611648, 0.909824 },
        { 7.223296, 1.819648 }
};

wmsSelectorWidget::wmsSelectorWidget (QWidget* parent, Qt::WFlags fl)
                : QDialog (parent, fl), Ui::wmsSelectorWidgetBase()
{
        // Initialize some variables
        http = 0;
        httpRequestAborted = false;
        progressDialog = 0;
        id = 0;
        Layer = 0;
        firstLayer = 0;
        zLevel = 0;
        initializeParser();
        // Initialize the GUI elements
        setupUi (this);
        // Initialize the environment
        urlWMS->setMode(KFile::File | KFile::ExistingOnly);
        KConfig cfg (QString("sportwatcher.rc"), KConfig::SimpleConfig);
        KConfigGroup ic (&cfg, "WMS");
        urlWMS->setUrl (ic.readEntry("ServerURL", "http://onearth.jpl.nasa.gov/wms.cgi"));
        Data = ic.readEntry("Data", QDir::home().absolutePath() + "/.sportwatcher");
        MAP = ic.readEntry("MAP", QDir::home().absolutePath() + "/.sportwatcher/track.wms");
        file.setFileName(Data + "/capabilities.xml");   // File to save WMS capabilities
        edBands->setValue(ic.readEntry("Bands", 3));
        Layers = ic.readEntry("Layer", QString("modis,global_mosaic"));
        StyleCommas = true;
        cbStyles->setChecked(StyleCommas);
        // Fill the cities combo box
        int i = 0;

        while (!Cities[i].city.isEmpty())
        {
           cbCities->addUrl(KUrl(Cities[i].city));
           i++;
        }

        // Connect the http module
        progressDialog = new KProgressDialog(this);
        http = new QHttp(this);
        connect(http, SIGNAL(requestFinished(int, bool)), this, SLOT(WMSrequestFinished(int, bool)));
        connect(http, SIGNAL(dataReadProgress(int, int)), this, SLOT(updateDataReadProgress(int, int)));
        connect(http, SIGNAL(responseHeaderReceived(const QHttpResponseHeader &)), this, SLOT(readResponseHeader(const QHttpResponseHeader &)));
        connect(http, SIGNAL(authenticationRequired(const QString &, quint16, QAuthenticator *)),
                this, SLOT(slotAuthenticationRequired(const QString &, quint16, QAuthenticator *)));
        connect(progressDialog, SIGNAL(cancelClicked()), this, SLOT(cancelDownload()));
#ifndef QT_NO_OPENSSL
        connect(http, SIGNAL(sslErrors(const QList<QSslError> &)), this, SLOT(sslErrors(const QList<QSslError> &)));
#endif
        getCapabilities();
        Init = true;
}

wmsSelectorWidget::~wmsSelectorWidget()
{
        if (file.exists())
           file.remove();

        destroyErrors();
}

/*$SPECIALIZATION$*/
void wmsSelectorWidget::slotGetCapabilities()
{
        actionLayer->availableListWidget()->clear();
        actionLayer->selectedListWidget()->clear();
        getCapabilities();
}

void wmsSelectorWidget::slotDetails()
{
int i;

        wmsCapabilitiesWidget *dlg = new wmsCapabilitiesWidget(this);
        dlg->setName(Service.Name);
        dlg->setTitle(Service.Title);
        dlg->setAbstract(Service.Abstract);
        dlg->setOnline(Service.OnlineResource);

        dlg->setPerson(Service.ContactPerson);
        dlg->setOrg(Service.ContactOrganisation);
        dlg->setPhone(Service.ContactVoiceTelephone);
        dlg->setFax(Service.ContactFacsimileTelephone);
        dlg->setMail(Service.ContactElectronicMailAddress);

        dlg->setAddress(Service.Address);
        dlg->setCity(Service.City);
        dlg->setState(Service.StateOrProvince);
        dlg->setPostCode(Service.PostCode);
        dlg->setCountry(Service.Country);

        dlg->setCapabilitiesGet(Request.GetCapabilities.Get);
        dlg->setCapabilitiesPost(Request.GetCapabilities.Post);

        if (Request.GetCapabilities.Format.size() > 0)
           dlg->setFormat(Request.GetCapabilities.Format.at(0));

        dlg->setMapGet(Request.GetMap.Get);
        dlg->setMapPost(Request.GetMap.Post);

        for (i = 0; i < Request.GetMap.Format.size(); ++i)
           dlg->addFormats(Request.GetMap.Format.at(i));

        for (i = 0; i < Request.GetFeatureInfo.Format.size(); ++i)
           dlg->addFeatures(Request.GetFeatureInfo.Format.at(i));

        if (firstLayer)
        {
        LAYER *akt = firstLayer;
        QStringList sl;

           while (akt)
           {
              for (i = 0; i < akt->SRS.size(); ++i)
                 sl << akt->SRS.at(i);

              akt = akt->next;
           }

           sl.removeDuplicates();

           for (i = 0; i < sl.size(); ++i)
              dlg->addDate(sl.at(i));
        }

        dlg->exec();
        delete dlg;
}

void wmsSelectorWidget::slotAdded(QListWidgetItem *item)
{
double minx, miny, maxx, maxy;

        setDimension(minx, miny, maxx, maxy, item);
        grabPicture(minx, miny, maxx, maxy);
}

void wmsSelectorWidget::slotRemoved(QListWidgetItem *item)
{
double minx, miny, maxx, maxy;

        setDimension(minx, miny, maxx, maxy, item);
        grabPicture(minx, miny, maxx, maxy);
}

void wmsSelectorWidget::slotUp(QListWidgetItem *item)
{
double minx, miny, maxx, maxy;

        setDimension(minx, miny, maxx, maxy, item);
        grabPicture(minx, miny, maxx, maxy);
}

void wmsSelectorWidget::slotDown(QListWidgetItem *item)
{
double minx, miny, maxx, maxy;

        setDimension(minx, miny, maxx, maxy, item);
        grabPicture(minx, miny, maxx, maxy);
}

void wmsSelectorWidget::slotCities(QString city)
{
int i = 0;
double minx, miny, maxx, maxy;

        while (!Cities[i].city.isEmpty())
        {
           if (Cities[i].city == city)
           {
              edLat->setValue(Cities[i].lat);
              edLon->setValue(Cities[i].lon);
              break;
           }

           i++;
        }

        if (actionLayer->selectedListWidget()->count() > 0)
        {
           setDimension(minx, miny, maxx, maxy, 0);
           grabPicture(minx, miny, maxx, maxy);
        }
}

void wmsSelectorWidget::slotStyles(bool mode)
{
        StyleCommas = mode;
}

void wmsSelectorWidget::slotSliderPressed()
{
        sliderPressed = true;
}

void wmsSelectorWidget::slotSliderReleased()
{
double minx, miny, maxx, maxy;

        sliderPressed = false;

        if (!sliderPressed && actionLayer->selectedListWidget()->count() > 0)
        {
           setDimension(minx, miny, maxx, maxy, 0);
           grabPicture(minx, miny, maxx, maxy);
        }
}

void wmsSelectorWidget::slotValueChanged(int val)
{
double minx, miny, maxx, maxy;

        zLevel = val;

        if (!sliderPressed && actionLayer->selectedListWidget()->count() > 0)
        {
           setDimension(minx, miny, maxx, maxy, 0);
           grabPicture(minx, miny, maxx, maxy);
        }
}

/*
 * This functions try to get a small example picture from the WMS server
 */
bool wmsSelectorWidget::grabPicture(double minx, double miny, double maxx, double maxy)
{
#if defined HAVE_GDAL
QPixmap pm;
GDALDataset *poDataset = 0;
GDALRasterBand *poBand = 0;
unsigned char *pafScanline = 0;
unsigned char *pafScanlineRed = 0;
unsigned char *pafScanlineGreen = 0;
unsigned char *pafScanlineBlue = 0;
unsigned char *pafScanlineAlpha = 0;
int nXSize, nYSize;
int width, height;
bool Fgeo = false;
QPainter paint;

        QApplication::setOverrideCursor (QCursor(Qt::WaitCursor));
        width = lbPreview->width();
        height = lbPreview->height() - 6;       // necessary to prevent growing of dialog window
        nXSize = nYSize = 0;

        if (!writeWMSTag(minx, miny, maxx, maxy, width, height))
        {
           QApplication::restoreOverrideCursor();
           KMessageBox::error(this, i18n("Error writing a tag file!"));
           return false;
        }

        // set the dimensions of the pixmap
        pm = QPixmap(width, height);
        // start painting the map
        paint.begin(&pm);
        QColor background(220, 220, 220);
        paint.fillRect(0, 0, width, height, background);

        if ((poDataset = (GDALDataset *)GDALOpen (MAP.toAscii().constData(), GA_ReadOnly)) != NULL)
        {
           int nRasterCount = poDataset->GetRasterCount();
           int nXBlock, nYBlock;
           GDALColorTable *pCT, *pCTb, *pCTr, *pCTg, *pCTa;

           int             bGotMin, bGotMax;
           int             tTypeLen, tColor, tColorEntrys;
           GDALDataType    tRasterType;
           double          adfMinMax[2];

           pCT = pCTb = pCTr = pCTg = pCTa = 0;
           tTypeLen = 0;
           pafScanlineRed = pafScanlineGreen = pafScanlineBlue = pafScanlineAlpha = 0;
           Fgeo = true;

           for (int a = 1; a <= nRasterCount; a++)
           {
              if (!Fgeo)
                break;

              if (!(poBand = poDataset->GetRasterBand (a)))
              {
                 paint.end();
                 QApplication::restoreOverrideCursor();
                 KMessageBox::error(this, i18n("Error getting a raster band:\n%1").arg(catGDALError()));
        
                 if (pafScanlineRed)
                    delete pafScanlineRed;

                 if (pafScanlineGreen)
                    delete pafScanlineGreen;

                 if (pafScanlineBlue)
                    delete pafScanlineBlue;

                 if (pafScanlineAlpha)
                    delete pafScanlineAlpha;

                 GDALClose (poDataset);
                    poDataset = 0;

                 return false;
              }

              poBand->GetBlockSize (&nXBlock, &nYBlock);
              nXSize = poBand->GetXSize();
              nYSize = poBand->GetYSize();
              tRasterType = poBand->GetRasterDataType ();
              tTypeLen = GDALGetDataTypeSize (tRasterType) / 8; // We need Bytes not Bits!
              tColor = poBand->GetColorInterpretation ();

              adfMinMax[0] = poBand->GetMinimum (&bGotMin);
              adfMinMax[1] = poBand->GetMaximum (&bGotMax);

              if (!(bGotMin && bGotMax))
                 GDALComputeRasterMinMax ((GDALRasterBandH)poBand, TRUE, adfMinMax);

              if ((pCT = poBand->GetColorTable()) != NULL)
                 tColorEntrys = poBand->GetColorTable()->GetColorEntryCount();

              switch (a)
              {
                 case 1: pafScanlineRed   = new unsigned char[tTypeLen * nXSize * nYSize]; pafScanline = pafScanlineRed; pCTr = pCT; break;
                 case 2: pafScanlineGreen = new unsigned char[tTypeLen * nXSize * nYSize]; pafScanline = pafScanlineGreen; pCTg = pCT; break;
                 case 3: pafScanlineBlue  = new unsigned char[tTypeLen * nXSize * nYSize]; pafScanline = pafScanlineBlue; pCTb = pCT; break;
                 case 4: pafScanlineAlpha  = new unsigned char[tTypeLen * nXSize * nYSize]; pafScanline = pafScanlineAlpha; pCTa = pCT; break;
              }

              if (!pafScanline)
              {
                 paint.end();
                 QApplication::restoreOverrideCursor();
                 KMessageBox::error(this, i18n("Not enough memory for a raster operation!"));

                 if (pafScanlineRed)
                    delete pafScanlineRed;

                 if (pafScanlineGreen)
                    delete pafScanlineGreen;

                 if (pafScanlineBlue)
                    delete pafScanlineBlue;

                 if (pafScanlineAlpha)
                    delete pafScanlineAlpha;

                 GDALClose (poDataset);
                    poDataset = 0;

                 return false;
              }

              memset (pafScanline, 0, tTypeLen * nXSize * nYSize);

              /*
               * Get the image (from the server) and put the tiles together.
               *
               * The function reads only one raster band. This is,
               * because the function is called for every raster band and
               * every raster band is stored into a separate array.
               */
              if (poBand->RasterIO (GF_Read, 0, 0, nXSize, nYSize, pafScanline, nXSize, nYSize, tRasterType, 0, 0) == CE_Failure)
              {
                 paint.end();
                 QApplication::restoreOverrideCursor();
                 KMessageBox::error(this, i18n("Error reading a raster band:\n%1").arg(catGDALError()));
                 QApplication::setOverrideCursor (QCursor(Qt::WaitCursor));
                 paint.begin(&pm);
                 Fgeo = false;
                 break;
              }
              else
                 Fgeo = true;
           }

           /*
            * Only if Fgeo is TRUE, we've read successfully all raster
            * bands. Now we have to put the bands together to get
            * an image.
            */
           if (Fgeo)
           {
           unsigned char *pCombinedBytes = new unsigned char[(tTypeLen * nXSize * nYSize * nRasterCount)];
           unsigned char *ptr_dest, *ptr_src;
           int j, x1, y1, a;

              ptr_dest = ptr_src = 0;

              /*
               * We need two nested loops to set the pixels in the wanted
               * order.
               */
              for (a = 0, j = 0; a < (nXSize * nYSize * nRasterCount); a += nRasterCount, j++)
              {
                 int k = a;

                 for (int m = nRasterCount - 1; m >= 0; m--, k++)
                 {
                    unsigned char *pBytes = 0;

                    switch (m)
                    {
                       case 3: pBytes = pafScanlineAlpha; pCT = pCTa; break;
                       case 2: pBytes = pafScanlineBlue; pCT = pCTb; break;
                       case 1: pBytes = pafScanlineGreen; pCT = pCTg; break;
                       default: pBytes = pafScanlineRed; pCT = pCTr;
                    }

                    ptr_dest = pCombinedBytes + k;
                    unsigned char b = pBytes[j];

                    /*
                     * If we have a color table, the pixels are pointers
                     * to the color table. We need to convert them into
                     * 24 bit pixels plus an optional alpha channel.
                     */
                    if (pCT != NULL)
                    {
                       GDALColorEntry ce;
                       unsigned int c = (unsigned int)b;
                       c = pCT->GetColorEntryAsRGB (c, &ce);

                       if  (m == 0) c = ce.c1;
                       if  (m == 1) c = ce.c2;
                       if  (m == 2) c = ce.c3;
                       if  (m == 3) c = ce.c4;

                       b = (unsigned char)c;
                    }

                    ptr_src = &b;
                    memcpy (ptr_dest, ptr_src, 1);
                 }
              }

              x1 = y1 = 0;

              /*
               * The following loop is QT specific! It sets the pixels
               * of the raw image, pixel by pixel. This may be slow, but
               * everything else didn't work :-(
               *
               * FIXME: We need a more effective routine to put the
               *        raw image into QT's "painter" class.
               */
              for (a = 0; a < (nXSize * nYSize * nRasterCount); a += nRasterCount)
              {
                 if (x1 < width && y1 < height)
                 {
                    if (nRasterCount == 3)
                       paint.setPen (QPen(QColor((int)pCombinedBytes[a+2], (int)pCombinedBytes[a+1], (int)pCombinedBytes[a]), Qt::SolidLine));
                    else if (nRasterCount > 3)
                       paint.setPen (QPen(QColor(qRgba((int)pCombinedBytes[a+3], (int)pCombinedBytes[a+2], (int)pCombinedBytes[a+1], (int)pCombinedBytes[a])), Qt::SolidLine));
                    else if (nRasterCount == 2)
                       paint.setPen (QPen(QColor((int)pCombinedBytes[a+1], (int)pCombinedBytes[a], (int)pCombinedBytes[a+1]), Qt::SolidLine));
                    else if (nRasterCount == 1)
                       paint.setPen (QPen(QColor((int)pCombinedBytes[a], (int)pCombinedBytes[a], (int)pCombinedBytes[a]), Qt::SolidLine));

                    paint.drawPoint(x1, y1);
                 }

                 x1++;

                 if (x1 >= nXSize)
                 {
                    x1 = 0;
                    y1++;
                 }
              }

              delete pCombinedBytes;
              pCombinedBytes = 0;
           }

           if (pafScanlineRed)
              delete pafScanlineRed;

           if (pafScanlineGreen)
              delete pafScanlineGreen;

           if (pafScanlineBlue)
              delete pafScanlineBlue;

           if (pafScanlineAlpha)
              delete pafScanlineAlpha;

           GDALClose (poDataset);
              poDataset = 0;
        }
        else
        {
           paint.end();
           lbPreview->setPixmap(pm);
           QApplication::restoreOverrideCursor();
           KMessageBox::error(this, i18n("Error initializing GDAL:\n%1").arg(catGDALError()));
           return false;
        }

        paint.end();
        lbPreview->setPixmap(pm);
        QApplication::restoreOverrideCursor();
#endif
        return true;
}

/*
 * This part is a parser, able to read an XML-file produced by a WMS-server.
 * The file contains informations about the layers and styles the server
 * supports.
 */
bool wmsSelectorWidget::startDocument()
{
        initializeParser();
        Exception.clear();
        WMSVersion.clear();
        element = el2 = el_none;
        attribute = at_none;
        line = 0;
        lcount = 0;
        return true;
}

bool wmsSelectorWidget::startElement( const QString&, const QString&,
                                    const QString& qName,
                                    const QXmlAttributes& att)
{
int index;

        attribute = at_none;

        if (qName.toLower() == QString("wmt_ms_capabilities"))
        {
           element = el_WMT_MS_Capabilities;

           if ((index = att.index(QString("version"))) != -1)
              WMSVersion = att.value(index);
        }
        else if (qName.toLower() == QString("service"))
           element = el_Service;
        else if (qName.toLower() == QString("name"))
           attribute = at_Name;
        else if (qName.toLower() == QString("title"))
           attribute = at_Title;
        else if (qName.toLower() == QString("onlineresource"))
        {
           if (element == el_Service)
           {
              if ((index = att.index(QString("href"))) != -1 || (index = att.index(QString("xlink:href"))) != -1)
                 Service.OnlineResource = att.value(index);

              if ((index = att.index(QString("type"))) != -1)
                 Service.Type = att.value(index);
           }
           else if (element == el_GetCapabilities && el2 == el_Get)
           {
              if ((index = att.index(QString("href"))) != -1 || (index = att.index(QString("xlink:href"))) != -1)
                 Request.GetCapabilities.Get = att.value(index);
           }
           else if (element == el_GetCapabilities && el2 == el_Post)
           {
              if ((index = att.index(QString("href"))) != -1 || (index = att.index(QString("xlink:href"))) != -1)
                 Request.GetCapabilities.Post = att.value(index);
           }
           else if (element == el_GetMap && el2 == el_Get)
           {
              if ((index = att.index(QString("href"))) != -1 || (index = att.index(QString("xlink:href"))) != -1)
                 Request.GetMap.Get = att.value(index);
           }
           else if (element == el_GetMap && el2 == el_Post)
           {
              if ((index = att.index(QString("href"))) != -1 || (index = att.index(QString("xlink:href"))) != -1)
                 Request.GetMap.Post = att.value(index);
           }
           else if (element == el_GetFeatureInfo && el2 == el_Get)
           {
              if ((index = att.index(QString("href"))) != -1 || (index = att.index(QString("xlink:href"))) != -1)
                 Request.GetFeatureInfo.Get = att.value(index);
           }
           else if (element == el_GetFeatureInfo && el2 == el_Post)
           {
              if ((index = att.index(QString("href"))) != -1 || (index = att.index(QString("xlink:href"))) != -1)
                 Request.GetFeatureInfo.Post = att.value(index);
           }
        }
        else if (qName.toLower() == QString("contactinformation"))
           element = el_ContactInformation;
        else if (qName.toLower() == QString("contactpersonprimary"))
           element = el_ContactPersonPrimary;
        else if (qName.toLower() == QString("contactperson"))
           attribute = at_ContactPerson;
        else if (qName.toLower() == QString("contactorganization"))
           attribute = at_ContactOrganisation;
        else if (qName.toLower() == QString("contactposition"))
           attribute = at_ContactPosition;
        else if (qName.toLower() == QString("contactaddress"))
           element = el_ContactAddress;
        else if (qName.toLower() == QString("addresstype"))
           attribute = at_AddressType;
        else if (qName.toLower() == QString("address"))
           attribute = at_Address;
        else if (qName.toLower() == QString("city"))
           attribute = at_City;
        else if (qName.toLower() == QString("stateorprovince"))
           attribute = at_StateOrProvince;
        else if (qName.toLower() == QString("postcode"))
           attribute = at_PostCode;
        else if (qName.toLower() == QString("country"))
           attribute = at_Country;
        else if (qName.toLower() == QString("contactvoicetelephone"))
           attribute = at_ContactVoiceTelephone;
        else if (qName.toLower() == QString("contactfacsimiletelephone"))
           attribute = at_ContactFacsimileTelephone;
        else if (qName.toLower() == QString("contactelectronicmailaddress"))
           attribute = at_ContactElectronicMailAddress;
        else if (qName.toLower() == QString("fees"))
           attribute = at_Fees;
        else if (qName.toLower() == QString("accessconstraints"))
           attribute = at_AccessConstraints;
        else if (qName.toLower() == QString("capability"))
           element = el_Capability;
        else if (qName.toLower() == QString("request"))
           element = el_Request;
        else if (qName.toLower() == QString("getcapabilities"))
           element = el_GetCapabilities;
        else if (qName.toLower() == QString("format"))
           attribute = at_Format;
        else if (qName.toLower() == QString("dcptype"))
           el2 = el_DCPType;
        else if (qName.toLower() == QString("http"))
           el2 = el_HTTP;
        else if (qName.toLower() == QString("get"))
           el2 = el_Get;
        else if (qName.toLower() == QString("post"))
           el2 = el_Post;
        else if (qName.toLower() == QString("getmap"))
           element = el_GetMap;
        else if (qName.toLower() == QString("getfeatureinfo"))
           element = el_GetFeatureInfo;
        else if (qName.toLower() == QString("exception"))
           element = el_Exception;
        else if (qName.toLower() == QString("layer"))
        {
        LAYER *akt;

           element = el_Layer;
           lcount++;
           akt = allocateLayer();

           if (firstLayer == 0)
              firstLayer = akt;

           if ((index = att.index(QString("opaque"))) != -1)
              akt->opaque = (att.value(index).toInt() == 0) ? false : true;

           if ((index = att.index(QString("noSubsets"))) != -1)
              akt->noSubsets = (att.value(index).toInt() == 0) ? false : true;

           if ((index = att.index(QString("queryable"))) != -1)
              akt->queryable = (att.value(index).toInt() == 0) ? false : true;

           if ((index = att.index(QString("cascaded"))) != -1)
              akt->cascaded = (att.value(index).toInt() == 0) ? false : true;
        }
        else if (qName.toLower() == QString("srs"))
           attribute = at_SRS;
        else if (qName.toLower() == QString("crs"))
           attribute = at_CRS;
        else if (qName.toLower() == QString("abstract"))
           attribute = at_Abstract;
        else if (qName.toLower() == QString("latlonboundingbox"))
        {
           if (lcount < 1)
           {
              KMessageBox::error(this, i18n("Error at line %1: Element LatLonBoundingBox was found outside of a Layer element!").arg(line));
              return false;
           }

           if (!Layer || !firstLayer)
           {
              KMessageBox::error(this, i18n("Fatal error at line %1: Layer was not initialized!").arg(line));
              return false;
           }

           if ((index = att.index(QString("maxx"))) != -1)
              Layer->LatLon.maxx = att.value(index).toDouble();

           if ((index = att.index(QString("maxy"))) != -1)
              Layer->LatLon.maxy = att.value(index).toDouble();

           if ((index = att.index(QString("minx"))) != -1)
              Layer->LatLon.minx = att.value(index).toDouble();

           if ((index = att.index(QString("miny"))) != -1)
              Layer->LatLon.miny = att.value(index).toDouble();
        }
        else if (qName.toLower() == QString("boundingbox"))
        {
           if (lcount < 1)
           {
              KMessageBox::error(this, i18n("Error at line %1: Element BoundingBox was found outside of a Layer element!").arg(line));
              return false;
           }

           if (!Layer || !firstLayer)
           {
              KMessageBox::error(this, i18n("Fatal error at line %1: Layer was not initialized!").arg(line));
              return false;
           }

           if ((index = att.index(QString("maxx"))) != -1)
              Layer->Bounding.maxx = att.value(index).toDouble();

           if ((index = att.index(QString("maxy"))) != -1)
              Layer->Bounding.maxy = att.value(index).toDouble();

           if ((index = att.index(QString("minx"))) != -1)
              Layer->Bounding.minx = att.value(index).toDouble();

           if ((index = att.index(QString("miny"))) != -1)
              Layer->Bounding.miny = att.value(index).toDouble();

           if ((index = att.index(QString("srs"))) != -1)
              Layer->Bounding.SRS = att.value(index);
        }
        else if (qName.toLower() == QString("metadataurl"))
           element = el_MetadataURL;
        else if (qName.toLower() == QString("legendurl"))
           element = el_LegendURL;
        else if (qName.toLower() == QString("style"))
        {
           element = el_Style;

           if (!Layer || !firstLayer)
           {
              KMessageBox::error(this, i18n("Fatal error at line %1: Layer was not initialized!").arg(line));
              return false;
           }

           if (!Layer->style)
              Layer->style = allocateStyle();
           else
           {
           STYLE *akt = findLastStyle(Layer);

              akt->next = allocateStyle();
           }
        }
        else if (qName.toLower() == QString("scalehint"))
        {
           if (lcount < 1)
           {
              KMessageBox::error(this, i18n("Error at line %1: Element ScaleHint was found outside of a Layer element!").arg(line));
              return false;
           }

           if (!Layer || !firstLayer)
           {
              KMessageBox::error(this, i18n("Fatal error at line %1: Layer was not initialized!").arg(line));
              return false;
           }

           if ((index = att.index(QString("min"))) != -1)
              Layer->scaleMin = att.value(index).toDouble();

           if ((index = att.index(QString("max"))) != -1)
              Layer->scaleMax = att.value(index).toDouble();
        }

        return true;
}

bool wmsSelectorWidget::endElement( const QString&, const QString&, const QString& qName)
{
        attribute = at_none;

        if (qName.toLower() == QString("wmt_ms_Capabilities"))
           element = el_none;
        else if (qName.toLower() == QString("service"))
           element = el_WMT_MS_Capabilities;
        else if (qName.toLower() == QString("keywordlist"))
           element = el_Service;
        else if (qName.toLower() == QString("contactinformation"))
           element = el_Service;
        else if (qName.toLower() == QString("contactpersonprimary"))
           element = el_ContactInformation;
        else if (qName.toLower() == QString("contactaddress"))
           element = el_ContactInformation;
        else if (qName.toLower() == QString("capability"))
           element = el_WMT_MS_Capabilities;
        else if (qName.toLower() == QString("request"))
           element = el_Capability;
        else if (qName.toLower() == QString("getcapabilities"))
           element = el_Request;
        else if (qName.toLower() == QString("dcptype"))
           el2 = el_none;
        else if (qName.toLower() == QString("http"))
           el2 = el_DCPType;
        else if (qName.toLower() == QString("get"))
           el2 = el_HTTP;
        else if (qName.toLower() == QString("post"))
           el2 = el_HTTP;
        else if (qName.toLower() == QString("getmap"))
           element = el_Request;
        else if (qName.toLower() == QString("getfeatureinfo"))
           element = el_Request;
        else if (qName.toLower() == QString("exception"))
           element = el_Capability;
        else if (qName.toLower() == QString("layer"))
        {
           lcount--;

           if (lcount == 0)
              element = el_Capability;
           else
              element = el_Layer;
        }
        else if (qName.toLower() == QString("metadataurl"))
           element = el_Layer;
        else if (qName.toLower() == QString("legendurl"))
           element = el_Layer;
        else if (qName.toLower() == QString("style"))
           element = el_Layer;

        return true;
}

bool wmsSelectorWidget::characters (const QString& chraw)
{
        if (chraw.at(0) == QChar('\n'))
        {
           line++;
           return true;
        }

        QString ch = chraw.trimmed();

        if (ch.length() == 0)
           return true;

        if (element == el_Service || element == el_ContactInformation ||
            element == el_ContactPersonPrimary || element == el_ContactAddress)
        {
           if (attribute == at_Name)
              Service.Name = ch;
           else if (attribute == at_Title)
              Service.Title = ch;
           else if (attribute == at_Abstract)
              Service.Abstract = ch;
           else if (attribute == at_ContactPerson)
              Service.ContactPerson = ch;
           else if (attribute == at_ContactOrganisation)
              Service.ContactOrganisation = ch;
           else if (attribute == at_ContactElectronicMailAddress)
              Service.ContactElectronicMailAddress = ch;
           else if (attribute == at_ContactPosition)
              Service.ContactPosition = ch;
           else if (attribute == at_AddressType)
              Service.AddressType = ch;
           else if (attribute == at_Address)
              Service.Address = ch;
           else if (attribute == at_City)
              Service.City = ch;
           else if (attribute == at_StateOrProvince)
              Service.StateOrProvince = ch;
           else if (attribute == at_PostCode)
              Service.PostCode = ch;
           else if (attribute == at_Country)
              Service.Country = ch;
           else if (attribute == at_ContactVoiceTelephone)
              Service.ContactVoiceTelephone = ch;
           else if (attribute == at_ContactFacsimileTelephone)
              Service.ContactFacsimileTelephone = ch;
           else if (attribute == at_Fees)
              Service.Fees = ch;
           else if (attribute == at_AccessConstraints)
              Service.AccessConstraints = ch;
        }
        else if (element == el_GetCapabilities)
        {
           if (attribute == at_Format)
              Request.GetCapabilities.Format << ch;
        }
        else if (element == el_GetMap)
        {
           if (attribute == at_Format)
              Request.GetMap.Format << ch;
        }
        else if (element == el_GetFeatureInfo)
        {
           if (attribute == at_Format)
              Request.GetFeatureInfo.Format << ch;
        }
        else if (element == el_Exception)
        {
           if (attribute == at_Format)
              Exception << ch;
        }
        else if (element == el_Layer)
        {
           if (attribute == at_Name)
              Layer->Name = ch;
           else if (attribute == at_Title)
              Layer->Title = ch;
           else if (attribute == at_Abstract)
              Layer->Abstract = ch;
           else if (attribute == at_SRS)
              Layer->SRS << ch;
           else if (attribute == at_CRS)
              Layer->CRS << ch;
        }
        else if (element == el_Style)
        {
        STYLE *akt = findLastStyle(Layer);

           if (!Layer->style)
           {
              Layer->style = allocateStyle();
              akt = Layer->style;
           }

           if (!akt)
           {
              KMessageBox::error(this, i18n("Fatal error at line %1: No, or unable to allocate memory for a style!").arg(line));
              return false;
           }

           if (attribute == at_Name)
              akt->Name = ch;
           else if (attribute == at_Title)
              akt->Title = ch;
        }

        return true;
}

void wmsSelectorWidget::getCapabilities()
{
        if (file.exists())
           file.remove();

        if (!file.open(QIODevice::WriteOnly))
        {
           KMessageBox::information(this,
                i18n("Unable to save the file %1: %2.").arg(file.fileName()).arg(file.errorString()),
                i18n("WMS capabilities"));

           return;
        }

#ifndef QT_NO_OPENSSL
        QHttp::ConnectionMode mode = (urlWMS->url().protocol().toLower() == "https") ? QHttp::ConnectionModeHttps : QHttp::ConnectionModeHttp;
#else
        QHttp::ConnectionMode mode = QHttp::ConnectionModeHttp;
#endif
        http->setHost(urlWMS->url().host(), mode, (urlWMS->url().port() == -1) ? 0 : urlWMS->url().port());

        if (!urlWMS->url().user().isEmpty())
           http->setUser(urlWMS->url().user(), urlWMS->url().pass());

        httpRequestAborted = false;
        id = http->get(urlWMS->url().url() + "?VERSION=1.1.1&REQUEST=GetCapabilities&SERVICE=WMS", &file);
        // Show a progress dialog
        progressDialog->setVisible(true);
        progressDialog->setWindowTitle(i18n("Getting capabilities"));
        progressDialog->setLabelText(i18n("Downloading capabilities."));
}

bool wmsSelectorWidget::parseWMS()
{
QXmlSimpleReader reader;
LAYER *aktLayer;

        QXmlInputSource source (&file);
        reader.setContentHandler (this);
        reader.parse (source);

        // Put the result into the elements of the mask
        aktLayer = firstLayer;

        while (aktLayer)
        {
           if (!aktLayer->Name.isEmpty())       // Do we have a valid layer?
              actionLayer->availableListWidget()->addItem(aktLayer->Name);

           aktLayer = aktLayer->next;
        }

        return true;
}

QString wmsSelectorWidget::getLayers()
{
QString la;
QListWidget *lw = actionLayer->selectedListWidget();

        for (int i = 0; i < lw->count(); i++)
        {
           QListWidgetItem *item = lw->item(i);
           la += item->text();

           if (i < lw->count())
              la += ",";
        }

        return la;
}

QString wmsSelectorWidget::getStyles()
{
QString la;
QListWidget *lw = actionLayer->selectedListWidget();
int anz = lw->count();

        if (cbStyles->isChecked() && anz > 1)
           la.fill(',', anz - 1);

        return la;
}

void wmsSelectorWidget::cancelDownload()
{
        httpRequestAborted = true;
        http->abort();
}

void wmsSelectorWidget::WMSrequestFinished(int requestId, bool error)
{
        if (requestId != id)
           return;

        if (httpRequestAborted)
        {
           file.close();
           file.remove();
           progressDialog->hide();
           return;
        }

        progressDialog->hide();
        file.close();

        if (error)
        {
           file.remove();
           KMessageBox::information(this, i18n("Download failed: %1.").arg(http->errorString()), i18n("WMS capabilities"));
        }
        else
        {
           parseWMS();
        
           if (Init)
           {
              // Set the already selected layers to the selected box
              // This will be done only, if the box with the available layers
              // is not empty. Otherwise we've to assume, that there was an
              // error getting the capabilities of the server.
              if (actionLayer->availableListWidget()->count() > 0)
              {
              QListWidget *item = actionLayer->selectedListWidget();
              QListWidget *av = actionLayer->availableListWidget();
              QStringList laList = Layers.split(',');

                 for (int i = 0; i < laList.size(); i++)
                 {
                    QList<QListWidgetItem*> qlwi = av->findItems(laList.at(i), Qt::MatchExactly);

                    if (qlwi.size() == 1)
                    {
                       item->addItem(laList.at(i));
                       av->takeItem(av->row(qlwi.at(0)));
                    }
                 }
              }

              Init = false;
           }
        }
}

void wmsSelectorWidget::readResponseHeader(const QHttpResponseHeader &responseHeader)
{
        switch (responseHeader.statusCode())
        {
           case 200:                   // Ok
           case 301:                   // Moved Permanently
           case 302:                   // Found
           case 303:                   // See Other
           case 307:                   // Temporary Redirect
                // these are not error conditions
           break;

           default:
              KMessageBox::information(this,
                i18n("Download failed: %1.").arg(responseHeader.reasonPhrase()),
                i18n("WMS capabilities"));
                httpRequestAborted = true;
                progressDialog->hide();
                http->abort();
        }
}

void wmsSelectorWidget::updateDataReadProgress(int bytesRead, int totalBytes)
 {
        if (httpRequestAborted)
           return;

        progressDialog->progressBar()->setMaximum(totalBytes);
        progressDialog->progressBar()->setValue(bytesRead);
 }

void wmsSelectorWidget::slotAuthenticationRequired(const QString &hostName, quint16, QAuthenticator *authenticator)
{
QDialog dlg;
Ui::Dialog ui;

        ui.setupUi(&dlg);
        dlg.adjustSize();
        ui.siteDescription->setText(i18n("%1 at %2").arg(authenticator->realm()).arg(hostName));

        if (dlg.exec() == QDialog::Accepted)
        {
           authenticator->setUser(ui.userEdit->text());
           authenticator->setPassword(ui.passwordEdit->text());
        }
}

#ifndef QT_NO_OPENSSL
void wmsSelectorWidget::sslErrors(const QList<QSslError> &errors)
{
QString errorString;

        foreach (const QSslError &error, errors)
        {
           if (!errorString.isEmpty())
              errorString += ", ";

           errorString += error.errorString();
        }

        if (KMessageBox::warningContinueCancel(this,
                i18n("One or more SSL errors has occurred: %1").arg(errorString),
                i18n("WMS capabilities")) == KMessageBox::Continue)
        {
           http->ignoreSslErrors();
        }
}
#endif

void wmsSelectorWidget::initializeParser()
{
LAYER *aktLayer;

        Service.Name.clear();
        Service.Title.clear();
        Service.Abstract.clear();
        Service.OnlineResource.clear();
        Service.Type.clear();
        Service.ContactPerson.clear();
        Service.ContactOrganisation.clear();
        Service.ContactPosition.clear();
        Service.AddressType.clear();
        Service.Address.clear();
        Service.City.clear();
        Service.StateOrProvince.clear();
        Service.PostCode.clear();
        Service.Country.clear();
        Service.ContactVoiceTelephone.clear();
        Service.ContactFacsimileTelephone.clear();
        Service.ContactElectronicMailAddress.clear();
        Service.Fees.clear();
        Service.AccessConstraints.clear();

        Request.GetCapabilities.Format.clear();
        Request.GetCapabilities.Get.clear();
        Request.GetCapabilities.Post.clear();
        
        Request.GetMap.Format.clear();
        Request.GetMap.Get.clear();
        Request.GetMap.Post.clear();

        Request.GetFeatureInfo.Format.clear();
        Request.GetFeatureInfo.Get.clear();
        Request.GetFeatureInfo.Post.clear();

        if (Layer)
        {
        LAYER *nl;

           aktLayer = Layer;

           while (aktLayer)
           {
              aktLayer->opaque = false;
              aktLayer->noSubsets = false;
              aktLayer->queryable = false;
              aktLayer->cascaded = false;
              aktLayer->Name.clear();
              aktLayer->Title.clear();
              aktLayer->Abstract.clear();
              aktLayer->SRS.clear();
              aktLayer->LatLon.maxx = 0.0;
              aktLayer->LatLon.maxy = 0.0;
              aktLayer->LatLon.minx = 0.0;
              aktLayer->LatLon.miny = 0.0;
              aktLayer->Bounding.maxx = 0.0;
              aktLayer->Bounding.maxy = 0.0;
              aktLayer->Bounding.minx = 0.0;
              aktLayer->Bounding.miny = 0.0;
              aktLayer->scaleMin = 0.0;
              aktLayer->scaleMax = 0.0;

              if (aktLayer->style)
              {
              STYLE *ns, *akt;

                 akt = aktLayer->style;

                 while (akt)
                 {
                    akt->Name.clear();
                    akt->Title.clear();
                    akt->Format.clear();
                    akt->LegendURL.clear();
                    ns = akt->next;
                    delete akt;
                    akt = ns;
                 }

                 aktLayer->style = 0;
              }

              nl = aktLayer->next;
              delete aktLayer;
              aktLayer = nl;
           }

           Layer = 0;
           firstLayer = 0;
        }
}

LAYER *wmsSelectorWidget::allocateLayer()
{
LAYER *aktLayer, *last;

        if (Layer)
        {
           last = Layer;

           while (last)
           {
              if (!last->next)
                 break;

              last = last->next;
           }

           aktLayer = new LAYER;
           aktLayer->next = 0;
           last->next = aktLayer;
           Layer = aktLayer;
        }
        else
        {
           aktLayer = new LAYER;
           aktLayer->next = 0;
           Layer = last = firstLayer = aktLayer;
        }
        
        aktLayer->opaque = false;
        aktLayer->noSubsets = false;
        aktLayer->queryable = false;
        aktLayer->cascaded = false;
        aktLayer->Name.clear();
        aktLayer->Title.clear();
        aktLayer->Abstract.clear();
        aktLayer->SRS.clear();
        aktLayer->LatLon.maxx = 0.0;
        aktLayer->LatLon.maxy = 0.0;
        aktLayer->LatLon.minx = 0.0;
        aktLayer->LatLon.miny = 0.0;
        aktLayer->LatLon.SRS.clear();
        aktLayer->Bounding.maxx = 0.0;
        aktLayer->Bounding.maxy = 0.0;
        aktLayer->Bounding.minx = 0.0;
        aktLayer->Bounding.miny = 0.0;
        aktLayer->Bounding.SRS.clear();
        aktLayer->scaleMin = 0.0;
        aktLayer->scaleMax = 0.0;
        aktLayer->style = 0;
        return aktLayer;
}

STYLE *wmsSelectorWidget::allocateStyle()
{
STYLE *akt;

        akt = new STYLE;
        akt->Name.clear();
        akt->Title.clear();
        akt->Format.clear();
        akt->LegendURL.clear();
        akt->next = 0;
        return akt;
}

STYLE *wmsSelectorWidget::findLastStyle(LAYER *l)
{
STYLE *akt;

        if (!l)
           return 0;

        akt = l->style;

        while (akt)
        {
           if (!akt->next)
              return akt;

           akt = akt->next;
        }

        return 0;
}

bool wmsSelectorWidget::writeWMSTag(double llat, double llon, double rlat, double rlon, int width, int height)
{
#if defined HAVE_GDAL
QFile fl(MAP);
QString xml, s, srs, crs, styles, bSize, ext;
QDir dir = QDir::home();
QString path = dir.absolutePath();
QStringList sl;
//int item;
double _llat, _llon, _rlat, _rlon;

        if (!fl.open(QIODevice::ReadWrite | QIODevice::Truncate))
        {
           KMessageBox::error (this, i18n("Error opening or creating the WMS tag file!\nPlease check file name and/or permissions."));
           return false;
        }

        KConfig cfg (QString("sportwatcher.rc"), KConfig::SimpleConfig);
        KConfigGroup wms (&cfg, "WMS");

        xml = "<GDAL_WMS>\n";
        xml += "   <Service name=\"WMS\">\n";

        if (!WMSVersion.isEmpty())
           xml += "      <Version>" + WMSVersion + "</Version>\n";
        else
           xml += "      <Version>1.1.1</Version>\n";

        xml += "      <ServerURL>" + urlWMS->url().url() + "?</serverURL>\n";
        _llon = llon;
        _llat = llat;
        _rlon = rlon;
        _rlat = rlat;

        if (firstLayer)
        {
        LAYER *akt = firstLayer;

           while (akt)
           {
              for (int i = 0; i < akt->SRS.size(); ++i)
                 sl << akt->SRS.at(i);

              akt = akt->next;
           }

           sl.removeDuplicates();

           if (sl.contains("EPSG:4326") || sl.contains("WGS:84"))
              srs = QString("EPSG:4326");
           else
              srs = sl.at(0);
        }
        else
           srs = QString("EPSG:4326");

        xml += "      <SRS>" + srs + "</SRS>\n";

        if (firstLayer && firstLayer->CRS.size())
        {
        LAYER *akt = firstLayer;

           sl.clear();

           while (akt)
           {
              for (int i = 0; i < akt->CRS.size(); ++i)
                 sl << akt->CRS.at(i);

              akt = akt->next;
           }

           sl.removeDuplicates();

           if (sl.contains("EPSG:4326") || sl.contains("CRS:84"))
              crs = QString("EPSG:4326");
           else
              crs = sl.at(0);
        }
        else
           crs = QString("EPSG:4326");

        xml += "      <CRS>" + crs + "</CRS>\n";
        xml += "      <ImageFormat>image/";
        xml += "png";
        ext = QString(".png");
        xml += "</ImageFormat>\n";

        xml += "      <Layers>";
        QListWidget *lw = actionLayer->selectedListWidget();
        s.clear();

        for (int i = 0; i < lw->count(); i++)
        {
        QListWidgetItem *lwi;

           if (i > 0 && i < lw->count())
           {
              xml += ",";
              s += ",";
           }

           lwi = lw->item(i);
           xml += lwi->text();
        }

        xml += "</Layers>\n";

        if (StyleCommas)
           xml += "      <Styles>" + s + "</Styles>\n";
        else
           xml += "      <Styles></Styles>\n";

        xml += "      <BBoxOrder>xyXY</BBoxOrder>\n";
        xml += "   </Service>\n";
        xml += "   <DataWindow>\n";
        s.sprintf ("%f", _llat);
        xml += "      <UpperLeftX>" + s + "</UpperLeftX>\n";
        s.sprintf ("%f", _llon);
        xml += "      <UpperLeftY>" + s + "</UpperLeftY>\n";
        s.sprintf ("%f", _rlat);
        xml += "      <LowerRightX>" + s + "</LowerRightX>\n";
        s.sprintf ("%f", _rlon);
        xml += "      <LowerRightY>" + s + "</LowerRightY>\n";
        s.sprintf ("%d", width);
        xml += "      <SizeX>" + s + "</SizeX>\n";
        s.sprintf ("%d", height);
        xml += "      <SizeY>" + s + "</SizeY>\n";
        xml += "   </DataWindow>\n";

        xml += "   <Projection>" + srs + "</Projection>\n";
        xml += "   <BandsCount>" + QString("%1").arg(edBands->value()) + "</BandsCount>\n";
/*      item = wms.readEntry("Tile", 2);

        switch (item)
        {
           case 0: bSize = QString("64"); break;
           case 1: bSize = QString("128"); break;
           case 2: bSize = QString("256"); break;
           case 3: bSize = QString("512"); break;
           case 4: bSize = QString("1024"); break;
           default: bSize = QString("256");
        }
*/
        bSize = QString("256");
        xml += "   <BlockSizeX>" + bSize + "</BlockSizeX>\n";
        xml += "   <BlockSizeY>" + bSize + "</BlockSizeY>\n";
        xml += "   <OverviewCount>" + wms.readEntry("Overview", QString("10")) + "</OverviewCount>\n";
        xml += "   <Cache>\n";
        xml += "      <Path>" + path + "/.gdalwmscache" + "</Path>\n";
        xml += "      <Depth>" + wms.readEntry("Depth", QString("2")) + "</Depth>\n";
        xml += "      <Extension>" + ext + "</Extension>\n";
        xml += "   </Cache>\n";
        QString adv((wms.readEntry("Advice", true)) ? "true" : "false");
        QString ver((wms.readEntry("Verify", false)) ? "true" : "false");

        xml += "   <OfflineMode>false</OfflineMode>\n";
        xml += "   <AdviseRead>" + adv + "</AdviseRead>\n";
        xml += "   <VerifyAdviseRead>" + ver + "</VerifyAdviseRead>\n";
        xml += "</GDAL_WMS>\n";

        write (fl.handle(), xml.toAscii().data(), strlen (xml.toAscii().data()));
        fl.close();
#endif
        return true;
}

void wmsSelectorWidget::setDimension(double &minx, double &miny, double &maxx, double &maxy, QListWidgetItem *item = 0)
{
double cx, cy, levX, levY;
LAYER *akt;

        cx = cy = 0.0;
        akt = firstLayer;

        if (zLevel >= 0 && zLevel < 10)
        {
           levX = zoom[zLevel].x;
           levY = zoom[zLevel].y;
        }
        else
        {
           levX = zoom[0].x;
           levY = zoom[0].y;
        }

        cx = edLat->value();
        cy = edLon->value();

        if (cx == 0.0 && cy == 0.0)
        {
           while (akt)
           {
              cx = akt->LatLon.minx + (akt->LatLon.maxx - akt->LatLon.minx) / 2.0;
              cy = akt->LatLon.miny + (akt->LatLon.maxy - akt->LatLon.miny) / 2.0;

              if ((cx != 0.0 || cy != 0.0) && !item)
                 break;

              if (item && item->text() == akt->Name && cx != 0.0 && cy != 0.0)
                 break;

              akt = akt->next;
           }

           if (cx == 0.0 && cy == 0.0)
           {    // Schloss Schoenbrunn in Vienna
              cx = 16.298223 + (0.014108 / 2.0);
              cy = 48.177103 + (0.003554 / 2.0);
           }

           edLat->setValue(cx);
           edLon->setValue(cy);
        }

        minx = cx - (levX / 2.0);
        maxx = cx + (levX / 2.0);
        miny = cy + (levY / 2.0);
        maxy = cy - (levY / 2.0);
}

#include "wmsselectorwidget.moc"