forked from shaba/openuds
Advancing on uds client connector
This commit is contained in:
parent
c70d94e866
commit
62f50304fe
@ -164,7 +164,7 @@ class UDSSystemTray(QtGui.QSystemTrayIcon):
|
||||
self.app = app_
|
||||
|
||||
style = app.style()
|
||||
icon = QtGui.QIcon(style.standardPixmap(QtGui.QStyle.SP_DesktopIcon))
|
||||
icon = QtGui.QIcon(style.standardPixmap(QtGui.QStyle.SP_ComputerIcon))
|
||||
|
||||
QtGui.QSystemTrayIcon.__init__(self, icon, parent)
|
||||
self.menu = QtGui.QMenu(parent)
|
||||
|
@ -38,6 +38,65 @@ import six
|
||||
|
||||
from uds.rest import RestRequest
|
||||
from uds.forward import forward
|
||||
import webbrowser
|
||||
|
||||
from UDSWindow import Ui_MainWindow
|
||||
|
||||
# Client connector version
|
||||
VERSION = '1.9.5'
|
||||
|
||||
|
||||
class UDSClient(QtGui.QMainWindow):
|
||||
def __init__(self):
|
||||
QtGui.QMainWindow.__init__(self)
|
||||
self.setWindowFlags(QtCore.Qt.FramelessWindowHint | QtCore.Qt.WindowStaysOnTopHint)
|
||||
|
||||
self.ui = Ui_MainWindow()
|
||||
self.ui.setupUi(self)
|
||||
|
||||
self.ui.progressBar.setValue(0)
|
||||
self.ui.cancelButton.clicked.connect(self.cancelPushed)
|
||||
|
||||
self.activateWindow()
|
||||
|
||||
def closeWindow(self):
|
||||
self.close()
|
||||
|
||||
def processError(self, rest):
|
||||
if 'error' in rest.data:
|
||||
raise Exception(rest.data['error'])
|
||||
# QtGui.QMessageBox.critical(self, 'Request error', rest.data['error'], QtGui.QMessageBox.Ok)
|
||||
# self.closeWindow()
|
||||
# return
|
||||
|
||||
def cancelPushed(self):
|
||||
self.close()
|
||||
|
||||
def version(self, rest):
|
||||
try:
|
||||
self.ui.progressBar.setValue(10)
|
||||
|
||||
self.processError(rest)
|
||||
|
||||
if rest.data['result']['requiredVersion'] > VERSION:
|
||||
QtGui.QMessageBox.critical(self, 'Upgrade required', 'A newer connector version is required.\nA browser will be opened to download it.', QtGui.QMessageBox.Ok)
|
||||
webbrowser.open(rest.data['result']['downloadUrl'])
|
||||
self.closeWindow()
|
||||
return
|
||||
|
||||
QtGui.QMessageBox.critical(self, 'Notice', six.text_type(rest.data), QtGui.QMessageBox.Ok)
|
||||
|
||||
except Exception as e:
|
||||
QtGui.QMessageBox.critical(self, 'Error', six.text_type(e), QtGui.QMessageBox.Ok)
|
||||
self.closeWindow()
|
||||
|
||||
def showEvent(self, *args, **kwargs):
|
||||
'''
|
||||
Starts proccess by requesting version info
|
||||
'''
|
||||
self.ui.info.setText('Requesting required connector version...')
|
||||
self.req = RestRequest('', self, self.version)
|
||||
self.req.get()
|
||||
|
||||
|
||||
def done(data):
|
||||
@ -46,6 +105,7 @@ def done(data):
|
||||
|
||||
if __name__ == "__main__":
|
||||
app = QtGui.QApplication(sys.argv)
|
||||
app.setStyle(QtGui.QStyleFactory.create('plastique'))
|
||||
|
||||
if six.PY3 is False:
|
||||
import threading
|
||||
@ -64,14 +124,26 @@ if __name__ == "__main__":
|
||||
QtGui.QMessageBox.critical(None, 'Notice', 'This program is designed to be used by UDS', QtGui.QMessageBox.Ok)
|
||||
sys.exit(1)
|
||||
|
||||
# Build base REST
|
||||
RestRequest.restApiUrl = '{}://{}/rest/client'.format(['http', 'https'][ssl], host)
|
||||
# Setup REST api endpoint
|
||||
# RestRequest.restApiUrl = '{}://{}/rest/client'.format(['http', 'https'][ssl], host)
|
||||
RestRequest.restApiUrl = 'https://172.27.0.1/rest/client'
|
||||
|
||||
v = RestRequest('', done)
|
||||
v.get()
|
||||
try:
|
||||
win = UDSClient()
|
||||
win.show()
|
||||
|
||||
sys.exit(app.exec_())
|
||||
except Exception as e:
|
||||
QtGui.QMessageBox.critical(None, 'Error', six.text_type(e), QtGui.QMessageBox.Ok)
|
||||
|
||||
sys.stdin.read()
|
||||
QtGui.QMessageBox.critical(None, 'Error', 'test', QtGui.QMessageBox.Ok)
|
||||
# Build base REST
|
||||
|
||||
# v = RestRequest('', done)
|
||||
# v.get()
|
||||
|
||||
# sys.exit(1)
|
||||
|
||||
# myapp = UDSConfigDialog(cfg)
|
||||
# myapp.show()
|
||||
sys.exit(app.exec_())
|
||||
|
2471
client/src/UDSResources_rc.py
Normal file
2471
client/src/UDSResources_rc.py
Normal file
File diff suppressed because it is too large
Load Diff
@ -2,7 +2,7 @@
|
||||
|
||||
# Form implementation generated from reading ui file 'UDSWindow.ui'
|
||||
#
|
||||
# Created: Fri Mar 27 15:03:01 2015
|
||||
# Created: Mon Mar 30 08:55:29 2015
|
||||
# by: PyQt4 UI code generator 4.11.2
|
||||
#
|
||||
# WARNING! All changes made in this file will be lost!
|
||||
@ -26,17 +26,73 @@ except AttributeError:
|
||||
class Ui_MainWindow(object):
|
||||
def setupUi(self, MainWindow):
|
||||
MainWindow.setObjectName(_fromUtf8("MainWindow"))
|
||||
MainWindow.resize(282, 185)
|
||||
MainWindow.setWindowModality(QtCore.Qt.NonModal)
|
||||
MainWindow.resize(259, 185)
|
||||
MainWindow.setCursor(QtGui.QCursor(QtCore.Qt.BusyCursor))
|
||||
icon = QtGui.QIcon()
|
||||
icon.addPixmap(QtGui.QPixmap(_fromUtf8(":/images/logo-uds-small")), QtGui.QIcon.Normal, QtGui.QIcon.Off)
|
||||
MainWindow.setWindowIcon(icon)
|
||||
MainWindow.setWindowOpacity(1.0)
|
||||
self.centralwidget = QtGui.QWidget(MainWindow)
|
||||
self.centralwidget.setAutoFillBackground(True)
|
||||
self.centralwidget.setObjectName(_fromUtf8("centralwidget"))
|
||||
self.verticalLayout_2 = QtGui.QVBoxLayout(self.centralwidget)
|
||||
self.verticalLayout_2.setSpacing(4)
|
||||
self.verticalLayout_2.setMargin(4)
|
||||
self.verticalLayout_2.setObjectName(_fromUtf8("verticalLayout_2"))
|
||||
self.frame = QtGui.QFrame(self.centralwidget)
|
||||
self.frame.setFrameShape(QtGui.QFrame.StyledPanel)
|
||||
self.frame.setFrameShadow(QtGui.QFrame.Raised)
|
||||
self.frame.setObjectName(_fromUtf8("frame"))
|
||||
self.verticalLayout_3 = QtGui.QVBoxLayout(self.frame)
|
||||
self.verticalLayout_3.setSpacing(4)
|
||||
self.verticalLayout_3.setMargin(4)
|
||||
self.verticalLayout_3.setObjectName(_fromUtf8("verticalLayout_3"))
|
||||
self.verticalLayout = QtGui.QVBoxLayout()
|
||||
self.verticalLayout.setObjectName(_fromUtf8("verticalLayout"))
|
||||
self.image = QtGui.QLabel(self.frame)
|
||||
self.image.setMinimumSize(QtCore.QSize(0, 24))
|
||||
self.image.setAutoFillBackground(True)
|
||||
self.image.setText(_fromUtf8(""))
|
||||
self.image.setPixmap(QtGui.QPixmap(_fromUtf8(":/images/logo-uds-small")))
|
||||
self.image.setScaledContents(False)
|
||||
self.image.setAlignment(QtCore.Qt.AlignCenter)
|
||||
self.image.setObjectName(_fromUtf8("image"))
|
||||
self.verticalLayout.addWidget(self.image)
|
||||
self.info = QtGui.QLabel(self.frame)
|
||||
self.info.setMaximumSize(QtCore.QSize(16777215, 16))
|
||||
self.info.setObjectName(_fromUtf8("info"))
|
||||
self.verticalLayout.addWidget(self.info)
|
||||
self.progressBar = QtGui.QProgressBar(self.frame)
|
||||
self.progressBar.setProperty("value", 24)
|
||||
self.progressBar.setTextVisible(False)
|
||||
self.progressBar.setObjectName(_fromUtf8("progressBar"))
|
||||
self.verticalLayout.addWidget(self.progressBar)
|
||||
self.horizontalLayout = QtGui.QHBoxLayout()
|
||||
self.horizontalLayout.setObjectName(_fromUtf8("horizontalLayout"))
|
||||
spacerItem = QtGui.QSpacerItem(40, 20, QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Minimum)
|
||||
self.horizontalLayout.addItem(spacerItem)
|
||||
self.cancelButton = QtGui.QPushButton(self.frame)
|
||||
self.cancelButton.setDefault(True)
|
||||
self.cancelButton.setFlat(False)
|
||||
self.cancelButton.setObjectName(_fromUtf8("cancelButton"))
|
||||
self.horizontalLayout.addWidget(self.cancelButton)
|
||||
spacerItem1 = QtGui.QSpacerItem(40, 20, QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Minimum)
|
||||
self.horizontalLayout.addItem(spacerItem1)
|
||||
self.verticalLayout.addLayout(self.horizontalLayout)
|
||||
self.verticalLayout_3.addLayout(self.verticalLayout)
|
||||
self.verticalLayout_2.addWidget(self.frame)
|
||||
MainWindow.setCentralWidget(self.centralwidget)
|
||||
|
||||
self.retranslateUi(MainWindow)
|
||||
QtCore.QMetaObject.connectSlotsByName(MainWindow)
|
||||
|
||||
def retranslateUi(self, MainWindow):
|
||||
MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow", None))
|
||||
MainWindow.setWindowTitle(_translate("MainWindow", "UDS Connection", None))
|
||||
self.info.setText(_translate("MainWindow", "TextLabel", None))
|
||||
self.cancelButton.setText(_translate("MainWindow", "Cancel", None))
|
||||
|
||||
import UDSResources_rc
|
||||
|
||||
if __name__ == "__main__":
|
||||
import sys
|
||||
|
@ -2,21 +2,66 @@
|
||||
<ui version="4.0">
|
||||
<class>MainWindow</class>
|
||||
<widget class="QMainWindow" name="MainWindow">
|
||||
<property name="windowModality">
|
||||
<enum>Qt::NonModal</enum>
|
||||
</property>
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>282</width>
|
||||
<width>259</width>
|
||||
<height>185</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="cursor">
|
||||
<cursorShape>BusyCursor</cursorShape>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>MainWindow</string>
|
||||
<string>UDS Connection</string>
|
||||
</property>
|
||||
<property name="windowIcon">
|
||||
<iconset resource="UDSResources.qrc">
|
||||
<normaloff>:/images/logo-uds-small</normaloff>:/images/logo-uds-small</iconset>
|
||||
</property>
|
||||
<property name="windowOpacity">
|
||||
<double>1.000000000000000</double>
|
||||
</property>
|
||||
<widget class="QWidget" name="centralwidget">
|
||||
<property name="autoFillBackground">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_2">
|
||||
<property name="spacing">
|
||||
<number>4</number>
|
||||
</property>
|
||||
<property name="margin">
|
||||
<number>4</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QLabel" name="label">
|
||||
<widget class="QFrame" name="frame">
|
||||
<property name="frameShape">
|
||||
<enum>QFrame::StyledPanel</enum>
|
||||
</property>
|
||||
<property name="frameShadow">
|
||||
<enum>QFrame::Raised</enum>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_3">
|
||||
<property name="spacing">
|
||||
<number>4</number>
|
||||
</property>
|
||||
<property name="margin">
|
||||
<number>4</number>
|
||||
</property>
|
||||
<item>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<item>
|
||||
<widget class="QLabel" name="image">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>0</width>
|
||||
<height>24</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="autoFillBackground">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
@ -34,6 +79,19 @@
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="info">
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>16777215</width>
|
||||
<height>16</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>TextLabel</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QProgressBar" name="progressBar">
|
||||
<property name="value">
|
||||
@ -44,6 +102,54 @@
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<item>
|
||||
<spacer name="horizontalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="cancelButton">
|
||||
<property name="text">
|
||||
<string>Cancel</string>
|
||||
</property>
|
||||
<property name="default">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="flat">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="horizontalSpacer_2">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</widget>
|
||||
|
@ -1,7 +1,7 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
#
|
||||
# Copyright (c) 2012 Virtual Cable S.L.
|
||||
# Copyright (c) 2015 Virtual Cable S.L.
|
||||
# All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without modification,
|
||||
@ -34,8 +34,11 @@ from __future__ import unicode_literals
|
||||
|
||||
from PyQt4.QtCore import pyqtSignal
|
||||
from PyQt4.QtCore import QObject, QUrl
|
||||
from PyQt4.Qt import QString
|
||||
from PyQt4.QtNetwork import QNetworkAccessManager, QNetworkRequest
|
||||
from PyQt4.QtNetwork import QNetworkAccessManager, QNetworkRequest, QNetworkReply, QSslCertificate
|
||||
from PyQt4.QtGui import QMessageBox
|
||||
|
||||
import json
|
||||
import six
|
||||
|
||||
|
||||
class RestRequest(QObject):
|
||||
@ -43,7 +46,7 @@ class RestRequest(QObject):
|
||||
restApiUrl = '' #
|
||||
done = pyqtSignal(QObject)
|
||||
|
||||
def __init__(self, url, done): # parent not used
|
||||
def __init__(self, url, parentWindow, done): # parent not used
|
||||
super(RestRequest, self).__init__()
|
||||
# private
|
||||
self._manager = QNetworkAccessManager()
|
||||
@ -52,6 +55,8 @@ class RestRequest(QObject):
|
||||
|
||||
# connect asynchronous result, when a request finishes
|
||||
self._manager.finished.connect(self._finished)
|
||||
self._manager.sslErrors.connect(self._sslError)
|
||||
self._parentWindow = parentWindow
|
||||
|
||||
self.done.connect(done)
|
||||
|
||||
@ -60,14 +65,32 @@ class RestRequest(QObject):
|
||||
'''
|
||||
Handle signal 'finished'. A network request has finished.
|
||||
'''
|
||||
self.data = reply.readAll()
|
||||
reply.deleteLater() # schedule for delete from main event loop
|
||||
try:
|
||||
if reply.error() != QNetworkReply.NoError:
|
||||
raise Exception(reply.errorString())
|
||||
|
||||
data = six.text_type(reply.readAll())
|
||||
self.data = json.loads(data)
|
||||
except Exception as e:
|
||||
self.data = {
|
||||
'result': None,
|
||||
'error': six.text_type(e)
|
||||
}
|
||||
|
||||
reply.deleteLater() # schedule for delete from main event loop
|
||||
self.done.emit(self)
|
||||
|
||||
'''
|
||||
Public API
|
||||
'''
|
||||
def _sslError(self, reply, errors):
|
||||
|
||||
print "SSL Error"
|
||||
print reply
|
||||
cert = errors[0].certificate()
|
||||
errorString = 'The certificate for "{}" has the following errors:\n'.format(cert.subjectInfo(QSslCertificate.CommonName))
|
||||
for err in errors:
|
||||
errorString += err.errorString() + '\n'
|
||||
|
||||
if QMessageBox.warning(self._parentWindow, 'SSL Error', errorString, QMessageBox.Yes | QMessageBox.No) == QMessageBox.Yes:
|
||||
reply.ignoreSslErrors()
|
||||
|
||||
def get(self):
|
||||
print self.url
|
||||
|
33
client/src/uds/tools.py
Normal file
33
client/src/uds/tools.py
Normal file
@ -0,0 +1,33 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
#
|
||||
# Copyright (c) 2015 Virtual Cable S.L.
|
||||
# All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without modification,
|
||||
# are permitted provided that the following conditions are met:
|
||||
#
|
||||
# * Redistributions of source code must retain the above copyright notice,
|
||||
# this list of conditions and the following disclaimer.
|
||||
# * Redistributions in binary form must reproduce the above copyright notice,
|
||||
# this list of conditions and the following disclaimer in the documentation
|
||||
# and/or other materials provided with the distribution.
|
||||
# * Neither the name of Virtual Cable S.L. nor the names of its contributors
|
||||
# may be used to endorse or promote products derived from this software
|
||||
# without specific prior written permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
'''
|
||||
@author: Adolfo Gómez, dkmaster at dkmon dot com
|
||||
'''
|
||||
from __future__ import unicode_literals
|
@ -54,8 +54,8 @@ import logging
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
CLIENT_VERSION = '1.7.0'
|
||||
REQUIRED_CLIENT_VERSION = '1.7.0'
|
||||
CLIENT_VERSION = '1.7.5'
|
||||
REQUIRED_CLIENT_VERSION = '1.7.5'
|
||||
|
||||
|
||||
# Enclosed methods under /actor path
|
||||
@ -74,8 +74,10 @@ class Client(Handler):
|
||||
:return: A dictionary, suitable for response to Caller
|
||||
'''
|
||||
result = result if result is not None else ''
|
||||
res = {'result': result, 'date': datetime.datetime.now()}
|
||||
res = {'result': result}
|
||||
if error is not None:
|
||||
if isinstance(error, int):
|
||||
error = errors.errorString(error)
|
||||
res['error'] = error
|
||||
return res
|
||||
|
||||
@ -90,13 +92,14 @@ class Client(Handler):
|
||||
Processes get requests
|
||||
'''
|
||||
logger.debug("Client args for GET: {0}".format(self._args))
|
||||
# return Client.result(error=errors.ACCESS_DENIED)
|
||||
|
||||
if len(self._args) == 0:
|
||||
url = self._request.build_absolute_uri(reverse('ClientDownload'))
|
||||
return Client.result({
|
||||
'available_version': CLIENT_VERSION,
|
||||
'required_version': REQUIRED_CLIENT_VERSION,
|
||||
'download_url': url
|
||||
'availableVersion': CLIENT_VERSION,
|
||||
'requiredVersion': REQUIRED_CLIENT_VERSION,
|
||||
'downloadUrl': url
|
||||
})
|
||||
|
||||
if len(self._args) != 2:
|
||||
|
Loading…
x
Reference in New Issue
Block a user