[ecflow] 15/50: upstream 4.6.1 release

Alastair McKinstry mckinstry at moszumanska.debian.org
Wed Sep 20 15:30:44 UTC 2017


This is an automated email from the git hooks/post-receive script.

mckinstry pushed a commit to branch debian/master
in repository ecflow.

commit 0a2d80392af084783bbe920591b7f9270e2dbead
Author: Alastair McKinstry <mckinstry at debian.org>
Date:   Tue May 16 22:46:21 2017 +0100

    upstream 4.6.1 release
---
 ACore/src/File.cpp                                 |  1 +
 ACore/src/ecflow_version.h                         |  4 +-
 ANode/src/ExprAst.cpp                              |  4 +-
 ANode/src/Expression.cpp                           |  1 +
 ANode/src/InLimitMgr.cpp                           |  2 +-
 ANode/src/Node.cpp                                 |  4 +-
 AParser/test/data/bad_defs/trigger/ecflow_969.def  | 12 +++++
 .../data/test_autoarchive_ast_node_reset.def.log   | 37 +++++++++++++++
 CSim/test/data/test_autoarchive_family.def.log     | 43 +++++++++++++++++
 Pyext/ecflow/__init__.py                           |  2 +-
 Pyext/test/py_s_TestClientApi.py                   | 41 ++++++++--------
 Pyext/test/py_u_TestAutoAddExtern.py               |  2 +-
 VERSION.cmake                                      |  4 +-
 Viewer/src/CompactView.cpp                         |  9 ++--
 Viewer/src/NodeViewDelegate.cpp                    | 55 ++++++++++++++++------
 Viewer/src/OutputFileProvider.cpp                  |  2 +-
 Viewer/src/OutputItemWidget.cpp                    |  2 +-
 Viewer/src/OverviewProvider.cpp                    |  9 ++++
 Viewer/src/ServerList.cpp                          |  5 +-
 Viewer/src/TableNodeModel.cpp                      |  2 +-
 Viewer/src/TreeNodeViewDelegate.cpp                |  4 +-
 Viewer/src/VAttribute.cpp                          |  6 +++
 Viewer/src/VAttribute.hpp                          |  3 +-
 Viewer/src/VAttributeType.cpp                      | 29 ++++++++++++
 Viewer/src/VAttributeType.hpp                      |  1 +
 Viewer/src/VDateAttr.cpp                           | 35 +++++++-------
 Viewer/src/VDateAttr.hpp                           | 16 ++++++-
 Viewer/src/VEventAttr.cpp                          | 32 ++++++-------
 Viewer/src/VEventAttr.hpp                          | 15 +++++-
 Viewer/src/VGenVarAttr.cpp                         | 22 ++-------
 Viewer/src/VGenVarAttr.hpp                         | 14 +++++-
 Viewer/src/VLabelAttr.cpp                          | 43 ++++++++++-------
 Viewer/src/VLabelAttr.hpp                          | 15 +++++-
 Viewer/src/VLateAttr.cpp                           | 32 ++++++-------
 Viewer/src/VLateAttr.hpp                           | 17 ++++++-
 Viewer/src/VLimitAttr.cpp                          | 32 ++++++-------
 Viewer/src/VLimitAttr.hpp                          | 15 +++++-
 Viewer/src/VLimiterAttr.cpp                        | 38 ++++++---------
 Viewer/src/VLimiterAttr.hpp                        | 17 ++++++-
 Viewer/src/VMeterAttr.cpp                          | 32 ++++++-------
 Viewer/src/VMeterAttr.hpp                          | 15 +++++-
 Viewer/src/VModelData.cpp                          | 12 +++--
 Viewer/src/VNode.hpp                               |  2 +-
 Viewer/src/VRepeatAttr.cpp                         | 44 ++++++++++-------
 Viewer/src/VRepeatAttr.hpp                         | 16 ++++++-
 Viewer/src/VTimeAttr.cpp                           | 38 +++++++--------
 Viewer/src/VTimeAttr.hpp                           | 17 ++++++-
 Viewer/src/VTriggerAttr.cpp                        | 40 ++++++++--------
 Viewer/src/VTriggerAttr.hpp                        | 16 ++++++-
 Viewer/src/VUserVarAttr.cpp                        | 24 +++-------
 Viewer/src/VUserVarAttr.hpp                        | 14 +++++-
 share/ecflow/etc/ecflowview_highlighter.json       |  2 +-
 52 files changed, 609 insertions(+), 290 deletions(-)

diff --git a/ACore/src/File.cpp b/ACore/src/File.cpp
index 063b1a5..d24a10f 100644
--- a/ACore/src/File.cpp
+++ b/ACore/src/File.cpp
@@ -931,6 +931,7 @@ std::string File::root_source_dir()
       count++;
       if (count == 1000) break;
    }
+
    return string();
 }
 
diff --git a/ACore/src/ecflow_version.h b/ACore/src/ecflow_version.h
index 29a7792..a36ec36 100644
--- a/ACore/src/ecflow_version.h
+++ b/ACore/src/ecflow_version.h
@@ -1,10 +1,10 @@
 #ifndef ecflow_version_config_h
 #define ecflow_version_config_h
  
-#define ECFLOW_VERSION   "4.6.0"
+#define ECFLOW_VERSION   "4.6.1"
 
 #define ECFLOW_RELEASE   "4"
 #define ECFLOW_MAJOR     "6"
-#define ECFLOW_MINOR     "0"
+#define ECFLOW_MINOR     "1"
 
 #endif 
diff --git a/ANode/src/ExprAst.cpp b/ANode/src/ExprAst.cpp
index b6e84f7..b8df403 100644
--- a/ANode/src/ExprAst.cpp
+++ b/ANode/src/ExprAst.cpp
@@ -443,7 +443,7 @@ AstDivide* AstDivide::clone() const
 bool AstDivide::check(std::string& error_msg) const
 {
    if (right_ && right_->value() == 0) {
-      error_msg = "Divide by zero in trigger expression";
+      error_msg = "Error: Divide by zero in trigger expression";
       return false;
    }
    return true;
@@ -564,7 +564,7 @@ AstModulo* AstModulo::clone() const
 bool AstModulo::check(std::string& error_msg) const
 {
    if (right_ && right_->value() == 0) {
-      error_msg = "Modulo by zero in trigger expression";
+      error_msg = "Error: Modulo by zero in trigger expression";
       return false;
    }
    return true;
diff --git a/ANode/src/Expression.cpp b/ANode/src/Expression.cpp
index 872645a..fffe863 100644
--- a/ANode/src/Expression.cpp
+++ b/ANode/src/Expression.cpp
@@ -201,6 +201,7 @@ void Expression::createAST( Node* node, const std::string& exprType, std::string
          ss << "Failed to parse " << vec_[i].toString(exprType) << " at " << node->debugNodePath()
 			            << " because " << localErrorMsg << "\n\n";
          errorMsg += ss.str();
+         break;
       }
    }
 
diff --git a/ANode/src/InLimitMgr.cpp b/ANode/src/InLimitMgr.cpp
index 58c3fbb..10a9c6a 100644
--- a/ANode/src/InLimitMgr.cpp
+++ b/ANode/src/InLimitMgr.cpp
@@ -435,7 +435,7 @@ limit_ptr InLimitMgr::find_limit(const InLimit& inLimit, std::string& errorMsg,
    if ( inLimit.tokens() > referencedLimit->theLimit() ) {
       if (reportWarnings) {
          // in limit exceeds the LIMIT value
-         std::stringstream ss;
+         std::stringstream ss; ss << "Warning: ";
          ss << node_->debugType() << " " << node_->absNodePath() << " has a " << inLimit.toString() << " reference\n";
          ss << " with value '" << inLimit.tokens() << "' which exceeds '" << referencedLimit->theLimit() << "' defined on the Limit\n";
          warningMsg += ss.str();
diff --git a/ANode/src/Node.cpp b/ANode/src/Node.cpp
index b0efc59..380fd95 100644
--- a/ANode/src/Node.cpp
+++ b/ANode/src/Node.cpp
@@ -1300,7 +1300,7 @@ bool Node::check_expressions(Ast* ast,const std::string& expr,bool trigger, std:
       ast->accept(astVisitor);
 
       if ( !astVisitor.errorMsg().empty() ) {
-         errorMsg += "Expression node tree references failed for '";
+         errorMsg += "Error: Expression node tree references failed for '";
          if ( trigger ) errorMsg += "trigger ";
          else           errorMsg += "complete ";
          errorMsg += expr;
@@ -1361,7 +1361,7 @@ bool Node::check(std::string& errorMsg, std::string& warningMsg) const
 
    // check inLimit references to limits.
    // Client: Unresolved references, which are not in the externs reported as errors/warnings
-   // Server: There are no exerns, all unresolved references reported as errors
+   // Server: There are no externs, all unresolved references reported as errors
    bool reportErrors = true;
    bool reportWarnings = true;
    inLimitMgr_.check(errorMsg,warningMsg,reportErrors, reportWarnings);
diff --git a/AParser/test/data/bad_defs/trigger/ecflow_969.def b/AParser/test/data/bad_defs/trigger/ecflow_969.def
new file mode 100644
index 0000000..6290bf3
--- /dev/null
+++ b/AParser/test/data/bad_defs/trigger/ecflow_969.def
@@ -0,0 +1,12 @@
+suite suite
+    task pertinic
+        event 1
+    task eda_pert
+    task rot
+    family pert_ic
+             complete pertinic:1
+             trigger eda_pert
+             trigger -a rot==complete
+             trigger -a pertinic==complete and not pertinic:1
+    endfamily
+endsuite
diff --git a/CSim/test/data/test_autoarchive_ast_node_reset.def.log b/CSim/test/data/test_autoarchive_ast_node_reset.def.log
new file mode 100644
index 0000000..0c62ff4
--- /dev/null
+++ b/CSim/test/data/test_autoarchive_ast_node_reset.def.log
@@ -0,0 +1,37 @@
+LOG:[16:39:41 10.5.2017]  complete: /s1
+LOG:[16:39:41 10.5.2017]  queued: /s1/family
+LOG:[16:39:41 10.5.2017]  queued: /s1/family/t
+LOG:[16:39:41 10.5.2017]  queued: /s1/family/t2
+LOG:[16:39:41 10.5.2017]  complete: /s1/family
+LOG:[16:39:41 10.5.2017]  complete: /s1/family/t
+LOG:[16:39:41 10.5.2017]  complete: /s1/family/t2
+LOG:[16:39:41 10.5.2017]  queued: /s2
+LOG:[16:39:41 10.5.2017]  queued: /s2/family
+LOG:[16:39:41 10.5.2017]  queued: /s2/family/t
+LOG:[16:39:41 10.5.2017]  queued: /s3
+LOG:[16:39:41 10.5.2017]  queued: /s3/family
+LOG:[16:39:41 10.5.2017]  queued: /s3/family/t
+MSG:[16:39:41 10.5.2017]  time dependency(0) max_simulation_period(24:00:00) calendarIncrement(01:00:00)
+LOG:[16:39:41 10.5.2017]  submitted: /s2/family/t
+LOG:[16:39:41 10.5.2017]  submitted: /s2/family
+LOG:[16:39:41 10.5.2017]  submitted: /s2
+LOG:[16:39:41 10.5.2017]  submitted: /
+LOG:[16:39:41 10.5.2017]  active: /s2/family/t
+LOG:[16:39:41 10.5.2017]  active: /s2/family
+LOG:[16:39:41 10.5.2017]  active: /s2
+LOG:[16:39:41 10.5.2017]  active: /
+LOG:[16:39:41 10.5.2017]  submitted: /s3/family/t
+LOG:[16:39:41 10.5.2017]  submitted: /s3/family
+LOG:[16:39:41 10.5.2017]  submitted: /s3
+LOG:[16:39:41 10.5.2017]  active: /s3/family/t
+LOG:[16:39:41 10.5.2017]  active: /s3/family
+LOG:[16:39:41 10.5.2017]  active: /s3
+LOG:[16:39:41 10.5.2017]  complete: /s2/family/t
+LOG:[16:39:41 10.5.2017]  complete: /s2/family
+LOG:[16:39:41 10.5.2017]  complete: /s2
+LOG:[16:39:41 10.5.2017]  complete: /s3/family/t
+LOG:[16:39:41 10.5.2017]  complete: /s3/family
+LOG:[16:39:41 10.5.2017]  complete: /s3
+LOG:[16:39:41 10.5.2017]  complete: /
+MSG:[16:39:41 10.5.2017] autoarchive SUITE:/s2
+MSG:[16:39:41 10.5.2017] autoarchive SUITE:/s3
diff --git a/CSim/test/data/test_autoarchive_family.def.log b/CSim/test/data/test_autoarchive_family.def.log
new file mode 100644
index 0000000..54b82f1
--- /dev/null
+++ b/CSim/test/data/test_autoarchive_family.def.log
@@ -0,0 +1,43 @@
+LOG:[16:39:41 10.5.2017]  queued: /test_autoarchive_family
+LOG:[16:39:41 10.5.2017]  queued: /test_autoarchive_family/family
+LOG:[16:39:41 10.5.2017]  queued: /test_autoarchive_family/family/t
+LOG:[16:39:41 10.5.2017]  queued: /test_autoarchive_1_2_hours_real
+LOG:[16:39:41 10.5.2017]  queued: /test_autoarchive_1_2_hours_real/family
+LOG:[16:39:41 10.5.2017]  queued: /test_autoarchive_1_2_hours_real/family/t
+LOG:[16:39:41 10.5.2017]  queued: /test_autoarchive_1_2_day_relative
+LOG:[16:39:41 10.5.2017]  queued: /test_autoarchive_1_2_day_relative/family
+LOG:[16:39:41 10.5.2017]  queued: /test_autoarchive_1_2_day_relative/family/t
+MSG:[16:39:41 10.5.2017]  time dependency(0) max_simulation_period(48:00:00) calendarIncrement(01:00:00)
+LOG:[16:39:41 10.5.2017]  submitted: /test_autoarchive_family/family/t
+LOG:[16:39:41 10.5.2017]  submitted: /test_autoarchive_family/family
+LOG:[16:39:41 10.5.2017]  submitted: /test_autoarchive_family
+LOG:[16:39:41 10.5.2017]  submitted: /
+LOG:[16:39:41 10.5.2017]  active: /test_autoarchive_family/family/t
+LOG:[16:39:41 10.5.2017]  active: /test_autoarchive_family/family
+LOG:[16:39:41 10.5.2017]  active: /test_autoarchive_family
+LOG:[16:39:41 10.5.2017]  active: /
+LOG:[16:39:41 10.5.2017]  submitted: /test_autoarchive_1_2_hours_real/family/t
+LOG:[16:39:41 10.5.2017]  submitted: /test_autoarchive_1_2_hours_real/family
+LOG:[16:39:41 10.5.2017]  submitted: /test_autoarchive_1_2_hours_real
+LOG:[16:39:41 10.5.2017]  active: /test_autoarchive_1_2_hours_real/family/t
+LOG:[16:39:41 10.5.2017]  active: /test_autoarchive_1_2_hours_real/family
+LOG:[16:39:41 10.5.2017]  active: /test_autoarchive_1_2_hours_real
+LOG:[16:39:41 10.5.2017]  submitted: /test_autoarchive_1_2_day_relative/family/t
+LOG:[16:39:41 10.5.2017]  submitted: /test_autoarchive_1_2_day_relative/family
+LOG:[16:39:41 10.5.2017]  submitted: /test_autoarchive_1_2_day_relative
+LOG:[16:39:41 10.5.2017]  active: /test_autoarchive_1_2_day_relative/family/t
+LOG:[16:39:41 10.5.2017]  active: /test_autoarchive_1_2_day_relative/family
+LOG:[16:39:41 10.5.2017]  active: /test_autoarchive_1_2_day_relative
+LOG:[16:39:41 10.5.2017]  complete: /test_autoarchive_family/family/t
+LOG:[16:39:41 10.5.2017]  complete: /test_autoarchive_family/family
+LOG:[16:39:41 10.5.2017]  complete: /test_autoarchive_family
+LOG:[16:39:41 10.5.2017]  complete: /test_autoarchive_1_2_hours_real/family/t
+LOG:[16:39:41 10.5.2017]  complete: /test_autoarchive_1_2_hours_real/family
+LOG:[16:39:41 10.5.2017]  complete: /test_autoarchive_1_2_hours_real
+LOG:[16:39:41 10.5.2017]  complete: /test_autoarchive_1_2_day_relative/family/t
+LOG:[16:39:41 10.5.2017]  complete: /test_autoarchive_1_2_day_relative/family
+LOG:[16:39:41 10.5.2017]  complete: /test_autoarchive_1_2_day_relative
+LOG:[16:39:41 10.5.2017]  complete: /
+MSG:[16:39:41 10.5.2017] autoarchive FAMILY:/test_autoarchive_1_2_hours_real/family
+MSG:[16:39:41 10.5.2017] autoarchive FAMILY:/test_autoarchive_family/family
+MSG:[16:39:41 10.5.2017] autoarchive FAMILY:/test_autoarchive_1_2_day_relative/family
diff --git a/Pyext/ecflow/__init__.py b/Pyext/ecflow/__init__.py
index c21b843..b4ac7df 100644
--- a/Pyext/ecflow/__init__.py
+++ b/Pyext/ecflow/__init__.py
@@ -15,6 +15,6 @@ from ecflow import *
 The ecFlow python module
 """
 
-__version__ = '4.6.0'
+__version__ = '4.6.1'
 
 # http://stackoverflow.com/questions/13040646/how-do-i-create-documentation-with-pydoc
diff --git a/Pyext/test/py_s_TestClientApi.py b/Pyext/test/py_s_TestClientApi.py
index 4ac8f39..0ca36a9 100644
--- a/Pyext/test/py_s_TestClientApi.py
+++ b/Pyext/test/py_s_TestClientApi.py
@@ -116,12 +116,13 @@ def test_client_get_server_defs(ci):
 
 def test_client_new_log(ci, port):
     print("test_client_new_log")
-    try : os.remove("./test_client_new_log.log") # delete file if it exists
+    new_log_file_name = "./test_client_new_log_" + str(os.getpid()) + ".log"
+    try : os.remove(new_log_file_name) # delete file if it exists
     except: pass
     
-    ci.new_log("./test_client_new_log.log") 
+    ci.new_log(new_log_file_name) 
     ci.flush_log() # close log file and force write to disk
-    assert os.path.exists("./test_client_new_log.log"), "New log does not exist"
+    assert os.path.exists(new_log_file_name), "New log does not exist"
     
     # reset new log to original
     ci.new_log(Test.log_file_path(port)) 
@@ -131,7 +132,8 @@ def test_client_new_log(ci, port):
     try:     log_text = log_file.read();     # assume log file not to big
     finally: log_file.close();
     assert log_text.find("--ping") != -1, "Expected to find --ping in log file"
-    try: os.remove("./test_client_new_log.log")
+ 
+    try: os.remove(new_log_file_name)
     except: pass
 
 
@@ -209,7 +211,7 @@ def test_client_load_from_disk(ci):
     print("test_client_load_from_disk")
     ci.delete_all() # start fresh
     defs = create_defs();
-    defs_file = "test_client_load_from_disk.def"
+    defs_file = "test_client_load_from_disk_" + str(os.getpid()) + ".def"
     defs.save_as_defs(defs_file)     
     assert os.path.exists(defs_file), "Expected file " + defs_file + " to exist after defs.save_as_defs()"
     ci.load(defs_file) # open and parse defs file, and load into server.\n"
@@ -546,7 +548,7 @@ def test_client_check(ci):
     # SERVER side check
     ci.load(defs)
     server_check = ci.check("") # empty string means check the whole defs, otherwise a node path can be specified.
-    # print server_check
+    # print(server_check)
     assert len(server_check) > 0, "Expected defs to fail, since no externs in server "
     
 def test_client_suites(ci):
@@ -1339,11 +1341,12 @@ def test_client_replace(ci,on_disk):
     #   f2
     #     t1
     #     t2
+    test_client_replace_def_file = "test_client_replace_" + str(os.getpid()) + ".def"
     client_def = create_defs("s1")
     client_def.find_suite("s1").add_family("f2").add_task("t1")
     if on_disk:
-        client_def.save_as_defs("test_client_replace.def")
-        client_def = "test_client_replace.def"
+        client_def.save_as_defs(test_client_replace_def_file)
+        client_def = test_client_replace_def_file
     
     ci.replace("/s1/f2",client_def,True,False)  # True means create parents as needed, False means don't bypass checks/zombies
     ci.get_server_defs()
@@ -1357,8 +1360,8 @@ def test_client_replace(ci,on_disk):
     client_def = Defs()
     client_def.add_suite("s1")    # should only have the suite
     if on_disk:
-        client_def.save_as_defs("test_client_replace.def")
-        client_def = "test_client_replace.def"
+        client_def.save_as_defs(test_client_replace_def_file)
+        client_def = test_client_replace_def_file
 
     ci.replace("/s1",client_def)   
     ci.get_server_defs()
@@ -1372,8 +1375,8 @@ def test_client_replace(ci,on_disk):
     client_def = Defs();
     client_def.add_suite("s2")
     if on_disk:
-        client_def.save_as_defs("test_client_replace.def")
-        client_def = "test_client_replace.def"
+        client_def.save_as_defs(test_client_replace_def_file)
+        client_def = test_client_replace_def_file
 
     ci.replace("/s2",client_def,True,False)  # True means create parents as needed, False means don't bypass checks/zombies
     ci.get_server_defs()
@@ -1384,8 +1387,8 @@ def test_client_replace(ci,on_disk):
     client_def = Defs();
     client_def.add_suite("s2").add_task("t1")
     if on_disk:
-        client_def.save_as_defs("test_client_replace.def")
-        client_def = "test_client_replace.def"
+        client_def.save_as_defs(test_client_replace_def_file)
+        client_def = test_client_replace_def_file
 
     ci.replace("/s2",client_def) 
         
@@ -1393,7 +1396,7 @@ def test_client_replace(ci,on_disk):
     assert len(list(ci.get_defs().suites)) == 2 ," Expected two suites:\n" + str(ci.get_defs())
     assert ci.get_defs().find_abs_node("/s2/t1") != None, "Expected to find task /s2/t1\n" + str(ci.get_defs())
     if on_disk:
-        os.remove(client_def)
+        os.remove(test_client_replace_def_file)
 
 def test_client_kill(ci):
     pass
@@ -1562,7 +1565,7 @@ def test_client_check_defstatus(ci):
     ci.begin_all_suites()
      
     ci.sync_local() # get the changes, synced with local defs
-    #print ci.get_defs();
+    #print(ci.get_defs())
     task_t1 = ci.get_defs().find_abs_node(t1)
     task_t2 = ci.get_defs().find_abs_node(t2)
     assert task_t1 != None,"Could not find t1"
@@ -1597,7 +1600,7 @@ def test_ECFLOW_189(ci):
     ci.begin_all_suites()
     
     ci.sync_local() # get the changes, synced with local defs
-    #print ci.get_defs();
+    #print(ci.get_defs())
     task_t1 = ci.get_defs().find_abs_node("/test_ECFLOW_189/f1/t1")
     task_t2 = ci.get_defs().find_abs_node("/test_ECFLOW_189/f1/t2")
     assert task_t1 != None,"Could not find /test_ECFLOW_189/f1/t1"
@@ -1614,7 +1617,7 @@ def test_ECFLOW_189(ci):
      
     time.sleep(3)
     ci.sync_local() # get the changes, synced with local defs
-    #print ci.get_defs();
+    #print(ci.get_defs())
     task_t1 = ci.get_defs().find_abs_node("/test_ECFLOW_189/f1/t1")
     task_t2 = ci.get_defs().find_abs_node("/test_ECFLOW_189/f1/t2")
     assert task_t1.get_state() == State.queued, "Expected state queued but found " + str(task_t1.get_state())
@@ -1645,7 +1648,7 @@ def test_ECFLOW_199(ci):
     ci.begin_all_suites()
     
     ci.sync_local() # get the changes, synced with local defs
-    #print ci.get_defs();
+    #print(ci.get_defs())
     assert len(list(ci.changed_node_paths)) == 0, "Expected first call to sync_local, to have no changed paths but found " + str(len(list(ci.changed_node_paths)))
     
     # ok now resume t1/t2, they should remain queued, since the Suite is still suspended
diff --git a/Pyext/test/py_u_TestAutoAddExtern.py b/Pyext/test/py_u_TestAutoAddExtern.py
index 1694f32..3158e44 100644
--- a/Pyext/test/py_u_TestAutoAddExtern.py
+++ b/Pyext/test/py_u_TestAutoAddExtern.py
@@ -17,7 +17,7 @@ from ecflow import Suite, Family, Task, Defs, Client, debug_build
 
 def check_then_auto_add_extern(defs):
     error_msg = defs.check() 
-    print error_msg
+    print(error_msg)
     assert len(error_msg) !=0,"Expect error in checks\n" + str(defs)
     
     defs.auto_add_externs(True)
diff --git a/VERSION.cmake b/VERSION.cmake
index bd4096c..e2a200d 100644
--- a/VERSION.cmake
+++ b/VERSION.cmake
@@ -1,7 +1,7 @@
 set( ECFLOW_RELEASE  "4" )
 set( ECFLOW_MAJOR    "6" )
-set( ECFLOW_MINOR    "0" )
+set( ECFLOW_MINOR    "1" )
 
 # use this form to be consistent with other packages,+ allow standard extraction of version from scripts
 # could replaced "4.0.8" with "${ECFLOW_RELEASE}.${ECFLOW_MAJOR}.${ECFLOW_MINOR}"
-set( ${PROJECT_NAME}_VERSION_STR  "4.6.0" )
+set( ${PROJECT_NAME}_VERSION_STR  "4.6.1" )
diff --git a/Viewer/src/CompactView.cpp b/Viewer/src/CompactView.cpp
index 7a2a575..c8705ac 100644
--- a/Viewer/src/CompactView.cpp
+++ b/Viewer/src/CompactView.cpp
@@ -824,7 +824,8 @@ void CompactView::drawRow(QPainter* painter,int start,int xOffset,int& yp,int& i
                     //line towards the siblings  - downwards
                     if(item->hasMoreSiblings)
                     {
-                        painter->drawLine(lineX,lineY,lineX,lineY+rh/2);
+                        //painter->drawLine(lineX,lineY,lineX,lineY+rh/2);
+                        painter->drawLine(lineX,lineY,lineX,yp+rh);
                         indentVec[item->level]=lineX;
                     }
                     else
@@ -836,7 +837,8 @@ void CompactView::drawRow(QPainter* painter,int start,int xOffset,int& yp,int& i
                     int lineY=yp+item->height/2;
 
                     painter->drawLine(lineX,lineY,lineX2,lineY);
-                    painter->drawLine(lineX,lineY+rh/2,lineX,lineY-rh/2);
+                    //painter->drawLine(lineX,lineY+rh/2,lineX,lineY-rh/2);
+                    painter->drawLine(lineX,yp,lineX,yp+rh);
                     indentVec[item->level]=lineX;
                 }
 
@@ -845,7 +847,8 @@ void CompactView::drawRow(QPainter* painter,int start,int xOffset,int& yp,int& i
                 {
                     int lineY=yp+item->height/2;
                     painter->drawLine(lineX,lineY,lineX2,lineY);
-                    painter->drawLine(lineX,lineY,lineX,lineY-rh/2);
+                    //painter->drawLine(lineX,lineY,lineX,lineY-rh/2);
+                    painter->drawLine(lineX,lineY,lineX,yp);
                     indentVec[item->level]=0;
                 }
             }
diff --git a/Viewer/src/NodeViewDelegate.cpp b/Viewer/src/NodeViewDelegate.cpp
index ddbab34..e088f02 100644
--- a/Viewer/src/NodeViewDelegate.cpp
+++ b/Viewer/src/NodeViewDelegate.cpp
@@ -457,13 +457,12 @@ int NodeViewDelegate::renderLabel(QPainter *painter,QStringList data,const QStyl
 	int multiCnt=val.count('\n');
 
 	QRect nameRect;
-	QRect valRect;
-	QRect multiValRect;
+    QRect valRect,valRestRect;
 
 	QFont nameFont=attrFont_;
 	nameFont.setBold(true);
 	QFont valFont=attrFont_;
-	QString multiVal;
+    QString valFirst,valRest;
 
 	if(multiCnt ==0 )
 	{
@@ -492,16 +491,29 @@ int NodeViewDelegate::renderLabel(QPainter *painter,QStringList data,const QStyl
 		nameRect.setWidth(nameWidth);
         nameRect.setHeight(attrBox_->height-attrBox_->topPadding-attrBox_->bottomPadding);
 
-		//The value rectangle
-		fm=QFontMetrics(valFont);
-        QSize valSize=fm.size(0,val);
+        //The value rectangles
+        fm=QFontMetrics(valFont);
+
+        //First row comes after the name rect!
+        QStringList valLst=val.split("\n");
+        Q_ASSERT(valLst.count() > 0);
+        valFirst=valLst[0];
+
+        valRect=nameRect;
+        valRect.setX(nameRect.x() + nameRect.width() + attrBox_->spacing);
+        valRect.setWidth(fm.width(valFirst));
+
+        //The rest of the rows
+        valLst.takeFirst();
+        valRest=valLst.join("\n");
+        QSize valSize=fm.size(0,valRest);
 
-		//Multiple line
-        valRect = QRect(nameRect.x(),
+        valRestRect = QRect(nameRect.x(),
                 nameRect.y()+nameRect.height()+2,
                 valSize.width(),valSize.height());
 
-        currentRight=valRect.x()+qMax(nameWidth,valSize.width());
+        currentRight=qMax(valRect.x()+valRect.width(),
+                     valRestRect.x() + valRestRect.width());
 	}
 
 
@@ -527,7 +539,10 @@ int NodeViewDelegate::renderLabel(QPainter *painter,QStringList data,const QStyl
     if(multiCnt ==0 )
         painter->drawText(attrBox_->adjustTextRect(valRect),Qt::AlignLeft | Qt::AlignVCenter,val);
     else
-        painter->drawText(valRect,Qt::AlignLeft | Qt::AlignVCenter,val);
+    {
+        painter->drawText(attrBox_->adjustTextRect(valRect),Qt::AlignLeft | Qt::AlignVCenter,valFirst);
+        painter->drawText(valRestRect,Qt::AlignLeft | Qt::AlignVCenter,valRest);
+    }
 
     if(selected && drawAttrSelectionRect_)
     {
@@ -581,13 +596,25 @@ void NodeViewDelegate::labelSize(QStringList data,int& totalWidth,int& totalHeig
         //The text rectangle
         QFontMetrics fm(nameFont);
         int nameWidth=fm.width(name);
+        int startX=currentRight+attrBox_->leftPadding;
         currentRight+=attrBox_->leftPadding+nameWidth;
         currentBottom+=attrBox_->height-attrBox_->topPadding-attrBox_->bottomPadding;
 
         //The value rectangle
         fm=QFontMetrics(valFont);
-        QSize valSize=fm.size(0,val);
-        currentRight+=qMax(nameWidth,valSize.width());
+
+        //First row comes after the name rect!
+        QStringList valLst=val.split("\n");
+        Q_ASSERT(valLst.count() > 0);
+
+        currentRight+=attrBox_->spacing+fm.width(valLst[0]);
+
+        //The rest of the rows
+        valLst.takeFirst();
+        QString valRest=valLst.join("\n");
+        QSize valSize=fm.size(0,valRest);
+
+        currentRight=qMax(currentRight,startX+valSize.width());
         currentBottom+=2+valSize.height();
     }
 
@@ -607,11 +634,11 @@ int NodeViewDelegate::labelHeight(int lineNum) const
 
     //value rect
     QStringList lst;
-    for(int i=0; i < lineNum; i++)
+    for(int i=0; i < lineNum-1; i++)
         lst << "1";
 
     QFontMetrics fm(attrFont_);
-    QSize valSize=fm.size(0,lst.join(QString('\n')));
+    QSize valSize=fm.size(0,lst.join(QString("\n")));
     currentBottom+=2+valSize.height();
 
     return currentBottom+attrBox_->bottomPadding+attrBox_->bottomMargin;
diff --git a/Viewer/src/OutputFileProvider.cpp b/Viewer/src/OutputFileProvider.cpp
index 3905e11..6b87ad7 100644
--- a/Viewer/src/OutputFileProvider.cpp
+++ b/Viewer/src/OutputFileProvider.cpp
@@ -165,7 +165,7 @@ void OutputFileProvider::fetchFile(ServerHandler *server,VNode *n,const std::str
     {
         if(n->isSubmitted())
             reply_->addLog("REMARK>This file is the <b>current</b> job output (defined by variable <b>ECF_JOBOUT</b>), but \
-                  beacuse the node status is <b>submitted</b> it may contain the ouput from a previous run!");
+                  because the node status is <b>submitted</b> it may contain the ouput from a previous run!");
         else
             reply_->addLog("REMARK>This file is the <b>current</b> job output (defined by variable <b>ECF_JOBOUT</b>).");
     }
diff --git a/Viewer/src/OutputItemWidget.cpp b/Viewer/src/OutputItemWidget.cpp
index 011a8e1..b4507e8 100644
--- a/Viewer/src/OutputItemWidget.cpp
+++ b/Viewer/src/OutputItemWidget.cpp
@@ -289,7 +289,7 @@ void OutputItemWidget::infoReady(VReply* reply)
             hasMessage=true;
             submittedWarning_=true;
             messageLabel_->showWarning("This is the current job output (as defined by variable ECF_JOBOUT), but \
-                   beacuse the node status is <b>submitted</b> it may contain the ouput from a previous run!");
+                   because the node status is <b>submitted</b> it may contain the ouput from a previous run!");
         }
         else
         {
diff --git a/Viewer/src/OverviewProvider.cpp b/Viewer/src/OverviewProvider.cpp
index 9c9adc1..ada0a40 100644
--- a/Viewer/src/OverviewProvider.cpp
+++ b/Viewer/src/OverviewProvider.cpp
@@ -11,6 +11,7 @@
 
 #include "ConnectState.hpp"
 #include "ServerHandler.hpp"
+#include "VAttribute.hpp"
 #include "VNode.hpp"
 #include "VNState.hpp"
 #include "VSState.hpp"
@@ -279,6 +280,14 @@ void OverviewProvider::nodeInfo(VInfoNode* info,std::stringstream& f)
 		f << inc << "edit " << (*it).name() << " '" << (*it).theValue() << "'\n";
 	}
 
+    //Other attributes
+    const std::vector<VAttribute*>& attr=node->attr();
+    for(std::vector<VAttribute*>::const_iterator it=attr.begin(); it != attr.end(); ++it)
+    {
+        if((*it)->typeName() != "var" && (*it)->typeName() != "genvar")
+            f << inc << (*it)->definition().toStdString() << "\n";
+    }
+
 	//Print children
 	for(unsigned int i=0; i < node->numOfChildren(); i++)
 	{
diff --git a/Viewer/src/ServerList.cpp b/Viewer/src/ServerList.cpp
index 9d0f94c..a95acd8 100644
--- a/Viewer/src/ServerList.cpp
+++ b/Viewer/src/ServerList.cpp
@@ -295,12 +295,13 @@ bool ServerList::load()
 
     if(!errStr.empty())
     {
-        errStr="Cound not parse the <b>server list file</b> (servers.txt) properly. The \
+        errStr="<b>Could not parse</b> the server list file <u>" + localFile_ + "</u>. The \
                     following errors occured:<br><br>" +
-                errStr + "<br><i>Note</i>: ecFlowUi will carry on but not all the speciefied servers will be available!";
+                errStr + "<br>Please <b>correct the errors</b> in the server list file and restart ecFlowUI!";
         UserMessage::setEchoToCout(false);
         UserMessage::message(UserMessage::ERROR,true,errStr);
         UserMessage::setEchoToCout(true);
+        exit(1);
     }
 
 	if(count() == 0)
diff --git a/Viewer/src/TableNodeModel.cpp b/Viewer/src/TableNodeModel.cpp
index cffbcbd..92a9224 100644
--- a/Viewer/src/TableNodeModel.cpp
+++ b/Viewer/src/TableNodeModel.cpp
@@ -168,7 +168,7 @@ QVariant TableNodeModel::nodeData(const QModelIndex& index, int role) const
                 id == TriggerColumn)
 		{
             if(VAttribute* a=vnode->attributeForType(0,columnToAttrType(id)))
-                return a->data();
+                return a->data(true);
             else
                 return QVariant();
 		}
diff --git a/Viewer/src/TreeNodeViewDelegate.cpp b/Viewer/src/TreeNodeViewDelegate.cpp
index ca8f8fe..df6372b 100644
--- a/Viewer/src/TreeNodeViewDelegate.cpp
+++ b/Viewer/src/TreeNodeViewDelegate.cpp
@@ -96,7 +96,9 @@ QSize TreeNodeViewDelegate::sizeHint(const QStyleOptionViewItem&, const QModelIn
 			for(int i=0; i < attLineNum; i++)
 				lst << "1";
 
-            return QSize(100,fm.size(0,lst.join(QString('\n'))).height()+6);
+            //return QSize(100,fm.size(0,lst.join(QString('\n'))).height()+6);
+            return QSize(100,labelHeight(attLineNum));
+
 		}
 	}
 
diff --git a/Viewer/src/VAttribute.cpp b/Viewer/src/VAttribute.cpp
index deb394c..b3bb235 100644
--- a/Viewer/src/VAttribute.cpp
+++ b/Viewer/src/VAttribute.cpp
@@ -40,6 +40,12 @@ QString VAttribute::toolTip() const
     return (t)?(t->toolTip(data())):QString();
 }
 
+QString VAttribute::definition() const
+{
+    VAttributeType* t=type();
+    return (t)?(t->definition(data())):QString();
+}
+
 const std::string& VAttribute::typeName() const
 {
     VAttributeType* t=type();
diff --git a/Viewer/src/VAttribute.hpp b/Viewer/src/VAttribute.hpp
index 5981704..9b68426 100644
--- a/Viewer/src/VAttribute.hpp
+++ b/Viewer/src/VAttribute.hpp
@@ -38,7 +38,8 @@ public:
     std::string strName() const;
     const std::string& typeName() const;
     std::string fullPath() const;
-    virtual QStringList data() const=0;
+    virtual QStringList data(bool firstLine=false) const=0;
+    QString definition() const;
     bool sameAs(QStringList d) const;
     bool sameContents(VItem*) const;
     bool value(const std::string& key,std::string& val) const;
diff --git a/Viewer/src/VAttributeType.cpp b/Viewer/src/VAttributeType.cpp
index b3447bd..c410228 100644
--- a/Viewer/src/VAttributeType.cpp
+++ b/Viewer/src/VAttributeType.cpp
@@ -141,4 +141,33 @@ void VAttributeType::load(VProperty* group)
     }
 }
 
+
 static SimpleLoader<VAttributeType> loader("attribute");
+
+//Initialise attribute types
+
+#include "VLabelAttr.hpp"
+#include "VMeterAttr.hpp"
+#include "VEventAttr.hpp"
+#include "VLimitAttr.hpp"
+#include "VLimiterAttr.hpp"
+#include "VRepeatAttr.hpp"
+#include "VTriggerAttr.hpp"
+#include "VDateAttr.hpp"
+#include "VTimeAttr.hpp"
+#include "VLateAttr.hpp"
+#include "VGenVarAttr.hpp"
+#include "VUserVarAttr.hpp"
+
+static VLabelAttrType labelAttrType;
+static VMeterAttrType meterAttType;
+static VEventAttrType eventAttrType;
+static VLimitAttrType limitAttrType;
+static VLimiterAttrType limiterAttrType;
+static VRepeatAttrType repeatAttrType;
+static VTriggerAttrType triggerAttrType;
+static VDateAttrType dateAttrType;
+static VTimeAttrType timeAttrType;
+static VLateAttrType lateAttrType;
+static VGenVarAttrType genvarAttrType;
+static VUserVarAttrType uservarAttrType;
diff --git a/Viewer/src/VAttributeType.hpp b/Viewer/src/VAttributeType.hpp
index 3e941f5..84395bc 100644
--- a/Viewer/src/VAttributeType.hpp
+++ b/Viewer/src/VAttributeType.hpp
@@ -35,6 +35,7 @@ public:
     int searchKeyToDataIndex(const std::string& key) const;
     QStringList searchKeys() const;
     virtual QString toolTip(QStringList d) const {return QString();}
+    virtual QString definition(QStringList d) const {return QString();}
 
     static void scan(VNode* vnode,std::vector<VAttribute*>& v);
     typedef void (*ScanProc) (VNode* vnode,std::vector<VAttribute*>& vec);
diff --git a/Viewer/src/VDateAttr.cpp b/Viewer/src/VDateAttr.cpp
index 2246da4..7d5a00c 100644
--- a/Viewer/src/VDateAttr.cpp
+++ b/Viewer/src/VDateAttr.cpp
@@ -19,19 +19,6 @@
 // VDateAttrType
 //================================
 
-class VDateAttrType : public VAttributeType
-{
-public:
-    explicit VDateAttrType();
-    QString toolTip(QStringList d) const;
-    void encode(const DateAttr& d,QStringList& data);
-    void encode(const DayAttr& d,QStringList& data);
-
-private:
-    enum DataIndex {TypeIndex=0,NameIndex=1};
-};
-
-
 VDateAttrType::VDateAttrType() : VAttributeType("date")
 {
     dataCount_=2;
@@ -50,6 +37,16 @@ QString VDateAttrType::toolTip(QStringList d) const
     return t;
 }
 
+QString VDateAttrType::definition(QStringList d) const
+{
+    QString t;
+    if(d.count() == dataCount_)
+    {
+        t+=" " + d[NameIndex];
+    }
+    return t;
+}
+
 void VDateAttrType::encode(const DateAttr& d,QStringList& data)
 {
     data << qName_ << QString::fromStdString(d.name());
@@ -60,8 +57,6 @@ void VDateAttrType::encode(const DayAttr& d,QStringList& data)
     data << qName_ << QString::fromStdString(d.name());
 }
 
-static VDateAttrType atype;
-
 //=====================================================
 //
 // VDateAttr
@@ -84,11 +79,13 @@ VDateAttr::VDateAttr(VNode *parent,const DayAttr& t, int index) :
 
 VAttributeType* VDateAttr::type() const
 {
-    return &atype;
+    static VAttributeType* atype=VAttributeType::find("date");
+    return atype;
 }
 
-QStringList VDateAttr::data() const
+QStringList VDateAttr::data(bool /*firstLine*/) const
 {
+    static VDateAttrType* atype=static_cast<VDateAttrType*>(type());
     QStringList s;
     if(parent_->node_)
     {
@@ -96,13 +93,13 @@ QStringList VDateAttr::data() const
         {
             const std::vector<DateAttr>& v=parent_->node_->dates();
             if(index_ < v.size())
-                atype.encode(v[index_],s);
+                atype->encode(v[index_],s);
         }
         else if(dataType_ == DayData)
         {
             const std::vector<DayAttr>& v=parent_->node_->days();
             if(index_ < v.size())
-                atype.encode(v[index_],s);
+                atype->encode(v[index_],s);
         }
     }
     return s;
diff --git a/Viewer/src/VDateAttr.hpp b/Viewer/src/VDateAttr.hpp
index d72143f..208bc32 100644
--- a/Viewer/src/VDateAttr.hpp
+++ b/Viewer/src/VDateAttr.hpp
@@ -12,6 +12,7 @@
 #define VDATE_HPP
 
 #include "VAttribute.hpp"
+#include "VAttributeType.hpp"
 
 #include <QStringList>
 #include <vector>
@@ -23,6 +24,19 @@ class VNode;
 class DateAttr;
 class DayAttr;
 
+class VDateAttrType : public VAttributeType
+{
+public:
+    explicit VDateAttrType();
+    QString toolTip(QStringList d) const;
+    QString definition(QStringList d) const;
+    void encode(const DateAttr& d,QStringList& data);
+    void encode(const DayAttr& d,QStringList& data);
+
+private:
+    enum DataIndex {TypeIndex=0,NameIndex=1};
+};
+
 class VDateAttr : public VAttribute
 {
 
@@ -33,7 +47,7 @@ public:
     VDateAttr(VNode *parent,const DayAttr&,int index);
 
     VAttributeType* type() const;
-    QStringList data() const;
+    QStringList data(bool firstLine) const;
     std::string strName() const;
 
     static void scan(VNode* vnode,std::vector<VAttribute*>& vec);
diff --git a/Viewer/src/VEventAttr.cpp b/Viewer/src/VEventAttr.cpp
index 2cf4c1f..d180a08 100644
--- a/Viewer/src/VEventAttr.cpp
+++ b/Viewer/src/VEventAttr.cpp
@@ -18,18 +18,6 @@
 // VEventAttrType
 //================================
 
-class VEventAttrType : public VAttributeType
-{
-public:
-    explicit VEventAttrType();
-    QString toolTip(QStringList d) const;
-    void encode(const Event&,QStringList&) const;
-
-private:
-     enum DataIndex {TypeIndex=0,NameIndex=1,ValueIndex=2};
-};
-
-
 VEventAttrType::VEventAttrType() : VAttributeType("event")
 {
     dataCount_=3;
@@ -52,6 +40,16 @@ QString VEventAttrType::toolTip(QStringList d) const
     return t;
 }
 
+QString VEventAttrType::definition(QStringList d) const
+{
+    QString t="event";
+    if(d.count() == dataCount_)
+    {
+        t+=" " + d[NameIndex];
+    }
+    return t;
+}
+
 void VEventAttrType::encode(const Event& e,QStringList& data) const
 {
     data << qName_ <<
@@ -59,8 +57,6 @@ void VEventAttrType::encode(const Event& e,QStringList& data) const
               QString::number((e.value()==true)?1:0);
 }
 
-static VEventAttrType atype;
-
 //=====================================================
 //
 // VEventAttr
@@ -74,16 +70,18 @@ VEventAttr::VEventAttr(VNode *parent,const Event& e, int index) : VAttribute(par
 
 VAttributeType* VEventAttr::type() const
 {
-    return &atype;
+    static VAttributeType* atype=VAttributeType::find("event");
+    return atype;
 }
 
-QStringList VEventAttr::data() const
+QStringList VEventAttr::data(bool /*firstLine*/) const
 {
+    static VEventAttrType* atype=static_cast<VEventAttrType*>(type());
     QStringList s;
     if(node_ptr node=parent_->node_)
     {
         const std::vector<Event>& v=parent_->node_->events();
-        atype.encode(v[index_],s);
+        atype->encode(v[index_],s);
     }
     return s;
 }
diff --git a/Viewer/src/VEventAttr.hpp b/Viewer/src/VEventAttr.hpp
index 459b343..d9e8c07 100644
--- a/Viewer/src/VEventAttr.hpp
+++ b/Viewer/src/VEventAttr.hpp
@@ -12,6 +12,7 @@
 #define VEVENT_HPP
 
 #include "VAttribute.hpp"
+#include "VAttributeType.hpp"
 
 #include <QStringList>
 #include <string>
@@ -23,13 +24,25 @@ class VNode;
 
 class Event;
 
+class VEventAttrType : public VAttributeType
+{
+public:
+    explicit VEventAttrType();
+    QString toolTip(QStringList d) const;
+    QString definition(QStringList d) const;
+    void encode(const Event&,QStringList&) const;
+
+private:
+     enum DataIndex {TypeIndex=0,NameIndex=1,ValueIndex=2};
+};
+
 class VEventAttr : public VAttribute
 {
 public:
     VEventAttr(VNode *parent,const Event&,int index);
 
     VAttributeType* type() const;
-    QStringList data() const;
+    QStringList data(bool firstLine) const;
     std::string strName() const;
 
     static void scan(VNode* vnode,std::vector<VAttribute*>& vec);
diff --git a/Viewer/src/VGenVarAttr.cpp b/Viewer/src/VGenVarAttr.cpp
index 3ab9d81..0b4a551 100644
--- a/Viewer/src/VGenVarAttr.cpp
+++ b/Viewer/src/VGenVarAttr.cpp
@@ -18,18 +18,6 @@
 // VGenVarAttrType
 //================================
 
-class VGenVarAttrType : public VAttributeType
-{
-public:
-    explicit VGenVarAttrType();
-    QString toolTip(QStringList d) const;
-    void encode(const Variable&,QStringList&) const;
-
-private:
-    enum DataIndex {TypeIndex=0,NameIndex=1,ValueIndex=2};
-};
-
-
 VGenVarAttrType::VGenVarAttrType() : VAttributeType("genvar")
 {
     dataCount_=3;
@@ -52,8 +40,6 @@ void VGenVarAttrType::encode(const Variable& v,QStringList& data) const
             QString::fromStdString(v.theValue());
 }
 
-static VGenVarAttrType atype;
-
 //=====================================================
 //
 // VGenVarAttr
@@ -67,17 +53,19 @@ VGenVarAttr::VGenVarAttr(VNode *parent,const Variable& v, int index) : VAttribut
 
 VAttributeType* VGenVarAttr::type() const
 {
-    return &atype;
+    static VAttributeType* atype=VAttributeType::find("genvar");
+    return atype;
 }
 
-QStringList VGenVarAttr::data() const
+QStringList VGenVarAttr::data(bool /*firstLine*/) const
 {
+    static VGenVarAttrType* atype=static_cast<VGenVarAttrType*>(type());
     QStringList s;
     if(parent_->isServer() == 0)
     {
         std::vector<Variable> v;
         parent_->genVariables(v);
-        atype.encode(v[index_],s);
+        atype->encode(v[index_],s);
     }
     return s;
 }
diff --git a/Viewer/src/VGenVarAttr.hpp b/Viewer/src/VGenVarAttr.hpp
index 6606a13..bdaa92d 100644
--- a/Viewer/src/VGenVarAttr.hpp
+++ b/Viewer/src/VGenVarAttr.hpp
@@ -12,6 +12,7 @@
 #define VGENVARATTR_HPP
 
 #include "VAttribute.hpp"
+#include "VAttributeType.hpp"
 
 #include <QStringList>
 #include <string>
@@ -22,13 +23,24 @@ class VAttributeType;
 class VNode;
 class Variable;
 
+class VGenVarAttrType : public VAttributeType
+{
+public:
+    explicit VGenVarAttrType();
+    QString toolTip(QStringList d) const;
+    void encode(const Variable&,QStringList&) const;
+
+private:
+    enum DataIndex {TypeIndex=0,NameIndex=1,ValueIndex=2};
+};
+
 class VGenVarAttr : public VAttribute
 {
 public:
     VGenVarAttr(VNode *parent,const Variable&,int index);
 
     VAttributeType* type() const;
-    QStringList data() const;
+    QStringList data(bool firstLine) const;
     std::string strName() const;
 
     static void scan(VNode* vnode,std::vector<VAttribute*>& vec);
diff --git a/Viewer/src/VLabelAttr.cpp b/Viewer/src/VLabelAttr.cpp
index 0bfc2ca..6019344 100644
--- a/Viewer/src/VLabelAttr.cpp
+++ b/Viewer/src/VLabelAttr.cpp
@@ -18,17 +18,6 @@
 // VLabelAttrType
 //================================
 
-class VLabelAttrType : public VAttributeType
-{
-public:
-    explicit VLabelAttrType();
-    QString toolTip(QStringList d) const;
-    void encode(const Label& label,QStringList& data) const;
-
-private:
-    enum DataIndex {TypeIndex=0,NameIndex=1,ValueIndex=2};
-};
-
 VLabelAttrType::VLabelAttrType() : VAttributeType("label")
 {
     dataCount_=3;
@@ -49,7 +38,17 @@ QString VLabelAttrType::toolTip(QStringList d) const
     return t;
 }
 
-void VLabelAttrType::encode(const Label& label,QStringList& data) const
+QString VLabelAttrType::definition(QStringList d) const
+{
+    QString t="label";
+    if(d.count() == dataCount_)
+    {
+        t+=" " + d[NameIndex] + " '" + d[ValueIndex] + "'";
+    }
+    return t;
+}
+
+void VLabelAttrType::encode(const Label& label,QStringList& data,bool firstLine) const
 {
     std::string val=label.new_value();
     if(val.empty() || val == " ")
@@ -57,13 +56,21 @@ void VLabelAttrType::encode(const Label& label,QStringList& data) const
         val=label.value();
     }
 
+    if(firstLine)
+    {
+        std::size_t pos=val.find("\n");
+        if(pos != std::string::npos)
+        {
+            if(pos > 0) pos--;
+            val=val.substr(0,pos);
+        }
+    }
+
     data << qName_ <<
                 QString::fromStdString(label.name()) <<
                 QString::fromStdString(val);
 }
 
-static VLabelAttrType atype;
-
 //=====================================================
 //
 // VLabelAttr
@@ -93,16 +100,18 @@ int VLabelAttr::lineNum() const
 
 VAttributeType* VLabelAttr::type() const
 {
-    return &atype;
+    static VAttributeType* atype=VAttributeType::find("label");
+    return atype;
 }
 
-QStringList VLabelAttr::data() const
+QStringList VLabelAttr::data(bool firstLine) const
 {
+    static VLabelAttrType* atype=static_cast<VLabelAttrType*>(type());
     QStringList s;
     if(parent_->node_)
     {
         const std::vector<Label>& v=parent_->node_->labels();
-        atype.encode(v[index_],s);
+        atype->encode(v[index_],s,firstLine);
     }
     return s;
 }
diff --git a/Viewer/src/VLabelAttr.hpp b/Viewer/src/VLabelAttr.hpp
index 57b324f..5162036 100644
--- a/Viewer/src/VLabelAttr.hpp
+++ b/Viewer/src/VLabelAttr.hpp
@@ -12,6 +12,7 @@
 #define VLABEL_HPP
 
 #include "VAttribute.hpp"
+#include "VAttributeType.hpp"
 
 #include <QStringList>
 #include <string>
@@ -23,6 +24,18 @@ class VNode;
 
 class Label;
 
+class VLabelAttrType : public VAttributeType
+{
+public:
+    explicit VLabelAttrType();
+    QString toolTip(QStringList d) const;
+    QString definition(QStringList d) const;
+    void encode(const Label& label,QStringList& data,bool firstLine) const;
+
+private:
+    enum DataIndex {TypeIndex=0,NameIndex=1,ValueIndex=2};
+};
+
 class VLabelAttr : public VAttribute
 {
 public:
@@ -30,7 +43,7 @@ public:
 
     int lineNum() const;
     VAttributeType* type() const;
-    QStringList data() const;
+    QStringList data(bool firstLine) const;
     std::string strName() const;
 
     static void scan(VNode* vnode,std::vector<VAttribute*>& vec);
diff --git a/Viewer/src/VLateAttr.cpp b/Viewer/src/VLateAttr.cpp
index a715990..6e7a60d 100644
--- a/Viewer/src/VLateAttr.cpp
+++ b/Viewer/src/VLateAttr.cpp
@@ -18,18 +18,6 @@
 // VLateAttrType
 //================================
 
-class VLateAttrType : public VAttributeType
-{
-public:
-    explicit VLateAttrType();
-    QString toolTip(QStringList d) const;
-    void encode(ecf::LateAttr* late,QStringList& data) const;   
-
-private:
-    enum DataIndex {TypeIndex=0,NameIndex=1};
-};
-
-
 VLateAttrType::VLateAttrType() : VAttributeType("late")
 {
     dataCount_=2;
@@ -49,14 +37,22 @@ QString VLateAttrType::toolTip(QStringList d) const
     return t;
 }
 
+QString VLateAttrType::definition(QStringList d) const
+{
+    QString t="late";
+    if(d.count() == dataCount_)
+    {
+        t+=" " + d[NameIndex];
+    }
+    return t;
+}
+
 void VLateAttrType::encode(ecf::LateAttr* late,QStringList& data) const
 {
     if(late)
         data << qName_ << QString::fromStdString(late->name());
 }
 
-static VLateAttrType atype;
-
 //=====================================================
 //
 // VLateAttr
@@ -71,16 +67,18 @@ VLateAttr::VLateAttr(VNode *parent,const std::string& name) :
 
 VAttributeType* VLateAttr::type() const
 {
-    return &atype;
+    static VAttributeType* atype=VAttributeType::find("late");
+    return atype;
 }
 
-QStringList VLateAttr::data() const
+QStringList VLateAttr::data(bool /*firstLine*/) const
 {
+    static VLateAttrType* atype=static_cast<VLateAttrType*>(type());
     QStringList s;
     if(node_ptr node=parent_->node())
     {
         ecf::LateAttr *late=node->get_late();
-        atype.encode(late,s);
+        atype->encode(late,s);
     }
     return s;
 }
diff --git a/Viewer/src/VLateAttr.hpp b/Viewer/src/VLateAttr.hpp
index 6f68b5f..79218e8 100644
--- a/Viewer/src/VLateAttr.hpp
+++ b/Viewer/src/VLateAttr.hpp
@@ -2,6 +2,9 @@
 #define VLATE_HPP
 
 #include "VAttribute.hpp"
+#include "VAttributeType.hpp"
+
+#include "LateAttr.hpp"
 
 #include <QStringList>
 #include <string>
@@ -13,13 +16,25 @@ class VNode;
 
 class Label;
 
+class VLateAttrType : public VAttributeType
+{
+public:
+    explicit VLateAttrType();
+    QString toolTip(QStringList d) const;
+    QString definition(QStringList d) const;
+    void encode(ecf::LateAttr* late,QStringList& data) const;
+
+private:
+    enum DataIndex {TypeIndex=0,NameIndex=1};
+};
+
 class VLateAttr : public VAttribute
 {
 public:
     VLateAttr(VNode *parent,const std::string&);
 
     VAttributeType* type() const;
-    QStringList data() const;
+    QStringList data(bool firstLine) const;
 
     static void scan(VNode* vnode,std::vector<VAttribute*>& vec);
 };
diff --git a/Viewer/src/VLimitAttr.cpp b/Viewer/src/VLimitAttr.cpp
index 8ca0c80..bde4047 100644
--- a/Viewer/src/VLimitAttr.cpp
+++ b/Viewer/src/VLimitAttr.cpp
@@ -18,18 +18,6 @@
 // VLimitAttrType
 //================================
 
-class VLimitAttrType : public VAttributeType
-{
-public:
-    explicit VLimitAttrType();
-    QString toolTip(QStringList d) const;
-    void encode(limit_ptr,QStringList&) const;
-
-private:
-     enum DataIndex {TypeIndex=0,NameIndex=1,ValueIndex=2,MaxIndex=3};
-};
-
-
 VLimitAttrType::VLimitAttrType() : VAttributeType("limit")
 {
     dataCount_=4;
@@ -52,6 +40,16 @@ QString VLimitAttrType::toolTip(QStringList d) const
     return t;
 }
 
+QString VLimitAttrType::definition(QStringList d) const
+{
+    QString t="limit";
+    if(d.count() == dataCount_)
+    {
+        t+=" " + d[NameIndex] + " " + d[MaxIndex];
+    }
+    return t;
+}
+
 void VLimitAttrType::encode(limit_ptr lim,QStringList& data) const
 {
     data << qName_ <<
@@ -60,8 +58,6 @@ void VLimitAttrType::encode(limit_ptr lim,QStringList& data) const
         QString::number(lim->theLimit());
 }
 
-static VLimitAttrType atype;
-
 //=====================================================
 //
 // VLimitAttr
@@ -75,16 +71,18 @@ VLimitAttr::VLimitAttr(VNode *parent,limit_ptr lim, int index) : VAttribute(pare
 
 VAttributeType* VLimitAttr::type() const
 {
-    return &atype;
+    static VAttributeType* atype=VAttributeType::find("limit");
+    return atype;
 }
 
-QStringList VLimitAttr::data() const
+QStringList VLimitAttr::data(bool /*firstLine*/) const
 {
+    static VLimitAttrType* atype=static_cast<VLimitAttrType*>(type());
     QStringList s;
     if(parent_->node_)
     {
         const std::vector<limit_ptr>& v=parent_->node_->limits();
-        atype.encode(v[index_],s);
+        atype->encode(v[index_],s);
     }
     return s;
 }
diff --git a/Viewer/src/VLimitAttr.hpp b/Viewer/src/VLimitAttr.hpp
index 992f65f..71b4edb 100644
--- a/Viewer/src/VLimitAttr.hpp
+++ b/Viewer/src/VLimitAttr.hpp
@@ -17,11 +17,24 @@
 
 #include "LimitFwd.hpp"
 #include "VAttribute.hpp"
+#include "VAttributeType.hpp"
 
 class AttributeFilter;
 class VAttributeType;
 class VNode;
 
+class VLimitAttrType : public VAttributeType
+{
+public:
+    explicit VLimitAttrType();
+    QString toolTip(QStringList d) const;
+    QString definition(QStringList d) const;
+    void encode(limit_ptr,QStringList&) const;
+
+private:
+     enum DataIndex {TypeIndex=0,NameIndex=1,ValueIndex=2,MaxIndex=3};
+};
+
 class VLimitAttr : public VAttribute
 {
 
@@ -29,7 +42,7 @@ public:
     VLimitAttr(VNode *parent,limit_ptr,int index);
 
     VAttributeType* type() const;
-    QStringList data() const;
+    QStringList data(bool firstLine) const;
     std::string strName() const;
     QStringList paths() const;
     void removePaths(const std::vector<std::string>& paths);
diff --git a/Viewer/src/VLimiterAttr.cpp b/Viewer/src/VLimiterAttr.cpp
index 5f27a05..2a2b815 100644
--- a/Viewer/src/VLimiterAttr.cpp
+++ b/Viewer/src/VLimiterAttr.cpp
@@ -18,20 +18,6 @@
 // VLimiterAttrType
 //================================
 
-class VLimiterAttrType : public VAttributeType
-{
-public:
-    explicit VLimiterAttrType();
-    QString toolTip(QStringList d) const;
-    void encode(const InLimit&,QStringList&) const;    
-    void scan(VNode* vnode,std::vector<VAttribute*>& vec);
-    int totalNum(VNode* vnode);
-
-private:
-    enum DataIndex {TypeIndex=0,NameIndex=1,PathIndex=2};
-};
-
-
 VLimiterAttrType::VLimiterAttrType() : VAttributeType("limiter")
 {
     dataCount_=3;
@@ -53,6 +39,16 @@ QString VLimiterAttrType::toolTip(QStringList d) const
     return t;
 }
 
+QString VLimiterAttrType::definition(QStringList d) const
+{
+    QString t="inlimit";
+    if(d.count() == dataCount_)
+    {
+        t+=" " + d[NameIndex];
+    }
+    return t;
+}
+
 void VLimiterAttrType::encode(const InLimit& lim,QStringList& data) const
 {
     data << qName_ <<
@@ -60,12 +56,6 @@ void VLimiterAttrType::encode(const InLimit& lim,QStringList& data) const
            QString::fromStdString(lim.pathToNode());
 }
 
-static void scan(VNode* vnode,std::vector<VAttribute*>& vec);
-static int totalNum(VNode* vnode);
-
-
-static VLimiterAttrType atype;
-
 //=====================================================
 //
 // VLimiterAttr
@@ -79,16 +69,18 @@ VLimiterAttr::VLimiterAttr(VNode *parent,const InLimit& lim, int index) : VAttri
 
 VAttributeType* VLimiterAttr::type() const
 {
-    return &atype;
+    static VAttributeType* atype=VAttributeType::find("limiter");
+    return atype;
 }
 
-QStringList VLimiterAttr::data() const
+QStringList VLimiterAttr::data(bool /*firstLine*/) const
 {
+    static VLimiterAttrType* atype=static_cast<VLimiterAttrType*>(type());
     QStringList s;
     if(parent_->node_)
     {
         const std::vector<InLimit>& v=parent_->node_->inlimits();
-        atype.encode(v[index_],s);
+        atype->encode(v[index_],s);
     }
     return s;
 }
diff --git a/Viewer/src/VLimiterAttr.hpp b/Viewer/src/VLimiterAttr.hpp
index 70dc469..9257b18 100644
--- a/Viewer/src/VLimiterAttr.hpp
+++ b/Viewer/src/VLimiterAttr.hpp
@@ -12,6 +12,7 @@
 #define VLIMITERATTR_HPP
 
 #include "VAttribute.hpp"
+#include "VAttributeType.hpp"
 
 #include <QStringList>
 #include <string>
@@ -23,6 +24,20 @@ class VNode;
 
 class InLimit;
 
+class VLimiterAttrType : public VAttributeType
+{
+public:
+    explicit VLimiterAttrType();
+    QString toolTip(QStringList d) const;
+    QString definition(QStringList d) const;
+    void encode(const InLimit&,QStringList&) const;
+    void scan(VNode* vnode,std::vector<VAttribute*>& vec);
+    int totalNum(VNode* vnode);
+
+private:
+    enum DataIndex {TypeIndex=0,NameIndex=1,PathIndex=2};
+};
+
 class VLimiterAttr : public VAttribute
 {
 
@@ -30,7 +45,7 @@ public:
     VLimiterAttr(VNode *parent,const InLimit&,int index);
 
     VAttributeType* type() const;
-    QStringList data() const;
+    QStringList data(bool firstLine) const;
     std::string strName() const;
 
     static void scan(VNode* vnode,std::vector<VAttribute*>& vec);
diff --git a/Viewer/src/VMeterAttr.cpp b/Viewer/src/VMeterAttr.cpp
index a64785b..a12ec25 100644
--- a/Viewer/src/VMeterAttr.cpp
+++ b/Viewer/src/VMeterAttr.cpp
@@ -18,18 +18,6 @@
 // VMeterAttrType
 //================================
 
-class VMeterAttrType : public VAttributeType
-{
-public:
-    explicit VMeterAttrType();
-    QString toolTip(QStringList d) const;
-    void encode(const Meter&,QStringList&) const;
-
-private:
-    enum DataIndex {TypeIndex=0,NameIndex=1,ValueIndex=2,MinIndex=3, MaxIndex=4,ThresholdIndex=5};
-};
-
-
 VMeterAttrType::VMeterAttrType() : VAttributeType("meter")
 {
     dataCount_=6;
@@ -52,6 +40,16 @@ QString VMeterAttrType::toolTip(QStringList d) const
     return t;
 }
 
+QString VMeterAttrType::definition(QStringList d) const
+{
+    QString t="meter";
+    if(d.count() == dataCount_)
+    {
+        t+=" " + d[NameIndex] + " " + d[MinIndex] + " " + d[MaxIndex] + " " + d[ThresholdIndex];
+    }
+    return t;
+}
+
 void VMeterAttrType::encode(const Meter& m,QStringList& data) const
 {
     data << qName_ <<
@@ -60,8 +58,6 @@ void VMeterAttrType::encode(const Meter& m,QStringList& data) const
                     QString::number(m.colorChange());
 }
 
-static VMeterAttrType atype;
-
 //=====================================================
 //
 // VMeterAttr
@@ -75,16 +71,18 @@ VMeterAttr::VMeterAttr(VNode *parent,const Meter& m, int index) : VAttribute(par
 
 VAttributeType* VMeterAttr::type() const
 {
-    return &atype;
+    static VAttributeType* atype=VAttributeType::find("meter");
+    return atype;
 }
 
-QStringList VMeterAttr::data() const
+QStringList VMeterAttr::data(bool /*firstLine*/) const
 {
+    static VMeterAttrType* atype=static_cast<VMeterAttrType*>(type());
     QStringList s;
     if(parent_->node_)
     {
         const std::vector<Meter>& v=parent_->node_->meters();
-        atype.encode(v[index_],s);
+        atype->encode(v[index_],s);
     }
     return s;
 }
diff --git a/Viewer/src/VMeterAttr.hpp b/Viewer/src/VMeterAttr.hpp
index 0f729f0..eb55675 100644
--- a/Viewer/src/VMeterAttr.hpp
+++ b/Viewer/src/VMeterAttr.hpp
@@ -12,6 +12,7 @@
 #define VMETERATTR_HPP
 
 #include "VAttribute.hpp"
+#include "VAttributeType.hpp"
 
 #include <QStringList>
 #include <string>
@@ -23,6 +24,18 @@ class VNode;
 
 class Meter;
 
+class VMeterAttrType : public VAttributeType
+{
+public:
+    explicit VMeterAttrType();
+    QString toolTip(QStringList d) const;
+    QString definition(QStringList d) const;
+    void encode(const Meter&,QStringList&) const;
+
+private:
+    enum DataIndex {TypeIndex=0,NameIndex=1,ValueIndex=2,MinIndex=3, MaxIndex=4,ThresholdIndex=5};
+};
+
 class VMeterAttr : public VAttribute
 {
 
@@ -30,7 +43,7 @@ public:
     VMeterAttr(VNode *parent,const Meter&,int index);
 
     VAttributeType* type() const;
-    QStringList data() const;
+    QStringList data(bool firstLine) const;
     std::string strName() const;
 
     static void scan(VNode* vnode,std::vector<VAttribute*>& vec);
diff --git a/Viewer/src/VModelData.cpp b/Viewer/src/VModelData.cpp
index 9f6a779..ddd9536 100644
--- a/Viewer/src/VModelData.cpp
+++ b/Viewer/src/VModelData.cpp
@@ -551,8 +551,8 @@ void VTreeServer::setForceShowNode(const VNode* node)
 
     //find the suite
     VNode* s=node->suite();
-    Q_ASSERT(s->isTopLevel());
     Q_ASSERT(s);
+    Q_ASSERT(s->isTopLevel());
 
     std::vector<VNode*> sv;
     sv.push_back(s);
@@ -704,8 +704,14 @@ void VTreeServer::clearForceShow(const VItem* itemCurrent)
 
     //The server matches
     //TODO: what if it is the ROOT?
-    if(itemCurrent->parent()->server() == server_)
-    {
+    ServerHandler *sh=0;
+    if(VNode *parent=itemCurrent->parent())
+        sh=parent->server();
+    else if(VServer* vs=itemCurrent->isServer())
+        sh=vs->server();
+
+    if(sh == server_)
+    {        
         //Item is a node and it is the same as we store
         if(VNode *itn=itemCurrent->isNode())
         {
diff --git a/Viewer/src/VNode.hpp b/Viewer/src/VNode.hpp
index 2bbc0d0..23bd487 100644
--- a/Viewer/src/VNode.hpp
+++ b/Viewer/src/VNode.hpp
@@ -112,7 +112,7 @@ public:
     bool isTopLevel() const;
 
     //Attributes
-    const std::vector<VAttribute*> attr() const {return attr_;}
+    const std::vector<VAttribute*>& attr() const {return attr_;}
     int attrNum(AttributeFilter* filter=0) const;
     VAttribute* attribute(int,AttributeFilter *filter=0) const;
     VAttribute* attributeForType(int,VAttributeType*) const;
diff --git a/Viewer/src/VRepeatAttr.cpp b/Viewer/src/VRepeatAttr.cpp
index f66e6e6..fdf9ec8 100644
--- a/Viewer/src/VRepeatAttr.cpp
+++ b/Viewer/src/VRepeatAttr.cpp
@@ -99,18 +99,6 @@ long ecf_repeat_date_to_julian(long ddate)
 // VRepeatAttrType
 //================================
 
-class VRepeatAttrType : public VAttributeType
-{
-public:
-    explicit VRepeatAttrType();
-    QString toolTip(QStringList d) const;
-    void encode(const Repeat&,QStringList&,const std::string&) const;
-
-private:
-    enum DataIndex {TypeIndex=0,SubtypeIndex=1,NameIndex=2,ValueIndex=3,StartIndex=4,EndIndex=5,StepIndex=6};
-};
-
-
 VRepeatAttrType::VRepeatAttrType() : VAttributeType("repeat")
 {
     dataCount_=7;
@@ -144,6 +132,28 @@ QString VRepeatAttrType::toolTip(QStringList d) const
     return t;
 }
 
+QString VRepeatAttrType::definition(QStringList d) const
+{
+    QString t="repeat";
+    if(d.count() == dataCount_)
+    {
+        t+=" " + d[SubtypeIndex];
+
+        if(d[SubtypeIndex] != "day")
+        {
+            t+=" " + d[NameIndex];
+            t+=" " + d[StartIndex];
+            t+=" " + d[EndIndex];
+            t+=" " + d[StepIndex];
+        }
+        else
+        {
+            t+=" " + d[StepIndex];
+        }
+    }
+    return t;
+}
+
 void VRepeatAttrType::encode(const Repeat& r,QStringList& data,const std::string& type) const
 {
     //We try to avoid creating a VRepeat object everytime we are here
@@ -158,8 +168,6 @@ void VRepeatAttrType::encode(const Repeat& r,QStringList& data,const std::string
 
 }
 
-static VRepeatAttrType atype;
-
 //=====================================================
 //
 // VRepeatAttr
@@ -173,7 +181,8 @@ VRepeatAttr::VRepeatAttr(VNode *parent) : VAttribute(parent,0)
 
 VAttributeType* VRepeatAttr::type() const
 {
-    return &atype;
+    static VAttributeType* atype=VAttributeType::find("repeat");
+    return atype;
 }
 
 int VRepeatAttr::step() const
@@ -186,13 +195,14 @@ int VRepeatAttr::step() const
     return 0;
 }
 
-QStringList VRepeatAttr::data() const
+QStringList VRepeatAttr::data(bool /*firstLine*/) const
 {
+    static VRepeatAttrType* atype=static_cast<VRepeatAttrType*>(type());
     QStringList s;
     if(parent_->node_)
     {
         const Repeat& r=parent_->node_->repeat();
-        atype.encode(r,s,subType());
+        atype->encode(r,s,subType());
     }
     return s;
 }
diff --git a/Viewer/src/VRepeatAttr.hpp b/Viewer/src/VRepeatAttr.hpp
index 4869568..bc4a90f 100644
--- a/Viewer/src/VRepeatAttr.hpp
+++ b/Viewer/src/VRepeatAttr.hpp
@@ -12,6 +12,8 @@
 #define VREPEATATTR_HPP
 
 #include "VAttribute.hpp"
+#include "VAttributeType.hpp"
+
 #include <string>
 #include <QStringList>
 
@@ -19,6 +21,18 @@ class VAttributeType;
 class VNode;
 class Repeat;
 
+class VRepeatAttrType : public VAttributeType
+{
+public:
+    explicit VRepeatAttrType();
+    QString toolTip(QStringList d) const;
+    QString definition(QStringList d) const;
+    void encode(const Repeat&,QStringList&,const std::string&) const;
+
+private:
+    enum DataIndex {TypeIndex=0,SubtypeIndex=1,NameIndex=2,ValueIndex=3,StartIndex=4,EndIndex=5,StepIndex=6};
+};
+
 class VRepeatAttr : public VAttribute
 {
 public:
@@ -31,7 +45,7 @@ public:
     virtual std::string value(int index) const=0;    
 
     VAttributeType* type() const;
-    QStringList data() const;
+    QStringList data(bool firstLine) const;
     std::string strName() const;
 
     static void scan(VNode* vnode,std::vector<VAttribute*>& vec);
diff --git a/Viewer/src/VTimeAttr.cpp b/Viewer/src/VTimeAttr.cpp
index ad0970b..4fe1eac 100644
--- a/Viewer/src/VTimeAttr.cpp
+++ b/Viewer/src/VTimeAttr.cpp
@@ -16,20 +16,6 @@
 // VTimeAttrType
 //================================
 
-class VTimeAttrType : public VAttributeType
-{
-public:
-    explicit VTimeAttrType();
-    QString toolTip(QStringList d) const;
-    void encode(const ecf::TimeAttr& d,QStringList& data);
-    void encode(const ecf::TodayAttr& d,QStringList& data);
-    void encode(const ecf::CronAttr& d,QStringList& data);
-
-private:
-    enum DataIndex {TypeIndex=0,NameIndex=1};
-};
-
-
 VTimeAttrType::VTimeAttrType() : VAttributeType("time")
 {
     dataCount_=2;
@@ -48,6 +34,16 @@ QString VTimeAttrType::toolTip(QStringList d) const
     return t;
 }
 
+QString VTimeAttrType::definition(QStringList d) const
+{
+    QString t;
+    if(d.count() == dataCount_)
+    {
+        t+=" " + d[NameIndex];
+    }
+    return t;
+}
+
 void VTimeAttrType::encode(const ecf::TimeAttr& d,QStringList& data)
 {
     data << qName_ << QString::fromStdString(d.name());
@@ -63,8 +59,6 @@ void VTimeAttrType::encode(const ecf::CronAttr& d,QStringList& data)
     data << qName_ << QString::fromStdString(d.name());
 }
 
-static VTimeAttrType atype;
-
 //=====================================================
 //
 // VTimeAttr
@@ -94,11 +88,13 @@ VTimeAttr::VTimeAttr(VNode *parent,const ecf::CronAttr& t, int index) :
 
 VAttributeType* VTimeAttr::type() const
 {
-    return &atype;
+    static VAttributeType* atype=VAttributeType::find("time");
+    return atype;
 }
 
-QStringList VTimeAttr::data() const
+QStringList VTimeAttr::data(bool /*firstLine*/) const
 {
+    static VTimeAttrType* atype=static_cast<VTimeAttrType*>(type());
     QStringList s;
     if(parent_->node_)
     {
@@ -106,19 +102,19 @@ QStringList VTimeAttr::data() const
         {
             const std::vector<ecf::TimeAttr>& v=parent_->node_->timeVec();
             if(index_ < v.size())
-                atype.encode(v[index_],s);
+                atype->encode(v[index_],s);
         }
         else if(dataType_ == TodayData)
         {
             const std::vector<ecf::TodayAttr>& v=parent_->node_->todayVec();
             if(index_ < v.size())
-                atype.encode(v[index_],s);
+                atype->encode(v[index_],s);
         }
         else if(dataType_ == CronData)
         {
             const std::vector<ecf::CronAttr>& v=parent_->node_->crons();
             if(index_ < v.size())
-                atype.encode(v[index_],s);
+                atype->encode(v[index_],s);
         }
     }
     return s;
diff --git a/Viewer/src/VTimeAttr.hpp b/Viewer/src/VTimeAttr.hpp
index dea4d9a..b4cbae2 100644
--- a/Viewer/src/VTimeAttr.hpp
+++ b/Viewer/src/VTimeAttr.hpp
@@ -12,6 +12,7 @@
 #define VTIME_HPP
 
 #include "VAttribute.hpp"
+#include "VAttributeType.hpp"
 
 #include <QStringList>
 #include <vector>
@@ -24,6 +25,20 @@ class AttributeFilter;
 class VAttributeType;
 class VNode;
 
+class VTimeAttrType : public VAttributeType
+{
+public:
+    explicit VTimeAttrType();
+    QString toolTip(QStringList d) const;
+    QString definition(QStringList d) const;
+    void encode(const ecf::TimeAttr& d,QStringList& data);
+    void encode(const ecf::TodayAttr& d,QStringList& data);
+    void encode(const ecf::CronAttr& d,QStringList& data);
+
+private:
+    enum DataIndex {TypeIndex=0,NameIndex=1};
+};
+
 class VTimeAttr : public VAttribute
 {
 
@@ -35,7 +50,7 @@ public:
     VTimeAttr(VNode *parent,const ecf::CronAttr&,int index);
 
     VAttributeType* type() const;
-    QStringList data() const;
+    QStringList data(bool firstLine) const;
     std::string strName() const;
 
     static void scan(VNode* vnode,std::vector<VAttribute*>& vec);
diff --git a/Viewer/src/VTriggerAttr.cpp b/Viewer/src/VTriggerAttr.cpp
index e9c097e..0776ad5 100644
--- a/Viewer/src/VTriggerAttr.cpp
+++ b/Viewer/src/VTriggerAttr.cpp
@@ -18,19 +18,6 @@
 // VTriggerAttrType
 //================================
 
-class VTriggerAttrType : public VAttributeType
-{
-public:
-    explicit VTriggerAttrType();
-    QString toolTip(QStringList d) const;
-    void encodeTrigger(Expression*,QStringList&) const;
-    void encodeComplete(Expression*,QStringList&) const;
-
-private:
-    enum DataIndex {TypeIndex=0,CompleteIndex=1,ExprIndex=2};
-};
-
-
 VTriggerAttrType::VTriggerAttrType() : VAttributeType("trigger")
 {
     dataCount_=3;
@@ -57,6 +44,21 @@ QString VTriggerAttrType::toolTip(QStringList d) const
     return t;
 }
 
+QString VTriggerAttrType::definition(QStringList d) const
+{
+    QString t;
+    if(d.count() == dataCount_)
+    {
+        if(d[CompleteIndex] == "0")
+            t+="trigger";
+        else if(d[CompleteIndex] == "1")
+            t+="complete";
+
+        t+=" " + d[ExprIndex];
+    }
+    return t;
+}
+
 void VTriggerAttrType::encodeTrigger(Expression *e,QStringList& data) const
 {
     data << qName_ << "0" << QString::fromStdString(e->expression());
@@ -67,8 +69,6 @@ void VTriggerAttrType::encodeComplete(Expression *e,QStringList& data) const
     data << qName_ << "1" << QString::fromStdString(e->expression());
 }
 
-static VTriggerAttrType atype;
-
 //=====================================================
 //
 // VTriggerAttr
@@ -82,21 +82,23 @@ VTriggerAttr::VTriggerAttr(VNode *parent,Expression* e, int index) :
 
 VAttributeType* VTriggerAttr::type() const
 {
-    return &atype;
+    static VAttributeType* atype=VAttributeType::find("trigger");
+    return atype;
 }
 
-QStringList VTriggerAttr::data() const
+QStringList VTriggerAttr::data(bool /*firstLine*/) const
 {
+    static VTriggerAttrType* atype=static_cast<VTriggerAttrType*>(type());
     QStringList s;
     if(node_ptr node=parent_->node())
     {
         if(index_ == 0)
         {
-            atype.encodeTrigger(node->get_trigger(),s);
+            atype->encodeTrigger(node->get_trigger(),s);
         }
         else
         {
-            atype.encodeComplete(node->get_complete(),s);
+            atype->encodeComplete(node->get_complete(),s);
         }
     }
     return s;
diff --git a/Viewer/src/VTriggerAttr.hpp b/Viewer/src/VTriggerAttr.hpp
index 5e00ecb..9fb7da3 100644
--- a/Viewer/src/VTriggerAttr.hpp
+++ b/Viewer/src/VTriggerAttr.hpp
@@ -12,6 +12,7 @@
 #define VTRIGGERATTR_HPP
 
 #include "VAttribute.hpp"
+#include "VAttributeType.hpp"
 
 #include <QStringList>
 #include <vector>
@@ -22,6 +23,19 @@ class VNode;
 
 class Expression;
 
+class VTriggerAttrType : public VAttributeType
+{
+public:
+    explicit VTriggerAttrType();
+    QString toolTip(QStringList d) const;
+    QString definition(QStringList d) const;
+    void encodeTrigger(Expression*,QStringList&) const;
+    void encodeComplete(Expression*,QStringList&) const;
+
+private:
+    enum DataIndex {TypeIndex=0,CompleteIndex=1,ExprIndex=2};
+};
+
 class VTriggerAttr : public VAttribute
 {
 
@@ -29,7 +43,7 @@ public:
     VTriggerAttr(VNode *parent,Expression*, int index);
 
     VAttributeType* type() const;
-    QStringList data() const;
+    QStringList data(bool firstLine) const;
     std::string strName() const;
 
     static void scan(VNode* vnode,std::vector<VAttribute*>& vec);
diff --git a/Viewer/src/VUserVarAttr.cpp b/Viewer/src/VUserVarAttr.cpp
index 8c799f3..d7f2ca1 100644
--- a/Viewer/src/VUserVarAttr.cpp
+++ b/Viewer/src/VUserVarAttr.cpp
@@ -18,18 +18,6 @@
 // VUserVarAttrType
 //================================
 
-class VUserVarAttrType : public VAttributeType
-{
-public:
-    explicit VUserVarAttrType();
-    QString toolTip(QStringList d) const;
-    void encode(const Variable&,QStringList&) const;
-
-private:
-    enum DataIndex {TypeIndex=0,NameIndex=1,ValueIndex=2};
-};
-
-
 VUserVarAttrType::VUserVarAttrType() : VAttributeType("var")
 {
     dataCount_=3;
@@ -52,8 +40,6 @@ void VUserVarAttrType::encode(const Variable& v,QStringList& data) const
             QString::fromStdString(v.theValue());
 }
 
-static VUserVarAttrType atype;
-
 //=====================================================
 //
 // VUserVarAttr
@@ -67,11 +53,13 @@ VUserVarAttr::VUserVarAttr(VNode *parent,const Variable& v, int index) : VAttrib
 
 VAttributeType* VUserVarAttr::type() const
 {
-    return &atype;
+    static VAttributeType* atype=VAttributeType::find("var");
+    return atype;
 }
 
-QStringList VUserVarAttr::data() const
+QStringList VUserVarAttr::data(bool /*firstLine*/) const
 {
+    static VUserVarAttrType* atype=static_cast<VUserVarAttrType*>(type());
     QStringList s;
 
     //Node
@@ -80,7 +68,7 @@ QStringList VUserVarAttr::data() const
         if(parent_->node_)
         {
             const std::vector<Variable>& v=parent_->node_->variables();
-            atype.encode(v[index_],s);
+            atype->encode(v[index_],s);
         }
     }
     //Server
@@ -88,7 +76,7 @@ QStringList VUserVarAttr::data() const
     {
         std::vector<Variable> v;
         parent_->variables(v);
-        atype.encode(v[index_],s);
+        atype->encode(v[index_],s);
     }
 
     return s;
diff --git a/Viewer/src/VUserVarAttr.hpp b/Viewer/src/VUserVarAttr.hpp
index 93975e6..dccfee4 100644
--- a/Viewer/src/VUserVarAttr.hpp
+++ b/Viewer/src/VUserVarAttr.hpp
@@ -12,6 +12,7 @@
 #define VUSERVARATTR_HPP
 
 #include "VAttribute.hpp"
+#include "VAttributeType.hpp"
 
 #include <QStringList>
 #include <string>
@@ -22,13 +23,24 @@ class VAttributeType;
 class VNode;
 class Variable;
 
+class VUserVarAttrType : public VAttributeType
+{
+public:
+    explicit VUserVarAttrType();
+    QString toolTip(QStringList d) const;
+    void encode(const Variable&,QStringList&) const;
+
+private:
+    enum DataIndex {TypeIndex=0,NameIndex=1,ValueIndex=2};
+};
+
 class VUserVarAttr : public VAttribute
 {
 public:
     VUserVarAttr(VNode *parent,const Variable&,int index);
 
     VAttributeType* type() const;
-    QStringList data() const;
+    QStringList data(bool firstLine) const;
     std::string strName() const;
 
     static void scan(VNode* vnode,std::vector<VAttribute*>& vec);
diff --git a/share/ecflow/etc/ecflowview_highlighter.json b/share/ecflow/etc/ecflowview_highlighter.json
index 583a2a6..e3cb35c 100644
--- a/share/ecflow/etc/ecflowview_highlighter.json
+++ b/share/ecflow/etc/ecflowview_highlighter.json
@@ -14,7 +14,7 @@
                 }, 
                 
                 "keyword" : {
-                    "pattern" : "(edit|cron|label|event|defstatus)",                       
+                    "pattern" : "^\\s*(edit|cron|date|day|inlimit|label|late|limit|meter|event|repeat|time|today|trigger|complete|defstatus)\\s+",
                     "colour"  : "rgb(136,0,136)",               
                     "bold"    : "true"
                 }, 

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/debian-science/packages/ecflow.git



More information about the debian-science-commits mailing list