Ian Jauslin
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'src/mainwindow.cpp')
-rw-r--r--src/mainwindow.cpp413
1 files changed, 413 insertions, 0 deletions
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(){}