Bug 135521 - Allow moving the view using the red square of the thumbnail view
Summary: Allow moving the view using the red square of the thumbnail view
Status: RESOLVED FIXED
Alias: None
Product: okular
Classification: Applications
Component: general (show other bugs)
Version: unspecified
Platform: Compiled Sources Linux
: NOR wishlist
Target Milestone: ---
Assignee: Okular developers
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2006-10-12 18:08 UTC by Albert Astals Cid
Modified: 2007-07-08 16:25 UTC (History)
1 user (show)

See Also:
Latest Commit:
Version Fixed In:


Attachments
add drag feature (4.27 KB, patch)
2007-05-26 11:09 UTC, Diego R. Brogna
Details
add drag and zoom feature (7.94 KB, patch)
2007-05-29 21:35 UTC, Diego R. Brogna
Details
add drag and zoom feature (8.14 KB, patch)
2007-05-30 10:13 UTC, Diego R. Brogna
Details
add drag and zoom feature (8.42 KB, patch)
2007-06-17 12:59 UTC, Diego R. Brogna
Details

Note You need to log in before you can comment on or make changes to this bug.
Description Albert Astals Cid 2006-10-12 18:08:29 UTC
Version:            (using KDE Devel)
Installed from:    Compiled sources

From Florian:

Currently you can only use the thumbnailview to switch to the top of the selected page but since you have the red square it makes sense to allow the "dragging" of the square from within the thumbnailview itself.

Albert agrees it would be nice.
Comment 1 Diego R. Brogna 2007-05-26 11:09:26 UTC
Created attachment 20697 [details]
add drag feature

Attached patch adds drag feature
Comment 2 Pino Toscano 2007-05-26 11:47:30 UTC
It is nice as a start, however it has a couple of issues:
- getting the iterator from the Document's visible rects is dangerous, as doing setViewport few lines below will make the Document notify the observers about the new viewport; the pageview is an observer as well, that will set new visible rects in the Document, thus the iterator may get dangling => crash.
Easily solvable getting a copy of the rects, and iterating on that copy
- it does not really scroll by mouse pixel-movement, but using normalized coords. I would expect the area to move exactly of what I moved the mouse
- it does not work if the page view has two columns or more; in this case, it just switches to the page where I released the mouse cursor

Keep the good work up! :)
Comment 3 Diego R. Brogna 2007-05-29 21:35:15 UTC
Created attachment 20719 [details]
add drag and zoom feature

I have fixed first two bugs and i have added zoom through wheel feature.
I'm working on third point.
Comment 4 Diego R. Brogna 2007-05-30 10:13:33 UTC
Created attachment 20723 [details]
add drag and zoom feature

fixes third bug
Comment 5 Albert Astals Cid 2007-06-04 11:58:33 UTC
Hi Diego, thanks for the patch, i'll see with Pino how we can integrate it in okular. 

For next time, please try to keep indentation the same way as the file you are editing, examples:

okular/core/observer.h:

virtual void notifyVisibleRectsChanged(); is preceded by spaces but your 
virtual void notifyZoom(int factor); is preceded by a tab

okular/ui/pageview.cpp:

void PageView::notifyZoom(int factor) mixes tabs and spaces "ARGGGG"
Comment 6 Albert Astals Cid 2007-06-04 11:59:21 UTC
Reassining to proper mailing list
Comment 7 Pino Toscano 2007-06-11 23:51:58 UTC
The patch (apart the indentation :) ) is mostly quite fine, I have just one small remark left, about the zooming feature.
IMHO it would be more intuitive to just scroll the thumbnail list when using the wheel, othwerwise there's a bad interaction when duting the scrolling the mouse passes from a non-highlighted area to an highlighted one (that is, the thmbnail list with stop scrolling and the document will zoom - a bit suprising I'd say).
What do you think?

Oh, and a really small thing: the area when you get the hand cursor is a bit shifted wrt to the page area, it should be easy to fix, I suppose.

Anyway, good work!
Comment 8 Florian Grässle 2007-06-12 12:45:52 UTC
Diego,

thanks you stood up and spent some time implementing it :)

As for the zooming I have to agree with Pino. The current behaviour could confuse people quite a bit. So what about surprising them in a more positive way?

We curently have a similar feature for the document view - press and hold CTRL and you can zoom in and out using the mouse scrollbar. We could use the same interaction mechanism in the thumbnailview as well. That way users can make use of their prior knowledge. They feel positively surprised since what they learned also works the same way in a slightly different view.
Comment 9 Diego R. Brogna 2007-06-17 12:58:46 UTC
Sorry for late reply (i haven't received the email).
Now for zooming press and hold CTRL + mouse wheel and i have fixed the hand cursor.
I hope that this patch have a better indentation.
Comment 10 Diego R. Brogna 2007-06-17 12:59:45 UTC
Created attachment 20875 [details]
add drag and zoom feature
Comment 11 Pino Toscano 2007-07-08 16:25:12 UTC
SVN commit 685273 by pino:

Allow the user to change the visible part(s) of the document by dragging the visible areas in the thumbnails, and to change the zoom of the document by Ctrl+wheel on them.

Patch by Diego R. Brogna, thanks a lot!

BUG: 135521


 M  +9 -0      core/document.cpp  
 M  +7 -0      core/document.h  
 M  +4 -0      core/observer.cpp  
 M  +5 -0      core/observer.h  
 M  +8 -0      ui/pageview.cpp  
 M  +1 -0      ui/pageview.h  
 M  +114 -2    ui/thumbnaillist.cpp  
 M  +5 -0      ui/thumbnaillist.h  


--- trunk/KDE/kdegraphics/okular/core/document.cpp #685272:685273
@@ -1654,6 +1654,15 @@
     }
 }
 
+void Document::setZoom(int factor, int excludeId)
+{
+    // notify change to all other (different from id) observers
+    QMap< int, DocumentObserver * >::const_iterator it = d->m_observers.begin(), end = d->m_observers.end();
+    for ( ; it != end ; ++ it )
+        if ( it.key() != excludeId )
+            (*it)->notifyZoom( factor );
+}
+
 void Document::setPrevViewport()
 // restore viewport from the history
 {
--- trunk/KDE/kdegraphics/okular/core/document.h #685272:685273
@@ -318,6 +318,13 @@
         void setNextDocumentViewport( const DocumentViewport &viewport );
 
         /**
+         * Sets the zoom for the current document.
+         *
+         * @param excludeId The observer ids which shouldn't be effected by this change.
+         */
+        void setZoom( int factor, int excludeId = -1 );
+
+        /**
          * Sends @p requests for pixmap generation.
          */
         void requestPixmaps( const QLinkedList<PixmapRequest*> &requests );
--- trunk/KDE/kdegraphics/okular/core/observer.cpp #685272:685273
@@ -40,6 +40,10 @@
 {
 }
 
+void DocumentObserver::notifyZoom( int )
+{
+}
+
 bool DocumentObserver::canUnloadPixmap( int ) const
 {
     return true;
--- trunk/KDE/kdegraphics/okular/core/observer.h #685272:685273
@@ -107,6 +107,11 @@
         virtual void notifyVisibleRectsChanged();
 
         /**
+         * This method is called whenever the zoom of the document has been changed.
+         */
+        virtual void notifyZoom( int factor );
+
+        /**
          * Returns whether the observer agrees that all pixmaps for the given
          * @p page can be unloaded to improve memory usage.
          *
--- trunk/KDE/kdegraphics/okular/ui/pageview.cpp #685272:685273
@@ -813,6 +813,14 @@
         QMetaObject::invokeMethod(this, "slotRequestVisiblePixmaps", Qt::QueuedConnection);
 }
 
+void PageView::notifyZoom( int factor )
+{
+    if ( factor > 0 )
+        updateZoom( ZoomIn );
+    else
+        updateZoom( ZoomOut );
+}
+
 bool PageView::canUnloadPixmap( int pageNumber ) const
 {
     if ( Okular::Settings::memoryLevel() != Okular::Settings::EnumMemoryLevel::Aggressive )
--- trunk/KDE/kdegraphics/okular/ui/pageview.h #685272:685273
@@ -73,6 +73,7 @@
         void notifyViewportChanged( bool smoothMove );
         void notifyPageChanged( int pageNumber, int changedFlags );
         void notifyContentsCleared( int changedFlags );
+        void notifyZoom(int factor);
         bool canUnloadPixmap( int pageNum ) const;
 
         QList< Okular::RegularAreaRect * > textSelections( const QPoint& start, const QPoint& end, int& firstpage );
--- trunk/KDE/kdegraphics/okular/ui/thumbnaillist.cpp #685272:685273
@@ -53,7 +53,10 @@
         QSize sizeHint() const;
 
     protected:
+        void mousePressEvent( QMouseEvent * e );
         void mouseReleaseEvent( QMouseEvent * e );
+        void mouseMoveEvent( QMouseEvent * e );
+        void wheelEvent( QWheelEvent * e );
         void contextMenuEvent( QContextMenuEvent * e );
         void paintEvent(QPaintEvent *);
 
@@ -69,6 +72,7 @@
         int m_pixmapWidth, m_pixmapHeight;
         int m_labelHeight, m_labelNumber;
         Okular::NormalizedRect m_visibleRect;
+        QPoint mouseGrabPos;
 };
 
 
@@ -302,6 +306,42 @@
     }
 }
 
+void ThumbnailList::forwardTrack( const Okular::Page * p, const QPoint &d, const QPoint &s )
+{
+    Okular::DocumentViewport vp=m_document->viewport();
+
+    QVector< Okular::VisiblePageRect * > vVpr = m_document->visiblePageRects();
+
+    QVector< Okular::VisiblePageRect * >::const_iterator vIt = vVpr.begin();
+    QVector< Okular::VisiblePageRect * >::const_iterator vEnd = vVpr.end();
+    for ( ; vIt != vEnd; ++vIt )
+    {
+        Okular::VisiblePageRect *vpr = ( *vIt );
+        if( vpr->pageNumber == p->number() )
+        {
+            double w = vpr->rect.right - vpr->rect.left,
+            h = vpr->rect.bottom - vpr->rect.top,
+            deltaX = d.x()*w/s.x(),
+            deltaY = d.y()*h/s.y();
+
+            vp.rePos.normalizedX -= deltaX;
+            vp.rePos.normalizedY -= deltaY;
+
+            if( !vp.rePos.enabled )
+            {
+                vp.rePos.enabled = true;
+                vp.rePos.normalizedY += h/2;
+            }
+            m_document->setViewport( vp );
+        }
+    }
+}
+
+void ThumbnailList::forwardZoom( const Okular::Page *, int i )
+{
+    m_document->setZoom( i );
+}
+
 const QPixmap * ThumbnailList::getBookmarkOverlay() const
 {
     return m_bookmarkOverlay;
@@ -500,6 +540,10 @@
 {
     m_labelNumber = m_page->number() + 1;
     m_labelHeight = QFontMetrics( font() ).height();
+    setMouseTracking(true);
+    mouseGrabPos.setX(0);
+    mouseGrabPos.setY(0);
+
 }
 
 void ThumbnailWidget::resizeFitWidth( int width )
@@ -533,12 +577,80 @@
     return QSize( width(), heightHint() );
 }
 
+void ThumbnailWidget::mousePressEvent( QMouseEvent * e )
+{
+    QRect r = m_visibleRect.geometry( m_pixmapWidth, m_pixmapHeight );
+
+    if ( r.contains( e->pos() ) )
+    {
+        mouseGrabPos = e->pos();
+    }
+    else
+    {
+        mouseGrabPos.setX( 0 );
+        mouseGrabPos.setY( 0 );
+    }
+}
+
 void ThumbnailWidget::mouseReleaseEvent( QMouseEvent * e )
 {
-    // don't handle the mouse click, forward it to the thumbnail list
-    m_tl->forwardClick( m_page, e->globalPos(), e->button() );
+    QRect r = m_visibleRect.geometry( m_pixmapWidth, m_pixmapHeight );
+    if ( r.contains( e->pos() ) )
+    {
+        setCursor( Qt::OpenHandCursor );
+    }
+    else
+    {
+        setCursor( Qt::ArrowCursor );
+        if ( mouseGrabPos.isNull() )
+        {
+            // don't handle the mouse click, forward it to the thumbnail list
+            m_tl->forwardClick( m_page, e->globalPos(), e->button() );
+        }
+    }
+    mouseGrabPos.setX( 0 );
+    mouseGrabPos.setY( 0 );
 }
 
+void ThumbnailWidget::mouseMoveEvent( QMouseEvent * e )
+{
+    QRect r = m_visibleRect.geometry( m_pixmapWidth, m_pixmapHeight );
+    if ( r.contains( e->pos()-QPoint( m_margin / 2, m_margin / 2 ) ) )
+    {
+        if (!mouseGrabPos.isNull())
+        {
+            setCursor( Qt::ClosedHandCursor );
+            QPoint mousePos = e->pos();
+            QPoint delta = mouseGrabPos - mousePos;
+            // don't handle the mouse move, forward it to the thumbnail list
+            m_tl->forwardTrack( m_page, delta, QPoint( r.width(), r.height() ) );
+            mouseGrabPos = e->pos();
+        }
+        else
+        {
+            setCursor( Qt::OpenHandCursor );
+        }
+    }
+    else
+    {
+        setCursor( Qt::ArrowCursor );
+    }
+}
+
+void ThumbnailWidget::wheelEvent( QWheelEvent * e )
+{
+    QRect r = m_visibleRect.geometry( m_pixmapWidth, m_pixmapHeight );
+
+    if ( r.contains( e->pos() - QPoint( m_margin / 2, m_margin / 2 ) ) && e->orientation() == Qt::Vertical && e->modifiers() == Qt::ControlModifier )
+    {
+        m_tl->forwardZoom( m_page, e->delta() );
+    }
+    else
+    {
+        e->ignore();
+    }
+}
+
 void ThumbnailWidget::contextMenuEvent( QContextMenuEvent * e )
 {
     // don't handle the mouse click, forward it to the thumbnail list
--- trunk/KDE/kdegraphics/okular/ui/thumbnaillist.h #685272:685273
@@ -15,6 +15,7 @@
 #include <kvbox.h>
 #include <qtoolbar.h>
 
+#include "core/area.h"
 #include "core/observer.h"
 
 class QTimer;
@@ -57,6 +58,10 @@
 
         // called by ThumbnailWidgets to send (forward) the mouse click signals
         void forwardClick( const Okular::Page *, const QPoint &, Qt::MouseButton );
+        // called by ThumbnailWidgets to send (forward) the mouse move signals
+        void forwardTrack( const Okular::Page *, const QPoint &, const QPoint & );
+        // called by ThumbnailWidgets to send (forward) the mouse zoom signals
+        void forwardZoom( const Okular::Page *, int );
         // called by ThumbnailWidgets to get the overlay bookmark pixmap
         const QPixmap * getBookmarkOverlay() const;