]> git.lyx.org Git - lyx.git/blob - src/graphics/GraphicsLoader.C
Strip redundant #includes.
[lyx.git] / src / graphics / GraphicsLoader.C
1 /**
2  * \file GraphicsLoader.C
3  * This file is part of LyX, the document processor.
4  * Licence details can be found in the file COPYING.
5  *
6  * \author Angus Leeming
7  *
8  * Full author contact details are available in file CREDITS.
9  */
10
11 #include <config.h>
12
13 #include "GraphicsLoader.h"
14
15 #include "GraphicsCacheItem.h"
16 #include "GraphicsImage.h"
17 #include "GraphicsParams.h"
18 #include "LoaderQueue.h"
19
20 #include <boost/bind.hpp>
21
22
23 namespace lyx {
24 namespace graphics {
25
26 struct Loader::Impl : boost::signals::trackable {
27         ///
28         Impl();
29         ///
30         ~Impl();
31         ///
32         void resetFile(string const &);
33         ///
34         void resetParams(Params const &);
35         ///
36         void createPixmap();
37         ///
38         void startLoading();
39         ///
40         Params const & params() const { return params_; }
41
42         /// The loading status of the image.
43         ImageStatus status_;
44         /** Must store a copy of the cached item to ensure that it is not
45          *  erased unexpectedly by the cache itself.
46          */
47         Cache::ItemPtr cached_item_;
48         /// We modify a local copy of the image once it is loaded.
49         Image::ImagePtr image_;
50         /// This signal is emitted when the image loading status changes.
51         boost::signal0<void> signal_;
52
53 private:
54         ///
55         void statusChanged();
56         ///
57         void checkedLoading();
58
59         ///
60         Params params_;
61 };
62
63
64 Loader::Loader()
65         : pimpl_(new Impl)
66 {}
67
68
69 Loader::Loader(string const & file, DisplayType type)
70         : pimpl_(new Impl)
71 {
72         reset(file, type);
73 }
74
75
76 Loader::Loader(string const & file, Params const & params)
77         : pimpl_(new Impl)
78 {
79         reset(file, params);
80 }
81
82
83 Loader::Loader(Loader const & other)
84         : pimpl_(new Impl)
85 {
86         Params const & params = other.pimpl_->params();
87         reset(params.filename, params);
88 }
89
90
91 Loader::~Loader()
92 {}
93
94
95 Loader & Loader::operator=(Loader const & other)
96 {
97         if (this != &other) {
98                 Params const & params = other.pimpl_->params();
99                 reset(params.filename, params);
100         }
101         return *this;
102 }
103
104
105 void Loader::reset(string const & file, DisplayType type) const
106 {
107         Params params;
108         params.display = type;
109         pimpl_->resetParams(params);
110
111         pimpl_->resetFile(file);
112         pimpl_->createPixmap();
113 }
114
115
116 void Loader::reset(string const & file, Params const & params) const
117 {
118         pimpl_->resetParams(params);
119         pimpl_->resetFile(file);
120         pimpl_->createPixmap();
121 }
122
123
124 void Loader::reset(Params const & params) const
125 {
126         pimpl_->resetParams(params);
127         pimpl_->createPixmap();
128 }
129
130
131 void Loader::startLoading() const
132 {
133         if (pimpl_->status_ != WaitingToLoad || !pimpl_->cached_item_.get())
134                 return;
135         pimpl_->startLoading();
136 }
137
138
139 void Loader::startMonitoring() const
140 {
141         if (!pimpl_->cached_item_.get())
142                 return;
143
144         pimpl_->cached_item_->startMonitoring();
145 }
146
147
148 bool Loader::monitoring() const
149 {
150         if (!pimpl_->cached_item_.get())
151                 return false;
152
153         return pimpl_->cached_item_->monitoring();
154 }
155
156
157 unsigned long Loader::checksum() const
158 {
159         if (!pimpl_->cached_item_.get())
160                 return 0;
161
162         return pimpl_->cached_item_->checksum();
163 }
164
165
166 string const & Loader::filename() const
167 {
168         static string const empty;
169         return pimpl_->cached_item_.get() ?
170                 pimpl_->cached_item_->filename() : empty;
171 }
172
173
174 ImageStatus Loader::status() const
175 {
176         return pimpl_->status_;
177 }
178
179
180 boost::signals::connection Loader::connect(slot_type const & slot) const
181 {
182         return pimpl_->signal_.connect(slot);
183 }
184
185
186 Image const * Loader::image() const
187 {
188         return pimpl_->image_.get();
189 }
190
191
192 Loader::Impl::Impl()
193         : status_(WaitingToLoad)
194 {
195 }
196
197
198 Loader::Impl::~Impl()
199 {
200         resetFile(string());
201 }
202
203
204 void Loader::Impl::resetFile(string const & file)
205 {
206         string const old_file = cached_item_.get() ?
207                 cached_item_->filename() : string();
208
209         if (file == old_file)
210                 return;
211
212         // If monitoring() the current file, should continue to monitor the
213         // new file.
214         bool continue_monitoring = false;
215
216         if (!old_file.empty()) {
217                 continue_monitoring = cached_item_->monitoring();
218                 cached_item_.reset();
219                 Cache::get().remove(old_file);
220         }
221
222         status_ = cached_item_.get() ? cached_item_->status() : WaitingToLoad;
223         image_.reset();
224
225         if (cached_item_.get() || file.empty())
226                 return;
227
228         Cache & gc = Cache::get();
229         if (!gc.inCache(file))
230                 gc.add(file);
231
232         // We /must/ make a local copy of this.
233         cached_item_ = gc.item(file);
234         status_ = cached_item_->status();
235
236         if (continue_monitoring && !cached_item_->monitoring())
237                 cached_item_->startMonitoring();
238
239         cached_item_->connect(boost::bind(&Impl::statusChanged, this));
240 }
241
242
243 void Loader::Impl::resetParams(Params const & params)
244 {
245         if (params == params_)
246                 return;
247
248         params_ = params;
249         status_ = cached_item_.get() ? cached_item_->status() : WaitingToLoad;
250         image_.reset();
251 }
252
253
254 void Loader::Impl::statusChanged()
255 {
256         status_ = cached_item_.get() ? cached_item_->status() : WaitingToLoad;
257         createPixmap();
258         signal_();
259 }
260
261
262 void Loader::Impl::createPixmap()
263 {
264         if (!cached_item_.get() ||
265             params_.display == NoDisplay || status_ != Loaded)
266                 return;
267
268         image_.reset(cached_item_->image()->clone());
269
270         // These do nothing if there's nothing to do
271         image_->clip(params_);
272         image_->rotate(params_);
273         image_->scale(params_);
274
275         bool const success = image_->setPixmap(params_);
276
277         if (success) {
278                 status_ = Ready;
279         } else {
280                 image_.reset();
281                 status_ = ErrorGeneratingPixmap;
282         }
283 }
284
285 void Loader::Impl::startLoading()
286 {
287         if (status_ != WaitingToLoad)
288                 return;
289
290         LoaderQueue::get().touch(cached_item_);
291 }
292
293
294 } // namespace graphics
295 } // namespace lyx