OSDN Git Service

Add BoardDatabase class
[kita/kita.git] / kita / src / libkita / datmanager.cpp
index 724e4f7..1415a03 100644 (file)
@@ -1,6 +1,6 @@
-/**************************************************************************
-*   Copyright (C) 2003 by Hideki Ikemoto , (c)2004 by 421                 *
-*   ikemo@wakaba.jp                                                       *
+/***************************************************************************
+*   Copyright (C) 2004 by Kita Developers                                 *
+*   ikemo@users.sourceforge.jp                                            *
 *                                                                         *
 *   This program is free software; you can redistribute it and/or modify  *
 *   it under the terms of the GNU General Public License as published by  *
 *   (at your option) any later version.                                   *
 ***************************************************************************/
 
+/* DatManager manages all information about thread */
 #include "datmanager.h"
-#include "qcp932codec.h"
-#include "comment.h"
-#include "access.h"
-#include "../part/kitaconfig.h"
-#include <qregexp.h>
-#include <qsemaphore.h>
+
+#include <QtCore/QFile>
+#include <QtCore/QObject>
+#include <QtCore/QRegExp>
+#include <QtCore/QStringList>
+
+#include "boarddatabase.h"
+#include "cache.h"
+#include "datinfo.h"
+#include "kita_misc.h"
+#include "thread.h"
+#include "threadindex.h"
+#include "threadinfo.h"
 
 using namespace Kita;
 
-/*---------------------------------------------------*/
+static const int DMANAGER_MAXQUEUE = 16;
 
-/* DatInfo stores information of *.dat */
+DatInfoList DatManager::m_datInfoList;
 
-DatInfo::DatInfo(const KURL& url):m_url(url){
 
-    QString idstr;
-    KURL logurl = url;
-    logurl.setProtocol( "k2ch" );
-    QString rawdata = Kita::Access::getCacheData(logurl);
-    m_linedat.clear();
-    m_subject = QString::null;
-    m_maxNum = 0;
+/*-----------------------------------------------------------------------*/
+DatManager::DatManager(const KUrl& url) : m_url(url)
+{
+    m_datUrl = getDatUrl(url);
+    m_searchDatInfo = searchDatInfo();
+    m_datInfo = getDatInfo();
+}
 
-    if(rawdata.length()){
-       QCp932Codec codec;
-       QString linedata =  codec.toUnicode( rawdata );
 
-       QStringList lines = QStringList::split( "\n", linedata );
-       for ( QStringList::iterator it = lines.begin(); it != lines.end(); ++it, ++m_maxNum){
+/* create DatInfo explicitly.                    */
+/* Usually, DatInfo is NOT created
+   if cache does not exist(i.e. ReadNum == 0). */ /* public */
+bool DatManager::createDatInfo() const
+{
+    return getDatInfo(false /* don't check the existence of cache */) != 0;
+}
 
-           /* copy dat */
-           m_linedat += (*it);
 
-           /* get id & copy */
-           idstr = "none";
-           QStringList list = QStringList::split( "<>", (*it), true );
-           if ( list.size() == 5 ){
-               /* copied from Comment::parseDateId */
-               QRegExp regexp( "(\\d\\d)/(\\d\\d)/(\\d\\d) (\\d\\d):(\\d\\d)( ID:(.*))?" );
-               if ( regexp.search( list[ 2 ] ) != -1 ) idstr = regexp.cap( 7 );
+/* get pointer of DatInfo */
 
-               /* get subject */
-               if ( m_subject == QString::null && list[4] != QString::null ) m_subject = list[ 4 ];
-           }
-           m_idlist += idstr;
-       }
-    }
+/*    !!!  NOTICE  !!!   */
+/* It is very dangerous to access to DatInfo directly. */
+/* Usually, access to it through DatManager.           */ /* public */
+DatInfo * DatManager::getDatInfoPointer() const
+{
+    return m_datInfo;
 }
 
 
-const QString& DatInfo::getDat(int num){
+/*------------------------------------------------------------------------*/
 
-    if(num > m_maxNum) return QString::null;
-    
-    if(m_linedat.at(num-1) == m_linedat.end()) return QString::null;
 
-    return *(m_linedat.at(num-1));
-}
+/* This function searches instance of DatInfo in m_datInfoList.
+   If cache exists, create DatInfo and return its pointer.
+   If checkCached == true and cache does not exist, return 0.
+   If checkCached == false and cache does not exist,
+   create DatInfo and return its pointer anyway.
+   see also DatManager::searchDatInfo() and DatManager::createDatInfo() */ /* private */
 
+DatInfo* DatManager::getDatInfo(bool checkCached) const
+{
+    /* search */
+    /* create and enroll instance */
+    return (m_searchDatInfo != 0)
+        ? m_searchDatInfo : enrollDatInfo(checkCached);
+}
 
-const QString& DatInfo::getId(int num){
 
-    if(num > m_maxNum) return QString::null;
-    
-    if(m_idlist.at(num-1) == m_linedat.end()) return QString::null;
+/* This function just searches instance of DatInfo specified by datURL
+   without creating instance.  */ /* private */
+DatInfo* DatManager::searchDatInfo() const
+{
+    if (m_datUrl.isEmpty())
+        return 0; /* This url is not enrolled in BoardManager. */
+    if (m_datInfoList.isEmpty())
+        return 0;
 
-    return *(m_idlist.at(num-1));
-}
+    int i = 0;
+    DatInfoList::Iterator it;
+    DatInfo* datInfo;
 
+    for (it = m_datInfoList.begin(); it != m_datInfoList.end(); ++it, i++) {
 
-/*---------------------------------------------------*/
+        datInfo = (*it);
 
-/* DatManager manages *.dat. */
-/* Call
-   Kita::DatManager::getHtml ,or
-   Kita::DatManager::getDat
-   in order to obtain data. */
+        if (m_datUrl == datInfo->url()) {
 
-DatInfoList DatManager::m_datInfo;
-QSemaphore DatManager::m_semap( 1 );
+            /* LRU */
+            if (i) {
+                m_datInfoList.erase(it);
+                m_datInfoList.prepend(datInfo);
+            }
 
-/* private */
-/* This function searches instance of DatInfo specified by url.
-   If instance does not exist, create instance. */
-DatInfo* DatManager::getDatInfo(const KURL& url){
-
-    m_semap++;
-    
-    if ( url.isEmpty() ){
-       m_semap--;
-       return NULL;
+            return datInfo;
+        }
     }
-    
-    int i = 0;
-    DatInfoList::Iterator it;
 
-    /* search */
-    if(m_datInfo.count()){
-       for(it = m_datInfo.begin(); it != m_datInfo.end(); ++it, i++ ){
-
-           if(url.host() == (*it)->url().host() &&
-              url.path() == (*it)->url().path()){
-
-               /* LRU */
-               if(i){
-                   m_datInfo.remove(it);
-                   m_datInfo.prepend((*it));
-               }
-
-               m_semap--; 
-               return (*it);
-           }
-       }
-    }
+    return 0;
+}
 
-    /* not found */
 
-    /*create new DatInfo and insert it into list. */
-    KURL daturl = url.protocol()+"://"+url.host()+url.path();
+/* create and enroll the instance of DatInfo and delete old instances.
+   Note that DatInfo::DatInfo() opens cached data and reads it. */
+/* private */
+DatInfo* DatManager::enrollDatInfo(bool checkCached) const
+{
+    if (m_datUrl.isEmpty())
+        return 0; /* This url is not enrolled in BoardManager. */
 
-    DatInfo* datInfo;
-    datInfo = new DatInfo(daturl);
-    if(datInfo->getMaxResNumber() == 0){ /* cache does not exist */
-       delete(datInfo);
+    /* create DatInfo & read cached data */
+    DatInfo* datInfo = new DatInfo(m_datUrl);
 
-       m_semap--;              
-       return NULL;
+    /* Does cache exist ? */
+    /* If cache does not exist, delete DatInfo here. */
+    if (checkCached && datInfo->getReadNum() == 0) {
+        delete datInfo;
+        return 0;
     }
-       
-    m_datInfo.prepend(datInfo);
-    
-    /* delete the last item of list */
-    if(m_datInfo.count() > DMANAGER_MAXQUEUE){
-       it = m_datInfo.fromLast();
-       m_datInfo.remove(it);
-
-       delete(*it);
+
+    m_datInfoList.prepend(datInfo);
+
+    /* delete the all old instances (LRU algorithm)*/
+    if (m_datInfoList.count() > DMANAGER_MAXQUEUE) {
+        for (int i = DMANAGER_MAXQUEUE; i < m_datInfoList.count(); i++) {
+            DatInfo* deleteInfo = m_datInfoList.at(i);
+            if (deleteInfo == 0)
+                continue;
+            m_datInfoList.removeAt(i);
+            i--;
+            delete datInfo;
+        }
     }
 
-    m_semap--;      
     return datInfo;
 }
 
 
 /* public */
-void DatManager::deleteDat(const KURL& url){
-    m_semap++;
-    
-    DatInfoList::Iterator it;
+void DatManager::deleteAllDatInfo()
+{
+    while (!m_datInfoList.isEmpty())
+        delete m_datInfoList.takeFirst();
+}
+
+
+
+/*-------------------------------------------------------------*/
+
+
 
-    for(it = m_datInfo.begin(); it != m_datInfo.end(); ++it){
-       if(url.host() == (*it)->url().host() &&
-          url.path() == (*it)->url().path()){
-           m_datInfo.remove(it);
-           delete(*it);
+/* update cache */   /* public */
+bool DatManager::updateCache(const QObject* parent) const
+{
+    return (m_datInfo == 0) ? false : m_datInfo->updateCache(parent);
+}
+
+
+/* public */
+int DatManager::getResponseCode() const
+{
+    return (m_datInfo == 0) ? 0 : m_datInfo->getResponseCode();
+}
+
+/* public */
+int DatManager::getServerTime() const
+{
+    return (m_datInfo == 0) ? 0 : m_datInfo->getServerTime();
+}
 
-           m_semap--;
-           return;
-       }
+
+/* public */
+bool DatManager::deleteCache() const
+{
+    Thread* thread = Thread::getByUrlNew(m_datUrl);
+    if (thread == 0)
+        return false;
+    if (thread->readNum() == 0)
+        return false;
+
+    /* init DatInfo */
+    if (m_searchDatInfo && !m_searchDatInfo->deleteCache()) {
+        return false;
     }
 
-    m_semap--;
+    /* reset readNum & veiwPos */
+    thread->setReadNum(0);
+    thread->setViewPos(0);
+
+    /* delete cache */
+    Cache cache(m_datUrl);
+    QString cachePath = cache.getPath();
+    QString indexPath = cache.getIndexPath();
+    QFile::remove(indexPath);
+    QFile::remove(cachePath);
+
+    /* delete log from "cache" */
+    ThreadInfo::removeThreadInfo(m_datUrl.prettyUrl());
+    return true;
 }
 
 
 /* public */
-const QString& DatManager::getDat(const KURL& url, int num){
-    DatInfo* datInfo = getDatInfo(url);
-    if(datInfo == NULL) return QString::null;
+bool DatManager::isLoadingNow() const
+{
+    return (m_searchDatInfo == 0) ? false : m_searchDatInfo->isLoadingNow();
+}
+
 
-    return datInfo->getDat(num); 
+/* public */
+void DatManager::stopLoading() const
+{
+    if (m_searchDatInfo == 0)
+        return;
+    m_searchDatInfo->stopLoading();
 }
 
+/*--------------------------------------*/
+/* string data */
+
+
 /* public */
-const QString& DatManager::getSubject(const KURL& url){
-    DatInfo* datInfo = getDatInfo(url);
-    if(datInfo == NULL) return QString::null;
+QString DatManager::getDat(int num) const
+{
+    return (m_datInfo == 0) ? QString() : m_datInfo->getDat(num);
+}
+
 
-    return datInfo->getSubject();
+
+/* public */
+QString DatManager::getId(int num) const
+{
+    return (m_datInfo == 0) ? QString() : m_datInfo->getId(num);
 }
 
 
 /* public */
-int DatManager::getNumByID(const KURL& url, QString strid ){
+QString DatManager::getPlainName(int num) const
+{
+    return (m_datInfo == 0) ? QString() : m_datInfo->getPlainName(num);
+}
 
-    DatInfo* datInfo = getDatInfo(url);
-    if(datInfo == NULL) return 0;
-    
-    int num = 0;
-    int maxNum = datInfo->getMaxResNumber();
 
-    for ( int i = 1; i <= maxNum; i++ ) {
-       if(datInfo->getId(i) == strid) num ++;
-    }
+/* public */
+QString DatManager::getPlainBody(int num) const
+{
+    return (m_datInfo == 0) ? QString() : m_datInfo->getPlainBody(num);
+}
+
 
-    return num;    
+/* public */
+QString DatManager::getPlainTitle(int num) const
+{
+    return (m_datInfo == 0) ? QString() : m_datInfo->getPlainTitle(num);
+}
+
+
+/* get name (i.e. subject) of thread from URL of dat file. */ /* public */
+QString DatManager::threadName() const
+{
+    Thread* thread = Thread::getByUrlNew(m_datUrl);
+    return (thread != 0) ? thread->threadName() : QString();
 }
 
 
 /* public */
-int DatManager::getMaxResNumber(const KURL& url){
-    DatInfo* datInfo = getDatInfo(url);
-    if(datInfo == NULL) return 0;
+QString DatManager::threadId() const
+{
+    return m_datUrl.fileName().section('.', 0, 0);
+}
+
+/*---------------------------------------*/
+/* HTML data */
 
-    return datInfo->getMaxResNumber();
+/* public */
+QString DatManager::getHtml(int startnum, int endnum, bool checkAbone) const
+{
+    return (m_datInfo == 0)
+        ? QString() : m_datInfo->getHTMLString(startnum, endnum, checkAbone);
 }
 
 
+
 /* public */
-QString DatManager::getHtml(const KURL& url, int startnum, int endnum ){
+QString DatManager::getHtmlById(const QString& strid, int &count) const
+{
+    return (m_datInfo == 0) ? QString() : m_datInfo->getHtmlById(strid, count);
+}
 
-    DatInfo* datInfo = getDatInfo(url);
-    if(datInfo == NULL) return QString::null;
-    
-    QString retstr = QString::null ;
-    bool showAddr = KitaConfig::showMailAddress();
 
-    for(int num = startnum; num <= endnum; num++){
-    
-       QString line = datInfo->getDat(num);
 
-       if(line != QString::null){
+/* Get HTML document of res tree.*/ /* public */
+QString DatManager::getTreeByRes(int rootnum, int &count) const
+{
+    return (m_datInfo == 0)
+        ? QString() : m_datInfo->getTreeByRes(rootnum, count);
+}
 
-           Kita::Comment comment( line );
+/* Get HTML document of reverse res tree.*/ /* public */
+QString DatManager::getTreeByResReverse(int rootnum, int &count) const
+{
+    return (m_datInfo == 0)
+        ? QString() : m_datInfo->getTreeByResReverse(rootnum, count);
+}
 
-           /* check abone */
-           if(checkAbone(datInfo->getId(num),ABONECHK_BY_ID)) continue;        
-           if(checkAbone(comment.getName(),ABONECHK_BY_NAME)) continue;
-           if(checkAbone(comment.getBody(),ABONECHK_BY_WORD)) continue;
-       
-           retstr += comment.toHtml( num, showAddr );
-       }
-    }
 
-    return retstr;
+/* public */
+int DatManager::getResNum() const
+{
+    Thread* thread = Thread::getByUrlNew(m_datUrl);
+    return (thread != 0) ? thread->resNum() : 0;
 }
 
 
-/* public */ /* This function is also called by kitadomtree. */
-bool DatManager::checkAbone(const QString& str, int mode)
+/* public */
+int DatManager::getReadNum() const
 {
+    Thread* thread = Thread::getByUrlNew(m_datUrl);
+    return (thread != 0) ? thread->readNum() : 0;
+}
 
-    QStringList &strlist = KitaConfig::aboneIDList();
-    switch(mode){
-    case ABONECHK_BY_ID: break;
-    case ABONECHK_BY_NAME: strlist = KitaConfig::aboneNameList(); break;
-    case ABONECHK_BY_WORD: strlist = KitaConfig::aboneWordList(); break;
-    default: return FALSE;
-    }
 
-    int i = -1;
-    for ( QStringList::iterator it = strlist.begin();
-         it != strlist.end(); ++it ) {
-       i = str.find( ( *it ) );
-       if ( i != -1 ){
-           return TRUE;
-       }
+/* public */
+int DatManager::getViewPos() const
+{
+    Thread* thread = Thread::getByUrlNew(m_datUrl);
+    return (thread != 0) ? thread->viewPos() : 0;
+}
+
+
+/* public */
+void DatManager::setViewPos(int num) const
+{
+    Thread* thread = Thread::getByUrlNew(m_datUrl);
+    if (thread != 0)
+        thread->setViewPos(num);
+
+    /* save idx */
+    ThreadIndex threadIndex(m_url);
+    threadIndex.setViewPos(num);
+
+    /* save "cache" */
+    ThreadInfo::setReadNum(m_datUrl.prettyUrl(), num);
+}
+
+
+/* public */
+int DatManager::getDatSize() const
+{
+    return (m_datInfo == 0) ? 0 : m_datInfo->getDatSize();
+}
+
+/* get number of responses which have same ID. */ /* public */
+int DatManager::getNumById(const QString& strid) const
+{
+    return (m_datInfo == 0) ? 0 : m_datInfo->getNumById(strid);
+}
+
+
+/* public */
+bool DatManager::isThreadEnrolled() const
+{
+    return !m_datUrl.isEmpty();
+}
+
+
+/* public */
+bool DatManager::is2chThread() const
+{
+    BoardDatabase db(m_url);
+    if (db.type() != Board_2ch)
+        return false;
+    if (m_datUrl.isEmpty())
+        return false;
+
+    QRegExp url_2ch(".*\\.2ch\\.net");
+    QRegExp url_bbspink(".*\\.bbspink\\.com");
+
+    if (url_2ch.indexIn(m_url.host()) != -1
+            || url_bbspink.indexIn(m_url.host()) != -1)
+        return true;
+
+    return false;
+}
+
+
+/* public */
+bool DatManager::isResValid(int num) const
+{
+    return (m_datInfo == 0) ? false : m_datInfo->isResValid(num);
+}
+
+
+/* public */
+bool DatManager::isBroken() const
+{
+    return (m_datInfo == 0) ? false : m_datInfo->isBroken();
+}
+
+/* public */
+bool DatManager::isResBroken(int num) const
+{
+    return (m_datInfo == 0) ? false : m_datInfo->isResBroken(num);
+}
+
+
+
+/* check if ID == strid  */ /* public */
+bool DatManager::checkId(const QString& strid, int num) const
+{
+    return (m_datInfo == 0) ? false : m_datInfo->checkId(strid, num);
+}
+
+
+/* check if keywords are included */ /* public */
+bool DatManager::checkWord(const QStringList& strlist, int num,
+        bool checkOr /* AND or OR search */) const
+{
+    return (m_datInfo == 0)
+        ? false : m_datInfo->checkWord(strlist, num, checkOr);
+}
+
+
+/* public */
+bool DatManager::isMarked(int num) const
+{
+    Thread* thread = Thread::getByUrlNew(m_datUrl);
+    return (thread == 0) ? false : thread->isMarked(num);
+}
+
+
+/* public */
+void DatManager::setMark(int num, bool mark) const
+{
+    Thread* thread = Thread::getByUrlNew(m_datUrl);
+    if (thread == 0)
+        return;
+
+    if (thread->setMark(num, mark)) {
+        ThreadIndex threadIndex(m_url);
+        threadIndex.setMarkList(thread->markList());
     }
+}
+
+
+/* public */
+bool DatManager::checkAbone(int num) const
+{
+    return (m_datInfo == 0) ? false : m_datInfo->checkAbone(num);
+}
+
+
+/* public */
+void DatManager::resetAbone() const
+{
+    if (m_datInfo == 0)
+        return;
+    m_datInfo->resetAbone();
+}
 
-    return FALSE;
+
+/* check if the thread is shown on the main thread tab. */ /* public */
+bool DatManager::isMainThreadOpened() const
+{
+    return (m_datInfo == 0) ? false : m_datInfo->isOpened();
+}
+
+void DatManager::setMainThreadOpened(bool isOpened) const
+{
+    if (m_datInfo == 0)
+        return;
+    m_datInfo->setOpened(isOpened);
+}
+
+
+/*--------------------------*/
+/* obsolete */
+
+/* public */
+QString DatManager::threadUrl() const
+{
+    return getThreadUrl(m_url);
 }