/* 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(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(curpagecurpagegotoPage(curpage-1); } else{ secondaryWindow->gotoPage(curpage); } } } // previous PDF page with offset for secondary screen void MainWindow::previousPage(){ if(!secondaryWindow || secondaryWindow->curpagepdfWindow::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 (pagepdfWindow::gotoPage(page+1); secondaryWindow->gotoPage(page); } else{ this->pdfWindow::gotoPage(totalpages); secondaryWindow->gotoPage(totalpages); } } void MainWindow::nextSlide(){ int i; for(i=0;isecondaryWindow->curpage+1){ this->gotoPage(slidelist.at(i)-1); break; } } } void MainWindow::previousSlide(){ int i; int size=slidelist.size(); for(i=0;icurpage+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(event); this->keyPressEvent(keyEvent); result = true; }//if type() else if (event->type() == QEvent::KeyRelease) { keyEvent = dynamic_cast(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(){}