Ejemplo n.º 1
0
/*! table is the database table name
 colName is the name of the column you wish to get all the values for
 values is a list of pointers to QVariants that will be modified with the retrived values.
 (Note that the const and & arguments are designed to prevent memory copies, so this should be fast.)
 Return value: returns the list of values
*/
QVariantList AMDatabase::retrieve(const QString& table, const QString& colName)
{
	QVariantList values;	// return value

	/// \todo sanitize more than this...
	if(table.isEmpty()) {
		AMErrorMon::report(AMErrorReport(this, AMErrorReport::Alert, AMDATABASE_MISSING_TABLE_NAME_IN_RETRIEVE, "Could not search the database. (Missing the table name.)"));
		return values;
	}

	// create a query on our database connection:
	QSqlQuery q( qdb() );

	// Prepare the query.
	q.prepare(QString("SELECT %1 FROM %2").arg(colName).arg(table));

	// run query. Did it succeed?
	if(!execQuery(q)) {
		q.finish();	// make sure that sqlite lock is released before emitting signals
		AMErrorMon::report(AMErrorReport(this, AMErrorReport::Alert, AMDATABASE_RETRIEVE_QUERY_FAILED, QString("database retrieve failed. Could not execute query (%1). The SQL reply was: %2").arg(q.executedQuery()).arg(q.lastError().text())));
		return values;
	}

	while(q.next())
		values << q.value(0);

	q.finish();	// make sure that sqlite lock is released before emitting signals
	// otherwise: didn't find this column.  That's normal if it's not there, just return empty list
	return values;
}
Ejemplo n.º 2
0
QVariant AMDatabase::retrieve(int id, const QString& table, const QString& colName)
{
	/// \todo sanitize more than this...
	if(table.isEmpty()) {
		AMErrorMon::report(AMErrorReport(this, AMErrorReport::Alert, -10, "Could not search the database. (Missing the table name.)"));
		return false;
	}

	// create a query on our database connection:
	QSqlQuery q( qdb() );


	/// Prepare the query. \todo: sanitize column names and table name. (Can't use binding because it's not an expression here)
	q.prepare(QString("SELECT %1 FROM %2 WHERE id = ?").arg(colName).arg(table));
	q.bindValue(0,id);

	// run query. Did it succeed?
	if(!execQuery(q)) {
		q.finish();	// make sure that sqlite lock is released before emitting signals
		AMErrorMon::report(AMErrorReport(this, AMErrorReport::Alert, -4, QString("database retrieve failed. Could not execute query (%1). The SQL reply was: %2").arg(q.executedQuery()).arg(q.lastError().text())));
		return false;
	}
	// If we found a record at this id:
	if(q.first()) {
		return q.value(0);
	}
	// else: didn't find this id.  That's normal if it's not there, just return null QVariant.
	else {
		return QVariant();
	}

}
Ejemplo n.º 3
0
/// delete all objects/rows in \c tableName that meet a certain condition. \c whereClause is a string suitable for appending after an SQL "WHERE" term. Returns the number of rows deleted, or 0 if it fails to delete any.
int AMDatabase::deleteRows(const QString& tableName, const QString& whereClause) {

	/// \todo sanitize more than this...
	if(tableName.isEmpty() || whereClause.isEmpty()) {
		AMErrorMon::report(AMErrorReport(this, AMErrorReport::Alert, -10, "Could not update the database. (Missing the table name, column, or WHERE clause.)"));
		return 0;
	}

	QSqlDatabase db = qdb();

	if(!db.isOpen()) {
		AMErrorMon::report(AMErrorReport(this, AMErrorReport::Alert, -2, "Could not update the database. (Database is not open.)"));
		return 0;
	}

	// Prepare the query (todo: sanitize table name)
	QSqlQuery query(db);
	query.prepare(QString("DELETE FROM %1 WHERE %2").arg(tableName).arg(whereClause));

	// Run query. Query failed?
	if(!execQuery(query)) {
		query.finish();	// make sure that sqlite lock is released before emitting signals
		AMErrorMon::report(AMErrorReport(this, AMErrorReport::Alert, -3, QString("Failed to delete the database object(s). Could not execute the query (%1). The SQL reply was: %2").arg(query.executedQuery()).arg(query.lastError().text())));
		return 0;
	}

	int numRowsAffected = query.numRowsAffected();

	query.finish();	// make sure that sqlite lock is released before emitting signals
	emit removed(tableName, -1);

	// Query succeeded.
	return numRowsAffected;
}
Ejemplo n.º 4
0
/*! id is the object's row in the database.
 table is the database table name
 colNames is a list of the column names that the values will be retrieved from
 values is a list of pointers to QVariants that will be modified with the retrived values.
 (Note that the const and & arguments are designed to prevent memory copies, so this should be fast.)
 Return value: returns true on success.
*/
QVariantList AMDatabase::retrieve(int id, const QString& table, const QStringList& colNames)
{
	QVariantList values;	// return value

	/// \todo sanitize more than this...
	if(table.isEmpty()) {
		AMErrorMon::report(AMErrorReport(this, AMErrorReport::Alert, -10, "Could not search the database. (Missing the table name.)"));
		return values;
	}

	// create a query on our database connection:
	QSqlQuery q( qdb() );

	// Create the list of columns:
	QString cols = colNames.join(", ");	// this will become something like "name, number, sampleName, comments, startTime"
	// Prepare the query. Todo: sanitize column names and table name. (Can't use binding because it's not an expression here)
	q.prepare(QString("SELECT %1 FROM %2 WHERE id = ?").arg(cols).arg(table));
	q.bindValue(0,id);

	// run query. Did it succeed?
	if(!execQuery(q)) {
		q.finish();	// make sure that sqlite lock is released before emitting signals
		AMErrorMon::report(AMErrorReport(this, AMErrorReport::Alert, -4, QString("database retrieve failed. Could not execute query (%1). The SQL reply was: %2").arg(q.executedQuery()).arg(q.lastError().text())));
		return values;
	}
	// If we found a record at this id:
	if(q.first()) {
		// copy columns to return values:
		for(int i=0; i<colNames.count(); i++)
			values << q.value(i);
	}
	q.finish();	// make sure that sqlite lock is released before emitting signals
	// otherwise: didn't find this id.  That's normal if it's not there, just return empty list
	return values;
}
Ejemplo n.º 5
0
/// changing single values in the database, at row \c id.
bool AMDatabase::update(int id, const QString& table, const QString& column, const QVariant& value) {

	QSqlDatabase db = qdb();

	if(!db.isOpen()) {
		AMErrorMon::report(AMErrorReport(this, AMErrorReport::Alert, -2, "Could not save to database. (Database is not open.)"));
		return false;
	}

	// Prepare the query. Todo: sanitize column names and table name. (Can't use binding because it's not an expression here)
	QSqlQuery query(db);
	query.prepare(QString("UPDATE %1 SET %2 = ? WHERE id = ?").arg(table).arg(column));
	query.bindValue(0, value);
	query.bindValue(1, QVariant(id));

	// Run query. Query failed?
	if(!execQuery(query)) {
		query.finish();	// make sure that sqlite lock is released before emitting signals
		AMErrorMon::report(AMErrorReport(this, AMErrorReport::Alert, -3, QString("database update failed. Could not execute query (%1). The SQL reply was: %2").arg(query.executedQuery()).arg(query.lastError().text())));
		return false;
	}
	// Query succeeded.
	query.finish();	// make sure that sqlite lock is released before emitting signals
	emit updated(table, id);
	return true;

}
Ejemplo n.º 6
0
/// Changing single values in the database (where the id isn't known).  Will update all rows based on the condition specified. \c whereClause is a string suitable for appending after an SQL "WHERE" term.  Will set the value in \c dataColumn to \c dataValue.
bool AMDatabase::update(const QString& tableName, const QString& whereClause, const QString& dataColumn, const QVariant& dataValue) {

	/// \todo sanitize more than this...
	if(whereClause.isEmpty() || dataColumn.isEmpty() || tableName.isEmpty()) {
		AMErrorMon::report(AMErrorReport(this, AMErrorReport::Alert, -10, "Could not complete the database update; missing the table name, column, or WHERE clause."));
		return false;
	}

	QSqlDatabase db = qdb();

	if(!db.isOpen()) {
		AMErrorMon::report(AMErrorReport(this, AMErrorReport::Alert, -2, "Could not save to the database. (Database is not open.)"));
		return false;
	}

	// Prepare the query. Todo: sanitize column names and table name. (Can't use binding because it's not an expression here)
	QSqlQuery query(db);
	query.prepare(QString("UPDATE %1 SET %2 = ? WHERE %3").arg(tableName).arg(dataColumn).arg(whereClause));
	query.bindValue(0, dataValue);

	// Run query. Query failed?
	if(!execQuery(query)) {
		query.finish();	// make sure that sqlite lock is released before emitting signals
		AMErrorMon::report(AMErrorReport(this, AMErrorReport::Alert, -3, QString("Failed to update the database. Could not execute the query (%1). The SQL reply was: %2").arg(query.executedQuery()).arg(query.lastError().text())));
		return false;
	}
	// Query succeeded.
	query.finish();	// make sure that sqlite lock is released before emitting signals
	emit updated(tableName, -1);
	return true;

}
Ejemplo n.º 7
0
// register a new class with the database system. This is all you need to do enable an AMDbObect subclass. Returns false if the initialization failed; true if it was completed successfully, or if the object is already registered.
bool AMDbObjectSupport::registerClass(const QMetaObject* mo) {

	QWriteLocker wl(&registryMutex_);

	// is this a subclass of AMDbObject? (Or an AMDbObject itself?)
	if(!inheritsAMDbObject(mo)){
		AMErrorMon::report(AMErrorReport(this, AMErrorReport::Alert, AMDBOBJECTSUPPORT_CANNOT_REGISTER_CLASS_NOT_DBOBJECT, "Could not register class to database, it does not inherit AMDbObject. Please report this problem to the Acquaman developers."));
		return false;	// can't register a non AMDbObject subclass.
	}

	// is it already registered? return true.
	QString className(mo->className());
	if(registeredClasses_.contains(className)) {
		AMErrorMon::report(AMErrorReport(0, AMErrorReport::Debug, AMDBOBJECTSUPPORT_CLASS_ALREADY_REGISTERED, QString("Database Support: The class '%1' has already been registered in the database. Skipping duplicate registration.").arg(className)));
		return true;
	}

	AMDbObjectInfo newInfo(mo);

	bool success = true;
	QSetIterator<AMDatabase*> iDatabases(registeredDatabases_);
	while(iDatabases.hasNext()) {
		success = success && getDatabaseReadyForClass(iDatabases.next(), newInfo);
	}

	if(success) {
		registeredClasses_.insert(className, newInfo);
		registeredClassesInOrder_ << newInfo;
		return true;
	}
	else{
		AMErrorMon::report(AMErrorReport(this, AMErrorReport::Alert, AMDBOBJECTSUPPORT_CANNOT_REGISTER_CLASS_CANNOT_READY_DATABASE, "Could not register class to database, could not make the database ready for this class. Please report this problem to the Acquaman developers."));
		return false;
	}
}
Ejemplo n.º 8
0
/*! Re-implemented from AMDbObject::loadFromDb(), this version also loads the scan's raw data if autoLoadData() is set to true, and the stored filePath doesn't match the existing filePath()*/
bool AMScan::loadFromDb(AMDatabase* db, int sourceId) {

    QString oldFilePath = filePath();

    // always call the base class implementation first. This retrieves/loads all the base-class properties.
    // return false if it fails:
    if( !AMDbObject::loadFromDb(db, sourceId)) {

        AMErrorMon::report(AMErrorReport(this, AMErrorReport::Debug, -482, "AMScan: Loading from database failed."));
        return false;
    }
    // In auto-load data mode: If the file path is different than the old one, clear and reload the raw data.
    if( !currentlyScanning() && autoLoadData() && filePath() != oldFilePath ) {
        if(!loadData()) {

            AMErrorMon::report(AMErrorReport(this, AMErrorReport::Debug, -483, "AMScan: Loading data failed."));
            return false;
        }
    }

    if(nameDictionary_) {
        nameDictionary_->deleteLater();
        nameDictionary_ = 0;
    }
    nameDictionary_ = new AMScanDictionary(this);

    return true;
}
Ejemplo n.º 9
0
bool AMCDFv1FileLoaderPlugin::load(AMScan *scan, const QString &userDataFolder, AMErrorMon *errorMonitor){

	if(!scan)
		return false;

	QFileInfo sourceFileInfo(scan->filePath());
	if(sourceFileInfo.isRelative()){
		sourceFileInfo.setFile(userDataFolder + "/" + scan->filePath());
	}

	// for now, we create a new AMCDFDataStore by opening this CDF file in read-only mode.  If read-only is a problem in the future (ex: data sources writing to the data store for caching values) we'll need to adjust this strategy.
	AMCDFDataStore* ds = new AMCDFDataStore(sourceFileInfo.filePath(), false, true);
	if(!ds->isValid()) {
		delete ds;
		errorMonitor->exteriorReport(AMErrorReport(0, AMErrorReport::Serious, AMCDFV1FILELOADERPLUGIN_CANNOT_OPEN_FILE, QString("Could not open the CDF file at '%1'. It's possible that the file has been moved, or is corrupted.").arg(sourceFileInfo.filePath())));
		return false;
	}

	if(!scan->replaceRawDataStore(ds)) {
		delete ds;
		errorMonitor->exteriorReport(AMErrorReport(0, AMErrorReport::Serious, AMCDFV1FILELOADERPLUGIN_CANNOT_USE_FILE, QString("Could not use the CDF file at '%1' for the scan '%2': it does not contain the correct measurements for the data sources that should exist in this scan.").arg(sourceFileInfo.filePath()).arg(scan->fullName())));
		return false;
	}

	return true;
}
Ejemplo n.º 10
0
bool AMExporterGeneralAscii::isValidFor(const AMScan *scan, const AMExporterOption *iOption) const
{
	// wrong
	const AMExporterOptionGeneralAscii* option = qobject_cast<const AMExporterOptionGeneralAscii*>(iOption);
	if(!option) {
		AMErrorMon::report(AMErrorReport(this, AMErrorReport::Alert, -2, "Invalid options specified for the General Ascii Exporter. Please report this bug to the Acquaman developers."));
		return false;
	}

	if(!option->includeAllDataSources()) {	// if includeAllDataSources is set, don't care about required specifications.
		QStringList dataSources = option->dataSources();

		// missing a required data source
		for(int i=dataSources.count()-1; i>=0; i--) {
			if(option->isDataSourceRequired(i) &&
					scan->indexOfDataSource(dataSources.at(i)) == -1) {

				AMErrorMon::report(AMErrorReport(this,
												 AMErrorReport::Alert,
												 -3,
												 "Export failed: The scan '" % scan->fullName() % "' does not contain the required data set '" % dataSources.at(i) % "'."));
				return false;
			}
		}
	}

	return true;
}
Ejemplo n.º 11
0
void AMControlMoveAction::startImplementation() {
	const AMControlInfo& setpoint = *(controlMoveInfo()->controlInfo());

	// lookup the control we need to use to run this
	control_ = getControlForAction(setpoint);

	// Must have a control, and it must be able to move.
	if(!control_) {
		AMErrorMon::report(AMErrorReport(this,
										 AMErrorReport::Alert,
										 -1,
										 QString("There was an error moving the control '%1' into position, because the control was not found. Please report this problem to the Acquaman developers.").arg(setpoint.name())));
		notifyFailed();
		return;
	}
	// check we can move...
	if(!control_->canMove()) {
		AMErrorMon::report(AMErrorReport(this,
										 AMErrorReport::Alert,
										 -2,
										 QString("There was an error moving the control '%1' into position, because the control was not connected and ready to move. Please report this problem to the beamline staff.")
										 .arg(control_->name())));
		notifyFailed();
		return;
	}

	// check that the destination is in range...
	if(control_->valueOutOfRange(controlMoveInfo()->isRelativeMove() ? control_->value()+setpoint.value() : setpoint.value())) {
		AMErrorMon::report(AMErrorReport(this,
										 AMErrorReport::Alert,
										 -3,
										 QString("There was an error moving the control '%1' into position, because the destination %2 %3 was outside its range. Please report this problem to the beamline staff.")
										 .arg(control_->name())
										 .arg(setpoint.value())
										 .arg(setpoint.units())));
		notifyFailed();
		return;
	}

	// connect to its moveSucceeded and moveFailed signals
	connect(control_, SIGNAL(moveStarted()), this, SLOT(onMoveStarted()));
	connect(control_, SIGNAL(moveReTargetted()), this, SLOT(onMoveStarted()));	// For controls that support allowsMovesWhileMoving(), they might already be moving when we request our move(). A moveReTargetted() signal from them also counts as a moveStarted() for us.
	connect(control_, SIGNAL(moveFailed(int)), this, SLOT(onMoveFailed(int)));
	connect(control_, SIGNAL(moveSucceeded()), this, SLOT(onMoveSucceeded()));

	// remember the start position:
	startPosition_ = control_->toInfo();

	// start the move:
	int failureExplanation;
	if(controlMoveInfo()->isRelativeMove())
		failureExplanation = control_->moveRelative(setpoint.value());
	else
		failureExplanation = control_->move(setpoint.value());

	if(failureExplanation != AMControl::NoFailure)
		onMoveFailed(failureExplanation);
}
Ejemplo n.º 12
0
QVariant AMDatabase::retrieveMax(const QString &table, const QString &colName, const QString &whereClause)
{
	// Sanitize the options
	if(table.isEmpty() || colName.isEmpty())
	{
		AMErrorMon::report(AMErrorReport(this, AMErrorReport::Alert, -10, "Could not search the database. (Missing table name or column name)"));
		return QVariant();
	}

	/*
	if(!tableExists(table))
	{
		AMErrorMon::report(AMErrorReport(this, AMErrorReport::Alert, -10, QString("Could not search the database. (Table %1 does not exist)").arg(table)));
		return QVariant();
	}

	if(!columnExists(table, colName))
	{
		AMErrorMon::report(AMErrorReport(this, AMErrorReport::Alert, -10, QString("Could not search the database. (Table %1 does not contain column %2").arg(table).arg(colName)));
		return QVariant();
	}
	*/

	QSqlQuery q( qdb() );

	QString queryString = QString("SELECT MAX(%1) FROM %2").arg(colName).arg(table);

	if(!whereClause.isEmpty())
	{
		queryString.append(" WHERE ").append(whereClause);
	}

	q.prepare(queryString);

	if(!execQuery(q)) {
		q.finish();	// make sure that sqlite lock is released before emitting signals
		AMErrorMon::report(AMErrorReport(this, AMErrorReport::Alert, -4, QString("database retrieve failed. Could not execute query (%1). The SQL reply was: %2").arg(q.executedQuery()).arg(q.lastError().text())));
		return QVariant();
	}
	// If we found a record at this id:
	if(q.first()) {
		return q.value(0);
	}
	// else: didn't find this id.  That's normal if it's not there, just return null QVariant.
	else {
		return QVariant();
	}

}
Ejemplo n.º 13
0
bool AMActionRegistry3::registerInfoAndAction(const QMetaObject *infoMetaObject, const QMetaObject *actionMetaObject, const QString &shortDescription, const QString &longDescription, const QString &iconFileName, bool exposeToAddActionDialog)
{
	if(!infoMetaObject)
		return false;
	if(!actionMetaObject)
		return false;

	// check that the alleged info inherits AMActionInfo
	if(!inheritsAMActionInfo(infoMetaObject)) {
		AMErrorMon::report(AMErrorReport(this, AMErrorReport::Debug, -1, "Could not register the AMActionInfo class " % QString(infoMetaObject->className()) % " because it does not inherit AMActionInfo."));
		return false;
	}
	// check that the alleged action inherits AMAction
	if(!inheritsAMAction(actionMetaObject)) {
		AMErrorMon::report(AMErrorReport(this, AMErrorReport::Debug, -2, "Could not register the AMAction class " % QString(actionMetaObject->className()) % " because it does not inherit AMAction."));
		return false;
	}

	// check for Q_INVOKABLE constructor in the AMAction that takes a pointer to this AMActionInfo. If this constructor doesn't exist, there won't be any way we can use this registration to construct an action from the info.
	bool hasSuitableConstructor = false;
	for(int i=0, cc=actionMetaObject->constructorCount(); i<cc; i++) {
		QList<QByteArray> parameterTypes = actionMetaObject->constructor(i).parameterTypes();
		if(parameterTypes.count() == 1 &&
				parameterTypes.at(0) == QByteArray(infoMetaObject->className()).append("*")) {
			hasSuitableConstructor = true;
			break;
		}
	}

	if(!hasSuitableConstructor) {
		AMErrorMon::report(AMErrorReport(this, AMErrorReport::Debug, -2, "Could not register the AMAction class " % QString(actionMetaObject->className()) % " because it does not have a Q_INVOKABLE constructor that takes an " % QString(infoMetaObject->className()) % "* argument."));
		return false;
	}


	// already registered?
	if(actionInfo2Actions_.contains(QString(infoMetaObject->className()))) {
		AMErrorMon::report(AMErrorReport(this, AMErrorReport::Debug, -2, "Could not register the AMActionInfo class " % QString(infoMetaObject->className()) % " because it is already registered."));
		return false;
	}

	// insert into registry
	actionInfo2Actions_.insert(
				QString(infoMetaObject->className()),
				AMActionInfoActionRegistration3(infoMetaObject, actionMetaObject, shortDescription, longDescription, iconFileName, exposeToAddActionDialog));
	// success!
	return true;
}
Ejemplo n.º 14
0
bool AMActionRegistry3::registerInfoAndEditor(const QMetaObject *infoMetaObject, const QMetaObject *editorMetaObject) {
	if(!infoMetaObject)
		return false;
	if(!editorMetaObject)
		return false;

	// check that the alleged info inherits AMActionInfo
	if(!inheritsAMActionInfo(infoMetaObject)) {
		AMErrorMon::report(AMErrorReport(this, AMErrorReport::Debug, -1, "Could not register the AMActionInfo class " % QString(infoMetaObject->className()) % " because it does not inherit AMActionInfo."));
		return false;
	}
	// check that the alleged editor inherits QWidget
	if(!inheritsQWidget(editorMetaObject)) {
		AMErrorMon::report(AMErrorReport(this, AMErrorReport::Debug, -2, "Could not register the Editor class " % QString(editorMetaObject->className()) % " because it does not inherit QWidget."));
		return false;
	}

	// check for Q_INVOKABLE constructor in the editor that takes a pointer to this AMActionInfo. If this constructor doesn't exist, there won't be any way we can use this registration to construct an editor for the info.
	bool hasSuitableConstructor = false;
	for(int i=0, cc=editorMetaObject->constructorCount(); i<cc; i++) {
		QList<QByteArray> parameterTypes = editorMetaObject->constructor(i).parameterTypes();
		if(parameterTypes.count() == 1 &&
				parameterTypes.at(0) == QByteArray(infoMetaObject->className()).append("*")) {
			hasSuitableConstructor = true;
			break;
		}
	}


	if(!hasSuitableConstructor) {
		AMErrorMon::report(AMErrorReport(this, AMErrorReport::Debug, -2, "Could not register the Editor class " % QString(editorMetaObject->className()) % " because it does not have a Q_INVOKABLE constructor that takes an " % QString(infoMetaObject->className()) % "* argument."));
		return false;
	}


	// already registered?
	if(actionInfo2Editors_.contains(QString(infoMetaObject->className()))) {
		AMErrorMon::report(AMErrorReport(this, AMErrorReport::Debug, -2, "Could not register the AMActionInfo class " % QString(infoMetaObject->className()) % " because it is already registered."));
		return false;
	}

	// insert into registry
	actionInfo2Editors_.insert(
				QString(infoMetaObject->className()),
				AMActionInfoEditorRegistration3(infoMetaObject, editorMetaObject));
	// success!
	return true;
}
Ejemplo n.º 15
0
/// Called before starting to satisfy any prerequisites (ie: setting up the beamline, setting up files, etc.)
bool REIXSXESScanController::initializeImplementation() {

	// Is the detector connected?
	//if(!REIXSBeamline::bl()->mcpDetector()->canRead() || !REIXSBeamline::bl()->mcpDetector()->canConfigure()) {
	if(!REIXSBeamline::bl()->mcpDetector()->isConnected()){
		AMErrorMon::report(AMErrorReport(this, AMErrorReport::Alert, 17, "Could not connect to the MCP detector before starting an XES scan. Please report this problem to the beamline staff."));
		return false;
	}


	// configure and clear the MCP detector.
	/// \todo We should really configure the detector even if we're not supposed to clear it, but right now setting the orientation clears the accumulated counts.  We'll be removing that orientation setting soon, since we no longer use it. Therefore, we should be OK to skip this if we're not supposed to clear.

	/*DAVID: Not Testing the configuration setting right now
	if(!config_->doNotClearExistingCounts()) {
		if( !REIXSBeamline::bl()->mcpDetector()->setFromInfo(*(config_->mcpDetectorInfo())) ) {
			AMErrorMon::report(AMErrorReport(this, AMErrorReport::Alert, 3, "Could not connect to and configure the MCP detector before starting an XES scan. Please report this problem to the beamline staff."));
			return false;
		}
	}
	*/



	// Do we actually need to move into position?
	if(config_->shouldStartFromCurrentPosition()) {
		onInitialSetupMoveSucceeded();
		return true;
	}

	else {

		if(!REIXSBeamline::bl()->spectrometer()->loadSpectrometerCalibration(AMDatabase::database("user"), config_->spectrometerCalibrationId())) {
			AMErrorMon::report(AMErrorReport(this, AMErrorReport::Alert, 10, QString("Could not load the spectrometer calibration (%1) that was specified in this scan configuration.").arg(config_->spectrometerCalibrationId())));
			return false;
		}

		if(!REIXSBeamline::bl()->spectrometer()->specifyGrating(config_->gratingNumber())) {
			AMErrorMon::report(AMErrorReport(this, AMErrorReport::Alert, 11, "There was no grating like the one specified in this scan configuration."));
			return false;
		}

		REIXSBeamline::bl()->spectrometer()->specifyDetectorTiltOffset(config_->detectorTiltOffset());
		REIXSBeamline::bl()->spectrometer()->specifyFocusOffset(config_->defocusDistanceMm());

		return true;
	}
}
Ejemplo n.º 16
0
/// returns a list of all the objecst/rows (by id) that match a given condition. \c whereClause is a string suitable for appending after an SQL "WHERE" statement.
QList<int> AMDatabase::objectsWhere(const QString& tableName, const QString& whereClause)
{
	QList<int> rl;

	/// \todo sanitize more than this...
	if(tableName.isEmpty()) {
		AMErrorMon::report(AMErrorReport(this, AMErrorReport::Alert, -10, "Could not search the database. (Missing the table name.)"));
		return rl;
	}

	QSqlQuery q( qdb() );

	QString query = "SELECT id FROM " % tableName;
	if(!whereClause.isEmpty())
		query.append(" WHERE ").append(whereClause);

	q.prepare(query);
	execQuery(q);

	while(q.next()) {
		rl << q.value(0).toInt();
	}
	q.finish();


	return rl;
}
// Called whenever the connection state of any PV changes: emits valuesChanged(), sizeChanged(), and stateChanged() as required.
void REIXSXESMCPDataSourcePre2013::onConnectionStateChanged() {
	bool wasConnected = isConnected_;

	isConnected_ = imagePV_->isConnected() &&
				   resolutionXPV_->hasValues() &&
				   resolutionYPV_->hasValues();

	// becoming disconnected...
	if(wasConnected && !isConnected_) {
		pixelsX_ = axes_[0].size = 0;
		pixelsY_ = axes_[1].size = 0;
		emitValuesChanged();
		emitSizeChanged();
		emitStateChanged(AMDataSource::InvalidFlag);

		AMErrorMon::report(AMErrorReport(this, AMErrorReport::Alert, -2, "Lost connection to MCP Detector " + imagePV_->pvName()));
	}

	// becoming connected...
	if(!wasConnected && isConnected_) {
		pixelsX_ = axes_[0].size = int(pow(2.0, double(resolutionXPV_->getInt())));
		pixelsY_ = axes_[1].size = int(pow(2.0, double(resolutionYPV_->getInt())));
		emitValuesChanged();
		emitSizeChanged();
		emitStateChanged(AMDataSource::ProcessingFlag);
	}
}
bool AM2DScanConfigurationGeneralView::canView(const QString &databaseName, const QString &tableName, int dbId){
	Q_UNUSED(dbId)
	AMDatabase *database = AMDatabase::database(databaseName);
	if(database){
		QSqlQuery q = database->query();
		q.prepare("PRAGMA table_info("%tableName%")");
		if(!database->execQuery(q)) {
			q.finish();
			AMErrorMon::report(AMErrorReport(0, AMErrorReport::Debug, -275003, QString("2D Scan Configuration Generl View: There was an error while trying to read meta data on table %1.").arg(tableName)));
		}
		else{
			QStringList columnNames;
			while(q.next()){
				columnNames << q.value(1).toString();
			}
			columnNames.removeFirst();
			q.finish();

			if(columnNames.contains("xStart") && columnNames.contains("xStep") && columnNames.contains("xEnd") &&
					columnNames.contains("yStart") && columnNames.contains("yStep") && columnNames.contains("yEnd") &&
					columnNames.contains("timeStep") && columnNames.contains("fastAxis") && columnNames.contains("slowAxis")){
				return true;
			}
		}
	}
	return false;
}
Ejemplo n.º 19
0
// Called when a stored scanInitialCondition is loaded out of the database, but scanInitialConditions() is not returning a pointer to a valid AMControlInfoList. Note: this should never happen, unless the database storage was corrupted and is loading the wrong object type.
void AMScan::dbLoadScanInitialConditions(AMDbObject* newLoadedObject) {
    AMErrorMon::report(AMErrorReport(this, AMErrorReport::Alert, -89, "There was an error re-loading the initial conditions for this scan from the database. This should never happen unless your database is corrupted. Please report this bug to the Acquaman developers."));

    // delete newLoadedObject, since we don't intend to do anything with it, but we're responsible for it.
    if(newLoadedObject)
        newLoadedObject->deleteLater();
}
Ejemplo n.º 20
0
void AMScanDatabaseImportController::copySamples()
{
	if(state_ != Importing) return;
	emit progressDescription("Copying Samples...");
	emit stepProgress(-1);
	int totalSteps = s2dSampleIds_.count();
	int currentStep = 0;

	QMutableMapIterator<int, int> i(s2dSampleIds_);
	while (i.hasNext()) {
		if(state_ != Importing) return;
		i.next();
		emit stepProgress(int(100.0*(++currentStep)/totalSteps));
		// key is id; value is id in destination database, or -1 if not there yet. (if not there, need to insert)
		int sourceId = i.key(), destinationId = i.value();
		if(destinationId<1) {
			AMSample s;
			s.loadFromDb(sourceDb_, sourceId);
			if(s.storeToDb(destinationDb_))
				i.setValue(s.id());
			else
				AMErrorMon::report(AMErrorReport(this, AMErrorReport::Alert, -2, "Could not import the sample '" % sourceSamples_.value(sourceId) % "' into the database."));
		}
		qApp->sendPostedEvents();
		qApp->processEvents();
	}
}
Ejemplo n.º 21
0
void AMScanDatabaseImportController::copyExperiments()
{
	if(state_ != Importing) return;
	emit progressDescription("Copying Experiments...");
	emit stepProgress(-1);
	int totalSteps = s2dExperimentIds_.count();
	int currentStep = 0;

	QMutableMapIterator<int, int> i(s2dExperimentIds_);
	while (i.hasNext()) {
		if(state_ != Importing) return;
		i.next();
		emit stepProgress(int(100.0*(++currentStep)/totalSteps));
		// key is id; value is id in destination database, or -1 if not there yet. (if not there, need to insert)
		int sourceId = i.key(), destinationId = i.value();
		if(destinationId<1) {
			AMExperiment e;
			e.loadFromDb(sourceDb_, sourceId);
			if(e.storeToDb(destinationDb_))
				i.setValue(e.id());
			else
				AMErrorMon::report(AMErrorReport(this, AMErrorReport::Alert, -2, "Could not import the experiment '" % sourceExperiments_.value(sourceId) % "' into the database."));
		}
		// TODO: need to update the scans that should be in this experiment. This will be tricky... don't know new scan IDs yet.
		qApp->sendPostedEvents();
		qApp->processEvents();
	}
}
Ejemplo n.º 22
0
QSqlDatabase AMDatabase::qdb() const
{
	// threadIDsOfOpenConnections_ can be written and read from any thread by this function. Need to mutex it.
	QMutexLocker ml(&qdbMutex_);

	// Do we have an open connection for this thread already?
	Qt::HANDLE threadId = QThread::currentThreadId();

	if(threadIDsOfOpenConnections_.contains(threadId)) {
		return QSqlDatabase::database(QString("%1%2").arg(connectionName_).arg((qulonglong)threadId));
	}

	else {
		QSqlDatabase db = QSqlDatabase::addDatabase("QSQLITE", QString("%1%2").arg(connectionName_).arg((qulonglong)threadId));
		db.setDatabaseName(dbAccessString_);
		db.setConnectOptions("QSQLITE_BUSY_TIMEOUT=10");

		bool ok = db.open();
		if(!ok) {
			AMErrorMon::report(AMErrorReport(this, AMErrorReport::Serious, -1, QString("error connecting to database (access %1). The SQL reply was: %2").arg(dbAccessString_).arg(db.lastError().text())));
		}

		threadIDsOfOpenConnections_ << threadId;
		return db;
	}
}
Ejemplo n.º 23
0
bool REIXSSpectrometer::stop()
{
	if(!canStop())
		return false;

	if(moveInProgress()) {
		moveAction_->cancel();
		/// \todo Actually, have to flag that a stop has started, and also catch when the stop is finished... Motors will take a while to actually receive and decelerate.
		moveAction_->deleteLater();
		moveAction_ = 0;
		emit moveFailed(AMControl::WasStoppedFailure);
		AMErrorMon::report(AMErrorReport(this, AMErrorReport::Alert, AMControl::WasStoppedFailure, "Spectrometer Move Stopped."));
	}

	// just in case anything was moving from outside our instructions (ie: commanded from somewhere else in the building)
	spectrometerRotationDrive_->stop();
	detectorTranslation_->stop();
	detectorTiltDrive_->stop();
	endstationTranslation_->stop();
	// hexapod: cannot stop without wrecking init. Don't worry for now... just let it stop over time. Not necessary for it to be not-moving before we re-send it somewhere new.

	/// \todo Actually, have to flag that a stop has started, and also catch when the stop is finished... Motors will take a while to actually receive and decelerate.

	return true;
}
Ejemplo n.º 24
0
/// Return a list of all the objects/rows (by id) that contain 'value' in a certain column
/// ex: AMDatabase::db()->scansContaining("name", "Carbon60") could return Scans with names Carbon60_alpha and bCarbon60_gamma
QList<int> AMDatabase::objectsContaining(const QString& tableName, const QString& colName, const QVariant& value)
{

	QList<int> rl;

	/// \todo sanitize more than this...
	if(tableName.isEmpty() || colName.isEmpty()) {
		AMErrorMon::report(AMErrorReport(this, AMErrorReport::Alert, -10, "Could not search the database. (Missing the table name or column name.)"));
		return rl;
	}


	QSqlQuery q( qdb() );

	q.prepare(QString("SELECT id FROM %1 WHERE %2 LIKE ('%' || :val || '%')").arg(tableName).arg(colName));

	q.bindValue(":val", value);
	execQuery(q);

	while(q.next()) {
		rl << q.value(0).toInt();
	}
	q.finish();


	return rl;
}
Ejemplo n.º 25
0
/// Return a list of all the objects/rows (by id) that match 'value' in a certain column.
/// ex: AMDatabase::db()->objectsMatching("name", "Carbon60"), or AMDatabase::db()->objectsMatching("dateTime", QDateTime::currentDateTime())
QList<int> AMDatabase::objectsMatching(const QString& tableName, const QString& colName, const QVariant& value)
{
	// return value: list of id's that match
	QList<int> rl;

	/// \todo sanitize more than this...
	if(tableName.isEmpty() || colName.isEmpty()) {
		AMErrorMon::report(AMErrorReport(this, AMErrorReport::Alert, -10, "Could not search the database. (Missing the table name or column name.)"));
		return rl;
	}

	QSqlQuery q( qdb() );

	// For date/times, we want a resolution of one minute to count as a match
	if(value.type() == QVariant::DateTime) {
		q.prepare(QString("SELECT id FROM %1 WHERE %2 BETWEEN datetime(?, '-1 minute') AND datetime(?, '+1 minute')").arg(tableName).arg(colName));
		q.bindValue(0, value);
		q.bindValue(1, value);
	}
	else {
		q.prepare(QString("SELECT id FROM %1 WHERE %2 = ?").arg(tableName).arg(colName));
		q.bindValue(0, value);
	}
	execQuery(q);

	while(q.next()) {
		rl << q.value(0).toInt();
	}
	q.finish();

	return rl;
}
Ejemplo n.º 26
0
/// ensure that a given column (with \c columName and \c columnType) exists, in the table \c tableName.  \c columnType is an SQLite type ("TEXT" or "INTEGER" recommended).
bool AMDatabase::ensureColumn(const QString& tableName, const QString& columnName, const QString& columnType) {

	QSqlQuery q( qdb() );

	q.prepare(QString("ALTER TABLE %1 ADD COLUMN %2 %3;").arg(tableName).arg(columnName).arg(columnType));

	if(execQuery(q)) {
		q.finish();
		AMErrorMon::report(AMErrorReport(this, AMErrorReport::Debug, 0, QString("Adding database column %1 to table %2.").arg(columnName).arg(tableName)));
		return true;
	}
	else {
		q.finish();	// make sure that sqlite lock is released before emitting signals
		AMErrorMon::report(AMErrorReport(this, AMErrorReport::Debug, 0, QString("Error adding database column %1 to table %2. Maybe it's already there? Sql reply says: %3").arg(columnName).arg(tableName).arg(q.lastError().text())));
		return false;
	}
}
Ejemplo n.º 27
0
void AMSamplePlatePre2013Selector::onDatabaseRemoved(const QString &tableName, int id) {
	if(tableName == samplePlateTableName_ ) {
		if(id == plate_->id()) {
			// deleted the current sample plate... This could be a problem.
			changeSamplePlate(plate_->id());	// will cause a failed load and trigger error handling as usual... hopefully
			AMErrorMon::report(AMErrorReport(this, AMErrorReport::Alert, -33, "Some part of the program has decided to delete the current sample plate. How rude!"));
		}
		plateRefreshScheduler_.schedule();
	}
}
Ejemplo n.º 28
0
bool AMExternalScanDataSourceAB::refreshData()
{
	AMDbObject* dbObject = 0;
	AMnDIndex oldSize = size();

	try {
		// We might have a scan_ loaded already from the constructor. If not, attempt to load ourselves.
		if(!scan_) {
			dbObject = AMDbObjectSupport::s()->createAndLoadObjectAt(sourceDb_,
															 AMDbObjectSupport::s()->tableNameForClass<AMScan>(),
															 sourceScanId_);
			scan_ = qobject_cast<AMScan*>(dbObject);
			if(!scan_)
				throw -1;
		}
		scan_->retain(this);

		int dataSourceIndex = scan_->indexOfDataSource(sourceDataSourceName_);
		if(dataSourceIndex < 0)
			throw -2;

		// get the axes from the source data. Since we're using AMStandardAnalysisBlock, this will automatically expose everything we need.
		axes_ = scan_->dataSourceAt(dataSourceIndex)->axes();

		// grab the data
		copyValues(dataSourceIndex);
		copyAxisValues(dataSourceIndex);

		setState(scan_->dataSourceAt(dataSourceIndex)->state());

		// delete the scan
		scan_->release(this);
		scan_ = 0;

		// signalling:

		emitAxisInfoChanged();
		if(oldSize != size())
			emitSizeChanged();
		emitValuesChanged();

		return true;
	}
	catch(int errCode) {
		if(dbObject)
			delete dbObject;
		if(scan_) {
			scan_->release(this);
			scan_ = 0;
		}
		setState(AMDataSource::InvalidFlag);
		AMErrorMon::report(AMErrorReport(this, AMErrorReport::Serious, errCode, "Could not load external scan data."));
		return false;
	}
}
Ejemplo n.º 29
0
void AMEXAFSScanConfiguration::dbLoadRegions(const QString &exafsRegionsString){
	if(exafsRegionsString.isEmpty())
		return;
	QStringList allRegions = exafsRegionsString.split("\n", QString::SkipEmptyParts);
	QStringList oneRegion;
	bool addRegionSuccess = false;

	for(int x = 0; x < allRegions.count(); x++){
		oneRegion = allRegions.at(x).split(",", QString::SkipEmptyParts);

		// Legacy Acquaman XAS settings (version 1.0)
		if (oneRegion.count() == 3)
			addRegionSuccess = addRegion(x, oneRegion.at(0).toDouble(), oneRegion.at(1).toDouble(), oneRegion.at(2).toDouble());
		// Another legacy Acquaman XAS settings version 1.1
		else if (oneRegion.at(0) == "xasVersion1.1"){

			addRegionSuccess = addRegion(x, oneRegion.at(1).toDouble(), oneRegion.at(2).toDouble(), oneRegion.at(3).toDouble(), oneRegion.at(6).toDouble());
			addRegionSuccess &= setRegionElasticStart(x, oneRegion.at(4).toInt() == 1 ? true : false);
			addRegionSuccess &= setRegionElasticEnd(x, oneRegion.at(5).toInt() == 1 ? true : false);
		}
		// Beginning of a more succinct usage of AMRegions.  Version 1.0
		else if (oneRegion.at(0) == "regionsVersion1.0"){

			addRegionSuccess = addRegion(x, oneRegion.at(1).toDouble(), oneRegion.at(2).toDouble(), oneRegion.at(3).toDouble(), oneRegion.at(6).toDouble());
			addRegionSuccess &= setRegionElasticStart(x, oneRegion.at(4).toInt() == 1 ? true : false);
			addRegionSuccess &= setRegionElasticEnd(x, oneRegion.at(5).toInt() == 1 ? true : false);
			addRegionSuccess &= setRegionUnits(x, oneRegion.at(7));
			addRegionSuccess &= setRegionTimeUnits(x, oneRegion.at(8));
		}

		else if (oneRegion.at(0) == "exafsVersion1.0"){

			addRegionSuccess = addRegion(x, oneRegion.at(4).toDouble(), oneRegion.at(5).toDouble(), oneRegion.at(6).toDouble(), oneRegion.at(9).toDouble());
			addRegionSuccess &= setRegionType(x, oneRegion.at(1) == "Energy" ? AMEXAFSRegion::Energy : AMEXAFSRegion::kSpace);
			addRegionSuccess &= setRegionIsRelative(x, oneRegion.at(3).toInt() == 1 ? true : false);
			addRegionSuccess &= setRegionEdgeEnergy(x, oneRegion.at(2).toDouble());
			addRegionSuccess &= setRegionElasticStart(x, oneRegion.at(7).toInt() == 1 ? true : false);
			addRegionSuccess &= setRegionElasticEnd(x, oneRegion.at(8).toInt() == 1 ? true : false);
			addRegionSuccess &= setRegionUnits(x, oneRegion.at(10));
			addRegionSuccess &= setRegionTimeUnits(x, oneRegion.at(11));

			if (x == 0){

				exafsRegions()->setDefaultEdgeEnergy(regionEdgeEnergy(x));
				exafsRegions()->setDefaultIsRelative(regionIsRelative(x));
			}
		}

		if (!addRegionSuccess)
			AMErrorMon::report(AMErrorReport(this,
							AMErrorReport::Alert,
							0,
							QString("There was an error reloading the scan region #%1, when reloading this scan from the database. Your database might be corrupted. Please report this bug to the Acquaman developers.").arg(x)));
	}
}
Ejemplo n.º 30
0
QString AMExporterGeneralAscii::exportScan(const AMScan *scan, const QString &destinationFolderPath, const AMExporterOption *option, int autoIndex)
{
	setCurrentAutoIndex(autoIndex);
	setCurrentFilename(option->fileName());
	setDestinationFolderPath(destinationFolderPath);

	// prepare scan and option
	setCurrentScan(scan);
	option_ = qobject_cast<const AMExporterOptionGeneralAscii*>(option);
	if(!option_) {
		AMErrorMon::report(AMErrorReport(this, AMErrorReport::Alert, -2, "Invalid options specified for the General Ascii Exporter. Please report this bug to the Acquaman developers."));
		return QString();
	}



	// prepare data sources
	if(!prepareDataSources())
		return QString();


	// prepare export file
	mainFileName_ = parseKeywordString( destinationFolderPath % "/" % option->fileName() );
	qDebug() << "Wants to save as " << mainFileName_;

	if(!openFile(mainFileName_)) {
		AMErrorMon::report(AMErrorReport(this, AMErrorReport::Alert, -3, "Export failed: Could not open the file '" % mainFileName_ % "' for writing.  Check that you have permission to save files there, and that a file with that name doesn't already exists."));
		return QString();
	}


	writeHeader();
	writeMainTable();
	writeSeparateSections();
	if(option_->includeHigherDimensionSources() && !writeSeparateFiles(destinationFolderPath)) {
		file_->close();
		return QString();
	}

	file_->close();
	return mainFileName_;
}