Gui: fix a couple of problems of class PrefQuantitySpinBox

* derive it from PrefWidget as any other preferences widget
* save history values to a separate group as otherwise two PrefQuantitySpinBox may override the values each other
This commit is contained in:
wmayer
2022-01-31 11:37:13 +01:00
parent f4a53c7eac
commit 6509c9ddec
2 changed files with 119 additions and 118 deletions

View File

@@ -29,6 +29,7 @@
#include <Base/Console.h>
#include <Base/Exception.h>
#include <Base/Tools.h>
#include <App/Application.h>
#include "PrefWidgets.h"
@@ -544,25 +545,72 @@ void PrefUnitSpinBox::savePreferences()
// --------------------------------------------------------------------
namespace Gui {
class HistoryList {
QStringList list;
int max_size = 5;
public:
const QStringList& asStringList() const {
return list;
}
int maximumSize() const {
return max_size;
}
void setMaximumSize(int num) {
max_size = num;
while (list.size() > num)
list.pop_front();
}
void clear() {
list.clear();
}
void append(const QString& value) {
if (!list.isEmpty() && list.back() == value)
return;
auto it = std::find(list.begin(), list.end(), value);
if (it != list.end())
list.erase(it);
else if (list.size() == max_size)
list.pop_front();
list.push_back(value);
}
};
class PrefQuantitySpinBoxPrivate
{
public:
PrefQuantitySpinBoxPrivate() :
historySize(5)
{
}
~PrefQuantitySpinBoxPrivate()
{
HistoryList history;
bool isSaving = false;
QByteArray getHistoryGroupName(QByteArray name) const {
return name + "_History";
}
QByteArray prefGrp;
ParameterGrp::handle handle;
int historySize;
void restoreHistory(ParameterGrp::handle hGrp) {
std::vector<std::string> hist = hGrp->GetASCIIs("Hist");
for (const auto& it : hist)
history.append(QString::fromStdString(it));
}
void clearHistory(ParameterGrp::handle hGrp) {
std::vector<std::string> hist = hGrp->GetASCIIs("Hist");
for (const auto& it : hist)
hGrp->RemoveASCII(it.c_str());
}
void saveHistory(ParameterGrp::handle hGrp) {
clearHistory(hGrp);
const QStringList& list = history.asStringList();
for (int i = 0; i < list.size(); i++) {
QByteArray key("Hist");
key.append(QByteArray::number(i));
hGrp->SetASCII(key, list[i].toUtf8());
}
}
};
}
PrefQuantitySpinBox::PrefQuantitySpinBox (QWidget * parent)
: QuantitySpinBox(parent), d_ptr(new PrefQuantitySpinBoxPrivate())
: QuantitySpinBox(parent)
, d_ptr(new PrefQuantitySpinBoxPrivate())
{
}
@@ -576,21 +624,16 @@ void PrefQuantitySpinBox::contextMenuEvent(QContextMenuEvent *event)
QMenu *editMenu = lineEdit()->createStandardContextMenu();
editMenu->setTitle(tr("Edit"));
QMenu* menu = new QMenu(QString::fromLatin1("PrefQuantitySpinBox"));
std::unique_ptr<QMenu> menu(new QMenu(QString::fromLatin1("PrefQuantitySpinBox")));
menu->addMenu(editMenu);
menu->addSeparator();
// datastructure to remember actions for values
std::vector<QString> values;
std::vector<QAction *> actions;
// add the history menu part...
QStringList history = getHistory();
for (QStringList::const_iterator it = history.begin();it!= history.end();++it) {
actions.push_back(menu->addAction(*it));
values.push_back(*it);
// data structure to remember actions for values
QStringList history = d->history.asStringList();
for (QStringList::const_iterator it = history.begin();it != history.end(); ++it) {
QAction* action = menu->addAction(*it);
action->setProperty("history_value", *it);
}
// add the save value portion of the menu
@@ -599,7 +642,7 @@ void PrefQuantitySpinBox::contextMenuEvent(QContextMenuEvent *event)
QAction *clearListAction = menu->addAction(tr("Clear list"));
clearListAction->setDisabled(history.empty());
// call the menu and wait until its back
// call the menu
QAction *userAction = menu->exec(event->globalPos());
// look what the user has chosen
@@ -607,123 +650,85 @@ void PrefQuantitySpinBox::contextMenuEvent(QContextMenuEvent *event)
pushToHistory(this->text());
}
else if (userAction == clearListAction) {
d->handle->Clear();
d->history.clear();
}
else {
int i=0;
for (std::vector<QAction *>::const_iterator it = actions.begin();it!=actions.end();++it,i++) {
if (*it == userAction) {
lineEdit()->setText(values[i]);
break;
}
else if (userAction) {
QVariant prop = userAction->property("history_value");
if (prop.isValid()) {
lineEdit()->setText(prop.toString());
}
}
delete menu;
}
void PrefQuantitySpinBox::onSave()
{
pushToHistory();
}
void PrefQuantitySpinBox::onRestore()
{
setToLastUsedValue();
}
void PrefQuantitySpinBox::pushToHistory(const QString &valueq)
void PrefQuantitySpinBox::restorePreferences()
{
Q_D(PrefQuantitySpinBox);
QString val;
if (valueq.isEmpty())
val = this->text();
else
val = valueq;
// Do not restore values while saving them
if (d->isSaving)
return;
std::string value(val.toUtf8());
if (d->handle.isValid()) {
try {
// do nothing if the given value is on top of the history
std::string tHist = d->handle->GetASCII("Hist0");
if (tHist != val.toUtf8().constData()) {
for (int i = d->historySize -1 ; i>=0 ;i--) {
QByteArray hist1 = "Hist";
QByteArray hist0 = "Hist";
hist1.append(QByteArray::number(i+1));
hist0.append(QByteArray::number(i));
std::string tHist = d->handle->GetASCII(hist0);
if (!tHist.empty())
d->handle->SetASCII(hist1,tHist.c_str());
}
d->handle->SetASCII("Hist0",value.c_str());
}
}
catch (const Base::Exception& e) {
Console().Warning("pushToHistory: %s\n", e.what());
}
if (getWindowParameter().isNull() || entryName().isEmpty()) {
failedToRestore(objectName());
return;
}
QString text = this->text();
text = QString::fromUtf8(getWindowParameter()->GetASCII(entryName(), text.toUtf8()).c_str());
lineEdit()->setText(text);
// Restore history
auto hGrp = getWindowParameter()->GetGroup(d->getHistoryGroupName(entryName()));
d->restoreHistory(hGrp);
}
void PrefQuantitySpinBox::savePreferences()
{
Q_D(PrefQuantitySpinBox);
if (getWindowParameter().isNull() || entryName().isEmpty()) {
failedToSave(objectName());
return;
}
getWindowParameter()->SetASCII( entryName(), text().toUtf8() );
// Save history
auto hGrp = getWindowParameter()->GetGroup(d->getHistoryGroupName(entryName()));
d->saveHistory(hGrp);
}
void PrefQuantitySpinBox::pushToHistory(const QString &value)
{
Q_D(PrefQuantitySpinBox);
d->history.append(value.isEmpty() ? this->text() : value);
Base::StateLocker lock(d->isSaving);
onSave();
}
QStringList PrefQuantitySpinBox::getHistory() const
{
Q_D(const PrefQuantitySpinBox);
QStringList res;
if (d->handle.isValid()) {
std::string tmp;
for (int i = 0 ; i< d->historySize ;i++) {
QByteArray hist = "Hist";
hist.append(QByteArray::number(i));
tmp = d->handle->GetASCII(hist);
if (!tmp.empty())
res.push_back(QString::fromUtf8(tmp.c_str()));
else
break; // end of history reached
}
}
return res;
return d->history.asStringList();
}
void PrefQuantitySpinBox::setToLastUsedValue()
{
QStringList hist = getHistory();
if (!hist.empty())
lineEdit()->setText(hist[0]);
}
void PrefQuantitySpinBox::setParamGrpPath(const QByteArray& path)
{
Q_D(PrefQuantitySpinBox);
QByteArray groupPath = path;
if (!groupPath.startsWith("User parameter:")) {
groupPath.prepend("User parameter:BaseApp/Preferences/");
}
d->handle = App::GetApplication().GetParameterGroupByPath(groupPath);
if (d->handle.isValid())
d->prefGrp = path;
}
QByteArray PrefQuantitySpinBox::paramGrpPath() const
{
Q_D(const PrefQuantitySpinBox);
if (d->handle.isValid())
return d->prefGrp;
return QByteArray();
lineEdit()->setText(hist.front());
}
int PrefQuantitySpinBox::historySize() const
{
Q_D(const PrefQuantitySpinBox);
return d->historySize;
return d->history.maximumSize();
}
void PrefQuantitySpinBox::setHistorySize(int i)
{
Q_D(PrefQuantitySpinBox);
d->historySize = i;
d->history.setMaximumSize(i);
}
// --------------------------------------------------------------------

View File

@@ -331,15 +331,16 @@ class PrefQuantitySpinBoxPrivate;
* The PrefQuantitySpinBox class.
* \author Werner Mayer
*/
class GuiExport PrefQuantitySpinBox : public QuantitySpinBox
class GuiExport PrefQuantitySpinBox : public QuantitySpinBox, public PrefWidget
{
Q_OBJECT
Q_PROPERTY(QByteArray prefEntry READ entryName WRITE setEntryName)
Q_PROPERTY(QByteArray prefPath READ paramGrpPath WRITE setParamGrpPath)
Q_PROPERTY(int historySize READ historySize WRITE setHistorySize)
public:
PrefQuantitySpinBox (QWidget * parent = 0);
PrefQuantitySpinBox (QWidget * parent = nullptr);
virtual ~PrefQuantitySpinBox();
/// set the input field to the last used value (works only if the setParamGrpPath() was called)
@@ -348,17 +349,9 @@ public:
int historySize() const;
/// set the value of the history size property
void setHistorySize(int);
/// Convenience method as offered by PrefWidget. Does the same as pushToHistory().
void onSave();
/// Convenience method as offered by PrefWidget. Does the same as setToLastUsedValue().
void onRestore();
/** @name history and default management */
//@{
/// the param group path where the widget writes and reads the default values
QByteArray paramGrpPath() const;
/// set the param group path where the widget writes and reads the default values
void setParamGrpPath(const QByteArray& name);
/// push a new value to the history, if no string given the actual text of the input field is used.
void pushToHistory(const QString& value = QString());
/// get the history of the field, newest first
@@ -367,6 +360,9 @@ public:
protected:
virtual void contextMenuEvent(QContextMenuEvent * event);
// restore from/save to parameters
void restorePreferences();
void savePreferences();
private:
QScopedPointer<PrefQuantitySpinBoxPrivate> d_ptr;