diffpdf-2.1.3/.hg_archival.txt0000644000000000000000000000022412227164102014326 0ustar 00000000000000repo: 33e5f4f1af1afbfedd1d61bb98d0dc592225d4e5 node: c1a420ee08871a0f9c3b1834c2a1e959a13b78fe branch: default latesttag: 2.1.3 latesttagdistance: 1 diffpdf-2.1.3/.hgignore0000644000000000000000000000032012227164102013040 0ustar 00000000000000syntax: glob mailinglist.txt NOTES.txt *.qm *.lout diffpdf *.pdf Makefile *.a *.o *.py[co] *.so *.sw[nop] *~ .#* [#]*# *.ld *.ldx louti[0-9]* *.li *.lix *.tmp *.bak test.* moc_* *.obj qrc_*.cpp ui_*.h .*.swp diffpdf-2.1.3/.hgtags0000644000000000000000000000603612227164102012525 0ustar 0000000000000006d89482ba0fb3014928a4fb8b6fce87c96480bd 1.1.4 3ca6a6ac561eaf742f269b788c508d48b9eb0270 1.1.5 3ca6a6ac561eaf742f269b788c508d48b9eb0270 1.1.5 6637d13c295cf2ff3efe2549c9e4376b7b3e56fc 1.1.5 6637d13c295cf2ff3efe2549c9e4376b7b3e56fc 1.1.5 87c54366e22d9f99651c60ffc79f29c4d264c8ed 1.1.5 378dc28308d890a15d691f180a6543420dc43831 1.1.6 24204ef756edc4aae546dcc3090c4a42f7b72b84 1.2.0 24204ef756edc4aae546dcc3090c4a42f7b72b84 1.2.0 6a8806aad3f690a8d6957aa80038c9c1364fcff0 1.2.0 6a8806aad3f690a8d6957aa80038c9c1364fcff0 1.2.0 399e05df385ab9323b0d162a7d98c4678fdd4c63 1.2.0 399e05df385ab9323b0d162a7d98c4678fdd4c63 1.2.0 66e3d835215f21638fdd14f76d58c507a2a89fbb 1.2.0 7e8a6a819e52825cacfe385050e7df67232c71d1 1.2.2 51e42fe7476d21e6f1847c4456c515a469c77d0e 1.3.0 6314d6106ff338fb0d82b726ceef89a2d894a3ce 1.5.0 6314d6106ff338fb0d82b726ceef89a2d894a3ce 1.5.0 2ec9e948357da9798ca577ef3a75d19e93330447 1.5.0 2ec9e948357da9798ca577ef3a75d19e93330447 1.5.0 678f537ac47e297f271d8f57317f07764290fe33 1.5.0 6f6b80bef2f646c5cfdf6e559043d24aae6499c1 1.5.1 f449027e906aefd57e06585aa00a7e9ccf982544 1.6.0 f449027e906aefd57e06585aa00a7e9ccf982544 1.6.0 0358a5a1cff8951510dbe379ee066da26afa133f 1.6.0 c8229d38823362e4307d7856815f4608eab48616 1.6.1 e53a98ee253e746742740b90c4ed04f25d35a07e 1.6.2 e53a98ee253e746742740b90c4ed04f25d35a07e 1.6.2 8ebb3ac95d50df44ca42dc1fa8bf43a9d98b6e0f 1.6.2 8ebb3ac95d50df44ca42dc1fa8bf43a9d98b6e0f 1.6.2 92b7483daa14e847076db97af2f4b998ca6057aa 1.6.2 92b7483daa14e847076db97af2f4b998ca6057aa 1.6.2 599ea80e644ab0d17b19ec9649f4e1dbc63649d7 1.6.2 13fcd5c651a274e83f5b69d5115ded90b6380611 1.6.3 dcbd235f0ae1855d63e3f7be5d4f9e1b91da5ee4 1.7.0 dd619f3e44e13b71f548cf056396aab1a8272714 1.7.1 e28e7ef4954b17bececafa0367cf7b5a77494718 1.7.2 acb05669a242d6f3c81613b443c1d09bc5aef0eb 1.8.0 5521ab2ae175840f5f2da4e941afda9d1eae36bc 1.9.0 b8e2786728d0c7ba153f471765354a3497d854a8 1.9.1 359b3d87f7ba96f520e9bd8efbedfa30a0a11416 1.9.2 359b3d87f7ba96f520e9bd8efbedfa30a0a11416 1.9.2 996a8e414c7bdb662ea7376242df936a51783152 1.9.2 996a8e414c7bdb662ea7376242df936a51783152 1.9.2 e9f47a0abac01d6490ac5b15bddac51e78601fe0 1.9.2 52f39f71783af6285a009706a04c406de7f7acf6 1.9.3 caf61c566ee9531cda26b58f2e6b90bb88e6daf9 1.9.4 52f39f71783af6285a009706a04c406de7f7acf6 1.9.3 8e95ce1e5fe49391a433e95d5872aba66e51a73f 1.9.3 caf61c566ee9531cda26b58f2e6b90bb88e6daf9 1.9.4 0000000000000000000000000000000000000000 1.9.4 0000000000000000000000000000000000000000 1.9.4 8b227028222946f64b3402ceddfcdbc14680fd39 1.9.4 157f25d221708d075ab36f4e37e71b3940357fd7 1.9.5 0ba80f776ae84286b7ac6366529b4e8ae2899069 1.9.6 de27fd1ba0ef48bd64285f2d87d53830fb467750 2.0.0 de27fd1ba0ef48bd64285f2d87d53830fb467750 2.0.0 299f5f678b326e4eaa360fe4220a2e14c717a7ef 2.0.0 17344e046d97d847a651b689034e36dcf04ab3cf 2.0.1 104aecb50e2a39a70b22d23c7d1b5594bbecf7f0 2.0.2 b0a18e92ca60da147af10b601fd023de3112070e 2.0.3 5ece363d3f6a21579c3e5df858617f4a9fa626d5 2.0.4 cf618707fe4e9078a7c816d7d911dc11747757d8 2.1.0 60d09fc106eec3c03513f4e7ebcc1a62e1d36027 2.1.1 f75194e40f2e8a292fc895818817d863eada7d4d 2.1.2 dfbd5bb065f1f6e8e7d5949efc2fff9ecb4cfc2b 2.1.3 diffpdf-2.1.3/CHANGES0000644000000000000000000001375212227164102012245 0ustar 000000000000002.1.3 - Minor GUI fixes. - Subtle bug fix by Bryan Huh which _may_ help resolve the bug that affects saving when page ranges are in effect. 2.1.2 - Minor GUI bug fixes. - Minor translation fixes. - Updated copyright year. 2.1.1 - Tiny bug fix to make sure that the help file is in the right language. 2.1.0 - Dragging and and dropping files from Windows Explorer, Thunar, etc., now works (at least for me, on Windows 7 and Xubuntu). - Updated Czech translation from Pavel Fric. - French translation from Pierre-Alain Bandinelli. - German translation (and many suggestions) from Rainer Krachten. - Translations should "just work"; i.e., if you use a French locale then the user interface and help text should appear in French. However, you can force DiffPDF to use any language it supports by using the --language command line option (e.g., --language=fr). If an unsupported locale or --language option is used, DiffPDF will fall back to English. - Now support -h as a synonym for --help. - Initial path defaults to home directory instead of DiffPDF's installation directory. - Improved the Options dialog's layout. - A subtle bugfix to the --words command line option. - Fixed a crash: clicking to set a margin when there're no PDFs loaded now safely does nothing. 2.0.0 - Can now have comparisons exclude text that's outside user-specified margins. This feature was sponsored by a company that prefers to remain anonymous. - Save As can now save images as well as PDFs. - Minor bug fixes and improvements. - Command line help (--help) will no longer work on Windows. This is to avoid a spurious console window appearing. I've put the output in the online help though. - Improved dock window handling so that docks can now be stacked on top of each other (useful for small screens). 1.9.2 - Added missing step to the README. 1.9.1 - Save As now preserves the aspect ratio. Bug reported by Rainer Krachten. 1.9.0 - Added Czech translation provided by Pavel Fric. - Will now use the default locale's language for standard dialogs (e.g., for the file dialog). - Dragging & dropping one or two files onto the filename line edits or onto the file viewer panels is now supported. Independently suggested by Liviu Andronic and Rory Gordon. (This does not seem to work on Windows.) - Show Zones checkbox is always visible (it was only visible with --debug in earlier versions). - DiffPDF now starts up with its initial comparison mode being whatever comparison mode was in force when it was shut down (or Words mode the first time it is run). - Improved About box with more version info + contributors. - Added --help command line option. (For Windows this only works if diffpdf is compiled with access to the console.) 1.8.0 - Introduced zoning: this can be slow in Characters mode but can provide better accuracy in text modes. 1.7.1 - Improved Character mode to be as liberal about hyphens as Words mode. - Minor doc changes that I forgot for 1.7.0. - Minor GUI bug fixes and changes. - Minor under the hood efficiency improvements. 1.7.0 - Renamed Text mode to Words mode. This mode is best for alphabetic text (e.g., English). - Added Characters mode. This mode is best for logographic text (e.g., Chinese and Japanese). This was suggested by Paul Howarth. 1.6.3 - Very minor cosmetic changes. 1.6.2 - Save button is now only enabled if there are changes. - An improved help window with slightly more information. 1.6.1 - In rare cases the highlighting on the right hand page could be in the wrong (horizontal) position; this has now been fixed. 1.6.0 - In addition to Appearance comparisons using highlighting, some composition modes can now be used to help make subtle differences more visible. (This was inspired by feedback by Florian Heiderich.) - Can now control the square size for appearance comparisons. Using very small squares can help reveal tiny Appearance differences. - Can now control the fill opacity for highlighting. - Extended zoom range from 20% to 800% (was 25% to 400%). 1.5.1 Quite a few false-positives have now been eliminated: - All hyphens are treated the same now. - Some weirdly-encoded open/close double-quotes are treated as normal Unicode open/close double-quotes. - Improved whitespace ignoring. 1.5.0 Added Save As action and dialog for saving the differences to a PDF file. 1.3.0 Added support for -a, --appearance, -t, --text command line options to set the initial comparison mode. 1.2.3 Added a mention of comparepdf in the About box. 1.2.2 Tiny change in how command line arguments are handled. This should make things work with both English and non-English locales on Windows. 1.2.1 Minor improvement with focus control for Previous and Next buttons. Acknowledged Steven Lee for building Windows binaries and Dirk Loss for building Mac OS X binaries in the About box. 1.2.0 Got rid of old text comparison mode. Various small user interface improvements. Fixed a subtle bug that meant the combine text highlighting setting wasn't saved and restored correctly. 1.1.5 Slightly changed the .pro file to make it a tiny bit more helpful. Added a Help button and separated Help and About information. Updated the README for Mac users (thanks to Dirk Loss for the info). 1.1.4 Improved the reporting of files that are the same. 1.1.3 Tiny bugfix for Debian. 1.1.2 It is now possible for the user to control whether highlighting is combined in text mode. Added a cache for page images. This makes it much quicker to flick back and forth between pages. The cache size can be set by the user: the bigger the cache the more pages that can be flicked through without recalculating. 1.1.1 Replaced QVariant::toReal() with QVariant::toDouble() to avoid breaking compatibility with Qt 4.4. 1.1.0 Added margin rules to indicate where changes are. (These can be turned off by setting a rule width of 0.0.) 1.0.0 Implemented the sequence matcher algorithm for text mode matching. 0.6.0 Redid the user interface to use dock widgets. 0.5.0 First release. diffpdf-2.1.3/README0000644000000000000000000001165712227164102012134 0ustar 00000000000000DiffPDF =========== DiffPDF is used to compare two PDF files. By default the comparison is of the words on each pair of pages, but comparing character by character is also supported (e.g., for logographic languages). And there's also support for comparing the pages by appearance (for example, if a diagram is changed or if a paragraph is reformatted, or a font changed). It is also possible to compare particular pages or page ranges. For example, if there are two versions of a PDF file, one with pages 1-12 and the other with pages 1-13 because of an extra page having been added as page 4, they can be compared by specifying two page ranges, 1-12 for the first and 1-3, 5-13 for the second. This will make DiffPDF compare pages in the pairs (1, 1), (2, 2), (3, 3), (4, 5), (5, 6), and so on, to (12, 13). A couple of example PDF files are provided online so that you can try it out. PDF files can be loaded from the GUI (by pressing the File #1 and File #2 buttons), or by specifying them on the command line. More information is available in the program's tooltips and About box. (If you want a command line tool for comparing PDFs see http://www.qtrac.eu/comparepdf.html.) Home page: http://www.qtrac.eu/diffpdf.html Windows Users ============= Download the zip file, e.g., diffpdf-1.9.2.zip (where the number will vary depending on the version). Navigate to the file in Windows Explorer and use the context menu to choose the Extract All option. It doesn't matter what folder you extract to, but best to use one specifically for DiffPDF. The folder will contain diffpdf.exe and may contain some .dll files too. If there are .dll files, you must not move diffpdf.exe to any other folder! Once unzipped you can double-click diffpdf.exe to run it. You might also like to add a shortcut to it from the desktop or from the start menu. Compiling and Installing DiffPDF (Mac-specific notes are at the end.) ================================ Prerequisites: A C++ compiler, the Qt 4 libraries (I test with Qt 4.7 and Qt 4.8. Earlier Qt's may work although Qt 4.4 and 4.5 will at least need a compiler with tr1 support), and the Poppler libraries (at least 0.20.1, including Poppler's Qt 4 headers). Linux and BSD users should be able to get everything through their package management system---and some distros already include diffpdf so you don't even have to build it. Mac OS X users can get a compiler by installing Xcode; you'll need to get Qt and Poppler separately. 1. Unpack the archive file, diffpdf-XXX.tar.gz $ tar xvfz diffpdf-XXX.tar.gz 2. Change directory to diffpdf-XXX $ cd diffpdf-XXX 3. Run lrelease; on some sytems this might be called lrelease-qt4 $ lrelease diffpdf.pro 4. Run qmake; on some systems, run qmake-qt4 $ qmake 5. Run make $ make 6. Copy or soft-link the diffpdf executable to somewhere on your PATH 7. Only the executable is needed; all the files that were unpacked or generated can be safely deleted. That's it! Running DiffPDF =============== A pair of tiny example files are available: http://www.qtrac.eu/boson1.pdf and http://www.qtrac.eu/boson2.pdf. You can use these to see the difference between text and appearance comparisons and to get a feel for how DiffPDF works. If you hit a bug, please report it to mark@qtrac.eu. Be sure to include "DiffPDF" in the subject line and specify the version you are using and details of your system, e.g., operating system name and version, compiler name and version, Qt library version, Poppler library version. License ======= This program was written by Mark Summerfield. Copyright © 2008-13 Qtrac Ltd. All rights reserved. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 2 of the License, or (at your option), any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License (in file gpl-2.0.txt) for more details. Building on Mac OS X ==================== Here's how to build it: $ /usr/bin/ruby -e "$(curl -fsSL https://raw.github.com/gist/323731)" $ brew install qt $ brew install poppler --with-qt4 # Dirs must be writeable because macdeployqt modifies copied files $ chmod -R u+w /usr/local/Cellar/qt/ $ chmod -R u+w /usr/local/Cellar/poppler/ $ curl -O http://www.qtrac.eu/diffpdf-1.5.0.tar.gz $ tar xvfz diffpdf-1.5.0.tar.gz $ cd diffpdf-1.5.0 $ lrelease diffpdf.pro $ qmake -spec macx-g++ $ make Here's how to make a .dmg: # Fix references, remove unneeded Frameworks and build DMG $ macdeployqt diffpdf.app/ $ cd diffpdf.app/Contents/Frameworks/ $ rm -r QtDeclarative.framework/ QtNetwork.framework/ QtScript.framework/ QtSql.framework/ QtSvg.framework/ QtXmlPatterns.framework/ $ cd ../../.. $ hdiutil create diffpdf-1.5.0.dmg -srcfolder diffpdf.app/ Thanks to Dirk Loss for this information. diffpdf-2.1.3/aboutform.cpp0000644000000000000000000001156012227164102013747 0ustar 00000000000000/* Copyright © 2011-13 Qtrac Ltd. All rights reserved. This program or module is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. */ #include "aboutform.hpp" #include #include #include #include #include #include #include static const QString Version("2.1.3"); AboutForm::AboutForm(QWidget *parent) : QDialog(parent) { QTextBrowser *aboutBrowser = new QTextBrowser; aboutBrowser->setReadOnly(true); aboutBrowser->setOpenExternalLinks(true); aboutBrowser->setHtml(tr( "" "" "" "" "" "" "
%1 %2 by Mark Summerfield
<mark@qtrac.eu>.
Copyright © 2008-13 " "Qtrac Ltd. All rights reserved." "
Built with Qt %3 and Poppler %4.

" "

This program compares the text or the visual appearance of " "each page in two PDF files." "


If you like %1 you might like my books:

" "I also provide training and consultancy in C++, Go, Python 2, " "Python 3, C++/Qt, and PyQt4.").arg(qApp->applicationName()) .arg(Version).arg(qVersion()).arg(POPPLER_VERSION)); QTextBrowser *contributorsBrowser = new QTextBrowser; contributorsBrowser->setReadOnly(true); contributorsBrowser->setHtml(tr("" "" "" "" "" "" "" "" "" "" "" "" "" "" "
Anonymous Company " "— funded the addition of the margin exclusion " "functionality
David Paleino — " "Debian packager
Dirk Loss — creating " "Mac binaries
Florian Heiderich — suggested " "using composition modes for showing subtle differences
Jasmin Blanchette — " "the original idea and subsequent suggestions
Liviu Andronic — suggested adding " "drag and drop
Paul Howarth — suggestions " "resulting in Characters mode
Pavel Fric — " "Czech translation
Pierre-Alain " "Bandinelli— French translation
Rainer Krachten " "— German translation and various suggestions
Rory Gordon — suggested adding " "drag and drop
Bryan Huh — subtle bug fix" "
Steven Lee — creating " "Windows binaries
")); QTextBrowser *licenceBrowser = new QTextBrowser; licenceBrowser->setReadOnly(true); licenceBrowser->setHtml(tr( "This program is free software: you can redistribute it " "and/or modify it under the terms of the GNU General Public License " "as published by the Free Software Foundation, either version 2 of " "the License, or (at your option), any " "later version. This program is distributed in the hope that it will " "be useful, but WITHOUT ANY WARRANTY; without even the implied " "warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. " "See the GNU General Public License (in file gpl-2.0.txt) " "for more details.")); QTabWidget *tabWidget = new QTabWidget; tabWidget->addTab(aboutBrowser, tr("&About")); tabWidget->addTab(contributorsBrowser, tr("&Contributors")); tabWidget->addTab(licenceBrowser, tr("&License")); QHBoxLayout *layout = new QHBoxLayout; layout->addWidget(tabWidget); setLayout(layout); resize(480, 400); setWindowTitle(tr("%1 — About").arg(qApp->applicationName())); } diffpdf-2.1.3/aboutform.hpp0000644000000000000000000000137212227164102013754 0ustar 00000000000000#ifndef ABOUTFORM_HPP #define ABOUTFORM_HPP /* Copyright © 2011-13 Qtrac Ltd. All rights reserved. This program or module is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. */ #include class AboutForm : public QDialog { Q_OBJECT public: AboutForm(QWidget *parent=0); }; #endif // ABOUTFORM_HPP diffpdf-2.1.3/accelerators.acc0000644000000000000000000000130112227164102014354 0ustar 00000000000000# Main Window File #&1... File #&2... Pages Pages &Compare &View Show Previous Next Zoom Zoning Columns Tolerance/&R Tolerance/&Y Show Zones Exclude Margins Top Bottom Left Right Compare Options... &Save As... About Quit # Options General Tab General Highlighting Performance Show &Tooltips in main window Rule Width &Cancel &OK # Options Highlighting Tab General Highlighting Performance Base Color Outline &Fill Fill Opacity Combine Highlighting in Text Modes &Cancel &OK # Options Highlighting Tab General Highlighting Performance Square Size Cache Size &Cancel &OK # Save As Dialog Current Page Pair All Page Pairs File #&1's Pages File #&2's Pages Both File's Pages Filename Browse... &Cancel &OKdiffpdf-2.1.3/diffpdf.10000644000000000000000000000317112227164102012730 0ustar 00000000000000.TH DIFFPDF 1 "2013-10-15" "diffpdf v2.1.3" .SH NAME diffpdf \- compare two PDF files textually or visually .SH SYNOPSIS .B diffpdf .RI [ file1 ] .RI [ file2 ] .SH DESCRIPTION This manual page very briefly documents the \fBdiffpdf\fP command. (Click the GUI's Help button or press F1 for more information.) .PP \fBDiffPDF\fP is a GUI application used to compare two PDF files. .br By default the comparison is of the words on each pair of pages, but comparing character by character is also supported (e.g., for logographic languages). And there's also support for comparing the pages by appearance (for example, if a diagram is changed or if a paragraph is reformatted, or a font changed). It is also possible to compare particular pages or page ranges. For example, if there are two versions of a PDF file, one with pages 1-12 and the other with pages 1-13 because of an extra page having been added as page 4, they can be compared by specifying two page ranges, 1-12 for the first and 1-3, 5-13 for the second. This will make DiffPDF compare pages in the pairs (1, 1), (2, 2), (3, 3), (4, 5), (5, 6), and so on, to (12, 13). .PP If the program is passed two PDF filenames on the command line it will start up and compare those files in Text mode (or in Appearance mode if the filenames are preceded by -a or --appearance). .SH "SEE ALSO" For a command line tool for comparing PDF files see http://www.qtrac.eu/comparepdf.html. .SH AUTHOR diffpdf was written by Mark Summerfield . .PP This manual page was written by Mark Summerfield and David Paleino , for the Debian project (and may be used by others). diffpdf-2.1.3/diffpdf.pro0000644000000000000000000000421612227164102013371 0ustar 00000000000000# NOTES.txt # CHANGES # README # help.html # diffpdf.1 #DEFINES += DEBUG HEADERS += mainwindow.hpp SOURCES += mainwindow.cpp HEADERS += textitem.hpp SOURCES += textitem.cpp HEADERS += aboutform.hpp SOURCES += aboutform.cpp HEADERS += optionsform.hpp SOURCES += optionsform.cpp HEADERS += helpform.hpp SOURCES += helpform.cpp HEADERS += saveform.hpp SOURCES += saveform.cpp HEADERS += generic.hpp SOURCES += generic.cpp HEADERS += sequence_matcher.hpp SOURCES += sequence_matcher.cpp SOURCES += main.cpp HEADERS += lineedit.hpp SOURCES += lineedit.cpp HEADERS += label.hpp SOURCES += label.cpp RESOURCES += resources.qrc TRANSLATIONS += diffpdf_cz.ts TRANSLATIONS += diffpdf_fr.ts TRANSLATIONS += diffpdf_de.ts TRANSLATIONS += diffpdf_es.ts CODECFORTR = UTF-8 LIBS += -lpoppler-qt4 win32 { CONFIG += release } exists($(HOME)/opt/poppler024/) { message(Using locally built Poppler library) INCLUDEPATH += $(HOME)/opt/poppler024/include/poppler/cpp INCLUDEPATH += $(HOME)/opt/poppler024/include/poppler/qt4 LIBS += -Wl,-rpath -Wl,$(HOME)/opt/poppler024/lib -L$(HOME)/opt/poppler024/lib } else { exists(/poppler_lib) { message(Using locally built Poppler library on Windows) INCLUDEPATH += /c/poppler_lib/include/poppler/cpp INCLUDEPATH += /c/poppler_lib/include/poppler/qt4 LIBS += -Wl,-rpath -Wl,/c/poppler_lib/bin -Wl,-L/c/poppler_lib/bin } else { exists(/usr/include/poppler/qt4) { INCLUDEPATH += /usr/include/poppler/cpp INCLUDEPATH += /usr/include/poppler/qt4 } else { INCLUDEPATH += /usr/local/include/poppler/cpp INCLUDEPATH += /usr/local/include/poppler/qt4 } } } #exists($(HOME)/opt/podofo09/) { # message(Using locally built PoDoFo library) # INCLUDEPATH += $(HOME)/opt/podofo09/include/poppler/cpp # INCLUDEPATH += $(HOME)/opt/podofo09/include/poppler/qt4 # LIBS += -Wl,-rpath -Wl,$(HOME)/opt/podofo09/lib64 -Wl,-L$(HOME)/opt/podofo09/lib64 #} else { # exists(/usr/include/podofo) { # INCLUDEPATH += /usr/include/podofo # } else { # INCLUDEPATH += /usr/local/include/podofo # } #} diffpdf-2.1.3/diffpdf_cz.ts0000644000000000000000000015274112227164102013722 0ustar 00000000000000 UTF-8 AboutForm <table border=0><tr><td width=90%><b>%1</a> %2</b> by Mark Summerfield</td><td rowspan=3><img align=right src=":/icon.png"></td></tr><tr><td><tt>&lt;mark@qtrac.eu&gt;</tt>.</td></tr><tr><td colspan=2>Copyright &copy; 2008-13 <a href="http://www.qtrac.eu">Qtrac</a> Ltd. All rights reserved.</td></tr><tr><td colspan=2>Built with Qt %3 and Poppler %4.</td></tr></table><hr><p>This program compares the text or the visual appearance of each page in two PDF files.<hr><p>If you like %1 you might like my books:<ul><li><a href="http://www.qtrac.eu/gobook.html">Programming in Go</a></li><li><a href="http://www.qtrac.eu/aqpbook.html">Advanced Qt Programming</a></li><li><a href="http://www.qtrac.eu/py3book.html">Programming in Python 3</a></li><li><a href="http://www.qtrac.eu/pyqtbook.html">Rapid GUI Programming with Python and Qt</a></li></ul>I also provide training and consultancy in C++, Go, Python&nbsp;2, Python&nbsp;3, C++/Qt, and PyQt4. <table border=0><tr><td width=90%><b>%1</a> %2</b> by Mark Summerfield</td><td rowspan=3><img align=right src=":/icon.png"></td></tr><tr><td><tt>&lt;mark@qtrac.eu&gt;</tt>.</td></tr><tr><td colspan=2>Copyright &copy; 2008-12 <a href="http://www.qtrac.eu">Qtrac</a> Ltd. All rights reserved.</td></tr><tr><td colspan=2>Built with Qt %3 and Poppler %4.</td></tr></table><hr><p>This program compares the text or the visual appearance of each page in two PDF files.<hr><p>If you like %1 you might like my books:<ul><li><a href="http://www.qtrac.eu/gobook.html">Programming in Go</a></li><li><a href="http://www.qtrac.eu/aqpbook.html">Advanced Qt Programming</a></li><li><a href="http://www.qtrac.eu/py3book.html">Programming in Python 3</a></li><li><a href="http://www.qtrac.eu/pyqtbook.html">Rapid GUI Programming with Python and Qt</a></li></ul>I also provide training and consultancy in C++, Go, Python&nbsp;2, Python&nbsp;3, C++/Qt, and PyQt4. <table border=0><tr><td width=90%><b>%1</a> %2</b> od Marka Summerfielda</td><td rowspan=3><img align=right src=":/icon.png"></td></tr><tr><td><tt>&lt;mark@qtrac.eu&gt;</tt>.</td></tr><tr><td colspan=2>Autorské právo &copy; 2008-2012 <a href="http://www.qtrac.eu">Qtrac</a> Ltd. Všechna práva vyhrazena.</td></tr><tr><td colspan=2>Sestaveno s Qt %3 a Poppler %4.</td></tr></table><hr><p>Tento program srovnává text nebo viditelný vzhled každé strany ve dvou souborech PDF.<hr><p>Pokud se vám líbí %1, mohou se vám líbit i moje knihy:<ul><li><a href="http://www.qtrac.eu/gobook.html">Programování v Go</a></li><li><a href="http://www.qtrac.eu/aqpbook.html">Pokročilé programování v Qt</a></li><li><a href="http://www.qtrac.eu/py3book.html">Programování v Pythonu 3</a></li><li><a href="http://www.qtrac.eu/pyqtbook.html">Rychlé programování GUI v Pythonu a Qt</a></li></ul>Také poskytuji školení a poradenství v C++, Go, Python&nbsp;2, Python&nbsp;3, C++/Qt, a PyQt4. <table><tr><td>&bull;</td><td bgcolor=lightyellow><i>Anonymous Company</i> &mdash; funded the addition of the margin exclusion functionality</td></tr><tr><td>&bull;</td><td><b>David Paleino</b> &mdash; Debian packager</td></tr><tr><td>&bull;</td><td><b>Dirk Loss</b> &mdash; creating Mac binaries</td></tr><tr><td>&bull;</td><td>Florian Heiderich &mdash; suggested using composition modes for showing subtle differences</td></tr><tr><td>&bull;</td><td><b>Jasmin Blanchette</b> &mdash; the original idea and subsequent suggestions</td></tr><tr><td>&bull;</td><td>Liviu Andronic &mdash; suggested adding drag and drop</td></tr><tr><td>&bull;</td><td>Paul Howarth &mdash; suggestions resulting in Characters mode</td></tr><tr><td>&bull;</td><td bgcolor="#F0F0F0"><i>Pavel Fric</i> &mdash; Czech translation</td></tr><tr><td>&bull;</td><td bgcolor="#F0F0F0"><i>Pierre-Alain Bandinelli</i>&mdash; French translation</td></tr><tr><td>&bull;</td><td bgcolor="#F0F0F0"><i>Rainer Krachten</i> &mdash; German translation and various suggestions</td></tr><tr><td>&bull;</td><td>Rory Gordon &mdash; suggested adding drag and drop</td></tr><tr><td>&bull;</td><td><b>Steven Lee</b> &mdash; creating Windows binaries</td></tr></table> <table><tr><td>&bull;</td><td bgcolor=lightyellow><i>Anonymous Company</i> &mdash; funded the addition of the margin exclusion functionality</td></tr><tr><td>&bull;</td><td><b>David Paleino</b> &mdash; Debian packager</td></tr><tr><td>&bull;</td><td><b>Dirk Loss</b> &mdash; creating Mac binaries</td></tr><tr><td>&bull;</td><td>Florian Heiderich &mdash; suggested using composition modes for showing subtle differences</td></tr><tr><td>&bull;</td><td><b>Jasmin Blanchette</b> &mdash; the original idea and subsequent suggestions</td></tr><tr><td>&bull;</td><td>Liviu Andronic &mdash; suggested adding drag and drop</td></tr><tr><td>&bull;</td><td>Paul Howarth &mdash; suggestions resulting in Characters mode</td></tr><tr><td>&bull;</td><td bgcolor="#F0F0F0"><i>Pavel Fric</i> &mdash; Czech translation</td></tr><tr><td>&bull;</td><td bgcolor="#F0F0F0"><i>Pierre-Alain</i> Bandinelli&mdash; French translation</td></tr><tr><td>&bull;</td><td bgcolor="#F0F0F0"><i>Rainer Krachten</i> &mdash; German translation and various suggestions</td></tr><tr><td>&bull;</td><td>Rory Gordon &mdash; suggested adding drag and drop</td></tr><tr><td>&bull;</td><td><b>Steven Lee</b> &mdash; creating Windows binaries</td></tr></table> <table><tr><td>&bull;</td><td bgcolor=lightyellow><i>Anonymní společnost</i> &mdash; financovala přidání funkce vyloučení okraje</td></tr><tr><td>&bull;</td><td><b>David Paleino</b> &mdash; tvůrce balíčků pro Debian</td></tr><tr><td>&bull;</td><td><b>Dirk Loss</b> &mdash; vytvoření instalačních souborů pro Apple Mac</td></tr><tr><td>&bull;</td><td>Florian Heiderich &mdash; navrhl použití skladebných režimů pro ukázání jemných rozdílů</td></tr><tr><td>&bull;</td><td><b>Jasmin Blanchette</b> &mdash; původní myšlenka a následující návrhy</td></tr><tr><td>&bull;</td><td>Liviu Andronic &mdash; navrhl přidání funkce táhnout a upustit</td></tr><tr><td>&bull;</td><td>Paul Howarth &mdash; návrhy vedoucí ve výsledku k režimu znaků</td></tr><tr><td>&bull;</td><td bgcolor="#F0F0F0"><i>Pavel Fric</i> &mdash; překlad do češtiny</td></tr><tr><td>&bull;</td><td bgcolor="#F0F0F0">Pierre-Alain Bandinelli&mdash; překlad do francouzštiny</td></tr><tr><td>&bull;</td><td bgcolor="#F0F0F0"><i>Rainer Krachten</i> &mdash; překlad do němčiny a různé návrhy</td></tr><tr><td>&bull;</td><td>Rory Gordon &mdash; navrhl přidání funkce táhnout a upustit</td></tr><tr><td>&bull;</td><td><b>Steven Lee</b> &mdash; vytvoření instalačních souborů pro Windows</td></tr></table> This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 2 of the License, or (at your option), any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License (in file <tt>gpl-2.0.txt</tt>) for more details. Tento program je svobodným softwarem; můžete jej rozdávat a/nebo upravovat za podmínek GNU General Public License (GPL), jak jsou zveřejněny Free Software Foundation; buď ve verzi 2 licence, nebo (podle své volby) v kterékoli pozdější verzi. Tento program je šířen v naději, že bude užitečný, ale BEZ JAKÉKOLI ZÁRUKY; také bez předpokládané záruky PRODEJNOSTI nebo POUŽITELNOSTI PRO NĚJAKÝ URČITÝ ÚČEL: Více podrobností naleznete v GNU Library General Public License (v souboru <tt>gpl-2.0.txt</tt>). &About &O programu &Contributors &Přispěvatelé &License &Povolení %1 — About %1 — O programu HelpForm Escape Uniknout %1 — Help %1 — Nápověda MainWindow DiffPDF DiffPDF File #&1... Soubor #&1... <p>Choose the first (left hand) file to be compared. <p>Vyberte první soubor k porovnání (levá strana). The first (left hand) file. První soubor (levá strana). File #&2... Soubor #&2... <p>Choose the second (right hand) file to be compared. <p>Vyberte druhý soubor k porovnání (pravá strana). The second (right hand) file. Druhý soubor (pravá strana). Pa&ges: St&rany: <p>Pages can be specified using ranges such as 1-10, and multiple ranges can be used, e.g., 1-10, 12-15, 20, 22, 35-39. This makes it straighforward to compare similar documents where one has one or more additional pages.<p>For example, if file1.pdf has pages 1-30 and file2.pdf has pages 1-31 with the extra page being page 14, the two page ranges would be set to 1-30 for file1.pdf and 1-13, 15-31 for file2.pdf. <p>Strany lze stanovit pomocí rozsahu jako 1-10, a lze použít více rozsahů, např., 1-10, 12-15, 20, 22, 35-39. To to dělá přímočarým pro poravnávání podobných dokumentů, kde jeden má jednu nebo více dodatečných stran.<p>Například, pokud soubor1.pdf má strany 1-30 a soubor2.pdf má strany 1-31 se stranou navíc, která je stranou 14, dva rozsahy stran by byly nastaveny na 1-30 pro soubor1.pdf a 1-13, 15-31 pro soubor2.pdf. &Pages: S&trany: &Compare &Porovnat <p>Click to compare (or re-compare) the documents&mdash;or to cancel a comparison that's in progress. <p>Klepněte pro porovnání (nebo pro nové porovnání) dokumentu&mdash; nebo pro zrušení probíhajícího porovnávání. Appearance Vzhled Characters Znaky Words Slova <p>If the <b>Words</b> comparison mode is chosen, then each page's text is compared word by word (best for alphabetic languages like English). If the <b>Characters</b> comparison mode is chosen, then each page's text is compared character by character (best for logographic languages like Chinese and Japanese). If the <b>Appearance</b> comparison mode is chosen then each page's visual appearance is compared. Comparing appearance can be slow for large documents and can also produce false positives&mdash;but is absolutely precise. <p>Pokud je vybrán porovnávací režim <b>Slova</b>, potom je text každé strany porovnáván slovo za slovem (nejlepší pro abecední jazyky jako je angličtina). Pokud je vybrán porovnávací režim <b>Znaky</b>, potom je text každé strany porovnáván znak za znakem (nejlepší pro logografické jazyky jako jsou čínština a japonština). Pokud je vybrán porovnávací režim <b>Vzhled</b>potom je porovnáván viditelný vzhled každé strany. Porovnávání vzhledu může být u velkým dokumentů pomalé a také může vyvolat falešné kladné výsledky; ale je naprosto přesné. Co&mpare: Po&rovnat: &View: P&ohled: <p>Shows each pair of pages which are different. The comparison is textual unless the <b>Appearance</b> comparison mode is chosen, in which case the comparison is done visually. Visual differences can occur if a paragraph is formated differently or if an embedded diagram or image has changed. <p>Ukazuje každou dvojici stran, jež jsou rozdílné. Porovnání je textové, dokud je vybrán porovnávací režim Vzhled, v kterémžto případě je porovnávání prováděno zrakově. Viditelné rozdíly se mohou objevit, pokud je odstavec formátován jinak, nebo pokud byl vložený výkres nebo obrázek změněn. (Not viewing) (Nezobrazeno) S&how: &Ukázat: <p>In show <b>Highlighting</b> mode the pages are shown side by side with their differences highlighted. All the other modes are composition modes which show the first PDF as-is and the composition (blend) of the two PDFs. <p>Při zobrazení v režimu <b>Zvýraznění</b> jsou strany ukázány vedle sebe. Rozdíly mezi nimi jsou zvýrazněny. Všechny další režimy jsou skladebné režimy, které ukazují první PDF, jak je, a složení (směs) dvou PDF. %1Highlighting%2 %1Zvýraznění%2 Not Src Xor Dest Not Src Xor Dest Difference Rozdíl Exclusion Vyloučení Src Xor Dest Src Xor Dest Previo&us &Předchozí Ne&xt &Další &Zoom: &Zvětšení: <p>Determines the scale at which the pages are shown. <p>Určuje měřítko, v jakém se strany ukazují. % % Zo&ning &Oblasti <p>Zoning is a computationally expensive experimental mode that can reduce or eliminate false positives particularly for pages that have tables or that mix alphabetic and logographic languages&mdash;it can also increase false positives! Zoning only applies to text comparisons. <p>Rozdělení na oblasti je výpočetně nákladný pokusný režim, který může omezit nebo vyřadit falešně kladné výsledky zvláště pro strany, které obsahují tabulky nebo které míchají abecední a logografické jazyky&mdash;také může zvýšit množství falešně kladných výsledků! Rozdělení na oblasti se používá pouze při porovnávání textů. Co&lumns: &Sloupce: <p>Use this to tell DiffPDF how many columns the page has; this should improve the zoning. <p>Toto použijte na to, abyste DiffPDF pověděli, kolik sloupců strana má; mělo by to zlepšit rozdělení na pásma. Tolerance/&R: Odchylka/&R: <p>This is the maximum distance between text (word) rectangles for the rectangles to appear in the same zone. <p>Toto je největší vzdálenost mezi textovými obdélníky (slovo) pro obdélníky, které se mají objevit ve stejné oblasti. Tolerance/&Y: Odchylka/&Y: <p>Text position <i>y</i> coordinates are rounded to the nearest Tolerance/Y value when zoning. <p>Souřadnice <i>y</i> polohy textu jsou při rozdělení na oblasti zaokrouhleny k nejbližší hodnotě odchylky/Y. Sho&w Zones &Ukázat oblasti This is purely for debugging. Toto je čistě pro účel ladění. <p>This shows the zones that are being used and may be helpful when adjusting tolerances. (Its original purpose was for debugging.) <p>Toto ukazuje oblasti, které jsou používány, a může být užitečné při úpravách odchylek (Původním účelem tu bylo ladění.) &Exclude Margins V&yloučit okraje <p>If this is checked, anything outside non-zero margins is ignored when comparing. <p>Je-li zaškrtnuto, přehlíží se při porovnávání vše vně ne-nulových okrajů. &Top: &Nahoře: <p>The top margin in points. Anything above this will be ignored. <p>Horní okraj v bodech. Vše nad ním se bude přehlížet. &Bottom: &Dole: <p>The bottom margin in points. Anything below this will be ignored. <p>Dolní okraj v bodech. Vše pod ním se bude přehlížet. Le&ft: V&levo: <p>The left margin in points. Anything left of this will be ignored. <p>Levý okraj v bodech. Vše nalevo od něj se bude přehlížet. R&ight: V&pravo: <p>The right margin in points. Anything right of this will be ignored. <p>Pravý okraj v bodech. Vše napravo od něj se bude přehlížet. Choose files... Vybrat soubory... &Options... &Volby... Click to customize the application. Klepněte pro přizpůsobení programu. &Save As... Uložit &jako... Save the differences. Uložit rozdíly. Help Nápověda F1 F1 Click for basic help. Klepněte pro základní nápovědu. &About &O programu Click for copyright and credits. Klepněte pro údaje o autorském právu a poděkování. &Quit U&končit Click to terminate the application. Klepněte pro ukončení programu. <p>Shows the first (left hand) document's page that corresponds to the page shown in the View Difference combobox. <p>Ukáže první stranu dokumentu (nalevo), která odpovídá straně ukázané ve sdruženém okně pro Pohled na rozdíly. <p>Shows the second (right hand) document's page that corresponds to the page shown in the View Difference combobox. <p>Ukáže druhou stranu dokumentu (napravo), která odpovídá straně ukázané ve sdruženém okně pro Pohled na rozdíly. Controls Ovládání Actions Činnosti Margins Okraje Zoning Oblasti Log Zápis DiffPDF — Controls DiffPDF — Ovládání DiffPDF — Actions DiffPDF — Činnosti DiffPDF — Zoning DiffPDF — Rozdělení na oblasti DiffPDF — Margins DiffPDF — Okraje DiffPDF — Log DiffPDF — Zápis DiffPDF: False Positive DiffPDF — Falešné kladné výsledky DiffPDF — Choose File #1 DiffPDF — Vybrat soubor #1 PDF files (*.pdf) Soubory PDF (*.pdf) DiffPDF — Error DiffPDF — Chyba Cannot compare a file to itself. Soubor nelze porovnávat se sebou samým. <p style='font-size: xx-large;color: darkgreen'>DiffPDF: Click Compare<br>or change File #2.</p> <p style='font-size: xx-large;color: darkgreen'>DiffPDF: Klepněte na Porovnat<br>nebo změňte Soubor #2.</p> <p style='font-size: xx-large;color: darkgreen'>DiffPDF: Choose File #2.</p> <p style='font-size: xx-large;color: darkgreen'>DiffPDF: Vybrat soubor #2.</p> 1-%1 1-%1 Choose second file Vybrat druhý soubor Ready to compare Připraven k porovnávání DiffPDF — Choose File #2 DiffPDF — Vybrat soubor #2 <p style='font-size: xx-large;color: darkgreen'>DiffPDF: Click Compare<br>or change File #1.</p> <p style='font-size: xx-large;color: darkgreen'>DiffPDF: Klepněte na Porovnat<br>nebo změňte Soubor #1.</p> <p style='font-size: xx-large;color: darkgreen'>DiffPDF: Choose File #1.</p> <p style='font-size: xx-large;color: darkgreen'>DiffPDF: Vybrat soubor #1.</p> Choose first file Vybrat první soubor Cannot load '%1'. Nelze nahrát '%1'. Cannot read a locked PDF ('%1'). Nelze přečíst zamknutý soubor PDF ('%1'). <b>%1</b> <b>%1</b> %1: %2. %1: %2. Created: %1, last modified %2. Vytvořeno: %1, naposledy změněno %2. Created: %1. Vytvořeno: %1. Page count: %1. Počet stran: %1. Page size: %1pt x %2pt (%3mm x %4mm). Velikost strany: %1 bodů x %2 bodů (%3mm x %4mm). <font color=red>%1</font> <font color=red>%1</font> Failed to understand page range '%1'. Nepodařilo se porozumět stranovému rozsahu '%1'. &Cancel Z&rušit Ready Připraven Failed to read page %1 from '%2'. Nepodařilo se přečíst stranu %1 z '%2'. Comparing: %1 vs. %2. Porovnává se: %1 s %2. Cancelled. Zrušeno. %1 vs. %2 %3 %4 %1 s %2 %3 %4 Comparing %1/%2 Porovnává se %1/%2 Completed in %1 seconds. Hotovo za %1 sekund. <font color=brown>Files differ on 1 page (%1 page%2 compared).</font> <font color=brown>Soubory se liší na 1 straně (%1 stran%2 porovnáno).</font> was byla s were bylo <font color=brown>Files differ on %1 pages (%2 page%3 compared).</font> <font color=brown>Soubory se liší na %1 stranách (%2 stran%3 porovnáno).</font> The PDFs appear to be the same. Zdá se, že soubory PDF jsou stejné. <p style='font-size: x-large;color: darkgreen'>DiffPDF: The PDFs appear to be the same.</p> <p style='font-size: xx-large;color: darkgreen'>DiffPDF: PDF se zdají být stejná.</p> 1 differs %1/%2 compared 1 se liší %1/%2 porovnáno %1 differ %2/%3 compared %1 se liší %2/%3 porovnáno %1 differ%2 %3/%4 compared %1 se liší%2 %3/%4 porovnáno DiffPDF %1 %2 %1 %3 DiffPDF %1 %2 %1 %3 DiffPDF %1 %2 vs. %3 %1 %4 DiffPDF %1 %2 s %3 %1 %4 Saved %1 Uloženo %1 Failed to save %1 Nepodařilo se uložit %1 OptionsForm DiffPDF — Options DiffPDF — Volby No Brush Žádný štětec Solid Plný Dense #1 Hustá #1 Dense #2 Hustá #2 Dense #3 Hustá #3 Dense #4 Hustá #4 Dense #5 Hustá #5 Dense #6 Hustá #6 Horizontal Vodorovná Vertical Svislá Cross Kříž Diagonal / Šikmá / Diagonal \ Šikmá \ Diagonal Cross Šikmá kříž No Pen Žádné pero Dashed Čárkovaný Dotted Tečkovaný Dash-Dotted Čárkovaný-tečkovaný Dash-Dot-Dotted Čárkovaný-tečka-tečkovaný % % <p>How opaque the highlighting color is. The default is 13% <p>Nakolik neprůhledná je zvýrazňovací barva. Výchozí hodnota je 13% px px <p>The size of the highlighting squares in Appearance mode. Small values are more expensive to compute. Large values give coarse comparisons. The default is 10 px <p>Velikost zvýrazňovacích polí v režimu Vzhled. Malé hodnoty jsou více náročné na výpočet. Velké hodnoty dávají hrubá porovnání. Výchozí hodnota je 10 px No Rules Žádné vyznačovací čáry Show &Tooltips in the Main Window Ukázat v hlavním okně &nástrojové rady Combine Highlighting in &Text Modes Spojit zvýraznění v &textových režimech MB MB <p>The cache is used to store pages already seen to make flipping back and forth as fast as possible. The bigger the cache the more pages that can be stored. <p>Vyrovnávací paměť se používá na ukládání již viděných stran, aby bylo prolistování zpět a vpřed tak rychlé, jak jen je to možné. Čím větší je vyrovnávací paměť, tím více stran lze uložit. &Rule width: Šířka v&yznačovací čáry: &General &Obecné &Base Color: Zá&kladní barva: O&utline: &Obrys: &Fill: &Výplň: F&ill Opacity: Neprůhlednost výp&lně: <p>The outline and fill are used to highlight differences using a semi-transparent version of the base color. The margin rules are painted using the base color and indicate where changes are. Set the rule width to 0.0 to switch the rules off. If combining highlighting is checked it will try to merge the highlighting of adjacent text differences. <p>Obrys a výplň se používají na zvýraznění rozdílů pomocí poloprůhledného podání základní barvy. Vyznačovací čáry na okrajích jsou malovány pomocí základní barvy a naznačují, kde jsou změny. Nastavte šířku vyznačovací čáry na 0.0 pro vypnutí vyznačovacích čar. Je-li zaškrtnuto spojení zvýraznění, bude proveden pokus o sloučení zvýraznění sousedních textových rozdílů. &Highlighting &Zvýraznění &Square Size: Velikost &pole: C&ache Size: V&elikost vyrovnávací paměti: &Performance &Výkon SaveForm DiffPDF — Save As DiffPDF — Uložit jako Pairs Dvojice Current &Page Pair Nynější dvojice &stran &All Page Pairs &Všechny dvojice stran Pages Strany File #&1's Pages Soubor #&1 strany File #&2's Pages Soubor #&2 strany &Both Files' Pages &Obě strany souboru &Filename: &Název souboru: B&rowse... &Procházet... DiffPDF — Browse DiffPDF — Procházet PDF files (*.pdf);;Image files (%1) Soubory PDF (*.pdf);;Obrázkové soubory (%1) diffpdf-2.1.3/diffpdf_de.ts0000644000000000000000000015473312227164102013701 0ustar 00000000000000 UTF-8 AboutForm <table border=0><tr><td width=90%><b>%1</a> %2</b> by Mark Summerfield</td><td rowspan=3><img align=right src=":/icon.png"></td></tr><tr><td><tt>&lt;mark@qtrac.eu&gt;</tt>.</td></tr><tr><td colspan=2>Copyright &copy; 2008-13 <a href="http://www.qtrac.eu">Qtrac</a> Ltd. All rights reserved.</td></tr><tr><td colspan=2>Built with Qt %3 and Poppler %4.</td></tr></table><hr><p>This program compares the text or the visual appearance of each page in two PDF files.<hr><p>If you like %1 you might like my books:<ul><li><a href="http://www.qtrac.eu/gobook.html">Programming in Go</a></li><li><a href="http://www.qtrac.eu/aqpbook.html">Advanced Qt Programming</a></li><li><a href="http://www.qtrac.eu/py3book.html">Programming in Python 3</a></li><li><a href="http://www.qtrac.eu/pyqtbook.html">Rapid GUI Programming with Python and Qt</a></li></ul>I also provide training and consultancy in C++, Go, Python&nbsp;2, Python&nbsp;3, C++/Qt, and PyQt4. <table border=0><tr><td width=90%><b>%1</a> %2</b> by Mark Summerfield</td><td rowspan=3><img align=right src=":/icon.png"></td></tr><tr><td><tt>&lt;mark@qtrac.eu&gt;</tt>.</td></tr><tr><td colspan=2>Copyright &copy; 2008-12 <a href="http://www.qtrac.eu">Qtrac</a> Ltd. All rights reserved.</td></tr><tr><td colspan=2>Built with Qt %3 and Poppler %4.</td></tr></table><hr><p>This program compares the text or the visual appearance of each page in two PDF files.<hr><p>If you like %1 you might like my books:<ul><li><a href="http://www.qtrac.eu/gobook.html">Programming in Go</a></li><li><a href="http://www.qtrac.eu/aqpbook.html">Advanced Qt Programming</a></li><li><a href="http://www.qtrac.eu/py3book.html">Programming in Python 3</a></li><li><a href="http://www.qtrac.eu/pyqtbook.html">Rapid GUI Programming with Python and Qt</a></li></ul>I also provide training and consultancy in C++, Go, Python&nbsp;2, Python&nbsp;3, C++/Qt, and PyQt4. <table border=0><tr><td width=90%><b>%1</a> %2</b> von Mark Summerfield</td><td rowspan=3><img align=right src=":/icon.png"></td></tr><tr><td><tt>&lt;mark@qtrac.eu&gt;</tt>.</td></tr><tr><td colspan=2>Copyright &copy; 2008-2013 <a href="http://www.qtrac.eu">Qtrac</a> Ltd. All rights reserved.</td></tr><tr><td colspan=2>Erzeugt mit Qt %3 und Poppler %4.</td></tr></table><hr><p>Dieses Programm vergleicht die Seiten von zwei PDF Dateien anhand der Texte oder der visuellen Unterschiede.<hr><p>Wenn Ihnen %1 gefällt, dann haben Sie vielleicht auch Interesse an meinen Büchern:<ul><li><a href="http://www.qtrac.eu/gobook.html">Programming in Go</a></li><li><a href="http://www.qtrac.eu/aqpbook.html">Advanced Qt Programming</a></li><li><a href="http://www.qtrac.eu/py3book.html">Programming in Python 3</a></li><li><a href="http://www.qtrac.eu/pyqtbook.html">Rapid GUI Programming with Python and Qt</a></li></ul>Gerne stehe ich Ihnen auch als Trainer oder Berater für C++, Go, Python&nbsp;2, Python&nbsp;3, C++/Qt, und PyQt4 zur Verfügung. <table><tr><td>&bull;</td><td bgcolor=lightyellow><i>Anonymous Company</i> &mdash; funded the addition of the margin exclusion functionality</td></tr><tr><td>&bull;</td><td><b>David Paleino</b> &mdash; Debian packager</td></tr><tr><td>&bull;</td><td><b>Dirk Loss</b> &mdash; creating Mac binaries</td></tr><tr><td>&bull;</td><td>Florian Heiderich &mdash; suggested using composition modes for showing subtle differences</td></tr><tr><td>&bull;</td><td><b>Jasmin Blanchette</b> &mdash; the original idea and subsequent suggestions</td></tr><tr><td>&bull;</td><td>Liviu Andronic &mdash; suggested adding drag and drop</td></tr><tr><td>&bull;</td><td>Paul Howarth &mdash; suggestions resulting in Characters mode</td></tr><tr><td>&bull;</td><td bgcolor="#F0F0F0"><i>Pavel Fric</i> &mdash; Czech translation</td></tr><tr><td>&bull;</td><td bgcolor="#F0F0F0"><i>Pierre-Alain Bandinelli</i>&mdash; French translation</td></tr><tr><td>&bull;</td><td bgcolor="#F0F0F0"><i>Rainer Krachten</i> &mdash; German translation and various suggestions</td></tr><tr><td>&bull;</td><td>Rory Gordon &mdash; suggested adding drag and drop</td></tr><tr><td>&bull;</td><td><b>Steven Lee</b> &mdash; creating Windows binaries</td></tr></table> <table><tr><td>&bull;</td><td bgcolor=lightyellow><i>Anonymous Company</i> &mdash; funded the addition of the margin exclusion functionality</td></tr><tr><td>&bull;</td><td><b>David Paleino</b> &mdash; Debian packager</td></tr><tr><td>&bull;</td><td><b>Dirk Loss</b> &mdash; creating Mac binaries</td></tr><tr><td>&bull;</td><td>Florian Heiderich &mdash; suggested using composition modes for showing subtle differences</td></tr><tr><td>&bull;</td><td><b>Jasmin Blanchette</b> &mdash; the original idea and subsequent suggestions</td></tr><tr><td>&bull;</td><td>Liviu Andronic &mdash; suggested adding drag and drop</td></tr><tr><td>&bull;</td><td>Paul Howarth &mdash; suggestions resulting in Characters mode</td></tr><tr><td>&bull;</td><td bgcolor="#F0F0F0"><i>Pavel Fric</i> &mdash; Czech translation</td></tr><tr><td>&bull;</td><td bgcolor="#F0F0F0"><i>Pierre-Alain</i> Bandinelli&mdash; French translation</td></tr><tr><td>&bull;</td><td bgcolor="#F0F0F0"><i>Rainer Krachten</i> &mdash; German translation and various suggestions</td></tr><tr><td>&bull;</td><td>Rory Gordon &mdash; suggested adding drag and drop</td></tr><tr><td>&bull;</td><td><b>Steven Lee</b> &mdash; creating Windows binaries</td></tr></table> <table><tr><td>&bull;</td><td bgcolor=lightyellow><i>Anonyme Firma</i> &mdash; Sponsor für die Erweiterung Randbereiche auszuschließen</td></tr><tr><td>&bull;</td><td><b>David Paleino</b> &mdash; Debian packager</td></tr><tr><td>&bull;</td><td><b>Dirk Loss</b> &mdash; Erstellung des Programms für Mac</td></tr><tr><td>&bull;</td><td>Florian Heiderich &mdash; schlug vor Kompositions-Modi zu verwenden um kleine Unterschiede anzuzeigen</td></tr><tr><td>&bull;</td><td><b>Jasmin Blanchette</b> &mdash; Die ursprüngliche Idee und weitere Vorschläge</td></tr><tr><td>&bull;</td><td>Liviu Andronic &mdash; schlug vor drag and drop hinzuzufügen</td></tr><tr><td>&bull;</td><td>Paul Howarth &mdash; Auf Basis seiner Vorschläge entstand der Zeichen-für-Zeichen Vergleichsmodus</td></tr><tr><td>&bull;</td><td bgcolor="#F0F0F0"><i>Pavel Fric</i> &mdash; Tschechische Übersetzung</td></tr><tr><td>&bull;</td><td bgcolor="#F0F0F0"><i>Pierre-Alain</i> Bandinelli&mdash; Französische Übersetzung</td></tr><tr><td>&bull;</td><td bgcolor="#F0F0F0"><i>Rainer Krachten</i> &mdash; Deutsche Übersetzung und einige Vorschläge</td></tr><tr><td>&bull;</td><td>Rory Gordon &mdash; schlug vor drag and drop hinzuzufügen</td></tr><tr><td>&bull;</td><td><b>Steven Lee</b> &mdash; Erstellung des Programms für Windows</td></tr></table> This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 2 of the License, or (at your option), any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License (in file <tt>gpl-2.0.txt</tt>) for more details. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 2 of the License, or (at your option), any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License (in file <tt>gpl-2.0.txt</tt>) for more details. &About &Info &Contributors &Mitwirkende &License &Lizenz %1 — About %1 — Info HelpForm Escape Where does this text show up? Does it refer to the key on the keyboard? Yes, this is a keypress so shouldn't be here! Escape %1 — Help %1 — Hilfe MainWindow DiffPDF DiffPDF File #&1... Datei #&1... <p>Choose the first (left hand) file to be compared. <p>Bitte wählen Sie die erste Datei (linke Seite) zum Vergleich aus. The first (left hand) file. Die erste Datei (linke Seite). File #&2... Datei #&2... <p>Choose the second (right hand) file to be compared. <p>Bitte wählen Sie die zweite Datei (rechte Seite) zum Vergleich aus. The second (right hand) file. Die zweite Datei (rechte Seite). Pa&ges: &Seiten: <p>Pages can be specified using ranges such as 1-10, and multiple ranges can be used, e.g., 1-10, 12-15, 20, 22, 35-39. This makes it straighforward to compare similar documents where one has one or more additional pages.<p>For example, if file1.pdf has pages 1-30 and file2.pdf has pages 1-31 with the extra page being page 14, the two page ranges would be set to 1-30 for file1.pdf and 1-13, 15-31 for file2.pdf. <p>Bei der Angabe von Seiten können Bereiche angegeben werden, etwa 1-10. Es können auch mehrere Bereiche angegeben werden, etwa 1-10, 12-15, 20, 22, 35-39. So ist es leicht möglich zwei Versionen des gleichen Dokuments zu vergleichen, auch wenn ein Dokument zusätzliche Seiten enthält.<p>Ein Beispiel: Angenommen Datei 1 enthält 30 Seiten und Datei 2 enthält 31 Seiten, und die zusätzliche Seite ist Seite 14, dann würden die Seitenbereiche angegeben mit 1-30 für Datei 1 und 1-13, 15-31 für Datei 2. &Pages: &Seiten: &Compare &Vergleichen <p>Click to compare (or re-compare) the documents&mdash;or to cancel a comparison that's in progress. <p>Startet den Vergleich der Dokumente &mdash; oder bricht einen laufenden Vergleich ab. Appearance Visuell Characters Zeichen-für-Zeichen Words Wort-für-Wort <p>If the <b>Words</b> comparison mode is chosen, then each page's text is compared word by word (best for alphabetic languages like English). If the <b>Characters</b> comparison mode is chosen, then each page's text is compared character by character (best for logographic languages like Chinese and Japanese). If the <b>Appearance</b> comparison mode is chosen then each page's visual appearance is compared. Comparing appearance can be slow for large documents and can also produce false positives&mdash;but is absolutely precise. <p>Im Vergleichsmodus <b>Wort-für-Wort</b> wird der Text jeder Seite wortweise verglichen (am besten geeignet für alphabetische Sprachen wie etwa Deutsch). Im Modus <b>Zeichen-für-Zeichen</b> werden die einzelnen Zeichen des Textes verglichen (am besten geeignet für logographische Sprachen wie Chinesisch oder Japanisch). Beim <b>visuellen</b> Vergleich wird jede Seite anhand der sichtbaren Unterschiede verglichen. Der visuelle Vergleich kann bei umfangreichen Dokumenten einige Zeit dauern und kann zu Fehlerkennungen führen&mdash;arbeitet jedoch absolut präzise. Co&mpare: &Vergleichsmodus: &View: &Ansicht: <p>Shows each pair of pages which are different. The comparison is textual unless the <b>Appearance</b> comparison mode is chosen, in which case the comparison is done visually. Visual differences can occur if a paragraph is formated differently or if an embedded diagram or image has changed. <p>Liste alle Seitenpaare mit Unterschieden. Der Vergleich ist textuell sofern nicht der <b>visuelle</b> Vergleichsmodus gewählt wurde. Visuelle Unterschiede können auftreten wenn ein Absatz anders formatiert wurde oder wenn ein eingebettetes Diagramm oder Bild sich geändert hat. (Not viewing) (Keine Anzeige) S&how: &Anzeige: <p>In show <b>Highlighting</b> mode the pages are shown side by side with their differences highlighted. All the other modes are composition modes which show the first PDF as-is and the composition (blend) of the two PDFs. <p>Bei Anzeigemodus <b>Hervorhebung</b> werden die Seiten nebeneinander gestellt und Unterschiede farblich markiert. Alle anderen Modi sind Kompositions-Modi welche die Seite aus Datei #1 anzeigen wie sie ist und daneben die Komposition (Überblendung) der beiden Seiten. %1Highlighting%2 %1Hervorhebung%2 Not Src Xor Dest Not Src Xor Dest Difference Difference Exclusion Exclusion Src Xor Dest Src Xor Dest Previo&us &Vorherige Ne&xt &Nächste &Zoom: &Vergrößerung: <p>Determines the scale at which the pages are shown. <p>Legt die Skalierung fest in welcher die Seiten angezeigt werden. % % Zo&ning &Einteilung <p>Zoning is a computationally expensive experimental mode that can reduce or eliminate false positives particularly for pages that have tables or that mix alphabetic and logographic languages&mdash;it can also increase false positives! Zoning only applies to text comparisons. <p>Die Einteilung ist ein rechenintensiver, experimenteller Modus, der Fehlerkennungen reduzieren und ganz verhindern kann, insbesondere bei Seiten die Tabellen enthalten oder die sowohl alphabetische als auch logographische Texte enthalten.&mdash;Er kann jedoch auch zu vermehrten Fehlerkennungen führen. Die Einteilung wird ausschließlich bei texutellen Vergleichsmodi angewendet. Co&lumns: &Spalten: <p>Use this to tell DiffPDF how many columns the page has; this should improve the zoning. <p>Gibt an, in wie viele Spalten die Seite aufgeteilt ist; die Angabe erleichtert die Einteilung. Tolerance/&R: Toleranz/&B: <p>This is the maximum distance between text (word) rectangles for the rectangles to appear in the same zone. <p>Der Maximalabstand der zwischen Text- (Wort-) Bereichen bestehen darf, damit sie zu einem einzigen Bereich zusammengefasst werden. Tolerance/&Y: Toleranz/&Y: <p>Text position <i>y</i> coordinates are rounded to the nearest Tolerance/Y value when zoning. <p><i>Y</i>-Koordinaten von Text-Bereichen werden bei der Einteilung auf den nächsten Toleranz/Y-Wert gerundet. Sho&w Zones Ein&teilung anzeigen <p>This shows the zones that are being used and may be helpful when adjusting tolerances. (Its original purpose was for debugging.) <p>Zeichnet die Einteilungs-Bereiche ein, was bei der Einstellung der Toleranzwerte hilfreich sein kann. (Wurde ursprünglich nur für die Fehlerbehebung entwickelt) &Exclude Margins &Randbereiche ausschließen <p>If this is checked, anything outside non-zero margins is ignored when comparing. <p>Wenn aktiv wird alles innerhalb der eingestellten Randbereiche für den Vergleich ignoriert. &Top: &Oben: <p>The top margin in points. Anything above this will be ignored. <p>Der obere Abstand in Punkten. Alles innerhalb des Bereichs wird ignoriert. &Bottom: &Unten: <p>The bottom margin in points. Anything below this will be ignored. <p>Der untere Abstand in Punkten. Alles innerhalb des Bereichs wird ignoriert. Le&ft: &Links: <p>The left margin in points. Anything left of this will be ignored. <p>Der linke Abstand in Punkten. Alles innerhalb des Bereichs wird ignoriert. R&ight: &Rechts: <p>The right margin in points. Anything right of this will be ignored. <p>Der rechte Abstand in Punkten. Alles innerhalb des Bereichs wird ignoriert. Choose files... Dateien auswählen... &Options... &Optionen... Click to customize the application. Anpassen der Anwendungseinstellungen. &Save As... &Speichern unter... Save the differences. Vergleich als Datei abspeichern. Help Hilfe F1 F1 Click for basic help. Zeigt die Hilfe an. &About &Info Click for copyright and credits. Zeigt die Lizenzbedingungen und Mitwirkende an. &Quit &Beenden Click to terminate the application. Schließt die Anwendung. <p>Shows the first (left hand) document's page that corresponds to the page shown in the View Difference combobox. <p>Zeigt die Seite des ersten (linken) Dokuments entsprechend des gewählten Eintrags in der Ansicht-Auswahlbox. <p>Shows the second (right hand) document's page that corresponds to the page shown in the View Difference combobox. <p>Zeigt die Seite des zweiten (rechten) Dokuments entsprechend des gewählten Eintrags in der Ansicht-Auswahlbox. Controls Steuerung Actions Aktionen Margins Randbereich Zoning Einteilung (Zonen-Bildung) Log Log DiffPDF — Controls DiffPDF — Steuerung DiffPDF — Actions DiffPDF — Aktionen DiffPDF — Zoning DiffPDF — Einteilung (Zonen-Bildung) DiffPDF — Margins DiffPDF — Randbereich DiffPDF — Log DiffPDF — Log DiffPDF: False Positive DiffPDF: Fehlerkennung DiffPDF — Choose File #1 DiffPDF — Bitte Datei #1 auswählen PDF files (*.pdf) PDF-Dateien (*.pdf) DiffPDF — Error DiffPDF — Fehler Cannot compare a file to itself. Datei kann nicht mit sich selbst verglichen werden. <p style='font-size: xx-large;color: darkgreen'>DiffPDF: Click Compare<br>or change File #2.</p> <p style='font-size: xx-large;color: darkgreen'>DiffPDF: Bitte Schaltfläche "Vergleichen" drücken<br>oder Datei #2 ändern.</p> <p style='font-size: xx-large;color: darkgreen'>DiffPDF: Choose File #2.</p> <p style='font-size: xx-large;color: darkgreen'>DiffPDF: Bitte Datei #2 auswählen.</p> 1-%1 1-%1 Choose second file Zweite Datei auswählen Ready to compare Bereit für den Vergleich DiffPDF — Choose File #2 DiffPDF — Bitte Datei #2 auswählen <p style='font-size: xx-large;color: darkgreen'>DiffPDF: Click Compare<br>or change File #1.</p> <p style='font-size: xx-large;color: darkgreen'>DiffPDF: Bitte Schaltfläche "Vergleichen" drücken<br>oder Datei #1 ändern.</p> <p style='font-size: xx-large;color: darkgreen'>DiffPDF: Choose File #1.</p> <p style='font-size: xx-large;color: darkgreen'>DiffPDF: Bitte Datei #1 auswählen.</p> Choose first file Erste Datei auswählen Cannot load '%1'. '%1' kann nicht geladen werden. Cannot read a locked PDF ('%1'). Gesperrte PDF-Datei ('%1') kann nicht geladen werden. <b>%1</b> <b>%1</b> %1: %2. %1: %2. Created: %1, last modified %2. Erstellt: %1, Letzte Änderung %2. Created: %1. Erstellt: %1. Page count: %1. Anzahl Seiten: %1. Page size: %1pt x %2pt (%3mm x %4mm). Seitenmaße: %1pt x %2pt (%3mm x %4mm). <font color=red>%1</font> <font color=red>%1</font> Failed to understand page range '%1'. Seitenbereich '%1' konnte nicht ausgewertet werden. &Cancel &Abbrechen Ready Bereit Failed to read page %1 from '%2'. Seite %1 aus '%2' konnte nicht gelesen werden. Comparing: %1 vs. %2. Vergleich: %1 mit %2. Cancelled. Abgebrochen. %1 vs. %2 %3 %4 For entries in View-ComboBox %1 mit %2 %3 %4 Comparing %1/%2 For Log Vergleiche %1/%2 Completed in %1 seconds. Displayed in the log, but only if comparison takes more than a second. Benötigte Zeit: %1 Sekunden. <font color=brown>Files differ on 1 page (%1 page%2 compared).</font> <font color=brown>Dateien unterscheiden sich auf einer Seite (%1 %2 verglichen).</font> was Seite wurde s were Seiten wurden <font color=brown>Files differ on %1 pages (%2 page%3 compared).</font> <font color=brown>Dateien unterscheiden sich auf %1 Seiten (%2 %3 verglichen).</font> The PDFs appear to be the same. Die PDF-Dateien scheinen gleich zu sein. <p style='font-size: x-large;color: darkgreen'>DiffPDF: The PDFs appear to be the same.</p> <p style='font-size: x-large;color: darkgreen'>DiffPDF: Die PDF-Dateien scheinen gleich zu sein.</p> 1 differs %1/%2 compared For Label at bottom of Controls-Panel. 1 unterschiedliche Seite (%1/%2 verglichen) %1 differ %2/%3 compared For Label at bottom of Controls-Panel. %1 unterschiedliche Seiten (%2/%3 verglichen) %1 differ%2 %3/%4 compared For Label at bottom of Controls-Panel. But what is %2? -> When there is only 1 difference, %2 is set to "s" => This makes no sense in German! %1 Unterschiede%2 - %3/%4 verglichen DiffPDF %1 %2 %1 %3 Appears in the saved pdf file. %1 is a bullet, %2 the filename, %3 is the date DiffPDF %1 %2 %1 %3 DiffPDF %1 %2 vs. %3 %1 %4 No clue what this means or where it apperas. DiffPDF %1 %2 mit %3 %1 %4 Saved %1 Gespeichert unter %1 Failed to save %1 Speichern von %1 fehlgeschlagen OptionsForm DiffPDF — Options DiffPDF — Optionen No Brush Ohne Solid Voll Dense #1 Stärke #1 Dense #2 Stärke #2 Dense #3 Stärke #3 Dense #4 Stärke #4 Dense #5 Stärke #5 Dense #6 Stärke #6 Horizontal Horizontal Vertical Vertikal Cross Kästchen Diagonal / Diagonal / Diagonal \ Diagonal \ Diagonal Cross Rauten No Pen Keine Dashed Striche Dotted Punkte Dash-Dotted Strich-Punkt-Strich Dash-Dot-Dotted Strich-Punkt-Punkt % % <p>How opaque the highlighting color is. The default is 13% <p>Deckungsgrad der Hervorhebungsfarbe. Standard ist 13% px px <p>The size of the highlighting squares in Appearance mode. Small values are more expensive to compute. Large values give coarse comparisons. The default is 10 px <p>Größe der Vergleichsbereiche beim visuellen Vergleich. Kleine Werte sind rechenintensiver. Große Werte bewirken ungenauere Ergebnisse. Der Standard ist 10 px No Rules Keine Randmarker Show &Tooltips in the Main Window Zeige &Hinweise im Hauptfenster Combine Highlighting in &Text Modes &Hervorhebungen beim Textvergleich zusammenfassen MB MB <p>The cache is used to store pages already seen to make flipping back and forth as fast as possible. The bigger the cache the more pages that can be stored. <p>Der Cache hält bereits angezeigte Seiten vor, um den Wechsel zwischen Seiten zu beschleunigen. Bei größerem Cache können mehr Seiten vorgehalten werden. &Rule width: &Randmarker: &General &Allgemein &Base Color: &Basisfarbe: O&utline: &Rahmen: &Fill: &Füllmuster: F&ill Opacity: &Deckkraft: <p>The outline and fill are used to highlight differences using a semi-transparent version of the base color. The margin rules are painted using the base color and indicate where changes are. Set the rule width to 0.0 to switch the rules off. If combining highlighting is checked it will try to merge the highlighting of adjacent text differences. <p>Rahmen und Füllmuster werden verwendet um Unterschiede hervorzuheben. Sie werden in der halbtransparenten Basisfarbe gezeichnet. Die Randmarker zeigen an, wo sich Unterschiede befinden. Sie werden in der Basisfarbe gezeichnet. Um die Randmarker zu deaktivieren kann der Wert auf 0.0 gestellt werden. Wenn "Hervorhebungen beim Textvergleich zusammenschließen" gewählt ist wird versucht nah zusammenliegende Textunterschiede als Einheit hervorzuheben. &Highlighting &Hervorhebung &Square Size: &Genauigkeit: C&ache Size: C&ache-Größe: &Performance &Leistungsoptimierung SaveForm DiffPDF — Save As DiffPDF — Speichern unter Pairs Seiten Current &Page Pair Aktuelle &Seite &All Page Pairs &Alle Seiten Pages Inhalt File #&1's Pages nur links (Datei #&1) File #&2's Pages nur rechts (Datei #&2) &Both Files' Pages &beide Seiten nebeneinander &Filename: &Dateiname: B&rowse... &Durchsuchen... DiffPDF — Browse DiffPDF — Durchsuchen PDF files (*.pdf);;Image files (%1) PDF Dateien (*.pdf);;Bilddateien (%1) diffpdf-2.1.3/diffpdf_es.ts0000644000000000000000000012255512227164102013715 0ustar 00000000000000 UTF-8 AboutForm <table border=0><tr><td width=90%><b>%1</a> %2</b> by Mark Summerfield</td><td rowspan=3><img align=right src=":/icon.png"></td></tr><tr><td><tt>&lt;mark@qtrac.eu&gt;</tt>.</td></tr><tr><td colspan=2>Copyright &copy; 2008-13 <a href="http://www.qtrac.eu">Qtrac</a> Ltd. All rights reserved.</td></tr><tr><td colspan=2>Built with Qt %3 and Poppler %4.</td></tr></table><hr><p>This program compares the text or the visual appearance of each page in two PDF files.<hr><p>If you like %1 you might like my books:<ul><li><a href="http://www.qtrac.eu/gobook.html">Programming in Go</a></li><li><a href="http://www.qtrac.eu/aqpbook.html">Advanced Qt Programming</a></li><li><a href="http://www.qtrac.eu/py3book.html">Programming in Python 3</a></li><li><a href="http://www.qtrac.eu/pyqtbook.html">Rapid GUI Programming with Python and Qt</a></li></ul>I also provide training and consultancy in C++, Go, Python&nbsp;2, Python&nbsp;3, C++/Qt, and PyQt4. <table><tr><td>&bull;</td><td bgcolor=lightyellow><i>Anonymous Company</i> &mdash; funded the addition of the margin exclusion functionality</td></tr><tr><td>&bull;</td><td><b>David Paleino</b> &mdash; Debian packager</td></tr><tr><td>&bull;</td><td><b>Dirk Loss</b> &mdash; creating Mac binaries</td></tr><tr><td>&bull;</td><td>Florian Heiderich &mdash; suggested using composition modes for showing subtle differences</td></tr><tr><td>&bull;</td><td><b>Jasmin Blanchette</b> &mdash; the original idea and subsequent suggestions</td></tr><tr><td>&bull;</td><td>Liviu Andronic &mdash; suggested adding drag and drop</td></tr><tr><td>&bull;</td><td>Paul Howarth &mdash; suggestions resulting in Characters mode</td></tr><tr><td>&bull;</td><td bgcolor="#F0F0F0"><i>Pavel Fric</i> &mdash; Czech translation</td></tr><tr><td>&bull;</td><td bgcolor="#F0F0F0"><i>Pierre-Alain Bandinelli</i>&mdash; French translation</td></tr><tr><td>&bull;</td><td bgcolor="#F0F0F0"><i>Rainer Krachten</i> &mdash; German translation and various suggestions</td></tr><tr><td>&bull;</td><td>Rory Gordon &mdash; suggested adding drag and drop</td></tr><tr><td>&bull;</td><td><b>Steven Lee</b> &mdash; creating Windows binaries</td></tr></table> This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 2 of the License, or (at your option), any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License (in file <tt>gpl-2.0.txt</tt>) for more details. &About &Contributors &License %1 — About HelpForm %1 — Help MainWindow DiffPDF File #&1... <p>Choose the first (left hand) file to be compared. The first (left hand) file. File #&2... <p>Choose the second (right hand) file to be compared. The second (right hand) file. Pa&ges: <p>Pages can be specified using ranges such as 1-10, and multiple ranges can be used, e.g., 1-10, 12-15, 20, 22, 35-39. This makes it straighforward to compare similar documents where one has one or more additional pages.<p>For example, if file1.pdf has pages 1-30 and file2.pdf has pages 1-31 with the extra page being page 14, the two page ranges would be set to 1-30 for file1.pdf and 1-13, 15-31 for file2.pdf. &Pages: &Compare <p>Click to compare (or re-compare) the documents&mdash;or to cancel a comparison that's in progress. Appearance Characters Words <p>If the <b>Words</b> comparison mode is chosen, then each page's text is compared word by word (best for alphabetic languages like English). If the <b>Characters</b> comparison mode is chosen, then each page's text is compared character by character (best for logographic languages like Chinese and Japanese). If the <b>Appearance</b> comparison mode is chosen then each page's visual appearance is compared. Comparing appearance can be slow for large documents and can also produce false positives&mdash;but is absolutely precise. Co&mpare: &View: <p>Shows each pair of pages which are different. The comparison is textual unless the <b>Appearance</b> comparison mode is chosen, in which case the comparison is done visually. Visual differences can occur if a paragraph is formated differently or if an embedded diagram or image has changed. (Not viewing) S&how: <p>In show <b>Highlighting</b> mode the pages are shown side by side with their differences highlighted. All the other modes are composition modes which show the first PDF as-is and the composition (blend) of the two PDFs. %1Highlighting%2 Not Src Xor Dest Difference Exclusion Src Xor Dest Previo&us Ne&xt &Zoom: <p>Determines the scale at which the pages are shown. % Zo&ning <p>Zoning is a computationally expensive experimental mode that can reduce or eliminate false positives particularly for pages that have tables or that mix alphabetic and logographic languages&mdash;it can also increase false positives! Zoning only applies to text comparisons. Co&lumns: <p>Use this to tell DiffPDF how many columns the page has; this should improve the zoning. Tolerance/&R: <p>This is the maximum distance between text (word) rectangles for the rectangles to appear in the same zone. Tolerance/&Y: <p>Text position <i>y</i> coordinates are rounded to the nearest Tolerance/Y value when zoning. Sho&w Zones <p>This shows the zones that are being used and may be helpful when adjusting tolerances. (Its original purpose was for debugging.) &Exclude Margins <p>If this is checked, anything outside non-zero margins is ignored when comparing. &Top: <p>The top margin in points. Anything above this will be ignored. &Bottom: <p>The bottom margin in points. Anything below this will be ignored. Le&ft: <p>The left margin in points. Anything left of this will be ignored. R&ight: <p>The right margin in points. Anything right of this will be ignored. Choose files... &Options... Click to customize the application. &Save As... Save the differences. Help F1 Click for basic help. &About Click for copyright and credits. &Quit Click to terminate the application. <p>Shows the first (left hand) document's page that corresponds to the page shown in the View Difference combobox. <p>Shows the second (right hand) document's page that corresponds to the page shown in the View Difference combobox. Controls Actions Margins Zoning Log DiffPDF — Controls DiffPDF — Actions DiffPDF — Zoning DiffPDF — Margins DiffPDF — Log DiffPDF: False Positive DiffPDF — Choose File #1 PDF files (*.pdf) DiffPDF — Error Cannot compare a file to itself. <p style='font-size: xx-large;color: darkgreen'>DiffPDF: Click Compare<br>or change File #2.</p> <p style='font-size: xx-large;color: darkgreen'>DiffPDF: Choose File #2.</p> 1-%1 Choose second file Ready to compare DiffPDF — Choose File #2 <p style='font-size: xx-large;color: darkgreen'>DiffPDF: Click Compare<br>or change File #1.</p> <p style='font-size: xx-large;color: darkgreen'>DiffPDF: Choose File #1.</p> Choose first file Cannot load '%1'. Cannot read a locked PDF ('%1'). <b>%1</b> %1: %2. Created: %1, last modified %2. Created: %1. Page count: %1. Page size: %1pt x %2pt (%3mm x %4mm). <font color=red>%1</font> Failed to understand page range '%1'. &Cancel Ready Failed to read page %1 from '%2'. Comparing: %1 vs. %2. Cancelled. %1 vs. %2 %3 %4 Comparing %1/%2 Completed in %1 seconds. <font color=brown>Files differ on 1 page (%1 page%2 compared).</font> was s were <font color=brown>Files differ on %1 pages (%2 page%3 compared).</font> The PDFs appear to be the same. <p style='font-size: x-large;color: darkgreen'>DiffPDF: The PDFs appear to be the same.</p> 1 differs %1/%2 compared %1 differ %2/%3 compared DiffPDF %1 %2 %1 %3 DiffPDF %1 %2 vs. %3 %1 %4 Saved %1 Failed to save %1 OptionsForm DiffPDF — Options No Brush Solid Dense #1 Dense #2 Dense #3 Dense #4 Dense #5 Dense #6 Horizontal Vertical Cross Diagonal / Diagonal \ Diagonal Cross No Pen Dashed Dotted Dash-Dotted Dash-Dot-Dotted % <p>How opaque the highlighting color is. The default is 13% px <p>The size of the highlighting squares in Appearance mode. Small values are more expensive to compute. Large values give coarse comparisons. The default is 10 px No Rules Show &Tooltips in the Main Window Combine Highlighting in &Text Modes MB <p>The cache is used to store pages already seen to make flipping back and forth as fast as possible. The bigger the cache the more pages that can be stored. &Rule width: &General &Base Color: O&utline: &Fill: F&ill Opacity: <p>The outline and fill are used to highlight differences using a semi-transparent version of the base color. The margin rules are painted using the base color and indicate where changes are. Set the rule width to 0.0 to switch the rules off. If combining highlighting is checked it will try to merge the highlighting of adjacent text differences. &Highlighting &Square Size: C&ache Size: &Performance SaveForm DiffPDF — Save As Pairs Current &Page Pair &All Page Pairs Pages File #&1's Pages File #&2's Pages &Both Files' Pages &Filename: B&rowse... DiffPDF — Browse PDF files (*.pdf);;Image files (%1) diffpdf-2.1.3/diffpdf_fr.ts0000644000000000000000000012706312227164102013714 0ustar 00000000000000 UTF-8 AboutForm <table border=0><tr><td width=90%><b>%1</a> %2</b> by Mark Summerfield</td><td rowspan=3><img align=right src=":/icon.png"></td></tr><tr><td><tt>&lt;mark@qtrac.eu&gt;</tt>.</td></tr><tr><td colspan=2>Copyright &copy; 2008-13 <a href="http://www.qtrac.eu">Qtrac</a> Ltd. All rights reserved.</td></tr><tr><td colspan=2>Built with Qt %3 and Poppler %4.</td></tr></table><hr><p>This program compares the text or the visual appearance of each page in two PDF files.<hr><p>If you like %1 you might like my books:<ul><li><a href="http://www.qtrac.eu/gobook.html">Programming in Go</a></li><li><a href="http://www.qtrac.eu/aqpbook.html">Advanced Qt Programming</a></li><li><a href="http://www.qtrac.eu/py3book.html">Programming in Python 3</a></li><li><a href="http://www.qtrac.eu/pyqtbook.html">Rapid GUI Programming with Python and Qt</a></li></ul>I also provide training and consultancy in C++, Go, Python&nbsp;2, Python&nbsp;3, C++/Qt, and PyQt4. <table border=0><tr><td width=90%><b>%1</a> %2</b> par Marc Summerfield</td><td rowspan=3><img align=right src=":/icon.png"></td></tr><tr><td><tt>&lt;mark@qtrac.eu&gt;</tt>.</td></tr><tr><td colspan=2>Copyright &copy; 2008-13 <a href="http://www.qtrac.eu">Qtrac</a> Ltd. Tous droits réservés.</td></tr><tr><td colspan=2>Construit avec Qt %3 et Poppler %4.</td></tr></table><hr><p>Ce programme compare page à page le texte ou l'apparence visuelle de deux fichiers PDF.<hr><p>Si vous appréciez %1 vous pourriez également apprécier mes livres:<ul><li><a href="http://www.qtrac.eu/gobook.html">Programming in Go</a></li><li><a href="http://www.qtrac.eu/aqpbook.html">Advanced Qt Programming</a></li><li><a href="http://www.qtrac.eu/py3book.html">Programming in Python 3</a></li><li><a href="http://www.qtrac.eu/pyqtbook.html">Rapid GUI Programming with Python and Qt</a></li></ul>J'organise également des formations et propose des prestations de conseil en C++, Go, Python&nbsp;2, Python&nbsp;3, C++/Qt, and PyQt4. <table><tr><td>&bull;</td><td bgcolor=lightyellow><i>Anonymous Company</i> &mdash; funded the addition of the margin exclusion functionality</td></tr><tr><td>&bull;</td><td><b>David Paleino</b> &mdash; Debian packager</td></tr><tr><td>&bull;</td><td><b>Dirk Loss</b> &mdash; creating Mac binaries</td></tr><tr><td>&bull;</td><td>Florian Heiderich &mdash; suggested using composition modes for showing subtle differences</td></tr><tr><td>&bull;</td><td><b>Jasmin Blanchette</b> &mdash; the original idea and subsequent suggestions</td></tr><tr><td>&bull;</td><td>Liviu Andronic &mdash; suggested adding drag and drop</td></tr><tr><td>&bull;</td><td>Paul Howarth &mdash; suggestions resulting in Characters mode</td></tr><tr><td>&bull;</td><td bgcolor="#F0F0F0"><i>Pavel Fric</i> &mdash; Czech translation</td></tr><tr><td>&bull;</td><td bgcolor="#F0F0F0"><i>Pierre-Alain</i> Bandinelli&mdash; French translation</td></tr><tr><td>&bull;</td><td bgcolor="#F0F0F0"><i>Rainer Krachten</i> &mdash; German translation and various suggestions</td></tr><tr><td>&bull;</td><td>Rory Gordon &mdash; suggested adding drag and drop</td></tr><tr><td>&bull;</td><td><b>Steven Lee</b> &mdash; creating Windows binaries</td></tr></table> <table><tr><td>&bull;</td><td bgcolor=lightyellow><i>Anonymous Company</i> &mdash; a financé l'addition de la fonctionalité d'exclusion des marges</td></tr><tr><td>&bull;</td><td><b>David Paleino</b> &mdash; s'occupe des paquets pour Debian</td></tr><tr><td>&bull;</td><td><b>Dirk Loss</b> &mdash; s'occupe des exécutables pour Mac</td></tr><tr><td>&bull;</td><td>Florian Heiderich &mdash; a suggéré d'utiliser les modes 'composition' pour mettre en évidence des différences subtiles</td></tr><tr><td>&bull;</td><td><b>Jasmin Blanchette</b> &mdash; a proposé l'idée orignale et les suggestions qui ont suivies</td></tr><tr><td>&bull;</td><td>Liviu Andronic &mdash; a suggéré d'ajouter le glisser/déposer</td></tr><tr><td>&bull;</td><td>Paul Howarth &mdash; a fait suggestions qui ont permis de mettre en place le mode 'caractères'</td></tr><tr><td>&bull;</td><td bgcolor="#F0F0F0"><i>Pavel Fric</i> &mdash; traduction en Tchèque</td></tr><tr><td>&bull;</td><td bgcolor="#F0F0F0">Pierre-Alain Bandinelli&mdash; traduction en Français</td></tr><tr><td>&bull;</td><td bgcolor="#F0F0F0"><i>Rainer Krachten</i> &mdash; traduction en allemand et multiples suggestions</td></tr><tr><td>&bull;</td><td>Rory Gordon &mdash; a suggéré d'ajouter le glisser/déposer</td></tr><tr><td>&bull;</td><td><b>Steven Lee</b> &mdash; s'occupe des binaires pour Windows</td></tr></table> This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 2 of the License, or (at your option), any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License (in file <tt>gpl-2.0.txt</tt>) for more details. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 2 of the License, or (at your option), any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License (in file <tt>gpl-2.0.txt</tt>) for more details. &About &A propos &Contributors &Contributeurs &License &Licence %1 ? About %1 — A propos <table><tr><td>&bull;</td><td bgcolor=lightyellow><i>Anonymous Company</i> &mdash; funded the addition of the margin exclusion functionality</td></tr><tr><td>&bull;</td><td><b>David Paleino</b> &mdash; Debian packager</td></tr><tr><td>&bull;</td><td><b>Dirk Loss</b> &mdash; creating Mac binaries</td></tr><tr><td>&bull;</td><td>Florian Heiderich &mdash; suggested using composition modes for showing subtle differences</td></tr><tr><td>&bull;</td><td><b>Jasmin Blanchette</b> &mdash; the original idea and subsequent suggestions</td></tr><tr><td>&bull;</td><td>Liviu Andronic &mdash; suggested adding drag and drop</td></tr><tr><td>&bull;</td><td>Paul Howarth &mdash; suggestions resulting in Characters mode</td></tr><tr><td>&bull;</td><td bgcolor="#F0F0F0"><i>Pavel Fric</i> &mdash; Czech translation</td></tr><tr><td>&bull;</td><td bgcolor="#F0F0F0"><i>Pierre-Alain Bandinelli</i>&mdash; French translation</td></tr><tr><td>&bull;</td><td bgcolor="#F0F0F0"><i>Rainer Krachten</i> &mdash; German translation and various suggestions</td></tr><tr><td>&bull;</td><td>Rory Gordon &mdash; suggested adding drag and drop</td></tr><tr><td>&bull;</td><td><b>Steven Lee</b> &mdash; creating Windows binaries</td></tr></table> %1 — About HelpForm Escape Quitter %1 ? Help %1 — Aide %1 — Help MainWindow DiffPDF DiffPDF File #&1... Fichier #&1... <p>Choose the first (left hand) file to be compared. <p>Choisissez le premier fichier (volet de gauche) à comparer. The first (left hand) file. Le premier fichier (volet de gauche). File #&2... Fichier #&2... <p>Choose the second (right hand) file to be compared. <p>Choisissez le second fichier (volet de droite) à comparer. The second (right hand) file. Le second fichier (volet de droite). Pa&ges: Pa&ges : <p>Pages can be specified using ranges such as 1-10, and multiple ranges can be used, e.g., 1-10, 12-15, 20, 22, 35-39. This makes it straighforward to compare similar documents where one has one or more additional pages.<p>For example, if file1.pdf has pages 1-30 and file2.pdf has pages 1-31 with the extra page being page 14, the two page ranges would be set to 1-30 for file1.pdf and 1-13, 15-31 for file2.pdf. <p>Les numéros de pages peuvent être spécifiés à l'aide d'intervalles simples (ex. 1-10), et à l'aide d'intervalles multiples, par ex. 1-10, 12-15, 20, 22, 35-39. Cela permet de comparer aisément des documents similaires quand l'un d'eux possède une ou plusieurs pages supplémentaires. <p>Par exemple, si le fichier fichier1.pdf comporte les pages 1-30 et fichier2.pdf comporte 31 pages, la page 14 étant une page ajoutée dans le deuxième fichier, alors il sera possible d'utiliser les intervalles suivants : pour fichier1.pdf, on utilisera l'intervalle 1-30 tandis que pour fichier2.pdf on indiquera les intervalles 1-13, 15-31 afin d'exclure la page 14 de la comparaison. &Pages: &Pages : &Compare &Comparer <p>Click to compare (or re-compare) the documents&mdash;or to cancel a comparison that's in progress. <p>Cliquez pour comparer (ou re-comparer) les documents&mdash;ou pour annuler la comparaison en cours. Appearance Apparence Characters Caractères Words Mots <p>If the <b>Words</b> comparison mode is chosen, then each page's text is compared word by word (best for alphabetic languages like English). If the <b>Characters</b> comparison mode is chosen, then each page's text is compared character by character (best for logographic languages like Chinese and Japanese). If the <b>Appearance</b> comparison mode is chosen then each page's visual appearance is compared. Comparing appearance can be slow for large documents and can also produce false positives&mdash;but is absolutely precise. <p>Si le mode de comparaison par <b>Mots</b> est choisi, alors le texte de chaque page est comparé mot à mot (idéal pour des langages alphabétiques comme l'anglais ou le français). Si le mode de comparaison par <b>Caractères</b> est choisi, alors le texte de chaque page est comparé caractère par caractère (idéal pour les langages à idéogrammes comme le chinois ou le japonais). Si le mode de comparaison <b>Apparence</b> est sélectionné, alors l'apparence visuelle de chaque page est utilisée pour la comparaison. Le mode comparaison peut être lent pour des documents de grande taille and peut aussi conduire à des faux positifs&mdash;mais il est également très précis. Co&mpare: Co&mparer : &View: &Affichage : <p>Shows each pair of pages which are different. The comparison is textual unless the <b>Appearance</b> comparison mode is chosen, in which case the comparison is done visually. Visual differences can occur if a paragraph is formated differently or if an embedded diagram or image has changed. <p>Affiche chaque couple de pages qui présentent des différences. La comparaison est textuelle sauf si le mode de comparaison <b>Apparence</b> est choisi ; dans ce cas la comparaison est visuelle. Des différences visuelles peuvent être détectées si un paragraphe présente une mise en page différente ou bien si un diagramme ou une image insérés sont différents. (Not viewing) (Pas d'affichage) S&how: A&fficher : <p>In show <b>Highlighting</b> mode the pages are shown side by side with their differences highlighted. All the other modes are composition modes which show the first PDF as-is and the composition (blend) of the two PDFs. <p>Si l'affichage <b>Surlignage</b> est sélectionné, les pages sont affichées côte à côte et les différences sont mises en évidence par un surlignage de couleur. Tous les autres modes d'affichage correspondent à des compositions qui présentent le premier PDF tel quel et une composition (fusion) des deux PDFs. %1Highlighting%2 %1Surlignage%2 Not Src Xor Dest Not Src Xor Dest Difference Différence Exclusion Exclusion Src Xor Dest Src Xor Dest Previo&us Précé&dent Ne&xt Sui&vant &Zoom: &Zoom : <p>Determines the scale at which the pages are shown. <p>Détermine l'échelle à laquelle les pages sont affichées. % % Zo&ning Découpage par zo&nes <p>Zoning is a computationally expensive experimental mode that can reduce or eliminate false positives particularly for pages that have tables or that mix alphabetic and logographic languages&mdash;it can also increase false positives! Zoning only applies to text comparisons. <p>Le découpage par zones est un mode expérimental, coûteux en opérations, permettant de réduire ou éliminer les faux positifs, particulièrementr dans les pages qui comportent des tableaux ou mélangent des langues alphabétiques et à idéogramme&mdash;mais comme rien n'est parfait, il peut aussi augmenter le nombre de faux positifs. Co&lumns: Co&lonnes : <p>Use this to tell DiffPDF how many columns the page has; this should improve the zoning. <p>Indique à DiffPDF combien de colonnes sont visibles sur la page ; cela améliore le découpage par zones. Tolerance/&R: Tolérance/&R : <p>This is the maximum distance between text (word) rectangles for the rectangles to appear in the same zone. <p>Il s'agit de la distance maxixmale entre des rectangles de texte (mots) inclus dans la même zone. Tolerance/&Y: Tolérance/&Y : <p>Text position <i>y</i> coordinates are rounded to the nearest Tolerance/Y value when zoning. <p>Les coordonnées de position en <i>y</i> du texte sont arrondies à la plus proche valeur de Tolérance/Y lors le découpage par zone est activé. Sho&w Zones Afficher les z&ones <p>This shows the zones that are being used and may be helpful when adjusting tolerances. (Its original purpose was for debugging.) <p>Affiche les zones utilisées ce qui peut s'avérer utile pour ajuster les tolérances (à l'origine, cette option a permis le débogage.) &Exclude Margins &Exclure les marges <p>If this is checked, anything outside non-zero margins is ignored when comparing. <p>Quand la case est cochée, tout élément en-dehors des marges sera ignoré lors des comparaisons. &Top: Hau&t : <p>The top margin in points. Anything above this will be ignored. <p>La marge en haut en points. Tout élément en haut de cette limite sera ignoré. &Bottom: &Bas : <p>The bottom margin in points. Anything below this will be ignored. <p>La marge en bas en points. Tout élément en bas de cette limite sera ignoré. Le&ft: Gauc&he : <p>The left margin in points. Anything left of this will be ignored. <p>La marge à gauche en points. Tout élément à gauche de cette limite sera ignoré. R&ight: Dro&ite : <p>The right margin in points. Anything right of this will be ignored. <p>La marge à droite en points. Tout élément à droite de cette limite sera ignoré. Choose files... Choisir des fichiers... &Options... &Options... Click to customize the application. Cliquez pour paramétrer l'application. &Save As... Enregistrer &sous... Save the differences. Enregistrer les différences. Help Aide F1 F1 Click for basic help. Cliquez pour obtenir une aide de base. &About &A propos Click for copyright and credits. Cliquez pour afficher les crédits et copyright. &Quit &Quitter Click to terminate the application. Cliquez pour stopper l'application. <p>Shows the first (left hand) document's page that corresponds to the page shown in the View Difference combobox. <p>Affiche la page du premier document (volet de gauche) qui comporte des différences. <p>Shows the second (right hand) document's page that corresponds to the page shown in the View Difference combobox. <p>Affiche la page du second document (volet de droite) qui comporte des différences. Controls Contrôles Actions Actions Margins Marges Zoning Découpage par zones Log Messages DiffPDF ? Controls DiffPDF — Contrôles DiffPDF ? Actions DiffPDF — Actions DiffPDF ? Zoning DiffPDF — Découpage par zones DiffPDF ? Margins DiffPDF — Marges DiffPDF ? Log DiffPDF — Messages DiffPDF: False Positive DiffPDF : Faux positif DiffPDF ? Choose File #1 DiffPDF — Choisir fichier #1 PDF files (*.pdf) Fichiers PDF (*.pdf) DiffPDF ? Error DiffPDF — Erreur Cannot compare a file to itself. Il n'est pas possible de comparer un fichier à lui-même. <p style='font-size: xx-large;color: darkgreen'>DiffPDF: Click Compare<br>or change File #2.</p> <p style='font-size: xx-large;color: darkgreen'>DiffPDF: Cliquez sur Comparer<br> ou changez le fichier #2.</p> <p style='font-size: xx-large;color: darkgreen'>DiffPDF: Choose File #2.</p> <p style='font-size: xx-large;color: darkgreen'>DiffPDF : Choisissez le fichier #2.</p> 1-%1 1-%1 Choose second file Choisissez un second fichier Ready to compare Prêt à comparer DiffPDF ? Choose File #2 DiffPDF — Choisissez fichier #2 <p style='font-size: xx-large;color: darkgreen'>DiffPDF: Click Compare<br>or change File #1.</p> <p style='font-size: xx-large;color: darkgreen'>DiffPDF : Cliquez sur Comparer<br>ou modifiez le fichier #1.</p> <p style='font-size: xx-large;color: darkgreen'>DiffPDF: Choose File #1.</p> <p style='font-size: xx-large;color: darkgreen'>DiffPDF : Choisissez fichier #1.</p> Choose first file Choisissez le premier fichier Cannot load '%1'. Impossible de charger '%1'. Cannot read a locked PDF ('%1'). Impossible de lire un PDF verrouillé ('%1'). <b>%1</b> <b>%1</b> %1: %2. %1 : %2. Created: %1, last modified %2. Créé : %1, dernière modification %2. Created: %1. Créé : %1. Page count: %1. Nombre de pages : %1. Page size: %1pt x %2pt (%3mm x %4mm). Taille de la page : %1pt x %2pt (%3mm x %4mm). <font color=red>%1</font> <font color=red>%1</font> Failed to understand page range '%1'. Impossible de comprendre l'intervalle de pages '%1'. &Cancel Ann&uler Ready Prêt Failed to read page %1 from '%2'. Impossible de lire la page %1 dans '%2'. Comparing: %1 vs. %2. Comparaison en cours : %1 vs. %2. Cancelled. Annulé. %1 vs. %2 %3 %4 %1 vs. %2 %3 %4 Comparing %1/%2 En train de comparer %1/%2 Completed in %1 seconds. Opération terminée en %1 secondes. <font color=brown>Files differ on 1 page (%1 page%2 compared).</font> <font color=brown>Les fichiers présentent des différences sur 1 page (%1 page%2 comparée%2).</font> was était s were s étaient <font color=brown>Files differ on %1 pages (%2 page%3 compared).</font> <font color=brown>Les fichiers présentent des différences sur %1 pages (%2 page%3 comparée%3).</font> The PDFs appear to be the same. Les fichiers PDFs semblent identiques. <p style='font-size: x-large;color: darkgreen'>DiffPDF: The PDFs appear to be the same.</p> <p style='font-size: x-large;color: dargreen'>DiffPDF : les fichiers PDFs semblent être identiques.</p> 1 differs %1/%2 compared 1 diffère %1/%2 comparés %1 differ %2/%3 compared %1 diffèrent %2/%3 comparés %1 differ%2 %3/%4 compared %1 diffère de %2 %3/%4 ont été comparées DiffPDF %1 %2 %1 %3 DiffPDF %1 %2 %1 %3 DiffPDF %1 %2 vs. %3 %1 %4 DiffPDF %1 %2 vs. %3 %1 %4 Saved %1 Fichier %1 enregistré Failed to save %1 Echec dans l'enregistrement %1 DiffPDF — Controls DiffPDF — Actions DiffPDF — Zoning DiffPDF — Margins DiffPDF — Log DiffPDF — Choose File #1 DiffPDF — Error DiffPDF — Choose File #2 OptionsForm DiffPDF ? Options DiffPDF — Options No Brush Pas de brosse Solid Continu Dense #1 Dense #1 Dense #2 Dense #2 Dense #3 Dense #3 Dense #4 Dense #4 Dense #5 Dense #5 Dense #6 Dense #6 Horizontal Hachures horizontales Vertical Hachures verticales Cross Quadrillage Diagonal / Hachures diagnoales / Diagonal \ Hachures diagonales \ Diagonal Cross Quadrillage diagonal No Pen Pas de trait Dashed Trait discontinu Dotted Pointillés Dash-Dotted Trait - Point Dash-Dot-Dotted Trait - point - point % % <p>How opaque the highlighting color is. The default is 13% <p>Mesure de l'opacité de la couleur de surlignage. Par défaut, la valeur est 13% px px <p>The size of the highlighting squares in Appearance mode. Small values are more expensive to compute. Large values give coarse comparisons. The default is 10 px <p>La taille des carrés de surligange en mode Apparence. Les petites valeurs sont plus coûteuses à traiter. Les valeurs plus grandes réduisent la précision des comparaisons. La valeur par défaut est 10px No Rules Pas de règles Show &Tooltips in the Main Window Afficher &les infobulles dans la fenêtre principale Combine Highlighting in &Text Modes Combiner les surlignages adjacents dans les modes &Textes MB MO <p>The cache is used to store pages already seen to make flipping back and forth as fast as possible. The bigger the cache the more pages that can be stored. <p>Le cache est utilisé pour stocker les pages déjà parcourues afin d'accélérer autant que possible la transition d'une page à l'autre. Plus le cache est important, plus le nombre de pages conservées en mémoire peut être grand. &Rule width: Largeur de la &règle : &General &General &Base Color: Couleur de &base : O&utline: Conto&ur : &Fill: R&emplissage : F&ill Opacity: Opacité du rempl&issage : <p>The outline and fill are used to highlight differences using a semi-transparent version of the base color. The margin rules are painted using the base color and indicate where changes are. Set the rule width to 0.0 to switch the rules off. If combining highlighting is checked it will try to merge the highlighting of adjacent text differences. <p>Le contour et le remplissage sont utilisés pour mettre en évidence des différences en utilisant une version semi-transparente de la couleur de base. Les règles des marges sont peintes avec la couleur de base(sp)(sp)et indiquent l'emplacement des changements. Choisissez une largeur des règles de 0.0 pour désactiver les règles. Si l'option 'Combiner les surlignages adjacents' est sélectionnée, DiffPDF essayera de fusionner les surlignages correspondant à des différences textuelles adjacentes. &Highlighting Surl&ignage &Square Size: Taille du &Carré : C&ache Size: Taille du c&ache : &Performance &Performance DiffPDF — Options SaveForm DiffPDF ? Save As DiffPDF — Enregistrer sous Pairs Couples Current &Page Pair Couple de &page courant &All Page Pairs Tous les couples de p&ages Pages Pages File #&1's Pages Pages du fichier #&1 File #&2's Pages Pages du fichier #&2 &Both Files' Pages &Les pages des 2 fichiers &Filename: Nom de &fichier : B&rowse... Pa&rcourir... DiffPDF ? Browse DiffPDF — Parcourir PDF files (*.pdf);;Image files (%1) Fichiers PDF (*.pdf);;Fichiers images (%1) DiffPDF — Save As DiffPDF — Browse diffpdf-2.1.3/generic.cpp0000644000000000000000000001313412227164102013364 0ustar 00000000000000/* Copyright © 2008-13 Qtrac Ltd. All rights reserved. This program or module is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. */ #include "generic.hpp" #include #include #include #include #include #include const QSize SwatchSize(24, 24); void scaleRect(int dpi, QRectF *rect) { if (dpi == POINTS_PER_INCH) return; qreal x1; qreal y1; qreal x2; qreal y2; rect->getCoords(&x1, &y1, &x2, &y2); qreal factor = dpi / static_cast(POINTS_PER_INCH); x1 *= factor; y1 *= factor; x2 *= factor; y2 *= factor; rect->setCoords(x1, y1, x2, y2); } int pointValueForPixelOffset(const double dpi, int px) { const double inches = px / dpi; return qRound(inches * POINTS_PER_INCH); } int pixelOffsetForPointValue(const double dpi, int pt) { const double inches = pt / static_cast(POINTS_PER_INCH); return qRound(inches * dpi); } QRectF rectForMargins(const int width, const int height, const int top, const int bottom, const int left, const int right) { return QRectF(QPointF(left, top), QPointF(width - right, height - bottom)); } Ranges unorderedRange(int end, int start) { Q_ASSERT(end >= start); Ranges ranges; while (start < end) ranges.insert(start++); return ranges; } QPixmap colorSwatch(const QColor &color) { QString key = QString("COLORSWATCH:%1").arg(color.name()); QPixmap pixmap(SwatchSize); #if QT_VERSION >= 0x040600 if (!QPixmapCache::find(key, &pixmap)) { #else if (!QPixmapCache::find(key, pixmap)) { #endif pixmap.fill(Qt::transparent); { QPainter painter(&pixmap); painter.setRenderHints(QPainter::Antialiasing); painter.setPen(Qt::NoPen); painter.setBrush(color); painter.drawEllipse(0, 0, SwatchSize.width(), SwatchSize.height()); } QPixmapCache::insert(key, pixmap); } return pixmap; } QPixmap brushSwatch(const Qt::BrushStyle style, const QColor &color) { QString key = QString("BRUSHSTYLESWATCH:%1:%2:%3") .arg(static_cast(style)).arg(color.name()).arg(color.alpha()); QPixmap pixmap(SwatchSize); #if QT_VERSION >= 0x040600 if (!QPixmapCache::find(key, &pixmap)) { #else if (!QPixmapCache::find(key, pixmap)) { #endif pixmap.fill(Qt::transparent); { QPainter painter(&pixmap); painter.setRenderHint(QPainter::Antialiasing); painter.setPen(Qt::NoPen); painter.setBrush(QBrush(color, style)); painter.drawRect(0, 0, SwatchSize.width(), SwatchSize.height()); } QPixmapCache::insert(key, pixmap); } return pixmap; } QPixmap penStyleSwatch(const Qt::PenStyle style, const QColor &color) { QString key = QString("PENSTYLESWATCH:%1:%2") .arg(static_cast(style)).arg(color.name()); QPixmap pixmap(SwatchSize); #if QT_VERSION >= 0x040600 if (!QPixmapCache::find(key, &pixmap)) { #else if (!QPixmapCache::find(key, pixmap)) { #endif pixmap.fill(Qt::transparent); { QPainter painter(&pixmap); QPen pen(style); pen.setColor(color); pen.setWidth(2); painter.setPen(pen); const int Y = SwatchSize.height() / 2; painter.drawLine(0, Y, SwatchSize.width(), Y); } QPixmapCache::insert(key, pixmap); } return pixmap; } const TextBoxList getTextBoxes(PdfPage page, const QRectF &rect) { TextBoxList boxes; foreach (Poppler::TextBox *box, page->textList()) { PdfTextBox box_ptr(box); if (rect.isEmpty() || rect.contains(box_ptr->boundingBox())) boxes.append(box_ptr); } return boxes; } const QString strippedFilename(const QString &filename) { const QString FilePrefix("file://"); QString filename_ = filename; if (filename_.startsWith(FilePrefix)) filename_ = filename_.mid(FilePrefix.length()); #ifdef Q_WS_WIN if (filename_.startsWith("/")) filename_ = filename_.mid(1); #endif return filename_.trimmed(); } const QStringList droppedFilenames(const QMimeData *mimeData) { QStringList filenames; QString text = mimeData->text(); if (!text.isEmpty()) { filenames = text.split("\n"); for (int i = 0; i < filenames.count(); ++i) filenames[i] = strippedFilename(filenames.at(i)); } else { foreach (const QUrl &url, mimeData->urls()) filenames << strippedFilename(url.toString()); } return filenames; } // Returns a copy of pageRect reduced if necessary to have the same // aspect ratio as pixmapSize. const QRect resizeRect(const QRect &pageRect, const QSize &pixmapSize) { double ratio = pixmapSize.width() / static_cast(pixmapSize.height()); double height = pageRect.height(); double width = ratio * height; if (width > pageRect.width()) { width = pageRect.width(); height = width / ratio; } QRect rect(pageRect); rect.setWidth(width); rect.setHeight(height); return rect; } diffpdf-2.1.3/generic.hpp0000644000000000000000000000632112227164102013371 0ustar 00000000000000#ifndef GENERIC_HPP #define GENERIC_HPP /* Copyright © 2008-13 Qtrac Ltd. All rights reserved. This program or module is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. */ #include #include #include #include #include class QColor; class QMimeData; class QRectF; #if QT_VERSION >= 0x040600 typedef QSharedPointer PdfDocument; typedef QSharedPointer PdfPage; typedef QSharedPointer PdfTextBox; #else typedef std::tr1::shared_ptr PdfDocument; typedef std::tr1::shared_ptr PdfPage; typedef std::tr1::shared_ptr PdfTextBox; #endif typedef QList TextBoxList; enum InitialComparisonMode{CompareAppearance=0, CompareCharacters=1, CompareWords=2}; enum Debug{DebugOff, DebugShowTexts, DebugShowTextsAndYX}; const int POINTS_PER_INCH = 72; typedef QSet Ranges; typedef QPair RangesPair; struct PagePair { PagePair(int l=-1, int r=-1, bool v=false) : left(l), right(r), hasVisualDifference(v) {} bool isNull() { return left == -1 || right == -1; } const int left; const int right; const bool hasVisualDifference; }; Q_DECLARE_METATYPE(PagePair) inline const QChar canonicalizedCharacter(const QChar &in) { QChar out = in; const ushort c = in.unicode(); switch (c) { case 0x93: out = QChar(0x201C); break; // “ case 0x94: out = QChar(0x201D); break; // ” case 0xAD: // fallthrough (soft-hyphen) case 0x2D: // fallthrough (hyphen-minus) case 0x2010: // fallthrough (hyphen) case 0x2011: // fallthrough (non-breaking hyphen) case 0x2043: out = '-'; break; // (hyphen-bullet) } return out; } void scaleRect(int dpi, QRectF *rect); int pointValueForPixelOffset(const double dpi, int px); int pixelOffsetForPointValue(const double dpi, int pt); QRectF rectForMargins(const int width, const int height, const int top, const int bottom, const int left, const int right); Ranges unorderedRange(int end, int start=0); QPixmap colorSwatch(const QColor &color); QPixmap brushSwatch(const Qt::BrushStyle style, const QColor &color); QPixmap penStyleSwatch(const Qt::PenStyle style, const QColor &color); const TextBoxList getTextBoxes(PdfPage page, const QRectF &rect=QRect()); const QString strippedFilename(const QString &filename); const QStringList droppedFilenames(const QMimeData *mimeData); const QRect resizeRect(const QRect &pageRect, const QSize &pixmapSize); /* // Not needed const int roundedToNearest(const int x, const int multiple) { Q_ASSERT(multiple) const int remainder = x % multiple; return (remainder == 0) ? x : x + multiple - remainder; } */ #endif // GENERIC_HPP diffpdf-2.1.3/gpl-2.0.txt0000644000000000000000000004310312227164102013063 0ustar 00000000000000 GNU GENERAL PUBLIC LICENSE Version 2, June 1991 Copyright (C) 1989, 1991 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This General Public License applies to most of the Free Software Foundation's software and to any other program whose authors commit to using it. (Some other Free Software Foundation software is covered by the GNU Lesser General Public License instead.) You can apply it to your programs, too. When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs; and that you know you can do these things. To protect your rights, we need to make restrictions that forbid anyone to deny you these rights or to ask you to surrender the rights. These restrictions translate to certain responsibilities for you if you distribute copies of the software, or if you modify it. For example, if you distribute copies of such a program, whether gratis or for a fee, you must give the recipients all the rights that you have. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. We protect your rights with two steps: (1) copyright the software, and (2) offer you this license which gives you legal permission to copy, distribute and/or modify the software. Also, for each author's protection and ours, we want to make certain that everyone understands that there is no warranty for this free software. If the software is modified by someone else and passed on, we want its recipients to know that what they have is not the original, so that any problems introduced by others will not reflect on the original authors' reputations. Finally, any free program is threatened constantly by software patents. We wish to avoid the danger that redistributors of a free program will individually obtain patent licenses, in effect making the program proprietary. To prevent this, we have made it clear that any patent must be licensed for everyone's free use or not licensed at all. The precise terms and conditions for copying, distribution and modification follow. GNU GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License applies to any program or other work which contains a notice placed by the copyright holder saying it may be distributed under the terms of this General Public License. The "Program", below, refers to any such program or work, and a "work based on the Program" means either the Program or any derivative work under copyright law: that is to say, a work containing the Program or a portion of it, either verbatim or with modifications and/or translated into another language. (Hereinafter, translation is included without limitation in the term "modification".) Each licensee is addressed as "you". Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running the Program is not restricted, and the output from the Program is covered only if its contents constitute a work based on the Program (independent of having been made by running the Program). Whether that is true depends on what the Program does. 1. You may copy and distribute verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and give any other recipients of the Program a copy of this License along with the Program. You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. 2. You may modify your copy or copies of the Program or any portion of it, thus forming a work based on the Program, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: a) You must cause the modified files to carry prominent notices stating that you changed the files and the date of any change. b) You must cause any work that you distribute or publish, that in whole or in part contains or is derived from the Program or any part thereof, to be licensed as a whole at no charge to all third parties under the terms of this License. c) If the modified program normally reads commands interactively when run, you must cause it, when started running for such interactive use in the most ordinary way, to print or display an announcement including an appropriate copyright notice and a notice that there is no warranty (or else, saying that you provide a warranty) and that users may redistribute the program under these conditions, and telling the user how to view a copy of this License. (Exception: if the Program itself is interactive but does not normally print such an announcement, your work based on the Program is not required to print an announcement.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Program, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Program, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Program. In addition, mere aggregation of another work not based on the Program with the Program (or with a work based on the Program) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may copy and distribute the Program (or a work based on it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you also do one of the following: a) Accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, b) Accompany it with a written offer, valid for at least three years, to give any third party, for a charge no more than your cost of physically performing source distribution, a complete machine-readable copy of the corresponding source code, to be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, c) Accompany it with the information you received as to the offer to distribute corresponding source code. (This alternative is allowed only for noncommercial distribution and only if you received the program in object code or executable form with such an offer, in accord with Subsection b above.) The source code for a work means the preferred form of the work for making modifications to it. For an executable work, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the executable. However, as a special exception, the source code distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. If distribution of executable or object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place counts as distribution of the source code, even though third parties are not compelled to copy the source along with the object code. 4. You may not copy, modify, sublicense, or distribute the Program except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense or distribute the Program is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. 5. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Program or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Program (or any work based on the Program), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Program or works based on it. 6. Each time you redistribute the Program (or any work based on the Program), the recipient automatically receives a license from the original licensor to copy, distribute or modify the Program subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties to this License. 7. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Program at all. For example, if a patent license would not permit royalty-free redistribution of the Program by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Program. If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply and the section as a whole is intended to apply in other circumstances. It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system, which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. 8. If the distribution and/or use of the Program is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Program under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. 9. The Free Software Foundation may publish revised and/or new versions of the General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Program specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of this License, you may choose any version ever published by the Free Software Foundation. 10. If you wish to incorporate parts of the Program into other free programs whose distribution conditions are different, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. NO WARRANTY 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS How to Apply These Terms to Your New Programs If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms. To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. Also add information on how to contact you by electronic and paper mail. If the program is interactive, make it output a short notice like this when it starts in an interactive mode: Gnomovision version 69, Copyright (C) year name of author Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. This is free software, and you are welcome to redistribute it under certain conditions; type `show c' for details. The hypothetical commands `show w' and `show c' should show the appropriate parts of the General Public License. Of course, the commands you use may be called something other than `show w' and `show c'; they could even be mouse-clicks or menu items--whatever suits your program. You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the program, if necessary. Here is a sample; alter the names: Yoyodyne, Inc., hereby disclaims all copyright interest in the program `Gnomovision' (which makes passes at compilers) written by James Hacker. , 1 April 1989 Ty Coon, President of Vice This General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Lesser General Public License instead of this License. diffpdf-2.1.3/help.html0000644000000000000000000002203312227164102013060 0ustar 00000000000000

DiffPDF

Basic Usage

Click the File #1 button to choose one PDF file and then the File #2 button to choose another (ideally very similar) PDF file, then click the Compare button to perform the comparison, and when that's finished, navigate through the pairs of differing pages using the View combobox or using the Previous and Next buttons. Alternatively, drag two files—either separately or together—and drop them onto DiffPDF's view panels, then click the Compare button.

The Compare Button

When the Compare button is pressed, DiffPDF does a high-speed scan of every pair of pages (~100 pairs of pages per second on the author's machine). To make the scan as fast as possible DiffPDF does a very rough check of each pair of pages—so it is possible that it identifies some false positives (i.e., page pairs that are really the same). False positives are quite rare. (There are no false negatives—differences are never missed.)

Words Comparison Mode

The default comparison mode is Words which does a smart text comparison word by word for each pair of pages. This mode is fairly liberal regarding whitespace and tries to ignore layout changes (within a page) insofar as possible. It also treats all hyphens (soft-hyphen, minus sign, etc.), the same, that is, as a plain hyphen. This mode is best for alphabetic languages like English.

Characters Comparison Mode

The Characters comparison mode does a smart text comparison character by character for each pair of pages. This mode is liberal regarding whitespace at the ends of lines and tries to ignore layout changes (within a page) insofar as possible. It also treats all hyphens (soft-hyphen, minus sign, etc.), the same, that is, as a plain hyphen. This mode is best for logographic languages like Chinese and Japanese.

Appearance Comparison Mode

The Appearance comparison mode can be used to detect changes in fonts, diagrams, or any other visual aspects. This mode is absolutely strict and compares each pair of pages pixel for pixel. By default this mode shows differences using highlighting just like the Words and Characters modes do. However, it is also possible to compare using composition modes which can be useful to detect very small and subtle differences that aren't immediately apparent.

Zoning

Zoning is an experimental feature designed to produce more accurate results (i.e., fewer false positives). Its main use is for pages that have tables or that mix alphabetic and logographic text, since these can cause the underlying popplar PDF library to provide the page's words mixed up. Warning: using zoning for large complex pages (bigger than A4, multiple columns, tables) in Characters mode can be very slow. (The current focus for the zoning code is functionality not efficiency.) Furthermore, in some cases zoning can cause an increase in false positives—this can occur because the zoning code reorders the text that is fed to the sequence matcher and sometimes the reordering is wrong. Getting this right is non-trivial; changing the tolerances may help.

The Tolerance/R value is the maximum distance between text (i.e., word) rectangles for the rectangles to be placed in the same zone. Lower values create more zones; higher values create fewer zones. More zones are expensive to compute but can produce more accurate results; fewer zones may reduce false positives. The Tolerance/Y value is is used for rounding y coordinates to the nearest multiple of this value. For example, if Tolerance/Y is 5 and a word at position (452,137) is followed by a superscript at (468,140), both will be treated as having a y coordinate of 140.

Page Ranges

By default DiffPDF compares every pair of pages in the two PDFs (or as many pairs of pages as the number of pages in the shorter PDF). It is also possible to compare particular pages or page ranges. For example, if there are two versions of a PDF file, one with pages 1-12 and the other with pages 1-13 because of an extra page having been added as page 4, they can be compared by specifying two page ranges, 1-12 for the first and 1-3, 5-13 for the second. This will make DiffPDF compare pages in the pairs (1, 1), (2, 2), (3, 3), (4, 5), (5, 6), and so on, to (12, 13).

Margins

It is possible to make DiffPDF ignore any text that is above a specified top margin, below a specified bottom margin, left of a specified left margin, and right of a specified right margin. One or more of these margins can be specified by, first, checking the Exclude Margins checkbox, and second by setting any of the margins. Margins can be set by clicking on a page view or by using the margin spinboxes.

Saving

Use the Save As button to pop up a Save dialog. This dialog lets you save a .pdf file with the highlighted changes, or individual image files (e.g., in .png or various other common image formats). The dialog supports saving the current or all left pages, right pages, or both pages.

The Options Dialog

This dialog is invoked by clicking the Options button. The dialog supports changing the highlighting color, whether to use a pen or fill or both, and the fill's opacity. The Square Size is used when doing Appearance mode comparisons: the smaller the size the more fine-grained the highlighting is—and the slower to compute. The Rule width determines the thickness of the margin rules which are used to indicate the vertical position of differences; the rules can be switched off using a Rule width of 0.

Dock Windows

The Controls, Actions, Margins, Zoning, and Log views are in dock widgets—these can be dragged into other dock areas (in which case they will reshape themselves as necessary), or dragged to float free. The Margins, Zoning, and Log views can also be closed; right click a dock area splitter and check their checkbox to open them again. These views may be shown tabbed: if there is enough space they can be dragged out of their tabs and all shown in full.

Command Line Usage

Although DiffPDF is a GUI program, if run from a console with two PDF files listed on the command line, DiffPDF will start up and immediately compare them in Words mode, or in Appearance mode if their names are preceded with -a or --appearance on the command line, or in Characters mode if their names are preceded with -c or --character on the command line. Run DiffPDF with --help to see all the command line options. (This won't work on Windows, although the other command line options will.) Here is the --help output:

usage: diffpdf [options] [file1.pdf [file2.pdf]]

A GUI program that compares two PDF files and shows
their differences.

The files are optional and are normally set through
the user interface.

options:
--help             show this usage text and terminate (run the
                   program without this option and press F1 for
                   online help)
--appearance  -a   set the initial comparison mode to Appearance
--characters  -c   set the initial comparison mode to Characters
--words       -w   set the initial comparison mode to Words
--language=xx      set the program to use the given translation
                   language, e.g., en for English, cz for Czech;
                   English will be used if there is no translation
                   available
--debug=2          write the text fed to the sequence matcher into
                   temporary files (e.g., /tmp/page1.txt etc.)
--debug=3          as --debug=2 but also includes coordinates in
                    y, x order

The text reordering is done by the TextItems::columnZoneYxOrder() method in the textitem.cpp file: suggestions for improvement are welcome! (Note that when using --debug3 coordinates are output in y, x order.)

If you're specifically looking for a command line PDF comparison tool, e.g., for automated testing, try comparepdf. diffpdf-2.1.3/help_cz.html0000644000000000000000000002502312227164102013556 0ustar 00000000000000

DiffPDF

Základní použití

Klepněte na tlačítko Soubor #1 pro výběr jednoho souboru PDF, a potom na tlačítko Soubor #2 pro výběr jiného souboru (ideálně velmi podobného) PDF. Pak klepněte na tlačítko Porovnat pro provedení srovnání, a když je toto dokončeno, pohybujte se dvojicemi porovnaných stran používajíce k tomu sdružené okno Pohled, nebo pomocí tlačítek Předchozí a Další. Jiným způsobem je přetažení dvou souborů — buď odděleně nebo společně — a jejich upuštění na zobrazovací panelyDiffPDF, potom klepněte na tlačítko Porovnat.

Tlačítko Porovnat

Když je stisknuto tlačítko Porovnat, DiffPDF udělá rychlé prohledání každé dvojice stran (~100 dvojic stran za sekundu na autorově stroji). Aby prohlídka byla co nejrychlejší DiffPDF udělá velmi hrubé přezkoušení každé dvojice stran —, takže je možné, že takto označí některé nálezy nesprávně jako kladné (např. dvojice stran, které jsou ve skutečnosti stejné). Falešné kladné nálezy jsou ale docela zřídkavé. (Nejsou tu nikdy žádné falešné záporné nálezy — rozdíly nejsou nikdy opomenuty.)

Režim porovnávání slov

Výchozím režimem je režim porovnávání slov, který dělá chytré srovnání slovo od slova u každé dvojice stran. Tento režim je celkem velkorysý, pokud jde o prázdná místa a pokouší se nevšímat si změn v rozložení (v rámci strany), jak jen to je možné. Stará se také o všechna dělítka (měkké dělení, znaménko minus atd.), totéž jako u prostého dělení. Tento režim je nejlepší pro jazyky s abecedou, jakými je například čeština nebo angličtina.

Režim porovnávání znaků

Režim porovnávání znaků, který dělá chytré srovnání znak po znaku u každé dvojice stran. Tento režim je velkorysý, pokud jde o prázdná místa na koncích řádků a pokouší se nevšímat si změn v rozložení (v rámci strany), insofar as possible. jak jen to je možné. Stará se také o všechna dělítka (měkké dělení, znaménko minus atd.), totéž jako u prostého dělení. Tento režim je nejlepší pro logografické jazyky, jakými jsou například čínština nebo japonština.

Režim porovnávání vzhledu

Režim porovnávání vzhledu lze použít na zjištění změn v písmech, diagramech, nebo u jakýchkoli jiných viditelných stránek dokumentu. Tento režim je naprosto přísný a porovnává každou dvojici stran pixel po pixelu. Ve výchozím nastavení ukazuje tento režim rozdíly pomocí zvýraznění, stejně jako to činí režimy porovnávání slov nebo znaků. Je nicméně možné porovnávat za použití skldebných režimů, což může být užitečné při zjišťování velmi malých a jemných rozdílů, jež nejsou hned zřejmé.

Rozdělení na oblasti

Rozdělení na oblasti je pokusná vlastnost navržená s cílem dosahovat přesnějších výsledků (např. méně falešných kladných nálezů). Její hlavní užití je na strany, jež mají tabulky míchající abecední a logografický text, protože tyto mohou způsobit, že knihovna poppler PDF poskytne slova na straně pomíchaná. Varování: použítí rozdělení na oblasti na velké složité strany (větší než A4, více sloupců, tabulky) v režimu Znaky může být velmi pomalé. (v současnosti je pozornost u rozdělení na oblasti věnována funkčnosti nikoli výkonu.) Dále může v některých případech rozdělení na oblasti zapříčinit nárůst v nesprávných kladných nálezech — to se může objevit, protože kód rozdělení na oblasti přeuspořádá text, který je přiveden do porovnání sekvence a někdy je přeuspořádání chybné. Udělat to správně není jednoduchá záležitost; změna odchylek může pomoci.

Hodnota odchylky/R je největší vzdálenost mezi textovými (např. slovo) obdélníky pro obdélníky k umístění ve stejné oblasti. Nižší hodnoty vytvoří více oblastí; vyšší vytvoří méně oblastí. Více oblastí je náročnější na výpočty, ale může podat přesnější výsledky; méně oblastí může zmenšit počet falešných kladných nálezů. Hodnota odchylky/Y se používá na zaokrouhlení souřadnice y k nejbližšímu násobku této hodnoty. Například je-li Odchylka/Y 5 a slovo v poloze (452,137) je následováno horním indexem v poloze (468,140), s oběma bude nakládáno tak, jakoby měly souřadnici y 140.

Rozsahy stran

Ve výchozím nastavení porovnává DiffPDF každou dvojici stran dvou souborů PDF (nebo tolik dvojic stran, jako je číslo stran v kratším ze souborů PDF). Také je možné porovnat zvláštní strany nebo rozsahy stran. Pokud jsou například dvě verze souboru PDF, jedna se stranami 1-12 a druhá se stranami 1-13 kvůli zvláštní straně přidané jako strana 4, lze je porovnat zadáním dvou rozsahů stran, 1-12 pro první a 1-3, 5-13 pro druhý soubor. To povede k tomu, že DiffPDF porovná strany ve dvojicích (1, 1), (2, 2), (3, 3), (4, 5), (5, 6), atd. až po (12, 13).

Okraje

Je možné, aby si DiffPDF nevšímal jakéhokoli textu, který je nad zadaným horním okrajem, pod zadaným dolním nalevo od zadaného levého okraje, a napravo od zadaného pravého okraje. Jeden nebo více těchto okrajů lze zadat nejprve zaškrtnutím zaškrtávacího okénka Vyloučit okraje a potom nastavením kteréhokoli z okrajů. Okraje lze nastavit klepnutím na pohled na stranu a použitím prvků představujících okraje.

Ukládání

Použijte tlačítko Uložit jako pro vyvolání dialogu pro uložení. Tento dialog vám umožní uložit soubor.pdf se zvýrazněnými změnami, nebo jednotlivé obrázkové soubory (např. v .png nebo v různých jiných běžných formátech obrázků). Dialog podporuje uložení nynější, nebo všech levých stran, pravých stran nebo obou stran.

Dialog voleb

Tento dialog je vyvolán klepnutím na tlačítko Volby. Dialog podporuje změnu barvy zvýraznění, zda použít pero nebo výplně nebo obojí, a neprůhlednost výplně. Velikost pole se používá při provádění porovnání v režimu vzhledu: čím menší velikost, tím je zvýraznění jemnější — a pomalejší na výpočty. Šířka vyznačovací čáry stanovuje tloušťku okrajových čar používaných na vyznačení svislé polohy rozdílů; čáry je možné vypnout použitím nastavení šířky vyznačovací čáry na 0.

Ukotvení oken

Ovládací prvky, činnosti, okraje, rozdělení na oblasti a pohled na zápisy jsou ukotvených prvcích — tyto lze přetáhnout do jiných kotevních oblastí pro kotvení (v takovém případě se jejich tvar změní podle potřeby), nebo odtáhnout k volnému plavení. Okraje, rozdělení na oblasti a pohled na zápisy jde také zavřít; klepnutí pravým tlačítkem myši na oddělovač kotevní oblasti a zaškrtnutí zaškrtávacího okénka pro jejich opětovné otevření. Tyto pohledy lze ukázat v kartách: Pokud je dostatek místa, lze je z jejich karet odtáhnout a ukázat všechny v úplnosti.

Použití v příkazovém řádku

I když je DiffPDF program s obrazovým uživatelským rozhraním, pokud se spustí v terminálu v příkazovém řádku s uvedením dvou souborů PDF, DiffPDF naběhne a okamžitě je porovná v režimu Slova, nebo v režimu Vzhled, jestliže jsou jejich názvy v příkazovém řádku uvozeny -a nebo --appearance, nebo v režimu Znaky, jestliže jsou jejich názvy v příkazovém řádku uvozeny -c nebo --character. Spusťte DiffPDF s --help, abyste viděli všechny volby pro příkazový řádek. (Toto nebude pracovat v případě systému Windows, ačkoli jiné volby pro příkazový řádek budou.) Zde je výstup --help:

Použití: diffpdf [volby] [file1.pdf [file2.pdf]]

Program s obrazovým uživatelským rozhraním, jenž porovnává dva soubory PDF a ukazuje rozdíly mezi nimi.

Soubory jsou volitelné a obyčejně nastavené přes uživatelské rozhraní.

Volby:
--help             Ukázat tento text o používání a skončit (spustit
                   program bez této volby a stistnout F1 pro
                   nápovědu na internetu)
--appearance  -a   Nastavit počáteční režim porovnávání na Vzhled
--characters  -c   Nastavit počáteční režim porovnávání na Znaky
--words       -w   Nastavit počáteční režim porovnávání na Slova
--language=xx      Nastavit program, aby používal daný překladový
                   jazyk, například en pro anglický, cz pro český;
                   Angličtina se bude používat, pokud není dostupný žádný
                   překlad
--debug=2          Zapsat text vedený do porovnání sekvence do
                   dočasných souborů (např. /tmp/page1.txt atd.)
--debug=3          Stejně jako --debug=2, ale také zahrnuje souřadnice v
                    y, x

Vykreslení textu je uděláno postupem TextItems::columnZoneYxOrder() v souboru textitem.cpp: návrhy na vylepšení jsou vítány! (Všimněte si, že při použití --debug3 jsou souřadnice výstup v y, x.)

Pokud hledáte zvláštní nástroj na porovnávání PDF v příkazovém řádku např. pro automatizované zkoušení, vyzkoušejte comparepdf. diffpdf-2.1.3/help_de.html0000644000000000000000000002452312227164102013536 0ustar 00000000000000

DiffPDF

Verwendung

Drücken Sie zunächst die Schaltfläche Datei #1 und wählen Sie eine PDF-Datei. Drücken Sie dann die Schaltfläche Datei #2 um eine weitere (idealerweise sehr ähnliche) PDF-Datei auszuwählen. Anschließend drücken Sie die Schaltfläche Vergleichen um den Vergleich beider Dateien zu starten. Sobald der Vorgang abgeschlossen ist können Sie die Seiten mit Unterschieden paarweise anzeigen lassen, indem Sie die Ansicht-Auswahlbox oder die Schaltflächen Vorherige und Nächste verwenden. Alternativ können Sie auch zwei Dateien—entweder einzeln oder auf einmal—mit der Maus auf die Seitenanzeigebereiche von DiffPDF ziehen, und anschließend die Schaltfläche Vergleichen drücken.

Der Vergleichsvorgang

Wenn die Schaltfläche Vergleichen gedrückt wird führt DiffPDF einen sehr schnellen Scan jedes Seitenpaares aus (etwa 100 Seitenpaare die Sekunde auf dem Computer des Entwicklers). Um die Geschwindigkeit des Scanvorgangs zu beschleunigen wird nur eine sehr grobe Prüfung der Seitenpaare durchgeführt—es ist daher möglich, dass es zu Fehlerkennungen kommt (d.h. ein Seitenpaar wird aufgelistet obwohl es keine Unterschiede gibt). Fehlerkennungen treten nur selten auf. (Es kann jedoch nicht vorkommen dass Seiten, die sich unterschieden, nicht erkannt werden.)

Vergleichsmodus Wort-für-Wort

Der Standardvergleichsmodus ist Wort-für-Wort, bei dem ein intelligenter Textvergleich wortweise für jedes Seitenpaar durchgeführt wird. In diesem Modus wird recht freiheitlich mit Leerraumzeichen (whitespace) umgegangen damit Änderungen am Layout nach Möglichkeit nicht als Unterschied erkannt werden (innerhalb einer Seite). Auch werden alle Binde- und Trennstriche als gleich angesehen. Dieser Modus eigenet sich am besten für alphabetische Sprachen wie etwa Deutsch und Englisch.

Vergleichsmodus Zeichen-für-Zeichen

Bei diesem Vergleichsmodus wird ein intelligenter Einzelzeichenvergleich für den Text jedes Seitenpaares durchgeführt. Hierbei wird recht freiheitlich mit Leerraumzeichen (whitespace) am Ende jeder Zeile umgegangen damit Änderungen am Laouyt nach Möglichkeit nicht als Unterschied erkannt werden. Auch werden alle Binde- und Trennstriche als gleich angesehen. Dieser Modus eigenet sich am besten für logographische Sprachen wie etwa Chinesisch und Japanisch.

Visueller Vergleich

Der visuelle Vergleichsmodus eignet sich um Unterschiede bei Schriftarten, Diagrammen oder anderen sichtbaren Elementen zu finden. Dieser Modus ist absolut genau und vergleicht jedes Seitenpaar Pixel für Pixel. Standardmäßig werden Unterschiede auch in diesem Modus durch farbliche Hervorhebug markiert. Alternativ können hier jedoch auch Kompositionsmodi verwendet werden, welche das Auffinden von minimalen Unterschieden erleichtern können.

Einteilung (Zonen-Bildung)

Die Einteilung ist ein experimenteller Modus um die Genauigkeit der Ergebnisse zu verbessern (d.h. weniger Fehlerkennungen). Der Hauptanwendungsbereich sind Seiten die Tabellen oder alphabetische und logographische Texte enthalten, da es hier dazu kommen kann dass die intern verwendete Poppler PDF Bibliothek die Texte auf der Seite in unterschiedlicher Reihenfolge liefert. Warnung: Einteilung kann bei großen, komplexen Seiten (größer als A4, mehrere Spalten, Tabellen) im Vergleichsmodus Zeichen-für-Zeichen sehr langsam sein. (Bei der Einteilung wird der Schwerpunkt auf die Funktionalität gelegt, nicht auf die Effizienz). Außerdem kann es in einigen Fällen passieren dass die Einteilung zu vermehrten Fehlerkennungen führt—dies kann vorkommen da sich durch die Einteilung die Reihenfolge ändert, in welcher der Text an den Sequenzmatcher übergeben wird, und diese Umsortierung verkehrt sein kann. Dies zu korrigieren kann schwierig sein; Änderungen an den Toleranz-Einstellungen können helfen.

Toleranz/B ist die maximale Distanz zwischen Textbereichen (Wörtern) bei der Texte der gleichen Zone zugeordnet werden. Kleinere Werte führen zu mehr Zonen; größere Werte zu weniger Zonen. Mehr Zonen benötigen mehr Zeit für die Berechnung aber können zu genaueren Ergebnissen führen; weniger Zonen können Fehlerkennungen reduzieren.

Toleranz/Y wird verwendet um die Y-Koordinate auf eine Vielzahl dieses Wertes zu runden. Ist beispielsweise Toleranz/Y auf 5 eingestellt dann wird ein Wort bei (452,137) und ein folgendes Superscript bei (468,140) bei der Verarbeitung behandelt als hätten beide die Y-Koordinate 140.

Seitenbereiche

Standardmäßig vergleicht DiffPDF alle Seitenpaare der beiden PDFs (die Anzahl wird durch die Zahl der Seiten des kürzeren PDFs bestimmt). Es ist auch möglich nur bestimmte Seiten oder Seitenbereiche zu vergleichen. Gibt es beispielsweise zwei Versionen eines PDFs, eine mit 12 Seiten und eine mit 13 Seiten, da eine Extraseite als Seite 4 eingefügt wurde, dann kann der Vergleich durchgeführt werden durch Angabe der Seitenbereiche 1-12 für das erste und 1-3,5-13 für das zweite PDF. Das bewirkt, dass DiffPDF die Seitepaare (1, 1), (2, 2), (3, 3), (4, 5), (5, 6), und so weiter, bis (12, 13) vergleicht.

Randbereiche

DiffPDF kann Text innerhalb von Randbereichen (oben, unten, links, rechts) vom Vergleich ausschließen. Ein oder mehrere Randbereiche können definiert werden indem zunächst die Checkbox Randbereiche ausschließen angehakt wird und anschließend Werte für die gewünschten Bereiche eingetragen werden. Randbereiche können auch durch Klick in die Seite definiert werden.

Speichern

Die Schaltfläche Speichern unter öffnet den Speichern-Dialog. Über diesen Dialog kann eine PDF-Datei mit den Hervorhebungen erstellt werden. Alternativ können auch Bilddateien erstellt werden (etwa PNG oder verschiedene andere Formate). Es kann nur das aktuelle Seitenpaar oder alle Seitenpaare gespeichert werden. Es können zudem nur die Seiten aus dem linken PDF (Datei #1), nur die aus dem rechten (Datei #2) oder beide Seiten nebeneinander gespeichert werden.

Optionen

Der Optionen Dialog wird geöffnet über die Schaltfläche Optionen. Für die Hervorhebungen kann die Farbe, dessen Füllmuster, Rahmen und Deckkraft eingestellt werden. Die Genauigkeit des visuellen Vergleichs kann eingestellt werden. Kleine Werte bewirken eine genauere Hervorhebung—sind jedoch rechenintensiver. Die Breite der Randmarker, welche die vertikale Position der Unterschiede anzeigen, kann eingestellt werden. Eine Breite von 0 deaktivert die Randmarker.

Andockbare Fenster

Die Bereiche Steuerung, Aktionen, Randbereich, Einteilung und Log sind Dock-Widgets—diese können mit der Maus an die gewünschte Stelle oder aus dem Hauptfenster heraus gezogen werden. Randbereich, Einteilung und Log können auch geschlossen werden; durch Klick auf die Titelzeile eines beliebigen Widgets mit der rechten Maustaste öffnet sich ein Menü, über welches die geschlossenen Widgets wieder eingeblendet werden können. Mehrere Widgets können auch übereinander gezogen werden, so dass über kleine Reiter zwischen Ihnen hin und hergeschalten werden kann.

Verwendung über die Kommandozeile

Obwohl DiffPDF ein Programm mit graphischer Benutzerschnittstelle ist kann es auch über eine Konsole gestartet werden. Werden dabei zwei PDF-Dateien übergeben, dann führt DiffPDF nach dem Start sofort einen Word-für-Wort Vergleich der beiden Dateien aus. Wird den Dateinamen ein -a oder --appearance vorangestellt, dann wird ein visueller Vergleich durchgeführt. -c oder --character startet einen Zeichen-für-Zeichen Vergleich. Die Angabe --help listet alle verfügbaren Kommandozeilenparameter auf. (Dies funktioniert nicht unter Windows, die anderen Parameter allerdings schon.) Hier ist die Ausgabe von --help:

usage: diffpdf [options] [file1.pdf [file2.pdf]]

A GUI program that compares two PDF files and shows
their differences.

The files are optional and are normally set through
the user interface.

options:
--help             show this usage text and terminate (run the
                   program without this option and press F1 for
                   online help)
--appearance  -a   set the initial comparison mode to Appearance
--characters  -c   set the initial comparison mode to Characters
--words       -w   set the initial comparison mode to Words
--language=xx      set the program to use the given translation
                   language, e.g., en for English, cz for Czech;
                   English will be used if there is no translation
                   available
--debug=2          write the text fed to the sequence matcher into
                   temporary files (e.g., /tmp/page1.txt etc.)
--debug=3          as --debug=2 but also includes coordinates in
                    y, x order

Die Text-Umsortierung wird vorgenommen in Methode TextItems::columnZoneYxOrder() in Datei textitem.cpp : Verbesserungsvorschläge nehme ich gerne entgegen! (Beachten Sie bitte dass bei Verwendung von --debug3 die Koordinaten in der Reihenfolge y, x angegeben werden.)

Wenn Sie auf der Suche nach einem Kommandozeilentool für den Vergleich von PDF-Dateien sind, etwa für automatisiertes Testen, dann probieren Sie auch comparepdf aus. diffpdf-2.1.3/help_fr.html0000644000000000000000000002604112227164102013552 0ustar 00000000000000

Usage de base

Cliquer sur le bouton Fichier #1 pour sélectionner un premier fichier PDF puis sur le bouton Fichier #2 pour en choisir un second (idéalement très similaire), et finalement cliquer sur le bouton Comparer pour lancer le travail de comparaison. Une fois la comparaison effectuée par le logiciel, naviguer d'une paire de pages présentant des différences à l'autre en utilisant le menu déroulant Vue ou bien les boutons Précédent et Suivant. De manière alternative, glisser 2 fichiers—soit l'un après l'autre, soit ensemble—et les déposer dans la fenêtre de DiffPDF, puis cliquer sur le bouton Comparer.

Le bouton Comparer

Quand le bouton Comparer est pressé, DiffPDF effectue un parcours ultra-rapide de chaque paire de page afin de détecter les différences (~100 paires de pages chaque seconde sur la machine de l'auteur). Pour détecter les différences très rapidement, DiffPDF effectue une comparaison assez grossière de chaque paire de page—il est donc possible que des faux positifs apparaissent (par exemple des pages appariées détectées différentes alors qu'elles sont strictement identiques). Les faux positifs sont toutefois assez rares. (Il n'y a pas de faux négatifs—les différences ne sont jamais manquées.)

Le mode de comparaison par Mots

Le mode de comparaison par défaut est celui par Mots : il s'agit d'une comparaison mot par mot sur chacune des paires de pages. Ce mode est assez laxiste concernant les espaces et essaye d'ignorer les changements de mise en page (au sein d'une même page) autant que possible. Ce mode considère également tous les tirets comme identiques. Ce mode est le plus adapté aux langues alphabétiques comme l'anglais ou le français.

Le mode de comparaison par Caractères

Le mode de comparaison par caracètres effectue une comparaison intelligente de chacun des caractères sur les paires de pages. Ce mode est laxiste concernant les espaces de fin de ligne et essaye d'ignorer les changements de mise en page autant que possible. Ce mode considère également tous les tirets comme identiques. Ce mode est le plus adapté aux langues à idéogrammes comme le chinois ou le japonais.

Le mode de comparaison selon l'Apparence

Le mode de comparaison selon l'Apparence peut être utilisé pour détecter des différences entre les polices, les illustrations ou tout autre élément visuel. La comparaison obéit à une logique stricte : les pixels de chaque page sont comparés deux à deux sur l'ensemble du document. Par défaut, ce mode utilise le surlignage pour mettre en évidence les différences. Cependant, il est possible d'utiliser les modes "compositions" pour détecter des différences subtiles qui ne sont pas facilement apparentes.

Découpage par zones

Le découpage par zones est une fonction encore expérimentale destinée à produire des résultats plus fiables (i.e. moins de faux positifs). Elle peut être utilisée principalement pour les pages qui contiennent des tableaux ou bien qui mélangent des textes alphabétiques et des idéogrammes. En effet, ces mélanges peuvent conduire la librairie sous-jacente Popplar à mélanger les textes. Attention : l'utilisation du découpage par zones pour des grandes pages complexes (plus grandes qu'A4, à multiples colonnes, avec de grandes tables) en mode Caractères peut provoquer de grosses lenteurs (pour le moment, le développement de cette fonction est axé sur sa rigueur et non son efficacité). En outre, dans certains cas le découpage par zones peut conduire à une augmentation du nombre de faux positifs—cela peut être le cas quand le code de découpage réordonne de manière erronée le texte avant de le traiter. Améliorer ceci n'est pas trivial; changer les limites de tolérance peut aider.

La valeur de la Tolérance/R est la valeur de la distance maximale entre les rectangles de texte (i.e. les mots) pour les considérer comme inclus dans la même zone. Des valeurs plus faibles conduisent à la création de zones plus nombreuses, des valeurs plus grandes à moins de zones. Un plus grand nombre de zones demande plus de temps de calcul mais produit des résultats plus exacts. Un nombre plus faible de zones peut contribuer à réduire les faux positifs. La valeur Tolérance/Y est utilisée pour arrondir la coordonnée en y (l'ordonnée) au multiple le plus proche de cette valeur. Par exemple, si la tolérance/Y est 5 et si un mot de coordonnées (452,137) est suivi d'un exposant de coordonnées (468,140), les 2 seront traités comme ayant une coordonnée y de 140.

Intervalles de pages

Par défaut DiffPDF compare chaque paire de pages des 2 fichiers PDF (ou bien le nombre maximale de paires possibles en se basant sur le fichier le plus court). Il est toutefois également possible de comparer des pages particulières ou bien des intervalles de pages. Par exemple, si 2 versions d'un fichier PDF existent, l'une avec 12 pages et l'autre avec 13 pages à cause de l'addition d'une nouvelle page à la position 4, il est nécessaire d'expliquer à DiffPDF quelles pages comparer : dans l'exemple décrit, on demandera de comparer les pages 1-12 du premier document avec les pages 1-3, 5-13 du second. Avec ce paramétrage, DiffPDF comparera les pages des paires (1,1), (2,2), (3,3), (4,5), (5,6) et ainsi de suite jusqu'à (12,13).

Marges

Il est possible de demander à DiffPDF ignorer tout texte se trouvant au-dessus d'une marge haute, en-dessous d'une marge basse, à gauche d'une marge gauche ou bien encore à droite d'une marge droite. Une ou plusieurs de ces marges peut être activée en cochant la case Exclure des marges puis en spécifiant les valeurs des marges en question. Les valeurs des marges peuvent être ajustées en cliquant dans la vue ou bien en saisissant une valeur manuellement.

Enregistrer

Utiliser le bouton Enregistrer Sous pour ouvrir une fenêtre d'enregistrement. Cette fenêtre permet d'enregistrer un fichier .pdf avec les changements mis en évidence, ou bien des fichiers images individuels (par exemple, en .png ou plusieurs autres formats d'image courants). La fenêtre permet de sauvegarder au choix, toutes les pages, la page courante seulement, les pages de droite, les pages de gauche...

La fenêtre d'Options

Cette fenêtre est invoquée par un clic sur le bouton Options. Il est possible de modifier la couleur de surlignage, le type de pinceau utilisé pour afficher les différences (crayon, remplissage ou bien les 2 ensemble) et l'opacité de la couleur de remplissage. La taille du carré est utilisée lorsqu'on utilie le mode de comparaison selon l'apparence : plus la taille est petite, plus le surlignage est précis—il est également plus lent à calculer. La largeur de la règle détermine l'épaisseur de la règle utilisée dans la marge pour indiquer la position verticale des erreurs ; ces règles peuvent être désactivées en choisissant une largeur nulle.

Utilisation des fenêtres en Docks

Les vues Contrôles, Actions, Marges, Découpage par zones et Log sont inclues dans des éléments dockables— ces derniers peuvent donc être glissés dans d'autres zones de l'écran (dans ce cas, ils se redessineront de manière adéquate) ou bien glissés en-dehors des zones pour se transformer en fenêtres flottantes. Ces éléments peuvent également être clos; ils seront réouverts en effectuant un clic droit sur les séparateurs et en sélectionnant la case à cocher leur correspondant. Enfin, ces éléments peuvent être affichés sous forme d'onglets.

Utilisation par la ligne de commande

Bien que DiffPDF soit un programme avec une interface graphique, il est possible de le lancer depuis la ligne de commande avec 2 fichiers passés en paramètres. DiffPDF démarrera automatiquement en mode 'Comparaison par Mots', ou bien en 'Comparaison selon l'apparence' si les noms des fichiers ont été précédés de l'option -a ou --appearance, ou encore en 'Comparaison par caractères' si l'on ajoute l'option -c ou --character sur la ligne de commande. Lancer DiffPDF avec l'option -h ou --help pour afficher toutes les options de la ligne de commande (cela ne fonctionnera pas sur Windows mais devrait fonctionner sur les autres systèmes d'exploitation). Voici la sortie provoquée par l'option --help :

usage: diffpdf [options] [file1.pdf [file2.pdf]]

A GUI program that compares two PDF files and shows
their differences.

The files are optional and are normally set through
the user interface.

options:
--help             show this usage text and terminate (run the
                   program without this option and press F1 for
                   online help)
--appearance  -a   set the initial comparison mode to Appearance
--characters  -c   set the initial comparison mode to Characters
--words       -w   set the initial comparison mode to Words
--language=xx      set the program to use the given translation
                   language, e.g., en for English, cz for Czech;
                   English will be used if there is no translation
                   available
--debug=2          write the text fed to the sequence matcher into
                   temporary files (e.g., /tmp/page1.txt etc.)
--debug=3          as --debug=3 but also includes coordinates in
                    y, x order

Le ré-ordonnancement du texte est effectué par la méthode TextItems::columnZoneYxOrder() dans le fichier textitem.cpp : toute suggestion d'amélioration est la bienvenue ! (Il est intéressant de noter qu'avec l'option --debug3 les coordonnées sont affichées dans l'ordre y, x.)

Si vous recherchez de manière spécifique un outil de comparaison de fichiers PDF en ligne de commande, par exemple pour effectuer des comparaisons automatiques, essayez comparepdf. diffpdf-2.1.3/helpform.cpp0000644000000000000000000000340112227164102013560 0ustar 00000000000000/* Copyright © 2011-13 Qtrac Ltd. All rights reserved. This program or module is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. */ #include "helpform.hpp" #include #include #include #include #include #include #include #include HelpForm::HelpForm(const QString &language, QWidget *parent) : QMainWindow(parent) { QTextBrowser *viewer = new QTextBrowser; viewer->setOpenExternalLinks(true); QString filename = QString(":/help_%1.html").arg(language); if (!QFile::exists(filename)) filename = ":/help.html"; QFile file(filename); file.open(QIODevice::ReadOnly|QIODevice::Text); QTextStream in(&file); in.setCodec("UTF-8"); viewer->setHtml(in.readAll()); viewer->setReadOnly(true); setCentralWidget(viewer); (void) new QShortcut(QKeySequence("Escape"), this, SLOT(close())); QPoint pos(0, 0); if (parent) pos = parent->pos(); move(pos); resize(640, 480); QSettings settings; restoreGeometry(settings.value("HelpForm/Geometry").toByteArray()); setWindowTitle(tr("%1 — Help").arg(qApp->applicationName())); } void HelpForm::closeEvent(QCloseEvent *) { QSettings settings; settings.setValue("HelpForm/Geometry", saveGeometry()); } diffpdf-2.1.3/helpform.hpp0000644000000000000000000000153712227164102013575 0ustar 00000000000000#ifndef HELPFORM_HPP #define HELPFORM_HPP /* Copyright © 2011-13 Qtrac Ltd. All rights reserved. This program or module is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. */ #include class QMainWindow; class HelpForm : public QMainWindow { Q_OBJECT public: HelpForm(const QString &language, QWidget *parent=0); protected: void closeEvent(QCloseEvent *event); }; #endif // HELPFORM_HPP diffpdf-2.1.3/images/icon.png0000644000000000000000000000156312227164102014152 0ustar 00000000000000PNG  IHDR@@iq pHYs P%%IDATx[k \:=jrJ4 0HL@qXGZ39Z7*ECځg)%,C,a TR\@,%(71_ %Ho<&fof(Ju\>Uzz*Ss.uTN)! H[#,AM()v1!g7$5Hi9wC Ԕ l% U+Y>)PBۨ ^ jR _xWBAFάz.Y{A1dDT/yʲ a5u<յ'}v`CV%ιb"Vjt]Lxq0 %c$TAmb|o"-E`ݯYݧ]_,y+RcifőfZ>koTӠCZl-/s5ȅ|>@Cu5yKg8V148.1# aKQ^[8Ѧ0]29o zyaYOTc@mB~"H'89=|`z[YiKzF怐Fpf&PfG0V!"n#\ X=,_A^LeP"p|vb$I"IBIENDB`diffpdf-2.1.3/images/right.png0000644000000000000000000000056312227164102014336 0ustar 00000000000000PNG  IHDR@@iq pHYs+%IDATx[09IܙT(BeYe^Uz:PGKvd0 LB1G0D F; "( t"(@\DP Ј Gˏ:jRJVБ >"m05D= VO􋛳\+4ݪ͏"qM 5tO Ck d=,a<n^=Lٺ{ԗ6jzQ̲,˲;{HV5'IENDB`diffpdf-2.1.3/label.cpp0000644000000000000000000000257312227164102013034 0ustar 00000000000000/* Copyright © 2011-13 Qtrac Ltd. All rights reserved. This program or module is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. */ #include "generic.hpp" #include "label.hpp" #include #include #include Label::Label(QWidget *parent) : QLabel(parent) { setAcceptDrops(true); } void Label::dragEnterEvent(QDragEnterEvent *event) { const QMimeData *mimeData = event->mimeData(); if (mimeData->hasFormat("text/plain") || mimeData->hasFormat("text/uri-list")) event->acceptProposedAction(); } void Label::dropEvent(QDropEvent *event) { QStringList filenames = droppedFilenames(event->mimeData()); if (!filenames.isEmpty()) emit filenamesDropped(filenames); event->acceptProposedAction(); } void Label::mousePressEvent(QMouseEvent *event) { if (event->button() == Qt::LeftButton) emit clicked(event->pos()); QLabel::mousePressEvent(event); } diffpdf-2.1.3/label.hpp0000644000000000000000000000173712227164102013042 0ustar 00000000000000#ifndef LABEL_HPP #define LABEL_HPP /* Copyright © 2011-13 Qtrac Ltd. All rights reserved. This program or module is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. */ #include class Label : public QLabel { Q_OBJECT public: Label(QWidget *parent=0); signals: void filenamesDropped(const QStringList &filenames); void clicked(const QPoint &pos); protected: void dragEnterEvent(QDragEnterEvent *event); void dropEvent(QDropEvent *event); void mousePressEvent(QMouseEvent *event); }; #endif // LABEL_HPP diffpdf-2.1.3/lineedit.cpp0000644000000000000000000000231612227164102013545 0ustar 00000000000000/* Copyright © 2011-13 Qtrac Ltd. All rights reserved. This program or module is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. */ #include "generic.hpp" #include "lineedit.hpp" #include #include LineEdit::LineEdit(QWidget *parent) : QLineEdit(parent) { setAcceptDrops(true); } void LineEdit::dragEnterEvent(QDragEnterEvent *event) { const QMimeData *mimeData = event->mimeData(); if (mimeData->hasFormat("text/plain") || mimeData->hasFormat("text/uri-list")) event->acceptProposedAction(); } void LineEdit::dropEvent(QDropEvent *event) { QStringList filenames = droppedFilenames(event->mimeData()); if (!filenames.isEmpty()) emit filenamesDropped(filenames); event->acceptProposedAction(); } diffpdf-2.1.3/lineedit.hpp0000644000000000000000000000164112227164102013552 0ustar 00000000000000#ifndef LINEEDIT_HPP #define LINEEDIT_HPP /* Copyright © 2011-13 Qtrac Ltd. All rights reserved. This program or module is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. */ #include class LineEdit : public QLineEdit { Q_OBJECT public: LineEdit(QWidget *parent=0); signals: void filenamesDropped(const QStringList &filenames); protected: void dragEnterEvent(QDragEnterEvent *event); void dropEvent(QDropEvent *event); }; #endif // LINEEDIT_HPP diffpdf-2.1.3/main.cpp0000644000000000000000000001154712227164102012702 0ustar 00000000000000/* Copyright © 2008-13 Qtrac Ltd. All rights reserved. This program or module is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. */ #include "mainwindow.hpp" #include #include #include #include #include #include #include #include int main(int argc, char *argv[]) { QApplication app(argc, argv); #ifdef Q_WS_MAC app.setCursorFlashTime(0); #endif app.setOrganizationName("Qtrac Ltd."); app.setOrganizationDomain("qtrac.eu"); app.setApplicationName("DiffPDF"); app.setWindowIcon(QIcon(":/icon.png")); QTextCodec::setCodecForTr(QTextCodec::codecForName("UTF-8")); QTextStream out(stdout); QStringList args = app.arguments().mid(1); QSettings settings; InitialComparisonMode comparisonMode = static_cast< InitialComparisonMode>(settings.value("InitialComparisonMode", CompareWords).toInt()); const QString LanguageOption = "--language="; QString filename1; QString filename2; QString language = QLocale::system().name(); bool optionsOK = true; Debug debug = DebugOff; foreach (const QString arg, args) { if (optionsOK && (arg == "--appearance" || arg == "-a")) comparisonMode = CompareAppearance; else if (optionsOK && (arg == "--characters" || arg == "-c")) comparisonMode = CompareCharacters; else if (optionsOK && (arg == "--words" || arg == "-w")) comparisonMode = CompareWords; else if (optionsOK && arg.startsWith(LanguageOption)) language = arg.mid(LanguageOption.length()); else if (optionsOK && (arg == "--help" || arg == "-h")) { out << "usage: diffpdf [options] [file1.pdf [file2.pdf]]\n\n" "A GUI program that compares two PDF files and shows " "their differences.\n" "\nThe files are optional and are normally set " "through the user interface.\n\n" "options:\n" "--help -h show this usage text and terminate " "(run the program without this option and press F1 for " "online help)\n" "--appearance -a set the initial comparison mode to " "Appearance\n" "--characters -c set the initial comparison mode to " "Characters\n" "--words -w set the initial comparison mode to " "Words\n" "--language=xx set the program to use the given " "translation language, e.g., en for English, cz for " "Czech; English will be used if there is no translation " "available\n" "--debug=2 write the text fed to the sequence " "matcher into temporary files (e.g., /tmp/page1.txt " "etc.)\n" "--debug=3 as --debug=3 but also includes " "coordinates in y, x order\n" "\nRun the program without the --help option and click " "About to see copyright and license details\n" ; return 0; } else if (optionsOK && (arg == "--debug" || arg == "--debug=1" || arg == "--debug1")) ; // basic debug mode currently does nothing (did show zones) else if (optionsOK && (arg == "--debug=2" || arg == "--debug2")) debug = DebugShowTexts; else if (optionsOK && (arg == "--debug=3" || arg == "--debug3")) debug = DebugShowTextsAndYX; else if (optionsOK && arg == "--") optionsOK = false; else if (filename1.isEmpty() && arg.toLower().endsWith(".pdf")) filename1 = arg; else if (filename2.isEmpty() && arg.toLower().endsWith(".pdf")) filename2 = arg; else out << "unrecognized argument '" << arg << "'\n"; } QTranslator qtTranslator; qtTranslator.load("qt_" + language, QLibraryInfo::location(QLibraryInfo::TranslationsPath)); app.installTranslator(&qtTranslator); QTranslator appTranslator; appTranslator.load("diffpdf_" + language, ":/"); app.installTranslator(&appTranslator); MainWindow window(debug, comparisonMode, filename1, filename2, language.left(2)); // We want de not de_DE etc. window.show(); return app.exec(); } diffpdf-2.1.3/mainwindow.cpp0000644000000000000000000022372012227164102014130 0ustar 00000000000000/* Copyright © 2008-13 Qtrac Ltd. All rights reserved. This program or module is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. */ #include "aboutform.hpp" #include "generic.hpp" #include "helpform.hpp" #include "label.hpp" #include "lineedit.hpp" #include "optionsform.hpp" #include "mainwindow.hpp" #include "sequence_matcher.hpp" #include "textitem.hpp" #ifdef DEBUG #include #endif #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include MainWindow::MainWindow(const Debug debug, const InitialComparisonMode comparisonMode, const QString &filename1, const QString &filename2, const QString &language, QWidget *parent) : QMainWindow(parent), controlDockArea(Qt::RightDockWidgetArea), actionDockArea(Qt::RightDockWidgetArea), marginsDockArea(Qt::RightDockWidgetArea), zoningDockArea(Qt::RightDockWidgetArea), logDockArea(Qt::RightDockWidgetArea), cancel(false), saveAll(true), savePages(SaveBothPages), language(language), debug(debug), aboutForm(0), helpForm(0) { currentPath = QDir::homePath(); QSettings settings; pen.setStyle(Qt::NoPen); pen.setColor(Qt::red); pen = settings.value("Outline", pen).value(); brush.setColor(pen.color()); brush.setStyle(Qt::SolidPattern); brush = settings.value("Fill", brush).value(); showToolTips = settings.value("ShowToolTips", true).toBool(); combineTextHighlighting = settings.value("CombineTextHighlighting", true).toBool(); QPixmapCache::setCacheLimit(1000 * qBound(1, settings.value("CacheSizeMB", 25).toInt(), 100)); createWidgets(filename1, filename2); createCentralArea(); createDockWidgets(); createConnections(); restoreGeometry(settings.value("MainWindow/Geometry").toByteArray()); restoreState(settings.value("MainWindow/State").toByteArray()); controlDockLocationChanged(static_cast( settings.value("MainWindow/ControlDockArea", static_cast(controlDockArea)).toInt())); actionDockLocationChanged(static_cast( settings.value("MainWindow/ActionDockArea", static_cast(actionDockArea)).toInt())); zoningDockLocationChanged(static_cast( settings.value("MainWindow/ZoningDockArea", static_cast(zoningDockArea)).toInt())); marginsDockLocationChanged(static_cast( settings.value("MainWindow/MarginsDockArea", static_cast(marginsDockArea)).toInt())); controlDockWidget->resize(controlDockWidget->minimumSizeHint()); actionDockWidget->resize(actionDockWidget->minimumSizeHint()); zoningDockWidget->resize(zoningDockWidget->minimumSizeHint()); marginsDockWidget->resize(marginsDockWidget->minimumSizeHint()); //logDockWidget->resize(logDockWidget->minimumSizeHint()); setWindowTitle(tr("DiffPDF")); setWindowIcon(QIcon(":/icon.png")); compareComboBox->setCurrentIndex(comparisonMode); QMetaObject::invokeMethod(this, "initialize", Qt::QueuedConnection, Q_ARG(QString, filename1), Q_ARG(QString, filename2)); } void MainWindow::createWidgets(const QString &filename1, const QString &filename2) { setFile1Button = new QPushButton(tr("File #&1...")); setFile1Button->setToolTip(tr("

Choose the first (left hand) file " "to be compared.")); filename1LineEdit = new LineEdit; filename1LineEdit->setToolTip(tr("The first (left hand) file.")); filename1LineEdit->setAlignment(Qt::AlignVCenter|Qt::AlignRight); filename1LineEdit->setMinimumWidth(100); filename1LineEdit->setText(filename1); setFile2Button = new QPushButton(tr("File #&2...")); setFile2Button->setToolTip(tr("

Choose the second (right hand) file " "to be compared.")); filename2LineEdit = new LineEdit; filename2LineEdit->setToolTip(tr("The second (right hand) file.")); filename2LineEdit->setAlignment(Qt::AlignVCenter|Qt::AlignRight); filename2LineEdit->setMinimumWidth(100); filename2LineEdit->setText(filename2); comparePages1Label = new QLabel(tr("Pa&ges:")); pages1LineEdit = new QLineEdit; comparePages1Label->setBuddy(pages1LineEdit); pages1LineEdit->setToolTip(tr("

Pages can be specified using ranges " "such as 1-10, and multiple ranges can be used, e.g., " "1-10, 12-15, 20, 22, 35-39. This makes it " "straighforward to compare similar documents where one " "has one or more additional pages.

For example, if " "file1.pdf has pages 1-30 and file2.pdf has pages 1-31 " "with the extra page being page 14, the two page ranges " "would be set to 1-30 for file1.pdf and 1-13, 15-31 for " "file2.pdf.")); comparePages2Label = new QLabel(tr("&Pages:")); pages2LineEdit = new QLineEdit; comparePages2Label->setBuddy(pages2LineEdit); pages2LineEdit->setToolTip(pages1LineEdit->toolTip()); compareButton = new QPushButton(tr("&Compare")); compareButton->setEnabled(false); compareButton->setDefault(true); compareButton->setAutoDefault(true); compareButton->setToolTip(tr("

Click to compare (or re-compare) " "the documents—or to cancel a comparison that's " "in progress.")); compareComboBox = new QComboBox; compareComboBox->addItems(QStringList() << tr("Appearance") << tr("Characters") << tr("Words")); compareComboBox->setToolTip( tr("

If the Words comparison " "mode is chosen, then each page's text is compared " "word by word (best for alphabetic languages like " "English). " "If the Characters comparison mode is chosen, " "then each page's text is compared character by " "character (best for logographic languages like Chinese " "and Japanese). " "If the Appearance comparison mode is chosen " "then each page's visual appearance is compared. " "Comparing appearance can be slow for large documents " "and can also produce false positives—but is " "absolutely precise.")); compareLabel = new QLabel(tr("Co&mpare:")); compareLabel->setBuddy(compareComboBox); viewDiffLabel = new QLabel(tr("&View:")); viewDiffLabel->setToolTip(tr("

Shows each pair of pages which " "are different. The comparison is textual unless the " "Appearance comparison mode is chosen, in " "which case the comparison is done visually. " "Visual differences can occur if a paragraph is " "formated differently or if an embedded diagram or " "image has changed.")); viewDiffComboBox = new QComboBox; viewDiffComboBox->addItem(tr("(Not viewing)")); viewDiffLabel->setBuddy(viewDiffComboBox); viewDiffComboBox->setToolTip(viewDiffLabel->toolTip()); showLabel = new QLabel(tr("S&how:")); showLabel->setToolTip(tr("

In show Highlighting mode the " "pages are shown side by side with their differences " "highlighted. All the other modes are composition " "modes which show the first PDF as-is and the " "composition (blend) of the two PDFs.")); showComboBox = new QComboBox; showComboBox->addItem(tr("%1Highlighting%2") .arg(QChar(0xAB)).arg(QChar(0xBB)), -1); showComboBox->addItem(tr("Not Src Xor Dest"), QPainter::RasterOp_NotSourceXorDestination); showComboBox->addItem(tr("Difference"), QPainter::CompositionMode_Difference); showComboBox->addItem(tr("Exclusion"), QPainter::CompositionMode_Exclusion); showComboBox->addItem(tr("Src Xor Dest"), QPainter::RasterOp_SourceXorDestination); showLabel->setBuddy(showComboBox); showComboBox->setToolTip(showLabel->toolTip()); previousButton = new QPushButton(tr("Previo&us")); previousButton->setToolTip( "

Navigate to the previous pair of pages."); #if QT_VERSION >= 0x040600 previousButton->setIcon(QIcon(":/left.png")); #endif nextButton = new QPushButton(tr("Ne&xt")); nextButton->setToolTip("

Navigate to the next pair of pages."); #if QT_VERSION >= 0x040600 nextButton->setIcon(QIcon(":/right.png")); #endif zoomLabel = new QLabel(tr("&Zoom:")); zoomLabel->setToolTip(tr("

Determines the scale at which the " "pages are shown.")); zoomSpinBox = new QSpinBox; zoomLabel->setBuddy(zoomSpinBox); zoomSpinBox->setRange(20, 800); zoomSpinBox->setSuffix(tr(" %")); zoomSpinBox->setSingleStep(5); QSettings settings; zoomSpinBox->setValue(settings.value("Zoom", 100).toInt()); zoomSpinBox->setToolTip(zoomLabel->toolTip()); zoningGroupBox = new QGroupBox(tr("Zo&ning")); zoningGroupBox->setToolTip(tr("

Zoning is a computationally " "expensive experimental mode that can reduce or " "eliminate false positives particularly for pages " "that have tables or that mix alphabetic and " "logographic languages—it can also increase " "false positives! Zoning only applies to text " "comparisons.")); zoningGroupBox->setCheckable(true); zoningGroupBox->setChecked(false); columnsLabel = new QLabel(tr("Co&lumns:")); columnsSpinBox = new QSpinBox; columnsSpinBox->setRange(1, 16); columnsSpinBox->setValue(settings.value("Columns", 1).toInt()); columnsSpinBox->setAlignment(Qt::AlignVCenter|Qt::AlignRight); columnsSpinBox->setToolTip(tr("

Use this to tell DiffPDF how " "many columns the page has; this should improve the " "zoning.")); columnsLabel->setBuddy(columnsSpinBox); toleranceRLabel = new QLabel(tr("Tolerance/&R:")); toleranceRSpinBox = new QSpinBox; toleranceRSpinBox->setRange(4, 144); toleranceRSpinBox->setValue(settings.value("Tolerance/R", 8).toInt()); toleranceRSpinBox->setAlignment(Qt::AlignVCenter|Qt::AlignRight); toleranceRSpinBox->setToolTip(tr("

This is the maximum distance " "between text (word) rectangles for the rectangles to " "appear in the same zone.")); toleranceRLabel->setBuddy(toleranceRSpinBox); toleranceYLabel = new QLabel(tr("Tolerance/&Y:")); toleranceYSpinBox = new QSpinBox; toleranceYSpinBox->setRange(0, 32); toleranceYSpinBox->setValue(settings.value("Tolerance/Y", 10).toInt()); toleranceYSpinBox->setAlignment(Qt::AlignVCenter|Qt::AlignRight); toleranceYSpinBox->setToolTip(tr("

Text position y " "coordinates are rounded to the nearest Tolerance/Y " "value when zoning.")); toleranceYLabel->setBuddy(toleranceYSpinBox); showZonesCheckBox = new QCheckBox(tr("Sho&w Zones")); showZonesCheckBox->setToolTip(tr("

This shows the zones that are " "being used and may be helpful when adjusting " "tolerances. (Its original purpose was for debugging.)")); marginsGroupBox = new QGroupBox(tr("&Exclude Margins")); marginsGroupBox->setToolTip(tr("

If this is checked, anything " "outside non-zero margins is ignored when comparing.")); marginsGroupBox->setCheckable(true); marginsGroupBox->setChecked(settings.value("Margins/Exclude", false).toBool()); topMarginLabel = new QLabel(tr("&Top:")); topMarginSpinBox = new QSpinBox; topMarginSpinBox->setSuffix(" pt"); topMarginSpinBox->setValue(settings.value("Margins/Top", 0).toInt()); topMarginSpinBox->setAlignment(Qt::AlignVCenter|Qt::AlignRight); topMarginSpinBox->setToolTip(tr("

The top margin in points. " "Anything above this will be ignored.")); topMarginLabel->setBuddy(topMarginSpinBox); bottomMarginLabel = new QLabel(tr("&Bottom:")); bottomMarginSpinBox = new QSpinBox; bottomMarginSpinBox->setSuffix(" pt"); bottomMarginSpinBox->setValue(settings.value("Margins/Bottom", 0) .toInt()); bottomMarginSpinBox->setAlignment(Qt::AlignVCenter|Qt::AlignRight); bottomMarginSpinBox->setToolTip(tr("

The bottom margin in points. " "Anything below this will be ignored.")); bottomMarginLabel->setBuddy(bottomMarginSpinBox); leftMarginLabel = new QLabel(tr("Le&ft:")); leftMarginSpinBox = new QSpinBox; leftMarginSpinBox->setSuffix(" pt"); leftMarginSpinBox->setValue(settings.value("Margins/Left", 0).toInt()); leftMarginSpinBox->setAlignment(Qt::AlignVCenter|Qt::AlignRight); leftMarginSpinBox->setToolTip(tr("

The left margin in points. " "Anything left of this will be ignored.")); leftMarginLabel->setBuddy(leftMarginSpinBox); rightMarginLabel = new QLabel(tr("R&ight:")); rightMarginSpinBox = new QSpinBox; rightMarginSpinBox->setSuffix(" pt"); rightMarginSpinBox->setValue(settings.value("Margins/Right", 0) .toInt()); rightMarginSpinBox->setAlignment(Qt::AlignVCenter|Qt::AlignRight); rightMarginSpinBox->setToolTip(tr("

The right margin in points. " "Anything right of this will be ignored.")); rightMarginLabel->setBuddy(rightMarginSpinBox); statusLabel = new QLabel(tr("Choose files...")); statusLabel->setFrameStyle(QFrame::StyledPanel|QFrame::Sunken); statusLabel->setMaximumHeight(statusLabel->minimumSizeHint().height()); optionsButton = new QPushButton(tr("&Options...")); optionsButton->setToolTip(tr("Click to customize the application.")); saveButton = new QPushButton(tr("&Save As...")); saveButton->setToolTip(tr("Save the differences.")); helpButton = new QPushButton(tr("Help")); helpButton->setShortcut(tr("F1")); helpButton->setToolTip(tr("Click for basic help.")); aboutButton = new QPushButton(tr("&About")); aboutButton->setToolTip(tr("Click for copyright and credits.")); quitButton = new QPushButton(tr("&Quit")); quitButton->setToolTip(tr("Click to terminate the application.")); page1Label = new Label; page1Label->setAlignment(Qt::AlignTop|Qt::AlignLeft); page1Label->setToolTip(tr("

Shows the first (left hand) document's " "page that corresponds to the page shown in the " "View Difference combobox.")); page2Label = new Label; page2Label->setAlignment(Qt::AlignTop|Qt::AlignLeft); page2Label->setToolTip(tr("

Shows the second (right hand) " "document's page that corresponds to the page shown in " "the View Difference combobox.")); logEdit = new QPlainTextEdit; QList widgets; widgets << setFile1Button << filename1LineEdit << pages1LineEdit << page1Label << setFile2Button << filename2LineEdit << pages2LineEdit << page2Label << compareButton << compareComboBox << viewDiffLabel << viewDiffComboBox << showLabel << showComboBox << zoomLabel << zoomSpinBox << optionsButton << zoningGroupBox << columnsLabel << columnsSpinBox << toleranceRLabel << toleranceRSpinBox << toleranceYLabel << toleranceYSpinBox << marginsGroupBox << topMarginLabel << topMarginSpinBox << bottomMarginSpinBox << bottomMarginLabel << leftMarginLabel << leftMarginSpinBox << rightMarginLabel << rightMarginSpinBox << saveButton << helpButton << aboutButton << quitButton << logEdit << previousButton << nextButton << showZonesCheckBox; foreach (QWidget *widget, widgets) if (!widget->toolTip().isEmpty()) widget->installEventFilter(this); } void MainWindow::createCentralArea() { QHBoxLayout *topLeftLayout = new QHBoxLayout; topLeftLayout->addWidget(setFile1Button); topLeftLayout->addWidget(filename1LineEdit, 3); topLeftLayout->addWidget(comparePages1Label); topLeftLayout->addWidget(pages1LineEdit, 2); area1 = new QScrollArea; area1->setWidget(page1Label); area1->setWidgetResizable(true); QVBoxLayout *leftLayout = new QVBoxLayout; leftLayout->addLayout(topLeftLayout); leftLayout->addWidget(area1, 1); QWidget *leftWidget = new QWidget; leftWidget->setLayout(leftLayout); QHBoxLayout *topRightLayout = new QHBoxLayout; topRightLayout->addWidget(setFile2Button); topRightLayout->addWidget(filename2LineEdit, 3); topRightLayout->addWidget(comparePages2Label); topRightLayout->addWidget(pages2LineEdit, 2); area2 = new QScrollArea; area2->setWidget(page2Label); area2->setWidgetResizable(true); QVBoxLayout *rightLayout = new QVBoxLayout; rightLayout->addLayout(topRightLayout); rightLayout->addWidget(area2, 1); QWidget *rightWidget = new QWidget; rightWidget->setLayout(rightLayout); splitter = new QSplitter(Qt::Horizontal); splitter->addWidget(leftWidget); splitter->addWidget(rightWidget); QSettings settings; splitter->restoreState(settings.value("MainWindow/ViewSplitter") .toByteArray()); setCentralWidget(splitter); } void MainWindow::createDockWidgets() { setTabPosition(Qt::LeftDockWidgetArea|Qt::RightDockWidgetArea, QTabWidget::North); setTabPosition(Qt::TopDockWidgetArea|Qt::BottomDockWidgetArea, QTabWidget::West); QDockWidget::DockWidgetFeatures features = QDockWidget::DockWidgetMovable| QDockWidget::DockWidgetFloatable; controlDockWidget = new QDockWidget(tr("Controls"), this); controlDockWidget->setObjectName("Controls"); controlDockWidget->setFeatures(features); controlLayout = new QBoxLayout(QBoxLayout::TopToBottom); compareLayout = new QHBoxLayout; compareLayout->addWidget(compareLabel); compareLayout->addWidget(compareComboBox, 1); controlLayout->addLayout(compareLayout); QHBoxLayout *viewLayout = new QHBoxLayout; viewLayout->addWidget(viewDiffLabel); viewLayout->addWidget(viewDiffComboBox, 1); controlLayout->addLayout(viewLayout); QHBoxLayout *showLayout = new QHBoxLayout; showLayout->addWidget(showLabel); showLayout->addWidget(showComboBox, 1); controlLayout->addLayout(showLayout); QHBoxLayout *navigationLayout = new QHBoxLayout; navigationLayout->addWidget(previousButton); navigationLayout->addWidget(nextButton); controlLayout->addLayout(navigationLayout); QHBoxLayout *zoomLayout = new QHBoxLayout; zoomLayout->addWidget(zoomLabel); zoomLayout->addWidget(zoomSpinBox); controlLayout->addLayout(zoomLayout); controlLayout->addWidget(statusLabel); controlLayout->addStretch(); QWidget *widget = new QWidget; widget->setLayout(controlLayout); controlDockWidget->setWidget(widget); addDockWidget(controlDockArea, controlDockWidget); actionDockWidget = new QDockWidget(tr("Actions"), this); actionDockWidget->setObjectName("Actions"); actionDockWidget->setFeatures(features); actionLayout = new QBoxLayout(QBoxLayout::TopToBottom); actionLayout->addWidget(compareButton); QHBoxLayout *optionLayout = new QHBoxLayout; optionLayout->addWidget(optionsButton); optionLayout->addWidget(saveButton); actionLayout->addLayout(optionLayout); QHBoxLayout *helpLayout = new QHBoxLayout; helpLayout->addWidget(helpButton); helpLayout->addWidget(aboutButton); actionLayout->addLayout(helpLayout); actionLayout->addWidget(quitButton); actionLayout->addStretch(); widget = new QWidget; widget->setLayout(actionLayout); actionDockWidget->setWidget(widget); addDockWidget(actionDockArea, actionDockWidget); marginsDockWidget = new QDockWidget(tr("Margins"), this); marginsDockWidget->setObjectName("Margins"); marginsDockWidget->setFeatures(features| QDockWidget::DockWidgetClosable); marginsLayout = new QBoxLayout(QBoxLayout::TopToBottom); QHBoxLayout *topMarginLayout = new QHBoxLayout; topMarginLayout->addWidget(topMarginLabel); topMarginLayout->addWidget(topMarginSpinBox); marginsLayout->addLayout(topMarginLayout); QHBoxLayout *bottomMarginLayout = new QHBoxLayout; bottomMarginLayout->addWidget(bottomMarginLabel); bottomMarginLayout->addWidget(bottomMarginSpinBox); marginsLayout->addLayout(bottomMarginLayout); QHBoxLayout *leftMarginLayout = new QHBoxLayout; leftMarginLayout->addWidget(leftMarginLabel); leftMarginLayout->addWidget(leftMarginSpinBox); marginsLayout->addLayout(leftMarginLayout); QHBoxLayout *rightMarginLayout = new QHBoxLayout; rightMarginLayout->addWidget(rightMarginLabel); rightMarginLayout->addWidget(rightMarginSpinBox); marginsLayout->addLayout(rightMarginLayout); marginsLayout->addStretch(); marginsGroupBox->setLayout(marginsLayout); marginsDockWidget->setWidget(marginsGroupBox); addDockWidget(marginsDockArea, marginsDockWidget); zoningDockWidget = new QDockWidget(tr("Zoning"), this); zoningDockWidget->setObjectName("Zoning"); zoningDockWidget->setFeatures(features| QDockWidget::DockWidgetClosable); zoningLayout = new QBoxLayout(QBoxLayout::TopToBottom); QHBoxLayout *columnLayout = new QHBoxLayout; columnLayout->addWidget(columnsLabel); columnLayout->addWidget(columnsSpinBox); zoningLayout->addLayout(columnLayout); QHBoxLayout *toleranceLayout1 = new QHBoxLayout; toleranceLayout1->addWidget(toleranceRLabel); toleranceLayout1->addWidget(toleranceRSpinBox); zoningLayout->addLayout(toleranceLayout1); QHBoxLayout *toleranceLayout2 = new QHBoxLayout; toleranceLayout2->addWidget(toleranceYLabel); toleranceLayout2->addWidget(toleranceYSpinBox); zoningLayout->addLayout(toleranceLayout2); zoningLayout->addWidget(showZonesCheckBox); zoningLayout->addStretch(); zoningGroupBox->setLayout(zoningLayout); zoningDockWidget->setWidget(zoningGroupBox); addDockWidget(zoningDockArea, zoningDockWidget); logDockWidget = new QDockWidget(tr("Log"), this); logDockWidget->setObjectName("Log"); logDockWidget->setFeatures(features|QDockWidget::DockWidgetClosable); logDockWidget->setWidget(logEdit); addDockWidget(Qt::RightDockWidgetArea, logDockWidget); tabifyDockWidget(marginsDockWidget, controlDockWidget); tabifyDockWidget(logDockWidget, zoningDockWidget); tabifyDockWidget(zoningDockWidget, actionDockWidget); } void MainWindow::createConnections() { connect(area1->verticalScrollBar(), SIGNAL(valueChanged(int)), area2->verticalScrollBar(), SLOT(setValue(int))); connect(area2->verticalScrollBar(), SIGNAL(valueChanged(int)), area1->verticalScrollBar(), SLOT(setValue(int))); connect(area1->horizontalScrollBar(), SIGNAL(valueChanged(int)), area2->horizontalScrollBar(), SLOT(setValue(int))); connect(area2->horizontalScrollBar(), SIGNAL(valueChanged(int)), area1->horizontalScrollBar(), SLOT(setValue(int))); connect(filename1LineEdit, SIGNAL(textEdited(const QString&)), this, SLOT(updateUi())); connect(filename1LineEdit, SIGNAL(filenamesDropped(const QStringList&)), this, SLOT(setFiles1(const QStringList&))); connect(filename2LineEdit, SIGNAL(textEdited(const QString&)), this, SLOT(updateUi())); connect(filename2LineEdit, SIGNAL(filenamesDropped(const QStringList&)), this, SLOT(setFiles2(const QStringList&))); connect(page1Label, SIGNAL(filenamesDropped(const QStringList&)), this, SLOT(setFiles1(const QStringList&))); connect(page2Label, SIGNAL(filenamesDropped(const QStringList&)), this, SLOT(setFiles2(const QStringList&))); connect(compareComboBox, SIGNAL(currentIndexChanged(int)), this, SLOT(updateUi())); connect(compareComboBox, SIGNAL(currentIndexChanged(int)), this, SLOT(updateViews())); connect(viewDiffComboBox, SIGNAL(currentIndexChanged(int)), this, SLOT(updateViews(int))); connect(viewDiffComboBox, SIGNAL(currentIndexChanged(int)), this, SLOT(updateUi())); connect(showComboBox, SIGNAL(currentIndexChanged(int)), this, SLOT(updateViews())); connect(previousButton, SIGNAL(clicked()), this, SLOT(previousPages())); connect(nextButton, SIGNAL(clicked()), this, SLOT(nextPages())); connect(setFile1Button, SIGNAL(clicked()), this, SLOT(setFile1())); connect(setFile2Button, SIGNAL(clicked()), this, SLOT(setFile2())); connect(compareButton, SIGNAL(clicked()), this, SLOT(compare())); connect(zoomSpinBox, SIGNAL(valueChanged(int)), this, SLOT(updateViews())); connect(zoningGroupBox, SIGNAL(toggled(bool)), this, SLOT(updateUi())); connect(zoningGroupBox, SIGNAL(toggled(bool)), this, SLOT(updateViews())); connect(columnsSpinBox, SIGNAL(valueChanged(int)), this, SLOT(updateViews())); connect(toleranceRSpinBox, SIGNAL(valueChanged(int)), this, SLOT(updateViews())); connect(toleranceYSpinBox, SIGNAL(valueChanged(int)), this, SLOT(updateViews())); connect(showZonesCheckBox, SIGNAL(toggled(bool)), this, SLOT(updateViews())); connect(marginsGroupBox, SIGNAL(toggled(bool)), this, SLOT(updateUi())); connect(marginsGroupBox, SIGNAL(toggled(bool)), this, SLOT(updateViews())); connect(leftMarginSpinBox, SIGNAL(valueChanged(int)), this, SLOT(updateViews())); connect(rightMarginSpinBox, SIGNAL(valueChanged(int)), this, SLOT(updateViews())); connect(topMarginSpinBox, SIGNAL(valueChanged(int)), this, SLOT(updateViews())); connect(bottomMarginSpinBox, SIGNAL(valueChanged(int)), this, SLOT(updateViews())); connect(page1Label, SIGNAL(clicked(const QPoint&)), this, SLOT(setAMargin(const QPoint&))); connect(page2Label, SIGNAL(clicked(const QPoint&)), this, SLOT(setAMargin(const QPoint&))); connect(optionsButton, SIGNAL(clicked()), this, SLOT(options())); connect(saveButton, SIGNAL(clicked()), this, SLOT(save())); connect(helpButton, SIGNAL(clicked()), this, SLOT(help())); connect(aboutButton, SIGNAL(clicked()), this, SLOT(about())); connect(quitButton, SIGNAL(clicked()), this, SLOT(close())); connect(controlDockWidget, SIGNAL(dockLocationChanged(Qt::DockWidgetArea)), this, SLOT(controlDockLocationChanged(Qt::DockWidgetArea))); connect(actionDockWidget, SIGNAL(dockLocationChanged(Qt::DockWidgetArea)), this, SLOT(actionDockLocationChanged(Qt::DockWidgetArea))); connect(zoningDockWidget, SIGNAL(dockLocationChanged(Qt::DockWidgetArea)), this, SLOT(zoningDockLocationChanged(Qt::DockWidgetArea))); connect(marginsDockWidget, SIGNAL(dockLocationChanged(Qt::DockWidgetArea)), this, SLOT(marginsDockLocationChanged(Qt::DockWidgetArea))); connect(controlDockWidget, SIGNAL(topLevelChanged(bool)), this, SLOT(controlTopLevelChanged(bool))); connect(actionDockWidget, SIGNAL(topLevelChanged(bool)), this, SLOT(actionTopLevelChanged(bool))); connect(zoningDockWidget, SIGNAL(topLevelChanged(bool)), this, SLOT(zoningTopLevelChanged(bool))); connect(marginsDockWidget, SIGNAL(topLevelChanged(bool)), this, SLOT(marginsTopLevelChanged(bool))); connect(logDockWidget, SIGNAL(topLevelChanged(bool)), this, SLOT(logTopLevelChanged(bool))); } void MainWindow::initialize(const QString &filename1, const QString &filename2) { if (!filename1.isEmpty()) { setFile1(filename1); setFile2Button->setFocus(); if (!filename2.isEmpty()) { setFile2(filename2); compare(); } } else updateUi(); } void MainWindow::updateUi() { compareButton->setEnabled(!filename1LineEdit->text().isEmpty() && !filename2LineEdit->text().isEmpty()); saveButton->setEnabled(viewDiffComboBox->count() > 1); if (!showZonesCheckBox->isEnabled()) showZonesCheckBox->setChecked(false); if (compareComboBox->currentIndex() != CompareAppearance) showComboBox->setCurrentIndex(0); showComboBox->setEnabled(compareComboBox->currentIndex() == CompareAppearance); QPushButton *button = qobject_cast(focusWidget()); bool enableNavigationButton = (button == previousButton || button == nextButton); previousButton->setEnabled(viewDiffComboBox->count() > 1 && viewDiffComboBox->currentIndex() > 0); nextButton->setEnabled(viewDiffComboBox->count() > 1 && viewDiffComboBox->currentIndex() + 1 < viewDiffComboBox->count()); if (enableNavigationButton && !(previousButton->isEnabled() && nextButton->isEnabled())) { if (previousButton->isEnabled()) previousButton->setFocus(); else nextButton->setFocus(); } if (marginsGroupBox->isChecked()) { page1Label->setCursor(Qt::PointingHandCursor); page2Label->setCursor(Qt::PointingHandCursor); } else { page1Label->setCursor(Qt::ArrowCursor); page2Label->setCursor(Qt::ArrowCursor); } } void MainWindow::controlDockLocationChanged(Qt::DockWidgetArea area) { if (area == Qt::TopDockWidgetArea || area == Qt::BottomDockWidgetArea) { controlLayout->setDirection(QBoxLayout::LeftToRight); } else { controlLayout->setDirection(QBoxLayout::TopToBottom); } controlDockArea = area; } void MainWindow::actionDockLocationChanged(Qt::DockWidgetArea area) { if (area == Qt::TopDockWidgetArea || area == Qt::BottomDockWidgetArea) actionLayout->setDirection(QBoxLayout::LeftToRight); else actionLayout->setDirection(QBoxLayout::TopToBottom); actionDockArea = area; } void MainWindow::zoningDockLocationChanged(Qt::DockWidgetArea area) { if (area == Qt::TopDockWidgetArea || area == Qt::BottomDockWidgetArea) zoningLayout->setDirection(QBoxLayout::LeftToRight); else zoningLayout->setDirection(QBoxLayout::TopToBottom); zoningDockArea = area; } void MainWindow::marginsDockLocationChanged(Qt::DockWidgetArea area) { if (area == Qt::TopDockWidgetArea || area == Qt::BottomDockWidgetArea) marginsLayout->setDirection(QBoxLayout::LeftToRight); else marginsLayout->setDirection(QBoxLayout::TopToBottom); marginsDockArea = area; } void MainWindow::controlTopLevelChanged(bool floating) { controlLayout->setDirection(floating ? QBoxLayout::TopToBottom : QBoxLayout::LeftToRight); if (QWidget *widget = static_cast(controlLayout->parent())) widget->setFixedSize(floating ? widget->minimumSizeHint() : QSize(QWIDGETSIZE_MAX, QWIDGETSIZE_MAX)); controlDockWidget->setWindowTitle(floating ? tr("DiffPDF — Controls") : tr("Controls")); } void MainWindow::actionTopLevelChanged(bool floating) { actionLayout->setDirection(floating ? QBoxLayout::TopToBottom : QBoxLayout::LeftToRight); if (QWidget *widget = static_cast(actionLayout->parent())) widget->setFixedSize(floating ? widget->minimumSizeHint() : QSize(QWIDGETSIZE_MAX, QWIDGETSIZE_MAX)); actionDockWidget->setWindowTitle(floating ? tr("DiffPDF — Actions") : tr("Actions")); } void MainWindow::zoningTopLevelChanged(bool floating) { zoningLayout->setDirection(floating ? QBoxLayout::TopToBottom : QBoxLayout::LeftToRight); if (QWidget *widget = static_cast(zoningLayout->parent())) widget->setFixedSize(floating ? widget->minimumSizeHint() : QSize(QWIDGETSIZE_MAX, QWIDGETSIZE_MAX)); zoningDockWidget->setWindowTitle(floating ? tr("DiffPDF — Zoning") : tr("Zoning")); } void MainWindow::marginsTopLevelChanged(bool floating) { marginsLayout->setDirection(floating ? QBoxLayout::TopToBottom : QBoxLayout::LeftToRight); if (QWidget *widget = static_cast(marginsLayout->parent())) widget->setFixedSize(floating ? widget->minimumSizeHint() : QSize(QWIDGETSIZE_MAX, QWIDGETSIZE_MAX)); marginsDockWidget->setWindowTitle(floating ? tr("DiffPDF — Margins") : tr("Margins")); } void MainWindow::logTopLevelChanged(bool floating) { logDockWidget->setWindowTitle(floating ? tr("DiffPDF — Log") : tr("Log")); } void MainWindow::previousPages() { int i = viewDiffComboBox->currentIndex(); if (i > 0) viewDiffComboBox->setCurrentIndex(i - 1); } void MainWindow::nextPages() { int i = viewDiffComboBox->currentIndex(); if (i + 1 < viewDiffComboBox->count()) viewDiffComboBox->setCurrentIndex(i + 1); } void MainWindow::updateViews(int index) { if (index == 0) { page1Label->clear(); page2Label->clear(); return; } else if (index == -1) index = viewDiffComboBox->currentIndex(); PagePair pair = viewDiffComboBox->itemData(index).value(); if (pair.isNull()) return; QString filename1 = filename1LineEdit->text(); PdfDocument pdf1 = getPdf(filename1); if (!pdf1) return; PdfPage page1(pdf1->page(pair.left)); if (!page1) return; QString filename2 = filename2LineEdit->text(); PdfDocument pdf2 = getPdf(filename2); if (!pdf2) return; PdfPage page2(pdf2->page(pair.right)); if (!page2) return; const QPair keys = cacheKeys(index, pair); const QPair pixmaps = populatePixmaps(pdf1, page1, pdf2, page2, pair.hasVisualDifference, keys.first, keys.second); page1Label->setPixmap(pixmaps.first); page2Label->setPixmap(pixmaps.second); if (showZonesCheckBox->isChecked()) showZones(); if (marginsGroupBox->isChecked()) showMargins(); } const QPair MainWindow::cacheKeys(const int index, const PagePair &pair) const { int comparisonMode; if (compareComboBox->currentIndex() == CompareAppearance) comparisonMode = showComboBox->currentIndex(); else comparisonMode = -compareComboBox->currentIndex(); QString zoning; if (zoningGroupBox->isChecked()) zoning = QString("%1:%2:%3").arg(columnsSpinBox->value()) .arg(toleranceRSpinBox->value()) .arg(toleranceYSpinBox->value()); QString margins; if (marginsGroupBox->isChecked()) margins = QString("%1:%2:%3:%4").arg(topMarginSpinBox->value()) .arg(bottomMarginSpinBox->value()) .arg(leftMarginSpinBox->value()) .arg(rightMarginSpinBox->value()); const QString key = QString("%1:%2:%3:%4:%5").arg(index) .arg(zoomSpinBox->value()).arg(comparisonMode).arg(zoning) .arg(margins); const QString key1 = QString("1:%1:%2:%3").arg(key).arg(pair.left) .arg(filename1LineEdit->text()); const QString key2 = QString("2:%1:%2:%3").arg(key).arg(pair.right) .arg(filename2LineEdit->text()); return qMakePair(key1, key2); } const QPair MainWindow::populatePixmaps( const PdfDocument &pdf1, const PdfPage &page1, const PdfDocument &pdf2, const PdfPage &page2, bool hasVisualDifference, const QString &key1, const QString &key2) { QPixmap pixmap1; QPixmap pixmap2; #if QT_VERSION >= 0x040600 if (!QPixmapCache::find(key1, &pixmap1) || !QPixmapCache::find(key2, &pixmap2)) { #else if (!QPixmapCache::find(key1, pixmap1) || !QPixmapCache::find(key2, pixmap2)) { #endif QApplication::setOverrideCursor(QCursor(Qt::WaitCursor)); const int DPI = static_cast(POINTS_PER_INCH * (zoomSpinBox->value() / 100.0)); const bool compareText = compareComboBox->currentIndex() != CompareAppearance; QImage plainImage1; QImage plainImage2; if (hasVisualDifference || !compareText) { plainImage1 = page1->renderToImage(DPI, DPI); plainImage2 = page2->renderToImage(DPI, DPI); } pdf1->setRenderHint(Poppler::Document::Antialiasing); pdf1->setRenderHint(Poppler::Document::TextAntialiasing); pdf2->setRenderHint(Poppler::Document::Antialiasing); pdf2->setRenderHint(Poppler::Document::TextAntialiasing); QImage image1 = page1->renderToImage(DPI, DPI); QImage image2 = page2->renderToImage(DPI, DPI); if (compareComboBox->currentIndex() != CompareAppearance || showComboBox->currentIndex() == 0) { QPainterPath highlighted1; QPainterPath highlighted2; if (hasVisualDifference || !compareText) computeVisualHighlights(&highlighted1, &highlighted2, plainImage1, plainImage2); else computeTextHighlights(&highlighted1, &highlighted2, page1, page2, DPI); if (!highlighted1.isEmpty()) paintOnImage(highlighted1, &image1); if (!highlighted2.isEmpty()) paintOnImage(highlighted2, &image2); if (highlighted1.isEmpty() && highlighted2.isEmpty()) { QFont font("Helvetica", 14); font.setOverline(true); font.setUnderline(true); highlighted1.addText(DPI / 4, DPI / 4, font, tr("DiffPDF: False Positive")); paintOnImage(highlighted1, &image1); } pixmap1 = QPixmap::fromImage(image1); pixmap2 = QPixmap::fromImage(image2); } else { pixmap1 = QPixmap::fromImage(image1); QImage composed(image1.size(), image1.format()); QPainter painter(&composed); painter.setCompositionMode(QPainter::CompositionMode_Source); painter.fillRect(composed.rect(), Qt::transparent); painter.setCompositionMode( QPainter::CompositionMode_SourceOver); painter.drawImage(0, 0, image1); painter.setCompositionMode( static_cast( showComboBox->itemData( showComboBox->currentIndex()).toInt())); painter.drawImage(0, 0, image2); painter.setCompositionMode( QPainter::CompositionMode_DestinationOver); painter.fillRect(composed.rect(), Qt::white); painter.end(); pixmap2 = QPixmap::fromImage(composed); } QPixmapCache::insert(key1, pixmap1); QPixmapCache::insert(key2, pixmap2); QApplication::restoreOverrideCursor(); } return qMakePair(pixmap1, pixmap2); } void MainWindow::computeTextHighlights(QPainterPath *highlighted1, QPainterPath *highlighted2, const PdfPage &page1, const PdfPage &page2, const int DPI) { const bool ComparingWords = compareComboBox->currentIndex() == CompareWords; QRectF rect1; QRectF rect2; QSettings settings; const int OVERLAP = settings.value("Overlap", 5).toInt(); const bool COMBINE = settings.value("CombineTextHighlighting", true) .toBool(); QRectF rect; if (marginsGroupBox->isChecked()) rect = pointRectForMargins(page1->pageSize()); const TextBoxList list1 = getTextBoxes(page1, rect); const TextBoxList list2 = getTextBoxes(page2, rect); TextItems items1 = ComparingWords ? getWords(list1) : getCharacters(list1); TextItems items2 = ComparingWords ? getWords(list2) : getCharacters(list2); const int ToleranceY = toleranceYSpinBox->value(); if (zoningGroupBox->isChecked()) { const int ToleranceR = toleranceRSpinBox->value(); const int Columns = columnsSpinBox->value(); items1.columnZoneYxOrder(page1->pageSize().width(), ToleranceR, ToleranceY, Columns); items2.columnZoneYxOrder(page2->pageSize().width(), ToleranceR, ToleranceY, Columns); } if (debug >= DebugShowTexts) { const bool Yx = debug == DebugShowTextsAndYX; items1.debug(1, ToleranceY, ComparingWords, Yx); items2.debug(2, ToleranceY, ComparingWords, Yx); } SequenceMatcher matcher(items1.texts(), items2.texts()); RangesPair rangesPair = computeRanges(&matcher); rangesPair = invertRanges(rangesPair.first, items1.count(), rangesPair.second, items2.count()); foreach (int index, rangesPair.first) addHighlighting(&rect1, highlighted1, items1.at(index).rect, OVERLAP, DPI, COMBINE); if (!rect1.isNull() && !rangesPair.first.isEmpty()) highlighted1->addRect(rect1); foreach (int index, rangesPair.second) addHighlighting(&rect2, highlighted2, items2.at(index).rect, OVERLAP, DPI, COMBINE); if (!rect2.isNull() && !rangesPair.second.isEmpty()) highlighted2->addRect(rect2); } void MainWindow::addHighlighting(QRectF *bigRect, QPainterPath *highlighted, const QRectF wordOrCharRect, const int OVERLAP, const int DPI, const bool COMBINE) { QRectF rect = wordOrCharRect; scaleRect(DPI, &rect); if (COMBINE && rect.adjusted(-OVERLAP, -OVERLAP, OVERLAP, OVERLAP) .intersects(*bigRect)) *bigRect = bigRect->united(rect); else { highlighted->addRect(*bigRect); *bigRect = rect; } } void MainWindow::computeVisualHighlights(QPainterPath *highlighted1, QPainterPath *highlighted2, const QImage &plainImage1, const QImage &plainImage2) { QSettings settings; const int SQUARE_SIZE = settings.value("SquareSize", 10).toInt(); QRect box; if (marginsGroupBox->isChecked()) box = pixelRectForMargins(plainImage1.size()); QRect target; for (int x = 0; x < plainImage1.width(); x += SQUARE_SIZE) { for (int y = 0; y < plainImage1.height(); y += SQUARE_SIZE) { const QRect rect(x, y, SQUARE_SIZE, SQUARE_SIZE); if (!box.isEmpty() && !box.contains(rect)) continue; QImage temp1 = plainImage1.copy(rect); QImage temp2 = plainImage2.copy(rect); if (temp1 != temp2) { if (rect.adjusted(-1, -1, 1, 1).intersects(target)) target = target.united(rect); else { highlighted1->addRect(target); highlighted2->addRect(target); target = rect; } } } } if (!target.isNull()) { highlighted1->addRect(target); highlighted2->addRect(target); } } QRect MainWindow::pixelRectForMargins(const QSize &size) { const int DPI = static_cast(POINTS_PER_INCH * (zoomSpinBox->value() / 100.0)); int top = pixelOffsetForPointValue(DPI, topMarginSpinBox->value()); int left = pixelOffsetForPointValue(DPI, leftMarginSpinBox->value()); int right = pixelOffsetForPointValue(DPI, rightMarginSpinBox->value()); int bottom = pixelOffsetForPointValue(DPI, bottomMarginSpinBox->value()); return QRect(QPoint(left, top), QPoint(size.width() - right, size.height() - bottom)); } void MainWindow::paintOnImage(const QPainterPath &path, QImage *image) { QPen pen_(pen); QBrush brush_(brush); QColor color = pen.color(); QSettings settings; const qreal Alpha = settings.value("Opacity", 13).toInt() / 100.0; color.setAlphaF(Alpha); pen_.setColor(color); brush_.setColor(color); QPainter painter(image); painter.setRenderHint(QPainter::Antialiasing); painter.setPen(pen_); painter.setBrush(brush_); const int SQUARE_SIZE = settings.value("SquareSize", 10).toInt(); const double RULE_WIDTH = settings.value("RuleWidth", 1.5).toDouble(); QRectF rect = path.boundingRect(); if (rect.width() < SQUARE_SIZE && rect.height() < SQUARE_SIZE) { rect.setHeight(SQUARE_SIZE); rect.setWidth(SQUARE_SIZE); painter.drawRect(rect); if (!qFuzzyCompare(RULE_WIDTH, 0.0)) { painter.setPen(QPen(pen.color())); painter.drawRect(0, rect.y(), RULE_WIDTH, rect.height()); } } else { QPainterPath path_(path); path_.setFillRule(Qt::WindingFill); painter.drawPath(path_); if (!qFuzzyCompare(RULE_WIDTH, 0.0)) { painter.setPen(QPen(pen.color())); QList polygons = path_.toFillPolygons(); foreach (const QPolygonF &polygon, polygons) { const QRectF rect = polygon.boundingRect(); painter.drawRect(0, rect.y(), RULE_WIDTH, rect.height()); } } } painter.end(); } void MainWindow::closeEvent(QCloseEvent*) { QSettings settings; settings.setValue("MainWindow/Geometry", saveGeometry()); settings.setValue("MainWindow/State", saveState()); settings.setValue("MainWindow/ControlDockArea", static_cast(controlDockArea)); settings.setValue("MainWindow/ActionDockArea", static_cast(actionDockArea)); settings.setValue("MainWindow/ZoningDockArea", static_cast(zoningDockArea)); settings.setValue("MainWindow/MarginsDockArea", static_cast(marginsDockArea)); settings.setValue("MainWindow/LogDockArea", static_cast(logDockArea)); settings.setValue("MainWindow/ViewSplitter", splitter->saveState()); settings.setValue("ShowToolTips", showToolTips); settings.setValue("CombineTextHighlighting", combineTextHighlighting); settings.setValue("Zoom", zoomSpinBox->value()); settings.setValue("Columns", columnsSpinBox->value()); settings.setValue("Tolerance/R", toleranceRSpinBox->value()); settings.setValue("Tolerance/Y", toleranceYSpinBox->value()); settings.setValue("Outline", pen); settings.setValue("Fill", brush); settings.setValue("InitialComparisonMode", compareComboBox->currentIndex()); settings.setValue("Margins/Exclude", marginsGroupBox->isChecked()); settings.setValue("Margins/Left", leftMarginSpinBox->value()); settings.setValue("Margins/Right", rightMarginSpinBox->value()); settings.setValue("Margins/Top", topMarginSpinBox->value()); settings.setValue("Margins/Bottom", bottomMarginSpinBox->value()); QMainWindow::close(); } bool MainWindow::eventFilter(QObject *object, QEvent *event) { if (event->type() == QEvent::ToolTip && !showToolTips) return true; return QMainWindow::eventFilter(object, event); } void MainWindow::setFiles1(const QStringList &filenames) { if (filenames.count() && !filenames.at(0).isEmpty()) { setFile1(filenames.at(0)); if (filenames.count() > 1 && !filenames.at(1).isEmpty()) setFile2(filenames.at(1)); } } void MainWindow::setFiles2(const QStringList &filenames) { if (filenames.count() && !filenames.at(0).isEmpty()) { setFile2(filenames.at(0)); if (filenames.count() > 1 && !filenames.at(1).isEmpty()) setFile1(filenames.at(1)); } } void MainWindow::setFile1(QString filename) { if (filename.isEmpty()) filename = QFileDialog::getOpenFileName(this, tr("DiffPDF — Choose File #1"), currentPath, tr("PDF files (*.pdf)")); if (!filename.isEmpty()) { if (filename == filename2LineEdit->text()) { QMessageBox::warning(this, tr("DiffPDF — Error"), tr("Cannot compare a file to itself.")); return; } filename1LineEdit->setText(filename); if (!filename2LineEdit->text().isEmpty()) page1Label->setText(tr("

DiffPDF: Click Compare
" "or change File #2.

")); else page1Label->setText(tr("

DiffPDF: Choose File #2.

")); page2Label->clear(); updateUi(); int page_count = writeFileInfo(filename); pages1LineEdit->setText(tr("1-%1").arg(page_count)); currentPath = QFileInfo(filename).canonicalPath(); setFile2Button->setFocus(); if (filename2LineEdit->text().isEmpty()) statusLabel->setText(tr("Choose second file")); else statusLabel->setText(tr("Ready to compare")); } } void MainWindow::setFile2(QString filename) { if (filename.isEmpty()) filename = QFileDialog::getOpenFileName(this, tr("DiffPDF — Choose File #2"), currentPath, tr("PDF files (*.pdf)")); if (!filename.isEmpty()) { if (filename == filename1LineEdit->text()) { QMessageBox::warning(this, tr("DiffPDF — Error"), tr("Cannot compare a file to itself.")); return; } filename2LineEdit->setText(filename); if (!filename1LineEdit->text().isEmpty()) page2Label->setText(tr("

DiffPDF: Click Compare
" "or change File #1.

")); else page2Label->setText(tr("

DiffPDF: Choose File #1.

")); page1Label->clear(); updateUi(); int page_count = writeFileInfo(filename); pages2LineEdit->setText(tr("1-%1").arg(page_count)); currentPath = QFileInfo(filename).canonicalPath(); compareButton->setFocus(); if (filename1LineEdit->text().isEmpty()) statusLabel->setText(tr("Choose first file")); else statusLabel->setText(tr("Ready to compare")); } } PdfDocument MainWindow::getPdf(const QString &filename) { PdfDocument pdf(Poppler::Document::load(filename)); if (!pdf) QMessageBox::warning(this, tr("DiffPDF — Error"), tr("Cannot load '%1'.").arg(filename)); else if (pdf->isLocked()) { QMessageBox::warning(this, tr("DiffPDF — Error"), tr("Cannot read a locked PDF ('%1').").arg(filename)); #if QT_VERSION >= 0x040600 pdf.clear(); #else pdf.reset(); #endif } return pdf; } int MainWindow::writeFileInfo(const QString &filename) { int page_count = 0; PdfDocument pdf = getPdf(filename); if (!pdf) return page_count; writeLine(tr("%1").arg(filename)); foreach (const QString &key, pdf->infoKeys()) { if (key == "CreationDate" || key == "ModDate") continue; writeLine(tr("%1: %2.").arg(key).arg(pdf->info(key))); } QDateTime created = pdf->date("CreationDate"); QDateTime modified = pdf->date("ModDate"); if (created != modified) writeLine(tr("Created: %1, last modified %2.") .arg(created.toString()) .arg(modified.toString())); else writeLine(tr("Created: %1.").arg(created.toString())); page_count = pdf->numPages(); writeLine(tr("Page count: %1.").arg(page_count)); if (page_count > 0) { const double PointToMM = 0.3527777777; PdfPage page1(pdf->page(0)); QSize size = page1->pageSize(); writeLine(tr("Page size: %1pt x %2pt (%3mm x %4mm).") .arg(size.width()).arg(size.height()) .arg(qRound(size.width() * PointToMM)) .arg(qRound(size.height() * PointToMM))); topMarginSpinBox->setRange(0, (size.height() / 2) - 10); bottomMarginSpinBox->setRange(0, (size.height() / 2) - 10); leftMarginSpinBox->setRange(0, (size.width() / 2) - 10); rightMarginSpinBox->setRange(0, (size.width() / 2) - 10); } return page_count; } void MainWindow::writeLine(const QString &text) { logEdit->appendHtml(text); logEdit->ensureCursorVisible(); } void MainWindow::writeError(const QString &text) { logEdit->appendHtml(tr("%1").arg(text)); logEdit->ensureCursorVisible(); } QList MainWindow::getPageList(int which, PdfDocument pdf) { // Poppler has 0-based page numbers; the UI has 1-based page numbers QLineEdit *pagesEdit = (which == 1 ? pages1LineEdit : pages2LineEdit); bool error = false; QList pages; QString page_string = pagesEdit->text(); page_string = page_string.replace(QRegExp("\\s+"), ""); QStringList page_list = page_string.split(","); bool ok; foreach (const QString &page, page_list) { int hyphen = page.indexOf("-"); if (hyphen > -1) { int p1 = page.left(hyphen).toInt(&ok); if (!ok || p1 < 1) { error = true; break; } int p2 = page.mid(hyphen + 1).toInt(&ok); if (!ok || p2 < 1 || p2 < p1) { error = true; break; } if (p1 == p2) pages.append(p1 - 1); else { for (int p = p1; p <= p2; ++p) { if (p > pdf->numPages()) break; pages.append(p - 1); } } } else { int p = page.toInt(&ok); if (ok && p > 0 && p <= pdf->numPages()) pages.append(p - 1); else { error = true; break; } } } if (error) { pages.clear(); writeError(tr("Failed to understand page range '%1'.") .arg(pagesEdit->text())); pagesEdit->setText(tr("1-%1").arg(pdf->numPages())); for (int page = 0; page < pdf->numPages(); ++page) pages.append(page); } return pages; } void MainWindow::compare() { if (compareButton->text() == tr("&Cancel")) { cancel = true; compareButton->setText(tr("&Compare")); compareButton->setEnabled(true); return; } cancel = false; QString filename1 = filename1LineEdit->text(); PdfDocument pdf1 = getPdf(filename1); if (!pdf1) return; QString filename2 = filename2LineEdit->text(); PdfDocument pdf2 = getPdf(filename2); if (!pdf2) { return; } comparePrepareUi(); QTime time; time.start(); const QPair pair = comparePages(filename1, pdf1, filename2, pdf2); compareUpdateUi(pair, time.elapsed()); } void MainWindow::comparePrepareUi() { QApplication::setOverrideCursor(QCursor(Qt::WaitCursor)); compareButton->setText(tr("&Cancel")); compareButton->setEnabled(true); compareButton->setFocus(); viewDiffComboBox->clear(); viewDiffComboBox->addItem(tr("(Not viewing)")); saveButton->setEnabled(false); statusLabel->setText(tr("Ready")); } const QPair MainWindow::comparePages(const QString &filename1, const PdfDocument &pdf1, const QString &filename2, const PdfDocument &pdf2) { QList pages1 = getPageList(1, pdf1); QList pages2 = getPageList(2, pdf2); int total = qMin(pages1.count(), pages2.count()); int number = 0; int index = 0; while (!pages1.isEmpty() && !pages2.isEmpty()) { int p1 = pages1.takeFirst(); PdfPage page1(pdf1->page(p1)); if (!page1) { writeError(tr("Failed to read page %1 from '%2'.") .arg(p1 + 1).arg(filename1)); continue; } int p2 = pages2.takeFirst(); PdfPage page2(pdf2->page(p2)); if (!page2) { writeError(tr("Failed to read page %1 from '%2'.") .arg(p2 + 1).arg(filename2)); continue; } writeLine(tr("Comparing: %1 vs. %2.").arg(p1 + 1).arg(p2 + 1)); QApplication::processEvents(); if (cancel) { writeError(tr("Cancelled.")); break; } Difference difference = getTheDifference(page1, page2); if (difference != NoDifference) { QVariant v; v.setValue(PagePair(p1, p2, difference == VisualDifference)); viewDiffComboBox->addItem(tr("%1 vs. %2 %3 %4") .arg(p1 + 1).arg(p2 + 1).arg(QChar(0x2022)) .arg(++index), v); } statusLabel->setText(tr("Comparing %1/%2").arg(++number) .arg(total)); } return qMakePair(number, total); } void MainWindow::compareUpdateUi(const QPair &pair, const int millisec) { const int differ = viewDiffComboBox->count() - 1; if (!cancel) { if (millisec > 1000) writeLine(tr("Completed in %1 seconds.") .arg(millisec / 1000.0, 0, 'f', 2)); if (viewDiffComboBox->count() > 1) { if (viewDiffComboBox->count() == 2) writeLine(tr("Files differ on 1 page " "(%1 page%2 compared).") .arg(pair.first) .arg(pair.first == 1 ? tr(" was") : tr("s were"))); else writeLine(tr("Files differ on %1 pages " "(%2 page%3 compared).") .arg(differ).arg(pair.first) .arg(pair.first == 1 ? tr(" was") : tr("s were"))); viewDiffComboBox->setFocus(); viewDiffComboBox->setCurrentIndex(1); } else { writeLine(tr("The PDFs appear to be the same.")); const QString message(tr("

" "DiffPDF: The PDFs appear to be the same.

")); page1Label->setText(message); page2Label->setText(message); } } compareButton->setText(tr("&Compare")); if (differ == 1) // Separated the cases for ease of translation statusLabel->setText(tr("1 differs %1/%2 compared").arg(pair.first) .arg(pair.second)); else statusLabel->setText(tr("%1 differ %2/%3 compared").arg(differ) .arg(pair.first).arg(pair.second)); saveButton->setEnabled(true); updateUi(); if (!cancel) viewDiffComboBox->setFocus(); QApplication::restoreOverrideCursor(); } MainWindow::Difference MainWindow::getTheDifference(PdfPage page1, PdfPage page2) { QRectF rect; if (marginsGroupBox->isChecked()) rect = pointRectForMargins(page1->pageSize()); const TextBoxList list1 = getTextBoxes(page1, rect); const TextBoxList list2 = getTextBoxes(page2, rect); if (list1.count() != list2.count()) return TextualDifference; for (int i = 0; i < list1.count(); ++i) if (list1[i]->text() != list2[i]->text()) return TextualDifference; if (compareComboBox->currentIndex() == CompareAppearance) { int x = -1; int y = -1; int width = -1; int height = -1; if (marginsGroupBox->isChecked()) computeImageOffsets(page1->pageSize(), &x, &y, &width, &height); QImage image1 = page1->renderToImage(POINTS_PER_INCH, POINTS_PER_INCH, x, y, width, height); QImage image2 = page2->renderToImage(POINTS_PER_INCH, POINTS_PER_INCH, x, y, width, height); if (image1 != image2) return VisualDifference; } return NoDifference; } QRectF MainWindow::pointRectForMargins(const QSize &size) { return rectForMargins(size.width(), size.height(), topMarginSpinBox->value(), bottomMarginSpinBox->value(), leftMarginSpinBox->value(), rightMarginSpinBox->value()); } void MainWindow::computeImageOffsets(const QSize &size, int *x, int *y, int *width, int *height) { const int DPI = static_cast(POINTS_PER_INCH * (zoomSpinBox->value() / 100.0)); *y = pixelOffsetForPointValue(DPI, topMarginSpinBox->value()); *x = pixelOffsetForPointValue(DPI, leftMarginSpinBox->value()); *width = pixelOffsetForPointValue(DPI, size.width() - (leftMarginSpinBox->value() + rightMarginSpinBox->value())); *height = pixelOffsetForPointValue(DPI, size.height() - (topMarginSpinBox->value() + bottomMarginSpinBox->value())); } void MainWindow::options() { QSettings settings; qreal ruleWidth = settings.value("RuleWidth", 1.5).toDouble(); int cacheSize = QPixmapCache::cacheLimit() / 1000; int alpha = settings.value("Opacity", 13).toInt(); int squareSize = settings.value("SquareSize", 10).toInt(); OptionsForm form(&pen, &brush, &ruleWidth, &showToolTips, &combineTextHighlighting, &cacheSize, &alpha, &squareSize, this); if (form.exec()) { settings.setValue("RuleWidth", ruleWidth); settings.setValue("CombineTextHighlighting", combineTextHighlighting); settings.setValue("CacheSizeMB", cacheSize); settings.setValue("Opacity", alpha); settings.setValue("SquareSize", squareSize); QPixmapCache::clear(); QPixmapCache::setCacheLimit(1000 * cacheSize); updateViews(); } } void MainWindow::save() { SaveForm form(currentPath, &saveFilename, &saveAll, &savePages, this); if (form.exec()) { QString filename1 = filename1LineEdit->text(); PdfDocument pdf1 = getPdf(filename1); if (!pdf1) return; QString filename2 = filename2LineEdit->text(); PdfDocument pdf2 = getPdf(filename2); if (!pdf2) return; saveButton->setEnabled(false); QApplication::processEvents(); const int originalIndex = viewDiffComboBox->currentIndex(); int start = originalIndex; int end = originalIndex + 1; if (saveAll) { start = 0; end = viewDiffComboBox->count(); } QString header; const QChar bullet(0x2022); if (savePages == SaveLeftPages) header = tr("DiffPDF %1 %2 %1 %3").arg(bullet) .arg(filename1) .arg(QDate::currentDate().toString(Qt::ISODate)); else if (savePages == SaveRightPages) header = tr("DiffPDF %1 %2 %1 %3").arg(bullet) .arg(filename2) .arg(QDate::currentDate().toString(Qt::ISODate)); else header = tr("DiffPDF %1 %2 vs. %3 %1 %4").arg(bullet) .arg(filename1).arg(filename2) .arg(QDate::currentDate().toString(Qt::ISODate)); if (saveFilename.toLower().endsWith(".pdf")) saveAsPdf(start, end, pdf1, pdf2, header); else saveAsImages(start, end, pdf1, pdf2, header); updateViews(originalIndex); if (saveFilename.toLower().endsWith(".pdf")) writeLine(tr("Saved %1").arg(saveFilename)); saveButton->setEnabled(true); } } void MainWindow::saveAsImages(const int start, const int end, const PdfDocument &pdf1, const PdfDocument &pdf2, const QString &header) { PdfPage page1(pdf1->page(0)); if (!page1) return; PdfPage page2(pdf2->page(0)); if (!page2) return; int width = 2 * (savePages == SaveBothPages ? page1->pageSize().width() + page2->pageSize().width() : page1->pageSize().width()); const int y = fontMetrics().lineSpacing(); const int height = (2 * page1->pageSize().height()) - y; const int gap = 30; const QRect rect(0, 0, width, height); if (savePages == SaveBothPages) width = (width / 2) - gap; const QRect leftRect(0, y, width, height); const QRect rightRect(width + gap, y, width, height); int count = 0; QString imageFilename = saveFilename; int i = imageFilename.lastIndexOf("."); if (i > -1) imageFilename.insert(i, "-%1"); else imageFilename += "-%1.png"; for (int index = start; index < end; ++index) { QImage image(rect.size(), QImage::Format_ARGB32); QPainter painter(&image); painter.setRenderHints(QPainter::Antialiasing| QPainter::TextAntialiasing|QPainter::SmoothPixmapTransform); painter.setFont(QFont("Helvetica", 11)); painter.setPen(Qt::darkCyan); painter.fillRect(rect, Qt::white); if (!paintSaveAs(&painter, index, pdf1, pdf2, header, rect, leftRect, rightRect)) continue; QString filename = imageFilename; filename = filename.arg(++count); if (image.save(filename)) writeLine(tr("Saved %1").arg(filename)); else writeLine(tr("Failed to save %1").arg(filename)); } } void MainWindow::saveAsPdf(const int start, const int end, const PdfDocument &pdf1, const PdfDocument &pdf2, const QString &header) { QPrinter printer(QPrinter::HighResolution); printer.setOutputFileName(saveFilename); printer.setOutputFormat(QPrinter::PdfFormat); printer.setColorMode(QPrinter::Color); printer.setCreator(tr("DiffPDF")); printer.setOrientation(savePages == SaveBothPages ? QPrinter::Landscape : QPrinter::Portrait); QPainter painter(&printer); painter.setRenderHints(QPainter::Antialiasing| QPainter::TextAntialiasing|QPainter::SmoothPixmapTransform); painter.setFont(QFont("Helvetica", 11)); painter.setPen(Qt::darkCyan); const QRect rect(0, 0, painter.viewport().width(), painter.fontMetrics().height()); const int y = painter.fontMetrics().lineSpacing(); const int height = painter.viewport().height() - y; const int gap = 30; int width = (painter.viewport().width() / 2) - gap; if (savePages != SaveBothPages) width = painter.viewport().width(); const QRect leftRect(0, y, width, height); const QRect rightRect(width + gap, y, width, height); for (int index = start; index < end; ++index) { if (!paintSaveAs(&painter, index, pdf1, pdf2, header, rect, leftRect, rightRect)) continue; if (index + 1 < end) printer.newPage(); } } bool MainWindow::paintSaveAs(QPainter *painter, const int index, const PdfDocument &pdf1, const PdfDocument &pdf2, const QString &header, const QRect &rect, const QRect &leftRect, const QRect &rightRect) { PagePair pair = viewDiffComboBox->itemData(index) .value(); if (pair.isNull()) return false; PdfPage page1(pdf1->page(pair.left)); if (!page1) return false; PdfPage page2(pdf2->page(pair.right)); if (!page2) return false; const QPair keys = cacheKeys(index, pair); const QPair pixmaps = populatePixmaps(pdf1, page1, pdf2, page2, pair.hasVisualDifference, keys.first, keys.second); painter->drawText(rect, header, QTextOption(Qt::AlignHCenter| Qt::AlignTop)); if (savePages == SaveBothPages) { QRect rect = resizeRect(leftRect, pixmaps.first.size()); painter->drawPixmap(rect, pixmaps.first); rect = resizeRect(rightRect, pixmaps.second.size()); painter->drawPixmap(rect, pixmaps.second); painter->drawRect(rightRect.adjusted(2.5, 2.5, 2.5, 2.5)); } else if (savePages == SaveLeftPages) { QRect rect = resizeRect(leftRect, pixmaps.first.size()); painter->drawPixmap(rect, pixmaps.first); } else { // (savePages == SaveRightPages) QRect rect = resizeRect(leftRect, pixmaps.second.size()); painter->drawPixmap(rect, pixmaps.second); } painter->drawRect(leftRect.adjusted(2.5, 2.5, 2.5, 2.5)); return true; } void MainWindow::help() { if (!helpForm) helpForm = new HelpForm(language, this); helpForm->show(); helpForm->raise(); helpForm->activateWindow(); } void MainWindow::about() { if (!aboutForm) aboutForm = new AboutForm(this); aboutForm->show(); aboutForm->raise(); aboutForm->activateWindow(); } void MainWindow::showZones() { PagePair pair = viewDiffComboBox->itemData( viewDiffComboBox->currentIndex()).value(); if (pair.isNull()) return; QString filename1 = filename1LineEdit->text(); PdfDocument pdf1 = getPdf(filename1); if (!pdf1) return; PdfPage page1(pdf1->page(pair.left)); if (!page1) return; const TextBoxList list1 = getTextBoxes(page1); showZones(page1->pageSize().width(), list1, page1Label); QString filename2 = filename2LineEdit->text(); PdfDocument pdf2 = getPdf(filename2); if (!pdf2) return; PdfPage page2(pdf2->page(pair.right)); if (!page2) return; const TextBoxList list2 = getTextBoxes(page2); showZones(page2->pageSize().width(), list2, page2Label); } void MainWindow::showZones(const int Width, const TextBoxList &list, QLabel *label) { if (!label || !label->pixmap() || label->pixmap()->isNull()) return; const bool ComparingWords = compareComboBox->currentIndex() == CompareWords; TextItems items = ComparingWords ? getWords(list) : getCharacters(list); items.columnYxOrder(Width, toleranceYSpinBox->value(), columnsSpinBox->value()); QList paths = items.generateZones(Width, toleranceRSpinBox->value(), toleranceYSpinBox->value(), columnsSpinBox->value()); const int DPI = static_cast(POINTS_PER_INCH * (zoomSpinBox->value() / 100.0)); QPixmap pixmap = label->pixmap()->copy(); QPainter painter(&pixmap); painter.setPen(Qt::green); for (int i = 0; i < paths.count(); ++i) { const QPainterPath &path = paths.at(i); QRectF rect = path.boundingRect(); scaleRect(DPI, &rect); painter.drawRect(rect); painter.drawText(rect.x(), rect.y(), QString("#%1").arg(i + 1)); } painter.end(); label->setPixmap(pixmap); } void MainWindow::showMargins() { if (leftMarginSpinBox->value() == 0 && rightMarginSpinBox->value() == 0 && topMarginSpinBox->value() == 0 && bottomMarginSpinBox->value() == 0) return; showMargins(page1Label); showMargins(page2Label); } void MainWindow::showMargins(QLabel *label) { if (!label || !label->pixmap() || label->pixmap()->isNull()) return; const int DPI = static_cast(POINTS_PER_INCH * (zoomSpinBox->value() / 100.0)); QPixmap pixmap = label->pixmap()->copy(); QPainter painter(&pixmap); painter.setPen(Qt::cyan); int left = leftMarginSpinBox->value(); if (left) { const int x = pixelOffsetForPointValue(DPI, left); painter.drawLine(x, 0, x, pixmap.height()); } int right = rightMarginSpinBox->value(); if (right) { const int x = pixmap.width() - pixelOffsetForPointValue(DPI, right); painter.drawLine(x, 0, x, pixmap.height()); } int top = topMarginSpinBox->value(); if (top) { const int y = pixelOffsetForPointValue(DPI, top); painter.drawLine(0, y, pixmap.width(), y); } int bottom = bottomMarginSpinBox->value(); if (bottom) { const int y = pixmap.height() - pixelOffsetForPointValue(DPI, bottom); painter.drawLine(0, y, pixmap.width(), y); } painter.end(); label->setPixmap(pixmap); } void MainWindow::setAMargin(const QPoint &pos) { if (!marginsGroupBox->isChecked() || !page1Label->pixmap() || page1Label->pixmap()->isNull()) return; const int DPI = static_cast(POINTS_PER_INCH * (zoomSpinBox->value() / 100.0)); const QSize &size = page1Label->pixmap()->size(); int x = pos.x(); int y = pos.y(); const int HorizontalMiddle = size.width() / 2; const int TopOffset = size.height() / 3; const int BottomOffset = size.height() - TopOffset; const int VerticalMiddle = size.height() / 2; if (y > TopOffset && y < BottomOffset) { // Setting left or right if (x < HorizontalMiddle) leftMarginSpinBox->setValue(pointValueForPixelOffset(DPI, x)); else rightMarginSpinBox->setValue(pointValueForPixelOffset(DPI, (size.width() - x))); } else { // Setting top or bottom if (y < VerticalMiddle) topMarginSpinBox->setValue(pointValueForPixelOffset(DPI, y)); else bottomMarginSpinBox->setValue(pointValueForPixelOffset(DPI, (size.height() - y))); } } diffpdf-2.1.3/mainwindow.hpp0000644000000000000000000001650612227164102014137 0ustar 00000000000000#ifndef MAINWINDOW_HPP #define MAINWINDOW_HPP /* Copyright © 2008-13 Qtrac Ltd. All rights reserved. This program or module is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. */ #include "generic.hpp" #include "saveform.hpp" #if QT_VERSION >= 0x040600 #include #else #include #endif #include #include #include #include #include class AboutForm; class HelpForm; class Label; class LineEdit; class QBoxLayout; class QCheckBox; class QComboBox; class QGroupBox; class QLabel; class QLineEdit; class QPlainTextEdit; class QPushButton; class QRadioButton; class QScrollArea; class QSpinBox; class QSplitter; class MainWindow : public QMainWindow { Q_OBJECT public: MainWindow(const Debug debug, const InitialComparisonMode comparisonMode, const QString &filename1, const QString &filename2, const QString &language, QWidget *parent=0); protected: void closeEvent(QCloseEvent *event); bool eventFilter(QObject *object, QEvent *event); private slots: void setFile1(QString filename=QString()); void setFile2(QString filename=QString()); void setFiles1(const QStringList &filenames); void setFiles2(const QStringList &filenames); void compare(); void options(); void save(); void about(); void help(); void initialize(const QString &filename1, const QString &filename2); void updateUi(); void updateViews(int index=-1); void controlDockLocationChanged(Qt::DockWidgetArea area); void actionDockLocationChanged(Qt::DockWidgetArea area); void zoningDockLocationChanged(Qt::DockWidgetArea area); void marginsDockLocationChanged(Qt::DockWidgetArea area); void controlTopLevelChanged(bool floating); void actionTopLevelChanged(bool floating); void zoningTopLevelChanged(bool floating); void marginsTopLevelChanged(bool floating); void logTopLevelChanged(bool floating); void previousPages(); void nextPages(); void showZones(); void showMargins(); void setAMargin(const QPoint &pos); private: enum Difference {NoDifference, TextualDifference, VisualDifference}; void createWidgets(const QString &filename1, const QString &filename2); void createCentralArea(); void createDockWidgets(); void createConnections(); const QPair comparePages(const QString &filename1, const PdfDocument &pdf1, const QString &filename2, const PdfDocument &pdf2); void comparePrepareUi(); void compareUpdateUi(const QPair &pair, const int millisec); int writeFileInfo(const QString &filename); void writeLine(const QString &text); void writeError(const QString &text); PdfDocument getPdf(const QString &filename); QList getPageList(int which, PdfDocument pdf); Difference getTheDifference(PdfPage page1, PdfPage page2); void paintOnImage(const QPainterPath &path, QImage *image); const QPair populatePixmaps(const PdfDocument &pdf1, const PdfPage &page1, const PdfDocument &pdf2, const PdfPage &page2, bool hasVisualDifference, const QString &key1, const QString &key2); void computeTextHighlights(QPainterPath *highlighted1, QPainterPath *highlighted2, const PdfPage &page1, const PdfPage &page2, const int DPI); void computeVisualHighlights(QPainterPath *highlighted1, QPainterPath *highlighted2, const QImage &plainImage1, const QImage &plainImage2); void addHighlighting(QRectF *bigRect, QPainterPath *highlighted, const QRectF wordOrCharRect, const int OVERLAP, const int DPI, const bool COMBINE=true); const QPair cacheKeys(const int index, const PagePair &pair) const; const TextBoxList zoneYxOrdered(const TextBoxList &list); void showZones(const int Width, const TextBoxList &list, QLabel *label); void showMargins(QLabel *label); void saveAsPdf(const int start, const int end, const PdfDocument &pdf1, const PdfDocument &pdf2, const QString &header); bool paintSaveAs(QPainter *painter, const int index, const PdfDocument &pdf1, const PdfDocument &pdf2, const QString &header, const QRect &rect, const QRect &leftRect, const QRect &rightRect); void saveAsImages(const int start, const int end, const PdfDocument &pdf1, const PdfDocument &pdf2, const QString &header); void computeImageOffsets(const QSize &size, int *x, int *y, int *width, int *height); QRectF pointRectForMargins(const QSize &size); QRect pixelRectForMargins(const QSize &size); QPushButton *setFile1Button; LineEdit *filename1LineEdit; QLabel *comparePages1Label; QLineEdit *pages1LineEdit; Label *page1Label; QScrollArea *area1; QPushButton *setFile2Button; LineEdit *filename2LineEdit; QLabel *comparePages2Label; QLineEdit *pages2LineEdit; Label *page2Label; QScrollArea *area2; QComboBox *compareComboBox; QLabel *compareLabel; QLabel *viewDiffLabel; QPushButton *compareButton; QComboBox *viewDiffComboBox; QPushButton *previousButton; QPushButton *nextButton; QLabel *statusLabel; QLabel *zoomLabel; QSpinBox *zoomSpinBox; QLabel *showLabel; QComboBox *showComboBox; QPushButton *optionsButton; QPushButton *saveButton; QPushButton *aboutButton; QPushButton *helpButton; QPushButton *quitButton; QPlainTextEdit *logEdit; QSplitter *splitter; QBoxLayout *controlLayout; QDockWidget *controlDockWidget; QBoxLayout *actionLayout; QDockWidget *actionDockWidget; QDockWidget *logDockWidget; QBoxLayout *compareLayout; QGroupBox *zoningGroupBox; QLabel *columnsLabel; QSpinBox *columnsSpinBox; QLabel *toleranceRLabel; QSpinBox *toleranceRSpinBox; QLabel *toleranceYLabel; QSpinBox *toleranceYSpinBox; QCheckBox *showZonesCheckBox; QBoxLayout *zoningLayout; QDockWidget *zoningDockWidget; QGroupBox *marginsGroupBox; QLabel *topMarginLabel; QSpinBox *topMarginSpinBox; QLabel *bottomMarginLabel; QSpinBox *bottomMarginSpinBox; QLabel *leftMarginLabel; QSpinBox *leftMarginSpinBox; QLabel *rightMarginLabel; QSpinBox *rightMarginSpinBox; QBoxLayout *marginsLayout; QDockWidget *marginsDockWidget; QBrush brush; QPen pen; QString currentPath; Qt::DockWidgetArea controlDockArea; Qt::DockWidgetArea actionDockArea; Qt::DockWidgetArea marginsDockArea; Qt::DockWidgetArea zoningDockArea; Qt::DockWidgetArea logDockArea; bool cancel; bool showToolTips; bool combineTextHighlighting; QString saveFilename; bool saveAll; SavePages savePages; const QString language; Debug debug; AboutForm *aboutForm; HelpForm *helpForm; }; #endif // MAINWINDOW_HPP diffpdf-2.1.3/optionsform.cpp0000644000000000000000000002452312227164102014333 0ustar 00000000000000/* Copyright © 2008-13 Qtrac Ltd. All rights reserved. This program or module is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. */ #include "generic.hpp" #include "optionsform.hpp" #include #include #include #include #include #include #include #include #include #include #include OptionsForm::OptionsForm(QPen *pen, QBrush *brush, qreal *ruleWidth, bool *showToolTips, bool *combineTextHighlighting, int *cacheSize, int *alpha, int *squareSize, QWidget *parent) : QDialog(parent), m_pen(pen), m_brush(brush), m_ruleWidth(ruleWidth), m_showToolTips(showToolTips), m_combineTextHighlighting(combineTextHighlighting), m_cacheSize(cacheSize), m_alpha(alpha), m_squareSize(squareSize) { this->pen = *m_pen; this->brush = *m_brush; createWidgets(); createLayout(); createConnections(); updateSwatches(); updateUi(); setWindowTitle(tr("DiffPDF — Options")); } void OptionsForm::createWidgets() { colorComboBox = new QComboBox; foreach (const QString &name, QColor::colorNames()) { QColor color(name); colorComboBox->addItem(colorSwatch(color), name, color); } colorComboBox->setCurrentIndex(colorComboBox->findData(pen.color())); QColor color = pen.color(); color.setAlphaF(*m_alpha / 100.0); brushStyleComboBox = new QComboBox; typedef QPair BrushPair; foreach (const BrushPair &pair, QList() << qMakePair(tr("No Brush"), Qt::NoBrush) << qMakePair(tr("Solid"), Qt::SolidPattern) << qMakePair(tr("Dense #1"), Qt::Dense1Pattern) << qMakePair(tr("Dense #2"), Qt::Dense2Pattern) << qMakePair(tr("Dense #3"), Qt::Dense3Pattern) << qMakePair(tr("Dense #4"), Qt::Dense4Pattern) << qMakePair(tr("Dense #5"), Qt::Dense5Pattern) << qMakePair(tr("Dense #6"), Qt::Dense6Pattern) << qMakePair(tr("Horizontal"), Qt::HorPattern) << qMakePair(tr("Vertical"), Qt::VerPattern) << qMakePair(tr("Cross"), Qt::CrossPattern) << qMakePair(tr("Diagonal /"), Qt::BDiagPattern) << qMakePair(tr("Diagonal \\"), Qt::FDiagPattern) << qMakePair(tr("Diagonal Cross"), Qt::DiagCrossPattern)) brushStyleComboBox->addItem(brushSwatch(pair.second, color), pair.first, pair.second); brushStyleComboBox->setCurrentIndex(brushStyleComboBox->findData( brush.style())); penStyleComboBox = new QComboBox; typedef QPair PenPair; foreach (const PenPair &pair, QList() << qMakePair(tr("No Pen"), Qt::NoPen) << qMakePair(tr("Solid"), Qt::SolidLine) << qMakePair(tr("Dashed"), Qt::DashLine) << qMakePair(tr("Dotted"), Qt::DotLine) << qMakePair(tr("Dash-Dotted"), Qt::DashDotLine) << qMakePair(tr("Dash-Dot-Dotted"), Qt::DashDotDotLine)) penStyleComboBox->addItem(penStyleSwatch(pair.second, color), pair.first, pair.second); penStyleComboBox->setCurrentIndex(penStyleComboBox->findData( pen.style())); alphaSpinBox = new QSpinBox; alphaSpinBox->setRange(1, 100); alphaSpinBox->setValue(*m_alpha); alphaSpinBox->setSuffix(tr(" %")); alphaSpinBox->setAlignment(Qt::AlignVCenter|Qt::AlignRight); alphaSpinBox->setToolTip(tr("

How opaque the highlighting " "color is. The default is 13%")); squareSizeSpinBox = new QSpinBox; squareSizeSpinBox->setRange(2, 40); squareSizeSpinBox->setValue(*m_squareSize); squareSizeSpinBox->setSuffix(tr(" px")); squareSizeSpinBox->setAlignment(Qt::AlignVCenter|Qt::AlignRight); squareSizeSpinBox->setToolTip(tr("

The size of the " "highlighting squares in Appearance mode. Small values are " "more expensive to compute. Large values give coarse " "comparisons. The default is 10 px")); ruleWidthSpinBox = new QDoubleSpinBox; ruleWidthSpinBox->setRange(0.0, 10.0); ruleWidthSpinBox->setDecimals(2); ruleWidthSpinBox->setSingleStep(0.25); ruleWidthSpinBox->setAlignment(Qt::AlignVCenter|Qt::AlignRight); ruleWidthSpinBox->setSpecialValueText(tr("No Rules")); ruleWidthSpinBox->setValue(*m_ruleWidth); showToolTipsCheckBox = new QCheckBox(tr("Show &Tooltips in " "the Main Window")); showToolTipsCheckBox->setChecked(*m_showToolTips); combineTextHighlightingCheckBox = new QCheckBox( tr("Combine Highlighting in &Text Modes")); combineTextHighlightingCheckBox->setChecked( *m_combineTextHighlighting); cacheSizeSpinBox = new QSpinBox; cacheSizeSpinBox->setRange(1, 100); cacheSizeSpinBox->setValue(*m_cacheSize); cacheSizeSpinBox->setSuffix(tr(" MB")); cacheSizeSpinBox->setToolTip(tr("

The cache is used to store pages " "already seen to make flipping back and forth as fast as " "possible. The bigger the cache the more pages that can be " "stored.")); buttonBox = new QDialogButtonBox(QDialogButtonBox::Ok| QDialogButtonBox::Cancel); tabWidget = new QTabWidget; } void OptionsForm::createLayout() { QFormLayout *generalLayout = new QFormLayout; generalLayout->addRow(showToolTipsCheckBox); generalLayout->addRow(tr("&Rule width:"), ruleWidthSpinBox); QWidget *widget = new QWidget; widget->setLayout(generalLayout); tabWidget->addTab(widget, tr("&General")); QFormLayout *highlightingLayout = new QFormLayout; highlightingLayout->addRow(tr("&Base Color:"), colorComboBox); highlightingLayout->addRow(tr("O&utline:"), penStyleComboBox); highlightingLayout->addRow(tr("&Fill:"), brushStyleComboBox); highlightingLayout->addRow(tr("F&ill Opacity:"), alphaSpinBox); highlightingLayout->addRow(combineTextHighlightingCheckBox); widget = new QWidget; widget->setToolTip(tr("

The outline and fill are used to highlight " "differences using a semi-transparent version of the base " "color. The margin rules are painted using the base color " "and indicate where changes are. Set the rule width to 0.0 " "to switch the rules off. If combining highlighting is " "checked it will try to merge the highlighting of adjacent " "text differences.")); widget->setLayout(highlightingLayout); tabWidget->addTab(widget, tr("&Highlighting")); QFormLayout *performanceLayout = new QFormLayout; performanceLayout->addRow(tr("&Square Size:"), squareSizeSpinBox); performanceLayout->addRow(tr("C&ache Size:"), cacheSizeSpinBox); widget = new QWidget; widget->setLayout(performanceLayout); tabWidget->addTab(widget, tr("&Performance")); QVBoxLayout *layout = new QVBoxLayout; layout->addWidget(tabWidget); layout->addWidget(buttonBox); setLayout(layout); } void OptionsForm::createConnections() { connect(colorComboBox, SIGNAL(currentIndexChanged(int)), this, SLOT(updateColor(int))); connect(penStyleComboBox, SIGNAL(currentIndexChanged(int)), this, SLOT(updatePenStyle(int))); connect(penStyleComboBox, SIGNAL(currentIndexChanged(int)), this, SLOT(updateUi())); connect(brushStyleComboBox, SIGNAL(currentIndexChanged(int)), this, SLOT(updateBrushStyle(int))); connect(brushStyleComboBox, SIGNAL(currentIndexChanged(int)), this, SLOT(updateUi())); connect(alphaSpinBox, SIGNAL(valueChanged(int)), this, SLOT(updateSwatches())); connect(buttonBox, SIGNAL(accepted()), this, SLOT(accept())); connect(buttonBox, SIGNAL(rejected()), this, SLOT(reject())); } void OptionsForm::updateColor(int index) { QColor color = colorComboBox->itemData(index).value(); brush.setColor(color); pen.setColor(color); updateSwatches(); } void OptionsForm::updatePenStyle(int index) { pen.setStyle(static_cast( penStyleComboBox->itemData(index).toInt())); } void OptionsForm::updateBrushStyle(int index) { brush.setStyle(static_cast( brushStyleComboBox->itemData(index).toInt())); } void OptionsForm::updateSwatches() { QColor color = colorComboBox->itemData( colorComboBox->currentIndex()).value(); color.setAlphaF(alphaSpinBox->value() / 100.0); for (int i = 0; i < brushStyleComboBox->count(); ++i) brushStyleComboBox->setItemIcon(i, brushSwatch( static_cast( brushStyleComboBox->itemData(i).toInt()), color)); for (int i = 0; i < penStyleComboBox->count(); ++i) penStyleComboBox->setItemIcon(i, penStyleSwatch( static_cast( penStyleComboBox->itemData(i).toInt()), color)); } void OptionsForm::updateUi() { Qt::BrushStyle brushStyle = static_cast( brushStyleComboBox->itemData( brushStyleComboBox->currentIndex()).toInt()); Qt::PenStyle penStyle = static_cast( penStyleComboBox->itemData( penStyleComboBox->currentIndex()).toInt()); buttonBox->button(QDialogButtonBox::Ok)->setEnabled( !(brushStyle == Qt::NoBrush && penStyle == Qt::NoPen)); } void OptionsForm::accept() { *m_pen = pen; *m_brush = brush; *m_ruleWidth = ruleWidthSpinBox->value(); *m_showToolTips = showToolTipsCheckBox->isChecked(); *m_combineTextHighlighting = combineTextHighlightingCheckBox->isChecked(); *m_cacheSize = cacheSizeSpinBox->value(); *m_alpha = alphaSpinBox->value(); *m_squareSize = squareSizeSpinBox->value(); QDialog::accept(); } diffpdf-2.1.3/optionsform.hpp0000644000000000000000000000367112227164102014341 0ustar 00000000000000#ifndef OPTIONSFORM_HPP #define OPTIONSFORM_HPP /* Copyright © 2008-13 Qtrac Ltd. All rights reserved. This program or module is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. */ #include #include #include class QCheckBox; class QComboBox; class QDialogButtonBox; class QDoubleSpinBox; class QSpinBox; class QTabWidget; class OptionsForm : public QDialog { Q_OBJECT public: OptionsForm(QPen *pen, QBrush *brush, qreal *ruleWidth, bool *showToolTips, bool *combineTextHighlighting, int *cacheSize, int *alpha, int *squareSize, QWidget *parent=0); private slots: void updateColor(int index); void updateBrushStyle(int index); void updatePenStyle(int index); void updateSwatches(); void updateUi(); void accept(); private: void createWidgets(); void createLayout(); void createConnections(); QTabWidget *tabWidget; QComboBox *colorComboBox; QComboBox *brushStyleComboBox; QComboBox *penStyleComboBox; QSpinBox *alphaSpinBox; QSpinBox *squareSizeSpinBox; QDoubleSpinBox *ruleWidthSpinBox; QCheckBox *showToolTipsCheckBox; QCheckBox *combineTextHighlightingCheckBox; QSpinBox *cacheSizeSpinBox; QDialogButtonBox *buttonBox; QPen *m_pen; QBrush *m_brush; qreal *m_ruleWidth; bool *m_showToolTips; bool *m_combineTextHighlighting; int *m_cacheSize; int *m_alpha; int *m_squareSize; QPen pen; QBrush brush; }; #endif // OPTIONSFORM_HPP diffpdf-2.1.3/resources.qrc0000644000000000000000000000060412227164102013763 0ustar 00000000000000 images/icon.png images/left.png images/right.png diffpdf_cz.qm diffpdf_de.qm diffpdf_fr.qm help.html help_cz.html help_de.html help_fr.html diffpdf-2.1.3/saveform.cpp0000644000000000000000000001143512227164102013574 0ustar 00000000000000/* Copyright © 2008-13 Qtrac Ltd. All rights reserved. This program or module is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. */ #include "saveform.hpp" #include #include #include #include #include #include #include #include #include #include SaveForm::SaveForm(const QString &path, QString *filename, bool *saveAll, SavePages *savePages, QWidget *parent) : QDialog(parent), m_path(path), m_filename(filename), m_saveAll(saveAll), m_savePages(savePages) { createWidgets(); createLayout(); createConnections(); updateUi(); setWindowTitle(tr("DiffPDF — Save As")); } void SaveForm::createWidgets() { saveGroupBox = new QGroupBox(tr("Pairs")); saveCurrentRadioButton = new QRadioButton(tr("Current &Page Pair")); saveAllRadioButton = new QRadioButton(tr("&All Page Pairs")); if (*m_saveAll) saveAllRadioButton->setChecked(true); else saveCurrentRadioButton->setChecked(true); pagesGroupBox = new QGroupBox(tr("Pages")); leftPagesRadioButton = new QRadioButton(tr("File #&1's Pages")); rightPagesRadioButton = new QRadioButton(tr("File #&2's Pages")); bothPagesRadioButton = new QRadioButton(tr("&Both Files' Pages")); if (*m_savePages == SaveLeftPages) leftPagesRadioButton->setChecked(true); else if (*m_savePages == SaveRightPages) rightPagesRadioButton->setChecked(true); else // m_savePages == SaveBothPages bothPagesRadioButton->setChecked(true); filenameLabel = new QLabel(tr("&Filename:")); filenameLineEdit = new QLineEdit; filenameLineEdit->setText(*m_filename); filenameLabel->setBuddy(filenameLineEdit); chooseFileButton = new QPushButton(tr("B&rowse...")); buttonBox = new QDialogButtonBox(QDialogButtonBox::Ok| QDialogButtonBox::Cancel); } void SaveForm::createLayout() { QHBoxLayout *saveLayout = new QHBoxLayout; saveLayout->addWidget(saveCurrentRadioButton); saveLayout->addWidget(saveAllRadioButton); saveLayout->addStretch(); saveGroupBox->setLayout(saveLayout); QHBoxLayout *pagesLayout = new QHBoxLayout; pagesLayout->addWidget(leftPagesRadioButton); pagesLayout->addWidget(rightPagesRadioButton); pagesLayout->addWidget(bothPagesRadioButton); pagesGroupBox->setLayout(pagesLayout); QHBoxLayout *filenameLayout = new QHBoxLayout; filenameLayout->addWidget(filenameLabel); filenameLayout->addWidget(filenameLineEdit); filenameLayout->addWidget(chooseFileButton); QVBoxLayout *layout = new QVBoxLayout; layout->addWidget(saveGroupBox); layout->addWidget(pagesGroupBox); layout->addLayout(filenameLayout); layout->addStretch(); layout->addWidget(buttonBox); setLayout(layout); } void SaveForm::createConnections() { connect(chooseFileButton, SIGNAL(clicked()), this, SLOT(chooseFile())); connect(filenameLineEdit, SIGNAL(textChanged(const QString&)), this, SLOT(updateUi())); connect(buttonBox, SIGNAL(accepted()), this, SLOT(accept())); connect(buttonBox, SIGNAL(rejected()), this, SLOT(reject())); } void SaveForm::updateUi() { buttonBox->button(QDialogButtonBox::Ok)->setEnabled( !filenameLineEdit->text().isEmpty()); } void SaveForm::chooseFile() { QList formats = QImageWriter::supportedImageFormats(); QStringList suffixes; foreach (const QByteArray &format, formats) suffixes << "*." + QString(format.toLower()); QString filename = QFileDialog::getSaveFileName(this, tr("DiffPDF — Browse"), m_path, tr("PDF files (*.pdf);;Image files (%1)") .arg(suffixes.join(" "))); if (!filename.isEmpty()) { filenameLineEdit->setText(filename); buttonBox->button(QDialogButtonBox::Ok)->setFocus(); } } void SaveForm::accept() { *m_filename = filenameLineEdit->text(); if (!m_filename->contains(".")) *m_filename += ".pdf"; *m_saveAll = saveAllRadioButton->isChecked(); if (leftPagesRadioButton->isChecked()) *m_savePages = SaveLeftPages; else if (rightPagesRadioButton->isChecked()) *m_savePages = SaveRightPages; else // bothPagesRadioButton->isChecked() *m_savePages = SaveBothPages; QDialog::accept(); } diffpdf-2.1.3/saveform.hpp0000644000000000000000000000326512227164102013603 0ustar 00000000000000#ifndef SAVEFORM_HPP #define SAVEFORM_HPP /* Copyright © 2008-13 Qtrac Ltd. All rights reserved. This program or module is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. */ #include #include #include class QDialogButtonBox; class QGroupBox; class QLabel; class QLineEdit; class QPushButton; class QRadioButton; enum SavePages {SaveLeftPages, SaveRightPages, SaveBothPages}; class SaveForm : public QDialog { Q_OBJECT public: SaveForm(const QString &path, QString *filename, bool *saveAll, SavePages *savePages, QWidget *parent=0); private slots: void accept(); void updateUi(); void chooseFile(); private: void createWidgets(); void createLayout(); void createConnections(); QGroupBox *saveGroupBox; QRadioButton *saveCurrentRadioButton; QRadioButton *saveAllRadioButton; QGroupBox *pagesGroupBox; QRadioButton *leftPagesRadioButton; QRadioButton *rightPagesRadioButton; QRadioButton *bothPagesRadioButton; QLabel *filenameLabel; QLineEdit *filenameLineEdit; QPushButton *chooseFileButton; QDialogButtonBox *buttonBox; const QString m_path; QString *m_filename; bool *m_saveAll; SavePages *m_savePages; }; #endif // SAVEFORM_HPP diffpdf-2.1.3/sequence_matcher.cpp0000644000000000000000000001272712227164102015272 0ustar 00000000000000/* Copyright © 2011-13 Qtrac Ltd. All rights reserved. This program or module is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. */ #include "sequence_matcher.hpp" #include RangesPair computeRanges(SequenceMatcher *matcher) { Ranges ranges1; Ranges ranges2; QList matches = matcher->get_matching_blocks(); foreach (const Match &match, matches) { if (match.size == 0) continue; ranges1 |= unorderedRange(match.i + match.size, match.i); ranges2 |= unorderedRange(match.j + match.size, match.j); } return qMakePair(ranges1, ranges2); } RangesPair invertRanges(const Ranges &ranges1, int length1, const Ranges &ranges2, int length2) { const Ranges newRanges1 = unorderedRange(length1) - ranges1; const Ranges newRanges2 = unorderedRange(length2) - ranges2; return qMakePair(newRanges1, newRanges2); } bool matchLessThan(const Match &a, const Match &b) { if (a.i != b.i) return a.i < b.i; if (a.j != b.j) return a.j < b.j; return a.size < b.size; } struct Offsets { Offsets(int a_low_=0, int a_high_=0, int b_low_=0, int b_high_=0) : a_low(a_low_), a_high(a_high_), b_low(b_low_), b_high(b_high_) {} int a_low; int a_high; int b_low; int b_high; }; SequenceMatcher::SequenceMatcher(const Sequence &a_, const Sequence &b_) : a(a_), b(b_) { set_sequences(a, b); } void SequenceMatcher::set_sequence1(const Sequence &sequence) { a = sequence; matching_blocks.clear(); } void SequenceMatcher::set_sequence2(const Sequence &sequence) { b = sequence; matching_blocks.clear(); chain_b(); } void SequenceMatcher::chain_b() { const int N = b.count(); b2j.clear(); QSet popular; for (int i = 0; i < N; ++i) { const Element &element = b.at(i); if (b2j.contains(element)) { QList &indexes = b2j[element]; if (N >= 200 && indexes.count() * 100 > N) { popular.insert(element); indexes.clear(); } else indexes.append(i); } else b2j[element].append(i); } foreach (const Element &element, popular) b2j.remove(element); } QList SequenceMatcher::get_matching_blocks() { if (!matching_blocks.isEmpty()) return matching_blocks; const int LengthA = a.count(); const int LengthB = b.count(); QList offsets; offsets << Offsets(0, LengthA, 0, LengthB); while (!offsets.isEmpty()) { const Offsets &offset = offsets.takeLast(); const int a_low = offset.a_low; const int a_high = offset.a_high; const int b_low = offset.b_low; const int b_high = offset.b_high; const Match match = find_longest_match(a_low, a_high, b_low, b_high); const int i = match.i; const int j = match.j; const int k = match.size; if (k) { matching_blocks.append(match); if (a_low < i && b_low < j) offsets.append(Offsets(a_low, i, b_low, j)); if (i + k < a_high && j + k < b_high) offsets.append(Offsets(i + k, a_high, j + k, b_high)); } } qSort(matching_blocks.begin(), matching_blocks.end(), matchLessThan); int i1 = 0; int j1 = 0; int k1 = 0; QList non_adjacent; foreach (const Match match, matching_blocks) { const int i2 = match.i; const int j2 = match.j; const int k2 = match.size; if (i1 + k1 == i2 && j1 + k1 == j2) k1 += k2; else { if (k1) non_adjacent.append(Match(i1, j1, k1)); i1 = i2; j1 = j2; k1 = k2; } } if (k1) non_adjacent.append(Match(i1, j1, k1)); non_adjacent.append(Match(LengthA, LengthB, 0)); matching_blocks = non_adjacent; return matching_blocks; } Match SequenceMatcher::find_longest_match(int a_low, int a_high, int b_low, int b_high) { int best_i = a_low; int best_j = b_low; int best_size = 0; QHash j2len; for (int i = a_low; i < a_high; ++i) { QHash newj2len; foreach (int j, b2j.value(a[i])) { if (j < b_low) continue; if (j >= b_high) break; const int k = j2len.value(j - 1, 0) + 1; newj2len[j] = k; if (k > best_size) { best_i = i - k + 1; best_j = j - k + 1; best_size = k; } } j2len = newj2len; } while (best_i > a_low && best_j > b_low && a[best_i - 1] == b[best_j - 1]) { --best_i; --best_j; ++best_size; } while (best_i + best_size < a_high && best_j + best_size < b_high && a[best_i + best_size] == b[best_j + best_size]) ++best_size; return Match(best_i, best_j, best_size); } diffpdf-2.1.3/sequence_matcher.hpp0000644000000000000000000000344212227164102015271 0ustar 00000000000000#ifndef SEQUENCE_MATCHER_HPP #define SEQUENCE_MATCHER_HPP /* Copyright © 2011-13 Qtrac Ltd. All rights reserved. This program or module is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. */ #include "generic.hpp" #include #include #include #include typedef QStringList Sequence; typedef QString Element; class SequenceMatcher; RangesPair computeRanges(SequenceMatcher *matcher); RangesPair invertRanges(const Ranges &ranges1, int length1, const Ranges &ranges2, int length2); struct Match { Match(int i_=0, int j_=0, int size_=0) : i(i_), j(j_), size(size_) {} int i; int j; int size; }; // A simplified C++ implementation of Python's difflib's SequenceMatcher class SequenceMatcher { public: SequenceMatcher(const Sequence &a_=Sequence(), const Sequence &b_=Sequence()); void set_sequences(const Sequence &a, const Sequence &b) { set_sequence1(a); set_sequence2(b); } void set_sequence1(const Sequence &sequence); void set_sequence2(const Sequence &sequence); QList get_matching_blocks(); Match find_longest_match(int a_low, int a_high, int b_low, int b_high); private: void chain_b(); Sequence a; Sequence b; QHash > b2j; QList matching_blocks; }; #endif // SEQUENCE_MATCHER_HPP diffpdf-2.1.3/textitem.cpp0000644000000000000000000001615612227164102013622 0ustar 00000000000000/* Copyright © 2008-13 Qtrac Ltd. All rights reserved. This program or module is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. */ #include "textitem.hpp" #include #include #include QStringList TextItems::texts() const { QStringList list; foreach (const TextItem &item, items) list << item.text; return list; } QList TextItems::rects() const { QList list; foreach (const TextItem &item, items) list << item.rect; return list; } struct Key { Key(const int a, const int b, const int c) : a(a), b(b), c(c) {} bool operator<(const Key &other) const { if (a != other.a) return a < other.a; if (b != other.b) return b < other.b; return c < other.c; } int a, b, c; }; void TextItems::columnZoneYxOrder(const int Width, const int ToleranceR, const int ToleranceY, const int Columns) { // Phase #1: Sort all the texts into (column, y, x) order columnYxOrder(Width, ToleranceY, Columns); // Phase #2: Sort all the texts into (column, zone, y, x) order QList zones = generateZones(Width, ToleranceR, ToleranceY, Columns); QMap itemForZoneYx; foreach (const TextItem &item, items) { const QRectF rect = item.rect.adjusted(-ToleranceR, -ToleranceR, ToleranceR, ToleranceR); const int y = normalizedY(static_cast(item.rect.y()), ToleranceY); for (int i = 0; i < zones.count(); ++i) { if (zones.at(i).intersects(rect)) { itemForZoneYx.insert(Key(i, y, item.rect.x()), item); break; } } } items = itemForZoneYx.values(); } void TextItems::columnYxOrder(const int Width, const int ToleranceY, const int Columns) { // Phase #1: Sort all the texts into (column, y, x) order const int Span = Width / Columns; QMap itemForColumnYx; foreach (const TextItem &item, items) { const QRect &rect = item.toRect(); const int Column = ((Columns == 1) ? 0 : (rect.width() > Span) ? Columns : rect.right() / Span); const int y = normalizedY(static_cast(rect.y()), ToleranceY); itemForColumnYx.insert(Key(Column, y, rect.x()), item); } items = itemForColumnYx.values(); } const QList TextItems::generateZones(const int Width, const int ToleranceR, const int ToleranceY, const int Columns) const { // Assumes that items are already in column, y, x order! // Phase #1: Generate the zones QList zones; foreach (const TextItem &item, items) { if (zones.isEmpty()) { // First word becomes first zone QPainterPath zone; zone.addRect(item.rect); zones << zone; } else { // Add to an existing zone within tolerance or a new one const QRectF tolerantRect = item.rect.adjusted(-ToleranceR, -ToleranceR, ToleranceR, ToleranceR); bool found = false; for (int i = 0; i < zones.count(); ++i) { QPainterPath zone = zones.at(i); if (zone.intersects(tolerantRect)) { zone.addRect(item.rect); zones[i] = zone; found = true; break; } } if (!found) { QPainterPath zone; zone.addRect(item.rect); zones << zone; } } } // Phase #2: Order the zones by (column, y, x) const int Span = Width / Columns; QMultiMap zonesForColumn; foreach (const QPainterPath &zone, zones) { const QRect &rect = zone.boundingRect().toRect(); const int Column = ((Columns == 1) ? 0 : (rect.width() > Span) ? Columns : rect.right() / Span); const int y = normalizedY(static_cast(rect.y()), ToleranceY); zonesForColumn.insertMulti(Key(Column, y, rect.x()), zone); } return zonesForColumn.values(); } void TextItems::debug(const int page, const int ToleranceY, const bool ComparingWords, const bool Yx) { QString filename = QDir::tempPath() + QString("/page1-%1.txt") .arg(page); int count = 1; while (QFile::exists(filename)) { filename = QDir::tempPath() + QString("/page%2-%1.txt").arg(page) .arg(++count); } QFile file(filename); if (!file.open(QIODevice::WriteOnly|QIODevice::Text)) { qDebug("%s", qPrintable(QString("cannot write debug file: %1") .arg(file.errorString()))); } QTextStream out(&file); out.setCodec("UTF-8"); out << "Page #" << page << ": " << (ComparingWords ? "Words" : "Characters") << " mode\n"; for (int i = 0; i < items.count(); ++i) { const TextItem &item = items.at(i); const QRect rect = item.toRect(); out << item.text; if (!ComparingWords) out << QString(" %1").arg(item.text.at(0).unicode(), 4, 16, QChar('0')); if (Yx) { const int y = normalizedY(static_cast(item.rect.y()), ToleranceY); out << QString(" (%1, %2)").arg(y).arg(rect.x()); } out << "\n"; } qDebug("%s", qPrintable(QString("wrote '%1'").arg(filename))); } inline int normalizedY(const int y, const int ToleranceY) { if (ToleranceY == 0) return y; const int remainder = y % ToleranceY; return (remainder == 0) ? y : y + ToleranceY - remainder; } const TextItems getWords(const TextBoxList &list) { TextItems items; foreach (const PdfTextBox &box, list) { QString word = box->text().trimmed(); for (int i = 0; i < word.length(); ++i) word[i] = canonicalizedCharacter(word[i]); // DON'T DO: if (!word.isEmpty()) words << word; // since it can mess up highlighting. items.append(TextItem(word, box->boundingBox())); } return items; } const TextItems getCharacters(const TextBoxList &list) { TextItems items; foreach (const PdfTextBox &box, list) { const QString word = box->text(); int limit = word.count() - 1; for (int i = limit; i >= 0; --i) if (!word[i].isSpace()) break; for (int i = 0; i <= limit; ++i) { items.append(TextItem(QString(canonicalizedCharacter(word[i])), box->charBoundingBox(i))); } } return items; } diffpdf-2.1.3/textitem.hpp0000644000000000000000000000360412227164102013621 0ustar 00000000000000#ifndef TEXTITEM_HPP #define TEXTITEM_HPP /* Copyright © 2008-13 Qtrac Ltd. All rights reserved. This program or module is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. */ #include "generic.hpp" #include #include #include #include struct TextItem { TextItem(const QString &text, const QRectF &rect) : text(text), rect(rect) {} QRect toRect() const { return rect.toRect(); } QString text; QRectF rect; }; class TextItems { public: TextItem at(const int index) const { return items.at(index); } void append(const TextItem &item) { items << item; } int count() const { return items.count(); } QStringList texts() const; QList rects() const; void columnZoneYxOrder(const int Width, const int ToleranceR, const int ToleranceY, const int Columns); void columnYxOrder(const int Width, const int ToleranceY, const int Columns); const QList generateZones(const int Width, const int ToleranceR, const int ToleranceY, const int Columns) const; void debug(const int page, const int ToleranceY, const bool ComparingWords=true, const bool Yx=false); private: QList items; }; inline int normalizedY(const int y, const int ToleranceY); const TextItems getWords(const TextBoxList &list); const TextItems getCharacters(const TextBoxList &list); #endif // TEXTITEM_HPP