Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Namespace Members | Class Members | File Members | Related Pages

qpdf.cpp

Go to the documentation of this file.
00001 //========================================================================
00002 //
00003 // qpdf.cc
00004 //
00005 // Copyright 2001 Robert Griebl
00006 //
00007 //========================================================================
00008 
00009 #include "aconf.h"
00010 #include "GString.h"
00011 #include "PDFDoc.h"
00012 #include "TextOutputDev.h"
00013 
00014 #include "QPEOutputDev.h"
00015 
00016 #include <qpe/qpeapplication.h>
00017 #include <qpe/resource.h>
00018 #include <qpe/applnk.h>
00019 #include <qpe/qcopenvelope_qws.h>
00020 
00021 
00022 #include <qclipboard.h>
00023 #include <qtoolbar.h>
00024 #include <qtoolbutton.h>
00025 #include <qmenubar.h>
00026 #include <qpopupmenu.h>
00027 #include <qwidgetstack.h>
00028 #include <qtimer.h>
00029 #include <qfileinfo.h>
00030 #include <qstring.h>
00031 #include <qlineedit.h>
00032 #include <qspinbox.h>
00033 #include <qlayout.h>
00034 #include <qdialog.h>
00035 #include <qlabel.h>
00036 #include <qmessagebox.h>
00037 
00038 #include "qpdf.h"
00039 
00040 #ifdef QPDF_QPE_ONLY
00041 #include <qpe/fileselector.h>
00042 #else
00043 #include <opie/ofileselector.h>
00044 #endif
00045 
00046 
00047 int main ( int argc, char **argv ) 
00048 {
00049         QPEApplication app ( argc, argv );
00050 
00051         // read config file
00052         globalParams = new GlobalParams ( "" );
00053         globalParams-> setErrQuiet ( true );
00054 
00055         QPdfDlg *dlg = new QPdfDlg ( );                         
00056         app. showMainDocumentWidget ( dlg );
00057 
00058         if (( app. argc ( ) == 3 ) && ( app. argv ( ) [1] == QCString ( "-f" )))
00059                 dlg-> openFile ( app. argv ( ) [2] );
00060 
00061         return app. exec ( );
00062 }
00063 
00064 
00065 QPdfDlg::QPdfDlg ( ) : QMainWindow ( )
00066 {
00067         setCaption ( tr( "QPdf" ));
00068         setIcon ( Resource::loadPixmap ( "qpdf_icon" ));
00069         
00070         m_busy = false;
00071         
00072         m_doc = 0;
00073         m_pages = 0;
00074         m_zoom = 72;
00075         m_currentpage = 0;      
00076 
00077         m_fullscreen = false;
00078         m_renderok = false;
00079                 
00080         
00081         setToolBarsMovable ( false );
00082 
00083         m_stack = new QWidgetStack ( this );
00084         m_stack-> setSizePolicy ( QSizePolicy ( QSizePolicy::Expanding, QSizePolicy::Expanding ));
00085         setCentralWidget ( m_stack );
00086 
00087         m_outdev = new QPEOutputDev ( m_stack );
00088         connect ( m_outdev, SIGNAL( selectionChanged(const QRect&)), this, SLOT( copyToClipboard(const QRect&)));
00089 
00090 #ifdef QPDF_QPE_ONLY
00091         m_filesel = new FileSelector ( "application/pdf", m_stack, "fs", false, true );
00092 #else
00093         m_filesel = new OFileSelector ( "application/pdf", m_stack, "fs", false, true );
00094 #endif
00095 
00096         connect ( m_filesel, SIGNAL( closeMe()), this, SLOT( closeFileSelector()));
00097         connect ( m_filesel, SIGNAL( fileSelected(const DocLnk&)), this, SLOT( openFile(const DocLnk&)));
00098 
00099         m_tb_menu = new QToolBar ( this );
00100         m_tb_menu-> setHorizontalStretchable ( true );
00101 
00102         QMenuBar *mb = new QMenuBar ( m_tb_menu );
00103 
00104         m_pm_zoom = new QPopupMenu ( mb );
00105         m_pm_zoom-> setCheckable ( true );
00106 
00107         mb-> insertItem ( tr( "Zoom" ), m_pm_zoom );
00108 
00109         m_pm_zoom-> insertItem ( tr( "Fit to width" ), 1 );
00110         m_pm_zoom-> insertItem ( tr( "Fit to page" ),  2 );
00111         m_pm_zoom-> insertSeparator ( );
00112         m_pm_zoom-> insertItem ( tr( "50%" ),   50 );
00113         m_pm_zoom-> insertItem ( tr( "75%" ),   75 );
00114         m_pm_zoom-> insertItem ( tr( "100%" ), 100 );
00115         m_pm_zoom-> insertItem ( tr( "125%" ), 125 );
00116         m_pm_zoom-> insertItem ( tr( "150%" ), 150 );
00117         m_pm_zoom-> insertItem ( tr( "200%" ), 200 );
00118         
00119         connect ( m_pm_zoom, SIGNAL( activated(int)), this, SLOT( setZoom(int)));
00120 
00121         m_tb_tool = new QToolBar ( this );
00122                 
00123         new QToolButton ( Resource::loadIconSet ( "fileopen" ),    tr( "Open..." ),       QString::null, this, SLOT( openFile()),  m_tb_tool, "open" );
00124         m_tb_tool-> addSeparator ( );
00125         m_to_find = new QToolButton ( Resource::loadIconSet ( "find" ),        tr( "Find..." ),       QString::null, this, SLOT( toggleFindBar()),     m_tb_tool, "find" );
00126         m_to_find-> setToggleButton ( true );
00127         m_tb_tool-> addSeparator ( );
00128         m_to_full = new QToolButton ( Resource::loadIconSet ( "fullscreen" ),  tr( "Fullscreen" ),    QString::null, this, SLOT( toggleFullscreen()),  m_tb_tool, "fullscreen" );
00129         m_to_full-> setToggleButton ( true );
00130         m_tb_tool-> addSeparator ( );
00131         new QToolButton ( Resource::loadIconSet ( "fastback" ),    tr( "First page" ),    QString::null, this, SLOT( firstPage()), m_tb_tool, "first" );
00132         new QToolButton ( Resource::loadIconSet ( "back" ),        tr( "Previous page" ), QString::null, this, SLOT( prevPage()),  m_tb_tool, "prev" );
00133         new QToolButton ( Resource::loadIconSet ( "down" ),        tr( "Goto page..." ),  QString::null, this, SLOT( gotoPageDialog()),  m_tb_tool, "goto" );
00134         new QToolButton ( Resource::loadIconSet ( "forward" ),     tr( "Next page" ),     QString::null, this, SLOT( nextPage()),  m_tb_tool, "next" );
00135         new QToolButton ( Resource::loadIconSet ( "fastforward" ), tr( "Last page" ),     QString::null, this, SLOT( lastPage()),  m_tb_tool, "last" );
00136 
00137         m_tb_find = new QToolBar ( this );
00138         addToolBar ( m_tb_find, "Search", QMainWindow::Top, true );
00139         m_tb_find-> setHorizontalStretchable ( true );
00140         m_tb_find-> hide ( );
00141 
00142         m_findedit = new QLineEdit ( m_tb_find, "findedit" );
00143         m_tb_find-> setStretchableWidget ( m_findedit );
00144         connect ( m_findedit, SIGNAL( textChanged(const QString&)), this, SLOT( findText(const QString&)));
00145 
00146         new QToolButton ( Resource::loadIconSet ( "next" ),        tr( "Next" ),          QString::null, this, SLOT( findText()),  m_tb_find, "findnext" );
00147 
00148         openFile ( );
00149 }
00150 
00151 QPdfDlg::~QPdfDlg ( )
00152 {
00153         delete m_doc;
00154 }
00155 
00156 // vv Fullscreen handling (for broken QT-lib) [David Hedbor, www.eongames.com]
00157 
00158 void QPdfDlg::resizeEvent ( QResizeEvent * )
00159 {
00160         if ( m_fullscreen && ( size ( ) != qApp-> desktop ( )-> size ( ))) 
00161                 setFullscreen ( true );
00162 }
00163 
00164 void QPdfDlg::focusInEvent ( QFocusEvent * )
00165 {
00166         if ( m_fullscreen )
00167                 setFullscreen ( true );
00168 }
00169 
00170 void QPdfDlg::toggleFullscreen ( )
00171 {
00172         if ( m_to_full-> isOn ( ) == m_fullscreen )
00173                 m_to_full-> setOn ( !m_fullscreen );
00174 
00175         m_fullscreen = !m_fullscreen;
00176         setFullscreen ( m_fullscreen );
00177 }
00178 
00179 void QPdfDlg::setFullscreen ( bool b )
00180 {
00181         static QSize normalsize;
00182 
00183         if ( b ) {
00184                 if ( !normalsize. isValid ( )) 
00185                         normalsize = size ( );
00186                 
00187                 setFixedSize ( qApp-> desktop ( )-> size ( ));
00188                 showNormal ( );
00189                 reparent ( 0, WStyle_Customize | WStyle_NoBorder, QPoint ( 0, 0 ));
00190                 showFullScreen ( );
00191         }
00192         else {
00193                 showNormal ( );
00194                 reparent ( 0, 0, QPoint ( 0, 0 ));
00195                 resize ( normalsize );
00196                 showMaximized ( );
00197                 normalsize = QSize ( );
00198         }       
00199 }
00200 
00201 // ^^ Fullscreen handling (for broken QT-lib)
00202 
00203 void QPdfDlg::setBusy ( bool b )
00204 {
00205         if ( b != m_busy ) {
00206                 m_busy = b;
00207                 
00208                 m_outdev-> setBusy ( m_busy );
00209                 setEnabled ( !m_busy );
00210         }
00211 }
00212 
00213 bool QPdfDlg::busy ( ) const
00214 {
00215         return m_busy;
00216 }
00217 
00218 
00219 void QPdfDlg::updateCaption ( )
00220 {
00221         QString cap = "";
00222         
00223         if ( !m_currentdoc. isEmpty ( )) 
00224                 cap = QString ( "%1 - " ). arg ( m_currentdoc );
00225         cap += "QPdf";
00226         
00227         setCaption ( cap );
00228 }
00229 
00230 
00231 void QPdfDlg::setZoom ( int id )
00232 {
00233         int dpi = 0;
00234 
00235         switch ( id ) {
00236         case 1:
00237                 if ( m_doc && m_doc-> isOk ( )) 
00238                         dpi = m_outdev-> visibleWidth ( ) * 72 / m_doc-> getPageWidth ( m_currentpage );
00239                 break;
00240         
00241         case 2:
00242                 if ( m_doc && m_doc-> isOk ( )) 
00243                         dpi = QMIN( m_outdev-> visibleWidth ( ) * 72 / m_doc-> getPageWidth ( m_currentpage ), \
00244                                     m_outdev-> visibleHeight ( ) * 72 / m_doc-> getPageHeight ( m_currentpage ));
00245                 break;
00246                 
00247         default:
00248                 dpi = id * 72 / 100;
00249                 break;
00250         }
00251         
00252         if ( dpi < 18 )
00253                 dpi = 18;
00254         if ( dpi > 216 )
00255                 dpi = 216;
00256 
00257         for ( uint i = 0; i < m_pm_zoom-> count ( ); i++ ) {
00258                 int xid = m_pm_zoom-> idAt ( i );
00259                 m_pm_zoom-> setItemChecked ( xid, xid == id );
00260         }
00261 
00262         if ( dpi != m_zoom ) { 
00263                 m_zoom = dpi;
00264 
00265                 renderPage ( );
00266         }
00267 }
00268 
00269 
00270 void QPdfDlg::gotoPageDialog ( )
00271 {
00272         QDialog *d = new QDialog ( this, "gotodlg", true );
00273         d-> setCaption ( tr( "Goto page" ));
00274         
00275         QBoxLayout *lay = new QVBoxLayout ( d, 4, 4  ); 
00276         
00277         QLabel *l = new QLabel ( tr( "Select from 1 .. %1:" ). arg ( m_pages ), d );
00278         lay-> addWidget ( l );
00279         
00280         QSpinBox *spin = new QSpinBox ( 1, m_pages, 1, d );
00281         spin-> setValue ( m_currentpage );
00282         spin-> setWrapping ( true );
00283         spin-> setButtonSymbols ( QSpinBox::PlusMinus );
00284         lay-> addWidget ( spin );
00285         
00286         if ( d-> exec ( ) == QDialog::Accepted ) {
00287                 gotoPage ( spin-> value ( ));
00288         }
00289         
00290         delete d;
00291 }
00292 
00293 void QPdfDlg::toggleFindBar ( )
00294 {
00295         if ( m_to_find-> isOn ( ) == m_tb_find-> isVisible ( ))
00296                 m_to_find-> setOn ( !m_tb_find-> isVisible ( ));
00297 
00298         if ( m_tb_find-> isVisible ( )) {
00299                 m_tb_find-> hide ( );
00300                 m_outdev-> setFocus ( );
00301         }
00302         else {
00303                 m_tb_find-> show ( );
00304                 m_findedit-> setFocus ( );
00305         }
00306 }
00307 
00308 void QPdfDlg::findText ( const QString &str )
00309 {
00310         if ( !m_doc || !m_doc-> isOk ( ) || str. isEmpty ( )) 
00311                 return;
00312 
00313         TextOutputDev *textOut = 0;
00314         int pg = 0;
00315 
00316         setBusy ( true );
00317                 
00318         int len = str. length ( );
00319         Unicode *u = new Unicode [len];
00320         for ( int i = 0; i < len; i++ )
00321                 u [i] = str [i]. unicode ( );
00322                 
00323         int xMin = 0, yMin = 0, xMax = 0, yMax = 0;
00324         QRect selr = m_outdev-> selection ( );
00325         bool fromtop = true; 
00326         
00327         if ( selr. isValid ( )) {
00328                 xMin = selr. right ( );
00329                 yMin = selr. top ( ) + selr. height ( ) / 2;
00330                 fromtop = false;
00331         }
00332 
00333         if ( m_outdev-> findText ( u, len, fromtop, true, &xMin, &yMin, &xMax, &yMax )) 
00334                 goto found;
00335 
00336         qApp-> processEvents ( );
00337                 
00338         // search following pages
00339         textOut = new TextOutputDev ( 0, gFalse, gFalse );
00340         if ( !textOut-> isOk ( )) 
00341                 goto done;
00342         
00343         qApp-> processEvents ( );
00344                 
00345         for ( pg = ( m_currentpage % m_pages ) + 1; pg != m_currentpage; pg = ( pg % m_pages ) + 1 ) {
00346                 m_doc-> displayPage ( textOut, pg, 72, 0, gFalse );
00347                 
00348                 fp_t xMin1, yMin1, xMax1, yMax1;
00349                 
00350                 qApp-> processEvents ( );
00351                 
00352                 if ( textOut-> findText ( u, len, gTrue, gTrue, &xMin1, &yMin1, &xMax1, &yMax1 ))
00353                         goto foundPage;
00354                         
00355                 qApp-> processEvents ( );       
00356         }
00357 
00358         // search current page ending at current selection
00359         if ( selr. isValid ( )) {
00360                 xMax = selr. left ( );
00361                 yMax = selr. top ( ) + selr. height ( ) / 2;
00362 
00363                 if ( m_outdev-> findText ( u, len, gTrue, gFalse, &xMin, &yMin, &xMax, &yMax )) 
00364                         goto found;
00365         }
00366         
00367         // not found
00368         QMessageBox::information ( this, tr( "Find..." ), tr( "'%1' could not be found." ). arg ( str ));
00369         goto done;
00370 
00371 foundPage:
00372         qApp-> processEvents ( );
00373 
00374         gotoPage ( pg );
00375         
00376         if ( !m_outdev-> findText ( u, len, gTrue, gTrue, &xMin, &yMin, &xMax, &yMax )) {
00377                 // this can happen if coalescing is bad
00378                 goto done;
00379         }
00380 
00381 found:
00382         selr. setCoords ( xMin, yMin, xMax, yMax );
00383         m_outdev-> setSelection ( selr, true ); // this will emit QPEOutputDev::selectionChanged ( ) -> copyToClipboard ( )
00384 
00385 done:                   
00386 
00387         delete [] u; 
00388         delete textOut;
00389 
00390         setBusy ( false );
00391 }
00392                 
00393 
00394 void QPdfDlg::findText ( )
00395 {
00396         findText ( m_findedit-> text ( ));
00397 }
00398 
00399 void QPdfDlg::copyToClipboard ( const QRect &r )
00400 {
00401         if ( m_doc && m_doc-> isOk ( ) && m_doc-> okToCopy ( ))
00402                 qApp-> clipboard ( )-> setText ( m_outdev-> getText ( r ));
00403 }
00404 
00405 void QPdfDlg::firstPage ( )
00406 {
00407         gotoPage ( 1 );
00408 }
00409 
00410 void QPdfDlg::prevPage ( )
00411 {
00412         gotoPage ( m_currentpage - 1 );
00413 }
00414 
00415 void QPdfDlg::nextPage ( )
00416 {
00417         gotoPage ( m_currentpage + 1 );
00418 }
00419 
00420 void QPdfDlg::lastPage ( )
00421 {
00422         gotoPage ( m_pages );
00423 }
00424 
00425 void QPdfDlg::gotoPage ( int n )
00426 {
00427         if ( n < 1 )
00428                 n = 1;
00429         if ( n > m_pages )
00430                 n = m_pages;
00431                 
00432         if ( n != m_currentpage ) {
00433                 m_currentpage = n;      
00434                 
00435                 renderPage ( );
00436         }
00437 }
00438 
00439 void QPdfDlg::renderPage ( )
00440 {
00441         if ( m_renderok && m_doc && m_doc-> isOk ( )) {
00442                 m_renderok = false;
00443         
00444                 setBusy ( true );
00445                 m_doc-> displayPage ( m_outdev, m_currentpage, m_zoom, 0, true ); 
00446                 setBusy ( false );
00447                 
00448                 m_outdev-> setPageCount ( m_currentpage, m_pages );
00449                 
00450                 m_renderok = true;
00451         }
00452 }
00453 
00454 void QPdfDlg::closeFileSelector ( )
00455 {
00456         m_tb_menu-> show ( );
00457         m_tb_tool-> show ( );
00458         m_stack-> raiseWidget ( m_outdev );
00459 }
00460 
00461 void QPdfDlg::openFile ( )
00462 {
00463         m_tb_menu-> hide ( );
00464         m_tb_tool-> hide ( );
00465         m_tb_find-> hide ( );
00466         m_stack-> raiseWidget ( m_filesel );
00467 }
00468 
00469 void QPdfDlg::openFile ( const QString &f )
00470 {
00471         DocLnk nf;
00472         nf. setType ( "application/pdf" );
00473         nf. setFile ( f );
00474         QFileInfo fi ( f );
00475         nf. setName ( fi. baseName ( ));
00476         openFile ( nf );
00477 }
00478 
00479 void QPdfDlg::openFile ( const DocLnk &f )
00480 {
00481         QString fn = f. file ( );
00482         QFileInfo fi ( fn );
00483         
00484         if ( fi. exists ( )) {
00485                 delete m_doc;
00486 
00487                 m_doc = new PDFDoc ( new GString ( fn. local8Bit ( )), 0, 0 );
00488 
00489                 if ( m_doc-> isOk ( )) {
00490                         m_currentdoc = f. name ( );
00491                         int sep = m_currentdoc. findRev ( '/' );
00492                         if ( sep > 0 )
00493                                 m_currentdoc = m_currentdoc. mid ( sep + 1 );
00494 
00495                         m_pages = m_doc-> getNumPages ( );
00496                         m_currentpage = 0;
00497                 
00498                         QTimer::singleShot ( 0, this, SLOT( delayedInit()));
00499                 }
00500                 else {
00501                         delete m_doc;
00502                         m_doc = 0;
00503                         
00504                         m_currentdoc = QString::null;
00505                 }
00506         
00507                 updateCaption ( );
00508         }
00509         else
00510                 QMessageBox::warning ( this, tr( "Error" ), tr( "File does not exist!" ));
00511 }
00512 
00513 void QPdfDlg::setDocument ( const QString &f )
00514 {
00515         if ( f. find ( ".desktop", 0, true ) == -1 ) 
00516                 openFile ( f );
00517         else 
00518                 openFile ( DocLnk ( f ));
00519                 
00520         closeFileSelector ( );
00521 }
00522 
00523 void QPdfDlg::delayedInit ( )
00524 {       
00525         closeFileSelector ( );
00526         
00527         m_currentpage = 0;
00528         m_zoom = 0;
00529         m_renderok = false;
00530         
00531         setZoom ( 100 );
00532         gotoPage ( 1 );
00533         
00534         m_renderok = true;
00535         
00536         renderPage ( );
00537         
00538         m_outdev-> setFocus ( );
00539 }
00540 

Generated on Sat Nov 5 16:18:12 2005 for OPIE by  doxygen 1.4.2