Commit 1e9f0e59 authored by Enrico Ros's avatar Enrico Ros

Another milestone has been reached: complete saving/restoring of

annotations in the 'document tie file'. Every attribute of kpdf dss
can be dumped to disk. Only rendering prevents HEAD merging now! :-)

Annotations:
  Storage: full annotations saving/loding on the tied XML is implemented.
    every annotation put on a page (either loaded from a pdf or created
    internally is loaded and saved when opening/closing a document).
    Attributes are dumped to XML and reloaded from it via qdom
  DataStructures: internal changes, better naming, some attributes fused.
    PopupAnnotation has become WindowAnnotation
  PDF16Parser: 100% completeness for the types we support

PDFGenerator:
  adapted to annotation ds changes. better parsing on a couple of attrs.
  correctly handle 'F'.

Misc:
  Document: remove/cleanup debugs, Page: performance testing stuff added,
  PagePainter: setPen( annot->color ), PageV..or: typo,
  TODO: many changes

svn path=/branches/kpdf_annotations/kdegraphics/kpdf/; revision=398789
parent a041d23e
TODO - KPdf HEAD
TODO - KPdf branch: "kpdf_annotations"
Legend:
ADD - ADDed (new feature)
CHG - CHanGed (existing behavior)
FIX - FIXed (bug or regression)
MRG - MeRGed (code from a branch or a patch)
In progress [nearly done]:
-> annotations: ask/confirm author's name for annotations (add config option)
[15:00] *eros* - implement unified LOAD/SAVE of annotations in the Document class
-> annotations: framework (BR67300,BR62793)
[14:57] *eros* - implement Annotation handlers in PageView
-> annotations: load and display pdf annotations as in pdf specification (BR93416)
-> annotations: move/dupe markup's T up to Annot (used as a classifier)
In progress [working on]:
[14:56] *eros* - implement all renderers for each annotation (~20) in PagePainter
-> annotations: tools (BR67300,BR91251), yellow notes 'post-it' like
[14:57] *eros* - implement [MISSING] Annotation creators in PageViewAnnotator
-> annotations: renderers in PagePainter (for the 6 markup annots)
-> annotations: handlers in PageView for WindowAnnots and others..
-> annotations: creators in PageViewAnnotator (80% done)
-> annotations: framework (BR67300,BR62793) and tools (BR67300,BR91251)
More items (first items will enter 'In progress list' first):
-> annotations: add the annot pane
-> annots toolbar: display tooltip only the first time
-> annotations: add config option for default name change
-> annotations: add the annot pane (cool plz!)
-> annotations: toolbar: display tooltip only the first time
-> annotations: provide nice wizards. Make it easy to deliver/copy/move the xml files (by Uga)
-> popup context menu when using right button in selection mode (BR99315)
-> pageview: add scrollbar marks for bookmarks (like kate)
-> evaluate changing KPDFLink to KPDFAction
-> evaluate completely handling links internally instead of asking xpdf structs
-> toc: add search bar (a 'prune on type' lineedit like in thumbnails widget) (BR99349)
-> bookmarks: fastmarks (new bookmark concept with tab-like signs, shortcuts, etc) (BR
-> bookmarks: go to next/previous actions (showing in thumbnailslist rmb popup too)
......@@ -33,6 +29,7 @@ More items (first items will enter 'In progress list' first):
-> core: Delay TOC (DocumentSynapsis) generation (and move it on thread)
-> core: add a way to handle "named xpdf links" in KPDFLink instead of resolving all
dests when displaying a page (speedups a lot generation of page with many links)
-> toolbar: move the toolbar to the top of pageview (left panel is really at the left of the toolbar)
-> thumbnailslist: show Viewport in(blended/contour)
-> thumbnailslist: refactor to do internal rendering as pageview does (way faster
-> thumbnailslist: clinking on higlighted rect should bring the viewport to that search result (BR98334)
......@@ -71,7 +68,7 @@ More items (first items will enter 'In progress list' first):
-> rotate the whole document / individual pages (on screen/print?) (BR99352)
-> presentation: provide a pageX/totalPages indicator in addition to the circle one
-> presentation: implement missing transitions (6/11 done)
-> presentation: add some gfx tools (like a red pencil / merge with annotations ??)
-> presentation: add a red pencil that creates ink annotations (author: i18n(presentation)))
-> presentation: save a flag (to the xml) to open a pdf in presentation mode
-> presentation: link following (now possible with uniform links) (BR98388)
-> presentation: wheel not visible on black. gradient appreciated on lighter backgrounds.
......@@ -90,8 +87,10 @@ More items (first items will enter 'In progress list' first):
-> cleanup code and update README.png
Done (newest features come first):
-> ADD: annotations: complete xml storage/retrieval of internal annotations
-> CHG: page properties (bookmarks, annotations, ...) storage moved to Page class
-> ADD: sidebar: add shortcut for showing/hiding it (BR99316)
-> ADD: PDF1.6 annotations parser (PDF's annotations -> our data structures).
-> ADD: annotations: PDF1.6 reader (PDF's annotations -> our data structures)
-> ADD: Internal data structures for annotations handling.
-> FIX: rmb when no doc displayed to restore menu
-> ADD: google-like search on thumbnails
......
This diff is collapsed.
......@@ -14,9 +14,11 @@
#include <qdatetime.h>
#include <qvaluelist.h>
#include <qfont.h>
#include <qdom.h>
#include "page.h"
class QDomNode;
class QDomDocument;
/** Annotations in PDF 1.6 specification **
KDPF tries to support ALL annotations and ALL parameters for each one. If
......@@ -180,40 +182,49 @@ Unused / Incomplete :
struct Annotation
{
// enum definitions
enum SubType { APopup, AText, ALine, AGeom, AHighlight, AStamp, AInk };
enum Flags { Hidden, NoOpenable, Print, Locked, ReadOnly };
enum SubType { AWindow, AText, ALine, AGeom, AHighlight, AStamp, AInk };
enum Flags { Hidden = 1, FixedSize = 2, FixedRotation = 4, DenyPrint = 8,
DenyWrite = 16, DenyDelete = 32, ToggleHidingOnMouse = 64 };
// struct definitions
struct Border
struct DrawStyle
{
double width;
double xCornerRadius;
double yCornerRadius;
enum { Solid, Dashed, Beveled, Inset, Underline } style;
enum S { Solid, Dashed, Beveled, Inset, Underline } style;
int dashMarks;
int dashSpaces;
enum { NoEffect, Cloudy } effect;
enum E { NoEffect, Cloudy } effect;
int effectIntensity;
// initialize default valudes
Border();
DrawStyle();
};
// data fields
// check properties
virtual SubType subType() const = 0; // for RTTI
virtual bool isMarkup() const { return false; } // for RTTI
virtual bool isApplied() const { return external; }
// data fields
NormalizedRect r;
double rUnscaledWidth;
double rUnscaledHeight;
QString author;
QString contents;
QString uniqueName;
QDateTime modifyDate;
int flags;
Border border;
DrawStyle drawStyle;
QColor color;
// special flags
bool external; // true: read from file, false: made by kpdf
// initialize default values
Annotation();
virtual ~Annotation() {};
// read values from XML node
Annotation( const QDomElement & node );
Annotation( const QDomNode & node );
// store custom config to XML node
virtual void store( QDomNode & parentNode, QDomDocument & document ) const;
};
......@@ -224,20 +235,20 @@ struct MarkupAnnotation : public Annotation
struct InReplyTo
{
int ID;
enum { Reply, Grouped } scope;
enum { Mark, Review } stateModel;
enum { Marked, Unmarked, Accepted, Rejected, Cancelled, Completed, None } state;
enum S { Reply, Grouped } scope;
enum M { Mark, Review } stateModel;
enum T { Marked, Unmarked, Accepted, Rejected, Cancelled, Completed, None } state;
// initialize default valudes
InReplyTo();
};
// data fields
bool isMarkup() const { return true; } // for RTTI
QString markupCreator;
double markupOpacity;
int markupPopupID;
QString markupPopupText;
QString markupSubject;
int markupWindowID;
QString markupWindowTitle;
QString markupWindowText;
QString markupWindowSummary;
QDateTime markupCreationDate;
InReplyTo markupReply;
......@@ -245,45 +256,44 @@ struct MarkupAnnotation : public Annotation
MarkupAnnotation();
virtual ~MarkupAnnotation() {};
// read values from XML node
MarkupAnnotation( const QDomElement & node );
MarkupAnnotation( const QDomNode & node );
// store custom config to XML node
virtual void store( QDomNode & parentNode, QDomDocument & document ) const;
};
struct PopupAnnotation : public Annotation
struct WindowAnnotation : public Annotation
{
// data fields (takes {Contents,M,C,T,..} from related parent)
int popupMarkupParentID;
bool popupOpened;
int windowMarkupParentID;
bool windowOpened;
// RTTI
SubType subType() const { return APopup; }
SubType subType() const { return AWindow; }
// common functions
PopupAnnotation();
PopupAnnotation( const QDomElement & node );
WindowAnnotation();
WindowAnnotation( const QDomNode & node );
void store( QDomNode & parentNode, QDomDocument & document ) const;
};
struct TextAnnotation : public MarkupAnnotation
{
// data fields
enum { Popup, InPlace } textType;
enum T { Linked, InPlace } textType;
QFont textFont;
bool popupOpened;
QString popupIcon;
bool textOpened;
QString textIcon;
int inplaceAlign; // 0:left, 1:center, 2:right
QString inplaceRichString;
QString inplacePlainString;
QString inplaceString; // use contents if this is empty
NormalizedPoint inplaceCallout[3];
enum { Unknown, Callout, TypeWriter } inplaceIntent;
enum I { Unknown, Callout, TypeWriter } inplaceIntent;
// RTTI
SubType subType() const { return AText; }
// common functions
TextAnnotation();
TextAnnotation( const QDomElement & node );
TextAnnotation( const QDomNode & node );
void store( QDomNode & parentNode, QDomDocument & document ) const;
};
......@@ -291,28 +301,28 @@ struct LineAnnotation : public MarkupAnnotation
{
// data fields (note uses border for rendering style)
QValueList<NormalizedPoint> linePoints;
enum { Square, Circle, Diamond, OpenArrow, ClosedArrow, None, Butt,
enum S { Square, Circle, Diamond, OpenArrow, ClosedArrow, None, Butt,
ROpenArrow, RClosedArrow, Slash } lineStartStyle, lineEndStyle;
bool lineClosed; // def:false (if true connect first and last points)
QColor lineInnerColor;
double lineLeadingFwdPt;
double lineLeadingBackPt;
bool lineShowCaption;
enum { Unknown, Arrow, Dimension, PolygonCloud } lineIntent;
enum I { Unknown, Arrow, Dimension, PolygonCloud } lineIntent;
// RTTI
SubType subType() const { return ALine; }
// common functions
LineAnnotation();
LineAnnotation( const QDomElement & node );
LineAnnotation( const QDomNode & node );
void store( QDomNode & parentNode, QDomDocument & document ) const;
};
struct GeomAnnotation : public MarkupAnnotation
{
// data fields (note uses border for rendering style)
enum { InscribedSquare, InscribedCircle } geomType;
enum T { InscribedSquare, InscribedCircle } geomType;
QColor geomInnerColor;
int geomWidthPt; //def:18
......@@ -321,14 +331,14 @@ struct GeomAnnotation : public MarkupAnnotation
// common functions
GeomAnnotation();
GeomAnnotation( const QDomElement & node );
GeomAnnotation( const QDomNode & node );
void store( QDomNode & parentNode, QDomDocument & document ) const;
};
struct HighlightAnnotation : public MarkupAnnotation
{
// data fields
enum { Highlight, Underline, Squiggly, StrikeOut } highlightType;
enum T { Highlight, Underline, Squiggly, StrikeOut } highlightType;
QValueList<NormalizedPoint[4]> highlightQuads;
// RTTI
......@@ -336,7 +346,7 @@ struct HighlightAnnotation : public MarkupAnnotation
// common functions
HighlightAnnotation();
HighlightAnnotation( const QDomElement & node );
HighlightAnnotation( const QDomNode & node );
void store( QDomNode & parentNode, QDomDocument & document ) const;
};
......@@ -350,7 +360,7 @@ struct StampAnnotation : public MarkupAnnotation
// common functions
StampAnnotation();
StampAnnotation( const QDomElement & node );
StampAnnotation( const QDomNode & node );
void store( QDomNode & parentNode, QDomDocument & document ) const;
};
......@@ -364,7 +374,7 @@ struct InkAnnotation : public MarkupAnnotation
// common functions
InkAnnotation();
InkAnnotation( const QDomElement & node );
InkAnnotation( const QDomNode & node );
void store( QDomNode & parentNode, QDomDocument & document ) const;
};
......
......@@ -505,8 +505,9 @@ void KPDFDocument::setViewport( const DocumentViewport & viewport, int excludeId
{
// if already broadcasted, don't redo it
DocumentViewport & oldViewport = *d->viewportIterator;
if ( viewport == oldViewport )
kdDebug() << "setViewport with the same viewport." << endl;
// disabled by enrico on 2005-03-18 (less debug output)
//if ( viewport == oldViewport )
// kdDebug() << "setViewport with the same viewport." << endl;
// set internal viewport taking care of history
if ( oldViewport.pageNumber == viewport.pageNumber || oldViewport.pageNumber == -1 )
......@@ -1222,7 +1223,7 @@ void KPDFDocument::loadDocumentInfo()
QDomDocument doc( "documentInfo" );
if ( !doc.setContent( &infoFile ) )
{
kdDebug() << "Could not set content" << endl;
kdDebug() << "Can't load XML pair! Check for broken xml." << endl;
infoFile.close();
return;
}
......
This diff is collapsed.
......@@ -22,6 +22,9 @@
#include "conf/settings.h"
#include "xpdf/TextOutputDev.h"
// temp includes
#include <sys/time.h>
/** class KPDFPage **/
......@@ -306,6 +309,8 @@ void KPDFPage::restoreLocalContents( const QDomNode & pageNode )
// parse annotationList child element
if ( childElement.tagName() == "annotationList" )
{
struct timeval ts, te;
gettimeofday( &ts, NULL );
// iterate over all annotations
QDomNode annotationNode = childElement.firstChild();
while( annotationNode.isElement() )
......@@ -322,8 +327,8 @@ void KPDFPage::restoreLocalContents( const QDomNode & pageNode )
int typeNumber = annotElement.attribute( "type" ).toInt();
switch ( typeNumber )
{
case Annotation::APopup:
annotation = new PopupAnnotation( annotElement );
case Annotation::AWindow:
annotation = new WindowAnnotation( annotElement );
break;
case Annotation::AText:
annotation = new TextAnnotation( annotElement );
......@@ -351,6 +356,10 @@ void KPDFPage::restoreLocalContents( const QDomNode & pageNode )
else
kdWarning() << "can't restore Annotation of type '" << typeNumber << "from XML." << endl;
}
gettimeofday( &te, NULL );
double startTime = (double)ts.tv_sec + ((double)ts.tv_usec) / 1000000.0;
double endTime = (double)te.tv_sec + ((double)te.tv_usec) / 1000000.0;
kdDebug() << "annots: XML Load time: " << (endTime-startTime)*1000.0 << "ms" << endl;
}
// parse bookmark child element
......@@ -383,23 +392,38 @@ void KPDFPage::saveLocalContents( QDomNode & parentNode, QDomDocument & document
// add annotations info if has got any
if ( !m_annotations.isEmpty() )
{
struct timeval ts, te;
gettimeofday( &ts, NULL );
// create the annotationList
QDomElement annotListElement = document.createElement( "annotationList" );
pageElement.appendChild( annotListElement );
// add every annotation to the annotationList
int addedAnnotations = 0;
QValueList< Annotation * >::iterator aIt = m_annotations.begin(), aEnd = m_annotations.end();
for ( ; aIt != aEnd; ++aIt )
{
// get annotation
const Annotation * a = *aIt;
// only save annotations created by us (not loaded from document)
if ( a->isApplied() )
continue;
// create annotation element and set type
QDomElement annotElement = document.createElement( "annotation" );
annotListElement.appendChild( annotElement );
annotElement.setAttribute( "type", (uint)a->subType() );
// add children and attributes to annotation element
a->store( annotElement, document );
addedAnnotations++;
}
// add number of children annotations as attribute
if ( addedAnnotations )
annotListElement.setAttribute( "annotations", addedAnnotations );
gettimeofday( &te, NULL );
double startTime = (double)ts.tv_sec + ((double)ts.tv_usec) / 1000000.0;
double endTime = (double)te.tv_sec + ((double)te.tv_usec) / 1000000.0;
kdDebug() << "annots: XML Save Time: " << (endTime-startTime)*1000.0 << "ms" << endl;
}
}
}
......
......@@ -234,7 +234,10 @@ void PagePainter::paintPageOnPainter( const KPDFPage * page, int id, int flags,
QRect annotRect = a->r.geometry( width, height );
// draw the annotation extent
if ( annotRect.isValid() && annotRect.intersects( limits ) )
{
p->setPen( a->color );
p->drawRect( annotRect );
}
}
}
......
......@@ -520,7 +520,7 @@ void PageViewAnnotator::slotToolSelected( int toolID )
{
LineAnnotation * l = new LineAnnotation();
if ( a.hasAttribute( "width" ) )
l->border.width = a.attribute( "width" ).toInt();
l->drawStyle.width = a.attribute( "width" ).toInt();
annotation = l;
}
else if ( aType == "Geom" )
......@@ -541,6 +541,7 @@ void PageViewAnnotator::slotToolSelected( int toolID )
// parse generic annotation attributes
if ( annotation )
{
annotation->author = Settings::annotationsAuthor();
if ( a.hasAttribute( "color" ) )
annotation->color = QColor( a.attribute( "color" ) );
}
......
......@@ -27,7 +27,7 @@ class AnnotatorEngine;
* annotation will become when finished.
*
* "data/tools.xml" is the file that contains Annotations/Engine association
* for the items placed in the toolbar. The XML is parsed (1) when popuplating
* for the items placed in the toolbar. The XML is parsed (1) when populating
* the toolbar and (2)after selecting a toolbar item, in which case an Ann is
* initialized with the values in the XML and an engine is created to handle
* that annotation.
......
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