<page>
    <title>QT GUI</title>
    <ns>0</ns>
    <id>3486</id>
    <revision>
      <id>4190</id>
      <parentid>4189</parentid>
      <timestamp>2018-05-15T19:45:25Z</timestamp>
      <contributor>
        <username>777arc</username>
        <id>632</id>
      </contributor>
      <comment>/* C++ and Message-Passing Widgets */</comment>
      <model>wikitext</model>
      <format>text/x-wiki</format>
      <text xml:space="preserve" bytes="12387">== Introduction ==

This is the gr-qtgui package. It contains various QT-based graphical
user interface blocks that add graphical sinks to a GNU Radio
flowgraph. The Python namespaces is in gnuradio.qtgui, which would be normally
imported as:

    from gnuradio import qtgui

See the Doxygen documentation for details about the blocks available
in this package. The relevant blocks are listed [https://gnuradio.org/doc/doxygen/group__qtgui__blk.html here].

A quick listing of the details can be found in Python after importing
by using:

    help(qtgui)

=== Blocks ===

There are a number of available QTGUI blocks for different plotting
purposes. These include:

# Time Domain (gr::qtgui::time_sink_c and gr::qtgui::time_sink_f): x-axis is time, y-axis is amplitude.
# Frequency Domain or PSD (gr::qtgui::freq_sink_c and gr::qtgui::freq_sink_f): x-axis is frequency, y-axis is magnitude in dB.
# Waterfall or spectrogram (gr::qtgui::waterfall_sink_c and gr::qtgui::waterfall_sink_f): x-axis is frequency, y-axis is time,z-axis is intensity related to magnitude in dB.
# Constellation (gr::qtgui::const_sink_c): polar plot of real vs. imaginary.
# Time Raster (gr::qtgui::time_raster_sink_f and gr::qtgui::time_raster_sink_b): time vs. time with the z-axis being intensity basedon value of the sample.
# Histogram (gr::qtgui::histogram_sink_f): Displays a histogram of the data stream.
# Combined Sink (gr::qtgui::sink_c and gr::qtgui::sink_f): combines time, frequency, waterfall, and constellation plots into one widget.

The time domain, frequency domain, and waterfall have both a complex
and a floating point block. The constellation plot only makes sense
with complex inputs. The time raster plots accept bits and floats.

Because the time raster plots are designed to show structure over time
in a signal, frame, packet, etc., they never drop samples. This is a
fairly taxing job and performance can be an issue. Since it is
expected that this block will work on a frame or packet structure, we
tend to be at the lowest possible rate at this point, so that will
help. Expect performance issues at high data rates.

Note: There seem to be extra performance issues with the raster
plotters in QWT version 5 that were fixed with QWT version 6. As such,
the time raster plots have incredibly poor performance with QWT5 to
the point of almost being unusable. In the future, we may restrict
compilation and installation of these plots only if QWT6 or higher is
discovered. For now, just be aware of this limitation.

== Drop-Down Menu and Interacting with Plots ==

All QTGUI sinks have interactive capabilities.

# Zooming is done simply by clicking the left mouse button and dragging a rectangle around the area to zoom.
# Zooming can be done in multiple steps.
# A right mouse click will zoom out one step.
# Ctrl+Right mouse click will zoom all the way out.
# Ctrl+Middle mouse click and hold can drag the canvas around.
# Mouse wheel up/down will zoom out/in on y axis (both axes in constellation plot).
# Middle mouse button brings up a context menu.

Each type of graph has a different set of menu items in the context
menu. Most have some way to change the appearance of the lines or
surfaces, such as changing the line width color, marker, and
transparency. Other common features can set the sampling rate, turn a
grid on and off, pause and unpause (stop/start) the display update, and
save the current figure. Specific features are things like setting the
number of points to display, setting the FFT size, FFT window, and any
FFT averaging.

=== Triggering Menu for Time Plots ===

The time plots have triggering capabilities. Triggering can happen
when the signal of a specific channel crosses (positive or negative
slope) a certain level threshold. Or triggering can be done off a
specific stream tag such that whenever a tag of a given key is found,
the scope will trigger.

In the signal level mode, the trigger can be either 'auto' or 'normal'
where the latter will only trigger when the event is seen. The 'auto'
mode will trigger on the event or every so often even if no trigger is
found. The 'free' mode ignores triggering and continuously
plots.

By default, the triggers plot the triggering event at the x=0 (i.e.,
the left-most point in the plot). A delay can be set to delay the
signal along the x-axis to observe any signal before the triggering
event. The delay feature works the same for both level and tag
triggers. The delay is set according to time in seconds, not
samples. So the delay can be calculated as the number of samples
divided by the sample rate given to the block.

All trigger settings (mode, slope, level, delay, channel, and tag key)
are settable in the GRC properties boxes to easily set up a repeatable
environment.

A note on the trigger delay setting. This value is limited by the
buffer size and/or the number of points being display. It is capped by
the minimum of these two values. The buffer size issue is generally
only a problem when plotting a large number of samples. However, if
the delay is set large to begin with (in the GRC properties box or
before top_block.start() is called), then the buffers are resized
accordingly offering more freedom. This should be a problem in a
limited number of scenarios, but a log INFO level message is produced
when asking for the delay outside of the available range.

== Dependencies ==

The QT GUI blocks require the following dependencies.

# QtCore (version >= 4.4)
# QtGui (version >= 4.4)
# QtOpenGL (version >= 4.4)
# PyQt4 for Qt4 (version >= 4.4)
# Qwt (version >= 5.2)

== Usage ==

To use the QTGUI interface, a bit of boiler-plate lines must be
included. First, the sink is defined, then it must be exposed from C++
into Python using the "sip.wrapinstance" command, and finally, the
"show" method is run on the new Python object. This sets up the QT
environment to show the widget, but the qApplication must also be
launched.

In the "main" function of the code, the qApp is retrieved. Then, after
the GNU Radio top block is started (remember that start() is a
non-blocking call to launch the main thread of the flowgraph), the
qapp's "exec_()" function is called. This function is a blocking call
while the GUI is alive.

from PyQt4 import Qt
from gnuradio import qtgui
import sys, sip
 
 class grclass(gr.top_block):
     ....
  
     self.snk = qtgui.sink_c(1024,           #fftsize
                             samp_rate,      #bw
                             "QT GUI Plot")  #name
 
     self.snk_win = sip.wrapinstance(self.snk.pyqwidget(), Qt.QWidget)
     self.snk_win.show()
 
 def main():
     qapp = Qt.QApplication(sys.argv)
     tb = grclass()
     tb.start()
     qapp.exec_()
     tb.stop()

There are graphical controls in all but the combined plotting
tools. In the margins of the GUIs (that is, not on the canvas showing
the signal itself), right-clicking the mouse will pull up a drop-down
menu that will allow you to change difference parameters of the
plots. These include things like the look of the lines (width, color,
style, markers, etc.), the ability to start and stop the display, the
ability to save to a file, and other plot-specific controls (FFT size
for the frequency and waterfall plots, etc.).

== Message Input Support ==

All QTGUI sinks can accept and plot messages over their "in" message
port. The message types must either be uniform vectors or PDUs. The
data type held within the uniform vector or PDU must match the data
type of the block itself. For example, a qtgui.time_sink_c will only
handle vectors that pass the pmt::is_c32vector test while a
qtgui.time_sink_f will only handle vectors that pass the
pmt::is_f32vector test.

The sinks must only be used with one type of input model: streaming or
messages. You cannot use them both together or unknown behavior will
occur.

In the GNU Radio Companion, the QTGUI sink blocks can be set to
message mode by changing the Type field. Most of the QTGUI sinks
support multiple data types, even for messages, but GRC only displays
the message type as the single gray color. Within the block's property
box, you can set the type to handle the correct message data type
(e.g., 'Complex Message' or 'Float Message'). When using a message
type interface, GRC will hide certain parameters that are not usable
or settable anymore. For example, when plotting a message in the time
sink, the number of points shown in the time sink is determined by the
length of the vector in the message. Presetting this in the GUI would
have no effect. 
This behavior in GRC is for convenience and to try and reduce confusion
about properties and settings in the message mode. However, all of the
API hooks are still there, so it is possible to set all of this
programmatically. The results would be harmless, however.

Here is an example of setting up and using a message passing complex
time sink block:

 from gnuradio import gr, qtgui
 
 tsnk = qtgui.time_sink_c(1024, samp_rate, "", 0)
 tsnk.set_update_time(0.05)
 tsnk.set_y_axis(-1.25, 1.25)
 tsnk.set_y_label("Amp (V)", "")
 tsnk.enable_autoscale(False)
 tsnk.enable_grid(False)
 tsnk.enable_control_panel(False)
 
 tb = gr.top_block()
 msg_block = ? # some PDU/message generating block
 tb.msg_connect((msg_block, 'msg'), (tsnk, 'in'))

== QTGUI Widgets ==

The QTGUI component also includes a number of widgets that can be used
to perform live updates of variables through standard QT input
widgets. Most of the widgets are implemented directly in Python
through PyQT. However, GNU Radio is introducing more widgets, written
and therefore available in C++ that also produce messages. The
Python-based widgets only act as variables and so as they are changed,
any block using those widgets to set parameters has the callback (i.e.,
set_value()) function's called.

=== Python widgets: ===

# Range: creates a slider and/or combo box to change to set/change the value of a parameter. This widget can set either float or int values.
# Entry: An edit box that allows a user to directly set a new value for the parameter.
# Chooser: Creates a drop-down menu of pre-set values.
# Check Box: Creates a check box. The user sets what the value of the check means when enabled or disabled.
# Push Button: Adds a button that changes state when pushed versus released (no sticky). The user sets up what the value is when pressed versus when released.
# Label: Adds a Label widget to annotate the GUI. Generally not used as a variable.
# Tab Widget: Adds a tab widget that can house other GUI widgets to format the interface. Use the GUI hint of the other QT widgets and instruments to specify if and where they exist in the tab widget using the format "tag widget name@index: row, col, row span, col span". Simply using "tab widget name@index" will put that widget into the specific index (starting at 0) of the tab widget while adding the "row, col, row span, col span" will allow the user to place them in the tab grid.

=== C++ and Message-Passing Widgets ===

The [https://gnuradio.org/doc/doxygen/classgr_1_1qtgui_1_1edit__box__msg.html Message Edit Box] is a QT edit box
that emits a message when editing is done (e.g., user presses enter,
tabs out of the widget, or mouse-clicks out of the widget). The
message type is settable as are the contents. Messages can be sent as
key:value pairs when Pair Mode is enabled. When Static Mode is
enabled, the data type and the pair key (if in Pair Mode) are set at
the start and cannot be changed at runtime.

== Configuration ==

There is currently a single configuration option in the preferences
files to set the rendering engine of the QTGUI sinks. Located in
etc/gnuradio/conf.d/gr-qtgui.conf:

 [qtgui]
 style = raster

The available styles are:

# opengl: the fastest but not likely to always work
# raster: fast and stable; terrible X forwarding performance
# native: most compute intensive; very good over X

We default this setting to raster for the mix of performance and
usability. When using QTGUI sinks through an X-forwarding session over
SSH, switch to using 'native' for a significant speed boost on the
remote end.

We can also set a QT Style Sheet (QSS) file to adjust the look of our
plotting tools. Set the 'qss' option of the 'qtgui' section in our
configuration file to a QSS file. An example QSS file is distributed
with the QTGUI examples found in
share/gnuradio/examples/qt-gui/dark.qss.</text>
      <sha1>6p0evs1odganpw5pf993ifhtdncao90</sha1>
    </revision>
  </page>
</mediawiki>