diff --git a/src/Gui/PrefWidgets.cpp b/src/Gui/PrefWidgets.cpp index 3f353f4f7c03..03f965edfde3 100644 --- a/src/Gui/PrefWidgets.cpp +++ b/src/Gui/PrefWidgets.cpp @@ -29,6 +29,7 @@ #include #include +#include #include #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 hist = hGrp->GetASCIIs("Hist"); + for (const auto& it : hist) + history.append(QString::fromStdString(it)); + } + void clearHistory(ParameterGrp::handle hGrp) { + std::vector 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 menu(new QMenu(QString::fromLatin1("PrefQuantitySpinBox"))); menu->addMenu(editMenu); menu->addSeparator(); - // datastructure to remember actions for values - std::vector values; - std::vector 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::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() +void PrefQuantitySpinBox::restorePreferences() { - pushToHistory(); + Q_D(PrefQuantitySpinBox); + + // Do not restore values while saving them + if (d->isSaving) + return; + + 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::onRestore() +void PrefQuantitySpinBox::savePreferences() { - setToLastUsedValue(); + 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 &valueq) +void PrefQuantitySpinBox::pushToHistory(const QString &value) { Q_D(PrefQuantitySpinBox); + d->history.append(value.isEmpty() ? this->text() : value); - QString val; - if (valueq.isEmpty()) - val = this->text(); - else - val = valueq; - - 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()); - } - } + 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); } // -------------------------------------------------------------------- diff --git a/src/Gui/PrefWidgets.h b/src/Gui/PrefWidgets.h index 2e989e79dcd7..a4b3ce6483ec 100644 --- a/src/Gui/PrefWidgets.h +++ b/src/Gui/PrefWidgets.h @@ -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 @@ class GuiExport PrefQuantitySpinBox : public QuantitySpinBox 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 @@ class GuiExport PrefQuantitySpinBox : public QuantitySpinBox protected: virtual void contextMenuEvent(QContextMenuEvent * event); + // restore from/save to parameters + void restorePreferences(); + void savePreferences(); private: QScopedPointer d_ptr;