Commit 7cd6f373 authored by Albert Astals Cid's avatar Albert Astals Cid
Browse files

Commiting first work on getting links to work.

ATM only links to web pages are tested, i would like to get pdf with some weird links like the one that quits the app viewing it, or links to external files, etc so i can test them.

svn path=/trunk/kdegraphics/kpdf/; revision=346314
parent 4dea29c9
......@@ -17,7 +17,7 @@
#include <qpainter.h>
#include <qmutex.h>
#include <kglobalsettings.h>
#include <kglobalsettings.h>
#include <kurldrag.h>
#include "PDFDoc.h"
......@@ -42,6 +42,7 @@ namespace KPDF
m_outputdev = new QOutputDevPixmap(paperColor);
setFocusPolicy( QWidget::StrongFocus );
viewport()->setFocusPolicy( QWidget::WheelFocus );
viewport()->setMouseTracking( true );
}
PageWidget::~PageWidget()
{
......@@ -65,6 +66,7 @@ namespace KPDF
void
PageWidget::contentsMousePressEvent(QMouseEvent* e)
{
double x, y;
if (m_doc == 0)
return;
if ( e->button() & LeftButton )
......@@ -77,12 +79,14 @@ namespace KPDF
emit rightClick();
}
m_pressedAction = m_doc->findLink(e->x()/m_ppp, e->y()/m_ppp);
m_outputdev->cvtDevToUser(e->x(), e->y(), &x, &y);
m_pressedAction = m_doc->findLink(x, y);
}
void
PageWidget::contentsMouseReleaseEvent(QMouseEvent* e)
{
double x, y;
if (m_doc == 0)
return;
......@@ -90,14 +94,11 @@ namespace KPDF
{
setCursor( arrowCursor );
}
else
{
LinkAction* action = m_doc->findLink(e->x()/m_ppp, e->y()/m_ppp);
if (action == m_pressedAction)
emit linkClicked(action);
m_pressedAction = 0;
}
m_outputdev->cvtDevToUser(e->x(), e->y(), &x, &y);
LinkAction* action = m_doc->findLink(x, y);
if (action == m_pressedAction && action) emit linkClicked(action);
m_pressedAction = 0;
}
void
......@@ -111,11 +112,11 @@ namespace KPDF
scrollBy( delta.x(), delta.y() );
m_dragGrabPos = e->globalPos();
}
else
{
LinkAction* action = m_doc->findLink(e->x()/m_ppp, e->y()/m_ppp);
setCursor(action != 0 ? Qt::PointingHandCursor : Qt::ArrowCursor);
}
double x, y;
m_outputdev->cvtDevToUser(e->x(), e->y(), &x, &y);
LinkAction* action = m_doc->findLink(x, y);
setCursor(action ? Qt::PointingHandCursor : Qt::ArrowCursor);
}
void PageWidget::drawContents ( QPainter *p, int clipx, int clipy, int clipw, int cliph )
......@@ -127,17 +128,17 @@ namespace KPDF
if ( !im.isNull() )
{
p->drawImage ( clipx, clipy, im, clipx, clipy, clipw, cliph );
if ((clipw + clipx) > im.width())
p->fillRect ( im.width(),
clipy,
clipw - (im.width() - clipx),
im.height() - clipy,
if ((clipw + clipx) > im.width())
p->fillRect ( im.width(),
clipy,
clipw - (im.width() - clipx),
im.height() - clipy,
bc );
if ((cliph + clipy) > im.height())
p->fillRect ( clipx,
im.height(),
clipw,
cliph - (im.height() - clipy),
p->fillRect ( clipx,
im.height(),
clipw,
cliph - (im.height() - clipy),
bc );
if (m_selection)
{
......@@ -178,7 +179,7 @@ namespace KPDF
{
// any idea why this mutex is necessary?
static QMutex mutex;
m_selection = false;
Q_ASSERT(mutex.locked() == false);
mutex.lock();
......@@ -374,7 +375,7 @@ namespace KPDF
m_xMin = 0;
m_yMin = 0;
}
b = m_outputdev -> find(u, len, !next, true, next, false, &m_xMin, &m_yMin, &m_xMax, &m_yMax);
m_xMin = m_xMin / m_zoomFactor;
m_yMin = m_yMin / m_zoomFactor;
......
......@@ -31,6 +31,7 @@
#include <qtimer.h>
#include <kaction.h>
#include <kapplication.h>
#include <kdebug.h>
#include <kinstance.h>
#include <kprinter.h>
......@@ -42,6 +43,8 @@
#include <kfiledialog.h>
#include <kfinddialog.h>
#include <kmessagebox.h>
#include <krun.h>
#include <kuserprofile.h>
#include <kio/netaccess.h>
#include "kpdf_error.h"
......@@ -50,6 +53,8 @@
#include "GString.h"
#include "gfile.h"
#include "Error.h"
#include "GlobalParams.h"
#include "PDFDoc.h"
#include "TextOutputDev.h"
......@@ -87,6 +92,7 @@ Part::Part(QWidget *parentWidget, const char *widgetName,
connect(pdfpartview, SIGNAL( clicked ( int ) ), this, SLOT( pageClicked ( int ) ));
m_outputDev = pdfpartview->outputdev;
connect(m_outputDev, SIGNAL(linkClicked(LinkAction*)), this, SLOT(executeAction(LinkAction*)));
m_outputDev->setAcceptDrops( true );
setWidget(pdfpartview);
......@@ -200,7 +206,7 @@ void Part::slotZoom( const QString&nz )
z.remove( z.find( '%' ), 1 );
bool isNumber = true;
zoom = KGlobal::locale()->readNumber( z, &isNumber ) / 100;
if ( isNumber )
{
kdDebug() << "ZOOM = " << nz << ", setting zoom = " << zoom << endl;
......@@ -562,12 +568,12 @@ Part::print()
double width, height;
int landscape, portrait;
KPrinter printer;
printer.setPageSelection(KPrinter::ApplicationSide);
printer.setMinMax(1, m_doc->getNumPages());
printer.setCurrentPage(m_currentPage);
printer.setMargins(0, 0, 0, 0);
// if some pages are landscape and others are not the most common win as kprinter does
// not accept a per page setting
landscape = 0;
......@@ -581,7 +587,7 @@ Part::print()
else portrait++;
}
if (landscape > portrait) printer.setOrientation(KPrinter::Landscape);
if (printer.setup(widget()))
{
doPrint( printer );
......@@ -595,70 +601,234 @@ Part::setFixedZoomFactor(float zoomFactor)
}
*/
/*
void
void
Part::executeAction(LinkAction* action)
{
if (action == 0)
return;
LinkActionKind kind = action->getKind();
switch (kind)
{
case actionGoTo:
case actionGoToR:
{
LinkDest* dest = 0;
GString* namedDest = 0;
if (kind == actionGoTo)
{
if ((dest = ((LinkGoTo*)action)->getDest()))
dest = dest->copy();
else if ((namedDest = ((LinkGoTo*)action)->getNamedDest()))
namedDest = namedDest->copy();
}
else
{
if ((dest = ((LinkGoToR*)action)->getDest()))
dest = dest->copy();
else if ((namedDest = ((LinkGoToR*)action)->getNamedDest()))
namedDest = namedDest->copy();
s = ((LinkGoToR*)action)->getFileName()->getCString();
//~ translate path name for VMS (deal with '/')
if (!loadFile(fileName))
{
delete dest;
delete namedDest;
return;
}
}
if (namedDest != 0)
{
dest = m_doc->findDest(namedDest);
delete namedDest;
}
if (dest != 0)
{
displayDestination(dest);
delete dest;
}
else
{
if (kind == actionGoToR)
displayPage(1);
}
break;
}
default:
break;
}
}*/
LinkActionKind kind;
LinkDest *dest;
GString *namedDest;
char *s;
GString *fileName, *fileName2;
// GString *cmd;
GString *actionName;
Object movieAnnot, obj1, obj2;
int i;
KService::Ptr ptr;
KURL::List lst;
kind = action -> getKind();
// copied from xpdf have a look and understand a bit :D
switch (kind)
{
// GoTo / GoToR action
case actionGoTo:
case actionGoToR:
if (kind == actionGoTo)
{
dest = NULL;
namedDest = NULL;
if ((dest = ((LinkGoTo *)action)->getDest()))
{
dest = dest->copy();
}
else if ((namedDest = ((LinkGoTo *)action)->getNamedDest()))
{
namedDest = namedDest->copy();
}
}
else
{
dest = NULL;
namedDest = NULL;
if ((dest = ((LinkGoToR *)action)->getDest()))
{
dest = dest->copy();
}
else if ((namedDest = ((LinkGoToR *)action)->getNamedDest()))
{
namedDest = namedDest->copy();
}
s = ((LinkGoToR *)action)->getFileName()->getCString();
//~ translate path name for VMS (deal with '/')
if (isAbsolutePath(s))
{
fileName = new GString(s);
}
else
{
fileName = appendToPath(grabPath(m_doc->getFileName()->getCString()), s);
}
if (!openURL(fileName->getCString()))
{
if (dest)
{
delete dest;
}
if (namedDest)
{
delete namedDest;
}
delete fileName;
return;
}
delete fileName;
}
if (namedDest)
{
dest = m_doc->findDest(namedDest);
delete namedDest;
}
if (dest)
{
// TODO implement
//displayDest(dest, zoom, rotate, gTrue);
delete dest;
}
else
{
if (kind == actionGoToR) goToPage(1);
}
break;
// Launch action
case actionLaunch:
fileName = ((LinkLaunch *)action)->getFileName();
s = fileName->getCString();
if (!strcmp(s + fileName->getLength() - 4, ".pdf") ||
!strcmp(s + fileName->getLength() - 4, ".PDF"))
{
//~ translate path name for VMS (deal with '/')
if (isAbsolutePath(s))
{
fileName = fileName->copy();
}
else
{
fileName = appendToPath(grabPath(m_doc->getFileName()->getCString()), s);
}
if (!openURL(fileName->getCString()))
{
delete fileName;
return;
}
delete fileName;
goToPage(1);
}
else
{
fileName = fileName->copy();
if (((LinkLaunch *)action)->getParams())
{
fileName->append(' ');
fileName->append(((LinkLaunch *)action)->getParams());
}
fileName->append(" &");
if (KMessageBox::questionYesNo(widget(), i18n("Do you want to execute the command:\n%1").arg(fileName->getCString()), i18n("Launching external application")) == KMessageBox::Yes)
{
system(fileName->getCString());
}
delete fileName;
}
break;
// URI action
case actionURI:
ptr = KServiceTypeProfile::preferredService("text/html", "Application");
lst.append(((LinkURI *)action)->getURI()->getCString());
KRun::run(*ptr, lst);
break;
// Named action
case actionNamed:
actionName = ((LinkNamed *)action)->getName();
if (!actionName->cmp("NextPage")) nextPage();
else if (!actionName->cmp("PrevPage")) previousPage();
else if (!actionName->cmp("FirstPage")) goToPage(1);
else if (!actionName->cmp("LastPage")) goToPage(m_doc->getNumPages());
else if (!actionName->cmp("GoBack"))
{
// TODO i think that means back in history not in page, check i XPDFCore.cc
//goBackward();
}
else if (!actionName->cmp("GoForward"))
{
// TODO i think that means forward in history not in page, check i XPDFCore.cc
// goForward();
}
// TODO is this legal if integrated on konqy?
else if (!actionName->cmp("Quit")) kapp -> quit();
else
{
error(-1, "Unknown named action: '%s'", actionName->getCString());
}
break;
// Movie action
case actionMovie:
if (((LinkMovie *)action)->hasAnnotRef())
{
m_doc->getXRef()->fetch(((LinkMovie *)action)->getAnnotRef()->num,
((LinkMovie *)action)->getAnnotRef()->gen,
&movieAnnot);
}
else
{
m_doc->getCatalog()->getPage(m_currentPage)->getAnnots(&obj1);
if (obj1.isArray())
{
for (i = 0; i < obj1.arrayGetLength(); ++i)
{
if (obj1.arrayGet(i, &movieAnnot)->isDict())
{
if (movieAnnot.dictLookup("Subtype", &obj2)->isName("Movie"))
{
obj2.free();
break;
}
obj2.free();
}
movieAnnot.free();
}
obj1.free();
}
}
if (movieAnnot.isDict())
{
if (movieAnnot.dictLookup("Movie", &obj1)->isDict())
{
if (obj1.dictLookup("F", &obj2))
{
if ((fileName = LinkAction::getFileSpecName(&obj2)))
{
if (!isAbsolutePath(fileName->getCString()))
{
fileName2 = appendToPath(grabPath(m_doc->getFileName()->getCString()),
fileName->getCString());
delete fileName;
fileName = fileName2;
}
// TODO implement :D
// get the mimetype of fileName and then run KServiceTypeProfile
// preferredService on it
// Having a file where test would be cool
//runCommand(cmd, fileName);
delete fileName;
}
obj2.free();
}
obj1.free();
}
}
movieAnnot.free();
break;
// unknown action type
case actionUnknown:
error(-1, "Unknown link action type: '%s'", ((LinkUnknown *)action)->getAction()->getCString());
break;
}
}
void Part::slotFitToWidthToggled()
{
m_zoomMode = m_fitToWidth->isChecked() ? FitWidth : FixedFactor;
......@@ -710,11 +880,11 @@ void Part::printPreview()
double width, height;
int landscape, portrait;
KPrinter printer;
printer.setMinMax(1, m_doc->getNumPages());
printer.setPreviewOnly( true );
printer.setMargins(0, 0, 0, 0);
// if some pages are landscape and others are not the most common win as kprinter does
// not accept a per page setting
landscape = 0;
......@@ -728,7 +898,7 @@ void Part::printPreview()
else portrait++;
}
if (landscape > portrait) printer.setOption("orientation-requested", "4");
doPrint(printer);
}
......@@ -740,7 +910,7 @@ void Part::doPrint( KPrinter& printer )
QOutputDevKPrinter printdev( painter, paperColor, printer );
printdev.startDoc(m_doc->getXRef());
QValueList<int> pages = printer.pageList();
for ( QValueList<int>::ConstIterator i = pages.begin(); i != pages.end();)
{
m_docMutex.lock();
......
......@@ -114,7 +114,7 @@ namespace KPDF
void slotGoToPage();
void printPreview();
/*void executeAction(LinkAction*);*/
void executeAction(LinkAction*);
void showScrollBars( bool );
void showMarkList( bool );
......@@ -125,7 +125,7 @@ namespace KPDF
private:
void doFind(QString s, bool next);
PDFDoc* m_doc;
PageWidget* m_outputDev;
PDFPartView * pdfpartview;
......
Markdown is supported
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