/* * Project: MoleCuilder * Description: creates and alters molecular systems * Copyright (C) 2013 Frederik Heber. All rights reserved. * * * This file is part of MoleCuilder. * * MoleCuilder 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. * * MoleCuilder 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 MoleCuilder. If not, see . */ /* * QtHomologyList.cpp * * Created on: Jun 24, 2013 * Author: heber */ // include config.h #ifdef HAVE_CONFIG_H #include #endif #include "Views/Qt4/QtHomologyList.hpp" #include "Views/Qt4/QtNumericalItem.hpp" #include #include #include #include #include #include #include "CodePatterns/MemDebug.hpp" #include #include #include #include "CodePatterns/Log.hpp" #include "Fragmentation/Homology/HomologyContainer.hpp" #include "FunctionApproximation/FunctionModel.hpp" #include "FunctionApproximation/TrainingData.hpp" #include "Potentials/CompoundPotential.hpp" #include "Potentials/EmpiricalPotential.hpp" #include "Potentials/InternalCoordinates/Coordinator.hpp" #include "Potentials/PotentialRegistry.hpp" #ifdef HAVE_QWT #include "UIElements/Views/Qt4/Plotting/QSeisData.hpp" #include "UIElements/Views/Qt4/Plotting/QSeisPageRegistry.hpp" #include "UIElements/Views/Qt4/Plotting/QSeisPlotCurve.hpp" #include "UIElements/Views/Qt4/Plotting/QSeisPlotPage.hpp" #include "UIElements/Views/Qt4/Plotting/QSeisCurveRegistry.hpp" #endif #include "World.hpp" using namespace std; using namespace boost::assign; const int QtHomologyList::COLUMNCOUNT = COLUMNTYPES_MAX; const char *QtHomologyList::COLUMNNAMES[QtHomologyList::COLUMNCOUNT]={"Number","Nodes","Edges","Occurrence"}; QtHomologyList::QtHomologyList(QWidget * _parent) : QWidget(_parent), Observer("QtHomologyList"), potentialregistry_enabled(false) { QHBoxLayout* layout = new QHBoxLayout(this); QSplitter *splitter = new QSplitter (Qt::Horizontal, this ); layout->addWidget(splitter); // tree widget treewidget = new QTreeWidget (splitter); treewidget->setSelectionMode( QTreeWidget::SingleSelection ); treewidget->setColumnCount(COLUMNCOUNT); treewidget->setSortingEnabled(true); //treewidget->setSizePolicy( QSizePolicy::Minimum, sizePolicy().verticalPolicy() ); QStringList header; for(int i=0; isetHeaderLabels(header); treewidget->sortByColumn(0); splitter->addWidget(treewidget); // plot widget #ifdef HAVE_QWT widget = new QSeisPlotPage ("energy", splitter); //widget->setSizePolicy( QSizePolicy::MinimumExpanding, sizePolicy().verticalPolicy() ); QSeisPageRegistry::getInstance().registerInstance(widget); #else widget = new QWidget(splitter); #endif splitter->addWidget(widget); dirty = true; clearing = false; QSettings settings; settings.beginGroup("QtHomologyList"); treewidget->resize(settings.value("treewidget_size", QSize(width()/2, 20)).toSize()); widget->resize(settings.value("plotwidget_size", QSize(width()/2, 20)).toSize()); settings.endGroup(); HomologyContainer &homologies = World::getInstance().getHomologies(); homologies.signOn(this); PotentialRegistry::getInstance().signOn(this); potentialregistry_enabled = true; #ifdef HAVE_QWT //connect the PlotCurveRegistry directly to the PlotPage registry connect(QSeisCurveRegistry::getPointer(), SIGNAL(curveAdded(std::string, QString)), QSeisPageRegistry::getPointer(), SLOT(addCurve(std::string, QString))); connect(QSeisCurveRegistry::getPointer(), SIGNAL(curveRemoved(std::string, QString)), QSeisPageRegistry::getPointer(), SLOT(removeCurve(std::string, QString))); connect(QSeisCurveRegistry::getPointer(), SIGNAL(curveChanged(std::string, QString)), QSeisPageRegistry::getPointer(), SLOT(updateCurve(std::string, QString))); #endif connect(treewidget,SIGNAL(itemSelectionChanged()),this,SLOT(rowSelected())); connect(this,SIGNAL(changed()),this,SLOT(update())); connect(this,SIGNAL(needsRefill()),this,SLOT(refill()), Qt::QueuedConnection); emit needsRefill(); } QtHomologyList::~QtHomologyList() { QSettings settings; settings.beginGroup("QtHomologyList"); settings.setValue("treewidget_size", treewidget->size()); settings.setValue("plotwidget_size", widget->size()); settings.endGroup(); HomologyContainer &homologies = World::getInstance().getHomologies(); homologies.signOff(this); if (potentialregistry_enabled) PotentialRegistry::getInstance().signOff(this); } void QtHomologyList::update(Observable *publisher) { dirty = true; // force an update from Qt... // clearing = true; // treewidget->clear(); // clearing = false; emit changed(); //doesn't work!?! } void QtHomologyList::refill() { clearing = true; const HomologyContainer &homologies = World::getInstance().getHomologies(); // clear everything HomologySelection.clear(); treewidget->clear(); #ifdef HAVE_QWT QSeisCurveRegistry::getInstance().resetRegistry(); #endif size_t count = 0; for (HomologyContainer::const_key_iterator homologyiter = homologies.key_begin(); homologyiter != homologies.key_end(); homologyiter = homologies.getNextKey(homologyiter), ++count) { HomologyContainer::range_t occurences = homologies.getHomologousGraphs(*homologyiter); const HomologyGraph &graph = occurences.first->first; const size_t times = std::distance(occurences.first, occurences.second); // create item std::vector numerical_columns; numerical_columns += OCCURRENCE; QTreeWidgetItem *treeItem = new QtNumericalItem(NUMBER, numerical_columns, treewidget); treeItem->setText(NUMBER, QString::number(count)); { std::stringstream output; graph.printNodes(output); treeItem->setText(NODES, QString(output.str().c_str())); } { std::stringstream output; graph.printEdges(output); treeItem->setText(EDGES, QString(output.str().c_str())); } if (times > 0) { treeItem->setText(OCCURRENCE, QString::number(times)); } else { treeItem->setText(OCCURRENCE, "none"); treeItem->setDisabled(true); } HomologySelection.push_back(treeItem->isSelected()); #ifdef HAVE_QWT // create associated curve in plot CompoundPotential *compound = new CompoundPotential(graph); ASSERT( compound != NULL, "QtHomologyList::refill() - compound is NULL."); TrainingData data(compound->getSpecificFilter()); data(homologies.getHomologousGraphs(graph)); if (!data.getTrainingInputs().empty()) { // generate QSeisData const TrainingData::InputVector_t &inputs = data.getAllArguments(); const TrainingData::OutputVector_t &outputs = data.getTrainingOutputs(); std::vector xvalues; std::vector yvalues; for (TrainingData::OutputVector_t::const_iterator outputiter = outputs.begin(); outputiter != outputs.end(); ++outputiter) yvalues.push_back((*outputiter)[0]); // go through each potential for (CompoundPotential::models_t::const_iterator potiter = compound->begin(); potiter != compound->end(); ++potiter) { const EmpiricalPotential &potential = dynamic_cast(**potiter); const std::string potentialname = potential.getName(); const FunctionModel::filter_t filter = potential.getSpecificFilter(); Coordinator::ptr coordinator = potential.getCoordinator(); // then we need to sample the potential xvalues.clear(); for (TrainingData::InputVector_t::const_iterator inputiter = inputs.begin(); inputiter != inputs.end(); ++inputiter) { const FunctionModel::list_of_arguments_t specificargs = filter(*inputiter); double average = 0.; for (FunctionModel::list_of_arguments_t::const_iterator argiter = specificargs.begin(); argiter != specificargs.end(); ++argiter) { const FunctionModel::arguments_t args = *argiter; average += (*coordinator)(args); } if (specificargs.size() > 1) { const size_t index = xvalues.size(); xvalues.push_back(average/(double)specificargs.size()); yvalues[index] *= 1./(double)specificargs.size(); } } // We need to sort the xvalues (and associated yvalues also) std::vector::const_iterator xiter = xvalues.begin(); std::vector::const_iterator yiter = yvalues.begin(); std::map > sorted_xy; for (;xiter != xvalues.end(); ++xiter, ++yiter) { std::set yset; yset.insert(*yiter); std::pair >::iterator, bool> inserter = sorted_xy.insert(std::make_pair(*xiter, yset)); if (!inserter.second) inserter.first->second.insert(*yiter); } xvalues.clear(); yvalues.clear(); for (std::map >::const_iterator iter = sorted_xy.begin(); iter != sorted_xy.end(); ++iter) { for (std::set::const_iterator valueiter = iter->second.begin(); valueiter != iter->second.end(); ++valueiter) { xvalues.push_back(iter->first); yvalues.push_back(*valueiter); } } QSeisData data(xvalues, yvalues, QString(potentialname.c_str())); // couple to QSeisPlotCurve and register the curve QSeisPlotCurve *curve = new QSeisPlotCurve(QString(potentialname.c_str()), "energy"); curve->updateCurve(&data); if (!QSeisCurveRegistry::getInstance().isPresentByName(curve->getName())) QSeisCurveRegistry::getInstance().registerInstance(curve); else delete curve; // couple to QSeisPlotPage widget->addCurve(potentialname); } } #endif } dirty = false; clearing = false; } void QtHomologyList::paintEvent(QPaintEvent * event) { if (dirty) refill(); // treewidget->paintEvent(event); } void QtHomologyList::subjectKilled(Observable *publisher) { // as a new instance should always already be present ... just sign on if (static_cast(publisher) == PotentialRegistry::getPointer()) { potentialregistry_enabled = false; } else { // its HomologyContainer } } void QtHomologyList::rowSelected() { //std::cout << "rowSelected\n"; for (int i=0;itopLevelItemCount();i++){ QTreeWidgetItem *item = treewidget->topLevelItem(i); bool newSelection = item->isSelected(); if (newSelection != HomologySelection[i]){ // TODO: Add selected curve to QTabWidget } } }