1 /*
2 dspdfviewer - Dual Screen PDF Viewer for LaTeX-Beamer
3 Copyright (C) 2012 Danny Edel <mail@danny-edel.de>
4
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 2 of the License, or
8 (at your option) any later version.
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License along
16 with this program; if not, write to the Free Software Foundation, Inc.,
17 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 */
19
20
21 #include "runtimeconfiguration.h"
22
23 #include <boost/program_options.hpp>
24 #include <iostream>
25 #include <fstream>
26 #include <QCoreApplication>
27
28 #ifndef DSPDFVIEWER_VERSION
29 #warning DSPDFVIEWER_VERSION was not set by the build system!
30 #define DSPDFVIEWER_VERSION "UNKNOWN"
31 #endif
32
33 #ifndef I3WORKAROUND_SHELLCODE
34 /* This will get executed once both windows are created, provided
35 * the user passed --i3-workaround=true via command line or configuration file.
36 *
37 * You can override the shellcode by providing -DI3WORKAROUND_SHELLCODE="your shellcode"
38 * at the cmake step.
39 */
40 #define I3WORKAROUND_SHELLCODE "i3-msg '[class=\"Dspdfviewer\" window_role=\"Audience_Window\"] move to output right, fullscreen'"
41 #endif
42
43 using namespace std;
44 using namespace boost::program_options;
45
RuntimeConfiguration(int argc,const char * const * argv)46 RuntimeConfiguration::RuntimeConfiguration(int argc, const char* const * argv):
47 m_useFullPage(false),
48 m_showPresenterArea(true),
49 m_duplicate(false),
50 m_showWallClock(true),
51 m_showThumbnails(true),
52 m_thumbnailPagePart(PagePart::FullPage),
53 m_showPresentationClock(true),
54 m_showSlideClock(true),
55 m_filePath(),
56 m_hyperlinkSupport(true),
57 m_cacheToMemory(true),
58 m_cacheSizeMegaBytes(0),
59 m_useSecondScreen(true),
60 m_i3workaround(false),
61 m_prerenderPreviousPages(3),
62 m_prerenderNextPages(10),
63 m_bottomPaneHeightPercent(20)
64 {
65 options_description generic( tr("Generic options").toLocal8Bit().constData() );
66
67 /** FIXME: Using .toLocal8Bit() [.constData()] is Very Very Very Ugly,
68 * but works because program_options copies the string...
69 */
70 generic.add_options()
71 ("help,h", tr("Print help message").toLocal8Bit() )
72 ("version,v", tr("Print version statement").toLocal8Bit() )
73 ;
74
75 options_description global( tr("Options affecting program behaviour")
76 .toLocal8Bit().constData() );
77 global.add_options()
78 ("full-page,f", //value<bool>(&m_useFullPage)->default_value(false)->implicit_value(true),
79 tr("Display the full slide on both screens (useful for PDFs created by presentation software other than latex-beamer)").toLocal8Bit() )
80 ("prerender-previous-pages",
81 value<unsigned>(&m_prerenderPreviousPages)->default_value(3),
82 tr("Pre-render the preceding arg slides\n"
83 "NOTE: If you set this to zero, you might not get a thumbnail for the previous slide unless it was loaded already."
84 ).toLocal8Bit()
85 )
86 ("prerender-next-pages",
87 value<unsigned>(&m_prerenderNextPages)->default_value(10),
88 tr(
89 "Pre-render the next arg slides\n"
90 "NOTE: If you set this to zero, you might not get a thumbnail for the next slide unless it was loaded already."
91 ).toLocal8Bit()
92 )
93 ("hyperlink-support,l",
94 value<bool>(&m_hyperlinkSupport)->default_value(true),
95 tr(
96 "Support PDF Hyperlinks\n"
97 "Follow hyperlinks when clicked (mouse pointer will change to a pointing hand) - set this to false if "
98 "you cannot reliably control your mouse pointer position and want to always go ahead one slide on click.").toLocal8Bit()
99 )
100 ("cache-to-memory",
101 value<bool>(&m_cacheToMemory)->default_value(true),
102 tr(
103 "Cache the PDF file into memory\n"
104 "Useful if you are editing the PDF file with latex while using the presenter software.").toLocal8Bit()
105 )
106 ("cache-size",
107 value<unsigned>(&m_cacheSizeMegaBytes)->default_value(1024),
108 tr(
109 "Size of the cache for pre-rendered pages, in megabytes."
110 ).toLocal8Bit()
111 )
112 ("i3-workaround",
113 value<bool>(&m_i3workaround)->default_value(false),
114 tr(
115 "Use i3 specific workaround: Execute shellcode once both windows have been created.")
116 #ifndef NDEBUG
117 .append( QString::fromUtf8(
118 "\nDebug info: Shellcode is \n"
119 I3WORKAROUND_SHELLCODE
120 ) )
121 #endif
122 .toLocal8Bit()
123 )
124 ;
125 options_description secondscreen( tr("Options affecting the second screen").toLocal8Bit().constData() );
126 secondscreen.add_options()
127 ("use-second-screen,u",
128 value<bool>(&m_useSecondScreen)->default_value(true),
129 tr(
130 "Use the second screen. If you only have one monitor and just want to use this application as a fast, pre-caching PDF viewer"
131 " you might want to say 0 here.\n"
132 "NOTE: Whatever you say on -a, -t, -w, -s or -p doesn't matter if you set this to false.\n"
133 "NOTE: You might want to say -f if you set this to false."
134 ).toLocal8Bit()
135 )
136 ("presenter-area,a",
137 value<bool>(&m_showPresenterArea)->default_value(true),
138 tr(
139 "Shows or hides the complete \"presenter area\" on the second screen, giving you a full-screen note page.\n"
140 "NOTE: Whatever you say on -t, -w, -s or -p doesnt matter if you set this to false."
141 ).toLocal8Bit()
142 )
143 ("duplicate,d",
144 value<bool>(&m_duplicate)->default_value(false),
145 tr("Duplicates the audience's screen next to the notes on the second screen.").toLocal8Bit()
146 )
147 ("thumbnails,t",
148 value<bool>(&m_showThumbnails)->default_value(true),
149 tr(
150 "Show thumbnails of previous, current and next slide").toLocal8Bit()
151 )
152 ("thumbnail-page-part,T",
153 value<PagePart>(&m_thumbnailPagePart)->default_value(PagePart::FullPage),
154 tr("Thumbnails show this page part. Valid values are \"left\", \"right\" or \"both\"").toLocal8Bit()
155 )
156 ("wall-clock,w",
157 value<bool>(&m_showWallClock)->default_value(true),
158 tr(
159 "Show the wall clock").toLocal8Bit()
160 )
161 ("presentation-clock,p",
162 value<bool>(&m_showPresentationClock)->default_value(true),
163 tr(
164 "Show the presentation clock").toLocal8Bit()
165 )
166 ("slide-clock,s",
167 value<bool>(&m_showSlideClock)->default_value(true),
168 tr("Show the slide clock").toLocal8Bit()
169 )
170 ("bottom-pane-height,b",
171 value<unsigned>(&m_bottomPaneHeightPercent)->default_value(20),
172 tr("Percentage of second screen to use for the bottom pane").toLocal8Bit()
173 )
174 ;
175
176 options_description hidden(tr("Hidden options").toLocal8Bit().constData());
177 hidden.add_options()
178 ("pdf-file", value< string >(&m_filePath), tr("PDF File to display").toLocal8Bit())
179 ;
180 positional_options_description p;
181 p.add("pdf-file", 1);
182
183 options_description help;
184 help.add(generic).add(global).add(secondscreen);
185
186
187
188 options_description commandLineOptions;
189 commandLineOptions.add(help).add(hidden);
190
191 options_description configFileOptions;
192 configFileOptions.add(global).add(secondscreen);
193
194 variables_map vm;
195 store( command_line_parser(argc,argv).options(commandLineOptions).positional(p).run(), vm);
196 QString configurationFileLocation = QString::fromUtf8( qgetenv("HOME").append("/.config/dspdfviewer.ini") );
197 {
198 // See if the configuration file exists and is readable
199 std::ifstream cfile( qPrintable(configurationFileLocation) );
200 if ( cfile.good() ) {
201 store( parse_config_file( cfile, configFileOptions), vm);
202 }
203 } // close input file
204 notify(vm);
205
206 if ( vm.count("version") || vm.count("help") ) {
207 cout << "dspdfviewer version " << DSPDFVIEWER_VERSION << endl;
208 cout << tr( "Written by Danny Edel\n"
209 "\n"
210 "Copyright (C) 2012 Danny Edel.\n"
211 "This is free software; see the source for copying conditions. There is NO\n"
212 "warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.").toLocal8Bit().constData() << endl;
213 if ( vm.count("help")) {
214 cout << endl;
215 cout << tr("Usage: %1 [options] pdf-file").arg( QString::fromUtf8(argv[0]) ).toLocal8Bit().constData() << endl;
216 cout << help << endl;
217 /*: Please try to keep line length below 70 chars and use \t (tab) for padding */
218 cout << tr("Interactive Controls:\n"
219 "\tPress F1 or ? during program execution to get a quick\n"
220 "\toverview about available controls.\n"
221 "\tPlease read the manpage (man dspdfviewer) for the full list.").toLocal8Bit().constData() << endl;
222 }
223 exit(0);
224 }
225
226 if ( m_bottomPaneHeightPercent < 1 || m_bottomPaneHeightPercent > 99 ) {
227 throw std::runtime_error( tr("Invalid height in specified. Please use a value from 1 to 99 (inclusive)").toLocal8Bit().constData() );
228 }
229
230 m_useFullPage = ( 0 < vm.count("full-page") );
231
232 /** Implied options */
233 if ( ! m_useSecondScreen ) {
234 /* If we dont use a second screen, there's no point in using the presenter area */
235 m_showPresenterArea = false;
236 }
237 if ( ! m_showPresenterArea ) {
238 /* If the presenter area is hidden, disable all clocks and the thumbnails */
239 m_showPresentationClock = false;
240 m_showWallClock = false;
241 m_showSlideClock = false;
242 /* This option will effectively disable rendering of thumbnails */
243 m_showThumbnails = false;
244 }
245 }
246
filePath() const247 string RuntimeConfiguration::filePath() const
248 {
249 if ( m_filePath.empty() ) {
250 throw noFileNameException();
251 }
252
253 return m_filePath;
254 }
255
filePathQString() const256 QString RuntimeConfiguration::filePathQString() const
257 {
258 return QString::fromLocal8Bit( filePath().c_str() );
259 }
260
useFullPage() const261 bool RuntimeConfiguration::useFullPage() const
262 {
263 return m_useFullPage;
264 }
265
showPresentationClock() const266 bool RuntimeConfiguration::showPresentationClock() const
267 {
268 return m_showPresentationClock;
269 }
showPresenterArea() const270 bool RuntimeConfiguration::showPresenterArea() const
271 {
272 return m_showPresenterArea;
273 }
duplicate() const274 bool RuntimeConfiguration::duplicate() const
275 {
276 return m_duplicate;
277 }
showSlideClock() const278 bool RuntimeConfiguration::showSlideClock() const
279 {
280 return m_showSlideClock;
281 }
showThumbnails() const282 bool RuntimeConfiguration::showThumbnails() const
283 {
284 return m_showThumbnails;
285 }
showWallClock() const286 bool RuntimeConfiguration::showWallClock() const
287 {
288 return m_showWallClock;
289 }
290
prerenderNextPages() const291 unsigned int RuntimeConfiguration::prerenderNextPages() const
292 {
293 return m_prerenderNextPages;
294 }
prerenderPreviousPages() const295 unsigned int RuntimeConfiguration::prerenderPreviousPages() const
296 {
297 return m_prerenderPreviousPages;
298 }
299
useSecondScreen() const300 bool RuntimeConfiguration::useSecondScreen() const
301 {
302 return m_useSecondScreen;
303 }
304
cacheSetting() const305 PDFCacheOption RuntimeConfiguration::cacheSetting() const
306 {
307 return m_cacheToMemory?
308 PDFCacheOption::keepPDFinMemory :
309 PDFCacheOption::rereadFromDisk;
310 }
311
bottomPaneHeight() const312 unsigned int RuntimeConfiguration::bottomPaneHeight() const
313 {
314 return m_bottomPaneHeightPercent;
315 }
316
hyperlinkSupport() const317 bool RuntimeConfiguration::hyperlinkSupport() const
318 {
319 return m_hyperlinkSupport;
320 }
321
filePath(const std::string & newPath)322 void RuntimeConfiguration::filePath(const std::string& newPath )
323 {
324 m_filePath = newPath;
325 }
326
filePathDefined() const327 bool RuntimeConfiguration::filePathDefined() const
328 {
329 return ! m_filePath.empty();
330 }
331
noFileNameException()332 noFileNameException::noFileNameException():
333 logic_error( QCoreApplication::translate("DSPDFViewer", "You did not specify a PDF-File to display.").toLocal8Bit().constData() ) {
334 }
335
i3workaround() const336 bool RuntimeConfiguration::i3workaround() const
337 {
338 return m_i3workaround;
339 }
340
i3workaround_shellcode() const341 std::string RuntimeConfiguration::i3workaround_shellcode() const
342 {
343 return std::string( I3WORKAROUND_SHELLCODE );
344 }
345
thumbnailPagePart() const346 PagePart RuntimeConfiguration::thumbnailPagePart() const
347 {
348 return m_thumbnailPagePart;
349 }
350
cacheSizeBytes() const351 unsigned RuntimeConfiguration::cacheSizeBytes() const {
352 return cacheSizeMegaBytes()*1024*1024;
353 }
354
cacheSizeMegaBytes() const355 unsigned RuntimeConfiguration::cacheSizeMegaBytes() const{
356 return m_cacheSizeMegaBytes;
357 }
358