//=========================================== // Lumina Desktop source code // Copyright (c) 2017-2018, Ken Moore // Available under the 3-clause BSD license // See the LICENSE file for full details //=========================================== #include "mainUI.h" #include "ui_mainUI.h" #include #include #include #include #include #include #include #include #include #include #include "PrintWidget.h" #include MainUI::MainUI() : QMainWindow(), ui(new Ui::MainUI()) { ui->setupUi(this); // this->setWindowTitle(tr("Lumina PDF Viewer")); this->setWindowIcon(LXDG::findIcon("application-pdf", "unknown")); presentationLabel = 0; CurrentPage = 1; lastdir = QDir::homePath(); BACKEND = new Renderer(); // Create the interface widgets PROPDIALOG = new PropDialog(BACKEND); BOOKMARKS = new BookmarkMenu(BACKEND, ui->splitter); BOOKMARKS->setContextMenuPolicy(Qt::CustomContextMenu); BOOKMARKS->setVisible(false); WIDGET = new PrintWidget(BACKEND, ui->splitter); WIDGET->setContextMenuPolicy(Qt::CustomContextMenu); ui->splitter->setCollapsible(0, true); ui->splitter->setCollapsible(1, false); clockTimer = new QTimer(this); clockTimer->setInterval(1000); // 1-second updates to clock connect(clockTimer, SIGNAL(timeout()), this, SLOT(updateClock())); label_clock = new QLabel(this); label_clock->setAlignment(Qt::AlignCenter); label_clock->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred); label_clock->setStyleSheet( "QLabel{color: palette(highlight-text); background-color: " "palette(highlight); border-radius: 5px; }"); label_page = new QLabel(this); label_page->setAlignment(Qt::AlignRight | Qt::AlignVCenter); label_page->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::Preferred); contextMenu = new QMenu(this); QObject::connect(contextMenu, SIGNAL(aboutToShow()), this, SLOT(updateContextMenu())); QObject::connect(WIDGET, SIGNAL(customContextMenuRequested(const QPoint &)), this, SLOT(showContextMenu(const QPoint &))); QObject::connect(WIDGET, SIGNAL(currentPageChanged()), this, SLOT(updatePageNumber())); QObject::connect(BACKEND, SIGNAL(PageLoaded()), this, SLOT(slotPageLoaded())); QObject::connect(BACKEND, SIGNAL(SetProgress(int)), this, SLOT(slotSetProgress(int))); QObject::connect(BACKEND, SIGNAL(reloadPages(int)), this, SLOT(startLoadingPages(int))); QObject::connect(BACKEND, SIGNAL(goToPosition(int, float, float)), WIDGET, SLOT(goToPosition(int, float, float))); QObject::connect(ui->splitter, &QSplitter::splitterMoved, this, [=]() { double percent = qBound( 0.0, (ui->splitter->sizes().first() / (double)this->width()) * 100.0, 33.3); ui->splitter->setSizes(QList() << this->width() * (percent / 100.0) << this->width() * ((100.0 - percent) / 100.0)); }); PrintDLG = new QPrintDialog(this); QObject::connect(PrintDLG, SIGNAL(accepted(QPrinter *)), this, SLOT(paintToPrinter(QPrinter *))); // connect(ui->menuStart_Presentation, SIGNAL(triggered(QAction*)), this, // SLOT(slotStartPresentation(QAction*)) ); // Create the other interface widgets progress = new QProgressBar(this); progress->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred); progress->setFormat("%v/%m (%p%)"); // [current]/[total] progAct = ui->toolBar->addWidget(progress); progAct->setVisible(false); clockAct = ui->toolBar->addWidget(label_clock); clockAct->setVisible(false); pageAct = ui->toolBar->addWidget(label_page); pageAct->setVisible(false); // Put the various actions into logical groups QActionGroup *tmp = new QActionGroup(this); tmp->setExclusive(true); tmp->addAction(ui->actionFit_Width); tmp->addAction(ui->actionFit_Page); ui->actionFit_Page->setChecked(true); tmp = new QActionGroup(this); tmp->setExclusive(true); tmp->addAction(ui->actionSingle_Page); tmp->addAction(ui->actionDual_Pages); tmp->addAction(ui->actionAll_Pages); ui->actionSingle_Page->setChecked(true); // Connect up the buttons QObject::connect(ui->actionClose, SIGNAL(triggered()), this, SLOT(close())); QObject::connect(ui->actionPrint, SIGNAL(triggered()), PrintDLG, SLOT(open())); QObject::connect(ui->actionFit_Width, SIGNAL(triggered()), WIDGET, SLOT(fitToWidth())); QObject::connect(ui->actionFit_Page, SIGNAL(triggered()), WIDGET, SLOT(fitView())); QObject::connect(ui->actionOpen_PDF, SIGNAL(triggered()), this, SLOT(OpenNewFile())); QObject::connect(ui->actionSingle_Page, SIGNAL(triggered()), WIDGET, SLOT(setSinglePageViewMode())); QObject::connect(ui->actionDual_Pages, SIGNAL(triggered()), WIDGET, SLOT(setFacingPagesViewMode())); QObject::connect(ui->actionAll_Pages, SIGNAL(triggered()), WIDGET, SLOT(setAllPagesViewMode())); // connect(ui->actionScroll_Mode, &QAction::triggered, this, [&] { // this->setScroll(true); }); connect(ui->actionSelect_Mode, // &QAction::triggered, this, [&] { this->setScroll(false); }); QObject::connect(ui->actionZoom_In, &QAction::triggered, WIDGET, [&] { WIDGET->zoomIn(1.2); }); QObject::connect(ui->actionZoom_Out, &QAction::triggered, WIDGET, [&] { WIDGET->zoomOut(1.2); }); QObject::connect(ui->actionRotate_Counterclockwise, &QAction::triggered, this, [&] { if (results.size() != 0) { foreach (TextData *x, results) { x->highlighted(false); } } BACKEND->setDegrees(-90); }); QObject::connect(ui->actionRotate_Clockwise, &QAction::triggered, this, [&] { if (results.size() != 0) { foreach (TextData *x, results) { x->highlighted(false); } } BACKEND->setDegrees(90); }); QObject::connect(ui->actionZoom_In_2, &QAction::triggered, WIDGET, [&] { WIDGET->zoomIn(1.2); }); QObject::connect(ui->actionZoom_Out_2, &QAction::triggered, WIDGET, [&] { WIDGET->zoomOut(1.2); }); QObject::connect(ui->actionFirst_Page, SIGNAL(triggered()), this, SLOT(firstPage())); QObject::connect(ui->actionPrevious_Page, SIGNAL(triggered()), this, SLOT(prevPage())); QObject::connect(ui->actionNext_Page, SIGNAL(triggered()), this, SLOT(nextPage())); QObject::connect(ui->actionLast_Page, SIGNAL(triggered()), this, SLOT(lastPage())); QObject::connect(ui->actionProperties, &QAction::triggered, WIDGET, [&] { PROPDIALOG->show(); }); QObject::connect(BACKEND, &Renderer::OrigSize, this, [&](QSizeF _pageSize) { pageSize = _pageSize; }); QObject::connect(ui->actionFind, &QAction::triggered, this, [&] { if (ui->findGroup->isVisible()) { ui->findGroup->setVisible(false); this->setFocus(); } else { ui->findGroup->setVisible(true); ui->findGroup->setFocus(); } }); QObject::connect(ui->actionFind_Next, &QAction::triggered, this, [&] { find(ui->textEdit->text(), true); }); QObject::connect(ui->actionFind_Previous, &QAction::triggered, this, [&] { find(ui->textEdit->text(), false); }); QObject::connect(ui->findNextB, &QPushButton::clicked, this, [&] { find(ui->textEdit->text(), true); }); QObject::connect(ui->findPrevB, &QPushButton::clicked, this, [&] { find(ui->textEdit->text(), false); }); QObject::connect(ui->matchCase, &QPushButton::clicked, this, [&](bool value) { this->matchCase = value; }); QObject::connect(ui->closeFind, &QPushButton::clicked, this, [&] { ui->findGroup->setVisible(false); this->setFocus(); }); QObject::connect(ui->actionClearHighlights, &QAction::triggered, WIDGET, [&] { WIDGET->updatePreview(); }); QObject::connect(ui->actionBookmarks, &QAction::triggered, this, [=]() { ui->splitter->setSizes(QList() << this->width() / 4 << 3 * this->width() / 4); }); // int curP = WIDGET->currentPage()-1; //currentPage reports pages starting at // 1 int lastP = numPages-1; ui->actionFirst_Page->setText(tr("First Page")); ui->actionPrevious_Page->setText(tr("Previous Page")); ui->actionNext_Page->setText(tr("Next Page")); ui->actionLast_Page->setText(tr("Last Page")); /*ui->actionFirst_Page->setEnabled(curP!=0); ui->actionPrevious_Page->setEnabled(curP>0); ui->actionNext_Page->setEnabled(curPactionLast_Page->setEnabled(curP!=lastP);*/ ui->actionStart_Here->setText(tr("Start Presentation (current slide)")); QObject::connect(ui->actionStart_Here, SIGNAL(triggered()), this, SLOT(startPresentationHere())); ui->actionStart_Begin->setText(tr("Start Presentation (at beginning)")); QObject::connect(ui->actionStart_Begin, SIGNAL(triggered()), this, SLOT(startPresentationBeginning())); ui->actionStop_Presentation->setText(tr("Stop Presentation")); QObject::connect(ui->actionStop_Presentation, SIGNAL(triggered()), this, SLOT(closePresentation())); // Setup all the icons ui->actionPrint->setIcon(LXDG::findIcon("document-print", "")); ui->actionClose->setIcon(LXDG::findIcon("window-close", "")); ui->actionFit_Width->setIcon(LXDG::findIcon("transform-scale", "")); ui->actionFit_Page->setIcon(LXDG::findIcon("zoom-fit-best", "")); ui->actionOpen_PDF->setIcon(LXDG::findIcon("document-open", "")); ui->actionSingle_Page->setIcon( LXDG::findIcon("view-split-top-bottom", "format-view-agenda")); ui->actionDual_Pages->setIcon( LXDG::findIcon("view-split-left-right", "format-view-grid-small")); ui->actionAll_Pages->setIcon( LXDG::findIcon("view-grid", "format-view-grid-large")); ui->actionScroll_Mode->setIcon(LXDG::findIcon("cursor-pointer", "")); ui->actionSelect_Mode->setIcon(LXDG::findIcon("cursor-text", "")); ui->actionZoom_In->setIcon(LXDG::findIcon("zoom-in", "")); ui->actionZoom_Out->setIcon(LXDG::findIcon("zoom-out", "")); ui->actionZoom_In_2->setIcon(LXDG::findIcon("zoom-in", "")); ui->actionZoom_Out_2->setIcon(LXDG::findIcon("zoom-out", "")); ui->actionRotate_Counterclockwise->setIcon( LXDG::findIcon("object-rotate-left", "")); ui->actionRotate_Clockwise->setIcon( LXDG::findIcon("object-rotate-right", "")); ui->actionFirst_Page->setIcon(LXDG::findIcon("go-first", "")); ui->actionPrevious_Page->setIcon(LXDG::findIcon("go-previous", "")); ui->actionNext_Page->setIcon(LXDG::findIcon("go-next", "")); ui->actionLast_Page->setIcon(LXDG::findIcon("go-last", "")); ui->actionStart_Here->setIcon( LXDG::findIcon("video-display", "media-playback-start-circled")); ui->actionStart_Begin->setIcon( LXDG::findIcon("view-presentation", "presentation-play")); ui->actionStop_Presentation->setIcon( LXDG::findIcon("media-playback-stop", "media-playback-stop-circled")); ui->actionBookmarks->setIcon(LXDG::findIcon("bookmark-new", "")); ui->actionFind->setIcon(LXDG::findIcon("edit-find", "")); ui->actionFind_Next->setIcon( LXDG::findIcon("go-down-search", "edit-find-next")); ui->actionFind_Previous->setIcon( LXDG::findIcon("go-up-search", "edit-find-prev")); ui->actionProperties->setIcon(LXDG::findIcon("dialog-information", "")); ui->actionSettings->setIcon(LXDG::findIcon("document-properties", "")); ui->findNextB->setIcon(LXDG::findIcon("go-down-search")); ui->findPrevB->setIcon(LXDG::findIcon("go-up-search")); ui->actionClearHighlights->setIcon(LXDG::findIcon("format-text-clear", "")); ui->findNextB->setIcon(LXDG::findIcon("go-down-search")); ui->matchCase->setIcon(LXDG::findIcon("format-text-italic")); ui->closeFind->setIcon(LXDG::findIcon("dialog-close")); // Now set the default state of the menu's and actions ui->actionStop_Presentation->setEnabled(false); ui->actionStart_Here->setEnabled(false); ui->actionStart_Begin->setEnabled(false); ui->findGroup->setVisible(false); // TESTING features/functionality bool TESTING = BACKEND->supportsExtraFeatures(); ui->actionBookmarks->setEnabled(TESTING); ui->actionBookmarks->setVisible(TESTING); ui->actionProperties->setEnabled(TESTING); ui->actionProperties->setVisible(TESTING); ui->actionClearHighlights->setEnabled(TESTING); ui->actionClearHighlights->setVisible(TESTING); ui->actionSettings->setEnabled(false); ui->actionSettings->setVisible(false); ui->actionScroll_Mode->setEnabled(false); ui->actionScroll_Mode->setVisible(false); ui->actionSelect_Mode->setEnabled(false); ui->actionSelect_Mode->setVisible(false); } MainUI::~MainUI() { if (BOOKMARKS != 0) { BOOKMARKS->deleteLater(); } if (PROPDIALOG != 0) { PROPDIALOG->deleteLater(); } delete BACKEND; } void MainUI::loadFile(QString path) { if (!QFile::exists(path) || path.isEmpty()) { return; } QString password; bool ok = true; while (ok && !BACKEND->loadDocument(path, password) && BACKEND->needPassword()) { password = QInputDialog::getText(this, tr("Unlock PDF"), tr("Password:"), QLineEdit::Password, "", &ok); if (!ok) { break; } // cancelled } // Clear the current display WIDGET->setVisible(false); BOOKMARKS->setVisible(false); // Load the new document info this->setWindowTitle(BACKEND->title()); if (BACKEND->needPassword()) { return; } // cancelled; qDebug() << " - Document Setup : start loading pages now"; // Populate or repopulate the Bookmarks menu and Properties Dialog QTimer::singleShot(10, BOOKMARKS, SLOT(loadBookmarks())); QTimer::singleShot(10, PROPDIALOG, SLOT(setInformation())); QTimer::singleShot(50, [&]() { startLoadingPages(0); }); } QScreen *MainUI::getScreen(bool current, bool &cancelled) { // Note: the "cancelled" boolian is actually an output - not an input QList screens = QApplication::screens(); cancelled = false; if (screens.length() == 1) { return screens[0]; } // only one option // Multiple screens available - figure it out if (current) { // Just return the screen the window is currently on for (int i = 0; i < screens.length(); i++) { if (screens[i]->geometry().contains(this->mapToGlobal(this->pos()))) { return screens[i]; } } // If it gets this far, there was an error and it should just return the // primary screen return QApplication::primaryScreen(); } else { // Ask the user to select a screen (for presentations, etc..) QStringList names; for (int i = 0; i < screens.length(); i++) { QString screensize = QString::number(screens[i]->size().width()) + "x" + QString::number(screens[i]->size().height()); names << QString(tr("%1 (%2)")).arg(screens[i]->name(), screensize); } bool ok = false; QString sel = QInputDialog::getItem(this, tr("Select Screen"), tr("Screen:"), names, 0, false, &ok); cancelled = !ok; if (!ok) { return screens[0]; } // cancelled - just return the first one int index = names.indexOf(sel); if (index < 0) { return screens[0]; } // error - should never happen though return screens[index]; // return the selected screen } } void MainUI::startPresentation(bool atStart) { if (BACKEND->hashSize() == 0) { qDebug() << "MainUI::startPresentation() called while backend is empty!\n"; return; } // just in case bool cancelled = false; QScreen *screen = getScreen( false, cancelled); // let the user select which screen to use (if multiples) if (cancelled) { return; } int page = 1; if (!atStart) { page = WIDGET->currentPage(); } // PDPI = QSize(SCALEFACTOR*screen->physicalDotsPerInchX(), // SCALEFACTOR*screen->physicalDotsPerInchY()); Now create the full-screen // window on the selected screen if (presentationLabel == 0) { // Create the label and any special flags for it presentationLabel = new PresentationLabel(); presentationLabel->setStyleSheet("background-color: black;"); presentationLabel->setAlignment(Qt::AlignCenter); presentationLabel->setContextMenuPolicy(Qt::CustomContextMenu); connect(presentationLabel, SIGNAL(customContextMenuRequested(const QPoint &)), this, SLOT(showContextMenu(const QPoint &))); connect(presentationLabel, SIGNAL(nextSlide()), this, SLOT(nextPage())); } // Now put the label in the proper location presentationLabel->setGeometry(screen->geometry()); presentationLabel->showFullScreen(); ui->actionStop_Presentation->setEnabled(true); ui->actionStart_Here->setEnabled(false); ui->actionStart_Begin->setEnabled(false); updateClock(); updatePageNumber(); clockAct->setVisible(true); clockTimer->start(); QApplication::processEvents(); // Now start at the proper page ShowPage(page); this->grabKeyboard(); // Grab any keyboard events - even from the presentation // window } void MainUI::ShowPage(int page) { // Check for valid document/page // qDebug() << "Load Page:" << page << "/" << BACKEND->numPages() << "Index:" // << page; page = std::max(1, std::min(page, BACKEND->numPages())); if (page == BACKEND->numPages() and CurrentPage == page) { endPresentation(); return; // invalid - no document loaded or invalid page specified } WIDGET->setCurrentPage(page); // page numbers start at 1 for this widget // Stop here if no presentation currently running if (presentationLabel == 0 || !presentationLabel->isVisible()) { WIDGET->updatePreview(); return; } // qDebug() << "Show Page:" << page << "/" << numPages; CurrentPage = page; QImage PAGEIMAGE; if (page < BACKEND->numPages() + 1) { PAGEIMAGE = BACKEND->imageHash(page - 1); } // Now scale the image according to the user-designations and show it if (!PAGEIMAGE.isNull()) { QPixmap pix; pix.convertFromImage(PAGEIMAGE.scaled(presentationLabel->size(), Qt::KeepAspectRatio, Qt::SmoothTransformation)); presentationLabel->setPixmap(pix); presentationLabel->show(); // always make sure it was not hidden } else { // Blank page (useful so there is one blank page after the last slide before // stopping the presentation) presentationLabel->setPixmap(QPixmap()); } } void MainUI::endPresentation() { if (presentationLabel == 0 || !presentationLabel->isVisible()) { return; } // not in presentation mode presentationLabel->hide(); // just hide this (no need to re-create the label // for future presentations) ui->actionStop_Presentation->setEnabled(false); ui->actionStart_Here->setEnabled(true); ui->actionStart_Begin->setEnabled(true); clockTimer->stop(); clockAct->setVisible(false); this->releaseKeyboard(); updatePageNumber(); } void MainUI::startLoadingPages(int degrees) { // qDebug() <<"Start Loading Pages"; // if(BACKEND->hashSize() != 0) { return; } //currently loaded[ing] loadingQueue.clear(); // BACKEND->clearHash(); WIDGET->setVisible(false); BOOKMARKS->setVisible(false); progress->setRange(0, BACKEND->numPages()); progress->setValue(0); progAct->setVisible(true); pageAct->setVisible(false); // PERFORMANCE NOTES: // Using Poppler to scale the image (adjust dpi value) helps a bit but you // take a larger CPU loading hit (and still quite a lot of pixelization) Using // Qt to scale the image (adjust page value) smooths out the image quite a bit // without a lot of performance loss (but cannot scale up without // pixelization) The best approach seams to be to increase the DPI a bit, but // match that with the same scaling on the page size (smoothing) QSize DPI(250, 250); // print-quality (some printers even go to 600 DPI nowdays) /*qDebug() << "Screen Resolutions:"; QList screens = QApplication::screens(); for(int i=0; iname() << screens[i]->logicalDotsPerInchX() << screens[i]->logicalDotsPerInchY(); }*/ int n = BACKEND->numPages() + 1; for (int i = 1; i < n; i++) { // qDebug() << " - Kickoff page load:" << i; if (BACKEND->loadMultiThread()) { QtConcurrent::run(BACKEND, &Renderer::renderPage, i, DPI, degrees); } else { BACKEND->renderPage(i, DPI, degrees); if (i % 50 == 0) { QCoreApplication::processEvents(); } } } // qDebug() << "Finish page loading kickoff"; } void MainUI::slotSetProgress(int finished) { progress->setValue(finished); } void MainUI::slotPageLoaded() { // loadingQueue.push_back(page); // int finished = loadingQueue.size(); // qDebug() << "Page Loaded:" << page << finished; // if (finished == BACKEND->numPages()) { progAct->setVisible(false); WIDGET->setVisible(true); BOOKMARKS->setVisible(true); ui->splitter->setSizes(QList() << 0 << this->width()); WIDGET->setCurrentPage(1); ui->actionStop_Presentation->setEnabled(false); ui->actionStart_Here->setEnabled(true); ui->actionStart_Begin->setEnabled(true); pageAct->setVisible(true); PROPDIALOG->setSize(pageSize); qDebug() << " - Document Setup: All pages loaded"; // QTimer::singleShot(10, WIDGET, // SLOT(updatePreview())); // start loading the file preview WIDGET->updatePreview(); } void MainUI::paintToPrinter(QPrinter *PRINTER) { if (BACKEND->hashSize() != BACKEND->numPages()) { return; } // qDebug() << "paintToPrinter"; int pages = BACKEND->numPages(); int firstpage = 0; int copies = PRINTER->copyCount(); bool collate = PRINTER->collateCopies(); bool reverse = (PRINTER->pageOrder() == QPrinter::LastPageFirst); // qDebug() << "PRINTER DPI:" << PRINTER->resolution() << // PRINTER->supportedResolutions(); if (PRINTER->resolution() < 300) { // Try to get 300 DPI resolution at least PRINTER->setResolution(300); qDebug() << "Trying to change print resolution to 300 minimum"; qDebug() << " -- Resolutions listed as supported:" << PRINTER->supportedResolutions(); } // bool duplex = (PRINTER->duplex()!=QPrinter::DuplexNone); // Determine the first page that needs to be printed, and the range if ((PRINTER->fromPage() != PRINTER->toPage() || PRINTER->fromPage() != 0) && PRINTER->printRange() == QPrinter::PageRange) { firstpage = PRINTER->fromPage() - 1; pages = PRINTER->toPage(); } qDebug() << "Start Printing PDF: Pages" << PRINTER->fromPage() << " to " << PRINTER->toPage() << " Copies:" << copies << " collate:" << collate << " Reverse Order:" << reverse; QList pageCount; // Assemble the page order/count based on printer settings for (int i = firstpage; i < pages; i++) { // Make sure even/odd pages are not selected as desired // Qt 5.7.1 does not seem to have even/odd page selections - 8/11/2017 pageCount << i; // add this page to the list // QT 5.9+ : Do not need to manually stack "copies". Already handled // internally for(int c=1; c tmp = pageCount; pageCount.clear(); for (int i = tmp.length() - 1; i >= 0; i--) { pageCount << tmp[i]; } // qDebug() << " - reversed:" << pageCount; } // QT 5.9+ : Do not need to manually stack "copies". Already handled // internally; /*if(collate && copies>0){ QList orig = pageCount; //original array of pages for(int c=1; cpageRect().width(), PRINTER->pageRect().height()); bool landscape = PRINTER->orientation() == QPrinter::Landscape; if (landscape) { sz = QSize(sz.height(), sz.width()); } // flip the size dimensions as needed // Now send out the pages in the right order/format QPainter painter(PRINTER); // Ensure all the antialiasing/smoothing options are turned on painter.setRenderHint(QPainter::Antialiasing); painter.setRenderHint(QPainter::TextAntialiasing); painter.setRenderHint(QPainter::SmoothPixmapTransform); QTransform transF; transF.rotate(90); // Show the progress bar progAct->setVisible(true); progress->setRange(0, pageCount.length() - 1); for (int i = 0; i < pageCount.length(); i++) { if (i != 0) { PRINTER->newPage(); } // qDebug() << "Printing Page:" << pageCount[i]; progress->setValue(i); QApplication::processEvents(); QImage img = BACKEND->imageHash(pageCount[i]) .scaled(sz, Qt::KeepAspectRatio, Qt::SmoothTransformation); // Now draw the image painter.drawImage(0, 0, img); // Also paint the annotations at their locations for (int k = 0; k < BACKEND->annotSize(i); k++) { Annotation *annot = BACKEND->annotList(i, k); if (annot->print()) { if (annot->getType() == 14) { painter.setPen(QPen(annot->getColor())); foreach (QVector pointList, annot->getInkList()) painter.drawLines(pointList); } else { painter.drawImage(annot->getLoc(), annot->renderImage()); } } } } progAct->setVisible(false); } void MainUI::OpenNewFile() { // Prompt for a file QString path = QFileDialog::getOpenFileName(this, tr("Open PDF"), lastdir, tr("PDF Documents (*.pdf)")); // Now Open it if (!path.isEmpty()) { loadFile(path); } } void MainUI::updateClock() { label_clock->setText( QDateTime::currentDateTime().toString("hh:mm:ss")); } void MainUI::updatePageNumber() { // qDebug() << "UpdatePageNumber"; QString text; if (presentationLabel == 0 || !presentationLabel->isVisible()) { text = tr("Page %1 of %2"); } else { text = "%1/%2"; } label_page->setText(text.arg(QString::number(WIDGET->currentPage()), QString::number(BACKEND->numPages()))); } /*void MainUI::setScroll(bool tog) { if(tog) { QApplication::setOverrideCursor(Qt::OpenHandCursor); }else{ QApplication::setOverrideCursor(Qt::IBeamCursor); } }*/ void MainUI::updateContextMenu() { contextMenu->clear(); contextMenu->addSection(QString(tr("Page %1 of %2")) .arg(QString::number(WIDGET->currentPage()), QString::number(BACKEND->numPages()))); contextMenu->addAction(ui->actionPrevious_Page); contextMenu->addAction(ui->actionNext_Page); contextMenu->addSeparator(); contextMenu->addAction(ui->actionFirst_Page); contextMenu->addAction(ui->actionLast_Page); contextMenu->addSeparator(); if (presentationLabel == 0 || !presentationLabel->isVisible()) { contextMenu->addAction(ui->actionStart_Begin); contextMenu->addAction(ui->actionStart_Here); } else { contextMenu->addAction(ui->actionStop_Presentation); } } void MainUI::keyPressEvent(QKeyEvent *event) { // See if this is one of the special hotkeys and act appropriately bool inPresentation = (presentationLabel != 0); switch (event->key()) { case Qt::Key_Escape: case Qt::Key_Backspace: { if (inPresentation) endPresentation(); } break; case Qt::Key_Right: case Qt::Key_Space: case Qt::Key_PageDown: { nextPage(); } break; case Qt::Key_Left: case Qt::Key_PageUp: { prevPage(); } break; case Qt::Key_Home: { firstPage(); } break; case Qt::Key_End: { lastPage(); } break; case Qt::Key_F11: { if (inPresentation) { endPresentation(); } else { startPresentationHere(); } } break; case Qt::Key_Up: { // Scroll the widget up } break; case Qt::Key_Down: { // Scroll the widget down /*qDebug() << "Send Wheel Event"; QWheelEvent wEvent( WIDGET->mapFromGlobal(QCursor::pos()), QCursor::pos(),QPoint(0,0), QPoint(0,30), 0, Qt::Vertical, Qt::LeftButton, Qt::NoModifier); QApplication::sendEvent(WIDGET, &wEvent);*/ } break; case Qt::Key_Enter: { /*if(ui->findGroup->hasFocus()) { find(ui->textEdit->text(), true); }*/ } break; default: { QMainWindow::keyPressEvent(event); } break; } return; } void MainUI::wheelEvent(QWheelEvent *event) { // Scroll the window according to the mouse wheel QMainWindow::wheelEvent(event); } void MainUI::find(QString text, bool forward) { if (!text.isEmpty()) { static bool previousMatchCase = matchCase; // qDebug() << "Finding Text"; // Detemine if it is the first time searching or a new search string bool newSearch = results.empty() || !(results[0]->text() == text); // Also search again if match case is turned on/off if (previousMatchCase != matchCase) { newSearch = true; previousMatchCase = matchCase; } // Clear results and highlights if the user gives a new search string if (newSearch) { // clear out the old results if (!results.empty()) { foreach (TextData *td, results) delete td; results.clear(); } WIDGET->updatePreview(); ui->resultsLabel->setText(""); // Get the new search results results = BACKEND->searchDocument(text, matchCase); // qDebug() << "Total Results: " << results.size(); currentHighlight = (forward) ? -1 : results.size(); } // qDebug() << "Jumping to next result"; if (!results.empty()) { // Jump to the location of the next or previous textbox and highlight if (forward) { currentHighlight++; if (currentHighlight >= results.size()) currentHighlight %= results.size(); } else { currentHighlight--; // Ensure currentHighlight will be between 0 and results.size() - 1 if (currentHighlight < 0) currentHighlight = results.size() - 1; } ui->resultsLabel->setText(QString::number(currentHighlight + 1) + " of " + QString::number(results.size()) + " results"); TextData *currentText = results[currentHighlight]; if (BACKEND->supportsExtraFeatures()) { WIDGET->highlightText(currentText); } else { ui->resultsLabel->setText("No results found"); } } } }