1 /***************************************************************************
2 * Copyright (C) 2004 by Kita Developers *
3 * ikemo@users.sourceforge.jp *
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 ***************************************************************************/
11 #include <kpopupmenu.h>
13 #include <khtml_events.h>
16 #include <dom/html_element.h>
17 #include <dom/html_misc.h>
20 #include <qapplication.h>
21 #include <qclipboard.h>
22 #include <qmessagebox.h>
25 #include "previewpart.h"
27 #include "thread/domtree.h"
28 #include "thread/respopup.h"
30 #include "kitaui/htmlview.h"
32 #include "libkita/kitaconfig.h"
33 #include "libkita/datmanager.h"
34 #include "libkita/boardmanager.h"
35 #include "libkita/datinfo.h"
36 #include "libkita/kita_misc.h"
37 #include "libkita/signalcollection.h"
38 #include "libkita/config_xt.h"
39 #include "libkita/abone.h"
41 /*-------------------------------------------*/
44 /*-------------------------------------*/
45 /* Don't forget to call setup() later. */
47 KitaPreviewPart::KitaPreviewPart( QWidget* parent, const char* name )
48 : KHTMLPart( new KitaHTMLView( this, parent, name ) )
51 m_datURL = QString::null;
58 KitaPreviewPart::~KitaPreviewPart()
64 void KitaPreviewPart::clearPart()
68 if ( !m_datURL.isEmpty() ) { /* This part is opened. */
70 /* don't forget to unlock previous datURL here. */
71 Kita::DatManager::unlock( m_datURL );
73 m_datURL = QString::null;
77 bool KitaPreviewPart::setup( const KURL& url )
79 if ( url.isEmpty() ) return FALSE;
83 m_datURL = Kita::getDatURL( url );
85 /* Lock datURL. Don't forget to unlock it later ! */
86 Kita::DatManager::lock ( m_datURL );
88 /* create HTML Document */
95 void KitaPreviewPart::connectSignals()
97 Kita::SignalCollection * signalCollection = Kita::SignalCollection::getInstance();
100 connect( signalCollection, SIGNAL( threadFaceChanged() ), SLOT( slotSetFaceOfHTMLPart() ) );
101 connect( signalCollection, SIGNAL( setStyleSheetOfHTMLPart() ), SLOT( slotSetStyleSheetOfHTMLPart() ) );
104 connect( this, SIGNAL( onURL( const QString& ) ), SLOT( slotOnURL( const QString& ) ) );
105 connect( this, SIGNAL( isKitaActive() ), signalCollection, SIGNAL( isKitaActive() ) );
107 connect( view(), SIGNAL( leave() ), SLOT( slotLeave() ) );
108 connect( view(), SIGNAL( verticalSliderReleased() ), SLOT( slotVSliderReleased() ) );
109 connect( view(), SIGNAL( horizontalSliderReleased() ), SLOT( slotHSliderReleased() ) );
111 connect( signalCollection, SIGNAL( kitaIsActive() ), SLOT( slotKitaIsActive() ) );
112 connect( signalCollection, SIGNAL( windowDeactivated() ), SLOT( slotHideChildPopup() ) );
115 connect( this, SIGNAL( openURLRequestExt(
116 const KURL&, const KParts::URLArgs&, QString, int,
118 signalCollection, SIGNAL( openURLRequestExt(
119 const KURL& , const KParts::URLArgs&, QString, int,
124 void KitaPreviewPart::createHTMLDocument()
127 QString style = QString( "body { font-size: %1pt; font-family: \"%2\"; color: %3; background-color: %4; }" )
128 .arg( Kita::Config::threadFont().pointSize() )
129 .arg( Kita::Config::threadFont().family() )
130 .arg( Kita::Config::threadColor().name() )
131 .arg( Kita::Config::threadBackground().name() );
133 QString text = "<html><head><style>";
134 text += KitaConfig::defaultStyleSheetText();
136 if ( Kita::Config::useStyleSheet() ) {
137 text += KitaConfig::styleSheetText();
139 text += "</style></head><body></body></html>";
141 setJScriptEnabled( false );
142 setJavaEnabled( false );
144 /* Use dummy URL here, and protocol should be "file:".
145 If protocol is "http:", local image files are not shown
146 (for security reasons ?).
148 begin( "file:/dummy.htm" );
153 /*---------------------------------------------------------------*/
154 /*---------------------------------------------------------------*/
155 /* direct rendering functions */
158 void KitaPreviewPart::setInnerHTML( const QString& innerHTML )
160 createHTMLDocument();
161 htmlDocument().body().setInnerHTML( innerHTML );
165 void KitaPreviewPart::slotSetFaceOfHTMLPart()
167 QFont font = Kita::Config::threadFont();
169 DOM::CSSStyleDeclaration style = htmlDocument().body().style();
170 style.setProperty( "font-family", font.family(), "" );
171 style.setProperty( "font-size", QString( "%1pt" ).arg( font.pointSize() ), "" );
172 style.setProperty( "color", Kita::Config::threadColor().name(), "" );
173 style.setProperty( "background-color", Kita::Config::threadBackground().name(), "" );
174 htmlDocument().applyChanges();
178 void KitaPreviewPart::slotSetStyleSheetOfHTMLPart()
180 /* [0]<html> -> [1]<head> -> [2]<style> */
181 DOM::HTMLCollection collection = htmlDocument().all();
182 DOM::HTMLElement element;
184 for ( i = 0 ; i < collection.length() ; i++ ) {
185 element = collection.item( i );
186 if ( element.tagName().upper() == "STYLE" ) {
187 QString style = QString( "body { font-size: %1pt; font-family: %2; color: %3; background-color: %4; }" )
188 .arg( Kita::Config::threadFont().pointSize() )
189 .arg( Kita::Config::threadFont().family() )
190 .arg( Kita::Config::threadColor().name() )
191 .arg( Kita::Config::threadBackground().name() );
193 QString style0 = KitaConfig::defaultStyleSheetText();
195 if ( Kita::Config::useStyleSheet() ) {
196 style0 += KitaConfig::styleSheetText();
199 element.setInnerText( style0 );
200 htmlDocument().applyChanges();
206 /*---------------------------------------------------------------*/
207 /*---------------------------------------------------------------*/
210 /* protected */ /* virtual */
211 void KitaPreviewPart::customEvent( QCustomEvent * e )
213 if ( e->type() == EVENT_GotoAnchor ) {
214 KHTMLPart::gotoAnchor( static_cast< GotoAnchorEvent* >( e ) ->getAnc() );
218 KHTMLPart::customEvent( e );
221 /*---------------------------------------------------------------*/
222 /*---------------------------------------------------------------*/
226 void KitaPreviewPart::khtmlMousePressEvent( khtml::MousePressEvent* e )
228 emit mousePressed(); /* to KitaThreadView to focus this view. */
231 if ( e->url().string() != QString::null ) {
232 kurl = KURL( Kita::BoardManager::boardURL( m_datURL ), e->url().string() );
235 if ( e->qmouseEvent()->button() & Qt::RightButton ) {
236 m_isPushedRightButton = TRUE;
238 m_isPushedRightButton = FALSE;
241 if ( e->url() != NULL ) {
243 if ( e->url().string().at( 0 ) == '#' ) { /* anchor */
245 kurl.setRef( e->url().string().mid( 1 ) ) ;
249 m_isPushedRightButton = FALSE;
253 KHTMLPart::khtmlMousePressEvent( e );
256 /*-------------------------------------------------------*/
257 /*-------------------------------------------------------*/
260 /*------------------------------------------------------*/
261 /* This function is called when user clicked res anchor */ /* private */
262 void KitaPreviewPart::clickAnchor( const KURL& urlin )
265 KURL datURL = Kita::getDatURL( urlin , refstr );
267 /*--------------------------------*/
268 /* If this is not anchor, then */
269 /* emit openURLRequest and return */
271 if ( datURL.host() != m_datURL.host() || datURL.path() != m_datURL.path() ) {
272 emit openURLRequestExt( urlin );
276 if ( refstr == QString::null ) return ;
278 /*-------------------------*/
279 /* start multi-popup mdde */
280 if ( m_isPushedRightButton && startMultiPopup() ) return ;
282 /*-------------------------------*/
283 /* open Kita Navi or goto anchor */
287 int i = refstr.find( "-" );
289 refNum = refstr.left( i ).toInt();
290 refNum2 = refstr.mid( i + 1 ).toInt();
291 if ( refNum2 < refNum ) refNum2 = refNum;
292 } else refNum = refNum2 = refstr.toInt();
294 if ( !refNum ) return ;
296 emit openURLRequestExt( urlin );
299 /*-------------------------------------------------------*/
300 /*-------------------------------------------------------*/
303 void KitaPreviewPart::slotDeletePopup()
305 if ( m_popup ) delete m_popup;
307 m_multiPopup = FALSE;
310 /* for convenience */ /* private */
311 void KitaPreviewPart::showPopup( const KURL& url, const QString& innerHTML )
313 showPopupCore( url, innerHTML, QCursor::pos() );
316 /* show popup window */ /* private */
317 void KitaPreviewPart::showPopupCore( const KURL& url, const QString& innerHTML, QPoint point )
320 m_multiPopup = FALSE;
322 m_popup = new Kita::ResPopup( view() , url );
324 connect( m_popup, SIGNAL( hideChildPopup() ), SLOT( slotHideChildPopup() ) );
326 m_popup->setText( innerHTML );
327 m_popup->adjustSize();
328 m_popup->adjustPos( point );
332 /*------------------------*/
333 /* start multi-popup mode */ /* private */
334 bool KitaPreviewPart::startMultiPopup()
336 if ( m_popup && m_popup->isVisible() ) {
338 m_popup->moveMouseAbove();
340 m_multiPopup = FALSE;
346 /* Is it multi-popup mode now ? */ /* private */
347 bool KitaPreviewPart::isMultiPopupMode()
349 if ( !m_popup ) m_multiPopup = FALSE;
350 else if ( m_popup->isHidden() ) m_multiPopup = FALSE;
356 void KitaPreviewPart::hidePopup()
358 if ( m_popup ) m_popup->hide();
359 m_multiPopup = FALSE;
363 void KitaPreviewPart::slotLeave()
365 if ( isMultiPopupMode() ) return ;
366 if ( view() ->isHorizontalSliderPressed() ) return ;
367 if ( view() ->isVerticalSliderPressed () ) return ;
373 void KitaPreviewPart::slotVSliderReleased()
375 QScrollBar * bar = view() ->verticalScrollBar();
376 QRect rt = bar->sliderRect();
382 void KitaPreviewPart::slotHSliderReleased()
384 QScrollBar * bar = view() ->horizontalScrollBar();
385 QRect rt = bar->sliderRect();
391 void KitaPreviewPart::slotHideChildPopup()
396 /*------------------------------------------*/
397 /* called back when kita is active .
398 see also an explanation in slotOnURL. */ /* private slot */
399 void KitaPreviewPart::slotKitaIsActive()
401 m_kitaIsActive = TRUE;
404 /*---------------------------------------------------*/
405 /* This slot is called when mouse moves onto the URL */ /* private slot */
406 void KitaPreviewPart::slotOnURL( const QString& url )
410 const int maxpopup = 10; /* max number of responses shown in the popup window */
412 /*----------------------------*/
414 if ( isMultiPopupMode() ) return ;
418 if ( url.isEmpty() ) return ;
419 if ( url.left( 7 ) == "mailto:" ) return ;
421 /* Is Kita active now ?
423 emit SIGNAL( isKitaActive() ) to KitaMainWindow, KitaNavi, etc. ,
424 and if one of them is active, then slotKitaIsActive() is called
425 back, and m_kitaIsActive is set to TRUE. */
426 m_kitaIsActive = FALSE;
428 if ( !m_kitaIsActive ) return ;
432 KURL datURL = m_datURL;
433 if ( url.at( 0 ) == '#' ) refstr = url.mid( 1 );
434 else datURL = Kita::getDatURL( KURL( m_datURL, url ) , refstr );
436 /*-------------------------*/
437 /* popup for anchor */
439 QString innerHTML = QString::null;
443 int i = refstr.find( "-" );
444 if ( i != -1 ) { /* >>refNum-refNum2 */
446 refNum = refstr.left( i ).toInt();
447 refNum2 = refstr.mid( i + 1 ).toInt();
450 if ( refNum2 < refNum ) refNum2 = refNum;
451 if ( refNum2 - refNum > maxpopup - 1 ) refNum2 = refNum + maxpopup - 1;
454 } else { /* >>refNum */
455 refNum = refstr.toInt();
459 /* another thread ? */
460 if ( datURL.host() != m_datURL.host() || datURL.path() != m_datURL.path() ) {
463 QString boardName = Kita::BoardManager::boardName( datURL );
464 if ( boardName != QString::null ) innerHTML += "[" + boardName + "] ";
466 /* If idx file of datURL is not read, thread name cannot be obtained.
467 so, create DatInfo if cache exists, and read idx file in DatInfo::DatInfo(). */
468 Kita::DatManager::getDatInfoPointer( datURL );
470 /* get thread Name */
471 QString subName = Kita::DatManager::threadName( datURL );
472 if ( subName != QString::null ) innerHTML += subName + "<br><br>";
474 if ( !refNum ) refNum = refNum2 = 1;
477 /* get HTML and show it */
478 if ( !refNum ) return ;
479 innerHTML += Kita::DatManager::getHtml( datURL, refNum, refNum2 );
481 if ( innerHTML != QString::null ) showPopup( datURL, innerHTML );