mirror of
https://invent.kde.org/graphics/okular
synced 2024-10-02 14:14:10 +00:00
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
This commit is contained in:
parent
9ff5451f1f
commit
d95efa7698
|
@ -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})
|
||||
|
||||
|
|
|
@ -19,7 +19,6 @@
|
|||
#include <qlayout.h>
|
||||
#include <qmutex.h>
|
||||
#include <qregexp.h>
|
||||
#include <qstack.h>
|
||||
#include <qtextstream.h>
|
||||
#include <QtGui/QPrinter>
|
||||
#include <QtGui/QPainter>
|
||||
|
@ -423,7 +422,7 @@ PDFGenerator::PDFGenerator( QObject *parent, const QVariantList &args )
|
|||
: Generator( parent, args ), pdfdoc( 0 ),
|
||||
docSynopsisDirty( true ),
|
||||
docEmbeddedFilesDirty( true ), nextFontPage( 0 ),
|
||||
annotProxy( 0 ), synctex_scanner( 0 )
|
||||
annotProxy( 0 )
|
||||
{
|
||||
setFeature( Threaded );
|
||||
setFeature( TextExtraction );
|
||||
|
@ -462,18 +461,7 @@ Okular::Document::OpenResult PDFGenerator::loadDocumentWithPassword( const QStri
|
|||
#endif
|
||||
// create PDFDoc for the given file
|
||||
pdfdoc = Poppler::Document::load( filePath, 0, 0 );
|
||||
Okular::Document::OpenResult success = init(pagesVector, password);
|
||||
if (success == Okular::Document::OpenSuccess)
|
||||
{
|
||||
// no need to check for the existence of a synctex file, no parser will be
|
||||
// created if none exists
|
||||
initSynctexParser(filePath);
|
||||
if ( !synctex_scanner && QFile::exists(filePath + QLatin1String( "sync" ) ) )
|
||||
{
|
||||
loadPdfSync(filePath, pagesVector);
|
||||
}
|
||||
}
|
||||
return success;
|
||||
return init(pagesVector, password);
|
||||
}
|
||||
|
||||
Okular::Document::OpenResult PDFGenerator::loadDocumentFromDataWithPassword( const QByteArray & fileData, QVector<Okular::Page*> & pagesVector, const QString &password )
|
||||
|
@ -546,11 +534,6 @@ bool PDFGenerator::doCloseDocument()
|
|||
docEmbeddedFiles.clear();
|
||||
nextFontPage = 0;
|
||||
rectsGenerated.clear();
|
||||
if ( synctex_scanner )
|
||||
{
|
||||
synctex_scanner_free( synctex_scanner );
|
||||
synctex_scanner = 0;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -1589,162 +1572,6 @@ void PDFGenerator::addFormFields( Poppler::Page * popplerPage, Okular::Page * pa
|
|||
page->setFormFields( okularFormFields );
|
||||
}
|
||||
|
||||
struct pdfsyncpoint
|
||||
{
|
||||
QString file;
|
||||
qlonglong x;
|
||||
qlonglong y;
|
||||
int row;
|
||||
int column;
|
||||
int page;
|
||||
};
|
||||
|
||||
void PDFGenerator::loadPdfSync( const QString & filePath, QVector<Okular::Page*> & pagesVector )
|
||||
{
|
||||
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 );
|
||||
|
||||
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(PDFDebug) << "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(PDFDebug) << "PdfSync: going one level down too much";
|
||||
}
|
||||
else
|
||||
kDebug(PDFDebug).nospace() << "PdfSync: unknown line format: '" << line << "'";
|
||||
|
||||
}
|
||||
|
||||
QVector< QLinkedList< Okular::SourceRefObjectRect * > > refRects( pagesVector.size() );
|
||||
foreach ( const pdfsyncpoint& pt, points )
|
||||
{
|
||||
// drop pdfsync points not completely valid
|
||||
if ( pt.page < 0 || pt.page >= 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 * pagesVector[pt.page]->width() ),
|
||||
( pt.y * dpi().height() ) / ( 72.27 * 65536.0 * 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() )
|
||||
pagesVector[i]->setSourceReferences( refRects.at(i) );
|
||||
}
|
||||
|
||||
void PDFGenerator::initSynctexParser( const QString& filePath )
|
||||
{
|
||||
synctex_scanner = synctex_scanner_new_with_output_file( QFile::encodeName( filePath ), 0, 1);
|
||||
}
|
||||
|
||||
const Okular::SourceReference * PDFGenerator::dynamicSourceReference( int pageNr, double absX, double absY )
|
||||
{
|
||||
if ( !synctex_scanner )
|
||||
return 0;
|
||||
|
||||
if (synctex_edit_query(synctex_scanner, pageNr + 1, absX * 72. / dpi().width(), absY * 72. / dpi().height()) > 0)
|
||||
{
|
||||
synctex_node_t node;
|
||||
// TODO what should we do if there is really more than one node?
|
||||
while (( node = synctex_next_result( 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( synctex_scanner, synctex_node_tag( node ) );
|
||||
|
||||
Okular::SourceReference * sourceRef = new Okular::SourceReference( QFile::decodeName( name ), line, col );
|
||||
return sourceRef;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
PDFGenerator::PrintError PDFGenerator::printError() const
|
||||
{
|
||||
return lastPrintError;
|
||||
|
@ -1752,58 +1579,58 @@ PDFGenerator::PrintError PDFGenerator::printError() const
|
|||
|
||||
void PDFGenerator::fillViewportFromSourceReference( Okular::DocumentViewport & viewport, const QString & reference ) const
|
||||
{
|
||||
if ( !synctex_scanner )
|
||||
return;
|
||||
|
||||
// The reference is of form "src:1111Filename", where "1111"
|
||||
// points to line number 1111 in the file "Filename".
|
||||
// Extract the file name and the numeral part from the reference string.
|
||||
// This will fail if Filename starts with a digit.
|
||||
QString name, lineString;
|
||||
// Remove "src:". Presence of substring has been checked before this
|
||||
// function is called.
|
||||
name = reference.mid( 4 );
|
||||
// split
|
||||
int nameLength = name.length();
|
||||
int i = 0;
|
||||
for( i = 0; i < nameLength; ++i )
|
||||
{
|
||||
if ( !name[i].isDigit() ) break;
|
||||
}
|
||||
lineString = name.left( i );
|
||||
name = name.mid( i );
|
||||
// Remove spaces.
|
||||
name = name.trimmed();
|
||||
lineString = lineString.trimmed();
|
||||
// Convert line to integer.
|
||||
bool ok;
|
||||
int line = lineString.toInt( &ok );
|
||||
if (!ok) line = -1;
|
||||
|
||||
// Use column == -1 for now.
|
||||
if( synctex_display_query( synctex_scanner, QFile::encodeName(name), line, -1 ) > 0 )
|
||||
{
|
||||
synctex_node_t node;
|
||||
// For now use the first hit. Could possibly be made smarter
|
||||
// in case there are multiple hits.
|
||||
while( ( node = synctex_next_result( synctex_scanner ) ) )
|
||||
{
|
||||
// TeX pages start at 1.
|
||||
viewport.pageNumber = synctex_node_page( node ) - 1;
|
||||
|
||||
if ( !viewport.isValid() ) return;
|
||||
|
||||
// TeX small points ...
|
||||
double px = (synctex_node_visible_h( node ) * dpi().width()) / 72.27;
|
||||
double py = (synctex_node_visible_v( node ) * dpi().height()) / 72.27;
|
||||
viewport.rePos.normalizedX = px / document()->page(viewport.pageNumber)->width();
|
||||
viewport.rePos.normalizedY = ( py + 0.5 ) / document()->page(viewport.pageNumber)->height();
|
||||
viewport.rePos.enabled = true;
|
||||
viewport.rePos.pos = Okular::DocumentViewport::Center;
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
// if ( !synctex_scanner )
|
||||
// return;
|
||||
//
|
||||
// // The reference is of form "src:1111Filename", where "1111"
|
||||
// // points to line number 1111 in the file "Filename".
|
||||
// // Extract the file name and the numeral part from the reference string.
|
||||
// // This will fail if Filename starts with a digit.
|
||||
// QString name, lineString;
|
||||
// // Remove "src:". Presence of substring has been checked before this
|
||||
// // function is called.
|
||||
// name = reference.mid( 4 );
|
||||
// // split
|
||||
// int nameLength = name.length();
|
||||
// int i = 0;
|
||||
// for( i = 0; i < nameLength; ++i )
|
||||
// {
|
||||
// if ( !name[i].isDigit() ) break;
|
||||
// }
|
||||
// lineString = name.left( i );
|
||||
// name = name.mid( i );
|
||||
// // Remove spaces.
|
||||
// name = name.trimmed();
|
||||
// lineString = lineString.trimmed();
|
||||
// // Convert line to integer.
|
||||
// bool ok;
|
||||
// int line = lineString.toInt( &ok );
|
||||
// if (!ok) line = -1;
|
||||
//
|
||||
// // Use column == -1 for now.
|
||||
// if( synctex_display_query( synctex_scanner, QFile::encodeName(name), line, -1 ) > 0 )
|
||||
// {
|
||||
// synctex_node_t node;
|
||||
// // For now use the first hit. Could possibly be made smarter
|
||||
// // in case there are multiple hits.
|
||||
// while( ( node = synctex_next_result( synctex_scanner ) ) )
|
||||
// {
|
||||
// // TeX pages start at 1.
|
||||
// viewport.pageNumber = synctex_node_page( node ) - 1;
|
||||
//
|
||||
// if ( !viewport.isValid() ) return;
|
||||
//
|
||||
// // TeX small points ...
|
||||
// double px = (synctex_node_visible_h( node ) * dpi().width()) / 72.27;
|
||||
// double py = (synctex_node_visible_v( node ) * dpi().height()) / 72.27;
|
||||
// viewport.rePos.normalizedX = px / document()->page(viewport.pageNumber)->width();
|
||||
// viewport.rePos.normalizedY = ( py + 0.5 ) / document()->page(viewport.pageNumber)->height();
|
||||
// viewport.rePos.enabled = true;
|
||||
// viewport.rePos.pos = Okular::DocumentViewport::Center;
|
||||
//
|
||||
// return;
|
||||
// }
|
||||
// }
|
||||
}
|
||||
|
||||
QWidget* PDFGenerator::printConfigurationWidget() const
|
||||
|
|
|
@ -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 );
|
||||
|
|
Loading…
Reference in a new issue