kviewshell
kmultipage.h
Go to the documentation of this file.00001 // -*- C++ -*- 00002 #ifndef _KMULTIPAGE_H 00003 #define _KMULTIPAGE_H 00004 00005 #include "pageView.h" 00006 #include "documentPageCache.h" 00007 #include "documentRenderer.h" 00008 #include "history.h" 00009 #include "kmultipageInterface.h" 00010 #include "marklist.h" 00011 00012 #include <kparts/part.h> 00013 #include <qtimer.h> 00014 00015 class Anchor; 00016 class DocumentWidget; 00017 class KConfigDialog; 00018 class KPrintDialogPage_PageOptions; 00019 class KPrinter; 00020 class PageView; 00021 class QPainter; 00022 class QSplitter; 00023 class QToolBox; 00024 class simplePageSize; 00025 class TableOfContents; 00026 class PageNumber; 00027 class SearchWidget; 00028 00029 00036 // TODO remove virtual inheritance for KDE 4. It's the reason for the strange DCOPObject construction 00037 class KMultiPage : public KParts::ReadOnlyPart, virtual public kmultipageInterface 00038 { 00039 Q_OBJECT 00040 00041 public: 00042 KMultiPage(QWidget *parentWidget, const char *widgetName, QObject *parent, const char *name); 00043 virtual ~KMultiPage(); 00044 00045 /* returns the scrollview used for the display */ 00046 virtual QWidget* mainWidget() {return _scrollView;} 00047 00048 /* Methods which are associated with the DCOP functionality of the 00049 kmultipage. This method returns the file name (not the URL) of 00050 the currently loaded file. */ 00051 QString name_of_current_file(); 00052 00053 /* Methods which are associated with the DCOP functionality of the 00054 kmultipage. This method can be implemented by the multipage, 00055 e.g. to jump to a certain location. */ 00056 virtual ASYNC jumpToReference(const QString& /*reference*/); 00057 00058 /* Methods which are associated with the DCOP functionality of the 00059 kmultipage. This method checks if a given file is loaded. */ 00060 bool is_file_loaded(const QString& filename); 00061 00062 /* Opens file and sets URL 00063 00064 This method does the same as openFile, but sets the m_url of the 00065 kmultipage. This can be important, for the following reason: 00066 assume that a DVI is or DJVU-file is located on a web server at 00067 baseURL=http://www.x.x/x.dvi The file may refer to external 00068 graphic files using relative links. 00069 00070 The file is downloaded by the kviewpart to a temporary file on 00071 the hard disk, say /tmp/t.dvi. The kviewpart would then call this 00072 method with filename=/tmp/t.dvi and baseURL=http://www.x.x/x.dvi, 00073 so the DVI-renderer knows to interpret the link to t.jpg as 00074 http://www.x.x/t.jpg, and will download the file from there. 00075 00076 @warning This method is virtual only for technical reasons. Do 00077 not re-implement this method 00078 00079 @returns true on success, false on failure 00080 */ 00081 virtual bool openURL(const QString &filename, const KURL &base_url); 00082 00184 virtual void print(); 00185 00186 00187 /* Returns true if the document specifies page sizes, and false 00188 otherwise. NOTE: the information returned by this method is not 00189 always 100% reliable. Although unlikely, it is theoretically 00190 possible that this method returns 'true', but still some of the 00191 sizes returned by sizeOfPage() are invalid. */ 00192 virtual bool hasSpecifiedPageSizes() const {return renderer && renderer->hasSpecifiedPageSizes();} 00193 00194 /* This methos is similar to openFile(). It is used when the "Watch 00195 file" option is activated, and the file has changed on disk. It 00196 differs from openFile() in two aspects: first, the file is 00197 checked for validity with DVIRenderer.isValidFile(m_file) if the 00198 file is invalid, a timer event is used to call the method again 00199 after a brief pause. Secondly, when the GUI is updated, the 00200 implementation does not jump to the first page, but tries to keep 00201 the current page. */ 00202 virtual void reload(); 00203 00204 // Interface definition start ------------------------------------------------ 00205 00217 virtual QStringList fileFormats() const = 0; 00218 00220 virtual bool closeURL(); 00221 00222 /* sets a zoom factor. The multipage implementation might refuse to 00223 use a given zoom factor, even if it falls within the bounds given 00224 by the constants MinZoom and MaxZoom which are defined in 00225 zoomlimits.h. In that case, the multipage implementation chooses a 00226 different zomm factor. The implementation returns the factor which 00227 has actually been used. A default implementation is provided. */ 00228 virtual double setZoom(double z); 00229 00231 virtual void readSettings(); 00232 00234 virtual void writeSettings(); 00235 00237 virtual bool supportsTextSearch() const { return getRenderer() && getRenderer()->supportsTextSearch(); } 00238 00248 virtual bool isModified() const {return false;} 00249 00250 /* Returns the number of the first (i.e. top-left) page in the 00251 display. Such a number cannot be reasonably assigned 00252 (e.g. because the current document is empty, or because no 00253 document has been loaded yet), the method returns "invalid page", 00254 i.e. 0. */ 00255 virtual PageNumber currentPageNumber(); 00256 00257 /* Returns the number of pages in the currently loaded document or 00258 0, if no document is loaded or if the document is empty */ 00259 PageNumber numberOfPages() const {return renderer.isNull() ? (PageNumber)0 : renderer->totalPages();} 00260 00261 /* List of pages selected in the sidebar 00262 00263 @returns a list with the numbers of the currently selected 00264 pages. */ 00265 virtual QValueList<int> selectedPages() {return markList()->selectedPages();} 00266 00267 virtual History* history() { return &document_history; } 00268 00280 virtual void addConfigDialogs(KConfigDialog* configDialog) { Q_UNUSED(configDialog); } 00281 00282 00283 /* These methods calculate the Zoomfactor needed to fit the pages 00284 into the current viewport. Note that the return value need *not* 00285 be within the limits defined in "zoomLimits.h". If they are not, 00286 this indicates that fitting to width or height is currently not 00287 possible (e.g. because no document is loaded). The return value 00288 should then be ignored and any operation that relies on the 00289 return value should be aborted. */ 00290 virtual double calculateFitToWidthZoomValue(); 00291 virtual double calculateFitToHeightZoomValue(); 00292 00293 /* Returns the number of columns into which the widgets are aligned. */ 00294 virtual Q_UINT8 getNrColumns() const { return _scrollView->getNrColumns(); } 00295 virtual Q_UINT8 getNrRows() const { return _scrollView->getNrRows(); } 00296 00297 virtual bool overviewMode() const { return _scrollView->overviewMode(); } 00298 00299 // =========== Interface definition ends 00300 00301 /* --------------------------------------------------------------------- 00302 The following methods export functions of the DocumentPageCache which 00303 are currently needed by KViewPart. TODO: Clean this up again without 00304 directly linking DocumentPageCache to the KViewPart. */ 00305 00306 /* Returns the size of page 'page'. If the document does not 00307 specify a size (which happens, e.g., for some DVI-files), then 00308 the userPreferredSize is returned. */ 00309 virtual SimplePageSize sizeOfPage(const PageNumber& page = 1) const { return pageCache->sizeOfPage(page); } 00310 00311 public slots: 00312 /* Sets the userPreferredSize, which is explained below */ 00313 virtual void setUserPreferredSize(const SimplePageSize& t) { pageCache->setUserPreferredSize(t); } 00314 virtual void setUseDocumentSpecifiedSize(bool b) { pageCache->setUseDocumentSpecifiedSize(b); } 00315 // -------------------------------------------------------------------- 00316 00317 protected: 00336 virtual void setFile(bool success); 00337 00338 /* Creates new instances of DocumentWidget. If you need special 00339 functionality and reimplement the DocumentWidget class, then you 00340 should also reimplement this method to ensure that your new 00341 DocumentWidgets will be used. This function is also the right 00342 place to connect to signals emitted by DocumentWidget. */ 00343 virtual DocumentWidget* createDocumentWidget(); 00344 00345 /* Used to enable/disable KActions of multiPage implementations. 00346 enableActions(true) should be called whenever a file is 00347 successfully loaded. enableActions(false) is called when the 00348 file is closed. */ 00349 virtual void enableActions(bool); 00350 00351 /* Initializes all data structures that need to know the renderer. 00352 This function must be called in the constructor of multipage 00353 implementations. */ 00354 void setRenderer(DocumentRenderer*); 00355 00361 virtual void initializePageCache(); 00362 00363 /* Returns a pointer to the renderer. */ 00364 virtual QGuardedPtr<DocumentRenderer> getRenderer() const { return renderer; } 00365 00366 PageView* scrollView() { return _scrollView; } 00367 00368 MarkList* markList() { return _markList; } 00369 00370 // The next two functions are used for the autozoom feature 00371 // TODO optimize (the calculation of the widest page needs to be done only once 00372 // per document, not everytime calculateFitToWidthZoomValue() is called) 00373 PageNumber widestPage() const; 00374 00375 // TODO Generalize this for more than 2 columns 00376 double zoomForWidthColumns(unsigned int viewportWidth) const; 00377 00378 public slots: 00379 virtual void doSelectAll(); 00380 00381 virtual void clearSelection(); 00382 00383 virtual void copyText(); 00384 00386 virtual void doExportText(); 00387 00388 /* Shows the "text search" dialog, if text search is supported by 00389 the renderer. Otherwise, the method returns immediately. */ 00390 virtual void showFindTextDialog(); 00391 00392 00393 /* This method may be called after the text search dialog 00394 'findDialog' has been set up, and the user has entered a search 00395 phrase. The method searches for the next occurence of the text, 00396 starting from the beginning of the current page, or after the 00397 currently selected text, if there is any. */ 00398 virtual void findNextText(); 00399 00400 /* This method may be called after the text search dialog 00401 'findDialog' has been set up, and the user has entered a search 00402 phrase. The method searches for the next occurence of the text, 00403 starting from the end of the current page, or before the 00404 currently selected text, if there is any. */ 00405 virtual void findPrevText(); 00406 00410 virtual void slotSave(); 00411 00412 /* The standard implementation just calls slotSave. */ 00413 virtual void slotSave_defaultFilename(); 00414 00415 /* Initialize/Update PageWidgets, thumbnail list and bookmark list 00416 00417 This slot is called after a document was loaded, when the 00418 document was modified (e.g. when pages were deleted), or the 00419 rendering mode is changed (e.g. when a different accessibility 00420 viewmode is selected). The following is done 00421 00422 - The page cache is cleared 00423 00424 - all page widgets as well as the thumbnails are updated. 00425 */ 00426 void renderModeChanged(); 00427 00428 /* Empties the page cache and --as the name suggests-- repaints all 00429 visible widgets. */ 00430 void repaintAllVisibleWidgets(); 00431 00432 /* Tells the multipage if scrollbars should be used. */ 00433 virtual void slotShowScrollbars(bool); 00434 00435 /* Show or hide the sidebar widget. */ 00436 virtual void slotShowSidebar(bool); 00437 00438 /* Show or hide thumbnails. */ 00439 virtual void slotShowThumbnails(bool); 00440 00441 /* Used internally. */ 00442 void slotIOJobFinished ( KIO::Job *job ); 00443 00444 /* Switches to fullscreen mode and back. */ 00445 virtual void slotSetFullPage(bool fullpage); 00446 00447 virtual void setViewMode(int); 00448 00449 /* Is called if settings are changed in the configuration dialog. 00450 If this method is reimplemented in a child class, it needs to be 00451 called from there. */ 00452 virtual void preferencesChanged(); 00453 00454 /* Page Navigation. */ 00455 virtual bool gotoPage(const PageNumber& page); 00456 virtual void gotoPage(const Anchor& a); 00457 00458 virtual void prevPage(); 00459 virtual void nextPage(); 00460 virtual void firstPage(); 00461 virtual void lastPage(); 00462 00463 virtual void scrollUp(); 00464 virtual void scrollDown(); 00465 virtual void scrollLeft(); 00466 virtual void scrollRight(); 00467 00468 virtual void scrollUpPage(); 00469 virtual void scrollDownPage(); 00470 virtual void scrollLeftPage(); 00471 virtual void scrollRightPage(); 00472 00473 virtual void readUp(); 00474 virtual void readDown(); 00475 00476 virtual void doGoBack(); 00477 virtual void doGoForward(); 00478 00479 /* Scrolls the main scrollview by deltaInPixel (positive values 00480 scroll DOWN). If the user tries to scroll past the beginning or 00481 the end of a page, then the method either returns without doing 00482 anything (if the current page is the first or last page, resp, or 00483 if the method is called within 200ms after the beg. or end of the 00484 page was reached), or goes the the next/previous page. The delay 00485 makes it a little easier for the user to scroll with the mouse 00486 wheel or the keyboard without involuntarily moving to another 00487 page. */ 00488 virtual void scroll(Q_INT32 deltaInPixel); 00489 00490 virtual void slotEnableMoveTool(bool enable); 00491 00492 protected slots: 00493 virtual bool gotoPage(const PageNumber& page, int y, bool isLink = true); 00494 00495 /* Make the selection visible */ 00496 void gotoPage(const TextSelection&); 00497 00498 private slots: 00499 void handleLocalLink(const QString &linkText); 00500 00501 signals: 00504 void enableMoveTool(bool enable); 00505 00506 /* Emitted when a page has been selected in the MarkList. */ 00507 void selected(const PageNumber& pageNumber); 00508 00509 /* Emitted to indicate the number of pages in the file and the 00510 current page. The receiver will not change or update the display, 00511 nor call the gotoPage()-method. */ 00512 void pageInfo(int nr, int currpg); 00513 00514 void askingToCheckActions(); 00515 00516 /* emitted when a new preview is available */ 00517 void previewChanged(bool previewAvailable); 00518 00519 void viewModeChanged(); 00520 00521 /* Emitted when the zoom of the pageview changes. */ 00522 void zoomChanged(); 00523 00524 void zoomOut(); 00525 void zoomIn(); 00526 00527 /* Emitted it the status of the text selection changes. */ 00528 void textSelected(bool); 00529 00530 void searchEnabled(bool); 00531 00532 // Interface definition end -------------------------------------------------- 00533 00534 public slots: 00535 virtual void generateDocumentWidgets(const PageNumber& startPage = PageNumber::invalidPage); 00536 00537 protected slots: 00538 /* This is the slot where mouseWheel events are processed that come 00539 from the multipage/scrollview. This method calles scroll, a 00540 delta-value of 120 (i.e. one notch on a standard wheel mouse) 00541 scrolls by two 'lines'. */ 00542 void wheelEvent(QWheelEvent *); 00543 00544 protected: 00564 KPrinter *getPrinter(bool enablePageSizeFeatures=true); 00565 00566 00571 QGuardedPtr<QWidget> parentWdg; 00572 00573 QPtrVector<DocumentWidget> widgetList; 00574 00575 History document_history; 00576 00577 /* Variable which is used internally by the method 00578 currentPageNumber() to provide 'lazy' page numbers. */ 00579 PageNumber lastCurrentPage; 00580 00581 /* The pageCache caches already drawn "documentPages" and invokes 00582 the renderer if the needed page is not available in the cache. */ 00583 DocumentPageCache* pageCache; 00584 00585 private slots: 00586 void setCurrentPageNumber(const PageNumber&); 00587 void updateWidgetSize(const PageNumber&); 00588 00589 /* Interrupts a search if one is currently performed, otherwise 00590 hide the search panel */ 00591 void stopSearch(); 00592 00593 private: 00594 /* For internal use by the reload()-method. See the comments in 00595 kmultipage.cpp, right before the timerEvent function. */ 00596 int timer_id; 00597 00598 /* For internal use the reload()-method. This is a dreadful 00599 hack. The problem we adress with this timer event is the 00600 following: the kviewshell has a KDirWatch object which looks at 00601 the DVI file and calls reload() when the object has changed. That 00602 works very nicely in principle, but in practise, when TeX runs 00603 for several seconds over a complicated file, this does not work 00604 at all. First, most of the time, while TeX is still writing, the 00605 file is invalid. Thus, reload() is very often called when the DVI 00606 file is bad. We solve this problem by checking the file first. If 00607 the file is bad, we do not reload. Second, when the file finally 00608 becomes good, it very often happens that KDirWatch does not 00609 notify us anymore. Whether this is a bug or a side effect of a 00610 feature of KDirWatch, I dare not say. We remedy that problem by 00611 using a timer: when reload() was called on a bad file, we 00612 automatically come back (via the timerEvent() function) every 00613 second and check if the file became good. If so, we stop the 00614 timer. It may well happen that KDirWatch calls us several times 00615 while we are waiting for the file to become good, but that does 00616 not do any harm. */ 00617 void timerEvent( QTimerEvent *e ); 00618 00619 /* This method opens a file and sets up the GUI when the file is 00620 loaded. It calls setFile() so that implementations of kmultipage 00621 can update their own GUI. DO NOT REIMPLEMENT THIS METHOD. */ 00622 bool openFile(); 00623 00624 /* Is set by setRenderer. */ 00625 QGuardedPtr<DocumentRenderer> renderer; 00626 00627 PageView *_scrollView; 00628 SearchWidget* searchWidget; 00629 QToolBox* sideBar; 00630 00631 MarkList* _markList; 00632 TableOfContents* tableOfContents; 00633 00634 QSplitter* splitterWidget; 00635 00636 /* This timer is used to implement a brief delay when the user 00637 scrolls past the beginning or the end of the page before a the 00638 program moves to a new page. That way, it is a little easier for 00639 the user to scroll with the mouse wheel or the keyboard without 00640 involuntarily moving to another page. The timer is used in the 00641 scroll() method. */ 00642 QTimer changePageDelayTimer; 00643 00644 // This is set to true while a text search is performed. 00645 // If set to false the search is interrupted. 00646 bool searchInProgress; 00647 }; 00648 00649 00650 #endif