File indexing completed on 2024-05-12 15:28:00

0001 /***************************************************************************
0002     File                 : MAtrixDock.cpp
0003     Project              : LabPlot
0004     Description          : widget for matrix properties
0005     --------------------------------------------------------------------
0006     Copyright            : (C) 2015 by Alexander Semke (alexander.semke@web.de)
0007 
0008  ***************************************************************************/
0009 
0010 /***************************************************************************
0011  *                                                                         *
0012  *  This program is free software; you can redistribute it and/or modify   *
0013  *  it under the terms of the GNU General Public License as published by   *
0014  *  the Free Software Foundation; either version 2 of the License, or      *
0015  *  (at your option) any later version.                                    *
0016  *                                                                         *
0017  *  This program is distributed in the hope that it will be useful,        *
0018  *  but WITHOUT ANY WARRANTY; without even the implied warranty of         *
0019  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the          *
0020  *  GNU General Public License for more details.                           *
0021  *                                                                         *
0022  *   You should have received a copy of the GNU General Public License     *
0023  *   along with this program; if not, write to the Free Software           *
0024  *   Foundation, Inc., 51 Franklin Street, Fifth Floor,                    *
0025  *   Boston, MA  02110-1301  USA                                           *
0026  *                                                                         *
0027  ***************************************************************************/
0028 
0029 #include "MatrixDock.h"
0030 #include "commonfrontend/matrix/MatrixView.h"
0031 #include "kdefrontend/TemplateHandler.h"
0032 
0033 #include <KConfig>
0034 
0035 #include <QDir>
0036 
0037  /*!
0038   \class MatrixDock
0039   \brief Provides a widget for editing the properties of the matrices currently selected in the project explorer.
0040 
0041   \ingroup kdefrontend
0042 */
0043 MatrixDock::MatrixDock(QWidget* parent): BaseDock(parent) {
0044     ui.setupUi(this);
0045     m_leName = ui.leName;
0046     m_leComment = ui.leComment;
0047 
0048     ui.cbFormat->addItem(i18n("Decimal"), QVariant('f'));
0049     ui.cbFormat->addItem(i18n("Scientific (e)"), QVariant('e'));
0050     ui.cbFormat->addItem(i18n("Scientific (E)"), QVariant('E'));
0051     ui.cbFormat->addItem(i18n("Automatic (g)"), QVariant('g'));
0052     ui.cbFormat->addItem(i18n("Automatic (G)"), QVariant('G'));
0053 
0054     ui.cbHeader->addItem(i18n("Rows and Columns"));
0055     ui.cbHeader->addItem(i18n("xy-Values"));
0056     ui.cbHeader->addItem(i18n("Rows, Columns and xy-Values"));
0057 
0058     //Validators
0059     ui.leXStart->setValidator( new QDoubleValidator(ui.leXStart) );
0060     ui.leXEnd->setValidator( new QDoubleValidator(ui.leXEnd) );
0061     ui.leYStart->setValidator( new QDoubleValidator(ui.leYStart) );
0062     ui.leYEnd->setValidator( new QDoubleValidator(ui.leYEnd) );
0063 
0064     connect(ui.leName, &QLineEdit::textChanged, this, &MatrixDock::nameChanged);
0065     connect(ui.leComment, &QLineEdit::textChanged, this, &MatrixDock::commentChanged);
0066     connect(ui.sbColumnCount, SIGNAL(valueChanged(int)), this, SLOT(columnCountChanged(int)));
0067     connect(ui.sbRowCount, SIGNAL(valueChanged(int)), this, SLOT(rowCountChanged(int)));
0068     connect(ui.leXStart, SIGNAL(returnPressed()), this, SLOT(xStartChanged()));
0069     connect(ui.leXEnd, SIGNAL(returnPressed()), this, SLOT(xEndChanged()));
0070     connect(ui.leYStart, SIGNAL(returnPressed()), this, SLOT(yStartChanged()));
0071     connect(ui.leYEnd, SIGNAL(returnPressed()), this, SLOT(yEndChanged()));
0072     connect(ui.cbFormat, SIGNAL(currentIndexChanged(int)), this, SLOT(numericFormatChanged(int)));
0073     connect(ui.sbPrecision, SIGNAL(valueChanged(int)), this, SLOT(precisionChanged(int)));
0074     connect(ui.cbHeader, SIGNAL(currentIndexChanged(int)), this, SLOT(headerFormatChanged(int)));
0075 
0076     auto* templateHandler = new TemplateHandler(this, TemplateHandler::ClassName::Matrix);
0077     ui.gridLayout->addWidget(templateHandler, 22, 0, 1, 4);
0078     templateHandler->show();
0079     connect(templateHandler, SIGNAL(loadConfigRequested(KConfig&)), this, SLOT(loadConfigFromTemplate(KConfig&)));
0080     connect(templateHandler, SIGNAL(saveConfigRequested(KConfig&)), this, SLOT(saveConfigAsTemplate(KConfig&)));
0081     connect(templateHandler, SIGNAL(info(QString)), this, SIGNAL(info(QString)));
0082 }
0083 
0084 void MatrixDock::setMatrices(QList<Matrix*> list) {
0085     m_initializing = true;
0086     m_matrixList = list;
0087     m_matrix = list.first();
0088     m_aspect = list.first();
0089 
0090     if (list.size() == 1) {
0091         ui.leName->setEnabled(true);
0092         ui.leComment->setEnabled(true);
0093 
0094         ui.leName->setText(m_matrix->name());
0095         ui.leComment->setText(m_matrix->comment());
0096     } else {
0097         //disable these fields if there is more than one matrix
0098         ui.leName->setEnabled(false);
0099         ui.leComment->setEnabled(false);
0100 
0101         ui.leName->setText(QString());
0102         ui.leComment->setText(QString());
0103     }
0104     ui.leName->setStyleSheet("");
0105     ui.leName->setToolTip("");
0106 
0107     //show the properties of the first Matrix in the list, if there are >1 matrixs
0108     this->load();
0109 
0110     // undo functions
0111     connect(m_matrix, SIGNAL(aspectDescriptionChanged(const AbstractAspect*)), this, SLOT(matrixDescriptionChanged(const AbstractAspect*)));
0112 
0113     connect(m_matrix, SIGNAL(rowCountChanged(int)), this, SLOT(matrixRowCountChanged(int)));
0114     connect(m_matrix, SIGNAL(columnCountChanged(int)), this, SLOT(matrixColumnCountChanged(int)));
0115 
0116     connect(m_matrix, SIGNAL(xStartChanged(double)), this, SLOT(matrixXStartChanged(double)));
0117     connect(m_matrix, SIGNAL(xEndChanged(double)), this, SLOT(matrixXEndChanged(double)));
0118     connect(m_matrix, SIGNAL(yStartChanged(double)), this, SLOT(matrixYStartChanged(double)));
0119     connect(m_matrix, SIGNAL(yEndChanged(double)), this, SLOT(matrixYEndChanged(double)));
0120 
0121     connect(m_matrix, SIGNAL(numericFormatChanged(char)), this, SLOT(matrixNumericFormatChanged(char)));
0122     connect(m_matrix, SIGNAL(precisionChanged(int)), this, SLOT(matrixPrecisionChanged(int)));
0123     connect(m_matrix, SIGNAL(headerFormatChanged(Matrix::HeaderFormat)), this, SLOT(matrixHeaderFormatChanged(Matrix::HeaderFormat)));
0124 
0125     m_initializing = false;
0126 }
0127 
0128 //*************************************************************
0129 //****** SLOTs for changes triggered in MatrixDock *******
0130 //*************************************************************
0131 //mapping to the logical coordinates
0132 void MatrixDock::xStartChanged() {
0133     if (m_initializing)
0134         return;
0135 
0136     QString str = ui.leXStart->text().trimmed();
0137     if (str.isEmpty()) return;
0138     bool ok;
0139     SET_NUMBER_LOCALE
0140     const double value{ numberLocale.toDouble(str, &ok) };
0141     if (ok) {
0142         for (auto* matrix : m_matrixList)
0143             matrix->setXStart(value);
0144     }
0145 }
0146 
0147 void MatrixDock::xEndChanged() {
0148     if (m_initializing)
0149         return;
0150 
0151     QString str = ui.leXEnd->text().trimmed();
0152     if (str.isEmpty()) return;
0153     bool ok;
0154     SET_NUMBER_LOCALE
0155     const double value{ numberLocale.toDouble(str, &ok) };
0156     if (ok) {
0157         for (auto* matrix : m_matrixList)
0158             matrix->setXEnd(value);
0159     }
0160 }
0161 
0162 void MatrixDock::yStartChanged() {
0163     if (m_initializing)
0164         return;
0165 
0166     QString str = ui.leYStart->text().trimmed();
0167     if (str.isEmpty()) return;
0168     bool ok;
0169     SET_NUMBER_LOCALE
0170     const double value{ numberLocale.toDouble(str, &ok) };
0171     if (ok) {
0172         for (auto* matrix : m_matrixList)
0173             matrix->setYStart(value);
0174     }
0175 }
0176 
0177 void MatrixDock::yEndChanged() {
0178     if (m_initializing)
0179         return;
0180 
0181     QString str = ui.leYEnd->text().trimmed();
0182     if (str.isEmpty()) return;
0183     bool ok;
0184     SET_NUMBER_LOCALE
0185     const double value{ numberLocale.toDouble(str, &ok) };
0186     if (ok) {
0187         for (auto* matrix : m_matrixList)
0188             matrix->setYEnd(value);
0189     }
0190 }
0191 
0192 //format
0193 void MatrixDock::numericFormatChanged(int index) {
0194     if (m_initializing)
0195         return;
0196 
0197     char format = ui.cbFormat->itemData(index).toChar().toLatin1();
0198     for (auto* matrix : m_matrixList)
0199         matrix->setNumericFormat(format);
0200 }
0201 
0202 void MatrixDock::precisionChanged(int precision) {
0203     if (m_initializing)
0204         return;
0205 
0206     for (auto* matrix : m_matrixList)
0207         matrix->setPrecision(precision);
0208 }
0209 
0210 void MatrixDock::headerFormatChanged(int value) {
0211     if (m_initializing)
0212         return;
0213 
0214     auto format = (Matrix::HeaderFormat)value;
0215     for (auto* matrix : m_matrixList)
0216         matrix->setHeaderFormat(format);
0217 }
0218 
0219 void MatrixDock::rowCountChanged(int rows) {
0220     if (m_initializing)
0221         return;
0222 
0223     for (auto* matrix : m_matrixList)
0224         matrix->setRowCount(rows);
0225 }
0226 
0227 void MatrixDock::columnCountChanged(int columns) {
0228     if (m_initializing)
0229         return;
0230 
0231     for (auto* matrix : m_matrixList)
0232         matrix->setColumnCount(columns);
0233 }
0234 
0235 //*************************************************************
0236 //******** SLOTs for changes triggered in Matrix *********
0237 //*************************************************************
0238 void MatrixDock::matrixDescriptionChanged(const AbstractAspect* aspect) {
0239     if (m_matrix != aspect)
0240         return;
0241 
0242     m_initializing = true;
0243     if (aspect->name() != ui.leName->text())
0244         ui.leName->setText(aspect->name());
0245     else if (aspect->comment() != ui.leComment->text())
0246         ui.leComment->setText(aspect->comment());
0247 
0248     m_initializing = false;
0249 }
0250 
0251 //matrix dimensions
0252 void MatrixDock::matrixRowCountChanged(int count) {
0253     m_initializing = true;
0254     ui.sbRowCount->setValue(count);
0255     m_initializing = false;
0256 }
0257 
0258 void MatrixDock::matrixColumnCountChanged(int count) {
0259     m_initializing = true;
0260     ui.sbColumnCount->setValue(count);
0261     m_initializing = false;
0262 }
0263 
0264 //mapping to the logical coordinates
0265 void MatrixDock::matrixXStartChanged(double value) {
0266     m_initializing = true;
0267     SET_NUMBER_LOCALE
0268     ui.leXStart->setText(numberLocale.toString(value));
0269     m_initializing = false;
0270 }
0271 
0272 void MatrixDock::matrixXEndChanged(double value) {
0273     m_initializing = true;
0274     SET_NUMBER_LOCALE
0275     ui.leXEnd->setText(numberLocale.toString(value));
0276     m_initializing = false;
0277 }
0278 
0279 void MatrixDock::matrixYStartChanged(double value) {
0280     m_initializing = true;
0281     SET_NUMBER_LOCALE
0282     ui.leYStart->setText(numberLocale.toString(value));
0283     m_initializing = false;
0284 }
0285 
0286 void MatrixDock::matrixYEndChanged(double value) {
0287     m_initializing = true;
0288     SET_NUMBER_LOCALE
0289     ui.leYEnd->setText(numberLocale.toString(value));
0290     m_initializing = false;
0291 }
0292 
0293 //format
0294 void MatrixDock::matrixNumericFormatChanged(char format) {
0295     m_initializing = true;
0296     int index = ui.cbFormat->findData((int)format);
0297     ui.cbFormat->setCurrentIndex(index);
0298     m_initializing = false;
0299 }
0300 
0301 void MatrixDock::matrixPrecisionChanged(int precision) {
0302     m_initializing = true;
0303     ui.sbPrecision->setValue(precision);
0304     m_initializing = false;
0305 }
0306 
0307 void MatrixDock::matrixHeaderFormatChanged(Matrix::HeaderFormat format) {
0308     m_initializing = true;
0309     ui.cbHeader->setCurrentIndex((int)format);
0310     m_initializing = false;
0311 }
0312 
0313 //*************************************************************
0314 //******************** SETTINGS *******************************
0315 //*************************************************************
0316 void MatrixDock::load() {
0317     //matrix dimensions
0318     ui.sbRowCount->setValue(m_matrix->rowCount());
0319     ui.sbColumnCount->setValue(m_matrix->columnCount());
0320 
0321     //mapping to the logical coordinates
0322     SET_NUMBER_LOCALE
0323     ui.leXStart->setText(numberLocale.toString(m_matrix->xStart()));
0324     ui.leXEnd->setText(numberLocale.toString(m_matrix->xEnd()));
0325     ui.leYStart->setText(numberLocale.toString(m_matrix->yStart()));
0326     ui.leYEnd->setText(numberLocale.toString(m_matrix->yEnd()));
0327 
0328     //format
0329     ui.cbFormat->setCurrentIndex(ui.cbFormat->findData((int)m_matrix->numericFormat()));
0330     ui.sbPrecision->setValue(m_matrix->precision());
0331     ui.cbHeader->setCurrentIndex(static_cast<int>(m_matrix->headerFormat()));
0332 }
0333 
0334 void MatrixDock::loadConfigFromTemplate(KConfig& config) {
0335     //extract the name of the template from the file name
0336     QString name;
0337     const int index = config.name().lastIndexOf(QLatin1String("/"));
0338     if (index != -1)
0339         name = config.name().right(config.name().size() - index - 1);
0340     else
0341         name = config.name();
0342 
0343     const int size = m_matrixList.size();
0344     if (size>1)
0345         m_matrix->beginMacro(i18n("%1 matrices: template \"%2\" loaded", size, name));
0346     else
0347         m_matrix->beginMacro(i18n("%1: template \"%2\" loaded", m_matrix->name(), name));
0348 
0349     this->loadConfig(config);
0350 
0351     m_matrix->endMacro();
0352 }
0353 
0354 /*!
0355     loads saved matrix properties from \c config.
0356  */
0357 void MatrixDock::loadConfig(KConfig& config) {
0358     KConfigGroup group = config.group("Matrix");
0359 
0360     //matrix dimensions
0361     ui.sbRowCount->setValue(group.readEntry("RowCount", m_matrix->rowCount()));
0362     ui.sbColumnCount->setValue(group.readEntry("ColumnCount", m_matrix->columnCount()));
0363 
0364     //mapping to the logical coordinates
0365     SET_NUMBER_LOCALE
0366     ui.leXStart->setText( numberLocale.toString(group.readEntry("XStart", m_matrix->xStart())) );
0367     ui.leXEnd->setText( numberLocale.toString(group.readEntry("XEnd", m_matrix->xEnd())) );
0368     ui.leYStart->setText( numberLocale.toString(group.readEntry("YStart", m_matrix->yStart())) );
0369     ui.leYEnd->setText( numberLocale.toString(group.readEntry("YEnd", m_matrix->yEnd())) );
0370 
0371     //format
0372     ui.cbFormat->setCurrentIndex( ui.cbFormat->findData(group.readEntry("NumericFormat", QString(m_matrix->numericFormat()))) );
0373     ui.sbPrecision->setValue(group.readEntry("Precision", m_matrix->precision()));
0374     ui.cbHeader->setCurrentIndex(group.readEntry("HeaderFormat", (int)m_matrix->headerFormat()));
0375 }
0376 
0377 /*!
0378     saves matrix properties to \c config.
0379  */
0380 void MatrixDock::saveConfigAsTemplate(KConfig& config) {
0381     KConfigGroup group = config.group("Matrix");
0382 
0383     //matrix dimensions
0384     group.writeEntry("RowCount", ui.sbRowCount->value());
0385     group.writeEntry("ColumnCount", ui.sbColumnCount->value());
0386 
0387     //mapping to the logical coordinates
0388     SET_NUMBER_LOCALE
0389     group.writeEntry("XStart", numberLocale.toDouble(ui.leXStart->text()) );
0390     group.writeEntry("XEnd", numberLocale.toDouble(ui.leXEnd->text()) );
0391     group.writeEntry("YStart", numberLocale.toDouble(ui.leYStart->text()) );
0392     group.writeEntry("YEnd", numberLocale.toDouble(ui.leYEnd->text()) );
0393 
0394     //format
0395     group.writeEntry("NumericFormat", ui.cbFormat->itemData(ui.cbFormat->currentIndex()));
0396     group.writeEntry("Precision", ui.sbPrecision->value());
0397     group.writeEntry("HeaderFormat", ui.cbHeader->currentIndex());
0398 
0399     config.sync();
0400 }