summaryrefslogtreecommitdiffstats
path: root/kghostview/thumbnailservice.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'kghostview/thumbnailservice.cpp')
-rw-r--r--kghostview/thumbnailservice.cpp161
1 files changed, 161 insertions, 0 deletions
diff --git a/kghostview/thumbnailservice.cpp b/kghostview/thumbnailservice.cpp
new file mode 100644
index 00000000..4d653cfa
--- /dev/null
+++ b/kghostview/thumbnailservice.cpp
@@ -0,0 +1,161 @@
+/**
+ * Copyright (C) 1997-2003 the KGhostView authors. See file AUTHORS.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#include "thumbnailservice.h"
+
+#include "kgv_miniwidget.h"
+#include "kpswidget.h"
+#include "kgv_view.h"
+
+#include <kdebug.h>
+#include <qtimer.h>
+#include <algorithm>
+#include <cassert>
+#include <cstring>
+
+ThumbnailService::ThumbnailService( KGVMiniWidget* parent, const char* name ) :
+ QObject( parent, name ),
+ _mini( parent ),
+ timer_( new QTimer( this ) ),
+ _busy( false ),
+ _enabled( false )
+{
+ _thumbnailDrawer = new KPSWidget( parent->_part->widget(), "thumbnail-drawer" );
+ _thumbnailDrawer->readSettings();
+ connect( _thumbnailDrawer, SIGNAL( newPageImage( QPixmap ) ), SLOT( slotDone( QPixmap ) ) );
+ connect( timer_, SIGNAL( timeout() ), SLOT( processOne() ) );
+ _thumbnailDrawer->hide();
+}
+
+ThumbnailService::~ThumbnailService()
+{
+}
+
+bool ThumbnailService::Request::operator < ( ThumbnailService::Request b ) const
+{
+ if ( urgent != b.urgent ) return urgent;
+ if ( page != b.page ) return page < b.page;
+ // below is just so that == can be in terms of "<"
+ if ( receiver != b.receiver ) return std::less<QObject*>()( receiver, b.receiver );
+ if ( slot != b.slot ) return std::strcmp( slot, b.slot ) < 0;
+ return false;
+}
+
+void ThumbnailService::delayedGetThumbnail( const int page, QObject* rec, const char* slot, bool urgent )
+{
+ kdDebug( 4500 ) << "ThumbnailService::delayedGetThumbnail: request for page " << page << endl;
+ pending.insert( Request( page, rec, slot, urgent ) );
+ if ( !_busy ) {
+ _busy = true;
+ // The reason for the code below might not be obvious:
+ // It is much nicer to have the the thumbnails appear from top to bottom.
+ // However, when several are requested at once (or almost), then we cannot control the order
+ // unless we delay a bit the first one
+ if ( urgent ) processOne();
+ else timer_->start( 150, true );
+ }
+}
+
+void ThumbnailService::cancelRequests( const int page, QObject* rec, const char* slot )
+{
+ std::set<Request>::iterator first = pending.begin(), last = pending.end();
+ while ( first != last ) {
+ if ( ( page == -1 || page == first->page ) &&
+ ( !rec || rec == first->receiver ) &&
+ ( !slot || !strcmp( slot, first->slot ) ) ) {
+ std::set<Request>::iterator next = first;
+ ++next;
+ pending.erase( first );
+ first = next;
+ } else {
+ ++first;
+ }
+ }
+}
+
+void ThumbnailService::reset()
+{
+ kdDebug( 4500 ) << "ThumbnailService::reset()" << endl;
+ timer_->stop();
+ pending.clear();
+ assert( _thumbnailDrawer );
+ _thumbnailDrawer->stopInterpreter();
+ _busy = false;
+ _enabled = false;
+}
+
+void ThumbnailService::setEnabled( const bool e )
+{
+ kdDebug( 4500 ) << "ThumbnailService::setEnabled( " << ( e ? "true" : "false" ) << " )" << endl;
+ _enabled = e;
+ if ( _enabled && _busy ) processOne();
+}
+
+void ThumbnailService::slotDone( QPixmap pix )
+{
+ kdDebug( 4500 ) << "ThumbnailService::slotDone(): got page" << endl;
+ pix.detach();
+ emit relayPixmap( pix );
+ processOne();
+}
+
+
+void ThumbnailService::processOne()
+{
+ kdDebug( 4500 ) << "ThumbnailService::processOne()" << endl;
+ if ( !_enabled ) return;
+ if ( !_mini || !_mini->dsc() || !_mini->dsc()->isStructured() ) {
+ _busy = false;
+ pending.clear();
+ return;
+ }
+ assert( _thumbnailDrawer );
+ if ( pending.empty() ) {
+ _busy = false;
+ return;
+ }
+ _busy = true;
+ FILE* file = _mini->psFile();
+ Request req = *pending.begin();
+ kdDebug( 4500 ) << "ThumbnailService::processOne(): processing " << req.page << "(of " << pending.size() << " requests)" << endl;
+ disconnect( SIGNAL( relayPixmap( QPixmap ) ) );
+ while ( !pending.empty() && req.page == pending.begin()->page ) {
+ req = *pending.begin();
+ connect( this, SIGNAL( relayPixmap( QPixmap ) ), req.receiver, req.slot );
+ pending.erase( pending.begin() );
+ }
+ _thumbnailDrawer->setOrientation( _mini->orientation( req.page ) );
+ _thumbnailDrawer->setBoundingBox( _mini->boundingBox( req.page ) );
+ _thumbnailDrawer->setMagnification( 0.2 );
+ if ( !_thumbnailDrawer->isInterpreterRunning() ) {
+ _thumbnailDrawer->setFileName( _mini->_document->fileName(), true );
+ _thumbnailDrawer->startInterpreter();
+ _thumbnailDrawer->sendPS( file, _mini->dsc()->beginprolog(),
+ _mini->dsc()->endprolog() );
+ _thumbnailDrawer->sendPS( file, _mini->dsc()->beginsetup(),
+ _mini->dsc()->endsetup() );
+ }
+ else {
+ _thumbnailDrawer->nextPage();
+ }
+ _thumbnailDrawer->sendPS( file, _mini->dsc()->page()[ req.page ].begin,
+ _mini->dsc()->page()[ req.page ].end );
+}
+
+#include "thumbnailservice.moc"
+