Ian Jauslin
summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/config.cpp115
-rw-r--r--src/config.h50
-rw-r--r--src/main.cpp30
-rw-r--r--src/mainwindow.cpp413
-rw-r--r--src/mainwindow.h126
-rw-r--r--src/mainwindow.ui40
-rw-r--r--src/pdfPresentation2.pro34
-rw-r--r--src/pdfWindow.cpp139
-rw-r--r--src/pdfWindow.h68
-rw-r--r--src/secondarywindow.ui39
10 files changed, 1054 insertions, 0 deletions
diff --git a/src/config.cpp b/src/config.cpp
new file mode 100644
index 0000000..60e3345
--- /dev/null
+++ b/src/config.cpp
@@ -0,0 +1,115 @@
+/*
+Copyright 2015 Ian Jauslin
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+#include "config.h"
+
+#define READMODE_DEFAULT 0
+#define READMODE_TIME 1
+#define READMODE_SLIDELIST 2
+
+// constructor
+Config::Config(int argc,char* argv[]){
+ // defaults
+ loadDefaults();
+ // CLI options
+ readconf(argc,argv);
+}
+
+// default values
+void Config::loadDefaults(){
+ document_path='\0';
+ presentation_time=15;
+ slidelist_path='\0';
+}
+
+// read CLI options
+void Config::readconf(int argc,char* argv[]){
+ int i;
+ // mode specifier (e.g. reading duration?)
+ int mode=READMODE_DEFAULT;
+ // loop over arguments
+ for(i=1;i<argc;i++){
+ // the i=th argument
+ char* arg=argv[i];
+ // behavior depends on mode
+ switch(mode){
+ // default mode
+ case READMODE_DEFAULT:
+ // - means flagging options should follow
+ if(arg[0]=='-'){
+ // loop over flags following -
+ for(arg++;*arg!='\0';arg++){
+ switch (*arg){
+ // duration flag
+ case 't':
+ //go into duration reading mode (next argument should be the duration)
+ mode=READMODE_TIME;
+ break;
+ // slidelist flag
+ case 's':
+ //go into slidelist reading mode
+ mode=READMODE_SLIDELIST;
+ }
+ }
+ }
+ else{
+ // if the argument does not start with -, then it must denote the path to the PDF file
+ document_path=arg;
+ }
+ break;
+ // read duration mode
+ case READMODE_TIME:
+ //check that the argument is an integer
+ if(check_int(arg)){
+ sscanf(arg,"%d",&presentation_time);
+ }
+ else{
+ printf("syntax error: received argument '-t %s' when -t must be followed by an integer\n",arg);
+ }
+ // back to default mode for next argument
+ mode=READMODE_DEFAULT;
+ break;
+
+ // read slidelist mode
+ case READMODE_SLIDELIST:
+ slidelist_path=arg;
+ // back to default mode for next argument
+ mode=READMODE_DEFAULT;
+ }
+ }
+}
+
+// display configuration options
+void Config::showconf(){
+ printf("document: %s\n",document_path);
+ printf("presentation duration: %d\n",presentation_time);
+ printf("slidelist: %s\n",slidelist_path);
+}
+
+// check whether a string is an integer
+bool Config::check_int(char* string){
+ // yes?
+ bool ret=1;
+ for(;*string!='\0';string++){
+ // is the character a digit?
+ ret=ret && isdigit(*string);
+ }
+ return(ret);
+}
+
+// empty destructor
+Config::~Config(){
+}
diff --git a/src/config.h b/src/config.h
new file mode 100644
index 0000000..4b7bd07
--- /dev/null
+++ b/src/config.h
@@ -0,0 +1,50 @@
+/*
+Copyright 2015 Ian Jauslin
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+#ifndef CONFIG_H
+#define CONFIG_H
+
+#include <stdio.h>
+#include <cctype>
+
+// configuration object (holds options)
+class Config
+{
+ public:
+ // duration of the presentation
+ int presentation_time;
+ // document path
+ char* document_path;
+ // path to slidelist
+ char* slidelist_path;
+
+ // constructor
+ Config(int argc, char* argv[]);
+ // display current options
+ void showconf();
+ // destructor
+ ~Config();
+
+ private:
+ // default values
+ void loadDefaults();
+ // read CLI options
+ void readconf(int argc, char* argv[]);
+ // check whether a string is an integer
+ bool check_int(char* string);
+};
+
+#endif // CONFIG_H
diff --git a/src/main.cpp b/src/main.cpp
new file mode 100644
index 0000000..337ae71
--- /dev/null
+++ b/src/main.cpp
@@ -0,0 +1,30 @@
+/*
+Copyright 2015 Ian Jauslin
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+#include "mainwindow.h"
+#include "config.h"
+#include <QApplication>
+
+int main(int argc, char *argv[])
+{
+ QApplication a(argc, argv);
+ Config* config=new Config(argc,argv);
+ MainWindow w;
+ w.setConfig(config);
+ w.show();
+
+ return a.exec();
+}
diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp
new file mode 100644
index 0000000..60d51f5
--- /dev/null
+++ b/src/mainwindow.cpp
@@ -0,0 +1,413 @@
+/*
+Copyright 2015 Ian Jauslin
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+#include "mainwindow.h"
+#include "ui_mainwindow.h"
+#include "ui_secondarywindow.h"
+
+//constructor
+MainWindow::MainWindow(QWidget *parent):
+ pdfWindow(parent),
+ ui(new Ui::MainWindow)
+{
+ //in order to catch arrow keys
+ QApplication::instance()->installEventFilter(this);
+
+ // reads ui_mainwindow.h
+ ui->setupUi(this);
+ // hard coded ui specs
+ this->loadUi();
+}
+
+// load global configuration object
+void MainWindow::setConfig(Config* config){
+ // initialize constants
+ pres_time_step=0;
+ secondaryWindow=NULL;
+ timebar=NULL;
+
+ conf=config;
+ if(conf->document_path=='\0'){
+ std::cout << "error: no document loaded\n";
+ return;
+ }
+ this->setDoc(conf->document_path);
+ this->readSlidelist(conf->slidelist_path);
+ // secondaryScreen must be called after setDoc
+ this->secondaryScreen();
+}
+
+// read list of frame numbers
+void MainWindow::readSlidelist(char* path){
+ // if file has been spcified
+ if(path!='\0'){
+ // list as a vector of integers
+ slidelist=QVector<int>(100,-1);
+ QFile file(path);
+ file.open(QIODevice::ReadOnly | QIODevice::Text);
+ int i=0;
+ // number read
+ int slidenum;
+ while (!file.atEnd()) {
+ const char* line = file.readLine().constData();
+ // if line is an integer
+ if(check_int(line)){
+ sscanf(line,"%d",&slidenum);
+ slidelist[i]=slidenum;
+ i++;
+ }
+ }
+ // resize slidelist to its actual size
+ slidelist.resize(i);
+ }
+}
+
+// check whether a string is an integer
+bool MainWindow::check_int(const char* string){
+ // yes?
+ bool ret=1;
+ for(;*string!='\n';string++){
+ // is the character a digit?
+ ret=ret && isdigit(*string);
+ }
+ return(ret);
+}
+
+
+// setup secondary screen
+void MainWindow::secondaryScreen(){
+ // desktop manager information
+ QDesktopWidget* desktop=QApplication::desktop();
+ const int nrscreens=desktop->screenCount();
+ if(nrscreens>=2){
+ // screen indices
+ nrMainScreen=(int)desktop->primaryScreen();
+ nrSecScreen=nrMainScreen+1%nrscreens;
+
+ if(secondaryWindow){delete secondaryWindow;}
+ secondaryWindow=new SecondaryWindow(this);
+ secondaryWindow->show();
+ secondaryWindow->setDoc(doc);
+
+ moveToScreen(this,nrMainScreen,desktop);
+ moveToScreen(secondaryWindow,nrSecScreen,desktop);
+ secondaryWindow->fullscreenPDF();
+
+ this->showhideTimeBar();
+ }
+}
+
+// exchange role of screens
+void MainWindow::exchangeScreens(){
+ if(secondaryWindow){
+ // desktop manager information
+ QDesktopWidget* desktop=QApplication::desktop();
+ // was the main window fullscreen? (the secondary one necessarily was)
+ bool wasFullscreen=0;
+ if(this->isFullScreen()){
+ wasFullscreen=1;
+ // no fullscreen when moving
+ this->showNormal();
+ }
+ secondaryWindow->showNormal();
+ moveToScreen(this,nrSecScreen,desktop);
+ moveToScreen(secondaryWindow,nrMainScreen,desktop);
+ if(wasFullscreen){
+ // workaround: if called immediately, the desktop manager makes the window fullscreen on the wrong screen
+ QTimer::singleShot(10, this, SLOT(showFullScreen()));
+ // this->showFullScreen();
+ }
+ // workaround: if called immediately, the desktop manager makes the window fullscreen on the wrong screen
+ QTimer::singleShot(10, secondaryWindow, SLOT(showFullScreen()));
+ // secondaryWindow->showFullScreen();
+ //exchange the indices
+ int tmp=nrMainScreen;
+ nrMainScreen=nrSecScreen;
+ nrSecScreen=tmp;
+ }
+}
+
+// next PDF page with offset for secondary screen
+void MainWindow::nextPage(){
+ // should this be here?
+ // secondaryWindow->showFullScreen();
+ this->pdfWindow::nextPage();
+ if(secondaryWindow){
+ if(curpage<totalpages-1 || secondaryWindow->curpage<totalpages-2){
+ secondaryWindow->gotoPage(curpage-1);
+ }
+ else{
+ secondaryWindow->gotoPage(curpage);
+ }
+ }
+}
+// previous PDF page with offset for secondary screen
+void MainWindow::previousPage(){
+ if(!secondaryWindow || secondaryWindow->curpage<totalpages-1){
+ this->pdfWindow::previousPage();
+ }
+ if(secondaryWindow){
+ if(curpage>0){
+ secondaryWindow->gotoPage(curpage-1);
+ }
+ else{
+ secondaryWindow->gotoPage(curpage);
+ }
+ }
+}
+// go to page on secondary screen +1 page on main screen
+void MainWindow::gotoPage(int page){
+ if(!secondaryWindow){
+ this->pdfWindow::gotoPage(page);
+ }
+ else if (page<totalpages-1){
+ this->pdfWindow::gotoPage(page+1);
+ secondaryWindow->gotoPage(page);
+ }
+ else{
+ this->pdfWindow::gotoPage(totalpages);
+ secondaryWindow->gotoPage(totalpages);
+ }
+}
+
+void MainWindow::nextSlide(){
+ int i;
+ for(i=0;i<slidelist.size();i++){
+ if(slidelist.at(i)>secondaryWindow->curpage+1){
+ this->gotoPage(slidelist.at(i)-1);
+ break;
+ }
+ }
+}
+void MainWindow::previousSlide(){
+ int i;
+ int size=slidelist.size();
+ for(i=0;i<size;i++){
+ if(slidelist.at(size-i-1)<secondaryWindow->curpage+1){
+ this->gotoPage(slidelist.at(size-i-1)-1);
+ break;
+ }
+ }
+}
+
+
+// show/hide time bar
+void MainWindow::showhideTimeBar(){
+ if(timebar){
+ // remove timebar
+ ui->centralWidget->layout()->removeWidget(timebar);
+ delete timebar;
+ timebar=NULL;
+ // so that the view covers the entire height
+ this->verticalOffset=0;
+ this->updatePDF();
+ }
+ else{
+ timebar=new TimeIndicator();
+ // initial time
+ timebar->setTime(pres_time_step,conf->presentation_time*60);
+ // add to window
+ ui->centralWidget->layout()->addWidget(timebar);
+ // so that the view leaves room for the bar
+ this->verticalOffset=timebar->sizeHint().height();
+ this->updatePDF();
+ }
+}
+
+// start/stop timer
+void MainWindow::startstopTimer(){
+ if(pres_timer.isActive()){
+ pres_timer.stop();
+ }
+ else{
+ pres_timer.start(1000,this);
+ }
+}
+
+//reset timer
+void MainWindow::resetTimer(){
+ if(pres_timer.isActive()){
+ pres_timer.stop();
+ }
+ pres_time_step=0;
+ timebar->setTime(0,1);
+}
+
+//called when pres_timer clicks: update timebar
+void MainWindow::timerEvent(QTimerEvent *event){
+ if (event->timerId() == pres_timer.timerId()) {
+ pres_time_step++;
+ // stop if end is reached
+ if(pres_time_step>=conf->presentation_time*60){
+ pres_timer.stop();
+ }
+ if(timebar){
+ timebar->setTime(pres_time_step,conf->presentation_time*60);
+ }
+ }
+}
+
+// move (non-fullscreen) window to a screen
+void MainWindow::moveToScreen(QWidget* widget,int ascreen,QDesktopWidget* desktop){
+ if(desktop->isVirtualDesktop()){
+ QRect geo=desktop->screenGeometry(ascreen);
+ // move and center
+ widget->move(QPoint(geo.x()+geo.width()/2-this->width()/2,geo.y()+geo.height()/2-this->height()/2));
+ }
+ else{
+ std::cout << "Sorry, so far multiple screens are only supported on X11\n";
+ }
+}
+
+// load hard coded UI
+void MainWindow::loadUi(){
+ // window layout
+ layout=new QVBoxLayout;
+ // view
+ layout->addWidget(pdfView);
+ // to get rid of extra space
+ layout->setContentsMargins(0,0,0,0);
+ layout->setSpacing(0);
+ // remove scrollbars
+ pdfView->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
+ pdfView->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
+ ui->centralWidget->setLayout(layout);
+}
+
+void MainWindow::keyPressEvent(QKeyEvent* event){
+ switch(event->key()){
+ case Qt::Key_Right:
+ this->nextPage();
+ break;
+ case Qt::Key_Left:
+ this->previousPage();
+ break;
+ case Qt::Key_Down:
+ this->nextSlide();
+ break;
+ case Qt::Key_Up:
+ this->previousSlide();
+ break;
+ case Qt::Key_F:
+ this->fullscreenPDF();
+ break;
+ case Qt::Key_Q:
+ QApplication::instance()->quit();
+ break;
+ case Qt::Key_S:
+ this->startstopTimer();
+ break;
+ case Qt::Key_T:
+ this->showhideTimeBar();
+ break;
+ case Qt::Key_R:
+ this->resetTimer();
+ break;
+ case Qt::Key_X:
+ this->exchangeScreens();
+ break;
+ default:
+ std::cout << "unknown key pressed: " << event->key() << '\n';
+ break;
+ }
+}
+
+// to catch arrow keys
+bool MainWindow::eventFilter(QObject *obj, QEvent *event)
+{
+ QKeyEvent *keyEvent = NULL;//event data, if this is a keystroke event
+ bool result = false;//return true to consume the keystroke
+
+ if (event->type() == QEvent::KeyPress)
+ {
+ keyEvent = dynamic_cast<QKeyEvent*>(event);
+ this->keyPressEvent(keyEvent);
+ result = true;
+ }//if type()
+
+ else if (event->type() == QEvent::KeyRelease)
+ {
+ keyEvent = dynamic_cast<QKeyEvent*>(event);
+ this->keyReleaseEvent(keyEvent);
+ result = true;
+ }//else if type()
+
+ //### Standard event processing ###
+ else
+ result = QObject::eventFilter(obj, event);
+
+ return result;
+}//eventFilter
+
+// destructor
+MainWindow::~MainWindow(){
+ if(timebar){delete timebar;}
+ delete layout;
+ if(secondaryWindow){delete secondaryWindow;}
+ delete ui;
+}
+
+
+
+
+//secondary window ----------------------------------
+
+// constructor
+SecondaryWindow::SecondaryWindow(QWidget *parent):
+ pdfWindow(parent),
+ ui(new Ui::SecondaryWindow)
+{
+ ui->setupUi(this);
+ this->loadUi();
+}
+
+// UI
+void SecondaryWindow::loadUi(){
+ QHBoxLayout* layout=new QHBoxLayout;
+ layout->addWidget(pdfView);
+ pdfView->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
+ pdfView->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
+ ui->centralWidget->setLayout(layout);
+ delete layout;
+}
+
+// destructor
+SecondaryWindow::~SecondaryWindow(){
+ delete ui;
+}
+
+
+
+
+// TimeIndicator--------------------------------------------------
+
+//contructor (completely inherited)
+TimeIndicator::TimeIndicator(QWidget *parent): QProgressBar(parent){}
+
+// set value of progress bar as well as text
+void TimeIndicator::setTime(int time,int maxtime){
+ this->setValue((time*100)/maxtime);
+ // string representing elapsed time
+ char timestr[9];
+ int hour=time/3600;
+ int minute=(time-hour*3600)/60;
+ int second=time-hour*3600-minute*60;
+ sprintf(timestr,"%02d:%02d:%02d",hour,minute,second);
+ this->setFormat(QString(timestr));
+}
+
+// destructor
+TimeIndicator::~TimeIndicator(){}
diff --git a/src/mainwindow.h b/src/mainwindow.h
new file mode 100644
index 0000000..4e4aa77
--- /dev/null
+++ b/src/mainwindow.h
@@ -0,0 +1,126 @@
+/*
+Copyright 2015 Ian Jauslin
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+#ifndef MAINWINDOW_H
+#define MAINWINDOW_H
+
+#include "pdfWindow.h"
+#include "config.h"
+#include <QKeyEvent>
+#include <QDesktopWidget>
+#include <QProgressBar>
+#include <QBasicTimer>
+#include <QTimer>
+#include <cctype>
+
+namespace Ui {
+ class MainWindow;
+ class SecondaryWindow;
+}
+
+class SecondaryWindow;
+class TimeIndicator;
+
+class MainWindow : public pdfWindow
+{
+ Q_OBJECT
+
+ public:
+ // index of main screen
+ int nrMainScreen;
+ // index of secondary screen
+ int nrSecScreen;
+ // timer counter
+ int pres_time_step;
+ SecondaryWindow* secondaryWindow;
+ // slidelist
+ QVector<int> slidelist;
+
+ // constructor
+ explicit MainWindow(QWidget *parent = 0);
+
+ void setConfig(Config* config);
+
+ //enable secondary screen
+ void secondaryScreen();
+ void exchangeScreens();
+ void moveToScreen(QWidget* widget,int screen,QDesktopWidget* desktop);
+
+ void nextPage();
+ void previousPage();
+ void gotoPage(int page);
+ void nextSlide();
+ void previousSlide();
+
+ void showhideTimeBar();
+ void startstopTimer();
+ void resetTimer();
+
+ // destructor
+ ~MainWindow();
+
+ private:
+ // global comnfiguration object
+ Config* conf;
+ // presentation timer
+ QBasicTimer pres_timer;
+ // Main layout
+ QVBoxLayout* layout;
+ TimeIndicator* timebar;
+ Ui::MainWindow *ui;
+
+ void loadUi();
+ void readSlidelist(char* path);
+ void keyPressEvent(QKeyEvent* event);
+ // to get arrow keys
+ bool eventFilter(QObject *obj, QEvent *event);
+
+ //called by pres_timer
+ void timerEvent(QTimerEvent *event);
+
+ // check whether a string is an integer
+ bool check_int(const char* string);
+};
+
+
+class SecondaryWindow : public pdfWindow
+{
+ Q_OBJECT
+
+ public:
+ // constructor
+ explicit SecondaryWindow(QWidget* parent = 0);
+ // destructor
+ ~SecondaryWindow();
+
+ private:
+ Ui::SecondaryWindow *ui;
+ void loadUi();
+};
+
+// time progress bar
+class TimeIndicator : public QProgressBar
+{
+ Q_OBJECT
+ public:
+ // constructor
+ explicit TimeIndicator(QWidget* parent = 0);
+ // destructore
+ ~TimeIndicator();
+ void setTime(int time,int maxtime);
+};
+
+#endif // MAINWINDOW_H
diff --git a/src/mainwindow.ui b/src/mainwindow.ui
new file mode 100644
index 0000000..fa53891
--- /dev/null
+++ b/src/mainwindow.ui
@@ -0,0 +1,40 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+Copyright 2015 Ian Jauslin
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+-->
+
+<ui version="4.0">
+ <class>MainWindow</class>
+ <widget class="QMainWindow" name="MainWindow">
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>400</width>
+ <height>300</height>
+ </rect>
+ </property>
+ <property name="windowTitle">
+ <string>pdfPresentation</string>
+ </property>
+ <widget class="QWidget" name="centralWidget">
+ </widget>
+ <!-- <widget class="QStatusBar" name="statusBar"/> -->
+ </widget>
+ <layoutdefault spacing="0" margin="0"/>
+ <resources/>
+ <connections/>
+</ui>
diff --git a/src/pdfPresentation2.pro b/src/pdfPresentation2.pro
new file mode 100644
index 0000000..2d5522f
--- /dev/null
+++ b/src/pdfPresentation2.pro
@@ -0,0 +1,34 @@
+## Copyright 2015 Ian Jauslin
+##
+## Licensed under the Apache License, Version 2.0 (the "License");
+## you may not use this file except in compliance with the License.
+## You may obtain a copy of the License at
+##
+## http://www.apache.org/licenses/LICENSE-2.0
+##
+## Unless required by applicable law or agreed to in writing, software
+## distributed under the License is distributed on an "AS IS" BASIS,
+## WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+## See the License for the specific language governing permissions and
+## limitations under the License.
+
+QT += core gui
+
+greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
+
+TARGET = build/pdfPresentation
+TEMPLATE = app
+
+SOURCES += main.cpp\
+ mainwindow.cpp\
+ pdfWindow.cpp\
+ config.cpp
+
+HEADERS += mainwindow.h\
+ pdfWindow.h\
+ config.h
+
+FORMS += mainwindow.ui\
+ secondarywindow.ui
+
+LIBS += -lpoppler-qt4
diff --git a/src/pdfWindow.cpp b/src/pdfWindow.cpp
new file mode 100644
index 0000000..e4ca3e4
--- /dev/null
+++ b/src/pdfWindow.cpp
@@ -0,0 +1,139 @@
+/*
+Copyright 2015 Ian Jauslin
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+#include "pdfWindow.h"
+
+// constructor
+pdfWindow::pdfWindow(QWidget *parent) :
+ QMainWindow(parent)
+{
+ // set defaults
+ fullscreen=0;
+ curpage=0;
+ totalpages=0;
+ verticalOffset=0;
+ document=NULL;
+
+ //scene to draw the view
+ pdfViewScene=new QGraphicsScene;
+ pdfView=new QGraphicsView(pdfViewScene);
+}
+
+// set PDF document
+void pdfWindow::setDoc(char* file){
+ if(document){delete document;}
+ doc=file;
+
+ QString filename=file;
+ document = Poppler::Document::load(filename);
+ if(document){
+ // display options
+ document->setRenderHint(Poppler::Document::Antialiasing,true);
+ document->setRenderHint(Poppler::Document::TextAntialiasing,true);
+
+ curpage=0;
+ totalpages=document->numPages();
+ this->updatePDF();
+ }
+}
+
+void pdfWindow::gotoPage(int page){
+ if(page<totalpages && page>=0){
+ curpage=page;
+ this->updatePDF();
+ }
+}
+void pdfWindow::nextPage(){
+ if(curpage<totalpages-1){
+ curpage++;
+ this->updatePDF();
+ }
+}
+void pdfWindow::previousPage(){
+ if(curpage>0){
+ curpage--;
+ this->updatePDF();
+ }
+}
+
+// toggle fullscreen
+void pdfWindow::fullscreenPDF(){
+ if(!fullscreen){
+ fullscreen=1;
+ this->showFullScreen();
+ }
+ else{
+ fullscreen=0;
+ this->showNormal();
+ }
+}
+
+// draw (or redraw) PDF
+void pdfWindow::updatePDF(){
+ // current page
+ Poppler::Page* pdfPage = document->page(curpage);
+ if(!pdfPage){
+ std::cout << "Error: could not load page " << curpage << '\n';
+ return;
+ }
+
+ // total size available
+ QSize windowsize=this->size();
+ // verticalOffset to allow timebar
+ QSize viewSize(windowsize.width()+2,windowsize.height()+2-verticalOffset);
+ pdfView->setGeometry(-1,-1,viewSize.width(),viewSize.height());
+
+ // page size in points (1/72 inch)
+ QSize pageSize=pdfPage->pageSize();
+ // aspect ratio
+ double aspect=double(pageSize.width())/double(pageSize.height());
+ // an image to display the page
+ QImage image;
+ // keep aspect ratop
+ if(viewSize.width()<=aspect*viewSize.height()){
+ // render PDF page with appropriate resolution (pix/inch)
+ image = pdfPage->renderToImage(72*viewSize.width()/pageSize.width(),72*viewSize.width()/aspect/pageSize.height(),0,0,viewSize.width(),viewSize.width()/aspect);
+ }
+ else{
+ // render PDF page with appropriate resolution (pix/inch)
+ image = pdfPage->renderToImage(72*viewSize.height()*aspect/pageSize.width(),72*viewSize.height()/pageSize.height(),0,0,viewSize.height()*aspect,viewSize.height());
+ }
+ delete pdfPage;
+
+ // update scene
+ delete pdfViewScene;
+ pdfViewScene=new QGraphicsScene;
+ pdfView->setScene(pdfViewScene);
+ pdfViewScene->setBackgroundBrush(Qt::black);
+ // draw image
+ pdfViewScene->addPixmap(QPixmap::fromImage(image));
+}
+
+// respond to resize
+void pdfWindow::resizeEvent(QResizeEvent* event){
+ if(document){
+ this->updatePDF();
+ }
+
+ QMainWindow::resizeEvent(event);
+}
+
+// destructor
+pdfWindow::~pdfWindow(){
+ if(document){delete document;}
+ delete pdfView;
+ delete pdfViewScene;
+}
diff --git a/src/pdfWindow.h b/src/pdfWindow.h
new file mode 100644
index 0000000..e3415d3
--- /dev/null
+++ b/src/pdfWindow.h
@@ -0,0 +1,68 @@
+/*
+Copyright 2015 Ian Jauslin
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+#ifndef PDFWINDOW_H
+#define PDFWINDOW_H
+
+#include <QMainWindow>
+#include <poppler/qt4/poppler-qt4.h>
+#include <iostream>
+#include <QGraphicsScene>
+#include <QGraphicsView>
+#include <QBoxLayout>
+
+
+class pdfWindow : public QMainWindow
+{
+ Q_OBJECT
+
+public:
+ // PDF document path
+ char* doc;
+ // current page
+ int curpage;
+ int totalpages;
+ // is fullscreen ?
+ bool fullscreen;
+ // offset for pdfView
+ int verticalOffset;
+
+ // constructor
+ explicit pdfWindow(QWidget *parent = 0);
+ void setDoc(char* file);
+ void gotoPage(int page);
+ void nextPage();
+ void previousPage();
+ // toggle fullscreen
+ void fullscreenPDF();
+ // destructor
+ ~pdfWindow();
+
+
+protected:
+ // document
+ Poppler::Document* document;
+ // to draw the view
+ QGraphicsScene* pdfViewScene;
+ QGraphicsView* pdfView;
+
+ // display PDF
+ void updatePDF();
+ // respond to window resize
+ void resizeEvent(QResizeEvent* event);
+};
+
+#endif // PDFWINDOW_H
diff --git a/src/secondarywindow.ui b/src/secondarywindow.ui
new file mode 100644
index 0000000..25d7364
--- /dev/null
+++ b/src/secondarywindow.ui
@@ -0,0 +1,39 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+Copyright 2015 Ian Jauslin
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+-->
+
+<ui version="4.0">
+ <class>SecondaryWindow</class>
+ <widget class="QMainWindow" name="SecondaryWindow">
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>400</width>
+ <height>300</height>
+ </rect>
+ </property>
+ <property name="windowTitle">
+ <string>pdfPresentation</string>
+ </property>
+ <widget class="QWidget" name="centralWidget">
+ </widget>
+ </widget>
+ <layoutdefault spacing="6" margin="11"/>
+ <resources/>
+ <connections/>
+</ui>