/***************************************************************************
**
**  This file is part of HVGui.
**
**  HVGui 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 3 of the License, or
**  (at your option) any later version.
**
**  HVGui 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 Foobar.  If not, see <http://www.gnu.org/licenses/>
**
**  See http://www.geopsy.org for more information.
**
**  Created: 2007-08-23
**  Copyright: 2007-2019
**    Marc Wathelet
**    Marc Wathelet (LGIT, Grenoble, France)
**
***************************************************************************/

#include <GeopsyGui.h>

#include "AbstractSummary.h"
#include "AbstractResultSheet.h"
#include "SummaryMapOptions.h"
#include "PeakEditor.h"
#include "AveragePeakModel.h"
#include "StationLine.h"

namespace HVGui {

/*!
  \class AbstractSummary AbstractSummary.h
  \brief Brief description of class still missing

  Full description of class still missing
*/

/*!
  Description of constructor still missing
*/
AbstractSummary::AbstractSummary(QWidget* parent)
    : GraphicSheetMenu(parent)
{
  TRACE;
  _stackedLayer=nullptr;
  _averageLayer=nullptr;
  _spectrumGridLayer=nullptr;
  _spectrumGridMaxLayer=nullptr;
  _gridCrossSectionLayer=nullptr;
  _spectrumGridPalette=nullptr;
  _bubbleLayer=nullptr;
  _bubbleNameLayer=nullptr;
  _bubblePalette=nullptr;

  _mapLabels=StationLine::StationName;
  _mapPeakSelection=StationLine::PeakNumber;
  _mapPeakValue=CurveResults::PeakFrequency;
  _mapPeakIndex=0;
  _mapShowBubbles=true;
  _mapPeakValueDecimals=2;

  _mapOptions=nullptr;
  setGeometry(5, 80, 500, 500);
}

/*!
  Description of destructor still missing
*/
AbstractSummary::~AbstractSummary()
{
  TRACE;
}

void AbstractSummary::addActions()
{
  TRACE;
  QAction * a;

  menuTools=addMenu(tr("&Tools"));

  a=new QAction(tr("&Pick maxima"), this);
  a->setStatusTip(tr("Switch grid plot to pick mode"));
  a->setCheckable(true);
  connect(a, SIGNAL(toggled(bool)), this, SLOT(pickGridMaxima(bool)));
  menuTools->addAction(a);

  a=new QAction(tr("&Auto pick maximum"), this);
  a->setStatusTip(tr( "Automatically pick the maximum of grid"));
  connect(a, SIGNAL(triggered()), this, SLOT(autoPickGridMaximum()));
  menuTools->addAction(a);

  a=new QAction(tr("&Cross section"), this);
  a->setStatusTip(tr( "Extract a cross section in the grid for each picked curve" ));
  connect(a, SIGNAL(triggered()), this, SLOT(gridCrossSection()));
  menuTools->addAction(a);

  a=new QAction(tr("&Map options"), this);
  a->setStatusTip(tr( "Set options for frequency map" ));
  connect(a, SIGNAL(triggered()), this, SLOT(mapOptions()));
  menuTools->addAction(a);

  a=new QAction(tr("&Edit peaks"), this);
  a->setStatusTip(tr("Do you think that the automatically computed peak frequency is not correct? Fix it ..."));
  connect(a, SIGNAL(triggered()), this, SLOT(editPeaks()));
  menuTools->addAction(a);
}

void AbstractSummary::setStations(const QList<AbstractStation *>& stations)
{
  TRACE;
  _results.clear();
  for(QList<AbstractStation *>::const_iterator it=stations.begin(); it!=stations.end(); ++it) {
    _results.append(static_cast<CurveResults *>((*it)->results(0)));
  }

  // Adjust the list of categories keeping format for exiting ones
  QStringList cats;
  for(QList<CurveResults *>::const_iterator it=_results.begin(); it!=_results.end(); ++it) {
    cats.append((*it)->category());
  }
  std::sort(cats.begin(), cats.end());
  unique(cats);
  static const Pen defaultPen(Qt::black, 0, Qt::NoPen);
  static const Symbol defaultSymbol(Symbol::Circle, 2.5, Pen(Qt::black), Brush(Qt::NoBrush) );
  _categories.setTexts(cats, defaultPen, defaultSymbol);

  QMap<double, CurveResults *> dist2stat=distance2Station();
  if(_stackedLayer==nullptr) {
    // Initialize graphs according to the availability of coordinates
    sheet()->setStatusBar(GeopsyGuiEngine::instance()->statusBar());
    createGraphs(dist2stat.count() > 1);
  }

  setValues(&dist2stat);

  sheet()->deepUpdate();
  setLimits();
}

void AbstractSummary::setStackedValues()
{
  TRACE;
  if(!_stackedLayer) return;
  // Add the curve to the curve plot
  _stackedLayer->clear();
  for(QList<CurveResults *>::const_iterator it=_results.begin(); it!=_results.end(); ++it) {
    const CurveResults& res=**it;
    static_cast<PlotLine2D *>(_stackedLayer->addLine())->setCurve(res.average());
  }
}

/*!
  Geometrical average for amplitudes.
*/
void AbstractSummary::setAverageValues()
{
  TRACE;
  if(!_averageLayer) return;
  // Add the curve to the curve plot
  _averageLayer->clear();
  Curve<Point2D> sum, sum2, curve;
  int n=0;
  for(QList<CurveResults *>::const_iterator it=_results.begin(); it!=_results.end(); ++it) {
    const CurveResults& res=**it;
    curve=res.average();
    if(!curve.isEmpty()) {
      curve.yLog10();
      sum.ySum(curve);
      curve.ySquare();
      sum2.ySum(curve);
      n++;
    }
  }
  if(n>0) {
    // Average layer
    sum.yMultiply(1.0/(double)n);
    curve=sum;
    curve.ySquare();
    curve.yMultiply(-n);
    sum2.ySum(curve);
    if(n<2) {
      sum2.ySetValue(0.0);
    } else {
      sum2.yMultiply(1.0/(double)(n-1));
      sum2.ySetMinimumValue(0.0);
      sum2.ySqrt();
    }
    sum.yExp10();
    sum2.yExp10();
    Curve<Point2D> max=sum;
    max.yMultiply(sum2);
    Curve<Point2D> min=sum;
    sum2.yInverse();
    min.yMultiply(sum2);
    PlotLine2D * l;
    l=static_cast<PlotLine2D *>(_averageLayer->addLine());
    l->setPen(Pen(Qt::black, 0.6, Qt::DashLine));
    l->setCurve(min);
    l=static_cast<PlotLine2D *>(_averageLayer->addLine());
    l->setPen(Pen(Qt::black, 0.6, Qt::DashLine));
    l->setCurve(max);
    l=static_cast<PlotLine2D *>(_averageLayer->addLine());
    l->setCurve(sum);
  }
}

/*!
  Add at least one peak.
*/
void AbstractSummary::setAveragePeak()
{
  TRACE;
  if(_results.count()>0) {
    AveragePeakModel m(&_results, _peaks);
    const SamplingParameters& s=_results.first()->frequencySampling();
    m.add(s.minimum(), s.maximum());
    _peaks=m.peaks();
  }
  updateAveragePeaks();
}

void AbstractSummary::updateAveragePeaks()
{
  if(!_averagePeakLayer) return;
  int n=_peaks.count();
  int n2=n*2;
  LayerLocker ll(_averagePeakLayer);
  // Adjust the number of band to fit number of peaks
  while(_averagePeakLayer->count()<n2) {
    _averagePeakLayer->addBand(QColor(Qt::lightGray));
    _averagePeakLayer->addBand(QColor(Qt::gray));
  }
  while(_averagePeakLayer->count()>n2) {
    _averagePeakLayer->removeBand(_averagePeakLayer->count()-1);
  }
  for(int i=0; i<n; i++) {
    double f=_peaks.at(i).mean();
    double df=_peaks.at(i).stddev();
    int i2=i*2;
    ParallelBand& b1=_averagePeakLayer->band(i2);
    b1.setMinimum(f/df);
    b1.setMaximum(f);
    ParallelBand& b2=_averagePeakLayer->band(i2+1);
    b2.setMinimum(f);
    b2.setMaximum(f*df);
  }
  _averagePeakLayer->deepUpdate();
}

void AbstractSummary::setSpectrumGridValues(const QMap<double, CurveResults *> * dist2stat)
{
  TRACE;
  if( !_spectrumGridLayer || !dist2stat) return;
  // Grab general info from the first station with non null average curve
  const CurveResults * res=nullptr;
  QMap<double, CurveResults *>::const_iterator it=dist2stat->begin();
  for(it=dist2stat->begin();it!=dist2stat->end();it++) {
    res=it.value();
    if(res->average().count()>0) break;
    res=nullptr;
  }
  if(!res) return;
  // Init the colored grid
  const Curve<Point2D>& f=res->average();
  int nFreqSamp=f.count();
  int nDist=dist2stat->count();
  IrregularGrid2D grid(nFreqSamp, nDist);

  // Set the sampling of the grid
  for(int i=0;i < nFreqSamp;i++ ) {
    grid.setX(i, f[i].x());
  }
  // Get the minimum to shift all from 0 to ...
  int i=0;
  double minDist=dist2stat->begin().key();
  for(it=dist2stat->begin();it!=dist2stat->end();it++, i++) {
    grid.setY(i, it.key() - minDist);
  }

  // Fill in the grid with the spectra
  i=0;
  for(it=dist2stat->begin();it!=dist2stat->end();it++, i++) {
    const CurveResults * res=it.value();
    double * gval=grid.valuePointer(0, i);
    if(res->windowCount()>0) {
      const Curve<Point2D>& c=res->average();
      if(c.count()==nFreqSamp) {
        for(int j=0; j<nFreqSamp; j++) {
          gval[j]=c[j].y();
        }
      }
    } else {
      for(int j=0; j<nFreqSamp; j++) {
        gval[j]=0.0;
      }
    }
  }
  _spectrumGridLayer->setGrid(grid);
}

void AbstractSummary::setBubbleValues()
{
  TRACE;
  if(!_bubbleLayer) return;
  ASSERT(_stackedLayer);
  AxisWindow * w=_stackedLayer->graph();
  switch(_mapPeakValue) {
  case CurveResults::PeakFrequency:
    _bubblePalette->setTitle(tr("%1 peak frequency (Hz)").arg(w->yAxis()->title()));
    break;
  case CurveResults::PeakAmplitude:
    _bubblePalette->setTitle(tr("%1 peak amplitude").arg(w->yAxis()->title()));
    break;
  }

  QVector<double> * xBubble=new QVector<double>;
  QVector<double> * yBubble=new QVector<double>;
  QVector<double> * valBubble=new QVector<double>;
  int n=_results.count();
  for(int i=0; i<n; i++) {
    CurveResults * res=_results.at(i);
    // Adjust the number of stations, TODO: when old result plot will be ok, revise this part
    if(i==_bubbleNameLayer->count()) {
      StationLine * l =static_cast<StationLine *>(_bubbleNameLayer->addLine());
      l->setStation(res);
    }
    Point rec=res->coordinates();
    StationLine * l=static_cast<StationLine *>(_bubbleNameLayer->line(i));
    l->setValue(_mapPeakSelection, _mapPeakValue, _mapPeakIndex);
    if(l->value().isValid() && _mapShowBubbles) {
      xBubble->append(rec.x());
      yBubble->append(rec.y());
      valBubble->append(l->value().value());
    }
    // Adjust category of station point
    int categoryIndex=_categories.indexOf(res->category());
    ASSERT(categoryIndex>-1);
    l->setLabel(_mapLabels);
    l->setLabelPrecision(_mapPeakValueDecimals);
    l->setSymbol(_categories.symbol(categoryIndex));
    l->setTextColor(_categories.textColor(categoryIndex));
  }
  _bubbleLayer->setXData(xBubble);
  _bubbleLayer->setYData(yBubble);
  _bubbleLayer->setValues(valBubble);

  double min=std::numeric_limits<double>::infinity(), max=-std::numeric_limits<double>::infinity();
  _bubbleLayer->valueRange(min, max);
  _bubbleLayer->setLogColorMap(min, max);
}

QMap<double, CurveResults *> AbstractSummary::distance2Station()
{
  // Calculate the best fitting cross section
  Curve<Point> statList;
  for(QList<CurveResults *>::const_iterator it=_results.begin();it!=_results.end();++it) {
    statList.append((*it)->coordinates());
  }
  // For each station I get its projection on the line (listed in the same order)
  QVector<double> distances=statList.project();
  // Create a map to sort distances
  QMap<double, CurveResults *> dist2stat;
  for(int i=_results.count() - 1;i >= 0;i-- ) {
    dist2stat.insert(distances[ i ], _results.at(i) );
  }
  return dist2stat;
}

void AbstractSummary::createStackedGraph(double x, double y)
{
  TRACE;
  ASSERT(!_stackedLayer);

  AxisWindow * w=sheet()->addGraph();
  w->setGeometry(x, y+0.5, 8.0, 8.0);
  w->xAxis()->setFrequency();
  _stackedLayer=new LineLayer(w);
  _stackedLayer->setObjectName("Curves");
  PlotLine2D * line;
  line=new PlotLine2D;
  line->setPen(Pen(Qt::SolidLine));
  line->setSymbol(Symbol(Symbol::NoSymbol));
  _stackedLayer->setReferenceLine(line);
}

void AbstractSummary::createAverageGraph(double x, double y)
{
  TRACE;
  ASSERT(!_averageLayer);

  AxisWindow * w=sheet()->addGraph();
  w->setGeometry(x, y+0.5, 8.0, 8.0);
  w->xAxis()->setFrequency();
  _averagePeakLayer=new ParallelBands(w); // Frequency bands
  _averagePeakLayer->setObjectName("Average f0");
  _averageLayer=new LineLayer(w);
  _averageLayer->setObjectName("Average");
  PlotLine2D * line;
  line=new PlotLine2D;
  line->setPen(Pen(Qt::black, 0.6, Qt::SolidLine));
  line->setSymbol(Symbol(Symbol::NoSymbol));
  _averageLayer->setReferenceLine(line);
}

void AbstractSummary::createSpectrumGridGraph(double x, double y)
{
  TRACE;
  ASSERT(!_spectrumGridLayer);
  ASSERT(_stackedLayer);

  AxisWindow * w=sheet()->addGraph();
  w->setGeometry(x, y+0.5, 16.0, 8.0);
  w->xAxis()->setFrequency();

  _spectrumGridPalette=new ColorMapWidget(nullptr);
  _spectrumGridPalette->setObjectName("SpectrumPalette");
  _spectrumGridPalette->generateColorScale(20, ColorPalette::McNames, true);
  _spectrumGridPalette->setNumberPrecision(2);
  _spectrumGridPalette->setOrientation(Axis::West);
  _spectrumGridPalette->setTitle(_stackedLayer->graph()->yAxis()->title());
  _spectrumGridPalette->setPrintXAnchor(x+16.5);
  _spectrumGridPalette->setPrintYAnchor(y+1.0);
  _spectrumGridPalette->setPrintWidth(1.3);
  _spectrumGridPalette->setPrintHeight(6.0);
  _sheet.addObject(_spectrumGridPalette);

  w->yAxis()->setTitle(tr("Distance along profile (m)"));
  _spectrumGridLayer=new IrregularGrid2DPlot (w);
  _spectrumGridLayer->setColorMap(_spectrumGridPalette->colorMap());
  connect(_spectrumGridPalette, SIGNAL(changed(ColorMap)), _spectrumGridLayer, SLOT(setColorMap(const ColorMap&)));
  connect(_spectrumGridLayer, SIGNAL(colorMapChanged(ColorMap)), _spectrumGridPalette, SLOT(setColorMap(const ColorMap &)));
  _spectrumGridLayer->setObjectName( "SpectrumGrid" );
  _spectrumGridMaxLayer=new GridMaxFollower(_spectrumGridLayer, YAxis);
  _spectrumGridMaxLayer->setObjectName( "MaxCurves" );
  _spectrumGridMaxLayer->addTrackingAction(tr("&Pick maximum"), GridMaxFollower::Pick, tr("Pick a new maximum."));
  _spectrumGridMaxLayer->addTrackingAction(tr("&Edit"), GridMaxFollower::Edit, tr("Edit points of an existing line."));
}

void AbstractSummary::createGridCrossSectionGraph(double x, double y)
{
  TRACE;
  ASSERT(!_gridCrossSectionLayer);
  ASSERT(_stackedLayer);
  ASSERT(_spectrumGridLayer);

  AxisWindow * w=sheet()->addGraph();
  w->setGeometry(x, y+0.5, 16.0, 8.0);
  w->xAxis()->setTitle(_spectrumGridLayer->graph()->yAxis()->title());
  w->yAxis()->setTitle(_stackedLayer->graph()->yAxis()->title());
  _gridCrossSectionLayer=new LineLayer(w);
  _gridCrossSectionLayer->setObjectName("CrossSections");
  PlotLine2D * line;
  line=new PlotLine2D;
  line->setPen(Pen( Qt::black, 0.6) );
  line->setSymbol(Symbol( Symbol::Circle, 1.2, Pen(Qt::black, 0.6),
                              Brush(Qt::black, Qt::SolidPattern) ));
  _gridCrossSectionLayer->setReferenceLine(line);
}

/*!
  Map with X,Y coordinates of stations, frequency ploted with colored circles
*/
void AbstractSummary::createBubbleGraph(double x, double y)
{
  TRACE;
  ASSERT(!_bubbleLayer);

  AxisWindow * w=sheet()->addGraph();
  w->setGeometry(x, y+0.5, 16.0, 16.0);

  _bubblePalette=new ColorMapWidget(nullptr);
  _bubblePalette->setObjectName("BubblePalette");
  _bubblePalette->generateColorScale(20, ColorPalette::McNames);
  _bubblePalette->setNumberPrecision(2);
  _bubblePalette->setOrientation(Axis::West);
  _bubblePalette->setPrintXAnchor(x+16.5);
  _bubblePalette->setPrintYAnchor(y+1.0);
  _bubblePalette->setPrintWidth(1.3);
  _bubblePalette->setPrintHeight(6.0);
  _sheet.addObject(_bubblePalette);

  w->xAxis()->setSizeType(Axis::Scaled);
  w->yAxis()->setSizeType(Axis::Scaled);
  ImageLayer * bg=new ImageLayer(w);
  bg->setObjectName("Background");
  _bubbleLayer=new XYValuePlot (w);
  _bubbleLayer->setObjectName("Peaks");
  _bubbleLayer->setDotDiameter(0.25);
  _bubbleLayer->setColorMap(_bubblePalette->colorMap());
  connect(_bubblePalette, SIGNAL(changed(ColorMap)), _bubbleLayer, SLOT(setColorMap(const ColorMap&)));
  connect(_bubbleLayer, SIGNAL(colorMapChanged(ColorMap)), _bubblePalette, SLOT(setColorMap(const ColorMap &)));
  _bubbleNameLayer=new NameLineLayer (w);
  _bubbleNameLayer->setObjectName("Stations");
  _bubbleNameLayer->setErrorBar(NameLineLayer::NoBar);
  StationLine * line;
  line=new StationLine;
  line->setPen(Pen(Qt::NoPen));
  _bubbleNameLayer->setReferenceLine(line);
}

void AbstractSummary::setValueTitle(const QString& t)
{
  TRACE;
  if(_stackedLayer) {
    _stackedLayer->graph()->yAxis()->setTitle(t);
  }
  if(_averageLayer) {
    _averageLayer->graph()->yAxis()->setTitle(t);
  }
  if(_spectrumGridPalette) {
    _spectrumGridPalette->setTitle(t);
  }
}

void AbstractSummary::setLimits()
{
  TRACE;
  Rect r;

  if(_stackedLayer) {
    r=_stackedLayer->boundingRect();
    AxisWindow * w=_stackedLayer->graph();
    w->xAxis() ->setRange(r.x1(), r.x2());
    w->yAxis() ->setRange(0, r.y2());
  }
  if(_averageLayer) {
    r=_averageLayer->boundingRect();
    AxisWindow * w=_averageLayer->graph();
    w->xAxis() ->setRange(r.x1(), r.x2());
    w->yAxis() ->setRange(0, r.y2());
  }
  if(_spectrumGridLayer) { // stacked is always there if spectrum is available
    // r.y2() comes from stacked
    _spectrumGridLayer->setLinearColorMap(0, r.y2());
    r=_spectrumGridLayer->boundingRect();
    AxisWindow * w=_spectrumGridLayer->graph();
    w->xAxis() ->setRange(r.x1(), r.x2());
    w->yAxis() ->setRange(r.y1(), r.y2());
    if(_gridCrossSectionLayer) {
      _gridCrossSectionLayer->graph()->xAxis() ->setRange(r.y1(), r.y2());
    }
  }
  if(_bubbleLayer) {
    r=_bubbleNameLayer->boundingRect();
    r.enlarge(0.2, LinearScale, LinearScale);
    // init to default size
    AxisWindow * w=_bubbleLayer->graph();
    w->setPrintWidth(8.0);
    w->setPrintHeight(8.0);
    w->setMapScale(r.x1(), r.y1(), r.x2(), r.y2());
  }
}

void AbstractSummary::pickGridMaxima(bool on)
{
  TRACE;
  if(!_spectrumGridMaxLayer) return;
  _spectrumGridMaxLayer->setTrackingAction(LineLayer::Pick, on);
}

void AbstractSummary::autoPickGridMaximum()
{
  TRACE;
  if(!_spectrumGridMaxLayer) return;
  PlotLine2D * l=static_cast<PlotLine2D *>(_spectrumGridMaxLayer->addLine());
  Curve<Point2D>& curve=l->curve();
  curve=_spectrumGridLayer->grid().followMaximumY<Curve<Point2D>, Point2D>();
  curve.swapXY();
  _spectrumGridMaxLayer->resetLineProperties();
  _spectrumGridMaxLayer->deepUpdate();
}

void AbstractSummary::gridCrossSection()
{
  TRACE;
  if(!_spectrumGridLayer) return;
  if(!_gridCrossSectionLayer) {
    createGridCrossSectionGraph(0.5, sheet()->printBottom());
  }
  int n=_spectrumGridMaxLayer->count();
  _gridCrossSectionLayer->clear();
  for(int i=0;i<n; i++) {
    PlotLine2D * l=static_cast<PlotLine2D *>(_gridCrossSectionLayer->addLine());
    Curve<Point2D>& curve=l->curve();
    curve= _spectrumGridLayer->grid().crossSection(static_cast<PlotLine2D *>(_spectrumGridMaxLayer->line(i))->curve(), 0.0);
  }
  _spectrumGridMaxLayer->resetLineProperties();
  AxisWindow * wSpectrumGrid=_spectrumGridLayer->graph();
  AxisWindow * wGridCrossSection=_gridCrossSectionLayer->graph();
  wGridCrossSection->xAxis()->setRange(wSpectrumGrid->yAxis()->minimum(), wSpectrumGrid->yAxis()->maximum());
  const ColorMap& pal=_spectrumGridLayer->colorMap();
  wGridCrossSection->yAxis()->setRange(0, pal.upperValue(pal.count()-2) );
  wGridCrossSection->deepUpdate();
}

void AbstractSummary::mapOptions()
{
  TRACE;
  Dialog * d=new Dialog(this);
  ASSERT(!_mapOptions);
  _mapOptions=new SummaryMapOptions(this);
  d->setMainWidget(_mapOptions, Dialog::Close);
  _mapOptions->setCategories(_categories);
  _mapOptions->setLabels(_mapLabels);
  _mapOptions->setPeakSelection(_mapPeakSelection);
  _mapOptions->setPeakValue(_mapPeakValue);
  _mapOptions->setPeakValueDecimals(_mapPeakValueDecimals);
  _mapOptions->setPeakIndex(_mapPeakIndex);
  _mapOptions->setShowBubbles(_mapShowBubbles);
  connect(_mapOptions, SIGNAL(touched()), this, SLOT(setMapOptions()));
  Settings::getRect(d, "SummaryMapOptions");
  if(d->exec()==QDialog::Accepted) {
    Settings::setRect(d, "SummaryMapOptions");
  }
  delete d;
  _mapOptions=nullptr;
}

void AbstractSummary::setMapOptions()
{
  if(_mapOptions && _bubbleLayer) {
    _mapPeakSelection=_mapOptions->peakSelection();
    _mapPeakValue=_mapOptions->peakValue();
    _mapLabels=_mapOptions->labels();
    _mapPeakValueDecimals=_mapOptions->peakValueDecimals();
    _mapPeakIndex=_mapOptions->peakIndex();
    _categories=_mapOptions->categories();
    _mapShowBubbles=_mapOptions->showBubbles();
    setValues();
    _bubbleLayer->graphContent()->deepUpdate();
  }
}

void AbstractSummary::editPeaks()
{
  TRACE;
  Dialog * d=new Dialog(this);
  PeakEditor * e=new PeakEditor(this);
  d->setMainWidget(e, Dialog::Close);
  AveragePeakModel * m=new AveragePeakModel(&_results, _peaks, e);
  e->setModel(m);
  Settings::getRect(d, "PeakEditor");
  if(d->exec()==QDialog::Accepted) {
    Settings::setRect(d, "PeakEditor");
    _peaks=m->peaks();
    updateAveragePeaks();
  }
  delete d;
}

} // namespace HVGui
