Changeset 277

Show
Ignore:
Timestamp:
06/11/07 09:12:09 (15 months ago)
Author:
jordi
Message:

Added a patch by Igor Vagulin which adds text selection and copy to clipboard features. This fixes bug #14.

Location:
trunk
Files:
16 modified

Legend:

Unmodified
Added
Removed
  • trunk/data/epdfview-ui.xml

    r254 r277  
    1111    <menu action="EditMenu"> 
    1212      <menuitem name="Find" action="Find"/> 
     13      <separator /> 
     14      <menuitem name="PageModeScroll" action="PageModeScroll"/> 
     15      <menuitem name="PageModeText" action="PageModeText"/> 
    1316      <separator /> 
    1417      <menuitem name="Preferences" action="Preferences"/> 
     
    3942    </menu> 
    4043  </menubar> 
    41    
     44 
    4245  <toolbar name="ToolBar"> 
    4346    <toolitem name="OpenFile" action="OpenFile"/> 
     
    5053    <toolitem name="ZoomFit" action="ZoomFit"/> 
    5154    <toolitem name="ZoomWidth" action="ZoomWidth"/> 
     55    <separator/> 
     56    <toolitem name="PageModeScroll" action="PageModeScroll"/> 
     57    <toolitem name="PageModeText" action="PageModeText"/> 
    5258  </toolbar> 
    5359 
  • trunk/src/DocumentPage.cxx

    r206 r277  
    1818#include <config.h> 
    1919#include <string.h> 
     20#include <gdk/gdk.h> 
    2021#include "epdfview.h" 
    2122 
     
    2930DocumentPage::DocumentPage () 
    3031{ 
     32    m_Selection = NULL; 
    3133    m_Data = NULL; 
    3234    m_HasSelection = FALSE; 
     
    5052    } 
    5153    g_list_free (m_LinkList); 
     54 
     55    if(m_Selection) 
     56        gdk_region_destroy(m_Selection); 
    5257} 
    5358 
     
    7984        invertArea (m_SelectionX1, m_SelectionY1, m_SelectionX2, m_SelectionY2); 
    8085        m_HasSelection = FALSE; 
     86    } 
     87 
     88    if(NULL != m_Selection){ 
     89        invertRegion(m_Selection); 
     90        gdk_region_destroy(m_Selection); 
     91        m_Selection = NULL; 
    8192    } 
    8293} 
     
    196207} 
    197208 
     209void 
     210DocumentPage::invertRegion (GdkRegion* region) 
     211{ 
     212    int count; 
     213    GdkRectangle *rectangles; 
     214    gdk_region_get_rectangles(region, &rectangles, &count); 
     215    while(count--){ 
     216        GdkRectangle r = rectangles[count]; 
     217        invertArea(r.x, r.y, r.x + r.width, r.y + r.height); 
     218    } 
     219    g_free(rectangles); 
     220} 
     221 
     222 
    198223/// 
    199224/// @brief Allocates the memory for a new page. 
     
    254279    m_HasSelection = TRUE; 
    255280} 
     281 
     282void 
     283DocumentPage::setSelection (GdkRegion *region) 
     284{ 
     285    clearSelection (); 
     286     
     287    invertRegion (region); 
     288     
     289    m_Selection = gdk_region_copy(region); 
     290} 
  • trunk/src/DocumentPage.h

    r196 r277  
    1818#if !defined (__DOCUMENT_PAGE_H__) 
    1919#define __DOCUMENT_PAGE_H__ 
     20 
     21typedef struct _GdkRegion GdkRegion; 
    2022 
    2123namespace ePDFView 
     
    4244            gboolean newPage (gint width, gint height); 
    4345            void setSelection (DocumentRectangle &selection, gdouble scale); 
     46            void setSelection (GdkRegion *region); 
    4447 
    4548        protected: 
     
    6265            /// The list of links from the page. 
    6366            GList *m_LinkList; 
    64  
     67            /// Selection region 
     68            GdkRegion *m_Selection; 
     69             
     70            void invertRegion (GdkRegion*); 
    6571            void invertArea (gint x1, gint y1, gint x2, gint y2); 
    6672    }; 
  • trunk/src/IDocument.h

    r222 r277  
    2222#define EPDFVIEW_DOCUMENT_ERROR     ePDFView::IDocument::getErrorQuark () 
    2323 
     24typedef struct _GdkRegion GdkRegion; 
     25 
    2426namespace ePDFView  
    2527{ 
     
    2729    class DocumentIndex; 
    2830    class IDocumentObserver; 
    29     class DocumentPage; 
     31    class DocumentPage;  
    3032 
    3133    /// 
     
    263265            virtual gboolean saveFile (const gchar *filename, 
    264266                                       GError **error) = 0; 
     267 
     268            virtual GdkRegion* getTextRegion (DocumentRectangle *rect) = 0; 
     269            virtual void setTextSelection (DocumentRectangle *rect) = 0; 
    265270 
    266271            void attach (const IDocumentObserver *observer); 
  • trunk/src/IDocumentObserver.h

    r200 r277  
    151151            virtual void notifySaveError (const GError *error) { } 
    152152 
     153            /// 
     154            /// @brief Someone select text in document. 
     155            /// 
     156            /// This function called when someone select some text 
     157            /// in document. 
     158            /// 
     159            /// @param text Selected text. 
     160            /// 
     161            virtual void notifyTextSelected (const gchar* text) { } 
     162 
    153163        protected: 
    154164            /// 
  • trunk/src/IMainView.h

    r263 r277  
    577577            virtual void setOutline (DocumentOutline *outline) = 0; 
    578578 
     579            virtual void copyTextToClibboard(const gchar* text) = 0; 
     580            virtual void activePageModeScroll (gboolean active) = 0; 
     581            virtual void activePageModeText (gboolean active) = 0; 
     582 
    579583        protected: 
    580584            /// 
  • trunk/src/IPageView.h

    r172 r277  
    3333        /// Drag cursor. 
    3434        PAGE_VIEW_CURSOR_DRAG, 
     35        /// Text selection cursor. 
     36        PAGE_VIEW_CURSOR_SELECT_TEXT, 
    3537        /// Link cursor. 
    3638        PAGE_VIEW_CURSOR_LINK 
  • trunk/src/MainPter.cxx

    r263 r277  
    696696} 
    697697 
     698void 
     699MainPter::pageModeScrollActivated (gboolean active) 
     700{ 
     701    IMainView &view = getView (); 
     702    if ( active ) 
     703    { 
     704        m_PagePter->setMode(PagePterModeScroll); 
     705        view.activePageModeText (FALSE); 
     706    } 
     707} 
     708 
     709void 
     710MainPter::pageModeTextActivated (gboolean active) 
     711{ 
     712    IMainView &view = getView (); 
     713    if ( active ) 
     714    { 
     715        m_PagePter->setMode(PagePterModeSelectText); 
     716        view.activePageModeScroll (FALSE); 
     717    } 
     718} 
     719 
    698720/// 
    699721/// @brief The "Zoom In" was activated. 
     
    9961018} 
    9971019#endif // DEBUG 
     1020 
     1021void  
     1022MainPter::notifyTextSelected (const gchar* text) 
     1023{ 
     1024    getView ().copyTextToClibboard(text); 
     1025} 
  • trunk/src/MainPter.h

    r253 r277  
    4040            MainPter (IDocument *document); 
    4141            ~MainPter (void); 
     42 
     43            void pageModeTextActivated(gboolean active); 
     44            void pageModeScrollActivated(gboolean active); 
    4245 
    4346            void setInitialState (void); 
     
    8588            void notifySave (void); 
    8689            void notifySaveError (const GError *error); 
     90            void notifyTextSelected (const gchar* text); 
    8791 
    8892#if defined (DEBUG) 
  • trunk/src/PDFDocument.cxx

    r258 r277  
    657657} 
    658658 
     659void  
     660PDFDocument::setTextSelection (DocumentRectangle *rect) 
     661{ 
     662    g_assert(rect); 
     663 
     664    PopplerPage *page = poppler_document_get_page (m_Document, getCurrentPageNum()-1); 
     665    if(!page) 
     666        return; 
     667 
     668    gdouble pageWidth, pageHeight; 
     669    poppler_page_get_size(page, &pageWidth, &pageHeight); 
     670     
     671    //for get text we must exchange y coordinate, don't ask me where logic here. 
     672    PopplerRectangle textRect = { rect->getX1(), 
     673                                  (pageHeight - rect->getY2()), 
     674                                  rect->getX2(), 
     675                                  (pageHeight - rect->getY1())}; 
     676    gchar *text = poppler_page_get_text(page, &textRect); 
     677    if(!text) 
     678        goto cleanup; 
     679         
     680    for ( GList *obs = g_list_first (m_Observers) ; 
     681          NULL != obs ; 
     682          obs = g_list_next (obs) ) 
     683        { 
     684            IDocumentObserver *observer = (IDocumentObserver*)obs->data; 
     685            observer->notifyTextSelected(text); 
     686        } 
     687 
     688 cleanup: 
     689    if(page) 
     690        g_object_unref(page); 
     691    if(text) 
     692        g_free(text); 
     693} 
     694GdkRegion* 
     695PDFDocument::getTextRegion (DocumentRectangle *r) 
     696{ 
     697    GdkRegion *res = NULL; 
     698    PopplerPage *page = poppler_document_get_page (m_Document, getCurrentPageNum()-1); 
     699    if(!page) 
     700        return NULL; 
     701 
     702    //calulate rect 
     703    PopplerRectangle rect; 
     704    rect.x1 = r->getX1() / getZoom(); 
     705    rect.y1 = r->getY1() / getZoom(); 
     706    rect.x2 = r->getX2() / getZoom(); 
     707    rect.y2 = r->getY2() / getZoom(); 
     708 
     709    //calc selection size 
     710    res = poppler_page_get_selection_region(page, getZoom(), &rect); 
     711                              
     712    //free some local data 
     713    g_object_unref(page); 
     714 
     715    return res; 
     716} 
     717 
     718 
    659719/// 
    660720/// @brief Gets the document's page layout from Poppler's page layout. 
  • trunk/src/PDFDocument.h

    r222 r277  
    5555            DocumentPage *renderPage (gint pageNum); 
    5656            gboolean saveFile (const gchar *fileName, GError **error); 
     57            GdkRegion* getTextRegion (DocumentRectangle* rect); 
     58            void setTextSelection (DocumentRectangle *rect); 
    5759 
    5860        protected: 
  • trunk/src/PagePter.cxx

    r275 r277  
    1616// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA 
    1717 
     18#include <gdk/gdk.h> 
    1819#include "epdfview.h" 
    1920 
     
    4849    gint y; 
    4950    /// The horizontal position of the page view scroll when the drag started. 
    50     gdouble scrollX; 
     51    int startX; 
    5152    /// The vertical position of the page view scroll when the drag started. 
    52     gdouble scrollY; 
     53    int startY; 
    5354}; 
    5455 
     
    6162PagePter::PagePter (IDocument *document) 
    6263{ 
     64    m_LastSelection = NULL; 
    6365    m_Document = document; 
    6466    m_Document->attach (this); 
     
    6668    m_NextPageScroll = PAGE_SCROLL_START; 
    6769    m_PageView = NULL; 
     70    m_Mode = PagePterModeScroll; 
    6871} 
    6972 
     
    130133 
    131134            IPageView &view = getView (); 
    132             m_DragInfo->scrollX = view.getHorizontalScroll (); 
    133             m_DragInfo->scrollY = view.getVerticalScroll (); 
    134             view.setCursor (PAGE_VIEW_CURSOR_DRAG); 
     135            m_DragInfo->startX = x; 
     136            m_DragInfo->startY = y; 
     137            if(m_Mode == PagePterModeScroll) 
     138                view.setCursor (PAGE_VIEW_CURSOR_DRAG); 
     139            else 
     140                view.setCursor (PAGE_VIEW_CURSOR_SELECT_TEXT); 
    135141        } 
    136142    } 
     
    150156    if ( 1 == button ) 
    151157    { 
     158        if(m_LastSelection) 
     159            gdk_region_destroy(m_LastSelection); 
     160        m_LastSelection = NULL; 
     161 
     162        if(m_Document->isLoaded() && m_Mode == PagePterModeSelectText){ 
     163            DocumentRectangle rect(m_DragInfo->startX, m_DragInfo->startY, 
     164                                   m_DragInfo->x, m_DragInfo->y); 
     165            m_Document->setTextSelection(&rect); 
     166        } 
     167 
    152168        delete m_DragInfo; 
    153169        m_DragInfo = NULL; 
     170 
     171        refreshPage(PAGE_SCROLL_NONE, FALSE); 
     172         
    154173        getView ().setCursor (PAGE_VIEW_CURSOR_NORMAL); 
    155174    } 
     
    182201        } 
    183202    } 
    184     else 
    185     { 
    186         view.scrollPage (view.getHorizontalScroll (), view.getVerticalScroll (), 
    187                          x - m_DragInfo->x, y - m_DragInfo->y); 
     203    else{ 
     204        m_DragInfo->x = x; 
     205        m_DragInfo->y = y;   
     206 
     207        if(m_Mode == PagePterModeScroll){ 
     208            view.scrollPage (view.getHorizontalScroll (), view.getVerticalScroll (), 
     209                             x - m_DragInfo->startX, y - m_DragInfo->startY); 
     210        } 
     211        else{ 
     212            if(!m_Document->isLoaded()) 
     213                return ; 
     214             
     215            DocumentRectangle rect(m_DragInfo->startX, m_DragInfo->startY, 
     216                                          m_DragInfo->x, m_DragInfo->y); 
     217 
     218            GdkRegion *region = m_Document->getTextRegion (&rect); 
     219 
     220            if( !m_LastSelection || !gdk_region_equal(m_LastSelection, region)){ 
     221                if(m_LastSelection) 
     222                    gdk_region_destroy(m_LastSelection); 
     223                m_LastSelection = gdk_region_copy(region); 
     224                DocumentPage *page = m_Document->getCurrentPage(); 
     225                if ( NULL != page ) 
     226                    refreshPage (PAGE_SCROLL_NONE, FALSE); 
     227            } 
     228        } 
    188229    } 
    189230} 
     
    274315        { 
    275316            g_WaitingForPage = FALSE; 
     317            if ( NULL != m_LastSelection ) 
     318                documentPage->setSelection(m_LastSelection); 
    276319            view.showPage (documentPage, pageScroll); 
    277320        } 
  • trunk/src/PagePter.h

    r170 r277  
    2424namespace ePDFView 
    2525{ 
     26    enum PagePterMode{ 
     27        PagePterModeScroll, 
     28        PagePterModeSelectText, 
     29    }; 
     30 
    2631    /// 
    2732    /// @class PagePter. 
     
    5459            void setView (IMainView &view); 
    5560            void viewResized (gint width, gint height); 
     61            void setMode(PagePterMode mode) 
     62            { 
     63                m_Mode = mode; 
     64            } 
    5665 
    5766        protected: 
     
    6473            /// The page view. 
    6574            IPageView *m_PageView; 
    66              
    67             void refreshPage (PageScroll pageScroll, gboolean wasZoomed); 
     75            /// Last text selection 
     76            GdkRegion *m_LastSelection; 
     77            /// What page presenter must do when user move mouse with button pressed. 
     78            PagePterMode m_Mode; 
     79 
     80            void refreshPage (PageScroll pageScroll, gboolean wasZoomed); 
    6881    }; 
    6982} 
  • trunk/src/gtk/MainView.cxx

    r263 r277  
    7777static void main_window_zoom_out_cb (GtkWidget *, gpointer); 
    7878static void main_window_zoom_width_cb (GtkToggleAction *, gpointer); 
     79static void main_window_page_mode_scroll_cb (GtkToggleAction *, gpointer); 
     80static void main_window_page_mode_text_cb (GtkToggleAction *, gpointer); 
    7981 
    8082#if defined (HAVE_CUPS) 
     
    186188    { "ZoomWidth", EPDFVIEW_STOCK_ZOOM_WIDTH, N_("Zoom to _Width"), NULL, 
    187189      N_("Make the current document fill the window width"), 
    188       G_CALLBACK (main_window_zoom_width_cb), FALSE } 
     190      G_CALLBACK (main_window_zoom_width_cb), FALSE }, 
     191 
     192    { "PageModeScroll", GTK_STOCK_FULLSCREEN, N_("Scroll"), NULL, 
     193      N_("Mouse scroll page"), 
     194      G_CALLBACK (main_window_page_mode_scroll_cb), FALSE }, 
     195 
     196    { "PageModeText", GTK_STOCK_SELECT_ALL, N_("Select Text"), NULL, 
     197      N_(" Mouse select text"), 
     198      G_CALLBACK (main_window_page_mode_text_cb), FALSE }, 
    189199 
    190200}; 
     
    273283} 
    274284 
     285void 
     286MainView::activePageModeScroll (gboolean active) 
     287{ 
     288    GtkAction *action = 
     289        gtk_ui_manager_get_action (m_UIManager, "/ToolBar/PageModeScroll"); 
     290    gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action), active); 
     291} 
     292 
     293 
     294void 
     295MainView::activePageModeText (gboolean active) 
     296{ 
     297    GtkAction *action = 
     298        gtk_ui_manager_get_action (m_UIManager, "/ToolBar/PageModeText"); 
     299    gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action), active); 
     300} 
     301 
    275302gchar * 
    276303MainView::openFileDialog (const gchar *lastFolder) 
     
    10371064        } 
    10381065    } 
     1066} 
     1067 
     1068void 
     1069MainView::copyTextToClibboard(const gchar* text) 
     1070{ 
     1071    GtkClipboard *clipboard = gtk_clipboard_get(GDK_SELECTION_PRIMARY); 
     1072    gtk_clipboard_set_text(clipboard, text, -1); 
    10391073} 
    10401074 
     
    14171451    pter->zoomWidthActivated (gtk_toggle_action_get_active (action)); 
    14181452} 
     1453 
     1454void 
     1455main_window_page_mode_scroll_cb (GtkToggleAction *action, gpointer data) 
     1456{ 
     1457    g_assert ( NULL != data && "The data parameter is NULL."); 
     1458 
     1459    MainPter *pter = (MainPter *)data; 
     1460    pter->pageModeScrollActivated (gtk_toggle_action_get_active (action)); 
     1461} 
     1462 
     1463void 
     1464main_window_page_mode_text_cb (GtkToggleAction *action, gpointer data) 
     1465{ 
     1466    g_assert ( NULL != data && "The data parameter is NULL."); 
     1467 
     1468    MainPter *pter = (MainPter *)data; 
     1469    pter->pageModeTextActivated (gtk_toggle_action_get_active (action)); 
     1470} 
  • trunk/src/gtk/MainView.h

    r263 r277  
    3636            void activeZoomFit (gboolean active); 
    3737            void activeZoomWidth (gboolean active); 
     38            void activePageModeScroll (gboolean active); 
     39            void activePageModeText (gboolean active); 
    3840            gchar *openFileDialog (const gchar *lastFolder); 
    3941            gchar *promptPasswordDialog (void); 
     
    6971            void setZoomText (const gchar *text); 
    7072            const gchar *getGoToPageText (void); 
     73            void copyTextToClibboard(const gchar* text); 
    7174            IFindView *getFindView (void); 
    7275            IPageView *getPageView (void); 
  • trunk/src/gtk/PageView.cxx

    r212 r277  
    185185        switch (cursorType) 
    186186        { 
     187            case PAGE_VIEW_CURSOR_SELECT_TEXT: 
     188                cursor = gdk_cursor_new (GDK_XTERM); 
     189                break; 
    187190            case PAGE_VIEW_CURSOR_LINK: 
    188191                cursor = gdk_cursor_new (GDK_HAND2);