QGIS/python/plugins/osm/OsmUploadDlg.py
2011-09-15 21:33:42 +03:00

1549 lines
58 KiB
Python
Executable File

# -*- coding: utf-8 -*-
"""@package OsmUploadDlg
Module provides simple way of uploading current OSM data.
When performing edit operations all changed features are marked as 'U'=Updated.
All new features are marked as 'A'=Added and all removed features are marked as 'R'=Removed.
Uploader checks features statuses first.
Then it creates HTTP connection. Upload is done in correct order
so that data on OSM server always stay consistent.
Upload phases and their exact order:
- phases: 0.changeset creation, 1.nodes creation, 2.ways deletion, 3.ways update,
4.ways addition, 5.nodes deletion, 6.nodes update, 7.relation creation,
8.relation deletion, 9.relation update, 10.changeset closing
"""
from ui_OsmUploadDlg import Ui_OsmUploadDlg
import OsmPlugin
from PyQt4.QtCore import *
from PyQt4.QtGui import *
from PyQt4.QtNetwork import *
from sys import *
class OsmUploadDlg(QDialog, Ui_OsmUploadDlg):
"""Class provides simple way of uploading current OSM data.
When performing edit operations all changed features are marked as 'U'=Updated.
All new features are marked as 'A'=Added and all removed features are marked as 'R'=Removed.
Uploader checks features statuses first.
Then it creates HTTP connection. Upload is done in correct order
so that data on OSM server always stay consistent.
Upload phases and their exact order:
- phases: 0.changeset creation, 1.nodes creation, 2.ways deletion, 3.ways update,
4.ways addition, 5.nodes deletion, 6.nodes update, 7.relation creation,
8.relation deletion, 9.relation update, 10.changeset closing
"""
def __init__(self,plugin):
"""The constructor.
@param plugin is pointer to instance of OSM Plugin.
"""
QDialog.__init__(self,None)
self.setupUi(self)
self.dockWidget=plugin.dockWidget
self.plugin=plugin
self.dbm=plugin.dbm
self.ur=plugin.undoredo
self.urlHost = "api.openstreetmap.org"
self.uploadButton = self.buttonBox.addButton(self.tr("Upload"), QDialogButtonBox.ActionRole)
self.uploadChangesTable.setColumnCount(5)
self.uploadChangesTable.setColumnWidth(0,80)
self.uploadChangesTable.setColumnWidth(1,60)
self.uploadChangesTable.setColumnWidth(2,60)
self.uploadChangesTable.setColumnWidth(3,60)
self.uploadChangesTable.setColumnWidth(4,60)
self.uploadChangesTable.setHeaderLabels(["","Points","Lines","Polygons","Relations"])
key=QString(self.dbm.currentKey)
p1=key.lastIndexOf(".")
p2=key.lastIndexOf("/")
key=key.mid(p2+1,p1-p2-1)
self.groupBox.setTitle(QString("Changes in ").append(key))
item = QTreeWidgetItem(["Added","0","0","0","0"])
for i in range(1,5):
item.setTextAlignment(i,Qt.AlignHCenter)
self.uploadChangesTable.addTopLevelItem(item)
item = QTreeWidgetItem(["Removed","0","0","0","0"])
for i in range(1,5):
item.setTextAlignment(i,Qt.AlignHCenter)
self.uploadChangesTable.addTopLevelItem(item)
item = QTreeWidgetItem(["Changed","0","0","0","0"])
for i in range(1,5):
item.setTextAlignment(i,Qt.AlignHCenter)
self.uploadChangesTable.addTopLevelItem(item)
self.userLineEdit.setFocus()
self.passwdLineEdit.setEchoMode(QLineEdit.Password)
self.uploadButton.setEnabled(False)
self.pseudoId_map={}
self.featureId_map={}
self.qhttp_map={}
self.progressDialog=QProgressDialog(self)
self.progressDialog.setModal(True)
self.finished=False
self.httpRequestAborted=False
self.savePasswd=False
self.changesetId=None
settings=QSettings()
if settings.contains("/OSM_Plugin/uploadUser"):
uplUser=settings.value("/OSM_Plugin/uploadUser",QVariant(QString())).toString()
self.userLineEdit.setText(uplUser)
if settings.contains("/OSM_Plugin/uploadPasswd"):
uplPasswd=settings.value("/OSM_Plugin/uploadPasswd",QVariant(QString())).toString()
self.passwdLineEdit.setText(uplPasswd)
self.chkSavePasswd.setChecked(True)
self.commentTextEdit.setFocus()
# phases: 0.changeset creation, 1.nodes creation, 2.ways deletion, 3.ways update,
# 4.ways addition, 5.nodes deletion, 6.nodes update, 7.relation creation,
# 8.relation deletion, 9.relation update, 10.changeset closing
self.phase=-1
self.cntPhases=11
self.cntActionsInPhase=[0]*self.cntPhases
self.cntActionsInPhaseDone=0
self.cntActionsDone=0
self.createStatistics()
if self.cntActionsAll<=2:
# no action to upload (except for changeset opening and closing)
self.commentTextEdit.setEnabled(False)
self.accountGroupBox.setEnabled(False)
self.showStatistics()
self.__prepareDatabaseQueries()
# connect signals
self.connect(self.uploadButton, SIGNAL("clicked()"), self.uploadChanges)
self.connect(self.userLineEdit, SIGNAL("textChanged(const QString &)"), self.enableUploadButton)
self.connect(self.passwdLineEdit, SIGNAL("textChanged(const QString &)"), self.enableUploadButton)
self.connect(self.chkShowPasswd, SIGNAL("clicked()"), self.__showPassword)
self.connect(self.chkSavePasswd, SIGNAL("clicked()"), self.__savePassword)
self.connect(self.progressDialog, SIGNAL("canceled()"), self.__cancelProgressDlg)
self.enableUploadButton()
# http connection
self.http=QHttp(self)
self.connect(self.http,SIGNAL("responseHeaderReceived(QHttpResponseHeader)"), self.__readResponseHeader)
self.connect(self.http,SIGNAL("authenticationRequired(const QString &, quint16, QAuthenticator *)"), self.__authRequired)
self.__setProxy()
self.reqSetHost=self.http.setHost(self.urlHost, 80)
self.httpRequestAborted = False
self.httpRequestCanceled = False
self.httpRequestZombie = False
self.responseHeader=""
# increase maximum recursion depth in python (__uploadStep is recursive function)
setrecursionlimit(1000000)
def uploadChanges(self):
"""Main function; starts the whole upload process.
If checkbox for password saving was checked, password is stored to Quantum GIS settings.
"""
self.progressDialog.setWindowTitle(self.tr("OSM Upload"))
self.progressDialog.setLabelText(self.tr("Uploading data..."))
self.uploadButton.setEnabled(False)
self.cursor=self.dbm.getConnection().cursor()
settings=QSettings()
settings.setValue("/OSM_Plugin/uploadUser",QVariant(self.userLineEdit.text()))
if self.savePasswd:
settings.setValue("/OSM_Plugin/uploadPasswd",QVariant(self.passwdLineEdit.text()))
else:
settings.remove("/OSM_Plugin/uploadPasswd")
self.reqSetUser=self.http.setUser(self.userLineEdit.text(),self.passwdLineEdit.text())
# start upload with its first step (the next steps will follow automatically)
self.__uploadStep()
def __uploadStep(self):
"""Function calls the next step of uploading.
"""
# first update progressbar value
self.progressDialog.setMaximum(self.cntActionsAll)
self.progressDialog.setValue(self.cntActionsDone)
# check if (in actual upload phase) number of done actions reach all actions that should be done;
# if it does, switch actual upload phase to the next one in the order
if (self.phase==-1) or (self.cntActionsInPhaseDone==self.cntActionsInPhase[self.phase]):
self.dbm.commit() # commit actions performed in finished phase
# search for first next phase in which some upload actions should be done
self.phase+=1
while self.phase<self.cntPhases and self.cntActionsInPhase[self.phase]==0:
self.phase+=1
# is there another phase to run?
if self.phase>=self.cntPhases:
self.cursor.close() # all upload phases were finished!
self.__finishUpload()
return
# yes, it is ;) tell its number
# print QString("Starting upload phase no.%1.").arg(self.phase)
# if necessary set up database cursor
if not self.phase in (0,10):
self.cursor.execute(self.selectQuery[self.phase])
# no action has been done yet in running phase
self.cntActionsInPhaseDone = 0
# just print common info
# print QString("Running step %1 of upload phase %2.").arg(self.cntActionsInPhaseDone+1).arg(self.phase)
# perform next action in running phase
if self.phase not in (0,10):
record = self.cursor.fetchone()
if record == None:
# strange situation, number of features ready to upload in actual phase was actually lower than it was signalized
# by self.cntActionsAll; well, ignore this step and run the next one, that will start the next upload phase!
self.cntActionsInPhaseDone = self.cntActionsInPhase[self.phase]
self.__uploadStep()
if self.phase == 0: # compulsory changeset creation
self.__createChangeset()
elif self.phase == 1: # nodes creation
self.__uploadNodeAddition(record)
elif self.phase == 2: # ways deletion
self.__uploadWayDeletion(record)
elif self.phase == 3: # ways update
self.__uploadWayUpdate(record)
elif self.phase == 4: # ways creation
self.__uploadWayAddition(record)
elif self.phase == 5: # nodes deletion
self.__uploadNodeDeletion(record)
elif self.phase == 6: # nodes update
self.__uploadNodeUpdate(record)
elif self.phase == 7: # relations creation
self.__uploadRelationAddition(record)
elif self.phase == 8: # relations deletion
self.__uploadRelationDeletion(record)
elif self.phase == 9: # relations update
self.__uploadRelationUpdate(record)
elif self.phase == 10: # compulsory changeset closing
self.__closeChangeset()
else:
print "Program shouldn't reach this place! (2)"
return
def __showPassword(self):
"""Function to show hidden password on dialog box,
so that user can verify if he has written it right.
"""
if self.chkShowPasswd.isChecked():
self.passwdLineEdit.setEchoMode(QLineEdit.Normal)
else:
self.passwdLineEdit.setEchoMode(QLineEdit.Password)
def __savePassword(self):
"""Function to show hidden password on dialog box,
so that user can verify if he has written it right.
"""
if self.chkSavePasswd.isChecked():
self.savePasswd=True
else:
self.savePasswd=False
def createStatistics(self):
"""Function finds out number of steps for all upload phases.
These statistics are found out with examining features' statuses.
Results are stored in uploaders' member variables.
"""
c=self.dbm.getConnection().cursor()
self.cntActionsAll = 0
# phases: 0.changeset creation, 1.nodes creation, 2.ways deletion, 3.ways update,
# 4.ways addition, 5.nodes deletion, 6.nodes update, 7.relation creation,
# 8.relation deletion, 9.relation update, 10.changeset closing
c.execute("select count(*) from node where status='A' and u=1")
for row in c:
self.cntNodesCreated = row[0]
self.cntActionsAll += row[0]
c.execute("select count(*) from way where status='A' and closed=0 and u=1")
for row in c:
self.cntLinesCreated = row[0]
self.cntActionsAll += row[0]
c.execute("select count(*) from way where status='A' and closed=1 and u=1")
for row in c:
self.cntPolygonsCreated = row[0]
self.cntActionsAll += row[0]
c.execute("select count(*) from node where status='R' and u=1")
for row in c:
self.cntNodesRemoved = row[0]
self.cntActionsAll += row[0]
c.execute("select count(*) from way where status='R' and closed=0 and u=1")
for row in c:
self.cntLinesRemoved = row[0]
self.cntActionsAll += row[0]
c.execute("select count(*) from way where status='R' and closed=1 and u=1")
for row in c:
self.cntPolygonsRemoved = row[0]
self.cntActionsAll += row[0]
c.execute("select count(*) from node where status='U' and u=1")
for row in c:
self.cntNodesUpdated = row[0]
self.cntActionsAll += row[0]
c.execute("select count(*) from way where status='U' and closed=0 and u=1")
for row in c:
self.cntLinesUpdated = row[0]
self.cntActionsAll += row[0]
c.execute("select count(*) from way where status='U' and closed=1 and u=1")
for row in c:
self.cntPolygonsUpdated = row[0]
self.cntActionsAll += row[0]
c.execute("select count(*) from relation where status='A' and u=1")
for row in c:
self.cntRelationsCreated = row[0]
self.cntActionsAll += row[0]
c.execute("select count(*) from relation where status='R' and u=1")
for row in c:
self.cntRelationsRemoved = row[0]
self.cntActionsAll += row[0]
c.execute("select count(*) from relation where status='U' and u=1")
for row in c:
self.cntRelationsUpdated = row[0]
self.cntActionsAll += row[0]
self.cntActionsInPhase[0] = 1
self.cntActionsInPhase[1] = self.cntNodesCreated
self.cntActionsInPhase[2] = self.cntLinesRemoved+self.cntPolygonsRemoved
self.cntActionsInPhase[3] = self.cntLinesUpdated+self.cntPolygonsUpdated
self.cntActionsInPhase[4] = self.cntLinesCreated+self.cntPolygonsCreated
self.cntActionsInPhase[5] = self.cntNodesRemoved
self.cntActionsInPhase[6] = self.cntNodesUpdated
self.cntActionsInPhase[7] = self.cntRelationsCreated
self.cntActionsInPhase[8] = self.cntRelationsRemoved
self.cntActionsInPhase[9] = self.cntRelationsUpdated
self.cntActionsInPhase[10] = 1
self.cntActionsAll += 2
c.close()
def zeroStatistics(self):
"""Function cancels all statistics of uploader.
"""
for i in range(1,self.cntPhases-1):
self.cntActionsInPhase[i] = 0
self.cntActionsAll = 2
self.cntNodesCreated = 0
self.cntLinesRemoved = 0
self.cntPolygonsRemoved = 0
self.cntLinesCreated = 0
self.cntPolygonsCreated = 0
self.cntNodesRemoved = 0
self.cntNodesUpdated = 0
self.cntLinesUpdated = 0
self.cntPolygonsUpdated = 0
self.cntRelationsCreated = 0
self.cntRelationsRemoved = 0
self.cntRelationsUpdated = 0
def showStatistics(self):
"""Function shows (statistics) counts of typical actions that are ready for upload.
Showing them is realized on OSM upload dialog with appropriate table of statistics.
"""
# phases: 0.changeset creation, 1.nodes creation, 2.ways deletion, 3.ways addition,
# 4.nodes deletion, 5.nodes update, 6.ways update, 7.relations addition, 8.relations deletion,
# 9.relations update, 10.changeset closing
self.uploadChangesTable.topLevelItem(0).setText(1,str(self.cntNodesCreated))
self.uploadChangesTable.topLevelItem(1).setText(1,str(self.cntNodesRemoved))
self.uploadChangesTable.topLevelItem(2).setText(1,str(self.cntNodesUpdated))
self.uploadChangesTable.topLevelItem(0).setText(2,str(self.cntLinesCreated))
self.uploadChangesTable.topLevelItem(1).setText(2,str(self.cntLinesRemoved))
self.uploadChangesTable.topLevelItem(2).setText(2,str(self.cntLinesUpdated))
self.uploadChangesTable.topLevelItem(0).setText(3,str(self.cntPolygonsCreated))
self.uploadChangesTable.topLevelItem(1).setText(3,str(self.cntPolygonsRemoved))
self.uploadChangesTable.topLevelItem(2).setText(3,str(self.cntPolygonsUpdated))
self.uploadChangesTable.topLevelItem(0).setText(4,str(self.cntRelationsCreated))
self.uploadChangesTable.topLevelItem(1).setText(4,str(self.cntRelationsRemoved))
self.uploadChangesTable.topLevelItem(2).setText(4,str(self.cntRelationsUpdated))
def __prepareDatabaseQueries(self):
"""Function prepares SQL queries for selecting objects to upload.
Resulting array of queries is stored in member variable.
"""
self.selectQuery = [
# changeset creation
""
# nodes creation
,"select n.id, n.lat, n.lon, n.user, n.timestamp, (select version_id \
from version where object_id=n.id and object_type='node') version_id from node n where n.status='A' and n.u=1"
# ways deletion
,"select w.id, w.user, w.timestamp, (select version_id from version where \
object_id=w.id and object_type='way') version_id, w.closed from way w where w.status='R' and w.u=1"
# ways update
,"select w.id, w.user, w.timestamp, (select version_id from version \
where object_id=w.id and object_type='way') version_id, w.closed from way w where w.status='U' and w.u=1"
# ways creation
,"select w.id, w.user, w.timestamp, (select version_id from version \
where object_id=w.id and object_type='way') version_id, w.closed from way w where w.status='A' and w.u=1"
# nodes deletion
,"select n.id, n.lat, n.lon, n.user, n.timestamp, (select version_id \
from version where object_id=n.id and object_type='node') version_id from node n where n.status='R' and n.u=1"
# nodes update
,"select n.id, n.lat, n.lon, n.user, n.timestamp, (select version_id \
from version where object_id=n.id and object_type='node') version_id from node n where n.status='U' and n.u=1"
# relations creation
,"select r.id, r.user, r.timestamp, (select version_id \
from version where object_id=r.id and object_type='relation') version_id from relation r where r.status='A' and r.u=1"
# relations deletion
,"select r.id, r.user, r.timestamp, (select version_id \
from version where object_id=r.id and object_type='relation') version_id from relation r where r.status='R' and r.u=1"
# relations update
,"select r.id, r.user, r.timestamp, (select version_id \
from version where object_id=r.id and object_type='relation') version_id from relation r where r.status='U' and r.u=1"
# changeset closing
,""
]
def __uploadNodeAddition(self, nodeRecord):
"""Sends upload request for addition of new node.
@param nodeRecord tuple object with information on node
"""
# create http connection with necessary authentication
urlPath = "/api/0.6/node/create"
# set http request's header
header = QHttpRequestHeader("PUT", urlPath,1,1)
header.setValue("Host", self.urlHost)
header.setValue("Connection", "keep-alive")
header.setContentType("text/xml; charset=utf-8")
# create http request's body (create XML with info about uploaded node)
requestXml = self.createNodeXml(nodeRecord)
# connect http response signals to appropriate functions
self.connect(self.http, SIGNAL("requestFinished(int, bool)"), self.__httpNodeAdditionReqFinished)
# send prepared request
requestBytes = requestXml.toAscii()
httpSessionId = self.http.request(header, requestBytes)
# remember http connection object and pseudoId, that was used
# to node's identification in sqlite3 database
self.qhttp_map[httpSessionId]=1
self.pseudoId_map[httpSessionId]=nodeRecord[0]
def __uploadNodeUpdate(self, nodeRecord):
"""Sends upload request for updating one node.
@param nodeRecord tuple object with information on node
"""
urlPath = QString("/api/0.6/node/%1").arg(nodeRecord[0])
# set http request's header
header = QHttpRequestHeader("PUT", urlPath,1,1)
header.setValue("Host", self.urlHost)
header.setValue("Connection", "keep-alive")
header.setContentType("text/xml; charset=utf-8")
# create http request's body (create XML with info about uploaded node)
requestXml = self.createNodeXml(nodeRecord)
# connect http response signals to appropriate functions
self.connect(self.http, SIGNAL("requestFinished(int, bool)"), self.__httpNodeUpdateReqFinished)
# send prepared request
requestBytes=requestXml.toAscii()
httpSessionId=self.http.request(header, requestBytes)
# remember http connection object
self.qhttp_map[httpSessionId]=1
self.featureId_map[httpSessionId]=nodeRecord[0]
def __uploadNodeDeletion(self, nodeRecord):
"""Send upload request for deletion of one node.
@param nodeRecord tuple object with information on node
"""
# create http connection with necessary authentication
urlPath = QString("/api/0.6/node/%1").arg(nodeRecord[0])
# set http request's header
header = QHttpRequestHeader("DELETE", urlPath,1,1)
header.setValue("Host", self.urlHost)
header.setValue("Connection", "keep-alive")
header.setContentType("text/xml; charset=utf-8")
# connect http response signals to appropriate functions
self.connect(self.http, SIGNAL("requestFinished(int, bool)"), self.__httpNodeDeletionReqFinished)
requestXml=self.createNodeDelXml(nodeRecord)
# send prepared request
requestBytes = requestXml.toAscii()
httpSessionId = self.http.request(header, requestBytes)
# remember http connection object
self.qhttp_map[httpSessionId]=1
self.featureId_map[httpSessionId]=nodeRecord[0]
def createNodeXml(self, nodeRecord):
"""Function creates XML that will be added as http body to node addition request.
@param nodeRecord tuple object with information on node
"""
requestXml = QString("<?xml version=\"1.0\" encoding=\"UTF-8\"?>")
version = nodeRecord[5] # version_id
requestXml.append(QString("<osm version=\"0.6\" generator=\"OpenStreetMap server\">"))
requestXml.append(QString("<node id=\"%1\" lat=\"%2\" lon=\"%3\" visible=\"true\" user=\"%4\" timestamp=\"%5\"")
.arg(nodeRecord[0]) # node_id
.arg(nodeRecord[1],0,'f',50) # lat
.arg(nodeRecord[2],0,'f',50) # lon
.arg(str(nodeRecord[3])) # user
.arg(str(nodeRecord[4])) # timestamp
)
if version<>None:
requestXml.append(QString(" version=\"%1\"").arg(str(version)))
requestXml.append(QString(" changeset=\"%1\">")
.arg(str(self.changesetId))
)
# selecting tags to construct correct XML
ct=self.dbm.getConnection().cursor()
ct.execute("select key, val from tag where object_id=:nodeId and object_type=\"node\" and u=1",{"nodeId":nodeRecord[0]})
for tagRecord in ct:
requestXml.append(QString("<tag k=\"%1\" v=\"%2\"/>").arg(tagRecord[0]).arg(tagRecord[1]))
ct.close()
requestXml.append(QString("</node></osm>"))
return requestXml
def createNodeDelXml(self, nodeRecord):
"""Function creates XML that will be added as http body to node deletion request.
@param nodeRecord tuple object with information on node
"""
requestXml = QString("<?xml version=\"1.0\" encoding=\"UTF-8\"?>")
requestXml.append(QString("<osm version=\"0.6\" generator=\"OpenStreetMap server\">"))
requestXml.append(QString("<node id=\"%1\" lat=\"%2\" lon=\"%3\" visible=\"true\" user=\"%4\" timestamp=\"%5\"")
.arg(nodeRecord[0])
.arg(nodeRecord[1],0,'f',50)
.arg(nodeRecord[2],0,'f',50)
.arg(str(nodeRecord[3]))
.arg(str(nodeRecord[4]))
)
requestXml.append(QString(" version=\"%1\"").arg(nodeRecord[5]))
requestXml.append(QString(" changeset=\"%1\"></node>").arg(str(self.changesetId)))
requestXml.append(QString("</osm>"))
return requestXml
def createWayXml(self, wayRecord):
"""Creates XML that have to be added as http body to way addition request.
@param wayRecord tuple object with information on way
"""
pseudoWayId = wayRecord[0]
requestXml = QString("<?xml version=\"1.0\" encoding=\"UTF-8\"?>")
version = wayRecord[3] # version_id
closed = wayRecord[4]
requestXml.append(QString("<osm version=\"0.6\" generator=\"OpenStreetMap server\">"))
requestXml.append(QString("<way id=\"%1\" visible=\"true\" timestamp=\"%3\" user=\"%2\"")
.arg(wayRecord[0]) # way_id
.arg(str(wayRecord[1])) # user
.arg(str(wayRecord[2])) # timestamp
)
if version<>None:
requestXml.append(QString(" version=\"%1\"").arg(str(version)))
requestXml.append(QString(" changeset=\"%1\">")
.arg(str(self.changesetId))
)
# selecting way members to construct correct XML
firstMember = None
cwm=self.dbm.getConnection().cursor()
cwm.execute("select node_id from way_member where way_id=:pseudoWayId and u=1",{"pseudoWayId": pseudoWayId})
for wayMemberRecord in cwm:
if firstMember==None:
firstMember=wayMemberRecord[0]
requestXml.append(QString("<nd ref=\"%1\"/>").arg(wayMemberRecord[0]))
cwm.close()
if closed==1:
tmp=None
if firstMember:
requestXml.append(QString("<nd ref=\"%1\"/>").arg(firstMember))
# selecting tags to construct correct XML
ct=self.dbm.getConnection().cursor()
ct.execute("select key, val from tag where object_id=:pseudoWayId and u=1",{"pseudoWayId": pseudoWayId})
for tagRecord in ct:
tmp=None
requestXml.append(QString("<tag k=\"%1\" v=\"%2\"/>").arg(tagRecord[0]).arg(tagRecord[1]))
ct.close()
# finish XML construction
requestXml.append(QString("</way></osm>"))
return requestXml
def __uploadWayAddition(self, wayRecord):
"""Sends upload request for addition of new way.
@param wayRecord tuple object with information on way
"""
pseudoWayId = wayRecord[0]
# create http connection with necessary authentication
urlPath = "/api/0.6/way/create"
# set http request's header
header = QHttpRequestHeader("PUT", urlPath,1,1)
header.setValue("Host", self.urlHost)
header.setValue("Connection", "keep-alive")
header.setContentType("text/xml; charset=utf-8")
# connect http response signals to appropriate functions
self.connect(self.http, SIGNAL("requestFinished(int, bool)"), self.__httpWayAdditionReqFinished)
# create http request's body (create XML with info about uploaded way)
requestXml = self.createWayXml(wayRecord)
# send prepared request
requestBytes = requestXml.toAscii()
httpSessionId = self.http.request(header, requestBytes)
# remember pseudoId, that was used to nodes identification in sqlite3 database
self.qhttp_map[httpSessionId]=1
self.pseudoId_map[httpSessionId]=pseudoWayId
def __uploadWayUpdate(self, wayRecord):
"""Send upload request for updating given way.
@param wayRecord tuple object with information on way
"""
# create http connection with necessary authentication
urlPath = QString("/api/0.6/way/%1").arg(wayRecord[0])
# set http request's header
header=QHttpRequestHeader("PUT", urlPath,1,1)
header.setValue("Host", self.urlHost)
header.setValue("Connection", "keep-alive")
header.setContentType("text/xml; charset=utf-8")
# connect http response signals to appropriate functions
self.connect(self.http, SIGNAL("requestFinished(int, bool)"), self.__httpWayUpdateReqFinished)
# create http request's body (create XML with info about uploaded way)
requestXml = self.createWayXml(wayRecord)
# send prepared request
requestBytes = requestXml.toAscii()
httpSessionId = self.http.request(header, requestBytes)
self.qhttp_map[httpSessionId]=1
self.featureId_map[httpSessionId]=wayRecord[0]
def __uploadWayDeletion(self, wayRecord):
"""Send upload request for removing given way.
@param wayRecord tuple object with information on way
"""
# create http connection with necessary authentication
urlPath = QString("/api/0.6/way/%1").arg(wayRecord[0])
# set http request's header
header = QHttpRequestHeader("DELETE", urlPath,1,1)
header.setValue("Host", self.urlHost)
header.setValue("Connection", "keep-alive")
header.setContentType("text/xml; charset=utf-8")
# connect http response signals to appropriate functions
self.connect(self.http, SIGNAL("requestFinished(int, bool)"), self.__httpWayDeletionReqFinished)
# create http request's body (create XML with info about uploaded way deletion)
requestXml = self.createWayXml(wayRecord)
# send prepared request
requestBytes = requestXml.toAscii()
httpSessionId = self.http.request(header, requestBytes)
# remember http connection object
self.qhttp_map[httpSessionId]=1
self.featureId_map[httpSessionId]=wayRecord[0]
def createRelationXml(self, relRecord):
"""Creates XML that will be added to relation addition/deletion/update http request.
@param relRecord tuple object with information on relation
"""
pseudoRelId = relRecord[0]
requestXml = QString("<?xml version=\"1.0\" encoding=\"UTF-8\"?>")
version = relRecord[3] # version_id
requestXml.append(QString("<osm version=\"0.6\" generator=\"OpenStreetMap server\">"))
requestXml.append(QString("<relation id=\"%1\" visible=\"true\" timestamp=\"%3\" user=\"%2\"")
.arg(relRecord[0]) # way_id
.arg(str(relRecord[1])) # user
.arg(str(relRecord[2])) # timestamp
)
if version<>None:
requestXml.append(QString(" version=\"%1\"").arg(str(version)))
requestXml.append(QString(" changeset=\"%1\">").arg(str(self.changesetId)))
# selecting way members to construct correct XML
firstMember = None
c=self.dbm.getConnection().cursor()
c.execute("select member_type, role, member_id from relation_member where relation_id=:pseudoRelId and u=1",{"pseudoRelId": pseudoRelId})
for relMemberRecord in c:
requestXml.append(QString("<member type=\"%1\"").arg(relMemberRecord[0]))
if relMemberRecord[1]<>None:
requestXml.append(QString(" role=\"%1\"").arg(relMemberRecord[1]))
requestXml.append(QString(" ref=\"%1\"/>").arg(relMemberRecord[2]))
c.close()
# selecting tags to construct correct XML
ct=self.dbm.getConnection().cursor()
ct.execute("select key, val from tag where object_id=:pseudoRelId and object_type='relation' and u=1",{"pseudoRelId": pseudoRelId})
for tagRecord in ct:
requestXml.append(QString("<tag k=\"%1\" v=\"%2\"/>").arg(tagRecord[0]).arg(tagRecord[1]))
ct.close()
# finish XML construction
requestXml.append(QString("</relation></osm>"))
return requestXml
def __uploadRelationAddition(self, relRecord):
"""Sends upload request for addition of new relation.
@param relRecord tuple object with information on relation
"""
pseudoRelId = relRecord[0]
# create http connection with necessary authentication
urlPath = "/api/0.6/relation/create"
# set http request's header
header = QHttpRequestHeader("PUT", urlPath,1,1)
header.setValue("Host", self.urlHost)
header.setValue("Connection", "keep-alive")
header.setContentType("text/xml; charset=utf-8")
# connect http response signals to appropriate functions
self.connect(self.http, SIGNAL("requestFinished(int, bool)"), self.__httpRelationAdditionReqFinished)
# create http request's body (create XML with info about uploaded way)
requestXml = self.createRelationXml(relRecord)
# send prepared request
requestBytes = requestXml.toAscii()
httpSessionId = self.http.request(header, requestBytes)
# remember pseudoId, that was used to nodes identification in sqlite3 database
self.qhttp_map[httpSessionId]=1
self.pseudoId_map[httpSessionId]=pseudoRelId
def __uploadRelationUpdate(self,relRecord):
"""Sends upload request for updating given relation.
@param relRecord tuple object with information on relation
"""
# create http connection with necessary authentication
urlPath = QString("/api/0.6/relation/%1").arg(relRecord[0])
# set http request's header
header=QHttpRequestHeader("PUT", urlPath,1,1)
header.setValue("Host", self.urlHost)
header.setValue("Connection", "keep-alive")
header.setContentType("text/xml; charset=utf-8")
# connect http response signals to appropriate functions
self.connect(self.http, SIGNAL("requestFinished(int, bool)"), self.__httpRelationUpdateReqFinished)
# create http request's body (create XML with info about uploaded way)
requestXml = self.createRelationXml(relRecord)
# send prepared request
requestBytes = requestXml.toAscii()
httpSessionId = self.http.request(header, requestBytes)
self.qhttp_map[httpSessionId]=1
self.featureId_map[httpSessionId]=relRecord[0]
def __uploadRelationDeletion(self, relRecord):
"""Function sends upload request for removing given relation.
@param relRecord tuple object with information on relation
"""
# create http connection with necessary authentication
urlPath = QString("/api/0.6/relation/%1").arg(relRecord[0])
# set http request's header
header=QHttpRequestHeader("DELETE", urlPath,1,1)
header.setValue("Host", self.urlHost)
header.setValue("Connection", "keep-alive")
header.setContentType("text/xml; charset=utf-8")
# connect http response signals to appropriate functions
self.connect(self.http, SIGNAL("requestFinished(int, bool)"), self.__httpRelationDeletionReqFinished)
# create http request's body (create XML with info about uploaded way deletion)
requestXml = self.createRelationXml(relRecord)
# send prepared request
requestBytes=requestXml.toAscii()
httpSessionId=self.http.request(header, requestBytes)
# remember http connection object
self.qhttp_map[httpSessionId]=1
self.featureId_map[httpSessionId]=relRecord[0]
def escape_html(self,text):
"""Function replaces chars that are problematic for html,
such as < > & " ' with &lt; &gt; &amp; &quot; &apos;
@param text text to replace problematic characters in
@return transformed text
"""
text=text.replace(QString("&"), QString("&amp;")); # must be first
text=text.replace(QString("<"), QString("&lt;"));
text=text.replace(QString(">"), QString("&gt;"));
text=text.replace(QString("\""), QString("&quot;"));
text=text.replace(QString("'"), QString("&apos;"));
return text
def __createChangeset(self):
"""Function sends request for creating new OSM changeset.
Changeset creation has to be first upload action.
Changeset closing has to be the last one.
"""
# create http connection with necessary authentication
urlPath="/api/0.6/changeset/create"
# set http request's header
header=QHttpRequestHeader("PUT",urlPath,1,1)
header.setValue("Host", self.urlHost)
header.setValue("Connection", "keep-alive")
header.setContentType("text/xml; charset=utf-8")
# connect http response signals to appropriate functions
self.connect(self.http, SIGNAL("requestFinished(int, bool)"), self.__httpChangesetCreationReqFinished)
# get user comment on upload actions
userComment=self.commentTextEdit.toPlainText()
userComment=self.escape_html(userComment)
userCommentBytes=userComment.toUtf8()
# create http request's body (create XML with info about uploaded way)
requestXml=QString("<osm>\n<changeset>\n<tag k=\"created_by\" v=\"QGIS OSM v"+OsmPlugin.versionNumber()+"\"/>\n<tag k=\"comment\" v=\""+userCommentBytes.data()+"\"/>\n</changeset>\n</osm>")
# send prepared request
requestBytes=requestXml.toAscii()
httpSessionId=self.http.request(header, requestBytes)
# remember http connection object
self.qhttp_map[httpSessionId]=1
def __closeChangeset(self):
"""Function sends request for closing opened OSM changeset.
Changeset creation has to be first upload action.
Changeset closing has to be the last one.
"""
# create http connection with necessary authentication
urlPath = QString("/api/0.6/changeset/%1/close").arg(self.changesetId)
# set http request's header
header = QHttpRequestHeader("PUT",urlPath,1,1)
header.setValue("Host", self.urlHost)
header.setValue("Connection", "keep-alive")
header.setContentLength(0)
# connect http response signals to appropriate functions
self.connect(self.http, SIGNAL("requestFinished(int, bool)"), self.__httpChangesetClosingReqFinished)
self.changesetId=None
# send prepared request
httpSessionId=self.http.request(header)
# remember http connection object
self.qhttp_map[httpSessionId]=1
def enableUploadButton(self):
"""Function finds out if it is possible to enable upload button.
If yes, function just enables it, else it disables it.
Following condition has to be satisfied to enable upload button:
-There has to be something to upload.
-Both user login and password has to be filled.
"""
user=self.userLineEdit.text()
passwd=self.passwdLineEdit.text()
if not self.finished and user<>"" and passwd<>"" and self.cntActionsAll>2:
self.uploadButton.setEnabled(True)
else:
self.uploadButton.setEnabled(False)
def __finishUpload(self):
"""This is function that runs after all edit actions changes are uploaded to OSM server.
It clears edit changes tables, hide progress bar, clear statistics,
clear undo/redo data, etc.
"""
self.finished = True
self.progressDialog.hide()
# delete database records with status='R' (Remove)
self.dbm.removeUselessRecords()
# show info that there are no more actions to upload
self.zeroStatistics()
self.showStatistics()
# disable dialog items
self.userLineEdit.setEnabled(False)
self.passwdLineEdit.setEnabled(False)
self.chkShowPasswd.setEnabled(False)
self.accept()
# clear undo/redo
self.ur.clear()
def cancelUpload(self,errMessage=None):
"""Function aborts the whole upload operation.
In errMessage function gets the reason of upload canceling (error message).
If OSM changeset was already opened while uploading, HTTP request to close it is send immediately.
The HTTP connection of uploader is aborted, progress dialog is closed and the whole upload dialog is rejected.
If there is some errMessage parameter, the message is shown to user.
@param errMessage message to tell user after canceling upload
"""
if self.httpRequestAborted:
return
if self.changesetId:
urlPath=QString("/api/0.6/changeset/%1/close").arg(self.changesetId)
header=QHttpRequestHeader("PUT",urlPath,1,1)
header.setValue("Host", self.urlHost)
header.setValue("Connection", "keep-alive")
httpSessionId=self.http.request(header)
self.httpRequestAborted=True
self.http.abort()
self.uploadButton.setEnabled(True)
self.disconnect(self.progressDialog, SIGNAL("canceled()"), self.__cancelProgressDlg)
self.progressDialog.close()
self.reject()
if errMessage and errMessage<>"":
QMessageBox.information(self,self.tr("OSM Upload"),errMessage)
def __cancelProgressDlg(self):
"""This functions catches the signal emitted when clicking on Cancel button of progress dialog.
It aborts opened HTTP connection and closes upload dialog.
"""
if self.httpRequestAborted:
return
self.httpRequestAborted=True
self.http.abort()
self.uploadButton.setEnabled(True)
self.reject()
##########################################################
# !!!!! HTTP RESPONSES FROM OPENSTREETMAP SERVER !!!!! #
##########################################################
def __httpNodeAdditionReqFinished(self, requestId, error):
"""Function is called when requestFinished(...) signal is emitted on global HTTP connection object
and "node adition" is current uploader's phase.
OSM server returns id that was assigned to uploaded node.
@param requestId identifier of http request
@param error True if error occured on given request; False otherwise
"""
if self.httpRequestAborted:
return
if not requestId in self.qhttp_map:
self.__examineResponse(requestId,error)
return
self.disconnect(self.http, SIGNAL("requestFinished(int, bool)"), self.__httpNodeAdditionReqFinished)
nodePseudoId=self.pseudoId_map[requestId]
del self.qhttp_map[requestId]
del self.pseudoId_map[requestId]
if error:
self.cancelUpload( self.tr("Node addition failed.") )
return
newNodeIdStr=QString(self.http.readAll().data())
newNodeId=(newNodeIdStr.toInt())[0]
# update node's identification in sqlite3 database
self.dbm.updateNodeId(nodePseudoId,newNodeId,self.userLineEdit.text())
self.dbm.recacheAffectedNow([(nodePseudoId,'Point'),(newNodeId,'Point')])
# call the next upload step
self.cntActionsInPhaseDone+=1
self.cntActionsDone+=1
self.__uploadStep()
def __httpNodeUpdateReqFinished(self, requestId, error):
"""Function is called when requestFinished(...) signal is emitted on global HTTP connection object
and "node updating" is current uploader's phase.
OSM server returns id of new node's version.
@param requestId identifier of http request
@param error True if error occured on given request; False otherwise
"""
if self.httpRequestAborted:
return
if not requestId in self.qhttp_map:
self.__examineResponse(requestId,error)
return
self.disconnect(self.http, SIGNAL("requestFinished(int, bool)"), self.__httpNodeUpdateReqFinished)
pointId=self.featureId_map[requestId]
del self.qhttp_map[requestId]
del self.featureId_map[requestId]
if error:
self.cancelUpload(self.tr("Node update failed."))
return
newVersionIdStr=QString(self.http.readAll().data())
newVersionId=(newVersionIdStr.toInt())[0]
self.dbm.updateVersionId(pointId,'node',newVersionId)
self.dbm.updateUser(pointId,'node',self.userLineEdit.text())
self.dbm.changePointStatus(pointId,'U','N')
self.dbm.recacheAffectedNow([(pointId,'Point')])
# call the next upload step
self.cntActionsInPhaseDone+=1
self.cntActionsDone+=1
self.__uploadStep()
def __httpNodeDeletionReqFinished(self, requestId, error):
"""Function is called when requestFinished(...) signal is emitted on global HTTP connection object
and "node deletion" is current uploader's phase.
@param requestId identifier of http request
@param error True if error occured on given request; False otherwise
"""
if self.httpRequestAborted:
return
if not requestId in self.qhttp_map:
self.__examineResponse(requestId,error)
return
self.disconnect(self.http, SIGNAL("requestFinished(int, bool)"), self.__httpNodeDeletionReqFinished)
pointId=self.featureId_map[requestId]
del self.qhttp_map[requestId]
del self.featureId_map[requestId]
if error:
self.cancelUpload(self.tr("Node deletion failed."))
return
self.dbm.removePointRecord(pointId)
self.dbm.recacheAffectedNow([(pointId,'Point')])
# call the next upload step
self.cntActionsInPhaseDone+=1
self.cntActionsDone+=1
self.__uploadStep()
def __httpWayAdditionReqFinished(self, requestId, error):
"""Function is called when requestFinished(...) signal is emitted on global HTTP connection object
and "way addition" is current uploader's phase.
OSM server returns id that was assigned to uploaded way.
@param requestId identifier of http request
@param error True if error occured on given request; False otherwise
"""
if self.httpRequestAborted:
return
if not requestId in self.qhttp_map:
self.__examineResponse(requestId,error)
return
self.disconnect(self.http, SIGNAL("requestFinished(int, bool)"), self.__httpWayAdditionReqFinished)
wayPseudoId = self.pseudoId_map[requestId]
del self.qhttp_map[requestId]
del self.pseudoId_map[requestId]
if error:
self.cancelUpload(self.tr("Way addition failed."))
return
newWayIdStr = QString(self.http.readAll().data())
newWayId = (newWayIdStr.toInt())[0]
# update way identification in sqlite3 database
self.dbm.updateWayId(wayPseudoId,newWayId,self.userLineEdit.text())
self.dbm.recacheAffectedNow([(wayPseudoId,'Line'),(newWayId,'Line'),(wayPseudoId,'Polygon'),(newWayId,'Polygon')])
# call the next upload step
self.cntActionsInPhaseDone+=1
self.cntActionsDone+=1
self.__uploadStep()
def __httpWayUpdateReqFinished(self, requestId, error):
"""Function is called when requestFinished(...) signal is emitted on global HTTP connection object
and "way updating" is current uploader's phase.
OSM server returns id of new way's version.
@param requestId identifier of http request
@param error True if error occured on given request; False otherwise
"""
if self.httpRequestAborted:
return
if not requestId in self.qhttp_map:
self.__examineResponse(requestId,error)
return
self.disconnect(self.http, SIGNAL("requestFinished(int, bool)"), self.__httpWayUpdateReqFinished)
wayId=self.featureId_map[requestId]
del self.qhttp_map[requestId]
del self.featureId_map[requestId]
if error:
self.cancelUpload(self.tr("Way update failed."))
return
newVersionIdStr=QString(self.http.readAll().data())
newVersionId=(newVersionIdStr.toInt())[0]
self.dbm.updateVersionId(wayId,'way',newVersionId)
self.dbm.updateUser(wayId,'way',self.userLineEdit.text())
self.dbm.changeWayStatus(wayId,'U','N')
self.dbm.recacheAffectedNow([(wayId,'Line'),(wayId,'Polygon')])
# call the next upload step
self.cntActionsInPhaseDone+=1
self.cntActionsDone+=1
self.__uploadStep()
def __httpWayDeletionReqFinished(self, requestId, error):
"""Function is called when requestFinished(...) signal is emitted on global HTTP connection object
and "way deletion" is current uploader's phase.
@param requestId identifier of http request
@param error True if error occured on given request; False otherwise
"""
if self.httpRequestAborted:
return
if not requestId in self.qhttp_map:
self.__examineResponse(requestId,error)
return
self.disconnect(self.http, SIGNAL("requestFinished(int, bool)"), self.__httpWayDeletionReqFinished)
wayId=self.featureId_map[requestId]
del self.qhttp_map[requestId]
del self.featureId_map[requestId]
if error:
self.cancelUpload(self.tr("Way deletion failed."))
return
self.dbm.removeWayRecord(wayId)
self.dbm.recacheAffectedNow([(wayId,'Line'),(wayId,'Polygon')])
# call the next upload step
self.cntActionsInPhaseDone+=1
self.cntActionsDone+=1
self.__uploadStep()
def __httpRelationAdditionReqFinished(self, requestId, error):
"""Function is called when requestFinished(...) signal is emitted on global HTTP connection object
and "relation addition" is current uploader's phase.
OSM server returns id that was assigned to uploaded relation.
@param requestId identifier of http request
@param error True if error occured on given request; False otherwise
"""
if self.httpRequestAborted:
return
if not requestId in self.qhttp_map:
self.__examineResponse(requestId,error)
return
self.disconnect(self.http, SIGNAL("requestFinished(int, bool)"), self.__httpRelationAdditionReqFinished)
relPseudoId = self.pseudoId_map[requestId]
del self.qhttp_map[requestId]
del self.pseudoId_map[requestId]
if error:
self.cancelUpload(self.tr("Relation addition failed."))
return
newRelIdStr=QString(self.http.readAll().data())
newRelId=(newRelIdStr.toInt())[0]
# update way identification in sqlite3 database
self.dbm.updateRelationId(relPseudoId,newRelId,self.userLineEdit.text())
# call the next upload step
self.cntActionsInPhaseDone+=1
self.cntActionsDone+=1
self.__uploadStep()
def __httpRelationUpdateReqFinished(self, requestId, error):
"""Function is called when requestFinished(...) signal is emitted on global HTTP connection object
and "relation updating" is current uploader's phase.
OSM server returns id of new relation's version.
@param requestId identifier of http request
@param error True if error occured on given request; False otherwise
"""
if self.httpRequestAborted:
return
if not requestId in self.qhttp_map:
self.__examineResponse(requestId,error)
return
self.disconnect(self.http, SIGNAL("requestFinished(int, bool)"), self.__httpRelationUpdateReqFinished)
relId=self.featureId_map[requestId]
del self.qhttp_map[requestId]
del self.featureId_map[requestId]
if error:
self.cancelUpload(self.tr("Relation update failed."))
return
newVersionIdStr=QString(self.http.readAll().data())
newVersionId=(newVersionIdStr.toInt())[0]
self.dbm.updateVersionId(relId,'relation',newVersionId)
self.dbm.updateUser(relId,'relation',self.userLineEdit.text())
self.dbm.changeRelationStatus(relId,'U','N')
# call the next upload step
self.cntActionsInPhaseDone+=1
self.cntActionsDone+=1
self.__uploadStep()
def __httpRelationDeletionReqFinished(self, requestId, error):
"""Function is called when requestFinished(...) signal is emitted on global HTTP connection object
and "relation deletion" is current uploader's phase.
@param requestId identifier of http request
@param error True if error occured on given request; False otherwise
"""
if self.httpRequestAborted:
return
if not requestId in self.qhttp_map:
self.__examineResponse(requestId,error)
return
self.disconnect(self.http, SIGNAL("requestFinished(int, bool)"), self.__httpRelationDeletionReqFinished)
relId=self.featureId_map[requestId]
del self.qhttp_map[requestId]
del self.featureId_map[requestId]
if error:
self.cancelUpload(self.tr("Relation deletion failed."))
return
self.dbm.removeRelationRecord(relId)
# call the next upload step
self.cntActionsInPhaseDone+=1
self.cntActionsDone+=1
self.__uploadStep()
def __httpChangesetCreationReqFinished(self, requestId, error):
"""Function is called when requestFinished(...) signal is emitted on global HTTP connection object
and "changeset creation" is current uploader's phase.
OSM server returns id that was assigned to created changeset.
@param requestId identifier of http request
@param error True if error occured on given request; False otherwise
"""
if self.httpRequestAborted:
return
if not requestId in self.qhttp_map:
self.__examineResponse(requestId,error)
return
self.disconnect(self.http, SIGNAL("requestFinished(int, bool)"), self.__httpChangesetCreationReqFinished)
if error:
self.cancelUpload(self.tr("Connection to OpenStreetMap server cannot be established. Please check your proxy settings, firewall settings and try again."))
return
del self.qhttp_map[requestId]
changesetIdStr=QString(self.http.readAll().data())
self.changesetId=(changesetIdStr.toInt())[0]
# call the next upload step
self.cntActionsInPhaseDone+=1
self.cntActionsDone+=1
self.__uploadStep()
def __httpChangesetClosingReqFinished(self, requestId, error):
"""Function is called when requestFinished(...) signal is emitted on global HTTP connection object
and "changeset closing" is current uploader's phase.
@param requestId identifier of http request
@param error True if error occured on given request; False otherwise
"""
if self.httpRequestAborted:
return
if not requestId in self.qhttp_map:
self.__examineResponse(requestId,error)
return
self.disconnect(self.http, SIGNAL("requestFinished(int, bool)"), self.__httpChangesetClosingReqFinished)
if error:
self.cancelUpload(self.tr("Changeset closing failed."))
return
# call the next upload step
self.cntActionsInPhaseDone+=1
self.cntActionsDone+=1
self.__uploadStep()
def __readResponseHeader(self, responseHeader):
"""Function is called when responseHeaderReceived(...) signal is emitted
on global HTTP connection object.
If statusCode of responseHeader doesn't equal to 200, function cancels the whole connection.
@param responseHeader header of HTTP response from the OSM server
"""
if responseHeader.statusCode() != 200:
self.cancelUpload(self.tr("Upload process failed. OpenStreetMap server response: %1 - %2.")
.arg(responseHeader.reasonPhrase())
.arg(responseHeader.value("Error")))
def __authRequired(self,s,a,b):
"""Function is called when authenticationRequired(...) signal is emitted
on global HTTP connection object.
We are really not interested in function parameters - we just cancel the connection.
"""
self.cancelUpload(self.tr("Authentication failed. Please try again with correct login and password."))
def __setProxy(self):
"""Function sets proxy to HTTP connection of uploader.
HTTP connection object is not given in function parameter,
because it's global - accessible for the whole uploader.
"""
# getting and setting proxy information
settings=QSettings()
proxyHost=QString()
proxyUser=QString()
proxyPassword=QString()
proxyPort=0
proxyType=QNetworkProxy.NoProxy
proxyEnabled=settings.value("proxy/proxyEnabled",QVariant(0)).toBool()
if proxyEnabled:
proxyHost=settings.value("proxy/proxyHost",QVariant("")).toString()
proxyPort=settings.value("proxy/proxyPort",QVariant(8080)).toInt()[0]
proxyUser=settings.value("proxy/proxyUser",QVariant("")).toString()
proxyPassword=settings.value("proxy/proxyPassword",QVariant("")).toString()
proxyTypeString=settings.value("proxy/proxyType",QVariant("")).toString()
if proxyTypeString=="DefaultProxy":
proxyType=QNetworkProxy.DefaultProxy
elif proxyTypeString=="Socks5Proxy":
proxyType=QNetworkProxy.Socks5Proxy
elif proxyTypeString=="HttpProxy":
proxyType=QNetworkProxy.HttpProxy
elif proxyTypeString=="HttpCachingProxy":
proxyType=QNetworkProxy.HttpCachingProxy
elif proxyTypeString=="FtpCachingProxy":
proxyType=QNetworkProxy.FtpCachingProxy
self.proxy=QNetworkProxy()
self.proxy.setType(proxyType)
self.proxy.setHostName(proxyHost)
self.proxy.setPort(proxyPort)
self.reqSetProxy=self.http.__setProxy(self.proxy)
def __examineResponse(self,requestId,error):
"""If error occured function examines requestId and cancel upload for appropriate reason.
@param requestId identifier of http request
@param error True if error occured on given request; False otherwise
"""
if self.httpRequestAborted or not error:
return
if requestId==self.reqSetHost:
self.cancelUpload(self.tr("Setting host failed."))
elif requestId==self.reqSetUser:
self.cancelUpload(self.tr("Setting user and password failed."))
elif requestId==self.reqSetProxy:
self.cancelUpload(self.tr("Setting proxy failed."))