summaryrefslogtreecommitdiffstats
path: root/examples/network
diff options
context:
space:
mode:
authorTimothy Pearson <kb9vqf@pearsoncomputing.net>2011-07-10 15:24:15 -0500
committerTimothy Pearson <kb9vqf@pearsoncomputing.net>2011-07-10 15:24:15 -0500
commitbd0f3345a938b35ce6a12f6150373b0955b8dd12 (patch)
tree7a520322212d48ebcb9fbe1087e7fca28b76185c /examples/network
downloadqt3-bd0f3345a938b35ce6a12f6150373b0955b8dd12.tar.gz
qt3-bd0f3345a938b35ce6a12f6150373b0955b8dd12.zip
Add Qt3 development HEAD version
Diffstat (limited to 'examples/network')
-rw-r--r--examples/network/archivesearch/archivedialog.ui137
-rw-r--r--examples/network/archivesearch/archivedialog.ui.h102
-rw-r--r--examples/network/archivesearch/archivesearch.doc25
-rw-r--r--examples/network/archivesearch/archivesearch.pro9
-rw-r--r--examples/network/archivesearch/main.cpp23
-rw-r--r--examples/network/clientserver/client/client.cpp125
-rw-r--r--examples/network/clientserver/client/client.pro9
-rw-r--r--examples/network/clientserver/clientserver.doc35
-rw-r--r--examples/network/clientserver/server/server.cpp162
-rw-r--r--examples/network/clientserver/server/server.pro9
-rw-r--r--examples/network/ftpclient/README3
-rw-r--r--examples/network/ftpclient/connectdialog.ui244
-rw-r--r--examples/network/ftpclient/ftpclient.doc24
-rw-r--r--examples/network/ftpclient/ftpclient.pro14
-rw-r--r--examples/network/ftpclient/ftpmainwindow.ui280
-rw-r--r--examples/network/ftpclient/ftpmainwindow.ui.h273
-rw-r--r--examples/network/ftpclient/ftpviewitem.cpp58
-rw-r--r--examples/network/ftpclient/ftpviewitem.h35
-rw-r--r--examples/network/ftpclient/images/file.pngbin0 -> 106 bytes
-rw-r--r--examples/network/ftpclient/images/folder.pngbin0 -> 145 bytes
-rw-r--r--examples/network/ftpclient/main.cpp23
-rw-r--r--examples/network/httpd/README7
-rw-r--r--examples/network/httpd/httpd.cpp141
-rw-r--r--examples/network/httpd/httpd.doc20
-rw-r--r--examples/network/httpd/httpd.pro9
-rw-r--r--examples/network/infoprotocol/infoclient/client.cpp120
-rw-r--r--examples/network/infoprotocol/infoclient/client.h47
-rw-r--r--examples/network/infoprotocol/infoclient/clientbase.ui276
-rw-r--r--examples/network/infoprotocol/infoclient/infoclient.pro11
-rw-r--r--examples/network/infoprotocol/infoclient/main.cpp21
-rw-r--r--examples/network/infoprotocol/infoserver/infodata.cpp88
-rw-r--r--examples/network/infoprotocol/infoserver/infodata.h31
-rw-r--r--examples/network/infoprotocol/infoserver/infoserver.pro13
-rw-r--r--examples/network/infoprotocol/infoserver/main.cpp22
-rw-r--r--examples/network/infoprotocol/infoserver/server.cpp99
-rw-r--r--examples/network/infoprotocol/infoserver/server.h69
-rw-r--r--examples/network/infoprotocol/infoserver/serverbase.ui117
-rw-r--r--examples/network/infoprotocol/infourlclient/client.cpp60
-rw-r--r--examples/network/infoprotocol/infourlclient/client.h35
-rw-r--r--examples/network/infoprotocol/infourlclient/clientbase.ui118
-rw-r--r--examples/network/infoprotocol/infourlclient/infourlclient.pro13
-rw-r--r--examples/network/infoprotocol/infourlclient/main.cpp23
-rw-r--r--examples/network/infoprotocol/infourlclient/qip.cpp132
-rw-r--r--examples/network/infoprotocol/infourlclient/qip.h48
-rw-r--r--examples/network/mail/composer.cpp65
-rw-r--r--examples/network/mail/composer.h41
-rw-r--r--examples/network/mail/mail.doc25
-rw-r--r--examples/network/mail/mail.pro12
-rw-r--r--examples/network/mail/main.cpp23
-rw-r--r--examples/network/mail/smtp.cpp127
-rw-r--r--examples/network/mail/smtp.h58
-rw-r--r--examples/network/networkprotocol/README5
-rw-r--r--examples/network/networkprotocol/main.cpp29
-rw-r--r--examples/network/networkprotocol/networkprotocol.doc26
-rw-r--r--examples/network/networkprotocol/networkprotocol.pro10
-rw-r--r--examples/network/networkprotocol/nntp.cpp256
-rw-r--r--examples/network/networkprotocol/nntp.h49
-rw-r--r--examples/network/networkprotocol/view.cpp90
-rw-r--r--examples/network/networkprotocol/view.h37
-rw-r--r--examples/network/remotecontrol/ipcserver.cpp84
-rw-r--r--examples/network/remotecontrol/ipcserver.h20
-rw-r--r--examples/network/remotecontrol/main.cpp11
-rw-r--r--examples/network/remotecontrol/maindialog.ui165
-rw-r--r--examples/network/remotecontrol/remotecontrol.pro16
-rw-r--r--examples/network/remotecontrol/remotectrl.ui145
-rw-r--r--examples/network/remotecontrol/remotectrlimpl.cpp50
-rw-r--r--examples/network/remotecontrol/remotectrlimpl.h26
-rw-r--r--examples/network/remotecontrol/startup.cpp45
-rw-r--r--examples/network/remotecontrol/startup.h28
69 files changed, 4553 insertions, 0 deletions
diff --git a/examples/network/archivesearch/archivedialog.ui b/examples/network/archivesearch/archivedialog.ui
new file mode 100644
index 0000000..0aafb7b
--- /dev/null
+++ b/examples/network/archivesearch/archivedialog.ui
@@ -0,0 +1,137 @@
+<!DOCTYPE UI><UI version="3.1" stdsetdef="1">
+<class>ArchiveDialog</class>
+<widget class="QDialog">
+ <property name="name">
+ <cstring>ArchiveDialog</cstring>
+ </property>
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>673</width>
+ <height>561</height>
+ </rect>
+ </property>
+ <property name="caption">
+ <string>Qt-interest Archive Search Tool</string>
+ </property>
+ <vbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QLayoutWidget">
+ <property name="name">
+ <cstring>layout1</cstring>
+ </property>
+ <hbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QLabel">
+ <property name="name">
+ <cstring>myTextLabel</cstring>
+ </property>
+ <property name="text">
+ <string>Search phrase</string>
+ </property>
+ </widget>
+ <widget class="QLineEdit">
+ <property name="name">
+ <cstring>myLineEdit</cstring>
+ </property>
+ </widget>
+ </hbox>
+ </widget>
+ <widget class="QSplitter">
+ <property name="name">
+ <cstring>splitter1</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Horizontal</enum>
+ </property>
+ <widget class="QListView">
+ <column>
+ <property name="text">
+ <string>Matching documents</string>
+ </property>
+ <property name="clickable">
+ <bool>true</bool>
+ </property>
+ <property name="resizable">
+ <bool>true</bool>
+ </property>
+ </column>
+ <property name="name">
+ <cstring>myListView</cstring>
+ </property>
+ </widget>
+ <widget class="QTextBrowser">
+ <property name="name">
+ <cstring>myTextBrowser</cstring>
+ </property>
+ </widget>
+ </widget>
+ <widget class="QLayoutWidget">
+ <property name="name">
+ <cstring>layout3</cstring>
+ </property>
+ <hbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <spacer>
+ <property name="name">
+ <cstring>mySpacer</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Horizontal</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Expanding</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>281</width>
+ <height>21</height>
+ </size>
+ </property>
+ </spacer>
+ <widget class="QPushButton">
+ <property name="name">
+ <cstring>myPushButton</cstring>
+ </property>
+ <property name="text">
+ <string>&amp;Quit</string>
+ </property>
+ <property name="autoDefault">
+ <bool>false</bool>
+ </property>
+ </widget>
+ </hbox>
+ </widget>
+ </vbox>
+</widget>
+<includes>
+ <include location="global" impldecl="in declaration">qhttp.h</include>
+ <include location="global" impldecl="in declaration">qurl.h</include>
+ <include location="global" impldecl="in declaration">qmessagebox.h</include>
+ <include location="global" impldecl="in declaration">qapplication.h</include>
+ <include location="global" impldecl="in declaration">qcursor.h</include>
+ <include location="global" impldecl="in declaration">qregexp.h</include>
+ <include location="local" impldecl="in implementation">archivedialog.ui.h</include>
+</includes>
+<variables>
+ <variable access="private">QHttp articleSearcher;</variable>
+ <variable access="private">QHttp articleFetcher;</variable>
+</variables>
+<slots>
+ <slot specifier="non virtual">fetch( QListViewItem * it )</slot>
+ <slot specifier="non virtual">fetchDone( bool error )</slot>
+ <slot specifier="non virtual">search()</slot>
+ <slot specifier="non virtual">searchDone( bool error )</slot>
+</slots>
+<functions>
+ <function access="private" specifier="non virtual">init()</function>
+</functions>
+<layoutdefaults spacing="6" margin="11"/>
+</UI>
diff --git a/examples/network/archivesearch/archivedialog.ui.h b/examples/network/archivesearch/archivedialog.ui.h
new file mode 100644
index 0000000..6608cd6
--- /dev/null
+++ b/examples/network/archivesearch/archivedialog.ui.h
@@ -0,0 +1,102 @@
+/****************************************************************************
+**
+** Copyright (C) 1992-2008 Trolltech ASA. All rights reserved.
+**
+** This file is part of an example program for Qt. This example
+** program may be used, distributed and modified without limitation.
+**
+*****************************************************************************/
+
+/****************************************************************************
+** ui.h extension file, included from the uic-generated form implementation.
+**
+** If you wish to add, delete or rename functions or slots use
+** Qt Designer which will update this file, preserving your code. Create an
+** init() function in place of a constructor, and a destroy() function in
+** place of a destructor.
+*****************************************************************************/
+
+void ArchiveDialog::init()
+{
+ connect(&articleSearcher, SIGNAL(done(bool)), this, SLOT(searchDone(bool)));
+ connect(&articleFetcher, SIGNAL(done(bool)), this, SLOT(fetchDone(bool)));
+ connect(myListView, SIGNAL(selectionChanged(QListViewItem*)), this, SLOT(fetch(QListViewItem*)));
+ connect(myLineEdit, SIGNAL(returnPressed()), this, SLOT(search()));
+ connect(myListView, SIGNAL(returnPressed(QListViewItem*)), this, SLOT(fetch(QListViewItem*)));
+ connect(myPushButton, SIGNAL(clicked()), this, SLOT(close()));
+}
+
+void ArchiveDialog::fetch( QListViewItem *it )
+{
+ QUrl u(it->text(1));
+ articleFetcher.setHost(u.host());
+ articleFetcher.get(it->text(1));
+}
+
+void ArchiveDialog::fetchDone( bool error )
+{
+ if (error) {
+ QMessageBox::critical(this, "Error fetching",
+ "An error occurred when fetching this document: "
+ + articleFetcher.errorString(),
+ QMessageBox::Ok, QMessageBox::NoButton);
+ } else {
+ myTextBrowser->setText(articleFetcher.readAll());
+ }
+}
+
+void ArchiveDialog::search()
+{
+ if (articleSearcher.state() == QHttp::HostLookup
+ || articleSearcher.state() == QHttp::Connecting
+ || articleSearcher.state() == QHttp::Sending
+ || articleSearcher.state() == QHttp::Reading) {
+ articleSearcher.abort();
+ }
+
+ if (myLineEdit->text() == "") {
+ QMessageBox::critical(this, "Empty query",
+ "Please type a search string.",
+ QMessageBox::Ok, QMessageBox::NoButton);
+ } else {
+ QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
+
+ articleSearcher.setHost("lists.trolltech.com");
+
+ QHttpRequestHeader header("POST", "/qt-interest/search.php");
+ header.setValue("Host", "lists.trolltech.com");
+ header.setContentType("application/x-www-form-urlencoded");
+
+ QString encodedTopic = myLineEdit->text();
+ QUrl::encode(encodedTopic);
+ QString searchString = "qt-interest=on&search=" + encodedTopic;
+
+ articleSearcher.request(header, searchString.utf8());
+ }
+
+}
+
+void ArchiveDialog::searchDone( bool error )
+{
+ if (error) {
+ QMessageBox::critical(this, "Error searching",
+ "An error occurred when searching: "
+ + articleSearcher.errorString(),
+ QMessageBox::Ok, QMessageBox::NoButton);
+ } else {
+ QString result(articleSearcher.readAll());
+
+ QRegExp rx("<a href=\"(http://lists\\.trolltech\\.com/qt-interest/.*)\">(.*)</a>");
+ rx.setMinimal(TRUE);
+ int pos = 0;
+ while (pos >= 0) {
+ pos = rx.search(result, pos);
+ if (pos > -1) {
+ pos += rx.matchedLength();
+ new QListViewItem(myListView, rx.cap(2), rx.cap(1));
+ }
+ }
+ }
+
+ QApplication::restoreOverrideCursor();
+}
diff --git a/examples/network/archivesearch/archivesearch.doc b/examples/network/archivesearch/archivesearch.doc
new file mode 100644
index 0000000..e4589cc
--- /dev/null
+++ b/examples/network/archivesearch/archivesearch.doc
@@ -0,0 +1,25 @@
+/*
+*/
+
+/*! \page archivesearch-example.html
+
+ \ingroup network-examples
+
+ \title A qt-interest mail archive search
+
+ This example does a search on the qt-interest mailinglist archives. It uses
+ QHttp to issue the search command and to fetch the results. The GUI parts
+ were done using \link designer-manual.book Qt Designer\endlink.
+
+ <hr>
+
+ The implementation of the HTTP requests (archivedialog.ui.h):
+
+ \include network/archivesearch/archivedialog.ui.h
+
+ <hr>
+
+ Main (main.cpp):
+
+ \include network/archivesearch/main.cpp
+*/
diff --git a/examples/network/archivesearch/archivesearch.pro b/examples/network/archivesearch/archivesearch.pro
new file mode 100644
index 0000000..1423814
--- /dev/null
+++ b/examples/network/archivesearch/archivesearch.pro
@@ -0,0 +1,9 @@
+TEMPLATE = app
+
+CONFIG += qt warn_on release
+
+REQUIRES = network full-config
+
+HEADERS += archivedialog.ui.h
+INTERFACES += archivedialog.ui
+SOURCES += main.cpp
diff --git a/examples/network/archivesearch/main.cpp b/examples/network/archivesearch/main.cpp
new file mode 100644
index 0000000..1766470
--- /dev/null
+++ b/examples/network/archivesearch/main.cpp
@@ -0,0 +1,23 @@
+/****************************************************************************
+**
+** Copyright (C) 1992-2008 Trolltech ASA. All rights reserved.
+**
+** This file is part of an example program for Qt. This example
+** program may be used, distributed and modified without limitation.
+**
+*****************************************************************************/
+
+#include "archivedialog.h"
+#include <qapplication.h>
+
+int main(int argc, char **argv)
+{
+ QApplication a( argc, argv );
+ ArchiveDialog ad;
+ ad.show();
+
+ QObject::connect( &a, SIGNAL(lastWindowClosed()),
+ &a, SLOT(quit()) );
+
+ return a.exec();
+}
diff --git a/examples/network/clientserver/client/client.cpp b/examples/network/clientserver/client/client.cpp
new file mode 100644
index 0000000..35cfb98
--- /dev/null
+++ b/examples/network/clientserver/client/client.cpp
@@ -0,0 +1,125 @@
+/****************************************************************************
+**
+** Copyright (C) 1992-2008 Trolltech ASA. All rights reserved.
+**
+** This file is part of an example program for Qt. This example
+** program may be used, distributed and modified without limitation.
+**
+*****************************************************************************/
+
+#include <qsocket.h>
+#include <qapplication.h>
+#include <qvbox.h>
+#include <qhbox.h>
+#include <qtextview.h>
+#include <qlineedit.h>
+#include <qlabel.h>
+#include <qpushbutton.h>
+#include <qtextstream.h>
+
+
+class Client : public QVBox
+{
+ Q_OBJECT
+public:
+ Client( const QString &host, Q_UINT16 port )
+ {
+ // GUI layout
+ infoText = new QTextView( this );
+ QHBox *hb = new QHBox( this );
+ inputText = new QLineEdit( hb );
+ QPushButton *send = new QPushButton( tr("Send") , hb );
+ QPushButton *close = new QPushButton( tr("Close connection") , this );
+ QPushButton *quit = new QPushButton( tr("Quit") , this );
+
+ connect( send, SIGNAL(clicked()), SLOT(sendToServer()) );
+ connect( close, SIGNAL(clicked()), SLOT(closeConnection()) );
+ connect( quit, SIGNAL(clicked()), qApp, SLOT(quit()) );
+
+ // create the socket and connect various of its signals
+ socket = new QSocket( this );
+ connect( socket, SIGNAL(connected()),
+ SLOT(socketConnected()) );
+ connect( socket, SIGNAL(connectionClosed()),
+ SLOT(socketConnectionClosed()) );
+ connect( socket, SIGNAL(readyRead()),
+ SLOT(socketReadyRead()) );
+ connect( socket, SIGNAL(error(int)),
+ SLOT(socketError(int)) );
+
+ // connect to the server
+ infoText->append( tr("Trying to connect to the server\n") );
+ socket->connectToHost( host, port );
+ }
+
+ ~Client()
+ {
+ }
+
+private slots:
+ void closeConnection()
+ {
+ socket->close();
+ if ( socket->state() == QSocket::Closing ) {
+ // We have a delayed close.
+ connect( socket, SIGNAL(delayedCloseFinished()),
+ SLOT(socketClosed()) );
+ } else {
+ // The socket is closed.
+ socketClosed();
+ }
+ }
+
+ void sendToServer()
+ {
+ // write to the server
+ QTextStream os(socket);
+ os << inputText->text() << "\n";
+ inputText->setText( "" );
+ }
+
+ void socketReadyRead()
+ {
+ // read from the server
+ while ( socket->canReadLine() ) {
+ infoText->append( socket->readLine() );
+ }
+ }
+
+ void socketConnected()
+ {
+ infoText->append( tr("Connected to server\n") );
+ }
+
+ void socketConnectionClosed()
+ {
+ infoText->append( tr("Connection closed by the server\n") );
+ }
+
+ void socketClosed()
+ {
+ infoText->append( tr("Connection closed\n") );
+ }
+
+ void socketError( int e )
+ {
+ infoText->append( tr("Error number %1 occurred\n").arg(e) );
+ }
+
+private:
+ QSocket *socket;
+ QTextView *infoText;
+ QLineEdit *inputText;
+};
+
+
+int main( int argc, char** argv )
+{
+ QApplication app( argc, argv );
+ Client client( argc<2 ? "localhost" : argv[1], 4242 );
+ app.setMainWidget( &client );
+ client.show();
+ return app.exec();
+}
+
+#include "client.moc"
diff --git a/examples/network/clientserver/client/client.pro b/examples/network/clientserver/client/client.pro
new file mode 100644
index 0000000..bc3b9e9
--- /dev/null
+++ b/examples/network/clientserver/client/client.pro
@@ -0,0 +1,9 @@
+TEMPLATE = app
+TARGET = client
+
+CONFIG += qt warn_on release
+
+REQUIRES = network full-config
+
+HEADERS =
+SOURCES = client.cpp
diff --git a/examples/network/clientserver/clientserver.doc b/examples/network/clientserver/clientserver.doc
new file mode 100644
index 0000000..67b72a5
--- /dev/null
+++ b/examples/network/clientserver/clientserver.doc
@@ -0,0 +1,35 @@
+/*
+*/
+
+/*! \page clientserver-example.html
+
+ \ingroup network-examples
+
+ \title A small client-server example
+
+ This example shows how two programs can communicate using sockets.
+
+ Two simple example programs are provided, a client program and a
+ server program. Both use the QSocket class, and the server also uses
+ QServerSocket class.
+
+ The server listens on port number 4242 and accepts incoming connections.
+ It sends back every line it receives from the client, prepended with
+ the line number.
+
+ The client tries to connect to the server on the host specified on the
+ command line or to localhost if no command line arguments are
+ specified. You can send single lines to the server.
+
+ <hr>
+
+ Implementation server (server.cpp):
+
+ \include network/clientserver/server/server.cpp
+
+ <hr>
+
+ Implementation client (client.cpp):
+
+ \include network/clientserver/client/client.cpp
+*/
diff --git a/examples/network/clientserver/server/server.cpp b/examples/network/clientserver/server/server.cpp
new file mode 100644
index 0000000..440647c
--- /dev/null
+++ b/examples/network/clientserver/server/server.cpp
@@ -0,0 +1,162 @@
+/****************************************************************************
+**
+** Copyright (C) 1992-2008 Trolltech ASA. All rights reserved.
+**
+** This file is part of an example program for Qt. This example
+** program may be used, distributed and modified without limitation.
+**
+*****************************************************************************/
+
+#include <qsocket.h>
+#include <qserversocket.h>
+#include <qapplication.h>
+#include <qvbox.h>
+#include <qtextview.h>
+#include <qlabel.h>
+#include <qpushbutton.h>
+#include <qtextstream.h>
+
+#include <stdlib.h>
+
+
+/*
+ The ClientSocket class provides a socket that is connected with a client.
+ For every client that connects to the server, the server creates a new
+ instance of this class.
+*/
+class ClientSocket : public QSocket
+{
+ Q_OBJECT
+public:
+ ClientSocket( int sock, QObject *parent=0, const char *name=0 ) :
+ QSocket( parent, name )
+ {
+ line = 0;
+ connect( this, SIGNAL(readyRead()),
+ SLOT(readClient()) );
+ connect( this, SIGNAL(connectionClosed()),
+ SLOT(deleteLater()) );
+ setSocket( sock );
+ }
+
+ ~ClientSocket()
+ {
+ }
+
+signals:
+ void logText( const QString& );
+
+private slots:
+ void readClient()
+ {
+ QTextStream ts( this );
+ while ( canReadLine() ) {
+ QString str = ts.readLine();
+ emit logText( tr("Read: '%1'\n").arg(str) );
+
+ ts << line << ": " << str << endl;
+ emit logText( tr("Wrote: '%1: %2'\n").arg(line).arg(str) );
+
+ line++;
+ }
+ }
+
+private:
+ int line;
+};
+
+
+/*
+ The SimpleServer class handles new connections to the server. For every
+ client that connects, it creates a new ClientSocket -- that instance is now
+ responsible for the communication with that client.
+*/
+class SimpleServer : public QServerSocket
+{
+ Q_OBJECT
+public:
+ SimpleServer( QObject* parent=0 ) :
+ QServerSocket( 4242, 1, parent )
+ {
+ if ( !ok() ) {
+ qWarning("Failed to bind to port 4242");
+ exit(1);
+ }
+ }
+
+ ~SimpleServer()
+ {
+ }
+
+ void newConnection( int socket )
+ {
+ ClientSocket *s = new ClientSocket( socket, this );
+ emit newConnect( s );
+ }
+
+signals:
+ void newConnect( ClientSocket* );
+};
+
+
+/*
+ The ServerInfo class provides a small GUI for the server. It also creates the
+ SimpleServer and as a result the server.
+*/
+class ServerInfo : public QVBox
+{
+ Q_OBJECT
+public:
+ ServerInfo()
+ {
+ SimpleServer *server = new SimpleServer( this );
+
+ QString itext = tr(
+ "This is a small server example.\n"
+ "Connect with the client now."
+ );
+ QLabel *lb = new QLabel( itext, this );
+ lb->setAlignment( AlignHCenter );
+ infoText = new QTextView( this );
+ QPushButton *quit = new QPushButton( tr("Quit") , this );
+
+ connect( server, SIGNAL(newConnect(ClientSocket*)),
+ SLOT(newConnect(ClientSocket*)) );
+ connect( quit, SIGNAL(clicked()), qApp,
+ SLOT(quit()) );
+ }
+
+ ~ServerInfo()
+ {
+ }
+
+private slots:
+ void newConnect( ClientSocket *s )
+ {
+ infoText->append( tr("New connection\n") );
+ connect( s, SIGNAL(logText(const QString&)),
+ infoText, SLOT(append(const QString&)) );
+ connect( s, SIGNAL(connectionClosed()),
+ SLOT(connectionClosed()) );
+ }
+
+ void connectionClosed()
+ {
+ infoText->append( tr("Client closed connection\n") );
+ }
+
+private:
+ QTextView *infoText;
+};
+
+
+int main( int argc, char** argv )
+{
+ QApplication app( argc, argv );
+ ServerInfo info;
+ app.setMainWidget( &info );
+ info.show();
+ return app.exec();
+}
+
+#include "server.moc"
diff --git a/examples/network/clientserver/server/server.pro b/examples/network/clientserver/server/server.pro
new file mode 100644
index 0000000..0a845b5
--- /dev/null
+++ b/examples/network/clientserver/server/server.pro
@@ -0,0 +1,9 @@
+TEMPLATE = app
+TARGET = server
+
+CONFIG += qt warn_on release
+
+REQUIRES = network full-config
+
+HEADERS =
+SOURCES = server.cpp
diff --git a/examples/network/ftpclient/README b/examples/network/ftpclient/README
new file mode 100644
index 0000000..8b1bd7e
--- /dev/null
+++ b/examples/network/ftpclient/README
@@ -0,0 +1,3 @@
+This example is a small ftp client. It shows how to use the QFtp class.
+
+This example needs the network extension.
diff --git a/examples/network/ftpclient/connectdialog.ui b/examples/network/ftpclient/connectdialog.ui
new file mode 100644
index 0000000..1531054
--- /dev/null
+++ b/examples/network/ftpclient/connectdialog.ui
@@ -0,0 +1,244 @@
+<!DOCTYPE UI><UI version="3.0" stdsetdef="1">
+<class>ConnectDialog</class>
+<widget class="QDialog">
+ <property name="name">
+ <cstring>ConnectDialog</cstring>
+ </property>
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>384</width>
+ <height>165</height>
+ </rect>
+ </property>
+ <property name="caption">
+ <string>Choose host to connect to</string>
+ </property>
+ <property name="sizeGripEnabled">
+ <bool>true</bool>
+ </property>
+ <vbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QFrame">
+ <property name="name">
+ <cstring>Frame3</cstring>
+ </property>
+ <property name="frameShape">
+ <enum>StyledPanel</enum>
+ </property>
+ <property name="frameShadow">
+ <enum>Raised</enum>
+ </property>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QLabel" row="0" column="0">
+ <property name="name">
+ <cstring>TextLabel2</cstring>
+ </property>
+ <property name="text">
+ <string>&amp;Remote Host:</string>
+ </property>
+ <property name="buddy" stdset="0">
+ <cstring>host</cstring>
+ </property>
+ </widget>
+ <widget class="QLabel" row="1" column="0">
+ <property name="name">
+ <cstring>TextLabel5</cstring>
+ </property>
+ <property name="text">
+ <string>&amp;Username:</string>
+ </property>
+ <property name="buddy" stdset="0">
+ <cstring>username</cstring>
+ </property>
+ </widget>
+ <widget class="QLabel" row="2" column="0">
+ <property name="name">
+ <cstring>TextLabel6</cstring>
+ </property>
+ <property name="text">
+ <string>&amp;Password:</string>
+ </property>
+ <property name="buddy" stdset="0">
+ <cstring>password</cstring>
+ </property>
+ </widget>
+ <widget class="QLineEdit" row="2" column="1">
+ <property name="name">
+ <cstring>password</cstring>
+ </property>
+ <property name="text">
+ <string></string>
+ </property>
+ <property name="echoMode">
+ <enum>Password</enum>
+ </property>
+ </widget>
+ <widget class="QLineEdit" row="1" column="1">
+ <property name="name">
+ <cstring>username</cstring>
+ </property>
+ <property name="text">
+ <string>anonymous</string>
+ </property>
+ </widget>
+ <widget class="QLayoutWidget" row="0" column="1">
+ <property name="name">
+ <cstring>Layout21</cstring>
+ </property>
+ <hbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QLineEdit">
+ <property name="name">
+ <cstring>host</cstring>
+ </property>
+ </widget>
+ <widget class="QLabel">
+ <property name="name">
+ <cstring>TextLabel3</cstring>
+ </property>
+ <property name="text">
+ <string>P&amp;ort:</string>
+ </property>
+ <property name="buddy" stdset="0">
+ <cstring>port</cstring>
+ </property>
+ </widget>
+ <widget class="QSpinBox">
+ <property name="name">
+ <cstring>port</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>1</hsizetype>
+ <vsizetype>0</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="maxValue">
+ <number>1000</number>
+ </property>
+ <property name="value">
+ <number>21</number>
+ </property>
+ </widget>
+ </hbox>
+ </widget>
+ </grid>
+ </widget>
+ <spacer>
+ <property name="name">
+ <cstring>Spacer5</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Vertical</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Expanding</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>31</width>
+ <height>0</height>
+ </size>
+ </property>
+ </spacer>
+ <widget class="QLayoutWidget">
+ <property name="name">
+ <cstring>Layout1</cstring>
+ </property>
+ <hbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <property name="margin">
+ <number>0</number>
+ </property>
+ <property name="spacing">
+ <number>6</number>
+ </property>
+ <spacer>
+ <property name="name">
+ <cstring>Horizontal Spacing2</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Horizontal</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Expanding</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>0</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ <widget class="QPushButton">
+ <property name="name">
+ <cstring>buttonOk</cstring>
+ </property>
+ <property name="text">
+ <string>OK</string>
+ </property>
+ <property name="accel">
+ <number>0</number>
+ </property>
+ <property name="autoDefault">
+ <bool>true</bool>
+ </property>
+ <property name="default">
+ <bool>true</bool>
+ </property>
+ </widget>
+ <widget class="QPushButton">
+ <property name="name">
+ <cstring>buttonCancel</cstring>
+ </property>
+ <property name="text">
+ <string>Cancel</string>
+ </property>
+ <property name="accel">
+ <number>0</number>
+ </property>
+ <property name="autoDefault">
+ <bool>true</bool>
+ </property>
+ </widget>
+ </hbox>
+ </widget>
+ </vbox>
+</widget>
+<connections>
+ <connection>
+ <sender>buttonOk</sender>
+ <signal>clicked()</signal>
+ <receiver>ConnectDialog</receiver>
+ <slot>accept()</slot>
+ </connection>
+ <connection>
+ <sender>buttonCancel</sender>
+ <signal>clicked()</signal>
+ <receiver>ConnectDialog</receiver>
+ <slot>reject()</slot>
+ </connection>
+</connections>
+<tabstops>
+ <tabstop>host</tabstop>
+ <tabstop>port</tabstop>
+ <tabstop>username</tabstop>
+ <tabstop>password</tabstop>
+ <tabstop>buttonOk</tabstop>
+ <tabstop>buttonCancel</tabstop>
+</tabstops>
+<layoutdefaults spacing="6" margin="11"/>
+</UI>
diff --git a/examples/network/ftpclient/ftpclient.doc b/examples/network/ftpclient/ftpclient.doc
new file mode 100644
index 0000000..13be191
--- /dev/null
+++ b/examples/network/ftpclient/ftpclient.doc
@@ -0,0 +1,24 @@
+/*
+*/
+
+/*! \page ftpclient-example.html
+
+ \ingroup network-examples
+
+ \title An FTP client
+
+ This example implements a FTP client. It uses QFtp to perform its FTP
+ commands. The GUI parts are done in the Designer.
+
+ <hr>
+
+ The implementation of the FTP commands (ftpmainwindow.ui.h):
+
+ \include network/ftpclient/ftpmainwindow.ui.h
+
+ <hr>
+
+ Main (main.cpp):
+
+ \include network/ftpclient/main.cpp
+*/
diff --git a/examples/network/ftpclient/ftpclient.pro b/examples/network/ftpclient/ftpclient.pro
new file mode 100644
index 0000000..eb71f13
--- /dev/null
+++ b/examples/network/ftpclient/ftpclient.pro
@@ -0,0 +1,14 @@
+TEMPLATE = app
+TARGET = ftpclient
+
+CONFIG += qt warn_on release
+
+REQUIRES = network full-config nocrosscompiler
+
+HEADERS = ftpviewitem.h
+SOURCES = main.cpp \
+ ftpviewitem.cpp
+FORMS = ftpmainwindow.ui \
+ connectdialog.ui
+IMAGES = images/file.png \
+ images/folder.png
diff --git a/examples/network/ftpclient/ftpmainwindow.ui b/examples/network/ftpclient/ftpmainwindow.ui
new file mode 100644
index 0000000..6c3ab30
--- /dev/null
+++ b/examples/network/ftpclient/ftpmainwindow.ui
@@ -0,0 +1,280 @@
+<!DOCTYPE UI><UI version="3.0" stdsetdef="1">
+<class>FtpMainWindow</class>
+<widget class="QMainWindow">
+ <property name="name">
+ <cstring>FtpMainWindow</cstring>
+ </property>
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>600</width>
+ <height>480</height>
+ </rect>
+ </property>
+ <property name="caption">
+ <string>Ftp client example</string>
+ </property>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QListView" row="1" column="0" rowspan="1" colspan="2">
+ <column>
+ <property name="text">
+ <string>Name</string>
+ </property>
+ <property name="clickable">
+ <bool>true</bool>
+ </property>
+ <property name="resizable">
+ <bool>true</bool>
+ </property>
+ </column>
+ <column>
+ <property name="text">
+ <string>Size</string>
+ </property>
+ <property name="clickable">
+ <bool>true</bool>
+ </property>
+ <property name="resizable">
+ <bool>true</bool>
+ </property>
+ </column>
+ <column>
+ <property name="text">
+ <string>Last Modified</string>
+ </property>
+ <property name="clickable">
+ <bool>true</bool>
+ </property>
+ <property name="resizable">
+ <bool>true</bool>
+ </property>
+ </column>
+ <property name="name">
+ <cstring>remoteView</cstring>
+ </property>
+ <property name="showSortIndicator">
+ <bool>true</bool>
+ </property>
+ </widget>
+ <widget class="QComboBox" row="0" column="1">
+ <property name="name">
+ <cstring>remotePath</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>7</hsizetype>
+ <vsizetype>0</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="editable">
+ <bool>true</bool>
+ </property>
+ <property name="duplicatesEnabled">
+ <bool>false</bool>
+ </property>
+ </widget>
+ <widget class="QLabel" row="0" column="0">
+ <property name="name">
+ <cstring>TextLabel4</cstring>
+ </property>
+ <property name="text">
+ <string>&amp;Remote Path:</string>
+ </property>
+ <property name="buddy" stdset="0">
+ <cstring>remotePath</cstring>
+ </property>
+ </widget>
+ </grid>
+</widget>
+<menubar>
+ <property name="name">
+ <cstring>menubar</cstring>
+ </property>
+ <item text="&amp;File" name="fileMenu">
+ <action name="fileConnectAction"/>
+ <action name="fileDownloadAction"/>
+ <action name="fileUploadAction"/>
+ <action name="fileRemoveAction"/>
+ <separator/>
+ <action name="fileExitAction"/>
+ </item>
+</menubar>
+<toolbars>
+ <toolbar dock="2">
+ <property name="name">
+ <cstring>toolBar</cstring>
+ </property>
+ <property name="label">
+ <string>Tools</string>
+ </property>
+ <action name="fileConnectAction"/>
+ <action name="fileDownloadAction"/>
+ <action name="fileUploadAction"/>
+ <action name="fileRemoveAction"/>
+ </toolbar>
+</toolbars>
+<actions>
+ <action>
+ <property name="name">
+ <cstring>fileDownloadAction</cstring>
+ </property>
+ <property name="iconSet">
+ <iconset>image0</iconset>
+ </property>
+ <property name="text">
+ <string>Download...</string>
+ </property>
+ <property name="accel">
+ <number>0</number>
+ </property>
+ </action>
+ <action>
+ <property name="name">
+ <cstring>fileExitAction</cstring>
+ </property>
+ <property name="text">
+ <string>Exit</string>
+ </property>
+ <property name="menuText">
+ <string>E&amp;xit</string>
+ </property>
+ <property name="accel">
+ <number>0</number>
+ </property>
+ </action>
+ <action>
+ <property name="name">
+ <cstring>fileRemoveAction</cstring>
+ </property>
+ <property name="iconSet">
+ <iconset>image1</iconset>
+ </property>
+ <property name="text">
+ <string>Remove</string>
+ </property>
+ </action>
+ <action>
+ <property name="name">
+ <cstring>fileUploadAction</cstring>
+ </property>
+ <property name="iconSet">
+ <iconset>image2</iconset>
+ </property>
+ <property name="text">
+ <string>Upload...</string>
+ </property>
+ </action>
+ <action>
+ <property name="name">
+ <cstring>fileConnectAction</cstring>
+ </property>
+ <property name="iconSet">
+ <iconset>image3</iconset>
+ </property>
+ <property name="text">
+ <string>Connect...</string>
+ </property>
+ </action>
+</actions>
+<images>
+ <image name="image0">
+ <data format="XPM.GZ" length="2477">789c95944953e3301046eff9152e74a3a61ac79bec9a9a03fbbeef4ccdc1926d92400224619d9aff3eeaafc719b640f02387477f96a5b6e49969ef6467d39b9e690c86f9b06d3ddbcafbde7471dbed3efefcf5e377632a083cf797265e30f5ad31b53bf4acb775d52b594839513e2ef86ced710a9faf3d95fa8e7814c621fc066e7c2379056ffa0cea47f066e06b83fa101e30a8afc1331d86325e0c370c7c573cd4b1c5fd863df019d41378c4c0f7e186819f8f1cf7530eaf18789f3df4433f8d313eea61938177e1b8e0182fd40ceedf80e74191c8789138833c8d5ce6b3557b22be5d7b26ebd770cbc0176a97feab01bc60e0d7f08a417ee491f4678e9ddb13a33fcac271a17e0ad78e0ceec35306f9367b1c30a81f8c5ce6b72e9e04f27cd582270cea4db8d6718c7e29ecb73865e05770c3209fc12d030fd993c821e3219f6807fa4b67f08c81a33f3ad56926ebc77c74c9c05378c5c003f634303a95f59dc04387f4a782733be47d3f8d5ccec761edb9e457e0b943d6730caff2dcc8fc57d9315d99ff235c3b24ff00b70e995f092fb332c77ea465f6dc77c8f37af0cc21fd5a849bdc5899ef12dc3a64bc7b78e1102fe0a5431cfbc3440cbc3b729c0fba835b07f61fe13c9a8a81ef8997612a7ec96e7d067e010f18bc7fa9470cead86f78fd721ed17f5b31a8dfb2171103c7f7a4c81c72de3af08a411d5e860c7c13aead95f5a99e380347bf4b6e38f693c27cf1b990f9e27b5165bef6258ffe55b8e4e33a39e3f3a46a26c9534e862c15545245e713e45bd4a60e5dd02575a94757742dcf199bbfa13e0d6848b77447f7f4408ff4c4778ccdcfd21ccdd3022dd2122dd38afbad7e925fa375daa0cd09f35bb44d3bb44b7b13e6f7e9800ee9888e913f71e9d30fd7abe88c7c6a52e03a1a5244f1cb7ebe7d3b9490a69432f72fa572655ee6955585a354953a7ffe14d552ede76ff855bea32ed4a5ea7ebe7ffee57bea4a5dab9bd729d51f937733a28e1a7c21cfd8d7a949f2aa5fa7fea7c7e7395df3c17adf1dffdd3cdf51f366d66ff393f2e5fc9fef8dbfa8437f7d</data>
+ </image>
+ <image name="image1">
+ <data format="XPM.GZ" length="721">789ca590c10ac2300c86ef7b8ab2de866c3a0f1ec447503c0ae2214d237a5041e741c477b749376d3bf5e29f16fae7234d4855a8d572ae8a2abb34d0ec51e10eceaab0d7c3e1b6deccee595ed7ca9d891ae5832c2f15aac5e948fcd6eead8722b6c4d68c39d85ab196832db2b5c4c116d81275b586ed56245d3eea3fa25bc504004a6d44a8e31a87003d318c20f8ad43961140d4c733eb5a31080909b28802428224cc5d9d10d79d1100f5894101a64f240fd023922757863169f3c6503cc12befc748f6e6b72363f467f3a274076f2524d47752fe268f69f604fb43a540</data>
+ </image>
+ <image name="image2">
+ <data format="XPM.GZ" length="2461">789cd594496fdb301046effe1542780b8a89ac8d128a1eb22fcdbe27450f1425c58e633b5eb216fdefe57c1319718bd6ceb17af1e1851fa5e190d2d2a27779b8e72d2e354663336e5bcfb6ccd05b2c1ebadd976fdfbffc682c0481e7fed2d80b163e35168ec69ef5f6fbbd92859413e5e3822fd71ea7f0d5da53193f148fc238645703f6a6cf60fc1cde0c7c9d637c040f188cefc0331d86984f313c67e047e2a18e2de6e7ec81cf603c81470cfc049e33f0d6c4319f647ec5c087eca11ffa698cfb1b78938177e1b8e03770cd60fe2edc044522f78bc419e469e252cf7eed89f841ed99ac5fc32d035fab5dfaada4de8281dfc32b06f941ed91f467859ddb13a33fcac27161fc0aae1d19dc87a70cf26df63860307e3a71a9efab7812c8f315fa1d270cc69b70ade318fd52385f71cac0fbf09c413e835b061eb2279143ee87f526da81fed2353c63e0385f3ad56926eb47fdba64e029bc62e0017b1ae43a95f55dc24387f407fb8d76c87ebf4e5cde87b3da8de4b7e0c621ebb98057c6e452ff363bca95fa5fe0da21f967b875487d15bccc4a83f3489becc677c8f3d03f9339a45febf0dce456eadd805b87dcef095e38c44b78e9102fd8f38881f7268ef7831ee1d681f347384f79c5c08fc5cb3015c7fb637d067e070f18ecbf78c460fc168e038071acdf560cc61fd88b88818fe19943de37cc2f2a06e31df63264e07b706dadac4ff5c41938fa5172c3719e14e6e37321e703df872af3b52f79f4abc2251fd3f9f97b9e54cdac3c19f7cbc9524125557443ad5979479b6ea94377d4a51ef5e99e06f29ce93c9235431ad1981ee8919ee8995ee89567bccf731d9359cbb442abb446ebb4419bb4e57edbd3f93afd56ff32edd057daa5bdd979d83e1dd0211dd1f19cf9133aa5333aa70be42f5dfaea5ffd777dbf269f9a14b88e8614513cddcf3f778712d29452e6fea59451f9745e5955384a55a99bf74f512dd57ebfc3bfe56f5547dda9eeecf3f396efa9beba5783b9f3ae22eaa8e107f28cfd0ff32337a366343b3f2f1fcefffcdcf80560e77be9</data>
+ </image>
+ <image name="image3">
+ <data format="XPM.GZ" length="2878">789c8d95476fe4381085effe150dd7cd58d44854c6600fce394ff0cc620f2425b5533bb4dba1bdd8ff3eac57526381757bac671bf8c0c7122b88feb434383bda1f2c7d5a7898d8c9851ff8733b1e2cd58fa3d1f4afbffffc6761d19841f889e3786016ff58583c9e0cfce0e0f6a611600a40111e611af56c4aacaff45ceafab372e2335ddf574e932c01df835de4749d74bf8b6d5181c7c2e12c69a1fe536513150eeb4fe032c9330f46bcb88aab22833f063b11f84039293aff2ab83565a9f14b611389b07e39630b7e04db2c4d359f23b013818733d6f8ebe0dad4899ec7825b11d65f84932828c6fab8e752fd053816c18ffc1323c27a35639c9f182c4f0a46be499a651def823311f8109c8b106f076c4d9de37c1c298bc0d98c35dfbd9e2b7dff96729176f537602f02aff6acf3c177e0366953ad37e6233522b00327411aef1b38844f311ffc1d5c8ae05f06573649753ed09fd48ac027c2592c02a31f991121def18cf5bcdbcab949b45f0f1d575a0f42fe28a7e6bf0196a700e37bc97211e29d818ba25be71c5c8ac029d88bb01ff5c99acc74f5d5f3b4595beafe9fc2791aa4f16fc145909e0ffdccad088cfcf25604f63d179a3ff22bcaa2acb41f9be02a48eb710e6e44e004dc8ac03f844be38a52e37d052741983f6ec1d22e3dffeb8cb57f6b3d57fabe939eadeec7794a1ba4f3f705dc5aeb903f217e150569bd6ec02648f7633eab3c48e7790a9604755eaec06590f274c67a1e7caf950fd2fa0d7bb63acf0db8a91aabdf33e6c14641fa7e9cc75641dadf1a2c4f8d75e46f9d755eeb83fbc3fa20ad2fee535b0729ebfe264819fd74a9083c9ab17eef389fcb83743ed14f272fd47ae23e753e48cf83efcfb522f0a1729394cad7c23e1281513f6f44e00b30061aef9b8043f619e687743f0a08567f2d02633e7cebdb5aef03cc771d05697cdcc7752a02237e5d05697f717f3789088cfbaf29bcefea83fba20d4f55ea3fbb8f6bbe9fa9d747fc6cd9b1e79a1b6e79f801ff395ff0255ff1358ff8866ff94edf33d77fcf637ee0093ff2133ff30b4ff95576ccf52f07adf02aaff13a6ff066f8dd9aef879b789b7778f7f7fecebdc7fb7cc087bff377ee233ee6133ee52ff07f0dee6f6fe70bbfea3b9ff18f50d19f1c713caf9e5d97c46f38e19433ceb9e0f22d3f57c4c165f44cb2373cf6bf1deefd61c591a79a9ad0a1ce3d7f7e78482d0de99c1d5da89b2ee7fbb90a1578a12b5ea76b44275ea1d1fb7ebaa29bf0f796eee89ec6f4f061ff841ee9899edff3d30b4d3bff2b2dd30aadd21aadbf976fa8cd066d22fe166dd30eedbeed9ed587688ff6c9f1331d840e257d77e6f9b1e3908ed8d0319dccabfdfffb4ba7f39d9dffdfcf0bbf00b514c1b3</data>
+ </image>
+</images>
+<connections>
+ <connection>
+ <sender>fileExitAction</sender>
+ <signal>activated()</signal>
+ <receiver>FtpMainWindow</receiver>
+ <slot>close()</slot>
+ </connection>
+ <connection>
+ <sender>fileDownloadAction</sender>
+ <signal>activated()</signal>
+ <receiver>FtpMainWindow</receiver>
+ <slot>downloadFile()</slot>
+ </connection>
+ <connection>
+ <sender>fileRemoveAction</sender>
+ <signal>activated()</signal>
+ <receiver>FtpMainWindow</receiver>
+ <slot>removeFile()</slot>
+ </connection>
+ <connection>
+ <sender>fileUploadAction</sender>
+ <signal>activated()</signal>
+ <receiver>FtpMainWindow</receiver>
+ <slot>uploadFile()</slot>
+ </connection>
+ <connection>
+ <sender>fileConnectAction</sender>
+ <signal>activated()</signal>
+ <receiver>FtpMainWindow</receiver>
+ <slot>connectToHost()</slot>
+ </connection>
+ <connection>
+ <sender>remotePath</sender>
+ <signal>activated(const QString&amp;)</signal>
+ <receiver>FtpMainWindow</receiver>
+ <slot>changePath(const QString&amp;)</slot>
+ </connection>
+ <connection>
+ <sender>remoteView</sender>
+ <signal>doubleClicked(QListViewItem*)</signal>
+ <receiver>FtpMainWindow</receiver>
+ <slot>changePathOrDownload(QListViewItem*)</slot>
+ </connection>
+ <connection>
+ <sender>remoteView</sender>
+ <signal>returnPressed(QListViewItem*)</signal>
+ <receiver>FtpMainWindow</receiver>
+ <slot>changePathOrDownload(QListViewItem*)</slot>
+ </connection>
+</connections>
+<includes>
+ <include location="local" impldecl="in implementation">ftpmainwindow.ui.h</include>
+</includes>
+<forwards>
+ <forward>class QFtp;</forward>
+ <forward>class QUrlInfo;</forward>
+</forwards>
+<variables>
+ <variable access="private">QFtp *ftp</variable>
+ <variable access="private">QLabel *stateFtp</variable>
+ <variable access="private">QString currentFtpDir</variable>
+</variables>
+<slots>
+ <slot access="public">connectToHost()</slot>
+ <slot access="private">uploadFile()</slot>
+ <slot access="private">downloadFile()</slot>
+ <slot access="private">removeFile()</slot>
+ <slot access="private">changePath( const QString &amp; newPath )</slot>
+ <slot access="private">ftp_commandStarted()</slot>
+ <slot access="private">ftp_commandFinished()</slot>
+ <slot access="private">ftp_done( bool error )</slot>
+ <slot access="private">ftp_stateChanged( int state )</slot>
+ <slot access="private">ftp_listInfo( const QUrlInfo &amp; i )</slot>
+ <slot access="private">ftp_rawCommandReply( int code, const QString &amp; text )</slot>
+ <slot access="private">changePathOrDownload( QListViewItem * )</slot>
+</slots>
+<functions>
+ <function access="private">init()</function>
+ <function access="private">destroy()</function>
+</functions>
+<layoutdefaults spacing="6" margin="11"/>
+</UI>
diff --git a/examples/network/ftpclient/ftpmainwindow.ui.h b/examples/network/ftpclient/ftpmainwindow.ui.h
new file mode 100644
index 0000000..2feeb5a
--- /dev/null
+++ b/examples/network/ftpclient/ftpmainwindow.ui.h
@@ -0,0 +1,273 @@
+/****************************************************************************
+**
+** Copyright (C) 1992-2008 Trolltech ASA. All rights reserved.
+**
+** This file is part of an example program for Qt. This example
+** program may be used, distributed and modified without limitation.
+**
+*****************************************************************************/
+
+/****************************************************************************
+**
+** ui.h extension file, included from the uic-generated form implementation.
+**
+** The init() function is used in place of a constructor.
+** The destroy() function is used in place of a destructor.
+** The slots uploadFile(), downloadFile(), removeFile() and connectToHost() are
+** connected with the resp. actions of the GUI.
+**
+*****************************************************************************/
+
+#include <qftp.h>
+#include <qlineedit.h>
+#include <qspinbox.h>
+#include <qstatusbar.h>
+#include <qmessagebox.h>
+#include <qfiledialog.h>
+#include <qprogressdialog.h>
+#include <qapplication.h>
+
+#include "connectdialog.h"
+#include "ftpviewitem.h"
+
+void FtpMainWindow::init()
+{
+ stateFtp = new QLabel( tr("Unconnected"), statusBar() );
+ statusBar()->addWidget( stateFtp, 0, TRUE );
+
+ ftp = new QFtp( this );
+ connect( ftp, SIGNAL(commandStarted(int)),
+ SLOT(ftp_commandStarted()) );
+ connect( ftp, SIGNAL(commandFinished(int,bool)),
+ SLOT(ftp_commandFinished()) );
+ connect( ftp, SIGNAL(done(bool)),
+ SLOT(ftp_done(bool)) );
+ connect( ftp, SIGNAL(stateChanged(int)),
+ SLOT(ftp_stateChanged(int)) );
+ connect( ftp, SIGNAL(listInfo(const QUrlInfo &)),
+ SLOT(ftp_listInfo(const QUrlInfo &)) );
+ connect( ftp, SIGNAL(rawCommandReply(int, const QString &)),
+ SLOT(ftp_rawCommandReply(int, const QString &)) );
+}
+
+void FtpMainWindow::destroy()
+{
+ if ( ftp->state() != QFtp::Unconnected )
+ ftp->close();
+}
+
+void FtpMainWindow::uploadFile()
+{
+ QString fileName = QFileDialog::getOpenFileName(
+ QString::null,
+ QString::null,
+ this,
+ "upload file dialog",
+ tr("Choose a file to upload") );
+ if ( fileName.isNull() )
+ return;
+
+ QFile *file = new QFile( fileName );
+ if ( !file->open( IO_ReadOnly ) ) {
+ QMessageBox::critical( this, tr("Upload error"),
+ tr("Can't open file '%1' for reading.").arg(fileName) );
+ delete file;
+ return;
+ }
+
+ QProgressDialog progress(
+ tr("Uploading file..."),
+ tr("Cancel"),
+ 0,
+ this,
+ "upload progress dialog",
+ TRUE );
+ connect( ftp, SIGNAL(dataTransferProgress(int,int)),
+ &progress, SLOT(setProgress(int,int)) );
+ connect( ftp, SIGNAL(commandFinished(int,bool)),
+ &progress, SLOT(reset()) );
+ connect( &progress, SIGNAL(cancelled()),
+ ftp, SLOT(abort()) );
+
+ QFileInfo fi( fileName );
+ ftp->put( file, fi.fileName() );
+ progress.exec(); // ### takes a lot of time!!!
+
+ ftp->list();
+}
+
+void FtpMainWindow::downloadFile()
+{
+ FtpViewItem *item = (FtpViewItem*)remoteView->selectedItem();
+ if ( !item || item->isDir() )
+ return;
+
+ QString fileName = QFileDialog::getSaveFileName(
+ item->text(0),
+ QString::null,
+ this,
+ "download file dialog",
+ tr("Save downloaded file as") );
+ if ( fileName.isNull() )
+ return;
+
+ // create file on the heap because it has to be valid throughout the whole
+ // asynchronous download operation
+ QFile *file = new QFile( fileName );
+ if ( !file->open( IO_WriteOnly ) ) {
+ QMessageBox::critical( this, tr("Download error"),
+ tr("Can't open file '%1' for writing.").arg(fileName) );
+ delete file;
+ return;
+ }
+
+ QProgressDialog progress(
+ tr("Downloading file..."),
+ tr("Cancel"),
+ 0,
+ this,
+ "download progress dialog",
+ TRUE );
+ connect( ftp, SIGNAL(dataTransferProgress(int,int)),
+ &progress, SLOT(setProgress(int,int)) );
+ connect( ftp, SIGNAL(commandFinished(int,bool)),
+ &progress, SLOT(reset()) );
+ connect( &progress, SIGNAL(cancelled()),
+ ftp, SLOT(abort()) );
+
+ ftp->get( item->text(0), file );
+ progress.exec(); // ### takes a lot of time!!!
+}
+
+void FtpMainWindow::removeFile()
+{
+ FtpViewItem *item = (FtpViewItem*)remoteView->selectedItem();
+ if ( !item || item->isDir() )
+ return;
+
+ ftp->remove( item->text(0) );
+ ftp->list();
+}
+
+void FtpMainWindow::connectToHost()
+{
+ ConnectDialog connectDialog;
+ if ( connectDialog.exec() == QDialog::Rejected )
+ return;
+
+ remotePath->clear();
+ remoteView->clear();
+
+ if ( ftp->state() != QFtp::Unconnected )
+ ftp->close();
+
+ ftp->connectToHost( connectDialog.host->text(), connectDialog.port->value() );
+ ftp->login( connectDialog.username->text(), connectDialog.password->text() );
+ ftp->rawCommand( "PWD" );
+ ftp->list();
+}
+
+// This slot is connected to the QComboBox::activated() signal of the
+// remotePath.
+void FtpMainWindow::changePath( const QString &newPath )
+{
+ ftp->cd( newPath );
+ ftp->rawCommand( "PWD" );
+ ftp->list();
+}
+
+// This slot is connected to the QListView::doubleClicked() and
+// QListView::returnPressed() signals of the remoteView.
+void FtpMainWindow::changePathOrDownload( QListViewItem *item )
+{
+ if ( ((FtpViewItem*)item)->isDir() )
+ changePath( item->text(0) );
+ else
+ downloadFile();
+}
+
+/****************************************************************************
+**
+** Slots connected to signals of the QFtp class
+**
+*****************************************************************************/
+
+void FtpMainWindow::ftp_commandStarted()
+{
+ QApplication::setOverrideCursor( QCursor(Qt::WaitCursor) );
+ if ( ftp->currentCommand() == QFtp::List ) {
+ remoteView->clear();
+ if ( currentFtpDir != "/" )
+ new FtpViewItem( remoteView, FtpViewItem::Directory, "..", "", "" );
+ }
+}
+
+void FtpMainWindow::ftp_commandFinished()
+{
+ QApplication::restoreOverrideCursor();
+ delete ftp->currentDevice();
+}
+
+void FtpMainWindow::ftp_done( bool error )
+{
+ if ( error ) {
+ QMessageBox::critical( this, tr("FTP Error"), ftp->errorString() );
+
+ // If we are connected, but not logged in, it is not meaningful to stay
+ // connected to the server since the error is a really fatal one (login
+ // failed).
+ if ( ftp->state() == QFtp::Connected )
+ ftp->close();
+ }
+}
+
+void FtpMainWindow::ftp_stateChanged( int state )
+{
+ switch ( (QFtp::State)state ) {
+ case QFtp::Unconnected:
+ stateFtp->setText( tr("Unconnected") );
+ break;
+ case QFtp::HostLookup:
+ stateFtp->setText( tr("Host lookup") );
+ break;
+ case QFtp::Connecting:
+ stateFtp->setText( tr("Connecting") );
+ break;
+ case QFtp::Connected:
+ stateFtp->setText( tr("Connected") );
+ break;
+ case QFtp::LoggedIn:
+ stateFtp->setText( tr("Logged in") );
+ break;
+ case QFtp::Closing:
+ stateFtp->setText( tr("Closing") );
+ break;
+ }
+}
+
+void FtpMainWindow::ftp_listInfo( const QUrlInfo &i )
+{
+ FtpViewItem::Type type;
+ if ( i.isDir() )
+ type = FtpViewItem::Directory;
+ else
+ type = FtpViewItem::File;
+
+ new FtpViewItem( remoteView, type,
+ i.name(), QString::number(i.size()), i.lastModified().toString() );
+}
+
+void FtpMainWindow::ftp_rawCommandReply( int code, const QString &text )
+{
+ if ( code == 257 ) {
+ currentFtpDir = text.section( '"', 1, 1 );
+
+ for ( int i = 0; i<remotePath->count(); i++ ) {
+ // make sure that we don't insert duplicates
+ if ( remotePath->text( i ) == currentFtpDir )
+ remotePath->removeItem( i );
+ }
+ remotePath->insertItem( currentFtpDir, 0 );
+ remotePath->setCurrentItem( 0 );
+ }
+}
diff --git a/examples/network/ftpclient/ftpviewitem.cpp b/examples/network/ftpclient/ftpviewitem.cpp
new file mode 100644
index 0000000..bb5d689
--- /dev/null
+++ b/examples/network/ftpclient/ftpviewitem.cpp
@@ -0,0 +1,58 @@
+/****************************************************************************
+**
+** Copyright (C) 1992-2008 Trolltech ASA. All rights reserved.
+**
+** This file is part of an example program for Qt. This example
+** program may be used, distributed and modified without limitation.
+**
+*****************************************************************************/
+
+#include <qpixmap.h>
+
+#include "ftpviewitem.h"
+
+
+FtpViewItem::FtpViewItem( QListView *parent, Type t, const QString &name, const QString &size, const QString &lastModified )
+ : QListViewItem(parent,name,size,lastModified), type(t)
+{
+ // the pixmaps for folders and files are in an image collection
+ if ( type == Directory )
+ setPixmap( 0, QPixmap::fromMimeSource( "folder.png" ) );
+ else
+ setPixmap( 0, QPixmap::fromMimeSource( "file.png" ) );
+}
+
+int FtpViewItem::compare( QListViewItem * i, int col, bool ascending ) const
+{
+ // The entry ".." is always the first one.
+ if ( text(0) == ".." ) {
+ if ( ascending )
+ return -1;
+ else
+ return 1;
+ }
+ if ( i->text(0) == ".." ) {
+ if ( ascending )
+ return 1;
+ else
+ return -1;
+ }
+
+ // Directories are before files.
+ if ( type != ((FtpViewItem*)i)->type ) {
+ if ( type == Directory ) {
+ if ( ascending )
+ return -1;
+ else
+ return 1;
+ } else {
+ if ( ascending )
+ return 1;
+ else
+ return -1;
+ }
+ }
+
+ // Use default sorting otherwise.
+ return QListViewItem::compare( i, col, ascending );
+}
diff --git a/examples/network/ftpclient/ftpviewitem.h b/examples/network/ftpclient/ftpviewitem.h
new file mode 100644
index 0000000..4ea931d
--- /dev/null
+++ b/examples/network/ftpclient/ftpviewitem.h
@@ -0,0 +1,35 @@
+/****************************************************************************
+**
+** Copyright (C) 1992-2008 Trolltech ASA. All rights reserved.
+**
+** This file is part of an example program for Qt. This example
+** program may be used, distributed and modified without limitation.
+**
+*****************************************************************************/
+
+#ifndef FTPVIEWITEM_H
+#define FTPVIEWITEM_H
+
+#include <qlistview.h>
+#include <qdatetime.h>
+
+class FtpViewItem : public QListViewItem
+{
+public:
+ enum Type {
+ Directory,
+ File
+ };
+
+ FtpViewItem( QListView *parent, Type t, const QString &name, const QString &size, const QString &lastModified );
+
+ int compare( QListViewItem * i, int col, bool ascending ) const;
+
+ bool isDir()
+ { return type==Directory; }
+
+private:
+ Type type;
+};
+
+#endif
diff --git a/examples/network/ftpclient/images/file.png b/examples/network/ftpclient/images/file.png
new file mode 100644
index 0000000..f042c91
--- /dev/null
+++ b/examples/network/ftpclient/images/file.png
Binary files differ
diff --git a/examples/network/ftpclient/images/folder.png b/examples/network/ftpclient/images/folder.png
new file mode 100644
index 0000000..5fd0a43
--- /dev/null
+++ b/examples/network/ftpclient/images/folder.png
Binary files differ
diff --git a/examples/network/ftpclient/main.cpp b/examples/network/ftpclient/main.cpp
new file mode 100644
index 0000000..abd6e89
--- /dev/null
+++ b/examples/network/ftpclient/main.cpp
@@ -0,0 +1,23 @@
+/****************************************************************************
+**
+** Copyright (C) 1992-2008 Trolltech ASA. All rights reserved.
+**
+** This file is part of an example program for Qt. This example
+** program may be used, distributed and modified without limitation.
+**
+*****************************************************************************/
+
+#include <qapplication.h>
+#include "ftpmainwindow.h"
+
+int main( int argc, char **argv )
+{
+ QApplication a( argc, argv );
+
+ FtpMainWindow m;
+ a.setMainWidget( &m );
+ m.show();
+ a.processEvents();
+ m.connectToHost();
+ return a.exec();
+}
diff --git a/examples/network/httpd/README b/examples/network/httpd/README
new file mode 100644
index 0000000..dc7229d
--- /dev/null
+++ b/examples/network/httpd/README
@@ -0,0 +1,7 @@
+This is an example for the QServerSocket class which is included in the
+network module.
+
+It is a simple http daemon. After starting it you can connect to port
+8080 with a web browser and an html page is shown. The program does
+not really parse the http request; so it is not of much use except for
+being a small example for QServerSocket.
diff --git a/examples/network/httpd/httpd.cpp b/examples/network/httpd/httpd.cpp
new file mode 100644
index 0000000..4c40961
--- /dev/null
+++ b/examples/network/httpd/httpd.cpp
@@ -0,0 +1,141 @@
+/****************************************************************************
+**
+** Copyright (C) 1992-2008 Trolltech ASA. All rights reserved.
+**
+** This file is part of an example program for Qt. This example
+** program may be used, distributed and modified without limitation.
+**
+*****************************************************************************/
+#include <stdlib.h>
+#include <qsocket.h>
+#include <qregexp.h>
+#include <qserversocket.h>
+#include <qapplication.h>
+#include <qmainwindow.h>
+#include <qtextstream.h>
+#include <qvbox.h>
+#include <qlabel.h>
+#include <qtextview.h>
+#include <qpushbutton.h>
+
+// HttpDaemon is the the class that implements the simple HTTP server.
+class HttpDaemon : public QServerSocket
+{
+ Q_OBJECT
+public:
+ HttpDaemon( QObject* parent=0 ) :
+ QServerSocket(8080,1,parent)
+ {
+ if ( !ok() ) {
+ qWarning("Failed to bind to port 8080");
+ exit( 1 );
+ }
+ }
+
+ void newConnection( int socket )
+ {
+ // When a new client connects, the server constructs a QSocket and all
+ // communication with the client is done over this QSocket. QSocket
+ // works asynchronouslyl, this means that all the communication is done
+ // in the two slots readClient() and discardClient().
+ QSocket* s = new QSocket( this );
+ connect( s, SIGNAL(readyRead()), this, SLOT(readClient()) );
+ connect( s, SIGNAL(delayedCloseFinished()), this, SLOT(discardClient()) );
+ s->setSocket( socket );
+ emit newConnect();
+ }
+
+signals:
+ void newConnect();
+ void endConnect();
+ void wroteToClient();
+
+private slots:
+ void readClient()
+ {
+ // This slot is called when the client sent data to the server. The
+ // server looks if it was a get request and sends a very simple HTML
+ // document back.
+ QSocket* socket = (QSocket*)sender();
+ if ( socket->canReadLine() ) {
+ QStringList tokens = QStringList::split( QRegExp("[ \r\n][ \r\n]*"), socket->readLine() );
+ if ( tokens[0] == "GET" ) {
+ QTextStream os( socket );
+ os.setEncoding( QTextStream::UnicodeUTF8 );
+ os << "HTTP/1.0 200 Ok\r\n"
+ "Content-Type: text/html; charset=\"utf-8\"\r\n"
+ "\r\n"
+ "<h1>Nothing to see here</h1>\n";
+ socket->close();
+ emit wroteToClient();
+ }
+ }
+ }
+ void discardClient()
+ {
+ QSocket* socket = (QSocket*)sender();
+ delete socket;
+ emit endConnect();
+ }
+};
+
+
+// HttpInfo provides a simple graphical user interface to the server and shows
+// the actions of the server.
+class HttpInfo : public QVBox
+{
+ Q_OBJECT
+public:
+ HttpInfo()
+ {
+ HttpDaemon *httpd = new HttpDaemon( this );
+
+ QString itext = QString(
+ "This is a small httpd example.\n"
+ "You can connect with your\n"
+ "web browser to port %1"
+ ).arg( httpd->port() );
+ QLabel *lb = new QLabel( itext, this );
+ lb->setAlignment( AlignHCenter );
+ infoText = new QTextView( this );
+ QPushButton *quit = new QPushButton( "quit" , this );
+
+ connect( httpd, SIGNAL(newConnect()), SLOT(newConnect()) );
+ connect( httpd, SIGNAL(endConnect()), SLOT(endConnect()) );
+ connect( httpd, SIGNAL(wroteToClient()), SLOT(wroteToClient()) );
+ connect( quit, SIGNAL(pressed()), qApp, SLOT(quit()) );
+ }
+
+ ~HttpInfo()
+ {
+ }
+
+private slots:
+ void newConnect()
+ {
+ infoText->append( "New connection" );
+ }
+ void endConnect()
+ {
+ infoText->append( "Connection closed\n\n" );
+ }
+ void wroteToClient()
+ {
+ infoText->append( "Wrote to client" );
+ }
+
+private:
+ QTextView *infoText;
+};
+
+
+int main( int argc, char** argv )
+{
+ QApplication app( argc, argv );
+ HttpInfo info;
+ app.setMainWidget( &info );
+ info.show();
+ return app.exec();
+}
+
+#include "httpd.moc"
diff --git a/examples/network/httpd/httpd.doc b/examples/network/httpd/httpd.doc
new file mode 100644
index 0000000..de1e0be
--- /dev/null
+++ b/examples/network/httpd/httpd.doc
@@ -0,0 +1,20 @@
+/*
+*/
+
+/*! \page httpd-example.html
+
+ \ingroup network-examples
+
+ \title A simple HTTP daemon
+
+ This example shows how to use the QServerSocket class. It is a very
+ simple implementation of a HTTP daemon that listens on port 8080 and
+ sends back a simple HTML page back for every GET request it gets. After
+ sending the page, it closes the connection.
+
+ <hr>
+
+ Implementation (httpd.cpp):
+
+ \include network/httpd/httpd.cpp
+*/
diff --git a/examples/network/httpd/httpd.pro b/examples/network/httpd/httpd.pro
new file mode 100644
index 0000000..a364499
--- /dev/null
+++ b/examples/network/httpd/httpd.pro
@@ -0,0 +1,9 @@
+TEMPLATE = app
+TARGET = httpd
+
+CONFIG += qt warn_on release
+
+REQUIRES = network large-config
+
+HEADERS =
+SOURCES = httpd.cpp
diff --git a/examples/network/infoprotocol/infoclient/client.cpp b/examples/network/infoprotocol/infoclient/client.cpp
new file mode 100644
index 0000000..89bcfd2
--- /dev/null
+++ b/examples/network/infoprotocol/infoclient/client.cpp
@@ -0,0 +1,120 @@
+/****************************************************************************
+**
+** Copyright (C) 1992-2008 Trolltech ASA. All rights reserved.
+**
+** This file is part of an example program for Qt. This example
+** program may be used, distributed and modified without limitation.
+**
+*****************************************************************************/
+
+#include <qsocket.h>
+#include <qapplication.h>
+#include <qtextedit.h>
+#include <qlineedit.h>
+#include <qlabel.h>
+#include <qpushbutton.h>
+#include <qtextstream.h>
+#include <qlistbox.h>
+
+#include "client.h"
+
+
+ClientInfo::ClientInfo( QWidget *parent, const char *name ) :
+ ClientInfoBase( parent, name ), socket( 0 )
+{
+ edHost->setText( "localhost" );
+ edPort->setText( QString::number( (uint)infoPort ) );
+
+ connect( infoList, SIGNAL(selected(const QString&)), SLOT(selectItem(const QString&)) );
+ connect( btnConnect, SIGNAL(clicked()), SLOT(connectToServer()) );
+ connect( btnBack, SIGNAL(clicked()), SLOT(stepBack()) );
+ connect( btnQuit, SIGNAL(clicked()), qApp, SLOT(quit()) );
+}
+
+
+void ClientInfo::connectToServer()
+{
+ delete socket;
+ socket = new QSocket( this );
+ connect( socket, SIGNAL(connected()), SLOT(socketConnected()) );
+ connect( socket, SIGNAL(connectionClosed()), SLOT(socketConnectionClosed()) );
+ connect( socket, SIGNAL(readyRead()), SLOT(socketReadyRead()) );
+ connect( socket, SIGNAL(error(int)), SLOT(socketError(int)) );
+
+ socket->connectToHost( edHost->text(), edPort->text().toInt() );
+}
+
+void ClientInfo::selectItem( const QString& item )
+{
+ // item in listBox selected, use LIST or GET depending of the node type.
+ if ( item.endsWith( "/" ) ) {
+ sendToServer( List, infoPath->text() + item );
+ infoPath->setText( infoPath->text() + item );
+ } else
+ sendToServer( Get, infoPath->text() + item );
+}
+
+void ClientInfo::stepBack()
+{
+ // go back (up) in path hierarchy
+ int i = infoPath->text().findRev( '/', -2 );
+ if ( i > 0 )
+ infoPath->setText( infoPath->text().left( i + 1 ) );
+ else
+ infoPath->setText( "/" );
+ infoList->clear();
+ sendToServer( List, infoPath->text() );
+}
+
+
+void ClientInfo::socketConnected()
+{
+ sendToServer( List, "/" );
+}
+
+void ClientInfo::sendToServer( Operation op, const QString& location )
+{
+ QString line;
+ switch (op) {
+ case List:
+ infoList->clear();
+ line = "LIST " + location;
+ break;
+ case Get:
+ line = "GET " + location;
+ break;
+ }
+ infoText->clear();
+ QTextStream os(socket);
+ os << line << "\r\n";
+}
+
+void ClientInfo::socketReadyRead()
+{
+ QTextStream stream( socket );
+ QString line;
+ while ( socket->canReadLine() ) {
+ line = stream.readLine();
+ if ( line.startsWith( "500" ) || line.startsWith( "550" ) ) {
+ infoText->append( tr( "error: " ) + line.mid( 4 ) );
+ } else if ( line.startsWith( "212+" ) ) {
+ infoList->insertItem( line.mid( 6 ) + QString( ( line[ 4 ] == 'D' ) ? "/" : "" ) );
+ } else if ( line.startsWith( "213+" ) ) {
+ infoText->append( line.mid( 4 ) );
+ }
+ }
+}
+
+
+void ClientInfo::socketConnectionClosed()
+{
+ infoText->clear();
+ infoText->append( tr( "error: Connection closed by the server\n" ) );
+}
+
+void ClientInfo::socketError( int code )
+{
+ infoText->clear();
+ infoText->append( tr( "error: Error number %1 occurred\n" ).arg( code ) );
+}
+
diff --git a/examples/network/infoprotocol/infoclient/client.h b/examples/network/infoprotocol/infoclient/client.h
new file mode 100644
index 0000000..a3e09af
--- /dev/null
+++ b/examples/network/infoprotocol/infoclient/client.h
@@ -0,0 +1,47 @@
+/****************************************************************************
+**
+** Copyright (C) 1992-2008 Trolltech ASA. All rights reserved.
+**
+** This file is part of an example program for Qt. This example
+** program may be used, distributed and modified without limitation.
+**
+*****************************************************************************/
+
+#ifndef CLIENT_H
+#define CLIENT_H
+
+#include "clientbase.h"
+
+class QSocket;
+class QTextEdit;
+class QLineEdit;
+class QListBox;
+class QLabel;
+
+static const Q_UINT16 infoPort = 42417;
+
+class ClientInfo : public ClientInfoBase
+{
+ Q_OBJECT
+public:
+ ClientInfo( QWidget *parent = 0, const char *name = 0 );
+
+private:
+ enum Operation { List, Get };
+
+private slots:
+ void connectToServer();
+ void selectItem( const QString& item );
+ void stepBack();
+ void sendToServer( Operation op, const QString& location );
+ void socketConnected();
+ void socketReadyRead();
+ void socketConnectionClosed();
+ void socketError( int code );
+
+private:
+ QSocket *socket;
+};
+
+#endif // CLIENT_H
+
diff --git a/examples/network/infoprotocol/infoclient/clientbase.ui b/examples/network/infoprotocol/infoclient/clientbase.ui
new file mode 100644
index 0000000..3f73c9a
--- /dev/null
+++ b/examples/network/infoprotocol/infoclient/clientbase.ui
@@ -0,0 +1,276 @@
+<!DOCTYPE UI><UI version="3.0" stdsetdef="1">
+<class>ClientInfoBase</class>
+<widget class="QWidget">
+ <property name="name">
+ <cstring>ClientInfoBase</cstring>
+ </property>
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>384</width>
+ <height>488</height>
+ </rect>
+ </property>
+ <property name="caption">
+ <string>Info Client</string>
+ </property>
+ <vbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <property name="margin">
+ <number>11</number>
+ </property>
+ <property name="spacing">
+ <number>6</number>
+ </property>
+ <widget class="QLayoutWidget">
+ <property name="name">
+ <cstring>Layout15</cstring>
+ </property>
+ <hbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <property name="margin">
+ <number>0</number>
+ </property>
+ <property name="spacing">
+ <number>6</number>
+ </property>
+ <widget class="QPushButton">
+ <property name="name">
+ <cstring>btnConnect</cstring>
+ </property>
+ <property name="text">
+ <string>&amp;Connect</string>
+ </property>
+ </widget>
+ <widget class="QLabel">
+ <property name="name">
+ <cstring>TextLabel1</cstring>
+ </property>
+ <property name="text">
+ <string>Host:</string>
+ </property>
+ </widget>
+ <widget class="QLineEdit">
+ <property name="name">
+ <cstring>edHost</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>7</hsizetype>
+ <vsizetype>0</vsizetype>
+ <horstretch>1</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string></string>
+ </property>
+ </widget>
+ <widget class="QLabel">
+ <property name="name">
+ <cstring>TextLabel2_2</cstring>
+ </property>
+ <property name="text">
+ <string>Port:</string>
+ </property>
+ </widget>
+ <widget class="QLineEdit">
+ <property name="name">
+ <cstring>edPort</cstring>
+ </property>
+ </widget>
+ </hbox>
+ </widget>
+ <widget class="QSplitter">
+ <property name="name">
+ <cstring>Splitter4</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Vertical</enum>
+ </property>
+ <widget class="QLayoutWidget">
+ <property name="name">
+ <cstring>Layout16</cstring>
+ </property>
+ <vbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <property name="margin">
+ <number>0</number>
+ </property>
+ <property name="spacing">
+ <number>6</number>
+ </property>
+ <widget class="QLayoutWidget">
+ <property name="name">
+ <cstring>Layout14</cstring>
+ </property>
+ <hbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <property name="margin">
+ <number>0</number>
+ </property>
+ <property name="spacing">
+ <number>6</number>
+ </property>
+ <widget class="QPushButton">
+ <property name="name">
+ <cstring>btnBack</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>1</hsizetype>
+ <vsizetype>0</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>&amp;Back</string>
+ </property>
+ <property name="toolTip" stdset="0">
+ <string>go one step back</string>
+ </property>
+ </widget>
+ <widget class="QLabel">
+ <property name="name">
+ <cstring>infoPath</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>3</hsizetype>
+ <vsizetype>5</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>/</string>
+ </property>
+ <property name="toolTip" stdset="0">
+ <string>current path</string>
+ </property>
+ </widget>
+ </hbox>
+ </widget>
+ <widget class="QListBox">
+ <property name="name">
+ <cstring>infoList</cstring>
+ </property>
+ <property name="toolTip" stdset="0">
+ <string>double click to open</string>
+ </property>
+ </widget>
+ </vbox>
+ </widget>
+ <widget class="QLayoutWidget">
+ <property name="name">
+ <cstring>Layout3</cstring>
+ </property>
+ <vbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <property name="margin">
+ <number>0</number>
+ </property>
+ <property name="spacing">
+ <number>6</number>
+ </property>
+ <widget class="QLabel">
+ <property name="name">
+ <cstring>TextLabel2</cstring>
+ </property>
+ <property name="text">
+ <string>Data:</string>
+ </property>
+ </widget>
+ <widget class="QTextEdit">
+ <property name="name">
+ <cstring>infoText</cstring>
+ </property>
+ <property name="readOnly">
+ <bool>true</bool>
+ </property>
+ </widget>
+ </vbox>
+ </widget>
+ </widget>
+ <widget class="QLayoutWidget">
+ <property name="name">
+ <cstring>Layout12</cstring>
+ </property>
+ <hbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <property name="margin">
+ <number>0</number>
+ </property>
+ <property name="spacing">
+ <number>6</number>
+ </property>
+ <spacer>
+ <property name="name" stdset="0">
+ <cstring>Spacer10</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Horizontal</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Expanding</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>20</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ <widget class="QPushButton">
+ <property name="name">
+ <cstring>btnQuit</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>3</hsizetype>
+ <vsizetype>0</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>&amp;Quit</string>
+ </property>
+ </widget>
+ <spacer>
+ <property name="name" stdset="0">
+ <cstring>Spacer9</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Horizontal</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Expanding</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>20</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </hbox>
+ </widget>
+ </vbox>
+</widget>
+<layoutdefaults spacing="6" margin="11"/>
+</UI>
diff --git a/examples/network/infoprotocol/infoclient/infoclient.pro b/examples/network/infoprotocol/infoclient/infoclient.pro
new file mode 100644
index 0000000..46759dd
--- /dev/null
+++ b/examples/network/infoprotocol/infoclient/infoclient.pro
@@ -0,0 +1,11 @@
+TEMPLATE = app
+TARGET = infoclient
+
+CONFIG += qt warn_on release
+
+REQUIRES = network full-config nocrosscompiler
+
+HEADERS = client.h
+SOURCES = main.cpp \
+ client.cpp
+INTERFACES = clientbase.ui
diff --git a/examples/network/infoprotocol/infoclient/main.cpp b/examples/network/infoprotocol/infoclient/main.cpp
new file mode 100644
index 0000000..cc4950a
--- /dev/null
+++ b/examples/network/infoprotocol/infoclient/main.cpp
@@ -0,0 +1,21 @@
+/****************************************************************************
+**
+** Copyright (C) 1992-2008 Trolltech ASA. All rights reserved.
+**
+** This file is part of an example program for Qt. This example
+** program may be used, distributed and modified without limitation.
+**
+*****************************************************************************/
+
+#include <qapplication.h>
+
+#include "client.h"
+
+int main( int argc, char** argv )
+{
+ QApplication app( argc, argv );
+ ClientInfo info;
+ app.setMainWidget( &info );
+ info.show();
+ return app.exec();
+}
diff --git a/examples/network/infoprotocol/infoserver/infodata.cpp b/examples/network/infoprotocol/infoserver/infodata.cpp
new file mode 100644
index 0000000..597f8a3
--- /dev/null
+++ b/examples/network/infoprotocol/infoserver/infodata.cpp
@@ -0,0 +1,88 @@
+/****************************************************************************
+**
+** Copyright (C) 1992-2008 Trolltech ASA. All rights reserved.
+**
+** This file is part of an example program for Qt. This example
+** program may be used, distributed and modified without limitation.
+**
+*****************************************************************************/
+
+#include "infodata.h"
+
+
+// we hard code all nodes and data in InfoData class
+InfoData::InfoData() :
+ nodes( 17, TRUE ), data( 17, TRUE )
+{
+ nodes.setAutoDelete(TRUE);
+ data.setAutoDelete(TRUE);
+ QStringList *item;
+
+ nodes.insert( "/", item = new QStringList( ) );
+ (*item) << "D network";
+ nodes.insert( "/network/", item = new QStringList() );
+ (*item) << "D workstations" << "D printers" << "D fax";
+ nodes.insert( "/network/workstations/", item = new QStringList() );
+ (*item) << "D nibble" << "D douglas";
+ nodes.insert( "/network/workstations/nibble/", item = new QStringList() );
+ (*item) << "F os" << "F cpu" << "F memory";
+ nodes.insert( "/network/workstations/douglas/", item = new QStringList() );
+ (*item) << "F os" << "F cpu" << "F memory";
+ nodes.insert( "/network/printers/", item = new QStringList() );
+ (*item) << "D overbitt" << "D kroksleiven";
+ nodes.insert( "/network/printers/overbitt/", item = new QStringList() );
+ (*item) << "D jobs" << "F type";
+ nodes.insert( "/network/printers/overbitt/jobs/", item = new QStringList() );
+ (*item) << "F job1" << "F job2";
+ nodes.insert( "/network/printers/kroksleiven/", item = new QStringList() );
+ (*item) << "D jobs" << "F type";
+ nodes.insert( "/network/printers/kroksleiven/jobs/", item = new QStringList() );
+ nodes.insert( "/network/fax/", item = new QStringList() );
+ (*item) << "F last_number";
+
+ data.insert( "/network/workstations/nibble/os", new QString( "Linux" ) );
+ data.insert( "/network/workstations/nibble/cpu", new QString( "AMD Athlon 1000" ) );
+ data.insert( "/network/workstations/nibble/memory", new QString( "256 MB" ) );
+ data.insert( "/network/workstations/douglas/os", new QString( "Windows 2000" ) );
+ data.insert( "/network/workstations/douglas/cpu", new QString( "2 x Intel Pentium III 800" ) );
+ data.insert( "/network/workstations/douglas/memory", new QString( "256 MB" ) );
+ data.insert( "/network/printers/overbitt/type", new QString( "Lexmark Optra S 1255 PS" ) );
+ data.insert( "/network/printers/overbitt/jobs/job1",
+ new QString( "Qt manual\n" "A4 size\n" "3000 pages" ) );
+ data.insert( "/network/printers/overbitt/jobs/job2",
+ new QString( "Monthly report\n" "Letter size\n" "24 pages\n" "8 copies" ) );
+ data.insert( "/network/printers/kroksleiven/type", new QString( "HP C LaserJet 4500-PS" ) );
+ data.insert( "/network/fax/last_number", new QString( "22 22 22 22" ) );
+}
+
+QStringList InfoData::list( QString path, bool *found ) const
+{
+ if ( !path.endsWith( "/" ) )
+ path += "/";
+ if ( !path.startsWith( "/" ) )
+ path = "/" + path;
+ QStringList *list = nodes[ path ];
+ if ( list ) {
+ *found = TRUE;
+ return *list;
+ } else {
+ *found = FALSE;
+ QStringList empty;
+ return empty;
+ }
+}
+
+QString InfoData::get( QString path, bool *found ) const
+{
+ if ( !path.startsWith( "/" ) )
+ path = "/" + path;
+ QString *file = data[ path ];
+ if ( file ) {
+ *found = TRUE;
+ return *file;
+ } else {
+ *found = FALSE;
+ QString empty;
+ return empty;
+ }
+}
diff --git a/examples/network/infoprotocol/infoserver/infodata.h b/examples/network/infoprotocol/infoserver/infodata.h
new file mode 100644
index 0000000..0189332
--- /dev/null
+++ b/examples/network/infoprotocol/infoserver/infodata.h
@@ -0,0 +1,31 @@
+/****************************************************************************
+**
+** Copyright (C) 1992-2008 Trolltech ASA. All rights reserved.
+**
+** This file is part of an example program for Qt. This example
+** program may be used, distributed and modified without limitation.
+**
+*****************************************************************************/
+
+#ifndef INFODATA_H
+#define INFODATA_H
+
+#include <qdict.h>
+#include <qstringlist.h>
+
+
+// The InfoData class manages data, organized in tree structure.
+class InfoData
+{
+public:
+ InfoData();
+ QStringList list( QString path, bool *found ) const;
+ QString get( QString path, bool *found ) const;
+
+private:
+ QDict< QStringList > nodes;
+ QDict< QString > data;
+};
+
+#endif // INFODATA_H
+
diff --git a/examples/network/infoprotocol/infoserver/infoserver.pro b/examples/network/infoprotocol/infoserver/infoserver.pro
new file mode 100644
index 0000000..3d79aef
--- /dev/null
+++ b/examples/network/infoprotocol/infoserver/infoserver.pro
@@ -0,0 +1,13 @@
+TEMPLATE = app
+TARGET = infoserver
+
+CONFIG += qt warn_on release
+
+REQUIRES = network full-config nocrosscompiler
+
+HEADERS = server.h \
+ infodata.h
+SOURCES = main.cpp \
+ server.cpp \
+ infodata.cpp
+INTERFACES = serverbase.ui
diff --git a/examples/network/infoprotocol/infoserver/main.cpp b/examples/network/infoprotocol/infoserver/main.cpp
new file mode 100644
index 0000000..fd0e8e3
--- /dev/null
+++ b/examples/network/infoprotocol/infoserver/main.cpp
@@ -0,0 +1,22 @@
+/****************************************************************************
+**
+** Copyright (C) 1992-2008 Trolltech ASA. All rights reserved.
+**
+** This file is part of an example program for Qt. This example
+** program may be used, distributed and modified without limitation.
+**
+*****************************************************************************/
+
+#include <qapplication.h>
+
+#include "server.h"
+
+int main( int argc, char** argv )
+{
+ QApplication app( argc, argv );
+ Q_UINT16 port = ( argc > 1 ) ? QString( argv[ 1 ] ).toInt() : infoPort;
+ ServerInfo info( port, 0, "server info" );
+ app.setMainWidget( &info );
+ info.show();
+ return app.exec();
+}
diff --git a/examples/network/infoprotocol/infoserver/server.cpp b/examples/network/infoprotocol/infoserver/server.cpp
new file mode 100644
index 0000000..f3815ae
--- /dev/null
+++ b/examples/network/infoprotocol/infoserver/server.cpp
@@ -0,0 +1,99 @@
+/****************************************************************************
+**
+** Copyright (C) 1992-2008 Trolltech ASA. All rights reserved.
+**
+** This file is part of an example program for Qt. This example
+** program may be used, distributed and modified without limitation.
+**
+*****************************************************************************/
+
+#include <qtextview.h>
+#include <qpushbutton.h>
+#include <qtextstream.h>
+#include <qapplication.h>
+#include <qmessagebox.h>
+#include <stdlib.h>
+
+#include "server.h"
+
+
+
+ServerInfo::ServerInfo( Q_UINT16 port, QWidget *parent, const char *name ) :
+ ServerInfoBase( parent, name )
+{
+ SimpleServer *server = new SimpleServer( port, this, "simple server" );
+ connect( server, SIGNAL(newConnect()), SLOT(newConnect()) );
+ connect( btnQuit, SIGNAL(clicked()), qApp, SLOT(quit()) );
+}
+
+void ServerInfo::newConnect()
+{
+ infoText->append( tr( "New connection\n" ) );
+}
+
+
+SimpleServer::SimpleServer( Q_UINT16 port, QObject* parent, const char *name ) :
+ QServerSocket( port, 1, parent, name )
+{
+ if ( !ok() ) {
+ QMessageBox::critical( 0, tr( "Error" ), tr( "Failed to bind to port %1" ).arg( port ) );
+ exit(1);
+ }
+}
+
+void SimpleServer::newConnection( int socket )
+{
+ (void)new ClientSocket( socket, &info, this, "client socket" );
+ emit newConnect();
+}
+
+
+ClientSocket::ClientSocket( int sock, InfoData *i, QObject *parent, const char *name ) :
+ QSocket( parent, name ), info( i )
+{
+ connect( this, SIGNAL(readyRead()), SLOT(readClient()) );
+ connect( this, SIGNAL(connectionClosed()), SLOT(connectionClosed()) );
+ setSocket( sock );
+}
+
+void ClientSocket::readClient()
+{
+ QTextStream stream( this );
+ QStringList answer;
+ while ( canReadLine() ) {
+ stream << processCommand( stream.readLine() );
+ }
+}
+
+QString ClientSocket::processCommand( const QString& command )
+{
+ QString answer;
+ QString com = command.simplifyWhiteSpace ();
+ if ( com.startsWith( "LIST" ) ) {
+ bool ok;
+ QStringList nodes = info->list( com.mid( 5 ), &ok );
+ if ( ok ) {
+ for ( QStringList::Iterator it = nodes.begin(); it != nodes.end(); ++it )
+ answer += "212+" + *it + "\r\n";
+ answer += "212 \r\n";
+ } else
+ answer += "550 Invalid path\r\n";
+ } else if ( com.startsWith( "GET " ) ) {
+ bool ok;
+ QStringList data = QStringList::split( '\n', info->get( com.mid( 4 ), &ok ), TRUE );
+ if ( ok ) {
+ for ( QStringList::Iterator it = data.begin(); it != data.end(); ++it )
+ answer += "213+" + *it + "\r\n";
+ answer += "213 \r\n";
+ } else
+ answer += "550 Info not found\r\n";
+ } else
+ answer += "500 Syntax error\r\n";
+
+ return answer;
+}
+
+void ClientSocket::connectionClosed()
+{
+ delete this;
+}
diff --git a/examples/network/infoprotocol/infoserver/server.h b/examples/network/infoprotocol/infoserver/server.h
new file mode 100644
index 0000000..fa07b93
--- /dev/null
+++ b/examples/network/infoprotocol/infoserver/server.h
@@ -0,0 +1,69 @@
+/****************************************************************************
+**
+** Copyright (C) 1992-2008 Trolltech ASA. All rights reserved.
+**
+** This file is part of an example program for Qt. This example
+** program may be used, distributed and modified without limitation.
+**
+*****************************************************************************/
+
+#ifndef SERVER_H
+#define SERVER_H
+
+#include <qsocket.h>
+#include <qserversocket.h>
+
+#include "infodata.h"
+#include "serverbase.h"
+
+static const Q_UINT16 infoPort = 42417;
+
+
+/*
+ The ServerInfo class provides a small GUI for the server. It also creates the
+ SimpleServer and as a result the server.
+*/
+class ServerInfo : public ServerInfoBase
+{
+ Q_OBJECT
+public:
+ ServerInfo( Q_UINT16 port = infoPort, QWidget *parent = 0, const char *name = 0 );
+
+private slots:
+ void newConnect();
+};
+
+
+class SimpleServer : public QServerSocket
+{
+ Q_OBJECT
+public:
+ SimpleServer( Q_UINT16 port = infoPort, QObject* parent = 0, const char *name = 0 );
+ void newConnection( int socket );
+
+signals:
+ void newConnect();
+
+private:
+ InfoData info;
+};
+
+
+class ClientSocket : public QSocket
+{
+ Q_OBJECT
+public:
+ ClientSocket( int sock, InfoData *i, QObject *parent = 0, const char *name = 0 );
+
+private slots:
+ void readClient();
+ void connectionClosed();
+
+private:
+ QString processCommand( const QString& command );
+ InfoData *info;
+};
+
+
+#endif //SERVER_H
+
diff --git a/examples/network/infoprotocol/infoserver/serverbase.ui b/examples/network/infoprotocol/infoserver/serverbase.ui
new file mode 100644
index 0000000..12998da
--- /dev/null
+++ b/examples/network/infoprotocol/infoserver/serverbase.ui
@@ -0,0 +1,117 @@
+<!DOCTYPE UI><UI version="3.0" stdsetdef="1">
+<class>ServerInfoBase</class>
+<widget class="QWidget">
+ <property name="name">
+ <cstring>ServerInfoBase</cstring>
+ </property>
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>272</width>
+ <height>282</height>
+ </rect>
+ </property>
+ <property name="caption">
+ <string>Info Server</string>
+ </property>
+ <vbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <property name="margin">
+ <number>11</number>
+ </property>
+ <property name="spacing">
+ <number>6</number>
+ </property>
+ <widget class="QLabel">
+ <property name="name">
+ <cstring>TextLabel1</cstring>
+ </property>
+ <property name="text">
+ <string>This is a small Information Server.
+Accepting client requests...</string>
+ </property>
+ <property name="alignment">
+ <set>AlignCenter</set>
+ </property>
+ </widget>
+ <widget class="QTextEdit">
+ <property name="name">
+ <cstring>infoText</cstring>
+ </property>
+ <property name="readOnly">
+ <bool>true</bool>
+ </property>
+ </widget>
+ <widget class="QLayoutWidget">
+ <property name="name">
+ <cstring>Layout1</cstring>
+ </property>
+ <hbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <property name="margin">
+ <number>0</number>
+ </property>
+ <property name="spacing">
+ <number>6</number>
+ </property>
+ <spacer>
+ <property name="name" stdset="0">
+ <cstring>Spacer2</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Horizontal</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Expanding</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>20</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ <widget class="QPushButton">
+ <property name="name">
+ <cstring>btnQuit</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>3</hsizetype>
+ <vsizetype>0</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>&amp;Quit</string>
+ </property>
+ </widget>
+ <spacer>
+ <property name="name" stdset="0">
+ <cstring>Spacer1</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Horizontal</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Expanding</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>20</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </hbox>
+ </widget>
+ </vbox>
+</widget>
+<layoutdefaults spacing="6" margin="11"/>
+</UI>
diff --git a/examples/network/infoprotocol/infourlclient/client.cpp b/examples/network/infoprotocol/infourlclient/client.cpp
new file mode 100644
index 0000000..712090f
--- /dev/null
+++ b/examples/network/infoprotocol/infourlclient/client.cpp
@@ -0,0 +1,60 @@
+/****************************************************************************
+**
+** Copyright (C) 1992-2008 Trolltech ASA. All rights reserved.
+**
+** This file is part of an example program for Qt. This example
+** program may be used, distributed and modified without limitation.
+**
+*****************************************************************************/
+
+#include <qapplication.h>
+#include <qtextedit.h>
+#include <qpushbutton.h>
+#include <qfiledialog.h>
+
+#include "qip.h"
+#include "client.h"
+
+
+
+
+ClientInfo::ClientInfo( QWidget *parent, const char *name ) :
+ ClientInfoBase( parent, name )
+{
+ connect( btnOpen, SIGNAL(clicked()), SLOT(downloadFile()) );
+ connect( btnQuit, SIGNAL(clicked()), qApp, SLOT(quit()) );
+ connect( &op, SIGNAL( data( const QByteArray &, QNetworkOperation * ) ),
+ this, SLOT( newData( const QByteArray & ) ) );
+}
+
+void ClientInfo::downloadFile()
+{
+ // under Windows you must not use the native file dialog
+ QString file = getOpenFileName();
+ if ( !file.isEmpty() ) {
+ infoText->clear();
+ // download the data
+ op = file;
+ op.get();
+ }
+}
+
+QString ClientInfo::getOpenFileName()
+{
+ static QString workingDirectory( "qip://localhost/" );
+
+ QFileDialog dlg( workingDirectory, QString::null, 0, 0, TRUE );
+ dlg.setCaption( QFileDialog::tr( "Open" ) );
+ dlg.setMode( QFileDialog::ExistingFile );
+ QString result;
+ if ( dlg.exec() == QDialog::Accepted ) {
+ result = dlg.selectedFile();
+ workingDirectory = dlg.url();
+ }
+ return result;
+}
+
+void ClientInfo::newData( const QByteArray &ba )
+{
+ infoText->append( QString::fromUtf8( ba ) );
+}
diff --git a/examples/network/infoprotocol/infourlclient/client.h b/examples/network/infoprotocol/infourlclient/client.h
new file mode 100644
index 0000000..ca8340b
--- /dev/null
+++ b/examples/network/infoprotocol/infourlclient/client.h
@@ -0,0 +1,35 @@
+/****************************************************************************
+**
+** Copyright (C) 1992-2008 Trolltech ASA. All rights reserved.
+**
+** This file is part of an example program for Qt. This example
+** program may be used, distributed and modified without limitation.
+**
+*****************************************************************************/
+
+#ifndef CLIENT_H
+#define CLIENT_H
+
+#include <qurloperator.h>
+
+#include "clientbase.h"
+
+
+class ClientInfo : public ClientInfoBase
+{
+ Q_OBJECT
+
+public:
+ ClientInfo( QWidget *parent = 0, const char *name = 0 );
+
+private slots:
+ void downloadFile();
+ void newData( const QByteArray &ba );
+
+private:
+ QUrlOperator op;
+ QString getOpenFileName();
+};
+
+#endif // CLIENT_H
+
diff --git a/examples/network/infoprotocol/infourlclient/clientbase.ui b/examples/network/infoprotocol/infourlclient/clientbase.ui
new file mode 100644
index 0000000..e18b9a3
--- /dev/null
+++ b/examples/network/infoprotocol/infourlclient/clientbase.ui
@@ -0,0 +1,118 @@
+<!DOCTYPE UI><UI version="3.0" stdsetdef="1">
+<class>ClientInfoBase</class>
+<widget class="QWidget">
+ <property name="name">
+ <cstring>ClientInfoBase</cstring>
+ </property>
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>325</width>
+ <height>279</height>
+ </rect>
+ </property>
+ <property name="caption">
+ <string>Info Client Protocol</string>
+ </property>
+ <vbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <property name="margin">
+ <number>11</number>
+ </property>
+ <property name="spacing">
+ <number>6</number>
+ </property>
+ <widget class="QLayoutWidget">
+ <property name="name">
+ <cstring>Layout5</cstring>
+ </property>
+ <hbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <property name="margin">
+ <number>0</number>
+ </property>
+ <property name="spacing">
+ <number>6</number>
+ </property>
+ <widget class="QPushButton">
+ <property name="name">
+ <cstring>btnOpen</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>3</hsizetype>
+ <vsizetype>0</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>&amp;Open</string>
+ </property>
+ <property name="default">
+ <bool>true</bool>
+ </property>
+ <property name="toolTip" stdset="0">
+ <string>open data</string>
+ </property>
+ </widget>
+ <spacer>
+ <property name="name" stdset="0">
+ <cstring>Spacer4</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Horizontal</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Expanding</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>20</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ <widget class="QPushButton">
+ <property name="name">
+ <cstring>btnQuit</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>3</hsizetype>
+ <vsizetype>0</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>&amp;Quit</string>
+ </property>
+ </widget>
+ </hbox>
+ </widget>
+ <widget class="QLabel">
+ <property name="name">
+ <cstring>TextLabel2</cstring>
+ </property>
+ <property name="text">
+ <string>Data:</string>
+ </property>
+ </widget>
+ <widget class="QTextEdit">
+ <property name="name">
+ <cstring>infoText</cstring>
+ </property>
+ <property name="readOnly">
+ <bool>true</bool>
+ </property>
+ </widget>
+ </vbox>
+</widget>
+<layoutdefaults spacing="6" margin="11"/>
+</UI>
diff --git a/examples/network/infoprotocol/infourlclient/infourlclient.pro b/examples/network/infoprotocol/infourlclient/infourlclient.pro
new file mode 100644
index 0000000..219083d
--- /dev/null
+++ b/examples/network/infoprotocol/infourlclient/infourlclient.pro
@@ -0,0 +1,13 @@
+TEMPLATE = app
+TARGET = infourlclient
+
+CONFIG += qt warn_on release
+
+REQUIRES = network full-config nocrosscompiler
+
+HEADERS = client.h \
+ qip.h
+SOURCES = main.cpp \
+ client.cpp \
+ qip.cpp
+INTERFACES = clientbase.ui
diff --git a/examples/network/infoprotocol/infourlclient/main.cpp b/examples/network/infoprotocol/infourlclient/main.cpp
new file mode 100644
index 0000000..677f8a1
--- /dev/null
+++ b/examples/network/infoprotocol/infourlclient/main.cpp
@@ -0,0 +1,23 @@
+/****************************************************************************
+**
+** Copyright (C) 1992-2008 Trolltech ASA. All rights reserved.
+**
+** This file is part of an example program for Qt. This example
+** program may be used, distributed and modified without limitation.
+**
+*****************************************************************************/
+
+#include <qapplication.h>
+
+#include "qip.h"
+#include "client.h"
+
+int main( int argc, char** argv )
+{
+ QApplication app( argc, argv );
+ QNetworkProtocol::registerNetworkProtocol( "qip", new QNetworkProtocolFactory< Qip > );
+ ClientInfo info;
+ app.setMainWidget( &info );
+ info.show();
+ return app.exec();
+}
diff --git a/examples/network/infoprotocol/infourlclient/qip.cpp b/examples/network/infoprotocol/infourlclient/qip.cpp
new file mode 100644
index 0000000..ef71ea3
--- /dev/null
+++ b/examples/network/infoprotocol/infourlclient/qip.cpp
@@ -0,0 +1,132 @@
+/****************************************************************************
+**
+** Copyright (C) 1992-2008 Trolltech ASA. All rights reserved.
+**
+** This file is part of an example program for Qt. This example
+** program may be used, distributed and modified without limitation.
+**
+*****************************************************************************/
+
+#include <qsocket.h>
+#include <qurlinfo.h>
+#include <qurloperator.h>
+#include <qtextstream.h>
+
+#include "qip.h"
+
+
+Qip::Qip()
+{
+ state = Start;
+ socket = new QSocket( this );
+ connect( socket, SIGNAL(connected()), SLOT(socketConnected()) );
+ connect( socket, SIGNAL(connectionClosed()), SLOT(socketConnectionClosed()) );
+ connect( socket, SIGNAL(readyRead()), SLOT(socketReadyRead()) );
+ connect( socket, SIGNAL(error(int)), SLOT(socketError(int)) );
+}
+
+int Qip::supportedOperations() const
+{
+ return OpListChildren | OpGet;
+}
+
+bool Qip::checkConnection( QNetworkOperation * )
+{
+ if ( socket->isOpen() )
+ return TRUE;
+
+ // don't call connectToHost() if we are already trying to connect
+ if ( socket->state() == QSocket::Connecting )
+ return FALSE;
+
+ socket->connectToHost( url()->host(), url()->port() != -1 ? url()->port() : infoPort );
+ return FALSE;
+}
+
+void Qip::operationListChildren( QNetworkOperation * )
+{
+ QTextStream os(socket);
+ os << "LIST " + url()->path() + "\r\n";
+ operationInProgress()->setState( StInProgress );
+}
+
+void Qip::operationGet( QNetworkOperation * )
+{
+ QTextStream os(socket);
+ os << "GET " + url()->path() + "\r\n";
+ operationInProgress()->setState( StInProgress );
+}
+
+void Qip::socketConnected()
+{
+ if ( url() )
+ emit connectionStateChanged( ConConnected, tr( "Connected to host %1" ).arg( url()->host() ) );
+ else
+ emit connectionStateChanged( ConConnected, tr ("Connected to host" ) );
+}
+
+void Qip::socketConnectionClosed()
+{
+ if ( url() )
+ emit connectionStateChanged( ConClosed, tr( "Connection to %1 closed" ).arg( url()->host() ) );
+ else
+ emit connectionStateChanged( ConClosed, tr ("Connection closed" ) );
+}
+
+void Qip::socketError( int code )
+{
+ if ( code == QSocket::ErrHostNotFound ||
+ code == QSocket::ErrConnectionRefused ) {
+ error( ErrHostNotFound, tr( "Host not found or couldn't connect to: %1\n" ).arg( url()->host() ) );
+ } else
+ error( ErrUnsupported, tr( "Error" ) );
+}
+
+void Qip::socketReadyRead()
+{
+ // read from the server
+ QTextStream stream( socket );
+ QString line;
+ while ( socket->canReadLine() ) {
+ line = stream.readLine();
+ if ( line.startsWith( "500" ) ) {
+ error( ErrValid, line.mid( 4 ) );
+ } else if ( line.startsWith( "550" ) ) {
+ error( ErrFileNotExisting, line.mid( 4 ) );
+ } else if ( line.startsWith( "212+" ) ) {
+ if ( state != List ) {
+ state = List;
+ emit start( operationInProgress() );
+ }
+ QUrlInfo inf;
+ inf.setName( line.mid( 6 ) + QString( ( line[ 4 ] == 'D' ) ? "/" : "" ) );
+ inf.setDir( line[ 4 ] == 'D' );
+ inf.setSymLink( FALSE );
+ inf.setFile( line[ 4 ] == 'F' );
+ inf.setWritable( FALSE );
+ inf.setReadable( TRUE );
+ emit newChild( inf, operationInProgress() );
+ } else if ( line.startsWith( "213+" ) ) {
+ state = Data;
+ emit data( line.mid( 4 ).utf8(), operationInProgress() );
+ }
+ if( line[3] == ' ' && state != Start) {
+ state = Start;
+ operationInProgress()->setState( StDone );
+ emit finished( operationInProgress() );
+ }
+ }
+}
+
+void Qip::error( int code, const QString& msg )
+{
+ if ( operationInProgress() ) {
+ operationInProgress()->setState( StFailed );
+ operationInProgress()->setErrorCode( code );
+ operationInProgress()->setProtocolDetail( msg );
+ clearOperationQueue();
+ emit finished( operationInProgress() );
+ }
+ state = Start;
+}
+
diff --git a/examples/network/infoprotocol/infourlclient/qip.h b/examples/network/infoprotocol/infourlclient/qip.h
new file mode 100644
index 0000000..339e46b
--- /dev/null
+++ b/examples/network/infoprotocol/infourlclient/qip.h
@@ -0,0 +1,48 @@
+/****************************************************************************
+**
+** Copyright (C) 1992-2008 Trolltech ASA. All rights reserved.
+**
+** This file is part of an example program for Qt. This example
+** program may be used, distributed and modified without limitation.
+**
+*****************************************************************************/
+
+#ifndef QIP_H
+#define QIP_H
+
+#include <qnetworkprotocol.h>
+
+class QSocket;
+
+static const Q_UINT16 infoPort = 42417;
+
+
+class Qip : public QNetworkProtocol
+{
+ Q_OBJECT
+
+public:
+ Qip();
+ virtual int supportedOperations() const;
+
+protected:
+ virtual void operationListChildren( QNetworkOperation *op );
+ virtual void operationGet( QNetworkOperation *op );
+ virtual bool checkConnection( QNetworkOperation *op );
+
+private slots:
+ void socketConnected();
+ void socketReadyRead();
+ void socketConnectionClosed();
+ void socketError( int code );
+
+private:
+ QSocket *socket;
+ enum State { Start, List, Data } state;
+ void error( int code, const QString& msg );
+};
+
+
+
+#endif // QIP_H
+
diff --git a/examples/network/mail/composer.cpp b/examples/network/mail/composer.cpp
new file mode 100644
index 0000000..4c2bb36
--- /dev/null
+++ b/examples/network/mail/composer.cpp
@@ -0,0 +1,65 @@
+/****************************************************************************
+**
+** Copyright (C) 1992-2008 Trolltech ASA. All rights reserved.
+**
+** This file is part of an example program for Qt. This example
+** program may be used, distributed and modified without limitation.
+**
+*****************************************************************************/
+
+#include "composer.h"
+#include "smtp.h"
+
+#include <qlineedit.h>
+#include <qmultilineedit.h>
+#include <qpushbutton.h>
+#include <qlabel.h>
+#include <qlayout.h>
+
+Composer::Composer( QWidget *parent )
+ : QWidget( parent )
+{
+ QGridLayout * layout = new QGridLayout( this, 1, 1, 6 );
+
+ layout->addWidget( new QLabel( tr( "From:" ), this ), 0, 0 );
+ from = new QLineEdit( this );
+ layout->addWidget( from, 0, 1 );
+
+ layout->addWidget( new QLabel( tr( "To:" ), this ), 1, 0 );
+ to = new QLineEdit( this );
+ layout->addWidget( to, 1, 1 );
+
+ layout->addWidget( new QLabel( tr( "Subject:" ), this ), 2, 0 );
+ subject = new QLineEdit( this );
+ layout->addWidget( subject, 2, 1 );
+
+ message = new QMultiLineEdit( this );
+ layout->addMultiCellWidget( message, 3, 3, 0, 1 );
+
+ send = new QPushButton( tr( "&Send" ), this );
+ layout->addWidget( send, 4, 0 );
+ connect( send, SIGNAL( clicked() ), this, SLOT( sendMessage() ) );
+
+ sendStatus = new QLabel( this );
+ layout->addWidget( sendStatus, 4, 1 );
+}
+
+
+void Composer::sendMessage()
+{
+ send->setEnabled( FALSE );
+ sendStatus->setText( tr( "Looking up mail servers" ) );
+ Smtp *smtp = new Smtp( from->text(), to->text(),
+ subject->text(),
+ message->text() );
+ connect( smtp, SIGNAL(destroyed()),
+ this, SLOT(enableSend()) );
+ connect( smtp, SIGNAL(status(const QString &)),
+ sendStatus, SLOT(setText(const QString &)) );
+}
+
+
+void Composer::enableSend()
+{
+ send->setEnabled( TRUE );
+}
diff --git a/examples/network/mail/composer.h b/examples/network/mail/composer.h
new file mode 100644
index 0000000..fa457ce
--- /dev/null
+++ b/examples/network/mail/composer.h
@@ -0,0 +1,41 @@
+/****************************************************************************
+**
+** Copyright (C) 1992-2008 Trolltech ASA. All rights reserved.
+**
+** This file is part of an example program for Qt. This example
+** program may be used, distributed and modified without limitation.
+**
+*****************************************************************************/
+
+#ifndef COMPOSER_H
+#define COMPOSER_H
+
+#include <qwidget.h>
+
+
+class QLineEdit;
+class QMultiLineEdit;
+class QLabel;
+class QPushButton;
+
+
+class Composer : public QWidget
+{
+ Q_OBJECT
+
+public:
+ Composer( QWidget *parent = 0 );
+
+private slots:
+ void sendMessage();
+ void enableSend();
+
+private:
+ QLineEdit *from, *to, *subject;
+ QMultiLineEdit *message;
+ QLabel * sendStatus;
+ QPushButton * send;
+};
+
+
+#endif
diff --git a/examples/network/mail/mail.doc b/examples/network/mail/mail.doc
new file mode 100644
index 0000000..009f155
--- /dev/null
+++ b/examples/network/mail/mail.doc
@@ -0,0 +1,25 @@
+/*
+*/
+
+/*! \page mail-example.html
+
+ \ingroup network-examples
+
+ \title A simple mail client
+
+ This example shows how to use the QSocket class. The client can only be
+ used to send mails. The interesting part is the implementation of the
+ SMTP protocol.
+
+ <hr>
+
+ Header file (smtp.h):
+
+ \include network/mail/smtp.h
+
+ <hr>
+
+ Implementation (smtp.cpp):
+
+ \include network/mail/smtp.cpp
+*/
diff --git a/examples/network/mail/mail.pro b/examples/network/mail/mail.pro
new file mode 100644
index 0000000..39c9de5
--- /dev/null
+++ b/examples/network/mail/mail.pro
@@ -0,0 +1,12 @@
+TEMPLATE = app
+TARGET = mail
+
+CONFIG += qt warn_on release
+
+REQUIRES = network full-config
+
+HEADERS = composer.h \
+ smtp.h
+SOURCES = composer.cpp \
+ main.cpp \
+ smtp.cpp
diff --git a/examples/network/mail/main.cpp b/examples/network/mail/main.cpp
new file mode 100644
index 0000000..ac60756
--- /dev/null
+++ b/examples/network/mail/main.cpp
@@ -0,0 +1,23 @@
+/****************************************************************************
+**
+** Copyright (C) 1992-2008 Trolltech ASA. All rights reserved.
+**
+** This file is part of an example program for Qt. This example
+** program may be used, distributed and modified without limitation.
+**
+*****************************************************************************/
+
+#include <qapplication.h>
+
+#include "composer.h"
+
+int main( int argc, char **argv )
+{
+ QApplication a( argc, argv );
+
+ Composer c;
+ a.setMainWidget( &c );
+ c.resize( 400, 500 );
+ c.show();
+ return a.exec();
+}
diff --git a/examples/network/mail/smtp.cpp b/examples/network/mail/smtp.cpp
new file mode 100644
index 0000000..f801070
--- /dev/null
+++ b/examples/network/mail/smtp.cpp
@@ -0,0 +1,127 @@
+/****************************************************************************
+**
+** Copyright (C) 1992-2008 Trolltech ASA. All rights reserved.
+**
+** This file is part of an example program for Qt. This example
+** program may be used, distributed and modified without limitation.
+**
+*****************************************************************************/
+
+#include "smtp.h"
+
+#include <qtextstream.h>
+#include <qsocket.h>
+#include <qdns.h>
+#include <qtimer.h>
+#include <qapplication.h>
+#include <qmessagebox.h>
+#include <qregexp.h>
+
+
+Smtp::Smtp( const QString &from, const QString &to,
+ const QString &subject,
+ const QString &body )
+{
+ socket = new QSocket( this );
+ connect ( socket, SIGNAL( readyRead() ),
+ this, SLOT( readyRead() ) );
+ connect ( socket, SIGNAL( connected() ),
+ this, SLOT( connected() ) );
+
+ mxLookup = new QDns( to.mid( to.find( '@' )+1 ), QDns::Mx );
+ connect( mxLookup, SIGNAL(resultsReady()),
+ this, SLOT(dnsLookupHelper()) );
+
+ message = QString::fromLatin1( "From: " ) + from +
+ QString::fromLatin1( "\nTo: " ) + to +
+ QString::fromLatin1( "\nSubject: " ) + subject +
+ QString::fromLatin1( "\n\n" ) + body + "\n";
+ message.replace( QString::fromLatin1( "\n" ),
+ QString::fromLatin1( "\r\n" ) );
+ message.replace( QString::fromLatin1( "\r\n.\r\n" ),
+ QString::fromLatin1( "\r\n..\r\n" ) );
+
+ this->from = from;
+ rcpt = to;
+
+ state = Init;
+}
+
+
+Smtp::~Smtp()
+{
+ delete t;
+ delete socket;
+}
+
+
+void Smtp::dnsLookupHelper()
+{
+ QValueList<QDns::MailServer> s = mxLookup->mailServers();
+ if ( s.isEmpty() ) {
+ if ( !mxLookup->isWorking() )
+ emit status( tr( "Error in MX record lookup" ) );
+ return;
+ }
+
+ emit status( tr( "Connecting to %1" ).arg( s.first().name ) );
+
+ socket->connectToHost( s.first().name, 25 );
+ t = new QTextStream( socket );
+}
+
+
+void Smtp::connected()
+{
+ emit status( tr( "Connected to %1" ).arg( socket->peerName() ) );
+}
+
+void Smtp::readyRead()
+{
+ // SMTP is line-oriented
+ if ( !socket->canReadLine() )
+ return;
+
+ QString responseLine;
+ do {
+ responseLine = socket->readLine();
+ response += responseLine;
+ } while( socket->canReadLine() && responseLine[3] != ' ' );
+ responseLine.truncate( 3 );
+
+ if ( state == Init && responseLine[0] == '2' ) {
+ // banner was okay, let's go on
+ *t << "HELO there\r\n";
+ state = Mail;
+ } else if ( state == Mail && responseLine[0] == '2' ) {
+ // HELO response was okay (well, it has to be)
+ *t << "MAIL FROM: <" << from << ">\r\n";
+ state = Rcpt;
+ } else if ( state == Rcpt && responseLine[0] == '2' ) {
+ *t << "RCPT TO: <" << rcpt << ">\r\n";
+ state = Data;
+ } else if ( state == Data && responseLine[0] == '2' ) {
+ *t << "DATA\r\n";
+ state = Body;
+ } else if ( state == Body && responseLine[0] == '3' ) {
+ *t << message << ".\r\n";
+ state = Quit;
+ } else if ( state == Quit && responseLine[0] == '2' ) {
+ *t << "QUIT\r\n";
+ // here, we just close.
+ state = Close;
+ emit status( tr( "Message sent" ) );
+ } else if ( state == Close ) {
+ deleteLater();
+ return;
+ } else {
+ // something broke.
+ QMessageBox::warning( qApp->activeWindow(),
+ tr( "Qt Mail Example" ),
+ tr( "Unexpected reply from SMTP server:\n\n" ) +
+ response );
+ state = Close;
+ }
+
+ response = "";
+}
diff --git a/examples/network/mail/smtp.h b/examples/network/mail/smtp.h
new file mode 100644
index 0000000..0a469a5
--- /dev/null
+++ b/examples/network/mail/smtp.h
@@ -0,0 +1,58 @@
+/****************************************************************************
+**
+** Copyright (C) 1992-2008 Trolltech ASA. All rights reserved.
+**
+** This file is part of an example program for Qt. This example
+** program may be used, distributed and modified without limitation.
+**
+*****************************************************************************/
+
+#ifndef SMTP_H
+#define SMTP_H
+
+#include <qobject.h>
+#include <qstring.h>
+
+class QSocket;
+class QTextStream;
+class QDns;
+
+class Smtp : public QObject
+{
+ Q_OBJECT
+
+public:
+ Smtp( const QString &from, const QString &to,
+ const QString &subject, const QString &body );
+ ~Smtp();
+
+signals:
+ void status( const QString & );
+
+private slots:
+ void dnsLookupHelper();
+ void readyRead();
+ void connected();
+
+private:
+ enum State {
+ Init,
+ Mail,
+ Rcpt,
+ Data,
+ Body,
+ Quit,
+ Close
+ };
+
+ QString message;
+ QString from;
+ QString rcpt;
+ QSocket *socket;
+ QTextStream * t;
+ int state;
+ QString response;
+ QDns * mxLookup;
+};
+
+#endif
diff --git a/examples/network/networkprotocol/README b/examples/network/networkprotocol/README
new file mode 100644
index 0000000..7c1e69d
--- /dev/null
+++ b/examples/network/networkprotocol/README
@@ -0,0 +1,5 @@
+This class shows you how to implement your own network protocols and how to
+use them in a program. This example is part of the network module.
+
+The class Nntp implements the nntp protocol. The implementation of the
+protocol is not complete and should not be used in real programs.
diff --git a/examples/network/networkprotocol/main.cpp b/examples/network/networkprotocol/main.cpp
new file mode 100644
index 0000000..8d636e4
--- /dev/null
+++ b/examples/network/networkprotocol/main.cpp
@@ -0,0 +1,29 @@
+/****************************************************************************
+**
+** Copyright (C) 1992-2008 Trolltech ASA. All rights reserved.
+**
+** This file is part of an example program for Qt. This example
+** program may be used, distributed and modified without limitation.
+**
+*****************************************************************************/
+
+#include <qapplication.h>
+#include <qnetwork.h>
+
+#include "nntp.h"
+#include "view.h"
+
+int main( int argc, char **argv )
+{
+ QApplication a( argc, argv );
+
+ qInitNetworkProtocols();
+ QNetworkProtocol::registerNetworkProtocol( "nntp", new QNetworkProtocolFactory<Nntp> );
+
+ View v;
+ v.resize( 600, 600 );
+ v.show();
+ a.setMainWidget( &v );
+
+ return a.exec();
+}
diff --git a/examples/network/networkprotocol/networkprotocol.doc b/examples/network/networkprotocol/networkprotocol.doc
new file mode 100644
index 0000000..ea00797
--- /dev/null
+++ b/examples/network/networkprotocol/networkprotocol.doc
@@ -0,0 +1,26 @@
+/*
+*/
+
+/*! \page networkprotocol-example.html
+
+ \ingroup network-examples
+
+ \title A simple NNTP implementation
+
+ This example shows how to implement your own QNetworkProtocol. The
+ protocol that was chosen for this example is NTTP. Please note that this
+ implementation is very simple since it is designed to be an example. It
+ should not be used as a real NNTP implemention.
+
+ <hr>
+
+ Header file (nntp.h):
+
+ \include network/networkprotocol/nntp.h
+
+ <hr>
+
+ Implementation (nntp.cpp):
+
+ \include network/networkprotocol/nntp.cpp
+*/
diff --git a/examples/network/networkprotocol/networkprotocol.pro b/examples/network/networkprotocol/networkprotocol.pro
new file mode 100644
index 0000000..1c6ea07
--- /dev/null
+++ b/examples/network/networkprotocol/networkprotocol.pro
@@ -0,0 +1,10 @@
+TEMPLATE = app
+TARGET = networkprotocol
+
+CONFIG += qt warn_on release
+
+REQUIRES = network full-config
+
+HEADERS = nntp.h view.h
+SOURCES = main.cpp \
+ nntp.cpp view.cpp
diff --git a/examples/network/networkprotocol/nntp.cpp b/examples/network/networkprotocol/nntp.cpp
new file mode 100644
index 0000000..1307b9b
--- /dev/null
+++ b/examples/network/networkprotocol/nntp.cpp
@@ -0,0 +1,256 @@
+/****************************************************************************
+**
+** Copyright (C) 1992-2008 Trolltech ASA. All rights reserved.
+**
+** This file is part of an example program for Qt. This example
+** program may be used, distributed and modified without limitation.
+**
+*****************************************************************************/
+
+#include "nntp.h"
+#include <qurlinfo.h>
+#include <stdlib.h>
+#include <qurloperator.h>
+#include <qstringlist.h>
+#include <qregexp.h>
+
+Nntp::Nntp()
+ : QNetworkProtocol(), connectionReady( FALSE ),
+ readGroups( FALSE ), readArticle( FALSE )
+{
+ // create the command socket and connect to its signals
+ commandSocket = new QSocket( this );
+ connect( commandSocket, SIGNAL( hostFound() ),
+ this, SLOT( hostFound() ) );
+ connect( commandSocket, SIGNAL( connected() ),
+ this, SLOT( connected() ) );
+ connect( commandSocket, SIGNAL( connectionClosed() ),
+ this, SLOT( closed() ) );
+ connect( commandSocket, SIGNAL( readyRead() ),
+ this, SLOT( readyRead() ) );
+ connect( commandSocket, SIGNAL( error( int ) ),
+ this, SLOT( error( int ) ) );
+}
+
+Nntp::~Nntp()
+{
+ close();
+ delete commandSocket;
+}
+
+void Nntp::operationListChildren( QNetworkOperation * )
+{
+ // create a command
+ QString path = url()->path(), cmd;
+ if ( path.isEmpty() || path == "/" ) {
+ // if the path is empty or we are in the root dir,
+ // we want to read the list of available newsgroups
+ cmd = "list newsgroups\r\n";
+ } else if ( url()->isDir() ) {
+ // if the path is a directory (in our case a news group)
+ // we want to list the articles of this group
+ path = path.replace( "/", "" );
+ cmd = "listgroup " + path + "\r\n";
+ } else
+ return;
+
+ // write the command to the socket
+ commandSocket->writeBlock( cmd.latin1(), cmd.length() );
+ readGroups = TRUE;
+}
+
+void Nntp::operationGet( QNetworkOperation *op )
+{
+ // get the dirPath of the URL (this is our news group)
+ // and the filename (which is the article we want to read)
+ QUrl u( op->arg( 0 ) );
+ QString dirPath = u.dirPath(), file = u.fileName();
+ dirPath = dirPath.replace( "/", "" );
+
+ // go to the group in which the article is
+ QString cmd;
+ cmd = "group " + dirPath + "\r\n";
+ commandSocket->writeBlock( cmd.latin1(), cmd.length() );
+
+ // read the head of the article
+ cmd = "article " + file + "\r\n";
+ commandSocket->writeBlock( cmd.latin1(), cmd.length() );
+ readArticle = TRUE;
+}
+
+bool Nntp::checkConnection( QNetworkOperation * )
+{
+ // we are connected, return TRUE
+ if ( commandSocket->isOpen() && connectionReady )
+ return TRUE;
+
+ // seems that there is no chance to connect
+ if ( commandSocket->isOpen() )
+ return FALSE;
+
+ // don't call connectToHost() if we are already trying to connect
+ if ( commandSocket->state() == QSocket::Connecting )
+ return FALSE;
+
+ // start connecting
+ connectionReady = FALSE;
+ commandSocket->connectToHost( url()->host(),
+ url()->port() != -1 ? url()->port() : 119 );
+ return FALSE;
+}
+
+void Nntp::close()
+{
+ // close the command socket
+ if ( commandSocket->isOpen() ) {
+ commandSocket->writeBlock( "quit\r\n", strlen( "quit\r\n" ) );
+ commandSocket->close();
+ }
+}
+
+int Nntp::supportedOperations() const
+{
+ // we only support listing children and getting data
+ return OpListChildren | OpGet;
+}
+
+void Nntp::hostFound()
+{
+ if ( url() )
+ emit connectionStateChanged( ConHostFound, tr( "Host %1 found" ).arg( url()->host() ) );
+ else
+ emit connectionStateChanged( ConHostFound, tr( "Host found" ) );
+}
+
+void Nntp::connected()
+{
+ if ( url() )
+ emit connectionStateChanged( ConConnected, tr( "Connected to host %1" ).arg( url()->host() ) );
+ else
+ emit connectionStateChanged( ConConnected, tr( "Connected to host" ) );
+}
+
+void Nntp::closed()
+{
+ if ( url() )
+ emit connectionStateChanged( ConClosed, tr( "Connection to %1 closed" ).arg( url()->host() ) );
+ else
+ emit connectionStateChanged( ConClosed, tr( "Connection closed" ) );
+}
+
+void Nntp::readyRead()
+{
+ // new data arrived on the command socket
+
+ // of we should read the list of available groups, let's do so
+ if ( readGroups ) {
+ parseGroups();
+ return;
+ }
+
+ // of we should read an article, let's do so
+ if ( readArticle ) {
+ parseArticle();
+ return;
+ }
+
+ // read the new data from the socket
+ QCString s;
+ s.resize( commandSocket->bytesAvailable() + 1 );
+ commandSocket->readBlock( s.data(), commandSocket->bytesAvailable() );
+
+ if ( !url() )
+ return;
+
+ // of the code of the server response was 200, we know that the
+ // server is ready to get commands from us now
+ if ( s.left( 3 ) == "200" )
+ connectionReady = TRUE;
+}
+
+void Nntp::parseGroups()
+{
+ if ( !commandSocket->canReadLine() )
+ return;
+
+ // read one line after the other
+ while ( commandSocket->canReadLine() ) {
+ QString s = commandSocket->readLine();
+
+ // if the line starts with a dot, all groups or articles have been listed,
+ // so we finished processing the listChildren() command
+ if ( s[ 0 ] == '.' ) {
+ readGroups = FALSE;
+ operationInProgress()->setState( StDone );
+ emit finished( operationInProgress() );
+ return;
+ }
+
+ // if the code of the server response is 215 or 211
+ // the next line will be the first group or article (depending on what we read).
+ // So let others know that we start reading now...
+ if ( s.left( 3 ) == "215" || s.left( 3 ) == "211" ) {
+ operationInProgress()->setState( StInProgress );
+ emit start( operationInProgress() );
+ continue;
+ }
+
+ // parse the line and create a QUrlInfo object
+ // which describes the child (group or article)
+ bool tab = s.find( '\t' ) != -1;
+ QString group = s.mid( 0, s.find( tab ? '\t' : ' ' ) );
+ QUrlInfo inf;
+ inf.setName( group );
+ QString path = url()->path();
+ inf.setDir( path.isEmpty() || path == "/" );
+ inf.setSymLink( FALSE );
+ inf.setFile( !inf.isDir() );
+ inf.setWritable( FALSE );
+ inf.setReadable( TRUE );
+
+ // let others know about our new child
+ emit newChild( inf, operationInProgress() );
+ }
+
+}
+
+void Nntp::parseArticle()
+{
+ if ( !commandSocket->canReadLine() )
+ return;
+
+ // read an article one line after the other
+ while ( commandSocket->canReadLine() ) {
+ QString s = commandSocket->readLine();
+
+ // if the line starts with a dot, we finished reading something
+ if ( s[ 0 ] == '.' ) {
+ readArticle = FALSE;
+ operationInProgress()->setState( StDone );
+ emit finished( operationInProgress() );
+ return;
+ }
+
+ if ( s.right( 1 ) == "\n" )
+ s.remove( s.length() - 1, 1 );
+
+ // emit the new data of the article which we read
+ emit data( QCString( s.ascii() ), operationInProgress() );
+ }
+}
+
+void Nntp::error( int code )
+{
+ if ( code == QSocket::ErrHostNotFound ||
+ code == QSocket::ErrConnectionRefused ) {
+ // this signal is called if connecting to the server failed
+ if ( operationInProgress() ) {
+ QString msg = tr( "Host not found or couldn't connect to: \n" + url()->host() );
+ operationInProgress()->setState( StFailed );
+ operationInProgress()->setProtocolDetail( msg );
+ operationInProgress()->setErrorCode( (int)ErrHostNotFound );
+ clearOperationQueue();
+ emit finished( operationInProgress() );
+ }
+ }
+}
diff --git a/examples/network/networkprotocol/nntp.h b/examples/network/networkprotocol/nntp.h
new file mode 100644
index 0000000..82a8142
--- /dev/null
+++ b/examples/network/networkprotocol/nntp.h
@@ -0,0 +1,49 @@
+/****************************************************************************
+**
+** Copyright (C) 1992-2008 Trolltech ASA. All rights reserved.
+**
+** This file is part of an example program for Qt. This example
+** program may be used, distributed and modified without limitation.
+**
+*****************************************************************************/
+
+#ifndef NNTP_H
+#define NNTP_H
+
+#include <qsocket.h>
+#include <qnetworkprotocol.h>
+
+class Nntp : public QNetworkProtocol
+{
+ Q_OBJECT
+
+public:
+ Nntp();
+ virtual ~Nntp();
+ virtual int supportedOperations() const;
+
+protected:
+ virtual void operationListChildren( QNetworkOperation *op );
+ virtual void operationGet( QNetworkOperation *op );
+
+ QSocket *commandSocket;
+ bool connectionReady;
+ bool readGroups;
+ bool readArticle;
+
+private:
+ bool checkConnection( QNetworkOperation *op );
+ void close();
+ void parseGroups();
+ void parseArticle();
+
+protected slots:
+ void hostFound();
+ void connected();
+ void closed();
+ void readyRead();
+ void error( int );
+
+};
+
+#endif
diff --git a/examples/network/networkprotocol/view.cpp b/examples/network/networkprotocol/view.cpp
new file mode 100644
index 0000000..fed5bdf
--- /dev/null
+++ b/examples/network/networkprotocol/view.cpp
@@ -0,0 +1,90 @@
+/****************************************************************************
+**
+** Copyright (C) 1992-2008 Trolltech ASA. All rights reserved.
+**
+** This file is part of an example program for Qt. This example
+** program may be used, distributed and modified without limitation.
+**
+*****************************************************************************/
+
+#include "view.h"
+
+#include <qlabel.h>
+#include <qpushbutton.h>
+#include <qmultilineedit.h>
+#include <qfiledialog.h>
+
+View::View()
+ : QVBox()
+{
+ // setup the GUI
+ setSpacing( 5 );
+ setMargin( 5 );
+
+ QLabel *l = new QLabel( this );
+ l->setAlignment( Qt::WordBreak ),
+ l->setText( tr( "The button below opens the QFileDialog and you "
+ "can choose a file then which is downloaded and "
+ "opened below then. You can use for that the <b>local "
+ "filesystem</b> using the file protocol, you can download "
+ "files from an <b>FTP</b> server using the ftp protocol and "
+ "you can download and open <b>USENET</b> articles using the "
+ "demo implementation of the nntp protocol of this "
+ "example (<i>This implementation of the nntp protocol is a very "
+ "basic and incomplete one, so you need to connect to a news server "
+ "which allows reading without authentification</i>)\n"
+ "To open a file from the local filesystem, enter in the "
+ "path combobox of the file dialog a url starting with file "
+ "(like <u>file:/usr/bin</u>), to download something from an FTP "
+ "server, use something like <u>ftp://ftp.trolltech.com</u> as url, and "
+ "for downloading a news article start with an url like "
+ "<u>nntp://news.tu-graz.ac.at</u> " ) );
+ QPushButton *b = new QPushButton( tr( "Open a file..." ), this );
+ connect( b, SIGNAL( clicked() ),
+ this, SLOT( downloadFile() ) );
+
+ fileView = new QMultiLineEdit( this );
+ fileView->setReadOnly( TRUE );
+
+ // if new data comes in, display it
+ connect( &op, SIGNAL( data( const QByteArray &, QNetworkOperation * ) ),
+ this, SLOT( newData( const QByteArray & ) ) );
+}
+
+void View::downloadFile()
+{
+ // QString file = QFileDialog::getOpenFileName();
+ // under Windows you must not use the native file dialog
+ QString file = getOpenFileName();
+ if ( !file.isEmpty() ) {
+ // clear the view
+ fileView->clear();
+
+ // download the data
+ op = file;
+ op.get();
+ }
+}
+
+QString View::getOpenFileName()
+{
+ static QString workingDirectory = QDir::currentDirPath();
+
+ QFileDialog *dlg = new QFileDialog( workingDirectory,
+ QString::null, 0, 0, TRUE );
+ dlg->setCaption( QFileDialog::tr( "Open" ) );
+ dlg->setMode( QFileDialog::ExistingFile );
+ QString result;
+ if ( dlg->exec() == QDialog::Accepted ) {
+ result = dlg->selectedFile();
+ workingDirectory = dlg->url();
+ }
+ delete dlg;
+ return result;
+}
+
+void View::newData( const QByteArray &ba )
+{
+ // append new data
+ fileView->append( ba );
+}
diff --git a/examples/network/networkprotocol/view.h b/examples/network/networkprotocol/view.h
new file mode 100644
index 0000000..9baba75
--- /dev/null
+++ b/examples/network/networkprotocol/view.h
@@ -0,0 +1,37 @@
+/****************************************************************************
+**
+** Copyright (C) 1992-2008 Trolltech ASA. All rights reserved.
+**
+** This file is part of an example program for Qt. This example
+** program may be used, distributed and modified without limitation.
+**
+*****************************************************************************/
+
+#ifndef VIEW_H
+#define VIEW_H
+
+#include <qvbox.h>
+#include <qcstring.h>
+#include <qurloperator.h>
+
+class QMultiLineEdit;
+
+class View : public QVBox
+{
+ Q_OBJECT
+
+public:
+ View();
+
+private slots:
+ void downloadFile();
+ void newData( const QByteArray &ba );
+
+private:
+ QMultiLineEdit *fileView;
+ QUrlOperator op;
+
+ QString getOpenFileName();
+};
+
+#endif
diff --git a/examples/network/remotecontrol/ipcserver.cpp b/examples/network/remotecontrol/ipcserver.cpp
new file mode 100644
index 0000000..f83f8a2
--- /dev/null
+++ b/examples/network/remotecontrol/ipcserver.cpp
@@ -0,0 +1,84 @@
+#include "ipcserver.h"
+
+#include <qsocket.h>
+#include <qvariant.h>
+#include <qimage.h>
+#include <qpalette.h>
+#include <qapplication.h>
+
+class IpcSocket : public QSocket
+{
+ Q_OBJECT
+
+public:
+ IpcSocket( QObject *parent) : QSocket( parent )
+ {
+ packetSize = 0;
+ connect( this, SIGNAL(readyRead()), SLOT(read()) );
+ }
+
+signals:
+ void receivedText( const QString& );
+ void receivedPixmap( const QPixmap& );
+
+private slots:
+ void read()
+ {
+ Q_ULONG bytesAvail = bytesAvailable();
+ for ( ;; ) {
+ if ( packetSize == 0 ) {
+ QDataStream ds( this );
+ if ( bytesAvail < 4 )
+ return;
+ ds >> packetSize;
+ bytesAvail -= 4;
+ } else {
+ if ( bytesAvail < packetSize )
+ return;
+ // read the packet in a byte array to be sure that you don't
+ // read too much or too less
+ QByteArray ba( packetSize );
+ readBlock( ba.data(), packetSize );
+ bytesAvail -= packetSize;
+ packetSize = 0;
+
+ QVariant variant;
+ QDataStream ds( ba, IO_ReadOnly );
+ ds >> variant;
+ switch ( variant.type() ) {
+ case QVariant::String:
+ emit receivedText( variant.toString() );
+ break;
+ case QVariant::Image:
+ emit receivedPixmap( QPixmap(variant.toImage()) );
+ break;
+ case QVariant::Palette:
+ QApplication::setPalette( variant.toPalette(), TRUE );
+ break;
+ default:
+ break;
+ }
+ }
+ }
+ }
+
+private:
+ Q_UINT32 packetSize;
+};
+
+IpcServer::IpcServer( Q_UINT16 port, QObject *parent ) :
+ QServerSocket( 0x7f000001, port, 1, parent )
+{
+}
+
+void IpcServer::newConnection( int socket )
+{
+ IpcSocket *s = new IpcSocket( this );
+ s->setSocket( socket );
+ connect( s, SIGNAL(receivedText(const QString&)),
+ SIGNAL(receivedText(const QString&)) );
+ connect( s, SIGNAL(receivedPixmap(const QPixmap&)),
+ SIGNAL(receivedPixmap(const QPixmap&)) );
+}
+
+#include "ipcserver.moc"
diff --git a/examples/network/remotecontrol/ipcserver.h b/examples/network/remotecontrol/ipcserver.h
new file mode 100644
index 0000000..2dc2515
--- /dev/null
+++ b/examples/network/remotecontrol/ipcserver.h
@@ -0,0 +1,20 @@
+#ifndef IPCSERVER_H
+#define IPCSERVER_H
+
+#include <qserversocket.h>
+
+class IpcServer : public QServerSocket
+{
+ Q_OBJECT
+
+public:
+ IpcServer( Q_UINT16 port, QObject *parent );
+
+ void newConnection( int socket );
+
+signals:
+ void receivedText( const QString& );
+ void receivedPixmap( const QPixmap& );
+};
+
+#endif // IPCSERVER_H
diff --git a/examples/network/remotecontrol/main.cpp b/examples/network/remotecontrol/main.cpp
new file mode 100644
index 0000000..563fe8c
--- /dev/null
+++ b/examples/network/remotecontrol/main.cpp
@@ -0,0 +1,11 @@
+#include <qapplication.h>
+
+#include "startup.h"
+
+int main( int argc, char **argv )
+{
+ QApplication a( argc, argv );
+ StartUp s;
+ QObject::connect( &a, SIGNAL(lastWindowClosed()), &a, SLOT(quit()) );
+ return a.exec();
+}
diff --git a/examples/network/remotecontrol/maindialog.ui b/examples/network/remotecontrol/maindialog.ui
new file mode 100644
index 0000000..bd1c619
--- /dev/null
+++ b/examples/network/remotecontrol/maindialog.ui
@@ -0,0 +1,165 @@
+<!DOCTYPE UI><UI version="3.0" stdsetdef="1">
+<class>MainDialog</class>
+<widget class="QDialog">
+ <property name="name">
+ <cstring>MainDialog</cstring>
+ </property>
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>273</width>
+ <height>263</height>
+ </rect>
+ </property>
+ <property name="caption">
+ <string>Image viewer</string>
+ </property>
+ <property name="sizeGripEnabled">
+ <bool>true</bool>
+ </property>
+ <vbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <property name="margin">
+ <number>11</number>
+ </property>
+ <property name="spacing">
+ <number>6</number>
+ </property>
+ <widget class="QLabel">
+ <property name="name">
+ <cstring>TextLabel2</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>5</hsizetype>
+ <vsizetype>5</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="frameShape">
+ <enum>MShape</enum>
+ </property>
+ <property name="text">
+ <string>If you start another instance of this application, you can use that instance to control this one.</string>
+ </property>
+ <property name="alignment">
+ <set>WordBreak|AlignCenter</set>
+ </property>
+ </widget>
+ <widget class="QLabel">
+ <property name="name">
+ <cstring>image</cstring>
+ </property>
+ <property name="pixmap">
+ <pixmap>image0</pixmap>
+ </property>
+ <property name="scaledContents">
+ <bool>false</bool>
+ </property>
+ <property name="alignment">
+ <set>AlignCenter</set>
+ </property>
+ </widget>
+ <widget class="QLabel">
+ <property name="name">
+ <cstring>description</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>5</hsizetype>
+ <vsizetype>0</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="font">
+ <font>
+ <pointsize>26</pointsize>
+ </font>
+ </property>
+ <property name="text">
+ <string>The Qt logo</string>
+ </property>
+ <property name="alignment">
+ <set>AlignCenter</set>
+ </property>
+ </widget>
+ <spacer>
+ <property name="name" stdset="0">
+ <cstring>Spacer2_2</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Vertical</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Expanding</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>20</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ <widget class="QLayoutWidget">
+ <property name="name">
+ <cstring>Layout2</cstring>
+ </property>
+ <hbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <property name="margin">
+ <number>0</number>
+ </property>
+ <property name="spacing">
+ <number>6</number>
+ </property>
+ <spacer>
+ <property name="name" stdset="0">
+ <cstring>Spacer2</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Horizontal</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Expanding</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>20</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ <widget class="QPushButton">
+ <property name="name">
+ <cstring>PushButton1</cstring>
+ </property>
+ <property name="text">
+ <string>Quit</string>
+ </property>
+ </widget>
+ </hbox>
+ </widget>
+ </vbox>
+</widget>
+<images>
+ <image name="image0">
+ <data format="XPM.GZ" length="55092">789cccbd47b7eb38b2ef397f9fa2d6e5ecae5e7cf266d0035266cb6da7ed77af1ed07b2f1aa9bf7c83883f704c56d5cd7c75bb5f95d6c9ca5f8a22114044202200f0fccffffcdbe7d3fddffef37ffe8fea625c02eb6f966f947ffb4fbb4e92ebfff57fff9fffcffff88fe160f0b7fecf68389bfe6df41fffc7fff80febf96fd6df9401ff5fcff64232ffde36244f7a762ac953fefd56f29cf35cf2a267f3072ff9f733c906e7836493f35eb2c59fd74ab6797b1f243bfcfb46b2cb7fef0a1e72799c5af2907f7f94cce5732cc963fefd483297cf3a8387d43f992999ffde0c25f3dfb79a64de5f662099dfcfe924cf386f24f3fe4a44ff0fd17e5b327f9e772799dfcfb8078fa87d662499cbebbb9249de6fc9bcbd9d2f99dab795ccc7b31a48e6e3b71a4ae6e315ed25f3f1b04f82a93f0dc1636a9ff32999daf32599f757a54ae6fde17e48e6fae23892b97e78a2bd63ea1f438cef849e97e892f9f7652b99b76f3d91cce53763f0947e6f08fd9c1137b664de5e43c83fc7f53bf0022cf475499c8be719c4f113d824de5cc01671fd0eb6895dbaff50d8ab174ae6f2ad3ac9a47f63c924df4832d73f732a99f777f324998fb73993ccfb5f7f96ccc7df3a49e6e3514592b9bd3aa664ae1fd6bd646eaf9a2b98f4ddf52573fdb58e60d89f6d49e6df9b13c97c3c1d45326fbf634826ffb2934cfee40086fdf88164de7ff65232d9eb9b646e1fa607867e9bbe641a8f816092cf14f2423f4d070c7d8b9f25f3e7bbaf60e89fb791ccfb3b15df43ffe22f30f42f13f240ffea1b18fab716bf877ee967b043dc92bf1f0ea16fdd9af3a8f740bc3dbe64f2f70bc9bcbfcd2fc9bcbfbd4432f90b4730f5cff55e3297bfc9c0187f732899f4772099c6e35b321f7f6b0fc6f8daa6649aff7692f9f3724d32d7f7cb4932ef6ffb4e32e9b302c6f86723c9dcdefc50326f9ff32e99f7975382a10fd75c32d7e795906742fdd3bd49e6df67a2bdd09ff20886beb89164fefcd54932ef9ffa2c98fca72bda0b7d6a9f25f3feb0c4f842bf9a07b0d02fd13fd0afe2090cffd6c660e85b24ae87be05a40f63e1df8277c9bc7debab643e5e575732efef6e2799cb1bfcf89ecbdbed2573fd5cfd781e1fcf952d98fa3b91cf277f74cd24f3fe0f3ec08807ba8d64ae9fc54232e98f27993faff9f13df787ae680ff4d57995cce57103c95c7fac3bc97c7c7c5f308d67b8028bf9f72299cbd3dc49e6f2981f92797fd69664de5f7e2499dbb33b92ccdb6f2dc1d067772099fca72e99b7ff6a49a6f946f437f4b9bd48267934b0d0ef77c9bc7dad68df9cee9fee25f3fe69447fcc31df88f1843eaf6e92f9f3da89649a0fee25f3f1cb85be41ff0331bed07f5f8ca7f0a7d43f13a1df9d2a99f777f32899dfffea80111faeae92b93cee41f090f7effa0c463ce77f48a6f9ee51321fafeb4930f547bb01433fecb164fe7cff5b321f2f2f92ccfb3f93d793bd745b30f421ae2593bfd94be6fd1b2692b93cde4e32b79fda164ced8ddec1d017e74332f9dbb564de5e772899e299140c7dcaa692b93db8df92797fe61d18fe3117e303fd59b792e979b164de3f8918ff05f5cf46f40ff4c715e301fdb9bd80e13f57f792797fad4a30fce906bf17f3f51ae331c4fc19a13d43f89780e693a9f0a7ed028cebfd4e321fafe6198c7cc00b2473f9bc77c95cdf4a4ff0908fc75a5c8f78bfb52553fcf02999ebbfdf08a6f10e5ec1c2bfdc49a6f97c2b99e6ff27c9642f3fbee7fab416f2407fc299643efe912f99ec692099cbd3b492b9bc9ab8ff94c63711fd0bfdb2a792c93e2ac9140f689229df5125f3feed5660e85ffd2a99fce34432efdfee00867e5e14c9941f8ec0d0bfcc904cf9572a99b7a76e25f3fe73c760a1afaa646ebf99e85fe86f2ec61bfaea0b79e11f0ba12f2eda8bfb4b7d267b98897c64dd81a1cfeb503297afbd934cf1d45e30fc93f81ef363b896ccefbf3a4a26793dc1149fae7d30f247ff2a99ea1d3fbee7fed68b05a31eb1924cf9c2083ca5f6076bc9542fd948e6fa900e2473fdbbbc09463d630246be1a6692f9f84481643edef95532b73f5df01cfd7993ccdb7be92453beb5924cf3c14432efbf5cfc7e01fffa2999e6bfb1646e5f9b022ce2cba364de3e37114cfec132c0d047f74d32f9e37b30f26b2f05431f5763c9bc7f42c1d04797e6cf99d0c71be41fc21fa52a18fe24207d9f0bfd5a1d04d3f8570fe009d573dca3642e7fbb054f697ca237c1246f3a944cf53a5b32c5a72f60f81bd796ccaf4f2bc994af2d2593be6f2453bea682e7345eed4e32d5ff14c9bcbf2f57c95cff7dd15ef8a35097ccdb93cd25537e2bfa6b3124fffd055ec2bfcc24537c548045fe518331decda7647ebd2eda6ba37fc478c01f6d44ffb8d43e1ded17e3af3960cc97f5022cf481e257a6dd149fd96bf08cc6ffe64aa6f92604c35eec4032b7efab2799e2375b30e94b2aae5f50ff58aa642e6fe148a67ce1065e927fb80d2553bd2494cc9fdf3e49a6fc45c863c07e1dc97cfcd3a3606a5f7d05633e887682497faf4bb08df8e2030cfb2bc9de17a2ff4bf49f886762f4cf10f666bd80618f3e8dff92f5177f5e914be6ed2f36e005c91b5f24533cf22598ecafeec04be467ae64f28757b041bfaf5f040f29fe68c0268d9726da63917e14a2bdd0c7f424998f5f44fdb314fd91bf83a18f8105467fdc4660e86783e789fee94a30e215e3118c78a3a0f9dc60fd45fa34072f491fc329d8a0f685a964aae7dfc0265d5f2f05537f568f60d86bb091ccfbe36248e6fad988dfbba85f8e24533e48f66f88fe892b30fa67634ba6f97508467f6d1cb0a827435ed11f35fa6388f9c9a7f8c814f157fd065e92fe5f6e6083e42f5cb0897ac417d8227dca3fc036f55fb305431fba77c1747f3b02bba4df3ad9ab29e42f669229df46fb647fe460d8d3aa0243fecd2758d4bbefc0a21eb403a33f2a8a772c263f6fff35055ba827d1f85aa2bf2f1a58f4f70a8cfb252a18febdf1c0f02701f58f2dda7f5d48a6fe9b8071fff21d2cfc83603caf51c1b87fb106433f4b1a1f87fd17eebf1b17ec903efbd43e46b0f71a0c79cb2d58c4e72d18cf2f1bb078be0dc6f3339abf5cd11f8906c6f5de1a8cf846e3f6c1cbe724df068cf6548964ae3f1b130c7f9096608c7f7603a3bde90e8ce7bb2f60b4d77e00c39f075c9f98f639e47fa34832d7e7f84c2c9eb7ba80216ffb08c6f3cc042cd64f1a30e42f9760d88fe382d19e1ced19c11e42aebf0cf17cd306435ecb04a33d610e16f20b16f1470a16ed3981457cf9443c82bdae2660e19f79bc341c8be7d70e18cfd71ec022df8ac178feaa05e379d72bf108e3df70ff369cc8fe1d8345bc9c81d1fe60452cfaeb7a03c3be74ba7e2adbd382f1fbcb3b18e3910dc1689f4df24e657fd4603cafb2c168bffb0cc6f32b1ebf0c67e2fe01e9d34cdcef1283e12faa6f30ee67f860e1ffe660a1efdc7f0ee7e2fed58c58b6e70cc6ef8d002cd6173db0a83f2dc0d0b78edbf77021e5bd078bf6aec1f87d41fabd14f2155bb0f8fd108cdfeb2330da93de83f1fc8ac6d310f2ac1a309ed772ff3734c5fdb48d64ee0fb72e58d4e75ec0f87d7202a33f0d713df4a5237bb7e4782a60b11ee681d15eed112cee1782a1cf158f4f86b6b8bf6581c5fa2af5a733823f762d30eed7d2efdd11f2efcd1d18d76bdc5e468311f2a3c007e379f5082cea75f760e8fbfa8d782cf49dfba3d150fcbebc030b7bdc83a17f099faf472371ffe64c2ceed73460e883cefb6b3416f7ab4fc463e10f2c30e46b8927e279b94b2cee6f6cc1d087ec092cec4930c6f342f24f85fc46442caef75660e8cf85fb93d18cfd9ec783f1162ceaa37cfe19cdc5fd3ceabfb990d79d80d13eeb152cd64fe9fa85f8de7c05a33df9188cf66cbec0d0c7f50d0c7df3b8ff1f2d85bcce002ce227078ceb1d0f2cfca54e3c41fb6f74bd21ef5780f17c5d058bf53beeaf46e618ebd77a2299c77f5bba9f25c6b7f4c1c2bfbd80d19eeb07f104fda1933cb678de2603e37eba01c6ef6f57b0a8ff71ff3d72c6a8b7e8d47faee88fb507c6effd188cdf3bdc1ec67d38c739e2e3c5a63393e21723269e60fde4f22c99d677b93e307577285eb7b8fd8f27ecfe9cf50e0c7d8a79ff8ca7ec7bfefb6b412cc627db81c57e823730ead9eb1158d43fb8bce399b8fe7a0716eb5d7330c663c3fb733c67eda1fa484d2cc6c39a83a11fed193ca57a651282b13e16f3f96ebc9860bdc8d880c5fe810c2cf21bae8fe3e544d4cb23c93c5ed30a30ea071b170cff92d0f81813d443d71730eaed9a07c6f53eb7b7b1c9bee7fa117c49a6f5024b30c5b3760cb6b19ec9e3adb13331e8face93ccfbaf3883f13c23013ba8a72e05d3fd0d1b8c7c734df23b53d8df86facf9da03e7e1b80f1fc82f7e76430813e6d63e229fa3be5e333194e4cd40b52b04ded31b8fe4e4653110ff2fa0a73a736f28d9a788afd67fa180cfd6a1db0588fe3fe7f32610accfb77c3f59721f2c77c493cc5fe0aaf00e37eb731788afa4e059ed1f8361f60d48f6dde1f93d914ebc7460a46bd2fe4fd37994fc7940f6cbec1e89f98cf5f93a578def5013c433d86da6f4c51bf09b9bd4dcce982f2b39cebcbc49a22fff6b83e4dec29ea15d95932adb704c433acffebf43c776ad1fd039d7886f5d315bf3f5356f09acf77d3d1d4a5fa65734f3cc3fe035d134cf7372c30ec355b824dc413dc3fb0e9906574dcdf79c4e2f74501c6fa5b74104cdfb73c3e9d4ea6d6887f7fdb10b3e791bef1f9940ddf1ceb078fe005f5b7c5e7e3e96c86f58f8d0246fd3a76c1f311f9b377b043e31bf07c693a9fa1de19df816dec07f804bb584fa3fe5accc47a86069e517b82002cd6f775b043f39bc6e3dde9923d8eeb7332035bd47f3705ec60ff824d3cc7fecf84ebefd498c19e2faf609bfa2be6f9f0d49c2d51cff5c016e5fb2b176c8f78fb8b15d8a5fa99c9e7d7a93543fdab1b831dfafde6287844f5d10e8cf1af49bfac39c63bff024f499e98ee6fb3fb937f7d023bd4fed407bb435aafb124d37e2d5d30b53f03cf87d43eeb0d8cf5dd7803c67cb7e1f63d75587f707df1e9fece7c30a2fd5d7b30f6b3469f9269fdc792cce5594dc1587fba52ffb84c1edebecd5e326f7f41faebceb19f2cda8271bfa6133ca2e727e0118d4fb2164cfa9c2892f978af4c30eca1f1c19321d7bf2bff7e3660e34ff5e53bb043cfaf5dc174bf6c0076a97fdb929805acfcfb6d0446bdbee4ed9f0d857eddd660f89b6e2298da5f05c4ac3f687e6bc0c311ad87e07a263f9f0fda77f094da537f8067245fc5f569369a1963d29f2b31eb5fdabfe20ba6e7a777e0d188ff3eb9815906c29fa78227d04f053ca3f6b65c3f6663260fd553a93d2cfca4fec91bc95cfeea041e517f5fb8fece2662fcdd023c86ff33c1d31167cd06cf21cf5c308d679d8017d41f0df72fb3e9cc1ef3ebab14ec8c69bfc05432ed47d38885fe5d4cc9b4fe37028fc8fecb37c9649f25784cf6ebbf82e7f47dbc042fe87e05f5cf4ce8936b82e7f4fb36113ca6f17a002fe8f986b8de80fe8bef4dd28fc292cce52fa68269fc4d1effb0db2f49decd0c0c7fdc92fe2ce6131a3f6d2d98fcb7bf02cf49bf370330d68fea5a30fdde38831dfabea3fe59b2fea178b0009bd41e4f03db23aeff37713decb5f00593fc2df5a7c1ee47eb6f2330eadd17156c8ea87ff7609bfc45590b267f78d5c02e714bfa6ab2f1207ff80136c87ef22918f34dfe06c67cd186c48b018dafcee3cd99c5ee47faa48217647f99609bf4c7a0f1b2160392afa3f6da6cfc68bcd69279ff949f6093daef4ec1f067f5817831a4e76de8f70ebb9ece177c806d6abfb3235ec0dfba2bc9b4df9bc6d7ed1376ae5f5c3fe703263f6f4f520a1e53fc99102f66d4be8cf7cf7cc8e4e3d7673e784c7cdd82a7d4de5a03c3fe751e9f3265c2fca09be009d94fc2e397394b87c99f186bf08cfa4fe3fd3b9fb0e7717dacc792e97c0b8f5f58f8bb20d6793d613e5f2cc7b49fc5005bd49e35b56fb1c4fcecf1fe9e2fd9f7743dfdde582ca83f8267b049ed59f3f9686eb2eb69fd782699d62fa83de67244f67de1fa3eb79643b237ef2698f4ab9e8347d4feb0008fc99e1c6a8fbd70d05f4762261e6f9f46e3e730a6f3160618fdbbe6f9c6dc5d0ea8bd0df5bf6b88f89aebdfa25f00a5f8ff4e32edd749c0636aff66019ee17939780e7de2f92a73f643e8bb031e537b7c133c237bf5dec073ba7f44f71f1a225ea3e78f447f79dfe011ddcfe3f22dc68c29feff06e379ba0e9ed2ef0b1effb1747d44f3b1fd0d5ed2f78d0236c65cdf367c7e5fb0009858bf07cfd15f7bf082f4a3492473f96f19d8257b6df8f82e66cb05f55fbe223630ff6f797cbc98b3f67079527afe82319d17e1f6b7581a03fafdc693ccc7d7a0fb194b97da7bbb111b63f2af1bae9f0bd31810eb7cbd61612d1dd2bf94da671943c8cfe7af856d8c69be6e0563be594f2573fdd7b8bd2c1c763ded0f53c01392c7bb4ae6fdd3717d5db8c684fa4bbb134cdfa767f094e28180fba3e5c080fff15fc0b309f5ef9764d24ff13dfc43cae7a3e5d0807d6cf8782d47acbdfcfeed0b783ea1fad50ebca0ef6f3ed82079a32f30f2c5644f6c627f5acce7df655fd0e1e3930460a662dc3f1cc14beaaf40133ca178a8069bf47cdf90ccc74ff3c10e8de78dfa676c8afd09b564daff5982b1ff36a6f64c58ffd2fed40b7836a1fac504bc9c50fd6101c6fc97abc426e2b3700fc67911f3018cf33ac99d643e1edd198cf3176e07463da4fa0063bf8826be47bd53e7fe773965e345fded806db217eb1d8c78f29612b3f6923ea9603cbffb0663bf4949d7b38083c663b3022f68fceb7bb043f6118682a9ff8c02ec92bfcbe9fe7dba49f5c30d18fb636c9e2f2ce7ecf7144f2a6097e4bbe5c4ecf7140fcdc0b0b734018bfde03a784af3c53504cfb15f47dc0ffb0bbb8160ecbffc002fa95e58edc1d8bf1a4dc1163d2f36c1a8575495609c5f1a4aa6f3a134febd83e2ed2f376093faafa3e72fcc01f1f50b3c217ddd5660ac37ad63f00cfe5407cf69beef5230ea35c6026c60bfe55532e55b39d8a4eb6f73b0d8df20ee6f637fe04a32cdff03b043fd757b904cf9d9168c7ae7ed2299ce7b3692697fc898d8c2f99ddb128cf3b317f49f85fa6348f75f1a06d9afb604c37ff817b04dfa1c0ec10ee9bb4ef22ecd015d7fdd8047345eb5079e907e598e60d2d7b40363ffe3762598e2d5750e16e703d692297ffc128cf35768af897afb36108cfaee5c32d56b0f9269fe2e24f3f61731d880ff5125d37ed80558ac974c25d37ec09d64de7fe64132f73fea27d8a2f15732c9b4bea008a6f655a23fb1dfb28c24d3fe470d8c7ae1ed5132e95b2099cf8fa6e82fd4e3c32fc9b4bee3125b38ef7723ff641816d99b7d03dbe48fc22bd8a1f9f95a825d9adf4af28706eb1ede5eaf060fe97aaf133ca1fc5605237e6d8ee009e5bbd5198cf58b4efc1efb6fb71730f67bae66e025c5df8a09c6fecae020998fafd248a6f3ba909fd93b6f4f71025bb0af52329ddf9849e6cf533fc036e993924ba6f96726993f2fcec00ef57ff12e99e2c34a32ed7f0cc1f017d5bb649aef7cc9bc3f22f13c97fa4fc3f859388f5a6d25f3f69443c1d86f3b06e37c4be54ae6edd354c9bc7dd791643aefdc4aa67acf2b18e7f134f13dced325a4ef26d3379affc95f9826e2cb952a99c6f7153ca57835fd0463ff691108267fb579028b78c2001b34dee14532bf7f62814df88b4832d52f2ab085f59d0118eba3752899ecff2699eae307c9b43fb405431f9454329d2fbb97ccdb938cc02ee95b2adaebd2f8b590dfc279e448974ce3f12998e67b4d30ce074713c934ff403e0be72d2dba9fc5e607defeca014fc85f5413f094e2313b954cfea0114cfe467901233fd41792a99e6a49a6f527c198afd71bc9549fb9822dea8fba944cf9502799dad782b17e6d7592c9be6782495fea42321fdff8c7f77cbcb477b043fa1deb9229ff4904e37cc697641a7f0decd27828aa647abfc45032ade7b982495f13b25fcbc2fb0c944032d9cb93606abf5949a6f314cf60bc4fc00a24f3f6b79960d29f5a914cf11dfa53d87bf82999d6df303e16ceb755a4cf369b3fc8ff7660ec3f57de04933ff0f760ac5f665bc114df2b67c1a44f57156c507f5f1cc9b49ff3198cfdc69bab60aac7ac4f601be7fd22c1781fc95132ddaf95ccdbabd492b93e794f60e883229e87fd9ef959326fbf3a964cf9e00318fe5d9d4be6fda192fed916ce83a92f92a93dbe64ca8fd11f229e4c6f92f9f3938164ca1f4f82b1fe994ae6df871f60acf79a6bc9bc7f62f49785f3b1b75230d95775914cf30bfacfc279b22df90f47c413a621995f9f7be011f99b6d2b98e2136d021e4f683d63059e4cb83e7ae2fa19dd4f3b83e734df943118f581f22099cba33c8397549f592dc026d69b8f9279fb6f9f60e453d6156c537f5a63c9644f8160aa47695330fc8dee0aa6e7c5b964f28791648a6fe692297e580aa6fa6628da8bf8c3bc974cf9642118fa38954cf58f89649acf1692e93c27e9936361ffbdd149e6df2b9e609c1f7d96ccf549ad24d37974e887d0676721998f8fba924cf1fa9364b247713df687754f92e9fc672399ea45a23d581f35af92f9f7b9f81eef13885ac1181f4b32d5dfa10f16f6a3044bc974dee9158cfd3f892399fcbb2d993fff26fa6786fd3ba23f711ef146d7bbcc7e283f7b944ce7995ec0639aafab25784af671db0a9e52feb200cfc9fe320f2cec650f5e52beae7d49a6f319e2fe4bd457766083f453bf80b11fa878154cf6b2adc1585f37c4fde0af235530f251717fc45b9e90d7c17ca848a67add5530ad1f74a160aa8f76e279c8e7c34630f97f3b174cf2379a645abf247fe35a781f90ff2818f3c1443297571d49a67cfd4930cd87da1b58e8ff5630ece74b32cd1fa564aaef7982697dc87900633f73694ae6faa0be4aa6fd789a648aa724637fd25a32ed3f79924ceb3d3330f6f325ad64de1fd98364927f2598facbd42553fd3594ccafcf311e16cecbdf22c95c5e652a99de7f267e8ff3c9e1bb641a6f4732bf3efb008bfd812f92297eb32473794b31bec87fa30a2ccea3ee0493ff30f79269bfe23718f53e6b2099ea0377609c7f34be2453fc7b914cf91c1f2f63c0e6478a0fb6e019d58be207c1538aff8fe039e503712b99e6eb5c3297a750c04b1afff22618fb1922c1347fc73bc9b47f4630f2f9eda360b2efab2e98fcd1ea158cfd83452598f47f6b48e6cf8feec1a8b7a40bc1f05f3bc9bcffb61918f596f85d32d5e3447fbaa48ff94030f6ffdc24737bf267c416f6a7ac3f2453fe580bc67e99122cceeb9c24533d6b2299f4ad108cfce30773fd500cc9341f7792a9fe6b0ba6f5da6b2399ce372ec1d85f1d9d25f3efd59b60f89f3bc9bc3fd4a364f22f6f60ec97543792797fa8a960d8c74d32f9932918f61ed49269ff832d99e44d24f3f61a23c1d43f96fc1ef1fe1c8cf763448e645a3f16cfc3fe3d632899e2955832cdafd01f0be7d5ad4a32ad9f3792b9fcc64030ced3d792b93e9723c9b41feb02c6fe67732b99f68b7c4aa6faa3180f9c17f6499ffa032dc46bf098ec5d8f24d3fe08133ca1f530ed049e527eb7f50593ffb83c48a6fd570a7846f7d36b30e6fff25b32d5ab73c1145f28ef82299ed1e660d473b64f92a9def92698fcdd5a3cdf46fd24914cfbcd74c9b43e21e445fda611f7437cb1fe124cf65edcc02edd3f7225d3fb001e05d3fc5ebd108b7879bb93ccfbc72f05937e66a9605abf538e92493f56e021d99f6249a6fa5b2b98fc9f72914cedc3785a789f52f12698e42943c964ef17c9e40fe792697e1849e6f2648e60ac470660bc9f243b4aa6fd3fa1647ebda20826f9d24c32ef0ff55e32d5d7447f60fe2f9f25933f5a4aa6f8e62c18f9502299f40ffa61e1fd4b4a2899f6279492495ed19e29e297028cf795048d64dedef05530e29137c9e47fe4efb19f740cc6fed152134ced0f55c9fcfb488c17dedf74b9934cf64dfa3c326754ffab0cc1643f510ac67a78ba04633e77466083ecb309c026cdffa921998f476582b19fa7ba0aa6f93e5e0ba6fca6188051bf4b447bb1bf4aff00237ff60f92e9fd41f792e9bc7d2599e6f717c1d8cf247e8f7a5d160ba6fecf23c1b4bf21a0f86264e13c72f82499f2fd57c1f06727c954bfcec098df755b30d9ef7a2e98ecdf78974cf54cb447d47b3d5330e2cb0fc9b4df47dc0ffbd12ea9647a9fec1e2cde07f92e99f60b1c05239e3e4ba6f9df974cf9d74932ed9ffff17b2e5f70014f90ef288261df8664b25f5332bd6f0ae36be1fc4ef92499f22d4b3297ff593c0fefb7525dc9e4df3c30de5fa53a9229feb12553bc2ec66f46f2565f92c97f37609ca7b4df25d37e825a32adff89fba39eaafb92293fea24f3ebb7627cb13ebbfd944cfbadbf2453fe37154cf287a664d257d15e715e80fa6fcce673f2af117846f94076075e503d2188c1d88f9a9b82c91f2457c954cf38832df2279ba9647adfe70a8cfaecf62098e2ef6e2699ce27ed04533cb2d5c0d8efaa3c09a6fa46f12199ec5d3c0feba51dcd9f63517f5dbd0886bd3f4be6d76f7f30d59b62c164afde5432d5271f2453bdf0118c7abd77124ced4f1ac914afae2553bd5edc0ff3b9f32498ec6d1308a6f66c55c9341fdd83313f9ba23da8ef46a564dabf664aa6fd21f27b8a37e291643abfe249a6f9ce174cfb13a2028cf78b25b9647a1fd4a364f20fdf92c97f0c25d37a512599d607a03f22bf375ac994ffa49229ff78944cf94a2618fe48fe1ef59e4632bd3f270163becf2ac994bf8beb71fe4b0d2453bd27964cf552d13fa807da2f9269ff612499e627d13ed40f424330b55f13d763bfc6ed4332c50f37c1f0f78a64daff3d964cfb43c578637daf7a138cfd39429f719e6745fa30314df21f590ec6fedd32134cfbb10c5d30f98bcb8b64da2f3c01dbd87fbc174cf5c92001e37c4d25eee760fff1b7605a0fc8b792e9fc81b8bf43f149740263ff68fe2a989eb722fb9c8878201849a6f75f9e25d3f37cc974fee15532bdaf752898ecdd0904d37a475080512faf7e30e9432e18e7f56e82914f5482c91e0bf13ce4ff7e2698c627fb924cebcfe2f7d8ff1b3e80719eaa934cfaee3992491e717ff80f6f2699f22ff13dcecfa753c9e4bf0e92293f394aa6fd139660b2cfc8904cf9df4230e68b4a32add78bf1c0feda740ec6fbebcab3648a8f2792c95fd492299e1848a67ccd164cf25b2d58f887ab64f2379d64de3fea4132bd6f4efc7e8e7827944cfb7f1e2553bd4f134cfa6c799269ffb6781eea8df14432b57f2718ebe591645a2f8b05231f15bfc77e0f652699e229f13cbc7faa9a4ba6f361427fb03f5013fa8cf5e2c495ccbfd73dc924af180fec0fd33e24737922f17c9c6f6cc91ea626f69b5e13f082fccfe64d32d547bfc0385f565ec0886fba1cecd07a663394ccfb237b05633d627b144cf6779949a6f75fd682c93f06349f4dc5fa433d154cfaace982697d721b4aa6f3c11918f585742299fce5bd64aa67958229be5ac560ac27ac12c178bfd79b64da0ff1e37b7adf95fc3dcef70592a95ebb174cfe3a10cf47fda01c08c67e1b5f32bdcfb0134cfde12a92493ed17f585fc81f25d378dc49a6f8e253308d57249e3f417c7a904cfbcd7e30c5d382b11e982592797f24df82b1de954ba67aa6907f4af69baec138af6c8d24533d692f99ea733bc1e4ff3c0b2cde37be944cfe712499f2b1b964b2675732c52bd0670bfb45d54832e58fba64da0fb301e3fd8d4a2499d67f857ee0fc72f82d99be5f81713e3e194aa6fd49e27e588fb89ec1884fae13c9d4ffa27fb0bff0229e67537fae481f66e612fb2d776083ec3debc026eaa53618f18a3b0323fe580f04d3f5c98b64da7f63825df217852e99ce77907c33113f6c4dc134df6f1f24d37c9982b17ee04f05537b9a77c9148f88dfa3deb07a92ccfb7f73168cf365778229be48bf25537d19f28bf501e55e309d4fc94f92c97fcec158cf2b12c1e41fbb4fc9b43e3d104cf3f7f6158cf87ebb170cffe448267942c1e47fba05187f1f455049a6f5614330f4ff0d8cf3b88ab83fde3770d94ba6fafc12bca0f6a557c1c80f6dc9644fb964aa7f1492a99eb1934cf3f718bc44fd632199f2ab67c914bfd782518f16e389f78346a23dd8bfa58c25d379ba4030c95b5f2453fc5c824deacfec2299f6eb6c25d37ae74630e2b94632ad170bf9b13fb87b964cf514713df61bd4aa643a9f0f7bb31cecbf10fa28f6e3f89269bd83e2adb9399f52bd33032fa6fcfef9086cd07e8d95f81eeb1b97a964b2bf0dd8a2f958ff02dbb41fbbbb825d9a3f2eb5608a3fe28560caafb6141fcd45fdb11a83b11e180f05d37e5c5f114cfe669d8051ef6f3dc1a40fab108cf3d9e55a30ce3b1a60d4d78bab649a5fe5f7645f978364dededbb360f247452899ea616730d6e7d6779269fdfb4330f9bbd4148cf8e7058cf5b8e44932bdffe25e30f6835c24d3f9d1b964b27f713decdd16ed9b937fd2f792a99ed2082679a247b0380f33964cf3ab18af05c52f57d1df381f5baf2453bcff0046fcacfe60daaf6a4aa6f9ed4b30ce7fce25d3fedd1918f65f8af1c37e6d4f954cf9cf5a32c927fa17fbede254326faf22aec77c1bd582a9fd971d58ecef3524d3fe5ea1bfd84f97d1f82ec47a83be124cf5c8ca07dba4efbab8de9df2dffba44f0b51afeb5cc1747d32154cf61eecc043ccf74f9269ffd3098cf7495c1e25d3f9c14a30ad9f281f92693de2001ee3bcf34430e94f71114cfe259883f17ef6b52599de2f36144cfaa23c4aa6fafd188cfa79d60a267de832c1345f1786649a3f7e30cd97a2bdc86ff55232c54fb9648a6fc4f367e44fbaa1649a5f669269ffb7f87e4ef6915f2453beaf4ba6f9443c1feb655a2c99e47b944cfb532493ff6bef25d3f86ec1e2bc532318ef1712fa82f3cdc55e32b5ff1b0c7b5acd25d3df9fa04ba67ac25e32bd0f44b4cfc0f95ad13f787f759c08c6fb8f34c9141f6e2453fee80b46fe22fac7c2fbafef24933f17fa8efdf9590dc6fb8d4a8a079626ceb3d513b04bfa5a527cb664f645eb65067848f359fd8369bfec063cc27ae45532d5e31f25f3f15c3d83315f5d12c9544f740553fe1e6592a93f3dc158bfb88127145ffb9560b2873a96cce5d75f25537ce90ba6fa62f283a95e2ae49bd2f82b0f82c93ef385645a6f17ed453d39984aa6fac04c32fdfd5607c1a42ff14a30cdb7b74232e5a76f60e483fe5132cdafb960c4fb5f60c4aba52218ebaf7b30d69fb6e27b9c1f0ceec1d82f962b92c95f1d24537da7148cf93d05239f534f92e9bc8bb81fcefb1547c9544fabc1383fe68af1c67e92f807d3fe43213ff6af7662fcb19fdaa37cc410f5ebfc5e30cd1f6b07ecd2f85a347e06332faa8f1cc0d0efdb17784cf6e91a82499ff44ff004eb318f92693fdebd649adf5f05937efa67c1347fe91618e7bb6e7782112faa60ac8736a1601a8fac00a31ee98c05e37d155bc1347ff8aa647a1fc009bca0f1f21682c99f9ae2fe0b6acf360763fd62bb168cfcb0148cf7790879f1be9ad4954cf53cd17fd8bfe49f24533db1164cfdbd7d07e33cd346fc1efb17b789643a4f300423bf303760bcdfec42f669b27885ee47f38169e1bc977e124cf18d3706e3fd11fa163c22fdda9482a7b43e7805c3ff058660ba9f2b9e87f364d14632d5fb4792e9ef37fe02e33cd926028bf364efe039c9b712f747fdd9ad24d3f58231fee58b601affdb9b648a6f7230dedfe12d25d3fa760a467d3817f218145fd99f9269bda1924cefdf93df23fe7e009b349f98623c2c1a5ffb2298ee97d8609c3f32e6609c3f8b2cc9646f0bc914cf3f4aa6786607c6fe958ee20f8bcdafb43f81e20b165e93fe5c3e25d37e30f13dea3ddd093cc27ede2d18f5983804e3fd1d9a25989ed7168269ff61fa089e223f9e8167d47f862699d6f39e25d3fe68152ce2b70318e7c9ec67c9f4fe12138cf70f252918f1932b9e67507caf08f9f1be9938069b648fc15e308dbf32108cf7df88e7637f627c150cff7a0163ff42f000c6f99c88ec9b4d37a867d1fc62b3f1a3fd3c743f5b8c5ff102463cb2da82117fb4df9269bde12498ec510f25d3fef01c8cfcb8b425d37eaa5232bd5f2506235ed85a9269bda4154ce31d89f6cef17ea8037841f76b447b17d84fb6012fa9fd6b211fea49978b608a4f0c156c423f3bc9b49f3602c31e6f7bc1d0bf4a32c50fe44f6c1bfb3be22918e7e93a6287d907adb70ec063eacfd51b784afdb3d1c0c85f8a5232cd97afe0398ddf652d99fcf75130e5879d09c67c961482c97eae7bb049f74b3ac9349e86649a4f2692b93cb978be8df749b88229be509660eca7f39f24d3f922713dd6afaedf8269bcd690c7c6f9d755001e52bc5b533ceb5a63d29fab2199ce63edc1139a9f82083c25f9f5068cf745dd2cf082c6238d25d3fb1d378229bf503ec178dfce6a0946fce9bd0aa6fe5ccf04e37d0af27aca77ac1bd8a2e747df9229fe2dc136f98ffc4530e9f34a934cf9f10fa6e78be739387f48fde9daa8f7273c3e310716f67b260f9269ffde1318efefb91e24537dcd06e3fd79f6156ca0deb1904cf6a080d1fe6a2199e67b5f303d4fbb801dd8fb0a8cf8f9a611db78ff5dac8211df745f60d413133e7e2c389be17ccc183c27ff97459279ffac4b30de27947e0826f94c4532bd7f5d032fa9fd6d2a784af58e21d8a0f9e1aa48a6f53f5b30d58ffd6730de5f94ad89ed01d9ef86eb2b0b2eb0feac6fc04b92af7525d3fbcd8f6093fccde64532d9cb4d30c57fe1128cfd33eb77c1a41feb028cf7355a1f82e9f9ee1cec62ffea9b60f227892918e785f0bd8dfdafe9b3601a4f270463fda81980f17ea59adbbf3966fd41ef472dc14bf2075b1b6c60fdec4132d50f0bc9944f1cc126c693dad7bf5e9ff2075c6f63bd6b45fd33b1e6549fb8adc0580fdc7682c97fdd5ab035a5f74309c67961e50bec523c1de2f736eaf7f11c3ca4feaba8bfa6d664467fffdc080c7f53b492a97e6f08a6f686776013fab4964cf69982717ed224ff30b5b15fe81608c6fbd3ce60c48b2d8dd78cdd8ff2eb5430c5839b5730f2dff60086be74a4af33d6ff148fdd8391ff6a74bf390b30693de808b6917f64c436ce8fdf1230f6bfb7345e0b6b3a27fbe9c0f319bdaf8bfcc782a5f7e43f0f60cc4705f99f256b3fedf71c826d92ef3625b627349f68dcdf9b2c9f9b927f237d3458ffd1fc5b8327f007241f530f1aaf6b00467cad51ffb2f8674efd41fed5b6711ed0e4fac192cf39b57733022fe97ecf977feda32abf7d8c9f3e26ffa7827fa74fcf0afb9da5daaac3fe58ff6a0be8f3df21cb2f72b9ecf3bb5c0afe9b90afff77f7df5116d62247f5d81ffad87ddba87590cbfd87bfb3f1f9779605f20899fa6be8cfffb79fff167b71e9f393743ffadc1663f4e33aa96fbdedf8eccf3f18b9ffff65e16dfbc90e6009240d1fa9bf2b3bc9439ee0df4d1661eb3f64f9313a3f24f3e4e717cbfa7791e5379fecfefa91d758f05a8e94457a8a7f2b590235542335561335553335570b364ea55aa917b5669f86e951ab76ec7365b2de544dd5d99f15ff9dc67eb1fe379365a3aed827652391a85bf6b963d2ecd43dfbec982c07464726dd91fdfb4e3da9f74cce7bf5817d0c76e53ff4daff5b6479e43dfdc446e699fddb597d515fb94ebda9efea87faa906ec9a9449f8c524f85607ea501da96375a24ed5993a67d2fc1bc9c25a7a5637ec9f91ba607f02d8fd92c9f2cafe6929aafaa4284cc7be15431d2ba662b18fad380af31a8aa7f8ff3d92fcf7cc954aa0844aa4c44aa2a44aa6e44ccf5ca63d2dfbf4b6622a059b45064aa954ca45a9954669954eb92a3745537465a5acffe8b5ff37cab251b6ca9db253cf8aa2ec95036bf1513929f7ca83f2a83c29cfca5979515e9537e55df9503e952ff6dfbf9581325446ca589928d37f23596c65a6cc9505d3b393b26413cd83f261288661b044c0b00dc7700dcff08dc0088dc8888dc4488dccc88dc2288dcab8a87746fddf23c99f9345b58ca6ff23a390df6677a3353ae36adc0ccdd08d95b13636c6d6b83376c69efd391847e364dcb3cf897d8e8c1fd8e7d178329e8db3f162bc1a6fc6bbf1c1b4b0cf02685e757f9b797f9aadfe999ff8af6561527c1a5feccfb7313086c6c818315fd4186363624c8d194b9916c6b2370ad3304dd3326de3683aa68b8fc73ebe19b04f684666c465eaa53a9a31936a6726666a66666e16666956e6c5accdc66ccdcebc9a375333757365aecdcd2f33b1f2eb1cfcd764311a736bde3169becd9db9e7b21ccc8379344fe6bdf9603e9a4fe6b379365fcc57f3cd7c373fcc4ff38b7dbecd8139c467648ed967c23e63736aceccb9b960992a3334e3de322cd3b22cdb722cd7f22cdf0aacd08aacd84aacd4caacdc2aac12b9dc2f91c5ffaa2c56655dac4b3f2e566d0cad5a3d5b8dd55a9d75b56e9666e9d6ca5a5b1bd6d3f7ccd96ead3bd6522689b5b3f61677bfd6019f2393666a9dac7beb817d1ead27ebd93ab351da592fd6abf566bd5b1fd6274b98bf5884b0601e3d61b3e9c0faeea3cf1fd1d1bfa2634cb31a8bfe82f001fff74a89aca135b2c6d6c49a5a336b6e2d7acdb196cc74fa4a9ed18f85b5b34d48f2439643bf4c614e6ddb766cd77ab03ddbb7033bb42326cfc178b4633bb1533bb37336abda766197ea935dd997de92fecce74fc932307756cdc6646055aa67d77663b776675fed9badd9ba71303fec95bdb6376c249ef9676fed9924625414662bcc5e602bf766681bf6d6beb377f6de3eb0cfde3eda27fb9e8debde7eb01fed27fbd93eb319d7b35fec57656fbfb1d1b07efffcafc9f27cb16a66274cb78cc6f8b4df992c1ff6a7fd657fdb037bc8faf3c47a7864bbe6dc1edb137b6a2db924bb7e64fab161ff9cb1f6ce85fd9b91bdb0972c485698ddcc1dc3311d662c8eed384cd2bde33a9ee33b8113b218f5dd89545df17fcdecfe155954d7183ab113333bb1edda499cd4c9ec2f27778a5e0ea7640ff0ed3d6b55653d3b17361acf4cc706cc6216dc6ed8ff3b356b6be3b44ca6b9d3998173756e8e66f7938feeac9cb5b3b1b7ecf78eb365d21c8d9d73e7ec9cbd73708ecec9b9771e7ec9107ecb7a7eb6a03f234b2f09f3c683fe7ecea3f3e43c3b67e7c58cadb33db1ced6b33d6656cc3ece2b6b5dc5dab5c0a7f765ec63cfe9e374f8bc39efbd24f6d20e9d0f66fd47e7d3f9ea7fe954ce379366dffff5f6cec8e9ff5acca933b3eb9fe4f8576599ab9db3b05f9c25fba1e21a6ce2b08c23f34accd3bab6ebb8aebd702a73e17ab66b1f5d9ff9a8931b981fccdacfaca5f76ec86c2ae673e6d18ddcd84d98bde0e3746e6a7acc73b02b594fbcd93336be67377373b7704bb7722f6e6d176e63356e6b358ae67656f3afe8987a70afaaeddeecd6d55cdd5db96b3626cfeec6dd9a43f7ceddb97b3622dbde86dd837bb4576e6031ed331df7e4debb0feea3fbe43e1b817b765fdc472195fbeabeb9efec5707f7c3f9703fdd2ff7db1db84377c474f1c0fe7dec4edca93b73e7eec25daabd2f6091b8a7aa81f70fbdda9f91c533d8f46d79b6e778ae937b9e71b2179eef055ec8e4601fdbf0222ff612e6030eb6d1eb8c977a99977b85577a9577f16aaff15aaff3aedecdd33cdd5b796b36e7c7c6c9db785befce7a70471ebb0b1b5d9dfd3ff36fde8e59cec1db7b07efe89dbc7bb5f01e58467af31ebcc71f5af5bb1ff853b23c79cfded97bf15ebd37a730637362dbde3bd32f2e099368cbe6f229b39ae7de76bd0fefd3fbf2bebd8137f446ded89b78536fe6cdbd85b76441d7a3aff8866ffa966ffb8e71f45ddfb31e7c9ff9e8ad6df8811ff663e547ee8069e4831ffb899ffa198bd6be51bffd523c9189fe75599e2f7eee177ee957fec5af0d6603e6d46f7a49fc967d3aff6acead27ffd6cf77bee6ebfeca5ffb1b7febdff93b7fef1ffca37f62f966a2bef8f78aea3ff88ffe93ffec9ffd17ffd57ff3df8da3bdf03ffc4fff8bf9f485bd30c74ee57ffb037fe88f8cbd3ff627fed49ff9737fa1382c27fd6679f70f597ea97dfc99d8d25f066aa004060b112da65f6aff97c0f7fae5b7811d38fe3570cd0fe31478811f04411844411c24411a64411e14411954c14509839a7d1afb3d68838ee59af3e06a3f07b7400bf460c5fc48ef0d9560ddeb99ad30d906f6c27a0e36ecaedbe02ed8057ba50e0e4a191c8353708f0af54f35ab3f2d8b1d3c048fc153f01c9ccdd829ad73f012bcf6da15bc05ef81137c049fccf38c83afe03b1804c360148c8309fb330d66c19c49b47016c1325443253442d3188416fbc39c71e8865ee88741188651c86cc73a8709f3cb4698f29881c50f61d6fbfc300f8bb00cabf012d661e32fd421d3b41fb2387f94e5e77af6cf63d25f1db661175ec39b19875aa8b3bbafac636f27e13a5c33795e8c7b2f0d37e136bc0b77e13e3c84c7f014de870fe163f8143e8767f52d7c095fc337ab08dfc38ff033fc62d2982c22f6d97ff90e07e1301c8563e3184ed82cb40dd6e1943d63e6ee99fd7c9b53f6dfe7e1225c466aa428456444e68fcacdaf5a46b288ff862c28f1d4c8525fd5d7c88e1c7f19b9e673e41987c8376751c02375a61351c8e2f7cf88e524511c25511a65c62dca8347ab65f369cafe3c4645f01895aa1255d125aaa3266a5910d345d7e8166966678ccc75d4467ab48ad6d126da4677c629da452c82f0039ef778d68ecdb40bf6bc7d74888ed129ba77d2e8217aecefcdabed866af4d1eeaff6f2932c068fb043b77516ca2e7a8a9ea373f4629ea357f6a437e6750d16a79ca37773c2e6e8aad7eae823fa8cbea2ef68a0ce153f1a2aea8f2a2c7f9e1b8da27134096d2b8ca6d1cc8aa379b48896b11a2b56111b319bac629b85166eccbc3d9f73962c7f93b29843e33ef6e3200ea3fb388ae3f081f554cadbcafc5a1f25fe2c0b7ff68f7131d4f8f9e22cd4f73889d3388bf3b888cbb86277bcb0f87111d7d6dedd5b4f7c2639b959dcc46ddcc557ff515dfdb4f662cb3bbaca5875e25bacc5ba3f8b57f13adec4dbf82edec57ba5890fea323ec6a7f83e7e881fe327e3143fb3d866c9bc7380b86e689de373fc120ce2d76011bfc5effd88736b3055a38fdeff992c0ad34726cb6b9cb8adba8a3f4c23fe649db7641ec6b09ee3da665ed3fc0c33f6dcaff83b1ec4c378a456eaca7e51ee94713c862c3c1eecff9dfdb7493c55f57816cfe345bc4c54e3c17e4894c448ccc44aecc449dcc44bfc24484263efde9b3e8bd8d887e7a42c3b65f3d6d17c4da2244e92244db2a84872b1baf07765b1c886f8155b36bbb2fe65914fa2b8499194e69b71f26fd69e8dc9d9b998dff6c13ad953e39054c925a99326d6d5f7beea9db4ccca52f40d55c1d97d95bb385332bb4abae49adc12cd38252ceb4956c93ad924dbe42eba26bb641f1c9243724cd82c657a8ec272014364d94c9b4b2f4dee9387e4d158264f09b34ab146d2e722ff4c96e499f5e198e50e2bf6efe7e4257935dfad3e3f3f276f56ff8afa7df26ece8dfb709c7c249fc957f29d0c143d192a8b64c4abe3bdc7b4fbac8dc9c264b2df93713231de9269324be6c63159d8c76469c6a99a2aa9919aa995daa9e3dfa76eeaa5bef1603a2cbfe1b2f45910cb54b769601cd3308dd2384dd294cbc2d76dfa7cc4180aaff6932c96b0fe3453466e6b97cc8e9d344f8bb4343fd22a4c98f75a5afdfe8687f4621becee75daa46ddaa5d7d451f4a04b6fa996ea91c9fd3f978549c3644957e93adda4dbf42eddb15fedd3837d4c8fe9c9d8a7f7e943fa18fae953642b7a344c9fd373fa92bed2c8902c2ca7db4681719fbea5efe947fa997ef5feb197a56f7f9f5bfd2acb8f91e17a78607dbb5412ff2139a7dfce9069eb673ae86da5f7c54ee5fa696f8f553a4ac7e9249da6b3a4b50b65c3f42c5177fe23ef31361a7d0edad724d379ba4897999a29c63163f971b4efb3e3ccecb3e2649559999d39ea57ea0475e6665ee66781e9fa81a3a06ab0eb675096e1c5599845599c25ce23b3172e8b6af5b9d52fb2889a9add3f99d14efd4a064ccf952c553eb2cc74cc2fe61b077dcecbf477613d982316e37efaeb2ccf8aaccc2a61e7e45b98b34db24b56678d5dc763f53b6bb32ebb662c62f343d6df6ff6c2fd66de9c652c99661ce3a74ccf56d93adb306bd3b36d76e74efa5999c53363a603cf76bfcd8445369691edb23d93e5901db313d31d85db7491ddff268bf28b2ca67a973d3032b24743c99eb82ccc37f67d642ebcc4661146f69c9db397ec357bcbde852c1855577d4bdaec23fb8c9e93419a655fd97736c8d8e866a36cec8eb24936355da7cc66d9bcf7ebacbf17d93257734509552b377233b7723b77d8377d3d6dc29edad74398b7cedddccbfdec900779a828ff4496be024a7dabf8bd36f63edacc23c330ee982cbd97efed70c024619219f7799c27fe364ff32c3c30597eac4172bf95e779919779a556f925aff3266f8d63dee5d75eb7dc613f1ef9cdfdeeb3e25cb316f153aee7ab7cad9eed32dfe4dbfcced67396c1b09879c8729a4bafd9feb7719f29f93e3fe4c73cc88e4c9b1392c52afe812cbd0f559209d332db2ed5263f1926f32baed05ca6678eed5877ecbfbce6f7fe5dfe104cf347a3fd690d92d97afe943f671725cecff94bfe9abfe5ef7dd4937ff49909af719cddaf6cca73628dcd8871fe997fe5dff9404d9cc833f3613ecac7f1579ff1997dbc4c51b4cfee30c9a7f92cc9988e1d59a699f47e377c0bdffe200bb75792259fab7b854d65ea77be302c63cfd2fb1dd5bc481673943bf9b2500b8545f5b3e8814547b6dcabc0575793b1fa919f0ba33059b7d9ac557d2cbfe8f312ebaeb7e4c2e96b1785cb62ad53e1157e111461112923d52ee22229d22233f67d5ec365611ac6aecdd98cb92f8aa22caa3c2459faf6b398f5f597f9e5375958c6b34f6fcc62be8b0b7be4ce74a97227646177ae8ba6688b2e288a6b714bf25f7684303d53fc645268855eac8ab5710835e7b597a5d8b06cabaf6a7ef4d5be60cd243916dbe2aed815fbe2a0d8c5317b284ec57df1503c16cc3efa1a279764614e0b268f7128cec54bf15abcfd248b1aaa7f57164fcab22bde59fe742a3ed894b5efa33c5420875c9645f1597c15dfc5a01806398ba2c90bffd8555114a3625c4c8a692f4931ebd72c989ea8c5bc8f467b5b6677e03163b12cd5ecbb544287c540d7d250c2d22cadd22e9dd2354ebc22c2ae36c7f6a1f498cdc6a55f06e1ae64290dd731f7efc822d654c40cf3adb665c472b053191b2ecbef852cfb5e16f3cb3a9749999659996749745f163f564a7824669465599597b22e9b5e92b2cd34661b565f3b6371dc985bb4e10ffaaca7ecca6b79b3be4acd0a4a9d8d67c4a45995eb72536e992cbabdeda326368e5bebbecf64cabb7257ee7b591425cd7a6d28b552fb45961fd13ef773ea8dcd103b75c56439183e1bebc81c5b7d3d2cb0674e63cfcb63792aefcb87f2b17c6271ce86e527a398c594ca9d5d97cfe5b97c295fcbb7f29d79d12eef32adafee9bb3bebec13f337b5f7eb079bc2c3fcbaff2bb1c985d392c47e5b89c94d3c42d67e5bc5c944be3c45c7d156a7c4c0f665f1939564a655466d06746a7e0d4ef2ab2aadf62fedefb3059d8b7663f36c8d834bbaa2c26cbbd19b2deec97483a264b6b06c6a1b22bc79bc5e3a00996e5c4dc562e538ba86236cfa29545e5574115329fca66bb3ea736471513d73a313946fd9a4515dbdb2aa9d22aabf2aaa84a2bacaaea52d55553b5556745c1b1ba062b362e5ba7a355b57ebda3aff254b74aabf42467b21c83a36ad9f51f641151a5cf6571d488e9e246bd315559556b264bc4662c268b193269f64c96a37bf65a6fae2e2387e9eb5bb5a9b6d55db5abf6cab53a54c7ea54f575e17be6c717d681c5d5233e26a3fe2ebd3d570f4c96c7eaa97af646d5b97ab1aaead5dc556fd57bf5517d565ff128afabef5e966ac07ac2e5f5cf678bddb11a56a36a9ce4ce23c6c5339adf627e4bca6270efba60d1ee539ac5a36a524db98e912c51af654c965335f33a8f656bca3c34ccae9a87af9eaac6ac3f17d5f2a26637f7f5a25cb81fb615f38349d17f26b406c3ee7570377d7e75312fd6c5be38e1cbc5bd78179f8d897f092e6134b8449798c9d2b91fccbadefb159cde673059946a7449823e47f6d9c7fea32ca859283c96225912f549bdbfa4ec9e593fc6fdfa9c6df523d4af3d18a774e75d2fb9925e8ad0c8eefbbcfd525eaacbe5525f9a4b6b9c2edde56a6fcdd1e5165f98bd93244764f10773e445d68e5da55df4cbeab2b6c2cbe6b2bddc5d7655a7b697fde57039ba2fbd2c173633b1d8cde27fd5d684fde2fef27079e4b2a0adfd5add3f95256071f24d29c2faf27479eeb585d61bfb95a07ecd81e9d8a377f35545b3df7975c88ca6feec72bebc5c5ecdc4383afae58daf136d8235f75dbd7e8db92c7c3d96f5f196c5dd5333bebc5f3e2e9f97afcb777cbcf06a13d388e16578195dc66c869ddb6c66cd466c967db5ee7adbbf4c2ed3cb8ccba2f0bcc2fe5d16392f4096545373b5cdcf97f9657159f6eb90bdcdb2d8b85fd50accc08d8c83a7298f8a1fb4c620fca8d55a49b6b5519bc98ac9f9565bb56def1cc38bfaf99ecd8d336ef74cc7b8341e9b3146e6dcdef82cdeac9ddaadbddaaf83484b46e9ad0eeba88eeb84e5ca9fcce3796c6e9db008f4c9dd32590e755a67756e325990875bfd0aeaeff9cbcfb2287eaa2b6e5dd4a5f25557c68149c0bc0fb3dfa8978569716cc69eee2b6aa9cc422bfc8caa9a4590ec7f0d6b5beb7eb84347cdaf2c63af9cd73063f67faa22f6ebdeaff7d27875c746f9cbfc626d5cd6d7fa566bb55eafea35d36ca77c8af27a536fcdd8b9b23cdceb6318d6239bdec2eabb7a57efcb3d932515759e3fe695d8112074cc55efd44370523ae5b13e184cb3597e7f6fdbbc12cfda581f599b4ff57dfde0b6a1556d13b77eac9fea67e3549feb17a65b8bfab59f159cd728b02d1691ceeb37bfb1b7fe376fd994b220ca89acbdfb5abfd71ff56738a8bfeaef7a500fcba01e992ed3c27db17077aec3f29881cb324b63578feb493de5b2507ef20f7264f6a797a59ffb13f6ff0d9bfda7f5ac9ed70b9657b2fc8bc52e5b7b592f9d779bcdc98dda288de13f5a35f3ca1f8dd958c64363db47f6d9374e3f438693be6ed3fbb2c665ff34a2d0def09a9af1cb1ae0d074eb5be3357e1334a1f3d4444ddc244dcafae291e54977eeaec9ac2dfb158b429bbc299ab2a9b8bdd09ca8f42b763fcb42732397c5e4b364aa8cd2cc99c77a7369eaa6316377c3eefb7039352d0b8359d6e186c6aee99a6b738badd0b48a466b74fbc18c9b557aecc7c57c6fd64cdfc76c2c3efa5cbdd9345bebdcdcb9dbbe8283d53fac9c9b5ebfb3a4d935fbe6604d9a63736aee9b0726c363f3d43c3799bbeb6be64c2fe3e6dcbc34afcd9b948559c51f65a1d95ecaa2f1959bb5faa138cd7bf3c1a22ac7ff609e89d973bfa6686f9b4fe3e0dbcd57f31dbae167ad3483669828d60b7bde283359ae356bc66c961b46611f41369366dacc9ab971b296eeb6e1e3815566167d9b9ed3354b63efad5bb5555aa3355bcbe8ebd581396efb15c45d9f2b87ba71689dd66dbdd6ef63181e7719aadfaf09ff365752a5cfa4bdc2fdfa937a8bc76de03dc65d1b1afd4afdb658703fbbed6dba8d8c531bb7499b865ef5de666d9e9fdaa22ddbcad8370fed85595585fce4beaddba66ddbaebd5e5876dfded8bcf3ddd70ee4eabfefed5aaddf1de36baddeaeda755bb35f6dda6df0dede056f5ec89eb7734a63d7eedb437b6c4f52163f38fd41161bd97abff39945bc2c951e313ddbe5b9a2b7f7ed43fbc8b4f7686ffa9d05b5d53ef55adf326fdf9edb97f6d518861f4e5c44ed5bb269df59ccb3cf3b7bc9645ef5f949fbd17eb65fed773b6887eda865b3068b697aed123b19f67e906bf6b69db0acf8d44edb593b6751cb397875ed76d12e3bb59fdbeace38754a67746667c571922779af472c8e39fe4116e75759d84c99a94967770e93e6dab99d67192cd770d89cb063be56ef7c7b5b9f7d3753baa00bbba8da767197746997b1b0b8e8ca7e6dc8db75157bfea5abbbc6df756dd775d7eed6699ddeadfaac8e723b5ec95b326b687b8fe2fb4e65dce75db7ee36eeaedb76776c02d875fbe6397aef0eddb13b75f7dd43f7f8ab2cbfc563b40fdae2fbb87b59fabdb76ef7d43de7cfddb97be95e6bc738b9ae7de8ff1a4166c38eb3eddeba77964f9cba8feeb3fbeabe9d85fad80dba6137eac6d19d195b0b33f6b56ed24dbb5937ef16ddf2aa5e95ab71358d9dfbca7763f9bd1ce6d00ffa99fd6ad97bc7bada4cbe73b7bb322bb18ee1cadd5d5deffdea3109dfaffe35b886d7280fa302b66ffe1d1d13eb0b72bf196a7fdcef5de36b52b2d65d53ebe19ab119ef6c9dddcf7eb5f79ab3ff5a5ccb6bc5e29897ebe55a5bfeb5b9b6d7ee7acd27d7db55bb321d5533b30bdf8da69c5c57d7f57573dde6937efe655aa8f4750ce623a2be06c6f7638dd87c74ecfd38d515ade7de5aaa8171bcde5d77d7bdda3847b5edab2c5993353c07367f9c07f8afd7f89ca7ebe17a8cd953afa7eb3d3dddbf998b6641d1eef5e1fa787dba3e5fcfd797eb6bad3069deaeefd78febe7f5ebfa5d75d74139bc0eafa3eb987d26d7e975769d7b6bd60b8bcccccceb92dba2f5f327f2dd7d73c7fc1c27ebcc52c3a79b7263f955348c4c36f3b9aa6dbf33591cbebef31764b99937eb66df1cd6379ecb66877edf8bad140b2fb9b139d0b8f7b51b0b346f8152ddc25b748bd5db2db9a5b7ec96df8a68d025e15755df4a7377ab6e97f0e3c626c65b5bac6e9db1ef772df0fd16d6af1f5eafb0d86cc4246aee7236b3dcaeb7db4d4bc6d133cb2d44fefb87ddf3ffb52ce6e34dbfad6eeb86c5860d1b0d663515f3f8ecff6d8fc5eecc9fe593dbe6b6bdddd5a5fa62d7cae2b65386b7fdeda0d4ea58dd869f55773bde4eb7fbcbddede1f6787bba3ddfce51623f180fb71733643e7af24759983454afa4fbbfdede54f7f67efb48068a226ac97f7d7d3f2a6e9fb7afdbf76dc02b565f2cb35c58776c86d89a73162f6d6e43e3741bddc6b7c96d9abab759eadce6f1241ef77bf56f8bc80a5fa2eab6d4d4a8d394a85202f5ac199aa9599aadb1b16e5acdedade4e78fbbef3396c82759cc58f3345f0bb4508bf242d1d20ce3f287d3597fc25e1eb5584bb454cbfad981dd7b617e7a119385f624cdedad96f733a75668a5566917ad564325615ed0b65fe289b25322add15aadd3aedacdf84c1dd573979aa6e9da4a5b6b1b7ba16da99af0ebc8b03f2a8bb1ad7667dada9db653bba0b9bddbef2c7f37642dcfa1f8f22fc8926a7beda01db59376af3db008efce9cfa1f2c3bda71eb6451633568f92e43ed517bd29eb5b3f6a2bd46b935d2de8c85f61e4fb40f36269f2c216e94246ccb2767e999da97f6ad0d3436a6edeeefd98bf5dcee2c35f2b59136d6260a8bd955d72eed525db37111f562ef2fcbf2a84db59936d716da52578d7da8318f79673d9993b86e6fecb363518056b6bac26c79a71bbad92a9dab5bc64db77527327457c97596ee844e7fe622ce597e32d4033dd4233dd6133dedc7e0d74f98f5b2447e2f95bbd7333dcfebb2d20bf6fbfe0c84266b797c86ff2b3a16157aa957fa45aff5466ff5aedf11c3f2de39af8f322fa45ffb798faffbfaa6ebbe66817ed3355dd757fa5adfe85bfdcef850bff59dbe77c6d5413fe847fda4dfeb0ffaa3fe14bd07aece722db28dde4ef86e0bf3e78fe9e8e764adbfe8af4aa36ead86cdca34abf4f6eff075c43fbd8724c9f537fdbdb8ea1ffaa7fea57febcc07588affed6ed3ca56a3f7beea637afd3a561f4733895c33d687fa888dd0589fe8537da6cff585be5ca92b6565accc95e5eddd3c7ded778d38d5ca5e39b6e1eec90f0b0ff68b2cae7170dc95bbf2567e3c535f56415f310a4e2cdeea57df6a5a7bfb73b2048fab701505b355bc4a56e92a5be5ed78555807166b6efa5ccb3afe248bc9b28265dee5ceed8565b4b755b9aa5697555dcd568d3e5ab5b1c7f7c23129dcddaaeb76abab395e752c5bbbe3f66e626ef955166f7533e3b261f9d270a5b1f178e335567efeafaf2afd9571311f57fa6ab55a6bb362b8daacb6abbbcbc76ad75767d2a05f79b0b67d0ecf64796372ec983c0adfc570cff7819ef85efea3d8cf6bdcbbdf76e87ff8cd6abf3aac8ead1d7cb84edffa7e9e679aa6b63b6627bfcae2af4eab7b9643ad570fcdfbea919fce727f3a052c4f69fca971795a3dafceab176db67ad5ebd5dbea7df5b1fa8cbff26ef595f615a31fbbddf98749f7c177bc0f9d57f6795b7daf06d17e35147b2cfbbdbccd9339ee7739b58bd5a8d72e173b9358e3acdf65b1ceab717d67ec5693d574355bcd51c3b7708ec1fdf3314c92af16abe55a5d2b6b439badcdb5b5b6d7ceda5d7bc69e45cffb1f7bdefb489eaffb32097a7b62b3105fc7e3fba9f9beea7e36627e6318266b7f1dacc3c0091cbecb91452c6431bd17f85d967e7473dbd8d7efeb681dab77e20c2d9745f9b16be9cff8b1f03198af933c5d5bc1789daeb375be2ed6e5ba5a5fd6b5b5b437741601fbf7fbd5b30fbe57a25f6bb15a16fc34ceba757416dfb3e83e9ce9d77ecd807df6ebceefd6cc62bc50c8d2eeb411f366bfd90bd7d26374b7beadb53573e4b2fee5fed5793f628aba5eaf37ebedfa6ebd5befd787f5717d5adfaf1fd68feba790c5fdd69eef5ac1b8b04fbf9ef76a7e704b3e584bbedb9f5950bffba8f7e2eb7e97fcb1df83b63eaf5f02d736cc28effa73246c8e1feb193f73d2e7373edfafe4b23c69bb7e5dbf35cafa7dfdc1e617c8f2f7f78ffdf38ff3283f69566595d196e7f5e7fa6bfdbd1eac87eb11d335bea38c568b980e4db0afbf8fa6c6acc7cffc04c6b2dfadd7cbe90f7a7bea77569a43967505d5e0a69a713e6171d79d36d1f3f5b8f776eb49bfa3b61f93cb389f38de7aba9eade7eabdd8d32b674be7afc8f2d3d9621ecf798f6a11dcaf179774bdcc5f36ea46d9181bb37faead164ebf368979c230a77db5439cb4602336661ab91436d3dc39174ba1fd0a2caa7f6511e4ae0f0b36569fdfacc6cce59f8ce3c6c9271b77e36dfc4d607da94f56f35b9bfed2b8fc7eb6381a2a9ee2da55972acd26dc449b78936cd24db6c9f9aa0bcb6eac27ffdbf68bbc782effdf76ae6549552488eee733a6f615fdba7dbb6356a899203e5a6db51f3b4444f0c14b1489987f9faa8202a4bd37b457331113b9d010943a661645669d93b6d9e37b5a6207f5ce54d90a7b630ee6244ed8f3c2d4532060d9afca32ad349d280e4d481246103617866ae8b10a11c3b2b36c86248e1fe983506f36cb7bd7f59cde1344592e9dd23decc91c0e90c0115250a0014d680104cf80a691efb672cf7c667bc1191af13a6a6c8d2ed758790ea8a041fba8a546ca6681e23a2c67047dffd9b4a1130fb9e20cbad0833e2ce34747a706bc2c0e85fef98baee722bfd4f4404187dc51957668dcd0c2d0b660004318c12b8c61025378f3347fb13bb0acbe5df0f8ab3a31cdd0e01d3ee0136ee036e9c2ddb1ed7437f7e95459c13d7169c0bcfd003fe0117eb2bb700a4ff08c94def1b9eef5e9337dca1557dfc052a8ea8aefae6ed98c216b9d45ef4ffa485524aebeeaa181333471eeaa5edbb7f71bff47100423b4421517519a70a1686ff7106f632dbe471b97ebe0a027b3a4874ec8a276354cdffc603e255ca59dee228325a4b8c2354b719e8d29bbca113774bcb961e319c8f15c1f6327bd3884873ca043ee1bdcda7dce35430f7d0c30740718e10e636fed2f7ddd7f0cc2861b3aa1161991827b3cecfa8d66ec6112bce2115354f693204dfadb96d559cd6ccab25f967cd21655d61b3627a2d61336b0892d72a03dc20e53978ef868d8fa229f5faee75a7fe935c07eb745b764495b08ec7d0311d5f514356ca3bffd70224ff774bfb3f1822818bb5ad8461d3bd8c5de6e837df6fe0507fb088787258ef015c7d68bd0fa1a7cc79ef3f0a8623d21573237714a0f6bb636061dba66de58d0211dac1b76bfe293ef6039b59ad281736c393795d713791dceebf80ee712f96e3009ddd07544a5d179e13613e6e4967d435ca3ec245389a0cad56bfd58aad7bf7aee9fc122ff178e852391e3f3ba9c7d9399eff23a234758aeb7d96b869def6fe7fb0f468e60216ac18678a2378b9890bd31a42ee18c42f1d27b720dcf09969c1fb0909d7904e76ec356026184f0baafc89d66956e3da5fecbf6f6f369d67545d6b5c5d924df135a7ec542cb5e26e49a7cbfc201afa191da8093df3604f79408ae9ab0ad576031ca9ca3caca1635c83935653d22cfb448ce3bcf6adc752c32e62a9eb9443352aa19aaaae7e288acea1ab4729f2cb50e052bf5d4871cf952b02732ae47d9db635ea9689b453c57bc2062244752ad5f5e84c592fcc3e1ee4c949995795bc152fdbea830d827ffc84c20e9088f91d2fb395e4b665b520152c3422492ebf27dce3a1163b10a2cc60916c11710bad85b6ed69a7320cdc09db863ceee0a1533e20c1ccef6c814cd995eb334f9fc9ecf4b7ebda988b5c23b67b1108e04dff03d63da7fc32f8b9a5f4caeec2fc7c9c7e6f5bc5e154b795ce2e596e3679fca7dd222b624e3bc58134fe3a1e0bbcd199677fcb81c4b3d6a7ea7d6aeb0fb7e71ceb9a3f5738b7cbeda2ba7de3ba79caf57e52fff15fb1fcbbfd3fefcfbaf3ffe0193cc32fd</data>
+ </image>
+</images>
+<connections>
+ <connection>
+ <sender>PushButton1</sender>
+ <signal>clicked()</signal>
+ <receiver>MainDialog</receiver>
+ <slot>close()</slot>
+ </connection>
+</connections>
+<layoutdefaults spacing="6" margin="11"/>
+</UI>
diff --git a/examples/network/remotecontrol/remotecontrol.pro b/examples/network/remotecontrol/remotecontrol.pro
new file mode 100644
index 0000000..0570253
--- /dev/null
+++ b/examples/network/remotecontrol/remotecontrol.pro
@@ -0,0 +1,16 @@
+TEMPLATE = app
+TARGET = remotecontrol
+
+CONFIG += qt warn_on release
+
+REQUIRES = network full-config nocrosscompiler
+
+HEADERS = startup.h \
+ remotectrlimpl.h \
+ ipcserver.h
+SOURCES = main.cpp \
+ startup.cpp \
+ remotectrlimpl.cpp \
+ ipcserver.cpp
+INTERFACES = remotectrl.ui \
+ maindialog.ui
diff --git a/examples/network/remotecontrol/remotectrl.ui b/examples/network/remotecontrol/remotectrl.ui
new file mode 100644
index 0000000..a1cecef
--- /dev/null
+++ b/examples/network/remotecontrol/remotectrl.ui
@@ -0,0 +1,145 @@
+<!DOCTYPE UI><UI version="3.0" stdsetdef="1">
+<class>RemoteCtrl</class>
+<widget class="QDialog">
+ <property name="name">
+ <cstring>RemoteCtrl</cstring>
+ </property>
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>279</width>
+ <height>185</height>
+ </rect>
+ </property>
+ <property name="caption">
+ <string>Remote control</string>
+ </property>
+ <property name="sizeGripEnabled">
+ <bool>true</bool>
+ </property>
+ <hbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <property name="margin">
+ <number>11</number>
+ </property>
+ <property name="spacing">
+ <number>6</number>
+ </property>
+ <widget class="QLayoutWidget">
+ <property name="name">
+ <cstring>Layout5</cstring>
+ </property>
+ <vbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <property name="margin">
+ <number>0</number>
+ </property>
+ <property name="spacing">
+ <number>6</number>
+ </property>
+ <widget class="QLineEdit">
+ <property name="name">
+ <cstring>textToSend</cstring>
+ </property>
+ </widget>
+ <spacer>
+ <property name="name" stdset="0">
+ <cstring>Spacer5_2</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Vertical</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Expanding</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>20</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </vbox>
+ </widget>
+ <widget class="QLayoutWidget">
+ <property name="name">
+ <cstring>Layout6</cstring>
+ </property>
+ <vbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <property name="margin">
+ <number>0</number>
+ </property>
+ <property name="spacing">
+ <number>6</number>
+ </property>
+ <widget class="QPushButton">
+ <property name="name">
+ <cstring>sText</cstring>
+ </property>
+ <property name="text">
+ <string>Send &amp;Text</string>
+ </property>
+ </widget>
+ <widget class="QPushButton">
+ <property name="name">
+ <cstring>sImage</cstring>
+ </property>
+ <property name="text">
+ <string>Send &amp;Image...</string>
+ </property>
+ </widget>
+ <widget class="QPushButton">
+ <property name="name">
+ <cstring>sPalette</cstring>
+ </property>
+ <property name="text">
+ <string>Send &amp;Palette...</string>
+ </property>
+ </widget>
+ <spacer>
+ <property name="name" stdset="0">
+ <cstring>Spacer6</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Vertical</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Expanding</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>20</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ <widget class="QPushButton">
+ <property name="name">
+ <cstring>quitButton</cstring>
+ </property>
+ <property name="text">
+ <string>&amp;Quit</string>
+ </property>
+ </widget>
+ </vbox>
+ </widget>
+ </hbox>
+</widget>
+<connections>
+ <connection>
+ <sender>quitButton</sender>
+ <signal>clicked()</signal>
+ <receiver>RemoteCtrl</receiver>
+ <slot>close()</slot>
+ </connection>
+</connections>
+<layoutdefaults spacing="6" margin="11"/>
+</UI>
diff --git a/examples/network/remotecontrol/remotectrlimpl.cpp b/examples/network/remotecontrol/remotectrlimpl.cpp
new file mode 100644
index 0000000..bac7806
--- /dev/null
+++ b/examples/network/remotecontrol/remotectrlimpl.cpp
@@ -0,0 +1,50 @@
+#include "remotectrlimpl.h"
+
+#include <qpushbutton.h>
+#include <qlineedit.h>
+#include <qsocket.h>
+#include <qfiledialog.h>
+#include <qcolordialog.h>
+#include <qimage.h>
+
+RemoteCtrlImpl::RemoteCtrlImpl( QSocket *s )
+{
+ socket = s;
+ connect( sImage, SIGNAL(clicked()), SLOT(sendImage()) );
+ connect( sText, SIGNAL(clicked()), SLOT(sendText()) );
+ connect( sPalette, SIGNAL(clicked()), SLOT(sendPalette()) );
+}
+
+void RemoteCtrlImpl::sendPacket( const QVariant &v )
+{
+ QByteArray ba;
+ QDataStream varDs( ba, IO_WriteOnly );
+ varDs << v;
+
+ QDataStream ds( socket );
+ ds << (Q_UINT32) ba.size();
+ socket->writeBlock( ba.data(), ba.size() );
+}
+
+void RemoteCtrlImpl::sendImage()
+{
+ QString imageName = QFileDialog::getOpenFileName( QString::null,
+ "Images (*.png *.xpm *.jpg)", this );
+ QImage image( imageName );
+ if ( !image.isNull() ) {
+ sendPacket( image );
+ }
+}
+
+void RemoteCtrlImpl::sendText()
+{
+ sendPacket( textToSend->text() );
+}
+
+void RemoteCtrlImpl::sendPalette()
+{
+ QColor col = QColorDialog::getColor( white, this );
+ if ( col.isValid() ) {
+ sendPacket( QPalette(col,col) );
+ }
+}
diff --git a/examples/network/remotecontrol/remotectrlimpl.h b/examples/network/remotecontrol/remotectrlimpl.h
new file mode 100644
index 0000000..382c9df
--- /dev/null
+++ b/examples/network/remotecontrol/remotectrlimpl.h
@@ -0,0 +1,26 @@
+#ifndef REMOTECTRLIMPL_H
+#define REMOTECTRLIMPL_H
+
+#include "remotectrl.h"
+
+class QSocket;
+
+class RemoteCtrlImpl : public RemoteCtrl
+{
+ Q_OBJECT
+
+public:
+ RemoteCtrlImpl( QSocket * );
+
+private slots:
+ void sendImage();
+ void sendText();
+ void sendPalette();
+
+private:
+ void sendPacket( const QVariant & );
+
+ QSocket *socket;
+};
+
+#endif // REMOTECTRLIMPL_H
diff --git a/examples/network/remotecontrol/startup.cpp b/examples/network/remotecontrol/startup.cpp
new file mode 100644
index 0000000..03fa87f
--- /dev/null
+++ b/examples/network/remotecontrol/startup.cpp
@@ -0,0 +1,45 @@
+#include "startup.h"
+#include "remotectrlimpl.h"
+#include "maindialog.h"
+#include "ipcserver.h"
+
+#include <qsocket.h>
+#include <qlabel.h>
+
+static const Q_UINT16 ipcPort = 54923;
+
+StartUp::StartUp()
+{
+ remoteCtrl = 0;
+ mainDialog = 0;
+
+ socket = new QSocket( this );
+ connect( socket, SIGNAL(connected()), SLOT(startRemoteCtrl()) );
+ connect( socket, SIGNAL(error(int)), SLOT(startMainDialog()) );
+ socket->connectToHost( "localhost", ipcPort );
+}
+
+StartUp::~StartUp()
+{
+ delete remoteCtrl;
+ delete mainDialog;
+}
+
+void StartUp::startRemoteCtrl()
+{
+ remoteCtrl = new RemoteCtrlImpl( socket );
+ remoteCtrl->show();
+}
+
+void StartUp::startMainDialog()
+{
+ mainDialog = new MainDialog();
+ mainDialog->show();
+
+ IpcServer *server = new IpcServer( ipcPort, this );
+
+ connect( server, SIGNAL(receivedText(const QString&)),
+ mainDialog->description, SLOT(setText(const QString&)) );
+ connect( server, SIGNAL(receivedPixmap(const QPixmap&)),
+ mainDialog->image, SLOT(setPixmap(const QPixmap&)) );
+}
diff --git a/examples/network/remotecontrol/startup.h b/examples/network/remotecontrol/startup.h
new file mode 100644
index 0000000..900d841
--- /dev/null
+++ b/examples/network/remotecontrol/startup.h
@@ -0,0 +1,28 @@
+#ifndef STARTUP_H
+#define STARTUP_H
+
+#include <qobject.h>
+
+class QSocket;
+class RemoteCtrlImpl;
+class MainDialog;
+
+class StartUp : public QObject
+{
+ Q_OBJECT
+
+public:
+ StartUp();
+ ~StartUp();
+
+private slots:
+ void startRemoteCtrl();
+ void startMainDialog();
+
+private:
+ QSocket *socket;
+ RemoteCtrlImpl *remoteCtrl;
+ MainDialog *mainDialog;
+};
+
+#endif // STARTUP_H