diff --git a/src/kdefrontend/dockwidgets/ColumnDock.cpp b/src/kdefrontend/dockwidgets/ColumnDock.cpp index 9e3564697..b7c8e4cfa 100644 --- a/src/kdefrontend/dockwidgets/ColumnDock.cpp +++ b/src/kdefrontend/dockwidgets/ColumnDock.cpp @@ -1,423 +1,436 @@ /*************************************************************************** File : ColumnDock.cpp Project : LabPlot -------------------------------------------------------------------- - Copyright : (C) 2011-2017 by Alexander Semke (alexander.semke@web.de) + Copyright : (C) 2011-2018 by Alexander Semke (alexander.semke@web.de) Copyright : (C) 2013-2017 by Stefan Gerlach (stefan.gerlach@uni.kn) Description : widget for column properties ***************************************************************************/ /*************************************************************************** * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the Free Software * * Foundation, Inc., 51 Franklin Street, Fifth Floor, * * Boston, MA 02110-1301 USA * * * ***************************************************************************/ #include "ColumnDock.h" #include "backend/core/AbstractFilter.h" #include "backend/core/datatypes/SimpleCopyThroughFilter.h" #include "backend/core/datatypes/Double2StringFilter.h" #include "backend/core/datatypes/String2DoubleFilter.h" #include "backend/core/datatypes/DateTime2StringFilter.h" #include "backend/core/datatypes/String2DateTimeFilter.h" #include "backend/datasources/LiveDataSource.h" #include "backend/spreadsheet/Spreadsheet.h" #include /*! \class ColumnDock \brief Provides a widget for editing the properties of the spreadsheet columns currently selected in the project explorer. \ingroup kdefrontend */ ColumnDock::ColumnDock(QWidget* parent) : QWidget(parent), m_column(nullptr), m_initializing(false) { ui.setupUi(this); connect(ui.leName, &QLineEdit::textChanged, this, &ColumnDock::nameChanged); connect(ui.leComment, &QLineEdit::textChanged, this, &ColumnDock::commentChanged); connect(ui.cbType, SIGNAL(currentIndexChanged(int)), this, SLOT(typeChanged(int))); connect(ui.cbFormat, SIGNAL(currentIndexChanged(int)), this, SLOT(formatChanged(int))); connect(ui.sbPrecision, SIGNAL(valueChanged(int)), this, SLOT(precisionChanged(int)) ); connect(ui.cbPlotDesignation, SIGNAL(currentIndexChanged(int)), this, SLOT(plotDesignationChanged(int))); retranslateUi(); } void ColumnDock::setColumns(QList list) { m_initializing = true; m_columnsList = list; m_column = list.first(); //check whether we have non-editable columns (e.g. columns for residuals calculated in XYFitCurve) bool nonEditable = false; for (auto* col : m_columnsList) { auto* s = dynamic_cast(col->parentAspect()); if (s) { if (dynamic_cast(s)) { nonEditable = true; break; } } else { nonEditable = true; break; } } if (list.size() == 1) { //names and comments of non-editable columns in a file data source can be changed. if (!nonEditable && dynamic_cast(m_column->parentAspect()) != nullptr) { ui.leName->setEnabled(false); ui.leComment->setEnabled(false); } else { ui.leName->setEnabled(true); ui.leComment->setEnabled(true); } ui.leName->setText(m_column->name()); ui.leComment->setText(m_column->comment()); } else { ui.leName->setEnabled(false); ui.leComment->setEnabled(false); ui.leName->setText(""); ui.leComment->setText(""); } //show the properties of the first column AbstractColumn::ColumnMode columnMode = m_column->columnMode(); - ui.cbType->setCurrentIndex(ui.cbType->findData((int)columnMode)); + this->updateFormatWidgets(columnMode); + this->updateTypeWidgets(columnMode); + ui.cbPlotDesignation->setCurrentIndex( int(m_column->plotDesignation()) ); //disable widgets if we have at least one non-editable column ui.cbType->setEnabled(!nonEditable); ui.lFormat->setVisible(!nonEditable); ui.cbFormat->setVisible(!nonEditable); ui.lPrecision->setVisible(!nonEditable); ui.sbPrecision->setVisible(!nonEditable); ui.lPlotDesignation->setVisible(!nonEditable); ui.cbPlotDesignation->setVisible(!nonEditable); if (nonEditable) { m_initializing = false; return; } - this->updateFormatWidgets(columnMode); + // slots + connect(m_column, &AbstractColumn::aspectDescriptionChanged, this, &ColumnDock::columnDescriptionChanged); + connect(m_column, &AbstractColumn::modeChanged, this, &ColumnDock::columnModeChanged); + connect(m_column->outputFilter(), &AbstractSimpleFilter::formatChanged, this, &ColumnDock::columnFormatChanged); + connect(m_column->outputFilter(), &AbstractSimpleFilter::digitsChanged, this, &ColumnDock::columnPrecisionChanged); + connect(m_column, &AbstractColumn::plotDesignationChanged, this, &ColumnDock::columnPlotDesignationChanged); - switch(columnMode) { + m_initializing = false; +} + +void ColumnDock::updateTypeWidgets(AbstractColumn::ColumnMode mode) { + ui.cbType->setCurrentIndex(ui.cbType->findData((int)mode)); + switch(mode) { case AbstractColumn::Numeric: { auto* filter = static_cast(m_column->outputFilter()); ui.cbFormat->setCurrentIndex(ui.cbFormat->findData(filter->numericFormat())); ui.sbPrecision->setValue(filter->numDigits()); break; } case AbstractColumn::Month: case AbstractColumn::Day: case AbstractColumn::DateTime: { auto* filter = static_cast(m_column->outputFilter()); DEBUG(" set column format: " << filter->format().toStdString()); ui.cbFormat->setCurrentIndex(ui.cbFormat->findData(filter->format())); break; } case AbstractColumn::Integer: // nothing to set case AbstractColumn::Text: break; } - - ui.cbPlotDesignation->setCurrentIndex( int(m_column->plotDesignation()) ); - - // slots - connect(m_column, SIGNAL(aspectDescriptionChanged(const AbstractAspect*)),this, SLOT(columnDescriptionChanged(const AbstractAspect*))); - connect(m_column->outputFilter(), SIGNAL(formatChanged()),this, SLOT(columnFormatChanged())); - connect(m_column->outputFilter(), SIGNAL(digitsChanged()),this, SLOT(columnPrecisionChanged())); - connect(m_column, SIGNAL(plotDesignationChanged(const AbstractColumn*)),this, SLOT(columnPlotDesignationChanged(const AbstractColumn*))); - - m_initializing = false; } /*! depending on the currently selected column type (column mode) updates the widgets for the column format, shows/hides the allowed widgets, fills the corresponding combobox with the possible entries. Called when the type (column mode) is changed. */ -void ColumnDock::updateFormatWidgets(const AbstractColumn::ColumnMode columnMode) { +void ColumnDock::updateFormatWidgets(AbstractColumn::ColumnMode mode) { ui.cbFormat->clear(); - switch (columnMode) { + switch (mode) { case AbstractColumn::Numeric: ui.cbFormat->addItem(i18n("Decimal"), QVariant('f')); ui.cbFormat->addItem(i18n("Scientific (e)"), QVariant('e')); ui.cbFormat->addItem(i18n("Scientific (E)"), QVariant('E')); ui.cbFormat->addItem(i18n("Automatic (g)"), QVariant('g')); ui.cbFormat->addItem(i18n("Automatic (G)"), QVariant('G')); break; case AbstractColumn::Month: ui.cbFormat->addItem(i18n("Number without Leading Zero"), QVariant("M")); ui.cbFormat->addItem(i18n("Number with Leading Zero"), QVariant("MM")); ui.cbFormat->addItem(i18n("Abbreviated Month Name"), QVariant("MMM")); ui.cbFormat->addItem(i18n("Full Month Name"), QVariant("MMMM")); break; case AbstractColumn::Day: ui.cbFormat->addItem(i18n("Number without Leading Zero"), QVariant("d")); ui.cbFormat->addItem(i18n("Number with Leading Zero"), QVariant("dd")); ui.cbFormat->addItem(i18n("Abbreviated Day Name"), QVariant("ddd")); ui.cbFormat->addItem(i18n("Full Day Name"), QVariant("dddd")); break; case AbstractColumn::DateTime: for (const auto& s : AbstractColumn::dateTimeFormats()) ui.cbFormat->addItem(s, QVariant(s)); break; case AbstractColumn::Integer: case AbstractColumn::Text: break; } - if (columnMode == AbstractColumn::Numeric) { + if (mode == AbstractColumn::Numeric) { ui.lPrecision->show(); ui.sbPrecision->show(); } else { ui.lPrecision->hide(); ui.sbPrecision->hide(); } - if (columnMode == AbstractColumn::Text || columnMode == AbstractColumn::Integer) { + if (mode == AbstractColumn::Text || mode == AbstractColumn::Integer) { ui.lFormat->hide(); ui.cbFormat->hide(); } else { ui.lFormat->show(); ui.cbFormat->show(); } - if (columnMode == AbstractColumn::DateTime) { + if (mode == AbstractColumn::DateTime) { ui.cbFormat->setEditable(true); ui.cbFormat->setCurrentItem("yyyy-MM-dd hh:mm:ss.zzz"); } else { ui.cbFormat->setEditable(false); ui.cbFormat->setCurrentIndex(0); } } //************************************************************* //******** SLOTs for changes triggered in ColumnDock ********** //************************************************************* void ColumnDock::retranslateUi() { m_initializing = true; ui.cbType->clear(); ui.cbType->addItem(i18n("Numeric"), QVariant(int(AbstractColumn::Numeric))); ui.cbType->addItem(i18n("Integer"), QVariant(int(AbstractColumn::Integer))); ui.cbType->addItem(i18n("Text"), QVariant(int(AbstractColumn::Text))); ui.cbType->addItem(i18n("Month Names"), QVariant(int(AbstractColumn::Month))); ui.cbType->addItem(i18n("Day Names"), QVariant(int(AbstractColumn::Day))); ui.cbType->addItem(i18n("Date and Time"), QVariant(int(AbstractColumn::DateTime))); ui.cbPlotDesignation->clear(); ui.cbPlotDesignation->addItem(i18n("None")); ui.cbPlotDesignation->addItem(i18n("X")); ui.cbPlotDesignation->addItem(i18n("Y")); ui.cbPlotDesignation->addItem(i18n("Z")); ui.cbPlotDesignation->addItem(i18n("X-error")); ui.cbPlotDesignation->addItem(i18n("X-error -")); ui.cbPlotDesignation->addItem(i18n("X-error +")); ui.cbPlotDesignation->addItem(i18n("Y-error")); ui.cbPlotDesignation->addItem(i18n("Y-error -")); ui.cbPlotDesignation->addItem(i18n("Y-error +")); m_initializing = false; } void ColumnDock::nameChanged() { if (m_initializing) return; m_columnsList.first()->setName(ui.leName->text()); } void ColumnDock::commentChanged() { if (m_initializing) return; m_columnsList.first()->setComment(ui.leComment->text()); } /*! called when the type (column mode - numeric, text etc.) of the column was changed. */ void ColumnDock::typeChanged(int index) { DEBUG("ColumnDock::typeChanged()"); if (m_initializing) return; AbstractColumn::ColumnMode columnMode = (AbstractColumn::ColumnMode)ui.cbType->itemData(index).toInt(); int format_index = ui.cbFormat->currentIndex(); m_initializing = true; this->updateFormatWidgets(columnMode); m_initializing = false; switch(columnMode) { case AbstractColumn::Numeric: { int digits = ui.sbPrecision->value(); for (auto* col : m_columnsList) { col->beginMacro(i18n("%1: change column type", col->name())); col->setColumnMode(columnMode); auto* filter = static_cast(col->outputFilter()); filter->setNumericFormat(ui.cbFormat->itemData(format_index).toChar().toLatin1()); filter->setNumDigits(digits); col->endMacro(); } break; } case AbstractColumn::Integer: case AbstractColumn::Text: for (auto* col : m_columnsList) col->setColumnMode(columnMode); break; case AbstractColumn::Month: case AbstractColumn::Day: for (auto* col : m_columnsList) { col->beginMacro(i18n("%1: change column type", col->name())); // the format is saved as item data QString format = ui.cbFormat->itemData(ui.cbFormat->currentIndex()).toString(); col->setColumnMode(columnMode); auto* filter = static_cast(col->outputFilter()); filter->setFormat(format); col->endMacro(); } break; case AbstractColumn::DateTime: for (auto* col : m_columnsList) { col->beginMacro(i18n("%1: change column type", col->name())); // the format is the current text QString format = ui.cbFormat->currentText(); col->setColumnMode(columnMode); auto* filter = static_cast(col->outputFilter()); filter->setFormat(format); col->endMacro(); } break; } DEBUG("ColumnDock::typeChanged() DONE"); } /*! called when the format for the current type (column mode) was changed. */ void ColumnDock::formatChanged(int index) { DEBUG("ColumnDock::formatChanged()"); if (m_initializing) return; AbstractColumn::ColumnMode mode = (AbstractColumn::ColumnMode)ui.cbType->itemData(ui.cbType->currentIndex()).toInt(); int format_index = index; switch(mode) { case AbstractColumn::Numeric: { for (auto* col : m_columnsList) { auto* filter = static_cast(col->outputFilter()); filter->setNumericFormat(ui.cbFormat->itemData(format_index).toChar().toLatin1()); } break; } case AbstractColumn::Integer: case AbstractColumn::Text: break; case AbstractColumn::Month: case AbstractColumn::Day: case AbstractColumn::DateTime: { QString format = ui.cbFormat->itemData(ui.cbFormat->currentIndex()).toString(); for (auto* col : m_columnsList) { auto* filter = static_cast(col->outputFilter()); filter->setFormat(format); } break; } } DEBUG("ColumnDock::formatChanged() DONE"); } void ColumnDock::precisionChanged(int digits) { if (m_initializing) return; for (auto* col : m_columnsList) { auto* filter = static_cast(col->outputFilter()); filter->setNumDigits(digits); } } void ColumnDock::plotDesignationChanged(int index) { if (m_initializing) return; auto pd = AbstractColumn::PlotDesignation(index); for (auto* col : m_columnsList) col->setPlotDesignation(pd); } //************************************************************* //********* SLOTs for changes triggered in Column ************* //************************************************************* void ColumnDock::columnDescriptionChanged(const AbstractAspect* aspect) { if (m_column != aspect) return; m_initializing = true; if (aspect->name() != ui.leName->text()) ui.leName->setText(aspect->name()); else if (aspect->comment() != ui.leComment->text()) ui.leComment->setText(aspect->comment()); m_initializing = false; } +void ColumnDock::columnModeChanged(const AbstractAspect* aspect) { + if (m_column != aspect) + return; + + m_initializing = true; + AbstractColumn::ColumnMode columnMode = m_column->columnMode(); + this->updateFormatWidgets(columnMode); + this->updateTypeWidgets(columnMode); + m_initializing = false; +} + void ColumnDock::columnFormatChanged() { DEBUG("ColumnDock::columnFormatChanged()"); m_initializing = true; AbstractColumn::ColumnMode columnMode = m_column->columnMode(); switch(columnMode) { case AbstractColumn::Numeric: { auto* filter = static_cast(m_column->outputFilter()); ui.cbFormat->setCurrentIndex(ui.cbFormat->findData(filter->numericFormat())); break; } case AbstractColumn::Integer: case AbstractColumn::Text: break; case AbstractColumn::Month: case AbstractColumn::Day: case AbstractColumn::DateTime: { auto* filter = static_cast(m_column->outputFilter()); ui.cbFormat->setCurrentIndex(ui.cbFormat->findData(filter->format())); break; } } m_initializing = false; } void ColumnDock::columnPrecisionChanged() { m_initializing = true; auto* filter = static_cast(m_column->outputFilter()); ui.sbPrecision->setValue(filter->numDigits()); m_initializing = false; } void ColumnDock::columnPlotDesignationChanged(const AbstractColumn* col) { m_initializing = true; ui.cbPlotDesignation->setCurrentIndex( int(col->plotDesignation()) ); m_initializing = false; } diff --git a/src/kdefrontend/dockwidgets/ColumnDock.h b/src/kdefrontend/dockwidgets/ColumnDock.h index 00990bc57..dc0fa13e0 100644 --- a/src/kdefrontend/dockwidgets/ColumnDock.h +++ b/src/kdefrontend/dockwidgets/ColumnDock.h @@ -1,73 +1,75 @@ /*************************************************************************** File : ColumnDock.h Project : LabPlot Description : widget for column properties -------------------------------------------------------------------- - Copyright : (C) 2011 Alexander Semke (alexander.semke@web.de) + Copyright : (C) 2011-2018 Alexander Semke (alexander.semke@web.de) Copyright : (C) 2017 Stefan Gerlach (stefan.gerlach@uni.kn) ***************************************************************************/ /*************************************************************************** * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the Free Software * * Foundation, Inc., 51 Franklin Street, Fifth Floor, * * Boston, MA 02110-1301 USA * * * ***************************************************************************/ #ifndef COLUMNDOCK_H #define COLUMNDOCK_H #include "backend/core/column/Column.h" #include "ui_columndock.h" template class QList; class ColumnDock : public QWidget { Q_OBJECT public: explicit ColumnDock(QWidget*); void setColumns(QList); private: Ui::ColumnDock ui; QList m_columnsList; Column* m_column; bool m_initializing; - void updateFormatWidgets(const AbstractColumn::ColumnMode); + void updateTypeWidgets(AbstractColumn::ColumnMode); + void updateFormatWidgets(AbstractColumn::ColumnMode); private slots: void retranslateUi(); void nameChanged(); void commentChanged(); void typeChanged(int); void formatChanged(int); void precisionChanged(int); void plotDesignationChanged(int); //SLOTs for changes triggered in Column void columnDescriptionChanged(const AbstractAspect*); + void columnModeChanged(const AbstractAspect*); void columnFormatChanged(); void columnPrecisionChanged(); void columnPlotDesignationChanged(const AbstractColumn*); signals: void info(const QString&); }; #endif // COLUMNDOCK_H