X-Git-Url: https://git.lyx.org/gitweb/?a=blobdiff_plain;f=src%2Ffrontends%2Fqt4%2FGuiCharacter.cpp;h=349fea2c508ef47bc39fe7d1175d37c8e5ae42cc;hb=fe18bea3d07be1987a8c6c561b4c714e0c4fad2a;hp=a1d7abe03a18985d29253f18ae9dd14744df94a7;hpb=9db0f4a83c420f1df9ad90450ee909839f1d88ab;p=lyx.git diff --git a/src/frontends/qt4/GuiCharacter.cpp b/src/frontends/qt4/GuiCharacter.cpp index a1d7abe03a..349fea2c50 100644 --- a/src/frontends/qt4/GuiCharacter.cpp +++ b/src/frontends/qt4/GuiCharacter.cpp @@ -6,6 +6,7 @@ * \author Angus Leeming * \author Edwin Leuven * \author John Levon + * \author Jürgen Spitzmüller * * Full author contact details are available in file CREDITS. */ @@ -14,16 +15,29 @@ #include "GuiCharacter.h" +#include "GuiApplication.h" #include "qt_helpers.h" + #include "Font.h" #include "Buffer.h" #include "BufferParams.h" #include "BufferView.h" +#include "Color.h" +#include "ColorCache.h" +#include "ColorSet.h" #include "Cursor.h" #include "FuncRequest.h" #include "Language.h" #include "Paragraph.h" +#include "support/gettext.h" +#include "support/lstrings.h" + +#include +#include +#include +#include +#include using namespace std; @@ -68,28 +82,49 @@ static QList barData() { QList bars; bars << BarPair(qt_("No change"), IGNORE); - bars << BarPair(qt_("Emph"), EMPH_TOGGLE); - bars << BarPair(qt_("Underbar"), UNDERBAR_TOGGLE); - bars << BarPair(qt_("Noun"), NOUN_TOGGLE); - bars << BarPair(qt_("Reset"), INHERIT); + bars << BarPair(qt_("(Without)[[underlining]]"), NONE); + bars << BarPair(qt_("Single[[underlining]]"), UNDERBAR); + bars << BarPair(qt_("Double[[underlining]]"), UULINE); + bars << BarPair(qt_("Wavy"), UWAVE); + bars << BarPair(qt_("Reset"), INHERIT); return bars; } -static QList colorData() +static QList strikeData() { - QList colors; - colors << ColorPair(qt_("No change"), Color_ignore); - colors << ColorPair(qt_("No color"), Color_none); - colors << ColorPair(qt_("Black"), Color_black); - colors << ColorPair(qt_("White"), Color_white); - colors << ColorPair(qt_("Red"), Color_red); - colors << ColorPair(qt_("Green"), Color_green); - colors << ColorPair(qt_("Blue"), Color_blue); - colors << ColorPair(qt_("Cyan"), Color_cyan); - colors << ColorPair(qt_("Magenta"), Color_magenta); - colors << ColorPair(qt_("Yellow"), Color_yellow); - colors << ColorPair(qt_("Reset"), Color_inherit); + QList strike; + strike << BarPair(qt_("No change"), IGNORE); + strike << BarPair(qt_("(Without)[[strikethrough]]"), NONE); + strike << BarPair(qt_("Single[[strikethrough]]"), STRIKEOUT); + strike << BarPair(qt_("With /"), XOUT); + strike << BarPair(qt_("Reset"), INHERIT); + return strike; +} + + +static QList colorData() +{ + QList colors; + colors << Color_black; + colors << Color_blue; + colors << Color_brown; + colors << Color_cyan; + colors << Color_darkgray; + colors << Color_gray; + colors << Color_green; + colors << Color_lightgray; + colors << Color_lime; + colors << Color_magenta; + colors << Color_olive; + colors << Color_orange; + colors << Color_pink; + colors << Color_purple; + colors << Color_red; + colors << Color_teal; + colors << Color_violet; + colors << Color_white; + colors << Color_yellow; return colors; } @@ -116,50 +151,89 @@ static QList familyData() return families; } + +static QList languageData() +{ + QList list; + // FIXME (Abdel 14/05/2008): it would be nice if we could use this model + // directly in the language combo; but, as we need also the 'No Change' and + // 'Reset' items, this is not possible right now. Separating those two + // entries in radio buttons would be a better GUI IMHO. + QAbstractItemModel * language_model = guiApp->languageModel(); + // Make sure the items are sorted. + language_model->sort(0); + + for (int i = 0; i != language_model->rowCount(); ++i) { + QModelIndex index = language_model->index(i, 0); + list << LanguagePair(index.data(Qt::DisplayRole).toString(), + index.data(Qt::UserRole).toString()); + } + return list; +} + + namespace { template -void fillCombo(QComboBox * combo, QList list) +void fillCombo(QComboBox * combo, QList const & list) { typename QList::const_iterator cit = list.begin(); for (; cit != list.end(); ++cit) combo->addItem(cit->first); } +template +void fillComboColor(QComboBox * combo, QList const & list) +{ + // at first add the 2 colors "No change" and "No color" + combo->addItem(qt_("No change"), "ignore"); + combo->addItem(qt_("(Without)[[color]]"), "none"); + // now add the real colors + QPixmap coloritem(32, 32); + QColor color; + QList::const_iterator cit = list.begin(); + for (; cit != list.end(); ++cit) { + QString const lyxname = toqstr(lcolor.getLyXName(*cit)); + QString const guiname = toqstr(translateIfPossible(lcolor.getGUIName(*cit))); + color = QColor(guiApp->colorCache().get(*cit, false)); + coloritem.fill(color); + combo->addItem(QIcon(coloritem), guiname, lyxname); + } + //the last color is "Reset" + combo->addItem(qt_("Reset"), "inherit"); } +} // namespace + GuiCharacter::GuiCharacter(GuiView & lv) - : GuiDialog(lv, "character", qt_("Text Style")), font_(ignore_font, ignore_language), - toggleall_(false), reset_lang_(false) + : GuiDialog(lv, "character", qt_("Text Style")), + font_(ignore_font, ignore_language), emph_(false), noun_(false) { setupUi(this); connect(okPB, SIGNAL(clicked()), this, SLOT(slotOK())); connect(applyPB, SIGNAL(clicked()), this, SLOT(slotApply())); connect(closePB, SIGNAL(clicked()), this, SLOT(slotClose())); - - connect(miscCO, SIGNAL(activated(int)), this, SLOT(change_adaptor())); - connect(sizeCO, SIGNAL(activated(int)), this, SLOT(change_adaptor())); - connect(familyCO, SIGNAL(activated(int)), this, SLOT(change_adaptor())); - connect(seriesCO, SIGNAL(activated(int)), this, SLOT(change_adaptor())); - connect(shapeCO, SIGNAL(activated(int)), this, SLOT(change_adaptor())); - connect(colorCO, SIGNAL(activated(int)), this, SLOT(change_adaptor())); - connect(langCO, SIGNAL(activated(int)), this, SLOT(change_adaptor())); - connect(toggleallCB, SIGNAL(clicked()), this, SLOT(change_adaptor())); - -#ifdef Q_WS_MACX - // On Mac it's common to have tool windows which are always in the - // foreground and are hidden when the main window is not focused. - setWindowFlags(Qt::Tool); - autoapplyCB->setChecked(true); -#endif + connect(autoapplyCB, SIGNAL(stateChanged(int)), this, + SLOT(slotAutoApply())); + + connect(ulineCO, SIGNAL(currentIndexChanged(int)), this, SLOT(change_adaptor())); + connect(strikeCO, SIGNAL(currentIndexChanged(int)), this, SLOT(change_adaptor())); + connect(sizeCO, SIGNAL(currentIndexChanged(int)), this, SLOT(change_adaptor())); + connect(familyCO, SIGNAL(currentIndexChanged(int)), this, SLOT(change_adaptor())); + connect(seriesCO, SIGNAL(currentIndexChanged(int)), this, SLOT(change_adaptor())); + connect(shapeCO, SIGNAL(currentIndexChanged(int)), this, SLOT(change_adaptor())); + connect(colorCO, SIGNAL(currentIndexChanged(int)), this, SLOT(change_adaptor())); + connect(langCO, SIGNAL(currentIndexChanged(int)), this, SLOT(change_adaptor())); family = familyData(); series = seriesData(); shape = shapeData(); size = sizeData(); bar = barData(); + strike = strikeData(); color = colorData(); + qSort(color.begin(), color.end(), ColorSorter); language = languageData(); language.prepend(LanguagePair(qt_("Reset"), "reset")); @@ -169,33 +243,59 @@ GuiCharacter::GuiCharacter(GuiView & lv) fillCombo(seriesCO, series); fillCombo(sizeCO, size); fillCombo(shapeCO, shape); - fillCombo(miscCO, bar); - fillCombo(colorCO, color); + fillCombo(ulineCO, bar); + fillCombo(strikeCO, strike); + fillComboColor(colorCO, color); fillCombo(langCO, language); - bc().setPolicy(ButtonPolicy::OkApplyCancelReadOnlyPolicy); + bc().setPolicy(ButtonPolicy::OkApplyCancelAutoReadOnlyPolicy); bc().setOK(okPB); bc().setApply(applyPB); bc().setCancel(closePB); + bc().setAutoApply(autoapplyCB); bc().addReadOnly(familyCO); bc().addReadOnly(seriesCO); bc().addReadOnly(sizeCO); bc().addReadOnly(shapeCO); - bc().addReadOnly(miscCO); + bc().addReadOnly(ulineCO); + bc().addReadOnly(strikeCO); + bc().addReadOnly(nounCB); + bc().addReadOnly(emphCB); bc().addReadOnly(langCO); bc().addReadOnly(colorCO); - bc().addReadOnly(toggleallCB); bc().addReadOnly(autoapplyCB); -// FIXME: hack to work around resizing bug in Qt >= 4.2 -// bug verified with Qt 4.2.{0-3} (JSpitzm) -#if QT_VERSION >= 0x040200 - // qt resizes the comboboxes only after show(), so ... - QDialog::show(); +#ifdef Q_OS_MAC + // On Mac it's common to have tool windows which are always in the + // foreground and are hidden when the main window is not focused. + setWindowFlags(Qt::Tool); + autoapplyCB->setChecked(true); #endif } +void GuiCharacter::on_emphCB_clicked() +{ + // skip intermediate state at user click + if (!emph_) { + emphCB->setCheckState(Qt::Checked); + emph_ = true; + } + change_adaptor(); +} + + +void GuiCharacter::on_nounCB_clicked() +{ + // skip intermediate state at user click + if (!noun_) { + nounCB->setCheckState(Qt::Checked); + noun_ = true; + } + change_adaptor(); +} + + void GuiCharacter::change_adaptor() { changed(); @@ -221,66 +321,187 @@ static int findPos2nd(QList

const & vec, B const & val) } -void GuiCharacter::updateContents() +namespace{ +FontState getBar(FontInfo const & fi) { - if (!autoapplyCB->isChecked()) - return; - if (bufferview()->cursor().selection()) { - //FIXME: it would be better to check if each font attribute is constant - // for the selection range. - font_ = Font(ignore_font, ignore_language); - } else - font_ = bufferview()->cursor().current_font; + if (fi.underbar() == FONT_ON) + return UNDERBAR; - paramsToDialog(font_); + if (fi.uuline() == FONT_ON) + return UULINE; + + if (fi.uwave() == FONT_ON) + return UWAVE; + + if (fi.underbar() == FONT_IGNORE) + return IGNORE; + + return NONE; } -static FontState getBar(FontInfo const & fi) +FontState getStrike(FontInfo const & fi) { - if (fi.emph() == FONT_TOGGLE) - return EMPH_TOGGLE; + if (fi.strikeout() == FONT_ON) + return STRIKEOUT; - if (fi.underbar() == FONT_TOGGLE) - return UNDERBAR_TOGGLE; + if (fi.xout() == FONT_ON) + return XOUT; - if (fi.noun() == FONT_TOGGLE) - return NOUN_TOGGLE; - - if (fi.emph() == FONT_IGNORE - && fi.underbar() == FONT_IGNORE - && fi.noun() == FONT_IGNORE) + if (fi.strikeout() == FONT_IGNORE) return IGNORE; - return INHERIT; + return NONE; } -static void setBar(FontInfo & fi, FontState val) +Qt::CheckState getMarkupState(lyx::FontState fs) +{ + switch (fs) { + case FONT_OFF: + return Qt::Unchecked; + case FONT_ON: + return Qt::Checked; + case FONT_TOGGLE: + case FONT_INHERIT: + case FONT_IGNORE: + default: + return Qt::PartiallyChecked; + } +} + +lyx::FontState setMarkupState(Qt::CheckState cs) +{ + switch (cs) { + case Qt::Unchecked: + return FONT_OFF; + case Qt::Checked: + return FONT_ON; + case Qt::PartiallyChecked: + default: + return FONT_IGNORE; + } +} + +} // end namespace anon + + +void GuiCharacter::updateContents() +{ + if (bufferview()->cursor().selection()) { + Font font = bufferview()->cursor().real_current_font; + FontInfo fi = font.fontInfo(); + BufferParams const & bp = buffer().masterParams(); + + // Check if each font attribute is constant for the selection range. + DocIterator const from = bufferview()->cursor().selectionBegin(); + DocIterator const to = bufferview()->cursor().selectionEnd(); + for (DocIterator dit = from ; dit != to && !dit.atEnd(); ) { + if (!dit.inTexted()) { + dit.forwardPos(); + continue; + } + Paragraph const & par = dit.paragraph(); + pos_type const pos = dit.pos(); + Font tmp = par.getFont(bp, pos, font); + if (font.language() != tmp.language()) + font.setLanguage(ignore_language); + if (fi.family() != tmp.fontInfo().family()) + font.fontInfo().setFamily(IGNORE_FAMILY); + if (fi.series() != tmp.fontInfo().series()) + font.fontInfo().setSeries(IGNORE_SERIES); + if (fi.shape() != tmp.fontInfo().shape()) + font.fontInfo().setShape(IGNORE_SHAPE); + if (fi.size() != tmp.fontInfo().size()) + font.fontInfo().setSize(FONT_SIZE_IGNORE); + if (fi.emph() != tmp.fontInfo().emph()) + font.fontInfo().setEmph(FONT_IGNORE); + if (fi.noun() != tmp.fontInfo().noun()) + font.fontInfo().setNoun(FONT_IGNORE); + if (fi.color() != tmp.fontInfo().color()) + font.fontInfo().setColor(Color_ignore); + if (fi.underbar() != tmp.fontInfo().underbar() + || fi.uuline() != tmp.fontInfo().uuline() + || fi.uwave() != tmp.fontInfo().uwave()) + setBar(font.fontInfo(), IGNORE); + if (fi.strikeout() != tmp.fontInfo().strikeout() + || fi.xout() != tmp.fontInfo().xout()) + setStrike(font.fontInfo(), IGNORE); + dit.forwardPos(); + } + font_ = font; + } else + font_ = bufferview()->cursor().real_current_font; + + paramsToDialog(font_); +} + + +void GuiCharacter::setBar(FontInfo & fi, FontState val) { switch (val) { case IGNORE: - fi.setEmph(FONT_IGNORE); fi.setUnderbar(FONT_IGNORE); - fi.setNoun(FONT_IGNORE); + fi.setUuline(FONT_IGNORE); + fi.setUwave(FONT_IGNORE); break; - - case EMPH_TOGGLE: - fi.setEmph(FONT_TOGGLE); + case UNDERBAR: + setBar(fi, NONE); + fi.setUnderbar(FONT_ON); break; - - case UNDERBAR_TOGGLE: - fi.setUnderbar(FONT_TOGGLE); + case UULINE: + setBar(fi, NONE); + fi.setUuline(FONT_ON); break; - - case NOUN_TOGGLE: - fi.setNoun(FONT_TOGGLE); + case UWAVE: + setBar(fi, NONE); + fi.setUwave(FONT_ON); break; - case INHERIT: - fi.setEmph(FONT_INHERIT); fi.setUnderbar(FONT_INHERIT); - fi.setNoun(FONT_INHERIT); + fi.setUuline(FONT_INHERIT); + fi.setUwave(FONT_INHERIT); + break; + case NONE: + fi.setUnderbar(FONT_OFF); + fi.setUuline(FONT_OFF); + fi.setUwave(FONT_OFF); + break; + case XOUT: + case STRIKEOUT: + default: + break; + } +} + + +void GuiCharacter::setStrike(FontInfo & fi, FontState val) +{ + switch (val) { + case IGNORE: + fi.setStrikeout(FONT_IGNORE); + fi.setXout(FONT_IGNORE); + break; + case STRIKEOUT: + setStrike(fi, NONE); + fi.setStrikeout(FONT_ON); + break; + case XOUT: + setStrike(fi, NONE); + fi.setXout(FONT_ON); + break; + case INHERIT: + fi.setStrikeout(FONT_INHERIT); + fi.setXout(FONT_INHERIT); + break; + case NONE: + fi.setStrikeout(FONT_OFF); + fi.setXout(FONT_OFF); + break; + case UNDERBAR: + case UWAVE: + case UULINE: + default: break; } } @@ -293,14 +514,20 @@ void GuiCharacter::paramsToDialog(Font const & font) seriesCO->setCurrentIndex(findPos2nd(series, fi.series())); shapeCO->setCurrentIndex(findPos2nd(shape, fi.shape())); sizeCO->setCurrentIndex(findPos2nd(size, fi.size())); - miscCO->setCurrentIndex(findPos2nd(bar, getBar(fi))); - colorCO->setCurrentIndex(findPos2nd(color, fi.color())); - - QString const lang = (font.language() == ignore_language) - ? "ignore" : toqstr(font.language()->lang()); + ulineCO->setCurrentIndex(findPos2nd(bar, getBar(fi))); + strikeCO->setCurrentIndex(findPos2nd(strike, getStrike(fi))); + colorCO->setCurrentIndex(colorCO->findData(toqstr(lcolor.getLyXName(fi.color())))); + emphCB->setCheckState(getMarkupState(fi.emph())); + nounCB->setCheckState(getMarkupState(fi.noun())); + emph_ = emphCB->checkState() == Qt::Checked; + noun_ = nounCB->checkState() == Qt::Checked; + + // reset_language is a null pointer. + QString const lang = (font.language() == reset_language) + ? "reset" : toqstr(font.language()->lang()); langCO->setCurrentIndex(findPos2nd(language, lang)); - - toggleallCB->setChecked(toggleall_); + // disable the OK/Apply buttons, since we have no changes yet + bc().setValid(false); } @@ -311,18 +538,22 @@ void GuiCharacter::applyView() fi.setSeries(series[seriesCO->currentIndex()].second); fi.setShape(shape[shapeCO->currentIndex()].second); fi.setSize(size[sizeCO->currentIndex()].second); - setBar(fi, bar[miscCO->currentIndex()].second); - fi.setColor(color[colorCO->currentIndex()].second); + fi.setEmph(setMarkupState(emphCB->checkState())); + fi.setNoun(setMarkupState(nounCB->checkState())); + setBar(fi, bar[ulineCO->currentIndex()].second); + setStrike(fi, strike[strikeCO->currentIndex()].second); + fi.setColor(lcolor.getFromLyXName(fromqstr(colorCO->itemData(colorCO->currentIndex()).toString()))); font_.setLanguage(languages.getLanguage( fromqstr(language[langCO->currentIndex()].second))); - - toggleall_ = toggleallCB->isChecked(); } bool GuiCharacter::initialiseParams(string const &) { + if (autoapplyCB->isChecked()) + return true; + FontInfo & fi = font_.fontInfo(); // so that the user can press Ok @@ -342,7 +573,23 @@ bool GuiCharacter::initialiseParams(string const &) void GuiCharacter::dispatchParams() { - dispatch(FuncRequest(getLfun(), font_.toString(toggleall_))); + dispatch(FuncRequest(getLfun(), font_.toString(false))); +} + + +void GuiCharacter::saveSession(QSettings & settings) const +{ + Dialog::saveSession(settings); + settings.setValue(sessionKey() + "/autoapply", autoapplyCB->isChecked()); +} + + +void GuiCharacter::restoreSession() +{ + Dialog::restoreSession(); + QSettings settings; + autoapplyCB->setChecked( + settings.value(sessionKey() + "/autoapply").toBool()); } @@ -352,4 +599,4 @@ Dialog * createGuiCharacter(GuiView & lv) { return new GuiCharacter(lv); } } // namespace frontend } // namespace lyx -#include "GuiCharacter_moc.cpp" +#include "moc_GuiCharacter.cpp"