Added AnnotationProxy to SaveInterface

Based on Pino Toscano's earlier work
remotes/origin/KDE/4.9
Fabio D'Urso 14 years ago committed by Albert Astals Cid
parent 07c57bb2ab
commit ec9f068d77
  1. 3
      core/annotations.cpp
  2. 53
      core/annotations.h
  3. 101
      core/document.cpp
  4. 21
      core/document.h
  5. 3
      core/page.cpp
  6. 5
      generators/poppler/generator_pdf.cpp
  7. 1
      generators/poppler/generator_pdf.h
  8. 12
      interfaces/saveinterface.h
  9. 39
      ui/annotwindow.cpp

@ -100,6 +100,9 @@ QRect AnnotationUtils::annotationGeometry( const Annotation * ann,
}
//END AnnotationUtils implementation
AnnotationProxy::~AnnotationProxy()
{
}
//BEGIN Annotation implementation

@ -655,6 +655,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:

@ -2331,6 +2331,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,41 +2346,110 @@ 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 );
}
}
void Document::modifyPageAnnotation( int page, Annotation * newannotation )
void Document::modifyPageAnnotation( int page, Annotation * annotation )
{
//TODO: modify annotations
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;
// 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) )
{
// Redraw everything, including ExternallyDrawn annotations
d->refreshPixmaps( page );
}
}
bool Document::canRemovePageAnnotation( const Annotation * annotation ) const
{
if ( !annotation || ( annotation->flags() & Annotation::DenyDelete ) )
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 );
}
}
}
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 )
@ -2386,9 +2458,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;
}
}
@ -2396,6 +2481,12 @@ 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 );
}
}
}

@ -369,9 +369,30 @@ class OKULAR_EXPORT Document : public QObject
/**
* 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.
*/

@ -26,6 +26,7 @@
#include "annotations_p.h"
#include "area.h"
#include "debug_p.h"
#include "document_p.h"
#include "form.h"
#include "form_p.h"
#include "pagecontroller_p.h"
@ -598,7 +599,7 @@ void Page::addAnnotation( Annotation * annotation )
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();

@ -1764,6 +1764,11 @@ bool PDFGenerator::save( const QString &fileName, SaveOptions options, QString *
return success;
}
Okular::AnnotationProxy* PDFGenerator::annotationProxy() const
{
return 0; // Not supported
}
#include "generator_pdf.moc"
/* kate: replace-tabs on; indent-width 4; */

@ -93,6 +93,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();

@ -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

@ -276,30 +276,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:
{
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:
{
txtann->setInplaceText( newText );
return;
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 ) );
}

Loading…
Cancel
Save