Browse Source

Merge pull request #1307 from dogmaphobic/newToolBar

New, QML based Tool Bar.
QGC4.4
Lorenz Meier 10 years ago
parent
commit
a4af4d4dd6
  1. 22
      files/images/status/battery_0.svg
  2. 31
      files/images/status/battery_100.svg
  3. 24
      files/images/status/battery_20.svg
  4. 26
      files/images/status/battery_40.svg
  5. 28
      files/images/status/battery_60.svg
  6. 30
      files/images/status/battery_80.svg
  7. 275
      files/images/status/gps.svg
  8. BIN
      files/images/status/message_megaphone.png
  9. BIN
      files/images/status/message_triangle.png
  10. 7
      qgroundcontrol.pro
  11. 13
      qgroundcontrol.qrc
  12. 5
      src/QGCQmlWidgetHolder.cpp
  13. 7
      src/QGCQmlWidgetHolder.h
  14. 11
      src/QGCQmlWidgetHolder.ui
  15. 4
      src/VehicleSetup/SetupViewTest.cc
  16. 8
      src/qgcunittest/MainWindowTest.cc
  17. 39
      src/uas/UASMessageHandler.cc
  18. 15
      src/uas/UASMessageHandler.h
  19. 606
      src/ui/MainWindow.cc
  20. 45
      src/ui/MainWindow.h
  21. 150
      src/ui/QGCLinkConfiguration.cc
  22. 1
      src/ui/QGCLinkConfiguration.h
  23. 2
      src/ui/QGCToolBar.cc
  24. 579
      src/ui/toolbar/MainToolBar.cc
  25. 180
      src/ui/toolbar/MainToolBar.h
  26. 489
      src/ui/toolbar/MainToolBar.qml
  27. 10
      src/ui/uas/UASMessageView.cc
  28. 7
      src/ui/uas/UASMessageView.h

22
files/images/status/battery_0.svg

@ -0,0 +1,22 @@ @@ -0,0 +1,22 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 18.1.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.1"
id="svg4264" sodipodi:docname="battery_0.svg" inkscape:version="0.91 r13725" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" xmlns:svg="http://www.w3.org/2000/svg" xmlns:cc="http://creativecommons.org/ns#"
xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="-142 87 326.3 620"
enable-background="new -142 87 326.3 620" xml:space="preserve">
<title id="title4294">Battery</title>
<sodipodi:namedview inkscape:window-maximized="0" inkscape:window-y="65" inkscape:window-x="2776" inkscape:window-height="1259" inkscape:window-width="2003" fit-margin-bottom="0.02" fit-margin-right="0.02" inkscape:current-layer="layer1" inkscape:pageshadow="2" inkscape:document-units="in" inkscape:pageopacity="0.0" units="in" borderopacity="1.0" bordercolor="#666666" pagecolor="#ffffff" showgrid="false" inkscape:cy="387.50002" inkscape:zoom="1.4103225" inkscape:cx="115.31779" id="base" fit-margin-top="0.02" fit-margin-left="0.02" showborder="true">
</sodipodi:namedview>
<path id="rect4970" inkscape:connector-curvature="0" fill="#E6E7E8" stroke="#E6E7E8" stroke-width="6" d="M-127.7,667.9v-502
c0-14.8,13.1-26.8,29.3-26.8h239.2c16.2,0,29.3,12,29.3,26.8v502c0,14.8-13.1,26.8-29.3,26.8H-98.4
C-114.6,694.7-127.7,682.7-127.7,667.9z"/>
<path id="rect4360" inkscape:connector-curvature="0" fill="none" d="M-140.6,677.6V156.1c0-15.4,14.2-27.9,31.8-27.9h259.9
c17.6,0,31.8,12.6,31.8,27.9v521.5c0,15.4-14.2,27.9-31.8,27.9h-259.8C-126.3,705.5-140.6,693-140.6,677.6z"/>
<g id="g4222" transform="translate(-127.22081,216.20249)">
<path id="path4224" inkscape:connector-curvature="0" fill="#E6E7E8" stroke="#E6E7E8" stroke-width="6" stroke-miterlimit="10" d="
M231.3-81.3c0,2.2-1.7,3.9-3.9,3.9h-155c-2.2,0-3.9-1.7-3.9-3.9v-40.2c0-2.2,1.7-3.9,3.9-3.9h155c2.2,0,3.9,1.7,3.9,3.9L231.3-81.3
L231.3-81.3L231.3-81.3z"/>
</g>
<text transform="matrix(0.757 0 0 1 -80.0776 552.9648)" font-family="'Helvetica'" font-size="406.7761">X</text>
</svg>

After

Width:  |  Height:  |  Size: 2.3 KiB

31
files/images/status/battery_100.svg

@ -0,0 +1,31 @@ @@ -0,0 +1,31 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 18.1.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.1"
id="svg4264" sodipodi:docname="battery_100.svg" inkscape:version="0.91 r13725" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" xmlns:svg="http://www.w3.org/2000/svg" xmlns:cc="http://creativecommons.org/ns#"
xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="-142 87 326.3 620"
enable-background="new -142 87 326.3 620" xml:space="preserve">
<title id="title4294">Battery</title>
<sodipodi:namedview inkscape:window-maximized="0" inkscape:window-y="65" inkscape:window-x="2776" inkscape:window-height="1259" inkscape:window-width="2003" fit-margin-bottom="0.02" fit-margin-right="0.02" inkscape:current-layer="layer1" inkscape:pageshadow="2" inkscape:document-units="in" inkscape:pageopacity="0.0" units="in" borderopacity="1.0" bordercolor="#666666" pagecolor="#ffffff" showgrid="false" inkscape:cy="393.84035" inkscape:zoom="1.2144444" inkscape:cx="202.22082" id="base" fit-margin-top="0.02" fit-margin-left="0.02" showborder="true">
</sodipodi:namedview>
<path id="rect4970" inkscape:connector-curvature="0" fill="#E6E7E8" stroke="#E6E7E8" stroke-width="6" d="M-127.7,667.9v-502
c0-14.8,13.1-26.8,29.3-26.8h239.2c16.2,0,29.3,12,29.3,26.8v502c0,14.8-13.1,26.8-29.3,26.8H-98.4
C-114.6,694.7-127.7,682.7-127.7,667.9z"/>
<path id="rect4360" inkscape:connector-curvature="0" fill="none" d="M-140.6,677.6V156.1c0-15.4,14.2-27.9,31.8-27.9h259.9
c17.6,0,31.8,12.6,31.8,27.9v521.5c0,15.4-14.2,27.9-31.8,27.9h-259.8C-126.3,705.5-140.6,693-140.6,677.6z"/>
<path id="path4669" sodipodi:nodetypes="ccccc" inkscape:connector-curvature="0" fill="#09753B" d="M-91.4,260.4v-90.1h225.1v90.1
H-91.4L-91.4,260.4z"/>
<path id="path4671" sodipodi:nodetypes="ccccc" inkscape:connector-curvature="0" fill="#09753B" d="M-91.4,363.3v-90.1h225.1v90.1
H-91.4z"/>
<path id="path4673" sodipodi:nodetypes="ccccc" inkscape:connector-curvature="0" fill="#09753B" d="M-91.4,466.3v-90.1h225.1v90.1
H-91.4z"/>
<path id="path4675" sodipodi:nodetypes="ccccc" inkscape:connector-curvature="0" fill="#09753B" d="M-91.4,569.2v-90.1h225.1v90.1
H-91.4z"/>
<path id="path4679" sodipodi:nodetypes="ccccc" inkscape:connector-curvature="0" fill="#09753B" d="M-91.4,672V582h225.1V672H-91.4
z"/>
<g id="g4222" transform="translate(-127.22081,216.20249)">
<path id="path4224" inkscape:connector-curvature="0" fill="#E6E7E8" stroke="#E6E7E8" stroke-width="6" stroke-miterlimit="10" d="
M229.9-81.3c0,2.2-1.7,3.9-3.9,3.9h-155c-2.2,0-3.9-1.7-3.9-3.9v-40.2c0-2.2,1.7-3.9,3.9-3.9h155c2.2,0,3.9,1.7,3.9,3.9L229.9-81.3
L229.9-81.3L229.9-81.3z"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 2.9 KiB

24
files/images/status/battery_20.svg

@ -0,0 +1,24 @@ @@ -0,0 +1,24 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 18.1.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.1"
id="svg4264" sodipodi:docname="battery_100.svg" inkscape:version="0.91 r13725" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" xmlns:svg="http://www.w3.org/2000/svg" xmlns:cc="http://creativecommons.org/ns#"
xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="-142 87 326.32 620"
enable-background="new -142 87 326.32 620" xml:space="preserve">
<title id="title4294">Battery</title>
<sodipodi:namedview inkscape:window-maximized="0" inkscape:window-y="65" inkscape:window-x="2776" inkscape:window-height="1259" inkscape:window-width="2003" fit-margin-bottom="0.02" fit-margin-right="0.02" inkscape:current-layer="layer1" inkscape:pageshadow="2" inkscape:document-units="in" inkscape:pageopacity="0.0" units="in" borderopacity="1.0" bordercolor="#666666" pagecolor="#ffffff" showgrid="false" inkscape:cy="393.84035" inkscape:zoom="1.2144444" inkscape:cx="202.22082" id="base" fit-margin-top="0.02" fit-margin-left="0.02" showborder="true">
</sodipodi:namedview>
<path id="rect4970" inkscape:connector-curvature="0" fill="#E6E7E8" stroke="#E6E7E8" stroke-width="6" d="M-127.68,667.88v-502
c0-14.8,13.12-26.8,29.28-26.8h239.2c16.16,0,29.28,12,29.28,26.8v502c0,14.8-13.12,26.8-29.28,26.8H-98.4
C-114.64,694.68-127.68,682.68-127.68,667.88z"/>
<path id="rect4360" inkscape:connector-curvature="0" fill="none" d="M-140.56,677.64V156.12c0-15.36,14.24-27.92,31.76-27.92
h259.92c17.6,0,31.76,12.56,31.76,27.92v521.52c0,15.36-14.24,27.92-31.76,27.92h-259.84C-126.32,705.48-140.56,693-140.56,677.64z"
/>
<path id="path4679" sodipodi:nodetypes="ccccc" inkscape:connector-curvature="0" fill="#471F0D" d="M-91.36,672.04v-90.08h225.12
v90.08H-91.36z"/>
<g id="g4222" transform="translate(-127.22081,216.20249)">
<path id="path4224" inkscape:connector-curvature="0" fill="#E6E7E8" stroke="#E6E7E8" stroke-width="6" stroke-miterlimit="10" d="
M229.861-81.283c0,2.24-1.68,3.92-3.92,3.92H70.901c-2.24,0-3.92-1.68-3.92-3.92v-40.16c0-2.24,1.68-3.92,3.92-3.92h155.04
c2.24,0,3.92,1.68,3.92,3.92L229.861-81.283L229.861-81.283L229.861-81.283z"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 2.4 KiB

26
files/images/status/battery_40.svg

@ -0,0 +1,26 @@ @@ -0,0 +1,26 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 18.1.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.1"
id="svg4264" sodipodi:docname="battery_100.svg" inkscape:version="0.91 r13725" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" xmlns:svg="http://www.w3.org/2000/svg" xmlns:cc="http://creativecommons.org/ns#"
xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="-142 87 326.32 620"
enable-background="new -142 87 326.32 620" xml:space="preserve">
<title id="title4294">Battery</title>
<sodipodi:namedview inkscape:window-maximized="0" inkscape:window-y="65" inkscape:window-x="2776" inkscape:window-height="1259" inkscape:window-width="2003" fit-margin-bottom="0.02" fit-margin-right="0.02" inkscape:current-layer="layer1" inkscape:pageshadow="2" inkscape:document-units="in" inkscape:pageopacity="0.0" units="in" borderopacity="1.0" bordercolor="#666666" pagecolor="#ffffff" showgrid="false" inkscape:cy="393.84035" inkscape:zoom="1.2144444" inkscape:cx="202.22082" id="base" fit-margin-top="0.02" fit-margin-left="0.02" showborder="true">
</sodipodi:namedview>
<path id="rect4970" inkscape:connector-curvature="0" fill="#E6E7E8" stroke="#E6E7E8" stroke-width="6" d="M-127.68,667.88v-502
c0-14.8,13.12-26.8,29.28-26.8h239.2c16.16,0,29.28,12,29.28,26.8v502c0,14.8-13.12,26.8-29.28,26.8H-98.4
C-114.64,694.68-127.68,682.68-127.68,667.88z"/>
<path id="rect4360" inkscape:connector-curvature="0" fill="none" d="M-140.56,677.64V156.12c0-15.36,14.24-27.92,31.76-27.92
h259.92c17.6,0,31.76,12.56,31.76,27.92v521.52c0,15.36-14.24,27.92-31.76,27.92h-259.84C-126.32,705.48-140.56,693-140.56,677.64z"
/>
<path id="path4675" sodipodi:nodetypes="ccccc" inkscape:connector-curvature="0" fill="#9F4B23" d="M-91.36,569.16v-90.08h225.12
v90.08H-91.36z"/>
<path id="path4679" sodipodi:nodetypes="ccccc" inkscape:connector-curvature="0" fill="#9F4B23" d="M-91.36,672.04v-90.08h225.12
v90.08H-91.36z"/>
<g id="g4222" transform="translate(-127.22081,216.20249)">
<path id="path4224" inkscape:connector-curvature="0" fill="#E6E7E8" stroke="#E6E7E8" stroke-width="6" stroke-miterlimit="10" d="
M229.861-81.283c0,2.24-1.68,3.92-3.92,3.92H70.901c-2.24,0-3.92-1.68-3.92-3.92v-40.16c0-2.24,1.68-3.92,3.92-3.92h155.04
c2.24,0,3.92,1.68,3.92,3.92L229.861-81.283L229.861-81.283L229.861-81.283z"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 2.6 KiB

28
files/images/status/battery_60.svg

@ -0,0 +1,28 @@ @@ -0,0 +1,28 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 18.1.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.1"
id="svg4264" sodipodi:docname="battery_100.svg" inkscape:version="0.91 r13725" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" xmlns:svg="http://www.w3.org/2000/svg" xmlns:cc="http://creativecommons.org/ns#"
xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="-142 87 326.32 620"
enable-background="new -142 87 326.32 620" xml:space="preserve">
<title id="title4294">Battery</title>
<sodipodi:namedview inkscape:window-maximized="0" inkscape:window-y="65" inkscape:window-x="2776" inkscape:window-height="1259" inkscape:window-width="2003" fit-margin-bottom="0.02" fit-margin-right="0.02" inkscape:current-layer="layer1" inkscape:pageshadow="2" inkscape:document-units="in" inkscape:pageopacity="0.0" units="in" borderopacity="1.0" bordercolor="#666666" pagecolor="#ffffff" showgrid="false" inkscape:cy="393.84035" inkscape:zoom="1.2144444" inkscape:cx="202.22082" id="base" fit-margin-top="0.02" fit-margin-left="0.02" showborder="true">
</sodipodi:namedview>
<path id="rect4970" inkscape:connector-curvature="0" fill="#E6E7E8" stroke="#E6E7E8" stroke-width="6" d="M-127.68,667.88v-502
c0-14.8,13.12-26.8,29.28-26.8h239.2c16.16,0,29.28,12,29.28,26.8v502c0,14.8-13.12,26.8-29.28,26.8H-98.4
C-114.64,694.68-127.68,682.68-127.68,667.88z"/>
<path id="rect4360" inkscape:connector-curvature="0" fill="none" d="M-140.56,677.64V156.12c0-15.36,14.24-27.92,31.76-27.92
h259.92c17.6,0,31.76,12.56,31.76,27.92v521.52c0,15.36-14.24,27.92-31.76,27.92h-259.84C-126.32,705.48-140.56,693-140.56,677.64z"
/>
<path id="path4673" sodipodi:nodetypes="ccccc" inkscape:connector-curvature="0" fill="#09753B" d="M-91.36,466.28V376.2h225.12
v90.08H-91.36z"/>
<path id="path4675" sodipodi:nodetypes="ccccc" inkscape:connector-curvature="0" fill="#09753B" d="M-91.36,569.16v-90.08h225.12
v90.08H-91.36z"/>
<path id="path4679" sodipodi:nodetypes="ccccc" inkscape:connector-curvature="0" fill="#09753B" d="M-91.36,672.04v-90.08h225.12
v90.08H-91.36z"/>
<g id="g4222" transform="translate(-127.22081,216.20249)">
<path id="path4224" inkscape:connector-curvature="0" fill="#E6E7E8" stroke="#E6E7E8" stroke-width="6" stroke-miterlimit="10" d="
M229.861-81.283c0,2.24-1.68,3.92-3.92,3.92H70.901c-2.24,0-3.92-1.68-3.92-3.92v-40.16c0-2.24,1.68-3.92,3.92-3.92h155.04
c2.24,0,3.92,1.68,3.92,3.92L229.861-81.283L229.861-81.283L229.861-81.283z"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 2.7 KiB

30
files/images/status/battery_80.svg

@ -0,0 +1,30 @@ @@ -0,0 +1,30 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 18.1.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.1"
id="svg4264" sodipodi:docname="battery_100.svg" inkscape:version="0.91 r13725" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" xmlns:svg="http://www.w3.org/2000/svg" xmlns:cc="http://creativecommons.org/ns#"
xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="-142 87 326.32 620"
enable-background="new -142 87 326.32 620" xml:space="preserve">
<title id="title4294">Battery</title>
<sodipodi:namedview inkscape:window-maximized="0" inkscape:window-y="65" inkscape:window-x="2776" inkscape:window-height="1259" inkscape:window-width="2003" fit-margin-bottom="0.02" fit-margin-right="0.02" inkscape:current-layer="layer1" inkscape:pageshadow="2" inkscape:document-units="in" inkscape:pageopacity="0.0" units="in" borderopacity="1.0" bordercolor="#666666" pagecolor="#ffffff" showgrid="false" inkscape:cy="393.84035" inkscape:zoom="1.2144444" inkscape:cx="202.22082" id="base" fit-margin-top="0.02" fit-margin-left="0.02" showborder="true">
</sodipodi:namedview>
<path id="rect4970" inkscape:connector-curvature="0" fill="#E6E7E8" stroke="#E6E7E8" stroke-width="6" d="M-127.68,667.88v-502
c0-14.8,13.12-26.8,29.28-26.8h239.2c16.16,0,29.28,12,29.28,26.8v502c0,14.8-13.12,26.8-29.28,26.8H-98.4
C-114.64,694.68-127.68,682.68-127.68,667.88z"/>
<path id="rect4360" inkscape:connector-curvature="0" fill="none" d="M-140.56,677.64V156.12c0-15.36,14.24-27.92,31.76-27.92
h259.92c17.6,0,31.76,12.56,31.76,27.92v521.52c0,15.36-14.24,27.92-31.76,27.92h-259.84C-126.32,705.48-140.56,693-140.56,677.64z"
/>
<path id="path4671" sodipodi:nodetypes="ccccc" inkscape:connector-curvature="0" fill="#09753B" d="M-91.36,363.32v-90.08h225.12
v90.08H-91.36z"/>
<path id="path4673" sodipodi:nodetypes="ccccc" inkscape:connector-curvature="0" fill="#09753B" d="M-91.36,466.28V376.2h225.12
v90.08H-91.36z"/>
<path id="path4675" sodipodi:nodetypes="ccccc" inkscape:connector-curvature="0" fill="#09753B" d="M-91.36,569.16v-90.08h225.12
v90.08H-91.36z"/>
<path id="path4679" sodipodi:nodetypes="ccccc" inkscape:connector-curvature="0" fill="#09753B" d="M-91.36,672.04v-90.08h225.12
v90.08H-91.36z"/>
<g id="g4222" transform="translate(-127.22081,216.20249)">
<path id="path4224" inkscape:connector-curvature="0" fill="#E6E7E8" stroke="#E6E7E8" stroke-width="6" stroke-miterlimit="10" d="
M229.861-81.283c0,2.24-1.68,3.92-3.92,3.92H70.901c-2.24,0-3.92-1.68-3.92-3.92v-40.16c0-2.24,1.68-3.92,3.92-3.92h155.04
c2.24,0,3.92,1.68,3.92,3.92L229.861-81.283L229.861-81.283L229.861-81.283z"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 2.8 KiB

275
files/images/status/gps.svg

@ -0,0 +1,275 @@ @@ -0,0 +1,275 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
version="1.1"
x="0px"
y="0px"
width="110px"
height="110px"
viewBox="0 0 110 110"
enable-background="new 0 0 110 110"
xml:space="preserve"
id="svg3852"
inkscape:version="0.91 r13725"
sodipodi:docname="gps.svg"><title
id="title4758">GPS</title><metadata
id="metadata3933"><rdf:RDF><cc:Work
rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" /><dc:title>GPS</dc:title><dc:creator><cc:Agent><dc:title>Gus Grubba</dc:title></cc:Agent></dc:creator><cc:license
rdf:resource="http://creativecommons.org/licenses/by-nc/3.0/" /></cc:Work><cc:License
rdf:about="http://creativecommons.org/licenses/by-nc/3.0/"><cc:permits
rdf:resource="http://creativecommons.org/ns#Reproduction" /><cc:permits
rdf:resource="http://creativecommons.org/ns#Distribution" /><cc:requires
rdf:resource="http://creativecommons.org/ns#Notice" /><cc:requires
rdf:resource="http://creativecommons.org/ns#Attribution" /><cc:prohibits
rdf:resource="http://creativecommons.org/ns#CommercialUse" /><cc:permits
rdf:resource="http://creativecommons.org/ns#DerivativeWorks" /></cc:License></rdf:RDF></metadata><defs
id="defs3931" /><sodipodi:namedview
pagecolor="#808080"
bordercolor="#666666"
borderopacity="1"
objecttolerance="10"
gridtolerance="10"
guidetolerance="10"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:window-width="640"
inkscape:window-height="480"
id="namedview3929"
showgrid="false"
inkscape:zoom="11.136364"
inkscape:cx="55"
inkscape:cy="55"
inkscape:current-layer="svg3852" /><g
id="Layer_2"
display="none" /><g
id="ex_thick"
style="fill:#ffffff;stroke:#ffffff;stroke-opacity:1"
transform="matrix(-1,0,0,-1,111.82126,108.29692)" /><g
id="Layer_2_copy_3"
display="none" /><g
id="ex_thin"
style="fill:#ffffff;stroke:#ffffff;stroke-opacity:1"
transform="matrix(-1,0,0,-1,111.82126,108.29692)" /><g
id="Layer_2_copy"
display="none" /><g
id="em_thick"
style="fill:#ffffff;stroke:#ffffff;stroke-opacity:1"
transform="matrix(-1,0,0,-1,111.82126,108.29692)" /><g
id="Layer_2_copy_4"
display="none"><g
display="inline"
id="g3861"><rect
x="-36.1"
y="-21.3"
fill="none"
stroke="#EB008B"
stroke-width="0.25"
stroke-linecap="round"
stroke-linejoin="round"
stroke-miterlimit="10"
width="56.3"
height="56.3"
id="rect3863" /><circle
fill="none"
stroke="#EB008B"
stroke-width="0.25"
stroke-linecap="round"
stroke-linejoin="round"
stroke-miterlimit="10"
cx="-8"
cy="6.8"
r="28.2"
id="circle3865" /></g><g
display="inline"
id="g3867"><rect
x="28.3"
y="-21.3"
fill="none"
stroke="#EB008B"
stroke-width="0.25"
stroke-linecap="round"
stroke-linejoin="round"
stroke-miterlimit="10"
width="56.3"
height="56.3"
id="rect3869" /><circle
fill="none"
stroke="#EB008B"
stroke-width="0.25"
stroke-linecap="round"
stroke-linejoin="round"
stroke-miterlimit="10"
cx="56.5"
cy="6.8"
r="28.2"
id="circle3871" /></g><g
display="inline"
id="g3873"><rect
x="91.5"
y="-21.3"
fill="none"
stroke="#EB008B"
stroke-width="0.25"
stroke-linecap="round"
stroke-linejoin="round"
stroke-miterlimit="10"
width="56.3"
height="56.3"
id="rect3875" /><circle
fill="none"
stroke="#EB008B"
stroke-width="0.25"
stroke-linecap="round"
stroke-linejoin="round"
stroke-miterlimit="10"
cx="119.7"
cy="6.8"
r="28.2"
id="circle3877" /></g></g><rect
x="-129.87416"
y="-13.196043"
transform="matrix(-0.70710678,-0.70710678,0.70710678,-0.70710678,0,0)"
stroke-miterlimit="10"
width="32.29969"
height="16.099846"
id="rect3882"
style="fill:#ffffff;stroke:#ffffff;stroke-width:1.5;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:10;stroke-opacity:1" /><rect
x="24.979502"
y="-2.9382656"
transform="matrix(0.70710678,0.70710678,-0.70710678,0.70710678,0,0)"
stroke-miterlimit="10"
width="32.29969"
height="16.099846"
id="rect3884"
style="fill:#ffffff;stroke:#ffffff;stroke-width:1.5;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:10;stroke-opacity:1" /><path
stroke-miterlimit="10"
d="m 31.121258,78.396923 c 4.7,4.7 12.4,4.7 17.1,0 l 22.8,-22.9 -17.1,-17.1 -22.8,22.8 c -4.7,4.8 -4.7,12.4 0,17.2 z"
id="path3886"
style="fill:#ffffff;stroke:#ffffff;stroke-width:1.5;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:10;stroke-opacity:1"
inkscape:connector-curvature="0" /><path
stroke-miterlimit="10"
d="m 62.521258,46.996923 c 6.3,6.3 16.5,6.3 22.8,0 l -22.8,-22.8 c -6.3,6.2 -6.3,16.5 0,22.8 z"
id="path3888"
style="fill:#ffffff;stroke:#ffffff;stroke-width:1.5;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:10;stroke-opacity:1"
inkscape:connector-curvature="0" /><path
stroke-miterlimit="10"
d="m 96.084265,44.511467 c 8.249995,-8.25 8.249995,-21.75 0,-30 -8.25,-8.2499943 -21.75,-8.2499943 -30,0"
id="path3890"
style="fill:none;stroke:#ffffff;stroke-width:3.89999986;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
inkscape:connector-curvature="0" /><path
stroke-miterlimit="10"
d="m 86.118561,36.977171 c 3.6,-3.6 3.6,-9.3 0,-12.9 -3.6,-3.6 -9.3,-3.6 -12.9,0"
id="path3892"
style="fill:none;stroke:#ffffff;stroke-width:3.89999986;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
inkscape:connector-curvature="0" /><line
stroke-miterlimit="10"
x1="65.321259"
y1="72.596924"
x2="59.621258"
y2="66.896919"
id="line3894"
style="fill:#ffffff;stroke:#ffffff;stroke-width:4.5;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:10;stroke-opacity:1;stroke-dasharray:none" /><line
stroke-miterlimit="10"
x1="42.521255"
y1="49.796921"
x2="36.821259"
y2="44.096924"
id="line3896"
style="fill:#ffffff;stroke:#ffffff;stroke-width:4.5;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:10;stroke-opacity:1;stroke-dasharray:none" /><g
id="Layer_2_copy_2"
display="none"><g
display="inline"
id="g3905"><rect
x="-36.1"
y="83.3"
fill="none"
stroke="#EB008B"
stroke-width="0.25"
stroke-linecap="round"
stroke-linejoin="round"
stroke-miterlimit="10"
width="56.3"
height="56.3"
id="rect3907" /><circle
fill="none"
stroke="#EB008B"
stroke-width="0.25"
stroke-linecap="round"
stroke-linejoin="round"
stroke-miterlimit="10"
cx="-8"
cy="111.5"
r="28.2"
id="circle3909" /></g><g
display="inline"
id="g3911"><rect
x="28.3"
y="83.3"
fill="none"
stroke="#EB008B"
stroke-width="0.25"
stroke-linecap="round"
stroke-linejoin="round"
stroke-miterlimit="10"
width="56.3"
height="56.3"
id="rect3913" /><circle
fill="none"
stroke="#EB008B"
stroke-width="0.25"
stroke-linecap="round"
stroke-linejoin="round"
stroke-miterlimit="10"
cx="56.5"
cy="111.5"
r="28.2"
id="circle3915" /></g><g
display="inline"
id="g3917"><rect
x="91.5"
y="83.3"
fill="none"
stroke="#EB008B"
stroke-width="0.25"
stroke-linecap="round"
stroke-linejoin="round"
stroke-miterlimit="10"
width="56.3"
height="56.3"
id="rect3919" /><circle
fill="none"
stroke="#EB008B"
stroke-width="0.25"
stroke-linecap="round"
stroke-linejoin="round"
stroke-miterlimit="10"
cx="119.7"
cy="111.5"
r="28.2"
id="circle3921" /></g></g><g
id="hornet"
style="fill:#ffffff;stroke:#ffffff;stroke-opacity:1"
transform="matrix(-1,0,0,-1,111.82126,108.29692)" /><g
id="Layer_2_copy_5"
display="none" /><g
id="hornet_THIN"
style="fill:#ffffff;stroke:#ffffff;stroke-opacity:1"
transform="matrix(-1,0,0,-1,111.82126,108.29692)" /><g
id="Layer_6"
display="none"><polygon
display="inline"
fill="none"
stroke="#224A80"
stroke-width="3"
stroke-linecap="round"
stroke-linejoin="round"
stroke-miterlimit="10"
points=" -14.6,111.2 -19.5,111.2 -19.5,152.2 3.4,152.2 3.4,111.2 -1.5,111.2 -1.5,104.7 -14.6,104.7 "
id="polygon3927" /></g></svg>

After

Width:  |  Height:  |  Size: 9.6 KiB

BIN
files/images/status/message_megaphone.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 346 B

BIN
files/images/status/message_triangle.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 295 B

7
qgroundcontrol.pro

@ -268,6 +268,7 @@ INCLUDEPATH += \ @@ -268,6 +268,7 @@ INCLUDEPATH += \
src/ui/configuration \
src/ui/px4_configuration \
src/ui/main \
src/ui/toolbar \
src/VehicleSetup \
src/AutoPilotPlugins
@ -493,7 +494,8 @@ HEADERS += \ @@ -493,7 +494,8 @@ HEADERS += \
src/comm/LinkConfiguration.h \
src/ui/QGCCommConfiguration.h \
src/ui/QGCUDPLinkConfiguration.h \
src/uas/UASMessageHandler.h
src/uas/UASMessageHandler.h \
src/ui/toolbar/MainToolBar.h
SOURCES += \
src/main.cc \
@ -633,7 +635,8 @@ SOURCES += \ @@ -633,7 +635,8 @@ SOURCES += \
src/comm/LinkConfiguration.cc \
src/ui/QGCCommConfiguration.cc \
src/ui/QGCUDPLinkConfiguration.cc \
src/uas/UASMessageHandler.cc
src/uas/UASMessageHandler.cc \
src/ui/toolbar/MainToolBar.cc
#
# Unit Test specific configuration goes here

13
qgroundcontrol.qrc

@ -54,6 +54,15 @@ @@ -54,6 +54,15 @@
<file>files/images/actions/system-shutdown.svg</file>
<file>files/images/actions/system-log-out.svg</file>
<file>files/images/actions/system-lock-screen.svg</file>
<file>files/images/status/gps.svg</file>
<file>files/images/status/battery_0.svg</file>
<file>files/images/status/battery_20.svg</file>
<file>files/images/status/battery_40.svg</file>
<file>files/images/status/battery_60.svg</file>
<file>files/images/status/battery_80.svg</file>
<file>files/images/status/battery_100.svg</file>
<file>files/images/status/message_megaphone.png</file>
<file>files/images/status/message_triangle.png</file>
<file>files/images/status/weather-storm.svg</file>
<file>files/images/status/weather-snow.svg</file>
<file>files/images/status/weather-showers.svg</file>
@ -235,9 +244,7 @@ @@ -235,9 +244,7 @@
<qresource prefix="/QLoggingCategory">
<file alias="qtlogging.ini">files/QLoggingCategory/qtlogging.ini</file>
</qresource>
<qresource prefix="/qml">
<file alias="test.qml">src/test.qml</file>
<file alias="QmlTest.qml">src/QmlControls/QmlTest.qml</file>
@ -298,8 +305,8 @@ @@ -298,8 +305,8 @@
<file alias="QGroundControl/Controls/FirmwareUpgradeIcon.png">src/VehicleSetup/FirmwareUpgradeIcon.png</file>
<file alias="QGroundControl/Controls/VehicleSummaryIcon.png">src/VehicleSetup/VehicleSummaryIcon.png</file>
<file alias="MainToolBar.qml">src/ui/toolbar/MainToolBar.qml</file>
</qresource>
<qresource prefix="/AutoPilotPlugins/PX4">
<file alias="ParameterFactMetaData.xml">src/AutoPilotPlugins/PX4/ParameterFactMetaData.xml</file>
</qresource>

5
src/QGCQmlWidgetHolder.cpp

@ -52,3 +52,8 @@ void QGCQmlWidgetHolder::setContextPropertyObject(const QString& name, QObject* @@ -52,3 +52,8 @@ void QGCQmlWidgetHolder::setContextPropertyObject(const QString& name, QObject*
{
_ui.qmlWidget->rootContext()->setContextProperty(name, object);
}
QQmlContext* QGCQmlWidgetHolder::getRootContext()
{
return _ui.qmlWidget->rootContext();
}

7
src/QGCQmlWidgetHolder.h

@ -49,10 +49,13 @@ public: @@ -49,10 +49,13 @@ public:
/// Sets the UAS into the widget which in turn will load facts into the context
void setAutoPilot(AutoPilotPlugin* autoPilot);
/// Get Root Context
QQmlContext* getRootContext();
/// Sets the QML into the control. Will display errors message box if error occurs loading source.
/// @return true: source loaded, false: source not loaded, errors occured
/// @return true: source loaded, false: source not loaded, errors occured
bool setSource(const QUrl& qmlUrl);
void setContextPropertyObject(const QString& name, QObject* object);
private:

11
src/QGCQmlWidgetHolder.ui

@ -15,12 +15,21 @@ @@ -15,12 +15,21 @@
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QGCQuickWidget" name="qmlWidget" native="true"/>
<widget class="QGCQuickWidget" name="qmlWidget">
<property name="acceptDrops">
<bool>true</bool>
</property>
</widget>
</item>
</layout>
</widget>
<customwidgets>
<customwidget>
<class>QQuickWidget</class>
<extends>QWidget</extends>
<header>QQuickWidget</header>
</customwidget>
<customwidget>
<class>QGCQuickWidget</class>
<extends>QQuickWidget</extends>
<header>QGCQuickWidget.h</header>

4
src/VehicleSetup/SetupViewTest.cc

@ -65,6 +65,8 @@ void SetupViewTest::_clickThrough_test(void) @@ -65,6 +65,8 @@ void SetupViewTest::_clickThrough_test(void)
// Find the Setup button and click it
// Tool Bar is now a QQuickWidget and cannot be manipulated like below
#if 0
QGCToolBar* toolbar = _mainWindow->findChild<QGCToolBar*>();
Q_ASSERT(toolbar);
@ -80,7 +82,7 @@ void SetupViewTest::_clickThrough_test(void) @@ -80,7 +82,7 @@ void SetupViewTest::_clickThrough_test(void)
Q_ASSERT(setupButton);
QTest::mouseClick(setupButton, Qt::LeftButton);
QTest::qWait(1000);
#endif
// Click through all the setup buttons
// FIXME: NYI

8
src/qgcunittest/MainWindowTest.cc

@ -31,7 +31,8 @@ @@ -31,7 +31,8 @@
#include "MockLink.h"
#include "QGCMessageBox.h"
UT_REGISTER_TEST(MainWindowTest)
// TODO: This needs to be changed to accomodate the new QML based tool bar
// UT_REGISTER_TEST(MainWindowTest)
MainWindowTest::MainWindowTest(void)
{
@ -66,6 +67,8 @@ void MainWindowTest::_connectWindowClose_test(MAV_AUTOPILOT autopilot) @@ -66,6 +67,8 @@ void MainWindowTest::_connectWindowClose_test(MAV_AUTOPILOT autopilot)
linkMgr->connectLink(link);
QTest::qWait(5000); // Give enough time for UI to settle and heartbeats to go through
// Tool Bar is now a QQuickWidget and cannot be manipulated like below
#if 0
// Click through all top level toolbar buttons
QGCToolBar* toolbar = _mainWindow->findChild<QGCToolBar*>();
Q_ASSERT(toolbar);
@ -77,7 +80,8 @@ void MainWindowTest::_connectWindowClose_test(MAV_AUTOPILOT autopilot) @@ -77,7 +80,8 @@ void MainWindowTest::_connectWindowClose_test(MAV_AUTOPILOT autopilot)
QTest::qWait(1000);
}
}
#endif
// On MainWindow close we should get a message box telling the user to disconnect first. Cancel should do nothing.
setExpectedMessageBox(QGCMessageBox::Cancel);
_mainWindow->close();

39
src/uas/UASMessageHandler.cc

@ -43,6 +43,9 @@ IMPLEMENT_QGC_SINGLETON(UASMessageHandler, UASMessageHandler) @@ -43,6 +43,9 @@ IMPLEMENT_QGC_SINGLETON(UASMessageHandler, UASMessageHandler)
UASMessageHandler::UASMessageHandler(QObject *parent)
: QGCSingleton(parent)
, _activeUAS(NULL)
, _errorCount(0)
, _warningCount(0)
, _normalCount(0)
{
connect(UASManager::instance(), SIGNAL(activeUASSet(UASInterface*)), this, SLOT(setActiveUAS(UASInterface*)));
emit textMessageReceived(NULL);
@ -60,6 +63,9 @@ void UASMessageHandler::clearMessages() @@ -60,6 +63,9 @@ void UASMessageHandler::clearMessages()
delete _messages.last();
_messages.pop_back();
}
_errorCount = 0;
_warningCount = 0;
_normalCount = 0;
_mutex.unlock();
}
@ -83,15 +89,16 @@ void UASMessageHandler::setActiveUAS(UASInterface* uas) @@ -83,15 +89,16 @@ void UASMessageHandler::setActiveUAS(UASInterface* uas)
}
}
void UASMessageHandler::handleTextMessage(int uasid, int compId, int severity, QString text)
void UASMessageHandler::handleTextMessage(int, int compId, int severity, QString text)
{
Q_UNUSED(uasid);
// Color the output depending on the message severity. We have 3 distinct cases:
// 1: If we have an ERROR or worse, make it bigger, bolder, and highlight it red.
// 2: If we have a warning or notice, just make it bold and color it orange.
// 3: Otherwise color it the standard color, white.
_mutex.lock();
// So first determine the styling based on the severity.
QString style;
switch (severity)
@ -102,13 +109,16 @@ void UASMessageHandler::handleTextMessage(int uasid, int compId, int severity, Q @@ -102,13 +109,16 @@ void UASMessageHandler::handleTextMessage(int uasid, int compId, int severity, Q
case MAV_SEVERITY_ERROR:
//Use set RGB values from given color from QGC
style = QString("color: rgb(%1, %2, %3); font-weight:bold").arg(QGC::colorRed.red()).arg(QGC::colorRed.green()).arg(QGC::colorRed.blue());
_errorCount++;
break;
case MAV_SEVERITY_NOTICE:
case MAV_SEVERITY_WARNING:
style = QString("color: rgb(%1, %2, %3); font-weight:bold").arg(QGC::colorOrange.red()).arg(QGC::colorOrange.green()).arg(QGC::colorOrange.blue());
_warningCount++;
break;
default:
style = QString("color:white; font-weight:bold");
_normalCount++;
break;
}
@ -149,8 +159,31 @@ void UASMessageHandler::handleTextMessage(int uasid, int compId, int severity, Q @@ -149,8 +159,31 @@ void UASMessageHandler::handleTextMessage(int uasid, int compId, int severity, Q
QString dateString = QDateTime::currentDateTime().toString("hh:mm:ss.zzz");
UASMessage* message = new UASMessage(compId, severity, text);
message->_setFormatedText(QString("<p style=\"color:#CCCCCC\">[%2 - COMP:%3]<font style=\"%1\">%4 %5</font></p>").arg(style).arg(dateString).arg(compId).arg(severityText).arg(text));
_mutex.lock();
_messages.append(message);
_mutex.unlock();
emit textMessageReceived(message);
}
int UASMessageHandler::getErrorCount() {
_mutex.lock();
int c = _errorCount;
_errorCount = 0;
_mutex.unlock();
return c;
}
int UASMessageHandler::getWarningCount() {
_mutex.lock();
int c = _warningCount;
_warningCount = 0;
_mutex.unlock();
return c;
}
int UASMessageHandler::getNormalCount() {
_mutex.lock();
int c = _normalCount;
_normalCount = 0;
_mutex.unlock();
return c;
}

15
src/uas/UASMessageHandler.h

@ -95,6 +95,18 @@ public: @@ -95,6 +95,18 @@ public:
* @brief Clear messages
*/
void clearMessages();
/**
* @brief Get error message count (Resets count once read)
*/
int getErrorCount();
/**
* @brief Get warning message count (Resets count once read)
*/
int getWarningCount();
/**
* @brief Get normal message count (Resets count once read)
*/
int getNormalCount();
public slots:
/**
* @brief Set currently active UAS
@ -120,6 +132,9 @@ private: @@ -120,6 +132,9 @@ private:
UASInterface* _activeUAS;
QVector<UASMessage*> _messages;
QMutex _mutex;
int _errorCount;
int _warningCount;
int _normalCount;
};
#endif // QGCMESSAGEHANDLER_H

606
src/ui/MainWindow.cc

File diff suppressed because it is too large Load Diff

45
src/ui/MainWindow.h

@ -30,6 +30,7 @@ This file is part of the QGROUNDCONTROL project @@ -30,6 +30,7 @@ This file is part of the QGROUNDCONTROL project
#ifndef _MAINWINDOW_H_
#define _MAINWINDOW_H_
#include <QMainWindow>
#include <QStatusBar>
#include <QStackedWidget>
@ -59,6 +60,7 @@ This file is part of the QGROUNDCONTROL project @@ -59,6 +60,7 @@ This file is part of the QGROUNDCONTROL project
#ifdef QGC_GOOGLE_EARTH_ENABLED
#include "QGCGoogleEarthView.h"
#endif
#include "MainToolBar.h"
#include "QGCToolBar.h"
#include "LogCompressor.h"
@ -76,7 +78,6 @@ class QSplashScreen; @@ -76,7 +78,6 @@ class QSplashScreen;
class QGCStatusBar;
class Linecharts;
class QGCDataPlot2D;
class MenuActionHelper;
class QGCUASFileViewMulti;
/**
@ -85,6 +86,7 @@ class QGCUASFileViewMulti; @@ -85,6 +86,7 @@ class QGCUASFileViewMulti;
**/
class MainWindow : public QMainWindow
{
friend class MainToolBar;
Q_OBJECT
public:
@ -107,13 +109,13 @@ public: @@ -107,13 +109,13 @@ public:
/** @brief Get auto link reconnect setting */
bool autoReconnectEnabled() const
{
return autoReconnect;
return _autoReconnect;
}
/** @brief Get low power mode setting */
bool lowPowerModeEnabled() const
{
return lowPowerMode;
return _lowPowerMode;
}
QList<QAction*> listLinkMenuActions();
@ -130,7 +132,6 @@ public: @@ -130,7 +132,6 @@ public:
public slots:
/** @brief Show the application settings */
void showSettings();
bool configLink(LinkInterface *link);
/** @brief Simulate a link */
void simulateLink(bool simulate);
/** @brief Set the currently controlled UAS */
@ -177,7 +178,7 @@ public slots: @@ -177,7 +178,7 @@ public slots:
void enableAutoReconnect(bool enabled);
/** @brief Save power by reducing update rates */
void enableLowPowerMode(bool enabled) { lowPowerMode = enabled; }
void enableLowPowerMode(bool enabled) { _lowPowerMode = enabled; }
void closeEvent(QCloseEvent* event);
@ -242,7 +243,6 @@ protected: @@ -242,7 +243,6 @@ protected:
LinkInterface* udpLink;
QSettings settings;
QActionGroup* centerStackActionGroup;
// Center widgets
QPointer<Linecharts> linechartWidget;
@ -254,6 +254,7 @@ protected: @@ -254,6 +254,7 @@ protected:
#endif
QPointer<QGCFirmwareUpdate> firmwareUpdateWidget;
QPointer<MainToolBar> _mainToolBar;
QPointer<QGCToolBar> toolBar;
QPointer<QDockWidget> mavlinkInspectorWidget;
@ -288,11 +289,7 @@ protected: @@ -288,11 +289,7 @@ protected:
LogCompressor* comp;
QString screenFileName;
QTimer* videoTimer;
bool autoReconnect;
MAVLinkSimulationLink* simulationLink;
bool lowPowerMode; ///< If enabled, QGC reduces the update rates of all widgets
QGCFlightGearLink* fgLink;
QTimer windowNameUpdateTimer;
@ -320,9 +317,6 @@ private: @@ -320,9 +317,6 @@ private:
QPointer<QWidget> _googleEarthView;
QPointer<QWidget> _local3DView;
VIEW_SECTIONS _currentView; ///< Currently displayed view
QWidget* _currentViewWidget; ///< Currently displayed view widget
// Dock widget names
static const char* _uasControlDockWidgetName;
static const char* _uasListDockWidgetName;
@ -365,20 +359,23 @@ private: @@ -365,20 +359,23 @@ private:
void _showDockWidget(const QString &name, bool show);
void _showHILConfigurationWidgets(void);
QList<QGCToolWidget*> _customWidgets;
QVBoxLayout* _centralLayout;
QList<QObject*> commsWidgetList;
MenuActionHelper *menuActionHelper;
Ui::MainWindow ui;
bool _autoReconnect;
bool _lowPowerMode; ///< If enabled, QGC reduces the update rates of all widgets
QActionGroup* _centerStackActionGroup;
MAVLinkSimulationLink* _simulationLink;
QList<QGCToolWidget*> _customWidgets;
QVBoxLayout* _centralLayout;
QList<QObject*> _commsWidgetList;
QWidget* _currentViewWidget; ///< Currently displayed view widget
QSplashScreen* _splashScreen; ///< Splash screen, NULL is splash screen not currently being shown
VIEW_SECTIONS _currentView; ///< Currently displayed view
Ui::MainWindow _ui;
QString _screenFileName;
QString getWindowStateKey();
QString getWindowGeometryKey();
QString _getWindowStateKey();
QString _getWindowGeometryKey();
QSplashScreen* _splashScreen; ///< Splash screen, NULL is splash screen not currently being shown
friend class MenuActionHelper; //For VIEW_SECTIONS
};
#endif /* _MAINWINDOW_H_ */

150
src/ui/QGCLinkConfiguration.cc

@ -58,64 +58,71 @@ QGCLinkConfiguration::~QGCLinkConfiguration() @@ -58,64 +58,71 @@ QGCLinkConfiguration::~QGCLinkConfiguration()
void QGCLinkConfiguration::on_delLinkButton_clicked()
{
QModelIndex index = _ui->linkView->currentIndex();
LinkConfiguration* config = _viewModel->getConfiguration(index.row());
if(config) {
// Ask user if they are sure
QMessageBox::StandardButton button = QGCMessageBox::question(
tr("Delete Link Configuration"),
tr("Are you sure you want to delete %1?\nDeleting a configuration will also disconnect it if connected.").arg(config->name()),
QMessageBox::Yes | QMessageBox::Cancel,
QMessageBox::Cancel);
if (button == QMessageBox::Yes) {
// Get link attached to this configuration (if any)
LinkInterface* iface = config->getLink();
if(iface) {
// Disconnect it (if connected)
LinkManager::instance()->disconnectLink(iface);
if(index.row() >= 0) {
LinkConfiguration* config = _viewModel->getConfiguration(index.row());
if(config) {
// Ask user if they are sure
QMessageBox::StandardButton button = QGCMessageBox::question(
tr("Delete Link Configuration"),
tr("Are you sure you want to delete %1?\nDeleting a configuration will also disconnect it if connected.").arg(config->name()),
QMessageBox::Yes | QMessageBox::Cancel,
QMessageBox::Cancel);
if (button == QMessageBox::Yes) {
// Get link attached to this configuration (if any)
LinkInterface* iface = config->getLink();
if(iface) {
// Disconnect it (if connected)
LinkManager::instance()->disconnectLink(iface);
}
_viewModel->beginChange();
// Remove configuration
LinkManager::instance()->removeLinkConfiguration(config);
// Save list
LinkManager::instance()->saveLinkConfigurationList();
_viewModel->endChange();
}
_viewModel->beginChange();
// Remove configuration
LinkManager::instance()->removeLinkConfiguration(config);
// Save list
LinkManager::instance()->saveLinkConfigurationList();
_viewModel->endChange();
}
}
_updateButtons();
}
void QGCLinkConfiguration::on_linkView_clicked(const QModelIndex &index)
void QGCLinkConfiguration::on_linkView_clicked(const QModelIndex&)
{
LinkConfiguration* config = _viewModel->getConfiguration(index.row());
bool enabled = (config && !config->getLink());
_ui->connectLinkButton->setEnabled(enabled);
_ui->delLinkButton->setEnabled(config != NULL);
_ui->editLinkButton->setEnabled(config != NULL);
_updateButtons();
}
void QGCLinkConfiguration::on_connectLinkButton_clicked()
{
QModelIndex index = _ui->linkView->currentIndex();
LinkConfiguration* config = _viewModel->getConfiguration(index.row());
if(config) {
// Only connect if not already connected
if(!config->getLink()) {
LinkInterface* link = LinkManager::instance()->createLink(config);
if(index.row() >= 0) {
LinkConfiguration* config = _viewModel->getConfiguration(index.row());
if(config) {
LinkInterface* link = config->getLink();
if(link) {
// Connect it
LinkManager::instance()->connectLink(link);
// Now go hunting for the parent so we can shut this down
QWidget* pQw = parentWidget();
while(pQw) {
SettingsDialog* pDlg = dynamic_cast<SettingsDialog*>(pQw);
if(pDlg) {
pDlg->accept();
break;
// Disconnect Link
if (link->isConnected()) {
LinkManager::instance()->disconnectLink(link);
}
} else {
LinkInterface* link = LinkManager::instance()->createLink(config);
if(link) {
// Connect it
LinkManager::instance()->connectLink(link);
// Now go hunting for the parent so we can shut this down
QWidget* pQw = parentWidget();
while(pQw) {
SettingsDialog* pDlg = dynamic_cast<SettingsDialog*>(pQw);
if(pDlg) {
pDlg->accept();
break;
}
pQw = pQw->parentWidget();
}
pQw = pQw->parentWidget();
}
}
}
}
_updateButtons();
}
void QGCLinkConfiguration::on_editLinkButton_clicked()
@ -170,6 +177,7 @@ void QGCLinkConfiguration::on_addLinkButton_clicked() @@ -170,6 +177,7 @@ void QGCLinkConfiguration::on_addLinkButton_clicked()
_viewModel->endChange();
}
}
_updateButtons();
}
void QGCLinkConfiguration::on_linkView_doubleClicked(const QModelIndex &index)
@ -179,27 +187,51 @@ void QGCLinkConfiguration::on_linkView_doubleClicked(const QModelIndex &index) @@ -179,27 +187,51 @@ void QGCLinkConfiguration::on_linkView_doubleClicked(const QModelIndex &index)
void QGCLinkConfiguration::_editLink(int row)
{
LinkConfiguration* config = _viewModel->getConfiguration(row);
if(config) {
LinkConfiguration* tmpConfig = LinkConfiguration::duplicateSettings(config);
QGCCommConfiguration* commDialog = new QGCCommConfiguration(this, tmpConfig);
if(commDialog->exec() == QDialog::Accepted) {
// Save changes (if any)
if(commDialog->getConfig()) {
_fixUnnamed(tmpConfig);
_viewModel->beginChange();
config->copyFrom(tmpConfig);
// Save it
LinkManager::instance()->saveLinkConfigurationList();
_viewModel->endChange();
// Tell link about changes (if any)
config->updateSettings();
if(row >= 0) {
LinkConfiguration* config = _viewModel->getConfiguration(row);
if(config) {
LinkConfiguration* tmpConfig = LinkConfiguration::duplicateSettings(config);
QGCCommConfiguration* commDialog = new QGCCommConfiguration(this, tmpConfig);
if(commDialog->exec() == QDialog::Accepted) {
// Save changes (if any)
if(commDialog->getConfig()) {
_fixUnnamed(tmpConfig);
_viewModel->beginChange();
config->copyFrom(tmpConfig);
// Save it
LinkManager::instance()->saveLinkConfigurationList();
_viewModel->endChange();
// Tell link about changes (if any)
config->updateSettings();
}
}
// Discard temporary duplicate
if(commDialog->getConfig())
delete commDialog->getConfig();
}
// Discard temporary duplicate
if(commDialog->getConfig())
delete commDialog->getConfig();
}
_updateButtons();
}
void QGCLinkConfiguration::_updateButtons()
{
LinkConfiguration* config = NULL;
QModelIndex index = _ui->linkView->currentIndex();
bool enabled = (index.row() >= 0);
if(enabled) {
config = _viewModel->getConfiguration(index.row());
if(config) {
LinkInterface* link = config->getLink();
if(link) {
_ui->connectLinkButton->setText("Disconnect");
} else {
_ui->connectLinkButton->setText("Connect");
}
}
}
_ui->connectLinkButton->setEnabled(enabled);
_ui->delLinkButton->setEnabled(config != NULL);
_ui->editLinkButton->setEnabled(config != NULL);
}
LinkViewModel::LinkViewModel(QObject *parent) : QAbstractListModel(parent)

1
src/ui/QGCLinkConfiguration.h

@ -60,6 +60,7 @@ private slots: @@ -60,6 +60,7 @@ private slots:
private:
void _editLink(int row);
void _fixUnnamed(LinkConfiguration* config);
void _updateButtons();
Ui::QGCLinkConfiguration* _ui;
LinkViewModel* _viewModel;

2
src/ui/QGCToolBar.cc

@ -743,6 +743,7 @@ void QGCToolBar::_updateConfigurations() @@ -743,6 +743,7 @@ void QGCToolBar::_updateConfigurations()
*/
void QGCToolBar::enterMessageLabel()
{
/*
// If not already there and messages are actually present
if(!_rollDownMessages && UASMessageHandler::instance()->messages().count())
{
@ -753,6 +754,7 @@ void QGCToolBar::enterMessageLabel() @@ -753,6 +754,7 @@ void QGCToolBar::enterMessageLabel()
_rollDownMessages->setMinimumSize(360,200);
_rollDownMessages->show();
}
*/
}
/**

579
src/ui/toolbar/MainToolBar.cc

@ -0,0 +1,579 @@ @@ -0,0 +1,579 @@
/*=====================================================================
QGroundControl Open Source Ground Control Station
(c) 2009, 2015 QGROUNDCONTROL PROJECT <http://www.qgroundcontrol.org>
This file is part of the QGROUNDCONTROL project
QGROUNDCONTROL is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
QGROUNDCONTROL is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with QGROUNDCONTROL. If not, see <http://www.gnu.org/licenses/>.
======================================================================*/
/**
* @file
* @brief QGC Main Tool Bar
* @author Gus Grubba <mavlink@grubba.com>
*/
#include <QQmlContext>
#include <QQmlEngine>
#include "MainWindow.h"
#include "MainToolBar.h"
#include "UASMessageHandler.h"
#include "UASMessageView.h"
MainToolBar::MainToolBar()
: _mav(NULL)
, _toolBar(NULL)
, _currentView(ViewNone)
, _batteryVoltage(0.0)
, _batteryPercent(0.0)
, _linkSelected(false)
, _connectionCount(0)
, _systemArmed(false)
, _currentHeartbeatTimeout(0)
, _waypointDistance(0.0)
, _currentWaypoint(0)
, _currentMessageCount(0)
, _currentErrorCount(0)
, _currentWarningCount(0)
, _currentNormalCount(0)
, _currentMessageType(MessageNone)
, _satelliteCount(-1)
, _dotsPerInch(72.0)
, _rollDownMessages(0)
{
setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::MinimumExpanding);
setObjectName("MainToolBar");
setMinimumHeight(40);
setMaximumHeight(40);
setMinimumWidth(MainWindow::instance()->minimumWidth());
// Get rid of layout default margins
QLayout* pl = layout();
if(pl) {
pl->setContentsMargins(0,0,0,0);
}
// Get screen DPI to manage font sizes on different platforms
QScreen *srn = QGuiApplication::screens().at(0); // TODO: Find current monitor as opposed to picking first one
_dotsPerInch = (qreal)srn->logicalDotsPerInch(); // Font point sizes are based on Mac 72dpi
setContextPropertyObject("mainToolBar", this);
setSource(QUrl::fromUserInput("qrc:/qml/MainToolBar.qml"));
setVisible(true);
// Configure the toolbar for the current default UAS (which should be none as we just booted)
_setActiveUAS(UASManager::instance()->getActiveUAS());
emit configListChanged();
emit heartbeatTimeoutChanged(_currentHeartbeatTimeout);
emit connectionCountChanged(_connectionCount);
// Link signals
connect(UASManager::instance(), &UASManager::activeUASSet, this, &MainToolBar::_setActiveUAS);
connect(LinkManager::instance(), &LinkManager::linkConfigurationChanged, this, &MainToolBar::_updateConfigurations);
connect(LinkManager::instance(), &LinkManager::linkConnected, this, &MainToolBar::_linkConnected);
connect(LinkManager::instance(), &LinkManager::linkDisconnected, this, &MainToolBar::_linkDisconnected);
}
MainToolBar::~MainToolBar()
{
}
void MainToolBar::onSetupView()
{
setCurrentView(ViewSetup);
MainWindow::instance()->loadSetupView();
}
void MainToolBar::onPlanView()
{
setCurrentView(ViewPlan);
MainWindow::instance()->loadOperatorView();
}
void MainToolBar::onFlyView()
{
setCurrentView(ViewFly);
MainWindow::instance()->loadPilotView();
}
void MainToolBar::onAnalyzeView()
{
setCurrentView(ViewAnalyze);
MainWindow::instance()->loadEngineerView();
}
void MainToolBar::onConnect(QString conf)
{
// If no connection, the role is "Connect"
if(_connectionCount == 0) {
// Connect Link
if(_currentConfig.isEmpty()) {
MainWindow::instance()->manageLinks();
} else {
// We don't want the combo box updating under our feet
LinkManager::instance()->suspendConfigurationUpdates(true);
// Create a link
LinkInterface* link = LinkManager::instance()->createLink(_currentConfig);
if(link) {
// Connect it
LinkManager::instance()->connectLink(link);
// Save last used connection
MainWindow::instance()->saveLastUsedConnection(_currentConfig);
}
LinkManager::instance()->suspendConfigurationUpdates(false);
}
} else {
if(conf.isEmpty()) {
// Disconnect Only Connected Link
int connectedCount = 0;
LinkInterface* connectedLink = NULL;
QList<LinkInterface*> links = LinkManager::instance()->getLinks();
foreach(LinkInterface* link, links) {
if (link->isConnected()) {
connectedCount++;
connectedLink = link;
}
}
Q_ASSERT(connectedCount == 1);
Q_ASSERT(_connectionCount == 1);
Q_ASSERT(connectedLink);
LinkManager::instance()->disconnectLink(connectedLink);
} else {
// Disconnect Named Connected Link
QList<LinkInterface*> links = LinkManager::instance()->getLinks();
foreach(LinkInterface* link, links) {
if (link->isConnected()) {
if(link->getLinkConfiguration() && link->getLinkConfiguration()->name() == conf) {
LinkManager::instance()->disconnectLink(link);
}
}
}
}
}
}
void MainToolBar::onLinkConfigurationChanged(const QString& config)
{
// User selected a link configuration from the combobox
if(_currentConfig != config) {
_currentConfig = config;
_linkSelected = true;
}
}
void MainToolBar::onEnterMessageArea(int x, int y)
{
// If not already there and messages are actually present
if(!_rollDownMessages && UASMessageHandler::instance()->messages().count())
{
// Reset Counts
int count = _currentMessageCount;
MessageType_t type = _currentMessageType;
_currentErrorCount = 0;
_currentWarningCount = 0;
_currentNormalCount = 0;
_currentMessageCount = 0;
_currentMessageType = MessageNone;
if(count != _currentMessageCount) {
emit messageCountChanged(0);
}
if(type != _currentMessageType) {
emit messageTypeChanged(MessageNone);
}
// Show messages
int dialogWidth = 400;
x = x - (dialogWidth >> 1);
if(x < 0) x = 0;
y = height() / 3;
// Put dialog on top of the message alert icon
QPoint p = mapToGlobal(QPoint(x,y));
_rollDownMessages = new UASMessageViewRollDown(MainWindow::instance());
_rollDownMessages->setAttribute(Qt::WA_DeleteOnClose);
_rollDownMessages->move(mapFromGlobal(p));
_rollDownMessages->setMinimumSize(dialogWidth,200);
connect(_rollDownMessages, &UASMessageViewRollDown::closeWindow, this, &MainToolBar::_leaveMessageView);
_rollDownMessages->show();
}
}
QString MainToolBar::getMavIconColor()
{
// TODO: Not using because not only the colors are ghastly, it doesn't respect dark/light palette
if(_mav)
return _mav->getColor().name();
else
return QString("black");
}
void MainToolBar::_leaveMessageView()
{
// Mouse has left the message window area (and it has closed itself)
_rollDownMessages = NULL;
}
void MainToolBar::setCurrentView(int currentView)
{
ViewType_t view = ViewNone;
switch((MainWindow::VIEW_SECTIONS)currentView) {
case MainWindow::VIEW_ENGINEER:
view = ViewAnalyze;
break;
case MainWindow::VIEW_MISSION:
view = ViewPlan;
break;
case MainWindow::VIEW_FLIGHT:
view = ViewFly;
break;
case MainWindow::VIEW_SETUP:
view = ViewSetup;
break;
default:
view = ViewNone;
break;
}
if(view != _currentView) {
_currentView = view;
emit currentViewChanged();
}
}
void MainToolBar::_setActiveUAS(UASInterface* active)
{
// Do nothing if system is the same
if (_mav == active) {
return;
}
// If switching the UAS, disconnect the existing one.
if (_mav)
{
disconnect(UASMessageHandler::instance(), &UASMessageHandler::textMessageReceived, this, &MainToolBar::_handleTextMessage);
disconnect(_mav, &UASInterface::heartbeatTimeout, this, &MainToolBar::_heartbeatTimeout);
disconnect(_mav, &UASInterface::batteryChanged, this, &MainToolBar::_updateBatteryRemaining);
disconnect(_mav, &UASInterface::modeChanged, this, &MainToolBar::_updateMode);
disconnect(_mav, &UASInterface::nameChanged, this, &MainToolBar::_updateName);
disconnect(_mav, &UASInterface::systemTypeSet, this, &MainToolBar::_setSystemType);
disconnect(_mav, SIGNAL(statusChanged(UASInterface*,QString,QString)), this, SLOT(_updateState(UASInterface*,QString,QString)));
disconnect(_mav, SIGNAL(armingChanged(bool)), this, SLOT(_updateArmingState(bool)));
if (_mav->getWaypointManager())
{
disconnect(_mav->getWaypointManager(), &UASWaypointManager::currentWaypointChanged, this, &MainToolBar::_updateCurrentWaypoint);
disconnect(_mav->getWaypointManager(), &UASWaypointManager::waypointDistanceChanged, this, &MainToolBar::_updateWaypointDistance);
}
UAS* pUas = dynamic_cast<UAS*>(_mav);
if(pUas) {
disconnect(pUas, &UAS::satelliteCountChanged, this, &MainToolBar::_setSatelliteCount);
}
}
// Connect new system
_mav = active;
if (_mav)
{
_setSystemType(_mav, _mav->getSystemType());
_updateArmingState(_mav->isArmed());
connect(UASMessageHandler::instance(), &UASMessageHandler::textMessageReceived, this, &MainToolBar::_handleTextMessage);
connect(_mav, &UASInterface::heartbeatTimeout, this, &MainToolBar::_heartbeatTimeout);
connect(_mav, &UASInterface::batteryChanged, this, &MainToolBar::_updateBatteryRemaining);
connect(_mav, &UASInterface::modeChanged, this, &MainToolBar::_updateMode);
connect(_mav, &UASInterface::nameChanged, this, &MainToolBar::_updateName);
connect(_mav, &UASInterface::systemTypeSet, this, &MainToolBar::_setSystemType);
connect(_mav, SIGNAL(statusChanged(UASInterface*,QString,QString)), this, SLOT(_updateState(UASInterface*, QString,QString)));
connect(_mav, SIGNAL(armingChanged(bool)), this, SLOT(_updateArmingState(bool)));
if (_mav->getWaypointManager())
{
connect(_mav->getWaypointManager(), &UASWaypointManager::currentWaypointChanged, this, &MainToolBar::_updateCurrentWaypoint);
connect(_mav->getWaypointManager(), &UASWaypointManager::waypointDistanceChanged, this, &MainToolBar::_updateWaypointDistance);
}
UAS* pUas = dynamic_cast<UAS*>(_mav);
if(pUas) {
_setSatelliteCount(pUas->getSatelliteCount(), QString(""));
connect(pUas, &UAS::satelliteCountChanged, this, &MainToolBar::_setSatelliteCount);
}
}
// Let toolbar know about it
emit mavPresentChanged(_mav != NULL);
}
void MainToolBar::_updateArmingState(bool armed)
{
if(_systemArmed != armed) {
_systemArmed = armed;
emit systemArmedChanged(armed);
}
}
void MainToolBar::_updateBatteryRemaining(UASInterface*, double voltage, double, double percent, int)
{
if(percent < 0.0) {
percent = 0.0;
}
if(voltage < 0.0) {
voltage = 0.0;
}
if (_batteryVoltage != voltage) {
_batteryVoltage = voltage;
emit batteryVoltageChanged(voltage);
}
if (_batteryPercent != percent) {
_batteryPercent = percent;
emit batteryPercentChanged(voltage);
}
}
void MainToolBar::_updateConfigurations()
{
bool resetSelected = false;
QString selected = _currentConfig;
QStringList tmpList;
QList<LinkConfiguration*> configs = LinkManager::instance()->getLinkConfigurationList();
foreach(LinkConfiguration* conf, configs) {
if(conf) {
tmpList << conf->name();
if((!_linkSelected && conf->isPreferred()) || selected.isEmpty()) {
selected = conf->name();
resetSelected = true;
}
}
}
// Any changes?
if(tmpList != _linkConfigurations) {
_linkConfigurations = tmpList;
emit configListChanged();
}
// Selection change?
if((selected != _currentConfig && _linkConfigurations.contains(selected)) ||
(selected.isEmpty())) {
_currentConfig = selected;
emit currentConfigChanged(_currentConfig);
}
if(resetSelected) {
_linkSelected = false;
}
}
void MainToolBar::_linkConnected(LinkInterface*)
{
_updateConnection();
}
void MainToolBar::_linkDisconnected(LinkInterface* link)
{
_updateConnection(link);
}
void MainToolBar::_updateConnection(LinkInterface *disconnectedLink)
{
QStringList connList;
int oldCount = _connectionCount;
// If there are multiple connected links add/update the connect button menu
_connectionCount = 0;
QList<LinkInterface*> links = LinkManager::instance()->getLinks();
foreach(LinkInterface* link, links) {
if (disconnectedLink != link && link->isConnected()) {
_connectionCount++;
if(link->getLinkConfiguration()) {
connList << link->getLinkConfiguration()->name();
}
}
}
if(oldCount != _connectionCount) {
emit connectionCountChanged(_connectionCount);
}
if(connList != _connectedList) {
_connectedList = connList;
emit connectedListChanged(_connectedList);
}
}
void MainToolBar::_updateState(UASInterface*, QString name, QString)
{
if (_currentState != name) {
_currentState = name;
emit currentStateChanged(_currentState);
}
}
void MainToolBar::_updateMode(int, QString name, QString)
{
if (name.size()) {
QString shortMode = name;
shortMode = shortMode.replace("D|", "");
shortMode = shortMode.replace("A|", "");
if (_currentMode != shortMode) {
_currentMode = shortMode;
emit currentModeChanged();
}
}
}
void MainToolBar::_updateName(const QString& name)
{
if (_systemName != name) {
_systemName = name;
// TODO: emit signal and use it
}
}
/**
* The current system type is represented through the system icon.
*
* @param uas Source system, has to be the same as this->uas
* @param systemType type ID, following the MAVLink system type conventions
* @see http://pixhawk.ethz.ch/software/mavlink
*/
void MainToolBar::_setSystemType(UASInterface*, unsigned int systemType)
{
_systemPixmap = "qrc:/files/images/mavs/";
switch (systemType) {
case MAV_TYPE_GENERIC:
_systemPixmap += "generic.svg";
break;
case MAV_TYPE_FIXED_WING:
_systemPixmap += "fixed-wing.svg";
break;
case MAV_TYPE_QUADROTOR:
_systemPixmap += "quadrotor.svg";
break;
case MAV_TYPE_COAXIAL:
_systemPixmap += "coaxial.svg";
break;
case MAV_TYPE_HELICOPTER:
_systemPixmap += "helicopter.svg";
break;
case MAV_TYPE_ANTENNA_TRACKER:
_systemPixmap += "antenna-tracker.svg";
break;
case MAV_TYPE_GCS:
_systemPixmap += "groundstation.svg";
break;
case MAV_TYPE_AIRSHIP:
_systemPixmap += "airship.svg";
break;
case MAV_TYPE_FREE_BALLOON:
_systemPixmap += "free-balloon.svg";
break;
case MAV_TYPE_ROCKET:
_systemPixmap += "rocket.svg";
break;
case MAV_TYPE_GROUND_ROVER:
_systemPixmap += "ground-rover.svg";
break;
case MAV_TYPE_SURFACE_BOAT:
_systemPixmap += "surface-boat.svg";
break;
case MAV_TYPE_SUBMARINE:
_systemPixmap += "submarine.svg";
break;
case MAV_TYPE_HEXAROTOR:
_systemPixmap += "hexarotor.svg";
break;
case MAV_TYPE_OCTOROTOR:
_systemPixmap += "octorotor.svg";
break;
case MAV_TYPE_TRICOPTER:
_systemPixmap += "tricopter.svg";
break;
case MAV_TYPE_FLAPPING_WING:
_systemPixmap += "flapping-wing.svg";
break;
case MAV_TYPE_KITE:
_systemPixmap += "kite.svg";
break;
default:
_systemPixmap += "unknown.svg";
break;
}
emit systemPixmapChanged(_systemPixmap);
}
void MainToolBar::_heartbeatTimeout(bool timeout, unsigned int ms)
{
unsigned int elapsed = ms;
if (!timeout)
{
elapsed = 0;
}
if(elapsed != _currentHeartbeatTimeout) {
_currentHeartbeatTimeout = elapsed;
emit heartbeatTimeoutChanged(_currentHeartbeatTimeout);
}
}
void MainToolBar::_handleTextMessage(UASMessage*)
{
UASMessageHandler* pMh = UASMessageHandler::instance();
Q_ASSERT(pMh);
MessageType_t type = _currentMessageType;
int errorCount = _currentErrorCount;
int warnCount = _currentWarningCount;
int normalCount = _currentNormalCount;
//-- Add current message counts
errorCount += pMh->getErrorCount();
warnCount += pMh->getWarningCount();
normalCount += pMh->getNormalCount();
//-- See if we have a higher level
if(errorCount != _currentErrorCount) {
_currentErrorCount = errorCount;
type = MessageError;
}
if(warnCount != _currentWarningCount) {
_currentWarningCount = warnCount;
if(_currentMessageType != MessageError) {
type = MessageWarning;
}
}
if(normalCount != _currentNormalCount) {
_currentNormalCount = normalCount;
if(_currentMessageType != MessageError && _currentMessageType != MessageWarning) {
type = MessageNormal;
}
}
int count = _currentErrorCount + _currentWarningCount + _currentNormalCount;
if(count != _currentMessageCount) {
_currentMessageCount = count;
// Display current total message count
emit messageCountChanged(count);
}
if(type != _currentMessageType) {
_currentMessageType = type;
// Update message level
emit messageTypeChanged(type);
}
}
void MainToolBar::_updateWaypointDistance(double distance)
{
if (_waypointDistance != distance) {
_waypointDistance = distance;
// TODO: emit signal and use it
}
}
void MainToolBar::_updateCurrentWaypoint(quint16 id)
{
if (_currentWaypoint != id) {
_currentWaypoint = id;
// TODO: emit signal and use it
}
}
void MainToolBar::_setSatelliteCount(double val, QString)
{
if(val < 0.0) val = 0.0;
if(val > 99.0) val = 99.0;
if(_satelliteCount != (int)val) {
_satelliteCount = (int)val;
emit satelliteCountChanged(_satelliteCount);
}
}

180
src/ui/toolbar/MainToolBar.h

@ -0,0 +1,180 @@ @@ -0,0 +1,180 @@
/*=====================================================================
QGroundControl Open Source Ground Control Station
(c) 2009, 2015 QGROUNDCONTROL PROJECT <http://www.qgroundcontrol.org>
This file is part of the QGROUNDCONTROL project
QGROUNDCONTROL is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
QGROUNDCONTROL is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with QGROUNDCONTROL. If not, see <http://www.gnu.org/licenses/>.
======================================================================*/
/**
* @file
* @brief QGC Main Tool Bar
* @author Gus Grubba <mavlink@grubba.com>
*/
#ifndef MAINTOOLBAR_H
#define MAINTOOLBAR_H
#include "QGCQmlWidgetHolder.h"
class UASInterface;
class UASMessage;
class UASMessageViewRollDown;
class MainToolBar : public QGCQmlWidgetHolder
{
Q_OBJECT
Q_ENUMS(ViewType_t)
Q_ENUMS(MessageType_t)
public:
MainToolBar();
~MainToolBar();
typedef enum {
ViewNone = -1,
ViewAnalyze, // MainWindow::VIEW_ENGINEER
ViewPlan , // MainWindow::VIEW_MISSION
ViewFly , // MainWindow::VIEW_FLIGHT
ViewSetup , // MainWindow::VIEW_SETUP
} ViewType_t;
typedef enum {
MessageNone,
MessageNormal,
MessageWarning,
MessageError
} MessageType_t;
Q_INVOKABLE void onSetupView();
Q_INVOKABLE void onPlanView();
Q_INVOKABLE void onFlyView();
Q_INVOKABLE void onAnalyzeView();
Q_INVOKABLE void onConnect(QString conf);
Q_INVOKABLE void onLinkConfigurationChanged(const QString& config);
Q_INVOKABLE void onEnterMessageArea(int x, int y);
Q_INVOKABLE QString getMavIconColor();
Q_PROPERTY(int connectionCount READ connectionCount NOTIFY connectionCountChanged)
Q_PROPERTY(double batteryVoltage READ batteryVoltage NOTIFY batteryVoltageChanged)
Q_PROPERTY(double batteryPercent READ batteryPercent NOTIFY batteryPercentChanged)
Q_PROPERTY(ViewType_t currentView READ currentView NOTIFY currentViewChanged)
Q_PROPERTY(QStringList configList READ configList NOTIFY configListChanged)
Q_PROPERTY(bool systemArmed READ systemArmed NOTIFY systemArmedChanged)
Q_PROPERTY(unsigned int heartbeatTimeout READ heartbeatTimeout NOTIFY heartbeatTimeoutChanged)
Q_PROPERTY(QString currentMode READ currentMode NOTIFY currentModeChanged)
Q_PROPERTY(MessageType_t messageType READ messageType NOTIFY messageTypeChanged)
Q_PROPERTY(int messageCount READ messageCount NOTIFY messageCountChanged)
Q_PROPERTY(QString currentConfig READ currentConfig NOTIFY currentConfigChanged)
Q_PROPERTY(QString systemPixmap READ systemPixmap NOTIFY systemPixmapChanged)
Q_PROPERTY(int satelliteCount READ satelliteCount NOTIFY satelliteCountChanged)
Q_PROPERTY(QStringList connectedList READ connectedList NOTIFY connectedListChanged)
Q_PROPERTY(bool mavPresent READ mavPresent NOTIFY mavPresentChanged)
Q_PROPERTY(QString currentState READ currentState NOTIFY currentStateChanged)
Q_PROPERTY(double dotsPerInch READ dotsPerInch NOTIFY dotsPerInchChanged)
int connectionCount () { return _connectionCount; }
double batteryVoltage () { return _batteryVoltage; }
double batteryPercent () { return _batteryPercent; }
ViewType_t currentView () { return _currentView; }
QStringList configList () { return _linkConfigurations; }
bool systemArmed () { return _systemArmed; }
unsigned int heartbeatTimeout () { return _currentHeartbeatTimeout; }
QString currentMode () { return _currentMode; }
MessageType_t messageType () { return _currentMessageType; }
int messageCount () { return _currentMessageCount; }
QString currentConfig () { return _currentConfig; }
QString systemPixmap () { return _systemPixmap; }
int satelliteCount () { return _satelliteCount; }
QStringList connectedList () { return _connectedList; }
bool mavPresent () { return _mav != NULL; }
QString currentState () { return _currentState; }
double dotsPerInch () { return _dotsPerInch; }
void setCurrentView (int currentView);
signals:
void connectionCountChanged (int count);
void batteryVoltageChanged (double value);
void batteryPercentChanged (double value);
void currentViewChanged ();
void configListChanged ();
void systemArmedChanged (bool systemArmed);
void heartbeatTimeoutChanged (unsigned int hbTimeout);
void currentModeChanged ();
void messageTypeChanged (MessageType_t type);
void messageCountChanged (int count);
void currentConfigChanged (QString config);
void systemPixmapChanged (QPixmap pix);
void satelliteCountChanged (int count);
void connectedListChanged (QStringList connectedList);
void mavPresentChanged (bool present);
void currentStateChanged (QString state);
void dotsPerInchChanged ();
private slots:
void _setActiveUAS (UASInterface* active);
void _updateBatteryRemaining (UASInterface*, double voltage, double, double percent, int);
void _updateArmingState (bool armed);
void _updateConfigurations ();
void _linkConnected (LinkInterface* link);
void _linkDisconnected (LinkInterface* link);
void _updateState (UASInterface* system, QString name, QString description);
void _updateMode (int system, QString name, QString description);
void _updateName (const QString& name);
void _setSystemType (UASInterface* uas, unsigned int systemType);
void _heartbeatTimeout (bool timeout, unsigned int ms);
void _handleTextMessage (UASMessage* message);
void _updateCurrentWaypoint (quint16 id);
void _updateWaypointDistance (double distance);
void _setSatelliteCount (double val, QString name);
void _leaveMessageView ();
private:
void _updateConnection (LinkInterface *disconnectedLink = NULL);
private:
UASInterface* _mav;
QQuickItem* _toolBar;
ViewType_t _currentView;
double _batteryVoltage;
double _batteryPercent;
QStringList _linkConfigurations;
QString _currentConfig;
bool _linkSelected;
int _connectionCount;
bool _systemArmed;
QString _currentState;
QString _currentMode;
QString _systemName;
QString _systemPixmap;
unsigned int _currentHeartbeatTimeout;
double _waypointDistance;
quint16 _currentWaypoint;
int _currentMessageCount;
int _currentErrorCount;
int _currentWarningCount;
int _currentNormalCount;
MessageType_t _currentMessageType;
int _satelliteCount;
QStringList _connectedList;
qreal _dotsPerInch;
UASMessageViewRollDown* _rollDownMessages;
};
#endif // MAINTOOLBAR_H

489
src/ui/toolbar/MainToolBar.qml

@ -0,0 +1,489 @@ @@ -0,0 +1,489 @@
/*=====================================================================
QGroundControl Open Source Ground Control Station
(c) 2009, 2015 QGROUNDCONTROL PROJECT <http://www.qgroundcontrol.org>
This file is part of the QGROUNDCONTROL project
QGROUNDCONTROL is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
QGROUNDCONTROL is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with QGROUNDCONTROL. If not, see <http://www.gnu.org/licenses/>.
======================================================================*/
/**
* @file
* @brief QGC Main Tool Bar
* @author Gus Grubba <mavlink@grubba.com>
*/
import QtQuick 2.3
import QtQuick.Controls 1.2
import QtQuick.Controls.Styles 1.2
import QGroundControl.Controls 1.0
import QGroundControl.FactControls 1.0
import QGroundControl.Palette 1.0
import QGroundControl.MainToolBar 1.0
Rectangle {
property var qgcPal: QGCPalette { id: palette; colorGroupEnabled: true }
property int cellSpacerSize: 4
property int cellHeight: 30
property int cellRadius: 3
property double dpiFactor: (72.0 / mainToolBar.dotsPerInch);
property var colorBlue: "#1a6eaa"
property var colorGreen: "#00d930"
property var colorRed: "#a81a1b"
property var colorOrange: "#a76f26"
property var colorWhite: "#f0f0f0"
id: toolBarHolder
color: qgcPal.windowShade
function getMessageColor() {
if(mainToolBar.messageType === MainToolBar.MessageNone)
return qgcPal.button;
if(mainToolBar.messageType === MainToolBar.MessageNormal)
return colorBlue;
if(mainToolBar.messageType === MainToolBar.MessageWarning)
return colorOrange;
if(mainToolBar.messageType === MainToolBar.MessageError)
return colorRed;
// Cannot be so make make it obnoxious to show error
return "purple";
}
function getMessageIcon() {
if(mainToolBar.messageType === MainToolBar.MessageNormal || mainToolBar.messageType === MainToolBar.MessageNone)
return "qrc:/files/images/status/message_megaphone.png";
else
return "qrc:/files/images/status/message_triangle.png";
}
function getBatteryIcon() {
if(mainToolBar.batteryPercent < 20.0)
return "qrc:/files/images/status/battery_0.svg";
else if(mainToolBar.batteryPercent < 40.0)
return "qrc:/files/images/status/battery_20.svg";
else if(mainToolBar.batteryPercent < 60.0)
return "qrc:/files/images/status/battery_40.svg";
else if(mainToolBar.batteryPercent < 80.0)
return "qrc:/files/images/status/battery_60.svg";
else if(mainToolBar.batteryPercent < 90.0)
return "qrc:/files/images/status/battery_80.svg";
else
return "qrc:/files/images/status/battery_100.svg";
}
function showMavStatus() {
return (mainToolBar.mavPresent && mainToolBar.heartbeatTimeout === 0 && mainToolBar.connectionCount > 0);
}
Row {
id: row1
height: cellHeight
anchors.left: parent.left
spacing: cellSpacerSize
anchors.verticalCenter: parent.verticalCenter
anchors.leftMargin: 10
ExclusiveGroup { id: mainActionGroup }
QGCButton {
id: setupButton
width: 90
height: cellHeight
exclusiveGroup: mainActionGroup
text: qsTr("1. Setup")
anchors.verticalCenter: parent.verticalCenter
checked: (mainToolBar.currentView === MainToolBar.ViewSetup)
onClicked: {
mainToolBar.onSetupView();
}
}
QGCButton {
id: planButton
width: 90
height: cellHeight
exclusiveGroup: mainActionGroup
text: qsTr("2. Plan")
anchors.verticalCenter: parent.verticalCenter
checked: (mainToolBar.currentView === MainToolBar.ViewPlan)
onClicked: {
mainToolBar.onPlanView();
}
}
QGCButton {
id: flyButton
width: 90
height: cellHeight
exclusiveGroup: mainActionGroup
text: qsTr("3. Fly")
anchors.verticalCenter: parent.verticalCenter
checked: (mainToolBar.currentView === MainToolBar.ViewFly)
onClicked: {
mainToolBar.onFlyView();
}
}
QGCButton {
id: analyzeButton
width: 90
height: cellHeight
exclusiveGroup: mainActionGroup
text: qsTr("4. Analyze")
anchors.verticalCenter: parent.verticalCenter
checked: (mainToolBar.currentView === MainToolBar.ViewAnalyze)
onClicked: {
mainToolBar.onAnalyzeView();
}
}
Rectangle {
width: 4
height: cellHeight
color: "#00000000"
border.color: "#00000000"
border.width: 0
}
Rectangle {
id: messages
width: (mainToolBar.messageCount > 99) ? 70 : 60
height: cellHeight
visible: (mainToolBar.connectionCount > 0)
anchors.verticalCenter: parent.verticalCenter
color: getMessageColor()
radius: cellRadius
border.color: "#00000000"
border.width: 0
property bool showTriangle: false
Image {
id: messageIcon
source: getMessageIcon();
height: 16
fillMode: Image.PreserveAspectFit
anchors.verticalCenter: parent.verticalCenter
anchors.left: parent.left
anchors.leftMargin: 10
}
Rectangle {
id: messageTextRect
anchors.verticalCenter: parent.verticalCenter
anchors.right: parent.right
width: messages.width - messageIcon.width
Text {
id: messageText
text: (mainToolBar.messageCount > 0) ? mainToolBar.messageCount : ''
font.pointSize: 14 * dpiFactor
font.weight: Font.DemiBold
anchors.verticalCenter: parent.verticalCenter
anchors.horizontalCenter: parent.horizontalCenter
horizontalAlignment: Text.AlignHCenter
color: colorWhite
}
}
Image {
id: dropDown
source: "QGroundControl/Controls/arrow-down.png"
visible: (messages.showTriangle)
anchors.bottom: parent.bottom
anchors.right: parent.right
anchors.bottomMargin: 3
anchors.rightMargin: 3
}
Timer {
id: mouseOffTimer
interval: 2000;
running: false;
repeat: false
onTriggered: {
messages.showTriangle = false;
}
}
MouseArea {
anchors.fill: parent
hoverEnabled: true
onEntered: {
messages.showTriangle = true;
mouseOffTimer.start();
}
onExited: {
messages.showTriangle = false;
}
onClicked: {
var p = mapToItem(toolBarHolder, mouseX, mouseY);
mainToolBar.onEnterMessageArea(p.x, p.y);
}
}
}
Rectangle {
id: mavIcon
width: cellHeight
height: cellHeight
visible: showMavStatus()
anchors.verticalCenter: parent.verticalCenter
color: colorBlue
radius: cellRadius
border.color: "#00000000"
border.width: 0
Image {
source: mainToolBar.systemPixmap
height: cellHeight * 0.75
fillMode: Image.PreserveAspectFit
anchors.verticalCenter: parent.verticalCenter
anchors.horizontalCenter: parent.horizontalCenter
}
}
Rectangle {
id: satelitte
width: 60
height: cellHeight
visible: showMavStatus()
anchors.verticalCenter: parent.verticalCenter
color: (mainToolBar.satelliteCount < 3) ? colorRed : colorBlue
radius: cellRadius
border.color: "#00000000"
border.width: 0
Image {
source: "qrc:/files/images/status/gps.svg";
height: 24
fillMode: Image.PreserveAspectFit
anchors.verticalCenter: parent.verticalCenter
anchors.left: parent.left
anchors.leftMargin: 10
mipmap: true
smooth: true
}
Text {
id: satelitteText
text: mainToolBar.satelliteCount
font.pointSize: 14 * dpiFactor
font.weight: Font.DemiBold
anchors.verticalCenter: parent.verticalCenter
anchors.right: parent.right
anchors.rightMargin: 10
horizontalAlignment: Text.AlignRight
color: colorWhite
}
}
Rectangle {
id: battery
width: 80
height: cellHeight
visible: showMavStatus()
anchors.verticalCenter: parent.verticalCenter
color: (mainToolBar.batteryPercent > 40.0 || mainToolBar.batteryPercent < 0.01) ? colorBlue : colorRed
radius: cellRadius
border.color: "#00000000"
border.width: 0
Image {
source: getBatteryIcon();
height: 20
fillMode: Image.PreserveAspectFit
anchors.verticalCenter: parent.verticalCenter
anchors.left: parent.left
anchors.leftMargin: 6
mipmap: true
smooth: true
}
Text {
id: batteryText
text: mainToolBar.batteryVoltage.toFixed(2) + ' V';
font.pointSize: 14 * dpiFactor
font.weight: Font.DemiBold
anchors.verticalCenter: parent.verticalCenter
anchors.right: parent.right
anchors.rightMargin: 8
horizontalAlignment: Text.AlignRight
color: colorWhite
}
}
Column {
anchors.verticalCenter: parent.verticalCenter
spacing: cellSpacerSize
visible: showMavStatus()
height: cellHeight * 0.75
width: 80
Rectangle {
id: armedStatus
width: parent.width
height: parent.height / 2
anchors.horizontalCenter: parent.horizontalCenter
color: "#00000000"
border.color: "#00000000"
border.width: 0
Text {
id: armedStatusText
text: (mainToolBar.systemArmed) ? qsTr("ARMED") : qsTr("DISARMED")
font.pointSize: 12 * dpiFactor
font.weight: Font.DemiBold
anchors.horizontalCenter: parent.horizontalCenter
anchors.verticalCenter: parent.verticalCenter
color: (mainToolBar.systemArmed) ? colorRed : colorGreen
}
}
Rectangle {
id: stateStatus
width: parent.width
height: parent.height / 2
anchors.horizontalCenter: parent.horizontalCenter
color: "#00000000"
border.color: "#00000000"
border.width: 0
Text {
id: stateStatusText
text: mainToolBar.currentState
font.pointSize: 12 * dpiFactor
font.weight: Font.DemiBold
anchors.horizontalCenter: parent.horizontalCenter
anchors.verticalCenter: parent.verticalCenter
color: (mainToolBar.currentState === "STANDBY") ? colorGreen : colorRed
}
}
}
Rectangle {
id: modeStatus
width: 90
height: cellHeight
visible: showMavStatus()
color: "#00000000"
border.color: "#00000000"
border.width: 0
Text {
id: modeStatusText
text: mainToolBar.currentMode
font.pointSize: 12 * dpiFactor
font.weight: Font.DemiBold
anchors.horizontalCenter: parent.horizontalCenter
anchors.verticalCenter: parent.verticalCenter
color: qgcPal.text
}
}
Rectangle {
id: connectionStatus
width: 160
height: cellHeight
visible: (mainToolBar.connectionCount > 0 && mainToolBar.mavPresent && mainToolBar.heartbeatTimeout != 0)
anchors.verticalCenter: parent.verticalCenter
color: "#00000000"
border.color: "#00000000"
border.width: 0
Text {
id: connectionStatusText
text: qsTr("CONNECTION LOST")
font.pointSize: 14 * dpiFactor
font.weight: Font.DemiBold
anchors.verticalCenter: parent.verticalCenter
anchors.horizontalCenter: parent.horizontalCenter
color: colorRed
}
}
}
Row {
id: row2
height: cellHeight
spacing: cellSpacerSize
anchors.right: parent.right
anchors.verticalCenter: parent.verticalCenter
anchors.leftMargin: 10
anchors.rightMargin: 10
QGCComboBox {
id: configList
width: 200
height: cellHeight
visible: (mainToolBar.connectionCount === 0 && mainToolBar.configList.length > 0)
anchors.verticalCenter: parent.verticalCenter
model: mainToolBar.configList
onCurrentIndexChanged: {
mainToolBar.onLinkConfigurationChanged(mainToolBar.configList[currentIndex]);
}
Component.onCompleted: {
mainToolBar.currentConfigChanged.connect(configList.onCurrentConfigChanged)
}
function onCurrentConfigChanged(config) {
var index = configList.find(config);
configList.currentIndex = index;
}
}
QGCButton {
id: connectButton
width: 90
height: cellHeight
visible: (mainToolBar.connectionCount === 0 || mainToolBar.connectionCount === 1)
text: (mainToolBar.configList.length > 0) ? (mainToolBar.connectionCount === 0) ? qsTr("Connect") : qsTr("Disconnect") : qsTr("Add Link")
anchors.verticalCenter: parent.verticalCenter
onClicked: {
mainToolBar.onConnect("");
}
}
Menu {
id: disconnectMenu
Component.onCompleted: {
mainToolBar.connectedListChanged.connect(disconnectMenu.onConnectedListChanged)
}
function onConnectedListChanged(conList) {
disconnectMenu.clear();
for(var i = 0; i < conList.length; i++) {
var mItem = disconnectMenu.addItem(conList[i]);
var menuSlot = function() {mainToolBar.onConnect(mItem.text)};
mItem.triggered.connect(menuSlot);
}
}
}
QGCButton {
id: multidisconnectButton
width: 90
height: cellHeight
text: qsTr("Disconnect")
visible: (mainToolBar.connectionCount > 1)
anchors.verticalCenter: parent.verticalCenter
menu: disconnectMenu
}
}
}

10
src/ui/uas/UASMessageView.cc

@ -24,7 +24,7 @@ This file is part of the QGROUNDCONTROL project @@ -24,7 +24,7 @@ This file is part of the QGROUNDCONTROL project
#include <QMenu>
#include <QScrollBar>
#include "QGCToolBar.h"
#include "MainToolBar.h"
#include "UASMessageView.h"
#include "QGCUnconnectedInfoWidget.h"
#include "UASMessageHandler.h"
@ -111,10 +111,9 @@ void UASMessageViewWidget::handleTextMessage(UASMessage *message) @@ -111,10 +111,9 @@ void UASMessageViewWidget::handleTextMessage(UASMessage *message)
UASMessageViewRollDown
-------------------------------------------------------------------------------------*/
UASMessageViewRollDown::UASMessageViewRollDown(QWidget *parent, QGCToolBar *toolBar)
UASMessageViewRollDown::UASMessageViewRollDown(QWidget *parent)
: UASMessageView(parent)
{
_toolBar = toolBar;
setAttribute(Qt::WA_TranslucentBackground);
setStyleSheet("background-color: rgba(0%,0%,0%,80%); border: 2px;");
QPlainTextEdit *msgWidget = ui()->plainTextEdit;
@ -154,9 +153,8 @@ void UASMessageViewRollDown::handleTextMessage(UASMessage *message) @@ -154,9 +153,8 @@ void UASMessageViewRollDown::handleTextMessage(UASMessage *message)
}
}
void UASMessageViewRollDown::leaveEvent(QEvent * event)
void UASMessageViewRollDown::leaveEvent(QEvent*)
{
Q_UNUSED(event);
_toolBar->leaveMessageView();
emit closeWindow();
close();
}

7
src/ui/uas/UASMessageView.h

@ -31,7 +31,6 @@ This file is part of the QGROUNDCONTROL project @@ -31,7 +31,6 @@ This file is part of the QGROUNDCONTROL project
#include "QGCUnconnectedInfoWidget.h"
class UASMessage;
class QGCToolBar;
namespace Ui {
class UASMessageView;
@ -69,14 +68,14 @@ class UASMessageViewRollDown : public UASMessageView @@ -69,14 +68,14 @@ class UASMessageViewRollDown : public UASMessageView
{
Q_OBJECT
public:
explicit UASMessageViewRollDown(QWidget *parent, QGCToolBar* toolBar);
explicit UASMessageViewRollDown(QWidget *parent);
~UASMessageViewRollDown();
signals:
void closeWindow();
public slots:
void handleTextMessage(UASMessage* message);
protected:
void leaveEvent(QEvent* event);
private:
QGCToolBar* _toolBar;
};
#endif // QGCMESSAGEVIEW_H

Loading…
Cancel
Save