]> git.lyx.org Git - lyx.git/blob - src/insets/insetgraphics.C
2285db34e011e4863c522576c0d072df13b214f8
[lyx.git] / src / insets / insetgraphics.C
1 /* This file is part of
2  * ====================================================== 
3  * 
4  *           LyX, The Document Processor
5  *       
6  *           Copyright 1995-2001 the LyX Team.
7  *           
8  *           This file Copyright 2000 Baruch Even.
9  * ====================================================== */
10
11 /*
12 Major tasks:
13         * Switch to convert the images in the background, this requires work on
14                 the converter, the systemcontroller and the graphics cache.
15
16 Minor tasks:
17     * Pop up a dialog if the widget version is higher than what we accept.
18         * Provide sed/awk/C code to downgrade from InsetGraphics to FigInset(?)
19         
20 */
21
22 /*
23 Known BUGS:
24     
25     * If the image is from the clipart, and the document is moved to another
26        directory, the user is screwed. Need a way to handle it.
27        This amounts to a problem of when to use relative or absolute file paths
28        We should probably use what the user asks to use... but when he chooses
29        by the file dialog we normally get an absolute path and this may not be 
30        what the user meant.
31     * Bug in FileDlg class (src/filedlg.[hC]) when selecting a file and then
32         pressing ok, it counts as if no real selection done. Apparently
33         when choosing a file it doesn't update the select file input line.
34                 
35         * If we are trying to create a file in a read-only directory and there
36                 are graphics that need converting, the converting will fail because
37                 it is done in-place, into the same directory as the original image.
38                 This needs to be fixed in the src/converter.C file
39                 [ This is presumed to be fixed, needs testing.]
40
41         * We do not dither or resize the image in a WYSIWYM way, we load it at
42                 its original size and color, resizing is done in the final output,
43                 but not in the LyX window.
44
45         * The scale option is only handled for the horizontal part, the vertical
46                 part will not work. For now it is also shown only for horizontal
47                 resizing on the form.
48
49         * EPS figures are not fully detected, they may have a lot of possible
50                 suffixes so we need to read the file and detect if it's EPS or not.
51                 [Implemented, need testing]
52                 
53 TODO Before initial production release:
54     * Replace insetfig everywhere
55         * Search for comments of the form
56             // INSET_GRAPHICS: remove this when InsetFig is thrown.
57           And act upon them. Make sure not to remove InsetFig code for the 
58                   1.2.0 release, only afterwards, after deployment shows InsetGraphics
59                   to be ok.
60  
61 TODO Extended features:
62  
63     * Advanced Latex tab folder.
64     * Add support for more features so that it will be better than insetfig.
65         * Keep aspect ratio radio button
66         * Support for complete control over the latex parameters for TeXperts
67         * What advanced features the users want to do?
68             Implement them in a non latex dependent way, but a logical way.
69             LyX should translate it to latex or any other fitting format.
70     * Add a way to roll the image file into the file format.
71     * When loading, if the image is not found in the expected place, try
72        to find it in the clipart, or in the same directory with the image.
73     * Keep a tab on the image file, if it changes, update the lyx view.
74         * The image choosing dialog could show thumbnails of the image formats
75                 it knows of, thus selection based on the image instead of based on
76                 filename.
77         * Add support for the 'picins' package.
78         * Add support for the 'picinpar' package.
79         * Improve support for 'subfigure' - Allow to set the various options
80                 that are possible.
81         * Add resizing by percentage of image size (50%, 150%) - usefull for two
82                 images of different size to be resized where they both should have
83                 the same scale compared to each other.
84  */
85
86 /* NOTES:
87  *
88  * Intentions:
89  *  This is currently a moving target, I'm trying stuff and learning what
90  *  is needed and how to accomplish it, since there is no predefined goal or
91  *  way to go I invent it as I go.
92  *
93  *  My current intention is for seperation from LaTeX, the basic needs are 
94  *  resizing and rotating, displaying on screen in various depths and printing
95  *  conversion of depths (independent of the display depth). For this I'll 
96  *  provide a simple interface.
97  *
98  *  The medium level includes clipping of the image, but in a limited way.
99  *
100  *  For the LaTeX gurus I'll provide a complete control over the output, but
101  *  this is latex dependent and guru dependent so I'd rather avoid doing this
102  *  for the normal user. This stuff includes clipping, special image size
103  *  specifications (\textwidth\minus 2in) which I see no way to generalize
104  *  to non-latex specific way.
105  *
106  * Used packages:
107  *  'graphicx' for the graphics inclusion.
108  *  'subfigure' for the subfigures.
109  *
110  * Fileformat:
111  *
112  * Current version is 1 (inset file format version), when changing it
113  * it should be changed in the Write() function when writing in one place
114  * and when reading one should change the version check and the error message.
115  *
116  * The filename is kept in  the lyx file in a relative way, so as to allow
117  * moving the document file and its images with no problem.
118  *
119  * Conversions:
120  *   Postscript output means EPS figures.
121  *
122  *   PDF output is best done with PDF figures if it's a direct conversion
123  *   or PNG figures otherwise.
124  *      Image format
125  *      from        to
126  *      EPS         epstopdf
127  *      JPG/PNG     direct
128  *      PDF         direct
129  *      others      PNG
130  */
131
132 #include <config.h> 
133
134 #ifdef __GNUG__
135 #pragma implementation
136 #endif 
137
138 #include "insets/insetgraphics.h"
139 #include "insets/insetgraphicsParams.h"
140 #include "graphics/GraphicsCache.h"
141 #include "graphics/GraphicsCacheItem.h"
142
143 #include "frontends/Dialogs.h"
144 #include "LyXView.h"
145 #include "buffer.h"
146 #include "BufferView.h"
147 #include "converter.h"
148 #include "frontends/support/LyXImage.h"
149 #include "Painter.h"
150 #include "lyx_gui_misc.h"
151 #include "support/FileInfo.h"
152 #include "support/filetools.h"
153 #include "support/lyxlib.h"
154 #include "lyxtext.h"
155 #include "lyxrc.h"
156 #include "font.h" // For the lyxfont class.
157 #include "fstream" // for ifstream in isEPS
158 #include <algorithm> // For the std::max
159 #include "support/lyxmanip.h"
160 #include "debug.h"
161 #include "gettext.h"
162
163 extern string system_tempdir;
164
165 using std::ifstream;
166 using std::ostream;
167 using std::endl;
168
169
170 // This function is a utility function
171 inline
172 string const RemoveExtension(string const & filename)
173 {
174         return ChangeExtension(filename, string());
175 }
176
177
178 // Initialize only those variables that do not have a constructor.
179 InsetGraphics::InsetGraphics()
180         : cacheHandle(0), imageLoaded(false)
181 {}
182
183
184 InsetGraphics::InsetGraphics(InsetGraphics const & ig, bool same_id)
185         : Inset(), SigC::Object()
186         , cacheHandle(ig.cacheHandle)
187         , imageLoaded(ig.imageLoaded)
188 {
189         setParams(ig.getParams());
190         if (same_id)
191                 id_ = ig.id_;
192 }
193
194
195 InsetGraphics::~InsetGraphics()
196 {
197         // Emits the hide signal to the dialog connected (if any)
198         hideDialog();
199 }
200
201
202 string const
203 InsetGraphics::statusMessage() const
204 {
205         string msg;
206
207         if (cacheHandle.get()) {
208                 switch (cacheHandle->getImageStatus()) {
209                 case GraphicsCacheItem::UnknownError:
210                         msg = _("Unknown Error");
211                         break;
212
213                 case GraphicsCacheItem::Loading:
214                         msg = _("Loading...");
215                         break;
216
217                 case GraphicsCacheItem::ErrorReading:
218                         msg = _("Error reading");
219                         break;
220
221                 case GraphicsCacheItem::ErrorConverting:
222                         msg = _("Error converting");
223                         break;
224
225                 case GraphicsCacheItem::Loaded:
226                         // No message to write.
227                         break;
228                 }
229         }
230
231         return msg;
232 }
233
234
235 int InsetGraphics::ascent(BufferView *, LyXFont const &) const
236 {
237         LyXImage * pixmap = 0;
238         if (cacheHandle.get() && (pixmap = cacheHandle->getImage()))
239                 return pixmap->getHeight();
240         else
241                 return 50;
242 }
243
244
245 int InsetGraphics::descent(BufferView *, LyXFont const &) const
246 {
247         // this is not true if viewport is used and clip is not.
248         return 0;
249 }
250
251
252 int InsetGraphics::width(BufferView *, LyXFont const & font) const
253 {
254         LyXImage * pixmap = 0;
255         
256         if (cacheHandle.get() && (pixmap = cacheHandle->getImage()))
257                 return pixmap->getWidth();
258         else {
259                 string const msg = statusMessage();
260                 int font_width = 0;
261                 
262                 if (!msg.empty())
263                         font_width = lyxfont::width(msg, font);
264                 
265                 return std::max(50, font_width + 15);
266         }
267 }
268
269
270 void InsetGraphics::draw(BufferView * bv, LyXFont const & font,
271                          int baseline, float & x, bool) const
272 {
273         Painter & paint = bv->painter();
274
275         int ldescent = descent(bv, font);
276         int lascent = ascent(bv, font);
277         int lwidth = width(bv, font);
278
279         // Make sure x is updated upon exit from this routine
280         int old_x = int(x);
281         x += lwidth;
282
283         // This will draw the graphics. If the graphics has not been loaded yet,
284         // we draw just a rectangle.
285         if (imageLoaded) {
286
287                 // Draw a ractangle with the specified color. If the image is
288                 // transparent, this will shine through.
289                 paint.fillRectangle(old_x + 2, baseline - lascent,
290                                     lwidth - 4, lascent + ldescent,
291                                     LColor::graphicsbg);
292
293                 paint.image(old_x + 2, baseline - lascent,
294                             lwidth - 4, lascent + ldescent,
295                             cacheHandle->getImage());
296         } else {
297                 
298                 // Get the image status, default to unknown error.
299                 GraphicsCacheItem::ImageStatus status = GraphicsCacheItem::UnknownError;
300                 if (cacheHandle.get())
301                         status = cacheHandle->getImageStatus();
302                 
303                 // Check if the image is now ready.
304                 if (status == GraphicsCacheItem::Loaded) {
305                         imageLoaded = true;
306
307                         // Tell BufferView we need to be updated!
308                         bv->text->status(bv, LyXText::CHANGED_IN_DRAW);
309                         return;
310                 }
311
312                 
313                 paint.rectangle(old_x + 2, baseline - lascent,
314                                 lwidth - 4,
315                                 lascent + ldescent);
316
317                 string const msg = statusMessage();
318                 if (!msg.empty()) {
319                         // Print the message.
320                         LyXFont msgFont(font);
321                         msgFont.setFamily(LyXFont::SANS_FAMILY);
322                         msgFont.setSize(LyXFont::SIZE_FOOTNOTE);
323                         string const justname = OnlyFilename (params.filename);
324                         paint.text(old_x + 8, 
325                                    baseline - lyxfont::maxAscent(msgFont) - 4,
326                                    justname, msgFont);
327
328                         msgFont.setSize(LyXFont::SIZE_TINY);
329                         paint.text(old_x + 8, baseline - 4, msg, msgFont);
330                 }
331         }
332 }
333
334
335 void InsetGraphics::edit(BufferView *bv, int, int, unsigned int)
336 {
337         bv->owner()->getDialogs()->showGraphics(this);
338 }
339
340
341 void InsetGraphics::edit(BufferView * bv, bool)
342 {
343         edit(bv, 0, 0, 0);
344 }
345
346
347 Inset::EDITABLE InsetGraphics::editable() const
348 {
349         return IS_EDITABLE;
350 }
351
352
353 void InsetGraphics::write(Buffer const * buf, ostream & os) const
354 {
355         os << "Graphics FormatVersion 1\n";
356
357         params.Write(buf, os);
358 }
359
360
361 void InsetGraphics::read(Buffer const * buf, LyXLex & lex)
362 {
363         string const token = lex.getString();
364
365         if (token == "Graphics")
366                 readInsetGraphics(buf, lex);
367         else if (token == "Figure") // Compatibility reading of FigInset figures.
368                 readFigInset(buf, lex);
369         else
370                 lyxerr[Debug::INFO] << "Not a Graphics or Figure inset!\n";
371
372         updateInset();
373 }
374
375 void InsetGraphics::readInsetGraphics(Buffer const * buf, LyXLex & lex)
376 {
377         bool finished = false;
378
379         while (lex.isOK() && !finished) {
380                 lex.next();
381
382                 string const token = lex.getString();
383                 lyxerr[Debug::INFO] << "Token: '" << token << '\'' 
384                                     << std::endl;
385
386                 if (token.empty()) {
387                         continue;
388                 } else if (token == "\\end_inset") {
389                         finished = true;
390                 } else if (token == "FormatVersion") {
391                         lex.next();
392                         int version = lex.getInteger();
393                         if (version > 1)
394                                 lyxerr
395                                 << "This document was created with a newer Graphics widget"
396                                 ", You should use a newer version of LyX to read this"
397                                 " file."
398                                 << std::endl;
399                         // TODO: Possibly open up a dialog?
400                 }
401                 else {
402                         if (! params.Read(buf, lex, token))
403                                 lyxerr << "Unknown token, " << token << ", skipping." 
404                                         << std::endl;
405                 }
406         }
407 }
408
409
410 void InsetGraphics::readFigInset(Buffer const * buf, LyXLex & lex)
411 {
412         bool finished = false;
413         
414         while (lex.isOK() && !finished) {
415                 lex.next();
416
417                 string const token = lex.getString();
418                 lyxerr[Debug::INFO] << "Token: " << token << endl;
419                 
420                 if (token.empty())
421                         continue;
422                 else if (token == "\\end_inset") {
423                         finished = true;
424                 } else if (token == "file") {
425                         if (lex.next()) {
426                                 string const name = lex.getString();
427                                 string const path = OnlyPath(buf->fileName());
428                                 params.filename = MakeAbsPath(name, path);
429                         }
430                 } else if (token == "extra") {
431                         if (lex.next());
432                         // kept for backwards compability. Delete in 0.13.x
433                 } else if (token == "subcaption") {
434                         if (lex.eatLine())
435                                 params.subcaptionText = lex.getString();
436                 } else if (token == "label") {
437                         if (lex.next());
438                         // kept for backwards compability. Delete in 0.13.x
439                 } else if (token == "angle") {
440                         if (lex.next())
441                                 params.rotateAngle = lex.getFloat();
442                 } else if (token == "size") {
443                         // Size of image on screen is ignored in InsetGraphics, just eat
444                         // the input.
445                         if (lex.next()) {
446                                 lex.getInteger();
447                         }
448                         if (lex.next()) {
449                                 lex.getInteger();
450                         }
451                 } else if (token == "flags") {
452                         InsetGraphicsParams::DisplayType tmp = InsetGraphicsParams::COLOR;
453                         if (lex.next())
454                                 switch (lex.getInteger()) {
455                                 case 1: tmp = InsetGraphicsParams::MONOCHROME; break;
456                                 case 2: tmp = InsetGraphicsParams::GRAYSCALE; break;
457                                 }
458                         params.display = tmp;
459                 } else if (token == "subfigure") {
460                         params.subcaption = true;
461                 } else if (token == "width") {
462                         if (lex.next()) {
463                                 params.widthResize = static_cast<InsetGraphicsParams::Resize>(lex.getInteger());
464                         }
465                         if (lex.next()) {
466                                 params.widthSize = lex.getFloat();
467                         }
468                 } else if (token == "height") {
469                         if (lex.next()) {
470                                 params.heightResize = static_cast<InsetGraphicsParams::Resize>(lex.getInteger());
471                         }
472                         if (lex.next()) {
473                                 params.heightSize = lex.getFloat();
474                         }
475                 }
476         }
477 }
478
479
480 namespace {
481
482 void formatResize(ostream & os, string const & key,
483                   InsetGraphicsParams::Resize resizeType, double size)
484 {
485         switch (resizeType) {
486         case InsetGraphicsParams::DEFAULT_SIZE:
487                 break;
488
489         case InsetGraphicsParams::CM:
490                 os << key << '=' << size << "cm,";
491                 break;
492
493         case InsetGraphicsParams::INCH:
494                 os << key << '=' << size << "in,";
495                 break;
496
497         case InsetGraphicsParams::PERCENT_PAGE:
498                 os << key << '=' << size / 100 << "\\text" << key << ',';
499                 break;
500
501         case InsetGraphicsParams::PERCENT_COLUMN:
502                 os << key << '=' << size / 100 << "\\column" << key << ',';
503                 break;
504
505         case InsetGraphicsParams::SCALE:
506                 os << "scale" << '=' << size << ',';
507         }
508 }
509
510 } // namespace anon
511
512
513 string const
514 InsetGraphics::createLatexOptions() const
515 {
516         // Calculate the options part of the command, we must do it to a string
517         // stream since we might have a trailing comma that we would like to remove
518         // before writing it to the output stream.
519         ostringstream options;
520
521         formatResize(options, "width", params.widthResize, params.widthSize);
522         formatResize(options, "height", params.heightResize, params.heightSize);
523
524         // Make sure it's not very close to zero, a float can be effectively
525         // zero but not exactly zero.
526         if (lyx::float_equal(params.rotateAngle, 0, 0.001)) {
527                 options << "angle="
528                         << params.rotateAngle << ',';
529         }
530
531         string opts = options.str().c_str();
532         opts = strip(opts, ',');
533
534         return opts;
535 }
536
537 namespace {
538
539 enum FileType {
540         EPS,
541         PNG,
542         JPEG,
543         GIF,
544         PDF,
545         UNKNOWN
546 };
547
548 bool isEPS(string const & filename)
549 {
550         if (filename.empty() || !IsFileReadable(filename)) return false;
551
552         ifstream ifs(filename.c_str());
553
554         if (!ifs) return false; // Couldn't open file...
555
556         bool is_eps = false; // Have we recognized the file as EPS?
557         string to_find = "%!PS-Adobe-"; // The string we use to recognize
558         int const max_attempts = 500; // Maximum strings to read to attempt recognition
559         int count = 0; // Counter of attempts.
560         string str;
561         for (; count < max_attempts; ++count) {
562                 if (ifs.eof()) {
563                         lyxerr[Debug::INFO] << "InsetGraphics (isEPS)"
564                                 " End of file reached and it wasn't found to be EPS!" << endl;
565                         break;
566                 }
567
568                 ifs >> str;
569                 if (str.find(to_find)) {
570                         is_eps = true;
571                         break;
572                 }
573         }
574
575         return is_eps;
576 }
577
578 enum FileType classifyFileType(string const & filename, string const & suffix)
579 {
580         if (suffix == "png")
581                 return PNG;
582         else if (suffix == "jpg" || suffix == "jpeg")
583                 return JPEG;
584         else if (suffix == "gif")
585                 return GIF;
586         else if (suffix == "pdf")
587                 return PDF;
588         else if (isEPS(filename))
589                 return EPS;
590
591         return UNKNOWN;
592 }
593
594 string decideOutputImageFormat(string const & suffix, enum FileType type)
595 {
596         // lyxrc.pdf_mode means:
597         // Are we creating a PDF or a PS file?
598         // (Should actually mean, are we using latex or pdflatex).
599         
600         if (lyxrc.pdf_mode) {
601                 if (type == EPS || type == EPS || type == PDF)
602                         return "pdf";
603                 else if (type == JPEG)
604                         return suffix;
605                 else
606                         return "png";
607         }
608
609         // If it's postscript, we always do eps.
610         // There are many suffixes that are actually EPS (ask Garst for example)
611         // so we detect if it's an EPS by looking in the file, if it is, we return
612         // the same suffix of the file so it won't be converted.
613         if (type == EPS)
614                 return suffix;
615         
616         return "eps";
617 }
618
619 } // Anon. namespace
620
621 string const 
622 InsetGraphics::prepareFile(Buffer const *buf) const
623 {
624
625         // do_convert = Do we need to convert the file?
626         // nice = Do we create a nice version?
627         //        This is used when exporting the latex file only.
628         // 
629         // 
630         // if (!do_convert)
631         //   return original filename
632         // 
633         // if (!nice)
634         //   convert_place = temp directory
635         //   return new filename in temp directory
636         // else
637         //   convert_place = original file directory
638         //   return original filename without the extension
639         //
640         
641         // Get the extension (format) of the original file.
642         string const extension = GetExtension(params.filename);
643         FileType type = classifyFileType(params.filename, extension);
644         
645         // Are we creating a PDF or a PS file?
646         // (Should actually mean, are we usind latex or pdflatex).
647         string const image_target = decideOutputImageFormat(extension, type);
648
649         if (extension == image_target)
650                 return params.filename;
651
652         string outfile;
653         if (!buf->niceFile) {
654                 string const temp = AddName(buf->tmppath, params.filename);
655                 outfile = RemoveExtension(temp);
656                 
657                 //lyxerr << "buf::tmppath = " << buf->tmppath << "\n";
658                 //lyxerr << "filename = " << params.filename << "\n";
659                 //lyxerr << "temp = " << temp << "\n";
660                 //lyxerr << "outfile = " << outfile << endl;
661         } else {
662                 string const path = OnlyPath(buf->fileName());
663                 string const relname = MakeRelPath(params.filename, path);
664                 outfile = RemoveExtension(relname);
665         }
666
667         converters.convert(buf, params.filename, outfile, extension, image_target);
668         
669         return outfile;
670 }
671
672
673 int InsetGraphics::latex(Buffer const *buf, ostream & os,
674                          bool /*fragile*/, bool/*fs*/) const
675 {
676         // MISSING: We have to decide how to do the order of the options
677         // that is dependent of order, like width, height, angle. Should
678         // we rotate before scale? Should we let the user decide?
679         // bool rot_before_scale; ?
680
681         // (BE) As a first step we should do a scale before rotate since this is
682         // more like the natural thought of how to do it.
683         // (BE) I believe that a priority list presented to the user with
684         // a default order would be the best, though it would be better to
685         // hide such a thing in an "Advanced options" dialog.
686         // (BE) This should go an advanced LaTeX options dialog.
687
688         // If there is no file specified, just output a message about it in
689         // the latex output.
690         if (params.filename.empty()) {
691                 os  << "\\fbox{\\rule[-0.5in]{0pt}{1in}"
692                         << _("empty figure path")
693                         << "}\n";
694
695                 return 1; // One end of line marker added to the stream.
696         }
697
698         // Keep count of newlines that we issued.
699         int newlines = 0;
700
701         // This variables collect all the latex code that should be before and
702         // after the actual includegraphics command.
703         string before;
704         string after;
705
706         // Do we want subcaptions?
707         if (params.subcaption) {
708                 before += "\\subfigure[" + params.subcaptionText + "]{";
709                 after = '}' + after;
710         }
711
712         // We never use the starred form, we use the "clip" option instead.
713         os << before << "\\includegraphics";
714
715         // Write the options if there are any.
716         string const opts = createLatexOptions();
717         if (!opts.empty()) {
718                 os << '[' << opts << ']';
719         }
720
721         // Make the filename relative to the lyx file
722         // and remove the extension so the LaTeX will use whatever is
723         // appropriate (when there are several versions in different formats)
724         string const filename = prepareFile(buf);
725         
726         os << '{' << filename << '}' << after;
727
728         // Return how many newlines we issued.
729         return newlines;
730 }
731
732
733 int InsetGraphics::ascii(Buffer const *, ostream &, int) const
734 {
735         // No graphics in ascii output. Possible to use gifscii to convert
736         // images to ascii approximation.
737         
738         // 1. Convert file to ascii using gifscii
739         // 2. Read ascii output file and add it to the output stream.
740         
741         return 0;
742 }
743
744
745 int InsetGraphics::linuxdoc(Buffer const *, ostream &) const
746 {
747         // No graphics in LinuxDoc output. Should check how/what to add.
748         return 0;
749 }
750
751
752 // For explanation on inserting graphics into DocBook checkout:
753 // http://linuxdoc.org/LDP/LDP-Author-Guide/inserting-pictures.html
754 // See also the docbook guide at http://www.docbook.org/
755 int InsetGraphics::docbook(Buffer const * buf, ostream & os) const
756 {
757         // Change the path to be relative to the main file.
758         string const buffer_dir = OnlyPath(buf->fileName());
759         string const filename = RemoveExtension(
760                                    MakeRelPath(params.filename, buffer_dir));
761
762         // In DocBook v5.0, the graphic tag will be eliminated from DocBook, will 
763         // need to switch to MediaObject. However, for now this is sufficient and 
764         // easier to use.
765         os << "<graphic fileref=\"" << filename << "\"></graphic>";
766         return 0;
767 }
768
769
770 void InsetGraphics::validate(LaTeXFeatures & features) const
771 {
772         // If we have no image, we should not require anything.
773         if (params.filename.empty())
774                 return ;
775
776         features.graphicx = true;
777
778         if (params.subcaption)
779                 features.subfigure = true;
780 }
781
782
783 // Update the inset after parameters changed (read from file or changed in
784 // dialog.
785 void InsetGraphics::updateInset() const
786 {
787         GraphicsCache & gc = GraphicsCache::getInstance();
788         boost::shared_ptr<GraphicsCacheItem> temp(0);
789
790         // We do it this way so that in the face of some error, we will still
791         // be in a valid state.
792         if (!params.filename.empty()) {
793                 temp = gc.addFile(params.filename);
794         }
795
796         // Mark the image as unloaded so that it gets updated.
797         imageLoaded = false;
798
799         cacheHandle = temp;
800 }
801
802
803 bool InsetGraphics::setParams(InsetGraphicsParams const & p)
804 {
805         // If nothing is changed, just return and say so.
806         if (params == p)
807                 return false;
808
809         // Copy the new parameters.
810         params = p;
811
812         // Update the inset with the new parameters.
813         updateInset();
814
815         // We have changed data, report it.
816         return true;
817 }
818
819
820 InsetGraphicsParams InsetGraphics::getParams() const
821 {
822         return params;
823 }
824
825
826 Inset * InsetGraphics::clone(Buffer const &, bool same_id) const
827 {
828         return new InsetGraphics(*this, same_id);
829 }