From kde-commits Thu Sep 14 05:46:30 2006 From: Stefan Kebekus Date: Thu, 14 Sep 2006 05:46:30 +0000 To: kde-commits Subject: branches/work/kviewshell-0.7/kviewshell Message-Id: <1158212790.964315.14791.nullmailer () svn ! kde ! org> X-MARC-Message: https://marc.info/?l=kde-commits&m=115821281928921 SVN commit 584141 by kebekus: fixes problems with links in DVI files M +10 -5 plugins/dvi/dviRenderer.cpp M +2 -2 plugins/pdf/pdfRenderer.cpp M +15 -0 shell/anchor.h M +11 -8 shell/dataModel.cpp M +26 -3 shell/dataModel.h M +3 -0 shell/documentWidget.cpp M +3 -0 shell/hyperlink.h M +2 -1 shell/kviewpart.cpp M +2 -0 shell/kvs_debug.h M +4 -0 shell/length.h M +11 -0 shell/pageNumber.h M +109 -14 shell/pageView.cpp M +0 -1 shell/pageView.h --- branches/work/kviewshell-0.7/kviewshell/plugins/dvi/dviRenderer.cpp #584140:584141 @@ -268,12 +268,13 @@ QRegExp itemExp("item\\.(.*)"); QRegExp citeExp("cite\\.(.*)"); - // And finally add anchors to the links + // And finally add anchors to the links, if the links are local for (i = page->hyperLinkList.begin(); i != page->hyperLinkList.end(); i++) { - Anchor anchor = findAnchor((*i).linkText); - (*i).anchor = anchor; - +#warning TODO: remove link if anchor cannot be found + if ((*i).linkText[0] == '#') // is local link? + (*i).anchor = findAnchor((*i).linkText.mid(1)); + // Also replace the targetnames created by the hyperref package, // with proper translatable names. QString temp = (*i).linkText; @@ -926,8 +927,12 @@ QMap::Iterator it = anchorList.find(locallink); if (it != anchorList.end()) return *it; - else + else { +#ifdef DEBUG_DVIRENDERER + kdDebug(kvs::dvi) << QString("dviRenderer::findAnchor(%1): no anchor found.").arg(locallink) << endl; +#endif return Anchor(); + } } #include "dviRenderer.moc" --- branches/work/kviewshell-0.7/kviewshell/plugins/pdf/pdfRenderer.cpp #584140:584141 @@ -53,6 +53,7 @@ #include "documentWidget.h" #include "documentInfoWidget_base.h" #include "hyperlink.h" +#include "kvs_debug.h" #include "textBox.h" #include "pagetransition.h" #include "pdfRenderer.h" @@ -182,9 +183,8 @@ Length y; y.setLength_in_pixel((int)destination.top(), res); Anchor anchor(destination.pageNumber(), y); - //kdDebug() << "Anchor: url = " << destination.toString() << " (page = " << destination.pageNumber() << ", y = " << destination.top() << ")" << endl; - //kdDebug() << "Hyperlink: (" << area.x() << ", " << area.y() << ", " << area.width() << ", " << area.height() << ")" << endl; Hyperlink hyperlink(area.bottom(), area, url, anchor); + // kdDebug(kvs::pdf) << "PdfRenderer::drawPage: hyperlink added " << hyperlink << endl; page->hyperLinkList.push_back(hyperlink); } else if (link->linkType() == Poppler::Link::Browse) --- branches/work/kviewshell-0.7/kviewshell/shell/anchor.h #584140:584141 @@ -11,6 +11,8 @@ #ifndef ANCHOR_H #define ANCHOR_H +#include + #include "length.h" #include "pageNumber.h" @@ -32,6 +34,16 @@ /** \brief Constructs an anchor that points to an invalid page */ Anchor() {page = 0;} + /** \brief Constructs an snchor that points to the top of a given + page + + The class contains no code to make sure in any way that the page + number pg exists + + @param pg number of the page + */ + Anchor(const PageNumber& pg): page(pg), distance_from_top() {} + /** \brief Constructs an snchor that points to a given position on a given page @@ -55,6 +67,9 @@ /** \brief Distance from the top of the page in inch */ Length distance_from_top; + + /** \brief This method implements typecasts to QString */ + operator QString() const { return QString("(page=%1, %2 from top)").arg(page.toQString()).arg(distance_from_top); } }; --- branches/work/kviewshell-0.7/kviewshell/shell/dataModel.cpp #584140:584141 @@ -56,15 +56,18 @@ void DataModel::setCurrentPageNumber(const PageNumber& pageNumber, bool weak) { - if (pageNumber != _currentPageNumber) - { - _currentPageNumber = pageNumber; - emit currentPageNumberChanged(); - if (!weak) - { + if (pageNumber > numberOfPages()) { + kdError(kvs::shell) << "DataModel::setCurrentPageNumber called with pageNumber higher than the number of pages in the document" << endl; + return; + } + + if (pageNumber == _currentPageNumber) + return; + + _currentPageNumber = pageNumber; + emit currentPageNumberChanged(); + if (!weak) emit gotoCurrentPage(); - } - } } --- branches/work/kviewshell-0.7/kviewshell/shell/dataModel.h #584140:584141 @@ -49,14 +49,32 @@ DataModel(QObject* parent = 0); virtual ~DataModel(); + + /** @brief get the current page number + */ PageNumber currentPageNumber(); + + /** @brief sets the current page number + + This method sets the current page number. The signal + currentPageNumberChanged() will be emitted. The signal + gotoCurrentPage() might be emitted. + + @param PageNumber The new page number; this number must not be + greater than numberOfPages(). If this number equals the + currentPageNumber(), this method exits immediately and nothing + happens. + + @param weak This parameter decides if the signal + gotoCurrentPage() is emitted. + */ void setCurrentPageNumber(const PageNumber&, bool weak = false); unsigned int numberOfPages(); void setNumberOfPages(unsigned int); - + /** @brief get the resolution currently used for drawing. - + @returns the resolution of the display device. In principle. In fact, kviewshell implements zooming by calling the setResolution()-method with values that are not exactly the @@ -182,11 +200,16 @@ signals: void currentPageNumberChanged(); + + /** This signal might emitted when the method setCurrentPageNumber() + is called. It indicates that the current page number has changed + and that the display should be updated accordingly. + */ void gotoCurrentPage(); void numberOfPagesChanged(); void layoutChanged(); - /** This signal es emitted whenever the selected text changes. + /** This signal is emitted whenever the selected text changes. The argument is false if no text is selected, true otherwise. @ref deselectText --- branches/work/kviewshell-0.7/kviewshell/shell/documentWidget.cpp #584140:584141 @@ -545,6 +545,9 @@ { if (pageData->hyperLinkList[i].box.contains(inverseMap(e->pos()))) { +#ifdef DEBUG_DOCUMENTWIDGET + kdDebug(kvs::shell) << "DocumentWidget::mousePressEvent(): mouse pressed on hyperlink " << pageData->hyperLinkList[i].linkText << endl; +#endif emit localLink(pageData->hyperLinkList[i]); return; } --- branches/work/kviewshell-0.7/kviewshell/shell/hyperlink.h #584140:584141 @@ -88,6 +88,9 @@ should be set to invalid. */ Anchor anchor; + + /** \brief This method implements typecasts to QString */ + operator QString() const { return QString("(name=%1, anchor=%2)").arg(linkText).arg(anchor); } }; --- branches/work/kviewshell-0.7/kviewshell/shell/kviewpart.cpp #584140:584141 @@ -1874,7 +1874,8 @@ args << "openURL"; args << Link_Url.toString(); kapp->kdeinitExec("kfmclient", args); - } + } else + kdError(kvs::shell) << "KMultiPage::handleLocalLink( ... ) with link to " << link << endl; } } --- branches/work/kviewshell-0.7/kviewshell/shell/kvs_debug.h #584140:584141 @@ -23,6 +23,8 @@ djvu = 1223, dvi = 4300, fax = 1223, + pdf = 1223, + ps = 1223, shell = 1223 }; --- branches/work/kviewshell-0.7/kviewshell/shell/length.h #584140:584141 @@ -13,6 +13,7 @@ #define _length_h_ #include +#include class QString; @@ -181,6 +182,9 @@ It is fine to set ok to 0. */ static float convertToMM(const QString &distance, bool *ok=0); + /** \brief This simple method implements typecasts to QString */ + operator QString() const { return QString::number(length_in_mm, 'f', 2)+"mm"; } + private: /** Length in millimeters */ double length_in_mm; --- branches/work/kviewshell-0.7/kviewshell/shell/pageNumber.h #584140:584141 @@ -11,6 +11,7 @@ #define PAGENUMBER_H #include +#include /** \brief Class to represent a page number @@ -55,6 +56,16 @@ */ bool isValid() const {return (pgNum != invalidPage);} + /** \brief This simple method represents the page number as a string + + We do not implement a typecast here, because otherwise there would + be too many ambiguous typecasts that one would have to sort out + manually. + + @returns the page number as a string or 'invalid' + */ + QString toQString() const { return isValid() ? QString::number(pgNum) : "invalid"; }; + private: /** \brief Single number that represents the page number */ Q_UINT16 pgNum; --- branches/work/kviewshell-0.7/kviewshell/shell/pageView.cpp #584140:584141 @@ -970,16 +970,10 @@ // If the number of widgets has changed, or the viewmode has been changed the widget // that displays the current page may not be visible anymore. Bring it back into focus. if (isWidgetListResized || !reload) - gotoPage(startPage); + gotoAnchor(startPage); } -bool PageView::gotoPage(const PageNumber& page) -{ - return gotoPage(page, 0, true); -} - - bool PageView::gotoPage(const PageNumber& page, int y, bool isLink) { kdDebug(kvs::shell) << "PageView::gotoPage()" << endl; @@ -1140,10 +1134,111 @@ void PageView::gotoAnchor(const Anchor& a) { - if (!a.page.isValid()) + kdDebug(kvs::shell) << "PageView::gotoAnchor()" << endl; + + // gotoPage(a.page, (int)(a.distance_from_top.getLength_in_inch() * dataModel->resolution() + 0.5), true); + + if (!a.page.isValid()) { + kdError(kvs::shell) << "PageView::gotoAnchor() call when anchor had invalid pageNumber." << endl; return; + } + if (dataModel->numberOfPages() == 0) { + kdError(kvs::shell) << "PageView::gotoAnchor() called with numberOfPages == 0" << endl; + return; + } + if (numberOfWidgets() == 0) { + kdError(kvs::shell) << "PageView::gotoAnchor() called, but widgetList is empty" << endl; + return; + } - gotoPage(a.page, (int)(a.distance_from_top.getLength_in_inch() * dataModel->resolution() + 0.5), true); + PageNumber page = a.page; + int y = (int)(a.distance_from_top.getLength_in_inch() * dataModel->resolution() + 0.5); +#warning FIX THIS + bool isLink = true; + + if (isLink) + dataModel->history()->add(page, y); + + DocumentWidget* _pageWidget; + + // If we are in overview viewmode + if (dataModel->preferences()->viewMode() == KVSPrefs::EnumViewMode::Overview) { + unsigned int visiblePages = dataModel->preferences()->overviewModeColumns() * dataModel->preferences()->overviewModeRows(); + // Pagenumber of the first visibile Page in the current tableau + unsigned int firstPage = pageWidget(0)->getPageNumber(); + // Pagenumber of the first page in the new tableau. + unsigned int tableauStartPage = page + 1 - (page % visiblePages); + // If these numbers arn't equal "page" is not in the current tableu. + bool newTableu = false; + if (firstPage != tableauStartPage) { // widgets need to be updated + newTableu = true; + if ((dataModel->numberOfPages() - tableauStartPage + 1 < visiblePages) || (numberOfWidgets() < visiblePages)) { + // resize widgetList + // the pages are also set correctly by "generateDocumentWidgets" + generateDocumentWidgets(tableauStartPage); + } else { + // "page" is not shown in the scrollview, so we have to switch widgets. + // Here we don't need to resize the widgetList. + for (unsigned int i = 0; i < numberOfWidgets(); i++) { + _pageWidget = pageWidget(i); + if (_pageWidget != 0) + _pageWidget->setPageNumber(tableauStartPage + i); + } + layoutPages(); + } + } + // move scrollview to "page". + // Make the widget pageWidget visible in the scrollview. Somehow this + // doesn't seem to trigger the signal contentsMoved in the + // QScrollview, so that we better call setCurrentPage() ourselves. + _pageWidget = pageWidget(page % visiblePages); + + if (newTableu) { + // If we have switched to a new tableu, we don't want smooth scrolling + moveViewportToWidget(_pageWidget, y, false); + } else + moveViewportToWidget(_pageWidget, y); + return; + } else if (numberOfWidgets() == 1) { + // If the widget list contains only a single element, then either + // the document contains only one page, or we are in "single page" + // view mode. In either case, we set the page number of the single + // widget to 'page' + _pageWidget = pageWidget(0); + + // Paranoia security check + if (_pageWidget == 0) { + kdError(kvs::shell) << "PageView::gotoAnchor() called with widgetList.size() == 1, but widgetList[0] == 0" << endl; + return; + } + + _pageWidget->setPageNumber(page); + layoutPages(); + moveViewportToWidget(_pageWidget, y, false); + } else { + // There are multiple widgets, then we are either in the + // "Continuous" or in the "Continouous-Facing" view mode. In that + // case, we find the widget which is supposed to display page + // 'page' and move the scrollview to make it visible + + // Paranoia security checks + if (numberOfWidgets() < page) { + kdError(kvs::shell) << "PageView::gotoAnchor() called with widgetList.size()=" << numberOfWidgets() << ", and page=" << page << endl; + return; + } + _pageWidget = pageWidget(page-1); + if (_pageWidget == 0) { + kdError(kvs::shell) << "PageView::gotoAnchor() called with widgetList.size() > 1, but widgetList[page] == 0" << endl; + return; + } + + moveViewportToWidget(_pageWidget, y); + } + + if (isLink && y != 0) + _pageWidget->flash(y); + + return; } @@ -1155,7 +1250,7 @@ np = dataModel->currentPageNumber() - nrCols*nrRows; } - gotoPage(np); + gotoAnchor(np); } @@ -1163,19 +1258,19 @@ { PageNumber np = QMIN(dataModel->currentPageNumber() + nrCols*nrRows, dataModel->numberOfPages()); - gotoPage(np); + gotoAnchor(np); } void PageView::firstPage() { - gotoPage(1); + gotoAnchor(Anchor(1)); } void PageView::lastPage() { - gotoPage(dataModel->numberOfPages()); + gotoAnchor(Anchor(dataModel->numberOfPages())); } @@ -1431,7 +1526,7 @@ void PageView::gotoCurrentPage() { - gotoPage(dataModel->currentPageNumber()); + gotoAnchor(Anchor(dataModel->currentPageNumber())); } #include "pageView.moc" --- branches/work/kviewshell-0.7/kviewshell/shell/pageView.h #584140:584141 @@ -53,7 +53,6 @@ // These two will probably end up private bool gotoPage(const PageNumber& page, int y, bool isLink = true); - bool gotoPage(const PageNumber& page); /** Make the selection visible */ void gotoSelection(const TextSelection&);