Program Listing for File FkinSettings.qml

Return to documentation for file (src/qml/components/FkinSettings.qml)

import QtQuick 2.11
import QtQuick.Controls 2.4
import QtQuick.Controls.Material 2.4
import QtQuick.Layouts 1.11
import QtQuick.Shapes 1.11
import QtCharts 2.2

import fkin.Dds 1.0
import "fkinHelpers.js" as Fkin

ColumnLayout {
  id: root;

  property alias themeChanger: themeChanger_;
  property bool ddsInitialized: false;


  property point mouseTip: Qt.point(0,0);
  property bool mouseActive: false;
  signal pointHovered(point pnt);

  onPointHovered:{
    mouseTip = pnt;
    mouseActive = true;
    hoverShow.restart();
  }

  Timer {
    id: hoverShow;
    interval: 1500;
    running: false;
    repeat: false;
    onTriggered: {
      root.mouseActive = false;
    }
  }

  FkinStyle { id: style; }
  FkinDdsTopics { id: topic; }

  function init(participant){

    dds.purseSpeed.init(participant,
                        topic.vesselSettingSpeed,
                        topic.idPursePlanner,
                        settingSpeed.value*1.852/3.6,
                        true);
    dds.purseRadius.init(participant,
                         topic.vesselSettingRadius,
                         topic.idPursePlanner,
                         Qt.vector2d(settingDiameter_x.value/2,settingDiameter_y.value/2),
                         true);
    dds.purseArcLength.init(participant,
                            topic.aimPointArcLength,
                            topic.idPursePlanner,
                            alongPath.value,
                            true);

    dds.purseFishMargin.init(participant,
                            topic.fishMargin,
                            topic.idPursePlanner,
                            fishMargin.value,
                            true);

    dds.purseLeadMargin.init(participant,
                             topic.leadMargin,
                             topic.idPursePlanner,
                             marginLead.value,
                             true);

    dds.purseLeadline.init(participant,
                           topic.leadlineParameters,
                           topic.idLeadline,
                           Qt.vector2d(tauLead.value, setPointLead.value),
                           true);

    ddsLeadlineTrajectoryBuffer.init(participant,
                                     topic.leadlineResponse,
                                     topic.idLeadline,
                                     2000,
                                     true);

  }

  function estimateO(a, b){
    var h = Math.pow((a - b), 2) / Math.pow((a + b), 2);
    return Math.PI*(a + b)*(1 + 3*h/(10 + Math.pow((4 - 3*h), (1/2)) ));
  }

  Item {
    id: dds;

    property alias purseSpeed: purseSpeed_;
    property alias purseRadius: purseRadius_;
    property alias purseArcLength: purseArcLength_;
    property alias purseFishMargin: purseFishMargin_;
    property alias purseLeadMargin: purseLeadMargin_;
    property alias purseLeadline: purseLeadline_;

    // Added some helper types for some parameters in FkinPurseDashboard

    DdsIdVec1dPublisher { id: purseSpeed_;      value: settingSpeed.value*1.852/3.6; }
    DdsIdVec2dPublisher { id: purseRadius_;     value: Qt.vector2d(settingDiameter_x.value/2,
                                                                   settingDiameter_y.value/2); }
    DdsIdVec1dPublisher { id: purseArcLength_;  value: alongPath.value; }
    DdsIdVec1dPublisher { id: purseFishMargin_; value: fishMargin.value; }
    DdsIdVec1dPublisher { id: purseLeadMargin_; value: marginLead.value; }
    DdsIdVec2dPublisher { id: purseLeadline_;   value: Qt.vector2d(tauLead.value,
                                                                   setPointLead.value); }
    DdsIdVec1dBuffer { id: ddsLeadlineTrajectoryBuffer; }

  }

  // Forcefully send parameters regularly
  Timer {
    interval: 2000;
    running: true;
    repeat: true;
    onTriggered: {
      if(root.ddsInitialized)
      {
        dds.purseSpeed.publish();
        dds.purseRadius.publish();
        dds.purseArcLength.publish();
        dds.purseFishMargin.publish();
        dds.purseLeadMargin.publish();
        dds.purseLeadline.publish();
      }
    }
  }


  RowLayout {
    Layout.alignment: Qt.AlignTop | Qt.AlignLeft;
    Label {
      font: style.iconFontBig;
      text: "\uebfc";
    }
    Label {
      text: qsTr("Pursing settings");
      font.weight: Font.DemiBold;
      font.underline: true;
    }
  }
  RowLayout {
    id: sets;
    width: parent.width;
    GridLayout {
      Layout.alignment: Qt.AlignTop | Qt.AlignLeft;
      columns: 2;

      Label {
        text: qsTr("Setting speed");
        property string toolTipText: qsTr("Speed in water, knots");
        ToolTip.text: toolTipText;
        ToolTip.visible: toolTipText ? ma_sp.containsMouse : false;
        MouseArea {
          id: ma_sp;
          anchors.fill: parent;
          hoverEnabled: true;
        }
      }
      RowLayout {
        Slider {
          id: settingSpeed;
          from: 5;
          value: 12;
          to: 15;
          stepSize: 1;
          snapMode: Slider.SnapOnRelease;
          //onValueChanged: console.log(qsTr("Setting speed: ") + value);

        }
        Label { text: settingSpeed.value + " kn";  }
      }

      Label {
        text: qsTr("Setting diameter, along");
        property string toolTipText: qsTr("Idealized setting diameter along fish direction");
        ToolTip.text: toolTipText;
        ToolTip.visible: toolTipText ? ma_diaX.containsMouse : false;
        MouseArea {
          id: ma_diaX;
          anchors.fill: parent;
          hoverEnabled: true;
        }

      }
      RowLayout {
        Slider {
          id: settingDiameter_x;
          from: 200;
          value: 300;
          to: 400;
          stepSize: 5;
          snapMode: Slider.SnapOnRelease;
          //onValueChanged: console.log(qsTr("Setting diameter: ") + value);
        }
        Label { text: settingDiameter_x.value + " m";  }
      }

      Label {
        text: qsTr("Setting diameter, across");
        property string toolTipText: qsTr("Idealized setting diameter across fish direction");
        ToolTip.text: toolTipText;
        ToolTip.visible: toolTipText ? ma_diaY.containsMouse : false;
        MouseArea {
          id: ma_diaY;
          anchors.fill: parent;
          hoverEnabled: true;
        }

      }
      RowLayout {
        Slider {
          id: settingDiameter_y;
          from: 200;
          value: 300;
          to: 400;
          stepSize: 5;
          snapMode: Slider.SnapOnRelease;
          //onValueChanged: console.log(qsTr("Setting diameter: ") + value);
        }
        Label { text: settingDiameter_y.value + " m";  }
      }

      Label {
        text: qsTr("Aim point distance");
        property string toolTipText: qsTr("Distance along vessel path from deployment point to the point at which the fish would collide, meter");
        ToolTip.text: toolTipText;
        ToolTip.visible: toolTipText ? ma.containsMouse : false;
        MouseArea {
          id: ma;
          anchors.fill: parent;
          hoverEnabled: true;
        }
      }

      RowLayout {
        Slider {

          id: alongPath;
          from: root.estimateO(settingDiameter_x.value/2, settingDiameter_y.value/2)/4; // (quarter)
          value: alongPath.from*4*1.75/5;       // default: 35% of circumference
          to: alongPath.from*4*3/5;          // approx. 60% of circumference
          stepSize: 5;
          snapMode: Slider.SnapOnRelease;
          //onValueChanged: console.log(qsTr("Along path distance: ") + value);

        }
        Label { text: Number(alongPath.value).toLocaleString(Qt.locale(),'f',0) + " m"; }
      }
      Label { text: qsTr("Circumference:"); }
      Label {
        id: circumInfo;
        property real circumference: root.estimateO(settingDiameter_x.value/2, settingDiameter_y.value/2);
        text: Number(circumference).toLocaleString(Qt.locale(),'f',0) + " m,  85%: " +
          Number(0.85*circumference).toLocaleString(Qt.locale(), 'f', 0) + " m"; }

      Label {
        text: qsTr("Fish margin when set");
        property string toolTipText: qsTr("Minimum distance to fish when finished setting, meter");
        ToolTip.text: toolTipText;
        ToolTip.visible: toolTipText ? ma_fm.containsMouse : false;
        MouseArea {
          id: ma_fm;
          anchors.fill: parent;
          hoverEnabled: true;
        }
      }
      RowLayout {
        Slider {
          id: fishMargin;
          from: 1;
          value: settingDiameter_x.value/3;
          to: settingDiameter_x.value*3/4;
          stepSize: 1;
          snapMode: Slider.SnapOnRelease;
        }
        Label { text: Number(fishMargin.value).toLocaleString(Qt.locale(),'f',0) + " m";  }
      }
      Label {
        text: qsTr("Leadline sink margin");
        property string toolTipText: qsTr("Margin at collision point = leadline depth - fish depth");
        ToolTip.text: toolTipText;
        ToolTip.visible: toolTipText ? maMarg.containsMouse : false;
        MouseArea {
          id: maMarg;
          anchors.fill: parent;
          hoverEnabled: true;
        }
      }
      RowLayout {
        Slider {
          id: marginLead;
          from: 1;
          to: setPointLead.value - 1;
          value: 50;
          stepSize: 1;
          snapMode: Slider.SnapOnRelease;
        }
        Label{ text: marginLead.value + " m"; }
      }
      Label {
        text: qsTr("Leadline time constant");
        property string toolTipText: qsTr("Time to reach about 2/3 of set point");
        ToolTip.text: toolTipText;
        ToolTip.visible: toolTipText ? maTau.containsMouse : false;
        MouseArea {
          id: maTau;
          anchors.fill: parent;
          hoverEnabled: true;
        }
      }
      RowLayout {
        Slider {
          id: tauLead;
          from: 250;
          to: 450;
          value: 350;
          stepSize: 5;
          snapMode: Slider.SnapOnRelease;
        }
        Label{ text: tauLead.value + " s"; }
      }
      Label {
        text: qsTr("Leadline set point");
        property string toolTipText: qsTr("Depth if not hauled");
        ToolTip.text: toolTipText;
        ToolTip.visible: toolTipText ? maSet.containsMouse : false;
        MouseArea {
          id: maSet;
          anchors.fill: parent;
          hoverEnabled: true;
        }
      }
      RowLayout {
        Slider {
          id: setPointLead;
          from: 80;
          to: 200;
          value: 160;
          stepSize: 2;
          snapMode: Slider.SnapOnRelease;
        }
        Label{ text: setPointLead.value + " m"; }
      }
    }

    ColumnLayout {
    Shape {
      width: settingDiameter_x.to*scale + 30;
      height: settingDiameter_x.to*scale + 20;
      id: shape;

      property real scale: 0.7;
      property real radiusX: scale*settingDiameter_x.value/2;
      property real radiusY: scale*settingDiameter_y.value/2;
      property real settingSweep: 360*(alongPath.value*shape.scale)/root.estimateO(shape.radiusX,shape.radiusY);
      property real eightySweep: 306 - settingSweep;
      // multisample, decide based on your scene settings
      layer.enabled: true;
      layer.samples: 6;


      ShapePath {
        fillColor: "transparent"; //Material.background;
        strokeColor: Material.color(Material.Orange, Material.Shade500);
        strokeWidth: 5;
        capStyle: ShapePath.FlatCap;

        PathAngleArc {
          id: sweepAlong;
          centerX: shape.radiusY + 10 + 10;
          centerY: shape.radiusX + 10;
          radiusX: shape.radiusY;
          radiusY: shape.radiusX;
          startAngle: -90;
          sweepAngle: -shape.settingSweep;
          //onSweepAngleChanged: console.log(sweepAngle);
        }
      }

      ShapePath {
        fillColor: "transparent";//Material.background;
        strokeColor: Material.accent;
        //strokeStyle: ShapePath.DashLine;
        strokeWidth: 4;
        capStyle: ShapePath.RoundCap;

        PathAngleArc {
          id: sentrum;
          centerX: sweepAlong.centerX; centerY: sweepAlong.centerY;
          radiusX: shape.radiusY; radiusY: shape.radiusX;
          startAngle: -90; //sweepAlong.startAngle + sweepAlong.sweepAngle;
          sweepAngle: shape.eightySweep;//300 - sweepAlong.sweepAngle;
        }
      }

      ShapePath {
        id: fishDir;
        strokeColor: Material.color(Material.DeepOrange, Material.Shade500);
        strokeWidth: 4;
        fillColor: "transparent";
        joinStyle: ShapePath.RoundJoin;


        startX: sweepAlong.centerX; startY: sweepAlong.centerY;
        PathLine {
          id: fishPoint;
          x: fishDir.startX; y: fishDir.startY - 0.3*shape.radiusX; }
        PathLine { relativeX: 7; relativeY: 7; }
        PathLine { relativeX: -14; relativeY: 0; }
        PathLine { relativeX: 7; relativeY: -7; }
      }

      ShapePath {
        id: trapMargin;
        strokeColor: Material.color(Material.Blue);
        strokeWidth: 3;
        fillColor: "transparent";
        joinStyle: ShapePath.RoundCap;
        strokeStyle: ShapePath.DashLine;

        startX: sentrum.centerX;
        startY: sentrum.centerY + shape.radiusX;
        PathLine { relativeX: 0; relativeY: -fishMargin.value*shape.scale; }

      }
    }
      Shape {
        width: 200;
        height: 100;
        id: shapeMargin;
        // multisample, decide based on your scene settings
        layer.enabled: true;
        layer.samples: 6;

        ShapePath {
          id: fishIndication;
          strokeColor: Material.color(Material.DeepOrange);
          strokeWidth: 3;
          fillColor: "transparent";

          startX: 50;
          startY: 10;
          PathLine { relativeX: 100; relativeY: 0; }

        }
        ShapePath {
          id: marginSink;
          strokeColor: Material.color(Material.Blue);
          strokeWidth: 3;
          fillColor: "transparent";
          strokeStyle: ShapePath.DashLine;
          startX: 150;
          startY: 10;
          PathLine { relativeX: 0; relativeY: 100*marginLead.value/marginLead.to; }
        }
      }
    }
  }

  RowLayout {
    id: leadPosition;
    Label { text: "\uef50"; font: style.iconFont; } // info
    Label {
      text: !root.mouseActive ? "" :
        new Date(root.mouseTip.x - new Date()).toLocaleTimeString(Qt.locale(), "mm:ss") + ": " +
        Number(root.mouseTip.y).toLocaleString(Qt.locale(),'f', 0) + " m";
      Layout.preferredWidth: 200;
    }
  }

  TimeChart {
    id: leadlineChart;
    //title: qsTr("Leadline response");
    Layout.fillWidth: true;
    Layout.maximumWidth: 1000;
    //Layout.preferredWidth: 0.8*parent.width;
    height: 350;
    labelY: "Leadline [m]";
    fovY: Qt.point(0, 5);
    axisY.reverse: true;
    widthMS: 1000000;
    futureMS: 0;
    axisT.tickCount: 8;

    axisT.visible: false;

    DateTimeAxis {
      id: anotherTime;
      titleText: qsTr("Time [min]");
      labelsFont: style.dateFont;
      titleFont: style.plotFont;
      format: "m";
      tickCount : 9;
      min: new Date(0);
      max: new Date(leadlineChart.widthMS);

      function setStyle(){
        anotherTime.labelsFont = style.dateFont;
        anotherTime.titleFont = style.dateFont;
      }
    }

    ScatterSeries {
      id: dummy;
      axisX: anotherTime;
      axisYRight: leadlineChart.axisY;
    }


    LineSeries {
      id: leadlineLine;
      name: qsTr("Leadline");
      axisX: leadlineChart.axisT;
      axisYRight: leadlineChart.axisY;
      // QTBUG-58230: cannot use OpenGL because 32 bit int overflow (time is int64)
      useOpenGL: false;
      Component.onCompleted: setStyle();
      function setStyle()
      {
        color = style.defaultLineColor;
        leadlineLine.style = Qt.SolidLine;
        width = 3;
      }

      onHovered: if(state){ root.pointHovered(point); }
    }

    Connections {
      target: themeChanger_;
      onToggled:
      {
        leadlineChart.themeChanged();
        leadlineLine.setStyle();
        anotherTime.setStyle();
      }
    }

    // Connect buffer data to be plotted to line series.
    Connections {
      target: ddsLeadlineTrajectoryBuffer;
      onNewData:
      {
        ddsLeadlineTrajectoryBuffer.updateSeries(leadlineLine, FKIN.T, FKIN.X);
        ddsLeadlineTrajectoryBuffer.clearBuffers();
      }
      onRangeChanged:
      {

        if(dim == FKIN.X)
        {
          leadlineLine.axisYRight.min = range.x;
          leadlineLine.axisYRight.max = range.y;
          Fkin.zoomToFrame(range, leadlineChart.fovY, leadlineLine.axisYRight, 2);
        }
      }
      onRangeTChanged:
      {
        leadlineChart.updateRangeT(ddsLeadlineTrajectoryBuffer.rangeTmin,
                                   ddsLeadlineTrajectoryBuffer.rangeTmax);
      }
    }

  }

  ProgressBar {
    // Horizontal line
    implicitWidth: parent.width;
    value: 1.0;
    Layout.alignment: Qt.AlignLeft;
  }


  RowLayout {
    Layout.alignment: Qt.AlignTop | Qt.AlignLeft;
    Label {
      font: style.iconFontBig;
      text: "\uef24"; // eye
    }
    Label {
      text: qsTr("Appearance");
      font.weight: Font.DemiBold;
      font.underline: true;
    }
  }
  RowLayout {
    Layout.alignment: Qt.AlignLeft;
    Label { text: qsTr("Styling");  }
    Switch {
      id: themeChanger_;
      text: qsTr("Dark Theme");

      Component.onCompleted:{
        if(Material.theme == Material.Dark)
          toggle();
      }
    }
  }

  // TODO: add settings for parameters of optimization problem

}