]> git.lyx.org Git - lyx.git/blob - src/frontends/qt4/GuiCharacter.cpp
PrefShortcuts: ShortcutEdit, adapted from Edwin's patch
[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  *
10  * Full author contact details are available in file CREDITS.
11  */
12
13 #include <config.h>
14
15 #include "GuiCharacter.h"
16
17 #include "qt_helpers.h"
18 #include "Color.h"
19 #include "Font.h"
20 #include "Buffer.h"
21 #include "BufferParams.h"
22 #include "FuncRequest.h"
23 #include "Language.h"
24 #include "Color.h"
25
26 #include <QCloseEvent>
27
28 using std::vector;
29 using std::string;
30
31
32 namespace lyx {
33 namespace frontend {
34
35 static vector<ShapePair> const getShapeData()
36 {
37         vector<ShapePair> shape(6);
38
39         ShapePair pr;
40
41         pr.first = qt_("No change");
42         pr.second = Font::IGNORE_SHAPE;
43         shape[0] = pr;
44
45         pr.first = qt_("Upright");
46         pr.second = Font::UP_SHAPE;
47         shape[1] = pr;
48
49         pr.first = qt_("Italic");
50         pr.second = Font::ITALIC_SHAPE;
51         shape[2] = pr;
52
53         pr.first = qt_("Slanted");
54         pr.second = Font::SLANTED_SHAPE;
55         shape[3] = pr;
56
57         pr.first = qt_("Small Caps");
58         pr.second = Font::SMALLCAPS_SHAPE;
59         shape[4] = pr;
60
61         pr.first = qt_("Reset");
62         pr.second = Font::INHERIT_SHAPE;
63         shape[5] = pr;
64
65         return shape;
66 }
67
68
69 static vector<SizePair> const getSizeData()
70 {
71         vector<SizePair> size(14);
72
73         SizePair pr;
74
75         pr.first = qt_("No change");
76         pr.second = Font::IGNORE_SIZE;
77         size[0] = pr;
78
79         pr.first = qt_("Tiny");
80         pr.second = Font::SIZE_TINY;
81         size[1] = pr;
82
83         pr.first = qt_("Smallest");
84         pr.second = Font::SIZE_SCRIPT;
85         size[2] = pr;
86
87         pr.first = qt_("Smaller");
88         pr.second = Font::SIZE_FOOTNOTE;
89         size[3] = pr;
90
91         pr.first = qt_("Small");
92         pr.second = Font::SIZE_SMALL;
93         size[4] = pr;
94
95         pr.first = qt_("Normal");
96         pr.second = Font::SIZE_NORMAL;
97         size[5] = pr;
98
99         pr.first = qt_("Large");
100         pr.second = Font::SIZE_LARGE;
101         size[6] = pr;
102
103         pr.first = qt_("Larger");
104         pr.second = Font::SIZE_LARGER;
105         size[7] = pr;
106
107         pr.first = qt_("Largest");
108         pr.second = Font::SIZE_LARGEST;
109         size[8] = pr;
110
111         pr.first = qt_("Huge");
112         pr.second = Font::SIZE_HUGE;
113         size[9] = pr;
114
115         pr.first = qt_("Huger");
116         pr.second = Font::SIZE_HUGER;
117         size[10] = pr;
118
119         pr.first = qt_("Increase");
120         pr.second = Font::INCREASE_SIZE;
121         size[11] = pr;
122
123         pr.first = qt_("Decrease");
124         pr.second = Font::DECREASE_SIZE;
125         size[12] = pr;
126
127         pr.first = qt_("Reset");
128         pr.second = Font::INHERIT_SIZE;
129         size[13] = pr;
130
131         return size;
132 }
133
134
135 static vector<BarPair> const getBarData()
136 {
137         vector<BarPair> bar(5);
138
139         BarPair pr;
140
141         pr.first = qt_("No change");
142         pr.second = IGNORE;
143         bar[0] = pr;
144
145         pr.first = qt_("Emph");
146         pr.second = EMPH_TOGGLE;
147         bar[1] = pr;
148
149         pr.first = qt_("Underbar");
150         pr.second = UNDERBAR_TOGGLE;
151         bar[2] = pr;
152
153         pr.first = qt_("Noun");
154         pr.second = NOUN_TOGGLE;
155         bar[3] = pr;
156
157         pr.first = qt_("Reset");
158         pr.second = INHERIT;
159         bar[4] = pr;
160
161         return bar;
162 }
163
164
165 static vector<ColorPair> const getColorData()
166 {
167         vector<ColorPair> color(11);
168
169         ColorPair pr;
170
171         pr.first = qt_("No change");
172         pr.second = Color::ignore;
173         color[0] = pr;
174
175         pr.first = qt_("No color");
176         pr.second = Color::none;
177         color[1] = pr;
178
179         pr.first = qt_("Black");
180         pr.second = Color::black;
181         color[2] = pr;
182
183         pr.first = qt_("White");
184         pr.second = Color::white;
185         color[3] = pr;
186
187         pr.first = qt_("Red");
188         pr.second = Color::red;
189         color[4] = pr;
190
191         pr.first = qt_("Green");
192         pr.second = Color::green;
193         color[5] = pr;
194
195         pr.first = qt_("Blue");
196         pr.second = Color::blue;
197         color[6] = pr;
198
199         pr.first = qt_("Cyan");
200         pr.second = Color::cyan;
201         color[7] = pr;
202
203         pr.first = qt_("Magenta");
204         pr.second = Color::magenta;
205         color[8] = pr;
206
207         pr.first = qt_("Yellow");
208         pr.second = Color::yellow;
209         color[9] = pr;
210
211         pr.first = qt_("Reset");
212         pr.second = Color::inherit;
213         color[10] = pr;
214
215         return color;
216 }
217
218
219 static vector<SeriesPair> const getSeriesData()
220 {
221         vector<SeriesPair> series(4);
222
223         SeriesPair pr;
224
225         pr.first = qt_("No change");
226         pr.second = Font::IGNORE_SERIES;
227         series[0] = pr;
228
229         pr.first = qt_("Medium");
230         pr.second = Font::MEDIUM_SERIES;
231         series[1] = pr;
232
233         pr.first = qt_("Bold");
234         pr.second = Font::BOLD_SERIES;
235         series[2] = pr;
236
237         pr.first = qt_("Reset");
238         pr.second = Font::INHERIT_SERIES;
239         series[3] = pr;
240
241         return series;
242 }
243
244
245 static vector<FamilyPair> const getFamilyData()
246 {
247         vector<FamilyPair> family(5);
248
249         FamilyPair pr;
250
251         pr.first = qt_("No change");
252         pr.second = Font::IGNORE_FAMILY;
253         family[0] = pr;
254
255         pr.first = qt_("Roman");
256         pr.second = Font::ROMAN_FAMILY;
257         family[1] = pr;
258
259         pr.first = qt_("Sans Serif");
260         pr.second = Font::SANS_FAMILY;
261         family[2] = pr;
262
263         pr.first = qt_("Typewriter");
264         pr.second = Font::TYPEWRITER_FAMILY;
265         family[3] = pr;
266
267         pr.first = qt_("Reset");
268         pr.second = Font::INHERIT_FAMILY;
269         family[4] = pr;
270
271         return family;
272 }
273
274
275 GuiCharacter::GuiCharacter(LyXView & lv)
276         : GuiDialog(lv, "character"), font_(Font::ALL_IGNORE),
277           toggleall_(false), reset_lang_(false)
278 {
279         setupUi(this);
280         setViewTitle(_("Text Style"));
281
282         connect(okPB, SIGNAL(clicked()), this, SLOT(slotOK()));
283         connect(applyPB, SIGNAL(clicked()), this, SLOT(slotApply()));
284         connect(closePB, SIGNAL(clicked()), this, SLOT(slotClose()));
285
286         connect(miscCO, SIGNAL(activated(int)), this, SLOT(change_adaptor()));
287         connect(sizeCO, SIGNAL(activated(int)), this, SLOT(change_adaptor()));
288         connect(familyCO, SIGNAL(activated(int)), this, SLOT(change_adaptor()));
289         connect(seriesCO, SIGNAL(activated(int)), this, SLOT(change_adaptor()));
290         connect(shapeCO, SIGNAL(activated(int)), this, SLOT(change_adaptor()));
291         connect(colorCO, SIGNAL(activated(int)), this, SLOT(change_adaptor()));
292         connect(langCO, SIGNAL(activated(int)), this, SLOT(change_adaptor()));
293         connect(toggleallCB, SIGNAL(clicked()), this, SLOT(change_adaptor()));
294
295         family = getFamilyData();
296         series = getSeriesData();
297         shape  = getShapeData();
298         size   = getSizeData();
299         bar    = getBarData();
300         color  = getColorData();
301         language = getLanguageData(true);
302
303         for (vector<FamilyPair>::const_iterator cit = family.begin();
304                 cit != family.end(); ++cit) {
305                 familyCO->addItem(cit->first);
306         }
307
308         for (vector<SeriesPair>::const_iterator cit = series.begin();
309                 cit != series.end(); ++cit) {
310                 seriesCO->addItem(cit->first);
311         }
312         for (vector<ShapePair>::const_iterator cit = shape.begin();
313                 cit != shape.end(); ++cit) {
314                 shapeCO->addItem(cit->first);
315         }
316         for (vector<SizePair>::const_iterator cit = size.begin();
317                 cit != size.end(); ++cit) {
318                 sizeCO->addItem(cit->first);
319         }
320         for (vector<BarPair>::const_iterator cit = bar.begin();
321                 cit != bar.end(); ++cit) {
322                 miscCO->addItem(cit->first);
323         }
324         for (vector<ColorPair>::const_iterator cit = color.begin();
325                 cit != color.end(); ++cit) {
326                 colorCO->addItem(cit->first);
327         }
328         for (vector<LanguagePair>::const_iterator cit = language.begin();
329                 cit != language.end(); ++cit) {
330                 langCO->addItem(toqstr(cit->first));
331         }
332
333         bc().setPolicy(ButtonPolicy::OkApplyCancelReadOnlyPolicy);
334         bc().setOK(okPB);
335         bc().setApply(applyPB);
336         bc().setCancel(closePB);
337         bc().addReadOnly(familyCO);
338         bc().addReadOnly(seriesCO);
339         bc().addReadOnly(sizeCO);
340         bc().addReadOnly(shapeCO);
341         bc().addReadOnly(miscCO);
342         bc().addReadOnly(langCO);
343         bc().addReadOnly(colorCO);
344         bc().addReadOnly(toggleallCB);
345         bc().addReadOnly(autoapplyCB);
346
347 // FIXME: hack to work around resizing bug in Qt >= 4.2
348 // bug verified with Qt 4.2.{0-3} (JSpitzm)
349 #if QT_VERSION >= 0x040200
350         // qt resizes the comboboxes only after show(), so ...
351         QDialog::show();
352 #endif
353 }
354
355
356 void GuiCharacter::change_adaptor()
357 {
358         changed();
359
360         if (!autoapplyCB->isChecked())
361                 return;
362
363         // to be really good here, we should set the combos to the values of
364         // the current text, and make it appear as "no change" if the values
365         // stay the same between applys. Might be difficult though wrt to a
366         // moved cursor - jbl
367         slotApply();
368         familyCO->setCurrentIndex(0);
369         seriesCO->setCurrentIndex(0);
370         sizeCO->setCurrentIndex(0);
371         shapeCO->setCurrentIndex(0);
372         miscCO->setCurrentIndex(0);
373         langCO->setCurrentIndex(0);
374         colorCO->setCurrentIndex(0);
375 }
376
377
378 void GuiCharacter::closeEvent(QCloseEvent * e)
379 {
380         slotClose();
381         GuiDialog::closeEvent(e);
382 }
383
384
385 template<class A, class B>
386 static int findPos2nd(vector<std::pair<A, B> > const & vec, B const & val)
387 {
388         typedef typename vector<std::pair<A, B> >::const_iterator
389                 const_iterator;
390
391         for (const_iterator cit = vec.begin(); cit != vec.end(); ++cit)
392                 if (cit->second == val)
393                         return int(cit - vec.begin());
394
395         return 0;
396 }
397
398
399 void GuiCharacter::updateContents()
400 {
401         familyCO->setCurrentIndex(findPos2nd(family, getFamily()));
402         seriesCO->setCurrentIndex(findPos2nd(series, getSeries()));
403         shapeCO->setCurrentIndex(findPos2nd(shape, getShape()));
404         sizeCO->setCurrentIndex(findPos2nd(size, getSize()));
405         miscCO->setCurrentIndex(findPos2nd(bar, getBar()));
406         colorCO->setCurrentIndex(findPos2nd(color, getColor()));
407         langCO->setCurrentIndex(findPos2nd(language, getLanguage()));
408
409         toggleallCB->setChecked(toggleall_);
410 }
411
412
413 void GuiCharacter::applyView()
414 {
415         setFamily(family[familyCO->currentIndex()].second);
416         setSeries(series[seriesCO->currentIndex()].second);
417         setShape(shape[shapeCO->currentIndex()].second);
418         setSize(size[sizeCO->currentIndex()].second);
419         setBar(bar[miscCO->currentIndex()].second);
420         setColor(color[colorCO->currentIndex()].second);
421         setLanguage(language[langCO->currentIndex()].second);
422
423         toggleall_ = toggleallCB->isChecked();
424 }
425
426
427 bool GuiCharacter::initialiseParams(string const &)
428 {
429         // so that the user can press Ok
430         if (getFamily()    != Font::IGNORE_FAMILY
431             || getSeries() != Font::IGNORE_SERIES
432             || getShape()  != Font::IGNORE_SHAPE
433             || getSize()   != Font::IGNORE_SIZE
434             || getBar()    != IGNORE
435             || getColor()  != Color::ignore
436             || font_.language() != ignore_language)
437                 setButtonsValid(true);
438
439         return true;
440 }
441
442
443 void GuiCharacter::dispatchParams()
444 {
445         dispatch(FuncRequest(getLfun(), font_.toString(toggleall_)));
446 }
447
448
449 Font::FONT_FAMILY GuiCharacter::getFamily() const
450 {
451         return font_.family();
452 }
453
454
455 void GuiCharacter::setFamily(Font::FONT_FAMILY val)
456 {
457         font_.setFamily(val);
458 }
459
460
461 Font::FONT_SERIES GuiCharacter::getSeries() const
462 {
463         return font_.series();
464 }
465
466
467 void GuiCharacter::setSeries(Font::FONT_SERIES val)
468 {
469         font_.setSeries(val);
470 }
471
472
473 Font::FONT_SHAPE GuiCharacter::getShape() const
474 {
475         return font_.shape();
476 }
477
478
479 void GuiCharacter::setShape(Font::FONT_SHAPE val)
480 {
481         font_.setShape(val);
482 }
483
484
485 Font::FONT_SIZE GuiCharacter::getSize() const
486 {
487         return font_.size();
488 }
489
490
491 void GuiCharacter::setSize(Font::FONT_SIZE val)
492 {
493         font_.setSize(val);
494 }
495
496
497 FontState GuiCharacter::getBar() const
498 {
499         if (font_.emph() == Font::TOGGLE)
500                 return EMPH_TOGGLE;
501
502         if (font_.underbar() == Font::TOGGLE)
503                 return UNDERBAR_TOGGLE;
504
505         if (font_.noun() == Font::TOGGLE)
506                 return NOUN_TOGGLE;
507
508         if (font_.emph() == Font::IGNORE
509             && font_.underbar() == Font::IGNORE
510             && font_.noun() == Font::IGNORE)
511                 return IGNORE;
512
513         return INHERIT;
514 }
515
516
517 void GuiCharacter::setBar(FontState val)
518 {
519         switch (val) {
520         case IGNORE:
521                 font_.setEmph(Font::IGNORE);
522                 font_.setUnderbar(Font::IGNORE);
523                 font_.setNoun(Font::IGNORE);
524                 break;
525
526         case EMPH_TOGGLE:
527                 font_.setEmph(Font::TOGGLE);
528                 break;
529
530         case UNDERBAR_TOGGLE:
531                 font_.setUnderbar(Font::TOGGLE);
532                 break;
533
534         case NOUN_TOGGLE:
535                 font_.setNoun(Font::TOGGLE);
536                 break;
537
538         case INHERIT:
539                 font_.setEmph(Font::INHERIT);
540                 font_.setUnderbar(Font::INHERIT);
541                 font_.setNoun(Font::INHERIT);
542                 break;
543         }
544 }
545
546
547 Color_color GuiCharacter::getColor() const
548 {
549         return font_.color();
550 }
551
552
553 void GuiCharacter::setColor(Color_color val)
554 {
555         switch (val) {
556         case Color::ignore:
557         case Color::none:
558         case Color::black:
559         case Color::white:
560         case Color::red:
561         case Color::green:
562         case Color::blue:
563         case Color::cyan:
564         case Color::magenta:
565         case Color::yellow:
566         case Color::inherit:
567                 font_.setColor(val);
568                 break;
569         default:
570                 break;
571         }
572 }
573
574
575 string GuiCharacter::getLanguage() const
576 {
577         if (reset_lang_)
578                 return "reset";
579         if (font_.language())
580                 return font_.language()->lang();
581         return "ignore";
582 }
583
584
585 void GuiCharacter::setLanguage(string const & val)
586 {
587         if (val == "ignore")
588                 font_.setLanguage(ignore_language);
589         else if (val == "reset") {
590                 reset_lang_ = true;
591                 // Ignored in getLanguage, but needed for dispatchParams
592                 font_.setLanguage(buffer().params().language);
593         } else {
594                 font_.setLanguage(languages.getLanguage(val));
595         }
596 }
597
598
599 Dialog * createGuiCharacter(LyXView & lv) { return new GuiCharacter(lv); }
600
601
602 } // namespace frontend
603 } // namespace lyx
604
605 #include "GuiCharacter_moc.cpp"