mirror of
https://github.com/qgis/QGIS.git
synced 2025-02-25 00:58:06 -05:00
333 lines
16 KiB
Python
Executable File
333 lines
16 KiB
Python
Executable File
"""
|
|
/***************************************************************************
|
|
MapServerExport - A QGIS plugin to export a saved project file
|
|
to a MapServer map file
|
|
-------------------
|
|
begin : 2008-01-07
|
|
copyright : (C) 2008 by Gary E.Sherman
|
|
email : sherman at mrcc.com
|
|
***************************************************************************/
|
|
|
|
/***************************************************************************
|
|
* *
|
|
* 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. *
|
|
* *
|
|
***************************************************************************/
|
|
/* Adapted by Erik van de Pol */
|
|
"""
|
|
# Import the PyQt and QGIS libraries
|
|
from PyQt4.QtCore import *
|
|
from PyQt4.QtGui import *
|
|
from xml.dom import minidom
|
|
from qgis.core import *
|
|
# Initialize Qt resources from file resources.py
|
|
import resources_rc
|
|
# Import the code for the dialog
|
|
from mapserverexportdialog import MapServerExportDialog
|
|
# Import the ms_export script that does the real work
|
|
from ms_export import *
|
|
|
|
class MapServerExport:
|
|
|
|
def __init__(self, iface):
|
|
# Save reference to the QGIS interface
|
|
self.iface = iface
|
|
|
|
def setCurrentTheme(self, theThemeName):
|
|
# Set icons to the current theme
|
|
self.action.setIcon(self.getThemeIcon("mapserver_export.png"))
|
|
|
|
def getThemeIcon(self, theName):
|
|
# get the icon from the best available theme
|
|
myCurThemePath = QgsApplication.activeThemePath() + "/plugins/" + theName;
|
|
myDefThemePath = QgsApplication.defaultThemePath() + "/plugins/" + theName;
|
|
myQrcPath = ":/plugins/mapserver_export/" + theName;
|
|
if QFile.exists(myCurThemePath):
|
|
return QIcon(myCurThemePath)
|
|
elif QFile.exists(myDefThemePath):
|
|
return QIcon(myDefThemePath)
|
|
elif QFile.exists(myQrcPath):
|
|
return QIcon(myQrcPath)
|
|
else:
|
|
return QIcon()
|
|
|
|
def initGui(self):
|
|
# Create action that will start plugin configuration
|
|
self.action = QAction(self.getThemeIcon("mapserver_export.png"), \
|
|
"MapServer Export", self.iface.mainWindow())
|
|
# connect the action to the run method
|
|
QObject.connect(self.action, SIGNAL("triggered()"), self.run)
|
|
QObject.connect(self.iface, SIGNAL("currentThemeChanged ( QString )"), self.setCurrentTheme)
|
|
# Add toolbar button and menu item
|
|
self.iface.addWebToolBarIcon(self.action)
|
|
self.iface.addPluginToWebMenu("&MapServer Export...", self.action)
|
|
|
|
def unload(self):
|
|
# Remove the plugin menu item and icon
|
|
self.iface.removePluginWebMenu("&MapServer Export...",self.action)
|
|
self.iface.removeWebToolBarIcon(self.action)
|
|
|
|
# run method that performs all the real work
|
|
def run(self):
|
|
# create and show the MapServerExport dialog
|
|
self.dlg = MapServerExportDialog(self.iface.mainWindow())
|
|
# attach events to inputs and buttons
|
|
QObject.connect(self.dlg.ui.btnChooseFile, SIGNAL("clicked()"), self.setMapFile)
|
|
QObject.connect(self.dlg.ui.txtMapFilePath, SIGNAL("textChanged(QString)"), self.mapfileChanged)
|
|
QObject.connect(self.dlg.ui.btnChooseProjectFile, SIGNAL("clicked()"), self.setProjectFile)
|
|
QObject.connect(self.dlg.ui.chkExpLayersOnly, SIGNAL("clicked(bool)"), self.toggleLayersOnly)
|
|
QObject.connect(self.dlg.ui.checkBoxCurrentProject, SIGNAL("clicked(bool)"), self.toggleUseCurrentProject)
|
|
QObject.connect(self.dlg.ui.btnChooseFooterFile, SIGNAL("clicked()"), self.setFooterFile)
|
|
QObject.connect(self.dlg.ui.btnChooseHeaderFile, SIGNAL("clicked()"), self.setHeaderFile)
|
|
QObject.connect(self.dlg.ui.btnChooseTemplateFile, SIGNAL("clicked()"), self.setTemplateFile)
|
|
QObject.connect(self.dlg.ui.buttonBox, SIGNAL("accepted()"), self.ok_clicked)
|
|
QObject.connect(self.dlg.ui.buttonBox, SIGNAL("helpRequested()"), self.helpRequested)
|
|
# qgs-project defaults to current instance
|
|
project = QgsProject.instance()
|
|
self.dlg.ui.txtQgisFilePath.setText(project.fileName())
|
|
# get some settings from former successfull exports
|
|
# defaults are defined in ms_export.py and set in mapserverexportdialog.py
|
|
settings = QSettings()
|
|
# map-file name and force mapfileChanged to enable/disable ok button
|
|
self.dlg.ui.txtMapFilePath.setText(settings.value("/MapserverExport/mapfileName", QVariant("")).toString ())
|
|
self.mapfileChanged(self.dlg.ui.txtMapFilePath.text())
|
|
# map width and height
|
|
if settings.contains("/MapserverExport/mapWidth"):
|
|
self.dlg.ui.txtMapWidth.setText(settings.value("/MapserverExport/mapWidth").toString ())
|
|
if settings.contains("/MapserverExport/mapHeight"):
|
|
self.dlg.ui.txtMapHeight.setText(settings.value("/MapserverExport/mapHeight").toString ())
|
|
# MapServer IMAGETYPE's [gif|png|jpeg|wbmp|gtiff|swf|userdefined]
|
|
self.dlg.ui.cmbMapImageType.addItems(QStringList(["agg","png","gif","jpeg","wbmp","gtiff","swf","userdefined"]))
|
|
if settings.contains("/MapserverExport/imageType"):
|
|
idx = self.dlg.ui.cmbMapImageType.findText(settings.value("/MapserverExport/imageType").toString ())
|
|
self.dlg.ui.cmbMapImageType.setCurrentIndex(idx)
|
|
# MapServer URL (default value already set by dialog defaults)
|
|
if settings.contains("/MapserverExport/mapserverUrl"):
|
|
self.dlg.ui.txtMapServerUrl.setText(settings.value("/MapserverExport/mapserverUrl").toString())
|
|
# set title or default to one if none available
|
|
title = project.title()
|
|
if title == "":
|
|
title = "QGIS-MAP"
|
|
self.dlg.ui.txtMapName.setText(title)
|
|
# TODO: fetch units used from current project
|
|
# QGIS: Meters, Feet, Degrees, UnknownUnit since 1.4 also: DecimalDegrees, DegreesMinutesSeconds, DegreesDecimalMinutes
|
|
# Mapserver: UNITS [feet|inches|kilometers|meters|miles|dd]
|
|
self.dlg.show()
|
|
|
|
def helpRequested(self):
|
|
QgsContextHelp.run( "MapServerExport" )
|
|
|
|
def ok_clicked(self):
|
|
# check if current project is saved or dirty
|
|
if not self.checkCurrentProject():
|
|
# abort because user apparently did not wat to save or Cancelled
|
|
return
|
|
if not self.checkMapFile():
|
|
print "Failed for Map file check, try again..."
|
|
return
|
|
else:
|
|
self.saveMapFile()
|
|
|
|
def toggleUseCurrentProject(self, boolUseCurrent):
|
|
self.dlg.ui.txtQgisFilePath.setEnabled(not boolUseCurrent)
|
|
self.dlg.ui.btnChooseProjectFile.setEnabled(not boolUseCurrent)
|
|
if boolUseCurrent:
|
|
#if self.dlg.ui.txtQgisFilePath.text().size() == 0:
|
|
# reload path of current project
|
|
self.dlg.ui.txtQgisFilePath.setText(QgsProject.instance().fileName())
|
|
else:
|
|
# open dialog to choose project file
|
|
self.setProjectFile()
|
|
|
|
|
|
def saveMapFile(self):
|
|
# get the settings from the dialog and export the map file
|
|
print "Creating exporter using '%s' and '%s'" % (self.dlg.ui.txtQgisFilePath.text(), self.dlg.ui.txtMapFilePath.text())
|
|
exporter = Qgis2Map(unicode(self.dlg.ui.txtMapFilePath.text()))
|
|
# Parse qgis project file and check success
|
|
if not(exporter.setQgsProject(self.dlg.ui.txtQgisFilePath.text())):
|
|
QMessageBox.warning(self.dlg, "No Map file export!", "Map file not exported because no valid qgis project file was given.")
|
|
return
|
|
if exporter.projectHasNewSymbology():
|
|
QMessageBox.information(self.dlg, "New Symbology layer(s) found", "The project you selected holds layer(s) which use 'New Symbology'.\n\nCurrently this plugin is not able to handle this.\n\nPlease change symbology of these layer(s) to 'Old Symbology'.")
|
|
self.dlg.hide()
|
|
return
|
|
self.dlg.hide()
|
|
print "Setting options"
|
|
exporter.setOptions(
|
|
unicode(self.dlg.ui.txtMapServerUrl.text()),
|
|
unicode(self.dlg.ui.cmbMapUnits.itemData( self.dlg.ui.cmbMapUnits.currentIndex() ).toString()),
|
|
unicode(self.dlg.ui.cmbMapImageType.currentText()),
|
|
unicode(self.dlg.ui.txtMapName.text()),
|
|
unicode(self.dlg.ui.txtMapWidth.text()),
|
|
unicode(self.dlg.ui.txtMapHeight.text()),
|
|
unicode(self.dlg.ui.txtWebTemplate.text()),
|
|
unicode(self.dlg.ui.txtWebHeader.text()),
|
|
unicode(self.dlg.ui.txtWebFooter.text()),
|
|
self.dlg.ui.checkBoxDump.isChecked(),
|
|
self.dlg.ui.checkBoxForce.isChecked(),
|
|
self.dlg.ui.checkBoxAntiAlias.isChecked(),
|
|
self.dlg.ui.checkBoxPartials.isChecked(),
|
|
self.dlg.ui.chkExpLayersOnly.isChecked(),
|
|
unicode(self.dlg.ui.txtFontsetPath.text()),
|
|
unicode(self.dlg.ui.txtSymbolsetPath.text())
|
|
)
|
|
print "Calling writeMapFile"
|
|
try:
|
|
result = exporter.writeMapFile()
|
|
except Exception, err:
|
|
QMessageBox.information(self.dlg, "MapServer Export Error", str(err))
|
|
return
|
|
# ok succesfull: write some setting for a next session
|
|
settings = QSettings()
|
|
# mapfile name
|
|
settings.setValue("/MapserverExport/mapfileName", QVariant(self.dlg.ui.txtMapFilePath.text()))
|
|
# map width and heigth
|
|
settings.setValue("/MapserverExport/mapWidth", QVariant(self.dlg.ui.txtMapWidth.text()))
|
|
settings.setValue("/MapserverExport/mapHeight", QVariant(self.dlg.ui.txtMapHeight.text()))
|
|
# mapserver url
|
|
settings.setValue("/MapserverExport/mapserverUrl", QVariant(self.dlg.ui.txtMapServerUrl.text()))
|
|
# map ImageType
|
|
settings.setValue("/MapserverExport/imageType", QVariant(self.dlg.ui.cmbMapImageType.currentText()))
|
|
# show results
|
|
QMessageBox.information(self.dlg, "MapServer Export Results", result)
|
|
|
|
def mapfileChanged(self, text):
|
|
# Enable OK button
|
|
btnOk = self.dlg.ui.buttonBox.button(QDialogButtonBox.Ok)
|
|
if text.size() > 0:
|
|
btnOk.setEnabled(True)
|
|
else:
|
|
btnOk.setEnabled(False)
|
|
|
|
def checkMapFile(self):
|
|
# Check if map file name is provided
|
|
mapFileName = self.dlg.ui.txtMapFilePath.text()
|
|
if mapFileName.size() == 0:
|
|
QMessageBox.warning(self.dlg, "Not saved!", "Map file not saved because no file name was given")
|
|
return False
|
|
# Check/fix for .map extension (mapserver fails to read otherwise)
|
|
if not mapFileName.trimmed().endsWith('.map'):
|
|
mapFileName += '.map'
|
|
self.dlg.ui.txtMapFilePath.setText(mapFileName)
|
|
# Check if map file exists and we should overwrite it
|
|
if QFile(mapFileName).exists():
|
|
if QMessageBox.Cancel == QMessageBox.question(self.dlg, "Overwrite excisting Map file?",
|
|
"Map file \"" + mapFileName + "\" already exists. \nShould we overwrite it?",
|
|
QMessageBox.Yes, QMessageBox.Cancel):
|
|
return False
|
|
# mapfile ok, extension ok, overwrite ok
|
|
return True
|
|
|
|
# check if current project is saved and or dirty (has modifications)
|
|
def checkCurrentProject(self, forUnload=False):
|
|
project = QgsProject.instance()
|
|
# question: save project on loading export dialog?
|
|
if project.isDirty():
|
|
msg = "Save project to \"" + project.fileName() + "\" before exporting?\nOnly the last saved version of your project will be exported."
|
|
if project.fileName()=="":
|
|
msg = "Please save project before exporting.\nOnly saved projects can be exported."
|
|
if forUnload:
|
|
msg = "Save project first?\nAfter saving, this project will be unloaded."
|
|
shouldSave = QMessageBox.question(self.dlg, "Save?", msg,
|
|
QMessageBox.Yes, QMessageBox.No, QMessageBox.Cancel)
|
|
if shouldSave == QMessageBox.Yes:
|
|
if project.fileName().size() == 0:
|
|
# project has not yet been saved:
|
|
saveAsFileName = QFileDialog.getSaveFileName(self.dlg,
|
|
"Save QGIS Project file as...", ".",
|
|
"QGIS Project Files (*.qgs)", "Filter list for selecting files from a dialog box")
|
|
# Check that a file was selected
|
|
if saveAsFileName.size() == 0:
|
|
QMessageBox.warning(self.dlg, "Not saved!", "QGis project file not saved because no file name was given.")
|
|
# fall back to using current project if available
|
|
self.dlg.ui.txtQgisFilePath.setText(project.fileName())
|
|
else:
|
|
if not saveAsFileName.trimmed().endsWith('.qgs'):
|
|
saveAsFileName += '.qgs'
|
|
self.dlg.ui.txtQgisFilePath.setText(saveAsFileName)
|
|
project.setFileName(saveAsFileName)
|
|
project.write()
|
|
else:
|
|
project.write()
|
|
#project ok now
|
|
return True
|
|
elif shouldSave == QMessageBox.No and forUnload:
|
|
# unloading a non saved project: just leave ...
|
|
return True
|
|
elif shouldSave == QMessageBox.No:
|
|
# users does not want to save project, but has to because only saved projects can be exported
|
|
return False
|
|
elif shouldSave == QMessageBox.Cancel:
|
|
# user cancelled
|
|
return False
|
|
else:
|
|
# project saved and not dirty
|
|
return True
|
|
|
|
def setMapFile(self):
|
|
mapFileName = QFileDialog.getSaveFileName(self.dlg, "Name for the map file", \
|
|
self.dlg.ui.txtMapFilePath.text(), "MapServer map files (*.map);;All files (*.*)","Filter list for selecting files from a dialog box")
|
|
self.dlg.ui.txtMapFilePath.setText(mapFileName)
|
|
|
|
def setProjectFile(self):
|
|
# check if it's needed to save current project, will return False if user cancelled
|
|
if not self.checkCurrentProject(True):
|
|
return
|
|
qgisProjectFile = QFileDialog.getOpenFileName(self.dlg, "Choose a QGIS Project", \
|
|
".", "QGIS Project Files (*.qgs);;", "Filter list for selecting files from a dialog box")
|
|
if not qgisProjectFile:
|
|
# cancelled: check checkBoxCurrentProject again
|
|
self.dlg.ui.checkBoxCurrentProject.setChecked(True)
|
|
self.dlg.ui.txtQgisFilePath.setEnabled(False)
|
|
return
|
|
try:
|
|
# reading a non-qgs or not existing file results in qgis crash
|
|
# QgsProject.instance().read(QFileInfo(qgisProjectFile))
|
|
# we try to open the file first to see if it can be parsed...
|
|
exporter = Qgis2Map(unicode(self.dlg.ui.txtMapFilePath.text()))
|
|
if exporter.setQgsProject(qgisProjectFile):
|
|
# project file OK !!
|
|
pass
|
|
if exporter.projectHasPostgisLayers():
|
|
loadProject = QMessageBox.question(self.dlg, "Load project?",
|
|
"The project you selected holds one or more postgis layers. \nTo be able to export a valid DATA string in the map file,\nthe project should be loaded into QGIS. \nNot loading can result in non valid DATA strings in map file.\nSo, should we load it into qgis?",
|
|
QMessageBox.Yes, QMessageBox.No)
|
|
if loadProject == QMessageBox.Yes:
|
|
QgsProject.instance().read(QFileInfo(qgisProjectFile))
|
|
else:
|
|
# postgis, but user refuses to load it, just go and see what happens
|
|
pass
|
|
else:
|
|
# NO postgis, go
|
|
pass
|
|
except Exception, err:
|
|
QMessageBox.information(self.dlg, "Error reading or loading the selected project file", str(err))
|
|
self.dlg.ui.checkBoxCurrentProject.setChecked(True)
|
|
self.dlg.ui.txtQgisFilePath.setEnabled(False)
|
|
return
|
|
self.dlg.ui.txtQgisFilePath.setText(qgisProjectFile)
|
|
|
|
def setTemplateFile(self):
|
|
templateFile = QFileDialog.getOpenFileName(self.dlg, "Choose the MapServer template file", \
|
|
".", "All files (*.*)", "Filter list for selecting files from a dialog box")
|
|
self.dlg.ui.txtWebTemplate.setText(templateFile)
|
|
|
|
def setHeaderFile(self):
|
|
headerFile = QFileDialog.getOpenFileName(self.dlg, "Choose the MapServer header file", \
|
|
".", "All files (*.*)", "Filter list for selecting files from a dialog box")
|
|
self.dlg.ui.txtWebHeader.setText(headerFile)
|
|
|
|
def setFooterFile(self):
|
|
footerFile = QFileDialog.getOpenFileName(self.dlg, "Choose the MapServer footer file", \
|
|
".", "All files (*.*)", "Filter list for selecting files from a dialog box")
|
|
self.dlg.ui.txtWebFooter.setText(footerFile)
|
|
|
|
def toggleLayersOnly(self, isChecked):
|
|
# disable other sections if only layer export is desired
|
|
self.dlg.ui.grpPaths.setEnabled(not isChecked)
|
|
self.dlg.ui.grpMap.setEnabled(not isChecked)
|