NEW: you can use any (preferably stepped/categorial) JKQTPMathImageColorPalette as default graph colors list in a style.ini file, by setting <tt>auto_styles/use_color_from_palette=PALETTE_NAME</tt>

FIXED/BREAKING: graph symbols were not properly applied when reading styles (in fact they were shuffled under some circumstances)
This commit is contained in:
jkriege2 2023-07-25 22:20:00 +02:00
parent a59218b8a8
commit 97c54916cf
5 changed files with 157 additions and 34 deletions

View File

@ -25,6 +25,7 @@ Changes, compared to \ref page_whatsnew_V4_0_0 "v4.0.0" include:
<li>BREAKING/REWORKED: Updated default styling of graphs. They are now more modern!</li>
<li>BREAKING/REWORKED: Implement better/more access functions to the graphs (inlcuding sorting, moving up/down, appending/prepending, graphs-iterators ...), solves issue <a href="https://github.com/jkriege2/JKQtPlotter/pull/97">#97</a>, thanks to <a href="https://github.com/sim186">user:sim186</a> for bringing this up</li>
<li>BREAKING/FIXED: fixed issue <a href="https://github.com/jkriege2/JKQtPlotter/pull/96">#96</a>: JKQTPlotter::saveAsPixelImage() does not add a border around the image any longer (can be reacivated by a new optional function parameter), thanks to <a href="https://github.com/nmielcarek">user:nmielcarek</a> for reporting</li>
<li>FIXED/BREAKING: graph symbols were not properly applied when reading styles (in fact they were shuffled under some circumstances)</li>
<li>FIXED issue described in <a href="https://github.com/jkriege2/JKQtPlotter/pull/62">#62: Fix custom labels draw, because giving exactly two label-strings did not display all of them</a>, thanks to <a href="https://github.com/FalsinSoft">user:FalsinSoft</a></li>
<li>FIXED issue <a href="https://github.com/jkriege2/JKQtPlotter/pull/70">#70: Typo in jkqtplotter/CMakeLists.txt</a>, thanks to <a href="https://github.com/tedlinlab">user:tedlinlab</a></li>
<li>FIXED issue <a href="https://github.com/jkriege2/JKQtPlotter/pull/80">#80: Bug with multiple inheritance with Q_GDAGET with CLANG</a>, thanks to <a href="https://github.com/igormironchik">user:igormironchik</a>, caused by <a href="https://bugreports.qt.io/browse/QTBUG-104874">QTBUG-104874</a></li>
@ -85,6 +86,7 @@ Changes, compared to \ref page_whatsnew_V4_0_0 "v4.0.0" include:
<li>NEW: several new color palettes (especially stepped/categorial palettes), e.g. JKQTPMathImageColorPalette::JKQTPMathImageOkabeIto_STEP, JKQTPMathImageColorPalette::JKQTPMathImageIBMColorBlindSafe, JKQTPMathImageColorPalette::JKQTPMathImageIBMColorBlindSafe_STEP, ...</li>
<li>NEW: add color palettes from Green's HELIX method, see <a href="https://arxiv.org/abs/1108.5083">https://arxiv.org/abs/1108.5083</a>, also see <a href="https://jiffyclub.github.io/palettable/cubehelix/">https://jiffyclub.github.io/palettable/cubehelix/</a>, see JKQTPCreateGreensCubeHelixLUT() and e.g. JKQTPMathImageCubeHelixClassic, JKQTPMathImageCubeHelix1, ...</li>
<li>NEW: Using Q_SIGNALS/Q_SLOTS instead of signals/slots MOC-keywords ... this allows for interoperability with other signals/slots frameworks, thanks to <a href="https://github.com/nickmontini">user:nickmontini</a> for the proposal</li>
<li>NEW: you can use any (preferably stepped/categorial) JKQTPMathImageColorPalette as default graph colors list in a style.ini file, by setting <tt>auto_styles/use_color_from_palette=PALETTE_NAME</tt></li>
</ul></li>
<li>JKQTMathText:<ul>

View File

@ -64,8 +64,8 @@ QMap<int, JKQTPImageTools::LUTData > JKQTPImageTools::getDefaultLUTs() {
lutstore[palette]=JKQTPImageTools::LUTData(palN, palNT);
JKQTPPaletteList lst;
lst<<jkqtp_qRgbOpaque(0xd50000);
lst<<jkqtp_qRgbOpaque(0xffdd00);
lst<<jkqtp_qRgbOpaque(0x0039d6);
lst<<jkqtp_qRgbOpaque(0xffdd00);
lst<<jkqtp_qRgbOpaque(0x00bb40);
lst<<jkqtp_qRgbOpaque(0xa84ce4);
lst<<jkqtp_qRgbOpaque(0xfd8600);
@ -2815,6 +2815,18 @@ QString JKQTPImageTools::JKQTPMathImageColorPalette2String(JKQTPMathImageColorPa
}
}
QString JKQTPImageTools::JKQTPMathImageColorPalette2StringHumanReadable(JKQTPMathImageColorPalette p)
{
std::lock_guard<std::mutex> lock(JKQTPImageTools::lutMutex);
auto it=JKQTPImageTools::global_jkqtpimagetools_lutstore.find(p);
if (it==JKQTPImageTools::global_jkqtpimagetools_lutstore.end()) return QString::number(static_cast<int>(p));
else {
if (it.value().nameT.size()>0) return it.value().nameT;
else if (it.value().name.size()>0) return it.value().name;
else return QString::number(static_cast<int>(p));
}
}
JKQTPMathImageColorPalette JKQTPImageTools::String2JKQTPMathImageColorPalette(const QString &p)
{
std::lock_guard<std::mutex> lock(JKQTPImageTools::lutMutex);
@ -2848,7 +2860,7 @@ JKQTPMathImageColorPalette JKQTPImageTools::String2JKQTPMathImageColorPalette(co
const JKQTPImageTools::LUTType& JKQTPImageTools::getLUTforPalette(QMap<int, JKQTPImageTools::LUTData >& lutstore, JKQTPMathImageColorPalette palette) {
const JKQTPImageTools::LUTType& JKQTPImageTools::getLUTforPalette(const QMap<int, JKQTPImageTools::LUTData >& lutstore, JKQTPMathImageColorPalette palette) {
static JKQTPImageTools::LUTType empty(JKQTPImageTools::LUTSIZE, 0);
auto it=lutstore.find(static_cast<int>(palette));
@ -2919,6 +2931,20 @@ QIcon JKQTPImageTools::GetPaletteIcon(JKQTPMathImageColorPalette palette) {
return JKQTPImageTools::GetPaletteIcon(static_cast<int>(palette));
}
const JKQTPImageTools::LUTType &JKQTPImageTools::getLUTforPalette(JKQTPMathImageColorPalette palette)
{
return getLUTforPalette(JKQTPImageTools::global_jkqtpimagetools_lutstore, palette);
}
QVector<QColor> JKQTPImageTools::getColorsforPalette(JKQTPMathImageColorPalette palette)
{
QVector<QColor> cols;
const auto& lut=JKQTPImageTools::getLUTforPalette(palette);
cols.reserve(lut.size());
std::for_each(lut.begin(), lut.end(), [&](QRgb c) { cols.push_back(c); });
return cols;
}

View File

@ -507,10 +507,14 @@ struct JKQTPImageTools {
/** \brief return a list of all globally available LUTs, machine-readable form */
static QStringList JKQTCOMMON_LIB_EXPORT getPredefinedPalettesMachineReadable();
/*! \brief convert the palette \a p to a string
/*! \brief convert the palette \a p to a machine-readable string
\see JKQTPImageTools::String2JKQTPMathImageColorPalette()
*/
static JKQTCOMMON_LIB_EXPORT QString JKQTPMathImageColorPalette2String(JKQTPMathImageColorPalette p);
/*! \brief convert the palette \a p to a human-readable (localized) string
\see JKQTPImageTools::String2JKQTPMathImageColorPalette()
*/
static JKQTCOMMON_LIB_EXPORT QString JKQTPMathImageColorPalette2StringHumanReadable(JKQTPMathImageColorPalette p);
/*! \brief convert the palette name \a p to JKQTPMathImageColorPalette (compatible with JKQTPImageTools::String2JKQTPMathImageColorPalette() )
\see JKQTPImageTools::JKQTPMathImageColorPalette2String()
@ -535,6 +539,10 @@ struct JKQTPImageTools {
/** \brief generates a QIcon for a specific JKQTPMathImageColorPalette */
static QIcon JKQTCOMMON_LIB_EXPORT GetPaletteIcon(JKQTPMathImageColorPalette palette) ;
/*! \brief create a LUT for a given JKQTPMathImageColorPalette, stored it in \a lutstore and return it */
static const LUTType& JKQTCOMMON_LIB_EXPORT getLUTforPalette(JKQTPMathImageColorPalette palette);
/*! \brief return the list of QColors making up a JKQTPMathImageColorPalette, stored it in \a lutstore and return it */
static QVector<QColor> JKQTCOMMON_LIB_EXPORT getColorsforPalette(JKQTPMathImageColorPalette palette);
private:
@ -577,7 +585,7 @@ struct JKQTPImageTools {
/*! \brief create a LUT for a given JKQTPMathImageColorPalette, store it in \a lutstore and return it
\internal
*/
static JKQTCOMMON_LIB_EXPORT const LUTType& getLUTforPalette(QMap<int, LUTData > &lutcache, JKQTPMathImageColorPalette palette);
static JKQTCOMMON_LIB_EXPORT const LUTType& getLUTforPalette(const QMap<int, LUTData > &lutcache, JKQTPMathImageColorPalette palette);
};

View File

@ -204,7 +204,17 @@ JKQTGraphsBaseStyle::JKQTGraphsBaseStyle(const JKQTBasePlotterStyle& parent):
impulseStyle(parent),
geometricStyle(parent),
annotationStyle(parent),
defaultPalette(JKQTPMathImageColorPalette::JKQTPMathImageMATLAB)
defaultPalette(JKQTPMathImageColorPalette::JKQTPMathImageMATLAB),
defaultGraphColors(getDefaultGraphColors()),
defaultGraphPenStyles(getDefaultGraphPenStyles()),
defaultGraphSymbols(getDefaultGraphSymbols()),
defaultGraphFillStyles(getDefaultGraphFillStyles())
{
}
QVector<QColor> JKQTGraphsBaseStyle::getDefaultGraphColors()
{
// color scale by Okabe & Ito:
// M. Okabe and K. Ito, “How to make figures and presentations that are friendly to color blind people,” University of Tokyo, 2002.
@ -212,11 +222,24 @@ JKQTGraphsBaseStyle::JKQTGraphsBaseStyle(const JKQTBasePlotterStyle& parent):
//defaultGraphColors<<QColor(0xD55E00).darker(150)<<QColor(0x0072B2).darker(150)<<QColor(0xF0E442).darker(150)<<QColor(0x009E73).darker(150)
// <<QColor(0x56B4E9).darker(150)<<QColor(0xE69F00).darker(150)<<QColor(0,0,0)<<QColor(0xCC79A7).darker(150);
// a bit brighter than above
defaultGraphColors<<QColor(0xD50000)<<QColor(0x0039D6)<<QColor(0xFFDD00)<<QColor(0x00BB40)<<QColor(0xA84CE4)<<QColor(0xFD8600)<<QColor(0x0B069C);
defaultGraphPenStyles<<Qt::SolidLine<<Qt::DashLine<<Qt::DotLine<<Qt::DashDotLine<<Qt::DashDotDotLine;
for (int i=2; i<=JKQTPMaxSymbolID; i++) defaultGraphSymbols.push_back(static_cast<JKQTPGraphSymbols>(i));
defaultGraphFillStyles<<Qt::SolidPattern;
return QVector<QColor>()<<QColor(0xD50000)<<QColor(0x0039D6)<<QColor(0xFFDD00)<<QColor(0x00BB40)<<QColor(0xA84CE4)<<QColor(0xFD8600)<<QColor(0x0B069C);
}
QVector<Qt::PenStyle> JKQTGraphsBaseStyle::getDefaultGraphPenStyles()
{
return QVector<Qt::PenStyle>()<<Qt::SolidLine<<Qt::DashLine<<Qt::DotLine<<Qt::DashDotLine<<Qt::DashDotDotLine;
}
QVector<JKQTPGraphSymbols> JKQTGraphsBaseStyle::getDefaultGraphSymbols()
{
QVector<JKQTPGraphSymbols> syms;
for (int i=2; i<=JKQTPMaxSymbolID; i++) syms.push_back(static_cast<JKQTPGraphSymbols>(i));
return syms;
}
QVector<Qt::BrushStyle> JKQTGraphsBaseStyle::getDefaultGraphFillStyles()
{
return QVector<Qt::BrushStyle>()<<Qt::SolidPattern;
}
void JKQTGraphsBaseStyle::loadSettings(const QSettings &settings, const QString &group, const JKQTGraphsBaseStyle &defaultStyle, const JKQTBasePlotterStyle& parent)
@ -242,18 +265,34 @@ void JKQTGraphsBaseStyle::loadSettings(const QSettings &settings, const QString
return -1;
};
defaultGraphColors.clear();
defaultGraphPenStyles.clear();
defaultGraphSymbols.clear();
defaultGraphFillStyles.clear();
QStringList allk=settings.allKeys();
bool loadColors=true;
if (settings.value("auto_styles/use_default_colors", false).toBool()) {
loadColors=false;
defaultGraphColors=defaultStyle.defaultGraphColors;
}
const QString ini_colors_fromm_palettes=settings.value("auto_styles/use_color_from_palette", "").toString();
if (JKQTPImageTools::getPredefinedPalettesMachineReadable().contains(ini_colors_fromm_palettes)) {
loadColors=false;
const auto& lut=JKQTPImageTools::getLUTforPalette(JKQTPImageTools::String2JKQTPMathImageColorPalette(ini_colors_fromm_palettes));
for (const auto& c: lut) {
defaultGraphColors.push_back(QColor(c));
}
}
const QStringList allk=settings.allKeys();
for (auto& k: allk) {
if (loadColors) {
int id=readID(k, group+"auto_styles/color");
if (id>=0) {
defaultGraphColors.push_back(jkqtp_String2QColor(settings.value(group+"auto_styles/color"+QString::number(id), jkqtp_QColor2String(QColor("red"))).toString()));
}
}
id=readID(k, group+"auto_styles/line_style");
int id=readID(k, group+"auto_styles/line_style");
if (id>=0) {
defaultGraphPenStyles.push_back(jkqtp_String2QPenStyle(settings.value(group+"auto_styles/line_style"+QString::number(id), jkqtp_QPenStyle2String(Qt::SolidLine)).toString()));
}
@ -268,22 +307,22 @@ void JKQTGraphsBaseStyle::loadSettings(const QSettings &settings, const QString
}
}
if (defaultGraphColors.size()==0) {
for (int i=defaultGraphColors.size(); i<defaultStyle.defaultGraphColors.size(); i++) {
for (int i=0; i<defaultStyle.defaultGraphColors.size(); i++) {
defaultGraphColors.push_back(defaultStyle.defaultGraphColors[i]);
}
}
if (defaultGraphPenStyles.size()==0) {
for (int i=defaultGraphPenStyles.size(); i<defaultStyle.defaultGraphPenStyles.size(); i++) {
for (int i=0; i<defaultStyle.defaultGraphPenStyles.size(); i++) {
defaultGraphPenStyles.push_back(defaultStyle.defaultGraphPenStyles[i]);
}
}
if (defaultGraphSymbols.size()==0) {
for (int i=defaultGraphSymbols.size(); i<defaultStyle.defaultGraphSymbols.size(); i++) {
for (int i=0; i<defaultStyle.defaultGraphSymbols.size(); i++) {
defaultGraphSymbols.push_back(defaultStyle.defaultGraphSymbols[i]);
}
}
if (defaultGraphFillStyles.size()==0) {
for (int i=defaultGraphFillStyles.size(); i<defaultStyle.defaultGraphFillStyles.size(); i++) {
for (int i=0; i<defaultStyle.defaultGraphFillStyles.size(); i++) {
defaultGraphFillStyles.push_back(defaultStyle.defaultGraphFillStyles[i]);
}
}
@ -306,26 +345,64 @@ void JKQTGraphsBaseStyle::saveSettings(QSettings &settings, const QString &group
settings.setValue(group+"palette", JKQTPImageTools::JKQTPMathImageColorPalette2String(defaultPalette));
bool saveSingleColors=true;
for (int pali=0; pali<static_cast<int>(JKQTPMathImagePREDEFINED_PALETTES_COUNT); pali++ ) {
const JKQTPMathImageColorPalette pal=static_cast<JKQTPMathImageColorPalette>(pali);
if (defaultGraphColors==JKQTPImageTools::getColorsforPalette(pal)) {
settings.setValue(group+"auto_styles/use_color_from_palette", JKQTPImageTools::JKQTPMathImageColorPalette2String(pal));
saveSingleColors=false;
break;
}
}
if (saveSingleColors && defaultGraphColors==getDefaultGraphColors()) {
settings.setValue(group+"auto_styles/use_default_colors", true);
saveSingleColors=false;
}
if (saveSingleColors) {
const QString maxnum=QString::number(defaultGraphColors.size());
int cnt=0;
for (auto& gs: defaultGraphColors) {
settings.setValue(group+"auto_styles/color"+QString::number(cnt), jkqtp_QColor2String(gs));
QString num=QString::number(cnt);
while (num.size()<maxnum.size()) num.prepend('0');
settings.setValue(group+"auto_styles/color"+num, jkqtp_QColor2String(gs));
cnt++;
}
cnt=0;
}
{
const QString maxnum=QString::number(defaultGraphPenStyles.size());
int cnt=0;
for (auto& gs: defaultGraphPenStyles) {
settings.setValue(group+"auto_styles/line_style"+QString::number(cnt), jkqtp_QPenStyle2String(gs));
QString num=QString::number(cnt);
while (num.size()<maxnum.size()) num.prepend('0');
settings.setValue(group+"auto_styles/line_style"+num, jkqtp_QPenStyle2String(gs));
cnt++;
}
cnt=0;
}
bool saveSingleSymbols=true;
if (defaultGraphSymbols==getDefaultGraphSymbols()) {
settings.setValue(group+"auto_styles/use_default_symbols", true);
saveSingleSymbols=false;
}
if (saveSingleSymbols) {
int cnt=0;
const QString maxnum=QString::number(defaultGraphSymbols.size());
for (auto& gs: defaultGraphSymbols) {
settings.setValue(group+"auto_styles/symbol"+QString::number(cnt), JKQTPGraphSymbols2String(gs));
QString num=QString::number(cnt);
while (num.size()<maxnum.size()) num.prepend('0');
settings.setValue(group+"auto_styles/symbol"+num, JKQTPGraphSymbols2String(gs));
cnt++;
}
cnt=0;
}
{
const QString maxnum=QString::number(defaultGraphFillStyles.size());
int cnt=0;
for (auto& gs: defaultGraphFillStyles) {
settings.setValue(group+"auto_styles/fill_style"+QString::number(cnt), jkqtp_QBrushStyle2String(gs));
QString num=QString::number(cnt);
while (num.size()<maxnum.size()) num.prepend('0');
settings.setValue(group+"auto_styles/fill_style"+num, jkqtp_QBrushStyle2String(gs));
cnt++;
}
}
defaultGraphStyle.saveSettings(settings, group+"graphs_base/");
barchartStyle.saveSettings(settings, group+"graphs_barchart/");
@ -358,6 +435,7 @@ const JKQTGraphsSpecificStyleProperties &JKQTGraphsBaseStyle::getGraphStyleByTyp
}
JKQTBarchartSpecificStyleProperties::JKQTBarchartSpecificStyleProperties(const JKQTBasePlotterStyle& parent):
JKQTGraphsSpecificStyleProperties(JKQTPPlotStyleType::Barchart, parent),
defaultRectRadiusAtValue(0),

View File

@ -360,6 +360,15 @@ class JKQTPLOTTER_LIB_EXPORT JKQTGraphsBaseStyle {
/** \brief Qt::BrushStyle used to automatically style different graphs differently */
QVector<Qt::BrushStyle> defaultGraphFillStyles;
/** \brief standard color palette for the default style */
static QVector<QColor> getDefaultGraphColors();
/** \brief a list of Qt::PenStyles used to automatically style different graphs differently in the default style */
static QVector<Qt::PenStyle> getDefaultGraphPenStyles();
/** \brief list of JKQTPGraphSymbols used to automatically assign to different graphs in the default style */
static QVector<JKQTPGraphSymbols> getDefaultGraphSymbols();
/** \brief list of Qt::BrushStyle used to automatically style different graphs differently in the default style */
static QVector<Qt::BrushStyle> getDefaultGraphFillStyles();
};
#endif // JKQTPGRAPHSBASESTYLE_H