Members of the KDE Community are recommended to subscribe to the kde-community mailing list at https://mail.kde.org/mailman/listinfo/kde-community to allow them to participate in important discussions and receive other important announcements

Commit cc7d8b67 authored by Enrico Ros's avatar Enrico Ros

Reworked the KPDFLink class. Links are functional now. TOC is working.

Only Movies and (XPDF's) LinkDestKind (that defines 'anchor place' for
link destination) aren't implemented as of now.
Fixed a bug in text selection. This commit will probably generate a fake
unsafe warning. Note: I'm committing from work :-P
CCMAIL: tsdgeos@terra.es

svn path=/branches/kpdf_experiments/kdegraphics/kpdf/; revision=353078
parent dadbd3dc
......@@ -125,52 +125,18 @@ void KPDFOutputDev::drawLink(Link * link, Catalog */*catalog*/)
if ( !link->isOk() )
return;
// create the new KPDFLink using transformed link coordinates
// create the new KPDFLink ...
KPDFLink * l = new KPDFLink( link->getAction() );
double x1, y1, x2, y2;
link->getRect( &x1, &y1, &x2, &y2 );
int left, top, right, bottom;
cvtUserToDev( x1, y1, &left, &top );
cvtUserToDev( x2, y2, &right, &bottom );
KPDFLink * l = new KPDFLink( left, top, right, bottom );
// ... and assign its coords withing current page geometry
l->setGeometry( left, top, right, bottom );
// add the link to the vector container
m_links.push_back( l );
// set link action params processing (XPDF)LinkAction
LinkAction * a = link->getAction();
switch ( a->getKind() )
{
case actionGoTo: {
LinkGoTo * g = (LinkGoTo *) a;
GString * nd = g->getNamedDest();
LinkDest * d = g->getDest();
l->setLinkGoto( d ? d->copy() : 0, nd ? nd->getCString() : 0 );
} break;
case actionGoToR: {
LinkGoToR * g = (LinkGoToR *) a;
GString * nd = g->getNamedDest();
LinkDest * d = g->getDest();
l->setLinkGoto( d ? d->copy() : 0, nd ? nd->getCString() : 0, g->getFileName()->getCString() );
} break;
case actionLaunch:
l->setLinkExecute( ((LinkLaunch *)a)->getFileName()->getCString(),
((LinkLaunch *)a)->getParams()->getCString() );
break;
case actionURI:
l->setLinkURI( ((LinkURI *)a)->getURI()->getCString() );
break;
case actionNamed:
l->setLinkNamed( ((LinkNamed *)a)->getName()->getCString() );
break;
case actionMovie: {
LinkMovie * m = (LinkMovie *) a;
Ref * r = m->getAnnotRef();
l->setLinkMovie( r->num, r->gen, m->getTitle()->getCString() );
} break;
case actionUnknown:
// TODO Warn or not???
break;
}
}
void KPDFOutputDev::updateFont(GfxState *state)
......
......@@ -280,6 +280,18 @@ void KPDFDocument::requestPixmap( int id, uint page, int width, int height, bool
}
}
void KPDFDocument::requestTextPage( uint n )
{
KPDFPage * page = d->pages[ n ];
// build a TextPage using the lightweight KPDFTextDev generator..
KPDFTextDev td;
d->docLock.lock();
d->pdfdoc->displayPage( &td, page->number()+1, 72, 72, 0, true, false );
d->docLock.unlock();
// ..and attach it to the page
page->setSearchPage( td.takeTextPage() );
}
// BEGIN slots
void KPDFDocument::slotSetCurrentPage( int page )
{
......@@ -288,6 +300,8 @@ void KPDFDocument::slotSetCurrentPage( int page )
void KPDFDocument::slotSetCurrentPagePosition( int page, float position )
{
if ( page < 0 || page > (int)d->pages.count() )
page = 0;
if ( page == d->currentPage && position == d->currentPosition )
return;
d->currentPage = page;
......@@ -354,15 +368,7 @@ void KPDFDocument::slotFind( const QString & string, bool keepCase )
}
KPDFPage * page = d->pages[ currentPage ];
if ( !page->hasSearchPage() )
{
// build a TextPage using the lightweight KPDFTextDev generator..
KPDFTextDev td;
d->docLock.lock();
d->pdfdoc->displayPage( &td, page->number()+1, 72, 72, 0, true, false );
d->docLock.unlock();
// ..and attach it to the page
page->setSearchPage( td.takeTextPage() );
}
requestTextPage( page->number() );
if ( page->hasText( d->searchText, d->searchCase, true ) )
{
foundPage = page;
......@@ -383,10 +389,8 @@ void KPDFDocument::slotFind( const QString & string, bool keepCase )
KMessageBox::information( 0, i18n("No matches found for '%1'.").arg(d->searchText) );
}
void KPDFDocument::slotProcessLink( int n, int x, int y )
void KPDFDocument::slotProcessLink( const KPDFLink * link )
{
KPDFPage * page = ( n < (int)d->pages.count() ) ? d->pages[ n ] : 0;
const KPDFLink * link = page ? page->getLink( x, y ) : 0;
if ( !link )
return;
......@@ -412,16 +416,47 @@ void KPDFDocument::slotProcessLink( int n, int x, int y )
// now previous KPDFLink and KPDFPage don't exist anymore!
if ( namedDest && !dest )
{
d->docLock.lock();
GString temp( namedDest );
d->docLock.lock();
dest = d->pdfdoc->findDest( &temp );
d->docLock.unlock();
}
if ( dest )
if ( dest && dest->isOk() )
{
// TODO implement page traversal
//pri NOWARN ntf("HERE I AM\n");
//displayDest(dest, zoom, rotate, gTrue);
// get destination page
int page = dest->getPageNum() - 1;
if ( dest->isPageRef() )
{
Ref ref = dest->getPageRef();
d->docLock.lock();
page = d->pdfdoc->findPage( ref.num, ref.gen ) - 1;
d->docLock.unlock();
}
// get destination position
/* TODO
switch ( dest->getKind() )
{
case destXYZ
OD -> cvtUserToDev( dest->getLeft(), dest->getTop(), &X, &Y );
if ( dest->getChangeLeft() )
make hor change
if ( dest->getChangeTop() )
make ver change
if ( dest->getChangeZoom() )
make zoom change
case destFit
case destFitB
fit page
case destFitH
case destFitBH
read top, fit Width
case destFitV
case destFitBV
read left, fit Height
destFitR
read and fit left,bottom,right,top
}*/
slotSetCurrentPage( page );
}
delete namedDest;
delete dest;
......@@ -432,21 +467,15 @@ void KPDFDocument::slotProcessLink( int n, int x, int y )
if ( fileName.endsWith( ".pdf" ) || fileName.endsWith( ".PDF" ) )
openRelativeFile( fileName );
else
{
KMessageBox::information( 0, i18n("The pdf file is trying to execute an external application and for your safety kpdf does not allow that.") );
/* core developers say this is too dangerous
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());
}*/
}
/* core developers say this is too dangerous. watch out for the security warning on kde-cvs :-)
fileName += " ";
if ( link->getParameters() )
fileName += link->getParameters();
fileName += " &";
if ( KMessageBox::questionYesNo( 0, i18n("Do you want to execute the command:\n%1").arg(fileName), i18n("Launching external application")) == KMessageBox::Yes )
system( fileName.latin1() );
*/
} break;
case KPDFLink::Named: {
......
......@@ -17,6 +17,7 @@
class Outline;
class KPDFPage;
class KPDFLink;
/**
* @short Base class for objects being notified when something changes.
......@@ -71,6 +72,7 @@ public:
// observers related methods
void addObserver( KPDFDocumentObserver * pObserver );
void requestPixmap( int id, uint page, int width, int height, bool syncronous = false );
void requestTextPage( uint page );
public slots:
// document commands via slots
......@@ -79,7 +81,7 @@ public slots:
void slotSetFilter( const QString & pattern, bool caseSensitive );
void slotBookmarkPage( int page, bool enabled );
void slotFind( const QString & text = "", bool caseSensitive = false );
void slotProcessLink( int page, int x, int y );
void slotProcessLink( const KPDFLink * link );
signals:
// notify changes via signals
......
......@@ -102,8 +102,6 @@ Part::Part(QWidget *parentWidget, const char *widgetName,
m_toolBox->setMinimumWidth( 60 );
m_toolBox->setMaximumWidth( 200 );
// TODO when links following is done connect the execute(LinkAction *action) signal from
// tocFrame to the same slot
TOC * tocFrame = new TOC( m_toolBox, document );
m_toolBox->addItem( tocFrame, QIconSet(SmallIcon("text_left")), i18n("Contents") );
connect(tocFrame, SIGNAL(hasTOC(bool)), this, SLOT(enableTOC(bool)));
......@@ -341,192 +339,54 @@ void Part::slotFindNext()
void Part::slotSaveFileAs()
{
KURL saveURL = KFileDialog::getSaveURL(
url().isLocalFile()
? url().url()
: url().fileName(),
QString::null,
widget(),
QString::null );
KURL saveURL = KFileDialog::getSaveURL(
url().isLocalFile() ? url().url() : url().fileName(),
QString::null, widget(), QString::null );
if( !KIO::NetAccess::upload( url().path(), saveURL, static_cast<QWidget*>( 0 ) ) )
; // TODO: Proper error dialog
KMessageBox::information( 0, i18n("File could not be saved in '%1'. Try to save it to another location.").arg( url().path() ) );
}
/*
void Part::displayDestination(LinkDest* dest)
{
int pageNumber;
// int dx, dy;
if (dest->isPageRef())
{
Ref pageRef = dest->getPageRef();
pageNumber = m_doc->findPage(pageRef.num, pageRef.gen);
}
else
{
pageNumber = dest->getPageNum();
}
if (pageNumber <= 0 || pageNumber > m_doc->getNumPages())
{
pageNumber = 1;
}
displayPage(pageNumber);
return;
if (fullScreen) {
return;
}
switch (dest->getKind()) {
case destXYZ:
out->cvtUserToDev(dest->getLeft(), dest->getTop(), &dx, &dy);
if (dest->getChangeLeft() || dest->getChangeTop()) {
if (dest->getChangeLeft()) {
hScrollbar->setPos(dx, canvas->getWidth());
}
if (dest->getChangeTop()) {
vScrollbar->setPos(dy, canvas->getHeight());
}
canvas->scroll(hScrollbar->getPos(), vScrollbar->getPos());
}
//~ what is the zoom parameter?
break;
case destFit:
case destFitB:
//~ do fit
hScrollbar->setPos(0, canvas->getWidth());
vScrollbar->setPos(0, canvas->getHeight());
canvas->scroll(hScrollbar->getPos(), vScrollbar->getPos());
break;
case destFitH:
case destFitBH:
//~ do fit
out->cvtUserToDev(0, dest->getTop(), &dx, &dy);
hScrollbar->setPos(0, canvas->getWidth());
vScrollbar->setPos(dy, canvas->getHeight());
canvas->scroll(hScrollbar->getPos(), vScrollbar->getPos());
break;
case destFitV:
case destFitBV:
//~ do fit
out->cvtUserToDev(dest->getLeft(), 0, &dx, &dy);
hScrollbar->setPos(dx, canvas->getWidth());
vScrollbar->setPos(0, canvas->getHeight());
canvas->scroll(hScrollbar->getPos(), vScrollbar->getPos());
break;
case destFitR:
//~ do fit
out->cvtUserToDev(dest->getLeft(), dest->getTop(), &dx, &dy);
hScrollbar->setPos(dx, canvas->getWidth());
vScrollbar->setPos(dy, canvas->getHeight());
canvas->scroll(hScrollbar->getPos(), vScrollbar->getPos());
break;
}
}*/
/*
void Part::executeAction(LinkAction* action)
void Part::slotToggleLeftPanel( bool on )
{
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;
}
}*/
// show/hide left qtoolbox
m_toolBox->setShown( on );
// this needs to be hidden explicitly to disable thumbnails gen
m_thumbnailList->setShown( on );
}
void Part::slotPrint()
void Part::slotPrintPreview()
{
/*
if (m_doc == 0)
if (m_doc == 0)
return;
double width, height;
int landscape, portrait;
KPrinter printer;
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);
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;
portrait = 0;
for (int i = 1; i <= m_doc->getNumPages(); i++)
{
landscape = 0;
portrait = 0;
for (int i = 1; i <= m_doc->getNumPages(); i++)
{
width = m_doc->getPageWidth(i);
height = m_doc->getPageHeight(i);
if (m_doc->getPageRotate(i) == 90 || m_doc->getPageRotate(i) == 270) qSwap(width, height);
if (width > height) landscape++;
else portrait++;
}
if (landscape > portrait) printer.setOrientation(KPrinter::Landscape);
}
if (landscape > portrait) printer.setOption("orientation-requested", "4");
if (printer.setup(widget()))
{
doPrint( printer );
}
doPrint(printer);
*/
}
void Part::slotPrintPreview()
void Part::slotPrint()
{
/*
if (m_doc == 0)
......@@ -536,8 +396,9 @@ void Part::slotPrintPreview()
int landscape, portrait;
KPrinter printer;
printer.setPageSelection(KPrinter::ApplicationSide);
printer.setMinMax(1, m_doc->getNumPages());
printer.setPreviewOnly( true );
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
......@@ -552,9 +413,12 @@ void Part::slotPrintPreview()
if (width > height) landscape++;
else portrait++;
}
if (landscape > portrait) printer.setOption("orientation-requested", "4");
if (landscape > portrait) printer.setOrientation(KPrinter::Landscape);
doPrint(printer);
if (printer.setup(widget()))
{
doPrint( printer );
}
*/
}
......@@ -579,14 +443,6 @@ void Part::doPrint( KPrinter& /*printer*/ )
*/
}
void Part::slotToggleLeftPanel( bool on )
{
// show/hide left qtoolbox
m_toolBox->setShown( on );
// this needs to be hidden explicitly to disable thumbnails gen
m_thumbnailList->setShown( on );
}
/*
* BrowserExtension class
*/
......
......@@ -38,51 +38,39 @@ class PageView;
class SearchWidget;
class KPDFDocument;
namespace KPDF
namespace KPDF {
class BrowserExtension;
/**
* This is a "Part". It that does all the real work in a KPart
* application.
*
* @short Main Part
* @author Wilco Greven <greven@kde.org>
* @version 0.2
*/
class Part : public KParts::ReadOnlyPart
{
class BrowserExtension;
/**
* This is a "Part". It that does all the real work in a KPart
* application.
*
* @short Main Part
* @author Wilco Greven <greven@kde.org>
* @version 0.2
*/
class Part : public KParts::ReadOnlyPart
{
Q_OBJECT
public:
/**
* Default constructor
*/
Q_OBJECT
public:
// Default constructor
Part(QWidget* parentWidget, const char* widgetName,
QObject* parent, const char* name, const QStringList& args);
/**
* Destructor
*/
virtual ~Part();
// Destructor
~Part();
static KAboutData* createAboutData();
protected:
// reimplemented from KParts::ReadOnlyPart
bool openFile();
bool openURL(const KURL &url);
bool closeURL();
void displayPage(int pageNumber ); //TODO REMOVE ME!
protected:
// reimplemented from KParts::ReadOnlyPart
virtual bool openFile();
// reimplemented from KParts::ReadOnlyPart
virtual bool openURL(const KURL &url);
void updateAction();
void doPrint( KPrinter& printer );
protected slots:
protected slots:
// connected to actions
void slotGoToPage();
void slotPreviousPage();
......@@ -98,11 +86,13 @@ namespace KPDF
void updateActions();
void enableTOC(bool enable);
public slots:
public slots:
// connected to Shell action (and browserExtension), not local one
void slotPrint();
private:
private:
void doPrint( KPrinter& printer );
// the document
KPDFDocument * document;
......@@ -124,19 +114,20 @@ namespace KPDF
KAction *m_lastPage;
KAction *m_find;
KAction *m_findNext;
};
};
class BrowserExtension : public KParts::BrowserExtension
{
Q_OBJECT
public:
class BrowserExtension : public KParts::BrowserExtension
{
Q_OBJECT
public:
BrowserExtension(Part*);
public slots:
public slots:
// Automatically detected by the host.
void print();
};
};
}
......
......@@ -214,9 +214,73 @@ void KPDFPage::setPixmapOverlayNotations( ..DOMdescription.. )
KPDFLink::KPDFLink( int l, int t, int r, int b )
: m_type( Unknown ), m_dest( 0 ), m_destNamed( 0 ),
m_fileName( 0 ), m_parameters( 0 ), m_uri( 0 )
KPDFLink::KPDFLink( LinkAction * a )
: m_type( Unknown ), x_min( 0 ), x_max( 0 ), y_min( 0 ), y_max( 0 ),
m_dest( 0 ), m_destNamed( 0 ), m_fileName( 0 ), m_parameters( 0 ), m_uri( 0 )
{
// set link action params processing (XPDF)LinkAction
switch ( a->getKind() )
{
case actionGoTo: {
LinkGoTo * g = (LinkGoTo *) a;
m_type = Goto;
// copy link dest (LinkDest class)
LinkDest * d = g->getDest();
m_dest = d ? d->copy() : 0;
// copy link namedDest (const char *)
GString * nd = g->getNamedDest();
copyString( m_destNamed, nd ? nd->getCString() : 0 );
} break;
case actionGoToR: {
m_type = Goto;
LinkGoToR * g = (LinkGoToR *) a;
// copy link file (const char *)
copyString( m_fileName, g->getFileName()->getCString() );
// copy link dest (LinkDest class)
LinkDest * d = g->getDest();
m_dest = d ? d->copy() : 0;
// copy link namedDest (const char *)
GString * nd = g->getNamedDest();
copyString( m_destNamed, nd ? nd->getCString() : 0 );
} break;
case actionLaunch: {
m_type = Execute;
LinkLaunch * e = (LinkLaunch *)a;
// copy name and parameters of the file to open(in case of PDF)/launch
copyString( m_fileName, e->getFileName()->getCString() );
copyString( m_parameters, e->getParams()->getCString() );
} break;
case actionURI:
m_type = URI;
// copy URI (const char *)
copyString( m_uri, ((LinkURI *)a)->getURI()->getCString() );
break;
case actionNamed:
m_type = Named;
// copy Action Name (const char * like Quit, Next, Back, etc..)
copyString( m_uri, ((LinkNamed *)a)->getName()->getCString() );
break;
case actionMovie: {
m_type = Movie;
LinkMovie * m = (LinkMovie *) a;
// copy Movie parameters (2 IDs and a const char *)
Ref * r = m->getAnnotRef();
m_refNum = r->num;
m_refGen = r->gen;
copyString( m_uri, m->getTitle()->getCString() );
} break;
case actionUnknown:
break;
}
}
void KPDFLink::setGeometry( int l, int t, int r, int b )
{
// assign coordinates swapping them if negative width or height
x_min = r > l ? l : r;
......@@ -234,43 +298,27 @@ KPDFLink::~KPDFLink()
delete [] m_uri;
}
void KPDFLink::setLinkGoto( LinkDest * d, const char * n, const char * file )
{
m_type = Goto;
delete m_dest;
m_dest = d;
copyString( m_destNamed, n );
copyString( m_fileName, file );
}
void KPDFLink::setLinkExecute( const char * file, const char * par )
bool KPDFLink::contains( int x, int y ) const
{
m_type = Execute;
copyString( m_fileName, file );
copyString( m_parameters, par );