1
/***************************************************************************
2
qgsmapserverexport.cpp - Export QGIS MapCanvas to MapServer
3
--------------------------------------
5
Copyright : (C) 2003 by Gary E.Sherman
6
email : sherman at mrcc.com
7
***************************************************************************
9
* This program is free software; you can redistribute it and/or modify *
10
* it under the terms of the GNU General Public License as published by *
11
* the Free Software Foundation; either version 2 of the License, or *
12
* (at your option) any later version. *
14
***************************************************************************/
15
/* $Id: qgsmapserverexport.cpp 6816 2007-03-18 11:43:41Z homann $ */
17
#include "qgsmapserverexport.h"
20
#include "qgsdatasourceuri.h"
21
#include "qgshelpviewer.h"
22
#include "qgsmapcanvas.h"
23
#include "qgsmaplayer.h"
25
#include "qgsvectorlayer.h"
26
#include "qgsvectordataprovider.h"
28
#include <QFileDialog>
30
#include <QMessageBox>
36
QgsMapserverExport::QgsMapserverExport(QgsMapCanvas * _map, QWidget * parent, Qt::WFlags fl)
37
: QDialog(parent, fl), map(_map)
40
connect(buttonOk, SIGNAL(clicked()), this, SLOT(accept()));
41
connect(buttonCancel, SIGNAL(clicked()), this, SLOT(reject()));
42
// These values shouldn't be translated, the units should be in english in the map file
43
// Qt designer adds translate() by default
44
cmbMapUnits->addItem(QString::fromUtf8("dd"));
45
cmbMapUnits->addItem(QString::fromUtf8("feet"));
46
cmbMapUnits->addItem(QString::fromUtf8("meters"));
47
cmbMapUnits->addItem(QString::fromUtf8("miles"));
48
cmbMapUnits->addItem(QString::fromUtf8("inches"));
49
cmbMapUnits->addItem(QString::fromUtf8("kilometers"));
53
QgsMapserverExport::~QgsMapserverExport()
57
// Get the base name for the map file
58
QString QgsMapserverExport::baseName()
60
QFileInfo fi(txtMapFilePath->text());
61
return fi.baseName(true);
65
bool QgsMapserverExport::write()
68
//QMessageBox::information(0,"Full Path",fullPath);
70
// Check for file and prompt for overwrite if it exists
71
if (QFile::exists(txtMapFilePath->text()))
73
okToSave = QMessageBox::warning(0, tr("Overwrite File?"), txtMapFilePath->text() +
74
tr(" exists. \nDo you want to overwrite it?"), tr("Yes"), tr("No"));
78
// write the project information to the selected file
88
void QgsMapserverExport::setFileName(QString fn)
93
QString QgsMapserverExport::fullPathName()
98
void QgsMapserverExport::writeMapFile()
100
// write the map file, making massive assumptions about default values
102
std::cout << "Opening map file " << txtMapFilePath->text().toLocal8Bit().data() << std::endl;
104
std::ofstream mapFile(txtMapFilePath->text().toLocal8Bit().data());
107
// XXX So, what encoding should we use here???
108
mapFile << "# Map file generated by QGIS version " << QGis::qgisVersion << std::endl;
109
mapFile << "# Edit this file to customize for your interface" << std::endl;
110
mapFile << "# Not all sections are complete. See comments for details." << std::endl;
111
if (!chkExpLayersOnly->isChecked())
114
mapFile << "NAME " << txtMapName->text().toLocal8Bit().data() << std::endl;
115
mapFile << "STATUS ON" << std::endl;
116
mapFile << "\n# Map image size. Change size as desired" << std::endl;
117
mapFile << "SIZE " << txtMapWidth->text().toLocal8Bit().data() << " " << txtMapHeight->text().toLocal8Bit().data() << std::endl;
118
// web interface definition - this is minimal!
119
mapFile << "#" << std::endl;
120
mapFile << "# Start of web interface definition. Only the TEMPLATE parameter" << std::endl;
121
mapFile << "# must be specified to display a map. See Mapserver documentation" << std::endl;
122
mapFile << "#" << std::endl;
123
mapFile << "WEB" << std::endl;
124
// if no header is supplied, write the header line but comment it out
125
if (txtWebHeader->text().isEmpty())
127
mapFile << " # HEADER" << std::endl;
130
// header provided - write it
131
mapFile << " HEADER " << txtWebHeader->text().toLocal8Bit().data() << std::endl;
133
// if no template provided, write the template line but comment it out
134
if (txtWebTemplate->text().isEmpty())
136
mapFile << " # TEMPLATE" << std::endl;
139
// template provided - write it
140
mapFile << " TEMPLATE " << txtWebTemplate->text().toLocal8Bit().data() << std::endl;
142
// if no footer provided, write the footer line but comment it out
143
if (txtWebFooter->text().isEmpty())
145
mapFile << " # FOOTER" << std::endl;
148
mapFile << " FOOTER " << txtWebFooter->text().toLocal8Bit().data() << std::endl;
150
QString minScale = txtMinScale->text().isEmpty()?"#MINSCALE":"MINSCALE";
151
QString maxScale = txtMinScale->text().isEmpty()?" #MAXSCALE ":" MAXSCALE ";
152
// write min and maxscale
153
mapFile << minScale.toLocal8Bit().data() << txtMinScale->text().toLocal8Bit().data() << std::endl;
154
mapFile << maxScale.toLocal8Bit().data() << txtMaxScale->text().toLocal8Bit().data() << std::endl;
155
// write comments about the imagepath and image url
156
mapFile << "# Set IMAGEPATH to the path where mapserver should\n" <<
157
"# write its output\n" <<
158
" IMAGEPATH '/tmp/'" << std::endl;
159
mapFile << "# Set IMAGEURL to the url that points to IMAGEPATH" << std::endl;
160
mapFile << " #IMAGEURL '/map_output/'" << std::endl;
161
// end of web section
162
mapFile << "END" << std::endl;
165
mapFile << "\n# Extent based on full extent of QGIS view" << std::endl;
166
mapFile << "EXTENT ";
167
QgsRect extent = map->extent();
168
mapFile << extent.xMin() << " " << extent.yMin() << " ";
169
mapFile << extent.xMax() << " " << extent.yMax() << std::endl;
171
mapFile << "UNITS " << cmbMapUnits->currentText().toLocal8Bit().data() << std::endl;
173
mapFile << "IMAGECOLOR 255 255 255" << std::endl;
174
mapFile << "IMAGETYPE " << cmbMapImageType->currentText().toLocal8Bit().data() << std::endl;
175
// projection information TODO: support projections :)
176
mapFile << "# Projection definition" << std::endl;
177
mapFile << "# Projections are not currenlty supported. If desired, add your own" << std::endl;
178
mapFile << "# projection information based on Mapserver documentation." << std::endl;
179
mapFile << "#" << std::endl;
183
mapFile << " # This file contains layer definitions only and is not a complete" << std::endl;
184
mapFile << " # Mapserver map file." << std::endl;
187
// write layer definitions
188
for (int i = 0; i < map->layerCount(); i++)
190
bool isPolygon = false;
192
QgsMapLayer *lyr = map->getZpos(i);
194
std::cout << "Mapsrver Export Processing Layer" << std::endl;
196
mapFile << "LAYER" << std::endl;
197
QString name = lyr->name().lower();
198
// MapServer NAME must be < 20 char and unique
199
name.replace(QRegExp(" "), "_");
200
name.replace(QRegExp("\\."), "_");
201
name.replace(QRegExp("\\("), "_");
202
name.replace(QRegExp("\\)"), "_");
203
mapFile << " NAME " << name.toLocal8Bit().data() << std::endl;
206
std::cout << "\tMapserver Export checking feature type" << std::endl;
209
switch (lyr->featureType())
212
case QGis::WKBMultiPoint:
215
case QGis::WKBLineString:
216
case QGis::WKBMultiLineString:
220
case QGis::WKBPolygon:
221
case QGis::WKBMultiPolygon:
222
mapFile << "POLYGON";
227
if(lyr->type() == QgsMapLayer::RASTER)
231
mapFile << std::endl;
234
std::cout << "\tMapserver Export checking visibility" << std::endl;
236
// set visibility (STATUS)
237
mapFile << " STATUS ";
245
mapFile << std::endl;
247
// data source (DATA)
248
// Data source spec depends on layer type
250
std::cout << "\tMapserver Export checking layer type" << std::endl;
254
case QgsMapLayer::VECTOR:
255
// get the provider type
257
QString providerType =
258
dynamic_cast<QgsVectorLayer*>(lyr)->providerType();
259
if(providerType == "postgres")
261
QgsDataSourceURI *dUri =
262
dynamic_cast<QgsVectorLayer *>(lyr)->getDataProvider()->getURI();
263
mapFile << "CONNECTION \"user=" << dUri->username.toLocal8Bit().data();
264
if(dUri->password.length() > 0)
266
mapFile << " password="<< dUri->password.toLocal8Bit().data();
268
mapFile << " dbname=" << dUri->database.toLocal8Bit().data()
269
<< " host=" << dUri->host.toLocal8Bit().data()
270
<< " port=" << dUri->port.toLocal8Bit().data()
271
<< "\"" << std::endl;
272
mapFile << "CONNECTIONTYPE postgis" << std::endl;
273
mapFile << "DATA \"" << dUri->geometryColumn.toLocal8Bit().data() << " from "
274
<< dUri->table.toLocal8Bit().data() << "\"" << std::endl;
275
if(dUri->sql.length() > 0)
277
mapFile << "FILTER \"" << dUri->sql.toLocal8Bit().data() << "\"" << std::endl;
285
mapFile << " DATA " << lyr->source().toLocal8Bit().data() << std::endl;
289
case QgsMapLayer::RASTER:
290
mapFile << " DATA " << lyr->source().toLocal8Bit().data() << std::endl;
295
std::cout << "\tMapserver Export creating symbol entries" << std::endl;
297
// create a simple class entry based on red fill color and black outline color
298
//TODO: adapt the following section to the new symbology
300
mapFile << " CLASS" << std::endl;
301
//QListViewItem *li = map->getLegend()->currentItem();
302
// return li->text(0);
304
std::cout << "\tMapserver Export symbol name" << std::endl;
306
mapFile << " NAME \"" << lyr->name().toLocal8Bit().data() << "\"" << std::endl;
307
mapFile << " # TEMPLATE" << std::endl;
311
std::cout << "\tMapserver Export symbol fill color" << std::endl;
313
// use random fill colors
314
// TODO Get fill color from the renderer
315
// TODO Figure out what to do for layers that are
316
// rendered with other than the simple symbol
318
int red = 1 + (int) (255.0 * rand() / (RAND_MAX + 1.0));
319
int green = 1 + (int) (255.0 * rand() / (RAND_MAX + 1.0));
320
int blue = 1 + (int) (255.0 * rand() / (RAND_MAX + 1.0));
322
mapFile << " COLOR " << red << " " << green << " " << blue << std::endl;
325
std::cout << "\tMapserver Export checking for line symbol " << std::endl;
327
if (isPolygon || isLine)
330
// TODO Get line color from the renderer
331
int red = 1 + (int) (255.0 * rand() / (RAND_MAX + 1.0));
332
int green = 1 + (int) (255.0 * rand() / (RAND_MAX + 1.0));
333
int blue = 1 + (int) (255.0 * rand() / (RAND_MAX + 1.0));
334
mapFile << " OUTLINECOLOR " << red << " "
335
<< green << " " << blue << std::endl;
337
mapFile << " END" << std::endl;
338
mapFile << "END" << std::endl;
340
std::cout << "\tMapserver Export layer definition done..." << std::endl;
343
if (!chkExpLayersOnly->isChecked())
345
mapFile << "END # Map File";
354
void QgsMapserverExport::on_chkExpLayersOnly_clicked()
356
// disable inputs if only layer objects are being written
357
grpMap->setEnabled(!chkExpLayersOnly->isChecked());
358
grpWeb->setEnabled(!chkExpLayersOnly->isChecked());
361
void QgsMapserverExport::on_btnChooseFile_clicked()
363
QString s = QFileDialog::getSaveFileName(
365
tr("Choose a filename for the exported map file"),
367
tr("Mapserver files (*.map)" ) );
368
txtMapFilePath->setText(s);
371
void QgsMapserverExport::on_buttonHelp_clicked()
373
//QMessageBox::information(this, "Help","Help");
374
QgsHelpViewer *hv = new QgsHelpViewer(this);
375
// causes problems in qt3.1.x: hv->setModal(false);
376
hv->setCaption( tr("QGIS Help - Mapserver Export") );