/*************************************************************************** * Copyright (C) 2005 by Piotr SzymaƄski * * * * 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 * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * ***************************************************************************/ #include "generator_chm.h" #include "lib/xchmfile.h" #include "settings.h" #include "core/page.h" #include "core/link.h" #include "core/observer.h" //for PAGEVIEW_ID #include "dom/html_misc.h" #include #include #include #include #include #include #include #include #include #include OKULAR_EXPORT_PLUGIN(CHMGenerator) CHMGenerator::CHMGenerator() : Okular::Generator() { m_syncGen=0; m_file=0; m_state=-1; m_docInfo=0; // m_asyncGen=0; // px=0; m_pixmapRequestZoom=1; } bool CHMGenerator::loadDocument( const QString & fileName, QVector< Okular::Page * > & pagesVector ) { m_fileName=fileName; m_file=new CHMFile (fileName); m_file->ParseAndFillTopicsTree (&m_docSyn); QPrinter p; p.setPageSize(static_cast< QPrinter::PageSize >( KGlobal::locale()->pageSize() )); p.setFullPage(true); kDebug () << "UrlPage count " << m_file->m_UrlPage.count() << endl; pagesVector.resize(m_file->m_UrlPage.count()); if (!m_syncGen) { m_syncGen = new KHTMLPart(); connect (m_syncGen,SIGNAL(completed()),this,SLOT(slotCompleted())); } QMap ::ConstIterator it=m_file->m_UrlPage.begin(), end=m_file->m_UrlPage.end(); m_state=0; for (;it!=end;++it) { preparePageForSyncOperation(100,it.key()); int i= it.value() - 1; pagesVector[ i ] = new Okular::Page (i, m_syncGen->view()->contentsWidth(), m_syncGen->view()->contentsHeight(),0); kDebug() << "W/H: " << m_syncGen->view()->contentsWidth() << "/" << m_syncGen->view()->contentsHeight() << endl; } return true; } bool CHMGenerator::closeDocument() { // delete the document information of the old document delete m_docInfo; m_docInfo=0; return true; } void CHMGenerator::preparePageForSyncOperation( int zoom , const QString & url) { KUrl pAddress= "ms-its:" + m_fileName + "::" + url; m_state=0; kDebug() << "Url: " << pAddress << endl; m_syncGen->setZoomFactor(zoom); m_doneFlagSet=false; m_syncGen->openUrl(pAddress); m_syncGen->view()->layout(); while (!m_doneFlagSet) { qApp->processEvents(QEventLoop::AllEvents, 50); } } void CHMGenerator::slotCompleted() { kDebug() << "completed() " << m_state << endl; if (m_state==0) { m_doneFlagSet=true; } else if (m_state==1) { // kDebug() << "completed(1) " << m_request->id << endl; QImage image( m_request->width(), m_request->height(), QImage::Format_ARGB32 ); image.fill( qRgb( 255, 255, 255 ) ); QPainter p( &image ); QRect r( 0, 0, m_request->width(), m_request->height() ); bool moreToPaint; // m_syncGen->view()->layout(); m_syncGen->paint( &p, r, 0, &moreToPaint ); p.end(); if ( m_pixmapRequestZoom > 1 ) { image = image.scaled( m_request->width()/m_pixmapRequestZoom, m_request->height()/m_pixmapRequestZoom ); m_pixmapRequestZoom = 1; } additionalRequestData(); syncLock.unlock(); m_request->page()->setImage( m_request->id(), image ); signalRequestDone( m_request ); } } const Okular::DocumentInfo * CHMGenerator::generateDocumentInfo() { if (!m_docInfo) { m_docInfo=new Okular::DocumentInfo(); m_docInfo->set( "mimeType", "application/x-chm" ); m_docInfo->set( "title", m_file->Title(), i18n("Title") ); } return m_docInfo; } const Okular::DocumentSynopsis * CHMGenerator::generateDocumentSynopsis() { return &m_docSyn; } const Okular::DocumentFonts * CHMGenerator::generateDocumentFonts() { return 0L; } bool CHMGenerator::canGeneratePixmap ( bool /*async*/ ) const { bool isLocked = true; if ( syncLock.tryLock() ) { syncLock.unlock(); isLocked = false; } return !isLocked; } void CHMGenerator::generatePixmap( Okular::PixmapRequest * request ) { QString a="S"; if (request->asynchronous()) a="As"; kDebug() << a << "ync PixmapRequest of " << request->width() << "x" << request->height() << " size, pageNo " << request->pageNumber() << ", priority: " << request->priority() << " id: " << request->id() << endl; int requestWidth = request->width(); int requestHeight = request->height(); if (requestWidth<300) { m_pixmapRequestZoom=900/requestWidth; requestWidth*=m_pixmapRequestZoom; requestHeight*=m_pixmapRequestZoom; } syncLock.lock(); QString url= m_file->getUrlForPage ( request->pageNumber() + 1 ); int zoom = qRound( qMax( static_cast(requestWidth)/static_cast(request->page()->width()) , static_cast(requestHeight)/static_cast(request->page()->height()) ) ) * 100; KUrl pAddress= "ms-its:" + m_fileName + "::" + url; kDebug() << "Page asked is: " << pAddress << " zoom is " << zoom << endl; m_syncGen->setZoomFactor(zoom); m_syncGen->view()->resize(requestWidth,requestHeight); m_request=request; m_state=1; // will emit openURL without problems m_syncGen->openUrl ( pAddress ); } void CHMGenerator::recursiveExploreNodes(DOM::Node node,Okular::TextPage *tp) { if (node.nodeType() == DOM::Node::TEXT_NODE) { QString nodeText=node.nodeValue().string(); QRect r=node.getRect(); int vWidth=m_syncGen->view()->contentsWidth(); int vHeight=m_syncGen->view()->contentsHeight(); Okular::NormalizedRect *nodeNormRect; #define NOEXP #ifndef NOEXP int x,y,height; int x_next,y_next,height_next; int nodeTextLength = nodeText.length(); if (nodeTextLength==1) { nodeNormRect=new Okular::NormalizedRect (r,vWidth,vHeight); tp->append(nodeText,nodeNormRect,nodeNormRect->bottom,0,(nodeText=="\n")); kDebug() << "Norm Rect is [" << nodeNormRect->left << "x" << nodeNormRect->top << "] [" << nodeNormRect->right << "x" << nodeNormRect->bottom << "]" << endl; kDebug() << "Node Dom text(" << nodeText.length() << "): " << nodeText << endl; } else { for (int i=0;iappend(QString(nodeText[i]),nodeNormRect,nodeNormRect->bottom,0,(nodeText[i]=='\n')); kDebug () << "Working with offset : " << i << endl; kDebug() << "Norm Rect is [" << nodeNormRect->left << "x" << nodeNormRect->top << "] [" << nodeNormRect->right << "x" << nodeNormRect->bottom << "]" << endl; kDebug() << "Node Dom text(1): " << nodeText[i] << endl; } } #else nodeNormRect=new Okular::NormalizedRect (r,vWidth,vHeight); tp->append(nodeText,nodeNormRect/*,0*/); #endif } DOM::Node child = node.firstChild(); while ( !child.isNull() ) { recursiveExploreNodes(child,tp); child = child.nextSibling(); } } void CHMGenerator::additionalRequestData() { Okular::Page * page=m_request->page(); bool genObjectRects = m_request->id() & (PAGEVIEW_ID | PRESENTATION_ID); bool genTextPage = !m_request->page()->hasSearchPage() && genObjectRects; if (genObjectRects || genTextPage ) { DOM::HTMLDocument domDoc=m_syncGen->htmlDocument(); // only generate object info when generating a full page not a thumbnail if ( genObjectRects ) { kDebug() << "Generating ObjRects - start" << endl; QLinkedList< Okular::ObjectRect * > objRects; int xScale=m_request->width(); int yScale=m_request->height(); // getting links DOM::HTMLCollection coll=domDoc.links(); DOM::Node n; QRect r; if (! coll.isNull() ) { int size=coll.length(); for(int i=0;ipage()->setObjectRects( objRects ); } if ( genTextPage ) { kDebug() << "Generating text page - start" << endl; Okular::TextPage *tp=new Okular::TextPage(); recursiveExploreNodes(domDoc,tp); page->setSearchPage (tp); } } } bool CHMGenerator::canGenerateTextPage() const { return true; } void CHMGenerator::generateSyncTextPage( Okular::Page * page ) { syncLock.lock(); double zoomP=Okular::Settings::zoomFactor(); int zoom = qRound( zoomP * 100 ); m_syncGen->view()->resize(qRound( page->width() * zoomP ) , qRound( page->height() * zoomP )); preparePageForSyncOperation(zoom, m_file->getUrlForPage ( page->number() + 1 )); Okular::TextPage *tp=new Okular::TextPage(); recursiveExploreNodes( m_syncGen->htmlDocument(), tp); page->setSearchPage(tp); syncLock.unlock(); } bool CHMGenerator::supportsSearching() const { return true; } QString CHMGenerator::metaData( const QString &key, const QString &option ) const { if ( key == "NamedViewport" && !option.isEmpty() ) { Okular::DocumentViewport viewport; viewport.pageNumber = m_file->getPageNum( option ) -1; if ( viewport.pageNumber >= 0 ) return viewport.toString(); } else if ( key == "DocumentTitle" ) { return m_file->Title(); } return QString(); } /* void PixmapThreader::run() { kDebug() << "starting thread\n"; m_pix = m_gen->renderPixmap(m_req); QCustomEvent * readyEvent = new QCustomEvent( CHM_DATAREADY_ID ); readyEvent->setData(m_req); QApplication::postEvent( m_gen , readyEvent ); } void CHMGenerator::customEvent( QCustomEvent * e ) { if (e->type() == CHM_DATAREADY_ID ) { PixmapRequest* request=(PixmapRequest*) e->data(); asyncLock.unlock(); kDebug() << "got pixmap\n"; request->page->setPixmap( request->id, px->takePixmap() ); signalRequestDone( request ); } }*/ #include "generator_chm.moc"