OSDN Git Service

>>657, show AA correctly, for KDE 3.1.x
[kita/kita.git] / kita / src / libkita / datmanager.cpp
1 /***************************************************************************
2 *   Copyright (C) 2004 by Kita Developers                                 *
3 *   ikemo@users.sourceforge.jp                                            *
4 *                                                                         *
5 *   This program is free software; you can redistribute it and/or modify  *
6 *   it under the terms of the GNU General Public License as published by  *
7 *   the Free Software Foundation; either version 2 of the License, or     *
8 *   (at your option) any later version.                                   *
9 ***************************************************************************/
10
11 /* DatManager manages all information about thread */
12
13 #include <qobject.h>
14 #include <qmutex.h>
15 #include <qstringlist.h>
16 #include <qregexp.h>
17 #include <qfile.h>
18
19 #include "thread.h"
20 #include "threadinfo.h"
21 #include "datmanager.h"
22 #include "datinfo.h"
23 #include "cache.h"
24 #include "kita_misc.h"
25 #include "kita-utf8.h"
26 #include "kita-utf16.h"
27 #include "threadindex.h"
28 #include "boardmanager.h"
29
30 using namespace Kita;
31
32 #define DMANAGER_MAXQUEUE 16
33
34 DatInfoList DatManager::m_datInfoList;
35 QMutex DatManager::m_mutex;
36
37
38 /*-----------------------------------------------------------------------*/
39
40
41 /* create DatInfo explicitly.                    */
42 /* Usually, DatInfo is NOT created
43    if cache does not exist( i.e. ReadNum == 0 ). */ /* public */
44 bool DatManager::createDatInfo( const KURL& url )
45 {
46     if( getDatInfo( url,
47                     FALSE /* don't check the existence of cache */
48             ) == NULL ) return FALSE;
49     return TRUE;
50 }
51
52
53 /* get pointer of DatInfo */
54
55 /*    !!!  NOTICE  !!!   */
56 /* It is very dangerous to access to DatInfo directly. */
57 /* Usually, access to it through DatManager.           */ /* public */
58 DatInfo * DatManager::getDatInfoPointer( const KURL& url )
59 {
60     return getDatInfo( url );
61 }
62
63
64 /*------------------------------------------------------------------------*/
65
66
67 /* This function searches instance of DatInfo in m_datInfoList.
68
69    If cache exists, create DatInfo and return its pointer.
70
71    If checkCached == TRUE and cache does not exist, return NULL.
72
73    If checkCached == FALSE and cache does not exist,
74    create DatInfo and return its pointer anyway.
75
76    see also DatManager::searchDatInfo() and DatManager::createDatInfo() */ /* private */
77
78 DatInfo* DatManager::getDatInfo( const KURL& url, bool checkCached )
79 {
80     /* search */
81     DatInfo* datInfo = searchDatInfo( url );
82     if( datInfo != NULL ) return datInfo;
83
84     /* create and enroll instance */
85     return enrollDatInfo( url, checkCached );
86 }
87
88
89 /* This function just searches instance of DatInfo specified by datURL
90    without creating instance.  */ /* private */
91 DatInfo* DatManager::searchDatInfo( const KURL& url )
92 {
93     QMutexLocker locker( &m_mutex );
94     
95     KURL datURL = Kita::getDatURL( url );
96     if ( datURL.isEmpty() ) return NULL; /* This url is not enrolled in BoardManager. */
97     if ( m_datInfoList.count() == 0 ) return NULL;
98
99     int i = 0;
100     DatInfoList::Iterator it;
101     DatInfo* datInfo;
102     
103     for ( it = m_datInfoList.begin(); it != m_datInfoList.end(); ++it, i++ ) {
104
105         datInfo = ( *it );
106
107         if ( datURL == datInfo->url() ) {
108
109             /* LRU */
110             if ( i ) {
111                 m_datInfoList.remove( it );
112                 m_datInfoList.prepend( datInfo );
113             }
114
115             return datInfo;
116         }
117     }
118
119     return NULL;
120 }
121
122
123 /* create and enroll the instance of DatInfo and delete old instances. 
124    Note that DatInfo::DatInfo() opens cached data and reads it. */  /* private */
125 DatInfo* DatManager::enrollDatInfo( const KURL& url, bool checkCached )
126 {
127     QMutexLocker locker( &m_mutex );
128     
129     KURL datURL = Kita::getDatURL( url );
130     if( datURL.isEmpty() ) return NULL; /* This url is not enrolled in BoardManager. */
131
132     /* create DatInfo & read cached data */
133     DatInfo* datInfo = new DatInfo( datURL );
134
135     /* Does cache exist ? */
136     /* If cache does not exist, delete DatInfo here. */
137     if( checkCached && datInfo->getReadNum() == 0 ){
138         delete datInfo;
139         return NULL;
140     }
141
142     m_datInfoList.prepend( datInfo );
143
144     /* delete the all old instances ( LRU algorithm )*/
145     if ( m_datInfoList.count() > DMANAGER_MAXQUEUE ) {
146
147         DatInfoList::Iterator it;
148         for ( it = m_datInfoList.at( DMANAGER_MAXQUEUE ); it != m_datInfoList.end(); ++it ){
149
150             if( ( *it ) == NULL ) continue;
151             DatInfo* deleteInfo = ( *it );
152             
153             if ( ! deleteInfo->isLocked() ){
154                 m_datInfoList.remove( it );
155                 --it;
156                 deleteInfo->wait(); /* wait until DatInfo::m_mutex is released. */
157                 delete deleteInfo;
158             }
159         }
160     }
161
162     return datInfo;
163 }
164
165
166 /* public */
167 void DatManager::deleteAllDatInfo()
168 {
169     DatInfoList::Iterator it;
170     for ( it = m_datInfoList.begin(); it != m_datInfoList.end(); ++it ){
171
172         if( ( *it ) == NULL ) continue;
173         ( *it )->wait();
174         delete ( *it );
175     }
176 }
177
178
179
180 /*-------------------------------------------------------------*/
181
182
183
184 /* update cache */   /* public */
185 bool DatManager::updateCache( const KURL& url , const QObject* parent )
186 {
187     DatInfo * datInfo = getDatInfo( url );
188     if ( datInfo == NULL ) return FALSE;
189
190     return datInfo->updateCache( parent );
191 }
192
193
194 /* public */
195 int DatManager::getResponseCode( const KURL& url )
196 {
197     DatInfo * datInfo = getDatInfo( url );
198     if ( datInfo == NULL ) return 0;
199
200     return datInfo->getResponseCode();
201 }
202
203 /* public */
204 int DatManager::getServerTime( const KURL& url )
205 {
206     DatInfo * datInfo = getDatInfo( url );
207     if ( datInfo == NULL ) return 0;
208
209     return datInfo->getServerTime();
210 }
211
212
213 /* public */
214 bool DatManager::deleteCache( const KURL& url )
215 {
216     KURL datURL = Kita::getDatURL( url );
217     Kita::Thread* thread = Kita::Thread::getByURLNew( datURL );
218     if( thread == NULL ) return FALSE;
219     if( thread->readNum() == 0 ) return FALSE;
220
221     /* init DatInfo */
222     DatInfo * datInfo = searchDatInfo( datURL );
223     if( datInfo ){
224         if( !datInfo->deleteCache() ) return FALSE;
225     }
226
227     /* reset readNum & veiwPos */
228     thread->setReadNum( 0 );
229     thread->setViewPos( 0 );
230
231     /* delete cache */
232     QString cachePath = Kita::Cache::getPath( datURL );
233     QString indexPath = Kita::Cache::getIndexPath( datURL );
234     QFile::remove( indexPath );
235     QFile::remove( cachePath );
236
237     /* delete log from "cache" */
238     KitaThreadInfo::removeThreadInfo( datURL.prettyURL() );
239     return TRUE;
240 }
241
242
243 /* public */
244 bool DatManager::isLoadingNow( const KURL& url )
245 {
246     DatInfo * datInfo = searchDatInfo( url );
247     if ( datInfo == NULL ) return FALSE;
248
249     return datInfo->isLoadingNow();
250 }
251
252
253 /* public */
254 void DatManager::stopLoading( const KURL& url )
255 {
256     DatInfo * datInfo = searchDatInfo( url );
257     if ( datInfo == NULL ) return ;
258
259     return datInfo->stopLoading();
260 }
261
262
263
264 /*----------------------*/
265 /* lock, unlock DatInfo */
266
267 /* public */
268 void DatManager::lock( const KURL& url )
269 {
270     DatInfo * datInfo = getDatInfo( url );
271     if( datInfo == NULL ) return;
272
273     datInfo->lock ();
274 }
275
276 /* public */
277 void DatManager::unlock( const KURL& url )
278 {
279     DatInfo * datInfo = searchDatInfo( url );
280     if ( datInfo == NULL ) return ;
281
282     datInfo->unlock();
283 }
284
285
286 /*--------------------------------------*/
287 /* string data */
288
289
290 /* public */
291 const QString& DatManager::getDat( const KURL& url, int num )
292 {
293     DatInfo * datInfo = getDatInfo( url );
294     if ( datInfo == NULL ) return QString::null;
295
296     return datInfo->getDat( num );
297 }
298
299
300
301 /* public */
302 const QString& DatManager::getId( const KURL& url, int num )
303 {
304     DatInfo * datInfo = getDatInfo( url );
305     if ( datInfo == NULL ) return QString::null;
306
307     return datInfo->getId( num );
308 }
309
310
311 /* public */
312 QString DatManager::getPlainName( const KURL& url, int num )
313 {
314     DatInfo * datInfo = getDatInfo( url );
315     if ( datInfo == NULL ) return QString::null;
316
317     return datInfo->getPlainName( num );
318 }
319
320
321 /* public */
322 QString DatManager::getPlainBody( const KURL& url, int num )
323 {
324     DatInfo * datInfo = getDatInfo( url );
325     if ( datInfo == NULL ) return QString::null;
326
327     return datInfo->getPlainBody( num );
328 }
329
330
331 /* public */
332 QString DatManager::getPlainTitle( const KURL& url, int num )
333 {
334     DatInfo * datInfo = getDatInfo( url );
335     if ( datInfo == NULL ) return QString::null;
336
337     return datInfo->getPlainTitle( num );
338 }
339
340
341 /* get name (i.e. subject ) of thread from URL of dat file. */ /* public */
342 const QString DatManager::threadName( const KURL& url )
343 {
344     KURL datURL = Kita::getDatURL( url );
345     Kita::Thread* thread = Kita::Thread::getByURLNew( datURL );
346     if( thread != NULL ) return thread->threadName();
347
348     return QString::null;
349 }
350
351
352 /* public */
353 const QString DatManager::threadID( const KURL& url )
354 {
355     KURL datURL = Kita::getDatURL( url );
356     return datURL.filename().section( ".", 0, 0 );
357 }
358
359
360 const QString DatManager::getCachePath( const KURL& url )
361 {
362     return Kita::Cache::getPath( url );
363 }
364
365 const QString DatManager::getCacheIndexPath( const KURL& url )
366 {
367     return Kita::Cache::getIndexPath( url );
368 }
369
370 /*---------------------------------------*/
371 /* HTML data */
372
373 /* public */
374 QString DatManager::getHtml( const KURL& url, int startnum, int endnum, bool checkAbone )
375 {
376     DatInfo * datInfo = getDatInfo( url );
377     if ( datInfo == NULL ) return QString::null;
378
379     return datInfo->getHTMLString( startnum, endnum, checkAbone );
380 }
381
382
383
384 /* public */
385 QString DatManager::getHtmlByID( const KURL& url, const QString& strid, int &count )
386 {
387     DatInfo* datInfo = getDatInfo( url );
388     if ( datInfo == NULL ) return QString::null;
389
390     return datInfo->getHtmlByID( strid, count );
391 }
392
393
394
395 /* Get HTML document of res tree.*/ /* public */
396 QString DatManager::getTreeByRes( const KURL& url, const int rootnum, int &count )
397 {
398     DatInfo* datInfo = getDatInfo( url );
399     if ( datInfo == NULL ) return QString::null;
400
401     return datInfo->getTreeByRes( rootnum, count );
402 }
403
404 /* Get HTML document of reverse res tree.*/ /* public */
405 QString DatManager::getTreeByResReverse( const KURL& url, const int rootnum, int &count )
406 {
407     DatInfo* datInfo = getDatInfo( url );
408     if ( datInfo == NULL ) return QString::null;
409
410     return datInfo->getTreeByResReverse( rootnum, count );
411 }
412
413
414 /* public */
415 int DatManager::getResNum( const KURL& url )
416 {
417     KURL datURL = Kita::getDatURL( url );
418     Kita::Thread* thread = Kita::Thread::getByURLNew( datURL );
419     if( thread != NULL ) return thread->resNum();
420
421     return 0;
422 }
423
424
425 /* public */
426 int DatManager::getReadNum( const KURL& url )
427 {
428     KURL datURL = Kita::getDatURL( url );
429     Kita::Thread* thread = Kita::Thread::getByURLNew( datURL );
430     if( thread != NULL ) return thread->readNum();
431
432     return 0;
433 }
434
435
436 /* public */
437 int DatManager::getViewPos( const KURL& url )
438 {
439     KURL datURL = Kita::getDatURL( url );
440     Kita::Thread* thread = Kita::Thread::getByURLNew( datURL );
441     if( thread != NULL ) return thread->viewPos();
442
443     return 0;
444 }
445
446
447 /* public */
448 void DatManager::setViewPos( const KURL& url , int num )
449 {
450     KURL datURL = Kita::getDatURL( url );
451     Kita::Thread* thread = Kita::Thread::getByURLNew( datURL );
452     if( thread != NULL ) thread->setViewPos( num );
453
454     /* save idx */
455     Kita::ThreadIndex::setViewPos( url, num );
456
457     /* save "cache" */
458     KitaThreadInfo::setReadNum( datURL.prettyURL(), num );
459 }
460
461
462 /* public */
463 int DatManager::getDatSize( const KURL& url )
464 {
465     DatInfo * datInfo = getDatInfo( url );
466     if ( datInfo == NULL ) return 0;
467
468     return datInfo->getDatSize();
469 }
470
471 /* get number of responses which have same ID. */ /* public */
472 int DatManager::getNumByID( const KURL& url, const QString& strid )
473 {
474     DatInfo * datInfo = getDatInfo( url );
475     if ( datInfo == NULL ) return 0;
476
477     return datInfo->getNumByID( strid );
478 }
479
480
481 /* public */
482 bool DatManager::isThreadEnrolled( const KURL& url )
483 {
484     if( Kita::getDatURL( url ).isEmpty() ) return FALSE;
485
486     return TRUE;
487 }
488
489
490 /* public */
491 bool DatManager::is2chThread( const KURL& url )
492 {
493     if( BoardManager::type( url ) != Board_2ch ) return FALSE;
494     if( Kita::getDatURL( url ).isEmpty() ) return FALSE;
495     
496     QRegExp url_2ch( ".*\\.2ch\\.net" );
497     QRegExp url_bbspink( ".*\\.bbspink\\.com" );
498     
499     if ( url_2ch.search( url.host() ) != -1
500          || url_bbspink.search( url.host() ) != -1 ) return TRUE;
501     
502     return FALSE;
503 }
504
505
506 /* public */
507 bool DatManager::isResValid( const KURL& url, int num )
508 {
509     DatInfo * datInfo = getDatInfo( url );
510     if ( datInfo == NULL ) return FALSE;
511
512     return datInfo->isResValid( num );
513 }
514
515
516 /* public */
517 bool DatManager::isBroken( const KURL& url )
518 {
519     DatInfo * datInfo = getDatInfo( url );
520     if ( datInfo == NULL ) return FALSE;
521
522     return datInfo->isBroken();
523 }
524
525 /* public */
526 bool DatManager::isResBroken( const KURL& url, int num )
527 {
528     DatInfo * datInfo = getDatInfo( url );
529     if ( datInfo == NULL ) return FALSE;
530
531     return datInfo->isResBroken( num );
532 }
533
534
535
536 /* check if ID == strid  */ /* public */
537 bool DatManager::checkID( const KURL& url, const QString& strid, int num )
538 {
539     DatInfo* datInfo = getDatInfo( url );
540     if ( datInfo == NULL ) return FALSE;
541
542     return datInfo->checkID( strid, num );
543 }
544
545
546 /* check if keywords are included */ /* public */
547 bool DatManager::checkWord( const KURL& url,
548                             QStringList& strlist, int num,
549                             bool checkOR /* AND or OR search */
550                           )
551 {
552     DatInfo* datInfo = getDatInfo( url );
553     if ( datInfo == NULL ) return FALSE;
554
555     return datInfo->checkWord( strlist, num, checkOR );
556 }
557
558
559 /* public */
560 bool DatManager::isMarked( const KURL& url, int num )
561 {
562     KURL datURL = Kita::getDatURL( url );
563     Kita::Thread* thread = Kita::Thread::getByURLNew( datURL );
564     if( thread == NULL ) return FALSE;
565
566     return thread->isMarked( num );
567 }
568
569
570 /* public */
571 void DatManager::setMark( const KURL& url, int num, bool mark )
572 {
573     KURL datURL = Kita::getDatURL( url );
574     Kita::Thread* thread = Kita::Thread::getByURLNew( datURL );
575     if( thread == NULL ) return;
576
577     if( thread->setMark( num, mark ) ) Kita::ThreadIndex::setMarkList( url, thread->markList() );
578 }
579
580
581 /* public */
582 bool DatManager::checkAbone( const KURL& url, int num )
583 {
584     DatInfo* datInfo = getDatInfo( url );
585     if ( datInfo == NULL ) return FALSE;
586
587     return datInfo->checkAbone( num );
588 }
589
590
591 /* public */
592 void DatManager::resetAbone( const KURL& url )
593 {
594     DatInfo* datInfo = getDatInfo( url );
595     if ( datInfo == NULL ) return ;
596
597     datInfo->resetAbone();
598 }
599
600
601 /* check if the thread is shown on the main thread tab. */ /* public */
602 bool DatManager::isMainThreadOpened( const KURL& url )
603 {
604     KURL datURL = Kita::getDatURL( url ).prettyURL();
605     Kita::Thread* thread = Kita::Thread::getByURLNew( datURL );
606     if( thread == NULL ) return FALSE;
607
608     return thread->isOpened();
609 }
610
611 void DatManager::setMainThreadOpened( const KURL& url, bool isOpened )
612 {
613     KURL datURL = Kita::getDatURL( url ).prettyURL();
614     Kita::Thread* thread = Kita::Thread::getByURLNew( datURL );
615     if( thread != NULL ) thread->setIsOpened( isOpened );
616 }
617
618
619 /*--------------------------*/
620 /* obsolete */
621
622 /* public */
623 const QString DatManager::threadURL( const KURL& url )
624 {
625     return Kita::getThreadURL( url );
626 }
627