diff options
author | Ahmed Youssef <xmonader@gmail.com> | 2009-08-19 20:26:00 +0300 |
---|---|---|
committer | Ahmed Youssef <xmonader@gmail.com> | 2009-08-19 20:26:00 +0300 |
commit | 704bf0e5e6ed9b2b8a3dcbf8c5ad2648d33f4d3f (patch) | |
tree | 84e43bc770019161a349922b88ab2d9a2fcb75a7 /examples/network |
Init
Diffstat (limited to 'examples/network')
-rw-r--r-- | examples/network/README | 26 | ||||
-rwxr-xr-x | examples/network/blockingfortuneclient.py | 198 | ||||
-rwxr-xr-x | examples/network/broadcastreceiver.py | 67 | ||||
-rwxr-xr-x | examples/network/broadcastsender.py | 75 | ||||
-rwxr-xr-x | examples/network/fortuneclient.py | 124 | ||||
-rwxr-xr-x | examples/network/fortuneserver.py | 78 | ||||
-rwxr-xr-x | examples/network/ftp/ftp.py | 251 | ||||
-rw-r--r-- | examples/network/ftp/ftp.qrc | 7 | ||||
-rw-r--r-- | examples/network/ftp/images/cdtoparent.png | bin | 0 -> 139 bytes | |||
-rw-r--r-- | examples/network/ftp/images/dir.png | bin | 0 -> 155 bytes | |||
-rw-r--r-- | examples/network/ftp/images/file.png | bin | 0 -> 129 bytes | |||
-rw-r--r-- | examples/network/http/authenticationdialog.ui | 129 | ||||
-rwxr-xr-x | examples/network/http/http.py | 196 | ||||
-rwxr-xr-x | examples/network/loopback.py | 154 | ||||
-rwxr-xr-x | examples/network/threadedfortuneserver.py | 121 |
15 files changed, 1426 insertions, 0 deletions
diff --git a/examples/network/README b/examples/network/README new file mode 100644 index 0000000..7cfd561 --- /dev/null +++ b/examples/network/README @@ -0,0 +1,26 @@ +PyQt is provided with an extensive set of network classes to support both +client-based and server side network programming. + +These examples demonstrate the fundamental aspects of network programming +with PyQt. + + +The example launcher provided with PyQt can be used to explore each of the +examples in this directory. + +Documentation for these examples can be found via the Tutorial and Examples +link in the main Qt documentation. + + +Finding the PyQt Examples and Demos launcher +============================================ + +On Windows: + +The launcher can be accessed via the Windows Start menu. Select the menu +entry entitled "Examples and Demos" entry in the submenu containing PyQt4. + +On all platforms: + +The source code for the launcher can be found in the examples/demos/qtdemo +directory in the PyQt package. diff --git a/examples/network/blockingfortuneclient.py b/examples/network/blockingfortuneclient.py new file mode 100755 index 0000000..068980d --- /dev/null +++ b/examples/network/blockingfortuneclient.py @@ -0,0 +1,198 @@ +#!/usr/bin/env python + +############################################################################ +# +# Copyright (C) 2004-2005 Trolltech AS. All rights reserved. +# +# This file is part of the example classes of the Qt Toolkit. +# +# This file may be used under the terms of the GNU General Public +# License version 2.0 as published by the Free Software Foundation +# and appearing in the file LICENSE.GPL included in the packaging of +# self file. Please review the following information to ensure GNU +# General Public Licensing requirements will be met: +# http://www.trolltech.com/products/qt/opensource.html +# +# If you are unsure which license is appropriate for your use, please +# review the following information: +# http://www.trolltech.com/products/qt/licensing.html or contact the +# sales department at sales@trolltech.com. +# +# This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +# WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +# +############################################################################ + +from PyQt4 import QtCore, QtGui, QtNetwork + + +class FortuneThread(QtCore.QThread): + newFortune = QtCore.pyqtSignal(str) + + error = QtCore.pyqtSignal(int, str) + + def __init__(self, parent=None): + super(FortuneThread, self).__init__(parent) + + self.quit = False + self.hostName = QtCore.QString() + self.cond = QtCore.QWaitCondition() + self.mutex = QtCore.QMutex() + self.port = 0 + + def __del__(self): + self.mutex.lock() + self.quit = True + self.cond.wakeOne() + self.mutex.unlock() + self.wait() + + def requestNewFortune(self, hostname, port): + locker = QtCore.QMutexLocker(self.mutex) + self.hostName = hostname + self.port = port + if not self.isRunning(): + self.start() + else: + self.cond.wakeOne() + + def run(self): + self.mutex.lock() + serverName = self.hostName + serverPort = self.port + self.mutex.unlock() + + while not self.quit: + Timeout = 5 * 1000 + + socket = QtNetwork.QTcpSocket() + socket.connectToHost(serverName, serverPort) + + if not socket.waitForConnected(Timeout): + self.error.emit(socket.error(), socket.errorString()) + return + + while socket.bytesAvailable() < 2: + if not socket.waitForReadyRead(Timeout): + self.error.emit(socket.error(), socket.errorString()) + return + + instr = QtCore.QDataStream(socket) + instr.setVersion(QtCore.QDataStream.Qt_4_0) + blockSize = instr.readUInt16() + + while socket.bytesAvailable() < blockSize: + if not socket.waitForReadyRead(Timeout): + self.error.emit(socket.error(), socket.errorString()) + return + + self.mutex.lock() + fortune = QtCore.QString() + instr >> fortune + self.newFortune.emit(fortune) + + self.cond.wait(self.mutex) + serverName = self.hostName + serverPort = self.port + self.mutex.unlock() + + +class BlockingClient(QtGui.QDialog): + def __init__(self, parent=None): + super(BlockingClient, self).__init__(parent) + + self.thread = FortuneThread() + self.currentFortune = QtCore.QString() + + hostLabel = QtGui.QLabel(self.tr("&Server name:")) + portLabel = QtGui.QLabel(self.tr("S&erver port:")) + + self.hostLineEdit = QtGui.QLineEdit("Localhost") + self.portLineEdit = QtGui.QLineEdit() + self.portLineEdit.setValidator(QtGui.QIntValidator(1, 65535, self)) + + hostLabel.setBuddy(self.hostLineEdit) + portLabel.setBuddy(self.portLineEdit) + + self.statusLabel = QtGui.QLabel(self.tr("This example requires that " + "you run the Fortune Server " + "example as well.")) + + self.getFortuneButton = QtGui.QPushButton(self.tr("Get Fortune")) + self.getFortuneButton.setDefault(True) + self.getFortuneButton.setEnabled(False) + + quitButton = QtGui.QPushButton(self.tr("Quit")) + + buttonBox = QtGui.QDialogButtonBox() + buttonBox.addButton(self.getFortuneButton, + QtGui.QDialogButtonBox.ActionRole) + buttonBox.addButton(quitButton, QtGui.QDialogButtonBox.RejectRole) + + self.hostLineEdit.textChanged.connect(self.enableGetFortuneButton) + self.portLineEdit.textChanged.connect(self.enableGetFortuneButton) + self.getFortuneButton.clicked.connect(self.requestNewFortune) + quitButton.clicked.connect(self.close) + self.thread.newFortune.connect(self.showFortune) + self.thread.error.connect(self.displayError) + + mainLayout = QtGui.QGridLayout() + mainLayout.addWidget(hostLabel, 0, 0) + mainLayout.addWidget(self.hostLineEdit, 0, 1) + mainLayout.addWidget(portLabel, 1, 0) + mainLayout.addWidget(self.portLineEdit, 1, 1) + mainLayout.addWidget(self.statusLabel, 2, 0, 1, 2) + mainLayout.addWidget(buttonBox, 3, 0, 1, 2) + self.setLayout(mainLayout) + + self.setWindowTitle(self.tr("Blocking Fortune Client")) + self.portLineEdit.setFocus() + + def requestNewFortune(self): + self.getFortuneButton.setEnabled(False) + self.thread.requestNewFortune(self.hostLineEdit.text(), + self.portLineEdit.text().toInt()[0]) + + def showFortune(self, nextFortune): + if nextFortune == self.currentFortune: + self.requestNewFortune() + return + + self.currentFortune = QtCore.QString(nextFortune) + self.statusLabel.setText(self.currentFortune) + self.getFortuneButton.setEnabled(True) + + def displayError(self, socketError, message): + if socketError == QtNetwork.QAbstractSocket.HostNotFoundError: + QtGui.QMessageBox.information(self, + self.tr("Blocking Fortune Client"), + self.tr("The host was not found. Please check the host " + "and port settings.")) + elif socketError == QtNetwork.QAbstractSocket.ConnectionRefusedError: + QtGui.QMessageBox.information(self, + self.tr("Blocking Fortune Client"), + self.tr("The connection was refused by the peer. Make " + "sure the fortune server is running, and check " + "that the host name and port settings are " + "correct.")) + else: + QtGui.QMessageBox.information(self, + self.tr("Blocking Fortune Client"), + self.tr("The following error occurred: %1.").arg(message)) + + self.getFortuneButton.setEnabled(True) + + def enableGetFortuneButton(self): + self.getFortuneButton.setEnabled( + not self.hostLineEdit.text().isEmpty() and + not self.portLineEdit.text().isEmpty()) + + +if __name__ == '__main__': + + import sys + + app = QtGui.QApplication(sys.argv) + client = BlockingClient() + client.show() + sys.exit(client.exec_()) diff --git a/examples/network/broadcastreceiver.py b/examples/network/broadcastreceiver.py new file mode 100755 index 0000000..169ec6c --- /dev/null +++ b/examples/network/broadcastreceiver.py @@ -0,0 +1,67 @@ +#!/usr/bin/env python + +############################################################################ +# +# Copyright (C) 2004-2005 Trolltech AS. All rights reserved. +# +# This file is part of the example classes of the Qt Toolkit. +# +# This file may be used under the terms of the GNU General Public +# License version 2.0 as published by the Free Software Foundation +# and appearing in the file LICENSE.GPL included in the packaging of +# self file. Please review the following information to ensure GNU +# General Public Licensing requirements will be met: +# http://www.trolltech.com/products/qt/opensource.html +# +# If you are unsure which license is appropriate for your use, please +# review the following information: +# http://www.trolltech.com/products/qt/licensing.html or contact the +# sales department at sales@trolltech.com. +# +# This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +# WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +# +############################################################################ + +from PyQt4 import QtGui, QtNetwork + + +class Receiver(QtGui.QDialog): + def __init__(self, parent=None): + super(Receiver, self).__init__(parent) + + self.statusLabel = QtGui.QLabel(self.tr("Listening for broadcasted messages")) + quitButton = QtGui.QPushButton(self.tr("&Quit")) + + self.udpSocket = QtNetwork.QUdpSocket(self) + self.udpSocket.bind(45454) + + self.udpSocket.readyRead.connect(self.processPendingDatagrams) + quitButton.clicked.connect(self.close) + + buttonLayout = QtGui.QHBoxLayout() + buttonLayout.addStretch(1) + buttonLayout.addWidget(quitButton) + buttonLayout.addStretch(1) + + mainLayout = QtGui.QVBoxLayout() + mainLayout.addWidget(self.statusLabel) + mainLayout.addLayout(buttonLayout) + self.setLayout(mainLayout) + + self.setWindowTitle(self.tr("Broadcast Receiver")) + + def processPendingDatagrams(self): + while self.udpSocket.hasPendingDatagrams(): + datagram, host, port = self.udpSocket.readDatagram(self.udpSocket.pendingDatagramSize()) + self.statusLabel.setText(self.tr("Received datagram: \"%1\"").arg(datagram)) + + +if __name__ == '__main__': + + import sys + + app = QtGui.QApplication(sys.argv) + receiver = Receiver() + receiver.show() + sys.exit(receiver.exec_()) diff --git a/examples/network/broadcastsender.py b/examples/network/broadcastsender.py new file mode 100755 index 0000000..48fb5d3 --- /dev/null +++ b/examples/network/broadcastsender.py @@ -0,0 +1,75 @@ +#!/usr/bin/env python + +############################################################################ +# +# Copyright (C) 2004-2005 Trolltech AS. All rights reserved. +# +# This file is part of the example classes of the Qt Toolkit. +# +# This file may be used under the terms of the GNU General Public +# License version 2.0 as published by the Free Software Foundation +# and appearing in the file LICENSE.GPL included in the packaging of +# self file. Please review the following information to ensure GNU +# General Public Licensing requirements will be met: +# http://www.trolltech.com/products/qt/opensource.html +# +# If you are unsure which license is appropriate for your use, please +# review the following information: +# http://www.trolltech.com/products/qt/licensing.html or contact the +# sales department at sales@trolltech.com. +# +# This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +# WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +# +############################################################################ + +from PyQt4 import QtCore, QtGui, QtNetwork + + +class Sender(QtGui.QDialog): + def __init__(self, parent=None): + super(Sender, self).__init__(parent) + + self.statusLabel = QtGui.QLabel(self.tr("Ready to broadcast datagrams on port 45454")) + + self.startButton = QtGui.QPushButton(self.tr("&Start")) + quitButton = QtGui.QPushButton(self.tr("&Quit")) + + buttonBox = QtGui.QDialogButtonBox() + buttonBox.addButton(self.startButton, QtGui.QDialogButtonBox.ActionRole) + buttonBox.addButton(quitButton, QtGui.QDialogButtonBox.RejectRole) + + self.timer = QtCore.QTimer(self) + self.udpSocket = QtNetwork.QUdpSocket(self) + self.messageNo = 1 + + self.startButton.clicked.connect(self.startBroadcasting) + quitButton.clicked.connect(self.close) + self.timer.timeout.connect(self.broadcastDatagramm) + + mainLayout = QtGui.QVBoxLayout() + mainLayout.addWidget(self.statusLabel) + mainLayout.addWidget(buttonBox) + self.setLayout(mainLayout) + + self.setWindowTitle(self.tr("Broadcast Sender")) + + def startBroadcasting(self): + self.startButton.setEnabled(False) + self.timer.start(1000) + + def broadcastDatagramm(self): + self.statusLabel.setText(self.tr("Now broadcasting datagram %1").arg(self.messageNo)) + datagram = "Broadcast message %d" % self.messageNo + self.udpSocket.writeDatagram(datagram, QtNetwork.QHostAddress(QtNetwork.QHostAddress.Broadcast), 45454) + self.messageNo += 1 + + +if __name__ == '__main__': + + import sys + + app = QtGui.QApplication(sys.argv) + sender = Sender() + sender.show() + sys.exit(sender.exec_()) diff --git a/examples/network/fortuneclient.py b/examples/network/fortuneclient.py new file mode 100755 index 0000000..8f293fa --- /dev/null +++ b/examples/network/fortuneclient.py @@ -0,0 +1,124 @@ +#!/usr/bin/env python + +"""PyQt4 port of the network/fortuneclient example from Qt v4.x""" + +from PyQt4 import QtCore, QtGui, QtNetwork + + +class Client(QtGui.QDialog): + def __init__(self, parent=None): + super(Client, self).__init__(parent) + + self.blockSize = 0 + self.currentFortune = QtCore.QString() + + hostLabel = QtGui.QLabel(self.tr("&Server name:")) + portLabel = QtGui.QLabel(self.tr("S&erver port:")) + + self.hostLineEdit = QtGui.QLineEdit("Localhost") + self.portLineEdit = QtGui.QLineEdit() + self.portLineEdit.setValidator(QtGui.QIntValidator(1, 65535, self)) + + hostLabel.setBuddy(self.hostLineEdit) + portLabel.setBuddy(self.portLineEdit) + + self.statusLabel = QtGui.QLabel(self.tr("This examples requires that " + "you run the Fortune Server " + "example as well.")) + + self.getFortuneButton = QtGui.QPushButton(self.tr("Get Fortune")) + self.getFortuneButton.setDefault(True) + self.getFortuneButton.setEnabled(False) + + quitButton = QtGui.QPushButton(self.tr("Quit")) + + buttonBox = QtGui.QDialogButtonBox() + buttonBox.addButton(self.getFortuneButton, + QtGui.QDialogButtonBox.ActionRole) + buttonBox.addButton(quitButton, QtGui.QDialogButtonBox.RejectRole) + + self.tcpSocket = QtNetwork.QTcpSocket(self) + + self.hostLineEdit.textChanged.connect(self.enableGetFortuneButton) + self.portLineEdit.textChanged.connect(self.enableGetFortuneButton) + self.getFortuneButton.clicked.connect(self.requestNewFortune) + quitButton.clicked.connect(self.close) + self.tcpSocket.readyRead.connect(self.readFortune) + self.tcpSocket.error.connect(self.displayError) + + mainLayout = QtGui.QGridLayout() + mainLayout.addWidget(hostLabel, 0, 0) + mainLayout.addWidget(self.hostLineEdit, 0, 1) + mainLayout.addWidget(portLabel, 1, 0) + mainLayout.addWidget(self.portLineEdit, 1, 1) + mainLayout.addWidget(self.statusLabel, 2, 0, 1, 2) + mainLayout.addWidget(buttonBox, 3, 0, 1, 2) + self.setLayout(mainLayout) + + self.setWindowTitle(self.tr("Fortune Client")) + self.portLineEdit.setFocus() + + def requestNewFortune(self): + self.getFortuneButton.setEnabled(False) + self.blockSize = 0 + self.tcpSocket.abort() + self.tcpSocket.connectToHost(self.hostLineEdit.text(), + self.portLineEdit.text().toInt()[0]) + + def readFortune(self): + instr = QtCore.QDataStream(self.tcpSocket) + instr.setVersion(QtCore.QDataStream.Qt_4_0) + + if self.blockSize == 0: + if self.tcpSocket.bytesAvailable() < 2: + return + + self.blockSize = instr.readUInt16() + + if self.tcpSocket.bytesAvailable() < self.blockSize: + return + + nextFortune = QtCore.QString() + instr >> nextFortune + + if nextFortune == self.currentFortune: + QtCore.QTimer.singleShot(0, self.requestNewFortune) + return + + self.currentFortune = nextFortune + self.statusLabel.setText(self.currentFortune) + self.getFortuneButton.setEnabled(True) + + def displayError(self, socketError): + if socketError == QtNetwork.QAbstractSocket.RemoteHostClosedError: + pass + elif socketError == QtNetwork.QAbstractSocket.HostNotFoundError: + QtGui.QMessageBox.information(self, self.tr("Fortune Client"), + self.tr("The host was not found. Please check the host " + "name and port settings.")) + elif socketError == QtNetwork.QAbstractSocket.ConnectionRefusedError: + QtGui.QMessageBox.information(self, self.tr("Fortune Client"), + self.tr("The connection was refused by the peer. Make " + "sure the fortune server is running, and check " + "that the host name and port settings are " + "correct.")) + else: + QtGui.QMessageBox.information(self, self.tr("Fortune Client"), + self.tr("The following error occurred: %1.").arg(self.tcpSocket.errorString())) + + self.getFortuneButton.setEnabled(True) + + def enableGetFortuneButton(self): + self.getFortuneButton.setEnabled( + not self.hostLineEdit.text().isEmpty() and + not self.portLineEdit.text().isEmpty()) + + +if __name__ == '__main__': + + import sys + + app = QtGui.QApplication(sys.argv) + client = Client() + client.show() + sys.exit(client.exec_()) diff --git a/examples/network/fortuneserver.py b/examples/network/fortuneserver.py new file mode 100755 index 0000000..d663fa1 --- /dev/null +++ b/examples/network/fortuneserver.py @@ -0,0 +1,78 @@ +#!/usr/bin/env python + +"""PyQt4 port of the network/fortuneserver example from Qt v4.x""" + +import random +import sys + +sys.path +=['/usr/local/lib/python2.6/site-packages'] + +from PySide import QtCore, QtGui, QtNetwork + + +class Server(QtGui.QDialog): + def __init__(self, parent=None): + super(Server, self).__init__(parent) + + statusLabel = QtGui.QLabel() + quitButton = QtGui.QPushButton(self.tr("Quit")) + quitButton.setAutoDefault(False) + + self.tcpServer = QtNetwork.QTcpServer(self) + if not self.tcpServer.listen(): + QtGui.QMessageBox.critical(self, self.tr("Fortune Server"), + self.tr("Unable to start the server: %1.").arg(self.tcpServer.errorString())) + self.close() + return + + statusLabel.setText(self.tr("The server is running on port %1.\n" + "Run the Fortune Client example now.").arg(self.tcpServer.serverPort())) + + self.fortunes = [ + self.tr("You've been leading a dog's life. Stay off the furniture."), + self.tr("You've got to think about tomorrow."), + self.tr("You will be surprised by a loud noise."), + self.tr("You will feel hungry again in another hour."), + self.tr("You might have mail."), + self.tr("You cannot kill time without injuring eternity."), + self.tr("Computers are not intelligent. They only think they are.")] + + quitButton.clicked.connect(self.close) + self.tcpServer.newConnection.connect(self.sendFortune) + + buttonLayout = QtGui.QHBoxLayout() + buttonLayout.addStretch(1) + buttonLayout.addWidget(quitButton) + buttonLayout.addStretch(1) + + mainLayout = QtGui.QVBoxLayout() + mainLayout.addWidget(statusLabel) + mainLayout.addLayout(buttonLayout) + self.setLayout(mainLayout) + + self.setWindowTitle(self.tr("Fortune Server")) + + def sendFortune(self): + block = QtCore.QByteArray() + out = QtCore.QDataStream(block, QtCore.QIODevice.WriteOnly) + out.setVersion(QtCore.QDataStream.Qt_4_0) + out.writeUInt16(0) + out << self.fortunes[random.randint(0, len(self.fortunes) - 1)] + out.device().seek(0) + out.writeUInt16(block.size() - 2) + + clientConnection = self.tcpServer.nextPendingConnection() + clientConnection.disconnected.connect(clientConnection.deleteLater) + + clientConnection.write(block) + clientConnection.disconnectFromHost() + + +if __name__ == '__main__': + + import sys + + app = QtGui.QApplication(sys.argv) + server = Server() + random.seed(None) + sys.exit(server.exec_()) diff --git a/examples/network/ftp/ftp.py b/examples/network/ftp/ftp.py new file mode 100755 index 0000000..cf2d373 --- /dev/null +++ b/examples/network/ftp/ftp.py @@ -0,0 +1,251 @@ +#!/usr/bin/env python + +"""PyQt4 port of the network/ftp example from Qt v4.x""" + +from PyQt4 import QtCore, QtGui, QtNetwork + +import ftp_rc + + +class FtpWindow(QtGui.QDialog): + def __init__(self, parent=None): + super(FtpWindow, self).__init__(parent) + + self.isDirectory = {} + self.currentPath = QtCore.QString() + self.ftp = None + self.outFile = None + + ftpServerLabel = QtGui.QLabel(self.tr("Ftp &server:")) + self.ftpServerLineEdit = QtGui.QLineEdit("ftp.trolltech.com") + ftpServerLabel.setBuddy(self.ftpServerLineEdit) + + self.statusLabel = QtGui.QLabel(self.tr("Please enter the name of an FTP server.")) + + self.fileList = QtGui.QTreeWidget() + self.fileList.setEnabled(False) + self.fileList.setRootIsDecorated(False) + self.fileList.setHeaderLabels(QtCore.QStringList() << self.tr("Name") << self.tr("Size") << self.tr("Owner") << self.tr("Group") << self.tr("Time")) + self.fileList.header().setStretchLastSection(False) + + self.connectButton = QtGui.QPushButton(self.tr("Connect")) + self.connectButton.setDefault(True) + + self.cdToParentButton = QtGui.QPushButton() + self.cdToParentButton.setIcon(QtGui.QIcon(":/images/cdtoparent.png")) + self.cdToParentButton.setEnabled(False) + + self.downloadButton = QtGui.QPushButton(self.tr("Download")) + self.downloadButton.setEnabled(False) + + self.quitButton = QtGui.QPushButton(self.tr("Quit")) + + buttonBox = QtGui.QDialogButtonBox() + buttonBox.addButton(self.downloadButton, + QtGui.QDialogButtonBox.ActionRole) + buttonBox.addButton(self.quitButton, QtGui.QDialogButtonBox.RejectRole) + + self.progressDialog = QtGui.QProgressDialog(self) + + self.fileList.itemActivated.connect(self.processItem) + self.fileList.currentItemChanged.connect(self.enableDownloadButton) + self.progressDialog.canceled.connect(self.cancelDownload) + self.connectButton.clicked.connect(self.connectOrDisconnect) + self.cdToParentButton.clicked.connect(self.cdToParent) + self.downloadButton.clicked.connect(self.downloadFile) + self.quitButton.clicked.connect(self.close) + + topLayout = QtGui.QHBoxLayout() + topLayout.addWidget(ftpServerLabel) + topLayout.addWidget(self.ftpServerLineEdit) + topLayout.addWidget(self.cdToParentButton) + topLayout.addWidget(self.connectButton) + + mainLayout = QtGui.QVBoxLayout() + mainLayout.addLayout(topLayout) + mainLayout.addWidget(self.fileList) + mainLayout.addWidget(self.statusLabel) + mainLayout.addWidget(buttonBox) + self.setLayout(mainLayout) + + self.setWindowTitle(self.tr("FTP")) + + def sizeHint(self): + return QtCore.QSize(500, 300) + + def connectOrDisconnect(self): + if self.ftp: + self.ftp.abort() + self.ftp.deleteLater() + self.ftp = None + + self.fileList.setEnabled(False) + self.cdToParentButton.setEnabled(False) + self.downloadButton.setEnabled(False) + self.connectButton.setEnabled(True) + self.connectButton.setText(self.tr("Connect")) + self.setCursor(QtCore.Qt.ArrowCursor) + + return + + self.setCursor(QtCore.Qt.WaitCursor) + + self.ftp = QtNetwork.QFtp(self) + self.ftp.commandFinished.connect(self.ftpCommandFinished) + self.ftp.listInfo.connect(self.addToList) + self.ftp.dataTransferProgress.connect(self.updateDataTransferProgress) + + self.fileList.clear() + self.currentPath.clear() + self.isDirectory.clear() + + url = QtCore.QUrl(self.ftpServerLineEdit.text()) + if not url.isValid() or url.scheme().toLower() != 'ftp': + self.ftp.connectToHost(self.ftpServerLineEdit.text(), 21) + self.ftp.login() + else: + self.ftp.connectToHost(url.host(), url.port(21)) + + if not url.userName().isEmpty(): + self.ftp.login(QtCore.QUrl.fromPercentEncoding(url.userName().toLatin1()), url.password()) + else: + self.ftp.login() + + if not url.path().isEmpty(): + self.ftp.cd(url.path()) + + self.fileList.setEnabled(True) + self.connectButton.setEnabled(False) + self.connectButton.setText(self.tr("Disconnect")) + self.statusLabel.setText(self.tr("Connecting to FTP server %1...") + .arg(self.ftpServerLineEdit.text())) + + def downloadFile(self): + fileName = self.fileList.currentItem().text(0) + + if QtCore.QFile.exists(fileName): + QtGui.QMessageBox.information(self, self.tr("FTP"), + self.tr("There already exists a file called %1 in the " + "current directory.").arg(fileName)) + return + + self.outFile = QtCore.QFile(fileName) + if not self.outFile.open(QtCore.QIODevice.WriteOnly): + QtGui.QMessageBox.information(self, self.tr("FTP"), + self.tr("Unable to save the file %1: %2.").arg(fileName).arg(self.outFile.errorString())) + self.outFile = None + return + + self.ftp.get(self.fileList.currentItem().text(0), self.outFile) + + self.progressDialog.setLabelText(self.tr("Downloading %1...").arg(fileName)) + self.downloadButton.setEnabled(False) + self.progressDialog.exec_() + + def cancelDownload(self): + self.ftp.abort() + + def ftpCommandFinished(self, _, error): + self.setCursor(QtCore.Qt.ArrowCursor) + + if self.ftp.currentCommand() == QtNetwork.QFtp.ConnectToHost: + if error: + QtGui.QMessageBox.information(self, self.tr("FTP"), + self.tr("Unable to connect to the FTP server at %1. " + "Please check that the host name is correct.").arg(self.ftpServerLineEdit.text())) + self.connectOrDisconnect() + return + + self.statusLabel.setText(self.tr("Logged onto %1.").arg(self.ftpServerLineEdit.text())) + self.fileList.setFocus() + self.downloadButton.setDefault(True) + self.connectButton.setEnabled(True) + return + + if self.ftp.currentCommand() == QtNetwork.QFtp.Login: + self.ftp.list() + + if self.ftp.currentCommand() == QtNetwork.QFtp.Get: + if error: + self.statusLabel.setText(self.tr("Canceled download of %1.") + .arg(self.outFile.fileName())) + self.outFile.close() + self.outFile.remove() + else: + self.statusLabel.setText(self.tr("Downloaded %1 to current directory.") + .arg(self.outFile.fileName())) + self.outFile.close() + + self.outFile = None + self.enableDownloadButton() + self.progressDialog.hide() + elif self.ftp.currentCommand() == QtNetwork.QFtp.List: + if not self.isDirectory: + self.fileList.addTopLevelItem(QtGui.QTreeWidgetItem([self.tr("<empty>")])) + self.fileList.setEnabled(False) + + def addToList(self, urlInfo): + item = QtGui.QTreeWidgetItem() + item.setText(0, urlInfo.name()) + item.setText(1, QtCore.QString.number(urlInfo.size())) + item.setText(2, urlInfo.owner()) + item.setText(3, urlInfo.group()) + item.setText(4, urlInfo.lastModified().toString("MMM dd yyyy")) + + if urlInfo.isDir(): + icon = QtGui.QIcon(":/images/dir.png") + else: + icon = QtGui.QIcon(":/images/file.png") + item.setIcon(0, icon) + + self.isDirectory[urlInfo.name()] = urlInfo.isDir() + self.fileList.addTopLevelItem(item) + if not self.fileList.currentItem(): + self.fileList.setCurrentItem(self.fileList.topLevelItem(0)) + self.fileList.setEnabled(True) + + def processItem(self, item): + name = item.text(0) + if self.isDirectory.get(name): + self.fileList.clear() + self.isDirectory.clear() + self.currentPath += "/" + name + self.ftp.cd(name) + self.ftp.list() + self.cdToParentButton.setEnabled(True) + self.setCursor(QtCore.Qt.WaitCursor) + + def cdToParent(self): + self.setCursor(QtCore.Qt.WaitCursor) + self.fileList.clear() + self.isDirectory.clear() + self.currentPath = self.currentPath.left(self.currentPath.lastIndexOf('/')) + if self.currentPath.isEmpty(): + self.cdToParentButton.setEnabled(False) + self.ftp.cd("/") + else: + self.ftp.cd(self.currentPath) + + self.ftp.list() + + def updateDataTransferProgress(self, readBytes, totalBytes): + self.progressDialog.setMaximum(totalBytes) + self.progressDialog.setValue(readBytes) + + def enableDownloadButton(self): + current = self.fileList.currentItem() + if current: + currentFile = current.text(0) + self.downloadButton.setEnabled(not self.isDirectory.get(currentFile)) + else: + self.downloadButton.setEnabled(False) + + +if __name__ == '__main__': + + import sys + + app = QtGui.QApplication(sys.argv) + ftpWin = FtpWindow() + ftpWin.show() + sys.exit(ftpWin.exec_()) diff --git a/examples/network/ftp/ftp.qrc b/examples/network/ftp/ftp.qrc new file mode 100644 index 0000000..b598ab8 --- /dev/null +++ b/examples/network/ftp/ftp.qrc @@ -0,0 +1,7 @@ +<!DOCTYPE RCC><RCC version="1.0"> +<qresource> + <file>images/cdtoparent.png</file> + <file>images/dir.png</file> + <file>images/file.png</file> +</qresource> +</RCC> diff --git a/examples/network/ftp/images/cdtoparent.png b/examples/network/ftp/images/cdtoparent.png Binary files differnew file mode 100644 index 0000000..24b6180 --- /dev/null +++ b/examples/network/ftp/images/cdtoparent.png diff --git a/examples/network/ftp/images/dir.png b/examples/network/ftp/images/dir.png Binary files differnew file mode 100644 index 0000000..e81f5cd --- /dev/null +++ b/examples/network/ftp/images/dir.png diff --git a/examples/network/ftp/images/file.png b/examples/network/ftp/images/file.png Binary files differnew file mode 100644 index 0000000..be6c530 --- /dev/null +++ b/examples/network/ftp/images/file.png diff --git a/examples/network/http/authenticationdialog.ui b/examples/network/http/authenticationdialog.ui new file mode 100644 index 0000000..82d908c --- /dev/null +++ b/examples/network/http/authenticationdialog.ui @@ -0,0 +1,129 @@ +<ui version="4.0" > + <class>Dialog</class> + <widget class="QDialog" name="Dialog" > + <property name="geometry" > + <rect> + <x>0</x> + <y>0</y> + <width>389</width> + <height>243</height> + </rect> + </property> + <property name="windowTitle" > + <string>Http authentication required</string> + </property> + <layout class="QGridLayout" > + <item row="0" column="0" colspan="2" > + <widget class="QLabel" name="label" > + <property name="text" > + <string>You need to supply a Username and a Password to access this site</string> + </property> + <property name="wordWrap" > + <bool>false</bool> + </property> + </widget> + </item> + <item row="2" column="0" > + <widget class="QLabel" name="label_2" > + <property name="text" > + <string>Username:</string> + </property> + </widget> + </item> + <item row="2" column="1" > + <widget class="QLineEdit" name="userEdit" /> + </item> + <item row="3" column="0" > + <widget class="QLabel" name="label_3" > + <property name="text" > + <string>Password:</string> + </property> + </widget> + </item> + <item row="3" column="1" > + <widget class="QLineEdit" name="passwordEdit" /> + </item> + <item row="5" column="0" colspan="2" > + <widget class="QDialogButtonBox" name="buttonBox" > + <property name="orientation" > + <enum>Qt::Horizontal</enum> + </property> + <property name="standardButtons" > + <set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set> + </property> + </widget> + </item> + <item row="1" column="0" > + <widget class="QLabel" name="label_4" > + <property name="text" > + <string>Site:</string> + </property> + </widget> + </item> + <item row="1" column="1" > + <widget class="QLabel" name="siteDescription" > + <property name="font" > + <font> + <weight>75</weight> + <bold>true</bold> + </font> + </property> + <property name="text" > + <string>%1 at %2</string> + </property> + <property name="wordWrap" > + <bool>true</bool> + </property> + </widget> + </item> + <item row="4" column="0" > + <spacer> + <property name="orientation" > + <enum>Qt::Vertical</enum> + </property> + <property name="sizeHint" > + <size> + <width>20</width> + <height>40</height> + </size> + </property> + </spacer> + </item> + </layout> + </widget> + <resources/> + <connections> + <connection> + <sender>buttonBox</sender> + <signal>accepted()</signal> + <receiver>Dialog</receiver> + <slot>accept()</slot> + <hints> + <hint type="sourcelabel" > + <x>248</x> + <y>254</y> + </hint> + <hint type="destinationlabel" > + <x>157</x> + <y>274</y> + </hint> + </hints> + </connection> + <connection> + <sender>buttonBox</sender> + <signal>rejected()</signal> + <receiver>Dialog</receiver> + <slot>reject()</slot> + <hints> + <hint type="sourcelabel" > + <x>316</x> + <y>260</y> + </hint> + <hint type="destinationlabel" > + <x>286</x> + <y>274</y> + </hint> + </hints> + </connection> + </connections> +</ui> diff --git a/examples/network/http/http.py b/examples/network/http/http.py new file mode 100755 index 0000000..d76b2d0 --- /dev/null +++ b/examples/network/http/http.py @@ -0,0 +1,196 @@ +#!/usr/bin/env python + +"""PyQt4 port of the network/http example from Qt v4.x""" + +from PyQt4 import QtCore, QtGui, QtNetwork + + +class HttpWindow(QtGui.QDialog): + def __init__(self, parent=None): + super(HttpWindow, self).__init__(parent) + + self.outFile = None + self.httpGetId = 0 + self.httpRequestAborted = False + + self.urlLineEdit = QtGui.QLineEdit("https://") + + urlLabel = QtGui.QLabel(self.tr("&URL:")) + urlLabel.setBuddy(self.urlLineEdit) + self.statusLabel = QtGui.QLabel(self.tr("Please enter the URL of a " + "file you want to download.")) + + self.downloadButton = QtGui.QPushButton(self.tr("Download")) + self.downloadButton.setDefault(True) + self.quitButton = QtGui.QPushButton(self.tr("Quit")) + self.quitButton.setAutoDefault(False) + + buttonBox = QtGui.QDialogButtonBox() + buttonBox.addButton(self.downloadButton, + QtGui.QDialogButtonBox.ActionRole) + buttonBox.addButton(self.quitButton, QtGui.QDialogButtonBox.RejectRole) + + self.progressDialog = QtGui.QProgressDialog(self) + + self.http = QtNetwork.QHttp(self) + + self.urlLineEdit.textChanged.connect(self.enableDownloadButton) + self.http.requestFinished.connect(self.httpRequestFinished) + self.http.dataReadProgress.connect(self.updateDataReadProgress) + self.http.responseHeaderReceived.connect(self.readResponseHeader) + self.http.authenticationRequired.connect(self.slotAuthenticationRequired) + self.http.sslErrors.connect(self.sslErrors) + self.progressDialog.canceled.connect(self.cancelDownload) + self.downloadButton.clicked.connect(self.downloadFile) + self.quitButton.clicked.connect(self.close) + + topLayout = QtGui.QHBoxLayout() + topLayout.addWidget(urlLabel) + topLayout.addWidget(self.urlLineEdit) + + mainLayout = QtGui.QVBoxLayout() + mainLayout.addLayout(topLayout) + mainLayout.addWidget(self.statusLabel) + mainLayout.addWidget(buttonBox) + self.setLayout(mainLayout) + + self.setWindowTitle(self.tr("HTTP")) + self.urlLineEdit.setFocus() + + def downloadFile(self): + url = QtCore.QUrl(self.urlLineEdit.text()) + fileInfo = QtCore.QFileInfo(url.path()) + fileName = QtCore.QString(fileInfo.fileName()) + + if fileName.isEmpty(): + fileName = "index.html" + + if QtCore.QFile.exists(fileName): + ret = QtGui.QMessageBox.question(self, self.tr("HTTP"), + self.tr("There already exists a file called %1 in the " + "current directory.").arg(fileName), + QtGui.QMessageBox.Ok | QtGui.QMessageBox.Cancel, + QtGui.QMessageBox.Cancel) + + if ret == QtGui.QMessageBox.Cancel: + return + + QtCore.QFile.remove(fileName) + + self.outFile = QtCore.QFile(fileName) + if not self.outFile.open(QtCore.QIODevice.WriteOnly): + QtGui.QMessageBox.information(self, self.tr("HTTP"), + self.tr("Unable to save the file %1: %2.").arg(fileName).arg(self.outFile.errorString())) + self.outFile = None + return + + if url.scheme().toLower() == 'https': + mode = QtNetwork.QHttp.ConnectionModeHttps + else: + mode = QtNetwork.QHttp.ConnectionModeHttp + + port = url.port() + + if port == -1: + port = 0 + + self.http.setHost(url.host(), mode, port) + + if not url.userName().isEmpty(): + self.http.setUser(url.userName(), url.password()) + + self.httpRequestAborted = False + path = QtCore.QUrl.toPercentEncoding(url.path(), "!$&'()*+,;=:@/") + if path.isEmpty(): + path = "/" + self.httpGetId = self.http.get(path, self.outFile) + + self.progressDialog.setWindowTitle(self.tr("HTTP")) + self.progressDialog.setLabelText(self.tr("Downloading %1.").arg(fileName)) + self.downloadButton.setEnabled(False) + + def cancelDownload(self): + self.statusLabel.setText(self.tr("Download canceled.")) + self.httpRequestAborted = True + self.http.abort() + self.downloadButton.setEnabled(True) + + def httpRequestFinished(self, requestId, error): + if requestId != self.httpGetId: + return + + if self.httpRequestAborted: + if self.outFile is not None: + self.outFile.close() + self.outFile.remove() + self.outFile = None + + self.progressDialog.hide() + return + + self.progressDialog.hide() + self.outFile.close() + + if error: + self.outFile.remove() + QtGui.QMessageBox.information(self, self.tr("HTTP"), + self.tr("Download failed: %1.").arg(self.http.errorString())) + else: + fileName = QtCore.QFileInfo(QtCore.QUrl(self.urlLineEdit.text()).path()).fileName() + self.statusLabel.setText(self.tr("Downloaded %1 to current directory.").arg(fileName)) + + self.downloadButton.setEnabled(True) + self.outFile = None + + def readResponseHeader(self, responseHeader): + # Check for genuine error conditions. + if responseHeader.statusCode() not in (200, 300, 301, 302, 303, 307): + QtGui.QMessageBox.information(self, self.tr("HTTP"), + self.tr("Download failed: %1.") + .arg(responseHeader.reasonPhrase())) + self.httpRequestAborted = True + self.progressDialog.hide() + self.http.abort() + + def updateDataReadProgress(self, bytesRead, totalBytes): + if self.httpRequestAborted: + return + + self.progressDialog.setMaximum(totalBytes) + self.progressDialog.setValue(bytesRead) + + def enableDownloadButton(self): + self.downloadButton.setEnabled(not self.urlLineEdit.text().isEmpty()) + + def slotAuthenticationRequired(self, hostName, _, authenticator): + import os + from PyQt4 import uic + + ui = os.path.join(os.path.dirname(__file__), 'authenticationdialog.ui') + dlg = uic.loadUi(ui) + dlg.adjustSize() + dlg.siteDescription.setText(self.tr("%1 at %2").arg(authenticator.realm()).arg(hostName)) + + if dlg.exec_() == QtGui.QDialog.Accepted: + authenticator.setUser(dlg.userEdit.text()) + authenticator.setPassword(dlg.passwordEdit.text()) + + def sslErrors(self, errors): + errorString = ", ".join([str(error.errorString()) for error in errors]) + + ret = QtGui.QMessageBox.warning(self, self.tr("HTTP Example"), + self.tr("One or more SSL errors has occurred: %1").arg(errorString), + QtGui.QMessageBox.Ignore | QtGui.QMessageBox.Abort) + + if ret == QtGui.QMessageBox.Ignore: + self.http.ignoreSslErrors() + + +if __name__ == '__main__': + + import sys + + app = QtGui.QApplication(sys.argv) + httpWin = HttpWindow() + httpWin.show() + sys.exit(httpWin.exec_()) diff --git a/examples/network/loopback.py b/examples/network/loopback.py new file mode 100755 index 0000000..8b6f8e1 --- /dev/null +++ b/examples/network/loopback.py @@ -0,0 +1,154 @@ +#!/usr/bin/env python + +############################################################################ +# +# Copyright (C) 2004-2005 Trolltech AS. All rights reserved. +# +# This file is part of the example classes of the Qt Toolkit. +# +# This file may be used under the terms of the GNU General Public +# License version 2.0 as published by the Free Software Foundation +# and appearing in the file LICENSE.GPL included in the packaging of +# self file. Please review the following information to ensure GNU +# General Public Licensing requirements will be met: +# http://www.trolltech.com/products/qt/opensource.html +# +# If you are unsure which license is appropriate for your use, please +# review the following information: +# http://www.trolltech.com/products/qt/licensing.html or contact the +# sales department at sales@trolltech.com. +# +# This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +# WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +# +############################################################################ + +from PyQt4 import QtCore, QtGui, QtNetwork + + +class Dialog(QtGui.QDialog): + TotalBytes = 50 * 1024 * 1024 + PayloadSize = 65536 + + def __init__(self, parent=None): + super(Dialog, self).__init__(parent) + + self.tcpServer = QtNetwork.QTcpServer() + self.tcpClient = QtNetwork.QTcpSocket() + self.bytesToWrite = 0 + self.bytesWritten = 0 + self.bytesReceived = 0 + + self.clientProgressBar = QtGui.QProgressBar() + self.clientStatusLabel = QtGui.QLabel(self.tr("Client ready")) + self.serverProgressBar = QtGui.QProgressBar() + self.serverStatusLabel = QtGui.QLabel(self.tr("Server ready")) + + self.startButton = QtGui.QPushButton(self.tr("&Start")) + self.quitButton = QtGui.QPushButton(self.tr("&Quit")) + + buttonBox = QtGui.QDialogButtonBox() + buttonBox.addButton(self.startButton, QtGui.QDialogButtonBox.ActionRole) + buttonBox.addButton(self.quitButton, QtGui.QDialogButtonBox.RejectRole) + + self.startButton.clicked.connect(self.start) + self.quitButton.clicked.connect(self.close) + self.tcpServer.newConnection.connect(self.acceptConnection) + self.tcpClient.connected.connect(self.startTransfer) + self.tcpClient.bytesWritten.connect(self.updateClientProgress) + self.tcpClient.error.connect(self.displayError) + + mainLayout = QtGui.QVBoxLayout() + mainLayout.addWidget(self.clientProgressBar) + mainLayout.addWidget(self.clientStatusLabel) + mainLayout.addWidget(self.serverProgressBar) + mainLayout.addWidget(self.serverStatusLabel) + mainLayout.addStretch(1) + mainLayout.addSpacing(10) + mainLayout.addWidget(buttonBox) + self.setLayout(mainLayout) + + self.setWindowTitle(self.tr("Loopback")) + + def start(self): + self.startButton.setEnabled(False) + + QtGui.QApplication.setOverrideCursor(QtCore.Qt.WaitCursor) + + self.bytesWritten = 0 + self.bytesReceived = 0 + + while not self.tcpServer.isListening() and not self.tcpServer.listen(): + ret = QtGui.QMessageBox.critical(self, self.tr("Loopback"), + self.tr("Unable to start the test: %1.").arg(self.tcpServer.errorString()), + QtGui.QMessageBox.Retry | QtGui.QMessageBox.Cancel) + if ret == QtGui.QMessageBox.Cancel: + return + + self.serverStatusLabel.setText(self.tr("Listening")) + self.clientStatusLabel.setText(self.tr("Connecting")) + + self.tcpClient.connectToHost(QtNetwork.QHostAddress(QtNetwork.QHostAddress.LocalHost), self.tcpServer.serverPort()) + + def acceptConnection(self): + self.tcpServerConnection = self.tcpServer.nextPendingConnection() + self.tcpServerConnection.readyRead.connect(self.updateServerProgress) + self.tcpServerConnection.error.connect(self.displayError) + + self.serverStatusLabel.setText(self.tr("Accepted connection")) + self.tcpServer.close() + + def startTransfer(self): + self.bytesToWrite = Dialog.TotalBytes - self.tcpClient.write(QtCore.QByteArray(Dialog.PayloadSize, '@')) + self.clientStatusLabel.setText(self.tr("Connected")) + + def updateServerProgress(self): + self.bytesReceived += self.tcpServerConnection.bytesAvailable() + self.tcpServerConnection.readAll() + + self.serverProgressBar.setMaximum(Dialog.TotalBytes) + self.serverProgressBar.setValue(self.bytesReceived) + self.serverStatusLabel.setText(self.tr("Received %1MB") + .arg(self.bytesReceived / (1024 * 1024))) + + if self.bytesReceived == Dialog.TotalBytes: + self.tcpServerConnection.close() + self.startButton.setEnabled(True) + QtGui.QApplication.restoreOverrideCursor() + + def updateClientProgress(self, numBytes): + self.bytesWritten += numBytes + if self.bytesToWrite > 0: + self.bytesToWrite -= self.tcpClient.write(QtCore.QByteArray( + min(self.bytesToWrite, Dialog.PayloadSize), '@')) + + self.clientProgressBar.setMaximum(Dialog.TotalBytes) + self.clientProgressBar.setValue(self.bytesWritten) + self.clientStatusLabel.setText(self.tr("Sent %1MB") + .arg(self.bytesWritten / (1024 * 1024))) + + def displayError(self, socketError): + if socketError == QtNetwork.QTcpSocket.RemoteHostClosedError: + return + + QtGui.QMessageBox.information(self, self.tr("Network error"), + self.tr("The following error occured: %1.").arg(self.tcpClient.errorString())) + + self.tcpClient.close() + self.tcpServer.close() + self.clientProgressBar.reset() + self.serverProgressBar.reset() + self.clientStatusLabel.setText(self.tr("Client ready")) + self.serverStatusLabel.setText(self.tr("Server ready")) + self.startButton.setEnabled(True) + QtGui.QApplication.restoreOverrideCursor() + + +if __name__ == '__main__': + + import sys + + app = QtGui.QApplication(sys.argv) + dialog = Dialog() + dialog.show() + sys.exit(dialog.exec_()) diff --git a/examples/network/threadedfortuneserver.py b/examples/network/threadedfortuneserver.py new file mode 100755 index 0000000..b7dfe8c --- /dev/null +++ b/examples/network/threadedfortuneserver.py @@ -0,0 +1,121 @@ +#!/usr/bin/env python + +############################################################################ +# +# Copyright (C) 2004-2005 Trolltech AS. All rights reserved. +# +# This file is part of the example classes of the Qt Toolkit. +# +# This file may be used under the terms of the GNU General Public +# License version 2.0 as published by the Free Software Foundation +# and appearing in the file LICENSE.GPL included in the packaging of +# self file. Please review the following information to ensure GNU +# General Public Licensing requirements will be met: +# http://www.trolltech.com/products/qt/opensource.html +# +# If you are unsure which license is appropriate for your use, please +# review the following information: +# http://www.trolltech.com/products/qt/licensing.html or contact the +# sales department at sales@trolltech.com. +# +# This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +# WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +# +############################################################################ + +import random + +from PyQt4 import QtCore, QtGui, QtNetwork + + +class FortuneThread(QtCore.QThread): + error = QtCore.pyqtSignal(QtNetwork.QTcpSocket.SocketError) + + def __init__(self, socketDescriptor, fortune, parent): + super(FortuneThread, self).__init__(parent) + + self.socketDescriptor = socketDescriptor + self.text = fortune + + def run(self): + tcpSocket = QtNetwork.QTcpSocket() + if not tcpSocket.setSocketDescriptor(self.socketDescriptor): + self.error.emit(tcpSocket.error()) + return + + block = QtCore.QByteArray() + outstr = QtCore.QDataStream(block, QtCore.QIODevice.WriteOnly) + outstr.setVersion(QtCore.QDataStream.Qt_4_0) + outstr.writeUInt16(0) + outstr << self.text + outstr.device().seek(0) + outstr.writeUInt16(block.count() - 2) + + tcpSocket.write(block) + tcpSocket.disconnectFromHost() + tcpSocket.waitForDisconnected() + + +class FortuneServer(QtNetwork.QTcpServer): + def __init__(self, parent=None): + super(FortuneServer, self).__init__(parent) + + self.fortunes = [ + self.tr("You've been leading a dog's life. Stay off the furniture."), + self.tr("You've got to think about tomorrow."), + self.tr("You will be surprised by a loud noise."), + self.tr("You will feel hungry again in another hour."), + self.tr("You might have mail."), + self.tr("You cannot kill time without injuring eternity."), + self.tr("Computers are not intelligent. They only think they are.")] + + def incomingConnection(self, socketDescriptor): + fortune = self.fortunes[random.randint(0, len(self.fortunes) - 1)] + thread = FortuneThread(socketDescriptor, fortune, self) + thread.finished.connect(thread.deleteLater) + thread.start() + + +class Dialog(QtGui.QDialog): + def __init__(self, parent=None): + super(Dialog, self).__init__(parent) + + self.server = FortuneServer() + + statusLabel = QtGui.QLabel() + quitButton = QtGui.QPushButton(self.tr("Quit")) + quitButton.setAutoDefault(False) + + if not self.server.listen(): + QtGui.QMessageBox.critical(self, + self.tr("Threaded Fortune Server"), + self.tr("Unable to start the server: %1.".arg(self.server.errorString()))) + self.close() + return + + statusLabel.setText(self.tr("The server is running on port %1.\n" + "Run the Fortune Client example now.").arg(self.server.serverPort())) + + quitButton.clicked.connect(self.close) + + buttonLayout = QtGui.QHBoxLayout() + buttonLayout.addStretch(1) + buttonLayout.addWidget(quitButton) + buttonLayout.addStretch(1) + + mainLayout = QtGui.QVBoxLayout() + mainLayout.addWidget(statusLabel) + mainLayout.addLayout(buttonLayout) + self.setLayout(mainLayout) + + self.setWindowTitle(self.tr("Threaded Fortune Server")) + + +if __name__ == '__main__': + + import sys + + app = QtGui.QApplication(sys.argv) + dialog = Dialog() + dialog.show() + sys.exit(dialog.exec_()) |