Commit fbc7d450 authored by Enrico Ros's avatar Enrico Ros

Adding support for annotations in framework. Only need to add and

implement annotations now (and create the save/load procedure).

Annotations: converging to a stable Annotation definition. Changed a bit
  the paint functions. Added a first 'template' annotation, a simple
  pen-like segments recorder for framework testing purposes only. This
  has events filters in place and the rough paint function implemented.

PageView: removed the MouseEdit mode and using that button for toggling
  the editToolBox instead. Added Annotation support. When the Annotation
  is created, all pageView events flow through that new object. Repaint
  of damaged/old areas is done internally and is based on the geometry
  of the annotation we're creating. When an Annotation is complete, it
  is reparented to the Page that adds it to its internal list.
  From that point on the annotation will be rendered by pagePainter
  using the pixmap-based paint function provided by the annotation
  itself.

PagePainter: draws annotations stored in pages when rendering (using the
  'rought paint function' till the good pixmap based one will be in
  place.

Page: added preliminary support for adding Annotation(s) to the page
  and deleting them all.

Document: added the pass-through call to add an Annotation to the Page
  and notify observers.

PageViewToolbox: can be draged and attached to any side. Position is
  remembered between runs (choose your side and that the toolbox will
  always be there). Available on Right and Bottom sides too. Emits -1
  when the current tool is deselected.

Misc: added Annotations to both the 'observers changed flags' and the
  'pagepainter' ones and updated ui classes accordingly.

svn path=/branches/kpdf_annotations/kdegraphics/kpdf/; revision=390638
parent 451a3091
......@@ -62,6 +62,9 @@
<default>true</default>
</entry>
<entry key="SplitterSizes" type="IntList" />
<entry key="EditToolboxPlacement" type="Int" >
<default>0</default>
</entry>
</group>
<group name="PageView" >
<entry key="ShowScrollBars" type="Bool" >
......
......@@ -12,12 +12,16 @@
#include <qpainter.h>
#include <qpixmap.h>
#include <qimage.h>
#include <klocale.h>
// system includes
#include <math.h>
// local includes
#include "annotations.h"
Annotation::Annotation()
: NormalizedRect()
: NormalizedRect(), m_state( NewBorn )
{
}
......@@ -31,3 +35,91 @@ void mouseReleaseEvent( double x, double y, Qt::ButtonState b );
void overlayPaint( QPainter * painter );
void finalPaint( QPixmap * pixmap, MouseState mouseState );
*/
HighlightAnnotation::HighlightAnnotation( Type type )
: Annotation(), m_type( type )
{
}
QString HighlightAnnotation::usageTip() const
{
return i18n( "Press and drag the mouse to highlight words." );
}
bool HighlightAnnotation::mouseEvent( MouseEvent e, double x, double y, Qt::ButtonState b )
{
// only process events if left button pressed
if ( b != Qt::LeftButton )
return false;
// start operation
if ( e == MousePress && m_state == NewBorn )
{
FloatPoint newPoint;
left = right = newPoint.x = x;
top = bottom = newPoint.y = y;
m_points.append( newPoint );
m_state = Creating;
return false;
}
// add a point to the path, TODO inline redundancy suppression
else if ( e == MouseMove && m_state == Creating )
{
double dist = hypot( x - m_points.last().x, y - m_points.last().y );
if ( dist < 0.02 )
return false;
left = QMIN( left, x );
top = QMIN( y, top );
right = QMAX( x, right );
bottom = QMAX( y, bottom );
FloatPoint newPoint;
newPoint.x = x;
newPoint.y = y;
m_points.append( newPoint );
return true;
}
// terminate precess
else if ( e == MouseRelease && m_state == Creating )
{
if ( m_points.count() > 2 )
m_state = Opened;
else
m_state = NewBorn;
return false;
}
// nothing change -> don't update gfx
return false;
}
void HighlightAnnotation::paintOverlay( QPainter * painter, int xScale, int yScale, const QRect & limits )
{
// draw annotations whith at least 2 points
if ( m_points.count() < 2 )
return;
// use basecolor
painter->setPen( QPen(m_baseColor, 3) );
// perform a rought paint drawing meanline only
//const QRect myRect = geometry( xScale, yScale );
QValueList<FloatPoint>::iterator pIt = m_points.begin(), pEnd = m_points.end();
FloatPoint pA = *pIt;
++pIt;
for ( ; pIt != pEnd; ++pIt )
{
FloatPoint pB = *pIt;
// painter->setPen( QPen(Qt::black, 2) );
// painter->drawLine( (int)(pA.x * (double)xScale)+1, (int)(pA.y * (double)yScale)+1,
// (int)(pB.x * (double)xScale)+1, (int)(pB.y * (double)yScale)+1 );
painter->drawLine( (int)(pA.x * (double)xScale), (int)(pA.y * (double)yScale),
(int)(pB.x * (double)xScale), (int)(pB.y * (double)yScale) );
pA = pB;
}
}
void HighlightAnnotation::paintFinal( QImage & /*backImage*/, int /*xScale*/, int /*yScale*/, const QRect & /*limits*/ )
{
// use m_type for painting
}
......@@ -12,6 +12,8 @@
#include <qstring.h>
#include <qdatetime.h>
#include <qpoint.h>
#include <qvaluelist.h>
#include "page.h"
/**
......@@ -31,10 +33,22 @@ class Annotation : public NormalizedRect
Annotation();
virtual ~Annotation();
enum State { Creating, Modifying, Closed, Opened };
enum MouseState { Normal, Hovered, Pressed };
enum State { NewBorn, Creating, Modifying, Closed, Opened };
enum MouseEvent { MousePress, MouseMove, MouseRelease };
//enum MouseState { Normal, Hovered, Pressed };
enum Flags { Hidden, NoOpenable, Print, Locked, ReadOnly };
// provide some i18n strings
virtual QString usageTip() const = 0;
// event handlers (must update state)
virtual bool mouseEvent( MouseEvent e, double x, double y, Qt::ButtonState b ) = 0;
// paint roughtly over a cleared area
virtual void paintOverlay( QPainter * painter, int xScale, int yScale, const QRect & limits ) = 0;
// cool-paint over a pixmap
virtual void paintFinal( QImage & backImage, int xScale, int yScale, const QRect & limits ) = 0;
State state() const { return m_state; }
const QString & text() const { return m_text; }
const QString & uniqueName() const { return m_uniqueName; }
......@@ -42,19 +56,11 @@ class Annotation : public NormalizedRect
const QDateTime & modifyDate() const { return m_modifyDate; }
const QColor & baseColor() const { return m_baseColor; }
// event handlers (must update state)
virtual void mousePressEvent( double x, double y, Qt::ButtonState b ) = 0;
virtual void mouseMoveEvent( double x, double y, Qt::ButtonState b ) = 0;
virtual void mouseReleaseEvent( double x, double y, Qt::ButtonState b ) = 0;
// paint roughtly over a cleared area
virtual void overlayPaint( QPainter * painter ) = 0;
// cool-paint over a pixmap
virtual void finalPaint( QPixmap * pixmap, MouseState mouseState ) = 0;
void setBaseColor( const QColor & color ) { m_baseColor = color; }
protected:
State m_state;
MouseState m_mouseState;
//MouseState m_mouseState;
QString m_text;
QString m_uniqueName;
QDateTime m_modifyDate;
......@@ -66,6 +72,7 @@ class Annotation : public NormalizedRect
class TextAnnotation : public Annotation
{
//Text (post-it like)
//FreeText (direct on page)
enum Type { InPlace, Popup };
......@@ -87,10 +94,26 @@ class PathAnnotation : public Annotation
//Polygon, PolyLine
};
struct FloatPoint
{
double x, y;
};
class HighlightAnnotation : public Annotation
{
//Highlight, Underline, Squiggly, StrikeOut, BLOCK
enum BrushHor { Horizontal, Vertical };
public:
enum Type { Highlight, Underline, Squiggly, StrikeOut, BLOCK };
HighlightAnnotation( Type type );
// [Annotation] inherited methods
QString usageTip() const;
bool mouseEvent( MouseEvent e, double x, double y, Qt::ButtonState b );
void paintOverlay( QPainter * painter, int xScale, int yScale, const QRect & limits );
void paintFinal( QImage & backImage, int xScale, int yScale, const QRect & limits );
private:
Type m_type;
QValueList<FloatPoint> m_points;
};
class StampAnnotation : public Annotation
......
......@@ -460,6 +460,20 @@ void KPDFDocument::requestTextPage( uint page )
generator->generateSyncTextPage( kp );
}
void KPDFDocument::addPageAnnotation( int page, Annotation * annotation )
{
// find out the page to attach annotation
KPDFPage * kp = pages_vector[ page ];
if ( !generator || !kp )
return;
// add annotation to the page
kp->addAnnotation( annotation );
// notify observers about the change
foreachObserver( notifyPageChanged( page, DocumentObserver::Annotations ) );
}
/* REFERENCE IMPLEMENTATION: better calling setViewport from other code
void KPDFDocument::setNextPage()
{
......
......@@ -24,6 +24,7 @@ class DocumentInfo;
class DocumentSynopsis;
class Generator;
class PixmapRequest;
class Annotation;
class KPrinter;
class KURL;
......@@ -80,6 +81,7 @@ class KPDFDocument : public QObject
void setNextViewport();
void requestPixmaps( const QValueList< PixmapRequest * > & requests );
void requestTextPage( uint page );
void addPageAnnotation( int page, Annotation * annotation );
enum SearchType { NextMatch, PrevMatch, AllDoc, GoogleLike };
bool searchText( int searchID, const QString & text, bool fromStart, bool caseSensitive,
......
......@@ -44,7 +44,7 @@ class DocumentObserver
virtual uint observerId() const = 0;
// commands from the Document to all observers
enum ChangedFlags { Pixmap = 1, Bookmark = 2, Highlights = 4 };
enum ChangedFlags { Pixmap = 1, Bookmark = 2, Highlights = 4, Annotations = 8 };
virtual void notifySetup( const QValueVector< KPDFPage * > & /*pages*/, bool /*documentChanged*/ ) {};
virtual void notifyViewportChanged( bool /*smoothMove*/ ) {};
virtual void notifyPageChanged( int /*pageNumber*/, int /*changedFlags*/ ) {};
......
......@@ -17,6 +17,7 @@
#include "page.h"
#include "pagetransition.h"
#include "link.h"
#include "annotations.h"
#include "conf/settings.h"
#include "xpdf/TextOutputDev.h"
......@@ -44,6 +45,7 @@ KPDFPage::~KPDFPage()
{
deletePixmapsAndRects();
deleteHighlights();
deleteAnnotations();
delete m_text;
delete m_transition;
}
......@@ -231,6 +233,11 @@ void KPDFPage::setHighlight( int s_id, NormalizedRect * &rect, const QColor & co
rect = hr;
}
void KPDFPage::addAnnotation( Annotation * annotation )
{
m_annotations.append( annotation );
}
void KPDFPage::setTransition( KPDFPageTransition * transition )
{
delete m_transition;
......@@ -277,6 +284,15 @@ void KPDFPage::deleteHighlights( int s_id )
}
}
void KPDFPage::deleteAnnotations()
{
// delete all stored annotations
QValueList< Annotation * >::iterator aIt = m_annotations.begin(), aEnd = m_annotations.end();
for ( ; aIt != aEnd; ++aIt )
delete *aIt;
m_annotations.clear();
}
/** class NormalizedRect **/
......
......@@ -66,11 +66,12 @@ class KPDFPage
void setBookmark( bool state );
void setObjectRects( const QValueList< ObjectRect * > rects );
void setHighlight( int s_id, NormalizedRect * &r, const QColor & color );
//void setAnnotation( Annotation * annotation );
void addAnnotation( Annotation * annotation );
void setTransition( KPDFPageTransition * transition );
void deletePixmap( int p_id );
void deletePixmapsAndRects();
void deleteHighlights( int s_id = -1 );
void deleteAnnotations();
private:
friend class PagePainter;
......@@ -82,7 +83,7 @@ class KPDFPage
TextPage * m_text;
QValueList< ObjectRect * > m_rects;
QValueList< HighlightRect * > m_highlights;
//QValueList< Annotation * > m_annotations;
QValueList< Annotation * > m_annotations;
KPDFPageTransition * m_transition;
};
......
<!DOCTYPE kpartgui SYSTEM "kpartgui.dtd">
<kpartgui name="kpdf_part" version="17">
<kpartgui name="kpdf_part" version="18">
<MenuBar>
<Menu name="file"><text>&amp;File</text>
<Action name="save" group="file_save"/>
......@@ -38,6 +38,8 @@
<Action name="mouse_drag"/>
<Action name="mouse_zoom"/>
<Action name="mouse_select"/>
<Separator/>
<Action name="mouse_toggle_annotate"/>
</Menu>
<Menu name="settings"><text>&amp;Settings</text>
<Action name="watch_file" group="show_merge"/>
......@@ -61,6 +63,5 @@
<Action name="mouse_drag"/>
<Action name="mouse_zoom"/>
<Action name="mouse_select"/>
<Action name="mouse_edit"/>
</ToolBar>
</kpartgui>
icons_DATA = highlight_green.png highlight_orange.png highlight_pink.png \
highlight_yellow.png pencil.png pinnote.png
highlight_yellow.png pencil.png pinnote.png coprex-white.png
iconsdir = $(kde_datadir)/kpdf/pics
......@@ -18,6 +18,7 @@
// local includes
#include "pagepainter.h"
#include "core/page.h"
#include "core/annotations.h"
#include "conf/settings.h"
void PagePainter::paintPageOnPainter( const KPDFPage * page, int id, int flags,
......@@ -67,6 +68,7 @@ void PagePainter::paintPageOnPainter( const KPDFPage * page, int id, int flags,
// find out what to paint over the pixmap (manipulations / overlays)
bool paintAccessibility = (flags & Accessibility) && Settings::changeColors() && (Settings::renderMode() != Settings::EnumRenderMode::Paper);
bool paintHighlights = (flags & Highlights) && !page->m_highlights.isEmpty();
bool paintAnnotations = (flags & Annotations) && !page->m_annotations.isEmpty();
bool enhanceLinks = (flags & EnhanceLinks) && Settings::highlightLinks();
bool enhanceImages = (flags & EnhanceImages) && Settings::highlightImages();
// check if there are really some highlightRects to paint
......@@ -89,9 +91,14 @@ void PagePainter::paintPageOnPainter( const KPDFPage * page, int id, int flags,
}
}
}
// check if there are really some annotations to paint
if ( paintAnnotations )
{
// TODO
}
// use backBuffer if 'pixmap direct manipulation' is needed
bool backBuffer = paintAccessibility || paintHighlights;
bool backBuffer = paintAccessibility || paintHighlights || paintAnnotations;
QPixmap * backPixmap = 0;
QPainter * p = destPainter;
if ( backBuffer )
......@@ -197,6 +204,25 @@ void PagePainter::paintPageOnPainter( const KPDFPage * page, int id, int flags,
backPixmap->convertFromImage( backImage );
}
// 2.3. annotations OVERLAY FIXME MOD in page
if ( paintAnnotations )
{
// draw annotations that are inside the 'limits' paint region
QValueList< Annotation * >::const_iterator aIt = page->m_annotations.begin(), aEnd = page->m_annotations.end();
for ( ; aIt != aEnd; ++aIt )
{
Annotation * a = *aIt;
QRect annotRect = a->geometry( width, height );
if ( annotRect.isValid() && annotRect.intersects( limits ) )
{
// find out the annotation rect on pixmap
annotRect = annotRect.intersect( limits );
a->paintOverlay( p, width, height, limits );
}
}
}
// 3. visually enchance links and images if requested
if ( enhanceLinks || enhanceImages )
{
......
......@@ -23,7 +23,8 @@ class PagePainter
// list of flags passed to the painting function. by OR-ing those flags
// you can decide wether or not to permit drawing of a certain feature.
enum PagePainterFlags { Accessibility = 1, EnhanceLinks = 2,
EnhanceImages = 4, Highlights = 8 };
EnhanceImages = 4, Highlights = 8,
Annotations = 16 };
// draw (using painter 'p') the 'page' requested by 'id' using features
// in 'flags'. 'limits' is the bounding rect of the paint operation,
......
This diff is collapsed.
......@@ -46,7 +46,7 @@ class PageView : public QScrollView, public DocumentObserver
// Zoom mode ( last 4 are internally used only! )
enum ZoomMode { ZoomFixed, ZoomFitWidth, ZoomFitPage, ZoomFitText,
ZoomIn, ZoomOut, ZoomRefreshCurrent };
enum MouseMode { MouseNormal, MouseZoom, MouseSelect, MouseEdit };
enum MouseMode { MouseNormal, MouseZoom, MouseSelect };
// create actions that interact with this widget
void setupActions( KActionCollection * collection );
......@@ -94,6 +94,9 @@ class PageView : public QScrollView, public DocumentObserver
void selectionStart( int x, int y, const QColor & color, bool aboveAll = false );
void selectionEndPoint( int x, int y );
void selectionClear();
// annotation related stuff
void updateAnnotation( QMouseEvent * e );
void deleteAnnotation();
// update internal zoom values and end in a slotRelayoutPages();
void updateZoom( ZoomMode newZm );
// update the text on the label using global zoom value or current page's one
......@@ -114,7 +117,9 @@ class PageView : public QScrollView, public DocumentObserver
// activated by the autoscroll timer (Shift+Up/Down keys)
void slotAutoScoll();
// type-ahead find timeout
void findAheadStop();
void slotStopFindAhead();
// activated when a tool is selected in the edit toolbar
void slotSetAnnotationTool( int toolID );
// connected to local actions (toolbar, menu, ..)
void slotZoom();
......@@ -128,7 +133,7 @@ class PageView : public QScrollView, public DocumentObserver
void slotSetMouseNormal();
void slotSetMouseZoom();
void slotSetMouseSelect();
void slotSetMouseDraw();
void slotToggleEditTools( bool );
void slotScrollUp();
void slotScrollDown();
};
......
This diff is collapsed.
......@@ -22,26 +22,43 @@ class PageViewToolbox : public QWidget
{
Q_OBJECT
public:
PageViewToolbox( QWidget * parent, QWidget * anchorWidget, bool isVertical );
enum Side { Left = 0, Top = 1, Right = 2, Bottom = 3 };
PageViewToolbox( QWidget * parent, QWidget * anchorWidget );
void setItems( const QValueList<ToolboxItem> & items );
void show();
// animate widget displaying with given contents
void showItems( Side side, const QValueList<ToolboxItem> & items );
// animate widget hiding and destroy itself
void hideAndDestroy();
// call this function to reposition the widget
void anchorChanged();
void paintEvent( QPaintEvent * );
void timerEvent( QTimerEvent * );
signals:
// the tool 'toolID' has been selected
void toolSelected( int toolID );
protected:
// handle widget events { paint, animation, dragging }
void mousePressEvent( QMouseEvent * e );
void mouseMoveEvent( QMouseEvent * e );
void mouseReleaseEvent( QMouseEvent * e );
void paintEvent( QPaintEvent * );
void timerEvent( QTimerEvent * );
// used by subclasses to save configuration
virtual void orientationChanged( Side /*side*/ ) {};
private:
QPoint getStartPoint();
QPoint getEndPoint();
// show widget full-sized in its place
void showFinal();
// build widget contents
void buildGfx();
// get the ending point of transition
QPoint getEndPoint();
// get the place from which transition starts
QPoint getStartPoint();
// private variables
QWidget * m_anchor;
bool m_vertical;
Side m_side;
QPoint m_currentPosition;
QPoint m_endPosition;
int m_timerID;
......@@ -50,16 +67,10 @@ class PageViewToolbox : public QWidget
QValueList< ToolboxButton * > m_buttons;
private slots:
// send 'toolSelected' signal when a button is pressed
void slotButtonClicked();
};
class PageViewEditTools : public PageViewToolbox
{
public:
PageViewEditTools( QWidget * parent, QWidget * anchorWidget );
};
struct ToolboxItem
{
int id;
......@@ -71,4 +82,14 @@ struct ToolboxItem
: id( _id ), text( _text ), pixmap( _pixmap ) {};
};
class PageViewEditTools : public PageViewToolbox
{
public:
// constructs a toolbox filled up with edit tools
PageViewEditTools( QWidget * parent, QWidget * anchorWidget );
// hook call to save widget placement
void orientationChanged( Side side );
};
#endif
......@@ -111,6 +111,9 @@ void PageViewMessage::display( const QString & message, Icon icon, int durationM
{
switch ( icon )
{
case Annotation:
symbol = SmallIcon( "pencil" );
break;
case Find:
symbol = SmallIcon( "viewmag" );
break;
......
......@@ -58,7 +58,7 @@ class PageViewMessage : public QWidget
public:
PageViewMessage( QWidget * parent );
enum Icon { None, Info, Warning, Error, Find };
enum Icon { None, Info, Warning, Error, Find, Annotation };
void display( const QString & message, Icon icon = Info, int durationMs = 4000 );
protected:
......
......@@ -508,7 +508,8 @@ void ThumbnailWidget::paintEvent( QPaintEvent * e )
clipRect = clipRect.intersect( QRect( 0, 0, m_pixmapWidth, m_pixmapHeight ) );
if ( clipRect.isValid() )
{
int flags = PagePainter::Accessibility | PagePainter::Highlights;
int flags = PagePainter::Accessibility | PagePainter::Highlights |
PagePainter::Annotations;
PagePainter::paintPageOnPainter( m_page, THUMBNAILS_ID, flags, &p,
clipRect, m_pixmapWidth, m_pixmapHeight );
}
......
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