Develop and Download Open Source Software

Browse Subversion Repository

Contents of /src/kimo2chtextbrowser.cpp

Parent Directory Parent Directory | Revision Log Revision Log


Revision 16 - (show annotations) (download) (as text)
Thu Jul 15 14:45:50 2010 UTC (13 years, 10 months ago) by mip
File MIME type: text/x-c++src
File size: 12655 byte(s)
New thread post feature
and some bug fix

1 #include "kimo2chtextbrowser.h"
2
3 extern Kimo2chPrefs applicationPrefs;
4 #define PARSERTHREAD
5
6 Kimo2chTextBrowser::Kimo2chTextBrowser(QWidget *parent, Kimo2chTextBrowser *parentPopupWidget)
7 :QTextBrowser(parent)
8 ,parentPopup(parentPopupWidget)
9 {
10 popup = NULL;
11 popupBrowser = NULL;
12 cm = NULL;
13 setAttribute(Qt::WA_Hover, true);
14 isEnterCursor = false;
15 setDocument(new QTextDocument(this));
16 #ifdef PARSERTHREAD
17 parserThread = new ParserThread(this);
18 connect(parserThread, SIGNAL(parseCompleted()), this, SLOT(setParsedText()));
19 #endif
20 }
21
22 Kimo2chTextBrowser::~Kimo2chTextBrowser()
23 {
24 #ifdef PARSERTHREAD
25 if(parserThread)
26 {
27 if(parserThread->isRunning())
28 {
29 parserThread->exit();
30 parserThread->wait();
31 }
32 delete parserThread;
33 parserThread = NULL;
34 }
35 /*
36 if(popup)
37 {
38 Kimo2chTextBrowser *browser = popup->findChild<Kimo2chTextBrowser*>("Popup");
39 if(browser)
40 {
41 delete browser;
42 browser = NULL;
43 delete popup;
44 popup = NULL;
45 }
46 }
47 */
48 #endif
49 }
50
51 void Kimo2chTextBrowser::setDat(QStringList dat, int count)
52 {
53 clearHistory();
54 #ifdef PARSERTHREAD
55 readedCount = count;
56 if(parserThread->isRunning())
57 {
58 parserThread->terminate();
59 }
60 datRef = dat;
61 parserThread->start();
62 #else
63 readedCount = count;
64 datRef = dat;
65 idMap.clear();
66 QString parsedText;
67 QTextStream parsedStream(&parsedText);
68 // Font family and size settings
69 parsedStream << "<body style=\"font-family : " << browserFontFamily << "; font-size :" << browserFontPointSize << "pt;\">";
70
71 QStringList::iterator iter = datRef.begin();
72 int i = 1;
73 while(iter != datRef.end())
74 {
75 QString datLine = *iter;
76 QStringList resItems = datLine.split("<>");
77 if(resItems.count() < 4)
78 {
79 // QMessageBox::warning(browser, tr("File error"), tr("DAT file is broken. Res format invalid."));
80 return;
81 }
82 QString idAnchor;
83 int idstart = resItems[2].indexOf("ID:");
84 if(idstart >= 0)
85 {
86 int idlength = resItems[2].indexOf(QRegExp("\\s"), idstart) - idstart;
87 QString id = resItems[2].mid(idstart, (idlength < 0) ? -1 : idlength);
88 idMap.insert(id, i);
89 }
90 parsedStream << "<a name=\"res" << i << "\">" << i << "</a> " << ResParser::parse(datLine);
91 iter++;
92 if(i > 1 && i == readedCount && iter != datRef.end())
93 {
94 parsedStream << "<hr>" << tr("New message(s)") << "<hr>";
95 }
96 i++;
97 }
98 parsedStream << "<br>"; // Add last blank line for margin.
99 #if 0
100 QTextDocument *oldDocument = this->document();
101 QTextDocument *newDocument = new QTextDocument(this);
102 newDocument->setHtml(parsedText);
103 setDocument(newDocument);
104 oldDocument->deleteLater();
105 #else
106 // document()->clear();
107 clock_t t1 = clock();
108 setText(parsedText);
109 clock_t t2 = clock();
110 qDebug() << "setHtml() time =" << t2 - t1;
111 #endif
112 scrollToAnchor(QString("res%1").arg(readedCount));
113 #endif
114 }
115
116 void Kimo2chTextBrowser::setParsedText()
117 {
118 qDebug() << "setText() start";
119 QTextDocument *oldDocument = document();
120 setDocument(new QTextDocument(this));
121 // document()->clear();
122 clock_t t1 = clock();
123 setText(parsedText);
124 clock_t t2 = clock();
125 qDebug() << "setHtml() time =" << t2 - t1;
126 scrollToAnchor(QString("res%1").arg(readedCount));
127 oldDocument->deleteLater();
128 }
129
130 /*
131 Anchor rewrite
132 */
133 QString Kimo2chTextBrowser::rewriteAnchor(const QString originalText)
134 {
135 QString tempText(originalText);
136 tempText.replace("���", "~");
137 // Res number anchor rewrite
138 tempText.remove(QRegExp("<a \\S+ target=\"_blank\">")); // Remove start tags
139 int pos = 0;
140 while((pos = tempText.indexOf(QRegExp("&gt;&gt;(-\\,\\d{,4})*</a>"), pos)) != -1)
141 {
142 int endpos = tempText.indexOf("</a>", pos);
143 QString anchor = tempText.mid(pos + 8, endpos - pos - 8);
144 tempText.insert(pos, QString("<a href=\"#res%1\">").arg(anchor));
145 pos = endpos + anchor.length() + 15;
146 }
147 // Anchor insert to URLs
148 pos = 0;
149 while((pos = tempText.indexOf(QRegExp("(http|ttp|tp)://"), pos)) != -1)
150 {
151 int endpos = tempText.indexOf(QRegExp("([^a-zA-Z0-9~%&#=\\(\\)\\:/\\-\\.\\?\\_])"), pos);
152 tempText.insert(endpos, "</a>");
153 QString url = tempText.mid(pos, endpos - pos);
154 url = url.mid(url.indexOf(":"));
155 tempText.insert(pos, QString("<a href=\"http%1\">").arg(url));
156 pos = endpos + url.length() + 15;
157 }
158 return tempText;
159 }
160
161 /*
162 Anchor res(message) popup
163 */
164 void Kimo2chTextBrowser::mouseMoveEvent(QMouseEvent *e)
165 {
166 if(parserThread && parserThread->isRunning())
167 {
168 return;
169 }
170 QString anchor = anchorAt(e->pos());
171 if(!(anchor.startsWith("#")) || (popup != NULL && popup->isVisible()))
172 {
173 QTextBrowser::mouseMoveEvent(e);
174 }
175 else
176 {
177 QDesktopWidget desktop;
178 if(popup == NULL)
179 {
180 popup = new QWidget(this, Qt::ToolTip);
181 popup->setAttribute(Qt::WA_DeleteOnClose, true);
182 popupBrowser = new Kimo2chTextBrowser(popup, this);
183 connect(popupBrowser, SIGNAL(linkClicked(QUrl)), this, SLOT(relayLink(QUrl)));
184 popupBrowser->setObjectName("Popup");
185 popupBrowser->setFont(font());
186 popupBrowser->setFontFamily(fontFamily());
187 popupBrowser->setFontPointSize(browserFontPointSize/*fontPointSize()*/);
188 popupBrowser->setLineWrapMode(QTextEdit::NoWrap);
189 popupBrowser->setDatData(datRef, idMap);
190 popup->hide();
191 }
192 QString parsedText;
193 QTextStream parsedStream(&parsedText);
194 // Hover cursor at res anchors
195 if(anchor.startsWith("#res"))
196 {
197 int startRes, endRes;
198 QString res = anchor.mid(4);
199 if(res.contains('-'))
200 {
201 startRes = res.split('-').at(0).toInt();
202 endRes = res.split('-').at(1).toInt();
203 }
204 else
205 {
206 startRes = endRes = res.toInt();
207 }
208 for(int num = startRes; num <= endRes; num++)
209 {
210 if(num > datRef.count())
211 {
212 popup->hide();
213 return;
214 }
215 QStringList resItems = datRef.at(num - 1).split("<>");
216 parsedStream << "<body style=\"font-family : " << applicationPrefs.browserFontFamily
217 << "; font-size : " << applicationPrefs.browserFontSize << "pt; \">";
218 parsedStream << num << ResParser::parse(datRef.at(num - 1));
219 }
220 }
221 else if(anchor.startsWith("#ID"))
222 {
223 QString id = anchor.mid(1);
224 if(id.length() < 11)
225 {
226 QToolTip::hideText();
227 return;
228 }
229 parsedStream << " <body style=\"font-family : " << applicationPrefs.browserFontFamily
230 << "; font-size : " << applicationPrefs.browserFontSize << "pt; \">";
231 QList<int> resList = idMap.values(id);
232 while(!resList.isEmpty())
233 {
234 int resNum = resList.takeLast();
235 QStringList resItems = datRef.at(resNum - 1).split("<>");
236 parsedStream << resNum << ResParser::parse(datRef.at(resNum - 1));
237 }
238 }
239 else
240 {
241 return;
242 }
243 isEnterCursor = false;
244 popupBrowser->setText(parsedText);
245 QSizeF size = popupBrowser->document()->size();
246 int margin = verticalScrollBar()->width() + 8;
247 popupBrowser->setFixedWidth(size.width() + margin < (desktop.width() / 2)? size.width() + margin : desktop.width() / 2);
248 popupBrowser->setFixedHeight(size.height() + margin < desktop.height() ? size.height() + margin : desktop.height());
249 QPoint pos = e->globalPos();
250 popup->move(pos.x() + size.width() < desktop.width() ? pos.x() : (pos.x() - size.width() > 0 ? pos.x() - size.width() : 0)
251 , pos.y() + size.height() < desktop.height() ? pos.y() : desktop.height() - popupBrowser->height());
252 popupBrowser->isEnterCursor = false;
253 popup->show();
254 }
255 QTextBrowser::mouseMoveEvent(e);
256 }
257
258 /*
259 Link clicked
260 */
261 void Kimo2chTextBrowser::mouseReleaseEvent(QMouseEvent *e)
262 {
263 //
264 QString anchor = anchorAt(e->pos());
265 if(anchor == "")
266 {
267 QTextBrowser::mouseReleaseEvent(e);
268 }
269 else
270 {
271 if(anchor.startsWith("#"))
272 {
273 if(anchor.startsWith("#res"))
274 {
275 this->scrollToAnchor(anchor.mid(1));
276 }
277 }
278 else
279 {
280 QUrl url = QUrl::fromEncoded(anchor.toAscii());
281 linkClicked(url);
282 }
283 }
284 }
285
286 /*
287 Context menu
288 */
289 void Kimo2chTextBrowser::contextMenuEvent(QContextMenuEvent *e)
290 {
291 // QTextBrowser::contextMenuEvent(e);
292 cm = createStandardContextMenu(e->globalPos());
293 copyURLAction = cm->addAction(QString(tr("Copy this link")), this, SLOT(copyAnchor()));
294 QString anchor = anchorAt(e->pos());
295 if(anchor.startsWith("http"))
296 {
297 anchorText = anchor;
298 }
299 else
300 {
301 copyURLAction->setEnabled(false);
302 }
303 if(anchor.startsWith("#ID:"))
304 {
305 copyAction = cm->addAction(tr("Copy this ID"), this, SLOT(copyHeadItem()));
306 copyAction->setData(anchor.mid(4));
307
308 aboneAction = cm->addAction(QString(tr("Abone %1").arg(anchor.mid(4))), this, SLOT(addAboneId()));
309 aboneAction->setData(anchor);
310 }
311 else if(anchor.startsWith("#NAME:"))
312 {
313 copyAction = cm->addAction(QString(tr("Copy this name %1").arg(anchor.mid(6))), this, SLOT(copyHeadItem()));
314 copyAction->setData(anchor.mid(6));
315
316 aboneAction = cm->addAction(QString(tr("Abone name for %1").arg(anchor.mid(6))), this, SLOT(addAboneName()));
317 aboneAction->setData(anchor.mid(6));
318 }
319 else if(anchor.startsWith("#MAIL:"))
320 {
321 copyAction = cm->addAction(tr("Copy this mail"), this, SLOT(copyHeadItem()));
322 copyAction->setData(anchor.mid(6));
323
324 aboneAction = cm->addAction(QString(tr("Abone mail for %1").arg(anchor.mid(6))), this, SLOT(addAboneMail()));
325 aboneAction->setData(anchor.mid(6));
326 }
327 cm->exec(e->globalPos());
328 delete cm;
329 cm = NULL;
330 }
331
332 /*******************************
333 Slots
334 *******************************/
335
336 /*
337 * relayLink
338 */
339
340 void Kimo2chTextBrowser::relayLink(QUrl url)
341 {
342 linkClicked(url);
343 }
344
345 /*
346 * copyAnchor
347 */
348 void Kimo2chTextBrowser::copyAnchor()
349 {
350 qDebug() << "Copy URL";
351 QClipboard *cb = QApplication::clipboard();
352 cb->setText(anchorText);
353 delete copyURLAction;
354 }
355
356 // Copy
357 void Kimo2chTextBrowser::copyHeadItem()
358 {
359 QClipboard *cb = QApplication::clipboard();
360 cb->setText(copyAction->data().toString());
361 delete copyAction;
362 delete aboneAction;
363 delete copyURLAction;
364 }
365
366
367 /*
368 * Add to Abone lists
369 */
370
371 void Kimo2chTextBrowser::addAboneId()
372 {
373 ResParser::aboneId.insert(aboneAction->data().toString().mid(1), true);
374 delete aboneAction;
375 delete copyAction;
376 delete copyURLAction;
377 // ResParser::aboneId.insert(aboneIdAction->data().toString().mid(1), true);
378 }
379
380 void Kimo2chTextBrowser::addAboneName()
381 {
382 ResParser::aboneName.insert(aboneAction->data().toString(), true);
383 delete aboneAction;
384 delete copyAction;
385 delete copyURLAction;
386 }
387
388 void Kimo2chTextBrowser::addAboneMail()
389 {
390 ResParser::aboneMail.insert(aboneAction->data().toString(), true);
391 delete aboneAction;
392 delete copyAction;
393 delete copyURLAction;
394 }
395
396 void Kimo2chTextBrowser::closePopup()
397 {
398 #if 0
399 if(popupBrowser != NULL)
400 {
401 popupBrowser->closePopup();
402 }
403 if(objectName() == "Popup")
404 {
405 // parentWidget()->close();
406 delete popup;
407 }
408 popup = NULL;
409 #endif
410 if(popup)
411 {
412 popup->close();
413 // delete popup;
414 popup = NULL;
415 }
416 // popupBrowser = NULL;
417 }
418
419 void Kimo2chTextBrowser::enterEvent(QEvent */*e*/)
420 {
421 isEnterCursor = true;
422 }
423
424 void Kimo2chTextBrowser::leaveEvent(QEvent */*e*/)
425 {
426 if(parentPopup && isEnterCursor && cm == NULL)
427 {
428 parentPopup->closePopup();
429 }
430 }
431
432 void Kimo2chTextBrowser::setFontFamily(const QString &fontFamily)
433 {
434 browserFontFamily = fontFamily;
435 QTextBrowser::setFontFamily(fontFamily);
436 }
437
438 void Kimo2chTextBrowser::setFontPointSize(qreal s)
439 {
440 browserFontPointSize = s;
441 QTextBrowser::setFontPointSize(s);
442 }
443
444 /*******************************************************
445 ParserThread
446 *******************************************************/
447
448 ParserThread::ParserThread(Kimo2chTextBrowser *parent)
449 : QThread(parent), browser(parent)
450 {
451 // browser = parent;
452 }
453
454 void ParserThread::run()
455 {
456 datRef = browser->getDatRef();
457 readedCount = browser->getReadedCount();
458 QMultiMap<QString, int> *idMap = browser->getIdMap();
459 idMap->clear();
460 QString parsedText;
461 QTextStream parsedStream(&parsedText);
462 // Font family and size settings
463 parsedStream << "<body style=\"font-family : " << browser->browserFontFamily << "; font-size :" << browser->browserFontPointSize << "pt;\">";
464
465 QStringList::iterator iter = datRef->begin();
466 int i = 1;
467 while(iter != datRef->end())
468 {
469 QString datLine = *iter;
470 QStringList resItems = datLine.split("<>");
471 if(resItems.count() < 4)
472 {
473 // QMessageBox::warning(browser, tr("File error"), tr("DAT file is broken. Res format invalid."));
474 return;
475 }
476 QString idAnchor;
477 int idstart = resItems[2].indexOf("ID:");
478 if(idstart >= 0)
479 {
480 int idlength = resItems[2].indexOf(QRegExp("\\s"), idstart) - idstart;
481 QString id = resItems[2].mid(idstart, (idlength < 0) ? -1 : idlength);
482 idMap->insert(id, i);
483 }
484 parsedStream << "<a name=\"res" << i << "\">" << i << "</a> " << ResParser::parse(datLine);
485 iter++;
486 if(i > 1 && i == readedCount && iter != datRef->end())
487 {
488 parsedStream << "<hr>" << tr("New message(s)") << "<hr>";
489 }
490 i++;
491 }
492 parsedStream << "<br>"; // Add last blank line for margin.
493 browser->setParsedText(parsedText);
494 // browser->setHtml(parsedText);
495 parseCompleted();
496 }

Back to OSDN">Back to OSDN
ViewVC Help
Powered by ViewVC 1.1.26