lyx_mirror/src/frontends/qt4/GuiCharacter.cpp

496 lines
13 KiB
C++
Raw Normal View History

/**
* \file GuiCharacter.cpp
* This file is part of LyX, the document processor.
* Licence details can be found in the file COPYING.
*
* \author Angus Leeming
* \author Edwin Leuven
* \author John Levon
*
* Full author contact details are available in file CREDITS.
*/
#include <config.h>
#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 <QAbstractItemModel>
#include <QComboBox>
#include <QModelIndex>
#include <QSettings>
#include <QVariant>
using namespace std;
namespace lyx {
namespace frontend {
static QList<ShapePair> shapeData()
{
QList<ShapePair> shapes;
shapes << ShapePair(qt_("No change"), IGNORE_SHAPE);
shapes << ShapePair(qt_("Upright"), UP_SHAPE);
shapes << ShapePair(qt_("Italic"), ITALIC_SHAPE);
shapes << ShapePair(qt_("Slanted"), SLANTED_SHAPE);
shapes << ShapePair(qt_("Small Caps"), SMALLCAPS_SHAPE);
shapes << ShapePair(qt_("Reset"), INHERIT_SHAPE);
return shapes;
}
static QList<SizePair> sizeData()
{
QList<SizePair> sizes;
sizes << SizePair(qt_("No change"), FONT_SIZE_IGNORE);
sizes << SizePair(qt_("Tiny"), FONT_SIZE_TINY);
sizes << SizePair(qt_("Smallest"), FONT_SIZE_SCRIPT);
sizes << SizePair(qt_("Smaller"), FONT_SIZE_FOOTNOTE);
sizes << SizePair(qt_("Small"), FONT_SIZE_SMALL);
sizes << SizePair(qt_("Normal"), FONT_SIZE_NORMAL);
sizes << SizePair(qt_("Large"), FONT_SIZE_LARGE);
sizes << SizePair(qt_("Larger"), FONT_SIZE_LARGER);
sizes << SizePair(qt_("Largest"), FONT_SIZE_LARGEST);
sizes << SizePair(qt_("Huge"), FONT_SIZE_HUGE);
sizes << SizePair(qt_("Huger"), FONT_SIZE_HUGER);
sizes << SizePair(qt_("Increase"), FONT_SIZE_INCREASE);
sizes << SizePair(qt_("Decrease"), FONT_SIZE_DECREASE);
sizes << SizePair(qt_("Reset"), FONT_SIZE_INHERIT);
return sizes;
}
static QList<BarPair> barData()
{
QList<BarPair> bars;
bars << BarPair(qt_("No change"), IGNORE);
bars << BarPair(qt_("Emph"), EMPH_TOGGLE);
bars << BarPair(qt_("Underbar"), UNDERBAR_TOGGLE);
bars << BarPair(qt_("Double underbar"), UULINE_TOGGLE);
bars << BarPair(qt_("Wavy underbar"), UWAVE_TOGGLE);
bars << BarPair(qt_("Strike out"), STRIKEOUT_TOGGLE);
bars << BarPair(qt_("Cross out"), XOUT_TOGGLE);
bars << BarPair(qt_("Noun"), NOUN_TOGGLE);
bars << BarPair(qt_("Reset"), INHERIT);
return bars;
}
static QList<ColorCode> colorData()
{
QList<ColorCode> 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;
}
static QList<SeriesPair> seriesData()
{
QList<SeriesPair> series;
series << SeriesPair(qt_("No change"), IGNORE_SERIES);
series << SeriesPair(qt_("Medium"), MEDIUM_SERIES);
series << SeriesPair(qt_("Bold"), BOLD_SERIES);
series << SeriesPair(qt_("Reset"), INHERIT_SERIES);
return series;
}
static QList<FamilyPair> familyData()
{
QList<FamilyPair> families;
families << FamilyPair(qt_("No change"), IGNORE_FAMILY);
families << FamilyPair(qt_("Roman"), ROMAN_FAMILY);
families << FamilyPair(qt_("Sans Serif"), SANS_FAMILY);
families << FamilyPair(qt_("Typewriter"), TYPEWRITER_FAMILY);
families << FamilyPair(qt_("Reset"), INHERIT_FAMILY);
return families;
}
static QList<LanguagePair> languageData()
{
QList<LanguagePair> 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<typename T>
void fillCombo(QComboBox * combo, QList<T> const & list)
{
typename QList<T>::const_iterator cit = list.begin();
for (; cit != list.end(); ++cit)
combo->addItem(cit->first);
}
template<typename T>
void fillComboColor(QComboBox * combo, QList<T> const & list)
{
// at first add the 2 colors "No change" and "No color"
combo->addItem(qt_("No change"), "ignore");
combo->addItem(qt_("No color"), "none");
// now add the real colors
QPixmap coloritem(32, 32);
QColor color;
QList<ColorCode>::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");
}
Bulk cleanup/fix incorrect annotation at the end of namespaces. This commit does a bulk fix of incorrect annotations (comments) at the end of namespaces. The commit was generated by initially running clang-format, and then from the diff of the result extracting the hunks corresponding to fixes of namespace comments. The changes being applied and all the results have been manually reviewed. The source code successfully builds on macOS. Further details on the steps below, in case they're of interest to someone else in the future. 1. Checkout a fresh and up to date version of src/ git pull && git checkout -- src && git status src 2. Ensure there's a suitable .clang-format in place, i.e. with options to fix the comment at the end of namespaces, including: FixNamespaceComments: true SpacesBeforeTrailingComments: 1 and that clang-format is >= 5.0.0, by doing e.g.: clang-format -dump-config | grep Comments: clang-format --version 3. Apply clang-format to the source: clang-format -i $(find src -name "*.cpp" -or -name "*.h") 4. Create and filter out hunks related to fixing the namespace git diff -U0 src > tmp.patch grepdiff '^} // namespace' --output-matching=hunk tmp.patch > fix_namespace.patch 5. Filter out hunks corresponding to simple fixes into to a separate patch: pcregrep -M -e '^diff[^\n]+\nindex[^\n]+\n--- [^\n]+\n\+\+\+ [^\n]+\n' \ -e '^@@ -[0-9]+ \+[0-9]+ @@[^\n]*\n-\}[^\n]*\n\+\}[^\n]*\n' \ fix_namespace.patch > fix_namespace_simple.patch 6. Manually review the simple patch and then apply it, after first restoring the source. git checkout -- src patch -p1 < fix_namespace_simple.path 7. Manually review the (simple) changes and then stage the changes git diff src git add src 8. Again apply clang-format and filter out hunks related to any remaining fixes to the namespace, this time filter with more context. There will be fewer hunks as all the simple cases have already been handled: clang-format -i $(find src -name "*.cpp" -or -name "*.h") git diff src > tmp.patch grepdiff '^} // namespace' --output-matching=hunk tmp.patch > fix_namespace2.patch 9. Manually review/edit the resulting patch file to remove hunks for files which need to be dealt with manually, noting the file names and line numbers. Then restore files to as before applying clang-format and apply the patch: git checkout src patch -p1 < fix_namespace2.patch 10. Manually fix the files noted in the previous step. Stage files, review changes and commit.
2017-07-23 11:11:54 +00:00
} // namespace
GuiCharacter::GuiCharacter(GuiView & lv)
: GuiDialog(lv, "character", qt_("Text Style")), font_(ignore_font, ignore_language),
toggleall_(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(autoapplyCB, SIGNAL(stateChanged(int)), this,
SLOT(slotAutoApply()));
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()));
family = familyData();
series = seriesData();
shape = shapeData();
size = sizeData();
bar = barData();
color = colorData();
qSort(color.begin(), color.end(), ColorSorter);
language = languageData();
language.prepend(LanguagePair(qt_("Reset"), "reset"));
language.prepend(LanguagePair(qt_("No change"), "ignore"));
fillCombo(familyCO, family);
fillCombo(seriesCO, series);
fillCombo(sizeCO, size);
fillCombo(shapeCO, shape);
fillCombo(miscCO, bar);
fillComboColor(colorCO, color);
fillCombo(langCO, language);
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(langCO);
bc().addReadOnly(colorCO);
bc().addReadOnly(toggleallCB);
bc().addReadOnly(autoapplyCB);
#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
// 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();
#endif
}
void GuiCharacter::change_adaptor()
{
changed();
if (!autoapplyCB->isChecked())
return;
// to be really good here, we should set the combos to the values of
// the current text, and make it appear as "no change" if the values
// stay the same between applys. Might be difficult though wrt to a
// moved cursor - jbl
slotApply();
}
template<class P, class B>
static int findPos2nd(QList<P> const & vec, B const & val)
{
for (int i = 0; i != vec.size(); ++i)
if (vec[i].second == val)
return i;
return 0;
}
void GuiCharacter::updateContents()
{
if (!autoapplyCB->isChecked()) {
bc().setValid(true);
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;
paramsToDialog(font_);
}
static FontState getBar(FontInfo const & fi)
{
if (fi.emph() == FONT_TOGGLE)
return EMPH_TOGGLE;
if (fi.underbar() == FONT_TOGGLE)
return UNDERBAR_TOGGLE;
if (fi.strikeout() == FONT_TOGGLE)
return STRIKEOUT_TOGGLE;
if (fi.xout() == FONT_TOGGLE)
return XOUT_TOGGLE;
if (fi.uuline() == FONT_TOGGLE)
return UULINE_TOGGLE;
if (fi.uwave() == FONT_TOGGLE)
return UWAVE_TOGGLE;
if (fi.noun() == FONT_TOGGLE)
return NOUN_TOGGLE;
if (fi.emph() == FONT_IGNORE
&& fi.underbar() == FONT_IGNORE
&& fi.noun() == FONT_IGNORE)
return IGNORE;
return INHERIT;
}
static void setBar(FontInfo & fi, FontState val)
{
switch (val) {
case IGNORE:
fi.setEmph(FONT_IGNORE);
fi.setUnderbar(FONT_IGNORE);
fi.setStrikeout(FONT_IGNORE);
fi.setXout(FONT_IGNORE);
fi.setUuline(FONT_IGNORE);
fi.setUwave(FONT_IGNORE);
fi.setNoun(FONT_IGNORE);
break;
case EMPH_TOGGLE:
setBar(fi, INHERIT);
fi.setEmph(FONT_TOGGLE);
break;
case UNDERBAR_TOGGLE:
setBar(fi, INHERIT);
fi.setUnderbar(FONT_TOGGLE);
break;
case STRIKEOUT_TOGGLE:
setBar(fi, INHERIT);
fi.setStrikeout(FONT_TOGGLE);
break;
case XOUT_TOGGLE:
setBar(fi, INHERIT);
fi.setXout(FONT_TOGGLE);
break;
case UULINE_TOGGLE:
setBar(fi, INHERIT);
fi.setUuline(FONT_TOGGLE);
break;
case UWAVE_TOGGLE:
setBar(fi, INHERIT);
fi.setUwave(FONT_TOGGLE);
break;
case NOUN_TOGGLE:
setBar(fi, INHERIT);
fi.setNoun(FONT_TOGGLE);
break;
case INHERIT:
fi.setEmph(FONT_INHERIT);
fi.setUnderbar(FONT_INHERIT);
fi.setStrikeout(FONT_INHERIT);
fi.setXout(FONT_INHERIT);
fi.setUuline(FONT_INHERIT);
fi.setUwave(FONT_INHERIT);
fi.setNoun(FONT_INHERIT);
break;
}
}
void GuiCharacter::paramsToDialog(Font const & font)
{
FontInfo const & fi = font.fontInfo();
familyCO->setCurrentIndex(findPos2nd(family, fi.family()));
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(colorCO->findData(toqstr(lcolor.getLyXName(fi.color()))));
// 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_);
}
void GuiCharacter::applyView()
{
FontInfo & fi = font_.fontInfo();
fi.setFamily(family[familyCO->currentIndex()].second);
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(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
if (fi.family() != IGNORE_FAMILY
|| fi.series() != IGNORE_SERIES
|| fi.shape() != IGNORE_SHAPE
|| fi.size() != FONT_SIZE_IGNORE
|| getBar(fi) != IGNORE
|| fi.color() != Color_ignore
|| font_.language() != ignore_language)
setButtonsValid(true);
paramsToDialog(font_);
return true;
}
void GuiCharacter::dispatchParams()
{
dispatch(FuncRequest(getLfun(), font_.toString(toggleall_)));
}
void GuiCharacter::saveSession() const
{
Dialog::saveSession();
QSettings settings;
settings.setValue(sessionKey() + "/toggleall", toggleallCB->isChecked());
settings.setValue(sessionKey() + "/autoapply", autoapplyCB->isChecked());
}
void GuiCharacter::restoreSession()
{
Dialog::restoreSession();
QSettings settings;
toggleallCB->setChecked(
settings.value(sessionKey() + "/toggleall").toBool());
autoapplyCB->setChecked(
settings.value(sessionKey() + "/autoapply").toBool());
}
Dialog * createGuiCharacter(GuiView & lv) { return new GuiCharacter(lv); }
} // namespace frontend
} // namespace lyx
#include "moc_GuiCharacter.cpp"