]> git.lyx.org Git - lyx.git/blob - src/frontends/qt4/GuiGraphics.cpp
more frontend cleanup
[lyx.git] / src / frontends / qt4 / GuiGraphics.cpp
1 /**
2  * \file GuiGraphics.cpp
3  * This file is part of LyX, the document processor.
4  * Licence details can be found in the file COPYING.
5  *
6  * \author John Levon
7  * \author Edwin Leuven
8  * \author Herbert Voß
9  * \author Richard Heck
10  *
11  * Full author contact details are available in file CREDITS.
12  */
13
14 #include <config.h>
15
16 #include "GuiGraphics.h"
17
18 #include "ControlGraphics.h"
19 #include "debug.h"
20 #include "LengthCombo.h"
21 #include "lengthcommon.h"
22 #include "LyXRC.h"
23 #include "qt_helpers.h"
24 #include "Validator.h"
25
26 #include "controllers/frontend_helpers.h"
27
28 #include "insets/InsetGraphicsParams.h"
29
30 #include "support/convert.h"
31 #include "support/lstrings.h"
32 #include "support/lyxlib.h"
33 #include "support/os.h"
34
35 #include <QCheckBox>
36 #include <QCloseEvent>
37 #include <QLabel>
38 #include <QLineEdit>
39 #include <QPushButton>
40 #include <QValidator>
41
42 #include <algorithm>
43 #include <cmath>
44
45 using lyx::support::float_equal;
46 using lyx::support::token;
47
48 using lyx::support::os::internal_path;
49
50 #ifndef CXX_GLOBAL_CSTD
51 using std::floor;
52 #endif
53
54 using std::vector;
55 using std::string;
56
57
58 namespace lyx {
59 namespace frontend {
60
61
62 template<class Pair>
63 std::vector<typename Pair::first_type> const
64 getFirst(std::vector<Pair> const & pr)
65 {
66         std::vector<typename Pair::first_type> tmp(pr.size());
67         std::transform(pr.begin(), pr.end(), tmp.begin(),
68                        boost::bind(&Pair::first, _1));
69         return tmp;
70 }
71
72 GuiGraphicsDialog::GuiGraphicsDialog(LyXView & lv)
73         : GuiDialog(lv, "graphics")
74 {
75         setupUi(this);
76         setViewTitle(_("Graphics"));
77         setController(new ControlGraphics(*this));
78
79         //main buttons
80         connect(okPB, SIGNAL(clicked()), this, SLOT(slotOK()));
81         connect(applyPB, SIGNAL(clicked()), this, SLOT(slotApply()));
82         connect(closePB, SIGNAL(clicked()), this, SLOT(slotClose()));
83         connect(restorePB, SIGNAL(clicked()), this, SLOT(slotRestore()));
84
85         //graphics pane
86         connect(filename, SIGNAL(textChanged(const QString &)),
87                 this, SLOT(change_adaptor()));
88         connect(WidthCB, SIGNAL( clicked()),
89                 this, SLOT(change_adaptor()));
90         connect(HeightCB, SIGNAL( clicked()),
91                 this, SLOT(change_adaptor()));
92         connect(Width, SIGNAL(textChanged(const QString &)),
93                 this, SLOT(change_adaptor()));
94         connect(Height, SIGNAL(textChanged(const QString &)),
95                 this, SLOT(change_adaptor()));
96         connect(heightUnit, SIGNAL(selectionChanged(lyx::Length::UNIT)),
97                 this, SLOT(change_adaptor()));
98         connect(widthUnit, SIGNAL(selectionChanged(lyx::Length::UNIT)),
99                 this, SLOT(change_adaptor()));
100         connect(aspectratio, SIGNAL(stateChanged(int)),
101                 this, SLOT(change_adaptor()));
102         connect(angle, SIGNAL(textChanged(const QString &)),
103                 this, SLOT(change_adaptor()));
104         connect(origin, SIGNAL(activated(int)),
105                 this, SLOT(change_adaptor()));
106         connect(scaleCB, SIGNAL(clicked()),
107                 this, SLOT(change_adaptor()));
108         connect(Scale, SIGNAL(textChanged(const QString &)),
109                 this, SLOT(change_adaptor()));
110         connect(rotateOrderCB, SIGNAL(clicked()),
111                 this, SLOT(change_adaptor()));
112
113         filename->setValidator(new PathValidator(true, filename));
114         setFocusProxy(filename);
115
116         QDoubleValidator * scaleValidator = new DoubleAutoValidator(Scale);
117         scaleValidator->setBottom(0);
118         scaleValidator->setDecimals(256); //I guess that will do
119         Scale->setValidator(scaleValidator);
120         Height->setValidator(unsignedLengthAutoValidator(Height));
121         Width->setValidator(unsignedLengthAutoValidator(Width));
122         angle->setValidator(new QDoubleValidator(-360, 360, 2, angle));
123
124         //clipping pane
125         connect(clip, SIGNAL(stateChanged(int)),
126                 this, SLOT(change_adaptor()));
127         connect(lbY, SIGNAL(textChanged(const QString&)),
128                 this, SLOT(change_bb()));
129         connect(lbYunit, SIGNAL(activated(int)),
130                 this, SLOT(change_bb()));
131         connect(rtY, SIGNAL(textChanged(const QString&)),
132                 this, SLOT(change_bb()));
133         connect(rtYunit, SIGNAL(activated(int)),
134                 this, SLOT(change_bb()));
135         connect(lbX, SIGNAL(textChanged(const QString&)),
136                 this, SLOT(change_bb()));
137         connect(lbXunit, SIGNAL(activated(int)),
138                 this, SLOT(change_bb()));
139         connect(rtX, SIGNAL(textChanged(const QString&)),
140                 this, SLOT(change_bb()));
141         connect(rtXunit, SIGNAL(activated(int)),
142                 this, SLOT(change_bb()));
143         connect(getPB, SIGNAL(clicked()),
144                 this, SLOT(change_adaptor()));
145
146         lbX->setValidator(new QDoubleValidator(lbX));
147         lbY->setValidator(new QDoubleValidator(lbY));
148         rtX->setValidator(new QDoubleValidator(rtX));
149         rtY->setValidator(new QDoubleValidator(rtY));
150
151         //extra options pane
152         connect(latexoptions, SIGNAL(textChanged(const QString&)),
153                 this, SLOT(change_adaptor()));
154         connect(draftCB, SIGNAL(stateChanged(int)),
155                 this, SLOT(change_adaptor()));
156         connect(unzipCB, SIGNAL(stateChanged(int)),
157                 this, SLOT(change_adaptor()));
158         // FIXME: we should connect to clicked() when we move to Qt 4.2 because
159         // the toggled(bool) signal is also trigged when we update the widgets
160         // (rgh-4/07) this isn't as much or a problem as it was, because we're now
161         // using blockSignals() to keep from triggering that signal when we call
162         // setChecked(). Note, too, that clicked() would get called whenever it
163         // is clicked, even right clicked (I think), not just whenever it is
164         // toggled.
165         connect(subfigure, SIGNAL(toggled(bool)),
166                 this, SLOT(change_adaptor()));
167         connect(subcaption, SIGNAL(textChanged(const QString&)),
168                 this, SLOT(change_adaptor()));
169         connect(displayGB, SIGNAL(toggled(bool)),
170                 this, SLOT(change_adaptor()));
171         connect(showCB, SIGNAL(currentIndexChanged(int)),
172                 this, SLOT(change_adaptor()));
173         connect(displayscale, SIGNAL(textChanged(const QString&)),
174                 this, SLOT(change_adaptor()));
175         displayscale->setValidator(new QIntValidator(displayscale));
176
177         bc().setPolicy(ButtonPolicy::NoRepeatedApplyReadOnlyPolicy);
178         bc().setOK(okPB);
179         bc().setApply(applyPB);
180         bc().setRestore(restorePB);
181         bc().setCancel(closePB);
182
183         bc().addReadOnly(latexoptions);
184         bc().addReadOnly(subfigure);
185         bc().addReadOnly(filenameL);
186         bc().addReadOnly(filename);
187         bc().addReadOnly(browsePB);
188         bc().addReadOnly(unzipCB);
189         bc().addReadOnly(bbFrame);
190         bc().addReadOnly(draftCB);
191         bc().addReadOnly(clip);
192         bc().addReadOnly(unzipCB);
193         bc().addReadOnly(displayGB);
194         bc().addReadOnly(sizeGB);
195         bc().addReadOnly(rotationGB);
196         bc().addReadOnly(latexoptions);
197         bc().addReadOnly(getPB);
198         bc().addReadOnly(rotateOrderCB);
199
200         // initialize the length validator
201         bc().addCheckedLineEdit(Scale, scaleCB);
202         bc().addCheckedLineEdit(Width, WidthCB);
203         bc().addCheckedLineEdit(Height, HeightCB);
204         bc().addCheckedLineEdit(displayscale, scaleLA);
205         bc().addCheckedLineEdit(angle, angleL);
206         bc().addCheckedLineEdit(lbX, xL);
207         bc().addCheckedLineEdit(lbY, yL);
208         bc().addCheckedLineEdit(rtX, xL_2);
209         bc().addCheckedLineEdit(rtY, yL_2);
210         bc().addCheckedLineEdit(filename, filenameL);
211 }
212
213
214 ControlGraphics & GuiGraphicsDialog::controller() const
215 {
216         return static_cast<ControlGraphics &>(GuiDialog::controller());
217 }
218
219
220 void GuiGraphicsDialog::change_adaptor()
221 {
222         changed();
223 }
224
225
226 void GuiGraphicsDialog::change_bb()
227 {
228         controller().bbChanged = true;
229         LYXERR(Debug::GRAPHICS)
230                 << "[controller().bb_Changed set to true]\n";
231         changed();
232 }
233
234
235 void GuiGraphicsDialog::closeEvent(QCloseEvent * e)
236 {
237         slotWMHide();
238         e->accept();
239 }
240
241
242 void GuiGraphicsDialog::on_browsePB_clicked()
243 {
244         docstring const str =
245                 controller().browse(qstring_to_ucs4(filename->text()));
246         if(!str.empty()){
247                 filename->setText(toqstr(str));
248                 changed();
249         }
250 }
251
252
253 void GuiGraphicsDialog::on_getPB_clicked()
254 {
255         getBB();
256 }
257
258
259 void GuiGraphicsDialog::on_editPB_clicked()
260 {
261         controller().editGraphics();
262 }
263
264
265 void GuiGraphicsDialog::on_filename_textChanged(const QString & filename)
266 {
267         editPB->setDisabled(filename.isEmpty());
268 }
269
270
271 void GuiGraphicsDialog::setAutoText()
272 {
273         if (scaleCB->isChecked())
274                 return;
275         if (!Scale->isEnabled() && Scale->text() != "100")
276                 Scale->setText(QString("auto"));
277
278         setAutoTextCB(WidthCB, Width, widthUnit);
279         setAutoTextCB(HeightCB, Height, heightUnit);
280 }
281
282
283 void GuiGraphicsDialog::on_scaleCB_toggled(bool setScale)
284 {
285         Scale->setEnabled(setScale);
286         if (setScale) {
287                 Scale->setText("100");
288                 Scale->setFocus(Qt::OtherFocusReason);
289         }
290
291         WidthCB->setDisabled(setScale);
292         WidthCB->blockSignals(true);
293         WidthCB->setChecked(false);
294         WidthCB->blockSignals(false);
295         Width->setEnabled(false);
296         widthUnit->setEnabled(false);
297
298         HeightCB->setDisabled(setScale);
299         HeightCB->blockSignals(true);
300         HeightCB->setChecked(false);
301         HeightCB->blockSignals(false);
302         Height->setEnabled(false);
303         heightUnit->setEnabled(false);
304
305         aspectratio->setDisabled(true);
306         aspectratio->setChecked(true);
307
308         rotateOrderCB->setEnabled((WidthCB->isChecked() ||
309                                  HeightCB->isChecked() ||
310                                  scaleCB->isChecked()) &&
311                                  (angle->text() != "0"));
312
313         setAutoText();
314 }
315
316
317 void GuiGraphicsDialog::on_WidthCB_toggled(bool setWidth)
318 {
319         Width->setEnabled(setWidth);
320         widthUnit->setEnabled(setWidth);
321         if (setWidth)
322                 Width->setFocus(Qt::OtherFocusReason);
323
324         bool const setHeight = HeightCB->isChecked();
325         aspectratio->setEnabled(setWidth && setHeight);
326         aspectratio->blockSignals(true);
327         aspectratio->setChecked(!(setWidth && setHeight));
328         aspectratio->blockSignals(false);
329
330         scaleCB->setEnabled(!setWidth && !setHeight);
331         //already will be unchecked, so don't need to do that
332         Scale->setEnabled((!setWidth && !setHeight) //=scaleCB->isEnabled()
333                         && scaleCB->isChecked()); //should be false, but let's check
334         rotateOrderCB->setEnabled((setWidth || setHeight ||
335                                  scaleCB->isChecked()) &&
336                                  (angle->text() != "0"));
337
338         setAutoText();
339 }
340
341
342 void GuiGraphicsDialog::on_HeightCB_toggled(bool setHeight)
343 {
344         Height->setEnabled(setHeight);
345         heightUnit->setEnabled(setHeight);
346         if (setHeight)
347                 Height->setFocus(Qt::OtherFocusReason);
348
349         bool const setWidth = WidthCB->isChecked();
350         aspectratio->setEnabled(setWidth && setHeight);
351         aspectratio->blockSignals(true);
352         aspectratio->setChecked(!(setWidth && setHeight));
353         aspectratio->blockSignals(false);
354
355         scaleCB->setEnabled(!setWidth && !setHeight);
356         //already unchecked
357         Scale->setEnabled((!setWidth && !setHeight) //=scaleCB->isEnabled()
358                 && scaleCB->isChecked()); //should be false
359         rotateOrderCB->setEnabled((setWidth || setHeight ||
360                                  scaleCB->isChecked()) &&
361                                  (angle->text() != "0"));
362
363         setAutoText();
364 }
365
366
367 void GuiGraphicsDialog::on_angle_textChanged(const QString & filename)
368 {
369         rotateOrderCB->setEnabled((WidthCB->isChecked() ||
370                                  HeightCB->isChecked() ||
371                                  scaleCB->isChecked()) &&
372                                  (filename != "0"));
373 }
374
375 // returns the number of the string s in the vector v
376 static int getItemNo(const vector<string> & v, string const & s)
377 {
378         vector<string>::const_iterator cit =
379                     find(v.begin(), v.end(), s);
380         return (cit != v.end()) ? int(cit - v.begin()) : 0;
381 }
382
383
384 void GuiGraphicsDialog::update_contents()
385 {
386         // clear and fill in the comboboxes
387         vector<string> const bb_units = frontend::getBBUnits();
388         lbXunit->clear();
389         lbYunit->clear();
390         rtXunit->clear();
391         rtYunit->clear();
392         for (vector<string>::const_iterator it = bb_units.begin();
393             it != bb_units.end(); ++it) {
394                 lbXunit->addItem(toqstr(*it));
395                 lbYunit->addItem(toqstr(*it));
396                 rtXunit->addItem(toqstr(*it));
397                 rtYunit->addItem(toqstr(*it));
398         }
399
400         InsetGraphicsParams & igp = controller().params();
401
402         // set the right default unit
403         Length::UNIT unitDefault = Length::CM;
404         switch (lyxrc.default_papersize) {
405                 case PAPER_USLETTER:
406                 case PAPER_USLEGAL:
407                 case PAPER_USEXECUTIVE:
408                         unitDefault = Length::IN;
409                         break;
410                 default:
411                         break;
412         }
413
414         string const name =
415                 igp.filename.outputFilename(kernel().bufferFilepath());
416         filename->setText(toqstr(name));
417
418         // set the bounding box values
419         if (igp.bb.empty()) {
420                 string const bb = controller().readBB(igp.filename.absFilename());
421                 // the values from the file always have the bigpoint-unit bp
422                 lbX->setText(toqstr(token(bb, ' ', 0)));
423                 lbY->setText(toqstr(token(bb, ' ', 1)));
424                 rtX->setText(toqstr(token(bb, ' ', 2)));
425                 rtY->setText(toqstr(token(bb, ' ', 3)));
426                 lbXunit->setCurrentIndex(0);
427                 lbYunit->setCurrentIndex(0);
428                 rtXunit->setCurrentIndex(0);
429                 rtYunit->setCurrentIndex(0);
430                 controller().bbChanged = false;
431         } else {
432                 // get the values from the inset
433                 Length anyLength;
434                 string const xl(token(igp.bb, ' ', 0));
435                 string const yl(token(igp.bb, ' ', 1));
436                 string const xr(token(igp.bb, ' ', 2));
437                 string const yr(token(igp.bb, ' ', 3));
438                 if (isValidLength(xl, &anyLength)) {
439                         lbX->setText(toqstr(convert<string>(anyLength.value())));
440                         string const unit(unit_name[anyLength.unit()]);
441                         lbXunit->setCurrentIndex(getItemNo(bb_units, unit));
442                 } else {
443                         lbX->setText(toqstr(xl));
444                 }
445                 if (isValidLength(yl, &anyLength)) {
446                         lbY->setText(toqstr(convert<string>(anyLength.value())));
447                         string const unit(unit_name[anyLength.unit()]);
448                         lbYunit->setCurrentIndex(getItemNo(bb_units, unit));
449                 } else {
450                         lbY->setText(toqstr(xl));
451                 }
452                 if (isValidLength(xr, &anyLength)) {
453                         rtX->setText(toqstr(convert<string>(anyLength.value())));
454                         string const unit(unit_name[anyLength.unit()]);
455                         rtXunit->setCurrentIndex(getItemNo(bb_units, unit));
456                 } else {
457                         rtX->setText(toqstr(xl));
458                 }
459                 if (isValidLength(yr, &anyLength)) {
460                         rtY->setText(toqstr(convert<string>(anyLength.value())));
461                         string const unit(unit_name[anyLength.unit()]);
462                         rtYunit->setCurrentIndex(getItemNo(bb_units, unit));
463                 } else {
464                         rtY->setText(toqstr(xl));
465                 }
466                 controller().bbChanged = true;
467         }
468
469         // Update the draft and clip mode
470         draftCB->setChecked(igp.draft);
471         clip->setChecked(igp.clip);
472         unzipCB->setChecked(igp.noUnzip);
473
474         // Update the subcaption check button and input field
475         subfigure->setChecked(igp.subcaption);
476         subcaption->setText(toqstr(igp.subcaptionText));
477
478         int item = 0;
479         switch (igp.display) {
480                 case graphics::DefaultDisplay: item = 0; break;
481                 case graphics::MonochromeDisplay: item = 1; break;
482                 case graphics::GrayscaleDisplay: item = 2; break;
483                 case graphics::ColorDisplay: item = 3; break;
484                 case graphics::NoDisplay: item = 0; break;
485         }
486         showCB->setCurrentIndex(item);
487         displayscale->setText(toqstr(convert<string>(igp.lyxscale)));
488         displayGB->setChecked(igp.display != graphics::NoDisplay);
489
490         // the output section (width/height)
491
492         Scale->setText(toqstr(igp.scale));
493         //igp.scale defaults to 100, so we treat it as empty
494         bool const scaleChecked = !igp.scale.empty() && igp.scale != "100";
495         scaleCB->blockSignals(true);
496         scaleCB->setChecked(scaleChecked);
497         scaleCB->blockSignals(false);
498         Scale->setEnabled(scaleChecked);
499
500         lengthAutoToWidgets(Width, widthUnit, igp.width,
501                 unitDefault);
502         bool const widthChecked = !Width->text().isEmpty() &&
503                 Width->text() != "auto";
504         WidthCB->blockSignals(true);
505         WidthCB->setChecked(widthChecked);
506         WidthCB->blockSignals(false);
507         Width->setEnabled(widthChecked);
508         widthUnit->setEnabled(widthChecked);
509
510         lengthAutoToWidgets(Height, heightUnit, igp.height,
511                 unitDefault);
512         bool const heightChecked = !Height->text().isEmpty()
513                 && Height->text() != "auto";
514         HeightCB->blockSignals(true);
515         HeightCB->setChecked(heightChecked);
516         HeightCB->blockSignals(false);
517         Height->setEnabled(heightChecked);
518         heightUnit->setEnabled(heightChecked);
519
520         scaleCB->setEnabled(!widthChecked && !heightChecked);
521         WidthCB->setEnabled(!scaleChecked);
522         HeightCB->setEnabled(!scaleChecked);
523         aspectratio->setEnabled(widthChecked && heightChecked);
524
525         setAutoText();
526
527         angle->setText(toqstr(igp.rotateAngle));
528         rotateOrderCB->setChecked(igp.scaleBeforeRotation);
529
530         rotateOrderCB->setEnabled( (widthChecked || heightChecked || scaleChecked)
531                 && igp.rotateAngle != "0");
532
533         origin->clear();
534
535         vector<RotationOriginPair> origindata = getRotationOriginData();
536         vector<docstring> const origin_lang = getFirst(origindata);
537         origin_ltx = getSecond(origindata);
538
539         for (vector<docstring>::const_iterator it = origin_lang.begin();
540             it != origin_lang.end(); ++it)
541                 origin->addItem(toqstr(*it));
542
543         if (!igp.rotateOrigin.empty())
544                 origin->setCurrentIndex(
545                         getItemNo(origin_ltx, igp.rotateOrigin));
546         else
547                 origin->setCurrentIndex(0);
548
549         // disable edit button when no filename is present
550         editPB->setDisabled(filename->text().isEmpty());
551
552         //// latex section
553         latexoptions->setText(toqstr(igp.special));
554 }
555
556
557 void GuiGraphicsDialog::applyView()
558 {
559         InsetGraphicsParams & igp = controller().params();
560
561         igp.filename.set(internal_path(fromqstr(filename->text())),
562                          kernel().bufferFilepath());
563
564         // the bb section
565         igp.bb.erase();
566         if (controller().bbChanged) {
567                 string bb;
568                 string lbXs = fromqstr(lbX->text());
569                 string lbYs = fromqstr(lbY->text());
570                 string rtXs = fromqstr(rtX->text());
571                 string rtYs = fromqstr(rtY->text());
572                 int bb_sum =
573                         convert<int>(lbXs) + convert<int>(lbYs) +
574                         convert<int>(rtXs) + convert<int>(rtXs);
575                 if (bb_sum) {
576                         if (lbXs.empty())
577                                 bb = "0 ";
578                         else
579                                 bb = lbXs + fromqstr(lbXunit->currentText()) + ' ';
580                         if (lbYs.empty())
581                                 bb += "0 ";
582                         else
583                                 bb += (lbYs + fromqstr(lbYunit->currentText()) + ' ');
584                         if (rtXs.empty())
585                                 bb += "0 ";
586                         else
587                                 bb += (rtXs + fromqstr(rtXunit->currentText()) + ' ');
588                         if (rtYs.empty())
589                                 bb += '0';
590                         else
591                                 bb += (rtYs + fromqstr(rtYunit->currentText()));
592                         igp.bb = bb;
593                 }
594         }
595
596         igp.draft = draftCB->isChecked();
597         igp.clip = clip->isChecked();
598         igp.subcaption = subfigure->isChecked();
599         igp.subcaptionText = fromqstr(subcaption->text());
600
601         switch (showCB->currentIndex()) {
602                 case 0: igp.display = graphics::DefaultDisplay; break;
603                 case 1: igp.display = graphics::MonochromeDisplay; break;
604                 case 2: igp.display = graphics::GrayscaleDisplay; break;
605                 case 3: igp.display = graphics::ColorDisplay; break;
606                 default:;
607         }
608
609         if (!displayGB->isChecked())
610                 igp.display = graphics::NoDisplay;
611
612         //the graphics section
613         if (scaleCB->isChecked() && !Scale->text().isEmpty()) {
614                 igp.scale = fromqstr(Scale->text());
615                 igp.width = Length("0pt");
616                 igp.height = Length("0pt");
617                 igp.keepAspectRatio = false;
618         } else {
619                 igp.scale = string();
620                 igp.width = WidthCB->isChecked() ?
621                         //Note that this works even if Width is "auto", since in
622                         //that case we get "0pt".
623                         Length(widgetsToLength(Width, widthUnit)):
624                         Length("0pt");
625                 igp.height = HeightCB->isChecked() ?
626                         Length(widgetsToLength(Height, heightUnit)) :
627                         Length("0pt");
628                 igp.keepAspectRatio = aspectratio->isEnabled() &&
629                         aspectratio->isChecked() &&
630                         igp.width.value() > 0 && igp.height.value() > 0;
631         }
632
633         igp.noUnzip = unzipCB->isChecked();
634         igp.lyxscale = displayscale->text().toInt();
635         igp.rotateAngle = fromqstr(angle->text());
636
637         double rotAngle = convert<double>(igp.rotateAngle);
638         if (std::abs(rotAngle) > 360.0) {
639                 rotAngle -= 360.0 * floor(rotAngle / 360.0);
640                 igp.rotateAngle = convert<string>(rotAngle);
641         }
642
643         // save the latex name for the origin. If it is the default
644         // then origin_ltx returns ""
645         igp.rotateOrigin = origin_ltx[origin->currentIndex()];
646         igp.scaleBeforeRotation = rotateOrderCB->isChecked();
647
648         // more latex options
649         igp.special = fromqstr(latexoptions->text());
650 }
651
652
653 void GuiGraphicsDialog::getBB()
654 {
655         string const fn = fromqstr(filename->text());
656         if (!fn.empty()) {
657                 string const bb = controller().readBB(fn);
658                 if (!bb.empty()) {
659                         lbX->setText(toqstr(token(bb, ' ', 0)));
660                         lbY->setText(toqstr(token(bb, ' ', 1)));
661                         rtX->setText(toqstr(token(bb, ' ', 2)));
662                         rtY->setText(toqstr(token(bb, ' ', 3)));
663                         // the default units for the bb values when reading
664                         // it from the file
665                         lbXunit->setCurrentIndex(0);
666                         lbYunit->setCurrentIndex(0);
667                         rtXunit->setCurrentIndex(0);
668                         rtYunit->setCurrentIndex(0);
669                 }
670                 controller().bbChanged = false;
671         }
672 }
673
674
675 bool GuiGraphicsDialog::isValid()
676 {
677         return !filename->text().isEmpty();
678 }
679
680 } // namespace frontend
681 } // namespace lyx
682
683
684 #include "GuiGraphics_moc.cpp"
685