📄 pdfwidget.cpp
字号:
} else if ((int)e->type() == PagePreview) { pagePreview(e->data()); } else { QScrollView::customEvent(e); }}void PDFWidget::pageReady(void* args){ QImage *image = (QImage*)args; delete pixmap; pixmap = new QPixmap(); pixmap->convertFromImage(*image, Qt::AutoColor); delete image; running = false; resizeContents(pixmap->width() <= viewport()->width() ? viewport()->width() : pixmap->width() + borderWidth * 2, (pixmap->height() <= viewport()->height()) ? viewport()->height() : pixmap->height() + borderWidth * 2); updateContents(0, 0, contentsWidth(), contentsHeight()); setContentsPos(scheduledContentsPosX, scheduledContentsPosY); updateViewRect(); selectedLink = selectLink(); qWarning("selectedLink = %i", selectedLink); drawLinks(pixmap, selectedLink); emit rendererRunning(false);}void PDFWidget::invalidatePixmap(void){ delete pixmap; pixmap = 0;}int PDFWidget::selectLink(){ Poppler::Links links = page->getLinks(); int linkCnt = links.getNumLinks(); if (linkCnt < 1 || !pixmap) { //qWarning("no pixmap or no link on this page"); return -1; } // is the currently selected link still visible? if (selectedLink != -1 && selectedLink < linkCnt) { Poppler::Link l = links.getLink(selectedLink); if (viewRect.contains(l.getScreenCoords().center(), true)) { //qWarning("old link %i si still visible", selectedLink); return l.getId(); } } Poppler::Link selected(9999, 9999, 9999, 9999, -1); // invalid for (int i = 0; i < linkCnt; i++) { Poppler::Link l = links.getLink(i); if (viewRect.contains(l.getScreenCoords().center(), true)) { QPoint lcoord = l.getScreenCoords().center(); // select the link nearest to the top/left if (direction == Forward) { if (lcoord.y() < selected.getScreenCoords().center().y() && lcoord.x() < selected.getScreenCoords().center().x()) { selected = l; } } // select the link nearest to the bottom right else if (direction == Back) { if (abs(lcoord.y() - pixmap->width()) < abs(selected.getScreenCoords().center().y() - pixmap->width())) { selected = l; } } } } return selected.getId();}int PDFWidget::selectNextLink(int direction, int currentLink){ Poppler::Links links = page->getLinks(); int linkCnt = links.getNumLinks(); if (linkCnt <= 0 || !pixmap) { //qWarning("no links on this page"); return -1; } if (currentLink == -1 || currentLink >= linkCnt) { //qWarning("no valid link. trying to select a new one"); return selectLink(); } if (currentLink == -1) { //qWarning("still no valid link..."); return -1; } //qWarning("ok the selected link is %i", currentLink); Poppler::Link selected = links.getLink(currentLink); Poppler::Link tmp; Poppler::Link tmpSameRow; int selected_y = selected.getScreenCoords().center().y(); int selected_x = selected.getScreenCoords().center().x(); for (int i = 0; i < linkCnt; i++) { Poppler::Link l = links.getLink(i); // inside the visible screen? if (viewRect.contains(l.getScreenCoords().center(), true)) { QPoint lcoord = l.getScreenCoords().center(); if (direction == Up) { // handle links in the same row further left if (selected.getId() != l.getId() && lcoord.y() == selected_y && lcoord.x() < selected_x) { if (tmpSameRow.getId() == -1) { tmpSameRow = l; } else if (abs(lcoord.x() - selected_x) < abs(tmpSameRow.getScreenCoords().center().x() - selected_x)) { tmpSameRow = l; } } // handle links further up else if (lcoord.y() < selected_y) { if (tmp.getId() != -1) { if (abs(selected_y - lcoord.y()) <= abs(selected_y - tmp.getScreenCoords().center().y())) { // if there are several links further up on the same row take the one most rigth if (lcoord.y() == tmp.getScreenCoords().center().y()) { if (lcoord.x() > tmp.getScreenCoords().center().x()) { tmp = l; } } else { tmp = l; } } } else { tmp = l; } } } else if (direction == Down) { // handle links in the same row further right if (selected.getId() != l.getId() && lcoord.y() == selected_y && lcoord.x() > selected_x) { if (tmpSameRow.getId() == -1) { tmpSameRow = l; } else if (abs(lcoord.x() - selected_x) < abs(tmpSameRow.getScreenCoords().center().x() - selected_x)) { tmpSameRow = l; } } // handle links further down else if (lcoord.y() > selected_y) { if (tmp.getId() != -1) { if (abs(selected_y - lcoord.y()) <= abs(selected_y - tmp.getScreenCoords().center().y())) { // if there are several links further down on the same row take the one most left if (lcoord.y() == tmp.getScreenCoords().center().y()) { if (lcoord.x() < tmp.getScreenCoords().center().x()) { tmp = l; } } else { tmp = l; } } } else { tmp = l; } } } else if (direction == Left) { if (selected.getId() != l.getId() && lcoord.x() < selected_x) { if (tmp.getId() == -1) { tmp = l; } else if (abs(lcoord.x() - selected_x) < abs(tmp.getScreenCoords().center().x() - selected_x)) { tmp = l; } } } else if (direction == Right) { if (selected.getId() != l.getId() && lcoord.x() > selected_x) { if (tmp.getId() == -1) { tmp = l; } else if (abs(lcoord.x() - selected_x) < abs(tmp.getScreenCoords().center().x() - selected_x)) { tmp = l; } } } } } // links on the same row have precedence if (tmpSameRow.getId() != -1) { selected = tmpSameRow; //qWarning("next selected link (sameRow): %i", selected.getId()); } else if (tmp.getId() != -1) { selected = tmp; //qWarning("next selected link: %i", selected.getId()); } else { if (!viewRect.contains(selected.getScreenCoords().center(), true)) { //qWarning("no new selected link"); return -1; } } //qWarning("the returned selectedLink is %i", selected.getId()); return selected.getId();}void PDFWidget::drawLinks(QPixmap *pixmap, int selectedLink){ if (!pixmap || running) return; Poppler::Links links = page->getLinks(); int linkCnt = links.getNumLinks(); QPainter p(pixmap); QPen red(QColor(255, 0, 0), 1); QPen blue(QColor(152, 204, 255), 1); p.setPen(blue); for (int i = 0; i < linkCnt; i++) { if (i != selectedLink) { p.drawRect(links.getLink(i).getScreenCoords()); } } if (selectedLink != -1) { //qWarning("drawLink selected %i", selectedLink); p.setPen(red); p.drawRect(links.getLink(selectedLink).getScreenCoords()); }}void PDFWidget::followLink(){ //qWarning("follow link"); if (selectedLink == -1) { return; } Poppler::Links links = page->getLinks(); Poppler::Link link = links.getLink(selectedLink); QPoint center = link.getLinkCenterScreenCoord(); //qWarning("x = %i, y = %i", center.x(), center.y()); int nxt = page->linkDest((double)center.x(), (double)center.y()); //qWarning("nxt = %i", nxt); if (nxt != -1 && nxt > 0 && nxt < doc->getNumPages()) { navStack.append(PageNum(currentPage)); //qWarning("put %i on the navStack", currentPage); emit pagesInHistory(true); jumpToPage(nxt); }}bool PDFWidget::rendererRunning(void){ return running;}// private slotvoid PDFWidget::pagePreview(void* arg) { QImage *image = (QImage*)arg; delete pixmap; pixmap = new QPixmap(); pixmap->convertFromImage(*image, Qt::AutoColor); delete image; resizeContents(pixmap->width() <= viewport()->width() ? viewport()->width() : pixmap->width() + borderWidth * 2, (pixmap->height() <= viewport()->height()) ? viewport()->height() : pixmap->height() + borderWidth * 2); updateContents(0, 0, contentsWidth(), contentsHeight()); if (firstPreview) { firstPreview = false; setContentsPos(scheduledContentsPosX, scheduledContentsPosY); }}void PDFWidget::emitNavSignals() { if (currentPage == 0) emit isFirstPage(true); else emit isFirstPage(false); //qWarning("cp: %i, mp: %i", currentPage, doc->getNumPages()); if (currentPage == doc->getNumPages() - 1) emit isLastPage(true); else emit isLastPage(false);}// this method is necessary to display documents correctly in "fit to width"// and "fit to page" mode if the pages of the documents have different dimensions.void PDFWidget::recalcZoomAndDisplay(){ if (zoomLevel == FIT_TO_PAGE || zoomLevel == FIT_TO_WIDTH) { setZoom(zoomLevel); } else { display(); }}// public slotvoid PDFWidget::nextPage(){ if (currentPage + 1 < doc->getNumPages()) { selectedLink = -1; direction = Forward; currentPage++; delete page; page = doc->getPage(currentPage); emitNavSignals(); recalcZoomAndDisplay(); scheduleContentsPosUpdate(contentsX(), 0); }}// public slotvoid PDFWidget::prevPage(){ if (currentPage > 0) { selectedLink = -1; direction = Back; currentPage--; delete page; page = doc->getPage(currentPage); emitNavSignals(); recalcZoomAndDisplay(); scheduleContentsPosUpdate(contentsX(), contentsHeight() - visibleHeight()); }}// public slotvoid PDFWidget::lastPage() { if (currentPage != doc->getNumPages() - 1) { selectedLink = -1; direction = Forward; currentPage = doc->getNumPages() - 1; delete page; page = doc->getPage(currentPage); emitNavSignals(); recalcZoomAndDisplay(); scheduleContentsPosUpdate(contentsX(), 0); }}// public slotvoid PDFWidget::firstPage() { if (currentPage != 0) { selectedLink = -1; direction = Back; currentPage = 0; delete page; page = doc->getPage(currentPage); emitNavSignals(); recalcZoomAndDisplay(); scheduleContentsPosUpdate(contentsX(), 0); }}// public slotvoid PDFWidget::jumpToPage(int pageX){ if ((pageX <= doc->getNumPages() - 1) && (pageX != currentPage)) { selectedLink = -1; direction = Forward; currentPage = pageX; delete page; page = doc->getPage(currentPage); recalcZoomAndDisplay(); scheduleContentsPosUpdate(contentsX(), 0); emitNavSignals(); }}void PDFWidget::setHotspot(QSize s){ m_hotspot = s;}void PDFWidget::viewportMousePressEvent(QMouseEvent *e){ if ( !doc ) { return; } int x = e->pos().x(), y = e->pos().y(); if ( (x > width() - m_hotspot.width()) && (y > height() - m_hotspot.height()) ) { emit hotspot(); } else if (e->button() == QMouseEvent::LeftButton) { m_panning = true; m_panningPos = new QPoint(x, y); // did the user touch a link? viewportToContents(x, y, x, y); x -= x_origin; y -= y_origin; m_linkSelected = page->isLink(x, y); if (m_linkSelected) { m_LinkPos = new QPoint(e->pos().x(), e->pos().y()); int tmpLink = page->linkId(x, y); if (tmpLink != -1) { selectedLink = tmpLink; //qWarning("clickedLink = %i", selectedLink); drawLinks(pixmap, selectedLink); updateContents(0, 0, contentsWidth(), contentsHeight()); } } }}void PDFWidget::viewportMouseReleaseEvent(QMouseEvent * e){ if ( !doc ) { return; } if (e->button() == QMouseEvent::LeftButton) { m_panning = false; delete m_panningPos; m_panningPos = 0; if (m_linkSelected) { int x, y; viewportToContents(e->pos().x(), e->pos().y(), x, y); int nxt = page->linkDest(x - x_origin, y - y_origin); if (nxt != -1 && nxt > 0 && nxt < doc->getNumPages()) { navStack.append(PageNum(currentPage)); //qWarning("put %i on the navStack", currentPage); emit pagesInHistory(true); jumpToPage(nxt); } m_linkSelected = false; delete m_LinkPos; } else { direction = Forward; selectedLink = selectLink(); //qWarning("selectedLink = %i", selectedLink); drawLinks(pixmap, selectedLink); updateContents(0, 0, contentsWidth(), contentsHeight()); } }}void PDFWidget::moveBack(){ if (navStack.fromLast() != navStack.end()) { int pageNum = navStack.last().getPageNum(); navStack.remove(navStack.fromLast()); //qWarning("took %i from the navStack", pageNum); emit pagesInHistory(navStack.count()); jumpToPage(pageNum); }}bool PDFWidget::arePagesInHistory(void){ return navStack.count() > 0;}void PDFWidget::viewportMouseMoveEvent(QMouseEvent * e){ if ( !doc ) { return; } if (e->state() & QMouseEvent::LeftButton && m_panning == true) { updateViewRect(); scrollBy(m_panningPos->x() - e->x(), m_panningPos->y() - e->y()); m_panningPos->setX(e->x()); m_panningPos->setY(e->y()); // to much moving around, probably clicking the link wasn't the // users intention int x, y; viewportToContents(e->pos().x(), e->pos().y(), x, y); if (m_linkSelected) { if ((abs(m_LinkPos->x() - (x - x_origin) ) > 3) || abs(m_LinkPos->y() - (y - y_origin) > 3)) { m_linkSelected = false; } } // lets see if we're above a link int tmpLink = page->linkId(x - x_origin, y - y_origin); if (tmpLink != -1) { selectedLink = tmpLink; //qWarning("movedToLink = %i", selectedLink); drawLinks(pixmap, selectedLink); updateContents(0, 0, contentsWidth(), contentsHeight()); } }}void PDFWidget::scheduleContentsPosUpdate( int x, int y ) { scheduledContentsPosX = x; scheduledContentsPosY = y;}int PDFWidget::getPageWidth() const{ Poppler::Page::Orientation orientation = page->orientation(); if (orientation == Poppler::Page::Landscape || orientation == Poppler::Page::Seascape) { return page->pageSize().height(); } else { return page->pageSize().width(); }}int PDFWidget::getPageHeight() const{ Poppler::Page::Orientation orientation = page->orientation(); if (orientation == Poppler::Page::Landscape || orientation == Poppler::Page::Seascape) { return page->pageSize().width(); } else { return page->pageSize().height(); }}void PDFWidget::redisplay(){ if (doc) { recalcZoomAndDisplay(); } else { qWarning("No document set (%s:%i)", __FILE__, __LINE__); }}void PDFWidget::resizeEvent(QResizeEvent *){ //qWarning("PDFWidget::resizeEvent(QResizeEvent *)"); invalidatePixmap(); resizeContents(viewport()->width(), viewport()->height()); //qWarning("viewport()->width() = %i, viewport()->height() = %i", viewport()->width(), viewport()->height()); setContentsPos(0, 0); updateContents(0, 0, contentsWidth(), contentsHeight()); redisplay();}int PDFWidget::getPageNumber(){ return currentPage + 1;}int PDFWidget::getNumPages(){ int ret = 0; if (doc) ret = doc->getNumPages(); return ret;}int PDFWidget::maxZoomLevel = 8;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -