OSDN Git Service

データベースの検討開始。
[wordring-tm/wordring-tm.git] / proxy / tmsocket.cpp
1 #include "tmsocket.h"
2 #include "tmwidget.h"
3
4 #include "html.h"
5
6 #include <QMutex>
7 #include <QMutexLocker>
8
9 #include <QJsonDocument>
10 #include <QJsonObject>
11
12 #include "debug.h"
13
14 // HtmlStringFragments --------------------------------------------------------
15
16 void TM::HtmlStringFragments::set_range(HtmlRange range)
17 {
18         m_fragments.clear();
19         m_state = 0;
20
21         for(HtmlNode const &node : range)
22         {
23                 if(node.type() != HtmlNode::Text) continue;
24                 HtmlStringFragment fragment;
25                 fragment.node = node;
26                 fragment.string = node.value();
27                 m_fragments.append(fragment);
28         }
29         for(HtmlStringFragment &fragment : m_fragments)
30         {
31                 QString result;
32                 QString &string = fragment.string;
33                 for(QChar const &ch : string)
34                 {
35                         QChar c = trim_whitespace(ch);
36                         if(c != '\0') result.append(c);
37                 }
38                 string = result;
39         }
40         QString &front = m_fragments.front().string;
41         if(front.startsWith(' ')) front.remove(0, 1);
42         QString &tail = m_fragments.back().string;
43         if(tail.endsWith(' ')) tail.remove(tail.size() - 1, 1);
44 }
45
46 QChar TM::HtmlStringFragments::trim_whitespace(QChar const &ch)
47 {
48         bool ws = false;
49         switch(ch.toLatin1())
50         {
51         case 0x9:
52         case 0xA:
53         case 0xC:
54         case 0xD:
55         case 0x20:
56         case 0x200B:
57                 ws = true;
58         }
59         switch(m_state)
60         {
61         case 0:
62                 if(ws)
63                 {
64                         m_state = 1;
65                         return ' ';
66                 }
67                 break;
68         case 1:
69                 if(ws) return '\0';
70                 else m_state = 0;
71         }
72         return ch;
73 }
74
75 QString TM::HtmlStringFragments::to_string()
76 {
77         QString result;
78
79         for(HtmlStringFragment const &fragment : m_fragments)
80         {
81                 result.append(fragment.string);
82         }
83
84         return result;
85 }
86
87 // SocketConnection -----------------------------------------------------------
88
89 TM::SocketConnection::SocketConnection(Widget *widget, QWebSocket *socket)
90         : QObject(socket)
91         , m_widget(widget)
92         , m_mutex(QMutex::Recursive)
93         , m_edit_mode(false)
94 {
95         connect(socket, SIGNAL(textMessageReceived(QString const&)),
96                         this, SLOT(onTextMessageReceived(QString const&)));
97         connect(socket, SIGNAL(binaryMessageReceived(QByteArray const&)),
98                         this, SLOT(onBinaryMessageReceived(QByteArray const&)));
99 }
100
101 TM::SocketConnection::~SocketConnection()
102 {
103         m_widget->detach(this);
104 }
105
106 QWebSocket* TM::SocketConnection::socket()
107 {
108         QWebSocket * result = qobject_cast<QWebSocket*>(parent());
109         assert(result);
110         return result;
111 }
112
113 void TM::SocketConnection::send_message(QString const &message)
114 {
115         socket()->sendTextMessage(message);
116 }
117
118 void TM::SocketConnection::send_message(QJsonObject const &json)
119 {
120         QJsonDocument doc;
121         doc.setObject(json);
122         send_message(doc.toJson().data());
123 }
124
125 void TM::SocketConnection::changeEditMode(bool edit_mode)
126 {
127         set_edit_mode(edit_mode);
128 }
129
130 void TM::SocketConnection::set_edit_mode(bool edit_mode)
131 {
132         if(edit_mode == m_edit_mode) return;
133
134         m_edit_mode = edit_mode;
135         QJsonObject json;
136         json["cmd"] = "set_edit_mode";
137         json["edit_mode"] = edit_mode;
138         send_message(json);
139
140 }
141
142 /*!
143  * \brief ウェブブラウザ上でクリックされ、editコマンドが発行されたときに呼び出されます。
144  */
145 void TM::SocketConnection::do_edit(QJsonObject const &json)
146 {
147         m_document.set_content(json["source"].toString().toUtf8());
148         HtmlNode body = m_document.first("html").first("body");
149         m_fragments.set_range(HtmlRange(body, body));
150         m_widget->set_string(m_fragments.to_string(), json["target"].toString());
151         //emit editCmd(json["id"].toInt(), m_document.to_string());
152         /*
153         QJsonObject reply;
154         reply["cmd"] = "doedit";
155         reply["id"] = json["id"].toString();
156         reply["html"] = "test2";
157         QJsonDocument doc;
158         doc.setObject(reply);
159         send_message(doc.toJson().data());
160         */
161 }
162
163 /*!
164  * \brief ウェブブラウザ上でドキュメントがフォーカスを取得し、
165  * focusコマンドが発行されたときに呼び出されます。
166  */
167 void TM::SocketConnection::do_focus(QJsonObject const &json)
168 {
169         m_widget->attach(this);
170         bool edit_mode = json["edit_mode"].toBool();
171         m_edit_mode = edit_mode;
172         m_widget->set_edit_mode(edit_mode);
173 }
174
175 void TM::SocketConnection::do_blur(QJsonObject const &)
176 {
177         //m_widget->detach(this);
178 }
179
180 void TM::SocketConnection::do_load(const QJsonObject &json)
181 {
182         m_widget->attach(this);
183         bool edit_mode = json["edit_mode"].toBool();
184         m_edit_mode = edit_mode;
185         m_widget->set_edit_mode(edit_mode);
186
187         //set_edit_mode(m_widget->edit_mode());
188 }
189
190 void TM::SocketConnection::onTextMessageReceived(QString const &message)
191 {
192         QJsonObject json = QJsonDocument::fromJson(message.toUtf8()).object();
193         QString cmd = json["cmd"].toString();
194         if(cmd == "edit") do_edit(json);
195         else if(cmd == "focus") do_focus(json);
196         else if(cmd == "blur") do_blur(json);
197         else if(cmd == "load") do_load(json);
198 }
199
200 void TM::SocketConnection::onBinaryMessageReceived(QByteArray const &message)
201 {
202         qDebug() << message;
203 }
204
205
206
207 // SocketServer ---------------------------------------------------------------
208
209 TM::SocketServer::SocketServer(Widget *widget, quint16 port, QObject *parent)
210         : QObject(parent)
211         , m_server(new QWebSocketServer(QStringLiteral("wordring websocket"),
212                                                                         QWebSocketServer::NonSecureMode, this))
213         , m_widget(widget)
214 {
215         bool result = m_server->listen(QHostAddress::LocalHost, port);
216         if(!result) qFatal("An error occured in SocketServer(quint16, QObject*).");
217
218         connect(m_server, SIGNAL(newConnection()), this, SLOT(onNewConnection()));
219 }
220
221 quint16 TM::SocketServer::port() const
222 {
223         return m_server->serverPort();
224 }
225
226 void TM::SocketServer::onNewConnection()
227 {
228         QWebSocket *socket = m_server->nextPendingConnection();
229         connect(socket, SIGNAL(disconnected()), this, SLOT(onDisconnected()));
230         new SocketConnection(m_widget, socket);
231 }
232
233 void TM::SocketServer::onDisconnected()
234 {
235         QWebSocket *socket = qobject_cast<QWebSocket*>(sender());
236         socket->deleteLater();
237 }
238
239
240
241
242
243