2 * \file GraphicsCacheItem.C
3 * Copyright 2002 the LyX Team
4 * Read the file COPYING
6 * \author Baruch Even <baruch.even@writeme.com>
7 * \author Herbert Voss <voss@lyx.org>
8 * \author Angus Leeming <a.leeming@ic.ac.uk>
14 #pragma implementation
17 #include "graphics/GraphicsCacheItem.h"
18 #include "graphics/GraphicsImage.h"
19 #include "graphics/GraphicsConverter.h"
23 #include "support/LAssert.h"
24 #include "support/filetools.h"
26 #include <boost/bind.hpp>
33 GCacheItem::GCacheItem(string const & file)
34 : filename_(file), zipped_(false),
35 remove_loaded_file_(false), status_(WaitingToLoad)
39 void GCacheItem::startLoading()
41 if (status() != WaitingToLoad)
44 convertToDisplayFormat();
48 void GCacheItem::setStatus(ImageStatus new_status)
50 if (status_ == new_status)
58 void GCacheItem::imageConverted(string const & file_to_load)
61 (!file_to_load.empty() && IsFileReadable(file_to_load));
63 string const text = success ? "succeeded" : "failed";
64 lyxerr[Debug::GRAPHICS] << "Image conversion " << text << "." << endl;
67 setStatus(ErrorConverting);
70 lyx::unlink(unzipped_filename_);
77 // Do the actual image loading from file to memory.
78 file_to_load_ = file_to_load;
84 // This function gets called from the callback after the image has been
85 // converted successfully.
86 void GCacheItem::loadImage()
89 lyxerr[Debug::GRAPHICS] << "Loading image." << endl;
91 // Connect a signal to this->imageLoaded and pass this signal to
93 SignalLoadTypePtr on_finish;
94 on_finish.reset(new SignalLoadType);
95 cl_ = on_finish->connect(boost::bind(&GCacheItem::imageLoaded, this, _1));
97 image_ = GImage::newImage();
98 image_->load(file_to_load_, on_finish);
102 void GCacheItem::imageLoaded(bool success)
104 string const text = success ? "succeeded" : "failed";
105 lyxerr[Debug::GRAPHICS] << "Image loading " << text << "." << endl;
107 // Clean up after loading.
109 lyx::unlink(unzipped_filename_);
111 if (remove_loaded_file_ && unzipped_filename_ != file_to_load_)
112 lyx::unlink(file_to_load_);
117 setStatus(ErrorLoading);
127 string const findTargetFormat(string const & from)
129 typedef GImage::FormatList FormatList;
130 FormatList const formats = GImage::loadableFormats();
132 // There must be a format to load from.
133 lyx::Assert(!formats.empty());
135 // First ascertain if we can load directly with no conversion
136 FormatList::const_iterator it1 = formats.begin();
137 FormatList::const_iterator end = formats.end();
138 for (; it1 != end; ++it1) {
143 // So, we have to convert to a loadable format. Can we?
144 grfx::GConverter const & graphics_converter = grfx::GConverter::get();
146 FormatList::const_iterator it2 = formats.begin();
147 for (; it2 != end; ++it2) {
148 if (graphics_converter.isReachable(from, *it2))
152 // Failed! so we have to try to convert it to XPM format
153 // with the standard converter
154 return string("xpm");
160 void GCacheItem::convertToDisplayFormat()
162 setStatus(Converting);
163 // Make a local copy in case we unzip it
164 string const filename = zippedFile(filename_) ?
165 unzipFile(filename_) : filename_;
166 string const displayed_filename = MakeDisplayPath(filename_);
167 lyxerr[Debug::GRAPHICS] << "[GrahicsCacheItem::convertToDisplayFormat]\n"
168 << "\tAttempting to convert image file: " << filename
169 << "\n\twith displayed filename: " << displayed_filename
172 // First, check that the file exists!
173 if (!IsFileReadable(filename)) {
174 setStatus(ErrorNoFile);
175 lyxerr[Debug::GRAPHICS] << "\tThe file is not readable" << endl;
179 string from = getExtFromContents(filename);
180 // Some old ps-files make problems, so we do not need direct
181 // loading of an ps-file
183 lyxerr[Debug::GRAPHICS]
184 << "\n\tThe file contains PostScript format data.\n"
185 << "\tchanging it to eps-format to get it converted to xpm\n";
188 lyxerr[Debug::GRAPHICS]
189 << "\n\tThe file contains " << from << " format data." << endl;
190 string const to = grfx::findTargetFormat(from);
193 // No conversion needed!
194 lyxerr[Debug::GRAPHICS] << "\tNo conversion needed (from == to)!" << endl;
195 file_to_load_ = filename;
200 lyxerr[Debug::GRAPHICS] << "\tConverting it to " << to << " format." << endl;
201 // Take only the filename part of the file, without path or extension.
202 string const temp = ChangeExtension(OnlyFilename(filename), string());
204 // Add some stuff to create a uniquely named temporary file.
205 // This file is deleted in loadImage after it is loaded into memory.
206 string const to_file_base = lyx::tempName(string(), temp);
207 remove_loaded_file_ = true;
209 // Remove the temp file, we only want the name...
210 lyx::unlink(to_file_base);
212 // Connect a signal to this->imageConverted and pass this signal to
213 // the graphics converter so that we can load the modified file
214 // on completion of the conversion process.
215 SignalConvertTypePtr on_finish;
216 on_finish.reset(new SignalConvertType);
217 cc_ = on_finish->connect(boost::bind(&GCacheItem::imageConverted, this, _1));
219 GConverter & graphics_converter = GConverter::get();
220 graphics_converter.convert(filename, to_file_base, from, to, on_finish);