瀏覽代碼

Add multi-range timers

Neal Wilson 9 年之前
父節點
當前提交
5973f49cc6
共有 2 個文件被更改,包括 244 次插入6 次删除
  1. 139
    1
      config/Windows/productionroaster.xml
  2. 105
    5
      src/typica.w

+ 139
- 1
config/Windows/productionroaster.xml 查看文件

@@ -67,6 +67,7 @@
67 67
 		var roasterIndex = roasterlist.currentIndex;
68 68
 		var channels = new Array();
69 69
 		var annotationButtons = new Array();
70
+                var rangetimers = new Array();
70 71
 		var nidevices = new Array();
71 72
 		var dataqsdkdevices = new Array();
72 73
 		var jsdevices = new Array();
@@ -614,7 +615,7 @@
614 615
 				}
615 616
                                 else if(driverReference.driver == "coolingtimer")
616 617
                                 {
617
-                                    var coolingTimer = new TimerDisplay;
618
+                                    var coolingTimer = new TimerDisplay();
618 619
                                     coolingTimer.setDisplayFormat("mm:ss");
619 620
                                     var decorator = new WidgetDecorator(coolingTimer, configModel.data(driverIndex, 0), 2);
620 621
                                     indicatorPanel.addWidget(decorator);
@@ -625,6 +626,138 @@
625 626
                                     coolingTimer.setResetValue(timeValue);
626 627
                                     stop.clicked.connect(coolingTimer.startTimer);
627 628
                                 }
629
+                                else if(driverReference.driver == "rangetimer")
630
+                                {
631
+                                    rangetimers.push(new TimerDisplay());
632
+                                    var rangeTimer = rangetimers[rangetimers.length - 1];
633
+                                    rangeTimer.setDisplayFormat("mm:ss");
634
+                                    var decorator = new WidgetDecorator(rangeTimer, configModel.data(driverIndex, 0), 2);
635
+                                    indicatorPanel.addWidget(decorator);
636
+                                    stop.clicked.connect(rangeTimer.stopTimer);
637
+                                    start.clicked.connect(rangeTimer.reset);
638
+                                    if(driverReference.starttrigger == "batch")
639
+                                    {
640
+                                        start.clicked.connect(rangeTimer.startTimer);
641
+                                    }
642
+                                    else if(driverReference.starttrigger == "manual")
643
+                                    {
644
+                                        var startButton = new AnnotationButton(driverReference.startbuttontext);
645
+                                        startButton.clicked.connect(rangeTimer.startTimer);
646
+                                        annotationPanel.addWidget(startButton);
647
+                                        tabControls.push(button);
648
+                                    }
649
+                                    else if(driverReference.starttrigger == "value")
650
+                                    {
651
+                                        var startTrigger = new ThresholdDetector();
652
+                                        startTrigger.setThreshold(Number(driverReference.startvalue));
653
+                                        var scope = new Object;
654
+                                        scope.invoke = function() {
655
+                                            if(timer.running && !(arguments.callee.rangeTimer.running))
656
+                                            {
657
+                                                arguments.callee.rangeTimer.startTimer();
658
+                                            }
659
+                                        };
660
+                                        scope.invoke.rangeTimer = rangeTimer;
661
+                                        startTrigger.timeForValue.connect(scope.invoke);
662
+                                        for(var j = 0; j < columnNames.length; j++)
663
+                                        {
664
+                                            if(columnNames[j] == driverReference.startcolumnname)
665
+                                            {
666
+                                                channels[j].newData.connect(startTrigger.newMeasurement);
667
+                                            }
668
+                                        }
669
+                                    }
670
+                                    stop.clicked.connect(rangeTimer.stopTimer)
671
+                                    if(driverReference.stoptrigger == "manual")
672
+                                    {
673
+                                        var stopButton = new AnnotationButton(driverReference.stopbuttontext);
674
+                                        stopButton.clicked.connect(rangeTimer.stopTimer);
675
+                                        annotationPanel.addWidget(stopButton);
676
+                                        tabControls.push(button);
677
+                                    }
678
+                                    else if(driverReference.stoptrigger == "value")
679
+                                    {
680
+                                        var stopTrigger = new ThresholdDetector();
681
+                                        stopTrigger.setThreshold(Number(driverReference.stopvalue));
682
+                                        stopTrigger.timeForValue.connect(rangeTimer.stopTimer);
683
+                                        for(var j = 0; j < columnNames.length; j++)
684
+                                        {
685
+                                            if(columnNames[j] == driverReference.stopcolumnname)
686
+                                            {
687
+                                                channels[j].newData.connect(stopTrigger.newMeasurement);
688
+                                            }
689
+                                        }
690
+                                    }
691
+                                    rangeTimer.reportingName = configModel.data(driverIndex, 0);
692
+                                    rangeTimer.report = function() {
693
+                                        return "" + this.reportingName + ": " + this.value;
694
+                                    };
695
+                                }
696
+                                else if(driverReference.driver = "multirangetimer")
697
+                                {
698
+                                    var rangeTimer = new TimerDisplay();
699
+                                    rangeTimer.setDisplayFormat("mm:ss");
700
+                                    var decorator = new WidgetDecorator(rangeTimer, configModel.data(driverIndex, 0), 2);
701
+                                    indicatorPanel.addWidget(decorator);
702
+                                    var rangenames = driverReference.rangenames;
703
+                                    var endtemps = driverReference.endtemps;
704
+                                    var names = rangenames.slice(2, rangenames.length - 2).split(", ");
705
+                                    rangeTimer.rangeNames = new Array();
706
+                                    for(var j = 0; j < names.length; j++)
707
+                                    {
708
+                                        var name = names[j].slice(1, names[j].length - 1);
709
+                                        rangeTimer.rangeNames.push(name);
710
+                                    }
711
+                                    rangeTimer.rangeEnds = new Array();
712
+                                    var ends = endtemps.slice(2, endtemps.length - 2).split(", ");
713
+                                    for(var j = 0; j < ends.length; j++)
714
+                                    {
715
+                                        rangeTimer.rangeEnds.push(Number(ends[j]));
716
+                                    }
717
+                                    rangeTimer.currentRange = 0;
718
+                                    rangeTimer.results = new Array();
719
+                                    rangeTimer.trigger = new ThresholdDetector();
720
+                                    for(var j = 0; j < columnNames.length; j++)
721
+                                    {
722
+                                        if(columnNames[j] == driverReference.trigger)
723
+                                        {
724
+                                            channels[j].newData.connect(rangeTimer.trigger.newMeasurement);
725
+                                        }
726
+                                    }
727
+                                    rangeTimer.startRanges = function() {
728
+                                        arguments.callee.timer.currentRange = 0;
729
+                                        arguments.callee.timer.results.splice(0, arguments.callee.timer.results.length);
730
+                                        arguments.callee.timer.trigger.setThreshold(arguments.callee.timer.rangeEnds[0]);
731
+                                    };
732
+                                    rangeTimer.startRanges.timer = rangeTimer;
733
+                                    start.clicked.connect(rangeTimer.startTimer);
734
+                                    start.clicked.connect(rangeTimer.startRanges);
735
+                                    rangeTimer.transition = function() {
736
+                                        arguments.callee.timer.stopTimer();
737
+                                        arguments.callee.timer.results.push(arguments.callee.timer.value);
738
+                                        arguments.callee.timer.reset();
739
+                                        arguments.callee.timer.startTimer();
740
+                                        arguments.callee.timer.currentRange++;
741
+                                        if(arguments.callee.timer.currentRange <= arguments.callee.timer.rangeEnds.length)
742
+                                        {
743
+                                            arguments.callee.timer.trigger.setThreshold(arguments.callee.timer.rangeEnds[arguments.callee.timer.currentRange]);
744
+                                        }
745
+                                    };
746
+                                    rangeTimer.transition.timer = rangeTimer;
747
+                                    rangeTimer.trigger.timeForValue.connect(rangeTimer.transition);
748
+                                    stop.clicked.connect(rangeTimer.transition);
749
+                                    stop.clicked.connect(rangeTimer.stopTimer);
750
+                                    rangeTimer.report = function() {
751
+                                        var retval = "";
752
+                                        for(var j = 0; j < arguments.callee.timer.results.length; j++)
753
+                                        {
754
+                                            retval += arguments.callee.timer.rangeNames[j] + ": " + arguments.callee.timer.results[j] + "\n";
755
+                                        }
756
+                                        return retval;
757
+                                    };
758
+                                    rangeTimer.report.timer = rangeTimer;
759
+                                    rangetimers.push(rangeTimer);
760
+                                }
628 761
 			}
629 762
 		}
630 763
 		for(var i = 1; i < tabControls.length; i++)
@@ -818,6 +951,11 @@
818 951
 				log.addOutputAnnotationColumn(lc + channels.length - channelSkip);
819 952
                 var filename = log.saveTemporary();
820 953
                 currentBatchInfo.tempData = filename;
954
+                var notes = findChildObject(currentBatchInfo, 'annotation');
955
+                for(var i = 0; i < rangetimers.length; i++)
956
+                {
957
+                    notes.append(rangetimers[i].report());
958
+                }
821 959
                 currentBatchInfo.raise();
822 960
                 currentBatchInfo.activateWindow();
823 961
             }

+ 105
- 5
src/typica.w 查看文件

@@ -4155,6 +4155,7 @@ QScriptValue setTabOrder(QScriptContext *context, QScriptEngine *)
4155 4155
     return QScriptValue();
4156 4156
 }
4157 4157
 
4158
+
4158 4159
 @** Application Configuration.
4159 4160
 
4160 4161
 \noindent While \pn{} is intended as a data logging application, the diversity
@@ -19176,10 +19177,10 @@ QStringList itemList = data.split(",");
19176 19177
 model.
19177 19178
 
19178 19179
 @<Populate model column from list@>=
19179
-for(int i = 0; i < itemList.size(); i++)
19180
+for(int j = 0; j < itemList.size(); j++)
19180 19181
 {
19181
-    tablemodel->setData(tablemodel->index(i, column),
19182
-                   QVariant(itemList.at(i).toDouble()),
19182
+    tablemodel->setData(tablemodel->index(j, column),
19183
+                   QVariant(itemList.at(j).toDouble()),
19183 19184
                    Qt::DisplayRole);
19184 19185
 }
19185 19186
 
@@ -19523,8 +19524,6 @@ void RangeTimerConfWidget::updateStopTrigger(int option)
19523 19524
     }
19524 19525
 }
19525 19526
 
19526
-
19527
-
19528 19527
 @ The widget is registered with the configuration system.
19529 19528
 @<Register device configuration widgets@>=
19530 19529
 app.registerDeviceConfigurationWidget("rangetimer",
@@ -19535,6 +19534,107 @@ RangeTimerConfWidget::staticMetaObject);
19535 19534
 @<Class implementations@>=
19536 19535
 @<RangeTimerConfWidget implementation@>
19537 19536
 
19537
+@ The multirange timer is a little different. To keep configuration tractible,
19538
+this is slightly less general purpose than the range timer and only supports
19539
+automatic triggering on a single data series.
19540
+
19541
+@<Class declarations@>=
19542
+class MultiRangeTimerConfWidget : public BasicDeviceConfigurationWidget
19543
+{
19544
+    @[Q_OBJECT@]@/
19545
+    public:@/
19546
+        @[Q_INVOKABLE@]@, MultiRangeTimerConfWidget(DeviceTreeModel *model,
19547
+                                                    const QModelIndex &index);
19548
+    @[private slots@]:@/
19549
+        void updateColumnName(const QString &text);
19550
+        void updateRangeData();
19551
+    private:@/
19552
+        SaltModel *tablemodel;
19553
+};
19554
+
19555
+@ These limitations allow a rather small set of controls for configuration. A
19556
+line edit to specify the data series used for automatic triggering and a table
19557
+which specifies the name of the timed range and an ending temperature.
19558
+
19559
+@<MultiRangeTimerConfWidget implementation@>=
19560
+MultiRangeTimerConfWidget::MultiRangeTimerConfWidget(DeviceTreeModel *model,
19561
+                                                     const QModelIndex &index)
19562
+: BasicDeviceConfigurationWidget(model, index), tablemodel(new SaltModel(2))
19563
+{
19564
+    QFormLayout *layout = new QFormLayout;
19565
+    QLineEdit *trigger = new QLineEdit;
19566
+    layout->addRow(tr("Trigger column name:"), trigger);
19567
+    tablemodel->setHeaderData(0, Qt::Horizontal, "Range Name");
19568
+    tablemodel->setHeaderData(1, Qt::Horizontal, "End Temperature");
19569
+    QTableView *rangeTable = new QTableView;
19570
+    rangeTable->setModel(tablemodel);
19571
+    layout->addRow(tr("Range data:"), rangeTable);
19572
+    @<Get device configuration data for current node@>@;
19573
+    for(int i = 0; i < configData.size(); i++)
19574
+    {
19575
+        node = configData.at(i).toElement();
19576
+        if(node.attribute("name") == "trigger")
19577
+        {
19578
+            trigger->setText(node.attribute("value"));
19579
+        }
19580
+        else if(node.attribute("name") == "rangenames")
19581
+        {
19582
+            QString data = node.attribute("value");
19583
+            if(data.length() > 3)
19584
+            {
19585
+                data.chop(2);
19586
+                data = data.remove(0, 2);
19587
+            }
19588
+            QStringList itemList = data.split(", ");
19589
+            for(int j = 0; j < itemList.size(); j++)
19590
+            {
19591
+                QString item = itemList.at(j);
19592
+                item.chop(1);
19593
+                item = item.remove(0, 1);
19594
+                tablemodel->setData(tablemodel->index(j, 0),
19595
+                                    QVariant(item), Qt::DisplayRole);
19596
+            }
19597
+        }
19598
+        else if(node.attribute("name") == "endtemps")
19599
+        {
19600
+            @<Convert numeric array literal to list@>@;
19601
+            int column = 1;
19602
+            @<Populate model column from list@>@;
19603
+        }
19604
+    }
19605
+    updateColumnName(trigger->text());
19606
+    updateRangeData();
19607
+    connect(trigger, SIGNAL(textEdited(QString)), this, SLOT(updateColumnName(QString)));
19608
+    connect(tablemodel, SIGNAL(dataChanged(QModelIndex, QModelIndex)), this, SLOT(updateRangeData()));
19609
+    setLayout(layout);
19610
+}
19611
+
19612
+@ The update mechanisms are reasonably straightforward. Table updates just
19613
+refresh the entire table instead of attempting to be clever about updating only
19614
+the element that changed.
19615
+
19616
+@<MultiRangeTimerConfWidget implementation@>=
19617
+void MultiRangeTimerConfWidget::updateRangeData()
19618
+{
19619
+    updateAttribute("rangenames", tablemodel->quotedArrayLiteral(0, Qt::DisplayRole));
19620
+    updateAttribute("endtemps", tablemodel->arrayLiteral(1, Qt::DisplayRole));
19621
+}
19622
+
19623
+void MultiRangeTimerConfWidget::updateColumnName(const QString &text)
19624
+{
19625
+    updateAttribute("trigger", text);
19626
+}
19627
+
19628
+@ The widget is registered with the configuration system.
19629
+@<Register device configuration widgets@>=
19630
+app.registerDeviceConfigurationWidget("multirangetimer",
19631
+MultiRangeTimerConfWidget::staticMetaObject);
19632
+
19633
+@ The implementation is in the main source file.
19634
+
19635
+@<Class implementations@>=
19636
+@<MultiRangeTimerConfWidget implementation@>
19637
+
19538 19638
 @* Profile Translation Configuration Widget.
19539 19639
 
19540 19640
 \noindent Configuring profile translation requires knowing which column to use

Loading…
取消
儲存