1 //========================================================================
2 //
3 // XpdfViewer.h
4 //
5 // Copyright 2015 Glyph & Cog, LLC
6 //
7 //========================================================================
8 
9 #ifndef XPDFVIEWER_H
10 #define XPDFVIEWER_H
11 
12 #include <aconf.h>
13 
14 #include <QDialog>
15 #include <QIcon>
16 #include <QLocalServer>
17 #include <QMainWindow>
18 #include <QToolButton>
19 #include "gtypes.h"
20 #include "Error.h"
21 #include "XpdfWidget.h"
22 
23 class GString;
24 class GList;
25 class PropertyListAnimation;
26 class QComboBox;
27 class QDialog;
28 class QHBoxLayout;
29 class QInputEvent;
30 class QLabel;
31 class QLineEdit;
32 class QListWidget;
33 class QListWidgetItem;
34 class QMenu;
35 class QModelIndex;
36 class QProgressDialog;
37 class QSignalMapper;
38 class QSplitter;
39 class QStackedLayout;
40 class QStackedWidget;
41 class QTimer;
42 class QToolBar;
43 class QToolButton;
44 class XpdfApp;
45 class XpdfMenuButton;
46 class XpdfTabInfo;
47 class XpdfViewer;
48 
49 //------------------------------------------------------------------------
50 
51 struct XpdfViewerCmd {
52   const char *name;
53   int nArgs;
54   GBool requiresDoc;
55   GBool requiresEvent;
56   void (XpdfViewer::*func)(GString *args[], int nArgs, QInputEvent *event);
57 };
58 
59 //------------------------------------------------------------------------
60 // XpdfMenuButton
61 //------------------------------------------------------------------------
62 
63 class XpdfMenuButton: public QToolButton {
64   Q_OBJECT
65 
66 public:
67 
68   XpdfMenuButton(QMenu *menuA);
69 
70 private slots:
71 
72   void btnPressed();
73 
74 private:
75 
76   QMenu *menu;
77 };
78 
79 //------------------------------------------------------------------------
80 // XpdfErrorWindow
81 //------------------------------------------------------------------------
82 
83 class XpdfErrorWindow: public QWidget {
84   Q_OBJECT
85 
86 public:
87 
88   XpdfErrorWindow(XpdfViewer *viewerA, int errorEventTypeA);
89   virtual ~XpdfErrorWindow();
90   virtual QSize sizeHint() const;
91   virtual void closeEvent(QCloseEvent *event);
92   virtual void keyPressEvent(QKeyEvent *event);
93   virtual void customEvent(QEvent *event);
94 
95 private slots:
96 
97   void clearBtnPressed();
98 
99 private:
100 
101   static void errorCbk(void *data, ErrorCategory category,
102 		       int pos, char *msg);
103   static void dummyErrorCbk(void *data, ErrorCategory category,
104 			    int pos, char *msg);
105 
106   XpdfViewer *viewer;
107   int errorEventType;
108   QListWidget *list;
109   QSize lastSize;
110 };
111 
112 //------------------------------------------------------------------------
113 // XpdfViewer
114 //------------------------------------------------------------------------
115 
116 class XpdfViewer: public QMainWindow {
117   Q_OBJECT
118 
119 public:
120 
121   XpdfViewer(XpdfApp *appA, GBool fullScreen);
122 
123   static XpdfViewer *create(XpdfApp *app, QString fileName, int page,
124 			    QString destName, int rot, QString password,
125 			    GBool fullScreen);
126 
127   virtual ~XpdfViewer();
128 
129   virtual QSize sizeHint() const;
130 
131   void tweakSize();
132 
133   // Open a file in the current tab.  Returns a boolean indicating
134   // success.
135   GBool open(QString fileName, int page, QString destName, int rot,
136 	     QString password);
137 
138   // Open a file in a new tab.  Returns a boolean indicating success.
139   GBool openInNewTab(QString fileName, int page, QString destName,
140 		     int rot, QString password, GBool switchToTab);
141 
142   // Check that [fileName] is open in the current tab -- if not, open
143   // it.  In either case, switch to [page] or [destName].  Returns a
144   // boolean indicating success.
145   GBool checkOpen(QString fileName, int page, QString destName,
146 		  QString password);
147 
148   virtual QMenu *createPopupMenu();
149 
150   // Start up the remote server socket.
151   void startRemoteServer(const QString &remoteServerName);
152 
153   // Execute a command [cmd], with [event] for context.
154   void execCmd(const char *cmd, QInputEvent *event);
155 
156 private slots:
157 
158   void remoteServerConnection();
159   void remoteServerRead();
160 
161   void pdfResized();
162   void pdfPaintDone(bool finished);
163   void preLoad();
164   void postLoad();
165   void keyPress(QKeyEvent *e);
166   void mousePress(QMouseEvent *e);
167   void mouseRelease(QMouseEvent *e);
168   void mouseClick(QMouseEvent *e);
169   void mouseDoubleClick(QMouseEvent *e);
170   void mouseTripleClick(QMouseEvent *e);
171   void mouseWheel(QWheelEvent *e);
172   void mouseMove(QMouseEvent *e);
173   void pageChange(int pg);
174   void sidebarSplitterMoved(int pos, int index);
175 #if XPDFWIDGET_PRINTING
176   void printStatus(int nextPage, int firstPage, int lastPage);
177   void cancelPrint();
178 #endif
179 
180   void openMenuAction();
181   void openInNewWinMenuAction();
182   void reloadMenuAction();
183   void saveAsMenuAction();
184   void saveImageMenuAction();
185 #if XPDFWIDGET_PRINTING
186   void printMenuAction();
187 #endif
188   void quitMenuAction();
189   void copyMenuAction();
190   void singlePageModeMenuAction();
191   void continuousModeMenuAction();
192   void sideBySideSingleModeMenuAction();
193   void sideBySideContinuousModeMenuAction();
194   void horizontalContinuousModeMenuAction();
195   void fullScreenMenuAction(bool checked);
196   void rotateClockwiseMenuAction();
197   void rotateCounterclockwiseMenuAction();
198   void zoomToSelectionMenuAction();
199   void toggleToolbarMenuAction(bool checked);
200   void toggleSidebarMenuAction(bool checked);
201   void viewPageLabelsMenuAction(bool checked);
202   void newTabMenuAction();
203   void newWindowMenuAction();
204   void closeTabMenuAction();
205   void closeWindowMenuAction();
206   void openErrorWindowMenuAction();
207   void helpMenuAction();
208   void keyBindingsMenuAction();
209   void aboutMenuAction();
210 
211   void popupMenuAction(int idx);
212 
213   void toggleSidebarButtonPressed();
214   void pageNumberChanged();
215   void backButtonPressed();
216   void forwardButtonPressed();
217   void zoomOutButtonPressed();
218   void zoomInButtonPressed();
219   void zoomIndexChanged(const QString &zoomText);
220   void zoomEditingFinished();
221   void fitWidthButtonPressed();
222   void fitPageButtonPressed();
223   void selectModeButtonPressed();
224   void statusIndicatorPressed();
225   void findTextChanged();
226   void findNextButtonPressed();
227   void findPrevButtonPressed();
228   void newTabButtonPressed();
229 
230   void switchTab(QListWidgetItem *current, QListWidgetItem *previous);
231   void infoComboBoxChanged(int idx);
232   void outlineItemClicked(const QModelIndex& idx);
233   void layerItemClicked(const QModelIndex& idx);
234   void attachmentSaveClicked(int idx);
235 
236   void clearFindError();
237 
238 private:
239 
240   friend class XpdfErrorWindow;
241 
242   //--- commands
243   int mouseX(QInputEvent *event);
244   int mouseY(QInputEvent *event);
245   void cmdAbout(GString *args[], int nArgs, QInputEvent *event);
246   void cmdBlockSelectMode(GString *args[], int nArgs, QInputEvent *event);
247   void cmdCheckOpenFile(GString *args[], int nArgs, QInputEvent *event);
248   void cmdCheckOpenFileAtDest(GString *args[], int nArgs, QInputEvent *event);
249   void cmdCheckOpenFileAtPage(GString *args[], int nArgs, QInputEvent *event);
250   void cmdCloseTabOrQuit(GString *args[], int nArgs, QInputEvent *event);
251   void cmdCloseSidebar(GString *args[], int nArgs, QInputEvent *event);
252   void cmdCloseSidebarMoveResizeWin(GString *args[], int nArgs, QInputEvent *event);
253   void cmdCloseSidebarResizeWin(GString *args[], int nArgs, QInputEvent *event);
254   void cmdCloseWindowOrQuit(GString *args[], int nArgs, QInputEvent *event);
255   void cmdContinuousMode(GString *args[], int nArgs, QInputEvent *event);
256   void cmdCopy(GString *args[], int nArgs, QInputEvent *event);
257   void cmdCopyLinkTarget(GString *args[], int nArgs, QInputEvent *event);
258 #if 0 // for debugging
259   void cmdDebug1(GString *args[], int nArgs, QInputEvent *event);
260 #endif
261   void cmdEndPan(GString *args[], int nArgs, QInputEvent *event);
262   void cmdEndSelection(GString *args[], int nArgs, QInputEvent *event);
263   void cmdExpandSidebar(GString *args[], int nArgs, QInputEvent *event);
264   void cmdFind(GString *args[], int nArgs, QInputEvent *event);
265   void cmdFindFirst(GString *args[], int nArgs, QInputEvent *event);
266   void cmdFindNext(GString *args[], int nArgs, QInputEvent *event);
267   void cmdFindPrevious(GString *args[], int nArgs, QInputEvent *event);
268   void cmdFocusToDocWin(GString *args[], int nArgs, QInputEvent *event);
269   void cmdFocusToPageNum(GString *args[], int nArgs, QInputEvent *event);
270   void cmdFollowLink(GString *args[], int nArgs, QInputEvent *event);
271   void cmdFollowLinkInNewTab(GString *args[], int nArgs, QInputEvent *event);
272   void cmdFollowLinkInNewTabNoSel(GString *args[], int nArgs, QInputEvent *event);
273   void cmdFollowLinkInNewWin(GString *args[], int nArgs, QInputEvent *event);
274   void cmdFollowLinkInNewWinNoSel(GString *args[], int nArgs, QInputEvent *event);
275   void cmdFollowLinkNoSel(GString *args[], int nArgs, QInputEvent *event);
276   void cmdFullScreenMode(GString *args[], int nArgs, QInputEvent *event);
277   void cmdGoBackward(GString *args[], int nArgs, QInputEvent *event);
278   void cmdGoForward(GString *args[], int nArgs, QInputEvent *event);
279   void cmdGotoDest(GString *args[], int nArgs, QInputEvent *event);
280   void cmdGotoLastPage(GString *args[], int nArgs, QInputEvent *event);
281   void cmdGotoPage(GString *args[], int nArgs, QInputEvent *event);
282   void cmdHelp(GString *args[], int nArgs, QInputEvent *event);
283   void cmdHideToolbar(GString *args[], int nArgs, QInputEvent *event);
284   void cmdHorizontalContinuousMode(GString *args[], int nArgs, QInputEvent *event);
285   void cmdLinearSelectMode(GString *args[], int nArgs, QInputEvent *event);
286   void cmdLoadTabState(GString *args[], int nArgs, QInputEvent *event);
287   void cmdNewTab(GString *args[], int nArgs, QInputEvent *event);
288   void cmdNewWindow(GString *args[], int nArgs, QInputEvent *event);
289   void cmdNextPage(GString *args[], int nArgs, QInputEvent *event);
290   void cmdNextPageNoScroll(GString *args[], int nArgs, QInputEvent *event);
291   void cmdNextTab(GString *args[], int nArgs, QInputEvent *event);
292   void cmdOpen(GString *args[], int nArgs, QInputEvent *event);
293   void cmdOpenErrorWindow(GString *args[], int nArgs, QInputEvent *event);
294   void cmdOpenFile(GString *args[], int nArgs, QInputEvent *event);
295   void cmdOpenFileAtDest(GString *args[], int nArgs, QInputEvent *event);
296   void cmdOpenFileAtDestIn(GString *args[], int nArgs, QInputEvent *event);
297   void cmdOpenFileAtPage(GString *args[], int nArgs, QInputEvent *event);
298   void cmdOpenFileAtPageIn(GString *args[], int nArgs, QInputEvent *event);
299   void cmdOpenFileIn(GString *args[], int nArgs, QInputEvent *event);
300   void cmdOpenIn(GString *args[], int nArgs, QInputEvent *event);
301   void cmdOpenSidebar(GString *args[], int nArgs, QInputEvent *event);
302   void cmdOpenSidebarMoveResizeWin(GString *args[], int nArgs, QInputEvent *event);
303   void cmdOpenSidebarResizeWin(GString *args[], int nArgs, QInputEvent *event);
304   void cmdPageDown(GString *args[], int nArgs, QInputEvent *event);
305   void cmdPageUp(GString *args[], int nArgs, QInputEvent *event);
306   void cmdPostPopupMenu(GString *args[], int nArgs, QInputEvent *event);
307   void cmdPrevPage(GString *args[], int nArgs, QInputEvent *event);
308   void cmdPrevPageNoScroll(GString *args[], int nArgs, QInputEvent *event);
309   void cmdPrevTab(GString *args[], int nArgs, QInputEvent *event);
310 #if XPDFWIDGET_PRINTING
311   void cmdPrint(GString *args[], int nArgs, QInputEvent *event);
312 #endif
313   void cmdQuit(GString *args[], int nArgs, QInputEvent *event);
314   void cmdRaise(GString *args[], int nArgs, QInputEvent *event);
315   void cmdReload(GString *args[], int nArgs, QInputEvent *event);
316   void cmdRotateCW(GString *args[], int nArgs, QInputEvent *event);
317   void cmdRotateCCW(GString *args[], int nArgs, QInputEvent *event);
318   void cmdRun(GString *args[], int nArgs, QInputEvent *event);
319   void cmdSaveAs(GString *args[], int nArgs, QInputEvent *event);
320   void cmdSaveImage(GString *args[], int nArgs, QInputEvent *event);
321   void cmdSaveTabState(GString *args[], int nArgs, QInputEvent *event);
322   void cmdScrollDown(GString *args[], int nArgs, QInputEvent *event);
323   void cmdScrollDownNextPage(GString *args[], int nArgs, QInputEvent *event);
324   void cmdScrollLeft(GString *args[], int nArgs, QInputEvent *event);
325   void cmdScrollOutlineDown(GString *args[], int nArgs, QInputEvent *event);
326   void cmdScrollOutlineUp(GString *args[], int nArgs, QInputEvent *event);
327   void cmdScrollRight(GString *args[], int nArgs, QInputEvent *event);
328   void cmdScrollToBottomEdge(GString *args[], int nArgs, QInputEvent *event);
329   void cmdScrollToBottomRight(GString *args[], int nArgs, QInputEvent *event);
330   void cmdScrollToLeftEdge(GString *args[], int nArgs, QInputEvent *event);
331   void cmdScrollToRightEdge(GString *args[], int nArgs, QInputEvent *event);
332   void cmdScrollToTopEdge(GString *args[], int nArgs, QInputEvent *event);
333   void cmdScrollToTopLeft(GString *args[], int nArgs, QInputEvent *event);
334   void cmdScrollUp(GString *args[], int nArgs, QInputEvent *event);
335   void cmdScrollUpPrevPage(GString *args[], int nArgs, QInputEvent *event);
336   void cmdSelectLine(GString *args[], int nArgs, QInputEvent *event);
337   void cmdSelectWord(GString *args[], int nArgs, QInputEvent *event);
338   void cmdSetSelection(GString *args[], int nArgs, QInputEvent *event);
339   void cmdShowKeyBindings(GString *args[], int nArgs, QInputEvent *event);
340   void cmdShowToolbar(GString *args[], int nArgs, QInputEvent *event);
341   void cmdShrinkSidebar(GString *args[], int nArgs, QInputEvent *event);
342   void cmdSideBySideContinuousMode(GString *args[], int nArgs, QInputEvent *event);
343   void cmdSideBySideSingleMode(GString *args[], int nArgs, QInputEvent *event);
344   void cmdSinglePageMode(GString *args[], int nArgs, QInputEvent *event);
345   void cmdStartExtendedSelection(GString *args[], int nArgs, QInputEvent *event);
346   void cmdStartPan(GString *args[], int nArgs, QInputEvent *event);
347   void cmdStartSelection(GString *args[], int nArgs, QInputEvent *event);
348   void cmdToggleContinuousMode(GString *args[], int nArgs, QInputEvent *event);
349   void cmdToggleFullScreenMode(GString *args[], int nArgs, QInputEvent *event);
350   void cmdToggleSelectMode(GString *args[], int nArgs, QInputEvent *event);
351   void cmdToggleSidebar(GString *args[], int nArgs, QInputEvent *event);
352   void cmdToggleSidebarMoveResizeWin(GString *args[], int nArgs, QInputEvent *event);
353   void cmdToggleSidebarResizeWin(GString *args[], int nArgs, QInputEvent *event);
354   void cmdToggleToolbar(GString *args[], int nArgs, QInputEvent *event);
355   void cmdViewPageLabels(GString *args[], int nArgs, QInputEvent *event);
356   void cmdViewPageNumbers(GString *args[], int nArgs, QInputEvent *event);
357   void cmdWindowMode(GString *args[], int nArgs, QInputEvent *event);
358   void cmdZoomFitPage(GString *args[], int nArgs, QInputEvent *event);
359   void cmdZoomFitWidth(GString *args[], int nArgs, QInputEvent *event);
360   void cmdZoomIn(GString *args[], int nArgs, QInputEvent *event);
361   void cmdZoomOut(GString *args[], int nArgs, QInputEvent *event);
362   void cmdZoomPercent(GString *args[], int nArgs, QInputEvent *event);
363   void cmdZoomToSelection(GString *args[], int nArgs, QInputEvent *event);
364   int scaleScroll(int delta);
365   void followLink(QInputEvent *event, GBool onlyIfNoSel,
366 		  GBool newTab, GBool newWindow);
367 
368   //--- GUI events
369   int getModifiers(Qt::KeyboardModifiers qtMods);
370   int getContext(Qt::KeyboardModifiers qtMods);
371   int getMouseButton(Qt::MouseButton qtBtn);
372   virtual void keyPressEvent(QKeyEvent *e);
373   virtual void dragEnterEvent(QDragEnterEvent *e);
374   virtual void dropEvent(QDropEvent *e);
375   virtual bool eventFilter(QObject *watched, QEvent *event);
376 
377   //--- GUI setup
378   void createWindow();
379   void createToolBar();
380   QToolButton *addToolBarButton(const QIcon &icon,
381 				const char *slot, const char *tip);
382   XpdfMenuButton *addToolBarMenuButton(const QIcon &icon,
383 				       const char *tip, QMenu *menu);
384   void addToolBarSeparator();
385   void addToolBarSpacing(int w);
386   void addToolBarStretch();
387   void createMainMenu();
388   void createXpdfPopupMenu();
389   QWidget *createTabPane();
390   QWidget *createInfoPane();
391   void updateInfoPane();
392   void destroyWindow();
393   void enterFullScreenMode();
394   void exitFullScreenMode();
395   void addTab();
396   void closeTab(XpdfTabInfo *tab);
397   void gotoTab(int idx);
398   void updateModeInfo();
399   void updateZoomInfo();
400   void updateSelectModeInfo();
401   void updateDocInfo();
402   void updatePageNumberOrLabel(int pg);
403   void updateOutline(int pg);
404   void setOutlineOpenItems(const QModelIndex &idx);
405   void fillAttachmentList();
406   void statusIndicatorStart();
407   void statusIndicatorStop();
408   void statusIndicatorOk();
409   void statusIndicatorError();
410   void showFindError();
411   void createKeyBindingsDialog();
412   QString createKeyBindingsHTML();
413   void createAboutDialog();
414   void execSaveImageDialog();
415 
416   static XpdfViewerCmd cmdTab[];
417 
418   XpdfApp *app;
419 
420   // menu
421   QMenuBar *mainMenu;
422   QMenu *displayModeSubmenu;
423   QAction *fullScreenMenuItem;
424   QAction *toggleToolbarMenuItem;
425   QAction *toggleSidebarMenuItem;
426   QAction *viewPageLabelsMenuItem;
427 
428   // popup menu
429   QMenu *popupMenu;
430   QSignalMapper *popupMenuSignalMapper;
431 
432   // toolbar
433   int toolBarFontSize;		// used for HiDPI scaling
434   QToolBar *toolBar;
435   QLineEdit *pageNumber;
436   QLabel *pageCount;
437   QComboBox *zoomComboBox;
438   QToolButton *fitWidthBtn;
439   QToolButton *fitPageBtn;
440   QToolButton *selectModeBtn;
441   PropertyListAnimation *indicatorAnimation;
442   QList<QVariant> indicatorIcons;
443   QList<QVariant> indicatorErrIcons;
444   QLineEdit *findEdit;
445   QAction *findCaseSensitiveAction;
446   QAction *findWholeWordsAction;
447 
448   // sidebar pane
449   QSplitter *sidebarSplitter;
450   int initialSidebarWidth;
451   int sidebarWidth;
452   QListWidget *tabList;
453   QComboBox *infoComboBox;
454   QStackedLayout *infoStack;
455 
456   // viewer pane
457   QStackedWidget *viewerStack;
458 
459   QLabel *linkTargetBar;
460   QString linkTargetInfo;
461 
462   GList *tabInfo;		// [XpdfTabInfo]
463   XpdfTabInfo *currentTab;
464 
465   double scaleFactor;
466 
467   XpdfWidget::DisplayMode fullScreenPreviousDisplayMode;
468   double fullScreenPreviousZoom;
469 
470   QTimer *findErrorTimer;
471 
472   XpdfErrorWindow *errorWindow;
473   QDialog *keyBindingsDialog;
474   QDialog *aboutDialog;
475 #if XPDFWIDGET_PRINTING
476   QProgressDialog *printStatusDialog;
477 #endif
478 
479   QString lastFileOpened;
480 
481   QLocalServer *remoteServer;
482 };
483 
484 #endif
485