[Gui] Add StatefulLabel

This commit is contained in:
Chris Hennes
2021-10-02 22:15:47 -05:00
parent 5cc7d017cc
commit 8f1cf9496f
3 changed files with 161 additions and 0 deletions

View File

@@ -874,6 +874,107 @@ void UrlLabel::setUrl(const QString& u)
// --------------------------------------------------------------------
StatefulLabel::StatefulLabel(QWidget* parent)
: QLabel(parent)
{
}
StatefulLabel::~StatefulLabel()
{
}
QString StatefulLabel::state() const
{
return _state;
}
void StatefulLabel::setDefaultStyle(const QString& defaultStyle)
{
_defaultStyle = defaultStyle;
}
void StatefulLabel::registerState(const QString& state, const QString& styleCSS,
const std::string& preferenceLocation,
const std::string& preferenceName)
{
_availableStates[state] = { QColor(), QColor(), styleCSS, preferenceLocation, preferenceName };
}
void StatefulLabel::registerState(const QString& state, const QColor& color,
const std::string& preferenceLocation,
const std::string& preferenceName)
{
_availableStates[state] = {color, QColor(), QString(), preferenceLocation, preferenceName};
}
void StatefulLabel::registerState(const QString& state, const QColor& foreground, const QColor& background,
const std::string& preferenceLocation,
const std::string& preferenceName)
{
_availableStates[state] = { foreground, background, QString(), preferenceLocation, preferenceName };
}
void StatefulLabel::setState(const QString& state)
{
_state = state;
if (auto entry = _availableStates.find(state); entry != _availableStates.end()) {
// Order of precedence: first, check if the user has set this in their preferences:
if (!entry->second.preferenceLocation.empty() && !entry->second.preferenceString.empty()) {
ParameterGrp::handle hGrp = App::GetApplication().GetParameterGroupByPath(entry->second.preferenceLocation.c_str());
// First, try to see if it's just stored a color (as an unsigned int):
auto availableColorPrefs = hGrp->GetUnsignedMap();
for (const auto &unsignedEntry : availableColorPrefs) {
if (unsignedEntry.first == entry->second.preferenceString) {
// Convert the stored Uint into usable color data:
unsigned int col = unsignedEntry.second;
QColor qcolor((col >> 24) & 0xff, (col >> 16) & 0xff, (col >> 8) & 0xff);
this->setStyleSheet(QString::fromUtf8("Gui--StatefulLabel{ color : rgba(%1,%2,%3,%4) ;}").arg(qcolor.red()).arg(qcolor.green()).arg(qcolor.blue()).arg(qcolor.alpha()));
return;
}
}
// If not, try to see if there's an entire style string set as ASCII:
auto availableStringPrefs = hGrp->GetASCIIMap();
for (const auto& stringEntry : availableStringPrefs) {
if (stringEntry.first == entry->second.preferenceString) {
this->setStyleSheet(QString::fromStdString(stringEntry.second));
return;
}
}
}
// If there is no preferences entry for this label, allow the stylesheet to set it, and only set to the default
// formatting if there is no stylesheet entry
if (styleSheet().isEmpty()) {
if (!entry->second.defaultCSS.isEmpty()) {
this->setStyleSheet(entry->second.defaultCSS);
return;
}
else {
auto fg = entry->second.foregroundColor;
auto bg = entry->second.backgroundColor;
QString colorEntries;
if (fg.isValid())
colorEntries.append(QString::fromUtf8("color : rgba(%1,%2,%3,%4);").arg(fg.red()).arg(fg.green()).arg(fg.blue()).arg(fg.alpha()));
if (bg.isValid())
colorEntries.append(QString::fromUtf8("background-color : rgba(%1,%2,%3,%4);").arg(bg.red()).arg(bg.green()).arg(bg.blue()).arg(bg.alpha()));
std::string tempForTesting = QString::fromUtf8("Gui--StatefulLabel{ %1 }").arg(colorEntries).toStdString();
this->setStyleSheet(QString::fromUtf8("Gui--StatefulLabel{ %1 }").arg(colorEntries));
return;
}
}
// else the stylesheet has already set our appearance, no need to do anything
}
else {
if (styleSheet().isEmpty()) {
this->setStyleSheet(_defaultStyle);
}
}
}
// --------------------------------------------------------------------
/* TRANSLATOR Gui::LabelButton */
/**

View File

@@ -273,6 +273,65 @@ private:
QString _url;
};
/**
* A text label whose appearance can change based on a specified state.
*
* The state is an arbitrary string exposed as a Qt Property (and thus available for selection via
* a stylesheet). This is intended for things like messages to the user, where a message that is an
* "error" might be colored differently than one that is a "warning" or a "message".
*
* In order of style precedence for a given state: User preference > Stylesheet > Default
*
* @author Chris Hennes
*/
class GuiExport StatefulLabel : public QLabel
{
Q_OBJECT
Q_PROPERTY( QString state READ state WRITE setState)
public:
StatefulLabel(QWidget* parent = nullptr);
virtual ~StatefulLabel();
QString state() const;
/** If an unrecognized state is set, use this style */
void setDefaultStyle(const QString &defaultStyle);
/** Register a state and its corresponding style (optionally attached to a user preference) */
void registerState(const QString &state, const QString &styleCSS,
const std::string& preferenceLocation = std::string(),
const std::string& preferenceName = std::string());
/** For convenience, allow simple color-only states via QColor (optionally attached to a user preference) */
void registerState(const QString& state, const QColor& color,
const std::string& preferenceLocation = std::string(),
const std::string& preferenceName = std::string());
/** For convenience, allow simple color-only states via QColor (optionally attached to a user preference) */
void registerState(const QString& state, const QColor& foreground, const QColor &background,
const std::string& preferenceLocation = std::string(),
const std::string& preferenceName = std::string());
public Q_SLOTS:
void setState(const QString &state);
private:
QString _state;
struct StateData {
QColor foregroundColor;
QColor backgroundColor;
QString defaultCSS;
std::string preferenceLocation;
std::string preferenceString;
};
std::map<QString, StateData> _availableStates;
QString _defaultStyle;
};
// ----------------------------------------------------------------------
/**

View File

@@ -111,6 +111,7 @@ WidgetFactorySupplier::WidgetFactorySupplier()
new WidgetProducer<Gui::ActionSelector>;
new WidgetProducer<Gui::ColorButton>;
new WidgetProducer<Gui::UrlLabel>;
new WidgetProducer<Gui::StatefulLabel>;
new WidgetProducer<Gui::FileChooser>;
new WidgetProducer<Gui::UIntSpinBox>;
new WidgetProducer<Gui::IntSpinBox>;