initial release
[pykit.git] / Publisher.cc
1 // $Id$
2 //
3 // Copyright (C) 2010
4
5 /** \file
6     \brief InternalNetworkAccessManager non-inline non-template implementation */
7
8 #include "Publisher.hh"
9 //#include "Publisher.ih"
10
11 // Custom includes
12 #include <iostream>
13 #include <QNetworkProxy>
14 #include <QVariant>
15 #include "Publisher.hh"
16 #include <boost/python.hpp>
17
18 //#include "Publisher.mpp"
19 #define prefix_
20 ///////////////////////////////cc.p////////////////////////////////////////
21
22 ///////////////////////////////////////////////////////////////////////////
23 // pykit::detail::InternalServerReply
24
25 namespace pykit {
26 namespace detail {
27
28     class InternalServerReply
29         : public QNetworkReply
30     {
31         Q_OBJECT;
32     public:
33         InternalServerReply(QNetworkAccessManager::Operation operation,
34                             QNetworkRequest const & networkRequest,
35                             Publisher * publisher);
36
37         // Forwarded to buffer
38         virtual bool atEnd() const;
39         virtual qint64 bytesAvailable() const;
40         virtual qint64 bytesToWrite() const;
41         virtual bool canReadLine() const;
42         virtual bool isSequential() const;
43         virtual qint64 pos() const;
44         virtual bool reset();
45         virtual bool seek(qint64 pos);
46         virtual qint64 size() const;
47         virtual bool waitForBytesWritten(int msecs);
48         virtual bool waitForReadyRead(int msecs);
49
50         virtual void abort();
51
52         using QNetworkReply::setHeader;
53
54         void clearResponse();
55
56     protected:
57         qint64 readData(char * data, qint64 maxSize);
58         qint64 writeData(char const * data, qint64 maxSize);
59
60     signals:
61         void initSignal();
62
63     private slots:
64         void initSlot();
65
66     private:
67         QBuffer buffer_;
68     };
69
70 }}
71
72 prefix_ pykit::detail::InternalServerReply::
73 InternalServerReply(QNetworkAccessManager::Operation operation,
74                     QNetworkRequest const & networkRequest, Publisher * publisher)
75 {
76     setRequest(networkRequest);
77     setOperation(operation);
78     setUrl(networkRequest.url());
79     open(ReadWrite | Unbuffered);
80     buffer_.open(ReadWrite | Unbuffered);
81
82     Request request (*this);
83     publisher->publish(request);
84
85     seek(0);
86     setHeader(QNetworkRequest::ContentLengthHeader, QVariant(size()));
87     setHeader(QNetworkRequest::ContentTypeHeader, QVariant("text/html; charset=UTF-8"));
88
89     // The following rigamole is needed to delay emitting readyRead() / finished() after until the
90     // connections to those signals have been set up.
91     //
92     // We use a queued signal here. This will call initSlot after processing has returned to the
93     // event loop.
94     connect(this, SIGNAL(initSignal()), this, SLOT(initSlot()), Qt::QueuedConnection);
95     emit initSignal();
96 }
97
98 prefix_ void pykit::detail::InternalServerReply::initSlot()
99 {
100     emit readyRead();
101     emit finished();
102 }
103
104 prefix_ bool pykit::detail::InternalServerReply::atEnd()
105     const
106 { return buffer_.atEnd(); }
107
108 prefix_ qint64 pykit::detail::InternalServerReply::bytesAvailable()
109     const
110 { return buffer_.bytesAvailable(); }
111
112 prefix_ qint64 pykit::detail::InternalServerReply::bytesToWrite()
113     const
114 { return buffer_.bytesToWrite(); }
115
116 prefix_ bool pykit::detail::InternalServerReply::canReadLine()
117     const
118 { return buffer_.canReadLine(); }
119
120 prefix_ bool pykit::detail::InternalServerReply::isSequential()
121     const
122 { return buffer_.isSequential(); }
123
124 prefix_ qint64 pykit::detail::InternalServerReply::pos()
125     const
126 { return buffer_.pos(); }
127
128 prefix_ bool pykit::detail::InternalServerReply::reset()
129 { return buffer_.reset(); }
130
131 prefix_ bool pykit::detail::InternalServerReply::seek(qint64 pos)
132 { return buffer_.seek(pos); }
133
134 prefix_ qint64 pykit::detail::InternalServerReply::size()
135     const
136 { return buffer_.size(); }
137
138 prefix_ bool pykit::detail::InternalServerReply::waitForBytesWritten(int msecs)
139 { return buffer_.waitForBytesWritten(msecs); }
140
141 prefix_ bool pykit::detail::InternalServerReply::waitForReadyRead(int msecs)
142 { return buffer_.waitForReadyRead(msecs); }
143
144 prefix_ qint64 pykit::detail::InternalServerReply::readData(char * data, qint64 maxSize)
145 { return buffer_.read(data,maxSize); }
146
147 prefix_ qint64 pykit::detail::InternalServerReply::writeData(char const * data, qint64 maxSize)
148 { return buffer_.write(data,maxSize); }
149
150 prefix_ void pykit::detail::InternalServerReply::abort()
151 {}
152
153 prefix_ void pykit::detail::InternalServerReply::clearResponse()
154 {
155     buffer_.buffer().clear();
156 }
157
158 ///////////////////////////////////////////////////////////////////////////
159 // pykit::Request
160
161 prefix_ void pykit::Request::write(std::string const & data)
162 {
163     reply_.write(data.c_str());
164 }
165
166 prefix_ void pykit::Request::reset()
167 {
168     reply_.clearResponse();
169 }
170
171 prefix_ void pykit::Request::setContentType(std::string const & contentType)
172 {
173     reply_.setHeader(QNetworkRequest::ContentTypeHeader, QVariant(contentType.c_str()));
174 }
175
176 prefix_ void pykit::Request::setLocation(std::string const & location)
177 {
178     reply_.setHeader(QNetworkRequest::LocationHeader, QVariant(location.c_str()));
179 }
180
181 prefix_ QUrl pykit::Request::url()
182     const
183 {
184     return reply_.url();
185 }
186
187 prefix_ pykit::Request::Request(detail::InternalServerReply & reply)
188     : reply_ (reply)
189 {}
190
191 ///////////////////////////////////////////////////////////////////////////
192 // pykit::InternalNetworkAccessManager
193
194 prefix_ pykit::InternalNetworkAccessManager::
195 InternalNetworkAccessManager(QNetworkAccessManager * manager, QObject * parent,
196                              Publisher * publisher)
197     : QNetworkAccessManager(parent), publisher_ (publisher)
198 {
199     setCache(manager->cache());
200     setCookieJar(manager->cookieJar());
201     setProxy(manager->proxy());
202     setProxyFactory(manager->proxyFactory());
203 }
204
205 prefix_ QNetworkReply *
206 pykit::InternalNetworkAccessManager::createRequest(Operation operation,
207                                                         QNetworkRequest const & request,
208                                                         QIODevice * device)
209 {
210     if (request.url().scheme() != "srv")
211         return QNetworkAccessManager::createRequest(operation, request, device);
212
213     return new detail::InternalServerReply(operation, request, publisher_);
214 }
215
216 #include "Publisher.moc"
217
218 ///////////////////////////////cc.e////////////////////////////////////////
219 #undef prefix_
220 //#include "Publisher.mpp"
221
222 \f
223 // Local Variables:
224 // mode: c++
225 // fill-column: 100
226 // comment-column: 40
227 // c-file-style: "j32"
228 // indent-tabs-mode: nil
229 // ispell-local-dictionary: "american"
230 // compile-command: "scons -U"
231 // End: