diff --git a/src/libkstapp/changedatasampledialog.cpp b/src/libkstapp/changedatasampledialog.cpp index b4d94f53..3d285b02 100644 --- a/src/libkstapp/changedatasampledialog.cpp +++ b/src/libkstapp/changedatasampledialog.cpp @@ -1,445 +1,449 @@ /*************************************************************************** * * * 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 "changedatasampledialog.h" #include "datacollection.h" #include "datavector.h" #include "datamatrix.h" #include "vscalar.h" #include "objectstore.h" #include "document.h" #include "mainwindow.h" #include "application.h" #include "dialogdefaults.h" #include "updatemanager.h" #include "updateserver.h" #include namespace Kst { ChangeDataSampleDialog::ChangeDataSampleDialog(QWidget *parent) : QDialog(parent) { setupUi(this); MainWindow::setWidgetFlags(this); if (MainWindow *mw = qobject_cast(parent)) { _store = mw->document()->objectStore(); } else { // FIXME: we need the object store qFatal("ERROR: can't construct a ChangeDataSampleDialog without the object store"); } connect(_add, SIGNAL(clicked()), this, SLOT(addButtonClicked())); connect(_remove, SIGNAL(clicked()), this, SLOT(removeButtonClicked())); connect(_removeAll, SIGNAL(clicked()), this, SLOT(removeAll())); connect(_addAll, SIGNAL(clicked()), this, SLOT(addAll())); connect(_vectorList, SIGNAL(itemDoubleClicked(QListWidgetItem*)), this, SLOT(availableDoubleClicked(QListWidgetItem*))); connect(_selectedVectorList, SIGNAL(itemDoubleClicked(QListWidgetItem*)), this, SLOT(selectedDoubleClicked(QListWidgetItem*))); connect(_vectorList, SIGNAL(itemSelectionChanged()), this, SLOT(updateButtons())); connect(_selectedVectorList, SIGNAL(itemSelectionChanged()), this, SLOT(updateButtons())); connect(_dataRange, SIGNAL(modified()), this, SLOT(modified())); connect(_buttonBox->button(QDialogButtonBox::Apply), SIGNAL(clicked()), this, SLOT(apply())); connect(_buttonBox->button(QDialogButtonBox::Ok), SIGNAL(clicked()), this, SLOT(OKClicked())); connect(_buttonBox->button(QDialogButtonBox::Cancel), SIGNAL(clicked()), this, SLOT(reject())); connect(UpdateServer::self(), SIGNAL(objectListsChanged()), this, SLOT(updateCurveListDialog())); initializeEntries(); updateButtons(); updateIndexEntries(); } ChangeDataSampleDialog::~ChangeDataSampleDialog() { } void ChangeDataSampleDialog::show() { updateCurveListDialog(); initializeEntries(); updateButtons(); QDialog::show(); } void ChangeDataSampleDialog::removeButtonClicked() { foreach (QListWidgetItem* item, _selectedVectorList->selectedItems()) { _vectorList->addItem(_selectedVectorList->takeItem(_selectedVectorList->row(item))); } _vectorList->clearSelection(); updateButtons(); updateIndexEntries(); } void ChangeDataSampleDialog::selectedDoubleClicked(QListWidgetItem * item) { if (item) { _vectorList->addItem(_selectedVectorList->takeItem(_selectedVectorList->row(item))); _vectorList->clearSelection(); updateButtons(); updateIndexEntries(); } } void ChangeDataSampleDialog::addButtonClicked() { foreach (QListWidgetItem* item, _vectorList->selectedItems()) { _selectedVectorList->addItem(_vectorList->takeItem(_vectorList->row(item))); } _selectedVectorList->clearSelection(); updateButtons(); updateIndexEntries(); } void ChangeDataSampleDialog::availableDoubleClicked(QListWidgetItem * item) { if (item) { _selectedVectorList->addItem(_vectorList->takeItem(_vectorList->row(item))); _selectedVectorList->clearSelection(); updateButtons(); updateIndexEntries(); } } void ChangeDataSampleDialog::updateIndexEntries() { // Make a list of all the data sources for all of the vectors which have been selected. QList data_sources; _selectedVectorList->blockSignals(true); _selectedVectorList->selectAll(); QList selectedItems = _selectedVectorList->selectedItems(); _selectedVectorList->clearSelection(); _selectedVectorList->blockSignals(false); for (int i = 0; i < selectedItems.size(); ++i) { if (DataVectorPtr vector = kst_cast(_store->retrieveObject(selectedItems.at(i)->text()))) { if (!data_sources.contains(vector->dataSource())) { data_sources.append(vector->dataSource()); } } } QStringList index_fields; // make a list of fields which are provided by all data sources... if (data_sources.size()>0) { foreach (const QString &field, data_sources[0]->indexFields()) { bool in_all = true; for (int i=1; iindexFields().contains(field)); } if (in_all) { index_fields.append(field); } } } _dataRange->updateIndexList(index_fields); } void ChangeDataSampleDialog::updateButtons() { bool valid = _selectedVectorList->count() > 0; _buttonBox->button(QDialogButtonBox::Ok)->setEnabled(valid); _buttonBox->button(QDialogButtonBox::Apply)->setEnabled(valid); _add->setEnabled(_vectorList->selectedItems().count() > 0); _addAll->setEnabled(_vectorList->count() > 0); _remove->setEnabled(_selectedVectorList->selectedItems().count() > 0); _removeAll->setEnabled(_selectedVectorList->count() > 0); } void ChangeDataSampleDialog::modified() { updateButtons(); } void ChangeDataSampleDialog::updateCurveListDialog() { PrimitiveList dataVectors = _store->getFramePrimitives(); _vectorList->blockSignals(true); _vectorList->clearSelection(); _selectedVectorList->clearSelection(); // make sure all items in _vectorList exist in the store; remove if they don't. for (int i_item = 0; i_item < _vectorList->count(); i_item++) { bool exists=false; for (int i_vector = 0; i_vectorName() == _vectorList->item(i_item)->text()) { exists = true; break; } } if (!exists) { QListWidgetItem *item = _vectorList->takeItem(i_item); delete item; i_item--; } } // make sure all items in _selectedVectorList exist in the store; remove if they don't. for (int i_item = 0; i_item<_selectedVectorList->count(); i_item++) { bool exists=false; for (int i_vector = 0; i_vectorName() == _selectedVectorList->item(i_item)->text()) { exists = true; break; } } if (!exists) { QListWidgetItem *item = _selectedVectorList->takeItem(i_item); delete item; i_item--; } } // insert into _vectorList all items in store not in one of the lists. for (int i_vector = 0; i_vectorcount(); i_item++) { if (dataVectors.at(i_vector)->Name() == _selectedVectorList->item(i_item)->text()) { _selectedVectorList->item(i_item)->setToolTip(dataVectors.at(i_vector)->descriptionTip()); listed = true; break; } } for (int i_item = 0; i_item<_vectorList->count(); i_item++) { if (dataVectors.at(i_vector)->Name() == _vectorList->item(i_item)->text()) { _vectorList->item(i_item)->setToolTip(dataVectors.at(i_vector)->descriptionTip()); listed = true; break; } } if (!listed) { QListWidgetItem *wi = new QListWidgetItem(dataVectors.at(i_vector)->Name()); _vectorList->addItem(wi); wi->setToolTip(dataVectors.at(i_vector)->descriptionTip()); } } _vectorList->blockSignals(false); } void ChangeDataSampleDialog::addAll() { _vectorList->selectAll(); addButtonClicked(); } void ChangeDataSampleDialog::removeAll() { _selectedVectorList->selectAll(); removeButtonClicked(); } void ChangeDataSampleDialog::initializeEntries() { _dataRange->setCountFromEnd(dialogDefaults().value("vector/countFromEnd",false).toBool()); _dataRange->setStart(dialogDefaults().value("vector/start", 0).toInt()); _dataRange->setReadToEnd(dialogDefaults().value("vector/readToEnd",true).toBool()); _dataRange->setRange(dialogDefaults().value("vector/range", 1).toInt()); _dataRange->setSkip(dialogDefaults().value("vector/skip", 0).toInt()); _dataRange->setDoSkip(dialogDefaults().value("vector/doSkip", false).toBool()); _dataRange->setDoFilter(dialogDefaults().value("vector/doAve",false).toBool()); _dataRange->setStartUnits(dialogDefaults().value("vector/startUnits",tr("frames")).toString()); _dataRange->setRangeUnits(dialogDefaults().value("vector/rangeUnits",tr("frames")).toString()); } void ChangeDataSampleDialog::updateDefaults(QListWidgetItem* item) { if (!item) { return; } if (DataVectorPtr vector = kst_cast(_store->retrieveObject(item->text()))) { vector->readLock(); _dataRange->setCountFromEnd(vector->countFromEOF()); _dataRange->setStart(vector->countFromEOF() ? 0 : vector->reqStartFrame()); _dataRange->setReadToEnd(vector->readToEOF()); _dataRange->setRange(vector->readToEOF() ? 0 : vector->reqNumFrames()); _dataRange->setSkip(vector->skip()); _dataRange->setDoSkip(vector->doSkip()); _dataRange->setDoFilter(vector->doAve()); vector->unlock(); } } void ChangeDataSampleDialog::OKClicked() { apply(); accept(); } void ChangeDataSampleDialog::apply() { _selectedVectorList->selectAll(); QList selectedItems = _selectedVectorList->selectedItems(); QString start_units; QString range_units; QHash f0_map; QHash r_map; bool custom_start_index = (_dataRange->_startUnits->currentIndex() != 0) && (!_dataRange->countFromEnd()); bool custom_range_index = (_dataRange->_rangeUnits->currentIndex() != 0) && (!_dataRange->readToEnd()); if (!custom_start_index && !custom_range_index) { // FIXME: also for custom index. start_units.clear(); // see if we have enough memory //FIXME: doesn't consider data objects that depend on this, and it should //FIXME: doesn't work under windows or mac double current_memory_used = 0.0; double memory_needed = 0.0; for (int i = 0; i < selectedItems.size(); ++i) { if (DataVectorPtr vector = kst_cast(_store->retrieveObject(selectedItems.at(i)->text()))) { current_memory_used += double(vector->length())*sizeof(double); long ns=0; if (_dataRange->readToEnd()) { ns = vector->fileLength() - (int)_dataRange->start(); } else { ns = (int)_dataRange->range(); } if (_dataRange->doSkip()) { ns/=_dataRange->skip(); } else { ns *= vector->samplesPerFrame(); } memory_needed += double(ns)*sizeof(double); } } double memory_available = Data::AvailableMemory(); if (memory_needed-current_memory_used > memory_available) { //QApplication::restoreOverrideCursor(); QMessageBox::warning(this, tr("Insufficient Memory"), tr("You requested to read in %1 MB of data but it seems that you only have approximately %2 MB of usable memory available. You cannot load this much data." ).arg((memory_needed-current_memory_used)/(1024*1024)).arg(memory_available/(1024*1024))); return; } } start_units = _dataRange->_startUnits->currentText(); range_units = _dataRange->_rangeUnits->currentText(); for (int i = 0; i < selectedItems.size(); ++i) { QString filename; DataSourcePtr datasource; bool valid = false; bool use_custom_start_index = false; bool use_custom_range_index = false; if (DataVectorPtr vector = kst_cast(_store->retrieveObject(selectedItems.at(i)->text()))) { filename = vector->filename(); datasource = vector->dataSource(); valid = true; use_custom_range_index = custom_range_index; use_custom_start_index = custom_start_index; } else if (DataMatrixPtr matrix = kst_cast(_store->retrieveObject(selectedItems.at(i)->text()))) { filename = matrix->filename(); datasource = matrix->dataSource(); valid = true; } else if (VScalarPtr vscalar = kst_cast(_store->retrieveObject(selectedItems.at(i)->text()))) { filename = vscalar->filename(); datasource = vscalar->dataSource(); valid = true; } if (valid) { if (!f0_map.contains(filename)) { int f0; int r; if (use_custom_start_index) { f0 = datasource->indexToFrame(_dataRange->start(), start_units); } else if (_dataRange->countFromEnd()) { f0 = -1; } else { f0 = _dataRange->start(); } if (use_custom_range_index) { r = _dataRange->range()*datasource->framePerIndex(range_units); } else if (_dataRange->readToEnd()) { r = -1; } else { r = (int)_dataRange->range(); } f0_map.insert(filename, f0); r_map.insert(filename, r); } } } for (int i = 0; i < selectedItems.size(); ++i) { if (DataVectorPtr vector = kst_cast(_store->retrieveObject(selectedItems.at(i)->text()))) { vector->writeLock(); int from = f0_map.value(vector->filename()); int range = r_map.value(vector->filename()); vector->changeFrames( from, range, _dataRange->skip(), _dataRange->doSkip(), _dataRange->doFilter()); vector->setStartUnits(start_units); vector->setRangeUnits(start_units); vector->registerChange(); vector->unlock(); } else if (DataMatrixPtr matrix = kst_cast(_store->retrieveObject(selectedItems.at(i)->text()))) { matrix->writeLock(); int from = f0_map.value(matrix->filename()); int range = r_map.value(matrix->filename()); - matrix->setFrame(from+range-1); + if (from < 0) { + matrix->setFrame(-1); + } else { + matrix->setFrame(from+range-1); + } matrix->setStartUnits(start_units); matrix->setRangeUnits(start_units); matrix->registerChange(); matrix->unlock(); } else if (VScalarPtr vscalar = kst_cast(_store->retrieveObject(selectedItems.at(i)->text()))) { vscalar->writeLock(); int from = f0_map.value(vscalar->filename()); int range = r_map.value(vscalar->filename()); vscalar->changeFrame(from+range-1); //vscalar->setStartUnits(start_units); //vscalar->setRangeUnits(start_units); vscalar->registerChange(); vscalar->unlock(); } } UpdateManager::self()->doUpdates(true); UpdateServer::self()->requestUpdateSignal(); dialogDefaults().setValue("vector/range", _dataRange->range()); dialogDefaults().setValue("vector/start", _dataRange->start()); dialogDefaults().setValue("vector/countFromEnd", _dataRange->countFromEnd()); dialogDefaults().setValue("vector/readToEnd", _dataRange->readToEnd()); dialogDefaults().setValue("vector/skip", _dataRange->skip()); dialogDefaults().setValue("vector/doSkip", _dataRange->doSkip()); dialogDefaults().setValue("vector/doAve", _dataRange->doFilter()); dialogDefaults().setValue("vector/startUnits", _dataRange->_startUnits->currentText()); dialogDefaults().setValue("vector/rangeUnits", _dataRange->_rangeUnits->currentText()); updateCurveListDialog(); kstApp->mainWindow()->document()->setChanged(true); } } // vim: ts=2 sw=2 et