OSDN Git Service

ce592c890201b610d868be2333d1dddaa8fa71f0
[kita/kita.git] / kita / src / kitasubjectview.cpp
1 /***************************************************************************
2 *   Copyright (C) 2003 by Hideki Ikemoto                                  *
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 #include "kitasubjectview.h"
12
13 // include files for Qt
14 #include <qtoolbutton.h>
15 #include <qtextbrowser.h>
16 #include <qtextcodec.h>
17 #include <qregexp.h>
18 #include <qfile.h>
19 #include <qclipboard.h>
20 #include <qapplication.h>
21 #include <qdatetime.h>
22 #include <qlabel.h>
23 #include <qmessagebox.h>
24 #include <qcombobox.h>
25
26 // kdelibs/kio
27 #include <kio/slaveconfig.h>
28 #include <kio/netaccess.h>
29
30 // include files for KDE
31 #include <kwin.h>
32 #include <kfilterdev.h>
33 #include <klistview.h>
34 #include <kiconloader.h>
35 #include <klocale.h>
36 #include <kpopupmenu.h>
37 #include <krun.h>
38 #include <kdebug.h>
39
40 #include "libkita/threadinfo.h"
41 #include "libkita/thread.h"
42 #include "libkita/kita_misc.h"
43 #include "libkita/kitaconfig.h"
44 #include "libkita/favoritethreads.h"
45 #include "libkita/datmanager.h"
46 #include "libkita/parsemisc.h"
47 #include "libkita/signalcollection.h"
48 #include "part/kita2ch.h"
49
50 #include "threadproperty.h"
51
52 KitaSubjectView::KitaSubjectView( QWidget* parent, const char* name )
53         : Kita::ThreadListView( parent, name )
54         , m_unreadNum( 0 ), m_readNum( 0 ), m_newNum( 0 )
55 {
56     connect( subjectList, SIGNAL( contextMenuRequested( QListViewItem*, const QPoint&, int ) ),
57              SLOT( slotContextMenuRequested( QListViewItem*, const QPoint&, int ) ) );
58     connect( subjectList, SIGNAL( returnPressed( QListViewItem* ) ),
59              SLOT( loadThread( QListViewItem* ) ) );
60     connect( ReloadButton, SIGNAL( clicked() ),
61              SLOT( reloadSubject() ) );
62
63     Kita::SignalCollection* signalCollection = Kita::SignalCollection::getInstance();
64     connect( signalCollection, SIGNAL( updateSubjectTab( const KURL& ) ),
65              SLOT( slotUpdateSubject( const KURL& ) ) );
66     connect( this, SIGNAL( closeThreadTab( const KURL& ) ),
67              signalCollection, SIGNAL( closeThreadTab( const KURL& ) ) );
68     connect( this, SIGNAL( loadBoardCompleted( const KURL& ) ),
69              signalCollection, SIGNAL( setMainURLLine( const KURL& ) ) );
70 }
71
72 KitaSubjectView::~KitaSubjectView()
73 {}
74
75 void KitaSubjectView::reloadSubject()
76 {
77     if ( ! m_boardURL.isEmpty() ) {
78         loadBoard( m_boardURL );
79     }
80 }
81
82
83 /* private slot */
84 void KitaSubjectView::slotCloseButton()
85 {
86     emit closeCurrentTab();
87 }
88
89
90 const KURL KitaSubjectView::boardURL()
91 {
92     return m_boardURL;
93 }
94
95 const QString KitaSubjectView::boardName()
96 {
97     return Kita::Board::getName( m_boardURL );
98 }
99
100 void KitaSubjectView::loadThread( QListViewItem* item )
101 {
102     if ( ! item ) return ;
103
104     KURL datURL = item->text( Col_DatURL );
105
106     if ( KitaConfig::alwaysUseTab() ) {
107         emit openURLRequestExt( datURL.prettyURL(), KParts::URLArgs(), "kita_open_2chthread", 1 );
108     } else { 
109         emit openURLRequestExt( datURL.prettyURL(), KParts::URLArgs(), "kita_open_2chthread", 0 );
110     }
111 }
112 /*
113 Í¥Àè½ç°Ì
114 ts_readed   : ´ûÆɤÇ1000Ķ¤¨¤Æ¤¤¤ë¤â¤Î
115 ts_normal   : Ì¤¼èÆÀ¤Ç1Æü°Ê¾å·Ð¤Ã¤Æ¤¤¤ë¤â¤Î
116 ts_new      : Ì¤¼èÆÀ¤Ç1Æü°ÊÆâ¤Î¤â¤Î
117 ts_read   : ´ûÆɤÇ1000°Ê²¼¤Î¤â¤Î
118 ts_hasunread: Ì¤Æɤ¢¤ê
119 */
120
121 enum {
122     ts_readed,
123     ts_normal,
124     ts_new,
125     ts_read,
126     ts_hasunread
127 };
128
129 void KitaSubjectView::loadBoard( const QString& boardURL )
130 {
131     setActiveWindow();
132     topLevelWidget() ->raise();
133     QDateTime currentdat = QDateTime::currentDateTime();
134
135     // reset member variables.
136     // FIXME: FavoriteListView::update()¤Ë¥³¥Ô¡¼
137     {
138         m_hitList.clear();
139         m_nextHitIndex = 0;
140         m_prevquery = "";
141     }
142
143     m_boardURL = boardURL;
144     m_unreadNum = 0;
145     m_readNum = 0;
146     m_newNum = 0;
147
148     KitaThreadInfo* cache = KitaThreadInfo::getInstance();
149     QPtrList<Kita::Thread> threadList = Kita::Board::getThreadList( boardURL );
150
151     // clear list
152     subjectList->clear();
153
154     for ( unsigned i = 0; i < threadList.count(); i++ ) {
155         Kita::Thread* thread = threadList.at( i );
156         QString datURL = thread->datURL();
157
158         QDateTime since;
159         since.setTime_t( Kita::datToSince( datURL ) );
160         QDateTime current = QDateTime::currentDateTime();
161
162         int readNum = KitaThreadInfo::readNum( datURL );
163         int resNum = KitaThreadInfo::resNum( datURL );
164         double speed = resNum / ( since.secsTo( current ) / ( 60.0 * 60.0 * 24.0 ) );
165
166         Kita::ThreadListViewItem* item = new Kita::ThreadListViewItem( subjectList );
167         item->setText( Col_ID, QString( "%1" ).arg( i + 1, 4 ) );
168         item->setText( Col_Subject, Kita::unescape( Kita::Thread::getName( datURL ) ) );
169         item->setText( Col_ResNum, QString( "%1" ).arg( resNum, 4 ) );
170         item->setText( Col_Read, ( readNum > 0 ) ? QString( "%1" ).arg( readNum, 4 ) : QString( "" ) );
171         item->setText( Col_Unread, ( readNum > 0 && resNum != readNum ) ? QString( "%1" ).arg( resNum - readNum, 4 ) : QString( "" ) );
172         item->setText( Col_Board, Kita::DatManager::boardName( datURL ) );
173         item->setText( Col_Since, since.toString( "yy/MM/dd hh:mm" ) );
174         item->setText( Col_DatURL, datURL );
175         item->setText( Col_Speed, QString( " %1 " ).arg( speed, 0, 'f', 2 ) );
176
177         // FIXME: updateThread¤Ë¥³¥Ô¡¼¤·¤Æ¤¤¤ë
178         // TODO: 'N'¤Î¥¢¥¤¥³¥ó¤òºîÀ®
179         if ( readNum > 0 && resNum != readNum ) {
180             // Ì¤Æɤ¢¤ê
181             item->setPixmap( Col_Mark, SmallIcon( "unread" ) );
182             m_unreadNum++;
183             item->setText( Col_MarkOrder, QString::number( ts_hasunread ) );
184         } else if ( readNum > 0 ) {
185             // ´ûÆÉ
186             item->setPixmap( Col_Mark, SmallIcon( "read" ) );
187             m_readNum++;
188             //if( readNum > 1000) item->setText( Col_MarkOrder, "0" );
189             //else item->setText( Col_MarkOrder, "3" );
190             item->setText( Col_MarkOrder, QString::number( ( readNum > 1000 ) ? ts_readed : ts_read ) );
191         } else if ( since.secsTo( currentdat ) < 3600 * KitaConfig::MarkTime() ) {
192             item->setPixmap( Col_Mark, SmallIcon( "newthread" ) );
193             m_newNum++;
194             item->setText( Col_MarkOrder, QString::number( ts_new ) );
195         } else {
196             item->setText( Col_MarkOrder, QString::number( ts_normal ) );
197         }
198     }
199
200     if ( HideButton->isOn() ) {
201         HideButton->toggle();
202     }
203     emit loadBoardCompleted( boardURL );
204
205     switch ( KitaConfig::sortOrder() ) {
206     case KitaConfig::Order_Mark:
207         subjectList->setSorting( Col_Mark );
208         break;
209     case KitaConfig::Order_ID:
210         subjectList->setSorting( Col_ID );
211         break;
212     default:
213         // do nothing
214         break;
215     }
216
217     subjectList->setSelected( subjectList->firstChild(), TRUE );
218     subjectList->setFocus();
219     UpdateKindLabel();
220 }
221
222 /* public slot */ /* virtual */
223 void KitaSubjectView::setFocus()
224 {
225     subjectList->setFocus();
226 }
227
228 /* public slot */
229 void KitaSubjectView::slotFocusSearchCombo()
230 {
231     if ( ! SearchCombo->hasFocus() ) {
232         SearchCombo->setFocus();
233     } else {
234         setFocus();
235     }
236 }
237
238 void KitaSubjectView::UpdateKindLabel()
239 {
240     QString fmtstr;
241     fmtstr += QString( "<font color=#C50000>%1</font>" ).arg( m_unreadNum );
242     fmtstr += QString( "/<font color=#00C200>%1</font>" ).arg( m_readNum );
243     fmtstr += QString( "/<font color=#5AAAFF>%1</font>" ).arg( m_newNum );
244     KindLabel->setText( fmtstr );
245 }
246
247 void KitaSubjectView::setFont( const QFont& font )
248 {
249     subjectList->setFont( font );
250 }
251
252 void KitaSubjectView::slotUpdateSubject( const KURL& url )
253 {
254     QDateTime currentdat = QDateTime::currentDateTime();
255
256     KURL datURL = Kita::ParseMisc::parseURLonly( url );
257     Kita::Thread* updated_thread = Kita::Thread::getByURLNew( datURL );
258     for ( QListViewItem * item = subjectList->firstChild(); item; item = item->nextSibling() ) {
259         if ( item->text( Col_DatURL ) == datURL.prettyURL() ) {
260             QDateTime since;
261             since.setTime_t( Kita::datToSince( datURL.prettyURL() ) );
262
263             int resNum = KitaThreadInfo::resNum( datURL.prettyURL() );
264             int readNum = KitaThreadInfo::readNum( datURL.prettyURL() );
265             item->setText( Col_ResNum, QString( "%1" ).arg( resNum, 4 ) );
266             item->setText( Col_Read, ( readNum > 0 ) ? QString( "%1" ).arg( readNum, 4 ) : QString( "" ) );
267             item->setText( Col_Unread, readNum > 0 && resNum != readNum ? QString( "%1" ).arg( resNum - readNum, 4 ) : QString( "" ) );
268
269             switch ( item->text( Col_MarkOrder ).toInt() ) {
270             case ts_readed :
271             case ts_read : m_readNum--; break;
272             case ts_new : m_newNum--; break;
273             case ts_hasunread : m_unreadNum--; break;
274             }
275
276             if ( readNum > 0 && resNum != readNum ) {
277                 // Ì¤Æɤ¢¤ê
278                 item->setPixmap( Col_Mark, SmallIcon( "unread" ) );
279                 m_unreadNum++;
280                 item->setText( Col_MarkOrder, QString::number( ts_hasunread ) );
281             } else if ( readNum > 0 ) {
282                 // ´ûÆÉ
283                 item->setPixmap( Col_Mark, SmallIcon( "read" ) );
284                 m_readNum++;
285                 //if( readNum > 1000) item->setText( Col_MarkOrder, "0" );
286                 //else item->setText( Col_MarkOrder, "3" );
287                 item->setText( Col_MarkOrder, QString::number( ( readNum > 1000 ) ? ts_readed : ts_read ) );
288             } else if ( since.secsTo( currentdat ) < 3600 * KitaConfig::MarkTime() ) {
289                 item->setPixmap( Col_Mark, SmallIcon( "newthread" ) );
290                 m_newNum++;
291                 item->setText( Col_MarkOrder, QString::number( ts_new ) );
292             } else {
293                 item->setPixmap( Col_Mark, NULL );
294                 item->setText( Col_MarkOrder, QString::number( ts_normal ) );
295             }
296             UpdateKindLabel();
297         }
298     }
299 }
300
301 void KitaSubjectView::slotContextMenuRequested( QListViewItem* item, const QPoint& point, int )
302 {
303     enum {
304         Menu_OpenWithBrowser,
305         Menu_OpenWithNewTab,
306         Menu_CopyTitleAndURL,
307         Menu_Favorites,
308         Menu_DeleteLog,
309         Menu_Property
310     };
311
312     if ( item == 0 ) {
313         return ;
314     }
315
316     QString datURL = item->text( Col_DatURL );
317     Kita::Thread* thread = Kita::Thread::getByURL( datURL );
318     QString threadURL = Kita::DatManager::threadURL( datURL );
319     bool isFavorites = FavoriteThreads::getInstance() ->contains( datURL );
320
321     KPopupMenu popup( 0 );
322     popup.insertItem( i18n( "Open with Web Browser" ), Menu_OpenWithBrowser );
323     popup.insertItem( i18n( "Open with new tab" ), Menu_OpenWithNewTab );
324     popup.insertItem( i18n( "Copy title and URL" ), Menu_CopyTitleAndURL );
325     if ( isFavorites ) {
326         popup.insertItem( i18n( "Remove from Favorites" ), Menu_Favorites );
327     } else {
328         popup.insertItem( i18n( "Add to Favorites" ), Menu_Favorites );
329     }
330     popup.insertSeparator();
331     popup.insertItem( i18n( "Delete Log" ), Menu_DeleteLog );
332     popup.insertSeparator();
333     popup.insertItem( i18n( "Property" ), Menu_Property );
334
335     QClipboard* clipboard = QApplication::clipboard();
336
337     switch ( popup.exec( point ) ) {
338     case Menu_OpenWithBrowser:
339         KRun::runURL( threadURL, "text/html" );
340         break;
341     case Menu_OpenWithNewTab:
342         emit openURLRequestExt( datURL, KParts::URLArgs(), "kita_open_2chthread", 1 );
343         break;
344     case Menu_CopyTitleAndURL:
345         clipboard->setText( Kita::Thread::getName( datURL ) + "\n" + threadURL );
346         break;
347     case Menu_Favorites:
348         if ( isFavorites ) {
349             emit bookmarked( datURL, false );
350         } else {
351             emit bookmarked( datURL, true );
352         }
353         break;
354     case Menu_DeleteLog:
355         deleteLog( threadURL );
356         break;
357     case Menu_Property:
358         {
359             // FIXME: memory leak
360             Kita::ThreadProperty* propertyWidget = new Kita::ThreadProperty( 0 );
361             propertyWidget->threadURLLabel->setText( threadURL );
362             propertyWidget->datURLLabel->setText( datURL );
363             propertyWidget->threadNameLabel->setText( Kita::DatManager::threadName( datURL ) );
364             propertyWidget->cachePathLabel->setText( Kita::DatManager::getCachePath( datURL ) );
365             propertyWidget->indexPathLabel->setText( Kita::DatManager::getCacheIndexPath( datURL ) );
366             propertyWidget->show();
367         }
368         break;
369     default:
370         break;
371     }
372 }
373
374 void KitaSubjectView::deleteLog( const KURL& url )
375 {
376     if ( QMessageBox::warning( this,
377                                "Kita",
378                                i18n( "Do you want to delete Log ?" ),
379                                QMessageBox::Ok, QMessageBox::Cancel | QMessageBox::Default )
380             == QMessageBox::Ok ) {
381         Kita::DatManager::deleteCache( url );
382         emit closeThreadTab( url );
383         slotUpdateSubject( url );
384     }
385 }