Free TextAnnotation,pop-up window and annotation properties dialog added.

svn path=/trunk/playground/graphics/okular/; revision=571124
This commit is contained in:
Chu Xiaodong 2006-08-08 15:31:13 +00:00
parent fb6409e8fd
commit 3f81e3788f
10 changed files with 337 additions and 165 deletions

View file

@ -70,6 +70,8 @@ install(TARGETS okularcore DESTINATION ${LIB_INSTALL_DIR} )
set(okularpart_SRCS
part.cpp
ui/embeddedfilesdialog.cpp
ui/embeddedannotationdialog.cpp
ui/annotationpropertiesdialog.cpp
ui/minibar.cpp
ui/newstuff.cpp
ui/pagepainter.cpp

View file

@ -724,6 +724,26 @@ void KPDFDocument::addPageAnnotation( int page, Annotation * annotation )
// notify observers about the change
foreachObserver( notifyPageChanged( page, DocumentObserver::Annotations ) );
}
void KPDFDocument::modifyPageAnnotation( int page, QString * annuniqueName,Annotation * newannotation )
{
//TODO: modify or add/delete annotations
if(newannotation==0 && annuniqueName==0)
return; //FIXME
if(newannotation==0)
{
;//delete
}
else if(annuniqueName==0)
{
;//add annotation
}
else //modify
{
;
}
}
/* REFERENCE IMPLEMENTATION: better calling setViewport from other code
void KPDFDocument::setNextPage()
{

View file

@ -128,6 +128,7 @@ class OKULAR_EXPORT KPDFDocument : public QObject
void requestPixmaps( const QLinkedList< PixmapRequest * > & requests );
void requestTextPage( uint page );
void addPageAnnotation( int page, Annotation * annotation );
void modifyPageAnnotation( int page, QString * annuniqueName,Annotation * newannotation );
enum SearchType { NextMatch, PrevMatch, AllDoc, GoogleAll, GoogleAny };
bool searchText( int searchID, const QString & text, bool fromStart, bool caseSensitive,

View file

@ -100,6 +100,7 @@ class OKULAR_EXPORT KPDFPage
private:
friend class PagePainter;
friend class PageViewAnnotator;
int m_number;
int m_orientation;
double m_width, m_height;

View file

@ -17,45 +17,53 @@ Engine/Annotation Types [specific attributes]:
Geom
-->
<annotatingTools>
<tool id="1" name="Green Highlighter" pixmap="tool_ink_green">
<tooltip>.. is ..</tooltip>
<engine type="SmoothLine" color="#00FF00">
<annotation type="Ink" color="#00FF00" width="2" />
</engine>
<shortcut>1</shortcut>
</tool>
<tool id="2" name="Pink Highlighter" pixmap="tool_hl_pink">
<tooltip>.. is ..</tooltip>
<engine type="SmoothLine" color="#FF0080">
<annotation type="Ink" color="#FF0080" width="4" />
</engine>
<shortcut>2</shortcut>
</tool>
<tool id="3" name="Yellow Highlighter" pixmap="tool_hl_yellow">
<tooltip>this ..</tooltip>
<engine type="SmoothLine" color="#FFFF00">
<annotation type="Highlight" color="#FFFF00" />
</engine>
<shortcut>3</shortcut>
</tool>
<tool id="4" name="note" pixmap="pinnote">
<tooltip>.. tooltip ..</tooltip>
<engine type="PickPoint" color="#FF00FF" hoverIcon="tool_note">
<annotation type="Text" color="#FF00FF" />
</engine>
<shortcut>4</shortcut>
</tool>
<tool id="5" name="Straight Yellow Line" pixmap="tool_hl_yellow">
<tooltip>.. test</tooltip>
<engine type="TwoPoints" color="#FFE000">
<annotation type="Line" width="4" color="#FFE000" />
</engine>
<shortcut>5</shortcut>
</tool>
<tool id="6" name="Warning Stamp" pixmap="messagebox_warning">
<engine type="PickPoint" hoverIcon="messagebox_warning">
<annotation type="Stamp" icon="messagebox_warning" />
</engine>
<shortcut>7</shortcut>
<tool id="1" name="Note" pixmap="tool_note">
<tooltip>Text Annotation</tooltip>
<engine type="PickPoint" color="#FFFF00" hoverIcon="tool_note">
<annotation type="Text" color="#FFFF00" />
</engine>
<shortcut>1</shortcut>
</tool>
<tool id="2" name="FreeText" pixmap="pinnote">
<tooltip>Free Text Annotation</tooltip>
<engine type="PickPoint" color="#FFFF00" hoverIcon="tool_note">
<annotation type="FreeText" color="#FFFF00" />
</engine>
<shortcut>2</shortcut>
</tool>
<tool id="3" name="Green Highlighter" pixmap="tool_ink_green">
<tooltip>Green Ink</tooltip>
<engine type="SmoothLine" color="#00FF00">
<annotation type="Ink" color="#00FF00" width="2" />
</engine>
<shortcut>3</shortcut>
</tool>
<tool id="4" name="Pink Highlighter" pixmap="tool_hl_pink">
<tooltip>Pink Ink</tooltip>
<engine type="SmoothLine" color="#FF0080">
<annotation type="Ink" color="#FF0080" width="4" />
</engine>
<shortcut>4</shortcut>
</tool>
<tool id="5" name="Yellow Highlighter" pixmap="tool_hl_yellow">
<tooltip>Yellow Highlight</tooltip>
<engine type="SmoothLine" color="#FFFF00">
<annotation type="Highlight" color="#FFFF00" />
</engine>
<shortcut>5</shortcut>
</tool>
<tool id="6" name="Straight Yellow Line" pixmap="tool_hl_yellow">
<tooltip>Straight Yellow Line</tooltip>
<engine type="TwoPoints" color="#FFE000">
<annotation type="Line" width="4" color="#FFE000" />
</engine>
<shortcut>6</shortcut>
</tool>
<tool id="7" name="Warning Stamp" pixmap="messagebox_warning">
<tooltip>Warning Stamp</tooltip>
<engine type="PickPoint" hoverIcon="messagebox_warning">
<annotation type="Stamp" icon="messagebox_warning" />
</engine>
<shortcut>7</shortcut>
</tool>
</annotatingTools>

View file

@ -440,43 +440,49 @@ void PagePainter::paintPageOnPainter( QPainter * destPainter, const KPDFPage * p
{
TextAnnotation * text = (TextAnnotation *)a;
if ( text->textType == TextAnnotation::InPlace )
{
int ny=annotRect.top();
int nx=annotRect.left();
QString title="Author:";
QString note=text->inplaceText;
title+=text->author;
int nwidth=10+qMax(title.length(),note.length())*7;
int nheight=40;//annotBoundary.height();
QBrush br(QColor::fromRgb(255,255,0));
mixedPainter->setBrush(br);
mixedPainter->setPen(QColor::fromRgb(0,0,0));
if(annotBoundary.width()<25)
mixedPainter->drawRoundRect(annotBoundary);
else
{
mixedPainter->drawRoundRect(nx,ny,nwidth,nheight);
mixedPainter->drawText(nx+5,ny+10,title);
mixedPainter->drawText(nx+5,ny+25,text->inplaceText);
}
// mixedPainter->setBrush(br);
continue;
}
if(text->textType != TextAnnotation::Linked)
continue;
{
//Have the square of fixed size and adapting text font
QFontMetricsF mf(text->textFont);
QRectF rcf=mf.boundingRect(text->inplaceText);
QSize sz(int(rcf.width()+5), int(rcf.height()+5));
QPixmap pixmap(sz);
pixmap.fill( a->style.color );
QPainter painter;
painter.begin( &pixmap );
painter.setPen( Qt::black );//( NoPen );
//painter.setBrush( bule);
painter.drawRect( 0, 0, sz.width()-1, sz.height()-1 );
painter.drawText(2,sz.height()-3,text->inplaceText);
//kDebug()<<"astario: w,h="<<sz.width()<<", "<<sz.height()<<endl;
painter.end();
QImage scaledImage;
scalePixmapOnImage( scaledImage, &pixmap,
annotBoundary.width(),
annotBoundary.height(), innerRect );
//colorizeImage( scaledImage, a->style.color, opacity );
//scaledImage.setAlphaBuffer( true );
pixmap = QPixmap::fromImage( scaledImage );
mixedPainter->drawPixmap( annotRect.topLeft(), pixmap );
}
if ( text->textType == TextAnnotation::Linked )
{
// get pixmap, colorize and alpha-blend it
QPixmap pixmap = DesktopIcon( text->textIcon );
QImage scaledImage;
scalePixmapOnImage( scaledImage, &pixmap, annotBoundary.width(),
annotBoundary.height(), innerRect );
colorizeImage( scaledImage, a->style.color, opacity );
scaledImage.setAlphaBuffer( true );
pixmap = QPixmap::fromImage( scaledImage );
QPixmap pixmap = DesktopIcon( text->textIcon );
QImage scaledImage;
scalePixmapOnImage( scaledImage, &pixmap,
annotBoundary.width(),
annotBoundary.height(), innerRect );
colorizeImage( scaledImage, a->style.color, opacity );
scaledImage.setAlphaBuffer( true );
pixmap = QPixmap::fromImage( scaledImage );
// draw the mangled image to painter
mixedPainter->drawPixmap( annotRect.topLeft(), pixmap );
mixedPainter->drawPixmap( annotRect.topLeft(), pixmap );
}
}
// draw StampAnnotation
else if ( type == Annotation::AStamp )

View file

@ -55,6 +55,8 @@
#include "pageview.h"
#include "pageviewutils.h"
#include "pagepainter.h"
#include "core/annotations.h"
#include "embeddedannotationdialog.h"
#include "pageviewannotator.h"
#include "core/document.h"
#include "core/page.h"
@ -111,6 +113,8 @@ public:
QTimer * autoScrollTimer;
// annotations
PageViewAnnotator * annotator;
//text annotation dialogs list
QList<EmbeddedAnnotationDialog *> m_annowindows;
// other stuff
QTimer * delayResizeTimer;
bool dirtyLayout;
@ -210,6 +214,11 @@ PageView::PageView( QWidget *parent, KPDFDocument *document )
PageView::~PageView()
{
// delete the local storage structure
foreach(EmbeddedAnnotationDialog* tempwnd, d->m_annowindows)
{
if(tempwnd)
delete tempwnd;
}
d->document->removeObserver( this );
delete d;
}
@ -329,6 +338,43 @@ void PageView::fitPageWidth( int page )
setFocus();
}
void PageView::setAnnotsWindow(Annotation * annot)
{
if(!annot)
return;
//find the annot window
EmbeddedAnnotationDialog* existWindow=0;
foreach(EmbeddedAnnotationDialog* tempwnd, d->m_annowindows)
{
if(tempwnd)
{
if(tempwnd->m_annot==annot)
{
existWindow=tempwnd;
break;
}
}
}
if(annot->window.flags & Annotation::Hidden)
{
if(existWindow)
{
existWindow->hide();
}
}
else
{
if(existWindow==0)
{
existWindow=new EmbeddedAnnotationDialog(this,annot);
d->m_annowindows<<existWindow;
}
existWindow->show();
}
return;
}
void PageView::displayMessage( const QString & message,PageViewMessage::Icon icon,int duration )
{
if ( !KpdfSettings::showOSD() )

View file

@ -29,6 +29,7 @@ class KActionCollection;
class KPDFDocument;
class PageViewPrivate;
struct Annotation;
/**
* @short The main view. Handles zoom and continuous mode.. oh, and page
@ -43,6 +44,9 @@ class PageView : public Q3ScrollView, public DocumentObserver
PageView( QWidget *parent, KPDFDocument *document );
~PageView();
//set pop-up annotation window states,such as hide/open ,position...
void setAnnotsWindow(Annotation * annot);
// Zoom mode ( last 4 are internally used only! )
enum ZoomMode { ZoomFixed = 0, ZoomFitWidth = 1, ZoomFitPage = 2, ZoomFitText,
ZoomIn, ZoomOut, ZoomRefreshCurrent };

View file

@ -18,6 +18,7 @@
#include <kinputdialog.h>
#include <kuser.h>
#include <kdebug.h>
#include <kmenu.h>
// system includes
#include <math.h>
@ -28,6 +29,7 @@
#include "core/annotations.h"
#include "settings.h"
#include "pageview.h"
#include "annotationpropertiesdialog.h"
#include "pageviewutils.h"
#include "pageviewannotator.h"
@ -208,7 +210,7 @@ class PickPointEngine : public AnnotatorEngine
{
public:
PickPointEngine( const QDomElement & engineElement )
: AnnotatorEngine( engineElement ), clicked( false )
: AnnotatorEngine( engineElement ), clicked( false ), xscale(1.0), yscale(1.0)
{
// parse engine specific attributes
QString pixmapName = engineElement.attribute( "hoverIcon" );
@ -224,11 +226,13 @@ class PickPointEngine : public AnnotatorEngine
delete pixmap;
}
QRect event( EventType type, Button /*button*/, double nX, double nY, double xScale, double yScale )
QRect event( EventType type, Button button, double nX, double nY, double xScale, double yScale )
{
xscale=xScale;
yscale=yScale;
// only proceed if pressing left button
//if ( button != Left )
// return QRect();
if ( button != Left )
return QRect();
// start operation on click
if ( type == Press && clicked == false )
@ -268,57 +272,71 @@ class PickPointEngine : public AnnotatorEngine
}
Annotation * end()
{
// find out annotation's description node
const QDomElement & annElement = m_engineElement.firstChild().toElement();
if ( annElement.isNull() || annElement.tagName() != "annotation" )
return 0;
// find out annotation's type
Annotation * ann = 0;
QString typeString = annElement.attribute( "type" );
// create TextAnnotation from path
if ( typeString == "Text") //<annotation type="Text"
{
//find if chlicked a text annoteation, if there is, load it, or create it.
//note dialog
QString prompt = i18n( "Please input the note:" ) ;
bool resok;
QString note ="";
note= KInputDialog::getText( i18n("Note"), prompt, note,&resok );
if(resok)
{
//add note
TextAnnotation * ta = new TextAnnotation();
ann = ta;
ta->inplaceText=note;
ta->textType = TextAnnotation::InPlace;
ta->boundary=this->rect;
}
}
// create StampAnnotation from path
else if ( typeString == "Stamp" )
{
StampAnnotation * sa = new StampAnnotation();
ann = sa;
sa->stampIconName="okular";
}
// safety check
if ( !ann )
return 0;
// set common attributes
ann->style.color = annElement.hasAttribute( "color" ) ?
annElement.attribute( "color" ) : m_engineColor;
if ( annElement.hasAttribute( "opacity" ) )
ann->style.opacity = annElement.attribute( "opacity" ).toDouble();
// return annotation
return ann;
{
// find out annotation's description node
const QDomElement & annElement = m_engineElement.firstChild().toElement();
if ( annElement.isNull() || annElement.tagName() != "annotation" )
return 0;
// find out annotation's type
Annotation * ann = 0;
QString typeString = annElement.attribute( "type" );
// create TextAnnotation from path
if ( typeString == "FreeText") //<annotation type="Text"
{
//note dialog
QString prompt = i18n( "Please input the free text:" ) ;
bool resok;
QString note ="";
note= KInputDialog::getText( i18n("FreeText"), prompt, note,&resok );
if(resok)
{
//add note
TextAnnotation * ta = new TextAnnotation();
ann = ta;
ta->inplaceText=note;
ta->textType = TextAnnotation::InPlace;
//set boundary
QFontMetricsF mf(ta->textFont);
QRectF rcf=mf.boundingRect(ta->inplaceText);
rect.right =rect.left + ((rcf.width()+5) / xscale) ;
rect.bottom = rect.top + ((rcf.height()+5) / yscale) ;
ta->boundary=this->rect;
}
}
else if ( typeString == "Text")
{
TextAnnotation * ta = new TextAnnotation();
ann = ta;
ta->textType = TextAnnotation::Linked;
ta->window.text="This is a text annotation";
//ta->window.flags &= ~(Annotation::Hidden);
ta->textIcon="comment";
ta->boundary=this->rect;
}
// create StampAnnotation from path
else if ( typeString == "Stamp" )
{
StampAnnotation * sa = new StampAnnotation();
ann = sa;
sa->stampIconName="okular";
}
// safety check
if ( !ann )
return 0;
// set common attributes
ann->style.color = annElement.hasAttribute( "color" ) ?
annElement.attribute( "color" ) : m_engineColor;
if ( annElement.hasAttribute( "opacity" ) )
ann->style.opacity = annElement.attribute( "opacity" ).toDouble();
ann->creationDate=ann->modifyDate=QDateTime::currentDateTime();
// return annotation
return ann;
}
private:
@ -326,6 +344,7 @@ class PickPointEngine : public AnnotatorEngine
NormalizedRect rect;
NormalizedPoint point;
QPixmap * pixmap;
double xscale,yscale;
};
/** @short TwoPointsEngine */
@ -403,42 +422,40 @@ class TwoPointsEngine : public AnnotatorEngine
}
Annotation * end()
{
// find out annotation's description node
const QDomElement & annElement = m_engineElement.firstChild().toElement();
if ( annElement.isNull() || annElement.tagName() != "annotation" )
return 0;
// find out annotation's type
Annotation * ann = 0;
QString typeString = annElement.attribute( "type" );
// create LineAnnotation from path
if ( typeString == "Line") //<annotation type="Text"
{
if ( points.count() != 2 )
return 0;
//add note
LineAnnotation * la = new LineAnnotation();
ann = la;
la->linePoints.append(points[0]);
la->linePoints.append(points[1]);
la->boundary=this->rect;
}
// safety check
if ( !ann )
return 0;
// set common attributes
ann->style.color = annElement.hasAttribute( "color" ) ?
annElement.attribute( "color" ) : m_engineColor;
if ( annElement.hasAttribute( "opacity" ) )
ann->style.opacity = annElement.attribute( "opacity" ).toDouble();
// return annotation
return ann;
{
// find out annotation's description node
const QDomElement & annElement = m_engineElement.firstChild().toElement();
if ( annElement.isNull() || annElement.tagName() != "annotation" )
return 0;
// find out annotation's type
Annotation * ann = 0;
QString typeString = annElement.attribute( "type" );
// create LineAnnotation from path
if ( typeString == "Line") //<annotation type="Text"
{
if ( points.count() != 2 )
return 0;
//add note
LineAnnotation * la = new LineAnnotation();
ann = la;
la->linePoints.append(points[0]);
la->linePoints.append(points[1]);
la->boundary=this->rect;
}
// safety check
if ( !ann )
return 0;
// set common attributes
ann->style.color = annElement.hasAttribute( "color" ) ?
annElement.attribute( "color" ) : m_engineColor;
if ( annElement.hasAttribute( "opacity" ) )
ann->style.opacity = annElement.attribute( "opacity" ).toDouble();
// return annotation
}
private:
@ -579,7 +596,72 @@ if ( !item ) return; //STRAPAAAATCH !!! FIXME
return;
if ( !m_lockedItem && eventType == AnnotatorEngine::Press )
m_lockedItem = item;
// 1.5 check if there is any exist annotations on (nX,nY)......Astario
if( e->type() == QEvent::MouseButtonRelease ) //m_selectedAnnotationName.isEmpty()
{
const KPDFPage * page = item->page();
QLinkedList< Annotation * >::const_iterator aIt = page->m_annotations.begin(), aEnd =page->m_annotations.end();
for ( ; aIt != aEnd; ++aIt )
{
Annotation * ann = *aIt;
if ( ann->boundary.contains( nX, nY ) )
{
Annotation::SubType type = ann->subType();
if(type==Annotation::AText)
{
m_selectedAnnotationName=ann->uniqueName;
if(buttonState == Qt::RightButton) //pop up content menu
{
KMenu menu( this->m_pageView );
QAction *popoutWindow=0, *deleteNote=0, *showProperties=0;
menu.addTitle( i18n("Annotation"));
if(ann->window.flags & Annotation::Hidden)
popoutWindow = menu.addAction( SmallIconSet("comment"), i18n( "&Open Pop-up Note" ) );
else
popoutWindow = menu.addAction( SmallIconSet("comment"), i18n( "&Close Pop-up Note" ) );
deleteNote = menu.addAction( SmallIconSet("delete"), i18n( "&Delete" ) );
showProperties = menu.addAction( SmallIconSet("thumbnail"), i18n( "&Properties..." ) );
QAction *choice = menu.exec( e->globalPos() );
// check if the user really selected an action
if ( choice )
{
if ( choice == popoutWindow)
{
//怎么表示窗口是否已经弹出?看文档 NM(Optional; PDF 1.4) The annotation name, a text string uniquely identifying it among all the annotations on its page.
if(ann->window.flags & Annotation::Hidden)
{
kDebug()<<"astario: select popoutWindow"<<endl;
}
else
{
kDebug()<<"astario: select close annotsWindow"<<endl;
}
ann->window.flags ^= Annotation::Hidden;
m_pageView->setAnnotsWindow(ann);
}
if(choice==deleteNote)
{
kDebug()<<"astario: select deleteNote"<<endl;
}
if(choice==showProperties)
{
kDebug()<<"astario: select showProperties"<<endl;
AnnotsPropertiesDialog propdialog( m_pageView, m_document, ann );
propdialog.exec();
}
};
}
}
}
}
}
// 2. use engine to perform operations
QRect paintRect = m_engine->event( eventType, button, nX, nY, itemWidth, itemHeight );

View file

@ -64,6 +64,8 @@ class PageViewAnnotator : public QObject
int m_lastToolID;
QRect m_lastDrawnRect;
PageViewItem * m_lockedItem;
//selected annotation name
QString m_selectedAnnotationName;
};
#endif