Commit 42310e18 authored by Pino Toscano's avatar Pino Toscano

Restructuring a bit how the text-editor-like selection works:

* putting it in an own view mode
* associating the selection to every page
* using a better algorithm to calculate the selection, even in a page range
* moving its drawing from the page view to the page painter, so it's possibile to draw it just like it's done with eg annotations

Other changes (more or less related):
* moved the annotation popup to a better place, so it won't interfere with annotation drawing
* commented some debug code in TextPage

svn path=/trunk/playground/graphics/okular/; revision=588795
parent 0776034e
......@@ -27,6 +27,13 @@ NormalizedPoint::NormalizedPoint( double dX, double dY )
NormalizedPoint::NormalizedPoint( int iX, int iY, int xScale, int yScale )
: x( (double)iX / (double)xScale ), y( (double)iY / (double)yScale ) {}
NormalizedPoint& NormalizedPoint::operator=( const NormalizedPoint & p )
{
x = p.x;
y = p.y;
return *this;
}
/** class NormalizedRect **/
......
......@@ -38,6 +38,7 @@ class OKULAR_EXPORT NormalizedPoint
NormalizedPoint();
NormalizedPoint( double dX, double dY );
NormalizedPoint( int ix, int iy, int xScale, int yScale );
NormalizedPoint& operator=( const NormalizedPoint & p );
};
/**
......
......@@ -755,6 +755,23 @@ void Document::removePageAnnotation( int page, Annotation * annotation )
}
}
void Document::setPageTextSelection( int page, RegularAreaRect * rect, const QColor & color )
{
Page * kp = pages_vector[ page ];
if ( !generator || !kp )
return;
// add or remove the selection basing whether rect is null or not
if ( rect )
kp->setTextSelections( rect, color );
else
kp->deleteTextSelections();
// notify observers about the change
foreachObserver( notifyPageChanged( page, DocumentObserver::TextSelection ) );
}
/* REFERENCE IMPLEMENTATION: better calling setViewport from other code
void Document::setNextPage()
{
......
......@@ -135,7 +135,9 @@ class OKULAR_EXPORT Document : public QObject
void addPageAnnotation( int page, Annotation * annotation );
void modifyPageAnnotation( int page, Annotation * newannotation );
void removePageAnnotation( int page, Annotation * annotation );
void setPageTextSelection( int page, RegularAreaRect * rect, const QColor & color );
enum SearchType { NextMatch, PrevMatch, AllDoc, GoogleAll, GoogleAny };
bool searchText( int searchID, const QString & text, bool fromStart, bool caseSensitive,
SearchType type, bool moveViewport, const QColor & color, bool noDialogs = false );
......
......@@ -52,7 +52,7 @@ class DocumentObserver
virtual uint observerId() const = 0;
// commands from the Document to all observers
enum ChangedFlags { Pixmap = 1, Bookmark = 2, Highlights = 4, Annotations = 8 };
enum ChangedFlags { Pixmap = 1, Bookmark = 2, Highlights = 4, TextSelection = 8, Annotations = 16 };
enum NotifyType { Setup = 1, Viewport = 2, Page = 4, Contents = 8, VisibleAreas = 16 };
virtual void notifySetup( const QVector< Okular::Page * > & /*pages*/, bool /*documentChanged*/ ) {};
virtual void notifyViewportChanged( bool /*smoothMove*/ ) {};
......
......@@ -47,7 +47,8 @@ static void deleteObjectRects( QLinkedList< ObjectRect * >& rects, const QSet<Ob
Page::Page( uint page, double w, double h, int o )
: m_number( page ), m_orientation( o ), m_width( w ), m_height( h ),
m_bookmarked( false ), m_maxuniqueNum( 0 ), m_text( 0 ), m_transition( 0 )
m_bookmarked( false ), m_maxuniqueNum( 0 ), m_text( 0 ), m_transition( 0 ),
m_textSelections( 0 )
{
// if landscape swap width <-> height (rotate 90deg CCW)
/* if ( r == 90 || r == 270 )
......@@ -67,6 +68,7 @@ Page::~Page()
deletePixmapsAndRects();
deleteHighlights();
deleteAnnotations();
deleteTextSelections();
delete m_text;
delete m_transition;
}
......@@ -240,6 +242,14 @@ void Page::setHighlight( int s_id, RegularAreaRect *rect, const QColor & color )
}*/
}
void Page::setTextSelections( RegularAreaRect *r, const QColor & color )
{
deleteTextSelections();
HighlightAreaRect * hr = new HighlightAreaRect( r );
hr->s_id = -1;
hr->color = color;
m_textSelections = hr;
}
void Page::addAnnotation( Annotation * annotation )
{
......@@ -357,6 +367,16 @@ void Page::deleteHighlights( int s_id )
}
}
void Page::deleteTextSelections()
{
if (m_textSelections)
{
qDeleteAll(*m_textSelections);
delete m_textSelections;
m_textSelections = 0;
}
}
void Page::deleteAnnotations()
{
// delete ObjectRects of type Annotation
......
......@@ -80,6 +80,7 @@ class OKULAR_EXPORT Page
void setBookmark( bool state );
void setObjectRects( const QLinkedList< ObjectRect * > rects );
void setHighlight( int s_id, RegularAreaRect *r, const QColor & color );
void setTextSelections( RegularAreaRect *r, const QColor & color );
void addAnnotation( Annotation * annotation );
void modifyAnnotation( Annotation * newannotation );
bool removeAnnotation( Annotation * annotation );
......@@ -88,6 +89,7 @@ class OKULAR_EXPORT Page
void deletePixmap( int p_id );
void deletePixmapsAndRects();
void deleteHighlights( int s_id = -1 );
void deleteTextSelections();
void deleteAnnotations();
// operations to save/restore page state (by Document)
......@@ -108,6 +110,7 @@ class OKULAR_EXPORT Page
QLinkedList< HighlightAreaRect * > m_highlights;
QLinkedList< Annotation * > m_annotations;
PageTransition * m_transition;
HighlightAreaRect * m_textSelections;
};
}
......
......@@ -56,7 +56,9 @@ RegularAreaRect * TextPage::getTextArea ( TextSelection * sel) const
const NormalizedPoint * endC=sel->end();
if (sel->dir() == 1 || (sel->itB()==-1 && sel->dir()==0))
{
#ifdef DEBUG_TEXTPAGE
kWarning() << "running first loop\n";
#endif
for (it=0;it<m_words.count();it++)
{
tmp=m_words[it]->area;
......@@ -66,7 +68,9 @@ RegularAreaRect * TextPage::getTextArea ( TextSelection * sel) const
{
/// we have found the (rx,ry)x(tx,ty)
itB=it;
#ifdef DEBUG_TEXTPAGE
kWarning() << "start is " << itB << " count is " << m_words.count() << endl;
#endif
break;
}
......@@ -74,11 +78,15 @@ RegularAreaRect * TextPage::getTextArea ( TextSelection * sel) const
sel->itB(itB);
}
itB=sel->itB();
#ifdef DEBUG_TEXTPAGE
kWarning() << "direction is " << sel->dir() << endl;
kWarning() << "reloaded start is " << itB << " against " << sel->itB() << endl;
#endif
if (sel->dir() == 0 || (sel->itE() == -1 && sel->dir()==1))
{
#ifdef DEBUG_TEXTPAGE
kWarning() << "running second loop\n";
#endif
for (it=m_words.count()-1; it>=itB;it--)
{
tmp=m_words[it]->area;
......@@ -88,17 +96,21 @@ RegularAreaRect * TextPage::getTextArea ( TextSelection * sel) const
{
/// we have found the (ux,uy)x(vx,vy)
itE=it;
#ifdef DEBUG_TEXTPAGE
kWarning() << "ending is " << itE << " count is " << m_words.count() << endl;
kWarning () << "conditions " << tmp->contains(endC->x,endC->y) << " "
<< ( tmp->top <= endC->y && tmp->bottom >= endC->y && tmp->right <= endC->x ) << " " <<
( tmp->top >= endC->y) << endl;
#endif
break;
}
}
sel->itE(itE);
}
#ifdef DEBUG_TEXTPAGE
kWarning() << "reloaded ending is " << itE << " against " << sel->itE() << endl;
#endif
if (sel->itB()!=-1 && sel->itE()!=-1)
{
......@@ -109,7 +121,9 @@ RegularAreaRect * TextPage::getTextArea ( TextSelection * sel) const
first.right=1;
/// if (rx,ry)x(1,ty) intersects the end cursor, there is only one line
bool sameBaseline=end->intersects(first);
#ifdef DEBUG_TEXTPAGE
kWarning() << "sameBaseline : " << sameBaseline << endl;
#endif
if (sameBaseline)
{
first=*start;
......@@ -137,7 +151,7 @@ RegularAreaRect * TextPage::getTextArea ( TextSelection * sel) const
{
tmp=m_words[it]->area;
if (tmp->intersects(&first) || tmp->intersects(&second) || tmp->intersects(&third))
ret->append(tmp);
ret->append(new NormalizedRect(*tmp));
}
// }
......
......@@ -50,6 +50,7 @@
<Action name="mouse_drag"/>
<Action name="mouse_zoom"/>
<Action name="mouse_select"/>
<Action name="mouse_textselect"/>
<Separator/>
<Action name="mouse_toggle_annotate"/>
</Menu>
......
......@@ -95,6 +95,7 @@ void PagePainter::paintPageOnPainter( QPainter * destPainter, const Okular::Page
/** 2 - FIND OUT WHAT TO PAINT (Flags + Configuration + Presence) **/
bool canDrawHighlights = (flags & Highlights) && !page->m_highlights.isEmpty();
bool canDrawTextSelection = (flags & TextSelection) && page->m_textSelections;
bool canDrawAnnotations = (flags & Annotations) && !page->m_annotations.isEmpty();
bool enhanceLinks = (flags & EnhanceLinks) && Okular::Settings::highlightLinks();
bool enhanceImages = (flags & EnhanceImages) && Okular::Settings::highlightImages();
......@@ -104,8 +105,8 @@ void PagePainter::paintPageOnPainter( QPainter * destPainter, const Okular::Page
QList< QPair<QColor, Okular::NormalizedRect *> > * bufferedHighlights = 0;
QList< Okular::Annotation * > * bufferedAnnotations = 0;
QList< Okular::Annotation * > * unbufferedAnnotations = 0;
// fill up lists with visible annotation/highlight objects
if ( canDrawHighlights || canDrawAnnotations )
// fill up lists with visible annotation/highlight objects/text selections
if ( canDrawHighlights || canDrawTextSelection || canDrawAnnotations )
{
// precalc normalized 'limits rect' for intersection
double nXMin = (double)limits.left() / (double)scaledWidth,
......@@ -132,6 +133,22 @@ void PagePainter::paintPageOnPainter( QPainter * destPainter, const Okular::Page
delete limitRect;
//}
}
if ( canDrawTextSelection )
{
if ( !bufferedHighlights )
bufferedHighlights = new QList< QPair<QColor, Okular::NormalizedRect *> >();
/* else
{*/
Okular::NormalizedRect* limitRect = new Okular::NormalizedRect(nXMin, nYMin, nXMax, nYMax );
QList< Okular::NormalizedRect * >::const_iterator hIt = page->m_textSelections->begin(), hEnd = page->m_textSelections->end();
for ( ; hIt != hEnd; ++hIt )
{
if ( (*hIt)->intersects( limitRect ) )
bufferedHighlights->append( qMakePair( page->m_textSelections->color, *hIt ) );
}
delete limitRect;
//}
}
// append annotations inside limits to the un/buffered list
if ( canDrawAnnotations )
{
......
......@@ -24,7 +24,7 @@ class PagePainter
// you can decide wether or not to permit drawing of a certain feature.
enum PagePainterFlags { Accessibility = 1, EnhanceLinks = 2,
EnhanceImages = 4, Highlights = 8,
Annotations = 16 };
TextSelection = 16, Annotations = 32 };
// 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.
......@@ -53,7 +53,7 @@ class PageView : public Q3ScrollView, public Okular::DocumentObserver
// Zoom mode ( last 4 are internally used only! )
enum ZoomMode { ZoomFixed = 0, ZoomFitWidth = 1, ZoomFitPage = 2, ZoomFitText,
ZoomIn, ZoomOut, ZoomRefreshCurrent };
enum MouseMode { MouseNormal, MouseZoom, MouseSelect };
enum MouseMode { MouseNormal, MouseZoom, MouseSelect, MouseTextSelect };
// create actions that interact with this widget
void setupActions( KActionCollection * collection );
......@@ -107,6 +107,7 @@ class PageView : public Q3ScrollView, public Okular::DocumentObserver
// drag and drop related events
void dragEnterEvent( QDragEnterEvent* );
void dragMoveEvent( QDragMoveEvent* );
void dropEvent( QDropEvent* );
private:
......@@ -117,14 +118,14 @@ class PageView : public Q3ScrollView, public Okular::DocumentObserver
// return the widget placed on a certain point or 0 if clicking on empty space
PageViewItem * pickItemOnPoint( int x, int y );
// start / modify / clear selection rectangle
void selectionStart( int x, int y, const QColor & color, bool aboveAll = false );
void selectionEndPoint( int x, int y );
void selectionStart( const QPoint & pos, const QColor & color, bool aboveAll = false );
void selectionEndPoint( const QPoint & pos );
void selectionClear();
void textSelectionForItem( PageViewItem * item, const QPoint & startPoint = QPoint(), const QPoint & endPoint = QPoint() );
// 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
void updateZoomText();
void textSelection( QList<QRect> * , const QColor & );
void textSelectionClear();
// updates cursor
void updateCursor( const QPoint &p );
......@@ -163,6 +164,7 @@ class PageView : public Q3ScrollView, public Okular::DocumentObserver
void slotSetMouseNormal();
void slotSetMouseZoom();
void slotSetMouseSelect();
void slotSetMouseTextSelect();
void slotToggleAnnotator( bool );
void slotScrollUp();
void slotScrollDown();
......
......@@ -656,9 +656,9 @@ bool PageViewAnnotator::routeEvents() const
return m_engine && m_toolBar;
}
void PageViewAnnotator::routeEvent( QMouseEvent * e, PageViewItem * item )
QRect PageViewAnnotator::routeEvent( QMouseEvent * e, PageViewItem * item )
{
if ( !item ) return; //STRAPAAAATCH !!! FIXME
if ( !item ) return QRect();
// find out mouse event type
AnnotatorEngine::EventType eventType = AnnotatorEngine::Press;
......@@ -682,9 +682,11 @@ if ( !item ) return; //STRAPAAAATCH !!! FIXME
double nX = (double)(e->x() - itemRect.left()) / itemWidth;
double nY = (double)(e->y() - itemRect.top()) / itemHeight;
QRect modifiedRect;
// 1. lock engine to current item
if ( m_lockedItem && item != m_lockedItem )
return;
return QRect();
if ( !m_lockedItem && eventType == AnnotatorEngine::Press )
m_lockedItem = item;
......@@ -702,6 +704,7 @@ if ( !item ) return; //STRAPAAAATCH !!! FIXME
QVector<QRect> rects = compoundRegion.unite( m_lastDrawnRect ).rects();
for ( int i = 0; i < rects.count(); i++ )
m_pageView->updateContents( rects[i] );
modifiedRect = compoundRegion.boundingRect() | m_lastDrawnRect;
}
// 4. if engine has finished, apply Annotation to the page
......@@ -720,6 +723,8 @@ if ( !item ) return; //STRAPAAAATCH !!! FIXME
// go on creating annotations of the same type
slotToolSelected( m_lastToolID );
}
return modifiedRect;
}
bool PageViewAnnotator::routePaints( const QRect & wantedRect ) const
......
......@@ -44,7 +44,7 @@ class PageViewAnnotator : public QObject
// methods used when creating the annotation
bool routeEvents() const;
void routeEvent( QMouseEvent * event, PageViewItem * item );
QRect routeEvent( QMouseEvent * event, PageViewItem * item );
bool routePaints( const QRect & wantedRect ) const;
void routePaint( QPainter * painter, const QRect & paintRect );
......
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