Commit fb57611f authored by Philipp Erhardt's avatar Philipp Erhardt
Browse files

Improve clickable link handling; URL support

parent 314997da
......@@ -13,9 +13,8 @@ KPage::KPage() :
KPage::~KPage() {
if (links != NULL) {
for (list<Poppler::LinkGoto *>::iterator it = links->begin();
it != links->end(); ++it) {
delete *it;
Q_FOREACH(Poppler::Link *l, *links) {
delete l;
}
}
delete links;
......
......@@ -23,7 +23,7 @@ private:
QImage img[3];
QImage thumbnail;
// QString label;
std::list<Poppler::LinkGoto *> *links;
QList<Poppler::Link *> *links;
QMutex mutex;
int status[3];
char rotation[3];
......
......@@ -486,7 +486,7 @@ QPoint GridLayout::get_target_page_distance(int target_page) const {
int page_height = ROUND(res->get_page_height(target_page) * size);
int center_x = (grid->get_width(target_page_offset % grid->get_column_count()) * size - page_width) / 2;
int center_y = (grid->get_height(target_page_offset / grid->get_column_count()) * size - page_height) / 2;
int center_y = (ROUND(grid->get_height(target_page_offset / grid->get_column_count()) * size) - page_height) / 2;
int wpos = off_x;
if (target_page_offset % grid->get_column_count() > horizontal_page) {
......@@ -502,12 +502,12 @@ QPoint GridLayout::get_target_page_distance(int target_page) const {
if (target_page_offset > page) {
for (int i = (page + grid->get_offset()) / grid->get_column_count();
i < target_page_offset / grid->get_column_count(); i++) {
hpos += grid->get_height(i) * size + useless_gap;
hpos += ROUND(grid->get_height(i) * size) + useless_gap;
}
} else {
for (int i = (page + grid->get_offset()) / grid->get_column_count();
i > target_page_offset / grid->get_column_count(); i--) {
hpos -= grid->get_height(i) * size + useless_gap;
hpos -= ROUND(grid->get_height(i) * size) + useless_gap;
}
}
return QPoint(wpos + center_x, hpos + center_y);
......@@ -573,40 +573,22 @@ pair<int,QPointF> GridLayout::get_page_at(int mx, int my) {
bool GridLayout::click_mouse(int mx, int my) {
pair<int,QPointF> page = get_page_at(mx, my);
// find matching box
const list<Poppler::LinkGoto *> *l = res->get_links(page.first);
if (l == NULL) {
return false;
}
for (list<Poppler::LinkGoto *>::const_iterator it = l->begin();
it != l->end(); ++it) {
QRectF r = (*it)->linkArea();
if (page.second.x() >= r.left() && page.second.x() < r.right()) {
if (page.second.y() < r.top() && page.second.y() >= r.bottom()) {
int new_page = (*it)->destination().pageNumber();
// TODO scroll_smooth() to the link position
scroll_page(new_page - 1, false);
return true;
}
}
}
return false;
return activate_link(page.first, page.second.x(), page.second.y());
}
bool GridLayout::goto_link_destination(Poppler::LinkDestination *link) {
bool GridLayout::goto_link_destination(const Poppler::LinkDestination &link) {
// TODO variable margin?
// TODO use this interface for clicked links
int link_page = link->pageNumber() - 1;
int link_page = link.pageNumber() - 1;
float w = res->get_page_width(link_page);
float h = res->get_page_height(link_page);
const QPointF link_point = rotate_point(QPointF(link->left(), link->top()) * h, w, h, res->get_rotation());
const QPointF link_point = rotate_point(QPointF(link.left(), link.top()) * h, w, h, res->get_rotation());
QPoint p = get_target_page_distance(link_page);
if (link->isChangeLeft()) {
if (link.isChangeLeft()) {
p.rx() += link_point.x() * size;
}
if (link->isChangeTop()) {
if (link.isChangeTop()) {
p.ry() += link_point.y() * size;
}
return view_point(p);
......
......@@ -30,7 +30,7 @@ public:
bool advance_invisible_hit(bool forward = true);
bool click_mouse(int mx, int my);
bool goto_link_destination(Poppler::LinkDestination *link);
bool goto_link_destination(const Poppler::LinkDestination &link);
bool goto_page_at(int mx, int my);
bool page_visible(int p) const;
......
#include <iostream>
#include <QImage>
#include <QDesktopServices>
#include <QUrl>
#include "layout.h"
#include "../viewer.h"
#include "../resourcemanager.h"
......@@ -186,8 +188,8 @@ bool Layout::click_mouse(int /*mx*/, int /*my*/) {
return false;
}
bool Layout::goto_link_destination(Poppler::LinkDestination *link) {
return scroll_page(link->pageNumber() - 1, false);
bool Layout::goto_link_destination(const Poppler::LinkDestination &link) {
return scroll_page(link.pageNumber() - 1, false);
}
bool Layout::goto_page_at(int /*mx*/, int /*my*/) {
......@@ -197,3 +199,40 @@ bool Layout::goto_page_at(int /*mx*/, int /*my*/) {
bool Layout::get_search_visible() const {
return search_visible;
}
bool Layout::activate_link(int page, float x, float y) {
// find matching box
const QList<Poppler::Link *> *links = res->get_links(page);
if (links == NULL) {
return false;
}
Q_FOREACH(Poppler::Link *l, *links) {
QRectF r = l->linkArea();
if (x >= r.left() && x < r.right()) {
if (y < r.top() && y >= r.bottom()) {
switch (l->linkType()) {
case Poppler::Link::Goto: {
Poppler::LinkGoto *link = static_cast<Poppler::LinkGoto *>(l);
// TODO support links to other files
return goto_link_destination(link->destination());
}
case Poppler::Link::Browse: {
Poppler::LinkBrowse *link = static_cast<Poppler::LinkBrowse *>(l);
QDesktopServices::openUrl(QUrl(link->url()));
break;
}
case Poppler::Link::Execute:
case Poppler::Link::Action:
case Poppler::Link::Sound:
case Poppler::Link::Movie:
case Poppler::Link::Rendition:
case Poppler::Link::JavaScript:
case Poppler::Link::None:
cerr << "link type not implemented (yet?)" << endl;
}
}
}
}
return false;
}
......@@ -3,6 +3,7 @@
#include <QPainter>
#include <QList>
#include <poppler/qt4/poppler-qt4.h>
#include <map>
......@@ -38,7 +39,7 @@ public:
virtual bool advance_invisible_hit(bool forward = true) = 0;
virtual bool click_mouse(int mx, int my);
virtual bool goto_link_destination(Poppler::LinkDestination *link);
virtual bool goto_link_destination(const Poppler::LinkDestination &link);
virtual bool goto_page_at(int mx, int my);
virtual bool get_search_visible() const;
......@@ -46,6 +47,7 @@ public:
protected:
virtual bool view_hit() = 0;
virtual bool activate_link(int page, float x, float y);
Viewer *viewer;
ResourceManager *res;
......
......@@ -186,23 +186,7 @@ bool PresentationLayout::click_mouse(int mx, int my) {
x = 1 - tmp;
}
// find matching box
const list<Poppler::LinkGoto *> *l = res->get_links(page);
if (l == NULL) {
return false;
}
for (list<Poppler::LinkGoto *>::const_iterator it = l->begin();
it != l->end(); ++it) {
QRectF r = (*it)->linkArea();
if (x >= r.left() && x < r.right()) {
if (y < r.top() && y >= r.bottom()) {
int new_page = (*it)->destination().pageNumber();
scroll_page(new_page - 1, false);
return true;
}
}
}
return false;
return activate_link(page, x, y);
}
bool PresentationLayout::page_visible(int p) const {
......
......@@ -298,21 +298,13 @@ bool PresenterLayout::click_mouse(int mx, int my) {
x = 1 - tmp;
}
// find matching box
const list<Poppler::LinkGoto *> *l = res->get_links(page + i);
if (l == NULL) {
return false;
// check bounds
if (x < 0.0f || x > 1.0f || y < 0.0f || y > 1.0f) {
continue;
}
for (list<Poppler::LinkGoto *>::const_iterator it = l->begin();
it != l->end(); ++it) {
QRectF r = (*it)->linkArea();
if (x >= r.left() && x < r.right()) {
if (y < r.top() && y >= r.bottom()) {
int new_page = (*it)->destination().pageNumber();
scroll_page(new_page - 1, false);
return true;
}
}
if (activate_link(page + i, x, y)) {
return true;
}
}
return false;
......
......@@ -440,12 +440,12 @@ int ResourceManager::get_page_count() const {
return page_count;
}
const list<Poppler::LinkGoto *> *ResourceManager::get_links(int page) {
const QList<Poppler::Link *> *ResourceManager::get_links(int page) {
if (page < 0 || page >= get_page_count()) {
return NULL;
}
link_mutex.lock();
list<Poppler::LinkGoto *> *l = k_page[page].links;
QList<Poppler::Link *> *l = k_page[page].links;
link_mutex.unlock();
return l;
}
......
......@@ -45,7 +45,7 @@ public:
float get_min_aspect() const;
float get_max_aspect() const;
int get_page_count() const;
const std::list<Poppler::LinkGoto *> *get_links(int page);
const QList<Poppler::Link *> *get_links(int page);
QDomDocument *get_toc() const;
int get_rotation() const;
......
......@@ -47,7 +47,7 @@ void Toc::goto_link(QTreeWidgetItem *item, int column) {
}
int old_page = viewer->get_canvas()->get_layout()->get_page();
Poppler::LinkDestination *link = item->data(0, Qt::UserRole).value<Poppler::LinkDestination *>();
if (viewer->get_canvas()->get_layout()->goto_link_destination(link)) {
if (viewer->get_canvas()->get_layout()->goto_link_destination(*link)) {
viewer->get_canvas()->update();
}
viewer->get_res()->store_jump(old_page);
......
......@@ -120,17 +120,12 @@ void Worker::run() {
if (res->k_page[page].links == NULL) {
res->link_mutex.unlock();
list<Poppler::LinkGoto *> *lg = new list<Poppler::LinkGoto *>;
Q_FOREACH(Poppler::Link *l, p->links()) {
if (l->linkType() == Poppler::Link::Goto) {
lg->push_back(static_cast<Poppler::LinkGoto *>(l));
} else {
delete l;
}
}
QList<Poppler::Link *> *links = new QList<Poppler::Link *>;
QList<Poppler::Link *> l = p->links();
links->swap(l);
res->link_mutex.lock();
res->k_page[page].links = lg;
res->k_page[page].links = links;
}
res->link_mutex.unlock();
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment