Skip to content
Browse files

+ timevectorlayer.py, timerasterlayer.py

first working version with raster layer support
  • Loading branch information...
1 parent b599d48 commit b510b7b1538149e9f367afe992e766a3c116bf8a @anitagraser committed Mar 23, 2012
View
6 __init__.py
@@ -8,7 +8,7 @@ def description():
return "The aim of TimeManager plugin for QGIS is to provide comfortable browsing through temporal geodata. A dock widget provides a time slider and a configuration dialog for your layers to manage."
def version():
- return "Version 0.5"
+ return "Version 0.6"
def qgisMinimumVersion():
return '1.6.0'
@@ -26,10 +26,10 @@ def experimental():
return True
def homepage():
- return 'http://www.geofrogger.net/trac/'
+ return "https://github.com/anitagraser/TimeManager"
def tracker():
- return 'http://www.geofrogger.net/trac/'
+ return "https://github.com/anitagraser/TimeManager"
def repository():
return 'http://plugins.qgis.org/plugins/'
View
7 dockwidget2.ui
@@ -149,7 +149,7 @@
<item>
<widget class="QComboBox" name="comboBoxTimeExtent">
<property name="currentIndex">
- <number>5</number>
+ <number>0</number>
</property>
<item>
<property name="text">
@@ -186,6 +186,11 @@
<string>weeks</string>
</property>
</item>
+ <item>
+ <property name="text">
+ <string>months</string>
+ </property>
+ </item>
</widget>
</item>
<item>
View
2 metadata.txt
@@ -1,7 +1,7 @@
[general]
name=TimeManager
description=Working with temporal data
-version=Version 0.5
+version=Version 0.6
qgisMinimumVersion=1.6.0
authorName=Anita Graser
icon=icon.png
View
2 options.ui
@@ -132,7 +132,7 @@
<number>1000000</number>
</property>
<property name="value">
- <number>2000</number>
+ <number>200</number>
</property>
</widget>
</item>
View
BIN testdata/tweets.dbf
Binary file not shown.
View
103 timelayer.py
@@ -1,33 +1,14 @@
#!/usr/bin/python
# -*- coding: UTF-8 -*-
-# $Id: timelayer.py 110 2011-04-03 09:55:37Z volter $
-
from datetime import datetime, timedelta
from qgis.core import *
class TimeLayer:
"""Manages the properties of a managed (managable) layer."""
- def __init__(self,layer,fromTimeAttribute,toTimeAttribute,enabled=True,timeFormat="%Y-%m-%d %H:%M:%S",offset=0):
+ def __init__(self,layer,enabled=True):
self.layer = layer
- self.fromTimeAttribute = fromTimeAttribute
- self.toTimeAttribute = toTimeAttribute
self.timeEnabled = enabled
- self.originalSubsetString = self.layer.subsetString()
- self.timeFormat = str(timeFormat) # cast in case timeFormat comes as a QString
- self.supportedFormats = [
- "%Y-%m-%d %H:%M:%S",
- "%Y-%m-%d %H:%M:%S.%f",
- "%Y-%m-%d %H:%M",
- "%Y-%m-%d",
- "%Y/%m/%d %H:%M:%S"]
- if timeFormat not in self.supportedFormats:
- self.supportedFormats.append(timeFormat)
- self.offset = int(offset)
- try:
- self.getTimeExtents()
- except NotATimeAttributeError, e:
- raise InvalidTimeLayerError(e.value)
def getLayer(self):
"""Get the layer associated with the current timeLayer"""
@@ -48,88 +29,6 @@ def isEnabled(self):
"""whether timeManagement is enabled for this layer"""
return self.timeEnabled
- def getTimeAttributes(self):
- """return the tuple of timeAttributes (fromTimeAttribute,toTimeAttribute)"""
- return(self.fromTimeAttribute,self.toTimeAttribute)
-
- def getTimeFormat(self):
- """returns the layer's time format"""
- return self.timeFormat
-
- def getOffset(self):
- """returns the layer's offset, integer in seconds"""
- return self.offset
-
- def strToDatetime(self, dtStr):
- """convert a date/time string into a Python datetime object"""
- try:
- # Try the last known format, if not, try all known formats.
- return datetime.strptime(dtStr, self.timeFormat)
- except:
- for fmt in self.supportedFormats:
- try:
- self.timeFormat = fmt
- return datetime.strptime(dtStr, self.timeFormat)
- except:
- pass
- # If all fail, re-raise the exception
- raise
-
- def getTimeExtents( self ):
- """Get layer's temporal extent using the fields and the format defined somewhere else!"""
- provider=self.layer.dataProvider()
- fromTimeAttributeIndex = provider.fieldNameIndex(self.fromTimeAttribute)
- toTimeAttributeIndex = provider.fieldNameIndex(self.toTimeAttribute)
- startStr = str(provider.minimumValue(fromTimeAttributeIndex).toString())
- endStr = str(provider.maximumValue(toTimeAttributeIndex).toString())
- try:
- startTime = self.strToDatetime(startStr)
- except ValueError:
- raise NotATimeAttributeError(str(self.getName())+': The attribute specified for use as start time contains invalid data:\n\n'+startStr+'\n\nis not one of the supported formats:\n'+str(self.supportedFormats))
- try:
- endTime = self.strToDatetime(endStr)
- except ValueError:
- raise NotATimeAttributeError(str(self.getName())+': The attribute specified for use as end time contains invalid data:\n'+endStr)
- # apply offset
- startTime += timedelta(seconds=self.offset)
- endTime += timedelta(seconds=self.offset)
- return (startTime,endTime)
-
- def setTimeRestriction(self,timePosition,timeFrame):
- """Constructs the query, including the original subset"""
- if not self.timeEnabled:
- self.deleteTimeRestriction()
- return
- startTime = datetime.strftime(timePosition + timedelta(seconds=self.offset),self.timeFormat)
- endTime = datetime.strftime((timePosition + timeFrame + timedelta(seconds=self.offset)),self.timeFormat)
- #subsetString = "\"%s\" < '%s' AND \"%s\" >= '%s' " % ( self.fromTimeAttribute,endTime,self.toTimeAttribute,startTime)
- if self.originalSubsetString == "":
- subsetString = "\"%s\" < '%s' AND \"%s\" >= '%s' " % ( self.fromTimeAttribute,endTime,self.toTimeAttribute,startTime)
- else:
- subsetString = "%s AND \"%s\" < '%s' AND \"%s\" >= '%s' " % ( self.originalSubsetString,self.fromTimeAttribute,endTime,self.toTimeAttribute,startTime)
- self.layer.setSubsetString( subsetString )
- #QMessageBox.information(self.iface.mainWindow(),"Test Output",subsetString)
-
- def deleteTimeRestriction(self):
- """Restore original subset"""
- self.layer.setSubsetString( self.originalSubsetString )
-
- def hasTimeRestriction(self):
- """returns true if current layer.subsetString is not equal to originalSubsetString"""
- return self.layer.subsetString != self.originalSubsetString
-
- def getSaveString(self):
- """get string to save in project file"""
- delimiter = ';'
- saveString = self.getLayerId() + delimiter
- saveString += self.originalSubsetString + delimiter
- saveString += self.fromTimeAttribute + delimiter
- saveString += self.toTimeAttribute + delimiter
- saveString += str(self.timeEnabled) + delimiter
- saveString += self.timeFormat + delimiter
- saveString += str(self.offset)
- return saveString
-
class NotATimeAttributeError(Exception):
def __init__(self, value):
self.value = value
View
19 timelayermanager.py
@@ -2,6 +2,8 @@
# -*- coding: UTF-8 -*-
from datetime import datetime, timedelta
+from dateutil.relativedelta import relativedelta
+
from PyQt4.QtCore import *
from qgis.core import *
@@ -57,6 +59,10 @@ def getFrameCount(self):
# this is how you can devide two timedeltas (not supported by default):
us1 = td1.microseconds + 1000000 * (td1.seconds + 86400 * td1.days)
us2 = td2.microseconds + 1000000 * (td2.seconds + 86400 * td2.days)
+
+ if us2 == 0:
+ return 1000 # this is just a stupid default, TODO!
+
return us1 / us2
def hasLayers(self):
@@ -82,7 +88,9 @@ def clearTimeLayerList(self):
def timeFrame(self):
"""returns the current time frame as datetime.timedelta object"""
- if self.timeFrameType == 'weeks':
+ if self.timeFrameType == 'months':
+ return relativedelta(months=self.timeFrameSize) # months are not supported by timedelta
+ elif self.timeFrameType == 'weeks':
return timedelta(weeks=self.timeFrameSize)
elif self.timeFrameType == 'days':
return timedelta(days=self.timeFrameSize)
@@ -98,16 +106,17 @@ def timeFrame(self):
elif self.timeFrameType == 'microseconds':
return timedelta(microseconds=self.timeFrameSize)
- #default
- #return timedelta(days=1)
def refresh(self):
- """Applies or removes the spatial constraints (not the complete subset) for all managed (and enabled) layers"""
+ """Applies or removes the temporal constraints for all managed (and enabled) layers"""
if not self.hasLayers():
return
if self.timeManagementEnabled:
for timeLayer in self.timeLayerList:
- timeLayer.setTimeRestriction(self.currentTimePosition,self.timeFrame())
+ #try:
+ timeLayer.setTimeRestriction(self.currentTimePosition,self.timeFrame())
+ #except AttributeError: # if timeLayer is of NoneType
+ # pass
else:
for timeLayer in self.timeLayerList:
if not timeLayer.hasTimeRestriction():
View
5 timemanager.py
@@ -24,7 +24,7 @@ class timemanager:
name = "TimeManagerPlugin"
longName = "TimeManager Plugin for QGIS >= 1.6"
description = "Working with temporal vector data"
- version = "Version 0.5"
+ version = "Version 0.6" # update in __init__.py too!
qgisMinimumVersion = '1.6.0'
author = "Anita Graser"
pluginUrl = "https://github.com/anitagraser/TimeManager"
@@ -41,8 +41,7 @@ def initGui( self ):
def unload( self ):
"""Unload the plugin"""
self.control.unload()
-
-
+
View
32 timemanagercontrol.py
@@ -7,6 +7,7 @@
from timemanagerguicontrol import *
from timelayer import *
+from timevectorlayer import *
from timelayermanager import *
from timemanagerprojecthandler import *
@@ -337,25 +338,40 @@ def restoreTimeLayers(self,value):
layer = QgsMapLayerRegistry.instance().mapLayer(l[0]) # get the layer
if not layer:
break
- layer.setSubsetString(l[1]) # restore the original subset string
- fromTimeAttribute=l[2]
- toTimeAttribute=l[3]
- enabled=l[4]
+
+ # this should be a python class factory
+ if type(layer).__name__ == "QgsRasterLayer":
+ timeLayerClass = TimeRasterLayer # get the correct class to use
+ elif type(layer).__name__ == "QgsVectorLayer":
+ timeLayerClass = TimeVectorLayer
+
+ if timeLayerClass == TimeVectorLayer:
+ layer.setSubsetString(l[1]) # restore the original subset string, only available for vector layers!
+
+ startTimeAttribute=l[2]
+ endTimeAttribute=l[3]
+ isEnabled=l[4]
timeFormat=l[5]
+
try:
offset=l[6]
except IndexError: # old versions didn't have an offset option
offset=0
- try:
- timeLayer = TimeLayer(layer,fromTimeAttribute,toTimeAttribute,enabled=="True",timeFormat,offset) # create a new TimeLayer
+
+ try: # here we use the previously determined class
+ timeLayer = timeLayerClass(layer,startTimeAttribute,endTimeAttribute,isEnabled,timeFormat,offset)
except InvalidTimeLayerError, e:
QMessageBox.information(self.iface.mainWindow(),'Error','An error occured while trying to add layer '+layer.name()+' to TimeManager.\n'+e.value)
return False
+
+ if not timeLayer:
+ break
+
self.timeLayerManager.registerTimeLayer(timeLayer)
self.guiControl.showLabel = True
self.guiControl.refreshMapCanvas('restoreTimeLayer')
- return True
-
+ return True
+
def restoreSettingCurrentMapTimePosition(self,value):
"""restore currentMapTimePosition"""
if value:
View
123 timemanagerguicontrol.py
@@ -18,9 +18,12 @@
from qgis.core import *
from timelayer import *
+from timevectorlayer import *
+from timerasterlayer import *
class TimeManagerGuiControl(QObject):
- """This class controls all plugin-related GUI elements. Emitted signals are defined here."""
+ """This class controls all plugin-related GUI elements. Emitted signals are defined here.
+ New TimeLayers are created here, in createTimeLayer()"""
def __init__ (self,iface,timeLayerManager):
"""initialize the GUI control"""
@@ -98,22 +101,24 @@ def showOptionsDialog(self,layerList,animationFrameLength,playBackwards,loopAnim
# restore options from layerList:
for layer in layerList:
+
layerName=layer.getName()
+ if layer.isEnabled():
+ checkState=Qt.Checked
+ else:
+ checkState=Qt.Unchecked
+ layerId=layer.getLayerId()
+
+ offset=layer.getOffset()
+
times=layer.getTimeAttributes()
startTime=times[0]
if times[0] != times[1]: # end time equals start time for timeLayers of type timePoint
endTime = times[1]
else:
endTime = ""
- if layer.isEnabled():
- checkState=Qt.Checked
- else:
- checkState=Qt.Unchecked
- layerId=layer.getLayerId()
timeFormat=layer.getTimeFormat()
- offset=layer.getOffset()
-
- self.addRowToOptionsTable(layerName,startTime,endTime,checkState,layerId,timeFormat,offset)
+ self.addRowToOptionsTable(layerName,checkState,layerId,offset,timeFormat,startTime,endTime)
# restore animation options
self.optionsDialog.spinBoxFrameLength.setValue(animationFrameLength)
@@ -150,46 +155,64 @@ def saveOptions(self):
# loop through the rows in the table widget and add all layers accordingly
for row in range(0,self.optionsDialog.tableWidget.rowCount()):
- # layer
- layer=QgsMapLayerRegistry.instance().mapLayer(self.optionsDialog.tableWidget.item(row,4).text())
- # start time
- startTimeAttribute = self.optionsDialog.tableWidget.item(row,1).text()
- # end time (optional)
- if self.optionsDialog.tableWidget.item(row,2).text() == QString(""):
- endTimeAttribute = startTimeAttribute # end time equals start time for timeLayers of type timePoint
- else:
- endTimeAttribute = self.optionsDialog.tableWidget.item(row,2).text()
- if self.optionsDialog.tableWidget.item(row,3).checkState() == Qt.Checked:
- isEnabled = True
+
+
+ if self.createTimeLayer(row):
+ # save animation options
+ animationFrameLength = self.optionsDialog.spinBoxFrameLength.value()
+ playBackwards = self.optionsDialog.checkBoxBackwards.isChecked()
+ self.showLabel = self.optionsDialog.checkBoxLabel.isChecked()
+ loopAnimation = self.optionsDialog.checkBoxLoop.isChecked()
+ self.emit(SIGNAL('setAnimationOptions(PyQt_PyObject,PyQt_PyObject,PyQt_PyObject)'),animationFrameLength,playBackwards,loopAnimation)
+
+ self.refreshMapCanvas('saveOptions')
+
+ if len(self.getManagedLayers()) > 0:
+ self.dock.pushButtonExportVideo.setEnabled(True)
+ else:
+ self.dock.pushButtonExportVideo.setEnabled(False)
+
+ self.emit(SIGNAL('saveOptionsEnd()'),)
else:
- isEnabled = False
- # time format
- timeFormat = self.optionsDialog.tableWidget.item(row,5).text()
- # offset
- offset = int(self.optionsDialog.tableWidget.item(row,6).text()) # currently only seconds!
- try:
- timeLayer = TimeLayer(layer,startTimeAttribute,endTimeAttribute,isEnabled,timeFormat,offset)
- except InvalidTimeLayerError, e:
- QMessageBox.information(self.iface.mainWindow(),'Error','An error occured while trying to add layer '+layer.name()+' to TimeManager.\n'+e.value)
break
- self.emit(SIGNAL('registerTimeLayer(PyQt_PyObject)'),timeLayer)
-
- # save animation options
- animationFrameLength = self.optionsDialog.spinBoxFrameLength.value()
- playBackwards = self.optionsDialog.checkBoxBackwards.isChecked()
- self.showLabel = self.optionsDialog.checkBoxLabel.isChecked()
- loopAnimation = self.optionsDialog.checkBoxLoop.isChecked()
- self.emit(SIGNAL('setAnimationOptions(PyQt_PyObject,PyQt_PyObject,PyQt_PyObject)'),animationFrameLength,playBackwards,loopAnimation)
-
- self.refreshMapCanvas('saveOptions')
-
- if len(self.getManagedLayers()) > 0:
- self.dock.pushButtonExportVideo.setEnabled(True)
+
+ def createTimeLayer(self,row):
+ """create a TimeLayer from options set in the table row"""
+ # layer
+ layer=QgsMapLayerRegistry.instance().mapLayer(self.optionsDialog.tableWidget.item(row,4).text())
+ if self.optionsDialog.tableWidget.item(row,3).checkState() == Qt.Checked:
+ isEnabled = True
else:
- self.dock.pushButtonExportVideo.setEnabled(False)
-
- self.emit(SIGNAL('saveOptionsEnd()'),)
+ isEnabled = False
+ # offset
+ offset = int(self.optionsDialog.tableWidget.item(row,6).text()) # currently only seconds!
+
+ # start time
+ startTimeAttribute = self.optionsDialog.tableWidget.item(row,1).text()
+ # end time (optional)
+ if self.optionsDialog.tableWidget.item(row,2).text() == QString(""):
+ endTimeAttribute = startTimeAttribute # end time equals start time for timeLayers of type timePoint
+ else:
+ endTimeAttribute = self.optionsDialog.tableWidget.item(row,2).text()
+ # time format
+ timeFormat = self.optionsDialog.tableWidget.item(row,5).text()
+
+ # this should be a python class factory
+ if type(layer).__name__ == "QgsVectorLayer":
+ timeLayerClass = TimeVectorLayer
+ elif type(layer).__name__ == "QgsRasterLayer":
+ timeLayerClass = TimeRasterLayer
+
+ try: # here we use the selected class
+ timeLayer = timeLayerClass(layer,startTimeAttribute,endTimeAttribute,isEnabled,timeFormat,offset)
+ except InvalidTimeLayerError, e:
+ QMessageBox.information(self.iface.mainWindow(),'Error','An error occured while trying to add layer '+layer.name()+' to TimeManager.\n'+e.value)
+ return False
+
+ self.emit(SIGNAL('registerTimeLayer(PyQt_PyObject)'),timeLayer)
+ return True
+
def setOptionsDialogToNone(self):
"""set self.optionsDialog to None"""
self.optionsDialog = None
@@ -215,10 +238,10 @@ def showAddLayerDialog(self):
tempname=''
# fill the combo box with all available vector layers
for (name,layer) in self.mapLayers.iteritems():
- if type(layer).__name__ == "QgsVectorLayer" and layer not in managedLayers:
+ #if type(layer).__name__ == "QgsVectorLayer" and layer not in managedLayers:
+ if layer not in managedLayers:
self.layerIds.append(name)
- # stripping out the trailing numeric code:
- tempname = str(layer.name()).rstrip('01234567890')
+ tempname = str(layer.name())#.rstrip('01234567890') # stripping out the trailing numeric code
self.addLayerDialog.comboBoxLayers.addItem(tempname)
if len(self.layerIds) == 0:
@@ -274,9 +297,9 @@ def addLayerToOptions(self):
timeFormat = "%Y-%m-%d %H:%M:%S" # default
offset = self.addLayerDialog.spinBoxOffset.value()
- self.addRowToOptionsTable(layerName,startTime,endTime,checkState,layerId,timeFormat,offset)
+ self.addRowToOptionsTable(layerName,checkState,layerId,offset,timeFormat,startTime,endTime)
- def addRowToOptionsTable(self,layerName,startTime,endTime,checkState,layerId,timeFormat,offset):
+ def addRowToOptionsTable(self,layerName,checkState,layerId,offset,timeFormat="",startTime="",endTime=""):
"""insert a new row into optionsDialog.tableWidget"""
# insert row
row=self.optionsDialog.tableWidget.rowCount()
View
6 timemanagerprojecthandler.py
@@ -50,7 +50,11 @@ def readSettings(self,settings):
self.readingSettings = True
# map data types to function names
- prj = QgsProject.instance()
+ try:
+ prj = QgsProject.instance()
+ except:
+ return None
+
functions = { 'str' : prj.readEntry,
'QString' : prj.readEntry,
'int' : prj.readNumEntry,
View
112 timerasterlayer.py
@@ -0,0 +1,112 @@
+# -*- coding: utf-8 -*-
+"""
+Created on Thu Mar 22 18:33:13 2012
+
+@author: Anita
+"""
+
+
+from datetime import datetime, timedelta
+from qgis.core import *
+from timelayer import *
+
+class TimeRasterLayer(TimeLayer):
+ def __init__(self,layer,fromTimeAttribute="",toTimeAttribute="",enabled=True,timeFormat="%Y-%m-%d %H:%M:%S",offset=0):
+ TimeLayer.__init__(self,layer,enabled)
+
+ self.layer = layer
+ self.fromTimeAttribute = fromTimeAttribute
+ self.toTimeAttribute = toTimeAttribute
+ self.timeFormat = timeFormat
+ self.supportedFormats = [
+ "%Y-%m-%d %H:%M:%S",
+ "%Y-%m-%d %H:%M:%S.%f",
+ "%Y-%m-%d %H:%M",
+ "%Y-%m-%d",
+ "%Y/%m/%d %H:%M:%S"]
+ self.offset = int(offset)
+
+ try:
+ self.getTimeExtents()
+ except NotATimeAttributeError, e:
+ raise InvalidTimeLayerError(e.value)
+
+ def getTimeAttributes(self):
+ """return the tuple of timeAttributes (fromTimeAttribute,toTimeAttribute)"""
+ return(self.fromTimeAttribute,self.toTimeAttribute)
+
+ def getTimeFormat(self):
+ """returns the layer's time format"""
+ return self.timeFormat
+
+ def getOffset(self):
+ """returns the layer's offset, integer in seconds"""
+ return self.offset
+
+ def strToDatetime(self, datetimeString):
+ """convert a date/time string into a Python datetime object"""
+ datetimeString = str(datetimeString)
+ try:
+ # Try the last known format, if not, try all known formats.
+ return datetime.strptime(datetimeString, self.timeFormat)
+ except:
+ for format in self.supportedFormats:
+ try:
+ self.timeFormat = format
+ return datetime.strptime(datetimeString, self.timeFormat)
+ except:
+ pass
+ # If all fail, re-raise the exception
+ raise
+
+ def getTimeExtents( self ):
+ """Get layer's temporal extent using the fields and the format defined somewhere else!"""
+ startStr = self.fromTimeAttribute
+ endStr = self.toTimeAttribute
+ try:
+ startTime = self.strToDatetime(startStr)
+ except ValueError:
+ raise NotATimeAttributeError(str(self.fromTimeAttribute)+': The attribute specified for use as start time contains invalid data:\n\n'+startStr+'\n\nis not one of the supported formats:\n'+str(self.supportedFormats))
+ try:
+ endTime = self.strToDatetime(endStr)
+ except ValueError:
+ raise NotATimeAttributeError(str(self.toTimeAttribute)+': The attribute specified for use as end time contains invalid data:\n'+endStr)
+ # apply offset
+ startTime += timedelta(seconds=self.offset)
+ endTime += timedelta(seconds=self.offset)
+ return (startTime,endTime)
+
+ def setTimeRestriction(self,timePosition,timeFrame):
+ """Constructs the query, including the original subset"""
+ if not self.timeEnabled:
+ self.deleteTimeRestriction()
+ return
+
+ startTime = timePosition + timedelta(seconds=self.offset)
+ endTime = timePosition + timeFrame + timedelta(seconds=self.offset)
+
+ if self.strToDatetime(self.fromTimeAttribute) < endTime and self.strToDatetime(self.toTimeAttribute) >= startTime:
+ # if the timestamp is within the extent --> show the raster
+ self.layer.setTransparency(255) # no transparency
+ else: # hide the raster
+ self.layer.setTransparency(0) # total transparency
+
+ def deleteTimeRestriction(self):
+ """The layer is removed from Time Manager and is therefore always shown"""
+ self.layer.setTransparency(255)
+
+ def hasTimeRestriction(self):
+ """returns true if current layer.subsetString is not equal to originalSubsetString"""
+ return True #self.layer.subsetString != self.originalSubsetString
+
+ def getSaveString(self):
+ """get string to save in project file"""
+ delimiter = ';'
+ saveString = self.getLayerId() + delimiter
+ saveString += '' + delimiter
+ saveString += self.fromTimeAttribute + delimiter
+ saveString += self.toTimeAttribute + delimiter
+ saveString += str(self.timeEnabled) + delimiter
+ saveString += self.timeFormat + delimiter
+ saveString += str(self.offset)
+ return saveString
View
116 timevectorlayer.py
@@ -0,0 +1,116 @@
+# -*- coding: utf-8 -*-
+"""
+Created on Thu Mar 22 17:28:19 2012
+
+@author: Anita
+"""
+
+from datetime import datetime, timedelta
+from qgis.core import *
+from timelayer import *
+
+class TimeVectorLayer(TimeLayer):
+ def __init__(self,layer,fromTimeAttribute,toTimeAttribute,enabled=True,timeFormat="%Y-%m-%d %H:%M:%S",offset=0):
+ TimeLayer.__init__(self,layer,enabled)
+
+ self.layer = layer
+ self.fromTimeAttribute = fromTimeAttribute
+ self.toTimeAttribute = toTimeAttribute
+ self.timeEnabled = enabled
+ self.originalSubsetString = self.layer.subsetString()
+ self.timeFormat = str(timeFormat) # cast in case timeFormat comes as a QString
+ self.supportedFormats = [
+ "%Y-%m-%d %H:%M:%S",
+ "%Y-%m-%d %H:%M:%S.%f",
+ "%Y-%m-%d %H:%M",
+ "%Y-%m-%d",
+ "%Y/%m/%d %H:%M:%S"]
+ if timeFormat not in self.supportedFormats:
+ self.supportedFormats.append(timeFormat)
+ self.offset = int(offset)
+ try:
+ self.getTimeExtents()
+ except NotATimeAttributeError, e:
+ raise InvalidTimeLayerError(e.value)
+
+ def getTimeAttributes(self):
+ """return the tuple of timeAttributes (fromTimeAttribute,toTimeAttribute)"""
+ return(self.fromTimeAttribute,self.toTimeAttribute)
+
+ def getTimeFormat(self):
+ """returns the layer's time format"""
+ return self.timeFormat
+
+ def getOffset(self):
+ """returns the layer's offset, integer in seconds"""
+ return self.offset
+
+ def strToDatetime(self, dtStr):
+ """convert a date/time string into a Python datetime object"""
+ try:
+ # Try the last known format, if not, try all known formats.
+ return datetime.strptime(dtStr, self.timeFormat)
+ except:
+ for fmt in self.supportedFormats:
+ try:
+ self.timeFormat = fmt
+ return datetime.strptime(dtStr, self.timeFormat)
+ except:
+ pass
+ # If all fail, re-raise the exception
+ raise
+
+ def getTimeExtents( self ):
+ """Get layer's temporal extent using the fields and the format defined somewhere else!"""
+ provider=self.layer.dataProvider()
+ fromTimeAttributeIndex = provider.fieldNameIndex(self.fromTimeAttribute)
+ toTimeAttributeIndex = provider.fieldNameIndex(self.toTimeAttribute)
+ startStr = str(provider.minimumValue(fromTimeAttributeIndex).toString())
+ endStr = str(provider.maximumValue(toTimeAttributeIndex).toString())
+ try:
+ startTime = self.strToDatetime(startStr)
+ except ValueError:
+ raise NotATimeAttributeError(str(self.getName())+': The attribute specified for use as start time contains invalid data:\n\n'+startStr+'\n\nis not one of the supported formats:\n'+str(self.supportedFormats))
+ try:
+ endTime = self.strToDatetime(endStr)
+ except ValueError:
+ raise NotATimeAttributeError(str(self.getName())+': The attribute specified for use as end time contains invalid data:\n'+endStr)
+ # apply offset
+ startTime += timedelta(seconds=self.offset)
+ endTime += timedelta(seconds=self.offset)
+ return (startTime,endTime)
+
+ def setTimeRestriction(self,timePosition,timeFrame):
+ """Constructs the query, including the original subset"""
+ if not self.timeEnabled:
+ self.deleteTimeRestriction()
+ return
+ startTime = datetime.strftime(timePosition + timedelta(seconds=self.offset),self.timeFormat)
+ endTime = datetime.strftime((timePosition + timeFrame + timedelta(seconds=self.offset)),self.timeFormat)
+ #subsetString = "\"%s\" < '%s' AND \"%s\" >= '%s' " % ( self.fromTimeAttribute,endTime,self.toTimeAttribute,startTime)
+ if self.originalSubsetString == "":
+ subsetString = "\"%s\" < '%s' AND \"%s\" >= '%s' " % ( self.fromTimeAttribute,endTime,self.toTimeAttribute,startTime)
+ else:
+ subsetString = "%s AND \"%s\" < '%s' AND \"%s\" >= '%s' " % ( self.originalSubsetString,self.fromTimeAttribute,endTime,self.toTimeAttribute,startTime)
+ self.layer.setSubsetString( subsetString )
+ #QMessageBox.information(self.iface.mainWindow(),"Test Output",subsetString)
+
+ def deleteTimeRestriction(self):
+ """Restore original subset"""
+ self.layer.setSubsetString( self.originalSubsetString )
+
+ def hasTimeRestriction(self):
+ """returns true if current layer.subsetString is not equal to originalSubsetString"""
+ return self.layer.subsetString != self.originalSubsetString
+
+ def getSaveString(self):
+ """get string to save in project file"""
+ delimiter = ';'
+ saveString = self.getLayerId() + delimiter
+ saveString += self.originalSubsetString + delimiter
+ saveString += self.fromTimeAttribute + delimiter
+ saveString += self.toTimeAttribute + delimiter
+ saveString += str(self.timeEnabled) + delimiter
+ saveString += self.timeFormat + delimiter
+ saveString += str(self.offset)
+ return saveString

0 comments on commit b510b7b

Please sign in to comment.
Something went wrong with that request. Please try again.