While assigning styles, handle glyph components of composites also.
[ttfautohint.git] / frontend / maingui.cpp
blob39256485979105d75acf802c02de5f322aec6a80
1 // maingui.cpp
3 // Copyright (C) 2012-2014 by Werner Lemberg.
4 //
5 // This file is part of the ttfautohint library, and may only be used,
6 // modified, and distributed under the terms given in `COPYING'. By
7 // continuing to use, modify, or distribute this file you indicate that you
8 // have read `COPYING' and understand and accept it fully.
9 //
10 // The file `COPYING' mentioned in the previous paragraph is distributed
11 // with the ttfautohint library.
14 #include <config.h>
16 #include <string.h>
17 #include <stdio.h>
18 #include <errno.h>
20 #include <QtGui>
22 #include "info.h"
23 #include "maingui.h"
25 #include <ttfautohint.h>
28 // XXX Qt 4.8 bug: locale->quoteString("foo")
29 // inserts wrongly encoded quote characters
30 // into rich text QString
31 #if HAVE_QT_QUOTESTRING
32 # define QUOTE_STRING(x) locale->quoteString(x)
33 # define QUOTE_STRING_LITERAL(x) locale->quoteString(x)
34 #else
35 # define QUOTE_STRING(x) "\"" + x + "\""
36 # define QUOTE_STRING_LITERAL(x) "\"" x "\""
37 #endif
40 // the available script tags and its descriptions are directly extracted
41 // from `ttfautohint-scripts.h'
42 typedef struct Script_Names_
44 const char* tag;
45 const char* description;
46 } Script_Names;
48 #undef SCRIPT
49 #define SCRIPT(s, S, d, h, sc1, sc2, sc3) \
50 {#s, d},
52 const Script_Names script_names[] =
54 #include <ttfautohint-scripts.h>
55 {NULL, NULL}
59 Main_GUI::Main_GUI(bool horizontal_layout,
60 int range_min,
61 int range_max,
62 int limit,
63 bool gray,
64 bool gdi,
65 bool dw,
66 int increase,
67 const char* exceptions,
68 bool ignore,
69 bool wincomp,
70 bool pre,
71 bool composites,
72 bool no,
73 const char* dflt,
74 const char* fallback,
75 bool symb,
76 bool dh)
77 : hinting_range_min(range_min),
78 hinting_range_max(range_max),
79 hinting_limit(limit),
80 gray_strong_stem_width(gray),
81 gdi_cleartype_strong_stem_width(gdi),
82 dw_cleartype_strong_stem_width(dw),
83 increase_x_height(increase),
84 x_height_snapping_exceptions_string(exceptions),
85 ignore_restrictions(ignore),
86 windows_compatibility(wincomp),
87 pre_hinting(pre),
88 hint_composites(composites),
89 no_info(no),
90 symbol(symb),
91 dehint(dh)
93 int i;
95 // map default script tag to an index,
96 // replacing an invalid one with the default value
97 int latn_script_idx = 0;
98 for (i = 0; script_names[i].tag; i++)
100 if (!strcmp("latn", script_names[i].tag))
101 latn_script_idx = i;
102 if (!strcmp(dflt, script_names[i].tag))
103 break;
105 default_script_idx = script_names[i].tag ? i : latn_script_idx;
107 // map fallback script tag to an index,
108 // replacing an invalid one with the default value
109 int none_script_idx = 0;
110 for (i = 0; script_names[i].tag; i++)
112 if (!strcmp("none", script_names[i].tag))
113 none_script_idx = i;
114 if (!strcmp(fallback, script_names[i].tag))
115 break;
117 fallback_script_idx = script_names[i].tag ? i : none_script_idx;
119 x_height_snapping_exceptions = NULL;
121 create_layout(horizontal_layout);
122 create_connections();
123 create_actions();
124 create_menus();
125 create_status_bar();
127 set_defaults();
128 read_settings();
130 setUnifiedTitleAndToolBarOnMac(true);
132 // XXX register translations somewhere and loop over them
133 if (QLocale::system().name() == "en_US")
134 locale = new QLocale;
135 else
136 locale = new QLocale(QLocale::C);
140 Main_GUI::~Main_GUI()
142 number_set_free(x_height_snapping_exceptions);
146 // overloading
148 void
149 Main_GUI::closeEvent(QCloseEvent* event)
151 write_settings();
152 event->accept();
156 void
157 Main_GUI::about()
159 QMessageBox::about(this,
160 tr("About TTFautohint"),
161 tr("<p>This is <b>TTFautohint</b> version %1<br>"
162 " Copyright %2 2011-2014<br>"
163 " by Werner Lemberg <tt>&lt;wl@gnu.org&gt;</tt></p>"
165 "<p><b>TTFautohint</b> adds new auto-generated hints"
166 " to a TrueType font or TrueType collection.</p>"
168 "<p>License:"
169 " <a href='http://www.freetype.org/FTL.TXT'>FreeType"
170 " License (FTL)</a> or"
171 " <a href='http://www.freetype.org/GPL.TXT'>GNU"
172 " GPLv2</a></p>")
173 .arg(VERSION)
174 .arg(QChar(0xA9)));
178 void
179 Main_GUI::browse_input()
181 // XXX remember last directory
182 QString file = QFileDialog::getOpenFileName(
183 this,
184 tr("Open Input File"),
185 QDir::homePath(),
186 "");
187 if (!file.isEmpty())
188 input_line->setText(QDir::toNativeSeparators(file));
192 void
193 Main_GUI::browse_output()
195 // XXX remember last directory
196 QString file = QFileDialog::getSaveFileName(
197 this,
198 tr("Open Output File"),
199 QDir::homePath(),
200 "");
202 if (!file.isEmpty())
203 output_line->setText(QDir::toNativeSeparators(file));
207 void
208 Main_GUI::check_min()
210 int min = min_box->value();
211 int max = max_box->value();
212 int limit = limit_box->value();
213 if (min > max)
214 max_box->setValue(min);
215 if (min > limit)
216 limit_box->setValue(min);
220 void
221 Main_GUI::check_max()
223 int min = min_box->value();
224 int max = max_box->value();
225 int limit = limit_box->value();
226 if (max < min)
227 min_box->setValue(max);
228 if (max > limit)
229 limit_box->setValue(max);
233 void
234 Main_GUI::check_limit()
236 int min = min_box->value();
237 int max = max_box->value();
238 int limit = limit_box->value();
239 if (limit < max)
240 max_box->setValue(limit);
241 if (limit < min)
242 min_box->setValue(limit);
246 void
247 Main_GUI::check_dehint()
249 if (dehint_box->isChecked())
251 min_label->setEnabled(false);
252 min_box->setEnabled(false);
254 max_label->setEnabled(false);
255 max_box->setEnabled(false);
257 default_label->setEnabled(false);
258 default_box->setEnabled(false);
259 fallback_label->setEnabled(false);
260 fallback_box->setEnabled(false);
262 no_limit_box->setEnabled(false);
263 limit_label->setEnabled(false);
264 limit_box->setEnabled(false);
266 no_increase_box->setEnabled(false);
267 increase_label->setEnabled(false);
268 increase_box->setEnabled(false);
270 snapping_label->setEnabled(false);
271 snapping_line->setEnabled(false);
273 wincomp_box->setEnabled(false);
274 pre_box->setEnabled(false);
275 hint_box->setEnabled(false);
276 symbol_box->setEnabled(false);
278 stem_label->setEnabled(false);
279 gray_box->setEnabled(false);
280 gdi_box->setEnabled(false);
281 dw_box->setEnabled(false);
283 else
285 min_label->setEnabled(true);
286 min_box->setEnabled(true);
288 max_label->setEnabled(true);
289 max_box->setEnabled(true);
291 default_label->setEnabled(true);
292 default_box->setEnabled(true);
293 fallback_label->setEnabled(true);
294 fallback_box->setEnabled(true);
296 no_limit_box->setEnabled(true);
297 check_no_limit();
299 no_increase_box->setEnabled(true);
300 check_no_increase();
302 snapping_label->setEnabled(true);
303 snapping_line->setEnabled(true);
305 wincomp_box->setEnabled(true);
306 pre_box->setEnabled(true);
307 hint_box->setEnabled(true);
308 symbol_box->setEnabled(true);
310 stem_label->setEnabled(true);
311 gray_box->setEnabled(true);
312 gdi_box->setEnabled(true);
313 dw_box->setEnabled(true);
318 void
319 Main_GUI::check_no_limit()
321 if (no_limit_box->isChecked())
323 limit_label->setEnabled(false);
324 limit_box->setEnabled(false);
326 else
328 limit_label->setEnabled(true);
329 limit_box->setEnabled(true);
334 void
335 Main_GUI::check_no_increase()
337 if (no_increase_box->isChecked())
339 increase_label->setEnabled(false);
340 increase_box->setEnabled(false);
342 else
344 increase_label->setEnabled(true);
345 increase_box->setEnabled(true);
350 void
351 Main_GUI::check_run()
353 if (input_line->text().isEmpty() || output_line->text().isEmpty())
354 run_button->setEnabled(false);
355 else
356 run_button->setEnabled(true);
360 void
361 Main_GUI::absolute_input()
363 QString input_name = QDir::fromNativeSeparators(input_line->text());
364 if (!input_name.isEmpty()
365 && QDir::isRelativePath(input_name))
367 QDir cur_path(QDir::currentPath() + "/" + input_name);
368 input_line->setText(QDir::toNativeSeparators(cur_path.absolutePath()));
373 void
374 Main_GUI::absolute_output()
376 QString output_name = QDir::fromNativeSeparators(output_line->text());
377 if (!output_name.isEmpty()
378 && QDir::isRelativePath(output_name))
380 QDir cur_path(QDir::currentPath() + "/" + output_name);
381 output_line->setText(QDir::toNativeSeparators(cur_path.absolutePath()));
386 void
387 Main_GUI::check_number_set()
389 QString text = snapping_line->text();
390 QString qs;
392 // construct ASCII string from arbitrary Unicode data;
393 // the idea is to accept, say, CJK fullwidth digits also
394 for (int i = 0; i < text.size(); i++)
396 QChar c = text.at(i);
398 int digit = c.digitValue();
399 if (digit >= 0)
400 qs += QString::number(digit);
401 else if (c.isSpace())
402 qs += ' ';
403 // U+30FC KATAGANA-HIRAGANA PROLONGED SOUND MARK is assigned
404 // to the `-' key in some Japanese input methods
405 else if (c.category() == QChar::Punctuation_Dash
406 || c == QChar(0x30FC))
407 qs += '-';
408 // various Unicode COMMA characters,
409 // including representation forms
410 else if (c == QChar(',')
411 || c == QChar(0x055D)
412 || c == QChar(0x060C)
413 || c == QChar(0x07F8)
414 || c == QChar(0x1363)
415 || c == QChar(0x1802)
416 || c == QChar(0x1808)
417 || c == QChar(0x3001)
418 || c == QChar(0xA4FE)
419 || c == QChar(0xA60D)
420 || c == QChar(0xA6F5)
421 || c == QChar(0xFE10)
422 || c == QChar(0xFE11)
423 || c == QChar(0xFE50)
424 || c == QChar(0xFE51)
425 || c == QChar(0xFF0C)
426 || c == QChar(0xFF64))
427 qs += ',';
428 else
429 qs += c; // we do error handling below
432 if (x_height_snapping_exceptions)
433 number_set_free(x_height_snapping_exceptions);
435 QByteArray str = qs.toLocal8Bit();
436 const char* s = number_set_parse(str.constData(),
437 &x_height_snapping_exceptions,
438 6, 0x7FFF);
439 if (s && *s)
441 statusBar()->setStyleSheet("color: red;");
442 if (x_height_snapping_exceptions == NUMBERSET_ALLOCATION_ERROR)
443 statusBar()->showMessage(
444 tr("allocation error"));
445 else if (x_height_snapping_exceptions == NUMBERSET_INVALID_CHARACTER)
446 statusBar()->showMessage(
447 tr("invalid character (use digits, dashes, commas, and spaces)"));
448 else if (x_height_snapping_exceptions == NUMBERSET_OVERFLOW)
449 statusBar()->showMessage(
450 tr("overflow"));
451 else if (x_height_snapping_exceptions == NUMBERSET_INVALID_RANGE)
452 statusBar()->showMessage(
453 tr("invalid range (minimum is 6, maximum is 32767)"));
454 else if (x_height_snapping_exceptions == NUMBERSET_OVERLAPPING_RANGES)
455 statusBar()->showMessage(
456 tr("overlapping ranges"));
457 else if (x_height_snapping_exceptions == NUMBERSET_NOT_ASCENDING)
458 statusBar()->showMessage(
459 tr("values und ranges must be specified in ascending order"));
461 snapping_line->setText(qs);
462 snapping_line->setFocus(Qt::OtherFocusReason);
463 snapping_line->setCursorPosition(s - str.constData());
465 x_height_snapping_exceptions = NULL;
467 else
469 // normalize if there is no error
470 char* new_str = number_set_show(x_height_snapping_exceptions,
471 6, 0x7FFF);
472 snapping_line->setText(new_str);
473 free(new_str);
478 void
479 Main_GUI::clear_status_bar()
481 statusBar()->clearMessage();
482 statusBar()->setStyleSheet("");
487 Main_GUI::check_filenames(const QString& input_name,
488 const QString& output_name)
490 if (!QFile::exists(input_name))
492 QMessageBox::warning(
493 this,
494 "TTFautohint",
495 tr("The file %1 cannot be found.")
496 .arg(QUOTE_STRING(QDir::toNativeSeparators(input_name))),
497 QMessageBox::Ok,
498 QMessageBox::Ok);
499 return 0;
502 if (input_name == output_name)
504 QMessageBox::warning(
505 this,
506 "TTFautohint",
507 tr("Input and output file names must be different."),
508 QMessageBox::Ok,
509 QMessageBox::Ok);
510 return 0;
513 if (QFile::exists(output_name))
515 int ret = QMessageBox::warning(
516 this,
517 "TTFautohint",
518 tr("The file %1 already exists.\n"
519 "Overwrite?")
520 .arg(QUOTE_STRING(QDir::toNativeSeparators(output_name))),
521 QMessageBox::Yes | QMessageBox::No,
522 QMessageBox::No);
523 if (ret == QMessageBox::No)
524 return 0;
527 return 1;
532 Main_GUI::open_files(const QString& input_name,
533 FILE** in,
534 const QString& output_name,
535 FILE** out)
537 const int buf_len = 1024;
538 char buf[buf_len];
540 *in = fopen(qPrintable(input_name), "rb");
541 if (!*in)
543 strerror_r(errno, buf, buf_len);
544 QMessageBox::warning(
545 this,
546 "TTFautohint",
547 tr("The following error occurred while opening input file %1:\n")
548 .arg(QUOTE_STRING(QDir::toNativeSeparators(input_name)))
549 + QString::fromLocal8Bit(buf),
550 QMessageBox::Ok,
551 QMessageBox::Ok);
552 return 0;
555 *out = fopen(qPrintable(output_name), "wb");
556 if (!*out)
558 strerror_r(errno, buf, buf_len);
559 QMessageBox::warning(
560 this,
561 "TTFautohint",
562 tr("The following error occurred while opening output file %1:\n")
563 .arg(QUOTE_STRING(QDir::toNativeSeparators(output_name)))
564 + QString::fromLocal8Bit(buf),
565 QMessageBox::Ok,
566 QMessageBox::Ok);
567 return 0;
570 return 1;
574 extern "C" {
576 struct GUI_Progress_Data
578 long last_sfnt;
579 bool begin;
580 QProgressDialog* dialog;
585 gui_progress(long curr_idx,
586 long num_glyphs,
587 long curr_sfnt,
588 long num_sfnts,
589 void* user)
591 GUI_Progress_Data* data = static_cast<GUI_Progress_Data*>(user);
593 if (num_sfnts > 1 && curr_sfnt != data->last_sfnt)
595 data->dialog->setLabelText(QCoreApplication::translate(
596 "GuiProgress",
597 "Auto-hinting subfont %1 of %2"
598 " with %3 glyphs...")
599 .arg(curr_sfnt + 1)
600 .arg(num_sfnts)
601 .arg(num_glyphs));
603 if (curr_sfnt + 1 == num_sfnts)
605 data->dialog->setAutoReset(true);
606 data->dialog->setAutoClose(true);
608 else
610 data->dialog->setAutoReset(false);
611 data->dialog->setAutoClose(false);
614 data->last_sfnt = curr_sfnt;
615 data->begin = true;
618 if (data->begin)
620 if (num_sfnts == 1)
621 data->dialog->setLabelText(QCoreApplication::translate(
622 "GuiProgress",
623 "Auto-hinting %1 glyphs...")
624 .arg(num_glyphs));
625 data->dialog->setMaximum(num_glyphs - 1);
627 data->begin = false;
630 data->dialog->setValue(curr_idx);
632 if (data->dialog->wasCanceled())
633 return 1;
635 return 0;
638 } // extern "C"
641 // return value 1 indicates a retry
644 Main_GUI::handle_error(TA_Error error,
645 const unsigned char* error_string,
646 QString output_name)
648 int ret = 0;
650 if (error == TA_Err_Canceled)
652 else if (error == TA_Err_Invalid_FreeType_Version)
653 QMessageBox::critical(
654 this,
655 "TTFautohint",
656 tr("FreeType version 2.4.5 or higher is needed.\n"
657 "Are you perhaps using a wrong FreeType DLL?"),
658 QMessageBox::Ok,
659 QMessageBox::Ok);
660 else if (error == TA_Err_Invalid_Font_Type)
661 QMessageBox::warning(
662 this,
663 "TTFautohint",
664 tr("This font is not a valid font"
665 " in SFNT format with TrueType outlines.\n"
666 "In particular, CFF outlines are not supported."),
667 QMessageBox::Ok,
668 QMessageBox::Ok);
669 else if (error == TA_Err_Already_Processed)
670 QMessageBox::warning(
671 this,
672 "TTFautohint",
673 tr("This font has already been processed by TTFautohint."),
674 QMessageBox::Ok,
675 QMessageBox::Ok);
676 else if (error == TA_Err_Missing_Legal_Permission)
678 int yesno = QMessageBox::warning(
679 this,
680 "TTFautohint",
681 tr("Bit 1 in the %1 field of the %2 table is set:"
682 " This font must not be modified"
683 " without permission of the legal owner.\n"
684 "Do you have such a permission?")
685 .arg(QUOTE_STRING_LITERAL("fsType"))
686 .arg(QUOTE_STRING_LITERAL("OS/2")),
687 QMessageBox::Yes | QMessageBox::No,
688 QMessageBox::No);
689 if (yesno == QMessageBox::Yes)
691 ignore_restrictions = true;
692 ret = 1;
695 else if (error == TA_Err_Missing_Unicode_CMap)
696 QMessageBox::warning(
697 this,
698 "TTFautohint",
699 tr("No Unicode character map."),
700 QMessageBox::Ok,
701 QMessageBox::Ok);
702 else if (error == TA_Err_Missing_Symbol_CMap)
703 QMessageBox::warning(
704 this,
705 "TTFautohint",
706 tr("No symbol character map."),
707 QMessageBox::Ok,
708 QMessageBox::Ok);
709 else if (error == TA_Err_Missing_Glyph)
710 QMessageBox::warning(
711 this,
712 "TTFautohint",
713 tr("No glyph for a standard character"
714 " to derive standard width and height.\n"
715 "Please check the documentation for a list of"
716 " script-specific standard characters.\n"
717 "\n"
718 "Set the %1 checkbox if you want to circumvent this test.")
719 .arg(QUOTE_STRING_LITERAL("symbol")),
720 QMessageBox::Ok,
721 QMessageBox::Ok);
722 else
723 QMessageBox::warning(
724 this,
725 "TTFautohint",
726 tr("Error code 0x%1 while autohinting font:\n")
727 .arg(error, 2, 16, QLatin1Char('0'))
728 + QString::fromLocal8Bit((const char*)error_string),
729 QMessageBox::Ok,
730 QMessageBox::Ok);
732 if (QFile::exists(output_name) && remove(qPrintable(output_name)))
734 const int buf_len = 1024;
735 char buf[buf_len];
737 strerror_r(errno, buf, buf_len);
738 QMessageBox::warning(
739 this,
740 "TTFautohint",
741 tr("The following error occurred while removing output file %1:\n")
742 .arg(QUOTE_STRING(QDir::toNativeSeparators(output_name)))
743 + QString::fromLocal8Bit(buf),
744 QMessageBox::Ok,
745 QMessageBox::Ok);
748 return ret;
752 void
753 Main_GUI::run()
755 statusBar()->clearMessage();
757 QString input_name = QDir::fromNativeSeparators(input_line->text());
758 QString output_name = QDir::fromNativeSeparators(output_line->text());
759 if (!check_filenames(input_name, output_name))
760 return;
762 // we need C file descriptors for communication with TTF_autohint
763 FILE* input;
764 FILE* output;
766 again:
767 if (!open_files(input_name, &input, output_name, &output))
768 return;
770 QProgressDialog dialog;
771 dialog.setCancelButtonText(tr("Cancel"));
772 dialog.setMinimumDuration(1000);
773 dialog.setWindowModality(Qt::WindowModal);
775 const unsigned char* error_string;
776 TA_Info_Func info_func = info;
777 GUI_Progress_Data gui_progress_data = {-1, true, &dialog};
778 Info_Data info_data;
780 info_data.data = NULL; // must be deallocated after use
781 info_data.data_wide = NULL; // must be deallocated after use
782 info_data.data_len = 0;
783 info_data.data_wide_len = 0;
785 info_data.hinting_range_min = min_box->value();
786 info_data.hinting_range_max = max_box->value();
787 info_data.hinting_limit = no_limit_box->isChecked()
789 : limit_box->value();
791 info_data.gray_strong_stem_width = gray_box->isChecked();
792 info_data.gdi_cleartype_strong_stem_width = gdi_box->isChecked();
793 info_data.dw_cleartype_strong_stem_width = dw_box->isChecked();
795 info_data.increase_x_height = no_increase_box->isChecked()
797 : increase_box->value();
798 info_data.x_height_snapping_exceptions = x_height_snapping_exceptions;
800 info_data.windows_compatibility = wincomp_box->isChecked();
801 info_data.pre_hinting = pre_box->isChecked();
802 info_data.hint_composites = hint_box->isChecked();
803 info_data.symbol = symbol_box->isChecked();
804 info_data.dehint = dehint_box->isChecked();
806 strncpy(info_data.default_script,
807 script_names[default_box->currentIndex()].tag,
808 sizeof (info_data.default_script));
809 strncpy(info_data.fallback_script,
810 script_names[fallback_box->currentIndex()].tag,
811 sizeof (info_data.fallback_script));
813 if (info_box->isChecked())
815 int ret = build_version_string(&info_data);
816 if (ret == 1)
817 QMessageBox::information(
818 this,
819 "TTFautohint",
820 tr("Can't allocate memory for <b>TTFautohint</b> options string"
821 " in <i>name</i> table."),
822 QMessageBox::Ok,
823 QMessageBox::Ok);
824 else if (ret == 2)
825 QMessageBox::information(
826 this,
827 "TTFautohint",
828 tr("<b>TTFautohint</b> options string"
829 " in <i>name</i> table too long."),
830 QMessageBox::Ok,
831 QMessageBox::Ok);
833 else
834 info_func = NULL;
836 QByteArray snapping_string = snapping_line->text().toLocal8Bit();
838 TA_Error error =
839 TTF_autohint("in-file, out-file,"
840 "hinting-range-min, hinting-range-max,"
841 "hinting-limit,"
842 "gray-strong-stem-width,"
843 "gdi-cleartype-strong-stem-width,"
844 "dw-cleartype-strong-stem-width,"
845 "error-string,"
846 "progress-callback, progress-callback-data,"
847 "info-callback, info-callback-data,"
848 "ignore-restrictions,"
849 "windows-compatibility,"
850 "pre-hinting,"
851 "hint-composites,"
852 "increase-x-height,"
853 "x-height-snapping-exceptions,"
854 "default-script, fallback-script,"
855 "symbol, dehint",
856 input, output,
857 info_data.hinting_range_min, info_data.hinting_range_max,
858 info_data.hinting_limit,
859 info_data.gray_strong_stem_width,
860 info_data.gdi_cleartype_strong_stem_width,
861 info_data.dw_cleartype_strong_stem_width,
862 &error_string,
863 gui_progress, &gui_progress_data,
864 info_func, &info_data,
865 ignore_restrictions,
866 info_data.windows_compatibility,
867 info_data.pre_hinting,
868 info_data.hint_composites,
869 info_data.increase_x_height,
870 snapping_string.constData(),
871 info_data.default_script, info_data.fallback_script,
872 info_data.symbol, info_data.dehint);
874 if (info_box->isChecked())
876 free(info_data.data);
877 free(info_data.data_wide);
880 fclose(input);
881 fclose(output);
883 if (error)
885 if (handle_error(error, error_string, output_name))
886 goto again;
888 else
889 statusBar()->showMessage(tr("Auto-hinting finished."));
893 // XXX distances are specified in pixels,
894 // making the layout dependent on the output device resolution
895 void
896 Main_GUI::create_layout(bool horizontal_layout)
899 // file stuff
901 QCompleter* completer = new QCompleter(this);
902 QFileSystemModel* model = new QFileSystemModel(completer);
903 model->setRootPath(QDir::rootPath());
904 completer->setModel(model);
906 input_label = new QLabel(tr("&Input File:"));
907 input_line = new Drag_Drop_Line_Edit;
908 input_button = new QPushButton(tr("Browse..."));
909 input_label->setBuddy(input_line);
910 // enforce rich text to get nice word wrapping
911 input_label->setToolTip(
912 tr("<b></b>The input file, either a TrueType font (TTF),"
913 " TrueType collection (TTC), or a TrueType-based OpenType font."));
914 input_line->setCompleter(completer);
916 output_label = new QLabel(tr("&Output File:"));
917 output_line = new Drag_Drop_Line_Edit;
918 output_button = new QPushButton(tr("Browse..."));
919 output_label->setBuddy(output_line);
920 output_label->setToolTip(
921 tr("<b></b>The output file, which will be essentially identical"
922 " to the input font but will contain new, generated hints."));
923 output_line->setCompleter(completer);
926 // minmax controls
928 min_label = new QLabel(tr("Hint Set Range Mi&nimum:"));
929 min_box = new QSpinBox;
930 min_label->setBuddy(min_box);
931 min_label->setToolTip(
932 tr("The minimum PPEM value of the range for which"
933 " <b>TTFautohint</b> computes <i>hint sets</i>."
934 " A hint set for a given PPEM value hints this size optimally."
935 " The larger the range, the more hint sets are considered,"
936 " usually increasing the size of the bytecode.<br>"
937 "Note that changing this range doesn't influence"
938 " the <i>gasp</i> table:"
939 " Hinting is enabled for all sizes."));
940 min_box->setKeyboardTracking(false);
941 min_box->setRange(2, 10000);
943 max_label = new QLabel(tr("Hint Set Range Ma&ximum:"));
944 max_box = new QSpinBox;
945 max_label->setBuddy(max_box);
946 max_label->setToolTip(
947 tr("The maximum PPEM value of the range for which"
948 " <b>TTFautohint</b> computes <i>hint sets</i>."
949 " A hint set for a given PPEM value hints this size optimally."
950 " The larger the range, the more hint sets are considered,"
951 " usually increasing the size of the bytecode.<br>"
952 "Note that changing this range doesn't influence"
953 " the <i>gasp</i> table:"
954 " Hinting is enabled for all sizes."));
955 max_box->setKeyboardTracking(false);
956 max_box->setRange(2, 10000);
959 // OpenType default script
961 default_label = new QLabel(tr("Defa&ult Script:"));
962 default_box = new QComboBox;
963 default_label->setBuddy(default_box);
964 default_label->setToolTip(
965 tr("This sets the default script for OpenType features:"
966 " After applying all features that are handled specially"
967 " (for example small caps or superscript glyphs),"
968 " <b>TTFautohint</b> uses this value for the remaining features."));
969 for (int i = 0; script_names[i].tag; i++)
971 // XXX: how to provide translations?
972 default_box->insertItem(i,
973 QString("%1 (%2)")
974 .arg(script_names[i].tag)
975 .arg(script_names[i].description));
979 // hinting and fallback controls
981 fallback_label = new QLabel(tr("Fallback &Script:"));
982 fallback_box = new QComboBox;
983 fallback_label->setBuddy(fallback_box);
984 fallback_label->setToolTip(
985 tr("This sets the fallback script for glyphs"
986 " that <b>TTFautohint</b> can't map to a script automatically."));
987 for (int i = 0; script_names[i].tag; i++)
989 // XXX: how to provide translations?
990 fallback_box->insertItem(i,
991 QString("%1 (%2)")
992 .arg(script_names[i].tag)
993 .arg(script_names[i].description));
997 // hinting limit
999 limit_label = new QLabel(tr("Hinting &Limit:"));
1000 limit_box = new QSpinBox;
1001 limit_label->setBuddy(limit_box);
1002 limit_label->setToolTip(
1003 tr("Make <b>TTFautohint</b> add bytecode to the output font so that"
1004 " sizes larger than this PPEM value are not hinted"
1005 " (regardless of the values in the <i>gasp</i> table)."));
1006 limit_box->setKeyboardTracking(false);
1007 limit_box->setRange(2, 10000);
1009 no_limit_box = new QCheckBox(tr("No Hinting Limit"), this);
1010 no_limit_box->setToolTip(
1011 tr("If switched on, <b>TTFautohint</b> adds no hinting limit"
1012 " to the bytecode."));
1015 // x height increase limit
1017 increase_label = new QLabel(tr("x Height In&crease Limit:"));
1018 increase_box = new QSpinBox;
1019 increase_label->setBuddy(increase_box);
1020 increase_label->setToolTip(
1021 tr("For PPEM values in the range 5&nbsp;&lt; PPEM &lt;&nbsp;<i>n</i>,"
1022 " where <i>n</i> is the value selected by this spin box,"
1023 " round up the font's x&nbsp;height much more often than normally.<br>"
1024 "Use this if holes in letters like <i>e</i> get filled,"
1025 " for example."));
1026 increase_box->setKeyboardTracking(false);
1027 increase_box->setRange(6, 10000);
1029 no_increase_box = new QCheckBox(tr("No x Height Increase"), this);
1030 no_increase_box->setToolTip(
1031 tr("If switched on,"
1032 " <b>TTFautohint</b> does not increase the x&nbsp;height."));
1035 // x height snapping exceptions
1037 snapping_label = new QLabel(tr("x Height Snapping Excep&tions:"));
1038 snapping_line = new Tooltip_Line_Edit;
1039 snapping_label->setBuddy(snapping_line);
1040 snapping_label->setToolTip(
1041 tr("<p>A list of comma separated PPEM values or value ranges"
1042 " at which no x&nbsp;height snapping shall be applied"
1043 " (x&nbsp;height snapping usually slightly increases"
1044 " the size of all glyphs).</p>"
1046 "Examples:<br>"
1047 "&nbsp;&nbsp;<tt>2, 3-5, 12-17</tt><br>"
1048 "&nbsp;&nbsp;<tt>-20, 40-</tt>"
1049 " (meaning PPEM &le; 20 or PPEM &ge; 40)<br>"
1050 "&nbsp;&nbsp;<tt>-</tt> (meaning all possible PPEM values)"));
1053 // flags
1055 wincomp_box = new QCheckBox(tr("Windows Com&patibility"), this);
1056 wincomp_box->setToolTip(
1057 tr("If switched on, add two artificial blue zones positioned at the"
1058 " <tt>usWinAscent</tt> and <tt>usWinDescent</tt> values"
1059 " (from the font's <i>OS/2</i> table)."
1060 " This option, usually in combination"
1061 " with value <tt>-</tt> (a single dash)"
1062 " for the <i>x&nbsp;Height Snapping Exceptions</i> option,"
1063 " should be used if those two <i>OS/2</i> values are tight,"
1064 " and you are experiencing clipping during rendering."));
1066 pre_box = new QCheckBox(tr("Pr&e-hinting"), this);
1067 pre_box->setToolTip(
1068 tr("If switched on, the original bytecode of the input font"
1069 " gets applied (at EM size, usually 2048ppem)"
1070 " to derive the glyph outlines for <b>TTFautohint</b>."
1071 " Note that the original bytecode will always be discarded."));
1073 hint_box = new QCheckBox(tr("Hint Co&mposites")
1074 + " ", this); // make label wider
1075 hint_box->setToolTip(
1076 tr("If switched on, <b>TTFautohint</b> hints composite glyphs"
1077 " as a whole, including subglyphs."
1078 " Otherwise, glyph components get hinted separately.<br>"
1079 "Deactivating this flag reduces the bytecode size enormously,"
1080 " however, it might yield worse results."));
1082 symbol_box = new QCheckBox(tr("S&ymbol Font"), this);
1083 symbol_box->setToolTip(
1084 tr("If switched on, <b>TTFautohint</b> uses default values"
1085 " for standard stem width and height"
1086 " instead of deriving these values from the input font.<br>"
1087 "Use this for fonts that don't contain glyphs"
1088 " of a (supported) script."));
1090 dehint_box = new QCheckBox(tr("&Dehint"), this);
1091 dehint_box->setToolTip(
1092 tr("<b></b>If set, remove all hints from the font."));
1094 info_box = new QCheckBox(tr("Add ttf&autohint Info"), this);
1095 info_box->setToolTip(
1096 tr("If switched on, information about <b>TTFautohint</b>"
1097 " and its calling parameters are added to the version string(s)"
1098 " (name ID&nbsp;5) in the <i>name</i> table."));
1101 // stem width and positioning
1103 stem_label = new QLabel(tr("Strong Stem &Width and Positioning:"));
1104 stem_label->setToolTip(
1105 tr("<b>TTFautohint</b> provides two different hinting algorithms"
1106 " that can be selected for various hinting modes."
1108 "<p><i>strong</i> (checkbox set):"
1109 " Position horizontal stems and snap stem widths"
1110 " to integer pixel values. While making the output look crisper,"
1111 " outlines become more distorted.</p>"
1113 "<p><i>smooth</i> (checkbox not set):"
1114 " Use discrete values for horizontal stems and stem widths."
1115 " This only slightly increases the contrast"
1116 " but avoids larger outline distortion.</p>"));
1118 gray_box = new QCheckBox(tr("Grayscale"), this);
1119 gray_box->setToolTip(
1120 tr("<b></b>Grayscale rendering, no ClearType activated."));
1121 stem_label->setBuddy(gray_box);
1123 gdi_box = new QCheckBox(tr("GDI ClearType"), this);
1124 gdi_box->setToolTip(
1125 tr("GDI ClearType rendering,"
1126 " introduced in 2000 for Windows XP.<br>"
1127 "The rasterizer version (as returned by the"
1128 " GETINFO bytecode instruction) is in the range"
1129 " 36&nbsp;&le; version &lt;&nbsp;38, and ClearType is enabled.<br>"
1130 "Along the vertical axis, this mode behaves like B/W rendering."));
1132 dw_box = new QCheckBox(tr("DW ClearType"), this);
1133 dw_box->setToolTip(
1134 tr("DirectWrite ClearType rendering,"
1135 " introduced in 2008 for Windows Vista.<br>"
1136 "The rasterizer version (as returned by the"
1137 " GETINFO bytecode instruction) is &ge;&nbsp;38,"
1138 " ClearType is enabled, and subpixel positioning is enabled also.<br>"
1139 "Smooth rendering along the vertical axis."));
1142 // running
1144 run_button = new QPushButton(" "
1145 + tr("&Run")
1146 + " "); // make label wider
1148 if (horizontal_layout)
1149 create_horizontal_layout();
1150 else
1151 create_vertical_layout();
1155 // XXX distances are specified in pixels,
1156 // making the layout dependent on the output device resolution
1157 void
1158 Main_GUI::create_vertical_layout()
1160 // top area
1161 QGridLayout* file_layout = new QGridLayout;
1163 file_layout->addWidget(input_label, 0, 0, Qt::AlignRight);
1164 file_layout->addWidget(input_line, 0, 1);
1165 file_layout->addWidget(input_button, 0, 2);
1167 file_layout->setRowStretch(1, 1);
1169 file_layout->addWidget(output_label, 2, 0, Qt::AlignRight);
1170 file_layout->addWidget(output_line, 2, 1);
1171 file_layout->addWidget(output_button, 2, 2);
1174 // the whole gui
1176 QGridLayout* gui_layout = new QGridLayout;
1177 QFrame* hline = new QFrame;
1178 hline->setFrameShape(QFrame::HLine);
1179 int row = 0; // this counter simplifies inserting new items
1181 gui_layout->setRowMinimumHeight(row, 10); // XXX urgh, pixels...
1182 gui_layout->setRowStretch(row++, 1);
1184 gui_layout->addLayout(file_layout, row, 0, row, -1);
1185 gui_layout->setRowStretch(row++, 1);
1187 gui_layout->addWidget(hline, row, 0, row, -1);
1188 gui_layout->setRowStretch(row++, 1);
1190 gui_layout->setRowMinimumHeight(row, 20); // XXX urgh, pixels...
1191 gui_layout->setRowStretch(row++, 1);
1193 gui_layout->addWidget(min_label, row, 0, Qt::AlignRight);
1194 gui_layout->addWidget(min_box, row++, 1, Qt::AlignLeft);
1195 gui_layout->addWidget(max_label, row, 0, Qt::AlignRight);
1196 gui_layout->addWidget(max_box, row++, 1, Qt::AlignLeft);
1198 gui_layout->setRowMinimumHeight(row, 20); // XXX urgh, pixels...
1199 gui_layout->setRowStretch(row++, 1);
1201 gui_layout->addWidget(default_label, row, 0, Qt::AlignRight);
1202 gui_layout->addWidget(default_box, row++, 1, Qt::AlignLeft);
1203 gui_layout->addWidget(fallback_label, row, 0, Qt::AlignRight);
1204 gui_layout->addWidget(fallback_box, row++, 1, Qt::AlignLeft);
1206 gui_layout->setRowMinimumHeight(row, 20); // XXX urgh, pixels...
1207 gui_layout->setRowStretch(row++, 1);
1209 gui_layout->addWidget(limit_label, row, 0, Qt::AlignRight);
1210 gui_layout->addWidget(limit_box, row++, 1, Qt::AlignLeft);
1211 gui_layout->addWidget(no_limit_box, row++, 1);
1213 gui_layout->addWidget(increase_label, row, 0, Qt::AlignRight);
1214 gui_layout->addWidget(increase_box, row++, 1, Qt::AlignLeft);
1215 gui_layout->addWidget(no_increase_box, row++, 1);
1217 gui_layout->addWidget(snapping_label, row, 0, Qt::AlignRight);
1218 gui_layout->addWidget(snapping_line, row++, 1, Qt::AlignLeft);
1220 gui_layout->setRowMinimumHeight(row, 20); // XXX urgh, pixels...
1221 gui_layout->setRowStretch(row++, 1);
1223 gui_layout->addWidget(wincomp_box, row++, 1);
1224 gui_layout->addWidget(pre_box, row++, 1);
1225 gui_layout->addWidget(hint_box, row++, 1);
1226 gui_layout->addWidget(symbol_box, row++, 1);
1227 gui_layout->addWidget(dehint_box, row++, 1);
1228 gui_layout->addWidget(info_box, row++, 1);
1230 gui_layout->setRowMinimumHeight(row, 20); // XXX urgh, pixels...
1231 gui_layout->setRowStretch(row++, 1);
1233 gui_layout->addWidget(stem_label, row, 0, Qt::AlignRight);
1234 gui_layout->addWidget(gray_box, row++, 1);
1235 gui_layout->addWidget(gdi_box, row++, 1);
1236 gui_layout->addWidget(dw_box, row++, 1);
1238 gui_layout->setRowMinimumHeight(row, 20); // XXX urgh, pixels...
1239 gui_layout->setRowStretch(row++, 1);
1241 gui_layout->addWidget(run_button, row++, 1, Qt::AlignRight);
1243 // create dummy widget to register layout
1244 QWidget* main_widget = new QWidget;
1245 main_widget->setLayout(gui_layout);
1246 setCentralWidget(main_widget);
1247 setWindowTitle("TTFautohint");
1251 // XXX distances are specified in pixels,
1252 // making the layout dependent on the output device resolution
1253 void
1254 Main_GUI::create_horizontal_layout()
1256 // top area
1257 QGridLayout* file_layout = new QGridLayout;
1259 file_layout->addWidget(input_label, 0, 0, Qt::AlignRight);
1260 file_layout->addWidget(input_line, 0, 1);
1261 file_layout->addWidget(input_button, 0, 2);
1263 file_layout->setRowStretch(1, 1);
1265 file_layout->addWidget(output_label, 2, 0, Qt::AlignRight);
1266 file_layout->addWidget(output_line, 2, 1);
1267 file_layout->addWidget(output_button, 2, 2);
1269 QGridLayout* gui_layout = new QGridLayout;
1270 QFrame* hline = new QFrame;
1271 hline->setFrameShape(QFrame::HLine);
1272 int row = 0; // this counter simplifies inserting new items
1274 // margin
1275 gui_layout->setColumnMinimumWidth(0, 10); // XXX urgh, pixels...
1276 gui_layout->setColumnStretch(0, 1);
1278 // left
1279 gui_layout->setRowMinimumHeight(row, 10); // XXX urgh, pixels...
1280 gui_layout->setRowStretch(row++, 1);
1282 gui_layout->addLayout(file_layout, row, 0, row, -1);
1283 gui_layout->setRowStretch(row++, 1);
1285 gui_layout->addWidget(hline, row, 0, row, -1);
1286 gui_layout->setRowStretch(row++, 1);
1288 gui_layout->setRowMinimumHeight(row, 20); // XXX urgh, pixels...
1289 gui_layout->setRowStretch(row++, 1);
1291 gui_layout->addWidget(min_label, row, 1, Qt::AlignRight);
1292 gui_layout->addWidget(min_box, row++, 2, Qt::AlignLeft);
1293 gui_layout->addWidget(max_label, row, 1, Qt::AlignRight);
1294 gui_layout->addWidget(max_box, row++, 2, Qt::AlignLeft);
1296 gui_layout->setRowMinimumHeight(row, 20); // XXX urgh, pixels...
1297 gui_layout->setRowStretch(row++, 1);
1299 gui_layout->addWidget(default_label, row, 1, Qt::AlignRight);
1300 gui_layout->addWidget(default_box, row++, 2, Qt::AlignLeft);
1301 gui_layout->addWidget(fallback_label, row, 1, Qt::AlignRight);
1302 gui_layout->addWidget(fallback_box, row++, 2, Qt::AlignLeft);
1304 gui_layout->setRowMinimumHeight(row, 20); // XXX urgh, pixels...
1305 gui_layout->setRowStretch(row++, 1);
1307 gui_layout->addWidget(limit_label, row, 1, Qt::AlignRight);
1308 gui_layout->addWidget(limit_box, row++, 2, Qt::AlignLeft);
1309 gui_layout->addWidget(no_limit_box, row++, 2);
1311 gui_layout->addWidget(increase_label, row, 1, Qt::AlignRight);
1312 gui_layout->addWidget(increase_box, row++, 2, Qt::AlignLeft);
1313 gui_layout->addWidget(no_increase_box, row++, 2);
1315 gui_layout->addWidget(snapping_label, row, 1, Qt::AlignRight);
1316 gui_layout->addWidget(snapping_line, row++, 2, Qt::AlignLeft);
1318 // column separator
1319 gui_layout->setColumnMinimumWidth(3, 20); // XXX urgh, pixels...
1320 gui_layout->setColumnStretch(3, 1);
1322 // right
1323 row = 4;
1324 gui_layout->addWidget(wincomp_box, row++, 4);
1325 gui_layout->addWidget(pre_box, row++, 4);
1326 gui_layout->addWidget(hint_box, row++, 4);
1327 gui_layout->addWidget(symbol_box, row++, 4);
1328 gui_layout->addWidget(dehint_box, row++, 4);
1329 gui_layout->addWidget(info_box, row++, 4);
1331 gui_layout->setRowMinimumHeight(row, 20); // XXX urgh, pixels...
1332 gui_layout->setRowStretch(row++, 1);
1334 gui_layout->addWidget(stem_label, row++, 4);
1336 QGridLayout* stem_layout = new QGridLayout;
1337 stem_layout->setColumnMinimumWidth(0, 20); // XXX urgh, pixels...
1338 stem_layout->addWidget(gray_box, 0, 1);
1339 stem_layout->addWidget(gdi_box, 1, 1);
1340 stem_layout->addWidget(dw_box, 2, 1);
1342 gui_layout->addLayout(stem_layout, row, 4, 3, 1);
1343 row += 3;
1345 gui_layout->setRowMinimumHeight(row, 20); // XXX urgh, pixels...
1346 gui_layout->setRowStretch(row++, 1);
1348 gui_layout->addWidget(run_button, row++, 4, Qt::AlignRight);
1350 // margin
1351 gui_layout->setColumnMinimumWidth(5, 10); // XXX urgh, pixels...
1352 gui_layout->setColumnStretch(5, 1);
1354 // create dummy widget to register layout
1355 QWidget* main_widget = new QWidget;
1356 main_widget->setLayout(gui_layout);
1357 setCentralWidget(main_widget);
1358 setWindowTitle("TTFautohint");
1362 void
1363 Main_GUI::create_connections()
1365 connect(input_button, SIGNAL(clicked()), this,
1366 SLOT(browse_input()));
1367 connect(output_button, SIGNAL(clicked()), this,
1368 SLOT(browse_output()));
1370 connect(input_line, SIGNAL(textChanged(QString)), this,
1371 SLOT(check_run()));
1372 connect(output_line, SIGNAL(textChanged(QString)), this,
1373 SLOT(check_run()));
1375 connect(input_line, SIGNAL(editingFinished()), this,
1376 SLOT(absolute_input()));
1377 connect(output_line, SIGNAL(editingFinished()), this,
1378 SLOT(absolute_output()));
1380 connect(min_box, SIGNAL(valueChanged(int)), this,
1381 SLOT(check_min()));
1382 connect(max_box, SIGNAL(valueChanged(int)), this,
1383 SLOT(check_max()));
1385 connect(limit_box, SIGNAL(valueChanged(int)), this,
1386 SLOT(check_limit()));
1387 connect(no_limit_box, SIGNAL(clicked()), this,
1388 SLOT(check_no_limit()));
1390 connect(no_increase_box, SIGNAL(clicked()), this,
1391 SLOT(check_no_increase()));
1393 connect(snapping_line, SIGNAL(editingFinished()), this,
1394 SLOT(check_number_set()));
1395 connect(snapping_line, SIGNAL(textEdited(QString)), this,
1396 SLOT(clear_status_bar()));
1398 connect(dehint_box, SIGNAL(clicked()), this,
1399 SLOT(check_dehint()));
1401 connect(run_button, SIGNAL(clicked()), this,
1402 SLOT(run()));
1406 void
1407 Main_GUI::create_actions()
1409 exit_act = new QAction(tr("E&xit"), this);
1410 exit_act->setShortcuts(QKeySequence::Quit);
1411 connect(exit_act, SIGNAL(triggered()), this, SLOT(close()));
1413 about_act = new QAction(tr("&About"), this);
1414 connect(about_act, SIGNAL(triggered()), this, SLOT(about()));
1416 about_Qt_act = new QAction(tr("About &Qt"), this);
1417 connect(about_Qt_act, SIGNAL(triggered()), qApp, SLOT(aboutQt()));
1421 void
1422 Main_GUI::create_menus()
1424 file_menu = menuBar()->addMenu(tr("&File"));
1425 file_menu->addAction(exit_act);
1427 help_menu = menuBar()->addMenu(tr("&Help"));
1428 help_menu->addAction(about_act);
1429 help_menu->addAction(about_Qt_act);
1433 void
1434 Main_GUI::create_status_bar()
1436 statusBar()->showMessage("");
1440 void
1441 Main_GUI::set_defaults()
1443 min_box->setValue(hinting_range_min);
1444 max_box->setValue(hinting_range_max);
1446 default_box->setCurrentIndex(default_script_idx);
1447 fallback_box->setCurrentIndex(fallback_script_idx);
1449 limit_box->setValue(hinting_limit ? hinting_limit : hinting_range_max);
1450 // handle command line option `--hinting-limit=0'
1451 if (!hinting_limit)
1453 hinting_limit = max_box->value();
1454 no_limit_box->setChecked(true);
1457 increase_box->setValue(increase_x_height ? increase_x_height
1458 : TA_INCREASE_X_HEIGHT);
1459 // handle command line option `--increase-x-height=0'
1460 if (!increase_x_height)
1462 increase_x_height = TA_INCREASE_X_HEIGHT;
1463 no_increase_box->setChecked(true);
1466 snapping_line->setText(x_height_snapping_exceptions_string);
1468 if (windows_compatibility)
1469 wincomp_box->setChecked(true);
1470 if (pre_hinting)
1471 pre_box->setChecked(true);
1472 if (hint_composites)
1473 hint_box->setChecked(true);
1474 if (symbol)
1475 symbol_box->setChecked(true);
1476 if (dehint)
1477 dehint_box->setChecked(true);
1478 if (!no_info)
1479 info_box->setChecked(true);
1481 if (gray_strong_stem_width)
1482 gray_box->setChecked(true);
1483 if (gdi_cleartype_strong_stem_width)
1484 gdi_box->setChecked(true);
1485 if (dw_cleartype_strong_stem_width)
1486 dw_box->setChecked(true);
1488 run_button->setEnabled(false);
1490 check_min();
1491 check_max();
1492 check_limit();
1494 check_no_limit();
1495 check_no_increase();
1496 check_number_set();
1498 // do this last since it disables almost everything
1499 check_dehint();
1503 void
1504 Main_GUI::read_settings()
1506 QSettings settings;
1507 // QPoint pos = settings.value("pos", QPoint(200, 200)).toPoint();
1508 // QSize size = settings.value("size", QSize(400, 400)).toSize();
1509 // resize(size);
1510 // move(pos);
1514 void
1515 Main_GUI::write_settings()
1517 QSettings settings;
1518 // settings.setValue("pos", pos());
1519 // settings.setValue("size", size());
1522 // end of maingui.cpp