Commit d95efa76 authored by Albert Astals Cid's avatar Albert Astals Cid

Move synctex up to the core from poppler generator

This way dvi and any other potential user gets it for free

The diff is huge, but the synctex files are just moves.

And the code in core/ is also mostly just a move from the generator_pdf.cpp code

Acked by Luigi

REVIEW: 120311
parent 9ff5451f
......@@ -13,6 +13,8 @@ macro_log_feature(QIMAGEBLITZ_FOUND "QImageBlitz" "An image effects library" "ht
macro_optional_find_package(LibKScreen)
macro_log_feature(LibKScreen_FOUND "LibKScreen" "KDE screen management library" "https://projects.kde.org/projects/kdereview/libkscreen" FALSE "1.0.2" "DPI detection support")
find_package(ZLIB REQUIRED)
add_definitions(${QT_DEFINITIONS} ${KDE4_DEFINITIONS})
add_definitions(-DQT_USE_FAST_CONCATENATION -DQT_USE_FAST_OPERATOR_PLUS)
include_directories(
......@@ -20,6 +22,8 @@ include_directories(
${KDE4_INCLUDES}
${QIMAGEBLITZ_INCLUDES}
${LibKScreen_INCLUDE_DIR}
${ZLIB_INCLUDE_DIR}
core/synctex
)
add_subdirectory( active )
......@@ -80,6 +84,8 @@ set(okularcore_SRCS
core/script/kjs_field.cpp
core/script/kjs_spell.cpp
core/script/kjs_util.cpp
core/synctex/synctex_parser.c
core/synctex/synctex_parser_utils.c
)
kde4_add_ui_files(okularcore_SRCS
......@@ -133,7 +139,7 @@ IF(APPLE)
SET(OKULAR_IOKIT "-framework IOKit" CACHE STRING "Apple IOKit framework")
ENDIF(APPLE)
target_link_libraries(okularcore ${OKULAR_IOKIT} ${KDE4_KIO_LIBS} ${KDE4_PHONON_LIBRARY} ${KDE4_KJSAPI_LIBRARY} ${MATH_LIB} ${KDE4_THREADWEAVER_LIBRARY} )
target_link_libraries(okularcore ${OKULAR_IOKIT} ${KDE4_KIO_LIBS} ${KDE4_PHONON_LIBRARY} ${KDE4_KJSAPI_LIBRARY} ${MATH_LIB} ${KDE4_THREADWEAVER_LIBRARY} ${ZLIB_LIBRARIES} )
if(LibKScreen_FOUND)
target_link_libraries(okularcore ${LibKScreen_LIBRARY})
......
......@@ -34,6 +34,7 @@
#include <QtGui/QLabel>
#include <QtGui/QPrinter>
#include <QtGui/QPrintDialog>
#include <QStack>
#include <QUndoCommand>
#include <kaboutdata.h>
......@@ -2048,6 +2049,132 @@ bool DocumentPrivate::isNormalizedRectangleFullyVisible( const Okular::Normalize
return rectFullyVisible;
}
struct pdfsyncpoint
{
QString file;
qlonglong x;
qlonglong y;
int row;
int column;
int page;
};
void DocumentPrivate::loadSyncFile( const QString & filePath )
{
QFile f( filePath + QLatin1String( "sync" ) );
if ( !f.open( QIODevice::ReadOnly ) )
return;
QTextStream ts( &f );
// first row: core name of the pdf output
const QString coreName = ts.readLine();
// second row: version string, in the form 'Version %u'
QString versionstr = ts.readLine();
QRegExp versionre( "Version (\\d+)" );
versionre.setCaseSensitivity( Qt::CaseInsensitive );
if ( !versionre.exactMatch( versionstr ) )
return;
QHash<int, pdfsyncpoint> points;
QStack<QString> fileStack;
int currentpage = -1;
const QLatin1String texStr( ".tex" );
const QChar spaceChar = QChar::fromLatin1( ' ' );
fileStack.push( coreName + texStr );
const QSizeF dpi = m_generator->dpi();
QString line;
while ( !ts.atEnd() )
{
line = ts.readLine();
const QStringList tokens = line.split( spaceChar, QString::SkipEmptyParts );
const int tokenSize = tokens.count();
if ( tokenSize < 1 )
continue;
if ( tokens.first() == QLatin1String( "l" ) && tokenSize >= 3 )
{
int id = tokens.at( 1 ).toInt();
QHash<int, pdfsyncpoint>::const_iterator it = points.constFind( id );
if ( it == points.constEnd() )
{
pdfsyncpoint pt;
pt.x = 0;
pt.y = 0;
pt.row = tokens.at( 2 ).toInt();
pt.column = 0; // TODO
pt.page = -1;
pt.file = fileStack.top();
points[ id ] = pt;
}
}
else if ( tokens.first() == QLatin1String( "s" ) && tokenSize >= 2 )
{
currentpage = tokens.at( 1 ).toInt() - 1;
}
else if ( tokens.first() == QLatin1String( "p*" ) && tokenSize >= 4 )
{
// TODO
kDebug() << "PdfSync: 'p*' line ignored";
}
else if ( tokens.first() == QLatin1String( "p" ) && tokenSize >= 4 )
{
int id = tokens.at( 1 ).toInt();
QHash<int, pdfsyncpoint>::iterator it = points.find( id );
if ( it != points.end() )
{
it->x = tokens.at( 2 ).toInt();
it->y = tokens.at( 3 ).toInt();
it->page = currentpage;
}
}
else if ( line.startsWith( QLatin1Char( '(' ) ) && tokenSize == 1 )
{
QString newfile = line;
// chop the leading '('
newfile.remove( 0, 1 );
if ( !newfile.endsWith( texStr ) )
{
newfile += texStr;
}
fileStack.push( newfile );
}
else if ( line == QLatin1String( ")" ) )
{
if ( !fileStack.isEmpty() )
{
fileStack.pop();
}
else
kDebug() << "PdfSync: going one level down too much";
}
else
kDebug().nospace() << "PdfSync: unknown line format: '" << line << "'";
}
QVector< QLinkedList< Okular::SourceRefObjectRect * > > refRects( m_pagesVector.size() );
foreach ( const pdfsyncpoint& pt, points )
{
// drop pdfsync points not completely valid
if ( pt.page < 0 || pt.page >= m_pagesVector.size() )
continue;
// magic numbers for TeX's RSU's (Ridiculously Small Units) conversion to pixels
Okular::NormalizedPoint p(
( pt.x * dpi.width() ) / ( 72.27 * 65536.0 * m_pagesVector[pt.page]->width() ),
( pt.y * dpi.height() ) / ( 72.27 * 65536.0 * m_pagesVector[pt.page]->height() )
);
QString file = pt.file;
Okular::SourceReference * sourceRef = new Okular::SourceReference( file, pt.row, pt.column );
refRects[ pt.page ].append( new Okular::SourceRefObjectRect( p, sourceRef ) );
}
for ( int i = 0; i < refRects.size(); ++i )
if ( !refRects.at(i).isEmpty() )
m_pagesVector[i]->setSourceReferences( refRects.at(i) );
}
Document::Document( QWidget *widget )
: QObject( 0 ), d( new DocumentPrivate( this ) )
{
......@@ -2245,6 +2372,14 @@ Document::OpenResult Document::openDocument( const QString & docFile, const KUrl
return openResult;
}
// no need to check for the existence of a synctex file, no parser will be
// created if none exists
d->synctex_scanner = synctex_scanner_new_with_output_file( QFile::encodeName( docFile ), 0, 1);
if ( !d->synctex_scanner && QFile::exists(docFile + QLatin1String( "sync" ) ) )
{
d->loadSyncFile(docFile);
}
d->m_generatorName = offer->name();
d->m_pageController = new PageController();
connect( d->m_pageController, SIGNAL(rotationFinished(int,Okular::Page*)),
......@@ -2399,6 +2534,12 @@ void Document::closeDocument()
d->m_generator->closeDocument();
}
if ( d->synctex_scanner )
{
synctex_scanner_free( d->synctex_scanner );
d->synctex_scanner = 0;
}
// stop timers
if ( d->m_memCheckTimer )
d->m_memCheckTimer->stop();
......@@ -3856,12 +3997,31 @@ void Document::processSourceReference( const SourceReference * ref )
const SourceReference * Document::dynamicSourceReference( int pageNr, double absX, double absY )
{
const SourceReference * ref = 0;
if ( d->m_generator )
if ( !d->synctex_scanner )
return 0;
const QSizeF dpi = d->m_generator->dpi();
qDebug() << absX << absY << dpi;
if (synctex_edit_query(d->synctex_scanner, pageNr + 1, absX * 72. / dpi.width(), absY * 72. / dpi.height()) > 0)
{
QMetaObject::invokeMethod( d->m_generator, "dynamicSourceReference", Qt::DirectConnection, Q_RETURN_ARG(const Okular::SourceReference*, ref), Q_ARG(int, pageNr), Q_ARG(double, absX), Q_ARG(double, absY) );
synctex_node_t node;
// TODO what should we do if there is really more than one node?
while (( node = synctex_next_result( d->synctex_scanner ) ))
{
int line = synctex_node_line(node);
int col = synctex_node_column(node);
// column extraction does not seem to be implemented in synctex so far. set the SourceReference default value.
if ( col == -1 )
{
col = 0;
}
const char *name = synctex_scanner_get_name( d->synctex_scanner, synctex_node_tag( node ) );
return new Okular::SourceReference( QFile::decodeName( name ), line, col );
}
}
return ref;
return 0;
}
Document::PrintingType Document::printingSupport() const
......
......@@ -13,6 +13,8 @@
#include "document.h"
#include "synctex/synctex_parser.h"
// qt/kde/system includes
#include <QtCore/QHash>
#include <QtCore/QLinkedList>
......@@ -97,7 +99,8 @@ class DocumentPrivate
m_archiveData( 0 ),
m_fontsCached( false ),
m_annotationEditingEnabled ( true ),
m_annotationBeingMoved( false )
m_annotationBeingMoved( false ),
synctex_scanner( 0 )
{
calculateMaxTextPages();
}
......@@ -182,6 +185,9 @@ class DocumentPrivate
*/
bool isNormalizedRectangleFullyVisible( const Okular::NormalizedRect & rectOfInterest, int rectPage );
// For sync files
void loadSyncFile( const QString & filePath );
// member variables
Document *m_parent;
QPointer<QWidget> m_widget;
......@@ -270,6 +276,8 @@ class DocumentPrivate
QUndoStack *m_undoStack;
QDomNode m_prevPropsOfAnnotBeingModified;
synctex_scanner_t synctex_scanner;
};
class DocumentInfoPrivate
......
......@@ -442,11 +442,6 @@ void Generator::requestFontData(const Okular::FontInfo & /*font*/, QByteArray *
}
const SourceReference * Generator::dynamicSourceReference( int /*pageNr*/, double /*absX*/, double /*absY*/)
{
return 0;
}
void Generator::setDPI(const QSizeF & dpi)
{
Q_D( Generator );
......
......@@ -538,15 +538,6 @@ class OKULAR_EXPORT Generator : public QObject
*/
void requestFontData(const Okular::FontInfo &font, QByteArray *data);
/**
* Asks the generator to dynamically generate a SourceReference for a given
* page number and absolute X and Y position on this page.
*
* @attention Ownership of the returned SourceReference is transferred to the caller.
* @since 0.10 (KDE 4.4)
*/
const SourceReference * dynamicSourceReference( int pageNr, double absX, double absY );
/**
* Returns the last print error in case print() failed
* @since 0.11 (KDE 4.5)
......
......@@ -13,7 +13,6 @@
#include <core/page.h>
#include <core/sourcereference.h>
#include <core/textpage.h>
#include <core/utils.h>
#include "generator_dvi.h"
#include "dviFile.h"
......@@ -122,7 +121,7 @@ bool DviGenerator::loadDocument( const QString & fileName, QVector< Okular::Page
kDebug(DviDebug) << "# of pages:" << m_dviRenderer->dviFile->total_pages;
m_resolution = Okular::Utils::dpiY();
m_resolution = dpi().height();
loadPages( pagesVector );
return true;
......@@ -538,7 +537,7 @@ void DviGenerator::loadPages( QVector< Okular::Page * > &pagesVector )
if ( sfa.page < 1 || (int)sfa.page > numofpages )
continue;
Okular::NormalizedPoint p( -1.0, (double)sfa.distance_from_top.getLength_in_pixel( Okular::Utils::dpiY() ) / (double)pageRequiredSize.height() );
Okular::NormalizedPoint p( -1.0, (double)sfa.distance_from_top.getLength_in_pixel( dpi().height() ) / (double)pageRequiredSize.height() );
Okular::SourceReference * sourceRef = new Okular::SourceReference( sfa.fileName, sfa.line );
refRects[ sfa.page - 1 ].append( new Okular::SourceRefObjectRect( p, sourceRef ) );
}
......
......@@ -21,19 +21,10 @@ include_directories(
########### next target ###############
find_package(ZLIB REQUIRED)
include_directories(
synctex
${ZLIB_INCLUDE_DIR}
)
set(okularGenerator_poppler_PART_SRCS
generator_pdf.cpp
formfields.cpp
annots.cpp
synctex/synctex_parser.c
synctex/synctex_parser_utils.c
)
kde4_add_ui_files(okularGenerator_poppler_PART_SRCS
......@@ -44,7 +35,7 @@ kde4_add_kcfg_files(okularGenerator_poppler_PART_SRCS conf/pdfsettings.kcfgc )
kde4_add_plugin(okularGenerator_poppler ${okularGenerator_poppler_PART_SRCS})
target_link_libraries(okularGenerator_poppler ${POPPLER_LIBRARY} okularcore ${KDE4_KDEUI_LIBS} ${QT_QTXML_LIBRARY} ${ZLIB_LIBRARIES})
target_link_libraries(okularGenerator_poppler ${POPPLER_LIBRARY} okularcore ${KDE4_KDEUI_LIBS} ${QT_QTXML_LIBRARY})
install(TARGETS okularGenerator_poppler DESTINATION ${PLUGIN_INSTALL_DIR})
......
This diff is collapsed.
......@@ -13,8 +13,6 @@
#define UNSTABLE_POPPLER_QT4
#include "synctex/synctex_parser.h"
#include <poppler-qt4.h>
#include <qbitarray.h>
......@@ -104,7 +102,6 @@ class PDFGenerator : public Okular::Generator, public Okular::ConfigInterface, p
protected slots:
void requestFontData(const Okular::FontInfo &font, QByteArray *data);
const Okular::SourceReference * dynamicSourceReference( int pageNr, double absX, double absY );
Okular::Generator::PrintError printError() const;
private:
......@@ -120,8 +117,6 @@ class PDFGenerator : public Okular::Generator, public Okular::ConfigInterface, p
void addFormFields( Poppler::Page * popplerPage, Okular::Page * page );
// load the source references from a pdfsync file
void loadPdfSync( const QString & fileName, QVector<Okular::Page*> & pagesVector );
// init the synctex parser if a synctex file exists
void initSynctexParser( const QString& filePath );
// search document for source reference
void fillViewportFromSourceReference( Okular::DocumentViewport & viewport, const QString & reference ) const;
......@@ -149,8 +144,6 @@ class PDFGenerator : public Okular::Generator, public Okular::ConfigInterface, p
QPointer<PDFOptionsPage> pdfOptionsPage;
synctex_scanner_t synctex_scanner;
PrintError lastPrintError;
};
......
......@@ -2355,6 +2355,7 @@ void PageView::mouseReleaseEvent( QMouseEvent * e )
if ( rect && ( distance > s_minDistance ) )
rect = 0;
}
qDebug() << "C" << rect;
if ( rect )
{
const Okular::SourceReference * ref = static_cast< const Okular::SourceReference * >( rect->object() );
......@@ -2363,6 +2364,7 @@ void PageView::mouseReleaseEvent( QMouseEvent * e )
else
{
const Okular::SourceReference * ref = d->document->dynamicSourceReference( pageItem-> pageNumber(), nX * pageItem->page()->width(), nY * pageItem->page()->height() );
qDebug() << "D" << ref;
if ( ref )
{
d->document->processSourceReference( ref );
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment