]> git.lyx.org Git - lyx.git/blob - src/frontends/qt4/GuiCharacter.cpp
Rename ambiguous enum
[lyx.git] / src / frontends / qt4 / GuiCharacter.cpp
1 /**
2  * \file GuiCharacter.cpp
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  * \author Edwin Leuven
8  * \author John Levon
9  * \author Jürgen Spitzmüller
10  *
11  * Full author contact details are available in file CREDITS.
12  */
13
14 #include <config.h>
15
16 #include "GuiCharacter.h"
17
18 #include "GuiApplication.h"
19 #include "qt_helpers.h"
20
21 #include "Font.h"
22 #include "Buffer.h"
23 #include "BufferParams.h"
24 #include "BufferView.h"
25 #include "Color.h"
26 #include "ColorCache.h"
27 #include "ColorSet.h"
28 #include "Cursor.h"
29 #include "FuncRequest.h"
30 #include "Language.h"
31 #include "Paragraph.h"
32
33 #include "support/gettext.h"
34 #include "support/lstrings.h"
35
36 #include <QAbstractItemModel>
37 #include <QPushButton>
38 #include <QComboBox>
39 #include <QModelIndex>
40 #include <QSettings>
41 #include <QVariant>
42
43 using namespace std;
44
45 namespace lyx {
46 namespace frontend {
47
48 static QList<ShapePair> shapeData()
49 {
50         QList<ShapePair> shapes;
51         shapes << ShapePair(qt_("No change"), IGNORE_SHAPE);
52         shapes << ShapePair(qt_("Default"), INHERIT_SHAPE);
53         shapes << ShapePair(qt_("Upright"), UP_SHAPE);
54         shapes << ShapePair(qt_("Italic"), ITALIC_SHAPE);
55         shapes << ShapePair(qt_("Slanted"), SLANTED_SHAPE);
56         shapes << ShapePair(qt_("Small Caps"), SMALLCAPS_SHAPE);
57         return shapes;
58 }
59
60
61 static QList<SizePair> sizeData()
62 {
63         QList<SizePair> sizes;
64         sizes << SizePair(qt_("No change"), FONT_SIZE_IGNORE);
65         sizes << SizePair(qt_("Default"), FONT_SIZE_INHERIT);
66         sizes << SizePair(qt_("Tiny"), FONT_SIZE_TINY);
67         sizes << SizePair(qt_("Smallest"), FONT_SIZE_SCRIPT);
68         sizes << SizePair(qt_("Smaller"), FONT_SIZE_FOOTNOTE);
69         sizes << SizePair(qt_("Small"), FONT_SIZE_SMALL);
70         sizes << SizePair(qt_("Normal"), FONT_SIZE_NORMAL);
71         sizes << SizePair(qt_("Large"), FONT_SIZE_LARGE);
72         sizes << SizePair(qt_("Larger"), FONT_SIZE_LARGER);
73         sizes << SizePair(qt_("Largest"), FONT_SIZE_LARGEST);
74         sizes << SizePair(qt_("Huge"), FONT_SIZE_HUGE);
75         sizes << SizePair(qt_("Huger"), FONT_SIZE_HUGER);
76         sizes << SizePair(qt_("Increase"), FONT_SIZE_INCREASE);
77         sizes << SizePair(qt_("Decrease"), FONT_SIZE_DECREASE);
78         return sizes;
79 }
80
81
82 static QList<BarPair> barData()
83 {
84         QList<BarPair> bars;
85         bars << BarPair(qt_("No change"), IGNORE);
86         bars << BarPair(qt_("Default"), INHERIT);
87         bars << BarPair(qt_("(Without)[[underlining]]"), NONE);
88         bars << BarPair(qt_("Single[[underlining]]"), UNDERBAR);
89         bars << BarPair(qt_("Double[[underlining]]"), UULINE);
90         bars << BarPair(qt_("Wavy"), UWAVE);
91         return bars;
92 }
93
94
95 static QList<BarPair> strikeData()
96 {
97         QList<BarPair> strike;
98         strike << BarPair(qt_("No change"), IGNORE);
99         strike << BarPair(qt_("Default"), INHERIT);
100         strike << BarPair(qt_("(Without)[[strikethrough]]"), NONE);
101         strike << BarPair(qt_("Single[[strikethrough]]"), STRIKEOUT);
102         strike << BarPair(qt_("With /"), XOUT);
103         return strike;
104 }
105
106
107 static QList<ColorCode> colorData()
108 {
109         QList<ColorCode> colors;
110         colors << Color_black;
111         colors << Color_blue;
112         colors << Color_brown;
113         colors << Color_cyan;
114         colors << Color_darkgray;
115         colors << Color_gray;
116         colors << Color_green;
117         colors << Color_lightgray;
118         colors << Color_lime;
119         colors << Color_magenta;
120         colors << Color_olive;
121         colors << Color_orange;
122         colors << Color_pink;
123         colors << Color_purple;
124         colors << Color_red;
125         colors << Color_teal;
126         colors << Color_violet;
127         colors << Color_white;
128         colors << Color_yellow;
129         return colors;
130 }
131
132
133 static QList<SeriesPair> seriesData()
134 {
135         QList<SeriesPair> series;
136         series << SeriesPair(qt_("No change"), IGNORE_SERIES);
137         series << SeriesPair(qt_("Default"),     INHERIT_SERIES);
138         series << SeriesPair(qt_("Medium"),    MEDIUM_SERIES);
139         series << SeriesPair(qt_("Bold"),      BOLD_SERIES);
140         return series;
141 }
142
143
144 static QList<FamilyPair> familyData()
145 {
146         QList<FamilyPair> families;
147         families << FamilyPair(qt_("No change"),  IGNORE_FAMILY);
148         families << FamilyPair(qt_("Default"),      INHERIT_FAMILY);
149         families << FamilyPair(qt_("Roman"),      ROMAN_FAMILY);
150         families << FamilyPair(qt_("Sans Serif"), SANS_FAMILY);
151         families << FamilyPair(qt_("Typewriter"), TYPEWRITER_FAMILY);
152         return families;
153 }
154
155
156 static QList<LanguagePair> languageData()
157 {
158         QList<LanguagePair> list;
159         // FIXME (Abdel 14/05/2008): it would be nice if we could use this model
160         // directly in the language combo; but, as we need also the 'No Change' and
161         // 'Default' items, this is not possible right now. Separating those two
162         // entries in radio buttons would be a better GUI IMHO.
163         QAbstractItemModel * language_model = guiApp->languageModel();
164         // Make sure the items are sorted.
165         language_model->sort(0);
166
167         for (int i = 0; i != language_model->rowCount(); ++i) {
168                 QModelIndex index = language_model->index(i, 0);
169                 list << LanguagePair(index.data(Qt::DisplayRole).toString(),
170                         index.data(Qt::UserRole).toString());
171         }
172         return list;
173 }
174
175
176 namespace {
177
178 template<typename T>
179 void fillCombo(QComboBox * combo, QList<T> const & list)
180 {
181         typename QList<T>::const_iterator cit = list.begin();
182         for (; cit != list.end(); ++cit)
183                 combo->addItem(cit->first);
184 }
185
186 template<typename T>
187 void fillComboColor(QComboBox * combo, QList<T> const & list)
188 {
189         // at first add the 2 colors "No change" and "No color"
190         combo->addItem(qt_("No change"), "ignore");
191         combo->addItem(qt_("Default"), "inherit");
192         combo->addItem(qt_("(Without)[[color]]"), "none");
193         // now add the real colors
194         QPixmap coloritem(32, 32);
195         QColor color;
196         QList<ColorCode>::const_iterator cit = list.begin();
197         for (; cit != list.end(); ++cit) {
198                 QString const lyxname = toqstr(lcolor.getLyXName(*cit));
199                 QString const guiname = toqstr(translateIfPossible(lcolor.getGUIName(*cit)));
200                 color = QColor(guiApp->colorCache().get(*cit, false));
201                 coloritem.fill(color);
202                 combo->addItem(QIcon(coloritem), guiname, lyxname);
203         }
204 }
205
206 } // namespace
207
208 GuiCharacter::GuiCharacter(GuiView & lv)
209         : GuiDialog(lv, "character", qt_("Text Properties")),
210           font_(ignore_font, ignore_language),
211           emph_(false), noun_(false), nospellcheck_(false)
212 {
213         setupUi(this);
214
215         connect(buttonBox, SIGNAL(clicked(QAbstractButton *)),
216                 this, SLOT(slotButtonBox(QAbstractButton *)));
217         connect(autoapplyCB, SIGNAL(stateChanged(int)), this,
218                 SLOT(slotAutoApply()));
219
220         connect(ulineCO, SIGNAL(currentIndexChanged(int)), this, SLOT(change_adaptor()));
221         connect(strikeCO, SIGNAL(currentIndexChanged(int)), this, SLOT(change_adaptor()));
222         connect(sizeCO, SIGNAL(currentIndexChanged(int)), this, SLOT(change_adaptor()));
223         connect(familyCO, SIGNAL(currentIndexChanged(int)), this, SLOT(change_adaptor()));
224         connect(seriesCO, SIGNAL(currentIndexChanged(int)), this, SLOT(change_adaptor()));
225         connect(shapeCO, SIGNAL(currentIndexChanged(int)), this, SLOT(change_adaptor()));
226         connect(colorCO, SIGNAL(currentIndexChanged(int)), this, SLOT(change_adaptor()));
227         connect(langCO, SIGNAL(currentIndexChanged(int)), this, SLOT(change_adaptor()));
228
229         family = familyData();
230         series = seriesData();
231         shape  = shapeData();
232         size   = sizeData();
233         bar    = barData();
234         strike = strikeData();
235         color  = colorData();
236         qSort(color.begin(), color.end(), ColorSorter);
237
238         language = languageData();
239         language.prepend(LanguagePair(qt_("Default"), "reset"));
240         language.prepend(LanguagePair(qt_("No change"), "ignore"));
241
242         fillCombo(familyCO, family);
243         fillCombo(seriesCO, series);
244         fillCombo(sizeCO, size);
245         fillCombo(shapeCO, shape);
246         fillCombo(ulineCO, bar);
247         fillCombo(strikeCO, strike);
248         fillComboColor(colorCO, color);
249         fillCombo(langCO, language);
250
251         bc().setPolicy(ButtonPolicy::OkApplyCancelAutoReadOnlyPolicy);
252         bc().setOK(buttonBox->button(QDialogButtonBox::Ok));
253         bc().setApply(buttonBox->button(QDialogButtonBox::Apply));
254         bc().setCancel(buttonBox->button(QDialogButtonBox::Cancel));
255         bc().setRestore(buttonBox->button(QDialogButtonBox::Reset));
256         bc().setAutoApply(autoapplyCB);
257         bc().addReadOnly(familyCO);
258         bc().addReadOnly(seriesCO);
259         bc().addReadOnly(sizeCO);
260         bc().addReadOnly(shapeCO);
261         bc().addReadOnly(ulineCO);
262         bc().addReadOnly(strikeCO);
263         bc().addReadOnly(nounCB);
264         bc().addReadOnly(emphCB);
265         bc().addReadOnly(nospellcheckCB);
266         bc().addReadOnly(langCO);
267         bc().addReadOnly(colorCO);
268         bc().addReadOnly(autoapplyCB);
269
270 #ifdef Q_OS_MAC
271         // On Mac it's common to have tool windows which are always in the
272         // foreground and are hidden when the main window is not focused.
273         setWindowFlags(Qt::Tool);
274         autoapplyCB->setChecked(true);
275 #endif
276 }
277
278
279 void GuiCharacter::on_emphCB_clicked()
280 {
281         // skip intermediate state at user click
282         if (!emph_) {
283                 emphCB->setCheckState(Qt::Checked);
284                 emph_ = true;
285         }
286         change_adaptor();
287 }
288
289
290 void GuiCharacter::on_nounCB_clicked()
291 {
292         // skip intermediate state at user click
293         if (!noun_) {
294                 nounCB->setCheckState(Qt::Checked);
295                 noun_ = true;
296         }
297         change_adaptor();
298 }
299
300
301 void GuiCharacter::on_nospellcheckCB_clicked()
302 {
303         // skip intermediate state at user click
304         if (!nospellcheck_) {
305                 nospellcheckCB->setCheckState(Qt::Checked);
306                 nospellcheck_ = true;
307         }
308         change_adaptor();
309 }
310
311
312 void GuiCharacter::slotRestoreDefaults()
313 {
314         Font font(inherit_font);
315         font.setLanguage(reset_language);
316         paramsToDialog(font);
317         change_adaptor();
318 }
319
320
321 template<class P, class B>
322 static int findPos2nd(QList<P> const & vec, B const & val)
323 {
324         for (int i = 0; i != vec.size(); ++i)
325                 if (vec[i].second == val)
326                         return i;
327         return 0;
328 }
329
330
331 namespace{
332 FontDeco getBar(FontInfo const & fi)
333 {
334         if (fi.underbar() == FONT_ON)
335                 return UNDERBAR;
336
337         if (fi.uuline() == FONT_ON)
338                 return UULINE;
339
340         if (fi.uwave() == FONT_ON)
341                 return UWAVE;
342
343         if (fi.underbar() == FONT_IGNORE)
344                 return IGNORE;
345
346         if (fi.underbar() == FONT_INHERIT)
347                 return INHERIT;
348
349         return NONE;
350 }
351
352
353 FontDeco getStrike(FontInfo const & fi)
354 {
355         if (fi.strikeout() == FONT_ON)
356                 return STRIKEOUT;
357
358         if (fi.xout() == FONT_ON)
359                 return XOUT;
360
361         if (fi.strikeout() == FONT_IGNORE)
362                 return IGNORE;
363
364         if (fi.strikeout() == FONT_INHERIT)
365                 return INHERIT;
366
367         return NONE;
368 }
369
370
371 Qt::CheckState getMarkupState(lyx::FontState fs)
372 {
373         switch (fs) {
374         case FONT_INHERIT:
375         case FONT_OFF:
376                 return Qt::Unchecked;
377         case FONT_ON:
378                 return Qt::Checked;
379         case FONT_TOGGLE:
380         case FONT_IGNORE:
381         default:
382                 return Qt::PartiallyChecked;
383         }
384 }
385
386 lyx::FontState setMarkupState(Qt::CheckState cs)
387 {
388         switch (cs) {
389         case Qt::Unchecked:
390                 return FONT_OFF;
391         case Qt::Checked:
392                 return FONT_ON;
393         case Qt::PartiallyChecked:
394         default:
395                 return FONT_IGNORE;
396         }
397 }
398
399 } // end namespace anon
400
401
402 void GuiCharacter::change_adaptor()
403 {
404         changed();
405
406         checkRestoreDefaults();
407
408         if (!autoapplyCB->isChecked())
409                 return;
410
411         // to be really good here, we should set the combos to the values of
412         // the current text, and make it appear as "no change" if the values
413         // stay the same between applys. Might be difficult though wrt to a
414         // moved cursor - jbl
415         slotApply();
416 }
417
418
419 void GuiCharacter::checkRestoreDefaults()
420 {
421         // (De)Activate Restore Defaults button
422         buttonBox->button(QDialogButtonBox::RestoreDefaults)->setEnabled(
423                 family[familyCO->currentIndex()].second != INHERIT_FAMILY
424                 || series[seriesCO->currentIndex()].second != INHERIT_SERIES
425                 || shape[shapeCO->currentIndex()].second != INHERIT_SHAPE
426                 || size[sizeCO->currentIndex()].second != FONT_SIZE_INHERIT
427                 || setMarkupState(emphCB->checkState()) != FONT_OFF
428                 || setMarkupState(nounCB->checkState()) != FONT_OFF
429                 || setMarkupState(nospellcheckCB->checkState()) != FONT_OFF
430                 || bar[ulineCO->currentIndex()].second != INHERIT
431                 || strike[strikeCO->currentIndex()].second != INHERIT
432                 || lcolor.getFromLyXName(fromqstr(colorCO->itemData(colorCO->currentIndex()).toString())) != Color_inherit
433                 || languages.getLanguage(fromqstr(language[langCO->currentIndex()].second)) != reset_language);
434 }
435
436
437 void GuiCharacter::updateContents()
438 {
439         if (bufferview()->cursor().selection()) {
440                 Font font = bufferview()->cursor().current_font;
441                 FontInfo fi = font.fontInfo();
442                 BufferParams const & bp = buffer().masterParams();
443
444                 // Check if each font attribute is constant for the selection range.
445                 DocIterator const from = bufferview()->cursor().selectionBegin();
446                 DocIterator const to = bufferview()->cursor().selectionEnd();
447                 for (DocIterator dit = from ; dit != to && !dit.atEnd(); ) {
448                         if (!dit.inTexted()) {
449                                 dit.forwardPos();
450                                 continue;
451                         }
452                         Paragraph const & par = dit.paragraph();
453                         pos_type const pos = dit.pos();
454                         Font tmp = par.getFontSettings(bp, pos);
455                         if (font.language() != tmp.language())
456                                 font.setLanguage(ignore_language);
457                         if (fi.family() != tmp.fontInfo().family())
458                                 font.fontInfo().setFamily(IGNORE_FAMILY);
459                         if (fi.series() != tmp.fontInfo().series())
460                                 font.fontInfo().setSeries(IGNORE_SERIES);
461                         if (fi.shape() != tmp.fontInfo().shape())
462                                 font.fontInfo().setShape(IGNORE_SHAPE);
463                         if (fi.size() != tmp.fontInfo().size())
464                                 font.fontInfo().setSize(FONT_SIZE_IGNORE);
465                         if (fi.emph() != tmp.fontInfo().emph())
466                                 font.fontInfo().setEmph(FONT_IGNORE);
467                         if (fi.noun() != tmp.fontInfo().noun())
468                                 font.fontInfo().setNoun(FONT_IGNORE);
469                         if (fi.nospellcheck() != tmp.fontInfo().nospellcheck())
470                                 font.fontInfo().setNoSpellcheck(FONT_IGNORE);
471                         if (fi.color() != tmp.fontInfo().color())
472                                 font.fontInfo().setColor(Color_ignore);
473                         if (fi.underbar() != tmp.fontInfo().underbar()
474                             || fi.uuline() != tmp.fontInfo().uuline()
475                             || fi.uwave() != tmp.fontInfo().uwave())
476                                 setBar(font.fontInfo(), IGNORE);
477                         if (fi.strikeout() != tmp.fontInfo().strikeout()
478                             || fi.xout() != tmp.fontInfo().xout())
479                                 setStrike(font.fontInfo(), IGNORE);
480                         dit.forwardPos();
481                 }
482                 font_ = font;
483         } else
484                 font_ = bufferview()->cursor().current_font;
485
486         // If we use the buffer language, display "Default"
487         if (font_.language() == buffer().params().language)
488                 font_.setLanguage(reset_language);
489
490         paramsToDialog(font_);
491
492         checkRestoreDefaults();
493 }
494
495
496 void GuiCharacter::setBar(FontInfo & fi, FontDeco val)
497 {
498         switch (val) {
499         case IGNORE:
500                 fi.setUnderbar(FONT_IGNORE);
501                 fi.setUuline(FONT_IGNORE);
502                 fi.setUwave(FONT_IGNORE);
503                 break;
504         case UNDERBAR:
505                 setBar(fi, NONE);
506                 fi.setUnderbar(FONT_ON);
507                 break;
508         case UULINE:
509                 setBar(fi, NONE);
510                 fi.setUuline(FONT_ON);
511                 break;
512         case UWAVE:
513                 setBar(fi, NONE);
514                 fi.setUwave(FONT_ON);
515                 break;
516         case INHERIT:
517                 fi.setUnderbar(FONT_INHERIT);
518                 fi.setUuline(FONT_INHERIT);
519                 fi.setUwave(FONT_INHERIT);
520                 break;
521         case NONE:
522                 fi.setUnderbar(FONT_OFF);
523                 fi.setUuline(FONT_OFF);
524                 fi.setUwave(FONT_OFF);
525                 break;
526         case XOUT:
527         case STRIKEOUT:
528         default:
529                 break;
530         }
531 }
532
533
534 void GuiCharacter::setStrike(FontInfo & fi, FontDeco val)
535 {
536         switch (val) {
537         case IGNORE:
538                 fi.setStrikeout(FONT_IGNORE);
539                 fi.setXout(FONT_IGNORE);
540                 break;
541         case STRIKEOUT:
542                 setStrike(fi, NONE);
543                 fi.setStrikeout(FONT_ON);
544                 break;
545         case XOUT:
546                 setStrike(fi, NONE);
547                 fi.setXout(FONT_ON);
548                 break;
549         case INHERIT:
550                 fi.setStrikeout(FONT_INHERIT);
551                 fi.setXout(FONT_INHERIT);
552                 break;
553         case NONE:
554                 fi.setStrikeout(FONT_OFF);
555                 fi.setXout(FONT_OFF);
556                 break;
557         case UNDERBAR:
558         case UWAVE:
559         case UULINE:
560         default:
561                 break;
562         }
563 }
564
565
566 void GuiCharacter::paramsToDialog(Font const & font)
567 {
568         FontInfo const & fi = font.fontInfo();
569         familyCO->setCurrentIndex(findPos2nd(family, fi.family()));
570         seriesCO->setCurrentIndex(findPos2nd(series, fi.series()));
571         shapeCO->setCurrentIndex(findPos2nd(shape, fi.shape()));
572         sizeCO->setCurrentIndex(findPos2nd(size, fi.size()));
573         ulineCO->setCurrentIndex(findPos2nd(bar, getBar(fi)));
574         strikeCO->setCurrentIndex(findPos2nd(strike, getStrike(fi)));
575         colorCO->setCurrentIndex(colorCO->findData(toqstr(lcolor.getLyXName(fi.color()))));
576         emphCB->setCheckState(getMarkupState(fi.emph()));
577         nounCB->setCheckState(getMarkupState(fi.noun()));
578         nospellcheckCB->setCheckState(getMarkupState(fi.nospellcheck()));
579         emph_ = emphCB->checkState() == Qt::Checked;
580         noun_ = nounCB->checkState() == Qt::Checked;
581         nospellcheck_ = nospellcheckCB->checkState() == Qt::Checked;
582
583         // reset_language is a null pointer.
584         QString const lang = (font.language() == reset_language)
585                 ? "reset" : toqstr(font.language()->lang());
586         langCO->setCurrentIndex(findPos2nd(language, lang));
587 }
588
589
590 void GuiCharacter::applyView()
591 {
592         FontInfo & fi = font_.fontInfo();
593         fi.setFamily(family[familyCO->currentIndex()].second);
594         fi.setSeries(series[seriesCO->currentIndex()].second);
595         fi.setShape(shape[shapeCO->currentIndex()].second);
596         fi.setSize(size[sizeCO->currentIndex()].second);
597         fi.setEmph(setMarkupState(emphCB->checkState()));
598         fi.setNoun(setMarkupState(nounCB->checkState()));
599         fi.setNoSpellcheck(setMarkupState(nospellcheckCB->checkState()));
600         setBar(fi, bar[ulineCO->currentIndex()].second);
601         setStrike(fi, strike[strikeCO->currentIndex()].second);
602         fi.setColor(lcolor.getFromLyXName(fromqstr(colorCO->itemData(colorCO->currentIndex()).toString())));
603
604         font_.setLanguage(languages.getLanguage(
605                 fromqstr(language[langCO->currentIndex()].second)));
606 }
607
608
609 bool GuiCharacter::initialiseParams(string const &)
610 {
611         if (autoapplyCB->isChecked())
612                 return true;
613
614         FontInfo & fi = font_.fontInfo();
615
616         // so that the user can press Ok
617         if (fi.family()    != IGNORE_FAMILY
618             || fi.series() != IGNORE_SERIES
619             || fi.shape()  != IGNORE_SHAPE
620             || fi.size()   != FONT_SIZE_IGNORE
621             || getBar(fi)  != IGNORE
622             || fi.color()  != Color_ignore
623             || font_.language() != ignore_language)
624                 setButtonsValid(true);
625
626         paramsToDialog(font_);
627         // Make sure that the bc is in the INITIAL state
628         if (bc().policy().buttonStatus(ButtonPolicy::OKAY))
629                 bc().restore();
630         return true;
631 }
632
633
634 void GuiCharacter::dispatchParams()
635 {
636         dispatch(FuncRequest(getLfun(), font_.toString(false)));
637 }
638
639
640 void GuiCharacter::saveSession(QSettings & settings) const
641 {
642         Dialog::saveSession(settings);
643         settings.setValue(sessionKey() + "/autoapply", autoapplyCB->isChecked());
644 }
645
646
647 void GuiCharacter::restoreSession()
648 {
649         Dialog::restoreSession();
650         QSettings settings;
651         autoapplyCB->setChecked(
652                 settings.value(sessionKey() + "/autoapply").toBool());
653 }
654
655
656 Dialog * createGuiCharacter(GuiView & lv) { return new GuiCharacter(lv); }
657
658
659 } // namespace frontend
660 } // namespace lyx
661
662 #include "moc_GuiCharacter.cpp"