1261 lines
36 KiB
Igor
1261 lines
36 KiB
Igor
#pragma rtGlobals=3 // Use modern global access method and strict wave access.
|
|
#pragma version = 1.2
|
|
#pragma IgorVersion = 6.2
|
|
#pragma ModuleName = PearlElog
|
|
|
|
// $Id$
|
|
// author: matthias.muntwiler@psi.ch
|
|
// Copyright (c) 2013-15 Paul Scherrer Institut
|
|
|
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
// you may not use this file except in compliance with the License.
|
|
// You may obtain a copy of the License at
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
|
|
/// @file
|
|
/// @brief interface for writing ELOG entries with Igor graphs as attachment.
|
|
/// @ingroup ArpesPackage
|
|
///
|
|
/// the functions in this module support the following work flows:
|
|
/// 1. send a preview of a selected measurement to ELOG.
|
|
/// 2. send any Igor graph to ELOG. (CLI and GUI)
|
|
/// 3. direct access to all ELOG parameters. (CLI only)
|
|
///
|
|
/// the configuration of the ELOG server and logbooks (except user name and password)
|
|
/// as well as the most recently used attributes are persisted in the preference file.
|
|
///
|
|
/// elog command line
|
|
///@verbatim
|
|
/// elog -h <hostname> [-p port] [-d subdir]
|
|
/// Location where elogd is running
|
|
/// -l logbook Name of logbook
|
|
/// -s Use SSL for communication
|
|
/// [-v] For verbose output
|
|
/// [-w password] Write password defined on server
|
|
/// [-u username password] User name and password
|
|
/// [-f <attachment>] Up to 50 attachments
|
|
/// -a <attribute>=<value> Up to 50 attributes
|
|
/// [-r <id>] Reply to existing message
|
|
/// [-q] Quote original text on reply
|
|
/// [-e <id>] Edit existing message
|
|
/// [-x] Suppress email notification
|
|
/// [-n 0|1|2] Encoding: 0:ELcode,1:plain,2:HTML
|
|
/// -m <textfile>] | <text>
|
|
///@endverbatim
|
|
///
|
|
/// user name and password are used if configured in the package data folder.
|
|
/// there is currently no separate user interface.
|
|
///
|
|
/// @attention some functions in this module refer specifically to the ELOG configuration at PEARL.
|
|
/// logbook and attributes are specific to the ELOG configuration at PEARL.
|
|
///
|
|
/// @author matthias muntwiler, matthias.muntwiler@psi.ch
|
|
///
|
|
/// @copyright 2013-15 Paul Scherrer Institut @n
|
|
/// Licensed under the Apache License, Version 2.0 (the "License"); @n
|
|
/// you may not use this file except in compliance with the License. @n
|
|
/// You may obtain a copy of the License at
|
|
/// http://www.apache.org/licenses/LICENSE-2.0
|
|
|
|
/// @namespace PearlElog
|
|
/// @brief interface for writing ELOG entries with Igor graphs as attachment.
|
|
///
|
|
/// PearlElog is declared in @ref pearl-elog.ipf.
|
|
|
|
static strconstant package_name = "pearl_elog"
|
|
static strconstant package_path = "root:packages:pearl_elog:"
|
|
|
|
/// main function to initialize ELOG and to open an ELOG panel.
|
|
///
|
|
/// this function takes care of all necessary initialization, configuration, and preferences.
|
|
/// if a panel exists, it will be moved to the front.
|
|
///
|
|
/// @param logbook name of the logbook
|
|
/// if empty, the ELOG package is initialized (overwriting existing data) but no panel is opened.
|
|
///
|
|
function pearl_elog(logbook)
|
|
string logbook
|
|
|
|
string win_name = logbook + "ElogPanel"
|
|
if (strlen(logbook) > 0)
|
|
if (strlen(WinList(win_name, ";", "")) > 0)
|
|
DoWindow /F $win_name
|
|
else
|
|
if (init_package() == 0)
|
|
load_prefs()
|
|
endif
|
|
PearlElogPanel(logbook)
|
|
endif
|
|
else
|
|
init_package(clean=1)
|
|
load_prefs()
|
|
endif
|
|
end
|
|
|
|
/// save preferences and recent values before Igor opens a new experiment.
|
|
static function IgorBeforeNewHook(igorApplicationNameStr)
|
|
string igorApplicationNameStr
|
|
save_prefs()
|
|
return 0
|
|
end
|
|
|
|
/// save preferences and recent values before Igor quits.
|
|
static function IgorQuitHook(igorApplicationNameStr)
|
|
string igorApplicationNameStr
|
|
save_prefs()
|
|
return 0
|
|
end
|
|
|
|
/// initialize the package and reload preferences after an experiment is loaded.
|
|
static function AfterFileOpenHook(refNum,file,pathName,type,creator,kind)
|
|
Variable refNum,kind
|
|
String file,pathName,type,creator
|
|
if( (kind >= 1) && (kind <= 2))
|
|
init_package(clean=1)
|
|
load_prefs()
|
|
endif
|
|
return 0
|
|
end
|
|
|
|
/// returns the package data folder or logbook datafolder
|
|
///
|
|
/// @param logbook name of logbook, or empty string for package datafolder
|
|
///
|
|
/// @returns data folder reference
|
|
static function /df get_elog_df(logbook)
|
|
string logbook
|
|
|
|
dfref df_package = $package_path
|
|
if (strlen(logbook) > 0)
|
|
dfref df_logbook = df_package:$logbook
|
|
return df_logbook
|
|
else
|
|
return df_package
|
|
endif
|
|
end
|
|
|
|
/// initialize the package data folder.
|
|
///
|
|
/// the data folder is initialized with a default, local configuration and the PEARL logbooks.
|
|
/// the server configuration should be set in the preferences.
|
|
///
|
|
/// @remark this function is specific to the setup at PEARL.
|
|
static function init_package([clean])
|
|
|
|
variable clean // 0 (default) = do not overwrite existing data
|
|
// 1 = clean configuration, overwrite existing data
|
|
|
|
if (ParamIsDefault(clean))
|
|
clean = 0
|
|
endif
|
|
|
|
dfref savedf = getdatafolderdfr()
|
|
dfref basedf = get_elog_df("")
|
|
if ((clean == 0) && (DataFolderRefStatus(dfr) == 1))
|
|
return 1
|
|
endif
|
|
|
|
setdatafolder root:
|
|
newdatafolder /o/s packages
|
|
newdatafolder /o/s $package_name
|
|
dfref basedf = getdatafolderdfr()
|
|
|
|
// common configuration (persistent except username and password)
|
|
string /g elog_path = "c:\\program files (x86)\\ELOG\\elog.exe"
|
|
string /g hostname = "localhost"
|
|
variable /g port = 0 // 0 = unspecified (default)
|
|
variable /g ssl = 0 // 0 = plain text (incl. passwords), 1 = secure connection
|
|
string /g subdir = ""
|
|
string /g username = ""
|
|
string /g password = ""
|
|
|
|
// list of configured logbooks
|
|
// there must be a sub-folder for each of these
|
|
string /g logbooks = "Experiments;Calculations"
|
|
|
|
// Experiments logbook
|
|
setdatafolder basedf
|
|
newdatafolder /o/s Experiments
|
|
// ELOG logbook name
|
|
string /g logbook = "Experiments"
|
|
|
|
// attributes (persistent)
|
|
// available attributes
|
|
string /g attributes = "author;project;sample;source;task;technique;valid"
|
|
// controls corresponding to attributes
|
|
// prefix determines the control type: sv_ = setvariable (string), pm_ = popup menu, cb = check box
|
|
string /g controls = "sv_author;sv_project;sv_sample;pm_source;pm_task;pm_technique;cb_valid"
|
|
// attributes with fixed options, value item declares the options string
|
|
string /g options = "source=sources;task=tasks;technique=techniques"
|
|
// attributes which must be defined
|
|
string /g required_attributes = "author;project;sample;source;task;technique;valid"
|
|
|
|
// option lists
|
|
string /g sources = "Manual Entry;Scienta Data;SScan Data;Prosilica Data;OTF Data;Beamline Status;LEED Data;QMS Data;Matrix Data;Igor Pro;Other"
|
|
string /g tasks = "Measurement;Sample Preparation;Sample Storage;Optimization;Analysis;Development;Maintenance;Test;Comment;Other"
|
|
string /g techniques = "XPS;UPS;XPD;XAS;XMCD;PhD;ARUPS;LEED;AES;STM;STS;QMS;MBE;Test;Other"
|
|
|
|
// usage data (persistent)
|
|
string /g recent = ""
|
|
string /g recent_message = ""
|
|
|
|
// run-time variables (volatile)
|
|
variable /g msg_id
|
|
|
|
// Calculations logbook
|
|
setdatafolder basedf
|
|
newdatafolder /o/s Calculations
|
|
// ELOG logbook name
|
|
string /g logbook = "Calculations"
|
|
|
|
// attributes (persistent)
|
|
// available attributes
|
|
string /g attributes = "author;project;sample;program;revision;machine;job;source path;result path;valid"
|
|
// controls corresponding to attributes
|
|
// prefix determines the control type: sv_ = setvariable (string), pm_ = popup menu, cb = check box
|
|
string /g controls = "sv_author;sv_project;sv_sample;pm_program;sv_revision;pm_machine;sv_job;sv_sourcepath;sv_resultpath;cb_valid"
|
|
// attributes with fixed options, value item declares the options string
|
|
string /g options = "program=programs;machine=machines"
|
|
// attributes which must be defined
|
|
string /g required_attributes = "author;project;sample"
|
|
|
|
// option lists
|
|
string /g programs = "DMSUP;EDAC;MSC;MUFPOT;SSC"
|
|
string /g machines = "llcx;Merlin;PC"
|
|
|
|
// usage data (persistent)
|
|
string /g recent = ""
|
|
string /g recent_message = ""
|
|
|
|
// run-time variables (volatile)
|
|
variable /g msg_id
|
|
|
|
setdatafolder savedf
|
|
return 0
|
|
end
|
|
|
|
/// set module configuration parameters
|
|
function elog_config([elog_path, hostname, port, subdir])
|
|
string elog_path
|
|
string hostname
|
|
variable port
|
|
string subdir
|
|
|
|
dfref saveDF = GetDataFolderDFR()
|
|
|
|
if (!ParamIsDefault(elog_path))
|
|
svar g_elog_path = $(package_path + "elog_path")
|
|
g_elog_path = elog_path
|
|
endif
|
|
if (!ParamIsDefault(hostname))
|
|
svar g_hostname = $(package_path + "hostname")
|
|
g_hostname = hostname
|
|
endif
|
|
if (!ParamIsDefault(port))
|
|
nvar g_port = $(package_path + "port")
|
|
g_port = port
|
|
endif
|
|
if (!ParamIsDefault(subdir))
|
|
svar g_subdir = $(package_path + "subdir")
|
|
g_subdir = subdir
|
|
endif
|
|
|
|
setdatafolder savedf
|
|
end
|
|
|
|
/// save persistent package data to the preferences file.
|
|
///
|
|
/// currently saves everything under the package folder.
|
|
static function save_prefs()
|
|
dfref saveDF = GetDataFolderDFR()
|
|
|
|
dfref df = get_elog_df("")
|
|
if (DataFolderRefStatus(df) == 1)
|
|
string fullPath = SpecialDirPath("Packages", 0, 0, 0)
|
|
fullPath += package_name
|
|
NewPath/O/C/Q tempPackagePrefsPath, fullPath
|
|
fullPath += ":preferences.pxp"
|
|
SetDataFolder df
|
|
SaveData /O /Q /R fullPath
|
|
KillPath/Z tempPackagePrefsPath
|
|
endif
|
|
|
|
SetDataFolder saveDF
|
|
end
|
|
|
|
/// load persistent package data from the preferences file.
|
|
///
|
|
/// the preferences file is an Igor packed experiment file in a special preferences folder
|
|
static function load_prefs()
|
|
dfref saveDF = GetDataFolderDFR()
|
|
|
|
variable result = -1
|
|
setdatafolder root:
|
|
NewDataFolder /O/S packages
|
|
NewDataFolder /O/S $package_name
|
|
string fullPath = SpecialDirPath("Packages", 0, 0, 0)
|
|
fullPath += package_name
|
|
|
|
GetFileFolderInfo /Q /Z fullPath
|
|
if (V_Flag == 0) // Disk directory exists?
|
|
fullPath += ":preferences.pxp"
|
|
GetFileFolderInfo /Q /Z fullPath
|
|
if (V_Flag == 0) // Preference file exist?
|
|
LoadData /O /R /Q fullPath
|
|
result = 0
|
|
endif
|
|
endif
|
|
|
|
SetDataFolder saveDF
|
|
return result
|
|
end
|
|
|
|
/// add a copy of the given graph to ELOG, prompting for attributes (deprecated)
|
|
///
|
|
/// @deprecated
|
|
/// this function is specific to the PEARL/Experiments logbook.
|
|
/// it cannot be customized without major efforts.
|
|
/// it will be removed in a future version.
|
|
function elog_add_graph_prompt(graphname, [replyto])
|
|
string graphname
|
|
variable replyto
|
|
|
|
print "executing deprecated function elog_add_graph_prompt."
|
|
|
|
dfref savedf = getdatafolderdfr()
|
|
//setdatafolder root:packages:elog
|
|
|
|
string attributes
|
|
string message = ""
|
|
svar mru_attributes = $(package_path + "attributes")
|
|
attributes = mru_attributes
|
|
|
|
variable result = elog_prompt_attributes(attributes, message)
|
|
if (result == 0)
|
|
if (ParamIsDefault(replyto))
|
|
result = elog_create_entry("Experiments", attributes, message, graphs=graphname)
|
|
else
|
|
result = elog_create_entry("Experiments", attributes, message, graphs=graphname, replyto=replyto)
|
|
endif
|
|
if (result == 0)
|
|
mru_attributes = attributes
|
|
endif
|
|
endif
|
|
|
|
setdatafolder savedf
|
|
return result
|
|
end
|
|
|
|
/// prompt for attributes (deprecated)
|
|
///
|
|
/// @deprecated
|
|
/// this function is specific to the PEARL/Experiments logbook.
|
|
/// it cannot be customized without major efforts.
|
|
/// it will be removed in a future version.
|
|
function elog_prompt_attributes(attributes, message)
|
|
string &attributes
|
|
string &message
|
|
|
|
print "executing deprecated function elog_prompt_attributes."
|
|
|
|
string author
|
|
string project
|
|
string sample
|
|
string source
|
|
string task
|
|
string technique
|
|
string file
|
|
variable valid
|
|
string loc_message
|
|
|
|
author = StringByKey("Author", attributes, "=", ";")
|
|
project = StringByKey("Project", attributes, "=", ";")
|
|
sample = StringByKey("Sample", attributes, "=", ";")
|
|
source = StringByKey("Source", attributes, "=", ";")
|
|
task = StringByKey("Task", attributes, "=", ";")
|
|
technique = StringByKey("Technique", attributes, "=", ";")
|
|
file = StringByKey("File", attributes, "=", ";")
|
|
valid = NumberByKey("Valid", attributes, "=", ";")
|
|
loc_message = message
|
|
|
|
svar sources = $(package_path + "sources")
|
|
svar tasks = $(package_path + "tasks")
|
|
svar techniques = $(package_path + "techniques")
|
|
|
|
prompt author, "Author"
|
|
prompt project, "Project"
|
|
prompt sample, "Sample"
|
|
prompt source, "Source", popup, sources
|
|
prompt task, "Task", popup, tasks
|
|
prompt technique, "Technique", popup, techniques
|
|
prompt file, "File"
|
|
prompt valid, "Valid"
|
|
prompt loc_message, "Message"
|
|
|
|
doprompt "Create New ELOG Entry", author, project, sample, task, technique, file, loc_message
|
|
source = "Manual Entry"
|
|
|
|
if (v_flag == 0)
|
|
attributes = ReplaceStringByKey("Author", attributes, author, "=", ";")
|
|
attributes = ReplaceStringByKey("Project", attributes, project, "=", ";")
|
|
attributes = ReplaceStringByKey("Sample", attributes, sample, "=", ";")
|
|
attributes = ReplaceStringByKey("Source", attributes, source, "=", ";")
|
|
attributes = ReplaceStringByKey("Task", attributes, task, "=", ";")
|
|
attributes = ReplaceStringByKey("Technique", attributes, technique, "=", ";")
|
|
attributes = ReplaceStringByKey("File", attributes, file, "=", ";")
|
|
//attributes = ReplaceNumberByKey("Valid", attributes, valid, "=", ";")
|
|
message = loc_message
|
|
endif
|
|
|
|
return v_flag
|
|
end
|
|
|
|
/// validate attributes
|
|
///
|
|
/// @returns 0 if all required attributes are present and enumerated items are correct.
|
|
/// non-zero if a violation is detected.
|
|
///
|
|
/// @todo
|
|
/// function currently not implemented, always returns 0
|
|
function elog_validate_attributes(logbook, attributes)
|
|
|
|
string logbook // name of the logbook (as in igor folder name)
|
|
string attributes // key=value list of attributes, semicolon separated
|
|
|
|
variable result = 0
|
|
return result
|
|
end
|
|
|
|
function elog_create_entry(logbook, attributes, message, [encoding, graphs, replyto])
|
|
string logbook
|
|
string attributes // key=value list of attributes, semicolon separated
|
|
string message
|
|
variable encoding // encoding of message, 0:ELcode, 1:plain (default), 2:HTML
|
|
string graphs // names of graph windows to be added as attachments, semicolon separated
|
|
variable replyto // existing message ID (> 1) to follow up on.
|
|
// 0 or default: start new thread
|
|
|
|
if (ParamIsDefault(encoding))
|
|
encoding = 1
|
|
endif
|
|
if (ParamIsDefault(graphs))
|
|
graphs = ""
|
|
endif
|
|
if (ParamIsDefault(replyto))
|
|
replyto = 0
|
|
endif
|
|
|
|
dfref savedf = getdatafolderdfr()
|
|
setdatafolder $(package_path)
|
|
setdatafolder $(logbook)
|
|
|
|
variable result = 0
|
|
nvar msg_id
|
|
|
|
if (elog_validate_attributes(logbook,attributes) != 0)
|
|
result = -3 // error: invalid/missing attributes
|
|
endif
|
|
|
|
string cmd = prepare_command_line(logbook)
|
|
if (strlen(cmd) == 0)
|
|
result = -2 // error: invalid/missing command line
|
|
endif
|
|
|
|
if (replyto >= 1)
|
|
cmd += " -r " + num2str(replyto)
|
|
endif
|
|
cmd += " -n " + num2str(encoding)
|
|
|
|
variable nattr = ItemsInList(attributes, ";")
|
|
variable iattr
|
|
string sattr
|
|
for (iattr = 0; (iattr < nattr) && (result == 0); iattr += 1)
|
|
sattr = StringFromList(iattr, attributes, ";")
|
|
if (strlen(StringFromList(1, sattr, "=")) > 0)
|
|
cmd += " -a \"" + sattr + "\""
|
|
endif
|
|
endfor
|
|
|
|
if (result == 0)
|
|
string cmd_graphs = prepare_graph_attachments(graphs)
|
|
cmd += " " + cmd_graphs
|
|
endif
|
|
|
|
if ((result == 0) && (strlen(message) > 0))
|
|
string messagefile = create_message_file(message)
|
|
if (strlen(messagefile) > 0)
|
|
cmd += " -m \"" + messagefile + "\""
|
|
cmd += " > \"" + get_log_path() + "\""
|
|
string cmd_file_path = create_cmd_file(cmd)
|
|
ExecuteScriptText cmd_file_path
|
|
variable id = parse_result()
|
|
if (id > 0)
|
|
msg_id = id
|
|
print "ELOG: sent message " + num2str(id)
|
|
else
|
|
print "ELOG: sending message failed."
|
|
result = -4 // error: elog returned error
|
|
endif
|
|
cleanup_temp_files()
|
|
else
|
|
result = -1 // error
|
|
endif
|
|
endif
|
|
|
|
setdatafolder savedf
|
|
return result
|
|
end
|
|
|
|
/// add one or more graphs to an existing ELOG entry
|
|
///
|
|
/// @param logbook name of the target logbook
|
|
/// @param id identification number of the existing entry
|
|
/// @param graphs names of graph windows to be added as attachments, semicolon separated
|
|
///
|
|
/// @warning this will delete all existing attachments of the entry!
|
|
function elog_add_attachment(logbook, id, graphs)
|
|
string logbook
|
|
variable id // existing entry ID
|
|
string graphs // names of graph windows to be added as attachments, semicolon separated
|
|
|
|
dfref savedf = getdatafolderdfr()
|
|
setdatafolder $(package_path)
|
|
setdatafolder $(logbook)
|
|
|
|
variable result = 0
|
|
nvar msg_id
|
|
|
|
string cmd = prepare_command_line(logbook)
|
|
if (strlen(cmd) == 0)
|
|
result = -2 // error: invalid/missing command line
|
|
endif
|
|
|
|
cmd += " -e " + num2str(id)
|
|
|
|
if (result == 0)
|
|
string cmd_graphs = prepare_graph_attachments(graphs)
|
|
if (strlen(cmd_graphs) == 0)
|
|
result = -3 // error: invalid/missing graphs
|
|
endif
|
|
endif
|
|
|
|
if (result == 0)
|
|
cmd += " " + cmd_graphs
|
|
cmd += " > \"" + get_log_path() + "\""
|
|
string cmd_file_path = create_cmd_file(cmd)
|
|
ExecuteScriptText cmd_file_path
|
|
id = parse_result()
|
|
if (id > 0)
|
|
msg_id = id
|
|
print "ELOG: attached graphs to message " + num2str(id)
|
|
else
|
|
print "ELOG: attaching graphs failed."
|
|
result = -4 // error: elog returned error
|
|
endif
|
|
cleanup_temp_files()
|
|
endif
|
|
|
|
setdatafolder savedf
|
|
return result
|
|
end
|
|
|
|
/// format the ELOG command and essential address arguments.
|
|
///
|
|
/// the following arguments are included (from global variables) if applicable:
|
|
/// host name, port, SSL, sub-dir, username, password
|
|
/// the result string does not include leading or trailing space
|
|
///
|
|
/// @param logbook name of the target logbook
|
|
static function /s prepare_command_line(logbook)
|
|
string logbook
|
|
|
|
dfref savedf = getdatafolderdfr()
|
|
setdatafolder $(package_path)
|
|
|
|
svar elog_path
|
|
svar hostname
|
|
nvar port
|
|
nvar ssl
|
|
svar subdir
|
|
svar username
|
|
svar password
|
|
|
|
string cmd
|
|
cmd = "\"" + elog_path + "\""
|
|
cmd += " -h " + hostname
|
|
if ((nvar_exists(port)) && (port > 0))
|
|
cmd += " -p " + num2str(port)
|
|
endif
|
|
if ((svar_exists(subdir)) && (strlen(subdir) > 0))
|
|
cmd += " -d " + subdir
|
|
endif
|
|
cmd += " -l \"" + logbook + "\""
|
|
if ((nvar_exists(ssl)) && (ssl != 0))
|
|
cmd += " -s"
|
|
endif
|
|
//cmd += " -w " + password
|
|
if (svar_exists(username) && svar_exists(password) && (strlen(username) > 0) && (strlen(password) > 0))
|
|
cmd += " -u " + username + " " + password
|
|
endif
|
|
|
|
setdatafolder savedf
|
|
return cmd
|
|
end
|
|
|
|
/// prepare screenshots of graph windows for attachments
|
|
///
|
|
/// prepares the attachment files from Igor graph windows
|
|
/// and returns the arguments to the elog command to attach the files.
|
|
/// the result string does not include leading or trailing space
|
|
///
|
|
/// @param graphs names of graph windows to be added as attachments, semicolon separated
|
|
///
|
|
static function /s prepare_graph_attachments(graphs)
|
|
string graphs // names of graph windows to be added as attachments, semicolon separated
|
|
|
|
dfref savedf = getdatafolderdfr()
|
|
setdatafolder $(package_path)
|
|
|
|
string cmd = ""
|
|
variable ngraphs = ItemsInList(graphs, ";")
|
|
variable igraph
|
|
string sgraph
|
|
string graph_path
|
|
for (igraph = 0; igraph < ngraphs; igraph += 1)
|
|
sgraph = StringFromList(igraph, graphs, ";")
|
|
graph_path = create_graph_file(sgraph, igraph)
|
|
if (strlen(graph_path) > 0)
|
|
cmd += " -f \"" + graph_path + "\""
|
|
endif
|
|
endfor
|
|
|
|
setdatafolder savedf
|
|
return cmd
|
|
end
|
|
|
|
static function /s get_timestamp(sep)
|
|
string sep
|
|
Variable now = DateTime
|
|
string dat = ReplaceString("-", Secs2Date(DateTime, -2), "")
|
|
string tim = ReplaceString(":", Secs2Time(DateTime, 3), "")
|
|
return dat + sep + tim
|
|
end
|
|
|
|
static function /s create_message_file(message)
|
|
string message
|
|
|
|
string path = SpecialDirPath("Temporary", 0, 1, 0)
|
|
variable len = strlen(path)
|
|
if (numtype(len) == 0)
|
|
path += "elog_temp_message.txt"
|
|
variable f1
|
|
Open f1 as path
|
|
fprintf f1, message
|
|
Close f1
|
|
else
|
|
path = ""
|
|
endif
|
|
|
|
return path
|
|
end
|
|
|
|
static function /s create_graph_file(graphname, fileindex)
|
|
string graphname
|
|
variable fileindex
|
|
|
|
string path = SpecialDirPath("Temporary", 0, 1, 0)
|
|
string ts = get_timestamp("_")
|
|
variable len = strlen(path)
|
|
if (numtype(len) == 0)
|
|
path += "elog_" + ts + "_" + num2str(fileindex) + ".png"
|
|
SavePICT /B=72 /E=-5 /M /O /W=(0,0,8,6) /WIN=$graphname /Z as path
|
|
if (v_flag != 0)
|
|
path = ""
|
|
endif
|
|
else
|
|
path = ""
|
|
endif
|
|
|
|
return path
|
|
end
|
|
|
|
static function /s create_cmd_file(cmd)
|
|
string cmd
|
|
|
|
string path = SpecialDirPath("Temporary", 0, 1, 0)
|
|
variable len = strlen(path)
|
|
if (numtype(len) == 0)
|
|
path += "elog_temp_cmd.bat"
|
|
variable f1
|
|
Open f1 as path
|
|
fprintf f1, cmd
|
|
Close f1
|
|
else
|
|
path = ""
|
|
endif
|
|
|
|
return path
|
|
end
|
|
|
|
static function /s get_log_path()
|
|
string path = SpecialDirPath("Temporary", 0, 1, 0)
|
|
variable len = strlen(path)
|
|
if (numtype(len) == 0)
|
|
path += "elog.log"
|
|
else
|
|
path = ""
|
|
endif
|
|
|
|
return path
|
|
end
|
|
|
|
static function /s cleanup_temp_files()
|
|
string path = SpecialDirPath("Temporary", 0, 1, 0)
|
|
string cmd
|
|
sprintf cmd, "del \"%s\elog*.*\"", path
|
|
//ExecuteScriptText cmd
|
|
return path
|
|
end
|
|
|
|
static strconstant elog_success_msg = "Message successfully transmitted"
|
|
static strconstant elog_parse_id = "ID=%u"
|
|
|
|
/// parse the result file from an elog invokation.
|
|
///
|
|
/// @returns the ID of the generated message,
|
|
/// or a value <= 0 if an error occurred.
|
|
static function parse_result()
|
|
string path = get_log_path()
|
|
string line = ""
|
|
|
|
variable len = strlen(path)
|
|
if (numtype(len) == 0)
|
|
variable f1
|
|
Open /R/Z f1 as path
|
|
if (v_flag == 0)
|
|
FReadLine f1, line
|
|
Close f1
|
|
endif
|
|
endif
|
|
|
|
variable success = 0
|
|
variable id = -1
|
|
if (strlen(line) > 0)
|
|
string part1 = StringFromList(0, line, ",")
|
|
string part2 = ReplaceString(" ", StringFromList(1, line, ","), "")
|
|
success = cmpstr(part1, elog_success_msg) == 0
|
|
if (success)
|
|
sscanf part2, elog_parse_id, id
|
|
endif
|
|
endif
|
|
|
|
return id
|
|
end
|
|
|
|
/// open a new panel for submitting data to ELOG.
|
|
///
|
|
/// this function creates only the panel but not the necessary package data folder.
|
|
/// call init_package() and load_prefs() once before creating panels.
|
|
///
|
|
/// @param logbook name of the target logbook
|
|
///
|
|
function /s PearlElogPanel(logbook)
|
|
string logbook
|
|
|
|
dfref savedf = getdatafolderdfr()
|
|
setdatafolder $(package_path)
|
|
setdatafolder $(logbook)
|
|
string df_path = getdatafolder(1)
|
|
string win_name = logbook + "ElogPanel"
|
|
string win_title = "ELOG " + logbook
|
|
|
|
NewPanel /K=1 /N=$win_name /W=(600,200,926,494) as win_title
|
|
win_name = s_name
|
|
ModifyPanel /w=$win_name cbRGB=(52224,52224,65280)
|
|
|
|
svar attributes
|
|
svar controls
|
|
svar options
|
|
|
|
variable iattr
|
|
variable nattr = ItemsInList(attributes, ";")
|
|
string s_attr
|
|
string s_control
|
|
string s_option
|
|
string options_path
|
|
string variable_path
|
|
variable ypos = 2
|
|
|
|
for (iattr = 0; iattr < nattr; iattr += 1)
|
|
s_attr = StringFromList(iattr, attributes, ";")
|
|
s_control = StringFromList(iattr, controls, ";")
|
|
strswitch(s_control[0,1])
|
|
case "sv":
|
|
SetVariable $s_control, win=$win_name, pos={0,ypos}, size={260,16}, bodyWidth=200
|
|
SetVariable $s_control, win=$win_name, title=s_attr, value= _STR:""
|
|
SetVariable $s_control, win=$win_name, userdata(attribute)=s_attr
|
|
ypos += 18
|
|
break
|
|
case "pm":
|
|
options_path = df_path + StringByKey(s_attr, options, "=", ";")
|
|
PopupMenu $s_control, win=$win_name, pos={0,ypos}, size={260,21}, bodyWidth=200
|
|
PopupMenu $s_control, win=$win_name, title=s_attr
|
|
PopupMenu $s_control, win=$win_name, mode=1, popvalue="Test", value= #options_path
|
|
PopupMenu $s_control, win=$win_name, userdata(attribute)=s_attr
|
|
ypos += 23
|
|
break
|
|
case "cb":
|
|
CheckBox $s_control, win=$win_name, pos={60,ypos}, size={260,14}
|
|
CheckBox $s_control, win=$win_name, title=s_attr, value= 1
|
|
CheckBox $s_control, win=$win_name, userdata(attribute)=s_attr
|
|
ypos += 17
|
|
break
|
|
endswitch
|
|
endfor
|
|
|
|
PopupMenu pm_attach,win=$win_name, pos={0,ypos},size={260,21},bodyWidth=200,title="Attachment"
|
|
PopupMenu pm_attach,win=$win_name, mode=1,popvalue="(none)",value=PearlElog#pm_list_attach_items()
|
|
PopupMenu pm_attach,win=$win_name, help={"Choose any visible Igor graph for attachment."}
|
|
Button b_select_attach_top,win=$win_name, pos={264,ypos},size={60,20},proc=PearlElog#bp_select_attach_top,title="Top Graph"
|
|
Button b_select_attach_top,win=$win_name, help={"Select top graph window."}
|
|
Button b_select_attach_top,win=$win_name, fcolor=(56576,60928,47872)
|
|
|
|
ypos += 246-160
|
|
Button b_submit,win=$win_name, pos={60,ypos},size={46,20},proc=PearlElog#bp_submit,title="Submit"
|
|
Button b_submit,win=$win_name, help={"Submit form data to ELOG (new entry)."}
|
|
Button b_submit,win=$win_name, fcolor=(56576,60928,47872)
|
|
|
|
Button b_clear,win=$win_name, pos={110,ypos},size={46,20},proc=PearlElog#bp_clear,title="Clear"
|
|
Button b_clear,win=$win_name, help={"Clear the form fields"}
|
|
Button b_clear,win=$win_name, fcolor=(56576,60928,47872)
|
|
|
|
ypos += 272-246
|
|
variable_path = df_path + "msg_id"
|
|
SetVariable sv_id,win=$win_name, pos={46,ypos},size={109,16},bodyWidth=94
|
|
SetVariable sv_id,win=$win_name, title="ID",value=$variable_path
|
|
SetVariable sv_id,win=$win_name, help={"ID of last submitted message, or message to attach or reply to."}
|
|
|
|
ypos += 270-272
|
|
Button b_attach,win=$win_name, pos={160,ypos},size={48,20},proc=PearlElog#bp_attach,title="Attach"
|
|
Button b_attach,win=$win_name, help={"Attach the selected graph to an existing ELOG entry (correct ID required)."}
|
|
Button b_attach,win=$win_name, fcolor=(56576,60928,47872)
|
|
|
|
Button b_reply,win=$win_name, pos={210,ypos},size={48,20},proc=PearlElog#bp_submit,title="Reply"
|
|
Button b_reply,win=$win_name, help={"Submit form data to ELOG as a reply to an existing message (correct ID required)."}
|
|
Button b_reply,win=$win_name, fcolor=(56576,60928,47872)
|
|
|
|
ypos += 184-270
|
|
TitleBox t_message,win=$win_name, pos={0,ypos},size={58,16},fixedSize=1,frame=0,anchor=RT,title="Message"
|
|
|
|
SetWindow $win_name, hook(elogPanelHook)=PearlElog#elog_panel_hook
|
|
SetWindow $win_name, userdata(logbook)=logbook
|
|
|
|
DefineGuide UGH0={FT,ypos},UGV0={FL,60},UGH1={FB,-52},UGV1={FR,-2}
|
|
NewNotebook /F=0 /N=Message /OPTS=3 /W=(115,404,345,341)/FG=(UGV0,UGH0,UGV1,UGH1) /HOST=#
|
|
Notebook kwTopWin, defaultTab=20, statusWidth=0, autoSave=0
|
|
Notebook kwTopWin font="Arial", fSize=10, fStyle=0, textRGB=(0,0,0)
|
|
RenameWindow #,Message
|
|
SetActiveSubwindow ##
|
|
|
|
// restore recently used attributes and message
|
|
svar /z /sdfr=get_elog_df(logbook) recent
|
|
if (svar_exists(recent) && (strlen(recent) > 0))
|
|
set_panel_attributes(win_name, recent)
|
|
endif
|
|
svar /z /sdfr=get_elog_df(logbook) recent_message
|
|
if (svar_exists(recent_message) && (strlen(recent_message) > 0))
|
|
set_panel_message(win_name, recent_message)
|
|
endif
|
|
|
|
setdatafolder savedf
|
|
return win_name
|
|
end
|
|
|
|
static function elog_panel_hook(s)
|
|
STRUCT WMWinHookStruct &s
|
|
|
|
Variable hookResult = 0
|
|
|
|
switch(s.eventCode)
|
|
case 6: // resize
|
|
// move bottom-aligned controls when the window is resized
|
|
variable b_top = s.winRect.bottom + 4
|
|
Button b_submit,pos={60,b_top}
|
|
Button b_clear,pos={110,b_top}
|
|
b_top += 24
|
|
Button b_attach,pos={160,b_top}
|
|
Button b_reply,pos={210,b_top}
|
|
b_top += 2
|
|
SetVariable sv_id,pos={46,b_top}
|
|
break
|
|
endswitch
|
|
|
|
return hookResult // 0 if nothing done, else 1
|
|
end
|
|
|
|
/// get a list of graph windows for a popup menu.
|
|
static function /s pm_list_attach_items()
|
|
|
|
// get graph names
|
|
string names = WinList("*", ";", "WIN:1;VISIBLE:1")
|
|
names = SortList(names, ";", 16)
|
|
|
|
// get corresponding graph titles
|
|
variable nnames = ItemsInList(names, ";")
|
|
variable iname
|
|
string name
|
|
string item
|
|
string items = ""
|
|
|
|
// format each entry like "name: title"
|
|
for (iname = 0; iname < nnames; iname += 1)
|
|
name = StringFromList(iname, names, ";")
|
|
getwindow /z $name, wtitle
|
|
if (v_flag == 0)
|
|
item = ReplaceString(";", s_value, ", ") // title
|
|
item = item + " (" + name + ")"
|
|
items = AddListItem(item, items, ";", inf)
|
|
endif
|
|
endfor
|
|
|
|
items = AddListItem("(none)", items, ";")
|
|
return items
|
|
end
|
|
|
|
/// button procedure for the Submit and Reply buttons
|
|
static function bp_submit(ba) : ButtonControl
|
|
STRUCT WMButtonAction &ba
|
|
|
|
switch( ba.eventCode )
|
|
case 2: // mouse up
|
|
string logbook = GetUserData(ba.win, "", "logbook")
|
|
string attributes
|
|
string message
|
|
string graphs
|
|
attributes = get_panel_attributes(ba.win)
|
|
message = get_panel_message(ba.win)
|
|
graphs = get_panel_graphs(ba.win)
|
|
|
|
variable id
|
|
if (cmpstr(ba.ctrlName, "b_reply") == 0)
|
|
// Reply button
|
|
ControlInfo /w=$ba.win sv_id
|
|
id = v_value
|
|
else
|
|
// Submit button
|
|
id = 0
|
|
endif
|
|
|
|
if ((elog_validate_attributes(logbook, attributes) == 0) && (strlen(message) > 0))
|
|
variable result
|
|
result = elog_create_entry(logbook, attributes, message, graphs=graphs, replyto=id)
|
|
if (result == 0)
|
|
svar /sdfr=get_elog_df(logbook) recent
|
|
recent = attributes
|
|
svar /sdfr=get_elog_df(logbook) recent_message
|
|
recent_message = message
|
|
else
|
|
abort "Submission failed. Error code " + num2str(result) + "."
|
|
endif
|
|
else
|
|
abort "Submission failed due to missing/invalid attribute."
|
|
endif
|
|
break
|
|
case -1: // control being killed
|
|
break
|
|
endswitch
|
|
|
|
return 0
|
|
end
|
|
|
|
/// select top graph window for attachment
|
|
static function bp_select_attach_top(ba) : ButtonControl
|
|
STRUCT WMButtonAction &ba
|
|
|
|
switch( ba.eventCode )
|
|
case 2: // mouse up
|
|
string graphs = WinName(0, 1, 1)
|
|
set_panel_graphs(ba.win, graphs)
|
|
break
|
|
case -1: // control being killed
|
|
break
|
|
endswitch
|
|
|
|
return 0
|
|
end
|
|
|
|
static function bp_attach(ba) : ButtonControl
|
|
STRUCT WMButtonAction &ba
|
|
|
|
switch( ba.eventCode )
|
|
case 2: // mouse up
|
|
string logbook = GetUserData(ba.win, "", "logbook")
|
|
string graphs
|
|
graphs = get_panel_graphs(ba.win)
|
|
|
|
variable id
|
|
ControlInfo /w=$ba.win sv_id
|
|
id = v_value
|
|
|
|
// TODO : is there a way around this restriction?
|
|
DoAlert /T="ELOG" 1, "This operation will replace all existing attachments. Do you want to continue?"
|
|
|
|
if ((id > 0) && (v_flag == 1))
|
|
variable result
|
|
result = elog_add_attachment(logbook, id, graphs)
|
|
if (result != 0)
|
|
abort "Submission failed. Error code " + num2str(result) + "."
|
|
endif
|
|
else
|
|
abort "Submission failed due to missing/invalid attribute."
|
|
endif
|
|
break
|
|
case -1: // control being killed
|
|
break
|
|
endswitch
|
|
|
|
return 0
|
|
end
|
|
|
|
static function bp_clear(ba) : ButtonControl
|
|
STRUCT WMButtonAction &ba
|
|
|
|
switch( ba.eventCode )
|
|
case 2: // mouse up
|
|
set_panel_attributes(ba.win, "", clear=1)
|
|
set_panel_message(ba.win, "")
|
|
set_panel_graphs(ba.win, "")
|
|
break
|
|
case -1: // control being killed
|
|
break
|
|
endswitch
|
|
|
|
return 0
|
|
end
|
|
|
|
static function /s get_default_panel_name()
|
|
string windowname
|
|
windowname = StringFromList(0, WinList("*ElogPanel*", ";", "WIN:64"), ";")
|
|
return windowname
|
|
end
|
|
|
|
/// get a list of attributes from the fields of the ELOG panel.
|
|
///
|
|
/// @param windowname window name of the ELOG panel
|
|
/// if empty, use default name "PearlElogPanel"
|
|
///
|
|
/// @return list of attributes to in the format <code>"key1=value1;key2=value2"</code>.
|
|
///
|
|
static function /s get_panel_attributes(windowname)
|
|
string windowname
|
|
|
|
if (strlen(windowname) == 0)
|
|
windowname = get_default_panel_name()
|
|
endif
|
|
if (strlen(windowname) == 0)
|
|
return ""
|
|
endif
|
|
|
|
string controls = ControlNameList(windowname, ";")
|
|
string attributes = ""
|
|
string control
|
|
string attribute
|
|
variable ico
|
|
variable nco = ItemsInList(controls, ";")
|
|
for (ico = 0; ico < nco; ico += 1)
|
|
control = StringFromList(ico, controls, ";")
|
|
attribute = GetUserData(windowname, control, "attribute")
|
|
if (strlen(attribute) > 0)
|
|
ControlInfo /w=$windowname $control
|
|
switch(v_flag)
|
|
case 2: // checkbox
|
|
attributes = ReplaceNumberByKey(attribute, attributes, v_value, "=", ";")
|
|
break
|
|
case 3: // popupmenu
|
|
case 5: // setvariable
|
|
attributes = ReplaceStringByKey(attribute, attributes, s_value, "=", ";")
|
|
break
|
|
endswitch
|
|
endif
|
|
endfor
|
|
|
|
return attributes
|
|
end
|
|
|
|
/// set the fields of the ELOG panel
|
|
///
|
|
/// @param windowname window name of the ELOG panel
|
|
/// if empty, use default name "PearlElogPanel"
|
|
///
|
|
/// @param attributes list of attributes to set (format "key1=value1;key2=value2")
|
|
///
|
|
/// @param clear what to do if a key is missing in attributes?
|
|
/// @arg 0 (default) leave the field unchanged
|
|
/// @arg 1 clear the field
|
|
///
|
|
static function /s set_panel_attributes(windowname, attributes, [clear])
|
|
string windowname
|
|
string attributes
|
|
variable clear
|
|
|
|
if (strlen(windowname) == 0)
|
|
windowname = get_default_panel_name()
|
|
endif
|
|
if (strlen(windowname) == 0)
|
|
return ""
|
|
endif
|
|
if (ParamIsDefault(clear))
|
|
clear = 0
|
|
endif
|
|
|
|
string path
|
|
|
|
string controls = ControlNameList(windowname, ";")
|
|
string control
|
|
string attribute
|
|
string value
|
|
variable numval
|
|
variable ico
|
|
variable nco = ItemsInList(controls, ";")
|
|
for (ico = 0; ico < nco; ico += 1)
|
|
control = StringFromList(ico, controls, ";")
|
|
attribute = GetUserData(windowname, control, "attribute")
|
|
if (strlen(attribute))
|
|
value = StringByKey(attribute, attributes, "=", ";")
|
|
if (strlen(value) || clear)
|
|
ControlInfo /w=$windowname $control
|
|
switch(v_flag)
|
|
case 2: // checkbox
|
|
numval = NumberByKey(attribute, attributes, "=", ";")
|
|
if ((numtype(numval) != 0) && clear)
|
|
numval = 0
|
|
endif
|
|
if (numtype(numval) == 0)
|
|
CheckBox $control, value=numval, win=$windowname
|
|
endif
|
|
break
|
|
case 3: // popupmenu
|
|
PopupMenu $control, popvalue=value, win=$windowname
|
|
break
|
|
case 5: // setvariable
|
|
SetVariable /z $control, value= _STR:value, win=$windowname
|
|
break
|
|
endswitch
|
|
endif
|
|
endif
|
|
endfor
|
|
|
|
return attributes
|
|
end
|
|
|
|
/// get the message field of the ELOG panel
|
|
///
|
|
/// @param windowname window name of the ELOG panel
|
|
/// if empty, use default name "PearlElogPanel"
|
|
///
|
|
/// @return message text
|
|
///
|
|
static function /s get_panel_message(windowname)
|
|
string windowname
|
|
|
|
if (strlen(windowname) == 0)
|
|
windowname = get_default_panel_name()
|
|
endif
|
|
if (strlen(windowname) == 0)
|
|
return ""
|
|
endif
|
|
|
|
string nb = windowname + "#Message"
|
|
notebook $nb selection={startOfFile, endOfFile}
|
|
getselection notebook, $nb, 2
|
|
|
|
return s_selection
|
|
end
|
|
|
|
/// set the message field of the ELOG panel
|
|
///
|
|
/// @param windowname window name of the ELOG panel
|
|
/// if empty, use default name "PearlElogPanel"
|
|
///
|
|
/// @param message message text that can be passed to the @c Notebook operation.
|
|
///
|
|
/// @return original message (unchanged)
|
|
///
|
|
static function /s set_panel_message(windowname, message)
|
|
string windowname
|
|
string message
|
|
|
|
if (strlen(windowname) == 0)
|
|
windowname = get_default_panel_name()
|
|
endif
|
|
|
|
string nb = windowname + "#Message"
|
|
notebook $nb selection={startOfFile, endOfFile},text=message
|
|
|
|
return message
|
|
end
|
|
|
|
/// get the names of the graphs selected for attachment
|
|
///
|
|
/// @returns a semicolon-separated list,
|
|
/// or the empty string if the selection is not valid.
|
|
///
|
|
/// in the current version, the function returns at most one graph.
|
|
/// in future versions, the function may return more than one graph.
|
|
///
|
|
static function /s get_panel_graphs(windowname)
|
|
string windowname // panel window name
|
|
|
|
if (strlen(windowname) == 0)
|
|
windowname = get_default_panel_name()
|
|
endif
|
|
if (strlen(windowname) == 0)
|
|
return ""
|
|
endif
|
|
|
|
ControlInfo /W=$windowname pm_attach
|
|
|
|
// menu item has the form: "title (name)"
|
|
string graphname = ReplaceString(")", StringFromList(ItemsInList(s_value, "(") - 1, s_value, "("), "")
|
|
string graphs = ""
|
|
string windows = WinList(graphname, ";", "WIN:1")
|
|
if (ItemsInList(windows) == 1)
|
|
graphs = graphname
|
|
else
|
|
graphs = ""
|
|
endif
|
|
|
|
return graphs
|
|
end
|
|
|
|
static function /s set_panel_graphs(windowname, graphs)
|
|
string windowname // panel window name. looks for default panel if empty.
|
|
string graphs // name of graph window to select for attachment.
|
|
|
|
if (strlen(windowname) == 0)
|
|
windowname = get_default_panel_name()
|
|
endif
|
|
if (strlen(windowname) == 0)
|
|
return ""
|
|
endif
|
|
|
|
// the panel supports only one graph
|
|
string graph = StringFromList(0, graphs, ";")
|
|
|
|
string items = pm_list_attach_items()
|
|
string item
|
|
string itemname
|
|
variable nitems = ItemsInList(items, ";")
|
|
variable iitem
|
|
for (iitem = 0; iitem < nitems; iitem += 1)
|
|
item = StringFromList(iitem, items, ";")
|
|
itemname = ReplaceString(")", StringFromList(ItemsInList(item, "(") - 1, item, "("), "")
|
|
if (cmpstr(graph, itemname) == 0)
|
|
iitem += 1
|
|
PopupMenu pm_attach mode=iitem, win=$windowname
|
|
break
|
|
endif
|
|
endfor
|
|
|
|
return graph
|
|
end |