├── po ├── ar.gmo ├── ca.gmo ├── cs.gmo ├── de.gmo ├── el.gmo ├── es.gmo ├── eu.gmo ├── fr.gmo ├── gl.gmo ├── he.gmo ├── hu.gmo ├── it.gmo ├── ja.gmo ├── nl.gmo ├── pl.gmo ├── pt.gmo ├── ru.gmo ├── sv.gmo ├── vi.gmo ├── pt_BR.gmo ├── zh_CN.gmo ├── zh_TW.gmo ├── LINGUAS ├── meson.build ├── POTFILES.in └── Makevars ├── tests ├── test1.pdf ├── test2.pdf ├── test_encrypted.pdf ├── Utils.h ├── meson.build ├── Utils.cxx ├── DumbPreferencesView.h ├── PreferencesPterTest.h ├── DocumentOutlineTest.h ├── DumbPreferencesView.cxx ├── PrintPterTest.h ├── PagePterTest.h ├── FindPterTest.h ├── main.cxx ├── DumbPageView.h ├── DumbFindView.h ├── ConfigTest.h ├── DumbPageView.cxx ├── DumbDocument.h ├── PDFDocumentTest.h ├── PreferencesPterTest.cxx ├── DumbFindView.cxx ├── DumbDocumentObserver.h ├── DumbPrintView.h ├── MainPterTest.h ├── PrintPterTest.cxx └── DumbDocument.cxx ├── data ├── stock_rotate-90.png ├── icon_epdfview-24.png ├── icon_epdfview-32.png ├── icon_epdfview-48.png ├── stock_rotate-270.png ├── stock_find_next_24.png ├── stock_find_previous_24.png ├── stock_zoom-page-width.png ├── epdfview-ui-print.xml ├── epdfview.desktop.in ├── dot.latexmkrc ├── bsd.latexmkrc ├── epdfview.desktop ├── epdfview.1 ├── README.md ├── epdfsync ├── meson.build └── epdfview-ui.xml ├── ChangeLog ├── meson_options.txt ├── AUTHORS ├── .travis.yml ├── src ├── gtk │ ├── meson.build │ ├── PreferencesView.h │ ├── StockIcons.h │ ├── FindView.h │ └── StockIcons.cxx ├── meson.build ├── DocumentLinkUri.h ├── DocumentLinkGoto.h ├── PreferencesPter.h ├── IDocumentLink.h ├── PreferencesPter.cxx ├── epdfview.h ├── DocumentLinkGoto.cxx ├── JobSave.h ├── PrintPter.h ├── DocumentRectangle.h ├── IDocumentLink.cxx ├── JobRender.h ├── JobLoad.h ├── DocumentLinkUri.cxx ├── FindPter.h ├── IJob.h ├── IPreferencesView.h ├── DocumentOutline.h ├── DocumentPage.h ├── DocumentRectangle.cxx ├── PDFDocument.h ├── IJob.cxx ├── PagePter.h ├── JobFind.h ├── gettext.h ├── JobPrint.h └── IFindView.h ├── snap └── snapcraft.yaml ├── .kiro ├── steering │ ├── product.md │ ├── tech.md │ └── structure.md └── specs │ └── gtk4-meson-migration │ └── requirements.md ├── .gitignore ├── .gitattributes ├── STATUS.md ├── BUILD_WINDOWS.md ├── .github └── workflows │ └── build.yml ├── docs ├── README.md ├── CRITICAL_BUG_FIXES.md ├── CI_FIXES_2025-11-12.md ├── DOCUMENTATION.md └── PRINT_MIGRATION_TODO.md ├── meson.build ├── THANKS ├── RUN_EPDFVIEW_WSL.md └── INSTALL /po/ar.gmo: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JotaRandom/epdfview/HEAD/po/ar.gmo -------------------------------------------------------------------------------- /po/ca.gmo: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JotaRandom/epdfview/HEAD/po/ca.gmo -------------------------------------------------------------------------------- /po/cs.gmo: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JotaRandom/epdfview/HEAD/po/cs.gmo -------------------------------------------------------------------------------- /po/de.gmo: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JotaRandom/epdfview/HEAD/po/de.gmo -------------------------------------------------------------------------------- /po/el.gmo: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JotaRandom/epdfview/HEAD/po/el.gmo -------------------------------------------------------------------------------- /po/es.gmo: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JotaRandom/epdfview/HEAD/po/es.gmo -------------------------------------------------------------------------------- /po/eu.gmo: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JotaRandom/epdfview/HEAD/po/eu.gmo -------------------------------------------------------------------------------- /po/fr.gmo: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JotaRandom/epdfview/HEAD/po/fr.gmo -------------------------------------------------------------------------------- /po/gl.gmo: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JotaRandom/epdfview/HEAD/po/gl.gmo -------------------------------------------------------------------------------- /po/he.gmo: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JotaRandom/epdfview/HEAD/po/he.gmo -------------------------------------------------------------------------------- /po/hu.gmo: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JotaRandom/epdfview/HEAD/po/hu.gmo -------------------------------------------------------------------------------- /po/it.gmo: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JotaRandom/epdfview/HEAD/po/it.gmo -------------------------------------------------------------------------------- /po/ja.gmo: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JotaRandom/epdfview/HEAD/po/ja.gmo -------------------------------------------------------------------------------- /po/nl.gmo: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JotaRandom/epdfview/HEAD/po/nl.gmo -------------------------------------------------------------------------------- /po/pl.gmo: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JotaRandom/epdfview/HEAD/po/pl.gmo -------------------------------------------------------------------------------- /po/pt.gmo: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JotaRandom/epdfview/HEAD/po/pt.gmo -------------------------------------------------------------------------------- /po/ru.gmo: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JotaRandom/epdfview/HEAD/po/ru.gmo -------------------------------------------------------------------------------- /po/sv.gmo: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JotaRandom/epdfview/HEAD/po/sv.gmo -------------------------------------------------------------------------------- /po/vi.gmo: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JotaRandom/epdfview/HEAD/po/vi.gmo -------------------------------------------------------------------------------- /po/pt_BR.gmo: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JotaRandom/epdfview/HEAD/po/pt_BR.gmo -------------------------------------------------------------------------------- /po/zh_CN.gmo: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JotaRandom/epdfview/HEAD/po/zh_CN.gmo -------------------------------------------------------------------------------- /po/zh_TW.gmo: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JotaRandom/epdfview/HEAD/po/zh_TW.gmo -------------------------------------------------------------------------------- /tests/test1.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JotaRandom/epdfview/HEAD/tests/test1.pdf -------------------------------------------------------------------------------- /tests/test2.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JotaRandom/epdfview/HEAD/tests/test2.pdf -------------------------------------------------------------------------------- /data/stock_rotate-90.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JotaRandom/epdfview/HEAD/data/stock_rotate-90.png -------------------------------------------------------------------------------- /tests/test_encrypted.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JotaRandom/epdfview/HEAD/tests/test_encrypted.pdf -------------------------------------------------------------------------------- /data/icon_epdfview-24.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JotaRandom/epdfview/HEAD/data/icon_epdfview-24.png -------------------------------------------------------------------------------- /data/icon_epdfview-32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JotaRandom/epdfview/HEAD/data/icon_epdfview-32.png -------------------------------------------------------------------------------- /data/icon_epdfview-48.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JotaRandom/epdfview/HEAD/data/icon_epdfview-48.png -------------------------------------------------------------------------------- /data/stock_rotate-270.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JotaRandom/epdfview/HEAD/data/stock_rotate-270.png -------------------------------------------------------------------------------- /data/stock_find_next_24.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JotaRandom/epdfview/HEAD/data/stock_find_next_24.png -------------------------------------------------------------------------------- /data/stock_find_previous_24.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JotaRandom/epdfview/HEAD/data/stock_find_previous_24.png -------------------------------------------------------------------------------- /data/stock_zoom-page-width.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JotaRandom/epdfview/HEAD/data/stock_zoom-page-width.png -------------------------------------------------------------------------------- /po/LINGUAS: -------------------------------------------------------------------------------- 1 | # Set of available languages. 2 | ar ca cs de el es eu fr gl hu he it ja nl pl pt_BR pt ru sv vi zh_CN zh_TW 3 | -------------------------------------------------------------------------------- /ChangeLog: -------------------------------------------------------------------------------- 1 | epdfview 0.2: 2 | 3 | * Forked https://github.com/jristz/epdfview - and remerged with changes 4 | * Included Ctrl-Button1Down handler 5 | * Included SIGHUP handler 6 | -------------------------------------------------------------------------------- /meson_options.txt: -------------------------------------------------------------------------------- 1 | option('tests', type: 'boolean', value: false, description: 'Build test suite') 2 | option('cups', type: 'feature', value: 'auto', description: 'Enable CUPS printing support') -------------------------------------------------------------------------------- /po/meson.build: -------------------------------------------------------------------------------- 1 | i18n = import('i18n') 2 | 3 | # Define gettext domain 4 | i18n.gettext('epdfview', 5 | preset: 'glib', 6 | args: [ 7 | '--keyword=_', 8 | '--keyword=N_', 9 | '--from-code=UTF-8' 10 | ] 11 | ) -------------------------------------------------------------------------------- /AUTHORS: -------------------------------------------------------------------------------- 1 | ePDFView is copyright © 2006-2011 Emma's Software. 2 | Jordi Fita 3 | 4 | 5 | ePDFView is copyright © 2014-2025 Pablo Lezaeta 6 | 7 | Contributors: 8 | Pedro A. Aranda Gutiérrez 9 | 10 | ePDFView is under the GPLv2+. 11 | -------------------------------------------------------------------------------- /data/epdfview-ui-print.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /data/epdfview.desktop.in: -------------------------------------------------------------------------------- 1 | [Desktop Entry] 2 | Name=ePDFView 3 | GenericName=PDF Viewer 4 | Comment=View PDF documents 5 | Exec=epdfview %f 6 | Icon=epdfview 7 | Terminal=false 8 | Type=Application 9 | MimeType=application/pdf;application/x-pdf; 10 | Categories=Office;Viewer; 11 | Keywords=PDF;Viewer; -------------------------------------------------------------------------------- /data/dot.latexmkrc: -------------------------------------------------------------------------------- 1 | $postscript_mode = $dvi_mode = 0; 2 | $pdf_mode = 1; 3 | $pdf_previewer = 'start epdfview'; 4 | $new_viewer_always = 0; 5 | $pdf_update_method = 2; 6 | ## $pdf_update_signal = "HUP"; ## default 7 | $pdflatex = 'pdflatex -synctex=1 %O %S'; 8 | $bibtex_use = 2; 9 | ## $diagnostics = 1; 10 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: cpp 2 | dist: focal 3 | 4 | before_install: 5 | - sudo apt-get update -qq 6 | - sudo apt-get install -y meson ninja-build libgtk-4-dev libpoppler-glib-dev libcups2-dev gettext 7 | 8 | script: 9 | - meson setup builddir 10 | - cd builddir 11 | - ninja 12 | - ninja test 13 | 14 | notifications: 15 | email: false 16 | -------------------------------------------------------------------------------- /data/bsd.latexmkrc: -------------------------------------------------------------------------------- 1 | $postscript_mode = $dvi_mode = 0; 2 | $pdf_mode = 1; 3 | $pdf_previewer = 'start epdfview'; 4 | $new_viewer_always = 0; 5 | $pdf_update_method = 2; 6 | ## $pdf_update_signal = "HUP"; ## default 7 | $pdflatex = 'pdflatex -synctex=1 %O %S'; 8 | $bibtex_use = 2; 9 | ## $diagnostics = 1; 10 | $pscmd = 'ps -f -U $USER'; 11 | $pid_position = 0; 12 | -------------------------------------------------------------------------------- /po/POTFILES.in: -------------------------------------------------------------------------------- 1 | # List of source files which contain translatable strings. 2 | src/Config.cxx 3 | src/FindPter.cxx 4 | src/IDocument.cxx 5 | src/main.cxx 6 | src/MainPter.cxx 7 | src/PagePter.cxx 8 | src/PrintPter.cxx 9 | src/PDFDocument.cxx 10 | # GTK4 UI 11 | src/gtk/FindView.cxx 12 | src/gtk/MainView.cxx 13 | src/gtk/PreferencesView.cxx 14 | src/gtk/PrintView.cxx 15 | src/gtk/StockIcons.cxx 16 | -------------------------------------------------------------------------------- /src/gtk/meson.build: -------------------------------------------------------------------------------- 1 | gtk_sources = [ 2 | join_paths(meson.current_source_dir(), 'FindView.cxx'), 3 | join_paths(meson.current_source_dir(), 'MainView.cxx'), 4 | join_paths(meson.current_source_dir(), 'PageView.cxx'), 5 | join_paths(meson.current_source_dir(), 'PreferencesView.cxx'), 6 | join_paths(meson.current_source_dir(), 'PrintView.cxx'), 7 | join_paths(meson.current_source_dir(), 'StockIcons.cxx'), 8 | ] -------------------------------------------------------------------------------- /data/epdfview.desktop: -------------------------------------------------------------------------------- 1 | [Desktop Entry] 2 | Categories=Viewer;Office;GTK;Graphics;Viewer; 3 | Comment=Lightweight PDF document viewer 4 | Comment[ca]=Visor de documents PDF lleuger 5 | Comment[es]=Visor de documentos PDF ligero 6 | Exec=epdfview %f 7 | GenericName=PDF Viewer 8 | GenericName[ca]=Visor PDF 9 | GenericName[es]=Visor PDF 10 | Icon=/usr/share/epdfview/extra/epdfview.svg 11 | Name=ePDFViewer 12 | Name[ca]=ePDFViewer 13 | Name[es]=ePDFViewer 14 | MimeType=application/pdf; 15 | Terminal=false 16 | Type=Application 17 | -------------------------------------------------------------------------------- /snap/snapcraft.yaml: -------------------------------------------------------------------------------- 1 | 2 | name: epdfview-git # you probably want to 'snapcraft register ' 3 | version: '0.1.8.r43-1' # just for humans, typically '1.2+git' or '1.3.2' 4 | summary: Single-line elevator pitch for your amazing snap # 79 char long summary 5 | description: 6 | Lightweight PDF document viewer. 7 | 8 | grade: devel # must be 'stable' to release into candidate/stable channels 9 | confinement: devmode # use 'strict' once you have the right plugs and slots 10 | 11 | parts: 12 | my-part: 13 | # See 'snapcraft plugins' 14 | plugin: nil 15 | 16 | options: 17 | source: 18 | required: true 19 | 20 | -------------------------------------------------------------------------------- /.kiro/steering/product.md: -------------------------------------------------------------------------------- 1 | # ePDFView Product Overview 2 | 3 | ePDFView is a free, lightweight PDF document viewer built with GTK4 and the Poppler library. It provides essential PDF viewing functionality with a clean, minimal interface. 4 | 5 | ## Core Features 6 | 7 | - Continuous view mode for seamless document reading 8 | - Multiple zoom modes (fit to page width, fit to page, custom zoom) 9 | - Page rotation (left/right) 10 | - Text search within documents 11 | - Print support via CUPS (Unix/Linux systems) 12 | - Bookmarks and outline navigation 13 | - Keyboard shortcuts for common operations 14 | - Full-screen viewing mode 15 | 16 | ## Target Users 17 | 18 | Desktop users who need a simple, fast PDF viewer without the complexity of full-featured PDF editors. Particularly suited for Linux/Unix environments where lightweight applications are preferred. 19 | 20 | ## License 21 | 22 | GNU General Public License v2 - open source software that can be freely redistributed and modified. -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Build directories 2 | builddir/ 3 | builddir_clean/ 4 | builddir_new/ 5 | build/ 6 | build-windows/ 7 | .build/ 8 | .idea 9 | 10 | # Meson generated files 11 | config.h 12 | 13 | # Compiled binaries 14 | *.o 15 | *.lo 16 | *.la 17 | *.so 18 | *.so.* 19 | *.a 20 | *.exe 21 | *.dll 22 | *.lib 23 | *.obj 24 | *.pdb 25 | epdfview 26 | 27 | # Generated files 28 | *.gmo 29 | *.pot 30 | POTFILES 31 | 32 | # IDE and editor files 33 | .vscode/ 34 | .idea/ 35 | *.swp 36 | *.swo 37 | *~ 38 | .DS_Store 39 | 40 | # Windows specific 41 | Thumbs.db 42 | desktop.ini 43 | *.stackdump 44 | 45 | # Debug files 46 | *.dSYM/ 47 | core 48 | vgcore.* 49 | 50 | # Package files 51 | *.deb 52 | *.rpm 53 | *.tar.gz 54 | *.tar.bz2 55 | *.tar.xz 56 | *.zip 57 | 58 | # Test files 59 | test-results/ 60 | *.log 61 | 62 | # Debug files 63 | *.gdb 64 | *.gdbinit 65 | *.gdb.* 66 | 67 | # Test scripts (but keep build scripts!) 68 | test*.sh 69 | -------------------------------------------------------------------------------- /tests/Utils.h: -------------------------------------------------------------------------------- 1 | // ePDFView - A lightweight PDF Viewer. 2 | // Copyright (C) 2006-2011 Emma's Software. 3 | // Copyright (C) 2014-2025 Pablo Lezaeta 4 | // Copyright (C) 2014 Pedro A. Aranda Gutiérrez 5 | 6 | // ePDFView - Test Util Functions. 7 | // 8 | // 9 | // This program is free software; you can redistribute it and/or modify 10 | // it under the terms of the GNU General Public License as published by 11 | // the Free Software Foundation; either version 2 of the License, or 12 | // (at your option) any later version. 13 | // 14 | // This program is distributed in the hope that it will be useful, 15 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 16 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 | // GNU General Public License for more details. 18 | // 19 | // You should have received a copy of the GNU General Public License 20 | // along with this program; if not, write to the Free Software 21 | // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 22 | 23 | #if !defined (__UTILS_TEST_H__) 24 | #define __UTILS_TEST_H__ 25 | 26 | gchar *getTestFile (const gchar *fileName); 27 | 28 | #endif // !__UTILS_TEST_H__ 29 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | # Set default behavior for line endings 2 | * text=lf 3 | 4 | # Explicitly declare text files you want to always be normalized and converted 5 | # to native line endings on checkout 6 | *.c text 7 | *.cxx text 8 | *.cpp text 9 | *.h text 10 | *.hpp text 11 | *.am text 12 | *.ac text 13 | *.in text 14 | *.m4 text 15 | *.sh text 16 | *.py text 17 | *.pl text 18 | *.md text 19 | *.txt text 20 | *.xml text 21 | *.desktop text 22 | *.po text 23 | *.pot text 24 | 25 | # Declare files that will always have CRLF line endings on checkout 26 | *.bat text eol=crlf 27 | 28 | # Declare files that will always have LF line endings on checkout 29 | *.sh text eol=lf 30 | configure text eol=lf 31 | 32 | # Denote all files that are truly binary and should not be modified 33 | *.png binary 34 | *.jpg binary 35 | *.jpeg binary 36 | *.gif binary 37 | *.ico binary 38 | *.svg binary 39 | *.pdf binary 40 | *.so binary 41 | *.a binary 42 | *.o binary 43 | *.gmo binary 44 | 45 | # Archive files 46 | *.tar binary 47 | *.gz binary 48 | *.bz2 binary 49 | *.xz binary 50 | *.zip binary 51 | 52 | # Meson build files 53 | meson.build text 54 | meson_options.txt text -------------------------------------------------------------------------------- /src/meson.build: -------------------------------------------------------------------------------- 1 | sources = [ 2 | 'Config.cxx', 3 | 'DocumentLinkGoto.cxx', 4 | 'DocumentLinkUri.cxx', 5 | 'DocumentOutline.cxx', 6 | 'DocumentPage.cxx', 7 | 'DocumentRectangle.cxx', 8 | 'FindPter.cxx', 9 | 'IDocument.cxx', 10 | 'IDocumentLink.cxx', 11 | 'IJob.cxx', 12 | 'JobFind.cxx', 13 | 'JobLoad.cxx', 14 | 'JobRender.cxx', 15 | 'JobSave.cxx', 16 | 'main.cxx', 17 | 'MainPter.cxx', 18 | 'PagePter.cxx', 19 | 'PDFDocument.cxx', 20 | 'PreferencesPter.cxx', 21 | ] 22 | 23 | # GTK4 UI sources 24 | gtk_sources = [ 25 | 'gtk/FindView.cxx', 26 | 'gtk/MainView.cxx', 27 | 'gtk/PageView.cxx', 28 | 'gtk/PreferencesView.cxx', 29 | 'gtk/StockIcons.cxx', 30 | ] 31 | 32 | sources += gtk_sources 33 | 34 | epdfview_deps = [ 35 | gtk_dep, 36 | poppler_dep, 37 | glib_dep, 38 | pango_dep, 39 | ] 40 | 41 | # Only compile print-related files when CUPS is available 42 | if cups_dep.found() and host_machine.system() != 'windows' 43 | epdfview_deps += cups_dep 44 | sources += ['JobPrint.cxx', 'PrintPter.cxx', 'gtk/PrintView.cxx'] 45 | endif 46 | 47 | # Create executable 48 | executable('epdfview', 49 | sources, 50 | dependencies: epdfview_deps, 51 | include_directories: inc, 52 | install: true, 53 | ) -------------------------------------------------------------------------------- /tests/meson.build: -------------------------------------------------------------------------------- 1 | if get_option('tests') 2 | test_sources = [ 3 | 'ConfigTest.cxx', 4 | 'DocumentOutlineTest.cxx', 5 | 'DumbDocument.cxx', 6 | 'DumbDocumentObserver.cxx', 7 | 'DumbFindView.cxx', 8 | 'DumbMainView.cxx', 9 | 'DumbPageView.cxx', 10 | 'DumbPreferencesView.cxx', 11 | 'DumbPrintView.cxx', 12 | 'FindPterTest.cxx', 13 | 'main.cxx', 14 | 'MainPterTest.cxx', 15 | 'PagePterTest.cxx', 16 | 'PDFDocumentTest.cxx', 17 | 'PreferencesPterTest.cxx', 18 | 'PrintPterTest.cxx', 19 | 'Utils.cxx', 20 | ] 21 | 22 | test_deps = [ 23 | gtk_dep, 24 | poppler_dep, 25 | glib_dep, 26 | pango_dep, 27 | ] 28 | 29 | # Add CUPS dependency if available 30 | if cups_dep.found() and host_machine.system() != 'windows' 31 | test_deps += cups_dep 32 | endif 33 | 34 | # Add CppUnit dependency if available 35 | cppunit_dep = dependency('cppunit', required: false) 36 | if cppunit_dep.found() 37 | test_deps += cppunit_dep 38 | 39 | epdfview_test = executable('epdfview-test', 40 | test_sources, 41 | include_directories: inc, 42 | dependencies: test_deps, 43 | ) 44 | 45 | test('epdfview unit tests', epdfview_test) 46 | else 47 | warning('CppUnit not found, tests will not be built') 48 | endif 49 | endif -------------------------------------------------------------------------------- /data/epdfview.1: -------------------------------------------------------------------------------- 1 | .TH "epdfview" "1" "2010\-07\-31" 2 | .SH "NAME" 3 | epdfview \- view PDF documents 4 | .SH "SYNOPSIS" 5 | .PP 6 | .B epdfview 7 | .RI "[ " OPTION... " ] [ " FILE " ]" 8 | .SH "DESCRIPTION" 9 | .PP 10 | This manual page documents briefly the \fBepdfview\fR command. 11 | .PP 12 | The aim of \fBepdfview\fR is to make a simple PDF document viewer, in the lines 13 | of \fBevince\fR(1) but without using the GNOME libraries. 14 | .SH "OPTIONS" 15 | .SS "Help Options" 16 | .TP 17 | .BR \-h , " \-\-help" 18 | Show help options 19 | .TP 20 | .BR \-\-help\-all 21 | Show all help options 22 | .TP 23 | .BR \-\-help\-gtk 24 | Show GTK+ Options 25 | .SS "GTK+ Options" 26 | .TP 27 | .BI \-\-class= CLASS 28 | Program class as used by the window manager 29 | .TP 30 | .BI \-\-name= NAME 31 | Program name as used by the window manager 32 | .TP 33 | .BI \-\-screen= SCREEN 34 | X screen to use 35 | .TP 36 | .BR \-\-sync 37 | Make X calls synchronous 38 | .TP 39 | .BI \-\-gtk\-module= MODULES 40 | Load additional GTK+ modules 41 | .TP 42 | .BR \-\-g\-fatal\-warnings 43 | Make all warnings fatal 44 | .SS "Application Options" 45 | .TP 46 | .BI \-\-display= DISPLAY 47 | X display to use 48 | .SH "SEE ALSO" 49 | .BR evince "(1), " xpdf (1) 50 | .SH "AUTHOR" 51 | \fBepdfview\fR is \(co 2006, 2007, 2009 Jordi Fita 52 | 53 | This manual page was written by Francois Wendling for the 54 | Debian GNU/Linux system (but may be used by others). 55 | -------------------------------------------------------------------------------- /tests/Utils.cxx: -------------------------------------------------------------------------------- 1 | // ePDFView - A lightweight PDF Viewer. 2 | // Copyright (C) 2006-2011 Emma's Software. 3 | // Copyright (C) 2014-2025 Pablo Lezaeta 4 | // Copyright (C) 2014 Pedro A. Aranda Gutiérrez 5 | 6 | // ePDFView - Test Util Functions. 7 | // 8 | // 9 | // This program is free software; you can redistribute it and/or modify 10 | // it under the terms of the GNU General Public License as published by 11 | // the Free Software Foundation; either version 2 of the License, or 12 | // (at your option) any later version. 13 | // 14 | // This program is distributed in the hope that it will be useful, 15 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 16 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 | // GNU General Public License for more details. 18 | // 19 | // You should have received a copy of the GNU General Public License 20 | // along with this program; if not, write to the Free Software 21 | // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 22 | 23 | #include 24 | #include "Utils.h" 25 | 26 | /// 27 | /// @brief Returns the path to the test data file. 28 | /// 29 | /// It assumes that TEST_DIR is defined to the relative 30 | /// tests directory and that the checks are executed from the 31 | /// test build dir. 32 | /// 33 | gchar * 34 | getTestFile (const gchar *fileName) 35 | { 36 | gchar *currentDir = g_get_current_dir (); 37 | gchar *filePath = g_build_filename (currentDir, TEST_DIR, fileName, NULL); 38 | g_free (currentDir); 39 | 40 | return filePath; 41 | } 42 | -------------------------------------------------------------------------------- /src/DocumentLinkUri.h: -------------------------------------------------------------------------------- 1 | // ePDFView - A lightweight PDF Viewer. 2 | // Copyright (C) 2006-2011 Emma's Software. 3 | // Copyright (C) 2014-2025 Pablo Lezaeta 4 | // Copyright (C) 2014 Pedro A. Aranda Gutiérrez 5 | 6 | // ePDFView - A lightweight PDF Viewer. 7 | // 8 | // 9 | // This program is free software; you can redistribute it and/or modify 10 | // it under the terms of the GNU General Public License as published by 11 | // the Free Software Foundation; either version 2 of the License, or 12 | // (at your option) any later version. 13 | // 14 | // This program is distributed in the hope that it will be useful, 15 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 16 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 | // GNU General Public License for more details. 18 | // 19 | // You should have received a copy of the GNU General Public License 20 | // along with this program; if not, write to the Free Software 21 | // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 22 | 23 | #if !defined (__DOCUMENT_LINK_URI_H__) 24 | #define __DOCUMENT_LINK_URI_H__ 25 | 26 | namespace ePDFView 27 | { 28 | class DocumentLinkUri: public IDocumentLink 29 | { 30 | public: 31 | DocumentLinkUri (gdouble x1, gdouble y1, gdouble x2, gdouble y2, 32 | const gchar *uri); 33 | virtual ~DocumentLinkUri (void); 34 | 35 | virtual void activate (IDocument *document); 36 | 37 | protected: 38 | /// The URI to go when the link is activated. 39 | gchar *m_Uri; 40 | }; 41 | } 42 | 43 | #endif // !__DOCUMENT_LINK_URI_H__ 44 | -------------------------------------------------------------------------------- /tests/DumbPreferencesView.h: -------------------------------------------------------------------------------- 1 | // ePDFView - A lightweight PDF Viewer. 2 | // Copyright (C) 2006-2011 Emma's Software. 3 | // Copyright (C) 2014-2025 Pablo Lezaeta 4 | // Copyright (C) 2014 Pedro A. Aranda Gutiérrez 5 | 6 | // ePDFView - Dumb Test Preferences View. 7 | // 8 | // 9 | // This program is free software; you can redistribute it and/or modify 10 | // it under the terms of the GNU General Public License as published by 11 | // the Free Software Foundation; either version 2 of the License, or 12 | // (at your option) any later version. 13 | // 14 | // This program is distributed in the hope that it will be useful, 15 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 16 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 | // GNU General Public License for more details. 18 | // 19 | // You should have received a copy of the GNU General Public License 20 | // along with this program; if not, write to the Free Software 21 | // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 22 | 23 | #if !defined (__DUMB_PREFERENCES_VIEW_H__) 24 | #define __DUMB_PREFERENCES_VIEW_H__ 25 | 26 | namespace ePDFView 27 | { 28 | class DumbPreferencesView: public IPreferencesView 29 | { 30 | public: 31 | DumbPreferencesView (void); 32 | virtual ~DumbPreferencesView (void); 33 | 34 | virtual const gchar *getBrowserCommandLine (void); 35 | 36 | // Test only functions. 37 | void setBrowserCommandLine (const char *commandLine); 38 | 39 | protected: 40 | gchar *m_BrowserCommandLine; 41 | }; 42 | } 43 | 44 | #endif // !__DUMB_PREFERENCES_VIEW_H__ 45 | -------------------------------------------------------------------------------- /src/DocumentLinkGoto.h: -------------------------------------------------------------------------------- 1 | // ePDFView - A lightweight PDF Viewer. 2 | // Copyright (C) 2006-2011 Emma's Software. 3 | // Copyright (C) 2014-2025 Pablo Lezaeta 4 | // Copyright (C) 2014 Pedro A. Aranda Gutiérrez 5 | 6 | // ePDFView - A lightweight PDF Viewer. 7 | // 8 | // 9 | // This program is free software; you can redistribute it and/or modify 10 | // it under the terms of the GNU General Public License as published by 11 | // the Free Software Foundation; either version 2 of the License, or 12 | // (at your option) any later version. 13 | // 14 | // This program is distributed in the hope that it will be useful, 15 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 16 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 | // GNU General Public License for more details. 18 | // 19 | // You should have received a copy of the GNU General Public License 20 | // along with this program; if not, write to the Free Software 21 | // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 22 | 23 | #if !defined (__DOCUMENT_LINK_GOTO_H__) 24 | #define __DOCUMENT_LINK_GOTO_H__ 25 | 26 | namespace ePDFView 27 | { 28 | class DocumentLinkGoto: public IDocumentLink 29 | { 30 | public: 31 | DocumentLinkGoto (gdouble x1, gdouble y1, gdouble x2, gdouble y2, 32 | gint destinationPage); 33 | virtual ~DocumentLinkGoto (void); 34 | 35 | virtual void activate (IDocument *document); 36 | 37 | protected: 38 | /// The number of the link's destination page. 39 | gint m_DestinationPage; 40 | }; 41 | } 42 | 43 | #endif // !__DOCUMENT_LINK_GOTO_H__ 44 | -------------------------------------------------------------------------------- /.kiro/steering/tech.md: -------------------------------------------------------------------------------- 1 | # Technology Stack & Build System 2 | 3 | ## Core Technologies 4 | 5 | - **Language**: C++ (C++11 standard) 6 | - **UI Framework**: GTK4 (with GTK3 compatibility layer) 7 | - **PDF Engine**: Poppler library (>= 0.5.0) 8 | - **Threading**: GLib threading (gthread-2.0) 9 | - **Printing**: CUPS (Unix/Linux only) 10 | - **Internationalization**: GNU gettext 11 | - **Testing**: CppUnit (optional, for unit tests) 12 | 13 | ## Build Systems 14 | 15 | The project supports two build systems: 16 | 17 | ### Meson (Recommended) 18 | ```bash 19 | # Configure 20 | meson setup builddir 21 | cd builddir 22 | 23 | # Build 24 | ninja 25 | 26 | # Install 27 | ninja install 28 | 29 | # Run tests (if enabled) 30 | ninja test 31 | ``` 32 | 33 | ### Autotools (Legacy) 34 | ```bash 35 | # Configure 36 | ./configure 37 | # or for debug builds: 38 | ./configure --enable-debug 39 | 40 | # Build 41 | make 42 | 43 | # Install 44 | make install 45 | 46 | # Run tests (if available) 47 | make check 48 | ``` 49 | 50 | ## Dependencies 51 | 52 | - GTK4 (>= 4.0.0) 53 | - Poppler-glib (>= 0.5.0) with GDK support 54 | - GLib (>= 2.8.0) with threading 55 | - Pango for text rendering 56 | - CUPS (optional, for printing on Unix/Linux) 57 | - CppUnit (optional, for unit tests) 58 | 59 | ## Compiler Flags 60 | 61 | - Warning level 3 (`-Wall` for autotools, `warning_level=3` for meson) 62 | - Debug builds include `-DDEBUG`, release builds use `-DNDEBUG -DG_DISABLE_ASSERT` 63 | - C++11 standard required 64 | - Additional flags: `-Wno-long-long` for C++ 65 | 66 | ## Platform Support 67 | 68 | - Primary: Linux/Unix systems 69 | - Secondary: Windows (with some limitations, no CUPS printing) 70 | - Cross-platform compatibility maintained through GTK4 -------------------------------------------------------------------------------- /data/README.md: -------------------------------------------------------------------------------- 1 | # Data Files 2 | 3 | This directory contains application resources and configuration files. 4 | 5 | ## Current Files 6 | 7 | ### Active (Used in GTK4 version) 8 | - **epdfview.svg** - Application icon (SVG, scalable) 9 | - **epdfview.desktop** / **epdfview.desktop.in** - Desktop entry file 10 | - **epdfview.1** - Manual page 11 | - **bsd.latexmkrc** / **dot.latexmkrc** - LaTeX integration configs 12 | - **epdfsync** - LaTeX-PDF sync script 13 | 14 | ### Deprecated (GTK2/GTK3 legacy, not used in GTK4) 15 | - **epdfview-ui.xml** - Old GTK UI definition (replaced by code-based UI) 16 | - **epdfview-ui-print.xml** - Old print dialog UI (replaced by GTK4 PrintOperation) 17 | - **stock_*.png** - Custom stock icons (GTK4 uses symbolic icons from theme) 18 | - **icon_epdfview-*.png** - PNG icons in various sizes (redundant with SVG) 19 | 20 | ## Icon System 21 | 22 | GTK4 uses the system icon theme with symbolic icons. Custom icons are no longer needed: 23 | - Navigation: `go-next-symbolic`, `go-previous-symbolic` 24 | - Zoom: `zoom-in-symbolic`, `zoom-out-symbolic` 25 | - Rotation: System provides rotation icons 26 | - Find: `edit-find-symbolic` 27 | 28 | The SVG icon (`epdfview.svg`) is used for: 29 | - Desktop launcher 30 | - Window icon 31 | - About dialog 32 | 33 | ## Cleanup Recommendation 34 | 35 | Safe to remove (not used in GTK4 build): 36 | ```bash 37 | rm -f epdfview-ui.xml 38 | rm -f epdfview-ui-print.xml 39 | rm -f stock_*.png 40 | rm -f icon_epdfview-*.png 41 | ``` 42 | 43 | Keep these files for compatibility and functionality: 44 | - All `.latexmkrc` files (LaTeX integration) 45 | - `epdfsync` (LaTeX sync) 46 | - `epdfview.svg` (main icon) 47 | - `epdfview.desktop*` (desktop integration) 48 | - `epdfview.1` (man page) 49 | -------------------------------------------------------------------------------- /data/epdfsync: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | from __future__ import print_function 3 | import sys 4 | import re 5 | import os 6 | from subprocess import Popen,PIPE 7 | 8 | try: 9 | if sys.argv[1] == '-l': 10 | LOG = open(os.path.join(os.getenv("HOME"),"epdfsync.log"), "a") 11 | arg = 2 12 | else: 13 | LOG = None 14 | arg = 1 15 | except: 16 | print ("%s: execute synctex and open up emacsclient" % os.path.basename(sys.argv[0])) 17 | print ("Arguments: [-l] page x y pdffile") 18 | print (" -l generates a log in ~/epdfsync.log") 19 | raise SystemExit 20 | 21 | 22 | print("Running " + " ".join(sys.argv), file=LOG) 23 | 24 | PAGE = int(sys.argv[arg]) 25 | X = int(sys.argv[arg+1]) 26 | Y = int(sys.argv[arg+2]) 27 | PDFFILE = sys.argv[arg+3] 28 | 29 | sarg = ":".join(sys.argv[arg:]) 30 | 31 | CMD = ["synctex", "edit", "-o", "%d:%d:%d:%s" % (PAGE,X,Y,PDFFILE)] 32 | print("Executing "+" ".join(CMD), file=LOG) 33 | synctex = Popen(CMD, stdout=PIPE, stderr=None) 34 | info, _ = synctex.communicate() 35 | print(info, file=LOG) 36 | try: 37 | inputRe=re.compile(r"Input:(.+)$",re.MULTILINE) 38 | fileName=inputRe.search(info).group(1) 39 | lineRe=re.compile(r"Line:(.+)$",re.MULTILINE) 40 | lineNumber=lineRe.search(info).group(1) 41 | 42 | print("emacsclient +%s %s" % (lineNumber, fileName), file=LOG) 43 | emacsclient = ["emacsclient", "-n", "-a", "emacs", "+"+lineNumber, fileName] 44 | Popen(emacsclient,stdout=None,stderr=None).communicate() 45 | except: 46 | print ("Something went wrong with synctex") 47 | if LOG is None: 48 | prin ("Enable loggong in .xpdfrc with '-l'") 49 | else: 50 | print(info, file=LOG) 51 | -------------------------------------------------------------------------------- /data/meson.build: -------------------------------------------------------------------------------- 1 | # Install application icons 2 | install_data('epdfview.svg', 3 | install_dir: join_paths(get_option('datadir'), 'icons', 'hicolor', 'scalable', 'apps') 4 | ) 5 | 6 | # Install PNG icons at various sizes 7 | # Keep original names in pixmaps for backward compatibility 8 | install_data('icon_epdfview-24.png', 9 | install_dir: join_paths(get_option('datadir'), 'pixmaps') 10 | ) 11 | 12 | install_data('icon_epdfview-32.png', 13 | install_dir: join_paths(get_option('datadir'), 'pixmaps') 14 | ) 15 | 16 | install_data('icon_epdfview-48.png', 17 | install_dir: join_paths(get_option('datadir'), 'pixmaps') 18 | ) 19 | 20 | # Also install to icon theme directories with standard names 21 | install_data('icon_epdfview-32.png', 22 | install_dir: join_paths(get_option('datadir'), 'icons', 'hicolor', '32x32', 'apps'), 23 | rename: 'epdfview.png' 24 | ) 25 | 26 | install_data('icon_epdfview-48.png', 27 | install_dir: join_paths(get_option('datadir'), 'icons', 'hicolor', '48x48', 'apps'), 28 | rename: 'epdfview.png' 29 | ) 30 | 31 | # Install stock icons (used in toolbar) 32 | stock_icons = [ 33 | 'stock_find_next_24.png', 34 | 'stock_find_previous_24.png', 35 | 'stock_rotate-270.png', 36 | 'stock_rotate-90.png', 37 | 'stock_zoom-page-width.png' 38 | ] 39 | 40 | foreach icon : stock_icons 41 | install_data(icon, 42 | install_dir: join_paths(get_option('datadir'), 'pixmaps') 43 | ) 44 | endforeach 45 | 46 | # Install man page 47 | install_man('epdfview.1') 48 | 49 | # Install desktop file 50 | desktop_file = 'epdfview.desktop' 51 | i18n.merge_file( 52 | input: desktop_file + '.in', 53 | output: desktop_file, 54 | type: 'desktop', 55 | po_dir: '../po', 56 | install: true, 57 | install_dir: join_paths(get_option('datadir'), 'applications') 58 | ) -------------------------------------------------------------------------------- /tests/PreferencesPterTest.h: -------------------------------------------------------------------------------- 1 | // ePDFView - A lightweight PDF Viewer. 2 | // Copyright (C) 2006-2011 Emma's Software. 3 | // Copyright (C) 2014-2025 Pablo Lezaeta 4 | // Copyright (C) 2014 Pedro A. Aranda Gutiérrez 5 | 6 | // ePDFView - Preferences Presenter Test Fixture. 7 | // 8 | // 9 | // This program is free software; you can redistribute it and/or modify 10 | // it under the terms of the GNU General Public License as published by 11 | // the Free Software Foundation; either version 2 of the License, or 12 | // (at your option) any later version. 13 | // 14 | // This program is distributed in the hope that it will be useful, 15 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 16 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 | // GNU General Public License for more details. 18 | // 19 | // You should have received a copy of the GNU General Public License 20 | // along with this program; if not, write to the Free Software 21 | // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 22 | 23 | #if !defined (__PREFERENCES_PTER_TEST_H__) 24 | #define __PREFERENCES_PTER_TEST_H__ 25 | 26 | #include 27 | 28 | namespace ePDFView 29 | { 30 | class PreferencesPterTest: public CppUnit::TestFixture 31 | { 32 | CPPUNIT_TEST_SUITE (PreferencesPterTest); 33 | CPPUNIT_TEST (externalCommandBrowser); 34 | CPPUNIT_TEST_SUITE_END (); 35 | 36 | public: 37 | void setUp (void); 38 | void tearDown (void); 39 | 40 | void externalCommandBrowser (void); 41 | 42 | protected: 43 | PreferencesPter *m_PreferencesPter; 44 | DumbPreferencesView *m_View; 45 | }; 46 | } 47 | 48 | #endif // !__PREFERENCES_PTER_TEST_H__ 49 | -------------------------------------------------------------------------------- /src/PreferencesPter.h: -------------------------------------------------------------------------------- 1 | // ePDFView - A lightweight PDF Viewer. 2 | // Copyright (C) 2006-2011 Emma's Software. 3 | // Copyright (C) 2014-2025 Pablo Lezaeta 4 | // Copyright (C) 2014 Pedro A. Aranda Gutiérrez 5 | 6 | // ePDFView - A lightweight PDF Viewer. 7 | // 8 | // 9 | // This program is free software; you can redistribute it and/or modify 10 | // it under the terms of the GNU General Public License as published by 11 | // the Free Software Foundation; either version 2 of the License, or 12 | // (at your option) any later version. 13 | // 14 | // This program is distributed in the hope that it will be useful, 15 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 16 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 | // GNU General Public License for more details. 18 | // 19 | // You should have received a copy of the GNU General Public License 20 | // along with this program; if not, write to the Free Software 21 | // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 22 | 23 | #if !defined (__PREFERENCES_PTER_H__) 24 | #define __PREFERENCES_PTER_H__ 25 | 26 | namespace ePDFView 27 | { 28 | /// 29 | /// @class PreferencesPter 30 | /// @brief Preferences Presenter. 31 | /// 32 | class PreferencesPter 33 | { 34 | public: 35 | PreferencesPter (void); 36 | ~PreferencesPter (void); 37 | 38 | IPreferencesView &getView (void); 39 | void setView (IPreferencesView *view); 40 | 41 | void browserCommandLineChanged (void); 42 | void backsearchCommandLineChanged (void); 43 | void closeActivated (void); 44 | 45 | protected: 46 | IPreferencesView *m_View; 47 | }; 48 | } 49 | 50 | #endif // !__PREFERENCES_PTER_H__ 51 | -------------------------------------------------------------------------------- /tests/DocumentOutlineTest.h: -------------------------------------------------------------------------------- 1 | // ePDFView - A lightweight PDF Viewer. 2 | // Copyright (C) 2006-2011 Emma's Software. 3 | // Copyright (C) 2014-2025 Pablo Lezaeta 4 | // Copyright (C) 2014 Pedro A. Aranda Gutiérrez 5 | 6 | // ePDFView - Document Outline Test Fixture. 7 | // 8 | // 9 | // This program is free software; you can redistribute it and/or modify 10 | // it under the terms of the GNU General Public License as published by 11 | // the Free Software Foundation; either version 2 of the License, or 12 | // (at your option) any later version. 13 | // 14 | // This program is distributed in the hope that it will be useful, 15 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 16 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 | // GNU General Public License for more details. 18 | // 19 | // You should have received a copy of the GNU General Public License 20 | // along with this program; if not, write to the Free Software 21 | // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 22 | 23 | #if !defined (__DOCUMENT_OUTLINE_TEST_H__) 24 | #define __DOCUMENT_OUTLINE_TEST_H__ 25 | 26 | #include 27 | 28 | namespace ePDFView 29 | { 30 | class DocumentOutlineTest: public CppUnit::TestFixture 31 | { 32 | CPPUNIT_TEST_SUITE (DocumentOutlineTest); 33 | CPPUNIT_TEST (initialStatus); 34 | CPPUNIT_TEST (noOutline); 35 | CPPUNIT_TEST (hasOutline); 36 | CPPUNIT_TEST_SUITE_END (); 37 | 38 | public: 39 | void setUp (void); 40 | void tearDown (void); 41 | 42 | void initialStatus (void); 43 | void noOutline (void); 44 | void hasOutline (void); 45 | 46 | protected: 47 | PDFDocument *m_Document; 48 | }; 49 | } 50 | 51 | #endif // !__DOCUMENT_OUTLINE_TEST_H__ 52 | -------------------------------------------------------------------------------- /tests/DumbPreferencesView.cxx: -------------------------------------------------------------------------------- 1 | // ePDFView - A lightweight PDF Viewer. 2 | // Copyright (C) 2006-2011 Emma's Software. 3 | // Copyright (C) 2014-2025 Pablo Lezaeta 4 | // Copyright (C) 2014 Pedro A. Aranda Gutiérrez 5 | 6 | // ePDFView - Dumb Test Preferences View. 7 | // 8 | // 9 | // This program is free software; you can redistribute it and/or modify 10 | // it under the terms of the GNU General Public License as published by 11 | // the Free Software Foundation; either version 2 of the License, or 12 | // (at your option) any later version. 13 | // 14 | // This program is distributed in the hope that it will be useful, 15 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 16 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 | // GNU General Public License for more details. 18 | // 19 | // You should have received a copy of the GNU General Public License 20 | // along with this program; if not, write to the Free Software 21 | // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 22 | 23 | #include 24 | #include "DumbPreferencesView.h" 25 | 26 | using namespace ePDFView; 27 | 28 | DumbPreferencesView::DumbPreferencesView (): 29 | IPreferencesView () 30 | { 31 | m_BrowserCommandLine = g_strdup (""); 32 | } 33 | 34 | DumbPreferencesView::~DumbPreferencesView () 35 | { 36 | g_free (m_BrowserCommandLine); 37 | } 38 | 39 | const gchar * 40 | DumbPreferencesView::getBrowserCommandLine () 41 | { 42 | return m_BrowserCommandLine; 43 | } 44 | 45 | //////////////////////////////////////////////////////////////// 46 | // Test Only Functions. 47 | //////////////////////////////////////////////////////////////// 48 | 49 | void 50 | DumbPreferencesView::setBrowserCommandLine (const gchar *commandLine) 51 | { 52 | g_free (m_BrowserCommandLine); 53 | m_BrowserCommandLine = g_strdup (commandLine); 54 | } 55 | -------------------------------------------------------------------------------- /src/IDocumentLink.h: -------------------------------------------------------------------------------- 1 | // ePDFView - A lightweight PDF Viewer. 2 | // Copyright (C) 2006-2011 Emma's Software. 3 | // Copyright (C) 2014-2025 Pablo Lezaeta 4 | // Copyright (C) 2014 Pedro A. Aranda Gutiérrez 5 | 6 | // ePDFView - A lightweight PDF Viewer. 7 | // 8 | // 9 | // This program is free software; you can redistribute it and/or modify 10 | // it under the terms of the GNU General Public License as published by 11 | // the Free Software Foundation; either version 2 of the License, or 12 | // (at your option) any later version. 13 | // 14 | // This program is distributed in the hope that it will be useful, 15 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 16 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 | // GNU General Public License for more details. 18 | // 19 | // You should have received a copy of the GNU General Public License 20 | // along with this program; if not, write to the Free Software 21 | // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 22 | 23 | #if !defined (__IDOCUMENT_LINK_H__) 24 | #define __IDOCUMENT_LINK_H__ 25 | 26 | namespace ePDFView 27 | { 28 | // Forward declarations. 29 | class IDocument; 30 | 31 | /// 32 | /// @class IDocumentLink 33 | /// @brief A single link on a page. 34 | /// 35 | /// This class is used by ePDFView::DocumentPage to maintain a list 36 | /// of all links that a single page have. 37 | /// 38 | class IDocumentLink 39 | { 40 | public: 41 | IDocumentLink (gdouble x1, gdouble y1, gdouble x2, gdouble y2); 42 | virtual ~IDocumentLink (void); 43 | 44 | virtual void activate (IDocument *document) = 0; 45 | gboolean positionIsOver (gint x, gint y); 46 | 47 | protected: 48 | /// The link rectangle. 49 | DocumentRectangle *m_Rect; 50 | }; 51 | } 52 | 53 | #endif // !__IDOCUMENT_LINK_H__ 54 | -------------------------------------------------------------------------------- /tests/PrintPterTest.h: -------------------------------------------------------------------------------- 1 | // ePDFView - A lightweight PDF Viewer. 2 | // Copyright (C) 2006-2011 Emma's Software. 3 | // Copyright (C) 2014-2025 Pablo Lezaeta 4 | // Copyright (C) 2014 Pedro A. Aranda Gutiérrez 5 | 6 | // ePDFView - Preferences Presenter Test Fixture. 7 | // 8 | // 9 | // This program is free software; you can redistribute it and/or modify 10 | // it under the terms of the GNU General Public License as published by 11 | // the Free Software Foundation; either version 2 of the License, or 12 | // (at your option) any later version. 13 | // 14 | // This program is distributed in the hope that it will be useful, 15 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 16 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 | // GNU General Public License for more details. 18 | // 19 | // You should have received a copy of the GNU General Public License 20 | // along with this program; if not, write to the Free Software 21 | // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 22 | 23 | #if !defined (__PRINT_PTER_TEST_H__) 24 | #define __PRINT_PTER_TEST_H__ 25 | 26 | #include 27 | 28 | namespace ePDFView 29 | { 30 | class PrintPterTest: public CppUnit::TestFixture 31 | { 32 | CPPUNIT_TEST_SUITE (PrintPterTest); 33 | CPPUNIT_TEST (initialSensitivity); 34 | CPPUNIT_TEST (collateSensitivity); 35 | CPPUNIT_TEST (pageRangeSensitivity); 36 | CPPUNIT_TEST_SUITE_END (); 37 | 38 | public: 39 | void setUp (void); 40 | void tearDown (void); 41 | 42 | void initialSensitivity (void); 43 | void collateSensitivity (void); 44 | void pageRangeSensitivity (void); 45 | 46 | protected: 47 | DumbDocument *m_Document; 48 | PrintPter *m_PrintPter; 49 | DumbPrintView *m_View; 50 | }; 51 | } 52 | 53 | #endif // !__PRINT_PTER_TEST_H__ 54 | -------------------------------------------------------------------------------- /po/Makevars: -------------------------------------------------------------------------------- 1 | # Makefile variables for PO directory in any package using GNU gettext. 2 | 3 | # Usually the message domain is the same as the package name. 4 | DOMAIN = $(PACKAGE) 5 | 6 | # These two variables depend on the location of this directory. 7 | subdir = po 8 | top_builddir = .. 9 | 10 | # These options get passed to xgettext. 11 | XGETTEXT_OPTIONS = --keyword=_ --keyword=N_ 12 | 13 | # This is the copyright holder that gets inserted into the header of the 14 | # $(DOMAIN).pot file. Set this to the copyright holder of the surrounding 15 | # package. (Note that the msgstr strings, extracted from the package's 16 | # sources, belong to the copyright holder of the package.) Translators are 17 | # expected to transfer the copyright for their translations to this person 18 | # or entity, or to disclaim their copyright. The empty string stands for 19 | # the public domain; in this case the translators are expected to disclaim 20 | # their copyright. 21 | COPYRIGHT_HOLDER = 22 | 23 | # This is the email address or URL to which the translators shall report 24 | # bugs in the untranslated strings: 25 | # - Strings which are not entire sentences, see the maintainer guidelines 26 | # in the GNU gettext documentation, section 'Preparing Strings'. 27 | # - Strings which use unclear terms or require additional context to be 28 | # understood. 29 | # - Strings which make invalid assumptions about notation of date, time or 30 | # money. 31 | # - Pluralisation problems. 32 | # - Incorrect English spelling. 33 | # - Incorrect formatting. 34 | # It can be your email address, or a mailing list address where translators 35 | # can write to without being subscribed, or the URL of a web page through 36 | # which the translators can contact you. 37 | MSGID_BUGS_ADDRESS = 38 | 39 | # This is the list of locale categories, beyond LC_MESSAGES, for which the 40 | # message catalogs shall be used. It is usually empty. 41 | EXTRA_LOCALE_CATEGORIES = 42 | -------------------------------------------------------------------------------- /tests/PagePterTest.h: -------------------------------------------------------------------------------- 1 | // ePDFView - A lightweight PDF Viewer. 2 | // Copyright (C) 2006-2011 Emma's Software. 3 | // Copyright (C) 2014-2025 Pablo Lezaeta 4 | // Copyright (C) 2014 Pedro A. Aranda Gutiérrez 5 | 6 | // ePDFView - Page Presenter Test Fixture. 7 | // 8 | // 9 | // This program is free software; you can redistribute it and/or modify 10 | // it under the terms of the GNU General Public License as published by 11 | // the Free Software Foundation; either version 2 of the License, or 12 | // (at your option) any later version. 13 | // 14 | // This program is distributed in the hope that it will be useful, 15 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 16 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 | // GNU General Public License for more details. 18 | // 19 | // You should have received a copy of the GNU General Public License 20 | // along with this program; if not, write to the Free Software 21 | // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 22 | 23 | #if !defined (__PAGE_PTER_TEST_H__) 24 | #define __PAGE_PTER_TEST_H__ 25 | 26 | #include 27 | 28 | namespace ePDFView 29 | { 30 | class PagePterTest: public CppUnit::TestFixture 31 | { 32 | CPPUNIT_TEST_SUITE (PagePterTest); 33 | CPPUNIT_TEST (pageZoomWidth); 34 | CPPUNIT_TEST (pageZoomFit); 35 | CPPUNIT_TEST (pageDrag); 36 | CPPUNIT_TEST_SUITE_END (); 37 | 38 | public: 39 | void setUp (void); 40 | void tearDown (void); 41 | 42 | void pageZoomWidth (void); 43 | void pageZoomFit (void); 44 | void pageDrag (void); 45 | 46 | protected: 47 | DumbDocument *m_Document; 48 | MainPter *m_MainPter; 49 | DumbMainView *m_MainView; 50 | PagePter *m_PagePter; 51 | DumbPageView *m_PageView; 52 | }; 53 | } 54 | 55 | #endif // !__PAGE_PTER_TEST_H__ 56 | -------------------------------------------------------------------------------- /src/gtk/PreferencesView.h: -------------------------------------------------------------------------------- 1 | // ePDFView - A lightweight PDF Viewer. 2 | // Copyright (C) 2006-2011 Emma's Software. 3 | // Copyright (C) 2014-2025 Pablo Lezaeta 4 | // Copyright (C) 2014 Pedro A. Aranda Gutiérrez 5 | 6 | // ePDFView - A lightweight PDF Viewer. 7 | // 8 | // 9 | // This program is free software; you can redistribute it and/or modify 10 | // it under the terms of the GNU General Public License as published by 11 | // the Free Software Foundation; either version 2 of the License, or 12 | // (at your option) any later version. 13 | // 14 | // This program is distributed in the hope that it will be useful, 15 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 16 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 | // GNU General Public License for more details. 18 | // 19 | // You should have received a copy of the GNU General Public License 20 | // along with this program; if not, write to the Free Software 21 | // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 22 | 23 | #if !defined (__PREFERENCES_VIEW_H__) 24 | #define __PREFERENCES_VIEW_H__ 25 | 26 | namespace ePDFView 27 | { 28 | class PreferencesView: public IPreferencesView 29 | { 30 | public: 31 | PreferencesView (GtkWindow *parent); 32 | virtual ~PreferencesView (void); 33 | 34 | virtual void setPresenter (PreferencesPter *pter); 35 | virtual const gchar *getBrowserCommandLine (void); 36 | virtual const gchar *getBacksearchCommandLine (void); 37 | 38 | protected: 39 | GtkWidget *m_PreferencesDialog; 40 | GtkWidget *m_BrowserCommandLine; 41 | GtkWidget *m_BacksearchCommandLine; 42 | 43 | // Signal handler IDs for cleanup 44 | gulong m_ResponseHandlerId; 45 | gulong m_CloseRequestHandlerId; 46 | 47 | GtkWidget *createExternalCommandsTab (void); 48 | }; 49 | } 50 | 51 | #endif // !__PREFERENCES_VIEW_H__ 52 | -------------------------------------------------------------------------------- /tests/FindPterTest.h: -------------------------------------------------------------------------------- 1 | // ePDFView - A lightweight PDF Viewer. 2 | // Copyright (C) 2006-2011 Emma's Software. 3 | // Copyright (C) 2014-2025 Pablo Lezaeta 4 | // Copyright (C) 2014 Pedro A. Aranda Gutiérrez 5 | 6 | // ePDFView - Find Presenter Test Fixture. 7 | // 8 | // 9 | // This program is free software; you can redistribute it and/or modify 10 | // it under the terms of the GNU General Public License as published by 11 | // the Free Software Foundation; either version 2 of the License, or 12 | // (at your option) any later version. 13 | // 14 | // This program is distributed in the hope that it will be useful, 15 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 16 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 | // GNU General Public License for more details. 18 | // 19 | // You should have received a copy of the GNU General Public License 20 | // along with this program; if not, write to the Free Software 21 | // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 22 | 23 | #if !defined (__FIND_PTER_TEST_H__) 24 | #define __FIND_PTER_TEST_H__ 25 | 26 | #include 27 | 28 | namespace ePDFView 29 | { 30 | class FindPterTest: public CppUnit::TestFixture 31 | { 32 | CPPUNIT_TEST_SUITE (FindPterTest); 33 | CPPUNIT_TEST (viewSensitivity); 34 | CPPUNIT_TEST (textDoesNotExist); 35 | CPPUNIT_TEST (findNext); 36 | CPPUNIT_TEST (findPrevious); 37 | CPPUNIT_TEST_SUITE_END (); 38 | 39 | public: 40 | void setUp (void); 41 | void tearDown (void); 42 | 43 | void viewSensitivity (void); 44 | void textDoesNotExist (void); 45 | void findNext (void); 46 | void findPrevious (void); 47 | 48 | private: 49 | PDFDocument *m_Document; 50 | FindPter *m_FindPter; 51 | DumbDocumentObserver *m_Observer; 52 | DumbFindView *m_View; 53 | }; 54 | } 55 | 56 | #endif // !__FIND_PTER_TEST_H__ 57 | -------------------------------------------------------------------------------- /tests/main.cxx: -------------------------------------------------------------------------------- 1 | // ePDFView - A lightweight PDF Viewer. 2 | // Copyright (C) 2006-2011 Emma's Software. 3 | // Copyright (C) 2014-2025 Pablo Lezaeta 4 | // Copyright (C) 2014 Pedro A. Aranda Gutiérrez 5 | 6 | // ePDFView - Test Suite. 7 | // 8 | // 9 | // This program is free software; you can redistribute it and/or modify 10 | // it under the terms of the GNU General Public License as published by 11 | // the Free Software Foundation; either version 2 of the License, or 12 | // (at your option) any later version. 13 | // 14 | // This program is distributed in the hope that it will be useful, 15 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 16 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 | // GNU General Public License for more details. 18 | // 19 | // You should have received a copy of the GNU General Public License 20 | // along with this program; if not, write to the Free Software 21 | // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 22 | 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include 29 | 30 | using namespace CPPUNIT_NS; 31 | 32 | int 33 | main (int argc, char **argv) 34 | { 35 | // We must initialize glib't types. 36 | g_type_init (); 37 | 38 | // Initialize the job's queue. 39 | ePDFView::IJob::init (); 40 | 41 | // Get the top level suite from the registry. 42 | Test *suite = TestFactoryRegistry::getRegistry ().makeTest (); 43 | 44 | // Add the test suite to the list of tests to run. 45 | TextUi::TestRunner runner; 46 | runner.addTest (suite); 47 | 48 | // Change the default outputter to a compiler error format outputter. 49 | runner.setOutputter (new CompilerOutputter (&runner.result (), std::cerr)); 50 | 51 | // Run the tests. 52 | bool wasSuccessful = runner.run (); 53 | 54 | return wasSuccessful ? EXIT_SUCCESS : EXIT_FAILURE; 55 | } 56 | -------------------------------------------------------------------------------- /tests/DumbPageView.h: -------------------------------------------------------------------------------- 1 | // ePDFView - A lightweight PDF Viewer. 2 | // Copyright (C) 2006-2011 Emma's Software. 3 | // Copyright (C) 2014-2025 Pablo Lezaeta 4 | // Copyright (C) 2014 Pedro A. Aranda Gutiérrez 5 | 6 | // ePDFView - Dumb Test Page View. 7 | // 8 | // 9 | // This program is free software; you can redistribute it and/or modify 10 | // it under the terms of the GNU General Public License as published by 11 | // the Free Software Foundation; either version 2 of the License, or 12 | // (at your option) any later version. 13 | // 14 | // This program is distributed in the hope that it will be useful, 15 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 16 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 | // GNU General Public License for more details. 18 | // 19 | // You should have received a copy of the GNU General Public License 20 | // along with this program; if not, write to the Free Software 21 | // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 22 | 23 | #if !defined (__DUMB_PAGE_VIEW_H__) 24 | #define __DUMB_PAGE_VIEW_H__ 25 | 26 | namespace ePDFView 27 | { 28 | class DumbPageView: public IPageView 29 | { 30 | public: 31 | DumbPageView (void); 32 | ~DumbPageView (void); 33 | 34 | gdouble getHorizontalScroll (void); 35 | void getSize (gint *width, gint *height); 36 | gdouble getVerticalScroll (void); 37 | void makeRectangleVisible (DocumentRectangle &rect, gdouble scale); 38 | void resizePage (gint width, gint height); 39 | void scrollPage (gdouble scrollX, gdouble scrollY, 40 | gint dx, gint dy); 41 | void setCursor (PageCursor cursorType); 42 | void showPage (DocumentPage *page, PageScroll scroll); 43 | void showText (const gchar *text); 44 | 45 | 46 | private: 47 | gdouble m_HorizontalScroll; 48 | gdouble m_VerticalScroll; 49 | }; 50 | } 51 | 52 | #endif // !__DUMB_PAGE_VIEW_H__ 53 | -------------------------------------------------------------------------------- /tests/DumbFindView.h: -------------------------------------------------------------------------------- 1 | // ePDFView - A lightweight PDF Viewer. 2 | // Copyright (C) 2006-2011 Emma's Software. 3 | // Copyright (C) 2014-2025 Pablo Lezaeta 4 | // Copyright (C) 2014 Pedro A. Aranda Gutiérrez 5 | 6 | // ePDFView - Dumb Test Find View. 7 | // 8 | // 9 | // This program is free software; you can redistribute it and/or modify 10 | // it under the terms of the GNU General Public License as published by 11 | // the Free Software Foundation; either version 2 of the License, or 12 | // (at your option) any later version. 13 | // 14 | // This program is distributed in the hope that it will be useful, 15 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 16 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 | // GNU General Public License for more details. 18 | // 19 | // You should have received a copy of the GNU General Public License 20 | // along with this program; if not, write to the Free Software 21 | // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 22 | 23 | #if !defined (__DUMB_FIND_VIEW_H__) 24 | #define __DUMB_FIND_VIEW_H__ 25 | 26 | namespace ePDFView 27 | { 28 | class DumbFindView: public IFindView 29 | { 30 | public: 31 | DumbFindView (void); 32 | ~DumbFindView (void); 33 | 34 | const gchar *getTextToFind (void); 35 | void hide (void); 36 | void sensitiveFindNext (gboolean sensitive); 37 | void sensitiveFindPrevious (gboolean sensitive); 38 | void setInformationText (const gchar *text); 39 | 40 | // Methods for test only purposes. 41 | const gchar *getInformationText (void); 42 | gboolean isFindNextSensitive (void); 43 | gboolean isFindPreviousSensitive (void); 44 | void setTextToFind (const gchar *text); 45 | 46 | protected: 47 | gboolean m_FindNextSensitive; 48 | gboolean m_FindPreviousSensitive; 49 | gchar *m_InformationText; 50 | gchar *m_TextToFind; 51 | }; 52 | } 53 | 54 | #endif // !__DUMB_FIND_VIEW_H__ 55 | -------------------------------------------------------------------------------- /src/PreferencesPter.cxx: -------------------------------------------------------------------------------- 1 | // ePDFView - A lightweight PDF Viewer. 2 | // Copyright (C) 2006-2011 Emma's Software. 3 | // Copyright (C) 2014-2025 Pablo Lezaeta 4 | // Copyright (C) 2014 Pedro A. Aranda Gutiérrez 5 | 6 | // ePDFView - A lightweight PDF Viewer. 7 | // 8 | // 9 | // This program is free software; you can redistribute it and/or modify 10 | // it under the terms of the GNU General Public License as published by 11 | // the Free Software Foundation; either version 2 of the License, or 12 | // (at your option) any later version. 13 | // 14 | // This program is distributed in the hope that it will be useful, 15 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 16 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 | // GNU General Public License for more details. 18 | // 19 | // You should have received a copy of the GNU General Public License 20 | // along with this program; if not, write to the Free Software 21 | // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 22 | 23 | #include 24 | #include "epdfview.h" 25 | 26 | using namespace ePDFView; 27 | 28 | PreferencesPter::PreferencesPter () 29 | { 30 | m_View = NULL; 31 | } 32 | 33 | PreferencesPter::~PreferencesPter () 34 | { 35 | delete m_View; 36 | } 37 | 38 | IPreferencesView & 39 | PreferencesPter::getView () 40 | { 41 | g_assert ( NULL != m_View && "The preferences' view is NULL."); 42 | 43 | return *m_View; 44 | } 45 | 46 | void 47 | PreferencesPter::setView (IPreferencesView *view) 48 | { 49 | m_View = view; 50 | getView ().setPresenter (this); 51 | } 52 | 53 | void 54 | PreferencesPter::browserCommandLineChanged () 55 | { 56 | const gchar *commandLine = getView ().getBrowserCommandLine (); 57 | Config::getConfig ().setExternalBrowserCommandLine (commandLine); 58 | } 59 | 60 | void 61 | PreferencesPter::backsearchCommandLineChanged () 62 | { 63 | const gchar *commandLine = getView ().getBacksearchCommandLine (); 64 | Config::getConfig ().setExternalBacksearchCommandLine (commandLine); 65 | } 66 | 67 | void 68 | PreferencesPter::closeActivated () 69 | { 70 | delete this; 71 | } 72 | -------------------------------------------------------------------------------- /src/epdfview.h: -------------------------------------------------------------------------------- 1 | // ePDFView - A lightweight PDF Viewer. 2 | // Copyright (C) 2006-2011 Emma's Software. 3 | // Copyright (C) 2014-2025 Pablo Lezaeta 4 | // Copyright (C) 2014 Pedro A. Aranda Gutiérrez 5 | 6 | // ePDFView - A lightweight PDF Viewer. 7 | // 8 | // 9 | // This program is free software; you can redistribute it and/or modify 10 | // it under the terms of the GNU General Public License as published by 11 | // the Free Software Foundation; either version 2 of the License, or 12 | // (at your option) any later version. 13 | // 14 | // This program is distributed in the hope that it will be useful, 15 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 16 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 | // GNU General Public License for more details. 18 | // 19 | // You should have received a copy of the GNU General Public License 20 | // along with this program; if not, write to the Free Software 21 | // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 22 | 23 | #if !defined (__E_PDF_VIEW_H__) 24 | #define __E_PDF_VIEW_H__ 25 | 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include 31 | 32 | #include 33 | 34 | #include 35 | #include 36 | #include 37 | #include 38 | #include 39 | #include 40 | #include 41 | #include 42 | #include 43 | 44 | #include 45 | #include 46 | #include 47 | #include 48 | #include 49 | #include 50 | #if defined (HAVE_CUPS) 51 | #endif // HAVE_CUPS 52 | 53 | #include 54 | #include 55 | #include 56 | #if defined (HAVE_CUPS) 57 | #include 58 | #endif // HAVE_CUPS 59 | #include 60 | #include 61 | #include 62 | #include 63 | #if defined (HAVE_CUPS) 64 | #include 65 | #endif // HAVE_CUPS 66 | #include 67 | 68 | #endif //!__E_PDF_VIEW_H__ 69 | -------------------------------------------------------------------------------- /tests/ConfigTest.h: -------------------------------------------------------------------------------- 1 | // ePDFView - A lightweight PDF Viewer. 2 | // Copyright (C) 2006-2011 Emma's Software. 3 | // Copyright (C) 2014-2025 Pablo Lezaeta 4 | // Copyright (C) 2014 Pedro A. Aranda Gutiérrez 5 | 6 | // ePDFView - Configuration Test Fixture. 7 | // 8 | // 9 | // This program is free software; you can redistribute it and/or modify 10 | // it under the terms of the GNU General Public License as published by 11 | // the Free Software Foundation; either version 2 of the License, or 12 | // (at your option) any later version. 13 | // 14 | // This program is distributed in the hope that it will be useful, 15 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 16 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 | // GNU General Public License for more details. 18 | // 19 | // You should have received a copy of the GNU General Public License 20 | // along with this program; if not, write to the Free Software 21 | // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 22 | 23 | #if !defined (__CONFIG_TEST_H__) 24 | #define __CONFIG_TEST_H__ 25 | 26 | #include 27 | 28 | namespace ePDFView 29 | { 30 | class ConfigTest: public CppUnit::TestFixture 31 | { 32 | CPPUNIT_TEST_SUITE (ConfigTest); 33 | CPPUNIT_TEST (defaultValues); 34 | CPPUNIT_TEST (windowValues); 35 | CPPUNIT_TEST (showToolbar); 36 | CPPUNIT_TEST (showStatusbar); 37 | CPPUNIT_TEST (openCurrentFolder); 38 | CPPUNIT_TEST (saveCurrentFolder); 39 | CPPUNIT_TEST (zoomValues); 40 | CPPUNIT_TEST (externalBrowser); 41 | CPPUNIT_TEST_SUITE_END (); 42 | 43 | public: 44 | void setUp (void); 45 | void tearDown (void); 46 | 47 | void defaultValues (void); 48 | void windowValues (void); 49 | void showToolbar (void); 50 | void showStatusbar (void); 51 | void openCurrentFolder (void); 52 | void saveCurrentFolder (void); 53 | void zoomValues (void); 54 | void externalBrowser (void); 55 | }; 56 | } 57 | 58 | #endif // __CONFIG_TEST_H__ 59 | -------------------------------------------------------------------------------- /src/DocumentLinkGoto.cxx: -------------------------------------------------------------------------------- 1 | // ePDFView - A lightweight PDF Viewer. 2 | // Copyright (C) 2006-2011 Emma's Software. 3 | // Copyright (C) 2014-2025 Pablo Lezaeta 4 | // Copyright (C) 2014 Pedro A. Aranda Gutiérrez 5 | 6 | // ePDFView - A lightweight PDF Viewer. 7 | // 8 | // 9 | // This program is free software; you can redistribute it and/or modify 10 | // it under the terms of the GNU General Public License as published by 11 | // the Free Software Foundation; either version 2 of the License, or 12 | // (at your option) any later version. 13 | // 14 | // This program is distributed in the hope that it will be useful, 15 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 16 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 | // GNU General Public License for more details. 18 | // 19 | // You should have received a copy of the GNU General Public License 20 | // along with this program; if not, write to the Free Software 21 | // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 22 | 23 | #include 24 | #include "epdfview.h" 25 | 26 | using namespace ePDFView; 27 | 28 | /// 29 | /// @brief Construct a new DocumentLinkGoto object. 30 | /// 31 | /// @param x1 The X coordinate of the link's top-left corner. 32 | /// @param y1 The Y coordinate of the link's top-left corner. 33 | /// @param x2 The X coordinate of the link's bottom-right corner. 34 | /// @param y2 The Y coordinate of the link's bottom-right corner. 35 | /// @param destinationPage The page number the links points to. 36 | /// 37 | DocumentLinkGoto::DocumentLinkGoto (gdouble x1, gdouble y1, gdouble x2, 38 | gdouble y2, gint destinationPage): 39 | IDocumentLink (x1, y1, x2, y2) 40 | { 41 | m_DestinationPage = destinationPage; 42 | } 43 | 44 | /// 45 | /// @brief Destroys all dynamically allocated memory by DocumentLinkGoto. 46 | /// 47 | DocumentLinkGoto::~DocumentLinkGoto () 48 | { 49 | } 50 | 51 | /// 52 | /// @brief Activates the link. 53 | /// 54 | /// @param document The document where the link was activated from. 55 | /// 56 | void 57 | DocumentLinkGoto::activate (IDocument *document) 58 | { 59 | document->goToPage (m_DestinationPage); 60 | } 61 | -------------------------------------------------------------------------------- /src/JobSave.h: -------------------------------------------------------------------------------- 1 | // ePDFView - A lightweight PDF Viewer. 2 | // Copyright (C) 2006-2011 Emma's Software. 3 | // Copyright (C) 2014-2025 Pablo Lezaeta 4 | // Copyright (C) 2014 Pedro A. Aranda Gutiérrez 5 | 6 | // ePDFView - A lightweight PDF Viewer. 7 | // 8 | // 9 | // This program is free software; you can redistribute it and/or modify 10 | // it under the terms of the GNU General Public License as published by 11 | // the Free Software Foundation; either version 2 of the License, or 12 | // (at your option) any later version. 13 | // 14 | // This program is distributed in the hope that it will be useful, 15 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 16 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 | // GNU General Public License for more details. 18 | // 19 | // You should have received a copy of the GNU General Public License 20 | // along with this program; if not, write to the Free Software 21 | // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 22 | 23 | #if !defined (__JOB_SAVE_H__) 24 | #define __JOB_SAVE_H__ 25 | 26 | namespace ePDFView 27 | { 28 | // Forward declarations. 29 | class IDocument; 30 | 31 | /// 32 | /// @class JobSave 33 | /// @brief A background job that saves a document's copy to a file. 34 | /// 35 | /// This class is used to save copies of PDF files. 36 | /// 37 | class JobSave: public IJob 38 | { 39 | public: 40 | JobSave (void); 41 | ~JobSave (void); 42 | 43 | IDocument &getDocument (void); 44 | GError *getError (void); 45 | const gchar *getFileName (void); 46 | gboolean run (void); 47 | void setDocument (IDocument *document); 48 | void setError (GError *error); 49 | void setFileName (const gchar *fileName); 50 | 51 | protected: 52 | /// The document to notify when loaded or on error. 53 | IDocument *m_Document; 54 | /// The error produced when loading. 55 | GError *m_Error; 56 | /// The file name to load or reload. 57 | gchar *m_FileName; 58 | }; 59 | } 60 | 61 | #endif // __JOB_SAVE_H__ 62 | -------------------------------------------------------------------------------- /tests/DumbPageView.cxx: -------------------------------------------------------------------------------- 1 | // ePDFView - A lightweight PDF Viewer. 2 | // Copyright (C) 2006-2011 Emma's Software. 3 | // Copyright (C) 2014-2025 Pablo Lezaeta 4 | // Copyright (C) 2014 Pedro A. Aranda Gutiérrez 5 | 6 | // ePDFView - Dumb Test Page View. 7 | // 8 | // 9 | // This program is free software; you can redistribute it and/or modify 10 | // it under the terms of the GNU General Public License as published by 11 | // the Free Software Foundation; either version 2 of the License, or 12 | // (at your option) any later version. 13 | // 14 | // This program is distributed in the hope that it will be useful, 15 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 16 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 | // GNU General Public License for more details. 18 | // 19 | // You should have received a copy of the GNU General Public License 20 | // along with this program; if not, write to the Free Software 21 | // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 22 | 23 | #include 24 | #include "DumbPageView.h" 25 | 26 | using namespace ePDFView; 27 | 28 | DumbPageView::DumbPageView (): 29 | IPageView () 30 | { 31 | m_HorizontalScroll = 0.0; 32 | m_VerticalScroll = 0.0; 33 | } 34 | 35 | DumbPageView::~DumbPageView () 36 | { 37 | } 38 | 39 | gdouble 40 | DumbPageView::getHorizontalScroll () 41 | { 42 | return m_HorizontalScroll; 43 | } 44 | 45 | void 46 | DumbPageView::getSize (gint *width, gint *height) 47 | { 48 | *width = 75; 49 | *height = 50; 50 | } 51 | 52 | gdouble 53 | DumbPageView::getVerticalScroll () 54 | { 55 | return m_VerticalScroll; 56 | } 57 | 58 | void 59 | DumbPageView::makeRectangleVisible (DocumentRectangle &rect, gdouble scale) 60 | { 61 | } 62 | 63 | void 64 | DumbPageView::resizePage (gint width, gint height) 65 | { 66 | } 67 | 68 | void 69 | DumbPageView::scrollPage (gdouble scrollX, gdouble scrollY, gint dx, gint dy) 70 | { 71 | m_HorizontalScroll = (gdouble)dx; 72 | m_VerticalScroll = (gdouble)dy; 73 | } 74 | 75 | void 76 | DumbPageView::setCursor (PageCursor cursorType) 77 | { 78 | } 79 | 80 | void 81 | DumbPageView::showPage (DocumentPage *page, PageScroll scroll) 82 | { 83 | } 84 | 85 | void 86 | DumbPageView::showText (const gchar *text) 87 | { 88 | } 89 | -------------------------------------------------------------------------------- /src/PrintPter.h: -------------------------------------------------------------------------------- 1 | // ePDFView - A lightweight PDF Viewer. 2 | // Copyright (C) 2006-2011 Emma's Software. 3 | // Copyright (C) 2014-2025 Pablo Lezaeta 4 | // Copyright (C) 2014 Pedro A. Aranda Gutiérrez 5 | 6 | // ePDFView - A lightweight PDF Viewer. 7 | // 8 | // 9 | // This program is free software; you can redistribute it and/or modify 10 | // it under the terms of the GNU General Public License as published by 11 | // the Free Software Foundation; either version 2 of the License, or 12 | // (at your option) any later version. 13 | // 14 | // This program is distributed in the hope that it will be useful, 15 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 16 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 | // GNU General Public License for more details. 18 | // 19 | // You should have received a copy of the GNU General Public License 20 | // along with this program; if not, write to the Free Software 21 | // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 22 | 23 | #if !defined (__PRINT_PTER_H__) 24 | #define __PRINT_PTER_H__ 25 | 26 | // Forward declarations. 27 | typedef struct _printerAttributes printerAttributes; 28 | 29 | namespace ePDFView 30 | { 31 | /// 32 | /// @class PrintPter 33 | /// @brief Print Presenter. 34 | /// 35 | class PrintPter 36 | { 37 | public: 38 | PrintPter (IDocument *document); 39 | ~PrintPter (void); 40 | 41 | IPrintView &getView (void); 42 | void setView (IPrintView *view); 43 | 44 | void cancelActivated (void); 45 | void numberOfCopiesChanged (void); 46 | void pageRangeOptionChanged (void); 47 | void printActivated (void); 48 | void printerSelectionChanged (void); 49 | 50 | protected: 51 | IDocument *m_Document; 52 | IPrintView *m_View; 53 | 54 | void getPageSizeForPrinter (const gchar *printerName, 55 | const gchar *sizeName, 56 | float *pageWidth, float *pageHeight); 57 | printerAttributes *getPrinterAttributes (const gchar *printerName); 58 | void listPrinters (void); 59 | }; 60 | } 61 | 62 | #endif // !__PRINT_PTER_H__ 63 | -------------------------------------------------------------------------------- /STATUS.md: -------------------------------------------------------------------------------- 1 | # ePDFView - Current Status 2 | 3 | **Version:** 0.3.0 4 | **Last Updated:** November 12, 2025 5 | **Status:** ✅ **Stable** 6 | 7 | --- 8 | 9 | ## Quick Status 10 | 11 | ### In Working Features ✅ 12 | - PDF viewing and rendering 13 | - Page navigation (keyboard, buttons, jump to page) 14 | - Zoom (fit page, fit width, custom percentages) 15 | - Find/Search with highlighting 16 | - Document outline/index 17 | - Full screen mode 18 | - Page rotation 19 | - Invert colors (night mode) 20 | - Preferences dialog 21 | - 22 language translations 22 | - File operations (open, save copy) 23 | 24 | ### Known Issues ⚠️ 25 | - **Print dialog:** GListStore type compatibility (medium priority) 26 | - **Compilation warnings:** ~82 unused parameter warnings (low priority) 27 | 28 | ### Recent Fixes (Nov 2025) ✅ 29 | - Fixed critical startup crash (SIGSEGV) 30 | - Navigation buttons work correctly 31 | - Page numbers update visually 32 | - Windows build support added 33 | - CI/CD for Linux, FreeBSD, Windows 34 | 35 | --- 36 | 37 | ## Platform Support 38 | 39 | | Platform | Status | Notes | 40 | |----------|--------|-------| 41 | | Linux (X11) | ✅ Fully working | Tested on Arch, Ubuntu, Fedora | 42 | | Linux (Wayland) | ✅ Fully working | Native Wayland support | 43 | | FreeBSD | ✅ Fully working | CI automated | 44 | | Windows (MSYS2) | ✅ Working | See `docs/BUILD_WINDOWS.md` | 45 | | WSL | ✅ Working | Requires X11 server | 46 | 47 | --- 48 | 49 | ## Build Status 50 | 51 | ![CI Build](https://github.com/JotaRandom/epdfview/actions/workflows/build.yml/badge.svg) 52 | 53 | - **Linux:** ✅ Passing 54 | - **FreeBSD:** ✅ Passing (fixed bash dependency) 55 | - **Windows:** ✅ Passing (MSYS2) 56 | 57 | --- 58 | 59 | ## For More Information 60 | 61 | - **Detailed Status:** See `PROJECT_STATUS.md` 62 | - **Development Tasks:** See `docs/TODO_NEXT_SESSION.md` 63 | - **Installation:** See `INSTALL` or `README` 64 | - **Recent Fixes:** See `docs/CRASH_FIX_2025-11-12.md` 65 | - **Build Guide (Windows):** See `docs/BUILD_WINDOWS.md` 66 | 67 | --- 68 | 69 | ## Quick Start 70 | 71 | ```bash 72 | # Linux/BSD 73 | meson setup builddir 74 | meson compile -C builddir 75 | ./builddir/src/epdfview 76 | 77 | # Install system-wide 78 | sudo meson install -C builddir 79 | ``` 80 | 81 | For Windows or WSL, see platform-specific documentation in `docs/`. 82 | -------------------------------------------------------------------------------- /src/DocumentRectangle.h: -------------------------------------------------------------------------------- 1 | // ePDFView - A lightweight PDF Viewer. 2 | // Copyright (C) 2006-2011 Emma's Software. 3 | // Copyright (C) 2014-2025 Pablo Lezaeta 4 | // Copyright (C) 2014 Pedro A. Aranda Gutiérrez 5 | 6 | // ePDFView - A lightweight PDF Viewer. 7 | // 8 | // 9 | // This program is free software; you can redistribute it and/or modify 10 | // it under the terms of the GNU General Public License as published by 11 | // the Free Software Foundation; either version 2 of the License, or 12 | // (at your option) any later version. 13 | // 14 | // This program is distributed in the hope that it will be useful, 15 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 16 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 | // GNU General Public License for more details. 18 | // 19 | // You should have received a copy of the GNU General Public License 20 | // along with this program; if not, write to the Free Software 21 | // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 22 | 23 | #if !defined (__DOCUMENT_RECTANGLE_H__) 24 | #define __DOCUMENT_RECTANGLE_H__ 25 | 26 | namespace ePDFView 27 | { 28 | /// 29 | /// @class DocumentRectangle. 30 | /// @brief A rectangle on a page. 31 | /// 32 | /// This class is just to hold the coordinates of a rectangle on a document. 33 | /// It is used as a way to know where are the document's link or the 34 | /// text that has been searched. 35 | /// 36 | class DocumentRectangle 37 | { 38 | public: 39 | DocumentRectangle (gdouble x1, gdouble y1, gdouble x2, gdouble y2); 40 | DocumentRectangle (DocumentRectangle &original); 41 | ~DocumentRectangle (void); 42 | 43 | gdouble getX1 (void); 44 | gdouble getX2 (void); 45 | gdouble getY1 (void); 46 | gdouble getY2 (void); 47 | 48 | protected: 49 | /// The X coordinate of the link's top-left corner. 50 | gdouble m_X1; 51 | /// The X coordinate of the link's bottom-right corner. 52 | gdouble m_X2; 53 | /// The Y coordinate of the link's top-left corner. 54 | gdouble m_Y1; 55 | /// The Y coordinate of the link's bottom-right corner. 56 | gdouble m_Y2; 57 | 58 | }; 59 | } 60 | 61 | #endif // !__DOCUMENT_RECTANGLE_H__ 62 | -------------------------------------------------------------------------------- /src/IDocumentLink.cxx: -------------------------------------------------------------------------------- 1 | // ePDFView - A lightweight PDF Viewer. 2 | // Copyright (C) 2006-2011 Emma's Software. 3 | // Copyright (C) 2014-2025 Pablo Lezaeta 4 | // Copyright (C) 2014 Pedro A. Aranda Gutiérrez 5 | 6 | // ePDFView - A lightweight PDF Viewer. 7 | // 8 | // 9 | // This program is free software; you can redistribute it and/or modify 10 | // it under the terms of the GNU General Public License as published by 11 | // the Free Software Foundation; either version 2 of the License, or 12 | // (at your option) any later version. 13 | // 14 | // This program is distributed in the hope that it will be useful, 15 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 16 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 | // GNU General Public License for more details. 18 | // 19 | // You should have received a copy of the GNU General Public License 20 | // along with this program; if not, write to the Free Software 21 | // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 22 | 23 | #include 24 | #include "epdfview.h" 25 | 26 | using namespace ePDFView; 27 | 28 | /// 29 | /// @brief Construct a new IDocumentLink object. 30 | /// 31 | /// @param x1 The X coordinate of the link's top-left corner. 32 | /// @param y1 The Y coordinate of the link's top-left corner. 33 | /// @param x2 The X coordinate of the link's bottom-right corner. 34 | /// @param y2 The Y coordinate of the link's bottom-right corner. 35 | /// 36 | IDocumentLink::IDocumentLink (gdouble x1, gdouble y1, gdouble x2, gdouble y2) 37 | { 38 | m_Rect = new DocumentRectangle (x1, y1, x2, y2); 39 | } 40 | 41 | /// 42 | /// @brief Destroys all dynamically allocated memory by IDocumentLink. 43 | /// 44 | IDocumentLink::~IDocumentLink () 45 | { 46 | delete m_Rect; 47 | } 48 | 49 | /// @brief Checks if a position is over the link. 50 | /// 51 | /// This function just check that the given position (x, y) is either 52 | /// inside the link's rectangle (i.e., is over the link) or not. 53 | /// 54 | /// @param x The X coordinate of the position to check. 55 | /// @param y The Y coordinate of the position to check. 56 | /// 57 | /// @return TRUE if the position is over the link. FALSE otherwise. 58 | /// 59 | gboolean 60 | IDocumentLink::positionIsOver (gint x, gint y) 61 | { 62 | return ( (gint)m_Rect->getX1 () <= x && (gint)m_Rect->getY1 () <= y && 63 | (gint)m_Rect->getX2 () >= x && (gint)m_Rect->getY2 () >= y ); 64 | } 65 | -------------------------------------------------------------------------------- /src/JobRender.h: -------------------------------------------------------------------------------- 1 | // ePDFView - A lightweight PDF Viewer. 2 | // Copyright (C) 2006-2011 Emma's Software. 3 | // Copyright (C) 2014-2025 Pablo Lezaeta 4 | // Copyright (C) 2014 Pedro A. Aranda Gutiérrez 5 | 6 | // ePDFView - A lightweight PDF Viewer. 7 | // 8 | // 9 | // This program is free software; you can redistribute it and/or modify 10 | // it under the terms of the GNU General Public License as published by 11 | // the Free Software Foundation; either version 2 of the License, or 12 | // (at your option) any later version. 13 | // 14 | // This program is distributed in the hope that it will be useful, 15 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 16 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 | // GNU General Public License for more details. 18 | // 19 | // You should have received a copy of the GNU General Public License 20 | // along with this program; if not, write to the Free Software 21 | // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 22 | 23 | #if !defined (__JOB_RENDER_H__) 24 | #define __JOB_RENDER_H__ 25 | 26 | namespace ePDFView 27 | { 28 | /// 29 | /// @class JobRender 30 | /// @brief A background job that renders a page. 31 | /// 32 | /// This class is used to render a single page. Render means not only 33 | /// get the image but also the links on that page. 34 | /// 35 | class JobRender: public IJob 36 | { 37 | public: 38 | JobRender (); 39 | ~JobRender (); 40 | 41 | gboolean run (void); 42 | 43 | guint32 getAge (void); 44 | IDocument *getDocument (void); 45 | DocumentPage *getPageImage (void); 46 | gint getPageNumber (void); 47 | void setAge (guint32 age); 48 | void setDocument (IDocument *document); 49 | void setPageNumber (gint pageNumber); 50 | 51 | static gboolean m_CanProcessJobs; 52 | static void setMinAge (guint32 age); 53 | 54 | protected: 55 | /// The job's age. 56 | guint32 m_Age; 57 | /// The class to use to render the page. 58 | IDocument *m_Document; 59 | static guint32 m_MinAge; 60 | /// The page's rendered image. 61 | DocumentPage *m_PageImage; 62 | /// The page's number to render. 63 | gint m_PageNumber; 64 | 65 | }; 66 | } 67 | 68 | #endif // !__JOB_RENDER_H__ 69 | -------------------------------------------------------------------------------- /src/JobLoad.h: -------------------------------------------------------------------------------- 1 | // ePDFView - A lightweight PDF Viewer. 2 | // Copyright (C) 2006-2011 Emma's Software. 3 | // Copyright (C) 2014-2025 Pablo Lezaeta 4 | // Copyright (C) 2014 Pedro A. Aranda Gutiérrez 5 | 6 | // ePDFView - A lightweight PDF Viewer. 7 | // 8 | // 9 | // This program is free software; you can redistribute it and/or modify 10 | // it under the terms of the GNU General Public License as published by 11 | // the Free Software Foundation; either version 2 of the License, or 12 | // (at your option) any later version. 13 | // 14 | // This program is distributed in the hope that it will be useful, 15 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 16 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 | // GNU General Public License for more details. 18 | // 19 | // You should have received a copy of the GNU General Public License 20 | // along with this program; if not, write to the Free Software 21 | // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 22 | 23 | #if !defined (__JOB_LOAD_H__) 24 | #define __JOB_LOAD_H__ 25 | 26 | namespace ePDFView 27 | { 28 | // Forward declarations. 29 | class IDocument; 30 | 31 | /// 32 | /// @class JobLoad 33 | /// @brief A background job that loads a file. 34 | /// 35 | /// This class is used to load and reload the PDF files. 36 | /// 37 | class JobLoad: public IJob 38 | { 39 | public: 40 | JobLoad (void); 41 | ~JobLoad (void); 42 | 43 | IDocument &getDocument (void); 44 | GError *getError (void); 45 | const gchar *getFileName (void); 46 | const gchar *getPassword (void); 47 | gboolean isReloading (void); 48 | gboolean run (void); 49 | void setDocument (IDocument *document); 50 | void setError (GError *error); 51 | void setFileName (const gchar *fileName); 52 | void setPassword (const gchar *password); 53 | void setReload (gboolean reload); 54 | 55 | protected: 56 | /// The document to notify when loaded or on error. 57 | IDocument *m_Document; 58 | /// The error produced when loading. 59 | GError *m_Error; 60 | /// The file name to load or reload. 61 | gchar *m_FileName; 62 | /// The password to use when loading the file. 63 | gchar *m_Password; 64 | /// Tells if we are reloading or loading from new. 65 | gboolean m_Reload; 66 | }; 67 | } 68 | 69 | #endif // __JOB_LOAD_H__ 70 | -------------------------------------------------------------------------------- /tests/DumbDocument.h: -------------------------------------------------------------------------------- 1 | // ePDFView - A lightweight PDF Viewer. 2 | // Copyright (C) 2006-2011 Emma's Software. 3 | // Copyright (C) 2014-2025 Pablo Lezaeta 4 | // Copyright (C) 2014 Pedro A. Aranda Gutiérrez 5 | 6 | // ePDFView - Dumb Test Document. 7 | // 8 | // 9 | // This program is free software; you can redistribute it and/or modify 10 | // it under the terms of the GNU General Public License as published by 11 | // the Free Software Foundation; either version 2 of the License, or 12 | // (at your option) any later version. 13 | // 14 | // This program is distributed in the hope that it will be useful, 15 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 16 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 | // GNU General Public License for more details. 18 | // 19 | // You should have received a copy of the GNU General Public License 20 | // along with this program; if not, write to the Free Software 21 | // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 22 | 23 | #if !defined(__DUMB_DOCUMENT_H__) 24 | #define __DUMB_DOCUMENT_H__ 25 | 26 | namespace ePDFView 27 | { 28 | class DumbDocument: public IDocument 29 | { 30 | public: 31 | DumbDocument (); 32 | ~DumbDocument (); 33 | 34 | // Interface methods. 35 | IDocument *copy (void) const; 36 | GList *findTextInPage (gint pageNum, const gchar *text); 37 | gboolean isLoaded (void); 38 | gboolean loadFile (const gchar *filename, const gchar *password, 39 | GError **error); 40 | void getPageSizeForPage (gint pageNum, gdouble *width, 41 | gdouble *height); 42 | void outputPostscriptBegin (const gchar *fileName, guint numberOfPages, gfloat pageWidth, gfloat pageHeight); 43 | void outputPostscriptEnd (void); 44 | void outputPostscriptPage (guint pageNumber); 45 | DocumentPage *renderPage (gint pageNum); 46 | gboolean saveFile (const gchar *fileName, GError **error); 47 | 48 | // Test functions. 49 | const gchar *getSavedFileName (void); 50 | void setOpenError (DocumentError error); 51 | void setOutline (DocumentOutline *outline); 52 | void setTestPassword (const gchar *password); 53 | 54 | private: 55 | gboolean m_Loaded; 56 | DocumentError m_OpenError; 57 | gchar *m_TestPassword; 58 | gchar *m_SavedFileName; 59 | }; 60 | } 61 | 62 | #endif // !__DUMB_DOCUMENT_H__ 63 | -------------------------------------------------------------------------------- /tests/PDFDocumentTest.h: -------------------------------------------------------------------------------- 1 | // ePDFView - A lightweight PDF Viewer. 2 | // Copyright (C) 2006-2011 Emma's Software. 3 | // Copyright (C) 2014-2025 Pablo Lezaeta 4 | // Copyright (C) 2014 Pedro A. Aranda Gutiérrez 5 | 6 | // ePDFView - PDF Document Test Fixture. 7 | // 8 | // 9 | // This program is free software; you can redistribute it and/or modify 10 | // it under the terms of the GNU General Public License as published by 11 | // the Free Software Foundation; either version 2 of the License, or 12 | // (at your option) any later version. 13 | // 14 | // This program is distributed in the hope that it will be useful, 15 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 16 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 | // GNU General Public License for more details. 18 | // 19 | // You should have received a copy of the GNU General Public License 20 | // along with this program; if not, write to the Free Software 21 | // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 22 | 23 | #if !defined (__PDF_DOCUMENT_TEST_H__) 24 | #define __PDF_DOCUMENT_TEST_H__ 25 | 26 | #include 27 | 28 | namespace ePDFView 29 | { 30 | class PDFDocumentTest: public CppUnit::TestFixture 31 | { 32 | CPPUNIT_TEST_SUITE (PDFDocumentTest); 33 | CPPUNIT_TEST (emptyDocument); 34 | CPPUNIT_TEST (fileNotFound); 35 | CPPUNIT_TEST (invalidFile); 36 | CPPUNIT_TEST (encryptedFile); 37 | CPPUNIT_TEST (validFile); 38 | CPPUNIT_TEST (relativePath); 39 | CPPUNIT_TEST (pageChange); 40 | CPPUNIT_TEST (pageRotate); 41 | CPPUNIT_TEST (pageZoom); 42 | CPPUNIT_TEST (pageRender); 43 | CPPUNIT_TEST (pageLinks); 44 | CPPUNIT_TEST (pageFindText); 45 | CPPUNIT_TEST_SUITE_END (); 46 | 47 | public: 48 | void setUp (void); 49 | void tearDown (void); 50 | 51 | void emptyDocument (void); 52 | void fileNotFound (void); 53 | void invalidFile (void); 54 | void encryptedFile (void); 55 | void validFile (void); 56 | void relativePath (void); 57 | void pageChange (void); 58 | void pageRotate (void); 59 | void pageZoom (void); 60 | void pageRender (void); 61 | void pageLinks (void); 62 | void pageFindText (void); 63 | 64 | private: 65 | PDFDocument *m_Document; 66 | DumbDocumentObserver *m_Observer; 67 | }; 68 | } 69 | 70 | #endif // !__PDF_DOCUMENT_TEST_H__ 71 | -------------------------------------------------------------------------------- /tests/PreferencesPterTest.cxx: -------------------------------------------------------------------------------- 1 | // ePDFView - A lightweight PDF Viewer. 2 | // Copyright (C) 2006-2011 Emma's Software. 3 | // Copyright (C) 2014-2025 Pablo Lezaeta 4 | // Copyright (C) 2014 Pedro A. Aranda Gutiérrez 5 | 6 | // ePDFView - Preferences Presenter Test Fixture. 7 | // 8 | // 9 | // This program is free software; you can redistribute it and/or modify 10 | // it under the terms of the GNU General Public License as published by 11 | // the Free Software Foundation; either version 2 of the License, or 12 | // (at your option) any later version. 13 | // 14 | // This program is distributed in the hope that it will be useful, 15 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 16 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 | // GNU General Public License for more details. 18 | // 19 | // You should have received a copy of the GNU General Public License 20 | // along with this program; if not, write to the Free Software 21 | // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 22 | 23 | #include 24 | #include "DumbPreferencesView.h" 25 | #include "PreferencesPterTest.h" 26 | 27 | using namespace ePDFView; 28 | 29 | // Register the test suite into the `registry'. 30 | CPPUNIT_TEST_SUITE_REGISTRATION (PreferencesPterTest); 31 | 32 | /// 33 | /// @brief Sets up the environment for each test. 34 | /// 35 | void 36 | PreferencesPterTest::setUp () 37 | { 38 | Config::loadFile (FALSE); 39 | m_PreferencesPter = new PreferencesPter (); 40 | m_View = new DumbPreferencesView (); 41 | m_PreferencesPter->setView (m_View); 42 | } 43 | 44 | /// 45 | /// @brief Cleans up after each test. 46 | /// 47 | void 48 | PreferencesPterTest::tearDown () 49 | { 50 | Config::destroy (); 51 | // Telling the presenter to close will delete the view and the presenter. 52 | m_PreferencesPter->closeActivated (); 53 | m_PreferencesPter = NULL; 54 | m_View = NULL; 55 | } 56 | 57 | /// 58 | /// @brief Test setting the external browser command line. 59 | /// 60 | void 61 | PreferencesPterTest::externalCommandBrowser () 62 | { 63 | Config &config = Config::getConfig (); 64 | 65 | gchar *commandLine = config.getExternalBrowserCommandLine (); 66 | CPPUNIT_ASSERT ( 0 == g_ascii_strcasecmp ("firefox %s", commandLine)); 67 | g_free (commandLine); 68 | 69 | m_View->setBrowserCommandLine ("Eterm links %s"); 70 | m_PreferencesPter->browserCommandLineChanged (); 71 | 72 | commandLine = config.getExternalBrowserCommandLine (); 73 | CPPUNIT_ASSERT ( 0 == g_ascii_strcasecmp ("Eterm links %s", commandLine)); 74 | g_free (commandLine); 75 | } 76 | -------------------------------------------------------------------------------- /src/gtk/StockIcons.h: -------------------------------------------------------------------------------- 1 | // ePDFView - A lightweight PDF Viewer. 2 | // Copyright (C) 2006-2011 Emma's Software. 3 | // Copyright (C) 2014-2025 Pablo Lezaeta 4 | // Copyright (C) 2014 Pedro A. Aranda Gutiérrez 5 | 6 | // ePDFView - A lightweight PDF Viewer. 7 | // 8 | // 9 | // This program is free software; you can redistribute it and/or modify 10 | // it under the terms of the GNU General Public License as published by 11 | // the Free Software Foundation; either version 2 of the License, or 12 | // (at your option) any later version. 13 | // 14 | // This program is distributed in the hope that it will be useful, 15 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 16 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 | // GNU General Public License for more details. 18 | // 19 | // You should have received a copy of the GNU General Public License 20 | // along with this program; if not, write to the Free Software 21 | // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 22 | 23 | #if !defined (__STOCK_ICONS_H__) 24 | #define __STOCK_ICONS_H__ 25 | 26 | #include 27 | 28 | G_BEGIN_DECLS 29 | 30 | // GTK4 stock icon replacements - use named icons instead of deprecated stock icons 31 | #define GTK_STOCK_ABOUT "help-about" 32 | #define GTK_STOCK_ADD "list-add" 33 | #define GTK_STOCK_CANCEL "process-stop" 34 | #define GTK_STOCK_CLOSE "window-close" 35 | #define GTK_STOCK_DIALOG_AUTHENTICATION "dialog-password" 36 | #define GTK_STOCK_FIND "edit-find" 37 | #define GTK_STOCK_FULLSCREEN "view-fullscreen" 38 | #define GTK_STOCK_GO_BACK "go-previous" 39 | #define GTK_STOCK_GO_FORWARD "go-next" 40 | #define GTK_STOCK_GO_TO_FIRST "go-first" 41 | #define GTK_STOCK_GO_TO_LAST "go-last" 42 | #define GTK_STOCK_OK "dialog-ok" 43 | #define GTK_STOCK_OPEN "document-open" 44 | #define GTK_STOCK_PREFERENCES "preferences-system" 45 | #define GTK_STOCK_PRINT "document-print" 46 | #define GTK_STOCK_SAVE "document-save" 47 | #define GTK_STOCK_SAVE_AS "document-save-as" 48 | #define GTK_STOCK_ZOOM_100 "zoom-original" 49 | #define GTK_STOCK_ZOOM_FIT "zoom-fit-best" 50 | #define GTK_STOCK_ZOOM_IN "zoom-in" 51 | #define GTK_STOCK_ZOOM_OUT "zoom-out" 52 | 53 | // ePDFView stock icons. 54 | #define EPDFVIEW_STOCK_FIND_NEXT "epdfview_find-next" 55 | #define EPDFVIEW_STOCK_FIND_PREVIOUS "epdfview_find-previous" 56 | #define EPDFVIEW_STOCK_ROTATE_LEFT "epdfview_rotate-left" 57 | #define EPDFVIEW_STOCK_ROTATE_RIGHT "epdfview_rotate-right" 58 | #define EPDFVIEW_STOCK_ZOOM_WIDTH "epdfview_zoom-width" 59 | 60 | void epdfview_stock_icons_init (void); 61 | 62 | G_END_DECLS 63 | 64 | #endif // !__STOCK_ICONS_H__ 65 | -------------------------------------------------------------------------------- /BUILD_WINDOWS.md: -------------------------------------------------------------------------------- 1 | # Building ePDFView on Windows 2 | 3 | ## Prerequisites 4 | 5 | 1. **Install MSYS2** 6 | - Download from: https://www.msys2.org/ 7 | - Install to default location: `C:\msys64` 8 | - After installation, run MSYS2 and update packages: 9 | ```bash 10 | pacman -Syu 11 | ``` 12 | 13 | 2. **Install Build Dependencies** 14 | - Open MSYS2 MinGW 64-bit terminal 15 | - Run: 16 | ```bash 17 | pacman -S --needed mingw-w64-x86_64-gcc \ 18 | mingw-w64-x86_64-meson \ 19 | mingw-w64-x86_64-ninja \ 20 | mingw-w64-x86_64-gtk4 \ 21 | mingw-w64-x86_64-poppler \ 22 | mingw-w64-x86_64-gettext 23 | ``` 24 | 25 | ## Building 26 | 27 | ### Option 1: Using PowerShell Script (Recommended) 28 | 29 | 1. Open PowerShell as Administrator 30 | 2. Navigate to the ePDFView directory 31 | 3. Run: 32 | ```powershell 33 | .\build-windows.ps1 34 | ``` 35 | 36 | ### Option 2: Using Batch Script 37 | 38 | 1. Open Command Prompt 39 | 2. Navigate to the ePDFView directory 40 | 3. Run: 41 | ```batch 42 | build-windows.bat 43 | ``` 44 | 45 | ### Option 3: Manual Build 46 | 47 | 1. Open MSYS2 MinGW 64-bit terminal 48 | 2. Navigate to the ePDFView directory 49 | 3. Run: 50 | ```bash 51 | meson setup build-windows --buildtype=release --prefix=/mingw64 52 | meson compile -C build-windows 53 | ``` 54 | 55 | ## Running 56 | 57 | After building, the executable will be at: 58 | ``` 59 | build-windows\src\epdfview.exe 60 | ``` 61 | 62 | To run it, you need the MSYS2 MinGW 64-bit environment. Either: 63 | - Run from MSYS2 MinGW 64-bit terminal: `./build-windows/src/epdfview.exe` 64 | - Or copy required DLLs from `C:\msys64\mingw64\bin` to the same folder as the executable 65 | 66 | ## Distribution 67 | 68 | To create a distributable package, you'll need to bundle the executable with its dependencies: 69 | 70 | 1. Create a folder for the package 71 | 2. Copy `epdfview.exe` 72 | 3. Use `ldd` to find required DLLs: 73 | ```bash 74 | ldd build-windows/src/epdfview.exe 75 | ``` 76 | 4. Copy all mingw64 DLLs to the package folder 77 | 5. Copy GTK4 runtime files (icons, schemas, etc.) 78 | 79 | ## Troubleshooting 80 | 81 | - **MSYS2 not found**: Make sure MSYS2 is installed at `C:\msys64` 82 | - **Build fails**: Update MSYS2 packages with `pacman -Syu` 83 | - **Missing DLLs**: Ensure you're using MSYS2 MinGW 64-bit terminal, not MSYS2 MSYS terminal 84 | 85 | ## Notes 86 | 87 | - ePDFView uses C++14 standard without GNU extensions for maximum portability 88 | - GTK4 on Windows is fully supported through MSYS2/MinGW 89 | - For native MSVC builds, additional work would be needed (not currently supported) 90 | -------------------------------------------------------------------------------- /src/DocumentLinkUri.cxx: -------------------------------------------------------------------------------- 1 | // ePDFView - A lightweight PDF Viewer. 2 | // Copyright (C) 2006-2011 Emma's Software. 3 | // Copyright (C) 2014-2025 Pablo Lezaeta 4 | // Copyright (C) 2014 Pedro A. Aranda Gutiérrez 5 | 6 | // ePDFView - A lightweight PDF Viewer. 7 | // 8 | // 9 | // This program is free software; you can redistribute it and/or modify 10 | // it under the terms of the GNU General Public License as published by 11 | // the Free Software Foundation; either version 2 of the License, or 12 | // (at your option) any later version. 13 | // 14 | // This program is distributed in the hope that it will be useful, 15 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 16 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 | // GNU General Public License for more details. 18 | // 19 | // You should have received a copy of the GNU General Public License 20 | // along with this program; if not, write to the Free Software 21 | // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 22 | 23 | #include 24 | #include "epdfview.h" 25 | 26 | using namespace ePDFView; 27 | 28 | /// 29 | /// @brief Construct a new DocumentLinkUri object. 30 | /// 31 | /// @param x1 The X coordinate of the link's top-left corner. 32 | /// @param y1 The Y coordinate of the link's top-left corner. 33 | /// @param x2 The X coordinate of the link's bottom-right corner. 34 | /// @param y2 The Y coordinate of the link's bottom-right corner. 35 | /// @param uri The URI the links points to. 36 | /// 37 | DocumentLinkUri::DocumentLinkUri (gdouble x1, gdouble y1, 38 | gdouble x2, gdouble y2, const gchar *uri): 39 | IDocumentLink (x1, y1, x2, y2) 40 | { 41 | g_assert (NULL != uri && "The URI for the link is NULL."); 42 | 43 | m_Uri = g_strdup (uri); 44 | } 45 | 46 | /// 47 | /// @brief Destroys all dynamically allocated memory by DocumentLinkUri. 48 | /// 49 | DocumentLinkUri::~DocumentLinkUri () 50 | { 51 | g_free (m_Uri); 52 | } 53 | 54 | /// 55 | /// @brief Activates the link. 56 | /// 57 | /// @param document The document where the link was activated from. 58 | /// 59 | void 60 | DocumentLinkUri::activate (IDocument *document) 61 | { 62 | // Create the command line to execute the external browser. 63 | gchar *userCommandLine = 64 | Config::getConfig ().getExternalBrowserCommandLine (); 65 | gchar *commandLine = g_strdup_printf (userCommandLine, m_Uri); 66 | g_free (userCommandLine); 67 | // Call the browser. 68 | GError *error = NULL; 69 | if ( !g_spawn_command_line_async (commandLine, &error) ) 70 | { 71 | g_error_free (error); 72 | } 73 | g_free (commandLine); 74 | } 75 | -------------------------------------------------------------------------------- /src/FindPter.h: -------------------------------------------------------------------------------- 1 | // ePDFView - A lightweight PDF Viewer. 2 | // Copyright (C) 2006-2011 Emma's Software. 3 | // Copyright (C) 2014-2025 Pablo Lezaeta 4 | // Copyright (C) 2014 Pedro A. Aranda Gutiérrez 5 | 6 | // ePDFView - A lightweight PDF Viewer. 7 | // 8 | // 9 | // This program is free software; you can redistribute it and/or modify 10 | // it under the terms of the GNU General Public License as published by 11 | // the Free Software Foundation; either version 2 of the License, or 12 | // (at your option) any later version. 13 | // 14 | // This program is distributed in the hope that it will be useful, 15 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 16 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 | // GNU General Public License for more details. 18 | // 19 | // You should have received a copy of the GNU General Public License 20 | // along with this program; if not, write to the Free Software 21 | // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 22 | 23 | #if !defined (__FIND_PTER_H__) 24 | #define __FIND_PTER_H__ 25 | 26 | namespace ePDFView 27 | { 28 | // Forward declarations. 29 | class JobFind; 30 | 31 | /// 32 | /// @class FindPter 33 | /// @brief Find bar presenter. 34 | /// 35 | /// This presenter is the controlling class of the find bar and 36 | /// the find next / previous functionality. 37 | /// 38 | class FindPter 39 | { 40 | public: 41 | FindPter (IDocument *document); 42 | ~FindPter (void); 43 | 44 | void closeActivated (void); 45 | void findNextActivated (void); 46 | void findPreviousActivated (void); 47 | IFindView &getView (void); 48 | void notifyFindFinished (gboolean endOfSearch); 49 | void notifyFindResults (gint pageNum, GList *results, 50 | FindDirection direction); 51 | void setView (IFindView *view); 52 | void textToFindChanged (void); 53 | 54 | protected: 55 | /// The current selected match from m_FindResults. 56 | GList *m_CurrentMatch; 57 | /// The document to search to. 58 | IDocument *m_Document; 59 | /// The current page that we found something. 60 | gint m_FindPage; 61 | /// The results on m_FindPage. 62 | GList *m_FindResults; 63 | /// The current find job. 64 | JobFind *m_Job; 65 | /// The view that the presenter is controlling. 66 | IFindView *m_View; 67 | 68 | void cancelJob (void); 69 | void freeFindResults (void); 70 | }; 71 | } 72 | 73 | #endif // !__FIND_PTER_H__ 74 | -------------------------------------------------------------------------------- /src/gtk/FindView.h: -------------------------------------------------------------------------------- 1 | // ePDFView - A lightweight PDF Viewer. 2 | // Copyright (C) 2006-2011 Emma's Software. 3 | // Copyright (C) 2014-2025 Pablo Lezaeta 4 | // Copyright (C) 2014 Pedro A. Aranda Gutiérrez 5 | 6 | // ePDFView - A lightweight PDF Viewer. 7 | // 8 | // 9 | // This program is free software; you can redistribute it and/or modify 10 | // it under the terms of the GNU General Public License as published by 11 | // the Free Software Foundation; either version 2 of the License, or 12 | // (at your option) any later version. 13 | // 14 | // This program is distributed in the hope that it will be useful, 15 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 16 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 | // GNU General Public License for more details. 18 | // 19 | // You should have received a copy of the GNU General Public License 20 | // along with this program; if not, write to the Free Software 21 | // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 22 | 23 | #if !defined (__FIND_VIEW_H__) 24 | #define __FIND_VIEW_H__ 25 | 26 | namespace ePDFView 27 | { 28 | // Forward declarations. 29 | class FindPter; 30 | 31 | class FindView: public IFindView 32 | { 33 | public: 34 | FindView (); 35 | ~FindView (void); 36 | 37 | const gchar *getTextToFind (void); 38 | void hide (void); 39 | void sensitiveFindNext (gboolean sensitive); 40 | void sensitiveFindPrevious (gboolean sensitive); 41 | void setInformationText (const gchar *text); 42 | void setPresenter (FindPter *pter); 43 | 44 | // GTK+ Functions. 45 | GtkWidget *getTopWidget (void); 46 | 47 | protected: 48 | // Member variables. 49 | GtkWidget *m_FindBar; 50 | GtkWidget *m_Close; 51 | GtkWidget *m_TextToFind; 52 | GtkWidget *m_FindNext; 53 | GtkWidget *m_FindPrevious; 54 | GtkWidget *m_InformationText; 55 | 56 | // Callbacks 57 | friend void find_view_close_cb (GtkWidget *widget, gpointer data); 58 | friend void find_view_next_cb (GtkWidget *widget, gpointer data); 59 | friend void find_view_previous_cb (GtkWidget *widget, gpointer data); 60 | friend void find_view_text_to_find_activate_cb (GtkEntry *entry, gpointer data); 61 | friend void find_view_text_to_find_changed_cb (GtkEntry *entry, gpointer data); 62 | friend gboolean find_view_text_to_find_key_press_cb (GtkEventControllerKey *controller, guint keyval, guint keycode, GdkModifierType state, gpointer data); 63 | }; 64 | } 65 | 66 | #endif // !__FIND_VIEW_H__ 67 | -------------------------------------------------------------------------------- /src/IJob.h: -------------------------------------------------------------------------------- 1 | // ePDFView - A lightweight PDF Viewer. 2 | // Copyright (C) 2006-2011 Emma's Software. 3 | // Copyright (C) 2014-2025 Pablo Lezaeta 4 | // Copyright (C) 2014 Pedro A. Aranda Gutiérrez 5 | 6 | // ePDFView - A lightweight PDF Viewer. 7 | // 8 | // 9 | // This program is free software; you can redistribute it and/or modify 10 | // it under the terms of the GNU General Public License as published by 11 | // the Free Software Foundation; either version 2 of the License, or 12 | // (at your option) any later version. 13 | // 14 | // This program is distributed in the hope that it will be useful, 15 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 16 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 | // GNU General Public License for more details. 18 | // 19 | // You should have received a copy of the GNU General Public License 20 | // along with this program; if not, write to the Free Software 21 | // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 22 | 23 | #if !defined (__IJOB_H__) 24 | #define __IJOB_H__ 25 | 26 | #if defined DEBUG 27 | #define JOB_NOTIFIER(callback, data) callback (data) 28 | #define JOB_DELETE TRUE 29 | #define JOB_NOTIFIER_END() 30 | #else // !DEBUG 31 | #define JOB_NOTIFIER(callback, data) g_idle_add (callback, data) 32 | #define JOB_DELETE FALSE 33 | #define JOB_NOTIFIER_END() delete job 34 | #endif // !DEBUG 35 | 36 | namespace ePDFView 37 | { 38 | /// @class IJob 39 | /// @brief Interface for jobs. 40 | /// 41 | /// A Job is simply a process that will be processed in background 42 | /// by the dispatch() function. 43 | /// 44 | class IJob 45 | { 46 | public: 47 | /// @brief Destroys all dynamically allocated memory for IJob. 48 | virtual ~IJob (void) { } 49 | 50 | static void clearQueue (void); 51 | static gpointer dispatcher (gpointer data); 52 | static void init (void); 53 | static void enqueue (IJob *job); 54 | 55 | /// 56 | /// @brief Runs the job. 57 | /// 58 | /// This is called by the dispatcher() function when 59 | /// the job must start its work. It's the job's entry point. 60 | /// 61 | /// @return TRUE if the job must be deleted after the 62 | /// call to run(). FALSE if the job will be 63 | /// deleted by himself. 64 | /// 65 | virtual gboolean run (void) = 0; 66 | 67 | protected: 68 | static GAsyncQueue *m_JobsQueue; 69 | 70 | /// @brief Creates a new IJob object. 71 | IJob () { } 72 | }; 73 | } 74 | 75 | #endif // __IJOB_H__ 76 | -------------------------------------------------------------------------------- /.github/workflows/build.yml: -------------------------------------------------------------------------------- 1 | name: Build and Test 2 | 3 | on: 4 | push: 5 | branches: [ main, master ] 6 | pull_request: 7 | branches: [ main, master ] 8 | 9 | jobs: 10 | build-linux: 11 | name: Build on Linux 12 | runs-on: ubuntu-latest 13 | 14 | steps: 15 | - uses: actions/checkout@v4 16 | 17 | - name: Install dependencies 18 | run: | 19 | sudo apt-get update 20 | sudo apt-get install -y meson ninja-build libgtk-4-dev libpoppler-glib-dev libcups2-dev gettext 21 | 22 | - name: Configure 23 | run: meson setup builddir --buildtype=release 24 | 25 | - name: Build 26 | run: meson compile -C builddir 27 | 28 | - name: Test 29 | run: meson test -C builddir || true 30 | 31 | - name: Upload artifact 32 | uses: actions/upload-artifact@v4 33 | with: 34 | name: epdfview-linux 35 | path: builddir/src/epdfview 36 | 37 | build-freebsd: 38 | name: Build on FreeBSD 39 | runs-on: ubuntu-latest 40 | 41 | steps: 42 | - uses: actions/checkout@v4 43 | 44 | - name: Build in FreeBSD VM 45 | uses: vmactions/freebsd-vm@v1 46 | with: 47 | # Use default FreeBSD shell (sh/tcsh) instead of bash 48 | # usesh: true causes "bash: not found" errors 49 | prepare: | 50 | pkg install -y meson ninja gtk4 poppler-glib cups gettext-tools 51 | run: | 52 | meson setup builddir --buildtype=release 53 | meson compile -C builddir 54 | 55 | - name: Upload artifact 56 | uses: actions/upload-artifact@v4 57 | with: 58 | name: epdfview-freebsd 59 | path: builddir/src/epdfview 60 | 61 | build-windows: 62 | name: Build on Windows (MSYS2) 63 | runs-on: windows-latest 64 | defaults: 65 | run: 66 | shell: msys2 {0} 67 | 68 | steps: 69 | - uses: actions/checkout@v4 70 | 71 | - name: Setup MSYS2 72 | uses: msys2/setup-msys2@v2 73 | with: 74 | msystem: MINGW64 75 | update: true 76 | install: >- 77 | mingw-w64-x86_64-gcc 78 | mingw-w64-x86_64-meson 79 | mingw-w64-x86_64-ninja 80 | mingw-w64-x86_64-gtk4 81 | mingw-w64-x86_64-poppler 82 | mingw-w64-x86_64-gettext 83 | mingw-w64-x86_64-pkg-config 84 | 85 | - name: Configure 86 | run: meson setup builddir --buildtype=release 87 | 88 | - name: Build 89 | run: meson compile -C builddir 90 | 91 | - name: Test 92 | run: meson test -C builddir || true 93 | 94 | - name: Upload artifact 95 | uses: actions/upload-artifact@v4 96 | with: 97 | name: epdfview-windows 98 | path: builddir/src/epdfview.exe -------------------------------------------------------------------------------- /tests/DumbFindView.cxx: -------------------------------------------------------------------------------- 1 | // ePDFView - A lightweight PDF Viewer. 2 | // Copyright (C) 2006-2011 Emma's Software. 3 | // Copyright (C) 2014-2025 Pablo Lezaeta 4 | // Copyright (C) 2014 Pedro A. Aranda Gutiérrez 5 | 6 | // ePDFView - Dumb Test Find View. 7 | // 8 | // 9 | // This program is free software; you can redistribute it and/or modify 10 | // it under the terms of the GNU General Public License as published by 11 | // the Free Software Foundation; either version 2 of the License, or 12 | // (at your option) any later version. 13 | // 14 | // This program is distributed in the hope that it will be useful, 15 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 16 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 | // GNU General Public License for more details. 18 | // 19 | // You should have received a copy of the GNU General Public License 20 | // along with this program; if not, write to the Free Software 21 | // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 22 | 23 | #include 24 | #include "DumbFindView.h" 25 | 26 | using namespace ePDFView; 27 | 28 | DumbFindView::DumbFindView (): 29 | IFindView () 30 | { 31 | m_FindNextSensitive = TRUE; 32 | m_FindNextSensitive = TRUE; 33 | m_InformationText = g_strdup (""); 34 | m_TextToFind = g_strdup (""); 35 | } 36 | 37 | DumbFindView::~DumbFindView () 38 | { 39 | g_free (m_InformationText); 40 | g_free (m_TextToFind); 41 | } 42 | 43 | const gchar * 44 | DumbFindView::getTextToFind () 45 | { 46 | return m_TextToFind; 47 | } 48 | 49 | void 50 | DumbFindView::hide () 51 | { 52 | } 53 | 54 | void 55 | DumbFindView::sensitiveFindNext (gboolean sensitive) 56 | { 57 | m_FindNextSensitive = sensitive; 58 | } 59 | 60 | void 61 | DumbFindView::sensitiveFindPrevious (gboolean sensitive) 62 | { 63 | m_FindPreviousSensitive = sensitive; 64 | } 65 | 66 | void 67 | DumbFindView::setInformationText (const gchar *text) 68 | { 69 | g_free (m_InformationText); 70 | m_InformationText = g_strdup (text); 71 | } 72 | 73 | //////////////////////////////////////////////////////////////// 74 | // Test Only Functions. 75 | //////////////////////////////////////////////////////////////// 76 | 77 | const gchar * 78 | DumbFindView::getInformationText () 79 | { 80 | return m_InformationText; 81 | } 82 | 83 | gboolean 84 | DumbFindView::isFindNextSensitive () 85 | { 86 | return m_FindNextSensitive; 87 | } 88 | 89 | gboolean 90 | DumbFindView::isFindPreviousSensitive () 91 | { 92 | return m_FindPreviousSensitive; 93 | } 94 | 95 | void 96 | DumbFindView::setTextToFind (const gchar *text) 97 | { 98 | g_free (m_TextToFind); 99 | m_TextToFind = g_strdup (text); 100 | getPresenter ()->textToFindChanged (); 101 | } 102 | -------------------------------------------------------------------------------- /.kiro/steering/structure.md: -------------------------------------------------------------------------------- 1 | # Project Structure & Architecture 2 | 3 | ## Directory Organization 4 | 5 | ``` 6 | ├── src/ # Main source code 7 | │ ├── gtk/ # GTK4-specific UI implementations 8 | │ ├── *.h *.cxx # Core application logic 9 | │ └── main.cxx # Application entry point 10 | ├── tests/ # Unit tests (CppUnit) 11 | ├── data/ # Application resources 12 | │ ├── *.desktop # Desktop integration files 13 | │ ├── *.svg *.png # Icons and images 14 | │ └── *.xml # UI definitions 15 | ├── po/ # Internationalization files 16 | ├── doc/ # Documentation 17 | ├── m4/ # Autotools macros 18 | ├── intl/ # GNU gettext internationalization 19 | └── builddir/ # Meson build output (generated) 20 | ``` 21 | 22 | ## Architecture Patterns 23 | 24 | ### MVP (Model-View-Presenter) 25 | - **Model**: `PDFDocument`, `DocumentPage`, `DocumentOutline` classes 26 | - **View**: Interface classes (`IMainView`, `IPageView`, etc.) with GTK implementations 27 | - **Presenter**: `MainPter`, `PagePter`, `FindPter` classes that coordinate between model and view 28 | 29 | ### Interface Segregation 30 | - Abstract interfaces define contracts (`IDocument`, `IMainView`, `IPageView`) 31 | - Concrete implementations in `src/gtk/` for GTK4-specific code 32 | - Clean separation between business logic and UI toolkit 33 | 34 | ### Observer Pattern 35 | - `IDocumentObserver` interface for document state changes 36 | - Presenters observe document events and update views accordingly 37 | 38 | ## File Naming Conventions 39 | 40 | - **Headers**: `.h` extension 41 | - **Implementation**: `.cxx` extension (not `.cpp`) 42 | - **Interfaces**: Prefixed with `I` (e.g., `IMainView.h`) 43 | - **Presenters**: Suffixed with `Pter` (e.g., `MainPter.h`) 44 | - **GTK Views**: Located in `src/gtk/` directory 45 | 46 | ## Code Organization 47 | 48 | ### Core Components 49 | - `main.cxx` - Application entry point and GTK initialization 50 | - `Config.*` - Application configuration management 51 | - `PDFDocument.*` - PDF document handling via Poppler 52 | - `Job*.*` - Background job system for threading 53 | 54 | ### UI Layer 55 | - `src/gtk/MainView.*` - Main application window 56 | - `src/gtk/PageView.*` - PDF page rendering widget 57 | - `src/gtk/FindView.*` - Search functionality UI 58 | - `src/gtk/GTK4Compat.h` - GTK3/GTK4 compatibility layer 59 | 60 | ### Business Logic 61 | - `MainPter.*` - Main application presenter 62 | - `PagePter.*` - Page display logic 63 | - `FindPter.*` - Search functionality logic 64 | 65 | ## Build Configuration 66 | 67 | - `meson.build` - Modern build system configuration 68 | - `configure.ac` + `Makefile.am` - Legacy autotools configuration 69 | - Conditional compilation for optional features (CUPS, different Poppler versions) -------------------------------------------------------------------------------- /docs/README.md: -------------------------------------------------------------------------------- 1 | # ePDFView Documentation 2 | 3 | This directory contains additional technical documentation for ePDFView. 4 | 5 | ## GTK4 Migration Documentation 6 | 7 | ePDFView was successfully migrated from GTK2/GTK3 to GTK4 in October 2025. 8 | 9 | ### Main Migration Documents 10 | 11 | - **GTK4_MIGRATION_SUMMARY.md** - Complete technical summary of the migration 12 | - All API changes documented 13 | - Before/after code comparisons 14 | - Migration challenges and solutions 15 | 16 | - **COMPLETE_GTK4_MIGRATION.md** - Milestone documentation 17 | - Full feature list 18 | - Testing checklist 19 | - Build instructions 20 | 21 | ### Specific Component Documentation 22 | 23 | - **MENU_SYSTEM_COMPLETE.md** - Menu system implementation 24 | - GMenuModel structure 25 | - Action system 26 | - Keyboard shortcuts 27 | 28 | - **TRANSLATIONS_AND_DOCS.md** - i18n system details 29 | - Meson i18n integration 30 | - 22 language support 31 | 32 | ### Build & Installation 33 | 34 | - **INSTALLATION.md** - Comprehensive installation guide 35 | - Detailed dependency information 36 | - Multiple installation scenarios 37 | - Packaging guidelines 38 | - Troubleshooting 39 | 40 | - **BUILD_STATUS.md** - Build system milestones 41 | - **COMPILATION_SUCCESS.md** - Initial successful build notes 42 | 43 | ### Issue Resolution 44 | 45 | - **FINAL_FIXES.md** - Icon path resolution 46 | - Multiple search path implementation 47 | - Installation location handling 48 | 49 | - **PRINT_MIGRATION_TODO.md** - Print system migration notes 50 | - Completed: Full CUPS integration 51 | - GTK4 dialog implementation 52 | 53 | ## For Developers 54 | 55 | If you're working on ePDFView: 56 | 57 | 1. **Start with** GTK4_MIGRATION_SUMMARY.md to understand the codebase changes 58 | 2. **Reference** COMPLETE_GTK4_MIGRATION.md for feature overview 59 | 3. **Use** INSTALLATION.md for build setup 60 | 4. **See** root CONTRIBUTING file for development guidelines 61 | 62 | ## For Users 63 | 64 | Most users should read the files in the root directory: 65 | 66 | - **README** - Basic usage and features 67 | - **INSTALL** - Installation instructions 68 | - **TRANSLATION** - Translation guide 69 | - **CONTRIBUTING** - How to contribute 70 | 71 | ## History 72 | 73 | ePDFView started as a lightweight PDF viewer for GTK2/GNOME. After years of 74 | maintenance, it was migrated to GTK4 to ensure future compatibility with modern 75 | Linux desktops. 76 | 77 | The migration was completed in October 2025 and included: 78 | - Complete UI reimplementation with GTK4 APIs 79 | - Menu system using GMenuModel 80 | - Event handling with modern controllers 81 | - Print system with CUPS integration 82 | - Build system migration to Meson 83 | - Full i18n support maintained 84 | 85 | ## Status 86 | 87 | ✅ **Migration Complete** 88 | ✅ **All Features Working** 89 | ✅ **Production Ready** 90 | 91 | Version 0.3.0 represents the first stable GTK4 release. 92 | -------------------------------------------------------------------------------- /src/gtk/StockIcons.cxx: -------------------------------------------------------------------------------- 1 | // ePDFView - A lightweight PDF Viewer. 2 | // Copyright (C) 2006-2011 Emma's Software. 3 | // Copyright (C) 2014-2025 Pablo Lezaeta 4 | // Copyright (C) 2014 Pedro A. Aranda Gutiérrez 5 | 6 | // ePDFView - A lightweight PDF Viewer. 7 | // 8 | // 9 | // This program is free software; you can redistribute it and/or modify 10 | // it under the terms of the GNU General Public License as published by 11 | // the Free Software Foundation; either version 2 of the License, or 12 | // (at your option) any later version. 13 | // 14 | // This program is distributed in the hope that it will be useful, 15 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 16 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 | // GNU General Public License for more details. 18 | // 19 | // You should have received a copy of the GNU General Public License 20 | // along with this program; if not, write to the Free Software 21 | // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 22 | 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include "StockIcons.h" 28 | 29 | // GTK4 stock icon definitions moved to StockIcons.h 30 | 31 | // Custom ePDFView icons that need to be loaded from files 32 | static const struct 33 | { 34 | const char *iconName; 35 | const char *iconFile; 36 | } g_CustomIcons[] = 37 | { 38 | { EPDFVIEW_STOCK_FIND_NEXT, "stock_find_next_24.png" }, 39 | { EPDFVIEW_STOCK_FIND_PREVIOUS, "stock_find_previous_24.png" }, 40 | { EPDFVIEW_STOCK_ROTATE_LEFT, "stock_rotate-270.png" }, 41 | { EPDFVIEW_STOCK_ROTATE_RIGHT, "stock_rotate-90.png" }, 42 | { EPDFVIEW_STOCK_ZOOM_WIDTH, "stock_zoom-page-width.png" } 43 | }; 44 | 45 | void 46 | epdfview_stock_icons_init (void) 47 | { 48 | // In GTK4, we add the data directory to the icon theme search path 49 | // This allows the icon theme to find our custom icons 50 | GtkIconTheme *icon_theme = gtk_icon_theme_get_for_display (gdk_display_get_default ()); 51 | 52 | // Add both system and local pixmaps directories 53 | // This handles both /usr/share and /usr/local/share installations 54 | const gchar *search_paths[] = { 55 | "/usr/share/pixmaps", // System location 56 | "/usr/local/share/pixmaps", // Local installation 57 | DATADIR "/pixmaps", // Configured prefix 58 | DATADIR, // Fallback to data dir 59 | NULL 60 | }; 61 | 62 | for (int i = 0; search_paths[i] != NULL; i++) { 63 | if (g_file_test(search_paths[i], G_FILE_TEST_IS_DIR)) { 64 | gtk_icon_theme_add_search_path (icon_theme, search_paths[i]); 65 | } 66 | } 67 | 68 | // The custom icons will be automatically found by their names when requested 69 | // No need to manually load them - GTK4 icon theme handles this 70 | } 71 | -------------------------------------------------------------------------------- /data/epdfview-ui.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | -------------------------------------------------------------------------------- /src/IPreferencesView.h: -------------------------------------------------------------------------------- 1 | // ePDFView - A lightweight PDF Viewer. 2 | // Copyright (C) 2006-2011 Emma's Software. 3 | // Copyright (C) 2014-2025 Pablo Lezaeta 4 | // Copyright (C) 2014 Pedro A. Aranda Gutiérrez 5 | 6 | // ePDFView - A lightweight PDF Viewer. 7 | // 8 | // 9 | // This program is free software; you can redistribute it and/or modify 10 | // it under the terms of the GNU General Public License as published by 11 | // the Free Software Foundation; either version 2 of the License, or 12 | // (at your option) any later version. 13 | // 14 | // This program is distributed in the hope that it will be useful, 15 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 16 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 | // GNU General Public License for more details. 18 | // 19 | // You should have received a copy of the GNU General Public License 20 | // along with this program; if not, write to the Free Software 21 | // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 22 | 23 | #if !defined (__IPREFERENCES_VIEW_H__) 24 | #define __IPREFERENCES_VIEW_H__ 25 | 26 | namespace ePDFView 27 | { 28 | // Forward declarations. 29 | class PreferencesPter; 30 | 31 | /// 32 | /// @class IPreferencesView 33 | /// @brief Interface for the preferences view. 34 | /// 35 | class IPreferencesView 36 | { 37 | public: 38 | /// 39 | /// @brief Destroys all allocated memory for IPreferencesView. 40 | /// 41 | virtual ~IPreferencesView (void) 42 | { 43 | } 44 | 45 | /// 46 | /// @brief Gets the view's presenter. 47 | /// 48 | /// @return The presenter that is controlling the view. 49 | /// 50 | PreferencesPter *getPresenter (void) 51 | { 52 | return m_Pter; 53 | } 54 | 55 | /// 56 | /// @brief Sets the view's presenter. 57 | /// 58 | /// After setting the presenter, the view can show the 59 | /// preferences dialog. 60 | /// 61 | /// @param pter The presenter that will control the view. 62 | /// 63 | virtual void setPresenter (PreferencesPter *pter) 64 | { 65 | m_Pter = pter; 66 | } 67 | 68 | virtual const gchar *getBrowserCommandLine (void) = 0; 69 | virtual const gchar *getBacksearchCommandLine (void) = 0; 70 | 71 | protected: 72 | /// The presenter that controls the view. 73 | PreferencesPter *m_Pter; 74 | 75 | /// 76 | /// @brief Constructs a new IPresenterView object. 77 | /// 78 | IPreferencesView (void) 79 | { 80 | m_Pter = NULL; 81 | } 82 | }; 83 | } 84 | 85 | #endif // !__IPREFERENCES_VIEW_H__ 86 | -------------------------------------------------------------------------------- /meson.build: -------------------------------------------------------------------------------- 1 | project('epdfview', 'cpp', 2 | version : '0.3.0', 3 | default_options : ['warning_level=2', 'cpp_std=c++14', 'werror=false'], 4 | meson_version : '>= 0.50.0', 5 | license : 'GPL-2.0-or-later', 6 | ) 7 | 8 | i18n = import('i18n') 9 | 10 | # Build options 11 | debug_build = get_option('buildtype') == 'debug' 12 | if debug_build 13 | add_project_arguments('-DDEBUG', language : 'cpp') 14 | else 15 | add_project_arguments('-DNDEBUG', '-DG_DISABLE_ASSERT', language : 'cpp') 16 | endif 17 | 18 | # Additional compiler flags 19 | add_project_arguments([ 20 | '-Wno-long-long', 21 | '-Wno-deprecated-declarations', 22 | '-Wno-deprecated', 23 | '-Wno-error=deprecated-declarations', 24 | # GTK4 migration debugging flags - DISABLED for now as they may cause issues 25 | '-DGDK_DISABLE_DEPRECATED', 26 | '-DGTK_DISABLE_DEPRECATED', 27 | '-DG_ENABLE_DIAGNOSTIC=1', 28 | ], language : 'cpp') 29 | 30 | # Dependencies with version requirements 31 | gtk_dep = dependency('gtk4', version : '>= 4.0.0') 32 | poppler_dep = dependency('poppler-glib', version : '>= 0.5.0') 33 | glib_dep = dependency('gthread-2.0', version : '>= 2.8.0') 34 | pango_dep = dependency('pango') 35 | 36 | # Check for CUPS 37 | cups_dep = dependency('cups', required : get_option('cups')) 38 | if cups_dep.found() and host_machine.system() != 'windows' 39 | message('CUPS support: ENABLED') 40 | add_project_arguments('-DHAVE_CUPS=1', language : 'cpp') 41 | else 42 | message('CUPS support: DISABLED') 43 | endif 44 | 45 | # Check for Poppler version 46 | if poppler_dep.version().version_compare('>=0.5.2') 47 | add_project_arguments('-DHAVE_POPPLER_0_5_2=1', language : 'cpp') 48 | endif 49 | if poppler_dep.version().version_compare('>=0.6.0') 50 | add_project_arguments('-DHAVE_POPPLER_0_6_0=1', language : 'cpp') 51 | endif 52 | if poppler_dep.version().version_compare('>=0.8.0') 53 | add_project_arguments('-DHAVE_POPPLER_0_8_0=1', language : 'cpp') 54 | endif 55 | if poppler_dep.version().version_compare('>=0.15.0') 56 | add_project_arguments('-DHAVE_POPPLER_0_15_0=1', language : 'cpp') 57 | endif 58 | if poppler_dep.version().version_compare('>=0.15.1') 59 | add_project_arguments('-DHAVE_POPPLER_0_15_1=1', language : 'cpp') 60 | endif 61 | if poppler_dep.version().version_compare('>=0.17.0') 62 | add_project_arguments('-DHAVE_POPPLER_0_17_0=1', language : 'cpp') 63 | endif 64 | 65 | # Configuration 66 | conf_data = configuration_data() 67 | conf_data.set_quoted('PACKAGE', 'epdfview') 68 | conf_data.set_quoted('VERSION', meson.project_version()) 69 | conf_data.set_quoted('LOCALEDIR', join_paths(get_option('prefix'), get_option('localedir'))) 70 | conf_data.set_quoted('DATADIR', join_paths(get_option('prefix'), get_option('datadir'))) 71 | configure_file(output : 'config.h', configuration : conf_data) 72 | 73 | # Include directories 74 | inc = include_directories('src', '.') 75 | 76 | # Subdirectories 77 | subdir('src') 78 | subdir('data') 79 | subdir('po') 80 | 81 | # Tests (optional) 82 | if get_option('tests') 83 | subdir('tests') 84 | endif -------------------------------------------------------------------------------- /src/DocumentOutline.h: -------------------------------------------------------------------------------- 1 | // ePDFView - A lightweight PDF Viewer. 2 | // Copyright (C) 2006-2011 Emma's Software. 3 | // Copyright (C) 2014-2025 Pablo Lezaeta 4 | // Copyright (C) 2014 Pedro A. Aranda Gutiérrez 5 | 6 | // ePDFView - A lightweight PDF Viewer. 7 | // 8 | // 9 | // This program is free software; you can redistribute it and/or modify 10 | // it under the terms of the GNU General Public License as published by 11 | // the Free Software Foundation; either version 2 of the License, or 12 | // (at your option) any later version. 13 | // 14 | // This program is distributed in the hope that it will be useful, 15 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 16 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 | // GNU General Public License for more details. 18 | // 19 | // You should have received a copy of the GNU General Public License 20 | // along with this program; if not, write to the Free Software 21 | // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 22 | 23 | #if !defined (__DOCUMENT_OUTLINE_H__) 24 | #define __DOCUMENT_OUTLINE_H__ 25 | 26 | namespace ePDFView 27 | { 28 | /// 29 | /// @class DocumentOutline 30 | /// @brief Stores the document's outline title, page num. and its children. 31 | /// 32 | /// Some documents have an index with them. This index can be used to 33 | /// help the user navigate through the document, similar to a table of 34 | /// contents. 35 | /// 36 | /// Each node contains a title, a destination page an possibly children 37 | /// nodes. The only node that have an empty name and a 0 page number is the 38 | /// top level DocumentOutline, that is only used as a container for all 39 | /// other DocumentOutline objects. 40 | /// 41 | class DocumentOutline 42 | { 43 | public: 44 | DocumentOutline (void); 45 | ~DocumentOutline (void); 46 | 47 | void addChild (DocumentOutline *child); 48 | gint getDestinationPage (void); 49 | DocumentOutline *getFirstChild (void); 50 | DocumentOutline *getNextChild (void); 51 | gint getNumChildren (void); 52 | const gchar *getTitle (void); 53 | void setParent (DocumentOutline *parent); 54 | void setTitle (const gchar *title); 55 | void setDestination (gint destination); 56 | 57 | protected: 58 | /// The list of this outline's children. 59 | GList *m_Children; 60 | /// The page number this outline points to. 61 | gint m_Destination; 62 | /// @brief This is used to know which child to return when calling 63 | /// the DocumentOutline::getNextChild() function. 64 | GList *m_LastReturnedChild; 65 | /// The outline's parent outline. 66 | DocumentOutline *m_Parent; 67 | /// The outline's name or title. 68 | gchar *m_Title; 69 | }; 70 | } 71 | 72 | #endif // !__DOCUMENT_OUTLINE_H__ 73 | -------------------------------------------------------------------------------- /src/DocumentPage.h: -------------------------------------------------------------------------------- 1 | // ePDFView - A lightweight PDF Viewer. 2 | // Copyright (C) 2006-2011 Emma's Software. 3 | // Copyright (C) 2014-2025 Pablo Lezaeta 4 | // Copyright (C) 2014 Pedro A. Aranda Gutiérrez 5 | 6 | // ePDFView - A lightweight PDF Viewer. 7 | // 8 | // 9 | // This program is free software; you can redistribute it and/or modify 10 | // it under the terms of the GNU General Public License as published by 11 | // the Free Software Foundation; either version 2 of the License, or 12 | // (at your option) any later version. 13 | // 14 | // This program is distributed in the hope that it will be useful, 15 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 16 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 | // GNU General Public License for more details. 18 | // 19 | // You should have received a copy of the GNU General Public License 20 | // along with this program; if not, write to the Free Software 21 | // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 22 | 23 | #if !defined (__DOCUMENT_PAGE_H__) 24 | #define __DOCUMENT_PAGE_H__ 25 | 26 | typedef struct _cairo_region cairo_region_t; 27 | 28 | namespace ePDFView 29 | { 30 | /// 31 | /// @class DocumentPage 32 | /// @brief A single document's page. 33 | /// 34 | /// Contains the rendered image of a single document's page. 35 | /// 36 | class DocumentPage 37 | { 38 | public: 39 | DocumentPage (void); 40 | ~DocumentPage (void); 41 | 42 | void addLink (IDocumentLink *link); 43 | void clearSelection (void); 44 | guchar *getData (void); 45 | gint getHeight (void); 46 | IDocumentLink *getLinkAtPosition (gint x, gint y); 47 | gint getRowStride (void); 48 | gint getWidth (void); 49 | gboolean hasAlpha (void); 50 | gboolean newPage (gint width, gint height); 51 | void setSelection (DocumentRectangle &selection, gdouble scale); 52 | void setSelection (cairo_region_t *region); 53 | 54 | protected: 55 | /// The page's image. 56 | guchar *m_Data; 57 | /// Tells if the page has a text selection. 58 | gboolean m_HasSelection; 59 | /// The page's height. 60 | gint m_Height; 61 | /// The selection top-left X coordinate. 62 | gint m_SelectionX1; 63 | /// The selection bottom-right X coordinate. 64 | gint m_SelectionX2; 65 | /// The selection top-left Y coordinate. 66 | gint m_SelectionY1; 67 | /// The selection bottom-right Y coordinate. 68 | gint m_SelectionY2; 69 | /// The page's width. 70 | gint m_Width; 71 | /// The list of links from the page. 72 | GList *m_LinkList; 73 | /// Selection region 74 | cairo_region_t *m_Selection; 75 | 76 | void invertRegion (cairo_region_t*); 77 | void invertArea (gint x1, gint y1, gint x2, gint y2); 78 | }; 79 | } 80 | 81 | #endif // !__DOCUMENT_PAGE_H__ 82 | -------------------------------------------------------------------------------- /tests/DumbDocumentObserver.h: -------------------------------------------------------------------------------- 1 | // ePDFView - A lightweight PDF Viewer. 2 | // Copyright (C) 2006-2011 Emma's Software. 3 | // Copyright (C) 2014-2025 Pablo Lezaeta 4 | // Copyright (C) 2014 Pedro A. Aranda Gutiérrez 5 | 6 | // ePDFView - Dumb Test Document Observer. 7 | // 8 | // 9 | // This program is free software; you can redistribute it and/or modify 10 | // it under the terms of the GNU General Public License as published by 11 | // the Free Software Foundation; either version 2 of the License, or 12 | // (at your option) any later version. 13 | // 14 | // This program is distributed in the hope that it will be useful, 15 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 16 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 | // GNU General Public License for more details. 18 | // 19 | // You should have received a copy of the GNU General Public License 20 | // along with this program; if not, write to the Free Software 21 | // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 22 | 23 | #if !defined (__DUMB_DOCUMENT_OBSERVER_H__) 24 | #define __DUMB_DOCUMENT_OBSERVER_H__ 25 | 26 | namespace ePDFView 27 | { 28 | class DumbDocumentObserver: public IDocumentObserver 29 | { 30 | public: 31 | DumbDocumentObserver (void); 32 | ~DumbDocumentObserver (void); 33 | 34 | void notifyFindChanged (DocumentRectangle *matchRect); 35 | void notifyFindFinished (void); 36 | void notifyFindStarted (void); 37 | void notifyLoad (void); 38 | void notifyLoadError (const GError *error); 39 | void notifyLoadPassword (const gchar *fileName, gboolean reload, 40 | const GError *error); 41 | void notifyPageChanged (gint pageNum); 42 | void notifyPageRotated (gint rotation); 43 | void notifyPageZoomed (gdouble zoom); 44 | void notifyReload (void); 45 | 46 | // Functions for test only purposes. 47 | gint getCurrentPage (void); 48 | DocumentRectangle *getFindMatchRect (void); 49 | const GError *getLoadError (void); 50 | gdouble getZoom (void); 51 | gboolean isStillSearching (void); 52 | gboolean loadFinished (void); 53 | gboolean notifiedError (void); 54 | gboolean notifiedLoaded (void); 55 | gboolean notifiedPassword (void); 56 | gboolean notifiedRotation (void); 57 | gboolean notifiedZoom (void); 58 | void setLoadError (const GError *error); 59 | 60 | protected: 61 | gint m_CurrentPage; 62 | GError *m_Error; 63 | DocumentRectangle *m_FindMatchRect; 64 | gboolean m_NotifiedError; 65 | gboolean m_NotifiedLoad; 66 | gboolean m_NotifiedPassword; 67 | gboolean m_NotifiedPageRotated; 68 | gboolean m_NotifiedPageZoomed; 69 | gboolean m_NotifiedReload; 70 | volatile gboolean m_Searching; 71 | gdouble m_Zoom; 72 | }; 73 | } 74 | 75 | #endif // !__DUMB_DOCUMENT_OBSERVER_H__ 76 | -------------------------------------------------------------------------------- /src/DocumentRectangle.cxx: -------------------------------------------------------------------------------- 1 | // ePDFView - A lightweight PDF Viewer. 2 | // Copyright (C) 2006-2011 Emma's Software. 3 | // Copyright (C) 2014-2025 Pablo Lezaeta 4 | // Copyright (C) 2014 Pedro A. Aranda Gutiérrez 5 | 6 | // ePDFView - A lightweight PDF Viewer. 7 | // 8 | // 9 | // This program is free software; you can redistribute it and/or modify 10 | // it under the terms of the GNU General Public License as published by 11 | // the Free Software Foundation; either version 2 of the License, or 12 | // (at your option) any later version. 13 | // 14 | // This program is distributed in the hope that it will be useful, 15 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 16 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 | // GNU General Public License for more details. 18 | // 19 | // You should have received a copy of the GNU General Public License 20 | // along with this program; if not, write to the Free Software 21 | // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 22 | 23 | #include "epdfview.h" 24 | 25 | using namespace ePDFView; 26 | 27 | /// 28 | /// @brief Constructs a new rectangle. 29 | /// 30 | /// @param x1 The X coordinate of the rectangle's top-left corner. 31 | /// @param y1 The Y coordinate of the rectangle's top-left corner. 32 | /// @param x2 The X coordinate of the rectangle's bottom-right corner. 33 | /// @param y2 The Y coordinate of the rectangle's bottom-right corner. 34 | /// 35 | DocumentRectangle::DocumentRectangle (gdouble x1, gdouble y1, 36 | gdouble x2, gdouble y2) 37 | { 38 | m_X1 = x1; 39 | m_X2 = x2; 40 | m_Y1 = y1; 41 | m_Y2 = y2; 42 | } 43 | 44 | /// 45 | /// @brief Constructs a new rectangle as a copy of another rectangle. 46 | /// 47 | /// @param original The original rectangle to copy. 48 | /// 49 | DocumentRectangle::DocumentRectangle (DocumentRectangle &original) 50 | { 51 | m_X1 = original.getX1 (); 52 | m_X2 = original.getX2 (); 53 | m_Y1 = original.getY1 (); 54 | m_Y2 = original.getY2 (); 55 | } 56 | 57 | /// 58 | /// @brief Destroys all dynamically allocated memory for DocumentRectangle. 59 | /// 60 | DocumentRectangle::~DocumentRectangle () 61 | { 62 | } 63 | 64 | /// 65 | /// @brief Gets the top-left corner X coordinates. 66 | /// 67 | /// @return The X coordinates of the rectangle's top-left corner. 68 | /// 69 | gdouble 70 | DocumentRectangle::getX1 () 71 | { 72 | return m_X1; 73 | } 74 | 75 | /// 76 | /// @brief Gets the bottom-right corner X coordinates. 77 | /// 78 | /// @return The X coordinates of the rectangle's bottom-right corner. 79 | /// 80 | gdouble 81 | DocumentRectangle::getX2 () 82 | { 83 | return m_X2; 84 | } 85 | 86 | /// 87 | /// @brief Gets the top-left corner Y coordinates. 88 | /// 89 | /// @return The Y coordinates of the rectangle's top-left corner. 90 | /// 91 | gdouble 92 | DocumentRectangle::getY1 () 93 | { 94 | return m_Y1; 95 | } 96 | 97 | /// 98 | /// @brief Gets the right-bottom corner Y coordinates. 99 | /// 100 | /// @return The Y coordinates of the rectangle's bottom-right corner. 101 | /// 102 | gdouble 103 | DocumentRectangle::getY2 () 104 | { 105 | return m_Y2; 106 | } 107 | -------------------------------------------------------------------------------- /docs/CRITICAL_BUG_FIXES.md: -------------------------------------------------------------------------------- 1 | # Critical Bug Fixes - ePDFView GTK4 2 | 3 | ## Bug #1: Window Not Showing (FIXED ✅) 4 | 5 | **Symptom:** Application compiled and ran but no window appeared. Exited immediately with code 0. 6 | 7 | **Root Cause:** Two issues: 8 | 1. `MainView::show()` was never called in `on_activate()` 9 | 2. Window was not registered with GtkApplication 10 | 11 | **Fix:** 12 | 1. Added `appData->mainView->show()` in `on_activate()` callback (main.cxx:92) 13 | 2. Added `gtk_application_add_window()` to register window (main.cxx:89) 14 | 3. Changed `gtk_widget_show()` to `gtk_window_present()` in MainView::show() (MainView.cxx:750) 15 | 4. Added sanity checks for window size in WSLg environments (MainView.cxx:749-751) 16 | 17 | **Files Modified:** 18 | - `src/main.cxx` - Added window registration and show() call 19 | - `src/gtk/MainView.cxx` - Fixed show() method, added size validation 20 | - `src/gtk/MainView.h` - Added getMainWindow() public getter 21 | 22 | **Result:** Window now appears correctly on both native Linux and WSL with WSLg. 23 | 24 | --- 25 | 26 | ## Bug #2: File Open Dialog Crashes (IN PROGRESS 🔧) 27 | 28 | **Symptom:** Clicking File → Open causes crash (coredump). 29 | 30 | **Investigation Needed:** 31 | - GApplication warning: "does not implement g_application_open()" 32 | - Application was created with G_APPLICATION_HANDLES_OPEN but no handler 33 | 34 | **Possible Issues:** 35 | 1. File dialog using deprecated GTK3 APIs 36 | 2. GApplication 'open' signal not connected 37 | 3. File loading code accessing invalid memory 38 | 39 | **Next Steps:** 40 | - Remove G_APPLICATION_HANDLES_OPEN flag (not needed) 41 | - Debug file dialog with gdb 42 | - Check MainView::openFileDialog() implementation 43 | 44 | --- 45 | 46 | ## Bug #3: WSLg Display Issues (FIXED ✅) 47 | 48 | **Symptom:** "your 131072x1 screen size is bogus" error in WSLg 49 | 50 | **Root Cause:** WSLg sometimes reports invalid screen dimensions 51 | 52 | **Fix:** Added sanity checks in MainView::show(): 53 | ```cpp 54 | if (width <= 0 || width > 10000) width = 800; 55 | if (height <= 0 || height > 10000) height = 600; 56 | ``` 57 | 58 | **Result:** Application uses sensible defaults when bogus dimensions detected. 59 | 60 | --- 61 | 62 | ## Testing Status 63 | 64 | ### Working ✅ 65 | - Application starts 66 | - Window appears 67 | - Window can be moved/resized 68 | - Menus display 69 | - Keyboard shortcuts work 70 | - Exit works 71 | 72 | ### Broken ❌ 73 | - File → Open crashes 74 | - Opening PDF from command line (needs open handler) 75 | 76 | ### Not Tested ⚠️ 77 | - All other features (pending file open fix) 78 | 79 | --- 80 | 81 | ## Running in WSL 82 | 83 | **Required:** 84 | ```bash 85 | export DISPLAY=:0 86 | epdfview 87 | ``` 88 | 89 | **Normal Warnings (Safe to Ignore):** 90 | - libEGL warning: DRI3 error 91 | - Unable to acquire session bus 92 | - bogus screen size (now handled) 93 | 94 | --- 95 | 96 | ## Next Session Priority 97 | 98 | 1. Fix file open dialog crash 99 | 2. Implement 'open' signal handler or remove G_APPLICATION_HANDLES_OPEN 100 | 3. Test with actual PDF files 101 | 4. Verify all menu items work 102 | 103 | --- 104 | 105 | **Status:** Window showing works! File opening needs urgent fix. 106 | **Date:** October 24, 2025 107 | **Version:** 0.3.0 108 | -------------------------------------------------------------------------------- /docs/CI_FIXES_2025-11-12.md: -------------------------------------------------------------------------------- 1 | # GitHub Issue: FreeBSD CI Build Failure - Bash Dependency 2 | 3 | ## Issue Description 4 | 5 | FreeBSD CI builds were failing with: 6 | ``` 7 | Error: The process '/usr/bin/bash' failed with exit code 1 8 | ``` 9 | 10 | ## Root Cause 11 | 12 | The GitHub Actions workflow had `usesh: true` in the FreeBSD VM configuration: 13 | 14 | ```yaml 15 | build-freebsd: 16 | name: Build on FreeBSD 17 | runs-on: ubuntu-latest 18 | steps: 19 | - uses: vmactions/freebsd-vm@v1 20 | with: 21 | usesh: true # ← THIS WAS THE PROBLEM 22 | prepare: | 23 | pkg install -y meson ninja gtk4 poppler-glib cups gettext-tools 24 | ``` 25 | 26 | **Why it failed:** 27 | - `usesh: true` forces the use of `/usr/bin/bash` 28 | - FreeBSD does not include bash by default 29 | - The default shell is `/bin/sh` (POSIX shell) or `/bin/tcsh` 30 | - The action tried to execute `/usr/bin/bash` which doesn't exist 31 | 32 | ## Solution 33 | 34 | Removed `usesh: true` from the workflow configuration: 35 | 36 | ```yaml 37 | build-freebsd: 38 | name: Build on FreeBSD 39 | runs-on: ubuntu-latest 40 | steps: 41 | - uses: vmactions/freebsd-vm@v1 42 | with: 43 | # Use default FreeBSD shell (sh/tcsh) instead of bash 44 | # usesh: true causes "bash: not found" errors 45 | prepare: | 46 | pkg install -y meson ninja gtk4 poppler-glib cups gettext-tools 47 | run: | 48 | meson setup builddir --buildtype=release 49 | meson compile -C builddir 50 | ``` 51 | 52 | This allows the action to use FreeBSD's default shell, which is always available. 53 | 54 | ## Additional Improvements 55 | 56 | While fixing this issue, we also: 57 | 58 | 1. **Added Windows CI Build:** 59 | - Uses MSYS2 environment 60 | - Builds with MinGW-w64 61 | - Automated testing on Windows platform 62 | 63 | 2. **Updated Documentation:** 64 | - `README` now reflects C++14 standard and platform support 65 | - `PROJECT_STATUS.md` updated with recent fixes 66 | - Created `STATUS.md` for quick status overview 67 | - Moved `CURRENT_STATUS.md` to `docs/` to reduce root directory clutter 68 | 69 | ## Files Modified 70 | 71 | - `.github/workflows/build.yml` - Fixed FreeBSD shell, added Windows build 72 | - `README` - Updated platform support, recent improvements 73 | - `PROJECT_STATUS.md` - Added recent fixes section 74 | - `STATUS.md` - New quick status file 75 | - `docs/CURRENT_STATUS.md` - Moved from root 76 | 77 | ## Testing 78 | 79 | After these changes, all three CI builds should pass: 80 | - ✅ Linux (Ubuntu) - Already working 81 | - ✅ FreeBSD - Fixed by removing bash dependency 82 | - ✅ Windows (MSYS2) - Newly added 83 | 84 | ## References 85 | 86 | - vmactions/freebsd-vm documentation: https://github.com/vmactions/freebsd-vm 87 | - FreeBSD default shells: `/bin/sh` (POSIX), `/bin/tcsh` 88 | - MSYS2 setup action: https://github.com/msys2/setup-msys2 89 | 90 | ## Commit Message 91 | 92 | ``` 93 | fix(ci): Remove bash dependency in FreeBSD build, add Windows CI 94 | 95 | - Remove `usesh: true` from FreeBSD workflow (bash not available by default) 96 | - Add Windows build using MSYS2/MinGW-w64 97 | - Update README and PROJECT_STATUS.md with recent improvements 98 | - Create STATUS.md for quick status overview 99 | - Move CURRENT_STATUS.md to docs/ directory 100 | 101 | Fixes FreeBSD CI failures caused by hardcoded /usr/bin/bash path. 102 | ``` 103 | -------------------------------------------------------------------------------- /src/PDFDocument.h: -------------------------------------------------------------------------------- 1 | // ePDFView - A lightweight PDF Viewer. 2 | // Copyright (C) 2006-2011 Emma's Software. 3 | // Copyright (C) 2014-2025 Pablo Lezaeta 4 | // Copyright (C) 2014 Pedro A. Aranda Gutiérrez 5 | 6 | // ePDFView - A lightweight PDF Viewer. 7 | // 8 | // 9 | // This program is free software; you can redistribute it and/or modify 10 | // it under the terms of the GNU General Public License as published by 11 | // the Free Software Foundation; either version 2 of the License, or 12 | // (at your option) any later version. 13 | // 14 | // This program is distributed in the hope that it will be useful, 15 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 16 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 | // GNU General Public License for more details. 18 | // 19 | // You should have received a copy of the GNU General Public License 20 | // along with this program; if not, write to the Free Software 21 | // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 22 | 23 | #if !defined (__PDF_DOCUMENT_H__) 24 | #define __PDF_DOCUMENT_H__ 25 | 26 | 27 | /// Forward declarations. 28 | typedef struct _PopplerDocument PopplerDocument; 29 | typedef struct _PopplerIndexIter PopplerIndexIter; 30 | typedef struct _PopplerLinkMapping PopplerLinkMapping; 31 | typedef struct _PopplerPage PopplerPage; 32 | typedef struct _PopplerPSFile PopplerPSFile; 33 | 34 | namespace ePDFView 35 | { 36 | /// 37 | /// @class PDFDocument 38 | /// @brief A PDF document. 39 | /// 40 | /// Derived class from IDocument that loads and renders PDF documents. 41 | /// 42 | class PDFDocument: public IDocument 43 | { 44 | public: 45 | PDFDocument (void); 46 | ~PDFDocument (void); 47 | 48 | IDocument *copy (void) const; 49 | GList *findTextInPage (gint pageNum, const gchar *textToFind); 50 | gboolean isLoaded (void); 51 | gboolean loadFile (const gchar *filename, const gchar *password, 52 | GError **error); 53 | void getPageSizeForPage (gint pageNum, gdouble *width, 54 | gdouble *height); 55 | void outputPostscriptBegin (const gchar *fileName, guint numOfPages, 56 | gfloat pageWidth, gfloat pageHeight); 57 | void outputPostscriptEnd (void); 58 | void outputPostscriptPage (guint pageNum); 59 | 60 | DocumentPage *renderPage (gint pageNum); 61 | gboolean saveFile (const gchar *fileName, GError **error); 62 | cairo_region_t* getTextRegion (DocumentRectangle* rect); 63 | void setTextSelection (DocumentRectangle *rect); 64 | 65 | protected: 66 | /// The PDF document. 67 | PopplerDocument *m_Document; 68 | /// The output to PostScript. 69 | PopplerPSFile *m_PostScript; 70 | 71 | IDocumentLink *createDocumentLink (const PopplerLinkMapping *link, 72 | const gdouble pageHeight, 73 | const gdouble scale); 74 | void loadMetadata (void); 75 | void setOutline (DocumentOutline *outline, 76 | PopplerIndexIter *childrenList); 77 | void setLinks (DocumentPage *renderedPage, 78 | PopplerPage *popplerPage); 79 | }; 80 | } 81 | 82 | #endif // !__DOCUMENT_H__ 83 | -------------------------------------------------------------------------------- /src/IJob.cxx: -------------------------------------------------------------------------------- 1 | // ePDFView - A lightweight PDF Viewer. 2 | // Copyright (C) 2006-2011 Emma's Software. 3 | // Copyright (C) 2014-2025 Pablo Lezaeta 4 | // Copyright (C) 2014 Pedro A. Aranda Gutiérrez 5 | 6 | // ePDFView - A lightweight PDF Viewer. 7 | // 8 | // 9 | // This program is free software; you can redistribute it and/or modify 10 | // it under the terms of the GNU General Public License as published by 11 | // the Free Software Foundation; either version 2 of the License, or 12 | // (at your option) any later version. 13 | // 14 | // This program is distributed in the hope that it will be useful, 15 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 16 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 | // GNU General Public License for more details. 18 | // 19 | // You should have received a copy of the GNU General Public License 20 | // along with this program; if not, write to the Free Software 21 | // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 22 | 23 | #include "epdfview.h" 24 | #include 25 | #include 26 | 27 | using namespace ePDFView; 28 | 29 | /// The queue of jobs to run in background. 30 | GAsyncQueue *IJob::m_JobsQueue = NULL; 31 | 32 | /// 33 | /// @brief Clears the list of jobs. 34 | /// 35 | /// This is mainly used for the test suites when they are going 36 | /// to delete the document class and don't want to generate segmentation 37 | /// faults. It just pops all queued jobs without run them. 38 | /// 39 | void 40 | IJob::clearQueue (void) 41 | { 42 | IJob *job = NULL; 43 | do 44 | { 45 | job = (IJob *)g_async_queue_try_pop (m_JobsQueue); 46 | } 47 | while ( NULL != job ); 48 | } 49 | 50 | /// 51 | /// @brief The job dispatcher. 52 | /// 53 | /// This function is the one that will run in a thread. What it does is 54 | /// just pop queued jobs from the queue and then runs them. 55 | /// 56 | /// @param data The asynchronous queue where the jobs will be enqueued. 57 | /// 58 | gpointer 59 | IJob::dispatcher (gpointer data) 60 | { 61 | while (true) 62 | { 63 | IJob *job = (IJob *)g_async_queue_pop (m_JobsQueue); 64 | if ( job->run () ) 65 | { 66 | delete job; 67 | } 68 | } 69 | #ifdef _WIN32 70 | _sleep(0); 71 | #else 72 | sleep(0); 73 | #endif 74 | } 75 | 76 | /// 77 | /// @brief Initialises the job dispatcher. 78 | /// 79 | /// This function must be the first called before any other jobs-related 80 | /// function, as it does initialised the thread subsystem, created the 81 | /// threaded dispatcher() function and initialised the job queue. 82 | /// 83 | void 84 | IJob::init () 85 | { 86 | // GLib threads are always available in modern versions (>= 2.32) 87 | // No need to call g_thread_init() or check g_thread_supported() 88 | m_JobsQueue = g_async_queue_new (); 89 | GError *error = NULL; 90 | if ( NULL == g_thread_create (IJob::dispatcher, NULL, FALSE, &error) ) 91 | { 92 | g_error ("Couldn't create the dispatcher thread: %s\n", error->message); 93 | } 94 | } 95 | 96 | /// 97 | /// @brief Adds a new job to the queue. 98 | /// 99 | /// It adds a new job to the queued jobs that will be dispatched by 100 | /// the dispatch() function. 101 | /// 102 | /// @param job The job to add to the queue. 103 | /// 104 | void 105 | IJob::enqueue (IJob *job) 106 | { 107 | g_assert ( NULL != job && "Tried to queue a NULL job."); 108 | 109 | g_async_queue_push (m_JobsQueue, (gpointer)job); 110 | } 111 | -------------------------------------------------------------------------------- /src/PagePter.h: -------------------------------------------------------------------------------- 1 | // ePDFView - A lightweight PDF Viewer. 2 | // Copyright (C) 2006-2011 Emma's Software. 3 | // Copyright (C) 2014-2025 Pablo Lezaeta 4 | // Copyright (C) 2014 Pedro A. Aranda Gutiérrez 5 | 6 | // ePDFView - A lightweight PDF Viewer. 7 | // 8 | // 9 | // This program is free software; you can redistribute it and/or modify 10 | // it under the terms of the GNU General Public License as published by 11 | // the Free Software Foundation; either version 2 of the License, or 12 | // (at your option) any later version. 13 | // 14 | // This program is distributed in the hope that it will be useful, 15 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 16 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 | // GNU General Public License for more details. 18 | // 19 | // You should have received a copy of the GNU General Public License 20 | // along with this program; if not, write to the Free Software 21 | // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 22 | 23 | #if !defined (__PAGE_PTER_H__) 24 | #define __PAGE_PTER_H__ 25 | 26 | // Forward declarations. 27 | typedef struct _DragInfo DragInfo; 28 | 29 | namespace ePDFView 30 | { 31 | enum PagePterMode{ 32 | PagePterModeScroll, 33 | PagePterModeSelectText, 34 | }; 35 | 36 | /// 37 | /// @class PagePter. 38 | /// @brief The page presenter. 39 | /// 40 | /// This class is the presenter that drives the page view that 41 | /// shows the current document's page image. 42 | /// 43 | class PagePter: public IDocumentObserver 44 | { 45 | public: 46 | PagePter (IDocument *document); 47 | ~PagePter (); 48 | 49 | void getSize (gint *width, gint *height); 50 | IPageView &getView (void); 51 | void onCtrlButton (gint mouseButton, gint mouseState,gint x, gint y); 52 | void mouseButtonPressed (gint mouseButton, gint mouseState,gint x, gint y); 53 | void mouseButtonReleased (gint mouseButton); 54 | void mouseMoved (gint x, gint y); 55 | void notifyFindChanged (DocumentRectangle *matchRect); 56 | void notifyLoad (void); 57 | void notifyPageChanged (gint pageNum); 58 | void notifyPageRotated (gint rotation); 59 | void notifyPageZoomed (gdouble zoom); 60 | void notifyReload (void); 61 | void tryReShowPage (void); 62 | static gboolean pageNotAvailable (gpointer user); 63 | void scrollToNextPage (void); 64 | void scrollToPreviousPage (void); 65 | void setNextPageScroll (PageScroll next); 66 | void setView (IMainView &view); 67 | void viewResized (gint width, gint height); 68 | void setMode(PagePterMode mode); 69 | void setInvertColorToggle(char on);//krogan 70 | void refreshPage (PageScroll pageScroll, gboolean wasZoomed); 71 | 72 | protected: 73 | /// The document whose page is shown. 74 | IDocument *m_Document; 75 | /// Information about dragging the page. 76 | DragInfo *m_DragInfo; 77 | /// How to scroll the next page to show. 78 | PageScroll m_NextPageScroll; 79 | /// The page view. 80 | IPageView *m_PageView; 81 | /// Last text selection 82 | cairo_region_t *m_LastSelection; 83 | /// What page presenter must do when user move mouse with button pressed. 84 | PagePterMode m_ScrollMode; 85 | }; 86 | } 87 | 88 | #endif // !__PAGE_PTER_H__ 89 | -------------------------------------------------------------------------------- /tests/DumbPrintView.h: -------------------------------------------------------------------------------- 1 | // ePDFView - A lightweight PDF Viewer. 2 | // Copyright (C) 2006-2011 Emma's Software. 3 | // Copyright (C) 2014-2025 Pablo Lezaeta 4 | // Copyright (C) 2014 Pedro A. Aranda Gutiérrez 5 | 6 | // ePDFView - Dumb Test Preferences View. 7 | // 8 | // 9 | // This program is free software; you can redistribute it and/or modify 10 | // it under the terms of the GNU General Public License as published by 11 | // the Free Software Foundation; either version 2 of the License, or 12 | // (at your option) any later version. 13 | // 14 | // This program is distributed in the hope that it will be useful, 15 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 16 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 | // GNU General Public License for more details. 18 | // 19 | // You should have received a copy of the GNU General Public License 20 | // along with this program; if not, write to the Free Software 21 | // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 22 | 23 | #if !defined (__DUMB_PRINT_VIEW_H__) 24 | #define __DUMB_PRINT_VIEW_H__ 25 | 26 | namespace ePDFView 27 | { 28 | class DumbPrintView: public IPrintView 29 | { 30 | public: 31 | DumbPrintView (); 32 | virtual ~DumbPrintView (void); 33 | 34 | virtual void addColorModel (const gchar *name, const gchar *value); 35 | virtual void addPageSize (const gchar *name, const gchar *value); 36 | virtual void addPrinter (const gchar *name, int jobs, 37 | const gchar *state, const gchar *location); 38 | virtual void addResolution (const gchar *name, const gchar *value); 39 | virtual void clearColorModelList (void); 40 | virtual void clearPageSizeList (void); 41 | virtual void clearResolutionList (void); 42 | virtual guint getNumberOfCopies (void); 43 | virtual PrintPageLayout getPageLayout (void); 44 | virtual PrintPageOrientation getPageOrientation (void); 45 | virtual const gchar *getPageRange (void); 46 | virtual gchar *getColorModel (void); 47 | virtual gchar *getPageSize (void); 48 | virtual gchar *getResolution (void); 49 | virtual gchar *getSelectedPrinterName (void); 50 | virtual gboolean isCheckedCollate (void); 51 | virtual gboolean isSelectedAllPagesRangeOption (void); 52 | virtual gboolean isSelectedEvenPageSet (void); 53 | virtual gboolean isSelectedOddPageSet (void); 54 | virtual void selectColorModel (guint colorModelIndex); 55 | virtual void selectPageSize (guint pageSizeIndex); 56 | virtual void selectPrinter (guint printerIndex); 57 | virtual void selectResolution (guint resolutionIndex); 58 | virtual void sensitiveCollate (gboolean sensitive); 59 | virtual void sensitivePageRange (gboolean sensitive); 60 | virtual void sensitivePrintButton (gboolean sensitive); 61 | 62 | // Test only functions. 63 | gboolean isSensitiveCollate (void); 64 | gboolean isSensitivePageRange (void); 65 | void selectAllPagesRangeOption (void); 66 | void selectCustomPagesRangeOption (void); 67 | void setNumberOfCopies (unsigned int copies); 68 | 69 | protected: 70 | gboolean m_AllPagesRangeOptionSelected; 71 | guint m_NumberOfCopies; 72 | gboolean m_SensitiveCollate; 73 | gboolean m_SensitivePageRange; 74 | }; 75 | } 76 | 77 | #endif // !__DUMB_PRINT_VIEW_H__ 78 | -------------------------------------------------------------------------------- /docs/DOCUMENTATION.md: -------------------------------------------------------------------------------- 1 | # ePDFView Documentation Index 2 | 3 | Welcome to ePDFView documentation! This project uses Markdown for all documentation. 4 | 5 | ## 📚 Documentation Files 6 | 7 | ### For End Users 8 | 9 | - **[README.md](README.md)** - Project overview, features, and quick start 10 | - **[INSTALL](INSTALL)** - Detailed build and installation instructions 11 | - **[BUILD_STATUS.md](BUILD_STATUS.md)** - Current project status and known issues 12 | 13 | ### For Developers 14 | 15 | - **[GTK4_MIGRATION_SUMMARY.md](GTK4_MIGRATION_SUMMARY.md)** - Complete GTK4 migration details 16 | - **[COMPILATION_SUCCESS.md](COMPILATION_SUCCESS.md)** - Build system and compilation info 17 | - **[MENU_SYSTEM_COMPLETE.md](MENU_SYSTEM_COMPLETE.md)** - Menu implementation details 18 | - **[TRANSLATIONS_AND_DOCS.md](TRANSLATIONS_AND_DOCS.md)** - Translation and documentation systems 19 | 20 | ### Source Code Documentation 21 | 22 | The source code is well-documented with inline comments. Key files: 23 | 24 | ``` 25 | src/ 26 | ├── gtk/ # GTK4 UI implementation 27 | │ ├── MainView.cxx # Main window and menu system 28 | │ ├── PageView.cxx # PDF rendering view 29 | │ ├── FindView.cxx # Search functionality 30 | │ └── PreferencesView.cxx 31 | ├── MainPter.cxx # Main presenter/controller 32 | ├── PagePter.cxx # Page presenter 33 | └── PDFDocument.cxx # Poppler integration 34 | ``` 35 | 36 | ## 🌍 Translations 37 | 38 | ePDFView supports 22 languages. Translation files are in the `po/` directory. 39 | 40 | **Supported Languages:** 41 | Arabic, Catalan, Czech, German, Greek, Spanish, Basque, French, Galician, 42 | Hebrew, Hungarian, Italian, Japanese, Dutch, Polish, Portuguese, 43 | Brazilian Portuguese, Russian, Swedish, Vietnamese, Chinese (Simplified), 44 | Chinese (Traditional) 45 | 46 | **For translators:** See [TRANSLATIONS_AND_DOCS.md](TRANSLATIONS_AND_DOCS.md) for details. 47 | 48 | ## 🔧 Build System 49 | 50 | ePDFView uses **Meson** build system (no Autotools, no Doxygen). 51 | 52 | **Quick Build:** 53 | ```bash 54 | meson setup builddir -Dcups=disabled 55 | meson compile -C builddir 56 | ./builddir/src/epdfview 57 | ``` 58 | 59 | **Full details:** See [INSTALL](INSTALL) 60 | 61 | ## 🎯 Project Status 62 | 63 | **GTK4 Migration:** ✅ 100% Complete 64 | **Compilation:** ✅ Successful 65 | **Menu System:** ✅ Fully functional 66 | **Translations:** ✅ All working 67 | 68 | See [COMPILATION_SUCCESS.md](COMPILATION_SUCCESS.md) for details. 69 | 70 | ## 🐛 Reporting Issues 71 | 72 | When reporting bugs, please include: 73 | 1. GTK4 version: `pkg-config --modversion gtk4` 74 | 2. Poppler version: `pkg-config --modversion poppler-glib` 75 | 3. Linux distribution and version 76 | 4. Steps to reproduce 77 | 5. Error messages or logs 78 | 79 | ## 📄 License 80 | 81 | ePDFView is licensed under GPL-2.0-or-later. 82 | See source files for full license text. 83 | 84 | ## 🤝 Contributing 85 | 86 | Contributions welcome! Please: 87 | 1. Follow existing code style 88 | 2. Test your changes thoroughly 89 | 3. Update documentation if needed 90 | 4. Ensure translations still work 91 | 92 | **Priority areas:** 93 | - Testing on different distributions 94 | - Wayland-specific testing 95 | - Translation updates 96 | - Bug fixes 97 | 98 | ## 📞 Contact 99 | 100 | - **Project:** https://github.com/JotaRandom/epdfview 101 | - **Original Project:** Emma's Software (archived) 102 | 103 | --- 104 | 105 | **Note:** This project has been migrated from GTK2/GTK3 to GTK4. 106 | Old Autotools and Doxygen documentation systems have been replaced 107 | with modern Meson and Markdown for simplicity and maintainability. 108 | -------------------------------------------------------------------------------- /tests/MainPterTest.h: -------------------------------------------------------------------------------- 1 | // ePDFView - A lightweight PDF Viewer. 2 | // Copyright (C) 2006-2011 Emma's Software. 3 | // Copyright (C) 2014-2025 Pablo Lezaeta 4 | // Copyright (C) 2014 Pedro A. Aranda Gutiérrez 5 | 6 | // ePDFView - Main Presenter Test Fixture. 7 | // 8 | // 9 | // This program is free software; you can redistribute it and/or modify 10 | // it under the terms of the GNU General Public License as published by 11 | // the Free Software Foundation; either version 2 of the License, or 12 | // (at your option) any later version. 13 | // 14 | // This program is distributed in the hope that it will be useful, 15 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 16 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 | // GNU General Public License for more details. 18 | // 19 | // You should have received a copy of the GNU General Public License 20 | // along with this program; if not, write to the Free Software 21 | // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 22 | 23 | #if !defined (__MAIN_PTER_TEST_H__) 24 | #define __MAIN_PTER_TEST_H__ 25 | 26 | #include 27 | 28 | namespace ePDFView 29 | { 30 | class MainPterTest: public CppUnit::TestFixture 31 | { 32 | CPPUNIT_TEST_SUITE (MainPterTest); 33 | CPPUNIT_TEST (initialStatus); 34 | CPPUNIT_TEST (loadDocument); 35 | CPPUNIT_TEST (loadCanceled); 36 | CPPUNIT_TEST (loadFailed); 37 | CPPUNIT_TEST (canceledPassword); 38 | CPPUNIT_TEST (badPassword); 39 | CPPUNIT_TEST (goodPassword); 40 | CPPUNIT_TEST (openLastFolder); 41 | CPPUNIT_TEST (saveDocument); 42 | CPPUNIT_TEST (saveCanceled); 43 | CPPUNIT_TEST (saveLastFolder); 44 | CPPUNIT_TEST (pageNavigation); 45 | CPPUNIT_TEST (pageNavigationEntry); 46 | CPPUNIT_TEST (pageRotate); 47 | CPPUNIT_TEST (pageZoomInAndOut); 48 | CPPUNIT_TEST (pageZoomWidth); 49 | CPPUNIT_TEST (pageZoomFit); 50 | CPPUNIT_TEST (pageZoomAndRotate); 51 | CPPUNIT_TEST (pageZoomIndicator); 52 | CPPUNIT_TEST (reloadNormal); 53 | CPPUNIT_TEST (reloadEncrypted); 54 | CPPUNIT_TEST (reloadChangedPassword); 55 | CPPUNIT_TEST (showIndex); 56 | CPPUNIT_TEST (showToolAndStatusBars); 57 | CPPUNIT_TEST_SUITE_END(); 58 | 59 | public: 60 | void setUp (void); 61 | void tearDown (void); 62 | 63 | void initialStatus (void); 64 | void loadDocument (void); 65 | void loadCanceled (void); 66 | void loadFailed (void); 67 | void canceledPassword (void); 68 | void badPassword (void); 69 | void goodPassword (void); 70 | void openLastFolder (void); 71 | void saveDocument (void); 72 | void saveCanceled (void); 73 | void saveLastFolder (void); 74 | void pageNavigation (void); 75 | void pageNavigationEntry (void); 76 | void pageRotate (void); 77 | void pageZoomInAndOut (void); 78 | void pageZoomWidth (void); 79 | void pageZoomFit (void); 80 | void pageZoomAndRotate (void); 81 | void pageZoomIndicator (void); 82 | void reloadNormal (void); 83 | void reloadEncrypted (void); 84 | void reloadChangedPassword (void); 85 | void showIndex (void); 86 | void showToolAndStatusBars (void); 87 | 88 | private: 89 | DumbMainView *m_View; 90 | DumbDocument *m_Document; 91 | MainPter *m_MainPter; 92 | }; 93 | } 94 | 95 | #endif // !__MAIN_PTER_TEST_H__ 96 | -------------------------------------------------------------------------------- /THANKS: -------------------------------------------------------------------------------- 1 | I would like to give thanks to the following for their support and 2 | contributions: 3 | 4 | - Ahmad Farghal , for his Arabic translation. 5 | - Alain Mendizabal , for his Basque translation. 6 | - Alex Dedul , for his patch. 7 | - Alexander , for corrections in the Polish translation. 8 | - b0ntrict0r@yandex.ru, for his patch. 9 | - Dennis Sheil , for his patch. 10 | - Enrico Tröger , for his full screen patch and others. 11 | - ewtoombs , for his patches. 12 | - François Wendling , for his man page. 13 | - Daniel Nylander , for his Swedish translation. 14 | - Daniel Pielmeie , for his patches. 15 | - Dragonlord , for his Czech translation. 16 | - Fábio Antunes , for his Brazilian Portuguese translation. 17 | - Fabio Vergnani , for his Italian translation. 18 | - Fridrich Strba , for his Windows patch. 19 | - Ihar Hrachyshka , for his vim keybindings patch. 20 | - Igor Vagulin , for his Russian translation and patches. 21 | - Ivor Buijs , for his patch to add scrollbars to the print window. 22 | - Jakob Gruber , for his segfault patches. 23 | - Jim Ramsay , for his patches. 24 | - Kirin Yuri , for correcting the Russian translation. 25 | - Lester Godwin , for his patches. 26 | - LoneFox <>, for his patches. 27 | - Michael Opitz , for his patches. 28 | - Michal Schmidt , for his patches. 29 | - Miguel Anxo Bouzada , for his Galician translation. 30 | - Moritz Heiber , for his German translation. 31 | - Mr_Moustache , for his French translation. 32 | - Nuno Miguel , for his European Portuguese translation. 33 | - Nyu , for his Japanese translation. 34 | - Pablo Mazzini , for his print patches. 35 | - Panchoat , for his Simplified Chinese translation. 36 | - Peter Polonkai , for his Hungarian translation. 37 | - Piotr Pacholak , for corrections in the Polish translation. 38 | - Previdi Roberto for his patches. 39 | - Rafał Mużyło , for his patches. 40 | - Ronald van Engelen , for his Dutch translation. 41 | - Sergey Starosek , for his Russian patches. 42 | - Stavros Giannouris , for his Greek translation. 43 | - Tilman Sauerbeck , for his patches. 44 | - tbm , for his patches. 45 | - Valery Koval , for his patches. 46 | - VnPenguin , for his Vietnamese translation. 47 | - Wei-Lun Chao , for his Traditional Chinese translation. 48 | - Wojciech Myrda , for his Polish translation. 49 | - Yaron Shahrabani 50 | - Yuri Pankov , for his patches. 51 | - Yves-Alexis Perez , for his patches. 52 | - zhou sf , for his patches. 53 | 54 | If you feel that you should be in this list and I didn't remember to add you in it, please send me an e-mail! :-) 55 | -------------------------------------------------------------------------------- /src/JobFind.h: -------------------------------------------------------------------------------- 1 | // ePDFView - A lightweight PDF Viewer. 2 | // Copyright (C) 2006-2011 Emma's Software. 3 | // Copyright (C) 2014-2025 Pablo Lezaeta 4 | // Copyright (C) 2014 Pedro A. Aranda Gutiérrez 5 | 6 | // ePDFView - A lightweight PDF Viewer. 7 | // 8 | // 9 | // This program is free software; you can redistribute it and/or modify 10 | // it under the terms of the GNU General Public License as published by 11 | // the Free Software Foundation; either version 2 of the License, or 12 | // (at your option) any later version. 13 | // 14 | // This program is distributed in the hope that it will be useful, 15 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 16 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 | // GNU General Public License for more details. 18 | // 19 | // You should have received a copy of the GNU General Public License 20 | // along with this program; if not, write to the Free Software 21 | // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 22 | 23 | #if !defined (__JOB_FIND_H__) 24 | #define __JOB_FIND_H__ 25 | 26 | namespace ePDFView 27 | { 28 | // Forward declarations. 29 | class FindPter; 30 | 31 | /// 32 | /// @brief The search direction. 33 | /// 34 | typedef enum _FindDirection 35 | { 36 | /// Search forwards. 37 | FIND_DIRECTION_FORWARDS, 38 | /// Search backwards. 39 | FIND_DIRECTION_BACKWARDS 40 | } FindDirection; 41 | 42 | /// 43 | /// @class JobFind 44 | /// @brief A background job that finds text on the document. 45 | /// 46 | class JobFind: public IJob 47 | { 48 | public: 49 | JobFind (void); 50 | ~JobFind (void); 51 | 52 | void cancel (void); 53 | void dequeue (void); 54 | void enqueue (void); 55 | gint getCurrentPage (void); 56 | FindDirection getDirection (void); 57 | IDocument *getDocument (void); 58 | FindPter *getFindPter (void); 59 | GList *getResults (void); 60 | gint getResultsPage (void); 61 | gint getStartingPage (void); 62 | const gchar *getTextToFind (void); 63 | gboolean isCanceled (void); 64 | gboolean isEnqueued (void); 65 | gboolean run (void); 66 | void setCurrentPage (gint pageNum); 67 | void setDirection (FindDirection direction); 68 | void setDocument (IDocument *document); 69 | void setFindPter (FindPter *pter); 70 | void setResults (gint pageNum, GList *results); 71 | void setStartingPage (gint pageNum); 72 | void setTextToFind (const gchar *textToFind); 73 | 74 | protected: 75 | /// Tells if the job has been canceled. 76 | gboolean m_Canceled; 77 | /// The current page to search the text. 78 | gint m_CurrentPage; 79 | /// The next page to look for the text: the next or the previous. 80 | FindDirection m_Direction; 81 | /// The document to search the text from. 82 | IDocument *m_Document; 83 | /// Tells if the job is enqueued. 84 | gboolean m_Enqueued; 85 | /// The presenter to tell when a change happens. 86 | FindPter *m_FindPter; 87 | /// The search results of a page. 88 | GList *m_Results; 89 | /// The page number where m_Results belongs to. 90 | gint m_ResultsPage; 91 | /// The starting page of the search. 92 | gint m_StartingPage; 93 | /// The search to find on the document. 94 | gchar *m_TextToFind; 95 | }; 96 | } 97 | 98 | #endif // !__JOB_FIND_H__ 99 | -------------------------------------------------------------------------------- /src/gettext.h: -------------------------------------------------------------------------------- 1 | /* Convenience header for conditional use of GNU . 2 | Copyright (C) 1995-1998, 2000-2002, 2004 Free Software Foundation, Inc. 3 | 4 | This program is free software; you can redistribute it and/or modify it 5 | under the terms of the GNU Library General Public License as published 6 | by the Free Software Foundation; either version 2, or (at your option) 7 | any later version. 8 | 9 | This program is distributed in the hope that it will be useful, 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 | Library General Public License for more details. 13 | 14 | You should have received a copy of the GNU Library General Public 15 | License along with this program; if not, write to the Free Software 16 | Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, 17 | USA. */ 18 | 19 | #ifndef _LIBGETTEXT_H 20 | #define _LIBGETTEXT_H 1 21 | 22 | /* NLS can be disabled through the configure --disable-nls option. */ 23 | #if ENABLE_NLS 24 | 25 | /* Get declarations of GNU message catalog functions. */ 26 | # include 27 | 28 | #else 29 | 30 | /* Solaris /usr/include/locale.h includes /usr/include/libintl.h, which 31 | chokes if dcgettext is defined as a macro. So include it now, to make 32 | later inclusions of a NOP. We don't include 33 | as well because people using "gettext.h" will not include , 34 | and also including would fail on SunOS 4, whereas 35 | is OK. */ 36 | #if defined(__sun) 37 | # include 38 | #endif 39 | 40 | /* Many header files from the libstdc++ coming with g++ 3.3 or newer include 41 | , which chokes if dcgettext is defined as a macro. So include 42 | it now, to make later inclusions of a NOP. */ 43 | #if defined(__cplusplus) && defined(__GNUG__) && (__GNUC__ >= 3) 44 | # include 45 | # if (__GLIBC__ >= 2) || _GLIBCXX_HAVE_LIBINTL_H 46 | # include 47 | # endif 48 | #endif 49 | 50 | /* Disabled NLS. 51 | The casts to 'const char *' serve the purpose of producing warnings 52 | for invalid uses of the value returned from these functions. 53 | On pre-ANSI systems without 'const', the config.h file is supposed to 54 | contain "#define const". */ 55 | # define gettext(Msgid) ((const char *) (Msgid)) 56 | # define dgettext(Domainname, Msgid) ((const char *) (Msgid)) 57 | # define dcgettext(Domainname, Msgid, Category) ((const char *) (Msgid)) 58 | # define ngettext(Msgid1, Msgid2, N) \ 59 | ((N) == 1 ? (const char *) (Msgid1) : (const char *) (Msgid2)) 60 | # define dngettext(Domainname, Msgid1, Msgid2, N) \ 61 | ((N) == 1 ? (const char *) (Msgid1) : (const char *) (Msgid2)) 62 | # define dcngettext(Domainname, Msgid1, Msgid2, N, Category) \ 63 | ((N) == 1 ? (const char *) (Msgid1) : (const char *) (Msgid2)) 64 | # define textdomain(Domainname) ((const char *) (Domainname)) 65 | # define bindtextdomain(Domainname, Dirname) ((const char *) (Dirname)) 66 | # define bind_textdomain_codeset(Domainname, Codeset) ((const char *) (Codeset)) 67 | 68 | #endif 69 | 70 | /* A pseudo function call that serves as a marker for the automated 71 | extraction of messages, but does not call gettext(). The run-time 72 | translation is done at a different place in the code. 73 | The argument, String, should be a literal string. Concatenated strings 74 | and other string expressions won't work. 75 | The macro's expansion is not parenthesized, so that it is suitable as 76 | initializer for static 'char[]' or 'const char[]' variables. */ 77 | #define gettext_noop(String) String 78 | #define _(s) gettext(s) 79 | #define N_(s) gettext_noop (s) 80 | 81 | #endif /* _LIBGETTEXT_H */ 82 | -------------------------------------------------------------------------------- /RUN_EPDFVIEW_WSL.md: -------------------------------------------------------------------------------- 1 | # Running ePDFView in WSL (Windows Subsystem for Linux) 2 | 3 | ## The Issue 4 | 5 | ePDFView needs a display server to show its GUI. In WSL, you need to ensure the DISPLAY variable is set. 6 | 7 | ## Solution 8 | 9 | ### For Windows 11 with WSLg (Built-in) 10 | 11 | WSLg is built into Windows 11 and provides automatic GUI support. You just need to set the DISPLAY variable: 12 | 13 | ```bash 14 | # In WSL Arch 15 | export DISPLAY=:0 16 | epdfview 17 | ``` 18 | 19 | ### Create a Wrapper Script 20 | 21 | Create a helper script to always set DISPLAY: 22 | 23 | ```bash 24 | # Create the script 25 | sudo tee /usr/local/bin/epdfview-wsl > /dev/null << 'EOF' 26 | #!/bin/bash 27 | export DISPLAY=:0 28 | export WAYLAND_DISPLAY=wayland-0 29 | exec /usr/local/bin/epdfview "$@" 30 | EOF 31 | 32 | # Make it executable 33 | sudo chmod +x /usr/local/bin/epdfview-wsl 34 | 35 | # Now you can just run: 36 | epdfview-wsl 37 | ``` 38 | 39 | ### Add to Your Shell Profile 40 | 41 | To automatically set DISPLAY for all GUI apps: 42 | 43 | ```bash 44 | # Add to ~/.bashrc or ~/.zshrc 45 | echo 'export DISPLAY=:0' >> ~/.bashrc 46 | source ~/.bashrc 47 | ``` 48 | 49 | ## Troubleshooting 50 | 51 | ### "bogus screen size" Error 52 | 53 | This is a WSLg issue with display detection. ePDFView now handles this automatically by using sensible defaults (800x600) when invalid dimensions are detected. 54 | 55 | ### Window Doesn't Appear 56 | 57 | 1. **Check if WSLg is running:** 58 | ```bash 59 | ls -la /mnt/wslg/ 60 | ``` 61 | Should show X11-unix, runtime-dir, etc. 62 | 63 | 2. **Check DISPLAY is set:** 64 | ```bash 65 | echo $DISPLAY 66 | ``` 67 | Should show `:0` or similar 68 | 69 | 3. **Test with a simple GUI app:** 70 | ```bash 71 | # Install xeyes for testing 72 | sudo pacman -S xorg-xeyes 73 | export DISPLAY=:0 74 | xeyes 75 | ``` 76 | If xeyes works, epdfview should too. 77 | 78 | 4. **Check if process is running:** 79 | ```bash 80 | export DISPLAY=:0 81 | epdfview & 82 | ps aux | grep epdfview 83 | ``` 84 | 85 | ### D-Bus Warning 86 | 87 | The warning "Unable to acquire session bus" is normal in WSL and doesn't affect functionality. It's just informational. 88 | 89 | ### libEGL Warning 90 | 91 | The "DRI3 error" warning is also normal in WSL without full GPU acceleration. It doesn't prevent the app from working. 92 | 93 | ## For Windows 10 (Without WSLg) 94 | 95 | If you're on Windows 10 without WSLg, you need an X server: 96 | 97 | 1. **Install VcXsrv or Xming** (Windows X server) 98 | - Download VcXsrv: https://sourceforge.net/projects/vcxsrv/ 99 | - Or Xming: https://sourceforge.net/projects/xming/ 100 | 101 | 2. **Start the X server** with: 102 | - Display number: 0 103 | - Disable access control 104 | 105 | 3. **Set DISPLAY in WSL:** 106 | ```bash 107 | export DISPLAY=$(cat /etc/resolv.conf | grep nameserver | awk '{print $2}'):0 108 | epdfview 109 | ``` 110 | 111 | ## Testing 112 | 113 | To test if everything is working: 114 | 115 | ```bash 116 | # Set display 117 | export DISPLAY=:0 118 | 119 | # Run epdfview (should stay running) 120 | epdfview & 121 | 122 | # Check if process exists 123 | sleep 1 124 | ps aux | grep epdfview 125 | 126 | # If you see the process, the window should be visible! 127 | ``` 128 | 129 | ## Native Arch Linux (Not WSL) 130 | 131 | If you're running on real Arch Linux (not WSL): 132 | 133 | ```bash 134 | # Just run it - no special setup needed! 135 | epdfview 136 | ``` 137 | 138 | The DISPLAY variable should already be set by your desktop environment. 139 | 140 | ## Summary 141 | 142 | **WSL (Windows 11):** 143 | ```bash 144 | export DISPLAY=:0 145 | epdfview 146 | ``` 147 | 148 | **WSL (Windows 10):** 149 | - Install VcXsrv 150 | - `export DISPLAY=:0` 151 | - `epdfview` 152 | 153 | **Native Linux:** 154 | - Just run `epdfview` 155 | 156 | --- 157 | 158 | **If the window appears, ePDFView is working correctly!** 🎉 159 | 160 | The warnings about D-Bus and libEGL are normal and can be ignored. 161 | -------------------------------------------------------------------------------- /docs/PRINT_MIGRATION_TODO.md: -------------------------------------------------------------------------------- 1 | # Print Functionality - GTK4 Migration TODO 2 | 3 | ## Status: ⚠️ NOT YET MIGRATED 4 | 5 | Print functionality (PrintView.cxx) contains extensive GTK3 code that requires significant refactoring for GTK4. 6 | 7 | ## Current Build Status 8 | 9 | **Recommended:** Keep CUPS disabled during build: 10 | ```bash 11 | meson setup builddir -Dcups=disabled 12 | ``` 13 | 14 | This excludes PrintView.cxx and JobPrint.cxx from compilation. 15 | 16 | ## Required Changes for GTK4 17 | 18 | PrintView.cxx (840 lines) uses many deprecated APIs: 19 | 20 | ### 1. Container APIs (70+ occurrences) 21 | - ❌ `gtk_container_set_border_width()` → ✅ Use widget margins 22 | - ❌ `gtk_container_add()` → ✅ `gtk_frame_set_child()`, `gtk_box_append()` 23 | - ❌ `gtk_box_pack_start_defaults()` → ✅ `gtk_box_append()` with properties 24 | 25 | ### 2. Layout Widgets (30+ occurrences) 26 | - ❌ `GtkTable` / `gtk_table_new()` → ✅ `GtkGrid` / `gtk_grid_new()` 27 | - ❌ `gtk_table_attach()` → ✅ `gtk_grid_attach()` 28 | - ❌ `GtkAlignment` / `gtk_alignment_new()` → ✅ Use widget margins 29 | - ❌ `gtk_alignment_set_padding()` → ✅ `gtk_widget_set_margin_*()` 30 | 31 | ### 3. Misc Widgets (20+ occurrences) 32 | - ❌ `GtkMisc` / `gtk_misc_set_alignment()` → ✅ `gtk_label_set_xalign/yalign()` 33 | - ❌ `gtk_frame_set_shadow_type()` → ✅ Removed (use CSS if needed) 34 | - ❌ `GtkRadioButton` groups → ✅ `GtkCheckButton` with `gtk_check_button_set_group()` 35 | 36 | ### 4. Dialog APIs 37 | - ❌ `gtk_dialog_run()` → ✅ Async with `gtk_window_present()` + GMainLoop 38 | - ❌ `gtk_window_set_skip_taskbar_hint()` → ✅ Removed (not needed) 39 | - ❌ Stock buttons → ✅ Use custom labels 40 | 41 | ### 5. Tree/List View (if using deprecated patterns) 42 | - ⚠️ `GtkTreeView` → Modern apps use `GtkListView`/`GtkColumnView` 43 | - Current usage may work but generates warnings 44 | 45 | ## Migration Strategy 46 | 47 | ### Phase 1: Dialog Structure ✅ (Partially Done) 48 | - [x] Basic dialog creation 49 | - [ ] Remove all container deprecated APIs 50 | - [ ] Replace GtkTable with GtkGrid 51 | - [ ] Replace GtkAlignment with margins 52 | 53 | ### Phase 2: Tab Content (3 tabs to fix) 54 | - [ ] **Printer Tab** - GtkTreeView for printer list 55 | - [ ] **Job Tab** - Radio buttons, entry, spin button 56 | - [ ] **Paper Tab** - Combo boxes for paper settings 57 | 58 | ### Phase 3: CUPS Integration 59 | - [ ] Review JobPrint.cxx for GTK4 changes 60 | - [ ] Test actual printing functionality 61 | - [ ] Handle print job status 62 | 63 | ### Phase 4: Modern Alternative (Optional) 64 | Consider using GTK4's built-in print dialog: 65 | ```c 66 | GtkPrintOperation *print_op = gtk_print_operation_new(); 67 | // Configure and run 68 | gtk_print_operation_run(print_op, GTK_PRINT_OPERATION_ACTION_PRINT_DIALOG, 69 | parent, NULL); 70 | ``` 71 | 72 | This would: 73 | - ✅ Be fully GTK4 native 74 | - ✅ Integrate with system print dialog 75 | - ✅ Handle all OS-specific printing 76 | - ❌ Lose custom UI we currently have 77 | - ❌ Less control over CUPS-specific options 78 | 79 | ## Estimated Effort 80 | 81 | **Full Custom Dialog Migration:** 8-12 hours 82 | - Complex due to 3 tabs, many widgets 83 | - Lots of testing needed 84 | - CUPS integration verification 85 | 86 | **Switch to GtkPrintOperation:** 2-4 hours 87 | - Simpler, more maintainable 88 | - Standard GTK4 approach 89 | - May lose some custom features 90 | 91 | ## For Now 92 | 93 | **Recommendation:** Build without CUPS until ready to tackle print migration: 94 | 95 | ```bash 96 | # In meson_options.txt 97 | option('cups', type: 'feature', value: 'disabled') 98 | 99 | # Or at build time 100 | meson setup builddir -Dcups=disabled 101 | ``` 102 | 103 | All other functionality works perfectly without printing! 104 | 105 | ## When Ready to Migrate 106 | 107 | 1. Study GTK4 print examples: https://docs.gtk.org/gtk4/class.PrintOperation.html 108 | 2. Decide: Custom dialog vs GtkPrintOperation 109 | 3. Systematically replace deprecated APIs 110 | 4. Test with actual printers 111 | 112 | ## Resources 113 | 114 | - GTK4 Printing: https://docs.gtk.org/gtk4/printing.html 115 | - Migration Guide: https://docs.gtk.org/gtk4/migrating-3to4.html 116 | - GtkGrid: https://docs.gtk.org/gtk4/class.Grid.html 117 | - Widget Margins: https://docs.gtk.org/gtk4/method.Widget.set_margin_start.html 118 | -------------------------------------------------------------------------------- /tests/PrintPterTest.cxx: -------------------------------------------------------------------------------- 1 | // ePDFView - A lightweight PDF Viewer. 2 | // Copyright (C) 2006-2011 Emma's Software. 3 | // Copyright (C) 2014-2025 Pablo Lezaeta 4 | // Copyright (C) 2014 Pedro A. Aranda Gutiérrez 5 | 6 | // ePDFView - Preferences Presenter Test Fixture. 7 | // 8 | // 9 | // This program is free software; you can redistribute it and/or modify 10 | // it under the terms of the GNU General Public License as published by 11 | // the Free Software Foundation; either version 2 of the License, or 12 | // (at your option) any later version. 13 | // 14 | // This program is distributed in the hope that it will be useful, 15 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 16 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 | // GNU General Public License for more details. 18 | // 19 | // You should have received a copy of the GNU General Public License 20 | // along with this program; if not, write to the Free Software 21 | // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 22 | 23 | #include 24 | #include "DumbDocument.h" 25 | #include "DumbPrintView.h" 26 | #include "PrintPterTest.h" 27 | 28 | using namespace ePDFView; 29 | 30 | // Register the test suite into the `registry'. 31 | CPPUNIT_TEST_SUITE_REGISTRATION (PrintPterTest); 32 | 33 | /// 34 | /// @brief Sets up the environment for each test. 35 | /// 36 | void 37 | PrintPterTest::setUp () 38 | { 39 | Config::loadFile (FALSE); 40 | m_Document = new DumbDocument (); 41 | m_PrintPter = new PrintPter (m_Document); 42 | m_View = new DumbPrintView (); 43 | m_PrintPter->setView (m_View); 44 | } 45 | 46 | /// 47 | /// @brief Cleans up after each test. 48 | /// 49 | void 50 | PrintPterTest::tearDown () 51 | { 52 | Config::destroy (); 53 | // Telling the presenter to cancel will delete the view and the 54 | // presenter. 55 | if ( NULL != m_PrintPter ) 56 | { 57 | m_PrintPter->cancelActivated (); 58 | m_PrintPter = NULL; 59 | m_View = NULL; 60 | } 61 | delete m_Document; 62 | } 63 | 64 | /// 65 | /// @brief Check the initial's dialog sensitivity. 66 | /// 67 | void 68 | PrintPterTest::initialSensitivity () 69 | { 70 | // By default "All Pages" range is selected, so the 71 | // custom page ranges is insensitive. 72 | CPPUNIT_ASSERT ( !m_View->isSensitivePageRange ()); 73 | // By default the number of copies is 1, so the collate 74 | // option is insensitive. 75 | CPPUNIT_ASSERT ( !m_View->isSensitiveCollate ()); 76 | } 77 | 78 | /// 79 | /// @brief Check "Collate"'s sensitivity. 80 | /// 81 | /// The collate option is always sensitive unless the number 82 | /// of copies is 1. 83 | /// 84 | void 85 | PrintPterTest::collateSensitivity () 86 | { 87 | m_View->setNumberOfCopies (1); 88 | m_PrintPter->numberOfCopiesChanged (); 89 | CPPUNIT_ASSERT ( !m_View->isSensitiveCollate ()); 90 | 91 | m_View->setNumberOfCopies (10); 92 | m_PrintPter->numberOfCopiesChanged (); 93 | CPPUNIT_ASSERT ( m_View->isSensitiveCollate ()); 94 | 95 | m_View->setNumberOfCopies (234); 96 | m_PrintPter->numberOfCopiesChanged (); 97 | CPPUNIT_ASSERT ( m_View->isSensitiveCollate ()); 98 | 99 | m_View->setNumberOfCopies (1); 100 | m_PrintPter->numberOfCopiesChanged (); 101 | CPPUNIT_ASSERT ( !m_View->isSensitiveCollate ()); 102 | 103 | m_View->setNumberOfCopies (32); 104 | m_PrintPter->numberOfCopiesChanged (); 105 | CPPUNIT_ASSERT ( m_View->isSensitiveCollate ()); 106 | } 107 | 108 | /// 109 | /// @brief Check "Page Range"'s sensitivity. 110 | /// 111 | /// The page range entry is only sensitive when the "Range:" radio 112 | /// button is selected. 113 | /// 114 | void 115 | PrintPterTest::pageRangeSensitivity () 116 | { 117 | m_View->selectAllPagesRangeOption (); 118 | m_PrintPter->pageRangeOptionChanged (); 119 | CPPUNIT_ASSERT ( !m_View->isSensitivePageRange ()); 120 | 121 | m_View->selectCustomPagesRangeOption (); 122 | m_PrintPter->pageRangeOptionChanged (); 123 | CPPUNIT_ASSERT ( m_View->isSensitivePageRange ()); 124 | 125 | m_View->selectAllPagesRangeOption (); 126 | m_PrintPter->pageRangeOptionChanged (); 127 | CPPUNIT_ASSERT ( !m_View->isSensitivePageRange ()); 128 | 129 | m_View->selectCustomPagesRangeOption (); 130 | m_PrintPter->pageRangeOptionChanged (); 131 | CPPUNIT_ASSERT ( m_View->isSensitivePageRange ()); 132 | } 133 | -------------------------------------------------------------------------------- /src/JobPrint.h: -------------------------------------------------------------------------------- 1 | // ePDFView - A lightweight PDF Viewer. 2 | // Copyright (C) 2006-2011 Emma's Software. 3 | // Copyright (C) 2014-2025 Pablo Lezaeta 4 | // Copyright (C) 2014 Pedro A. Aranda Gutiérrez 5 | 6 | // ePDFView - A lightweight PDF Viewer. 7 | // 8 | // 9 | // This program is free software; you can redistribute it and/or modify 10 | // it under the terms of the GNU General Public License as published by 11 | // the Free Software Foundation; either version 2 of the License, or 12 | // (at your option) any later version. 13 | // 14 | // This program is distributed in the hope that it will be useful, 15 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 16 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 | // GNU General Public License for more details. 18 | // 19 | // You should have received a copy of the GNU General Public License 20 | // along with this program; if not, write to the Free Software 21 | // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 22 | 23 | #if !defined (__JOB_PRINT_H__) 24 | #define __JOB_PRINT_H__ 25 | 26 | namespace ePDFView 27 | { 28 | /// 29 | /// @enum PrintPageLayout 30 | /// 31 | enum PrintPageLayout 32 | { 33 | PRINT_PAGE_LAYOUT_PLAIN, 34 | PRINT_PAGE_LAYOUT_2IN1, 35 | PRINT_PAGE_LAYOUT_4IN1, 36 | PRINT_PAGE_LAYOUT_6IN1 37 | }; 38 | 39 | /// 40 | /// @enum PrintPageOrientation. 41 | /// 42 | enum PrintPageOrientation 43 | { 44 | PRINT_PAGE_ORIENTATION_PORTRAIT, 45 | PRINT_PAGE_ORIENTATION_LANDSCAPE 46 | }; 47 | 48 | /// 49 | /// @enum PrintPageSet 50 | /// 51 | enum PrintPageSet 52 | { 53 | PRINT_ALL_PAGE_SET, 54 | PRINT_EVEN_PAGE_SET, 55 | PRINT_ODD_PAGE_SET 56 | }; 57 | 58 | /// 59 | /// @class JobPrint 60 | /// @brief A background job that prints the document. 61 | /// 62 | /// This class converts the document to postscript and then 63 | /// uses CUPS to print the converted document. 64 | /// 65 | class JobPrint: public IJob 66 | { 67 | public: 68 | JobPrint (void); 69 | ~JobPrint (void); 70 | 71 | gboolean getCollate (void); 72 | const gchar *getColorModel (void); 73 | IDocument &getDocument (void); 74 | guint getNumberOfCopies (void); 75 | PrintPageLayout getPageLayout (void); 76 | PrintPageOrientation getPageOrientation (void); 77 | const gchar *getPrinterName (void); 78 | const gchar *getResolution (void); 79 | const gchar *getTempFileName (void); 80 | virtual gboolean run (void); 81 | void setCollate (gboolean collate); 82 | void setColorModel (const gchar *colorModel); 83 | void setDocument (IDocument *document); 84 | void setNumberOfCopies (guint copies); 85 | void setPageLayout (PrintPageLayout layout); 86 | void setPageOrientation (PrintPageOrientation orientation); 87 | void setPageRange (const gchar *range); 88 | void setPageSet (PrintPageSet set); 89 | void setPageSize (gfloat pageWidth, gfloat pageHeight); 90 | void setPrinterName (const gchar *name); 91 | void setResolution (const gchar *resolution); 92 | void setUpPrint (void); 93 | 94 | protected: 95 | gboolean m_Collate; 96 | gchar *m_ColorModel; 97 | guint m_CurrentPage; 98 | IDocument *m_Document; 99 | IDocument *m_DocumentCopy; 100 | guint m_NumberOfCopies; 101 | gfloat m_PageHeight; 102 | PrintPageLayout m_PageLayout; 103 | PrintPageOrientation m_PageOrientation; 104 | gboolean *m_PageRange; 105 | gchar *m_PageRangeString; 106 | PrintPageSet m_PageSet; 107 | gchar *m_Resolution; 108 | gfloat m_PageWidth; 109 | gchar *m_PrinterName; 110 | gchar *m_TempFileName; 111 | 112 | guint getCurrentPage (void); 113 | gfloat getPageHeight (void); 114 | const gchar *getPageRangeString (void); 115 | PrintPageSet getPageSet (void); 116 | gfloat getPageWidth (void); 117 | void setCurrentPage (guint pageNumber); 118 | void setTempFileName (const gchar *fileName); 119 | guint setUpPageRange (void); 120 | }; 121 | } 122 | 123 | #endif // __JOB_PRINT_H__ 124 | -------------------------------------------------------------------------------- /tests/DumbDocument.cxx: -------------------------------------------------------------------------------- 1 | // ePDFView - A lightweight PDF Viewer. 2 | // Copyright (C) 2006-2011 Emma's Software. 3 | // Copyright (C) 2014-2025 Pablo Lezaeta 4 | // Copyright (C) 2014 Pedro A. Aranda Gutiérrez 5 | 6 | // ePDFView - Dumb Test Document. 7 | // 8 | // 9 | // This program is free software; you can redistribute it and/or modify 10 | // it under the terms of the GNU General Public License as published by 11 | // the Free Software Foundation; either version 2 of the License, or 12 | // (at your option) any later version. 13 | // 14 | // This program is distributed in the hope that it will be useful, 15 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 16 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 | // GNU General Public License for more details. 18 | // 19 | // You should have received a copy of the GNU General Public License 20 | // along with this program; if not, write to the Free Software 21 | // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 22 | 23 | #include 24 | #include "DumbDocument.h" 25 | 26 | using namespace ePDFView; 27 | 28 | //////////////////////////////////////////////////////////////// 29 | // Interface Methods 30 | //////////////////////////////////////////////////////////////// 31 | 32 | DumbDocument::DumbDocument (): 33 | IDocument () 34 | { 35 | m_Loaded = FALSE; 36 | m_OpenError = DocumentErrorNone; 37 | m_SavedFileName = g_strdup (""); 38 | m_TestPassword = NULL; 39 | setNumPages (2); 40 | } 41 | 42 | DumbDocument::~DumbDocument () 43 | { 44 | clearCache (); 45 | g_free (m_SavedFileName); 46 | g_free (m_TestPassword); 47 | } 48 | 49 | IDocument * 50 | DumbDocument::copy () const 51 | { 52 | return new DumbDocument (); 53 | } 54 | 55 | GList * 56 | DumbDocument::findTextInPage (gint pageNum, const gchar *textToFind) 57 | { 58 | return NULL; 59 | } 60 | 61 | gboolean 62 | DumbDocument::isLoaded () 63 | { 64 | return m_Loaded; 65 | } 66 | 67 | gboolean 68 | DumbDocument::loadFile (const gchar *filename, const gchar *password, 69 | GError **error) 70 | { 71 | if ( DocumentErrorNone == m_OpenError ) 72 | { 73 | m_Loaded = TRUE; 74 | setFileName (filename); 75 | setPassword (password); 76 | } 77 | else if ( DocumentErrorEncrypted == m_OpenError && 78 | NULL != password && NULL != m_TestPassword && 79 | 0 == g_ascii_strcasecmp (password, m_TestPassword)) 80 | { 81 | m_Loaded = TRUE; 82 | setFileName (filename); 83 | setPassword (password); 84 | } 85 | else 86 | { 87 | g_set_error (error, EPDFVIEW_DOCUMENT_ERROR, m_OpenError, 88 | "%s", IDocument::getErrorMessage (m_OpenError)); 89 | m_Loaded = FALSE; 90 | } 91 | return m_Loaded; 92 | } 93 | 94 | void 95 | DumbDocument::getPageSizeForPage (gint pageNum, gdouble *width, gdouble *height) 96 | { 97 | if ( 90 == getRotation () || 270 == getRotation () ) 98 | { 99 | *width = 250; 100 | *height = 100; 101 | } 102 | else 103 | { 104 | *width = 100; 105 | *height = 250; 106 | } 107 | } 108 | 109 | void 110 | DumbDocument::outputPostscriptBegin (const gchar *fileName, guint numberOfPages, 111 | gfloat pageWidth, gfloat pageHeight) 112 | { 113 | } 114 | 115 | void 116 | DumbDocument::outputPostscriptEnd () 117 | { 118 | } 119 | 120 | void 121 | DumbDocument::outputPostscriptPage (guint pageNumber) 122 | { 123 | } 124 | 125 | DocumentPage * 126 | DumbDocument::renderPage (gint pageNum) 127 | { 128 | return new DocumentPage (); 129 | } 130 | 131 | gboolean 132 | DumbDocument::saveFile (const gchar *fileName, GError **error) 133 | { 134 | g_free (m_SavedFileName); 135 | m_SavedFileName = g_strdup (fileName); 136 | return TRUE; 137 | } 138 | 139 | //////////////////////////////////////////////////////////////// 140 | // Tests Methods 141 | //////////////////////////////////////////////////////////////// 142 | 143 | const gchar * 144 | DumbDocument::getSavedFileName () 145 | { 146 | return m_SavedFileName; 147 | } 148 | 149 | void 150 | DumbDocument::setOpenError (DocumentError error) 151 | { 152 | m_OpenError = error; 153 | } 154 | 155 | void 156 | DumbDocument::setOutline (DocumentOutline *outline) 157 | { 158 | m_Outline = outline; 159 | } 160 | 161 | void 162 | DumbDocument::setTestPassword (const gchar *password) 163 | { 164 | gchar *oldPassword = m_TestPassword; 165 | m_TestPassword = g_strdup (password); 166 | g_free (oldPassword); 167 | } 168 | -------------------------------------------------------------------------------- /INSTALL: -------------------------------------------------------------------------------- 1 | ePDFView Installation Instructions 2 | =================================== 3 | 4 | PREREQUISITES 5 | ============= 6 | 7 | Required: 8 | * GTK4 >= 4.0.0 9 | * Poppler with GLib bindings >= 0.5.0 10 | * GLib >= 2.8.0 11 | * Meson >= 0.50.0 12 | * Ninja build tool 13 | * pkg-config 14 | 15 | Optional: 16 | * CUPS (for printing support) 17 | * CppUnit (for running tests) 18 | 19 | INSTALLING DEPENDENCIES 20 | ======================= 21 | 22 | Arch Linux: 23 | $ sudo pacman -S gtk4 poppler-glib meson ninja cups base-devel 24 | 25 | Ubuntu/Debian: 26 | $ sudo apt install libgtk-4-dev libpoppler-glib-dev meson \ 27 | ninja-build libcups2-dev build-essential gettext 28 | 29 | Fedora/RHEL: 30 | $ sudo dnf install gtk4-devel poppler-glib-devel meson \ 31 | ninja-build cups-devel gcc-c++ gettext 32 | 33 | openSUSE: 34 | $ sudo zypper install gtk4-devel poppler-glib-devel meson \ 35 | ninja cups-devel gcc-c++ gettext-tools 36 | 37 | BASIC INSTALLATION 38 | ================== 39 | 40 | 1. Get the source code: 41 | 42 | From Git: 43 | $ git clone https://github.com/JotaRandom/epdfview.git 44 | $ cd epdfview 45 | 46 | From release tarball: 47 | $ tar xzf epdfview-0.3.0.tar.gz 48 | $ cd epdfview-0.3.0 49 | 50 | 2. Configure the build: 51 | 52 | $ meson setup builddir 53 | 54 | 3. Compile: 55 | 56 | $ meson compile -C builddir 57 | 58 | 4. Install (system-wide): 59 | 60 | $ sudo meson install -C builddir 61 | 62 | 5. Run: 63 | 64 | $ epdfview 65 | 66 | INSTALLATION OPTIONS 67 | ==================== 68 | 69 | Install to /usr instead of /usr/local: 70 | 71 | $ meson setup builddir --prefix=/usr 72 | $ meson compile -C builddir 73 | $ sudo meson install -C builddir 74 | 75 | Install to custom location: 76 | 77 | $ meson setup builddir --prefix=/opt/epdfview 78 | $ meson compile -C builddir 79 | $ sudo meson install -C builddir 80 | 81 | Install to home directory (no sudo needed): 82 | 83 | $ meson setup builddir --prefix=$HOME/.local 84 | $ meson compile -C builddir 85 | $ meson install -C builddir 86 | $ export PATH="$HOME/.local/bin:$PATH" 87 | 88 | BUILD OPTIONS 89 | ============= 90 | 91 | Disable CUPS printing support: 92 | 93 | $ meson setup builddir -Dcups=disabled 94 | 95 | Debug build: 96 | 97 | $ meson setup builddir --buildtype=debug 98 | 99 | Release build (optimized): 100 | 101 | $ meson setup builddir --buildtype=release 102 | 103 | View all options: 104 | 105 | $ meson configure builddir 106 | 107 | RUNNING WITHOUT INSTALLING 108 | =========================== 109 | 110 | After building, you can run directly from the build directory: 111 | 112 | $ ./builddir/src/epdfview 113 | 114 | UNINSTALLING 115 | ============ 116 | 117 | From the build directory: 118 | 119 | $ sudo ninja -C builddir uninstall 120 | 121 | Or manually remove files listed in: 122 | 123 | builddir/meson-logs/install-log.txt 124 | 125 | TROUBLESHOOTING 126 | =============== 127 | 128 | GTK4 not found: 129 | * Install GTK4 development packages 130 | * Verify: pkg-config --modversion gtk4 131 | 132 | Poppler not found: 133 | * Install Poppler GLib development packages 134 | * Verify: pkg-config --modversion poppler-glib 135 | 136 | CUPS not found (optional): 137 | * Install CUPS development packages 138 | * Or disable with: -Dcups=disabled 139 | 140 | Icons missing at runtime: 141 | * Icons installed to: PREFIX/share/pixmaps/ 142 | * Application searches: /usr/share/pixmaps and /usr/local/share/pixmaps 143 | * Reinstall or copy icons manually 144 | 145 | Build fails: 146 | * Clean build: rm -rf builddir && meson setup builddir 147 | * Check dependencies are installed 148 | * Read error messages carefully 149 | 150 | ADDITIONAL DOCUMENTATION 151 | ======================== 152 | 153 | For more detailed installation instructions and troubleshooting: 154 | 155 | See docs/INSTALLATION.md for comprehensive guide 156 | See docs/GTK4_MIGRATION_SUMMARY.md for technical details 157 | See CONTRIBUTING for development setup 158 | 159 | PACKAGING 160 | ========= 161 | 162 | For distribution packagers: 163 | 164 | Recommended install prefix: /usr 165 | Desktop file: data/epdfview.desktop 166 | Icons: data/*.png, data/epdfview.svg 167 | Translations: po/*.po (22 languages) 168 | Man page: data/epdfview.1 169 | 170 | Example for package: 171 | 172 | $ meson setup builddir --prefix=/usr 173 | $ meson compile -C builddir 174 | $ DESTDIR=$pkgdir meson install -C builddir 175 | 176 | LICENSE 177 | ======= 178 | 179 | ePDFView is free software licensed under GPL-2.0-or-later. 180 | See COPYING for full license text. 181 | -------------------------------------------------------------------------------- /src/IFindView.h: -------------------------------------------------------------------------------- 1 | // ePDFView - A lightweight PDF Viewer. 2 | // Copyright (C) 2006-2011 Emma's Software. 3 | // Copyright (C) 2014-2025 Pablo Lezaeta 4 | // Copyright (C) 2014 Pedro A. Aranda Gutiérrez 5 | 6 | // ePDFView - A lightweight PDF Viewer. 7 | // 8 | // 9 | // This program is free software; you can redistribute it and/or modify 10 | // it under the terms of the GNU General Public License as published by 11 | // the Free Software Foundation; either version 2 of the License, or 12 | // (at your option) any later version. 13 | // 14 | // This program is distributed in the hope that it will be useful, 15 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 16 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 | // GNU General Public License for more details. 18 | // 19 | // You should have received a copy of the GNU General Public License 20 | // along with this program; if not, write to the Free Software 21 | // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 22 | 23 | #if !defined (__IFIND_VIEW_H__) 24 | #define __IFIND_VIEW_H__ 25 | 26 | namespace ePDFView 27 | { 28 | // Forward declarations. 29 | class FindPter; 30 | 31 | /// 32 | /// @class IFindView 33 | /// @brief Interface for the find view. 34 | /// 35 | /// The find view is the view that will ask to the user the text to 36 | /// find in the dialog and also the "find progress dialog", which 37 | /// tells the user where is looking for at the moment. 38 | /// 39 | class IFindView 40 | { 41 | public: 42 | /// 43 | /// @brief Destroys all allocated memory for IFindView. 44 | /// 45 | virtual ~IFindView (void) 46 | { 47 | } 48 | 49 | /// 50 | /// @brief Gets the view's presenter. 51 | /// 52 | /// @return The presenter that is controlling the view. 53 | /// 54 | FindPter *getPresenter (void) 55 | { 56 | return m_Pter; 57 | } 58 | 59 | /// 60 | /// @brief Sets the view's presenter. 61 | /// 62 | /// After settings the presenter, the view can show the 63 | /// find bar. 64 | /// 65 | /// @param pter The presenter that will control the view. 66 | /// 67 | virtual void setPresenter (FindPter *pter) 68 | { 69 | m_Pter = pter; 70 | } 71 | 72 | /// 73 | /// @brief Gets the text to find. 74 | /// 75 | /// The view must get the text to find from the find dialog 76 | /// and return it. 77 | /// 78 | /// @return The text to find entered by the user. 79 | /// 80 | virtual const gchar *getTextToFind (void) = 0; 81 | 82 | /// 83 | /// @brief Hides the view. 84 | /// 85 | /// The view must be hidden when the presenter calls this member 86 | /// and also the text of the find entry must be set to an empty 87 | /// string. 88 | /// 89 | virtual void hide (void) = 0; 90 | 91 | /// 92 | /// @brief Sensitives the Find Next button. 93 | /// 94 | /// @param sensitive TRUE to sensitive the button, FALSE 95 | /// to insensitive it. 96 | /// 97 | virtual void sensitiveFindNext (gboolean sensitive) = 0; 98 | 99 | /// 100 | /// @brief Sensitives the Find Next button. 101 | /// 102 | /// @param sensitive TRUE to sensitive the button, FALSE 103 | /// to insensitive it. 104 | /// 105 | virtual void sensitiveFindPrevious (gboolean sensitive) = 0; 106 | 107 | /// 108 | /// @brief Sets the information text. 109 | /// 110 | /// The view must set a label to the specified text to 111 | /// show it to the user. The text to show is something like 112 | /// "Searching on page %d of %d" or "Not Found!", etc... 113 | /// 114 | /// @param text The text to show. 115 | /// 116 | virtual void setInformationText (const gchar *text) = 0; 117 | 118 | protected: 119 | /// The presenter that controls the view. 120 | FindPter *m_Pter; 121 | 122 | /// 123 | /// @brief Constructs a new IFindView object. 124 | /// 125 | IFindView (void) 126 | { 127 | m_Pter = NULL; 128 | } 129 | }; 130 | } 131 | 132 | #endif // !__IFIND_VIEW_H__ 133 | -------------------------------------------------------------------------------- /.kiro/specs/gtk4-meson-migration/requirements.md: -------------------------------------------------------------------------------- 1 | # Requirements Document 2 | 3 | ## Introduction 4 | 5 | This specification defines the requirements for migrating ePDFView from GTK2/Make to GTK4/Meson build system. The project is currently halfway through this migration and needs to be completed to modernize the codebase, improve maintainability, and ensure compatibility with current Linux distributions. 6 | 7 | ## Glossary 8 | 9 | - **ePDFView**: The lightweight PDF viewer application being migrated 10 | - **GTK2**: Legacy version of the GIMP Toolkit (deprecated) 11 | - **GTK4**: Current version of the GIMP Toolkit with modern APIs 12 | - **Make/Autotools**: Legacy build system using configure.ac and Makefile.am 13 | - **Meson**: Modern build system with meson.build files 14 | - **Migration_System**: The combined effort to update both UI toolkit and build system 15 | - **Compatibility_Layer**: Code that bridges GTK2/GTK4 API differences 16 | 17 | ## Requirements 18 | 19 | ### Requirement 1 20 | 21 | **User Story:** As a developer, I want to complete the GTK4 migration, so that the application uses modern UI APIs and remains compatible with current Linux distributions. 22 | 23 | #### Acceptance Criteria 24 | 25 | 1. WHEN building the application, THE Migration_System SHALL use only GTK4 APIs without GTK2 dependencies 26 | 2. WHEN the application runs, THE Migration_System SHALL display all UI elements correctly using GTK4 widgets 27 | 3. WHEN users interact with the interface, THE Migration_System SHALL respond to events using GTK4 event handling 28 | 4. WHERE GTK4 API changes exist, THE Migration_System SHALL implement proper replacements for deprecated GTK2 functions 29 | 5. WHILE maintaining functionality, THE Migration_System SHALL remove all GTK2 compatibility code from GTK4Compat.h 30 | 31 | ### Requirement 2 32 | 33 | **User Story:** As a developer, I want to complete the Meson build system migration, so that the project uses modern build tools and simplifies the build process. 34 | 35 | #### Acceptance Criteria 36 | 37 | 1. WHEN configuring the build, THE Migration_System SHALL use only Meson build files without Autotools dependencies 38 | 2. WHEN building the application, THE Migration_System SHALL compile successfully using ninja build commands 39 | 3. WHEN installing the application, THE Migration_System SHALL install all components correctly via Meson install 40 | 4. WHERE build options exist, THE Migration_System SHALL support debug/release configurations through Meson options 41 | 5. WHILE preserving functionality, THE Migration_System SHALL remove all Autotools files (configure.ac, Makefile.am, etc.) 42 | 43 | ### Requirement 3 44 | 45 | **User Story:** As a developer, I want to ensure all application features work correctly after migration, so that users experience no loss of functionality. 46 | 47 | #### Acceptance Criteria 48 | 49 | 1. WHEN opening PDF files, THE Migration_System SHALL display documents with the same quality as the original version 50 | 2. WHEN using zoom controls, THE Migration_System SHALL provide all zoom modes (fit, width, custom) correctly 51 | 3. WHEN searching text, THE Migration_System SHALL find and highlight text matches as before 52 | 4. WHERE printing is available, THE Migration_System SHALL maintain CUPS printing functionality on supported platforms 53 | 5. WHILE navigating documents, THE Migration_System SHALL preserve all keyboard shortcuts and menu actions 54 | 55 | ### Requirement 4 56 | 57 | **User Story:** As a maintainer, I want clean, modern code without legacy compatibility layers, so that the codebase is easier to maintain and extend. 58 | 59 | #### Acceptance Criteria 60 | 61 | 1. WHEN reviewing source code, THE Migration_System SHALL contain no GTK2-specific code or includes 62 | 2. WHEN examining build files, THE Migration_System SHALL contain no Autotools configuration files 63 | 3. WHEN checking dependencies, THE Migration_System SHALL require only GTK4 and modern library versions 64 | 4. WHERE compatibility code exists, THE Migration_System SHALL remove temporary migration helpers 65 | 5. WHILE updating code, THE Migration_System SHALL follow consistent C++11 coding standards throughout 66 | 67 | ### Requirement 5 68 | 69 | **User Story:** As a user, I want the migrated application to install and run on modern Linux distributions, so that I can continue using ePDFView with current systems. 70 | 71 | #### Acceptance Criteria 72 | 73 | 1. WHEN installing on current distributions, THE Migration_System SHALL install without dependency conflicts 74 | 2. WHEN launching the application, THE Migration_System SHALL start correctly on Wayland and X11 display servers 75 | 3. WHEN using system themes, THE Migration_System SHALL respect GTK4 theming and dark mode preferences 76 | 4. WHERE desktop integration exists, THE Migration_System SHALL register proper MIME types and desktop entries 77 | 5. WHILE maintaining compatibility, THE Migration_System SHALL work with current versions of Poppler library --------------------------------------------------------------------------------