1 | /* |
2 | * Copyright (C) 2007 Thomas Georgiou <TAGeorgiou@gmail.com> and Jeff Cooper <weirdsox11@gmail.com> |
3 | * |
4 | * This program is free software; you can redistribute it and/or modify |
5 | * it under the terms of the GNU Library General Public License version 2 as |
6 | * published by the Free Software Foundation |
7 | * |
8 | * This program is distributed in the hope that it will be useful, |
9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
11 | * GNU General Public License for more details |
12 | * |
13 | * You should have received a copy of the GNU Library General Public |
14 | * License along with this program; if not, write to the |
15 | * Free Software Foundation, Inc., |
16 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. |
17 | */ |
18 | |
19 | #include "dictengine.h" |
20 | #include <iostream> |
21 | |
22 | #include <KDebug> |
23 | #include <KLocale> |
24 | #include <ktcpsocket.h> |
25 | |
26 | #include <Plasma/DataContainer> |
27 | |
28 | DictEngine::DictEngine(QObject* parent, const QVariantList& args) |
29 | : Plasma::DataEngine(parent, args) |
30 | , m_tcpSocket(0) |
31 | { |
32 | Q_UNUSED(args) |
33 | m_serverName = "dict.org" ; //In case we need to switch it later |
34 | m_dictName = "wn" ; //Default, good dictionary |
35 | } |
36 | |
37 | DictEngine::~DictEngine() |
38 | { |
39 | } |
40 | |
41 | void DictEngine::setDict(const QString &dict) |
42 | { |
43 | m_dictName = dict; |
44 | } |
45 | |
46 | void DictEngine::setServer(const QString &server) |
47 | { |
48 | m_serverName = server; |
49 | } |
50 | |
51 | static QString wnToHtml(const QString &word, QByteArray &text) |
52 | { |
53 | Q_UNUSED(word) |
54 | QList<QByteArray> splitText = text.split('\n'); |
55 | QString def; |
56 | def += "<dl>\n" ; |
57 | QRegExp linkRx("\\{(.*)\\}" ); |
58 | linkRx.setMinimal(true); |
59 | |
60 | bool isFirst=true; |
61 | while (!splitText.empty()) { |
62 | //150 n definitions retrieved - definitions follow |
63 | //151 word database name - text follows |
64 | //250 ok (optional timing information here) |
65 | //552 No match |
66 | QString currentLine = splitText.takeFirst(); |
67 | if (currentLine.startsWith(QLatin1String("151" ))) { |
68 | isFirst = true; |
69 | continue; |
70 | } |
71 | |
72 | if (currentLine.startsWith('.')) { |
73 | def += "</dd>" ; |
74 | continue; |
75 | } |
76 | |
77 | if (!(currentLine.startsWith(QLatin1String("150" )) |
78 | || currentLine.startsWith(QLatin1String("151" )) |
79 | || currentLine.startsWith(QLatin1String("250" )) |
80 | || currentLine.startsWith(QLatin1String("552" )))) { |
81 | currentLine.replace(linkRx,"<a href=\"\\1\">\\1</a>" ); |
82 | |
83 | if (isFirst) { |
84 | def += "<dt><b>" + currentLine + "</b></dt>\n<dd>" ; |
85 | isFirst = false; |
86 | continue; |
87 | } else { |
88 | if (currentLine.contains(QRegExp("([1-9]{1,2}:)" ))) { |
89 | def += "\n<br>\n" ; |
90 | } |
91 | currentLine.replace(QRegExp("^([\\s\\S]*[1-9]{1,2}:)" ), "<b>\\1</b>" ); |
92 | def += currentLine; |
93 | continue; |
94 | } |
95 | } |
96 | |
97 | } |
98 | |
99 | def += "</dl>" ; |
100 | return def; |
101 | } |
102 | |
103 | void DictEngine::getDefinition() |
104 | { |
105 | m_tcpSocket->readAll(); |
106 | QByteArray ret; |
107 | |
108 | m_tcpSocket->write(QByteArray("DEFINE " )); |
109 | m_tcpSocket->write(m_dictName.toAscii()); |
110 | m_tcpSocket->write(QByteArray(" \"" )); |
111 | m_tcpSocket->write(m_currentWord.toUtf8()); |
112 | m_tcpSocket->write(QByteArray("\"\n" )); |
113 | m_tcpSocket->flush(); |
114 | |
115 | while (!ret.contains("250" ) && !ret.contains("552" ) && !ret.contains("550" )) { |
116 | m_tcpSocket->waitForReadyRead(); |
117 | ret += m_tcpSocket->readAll(); |
118 | } |
119 | |
120 | connect(m_tcpSocket, SIGNAL(disconnected()), this, SLOT(socketClosed())); |
121 | m_tcpSocket->disconnectFromHost(); |
122 | // setData(m_currentWord, m_dictName, ret); |
123 | // qWarning()<<ret; |
124 | setData(m_currentWord, "text" , wnToHtml(m_currentWord,ret)); |
125 | } |
126 | |
127 | void DictEngine::getDicts() |
128 | { |
129 | QMap<QString, QString> theHash; |
130 | m_tcpSocket->readAll(); |
131 | QByteArray ret; |
132 | |
133 | m_tcpSocket->write(QByteArray("SHOW DB\n" ));; |
134 | m_tcpSocket->flush(); |
135 | |
136 | m_tcpSocket->waitForReadyRead(); |
137 | while (!ret.contains("250" )) { |
138 | m_tcpSocket->waitForReadyRead(); |
139 | ret += m_tcpSocket->readAll(); |
140 | } |
141 | |
142 | QList<QByteArray> retLines = ret.split('\n'); |
143 | QString tmp1, tmp2; |
144 | |
145 | while (!retLines.empty()) { |
146 | QString curr(retLines.takeFirst()); |
147 | |
148 | if (curr.startsWith(QLatin1String("554" ))) { |
149 | //TODO: What happens if no DB available? |
150 | //TODO: Eventually there will be functionality to change the server... |
151 | break; |
152 | } |
153 | |
154 | // ignore status code and empty lines |
155 | if (curr.startsWith(QLatin1String("250" )) || curr.startsWith(QLatin1String("110" )) |
156 | || curr.isEmpty()) { |
157 | continue; |
158 | } |
159 | |
160 | if (!curr.startsWith('-') && !curr.startsWith('.')) { |
161 | curr = curr.trimmed(); |
162 | tmp1 = curr.section(' ', 0, 0); |
163 | tmp2 = curr.section(' ', 1); |
164 | // theHash.insert(tmp1, tmp2); |
165 | //kDebug() << tmp1 + " " + tmp2; |
166 | setData("list-dictionaries" , tmp1, tmp2); |
167 | } |
168 | } |
169 | |
170 | m_tcpSocket->disconnectFromHost(); |
171 | // setData("list-dictionaries", "dictionaries", QByteArray(theHash); |
172 | } |
173 | |
174 | |
175 | |
176 | void DictEngine::socketClosed() |
177 | { |
178 | m_tcpSocket->deleteLater(); |
179 | m_tcpSocket = 0; |
180 | } |
181 | |
182 | bool DictEngine::sourceRequestEvent(const QString &query) |
183 | { |
184 | // FIXME: this is COMPLETELY broken .. it can only look up one query at a time! |
185 | // a DataContainer subclass that does the look up should probably be made |
186 | if (m_currentQuery == query) { |
187 | return false; |
188 | } |
189 | |
190 | if (m_tcpSocket) { |
191 | m_tcpSocket->abort(); //stop if lookup is in progress and new query is requested |
192 | m_tcpSocket->deleteLater(); |
193 | m_tcpSocket = 0; |
194 | } |
195 | |
196 | QStringList queryParts = query.split(':', QString::SkipEmptyParts); |
197 | if (queryParts.isEmpty()) { |
198 | return false; |
199 | } |
200 | |
201 | m_currentWord = queryParts.last(); |
202 | m_currentQuery = query; |
203 | |
204 | //asked for a dictionary? |
205 | if (queryParts.count() > 1) { |
206 | setDict(queryParts[queryParts.count()-2]); |
207 | //default to wordnet |
208 | } else { |
209 | setDict("wn" ); |
210 | } |
211 | |
212 | //asked for a server? |
213 | if (queryParts.count() > 2) { |
214 | setServer(queryParts[queryParts.count()-3]); |
215 | //default to wordnet |
216 | } else { |
217 | setServer("dict.org" ); |
218 | } |
219 | |
220 | if (m_currentWord.simplified().isEmpty()) { |
221 | setData(m_currentWord, m_dictName, QString()); |
222 | } else { |
223 | setData(m_currentWord, m_dictName, QString()); |
224 | m_tcpSocket = new KTcpSocket(this); |
225 | m_tcpSocket->abort(); |
226 | connect(m_tcpSocket, SIGNAL(disconnected()), this, SLOT(socketClosed())); |
227 | |
228 | if (m_currentWord == "list-dictionaries" ) { |
229 | connect(m_tcpSocket, SIGNAL(readyRead()), this, SLOT(getDicts())); |
230 | } else { |
231 | connect(m_tcpSocket, SIGNAL(readyRead()), this, SLOT(getDefinition())); |
232 | } |
233 | |
234 | m_tcpSocket->connectToHost(m_serverName, 2628); |
235 | } |
236 | |
237 | return true; |
238 | } |
239 | |
240 | #include "dictengine.moc" |
241 | |