This article outlines the internal architecture of PulseView.
The folder structure of the PulseView source corresponds to the C++ namespaces.
Everything is owned by pv::MainWindow. This owns a pv::Session.
The pv::Session object is responsible for acquisition and owns the captured data. For acquisition, pv::Session is basically a wrapper around a libsigrok session, with PulseView specific datafeed callbacks. The captured data is stored in "data objects": pv::data::Logic and pv::data::Analog owned by pv::Session. Each of these is a stack of sampled snapshots: pv::data::LogicSnapshot, pv::data::AnalogSnapshot. In the future this stacking will be used for digital phosphor/persistence.
(The name for pv::data::LogicSnapshot and pv::data::AnalogSnapshot may change in the future as they might be better named frame to correspond with the libsigrok terminology).
These Snapshot objects store a big binary array of the raw data of a single contiguous capture of sampled data for one or more channels. They also contain data and algorithms for indexing the signal in such a way that it can be drawn quickly at any level of detail.
pv::Session also contains list of pv::view::Signal objects. Each Signal object represents an input channel on the device, and it contains the channel number and the object that it is associated with. So for example in the case of pv::view::LogicSignal, this Signal object will know the bit index of the data within the binary array of a pv::data::LogicSnapshot.
The Signal objects: pv::view::LogicSignal and pv::view::AnalogSignal (derived from pv::view::Signal) are actually view objects. So they know about the data, but they can also draw the trace, and header label, etc. for the View. They rather bridge the boundary of the Model/View divide.
The pv::MainWindow also owns a pv::view::View, this is the whole body of the GUI containing everything in the window that's not a menubar or toolbar. The ruler, the signals header, and the viewport are all widgets owned by pv::view::View. All the component classes of pv::view::View are stored in the pv::view namespace.
The View builds around that pv::Session. With the pv::view::Signal objects implementing the mapping of data to traces.
The pv::prop namespace contains a simple framework that can reused to generate GUIs for the sr_config properties, and in future decoder properties. This is used for building the device config windows and may in future be integrated into toolbars.
The pv::prop namespace itself contains semantic objects that represent different types of data: Bool, Double, Int, Enum etc. The object can generate Qt widgets of themselves, and are able to read and write configurations, using flexible boost function callbacks. The pv::prop::binding namespace contains classes which expose the properties of an interface such as the sr_config interface. These classes can also contain shim code that can understand special cases of the configuration, for example that SR_SAMPLERATE_CONF can be either a free value or a member of a list of values.