Backport recent changes from mainline.
authorUwe Hermann <uwe@hermann-uwe.de>
Tue, 13 Jun 2017 14:49:11 +0000 (16:49 +0200)
committerUwe Hermann <uwe@hermann-uwe.de>
Mon, 29 Oct 2018 10:40:26 +0000 (11:40 +0100)
This includes all changes from

  0adee2d93430b5fb879388e66f3bd44fd11b3b22
  manual: Bump date.

up to

  10906507eb3d32346506a12d4387205f7c7c6e72
  HACKING: Update URL to Linux kernel coding style.

264 files changed:
.gitignore
CMakeLists.txt
HACKING
INSTALL
README
android/loghandler.cpp
contrib/org.sigrok.PulseView.desktop
contrib/pulseview_cross.nsi.in
doc/pulseview.1
icons/help-browser.png [new file with mode: 0644]
icons/media-playback-pause.png [new file with mode: 0644]
icons/media-playback-start.png [new file with mode: 0644]
icons/settings-general.png [new file with mode: 0644]
icons/view-displaymode-last_complete_segment.svg [new file with mode: 0644]
icons/view-displaymode-last_segment.svg [new file with mode: 0644]
icons/view-displaymode-single_segment.svg [new file with mode: 0644]
icons/zoom-original.png [deleted file]
main.cpp
manual/CMakeLists.txt [new file with mode: 0644]
manual/acquisition.txt [new file with mode: 0644]
manual/analysis.txt [new file with mode: 0644]
manual/asciidoctor-stylesheet-factory/LICENSE [new file with mode: 0644]
manual/asciidoctor-stylesheet-factory/stylesheets/readthedocs.css [new file with mode: 0644]
manual/cli.txt [new file with mode: 0644]
manual/decoders.txt [new file with mode: 0644]
manual/images/_callouts.xcf [new file with mode: 0644]
manual/images/device_selector.png [new file with mode: 0644]
manual/images/device_selector_dropdown.png [new file with mode: 0644]
manual/images/device_selector_scan.png [new file with mode: 0644]
manual/images/pv_after_startup.png [new file with mode: 0644]
manual/images/pv_after_startup.xcf [new file with mode: 0644]
manual/images/pv_analysis.png [new file with mode: 0644]
manual/images/pv_analysis.xcf [new file with mode: 0644]
manual/images/pv_conversion_a2l.png [new file with mode: 0644]
manual/images/pv_cursors_markers.png [new file with mode: 0644]
manual/images/pv_cursors_markers.xcf [new file with mode: 0644]
manual/images/pv_decoders_1.png [new file with mode: 0644]
manual/images/pv_decoders_1.xcf [new file with mode: 0644]
manual/images/pv_decoders_2.png [new file with mode: 0644]
manual/images/pv_decoders_3.png [new file with mode: 0644]
manual/images/pv_decoders_3.xcf [new file with mode: 0644]
manual/images/pv_decoders_4.png [new file with mode: 0644]
manual/images/pv_device_config.png [new file with mode: 0644]
manual/images/pv_device_config.xcf [new file with mode: 0644]
manual/images/pv_import.png [new file with mode: 0644]
manual/images/pv_nodevice.png [new file with mode: 0644]
manual/images/top_bar.png [new file with mode: 0644]
manual/import_export.txt [new file with mode: 0644]
manual/installation.txt [new file with mode: 0644]
manual/license.txt [new file with mode: 0644]
manual/manual.txt [new file with mode: 0644]
manual/overview.txt [new file with mode: 0644]
pulseview.qrc
pv/application.cpp
pv/application.hpp
pv/binding/binding.cpp
pv/binding/binding.hpp
pv/binding/decoder.cpp
pv/binding/decoder.hpp
pv/binding/device.cpp
pv/binding/device.hpp
pv/binding/inputoutput.cpp
pv/data/analog.cpp
pv/data/analog.hpp
pv/data/analogsegment.cpp
pv/data/analogsegment.hpp
pv/data/decode/annotation.cpp
pv/data/decode/annotation.hpp
pv/data/decode/decoder.cpp
pv/data/decode/decoder.hpp
pv/data/decode/row.cpp
pv/data/decode/row.hpp
pv/data/decode/rowdata.cpp
pv/data/decode/rowdata.hpp
pv/data/decoderstack.cpp [deleted file]
pv/data/decoderstack.hpp [deleted file]
pv/data/decodesignal.cpp [new file with mode: 0644]
pv/data/decodesignal.hpp [new file with mode: 0644]
pv/data/logic.cpp
pv/data/logic.hpp
pv/data/logicsegment.cpp
pv/data/logicsegment.hpp
pv/data/segment.cpp
pv/data/segment.hpp
pv/data/signalbase.cpp
pv/data/signalbase.hpp
pv/data/signaldata.hpp
pv/devicemanager.cpp
pv/devicemanager.hpp
pv/devices/device.cpp
pv/devices/file.hpp
pv/devices/hardwaredevice.cpp
pv/devices/inputfile.cpp
pv/devices/inputfile.hpp
pv/dialogs/connect.cpp
pv/dialogs/connect.hpp
pv/dialogs/settings.cpp
pv/dialogs/settings.hpp
pv/dialogs/storeprogress.cpp
pv/globalsettings.cpp
pv/globalsettings.hpp
pv/logging.cpp [new file with mode: 0644]
pv/logging.hpp [new file with mode: 0644]
pv/mainwindow.cpp
pv/mainwindow.hpp
pv/popups/channels.cpp
pv/popups/channels.hpp
pv/popups/deviceoptions.cpp
pv/popups/deviceoptions.hpp
pv/prop/bool.cpp
pv/prop/bool.hpp
pv/prop/double.cpp
pv/prop/double.hpp
pv/prop/enum.cpp
pv/prop/enum.hpp
pv/prop/int.cpp
pv/prop/int.hpp
pv/prop/property.hpp
pv/prop/string.cpp
pv/prop/string.hpp
pv/session.cpp
pv/session.hpp
pv/storesession.cpp
pv/toolbars/mainbar.cpp
pv/toolbars/mainbar.hpp
pv/util.cpp
pv/util.hpp
pv/views/trace/analogsignal.cpp
pv/views/trace/analogsignal.hpp
pv/views/trace/cursor.cpp
pv/views/trace/cursor.hpp
pv/views/trace/cursorpair.cpp
pv/views/trace/cursorpair.hpp
pv/views/trace/decodetrace.cpp
pv/views/trace/decodetrace.hpp
pv/views/trace/flag.cpp
pv/views/trace/flag.hpp
pv/views/trace/header.cpp
pv/views/trace/header.hpp
pv/views/trace/logicsignal.cpp
pv/views/trace/logicsignal.hpp
pv/views/trace/marginwidget.cpp
pv/views/trace/rowitem.cpp
pv/views/trace/rowitem.hpp
pv/views/trace/ruler.cpp
pv/views/trace/ruler.hpp
pv/views/trace/signal.cpp
pv/views/trace/signal.hpp
pv/views/trace/signalscalehandle.cpp [deleted file]
pv/views/trace/signalscalehandle.hpp [deleted file]
pv/views/trace/standardbar.cpp
pv/views/trace/standardbar.hpp
pv/views/trace/timeitem.cpp
pv/views/trace/timeitem.hpp
pv/views/trace/timemarker.cpp
pv/views/trace/timemarker.hpp
pv/views/trace/trace.cpp
pv/views/trace/trace.hpp
pv/views/trace/tracegroup.cpp
pv/views/trace/tracegroup.hpp
pv/views/trace/tracepalette.cpp
pv/views/trace/tracepalette.hpp
pv/views/trace/tracetreeitem.cpp
pv/views/trace/tracetreeitem.hpp
pv/views/trace/tracetreeitemowner.cpp
pv/views/trace/triggermarker.cpp
pv/views/trace/triggermarker.hpp
pv/views/trace/view.cpp
pv/views/trace/view.hpp
pv/views/trace/viewitem.cpp
pv/views/trace/viewitem.hpp
pv/views/trace/viewitemowner.cpp
pv/views/trace/viewitemowner.hpp
pv/views/trace/viewitempaintparams.cpp
pv/views/trace/viewitempaintparams.hpp
pv/views/trace/viewport.cpp
pv/views/trace/viewport.hpp
pv/views/trace/viewwidget.cpp
pv/views/trace/viewwidget.hpp
pv/views/viewbase.cpp
pv/views/viewbase.hpp
pv/widgets/colorbutton.cpp [new file with mode: 0644]
pv/widgets/colorbutton.hpp [new file with mode: 0644]
pv/widgets/colorpopup.cpp [new file with mode: 0644]
pv/widgets/colorpopup.hpp [new file with mode: 0644]
pv/widgets/colourbutton.cpp [deleted file]
pv/widgets/colourbutton.hpp [deleted file]
pv/widgets/colourpopup.cpp [deleted file]
pv/widgets/colourpopup.hpp [deleted file]
pv/widgets/decodermenu.cpp
pv/widgets/devicetoolbutton.cpp
pv/widgets/popup.hpp
pv/widgets/sweeptimingwidget.cpp
pv/widgets/sweeptimingwidget.hpp
pv/widgets/wellarray.hpp
signalhandler.hpp
test/CMakeLists.txt
test/data/segment.cpp
test/view/ruler.cpp
themes/darkstyle/darkstyle.qss [new file with mode: 0644]
themes/darkstyle/icon_branch_closed.png [new file with mode: 0644]
themes/darkstyle/icon_branch_end.png [new file with mode: 0644]
themes/darkstyle/icon_branch_more.png [new file with mode: 0644]
themes/darkstyle/icon_branch_open.png [new file with mode: 0644]
themes/darkstyle/icon_checkbox_checked.png [new file with mode: 0644]
themes/darkstyle/icon_checkbox_checked_disabled.png [new file with mode: 0644]
themes/darkstyle/icon_checkbox_checked_pressed.png [new file with mode: 0644]
themes/darkstyle/icon_checkbox_indeterminate.png [new file with mode: 0644]
themes/darkstyle/icon_checkbox_indeterminate_disabled.png [new file with mode: 0644]
themes/darkstyle/icon_checkbox_indeterminate_pressed.png [new file with mode: 0644]
themes/darkstyle/icon_checkbox_unchecked.png [new file with mode: 0644]
themes/darkstyle/icon_checkbox_unchecked_disabled.png [new file with mode: 0644]
themes/darkstyle/icon_checkbox_unchecked_pressed.png [new file with mode: 0644]
themes/darkstyle/icon_close.png [new file with mode: 0644]
themes/darkstyle/icon_radiobutton_checked.png [new file with mode: 0644]
themes/darkstyle/icon_radiobutton_checked_disabled.png [new file with mode: 0644]
themes/darkstyle/icon_radiobutton_checked_pressed.png [new file with mode: 0644]
themes/darkstyle/icon_radiobutton_unchecked.png [new file with mode: 0644]
themes/darkstyle/icon_radiobutton_unchecked_disabled.png [new file with mode: 0644]
themes/darkstyle/icon_radiobutton_unchecked_pressed.png [new file with mode: 0644]
themes/darkstyle/icon_restore.png [new file with mode: 0644]
themes/darkstyle/icon_undock.png [new file with mode: 0644]
themes/darkstyle/icon_vline.png [new file with mode: 0644]
themes/qdarkstyle/rc/Hmovetoolbar.png [new file with mode: 0644]
themes/qdarkstyle/rc/Hsepartoolbar.png [new file with mode: 0644]
themes/qdarkstyle/rc/Vmovetoolbar.png [new file with mode: 0644]
themes/qdarkstyle/rc/Vsepartoolbar.png [new file with mode: 0644]
themes/qdarkstyle/rc/branch_closed-on.png [new file with mode: 0644]
themes/qdarkstyle/rc/branch_closed.png [new file with mode: 0644]
themes/qdarkstyle/rc/branch_open-on.png [new file with mode: 0644]
themes/qdarkstyle/rc/branch_open.png [new file with mode: 0644]
themes/qdarkstyle/rc/checkbox_checked.png [new file with mode: 0644]
themes/qdarkstyle/rc/checkbox_checked_disabled.png [new file with mode: 0644]
themes/qdarkstyle/rc/checkbox_checked_focus.png [new file with mode: 0644]
themes/qdarkstyle/rc/checkbox_indeterminate.png [new file with mode: 0644]
themes/qdarkstyle/rc/checkbox_indeterminate_disabled.png [new file with mode: 0644]
themes/qdarkstyle/rc/checkbox_indeterminate_focus.png [new file with mode: 0644]
themes/qdarkstyle/rc/checkbox_unchecked.png [new file with mode: 0644]
themes/qdarkstyle/rc/checkbox_unchecked_disabled.png [new file with mode: 0644]
themes/qdarkstyle/rc/checkbox_unchecked_focus.png [new file with mode: 0644]
themes/qdarkstyle/rc/close-hover.png [new file with mode: 0644]
themes/qdarkstyle/rc/close-pressed.png [new file with mode: 0644]
themes/qdarkstyle/rc/close.png [new file with mode: 0644]
themes/qdarkstyle/rc/down_arrow.png [new file with mode: 0644]
themes/qdarkstyle/rc/down_arrow_disabled.png [new file with mode: 0644]
themes/qdarkstyle/rc/left_arrow.png [new file with mode: 0644]
themes/qdarkstyle/rc/left_arrow_disabled.png [new file with mode: 0644]
themes/qdarkstyle/rc/radio_checked.png [new file with mode: 0644]
themes/qdarkstyle/rc/radio_checked_disabled.png [new file with mode: 0644]
themes/qdarkstyle/rc/radio_checked_focus.png [new file with mode: 0644]
themes/qdarkstyle/rc/radio_unchecked.png [new file with mode: 0644]
themes/qdarkstyle/rc/radio_unchecked_disabled.png [new file with mode: 0644]
themes/qdarkstyle/rc/radio_unchecked_focus.png [new file with mode: 0644]
themes/qdarkstyle/rc/right_arrow.png [new file with mode: 0644]
themes/qdarkstyle/rc/right_arrow_disabled.png [new file with mode: 0644]
themes/qdarkstyle/rc/sizegrip.png [new file with mode: 0644]
themes/qdarkstyle/rc/stylesheet-branch-end.png [new file with mode: 0644]
themes/qdarkstyle/rc/stylesheet-branch-more.png [new file with mode: 0644]
themes/qdarkstyle/rc/stylesheet-vline.png [new file with mode: 0644]
themes/qdarkstyle/rc/transparent.png [new file with mode: 0644]
themes/qdarkstyle/rc/undock.png [new file with mode: 0644]
themes/qdarkstyle/rc/up_arrow.png [new file with mode: 0644]
themes/qdarkstyle/rc/up_arrow_disabled.png [new file with mode: 0644]
themes/qdarkstyle/style.qss [new file with mode: 0644]

index ea272ee6147c921755ec9a57ff4986c91f0ef36d..59d7aa2fc423b4511548bddc9616dcade48ce93f 100644 (file)
@@ -50,3 +50,5 @@ android/src/org/kde/
 # QtCreator cruft
 /CMakeLists.txt.user*
 *.cbp
+
+doxy
index af39c89e19f8b9f9f5e251426d3b10bb8ba9d01b..b74792de7a1d33b3267867f291ea04d3bf0fbce7 100644 (file)
@@ -24,16 +24,27 @@ include(GNUInstallDirs)
 
 project(pulseview)
 
+# Let AUTOMOC and AUTOUIC process GENERATED files.
+if(POLICY CMP0071)
+       cmake_policy(SET CMP0071 NEW)
+endif()
+
+# Only interpret if() arguments as variables or keywords when unquoted.
+if(POLICY CMP0054)
+       cmake_policy(SET CMP0054 NEW)
+endif()
+
 list(APPEND CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/CMake")
 
 #===============================================================================
 #= User Options
 #-------------------------------------------------------------------------------
 
-option(DISABLE_WERROR "Build without -Werror" FALSE)
+option(DISABLE_WERROR "Build without -Werror" TRUE)
 option(ENABLE_SIGNALS "Build with UNIX signals" TRUE)
+option(ENABLE_STACKTRACE "Enable stack trace when crashing" FALSE)
 option(ENABLE_DECODE "Build with libsigrokdecode" TRUE)
-option(ENABLE_TESTS "Enable unit tests" TRUE)
+option(ENABLE_TESTS "Enable unit tests" FALSE)
 option(STATIC_PKGDEPS_LIBS "Statically link to (pkg-config) libraries" FALSE)
 
 if(WIN32)
@@ -51,6 +62,12 @@ if(NOT CMAKE_BUILD_TYPE)
        FORCE)
 endif()
 
+#===============================================================================
+#= Documentation
+#-------------------------------------------------------------------------------
+
+add_subdirectory(manual)
+
 #===============================================================================
 #= Dependencies
 #-------------------------------------------------------------------------------
@@ -58,10 +75,11 @@ endif()
 list(APPEND PKGDEPS glib-2.0>=2.28.0)
 list(APPEND PKGDEPS glibmm-2.4>=2.28.0)
 
-list(APPEND PKGDEPS libsigrokcxx>=0.5.0)
+set(LIBSR_CXX_BINDING "libsigrokcxx>=0.5.1")
+list(APPEND PKGDEPS "${LIBSR_CXX_BINDING}")
 
 if(ENABLE_DECODE)
-       list(APPEND PKGDEPS libsigrokdecode>=0.5.0)
+       list(APPEND PKGDEPS libsigrokdecode>=0.5.2)
 endif()
 
 if(ANDROID)
@@ -69,6 +87,10 @@ if(ANDROID)
 endif()
 
 find_package(PkgConfig)
+pkg_check_modules(LIBSRCXX QUIET ${LIBSR_CXX_BINDING})
+if(NOT LIBSRCXX_FOUND OR NOT LIBSRCXX_VERSION)
+       message(FATAL_ERROR "libsigrok C++ bindings missing, check libsigrok's 'configure' output (missing dependencies?)")
+endif()
 pkg_check_modules(PKGDEPS REQUIRED ${PKGDEPS})
 
 set(CMAKE_AUTOMOC TRUE)
@@ -78,7 +100,10 @@ find_package(Qt5 COMPONENTS Core Gui Widgets Svg REQUIRED)
 if(WIN32)
        # MXE workaround: Use pkg-config to find Qt5 libs.
        # https://github.com/mxe/mxe/issues/1642
-       pkg_check_modules(QT5ALL REQUIRED Qt5Widgets Qt5Gui Qt5Svg)
+       # Not required (and doesn't work) on MSYS2.
+       if(NOT DEFINED ENV{MSYSTEM})
+               pkg_check_modules(QT5ALL REQUIRED Qt5Widgets Qt5Gui Qt5Svg)
+       endif()
 endif()
 
 set(QT_LIBRARIES Qt5::Gui Qt5::Widgets Qt5::Svg)
@@ -87,7 +112,12 @@ set(BOOSTCOMPS filesystem serialization system)
 if(ENABLE_TESTS)
        list(APPEND BOOSTCOMPS unit_test_framework)
 endif()
-find_package(Boost 1.55 COMPONENTS ${BOOSTCOMPS} REQUIRED)
+
+if(ENABLE_STACKTRACE)
+       find_package(Boost 1.65.1 COMPONENTS ${BOOSTCOMPS} REQUIRED)
+else()
+       find_package(Boost 1.55 COMPONENTS ${BOOSTCOMPS} REQUIRED)
+endif()
 
 # Find the platform's thread library (needed for C++11 threads).
 # This will set ${CMAKE_THREAD_LIBS_INIT} to the correct, OS-specific value.
@@ -153,7 +183,7 @@ memaccess_check_unaligned_le(HAVE_UNALIGNED_LITTLE_ENDIAN_ACCESS)
 #-------------------------------------------------------------------------------
 
 set(PV_TITLE PulseView)
-set(PV_VERSION_STRING "0.4.0")
+set(PV_VERSION_STRING "0.5.0")
 
 set(PV_GLIBMM_VERSION ${PKGDEPS_glibmm-2.4_VERSION})
 
@@ -167,6 +197,12 @@ if(NOT PV_TAG_VERSION_STRING)
                string(SUBSTRING "${PV_HASH}" 0 7 PV_SHORTHASH)
                set(PV_VERSION_STRING "${PV_VERSION_STRING}-git-${PV_SHORTHASH}")
        endif()
+
+       # Non-tagged releases use the unstable manual
+       set(PV_MANUAL_VERSION "unstable")
+else()
+       # Tagged releases use a fixed manual version
+       set(PV_MANUAL_VERSION ${PV_VERSION_STRING})
 endif()
 
 if(PV_VERSION_STRING MATCHES "^([0-9]+)\\.([0-9]+)\\.([0-9]+)(-[-0-9a-z]*)?$")
@@ -176,7 +212,7 @@ if(PV_VERSION_STRING MATCHES "^([0-9]+)\\.([0-9]+)\\.([0-9]+)(-[-0-9a-z]*)?$")
        set(PV_VERSION_SUFFIX ${CMAKE_MATCH_4})
 endif()
 
-message("-- ${PV_TITLE} version: ${PV_VERSION_STRING}")
+message(STATUS "${PV_TITLE} version: ${PV_VERSION_STRING}")
 
 configure_file (
        ${PROJECT_SOURCE_DIR}/config.h.in
@@ -192,6 +228,7 @@ set(pulseview_SOURCES
        pv/application.cpp
        pv/devicemanager.cpp
        pv/globalsettings.cpp
+       pv/logging.cpp
        pv/mainwindow.cpp
        pv/session.cpp
        pv/storesession.cpp
@@ -234,7 +271,6 @@ set(pulseview_SOURCES
        pv/views/trace/rowitem.cpp
        pv/views/trace/ruler.cpp
        pv/views/trace/signal.cpp
-       pv/views/trace/signalscalehandle.cpp
        pv/views/trace/timeitem.cpp
        pv/views/trace/timemarker.cpp
        pv/views/trace/trace.cpp
@@ -251,8 +287,8 @@ set(pulseview_SOURCES
        pv/views/trace/viewwidget.cpp
        pv/views/viewbase.cpp
        pv/views/trace/standardbar.cpp
-       pv/widgets/colourbutton.cpp
-       pv/widgets/colourpopup.cpp
+       pv/widgets/colorbutton.cpp
+       pv/widgets/colorpopup.cpp
        pv/widgets/devicetoolbutton.cpp
        pv/widgets/exportmenu.cpp
        pv/widgets/importmenu.cpp
@@ -265,6 +301,7 @@ set(pulseview_SOURCES
 
 # This list includes only QObject derived class headers.
 set(pulseview_HEADERS
+       pv/logging.hpp
        pv/globalsettings.hpp
        pv/mainwindow.hpp
        pv/session.hpp
@@ -297,7 +334,6 @@ set(pulseview_HEADERS
        pv/views/trace/rowitem.hpp
        pv/views/trace/ruler.hpp
        pv/views/trace/signal.hpp
-       pv/views/trace/signalscalehandle.hpp
        pv/views/trace/timeitem.hpp
        pv/views/trace/timemarker.hpp
        pv/views/trace/trace.hpp
@@ -310,8 +346,8 @@ set(pulseview_HEADERS
        pv/views/trace/viewwidget.hpp
        pv/views/viewbase.hpp
        pv/views/trace/standardbar.hpp
-       pv/widgets/colourbutton.hpp
-       pv/widgets/colourpopup.hpp
+       pv/widgets/colorbutton.hpp
+       pv/widgets/colorpopup.hpp
        pv/widgets/devicetoolbutton.hpp
        pv/widgets/exportmenu.hpp
        pv/widgets/importmenu.hpp
@@ -334,7 +370,7 @@ endif()
 if(ENABLE_DECODE)
        list(APPEND pulseview_SOURCES
                pv/binding/decoder.cpp
-               pv/data/decoderstack.cpp
+               pv/data/decodesignal.cpp
                pv/data/decode/annotation.cpp
                pv/data/decode/decoder.cpp
                pv/data/decode/row.cpp
@@ -345,7 +381,7 @@ if(ENABLE_DECODE)
        )
 
        list(APPEND pulseview_HEADERS
-               pv/data/decoderstack.hpp
+               pv/data/decodesignal.hpp
                pv/views/trace/decodetrace.hpp
                pv/widgets/decodergroupbox.hpp
                pv/widgets/decodermenu.hpp
@@ -390,6 +426,10 @@ if(ENABLE_SIGNALS)
        add_definitions(-DENABLE_SIGNALS)
 endif()
 
+if(ENABLE_STACKTRACE)
+       add_definitions(-DENABLE_STACKTRACE)
+endif()
+
 #===============================================================================
 #= Global Include Directories
 #-------------------------------------------------------------------------------
@@ -430,12 +470,20 @@ endif()
 if(WIN32)
        # On Windows we need to statically link the libqsvg imageformat
        # plugin (and the QtSvg component) for SVG graphics/icons to work.
-       # We also need QWindowsIntegrationPlugin, Qt5PlatformSupport, and all
-       # Qt libs and their dependencies.
+       # We also need QWindowsIntegrationPlugin, Qt5PlatformSupport (only for
+       # Qt < 5.8.0), and all Qt libs and their dependencies.
        add_definitions(-DQT_STATICPLUGIN)
        list(APPEND PULSEVIEW_LINK_LIBS Qt5::QSvgPlugin)
        list(APPEND PULSEVIEW_LINK_LIBS Qt5::QWindowsIntegrationPlugin)
-       list(APPEND PULSEVIEW_LINK_LIBS -lQt5PlatformSupport ${QT5ALL_LDFLAGS})
+       if(Qt5Gui_VERSION VERSION_LESS 5.8.0)
+               list(APPEND PULSEVIEW_LINK_LIBS -lQt5PlatformSupport)
+       endif()
+       list(APPEND PULSEVIEW_LINK_LIBS ${QT5ALL_LDFLAGS})
+endif()
+
+if(ENABLE_STACKTRACE)
+       # Needed to resolve dladdr.
+       list(APPEND PULSEVIEW_LINK_LIBS "-ldl")
 endif()
 
 if(ANDROID)
@@ -450,7 +498,7 @@ endif()
 
 target_link_libraries(${PROJECT_NAME} ${PULSEVIEW_LINK_LIBS})
 
-if(WIN32)
+if(WIN32 AND NOT ${CMAKE_BUILD_TYPE} STREQUAL "Debug")
        # Pass -mwindows so that no "DOS box" opens when PulseView is started.
        set_target_properties(${PROJECT_NAME} PROPERTIES LINK_FLAGS "-mwindows")
 endif()
diff --git a/HACKING b/HACKING
index d539681c38026150e448da04f490c4e64fca3790..32c10dddbb280bc47d92971ca465b6fd75d3b3ad 100644 (file)
--- a/HACKING
+++ b/HACKING
@@ -5,8 +5,9 @@ HACKING
 Coding style
 ------------
 
-This project is programmed using the Linux kernel coding style, see
-http://lxr.linux.no/linux/Documentation/CodingStyle for details.
+This project is programmed using the Linux kernel coding style:
+
+  https://www.kernel.org/doc/html/latest/process/coding-style.html
 
 Please use the same style for any code contributions, thanks!
 
@@ -17,15 +18,16 @@ OK (in order to meet Qt/C++ related guidelines, for example).
 Contributions
 -------------
 
- - Patches should be sent to the development mailinglist at
+ - In order to contribute you should ideally clone the git repository and
+   let us know (preferably via IRC, or via the mailing list) from where to
+   pull/review your changes. You can use github.com, or any other public git
+   hosting site.
+
+ - Alternatively, patches can be sent to the development mailinglist at
    sigrok-devel@lists.sourceforge.net (please subscribe to the list first).
 
    https://lists.sourceforge.net/lists/listinfo/sigrok-devel
 
- - Alternatively, you can also clone the git repository and let us know
-   from where to pull/review your changes. You can use gitorious.org,
-   github.com, or any other public git hosting site.
-
 
 Random notes
 ------------
diff --git a/INSTALL b/INSTALL
index 3f883e9731f45a80ca629abcb7fd8f6497e1349c..edb7940d522c9126e1edcbf8579e1d54fd2762f7 100644 (file)
--- a/INSTALL
+++ b/INSTALL
@@ -22,9 +22,12 @@ Requirements
     - libboost-filesystem
     - libboost-serialization
     - libboost-test (optional, only needed to run the unit tests)
- - libsigrokcxx >= 0.5.0 (libsigrok C++ bindings)
- - libsigrokdecode >= 0.5.0
+    - libboost-stacktrace (optional, only needed for debugging)
+ - libsigrokcxx >= 0.5.1 (libsigrok C++ bindings)
+ - libsigrokdecode >= 0.5.2
  - libsigrokandroidutils >= 0.1.0 (optional, only needed on Android)
+ - asciidoctor (optional, only needed to build the HTML manual)
+ - asciidoctor-pdf (optional, only needed to build the PDF manual)
 
 
 Building and installing
@@ -56,3 +59,21 @@ In order to build a source package begin with an unconfigured source tree.
  $ cmake ..
  $ make package_source
 
+
+Generating the manual
+---------------------
+
+To generate the HTML manual, you only need Asciidoctor. If you also want
+to generate the PDF manual, you need to install asciidoctor-pdf as well
+and make it available for execution:
+
+ $ gem install --pre asciidoctor-pdf
+ $ export PATH=~/.gem/ruby/2.3.0/bin:$PATH
+
+Then, to build the PulseView manual, run:
+
+ $ make manual
+
+Note: The stylesheet used is a lightly modified version of "Read The Docs"
+from the Asciidoctor stylesheet factory:
+https://asciidoctor.org/docs/user-manual/#stylesheet-factory
diff --git a/README b/README
index 613ecc5c2faba3be33fe45f831586aaa474eaeb2..8608b3bf7314024ff15b5c0f0e13eca510bde5b9 100644 (file)
--- a/README
+++ b/README
@@ -44,11 +44,26 @@ is to be interpreted as
  Copyright (C) 2010,2011,2012,2013 Contributor Name
 
 
-Icons authors and licenses
---------------------------
+Resource authors and licenses
+-----------------------------
 
 icons/information.svg: Bobarino
   https://en.wikipedia.org/wiki/File:Information.svg
+  License:
+    GFDL 1.2 or later / CC-BY-SA 3.0
+    https://en.wikipedia.org/wiki/File:Information.svg#Licensing
+
+QDarkStyleSheet: Colin Duquesnoy
+  https://github.com/ColinDuquesnoy/QDarkStyleSheet
+  License:
+    CC-BY 4.0
+    https://github.com/ColinDuquesnoy/QDarkStyleSheet/blob/master/LICENSE.md
+
+DarkStyle: Juergen Skrotzky
+  https://github.com/Jorgen-VikingGod/Qt-Frameless-Window-DarkStyle
+  License:
+    MIT license
+    https://github.com/Jorgen-VikingGod/Qt-Frameless-Window-DarkStyle#licence
 
 
 Mailing list
index 2c6674cda51cdcd6a398198525c301a24acf3462..c9953a6e2894e21e924e99d8ffa4fbefa2b8efb7 100644 (file)
 
 #include <android/log.h>
 
-#include <stdint.h>
+#include <cstdint>
 #include <libsigrok/libsigrok.h>
 
 #include "android/loghandler.hpp"
 
 namespace pv {
 
+static sr_log_callback prev_sr_log_cb;
+static void *prev_sr_log_cb_data;
+
+#ifdef ENABLE_DECODE
+static srd_log_callback prev_srd_log_cb;
+static void *prev_srd_log_cb_data;
+#endif
+
 int AndroidLogHandler::sr_callback(void *cb_data, int loglevel, const char *format, va_list args)
 {
        static const int prio[] = {
@@ -40,11 +48,18 @@ int AndroidLogHandler::sr_callback(void *cb_data, int loglevel, const char *form
                [SR_LOG_DBG] = ANDROID_LOG_DEBUG,
                [SR_LOG_SPEW] = ANDROID_LOG_VERBOSE,
        };
+       va_list args2;
        int ret;
 
        /* This specific log callback doesn't need the void pointer data. */
        (void)cb_data;
 
+       /* Call the previously registered log callback (library's default). */
+       va_copy(args2, args);
+       if (prev_sr_log_cb)
+               prev_sr_log_cb(prev_sr_log_cb_data, loglevel, format, args2);
+       va_end(args2);
+
        /* Only output messages of at least the selected loglevel(s). */
        if (loglevel > sr_log_loglevel_get())
                return SR_OK;
@@ -70,11 +85,18 @@ int AndroidLogHandler::srd_callback(void *cb_data, int loglevel, const char *for
                [SRD_LOG_DBG] = ANDROID_LOG_DEBUG,
                [SRD_LOG_SPEW] = ANDROID_LOG_VERBOSE,
        };
+       va_list args2;
        int ret;
 
        /* This specific log callback doesn't need the void pointer data. */
        (void)cb_data;
 
+       /* Call the previously registered log callback (library's default). */
+       va_copy(args2, args);
+       if (prev_srd_log_cb)
+               prev_srd_log_cb(prev_srd_log_cb_data, loglevel, format, args2);
+       va_end(args2);
+
        /* Only output messages of at least the selected loglevel(s). */
        if (loglevel > srd_log_loglevel_get())
                return SRD_OK;
@@ -94,8 +116,10 @@ int AndroidLogHandler::srd_callback(void *cb_data, int loglevel, const char *for
 
 void AndroidLogHandler::install_callbacks()
 {
+       sr_log_callback_get(&prev_sr_log_cb, &prev_sr_log_cb_data);
        sr_log_callback_set(sr_callback, nullptr);
 #ifdef ENABLE_DECODE
+       srd_log_callback_get(&prev_srd_log_cb, &prev_srd_log_cb_data);
        srd_log_callback_set(srd_callback, nullptr);
 #endif
 }
index 7bdfbf309c1e1600136cd8d4079911b033a6c3c0..f76276e27e3eeebc183cdc4f43327cb9c09e40f3 100644 (file)
@@ -7,4 +7,4 @@ Comment=Control your logic analyzer, oscilloscope, or MSO
 Exec=pulseview
 Icon=pulseview
 Type=Application
-MimeType=application/vnd.sigrok.session
+MimeType=application/vnd.sigrok.session;
index 13a45fe18435746f1f46c1062dd611a2ecb6b2cd..fdcdf49ebf667e406192de01869e04d65c30d885 100644 (file)
@@ -81,7 +81,7 @@ RequestExecutionLevel admin
 !define SHCNF_IDLIST 0
 
 
-# --- Functions ---------------------------------------------------------------
+# --- Functions/Macros --------------------------------------------------------
 
 Function register_sr_files
        ${registerExtension} "$INSTDIR\pulseview.exe" ".sr" "sigrok session file"
@@ -90,6 +90,12 @@ Function register_sr_files
        System::Call 'Shell32::SHChangeNotify(i ${SHCNE_ASSOCCHANGED}, i ${SHCNF_IDLIST}, i 0, i 0)'
 FunctionEnd
 
+# Inspired by http://nsis.sourceforge.net/Create_Internet_Shorcuts_during_installation
+!Macro "CreateURL" "URLFile" "URLSite" "URLDesc"
+       WriteINIStr "$INSTDIR\${URLFile}.URL" "InternetShortcut" "URL" "${URLSite}"
+       CreateShortCut "$SMPROGRAMS\sigrok\PulseView\${URLFile}.lnk" "$INSTDIR\${URLFile}.url" "" \
+               "$INSTDIR\pulseview.exe" 0 "SW_SHOWNORMAL" "" "${URLDesc}"
+!MacroEnd
 
 # --- MUI pages ---------------------------------------------------------------
 
@@ -177,6 +183,12 @@ Section "PulseView (required)" Section1
                0 SW_SHOWNORMAL \
                "" "Open-source, portable sigrok GUI"
 
+       # Create a shortcut for the PulseView application running in debug mode.
+       CreateShortCut "$SMPROGRAMS\sigrok\PulseView\PulseView (Debug).lnk" \
+               "$INSTDIR\pulseview.exe" "-l 5" "$INSTDIR\pulseview.exe" \
+               0 SW_SHOWNORMAL \
+               "" "Open-source, portable sigrok GUI (debug log level)"
+
        # Create a shortcut for the uninstaller.
        CreateShortCut "$SMPROGRAMS\sigrok\PulseView\Uninstall PulseView.lnk" \
                "$INSTDIR\Uninstall.exe" "" "$INSTDIR\Uninstall.exe" 0 \
@@ -192,6 +204,10 @@ Section "PulseView (required)" Section1
                "$INSTDIR\zadig_xp.exe" "" "$INSTDIR\zadig_xp.exe" 0 \
                SW_SHOWNORMAL "" "Zadig (PulseView, Win XP)"
 
+       # Create shortcuts to the HTML and PDF manuals, respectively.
+       !InsertMacro "CreateURL" "PulseView HTML manual" "https://sigrok.org/doc/pulseview/@PV_MANUAL_VERSION@/manual.html" "PulseView HTML manual"
+       !InsertMacro "CreateURL" "PulseView PDF manual" "https://sigrok.org/doc/pulseview/@PV_MANUAL_VERSION@/manual.pdf" "PulseView PDF manual"
+
        # Create registry keys for "Add/remove programs" in the control panel.
        WriteRegStr HKLM "${REGSTR}" "DisplayName" "PulseView"
        WriteRegStr HKLM "${REGSTR}" "UninstallString" \
@@ -267,6 +283,10 @@ Section "Uninstall"
        # Delete the example *.sr files.
        RMDir /r "$INSTDIR\examples\*"
 
+       # Delete the URL files for the manual.
+       Delete "$INSTDIR\PulseView HTML manual.url"
+       Delete "$INSTDIR\PulseView PDF manual.url"
+
        # Delete the install directory and its sub-directories.
        RMDir "$INSTDIR\share"
        RMDir "$INSTDIR\examples"
@@ -274,11 +294,16 @@ Section "Uninstall"
 
        # Delete the links from the start menu.
        Delete "$SMPROGRAMS\sigrok\PulseView\PulseView.lnk"
+       Delete "$SMPROGRAMS\sigrok\PulseView\PulseView (Debug).lnk"
        Delete "$SMPROGRAMS\sigrok\PulseView\Uninstall PulseView.lnk"
        Delete "$SMPROGRAMS\sigrok\PulseView\Zadig (PulseView).lnk"
        Delete "$SMPROGRAMS\sigrok\PulseView\Zadig (PulseView, Win XP).lnk"
        Delete "$SMPROGRAMS\sigrok\PulseView\Examples (PulseView).lnk"
 
+       # Delete the links to the manual.
+       Delete "$SMPROGRAMS\sigrok\PulseView\PulseView HTML manual.lnk"
+       Delete "$SMPROGRAMS\sigrok\PulseView\PulseView PDF manual.lnk"
+
        # Delete the sub-directory in the start menu.
        RMDir "$SMPROGRAMS\sigrok\PulseView"
        RMDir "$SMPROGRAMS\sigrok"
index ad1cf59556974e7c8ae7b6bfb27e0276e4f2809f..8289eaa85f858becb08069c3b67a4e742105402c 100644 (file)
@@ -1,4 +1,4 @@
-.TH PULSEVIEW 1 "June 6, 2017"
+.TH PULSEVIEW 1 "March 30, 2018"
 .SH "NAME"
 PulseView \- Qt-based LA/scope/MSO GUI for sigrok
 .SH "SYNOPSIS"
@@ -41,6 +41,20 @@ Show a help text and exit.
 .B "\-V, \-\-version"
 Show version information and exit.
 .TP
+.BR "\-d, \-\-driver " <drivername>
+Specify the capture device to connect to. If the
+.B \-\-driver
+option is not supplied, PulseView attempts to re-connect to the
+most recently used device, or auto-detect available devices.
+.TP
+.BR "\-D, \-\-dont\-scan "
+Usually PulseView automatically scans all drivers to find suitable
+devices during program startup. This option disables the auto-scan.
+Users can either specify the
+.B \-\-driver
+option to pick a device at startup, or interactively scan for devices
+after PulseView has finished starting up.
+.TP
 .BR "\-i, \-\-input\-file " <filename>
 Load input from a file. If the
 .B \-\-input\-format
diff --git a/icons/help-browser.png b/icons/help-browser.png
new file mode 100644 (file)
index 0000000..593ecd5
Binary files /dev/null and b/icons/help-browser.png differ
diff --git a/icons/media-playback-pause.png b/icons/media-playback-pause.png
new file mode 100644 (file)
index 0000000..ee40fc2
Binary files /dev/null and b/icons/media-playback-pause.png differ
diff --git a/icons/media-playback-start.png b/icons/media-playback-start.png
new file mode 100644 (file)
index 0000000..10102d8
Binary files /dev/null and b/icons/media-playback-start.png differ
diff --git a/icons/settings-general.png b/icons/settings-general.png
new file mode 100644 (file)
index 0000000..4decc89
Binary files /dev/null and b/icons/settings-general.png differ
diff --git a/icons/view-displaymode-last_complete_segment.svg b/icons/view-displaymode-last_complete_segment.svg
new file mode 100644 (file)
index 0000000..125369e
--- /dev/null
@@ -0,0 +1,521 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<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"
+   width="35.433071"
+   height="35.433071"
+   id="svg2"
+   version="1.1"
+   inkscape:version="0.48.5 r10040"
+   sodipodi:docname="view-displaymode-last_complete_segment.svg">
+  <sodipodi:namedview
+     id="base"
+     pagecolor="#ffffff"
+     bordercolor="#666666"
+     borderopacity="1.0"
+     inkscape:pageopacity="0.0"
+     inkscape:pageshadow="2"
+     inkscape:zoom="15.465778"
+     inkscape:cx="7.8560557"
+     inkscape:cy="17.231594"
+     inkscape:document-units="px"
+     inkscape:current-layer="layer1"
+     showgrid="false"
+     units="mm"
+     inkscape:window-width="1369"
+     inkscape:window-height="743"
+     inkscape:window-x="174"
+     inkscape:window-y="153"
+     inkscape:window-maximized="0" />
+  <defs
+     id="defs4" />
+  <metadata
+     id="metadata7">
+    <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 />
+      </cc:Work>
+    </rdf:RDF>
+  </metadata>
+  <g
+     inkscape:groupmode="layer"
+     id="layer2"
+     inkscape:label="Layer"
+     style="display:none">
+    <g
+       transform="translate(0,-1016.9291)"
+       style="display:inline"
+       id="g7555-6">
+      <path
+         inkscape:connector-curvature="0"
+         id="path3768-2-3-5-9"
+         d="m 0,1044.2466 35.26169,0"
+         style="fill:none;stroke:#c9c9c9;stroke-width:0.19036053;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0" />
+      <path
+         inkscape:connector-curvature="0"
+         id="path3768-2-6"
+         d="m 0,1020.9238 35.26169,0"
+         style="fill:none;stroke:#c9c9c9;stroke-width:0.18860409;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0" />
+      <path
+         inkscape:connector-curvature="0"
+         id="path3768-1-9"
+         d="m 0,1029.0753 35.26169,0"
+         style="fill:none;stroke:#c9c9c9;stroke-width:0.18860409;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0" />
+      <path
+         inkscape:connector-curvature="0"
+         id="path3755-4-29"
+         d="m 3.8604174,1017.11 0,15.8294"
+         style="fill:none;stroke:#c9c9c9;stroke-width:0.18860409;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" />
+      <path
+         inkscape:connector-curvature="0"
+         id="path3755-4-0-6"
+         d="m 7.7208349,1017.11 0,15.8294"
+         style="fill:none;stroke:#c9c9c9;stroke-width:0.18860409;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" />
+      <path
+         inkscape:connector-curvature="0"
+         id="path3755-4-5-8"
+         d="m 11.581253,1017.11 0,15.8294"
+         style="fill:none;stroke:#c9c9c9;stroke-width:0.18860409;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" />
+      <path
+         inkscape:connector-curvature="0"
+         id="path3755-4-9-14"
+         d="m 15.441669,1017.11 0,15.8294"
+         style="fill:none;stroke:#c9c9c9;stroke-width:0.18860409;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" />
+      <path
+         inkscape:connector-curvature="0"
+         id="path3755-4-7-90"
+         d="m 19.302086,1017.11 0,15.8294"
+         style="fill:none;stroke:#c9c9c9;stroke-width:0.18860409;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" />
+      <path
+         inkscape:connector-curvature="0"
+         id="path3755-4-3-32"
+         d="m 23.162504,1017.11 0,15.8294"
+         style="fill:none;stroke:#c9c9c9;stroke-width:0.18860409;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" />
+      <path
+         inkscape:connector-curvature="0"
+         id="path3755-4-1-3"
+         d="m 27.022922,1017.11 0,15.8294"
+         style="fill:none;stroke:#c9c9c9;stroke-width:0.18860409;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" />
+      <path
+         inkscape:connector-curvature="0"
+         id="path3755-4-90-6"
+         d="m 30.883338,1017.11 0,15.8294"
+         style="fill:none;stroke:#c9c9c9;stroke-width:0.18860409;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" />
+      <path
+         inkscape:connector-curvature="0"
+         id="path3755-4-2-4"
+         d="m 34.743757,1017.11 0,15.8294"
+         style="fill:none;stroke:#c9c9c9;stroke-width:0.18860409;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" />
+      <path
+         inkscape:connector-curvature="0"
+         id="path3755-49"
+         d="m 0,1017.11 0,15.8294"
+         style="fill:none;stroke:#000000;stroke-width:0.3772082;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" />
+      <path
+         inkscape:connector-curvature="0"
+         id="path3768-9"
+         d="m 0,1024.9996 35.26169,0"
+         style="fill:none;stroke:#000000;stroke-width:0.3772082;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0" />
+      <path
+         id="path4190-3"
+         title="sin(x)"
+         d="m 0.17138129,1025.0901 c 0.18430284,-0.3999 0.36860568,-0.8 0.55290852,-1.1919 0.18430286,-0.3921 0.36860569,-0.7762 0.55290859,-1.1447 0.1843028,-0.3686 0.3686057,-0.7216 0.5529085,-1.0521 0.1843028,-0.3303 0.3686057,-0.6383 0.5529085,-0.9175 0.1843029,-0.2794 0.3686057,-0.5299 0.5529085,-0.7468 0.1843029,-0.2172 0.3686057,-0.4004 0.5529086,-0.5466 0.1843028,-0.1461 0.3686056,-0.2549 0.5529085,-0.3244 0.1843028,-0.069 0.3686057,-0.1 0.5529085,-0.09 0.1843029,0.011 0.3686057,0.06 0.5529085,0.1489 0.1843029,0.09 0.3686057,0.217 0.5529086,0.3815 0.1843028,0.1645 0.3686056,0.3655 0.5529085,0.5989 0.1843028,0.2335 0.3686057,0.4995 0.5529085,0.7927 0.1843028,0.2931 0.3686057,0.6135 0.5529085,0.9549 0.1843029,0.3412 0.3686057,0.7034 0.5529086,1.0792 0.1843028,0.3758 0.3686056,0.7653 0.5529085,1.1608 0.1843028,0.3956 0.3686057,0.7969 0.5529085,1.1964 0.1843028,0.3994 0.3686057,0.7969 0.5529085,1.1845 0.1843029,0.3876 0.3686059,0.7653 0.5529088,1.1257 0.184302,0.3603 0.368605,0.7033 0.552908,1.022 0.184303,0.3189 0.368606,0.6135 0.552909,0.8782 0.184303,0.2646 0.368605,0.4992 0.552908,0.6992 0.184303,0.2001 0.368606,0.3653 0.552909,0.4927 0.184303,0.1274 0.368605,0.2168 0.552908,0.2665 0.184303,0.05 0.368606,0.06 0.552909,0.031 0.184303,-0.031 0.368605,-0.1 0.552908,-0.2079 0.184303,-0.1088 0.368606,-0.2552 0.552909,-0.4377 0.184303,-0.1824 0.368606,-0.4005 0.552908,-0.6498 0.184303,-0.2495 0.368606,-0.5301 0.552909,-0.8364 0.184303,-0.3065 0.368606,-0.6385 0.552908,-0.9897 0.184303,-0.3513 0.368606,-0.7217 0.552909,-1.1039 0.184303,-0.3821 0.368606,-0.7762 0.552908,-1.1741 0.184303,-0.398 0.368606,-0.8 0.552909,-1.1979 0.184303,-0.398 0.368606,-0.7919 0.552909,-1.1742 0.184302,-0.3821 0.368605,-0.7525 0.552908,-1.1038 0.184303,-0.3512 0.368606,-0.6833 0.552909,-0.9896 0.184302,-0.3064 0.368605,-0.587 0.552908,-0.8364 0.184303,-0.2494 0.368606,-0.4675 0.552909,-0.6499 0.184302,-0.1825 0.368605,-0.3294 0.552908,-0.4377 0.184303,-0.1088 0.368606,-0.1782 0.552909,-0.208 0.184302,-0.031 0.368605,-0.019 0.552908,0.031 0.184303,0.05 0.368606,0.1392 0.552909,0.2666 0.184303,0.1274 0.368605,0.2927 0.552908,0.4926 0.184303,0.2001 0.368606,0.4347 0.552909,0.6993 0.184303,0.2646 0.368605,0.5594 0.552908,0.8781 0.184303,0.3189 0.368606,0.6618 0.552909,1.0222 0.184303,0.3603 0.368605,0.738 0.552908,1.1256 0.184303,0.3876 0.368606,0.785 0.552909,1.1845 0.184303,0.3994 0.368606,0.8009 0.552908,1.1963 0.184303,0.3955 0.368606,0.7851 0.552909,1.161 0.184303,0.3758 0.368606,0.7379 0.552908,1.0792 0.184303,0.3411 0.368606,0.6616 0.552909,0.9548 0.184303,0.2932 0.368606,0.5592 0.552908,0.7927 0.184303,0.2334 0.368606,0.4343 0.552909,0.5988 0.184303,0.1645 0.368606,0.2926 0.552909,0.3816 0.184302,0.089 0.368605,0.1389 0.552908,0.1489 0.184303,0.011 0.368606,-0.02 0.552909,-0.09 0.184302,-0.069 0.368605,-0.1784 0.552908,-0.3246 0.184303,-0.1461 0.368606,-0.3295 0.552909,-0.5464 0.184302,-0.217 0.368605,-0.4676 0.552908,-0.7469 0.184303,-0.2792 0.368606,-0.5872 0.552909,-0.9177 0.184302,-0.3303 0.368605,-0.6834 0.552908,-1.0519 0.184303,-0.3686 0.368606,-0.7526 0.552909,-1.1446 0.184303,-0.392 0.368605,-0.7921 0.552908,-1.1919"
+         style="fill:none;stroke:#2e0dff;stroke-width:0.30176657;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+         inkscape:connector-curvature="0" />
+      <path
+         inkscape:connector-curvature="0"
+         id="path3768-2-3-7"
+         d="m 0,1040.0689 35.26169,0"
+         style="fill:none;stroke:#c9c9c9;stroke-width:0.19036053;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0" />
+      <path
+         inkscape:connector-curvature="0"
+         id="path3768-1-5-1"
+         d="m 0,1048.373 35.26169,0"
+         style="fill:none;stroke:#c9c9c9;stroke-width:0.19036053;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0" />
+      <path
+         inkscape:connector-curvature="0"
+         id="path3755-4-38-0"
+         d="m 3.860417,1036.1837 0,16.1257"
+         style="fill:none;stroke:#c9c9c9;stroke-width:0.19036053;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" />
+      <path
+         inkscape:connector-curvature="0"
+         id="path3755-4-0-5-8"
+         d="m 7.720835,1036.1837 0,16.1257"
+         style="fill:none;stroke:#c9c9c9;stroke-width:0.19036053;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" />
+      <path
+         inkscape:connector-curvature="0"
+         id="path3755-4-5-0-7"
+         d="m 11.581253,1036.1837 0,16.1257"
+         style="fill:none;stroke:#c9c9c9;stroke-width:0.19036053;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" />
+      <path
+         inkscape:connector-curvature="0"
+         id="path3755-4-9-1-2"
+         d="m 15.441669,1036.1837 0,16.1257"
+         style="fill:none;stroke:#c9c9c9;stroke-width:0.19036053;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" />
+      <path
+         inkscape:connector-curvature="0"
+         id="path3755-4-7-9-8"
+         d="m 19.302086,1036.1837 0,16.1257"
+         style="fill:none;stroke:#c9c9c9;stroke-width:0.19036053;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" />
+      <path
+         inkscape:connector-curvature="0"
+         id="path3755-4-3-3-8"
+         d="m 23.162504,1036.1837 0,16.1257"
+         style="fill:none;stroke:#c9c9c9;stroke-width:0.19036053;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" />
+      <path
+         inkscape:connector-curvature="0"
+         id="path3755-4-1-4-9"
+         d="m 27.022922,1036.1837 0,16.1257"
+         style="fill:none;stroke:#c9c9c9;stroke-width:0.19036053;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" />
+      <path
+         inkscape:connector-curvature="0"
+         id="path3755-4-90-5-2"
+         d="m 30.883338,1036.1837 0,16.1257"
+         style="fill:none;stroke:#c9c9c9;stroke-width:0.19036053;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" />
+      <path
+         inkscape:connector-curvature="0"
+         id="path3755-4-2-0-4"
+         d="m 34.743757,1036.1837 0,16.1257"
+         style="fill:none;stroke:#c9c9c9;stroke-width:0.19036053;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" />
+      <path
+         inkscape:connector-curvature="0"
+         id="path3755-6-0"
+         d="m 0,1036.1837 0,16.1257"
+         style="fill:none;stroke:#000000;stroke-width:0.38072109;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" />
+      <path
+         inkscape:connector-curvature="0"
+         id="path3768-4-0"
+         d="m 0,1052.2209 35.26169,0"
+         style="fill:none;stroke:#000000;stroke-width:0.38072109;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0" />
+      <path
+         inkscape:connector-curvature="0"
+         style="fill:none;stroke:#ff970d;stroke-width:0.30000001;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+         d="m 0.25968796,1051.8993 c 0.18450185,0 0.3690037,0 0.55350556,0 0.18450185,0 0.36900368,0 0.55350558,0 0.1845018,0 0.3690037,0 0.5535055,0 0.1845019,0 0.3690037,0 0.5535056,0 0.1845018,0 0.3690037,0 0.5535055,0 0.1845019,0 0.3690037,0 0.5535056,0 0.1845018,-10e-5 0.3690037,-10e-5 0.5535055,-3e-4 0.1845019,-10e-5 0.3690037,-3e-4 0.5535056,-7e-4 0.1845018,-4e-4 0.3690037,-10e-4 0.5535055,0 0.1845019,0 0.3690038,0 0.5535056,-0.01 0.1845019,0 0.3690037,-0.01 0.5535056,-0.011 0.1845018,-0.01 0.3690037,-0.012 0.5535055,-0.022 0.1845019,-0.01 0.3690037,-0.023 0.5535056,-0.041 0.1845018,-0.018 0.3690037,-0.041 0.5535055,-0.072 0.1845019,-0.031 0.3690037,-0.069 0.5535056,-0.1174 0.1845018,-0.049 0.3690037,-0.1081 0.5535055,-0.1816 0.1845019,-0.073 0.3690037,-0.1613 0.5535056,-0.267 0.1845018,-0.1057 0.3690036,-0.2294 0.5535056,-0.3745 0.184502,-0.1451 0.369003,-0.3119 0.553505,-0.5028 0.184502,-0.1909 0.369004,-0.4062 0.553506,-0.6472 0.184502,-0.241 0.369003,-0.5079 0.553505,-0.8001 0.184502,-0.2922 0.369004,-0.6099 0.553506,-0.9503 0.184502,-0.3405 0.369004,-0.7038 0.553505,-1.0848 0.184502,-0.3811 0.369004,-0.7798 0.553506,-1.1888 0.184502,-0.409 0.369004,-0.8281 0.553506,-1.2479 0.184501,-0.4198 0.369003,-0.8402 0.553505,-1.2503 0.184502,-0.41 0.369004,-0.8095 0.553506,-1.1872 0.184502,-0.3777 0.369003,-0.7333 0.553505,-1.0561 0.184502,-0.3227 0.369004,-0.6123 0.553506,-0.8596 0.184502,-0.2473 0.369003,-0.452 0.553505,-0.6075 0.184502,-0.1555 0.369004,-0.2614 0.553506,-0.3145 0.184502,-0.053 0.369004,-0.053 0.553505,0 0.184502,0.053 0.369004,0.1591 0.553506,0.3145 0.184502,0.1554 0.369004,0.3603 0.553506,0.6075 0.184501,0.2472 0.369003,0.537 0.553505,0.8596 0.184502,0.3227 0.369004,0.6784 0.553506,1.0561 0.184502,0.3776 0.369003,0.7772 0.553505,1.1872 0.184502,0.4101 0.369004,0.8305 0.553506,1.2503 0.184502,0.4198 0.369003,0.8389 0.553505,1.2479 0.184502,0.409 0.369004,0.8077 0.553506,1.1888 0.184502,0.381 0.369004,0.7443 0.553505,1.0848 0.184502,0.3405 0.369004,0.6581 0.553506,0.9503 0.184502,0.2923 0.369004,0.5591 0.553506,0.8001 0.184501,0.241 0.369003,0.4563 0.553505,0.6472 0.184502,0.191 0.369004,0.3576 0.553506,0.5028 0.184502,0.1452 0.369003,0.2688 0.553505,0.3745 0.184502,0.1057 0.369004,0.1934 0.553506,0.267 0.184502,0.074 0.369003,0.1328 0.553505,0.1816 0.184502,0.049 0.369004,0.087 0.553506,0.1174 0.184502,0.031 0.369004,0.054 0.553505,0.072 0.184502,0.018 0.369004,0.031 0.553506,0.041 0.184502,0.01 0.369004,0.017 0.553506,0.022 0.184501,0.01 0.369003,0.01 0.553505,0.011 0.184502,0 0.369004,0 0.553506,0.01 0.184502,10e-4 0.369003,0 0.553505,0 0.184502,4e-4 0.369004,6e-4 0.553506,7e-4 0.184502,2e-4 0.369003,2e-4 0.553505,3e-4 0.184502,0 0.369004,0 0.553506,0 0.184502,0 0.369004,0 0.553505,0 0.184502,0 0.369004,0 0.553506,0 0.184502,0 0.369004,0 0.553506,0 0.184501,0 0.369003,0 0.553505,0 0.184502,0 0.369004,0 0.553506,0"
+         title="pow(sin(x), 10)"
+         id="path7506-5" />
+    </g>
+  </g>
+  <g
+     inkscape:label="Layer 1"
+     inkscape:groupmode="layer"
+     id="layer1"
+     transform="translate(0,-1016.9291)"
+     style="display:inline">
+    <rect
+       style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="rect4735"
+       width="21.984022"
+       height="15.841428"
+       x="-0.12931778"
+       y="1017.1877" />
+    <path
+       style="fill:none;stroke:#c9c9c9;stroke-width:0.1497674;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
+       d="m -0.38664415,1020.9238 22.23492015,0"
+       id="path3768-2"
+       inkscape:connector-curvature="0" />
+    <path
+       style="fill:none;stroke:#c9c9c9;stroke-width:0.14911523;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
+       d="m -0.25776149,1029.0753 22.04169149,0"
+       id="path3768-1"
+       inkscape:connector-curvature="0" />
+    <path
+       style="fill:none;stroke:#c9c9c9;stroke-width:0.18860409;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+       d="m 3.8604174,1017.11 0,15.8294"
+       id="path3755-4"
+       inkscape:connector-curvature="0" />
+    <path
+       style="fill:none;stroke:#c9c9c9;stroke-width:0.18860409;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+       d="m 7.7208349,1017.11 0,15.8294"
+       id="path3755-4-0"
+       inkscape:connector-curvature="0" />
+    <path
+       style="fill:none;stroke:#c9c9c9;stroke-width:0.18860409;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+       d="m 11.581253,1017.11 0,15.8294"
+       id="path3755-4-5"
+       inkscape:connector-curvature="0" />
+    <path
+       style="fill:none;stroke:#c9c9c9;stroke-width:0.18860409;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+       d="m 15.441669,1017.11 0,15.8294"
+       id="path3755-4-9"
+       inkscape:connector-curvature="0" />
+    <path
+       style="fill:none;stroke:#c9c9c9;stroke-width:0.18860409;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+       d="m 19.302086,1017.11 0,15.8294"
+       id="path3755-4-7"
+       inkscape:connector-curvature="0" />
+    <path
+       style="fill:none;stroke:#000000;stroke-width:0.29803008;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
+       d="m -0.25689803,1024.9996 22.01207903,0"
+       id="path3768"
+       inkscape:connector-curvature="0" />
+    <path
+       inkscape:connector-curvature="0"
+       style="fill:none;stroke:#2e0dff;stroke-width:0.802;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+       d="m 0.17138129,1025.0901 c 0.18430284,-0.3999 0.36860568,-0.8 0.55290852,-1.1919 0.18430286,-0.3921 0.36860569,-0.7762 0.55290859,-1.1447 0.1843028,-0.3686 0.3686057,-0.7216 0.5529085,-1.0521 0.1843028,-0.3303 0.3686057,-0.6383 0.5529085,-0.9175 0.1843029,-0.2794 0.3686057,-0.5299 0.5529085,-0.7468 0.1843029,-0.2172 0.3686057,-0.4004 0.5529086,-0.5466 0.1843028,-0.1461 0.3686056,-0.2549 0.5529085,-0.3244 0.1843028,-0.069 0.3686057,-0.1 0.5529085,-0.09 0.1843029,0.011 0.3686057,0.06 0.5529085,0.1489 0.1843029,0.09 0.3686057,0.217 0.5529086,0.3815 0.1843028,0.1645 0.3686056,0.3655 0.5529085,0.5989 0.1843028,0.2335 0.3686057,0.4995 0.5529085,0.7927 0.1843028,0.2931 0.3686057,0.6135 0.5529085,0.9549 0.1843029,0.3412 0.3686057,0.7034 0.5529086,1.0792 0.1843028,0.3758 0.3686056,0.7653 0.5529085,1.1608 0.1843028,0.3956 0.3686057,0.7969 0.5529085,1.1964 0.1843028,0.3994 0.3686057,0.7969 0.5529085,1.1845 0.1843029,0.3876 0.3686059,0.7653 0.5529088,1.1257 0.184302,0.3603 0.368605,0.7033 0.552908,1.022 0.184303,0.3189 0.368606,0.6135 0.552909,0.8782 0.184303,0.2646 0.368605,0.4992 0.552908,0.6992 0.184303,0.2001 0.368606,0.3653 0.552909,0.4927 0.184303,0.1274 0.368605,0.2168 0.552908,0.2665 0.184303,0.05 0.368606,0.06 0.552909,0.031 0.184303,-0.031 0.368605,-0.1 0.552908,-0.2079 0.184303,-0.1088 0.368606,-0.2552 0.552909,-0.4377 0.184303,-0.1824 0.368606,-0.4005 0.552908,-0.6498 0.184303,-0.2495 0.368606,-0.5301 0.552909,-0.8364 0.184303,-0.3065 0.368606,-0.6385 0.552908,-0.9897 0.184303,-0.3513 0.368606,-0.7217 0.552909,-1.1039 0.184303,-0.3821 0.368606,-0.7762 0.552908,-1.1741 0.184303,-0.398 0.368606,-0.8 0.552909,-1.1979 0.184303,-0.398 0.368606,-0.7919 0.552909,-1.1742 0.184302,-0.3821 0.368605,-0.7525 0.552908,-1.1038 0.184303,-0.3512 0.368606,-0.6833 0.552909,-0.9896 0.184302,-0.3064 0.368605,-0.587 0.552908,-0.8364 0.184303,-0.2494 0.368606,-0.4675 0.552909,-0.6499 0.184302,-0.1825 0.368605,-0.3294 0.552908,-0.4377 0.184303,-0.1088 0.368606,-0.1782 0.552909,-0.208"
+       title="sin(x)"
+       id="path4190"
+       sodipodi:nodetypes="ccccccccccscccsccsccccscccccccccccccsccc" />
+    <rect
+       style="fill:none;stroke:#000000;stroke-width:0.29496232;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+       id="rect3905"
+       width="22.075964"
+       height="15.974718"
+       x="-0.19596301"
+       y="1017.121" />
+    <rect
+       style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="rect4735-9"
+       width="21.984022"
+       height="15.841428"
+       x="3.2648256"
+       y="1021.9644" />
+    <path
+       style="fill:none;stroke:#c9c9c9;stroke-width:0.1497674;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
+       d="m 3.0074993,1025.7005 22.2349197,0"
+       id="path3768-2-9"
+       inkscape:connector-curvature="0" />
+    <path
+       style="fill:none;stroke:#c9c9c9;stroke-width:0.14911523;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
+       d="m 3.1363819,1033.852 22.0416911,0"
+       id="path3768-1-4"
+       inkscape:connector-curvature="0" />
+    <path
+       style="fill:none;stroke:#c9c9c9;stroke-width:0.18860409;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+       d="m 7.2545608,1021.8867 0,15.8294"
+       id="path3755-4-2"
+       inkscape:connector-curvature="0" />
+    <path
+       style="fill:none;stroke:#c9c9c9;stroke-width:0.18860409;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+       d="m 11.114978,1021.8867 0,15.8294"
+       id="path3755-4-0-2"
+       inkscape:connector-curvature="0" />
+    <path
+       style="fill:none;stroke:#c9c9c9;stroke-width:0.18860409;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+       d="m 14.975396,1021.8867 0,15.8294"
+       id="path3755-4-5-3"
+       inkscape:connector-curvature="0" />
+    <path
+       style="fill:none;stroke:#c9c9c9;stroke-width:0.18860409;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+       d="m 18.835812,1021.8867 0,15.8294"
+       id="path3755-4-9-8"
+       inkscape:connector-curvature="0" />
+    <path
+       style="fill:none;stroke:#c9c9c9;stroke-width:0.18860409;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+       d="m 22.696229,1021.8867 0,15.8294"
+       id="path3755-4-7-9"
+       inkscape:connector-curvature="0" />
+    <path
+       style="fill:none;stroke:#000000;stroke-width:0.29803008;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
+       d="m 3.1372454,1029.7763 22.0120786,0"
+       id="path3768-7"
+       inkscape:connector-curvature="0" />
+    <path
+       inkscape:connector-curvature="0"
+       style="fill:none;stroke:#2e0dff;stroke-width:0.802;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+       d="m 3.5655247,1029.8668 c 0.1843028,-0.3999 0.3686057,-0.8 0.5529085,-1.1919 0.1843029,-0.3921 0.3686057,-0.7762 0.5529086,-1.1447 0.1843028,-0.3686 0.3686057,-0.7216 0.5529085,-1.0521 0.1843028,-0.3303 0.3686057,-0.6383 0.5529085,-0.9175 0.1843029,-0.2794 0.3686057,-0.5299 0.5529085,-0.7468 0.1843029,-0.2172 0.3686057,-0.4004 0.5529086,-0.5466 0.1843028,-0.1461 0.3686056,-0.2549 0.5529085,-0.3244 0.1843028,-0.069 0.3686057,-0.1 0.5529085,-0.09 0.1843029,0.011 0.3686057,0.06 0.5529085,0.1489 0.1843029,0.09 0.3686057,0.217 0.5529086,0.3815 0.1843028,0.1645 0.3686056,0.3655 0.5529085,0.5989 0.1843028,0.2335 0.3686055,0.4995 0.5529085,0.7927 0.184303,0.2931 0.368606,0.6135 0.552909,0.9549 0.184302,0.3412 0.368605,0.7034 0.552908,1.0792 0.184303,0.3758 0.368606,0.7653 0.552909,1.1608 0.184302,0.3956 0.368605,0.7969 0.552908,1.1964 0.184303,0.3994 0.368606,0.7969 0.552909,1.1845 0.184303,0.3876 0.368606,0.7653 0.552908,1.1257 0.184302,0.3603 0.368605,0.7033 0.552908,1.022 0.184303,0.3189 0.368606,0.6135 0.552909,0.8782 0.184303,0.2646 0.368605,0.4992 0.552908,0.6992 0.184303,0.2001 0.368606,0.3653 0.552909,0.4927 0.184303,0.1274 0.368605,0.2168 0.552908,0.2665 0.184303,0.05 0.368606,0.06 0.552909,0.031 0.184303,-0.031 0.368605,-0.1 0.552908,-0.2079 0.184303,-0.1088 0.368606,-0.2552 0.552909,-0.4377 0.184303,-0.1824 0.368606,-0.4005 0.552908,-0.6498 0.184303,-0.2495 0.368606,-0.5301 0.552909,-0.8364 0.184303,-0.3065 0.368606,-0.6385 0.552908,-0.9897 0.184303,-0.3513 0.368606,-0.7217 0.552909,-1.1039 0.184303,-0.3821 0.368606,-0.7762 0.552908,-1.1741 0.184303,-0.398 0.368606,-0.8 0.552909,-1.1979 0.184303,-0.398 0.368606,-0.7919 0.552909,-1.1742 0.184302,-0.3821 0.368605,-0.7525 0.552908,-1.1038 0.184303,-0.3512 0.368606,-0.6833 0.552909,-0.9896 0.184302,-0.3064 0.368605,-0.587 0.552908,-0.8364 0.184303,-0.2494 0.368606,-0.4675 0.552909,-0.6499 0.184302,-0.1825 0.368605,-0.3294 0.552908,-0.4377 0.184303,-0.1088 0.368606,-0.1782 0.552909,-0.208"
+       title="sin(x)"
+       id="path4190-0"
+       sodipodi:nodetypes="ccccccccccscccsccsccccscccccccccccccsccc" />
+    <rect
+       style="fill:none;stroke:#000000;stroke-width:0.29496232;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+       id="rect3905-8"
+       width="22.075964"
+       height="15.974718"
+       x="3.1981804"
+       y="1021.8977" />
+    <rect
+       style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="rect4735-2"
+       width="21.984022"
+       height="15.841428"
+       x="6.5999274"
+       y="1026.7411" />
+    <path
+       style="fill:none;stroke:#c9c9c9;stroke-width:0.1497674;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
+       d="m 6.3426012,1030.4772 22.2349198,0"
+       id="path3768-2-3"
+       inkscape:connector-curvature="0" />
+    <path
+       style="fill:none;stroke:#c9c9c9;stroke-width:0.14911523;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
+       d="m 6.4714839,1038.6287 22.0416911,0"
+       id="path3768-1-3"
+       inkscape:connector-curvature="0" />
+    <path
+       style="fill:none;stroke:#c9c9c9;stroke-width:0.18860409;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+       d="m 10.589663,1026.6634 0,15.8294"
+       id="path3755-4-1"
+       inkscape:connector-curvature="0" />
+    <path
+       style="fill:none;stroke:#c9c9c9;stroke-width:0.18860409;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+       d="m 14.45008,1026.6634 0,15.8294"
+       id="path3755-4-0-3"
+       inkscape:connector-curvature="0" />
+    <path
+       style="fill:none;stroke:#c9c9c9;stroke-width:0.18860409;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+       d="m 18.310498,1026.6634 0,15.8294"
+       id="path3755-4-5-1"
+       inkscape:connector-curvature="0" />
+    <path
+       style="fill:none;stroke:#c9c9c9;stroke-width:0.18860409;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+       d="m 22.170914,1026.6634 0,15.8294"
+       id="path3755-4-9-88"
+       inkscape:connector-curvature="0" />
+    <path
+       style="fill:none;stroke:#c9c9c9;stroke-width:0.18860409;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+       d="m 26.031331,1026.6634 0,15.8294"
+       id="path3755-4-7-2"
+       inkscape:connector-curvature="0" />
+    <path
+       style="fill:none;stroke:#000000;stroke-width:0.29803008;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
+       d="m 6.4723474,1034.553 22.0120786,0"
+       id="path3768-98"
+       inkscape:connector-curvature="0" />
+    <path
+       inkscape:connector-curvature="0"
+       style="fill:none;stroke:#2e0dff;stroke-width:0.802;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+       d="m 6.9006267,1034.6435 c 0.1843028,-0.3999 0.3686057,-0.8 0.5529085,-1.1919 0.1843029,-0.3921 0.3686057,-0.7762 0.5529086,-1.1447 0.1843028,-0.3686 0.3686057,-0.7216 0.5529085,-1.0521 0.1843028,-0.3303 0.3686057,-0.6383 0.5529085,-0.9175 0.1843029,-0.2794 0.3686057,-0.5299 0.5529085,-0.7468 0.1843029,-0.2172 0.3686057,-0.4004 0.5529087,-0.5466 0.184303,-0.1461 0.368605,-0.2549 0.552908,-0.3244 0.184303,-0.069 0.368606,-0.1 0.552909,-0.09 0.184303,0.011 0.368606,0.06 0.552908,0.1489 0.184303,0.09 0.368606,0.217 0.552909,0.3815 0.184303,0.1645 0.368606,0.3655 0.552908,0.5989 0.184303,0.2335 0.368606,0.4995 0.552909,0.7927 0.184303,0.2931 0.368606,0.6135 0.552909,0.9549 0.184302,0.3412 0.368605,0.7034 0.552908,1.0792 0.184303,0.3758 0.368606,0.7653 0.552909,1.1608 0.184302,0.3956 0.368605,0.7969 0.552908,1.1964 0.184303,0.3994 0.368606,0.7969 0.552909,1.1845 0.184303,0.3876 0.368605,0.7653 0.552908,1.1257 0.184302,0.3603 0.368605,0.7033 0.552908,1.022 0.184303,0.3189 0.368606,0.6135 0.552909,0.8782 0.184303,0.2646 0.368605,0.4992 0.552908,0.6992 0.184303,0.2001 0.368606,0.3653 0.552909,0.4927 0.184303,0.1274 0.368605,0.2168 0.552908,0.2665 0.184303,0.05 0.368606,0.06 0.552909,0.031 0.184303,-0.031 0.368605,-0.1 0.552908,-0.2079 0.184303,-0.1088 0.368606,-0.2552 0.552909,-0.4377 0.184303,-0.1824 0.368606,-0.4005 0.552908,-0.6498 0.184303,-0.2495 0.368606,-0.5301 0.552909,-0.8364 0.184303,-0.3065 0.368606,-0.6385 0.552908,-0.9897 0.184303,-0.3513 0.368606,-0.7217 0.552909,-1.1039 0.184303,-0.3821 0.368606,-0.7762 0.552908,-1.1741 0.184303,-0.398 0.368606,-0.8 0.552909,-1.1979 0.184303,-0.398 0.368606,-0.7919 0.552909,-1.1742 0.184302,-0.3821 0.368605,-0.7525 0.552908,-1.1038 0.184303,-0.3512 0.368606,-0.6833 0.552909,-0.9896 0.184302,-0.3064 0.368605,-0.587 0.552908,-0.8364 0.184303,-0.2494 0.368606,-0.4675 0.552909,-0.6499 0.184302,-0.1825 0.368605,-0.3294 0.552908,-0.4377 0.184303,-0.1088 0.368606,-0.1782 0.552909,-0.208"
+       title="sin(x)"
+       id="path4190-8"
+       sodipodi:nodetypes="ccccccccccscccsccsccccscccccccccccccsccc" />
+    <rect
+       style="fill:none;stroke:#000000;stroke-width:0.29496232;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+       id="rect3905-7"
+       width="22.075964"
+       height="15.974718"
+       x="6.5332823"
+       y="1026.6744" />
+    <rect
+       style="fill:#f6e879;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="rect4735-98"
+       width="21.984022"
+       height="15.841428"
+       x="9.935029"
+       y="1031.5178" />
+    <path
+       style="fill:none;stroke:#c9c9c9;stroke-width:0.1497674;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
+       d="m 9.6777028,1035.2539 22.2349202,0"
+       id="path3768-2-4"
+       inkscape:connector-curvature="0" />
+    <path
+       style="fill:none;stroke:#c9c9c9;stroke-width:0.14911523;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
+       d="m 9.8065855,1043.4054 22.0416915,0"
+       id="path3768-1-6"
+       inkscape:connector-curvature="0" />
+    <path
+       style="fill:none;stroke:#c9c9c9;stroke-width:0.18860409;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+       d="m 13.924764,1031.4401 0,15.8294"
+       id="path3755-4-54"
+       inkscape:connector-curvature="0" />
+    <path
+       style="fill:none;stroke:#c9c9c9;stroke-width:0.18860409;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+       d="m 17.785182,1031.4401 0,15.8294"
+       id="path3755-4-0-5"
+       inkscape:connector-curvature="0" />
+    <path
+       style="fill:none;stroke:#c9c9c9;stroke-width:0.18860409;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+       d="m 21.6456,1031.4401 0,15.8294"
+       id="path3755-4-5-9"
+       inkscape:connector-curvature="0" />
+    <path
+       style="fill:none;stroke:#c9c9c9;stroke-width:0.18860409;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+       d="m 25.506016,1031.4401 0,15.8294"
+       id="path3755-4-9-87"
+       inkscape:connector-curvature="0" />
+    <path
+       style="fill:none;stroke:#c9c9c9;stroke-width:0.18860409;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+       d="m 29.366433,1031.4401 0,15.8294"
+       id="path3755-4-7-4"
+       inkscape:connector-curvature="0" />
+    <path
+       style="fill:none;stroke:#000000;stroke-width:0.29803008;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
+       d="m 9.807449,1039.3297 22.012079,0"
+       id="path3768-6"
+       inkscape:connector-curvature="0" />
+    <path
+       inkscape:connector-curvature="0"
+       style="fill:none;stroke:#2e0dff;stroke-width:0.802;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+       d="m 10.235728,1039.4202 c 0.184303,-0.3999 0.368606,-0.8 0.552909,-1.1919 0.184303,-0.3921 0.368605,-0.7762 0.552908,-1.1447 0.184303,-0.3686 0.368606,-0.7216 0.552909,-1.0521 0.184303,-0.3303 0.368606,-0.6383 0.552908,-0.9175 0.184303,-0.2794 0.368606,-0.5299 0.552909,-0.7468 0.184303,-0.2172 0.368606,-0.4004 0.552908,-0.5466 0.184303,-0.1461 0.368606,-0.2549 0.552909,-0.3244 0.184303,-0.069 0.368606,-0.1 0.552909,-0.09 0.184302,0.011 0.368605,0.06 0.552908,0.1489 0.184303,0.09 0.368606,0.217 0.552909,0.3815 0.184302,0.1645 0.368605,0.3655 0.552908,0.5989 0.184303,0.2335 0.368606,0.4995 0.552909,0.7927 0.184302,0.2931 0.368605,0.6135 0.552908,0.9549 0.184303,0.3412 0.368606,0.7034 0.552909,1.0792 0.184302,0.3758 0.368605,0.7653 0.552908,1.1608 0.184303,0.3956 0.368606,0.7969 0.552909,1.1964 0.184302,0.3994 0.368605,0.7969 0.552908,1.1845 0.184303,0.3876 0.368606,0.7653 0.552909,1.1257 0.184302,0.3603 0.368605,0.7033 0.552908,1.022 0.184303,0.3189 0.368606,0.6135 0.552909,0.8782 0.184303,0.2646 0.368605,0.4992 0.552908,0.6992 0.184303,0.2001 0.368606,0.3653 0.552909,0.4927 0.184303,0.1274 0.368605,0.2168 0.552908,0.2665 0.184303,0.05 0.368606,0.06 0.552909,0.031 0.184303,-0.031 0.368605,-0.1 0.552908,-0.2079 0.184303,-0.1088 0.368606,-0.2552 0.552909,-0.4377 0.184303,-0.1824 0.368606,-0.4005 0.552908,-0.6498 0.184303,-0.2495 0.368606,-0.5301 0.552909,-0.8364 0.184303,-0.3065 0.368606,-0.6385 0.552908,-0.9897 0.184303,-0.3513 0.368606,-0.7217 0.552909,-1.1039 0.184303,-0.3821 0.368606,-0.7762 0.552908,-1.1741 0.184303,-0.398 0.368606,-0.8 0.552909,-1.1979 0.184303,-0.398 0.368606,-0.7919 0.552909,-1.1742 0.184302,-0.3821 0.368605,-0.7525 0.552908,-1.1038 0.184303,-0.3512 0.368606,-0.6833 0.552909,-0.9896 0.184302,-0.3064 0.368605,-0.587 0.552908,-0.8364 0.184303,-0.2494 0.368606,-0.4675 0.552909,-0.6499 0.184302,-0.1825 0.368605,-0.3294 0.552908,-0.4377 0.184303,-0.1088 0.368606,-0.1782 0.552909,-0.208"
+       title="sin(x)"
+       id="path4190-84"
+       sodipodi:nodetypes="ccccccccccscccsccsccccscccccccccccccsccc" />
+    <rect
+       style="fill:none;stroke:#000000;stroke-width:0.29496232000000000;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+       id="rect3905-86"
+       width="22.075964"
+       height="15.974718"
+       x="9.8683844"
+       y="1031.451" />
+    <rect
+       style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="rect4735-23"
+       width="21.984022"
+       height="15.841428"
+       x="13.270129"
+       y="1036.2946" />
+    <path
+       style="fill:none;stroke:#c9c9c9;stroke-width:0.1497674;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
+       d="m 13.012803,1040.0306 22.23492,0"
+       id="path3768-2-5"
+       inkscape:connector-curvature="0" />
+    <path
+       style="fill:none;stroke:#c9c9c9;stroke-width:0.14911523;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
+       d="m 13.141686,1048.1821 22.041691,0"
+       id="path3768-1-5"
+       inkscape:connector-curvature="0" />
+    <path
+       style="fill:none;stroke:#c9c9c9;stroke-width:0.18860409;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+       d="m 17.259864,1036.2168 0,15.8294"
+       id="path3755-4-6"
+       inkscape:connector-curvature="0" />
+    <path
+       style="fill:none;stroke:#c9c9c9;stroke-width:0.18860409;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+       d="m 21.120282,1036.2168 0,15.8294"
+       id="path3755-4-0-35"
+       inkscape:connector-curvature="0" />
+    <path
+       style="fill:none;stroke:#c9c9c9;stroke-width:0.18860409;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+       d="m 24.9807,1036.2168 0,15.8294"
+       id="path3755-4-5-82"
+       inkscape:connector-curvature="0" />
+    <path
+       style="fill:none;stroke:#c9c9c9;stroke-width:0.18860409;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+       d="m 28.841116,1036.2168 0,15.8294"
+       id="path3755-4-9-5"
+       inkscape:connector-curvature="0" />
+    <path
+       style="fill:none;stroke:#c9c9c9;stroke-width:0.18860409;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+       d="m 32.701533,1036.2168 0,15.8294"
+       id="path3755-4-7-7"
+       inkscape:connector-curvature="0" />
+    <path
+       style="fill:none;stroke:#000000;stroke-width:0.29803008;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
+       d="m 13.142549,1044.1064 22.012079,0"
+       id="path3768-25"
+       inkscape:connector-curvature="0" />
+    <path
+       inkscape:connector-curvature="0"
+       style="fill:none;stroke:#2e0dff;stroke-width:0.802;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+       d="m 13.570828,1044.1969 c 0.184303,-0.3999 0.368606,-0.8 0.552909,-1.1919 0.184303,-0.3921 0.368605,-0.7762 0.552908,-1.1447 0.184303,-0.3686 0.368606,-0.7216 0.552909,-1.0521 0.184303,-0.3303 0.368606,-0.6383 0.552908,-0.9175 0.184303,-0.2794 0.368606,-0.5299 0.552909,-0.7468 0.184303,-0.2172 0.368606,-0.4004 0.552908,-0.5466 0.184303,-0.1461 0.368606,-0.2549 0.552909,-0.3244 0.184303,-0.069 0.368606,-0.1 0.552909,-0.09 0.184302,0.011 0.368605,0.06 0.552908,0.1489 0.184303,0.09 0.368606,0.217 0.552909,0.3815 0.184302,0.1645 0.368605,0.3655 0.552908,0.5989 0.184303,0.2335 0.368606,0.4995 0.552909,0.7927 0.184302,0.2931 0.368605,0.6135 0.552908,0.9549 0.184303,0.3412 0.368606,0.7034 0.552909,1.0792 0.184303,0.3758 0.368605,0.7653 0.552908,1.1608 0.184303,0.3956 0.368606,0.7969 0.552909,1.1964 0.184303,0.3994 0.368605,0.7969 0.552908,1.1845 0.184303,0.3876 0.368606,0.7653 0.552909,1.1257 0.184302,0.3603 0.368605,0.7033 0.552908,1.022"
+       title="sin(x)"
+       id="path4190-80"
+       sodipodi:nodetypes="ccccccccccscccsccscc" />
+    <rect
+       style="fill:none;stroke:#000000;stroke-width:0.29496232;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+       id="rect3905-9"
+       width="22.075964"
+       height="15.974718"
+       x="13.203484"
+       y="1036.2278" />
+  </g>
+</svg>
diff --git a/icons/view-displaymode-last_segment.svg b/icons/view-displaymode-last_segment.svg
new file mode 100644 (file)
index 0000000..4c4bf53
--- /dev/null
@@ -0,0 +1,521 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<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"
+   width="35.433071"
+   height="35.433071"
+   id="svg2"
+   version="1.1"
+   inkscape:version="0.48.5 r10040"
+   sodipodi:docname="view-displaymode-last_segment.svg">
+  <sodipodi:namedview
+     id="base"
+     pagecolor="#ffffff"
+     bordercolor="#666666"
+     borderopacity="1.0"
+     inkscape:pageopacity="0.0"
+     inkscape:pageshadow="2"
+     inkscape:zoom="15.465778"
+     inkscape:cx="7.8560557"
+     inkscape:cy="17.231594"
+     inkscape:document-units="px"
+     inkscape:current-layer="layer1"
+     showgrid="false"
+     units="mm"
+     inkscape:window-width="1369"
+     inkscape:window-height="743"
+     inkscape:window-x="46"
+     inkscape:window-y="65"
+     inkscape:window-maximized="0" />
+  <defs
+     id="defs4" />
+  <metadata
+     id="metadata7">
+    <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 />
+      </cc:Work>
+    </rdf:RDF>
+  </metadata>
+  <g
+     inkscape:groupmode="layer"
+     id="layer2"
+     inkscape:label="Layer"
+     style="display:none">
+    <g
+       transform="translate(0,-1016.9291)"
+       style="display:inline"
+       id="g7555-6">
+      <path
+         inkscape:connector-curvature="0"
+         id="path3768-2-3-5-9"
+         d="m 0,1044.2466 35.26169,0"
+         style="fill:none;stroke:#c9c9c9;stroke-width:0.19036053;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0" />
+      <path
+         inkscape:connector-curvature="0"
+         id="path3768-2-6"
+         d="m 0,1020.9238 35.26169,0"
+         style="fill:none;stroke:#c9c9c9;stroke-width:0.18860409;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0" />
+      <path
+         inkscape:connector-curvature="0"
+         id="path3768-1-9"
+         d="m 0,1029.0753 35.26169,0"
+         style="fill:none;stroke:#c9c9c9;stroke-width:0.18860409;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0" />
+      <path
+         inkscape:connector-curvature="0"
+         id="path3755-4-29"
+         d="m 3.8604174,1017.11 0,15.8294"
+         style="fill:none;stroke:#c9c9c9;stroke-width:0.18860409;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" />
+      <path
+         inkscape:connector-curvature="0"
+         id="path3755-4-0-6"
+         d="m 7.7208349,1017.11 0,15.8294"
+         style="fill:none;stroke:#c9c9c9;stroke-width:0.18860409;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" />
+      <path
+         inkscape:connector-curvature="0"
+         id="path3755-4-5-8"
+         d="m 11.581253,1017.11 0,15.8294"
+         style="fill:none;stroke:#c9c9c9;stroke-width:0.18860409;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" />
+      <path
+         inkscape:connector-curvature="0"
+         id="path3755-4-9-14"
+         d="m 15.441669,1017.11 0,15.8294"
+         style="fill:none;stroke:#c9c9c9;stroke-width:0.18860409;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" />
+      <path
+         inkscape:connector-curvature="0"
+         id="path3755-4-7-90"
+         d="m 19.302086,1017.11 0,15.8294"
+         style="fill:none;stroke:#c9c9c9;stroke-width:0.18860409;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" />
+      <path
+         inkscape:connector-curvature="0"
+         id="path3755-4-3-32"
+         d="m 23.162504,1017.11 0,15.8294"
+         style="fill:none;stroke:#c9c9c9;stroke-width:0.18860409;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" />
+      <path
+         inkscape:connector-curvature="0"
+         id="path3755-4-1-3"
+         d="m 27.022922,1017.11 0,15.8294"
+         style="fill:none;stroke:#c9c9c9;stroke-width:0.18860409;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" />
+      <path
+         inkscape:connector-curvature="0"
+         id="path3755-4-90-6"
+         d="m 30.883338,1017.11 0,15.8294"
+         style="fill:none;stroke:#c9c9c9;stroke-width:0.18860409;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" />
+      <path
+         inkscape:connector-curvature="0"
+         id="path3755-4-2-4"
+         d="m 34.743757,1017.11 0,15.8294"
+         style="fill:none;stroke:#c9c9c9;stroke-width:0.18860409;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" />
+      <path
+         inkscape:connector-curvature="0"
+         id="path3755-49"
+         d="m 0,1017.11 0,15.8294"
+         style="fill:none;stroke:#000000;stroke-width:0.3772082;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" />
+      <path
+         inkscape:connector-curvature="0"
+         id="path3768-9"
+         d="m 0,1024.9996 35.26169,0"
+         style="fill:none;stroke:#000000;stroke-width:0.3772082;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0" />
+      <path
+         id="path4190-3"
+         title="sin(x)"
+         d="m 0.17138129,1025.0901 c 0.18430284,-0.3999 0.36860568,-0.8 0.55290852,-1.1919 0.18430286,-0.3921 0.36860569,-0.7762 0.55290859,-1.1447 0.1843028,-0.3686 0.3686057,-0.7216 0.5529085,-1.0521 0.1843028,-0.3303 0.3686057,-0.6383 0.5529085,-0.9175 0.1843029,-0.2794 0.3686057,-0.5299 0.5529085,-0.7468 0.1843029,-0.2172 0.3686057,-0.4004 0.5529086,-0.5466 0.1843028,-0.1461 0.3686056,-0.2549 0.5529085,-0.3244 0.1843028,-0.069 0.3686057,-0.1 0.5529085,-0.09 0.1843029,0.011 0.3686057,0.06 0.5529085,0.1489 0.1843029,0.09 0.3686057,0.217 0.5529086,0.3815 0.1843028,0.1645 0.3686056,0.3655 0.5529085,0.5989 0.1843028,0.2335 0.3686057,0.4995 0.5529085,0.7927 0.1843028,0.2931 0.3686057,0.6135 0.5529085,0.9549 0.1843029,0.3412 0.3686057,0.7034 0.5529086,1.0792 0.1843028,0.3758 0.3686056,0.7653 0.5529085,1.1608 0.1843028,0.3956 0.3686057,0.7969 0.5529085,1.1964 0.1843028,0.3994 0.3686057,0.7969 0.5529085,1.1845 0.1843029,0.3876 0.3686059,0.7653 0.5529088,1.1257 0.184302,0.3603 0.368605,0.7033 0.552908,1.022 0.184303,0.3189 0.368606,0.6135 0.552909,0.8782 0.184303,0.2646 0.368605,0.4992 0.552908,0.6992 0.184303,0.2001 0.368606,0.3653 0.552909,0.4927 0.184303,0.1274 0.368605,0.2168 0.552908,0.2665 0.184303,0.05 0.368606,0.06 0.552909,0.031 0.184303,-0.031 0.368605,-0.1 0.552908,-0.2079 0.184303,-0.1088 0.368606,-0.2552 0.552909,-0.4377 0.184303,-0.1824 0.368606,-0.4005 0.552908,-0.6498 0.184303,-0.2495 0.368606,-0.5301 0.552909,-0.8364 0.184303,-0.3065 0.368606,-0.6385 0.552908,-0.9897 0.184303,-0.3513 0.368606,-0.7217 0.552909,-1.1039 0.184303,-0.3821 0.368606,-0.7762 0.552908,-1.1741 0.184303,-0.398 0.368606,-0.8 0.552909,-1.1979 0.184303,-0.398 0.368606,-0.7919 0.552909,-1.1742 0.184302,-0.3821 0.368605,-0.7525 0.552908,-1.1038 0.184303,-0.3512 0.368606,-0.6833 0.552909,-0.9896 0.184302,-0.3064 0.368605,-0.587 0.552908,-0.8364 0.184303,-0.2494 0.368606,-0.4675 0.552909,-0.6499 0.184302,-0.1825 0.368605,-0.3294 0.552908,-0.4377 0.184303,-0.1088 0.368606,-0.1782 0.552909,-0.208 0.184302,-0.031 0.368605,-0.019 0.552908,0.031 0.184303,0.05 0.368606,0.1392 0.552909,0.2666 0.184303,0.1274 0.368605,0.2927 0.552908,0.4926 0.184303,0.2001 0.368606,0.4347 0.552909,0.6993 0.184303,0.2646 0.368605,0.5594 0.552908,0.8781 0.184303,0.3189 0.368606,0.6618 0.552909,1.0222 0.184303,0.3603 0.368605,0.738 0.552908,1.1256 0.184303,0.3876 0.368606,0.785 0.552909,1.1845 0.184303,0.3994 0.368606,0.8009 0.552908,1.1963 0.184303,0.3955 0.368606,0.7851 0.552909,1.161 0.184303,0.3758 0.368606,0.7379 0.552908,1.0792 0.184303,0.3411 0.368606,0.6616 0.552909,0.9548 0.184303,0.2932 0.368606,0.5592 0.552908,0.7927 0.184303,0.2334 0.368606,0.4343 0.552909,0.5988 0.184303,0.1645 0.368606,0.2926 0.552909,0.3816 0.184302,0.089 0.368605,0.1389 0.552908,0.1489 0.184303,0.011 0.368606,-0.02 0.552909,-0.09 0.184302,-0.069 0.368605,-0.1784 0.552908,-0.3246 0.184303,-0.1461 0.368606,-0.3295 0.552909,-0.5464 0.184302,-0.217 0.368605,-0.4676 0.552908,-0.7469 0.184303,-0.2792 0.368606,-0.5872 0.552909,-0.9177 0.184302,-0.3303 0.368605,-0.6834 0.552908,-1.0519 0.184303,-0.3686 0.368606,-0.7526 0.552909,-1.1446 0.184303,-0.392 0.368605,-0.7921 0.552908,-1.1919"
+         style="fill:none;stroke:#2e0dff;stroke-width:0.30176657;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+         inkscape:connector-curvature="0" />
+      <path
+         inkscape:connector-curvature="0"
+         id="path3768-2-3-7"
+         d="m 0,1040.0689 35.26169,0"
+         style="fill:none;stroke:#c9c9c9;stroke-width:0.19036053;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0" />
+      <path
+         inkscape:connector-curvature="0"
+         id="path3768-1-5-1"
+         d="m 0,1048.373 35.26169,0"
+         style="fill:none;stroke:#c9c9c9;stroke-width:0.19036053;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0" />
+      <path
+         inkscape:connector-curvature="0"
+         id="path3755-4-38-0"
+         d="m 3.860417,1036.1837 0,16.1257"
+         style="fill:none;stroke:#c9c9c9;stroke-width:0.19036053;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" />
+      <path
+         inkscape:connector-curvature="0"
+         id="path3755-4-0-5-8"
+         d="m 7.720835,1036.1837 0,16.1257"
+         style="fill:none;stroke:#c9c9c9;stroke-width:0.19036053;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" />
+      <path
+         inkscape:connector-curvature="0"
+         id="path3755-4-5-0-7"
+         d="m 11.581253,1036.1837 0,16.1257"
+         style="fill:none;stroke:#c9c9c9;stroke-width:0.19036053;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" />
+      <path
+         inkscape:connector-curvature="0"
+         id="path3755-4-9-1-2"
+         d="m 15.441669,1036.1837 0,16.1257"
+         style="fill:none;stroke:#c9c9c9;stroke-width:0.19036053;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" />
+      <path
+         inkscape:connector-curvature="0"
+         id="path3755-4-7-9-8"
+         d="m 19.302086,1036.1837 0,16.1257"
+         style="fill:none;stroke:#c9c9c9;stroke-width:0.19036053;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" />
+      <path
+         inkscape:connector-curvature="0"
+         id="path3755-4-3-3-8"
+         d="m 23.162504,1036.1837 0,16.1257"
+         style="fill:none;stroke:#c9c9c9;stroke-width:0.19036053;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" />
+      <path
+         inkscape:connector-curvature="0"
+         id="path3755-4-1-4-9"
+         d="m 27.022922,1036.1837 0,16.1257"
+         style="fill:none;stroke:#c9c9c9;stroke-width:0.19036053;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" />
+      <path
+         inkscape:connector-curvature="0"
+         id="path3755-4-90-5-2"
+         d="m 30.883338,1036.1837 0,16.1257"
+         style="fill:none;stroke:#c9c9c9;stroke-width:0.19036053;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" />
+      <path
+         inkscape:connector-curvature="0"
+         id="path3755-4-2-0-4"
+         d="m 34.743757,1036.1837 0,16.1257"
+         style="fill:none;stroke:#c9c9c9;stroke-width:0.19036053;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" />
+      <path
+         inkscape:connector-curvature="0"
+         id="path3755-6-0"
+         d="m 0,1036.1837 0,16.1257"
+         style="fill:none;stroke:#000000;stroke-width:0.38072109;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" />
+      <path
+         inkscape:connector-curvature="0"
+         id="path3768-4-0"
+         d="m 0,1052.2209 35.26169,0"
+         style="fill:none;stroke:#000000;stroke-width:0.38072109;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0" />
+      <path
+         inkscape:connector-curvature="0"
+         style="fill:none;stroke:#ff970d;stroke-width:0.30000001;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+         d="m 0.25968796,1051.8993 c 0.18450185,0 0.3690037,0 0.55350556,0 0.18450185,0 0.36900368,0 0.55350558,0 0.1845018,0 0.3690037,0 0.5535055,0 0.1845019,0 0.3690037,0 0.5535056,0 0.1845018,0 0.3690037,0 0.5535055,0 0.1845019,0 0.3690037,0 0.5535056,0 0.1845018,-10e-5 0.3690037,-10e-5 0.5535055,-3e-4 0.1845019,-10e-5 0.3690037,-3e-4 0.5535056,-7e-4 0.1845018,-4e-4 0.3690037,-10e-4 0.5535055,0 0.1845019,0 0.3690038,0 0.5535056,-0.01 0.1845019,0 0.3690037,-0.01 0.5535056,-0.011 0.1845018,-0.01 0.3690037,-0.012 0.5535055,-0.022 0.1845019,-0.01 0.3690037,-0.023 0.5535056,-0.041 0.1845018,-0.018 0.3690037,-0.041 0.5535055,-0.072 0.1845019,-0.031 0.3690037,-0.069 0.5535056,-0.1174 0.1845018,-0.049 0.3690037,-0.1081 0.5535055,-0.1816 0.1845019,-0.073 0.3690037,-0.1613 0.5535056,-0.267 0.1845018,-0.1057 0.3690036,-0.2294 0.5535056,-0.3745 0.184502,-0.1451 0.369003,-0.3119 0.553505,-0.5028 0.184502,-0.1909 0.369004,-0.4062 0.553506,-0.6472 0.184502,-0.241 0.369003,-0.5079 0.553505,-0.8001 0.184502,-0.2922 0.369004,-0.6099 0.553506,-0.9503 0.184502,-0.3405 0.369004,-0.7038 0.553505,-1.0848 0.184502,-0.3811 0.369004,-0.7798 0.553506,-1.1888 0.184502,-0.409 0.369004,-0.8281 0.553506,-1.2479 0.184501,-0.4198 0.369003,-0.8402 0.553505,-1.2503 0.184502,-0.41 0.369004,-0.8095 0.553506,-1.1872 0.184502,-0.3777 0.369003,-0.7333 0.553505,-1.0561 0.184502,-0.3227 0.369004,-0.6123 0.553506,-0.8596 0.184502,-0.2473 0.369003,-0.452 0.553505,-0.6075 0.184502,-0.1555 0.369004,-0.2614 0.553506,-0.3145 0.184502,-0.053 0.369004,-0.053 0.553505,0 0.184502,0.053 0.369004,0.1591 0.553506,0.3145 0.184502,0.1554 0.369004,0.3603 0.553506,0.6075 0.184501,0.2472 0.369003,0.537 0.553505,0.8596 0.184502,0.3227 0.369004,0.6784 0.553506,1.0561 0.184502,0.3776 0.369003,0.7772 0.553505,1.1872 0.184502,0.4101 0.369004,0.8305 0.553506,1.2503 0.184502,0.4198 0.369003,0.8389 0.553505,1.2479 0.184502,0.409 0.369004,0.8077 0.553506,1.1888 0.184502,0.381 0.369004,0.7443 0.553505,1.0848 0.184502,0.3405 0.369004,0.6581 0.553506,0.9503 0.184502,0.2923 0.369004,0.5591 0.553506,0.8001 0.184501,0.241 0.369003,0.4563 0.553505,0.6472 0.184502,0.191 0.369004,0.3576 0.553506,0.5028 0.184502,0.1452 0.369003,0.2688 0.553505,0.3745 0.184502,0.1057 0.369004,0.1934 0.553506,0.267 0.184502,0.074 0.369003,0.1328 0.553505,0.1816 0.184502,0.049 0.369004,0.087 0.553506,0.1174 0.184502,0.031 0.369004,0.054 0.553505,0.072 0.184502,0.018 0.369004,0.031 0.553506,0.041 0.184502,0.01 0.369004,0.017 0.553506,0.022 0.184501,0.01 0.369003,0.01 0.553505,0.011 0.184502,0 0.369004,0 0.553506,0.01 0.184502,10e-4 0.369003,0 0.553505,0 0.184502,4e-4 0.369004,6e-4 0.553506,7e-4 0.184502,2e-4 0.369003,2e-4 0.553505,3e-4 0.184502,0 0.369004,0 0.553506,0 0.184502,0 0.369004,0 0.553505,0 0.184502,0 0.369004,0 0.553506,0 0.184502,0 0.369004,0 0.553506,0 0.184501,0 0.369003,0 0.553505,0 0.184502,0 0.369004,0 0.553506,0"
+         title="pow(sin(x), 10)"
+         id="path7506-5" />
+    </g>
+  </g>
+  <g
+     inkscape:label="Layer 1"
+     inkscape:groupmode="layer"
+     id="layer1"
+     transform="translate(0,-1016.9291)"
+     style="display:inline">
+    <rect
+       style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="rect4735"
+       width="21.984022"
+       height="15.841428"
+       x="-0.12931778"
+       y="1017.1877" />
+    <path
+       style="fill:none;stroke:#c9c9c9;stroke-width:0.1497674;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
+       d="m -0.38664415,1020.9238 22.23492015,0"
+       id="path3768-2"
+       inkscape:connector-curvature="0" />
+    <path
+       style="fill:none;stroke:#c9c9c9;stroke-width:0.14911523;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
+       d="m -0.25776149,1029.0753 22.04169149,0"
+       id="path3768-1"
+       inkscape:connector-curvature="0" />
+    <path
+       style="fill:none;stroke:#c9c9c9;stroke-width:0.18860409;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+       d="m 3.8604174,1017.11 0,15.8294"
+       id="path3755-4"
+       inkscape:connector-curvature="0" />
+    <path
+       style="fill:none;stroke:#c9c9c9;stroke-width:0.18860409;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+       d="m 7.7208349,1017.11 0,15.8294"
+       id="path3755-4-0"
+       inkscape:connector-curvature="0" />
+    <path
+       style="fill:none;stroke:#c9c9c9;stroke-width:0.18860409;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+       d="m 11.581253,1017.11 0,15.8294"
+       id="path3755-4-5"
+       inkscape:connector-curvature="0" />
+    <path
+       style="fill:none;stroke:#c9c9c9;stroke-width:0.18860409;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+       d="m 15.441669,1017.11 0,15.8294"
+       id="path3755-4-9"
+       inkscape:connector-curvature="0" />
+    <path
+       style="fill:none;stroke:#c9c9c9;stroke-width:0.18860409;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+       d="m 19.302086,1017.11 0,15.8294"
+       id="path3755-4-7"
+       inkscape:connector-curvature="0" />
+    <path
+       style="fill:none;stroke:#000000;stroke-width:0.29803008;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
+       d="m -0.25689803,1024.9996 22.01207903,0"
+       id="path3768"
+       inkscape:connector-curvature="0" />
+    <path
+       inkscape:connector-curvature="0"
+       style="fill:none;stroke:#2e0dff;stroke-width:0.802;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+       d="m 0.17138129,1025.0901 c 0.18430284,-0.3999 0.36860568,-0.8 0.55290852,-1.1919 0.18430286,-0.3921 0.36860569,-0.7762 0.55290859,-1.1447 0.1843028,-0.3686 0.3686057,-0.7216 0.5529085,-1.0521 0.1843028,-0.3303 0.3686057,-0.6383 0.5529085,-0.9175 0.1843029,-0.2794 0.3686057,-0.5299 0.5529085,-0.7468 0.1843029,-0.2172 0.3686057,-0.4004 0.5529086,-0.5466 0.1843028,-0.1461 0.3686056,-0.2549 0.5529085,-0.3244 0.1843028,-0.069 0.3686057,-0.1 0.5529085,-0.09 0.1843029,0.011 0.3686057,0.06 0.5529085,0.1489 0.1843029,0.09 0.3686057,0.217 0.5529086,0.3815 0.1843028,0.1645 0.3686056,0.3655 0.5529085,0.5989 0.1843028,0.2335 0.3686057,0.4995 0.5529085,0.7927 0.1843028,0.2931 0.3686057,0.6135 0.5529085,0.9549 0.1843029,0.3412 0.3686057,0.7034 0.5529086,1.0792 0.1843028,0.3758 0.3686056,0.7653 0.5529085,1.1608 0.1843028,0.3956 0.3686057,0.7969 0.5529085,1.1964 0.1843028,0.3994 0.3686057,0.7969 0.5529085,1.1845 0.1843029,0.3876 0.3686059,0.7653 0.5529088,1.1257 0.184302,0.3603 0.368605,0.7033 0.552908,1.022 0.184303,0.3189 0.368606,0.6135 0.552909,0.8782 0.184303,0.2646 0.368605,0.4992 0.552908,0.6992 0.184303,0.2001 0.368606,0.3653 0.552909,0.4927 0.184303,0.1274 0.368605,0.2168 0.552908,0.2665 0.184303,0.05 0.368606,0.06 0.552909,0.031 0.184303,-0.031 0.368605,-0.1 0.552908,-0.2079 0.184303,-0.1088 0.368606,-0.2552 0.552909,-0.4377 0.184303,-0.1824 0.368606,-0.4005 0.552908,-0.6498 0.184303,-0.2495 0.368606,-0.5301 0.552909,-0.8364 0.184303,-0.3065 0.368606,-0.6385 0.552908,-0.9897 0.184303,-0.3513 0.368606,-0.7217 0.552909,-1.1039 0.184303,-0.3821 0.368606,-0.7762 0.552908,-1.1741 0.184303,-0.398 0.368606,-0.8 0.552909,-1.1979 0.184303,-0.398 0.368606,-0.7919 0.552909,-1.1742 0.184302,-0.3821 0.368605,-0.7525 0.552908,-1.1038 0.184303,-0.3512 0.368606,-0.6833 0.552909,-0.9896 0.184302,-0.3064 0.368605,-0.587 0.552908,-0.8364 0.184303,-0.2494 0.368606,-0.4675 0.552909,-0.6499 0.184302,-0.1825 0.368605,-0.3294 0.552908,-0.4377 0.184303,-0.1088 0.368606,-0.1782 0.552909,-0.208"
+       title="sin(x)"
+       id="path4190"
+       sodipodi:nodetypes="ccccccccccscccsccsccccscccccccccccccsccc" />
+    <rect
+       style="fill:none;stroke:#000000;stroke-width:0.29496232;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+       id="rect3905"
+       width="22.075964"
+       height="15.974718"
+       x="-0.19596301"
+       y="1017.121" />
+    <rect
+       style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="rect4735-9"
+       width="21.984022"
+       height="15.841428"
+       x="3.2648256"
+       y="1021.9644" />
+    <path
+       style="fill:none;stroke:#c9c9c9;stroke-width:0.1497674;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
+       d="m 3.0074993,1025.7005 22.2349197,0"
+       id="path3768-2-9"
+       inkscape:connector-curvature="0" />
+    <path
+       style="fill:none;stroke:#c9c9c9;stroke-width:0.14911523;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
+       d="m 3.1363819,1033.852 22.0416911,0"
+       id="path3768-1-4"
+       inkscape:connector-curvature="0" />
+    <path
+       style="fill:none;stroke:#c9c9c9;stroke-width:0.18860409;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+       d="m 7.2545608,1021.8867 0,15.8294"
+       id="path3755-4-2"
+       inkscape:connector-curvature="0" />
+    <path
+       style="fill:none;stroke:#c9c9c9;stroke-width:0.18860409;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+       d="m 11.114978,1021.8867 0,15.8294"
+       id="path3755-4-0-2"
+       inkscape:connector-curvature="0" />
+    <path
+       style="fill:none;stroke:#c9c9c9;stroke-width:0.18860409;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+       d="m 14.975396,1021.8867 0,15.8294"
+       id="path3755-4-5-3"
+       inkscape:connector-curvature="0" />
+    <path
+       style="fill:none;stroke:#c9c9c9;stroke-width:0.18860409;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+       d="m 18.835812,1021.8867 0,15.8294"
+       id="path3755-4-9-8"
+       inkscape:connector-curvature="0" />
+    <path
+       style="fill:none;stroke:#c9c9c9;stroke-width:0.18860409;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+       d="m 22.696229,1021.8867 0,15.8294"
+       id="path3755-4-7-9"
+       inkscape:connector-curvature="0" />
+    <path
+       style="fill:none;stroke:#000000;stroke-width:0.29803008;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
+       d="m 3.1372454,1029.7763 22.0120786,0"
+       id="path3768-7"
+       inkscape:connector-curvature="0" />
+    <path
+       inkscape:connector-curvature="0"
+       style="fill:none;stroke:#2e0dff;stroke-width:0.802;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+       d="m 3.5655247,1029.8668 c 0.1843028,-0.3999 0.3686057,-0.8 0.5529085,-1.1919 0.1843029,-0.3921 0.3686057,-0.7762 0.5529086,-1.1447 0.1843028,-0.3686 0.3686057,-0.7216 0.5529085,-1.0521 0.1843028,-0.3303 0.3686057,-0.6383 0.5529085,-0.9175 0.1843029,-0.2794 0.3686057,-0.5299 0.5529085,-0.7468 0.1843029,-0.2172 0.3686057,-0.4004 0.5529086,-0.5466 0.1843028,-0.1461 0.3686056,-0.2549 0.5529085,-0.3244 0.1843028,-0.069 0.3686057,-0.1 0.5529085,-0.09 0.1843029,0.011 0.3686057,0.06 0.5529085,0.1489 0.1843029,0.09 0.3686057,0.217 0.5529086,0.3815 0.1843028,0.1645 0.3686056,0.3655 0.5529085,0.5989 0.1843028,0.2335 0.3686055,0.4995 0.5529085,0.7927 0.184303,0.2931 0.368606,0.6135 0.552909,0.9549 0.184302,0.3412 0.368605,0.7034 0.552908,1.0792 0.184303,0.3758 0.368606,0.7653 0.552909,1.1608 0.184302,0.3956 0.368605,0.7969 0.552908,1.1964 0.184303,0.3994 0.368606,0.7969 0.552909,1.1845 0.184303,0.3876 0.368606,0.7653 0.552908,1.1257 0.184302,0.3603 0.368605,0.7033 0.552908,1.022 0.184303,0.3189 0.368606,0.6135 0.552909,0.8782 0.184303,0.2646 0.368605,0.4992 0.552908,0.6992 0.184303,0.2001 0.368606,0.3653 0.552909,0.4927 0.184303,0.1274 0.368605,0.2168 0.552908,0.2665 0.184303,0.05 0.368606,0.06 0.552909,0.031 0.184303,-0.031 0.368605,-0.1 0.552908,-0.2079 0.184303,-0.1088 0.368606,-0.2552 0.552909,-0.4377 0.184303,-0.1824 0.368606,-0.4005 0.552908,-0.6498 0.184303,-0.2495 0.368606,-0.5301 0.552909,-0.8364 0.184303,-0.3065 0.368606,-0.6385 0.552908,-0.9897 0.184303,-0.3513 0.368606,-0.7217 0.552909,-1.1039 0.184303,-0.3821 0.368606,-0.7762 0.552908,-1.1741 0.184303,-0.398 0.368606,-0.8 0.552909,-1.1979 0.184303,-0.398 0.368606,-0.7919 0.552909,-1.1742 0.184302,-0.3821 0.368605,-0.7525 0.552908,-1.1038 0.184303,-0.3512 0.368606,-0.6833 0.552909,-0.9896 0.184302,-0.3064 0.368605,-0.587 0.552908,-0.8364 0.184303,-0.2494 0.368606,-0.4675 0.552909,-0.6499 0.184302,-0.1825 0.368605,-0.3294 0.552908,-0.4377 0.184303,-0.1088 0.368606,-0.1782 0.552909,-0.208"
+       title="sin(x)"
+       id="path4190-0"
+       sodipodi:nodetypes="ccccccccccscccsccsccccscccccccccccccsccc" />
+    <rect
+       style="fill:none;stroke:#000000;stroke-width:0.29496232;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+       id="rect3905-8"
+       width="22.075964"
+       height="15.974718"
+       x="3.1981804"
+       y="1021.8977" />
+    <rect
+       style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="rect4735-2"
+       width="21.984022"
+       height="15.841428"
+       x="6.5999274"
+       y="1026.7411" />
+    <path
+       style="fill:none;stroke:#c9c9c9;stroke-width:0.1497674;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
+       d="m 6.3426012,1030.4772 22.2349198,0"
+       id="path3768-2-3"
+       inkscape:connector-curvature="0" />
+    <path
+       style="fill:none;stroke:#c9c9c9;stroke-width:0.14911523;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
+       d="m 6.4714839,1038.6287 22.0416911,0"
+       id="path3768-1-3"
+       inkscape:connector-curvature="0" />
+    <path
+       style="fill:none;stroke:#c9c9c9;stroke-width:0.18860409;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+       d="m 10.589663,1026.6634 0,15.8294"
+       id="path3755-4-1"
+       inkscape:connector-curvature="0" />
+    <path
+       style="fill:none;stroke:#c9c9c9;stroke-width:0.18860409;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+       d="m 14.45008,1026.6634 0,15.8294"
+       id="path3755-4-0-3"
+       inkscape:connector-curvature="0" />
+    <path
+       style="fill:none;stroke:#c9c9c9;stroke-width:0.18860409;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+       d="m 18.310498,1026.6634 0,15.8294"
+       id="path3755-4-5-1"
+       inkscape:connector-curvature="0" />
+    <path
+       style="fill:none;stroke:#c9c9c9;stroke-width:0.18860409;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+       d="m 22.170914,1026.6634 0,15.8294"
+       id="path3755-4-9-88"
+       inkscape:connector-curvature="0" />
+    <path
+       style="fill:none;stroke:#c9c9c9;stroke-width:0.18860409;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+       d="m 26.031331,1026.6634 0,15.8294"
+       id="path3755-4-7-2"
+       inkscape:connector-curvature="0" />
+    <path
+       style="fill:none;stroke:#000000;stroke-width:0.29803008;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
+       d="m 6.4723474,1034.553 22.0120786,0"
+       id="path3768-98"
+       inkscape:connector-curvature="0" />
+    <path
+       inkscape:connector-curvature="0"
+       style="fill:none;stroke:#2e0dff;stroke-width:0.802;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+       d="m 6.9006267,1034.6435 c 0.1843028,-0.3999 0.3686057,-0.8 0.5529085,-1.1919 0.1843029,-0.3921 0.3686057,-0.7762 0.5529086,-1.1447 0.1843028,-0.3686 0.3686057,-0.7216 0.5529085,-1.0521 0.1843028,-0.3303 0.3686057,-0.6383 0.5529085,-0.9175 0.1843029,-0.2794 0.3686057,-0.5299 0.5529085,-0.7468 0.1843029,-0.2172 0.3686057,-0.4004 0.5529087,-0.5466 0.184303,-0.1461 0.368605,-0.2549 0.552908,-0.3244 0.184303,-0.069 0.368606,-0.1 0.552909,-0.09 0.184303,0.011 0.368606,0.06 0.552908,0.1489 0.184303,0.09 0.368606,0.217 0.552909,0.3815 0.184303,0.1645 0.368606,0.3655 0.552908,0.5989 0.184303,0.2335 0.368606,0.4995 0.552909,0.7927 0.184303,0.2931 0.368606,0.6135 0.552909,0.9549 0.184302,0.3412 0.368605,0.7034 0.552908,1.0792 0.184303,0.3758 0.368606,0.7653 0.552909,1.1608 0.184302,0.3956 0.368605,0.7969 0.552908,1.1964 0.184303,0.3994 0.368606,0.7969 0.552909,1.1845 0.184303,0.3876 0.368605,0.7653 0.552908,1.1257 0.184302,0.3603 0.368605,0.7033 0.552908,1.022 0.184303,0.3189 0.368606,0.6135 0.552909,0.8782 0.184303,0.2646 0.368605,0.4992 0.552908,0.6992 0.184303,0.2001 0.368606,0.3653 0.552909,0.4927 0.184303,0.1274 0.368605,0.2168 0.552908,0.2665 0.184303,0.05 0.368606,0.06 0.552909,0.031 0.184303,-0.031 0.368605,-0.1 0.552908,-0.2079 0.184303,-0.1088 0.368606,-0.2552 0.552909,-0.4377 0.184303,-0.1824 0.368606,-0.4005 0.552908,-0.6498 0.184303,-0.2495 0.368606,-0.5301 0.552909,-0.8364 0.184303,-0.3065 0.368606,-0.6385 0.552908,-0.9897 0.184303,-0.3513 0.368606,-0.7217 0.552909,-1.1039 0.184303,-0.3821 0.368606,-0.7762 0.552908,-1.1741 0.184303,-0.398 0.368606,-0.8 0.552909,-1.1979 0.184303,-0.398 0.368606,-0.7919 0.552909,-1.1742 0.184302,-0.3821 0.368605,-0.7525 0.552908,-1.1038 0.184303,-0.3512 0.368606,-0.6833 0.552909,-0.9896 0.184302,-0.3064 0.368605,-0.587 0.552908,-0.8364 0.184303,-0.2494 0.368606,-0.4675 0.552909,-0.6499 0.184302,-0.1825 0.368605,-0.3294 0.552908,-0.4377 0.184303,-0.1088 0.368606,-0.1782 0.552909,-0.208"
+       title="sin(x)"
+       id="path4190-8"
+       sodipodi:nodetypes="ccccccccccscccsccsccccscccccccccccccsccc" />
+    <rect
+       style="fill:none;stroke:#000000;stroke-width:0.29496232;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+       id="rect3905-7"
+       width="22.075964"
+       height="15.974718"
+       x="6.5332823"
+       y="1026.6744" />
+    <rect
+       style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="rect4735-98"
+       width="21.984022"
+       height="15.841428"
+       x="9.935029"
+       y="1031.5178" />
+    <path
+       style="fill:none;stroke:#c9c9c9;stroke-width:0.1497674;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
+       d="m 9.6777028,1035.2539 22.2349202,0"
+       id="path3768-2-4"
+       inkscape:connector-curvature="0" />
+    <path
+       style="fill:none;stroke:#c9c9c9;stroke-width:0.14911523;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
+       d="m 9.8065855,1043.4054 22.0416915,0"
+       id="path3768-1-6"
+       inkscape:connector-curvature="0" />
+    <path
+       style="fill:none;stroke:#c9c9c9;stroke-width:0.18860409;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+       d="m 13.924764,1031.4401 0,15.8294"
+       id="path3755-4-54"
+       inkscape:connector-curvature="0" />
+    <path
+       style="fill:none;stroke:#c9c9c9;stroke-width:0.18860409;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+       d="m 17.785182,1031.4401 0,15.8294"
+       id="path3755-4-0-5"
+       inkscape:connector-curvature="0" />
+    <path
+       style="fill:none;stroke:#c9c9c9;stroke-width:0.18860409;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+       d="m 21.6456,1031.4401 0,15.8294"
+       id="path3755-4-5-9"
+       inkscape:connector-curvature="0" />
+    <path
+       style="fill:none;stroke:#c9c9c9;stroke-width:0.18860409;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+       d="m 25.506016,1031.4401 0,15.8294"
+       id="path3755-4-9-87"
+       inkscape:connector-curvature="0" />
+    <path
+       style="fill:none;stroke:#c9c9c9;stroke-width:0.18860409;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+       d="m 29.366433,1031.4401 0,15.8294"
+       id="path3755-4-7-4"
+       inkscape:connector-curvature="0" />
+    <path
+       style="fill:none;stroke:#000000;stroke-width:0.29803008;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
+       d="m 9.807449,1039.3297 22.012079,0"
+       id="path3768-6"
+       inkscape:connector-curvature="0" />
+    <path
+       inkscape:connector-curvature="0"
+       style="fill:none;stroke:#2e0dff;stroke-width:0.802;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+       d="m 10.235728,1039.4202 c 0.184303,-0.3999 0.368606,-0.8 0.552909,-1.1919 0.184303,-0.3921 0.368605,-0.7762 0.552908,-1.1447 0.184303,-0.3686 0.368606,-0.7216 0.552909,-1.0521 0.184303,-0.3303 0.368606,-0.6383 0.552908,-0.9175 0.184303,-0.2794 0.368606,-0.5299 0.552909,-0.7468 0.184303,-0.2172 0.368606,-0.4004 0.552908,-0.5466 0.184303,-0.1461 0.368606,-0.2549 0.552909,-0.3244 0.184303,-0.069 0.368606,-0.1 0.552909,-0.09 0.184302,0.011 0.368605,0.06 0.552908,0.1489 0.184303,0.09 0.368606,0.217 0.552909,0.3815 0.184302,0.1645 0.368605,0.3655 0.552908,0.5989 0.184303,0.2335 0.368606,0.4995 0.552909,0.7927 0.184302,0.2931 0.368605,0.6135 0.552908,0.9549 0.184303,0.3412 0.368606,0.7034 0.552909,1.0792 0.184302,0.3758 0.368605,0.7653 0.552908,1.1608 0.184303,0.3956 0.368606,0.7969 0.552909,1.1964 0.184302,0.3994 0.368605,0.7969 0.552908,1.1845 0.184303,0.3876 0.368606,0.7653 0.552909,1.1257 0.184302,0.3603 0.368605,0.7033 0.552908,1.022 0.184303,0.3189 0.368606,0.6135 0.552909,0.8782 0.184303,0.2646 0.368605,0.4992 0.552908,0.6992 0.184303,0.2001 0.368606,0.3653 0.552909,0.4927 0.184303,0.1274 0.368605,0.2168 0.552908,0.2665 0.184303,0.05 0.368606,0.06 0.552909,0.031 0.184303,-0.031 0.368605,-0.1 0.552908,-0.2079 0.184303,-0.1088 0.368606,-0.2552 0.552909,-0.4377 0.184303,-0.1824 0.368606,-0.4005 0.552908,-0.6498 0.184303,-0.2495 0.368606,-0.5301 0.552909,-0.8364 0.184303,-0.3065 0.368606,-0.6385 0.552908,-0.9897 0.184303,-0.3513 0.368606,-0.7217 0.552909,-1.1039 0.184303,-0.3821 0.368606,-0.7762 0.552908,-1.1741 0.184303,-0.398 0.368606,-0.8 0.552909,-1.1979 0.184303,-0.398 0.368606,-0.7919 0.552909,-1.1742 0.184302,-0.3821 0.368605,-0.7525 0.552908,-1.1038 0.184303,-0.3512 0.368606,-0.6833 0.552909,-0.9896 0.184302,-0.3064 0.368605,-0.587 0.552908,-0.8364 0.184303,-0.2494 0.368606,-0.4675 0.552909,-0.6499 0.184302,-0.1825 0.368605,-0.3294 0.552908,-0.4377 0.184303,-0.1088 0.368606,-0.1782 0.552909,-0.208"
+       title="sin(x)"
+       id="path4190-84"
+       sodipodi:nodetypes="ccccccccccscccsccsccccscccccccccccccsccc" />
+    <rect
+       style="fill:none;stroke:#000000;stroke-width:0.29496232000000000;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+       id="rect3905-86"
+       width="22.075964"
+       height="15.974718"
+       x="9.8683844"
+       y="1031.451" />
+    <rect
+       style="fill:#f6e879;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="rect4735-23"
+       width="21.984022"
+       height="15.841428"
+       x="13.270129"
+       y="1036.2946" />
+    <path
+       style="fill:none;stroke:#c9c9c9;stroke-width:0.1497674;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
+       d="m 13.012803,1040.0306 22.23492,0"
+       id="path3768-2-5"
+       inkscape:connector-curvature="0" />
+    <path
+       style="fill:none;stroke:#c9c9c9;stroke-width:0.14911523;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
+       d="m 13.141686,1048.1821 22.041691,0"
+       id="path3768-1-5"
+       inkscape:connector-curvature="0" />
+    <path
+       style="fill:none;stroke:#c9c9c9;stroke-width:0.18860409;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+       d="m 17.259864,1036.2168 0,15.8294"
+       id="path3755-4-6"
+       inkscape:connector-curvature="0" />
+    <path
+       style="fill:none;stroke:#c9c9c9;stroke-width:0.18860409;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+       d="m 21.120282,1036.2168 0,15.8294"
+       id="path3755-4-0-35"
+       inkscape:connector-curvature="0" />
+    <path
+       style="fill:none;stroke:#c9c9c9;stroke-width:0.18860409;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+       d="m 24.9807,1036.2168 0,15.8294"
+       id="path3755-4-5-82"
+       inkscape:connector-curvature="0" />
+    <path
+       style="fill:none;stroke:#c9c9c9;stroke-width:0.18860409;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+       d="m 28.841116,1036.2168 0,15.8294"
+       id="path3755-4-9-5"
+       inkscape:connector-curvature="0" />
+    <path
+       style="fill:none;stroke:#c9c9c9;stroke-width:0.18860409;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+       d="m 32.701533,1036.2168 0,15.8294"
+       id="path3755-4-7-7"
+       inkscape:connector-curvature="0" />
+    <path
+       style="fill:none;stroke:#000000;stroke-width:0.29803008;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
+       d="m 13.142549,1044.1064 22.012079,0"
+       id="path3768-25"
+       inkscape:connector-curvature="0" />
+    <path
+       inkscape:connector-curvature="0"
+       style="fill:none;stroke:#2e0dff;stroke-width:0.802;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+       d="m 13.570828,1044.1969 c 0.184303,-0.3999 0.368606,-0.8 0.552909,-1.1919 0.184303,-0.3921 0.368605,-0.7762 0.552908,-1.1447 0.184303,-0.3686 0.368606,-0.7216 0.552909,-1.0521 0.184303,-0.3303 0.368606,-0.6383 0.552908,-0.9175 0.184303,-0.2794 0.368606,-0.5299 0.552909,-0.7468 0.184303,-0.2172 0.368606,-0.4004 0.552908,-0.5466 0.184303,-0.1461 0.368606,-0.2549 0.552909,-0.3244 0.184303,-0.069 0.368606,-0.1 0.552909,-0.09 0.184302,0.011 0.368605,0.06 0.552908,0.1489 0.184303,0.09 0.368606,0.217 0.552909,0.3815 0.184302,0.1645 0.368605,0.3655 0.552908,0.5989 0.184303,0.2335 0.368606,0.4995 0.552909,0.7927 0.184302,0.2931 0.368605,0.6135 0.552908,0.9549 0.184303,0.3412 0.368606,0.7034 0.552909,1.0792 0.184303,0.3758 0.368605,0.7653 0.552908,1.1608 0.184303,0.3956 0.368606,0.7969 0.552909,1.1964 0.184303,0.3994 0.368605,0.7969 0.552908,1.1845 0.184303,0.3876 0.368606,0.7653 0.552909,1.1257 0.184302,0.3603 0.368605,0.7033 0.552908,1.022"
+       title="sin(x)"
+       id="path4190-80"
+       sodipodi:nodetypes="ccccccccccscccsccscc" />
+    <rect
+       style="fill:none;stroke:#000000;stroke-width:0.29496232;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+       id="rect3905-9"
+       width="22.075964"
+       height="15.974718"
+       x="13.203484"
+       y="1036.2278" />
+  </g>
+</svg>
diff --git a/icons/view-displaymode-single_segment.svg b/icons/view-displaymode-single_segment.svg
new file mode 100644 (file)
index 0000000..ed8d3ac
--- /dev/null
@@ -0,0 +1,530 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<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"
+   width="35.433071"
+   height="35.433071"
+   id="svg2"
+   version="1.1"
+   inkscape:version="0.48.5 r10040"
+   sodipodi:docname="view-displaymode-single_segment.svg">
+  <sodipodi:namedview
+     id="base"
+     pagecolor="#ffffff"
+     bordercolor="#666666"
+     borderopacity="1.0"
+     inkscape:pageopacity="0.0"
+     inkscape:pageshadow="2"
+     inkscape:zoom="15.465778"
+     inkscape:cx="17.716536"
+     inkscape:cy="17.716536"
+     inkscape:document-units="px"
+     inkscape:current-layer="layer1"
+     showgrid="false"
+     units="mm"
+     inkscape:window-width="1369"
+     inkscape:window-height="743"
+     inkscape:window-x="242"
+     inkscape:window-y="213"
+     inkscape:window-maximized="0" />
+  <defs
+     id="defs4">
+    <filter
+       inkscape:collect="always"
+       id="filter8271">
+      <feGaussianBlur
+         inkscape:collect="always"
+         stdDeviation="0.17615273"
+         id="feGaussianBlur8273" />
+    </filter>
+  </defs>
+  <metadata
+     id="metadata7">
+    <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></dc:title>
+      </cc:Work>
+    </rdf:RDF>
+  </metadata>
+  <g
+     inkscape:groupmode="layer"
+     id="layer2"
+     inkscape:label="Layer"
+     style="display:none">
+    <g
+       transform="translate(0,-1016.9291)"
+       style="display:inline"
+       id="g7555-6">
+      <path
+         inkscape:connector-curvature="0"
+         id="path3768-2-3-5-9"
+         d="m 0,1044.2466 35.26169,0"
+         style="fill:none;stroke:#c9c9c9;stroke-width:0.19036053;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0" />
+      <path
+         inkscape:connector-curvature="0"
+         id="path3768-2-6"
+         d="m 0,1020.9238 35.26169,0"
+         style="fill:none;stroke:#c9c9c9;stroke-width:0.18860409;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0" />
+      <path
+         inkscape:connector-curvature="0"
+         id="path3768-1-9"
+         d="m 0,1029.0753 35.26169,0"
+         style="fill:none;stroke:#c9c9c9;stroke-width:0.18860409;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0" />
+      <path
+         inkscape:connector-curvature="0"
+         id="path3755-4-29"
+         d="m 3.8604174,1017.11 0,15.8294"
+         style="fill:none;stroke:#c9c9c9;stroke-width:0.18860409;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" />
+      <path
+         inkscape:connector-curvature="0"
+         id="path3755-4-0-6"
+         d="m 7.7208349,1017.11 0,15.8294"
+         style="fill:none;stroke:#c9c9c9;stroke-width:0.18860409;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" />
+      <path
+         inkscape:connector-curvature="0"
+         id="path3755-4-5-8"
+         d="m 11.581253,1017.11 0,15.8294"
+         style="fill:none;stroke:#c9c9c9;stroke-width:0.18860409;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" />
+      <path
+         inkscape:connector-curvature="0"
+         id="path3755-4-9-14"
+         d="m 15.441669,1017.11 0,15.8294"
+         style="fill:none;stroke:#c9c9c9;stroke-width:0.18860409;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" />
+      <path
+         inkscape:connector-curvature="0"
+         id="path3755-4-7-90"
+         d="m 19.302086,1017.11 0,15.8294"
+         style="fill:none;stroke:#c9c9c9;stroke-width:0.18860409;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" />
+      <path
+         inkscape:connector-curvature="0"
+         id="path3755-4-3-32"
+         d="m 23.162504,1017.11 0,15.8294"
+         style="fill:none;stroke:#c9c9c9;stroke-width:0.18860409;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" />
+      <path
+         inkscape:connector-curvature="0"
+         id="path3755-4-1-3"
+         d="m 27.022922,1017.11 0,15.8294"
+         style="fill:none;stroke:#c9c9c9;stroke-width:0.18860409;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" />
+      <path
+         inkscape:connector-curvature="0"
+         id="path3755-4-90-6"
+         d="m 30.883338,1017.11 0,15.8294"
+         style="fill:none;stroke:#c9c9c9;stroke-width:0.18860409;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" />
+      <path
+         inkscape:connector-curvature="0"
+         id="path3755-4-2-4"
+         d="m 34.743757,1017.11 0,15.8294"
+         style="fill:none;stroke:#c9c9c9;stroke-width:0.18860409;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" />
+      <path
+         inkscape:connector-curvature="0"
+         id="path3755-49"
+         d="m 0,1017.11 0,15.8294"
+         style="fill:none;stroke:#000000;stroke-width:0.3772082;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" />
+      <path
+         inkscape:connector-curvature="0"
+         id="path3768-9"
+         d="m 0,1024.9996 35.26169,0"
+         style="fill:none;stroke:#000000;stroke-width:0.3772082;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0" />
+      <path
+         id="path4190-3"
+         title="sin(x)"
+         d="m 0.17138129,1025.0901 c 0.18430284,-0.3999 0.36860568,-0.8 0.55290852,-1.1919 0.18430286,-0.3921 0.36860569,-0.7762 0.55290859,-1.1447 0.1843028,-0.3686 0.3686057,-0.7216 0.5529085,-1.0521 0.1843028,-0.3303 0.3686057,-0.6383 0.5529085,-0.9175 0.1843029,-0.2794 0.3686057,-0.5299 0.5529085,-0.7468 0.1843029,-0.2172 0.3686057,-0.4004 0.5529086,-0.5466 0.1843028,-0.1461 0.3686056,-0.2549 0.5529085,-0.3244 0.1843028,-0.069 0.3686057,-0.1 0.5529085,-0.09 0.1843029,0.011 0.3686057,0.06 0.5529085,0.1489 0.1843029,0.09 0.3686057,0.217 0.5529086,0.3815 0.1843028,0.1645 0.3686056,0.3655 0.5529085,0.5989 0.1843028,0.2335 0.3686057,0.4995 0.5529085,0.7927 0.1843028,0.2931 0.3686057,0.6135 0.5529085,0.9549 0.1843029,0.3412 0.3686057,0.7034 0.5529086,1.0792 0.1843028,0.3758 0.3686056,0.7653 0.5529085,1.1608 0.1843028,0.3956 0.3686057,0.7969 0.5529085,1.1964 0.1843028,0.3994 0.3686057,0.7969 0.5529085,1.1845 0.1843029,0.3876 0.3686059,0.7653 0.5529088,1.1257 0.184302,0.3603 0.368605,0.7033 0.552908,1.022 0.184303,0.3189 0.368606,0.6135 0.552909,0.8782 0.184303,0.2646 0.368605,0.4992 0.552908,0.6992 0.184303,0.2001 0.368606,0.3653 0.552909,0.4927 0.184303,0.1274 0.368605,0.2168 0.552908,0.2665 0.184303,0.05 0.368606,0.06 0.552909,0.031 0.184303,-0.031 0.368605,-0.1 0.552908,-0.2079 0.184303,-0.1088 0.368606,-0.2552 0.552909,-0.4377 0.184303,-0.1824 0.368606,-0.4005 0.552908,-0.6498 0.184303,-0.2495 0.368606,-0.5301 0.552909,-0.8364 0.184303,-0.3065 0.368606,-0.6385 0.552908,-0.9897 0.184303,-0.3513 0.368606,-0.7217 0.552909,-1.1039 0.184303,-0.3821 0.368606,-0.7762 0.552908,-1.1741 0.184303,-0.398 0.368606,-0.8 0.552909,-1.1979 0.184303,-0.398 0.368606,-0.7919 0.552909,-1.1742 0.184302,-0.3821 0.368605,-0.7525 0.552908,-1.1038 0.184303,-0.3512 0.368606,-0.6833 0.552909,-0.9896 0.184302,-0.3064 0.368605,-0.587 0.552908,-0.8364 0.184303,-0.2494 0.368606,-0.4675 0.552909,-0.6499 0.184302,-0.1825 0.368605,-0.3294 0.552908,-0.4377 0.184303,-0.1088 0.368606,-0.1782 0.552909,-0.208 0.184302,-0.031 0.368605,-0.019 0.552908,0.031 0.184303,0.05 0.368606,0.1392 0.552909,0.2666 0.184303,0.1274 0.368605,0.2927 0.552908,0.4926 0.184303,0.2001 0.368606,0.4347 0.552909,0.6993 0.184303,0.2646 0.368605,0.5594 0.552908,0.8781 0.184303,0.3189 0.368606,0.6618 0.552909,1.0222 0.184303,0.3603 0.368605,0.738 0.552908,1.1256 0.184303,0.3876 0.368606,0.785 0.552909,1.1845 0.184303,0.3994 0.368606,0.8009 0.552908,1.1963 0.184303,0.3955 0.368606,0.7851 0.552909,1.161 0.184303,0.3758 0.368606,0.7379 0.552908,1.0792 0.184303,0.3411 0.368606,0.6616 0.552909,0.9548 0.184303,0.2932 0.368606,0.5592 0.552908,0.7927 0.184303,0.2334 0.368606,0.4343 0.552909,0.5988 0.184303,0.1645 0.368606,0.2926 0.552909,0.3816 0.184302,0.089 0.368605,0.1389 0.552908,0.1489 0.184303,0.011 0.368606,-0.02 0.552909,-0.09 0.184302,-0.069 0.368605,-0.1784 0.552908,-0.3246 0.184303,-0.1461 0.368606,-0.3295 0.552909,-0.5464 0.184302,-0.217 0.368605,-0.4676 0.552908,-0.7469 0.184303,-0.2792 0.368606,-0.5872 0.552909,-0.9177 0.184302,-0.3303 0.368605,-0.6834 0.552908,-1.0519 0.184303,-0.3686 0.368606,-0.7526 0.552909,-1.1446 0.184303,-0.392 0.368605,-0.7921 0.552908,-1.1919"
+         style="fill:none;stroke:#2e0dff;stroke-width:0.30176657;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+         inkscape:connector-curvature="0" />
+      <path
+         inkscape:connector-curvature="0"
+         id="path3768-2-3-7"
+         d="m 0,1040.0689 35.26169,0"
+         style="fill:none;stroke:#c9c9c9;stroke-width:0.19036053;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0" />
+      <path
+         inkscape:connector-curvature="0"
+         id="path3768-1-5-1"
+         d="m 0,1048.373 35.26169,0"
+         style="fill:none;stroke:#c9c9c9;stroke-width:0.19036053;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0" />
+      <path
+         inkscape:connector-curvature="0"
+         id="path3755-4-38-0"
+         d="m 3.860417,1036.1837 0,16.1257"
+         style="fill:none;stroke:#c9c9c9;stroke-width:0.19036053;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" />
+      <path
+         inkscape:connector-curvature="0"
+         id="path3755-4-0-5-8"
+         d="m 7.720835,1036.1837 0,16.1257"
+         style="fill:none;stroke:#c9c9c9;stroke-width:0.19036053;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" />
+      <path
+         inkscape:connector-curvature="0"
+         id="path3755-4-5-0-7"
+         d="m 11.581253,1036.1837 0,16.1257"
+         style="fill:none;stroke:#c9c9c9;stroke-width:0.19036053;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" />
+      <path
+         inkscape:connector-curvature="0"
+         id="path3755-4-9-1-2"
+         d="m 15.441669,1036.1837 0,16.1257"
+         style="fill:none;stroke:#c9c9c9;stroke-width:0.19036053;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" />
+      <path
+         inkscape:connector-curvature="0"
+         id="path3755-4-7-9-8"
+         d="m 19.302086,1036.1837 0,16.1257"
+         style="fill:none;stroke:#c9c9c9;stroke-width:0.19036053;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" />
+      <path
+         inkscape:connector-curvature="0"
+         id="path3755-4-3-3-8"
+         d="m 23.162504,1036.1837 0,16.1257"
+         style="fill:none;stroke:#c9c9c9;stroke-width:0.19036053;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" />
+      <path
+         inkscape:connector-curvature="0"
+         id="path3755-4-1-4-9"
+         d="m 27.022922,1036.1837 0,16.1257"
+         style="fill:none;stroke:#c9c9c9;stroke-width:0.19036053;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" />
+      <path
+         inkscape:connector-curvature="0"
+         id="path3755-4-90-5-2"
+         d="m 30.883338,1036.1837 0,16.1257"
+         style="fill:none;stroke:#c9c9c9;stroke-width:0.19036053;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" />
+      <path
+         inkscape:connector-curvature="0"
+         id="path3755-4-2-0-4"
+         d="m 34.743757,1036.1837 0,16.1257"
+         style="fill:none;stroke:#c9c9c9;stroke-width:0.19036053;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" />
+      <path
+         inkscape:connector-curvature="0"
+         id="path3755-6-0"
+         d="m 0,1036.1837 0,16.1257"
+         style="fill:none;stroke:#000000;stroke-width:0.38072109;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" />
+      <path
+         inkscape:connector-curvature="0"
+         id="path3768-4-0"
+         d="m 0,1052.2209 35.26169,0"
+         style="fill:none;stroke:#000000;stroke-width:0.38072109;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0" />
+      <path
+         inkscape:connector-curvature="0"
+         style="fill:none;stroke:#ff970d;stroke-width:0.30000001;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+         d="m 0.25968796,1051.8993 c 0.18450185,0 0.3690037,0 0.55350556,0 0.18450185,0 0.36900368,0 0.55350558,0 0.1845018,0 0.3690037,0 0.5535055,0 0.1845019,0 0.3690037,0 0.5535056,0 0.1845018,0 0.3690037,0 0.5535055,0 0.1845019,0 0.3690037,0 0.5535056,0 0.1845018,-10e-5 0.3690037,-10e-5 0.5535055,-3e-4 0.1845019,-10e-5 0.3690037,-3e-4 0.5535056,-7e-4 0.1845018,-4e-4 0.3690037,-10e-4 0.5535055,0 0.1845019,0 0.3690038,0 0.5535056,-0.01 0.1845019,0 0.3690037,-0.01 0.5535056,-0.011 0.1845018,-0.01 0.3690037,-0.012 0.5535055,-0.022 0.1845019,-0.01 0.3690037,-0.023 0.5535056,-0.041 0.1845018,-0.018 0.3690037,-0.041 0.5535055,-0.072 0.1845019,-0.031 0.3690037,-0.069 0.5535056,-0.1174 0.1845018,-0.049 0.3690037,-0.1081 0.5535055,-0.1816 0.1845019,-0.073 0.3690037,-0.1613 0.5535056,-0.267 0.1845018,-0.1057 0.3690036,-0.2294 0.5535056,-0.3745 0.184502,-0.1451 0.369003,-0.3119 0.553505,-0.5028 0.184502,-0.1909 0.369004,-0.4062 0.553506,-0.6472 0.184502,-0.241 0.369003,-0.5079 0.553505,-0.8001 0.184502,-0.2922 0.369004,-0.6099 0.553506,-0.9503 0.184502,-0.3405 0.369004,-0.7038 0.553505,-1.0848 0.184502,-0.3811 0.369004,-0.7798 0.553506,-1.1888 0.184502,-0.409 0.369004,-0.8281 0.553506,-1.2479 0.184501,-0.4198 0.369003,-0.8402 0.553505,-1.2503 0.184502,-0.41 0.369004,-0.8095 0.553506,-1.1872 0.184502,-0.3777 0.369003,-0.7333 0.553505,-1.0561 0.184502,-0.3227 0.369004,-0.6123 0.553506,-0.8596 0.184502,-0.2473 0.369003,-0.452 0.553505,-0.6075 0.184502,-0.1555 0.369004,-0.2614 0.553506,-0.3145 0.184502,-0.053 0.369004,-0.053 0.553505,0 0.184502,0.053 0.369004,0.1591 0.553506,0.3145 0.184502,0.1554 0.369004,0.3603 0.553506,0.6075 0.184501,0.2472 0.369003,0.537 0.553505,0.8596 0.184502,0.3227 0.369004,0.6784 0.553506,1.0561 0.184502,0.3776 0.369003,0.7772 0.553505,1.1872 0.184502,0.4101 0.369004,0.8305 0.553506,1.2503 0.184502,0.4198 0.369003,0.8389 0.553505,1.2479 0.184502,0.409 0.369004,0.8077 0.553506,1.1888 0.184502,0.381 0.369004,0.7443 0.553505,1.0848 0.184502,0.3405 0.369004,0.6581 0.553506,0.9503 0.184502,0.2923 0.369004,0.5591 0.553506,0.8001 0.184501,0.241 0.369003,0.4563 0.553505,0.6472 0.184502,0.191 0.369004,0.3576 0.553506,0.5028 0.184502,0.1452 0.369003,0.2688 0.553505,0.3745 0.184502,0.1057 0.369004,0.1934 0.553506,0.267 0.184502,0.074 0.369003,0.1328 0.553505,0.1816 0.184502,0.049 0.369004,0.087 0.553506,0.1174 0.184502,0.031 0.369004,0.054 0.553505,0.072 0.184502,0.018 0.369004,0.031 0.553506,0.041 0.184502,0.01 0.369004,0.017 0.553506,0.022 0.184501,0.01 0.369003,0.01 0.553505,0.011 0.184502,0 0.369004,0 0.553506,0.01 0.184502,10e-4 0.369003,0 0.553505,0 0.184502,4e-4 0.369004,6e-4 0.553506,7e-4 0.184502,2e-4 0.369003,2e-4 0.553505,3e-4 0.184502,0 0.369004,0 0.553506,0 0.184502,0 0.369004,0 0.553505,0 0.184502,0 0.369004,0 0.553506,0 0.184502,0 0.369004,0 0.553506,0 0.184501,0 0.369003,0 0.553505,0 0.184502,0 0.369004,0 0.553506,0"
+         title="pow(sin(x), 10)"
+         id="path7506-5" />
+    </g>
+  </g>
+  <g
+     inkscape:label="Layer 1"
+     inkscape:groupmode="layer"
+     id="layer1"
+     transform="translate(0,-1016.9291)"
+     style="display:inline">
+    <rect
+       style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="rect4735"
+       width="21.984022"
+       height="15.841428"
+       x="-0.12931778"
+       y="1017.1877" />
+    <path
+       style="fill:none;stroke:#c9c9c9;stroke-width:0.1497674;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
+       d="m -0.38664415,1020.9238 22.23492015,0"
+       id="path3768-2"
+       inkscape:connector-curvature="0" />
+    <path
+       style="fill:none;stroke:#c9c9c9;stroke-width:0.14911523;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
+       d="m -0.25776149,1029.0753 22.04169149,0"
+       id="path3768-1"
+       inkscape:connector-curvature="0" />
+    <path
+       style="fill:none;stroke:#c9c9c9;stroke-width:0.18860409;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+       d="m 3.8604174,1017.11 0,15.8294"
+       id="path3755-4"
+       inkscape:connector-curvature="0" />
+    <path
+       style="fill:none;stroke:#c9c9c9;stroke-width:0.18860409;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+       d="m 7.7208349,1017.11 0,15.8294"
+       id="path3755-4-0"
+       inkscape:connector-curvature="0" />
+    <path
+       style="fill:none;stroke:#c9c9c9;stroke-width:0.18860409;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+       d="m 11.581253,1017.11 0,15.8294"
+       id="path3755-4-5"
+       inkscape:connector-curvature="0" />
+    <path
+       style="fill:none;stroke:#c9c9c9;stroke-width:0.18860409;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+       d="m 15.441669,1017.11 0,15.8294"
+       id="path3755-4-9"
+       inkscape:connector-curvature="0" />
+    <path
+       style="fill:none;stroke:#c9c9c9;stroke-width:0.18860409;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+       d="m 19.302086,1017.11 0,15.8294"
+       id="path3755-4-7"
+       inkscape:connector-curvature="0" />
+    <path
+       style="fill:none;stroke:#000000;stroke-width:0.29803008;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
+       d="m -0.25689803,1024.9996 22.01207903,0"
+       id="path3768"
+       inkscape:connector-curvature="0" />
+    <path
+       inkscape:connector-curvature="0"
+       style="fill:none;stroke:#2e0dff;stroke-width:0.802;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+       d="m 0.17138129,1025.0901 c 0.18430284,-0.3999 0.36860568,-0.8 0.55290852,-1.1919 0.18430286,-0.3921 0.36860569,-0.7762 0.55290859,-1.1447 0.1843028,-0.3686 0.3686057,-0.7216 0.5529085,-1.0521 0.1843028,-0.3303 0.3686057,-0.6383 0.5529085,-0.9175 0.1843029,-0.2794 0.3686057,-0.5299 0.5529085,-0.7468 0.1843029,-0.2172 0.3686057,-0.4004 0.5529086,-0.5466 0.1843028,-0.1461 0.3686056,-0.2549 0.5529085,-0.3244 0.1843028,-0.069 0.3686057,-0.1 0.5529085,-0.09 0.1843029,0.011 0.3686057,0.06 0.5529085,0.1489 0.1843029,0.09 0.3686057,0.217 0.5529086,0.3815 0.1843028,0.1645 0.3686056,0.3655 0.5529085,0.5989 0.1843028,0.2335 0.3686057,0.4995 0.5529085,0.7927 0.1843028,0.2931 0.3686057,0.6135 0.5529085,0.9549 0.1843029,0.3412 0.3686057,0.7034 0.5529086,1.0792 0.1843028,0.3758 0.3686056,0.7653 0.5529085,1.1608 0.1843028,0.3956 0.3686057,0.7969 0.5529085,1.1964 0.1843028,0.3994 0.3686057,0.7969 0.5529085,1.1845 0.1843029,0.3876 0.3686059,0.7653 0.5529088,1.1257 0.184302,0.3603 0.368605,0.7033 0.552908,1.022 0.184303,0.3189 0.368606,0.6135 0.552909,0.8782 0.184303,0.2646 0.368605,0.4992 0.552908,0.6992 0.184303,0.2001 0.368606,0.3653 0.552909,0.4927 0.184303,0.1274 0.368605,0.2168 0.552908,0.2665 0.184303,0.05 0.368606,0.06 0.552909,0.031 0.184303,-0.031 0.368605,-0.1 0.552908,-0.2079 0.184303,-0.1088 0.368606,-0.2552 0.552909,-0.4377 0.184303,-0.1824 0.368606,-0.4005 0.552908,-0.6498 0.184303,-0.2495 0.368606,-0.5301 0.552909,-0.8364 0.184303,-0.3065 0.368606,-0.6385 0.552908,-0.9897 0.184303,-0.3513 0.368606,-0.7217 0.552909,-1.1039 0.184303,-0.3821 0.368606,-0.7762 0.552908,-1.1741 0.184303,-0.398 0.368606,-0.8 0.552909,-1.1979 0.184303,-0.398 0.368606,-0.7919 0.552909,-1.1742 0.184302,-0.3821 0.368605,-0.7525 0.552908,-1.1038 0.184303,-0.3512 0.368606,-0.6833 0.552909,-0.9896 0.184302,-0.3064 0.368605,-0.587 0.552908,-0.8364 0.184303,-0.2494 0.368606,-0.4675 0.552909,-0.6499 0.184302,-0.1825 0.368605,-0.3294 0.552908,-0.4377 0.184303,-0.1088 0.368606,-0.1782 0.552909,-0.208"
+       title="sin(x)"
+       id="path4190"
+       sodipodi:nodetypes="ccccccccccscccsccsccccscccccccccccccsccc" />
+    <rect
+       style="fill:none;stroke:#000000;stroke-width:0.29496232;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+       id="rect3905"
+       width="22.075964"
+       height="15.974718"
+       x="-0.19596301"
+       y="1017.121" />
+    <rect
+       style="fill:#f6e879;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="rect4735-9"
+       width="21.984022"
+       height="15.841428"
+       x="3.2648256"
+       y="1021.9644" />
+    <path
+       style="fill:none;stroke:#c9c9c9;stroke-width:0.1497674;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
+       d="m 3.0074993,1025.7005 22.2349197,0"
+       id="path3768-2-9"
+       inkscape:connector-curvature="0" />
+    <path
+       style="fill:none;stroke:#c9c9c9;stroke-width:0.14911523;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
+       d="m 3.1363819,1033.852 22.0416911,0"
+       id="path3768-1-4"
+       inkscape:connector-curvature="0" />
+    <path
+       style="fill:none;stroke:#c9c9c9;stroke-width:0.18860409;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+       d="m 7.2545608,1021.8867 0,15.8294"
+       id="path3755-4-2"
+       inkscape:connector-curvature="0" />
+    <path
+       style="fill:none;stroke:#c9c9c9;stroke-width:0.18860409;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+       d="m 11.114978,1021.8867 0,15.8294"
+       id="path3755-4-0-2"
+       inkscape:connector-curvature="0" />
+    <path
+       style="fill:none;stroke:#c9c9c9;stroke-width:0.18860409;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+       d="m 14.975396,1021.8867 0,15.8294"
+       id="path3755-4-5-3"
+       inkscape:connector-curvature="0" />
+    <path
+       style="fill:none;stroke:#c9c9c9;stroke-width:0.18860409;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+       d="m 18.835812,1021.8867 0,15.8294"
+       id="path3755-4-9-8"
+       inkscape:connector-curvature="0" />
+    <path
+       style="fill:none;stroke:#c9c9c9;stroke-width:0.18860409;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+       d="m 22.696229,1021.8867 0,15.8294"
+       id="path3755-4-7-9"
+       inkscape:connector-curvature="0" />
+    <path
+       style="fill:none;stroke:#000000;stroke-width:0.29803008;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
+       d="m 3.1372454,1029.7763 22.0120786,0"
+       id="path3768-7"
+       inkscape:connector-curvature="0" />
+    <path
+       inkscape:connector-curvature="0"
+       style="fill:none;stroke:#2e0dff;stroke-width:0.802;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+       d="m 3.5655247,1029.8668 c 0.1843028,-0.3999 0.3686057,-0.8 0.5529085,-1.1919 0.1843029,-0.3921 0.3686057,-0.7762 0.5529086,-1.1447 0.1843028,-0.3686 0.3686057,-0.7216 0.5529085,-1.0521 0.1843028,-0.3303 0.3686057,-0.6383 0.5529085,-0.9175 0.1843029,-0.2794 0.3686057,-0.5299 0.5529085,-0.7468 0.1843029,-0.2172 0.3686057,-0.4004 0.5529086,-0.5466 0.1843028,-0.1461 0.3686056,-0.2549 0.5529085,-0.3244 0.1843028,-0.069 0.3686057,-0.1 0.5529085,-0.09 0.1843029,0.011 0.3686057,0.06 0.5529085,0.1489 0.1843029,0.09 0.3686057,0.217 0.5529086,0.3815 0.1843028,0.1645 0.3686056,0.3655 0.5529085,0.5989 0.1843028,0.2335 0.3686055,0.4995 0.5529085,0.7927 0.184303,0.2931 0.368606,0.6135 0.552909,0.9549 0.184302,0.3412 0.368605,0.7034 0.552908,1.0792 0.184303,0.3758 0.368606,0.7653 0.552909,1.1608 0.184302,0.3956 0.368605,0.7969 0.552908,1.1964 0.184303,0.3994 0.368606,0.7969 0.552909,1.1845 0.184303,0.3876 0.368606,0.7653 0.552908,1.1257 0.184302,0.3603 0.368605,0.7033 0.552908,1.022 0.184303,0.3189 0.368606,0.6135 0.552909,0.8782 0.184303,0.2646 0.368605,0.4992 0.552908,0.6992 0.184303,0.2001 0.368606,0.3653 0.552909,0.4927 0.184303,0.1274 0.368605,0.2168 0.552908,0.2665 0.184303,0.05 0.368606,0.06 0.552909,0.031 0.184303,-0.031 0.368605,-0.1 0.552908,-0.2079 0.184303,-0.1088 0.368606,-0.2552 0.552909,-0.4377 0.184303,-0.1824 0.368606,-0.4005 0.552908,-0.6498 0.184303,-0.2495 0.368606,-0.5301 0.552909,-0.8364 0.184303,-0.3065 0.368606,-0.6385 0.552908,-0.9897 0.184303,-0.3513 0.368606,-0.7217 0.552909,-1.1039 0.184303,-0.3821 0.368606,-0.7762 0.552908,-1.1741 0.184303,-0.398 0.368606,-0.8 0.552909,-1.1979 0.184303,-0.398 0.368606,-0.7919 0.552909,-1.1742 0.184302,-0.3821 0.368605,-0.7525 0.552908,-1.1038 0.184303,-0.3512 0.368606,-0.6833 0.552909,-0.9896 0.184302,-0.3064 0.368605,-0.587 0.552908,-0.8364 0.184303,-0.2494 0.368606,-0.4675 0.552909,-0.6499 0.184302,-0.1825 0.368605,-0.3294 0.552908,-0.4377 0.184303,-0.1088 0.368606,-0.1782 0.552909,-0.208"
+       title="sin(x)"
+       id="path4190-0"
+       sodipodi:nodetypes="ccccccccccscccsccsccccscccccccccccccsccc" />
+    <rect
+       style="fill:none;stroke:#000000;stroke-width:0.29496232;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+       id="rect3905-8"
+       width="22.075964"
+       height="15.974718"
+       x="3.1981804"
+       y="1021.8977" />
+    <rect
+       style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="rect4735-2"
+       width="21.984022"
+       height="15.841428"
+       x="6.5999274"
+       y="1026.7411" />
+    <path
+       style="fill:none;stroke:#c9c9c9;stroke-width:0.1497674;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
+       d="m 6.3426012,1030.4772 22.2349198,0"
+       id="path3768-2-3"
+       inkscape:connector-curvature="0" />
+    <path
+       style="fill:none;stroke:#c9c9c9;stroke-width:0.14911523;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
+       d="m 6.4714839,1038.6287 22.0416911,0"
+       id="path3768-1-3"
+       inkscape:connector-curvature="0" />
+    <path
+       style="fill:none;stroke:#c9c9c9;stroke-width:0.18860409;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+       d="m 10.589663,1026.6634 0,15.8294"
+       id="path3755-4-1"
+       inkscape:connector-curvature="0" />
+    <path
+       style="fill:none;stroke:#c9c9c9;stroke-width:0.18860409;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+       d="m 14.45008,1026.6634 0,15.8294"
+       id="path3755-4-0-3"
+       inkscape:connector-curvature="0" />
+    <path
+       style="fill:none;stroke:#c9c9c9;stroke-width:0.18860409;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+       d="m 18.310498,1026.6634 0,15.8294"
+       id="path3755-4-5-1"
+       inkscape:connector-curvature="0" />
+    <path
+       style="fill:none;stroke:#c9c9c9;stroke-width:0.18860409;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+       d="m 22.170914,1026.6634 0,15.8294"
+       id="path3755-4-9-88"
+       inkscape:connector-curvature="0" />
+    <path
+       style="fill:none;stroke:#c9c9c9;stroke-width:0.18860409;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+       d="m 26.031331,1026.6634 0,15.8294"
+       id="path3755-4-7-2"
+       inkscape:connector-curvature="0" />
+    <path
+       style="fill:none;stroke:#000000;stroke-width:0.29803008;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
+       d="m 6.4723474,1034.553 22.0120786,0"
+       id="path3768-98"
+       inkscape:connector-curvature="0" />
+    <path
+       inkscape:connector-curvature="0"
+       style="fill:none;stroke:#2e0dff;stroke-width:0.802;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+       d="m 6.9006267,1034.6435 c 0.1843028,-0.3999 0.3686057,-0.8 0.5529085,-1.1919 0.1843029,-0.3921 0.3686057,-0.7762 0.5529086,-1.1447 0.1843028,-0.3686 0.3686057,-0.7216 0.5529085,-1.0521 0.1843028,-0.3303 0.3686057,-0.6383 0.5529085,-0.9175 0.1843029,-0.2794 0.3686057,-0.5299 0.5529085,-0.7468 0.1843029,-0.2172 0.3686057,-0.4004 0.5529087,-0.5466 0.184303,-0.1461 0.368605,-0.2549 0.552908,-0.3244 0.184303,-0.069 0.368606,-0.1 0.552909,-0.09 0.184303,0.011 0.368606,0.06 0.552908,0.1489 0.184303,0.09 0.368606,0.217 0.552909,0.3815 0.184303,0.1645 0.368606,0.3655 0.552908,0.5989 0.184303,0.2335 0.368606,0.4995 0.552909,0.7927 0.184303,0.2931 0.368606,0.6135 0.552909,0.9549 0.184302,0.3412 0.368605,0.7034 0.552908,1.0792 0.184303,0.3758 0.368606,0.7653 0.552909,1.1608 0.184302,0.3956 0.368605,0.7969 0.552908,1.1964 0.184303,0.3994 0.368606,0.7969 0.552909,1.1845 0.184303,0.3876 0.368605,0.7653 0.552908,1.1257 0.184302,0.3603 0.368605,0.7033 0.552908,1.022 0.184303,0.3189 0.368606,0.6135 0.552909,0.8782 0.184303,0.2646 0.368605,0.4992 0.552908,0.6992 0.184303,0.2001 0.368606,0.3653 0.552909,0.4927 0.184303,0.1274 0.368605,0.2168 0.552908,0.2665 0.184303,0.05 0.368606,0.06 0.552909,0.031 0.184303,-0.031 0.368605,-0.1 0.552908,-0.2079 0.184303,-0.1088 0.368606,-0.2552 0.552909,-0.4377 0.184303,-0.1824 0.368606,-0.4005 0.552908,-0.6498 0.184303,-0.2495 0.368606,-0.5301 0.552909,-0.8364 0.184303,-0.3065 0.368606,-0.6385 0.552908,-0.9897 0.184303,-0.3513 0.368606,-0.7217 0.552909,-1.1039 0.184303,-0.3821 0.368606,-0.7762 0.552908,-1.1741 0.184303,-0.398 0.368606,-0.8 0.552909,-1.1979 0.184303,-0.398 0.368606,-0.7919 0.552909,-1.1742 0.184302,-0.3821 0.368605,-0.7525 0.552908,-1.1038 0.184303,-0.3512 0.368606,-0.6833 0.552909,-0.9896 0.184302,-0.3064 0.368605,-0.587 0.552908,-0.8364 0.184303,-0.2494 0.368606,-0.4675 0.552909,-0.6499 0.184302,-0.1825 0.368605,-0.3294 0.552908,-0.4377 0.184303,-0.1088 0.368606,-0.1782 0.552909,-0.208"
+       title="sin(x)"
+       id="path4190-8"
+       sodipodi:nodetypes="ccccccccccscccsccsccccscccccccccccccsccc" />
+    <rect
+       style="fill:none;stroke:#000000;stroke-width:0.29496232;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+       id="rect3905-7"
+       width="22.075964"
+       height="15.974718"
+       x="6.5332823"
+       y="1026.6744" />
+    <rect
+       style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="rect4735-98"
+       width="21.984022"
+       height="15.841428"
+       x="9.935029"
+       y="1031.5178" />
+    <path
+       style="fill:none;stroke:#c9c9c9;stroke-width:0.1497674;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
+       d="m 9.6777028,1035.2539 22.2349202,0"
+       id="path3768-2-4"
+       inkscape:connector-curvature="0" />
+    <path
+       style="fill:none;stroke:#c9c9c9;stroke-width:0.14911523;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
+       d="m 9.8065855,1043.4054 22.0416915,0"
+       id="path3768-1-6"
+       inkscape:connector-curvature="0" />
+    <path
+       style="fill:none;stroke:#c9c9c9;stroke-width:0.18860409;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+       d="m 13.924764,1031.4401 0,15.8294"
+       id="path3755-4-54"
+       inkscape:connector-curvature="0" />
+    <path
+       style="fill:none;stroke:#c9c9c9;stroke-width:0.18860409;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+       d="m 17.785182,1031.4401 0,15.8294"
+       id="path3755-4-0-5"
+       inkscape:connector-curvature="0" />
+    <path
+       style="fill:none;stroke:#c9c9c9;stroke-width:0.18860409;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+       d="m 21.6456,1031.4401 0,15.8294"
+       id="path3755-4-5-9"
+       inkscape:connector-curvature="0" />
+    <path
+       style="fill:none;stroke:#c9c9c9;stroke-width:0.18860409;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+       d="m 25.506016,1031.4401 0,15.8294"
+       id="path3755-4-9-87"
+       inkscape:connector-curvature="0" />
+    <path
+       style="fill:none;stroke:#c9c9c9;stroke-width:0.18860409;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+       d="m 29.366433,1031.4401 0,15.8294"
+       id="path3755-4-7-4"
+       inkscape:connector-curvature="0" />
+    <path
+       style="fill:none;stroke:#000000;stroke-width:0.29803008;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
+       d="m 9.807449,1039.3297 22.012079,0"
+       id="path3768-6"
+       inkscape:connector-curvature="0" />
+    <path
+       inkscape:connector-curvature="0"
+       style="fill:none;stroke:#2e0dff;stroke-width:0.802;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+       d="m 10.235728,1039.4202 c 0.184303,-0.3999 0.368606,-0.8 0.552909,-1.1919 0.184303,-0.3921 0.368605,-0.7762 0.552908,-1.1447 0.184303,-0.3686 0.368606,-0.7216 0.552909,-1.0521 0.184303,-0.3303 0.368606,-0.6383 0.552908,-0.9175 0.184303,-0.2794 0.368606,-0.5299 0.552909,-0.7468 0.184303,-0.2172 0.368606,-0.4004 0.552908,-0.5466 0.184303,-0.1461 0.368606,-0.2549 0.552909,-0.3244 0.184303,-0.069 0.368606,-0.1 0.552909,-0.09 0.184302,0.011 0.368605,0.06 0.552908,0.1489 0.184303,0.09 0.368606,0.217 0.552909,0.3815 0.184302,0.1645 0.368605,0.3655 0.552908,0.5989 0.184303,0.2335 0.368606,0.4995 0.552909,0.7927 0.184302,0.2931 0.368605,0.6135 0.552908,0.9549 0.184303,0.3412 0.368606,0.7034 0.552909,1.0792 0.184302,0.3758 0.368605,0.7653 0.552908,1.1608 0.184303,0.3956 0.368606,0.7969 0.552909,1.1964 0.184302,0.3994 0.368605,0.7969 0.552908,1.1845 0.184303,0.3876 0.368606,0.7653 0.552909,1.1257 0.184302,0.3603 0.368605,0.7033 0.552908,1.022 0.184303,0.3189 0.368606,0.6135 0.552909,0.8782 0.184303,0.2646 0.368605,0.4992 0.552908,0.6992 0.184303,0.2001 0.368606,0.3653 0.552909,0.4927 0.184303,0.1274 0.368605,0.2168 0.552908,0.2665 0.184303,0.05 0.368606,0.06 0.552909,0.031 0.184303,-0.031 0.368605,-0.1 0.552908,-0.2079 0.184303,-0.1088 0.368606,-0.2552 0.552909,-0.4377 0.184303,-0.1824 0.368606,-0.4005 0.552908,-0.6498 0.184303,-0.2495 0.368606,-0.5301 0.552909,-0.8364 0.184303,-0.3065 0.368606,-0.6385 0.552908,-0.9897 0.184303,-0.3513 0.368606,-0.7217 0.552909,-1.1039 0.184303,-0.3821 0.368606,-0.7762 0.552908,-1.1741 0.184303,-0.398 0.368606,-0.8 0.552909,-1.1979 0.184303,-0.398 0.368606,-0.7919 0.552909,-1.1742 0.184302,-0.3821 0.368605,-0.7525 0.552908,-1.1038 0.184303,-0.3512 0.368606,-0.6833 0.552909,-0.9896 0.184302,-0.3064 0.368605,-0.587 0.552908,-0.8364 0.184303,-0.2494 0.368606,-0.4675 0.552909,-0.6499 0.184302,-0.1825 0.368605,-0.3294 0.552908,-0.4377 0.184303,-0.1088 0.368606,-0.1782 0.552909,-0.208"
+       title="sin(x)"
+       id="path4190-84"
+       sodipodi:nodetypes="ccccccccccscccsccsccccscccccccccccccsccc" />
+    <rect
+       style="fill:none;stroke:#000000;stroke-width:0.29496232;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+       id="rect3905-86"
+       width="22.075964"
+       height="15.974718"
+       x="9.8683844"
+       y="1031.451" />
+    <rect
+       style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="rect4735-23"
+       width="21.984022"
+       height="15.841428"
+       x="13.270129"
+       y="1036.2946" />
+    <path
+       style="fill:none;stroke:#c9c9c9;stroke-width:0.1497674;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
+       d="m 13.012803,1040.0306 22.23492,0"
+       id="path3768-2-5"
+       inkscape:connector-curvature="0" />
+    <path
+       style="fill:none;stroke:#c9c9c9;stroke-width:0.14911523;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
+       d="m 13.141686,1048.1821 22.041691,0"
+       id="path3768-1-5"
+       inkscape:connector-curvature="0" />
+    <path
+       style="fill:none;stroke:#c9c9c9;stroke-width:0.18860409;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+       d="m 17.259864,1036.2168 0,15.8294"
+       id="path3755-4-6"
+       inkscape:connector-curvature="0" />
+    <path
+       style="fill:none;stroke:#c9c9c9;stroke-width:0.18860409;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+       d="m 21.120282,1036.2168 0,15.8294"
+       id="path3755-4-0-35"
+       inkscape:connector-curvature="0" />
+    <path
+       style="fill:none;stroke:#c9c9c9;stroke-width:0.18860409;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+       d="m 24.9807,1036.2168 0,15.8294"
+       id="path3755-4-5-82"
+       inkscape:connector-curvature="0" />
+    <path
+       style="fill:none;stroke:#c9c9c9;stroke-width:0.18860409;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+       d="m 28.841116,1036.2168 0,15.8294"
+       id="path3755-4-9-5"
+       inkscape:connector-curvature="0" />
+    <path
+       style="fill:none;stroke:#c9c9c9;stroke-width:0.18860409;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+       d="m 32.701533,1036.2168 0,15.8294"
+       id="path3755-4-7-7"
+       inkscape:connector-curvature="0" />
+    <path
+       style="fill:none;stroke:#000000;stroke-width:0.29803008;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
+       d="m 13.142549,1044.1064 22.012079,0"
+       id="path3768-25"
+       inkscape:connector-curvature="0" />
+    <path
+       inkscape:connector-curvature="0"
+       style="fill:none;stroke:#2e0dff;stroke-width:0.802;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+       d="m 13.570828,1044.1969 c 0.184303,-0.3999 0.368606,-0.8 0.552909,-1.1919 0.184303,-0.3921 0.368605,-0.7762 0.552908,-1.1447 0.184303,-0.3686 0.368606,-0.7216 0.552909,-1.0521 0.184303,-0.3303 0.368606,-0.6383 0.552908,-0.9175 0.184303,-0.2794 0.368606,-0.5299 0.552909,-0.7468 0.184303,-0.2172 0.368606,-0.4004 0.552908,-0.5466 0.184303,-0.1461 0.368606,-0.2549 0.552909,-0.3244 0.184303,-0.069 0.368606,-0.1 0.552909,-0.09 0.184302,0.011 0.368605,0.06 0.552908,0.1489 0.184303,0.09 0.368606,0.217 0.552909,0.3815 0.184302,0.1645 0.368605,0.3655 0.552908,0.5989 0.184303,0.2335 0.368606,0.4995 0.552909,0.7927 0.184302,0.2931 0.368605,0.6135 0.552908,0.9549 0.184303,0.3412 0.368606,0.7034 0.552909,1.0792 0.184303,0.3758 0.368605,0.7653 0.552908,1.1608 0.184303,0.3956 0.368606,0.7969 0.552909,1.1964 0.184303,0.3994 0.368605,0.7969 0.552908,1.1845 0.184303,0.3876 0.368606,0.7653 0.552909,1.1257 0.184302,0.3603 0.368605,0.7033 0.552908,1.022"
+       title="sin(x)"
+       id="path4190-80"
+       sodipodi:nodetypes="ccccccccccscccsccscc" />
+    <rect
+       style="fill:none;stroke:#000000;stroke-width:0.29496232;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+       id="rect3905-9"
+       width="22.075964"
+       height="15.974718"
+       x="13.203484"
+       y="1036.2278" />
+  </g>
+</svg>
diff --git a/icons/zoom-original.png b/icons/zoom-original.png
deleted file mode 100644 (file)
index 8ae3043..0000000
Binary files a/icons/zoom-original.png and /dev/null differ
index ce7db5fadcc2a18a05d567a0ac284cfe7065595f..a77969ea7f72313e6c42b71cf0cd09980c53e0da 100644 (file)
--- a/main.cpp
+++ b/main.cpp
 #endif
 
 #include <cstdint>
-#include <libsigrokcxx/libsigrokcxx.hpp>
-
+#include <fstream>
 #include <getopt.h>
+#include <vector>
+
+#include <libsigrokcxx/libsigrokcxx.hpp>
 
+#include <QCheckBox>
 #include <QDebug>
+#include <QFile>
+#include <QFileInfo>
+#include <QMessageBox>
 #include <QSettings>
+#include <QTextStream>
+
+#include "config.h"
 
 #ifdef ENABLE_SIGNALS
 #include "signalhandler.hpp"
 #endif
 
+#ifdef ENABLE_STACKTRACE
+#include <signal.h>
+#include <boost/stacktrace.hpp>
+#include <QStandardPaths>
+#endif
+
 #include "pv/application.hpp"
 #include "pv/devicemanager.hpp"
+#include "pv/globalsettings.hpp"
+#include "pv/logging.hpp"
 #include "pv/mainwindow.hpp"
+#include "pv/session.hpp"
+#include "pv/util.hpp"
+
 #ifdef ANDROID
 #include <libsigrokandroidutils/libsigrokandroidutils.h>
 #include "android/assetreader.hpp"
 #include "android/loghandler.hpp"
 #endif
 
-#include "config.h"
-
 #ifdef _WIN32
 #include <QtPlugin>
 Q_IMPORT_PLUGIN(QWindowsIntegrationPlugin)
@@ -51,9 +69,76 @@ Q_IMPORT_PLUGIN(QSvgPlugin)
 #endif
 
 using std::exception;
+using std::ifstream;
+using std::ofstream;
 using std::shared_ptr;
 using std::string;
 
+#if ENABLE_STACKTRACE
+QString stacktrace_filename;
+
+void signal_handler(int signum)
+{
+       ::signal(signum, SIG_DFL);
+       boost::stacktrace::safe_dump_to(stacktrace_filename.toLocal8Bit().data());
+       ::raise(SIGABRT);
+}
+
+void process_stacktrace(QString temp_path)
+{
+       const QString stacktrace_outfile = temp_path + "/pv_stacktrace.txt";
+
+       ifstream ifs(stacktrace_filename.toLocal8Bit().data());
+       ofstream ofs(stacktrace_outfile.toLocal8Bit().data(),
+               ofstream::out | ofstream::trunc);
+
+       boost::stacktrace::stacktrace st =
+               boost::stacktrace::stacktrace::from_dump(ifs);
+       ofs << st;
+
+       ofs.close();
+       ifs.close();
+
+       QFile f(stacktrace_outfile);
+       f.open(QFile::ReadOnly | QFile::Text);
+       QTextStream fs(&f);
+       QString stacktrace = fs.readAll();
+       stacktrace = stacktrace.trimmed().replace('\n', "<br />");
+
+       qDebug() << QObject::tr("Stack trace of previous crash:");
+       qDebug() << "---------------------------------------------------------";
+       // Note: qDebug() prints quotation marks for QString output, so we feed it char*
+       qDebug() << stacktrace.toLocal8Bit().data();
+       qDebug() << "---------------------------------------------------------";
+
+       f.close();
+
+       // Remove stack trace so we don't process it again the next time we run
+       QFile::remove(stacktrace_filename.toLocal8Bit().data());
+
+       // Show notification dialog if permitted
+       pv::GlobalSettings settings;
+       if (settings.value(pv::GlobalSettings::Key_Log_NotifyOfStacktrace).toBool()) {
+               QCheckBox *cb = new QCheckBox(QObject::tr("Don't show this message again"));
+
+               QMessageBox msgbox;
+               msgbox.setText(QObject::tr("When %1 last crashed, it created a stack trace.\n" \
+                       "A human-readable form has been saved to disk and was written to " \
+                       "the log. You may access it from the settings dialog.").arg(PV_TITLE));
+               msgbox.setIcon(QMessageBox::Icon::Information);
+               msgbox.addButton(QMessageBox::Ok);
+               msgbox.setCheckBox(cb);
+
+               QObject::connect(cb, &QCheckBox::stateChanged, [](int state){
+                       pv::GlobalSettings settings;
+                       settings.setValue(pv::GlobalSettings::Key_Log_NotifyOfStacktrace,
+                               !state); });
+
+               msgbox.exec();
+       }
+}
+#endif
+
 void usage()
 {
        fprintf(stdout,
@@ -66,6 +151,8 @@ void usage()
                "Application Options:\n"
                "  -V, --version                   Show release version\n"
                "  -l, --loglevel                  Set libsigrok/libsigrokdecode loglevel\n"
+               "  -d, --driver                    Specify the device driver to use\n"
+               "  -D, --dont-scan                 Don't auto-scan for devices, use -d spec only\n"
                "  -i, --input-file                Load input from file\n"
                "  -I, --input-format              Input format\n"
                "  -c, --clean                     Don't restore previous sessions on startup\n"
@@ -76,8 +163,11 @@ int main(int argc, char *argv[])
 {
        int ret = 0;
        shared_ptr<sigrok::Context> context;
-       string open_file, open_file_format;
+       string open_file_format, driver;
+       vector<string> open_files;
        bool restore_sessions = true;
+       bool do_scan = true;
+       bool show_version = false;
 
        Application a(argc, argv);
 
@@ -93,14 +183,17 @@ int main(int argc, char *argv[])
                        {"help", no_argument, nullptr, 'h'},
                        {"version", no_argument, nullptr, 'V'},
                        {"loglevel", required_argument, nullptr, 'l'},
+                       {"driver", required_argument, nullptr, 'd'},
+                       {"dont-scan", no_argument, nullptr, 'D'},
                        {"input-file", required_argument, nullptr, 'i'},
                        {"input-format", required_argument, nullptr, 'I'},
                        {"clean", no_argument, nullptr, 'c'},
+                       {"log-to-stdout", no_argument, nullptr, 's'},
                        {nullptr, 0, nullptr, 0}
                };
 
                const int c = getopt_long(argc, argv,
-                       "l:Vhc?i:I:", long_options, nullptr);
+                       "h?VDcl:d:i:I:", long_options, nullptr);
                if (c == -1)
                        break;
 
@@ -111,13 +204,16 @@ int main(int argc, char *argv[])
                        return 0;
 
                case 'V':
-                       // Print version info
-                       fprintf(stdout, "%s %s\n", PV_TITLE, PV_VERSION_STRING);
-                       return 0;
+                       show_version = true;
+                       break;
 
                case 'l':
                {
                        const int loglevel = atoi(optarg);
+                       if (loglevel < 0 || loglevel > 5) {
+                               qDebug() << "ERROR: invalid log level spec.";
+                               break;
+                       }
                        context->set_log_level(sigrok::LogLevel::get(loglevel));
 
 #ifdef ENABLE_DECODE
@@ -132,8 +228,16 @@ int main(int argc, char *argv[])
                        break;
                }
 
+               case 'd':
+                       driver = optarg;
+                       break;
+
+               case 'D':
+                       do_scan = false;
+                       break;
+
                case 'i':
-                       open_file = optarg;
+                       open_files.emplace_back(optarg);
                        break;
 
                case 'I':
@@ -145,17 +249,40 @@ int main(int argc, char *argv[])
                        break;
                }
        }
+       argc -= optind;
+       argv += optind;
 
-       if (argc - optind > 1) {
-               fprintf(stderr, "Only one file can be opened.\n");
-               return 1;
-       }
+       for (int i = 0; i < argc; i++)
+               open_files.emplace_back(argv[i]);
+
+       qRegisterMetaType<pv::util::Timestamp>("util::Timestamp");
+       qRegisterMetaType<uint64_t>("uint64_t");
+
+       // Prepare the global settings since logging needs them early on
+       pv::GlobalSettings settings;
+       settings.save_internal_defaults();
+       settings.set_defaults_where_needed();
+       settings.apply_theme();
 
-       if (argc - optind == 1)
-               open_file = argv[argc - 1];
+       pv::logging.init();
 
        // Initialise libsigrok
        context = sigrok::Context::create();
+       pv::Session::sr_context = context;
+
+#if ENABLE_STACKTRACE
+       QString temp_path = QStandardPaths::standardLocations(
+               QStandardPaths::TempLocation).at(0);
+       stacktrace_filename = temp_path + "/pv_stacktrace.dmp";
+       qDebug() << "Stack trace file is" << stacktrace_filename;
+
+       ::signal(SIGSEGV, &signal_handler);
+       ::signal(SIGABRT, &signal_handler);
+
+       if (QFileInfo::exists(stacktrace_filename))
+               process_stacktrace(temp_path);
+#endif
+
 #ifdef ANDROID
        context->set_resource_reader(&asset_reader);
 #endif
@@ -172,10 +299,17 @@ int main(int argc, char *argv[])
                srd_decoder_load_all();
 #endif
 
+#ifndef ENABLE_STACKTRACE
                try {
-                       // Create the device manager, initialise the drivers
-                       pv::DeviceManager device_manager(context);
+#endif
+
+               // Create the device manager, initialise the drivers
+               pv::DeviceManager device_manager(context, driver, do_scan);
 
+               a.collect_version_info(context);
+               if (show_version) {
+                       a.print_version_info();
+               } else {
                        // Initialise the main window
                        pv::MainWindow w(device_manager);
                        w.show();
@@ -183,33 +317,32 @@ int main(int argc, char *argv[])
                        if (restore_sessions)
                                w.restore_sessions();
 
-                       if (!open_file.empty())
-                               w.add_session_with_file(open_file, open_file_format);
-                       else
+                       if (open_files.empty())
                                w.add_default_session();
+                       else
+                               for (string& open_file : open_files)
+                                       w.add_session_with_file(open_file, open_file_format);
 
 #ifdef ENABLE_SIGNALS
                        if (SignalHandler::prepare_signals()) {
-                               SignalHandler *const handler =
-                                       new SignalHandler(&w);
-                               QObject::connect(handler,
-                                       SIGNAL(int_received()),
+                               SignalHandler *const handler = new SignalHandler(&w);
+                               QObject::connect(handler, SIGNAL(int_received()),
                                        &w, SLOT(close()));
-                               QObject::connect(handler,
-                                       SIGNAL(term_received()),
+                               QObject::connect(handler, SIGNAL(term_received()),
                                        &w, SLOT(close()));
-                       } else {
-                               qWarning() <<
-                                       "Could not prepare signal handler.";
-                       }
+                       } else
+                               qWarning() << "Could not prepare signal handler.";
 #endif
 
                        // Run the application
                        ret = a.exec();
+               }
 
-               } catch (exception e) {
-                       qDebug() << e.what();
+#ifndef ENABLE_STACKTRACE
+               } catch (exception& e) {
+                       qDebug() << "Exception:" << e.what();
                }
+#endif
 
 #ifdef ENABLE_DECODE
                // Destroy libsigrokdecode
diff --git a/manual/CMakeLists.txt b/manual/CMakeLists.txt
new file mode 100644 (file)
index 0000000..c425f36
--- /dev/null
@@ -0,0 +1,87 @@
+##
+## This file is part of the PulseView project.
+##
+## Copyright (C) 2018 Gerhard Sittig <gerhard.sittig@gmx.net>
+##
+## This program 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 2 of the License, or
+## (at your option) any later version.
+##
+## This program 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 this program.  If not, see <http://www.gnu.org/licenses/>.
+##
+
+cmake_minimum_required(VERSION 2.8.12)
+
+# External dependencies, required and optional tools.
+find_program(ASCIIDOCTOR_EXECUTABLE NAMES asciidoctor)
+find_program(ASCIIDOCTOR_PDF_EXECUTABLE NAMES asciidoctor-pdf)
+
+# Tunables.
+set(STYLES_DIR "asciidoctor-stylesheet-factory/stylesheets")
+set(STYLE_SHEET "readthedocs.css")
+
+# Input files.
+set(MANUAL_SRC "${CMAKE_CURRENT_SOURCE_DIR}/manual.txt")
+
+# Output files, conversion results.
+set(MANUAL_OUT_HTML "${CMAKE_CURRENT_BINARY_DIR}/manual.html")
+set(MANUAL_OUT_PDF "${CMAKE_CURRENT_BINARY_DIR}/manual.pdf")
+
+# Manual related make(1) targets.
+add_custom_target(manual-html
+       COMMAND ${ASCIIDOCTOR_EXECUTABLE}
+               -a stylesheet=${STYLE_SHEET}
+               -a stylesdir=${CMAKE_CURRENT_SOURCE_DIR}/${STYLES_DIR}
+               -a toc=left
+               --destination-dir=${CMAKE_CURRENT_BINARY_DIR}
+               ${MANUAL_SRC}
+       BYPRODUCTS ${MANUAL_OUT_HTML}
+       DEPENDS ${MANUAL_SRC}
+       WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
+       COMMENT "Generating manual, HTML output"
+)
+if (ASCIIDOCTOR_PDF_EXECUTABLE)
+       add_custom_target(manual-pdf
+               COMMAND ${ASCIIDOCTOR_PDF_EXECUTABLE}
+                       -a stylesheet=${STYLE_SHEET}
+                       -a stylesdir=${CMAKE_CURRENT_SOURCE_DIR}/${STYLES_DIR}
+                       --destination-dir=${CMAKE_CURRENT_BINARY_DIR}
+                       ${MANUAL_SRC}
+               BYPRODUCTS ${MANUAL_OUT_PDF}
+               DEPENDS ${MANUAL_SRC}
+               WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
+               COMMENT "Generating manual, HTML output"
+       )
+else ()
+       add_custom_target(manual-pdf
+               COMMAND ${CMAKE_COMMAND} -E echo
+                       "asciidoctor-pdf executable is missing, NOT generating PDF output"
+               DEPENDS ${MANUAL_SRC}
+               WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
+       )
+endif ()
+add_custom_target(manual)
+add_dependencies(manual manual-html manual-pdf)
+
+set(MANUAL_INST_SUBDIR "share/doc/pulseview")
+install(
+       FILES ${MANUAL_OUT_HTML} ${MANUAL_OUT_PDF}
+       DESTINATION ${MANUAL_INST_SUBDIR}
+       PERMISSIONS OWNER_READ OWNER_WRITE GROUP_READ WORLD_READ
+       OPTIONAL
+)
+if (ASCIIDOCTOR_EXECUTABLE)
+       install(
+               DIRECTORY images
+               DESTINATION ${MANUAL_INST_SUBDIR}
+               FILE_PERMISSIONS OWNER_READ OWNER_WRITE GROUP_READ WORLD_READ
+               PATTERN "*.xcf" EXCLUDE
+       )
+endif ()
diff --git a/manual/acquisition.txt b/manual/acquisition.txt
new file mode 100644 (file)
index 0000000..685c9cd
--- /dev/null
@@ -0,0 +1,134 @@
+== Data Acquisition
+
+Working with PulseView follows a pattern:
+
+image::pv_nodevice.png[]
+<1> Open a new session
+<2> Select the device you want to work with:
+<3> Click "Run" to acquire signal data (waiting for a trigger first if you set one)
+
+When you start PulseView and no sessions are restored from the last time you used it, it will
+come up with a session that has the demo device selected. That way, you can get to know the
+program even when you don't have any hardware to use it with.
+
+=== Device Selection
+
+The device selector offers two methods to choose the device to use. If you click on the small
+arrow on the side, you see a list of devices PulseView has recognized. If the device you want
+to use it listed, you can just select it here to use it.
+
+image::device_selector_dropdown.png[]
+
+If it's not listed, you'll need to scan for it first. Since most serial port and Ethernet
+devices can't be auto-detected, this is usually required for those.
+To do so, either choose the "Connect to Device" option from the list or click on the button
+itself. You will see the following dialog:
+
+image::device_selector_scan.png[]
+
+First, you'll need to pick a driver that you want to use. In order to do this, you'll need
+to know which driver is used to talk to the device. If you're unsure, you can either try the
+driver which you think may fit best or you can check the wiki. For every supported device there's
+a wiki page, showing you which driver is used.
+
+Once the driver has been chosen, you need to select the interface. Please be aware that USB
+is only usable for devices that directly communicate over USB. Devices that use USB to emulate
+a serial port (like the OpenBench Logic Sniffer) will have their serial port listed in the
+serial port drop-down.
+
+In case your device connects via Ethernet, you must supply the IP address and port. You are
+also given the option to choose between raw TCP access and using the VXI protocol. VXI is an
+industry standard which is mainly used in professional equipment and the device will most
+likely let you know that it supports VXI. If your device however is more of a hobbyist grade
+device, it's more likely that using raw TCP will be the correct choice.
+
+After you selected the appropriate options, clicking the scan button will make PulseView try
+to connect to the device with the given settings. If successful, any device(s) found will be
+shown in the list box.
+
+[NOTE]
+When a session uses a USB device and you close Pulseview, a session with that same device
+is re-opened when you start Pulseview again. Currently, this is however not the case for non-USB
+devices, such as ones that connect via serial port or Ethernet.
+
+[NOTE]
+To avoid having to manually enter the device configuration for a serial port or Ethernet
+device every time you want to use it and then having to scan for it, you can also use the
+command line parameter -d to have PulseView scan for it on startup.
+
+You may then change the device configuration and/or start the data acquisition by clicking
+the "Run" button on the top left.
+
+When you run the acquisition, you'll notice that the newly captured data goes off-screen.
+This is to improve performance and let PulseView acquire the data without bogging down your
+CPU too much. If you find this inconvenient because you'd like to see what kind of data is
+coming in, you have three options:
+
+* Enable "always perform zoom-to-fit" temporarily (see chapter "Data Analysis")
+* Enable "constantly perform zoom-to-fit during acquisition" in the options
+* Enable "always keep newest samples at the right edge during capture" in the options
+
+Which method suits you best is up for you to decide.
+
+=== Device Configuration
+
+In PulseView, the device configuration is done using these buttons:
+
+image::pv_device_config.png[]
+<1> Device-specific settings
+<2> Channel-specific settings
+<3> Number of samples to capture
+<4> Sample rate at which to capture the samples
+<5> Per-channel trigger setting (see below)
+
+The values offered for those four elements depend on your device. Which settings you should choose
+depends on several factors: the needs of your measurement, the device you use to capture the data
+and the capabilities of your computer.
+
+The sample rate you choose must at least be twice that of the highest frequency you want to
+capture - ideally 3 to 5 times as much so that you have some margin. That way, a jittering signal
+won't ruin your measurements.
+
+[NOTE]
+If you're using a device with a Cypress FX2 (most 8 channel / 24 MHz logic analyzers do) then you should
+be aware that the 24 MHz sampling rate (12 MHz for 16 channels) can only be sustained under perfect
+conditions. Usually, those devices are shipped with low-quality USB cables, impairing USB transfers as
+USB traffic increases. Therefore, you can try a different USB cable if you're facing issues at higher
+sample rates. If they persist, it's worth trying a different USB port as well.
+
+=== Triggers
+
+The signal labels on the left side of the view (D0, D1 and so on in the picture above) allow you to
+configure certain aspects of these signals. If the device supports it then the trigger that will be
+used for this signal will be among them.
+
+As of now, the trigger system is awaiting extension for advanced and complex trigger types, meaning
+that the only triggers available to you are:
+
+* Trigger when the signal has a "low" level
+* Trigger when the signal has a "high" level
+* Trigger when the signal switches from "low" to "high" level (rising edge)
+* Trigger when the signal switches from "hig" to "low" level (falling edge)
+* Trigger when the signal changes level in any way (any edge)
+
+Once you choose a trigger, the icon for the type you chose becomes visible on the right side of the
+trace view.
+
+When you click "Run" with a trigger configured, PulseView will wait for the device to trigger and
+send data before it can show anything. There is currently no frame limit, so if the device driver
+supports it, PulseView will continue arming the trigger and collecting data until you either click
+"Stop" or it runs out of memory.
+
+=== Channel Groups
+
+Some devices share certain settings between a group of channels, which is why PulseView may show
+the channels your device offers in groups. You can see which channels are grouped by looking at the
+dark gray bar on the left. If there is none, no channels are grouped.
+
+Currently, the grouping is only done for your convenience and there's no direct functional impact.
+This means that you're free to ungroup and group channels as you please. To do so, right-click
+on the dark gray bar and select "Ungroup".
+If you want to create a new group, select the signals you want to group by holding down CTRL
+and clicking on the signal labels. Once you have selected the ones you want to be grouped,
+right-click on one of the labels you selected and choose "Group".
+
diff --git a/manual/analysis.txt b/manual/analysis.txt
new file mode 100644 (file)
index 0000000..7aa487b
--- /dev/null
@@ -0,0 +1,84 @@
+== Data Analysis
+
+Once you have acquired some measurement data, it's time to have a look and see what
+insights you can gain from it. Usually, the first step is to look at the data as a
+whole, achieved by clicking the _Zoom to Fit_ button:
+
+image::pv_analysis.png[]
+
+<1> Zoom-to-Fit button
+<2> Zoom in/zoom out buttons
+<3> Cursors
+<4> Time scale (used to set up and show markers, see below)
+
+If you have located an area of interest (maybe with the help of decoders, more about
+that later), you can zoom in on it using the _zoom in_/_zoom out_ buttons, using the
+scroll wheel of your mouse or the pinch/expand gestures on your touch panel.
+
+[NOTE]
+When a data capture is ongoing, the Zoom-to-Fit button stays active if you click it,
+meaning that PulseView automatically fits all data to the views until either the
+capture is finished or the Zoom-to-Fit button is clicked again.
+If you want this feature but don't want to always have to click the button, you
+can enable the "Always Zoom-to-Fit" option in the settings.
+
+=== Cursors and Markers
+
+Just looking at the signal data however is usually not sufficient. A lot of times,
+you'll want to make sure that timings are honored and the bit times are like what
+you'd expect. To do so, you'll want to use cursors and markers.
+
+In the picture above, you can enable the cursor by clicking on the cursor button.
+You can move both of its boundaries around by clicking on the blue flags in the
+time scale area. The area between the two boundary lines shows the time distance
+and its inverse (i.e. the frequency). If you can't see it, just zoom in until it
+shows. You can also move both boundaries at the same time by dragging the label
+where this information is shown.
+
+image::pv_cursors_markers.png[]
+
+<1> Cursors button, showing enabled state
+<2> Cursor
+<3> Marker
+
+Markers are movable indicators that you can create wherever you like on the
+time scale - just double-click on it and it'll create one for you where your
+mouse cursor is at the time, or use the context menu when right-clicking on
+the ruler or a signal trace.
+You can click on its label and you'll have the option to change its name, or
+drag it to reposition it.
+
+[NOTE]
+For timing comparison purposes, you can also enable a vertical marker line that
+follows your mouse cursor: _Settings_ -> _Views_ -> _Highlight mouse cursor_
+
+[NOTE]
+There is also a special kind of marker that appears for each time the data
+acquisition device has triggered. It cannot be moved and appears as a vertical
+dashed line.
+
+=== Special-Purpose Decoders
+
+There are some decoders available that analyze the data instead of decoding it.
+You can make use of them to examine various properties of the signals that are
+of interest to you.
+
+Their names are:
+
+* Counter - counts pulses and/or groups of pulses (i.e. words)
+* Guess bitrate - guesses the bitrate when using a serial protocol
+* Jitter - determines the jitter (variance) of a signal
+* Timing - shows the time passing between the chosen signal edges
+
+=== Other Features
+
+Trace Views also allow you to maximize the viewing area by minimizing the area
+occupied by the label area on the left. To do this, simply position the mouse
+cursor at the right edge of the label area (or left edge of the viewing area).
+Your mouse cursor will change shape and you now can drag the border.
+
+This way, you can give signals long, expressive names without clogging up the
+view area.
+
+Also, you can create multiple views by clicking on the "New View" button on
+the very left of the toolbar. Those can be rearranged as you wish.
diff --git a/manual/asciidoctor-stylesheet-factory/LICENSE b/manual/asciidoctor-stylesheet-factory/LICENSE
new file mode 100644 (file)
index 0000000..5f4d18e
--- /dev/null
@@ -0,0 +1,45 @@
+Asciidoctor styles
+------------------
+
+Copyright (c) 2013 Dan Allen
+
+MIT License
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+
+Other licensed work
+-------------------
+
+- Foundation 4 by Zurb, on which the themes are built, is licensed under the
+  Apache License, v2.0:
+
+  http://apache.org/licenses/LICENSE-2.0
+  http://foundation.zurb.com
+
+- The riak theme is derived from the Riak documentation theme by Basho,
+  licensed under the Creative Commons Attribution 3.0 Unported License:
+
+  http://creativecommons.org/licenses/by/3.0/us
+  http://docs.basho.org
+
+- The iconic theme is inspired by O'Reilly typography and Atlas manual.
+
+  http://oreilly.com
diff --git a/manual/asciidoctor-stylesheet-factory/stylesheets/readthedocs.css b/manual/asciidoctor-stylesheet-factory/stylesheets/readthedocs.css
new file mode 100644 (file)
index 0000000..7adc8d1
--- /dev/null
@@ -0,0 +1,727 @@
+/*! normalize.css v2.1.2 | MIT License | git.io/normalize */
+/* ========================================================================== HTML5 display definitions ========================================================================== */
+/** Correct `block` display not defined in IE 8/9. */
+article, aside, details, figcaption, figure, footer, header, hgroup, main, nav, section, summary { display: block; }
+
+/** Correct `inline-block` display not defined in IE 8/9. */
+audio, canvas, video { display: inline-block; }
+
+/** Prevent modern browsers from displaying `audio` without controls. Remove excess height in iOS 5 devices. */
+audio:not([controls]) { display: none; height: 0; }
+
+/** Address `[hidden]` styling not present in IE 8/9. Hide the `template` element in IE, Safari, and Firefox < 22. */
+[hidden], template { display: none; }
+
+script { display: none !important; }
+
+/* ========================================================================== Base ========================================================================== */
+/** 1. Set default font family to sans-serif. 2. Prevent iOS text size adjust after orientation change, without disabling user zoom. */
+html { font-family: sans-serif; /* 1 */ -ms-text-size-adjust: 100%; /* 2 */ -webkit-text-size-adjust: 100%; /* 2 */ }
+
+/** Remove default margin. */
+body { margin: 0; }
+
+/* ========================================================================== Links ========================================================================== */
+/** Remove the gray background color from active links in IE 10. */
+a { background: transparent; }
+
+/** Address `outline` inconsistency between Chrome and other browsers. */
+a:focus { outline: thin dotted; }
+
+/** Improve readability when focused and also mouse hovered in all browsers. */
+a:active, a:hover { outline: 0; }
+
+/* ========================================================================== Typography ========================================================================== */
+/** Address variable `h1` font-size and margin within `section` and `article` contexts in Firefox 4+, Safari 5, and Chrome. */
+h1 { font-size: 2em; margin: 0.67em 0; }
+
+/** Address styling not present in IE 8/9, Safari 5, and Chrome. */
+abbr[title] { border-bottom: 1px dotted; }
+
+/** Address style set to `bolder` in Firefox 4+, Safari 5, and Chrome. */
+b, strong { font-weight: bold; }
+
+/** Address styling not present in Safari 5 and Chrome. */
+dfn { font-style: italic; }
+
+/** Address differences between Firefox and other browsers. */
+hr { -moz-box-sizing: content-box; box-sizing: content-box; height: 0; }
+
+/** Address styling not present in IE 8/9. */
+mark { background: #ff0; color: #000; }
+
+/** Correct font family set oddly in Safari 5 and Chrome. */
+code, kbd, pre, samp { font-family: monospace, serif; font-size: 1em; }
+
+/** Improve readability of pre-formatted text in all browsers. */
+pre { white-space: pre-wrap; }
+
+/** Set consistent quote types. */
+q { quotes: "\201C" "\201D" "\2018" "\2019"; }
+
+/** Address inconsistent and variable font size in all browsers. */
+small { font-size: 80%; }
+
+/** Prevent `sub` and `sup` affecting `line-height` in all browsers. */
+sub, sup { font-size: 75%; line-height: 0; position: relative; vertical-align: baseline; }
+
+sup { top: -0.5em; }
+
+sub { bottom: -0.25em; }
+
+/* ========================================================================== Embedded content ========================================================================== */
+/** Remove border when inside `a` element in IE 8/9. */
+img { border: 0; }
+
+/** Correct overflow displayed oddly in IE 9. */
+svg:not(:root) { overflow: hidden; }
+
+/* ========================================================================== Figures ========================================================================== */
+/** Address margin not present in IE 8/9 and Safari 5. */
+figure { margin: 0; }
+
+/* ========================================================================== Forms ========================================================================== */
+/** Define consistent border, margin, and padding. */
+fieldset { border: 1px solid #c0c0c0; margin: 0 2px; padding: 0.35em 0.625em 0.75em; }
+
+/** 1. Correct `color` not being inherited in IE 8/9. 2. Remove padding so people aren't caught out if they zero out fieldsets. */
+legend { border: 0; /* 1 */ padding: 0; /* 2 */ }
+
+/** 1. Correct font family not being inherited in all browsers. 2. Correct font size not being inherited in all browsers. 3. Address margins set differently in Firefox 4+, Safari 5, and Chrome. */
+button, input, select, textarea { font-family: inherit; /* 1 */ font-size: 100%; /* 2 */ margin: 0; /* 3 */ }
+
+/** Address Firefox 4+ setting `line-height` on `input` using `!important` in the UA stylesheet. */
+button, input { line-height: normal; }
+
+/** Address inconsistent `text-transform` inheritance for `button` and `select`. All other form control elements do not inherit `text-transform` values. Correct `button` style inheritance in Chrome, Safari 5+, and IE 8+. Correct `select` style inheritance in Firefox 4+ and Opera. */
+button, select { text-transform: none; }
+
+/** 1. Avoid the WebKit bug in Android 4.0.* where (2) destroys native `audio` and `video` controls. 2. Correct inability to style clickable `input` types in iOS. 3. Improve usability and consistency of cursor style between image-type `input` and others. */
+button, html input[type="button"], input[type="reset"], input[type="submit"] { -webkit-appearance: button; /* 2 */ cursor: pointer; /* 3 */ }
+
+/** Re-set default cursor for disabled elements. */
+button[disabled], html input[disabled] { cursor: default; }
+
+/** 1. Address box sizing set to `content-box` in IE 8/9. 2. Remove excess padding in IE 8/9. */
+input[type="checkbox"], input[type="radio"] { box-sizing: border-box; /* 1 */ padding: 0; /* 2 */ }
+
+/** 1. Address `appearance` set to `searchfield` in Safari 5 and Chrome. 2. Address `box-sizing` set to `border-box` in Safari 5 and Chrome (include `-moz` to future-proof). */
+input[type="search"] { -webkit-appearance: textfield; /* 1 */ -moz-box-sizing: content-box; -webkit-box-sizing: content-box; /* 2 */ box-sizing: content-box; }
+
+/** Remove inner padding and search cancel button in Safari 5 and Chrome on OS X. */
+input[type="search"]::-webkit-search-cancel-button, input[type="search"]::-webkit-search-decoration { -webkit-appearance: none; }
+
+/** Remove inner padding and border in Firefox 4+. */
+button::-moz-focus-inner, input::-moz-focus-inner { border: 0; padding: 0; }
+
+/** 1. Remove default vertical scrollbar in IE 8/9. 2. Improve readability and alignment in all browsers. */
+textarea { overflow: auto; /* 1 */ vertical-align: top; /* 2 */ }
+
+/* ========================================================================== Tables ========================================================================== */
+/** Remove most spacing between table cells. */
+table { border-collapse: collapse; border-spacing: 0; }
+
+meta.foundation-mq-small { font-family: "only screen and (min-width: 768px)"; width: 768px; }
+
+meta.foundation-mq-medium { font-family: "only screen and (min-width:1280px)"; width: 1280px; }
+
+meta.foundation-mq-large { font-family: "only screen and (min-width:1440px)"; width: 1440px; }
+
+*, *:before, *:after { -moz-box-sizing: border-box; -webkit-box-sizing: border-box; box-sizing: border-box; }
+
+html, body { font-size: 100%; }
+
+body { background: #fff; color: #222; padding: 0; margin: 0; font-family: "Helvetica Neue", "Helvetica", Helvetica, Arial, sans-serif; font-weight: normal; font-style: normal; line-height: 1; position: relative; cursor: auto; }
+
+a:hover { cursor: pointer; }
+
+img, object, embed { max-width: 100%; height: auto; }
+
+object, embed { height: 100%; }
+
+img { -ms-interpolation-mode: bicubic; }
+
+#map_canvas img, #map_canvas embed, #map_canvas object, .map_canvas img, .map_canvas embed, .map_canvas object { max-width: none !important; }
+
+.left { float: left !important; }
+
+.right { float: right !important; }
+
+.text-left { text-align: left !important; }
+
+.text-right { text-align: right !important; }
+
+.text-center { text-align: center !important; }
+
+.text-justify { text-align: justify !important; }
+
+.hide { display: none; }
+
+.antialiased { -webkit-font-smoothing: antialiased; }
+
+img { display: inline-block; vertical-align: middle; }
+
+textarea { height: auto; min-height: 50px; }
+
+select { width: 100%; }
+
+object, svg { display: inline-block; vertical-align: middle; }
+
+.center { margin-left: auto; margin-right: auto; }
+
+.stretch { width: 100%; }
+
+p.lead { font-size: 1.21875em; line-height: 1.6; }
+
+.subheader, .admonitionblock td.content > .title, .audioblock > .title, .exampleblock > .title, .imageblock > .title, .listingblock > .title, .literalblock > .title, .stemblock > .title, .openblock > .title, .paragraph > .title, .quoteblock > .title, table.tableblock > .title, .verseblock > .title, .videoblock > .title, .dlist > .title, .olist > .title, .ulist > .title, .qlist > .title, .hdlist > .title { line-height: 1.4; color: #6c818f; font-weight: 300; margin-top: 0.2em; margin-bottom: 0.5em; }
+
+/* Typography resets */
+div, dl, dt, dd, ul, ol, li, h1, h2, h3, #toctitle, .sidebarblock > .content > .title, h4, h5, h6, pre, form, p, blockquote, th, td { margin: 0; padding: 0; direction: ltr; }
+
+/* Default Link Styles */
+a { color: #444; text-decoration: underline; line-height: inherit; }
+a:hover, a:focus { color: #111; }
+a img { border: none; }
+
+/* Default paragraph styles */
+p { font-family: inherit; font-weight: normal; font-size: 1em; line-height: 1.5; margin-bottom: 1.25em; text-rendering: optimizeLegibility; }
+p aside { font-size: 0.875em; line-height: 1.35; font-style: italic; }
+
+/* Default header styles */
+h1, h2, h3, #toctitle, .sidebarblock > .content > .title, h4, h5, h6 { font-family: ff-meta-web-pro-1, ff-meta-web-pro-2, Arial, "Helvetica Neue", sans-serif; font-weight: bold; font-style: normal; color: #465158; text-rendering: optimizeLegibility; margin-top: 1em; margin-bottom: 0.5em; line-height: 1.2125em; }
+h1 small, h2 small, h3 small, #toctitle small, .sidebarblock > .content > .title small, h4 small, h5 small, h6 small { font-size: 60%; color: #909ea7; line-height: 0; }
+
+h1 { font-size: 2.125em; }
+
+h2 { font-size: 1.6875em; }
+
+h3, #toctitle, .sidebarblock > .content > .title { font-size: 1.375em; }
+
+h4 { font-size: 1.125em; }
+
+h5 { font-size: 1.125em; }
+
+h6 { font-size: 1em; }
+
+hr { border: solid #ddd; border-width: 1px 0 0; clear: both; margin: 1.25em 0 1.1875em; height: 0; }
+
+/* Helpful Typography Defaults */
+em, i { font-style: italic; line-height: inherit; }
+
+strong, b { font-weight: bold; line-height: inherit; }
+
+small { font-size: 60%; line-height: inherit; }
+
+code { font-family: "Consolas", "Deja Vu Sans Mono", "Bitstream Vera Sans Mono", monospace; font-weight: normal; color: #444; }
+
+/* Lists */
+ul, ol, dl { font-size: 1em; line-height: 1.5; margin-bottom: 1.25em; list-style-position: outside; font-family: inherit; }
+
+ul, ol { margin-left: 0; }
+ul.no-bullet, ol.no-bullet { margin-left: 0; }
+
+/* Unordered Lists */
+ul li ul, ul li ol { margin-left: 1.25em; margin-bottom: 0; font-size: 1em; /* Override nested font-size change */ }
+ul.square li ul, ul.circle li ul, ul.disc li ul { list-style: inherit; }
+ul.square { list-style-type: square; }
+ul.circle { list-style-type: circle; }
+ul.disc { list-style-type: disc; }
+ul.no-bullet { list-style: none; }
+
+/* Ordered Lists */
+ol li ul, ol li ol { margin-left: 1.25em; margin-bottom: 0; }
+
+/* Definition Lists */
+dl dt { margin-bottom: 0.3em; font-weight: bold; }
+dl dd { margin-bottom: 0.75em; }
+
+/* Abbreviations */
+abbr, acronym { text-transform: uppercase; font-size: 90%; color: #000; border-bottom: 1px dotted #ddd; cursor: help; }
+
+abbr { text-transform: none; }
+
+/* Blockquotes */
+blockquote { margin: 0 0 1.25em; padding: 0.5625em 1.25em 0 1.1875em; border-left: 1px solid #ddd; }
+blockquote cite { display: block; font-size: 0.8125em; color: #748590; }
+blockquote cite:before { content: "\2014 \0020"; }
+blockquote cite a, blockquote cite a:visited { color: #748590; }
+
+blockquote, blockquote p { line-height: 1.5; color: #909ea7; }
+
+/* Microformats */
+.vcard { display: inline-block; margin: 0 0 1.25em 0; border: 1px solid #ddd; padding: 0.625em 0.75em; }
+.vcard li { margin: 0; display: block; }
+.vcard .fn { font-weight: bold; font-size: 0.9375em; }
+
+.vevent .summary { font-weight: bold; }
+.vevent abbr { cursor: auto; text-decoration: none; font-weight: bold; border: none; padding: 0 0.0625em; }
+
+@media only screen and (min-width: 768px) { h1, h2, h3, #toctitle, .sidebarblock > .content > .title, h4, h5, h6 { line-height: 1.4; }
+  h1 { font-size: 2.75em; }
+  h2 { font-size: 2.3125em; }
+  h3, #toctitle, .sidebarblock > .content > .title { font-size: 1.6875em; }
+  h4 { font-size: 1.4375em; } }
+/* Tables */
+table { background: #fff; margin-bottom: 1.25em; border: solid 0 #ddd; }
+table thead, table tfoot { background: none; font-weight: bold; }
+table thead tr th, table thead tr td, table tfoot tr th, table tfoot tr td { padding: 1px 8px 1px 5px; font-size: 1em; color: #222; text-align: left; }
+table tr th, table tr td { padding: 1px 8px 1px 5px; font-size: 1em; color: #222; }
+table tr.even, table tr.alt, table tr:nth-of-type(even) { background: none; }
+table thead tr th, table tfoot tr th, table tbody tr td, table tr td, table tfoot tr td { display: table-cell; line-height: 1.5; }
+
+body { -moz-osx-font-smoothing: grayscale; -webkit-font-smoothing: antialiased; tab-size: 4; }
+
+h1, h2, h3, #toctitle, .sidebarblock > .content > .title, h4, h5, h6 { line-height: 1.4; }
+
+.clearfix:before, .clearfix:after, .float-group:before, .float-group:after { content: " "; display: table; }
+.clearfix:after, .float-group:after { clear: both; }
+
+*:not(pre) > code { font-size: 0.95em; font-style: normal !important; letter-spacing: 0; padding: 0; background-color: #f2f2f2; -webkit-border-radius: 6px; border-radius: 6px; line-height: inherit; word-wrap: break-word; }
+*:not(pre) > code.nobreak { word-wrap: normal; }
+*:not(pre) > code.nowrap { white-space: nowrap; }
+
+pre, pre > code { line-height: 1.2; color: inherit; font-family: "Consolas", "Deja Vu Sans Mono", "Bitstream Vera Sans Mono", monospace; font-weight: normal; }
+
+em em { font-style: normal; }
+
+strong strong { font-weight: normal; }
+
+.keyseq { color: #333333; }
+
+kbd { font-family: "Consolas", "Deja Vu Sans Mono", "Bitstream Vera Sans Mono", monospace; display: inline-block; color: #000; font-size: 0.65em; line-height: 1.45; background-color: #f7f7f7; border: 1px solid #ccc; -webkit-border-radius: 3px; border-radius: 3px; -moz-box-shadow: 0 1px 0 rgba(0, 0, 0, 0.2), 0 0 0 0.1em white inset; -webkit-box-shadow: 0 1px 0 rgba(0, 0, 0, 0.2), 0 0 0 0.1em white inset; box-shadow: 0 1px 0 rgba(0, 0, 0, 0.2), 0 0 0 0.1em white inset; margin: 0 0.15em; padding: 0.2em 0.5em; vertical-align: middle; position: relative; top: -0.1em; white-space: nowrap; }
+
+.keyseq kbd:first-child { margin-left: 0; }
+
+.keyseq kbd:last-child { margin-right: 0; }
+
+.menuseq, .menuref { color: #000; }
+
+.menuseq b:not(.caret), .menuref { font-weight: inherit; }
+
+.menuseq { word-spacing: -0.02em; }
+.menuseq b.caret { font-size: 1.25em; line-height: 0.8; }
+.menuseq i.caret { font-weight: bold; text-align: center; width: 0.45em; }
+
+b.button:before, b.button:after { position: relative; top: -1px; font-weight: normal; }
+
+b.button:before { content: "["; padding: 0 3px 0 2px; }
+
+b.button:after { content: "]"; padding: 0 2px 0 3px; }
+
+p a > code:hover { color: #373737; }
+
+#header, #content, #footnotes, #footer { width: 100%; margin-left: auto; margin-right: auto; margin-top: 0; margin-bottom: 0; max-width: 62.5em; *zoom: 1; position: relative; padding-left: 0.9375em; padding-right: 0.9375em; }
+#header:before, #header:after, #content:before, #content:after, #footnotes:before, #footnotes:after, #footer:before, #footer:after { content: " "; display: table; }
+#header:after, #content:after, #footnotes:after, #footer:after { clear: both; }
+
+#content { margin-top: 1.25em; }
+
+#content:before { content: none; }
+
+#header > h1:first-child { color: #111; margin-top: 2.25rem; margin-bottom: 0; }
+#header > h1:first-child + #toc { margin-top: 8px; border-top: 1px solid #ddd; }
+#header > h1:only-child, body.toc2 #header > h1:nth-last-child(2) { border-bottom: 1px solid #ddd; padding-bottom: 8px; }
+#header .details { border-bottom: 1px solid #ddd; line-height: 1.45; padding-top: 0.25em; padding-bottom: 0.25em; padding-left: 0.25em; color: #748590; display: -ms-flexbox; display: -webkit-flex; display: flex; -ms-flex-flow: row wrap; -webkit-flex-flow: row wrap; flex-flow: row wrap; }
+#header .details span:first-child { margin-left: -0.125em; }
+#header .details span.email a { color: #909ea7; }
+#header .details br { display: none; }
+#header .details br + span:before { content: "\00a0\2013\00a0"; }
+#header .details br + span.author:before { content: "\00a0\22c5\00a0"; color: #909ea7; }
+#header .details br + span#revremark:before { content: "\00a0|\00a0"; }
+#header #revnumber { text-transform: capitalize; }
+#header #revnumber:after { content: "\00a0"; }
+
+#content > h1:first-child:not([class]) { color: #111; border-bottom: 1px solid #ddd; padding-bottom: 8px; margin-top: 0; padding-top: 1rem; margin-bottom: 1.25rem; }
+
+#toc { border-bottom: 1px solid #ddd; padding-bottom: 0.5em; }
+#toc > ul { margin-left: 0.125em; }
+#toc ul.sectlevel0 > li > a { font-style: italic; }
+#toc ul.sectlevel0 ul.sectlevel1 { margin: 0.5em 0; }
+#toc ul { font-family: ff-meta-web-pro-1, ff-meta-web-pro-2, Arial, "Helvetica Neue", sans-serif; list-style-type: none; }
+#toc li { line-height: 1.3334; margin-top: 0.3334em; }
+#toc a { text-decoration: none; }
+#toc a:active { text-decoration: underline; }
+
+#toctitle { color: #6c818f; font-size: 1.2em; }
+
+@media only screen and (min-width: 768px) { #toctitle { font-size: 1.375em; }
+  body.toc2 { padding-left: 15em; padding-right: 0; }
+  #toc.toc2 { margin-top: 0 !important; background-color: #f2f2f2; position: fixed; width: 15em; left: 0; top: 0; border-right: 1px solid #ddd; border-top-width: 0 !important; border-bottom-width: 0 !important; z-index: 1000; padding: 1.25em 1em; height: 100%; overflow: auto; }
+  #toc.toc2 #toctitle { margin-top: 0; margin-bottom: 0.8rem; font-size: 1.2em; }
+  #toc.toc2 > ul { font-size: 0.9em; margin-bottom: 0; }
+  #toc.toc2 ul ul { margin-left: 0; padding-left: 1em; }
+  #toc.toc2 ul.sectlevel0 ul.sectlevel1 { padding-left: 0; margin-top: 0.5em; margin-bottom: 0.5em; }
+  body.toc2.toc-right { padding-left: 0; padding-right: 15em; }
+  body.toc2.toc-right #toc.toc2 { border-right-width: 0; border-left: 1px solid #ddd; left: auto; right: 0; } }
+@media only screen and (min-width: 1280px) { body.toc2 { padding-left: 20em; padding-right: 0; }
+  #toc.toc2 { width: 20em; }
+  #toc.toc2 #toctitle { font-size: 1.375em; }
+  #toc.toc2 > ul { font-size: 0.95em; }
+  #toc.toc2 ul ul { padding-left: 1.25em; }
+  body.toc2.toc-right { padding-left: 0; padding-right: 20em; } }
+#content #toc { border-style: solid; border-width: 1px; border-color: #d9d9d9; margin-bottom: 1.25em; padding: 1.25em; background: #f2f2f2; -webkit-border-radius: 6px; border-radius: 6px; }
+#content #toc > :first-child { margin-top: 0; }
+#content #toc > :last-child { margin-bottom: 0; }
+
+#footer { max-width: 100%; background-color: #000; padding: 1.25em; }
+
+#footer-text { color: white; line-height: 1.35; }
+
+#content { margin-bottom: 0.625em; }
+
+.sect1 { padding-bottom: 0.625em; }
+
+@media only screen and (min-width: 768px) { #content { margin-bottom: 1.25em; }
+  .sect1 { padding-bottom: 1.25em; } }
+.sect1:last-child { padding-bottom: 0; }
+
+.sect1 + .sect1 { border-top: 1px solid #ddd; }
+
+#content h1 > a.anchor, h2 > a.anchor, h3 > a.anchor, #toctitle > a.anchor, .sidebarblock > .content > .title > a.anchor, h4 > a.anchor, h5 > a.anchor, h6 > a.anchor { position: absolute; z-index: 1001; width: 1.5ex; margin-left: -1.5ex; display: block; text-decoration: none !important; visibility: hidden; text-align: center; font-weight: normal; }
+#content h1 > a.anchor:before, h2 > a.anchor:before, h3 > a.anchor:before, #toctitle > a.anchor:before, .sidebarblock > .content > .title > a.anchor:before, h4 > a.anchor:before, h5 > a.anchor:before, h6 > a.anchor:before { content: "\00A7"; font-size: 0.85em; display: block; padding-top: 0.1em; }
+#content h1:hover > a.anchor, #content h1 > a.anchor:hover, h2:hover > a.anchor, h2 > a.anchor:hover, h3:hover > a.anchor, #toctitle:hover > a.anchor, .sidebarblock > .content > .title:hover > a.anchor, h3 > a.anchor:hover, #toctitle > a.anchor:hover, .sidebarblock > .content > .title > a.anchor:hover, h4:hover > a.anchor, h4 > a.anchor:hover, h5:hover > a.anchor, h5 > a.anchor:hover, h6:hover > a.anchor, h6 > a.anchor:hover { visibility: visible; }
+#content h1 > a.link, h2 > a.link, h3 > a.link, #toctitle > a.link, .sidebarblock > .content > .title > a.link, h4 > a.link, h5 > a.link, h6 > a.link { color: #465158; text-decoration: none; }
+#content h1 > a.link:hover, h2 > a.link:hover, h3 > a.link:hover, #toctitle > a.link:hover, .sidebarblock > .content > .title > a.link:hover, h4 > a.link:hover, h5 > a.link:hover, h6 > a.link:hover { color: #3b444a; }
+
+.audioblock, .imageblock, .literalblock, .listingblock, .stemblock, .videoblock { margin-bottom: 1.25em; }
+
+.admonitionblock td.content > .title, .audioblock > .title, .exampleblock > .title, .imageblock > .title, .listingblock > .title, .literalblock > .title, .stemblock > .title, .openblock > .title, .paragraph > .title, .quoteblock > .title, table.tableblock > .title, .verseblock > .title, .videoblock > .title, .dlist > .title, .olist > .title, .ulist > .title, .qlist > .title, .hdlist > .title { text-rendering: optimizeLegibility; text-align: left; }
+
+table.tableblock.fit-content > caption.title { white-space: nowrap; width: 0; }
+
+.paragraph.lead > p, #preamble > .sectionbody > [class="paragraph"]:first-of-type p { font-size: 1.21875em; line-height: 1.6; color: #111; }
+
+table.tableblock #preamble > .sectionbody > [class="paragraph"]:first-of-type p { font-size: inherit; }
+
+.admonitionblock > table { border-collapse: separate; border: 0; background: none; width: 100%; }
+.admonitionblock > table td.icon { text-align: center; width: 80px; }
+.admonitionblock > table td.icon img { max-width: none; }
+.admonitionblock > table td.icon .title { font-weight: bold; font-family: ff-meta-web-pro-1, ff-meta-web-pro-2, Arial, "Helvetica Neue", sans-serif; text-transform: uppercase; }
+.admonitionblock > table td.content { padding-left: 1.125em; padding-right: 1.25em; border-left: 1px solid #ddd; color: #748590; }
+.admonitionblock > table td.content > :last-child > :last-child { margin-bottom: 0; }
+
+.exampleblock > .content { border-style: solid; border-width: 1px; border-color: #e6e6e6; margin-bottom: 1.25em; padding: 1.25em; background: #fff; -webkit-border-radius: 6px; border-radius: 6px; }
+.exampleblock > .content > :first-child { margin-top: 0; }
+.exampleblock > .content > :last-child { margin-bottom: 0; }
+
+.sidebarblock { border-style: solid; border-width: 1px; border-color: #d9d9d9; margin-bottom: 1.25em; padding: 1.25em; background: #f2f2f2; -webkit-border-radius: 6px; border-radius: 6px; }
+.sidebarblock > :first-child { margin-top: 0; }
+.sidebarblock > :last-child { margin-bottom: 0; }
+.sidebarblock > .content > .title { color: #6c818f; margin-top: 0; }
+
+.exampleblock > .content > :last-child > :last-child, .exampleblock > .content .olist > ol > li:last-child > :last-child, .exampleblock > .content .ulist > ul > li:last-child > :last-child, .exampleblock > .content .qlist > ol > li:last-child > :last-child, .sidebarblock > .content > :last-child > :last-child, .sidebarblock > .content .olist > ol > li:last-child > :last-child, .sidebarblock > .content .ulist > ul > li:last-child > :last-child, .sidebarblock > .content .qlist > ol > li:last-child > :last-child { margin-bottom: 0; }
+
+.literalblock pre, .listingblock pre:not(.highlight), .listingblock pre[class="highlight"], .listingblock pre[class^="highlight "], .listingblock pre.CodeRay, .listingblock pre.prettyprint { background: #eee; }
+.sidebarblock .literalblock pre, .sidebarblock .listingblock pre:not(.highlight), .sidebarblock .listingblock pre[class="highlight"], .sidebarblock .listingblock pre[class^="highlight "], .sidebarblock .listingblock pre.CodeRay, .sidebarblock .listingblock pre.prettyprint { background: #f2f1f1; }
+
+.literalblock pre, .literalblock pre[class], .listingblock pre, .listingblock pre[class] { border: 1px solid #ccc; -webkit-border-radius: 6px; border-radius: 6px; word-wrap: break-word; padding: 0.5em; font-size: 0.8125em; }
+.literalblock pre.nowrap, .literalblock pre[class].nowrap, .listingblock pre.nowrap, .listingblock pre[class].nowrap { overflow-x: auto; white-space: pre; word-wrap: normal; }
+@media only screen and (min-width: 768px) { .literalblock pre, .literalblock pre[class], .listingblock pre, .listingblock pre[class] { font-size: 0.90625em; } }
+@media only screen and (min-width: 1280px) { .literalblock pre, .literalblock pre[class], .listingblock pre, .listingblock pre[class] { font-size: 1em; } }
+
+.literalblock.output pre { color: #eee; background-color: inherit; }
+
+.listingblock pre.highlightjs { padding: 0; }
+.listingblock pre.highlightjs > code { padding: 0.5em; -webkit-border-radius: 6px; border-radius: 6px; }
+
+.listingblock > .content { position: relative; }
+
+.listingblock code[data-lang]:before { display: none; content: attr(data-lang); position: absolute; font-size: 0.75em; top: 0.425rem; right: 0.5rem; line-height: 1; text-transform: uppercase; color: #999; }
+
+.listingblock:hover code[data-lang]:before { display: block; }
+
+.listingblock.terminal pre .command:before { content: attr(data-prompt); padding-right: 0.5em; color: #999; }
+
+.listingblock.terminal pre .command:not([data-prompt]):before { content: "$"; }
+
+table.pyhltable { border-collapse: separate; border: 0; margin-bottom: 0; background: none; }
+
+table.pyhltable td { vertical-align: top; padding-top: 0; padding-bottom: 0; line-height: 1.2; }
+
+table.pyhltable td.code { padding-left: .75em; padding-right: 0; }
+
+pre.pygments .lineno, table.pyhltable td:not(.code) { color: #999; padding-left: 0; padding-right: .5em; border-right: 1px solid #ddd; }
+
+pre.pygments .lineno { display: inline-block; margin-right: .25em; }
+
+table.pyhltable .linenodiv { background: none !important; padding-right: 0 !important; }
+
+.quoteblock { margin: 0 1em 1.25em 1.5em; display: table; }
+.quoteblock > .title { margin-left: -1.5em; margin-bottom: 0.75em; }
+.quoteblock blockquote, .quoteblock blockquote p { color: #909ea7; font-size: 1.15rem; line-height: 1.75; word-spacing: 0.1em; letter-spacing: 0; font-style: italic; text-align: justify; }
+.quoteblock blockquote { margin: 0; padding: 0; border: 0; }
+.quoteblock blockquote:before { content: "\201c"; float: left; font-size: 2.75em; font-weight: bold; line-height: 0.6em; margin-left: -0.6em; color: #6c818f; text-shadow: 0 1px 2px rgba(0, 0, 0, 0.1); }
+.quoteblock blockquote > .paragraph:last-child p { margin-bottom: 0; }
+.quoteblock .attribution { margin-top: 0.5em; margin-right: 0.5ex; text-align: right; }
+.quoteblock .quoteblock { margin-left: 0; margin-right: 0; padding: 0.5em 0; border-left: 3px solid #748590; }
+.quoteblock .quoteblock blockquote { padding: 0 0 0 0.75em; }
+.quoteblock .quoteblock blockquote:before { display: none; }
+
+.verseblock { margin: 0 1em 1.25em 1em; }
+.verseblock pre { font-family: "Open Sans", "DejaVu Sans", sans; font-size: 1.15rem; color: #909ea7; font-weight: 300; text-rendering: optimizeLegibility; }
+.verseblock pre strong { font-weight: 400; }
+.verseblock .attribution { margin-top: 1.25rem; margin-left: 0.5ex; }
+
+.quoteblock .attribution, .verseblock .attribution { font-size: 0.8125em; line-height: 1.45; font-style: italic; }
+.quoteblock .attribution br, .verseblock .attribution br { display: none; }
+.quoteblock .attribution cite, .verseblock .attribution cite { display: block; letter-spacing: -0.025em; color: #748590; }
+
+.quoteblock.abstract { margin: 0 1em 1.25em 1em; display: block; }
+.quoteblock.abstract > .title { margin: 0 0 0.375em 0; font-size: 1.15em; text-align: center; }
+.quoteblock.abstract blockquote, .quoteblock.abstract blockquote p { word-spacing: 0; line-height: 1.6; }
+.quoteblock.abstract blockquote:before, .quoteblock.abstract p:before { display: none; }
+
+table.tableblock { max-width: 100%; border-collapse: separate; }
+
+p.tableblock:last-child { margin-bottom: 0; }
+
+td.tableblock > .content { margin-bottom: -1.25em; }
+
+table.tableblock, th.tableblock, td.tableblock { border: 0 solid #ddd; }
+
+table.grid-all > thead > tr > .tableblock, table.grid-all > tbody > tr > .tableblock { border-width: 0 0 0 0; }
+
+table.grid-all > tfoot > tr > .tableblock { border-width: 0 0 0 0; }
+
+table.grid-cols > * > tr > .tableblock { border-width: 0 0 0 0; }
+
+table.grid-rows > thead > tr > .tableblock, table.grid-rows > tbody > tr > .tableblock { border-width: 0 0 0 0; }
+
+table.grid-rows > tfoot > tr > .tableblock { border-width: 0 0 0 0; }
+
+table.grid-all > * > tr > .tableblock:last-child, table.grid-cols > * > tr > .tableblock:last-child { border-right-width: 0; }
+
+table.grid-all > tbody > tr:last-child > .tableblock, table.grid-all > thead:last-child > tr > .tableblock, table.grid-rows > tbody > tr:last-child > .tableblock, table.grid-rows > thead:last-child > tr > .tableblock { border-bottom-width: 0; }
+
+table.frame-all { border-width: 0; }
+
+table.frame-sides { border-width: 0 0; }
+
+table.frame-topbot, table.frame-ends { border-width: 0 0; }
+
+table.stripes-all tr, table.stripes-odd tr:nth-of-type(odd) { background: none; }
+
+table.stripes-none tr, table.stripes-odd tr:nth-of-type(even) { background: none; }
+
+th.halign-left, td.halign-left { text-align: left; }
+
+th.halign-right, td.halign-right { text-align: right; }
+
+th.halign-center, td.halign-center { text-align: center; }
+
+th.valign-top, td.valign-top { vertical-align: top; }
+
+th.valign-bottom, td.valign-bottom { vertical-align: bottom; }
+
+th.valign-middle, td.valign-middle { vertical-align: middle; }
+
+table thead th, table tfoot th { font-weight: bold; }
+
+tbody tr th { display: table-cell; line-height: 1.5; background: none; }
+
+tbody tr th, tbody tr th p, tfoot tr th, tfoot tr th p { color: #222; font-weight: bold; }
+
+p.tableblock > code:only-child { background: none; padding: 0; }
+
+p.tableblock { font-size: 1em; }
+
+td > div.verse { white-space: pre; }
+
+ol { margin-left: 0.25em; }
+
+ul li ol { margin-left: 0; }
+
+dl dd { margin-left: 1.125em; }
+
+dl dd:last-child, dl dd:last-child > :last-child { margin-bottom: 0; }
+
+ol > li p, ul > li p, ul dd, ol dd, .olist .olist, .ulist .ulist, .ulist .olist, .olist .ulist { margin-bottom: 0.625em; }
+
+ul.checklist, ul.none, ol.none, ul.no-bullet, ol.no-bullet, ol.unnumbered, ul.unstyled, ol.unstyled { list-style-type: none; }
+
+ul.no-bullet, ol.no-bullet, ol.unnumbered { margin-left: 0.625em; }
+
+ul.unstyled, ol.unstyled { margin-left: 0; }
+
+ul.checklist { margin-left: 0.625em; }
+
+ul.checklist li > p:first-child > .fa-square-o:first-child, ul.checklist li > p:first-child > .fa-check-square-o:first-child { width: 1.25em; font-size: 0.8em; position: relative; bottom: 0.125em; }
+
+ul.checklist li > p:first-child > input[type="checkbox"]:first-child { margin-right: 0.25em; }
+
+ul.inline { display: -ms-flexbox; display: -webkit-box; display: flex; -ms-flex-flow: row wrap; -webkit-flex-flow: row wrap; flex-flow: row wrap; list-style: none; margin: 0 0 0.625em -1.25em; }
+
+ul.inline > li { margin-left: 1.25em; }
+
+.unstyled dl dt { font-weight: normal; font-style: normal; }
+
+ol.arabic { list-style-type: decimal; }
+
+ol.decimal { list-style-type: decimal-leading-zero; }
+
+ol.loweralpha { list-style-type: lower-alpha; }
+
+ol.upperalpha { list-style-type: upper-alpha; }
+
+ol.lowerroman { list-style-type: lower-roman; }
+
+ol.upperroman { list-style-type: upper-roman; }
+
+ol.lowergreek { list-style-type: lower-greek; }
+
+.hdlist > table, .colist > table { border: 0; background: none; }
+.hdlist > table > tbody > tr, .colist > table > tbody > tr { background: none; }
+
+td.hdlist1, td.hdlist2 { vertical-align: top; padding: 0 0.625em; }
+
+td.hdlist1 { font-weight: bold; padding-bottom: 1.25em; }
+
+.literalblock + .colist, .listingblock + .colist { margin-top: -0.5em; }
+
+.colist td:not([class]):first-child { padding: 0.4em 0.75em 0 0.75em; line-height: 1; vertical-align: top; }
+.colist td:not([class]):first-child img { max-width: none; }
+.colist td:not([class]):last-child { padding: 0.25em 0; }
+
+.thumb, .th { line-height: 0; display: inline-block; border: solid 4px #fff; -webkit-box-shadow: 0 0 0 1px #ddd; box-shadow: 0 0 0 1px #ddd; }
+
+.imageblock.left { margin: 0.25em 0.625em 1.25em 0; }
+.imageblock.right { margin: 0.25em 0 1.25em 0.625em; }
+.imageblock > .title { margin-bottom: 0; }
+.imageblock.thumb, .imageblock.th { border-width: 6px; }
+.imageblock.thumb > .title, .imageblock.th > .title { padding: 0 0.125em; }
+
+.image.left, .image.right { margin-top: 0.25em; margin-bottom: 0.25em; display: inline-block; line-height: 0; }
+.image.left { margin-right: 0.625em; }
+.image.right { margin-left: 0.625em; }
+
+a.image { text-decoration: none; display: inline-block; }
+a.image object { pointer-events: none; }
+
+sup.footnote, sup.footnoteref { font-size: 0.875em; position: static; vertical-align: super; }
+sup.footnote a, sup.footnoteref a { text-decoration: none; }
+sup.footnote a:active, sup.footnoteref a:active { text-decoration: underline; }
+
+#footnotes { padding-top: 0.75em; padding-bottom: 0.75em; margin-bottom: 0.625em; }
+#footnotes hr { width: 20%; min-width: 6.25em; margin: -0.25em 0 0.75em 0; border-width: 1px 0 0 0; }
+#footnotes .footnote { padding: 0 0.375em 0 0.225em; line-height: 1.3334; font-size: 0.875em; margin-left: 1.2em; margin-bottom: 0.2em; }
+#footnotes .footnote a:first-of-type { font-weight: bold; text-decoration: none; margin-left: -1.05em; }
+#footnotes .footnote:last-of-type { margin-bottom: 0; }
+#content #footnotes { margin-top: -0.625em; margin-bottom: 0; padding: 0.75em 0; }
+
+.gist .file-data > table { border: 0; background: #fff; width: 100%; margin-bottom: 0; }
+.gist .file-data > table td.line-data { width: 99%; }
+
+div.unbreakable { page-break-inside: avoid; }
+
+.big { font-size: larger; }
+
+.small { font-size: smaller; }
+
+.underline { text-decoration: underline; }
+
+.overline { text-decoration: overline; }
+
+.line-through { text-decoration: line-through; }
+
+.aqua { color: #00bfbf; }
+
+.aqua-background { background-color: #00fafa; }
+
+.black { color: black; }
+
+.black-background { background-color: black; }
+
+.blue { color: #0000bf; }
+
+.blue-background { background-color: #0000fa; }
+
+.fuchsia { color: #bf00bf; }
+
+.fuchsia-background { background-color: #fa00fa; }
+
+.gray { color: #606060; }
+
+.gray-background { background-color: #7d7d7d; }
+
+.green { color: #006000; }
+
+.green-background { background-color: #007d00; }
+
+.lime { color: #00bf00; }
+
+.lime-background { background-color: #00fa00; }
+
+.maroon { color: #600000; }
+
+.maroon-background { background-color: #7d0000; }
+
+.navy { color: #000060; }
+
+.navy-background { background-color: #00007d; }
+
+.olive { color: #606000; }
+
+.olive-background { background-color: #7d7d00; }
+
+.purple { color: #600060; }
+
+.purple-background { background-color: #7d007d; }
+
+.red { color: #bf0000; }
+
+.red-background { background-color: #fa0000; }
+
+.silver { color: #909090; }
+
+.silver-background { background-color: #bcbcbc; }
+
+.teal { color: #006060; }
+
+.teal-background { background-color: #007d7d; }
+
+.white { color: #bfbfbf; }
+
+.white-background { background-color: #fafafa; }
+
+.yellow { color: #bfbf00; }
+
+.yellow-background { background-color: #fafa00; }
+
+span.icon > .fa { cursor: default; }
+a span.icon > .fa { cursor: inherit; }
+
+.admonitionblock td.icon [class^="fa icon-"] { font-size: 2.5em; text-shadow: 1px 1px 2px rgba(0, 0, 0, 0.5); cursor: default; }
+.admonitionblock td.icon .icon-note:before { content: "\f05a"; color: #333333; }
+.admonitionblock td.icon .icon-tip:before { content: "\f0eb"; text-shadow: 1px 1px 2px rgba(155, 155, 0, 0.8); color: #111; }
+.admonitionblock td.icon .icon-warning:before { content: "\f071"; color: #bf6900; }
+.admonitionblock td.icon .icon-caution:before { content: "\f06d"; color: #bf3400; }
+.admonitionblock td.icon .icon-important:before { content: "\f06a"; color: #bf0000; }
+
+.conum[data-value] { display: inline-block; color: #fff !important; background-color: #000; -webkit-border-radius: 100px; border-radius: 100px; text-align: center; font-size: 0.75em; width: 1.67em; height: 1.67em; line-height: 1.67em; font-family: "Open Sans", "DejaVu Sans", sans-serif; font-style: normal; font-weight: bold; }
+.conum[data-value] * { color: #fff !important; }
+.conum[data-value] + b { display: none; }
+.conum[data-value]:after { content: attr(data-value); }
+pre .conum[data-value] { position: relative; top: -0.125em; }
+
+b.conum * { color: inherit !important; }
+
+.conum:not([data-value]):empty { display: none; }
+
+h4 { color: #6c818f; }
+
+.literalblock > .content > pre, .listingblock > .content > pre { -webkit-border-radius: 6px; border-radius: 6px; margin-left: 2em; margin-right: 2em; }
+
+.admonitionblock { margin-left: 2em; margin-right: 2em; }
+.admonitionblock > table { border: 1px solid #607f90; border-top-width: 1.5em; background-color: #f0f9ff; border-collapse: separate; -webkit-border-radius: 0; border-radius: 0; }
+.admonitionblock > table td.icon { padding-top: .5em; padding-bottom: .5em; }
+.admonitionblock > table td.content { padding: .5em 1em; color: #000; font-size: .9em; border-left: none; }
+
+.sidebarblock { background-color: #e8ecef; border-color: #ccc; }
+.sidebarblock > .content > .title { color: #444; }
+
+table.tableblock.grid-all { border-collapse: collapse; -webkit-border-radius: 0; border-radius: 0; }
+table.tableblock.grid-all th.tableblock, table.tableblock.grid-all td.tableblock { border-bottom: 1px solid #aaa; }
+
+#footer { background-color: #465158; padding: 2em; }
+
+#footer-text { color: #eee; font-size: 0.8em; text-align: center; }
diff --git a/manual/cli.txt b/manual/cli.txt
new file mode 100644 (file)
index 0000000..001b6e9
--- /dev/null
@@ -0,0 +1,42 @@
+== Command-line Interface
+
+Even though PulseView has a graphical user interface, there is also a command-line interface that
+you can make use of. It is meant to provide functions for convenience and debug purposes, not to
+replace the user interface itself.
+
+Running 
+
+       pulseview -h
+
+gives you a list of these functions.
+
+Since PulseView can't automatically scan for devices connected to a COM port (ttySx on Linux) or
+Ethernet, you can tell it to look for a specific device using the -d or --driver parameter. Its
+usage is the same as for sigrok-cli. For example:
+
+       pulseview -d lecroy-xstream:conn=vxi/192.168.178.20/111
+
+Also, just as with sigrok-cli, you can specify -i / --input-file and -I / --input-format to open
+a file on startup. Without -I, it is assumed that the file is in the native sigrok format (.sr).
+You can also specify more than one file but they are all expected to be in the same format then.
+Example:
+
+       pulseview -i data.csv -I csv:samplerate=3000000
+
+The remaining parameters are mostly for debug purposes:
+
+       -V / --version          Shows the release version
+       -l / --loglevel         Sets the libsigrok/libsigrokdecode log level (max is 5)
+       -D / --dont-scan        Don't auto-scan for devices
+       -c / --clean            Don't restore previous sessions on startup
+
+Of these, -D / --dont-scan can be useful when PulseView gets stuck during the startup device scan.
+No such scan will be performed then, allowing the program to start up but you'll have to scan for
+your acquisition device(s) manually before you can use them.
+
+Another potentially useful option is -c / --clean, which can be used when PulseView doesn't start
+up and you don't know what could cause this.
+
+Thus, the combination of both parameters can be seen as some kind of "safe mode" for PulseView:
+
+       pulseview -c -D
diff --git a/manual/decoders.txt b/manual/decoders.txt
new file mode 100644 (file)
index 0000000..d2ca15a
--- /dev/null
@@ -0,0 +1,140 @@
+== Decoders
+
+Protocol decoders are one of the key elements of PulseView's functionality. They take
+input data that you acquired and process it in a way that results in a (hopefully) much
+easier to understand representation of that same data.
+
+In its simplest form, a protocol decoder (PD) converts a group of 1-bit signals into a
+stream of n-bit events. This is exactly what the parallel PD does: it takes for example
+8 logic channels and treats them like an 8-bit parallel bus, emitting annotations that
+show the current state of the bus at any point in time.
+
+=== Basic Operation
+
+Another one of the protocol decoders available to you is the I²C decoder. It takes the
+two I²C signals SCL and SDA (serial clock / serial data) and shows you the details of
+the I²C communication without the need to evaluate the signal bit by bit yourself.
+
+As an example, let's have look at one of the sample .sr files we keep around for
+validation of the PD code base: https://sigrok.org/gitweb/?p=sigrok-dumps.git;a=blob_plain;f=i2c/rtc_dallas_ds1307/rtc_ds1307_200khz.sr;hb=HEAD[rtc_ds1307_200khz.sr].
+It contains the capture of an I²C master interacting with a https://www.maximintegrated.com/en/products/digital/real-time-clocks/DS1307.html[Dallas DS1307 I²C Real-Time Clock]
+where the master repeatedly sets and queries the time of day. After loading and using
+"zoom-to-fit", it looks similar to this:
+
+image::pv_decoders_1.png[]
+
+Adding the I²C decoder by clicking on ➊ and selecting I²C from the list adds
+a new decode signal to the view. PulseView tries to match existing signals to the signals
+that the newly added protocol decoder needs to function, which is what happened here -
+SCL and SDA have been automatically assigned and the PD has decoded the communication with
+the default parameters. If you need to change the signal assignment or change the decoding
+parameters, you can click on ➋ to do so.
+
+When you zoom in, you now see that PulseView has decoded the I²C messages and displays
+these annotations as part of the decode signal (note that we have zoomed in so far that
+PulseView shows you the individual samples):
+
+image::pv_decoders_2.png[]
+
+This is already very useful, and a massive improvement over counting out pulses on an
+oscilloscope screen. However, sigrok allows us to go one step further with the use of
+so-called stacked decoders. 
+
+=== Decoder Stacking
+
+To add a stacked decoder we open the settings of the decode signal, go to the _Stack
+Decoder_ menu ➊, and select the DS1307 decoder:
+
+image::pv_decoders_3.png[]
+
+With the stacked decoder added, we can now see that PulseView has decoded the meaning
+of the I²C commands, so that we don't need to bother searching the reference manual.
+In this view, we can see that the I²C packet was a command to read the date and time,
+which was then reported to be 10.03.2013 23:35:30. 
+
+There are all kinds of stacked decoders available, but keep in mind that they're not
+shown in the decoder menu. Stacked decoders require a lower-level decoder first before
+they become stackable. Most of the time, they require either the UART, I²C or SPI decoder.
+
+You can check the https://sigrok.org/wiki/Protocol_decoders[List of Protocol Decoders]
+to see which protocol decoders have been created already.
+
+=== Using Decoders on Analog Signals
+
+If you're capturing data using an oscilloscope or import analog signal data from a file,
+you'll quickly notice that protocol decoders don't give you the option to select analog
+channels as inputs. That is because as of now, decoders only work on logic signals. You
+can however convert analog signals into logic signals by choosing a conversion setting
+from the signal setting popup.
+
+image::pv_conversion_a2l.png[]
+
+Here, A1 has been converted using a threshold (with default settings) and A2 has been
+converted using a Schmitt-Trigger emulation (also with default settings). Additionally,
+the conversion threshold display mode has been set to _Background_ in the _Views_ settings
+dialog. This way, you can tell how PulseView decided to change the logic signal level
+as you can now visually understand where the ranges for high and low are placed.
+
+Aside from the default conversion threshold(s), you can choose from a few common presets
+or enter custom values as well. They take the form "0.0V" and "0.0V/0.0V", respectively.
+
+=== Troubleshooting
+
+In case a protocol decoder doesn't provide the expected result, there are several things
+you can check.
+
+The first check you should perform is whether the time unit in the ruler
+is given as "sa". This is short for "samples" and means that the device didn't provide
+a sample rate and so PulseView has no way of showing a time scale in seconds or
+fractions thereof. While some decoders can run without timing information, or only
+optionally make use of the time scale, others may not be able to interpret the
+input data since timing information is an essential part of the very protocol.
+
+Another issue to remain aware of is that decoders need enough samples per protocol step
+to reliably interpret the information. In typical cases the minimum sample rate should
+be four to five times the rate of the fastest activity in the protocol.
+
+If a protocol decoder runs but shows you annotations that don't seem to make any sense,
+it's worth double-checking the decoder settings. One common source of error is the
+baud rate. For example, the CAN protocol decoder doesn't know what baud rate
+is used on the bus that you captured, so it could be that a different baud rate is used
+than the one you set. Also, if this is still not the reason for the malfunction, it's
+worth checking whether any of the signals have been captured inverted. Again using the
+CAN bus as an example, the decoder will decode the signal just fine if it's inverted but
+it'll show data even when the signal looks "idle".
+
+When a protocol decoder stops execution because of an unmet constraint (required input
+not connected, essential parameter not specified) or a bug in the decoder itself, you
+will be presented a static red message in the protocol decoder's display area.
+In that case, you check the log output in the settings menu. There you'll find the Python
+error description which you can use to either adjust the configuration,
+or debug the decoder (and let us know of the fix) or you can copy that information and
+file a bug report so that we can fix it.
+
+Further helpful knowledge and explanations on logic analyzers can be found in our
+https://sigrok.org/wiki/FAQ#Where_can_I_learn_more_about_logic_analyzers.3F["Learn about logic analyzers" FAQ item].
+
+=== Exporting Annotations
+
+If you want to postprocess annotations that were generated by a protocol decoder, you
+can do so by right-clicking into the area of the decode signal (not on the signal label
+on the left). You are shown several export methods to choose from, with the last one
+being only available if the cursor is enabled.
+
+After you chose a method that suits your needs, you are prompted for a file to export
+the annotations to. The contents of the file very much depend on the option you chose
+but also on the annotation export format string that you can define in the _Decoders_
+menu of the settings dialog. If the default output isn't useful to you, you can
+customize it there.
+
+=== Creating a Protocol Decoder
+
+Protocol decoders are written in Python and can be created using nothing more than a
+text editor. You, too, can write one!
+
+To find out how to go about it, please see our https://sigrok.org/wiki/Protocol_decoder_HOWTO[Protocol Decoder How-To]
+and the https://sigrok.org/wiki/Protocol_decoder_API[Protocol Decoder API Reference].
+
+If you do write one, we'd appreciate if you'd contribute to our project so that everyone
+can benefit from your work.
+
diff --git a/manual/images/_callouts.xcf b/manual/images/_callouts.xcf
new file mode 100644 (file)
index 0000000..c712315
Binary files /dev/null and b/manual/images/_callouts.xcf differ
diff --git a/manual/images/device_selector.png b/manual/images/device_selector.png
new file mode 100644 (file)
index 0000000..2bba96b
Binary files /dev/null and b/manual/images/device_selector.png differ
diff --git a/manual/images/device_selector_dropdown.png b/manual/images/device_selector_dropdown.png
new file mode 100644 (file)
index 0000000..08c7399
Binary files /dev/null and b/manual/images/device_selector_dropdown.png differ
diff --git a/manual/images/device_selector_scan.png b/manual/images/device_selector_scan.png
new file mode 100644 (file)
index 0000000..0cbe54b
Binary files /dev/null and b/manual/images/device_selector_scan.png differ
diff --git a/manual/images/pv_after_startup.png b/manual/images/pv_after_startup.png
new file mode 100644 (file)
index 0000000..22a0fcc
Binary files /dev/null and b/manual/images/pv_after_startup.png differ
diff --git a/manual/images/pv_after_startup.xcf b/manual/images/pv_after_startup.xcf
new file mode 100644 (file)
index 0000000..e81a4a5
Binary files /dev/null and b/manual/images/pv_after_startup.xcf differ
diff --git a/manual/images/pv_analysis.png b/manual/images/pv_analysis.png
new file mode 100644 (file)
index 0000000..215d148
Binary files /dev/null and b/manual/images/pv_analysis.png differ
diff --git a/manual/images/pv_analysis.xcf b/manual/images/pv_analysis.xcf
new file mode 100644 (file)
index 0000000..93b7859
Binary files /dev/null and b/manual/images/pv_analysis.xcf differ
diff --git a/manual/images/pv_conversion_a2l.png b/manual/images/pv_conversion_a2l.png
new file mode 100644 (file)
index 0000000..b804fef
Binary files /dev/null and b/manual/images/pv_conversion_a2l.png differ
diff --git a/manual/images/pv_cursors_markers.png b/manual/images/pv_cursors_markers.png
new file mode 100644 (file)
index 0000000..fc8552c
Binary files /dev/null and b/manual/images/pv_cursors_markers.png differ
diff --git a/manual/images/pv_cursors_markers.xcf b/manual/images/pv_cursors_markers.xcf
new file mode 100644 (file)
index 0000000..3748545
Binary files /dev/null and b/manual/images/pv_cursors_markers.xcf differ
diff --git a/manual/images/pv_decoders_1.png b/manual/images/pv_decoders_1.png
new file mode 100644 (file)
index 0000000..ac33def
Binary files /dev/null and b/manual/images/pv_decoders_1.png differ
diff --git a/manual/images/pv_decoders_1.xcf b/manual/images/pv_decoders_1.xcf
new file mode 100644 (file)
index 0000000..19fc127
Binary files /dev/null and b/manual/images/pv_decoders_1.xcf differ
diff --git a/manual/images/pv_decoders_2.png b/manual/images/pv_decoders_2.png
new file mode 100644 (file)
index 0000000..4c85672
Binary files /dev/null and b/manual/images/pv_decoders_2.png differ
diff --git a/manual/images/pv_decoders_3.png b/manual/images/pv_decoders_3.png
new file mode 100644 (file)
index 0000000..153cfdd
Binary files /dev/null and b/manual/images/pv_decoders_3.png differ
diff --git a/manual/images/pv_decoders_3.xcf b/manual/images/pv_decoders_3.xcf
new file mode 100644 (file)
index 0000000..f570f12
Binary files /dev/null and b/manual/images/pv_decoders_3.xcf differ
diff --git a/manual/images/pv_decoders_4.png b/manual/images/pv_decoders_4.png
new file mode 100644 (file)
index 0000000..bb8d863
Binary files /dev/null and b/manual/images/pv_decoders_4.png differ
diff --git a/manual/images/pv_device_config.png b/manual/images/pv_device_config.png
new file mode 100644 (file)
index 0000000..ee7694b
Binary files /dev/null and b/manual/images/pv_device_config.png differ
diff --git a/manual/images/pv_device_config.xcf b/manual/images/pv_device_config.xcf
new file mode 100644 (file)
index 0000000..0e7252d
Binary files /dev/null and b/manual/images/pv_device_config.xcf differ
diff --git a/manual/images/pv_import.png b/manual/images/pv_import.png
new file mode 100644 (file)
index 0000000..645e319
Binary files /dev/null and b/manual/images/pv_import.png differ
diff --git a/manual/images/pv_nodevice.png b/manual/images/pv_nodevice.png
new file mode 100644 (file)
index 0000000..a5db293
Binary files /dev/null and b/manual/images/pv_nodevice.png differ
diff --git a/manual/images/top_bar.png b/manual/images/top_bar.png
new file mode 100644 (file)
index 0000000..5aeae70
Binary files /dev/null and b/manual/images/top_bar.png differ
diff --git a/manual/import_export.txt b/manual/import_export.txt
new file mode 100644 (file)
index 0000000..2e5c8b2
--- /dev/null
@@ -0,0 +1,34 @@
+== Data Import/Export
+
+In order to facilitate versatile use of the sigrok suite, libsigrok allows users to import
+and export data from files in various formats - some of them as generic as possible, others
+very specific. For a list and details, make sure to check https://sigrok.org/wiki/Input_output_formats[the wiki].
+
+=== Import
+
+The first step to importing data from a file is to know what format the data in the file is
+encoded in. There are common, not-so-common and outright exotic ways to represent data and sigrok
+tries to suit as many needs as it can. To see which formats your version of PulseView supports,
+just click on the small arrow next to the _Open_ button:
+
+image::pv_import.png[]
+
+After choosing the format that you want to use, PulseView will ask for the file name to open.
+Once you picked the file, you may be asked to specify the details of the format, if the input
+module requires them.
+
+For example, the VCD import will ask you for these:
+
+* Compress idle periods: Compress idle periods longer than the specified value (default 0)
+* Downsampling factor: Downsample, i.e. divide the samplerate by the specified factor (default 1)
+* Number of logic channels: The number of (logic) channels in the data (default 0)
+* Skip samples until timestamp: Skip samples until the specified timestamp; < 0: Skip until first timestamp listed; 0: Don't skip (default -1)
+
+The detailed description of each item can also be seen when clicking on the help icon on the right
+or hovering your mouse over it. A click on _OK_ then loads the data from the selected file and you
+can work with it.
+
+=== Export
+
+Export works just the same as the import: clicking on the small arrow next to the _Save_ button
+brings up the export menu. Simply choose the format you want to use and proceed.
diff --git a/manual/installation.txt b/manual/installation.txt
new file mode 100644 (file)
index 0000000..047333e
--- /dev/null
@@ -0,0 +1,100 @@
+[[installation,Installation]]
+== Installation
+
+PulseView can be run on Linux, Windows, Mac OS X or Android. For some platforms, we provide binary
+packages, for others we provide installers and for others we provide AppImage containers that
+you can run without the need to install anything. Check the https://sigrok.org/wiki/Downloads[sigrok download page]
+to see which option is available for your platform.
+
+=== Linux
+
+On Linux, the usual way to install PulseView is to install the packages provided by your distro's
+package manager. However, sometimes only outdated packages are made available to you. In that case,
+you have two options:
+
+. https://sigrok.org/wiki/Downloads[Download] and use the AppImage which contains all required files and needs no installation:
++
+--
+[listing, subs="normal"]
+chmod u+x PulseView-NIGHTLY-x86_64.AppImage
+./PulseView-NIGHTLY-x86_64.AppImage
+
+Please be aware, however, that the AppImages are built every night, so they always contain
+the latest development changes. While we do try to keep the code base in a working state, it is sometimes
+unavoidable to introduce bugs that show up in the nightly builds. If you encounter something that is
+odd to you, please download and install the latest nightly and check if the issue still exists. If it
+does, feel free to https://sigrok.org/bugzilla/[file a bug].
+
+No system files are changed, so if you decide that you no longer want to use PulseView, simply
+delete the AppImage. If you also want the stored settings gone, delete ~/.config/sigrok as well.
+--
+
+. Uninstall any sigrok packages from your package manager and build PulseView from source:
++
+--
+[listing, subs="normal"]
+_[install dependencies https://sigrok.org/wiki/Linux#Building[as listed on the wiki]]_
+mkdir ~/sr
+cd ~/sr
+wget 'https://sigrok.org/gitweb/?p=sigrok-util.git;a=blob_plain;f=cross-compile/linux/sigrok-cross-linux' -O sigrok-cross-linux
+chmod u+x sigrok-cross-linux
+./sigrok-cross-linux
+export LD_LIBRARY_PATH=~/sr/lib
+~/sr/bin/pulseview
+
+No system files are changed, so if you decide that you no longer want to use PulseView, simply
+delete the ~/sr directory. If you also want the stored settings gone, delete ~/.config/sigrok
+as well.
+--
+
+[WARNING]
+--
+If you don't install the PulseView distro packages (as is the case when using the AppImage or building
+from source), PulseView will not be able to access USB and serial port devices unless it's run as root.
+Since programs shouldn't be run as root unless absolutely necessary, we provide udev configuration files
+that allows PulseView access to those devices without being root.
+
+Here's how you install them:
+[listing, subs="normal"]
+sudo bash
+cd /etc/udev/rules.d/
+wget 'https://sigrok.org/gitweb/?p=libsigrok.git;a=blob_plain;f=contrib/60-libsigrok.rules' -O 60-libsigrok.rules
+wget 'https://sigrok.org/gitweb/?p=libsigrok.git;a=blob_plain;f=contrib/61-libsigrok-plugdev.rules' -O 61-libsigrok-plugdev.rules
+wget 'https://sigrok.org/gitweb/?p=libsigrok.git;a=blob_plain;f=contrib/61-libsigrok-uaccess.rules' -O 61-libsigrok-uaccess.rules
+sudo udevadm control --reload-rules
+--
+
+=== Windows
+
+We offer installers for PulseView that contain everything you need to get started. Simply download
+them from the https://sigrok.org/wiki/Downloads[sigrok download page] and run them as any other Windows
+installer.
+Please be aware, however, that the Windows installers are built every night, so they always contain
+the latest development changes. While we do try to keep the code base in a working state, it is sometimes
+unavoidable to introduce bugs that show up in the nightly builds. If you encounter something that is
+odd to you, please download and install the latest nightly and check if the issue still exists. If it
+does, feel free to https://sigrok.org/bugzilla/[file a bug].
+
+After installation, you will find a program called Zadig in the start menu. By default, certain devices
+recognized by Windows will have drivers installed for them that PulseView cannot use. The purpose of
+Zadig is to let you change the driver Windows uses for a particular device - for most devices you'll need
+to choose WinUSB to use them with PulseView or the original proprietary Windows driver to use it with whatever
+other software you access the device with. More details are available https://sigrok.org/wiki/Windows[in the wiki].
+
+In case your device doesn't show up in PulseView and you can't find it with a scan either (see next
+chapter), check with Zadig whether the correct driver is assigned for the device.
+
+=== Mac OS X
+
+We offer DMG installers for PulseView that contain everything you need to get started. Simply download
+them from the https://sigrok.org/wiki/Downloads[sigrok download page] and run them.
+
+Please be aware, however, that the DMG installers are built every night, so they always contain
+the latest development changes. While we do try to keep the code base in a working state, it is sometimes
+unavoidable to introduce bugs that show up in the nightly builds. If you encounter something that is
+odd to you, please download and install the latest nightly and check if the issue still exists. If it
+does, feel free to https://sigrok.org/bugzilla/[file a bug].
+
+No system files are changed, so if you decide that you no longer want to use PulseView, simply
+delete the DMG file. If you also want the stored settings gone, delete
+~/Library/Preferences/pulseview.plist as well.
diff --git a/manual/license.txt b/manual/license.txt
new file mode 100644 (file)
index 0000000..34ac580
--- /dev/null
@@ -0,0 +1,3 @@
+== License
+
+This work is licensed under the Creative Commons Attribution-ShareAlike 4.0 International License. To view a copy of this license, visit http://creativecommons.org/licenses/by-sa/4.0/ or send a letter to Creative Commons, PO Box 1866, Mountain View, CA 94042, USA.
diff --git a/manual/manual.txt b/manual/manual.txt
new file mode 100644 (file)
index 0000000..c4a3127
--- /dev/null
@@ -0,0 +1,28 @@
+PulseView User Manual
+=====================
+unreleased development snapshot, dated 2018-10-29
+:doctype: book
+:imagesdir: ./images
+:sectnums:
+:toc:
+:toclevels: 2
+:icons: font
+:figure-caption: Image
+
+ifdef::ebook-format[:leveloffset: -1]
+
+include::license.txt[]
+
+include::overview.txt[]
+
+include::installation.txt[]
+
+include::acquisition.txt[]
+
+include::analysis.txt[]
+
+include::decoders.txt[]
+
+include::import_export.txt[]
+
+include::cli.txt[]
diff --git a/manual/overview.txt b/manual/overview.txt
new file mode 100644 (file)
index 0000000..bfd87f8
--- /dev/null
@@ -0,0 +1,40 @@
+[[overview,Overview]]
+== Overview
+
+PulseView is a graphical frontend for the libsigrok and libsigrokdecode libraries, permitting
+access to a wide range of devices and protocol decoders to let you record, analyze, process
+and export analog and logic data. It is part of the sigrok suite, just like the libraries that
+it makes use of.
+
+The sigrok suite needs some kind of hardware to interface to the signals you want to examine.
+We found that most people are currently using logic analyzers based on the http://www.cypress.com/products/ez-usb-fx2lp[Cypress FX2 microcontroller].
+With http://sigrok.org/wiki/Fx2lafw[fx2lafw], sigrok's open source runtime firmware, any device
+containing an FX2 can become a powerful streaming logic analyzer.
+A variety of compatible low cost chinese made logic analyzer products are available for as little
+as $5. These can easily be found by searching for _24MHz Logic Analyzer_. There are also barebone
+Cypress FX2 boards such as the Lcsoft Mini Board, which can usually be found by searching for
+_Cypress FX2 Board_ or similar.
+
+In addition, a good set of https://sigrok.org/wiki/Probe_comparison[quality probe hooks] is recommended.
+
+Aside from FX2-based logic analyzers, sigrok also supports FX2-based oscilloscopes such as the
+https://sigrok.org/wiki/Hantek_6022BE[Hantek 6022BE], non-FX2 devices like the
+https://sigrok.org/wiki/Openbench_Logic_Sniffer[Openbench Logic Sniffer] or devices that make use
+of the SCPI protocol, as all reasonably modern oscilloscopes do (Rigol DS1054z, LeCroy WaveRunner,
+Yokogawa DLM and similar).
+
+Please be aware however, that PulseView currently only supports devices that can either work as an
+https://sigrok.org/wiki/Supported_hardware#Oscilloscopes[oscilloscope],
+a https://sigrok.org/wiki/Supported_hardware#Logic_analyzers[logic analyzer] or
+a https://sigrok.org/wiki/Supported_hardware#Mixed-signal_devices[mixed-signal device]. This
+means that multimeters in particular are currently only usable with either https://sigrok.org/wiki/Sigrok-cli[sigrok-cli]
+or https://sigrok.org/wiki/Sigrok-meter[sigrok-meter].
+
+image::pv_after_startup.png[]
+
+The PulseView user interface is geared towards navigation and analysis of captured waveforms, so
+the most space is by default used up by the main trace view. From here, you can access the most
+often used features.
+
+Before we dive deeper into how to accomplish things, let's make PulseView available on your
+system first.
index 5b6d09836d6cb8ea62e70cb080f9451bf9ce1704..33e36100b075b92783de804a2dd841ce9b1e8f8b 100644 (file)
@@ -1,5 +1,5 @@
 <RCC>
-    <qresource prefix="/" >
+    <qresource prefix="/">
        <file>icons/add-decoder.svg</file>
        <file>icons/application-exit.png</file>
        <file>icons/channels.svg</file>
@@ -9,9 +9,13 @@
        <file>icons/document-new.png</file>
        <file>icons/document-open.png</file>
        <file>icons/document-save-as.png</file>
+       <file>icons/help-browser.png</file>
        <file>icons/information.svg</file>
+       <file>icons/media-playback-pause.png</file>
+       <file>icons/media-playback-start.png</file>
        <file>icons/menu.svg</file>
        <file>icons/preferences-system.png</file>
+       <file>icons/settings-general.png</file>
        <file>icons/settings-views.svg</file>
        <file>icons/pulseview.png</file>
        <file>icons/pulseview.svg</file>
        <file>icons/trigger-marker-rising.svg</file>
        <file>icons/trigger-none.svg</file>
        <file>icons/trigger-rising.svg</file>
+       <file>icons/view-displaymode-last_complete_segment.svg</file>
+       <file>icons/view-displaymode-last_segment.svg</file>
+       <file>icons/view-displaymode-single_segment.svg</file>
        <file>icons/window-new.png</file>
        <file>icons/zoom-fit-best.png</file>
        <file>icons/zoom-in.png</file>
-       <file>icons/zoom-original.png</file>
        <file>icons/zoom-out.png</file>
     </qresource>
+
+    <qresource prefix="/">
+       <!-- QDarkStyleSheet -->
+       <file>themes/qdarkstyle/style.qss</file>
+       <file>themes/qdarkstyle/rc/up_arrow_disabled.png</file>
+       <file>themes/qdarkstyle/rc/Hmovetoolbar.png</file>
+       <file>themes/qdarkstyle/rc/stylesheet-branch-end.png</file>
+       <file>themes/qdarkstyle/rc/branch_closed-on.png</file>
+       <file>themes/qdarkstyle/rc/stylesheet-vline.png</file>
+       <file>themes/qdarkstyle/rc/branch_closed.png</file>
+       <file>themes/qdarkstyle/rc/branch_open-on.png</file>
+       <file>themes/qdarkstyle/rc/transparent.png</file>
+       <file>themes/qdarkstyle/rc/right_arrow_disabled.png</file>
+       <file>themes/qdarkstyle/rc/sizegrip.png</file>
+       <file>themes/qdarkstyle/rc/close.png</file>
+       <file>themes/qdarkstyle/rc/close-hover.png</file>
+       <file>themes/qdarkstyle/rc/close-pressed.png</file>
+       <file>themes/qdarkstyle/rc/down_arrow.png</file>
+       <file>themes/qdarkstyle/rc/Vmovetoolbar.png</file>
+       <file>themes/qdarkstyle/rc/left_arrow.png</file>
+       <file>themes/qdarkstyle/rc/stylesheet-branch-more.png</file>
+       <file>themes/qdarkstyle/rc/up_arrow.png</file>
+       <file>themes/qdarkstyle/rc/right_arrow.png</file>
+       <file>themes/qdarkstyle/rc/left_arrow_disabled.png</file>
+       <file>themes/qdarkstyle/rc/Hsepartoolbar.png</file>
+       <file>themes/qdarkstyle/rc/branch_open.png</file>
+       <file>themes/qdarkstyle/rc/Vsepartoolbar.png</file>
+       <file>themes/qdarkstyle/rc/down_arrow_disabled.png</file>
+       <file>themes/qdarkstyle/rc/undock.png</file>
+       <file>themes/qdarkstyle/rc/checkbox_checked_disabled.png</file>
+       <file>themes/qdarkstyle/rc/checkbox_checked_focus.png</file>
+       <file>themes/qdarkstyle/rc/checkbox_checked.png</file>
+       <file>themes/qdarkstyle/rc/checkbox_indeterminate.png</file>
+       <file>themes/qdarkstyle/rc/checkbox_indeterminate_focus.png</file>
+       <file>themes/qdarkstyle/rc/checkbox_unchecked_disabled.png</file>
+       <file>themes/qdarkstyle/rc/checkbox_unchecked_focus.png</file>
+       <file>themes/qdarkstyle/rc/checkbox_unchecked.png</file>
+       <file>themes/qdarkstyle/rc/radio_checked_disabled.png</file>
+       <file>themes/qdarkstyle/rc/radio_checked_focus.png</file>
+       <file>themes/qdarkstyle/rc/radio_checked.png</file>
+       <file>themes/qdarkstyle/rc/radio_unchecked_disabled.png</file>
+       <file>themes/qdarkstyle/rc/radio_unchecked_focus.png</file>
+       <file>themes/qdarkstyle/rc/radio_unchecked.png</file>
+    </qresource>
+
+    <qresource prefix="/">
+       <!-- DarkStyle -->
+       <file>themes/darkstyle/darkstyle.qss</file>
+       <file>themes/darkstyle/icon_close.png</file>
+       <file>themes/darkstyle/icon_restore.png</file>
+       <file>themes/darkstyle/icon_undock.png</file>
+       <file>themes/darkstyle/icon_branch_closed.png</file>
+       <file>themes/darkstyle/icon_branch_end.png</file>
+       <file>themes/darkstyle/icon_branch_more.png</file>
+       <file>themes/darkstyle/icon_branch_open.png</file>
+       <file>themes/darkstyle/icon_vline.png</file>
+       <file>themes/darkstyle/icon_checkbox_checked.png</file>
+       <file>themes/darkstyle/icon_checkbox_indeterminate.png</file>
+       <file>themes/darkstyle/icon_checkbox_unchecked.png</file>
+       <file>themes/darkstyle/icon_checkbox_checked_pressed.png</file>
+       <file>themes/darkstyle/icon_checkbox_indeterminate_pressed.png</file>
+       <file>themes/darkstyle/icon_checkbox_unchecked_pressed.png</file>
+       <file>themes/darkstyle/icon_checkbox_checked_disabled.png</file>
+       <file>themes/darkstyle/icon_checkbox_indeterminate_disabled.png</file>
+       <file>themes/darkstyle/icon_checkbox_unchecked_disabled.png</file>
+       <file>themes/darkstyle/icon_radiobutton_checked.png</file>
+       <file>themes/darkstyle/icon_radiobutton_unchecked.png</file>
+       <file>themes/darkstyle/icon_radiobutton_checked_pressed.png</file>
+       <file>themes/darkstyle/icon_radiobutton_unchecked_pressed.png</file>
+       <file>themes/darkstyle/icon_radiobutton_checked_disabled.png</file>
+       <file>themes/darkstyle/icon_radiobutton_unchecked_disabled.png</file>
+</qresource>
 </RCC>
index 383b5c23d29737c6c14ebb537b4756a57ee83139..5a6e28a1da996034aa24218df7ef2d66eb425543 100644 (file)
 #include "config.h"
 
 #include <iostream>
+#include <typeinfo>
 
-using std::cerr;
+#include <QDebug>
+
+#include <boost/version.hpp>
+
+#ifdef ENABLE_STACKTRACE
+#include <boost/stacktrace.hpp>
+#endif
+
+#ifdef ENABLE_DECODE
+#include <libsigrokdecode/libsigrokdecode.h>
+#endif
+
+using std::cout;
 using std::endl;
 using std::exception;
+using std::shared_ptr;
+
+#ifdef ENABLE_DECODE
+static gint sort_pds(gconstpointer a, gconstpointer b)
+{
+       const struct srd_decoder *sda, *sdb;
+
+       sda = (const struct srd_decoder *)a;
+       sdb = (const struct srd_decoder *)b;
+       return strcmp(sda->id, sdb->id);
+}
+#endif
 
 Application::Application(int &argc, char* argv[]) :
        QApplication(argc, argv)
@@ -35,13 +60,186 @@ Application::Application(int &argc, char* argv[]) :
        setOrganizationDomain("sigrok.org");
 }
 
+void Application::collect_version_info(shared_ptr<sigrok::Context> context)
+{
+       // Library versions and features
+       version_info_.emplace_back(applicationName(), applicationVersion());
+       version_info_.emplace_back("Qt", qVersion());
+       version_info_.emplace_back("glibmm", PV_GLIBMM_VERSION);
+       version_info_.emplace_back("Boost", BOOST_LIB_VERSION);
+
+       version_info_.emplace_back("libsigrok", QString("%1/%2 (rt: %3/%4)")
+               .arg(SR_PACKAGE_VERSION_STRING, SR_LIB_VERSION_STRING,
+               sr_package_version_string_get(), sr_lib_version_string_get()));
+
+       GSList *l_orig = sr_buildinfo_libs_get();
+       for (GSList *l = l_orig; l; l = l->next) {
+               GSList *m = (GSList *)l->data;
+               const char *lib = (const char *)m->data;
+               const char *version = (const char *)m->next->data;
+               version_info_.emplace_back(QString(" - %1").arg(QString(lib)), QString(version));
+               g_slist_free_full(m, g_free);
+       }
+       g_slist_free(l_orig);
+
+       char *host = sr_buildinfo_host_get();
+       version_info_.emplace_back(" - Host", QString(host));
+       g_free(host);
+
+       char *scpi_backends = sr_buildinfo_scpi_backends_get();
+       version_info_.emplace_back(" - SCPI backends", QString(scpi_backends));
+       g_free(scpi_backends);
+
+#ifdef ENABLE_DECODE
+       struct srd_decoder *dec;
+
+       version_info_.emplace_back("libsigrokdecode", QString("%1/%2 (rt: %3/%4)")
+               .arg(SRD_PACKAGE_VERSION_STRING, SRD_LIB_VERSION_STRING,
+               srd_package_version_string_get(), srd_lib_version_string_get()));
+
+       l_orig = srd_buildinfo_libs_get();
+       for (GSList *l = l_orig; l; l = l->next) {
+               GSList *m = (GSList *)l->data;
+               const char *lib = (const char *)m->data;
+               const char *version = (const char *)m->next->data;
+               version_info_.emplace_back(QString(" - %1").arg(QString(lib)), QString(version));
+               g_slist_free_full(m, g_free);
+       }
+       g_slist_free(l_orig);
+
+       host = srd_buildinfo_host_get();
+       version_info_.emplace_back(" - Host", QString(host));
+       g_free(host);
+#endif
+
+       // Firmware paths
+       l_orig = sr_resourcepaths_get(SR_RESOURCE_FIRMWARE);
+       for (GSList *l = l_orig; l; l = l->next)
+               fw_path_list_.emplace_back((char*)l->data);
+       g_slist_free_full(l_orig, g_free);
+
+       // PD paths
+#ifdef ENABLE_DECODE
+       l_orig = srd_searchpaths_get();
+       for (GSList *l = l_orig; l; l = l->next)
+               pd_path_list_.emplace_back((char*)l->data);
+       g_slist_free_full(l_orig, g_free);
+#endif
+
+       // Device drivers
+       for (auto& entry : context->drivers())
+               driver_list_.emplace_back(QString::fromUtf8(entry.first.c_str()),
+                       QString::fromUtf8(entry.second->long_name().c_str()));
+
+       // Input formats
+       for (auto& entry : context->input_formats())
+               input_format_list_.emplace_back(QString::fromUtf8(entry.first.c_str()),
+                       QString::fromUtf8(entry.second->description().c_str()));
+
+       // Output formats
+       for (auto& entry : context->output_formats())
+               output_format_list_.emplace_back(QString::fromUtf8(entry.first.c_str()),
+                       QString::fromUtf8(entry.second->description().c_str()));
+
+       // Protocol decoders
+#ifdef ENABLE_DECODE
+       GSList *sl = g_slist_copy((GSList *)srd_decoder_list());
+       sl = g_slist_sort(sl, sort_pds);
+       for (const GSList *l = sl; l; l = l->next) {
+               dec = (struct srd_decoder *)l->data;
+               pd_list_.emplace_back(QString::fromUtf8(dec->id),
+                       QString::fromUtf8(dec->longname));
+       }
+       g_slist_free(sl);
+#endif
+}
+
+void Application::print_version_info()
+{
+       cout << PV_TITLE << " " << PV_VERSION_STRING << endl;
+
+       cout << endl << "Libraries and features:" << endl;
+       for (pair<QString, QString>& entry : version_info_)
+               cout << "  " << entry.first.toStdString() << " " << entry.second.toStdString() << endl;
+
+       cout << endl << "Firmware search paths:" << endl;
+       for (QString& entry : fw_path_list_)
+               cout << "  " << entry.toStdString() << endl;
+
+       cout << endl << "Protocol decoder search paths:" << endl;
+       for (QString& entry : pd_path_list_)
+               cout << "  " << entry.toStdString() << endl;
+
+       cout << endl << "Supported hardware drivers:" << endl;
+       for (pair<QString, QString>& entry : driver_list_)
+               cout << "  " << entry.first.leftJustified(21, ' ').toStdString() <<
+               entry.second.toStdString() << endl;
+
+       cout << endl << "Supported input formats:" << endl;
+       for (pair<QString, QString>& entry : input_format_list_)
+               cout << "  " << entry.first.leftJustified(21, ' ').toStdString() <<
+               entry.second.toStdString() << endl;
+
+       cout << endl << "Supported output formats:" << endl;
+       for (pair<QString, QString>& entry : output_format_list_)
+               cout << "  " << entry.first.leftJustified(21, ' ').toStdString() <<
+               entry.second.toStdString() << endl;
+
+#ifdef ENABLE_DECODE
+       cout << endl << "Supported protocol decoders:" << endl;
+       for (pair<QString, QString>& entry : pd_list_)
+               cout << "  " << entry.first.leftJustified(21, ' ').toStdString() <<
+               entry.second.toStdString() << endl;
+#endif
+}
+
+vector< pair<QString, QString> > Application::get_version_info() const
+{
+       return version_info_;
+}
+
+vector<QString> Application::get_fw_path_list() const
+{
+       return fw_path_list_;
+}
+
+vector<QString> Application::get_pd_path_list() const
+{
+       return pd_path_list_;
+}
+
+vector< pair<QString, QString> > Application::get_driver_list() const
+{
+       return driver_list_;
+}
+
+vector< pair<QString, QString> > Application::get_input_format_list() const
+{
+       return input_format_list_;
+}
+
+vector< pair<QString, QString> > Application::get_output_format_list() const
+{
+       return output_format_list_;
+}
+
+vector< pair<QString, QString> > Application::get_pd_list() const
+{
+       return pd_list_;
+}
+
 bool Application::notify(QObject *receiver, QEvent *event)
 {
        try {
                return QApplication::notify(receiver, event);
        } catch (exception& e) {
-               cerr << "Caught exception: " << e.what() << endl;
+               qDebug().nospace() << "Caught exception of type " << \
+                       typeid(e).name() << " (" << e.what() << ")";
+#ifdef ENABLE_STACKTRACE
+               throw e;
+#else
                exit(1);
+#endif
                return false;
        }
 }
index 7059c02a35293f0e741977ea5cf588356734cbd5..c618f80d9c1abeee91a1ee61e54d46d8d3c7b9b3 100644 (file)
 #ifndef PULSEVIEW_PV_APPLICATION_HPP
 #define PULSEVIEW_PV_APPLICATION_HPP
 
+#include <vector>
+
 #include <QApplication>
 
+#include <libsigrokcxx/libsigrokcxx.hpp>
+
+using std::shared_ptr;
+using std::pair;
+using std::vector;
+
 class Application : public QApplication
 {
+       Q_OBJECT
+
 public:
        Application(int &argc, char* argv[]);
+
+       void collect_version_info(shared_ptr<sigrok::Context> context);
+       void print_version_info();
+
+       vector< pair<QString, QString> > get_version_info() const;
+       vector<QString> get_fw_path_list() const;
+       vector<QString> get_pd_path_list() const;
+       vector< pair<QString, QString> > get_driver_list() const;
+       vector< pair<QString, QString> > get_input_format_list() const;
+       vector< pair<QString, QString> > get_output_format_list() const;
+       vector< pair<QString, QString> > get_pd_list() const;
+
 private:
        bool notify(QObject *receiver, QEvent *event);
+
+       vector< pair<QString, QString> > version_info_;
+       vector<QString> fw_path_list_;
+       vector<QString> pd_path_list_;
+       vector< pair<QString, QString> > driver_list_;
+       vector< pair<QString, QString> > input_format_list_;
+       vector< pair<QString, QString> > output_format_list_;
+       vector< pair<QString, QString> > pd_list_;
 };
 
 #endif // PULSEVIEW_PV_APPLICATION_HPP
index ae4f2943bdfe988a9dc6e82af5337525c317c04f..9735e14681edaa6d9f1b6bdd642f76ba8db694d8 100644 (file)
 #include <cassert>
 
 #include <QFormLayout>
+#include <QHBoxLayout>
+#include <QIcon>
 #include <QLabel>
+#include <QPushButton>
 
 #include <pv/prop/property.hpp>
 
@@ -46,28 +49,56 @@ void Binding::commit()
        }
 }
 
-void Binding::add_properties_to_form(QFormLayout *layout,
-       bool auto_commit) const
+void Binding::add_properties_to_form(QFormLayout *layout, bool auto_commit)
 {
        assert(layout);
 
+       help_labels_.clear();
+
        for (shared_ptr<pv::prop::Property> p : properties_) {
                assert(p);
 
-               QWidget *const widget = p->get_widget(layout->parentWidget(),
-                       auto_commit);
+               QWidget *widget;
+               QLabel *help_lbl = nullptr;
+
+               if (p->desc().isEmpty()) {
+                       widget = p->get_widget(layout->parentWidget(), auto_commit);
+               } else {
+                       QPushButton *help_btn = new QPushButton();
+                       help_btn->setFlat(true);
+                       help_btn->setIcon(QIcon(":/icons/help-browser.png"));
+                       help_btn->setToolTip(p->desc());
+                       connect(help_btn, SIGNAL(clicked(bool)),
+                               this, SLOT(on_help_clicked()));
+
+                       QHBoxLayout *layout = new QHBoxLayout();
+                       layout->setContentsMargins(0, 0, 0, 0);
+                       layout->addWidget(p->get_widget(layout->parentWidget(), auto_commit));
+                       layout->addWidget(help_btn, 0, Qt::AlignRight);
+
+                       widget = new QWidget();
+                       widget->setLayout(layout);
+
+                       help_lbl = new QLabel(p->desc());
+                       help_lbl->setVisible(false);
+                       help_lbl->setWordWrap(true);
+                       help_labels_[help_btn] = help_lbl;
+               }
+
                if (p->labeled_widget()) {
                        layout->addRow(widget);
                } else {
                        auto *lbl = new QLabel(p->name());
-                       lbl->setToolTip(p->desc());
+                       lbl->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
                        layout->addRow(lbl, widget);
                }
+
+               if (help_lbl)
+                       layout->addRow(help_lbl);
        }
 }
 
-QWidget* Binding::get_property_form(QWidget *parent,
-       bool auto_commit) const
+QWidget* Binding::get_property_form(QWidget *parent, bool auto_commit)
 {
        QWidget *const form = new QWidget(parent);
        QFormLayout *const layout = new QFormLayout(form);
@@ -76,6 +107,14 @@ QWidget* Binding::get_property_form(QWidget *parent,
        return form;
 }
 
+void Binding::update_property_widgets()
+{
+       for (shared_ptr<pv::prop::Property> p : properties_) {
+               assert(p);
+               p->update_widget();
+       }
+}
+
 QString Binding::print_gvariant(Glib::VariantBase gvar)
 {
        QString s;
@@ -84,13 +123,21 @@ QString Binding::print_gvariant(Glib::VariantBase gvar)
                s = QString::fromStdString("(null)");
        else if (gvar.is_of_type(Glib::VariantType("s")))
                s = QString::fromStdString(
-                       Glib::VariantBase::cast_dynamic<Glib::Variant<string>>(
-                               gvar).get());
+                       Glib::VariantBase::cast_dynamic<Glib::Variant<string>>(gvar).get());
        else
                s = QString::fromStdString(gvar.print());
 
        return s;
 }
 
+void Binding::on_help_clicked()
+{
+       QPushButton *btn = qobject_cast<QPushButton*>(QObject::sender());
+       assert(btn);
+
+       QLabel *lbl = help_labels_.at(btn);
+       lbl->setVisible(!lbl->isVisible());
+}
+
 }  // namespace binding
 }  // namespace pv
index e672ff176f24a5301026e519057b47b0db0b263f..5580a0b05b48765d74fd9272beafe4e38ddc2ca8 100644 (file)
@@ -26,15 +26,19 @@ G_GNUC_BEGIN_IGNORE_DEPRECATIONS
 #include <glibmm.h>
 G_GNUC_END_IGNORE_DEPRECATIONS
 
+#include <map>
 #include <memory>
 #include <vector>
 
+#include <QObject>
 #include <QString>
 
+using std::map;
 using std::shared_ptr;
 using std::vector;
 
 class QFormLayout;
+class QLabel;
 class QWidget;
 
 namespace pv {
@@ -45,23 +49,29 @@ class Property;
 
 namespace binding {
 
-class Binding
+class Binding: public QObject
 {
+       Q_OBJECT
+
 public:
        const vector< shared_ptr<prop::Property> >& properties();
 
        void commit();
 
-       void add_properties_to_form(QFormLayout *layout,
-               bool auto_commit = false) const;
+       void add_properties_to_form(QFormLayout *layout, bool auto_commit = false);
+
+       QWidget* get_property_form(QWidget *parent, bool auto_commit = false);
 
-       QWidget* get_property_form(QWidget *parent,
-               bool auto_commit = false) const;
+       void update_property_widgets();
 
        static QString print_gvariant(Glib::VariantBase gvar);
 
+protected Q_SLOTS:
+       void on_help_clicked();
+
 protected:
        vector< shared_ptr<prop::Property> > properties_;
+       map<QWidget*, QLabel*> help_labels_;
 };
 
 }  // namespace binding
index f2e2e1d579f46eabe7b67104de3a103a6647055a..f51f90774afd0561d130704819528f9fd887a0f1 100644 (file)
 #include <boost/none_t.hpp>
 
 #include <pv/data/decode/decoder.hpp>
-#include <pv/data/decoderstack.hpp>
+#include <pv/data/decodesignal.hpp>
 #include <pv/prop/double.hpp>
 #include <pv/prop/enum.hpp>
 #include <pv/prop/int.hpp>
 #include <pv/prop/string.hpp>
 
 using boost::none;
-using std::make_pair;
 using std::map;
 using std::pair;
 using std::shared_ptr;
@@ -48,9 +47,9 @@ namespace pv {
 namespace binding {
 
 Decoder::Decoder(
-       shared_ptr<pv::data::DecoderStack> decoder_stack,
+       shared_ptr<pv::data::DecodeSignal> decode_signal,
        shared_ptr<data::decode::Decoder> decoder) :
-       decoder_stack_(decoder_stack),
+       decode_signal_(decode_signal),
        decoder_(decoder)
 {
        assert(decoder_);
@@ -97,7 +96,7 @@ shared_ptr<Property> Decoder::bind_enum(
        vector< pair<Glib::VariantBase, QString> > values;
        for (GSList *l = option->values; l; l = l->next) {
                Glib::VariantBase var = Glib::VariantBase((GVariant*)l->data, true);
-               values.push_back(make_pair(var, print_gvariant(var)));
+               values.emplace_back(var, print_gvariant(var));
        }
 
        return shared_ptr<Property>(new Enum(name, desc, values, getter, setter));
@@ -137,8 +136,8 @@ void Decoder::setter(const char *id, Glib::VariantBase value)
        assert(decoder_);
        decoder_->set_option(id, value.gobj());
 
-       assert(decoder_stack_);
-       decoder_stack_->begin_decode();
+       assert(decode_signal_);
+       decode_signal_->begin_decode();
 }
 
 }  // namespace binding
index bf670403dee317f486c5d43ab093eb74932288fa..a93a057f1a371b8571f19b0cd2808aa11e217b9e 100644 (file)
@@ -31,7 +31,7 @@ struct srd_decoder_option;
 namespace pv {
 
 namespace data {
-class DecoderStack;
+class DecodeSignal;
 namespace decode {
 class Decoder;
 }
@@ -42,7 +42,7 @@ namespace binding {
 class Decoder : public Binding
 {
 public:
-       Decoder(shared_ptr<pv::data::DecoderStack> decoder_stack,
+       Decoder(shared_ptr<pv::data::DecodeSignal> decode_signal,
                shared_ptr<pv::data::decode::Decoder> decoder);
 
 private:
@@ -55,7 +55,7 @@ private:
        void setter(const char *id, Glib::VariantBase value);
 
 private:
-       shared_ptr<pv::data::DecoderStack> decoder_stack_;
+       shared_ptr<pv::data::DecodeSignal> decode_signal_;
        shared_ptr<pv::data::decode::Decoder> decoder_;
 };
 
index 20082db2f7a949666151fc01e006d7408f7fb3ab..37c9d43d55248218b4e7e247cd6173fa1696b664 100644 (file)
@@ -32,7 +32,6 @@
 using boost::optional;
 
 using std::function;
-using std::make_pair;
 using std::pair;
 using std::set;
 using std::shared_ptr;
@@ -69,7 +68,7 @@ Device::Device(shared_ptr<sigrok::Configurable> configurable) :
                string name_str;
                try {
                        name_str = key->description();
-               } catch (Error e) {
+               } catch (Error& e) {
                        name_str = key->name();
                }
 
@@ -98,6 +97,8 @@ Device::Device(shared_ptr<sigrok::Configurable> configurable) :
                case SR_CONF_TRIGGER_SLOPE:
                case SR_CONF_COUPLING:
                case SR_CONF_CLOCK_EDGE:
+               case SR_CONF_DATA_SOURCE:
+               case SR_CONF_EXTERNAL_CLOCK_SOURCE:
                        bind_enum(name, "", key, capabilities, get, set);
                        break;
 
@@ -105,6 +106,7 @@ Device::Device(shared_ptr<sigrok::Configurable> configurable) :
                case SR_CONF_EXTERNAL_CLOCK:
                case SR_CONF_RLE:
                case SR_CONF_POWER_OFF:
+               case SR_CONF_AVERAGING:
                        bind_bool(name, "", get, set);
                        break;
 
@@ -127,6 +129,13 @@ Device::Device(shared_ptr<sigrok::Configurable> configurable) :
                                bind_int(name, "", "", pair<int64_t, int64_t>(1, 500), get, set);
                        break;
 
+               case SR_CONF_AVG_SAMPLES:
+                       if (capabilities.count(Capability::LIST))
+                               bind_enum(name, "", key, capabilities, get, set, print_averages);
+                       else
+                               bind_int(name, "", "", pair<int64_t, int64_t>(0, INT32_MAX), get, set);
+                       break;
+
                default:
                        break;
                }
@@ -157,7 +166,7 @@ void Device::bind_enum(const QString &name, const QString &desc,
 
                vector< pair<Glib::VariantBase, QString> > values;
                while ((iter.next_value(gvar)))
-                       values.push_back(make_pair(gvar, printer(gvar)));
+                       values.emplace_back(gvar, printer(gvar));
 
                properties_.push_back(shared_ptr<Property>(new Enum(name, desc, values,
                        getter, setter)));
@@ -206,5 +215,12 @@ QString Device::print_probe_factor(Glib::VariantBase gvar)
        return QString("%1x").arg(factor);
 }
 
+QString Device::print_averages(Glib::VariantBase gvar)
+{
+       uint64_t avg;
+       avg = g_variant_get_uint64(gvar.gobj());
+       return QString("%1").arg(avg);
+}
+
 }  // namespace binding
 }  // namespace pv
index dcef9470cc12e091565871486d1ef3d6a8799053..9f5daf574a250beef9e3b5030e75599f88766fc1 100644 (file)
@@ -20,6 +20,8 @@
 #ifndef PULSEVIEW_PV_BINDING_DEVICE_HPP
 #define PULSEVIEW_PV_BINDING_DEVICE_HPP
 
+#include <functional>
+
 #include <boost/optional.hpp>
 
 #include <QObject>
@@ -40,7 +42,7 @@ namespace pv {
 
 namespace binding {
 
-class Device : public QObject, public Binding
+class Device : public Binding
 {
        Q_OBJECT
 
@@ -66,6 +68,7 @@ private:
        static QString print_vdiv(Glib::VariantBase gvar);
        static QString print_voltage_threshold(Glib::VariantBase gvar);
        static QString print_probe_factor(Glib::VariantBase gvar);
+       static QString print_averages(Glib::VariantBase gvar);
 
 protected:
        shared_ptr<sigrok::Configurable> configurable_;
index 9d2299afaf95fd767a5d7142fb71a606e3d97f0f..f9a061c76e78c7b7e77a33ec1d04250328263b70 100644 (file)
@@ -35,7 +35,6 @@
 
 using boost::none;
 
-using std::make_pair;
 using std::map;
 using std::pair;
 using std::shared_ptr;
@@ -60,12 +59,13 @@ namespace binding {
 InputOutput::InputOutput(
        const map<string, shared_ptr<Option>> &options)
 {
-       for (pair<string, shared_ptr<Option>> o : options) {
+       for (const pair<string, shared_ptr<Option>>& o : options) {
                const shared_ptr<Option> &opt = o.second;
                assert(opt);
 
                const QString name = QString::fromStdString(opt->name());
                const QString desc = QString::fromStdString(opt->description());
+
                const VariantBase def_val = opt->default_value();
                const vector<VariantBase> values = opt->values();
 
@@ -111,7 +111,7 @@ shared_ptr<Property> InputOutput::bind_enum(
 {
        vector< pair<VariantBase, QString> > enum_vals;
        for (VariantBase var : values)
-               enum_vals.push_back(make_pair(var, print_gvariant(var)));
+               enum_vals.emplace_back(var, print_gvariant(var));
        return shared_ptr<Property>(new Enum(name, desc, enum_vals, getter, setter));
 }
 
index 854dae3e68eaaec8d71212219365323abcefbbe8..f8fe473d3681ebc31f0850d052af2d952d8fbae4 100644 (file)
@@ -37,7 +37,7 @@ Analog::Analog() :
 
 void Analog::push_segment(shared_ptr<AnalogSegment> &segment)
 {
-       segments_.push_front(segment);
+       segments_.push_back(segment);
 }
 
 const deque< shared_ptr<AnalogSegment> >& Analog::analog_segments() const
@@ -51,6 +51,11 @@ vector< shared_ptr<Segment> > Analog::segments() const
                segments_.begin(), segments_.end());
 }
 
+uint32_t Analog::get_segment_count() const
+{
+       return (uint32_t)segments_.size();
+}
+
 void Analog::clear()
 {
        segments_.clear();
@@ -58,10 +63,18 @@ void Analog::clear()
        samples_cleared();
 }
 
+double Analog::get_samplerate() const
+{
+       if (segments_.empty())
+               return 1.0;
+
+       return segments_.front()->samplerate();
+}
+
 uint64_t Analog::max_sample_count() const
 {
        uint64_t l = 0;
-       for (const shared_ptr<AnalogSegment> s : segments_) {
+       for (const shared_ptr<AnalogSegment>& s : segments_) {
                assert(s);
                l = max(l, s->get_sample_count());
        }
@@ -74,5 +87,10 @@ void Analog::notify_samples_added(QObject* segment, uint64_t start_sample,
        samples_added(segment, start_sample, end_sample);
 }
 
+void Analog::notify_min_max_changed(float min, float max)
+{
+       min_max_changed(min, max);
+}
+
 } // namespace data
 } // namespace pv
index 30860ce18e4a0c4f98590629fd965c8a0326d3de..c0b9a0134d72d9b5028f75b5d19040a71d81c991 100644 (file)
@@ -49,19 +49,27 @@ public:
 
        vector< shared_ptr<Segment> > segments() const;
 
+       uint32_t get_segment_count() const;
+
        void clear();
 
+       double get_samplerate() const;
+
        uint64_t max_sample_count() const;
 
        void notify_samples_added(QObject* segment, uint64_t start_sample,
                uint64_t end_sample);
 
+       void notify_min_max_changed(float min, float max);
+
 Q_SIGNALS:
        void samples_cleared();
 
        void samples_added(QObject* segment, uint64_t start_sample,
                uint64_t end_sample);
 
+       void min_max_changed(float min, float max);
+
 private:
        deque< shared_ptr<AnalogSegment> > segments_;
 };
index 5e42556ca8c3f01341283f909f2ffc81ed2d394a..342612aae02e15954671d2044f3bdb337682cd09 100644 (file)
@@ -48,8 +48,8 @@ const int AnalogSegment::EnvelopeScaleFactor = 1 << EnvelopeScalePower;
 const float AnalogSegment::LogEnvelopeScaleFactor = logf(EnvelopeScaleFactor);
 const uint64_t AnalogSegment::EnvelopeDataUnit = 64 * 1024;    // bytes
 
-AnalogSegment::AnalogSegment(Analog& owner, uint64_t samplerate) :
-       Segment(samplerate, sizeof(float)),
+AnalogSegment::AnalogSegment(Analog& owner, uint32_t segment_id, uint64_t samplerate) :
+       Segment(segment_id, samplerate, sizeof(float)),
        owner_(owner),
        min_value_(0),
        max_value_(0)
@@ -75,7 +75,7 @@ void AnalogSegment::append_interleaved_samples(const float *data,
        uint64_t prev_sample_count = sample_count_;
 
        // Deinterleave the samples and add them
-       unique_ptr<float> deint_data(new float[sample_count]);
+       unique_ptr<float[]> deint_data(new float[sample_count]);
        float *deint_data_ptr = deint_data.get();
        for (uint32_t i = 0; i < sample_count; i++) {
                *deint_data_ptr = (float)(*data);
@@ -96,18 +96,19 @@ void AnalogSegment::append_interleaved_samples(const float *data,
                        prev_sample_count + 1);
 }
 
-const float* AnalogSegment::get_samples(
-       int64_t start_sample, int64_t end_sample) const
+void AnalogSegment::get_samples(int64_t start_sample, int64_t end_sample,
+       float* dest) const
 {
        assert(start_sample >= 0);
        assert(start_sample < (int64_t)sample_count_);
        assert(end_sample >= 0);
-       assert(end_sample < (int64_t)sample_count_);
+       assert(end_sample <= (int64_t)sample_count_);
        assert(start_sample <= end_sample);
+       assert(dest != nullptr);
 
        lock_guard<recursive_mutex> lock(mutex_);
 
-       return (float*)get_raw_samples(start_sample, (end_sample - start_sample));
+       get_raw_samples(start_sample, (end_sample - start_sample), (uint8_t*)dest);
 }
 
 const pair<float, float> AnalogSegment::get_min_max() const
@@ -115,19 +116,11 @@ const pair<float, float> AnalogSegment::get_min_max() const
        return make_pair(min_value_, max_value_);
 }
 
-SegmentAnalogDataIterator* AnalogSegment::begin_sample_iteration(uint64_t start)
+float* AnalogSegment::get_iterator_value_ptr(SegmentDataIterator* it)
 {
-       return (SegmentAnalogDataIterator*)begin_raw_sample_iteration(start);
-}
-
-void AnalogSegment::continue_sample_iteration(SegmentAnalogDataIterator* it, uint64_t increase)
-{
-       Segment::continue_raw_sample_iteration((SegmentRawDataIterator*)it, increase);
-}
+       assert(it->sample_index <= (sample_count_ - 1));
 
-void AnalogSegment::end_sample_iteration(SegmentAnalogDataIterator* it)
-{
-       Segment::end_raw_sample_iteration((SegmentRawDataIterator*)it);
+       return (float*)(it->chunk + it->chunk_offs);
 }
 
 void AnalogSegment::get_envelope_section(EnvelopeSection &s,
@@ -170,24 +163,25 @@ void AnalogSegment::append_payload_to_envelope_levels()
        Envelope &e0 = envelope_levels_[0];
        uint64_t prev_length;
        EnvelopeSample *dest_ptr;
-       SegmentRawDataIterator* it;
+       SegmentDataIterator* it;
 
        // Expand the data buffer to fit the new samples
        prev_length = e0.length;
        e0.length = sample_count_ / EnvelopeScaleFactor;
 
        // Calculate min/max values in case we have too few samples for an envelope
+       const float old_min_value = min_value_, old_max_value = max_value_;
        if (sample_count_ < EnvelopeScaleFactor) {
-               it = begin_raw_sample_iteration(0);
+               it = begin_sample_iteration(0);
                for (uint64_t i = 0; i < sample_count_; i++) {
-                       const float sample = *((float*)it->value);
+                       const float sample = *get_iterator_value_ptr(it);
                        if (sample < min_value_)
                                min_value_ = sample;
                        if (sample > max_value_)
                                max_value_ = sample;
-                       continue_raw_sample_iteration(it, 1);
+                       continue_sample_iteration(it, 1);
                }
-               end_raw_sample_iteration(it);
+               end_sample_iteration(it);
        }
 
        // Break off if there are no new samples to compute
@@ -202,9 +196,9 @@ void AnalogSegment::append_payload_to_envelope_levels()
        uint64_t start_sample = prev_length * EnvelopeScaleFactor;
        uint64_t end_sample = e0.length * EnvelopeScaleFactor;
 
-       it = begin_raw_sample_iteration(start_sample);
+       it = begin_sample_iteration(start_sample);
        for (uint64_t i = start_sample; i < end_sample; i += EnvelopeScaleFactor) {
-               const float* samples = (float*)it->value;
+               const float* samples = get_iterator_value_ptr(it);
 
                const EnvelopeSample sub_sample = {
                        *min_element(samples, samples + EnvelopeScaleFactor),
@@ -216,10 +210,10 @@ void AnalogSegment::append_payload_to_envelope_levels()
                if (sub_sample.max > max_value_)
                        max_value_ = sub_sample.max;
 
-               continue_raw_sample_iteration(it, EnvelopeScaleFactor);
+               continue_sample_iteration(it, EnvelopeScaleFactor);
                *dest_ptr++ = sub_sample;
        }
-       end_raw_sample_iteration(it);
+       end_sample_iteration(it);
 
        // Compute higher level mipmaps
        for (unsigned int level = 1; level < ScaleStepCount; level++) {
@@ -256,6 +250,10 @@ void AnalogSegment::append_payload_to_envelope_levels()
                        *dest_ptr = sub_sample;
                }
        }
+
+       // Notify if the min or max value changed
+       if ((old_min_value != min_value_) || (old_max_value != max_value_))
+               owner_.min_max_changed(min_value_, max_value_);
 }
 
 } // namespace data
index 8dd6f5f189746ec903157c7563892ad2073f1170..df25f0b74a669109663a08e0df4dbeff3b5a7641 100644 (file)
@@ -38,13 +38,7 @@ namespace data {
 
 class Analog;
 
-typedef struct {
-       uint64_t sample_index, chunk_num, chunk_offs;
-       uint8_t* chunk;
-       float* value;
-} SegmentAnalogDataIterator;
-
-class AnalogSegment : public QObject, public Segment
+class AnalogSegment : public Segment
 {
        Q_OBJECT
 
@@ -79,21 +73,18 @@ private:
        static const uint64_t EnvelopeDataUnit;
 
 public:
-       AnalogSegment(Analog& owner, uint64_t samplerate);
+       AnalogSegment(Analog& owner, uint32_t segment_id, uint64_t samplerate);
 
        virtual ~AnalogSegment();
 
        void append_interleaved_samples(const float *data,
                size_t sample_count, size_t stride);
 
-       const float* get_samples(int64_t start_sample,
-               int64_t end_sample) const;
+       void get_samples(int64_t start_sample, int64_t end_sample, float* dest) const;
 
        const pair<float, float> get_min_max() const;
 
-       SegmentAnalogDataIterator* begin_sample_iteration(uint64_t start);
-       void continue_sample_iteration(SegmentAnalogDataIterator* it, uint64_t increase);
-       void end_sample_iteration(SegmentAnalogDataIterator* it);
+       float* get_iterator_value_ptr(SegmentDataIterator* it);
 
        void get_envelope_section(EnvelopeSection &s,
                uint64_t start, uint64_t end, float min_length) const;
index 7c720430e9d6cf7e6a688fd6c138cad2cd90589b..e983b0df1c3e971ba7942c9ccadb86ed10e09bbb 100644 (file)
@@ -32,16 +32,17 @@ namespace pv {
 namespace data {
 namespace decode {
 
-Annotation::Annotation(const srd_proto_data *const pdata) :
+Annotation::Annotation(const srd_proto_data *const pdata, const Row *row) :
        start_sample_(pdata->start_sample),
-       end_sample_(pdata->end_sample)
+       end_sample_(pdata->end_sample),
+       row_(row)
 {
        assert(pdata);
        const srd_proto_data_annotation *const pda =
                (const srd_proto_data_annotation*)pdata->data;
        assert(pda);
 
-       format_ = pda->ann_class;
+       ann_class_ = (Class)(pda->ann_class);
 
        const char *const *annotations = (char**)pda->ann_text;
        while (*annotations) {
@@ -60,9 +61,9 @@ uint64_t Annotation::end_sample() const
        return end_sample_;
 }
 
-int Annotation::format() const
+Annotation::Class Annotation::ann_class() const
 {
-       return format_;
+       return ann_class_;
 }
 
 const vector<QString>& Annotation::annotations() const
@@ -70,6 +71,16 @@ const vector<QString>& Annotation::annotations() const
        return annotations_;
 }
 
+const Row* Annotation::row() const
+{
+       return row_;
+}
+
+bool Annotation::operator<(const Annotation &other) const
+{
+       return (start_sample_ < other.start_sample_);
+}
+
 } // namespace decode
 } // namespace data
 } // namespace pv
index 2be8e88d989e4cddacaa18d9b86156ca875c4e95..8b91c4f47e066605e307ed0301fbd1871d59436d 100644 (file)
@@ -20,7 +20,8 @@
 #ifndef PULSEVIEW_PV_VIEW_DECODE_ANNOTATION_HPP
 #define PULSEVIEW_PV_VIEW_DECODE_ANNOTATION_HPP
 
-#include <stdint.h>
+#include <cstdint>
+#include <vector>
 
 #include <QString>
 
@@ -32,21 +33,30 @@ namespace pv {
 namespace data {
 namespace decode {
 
+class Row;
+
 class Annotation
 {
 public:
-       Annotation(const srd_proto_data *const pdata);
+       typedef uint32_t Class;
+
+public:
+       Annotation(const srd_proto_data *const pdata, const Row *row);
 
        uint64_t start_sample() const;
        uint64_t end_sample() const;
-       int format() const;
+       Class ann_class() const;
        const vector<QString>& annotations() const;
+       const Row* row() const;
+
+       bool operator<(const Annotation &other) const;
 
 private:
        uint64_t start_sample_;
        uint64_t end_sample_;
-       int format_;
+       Class ann_class_;
        vector<QString> annotations_;
+       const Row *row_;
 };
 
 } // namespace decode
index 841d4fd7b874cdf4ba30227beaf862f361d60627..f86c5d08dc86d9261718ab92e2005b1b30dbd914 100644 (file)
 
 #include <cassert>
 
+#include <QDebug>
+
 #include <libsigrokcxx/libsigrokcxx.hpp>
 #include <libsigrokdecode/libsigrokdecode.h>
 
 #include "decoder.hpp"
 
 #include <pv/data/signalbase.hpp>
+#include <pv/data/decodesignal.hpp>
 
-using std::set;
+using pv::data::DecodeChannel;
 using std::map;
-using std::shared_ptr;
 using std::string;
 
 namespace pv {
@@ -38,7 +40,7 @@ namespace decode {
 Decoder::Decoder(const srd_decoder *const dec) :
        decoder_(dec),
        shown_(true),
-       initial_pins_(nullptr)
+       decoder_inst_(nullptr)
 {
 }
 
@@ -63,30 +65,16 @@ void Decoder::show(bool show)
        shown_ = show;
 }
 
-const map<const srd_channel*, shared_ptr<data::SignalBase> >&
-Decoder::channels() const
+const vector<DecodeChannel*>& Decoder::channels() const
 {
        return channels_;
 }
 
-void Decoder::set_channels(map<const srd_channel*,
-       shared_ptr<data::SignalBase> > channels)
+void Decoder::set_channels(vector<DecodeChannel*> channels)
 {
        channels_ = channels;
 }
 
-void Decoder::set_initial_pins(GArray *initial_pins)
-{
-       if (initial_pins_)
-               g_array_free(initial_pins_, TRUE);
-       initial_pins_ = initial_pins;
-}
-
-GArray *Decoder::initial_pins() const
-{
-       return initial_pins_;
-}
-
 const map<string, GVariant*>& Decoder::options() const
 {
        return options_;
@@ -97,33 +85,39 @@ void Decoder::set_option(const char *id, GVariant *value)
        assert(value);
        g_variant_ref(value);
        options_[id] = value;
+
+       // If we have a decoder instance, apply option value immediately
+       apply_all_options();
 }
 
-bool Decoder::have_required_channels() const
+void Decoder::apply_all_options()
 {
-       for (GSList *l = decoder_->channels; l; l = l->next) {
-               const srd_channel *const pdch = (const srd_channel*)l->data;
-               assert(pdch);
-               if (channels_.find(pdch) == channels_.end())
-                       return false;
+       if (decoder_inst_) {
+               GHashTable *const opt_hash = g_hash_table_new_full(g_str_hash,
+                       g_str_equal, g_free, (GDestroyNotify)g_variant_unref);
+
+               for (const auto& option : options_) {
+                       GVariant *const value = option.second;
+                       g_variant_ref(value);
+                       g_hash_table_replace(opt_hash, (void*)g_strdup(
+                               option.first.c_str()), value);
+               }
+
+               srd_inst_option_set(decoder_inst_, opt_hash);
+               g_hash_table_destroy(opt_hash);
        }
-
-       return true;
 }
 
-set< shared_ptr<pv::data::Logic> > Decoder::get_data()
+bool Decoder::have_required_channels() const
 {
-       set< shared_ptr<pv::data::Logic> > data;
-       for (const auto& channel : channels_) {
-               shared_ptr<data::SignalBase> b(channel.second);
-               assert(b);
-               data.insert(b->logic_data());
-       }
+       for (DecodeChannel *ch : channels_)
+               if (!ch->assigned_signal && !ch->is_optional)
+                       return false;
 
-       return data;
+       return true;
 }
 
-srd_decoder_inst* Decoder::create_decoder_inst(srd_session *session) const
+srd_decoder_inst* Decoder::create_decoder_inst(srd_session *session)
 {
        GHashTable *const opt_hash = g_hash_table_new_full(g_str_hash,
                g_str_equal, g_free, (GDestroyNotify)g_variant_unref);
@@ -135,29 +129,47 @@ srd_decoder_inst* Decoder::create_decoder_inst(srd_session *session) const
                        option.first.c_str()), value);
        }
 
-       srd_decoder_inst *const decoder_inst = srd_inst_new(
-               session, decoder_->id, opt_hash);
+       if (decoder_inst_)
+               qDebug() << "WARNING: previous decoder instance" << decoder_inst_ << "exists";
+
+       decoder_inst_ = srd_inst_new(session, decoder_->id, opt_hash);
        g_hash_table_destroy(opt_hash);
 
-       if (!decoder_inst)
+       if (!decoder_inst_)
                return nullptr;
 
        // Setup the channels
+       GArray *const init_pin_states = g_array_sized_new(false, true,
+               sizeof(uint8_t), channels_.size());
+
+       g_array_set_size(init_pin_states, channels_.size());
+
        GHashTable *const channels = g_hash_table_new_full(g_str_hash,
                g_str_equal, g_free, (GDestroyNotify)g_variant_unref);
 
-       for (const auto& channel : channels_) {
-               shared_ptr<data::SignalBase> b(channel.second);
-               GVariant *const gvar = g_variant_new_int32(b->index());
+       for (DecodeChannel *ch : channels_) {
+               if (!ch->assigned_signal)
+                       continue;
+
+               init_pin_states->data[ch->id] = ch->initial_pin_state;
+
+               GVariant *const gvar = g_variant_new_int32(ch->bit_id);  // bit_id = bit position
                g_variant_ref_sink(gvar);
-               g_hash_table_insert(channels, channel.first->id, gvar);
+               // key is channel name (pdch->id), value is bit position in each sample (gvar)
+               g_hash_table_insert(channels, ch->pdch_->id, gvar);
        }
 
-       srd_inst_channel_set_all(decoder_inst, channels);
+       srd_inst_channel_set_all(decoder_inst_, channels);
 
-       srd_inst_initial_pins_set_all(decoder_inst, initial_pins_);
+       srd_inst_initial_pins_set_all(decoder_inst_, init_pin_states);
+       g_array_free(init_pin_states, true);
 
-       return decoder_inst;
+       return decoder_inst_;
+}
+
+void Decoder::invalidate_decoder_inst()
+{
+       decoder_inst_ = nullptr;
 }
 
 }  // namespace decode
index eff2367fb3604cf4c76e7e9ca7c9887cf0e741c4..55742c6070e5a020c00042b2c8894e744b13986e 100644 (file)
 #include <map>
 #include <memory>
 #include <set>
+#include <vector>
 
 #include <glib.h>
 
 using std::map;
-using std::set;
-using std::shared_ptr;
 using std::string;
+using std::vector;
 
 struct srd_decoder;
 struct srd_decoder_inst;
@@ -40,6 +40,7 @@ namespace pv {
 
 namespace data {
 
+struct DecodeChannel;
 class Logic;
 class SignalBase;
 
@@ -57,33 +58,28 @@ public:
        bool shown() const;
        void show(bool show = true);
 
-       const map<const srd_channel*,
-               shared_ptr<data::SignalBase> >& channels() const;
-       void set_channels(map<const srd_channel*,
-               shared_ptr<data::SignalBase> > channels);
-
-       void set_initial_pins(GArray *initial_pins);
-
-       GArray *initial_pins() const;
+       const vector<data::DecodeChannel*>& channels() const;
+       void set_channels(vector<data::DecodeChannel*> channels);
 
        const map<string, GVariant*>& options() const;
 
        void set_option(const char *id, GVariant *value);
 
-       bool have_required_channels() const;
+       void apply_all_options();
 
-       srd_decoder_inst* create_decoder_inst(srd_session *session) const;
+       bool have_required_channels() const;
 
-       set< shared_ptr<pv::data::Logic> > get_data();
+       srd_decoder_inst* create_decoder_inst(srd_session *session);
+       void invalidate_decoder_inst();
 
 private:
        const srd_decoder *const decoder_;
 
        bool shown_;
 
-       map<const srd_channel*, shared_ptr<pv::data::SignalBase> > channels_;
-       GArray *initial_pins_;
+       vector<data::DecodeChannel*> channels_;
        map<string, GVariant*> options_;
+       srd_decoder_inst *decoder_inst_;
 };
 
 } // namespace decode
index 1266b8436e1e09934b92418b62e5a6ebc42e7728..8195f3e2d00f023c0cdfb91f4b0464c8065d5eab 100644 (file)
@@ -31,7 +31,8 @@ Row::Row() :
 {
 }
 
-Row::Row(const srd_decoder *decoder, const srd_decoder_annotation_row *row) :
+Row::Row(int index, const srd_decoder *decoder, const srd_decoder_annotation_row *row) :
+       index_(index),
        decoder_(decoder),
        row_(row)
 {
@@ -60,6 +61,18 @@ const QString Row::title() const
        return QString();
 }
 
+const QString Row::class_name() const
+{
+       if (row_ && row_->desc)
+               return QString::fromUtf8(row_->desc);
+       return QString();
+}
+
+int Row::index() const
+{
+       return index_;
+}
+
 bool Row::operator<(const Row &other) const
 {
        return (decoder_ < other.decoder_) ||
index 5ddd10d3318fb2b0c9e0d399fa8b83915164d45f..34bb2373e844babd768335d4d8a335a227696b0c 100644 (file)
@@ -36,17 +36,20 @@ class Row
 public:
        Row();
 
-       Row(const srd_decoder *decoder,
+       Row(int index, const srd_decoder *decoder,
                const srd_decoder_annotation_row *row = nullptr);
 
        const srd_decoder* decoder() const;
        const srd_decoder_annotation_row* row() const;
 
        const QString title() const;
+       const QString class_name() const;
+       int index() const;
 
        bool operator<(const Row &other) const;
 
 private:
+       int index_;
        const srd_decoder *decoder_;
        const srd_decoder_annotation_row *row_;
 };
index 02859b2790a5b10f7979653ccc1ff41f8000e84c..2a26169eb6cc0f14adb5a107726c40ee891838b6 100644 (file)
@@ -42,9 +42,9 @@ void RowData::get_annotation_subset(
                        dest.push_back(annotation);
 }
 
-void RowData::push_annotation(const Annotation &a)
+void RowData::emplace_annotation(srd_proto_data *pdata, const Row *row)
 {
-       annotations_.push_back(a);
+       annotations_.emplace_back(pdata, row);
 }
 
 }  // namespace decode
index 3cb69b3ef1b5ad84ad95581c961c9a4f9694850f..0589ec894eb444fad4f2d0d759c98a1eabc13fc7 100644 (file)
@@ -22,6 +22,8 @@
 
 #include <vector>
 
+#include <libsigrokdecode/libsigrokdecode.h>
+
 #include "annotation.hpp"
 
 using std::vector;
@@ -30,6 +32,8 @@ namespace pv {
 namespace data {
 namespace decode {
 
+class Row;
+
 class RowData
 {
 public:
@@ -39,13 +43,15 @@ public:
        uint64_t get_max_sample() const;
 
        /**
-        * Extracts sorted annotations between two period into a vector.
+        * Extracts annotations between the given sample range into a vector.
+        * Note: The annotations are unsorted and only annotations that fully
+        * fit into the sample range are considered.
         */
        void get_annotation_subset(
                vector<pv::data::decode::Annotation> &dest,
                uint64_t start_sample, uint64_t end_sample) const;
 
-       void push_annotation(const Annotation &a);
+       void emplace_annotation(srd_proto_data *pdata, const Row *row);
 
 private:
        vector<Annotation> annotations_;
diff --git a/pv/data/decoderstack.cpp b/pv/data/decoderstack.cpp
deleted file mode 100644 (file)
index 1e1d600..0000000
+++ /dev/null
@@ -1,460 +0,0 @@
-/*
- * This file is part of the PulseView project.
- *
- * Copyright (C) 2012 Joel Holdsworth <joel@airwebreathe.org.uk>
- *
- * This program 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 2 of the License, or
- * (at your option) any later version.
- *
- * This program 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 this program; if not, see <http://www.gnu.org/licenses/>.
- */
-
-#include <libsigrokdecode/libsigrokdecode.h>
-
-#include <stdexcept>
-
-#include <QDebug>
-
-#include "decoderstack.hpp"
-
-#include <pv/data/decode/annotation.hpp>
-#include <pv/data/decode/decoder.hpp>
-#include <pv/data/logic.hpp>
-#include <pv/data/logicsegment.hpp>
-#include <pv/session.hpp>
-#include <pv/views/trace/logicsignal.hpp>
-
-using std::lock_guard;
-using std::mutex;
-using std::unique_lock;
-using std::deque;
-using std::make_pair;
-using std::max;
-using std::min;
-using std::list;
-using std::shared_ptr;
-using std::make_shared;
-using std::vector;
-
-using boost::optional;
-
-using namespace pv::data::decode;
-
-namespace pv {
-namespace data {
-
-const double DecoderStack::DecodeMargin = 1.0;
-const double DecoderStack::DecodeThreshold = 0.2;
-const int64_t DecoderStack::DecodeChunkLength = 10 * 1024 * 1024;
-const unsigned int DecoderStack::DecodeNotifyPeriod = 1024;
-
-mutex DecoderStack::global_srd_mutex_;
-
-DecoderStack::DecoderStack(pv::Session &session,
-       const srd_decoder *const dec) :
-       session_(session),
-       start_time_(0),
-       samplerate_(0),
-       sample_count_(0),
-       frame_complete_(false),
-       samples_decoded_(0)
-{
-       connect(&session_, SIGNAL(frame_began()),
-               this, SLOT(on_new_frame()));
-       connect(&session_, SIGNAL(data_received()),
-               this, SLOT(on_data_received()));
-       connect(&session_, SIGNAL(frame_ended()),
-               this, SLOT(on_frame_ended()));
-
-       stack_.push_back(make_shared<decode::Decoder>(dec));
-}
-
-DecoderStack::~DecoderStack()
-{
-       if (decode_thread_.joinable()) {
-               interrupt_ = true;
-               input_cond_.notify_one();
-               decode_thread_.join();
-       }
-}
-
-const list< shared_ptr<decode::Decoder> >& DecoderStack::stack() const
-{
-       return stack_;
-}
-
-void DecoderStack::push(shared_ptr<decode::Decoder> decoder)
-{
-       assert(decoder);
-       stack_.push_back(decoder);
-}
-
-void DecoderStack::remove(int index)
-{
-       assert(index >= 0);
-       assert(index < (int)stack_.size());
-
-       // Find the decoder in the stack
-       auto iter = stack_.begin();
-       for (int i = 0; i < index; i++, iter++)
-               assert(iter != stack_.end());
-
-       // Delete the element
-       stack_.erase(iter);
-}
-
-double DecoderStack::samplerate() const
-{
-       return samplerate_;
-}
-
-const pv::util::Timestamp& DecoderStack::start_time() const
-{
-       return start_time_;
-}
-
-int64_t DecoderStack::samples_decoded() const
-{
-       lock_guard<mutex> decode_lock(output_mutex_);
-       return samples_decoded_;
-}
-
-vector<Row> DecoderStack::get_visible_rows() const
-{
-       lock_guard<mutex> lock(output_mutex_);
-
-       vector<Row> rows;
-
-       for (const shared_ptr<decode::Decoder> &dec : stack_) {
-               assert(dec);
-               if (!dec->shown())
-                       continue;
-
-               const srd_decoder *const decc = dec->decoder();
-               assert(dec->decoder());
-
-               // Add a row for the decoder if it doesn't have a row list
-               if (!decc->annotation_rows)
-                       rows.emplace_back(decc);
-
-               // Add the decoder rows
-               for (const GSList *l = decc->annotation_rows; l; l = l->next) {
-                       const srd_decoder_annotation_row *const ann_row =
-                               (srd_decoder_annotation_row *)l->data;
-                       assert(ann_row);
-                       rows.emplace_back(decc, ann_row);
-               }
-       }
-
-       return rows;
-}
-
-void DecoderStack::get_annotation_subset(
-       vector<pv::data::decode::Annotation> &dest,
-       const Row &row, uint64_t start_sample,
-       uint64_t end_sample) const
-{
-       lock_guard<mutex> lock(output_mutex_);
-
-       const auto iter = rows_.find(row);
-       if (iter != rows_.end())
-               (*iter).second.get_annotation_subset(dest,
-                       start_sample, end_sample);
-}
-
-QString DecoderStack::error_message()
-{
-       lock_guard<mutex> lock(output_mutex_);
-       return error_message_;
-}
-
-void DecoderStack::clear()
-{
-       sample_count_ = 0;
-       frame_complete_ = false;
-       samples_decoded_ = 0;
-       error_message_ = QString();
-       rows_.clear();
-       class_rows_.clear();
-}
-
-void DecoderStack::begin_decode()
-{
-       if (decode_thread_.joinable()) {
-               interrupt_ = true;
-               input_cond_.notify_one();
-               decode_thread_.join();
-       }
-
-       clear();
-
-       // Check that all decoders have the required channels
-       for (const shared_ptr<decode::Decoder> &dec : stack_)
-               if (!dec->have_required_channels()) {
-                       error_message_ = tr("One or more required channels "
-                               "have not been specified");
-                       return;
-               }
-
-       // Add classes
-       for (const shared_ptr<decode::Decoder> &dec : stack_) {
-               assert(dec);
-               const srd_decoder *const decc = dec->decoder();
-               assert(dec->decoder());
-
-               // Add a row for the decoder if it doesn't have a row list
-               if (!decc->annotation_rows)
-                       rows_[Row(decc)] = decode::RowData();
-
-               // Add the decoder rows
-               for (const GSList *l = decc->annotation_rows; l; l = l->next) {
-                       const srd_decoder_annotation_row *const ann_row =
-                               (srd_decoder_annotation_row *)l->data;
-                       assert(ann_row);
-
-                       const Row row(decc, ann_row);
-
-                       // Add a new empty row data object
-                       rows_[row] = decode::RowData();
-
-                       // Map out all the classes
-                       for (const GSList *ll = ann_row->ann_classes;
-                               ll; ll = ll->next)
-                               class_rows_[make_pair(decc,
-                                       GPOINTER_TO_INT(ll->data))] = row;
-               }
-       }
-
-       // We get the logic data of the first channel in the list.
-       // This works because we are currently assuming all
-       // logic signals have the same data/segment
-       pv::data::SignalBase *signalbase;
-       pv::data::Logic *data = nullptr;
-
-       for (const shared_ptr<decode::Decoder> &dec : stack_)
-               if (dec && !dec->channels().empty() &&
-                       ((signalbase = (*dec->channels().begin()).second.get())) &&
-                       ((data = signalbase->logic_data().get())))
-                       break;
-
-       if (!data)
-               return;
-
-       // Check we have a segment of data
-       const deque< shared_ptr<pv::data::LogicSegment> > &segments =
-               data->logic_segments();
-       if (segments.empty())
-               return;
-       segment_ = segments.front();
-
-       // Get the samplerate and start time
-       start_time_ = segment_->start_time();
-       samplerate_ = segment_->samplerate();
-       if (samplerate_ == 0.0)
-               samplerate_ = 1.0;
-
-       interrupt_ = false;
-       decode_thread_ = std::thread(&DecoderStack::decode_proc, this);
-}
-
-uint64_t DecoderStack::max_sample_count() const
-{
-       uint64_t max_sample_count = 0;
-
-       for (const auto& row : rows_)
-               max_sample_count = max(max_sample_count,
-                       row.second.get_max_sample());
-
-       return max_sample_count;
-}
-
-optional<int64_t> DecoderStack::wait_for_data() const
-{
-       unique_lock<mutex> input_lock(input_mutex_);
-
-       // Do wait if we decoded all samples but we're still capturing
-       // Do not wait if we're done capturing
-       while (!interrupt_ && !frame_complete_ &&
-               (samples_decoded_ >= sample_count_) &&
-               (session_.get_capture_state() != Session::Stopped)) {
-
-               input_cond_.wait(input_lock);
-       }
-
-       // Return value is valid if we're not aborting the decode,
-       return boost::make_optional(!interrupt_ &&
-               // and there's more work to do...
-               (samples_decoded_ < sample_count_ || !frame_complete_) &&
-               // and if the end of the data hasn't been reached yet
-               (!((samples_decoded_ >= sample_count_) && (session_.get_capture_state() == Session::Stopped))),
-               sample_count_);
-}
-
-void DecoderStack::decode_data(
-       const int64_t abs_start_samplenum, const int64_t sample_count, const unsigned int unit_size,
-       srd_session *const session)
-{
-       const unsigned int chunk_sample_count =
-               DecodeChunkLength / segment_->unit_size();
-
-       for (int64_t i = abs_start_samplenum; !interrupt_ && i < sample_count;
-                       i += chunk_sample_count) {
-
-               const int64_t chunk_end = min(
-                       i + chunk_sample_count, sample_count);
-               const uint8_t* chunk = segment_->get_samples(i, chunk_end);
-
-               if (srd_session_send(session, i, chunk_end, chunk,
-                               (chunk_end - i) * unit_size, unit_size) != SRD_OK) {
-                       error_message_ = tr("Decoder reported an error");
-                       delete[] chunk;
-                       break;
-               }
-               delete[] chunk;
-
-               {
-                       lock_guard<mutex> lock(output_mutex_);
-                       samples_decoded_ = chunk_end;
-               }
-
-               if (i % DecodeNotifyPeriod == 0)
-                       new_decode_data();
-       }
-
-       new_decode_data();
-}
-
-void DecoderStack::decode_proc()
-{
-       optional<int64_t> sample_count;
-       srd_session *session;
-       srd_decoder_inst *prev_di = nullptr;
-
-       assert(segment_);
-
-       // Prevent any other decode threads from accessing libsigrokdecode
-       lock_guard<mutex> srd_lock(global_srd_mutex_);
-
-       // Create the session
-       srd_session_new(&session);
-       assert(session);
-
-       // Create the decoders
-       const unsigned int unit_size = segment_->unit_size();
-
-       for (const shared_ptr<decode::Decoder> &dec : stack_) {
-               srd_decoder_inst *const di = dec->create_decoder_inst(session);
-
-               if (!di) {
-                       error_message_ = tr("Failed to create decoder instance");
-                       srd_session_destroy(session);
-                       return;
-               }
-
-               if (prev_di)
-                       srd_inst_stack (session, prev_di, di);
-
-               prev_di = di;
-       }
-
-       // Get the intial sample count
-       {
-               unique_lock<mutex> input_lock(input_mutex_);
-               sample_count = sample_count_ = segment_->get_sample_count();
-       }
-
-       // Start the session
-       srd_session_metadata_set(session, SRD_CONF_SAMPLERATE,
-               g_variant_new_uint64((uint64_t)samplerate_));
-
-       srd_pd_output_callback_add(session, SRD_OUTPUT_ANN,
-               DecoderStack::annotation_callback, this);
-
-       srd_session_start(session);
-
-       int64_t abs_start_samplenum = 0;
-       do {
-               decode_data(abs_start_samplenum, *sample_count, unit_size, session);
-               abs_start_samplenum = *sample_count;
-       } while (error_message_.isEmpty() && (sample_count = wait_for_data()));
-
-       // Destroy the session
-       srd_session_destroy(session);
-}
-
-void DecoderStack::annotation_callback(srd_proto_data *pdata, void *decoder)
-{
-       assert(pdata);
-       assert(decoder);
-
-       DecoderStack *const d = (DecoderStack*)decoder;
-       assert(d);
-
-       lock_guard<mutex> lock(d->output_mutex_);
-
-       const Annotation a(pdata);
-
-       // Find the row
-       assert(pdata->pdo);
-       assert(pdata->pdo->di);
-       const srd_decoder *const decc = pdata->pdo->di->decoder;
-       assert(decc);
-
-       auto row_iter = d->rows_.end();
-
-       // Try looking up the sub-row of this class
-       const auto r = d->class_rows_.find(make_pair(decc, a.format()));
-       if (r != d->class_rows_.end())
-               row_iter = d->rows_.find((*r).second);
-       else {
-               // Failing that, use the decoder as a key
-               row_iter = d->rows_.find(Row(decc));
-       }
-
-       assert(row_iter != d->rows_.end());
-       if (row_iter == d->rows_.end()) {
-               qDebug() << "Unexpected annotation: decoder = " << decc <<
-                       ", format = " << a.format();
-               assert(false);
-               return;
-       }
-
-       // Add the annotation
-       (*row_iter).second.push_annotation(a);
-}
-
-void DecoderStack::on_new_frame()
-{
-       begin_decode();
-}
-
-void DecoderStack::on_data_received()
-{
-       {
-               unique_lock<mutex> lock(input_mutex_);
-               if (segment_)
-                       sample_count_ = segment_->get_sample_count();
-       }
-       input_cond_.notify_one();
-}
-
-void DecoderStack::on_frame_ended()
-{
-       {
-               unique_lock<mutex> lock(input_mutex_);
-               if (segment_)
-                       frame_complete_ = true;
-       }
-       input_cond_.notify_one();
-}
-
-} // namespace data
-} // namespace pv
diff --git a/pv/data/decoderstack.hpp b/pv/data/decoderstack.hpp
deleted file mode 100644 (file)
index 5216006..0000000
+++ /dev/null
@@ -1,183 +0,0 @@
-/*
- * This file is part of the PulseView project.
- *
- * Copyright (C) 2012 Joel Holdsworth <joel@airwebreathe.org.uk>
- *
- * This program 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 2 of the License, or
- * (at your option) any later version.
- *
- * This program 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 this program; if not, see <http://www.gnu.org/licenses/>.
- */
-
-#ifndef PULSEVIEW_PV_DATA_DECODERSTACK_HPP
-#define PULSEVIEW_PV_DATA_DECODERSTACK_HPP
-
-#include "signaldata.hpp"
-
-#include <atomic>
-#include <condition_variable>
-#include <list>
-#include <map>
-#include <memory>
-#include <thread>
-
-#include <boost/optional.hpp>
-
-#include <QObject>
-#include <QString>
-
-#include <pv/data/decode/row.hpp>
-#include <pv/data/decode/rowdata.hpp>
-#include <pv/util.hpp>
-
-using std::atomic;
-using std::condition_variable;
-using std::list;
-using std::map;
-using std::mutex;
-using std::pair;
-using std::shared_ptr;
-using std::vector;
-
-struct srd_decoder;
-struct srd_decoder_annotation_row;
-struct srd_channel;
-struct srd_proto_data;
-struct srd_session;
-
-namespace DecoderStackTest {
-struct TwoDecoderStack;
-}
-
-namespace pv {
-
-class Session;
-
-namespace view {
-class LogicSignal;
-}
-
-namespace data {
-
-class LogicSegment;
-
-namespace decode {
-class Annotation;
-class Decoder;
-}
-
-class Logic;
-
-class DecoderStack : public QObject
-{
-       Q_OBJECT
-
-private:
-       static const double DecodeMargin;
-       static const double DecodeThreshold;
-       static const int64_t DecodeChunkLength;
-       static const unsigned int DecodeNotifyPeriod;
-
-public:
-       DecoderStack(pv::Session &session, const srd_decoder *const dec);
-
-       virtual ~DecoderStack();
-
-       const list< shared_ptr<decode::Decoder> >& stack() const;
-       void push(shared_ptr<decode::Decoder> decoder);
-       void remove(int index);
-
-       double samplerate() const;
-
-       const pv::util::Timestamp& start_time() const;
-
-       int64_t samples_decoded() const;
-
-       vector<decode::Row> get_visible_rows() const;
-
-       /**
-        * Extracts sorted annotations between two period into a vector.
-        */
-       void get_annotation_subset(
-               vector<pv::data::decode::Annotation> &dest,
-               const decode::Row &row, uint64_t start_sample,
-               uint64_t end_sample) const;
-
-       QString error_message();
-
-       void clear();
-
-       uint64_t max_sample_count() const;
-
-       void begin_decode();
-
-private:
-       boost::optional<int64_t> wait_for_data() const;
-
-       void decode_data(const int64_t abs_start_samplenum, const int64_t sample_count,
-               const unsigned int unit_size, srd_session *const session);
-
-       void decode_proc();
-
-       static void annotation_callback(srd_proto_data *pdata, void *decoder);
-
-private Q_SLOTS:
-       void on_new_frame();
-
-       void on_data_received();
-
-       void on_frame_ended();
-
-Q_SIGNALS:
-       void new_decode_data();
-
-private:
-       pv::Session &session_;
-
-       pv::util::Timestamp start_time_;
-       double samplerate_;
-
-       /**
-        * This mutex prevents more than one thread from accessing
-        * libsigrokdecode concurrently.
-        * @todo A proper solution should be implemented to allow multiple
-        * decode operations in parallel.
-        */
-       static mutex global_srd_mutex_;
-
-       list< shared_ptr<decode::Decoder> > stack_;
-
-       shared_ptr<pv::data::LogicSegment> segment_;
-
-       mutable mutex input_mutex_;
-       mutable condition_variable input_cond_;
-       int64_t sample_count_;
-       bool frame_complete_;
-
-       mutable mutex output_mutex_;
-       int64_t samples_decoded_;
-
-       map<const decode::Row, decode::RowData> rows_;
-
-       map<pair<const srd_decoder*, int>, decode::Row> class_rows_;
-
-       QString error_message_;
-
-       std::thread decode_thread_;
-       atomic<bool> interrupt_;
-
-       friend struct DecoderStackTest::TwoDecoderStack;
-};
-
-} // namespace data
-} // namespace pv
-
-#endif // PULSEVIEW_PV_DATA_DECODERSTACK_HPP
diff --git a/pv/data/decodesignal.cpp b/pv/data/decodesignal.cpp
new file mode 100644 (file)
index 0000000..68b17a6
--- /dev/null
@@ -0,0 +1,1317 @@
+/*
+ * This file is part of the PulseView project.
+ *
+ * Copyright (C) 2017 Soeren Apel <soeren@apelpie.net>
+ *
+ * This program 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 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <forward_list>
+#include <limits>
+
+#include <QDebug>
+
+#include "logic.hpp"
+#include "logicsegment.hpp"
+#include "decodesignal.hpp"
+#include "signaldata.hpp"
+
+#include <pv/binding/decoder.hpp>
+#include <pv/data/decode/decoder.hpp>
+#include <pv/data/decode/row.hpp>
+#include <pv/globalsettings.hpp>
+#include <pv/session.hpp>
+
+using std::forward_list;
+using std::lock_guard;
+using std::make_pair;
+using std::make_shared;
+using std::min;
+using std::out_of_range;
+using std::shared_ptr;
+using std::unique_lock;
+using pv::data::decode::Annotation;
+using pv::data::decode::Decoder;
+using pv::data::decode::Row;
+
+namespace pv {
+namespace data {
+
+const double DecodeSignal::DecodeMargin = 1.0;
+const double DecodeSignal::DecodeThreshold = 0.2;
+const int64_t DecodeSignal::DecodeChunkLength = 256 * 1024;
+
+
+DecodeSignal::DecodeSignal(pv::Session &session) :
+       SignalBase(nullptr, SignalBase::DecodeChannel),
+       session_(session),
+       srd_session_(nullptr),
+       logic_mux_data_invalid_(false),
+       stack_config_changed_(true),
+       current_segment_id_(0)
+{
+       connect(&session_, SIGNAL(capture_state_changed(int)),
+               this, SLOT(on_capture_state_changed(int)));
+}
+
+DecodeSignal::~DecodeSignal()
+{
+       reset_decode(true);
+}
+
+const vector< shared_ptr<Decoder> >& DecodeSignal::decoder_stack() const
+{
+       return stack_;
+}
+
+void DecodeSignal::stack_decoder(const srd_decoder *decoder)
+{
+       assert(decoder);
+       const shared_ptr<Decoder> dec = make_shared<decode::Decoder>(decoder);
+
+       stack_.push_back(dec);
+
+       // Set name if this decoder is the first in the list
+       if (stack_.size() == 1)
+               set_name(QString::fromUtf8(decoder->name));
+
+       // Include the newly created decode channels in the channel lists
+       update_channel_list();
+
+       stack_config_changed_ = true;
+       auto_assign_signals(dec);
+       commit_decoder_channels();
+       begin_decode();
+}
+
+void DecodeSignal::remove_decoder(int index)
+{
+       assert(index >= 0);
+       assert(index < (int)stack_.size());
+
+       // Find the decoder in the stack
+       auto iter = stack_.begin();
+       for (int i = 0; i < index; i++, iter++)
+               assert(iter != stack_.end());
+
+       // Delete the element
+       stack_.erase(iter);
+
+       // Update channels and decoded data
+       stack_config_changed_ = true;
+       update_channel_list();
+       begin_decode();
+}
+
+bool DecodeSignal::toggle_decoder_visibility(int index)
+{
+       auto iter = stack_.cbegin();
+       for (int i = 0; i < index; i++, iter++)
+               assert(iter != stack_.end());
+
+       shared_ptr<Decoder> dec = *iter;
+
+       // Toggle decoder visibility
+       bool state = false;
+       if (dec) {
+               state = !dec->shown();
+               dec->show(state);
+       }
+
+       return state;
+}
+
+void DecodeSignal::reset_decode(bool shutting_down)
+{
+       if (stack_config_changed_ || shutting_down)
+               stop_srd_session();
+       else
+               terminate_srd_session();
+
+       if (decode_thread_.joinable()) {
+               decode_interrupt_ = true;
+               decode_input_cond_.notify_one();
+               decode_thread_.join();
+       }
+
+       if (logic_mux_thread_.joinable()) {
+               logic_mux_interrupt_ = true;
+               logic_mux_cond_.notify_one();
+               logic_mux_thread_.join();
+       }
+
+       resume_decode();  // Make sure the decode thread isn't blocked by pausing
+
+       class_rows_.clear();
+       current_segment_id_ = 0;
+       segments_.clear();
+
+       logic_mux_data_.reset();
+       logic_mux_data_invalid_ = true;
+
+       if (!error_message_.isEmpty()) {
+               error_message_ = QString();
+               // TODO Emulate noquote()
+               qDebug().nospace() << name() << ": Error cleared";
+       }
+
+       decode_reset();
+}
+
+void DecodeSignal::begin_decode()
+{
+       if (decode_thread_.joinable()) {
+               decode_interrupt_ = true;
+               decode_input_cond_.notify_one();
+               decode_thread_.join();
+       }
+
+       if (logic_mux_thread_.joinable()) {
+               logic_mux_interrupt_ = true;
+               logic_mux_cond_.notify_one();
+               logic_mux_thread_.join();
+       }
+
+       reset_decode();
+
+       if (stack_.size() == 0) {
+               set_error_message(tr("No decoders"));
+               return;
+       }
+
+       assert(channels_.size() > 0);
+
+       if (get_assigned_signal_count() == 0) {
+               set_error_message(tr("There are no channels assigned to this decoder"));
+               return;
+       }
+
+       // Make sure that all assigned channels still provide logic data
+       // (can happen when a converted signal was assigned but the
+       // conversion removed in the meanwhile)
+       for (data::DecodeChannel& ch : channels_)
+               if (ch.assigned_signal && !(ch.assigned_signal->logic_data() != nullptr))
+                       ch.assigned_signal = nullptr;
+
+       // Check that all decoders have the required channels
+       for (const shared_ptr<decode::Decoder>& dec : stack_)
+               if (!dec->have_required_channels()) {
+                       set_error_message(tr("One or more required channels "
+                               "have not been specified"));
+                       return;
+               }
+
+       // Map out all the annotation classes
+       int row_index = 0;
+       for (const shared_ptr<decode::Decoder>& dec : stack_) {
+               assert(dec);
+               const srd_decoder *const decc = dec->decoder();
+               assert(dec->decoder());
+
+               for (const GSList *l = decc->annotation_rows; l; l = l->next) {
+                       const srd_decoder_annotation_row *const ann_row =
+                               (srd_decoder_annotation_row *)l->data;
+                       assert(ann_row);
+
+                       const Row row(row_index++, decc, ann_row);
+
+                       for (const GSList *ll = ann_row->ann_classes;
+                               ll; ll = ll->next)
+                               class_rows_[make_pair(decc,
+                                       GPOINTER_TO_INT(ll->data))] = row;
+               }
+       }
+
+       // Free the logic data and its segment(s) if it needs to be updated
+       if (logic_mux_data_invalid_)
+               logic_mux_data_.reset();
+
+       if (!logic_mux_data_) {
+               const uint32_t ch_count = get_assigned_signal_count();
+               logic_mux_unit_size_ = (ch_count + 7) / 8;
+               logic_mux_data_ = make_shared<Logic>(ch_count);
+       }
+
+       // Receive notifications when new sample data is available
+       connect_input_notifiers();
+
+       if (get_input_segment_count() == 0) {
+               set_error_message(tr("No input data"));
+               return;
+       }
+
+       // Make sure the logic output data is complete and up-to-date
+       logic_mux_interrupt_ = false;
+       logic_mux_thread_ = std::thread(&DecodeSignal::logic_mux_proc, this);
+
+       // Decode the muxed logic data
+       decode_interrupt_ = false;
+       decode_thread_ = std::thread(&DecodeSignal::decode_proc, this);
+}
+
+void DecodeSignal::pause_decode()
+{
+       decode_paused_ = true;
+}
+
+void DecodeSignal::resume_decode()
+{
+       // Manual unlocking is done before notifying, to avoid waking up the
+       // waiting thread only to block again (see notify_one for details)
+       decode_pause_mutex_.unlock();
+       decode_pause_cond_.notify_one();
+       decode_paused_ = false;
+}
+
+bool DecodeSignal::is_paused() const
+{
+       return decode_paused_;
+}
+
+QString DecodeSignal::error_message() const
+{
+       lock_guard<mutex> lock(output_mutex_);
+       return error_message_;
+}
+
+const vector<data::DecodeChannel> DecodeSignal::get_channels() const
+{
+       return channels_;
+}
+
+void DecodeSignal::auto_assign_signals(const shared_ptr<Decoder> dec)
+{
+       bool new_assignment = false;
+
+       // Try to auto-select channels that don't have signals assigned yet
+       for (data::DecodeChannel& ch : channels_) {
+               // If a decoder is given, auto-assign only its channels
+               if (dec && (ch.decoder_ != dec))
+                       continue;
+
+               if (ch.assigned_signal)
+                       continue;
+
+               QString ch_name = ch.name.toLower();
+               ch_name = ch_name.replace(QRegExp("[-_.]"), " ");
+
+               shared_ptr<data::SignalBase> match;
+               for (const shared_ptr<data::SignalBase>& s : session_.signalbases()) {
+                       if (!s->enabled())
+                               continue;
+
+                       QString s_name = s->name().toLower();
+                       s_name = s_name.replace(QRegExp("[-_.]"), " ");
+
+                       if (s->logic_data() &&
+                               ((ch_name.contains(s_name)) || (s_name.contains(ch_name)))) {
+                               if (!match)
+                                       match = s;
+                               else {
+                                       // Only replace an existing match if it matches more characters
+                                       int old_unmatched = ch_name.length() - match->name().length();
+                                       int new_unmatched = ch_name.length() - s->name().length();
+                                       if (abs(new_unmatched) < abs(old_unmatched))
+                                               match = s;
+                               }
+                       }
+               }
+
+               if (match) {
+                       ch.assigned_signal = match.get();
+                       new_assignment = true;
+               }
+       }
+
+       if (new_assignment) {
+               logic_mux_data_invalid_ = tru