mirror of
https://git.lyx.org/repos/lyx.git
synced 2024-12-25 05:55:34 +00:00
Alfredo's Loader Queue.
git-svn-id: svn://svn.lyx.org/lyx/lyx-devel/trunk@6221 a592a061-630c-0410-9148-cb99ea01b6c8
This commit is contained in:
parent
01ae17a24d
commit
546e14eb16
@ -34,6 +34,9 @@
|
||||
and a few other (not so) minor things, like
|
||||
rewriting most of the LyX kernel. Also current
|
||||
source maintainer.
|
||||
@bAlfredo Braunstein
|
||||
@iE-mail: abraunst@libero.it
|
||||
a (psuedo) threaded graphics loader queue
|
||||
@bChristian Buescher
|
||||
user-definable keys, lyxserver and more
|
||||
@bFrancesc Burrull i Mestres
|
||||
|
@ -4,6 +4,10 @@
|
||||
* examples/de_beispiel_roh.lyx: Small fixes to make it look like a German
|
||||
document
|
||||
|
||||
2003-02-21 Angus Leeming <leeming@lyx.org>
|
||||
|
||||
* CREDITS: Add Alfredo Braunstein.
|
||||
|
||||
2003-02-21 Angus Leeming <leeming@lyx.org>
|
||||
|
||||
* ui/default.ui: change bibkey-insert to bibtem-insert.
|
||||
|
@ -1,3 +1,11 @@
|
||||
2003-02-20 Alfredo Braunstein <abraunst@libero.it>
|
||||
|
||||
* LoaderQueue.[Ch]: added. Implements a service queue that loads
|
||||
images in background
|
||||
* GraphicsSupport.[Ch]: removed
|
||||
* Makefile.am: the changes above
|
||||
* GraphicsLoader.C: use the loading queue
|
||||
|
||||
2003-01-21 Angus Leeming <leeming@lyx.org>
|
||||
|
||||
* PreviewLoader.C (dumpPreamble): ensure that \lyxlock does not prevent
|
||||
|
@ -18,7 +18,7 @@
|
||||
#include "GraphicsCacheItem.h"
|
||||
#include "GraphicsImage.h"
|
||||
#include "GraphicsParams.h"
|
||||
#include "GraphicsSupport.h"
|
||||
#include "LoaderQueue.h"
|
||||
|
||||
#include "frontends/LyXView.h"
|
||||
#include "frontends/Timeout.h"
|
||||
@ -66,8 +66,6 @@ private:
|
||||
///
|
||||
Params params_;
|
||||
|
||||
///
|
||||
Timeout timer;
|
||||
// Multiple Insets can share the same image
|
||||
typedef std::list<Inset const *> InsetList;
|
||||
///
|
||||
@ -196,10 +194,8 @@ Image const * Loader::image() const
|
||||
|
||||
|
||||
Loader::Impl::Impl(Params const & params)
|
||||
: status_(WaitingToLoad), params_(params),
|
||||
timer(2000, Timeout::ONETIME)
|
||||
: status_(WaitingToLoad), params_(params)
|
||||
{
|
||||
timer.timeout.connect(boost::bind(&Impl::checkedLoading, this));
|
||||
}
|
||||
|
||||
|
||||
@ -293,7 +289,7 @@ void Loader::Impl::createPixmap()
|
||||
|
||||
void Loader::Impl::startLoading(Inset const & inset, BufferView const & bv)
|
||||
{
|
||||
if (status_ != WaitingToLoad || timer.running())
|
||||
if (status_ != WaitingToLoad)
|
||||
return;
|
||||
|
||||
InsetList::const_iterator it = insets.begin();
|
||||
@ -303,46 +299,7 @@ void Loader::Impl::startLoading(Inset const & inset, BufferView const & bv)
|
||||
insets.push_back(&inset);
|
||||
view = bv.owner()->view();
|
||||
|
||||
timer.start();
|
||||
}
|
||||
|
||||
|
||||
namespace {
|
||||
|
||||
struct FindVisibleInset {
|
||||
|
||||
FindVisibleInset(std::list<VisibleParagraph> const & vps) : vps_(vps) {}
|
||||
|
||||
bool operator()(Inset const * inset_ptr)
|
||||
{
|
||||
if (!inset_ptr)
|
||||
return false;
|
||||
return isInsetVisible(*inset_ptr, vps_);
|
||||
}
|
||||
|
||||
private:
|
||||
std::list<VisibleParagraph> const & vps_;
|
||||
};
|
||||
|
||||
} // namespace anon
|
||||
|
||||
|
||||
void Loader::Impl::checkedLoading()
|
||||
{
|
||||
if (insets.empty() || !view.get())
|
||||
return;
|
||||
|
||||
std::list<VisibleParagraph> const vps =
|
||||
getVisibleParagraphs(*view.get());
|
||||
|
||||
InsetList::const_iterator it = insets.begin();
|
||||
InsetList::const_iterator end = insets.end();
|
||||
|
||||
it = std::find_if(it, end, FindVisibleInset(vps));
|
||||
|
||||
// One of the insets is visible, so start loading the image.
|
||||
if (it != end)
|
||||
cached_item_->startLoading();
|
||||
LoaderQueue::get().touch(cached_item_);
|
||||
}
|
||||
|
||||
|
||||
|
@ -1,100 +0,0 @@
|
||||
/**
|
||||
* \file GraphicsSupport.C
|
||||
* This file is part of LyX, the document processor.
|
||||
* Licence details can be found in the file COPYING.
|
||||
*
|
||||
* \author Angus Leeming
|
||||
*
|
||||
* Full author contact details are available in file CREDITS
|
||||
*/
|
||||
|
||||
#include <config.h>
|
||||
|
||||
#include "GraphicsSupport.h"
|
||||
|
||||
#include "BufferView.h"
|
||||
#include "lyxtext.h"
|
||||
#include "lyxrow.h"
|
||||
#include "paragraph.h"
|
||||
#include "frontends/Painter.h"
|
||||
|
||||
|
||||
typedef std::list<VisibleParagraph> VPList;
|
||||
|
||||
|
||||
VPList const getVisibleParagraphs(BufferView const & bv)
|
||||
{
|
||||
// top_y is not const because it's reset by getRowNearY.
|
||||
int top_y = bv.text->first_y;
|
||||
Row const * row = bv.text->getRowNearY(top_y);
|
||||
|
||||
int const bv_height = bv.painter().paperHeight();
|
||||
|
||||
VPList vps;
|
||||
Row const * last_row = 0;
|
||||
|
||||
for (int height = 0; row && height < bv_height; row = row->next()) {
|
||||
height += row->height();
|
||||
|
||||
if (vps.empty() || vps.back().par != row->par()) {
|
||||
vps.push_back(VisibleParagraph(row->par(),
|
||||
row->pos(),
|
||||
row->par()->size()));
|
||||
}
|
||||
|
||||
last_row = row;
|
||||
}
|
||||
|
||||
// If the end of the final paragraph is not visble,
|
||||
// update vps.back().end
|
||||
if (last_row && last_row->next() &&
|
||||
last_row->par() == last_row->next()->par()) {
|
||||
vps.back().end = last_row->next()->pos();
|
||||
}
|
||||
|
||||
return vps;
|
||||
}
|
||||
|
||||
|
||||
namespace {
|
||||
|
||||
struct InsetVisibleInParagraph {
|
||||
InsetVisibleInParagraph(Inset const & inset) : inset_(inset) {}
|
||||
bool operator()(VisibleParagraph const & vp)
|
||||
{
|
||||
Paragraph * par = vp.par;
|
||||
InsetList::iterator it = par->insetlist.begin();
|
||||
InsetList::iterator end = par->insetlist.end();
|
||||
|
||||
// Can't refactor this as a functor because we rely on the
|
||||
// inset_iterator member function getPos().
|
||||
for (; it != end; ++it) {
|
||||
lyx::pos_type const pos = it.getPos();
|
||||
if (pos >= vp.start && pos <= vp.end) {
|
||||
if (it.getInset() == &inset_ ||
|
||||
it.getInset()->getInsetFromID(inset_.id()) != 0)
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private:
|
||||
Inset const & inset_;
|
||||
};
|
||||
|
||||
} // namespace anon
|
||||
|
||||
|
||||
bool isInsetVisible(Inset const & inset, VPList const & vps)
|
||||
{
|
||||
if (vps.empty())
|
||||
return false;
|
||||
|
||||
VPList::const_iterator it = vps.begin();
|
||||
VPList::const_iterator end = vps.end();
|
||||
|
||||
it = std::find_if(it, end, InsetVisibleInParagraph(inset));
|
||||
|
||||
return it != end;
|
||||
}
|
@ -1,48 +0,0 @@
|
||||
// -*- C++ -*-
|
||||
/**
|
||||
* \file GraphicsSupport.h
|
||||
* This file is part of LyX, the document processor.
|
||||
* Licence details can be found in the file COPYING.
|
||||
*
|
||||
* \author Angus Leeming
|
||||
*
|
||||
* Full author contact details are available in file CREDITS
|
||||
*/
|
||||
|
||||
#ifndef GRAPHICSSUPPORT_H
|
||||
#define GRAPHICSSUPPORT_H
|
||||
|
||||
#include "support/types.h"
|
||||
#include <list>
|
||||
|
||||
class BufferView;
|
||||
class Inset;
|
||||
class Paragraph;
|
||||
|
||||
/** A Paragraph * together with delimiters for the start and end positions
|
||||
of visibility.
|
||||
*/
|
||||
struct VisibleParagraph {
|
||||
///
|
||||
VisibleParagraph() : par(0), start(0), end(0) {}
|
||||
///
|
||||
VisibleParagraph(Paragraph * p, lyx::pos_type s, lyx::pos_type e)
|
||||
: par(p), start(s), end(e) {}
|
||||
///
|
||||
Paragraph * par;
|
||||
///
|
||||
lyx::pos_type start;
|
||||
///
|
||||
lyx::pos_type end;
|
||||
};
|
||||
|
||||
|
||||
/// Returns a list of all Paragraphs currently visible in bv.
|
||||
std::list<VisibleParagraph> const getVisibleParagraphs(BufferView const & bv);
|
||||
|
||||
/** Given this data, check whether inset lies within it and is, therefore,
|
||||
* visible.
|
||||
*/
|
||||
bool isInsetVisible(Inset const & inset, std::list<VisibleParagraph> const &);
|
||||
|
||||
#endif // GRAPHICSSUPPORT_H
|
116
src/graphics/LoaderQueue.C
Normal file
116
src/graphics/LoaderQueue.C
Normal file
@ -0,0 +1,116 @@
|
||||
/**
|
||||
* \file LoaderQueue.C
|
||||
* This file is part of LyX, the document processor.
|
||||
* Licence details can be found in the file COPYING.
|
||||
*
|
||||
* \author Alfredo Braunstein
|
||||
*
|
||||
* Full author contact details are available in file CREDITS
|
||||
*/
|
||||
|
||||
#include "LoaderQueue.h"
|
||||
|
||||
#include "debug.h"
|
||||
|
||||
#include <boost/bind.hpp>
|
||||
|
||||
using std::endl;
|
||||
using std::list;
|
||||
|
||||
|
||||
namespace grfx {
|
||||
|
||||
|
||||
LoaderQueue & LoaderQueue::get()
|
||||
{
|
||||
static LoaderQueue singleton;
|
||||
return singleton;
|
||||
}
|
||||
|
||||
|
||||
void LoaderQueue::loadNext()
|
||||
{
|
||||
emptyBucket();
|
||||
lyxerr[Debug::GRAPHICS] << "LoaderQueue: "
|
||||
<< cache_queue_.size()
|
||||
<< " items in the queue" << endl;
|
||||
int counter = 10;
|
||||
while (cache_queue_.size() && counter--) {
|
||||
if(cache_queue_.front()->status() == WaitingToLoad)
|
||||
cache_queue_.front()->startLoading();
|
||||
cache_set_.erase(cache_queue_.front());
|
||||
cache_queue_.pop_front();
|
||||
}
|
||||
if (cache_queue_.size() || bucket_.size()) {
|
||||
startLoader();
|
||||
} else {
|
||||
stopLoader();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
LoaderQueue::LoaderQueue() : timer(100, Timeout::ONETIME),
|
||||
running_(false)
|
||||
{
|
||||
timer.timeout.connect(boost::bind(&LoaderQueue::loadNext, this));
|
||||
}
|
||||
|
||||
|
||||
void LoaderQueue::emptyBucket()
|
||||
{
|
||||
lyxerr[Debug::GRAPHICS] << "LoaderQueue: emptying bucket"
|
||||
<< endl;
|
||||
while (! bucket_.empty()) {
|
||||
addToQueue(bucket_.front());
|
||||
bucket_.pop();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void LoaderQueue::startLoader()
|
||||
{
|
||||
lyxerr[Debug::GRAPHICS] << "LoaderQueue: waking up" << endl;
|
||||
running_ = true ;
|
||||
timer.start();
|
||||
}
|
||||
|
||||
|
||||
void LoaderQueue::stopLoader()
|
||||
{
|
||||
timer.stop();
|
||||
running_ = false ;
|
||||
lyxerr[Debug::GRAPHICS] << "LoaderQueue: I'm going to sleep" << endl;
|
||||
}
|
||||
|
||||
|
||||
bool LoaderQueue::running() const
|
||||
{
|
||||
return running_ ;
|
||||
}
|
||||
|
||||
|
||||
void LoaderQueue::touch(Cache::ItemPtr const & item)
|
||||
{
|
||||
if (! running_)
|
||||
startLoader();
|
||||
bucket_.push(item);
|
||||
}
|
||||
|
||||
|
||||
void LoaderQueue::addToQueue(Cache::ItemPtr const & item)
|
||||
{
|
||||
if (! cache_set_.insert(item).second) {
|
||||
list<Cache::ItemPtr>::iterator
|
||||
it = cache_queue_.begin();
|
||||
list<Cache::ItemPtr>::iterator
|
||||
end = cache_queue_.end();
|
||||
|
||||
it = std::find(it, end, item);
|
||||
if (it != end)
|
||||
cache_queue_.erase(it);
|
||||
}
|
||||
cache_queue_.push_front(item);
|
||||
}
|
||||
|
||||
|
||||
} // namespace grfx
|
69
src/graphics/LoaderQueue.h
Normal file
69
src/graphics/LoaderQueue.h
Normal file
@ -0,0 +1,69 @@
|
||||
// -*- C++ -*-
|
||||
/**
|
||||
* \file LoaderQueue.h
|
||||
* This file is part of LyX, the document processor.
|
||||
* Licence details can be found in the file COPYING.
|
||||
*
|
||||
* \author Alfredo Braunstein
|
||||
*
|
||||
* Full author contact details are available in file CREDITS.
|
||||
*
|
||||
* This implements a threaded service queue which loads images on background.
|
||||
* In order to request an image loading you call touch() with the pointer to
|
||||
* the cached image. Then it will try to satisfy the request as soon as
|
||||
* posible (that's it: after finishing an eventual loading on progress)
|
||||
* touch() returns inmediately, in order not tu disrupt the flow of the main
|
||||
* thread.
|
||||
* The service thread is the method loadNext(). It's actually not a thread,
|
||||
* but implemented with a timer that comes back every x msec.
|
||||
*/
|
||||
|
||||
#ifndef LOADERQUEUE_H
|
||||
#define LOADERQUEUE_H
|
||||
|
||||
#include "GraphicsCache.h"
|
||||
#include "GraphicsCacheItem.h"
|
||||
|
||||
#include "frontends/Timeout.h"
|
||||
|
||||
#include <set>
|
||||
#include <queue>
|
||||
|
||||
namespace grfx {
|
||||
|
||||
class LoaderQueue {
|
||||
public:
|
||||
//use this to request a loading
|
||||
void touch(Cache::ItemPtr const & item);
|
||||
//query if the clock is ticking
|
||||
bool running() const;
|
||||
//get the and only instance of the class
|
||||
static LoaderQueue & get();
|
||||
private:
|
||||
//this class is a singleton class... use LoaderQueue::get() instead
|
||||
LoaderQueue();
|
||||
//in-progress loading queue (elements are unique here)
|
||||
std::list<Cache::ItemPtr> cache_queue_;
|
||||
//makes faster the insertion of new elements
|
||||
std::set<Cache::ItemPtr> cache_set_;
|
||||
//newly touched element go here, loadNext move them to cache_queue_
|
||||
std::queue<Cache::ItemPtr> bucket_;
|
||||
//
|
||||
Timeout timer;
|
||||
//
|
||||
bool running_;
|
||||
//moves bucket_ to cache_queue_
|
||||
void emptyBucket();
|
||||
//adds or reprioritizes one element in cache_queue_
|
||||
void addToQueue(Cache::ItemPtr const & item);
|
||||
//this is the 'threaded' method, that does the loading in background
|
||||
void loadNext();
|
||||
//
|
||||
void startLoader();
|
||||
//
|
||||
void stopLoader();
|
||||
};
|
||||
|
||||
} // namespace grfx
|
||||
|
||||
#endif // LOADERQUEUE_H
|
@ -17,8 +17,8 @@ libgraphics_la_SOURCES = \
|
||||
GraphicsLoader.C \
|
||||
GraphicsParams.C \
|
||||
GraphicsParams.h \
|
||||
GraphicsSupport.h \
|
||||
GraphicsSupport.C \
|
||||
LoaderQueue.h \
|
||||
LoaderQueue.C \
|
||||
GraphicsTypes.h \
|
||||
GraphicsTypes.C \
|
||||
PreviewImage.h \
|
||||
|
Loading…
Reference in New Issue
Block a user