]> git.lyx.org Git - lyx.git/blobdiff - src/frontends/qt4/GuiPrefs.cpp
Improve wording (#10670)
[lyx.git] / src / frontends / qt4 / GuiPrefs.cpp
index 6dfd337dcdd005f086eb6add84923f46861ae7a6..bacf17ac57de7ce9e0b97c2d2689614673588c5d 100644 (file)
 #include "LyXAction.h"
 #include "LyX.h"
 #include "PanelStack.h"
-#include "paper.h"
 #include "Session.h"
 #include "SpellChecker.h"
 
 #include "support/debug.h"
 #include "support/FileName.h"
 #include "support/filetools.h"
-#include "support/foreach.h"
 #include "support/gettext.h"
 #include "support/lassert.h"
 #include "support/lstrings.h"
@@ -74,6 +72,7 @@
 #include <iomanip>
 #include <sstream>
 #include <algorithm>
+#include <math.h>
 
 using namespace Ui;
 
@@ -232,7 +231,7 @@ QString browseRelToSub(QString const & filename, QString const & relpath,
 
        QString testname = reloutname;
        testname.remove(QRegExp("^(\\.\\./)+"));
-       
+
        if (testname.contains("/"))
                return outname;
        else
@@ -314,7 +313,6 @@ static void setComboxFont(QComboBox * cb, string const & family,
        // for bug 1063.
 
        QFont font;
-       font.setKerning(false);
 
        QString const font_family = toqstr(family);
        if (font_family == guiApp->romanFontName()) {
@@ -405,6 +403,17 @@ PrefOutput::PrefOutput(GuiPreferences * form)
                this, SIGNAL(changed()));
        connect(pdfCB, SIGNAL(editTextChanged(QString)),
                this, SIGNAL(changed()));
+       connect(printerPaperTypeED, SIGNAL(textChanged(QString)),
+               this, SIGNAL(changed()));
+       connect(printerLandscapeED, SIGNAL(textChanged(QString)),
+               this, SIGNAL(changed()));
+       connect(printerPaperSizeED, SIGNAL(textChanged(QString)),
+               this, SIGNAL(changed()));
+
+       printerPaperTypeED->setValidator(new NoNewLineValidator(printerPaperTypeED));
+       printerLandscapeED->setValidator(new NoNewLineValidator(printerLandscapeED));
+       printerPaperSizeED->setValidator(new NoNewLineValidator(printerPaperSizeED));
+
        dviCB->addItem("");
        dviCB->addItem("xdvi -sourceposition '$$n:\\ $$t' $$o");
        dviCB->addItem("yap -1 -s \"$$n $$t\" $$o");
@@ -412,9 +421,10 @@ PrefOutput::PrefOutput(GuiPreferences * form)
        dviCB->addItem("synctex view -i $$n:0:$$t -o $$o -x \"evince -i %{page+1} $$o\"");
        pdfCB->addItem("");
        pdfCB->addItem("CMCDDE SUMATRA control [ForwardSearch(\\\"$$o\\\",\\\"$$t\\\",$$n,0,0,1)]");
-       pdfCB->addItem("SumatraPDF -reuse-instance $$o -forward-search $$t $$n");
+       pdfCB->addItem("SumatraPDF -reuse-instance \"$$o\" -forward-search \"$$t\" $$n");
        pdfCB->addItem("synctex view -i $$n:0:$$t -o $$o -x \"xpdf -raise -remote $$t.tmp $$o %{page+1}\"");
        pdfCB->addItem("okular --unique \"$$o#src:$$n $$f\"");
+       pdfCB->addItem("qpdfview --unique \"$$o#src:$$f:$$n:0\"");
        pdfCB->addItem("synctex view -i $$n:0:$$t -o $$o -x \"evince -i %{page+1} $$o\"");
        pdfCB->addItem("/Applications/Skim.app/Contents/SharedSupport/displayline $$n $$o $$t");
 }
@@ -430,7 +440,7 @@ void PrefOutput::on_DateED_textChanged(const QString &)
 }
 
 
-void PrefOutput::apply(LyXRC & rc) const
+void PrefOutput::applyRC(LyXRC & rc) const
 {
        rc.date_insert_format = fromqstr(DateED->text());
        rc.plaintext_linelen = plaintextLinelengthSB->value();
@@ -448,10 +458,14 @@ void PrefOutput::apply(LyXRC & rc) const
                rc.export_overwrite = ALL_FILES;
                break;
        }
+
+       rc.print_paper_flag = fromqstr(printerPaperTypeED->text());
+       rc.print_landscape_flag = fromqstr(printerLandscapeED->text());
+       rc.print_paper_dimension_flag = fromqstr(printerPaperSizeED->text());
 }
 
 
-void PrefOutput::update(LyXRC const & rc)
+void PrefOutput::updateRC(LyXRC const & rc)
 {
        DateED->setText(toqstr(rc.date_insert_format));
        plaintextLinelengthSB->setValue(rc.plaintext_linelen);
@@ -469,6 +483,10 @@ void PrefOutput::update(LyXRC const & rc)
                overwriteCO->setCurrentIndex(2);
                break;
        }
+
+       printerPaperTypeED->setText(toqstr(rc.print_paper_flag));
+       printerLandscapeED->setText(toqstr(rc.print_landscape_flag));
+       printerPaperSizeED->setText(toqstr(rc.print_paper_dimension_flag));
 }
 
 
@@ -497,10 +515,12 @@ PrefInput::PrefInput(GuiPreferences * form)
                this, SIGNAL(changed()));
        connect(dontswapCB, SIGNAL(toggled(bool)),
                this, SIGNAL(changed()));
+       connect(mmPasteCB, SIGNAL(toggled(bool)),
+               this, SIGNAL(changed()));
 
        // reveal checkbox for switching Ctrl and Meta on Mac:
        bool swapcb = false;
-#ifdef Q_WS_MACX
+#ifdef Q_OS_MAC
 #if QT_VERSION > 0x040600
        swapcb = true;
 #endif
@@ -509,7 +529,7 @@ PrefInput::PrefInput(GuiPreferences * form)
 }
 
 
-void PrefInput::apply(LyXRC & rc) const
+void PrefInput::applyRC(LyXRC & rc) const
 {
        // FIXME: can derive CB from the two EDs
        rc.use_kbmap = keymapCB->isChecked();
@@ -532,10 +552,11 @@ void PrefInput::apply(LyXRC & rc) const
                rc.scroll_wheel_zoom = LyXRC::SCROLL_WHEEL_ZOOM_OFF;
        }
        rc.mac_dontswap_ctrl_meta  = dontswapCB->isChecked();
+       rc.mouse_middlebutton_paste = mmPasteCB->isChecked();
 }
 
 
-void PrefInput::update(LyXRC const & rc)
+void PrefInput::updateRC(LyXRC const & rc)
 {
        // FIXME: can derive CB from the two EDs
        keymapCB->setChecked(rc.use_kbmap);
@@ -560,6 +581,7 @@ void PrefInput::update(LyXRC const & rc)
                break;
        }
        dontswapCB->setChecked(rc.mac_dontswap_ctrl_meta);
+       mmPasteCB->setChecked(rc.mouse_middlebutton_paste);
 }
 
 
@@ -600,8 +622,8 @@ void PrefInput::on_scrollzoomEnableCB_toggled(bool enabled)
 {
        scrollzoomValueCO->setEnabled(enabled);
 }
-       
-       
+
+
 /////////////////////////////////////////////////////////////////////
 //
 // PrefCompletion
@@ -657,7 +679,7 @@ void PrefCompletion::enableCB()
 }
 
 
-void PrefCompletion::apply(LyXRC & rc) const
+void PrefCompletion::applyRC(LyXRC & rc) const
 {
        rc.completion_inline_delay = inlineDelaySB->value();
        rc.completion_inline_math = inlineMathCB->isChecked();
@@ -674,7 +696,7 @@ void PrefCompletion::apply(LyXRC & rc) const
 }
 
 
-void PrefCompletion::update(LyXRC const & rc)
+void PrefCompletion::updateRC(LyXRC const & rc)
 {
        inlineDelaySB->setValue(rc.completion_inline_delay);
        inlineMathCB->setChecked(rc.completion_inline_math);
@@ -686,7 +708,7 @@ void PrefCompletion::update(LyXRC const & rc)
        popupTextCB->setChecked(rc.completion_popup_text);
        cursorTextCB->setChecked(rc.completion_cursor_text);
        popupAfterCompleteCB->setChecked(rc.completion_popup_after_complete);
-        enableCB();
+       enableCB();
        minlengthSB->setValue(rc.completion_minlength);
 }
 
@@ -722,6 +744,8 @@ PrefLatex::PrefLatex(GuiPreferences * form)
                this, SIGNAL(changed()));
        connect(latexBibtexED, SIGNAL(textChanged(QString)),
                this, SIGNAL(changed()));
+       connect(latexJBibtexCO, SIGNAL(activated(int)),
+               this, SIGNAL(changed()));
        connect(latexJBibtexED, SIGNAL(textChanged(QString)),
                this, SIGNAL(changed()));
        connect(latexIndexCO, SIGNAL(activated(int)),
@@ -758,7 +782,7 @@ void PrefLatex::on_latexBibtexCO_activated(int n)
        QString const bibtex = latexBibtexCO->itemData(n).toString();
        if (bibtex.isEmpty()) {
                latexBibtexED->clear();
-               latexBibtexOptionsLA->setText(qt_("Co&mmand:"));
+               latexBibtexOptionsLA->setText(qt_("C&ommand:"));
                return;
        }
        for (LyXRC::CommandSet::const_iterator it = bibtex_alternatives.begin();
@@ -778,6 +802,31 @@ void PrefLatex::on_latexBibtexCO_activated(int n)
 }
 
 
+void PrefLatex::on_latexJBibtexCO_activated(int n)
+{
+       QString const jbibtex = latexJBibtexCO->itemData(n).toString();
+       if (jbibtex.isEmpty()) {
+               latexJBibtexED->clear();
+               latexJBibtexOptionsLA->setText(qt_("Co&mmand:"));
+               return;
+       }
+       for (LyXRC::CommandSet::const_iterator it = jbibtex_alternatives.begin();
+            it != jbibtex_alternatives.end(); ++it) {
+               QString const bib = toqstr(*it);
+               int ind = bib.indexOf(" ");
+               QString sel_command = bib.left(ind);
+               QString sel_options = ind < 0 ? QString() : bib.mid(ind + 1);
+               if (jbibtex == sel_command) {
+                       if (ind < 0)
+                               latexJBibtexED->clear();
+                       else
+                               latexJBibtexED->setText(sel_options.trimmed());
+               }
+       }
+       latexJBibtexOptionsLA->setText(qt_("Opt&ions:"));
+}
+
+
 void PrefLatex::on_latexIndexCO_activated(int n)
 {
        QString const index = latexIndexCO->itemData(n).toString();
@@ -803,7 +852,7 @@ void PrefLatex::on_latexIndexCO_activated(int n)
 }
 
 
-void PrefLatex::apply(LyXRC & rc) const
+void PrefLatex::applyRC(LyXRC & rc) const
 {
        // If bibtex is not empty, bibopt contains the options, otherwise
        // it is a customized bibtex command with options.
@@ -817,6 +866,18 @@ void PrefLatex::apply(LyXRC & rc) const
        else
                rc.bibtex_command = fromqstr(bibtex) + " " + fromqstr(bibopt);
 
+       // If jbibtex is not empty, jbibopt contains the options, otherwise
+       // it is a customized bibtex command with options.
+       QString const jbibtex = latexJBibtexCO->itemData(
+               latexJBibtexCO->currentIndex()).toString();
+       QString const jbibopt = latexJBibtexED->text();
+       if (jbibtex.isEmpty())
+               rc.jbibtex_command = fromqstr(jbibopt);
+       else if (jbibopt.isEmpty())
+               rc.jbibtex_command = fromqstr(jbibtex);
+       else
+               rc.jbibtex_command = fromqstr(jbibtex) + " " + fromqstr(jbibopt);
+
        // If index is not empty, idxopt contains the options, otherwise
        // it is a customized index command with options.
        QString const index = latexIndexCO->itemData(
@@ -834,7 +895,6 @@ void PrefLatex::apply(LyXRC & rc) const
        else
                rc.fontenc = "default";
        rc.chktex_command = fromqstr(latexChecktexED->text());
-       rc.jbibtex_command = fromqstr(latexJBibtexED->text());
        rc.jindex_command = fromqstr(latexJIndexED->text());
        rc.nomencl_command = fromqstr(latexNomenclED->text());
        rc.auto_reset_options = latexAutoresetCB->isChecked();
@@ -845,10 +905,11 @@ void PrefLatex::apply(LyXRC & rc) const
 }
 
 
-void PrefLatex::update(LyXRC const & rc)
+void PrefLatex::updateRC(LyXRC const & rc)
 {
        latexBibtexCO->clear();
 
+       latexBibtexCO->addItem(qt_("Automatic"), "automatic");
        latexBibtexCO->addItem(qt_("Custom"), QString());
        for (LyXRC::CommandSet::const_iterator it = rc.bibtex_alternatives.begin();
                             it != rc.bibtex_alternatives.end(); ++it) {
@@ -871,7 +932,35 @@ void PrefLatex::update(LyXRC const & rc)
        } else {
                latexBibtexED->setText(toqstr(rc.bibtex_command));
                latexBibtexCO->setCurrentIndex(0);
-               latexBibtexOptionsLA->setText(qt_("Co&mmand:"));
+               latexBibtexOptionsLA->setText(qt_("C&ommand:"));
+       }
+
+       latexJBibtexCO->clear();
+
+       latexJBibtexCO->addItem(qt_("Automatic"), "automatic");
+       latexJBibtexCO->addItem(qt_("Custom"), QString());
+       for (LyXRC::CommandSet::const_iterator it = rc.jbibtex_alternatives.begin();
+                            it != rc.jbibtex_alternatives.end(); ++it) {
+               QString const command = toqstr(*it).left(toqstr(*it).indexOf(" "));
+               latexJBibtexCO->addItem(command, command);
+       }
+
+       jbibtex_alternatives = rc.jbibtex_alternatives;
+
+       QString const jbib = toqstr(rc.jbibtex_command);
+       ind = jbib.indexOf(" ");
+       sel_command = jbib.left(ind);
+       sel_options = ind < 0 ? QString() : jbib.mid(ind + 1);
+
+       pos = latexJBibtexCO->findData(sel_command);
+       if (pos != -1) {
+               latexJBibtexCO->setCurrentIndex(pos);
+               latexJBibtexED->setText(sel_options.trimmed());
+               latexJBibtexOptionsLA->setText(qt_("Opt&ions:"));
+       } else {
+               latexJBibtexED->setText(toqstr(rc.bibtex_command));
+               latexJBibtexCO->setCurrentIndex(0);
+               latexJBibtexOptionsLA->setText(qt_("Co&mmand:"));
        }
 
        latexIndexCO->clear();
@@ -910,7 +999,6 @@ void PrefLatex::update(LyXRC const & rc)
                latexEncodingED->setText(toqstr(rc.fontenc));
        }
        latexChecktexED->setText(toqstr(rc.chktex_command));
-       latexJBibtexED->setText(toqstr(rc.jbibtex_command));
        latexJIndexED->setText(toqstr(rc.jindex_command));
        latexNomenclED->setText(toqstr(rc.nomencl_command));
        latexAutoresetCB->setChecked(rc.auto_reset_options);
@@ -990,7 +1078,7 @@ PrefScreenFonts::PrefScreenFonts(GuiPreferences * form)
 }
 
 
-void PrefScreenFonts::apply(LyXRC & rc) const
+void PrefScreenFonts::applyRC(LyXRC & rc) const
 {
        LyXRC const oldrc = rc;
 
@@ -1029,7 +1117,7 @@ void PrefScreenFonts::apply(LyXRC & rc) const
 }
 
 
-void PrefScreenFonts::update(LyXRC const & rc)
+void PrefScreenFonts::updateRC(LyXRC const & rc)
 {
        setComboxFont(screenRomanCO, rc.roman_font_name,
                        rc.roman_font_foundry);
@@ -1046,7 +1134,7 @@ void PrefScreenFonts::update(LyXRC const & rc)
        updateScreenFontSizes(rc);
 
        pixmapCacheCB->setChecked(rc.use_pixmap_cache);
-#if defined(Q_WS_X11)
+#if defined(Q_WS_X11) || defined(QPA_XCB)
        pixmapCacheCB->setEnabled(false);
 #endif
 
@@ -1092,17 +1180,6 @@ void PrefScreenFonts::selectTypewriter(const QString & name)
 //
 /////////////////////////////////////////////////////////////////////
 
-namespace {
-
-struct ColorSorter
-{
-       bool operator()(ColorCode lhs, ColorCode rhs) const {
-               return 
-                       compare_no_case(lcolor.getGUIName(lhs), lcolor.getGUIName(rhs)) < 0;
-       }
-};
-
-} // namespace anon
 
 PrefColors::PrefColors(GuiPreferences * form)
        : PrefModule(catLookAndFeel, N_("Colors"), form)
@@ -1118,18 +1195,29 @@ PrefColors::PrefColors(GuiPreferences * form)
                if (lc == Color_none
                    || lc == Color_black
                    || lc == Color_white
-                   || lc == Color_red
-                   || lc == Color_green
                    || lc == Color_blue
+                   || lc == Color_brown
                    || lc == Color_cyan
+                   || lc == Color_darkgray
+                   || lc == Color_gray
+                   || lc == Color_green
+                   || lc == Color_lightgray
+                   || lc == Color_lime
                    || lc == Color_magenta
+                   || lc == Color_olive
+                   || lc == Color_orange
+                   || lc == Color_pink
+                   || lc == Color_purple
+                   || lc == Color_red
+                   || lc == Color_teal
+                   || lc == Color_violet
                    || lc == Color_yellow
                    || lc == Color_inherit
                    || lc == Color_ignore)
                        continue;
                lcolors_.push_back(lc);
        }
-       sort(lcolors_.begin(), lcolors_.end(), ColorSorter());
+       qSort(lcolors_.begin(), lcolors_.end(), ColorSorter);
        vector<ColorCode>::const_iterator cit = lcolors_.begin();
        vector<ColorCode>::const_iterator const end = lcolors_.end();
        for (; cit != end; ++cit) {
@@ -1153,7 +1241,7 @@ PrefColors::PrefColors(GuiPreferences * form)
 }
 
 
-void PrefColors::apply(LyXRC & rc) const
+void PrefColors::applyRC(LyXRC & rc) const
 {
        LyXRC oldrc = rc;
 
@@ -1167,7 +1255,7 @@ void PrefColors::apply(LyXRC & rc) const
 }
 
 
-void PrefColors::update(LyXRC const & rc)
+void PrefColors::updateRC(LyXRC const & rc)
 {
        for (unsigned int i = 0; i < lcolors_.size(); ++i) {
                QColor color = QColor(guiApp->colorCache().get(lcolors_[i], false));
@@ -1206,12 +1294,17 @@ void PrefColors::changeSysColor()
 {
        for (int row = 0 ; row < lyxObjectsLW->count() ; ++row) {
                // skip colors that are taken from system palette
-               bool const hide = syscolorsCB->isChecked()
+               bool const disable = syscolorsCB->isChecked()
                        && guiApp->colorCache().isSystem(lcolors_[row]);
 
-               lyxObjectsLW->item(row)->setHidden(hide);
-       }
+               QListWidgetItem * const item = lyxObjectsLW->item(row);
+               Qt::ItemFlags const flags = item->flags();
 
+               if (disable)
+                       item->setFlags(flags & ~Qt::ItemIsEnabled);
+               else
+                       item->setFlags(flags | Qt::ItemIsEnabled);
+       }
 }
 
 void PrefColors::changeLyxObjectsSelection()
@@ -1243,17 +1336,23 @@ void PrefDisplay::on_instantPreviewCO_currentIndexChanged(int index)
 }
 
 
-void PrefDisplay::apply(LyXRC & rc) const
+void PrefDisplay::applyRC(LyXRC & rc) const
 {
        switch (instantPreviewCO->currentIndex()) {
                case 0:
                        rc.preview = LyXRC::PREVIEW_OFF;
                        break;
                case 1:
-                       rc.preview = LyXRC::PREVIEW_NO_MATH;
+                       if (rc.preview != LyXRC::PREVIEW_NO_MATH) {
+                               rc.preview = LyXRC::PREVIEW_NO_MATH;
+                               form_->updatePreviews();
+                       }
                        break;
                case 2:
-                       rc.preview = LyXRC::PREVIEW_ON;
+                       if (rc.preview != LyXRC::PREVIEW_ON) {
+                               rc.preview = LyXRC::PREVIEW_ON;
+                               form_->updatePreviews();
+                       }
                        break;
        }
 
@@ -1271,7 +1370,7 @@ void PrefDisplay::apply(LyXRC & rc) const
 }
 
 
-void PrefDisplay::update(LyXRC const & rc)
+void PrefDisplay::updateRC(LyXRC const & rc)
 {
        switch (rc.preview) {
        case LyXRC::PREVIEW_OFF:
@@ -1353,7 +1452,7 @@ PrefPaths::PrefPaths(GuiPreferences * form)
 }
 
 
-void PrefPaths::apply(LyXRC & rc) const
+void PrefPaths::applyRC(LyXRC & rc) const
 {
        rc.document_path = internal_path(fromqstr(workingDirED->text()));
        rc.example_path = internal_path(fromqstr(exampleDirED->text()));
@@ -1369,7 +1468,7 @@ void PrefPaths::apply(LyXRC & rc) const
 }
 
 
-void PrefPaths::update(LyXRC const & rc)
+void PrefPaths::updateRC(LyXRC const & rc)
 {
        workingDirED->setText(toqstr(external_path(rc.document_path)));
        exampleDirED->setText(toqstr(external_path(rc.example_path)));
@@ -1512,7 +1611,7 @@ PrefSpellchecker::PrefSpellchecker(GuiPreferences * form)
 }
 
 
-void PrefSpellchecker::apply(LyXRC & rc) const
+void PrefSpellchecker::applyRC(LyXRC & rc) const
 {
        string const speller = fromqstr(spellcheckerCB->
                itemData(spellcheckerCB->currentIndex()).toString());
@@ -1526,7 +1625,7 @@ void PrefSpellchecker::apply(LyXRC & rc) const
 }
 
 
-void PrefSpellchecker::update(LyXRC const & rc)
+void PrefSpellchecker::updateRC(LyXRC const & rc)
 {
        spellcheckerCB->setCurrentIndex(
                spellcheckerCB->findData(toqstr(rc.spellchecker)));
@@ -1541,12 +1640,12 @@ void PrefSpellchecker::update(LyXRC const & rc)
 void PrefSpellchecker::on_spellcheckerCB_currentIndexChanged(int index)
 {
        QString spellchecker = spellcheckerCB->itemData(index).toString();
-       
+
        compoundWordCB->setEnabled(spellchecker == QString("aspell"));
 }
-       
-       
-       
+
+
+
 /////////////////////////////////////////////////////////////////////
 //
 // PrefConverters
@@ -1583,24 +1682,32 @@ PrefConverters::PrefConverters(GuiPreferences * form)
                this, SIGNAL(changed()));
        connect(maxAgeLE, SIGNAL(textEdited(QString)),
                this, SIGNAL(changed()));
+       connect(needauthForbiddenCB, SIGNAL(toggled(bool)),
+               this, SIGNAL(changed()));
+       connect(needauthCB, SIGNAL(toggled(bool)),
+               this, SIGNAL(changed()));
 
        converterED->setValidator(new NoNewLineValidator(converterED));
        converterFlagED->setValidator(new NoNewLineValidator(converterFlagED));
-       maxAgeLE->setValidator(new QDoubleValidator(maxAgeLE));
+       maxAgeLE->setValidator(new QDoubleValidator(0, HUGE_VAL, 6, maxAgeLE));
        //converterDefGB->setFocusProxy(convertersLW);
 }
 
 
-void PrefConverters::apply(LyXRC & rc) const
+void PrefConverters::applyRC(LyXRC & rc) const
 {
        rc.use_converter_cache = cacheCB->isChecked();
+       rc.use_converter_needauth_forbidden = needauthForbiddenCB->isChecked();
+       rc.use_converter_needauth = needauthCB->isChecked();
        rc.converter_cache_maxage = int(widgetToDouble(maxAgeLE) * 86400.0);
 }
 
 
-void PrefConverters::update(LyXRC const & rc)
+void PrefConverters::updateRC(LyXRC const & rc)
 {
        cacheCB->setChecked(rc.use_converter_cache);
+       needauthForbiddenCB->setChecked(rc.use_converter_needauth_forbidden);
+       needauthCB->setChecked(rc.use_converter_needauth);
        QString max_age;
        doubleToWidget(maxAgeLE, (double(rc.converter_cache_maxage) / 86400.0), 'g', 6);
        updateGui();
@@ -1609,20 +1716,22 @@ void PrefConverters::update(LyXRC const & rc)
 
 void PrefConverters::updateGui()
 {
+       QString const pattern("%1 -> %2");
        form_->formats().sort();
        form_->converters().update(form_->formats());
        // save current selection
-       QString current = converterFromCO->currentText()
-               + " -> " + converterToCO->currentText();
+       QString current =
+               pattern
+               .arg(converterFromCO->currentText())
+               .arg(converterToCO->currentText());
 
        converterFromCO->clear();
        converterToCO->clear();
 
-       Formats::const_iterator cit = form_->formats().begin();
-       Formats::const_iterator end = form_->formats().end();
-       for (; cit != end; ++cit) {
-               converterFromCO->addItem(qt_(cit->prettyname()));
-               converterToCO->addItem(qt_(cit->prettyname()));
+       for (Format const & f : form_->formats()) {
+               QString const name = toqstr(translateIfPossible(f.prettyname()));
+               converterFromCO->addItem(name);
+               converterToCO->addItem(name);
        }
 
        // currentRowChanged(int) is also triggered when updating the listwidget
@@ -1630,19 +1739,20 @@ void PrefConverters::updateGui()
        convertersLW->blockSignals(true);
        convertersLW->clear();
 
-       Converters::const_iterator ccit = form_->converters().begin();
-       Converters::const_iterator cend = form_->converters().end();
-       for (; ccit != cend; ++ccit) {
+       for (Converter const & c : form_->converters()) {
                QString const name =
-                       qt_(ccit->From->prettyname()) + " -> " + qt_(ccit->To->prettyname());
-               int type = form_->converters().getNumber(ccit->From->name(), ccit->To->name());
+                       pattern
+                       .arg(toqstr(translateIfPossible(c.From()->prettyname())))
+                       .arg(toqstr(translateIfPossible(c.To()->prettyname())));
+               int type = form_->converters().getNumber(c.From()->name(),
+                                                        c.To()->name());
                new QListWidgetItem(name, convertersLW, type);
        }
        convertersLW->sortItems(Qt::AscendingOrder);
        convertersLW->blockSignals(false);
 
        // restore selection
-       if (!current.isEmpty()) {
+       if (current != pattern.arg(QString()).arg(QString())) {
                QList<QListWidgetItem *> const item =
                        convertersLW->findItems(current, Qt::MatchExactly);
                if (!item.isEmpty())
@@ -1661,10 +1771,10 @@ void PrefConverters::switchConverter()
 {
        int const cnr = convertersLW->currentItem()->type();
        Converter const & c(form_->converters().get(cnr));
-       converterFromCO->setCurrentIndex(form_->formats().getNumber(c.from));
-       converterToCO->setCurrentIndex(form_->formats().getNumber(c.to));
-       converterED->setText(toqstr(c.command));
-       converterFlagED->setText(toqstr(c.flags));
+       converterFromCO->setCurrentIndex(form_->formats().getNumber(c.from()));
+       converterToCO->setCurrentIndex(form_->formats().getNumber(c.to()));
+       converterED->setText(toqstr(c.command()));
+       converterFlagED->setText(toqstr(c.flags()));
 
        updateButtons();
 }
@@ -1693,8 +1803,8 @@ void PrefConverters::updateButtons()
        if (convertersLW->count() > 0) {
                int const cnr = convertersLW->currentItem()->type();
                Converter const & c = form_->converters().get(cnr);
-               old_command = c.command;
-               old_flag = c.flags;
+               old_command = c.command();
+               old_flag = c.flags();
        }
 
        string const new_command = fromqstr(converterED->text());
@@ -1758,6 +1868,12 @@ void PrefConverters::on_cacheCB_stateChanged(int state)
 }
 
 
+void PrefConverters::on_needauthForbiddenCB_toggled(bool checked)
+{
+       needauthCB->setEnabled(!checked);
+}
+
+
 /////////////////////////////////////////////////////////////////////
 //
 // FormatValidator
@@ -1857,7 +1973,7 @@ public:
 private:
        QString toString(Format const & format) const
        {
-               return qt_(format.prettyname());
+               return toqstr(translateIfPossible(format.prettyname()));
        }
 };
 
@@ -1904,20 +2020,20 @@ PrefFileformats::PrefFileformats(GuiPreferences * form)
 
 namespace {
 
-string const l10n_shortcut(string const prettyname, string const shortcut)
+string const l10n_shortcut(docstring const & prettyname, string const & shortcut)
 {
        if (shortcut.empty())
                return string();
 
        string l10n_format =
-               to_utf8(_(prettyname + '|' + shortcut));
+               to_utf8(_(to_utf8(prettyname) + '|' + shortcut));
        return split(l10n_format, '|');
 }
 
 } // namespace anon
 
 
-void PrefFileformats::apply(LyXRC & rc) const
+void PrefFileformats::applyRC(LyXRC & rc) const
 {
        QString const default_format = defaultFormatCB->itemData(
                defaultFormatCB->currentIndex()).toString();
@@ -1928,7 +2044,7 @@ void PrefFileformats::apply(LyXRC & rc) const
 }
 
 
-void PrefFileformats::update(LyXRC const & rc)
+void PrefFileformats::updateRC(LyXRC const & rc)
 {
        viewer_alternatives = rc.viewer_alternatives;
        editor_alternatives = rc.editor_alternatives;
@@ -1959,25 +2075,24 @@ void PrefFileformats::updateView()
        defaultFormatCB->clear();
        defaultOTFFormatCB->clear();
        form_->formats().sort();
-       Formats::const_iterator cit = form_->formats().begin();
-       Formats::const_iterator end = form_->formats().end();
-       for (; cit != end; ++cit) {
-               formatsCB->addItem(qt_(cit->prettyname()),
-                               QVariant(form_->formats().getNumber(cit->name())));
-               if (cit->viewer().empty())
+       for (Format const & f : form_->formats()) {
+               QString const prettyname = toqstr(translateIfPossible(f.prettyname()));
+               formatsCB->addItem(prettyname,
+                                  QVariant(form_->formats().getNumber(f.name())));
+               if (f.viewer().empty())
                        continue;
-               if (form_->converters().isReachable("xhtml", cit->name())
-                   || form_->converters().isReachable("dviluatex", cit->name())
-                   || form_->converters().isReachable("luatex", cit->name())
-                   || form_->converters().isReachable("xetex", cit->name())) {
-                       defaultFormatCB->addItem(qt_(cit->prettyname()),
-                                       QVariant(toqstr(cit->name())));
-                       defaultOTFFormatCB->addItem(qt_(cit->prettyname()),
-                                       QVariant(toqstr(cit->name())));
-               } else if (form_->converters().isReachable("latex", cit->name())
-                          || form_->converters().isReachable("pdflatex", cit->name()))
-                       defaultFormatCB->addItem(qt_(cit->prettyname()),
-                                       QVariant(toqstr(cit->name())));
+               if (form_->converters().isReachable("xhtml", f.name())
+                   || form_->converters().isReachable("dviluatex", f.name())
+                   || form_->converters().isReachable("luatex", f.name())
+                   || form_->converters().isReachable("xetex", f.name())) {
+                       defaultFormatCB->addItem(prettyname,
+                                       QVariant(toqstr(f.name())));
+                       defaultOTFFormatCB->addItem(prettyname,
+                                       QVariant(toqstr(f.name())));
+               } else if (form_->converters().isReachable("latex", f.name())
+                          || form_->converters().isReachable("pdflatex", f.name()))
+                       defaultFormatCB->addItem(prettyname,
+                                       QVariant(toqstr(f.name())));
        }
 
        // restore selections
@@ -2119,10 +2234,10 @@ void PrefFileformats::on_formatsCB_editTextChanged(const QString &)
 void PrefFileformats::updatePrettyname()
 {
        QString const newname = formatsCB->currentText();
-       if (newname == qt_(currentFormat().prettyname()))
+       if (newname == toqstr(translateIfPossible(currentFormat().prettyname())))
                return;
 
-       currentFormat().setPrettyname(fromqstr(newname));
+       currentFormat().setPrettyname(qstring_to_ucs4(newname));
        formatsChanged();
        updateView();
        changed();
@@ -2133,13 +2248,13 @@ namespace {
        void updateComboBox(LyXRC::Alternatives const & alts,
                            string const & fmt, QComboBox * combo)
        {
-               LyXRC::Alternatives::const_iterator it = 
+               LyXRC::Alternatives::const_iterator it =
                                alts.find(fmt);
                if (it != alts.end()) {
                        LyXRC::CommandSet const & cmds = it->second;
-                       LyXRC::CommandSet::const_iterator sit = 
+                       LyXRC::CommandSet::const_iterator sit =
                                        cmds.begin();
-                       LyXRC::CommandSet::const_iterator const sen = 
+                       LyXRC::CommandSet::const_iterator const sen =
                                        cmds.end();
                        for (; sit != sen; ++sit) {
                                QString const qcmd = toqstr(*sit);
@@ -2224,7 +2339,7 @@ Format & PrefFileformats::currentFormat()
 
 void PrefFileformats::on_formatNewPB_clicked()
 {
-       form_->formats().add("", "", "", "", "", "", "", Format::none);
+       form_->formats().add("", "", docstring(), "", "", "", "", Format::none);
        updateView();
        formatsCB->setCurrentIndex(0);
        formatsCB->setFocus(Qt::OtherFocusReason);
@@ -2262,8 +2377,6 @@ PrefLanguage::PrefLanguage(GuiPreferences * form)
 {
        setupUi(this);
 
-       connect(rtlGB, SIGNAL(clicked()),
-               this, SIGNAL(changed()));
        connect(visualCursorRB, SIGNAL(clicked()),
                this, SIGNAL(changed()));
        connect(logicalCursorRB, SIGNAL(clicked()),
@@ -2295,19 +2408,16 @@ PrefLanguage::PrefLanguage(GuiPreferences * form)
        startCommandED->setValidator(new NoNewLineValidator(startCommandED));
        endCommandED->setValidator(new NoNewLineValidator(endCommandED));
 
-       uiLanguageCO->clear();
-
-       QAbstractItemModel * language_model = guiApp->languageModel();
-       // FIXME: it would be nice if sorting was enabled/disabled via a checkbox.
-       language_model->sort(0);
        defaultDecimalPointLE->setInputMask("X; ");
        defaultDecimalPointLE->setMaxLength(1);
 
        defaultLengthUnitCO->addItem(lyx::qt_(unit_name_gui[Length::CM]), Length::CM);
        defaultLengthUnitCO->addItem(lyx::qt_(unit_name_gui[Length::IN]), Length::IN);
 
-       set<string> added;
+       QAbstractItemModel * language_model = guiApp->languageModel();
+       language_model->sort(0);
        uiLanguageCO->blockSignals(true);
+       uiLanguageCO->clear();
        uiLanguageCO->addItem(qt_("Default"), toqstr("auto"));
        for (int i = 0; i != language_model->rowCount(); ++i) {
                QModelIndex index = language_model->index(i, 0);
@@ -2318,14 +2428,13 @@ PrefLanguage::PrefLanguage(GuiPreferences * form)
                if (!lang)
                        continue;
                // never remove the currently selected language
-               if (name != form->rc().gui_language 
+               if (name != form->rc().gui_language
                    && name != lyxrc.gui_language
                    && (!Messages::available(lang->code())
-                       || added.find(lang->code()) != added.end()))
-                               continue;
-               added.insert(lang->code());
+                       || !lang->hasGuiSupport()))
+                       continue;
                uiLanguageCO->addItem(index.data(Qt::DisplayRole).toString(),
-                       index.data(Qt::UserRole).toString());
+                                     index.data(Qt::UserRole).toString());
        }
        uiLanguageCO->blockSignals(false);
 }
@@ -2345,11 +2454,9 @@ void PrefLanguage::on_languagePackageCO_currentIndexChanged(int i)
 }
 
 
-void PrefLanguage::apply(LyXRC & rc) const
+void PrefLanguage::applyRC(LyXRC & rc) const
 {
-       // FIXME: remove rtl_support bool
-       rc.rtl_support = rtlGB->isChecked();
-       rc.visual_cursor = rtlGB->isChecked() && visualCursorRB->isChecked();
+       rc.visual_cursor = visualCursorRB->isChecked();
        rc.mark_foreign_language = markForeignCB->isChecked();
        rc.language_auto_begin = autoBeginCB->isChecked();
        rc.language_auto_end = autoEndCB->isChecked();
@@ -2373,10 +2480,8 @@ void PrefLanguage::apply(LyXRC & rc) const
 }
 
 
-void PrefLanguage::update(LyXRC const & rc)
+void PrefLanguage::updateRC(LyXRC const & rc)
 {
-       // FIXME: remove rtl_support bool
-       rtlGB->setChecked(rc.rtl_support);
        if (rc.visual_cursor)
                visualCursorRB->setChecked(true);
        else
@@ -2401,122 +2506,6 @@ void PrefLanguage::update(LyXRC const & rc)
 }
 
 
-/////////////////////////////////////////////////////////////////////
-//
-// PrefPrinter
-//
-/////////////////////////////////////////////////////////////////////
-
-PrefPrinter::PrefPrinter(GuiPreferences * form)
-       : PrefModule(catOutput, N_("Printer"), form)
-{
-       setupUi(this);
-
-       connect(printerAdaptCB, SIGNAL(clicked()),
-               this, SIGNAL(changed()));
-       connect(printerCommandED, SIGNAL(textChanged(QString)),
-               this, SIGNAL(changed()));
-       connect(printerNameED, SIGNAL(textChanged(QString)),
-               this, SIGNAL(changed()));
-       connect(printerPageRangeED, SIGNAL(textChanged(QString)),
-               this, SIGNAL(changed()));
-       connect(printerCopiesED, SIGNAL(textChanged(QString)),
-               this, SIGNAL(changed()));
-       connect(printerReverseED, SIGNAL(textChanged(QString)),
-               this, SIGNAL(changed()));
-       connect(printerToPrinterED, SIGNAL(textChanged(QString)),
-               this, SIGNAL(changed()));
-       connect(printerExtensionED, SIGNAL(textChanged(QString)),
-               this, SIGNAL(changed()));
-       connect(printerSpoolCommandED, SIGNAL(textChanged(QString)),
-               this, SIGNAL(changed()));
-       connect(printerPaperTypeED, SIGNAL(textChanged(QString)),
-               this, SIGNAL(changed()));
-       connect(printerEvenED, SIGNAL(textChanged(QString)),
-               this, SIGNAL(changed()));
-       connect(printerOddED, SIGNAL(textChanged(QString)),
-               this, SIGNAL(changed()));
-       connect(printerCollatedED, SIGNAL(textChanged(QString)),
-               this, SIGNAL(changed()));
-       connect(printerLandscapeED, SIGNAL(textChanged(QString)),
-               this, SIGNAL(changed()));
-       connect(printerToFileED, SIGNAL(textChanged(QString)),
-               this, SIGNAL(changed()));
-       connect(printerExtraED, SIGNAL(textChanged(QString)),
-               this, SIGNAL(changed()));
-       connect(printerSpoolPrefixED, SIGNAL(textChanged(QString)),
-               this, SIGNAL(changed()));
-       connect(printerPaperSizeED, SIGNAL(textChanged(QString)),
-               this, SIGNAL(changed()));
-
-       printerNameED->setValidator(new NoNewLineValidator(printerNameED));
-       printerCommandED->setValidator(new NoNewLineValidator(printerCommandED));
-       printerEvenED->setValidator(new NoNewLineValidator(printerEvenED));
-       printerPageRangeED->setValidator(new NoNewLineValidator(printerPageRangeED));
-       printerCopiesED->setValidator(new NoNewLineValidator(printerCopiesED));
-       printerReverseED->setValidator(new NoNewLineValidator(printerReverseED));
-       printerToFileED->setValidator(new NoNewLineValidator(printerToFileED));
-       printerPaperTypeED->setValidator(new NoNewLineValidator(printerPaperTypeED));
-       printerExtraED->setValidator(new NoNewLineValidator(printerExtraED));
-       printerOddED->setValidator(new NoNewLineValidator(printerOddED));
-       printerCollatedED->setValidator(new NoNewLineValidator(printerCollatedED));
-       printerLandscapeED->setValidator(new NoNewLineValidator(printerLandscapeED));
-       printerToPrinterED->setValidator(new NoNewLineValidator(printerToPrinterED));
-       printerExtensionED->setValidator(new NoNewLineValidator(printerExtensionED));
-       printerPaperSizeED->setValidator(new NoNewLineValidator(printerPaperSizeED));
-       printerSpoolCommandED->setValidator(new NoNewLineValidator(printerSpoolCommandED));
-       printerSpoolPrefixED->setValidator(new NoNewLineValidator(printerSpoolPrefixED));
-}
-
-
-void PrefPrinter::apply(LyXRC & rc) const
-{
-       rc.print_adapt_output = printerAdaptCB->isChecked();
-       rc.print_command = fromqstr(printerCommandED->text());
-       rc.printer = fromqstr(printerNameED->text());
-
-       rc.print_pagerange_flag = fromqstr(printerPageRangeED->text());
-       rc.print_copies_flag = fromqstr(printerCopiesED->text());
-       rc.print_reverse_flag = fromqstr(printerReverseED->text());
-       rc.print_to_printer = fromqstr(printerToPrinterED->text());
-       rc.print_file_extension = fromqstr(printerExtensionED->text());
-       rc.print_spool_command = fromqstr(printerSpoolCommandED->text());
-       rc.print_paper_flag = fromqstr(printerPaperTypeED->text());
-       rc.print_evenpage_flag = fromqstr(printerEvenED->text());
-       rc.print_oddpage_flag = fromqstr(printerOddED->text());
-       rc.print_collcopies_flag = fromqstr(printerCollatedED->text());
-       rc.print_landscape_flag = fromqstr(printerLandscapeED->text());
-       rc.print_to_file = internal_path(fromqstr(printerToFileED->text()));
-       rc.print_extra_options = fromqstr(printerExtraED->text());
-       rc.print_spool_printerprefix = fromqstr(printerSpoolPrefixED->text());
-       rc.print_paper_dimension_flag = fromqstr(printerPaperSizeED->text());
-}
-
-
-void PrefPrinter::update(LyXRC const & rc)
-{
-       printerAdaptCB->setChecked(rc.print_adapt_output);
-       printerCommandED->setText(toqstr(rc.print_command));
-       printerNameED->setText(toqstr(rc.printer));
-
-       printerPageRangeED->setText(toqstr(rc.print_pagerange_flag));
-       printerCopiesED->setText(toqstr(rc.print_copies_flag));
-       printerReverseED->setText(toqstr(rc.print_reverse_flag));
-       printerToPrinterED->setText(toqstr(rc.print_to_printer));
-       printerExtensionED->setText(toqstr(rc.print_file_extension));
-       printerSpoolCommandED->setText(toqstr(rc.print_spool_command));
-       printerPaperTypeED->setText(toqstr(rc.print_paper_flag));
-       printerEvenED->setText(toqstr(rc.print_evenpage_flag));
-       printerOddED->setText(toqstr(rc.print_oddpage_flag));
-       printerCollatedED->setText(toqstr(rc.print_collcopies_flag));
-       printerLandscapeED->setText(toqstr(rc.print_landscape_flag));
-       printerToFileED->setText(toqstr(external_path(rc.print_to_file)));
-       printerExtraED->setText(toqstr(rc.print_extra_options));
-       printerSpoolPrefixED->setText(toqstr(rc.print_spool_printerprefix));
-       printerPaperSizeED->setText(toqstr(rc.print_paper_dimension_flag));
-}
-
-
 /////////////////////////////////////////////////////////////////////
 //
 // PrefUserInterface
@@ -2546,13 +2535,13 @@ PrefUserInterface::PrefUserInterface(GuiPreferences * form)
        iconSetCO->addItem(qt_("Classic"), "classic");
        iconSetCO->addItem(qt_("Oxygen"), "oxygen");
 
-#if (!defined Q_WS_X11 || QT_VERSION < 0x040600)
+#if (!(defined Q_WS_X11 || defined(QPA_XCB)) || QT_VERSION < 0x040600)
        useSystemThemeIconsCB->hide();
 #endif
 }
 
 
-void PrefUserInterface::apply(LyXRC & rc) const
+void PrefUserInterface::applyRC(LyXRC & rc) const
 {
        rc.icon_set = fromqstr(iconSetCO->itemData(
                iconSetCO->currentIndex()).toString());
@@ -2564,7 +2553,7 @@ void PrefUserInterface::apply(LyXRC & rc) const
 }
 
 
-void PrefUserInterface::update(LyXRC const & rc)
+void PrefUserInterface::updateRC(LyXRC const & rc)
 {
        int iconset = iconSetCO->findData(toqstr(rc.icon_set));
        if (iconset < 0)
@@ -2622,10 +2611,12 @@ PrefDocHandling::PrefDocHandling(GuiPreferences * form)
                this, SIGNAL(changed()));
        connect(saveCompressedCB, SIGNAL(clicked()),
                this, SIGNAL(changed()));
+       connect(saveOriginCB, SIGNAL(clicked()),
+               this, SIGNAL(changed()));
 }
 
 
-void PrefDocHandling::apply(LyXRC & rc) const
+void PrefDocHandling::applyRC(LyXRC & rc) const
 {
        rc.use_lastfilepos = restoreCursorCB->isChecked();
        rc.load_session = loadSessionCB->isChecked();
@@ -2633,6 +2624,7 @@ void PrefDocHandling::apply(LyXRC & rc) const
        rc.autosave = autoSaveCB->isChecked() ?  autoSaveSB->value() * 60 : 0;
        rc.make_backup = backupCB->isChecked();
        rc.save_compressed = saveCompressedCB->isChecked();
+       rc.save_origin = saveOriginCB->isChecked();
        rc.open_buffers_in_tabs = openDocumentsInTabsCB->isChecked();
        rc.single_instance = singleInstanceCB->isChecked();
        rc.single_close_tab_button = singleCloseTabButtonCB->isChecked();
@@ -2653,7 +2645,7 @@ void PrefDocHandling::apply(LyXRC & rc) const
 }
 
 
-void PrefDocHandling::update(LyXRC const & rc)
+void PrefDocHandling::updateRC(LyXRC const & rc)
 {
        restoreCursorCB->setChecked(rc.use_lastfilepos);
        loadSessionCB->setChecked(rc.load_session);
@@ -2668,6 +2660,7 @@ void PrefDocHandling::update(LyXRC const & rc)
        autoSaveSB->setEnabled(autosave);
        backupCB->setChecked(rc.make_backup);
        saveCompressedCB->setChecked(rc.save_compressed);
+       saveOriginCB->setChecked(rc.save_origin);
        openDocumentsInTabsCB->setChecked(rc.open_buffers_in_tabs);
        singleInstanceCB->setChecked(rc.single_instance && !rc.lyxpipes.empty());
        singleInstanceCB->setEnabled(!rc.lyxpipes.empty());
@@ -2730,7 +2723,7 @@ PrefEdit::PrefEdit(GuiPreferences * form)
 }
 
 
-void PrefEdit::apply(LyXRC & rc) const
+void PrefEdit::applyRC(LyXRC & rc) const
 {
        rc.cursor_follows_scrollbar = cursorFollowsCB->isChecked();
        rc.scroll_below_document = scrollBelowCB->isChecked();
@@ -2753,7 +2746,7 @@ void PrefEdit::apply(LyXRC & rc) const
 }
 
 
-void PrefEdit::update(LyXRC const & rc)
+void PrefEdit::updateRC(LyXRC const & rc)
 {
        cursorFollowsCB->setChecked(rc.cursor_follows_scrollbar);
        scrollBelowCB->setChecked(rc.scroll_below_document);
@@ -2763,7 +2756,7 @@ void PrefEdit::update(LyXRC const & rc)
        macroEditStyleCO->setCurrentIndex(rc.macro_edit_style);
        cursorWidthSB->setValue(rc.cursor_width);
        toggleScrollbarCB->setChecked(rc.full_screen_scrollbar);
-       toggleScrollbarCB->setChecked(rc.full_screen_statusbar);
+       toggleStatusbarCB->setChecked(rc.full_screen_statusbar);
        toggleToolbarsCB->setChecked(rc.full_screen_toolbars);
        toggleTabbarCB->setChecked(rc.full_screen_tabbar);
        toggleMenubarCB->setChecked(rc.full_screen_menubar);
@@ -2787,7 +2780,9 @@ GuiShortcutDialog::GuiShortcutDialog(QWidget * parent) : QDialog(parent)
 
 
 PrefShortcuts::PrefShortcuts(GuiPreferences * form)
-       : PrefModule(catEditing, N_("Shortcuts"), form)
+       : PrefModule(catEditing, N_("Shortcuts"), form),
+         editItem_(0), mathItem_(0), bufferItem_(0), layoutItem_(0),
+         systemItem_(0)
 {
        setupUi(this);
 
@@ -2823,7 +2818,7 @@ PrefShortcuts::PrefShortcuts(GuiPreferences * form)
 }
 
 
-void PrefShortcuts::apply(LyXRC & rc) const
+void PrefShortcuts::applyRC(LyXRC & rc) const
 {
        rc.bind_file = internal_path(fromqstr(bindFileED->text()));
        // write user_bind and user_unbind to .lyx/bind/user.bind
@@ -2850,7 +2845,7 @@ void PrefShortcuts::apply(LyXRC & rc) const
 }
 
 
-void PrefShortcuts::update(LyXRC const & rc)
+void PrefShortcuts::updateRC(LyXRC const & rc)
 {
        bindFileED->setText(toqstr(external_path(rc.bind_file)));
        //
@@ -2905,17 +2900,30 @@ void PrefShortcuts::updateShortcutsTW()
        KeyMap::BindingList::const_iterator it = bindinglist.begin();
        KeyMap::BindingList::const_iterator it_end = bindinglist.end();
        for (; it != it_end; ++it)
-               insertShortcutItem(it->request, it->sequence, KeyMap::ItemType(it->tag));
+               insertShortcutItem(it->request, it->sequence, it->tag);
 
        shortcutsTW->sortItems(0, Qt::AscendingOrder);
-       QList<QTreeWidgetItem*> items = shortcutsTW->selectedItems();
-       removePB->setEnabled(!items.isEmpty() && !items[0]->text(1).isEmpty());
-       modifyPB->setEnabled(!items.isEmpty());
-
+       on_shortcutsTW_itemSelectionChanged();
+       on_searchLE_textEdited();
        shortcutsTW->resizeColumnToContents(0);
 }
 
 
+//static
+KeyMap::ItemType PrefShortcuts::itemType(QTreeWidgetItem & item)
+{
+       return static_cast<KeyMap::ItemType>(item.data(0, Qt::UserRole).toInt());
+}
+
+
+//static
+bool PrefShortcuts::isAlwaysHidden(QTreeWidgetItem & item)
+{
+       // Hide rebound system settings that are empty
+       return itemType(item) == KeyMap::UserUnbind && item.text(1).isEmpty();
+}
+
+
 void PrefShortcuts::setItemType(QTreeWidgetItem * item, KeyMap::ItemType tag)
 {
        item->setData(0, Qt::UserRole, QVariant(tag));
@@ -2935,7 +2943,7 @@ void PrefShortcuts::setItemType(QTreeWidgetItem * item, KeyMap::ItemType tag)
                font.setStrikeOut(true);
                break;
        }
-
+       item->setHidden(isAlwaysHidden(*item));
        item->setFont(1, font);
 }
 
@@ -2948,7 +2956,6 @@ QTreeWidgetItem * PrefShortcuts::insertShortcutItem(FuncRequest const & lfun,
        QString const lfun_name = toqstr(from_utf8(action_name)
                        + ' ' + lfun.argument());
        QString const shortcut = toqstr(seq.print(KeySequence::ForGui));
-       KeyMap::ItemType item_tag = tag;
 
        QTreeWidgetItem * newItem = 0;
        // for unbind items, try to find an existing item in the system bind list
@@ -2956,15 +2963,15 @@ QTreeWidgetItem * PrefShortcuts::insertShortcutItem(FuncRequest const & lfun,
                QList<QTreeWidgetItem*> const items = shortcutsTW->findItems(lfun_name,
                        Qt::MatchFlags(Qt::MatchExactly | Qt::MatchRecursive), 0);
                for (int i = 0; i < items.size(); ++i) {
-                       if (items[i]->text(1) == shortcut)
+                       if (items[i]->text(1) == shortcut) {
                                newItem = items[i];
                                break;
                        }
+               }
                // if not found, this unbind item is KeyMap::UserExtraUnbind
                // Such an item is not displayed to avoid confusion (what is
                // unmatched removed?).
                if (!newItem) {
-                       item_tag = KeyMap::UserExtraUnbind;
                        return 0;
                }
        }
@@ -2997,7 +3004,7 @@ QTreeWidgetItem * PrefShortcuts::insertShortcutItem(FuncRequest const & lfun,
        newItem->setText(1, shortcut);
        // record BindFile representation to recover KeySequence when needed.
        newItem->setData(1, Qt::UserRole, toqstr(seq.print(KeySequence::BindFile)));
-       setItemType(newItem, item_tag);
+       setItemType(newItem, tag);
        return newItem;
 }
 
@@ -3010,9 +3017,7 @@ void PrefShortcuts::on_shortcutsTW_itemSelectionChanged()
        if (items.isEmpty())
                return;
 
-       KeyMap::ItemType tag = 
-               static_cast<KeyMap::ItemType>(items[0]->data(0, Qt::UserRole).toInt());
-       if (tag == KeyMap::UserUnbind)
+       if (itemType(*items[0]) == KeyMap::UserUnbind)
                removePB->setText(qt_("Res&tore"));
        else
                removePB->setText(qt_("Remo&ve"));
@@ -3041,6 +3046,23 @@ void PrefShortcuts::modifyShortcut()
 }
 
 
+void PrefShortcuts::unhideEmpty(QString const & lfun, bool select)
+{
+       // list of items that match lfun
+       QList<QTreeWidgetItem*> items = shortcutsTW->findItems(lfun,
+            Qt::MatchFlags(Qt::MatchExactly | Qt::MatchRecursive), 0);
+       for (int i = 0; i < items.size(); ++i) {
+               QTreeWidgetItem * item = items[i];
+               if (isAlwaysHidden(*item)) {
+                       setItemType(item, KeyMap::System);
+                       if (select)
+                               shortcutsTW->setCurrentItem(item);
+                       return;
+               }
+       }
+}
+
+
 void PrefShortcuts::removeShortcut()
 {
        // it seems that only one item can be selected, but I am
@@ -3050,10 +3072,8 @@ void PrefShortcuts::removeShortcut()
                string shortcut = fromqstr(items[i]->data(1, Qt::UserRole).toString());
                string lfun = fromqstr(items[i]->text(0));
                FuncRequest func = lyxaction.lookupFunc(lfun);
-               KeyMap::ItemType tag = 
-                       static_cast<KeyMap::ItemType>(items[i]->data(0, Qt::UserRole).toInt());
 
-               switch (tag) {
+               switch (itemType(*items[i])) {
                case KeyMap::System: {
                        // for system bind, we do not touch the item
                        // but add an user unbind item
@@ -3072,11 +3092,19 @@ void PrefShortcuts::removeShortcut()
                        else
                                shortcutsTW->scrollToItem(parent);
                        user_bind_.unbind(shortcut, func);
+                       // If this user binding hid an empty system binding, unhide the
+                       // latter and select it.
+                       unhideEmpty(items[i]->text(0), true);
                        break;
                }
                case KeyMap::UserUnbind: {
                        // for user_unbind, we remove the unbind, and the item
                        // become KeyMap::System again.
+                       KeySequence seq;
+                       seq.parse(shortcut);
+                       // Ask the user to replace current binding
+                       if (!validateNewShortcut(func, seq, QString()))
+                               break;
                        user_unbind_.unbind(shortcut, func);
                        setItemType(items[i], KeyMap::System);
                        removePB->setText(qt_("Remo&ve"));
@@ -3094,6 +3122,37 @@ void PrefShortcuts::removeShortcut()
 }
 
 
+void PrefShortcuts::deactivateShortcuts(QList<QTreeWidgetItem*> const & items)
+{
+       for (int i = 0; i < items.size(); ++i) {
+               string shortcut = fromqstr(items[i]->data(1, Qt::UserRole).toString());
+               string lfun = fromqstr(items[i]->text(0));
+               FuncRequest func = lyxaction.lookupFunc(lfun);
+
+               switch (itemType(*items[i])) {
+               case KeyMap::System:
+                       // for system bind, we do not touch the item
+                       // but add an user unbind item
+                       user_unbind_.bind(shortcut, func);
+                       setItemType(items[i], KeyMap::UserUnbind);
+                       break;
+
+               case KeyMap::UserBind: {
+                       // for user_bind, we remove this bind
+                       QTreeWidgetItem * parent = items[i]->parent();
+                       int itemIdx = parent->indexOfChild(items[i]);
+                       parent->takeChild(itemIdx);
+                       user_bind_.unbind(shortcut, func);
+                       unhideEmpty(items[i]->text(0), false);
+                       break;
+               }
+               default:
+                       break;
+               }
+       }
+}
+
+
 void PrefShortcuts::selectBind()
 {
        QString file = form_->browsebind(internalPath(bindFileED->text()));
@@ -3133,8 +3192,11 @@ void PrefShortcuts::on_searchLE_textEdited()
        if (searchLE->text().isEmpty()) {
                // show all hidden items
                QTreeWidgetItemIterator it(shortcutsTW, QTreeWidgetItemIterator::Hidden);
-               while (*it)
-                       shortcutsTW->setItemHidden(*it++, false);
+               for (; *it; ++it)
+                       shortcutsTW->setItemHidden(*it, isAlwaysHidden(**it));
+               // close all categories
+               for (int i = 0; i < shortcutsTW->topLevelItemCount(); ++i)
+                       shortcutsTW->collapseItem(shortcutsTW->topLevelItem(i));
                return;
        }
        // search both columns
@@ -3148,10 +3210,11 @@ void PrefShortcuts::on_searchLE_textEdited()
        while (*it)
                shortcutsTW->setItemHidden(*it++, true);
        // show matched items
-       for (int i = 0; i < matched.size(); ++i) {
-               shortcutsTW->setItemHidden(matched[i], false);
-        shortcutsTW->setItemExpanded(matched[i]->parent(), true);
-       }
+       for (int i = 0; i < matched.size(); ++i)
+               if (!isAlwaysHidden(*matched[i])) {
+                       shortcutsTW->setItemHidden(matched[i], false);
+                       shortcutsTW->setItemExpanded(matched[i]->parent(), true);
+               }
 }
 
 
@@ -3164,37 +3227,55 @@ docstring makeCmdString(FuncRequest const & f)
 }
 
 
-void PrefShortcuts::shortcutOkPressed()
+FuncRequest PrefShortcuts::currentBinding(KeySequence const & k)
 {
-       QString const new_lfun = shortcut_->lfunLE->text();
-       FuncRequest func = lyxaction.lookupFunc(fromqstr(new_lfun));
+       FuncRequest res = user_bind_.getBinding(k);
+       if (res.action() != LFUN_UNKNOWN_ACTION)
+               return res;
+       res = system_bind_.getBinding(k);
+       // Check if it is unbound. Note: user_unbind_ can only unbind one
+       // FuncRequest per key sequence.
+       if (user_unbind_.getBinding(k) == res)
+               return FuncRequest::unknown;
+       return res;
+}
 
+
+bool PrefShortcuts::validateNewShortcut(FuncRequest const & func,
+                                        KeySequence const & k,
+                                        QString const & lfun_to_modify)
+{
        if (func.action() == LFUN_UNKNOWN_ACTION) {
                Alert::error(_("Failed to create shortcut"),
                        _("Unknown or invalid LyX function"));
-               return;
+               return false;
+       }
+
+       // It is not currently possible to bind Hidden lfuns such as self-insert. In
+       // the future, to remove this limitation, see GuiPrefs::insertShortcutItem
+       // and how it is used in GuiPrefs::shortcutOkPressed.
+       if (lyxaction.getActionType(func.action()) == LyXAction::Hidden) {
+               Alert::error(_("Failed to create shortcut"),
+                       _("This LyX function is hidden and cannot be bound."));
+               return false;
        }
 
-       KeySequence k = shortcut_->shortcutWG->getKeySequence();
        if (k.length() == 0) {
                Alert::error(_("Failed to create shortcut"),
                        _("Invalid or empty key sequence"));
-               return;
+               return false;
        }
 
-       // check to see if there's been any change
-       FuncRequest oldBinding = system_bind_.getBinding(k);
-       if (oldBinding.action() == LFUN_UNKNOWN_ACTION)
-               oldBinding = user_bind_.getBinding(k);
+       FuncRequest oldBinding = currentBinding(k);
        if (oldBinding == func)
-               // nothing has changed
-               return;
-       
+               // nothing to change
+               return false;
+
        // make sure this key isn't already bound---and, if so, prompt user
-       FuncCode const unbind = user_unbind_.getBinding(k).action();
+       // (exclude the lfun the user already wants to modify)
        docstring const action_string = makeCmdString(oldBinding);
-       if (oldBinding.action() > LFUN_NOACTION && unbind == LFUN_UNKNOWN_ACTION
-                 && save_lfun_ != toqstr(action_string)) {
+       if (oldBinding.action() != LFUN_UNKNOWN_ACTION
+           && lfun_to_modify != toqstr(action_string)) {
                docstring const new_action_string = makeCmdString(func);
                docstring const text = bformat(_("Shortcut `%1$s' is already bound to "
                                                 "%2$s.\n"
@@ -3205,35 +3286,42 @@ void PrefShortcuts::shortcutOkPressed()
                int ret = Alert::prompt(_("Redefine shortcut?"),
                                        text, 0, 1, _("&Redefine"), _("&Cancel"));
                if (ret != 0)
-                       return;
+                       return false;
                QString const sequence_text = toqstr(k.print(KeySequence::ForGui));
                QList<QTreeWidgetItem*> items = shortcutsTW->findItems(sequence_text,
                        Qt::MatchFlags(Qt::MatchExactly | Qt::MatchRecursive), 1);
-               if (items.size() > 0) {
-                       // should always happen
-                       bool expanded = items[0]->parent()->isExpanded();
-                       shortcutsTW->setCurrentItem(items[0]);
-                       removeShortcut();
-                       shortcutsTW->setCurrentItem(0);
-                       // make sure user doesn't see tree expansion if
-                       // old binding wasn't in an expanded tree
-                       if (!expanded)
-                               items[0]->parent()->setExpanded(false);
-               }
+               deactivateShortcuts(items);
        }
+       return true;
+}
 
-       shortcut_->accept();
 
-       if (!save_lfun_.isEmpty())
+void PrefShortcuts::shortcutOkPressed()
+{
+       QString const new_lfun = shortcut_->lfunLE->text();
+       FuncRequest func = lyxaction.lookupFunc(fromqstr(new_lfun));
+       KeySequence k = shortcut_->shortcutWG->getKeySequence();
+
+       // save_lfun_ contains the text of the lfun to modify, if the user clicked
+       // "modify", or is empty if they clicked "new" (which I do not really like)
+       if (!validateNewShortcut(func, k, save_lfun_))
+               return;
+
+       if (!save_lfun_.isEmpty()) {
                // real modification of the lfun's shortcut,
                // so remove the previous one
-               removeShortcut();
+               QList<QTreeWidgetItem*> to_modify = shortcutsTW->selectedItems();
+               deactivateShortcuts(to_modify);
+       }
+
+       shortcut_->accept();
 
        QTreeWidgetItem * item = insertShortcutItem(func, k, KeyMap::UserBind);
        if (item) {
                user_bind_.bind(&k, func);
                shortcutsTW->sortItems(0, Qt::AscendingOrder);
                shortcutsTW->setItemExpanded(item->parent(), true);
+               shortcutsTW->setCurrentItem(item);
                shortcutsTW->scrollToItem(item);
        } else {
                Alert::error(_("Failed to create shortcut"),
@@ -3282,14 +3370,14 @@ PrefIdentity::PrefIdentity(GuiPreferences * form)
 }
 
 
-void PrefIdentity::apply(LyXRC & rc) const
+void PrefIdentity::applyRC(LyXRC & rc) const
 {
        rc.user_name = fromqstr(nameED->text());
        rc.user_email = fromqstr(emailED->text());
 }
 
 
-void PrefIdentity::update(LyXRC const & rc)
+void PrefIdentity::updateRC(LyXRC const & rc)
 {
        nameED->setText(toqstr(rc.user_name));
        emailED->setText(toqstr(rc.user_email));
@@ -3304,7 +3392,8 @@ void PrefIdentity::update(LyXRC const & rc)
 /////////////////////////////////////////////////////////////////////
 
 GuiPreferences::GuiPreferences(GuiView & lv)
-       : GuiDialog(lv, "prefs", qt_("Preferences")), update_screen_font_(false)
+       : GuiDialog(lv, "prefs", qt_("Preferences")), update_screen_font_(false),
+         update_previews_(false)
 {
        setupUi(this);
 
@@ -3336,9 +3425,8 @@ GuiPreferences::GuiPreferences(GuiView & lv)
        addModule(new PrefSpellchecker(this));
 
        //for strftime validator
-       PrefOutput * output = new PrefOutput(this); 
+       PrefOutput * output = new PrefOutput(this);
        addModule(output);
-       addModule(new PrefPrinter(this));
        addModule(new PrefLatex(this));
 
        PrefConverters * converters = new PrefConverters(this);
@@ -3384,42 +3472,43 @@ void GuiPreferences::change_adaptor()
 }
 
 
-void GuiPreferences::apply(LyXRC & rc) const
+void GuiPreferences::applyRC(LyXRC & rc) const
 {
        size_t end = modules_.size();
        for (size_t i = 0; i != end; ++i)
-               modules_[i]->apply(rc);
+               modules_[i]->applyRC(rc);
 }
 
 
-void GuiPreferences::updateRc(LyXRC const & rc)
+void GuiPreferences::updateRC(LyXRC const & rc)
 {
        size_t const end = modules_.size();
        for (size_t i = 0; i != end; ++i)
-               modules_[i]->update(rc);
+               modules_[i]->updateRC(rc);
 }
 
 
 void GuiPreferences::applyView()
 {
-       apply(rc());
+       applyRC(rc());
 }
 
 
 bool GuiPreferences::initialiseParams(string const &)
 {
        rc_ = lyxrc;
-       formats_ = lyx::formats;
+       formats_ = theFormats();
        converters_ = theConverters();
        converters_.update(formats_);
        movers_ = theMovers();
        colors_.clear();
        update_screen_font_ = false;
-       
-       updateRc(rc_);
-       // Make sure that the bc is in the INITIAL state  
-       if (bc().policy().buttonStatus(ButtonPolicy::RESTORE))  
-               bc().restore();  
+       update_previews_ = false;
+
+       updateRC(rc_);
+       // Make sure that the bc is in the INITIAL state
+       if (bc().policy().buttonStatus(ButtonPolicy::RESTORE))
+               bc().restore();
 
        return true;
 }
@@ -3435,16 +3524,17 @@ void GuiPreferences::dispatchParams()
        prefsApplied(rc_);
        // FIXME: these need lfuns
        // FIXME UNICODE
-       Author const & author = 
+       Author const & author =
                Author(from_utf8(rc_.user_name), from_utf8(rc_.user_email));
        theBufferList().recordCurrentAuthor(author);
 
-       lyx::formats = formats_;
+       theFormats() = formats_;
 
        theConverters() = converters_;
-       theConverters().update(lyx::formats);
+       theConverters().update(formats_);
        theConverters().buildGraph();
-
+       theBufferList().invalidateConverterCache();
+       
        theMovers() = movers_;
 
        vector<string>::const_iterator it = colors_.begin();
@@ -3455,9 +3545,16 @@ void GuiPreferences::dispatchParams()
 
        if (update_screen_font_) {
                dispatch(FuncRequest(LFUN_SCREEN_FONT_UPDATE));
+               // resets flag in case second apply in same dialog
                update_screen_font_ = false;
        }
 
+        if (update_previews_) {
+               // resets flag in case second apply in same dialog
+               theBufferList().updatePreviews();
+               update_previews_ = false;
+       }
+
        // The Save button has been pressed
        if (isClosing())
                dispatch(FuncRequest(LFUN_PREFERENCES_SAVE));
@@ -3476,6 +3573,12 @@ void GuiPreferences::updateScreenFonts()
 }
 
 
+void GuiPreferences::updatePreviews()
+{
+       update_previews_ = true;
+}
+
+
 QString GuiPreferences::browsebind(QString const & file) const
 {
        return browseLibFile("bind", file, "bind", qt_("Choose bind file"),