diff --git a/src/libkstapp/curvedialog.cpp b/src/libkstapp/curvedialog.cpp index 6afeccdc..674da4b4 100644 --- a/src/libkstapp/curvedialog.cpp +++ b/src/libkstapp/curvedialog.cpp @@ -1,616 +1,645 @@ /*************************************************************************** * * * copyright : (C) 2007 The University of Toronto * * netterfield@astro.utoronto.ca * * * * 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. * * * ***************************************************************************/ #include "curvedialog.h" #include "dialogpage.h" #include "editmultiplewidget.h" #include "curve.h" #include "view.h" #include "plotitem.h" #include "tabwidget.h" #include "mainwindow.h" #include "application.h" #include "plotrenderitem.h" #include "datacollection.h" #include "document.h" #include "objectstore.h" #include "updatemanager.h" #include namespace Kst { CurveTab::CurveTab(QWidget *parent) : DataTab(parent) { setupUi(this); setTabTitle(tr("Curve")); _xError->setAllowEmptySelection(true); _yError->setAllowEmptySelection(true); _xMinusError->setAllowEmptySelection(true); _yMinusError->setAllowEmptySelection(true); _curvePlacement->setExistingPlots(Data::self()->plotList()); _xVectorLabel->setBuddy(_xVector->_vector); _yVectorLabel->setBuddy(_yVector->_vector); _xErrorLabel->setBuddy(_xError->_vector); _yErrorLabel->setBuddy(_yError->_vector); _xMinusErrorLabel->setBuddy(_xMinusError->_vector); _yMinusErrorLabel->setBuddy(_yMinusError->_vector); _xVector->setIsX(true); connect(_xVector, SIGNAL(selectionChanged(QString)), this, SIGNAL(vectorsChanged())); connect(_yVector, SIGNAL(selectionChanged(QString)), this, SIGNAL(vectorsChanged())); connect(_xMinusSameAsPlus, SIGNAL(toggled(bool)), this, SLOT(xCheckboxClicked())); connect(_yMinusSameAsPlus, SIGNAL(toggled(bool)), this, SLOT(yCheckboxClicked())); connect(_xError, SIGNAL(selectionChanged(QString)), this, SLOT(xErrorChanged())); connect(_yError, SIGNAL(selectionChanged(QString)), this, SLOT(xErrorChanged())); connect(_xVector, SIGNAL(selectionChanged(QString)), this, SIGNAL(modified())); connect(_yVector, SIGNAL(selectionChanged(QString)), this, SIGNAL(modified())); connect(_xError, SIGNAL(selectionChanged(QString)), this, SIGNAL(modified())); connect(_yError, SIGNAL(selectionChanged(QString)), this, SIGNAL(modified())); connect(_xMinusError, SIGNAL(selectionChanged(QString)), this, SIGNAL(modified())); connect(_yMinusError, SIGNAL(selectionChanged(QString)), this, SIGNAL(modified())); // if the content of any of the vector combos is changed (new or edit), update them all. connect(_xVector, SIGNAL(contentChanged()), this, SLOT(updateVectorCombos())); connect(_yVector, SIGNAL(contentChanged()), this, SLOT(updateVectorCombos())); connect(_xError, SIGNAL(contentChanged()), this, SLOT(updateVectorCombos())); connect(_yError, SIGNAL(contentChanged()), this, SLOT(updateVectorCombos())); connect(_xMinusError, SIGNAL(contentChanged()), this, SLOT(updateVectorCombos())); connect(_yMinusError, SIGNAL(contentChanged()), this, SLOT(updateVectorCombos())); connect(_curveAppearance, SIGNAL(modified()), this, SIGNAL(modified())); connect(_ignoreAutoScale, SIGNAL(stateChanged(int)), this, SIGNAL(modified())); connect(_xMinusSameAsPlus, SIGNAL(stateChanged(int)), this, SIGNAL(modified())); connect(_yMinusSameAsPlus, SIGNAL(stateChanged(int)), this, SIGNAL(modified())); - + connect(_manualLegendName, SIGNAL(textChanged(QString)), this, SIGNAL(modified())); + connect(_autoLegend, SIGNAL(toggled(bool)), this, SIGNAL(modified())); } CurveTab::~CurveTab() { } VectorPtr CurveTab::xVector() const { return _xVector->selectedVector(); } bool CurveTab::xVectorDirty() const { return _xVector->selectedVectorDirty(); } void CurveTab::setXVector(VectorPtr vector) { _xVector->setSelectedVector(vector); } bool CurveTab::xVectorSelected() const { return _xVector->vectorSelected(); } VectorPtr CurveTab::yVector() const { return _yVector->selectedVector(); } bool CurveTab::yVectorDirty() const { return _yVector->selectedVectorDirty(); } bool CurveTab::yVectorSelected() const { return _yVector->vectorSelected(); } void CurveTab::setYVector(VectorPtr vector) { _yVector->setSelectedVector(vector); } VectorPtr CurveTab::xError() const { return _xError->selectedVector(); } bool CurveTab::xErrorDirty() const { return _xError->selectedVectorDirty(); } void CurveTab::setXError(VectorPtr vector) { _xError->setSelectedVector(vector); } VectorPtr CurveTab::yError() const { return _yError->selectedVector(); } bool CurveTab::yErrorDirty() const { return _yError->selectedVectorDirty(); } void CurveTab::setYError(VectorPtr vector) { _yError->setSelectedVector(vector); } VectorPtr CurveTab::xMinusError() const { return _xMinusError->selectedVector(); } bool CurveTab::xMinusErrorDirty() const { return _xMinusError->selectedVectorDirty(); } void CurveTab::setXMinusError(VectorPtr vector) { _xMinusError->setSelectedVector(vector); } VectorPtr CurveTab::yMinusError() const { return _yMinusError->selectedVector(); } bool CurveTab::yMinusErrorDirty() const { return _yMinusError->selectedVectorDirty(); } void CurveTab::setYMinusError(VectorPtr vector) { _yMinusError->setSelectedVector(vector); } void CurveTab::xCheckboxClicked() { _xMinusError->setEnabled(!_xMinusSameAsPlus->isChecked()); _xMinusErrorLabel->setEnabled(!_xMinusSameAsPlus->isChecked()); xErrorChanged(); } void CurveTab::yCheckboxClicked() { _yMinusError->setEnabled(!_yMinusSameAsPlus->isChecked()); _yMinusErrorLabel->setEnabled(!_yMinusSameAsPlus->isChecked()); yErrorChanged(); } void CurveTab::xErrorChanged() { if (_xMinusSameAsPlus->isChecked()) { _xMinusError->setSelectedVector(_xError->selectedVector()); } } void CurveTab::yErrorChanged() { if (_yMinusSameAsPlus->isChecked()) { _yMinusError->setSelectedVector(_yError->selectedVector()); } } void CurveTab::setObjectStore(ObjectStore *store) { _xVector->setObjectStore(store); _yVector->setObjectStore(store); _xError->setObjectStore(store); _yError->setObjectStore(store); _xMinusError->setObjectStore(store); _yMinusError->setObjectStore(store); } void CurveTab::hidePlacementOptions() { _curvePlacement->setVisible(false); } CurveAppearance* CurveTab::curveAppearance() const { return _curveAppearance; } CurvePlacement* CurveTab::curvePlacement() const { return _curvePlacement; } bool CurveTab::ignoreAutoScale() const { return _ignoreAutoScale->isChecked(); } bool CurveTab::ignoreAutoScaleDirty() const { return _ignoreAutoScale->checkState() != Qt::PartiallyChecked; } void CurveTab::setIgnoreAutoScale(bool ignoreAutoScale) { _ignoreAutoScale->setChecked(ignoreAutoScale); } void CurveTab::clearTabValues() { _xVector->clearSelection(); _yVector->clearSelection(); _xError->clearSelection(); _yError->clearSelection(); _xMinusError->clearSelection(); _yMinusError->clearSelection(); _ignoreAutoScale->setCheckState(Qt::PartiallyChecked); _curveAppearance->clearValues(); } void CurveTab::setPlotMode(PlotItem *plot) { _curvePlacement->setPlace(CurvePlacement::ExistingPlot); _curvePlacement->setExistingPlots(Data::self()->plotList()); if (plot) { _curvePlacement->setCurrentPlot(plot); } _curveAppearance->setVisible(true); _curvePlacement->setVisible(true); _ignoreAutoScale->setVisible(true); } +QString CurveTab::manualLegendName() const { + if (_autoLegend->isChecked()) { + return QString(); + } else { + return _manualLegendName->text(); + } +} + +void CurveTab::setManualLegendNameText(const QString &name) { + _manualLegendName->setText(name); +} + +void CurveTab::setLegendAuto(bool is_auto) { + _autoLegend->setChecked(is_auto); +} + +void CurveTab::setLegendNameVisible(bool visible) { + _autoLegend->setVisible(visible); + _manualLegendName->setVisible(visible); + _legendLabel->setVisible(visible); +} + void CurveTab::updateVectorCombos() { _xVector->fillVectors(); _yVector->fillVectors(); _xError->fillVectors(); _yError->fillVectors(); _xMinusError->fillVectors(); _yMinusError->fillVectors(); } CurveDialog::CurveDialog(ObjectPtr dataObject, QWidget *parent) : DataDialog(dataObject, parent) { if (editMode() == Edit) setWindowTitle(tr("Edit Curve")); else setWindowTitle(tr("New Curve")); _curveTab = new CurveTab(this); addDataTab(_curveTab); if (editMode() == Edit) { configureTab(dataObject); } else { configureTab(0); } connect(_curveTab, SIGNAL(vectorsChanged()), this, SLOT(updateButtons())); connect(this, SIGNAL(editMultipleMode()), this, SLOT(editMultipleMode())); connect(this, SIGNAL(editSingleMode()), this, SLOT(editSingleMode())); connect(_curveTab, SIGNAL(modified()), this, SLOT(modified())); updateButtons(); } CurveDialog::~CurveDialog() { } // QString CurveDialog::tagString() const { // return DataDialog::tagString(); // } // void CurveDialog::editMultipleMode() { + _curveTab->setLegendNameVisible(false); _curveTab->clearTabValues(); } void CurveDialog::editSingleMode() { + _curveTab->setLegendNameVisible(true); configureTab(dataObject()); } - void CurveDialog::configureTab(ObjectPtr object) { if (!object) { _curveTab->curveAppearance()->loadWidgetDefaults(); _curveTab->setToLastX(); } else if (CurvePtr curve = kst_cast(object)) { _curveTab->curveAppearance()->loadWidgetDefaults(); _curveTab->setXVector(curve->xVector()); _curveTab->setYVector(curve->yVector()); if (curve->hasXError()) { _curveTab->setXError(curve->xErrorVector()); } if (curve->hasYError()) { _curveTab->setYError(curve->yErrorVector()); } if (curve->hasXMinusError()) { _curveTab->setXMinusError(curve->xMinusErrorVector()); } if (curve->hasYMinusError()) { _curveTab->setYMinusError(curve->yMinusErrorVector()); } _curveTab->setIgnoreAutoScale(curve->ignoreAutoScale()); _curveTab->curveAppearance()->setColor(curve->color()); _curveTab->curveAppearance()->setHeadColor(curve->headColor()); _curveTab->curveAppearance()->setShowPoints(curve->hasPoints()); _curveTab->curveAppearance()->setShowLines(curve->hasLines()); _curveTab->curveAppearance()->setShowBars(curve->hasBars()); _curveTab->curveAppearance()->setShowHead(curve->hasHead()); _curveTab->curveAppearance()->setLineWidth(curve->lineWidth()); _curveTab->curveAppearance()->setPointSize(curve->pointSize()); _curveTab->curveAppearance()->setLineStyle(curve->lineStyle()); _curveTab->curveAppearance()->setPointType(curve->pointType()); _curveTab->curveAppearance()->setPointDensity(curve->pointDensity()); _curveTab->curveAppearance()->setBarFillColor(curve->barFillColor()); _curveTab->curveAppearance()->setHeadType(curve->headType()); + _curveTab->setManualLegendNameText(curve->legendName(true, true)); + _curveTab->setLegendAuto(curve->manualLegendName().isEmpty()); _curveTab->hidePlacementOptions(); if (_editMultipleWidget) { CurveList objects = _document->objectStore()->getObjects(); _editMultipleWidget->clearObjects(); foreach(CurvePtr object, objects) { _editMultipleWidget->addObject(object->Name(), object->descriptionTip()); } } } } void CurveDialog::setVector(VectorPtr vector) { _curveTab->setYVector(vector); } void CurveDialog::setPlotMode(PlotItem *plot) { _curveTab->setPlotMode(plot); } void CurveDialog::updateButtons() { _buttonBox->button(QDialogButtonBox::Ok)->setEnabled(dialogValid()); } bool CurveDialog::dialogValid() const { bool valid = (_curveTab->xVectorSelected() && _curveTab->yVectorSelected()) || (editMode() == EditMultiple); return (valid); } ObjectPtr CurveDialog::createNewDataObject() { Q_ASSERT(_document && _document->objectStore()); ObjectStore *os = _document->objectStore(); CurvePtr curve = os->createObject(); curve->setXVector(_curveTab->xVector()); curve->setYVector(_curveTab->yVector()); curve->setXError(_curveTab->xError()); curve->setYError(_curveTab->yError()); curve->setXMinusError(_curveTab->xMinusError()); curve->setYMinusError(_curveTab->yMinusError()); curve->setColor(_curveTab->curveAppearance()->color()); curve->setHeadColor(_curveTab->curveAppearance()->headColor()); curve->setHasPoints(_curveTab->curveAppearance()->showPoints()); curve->setHasLines(_curveTab->curveAppearance()->showLines()); curve->setHasBars(_curveTab->curveAppearance()->showBars()); curve->setHasHead(_curveTab->curveAppearance()->showHead()); curve->setLineWidth(_curveTab->curveAppearance()->lineWidth()); curve->setPointSize(_curveTab->curveAppearance()->pointSize()); curve->setLineStyle(_curveTab->curveAppearance()->lineStyle()); curve->setPointType(_curveTab->curveAppearance()->pointType()); curve->setPointDensity(_curveTab->curveAppearance()->pointDensity()); curve->setBarFillColor(_curveTab->curveAppearance()->barFillColor()); curve->setHeadType(_curveTab->curveAppearance()->headType()); curve->setIgnoreAutoScale(_curveTab->ignoreAutoScale()); + curve->setManualLegendName(_curveTab->manualLegendName()); if (DataDialog::tagStringAuto()) { curve->setDescriptiveName(QString()); } else { curve->setDescriptiveName(DataDialog::tagString()); } curve->writeLock(); curve->registerChange(); curve->unlock(); _curveTab->curveAppearance()->setWidgetDefaults(); if(editMode()==New) { PlotItem *plotItem = 0; switch (_curveTab->curvePlacement()->place()) { case CurvePlacement::NoPlot: break; case CurvePlacement::ExistingPlot: { plotItem = static_cast(_curveTab->curvePlacement()->existingPlot()); break; } case CurvePlacement::NewPlotNewTab: _document->createView(); // fall through to case NewPlot. case CurvePlacement::NewPlot: { CreatePlotForCurve *cmd = new CreatePlotForCurve(); cmd->createItem(); plotItem = static_cast(cmd->item()); if (_curveTab->curvePlacement()->scaleFonts()) { plotItem->view()->resetPlotFontSizes(plotItem); plotItem->view()->configurePlotFontDefaults(plotItem); // copy plots already in window } break; } default: break; } if (_curveTab->curvePlacement()->place() != CurvePlacement::NoPlot) { PlotRenderItem *renderItem = plotItem->renderItem(PlotRenderItem::Cartesian); renderItem->addRelation(kst_cast(curve)); plotItem->update(); if (_curveTab->curvePlacement()->place() != CurvePlacement::ExistingPlot) { plotItem->view()->appendToLayout(_curveTab->curvePlacement()->layout(), plotItem, _curveTab->curvePlacement()->gridColumns()); if (_curveTab->curvePlacement()->layout() == CurvePlacement::Custom) { plotItem->createCustomLayout(_curveTab->curvePlacement()->gridColumns()); } } } } return ObjectPtr(curve.data()); } ObjectPtr CurveDialog::editExistingDataObject() const { if (CurvePtr curve = kst_cast(dataObject())) { if (editMode() == EditMultiple) { QStringList objects = _editMultipleWidget->selectedObjects(); foreach (const QString &objectName, objects) { CurvePtr curve = kst_cast(_document->objectStore()->retrieveObject(objectName)); if (curve) { VectorPtr xVector = _curveTab->xVectorDirty() ? _curveTab->xVector() : curve->xVector(); VectorPtr yVector = _curveTab->yVectorDirty() ? _curveTab->yVector() : curve->yVector(); VectorPtr xError = 0; if (_curveTab->xErrorDirty()) { xError = _curveTab->xError(); } else if (curve->hasXError()) { xError = curve->xErrorVector(); } VectorPtr yError = 0; if (_curveTab->yErrorDirty()) { yError = _curveTab->yError(); } else if (curve->hasYError()) { yError = curve->yErrorVector(); } VectorPtr xMinusError = 0; if (_curveTab->xMinusErrorDirty()) { xMinusError = _curveTab->xMinusError(); } else if (curve->hasXMinusError()) { xMinusError = curve->xMinusErrorVector(); } VectorPtr yMinusError = 0; if (_curveTab->yMinusErrorDirty()) { yMinusError = _curveTab->yMinusError(); } else if (curve->hasYMinusError()) { yMinusError = curve->yMinusErrorVector(); } QColor color = _curveTab->curveAppearance()->colorDirty() ? _curveTab->curveAppearance()->color() : curve->color(); QColor headColor = _curveTab->curveAppearance()->headColorDirty() ? _curveTab->curveAppearance()->headColor() : curve->headColor(); QColor barFillColor = _curveTab->curveAppearance()->barFillColorDirty() ? _curveTab->curveAppearance()->barFillColor() : curve->barFillColor(); int lineWidth = _curveTab->curveAppearance()->lineWidthDirty() ? _curveTab->curveAppearance()->lineWidth() : curve->lineWidth(); double pointSize = _curveTab->curveAppearance()->pointSizeDirty() ? _curveTab->curveAppearance()->pointSize() : curve->pointSize(); int lineStyle = _curveTab->curveAppearance()->lineStyleDirty() ? _curveTab->curveAppearance()->lineStyle() : curve->lineStyle(); int pointType = _curveTab->curveAppearance()->pointTypeDirty() ? _curveTab->curveAppearance()->pointType() : curve->pointType(); int pointDensity = _curveTab->curveAppearance()->pointDensityDirty() ? _curveTab->curveAppearance()->pointDensity() : curve->pointDensity(); int headType = _curveTab->curveAppearance()->headTypeDirty() ? _curveTab->curveAppearance()->headType() : curve->headType(); bool showPoints = _curveTab->curveAppearance()->showPointsDirty() ? _curveTab->curveAppearance()->showPoints() : curve->hasPoints(); bool showLines = _curveTab->curveAppearance()->showLinesDirty() ? _curveTab->curveAppearance()->showLines() : curve->hasLines(); bool showBars = _curveTab->curveAppearance()->showBarsDirty() ? _curveTab->curveAppearance()->showBars() : curve->hasBars(); bool showHead = _curveTab->curveAppearance()->showHeadDirty() ? _curveTab->curveAppearance()->showHead() : curve->hasHead(); bool ignoreAutoScale = _curveTab->ignoreAutoScaleDirty() ? _curveTab->ignoreAutoScale() : curve->ignoreAutoScale(); curve->writeLock(); curve->setXVector(xVector); curve->setYVector(yVector); curve->setXError(xError); curve->setYError(yError); curve->setXMinusError(xMinusError); curve->setYMinusError(yMinusError); curve->setColor(color); curve->setHeadColor(headColor); curve->setBarFillColor(barFillColor); curve->setHasPoints(showPoints); curve->setHasLines(showLines); curve->setHasBars(showBars); curve->setHasHead(showHead); curve->setLineWidth(lineWidth); curve->setPointSize(pointSize); curve->setLineStyle(lineStyle); curve->setPointType(pointType); curve->setPointDensity(pointDensity); curve->setHeadType(headType); curve->setIgnoreAutoScale(ignoreAutoScale); if (DataDialog::tagStringAuto()) { curve->setDescriptiveName(QString()); } else { curve->setDescriptiveName(DataDialog::tagString()); } curve->registerChange(); curve->unlock(); } } } else { curve->writeLock(); curve->setXVector(_curveTab->xVector()); curve->setYVector(_curveTab->yVector()); curve->setXError(_curveTab->xError()); curve->setYError(_curveTab->yError()); curve->setXMinusError(_curveTab->xMinusError()); curve->setYMinusError(_curveTab->yMinusError()); curve->setColor(_curveTab->curveAppearance()->color()); curve->setHeadColor(_curveTab->curveAppearance()->headColor()); curve->setBarFillColor(_curveTab->curveAppearance()->barFillColor()); curve->setHasPoints(_curveTab->curveAppearance()->showPoints()); curve->setHasLines(_curveTab->curveAppearance()->showLines()); curve->setHasBars(_curveTab->curveAppearance()->showBars()); curve->setHasHead(_curveTab->curveAppearance()->showHead()); curve->setLineWidth(_curveTab->curveAppearance()->lineWidth()); curve->setPointSize(_curveTab->curveAppearance()->pointSize()); curve->setLineStyle(_curveTab->curveAppearance()->lineStyle()); curve->setPointType(_curveTab->curveAppearance()->pointType()); curve->setPointDensity(_curveTab->curveAppearance()->pointDensity()); curve->setHeadType(_curveTab->curveAppearance()->headType()); curve->setIgnoreAutoScale(_curveTab->ignoreAutoScale()); + curve->setManualLegendName(_curveTab->manualLegendName()); + if (DataDialog::tagStringAuto()) { curve->setDescriptiveName(QString()); } else { curve->setDescriptiveName(DataDialog::tagString()); } curve->registerChange(); curve->unlock(); _curveTab->curveAppearance()->setWidgetDefaults(false); } } return dataObject(); } } // vim: ts=2 sw=2 et diff --git a/src/libkstapp/curvedialog.h b/src/libkstapp/curvedialog.h index 08e476c4..6d12d52a 100644 --- a/src/libkstapp/curvedialog.h +++ b/src/libkstapp/curvedialog.h @@ -1,115 +1,121 @@ /*************************************************************************** * * * copyright : (C) 2007 The University of Toronto * * netterfield@astro.utoronto.ca * * * * 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. * * * ***************************************************************************/ #ifndef CURVEDIALOG_H #define CURVEDIALOG_H #include "datadialog.h" #include "datatab.h" #include "plotitem.h" #include "ui_curvetab.h" #include #include "kst_export.h" namespace Kst { class CurveTab : public DataTab, Ui::CurveTab { Q_OBJECT public: explicit CurveTab(QWidget *parent = 0); virtual ~CurveTab(); VectorPtr xVector() const; bool xVectorDirty() const; void setXVector(VectorPtr vector); bool xVectorSelected() const; VectorPtr yVector() const; bool yVectorDirty() const; void setYVector(VectorPtr vector); bool yVectorSelected() const; VectorPtr xError() const; bool xErrorDirty() const; void setXError(VectorPtr vector); VectorPtr yError() const; bool yErrorDirty() const; void setYError(VectorPtr vector); VectorPtr xMinusError() const; bool xMinusErrorDirty() const; void setXMinusError(VectorPtr vector); VectorPtr yMinusError() const; bool yMinusErrorDirty() const; void setYMinusError(VectorPtr vector); CurveAppearance* curveAppearance() const; CurvePlacement* curvePlacement() const; bool ignoreAutoScale() const; bool ignoreAutoScaleDirty() const; void setIgnoreAutoScale(bool ignoreAutoScale); void setObjectStore(ObjectStore *store); void hidePlacementOptions(); void clearTabValues(); void setToLastX() {_xVector->setToLastX();} void setPlotMode(PlotItem *plot); + + QString manualLegendName() const; + void setManualLegendNameText(const QString &name); + void setLegendAuto(bool is_auto); + void setLegendNameVisible(bool visible); + Q_SIGNALS: void vectorsChanged(); public Q_SLOTS: void xCheckboxClicked(); void yCheckboxClicked(); void xErrorChanged(); void yErrorChanged(); void updateVectorCombos(); }; class CurveDialog : public DataDialog { Q_OBJECT public: explicit CurveDialog(ObjectPtr dataObject, QWidget *parent = 0); virtual ~CurveDialog(); void setVector(VectorPtr vector); void setPlotMode(PlotItem *plot); protected: virtual ObjectPtr createNewDataObject(); virtual ObjectPtr editExistingDataObject() const; virtual bool dialogValid() const; private Q_SLOTS: void updateButtons(); void editMultipleMode(); void editSingleMode(); private: void configureTab(ObjectPtr curve=0); CurveTab *_curveTab; }; } #endif // vim: ts=2 sw=2 et diff --git a/src/libkstapp/curvetab.ui b/src/libkstapp/curvetab.ui index 119a008f..a2e86a3e 100644 --- a/src/libkstapp/curvetab.ui +++ b/src/libkstapp/curvetab.ui @@ -1,255 +1,314 @@ CurveTab + + + 0 + 0 + 443 + 250 + + + + + + + + + 0 + 0 + + + + Legend Name: + + + + + + + false + + + + + + + Auto + + + true + + + + + Curve Contents 0 0 0 0 0 &X-axis vector: false 0 0 &Y-axis vector: false 0 0 +X e&rror bar: false 0 0 &+Y error bar: false 0 0 -X error bar: false 0 0 &-Y error bar: false &Use +X error bar for -X U&se +Y error bar for -Y Qt::Vertical QSizePolicy::Fixed 71 31 0 0 I&gnore in automatic axes range calculations 0 0 Qt::Vertical 20 87 Kst::VectorSelector QWidget
vectorselector.h
Kst::CurvePlacement QWidget
curveplacement.h
Kst::CurveAppearance QWidget
curveappearance.h
_xVector _yVector _xError _yError _xMinusError _yMinusError _xMinusSameAsPlus _yMinusSameAsPlus _ignoreAutoScale _curveAppearance _curvePlacement - + + + _autoLegend + toggled(bool) + _manualLegendName + setDisabled(bool) + + + 397 + 21 + + + 301 + 31 + + + +
diff --git a/src/libkstapp/datadialog.cpp b/src/libkstapp/datadialog.cpp index 3fc21c4c..f4ccfb88 100644 --- a/src/libkstapp/datadialog.cpp +++ b/src/libkstapp/datadialog.cpp @@ -1,252 +1,261 @@ /*************************************************************************** * * * copyright : (C) 2007 The University of Toronto * * netterfield@astro.utoronto.ca * * * * 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. * * * ***************************************************************************/ #include "datadialog.h" #include #include #include #include #include #include #include #include "datatab.h" #include "dialogpage.h" #include "editmultiplewidget.h" #include "dataobject.h" #include "document.h" #include "mainwindow.h" #include "application.h" #include "updatemanager.h" #include "sessionmodel.h" #include "updateserver.h" namespace Kst { DataDialog::DataDialog(Kst::ObjectPtr dataObject, QWidget *parent, bool edit_multiple) - : Dialog(parent), _dataObject(dataObject), _modified(false) { + : Dialog(parent), _dataObject(dataObject), _modified(false), _coreWindowWidth(0) { _dataObjectName.clear(); if (_dataObject) _mode = Edit; else _mode = New; if (MainWindow *mw = qobject_cast(parent)) { _document = mw->document(); } else { // FIXME: we need a document qFatal("ERROR: can't construct a Data Dialog without a document"); } createGui(edit_multiple); } DataDialog::~DataDialog() { } void DataDialog::createGui(bool edit_multiple) { if (_mode == New) { buttonBox()->button(QDialogButtonBox::Apply)->setVisible(false); buttonBox()->button(QDialogButtonBox::Apply)->setEnabled(false); } connect(this, SIGNAL(apply()), this, SLOT(slotApply())); QWidget *extension = extensionWidget(); QVBoxLayout *extensionLayout = new QVBoxLayout(extension); extensionLayout->setContentsMargins(0, -1, 0, -1); if (edit_multiple) { _editMultipleWidget = new EditMultipleWidget(); extensionLayout->addWidget(_editMultipleWidget); } else { _editMultipleWidget = 0L; } extension->setLayout(extensionLayout); QWidget *box = topCustomWidget(); QHBoxLayout *layout = new QHBoxLayout(box); _nameLabel = new QLabel(tr("&Name:"), box); _nameLabel->setObjectName("_nameLabel"); _tagString = new QLineEdit(box); connect(_tagString, SIGNAL(textChanged(QString)), this, SLOT(modified())); _nameLabel->setBuddy(_tagString); _shortName = new QLabel(QString(), box); _tagStringAuto = new QCheckBox(tr("&Auto","automatic"), box); _tagStringAuto->setObjectName("_tagStringAuto"); connect(_tagStringAuto, SIGNAL(toggled(bool)), _tagString, SLOT(setDisabled(bool))); connect(_tagStringAuto, SIGNAL(toggled(bool)), this, SLOT(modified())); if (edit_multiple) { _editMultipleButton = new QPushButton(tr("Edit Multiple >>")); _editMultipleButton->setObjectName("_editMultipleButton"); _editMultipleButton->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed); connect(_editMultipleButton, SIGNAL(clicked()), this, SLOT(slotEditMultiple())); } QLabel *spacer = new QLabel(); if (_dataObject) { setTagString(_dataObject->descriptiveName()); setShortName(_dataObject->shortName()); _tagStringAuto->setChecked(!_dataObject->descriptiveNameIsManual()); } else { _tagStringAuto->setChecked(true); setTagString(QString()); if (edit_multiple) { _editMultipleButton->setVisible(false); } } layout->addWidget(_nameLabel); layout->addWidget(_tagString); layout->addWidget(_shortName); layout->addWidget(_tagStringAuto); layout->addWidget(spacer); if (edit_multiple) { layout->addWidget(_editMultipleButton); } box->setLayout(layout); } QString DataDialog::tagString() const { return _tagString->text(); } void DataDialog::setTagString(const QString &tagString) { _tagString->setText(tagString); } void DataDialog::setShortName(const QString &name) { _shortName->setText('('+name+')'); } bool DataDialog::tagStringAuto() const { return _tagStringAuto->isChecked(); } void DataDialog::addDataTab(DataTab *tab) { Q_ASSERT(tab); Q_ASSERT(_document); tab->setObjectStore(_document->objectStore()); DialogPage *page = new DialogPage(this); page->setPageTitle(tab->tabTitle()); page->addDialogTab(tab); addDialogPage(page); } void DataDialog::slotApply() { Kst::ObjectPtr ptr; if (!dataObject()) { ptr = createNewDataObject(); } else { ptr = editExistingDataObject(); } setDataObject(ptr); UpdateManager::self()->doUpdates(); UpdateServer::self()->requestUpdateSignal(); kstApp->mainWindow()->document()->setChanged(true); clearModified(); } void DataDialog::modified() { _modified = true; updateApplyButton(); } void DataDialog::clearModified() { _modified = false; updateApplyButton(); } void DataDialog::updateApplyButton() { bool valid = dialogValid(); _buttonBox->button(QDialogButtonBox::Apply)->setEnabled(_modified && valid); _buttonBox->button(QDialogButtonBox::Ok)->setEnabled(_modified && valid); } void DataDialog::editMultiple(const QList &objects) { slotEditMultiple(); QStringList names; int n = objects.count(); for (int i = 0; i < n; i++) { names.append(objects.at(i)->Name()); } _editMultipleWidget->selectObjects(names); } void DataDialog::slotEditMultiple() { int charWidth = fontMetrics().averageCharWidth(); int currentWidth = width(); int extensionWidth = extensionWidget()->width(); if (extensionWidthsetVisible(!extensionWidget()->isVisible()); + if (_coreWindowWidth == 0) { + _coreWindowWidth = currentWidth; + } if (!extensionWidget()->isVisible()) { _tagString->setVisible(true); _shortName->setVisible(true); _tagStringAuto->setVisible(true); _nameLabel->setVisible(true); - setMinimumWidth(currentWidth - extensionWidth); - resize(currentWidth - extensionWidth, height()); + //setMinimumWidth(currentWidth - extensionWidth); + if (_coreWindowWidth > currentWidth - extensionWidth) { + resize(_coreWindowWidth, height()); + } else { + resize(currentWidth - extensionWidth, height()); + _coreWindowWidth = currentWidth - extensionWidth; + } _mode = Edit; _editMultipleButton->setText(tr("Edit Multiple >>")); emit editSingleMode(); } else { if (currentWidthsetVisible(false); _shortName->setVisible(false); _tagStringAuto->setVisible(false); _nameLabel->setVisible(false); - setMinimumWidth(currentWidth + extensionWidth); + _coreWindowWidth = currentWidth; + //setMinimumWidth(currentWidth + extensionWidth); resize(currentWidth + extensionWidth, height()); _mode = EditMultiple; _editMultipleButton->setText(tr("<< Edit one %1").arg(_shortName->text())); emit editMultipleMode(); } clearModified(); } QString DataDialog::dataObjectName() const { return _dataObjectName; } } // vim: ts=2 sw=2 et diff --git a/src/libkstapp/datadialog.h b/src/libkstapp/datadialog.h index df12d4f3..dba2b298 100644 --- a/src/libkstapp/datadialog.h +++ b/src/libkstapp/datadialog.h @@ -1,96 +1,97 @@ /*************************************************************************** * * * copyright : (C) 2007 The University of Toronto * * netterfield@astro.utoronto.ca * * * * 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. * * * ***************************************************************************/ #ifndef DATADIALOG_H #define DATADIALOG_H #include "dialog.h" #include "kst_export.h" #include "dataobject.h" class QLineEdit; class QCheckBox; class QLabel; namespace Kst { class DataTab; class Document; class EditMultipleWidget; class DataDialog : public Dialog { Q_OBJECT public: friend class DialogLauncherSI; friend class DialogSI; enum EditMode { New, Edit, EditMultiple }; explicit DataDialog(ObjectPtr dataObject = 0, QWidget *parent = 0, bool edit_multiple = true); virtual ~DataDialog(); EditMode editMode() const { return _mode; } void addDataTab(DataTab *tab); QString dataObjectName() const; void editMultiple(const QList &objects); protected: virtual QString tagString() const; void setTagString(const QString &tagString); void setShortName(const QString &name); bool tagStringAuto() const; ObjectPtr dataObject() const { return _dataObject; } void setDataObject(ObjectPtr dataObject) { _dataObject = dataObject; } virtual ObjectPtr createNewDataObject() = 0; virtual ObjectPtr editExistingDataObject() const = 0; Document *_document; EditMultipleWidget *_editMultipleWidget; QString _dataObjectName; virtual bool dialogValid() const {return true;} public Q_SLOTS: void slotEditMultiple(); private Q_SLOTS: void slotApply(); void modified(); void clearModified(); Q_SIGNALS: void editMultipleMode(); void editSingleMode(); private: void createGui(bool edit_multiple = true); void updateApplyButton(); private: QLineEdit *_tagString; QCheckBox *_tagStringAuto; QLabel *_shortName; QLabel *_nameLabel; QPushButton *_editMultipleButton; ObjectPtr _dataObject; EditMode _mode; bool _modified; + int _coreWindowWidth; }; } #endif // vim: ts=2 sw=2 et diff --git a/src/libkstapp/legenditem.cpp b/src/libkstapp/legenditem.cpp index cfa26cb0..eec30a35 100644 --- a/src/libkstapp/legenditem.cpp +++ b/src/libkstapp/legenditem.cpp @@ -1,552 +1,532 @@ /*************************************************************************** * * * copyright : (C) 2008 The University of Toronto * * * * 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. * * * ***************************************************************************/ #include "legenditem.h" #include #include "labelrenderer.h" #include "debug.h" #include "plotitem.h" #include "legenditemdialog.h" #include "objectstore.h" #include "dialogdefaults.h" #include "legendscriptinterface.h" #include #include #include #define LEGENDITEMMAXWIDTH 900 #define LEGENDITEMMAXHEIGHT 100 namespace Kst { LegendItem::LegendItem(PlotItem *parentPlot) : ViewItem(parentPlot->view()), _plotItem(parentPlot), _auto(true), _verticalDisplay(true) { setTypeName(tr("Legend", "a legend in a plot")); _initializeShortName(); setFixedSize(true); setAllowedGripModes(Move /*| Resize*/ /*| Rotate*/ /*| Scale*/); setViewRect(0.0, 0.0, 0.0, 0.0); view()->scene()->addItem(this); setParentViewItem(_plotItem->renderItem()); QPointF origin = QPointF(_plotItem->plotRect().width() * 0.15, _plotItem->plotRect().height() * 0.15); setPos(origin); applyDefaults(); applyDialogDefaultsStroke(); applyDialogDefaultsFill(); applyDialogDefaultsLockPosToData(); } void LegendItem::_initializeShortName() { _shortName = 'L'+QString::number(_legendnum); if (_legendnum>max_legendnum) max_legendnum = _legendnum; _legendnum++; } LegendItem::~LegendItem() { } void LegendItem::paint(QPainter *painter) { if (!isVisible()) { return; } RelationList legendItems; if (_auto) { legendItems = plot()->renderItem(PlotRenderItem::Cartesian)->relationList(); } else { legendItems = _relations; } int count = legendItems.count(); if (count <= 0) { // no legend or box if there are no legend items return; } QFont font(_font); font.setPointSizeF(view()->scaledFontSize(_fontScale, *painter->device())); painter->setFont(font); // generate string list of relation names QStringList names; bool allAuto = true; bool sameX = true; bool sameYUnits = true; LabelInfo label_info = legendItems.at(0)->xLabelInfo(); QString yUnits = legendItems.at(0)->yLabelInfo().units; for (int i = 0; idescriptiveNameIsManual()) { allAuto = false; } if (relation->xLabelInfo() != label_info) { sameX = false; } // sameYUnits is false if any non empty units are defined differently. if (yUnits.isEmpty()) { yUnits = relation->yLabelInfo().units; } else if (relation->yLabelInfo().units != yUnits) { if (!relation->yLabelInfo().units.isEmpty()) { sameYUnits = false; } } } - if (!allAuto) { - for (int i = 0; idescriptiveName()); - } - } else { - for (int i = 0; ititleInfo().singleRenderItemLabel(); - if (label.isEmpty()) { - label_info = relation->yLabelInfo(); - QString y_label = label_info.name; - if (!sameYUnits) { - if (!label_info.units.isEmpty()) { - y_label = tr("%1 \\[%2\\]", "axis labels. %1 is quantity, %2 is units. eg Time [s]. '[' must be escaped.").arg(y_label).arg(label_info.units); - } - } - if (!y_label.isEmpty()) { - LabelInfo xlabel_info = relation->xLabelInfo(); - if (!sameX) { - label = tr("%1 vs %2", "describes a plot. %1 is X axis. %2 is Y axis").arg(y_label).arg(xlabel_info.name); - } else if (xlabel_info.quantity.isEmpty()) { - label = y_label; - } else if (xlabel_info.quantity != xlabel_info.name) { - label = tr("%1 vs %2", "describes a plot. %1 is X axis. %2 is Y axis").arg(y_label).arg(xlabel_info.name); - } else { - label = y_label; - } - } else { - label = relation->descriptiveName(); - } +// if (!allAuto) { + // for (int i = 0; idescriptiveName()); + // } + // } else { + + // FIXME: move most of this into a new function, relation->legend_name + // then create separate [legend_name] and Auto in the relation dialog. + // show relation->legend_name in dialog when [x] Auto + for (int i = 0; ilegendName(sameX, sameYUnits); + + int i_dup = names.indexOf(label); + if (i_dup<0) { + names.append(label); + } else { + RelationPtr dup_relation = legendItems.at(i_dup); + if (!dup_relation->yLabelInfo().file.isEmpty()) { + names.replace(i_dup, label + " (" + dup_relation->yLabelInfo().escapedFile() + ')'); } - int i_dup = names.indexOf(label); - if (i_dup<0) { - names.append(label); - } else { - RelationPtr dup_relation = legendItems.at(i_dup); - if (!dup_relation->yLabelInfo().file.isEmpty()) { - names.replace(i_dup, label + " (" + dup_relation->yLabelInfo().escapedFile() + ')'); - } - if (!relation->yLabelInfo().file.isEmpty()) { - names.append(label + " (" + relation->yLabelInfo().escapedFile() + ')'); - } + if (!relation->yLabelInfo().file.isEmpty()) { + names.append(label + " (" + relation->yLabelInfo().escapedFile() + ')'); } } } - QSize legendSize(0, 0); QSize titleSize(0,0); Label::Parsed *parsed = Label::parse(_title, _color); int pad = painter->fontMetrics().ascent()/4; Label::RenderContext rc(painter->font(), painter); Label::renderLabel(rc, parsed->chunk, false, false); if (!_title.isEmpty()) { titleSize.setWidth(rc.x+3*pad); titleSize.setHeight(painter->fontMetrics().height()+pad); } QList sizes; int max_w = 0; int max_h = 0; for (int i = 0; isave(); size = paintRelation(names.at(i), relation, painter, false); painter->restore(); sizes.append(size); max_w = qMax(max_w, size.width()); max_h = qMax(max_h, size.height()); } // determine number of rows and number of columns int n_rows = 0; int n_cols = 0; if (_verticalDisplay) { int h=titleSize.height(); for (int i = 0; iplotRect().height()*0.6+1; n_cols = qMin(count, h / max_legend_height + 1); n_rows = count / n_cols; while (n_rows*n_colsplotRect().width()*0.8+1; n_rows = qMin(count, w / max_legend_width+1); n_cols = count/n_rows; while (n_rows*n_cols col_sizes; for (int i=0; idrawRect(rect()); int x=rect().x(); int y=rect().y(); if (!_title.isEmpty()) { rc.y = rect().y() + titleSize.height()-pad; rc.x = qMax(rect().x()+pad, rect().x() + legendSize.width()/2 - titleSize.width()/2); Label::renderLabel(rc, parsed->chunk, false, true); y+= titleSize.height(); } legendSize.setWidth(0); legendSize.setHeight(0); for (int i = 0; isave(); painter->translate(x,y); paintRelation(names.at(i), relation, painter, true); painter->restore(); int col = i/n_rows; int row = i%n_rows; if (row == n_rows-1) { // end of a column x += col_sizes.at(col).width(); y = rect().y() + titleSize.height(); } else { y += sizes.at(i).height(); } } delete parsed; } QSize LegendItem::paintRelation(QString name, RelationPtr relation, QPainter *painter, bool draw) { Label::Parsed *parsed = Label::parse(name, _color); int fontHeight = painter->fontMetrics().height(); int fontAscent = painter->fontMetrics().ascent(); QSize symbol_size = relation->legendSymbolSize(painter); int label_width = 0; int paddingValue = fontHeight / 4; if (relation->symbolLabelOnTop()) { Label::RenderContext tmprc(painter->font(), painter); Label::renderLabel(tmprc, parsed->chunk, false, false); label_width = tmprc.x; painter->translate(paddingValue, fontHeight+paddingValue / 2); symbol_size.setWidth(qMax(label_width, symbol_size.width())); } else { painter->translate(paddingValue, paddingValue / 2); } if (draw) { relation->paintLegendSymbol(painter, symbol_size); } if (relation->symbolLabelOnTop()) { painter->translate((symbol_size.width()-label_width)/2, fontAscent - fontHeight); } else { painter->translate(symbol_size.width() + paddingValue, 0); } Label::RenderContext rc(painter->font(), painter); if (relation->symbolLabelOnTop()) { rc.y = 0; } else { rc.y = (symbol_size.height()+painter->fontMetrics().boundingRect('M').height())/2; } if (parsed) { Label::renderLabel(rc, parsed->chunk, false, draw); delete parsed; parsed = 0; } double h = symbol_size.height() + paddingValue; if (relation->symbolLabelOnTop()) { h += fontHeight; } if (relation->symbolLabelOnTop()) { return QSize(qMax(rc.x,(symbol_size.width())) + (paddingValue * 2), h); } else { return QSize((symbol_size.width()) + (paddingValue * 3) + rc.x, h); } } void LegendItem::save(QXmlStreamWriter &xml) { Q_UNUSED(xml); } QColor LegendItem::legendColor() const { return _color; } void LegendItem::setLegendColor(const QColor &color) { _color = color; } void LegendItem::applyDefaults() { _auto = dialogDefaults().value(defaultsGroupName()+"/auto",true).toBool(); _color = dialogDefaults().value(defaultsGroupName()+"/color",QColor(Qt::black)).value(); QFont font; font.fromString(dialogDefaults().value(defaultsGroupName()+"/font",font.toString()).toString()); setLegendFont(font); setFontScale(dialogDefaults().value(defaultsGroupName()+"/fontScale", 12.0).toDouble()); _verticalDisplay = dialogDefaults().value(defaultsGroupName()+"/verticalDisplay",true).toBool(); } void LegendItem::setFont(const QFont &f, const QColor &c) { setLegendColor(c); setLegendFont(f); setFontScale(f.pointSize()); } void LegendItem::saveAsDialogDefaults() const { dialogDefaults().setValue(defaultsGroupName()+"/auto",_auto); dialogDefaults().setValue(defaultsGroupName()+"/title", _title); dialogDefaults().setValue(defaultsGroupName()+"/verticalDisplay", _verticalDisplay); QFont F = _font; F.setPointSize(_fontScale); saveDialogDefaultsFont(F, _color); saveDialogDefaultsPen(defaultsGroupName(), pen()); saveDialogDefaultsBrush(defaultsGroupName(), brush()); } void LegendItem::saveDialogDefaultsFont(const QFont &F, const QColor &C) { dialogDefaults().setValue(staticDefaultsGroupName()+"/font", QVariant(F).toString()); dialogDefaults().setValue(staticDefaultsGroupName()+"/fontScale",F.pointSize()); dialogDefaults().setValue(staticDefaultsGroupName()+"/color", C.name()); } void LegendItem::saveInPlot(QXmlStreamWriter &xml) { xml.writeStartElement("legend"); xml.writeAttribute("auto", QVariant(_auto).toString()); xml.writeAttribute("title", QVariant(_title).toString()); xml.writeAttribute("font", QVariant(_font).toString()); xml.writeAttribute("fontscale", QVariant(_fontScale).toString()); xml.writeAttribute("color", QVariant(_color).toString()); xml.writeAttribute("verticaldisplay", QVariant(_verticalDisplay).toString()); ViewItem::save(xml); foreach (const RelationPtr &relation, _relations) { xml.writeStartElement("relation"); xml.writeAttribute("tag", relation->Name()); xml.writeEndElement(); } xml.writeEndElement(); } bool LegendItem::configureFromXml(QXmlStreamReader &xml, ObjectStore *store) { bool validTag = true; QString primaryTag = xml.name().toString(); QXmlStreamAttributes attrs = xml.attributes(); QStringRef av; av = attrs.value("auto"); if (!av.isNull()) { setAutoContents(QVariant(av.toString()).toBool()); } av = attrs.value("title"); if (!av.isNull()) { setTitle(av.toString()); } av = attrs.value("font"); if (!av.isNull()) { QFont font; font.fromString(av.toString()); setLegendFont(font); } av = attrs.value("fontscale"); if (!av.isNull()) { setFontScale(QVariant(av.toString()).toDouble()); } av = attrs.value("color"); if (!av.isNull()) { setLegendColor(QColor(av.toString())); } av = attrs.value("verticaldisplay"); if (!av.isNull()) { setVerticalDisplay(QVariant(av.toString()).toBool()); } QString expectedEnd; while (!(xml.isEndElement() && (xml.name().toString() == primaryTag))) { if (xml.isStartElement()) { if (xml.name().toString() == "relation") { expectedEnd = xml.name().toString(); attrs = xml.attributes(); QString tagName = attrs.value("tag").toString(); RelationPtr relation = kst_cast(store->retrieveObject(tagName)); if (relation) { _relations.append(relation); } } else { parse(xml, validTag); } } else if (xml.isEndElement()) { if (xml.name().toString() != expectedEnd) { validTag = false; break; } } xml.readNext(); } return validTag; } void LegendItem::edit() { LegendItemDialog *editDialog = new LegendItemDialog(this); editDialog->show(); } void LegendItem::remove() { if (_plotItem) { _plotItem->setShowLegend(false); } ViewItem::remove(); } void LegendItem::setAutoContents(const bool autoContents) { _auto = autoContents; } bool LegendItem::autoContents() const { return _auto; } void LegendItem::setVerticalDisplay(const bool vertical) { _verticalDisplay = vertical; } bool LegendItem::verticalDisplay() const { return _verticalDisplay; } void LegendItem::setTitle(const QString &title) { _title = title; } QString LegendItem::title() const { return _title; } QFont LegendItem::font() const { return _font; } void LegendItem::setLegendFont(const QFont &font) { _font = font; } qreal LegendItem::fontScale() const { return _fontScale; } void LegendItem::setFontScale(const qreal scale) { _fontScale = scale; } QString LegendItem::_automaticDescriptiveName() const { QString name = tr("Empty Legend"); if (_auto) { name = _plotItem->descriptiveName(); } else if (_relations.size()>0) { name = _relations.at(0)->descriptiveName(); if (_relations.size()>1) { name += ", ..."; } } //qDebug() << "a desc name called: " << name << " relation.length: " << _relations.length(); return name; } QString LegendItem::descriptionTip() const { QString contents; foreach (const RelationPtr &relation, _relations) { contents += QString(" %1\n").arg(relation->Name()); } return tr("Plot: %1 \nContents:\n %2").arg(Name()).arg(contents); } ScriptInterface* LegendItem::createScriptInterface() { return new LegendSI(this); } } // vim: ts=2 sw=2 et diff --git a/src/libkstmath/relation.cpp b/src/libkstmath/relation.cpp index 9e0ee5d2..bc33bf81 100644 --- a/src/libkstmath/relation.cpp +++ b/src/libkstmath/relation.cpp @@ -1,505 +1,551 @@ /*************************************************************************** relation.cpp: base class for a curve ------------------- begin : June 2003 copyright : (C) 2003 University of Toronto email : netterfield@astro.utoronto.ca ***************************************************************************/ /*************************************************************************** * * * 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. * * Permission is granted to link with any opensource library * * * ***************************************************************************/ #include "relation.h" #include "datacollection.h" #include "debug.h" #include "objectstore.h" #include namespace Kst { const QString Relation::staticTypeString = "Relation"; Relation::Relation(ObjectStore *store) : Object() { Q_UNUSED(store); commonConstructor(); } void Relation::commonConstructor() { MaxX = MinX = MinPosX = MeanX = MaxY = MinY = MinPosY = 0.0; NS = 0; _redrawRequired = true; _ignoreAutoScale = false; _contextDetails.Lx = 0.0; _contextDetails.Hx = 0.0; _contextDetails.Ly = 0.0; _contextDetails.Hy = 0.0; _contextDetails.m_X = 0.0; _contextDetails.m_Y = 0.0; _contextDetails.b_X = 0.0; _contextDetails.b_Y = 0.0; _contextDetails.XMin = 0.0; _contextDetails.XMax = 0.0; _contextDetails.xLog = false; _contextDetails.yLog = false; _contextDetails.xLogBase = 0.0; _contextDetails.yLogBase = 0.0; _contextDetails.penWidth = 0; + + _manualLegendName.clear(); } Relation::~Relation() { } void Relation::save(QXmlStreamWriter &s) { Q_UNUSED(s) } void Relation::deleteDependents() { Data::self()->removeCurveFromPlots(this); } void Relation::paint(const CurveRenderContext& context) { if (redrawRequired(context) || _redrawRequired) { updatePaintObjects(context); _redrawRequired = false; } paintObjects(context); } bool Relation::redrawRequired(const CurveRenderContext& context) { if ((_contextDetails.Lx == context.Lx) && (_contextDetails.Hx == context.Hx) && (_contextDetails.Ly == context.Ly) && (_contextDetails.Hy == context.Hy) && (_contextDetails.m_X == context.m_X) && (_contextDetails.m_Y == context.m_Y) && (_contextDetails.b_X == context.b_X) && (_contextDetails.b_Y == context.b_Y) && (_contextDetails.XMin == context.XMin) && (_contextDetails.XMax == context.XMax) && (_contextDetails.xLog == context.xLog) && (_contextDetails.yLog == context.yLog) && (_contextDetails.xLogBase == context.xLogBase) && (_contextDetails.yLogBase == context.yLogBase) && (_contextDetails.penWidth == context.penWidth) ) { return false; } else { _contextDetails.Lx = context.Lx; _contextDetails.Hx = context.Hx; _contextDetails.Ly = context.Ly; _contextDetails.Hy = context.Hy; _contextDetails.m_X = context.m_X; _contextDetails.m_Y = context.m_Y; _contextDetails.b_X = context.b_X; _contextDetails.b_Y = context.b_Y; _contextDetails.XMin = context.XMin; _contextDetails.XMax = context.XMax; _contextDetails.xLog = context.xLog; _contextDetails.yLog = context.yLog; _contextDetails.xLogBase = context.xLogBase; _contextDetails.yLogBase = context.yLogBase; _contextDetails.penWidth = context.penWidth; return true; } } void Relation::setIgnoreAutoScale(bool ignoreAutoScale) { _ignoreAutoScale = ignoreAutoScale; } qint64 Relation::minInputSerial() const{ qint64 minSerial = LLONG_MAX; foreach (VectorPtr P, _inputVectors) { minSerial = qMin(minSerial, P->serial()); } foreach (ScalarPtr P, _inputScalars) { minSerial = qMin(minSerial, P->serial()); } foreach (MatrixPtr P, _inputMatrices) { minSerial = qMin(minSerial, P->serial()); } foreach (StringPtr P, _inputStrings) { minSerial = qMin(minSerial, P->serial()); } return minSerial; } qint64 Relation::maxInputSerialOfLastChange() const { qint64 maxSerial = NoInputs; foreach (VectorPtr P, _inputVectors) { maxSerial = qMax(maxSerial, P->serialOfLastChange()); } foreach (ScalarPtr P, _inputScalars) { maxSerial = qMax(maxSerial, P->serialOfLastChange()); } foreach (MatrixPtr P, _inputMatrices) { maxSerial = qMax(maxSerial, P->serialOfLastChange()); } foreach (StringPtr P, _inputStrings) { maxSerial = qMax(maxSerial, P->serialOfLastChange()); } return maxSerial; } +QString Relation::manualLegendName() const +{ + return _manualLegendName; +} + +void Relation::setManualLegendName(const QString &manualLegendName) +{ + _manualLegendName = manualLegendName; +} + void Relation::writeLockInputsAndOutputs() const { Q_ASSERT(myLockStatus() == KstRWLock::WRITELOCKED); - #ifdef LOCKTRACE +#ifdef LOCKTRACE qDebug() << (void*)this << this->Name() << ") Relation::writeLockInputsAndOutputs() by tid=" << (int)QThread::currentThread() << endl; #endif QList inputs; QList outputs; QList sl = _inputStrings.values(); for (QList::Iterator i = sl.begin(); i != sl.end(); ++i) { inputs += (*i).data(); } sl = _outputStrings.values(); for (QList::Iterator i = sl.begin(); i != sl.end(); ++i) { outputs += (*i).data(); } QList sc = _inputScalars.values(); for (QList::Iterator i = sc.begin(); i != sc.end(); ++i) { inputs += (*i).data(); } sc = _outputScalars.values(); for (QList::Iterator i = sc.begin(); i != sc.end(); ++i) { outputs += (*i).data(); } QList vl = _inputVectors.values(); for (QList::Iterator i = vl.begin(); i != vl.end(); ++i) { inputs += (*i).data(); } vl = _outputVectors.values(); for (QList::Iterator i = vl.begin(); i != vl.end(); ++i) { outputs += (*i).data(); } QList ml = _inputMatrices.values(); for (QList::Iterator i = ml.begin(); i != ml.end(); ++i) { inputs += (*i).data(); } ml = _outputMatrices.values(); for (QList::Iterator i = ml.begin(); i != ml.end(); ++i) { outputs += (*i).data(); } qSort(inputs); qSort(outputs); QList::ConstIterator inputIt = inputs.constBegin(); QList::ConstIterator outputIt = outputs.constBegin(); while (inputIt != inputs.constEnd() || outputIt != outputs.constEnd()) { if (inputIt != inputs.constEnd() && (outputIt == outputs.constEnd() || (void*)(*inputIt) < (void*)(*outputIt))) { // do input if (!(*inputIt)) { qWarning() << "Input for data object " << this->Name() << " is invalid." << endl; } #ifdef LOCKTRACE qDebug() << (void*)this << this->Name() << ") KstDataObject::writeLockInputsAndOutputs() by tid=" << (int)QThread::currentThread() << ": write locking input \"" << (*inputIt)->Name() << "\" (" << (void*)((KstRWLock*)*inputIt) << ")" << endl; #endif (*inputIt)->writeLock(); ++inputIt; } else { // do output if (!(*outputIt)) { qWarning() << "Output for data object " << this->Name() << " is invalid." << endl; } #ifdef LOCKTRACE qDebug() << (void*)this << this->Name() << ") KstDataObject::writeLockInputsAndOutputs() by tid=" << (int)QThread::currentThread() << ": write locking output \"" << (*outputIt)->Name() << "\" (" << (void*)((KstRWLock*)*outputIt) << ")" << endl; #endif if ((*outputIt)->provider() != this) { } (*outputIt)->writeLock(); ++outputIt; } } } void Relation::unlockInputsAndOutputs() const { #ifdef LOCKTRACE qDebug() << (void*)this << this->Name() << ") Relation::unlockInputsAndOutputs() by tid=" << (int)QThread::currentThread() << endl; #endif for (MatrixMap::ConstIterator i = _outputMatrices.constBegin(); i != _outputMatrices.constEnd(); ++i) { if (!(*i)) { qWarning() << "Output matrix for data object " << this->Name() << " is invalid." << endl; } #ifdef LOCKTRACE qDebug() << (void*)this << this->Name() << ") Relation::unlockInputsAndOutputs() by tid=" << (int)QThread::currentThread() << ": unlocking output matrix \"" << (*i)->Name() << "\" (" << (void*)((KstRWLock*)*i) << ")" << endl; #endif (*i)->unlock(); } for (MatrixMap::ConstIterator i = _inputMatrices.constBegin(); i != _inputMatrices.constEnd(); ++i) { if (!(*i)) { qWarning() << "Input matrix for data object " << this->Name() << " is invalid." << endl; } #ifdef LOCKTRACE qDebug() << (void*)this << this->Name() << ") Relation::unlockInputsAndOutputs() by tid=" << (int)QThread::currentThread() << ": unlocking input matrix \"" << (*i)->Name() << "\" (" << (void*)((KstRWLock*)*i) << ")" << endl; #endif (*i)->unlock(); } for (VectorMap::ConstIterator i = _outputVectors.constBegin(); i != _outputVectors.constEnd(); ++i) { if (!(*i)) { qWarning() << "Output vector for data object " << this->Name() << " is invalid." << endl; } #ifdef LOCKTRACE qDebug() << (void*)this << this->Name() << ") Relation::unlockInputsAndOutputs() by tid=" << (int)QThread::currentThread() << ": unlocking output vector \"" << (*i)->Name() << "\" (" << (void*)((KstRWLock*)*i) << ")" << endl; #endif (*i)->unlock(); } for (VectorMap::ConstIterator i = _inputVectors.constBegin(); i != _inputVectors.constEnd(); ++i) { if (!(*i)) { qWarning() << "Input vector for data object " << this->Name() << " is invalid." << endl; } #ifdef LOCKTRACE qDebug() << (void*)this << this->Name() << ") Relation::unlockInputsAndOutputs() by tid=" << (int)QThread::currentThread() << ": unlocking input vector \"" << (*i)->Name() << "\" (" << (void*)((KstRWLock*)*i) << ")" << endl; #endif (*i)->unlock(); } for (ScalarMap::ConstIterator i = _outputScalars.constBegin(); i != _outputScalars.constEnd(); ++i) { if (!(*i)) { qWarning() << "Output scalar for data object " << this->Name() << " is invalid." << endl; } #ifdef LOCKTRACE qDebug() << (void*)this << this->Name() << ") Relation::unlockInputsAndOutputs() by tid=" << (int)QThread::currentThread() << ": unlocking output scalar \"" << (*i)->Name() << "\" (" << (void*)((KstRWLock*)*i) << ")" << endl; #endif (*i)->unlock(); } for (ScalarMap::ConstIterator i = _inputScalars.constBegin(); i != _inputScalars.constEnd(); ++i) { if (!(*i)) { qWarning() << "Input scalar for data object " << this->Name() << " is invalid." << endl; } #ifdef LOCKTRACE qDebug() << (void*)this << this->Name() << ") Relation::unlockInputsAndOutputs() by tid=" << (int)QThread::currentThread() << ": unlocking input scalar \"" << (*i)->Name() << "\" (" << (void*)((KstRWLock*)*i) << ")" << endl; #endif (*i)->unlock(); } for (StringMap::ConstIterator i = _outputStrings.constBegin(); i != _outputStrings.constEnd(); ++i) { if (!(*i)) { qWarning() << "Output string for data object " << this->Name() << " is invalid." << endl; } #ifdef LOCKTRACE qDebug() << (void*)this << this->Name() << ") Relation::unlockInputsAndOutputs() by tid=" << (int)QThread::currentThread() << ": unlocking output string \"" << (*i)->Name() << "\" (" << (void*)((KstRWLock*)*i) << ")" << endl; #endif (*i)->unlock(); } for (StringMap::ConstIterator i = _inputStrings.constBegin(); i != _inputStrings.constEnd(); ++i) { if (!(*i)) { qWarning() << "Input string for data object " << this->Name() << " is invalid." << endl; } #ifdef LOCKTRACE qDebug() << (void*)this << this->Name() << ") Relation::unlockInputsAndOutputs() by tid=" << (int)QThread::currentThread() << ": unlocking input string \"" << (*i)->Name() << "\" (" << (void*)((KstRWLock*)*i) << ")" << endl; #endif (*i)->unlock(); } } bool Relation::uses(ObjectPtr p) const { VectorPtr v = kst_cast(p); if (v) { for (VectorMap::ConstIterator j = _inputVectors.constBegin(); j != _inputVectors.constEnd(); ++j) { if (j.value() == v) { return true; } } QHashIterator scalarDictIter(v->scalars()); for (ScalarMap::ConstIterator j = _inputScalars.constBegin(); j != _inputScalars.constEnd(); ++j) { while (scalarDictIter.hasNext()) { scalarDictIter.next(); if (scalarDictIter.value() == j.value()) { return true; } } } QHashIterator stringDictIter(v->strings()); for (StringMap::ConstIterator j = _inputStrings.constBegin(); j != _inputStrings.constEnd(); ++j) { while (stringDictIter.hasNext()) { stringDictIter.next(); if (stringDictIter.value() == j.value()) { return true; } } } } else if (MatrixPtr matrix = kst_cast(p)) { for (MatrixMap::ConstIterator j = _inputMatrices.constBegin(); j != _inputMatrices.constEnd(); ++j) { if (j.value() == matrix) { return true; } } QHashIterator scalarDictIter(matrix->scalars()); for (ScalarMap::ConstIterator j = _inputScalars.constBegin(); j != _inputScalars.constEnd(); ++j) { while (scalarDictIter.hasNext()) { scalarDictIter.next(); if (scalarDictIter.value() == j.value()) { return true; } } } } else if (DataObjectPtr obj = kst_cast(p) ) { // check all connections from this object to p for (VectorMap::Iterator j = obj->outputVectors().begin(); j != obj->outputVectors().end(); ++j) { for (VectorMap::ConstIterator k = _inputVectors.constBegin(); k != _inputVectors.constEnd(); ++k) { if (j.value() == k.value()) { return true; } } // also check dependencies on vector stats QHashIterator scalarDictIter(j.value()->scalars()); for (ScalarMap::ConstIterator k = _inputScalars.constBegin(); k != _inputScalars.constEnd(); ++k) { while (scalarDictIter.hasNext()) { scalarDictIter.next(); if (scalarDictIter.value() == k.value()) { return true; } } } // also check dependencies on vector strings QHashIterator stringDictIter(j.value()->strings()); for (StringMap::ConstIterator k = _inputStrings.constBegin(); k != _inputStrings.constEnd(); ++k) { while (stringDictIter.hasNext()) { stringDictIter.next(); if (stringDictIter.value() == k.value()) { return true; } } } } for (MatrixMap::Iterator j = obj->outputMatrices().begin(); j != obj->outputMatrices().end(); ++j) { for (MatrixMap::ConstIterator k = _inputMatrices.constBegin(); k != _inputMatrices.constEnd(); ++k) { if (j.value() == k.value()) { return true; } } // also check dependencies on vector stats QHashIterator scalarDictIter(j.value()->scalars()); for (ScalarMap::ConstIterator k = _inputScalars.constBegin(); k != _inputScalars.constEnd(); ++k) { while (scalarDictIter.hasNext()) { scalarDictIter.next(); if (scalarDictIter.value() == k.value()) { return true; } } } } for (ScalarMap::Iterator j = obj->outputScalars().begin(); j != obj->outputScalars().end(); ++j) { for (ScalarMap::ConstIterator k = _inputScalars.constBegin(); k != _inputScalars.constEnd(); ++k) { if (j.value() == k.value()) { return true; } } } for (StringMap::Iterator j = obj->outputStrings().begin(); j != obj->outputStrings().end(); ++j) { for (StringMap::ConstIterator k = _inputStrings.constBegin(); k != _inputStrings.constEnd(); ++k) { if (j.value() == k.value()) { return true; } } } } return false; } PrimitiveList Relation::inputPrimitives() const { PrimitiveList primitive_list; int n = _inputMatrices.count(); for (int i = 0; i< n; i++) { primitive_list.append(kst_cast(_inputMatrices.values().at(i))); } n = _inputStrings.count(); for (int i = 0; i< n; i++) { primitive_list.append(kst_cast(_inputStrings.values().at(i))); } n = _inputScalars.count(); for (int i = 0; i< n; i++) { primitive_list.append(kst_cast(_inputScalars.values().at(i))); } n = _inputVectors.count(); for (int i = 0; i< n; i++) { primitive_list.append(kst_cast(_inputVectors.values().at(i))); } return primitive_list; } + +QString Relation::legendName(bool sameX, bool sameYUnits) const { + if (_manualLegendName.isEmpty()) { + QString label = titleInfo().singleRenderItemLabel(); + if (label.isEmpty()) { + LabelInfo label_info = yLabelInfo(); + QString y_label = label_info.name; + if (!sameYUnits) { + if (!label_info.units.isEmpty()) { + y_label = tr("%1 \\[%2\\]", "axis labels. %1 is quantity, %2 is units. eg Time [s]. '[' must be escaped.").arg(y_label).arg(label_info.units); + } + } + if (!y_label.isEmpty()) { + LabelInfo xlabel_info = xLabelInfo(); + if (!sameX) { + label = tr("%1 vs %2", "describes a plot. %1 is X axis. %2 is Y axis").arg(y_label).arg(xlabel_info.name); + } else if (xlabel_info.quantity.isEmpty()) { + label = y_label; + } else if (xlabel_info.quantity != xlabel_info.name) { + label = tr("%1 vs %2", "describes a plot. %1 is X axis. %2 is Y axis").arg(y_label).arg(xlabel_info.name); + } else { + label = y_label; + } + } else { + label = descriptiveName(); + } + } + return label; + } else { + return _manualLegendName; + } +} + + void Relation::replaceInput(PrimitivePtr p, PrimitivePtr new_p) { if (VectorPtr v = kst_cast(p) ) { if (VectorPtr new_v = kst_cast(new_p)) { for (VectorMap::Iterator j = _inputVectors.begin(); j != _inputVectors.end(); ++j) { if (j.value() == v) { _inputVectors[j.key()] = new_v; } } } } else if (MatrixPtr m = kst_cast(p) ) { if (MatrixPtr new_m = kst_cast(new_p)) { for (MatrixMap::Iterator j = _inputMatrices.begin(); j != _inputMatrices.end(); ++j) { if (j.value() == m) { _inputMatrices[j.key()] = new_m; } } } } else if (StringPtr s = kst_cast(p) ) { if (StringPtr new_s = kst_cast(new_p)) { for (StringMap::Iterator j = _inputStrings.begin(); j != _inputStrings.end(); ++j) { if (j.value() == s) { _inputStrings[j.key()] = new_s; } } } } else if (ScalarPtr s = kst_cast(p) ) { if (ScalarPtr new_s = kst_cast(new_p)) { for (ScalarMap::Iterator j = _inputScalars.begin(); j != _inputScalars.end(); ++j) { if (j.value() == s) { _inputScalars[j.key()] = new_s; } } } } } } // vim: ts=2 sw=2 et diff --git a/src/libkstmath/relation.h b/src/libkstmath/relation.h index 195c0409..fe569b47 100644 --- a/src/libkstmath/relation.h +++ b/src/libkstmath/relation.h @@ -1,215 +1,222 @@ /*************************************************************************** relation.h: base curve type for kst ------------------- begin : Fri Oct 22 2000 copyright : (C) 2000 by C. Barth Netterfield email : netterfield@astro.utoronto.ca ***************************************************************************/ /*************************************************************************** * * * 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. * * * ***************************************************************************/ #ifndef RELATION_H #define RELATION_H #include #include "dataobject.h" #include "painter.h" #include "kstmath_export.h" #include "labelparser.h" #include "labelinfo.h" /**A class for handling curves for kst *@author C. Barth Netterfield */ class QXmlStreamWriter; namespace Kst { // context for rendering a curve in a plot class CurveRenderContext { public: // FIXME: use reasonable defaults CurveRenderContext() : painter(0L), Lx(0.0), Hx(0.0), Ly(0.0), Hy(0.0), m_X(0.0), m_Y(0.0), b_X(0.0), b_Y(0.0), x_max(0.0), y_max(0.0), x_min(0.0), y_min(0.0), XMin(0.0), YMin(0.0), XMax(0.0), YMax(0.0), xLog(false), yLog(false), xLogBase(0.0), yLogBase(0.0), penWidth(0), antialias(false) {} QPainter* painter; QRect window; double Lx, Hx, Ly, Hy; double m_X, m_Y, b_X, b_Y; double x_max, y_max, x_min, y_min; double XMin, YMin, XMax, YMax; // range and domain of plot bool xLog, yLog; double xLogBase, yLogBase; QColor foregroundColor; // plot foreground color QColor backgroundColor; // plot background color int penWidth; bool antialias; }; struct CurveContextDetails { double Lx, Hx, Ly, Hy; double m_X, m_Y; double b_X, b_Y; double XMin, XMax; bool xLog, yLog; double xLogBase, yLogBase; int penWidth; }; class ObjectStore; class Relation; class KSTMATH_EXPORT Relation : public Object { Q_OBJECT public: static const QString staticTypeString; const QString& typeString() const { return staticTypeString; } explicit Relation(ObjectStore *store); virtual ~Relation(); virtual void showNewDialog() { } virtual void showEditDialog() { } virtual void save(QXmlStreamWriter &s); virtual QString propertyString() const = 0; virtual int sampleCount() const { return NS; } virtual void setIgnoreAutoScale(bool ignoreAutoScale); virtual bool ignoreAutoScale() const { return _ignoreAutoScale; } virtual int samplesPerFrame() const { return 1; } virtual void deleteDependents(); virtual double maxX() const { return MaxX; } virtual double minX() const { return MinX; } virtual double maxY() const { return MaxY; } virtual double minY() const { return MinY; } virtual double minPosY() const { return MinPosY; } virtual double ns_maxX(int) const = 0; virtual double ns_minX(int) const = 0; virtual double ns_maxY(int) const = 0; virtual double ns_minY(int) const = 0; virtual double minPosX() const { return MinPosX; } virtual double midX() const { return (MaxX+MinX)*0.5; } virtual double midY() const { return (MaxY+MinY)*0.5; } virtual void yRange(double xFrom, double xTo, double* yMin, double* yMax) = 0; virtual bool uses(ObjectPtr p) const; // return closest distance to the given point // images always return a rating >= 5 virtual double distanceToPoint(double xpos, double dx, double ypos) const = 0; // render this curve void paint(const CurveRenderContext& context); virtual void paintObjects(const CurveRenderContext& context) = 0; virtual void updatePaintObjects(const CurveRenderContext& context) = 0; // render the legend symbol for this curve virtual QSize legendSymbolSize(QPainter *p) = 0; virtual void paintLegendSymbol(QPainter *p, const QSize &size) = 0; virtual bool symbolLabelOnTop() = 0; //virtual SharedPtr makeDuplicate(QMap< SharedPtr, SharedPtr > &duplicatedRelations) = 0; virtual SharedPtr makeDuplicate() const = 0; virtual void replaceInput(PrimitivePtr p, PrimitivePtr new_p); // Compare the cached the context to the provided one. bool redrawRequired(const CurveRenderContext& context); // If you use these, you must lock() and unlock() the object as long as you // hold the reference const VectorMap& inputVectors() const { return _inputVectors; } const VectorMap& outputVectors() const { return _outputVectors; } VectorMap& inputVectors() { return _inputVectors; } VectorMap& outputVectors() { return _outputVectors; } const ScalarMap& inputScalars() const { return _inputScalars; } const ScalarMap& outputScalars() const { return _outputScalars; } ScalarMap& inputScalars() { return _inputScalars; } ScalarMap& outputScalars() { return _outputScalars; } const StringMap& inputStrings() const { return _inputStrings; } const StringMap& outputStrings() const { return _outputStrings; } StringMap& inputStrings() { return _inputStrings; } StringMap& outputStrings() { return _outputStrings; } const MatrixMap& inputMatrices() const { return _inputMatrices; } const MatrixMap& outputMatrices() const { return _outputMatrices; } MatrixMap& inputMatrices() { return _inputMatrices; } MatrixMap& outputMatrices() { return _outputMatrices; } PrimitiveList inputPrimitives() const; virtual bool invertXHint() const {return false;} virtual bool invertYHint() const {return false;} virtual LabelInfo xLabelInfo() const = 0; virtual LabelInfo yLabelInfo() const = 0; virtual LabelInfo titleInfo() const = 0; - protected: + virtual QString legendName(bool sameX, bool sameYUnits) const; + + QString manualLegendName() const; + void setManualLegendName(const QString &manualLegendName); + +protected: virtual void writeLockInputsAndOutputs() const; virtual void unlockInputsAndOutputs() const; virtual qint64 minInputSerial() const; virtual qint64 maxInputSerialOfLastChange() const; CurveHintList *_curveHints; QString _typeString, _type; VectorMap _inputVectors; VectorMap _outputVectors; ScalarMap _inputScalars; ScalarMap _outputScalars; StringMap _inputStrings; StringMap _outputStrings; MatrixMap _inputMatrices; MatrixMap _outputMatrices; double MaxX; double MinX; double MinPosX; double MeanX; double MaxY; double MinY; double MinPosY; int NS; bool _ignoreAutoScale; CurveContextDetails _contextDetails; bool _redrawRequired; + QString _manualLegendName; + private: void commonConstructor(); }; typedef SharedPtr RelationPtr; typedef ObjectList RelationList; } #endif // vim: ts=2 sw=2 et