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