Merge branch 'master' into mart/okularActive

This commit is contained in:
Marco Martin 2012-07-31 13:32:05 +02:00
commit d11d5d8106
18 changed files with 788 additions and 98 deletions

View file

@ -101,6 +101,7 @@ install( FILES
interfaces/configinterface.h
interfaces/guiinterface.h
interfaces/printinterface.h
interfaces/saveinterface.h
interfaces/viewerinterface.h
DESTINATION ${INCLUDE_INSTALL_DIR}/okular/interfaces COMPONENT Devel)

View file

@ -16,6 +16,7 @@
// local includes
#include "document.h"
#include "document_p.h"
#include "movie.h"
#include "page_p.h"
#include "sound.h"
@ -100,6 +101,9 @@ QRect AnnotationUtils::annotationGeometry( const Annotation * ann,
}
//END AnnotationUtils implementation
AnnotationProxy::~AnnotationProxy()
{
}
//BEGIN Annotation implementation
@ -732,9 +736,9 @@ void Annotation::setDisposeDataFunction( DisposeDataFunction func )
bool Annotation::canBeMoved() const
{
Q_D( const Annotation );
// for now, it is pointless moving external annotations
// as we cannot change them anyway
if ( d->m_flags & External )
// Don't move annotations if they cannot be modified
if ( !d->m_page || !d->m_page->m_doc->m_parent->canModifyPageAnnotation(this) )
return false;
// highlight "requires" to be "bounded" to text, and that's tricky for now
@ -764,8 +768,8 @@ void Annotation::store( QDomNode & annNode, QDomDocument & document ) const
e.setAttribute( "creationDate", d->m_creationDate.toString(Qt::ISODate) );
// store -other- attributes
if ( d->m_flags )
e.setAttribute( "flags", d->m_flags );
if ( d->m_flags ) // Strip internal flags
e.setAttribute( "flags", d->m_flags & ~(External | ExternallyDrawn | BeingMoved) );
if ( d->m_style.color().isValid() )
e.setAttribute( "color", d->m_style.color().name() );
if ( d->m_style.opacity() != 1.0 )

View file

@ -128,7 +128,8 @@ class OKULAR_EXPORT Annotation
DenyDelete = 32, ///< Cannot be deleted
ToggleHidingOnMouse = 64, ///< Can be hidden/shown by mouse click
External = 128, ///< Is stored external
ExternallyDrawn = 256 ///< Is drawn externally (eg the generator which povided it) @since 0.10 (KDE 4.4)
ExternallyDrawn = 256, ///< Is drawn externally (by the generator which provided it) @since 0.10 (KDE 4.4)
BeingMoved = 512 ///< Is being moved (mouse drag and drop). If ExternallyDrawn, the generator must not draw it @since 0.15 (KDE 4.9)
};
/**
@ -655,6 +656,59 @@ class OKULAR_EXPORT Annotation
Q_DISABLE_COPY( Annotation )
};
/**
* @short Native annotation interface
*
* Generators can subclass it to provide native annotation support.
* Generators can use Annotation::setNativeId to store per-annotation data.
*
* @since 0.15 (KDE 4.9)
*/
class OKULAR_EXPORT AnnotationProxy
{
public:
enum Capability
{
Addition, ///< Generator can create native annotations
Modification, ///< Generator can edit native annotations
Removal ///< Generator can remove native annotations
};
/**
* Destroys the annotation proxy.
*/
virtual ~AnnotationProxy();
/**
* Query for the supported capabilities.
*/
virtual bool supports( Capability capability ) const = 0;
/**
* Called when a new @p annotation is added to a @p page.
*
* @note Only called if supports(Addition) == true
*/
virtual void notifyAddition( Annotation *annotation, int page ) = 0;
/**
* Called after an existing @p annotation at a given @p page is modified.
*
* Generator can call @p annotation getters to get the new values.
* @p appearanceChanged tells if a non-visible property was modifed
*
* @note Only called if supports(Modification) == true
*/
virtual void notifyModification( const Annotation *annotation, int page, bool appearanceChanged ) = 0;
/**
* Called when an existing @p annotation at a given @p page is removed.
*
* @note Only called if supports(Removal) == true
*/
virtual void notifyRemoval( Annotation *annotation, int page ) = 0;
};
class OKULAR_EXPORT TextAnnotation : public Annotation
{
public:

View file

@ -771,6 +771,24 @@ DocumentViewport DocumentPrivate::nextDocumentViewport() const
return ret;
}
void DocumentPrivate::warnLimitedAnnotSupport()
{
if ( !m_showWarningLimitedAnnotSupport )
return;
m_showWarningLimitedAnnotSupport = false; // Show the warning once
if ( canAddAnnotationsNatively() )
{
// Show only if there are external annotations (we follow the usual XML path otherwise)
if ( m_containsExternalAnnotations )
KMessageBox::sorry( m_parent->widget(), i18n("Your changes will not be saved automatically. Use File -> Save As... or your changes will be lost") );
}
else
{
KMessageBox::information( m_parent->widget(), i18n("You can save the annotated document using File -> Export As -> Document Archive"), QString(), "annotExportAsArchive" );
}
}
void DocumentPrivate::saveDocumentInfo() const
{
if ( m_xmlFileName.isEmpty() )
@ -791,10 +809,13 @@ void DocumentPrivate::saveDocumentInfo() const
// 2.1. Save page attributes (bookmark state, annotations, ... ) to DOM
QDomElement pageList = doc.createElement( "pageList" );
root.appendChild( pageList );
PageItems saveWhat = AllPageItems;
if ( canAddAnnotationsNatively() && m_containsExternalAnnotations )
saveWhat &= ~AnnotationPageItems; // Don't save local annotations in this case
// <page list><page number='x'>.... </page> save pages that hold data
QVector< Page * >::const_iterator pIt = m_pagesVector.constBegin(), pEnd = m_pagesVector.constEnd();
for ( ; pIt != pEnd; ++pIt )
(*pIt)->d->saveLocalContents( pageList, doc );
(*pIt)->d->saveLocalContents( pageList, doc, saveWhat );
// 2.2. Save document info (current viewport, history, ... ) to DOM
QDomElement generalInfo = doc.createElement( "generalInfo" );
@ -1657,12 +1678,16 @@ bool Document::openDocument( const QString & docFile, const KUrl& url, const KMi
}
d->m_generatorName = offer->name();
d->m_containsExternalAnnotations = false;
d->m_showWarningLimitedAnnotSupport = true;
foreach ( Page * p, d->m_pagesVector )
{
p->d->m_doc = d;
if ( !p->annotations().empty() )
d->m_containsExternalAnnotations = true;
}
// 2. load Additional Data (our bookmarks and metadata) about the document
// 2. load Additional Data (bookmarks, local annotations and metadata) about the document
if ( d->m_archiveData )
{
d->loadDocumentInfo( d->m_archiveData->metadataFileName );
@ -2331,6 +2356,9 @@ void Document::requestTextPage( uint page )
void Document::addPageAnnotation( int page, Annotation * annotation )
{
Okular::SaveInterface * iface = qobject_cast< Okular::SaveInterface * >( d->m_generator );
AnnotationProxy *proxy = iface ? iface->annotationProxy() : 0;
// find out the page to attach annotation
Page * kp = d->m_pagesVector[ page ];
if ( !d->m_generator || !kp )
@ -2343,42 +2371,160 @@ void Document::addPageAnnotation( int page, Annotation * annotation )
// add annotation to the page
kp->addAnnotation( annotation );
// tell the annotation proxy
if ( proxy && proxy->supports(AnnotationProxy::Addition) )
proxy->notifyAddition( annotation, page );
// notify observers about the change
foreachObserver( notifyPageChanged( page, DocumentObserver::Annotations ) );
if ( annotation->flags() & Annotation::ExternallyDrawn )
{
// Redraw everything, including ExternallyDrawn annotations
d->refreshPixmaps( page );
}
d->warnLimitedAnnotSupport();
}
void Document::modifyPageAnnotation( int page, Annotation * newannotation )
bool Document::canModifyPageAnnotation( const Annotation * annotation ) const
{
//TODO: modify annotations
if ( !annotation || ( annotation->flags() & Annotation::DenyWrite ) )
return false;
if ( !isAllowed(Okular::AllowNotes) )
return false;
if ( ( annotation->flags() & Annotation::External ) && !d->canModifyExternalAnnotations() )
return false;
switch ( annotation->subType() )
{
case Annotation::AText:
case Annotation::ALine:
case Annotation::AGeom:
case Annotation::AHighlight:
case Annotation::AStamp:
case Annotation::AInk:
return true;
default:
return false;
}
}
void Document::modifyPageAnnotation( int page, Annotation * annotation )
{
modifyPageAnnotation( page, annotation, true );
}
void Document::modifyPageAnnotation( int page, Annotation * annotation, bool appearanceChanged )
{
Okular::SaveInterface * iface = qobject_cast< Okular::SaveInterface * >( d->m_generator );
AnnotationProxy *proxy = iface ? iface->annotationProxy() : 0;
// find out the page
Page * kp = d->m_pagesVector[ page ];
if ( !d->m_generator || !kp )
return;
kp->d->modifyAnnotation( newannotation );
// tell the annotation proxy
if ( proxy && proxy->supports(AnnotationProxy::Modification) )
proxy->notifyModification( annotation, page, appearanceChanged );
// notify observers about the change
foreachObserver( notifyPageChanged( page, DocumentObserver::Annotations ) );
if ( appearanceChanged && (annotation->flags() & Annotation::ExternallyDrawn) )
{
/* When an annotation is being moved, the generator will not render it.
* Therefore there's no need to refresh pixmaps after the first time */
if ( annotation->flags() & Annotation::BeingMoved )
{
if ( d->m_annotationBeingMoved )
return;
else // First time: take note
d->m_annotationBeingMoved = true;
}
else
{
d->m_annotationBeingMoved = false;
}
// Redraw everything, including ExternallyDrawn annotations
d->refreshPixmaps( page );
}
// If the user is moving the annotation, don't steal the focus
if ( (annotation->flags() & Annotation::BeingMoved) == 0 )
d->warnLimitedAnnotSupport();
}
bool Document::canRemovePageAnnotation( const Annotation * annotation ) const
{
if ( !annotation || ( annotation->flags() & Annotation::DenyDelete ) )
return false;
if ( ( annotation->flags() & Annotation::External ) && !d->canRemoveExternalAnnotations() )
return false;
switch ( annotation->subType() )
{
case Annotation::AText:
case Annotation::ALine:
case Annotation::AGeom:
case Annotation::AHighlight:
case Annotation::AStamp:
case Annotation::AInk:
return true;
default:
return false;
}
}
void Document::removePageAnnotation( int page, Annotation * annotation )
{
Okular::SaveInterface * iface = qobject_cast< Okular::SaveInterface * >( d->m_generator );
AnnotationProxy *proxy = iface ? iface->annotationProxy() : 0;
bool isExternallyDrawn;
// find out the page
Page * kp = d->m_pagesVector[ page ];
if ( !d->m_generator || !kp )
return;
if ( annotation->flags() & Annotation::ExternallyDrawn )
isExternallyDrawn = true;
else
isExternallyDrawn = false;
// try to remove the annotation
if ( kp->removeAnnotation( annotation ) )
if ( canRemovePageAnnotation( annotation ) )
{
// tell the annotation proxy
if ( proxy && proxy->supports(AnnotationProxy::Removal) )
proxy->notifyRemoval( annotation, page );
kp->removeAnnotation( annotation ); // Also destroys the object
// in case of success, notify observers about the change
foreachObserver( notifyPageChanged( page, DocumentObserver::Annotations ) );
if ( isExternallyDrawn )
{
// Redraw everything, including ExternallyDrawn annotations
d->refreshPixmaps( page );
}
}
d->warnLimitedAnnotSupport();
}
void Document::removePageAnnotations( int page, const QList< Annotation * > &annotations )
{
Okular::SaveInterface * iface = qobject_cast< Okular::SaveInterface * >( d->m_generator );
AnnotationProxy *proxy = iface ? iface->annotationProxy() : 0;
bool refreshNeeded = false;
// find out the page
Page * kp = d->m_pagesVector[ page ];
if ( !d->m_generator || !kp )
@ -2387,9 +2533,22 @@ void Document::removePageAnnotations( int page, const QList< Annotation * > &ann
bool changed = false;
foreach ( Annotation * annotation, annotations )
{
// try to remove the annotation
if ( kp->removeAnnotation( annotation ) )
bool isExternallyDrawn;
if ( annotation->flags() & Annotation::ExternallyDrawn )
isExternallyDrawn = true;
else
isExternallyDrawn = false;
if ( canRemovePageAnnotation( annotation ) )
{
if ( isExternallyDrawn )
refreshNeeded = true;
// tell the annotation proxy
if ( proxy && proxy->supports(AnnotationProxy::Removal) )
proxy->notifyRemoval( annotation, page );
kp->removeAnnotation( annotation ); // Also destroys the object
changed = true;
}
}
@ -2397,7 +2556,48 @@ void Document::removePageAnnotations( int page, const QList< Annotation * > &ann
{
// in case we removed even only one annotation, notify observers about the change
foreachObserver( notifyPageChanged( page, DocumentObserver::Annotations ) );
if ( refreshNeeded )
{
// Redraw everything, including ExternallyDrawn annotations
d->refreshPixmaps( page );
}
}
d->warnLimitedAnnotSupport();
}
bool DocumentPrivate::canAddAnnotationsNatively() const
{
Okular::SaveInterface * iface = qobject_cast< Okular::SaveInterface * >( m_generator );
if ( iface && iface->supportsOption(Okular::SaveInterface::SaveChanges) &&
iface->annotationProxy() && iface->annotationProxy()->supports(AnnotationProxy::Addition) )
return true;
return false;
}
bool DocumentPrivate::canModifyExternalAnnotations() const
{
Okular::SaveInterface * iface = qobject_cast< Okular::SaveInterface * >( m_generator );
if ( iface && iface->supportsOption(Okular::SaveInterface::SaveChanges) &&
iface->annotationProxy() && iface->annotationProxy()->supports(AnnotationProxy::Modification) )
return true;
return false;
}
bool DocumentPrivate::canRemoveExternalAnnotations() const
{
Okular::SaveInterface * iface = qobject_cast< Okular::SaveInterface * >( m_generator );
if ( iface && iface->supportsOption(Okular::SaveInterface::SaveChanges) &&
iface->annotationProxy() && iface->annotationProxy()->supports(AnnotationProxy::Removal) )
return true;
return false;
}
void Document::setPageTextSelection( int page, RegularAreaRect * rect, const QColor & color )
@ -3454,8 +3654,32 @@ bool Document::saveDocumentArchive( const QString &fileName )
filesNode.appendChild( metadataFileNameNode );
metadataFileNameNode.appendChild( contentDoc.createTextNode( "metadata.xml" ) );
// If the generator can save annotations natively, do it
KTemporaryFile modifiedFile;
bool annotationsSavedNatively = false;
if ( d->canAddAnnotationsNatively() )
{
if ( !modifiedFile.open() )
return false;
modifiedFile.close(); // We're only interested in the file name
QString errorText;
if ( saveChanges( modifiedFile.fileName(), &errorText ) )
{
docPath = modifiedFile.fileName(); // Save this instead of the original file
annotationsSavedNatively = true;
}
else
{
kWarning(OkularDebug) << "saveChanges failed: " << errorText;
kDebug(OkularDebug) << "Falling back to saving a copy of the original file";
}
}
KTemporaryFile metadataFile;
if ( !d->savePageDocumentInfo( &metadataFile, AnnotationPageItems ) )
PageItems saveWhat = annotationsSavedNatively ? None : AnnotationPageItems;
if ( !d->savePageDocumentInfo( &metadataFile, saveWhat ) )
return false;
const QByteArray contentDocXml = contentDoc.toByteArray();

View file

@ -367,11 +367,39 @@ class OKULAR_EXPORT Document : public QObject
*/
void addPageAnnotation( int page, Annotation *annotation );
/**
* Tests if the @p annotation can be modified
*
* @since 0.15 (KDE 4.9)
*/
bool canModifyPageAnnotation( const Annotation * annotation ) const;
/**
* Modifies the given @p annotation on the given @p page.
*
* Same as calling modifyPageAnnotation(int,Annotation*,bool) with
* appearanceChanged = true
*/
void modifyPageAnnotation( int page, Annotation *annotation );
/**
* Modifies the given @p annotation on the given @p page.
*
* The caller can set @p appearanceChanged to false if it didn't change
* the annotation appearance (because it only changed non-visible data
* such as timestamps or author name).
*
* @since 0.15 (KDE 4.9)
*/
void modifyPageAnnotation( int page, Annotation *annotation, bool appearanceChanged );
/**
* Tests if the @p annotation can be removed
*
* @since 0.15 (KDE 4.9)
*/
bool canRemovePageAnnotation( const Annotation * annotation ) const;
/**
* Removes the given @p annotation from the given @p page.
*/

View file

@ -85,7 +85,8 @@ class DocumentPrivate
m_scripter( 0 ),
m_archiveData( 0 ),
m_fontsCached( false ),
m_documentInfo( 0 )
m_documentInfo( 0 ),
m_annotationBeingMoved( false )
{
calculateMaxTextPages();
}
@ -114,6 +115,10 @@ class DocumentPrivate
bool openDocumentInternal( const KService::Ptr& offer, bool isstdin, const QString& docFile, const QByteArray& filedata );
bool savePageDocumentInfo( KTemporaryFile *infoFile, int what ) const;
DocumentViewport nextDocumentViewport() const;
bool canAddAnnotationsNatively() const;
bool canModifyExternalAnnotations() const;
bool canRemoveExternalAnnotations() const;
void warnLimitedAnnotSupport();
// private slots
void saveDocumentInfo() const;
@ -227,6 +232,10 @@ class DocumentPrivate
FontInfo::List m_fontsCache;
QSet< View * > m_views;
bool m_annotationBeingMoved; // is an annotation currently being moved?
bool m_containsExternalAnnotations; // set on opening and never changed
bool m_showWarningLimitedAnnotSupport;
};
}

View file

@ -14,6 +14,7 @@
#include <QtCore/QSet>
#include <QtCore/QString>
#include <QtCore/QVariant>
#include <QtCore/QUuid>
#include <QtGui/QPixmap>
#include <QtXml/QDomDocument>
#include <QtXml/QDomElement>
@ -26,6 +27,8 @@
#include "annotations_p.h"
#include "area.h"
#include "debug_p.h"
#include "document.h"
#include "document_p.h"
#include "form.h"
#include "form_p.h"
#include "pagecontroller_p.h"
@ -59,7 +62,7 @@ static void deleteObjectRects( QLinkedList< ObjectRect * >& rects, const QSet<Ob
PagePrivate::PagePrivate( Page *page, uint n, double w, double h, Rotation o )
: m_page( page ), m_number( n ), m_orientation( o ),
m_width( w ), m_height( h ), m_doc( 0 ), m_boundingBox( 0, 0, 1, 1 ),
m_rotation( Rotation0 ), m_maxuniqueNum( 0 ),
m_rotation( Rotation0 ),
m_text( 0 ), m_transition( 0 ), m_textSelections( 0 ),
m_openingAction( 0 ), m_closingAction( 0 ), m_duration( -1 ),
m_isBoundingBoxKnown( false )
@ -573,14 +576,10 @@ QColor Page::textSelectionColor() const
void Page::addAnnotation( Annotation * annotation )
{
//uniqueName: okular-PAGENUM-ID
// Generate uniqueName: okular-{UUID}
if(annotation->uniqueName().isEmpty())
{
QString uniqueName = "okular-";
uniqueName += ( QString::number(d->m_number) + '-' + QString::number(++(d->m_maxuniqueNum)) );
kDebug(OkularDebug).nospace() << "inc m_maxuniqueNum=" << d->m_maxuniqueNum;
QString uniqueName = "okular-" + QUuid::createUuid().toString();
annotation->setUniqueName( uniqueName );
}
annotation->d_ptr->m_page = d;
@ -596,37 +595,9 @@ void Page::addAnnotation( Annotation * annotation )
m_rects.append( rect );
}
void PagePrivate::modifyAnnotation(Annotation * newannotation )
{
if(!newannotation)
return;
QLinkedList< Annotation * >::iterator aIt = m_page->m_annotations.begin(), aEnd = m_page->m_annotations.end();
for ( ; aIt != aEnd; ++aIt )
{
if((*aIt)==newannotation)
return; //modified already
if((*aIt) && (*aIt)->uniqueName()==newannotation->uniqueName())
{
int rectfound = false;
QLinkedList< ObjectRect * >::iterator it = m_page->m_rects.begin(), end = m_page->m_rects.end();
for ( ; it != end && !rectfound; ++it )
if ( ( (*it)->objectType() == ObjectRect::OAnnotation ) && ( (*it)->object() == (*aIt) ) )
{
delete *it;
*it = new AnnotationObjectRect( newannotation );
rectfound = true;
}
delete *aIt;
*aIt = newannotation;
break;
}
}
}
bool Page::removeAnnotation( Annotation * annotation )
{
if ( !annotation || ( annotation->flags() & Annotation::DenyDelete ) )
if ( !d->m_doc->m_parent->canRemovePageAnnotation(annotation) )
return false;
QLinkedList< Annotation * >::iterator aIt = m_annotations.begin(), aEnd = m_annotations.end();
@ -780,17 +751,7 @@ void PagePrivate::restoreLocalContents( const QDomNode & pageNode )
// append annotation to the list or show warning
if ( annotation )
{
annotation->d_ptr->m_page = this;
m_page->m_annotations.append( annotation );
m_page->m_rects.append( new AnnotationObjectRect( annotation ) );
int pos = annotation->uniqueName().lastIndexOf("-");
if(pos != -1)
{
int uniqID=annotation->uniqueName().right(annotation->uniqueName().length()-pos-1).toInt();
if ( m_maxuniqueNum < uniqID )
m_maxuniqueNum = uniqID;
}
m_doc->m_parent->addPageAnnotation(m_number, annotation);
kDebug(OkularDebug) << "restored annot:" << annotation->uniqueName();
}
else

View file

@ -66,13 +66,6 @@ class PagePrivate
*/
void saveLocalContents( QDomNode & parentNode, QDomDocument & document, PageItems what = AllPageItems ) const;
/**
* Modifies an existing annotation by replacing it with a new @p annotation.
*
* The unique name is used to find the old annotation.
*/
void modifyAnnotation( Annotation * annotation );
/**
* Rotates the image and object rects of the page to the given @p orientation.
*/
@ -121,7 +114,6 @@ class PagePrivate
DocumentPrivate *m_doc;
NormalizedRect m_boundingBox;
Rotation m_rotation;
int m_maxuniqueNum;
TextPage * m_text;
PageTransition * m_transition;

View file

@ -14,7 +14,10 @@
#include <qvariant.h>
#include <core/annotations.h>
#include <core/area.h>
#include "annots.h"
#include "generator_pdf.h"
#include "popplerembeddedfile.h"
#include "config-okular-poppler.h"
@ -32,11 +35,243 @@ static void disposeAnnotation( const Okular::Annotation *ann )
delete popplerAnn;
}
static QPointF normPointToPointF( const Okular::NormalizedPoint& pt )
{
return QPointF(pt.x, pt.y);
}
static QRectF normRectToRectF( const Okular::NormalizedRect& rect )
{
return QRectF( QPointF(rect.left, rect.top), QPointF(rect.right, rect.bottom) );
}
// Poppler and Okular share the same flag values, but we don't want to export internal flags
static int maskExportedFlags(int flags)
{
return flags & ( Okular::Annotation::Hidden |
Okular::Annotation::FixedSize |
Okular::Annotation::FixedRotation |
Okular::Annotation::DenyPrint |
Okular::Annotation::DenyWrite |
Okular::Annotation::DenyDelete |
Okular::Annotation::ToggleHidingOnMouse );
}
//BEGIN PopplerAnnotationProxy implementation
PopplerAnnotationProxy::PopplerAnnotationProxy( Poppler::Document *doc, QMutex *userMutex )
: ppl_doc ( doc ), mutex ( userMutex )
{
}
PopplerAnnotationProxy::~PopplerAnnotationProxy()
{
}
bool PopplerAnnotationProxy::supports( Capability cap ) const
{
switch ( cap )
{
#ifdef HAVE_POPPLER_0_20
case Addition:
case Modification:
case Removal:
return true;
#endif
default:
return false;
}
}
void PopplerAnnotationProxy::notifyAddition( Okular::Annotation *okl_ann, int page )
{
#ifdef HAVE_POPPLER_0_20
// Export annotation to DOM
QDomDocument doc;
QDomElement dom_ann = doc.createElement( "root" );
Okular::AnnotationUtils::storeAnnotation( okl_ann, dom_ann, doc );
QMutexLocker ml(mutex);
// Create poppler annotation
Poppler::Annotation *ppl_ann = Poppler::AnnotationUtils::createAnnotation( dom_ann );
// Poppler doesn't render StampAnnotations yet
if ( ppl_ann->subType() != Poppler::Annotation::AStamp )
okl_ann->setFlags( okl_ann->flags() | Okular::Annotation::ExternallyDrawn );
// Poppler stores highlight points in swapped order
if ( ppl_ann->subType() == Poppler::Annotation::AHighlight )
{
Poppler::HighlightAnnotation * hlann = static_cast<Poppler::HighlightAnnotation*>( ppl_ann );
QList<Poppler::HighlightAnnotation::Quad> quads = hlann->highlightQuads();
QMutableListIterator<Poppler::HighlightAnnotation::Quad> it( quads );
while ( it.hasNext() )
{
Poppler::HighlightAnnotation::Quad &q = it.next();
QPointF t;
t = q.points[3];
q.points[3] = q.points[0];
q.points[0] = t;
t = q.points[2];
q.points[2] = q.points[1];
q.points[1] = t;
}
hlann->setHighlightQuads( quads );
}
// Bind poppler object to page
Poppler::Page *ppl_page = ppl_doc->page( page );
ppl_page->addAnnotation( ppl_ann );
delete ppl_page;
// Set pointer to poppler annotation as native Id
okl_ann->setNativeId( qVariantFromValue( ppl_ann ) );
okl_ann->setDisposeDataFunction( disposeAnnotation );
kDebug(PDFGenerator::PDFDebug) << okl_ann->uniqueName();
#endif
}
void PopplerAnnotationProxy::notifyModification( const Okular::Annotation *okl_ann, int page, bool appearanceChanged )
{
#ifdef HAVE_POPPLER_0_20
Q_UNUSED( page );
Q_UNUSED( appearanceChanged );
Poppler::Annotation *ppl_ann = qvariant_cast<Poppler::Annotation*>( okl_ann->nativeId() );
if ( !ppl_ann ) // Ignore non-native annotations
return;
QMutexLocker ml(mutex);
if ( okl_ann->flags() & Okular::Annotation::BeingMoved )
{
// Okular ui already renders the annotation on its own
ppl_ann->setFlags( Poppler::Annotation::Hidden );
return;
}
// Set basic properties
ppl_ann->setBoundary(normRectToRectF( okl_ann->boundingRectangle() ));
ppl_ann->setAuthor( okl_ann->author() );
ppl_ann->setContents( okl_ann->contents() );
ppl_ann->setFlags(maskExportedFlags( okl_ann->flags() ));
// Set style
Poppler::Annotation::Style s;
s.setColor( okl_ann->style().color() );
s.setWidth( okl_ann->style().width() );
s.setOpacity( okl_ann->style().opacity() );
ppl_ann->setStyle( s );
// Set type-specific properties (if any)
switch ( ppl_ann->subType() )
{
case Poppler::Annotation::AText:
{
const Okular::TextAnnotation * okl_txtann = static_cast<const Okular::TextAnnotation*>(okl_ann);
Poppler::TextAnnotation * ppl_txtann = static_cast<Poppler::TextAnnotation*>(ppl_ann);
ppl_txtann->setTextIcon( okl_txtann->textIcon() );
ppl_txtann->setTextFont( okl_txtann->textFont() );
ppl_txtann->setInplaceAlign( okl_txtann->inplaceAlignment() );
if ( okl_txtann->textType() == Okular::TextAnnotation::InPlace )
ppl_txtann->setContents( okl_txtann->inplaceText() ); // overrides contents
ppl_txtann->setCalloutPoints( QVector<QPointF>() );
ppl_txtann->setInplaceIntent( (Poppler::TextAnnotation::InplaceIntent)okl_txtann->inplaceIntent() );
break;
}
case Poppler::Annotation::ALine:
{
const Okular::LineAnnotation * okl_lineann = static_cast<const Okular::LineAnnotation*>(okl_ann);
Poppler::LineAnnotation * ppl_lineann = static_cast<Poppler::LineAnnotation*>(ppl_ann);
QLinkedList<QPointF> points;
foreach ( const Okular::NormalizedPoint &p, okl_lineann->linePoints() )
points.append(normPointToPointF( p ));
ppl_lineann->setLinePoints( points );
ppl_lineann->setLineStartStyle( (Poppler::LineAnnotation::TermStyle)okl_lineann->lineStartStyle() );
ppl_lineann->setLineEndStyle( (Poppler::LineAnnotation::TermStyle)okl_lineann->lineEndStyle() );
ppl_lineann->setLineClosed( okl_lineann->lineClosed() );
ppl_lineann->setLineInnerColor( okl_lineann->lineInnerColor() );
ppl_lineann->setLineLeadingForwardPoint( okl_lineann->lineLeadingForwardPoint() );
ppl_lineann->setLineLeadingBackPoint( okl_lineann->lineLeadingBackwardPoint() );
ppl_lineann->setLineShowCaption( okl_lineann->showCaption() );
ppl_lineann->setLineIntent( (Poppler::LineAnnotation::LineIntent)okl_lineann->lineIntent() );
break;
}
case Poppler::Annotation::AGeom:
{
const Okular::GeomAnnotation * okl_geomann = static_cast<const Okular::GeomAnnotation*>(okl_ann);
Poppler::GeomAnnotation * ppl_geomann = static_cast<Poppler::GeomAnnotation*>(ppl_ann);
ppl_geomann->setGeomType( (Poppler::GeomAnnotation::GeomType)okl_geomann->geometricalType() );
ppl_geomann->setGeomInnerColor( okl_geomann->geometricalInnerColor() );
break;
}
case Poppler::Annotation::AHighlight:
{
const Okular::HighlightAnnotation * okl_hlann = static_cast<const Okular::HighlightAnnotation*>(okl_ann);
Poppler::HighlightAnnotation * ppl_hlann = static_cast<Poppler::HighlightAnnotation*>(ppl_ann);
ppl_hlann->setHighlightType( (Poppler::HighlightAnnotation::HighlightType)okl_hlann->highlightType() );
break;
}
case Poppler::Annotation::AStamp:
{
const Okular::StampAnnotation * okl_stampann = static_cast<const Okular::StampAnnotation*>(okl_ann);
Poppler::StampAnnotation * ppl_stampann = static_cast<Poppler::StampAnnotation*>(ppl_ann);
ppl_stampann->setStampIconName( okl_stampann->stampIconName() );
break;
}
case Poppler::Annotation::AInk:
{
const Okular::InkAnnotation * okl_inkann = static_cast<const Okular::InkAnnotation*>(okl_ann);
Poppler::InkAnnotation * ppl_inkann = static_cast<Poppler::InkAnnotation*>(ppl_ann);
QList< QLinkedList<QPointF> > paths;
foreach ( const QLinkedList<Okular::NormalizedPoint> &path, okl_inkann->inkPaths() )
{
QLinkedList<QPointF> points;
foreach ( const Okular::NormalizedPoint &p, path )
points.append(normPointToPointF( p ));
paths.append( points );
}
ppl_inkann->setInkPaths( paths );
break;
}
default:
kDebug() << "Type-specific property modification is not implemented for this annotation type";
break;
}
kDebug(PDFGenerator::PDFDebug) << okl_ann->uniqueName();
#endif
}
void PopplerAnnotationProxy::notifyRemoval( Okular::Annotation *okl_ann, int page )
{
#ifdef HAVE_POPPLER_0_20
Poppler::Annotation *ppl_ann = qvariant_cast<Poppler::Annotation*>( okl_ann->nativeId() );
if ( !ppl_ann ) // Ignore non-native annotations
return;
QMutexLocker ml(mutex);
Poppler::Page *ppl_page = ppl_doc->page( page );
ppl_page->removeAnnotation( ppl_ann ); // Also destroys ppl_ann
delete ppl_page;
okl_ann->setNativeId( qVariantFromValue(0) ); // So that we don't double-free in disposeAnnotation
kDebug(PDFGenerator::PDFDebug) << okl_ann->uniqueName();
#endif
}
//END PopplerAnnotationProxy implementation
Okular::Annotation* createAnnotationFromPopplerAnnotation( Poppler::Annotation *ann, bool *doDelete )
{
Okular::Annotation *annotation = 0;
*doDelete = true;
bool tieToOkularAnn = false;
bool externallyDrawn = false;
switch ( ann->subType() )
{
case Poppler::Annotation::AFileAttachment:
@ -86,6 +321,21 @@ Okular::Annotation* createAnnotationFromPopplerAnnotation( Poppler::Annotation *
break;
}
case Poppler::Annotation::AText:
case Poppler::Annotation::ALine:
case Poppler::Annotation::AGeom:
case Poppler::Annotation::AHighlight:
case Poppler::Annotation::AInk:
{
externallyDrawn = true;
/* fallback */
}
case Poppler::Annotation::AStamp:
{
tieToOkularAnn = true;
*doDelete = false;
/* fallback */
}
#endif
default:
{
@ -95,7 +345,7 @@ Okular::Annotation* createAnnotationFromPopplerAnnotation( Poppler::Annotation *
doc.appendChild( root );
Poppler::AnnotationUtils::storeAnnotation( ann, root, doc );
annotation = Okular::AnnotationUtils::createAnnotation( root );
return annotation;
break;
}
}
if ( annotation )
@ -107,6 +357,27 @@ Okular::Annotation* createAnnotationFromPopplerAnnotation( Poppler::Annotation *
annotation->setCreationDate( ann->creationDate() );
annotation->setFlags( ann->flags() );
annotation->setBoundingRectangle( Okular::NormalizedRect::fromQRectF( ann->boundary() ) );
if (externallyDrawn)
annotation->setFlags( annotation->flags() | Okular::Annotation::ExternallyDrawn );
// Poppler stores highlight points in swapped order
if ( annotation->subType() == Okular::Annotation::AHighlight )
{
Okular::HighlightAnnotation * hlann = static_cast<Okular::HighlightAnnotation*>( annotation );
QList<Okular::HighlightAnnotation::Quad> &quads = hlann->highlightQuads();
for (QList<Okular::HighlightAnnotation::Quad>::iterator it = quads.begin(); it != quads.end(); ++it)
{
Okular::NormalizedPoint t;
t = it->point( 3 );
it->setPoint( it->point(0), 3 );
it->setPoint( t, 0 );
t = it->point( 2 );
it->setPoint( it->point(1), 2 );
it->setPoint( t, 1 );
}
}
// TODO clone style
// TODO clone window
// TODO clone revisions

View file

@ -0,0 +1,38 @@
/***************************************************************************
* Copyright (C) 2012 by Fabio D'Urso <fabiodurso@hotmail.it> *
* *
* 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. *
***************************************************************************/
#ifndef _OKULAR_GENERATOR_PDF_ANNOTS_H_
#define _OKULAR_GENERATOR_PDF_ANNOTS_H_
#include <poppler-annotation.h>
#include <poppler-qt4.h>
#include <qmutex.h>
#include "core/annotations.h"
#include "config-okular-poppler.h"
extern Okular::Annotation* createAnnotationFromPopplerAnnotation( Poppler::Annotation *ann, bool * doDelete );
class PopplerAnnotationProxy : public Okular::AnnotationProxy
{
public:
PopplerAnnotationProxy( Poppler::Document *doc, QMutex *userMutex );
~PopplerAnnotationProxy();
bool supports( Capability capability ) const;
void notifyAddition( Okular::Annotation *annotation, int page );
void notifyModification( const Okular::Annotation *annotation, int page, bool appearanceChanged );
void notifyRemoval( Okular::Annotation *annotation, int page );
private:
Poppler::Document *ppl_doc;
QMutex *mutex;
};
#endif

View file

@ -52,6 +52,7 @@
# include <poppler-media.h>
#endif
#include "annots.h"
#include "formfields.h"
#include "popplerembeddedfile.h"
@ -61,7 +62,6 @@ Q_DECLARE_METATYPE(Poppler::FontInfo)
Q_DECLARE_METATYPE(const Poppler::LinkMovie*)
#endif
static const int PDFDebug = 4710;
static const int defaultPageWidth = 595;
static const int defaultPageHeight = 842;
@ -72,11 +72,30 @@ class PDFOptionsPage : public QWidget
{
setWindowTitle( i18n( "PDF Options" ) );
QVBoxLayout *layout = new QVBoxLayout(this);
m_printAnnots = new QCheckBox(i18n("Print annotations"), this);
m_printAnnots->setToolTip(i18n("Include annotations in the printed document"));
m_printAnnots->setWhatsThis(i18n("Includes annotations in the printed document. You can disable this if you want to print the original unannotated document."));
layout->addWidget(m_printAnnots);
m_forceRaster = new QCheckBox(i18n("Force rasterization"), this);
m_forceRaster->setToolTip(i18n("Rasterize into an image before printing"));
m_forceRaster->setWhatsThis(i18n("Forces the rasterization of each page into an image before printing it. This usually gives somewhat worse results, but is useful when printing documents that appear to print incorrectly."));
layout->addWidget(m_forceRaster);
layout->addStretch(1);
#ifndef HAVE_POPPLER_0_20
m_printAnnots->setVisible( false );
#endif
setPrintAnnots( true ); // Default value
}
bool printAnnots()
{
return m_printAnnots->isChecked();
}
void setPrintAnnots( bool printAnnots )
{
m_printAnnots->setChecked( printAnnots );
}
bool printForceRaster()
@ -90,6 +109,7 @@ class PDFOptionsPage : public QWidget
}
private:
QCheckBox *m_printAnnots;
QCheckBox *m_forceRaster;
};
@ -317,8 +337,6 @@ static QLinkedList<Okular::ObjectRect*> generateLinks( const QList<Poppler::Link
return links;
}
extern Okular::Annotation* createAnnotationFromPopplerAnnotation( Poppler::Annotation *ann, bool * doDelete );
/** NOTES on threading:
* internal: thread race prevention is done via the 'docLock' mutex. the
* mutex is needed only because we have the asynchronous thread; else
@ -364,7 +382,7 @@ PDFGenerator::PDFGenerator( QObject *parent, const QVariantList &args )
docInfoDirty( true ), docSynopsisDirty( true ),
docEmbeddedFilesDirty( true ), nextFontPage( 0 ),
dpiX( 72.0 /*Okular::Utils::dpiX()*/ ), dpiY( 72.0 /*Okular::Utils::dpiY()*/ ),
synctex_scanner(0)
annotProxy( 0 ), synctex_scanner( 0 )
{
setFeature( Threaded );
setFeature( TextExtraction );
@ -513,6 +531,9 @@ bool PDFGenerator::init(QVector<Okular::Page*> & pagesVector, const QString &wal
// update the configuration
reparseConfig();
// create annotation proxy
annotProxy = new PopplerAnnotationProxy( pdfdoc, userMutex() );
// the file has been loaded correctly
return true;
}
@ -521,6 +542,8 @@ bool PDFGenerator::doCloseDocument()
{
// remove internal objects
userMutex()->lock();
delete annotProxy;
annotProxy = 0;
delete pdfdoc;
pdfdoc = 0;
userMutex()->unlock();
@ -1026,9 +1049,11 @@ bool PDFGenerator::print( QPrinter& printer )
pstitle = document()->currentDocument().fileName();
}
bool printAnnots = true;
bool forceRasterize = false;
if ( pdfOptionsPage )
{
printAnnots = pdfOptionsPage->printAnnots();
forceRasterize = pdfOptionsPage->printForceRaster();
}
@ -1047,6 +1072,11 @@ bool PDFGenerator::print( QPrinter& printer )
psConverter->setForceRasterize(forceRasterize);
psConverter->setTitle(pstitle);
#ifdef HAVE_POPPLER_0_20
if (!printAnnots)
psConverter->setPSOptions(psConverter->psOptions() | Poppler::PSConverter::HideAnnotations );
#endif
userMutex()->lock();
if (psConverter->convert())
{
@ -1724,7 +1754,11 @@ bool PDFGenerator::supportsOption( SaveOption option ) const
switch ( option )
{
case SaveChanges:
return true;
{
QMutexLocker locker( userMutex() );
// Saving files with /Encrypt is not supported
return pdfdoc->isEncrypted() ? false : true;
}
default: ;
}
return false;
@ -1764,6 +1798,11 @@ bool PDFGenerator::save( const QString &fileName, SaveOptions options, QString *
return success;
}
Okular::AnnotationProxy* PDFGenerator::annotationProxy() const
{
return annotProxy;
}
#include "generator_pdf.moc"
/* kate: replace-tabs on; indent-width 4; */

View file

@ -32,6 +32,7 @@ class SourceReference;
}
class PDFOptionsPage;
class PopplerAnnotationProxy;
/**
* @short A generator that builds contents from a PDF document.
@ -56,6 +57,8 @@ class PDFGenerator : public Okular::Generator, public Okular::ConfigInterface, p
PDFGenerator( QObject *parent, const QVariantList &args );
virtual ~PDFGenerator();
static const int PDFDebug = 4710;
// [INHERITED] load a document and fill up the pagesVector
bool loadDocument( const QString & fileName, QVector<Okular::Page*> & pagesVector );
bool loadDocumentFromData( const QByteArray & fileData, QVector<Okular::Page*> & pagesVector );
@ -93,6 +96,7 @@ class PDFGenerator : public Okular::Generator, public Okular::ConfigInterface, p
// [INHERITED] save interface
bool supportsOption( SaveOption ) const;
bool save( const QString &fileName, SaveOptions options, QString *errorText );
Okular::AnnotationProxy* annotationProxy() const;
protected:
bool doCloseDocument();
@ -142,6 +146,7 @@ class PDFGenerator : public Okular::Generator, public Okular::ConfigInterface, p
int nextFontPage;
double dpiX;
double dpiY;
PopplerAnnotationProxy *annotProxy;
QHash<Okular::Annotation*, Poppler::Annotation*> annotationsHash;
QBitArray rectsGenerated;

View file

@ -65,11 +65,21 @@ class OKULAR_EXPORT SaveInterface
* Save to the specified @p fileName with the specified @p options.
*/
virtual bool save( const QString &fileName, SaveOptions options, QString *errorText ) = 0;
/**
* Returns the annotation proxy. Generators can return NULL if native
* annotations are not supported.
*
* @note Returning NULL is equivalent to returning an AnnotationProxy
* that doesn't support any capability.
* @since 0.15 (KDE 4.9)
*/
virtual AnnotationProxy* annotationProxy() const = 0;
};
}
Q_DECLARE_INTERFACE( Okular::SaveInterface, "org.kde.okular.SaveInterface/0.2" )
Q_DECLARE_INTERFACE( Okular::SaveInterface, "org.kde.okular.SaveInterface/0.3" )
Q_DECLARE_OPERATORS_FOR_FLAGS( Okular::SaveInterface::SaveOptions )
#endif

View file

@ -53,8 +53,11 @@ void AnnotationPopup::exec( const QPoint &point )
deleteNote->setEnabled( mDocument->isAllowed( Okular::AllowNotes ) );
const AnnotPagePair &firstAnnotPagePair = mAnnotations.at(0);
if ( onlyOne && firstAnnotPagePair.annotation->flags() & Okular::Annotation::DenyDelete )
deleteNote->setEnabled( false );
foreach ( const AnnotPagePair& pair, mAnnotations )
{
if ( !mDocument->canRemovePageAnnotation(pair.annotation) )
deleteNote->setEnabled( false );
}
showProperties = menu.addAction( KIcon( "configure" ), i18n( "&Properties" ) );
showProperties->setEnabled( onlyOne );

View file

@ -34,7 +34,7 @@ AnnotsPropertiesDialog::AnnotsPropertiesDialog( QWidget *parent, Okular::Documen
{
setFaceType( Tabbed );
m_annot=ann;
bool canEditAnnotations = !(ann->flags() & Okular::Annotation::External) && m_document->isAllowed( Okular::AllowNotes );
const bool canEditAnnotations = m_document->canModifyPageAnnotation( ann );
setCaptionTextbyAnnotType();
if ( canEditAnnotations )
{

View file

@ -190,6 +190,8 @@ AnnotWindow::AnnotWindow( QWidget * parent, Okular::Annotation * annot, Okular::
setFrameStyle( Panel | Raised );
setAttribute( Qt::WA_DeleteOnClose );
const bool canEditAnnotation = m_document->canModifyPageAnnotation( annot );
textEdit = new KTextEdit( this );
textEdit->setAcceptRichText( false );
textEdit->setPlainText( GuiUtils::contents( m_annot ) );
@ -197,6 +199,9 @@ AnnotWindow::AnnotWindow( QWidget * parent, Okular::Annotation * annot, Okular::
connect(textEdit,SIGNAL(textChanged()),
this,SLOT(slotsaveWindowText()));
if (!canEditAnnotation)
textEdit->setReadOnly(true);
m_latexRenderer = new GuiUtils::LatexRenderer();
emit containsLatex( GuiUtils::LatexRenderer::mightContainLatex( GuiUtils::contents( m_annot ) ) );
@ -276,30 +281,47 @@ void AnnotWindow::slotOptionBtn()
void AnnotWindow::slotsaveWindowText()
{
const QString newText = textEdit->toPlainText();
// 0. tell the document
m_document->modifyPageAnnotation( m_page, m_annot );
bool appearanceChanged = false;
// 1. window text
// Set window text
if ( !m_annot->window().text().isEmpty() )
{
m_annot->window().setText( newText );
return;
}
// 2. if Text and InPlace, the inplace text
if ( m_annot->subType() == Okular::Annotation::AText )
// Handle special cases
switch ( m_annot->subType() )
{
Okular::TextAnnotation * txtann = static_cast< Okular::TextAnnotation * >( m_annot );
if ( txtann->textType() == Okular::TextAnnotation::InPlace )
// If it's an in-place TextAnnotation, set the inplace text
case Okular::Annotation::AText:
{
txtann->setInplaceText( newText );
return;
Okular::TextAnnotation * txtann = static_cast< Okular::TextAnnotation * >( m_annot );
if ( txtann->textType() == Okular::TextAnnotation::InPlace )
{
txtann->setInplaceText( newText );
appearanceChanged = true;
}
break;
}
// If it's a LineAnnotation, check if caption text is visible
case Okular::Annotation::ALine:
{
Okular::LineAnnotation * lineann = static_cast< Okular::LineAnnotation * >( m_annot );
if ( lineann->showCaption() )
appearanceChanged = true;
break;
}
default:
break;
}
// 3. contents
// Set contents
m_annot->setContents( newText );
// Tell the document
m_document->modifyPageAnnotation( m_page, m_annot, appearanceChanged );
emit containsLatex( GuiUtils::LatexRenderer::mightContainLatex( newText ) );
}

View file

@ -117,6 +117,7 @@ void PagePainter::paintCroppedPageOnPainter( QPainter * destPainter, const Okula
QList< QPair<QColor, Okular::NormalizedRect> > * bufferedHighlights = 0;
QList< Okular::Annotation * > * bufferedAnnotations = 0;
QList< Okular::Annotation * > * unbufferedAnnotations = 0;
Okular::Annotation *boundingRectOnlyAnn = 0; // Paint the bounding rect of this annotation
// fill up lists with visible annotation/highlight objects/text selections
if ( canDrawHighlights || canDrawTextSelection || canDrawAnnotations )
{
@ -169,9 +170,20 @@ void PagePainter::paintCroppedPageOnPainter( QPainter * destPainter, const Okula
for ( ; aIt != aEnd; ++aIt )
{
Okular::Annotation * ann = *aIt;
if ( ann->flags() & ( Okular::Annotation::Hidden | Okular::Annotation::ExternallyDrawn ) )
int flags = ann->flags();
if ( flags & Okular::Annotation::Hidden )
continue;
if ( flags & Okular::Annotation::ExternallyDrawn )
{
// ExternallyDrawn annots are never rendered by PagePainter.
// Just paint the boundingRect if the annot is BeingMoved
if ( flags & Okular::Annotation::BeingMoved )
boundingRectOnlyAnn = ann;
continue;
}
bool intersects = ann->transformedBoundingRectangle().intersects( nXMin, nYMin, nXMax, nYMax );
if ( ann->subType() == Okular::Annotation::AText )
{
@ -703,6 +715,13 @@ void PagePainter::paintCroppedPageOnPainter( QPainter * destPainter, const Okula
}
}
if ( boundingRectOnlyAnn )
{
QRect annotBoundary = boundingRectOnlyAnn->transformedBoundingRectangle().geometry( scaledWidth, scaledHeight ).translated( -scaledCrop.topLeft() );
mixedPainter->setPen( Qt::DashLine );
mixedPainter->drawRect( annotBoundary );
}
/** 6 -- MIXED FLOW. Draw LINKS+IMAGES BORDER on ACTIVE PAINTER **/
if ( enhanceLinks || enhanceImages )
{

View file

@ -132,6 +132,7 @@ public:
bool mouseOnRect;
Okular::Annotation * mouseAnn;
QPoint mouseAnnPos;
int mouseAnnPageNum;
// table selection
QList<double> tableSelectionCols;
@ -1793,7 +1794,7 @@ void PageView::mouseMoveEvent( QMouseEvent * e )
}
d->mouseAnn->translate( Okular::NormalizedPoint( pf.x(), pf.y() ) );
d->mouseAnnPos = newpos;
d->document->modifyPageAnnotation( pageItem->pageNumber(), d->mouseAnn );
d->document->modifyPageAnnotation( d->mouseAnnPageNum, d->mouseAnn );
}
}
// drag page
@ -1965,11 +1966,17 @@ void PageView::mousePressEvent( QMouseEvent * e )
if ( d->mouseAnn && !d->mouseAnn->canBeMoved() )
d->mouseAnn = 0;
}
if ( !d->mouseAnn )
if ( d->mouseAnn )
{
d->mouseGrabPos = d->mouseOnRect ? QPoint() : d->mousePressPos;
if ( !d->mouseOnRect )
d->leftClickTimer.start( QApplication::doubleClickInterval() + 10 );
d->mouseAnn->setFlags( d->mouseAnn->flags() | Okular::Annotation::BeingMoved );
d->mouseAnnPageNum = pageItem->pageNumber();
d->document->modifyPageAnnotation( d->mouseAnnPageNum, d->mouseAnn );
}
else
{
d->mouseGrabPos = d->mouseOnRect ? QPoint() : d->mousePressPos;
if ( !d->mouseOnRect )
d->leftClickTimer.start( QApplication::doubleClickInterval() + 10 );
}
}
else if ( rightButton )
@ -2145,6 +2152,9 @@ void PageView::mouseReleaseEvent( QMouseEvent * e )
if ( d->mouseAnn )
{
// Just finished to move the annotation
d->mouseAnn->setFlags( d->mouseAnn->flags() & ~Okular::Annotation::BeingMoved );
d->document->modifyPageAnnotation( d->mouseAnnPageNum, d->mouseAnn );
setCursor( Qt::ArrowCursor );
d->mouseAnn = 0;
}