Source

qtwsgi / step3.py

#! /usr/bin/env python
# -*- coding: utf-8 -*-

import sys
import cgi

from wsgiref.util import setup_testing_defaults
from wsgiref import simple_server

from PySide import QtCore, QtNetwork, QtGui

ENCODING = 'utf-8'

class QWSGILineEdit(QtGui.QLineEdit):
    def __init__(self, name, text, parent=None):
        super(QWSGILineEdit, self).__init__(text, parent=parent)
        self.setObjectName(name)

    def html(self):
        """For rendering input."""

        return """
        <label for=\"%(name)s\">%(name)s
        <input type=\"text\" id=\"%(name)s\" name=\"%(name)s\" value=\"%(value)s\" />
        </label>
        """ % { 'name': self.objectName(),
                'value': self.text(), }

    def update(self, value):
        """Update value"""

        self.setText(value)

class QWSGIQComboBox(QtGui.QComboBox):
    def __init__(self, name, parent=None):
        super(QWSGIQComboBox, self).__init__(parent=parent)
        self.setObjectName(name)

    def html(self):
        options = []
        for i in range(self.count()):
            options.append("<option value=\"%(index)d\">%(text)s</option>" % {
                    'index': i,
                    'text': self.itemText(i), })

        return """
        <label for=\"%(name)s\">%(name)s
        <select id=\"%(name)s\" name=\"%(name)s\" />
        %(options)s
        </select>
        </label>
        """ % { 'name': self.objectName(), 
                'options': ''.join(options), }

    def update(self, value):
        """Update index"""

        try:
            value = int(value)
            self.setCurrentIndex(value)
        except ValueError:
            pass

class QWSGIFormWidget(QtGui.QWidget):
    def __init__(self, parent=None):
        super(QWSGIFormWidget, self).__init__(parent=parent)
        self.headers = [('Content-type', 'text/html'), ]
        self.setLayout(QtGui.QVBoxLayout(self))

        # Input widgets
        self.inputs = []

    def add_input(self, qwsgiwidget):
        self.layout().addWidget(qwsgiwidget)
        self.inputs.append(qwsgiwidget)

    def __call__(self, environ, start_response):
        if environ.get('REQUEST_METHOD').upper() == 'GET':
            return self.get(environ, start_response)
        elif environ.get('REQUEST_METHOD').upper() == 'POST':
            return self.post(environ, start_response)
        else:
            return self.http501(environ, start_response)

    def get(self, environ, start_response):
        start_response('200 OK', self.headers)

        ret = []
        ret.append("<form method=\"POST\" action=\".\">")
        for qwsgiwidget in self.inputs:
            ret.append("<p>")
            ret.append(qwsgiwidget.html())
            ret.append("</p>")
        ret.append("<p><input type=\"submit\" value=\"submit\" /></p>")
        ret.append("</form>")
        return [type(r) is unicode and r.encode(ENCODING) or r for r in ret]

    def post(self, environ, start_response):
        body= '' # For py3k
        try:
            length = int(environ.get('CONTENT_LENGTH', '0'))
        except ValueError:
            length = 0

        wsgi_input = environ['wsgi.input']

        post_vars = dict(cgi.parse_qsl(wsgi_input.read(length)))

        # Update all values
        for k, v in post_vars.items():
            qwsgiwidgets = self.findChildren(QtGui.QWidget, k)
            if qwsgiwidgets:
                qwsgiwidgets[0].update(v)

        return self.get(environ, start_response)

    def http501(self, environ, start_response):
        start_response('501 NotImplemented', self.headers)
        return "Not Implemented."

class QHttpServerThread(QtCore.QThread):
    u"""Http threads"""

    def __init__(self, wsgi_server, parent=None):
        super(QHttpServerThread, self).__init__(parent=parent)
        self.wsgi_server = wsgi_server
        self.__is_run = False

    def run(self):
        self.__is_run = True
        while (self.__is_run):
            self.wsgi_server.handle_request()

    def stop(self):
        self.__is_run = False
        self.quit()

class QHttpWidget(QtGui.QWidget):
    def __init__(self, host='localhost', port=8000, parent=None):
        super(QHttpWidget, self).__init__(parent=parent)
        self.setLayout(QtGui.QVBoxLayout(self))

        # Create WSGI application
        qwsgiform = QWSGIFormWidget(parent=self)
        qwsgiform.add_input(QWSGILineEdit('spam', 'Spam', parent=qwsgiform))
        qwsgiform.add_input(QWSGILineEdit('egg', 'Egg', parent=qwsgiform))
        qwsgicombobox = QWSGIQComboBox('selector', parent=qwsgiform)
        qwsgicombobox.addItems(['foo', 'bar', 'baz', ])
        qwsgiform.add_input(qwsgicombobox)

        self.wsgi_server = QHttpServerThread(
                simple_server.make_server(host, port, qwsgiform), parent=self)
        self.layout().addWidget(qwsgiform)

        # Add buttons
        btn_layout = QtGui.QHBoxLayout()

        ## Run button
        self.run_btn = QtGui.QPushButton("run", self)
        self.run_btn.setEnabled(True)
        btn_layout.addWidget(self.run_btn)
        self.run_btn.clicked.connect(self.run_server)

        ## Stop button
        self.stop_btn = QtGui.QPushButton("stop", self)
        self.stop_btn.setEnabled(False)
        btn_layout.addWidget(self.stop_btn)
        self.stop_btn.clicked.connect(self.stop_server)

        self.layout().addLayout(btn_layout)

    @QtCore.Slot()
    def run_server(self):
        """Start WSGI Server"""

        self.wsgi_server.start()

        self.run_btn.setEnabled(False)
        self.stop_btn.setEnabled(True)

    @QtCore.Slot()
    def stop_server(self):
        """Stop WSGI Server"""

        self.wsgi_server.stop()

        self.run_btn.setEnabled(True)
        self.stop_btn.setEnabled(False)

if __name__ == '__main__':
    app = QtGui.QApplication(sys.argv)
    window = QHttpWidget()
    window.show()
    sys.exit(app.exec_())