diff --git a/src/libkstapp/changedatasampledialog.cpp b/src/libkstapp/changedatasampledialog.cpp index 3d285b02..d2f3e9d0 100644 --- a/src/libkstapp/changedatasampledialog.cpp +++ b/src/libkstapp/changedatasampledialog.cpp @@ -1,449 +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; + bool valid = (_selectedVectorList->count() > 0) && (_dataRange->rangeIsValid()); _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()); 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 diff --git a/src/libkstapp/datawizard.cpp b/src/libkstapp/datawizard.cpp index 2065760a..cde36f19 100644 --- a/src/libkstapp/datawizard.cpp +++ b/src/libkstapp/datawizard.cpp @@ -1,1391 +1,1392 @@ /*************************************************************************** * * * 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 "datawizard.h" #include #include #include #include #include #include "colorsequence.h" #include "curve.h" #include "datacollection.h" #include "datasourceconfiguredialog.h" #include "datavector.h" #include "dialogdefaults.h" #include "document.h" #include "mainwindow.h" #include "objectstore.h" #include "plotitem.h" #include "plotiteminterface.h" #include "applicationsettings.h" #include "updatemanager.h" #include "datasourcepluginmanager.h" #include "sharedaxisboxitem.h" #include "boxitem.h" #include "updateserver.h" #include "geticon.h" namespace Kst { // // DataWizardPageDataSource // DataWizardPageDataSource::DataWizardPageDataSource(ObjectStore *store, QWidget *parent, const QString& default_source) : QWizardPage(parent), _pageValid(false), _store(store), _requestID(0) { setupUi(this); MainWindow::setWidgetFlags(this); connect(_url, SIGNAL(changed(QString)), this, SLOT(sourceChanged(QString))); connect(_configureSource, SIGNAL(clicked()), this, SLOT(configureSource())); //connect(_recentFiles, SIGNAL(currentTextChanged(QString)), _url, SLOT(setFile(QString))); connect(_recentFiles, SIGNAL(itemClicked(QListWidgetItem*)), this, SLOT(recentFileClicked(QListWidgetItem*))); connect(_url, SIGNAL(changed(QString)), _recentFiles, SLOT(clearSelection())); connect(_cleanupRecentFiles, SIGNAL(clicked(bool)), this, SLOT(cleanupRecentDataFilesClicked())); if (default_source.isEmpty()) { _url->setFile(dialogDefaults().value("vector/datasource", ".").toString()); } else { _url->setFile(default_source); } _url->setFocus(); _updateBox->addItem(tr("Time Interval", "update periodically")); _updateBox->addItem(tr("Change Detection", "update when a change is detected")); _updateBox->addItem(tr("No Update", "do not update the file")); updateUpdateBox(); QStringList recentFiles = kstApp->mainWindow()->recentDataFiles(); _recentFiles->addItems(recentFiles); int h = fontMetrics().lineSpacing(); _url->setFixedHeight(h*4/3); } DataWizardPageDataSource::~DataWizardPageDataSource() { } void DataWizardPageDataSource::updateUpdateBox() { if (_dataSource) { _updateBox->setEnabled(true); switch (_dataSource->updateType()) { case DataSource::Timer: _updateBox->setCurrentIndex(0); break; case DataSource::File: _updateBox->setCurrentIndex(1); break; case DataSource::None: _updateBox->setCurrentIndex(2); break; default: _updateBox->setCurrentIndex(dialogDefaults().value("wizard/updateType", 0).toInt()); break; }; } else { _updateBox->setEnabled(false); } } void DataWizardPageDataSource::setTypeActivated() { updateTypeActivated(_updateBox->currentIndex()); } int DataWizardPageDataSource::updateType() { return _updateBox->currentIndex(); } void DataWizardPageDataSource::updateTypeActivated(int idx) { if (!_dataSource) { _updateBox->setEnabled(false); return; } _updateBox->setEnabled(true); switch (idx) { case 0: _dataSource->startUpdating(DataSource::Timer); break; case 1: _dataSource->startUpdating(DataSource::File); break; case 2: _dataSource->startUpdating(DataSource::None); break; default: break; }; } void DataWizardPageDataSource::recentFileClicked(QListWidgetItem *item) { _url->setFile(item->text()); } void DataWizardPageDataSource::cleanupRecentDataFilesClicked() { kstApp->mainWindow()->cleanupRecentDataFilesList(); QStringList recentFiles = kstApp->mainWindow()->recentDataFiles(); _recentFiles->clear(); _recentFiles->addItems(recentFiles); } bool DataWizardPageDataSource::isComplete() const { return _pageValid; } DataSourcePtr DataWizardPageDataSource::dataSource() const { return _dataSource; } QStringList DataWizardPageDataSource::dataSourceFieldList() const { return _dataSource->vector().list(); } void DataWizardPageDataSource::configureSource() { QPointer dialog = new DataSourceConfigureDialog(DataDialog::New, _dataSource, this); if ( dialog->exec() == QDialog::Accepted ) { sourceChanged(_dataSource->fileName()); } delete dialog; } void DataWizardPageDataSource::sourceValid(QString filename, int requestID) { if (_requestID != requestID) { return; } _pageValid = true; _dataSource = DataSourcePluginManager::findOrLoadSource(_store, filename, true); connect(_dataSource, SIGNAL(progress(int,QString)), kstApp->mainWindow(), SLOT(updateProgress(int,QString))); _fileType->setText(_dataSource->fileType()); _dataSource->readLock(); _configureSource->setEnabled(_dataSource->hasConfigWidget()); _dataSource->unlock(); { DataSourcePtr tmpds = _dataSource; // increase usage count _store->cleanUpDataSourceList(); } updateUpdateBox(); emit completeChanged(); emit dataSourceChanged(); } void DataWizardPageDataSource::sourceChanged(const QString& file) { _pageValid = false; _fileType->setText(QString()); _configureSource->setEnabled(false); _updateBox->setEnabled(false); emit completeChanged(); _requestID += 1; ValidateDataSourceThread *validateDSThread = new ValidateDataSourceThread(file, _requestID); connect(validateDSThread, SIGNAL(dataSourceValid(QString,int)), this, SLOT(sourceValid(QString,int))); QThreadPool::globalInstance()->start(validateDSThread); } // // DataWizardPageVectors // DataWizardPageVectors::DataWizardPageVectors(QWidget *parent) : QWizardPage(parent) { setupUi(this); _up->setIcon(KstGetIcon("kst_uparrow")); _down->setIcon(KstGetIcon("kst_downarrow")); _add->setIcon(KstGetIcon("kst_rightarrow")); _remove->setIcon(KstGetIcon("kst_leftarrow")); _up->setToolTip(tr("Raise in plot order: Alt+Up")); _down->setToolTip(tr("Lower in plot order: Alt+Down")); _add->setToolTip(tr("Select: Alt+s")); _remove->setToolTip(tr("Remove: Alt+r")); connect(_add, SIGNAL(clicked()), this, SLOT(add())); connect(_remove, SIGNAL(clicked()), this, SLOT(remove())); connect(_up, SIGNAL(clicked()), this, SLOT(up())); connect(_down, SIGNAL(clicked()), this, SLOT(down())); connect(_vectors, SIGNAL(itemDoubleClicked(QListWidgetItem*)), this, SLOT(add())); connect(_vectorsToPlot, SIGNAL(itemDoubleClicked(QListWidgetItem*)), this, SLOT(remove())); connect(_vectorReduction, SIGNAL(textChanged(QString)), this, SLOT(filterVectors(QString))); connect(_vectorSearch, SIGNAL(clicked()), this, SLOT(searchVectors())); _vectors->setSortingEnabled(false); _vectorsToPlot->setSortingEnabled(false); } DataWizardPageVectors::~DataWizardPageVectors() { } QListWidget* DataWizardPageVectors::plotVectors() const { return _vectorsToPlot; } void DataWizardPageVectors::updateVectors() { _vectors->clear(); _vectorsToPlot->clear(); _vectors->addItems(((DataWizard*)wizard())->dataSourceFieldList()); _availableLabel->setText(tr("%1 vector(s) available").arg(_vectors->count())); } bool DataWizardPageVectors::vectorsSelected() const { return _vectorsToPlot->count() > 0; } bool DataWizardPageVectors::isComplete() const { return vectorsSelected(); } void DataWizardPageVectors::remove() { int j=0, i=0; int count = _vectorsToPlot->count(); for (i = 0; i < count; ++i) { if (_vectorsToPlot->item(i-j) && _vectorsToPlot->item(i-j)->isSelected()) { _vectors->addItem(_vectorsToPlot->takeItem(i-j)); j += 1; } } _vectors->clearSelection(); _selectedLabel->setText(tr("%1 vector(s) selected").arg(_vectorsToPlot->count())); emit completeChanged(); } void DataWizardPageVectors::add() { for (int i = 0; i < _vectors->count(); i++) { if (_vectors->item(i) && _vectors->item(i)->isSelected()) { _vectorsToPlot->addItem(_vectors->takeItem(i)); i--; } } _vectorsToPlot->setCurrentRow(_vectorsToPlot->count() - 1); _selectedLabel->setText(tr("%1 vector(s) selected").arg(_vectorsToPlot->count())); emit completeChanged(); } void DataWizardPageVectors::up() { _vectorsToPlot->setFocus(); int i = _vectorsToPlot->currentRow(); if (i != -1) { QListWidgetItem *item = _vectorsToPlot->takeItem(i); _vectorsToPlot->insertItem(i-1, item); _vectorsToPlot->clearSelection(); _vectorsToPlot->setCurrentItem(item); emit completeChanged(); } } void DataWizardPageVectors::down() { // move item down int i = _vectorsToPlot->currentRow(); if (i != -1) { QListWidgetItem *item = _vectorsToPlot->takeItem(i); _vectorsToPlot->insertItem(i+1, item); _vectorsToPlot->clearSelection(); _vectorsToPlot->setCurrentItem(item); emit completeChanged(); } } void DataWizardPageVectors::filterVectors(const QString& filter) { _vectors->clearSelection(); if (filter=="*") { // optimization _vectors->selectAll(); return; } QRegExp re(filter, Qt::CaseSensitive, QRegExp::Wildcard); QStringList selected; for (int i = 0; i < _vectors->count(); i++) { QListWidgetItem *item = _vectors->item(i); if (re.exactMatch(item->text())) { item = _vectors->takeItem(i); selected.append(item->text()); i--; } } _vectors->insertItems(0, selected); // special case optimization: // selecting and unselecting individual items is expensive, // but selecting all of them is fast, // so either select or select all, then unselect, which ever is fewer. if (selected.count() > _vectors->count()/2) { _vectors->selectAll(); for (int i=selected.count(); i<_vectors->count(); i++) { _vectors->item(i)->setSelected(false); } } else { for (int i=0; iitem(i)->setSelected(true); } } if (selected.count()>0) { _vectors->scrollToTop(); } } void DataWizardPageVectors::searchVectors() { QString s = _vectorReduction->text(); if (!s.isEmpty()) { if (s[0] != '*') { s = '*' + s; } if (s[s.length()-1] != '*') { s += '*'; } _vectorReduction->setText(s); } } // // DataWizardPageFilters // DataWizardPageFilters::DataWizardPageFilters(QWidget *parent) : QWizardPage(parent) { setupUi(this); } DataWizardPageFilters::~DataWizardPageFilters() { } DataWizardPagePlot::DataWizardPagePlot(QWidget *parent) : QWizardPage(parent) { setupUi(this); connect(_customGrid, SIGNAL(toggled(bool)), this, SLOT(updateButtons())); updatePlotBox(); updateButtons(); } // // DataWizardPagePlot // DataWizardPagePlot::~DataWizardPagePlot() { } void DataWizardPagePlot::updateButtons() { _gridColumns->setEnabled(_customGrid->isChecked()); } DataWizardPagePlot::CurvePlotPlacement DataWizardPagePlot::curvePlacement() const { CurvePlotPlacement placement = OnePlot; if (_multiplePlots->isChecked()) { placement = MultiplePlots; } else if (_cycleThrough->isChecked()) { placement = CyclePlotCount; } else if (_cycleExisting->isChecked()) { placement = CycleExisting; } else if (_existingPlot->isChecked()) { placement = ExistingPlot; } return placement; } DataWizardPagePlot::PlotTabPlacement DataWizardPagePlot::plotTabPlacement() const { PlotTabPlacement placement = CurrentTab; if (_newTab->isChecked()) { placement = NewTab; } else if (_separateTabs->isChecked()) { placement = SeparateTabs; } return placement; } CurvePlacement::Layout DataWizardPagePlot::layout() const { if (_autoLayout->isChecked()) return CurvePlacement::Auto; else if (_customGrid->isChecked()) return CurvePlacement::Custom; else return CurvePlacement::Protect; } int DataWizardPagePlot::gridColumns() const { return _gridColumns->value(); } bool DataWizardPagePlot::drawLines() const { return _drawLines->isChecked(); } bool DataWizardPagePlot::drawPoints() const { return _drawPoints->isChecked(); } bool DataWizardPagePlot::drawLinesAndPoints() const { return _drawBoth->isChecked(); } bool DataWizardPagePlot::PSDLogX() const { return _psdLogX->isChecked(); } bool DataWizardPagePlot::PSDLogY() const { return _psdLogY->isChecked(); } bool DataWizardPagePlot::legendsOn() const { return _legendsOn->isChecked(); } bool DataWizardPagePlot::legendsAuto() const { return _legendsAuto->isChecked(); } bool DataWizardPagePlot::legendsVertical() const { return _legendsVertical->isChecked(); } bool DataWizardPagePlot::rescaleFonts() const { return _rescaleFonts->isChecked(); } bool DataWizardPagePlot::shareAxis() const { return _shareAxis->isChecked(); } int DataWizardPagePlot::plotCount() const { return _plotNumber->value(); } PlotItemInterface *DataWizardPagePlot::existingPlot() const { return _existingPlotName->itemData(_existingPlotName->currentIndex()).value(); } void DataWizardPagePlot::updatePlotBox() { _plotNumber->setValue(dialogDefaults().value("wizard/plotCount",2).toInt()); if (dialogDefaults().value("wizard/legendsAuto",true).toBool()) { _legendsOn->setChecked(true); } else if (dialogDefaults().value("wizard/legendsOn",false).toBool()) { _legendsAuto->setChecked(true); } else { _legendsOff->setChecked(true); } _psdLogX->setChecked(dialogDefaults().value("wizard/logX",false).toBool()); _psdLogY->setChecked(dialogDefaults().value("wizard/logY",false).toBool()); _legendsOn->setChecked(dialogDefaults().value("wizard/legendsOn",false).toBool()); _legendsAuto->setChecked(dialogDefaults().value("wizard/legendsAuto",false).toBool()); _legendsVertical->setChecked(dialogDefaults().value("legend/verticalDisplay",false).toBool()); _rescaleFonts->setChecked(dialogDefaults().value("wizard/rescaleFonts", true).toBool()); _shareAxis->setChecked(dialogDefaults().value("wizard/shareAxis", false).toBool()); _shareAxis->hide(); //FIXME - not done yet. if (dialogDefaults().value("wizard/linesOnly", true).toBool()) { _drawLines->setChecked(true); } else if (dialogDefaults().value("wizard/pointsOnly", true).toBool()) { _drawPoints->setChecked(true); } else { _drawBoth->setChecked(true); } foreach (PlotItemInterface *plot, Data::self()->plotList()) { _existingPlotName->addItem(plot->plotName(), qVariantFromValue(plot)); } bool havePlots = _existingPlotName->count() > 0; _cycleExisting->setEnabled(havePlots); _existingPlot->setEnabled(havePlots); _existingPlotName->setEnabled(havePlots && _existingPlot->isChecked()); _plotLayoutBox->setEnabled(!_existingPlot->isChecked()); CurvePlotPlacement placement = static_cast(dialogDefaults().value("wizard/curvePlacement",MultiplePlots).toInt()); switch (placement) { case OnePlot: _onePlot->setChecked(true); break; case MultiplePlots: _multiplePlots->setChecked(true); break; case CyclePlotCount: _cycleThrough->setChecked(true); break; case CycleExisting: if (havePlots) { _cycleExisting->setChecked(true); } else { _multiplePlots->setChecked(true); } break; case ExistingPlot: if (havePlots) { _existingPlot->setChecked(true); } else { _onePlot->setChecked(true); } break; default: _multiplePlots->setChecked(true); break; } CurvePlacement::Layout layout = static_cast(dialogDefaults().value("wizard/plotLayout", CurvePlacement::Auto).toInt()); switch (layout) { case CurvePlacement::Auto: _autoLayout->setChecked(true); break; case CurvePlacement::Custom: _customGrid->setChecked(true); break; case CurvePlacement::Protect: _protectLayout->setChecked(true); break; } PlotTabPlacement tabPlacement = static_cast(dialogDefaults().value("wizard/plotPlacement", SeparateTabs).toInt()); switch (tabPlacement) { case CurrentTab: _currentTab->setChecked(true); break; case NewTab: _newTab->setChecked(true); break; case SeparateTabs: _separateTabs->setChecked(true); break; } _gridColumns->setValue(dialogDefaults().value("wizard/gridColumns", CurvePlacement::Auto).toInt()); } // // DataWizardPageDataPresentation // DataWizardPageDataPresentation::DataWizardPageDataPresentation(ObjectStore *store, DataWizard *parent) : QWizardPage(parent), _pageValid(false), _dw(parent) { setupUi(this); _xVectorExisting->setObjectStore(store); _xVectorExisting->setToLastX(dialogDefaults().value("curve/xvectorfield","INDEX").toString()); _xAxisUseExisting->setChecked(_xVectorExisting->count()>0); dataRange()->loadWidgetDefaults(); getFFTOptions()->loadWidgetDefaults(); connect(_xAxisCreateFromField, SIGNAL(toggled(bool)), this, SLOT(optionsUpdated())); connect(_xVector, SIGNAL(currentIndexChanged(int)), this, SLOT(optionsUpdated())); connect(_xVectorExisting, SIGNAL(selectionChanged(QString)), this, SLOT(optionsUpdated())); connect(_xVectorExisting, SIGNAL(selectionChanged(QString)), this, SLOT(checkWarningLabel())); connect(_xAxisCreateFromField, SIGNAL(toggled(bool)), this, SLOT(checkWarningLabel())); connect(_DataRange, SIGNAL(modified()), this, SLOT(checkWarningLabel())); + connect(_DataRange, SIGNAL(modified()), this, SIGNAL(completeChanged())); connect(_xAxisGroup, SIGNAL(toggled(bool)), this, SLOT(checkWarningLabel())); _FFTOptions->GroupBoxFFTOptions->setCheckable(true); _FFTOptions->GroupBoxFFTOptions->setTitle(tr("Create S&pectra Plots. Set FFT options below:")); _FFTOptions->GroupBoxFFTOptions->setChecked(dialogDefaults().value("wizard/doPSD",false).toBool()); _xAxisGroup->setChecked(dialogDefaults().value("wizard/doXY",true).toBool()); checkWarningLabel(); } DataWizardPageDataPresentation::~DataWizardPageDataPresentation() { } FFTOptions* DataWizardPageDataPresentation::getFFTOptions() const { return _FFTOptions; } DataRange* DataWizardPageDataPresentation::dataRange() const { return _DataRange; } bool DataWizardPageDataPresentation::createXAxisFromField() const { return _xAxisCreateFromField->isChecked(); } QString DataWizardPageDataPresentation::vectorField() const { return _xVector->currentText(); } VectorPtr DataWizardPageDataPresentation::selectedVector() const { return _xVectorExisting->selectedVector(); } bool DataWizardPageDataPresentation::plotPSD() const { return _FFTOptions->GroupBoxFFTOptions->isChecked(); } bool DataWizardPageDataPresentation::plotData() const { return _xAxisGroup->isChecked(); } bool DataWizardPageDataPresentation::plotDataPSD() const { return (plotPSD() && plotData()); } void DataWizardPageDataPresentation::optionsUpdated() { _pageValid = validOptions(); emit completeChanged(); } void DataWizardPageDataPresentation::checkWarningLabel() { bool warn = false; if (_xAxisGroup->isChecked() && _xAxisUseExisting->isChecked()) { DataVectorPtr xv = kst_cast(_xVectorExisting->selectedVector()); if (xv) { // do the number of requested frames match? if (xv->readToEOF()) { if (!_DataRange->readToEnd()) { warn = true; } } else { if (xv->reqNumFrames() != _DataRange->range() || _DataRange->readToEnd()) { warn = true; } } // does the starting frame match? if (xv->countFromEOF()) { if (!_DataRange->countFromEnd()) { warn = true; } } else { if (xv->reqStartFrame() != _DataRange->start() || (_DataRange->countFromEnd())) { warn = true; } } if (warn) { _xAxisWarningLabel->setText(tr("Warning: the data range of the existing X vector does not match the Y vectors.")); } else { if (_dw->_pageDataSource->dataSource()) { if (_dw->_pageDataSource->dataSource()->fileName() != xv->filename()) { warn = true; _xAxisWarningLabel->setText(tr("Warning: the file name of the existing X vector does not match the Y vectors.")); } } } } else if (_xVectorExisting->selectedVector()) { _xAxisWarningLabel->setText(tr("Warning: the selected X vector may not match the data range of the Y vectors.")); warn = true; } } _xAxisWarningLabel->setVisible(warn); _XAxisWarningLabel2->setVisible(warn); } void DataWizardPageDataPresentation::updateVectors() { _xVector->clear(); _xVector->addItems(((DataWizard*)wizard())->dataSourceFieldList()); _pageValid = validOptions(); int x_index = _xVector->findText(dialogDefaults().value("curve/xvectorfield","INDEX").toString()); if (x_index<0) { x_index = _xVector->findText("INDEX"); } if (x_index<0) { x_index = 0; } _xVector->setCurrentIndex(x_index); dataRange()->updateIndexList(((DataWizard*)wizard())->dataSourceIndexList()); emit completeChanged(); } void DataWizardPageDataPresentation::applyFilter(bool filter) { emit filterApplied(filter); } bool DataWizardPageDataPresentation::isComplete() const { - return _pageValid; + return _DataRange->rangeIsValid() && _pageValid; } bool DataWizardPageDataPresentation::validOptions() { if (!_xAxisGroup->isEnabled()) { return true; } if (_xAxisCreateFromField->isChecked()) { QString txt = _xVector->currentText(); for (int i = 0; i < _xVector->count(); ++i) { if (_xVector->itemText(i) == txt) { return true; } } return false; } else { return (_xVectorExisting->selectedVector()); } } int DataWizardPageDataPresentation::nextId() const { // if (_applyFilters->isChecked()) { // return DataWizard::PageFilters; // } else { return DataWizard::PagePlot; // } } // // DataWizard // DataWizard::DataWizard(QWidget *parent, const QString& fileToOpen) : QWizard(parent), _document(0) { MainWindow *mw = qobject_cast(parent); if (!mw) { // we need a document // not sure that this can ever happen. qFatal("ERROR: can't construct a DataWizard without a document"); return; } _document = mw->document(); Q_ASSERT(_document); _pageDataSource = new DataWizardPageDataSource(_document->objectStore(), this, fileToOpen); connect(_pageDataSource, SIGNAL(progress(int,QString)), mw, SLOT(updateProgress(int,QString))); _pageVectors = new DataWizardPageVectors(this); _pageDataPresentation = new DataWizardPageDataPresentation(_document->objectStore(), this); _pageFilters = new DataWizardPageFilters(this); _pagePlot = new DataWizardPagePlot(this); setPage(PageDataSource, _pageDataSource); setPage(PageVectors, _pageVectors); setPage(PageDataPresentation, _pageDataPresentation); setPage(PageFilters, _pageFilters); setPage(PagePlot, _pagePlot); setWindowTitle("Data Wizard"); setAttribute(Qt::WA_DeleteOnClose); show(); connect(_pageDataSource, SIGNAL(dataSourceChanged()), _pageVectors, SLOT(updateVectors())); connect(_pageDataSource, SIGNAL(dataSourceChanged()), _pageDataPresentation, SLOT(updateVectors())); connect(_pageDataSource, SIGNAL(dataSourceChanged()), _pageDataPresentation, SLOT(checkWarningLabel())); connect(_pageDataSource, SIGNAL(destroyed()), kstApp->mainWindow(), SLOT(cleanUpDataSourceList())); disconnect(button(QWizard::FinishButton), SIGNAL(clicked()), (QDialog*)this, SLOT(accept())); connect(button(QWizard::FinishButton), SIGNAL(clicked()), this, SLOT(finished())); // the dialog needs to know that the default has been set.... _pageDataSource->sourceChanged(dialogDefaults().value("vector/datasource",".").toString()); if (!fileToOpen.isEmpty()) { _pageDataSource->sourceChanged(fileToOpen); } } DataWizard::~DataWizard() { } QStringList DataWizard::dataSourceFieldList() const { return _pageDataSource->dataSourceFieldList(); } QStringList DataWizard::dataSourceIndexList() const { return _pageDataSource->dataSource()->indexFields(); } void DataWizard::finished() { DataVectorList vectors; uint n_curves = 0; uint n_steps = 0; dialogDefaults().setValue("wizard/updateType", _pageDataSource->updateType()); dialogDefaults().setValue("wizard/doPSD", _pageDataPresentation->plotPSD()); dialogDefaults().setValue("wizard/doXY", _pageDataPresentation->plotData()); dialogDefaults().setValue("wizard/curvePlacement", _pagePlot->curvePlacement()); dialogDefaults().setValue("wizard/plotPlacement", _pagePlot->plotTabPlacement()); dialogDefaults().setValue("wizard/plotCount", _pagePlot->plotCount()); dialogDefaults().setValue("wizard/legendsOn", _pagePlot->legendsOn()); dialogDefaults().setValue("wizard/legendsAuto", _pagePlot->legendsAuto()); dialogDefaults().setValue("legend/verticalDisplay", _pagePlot->legendsVertical()); dialogDefaults().setValue("wizard/logX", _pagePlot->PSDLogX()); dialogDefaults().setValue("wizard/logY", _pagePlot->PSDLogY()); dialogDefaults().setValue("wizard/rescaleFonts", _pagePlot->rescaleFonts()); dialogDefaults().setValue("wizard/shareAxis", _pagePlot->shareAxis()); dialogDefaults().setValue("wizard/linesOnly", _pagePlot->drawLines()); dialogDefaults().setValue("wizard/pointsOnly", _pagePlot->drawPoints()); dialogDefaults().setValue("wizard/plotLayout", _pagePlot->layout()); dialogDefaults().setValue("wizard/gridColumns", _pagePlot->gridColumns()); QApplication::setOverrideCursor(QCursor(Qt::WaitCursor)); DataSourcePtr ds = _pageDataSource->dataSource(); if (!ds.isPtrValid()) { return; } ds->enableUpdates(); emit dataSourceLoaded(ds->fileName()); // check for sufficient memory double memoryRequested = 0; double memoryAvailable = Data::AvailableMemory(); double frames; ds->writeLock(); double startOffset = _pageDataPresentation->dataRange()->start(); double rangeCount = _pageDataPresentation->dataRange()->range(); bool customStartIndex = (_pageDataPresentation->dataRange()->_startUnits->currentIndex() != 0) && (!_pageDataPresentation->dataRange()->countFromEnd()); bool customRangeCount = (_pageDataPresentation->dataRange()->_rangeUnits->currentIndex() != 0) && (!_pageDataPresentation->dataRange()->readToEnd()); if (customStartIndex) { startOffset = ds->indexToFrame(_pageDataPresentation->dataRange()->start(), _pageDataPresentation->dataRange()->startUnits()); } if (customRangeCount) { rangeCount = _pageDataPresentation->dataRange()->range()*ds->framePerIndex(_pageDataPresentation->dataRange()->rangeUnits()); } bool separate_tabs = ((_pagePlot->plotTabPlacement() == DataWizardPagePlot::SeparateTabs) && _pageDataPresentation->plotPSD() && _pageDataPresentation->plotData()); // only add to memory requirement if xVector is to be created if (_pageDataPresentation->createXAxisFromField()) { if (_pageDataPresentation->dataRange()->readToEnd()) { frames = ds->vector().dataInfo(_pageDataPresentation->vectorField()).frameCount - startOffset; } else { frames = qMin(rangeCount,double(ds->vector().dataInfo(_pageDataPresentation->vectorField()).frameCount)); } if (_pageDataPresentation->dataRange()->doSkip() && _pageDataPresentation->dataRange()->skip() > 0) { memoryRequested += double(frames) / _pageDataPresentation->dataRange()->skip() * sizeof(double); } else { memoryRequested += double(frames) * ds->vector().dataInfo(_pageDataPresentation->vectorField()).samplesPerFrame * sizeof(double); } } // memory estimate for the y vectors { int fftLen = int(pow(2.0, double(_pageDataPresentation->getFFTOptions()->FFTLength() - 1))); ds->vector().prepareRead(_pageVectors->plotVectors()->count()); for (int i = 0; i < _pageVectors->plotVectors()->count(); i++) { QString field = _pageVectors->plotVectors()->item(i)->text(); if (_pageDataPresentation->dataRange()->readToEnd()) { frames = ds->vector().dataInfo(field).frameCount - startOffset; } else { frames = rangeCount; int fc = ds->vector().dataInfo(field).frameCount; if (frames > (unsigned long) fc) { frames = fc; } } if (_pageDataPresentation->dataRange()->doSkip() && _pageDataPresentation->dataRange()->skip() > 0) { memoryRequested += double(frames) / _pageDataPresentation->dataRange()->skip()*sizeof(double); } else { memoryRequested += double(frames) * ds->vector().dataInfo(field).samplesPerFrame * sizeof(double); } if (_pageDataPresentation->plotPSD()) { memoryRequested += fftLen * 6.0; } } } ds->unlock(); if (memoryRequested > memoryAvailable) { 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(memoryRequested/(1024*1024)).arg(memoryAvailable/(1024*1024))); return; } n_steps += _pageVectors->plotVectors()->count(); if (_pageDataPresentation->plotPSD()) { n_steps += _pageVectors->plotVectors()->count(); } VectorPtr xv; // only create x vector if needed if (_pageDataPresentation->createXAxisFromField()) { n_steps += 1; // for the creation of the x-vector const QString field = _pageDataPresentation->vectorField(); dialogDefaults().setValue("curve/xvectorfield",field); Q_ASSERT(_document && _document->objectStore()); DataVectorPtr dxv = _document->objectStore()->createObject(); dxv->writeLock(); dxv->change(ds, field, _pageDataPresentation->dataRange()->countFromEnd() ? -1 : startOffset, _pageDataPresentation->dataRange()->readToEnd() ? -1 : rangeCount, _pageDataPresentation->dataRange()->skip(), _pageDataPresentation->dataRange()->doSkip(), _pageDataPresentation->dataRange()->doFilter()); if (customStartIndex) { dxv->setStartUnits(_pageDataPresentation->dataRange()->_startUnits->currentText()); } if (customRangeCount) { dxv->setRangeUnits(_pageDataPresentation->dataRange()->_rangeUnits->currentText()); } dxv->registerChange(); dxv->unlock(); xv = dxv; } else { xv = kst_cast(_pageDataPresentation->selectedVector()); } bool xAxisIsTime = xv->isTime(); { DataVectorPtr vector; for (int i = 0; i < _pageVectors->plotVectors()->count(); i++) { QString field = _pageVectors->plotVectors()->item(i)->text(); Q_ASSERT(_document && _document->objectStore()); vector = _document->objectStore()->createObject(); vector->writeLock(); vector->change(ds, field, _pageDataPresentation->dataRange()->countFromEnd() ? -1 : startOffset, _pageDataPresentation->dataRange()->readToEnd() ? -1 : rangeCount, _pageDataPresentation->dataRange()->skip(), _pageDataPresentation->dataRange()->doSkip(), _pageDataPresentation->dataRange()->doFilter()); if (customStartIndex) { vector->setStartUnits(_pageDataPresentation->dataRange()->_startUnits->currentText()); } if (customRangeCount) { vector->setRangeUnits(_pageDataPresentation->dataRange()->_rangeUnits->currentText()); } vector->registerChange(); vector->unlock(); vectors.append(vector); ++n_curves; } if (n_curves>0) { _pageDataPresentation->dataRange()->setWidgetDefaults(); setDataVectorDefaults(vector); } } // Create a new tab, if we asked for it and the current tab isn't empty. if ((_pagePlot->plotTabPlacement() == DataWizardPagePlot::NewTab) || separate_tabs) { // (_pagePlot->plotTabPlacement() == DataWizardPagePlot::SeparateTabs)) { if (_document->currentView()->scene()->items().count()>0) { _document->createView(); } } if (_pageDataPresentation->plotPSD() || _pageDataPresentation->plotData()) { // create the necessary plots QList plotList; PlotItem *plotItem = 0; bool relayout = true; int plotsInPage = _document->currentView()->scene()->items().count(); switch (_pagePlot->curvePlacement()) { case DataWizardPagePlot::ExistingPlot: { plotItem = static_cast(_pagePlot->existingPlot()); plotList.append(plotItem); relayout = false; break; } case DataWizardPagePlot::OnePlot: { CreatePlotForCurve *cmd = new CreatePlotForCurve(); cmd->createItem(); plotItem = static_cast(cmd->item()); plotList.append(plotItem); if (_pageDataPresentation->plotDataPSD()) { if (separate_tabs) { _document->createView(); } CreatePlotForCurve *cmd = new CreatePlotForCurve(); cmd->createItem(); plotItem = static_cast(cmd->item()); plotList.append(plotItem); } break; } case DataWizardPagePlot::MultiplePlots: { int nplots = vectors.count() * (_pageDataPresentation->plotPSD() + _pageDataPresentation->plotData()); if (separate_tabs) nplots/=2; for (int i = 0; i < nplots; ++i) { CreatePlotForCurve *cmd = new CreatePlotForCurve(); cmd->createItem(); plotItem = static_cast(cmd->item()); plotList.append(plotItem); } if (separate_tabs) { _document->createView(); for (int i = 0; i < nplots; ++i) { CreatePlotForCurve *cmd = new CreatePlotForCurve(); cmd->createItem(); plotItem = static_cast(cmd->item()); plotList.append(plotItem); } } break; } case DataWizardPagePlot::CycleExisting: { foreach (PlotItemInterface *plot, Data::self()->plotList()) { plotItem = static_cast(plot); plotList.append(plotItem); } relayout = false; break; } case DataWizardPagePlot::CyclePlotCount: { int nplots = _pagePlot->plotCount() * (_pageDataPresentation->plotPSD() + _pageDataPresentation->plotData()); for (int i = 0; i < nplots; ++i) { CreatePlotForCurve *cmd = new CreatePlotForCurve(); cmd->createItem(); plotItem = static_cast(cmd->item()); plotList.append(plotItem); } } default: break; } // create the data curves QList colors; QColor color; int ptype = 0; int i_plot = 0; for (DataVectorList::Iterator it = vectors.begin(); it != vectors.end(); ++it) { if (_pageDataPresentation->plotData()) { color = ColorSequence::self().next(); colors.append(color); DataVectorPtr vector = kst_cast(*it); Q_ASSERT(vector); Q_ASSERT(_document && _document->objectStore()); CurvePtr curve = _document->objectStore()->createObject(); curve->setXVector(xv); curve->setYVector(vector); curve->setXError(0); curve->setYError(0); curve->setXMinusError(0); curve->setYMinusError(0); curve->setColor(color); curve->setHasPoints(_pagePlot->drawLinesAndPoints() || _pagePlot->drawPoints()); curve->setHasLines(_pagePlot->drawLinesAndPoints() || _pagePlot->drawLines()); curve->setLineWidth(dialogDefaults().value("curves/lineWidth",0).toInt()); curve->setPointSize(dialogDefaults().value("curves/pointSize",CURVE_DEFAULT_POINT_SIZE).toDouble()); curve->setPointType(ptype++ % KSTPOINT_MAXTYPE); curve->writeLock(); curve->registerChange(); curve->unlock(); Q_ASSERT(plotList[i_plot]); PlotRenderItem *renderItem = plotList[i_plot]->renderItem(PlotRenderItem::Cartesian); renderItem->addRelation(kst_cast(curve)); // increment i_plot, as appropriate; if (_pagePlot->curvePlacement() != DataWizardPagePlot::OnePlot) { ++i_plot; if (_pagePlot->curvePlacement()==DataWizardPagePlot::CyclePlotCount) { if (i_plot == _pagePlot->plotCount()) { i_plot = 0; } } else if (i_plot == plotList.count()) { i_plot = 0; } } } } if (_pagePlot->curvePlacement() == DataWizardPagePlot::OnePlot) { // if we are one plot, now we can move to the psd plot if (++i_plot == plotList.count()) { i_plot = 0; } } else if (_pageDataPresentation->plotDataPSD()) { i_plot = plotList.count()/2; } // create the PSDs if (_pageDataPresentation->plotPSD()) { int indexColor = 0; ptype = 0; PSDPtr powerspectrum; int n_psd=0; for (DataVectorList::Iterator it = vectors.begin(); it != vectors.end(); ++it) { if ((*it)->length() > 0) { Q_ASSERT(_document && _document->objectStore()); powerspectrum = _document->objectStore()->createObject(); n_psd++; Q_ASSERT(powerspectrum); powerspectrum->writeLock(); powerspectrum->change(*it, _pageDataPresentation->getFFTOptions()->sampleRate(), _pageDataPresentation->getFFTOptions()->interleavedAverage(), _pageDataPresentation->getFFTOptions()->FFTLength(), _pageDataPresentation->getFFTOptions()->apodize(), _pageDataPresentation->getFFTOptions()->removeMean(), _pageDataPresentation->getFFTOptions()->vectorUnits(), _pageDataPresentation->getFFTOptions()->rateUnits(), _pageDataPresentation->getFFTOptions()->apodizeFunction(), _pageDataPresentation->getFFTOptions()->sigma(), _pageDataPresentation->getFFTOptions()->output()); powerspectrum->registerChange(); powerspectrum->unlock(); CurvePtr curve = _document->objectStore()->createObject(); Q_ASSERT(curve); curve->setXVector(powerspectrum->vX()); curve->setYVector(powerspectrum->vY()); curve->setHasPoints(_pagePlot->drawLinesAndPoints() || _pagePlot->drawPoints()); curve->setHasLines(_pagePlot->drawLinesAndPoints() || _pagePlot->drawLines()); curve->setLineWidth(dialogDefaults().value("curves/lineWidth",0).toInt()); curve->setPointSize(dialogDefaults().value("curves/pointSize",CURVE_DEFAULT_POINT_SIZE).toDouble()); curve->setPointType(ptype++ % KSTPOINT_MAXTYPE); if (!_pageDataPresentation->plotDataPSD() || colors.count() <= indexColor) { color = ColorSequence::self().next(); } else { color = colors[indexColor]; indexColor++; } curve->setColor(color); curve->writeLock(); curve->registerChange(); curve->unlock(); Q_ASSERT(plotList[i_plot]); PlotRenderItem *renderItem = plotList[i_plot]->renderItem(PlotRenderItem::Cartesian); plotList[i_plot]->xAxis()->setAxisLog(_pagePlot->PSDLogX()); plotList[i_plot]->yAxis()->setAxisLog(_pagePlot->PSDLogY()); renderItem->addRelation(kst_cast(curve)); if (_pagePlot->curvePlacement() != DataWizardPagePlot::OnePlot) { // change plots if we are not onePlot if (++i_plot == plotList.count()) { if (_pageDataPresentation->plotDataPSD()) { // if xy and psd i_plot = plotList.count()/2; } else { i_plot = 0;; } } } } } if (n_psd>0) { _pageDataPresentation->getFFTOptions()->setWidgetDefaults(); } } if (relayout && !plotList.isEmpty()) { if (plotsInPage==0 || _pagePlot->rescaleFonts()) { int np = plotList.count(); int n_add = np; bool two_pages = (plotList.at(np-1)->view() != plotList.at(0)->view()); if (two_pages) { n_add/=2; } if (np > 0) { // don't crash if there are no plots plotList.at(0)->view()->resetPlotFontSizes(plotList.mid(0, n_add)); // set font sizes on first page. if (two_pages) { // and second, if there is one. plotList.at(np-1)->view()->resetPlotFontSizes(plotList.mid(n_add, n_add)); } } } foreach (PlotItem* plot, plotList) { plot->view()->configurePlotFontDefaults(plot); // copy plots already in window } CurvePlacement::Layout layout_type = _pagePlot->layout(); int num_columns = _pagePlot->gridColumns(); if (plotsInPage == 0) { // no format to protext if (layout_type != CurvePlacement::Custom) { layout_type = CurvePlacement::Custom; if (separate_tabs) { // if (_pagePlot->plotTabPlacement() == DataWizardPagePlot::SeparateTabs) { num_columns = sqrt((double)plotList.size()/2); } else { num_columns = sqrt((double)plotList.size()); } } } foreach (PlotItem* plot, plotList) { if (xAxisIsTime) { plot->xAxis()->setAxisInterpret(true); // For ASCII, we can get the time/date format string from the datasource config DataSourcePtr ds = _pageDataSource->dataSource(); if (ds->typeString() == "ASCII file") { if (!ds->timeFormat().isEmpty()) { // Only set it when we use a specific ASCII format plot->xAxis()->setAxisDisplayFormatString(ds->timeFormat()); plot->xAxis()->setAxisDisplay(AXIS_DISPLAY_QTDATETIME_FORMAT); } } } plot->update(); plot->view()->appendToLayout(layout_type, plot, num_columns); } if (!plotList.isEmpty() && layout_type == CurvePlacement::Custom) { plotList.at(0)->createCustomLayout(num_columns); if (_pageDataPresentation->plotDataPSD()) { plotList.at(plotList.count()/2)->createCustomLayout(num_columns); } } } foreach (PlotItem* plot, plotList) { if (_pagePlot->legendsOn()) { plot->setShowLegend(true, true); plot->legend()->setVerticalDisplay(_pagePlot->legendsVertical()); } else if (_pagePlot->legendsAuto()) { if (plot->renderItem(PlotRenderItem::Cartesian)->relationList().count() > 1) { plot->setShowLegend(true, true); plot->legend()->setVerticalDisplay(_pagePlot->legendsVertical()); } } else { plot->setShowLegend(false,false); } } if (_pagePlot->shareAxis()) { //FIXME: apply shared axis // also delete the line _shareAxis->hide(); } } UpdateManager::self()->doUpdates(true); kstApp->mainWindow()->document()->setChanged(true); QApplication::restoreOverrideCursor(); accept(); UpdateServer::self()->requestUpdateSignal(); _pageDataSource->setTypeActivated(); ds->vector().readingDone(); } } // vim: ts=2 sw=2 et diff --git a/src/libkstapp/mainwindow.cpp b/src/libkstapp/mainwindow.cpp index 0f57aae6..645a6a5e 100644 --- a/src/libkstapp/mainwindow.cpp +++ b/src/libkstapp/mainwindow.cpp @@ -1,2446 +1,2447 @@ /*************************************************************************** * * * 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 "mainwindow.h" #include "boxitem.h" #include "datamanager.h" #include "debugdialog.h" #include "debugnotifier.h" #include "document.h" #include "ellipseitem.h" #include "exportgraphicsdialog.h" #include "exportvectorsdialog.h" #include "logdialog.h" #include "application.h" #include "debug.h" #include "labelitem.h" #include "lineitem.h" #include "circleitem.h" #include "arrowitem.h" #include "memorywidget.h" #include "objectstore.h" #include "pictureitem.h" #include "plotitem.h" #include "plotitemmanager.h" #include "svgitem.h" #include "tabwidget.h" #include "sharedaxisboxitem.h" #include "ui_aboutdialog.h" #include "viewvectordialog.h" #include "viewmatrixdialog.h" #include "viewprimitivedialog.h" #include "view.h" #include "applicationsettings.h" #include "updatemanager.h" #include "datasourcepluginmanager.h" #include "pluginmenuitemaction.h" #include "applicationsettingsdialog.h" #include "themedialog.h" #include "differentiatecurvesdialog.h" #include "filtermultipledialog.h" #include "choosecolordialog.h" #include "changedatasampledialog.h" #include "changefiledialog.h" #include "bugreportwizard.h" #include "datawizard.h" #include "aboutdialog.h" #include "datavector.h" #include "commandlineparser.h" #include "dialogdefaults.h" #include "settings.h" #include "dialoglauncher.h" #include "scriptserver.h" #include "geticon.h" #ifndef KST_NO_SVG #include #endif #include #ifndef KST_NO_PRINTER #include #endif #include #include #include #include #include #include #include #include #include namespace Kst { MainWindow::MainWindow() : _settings(createSettings("application")), _dataManager(0), _exportGraphics(0), _exportVectors(0), _logDialog(0), _differentiateCurvesDialog(0), _filterMultipleDialog(0), _chooseColorDialog(0), _changeDataSampleDialog(0), _changeFileDialog(0), _bugReportWizard(0), _applicationSettingsDialog(0), _themeDialog(0), _aboutDialog(0), _viewVectorDialog(0), _highlightPoint(false), _statusBarTimeout(0), #if defined(__QNX__) qnxToolbarsVisible(true), #endif _ae_width(1280), _ae_height(1024), _ae_display(2), _ae_export_all(false), _ae_autosave_period(0), _ae_Timer(0) { _doc = new Document(this); _scriptServer = new ScriptServer(_doc->objectStore()); _videoMapper = new QSignalMapper(this); _tabWidget = new TabWidget(this); _undoGroup = new QUndoGroup(this); _debugDialog = new DebugDialog(this); Debug::self()->setHandler(_debugDialog); setWindowTitle("Kst"); createActions(); createMenus(); createToolBars(); createStatusBar(); _tabWidget->createView(); setCentralWidget(_tabWidget); _tabWidget->setAcceptDrops(false); // Force drops to be passed to parent connect(_tabWidget, SIGNAL(currentChanged(int)), this, SLOT(currentViewChanged())); connect(_tabWidget, SIGNAL(currentViewModeChanged()), this, SLOT(currentViewModeChanged())); connect(PlotItemManager::self(), SIGNAL(tiedZoomRemoved()), this, SLOT(tiedZoomRemoved())); connect(PlotItemManager::self(), SIGNAL(allPlotsTiedZoom()), this, SLOT(allPlotsTiedZoom())); readSettings(); connect(UpdateManager::self(), SIGNAL(objectsUpdated(qint64)), this, SLOT(updateViewItems(qint64))); QTimer::singleShot(0, this, SLOT(performHeavyStartupActions())); updateRecentKstFiles(); setAcceptDrops(true); #if defined(__QNX__) // We want to be able to intercept bezel gestures, which show up in Qt as menu button keyPressEvents. qApp->installEventFilter(this); qnxToggleToolbarVisibility(); #endif } MainWindow::~MainWindow() { delete _dataManager; _dataManager = 0; delete _doc; _doc = 0; delete _viewVectorDialog; _viewVectorDialog = 0; delete _scriptServer; _scriptServer = 0; } void MainWindow::performHeavyStartupActions() { // Set the timer for the UpdateManager. UpdateManager::self()->setMinimumUpdatePeriod(ApplicationSettings::self()->minimumUpdatePeriod()); DataObject::init(); DataSourcePluginManager::init(); } void MainWindow::cleanup() { if (document() && document()->objectStore()) { document()->objectStore()->clear(); } } void MainWindow::setLayoutMode(bool layoutMode) { foreach (View *v, tabWidget()->views() ) { Q_ASSERT(v); if (layoutMode) { v->setViewMode(View::Layout); _highlightPointAct->setEnabled(false); _tiedZoomAct->setEnabled(false); } else { v->setViewMode(View::Data); _highlightPointAct->setEnabled(true); _tiedZoomAct->setEnabled(true); } } } void MainWindow::setHighlightPoint(bool highlight) { _highlightPoint = highlight; } void MainWindow::changeZoomOnlyMode(QAction* act) { if (act == _layoutModeAct && act->isChecked()) { setLayoutMode(true); } else { setLayoutMode(false); } foreach (View *view, tabWidget()->views() ) { view->setZoomOnly((View::ZoomOnlyMode)act->data().toInt()); } } void MainWindow::toggleTiedZoom() { if (isTiedTabs()) { PlotItemManager::self()->toggleAllTiedZoom(0); /* QList views = tabWidget()->views(); foreach (View* view, views) { PlotItemManager::self()->toggleAllTiedZoom(view); } */ } else { PlotItemManager::self()->toggleAllTiedZoom(tabWidget()->currentView()); } } void MainWindow::tiedZoomRemoved() { _tiedZoomAct->setChecked(false); } void MainWindow::allPlotsTiedZoom() { _tiedZoomAct->setChecked(true); } bool MainWindow::promptSaveDone() { if (! _doc->isChanged()) { return true; // No need to ask if there is no unsaved change -> we're done } else { // Changes registered: ask the user int rc = QMessageBox::warning(this, tr("Kst: Save Prompt"), tr("Your document has been modified.\nSave changes?"), QMessageBox::Save | QMessageBox::Discard | QMessageBox::Cancel, QMessageBox::Save); if (rc == QMessageBox::Save) { save(); } else if (rc == QMessageBox::Cancel) { return false; } return true; } } void MainWindow::closeEvent(QCloseEvent *e) { if (!promptSaveDone()) { e->ignore(); return; } //cleanup(); QMainWindow::closeEvent(e); kstApp->closeAllWindows(); } Document *MainWindow::document() const { return _doc; } QUndoGroup *MainWindow::undoGroup() const { return _undoGroup; } TabWidget *MainWindow::tabWidget() const { return _tabWidget; } void MainWindow::save() { if (_doc->isOpen()) { _doc->save(); } else { saveAs(); } } void MainWindow::saveAs() { QString fn = QFileDialog::getSaveFileName(this, tr("Kst: Save File"), _doc->fileName(), tr("Kst Sessions (*.kst)")); if (fn.isEmpty()) { return; } QString restorePath = QDir::currentPath(); QString kstfiledir = fn.left(fn.lastIndexOf('/')) + '/'; QDir::setCurrent(kstfiledir); //QString currentP = QDir::currentPath(); _doc->save(fn); QDir::setCurrent(restorePath); setWindowTitle("Kst - " + fn); updateRecentKstFiles(fn); } void MainWindow::newDoc(bool force) { bool clearApproved = false; if (force) { clearApproved = true; } else { clearApproved = promptSaveDone(); } if (clearApproved) { cleanup(); delete _dataManager; _dataManager = 0; delete _doc; resetNameIndexes(); _doc = new Document(this); _scriptServer->setStore(_doc->objectStore()); tabWidget()->clear(); tabWidget()->createView(); return; } else { return; } } void MainWindow::open() { if (!promptSaveDone()) { return; } const QString key = "lastOpenedKstFile"; QString fn = _settings.value(key).toString(); if (fn.isEmpty()) { fn = _doc->fileName(); } fn = QFileDialog::getOpenFileName(this, tr("Kst: Open File"), fn, tr("Kst Sessions (*.kst)")); if (fn.isEmpty()) { return; } _settings.setValue(key, fn); openFile(fn); } QAction* MainWindow::createRecentFileAction(const QString& filename, int idx, const QString& name, const char* openslot) { QAction* action = new QAction(this); QString text = tr("&%1 %2", "Part of a list. %1 is an index. %2 is a file name").arg(idx).arg(name); action->setText(text); action->setData(filename); action->setStatusTip(filename); action->setVisible(true); connect(action, SIGNAL(triggered()), this, openslot); return action; } void MainWindow::updateRecentKstFiles(const QString& filename) { updateRecentFiles("recentKstFileList", _fileMenu, _bottomRecentKstActions, _recentKstFilesMenu, filename, SLOT(openRecentKstFile())); } void MainWindow::updateRecentDataFiles(const QString& filename) { updateRecentFiles("recentDataFileList", _toolsMenu, _bottomRecentDataActions, _recentDataFilesMenu, filename, SLOT(openRecentDataFile())); if (!filename.isEmpty()) { dialogDefaults().setValue("vector/datasource", filename); } } QStringList MainWindow::recentDataFiles() { QStringList recentFiles = _settings.value("recentDataFileList").toStringList(); if (recentFiles.removeDuplicates() > 0) { _settings.setValue("recentDataFileList", recentFiles); } return recentFiles; } void MainWindow::cleanupRecentDataFilesList() { QStringList recentFiles = _settings.value("recentDataFileList").toStringList(); recentFiles.removeDuplicates(); foreach(const QString& it, recentFiles) { if (!QFileInfo(it).exists()) { recentFiles.removeOne(it); } } _settings.setValue("recentDataFileList", recentFiles); updateRecentKstFiles(); updateRecentDataFiles(); } void MainWindow::updateRecentFiles(const QString& key ,QMenu* menu, QList& actions, QMenu* submenu, const QString& newfilename, const char* openslot) { // Always add absolute paths to the recent file lists, otherwise they are not very reusable QString absoluteFilePath = DataSource::cleanPath(newfilename); if (!newfilename.isEmpty() && !QDir::isAbsolutePath(newfilename)) { // If it's not empty and not absolute either, add the dir absoluteFilePath = DataSource::cleanPath(QDir::currentPath() + '/' + newfilename); } foreach(QAction* it, actions) { menu->removeAction(it); delete it; } actions.clear(); QStringList recentFiles = _settings.value(key).toStringList(); if (recentFiles.removeDuplicates() > 0) { _settings.setValue(key, recentFiles); } if (!absoluteFilePath.isEmpty()) { recentFiles.removeOne(absoluteFilePath); recentFiles.push_front(absoluteFilePath); recentFiles = recentFiles.mid(0, 30); _settings.setValue(key, recentFiles); } submenu->clear(); QAction* check = new QAction(this); check->setText(tr("&Cleanup Non-Existent Files")); check->setData(key); check->setVisible(true); connect(check, SIGNAL(triggered()), this, SLOT(checkRecentFilesOnExistence())); submenu->addAction(check); submenu->addSeparator(); int i = 0; foreach(const QString& it, recentFiles) { i++; if (i <= 5) { // don't make file menu too wide, show complete path in statusbar QAction* action = createRecentFileAction(it, i, QFileInfo(it).fileName(), openslot); actions << action; menu->addAction(action); } submenu->addAction(createRecentFileAction(it, i, it, openslot)); } } void MainWindow::openRecentKstFile() { QAction *action = qobject_cast(sender()); if (action) { openFile(action->data().toString()); } } void MainWindow::checkRecentFilesOnExistence() { QAction *action = qobject_cast(sender()); if (action) { QStringList recentFiles = _settings.value(action->data().toString()).toStringList(); recentFiles.removeDuplicates(); foreach(const QString& it, recentFiles) { if (!QFileInfo(it).exists()) { recentFiles.removeOne(it); } } _settings.setValue(action->data().toString(), recentFiles); updateRecentKstFiles(); updateRecentDataFiles(); } } void MainWindow::autoExportImage() { exportGraphicsFile(_ae_filename, _ae_format, _ae_width, _ae_height, _ae_display, _ae_export_all, _ae_autosave_period); } bool MainWindow::initFromCommandLine() { delete _doc; _doc = new Document(this); _scriptServer->setStore(_doc->objectStore()); CommandLineParser P(_doc, this); bool ok = _doc->initFromCommandLine(&P); if (!P.pngFile().isEmpty()) { int w = 1280; int h = 1024; if (P.pngWidth()>1) { w = P.pngWidth(); } if (P.pngHeight()>1) { h = P.pngHeight(); } exportGraphicsFile(P.pngFile(), "png", w, h, 2, true, 0); ok = false; } if (!P.printFile().isEmpty()) { #ifndef KST_NO_PRINTER printFromCommandLine(P.printFile()); #endif ok = false; } if (!P.kstFileName().isEmpty()) { setWindowTitle("Kst - " + P.kstFileName()); } _doc->setChanged(false); return ok; } void MainWindow::openFile(const QString &file) { QApplication::setOverrideCursor(QCursor(Qt::WaitCursor)); + cleanup(); newDoc(true); // Does all the init stuff, but does not ask for override as it's supposed to be done elsewhere bool ok = _doc->open(file); updateProgress(100, ""); QApplication::restoreOverrideCursor(); if (!ok) { QString lastError = _doc->lastError(); if (lastError.isEmpty()) lastError = tr("For details see Help->Debug Dialog->Log."); QMessageBox::critical(this, tr("Kst"),tr("Error opening document:\n '%1'\n%2\n").arg(file, lastError)); } setWindowTitle("Kst - " + file); updateRecentKstFiles(file); } void MainWindow::exportGraphicsFile(const QString &filename, const QString &format, int width, int height, int display, bool export_all, int autosave_period) { int viewCount = 0; int n_views = _tabWidget->views().size(); int i_startview, i_endview; _ae_filename = filename; _ae_format = format; _ae_width = width; _ae_height = height; _ae_display = display; _ae_export_all = export_all; _ae_autosave_period = autosave_period; dialogDefaults().setValue("export/filename", filename); dialogDefaults().setValue("export/format", format); dialogDefaults().setValue("export/xsize", width); dialogDefaults().setValue("export/ysize", height); dialogDefaults().setValue("export/sizeOption", display); if (export_all) { i_startview = 0; i_endview = n_views-1; } else { i_startview = i_endview = _tabWidget->currentIndex(); } for (int i_view = i_startview; i_view<=i_endview; i_view++) { View *view = _tabWidget->views().at(i_view); QSize size; if (display == 0) { // Width set by user, maintain aspect ratio QSize sizeWindow(view->geometry().size()); size.setWidth(width); size.setHeight((int)((qreal)width * (qreal)sizeWindow.height() / (qreal)sizeWindow.width())); } else if (display == 1) { // Height set by user, maintain aspect ratio QSize sizeWindow(view->geometry().size()); size.setHeight(height); size.setWidth((int)((qreal)height * (qreal)sizeWindow.width() / (qreal)sizeWindow.height())); } else if (display == 2) { // Width and height set by user size.setWidth(width); size.setHeight(height); } else { //if (display == 3) { // Square (width x width) size.setWidth(width); size.setHeight(width); } QString file = filename; if (i_startview - i_endview != 0) { QFileInfo QFI(filename); file = QFI.dir().path() + '/' + QFI.completeBaseName() + '_' + _tabWidget->tabBar()->tabText(viewCount).replace(QString("&"),QString()) + '.' + QFI.suffix(); } if (format == QString("svg")) { #ifndef KST_NO_SVG QPainter painter; QSvgGenerator generator; QSize currentSize(view->size()); view->resize(size); view->processResize(size); view->setPrinting(true); generator.setFileName(file); generator.setResolution(300); generator.setSize(view->size()); generator.setViewBox(view->rect()); painter.begin(&generator); view->render(&painter); painter.end(); view->setPrinting(false); view->resize(currentSize); view->processResize(currentSize); #endif } else if (format == QString("eps")) { #ifndef KST_NO_PRINTER QPrinter printer(QPrinter::ScreenResolution); #ifdef QT5 printer.setOutputFormat(QPrinter::PdfFormat); #else printer.setOutputFormat(QPrinter::PostScriptFormat); #endif printer.setOutputFileName(file); printer.setOrientation(QPrinter::Portrait); printer.setPrintRange(QPrinter::PageRange); printer.setFromTo(i_view+1, i_view+1); printer.setPaperSize(size, QPrinter::DevicePixel); printToPrinter(&printer); } else if (format == QString("pdf")) { QPrinter printer(QPrinter::ScreenResolution); printer.setOutputFormat(QPrinter::PdfFormat); printer.setOutputFileName(file); //setPrinterDefaults(&printer); printer.setOrientation(QPrinter::Portrait); printer.setPrintRange(QPrinter::PageRange); printer.setFromTo(i_view+1, i_view+1); printer.setPaperSize(size, QPrinter::DevicePixel); printToPrinter(&printer); #endif } else { QPainter painter; QImage image(size, QImage::Format_ARGB32); painter.begin(&image); QSize currentSize(view->size()); view->resize(size); view->processResize(size); view->setPrinting(true); view->render(&painter); view->setPrinting(false); view->resize(currentSize); view->processResize(currentSize); painter.end(); QImageWriter imageWriter(file, format.toLatin1()); imageWriter.write(image); } viewCount++; } if (_ae_autosave_period > 0) { if (_ae_Timer == 0) { // create timer (only once) _ae_Timer = new QTimer(this); _ae_Timer->setSingleShot(true); connect(_ae_Timer, SIGNAL(timeout()), this, SLOT(autoExportImage())); } _ae_Timer->start(_ae_autosave_period); // one shot timer... } } void MainWindow::exportLog(const QString &imagename, QString &msgfilename, const QString &format, int x_size, int y_size, int size_option_index, const QString &message) { View *view = _tabWidget->currentView(); QSize size; if (size_option_index == 0) { size.setWidth(x_size); size.setHeight(y_size); } else if (size_option_index == 1) { size.setWidth(x_size); size.setHeight(y_size); } else if (size_option_index == 2) { QSize sizeWindow(view->geometry().size()); size.setWidth(x_size); size.setHeight((int)((qreal)x_size * (qreal)sizeWindow.height() / (qreal)sizeWindow.width())); } else { QSize sizeWindow(view->geometry().size()); size.setHeight(y_size); size.setWidth((int)((qreal)y_size * (qreal)sizeWindow.width() / (qreal)sizeWindow.height())); } QImage image(size, QImage::Format_ARGB32); QPainter painter(&image); QSize currentSize(view->size()); view->resize(size); view->processResize(size); view->setPrinting(true); view->render(&painter); view->setPrinting(false); view->resize(currentSize); view->processResize(currentSize); QImageWriter imageWriter(imagename, format.toLatin1()); imageWriter.write(image); QFile file(msgfilename); if (file.open(QIODevice::WriteOnly | QIODevice::Text)) { QTextStream out(&file); out << message; file.close(); } } #ifndef KST_NO_PRINTER void MainWindow::printToPrinter(QPrinter *printer) { QPainter painter(printer); QList pages; switch (printer->printRange()) { case QPrinter::PageRange: if (printer->fromPage()>0) { for (int i_page = printer->fromPage(); i_page<=printer->toPage(); i_page++) { pages.append(_tabWidget->views().at(i_page-1)); } } break; case QPrinter::AllPages: foreach (View *view, _tabWidget->views()) { pages.append(view); } break; case QPrinter::Selection: default: pages.append(_tabWidget->currentView()); break; } QSize printerPageSize = printer->pageRect().size(); for (int i = 0; i < printer->numCopies(); ++i) { for (int i_page = 0; i_pagesize()); view->resize(printerPageSize); view->processResize(printerPageSize); view->setPrinting(true); view->render(&painter); view->setPrinting(false); view->resize(currentSize); view->processResize(currentSize); if (i_pagenewPage(); } } } void MainWindow::printFromCommandLine(const QString &printFileName) { QPrinter printer(QPrinter::ScreenResolution); printer.setResolution(300); printer.setOutputFileName(printFileName); setPrinterDefaults(&printer); printer.setPrintRange(QPrinter::AllPages); printToPrinter(&printer); } void MainWindow::setPrinterDefaults(QPrinter *printer) { if (dialogDefaults().value("print/landscape",true).toBool()) { printer->setOrientation(QPrinter::Landscape); } else { printer->setOrientation(QPrinter::Portrait); } printer->setPaperSize(QPrinter::PaperSize(dialogDefaults().value("print/paperSize", QPrinter::Letter).toInt())); QPointF topLeft =dialogDefaults().value("print/topLeftMargin", QPointF(15.0,15.0)).toPointF(); QPointF bottomRight =dialogDefaults().value("print/bottomRightMargin", QPointF(15.0,15.0)).toPointF(); printer->setPageMargins(topLeft.x(), topLeft.y(), bottomRight.x(), bottomRight.y(), QPrinter::Millimeter); // Apparent Qt bug: setting the page margins here doesn't set the correspoding values in the print // dialog->printer-options sub-dialog under linux. If you don't open the printer-options sub-dialog, // the values here are honored. } void MainWindow::savePrinterDefaults(QPrinter *printer) { dialogDefaults().setValue("print/landscape", printer->orientation() == QPrinter::Landscape); dialogDefaults().setValue("print/paperSize", int(printer->paperSize())); qreal left, top, right, bottom; printer->getPageMargins(&left, &top, &right, &bottom, QPrinter::Millimeter); dialogDefaults().setValue("print/topLeftMargin", QPointF(left, top)); dialogDefaults().setValue("print/bottomRightMargin", QPointF(right, bottom)); } void MainWindow::print() { QPrinter printer(QPrinter::ScreenResolution); printer.setResolution(300); setPrinterDefaults(&printer); #ifndef Q_OS_WIN // QPrintDialog: Cannot be used on non-native printers printer.setOutputFileName(dialogDefaults().value("print/path", "./print.pdf").toString()); #endif QPointer pd = new QPrintDialog(&printer, this); #if QT_VERSION >= 0x040500 pd->setOption(QPrintDialog::PrintToFile); pd->setOption(QPrintDialog::PrintPageRange, true); pd->setOption(QAbstractPrintDialog::PrintShowPageSize,true); #endif if (pd->exec() == QDialog::Accepted) { QApplication::setOverrideCursor(QCursor(Qt::WaitCursor)); printToPrinter(&printer); QApplication::restoreOverrideCursor(); savePrinterDefaults(&printer); } dialogDefaults().setValue("print/path", printer.outputFileName()); delete pd; } #endif void MainWindow::currentViewChanged() { if(!_tabWidget->currentView()) return; _undoGroup->setActiveStack(_tabWidget->currentView()->undoStack()); currentViewModeChanged(); } void MainWindow::currentViewModeChanged() { if(!_tabWidget->currentView()) return; _layoutModeAct->setChecked(_tabWidget->currentView()->viewMode() == View::Layout); } void MainWindow::aboutToQuit() { writeSettings(); } void MainWindow::about() { if (!_aboutDialog) { _aboutDialog = new AboutDialog(this); } if (_aboutDialog->isVisible()) { _aboutDialog->raise(); _aboutDialog->activateWindow(); } _aboutDialog->show(); } void MainWindow::clearDrawingMarker() { _createBoxAct->setChecked(false); _createSharedAxisBoxAct->setChecked(false); _createCircleAct->setChecked(false); _createEllipseAct->setChecked(false); _createLabelAct->setChecked(false); _createLineAct->setChecked(false); _createArrowAct->setChecked(false); _createPictureAct->setChecked(false); _createPlotAct->setChecked(false); #ifndef KST_NO_SVG _createSvgAct->setChecked(false); #endif _tabWidget->currentView()->setMouseMode(View::Default); } void MainWindow::createBox() { if (_createBoxAct->isChecked()) { clearDrawingMarker(); _createBoxAct->setChecked(true); CreateBoxCommand *cmd = new CreateBoxCommand; cmd->createItem(); } else { _tabWidget->currentView()->setMouseMode(View::Default); } } void MainWindow::createSharedAxisBox() { if (_createSharedAxisBoxAct->isChecked()) { clearDrawingMarker(); _createSharedAxisBoxAct->setChecked(true); CreateSharedAxisBoxCommand *cmd = new CreateSharedAxisBoxCommand; cmd->createItem(); } else { _tabWidget->currentView()->setMouseMode(View::Default); } } void MainWindow::createVector() { QString tmp; DialogLauncher::self()->showVectorDialog(tmp); } void MainWindow::createMatrix() { QString tmp; DialogLauncher::self()->showMatrixDialog(tmp); } void MainWindow::createScalar() { QString scalarName; DialogLauncher::self()->showScalarDialog(scalarName); } void MainWindow::createString() { QString stringName; DialogLauncher::self()->showStringDialog(stringName); } void MainWindow::createCircle() { if (_createCircleAct->isChecked()) { clearDrawingMarker(); _createCircleAct->setChecked(true); CreateCircleCommand *cmd = new CreateCircleCommand; cmd->createItem(); } else { _tabWidget->currentView()->setMouseMode(View::Default); } } void MainWindow::createEllipse() { if (_createEllipseAct->isChecked()) { clearDrawingMarker(); _createEllipseAct->setChecked(true); CreateEllipseCommand *cmd = new CreateEllipseCommand; cmd->createItem(); } else { _tabWidget->currentView()->setMouseMode(View::Default); } } void MainWindow::createLabel() { if (_createLabelAct->isChecked()) { clearDrawingMarker(); _createLabelAct->setChecked(true); CreateLabelCommand *cmd = new CreateLabelCommand; cmd->createItem(); } else { _tabWidget->currentView()->setMouseMode(View::Default); } } void MainWindow::createLine() { if (_createLineAct->isChecked()) { clearDrawingMarker(); _createLineAct->setChecked(true); CreateLineCommand *cmd = new CreateLineCommand; cmd->createItem(); } else { _tabWidget->currentView()->setMouseMode(View::Default); } } void MainWindow::createArrow() { if (_createArrowAct->isChecked()) { clearDrawingMarker(); _createArrowAct->setChecked(true); CreateArrowCommand *cmd = new CreateArrowCommand; cmd->createItem(); } else { _tabWidget->currentView()->setMouseMode(View::Default); } } void MainWindow::createPicture() { if (_createPictureAct->isChecked()) { clearDrawingMarker(); _createPictureAct->setChecked(true); CreatePictureCommand *cmd = new CreatePictureCommand; cmd->createItem(); } else { _tabWidget->currentView()->setMouseMode(View::Default); } } void MainWindow::createPlot() { if (_createPlotAct->isChecked()) { clearDrawingMarker(); _createPlotAct->setChecked(true); CreatePlotCommand *cmd = new CreatePlotCommand; cmd->createItem(); } else { _tabWidget->currentView()->setMouseMode(View::Default); } } void MainWindow::insertPlot() { CreatePlotForCurve *cmd = new CreatePlotForCurve(); cmd->createItem(); PlotItem *plotItem = static_cast(cmd->item()); plotItem->view()->resetPlotFontSizes(plotItem); plotItem->view()->configurePlotFontDefaults(plotItem); // copy plots already in window plotItem->view()->appendToLayout(CurvePlacement::Auto, plotItem, 0); } #ifndef KST_NO_SVG void MainWindow::createSvg() { if (_createSvgAct->isChecked()) { clearDrawingMarker(); _createSvgAct->setChecked(true); CreateSvgCommand *cmd = new CreateSvgCommand; cmd->createItem(); } else { _tabWidget->currentView()->setMouseMode(View::Default); } } #endif void MainWindow::createCurve() { DialogLauncher::self()->showCurveDialog(); } void MainWindow::createPSD() { DialogLauncher::self()->showPowerSpectrumDialog(); } void MainWindow::createEquation() { DialogLauncher::self()->showEquationDialog(); } void MainWindow::createHistogram() { DialogLauncher::self()->showHistogramDialog(); } void MainWindow::createImage() { DialogLauncher::self()->showImageDialog(); } void MainWindow::createSpectogram() { DialogLauncher::self()->showCSDDialog(); } void MainWindow::createEventMonitor() { DialogLauncher::self()->showEventMonitorDialog(); } void MainWindow::createActions() { // ***************************** File actions ******************************** // _openAct = new QAction(tr("&Open..."), this); _openAct->setStatusTip(tr("Open a new session")); _openAct->setShortcuts(QKeySequence::Open); _openAct->setIcon(KstGetIcon("document-open")); connect(_openAct, SIGNAL(triggered()), this, SLOT(open())); _saveAct = new QAction(tr("&Save"), this); _saveAct->setStatusTip(tr("Save the current session")); _saveAct->setShortcuts(QKeySequence::Save); _saveAct->setIcon(KstGetIcon("document-save")); connect(_saveAct, SIGNAL(triggered()), this, SLOT(save())); _saveAsAct = new QAction(tr("Save &as..."), this); _saveAsAct->setStatusTip(tr("Save the current session")); _saveAsAct->setIcon(KstGetIcon("document-save-as")); _saveAsAct->setShortcuts(QKeySequence::SaveAs); connect(_saveAsAct, SIGNAL(triggered()), this, SLOT(saveAs())); _closeAct = new QAction(tr("Ne&w Session"), this); _closeAct->setStatusTip(tr("Close current session and start a new, empty one")); _closeAct->setIcon(KstGetIcon("document-close")); _closeAct->setShortcuts(QKeySequence::Close); connect(_closeAct, SIGNAL(triggered()), this, SLOT(newDoc())); _reloadAct = new QAction(tr("Reload All &Data Sources"), this); _reloadAct->setStatusTip(tr("Reload all data sources")); _reloadAct->setIcon(KstGetIcon("kst_reload")); connect(_reloadAct, SIGNAL(triggered()), this, SLOT(reload())); _printAct = new QAction(tr("&Print..."), this); _printAct->setStatusTip(tr("Print the current view")); _printAct->setIcon(KstGetIcon("document-print")); _printAct->setShortcuts(QKeySequence::Print); connect(_printAct, SIGNAL(triggered()), this, SLOT(print())); #ifdef KST_NO_PRINTER _printAct->setEnabled(false); #endif _exportGraphicsAct = new QAction(tr("&Export as Image(s)..."), this); _exportGraphicsAct->setStatusTip(tr("Export graphics to disk")); _exportGraphicsAct->setIcon(KstGetIcon("insert-image")); connect(_exportGraphicsAct, SIGNAL(triggered()), this, SLOT(showExportGraphicsDialog())); _exportVectorsAct = new QAction(tr("Save &Vectors to Disk..."), this); _exportVectorsAct->setStatusTip(tr("Export vectors to ascii file")); _exportVectorsAct->setIcon(KstGetIcon("save-vectors")); connect(_exportVectorsAct, SIGNAL(triggered()), this, SLOT(showExportVectorsDialog())); _logAct = new QAction(tr("&Log Entry..."), this); _logAct->setStatusTip(tr("Commit a log entry")); _logAct->setIcon(KstGetIcon("new-log-event")); connect(_logAct, SIGNAL(triggered()), this, SLOT(showLogDialog())); _newTabAct = new QAction(tr("&New Tab"), this); _newTabAct->setStatusTip(tr("Create a new tab")); _newTabAct->setIcon(KstGetIcon("tab-new")); connect(_newTabAct, SIGNAL(triggered()), tabWidget(), SLOT(createView())); _closeTabAct = new QAction(tr("&Close Tab"), this); _closeTabAct->setStatusTip(tr("Close the current tab")); _closeTabAct->setIcon(KstGetIcon("tab-close")); connect(_closeTabAct, SIGNAL(triggered()), tabWidget(), SLOT(closeCurrentView())); _exitAct = new QAction(tr("E&xit"), this); _exitAct->setShortcuts(QKeySequence::Quit); _exitAct->setStatusTip(tr("Exit the application")); _exitAct->setIcon(KstGetIcon("application-exit")); connect(_exitAct, SIGNAL(triggered()), this, SLOT(close())); // ************************** Edit Actions ******************************* // _undoAct = _undoGroup->createUndoAction(this); _undoAct->setShortcuts(QKeySequence::Undo); _undoAct->setIcon(KstGetIcon("edit-undo")); _redoAct = _undoGroup->createRedoAction(this); _redoAct->setShortcuts(QKeySequence::Redo); _redoAct->setIcon(KstGetIcon("edit-redo")); // ********************* View Actions ********************************** // _vectorEditorAct = new QAction(tr("&Vectors"), this); _vectorEditorAct->setStatusTip(tr("Show all vectors in a spreadsheet")); connect(_vectorEditorAct, SIGNAL(triggered()), this, SLOT(showVectorEditor())); _scalarEditorAct = new QAction(tr("&Scalars"), this); _scalarEditorAct->setStatusTip(tr("Show all scalars in a spreadsheet")); connect(_scalarEditorAct, SIGNAL(triggered()), this, SLOT(showScalarEditor())); _matrixEditorAct = new QAction(tr("&Matrices"), this); _matrixEditorAct->setStatusTip(tr("Show all matrices in a spreadsheet")); connect(_matrixEditorAct, SIGNAL(triggered()), this, SLOT(showMatrixEditor())); _stringEditorAct = new QAction(tr("S&trings"), this); _stringEditorAct->setStatusTip(tr("Show all strings in a spreadsheet")); connect(_stringEditorAct, SIGNAL(triggered()), this, SLOT(showStringEditor())); // ************************ Data Range 1 click Actions ************************** // _backAct = new QAction(tr("&Back One Screen"), this); _backAct->setStatusTip(tr("Back one screen (Page Up)")); _backAct->setIcon(KstGetIcon("page-previous")); _backAct->setShortcut(Qt::Key_PageUp); connect(_backAct, SIGNAL(triggered()), this, SLOT(back())); _forwardAct = new QAction(tr("&Forward One Screen"), this); _forwardAct->setStatusTip(tr("Forward one screen (Page Down)")); _forwardAct->setIcon(KstGetIcon("page-next")); _forwardAct->setShortcut(Qt::Key_PageDown); connect(_forwardAct, SIGNAL(triggered()), this, SLOT(forward())); _readFromEndAct = new QAction(tr("&Count from End"), this); _readFromEndAct->setStatusTip(tr("Count from end mode (End)")); _readFromEndAct->setIcon(KstGetIcon("count-from-end")); _readFromEndAct->setShortcut(Qt::Key_End); connect(_readFromEndAct, SIGNAL(triggered()), this, SLOT(readFromEnd())); _readToEndAct = new QAction(tr("&Read to End"), this); _readToEndAct->setStatusTip(tr("Read to end mode")); _readToEndAct->setIcon(KstGetIcon("read-to-end")); _readToEndAct->setShortcut(Qt::ShiftModifier+Qt::Key_End); connect(_readToEndAct, SIGNAL(triggered()), this, SLOT(readToEnd())); _pauseAct = new QAction(tr("&Pause"), this); _pauseAct->setIcon(KstGetIcon("pause")); _pauseAct->setCheckable(true); _pauseAct->setShortcut(tr("p", "shortcut for pause")); _pauseAct->setStatusTip(tr("Toggle pause updates of data sources (%1)").arg(_pauseAct->shortcut().toString())); connect(_pauseAct, SIGNAL(toggled(bool)), this, SLOT(pause(bool))); _changeDataSampleDialogAct = new QAction(tr("Change Data &Sample Range..."), this); _changeDataSampleDialogAct->setStatusTip(tr("Show Kst's Change Data Sample Range Dialog")); _changeDataSampleDialogAct->setIcon(KstGetIcon("kst_changenpts")); connect(_changeDataSampleDialogAct, SIGNAL(triggered()), this, SLOT(showChangeDataSampleDialog())); // ************************ Create Actions ************************** // _insertPlotAct = new QAction(tr("&Plot"), this); _insertPlotAct->setIcon(KstGetIcon("kst_newplot")); _insertPlotAct->setShortcut(QString("F11")); _insertPlotAct->setStatusTip(tr("Insert a plot in the current view (%1)").arg(_insertPlotAct->shortcut().toString())); _insertPlotAct->setCheckable(false); connect(_insertPlotAct, SIGNAL(triggered()), this, SLOT(insertPlot())); _createPlotAct = new QAction(tr("&Plot"), this); _createPlotAct->setIcon(KstGetIcon("kst_newplot")); //_createPlotAct->setShortcut(QString("F11")); _createPlotAct->setStatusTip(tr("Create a plot for the current view")); _createPlotAct->setCheckable(true); connect(_createPlotAct, SIGNAL(triggered()), this, SLOT(createPlot())); _newScalarAct = new QAction(tr("&Scalar"), this); connect(_newScalarAct, SIGNAL(triggered()), this, SLOT(createScalar())); _newVectorAct = new QAction(tr("&Vector"), this); connect(_newVectorAct, SIGNAL(triggered()), this, SLOT(createVector())); _newMatrixAct = new QAction(tr("&Matrix"), this); connect(_newMatrixAct, SIGNAL(triggered()), this, SLOT(createMatrix())); _newStringAct = new QAction(tr("Strin&g"), this); connect(_newStringAct, SIGNAL(triggered()), this, SLOT(createString())); _newCurveAct = new QAction(tr("&Curve"), this); connect(_newCurveAct, SIGNAL(triggered()), this, SLOT(createCurve())); _newEquationAct = new QAction(tr("&Equation"), this); connect(_newEquationAct, SIGNAL(triggered()), this, SLOT(createEquation())); _newPSDAct = new QAction(tr("Po&wer Spectrum"), this); connect(_newPSDAct, SIGNAL(triggered()), this, SLOT(createPSD())); _newHistogramAct = new QAction(tr("&Histogram"), this); connect(_newHistogramAct, SIGNAL(triggered()), this, SLOT(createHistogram())); _newImageAct = new QAction(tr("&Image"), this); connect(_newImageAct, SIGNAL(triggered()), this, SLOT(createImage())); _newSpectrogramAct = new QAction(tr("Spectr&ogram"), this); connect(_newSpectrogramAct, SIGNAL(triggered()), this, SLOT(createSpectogram())); _newEventMonitorAct = new QAction(tr("Eve&nt Monitor"), this); connect(_newEventMonitorAct, SIGNAL(triggered()), this, SLOT(createEventMonitor())); // Advanced layout _createLabelAct = new QAction(tr("&Label"), this); _createLabelAct->setIcon(KstGetIcon("kst_gfx_label")); _createLabelAct->setShortcut(QString("F3")); _createLabelAct->setStatusTip(tr("Create a label for the current view (%1)").arg(_createLabelAct->shortcut().toString())); _createLabelAct->setCheckable(true); connect(_createLabelAct, SIGNAL(triggered()), this, SLOT(createLabel())); _createBoxAct = new QAction(tr("&Box"), this); _createBoxAct->setIcon(KstGetIcon("kst_gfx_rectangle")); _createBoxAct->setShortcut(QString("F4")); _createBoxAct->setStatusTip(tr("Create a box for the current view (%1)").arg(_createBoxAct->shortcut().toString())); _createBoxAct->setCheckable(true); connect(_createBoxAct, SIGNAL(triggered()), this, SLOT(createBox())); _createCircleAct = new QAction(tr("&Circle"), this); _createCircleAct->setIcon(KstGetIcon("kst_gfx_circle")); _createCircleAct->setShortcut(QString("F5")); _createCircleAct->setStatusTip(tr("Create a circle for the current view (%1)").arg(_createCircleAct->shortcut().toString())); _createCircleAct->setCheckable(true); connect(_createCircleAct, SIGNAL(triggered()), this, SLOT(createCircle())); _createEllipseAct = new QAction(tr("&Ellipse"), this); _createEllipseAct->setIcon(KstGetIcon("kst_gfx_ellipse")); _createEllipseAct->setShortcut(QString("F6")); _createEllipseAct->setStatusTip(tr("Create an ellipse for the current view (%1)").arg(_createEllipseAct->shortcut().toString())); _createEllipseAct->setCheckable(true); connect(_createEllipseAct, SIGNAL(triggered()), this, SLOT(createEllipse())); _createLineAct = new QAction(tr("&Line"), this); _createLineAct->setIcon(KstGetIcon("kst_gfx_line")); _createLineAct->setShortcut(QString("F7")); _createLineAct->setStatusTip(tr("Create a line for the current view (%1)").arg(_createLineAct->shortcut().toString())); _createLineAct->setCheckable(true); connect(_createLineAct, SIGNAL(triggered()), this, SLOT(createLine())); _createArrowAct = new QAction(tr("&Arrow"), this); _createArrowAct->setIcon(KstGetIcon("kst_gfx_arrow")); _createArrowAct->setShortcut(QString("F8")); _createArrowAct->setStatusTip(tr("Create a arrow for the current view (%1)").arg(_createArrowAct->shortcut().toString())); _createArrowAct->setCheckable(true); connect(_createArrowAct, SIGNAL(triggered()), this, SLOT(createArrow())); _createPictureAct = new QAction(tr("&Picture"), this); _createPictureAct->setIcon(KstGetIcon("insert-image")); _createPictureAct->setShortcut(QString("F9")); _createPictureAct->setStatusTip(tr("Create a picture for the current view (%1)").arg(_createPictureAct->shortcut().toString())); _createPictureAct->setCheckable(true); connect(_createPictureAct, SIGNAL(triggered()), this, SLOT(createPicture())); #ifndef KST_NO_SVG _createSvgAct = new QAction(tr("&Svg"), this); _createSvgAct->setIcon(KstGetIcon("draw-bezier-curves")); _createSvgAct->setShortcut(QString("F10")); _createSvgAct->setStatusTip(tr("Create a svg for the current view (%1)").arg(_createSvgAct->shortcut().toString())); _createSvgAct->setCheckable(true); connect(_createSvgAct, SIGNAL(triggered()), this, SLOT(createSvg())); #endif _createSharedAxisBoxAct = new QAction(tr("Shared Axis &Box"), this); _createSharedAxisBoxAct->setStatusTip(tr("Create a shared axis box for the current item")); _createSharedAxisBoxAct->setIcon(KstGetIcon("kst_gfx_sharedaxisbox")); _createSharedAxisBoxAct->setCheckable(true); //_createSharedAxisBoxAct->setEnabled(false); connect(_createSharedAxisBoxAct, SIGNAL(triggered()), this, SLOT(createSharedAxisBox())); // ************************** Mode Actions ******************************* // // First, general options _tiedZoomAct = new QAction(tr("&Toggle Tied Zoom"), this); _tiedZoomAct->setIcon(KstGetIcon("tied-zoom")); _tiedZoomAct->setCheckable(false); _tiedZoomAct->setStatusTip(tr("Toggle the current view's tied zoom (%1)").arg(_tiedZoomAct->shortcut().toString())); connect(_tiedZoomAct, SIGNAL(triggered()), this, SLOT(toggleTiedZoom())); _tabTiedAct = new QAction(tr("Tie &Across All Tabs"), this); _tabTiedAct->setStatusTip(tr("Tied zoom applies between tabs")); //_tiedZoomAct->setIcon(KstGetIcon("tied-zoom")); _tabTiedAct->setCheckable(true); //connect(_tiedZoomAct, SIGNAL(triggered()), this, SLOT(toggleTiedZoom())); _highlightPointAct = new QAction(tr("&Highlight Data Points"), this); _highlightPointAct->setStatusTip(tr("Highlight closest data point")); _highlightPointAct->setIcon(KstGetIcon("kst_datamode")); _highlightPointAct->setCheckable(true); connect(_highlightPointAct, SIGNAL(toggled(bool)), this, SLOT(setHighlightPoint(bool))); // Then, exclusive interaction modes QActionGroup* _interactionModeGroup = new QActionGroup(this); _standardZoomAct = _interactionModeGroup->addAction(tr("X-Y &Zoom/Scroll")); _standardZoomAct->setStatusTip(tr("Zoom arbitrarily in X- or Y-direction")); //TODO _standardZoomAct->setShortcut(QString("a")); _standardZoomAct->setCheckable(true); _standardZoomAct->setData(View::ZoomOnlyDisabled); _standardZoomAct->setIcon(KstGetIcon("xy-zoom")); _xOnlyZoomAct = _interactionModeGroup->addAction(tr("&X-only Zoom")); _xOnlyZoomAct->setStatusTip(tr("Zoom only in X direction")); //TODO _xOnlyZoomAct->setShortcut(QString("x")); _xOnlyZoomAct->setCheckable(true); _xOnlyZoomAct->setData(View::ZoomOnlyX); _xOnlyZoomAct->setIcon(KstGetIcon("x-zoom")); _yOnlyZoomAct = _interactionModeGroup->addAction(tr("&Y-only Zoom")); _yOnlyZoomAct->setStatusTip(tr("Zoom only in X direction")); //TODO _yOnlyZoomAct->setShortcut(QString("y")); _yOnlyZoomAct->setData(View::ZoomOnlyY); _yOnlyZoomAct->setCheckable(true); _yOnlyZoomAct->setIcon(KstGetIcon("y-zoom")); _layoutModeAct = _interactionModeGroup->addAction(tr("&Layout Mode")); _layoutModeAct->setIcon(KstGetIcon("transform-move")); _layoutModeAct->setCheckable(true); _layoutModeAct->setShortcut(QString("F2")); _layoutModeAct->setStatusTip(tr("Toggle the current view's layout mode (%1)").arg(_layoutModeAct->shortcut().toString())); connect(_layoutModeAct, SIGNAL(toggled(bool)), this, SLOT(setLayoutMode(bool))); _interactionModeGroup->setExclusive(true); connect(_interactionModeGroup, SIGNAL(triggered(QAction*)), this, SLOT(changeZoomOnlyMode(QAction*))); // *********************** Tools actions ************************************** // _dataManagerAct = new QAction(tr("Data &Manager"), this); _dataManagerAct->setIcon(KstGetIcon("data-manager")); _dataManagerAct->setShortcut(QString("d")); _dataManagerAct->setStatusTip(tr("Show Kst's data manager window (%1)").arg(_dataManagerAct->shortcut().toString())); connect(_dataManagerAct, SIGNAL(triggered()), this, SLOT(showDataManager())); _dataWizardAct = new QAction(tr("&Data Wizard"), this); _dataWizardAct->setIcon(KstGetIcon("tools-wizard")); _dataWizardAct->setShortcut(QString("w")); _dataWizardAct->setStatusTip(tr("Show Kst's Data Wizard (%1)").arg(_dataWizardAct->shortcut().toString())); connect(_dataWizardAct, SIGNAL(triggered()), this, SLOT(showDataWizard())); _changeFileDialogAct = new QAction(tr("Change Data &File"), this); _changeFileDialogAct->setIcon(KstGetIcon("change-data-file")); _changeFileDialogAct->setStatusTip(tr("Show Kst's Change Data File Dialog (%1)").arg(_changeFileDialogAct->shortcut().toString())); connect(_changeFileDialogAct, SIGNAL(triggered()), this, SLOT(showChangeFileDialog())); _chooseColorDialogAct = new QAction(tr("Assign Curve &Color per File"), this); _chooseColorDialogAct->setStatusTip(tr("Show Kst's Choose Color Dialog")); _chooseColorDialogAct->setIcon(KstGetIcon("code-class")); connect(_chooseColorDialogAct, SIGNAL(triggered()), this, SLOT(showChooseColorDialog())); _differentiateCurvesDialogAct = new QAction(tr("D&ifferentiate Curves"), this); _differentiateCurvesDialogAct->setStatusTip(tr("Show Kst's Differentiate Curves Dialog")); _differentiateCurvesDialogAct->setIcon(KstGetIcon("kst_differentiatecurves")); connect(_differentiateCurvesDialogAct, SIGNAL(triggered()), this, SLOT(showDifferentiateCurvesDialog())); _filterMultipleDialogAct = new QAction(tr("&Filter Vectors"), this); _filterMultipleDialogAct->setStatusTip(tr("Filter multiple vectors")); _filterMultipleDialogAct->setIcon(KstGetIcon("kst_filter_vectors")); connect(_filterMultipleDialogAct, SIGNAL(triggered()), this, SLOT(filterMultipleDialog())); // *********************** Settings actions ************************************** // _settingsDialogAct = new QAction(tr("&Configure Kst"), this); _settingsDialogAct->setStatusTip(tr("Show Kst's Configuration Dialog")); _settingsDialogAct->setIcon(KstGetIcon("configure")); connect(_settingsDialogAct, SIGNAL(triggered()), this, SLOT(showSettingsDialog())); _themeDialogAct = new QAction(tr("&Theme"), this); _themeDialogAct->setStatusTip(tr("Show Kst's Theme Dialog")); _themeDialogAct->setIcon(KstGetIcon("themes")); connect(_themeDialogAct, SIGNAL(triggered()), this, SLOT(showThemeDialog())); _clearUISettings = new QAction(tr("Clear settings and defaults"), this); _clearUISettings->setStatusTip(tr("Clear sticky defaults and all settings in all dialogs.")); //_clearUISettings->setIcon(KstGetIcon("configure")); // FIXME: pick an icon (broom?) connect(_clearUISettings, SIGNAL(triggered()), this, SLOT(clearDefaults())); _clearDataSourceSettings = new QAction(tr("Clear datasource settings"), this); _clearDataSourceSettings->setStatusTip(tr("Clear datasource settings")); //_clearDataSourceSettings->setIcon(KstGetIcon("configure")); // FIXME: pick an icon (broom?) connect(_clearDataSourceSettings, SIGNAL(triggered()), this, SLOT(clearDataSourceSettings())); // *********************** Help actions ************************************** // _debugDialogAct = new QAction(tr("&Debug Dialog"), this); _debugDialogAct->setStatusTip(tr("Show the Kst debugging dialog")); _debugDialogAct->setIcon(KstGetIcon("text-x-log")); connect(_debugDialogAct, SIGNAL(triggered()), this, SLOT(showDebugDialog())); _bugReportWizardAct = new QAction(tr("&Bug Report Wizard"), this); _bugReportWizardAct->setStatusTip(tr("Show Kst's Bug Report Wizard")); _bugReportWizardAct->setIcon(KstGetIcon("kbugbuster")); connect(_bugReportWizardAct, SIGNAL(triggered()), this, SLOT(showBugReportWizard())); _aboutAct = new QAction(tr("&About"), this); _aboutAct->setStatusTip(tr("Show Kst's About box")); _aboutAct->setIcon(KstGetIcon("dialog-information")); connect(_aboutAct, SIGNAL(triggered()), this, SLOT(about())); _video1Act = new QAction(tr("#&1: Quick Start"), this); _video1Act->setStatusTip(tr("Kst presentation #1: The shortest tutorial to the fastest plotting tool")); connect(_video1Act, SIGNAL(triggered()), _videoMapper, SLOT(map())); _videoMapper->setMapping(_video1Act, 1); _video2Act = new QAction(tr("#&2: General UI Presentation"), this); _video2Act->setStatusTip(tr("Kst presentation #2: General presentation of the user interface and most important concepts")); connect(_video2Act, SIGNAL(triggered()), _videoMapper, SLOT(map())); _videoMapper->setMapping(_video2Act, 2); _video3Act = new QAction(tr("#&3: Live Data / Range Tools"), this); _video3Act->setStatusTip(tr("Kst presentation #3: Range tools and live plots with streaming data")); connect(_video3Act, SIGNAL(triggered()), _videoMapper, SLOT(map())); _videoMapper->setMapping(_video3Act, 3); _video4Act = new QAction(tr("#&4: FFT, Equations, Fits, Filters"), this); _video4Act->setStatusTip(tr("Kst presentation #4: FFTs, equations, filters, fits, plugins")); connect(_video4Act, SIGNAL(triggered()), _videoMapper, SLOT(map())); _videoMapper->setMapping(_video4Act, 4); _video5Act = new QAction(tr("#&5: Productivity Features"), this); _video5Act->setStatusTip(tr("Kst presentation #5: Unique productivity features like edit multiple mode and change data file tool")); connect(_video5Act, SIGNAL(triggered()), _videoMapper, SLOT(map())); _videoMapper->setMapping(_video5Act, 5); _video6Act = new QAction(tr("#&6: Advanced Layout / Export"), this); _video6Act->setStatusTip(tr("Kst presentation #6: Advanced layout and export options")); connect(_video6Act, SIGNAL(triggered()), _videoMapper, SLOT(map())); _videoMapper->setMapping(_video6Act, 6); _video7Act = new QAction(tr("#&7: Matrices / Images / Metadata"), this); _video7Act->setStatusTip(tr("Kst presentation #7: Matrices, images and metadata")); connect(_video7Act, SIGNAL(triggered()), _videoMapper, SLOT(map())); _videoMapper->setMapping(_video7Act, 7); connect(_videoMapper, SIGNAL(mapped(int)), this, SLOT(videoTutorial(int))); } void MainWindow::createMenus() { _fileMenu = menuBar()->addMenu(tr("&File")); // Session operations _fileMenu->addAction(_openAct); _fileMenu->addAction(_saveAct); _fileMenu->addAction(_saveAsAct); _fileMenu->addAction(_closeAct); _fileMenu->addSeparator(); _recentKstFilesMenu = _fileMenu->addMenu(tr("&Recent Sessions")); _recentDataFilesMenu = _fileMenu->addMenu(tr("Recent Data &Files")); _fileMenu->addSeparator(); // Reload, isolate it a bit from the other entries to avoid inadvertent triggering _fileMenu->addAction(_reloadAct); _fileMenu->addSeparator(); // Print/export _fileMenu->addAction(_printAct); _fileMenu->addAction(_exportGraphicsAct); _fileMenu->addAction(_exportVectorsAct); _fileMenu->addAction(_logAct); _fileMenu->addSeparator(); // Tabs _fileMenu->addAction(_newTabAct); _fileMenu->addAction(_closeTabAct); _fileMenu->addSeparator(); // exit _fileMenu->addAction(_exitAct); // recent files _fileMenu->addSeparator(); updateRecentKstFiles(); _editMenu = menuBar()->addMenu(tr("&Edit")); _editMenu->addAction(_undoAct); _editMenu->addAction(_redoAct); // Cut/Copy/Paste will come here _viewMenu = menuBar()->addMenu(tr("&View")); _viewMenu->addAction(_vectorEditorAct); _viewMenu->addAction(_scalarEditorAct); _viewMenu->addAction(_matrixEditorAct); _viewMenu->addAction(_stringEditorAct); _rangeMenu = menuBar()->addMenu(tr("&Range")); _rangeMenu->addAction(_backAct); _rangeMenu->addAction(_forwardAct); _rangeMenu->addSeparator(); _rangeMenu->addAction(_readFromEndAct); _rangeMenu->addAction(_readToEndAct); _rangeMenu->addAction(_pauseAct); _rangeMenu->addSeparator(); _rangeMenu->addAction(_changeDataSampleDialogAct); _createMenu = menuBar()->addMenu(tr("&Create")); // Containers _createMenu->addAction(_insertPlotAct); //_createMenu->addAction(_createPlotAct); _createMenu->addAction(_createSharedAxisBoxAct); _createMenu->addSeparator(); // Primitives _createMenu->addAction(_newScalarAct); _createMenu->addAction(_newVectorAct); _createMenu->addAction(_newMatrixAct); _createMenu->addAction(_newStringAct); _createMenu->addSeparator(); // Data objects _createMenu->addAction(_newEquationAct); _createMenu->addAction(_newHistogramAct); _createMenu->addAction(_newPSDAct); _createMenu->addAction(_newSpectrogramAct); _createMenu->addAction(_newEventMonitorAct); _createMenu->addSeparator(); // Now, create the dynamic plugin menus QMenu* _pluginsMenu = _createMenu->addMenu(tr("Standard P&lugin")); QMenu* _fitPluginsMenu = _createMenu->addMenu(tr("Fit Pl&ugin")); QMenu* _filterPluginsMenu = _createMenu->addMenu(tr("Fil&ter Plugin")); PluginMenuItemAction* action; foreach (const QString &pluginName, DataObject::dataObjectPluginList()) { action = new PluginMenuItemAction(pluginName, this); connect(action, SIGNAL(triggered(QString&)), this, SLOT(showPluginDialog(QString&))); _pluginsMenu->addAction(action); } foreach (const QString &pluginName, DataObject::fitsPluginList()) { action = new PluginMenuItemAction(pluginName, this); connect(action, SIGNAL(triggered(QString&)), this, SLOT(showPluginDialog(QString&))); _fitPluginsMenu->addAction(action); } foreach (const QString &pluginName, DataObject::filterPluginList()) { action = new PluginMenuItemAction(pluginName, this); connect(action, SIGNAL(triggered(QString&)), this, SLOT(showPluginDialog(QString&))); _filterPluginsMenu->addAction(action); } _createMenu->addSeparator(); // Relations _createMenu->addAction(_newCurveAct); _createMenu->addAction(_newImageAct); _createMenu->addSeparator(); // Annotation objects QMenu* annotations = _createMenu->addMenu(tr("&Annotation")); annotations->addAction(_createLabelAct); annotations->addAction(_createBoxAct); annotations->addAction(_createCircleAct); annotations->addAction(_createEllipseAct); annotations->addAction(_createLineAct); annotations->addAction(_createArrowAct); annotations->addAction(_createPictureAct); #ifndef KST_NO_SVG annotations->addAction(_createSvgAct); #endif _modeMenu = menuBar()->addMenu(tr("&Mode")); // Interaction mode _modeMenu->addSeparator()->setText(tr("Interaction mode")); _modeMenu->addAction(_standardZoomAct); _modeMenu->addAction(_xOnlyZoomAct); _modeMenu->addAction(_yOnlyZoomAct); _modeMenu->addAction(_layoutModeAct); _standardZoomAct->setChecked(true); _modeMenu->addSeparator(); // Tied zoom options _modeMenu->addAction(_tiedZoomAct); _modeMenu->addAction(_tabTiedAct); _modeMenu->addSeparator(); // Data mode _modeMenu->addAction(_highlightPointAct); _toolsMenu = menuBar()->addMenu(tr("&Tools")); _toolsMenu->addAction(_dataManagerAct); _toolsMenu->addAction(_dataWizardAct); _toolsMenu->addAction(_changeFileDialogAct); _toolsMenu->addAction(_chooseColorDialogAct); _toolsMenu->addAction(_differentiateCurvesDialogAct); _toolsMenu->addAction(_filterMultipleDialogAct); _toolsMenu->addSeparator(); updateRecentDataFiles(); _settingsMenu = menuBar()->addMenu(tr("&Settings")); _settingsMenu->addAction(_settingsDialogAct); _settingsMenu->addAction(_themeDialogAct); _settingsMenu->addAction(_clearUISettings); _settingsMenu->addAction(_clearDataSourceSettings); menuBar()->addSeparator(); _helpMenu = menuBar()->addMenu(tr("&Help")); QMenu* _videoTutorialsMenu = _helpMenu->addMenu(tr("&Video tutorials")); _videoTutorialsMenu->addAction(_video1Act); _videoTutorialsMenu->addAction(_video2Act); _videoTutorialsMenu->addAction(_video3Act); _videoTutorialsMenu->addAction(_video4Act); _videoTutorialsMenu->addAction(_video5Act); _videoTutorialsMenu->addAction(_video6Act); _videoTutorialsMenu->addAction(_video7Act); _helpMenu->addSeparator(); _helpMenu->addAction(_debugDialogAct); _helpMenu->addAction(_bugReportWizardAct); _helpMenu->addSeparator(); _helpMenu->addAction(_aboutAct); } void MainWindow::createToolBars() { setToolButtonStyle(Qt::ToolButtonIconOnly); _fileToolBar = addToolBar(tr("File")); _fileToolBar->setObjectName("File Toolbar"); _fileToolBar->addAction(_openAct); _fileToolBar->addAction(_saveAct); _fileToolBar->addAction(_reloadAct); _fileToolBar->addAction(_printAct); _fileToolBar->addAction(_logAct); _editToolBar = addToolBar(tr("Edit")); _editToolBar->setObjectName("Edit Toolbar"); _editToolBar->addAction(_undoAct); _editToolBar->addAction(_redoAct); _toolsToolBar = addToolBar(tr("Tools")); _toolsToolBar->setObjectName("Tools Toolbar"); _toolsToolBar->addAction(_dataManagerAct); _toolsToolBar->addAction(_dataWizardAct); _toolsToolBar->addAction(_changeDataSampleDialogAct); _toolsToolBar->addAction(_changeFileDialogAct); _rangeToolBar = addToolBar(tr("Data Range")); _rangeToolBar->setObjectName("Data Range Toolbar"); _rangeToolBar->addAction(_backAct); _rangeToolBar->addAction(_forwardAct); _rangeToolBar->addAction(_readFromEndAct); _rangeToolBar->addAction(_readToEndAct); _rangeToolBar->addAction(_pauseAct); _modeToolBar = addToolBar(tr("Mode")); _modeToolBar->setObjectName("Mode Toolbar"); _modeToolBar->addAction(_tiedZoomAct); _modeToolBar->addAction(_highlightPointAct); _modeToolBar->addSeparator(); _modeToolBar->addAction(_standardZoomAct); _modeToolBar->addAction(_xOnlyZoomAct); _modeToolBar->addAction(_yOnlyZoomAct); _modeToolBar->addAction(_layoutModeAct); _plotLayoutToolBar = addToolBar(tr("Plot Layout")); _plotLayoutToolBar->setObjectName("Plot Layout Toolbar"); _plotLayoutToolBar->addAction(_createSharedAxisBoxAct); _plotLayoutToolBar->addAction(_insertPlotAct); //_plotLayoutToolBar->addAction(_createPlotAct); _annotationToolBar = addToolBar(tr("Advanced Layout")); _annotationToolBar->setObjectName("Advanced Layout Toolbar"); _annotationToolBar->addAction(_createLabelAct); _annotationToolBar->addAction(_createBoxAct); _annotationToolBar->addAction(_createCircleAct); _annotationToolBar->addAction(_createEllipseAct); _annotationToolBar->addAction(_createLineAct); _annotationToolBar->addAction(_createArrowAct); _annotationToolBar->addAction(_createPictureAct); #ifndef KST_NO_SVG _annotationToolBar->addAction(_createSvgAct); #endif } void MainWindow::createStatusBar() { _messageLabel = new QLabel(statusBar()); setStatusMessage(tr("Ready"), 3000); _progressBar = new QProgressBar(statusBar()); _progressBar->setFixedWidth(200); _progressBar->hide(); statusBar()->addPermanentWidget(_progressBar); MemoryWidget *mw = new MemoryWidget(statusBar()); statusBar()->addPermanentWidget(mw); DebugNotifier *dn = new DebugNotifier(statusBar()); connect(dn, SIGNAL(showDebugLog()), this, SLOT(showDebugDialog())); connect(_debugDialog, SIGNAL(notifyOfError()), dn, SLOT(reanimate())); connect(_debugDialog, SIGNAL(notifyAllClear()), dn, SLOT(close())); statusBar()->addPermanentWidget(dn); } /** set the status bar message. If you are doing this inside a view * object paint() call, then set delayed to true, and call ::updateStatusMessage() * later (after leaving paint). This is currently done for you in updateViewItems */ void MainWindow::setStatusMessage(QString message, int timeout, bool delayed) { _statusBarMessage = message; _statusBarTimeout = timeout; if (!delayed) { statusBar()->showMessage(message, timeout); } } void MainWindow::videoTutorial(int i) { switch (i) { case 1: QDesktopServices::openUrl(QUrl("http://www.youtube.com/watch?v=d1uz5g_cWh4")); break; case 2: QDesktopServices::openUrl(QUrl("http://www.youtube.com/watch?v=6z2bGNrgwL0")); break; case 3: QDesktopServices::openUrl(QUrl("http://www.youtube.com/watch?v=dstOQpmfY1U")); break; case 4: QDesktopServices::openUrl(QUrl("http://www.youtube.com/watch?v=YJ54X0nKnmk")); break; case 5: QDesktopServices::openUrl(QUrl("http://www.youtube.com/watch?v=3YZVC-GiS_4")); break; case 6: QDesktopServices::openUrl(QUrl("http://www.youtube.com/watch?v=rI7nYHlz6rs")); break; case 7: QDesktopServices::openUrl(QUrl("http://www.youtube.com/watch?v=mgP24MryyKw")); break; default: break; } } QString MainWindow::statusMessage() { return statusBar()->currentMessage(); } void MainWindow::updateStatusMessage() { statusBar()->showMessage(_statusBarMessage, _statusBarTimeout); } QProgressBar *MainWindow::progressBar() const { return _progressBar; } void MainWindow::updateProgress(int percent, const QString& message) { if (percent == -1) { _progressBar->setMaximum(0); _progressBar->setMinimum(0); _progressBar->show(); return; } if (percent > 0 && percent < 100) { _progressBar->setMaximum(100); _progressBar->setValue(percent); _progressBar->show(); } else { _progressBar->hide(); } setStatusMessage(message); } void MainWindow::readFromEnd() { int nf = 0; int skip; bool do_skip; bool do_filter; DataVectorList dataVectors = document()->objectStore()->getObjects(); foreach (DataVectorPtr v, dataVectors) { v->readLock(); nf = v->reqNumFrames(); if (nf <=0 ) { nf = v->numFrames(); } skip = v->skip(); do_skip = v->doSkip(); do_filter = v->doAve(); v->unlock(); v->writeLock(); v->changeFrames(-1, nf, skip, do_skip, do_filter); v->registerChange(); v->unlock(); } DataMatrixList dataMatrices = document()->objectStore()->getObjects(); foreach (DataMatrixPtr m, dataMatrices) { m->readLock(); m->setFrame(-1); m->registerChange(); m->unlock(); } UpdateManager::self()->doUpdates(true); dialogDefaults().setValue("vector/range", nf); dialogDefaults().setValue("vector/countFromEnd", true); dialogDefaults().setValue("vector/readToEnd", false); } void MainWindow::readToEnd() { int f0 = 0; int skip; bool do_skip; bool do_filter; DataVectorList dataVectors = document()->objectStore()->getObjects(); foreach (DataVectorPtr v, dataVectors) { v->readLock(); f0 = v->startFrame(); skip = v->skip(); do_skip = v->doSkip(); do_filter = v->doAve(); v->unlock(); v->writeLock(); v->changeFrames(f0, -1, skip, do_skip, do_filter); v->registerChange(); v->unlock(); } DataMatrixList dataMatrices = document()->objectStore()->getObjects(); foreach (DataMatrixPtr m, dataMatrices) { m->readLock(); m->setFrame(-1); m->registerChange(); m->unlock(); } dialogDefaults().setValue("vector/start", f0); dialogDefaults().setValue("vector/countFromEnd", false); dialogDefaults().setValue("vector/readToEnd", true); UpdateManager::self()->doUpdates(true); } void MainWindow::pause(bool pause) { UpdateManager::self()->setPaused(pause); //if (!pause) { //foreach (DataSourcePtr s, document()->objectStore()->dataSourceList()) { //s->checkUpdate(); //} //} } void MainWindow::forward() { int f0 = 0; int nf = 0; int lastF = -1; int skip; int filelength; bool count_from_end; bool read_to_end; bool do_skip; bool do_filter; DataVectorList dataVectors = document()->objectStore()->getObjects(); DataMatrixList dataMatrices = document()->objectStore()->getObjects(); QHash lastframehash; foreach (DataVectorPtr v, dataVectors) { v->readLock(); f0 = v->startFrame(); nf = v->numFrames(); count_from_end = v->countFromEOF(); read_to_end = v->readToEOF(); filelength = v->fileLength(); skip = v->skip(); do_skip = v->doSkip(); do_filter = v->doAve(); v->unlock(); if ((!count_from_end) && (!read_to_end)) { f0 += nf; if (f0+nf>=filelength) { f0 = filelength - nf; } lastF = f0 + nf - 1; ++lastframehash[lastF]; v->writeLock(); v->changeFrames(f0, nf, skip, do_skip, do_filter); v->registerChange(); v->unlock(); } } int most_popular_lastF = -1; int n_most_popular_lastF = -1; foreach (int key, lastframehash.keys()) { int n = lastframehash[key] ; if (n > n_most_popular_lastF) { n_most_popular_lastF = n; most_popular_lastF = key; } } foreach (DataMatrixPtr m, dataMatrices) { if (m->hasStream()) { int new_frame; int filelength = m->fileLength(); if (most_popular_lastF>=0) { if (most_popular_lastF < filelength) { new_frame = most_popular_lastF; } else { new_frame = filelength-1; } } else { if (m->frame()+1 < filelength) { new_frame = m->frame()+1; } else { new_frame = filelength-1; } } m->writeLock(); m->setFrame(new_frame); m->registerChange(); m->unlock(); } } dialogDefaults().setValue("vector/range", nf); dialogDefaults().setValue("vector/start", f0); dialogDefaults().setValue("vector/countFromEnd", false); dialogDefaults().setValue("vector/readToEnd", false); UpdateManager::self()->doUpdates(true); } void MainWindow::back() { int f0 = 0; int nf = 0; int skip; int filelength; bool count_from_end; bool read_to_end; bool do_skip; bool do_filter; int lastF = -1; DataVectorList dataVectors = document()->objectStore()->getObjects(); DataMatrixList dataMatrices = document()->objectStore()->getObjects(); QHash lastframehash; foreach (DataVectorPtr v, dataVectors) { v->readLock(); f0 = v->startFrame(); nf = v->numFrames(); count_from_end = v->countFromEOF(); read_to_end = v->readToEOF(); filelength = v->fileLength(); skip = v->skip(); do_skip = v->doSkip(); do_filter = v->doAve(); v->unlock(); if (f0 != 0) { if (count_from_end) { f0 = filelength - nf; } if (read_to_end) { nf = filelength - f0; } f0 -= nf; if (f0<0) { f0 = 0; } lastF = f0 + nf - 1; ++lastframehash[lastF]; v->writeLock(); v->changeFrames(f0, nf, skip, do_skip, do_filter); v->registerChange(); v->unlock(); } } int most_popular_lastF = -1; int n_most_popular_lastF = -1; foreach (int key, lastframehash.keys()) { int n = lastframehash[key] ; if (n > n_most_popular_lastF) { n_most_popular_lastF = n; most_popular_lastF = key; } } foreach (DataMatrixPtr m, dataMatrices) { if (m->hasStream()) { int new_frame; int filelength = m->fileLength(); if (most_popular_lastF>=0) { if (most_popular_lastF < filelength) { new_frame = most_popular_lastF; } else { new_frame = filelength-1; } } else { if (m->frame()-1 >= 0) { new_frame = m->frame()-1; } else { new_frame = filelength-2; } } m->writeLock(); m->setFrame(new_frame); m->registerChange(); m->unlock(); } } dialogDefaults().setValue("vector/range", nf); dialogDefaults().setValue("vector/start", f0); dialogDefaults().setValue("vector/countFromEnd", false); dialogDefaults().setValue("vector/readToEnd", false); UpdateManager::self()->doUpdates(true); } void MainWindow::reload() { document()->objectStore()->rebuildDataSourceList(); UpdateManager::self()->doUpdates(true); //document()->setChanged(true); } void MainWindow::showDataManager() { if (!_dataManager) { _dataManager = new DataManager(this, _doc); } if (_dataManager->isVisible()) { _dataManager->raise(); _dataManager->activateWindow(); } _dataManager->show(); } void MainWindow::updateViewItems(qint64 serial) { QList plots = ViewItem::getItems(); bool changed = false; foreach (PlotItem *plot, plots) { changed |= plot->handleChangedInputs(serial); } QList labels = ViewItem::getItems(); foreach (LabelItem * label, labels) { if (label->_labelRc) { label->inputsChanged(serial); } } if (changed) { _tabWidget->currentView()->update(); if (_viewVectorDialog) { _viewVectorDialog->update(); } kstApp->mainWindow()->updateStatusMessage(); } QTimer::singleShot(20, UpdateManager::self(), SLOT(viewItemUpdateFinished())); // why 20ms ??? } void MainWindow::showVectorEditor() { if (!_viewVectorDialog) { _viewVectorDialog = new ViewVectorDialog(this, _doc); } if (_viewVectorDialog->isVisible()) { _viewVectorDialog->raise(); _viewVectorDialog->activateWindow(); } _viewVectorDialog->show(); } void MainWindow::showScalarEditor() { ViewPrimitiveDialog *viewScalarDialog = new ViewScalarDialog(this, _doc); viewScalarDialog->show(); } void MainWindow::showStringEditor() { ViewPrimitiveDialog *viewStringDialog = new ViewStringDialog(this, _doc); viewStringDialog->show(); } void MainWindow::showMatrixEditor() { ViewMatrixDialog *viewMatrixDialog = new ViewMatrixDialog(this, _doc); viewMatrixDialog->show(); } void MainWindow::showDebugDialog() { if (!_debugDialog) { _debugDialog = new DebugDialog(this); } _debugDialog->setObjectStore(document()->objectStore()); if (_debugDialog->isVisible()) { _debugDialog->raise(); _debugDialog->activateWindow(); } _debugDialog->show(); } void MainWindow::showExportGraphicsDialog() { if (!_exportGraphics) { _exportGraphics = new ExportGraphicsDialog(this); connect(_exportGraphics, SIGNAL(exportGraphics(QString,QString,int,int,int,bool,int)), this, SLOT(exportGraphicsFile(QString,QString,int,int,int,bool,int))); } if (_exportGraphics->isVisible()) { _exportGraphics->raise(); _exportGraphics->activateWindow(); } _exportGraphics->show(); } void MainWindow::showExportVectorsDialog() { if (!_exportVectors) { _exportVectors = new ExportVectorsDialog(this); } if (_exportVectors->isVisible()) { _exportVectors->raise(); _exportVectors->activateWindow(); } _exportVectors->show(); } void MainWindow::showLogDialog() { if (!_logDialog) { _logDialog = new LogDialog(this); //connect(_logDialog, SIGNAL(exportLog(const QString &, time_t, const QString &, int, int, int, const QString &)), // this, SLOT(exportLog(const QString &, time_t, const QString &, int, int, int, const QString &))); } if (_logDialog->isVisible()) { _logDialog->raise(); _logDialog->activateWindow(); } _logDialog->show(); } void MainWindow::showSettingsDialog() { if (!_applicationSettingsDialog) { _applicationSettingsDialog = new ApplicationSettingsDialog(this); } if (_applicationSettingsDialog->isVisible()) { _applicationSettingsDialog->raise(); _applicationSettingsDialog->activateWindow(); } _applicationSettingsDialog->show(); } void MainWindow::showThemeDialog() { if (!_themeDialog) { _themeDialog = new ThemeDialog(this); } if (_themeDialog->isVisible()) { _themeDialog->raise(); _themeDialog->activateWindow(); } _themeDialog->reset(); _themeDialog->show(); } void MainWindow::clearDefaults() { QMessageBox confirmationBox; confirmationBox.setText(tr("Clear all settings and defaults?")); confirmationBox.setInformativeText(tr("You are about to clear all settings defaults in all dialogs in kst.\nThis can not be undone.")); confirmationBox.setStandardButtons(QMessageBox::Ok | QMessageBox::Cancel); confirmationBox.setDefaultButton(QMessageBox::Ok); int confirmed = confirmationBox.exec(); switch (confirmed) { case QMessageBox::Ok: dialogDefaults().clear(); ApplicationSettings::self()->clear(); DataSourcePluginManager::settingsObject().clear(); break; case QMessageBox::Cancel: default: // cancel: do nothing at all. break; } } void MainWindow::clearDataSourceSettings() { QMessageBox confirmationBox; confirmationBox.setText(tr("Clear datasource settings?")); confirmationBox.setInformativeText(tr("You are about to clear all\nconfiguration settings for\nall datasources/file types.")); confirmationBox.setStandardButtons(QMessageBox::Ok | QMessageBox::Cancel); confirmationBox.setDefaultButton(QMessageBox::Ok); int confirmed = confirmationBox.exec(); switch (confirmed) { case QMessageBox::Ok: DataSourcePluginManager::settingsObject().clear(); break; case QMessageBox::Cancel: default: // cancel: do nothing at all. break; } } void MainWindow::showDifferentiateCurvesDialog() { if (!_differentiateCurvesDialog) { _differentiateCurvesDialog = new DifferentiateCurvesDialog(this); } if (_differentiateCurvesDialog->isVisible()) { _differentiateCurvesDialog->raise(); _differentiateCurvesDialog->activateWindow(); } _differentiateCurvesDialog->show(); } void MainWindow::filterMultipleDialog() { if (!_filterMultipleDialog) { _filterMultipleDialog = new FilterMultipleDialog(this); } if (_filterMultipleDialog->isVisible()) { _filterMultipleDialog->raise(); _filterMultipleDialog->activateWindow(); } _filterMultipleDialog->show(); } void MainWindow::showChooseColorDialog() { if (!_chooseColorDialog) { _chooseColorDialog = new ChooseColorDialog(this); } if (_chooseColorDialog->isVisible()) { _chooseColorDialog->raise(); _chooseColorDialog->activateWindow(); } _chooseColorDialog->show(); } void MainWindow::showChangeDataSampleDialog() { if (!_changeDataSampleDialog) { _changeDataSampleDialog = new ChangeDataSampleDialog(this); } if (_changeDataSampleDialog->isVisible()) { _changeDataSampleDialog->raise(); _changeDataSampleDialog->activateWindow(); } _changeDataSampleDialog->show(); } void MainWindow::showDataWizard() { DataWizard *dataWizard = new DataWizard(this); connect(dataWizard, SIGNAL(dataSourceLoaded(QString)), this, SLOT(updateRecentDataFiles(QString))); dataWizard->show(); } void MainWindow::showDataWizard(const QString &dataFile) { DataWizard *dataWizard = new DataWizard(this, dataFile); dataWizard->show(); } void MainWindow::openRecentDataFile() { QAction *action = qobject_cast(sender()); if (action) { DataWizard *dataWizard = new DataWizard(this, action->data().toString()); connect(dataWizard, SIGNAL(dataSourceLoaded(QString)), this, SLOT(updateRecentDataFiles(QString))); dataWizard->show(); } } void MainWindow::showBugReportWizard() { if (!_bugReportWizard) { _bugReportWizard = new BugReportWizard(this); } if (_bugReportWizard->isVisible()) { _bugReportWizard->raise(); _bugReportWizard->activateWindow(); } _bugReportWizard->show(); } void MainWindow::showChangeFileDialog() { if (!_changeFileDialog) { _changeFileDialog = new ChangeFileDialog(this); } if (_changeFileDialog->isVisible()) { _changeFileDialog->raise(); _changeFileDialog->activateWindow(); } _changeFileDialog->show(); } void MainWindow::showPluginDialog(QString &pluginName) { DialogLauncher::self()->showBasicPluginDialog(pluginName); } bool MainWindow::isTiedTabs() { return _tabTiedAct->isChecked(); } void MainWindow::readSettings() { #if defined(__QNX__) || defined(__ANDROID__) // There is only one size we want on mobile platforms - full screen! setWindowState(Qt::WindowFullScreen); #else QByteArray geo = _settings.value("geometry").toByteArray(); if (!geo.isEmpty()) { restoreGeometry(geo); } else { setGeometry(50, 50, 800, 600); } #endif // defined(__QNX__) || defined(__ANDROID__) restoreState(_settings.value("toolbarState").toByteArray()); _tabTiedAct->setChecked(_settings.value("tieTabs").toBool()); } void MainWindow::writeSettings() { _settings.setValue("geometry", saveGeometry()); _settings.setValue("toolbarState", saveState()); _settings.setValue("tieTabs", _tabTiedAct->isChecked()); } void MainWindow::setWidgetFlags(QWidget* widget) { if (widget) { // Make sure the dialog gets maximize and minimize buttons under Windows widget->QWidget::setWindowFlags((Qt::WindowFlags) Qt::Dialog | Qt::WindowMinimizeButtonHint | Qt::WindowMaximizeButtonHint #if QT_VERSION >= 0x040500 | Qt::WindowCloseButtonHint #endif ); } } void MainWindow::dragEnterEvent(QDragEnterEvent *event) { if (event->mimeData()->hasUrls()) { event->acceptProposedAction(); } } void MainWindow::dropEvent(QDropEvent *event) { QString path = event->mimeData()->urls().first().toLocalFile(); if (path.endsWith(QString(".kst"))) { if (!promptSaveDone()) { // There are things to save => cancel event->ignore(); return; } openFile(path); } else { showDataWizard(path); // This is not destructive: it only add data, no need to ask for confirmation } event->accept(); } void MainWindow::cleanUpDataSourceList() { _doc->objectStore()->cleanUpDataSourceList(); } #if defined(__QNX__) bool MainWindow::eventFilter(QObject *obj, QEvent *event) { if (!qApp->activeWindow()) { activateWindow(); } if (event->type() == QEvent::KeyPress) { QKeyEvent *keyEvent = static_cast(event); if (keyEvent->key()==Qt::Key_Menu) { // i.e., bezel swipe gesture... qnxToggleToolbarVisibility(); } return false; } else if (event->type() == QEvent::MouseButtonPress && obj != menuBar()) { if (_qnxToolbarsVisible) qnxToggleToolbarVisibility(); update(); return false; } else if (event->type() == QEvent::WindowActivate) { update(); return false; } else { return QObject::eventFilter(obj, event); } } void MainWindow::keyPressEvent(QKeyEvent *event) { if ((event->type() == QEvent::KeyPress && static_cast(event)->key() == Qt::Key_Menu)) { qnxToggleToolbarVisibility(); } } void MainWindow::qnxToggleToolbarVisibility() { if (_qnxLastToolbarEvent.msecsTo(QDateTime::currentDateTime()) < 100) { return; // HACK } _qnxLastToolbarEvent = QDateTime::currentDateTime(); menuBar()->setVisible(!_qnxToolbarsVisible); statusBar()->setVisible(!_qnxToolbarsVisible); _fileToolBar->setVisible(!_qnxToolbarsVisible); _editToolBar->setVisible(!_qnxToolbarsVisible); _toolsToolBar->setVisible(!_qnxToolbarsVisible); _rangeToolBar->setVisible(!_qnxToolbarsVisible); _modeToolBar->setVisible(!_qnxToolbarsVisible); _plotLayoutToolBar->setVisible(!_qnxToolbarsVisible); _annotationToolBar->setVisible(!_qnxToolbarsVisible); _qnxToolbarsVisible = !_qnxToolbarsVisible; } #endif } // vim: ts=2 sw=2 et diff --git a/src/libkstapp/vectordialog.cpp b/src/libkstapp/vectordialog.cpp index 143278de..abcc79b1 100644 --- a/src/libkstapp/vectordialog.cpp +++ b/src/libkstapp/vectordialog.cpp @@ -1,656 +1,660 @@ /*************************************************************************** * * * 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 "vectordialog.h" #include "application.h" #include "dialogpage.h" #include "datasourceconfiguredialog.h" #include "editmultiplewidget.h" #include "datavector.h" #include "generatedvector.h" #include "datacollection.h" #include "document.h" #include "objectstore.h" #include "datasourcepluginmanager.h" #include "dialogdefaults.h" #include "debug.h" #include #include namespace Kst { VectorTab::VectorTab(ObjectStore *store, QWidget *parent) : DataTab(parent), validating(false), _mode(DataVector), _store(store), _initField(QString()), _requestID(0), _valid(false) { setupUi(this); setTabTitle(tr("Vector")); connect(_generatedVectorGroup, SIGNAL(clicked(bool)), this, SLOT(generateClicked())); connect(_dataVectorGroup, SIGNAL(clicked(bool)), this, SLOT(readFromSourceClicked())); connect(_fileName, SIGNAL(changed(QString)), this, SLOT(fileNameChanged(QString))); connect(_configure, SIGNAL(clicked()), this, SLOT(showConfigWidget())); connect(_field, SIGNAL(editTextChanged(QString)), this, SIGNAL(fieldChanged())); connect(_dataRange, SIGNAL(modified()), this, SIGNAL(modified())); connect(_numberOfSamples, SIGNAL(valueChanged(int)), this, SIGNAL(modified())); connect(_from, SIGNAL(textChanged(QString)), this, SIGNAL(modified())); connect(_to, SIGNAL(textChanged(QString)), this, SIGNAL(modified())); // embed data range in the data source box _dataRange->groupBox2->setFlat(true); _dataRange->groupBox2->setTitle(""); int top_margin; _dataRange->groupBox2->layout()->getContentsMargins(NULL,&top_margin,NULL,NULL); _dataRange->groupBox2->layout()->setContentsMargins(0,top_margin,0,0); _connect->setVisible(false); _updateBox->addItem(tr("Time Interval", "update periodically")); _updateBox->addItem(tr("Change Detection", "update when a change is detected")); _updateBox->addItem(tr("No Update", "do not update the file")); updateUpdateBox(); connect(_updateBox, SIGNAL(currentIndexChanged(int)), this, SLOT(updateTypeActivated(int))); connect(_updateBox, SIGNAL(currentIndexChanged(int)), this, SIGNAL(modified())); } VectorTab::~VectorTab() { } void VectorTab::updateUpdateBox() { if (_dataSource) { _updateBox->setEnabled(_mode == DataVector); switch (_dataSource->updateType()) { case DataSource::Timer: _updateBox->setCurrentIndex(0); break; case DataSource::File: _updateBox->setCurrentIndex(1); break; case DataSource::None: _updateBox->setCurrentIndex(2); break; default: break; }; } else { _updateBox->setEnabled(false); } } void VectorTab::updateTypeActivated(int idx) { if (!_dataSource) { _updateBox->setEnabled(false); return; } switch (idx) { _updateBox->setEnabled(true); case 0: _dataSource->startUpdating(DataSource::Timer); break; case 1: _dataSource->startUpdating(DataSource::File); break; case 2: _dataSource->startUpdating(DataSource::None); break; default: break; }; } DataSourcePtr VectorTab::dataSource() const { return _dataSource; } void VectorTab::setDataSource(DataSourcePtr dataSource) { _dataSource = dataSource; } void VectorTab::setVectorMode(VectorMode mode) { _mode = mode; if (mode == DataVector) { _dataVectorGroup->setChecked(true); _dataRange->setEnabled(true); _generatedVectorGroup->setChecked(false); _field->setEnabled(_valid); _configure->setEnabled(_valid); updateUpdateBox(); } else { _generatedVectorGroup->setChecked(true); _dataVectorGroup->setChecked(false); _dataRange->setEnabled(false); } } QString VectorTab::file() const { return _fileName->file(); } void VectorTab::setFile(const QString &file) { _fileName->setFile(DataSource::cleanPath(file)); } QString VectorTab::field() const { return _field->currentText(); } void VectorTab::setField(const QString &field) { _initField = field; // for delayed index setting _field->setCurrentIndex(_field->findText(field)); } void VectorTab::setFieldList(const QStringList &fieldList) { _field->clear(); _field->addItems(fieldList); } DataRange *VectorTab::dataRange() const { return _dataRange; } qreal VectorTab::from() const { return _from->text().toDouble(); } bool VectorTab::fromDirty() const { return (!_from->text().isEmpty()); } void VectorTab::setFrom(qreal from) { _from->setText(QString::number(from)); } qreal VectorTab::to() const { return _to->text().toDouble(); } bool VectorTab::toDirty() const { return (!_to->text().isEmpty()); } void VectorTab::setTo(qreal to) { _to->setText(QString::number(to)); } int VectorTab::numberOfSamples() const { return _numberOfSamples->value(); } bool VectorTab::numberOfSamplesDirty() const { return (!_numberOfSamples->text().isEmpty()); } void VectorTab::setNumberOfSamples(int numberOfSamples) { _numberOfSamples->setValue(numberOfSamples); } void VectorTab::generateClicked() { if (_generatedVectorGroup->isChecked()) setVectorMode(GeneratedVector); else setVectorMode(DataVector); emit sourceChanged(); } void VectorTab::readFromSourceClicked() { if (_dataVectorGroup->isChecked()) setVectorMode(DataVector); else setVectorMode(GeneratedVector); emit sourceChanged(); } void VectorTab::hideGeneratedOptions() { _generatedVectorGroup->setVisible(false); _dataVectorGroup->setCheckable(false); _dataVectorGroup->setTitle(""); _dataVectorGroup->setFlat(true); int top_margin; _dataVectorGroup->layout()->getContentsMargins(NULL,&top_margin,NULL,NULL); _dataVectorGroup->layout()->setContentsMargins(0,top_margin,0,0); } void VectorTab::hideDataOptions() { _dataVectorGroup->setVisible(false); _dataRange->setVisible(false); _generatedVectorGroup->setCheckable(false); _generatedVectorGroup->setTitle(""); _generatedVectorGroup->setFlat(true); int top_margin; _generatedVectorGroup->layout()->getContentsMargins(NULL,&top_margin,NULL,NULL); _generatedVectorGroup->layout()->setContentsMargins(0,top_margin,0,0); } void VectorTab::clearTabValues() { _numberOfSamples->clear(); _from->clear(); _to->clear(); _dataRange->clearValues(); } void VectorTab::enableSingleEditOptions(bool enabled) { _dataVectorGroup->setEnabled(enabled); } void VectorTab::sourceValid(QString filename, int requestID) { if (_requestID != requestID) { return; } _valid = true; _dataSource = DataSourcePluginManager::findOrLoadSource(_store, filename); _field->setEnabled(true); _dataSource->readLock(); _field->addItems(_dataSource->vector().list()); if (!_initField.isEmpty()) { setField(_initField); } _field->setEditable(!_dataSource->vector().isListComplete()); _configure->setEnabled(_dataSource->hasConfigWidget() && (_mode == DataVector)); updateUpdateBox(); updateIndexList(_dataSource); _dataSource->unlock(); validating = false; _store->cleanUpDataSourceList(); _field->setEnabled(_mode == DataVector); emit sourceChanged(); } void VectorTab::fileNameChanged(const QString &file) { _field->clear(); _field->setEnabled(false); _configure->setEnabled(false); _valid = false; clearIndexList(); emit sourceChanged(); _requestID += 1; ValidateDataSourceThread *validateDSThread = new ValidateDataSourceThread(file, _requestID); connect(validateDSThread, SIGNAL(dataSourceValid(QString,int)), this, SLOT(sourceValid(QString,int))); validating = true; QThreadPool::globalInstance()->start(validateDSThread); } void VectorTab::showConfigWidget() { QPointer dialog = new DataSourceConfigureDialog(dataDialog()->editMode(), _dataSource, this); if ( dialog->exec() == QDialog::Accepted ) { fileNameChanged(_dataSource->fileName()); } delete dialog; } VectorDialog::VectorDialog(ObjectPtr dataObject, QWidget *parent) : DataDialog(dataObject, parent, false) { if (editMode() == Edit) setWindowTitle(tr("Edit Vector")); else setWindowTitle(tr("New Vector")); Q_ASSERT(_document); _vectorTab = new VectorTab(_document->objectStore(), this); addDataTab(_vectorTab); if (editMode() == Edit) { configureTab(dataObject); } else { configureTab(0); } connect(_vectorTab, SIGNAL(sourceChanged()), this, SLOT(updateButtons())); connect(_vectorTab, SIGNAL(fieldChanged()), this, SLOT(updateButtons())); connect(this, SIGNAL(editMultipleMode()), this, SLOT(editMultipleMode())); connect(this, SIGNAL(editSingleMode()), this, SLOT(editSingleMode())); connect(_vectorTab, SIGNAL(modified()), this, SLOT(modified())); connect(_vectorTab, SIGNAL(destroyed()), kstApp->mainWindow(), SLOT(cleanUpDataSourceList())); + connect(_vectorTab->dataRange(), SIGNAL(modified()), this, SLOT(updateButtons())); + updateButtons(); } VectorDialog::~VectorDialog() { } void VectorDialog::editMultipleMode() { _vectorTab->enableSingleEditOptions(false); _vectorTab->clearTabValues(); } void VectorDialog::editSingleMode() { _vectorTab->enableSingleEditOptions(true); configureTab(dataObject()); } void VectorDialog::updateButtons() { bool valid = _vectorTab->vectorMode() == VectorTab::GeneratedVector || !_vectorTab->field().isEmpty(); - // FIXME: add stricter validity testing. + + valid &= _vectorTab->dataRange()->rangeIsValid(); + _buttonBox->button(QDialogButtonBox::Ok)->setEnabled(valid); _buttonBox->button(QDialogButtonBox::Apply)->setEnabled(valid); } void VectorDialog::configureTab(ObjectPtr vector) { if (!vector) { _vectorTab->dataRange()->loadWidgetDefaults(); _vectorTab->setFile(dialogDefaults().value("vector/datasource",_vectorTab->file()).toString()); _vectorTab->setFrom(dialogDefaults().value("genVector/min",-10).toInt()); _vectorTab->setTo(dialogDefaults().value("genVector/max",10).toInt()); _vectorTab->setNumberOfSamples(dialogDefaults().value("genVector/length",1000).toInt()); _vectorTab->setVectorMode((VectorTab::VectorMode)dialogDefaults().value("genVector/vectorType",VectorTab::GeneratedVector).toInt()); // FIXME: should be sticky } else if (DataVectorPtr dataVector = kst_cast(vector)) { _vectorTab->setVectorMode(VectorTab::DataVector); _vectorTab->setFile(dataVector->dataSource()->fileName()); _vectorTab->setDataSource(dataVector->dataSource()); _vectorTab->updateIndexList(dataVector->dataSource()); _vectorTab->setField(dataVector->field()); _vectorTab->dataRange()->setRangeUnits(dataVector->rangeUnits()); if ( _vectorTab->dataRange()->rangeUnitsIndex()>0) { double frame_per_index = dataVector->dataSource()->framePerIndex(dataVector->startUnits()); if (frame_per_index == 0) { frame_per_index = 1.0; } _vectorTab->dataRange()->setRange(dataVector->numFrames()/frame_per_index); } else { _vectorTab->dataRange()->setRange(dataVector->numFrames()); } _vectorTab->dataRange()->setStartUnits(dataVector->startUnits()); if (_vectorTab->dataRange()->startUnitsIndex()>0) { _vectorTab->dataRange()->setStart(dataVector->dataSource()->frameToIndex(dataVector->startFrame(),dataVector->startUnits())); } else { _vectorTab->dataRange()->setStart(dataVector->startFrame()); } _vectorTab->dataRange()->setCountFromEnd(dataVector->countFromEOF()); _vectorTab->dataRange()->setReadToEnd(dataVector->readToEOF()); _vectorTab->dataRange()->setSkip(dataVector->skip()); _vectorTab->dataRange()->setDoSkip(dataVector->doSkip()); _vectorTab->dataRange()->setDoFilter(dataVector->doAve()); _vectorTab->hideGeneratedOptions(); if (_editMultipleWidget) { DataVectorList objects = _document->objectStore()->getObjects(); _editMultipleWidget->clearObjects(); foreach(DataVectorPtr object, objects) { _editMultipleWidget->addObject(object->Name(), object->descriptionTip()); } } } else if (GeneratedVectorPtr generatedVector = kst_cast(vector)) { _vectorTab->setVectorMode(VectorTab::GeneratedVector); _vectorTab->setFrom(generatedVector->min()); _vectorTab->setTo(generatedVector->max()); _vectorTab->setNumberOfSamples(generatedVector->length()); _vectorTab->hideDataOptions(); if (_editMultipleWidget) { DataVectorList objects = _document->objectStore()->getObjects(); _editMultipleWidget->clearObjects(); foreach(DataVectorPtr object, objects) { _editMultipleWidget->addObject(object->Name(), object->descriptionTip()); } } } } ObjectPtr VectorDialog::createNewDataObject() { switch(_vectorTab->vectorMode()) { case VectorTab::DataVector: dialogDefaults().setValue("genVector/vectorType", VectorTab::DataVector); return createNewDataVector(); case VectorTab::GeneratedVector: dialogDefaults().setValue("genVector/vectorType", VectorTab::GeneratedVector); return createNewGeneratedVector(); default: return 0; } } void VectorTab::updateIndexList(DataSourcePtr dataSource) { dataRange()->updateIndexList(dataSource->indexFields()); } void VectorTab::clearIndexList() { dataRange()->clearIndexList(); } ObjectPtr VectorDialog::createNewDataVector() { DataSourcePtr dataSource = _vectorTab->dataSource(); //FIXME better validation than this please... if (!dataSource) return 0; // Hook the progress signal when loading a new datasource to get feedback in case it takes long connect(dataSource, SIGNAL(progress(int,QString)), kstApp->mainWindow(), SLOT(updateProgress(int,QString))); dataSource->vector().prepareRead(1); const QString field = _vectorTab->field(); const DataRange *dataRange = _vectorTab->dataRange(); Q_ASSERT(_document && _document->objectStore()); DataVectorPtr vector = _document->objectStore()->createObject(); double startOffset = dataRange->start(); double rangeCount = dataRange->range(); if ((dataRange->_startUnits->currentIndex() != 0) && (!dataRange->countFromEnd())) { startOffset = _vectorTab->dataSource()->indexToFrame(dataRange->start(), dataRange->startUnits()); } if ((dataRange->_rangeUnits->currentIndex() != 0) && (!dataRange->readToEnd())) { rangeCount = dataRange->range()*_vectorTab->dataSource()->framePerIndex(dataRange->rangeUnits()); } vector->writeLock(); vector->change(dataSource, field, dataRange->countFromEnd() ? -1 : int(startOffset), dataRange->readToEnd() ? -1 : int(rangeCount), dataRange->skip(), dataRange->doSkip(), dataRange->doFilter()); vector->setRangeUnits(dataRange->rangeUnits()); vector->setStartUnits(dataRange->startUnits()); if (DataDialog::tagStringAuto()) { vector->setDescriptiveName(QString()); } else { vector->setDescriptiveName(DataDialog::tagString()); } setDataVectorDefaults(vector); _vectorTab->dataRange()->setWidgetDefaults(); vector->registerChange(); vector->unlock(); _dataObjectName = vector->Name(); //UpdateServer::self()->requestUpdateSignal(); return vector; } ObjectPtr VectorDialog::createNewGeneratedVector() { const qreal from = _vectorTab->from(); const qreal to = _vectorTab->to(); const int numberOfSamples = _vectorTab->numberOfSamples(); Q_ASSERT(_document && _document->objectStore()); GeneratedVectorPtr vector = _document->objectStore()->createObject(); vector->changeRange(from, to, numberOfSamples); setGenVectorDefaults(vector); if (DataDialog::tagStringAuto()) { vector->setDescriptiveName(QString()); } else { vector->setDescriptiveName(DataDialog::tagString()); } _dataObjectName = vector->Name(); _vectorTab->setDataSource(0L); _document->objectStore()->cleanUpDataSourceList(); //UpdateServer::self()->requestUpdateSignal(); return vector; } ObjectPtr VectorDialog::editExistingDataObject() const { if (DataVectorPtr dataVector = kst_cast(dataObject())) { if (editMode() == EditMultiple) { const DataRange *dataRange = _vectorTab->dataRange(); QStringList objects = _editMultipleWidget->selectedObjects(); foreach (const QString &objectName, objects) { DataVectorPtr vector = kst_cast(_document->objectStore()->retrieveObject(objectName)); if (vector) { int start = dataRange->startDirty() ? dataRange->start() : vector->startFrame(); int range = dataRange->rangeDirty() ? dataRange->range() : vector->numFrames(); int skip = dataRange->skipDirty() ? dataRange->skip() : vector->skip(); if (dataRange->countFromEndDirty()) { start = dataRange->countFromEnd() ? -1 : dataRange->start(); range = dataRange->readToEnd() ? -1 : dataRange->range(); } bool doSkip = dataRange->doSkipDirty() ? dataRange->doSkip() : vector->doSkip(); bool doAve = dataRange->doFilterDirty() ? dataRange->doFilter() : vector->doAve(); vector->writeLock(); vector->changeFrames(start, range, skip, doSkip, doAve); vector->registerChange(); vector->unlock(); } } } else { const DataSourcePtr dataSource = _vectorTab->dataSource(); //FIXME better validation than this please... if (!dataSource) return 0; const QString field = _vectorTab->field(); const DataRange *dataRange = _vectorTab->dataRange(); double startOffset = dataRange->start(); double rangeCount = dataRange->range(); if ((dataRange->_startUnits->currentIndex() != 0) && (!dataRange->countFromEnd())) { startOffset = _vectorTab->dataSource()->indexToFrame(dataRange->start(), dataRange->startUnits()); } if ((dataRange->_rangeUnits->currentIndex() != 0) && (!dataRange->readToEnd())) { rangeCount = dataRange->range()*_vectorTab->dataSource()->framePerIndex(dataRange->rangeUnits()) + 0.0001; } dataVector->writeLock(); dataVector->change(dataSource, field, dataRange->countFromEnd() ? -1 : int(startOffset), dataRange->readToEnd() ? -1 : int(rangeCount), dataRange->skip(), dataRange->doSkip(), dataRange->doFilter()); if (DataDialog::tagStringAuto()) { dataVector->setDescriptiveName(QString()); } else { dataVector->setDescriptiveName(DataDialog::tagString()); } dataVector->registerChange(); dataVector->unlock(); setDataVectorDefaults(dataVector); _vectorTab->dataRange()->setWidgetDefaults(); } } else if (GeneratedVectorPtr generatedVector = kst_cast(dataObject())) { if (editMode() == EditMultiple) { QStringList objects = _editMultipleWidget->selectedObjects(); foreach (const QString &objectName, objects) { GeneratedVectorPtr vector = kst_cast(_document->objectStore()->retrieveObject(objectName)); if (vector) { double min = _vectorTab->fromDirty() ? _vectorTab->from() : vector->min(); double max = _vectorTab->toDirty() ? _vectorTab->to() : vector->max(); double length = _vectorTab->numberOfSamplesDirty() ? _vectorTab->numberOfSamples() : vector->length(); vector->writeLock(); vector->changeRange(min, max, length); vector->registerChange(); vector->unlock(); } } } else { const qreal from = _vectorTab->from(); const qreal to = _vectorTab->to(); const int numberOfSamples = _vectorTab->numberOfSamples(); generatedVector->writeLock(); generatedVector->changeRange(from, to, numberOfSamples); if (DataDialog::tagStringAuto()) { generatedVector->setDescriptiveName(QString()); } else { generatedVector->setDescriptiveName(DataDialog::tagString()); } generatedVector->registerChange(); generatedVector->unlock(); setGenVectorDefaults(generatedVector); } } return dataObject(); } void VectorDialog::waitForValidation() { while (_vectorTab->validating && (_vectorTab->vectorMode() == VectorTab::DataVector)) { Sleep::ms(10); QApplication::processEvents(); } } } // vim: ts=2 sw=2 et diff --git a/src/widgets/datarange.cpp b/src/widgets/datarange.cpp index 06ae7450..eea82795 100644 --- a/src/widgets/datarange.cpp +++ b/src/widgets/datarange.cpp @@ -1,364 +1,372 @@ /*************************************************************************** * * * 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 "datarange.h" #include "dialogdefaults.h" namespace Kst { DataRange::DataRange(QWidget *parent) : QWidget(parent) { setupUi(this); connect(_countFromEnd, SIGNAL(toggled(bool)), this, SLOT(countFromEndChanged())); connect(_readToEnd, SIGNAL(toggled(bool)), this, SLOT(readToEndChanged())); connect(_doSkip, SIGNAL(toggled(bool)), this, SLOT(doSkipChanged())); connect(_start, SIGNAL(textEdited(QString)), this, SLOT(startChanged())); connect(_range, SIGNAL(textEdited(QString)), this, SLOT(rangeChanged())); connect(_last, SIGNAL(textEdited(QString)), this, SLOT(lastChanged())); connect(_skip, SIGNAL(valueChanged(int)), this, SIGNAL(modified())); connect(_doFilter, SIGNAL(toggled(bool)), this, SIGNAL(modified())); connect(_countFromEnd, SIGNAL(toggled(bool)), this, SIGNAL(modified())); connect(_readToEnd, SIGNAL(toggled(bool)), this, SIGNAL(modified())); connect(_doSkip, SIGNAL(toggled(bool)), this, SIGNAL(modified())); connect(_startUnits, SIGNAL(currentIndexChanged(int)), this, SLOT(unitsChanged())); connect(_rangeUnits, SIGNAL(currentIndexChanged(int)), this, SLOT(unitsChanged())); _controlField0 = Range; _controlField1 = Start; } DataRange::~DataRange() { } void DataRange::clearValues() { _start->clear(); _range->clear(); _skip->clear(); _doFilter->setCheckState(Qt::PartiallyChecked); _readToEnd->setCheckState(Qt::PartiallyChecked); _doSkip->setCheckState(Qt::PartiallyChecked); } qreal DataRange::start() const { return _start->text().toDouble(); } bool DataRange::startDirty() const { return !_start->text().isEmpty(); } void DataRange::setStart(qreal start, bool callUpdateFields) { _start->setText(QString::number(start, 'g', 12)); if (callUpdateFields) { updateFields(None); } } qreal DataRange::last() const { return _last->text().toDouble(); } bool DataRange::lastDirty() const { return !_last->text().isEmpty(); } void DataRange::setLast(qreal last, bool callUpdateFields) { _last->setText(QString::number(last, 'g', 12)); if (callUpdateFields) { updateFields(None); } } void DataRange::clearIndexList() { _startUnits->clear(); _rangeUnits->clear(); } void DataRange::updateIndexList(const QStringList &indexFields) { _startUnits->clear(); _startUnits->addItems(indexFields); setStartUnits(_requestedStartUnits); _rangeUnits->clear(); _rangeUnits->addItems(indexFields); setRangeUnits(_requestedRangeUnits); } QString DataRange::startUnits() const { return _startUnits->currentText(); } int DataRange::startUnitsIndex() const { return _startUnits->currentIndex(); } void DataRange::setStartUnits(const QString &startUnits) { _requestedStartUnits = startUnits; int i = _startUnits->findText(startUnits); if (i>=0) { _startUnits->setCurrentIndex(i); } } qreal DataRange::range() const { return _range->text().toDouble(); } int DataRange::rangeUnitsIndex() const { return _rangeUnits->currentIndex(); } bool DataRange::rangeDirty() const { return !_range->text().isEmpty(); } void DataRange::setRange(qreal range, bool callUpdateFields) { _range->setText(QString::number(range)); if (callUpdateFields) { updateFields(None); } } QString DataRange::rangeUnits() const { return _rangeUnits->currentText(); } void DataRange::setRangeUnits(const QString &rangeUnits) { _requestedRangeUnits = rangeUnits; int i = _rangeUnits->findText(rangeUnits); if (i>=0) { _rangeUnits->setCurrentIndex(i); } else { _rangeUnits->setCurrentIndex(0); } } int DataRange::skip() const { return _skip->value(); } bool DataRange::skipDirty() const { return !_skip->text().isEmpty(); } void DataRange::setSkip(int skip) { _skip->setValue(skip); } bool DataRange::countFromEnd() const { return _countFromEnd->isChecked(); } void DataRange::setCountFromEnd(bool countFromEnd) { _countFromEnd->setChecked(countFromEnd); updateFields(None); } bool DataRange::countFromEndDirty() const { return _readToEnd->checkState() == Qt::PartiallyChecked; } bool DataRange::readToEnd() const { return _readToEnd->isChecked(); } bool DataRange::readToEndDirty() const { return _readToEnd->checkState() == Qt::PartiallyChecked; } void DataRange::setReadToEnd(bool readToEnd) { _readToEnd->setChecked(readToEnd); updateFields(None); } bool DataRange::doSkip() const { return _doSkip->isChecked(); } bool DataRange::doSkipDirty() const { return _doSkip->checkState() == Qt::PartiallyChecked; } void DataRange::setDoSkip(bool doSkip) { _doSkip->setChecked(doSkip); } bool DataRange::doFilter() const { return _doFilter->isChecked(); } bool DataRange::doFilterDirty() const { return _doFilter->checkState() == Qt::PartiallyChecked; } void DataRange::setDoFilter(bool doFilter) { _doFilter->setChecked(doFilter); } void DataRange::countFromEndChanged() { if (countFromEnd()) { setReadToEnd(false); } updateFields(None); } void DataRange::readToEndChanged() { if (readToEnd()) { setCountFromEnd(false); } updateFields(None); } void DataRange::unitsChanged() { updateFields(None); } void DataRange::doSkipChanged() { _skip->setEnabled(doSkip()); _doFilter->setEnabled(doSkip()); } // control field logic: // the last one changed, other than this one, should be the control field // do we need a history? // F0 R -> L // F0 L -> R // R L -> F0 // R F0 -> L void DataRange::startChanged() { updateFields(Start); emit modified(); } void DataRange::lastChanged() { updateFields(Last); emit modified(); } void DataRange::rangeChanged() { updateFields(Range); emit modified(); } void DataRange::updateFields(ControlField cf) { bool enable_last = (_rangeUnits->currentIndex() == _startUnits->currentIndex()); enable_last &= !readToEnd(); enable_last &= !countFromEnd(); _last->setEnabled(enable_last); _lastLabel->setEnabled(enable_last); _start->setEnabled(!countFromEnd()); _startLabel->setEnabled(!countFromEnd()); _startUnits->setEnabled(!countFromEnd()); _range->setEnabled(!readToEnd()); _rangeLabel->setEnabled(!readToEnd()); _rangeUnits->setEnabled(!readToEnd()); if ((cf!=None) && (cf != _controlField1)) { _controlField0 = _controlField1; _controlField1 = cf; } // don't do anything if it wouldn't make sense to. if (readToEnd() || countFromEnd()) { return; } if (startUnits() != (rangeUnits())) { return; } if ((_controlField0 != Start) && (_controlField1 != Start)) { _start->setText(QString::number(last() - range() + 1, 'g', 12)); } else if ((_controlField0 != Last) && (_controlField1 != Last)) { _last->setText(QString::number(start() + range() - 1, 'g', 12)); } else if ((_controlField0 != Range) && (_controlField1 != Range)) { _range->setText(QString::number(last() - start() + 1, 'g', 12)); } } void DataRange::setWidgetDefaults() { //FIXME Do we need a V->readLock() here? dialogDefaults().setValue("vector/range", range()); dialogDefaults().setValue("vector/start", start()); dialogDefaults().setValue("vector/countFromEnd", countFromEnd()); dialogDefaults().setValue("vector/readToEnd", readToEnd()); dialogDefaults().setValue("vector/skip", skip()); dialogDefaults().setValue("vector/doSkip", doSkip()); dialogDefaults().setValue("vector/doAve", doFilter()); dialogDefaults().setValue("vector/rangeUnits", rangeUnits()); dialogDefaults().setValue("vector/startUnits", rangeUnits()); } void DataRange::loadWidgetDefaults() { setRange(dialogDefaults().value("vector/range", 1).toInt()); setStart(dialogDefaults().value("vector/start", 0).toInt()); setCountFromEnd(dialogDefaults().value("vector/countFromEnd",false).toBool()); setReadToEnd(dialogDefaults().value("vector/readToEnd",true).toBool()); setSkip(dialogDefaults().value("vector/skip", 0).toInt()); setDoSkip(dialogDefaults().value("vector/doSkip", false).toBool()); setDoFilter(dialogDefaults().value("vector/doAve",false).toBool()); setRangeUnits(dialogDefaults().value("vector/rangeUnits",tr("frames")).toString()); setStartUnits(dialogDefaults().value("vector/startUnits",tr("frames")).toString()); } +bool DataRange::rangeIsValid() { + if (readToEnd()) { + return true; + } else { + return (range()>1); + } +} + } // vim: ts=2 sw=2 et diff --git a/src/widgets/datarange.h b/src/widgets/datarange.h index fc72fb59..a28e384e 100644 --- a/src/widgets/datarange.h +++ b/src/widgets/datarange.h @@ -1,107 +1,108 @@ /*************************************************************************** * * * 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 DATARANGE_H #define DATARANGE_H #include #include "ui_datarange.h" #include "kstwidgets_export.h" namespace Kst { //FIXME Need to add time related methods/functionality class KSTWIDGETS_EXPORT DataRange : public QWidget, public Ui::DataRange { Q_OBJECT public: explicit DataRange(QWidget *parent = 0); virtual ~DataRange(); qreal start() const; bool startDirty() const; void setStart(qreal start, bool callUpdateFields = true); QString startUnits() const; int startUnitsIndex() const; void setStartUnits(const QString &startUnits); qreal range() const; bool rangeDirty() const; void setRange(qreal range, bool callUpdateFields = true); qreal last() const; bool lastDirty() const; void setLast(qreal last, bool callUpdateFields = true); void updateIndexList(const QStringList &indexFields); void clearIndexList(); //FIXME Probably should be an enum... QString rangeUnits() const; int rangeUnitsIndex() const; void setRangeUnits(const QString &rangeUnits); int skip() const; bool skipDirty() const; void setSkip(int skip); bool countFromEnd() const; bool countFromEndDirty() const; void setCountFromEnd(bool countFromEnd); bool readToEnd() const; bool readToEndDirty() const; void setReadToEnd(bool readToEnd); bool doSkip() const; bool doSkipDirty() const; void setDoSkip(bool doSkip); bool doFilter() const; bool doFilterDirty() const; void setDoFilter(bool doFilter); void clearValues(); void setWidgetDefaults(); void loadWidgetDefaults(); - + + bool rangeIsValid(); enum ControlField {Start, Last, Range, None}; void updateFields(ControlField cf); Q_SIGNALS: void modified(); private Q_SLOTS: void countFromEndChanged(); void readToEndChanged(); void doSkipChanged(); void startChanged(); void lastChanged(); void rangeChanged(); void unitsChanged(); private: QString _requestedRangeUnits; QString _requestedStartUnits; ControlField _controlField0; ControlField _controlField1; }; } #endif // vim: ts=2 sw=2 et