From f6cd539f7c9f0791048fb0773b5850e590e577de Mon Sep 17 00:00:00 2001
From: Tom Vierjahn <vierjahn@vr.rwth-aachen.de>
Date: Sat, 22 Oct 2016 19:11:50 -0400
Subject: [PATCH] pvt.16.10.0

---
 CMakeLists.txt                                |   1 +
 README.md                                     |  18 ++-
 pv_app/CMakeLists.txt                         |   6 +-
 pv_app/src/_SourceFiles.cmake                 |  41 -----
 pv_app/src/application.cpp                    |  21 +--
 pv_app/src/application.hpp                    |  19 +--
 pvt/_SourceFiles.cmake                        |   2 +
 .../rendering/renderable_cartesian_grid.hpp   | 103 ++++++++++++
 pvt/include/pvt/rendering/shader_strings.hpp  |   2 +
 ...ata_file_native_system_geometry_loader.cpp |   1 -
 .../rendering/renderable_cartesian_grid.cpp   | 146 ++++++++++++++++++
 pvt/src/rendering/shader_strings.cpp          |  34 +++-
 qpvt/CMakeLists.txt                           | 119 ++++++++++++++
 qpvt/_SourceFiles.cmake                       |  77 +++++++++
 qpvt/include/qpvt/api.hpp                     |  47 ++++++
 .../directed_variation_glyph_delegate.hpp     |  14 +-
 .../delegates}/severity_glyph_delegate.hpp    |  14 +-
 .../qpvt/models}/cnode_impact_list_model.hpp  |  14 +-
 .../include/qpvt/models}/cnode_tree_model.hpp |  15 +-
 .../qpvt/models}/correlated_views_model.hpp   |  14 +-
 .../qpvt/models}/metric_tree_model.hpp        |  15 +-
 .../qpvt/models}/perf_data_tree_model.hpp     |  14 +-
 .../include/qpvt/utility}/camera_tools.hpp    |  14 +-
 .../cartesian_topology_viewer_widget.hpp      |  13 +-
 .../widgets}/cnode_impact_selector_widget.hpp |  16 +-
 .../qpvt/widgets}/data_range_h_slider.hpp     |  15 +-
 .../qpvt/widgets}/data_range_v_slider.hpp     |  15 +-
 .../qpvt/widgets}/geometry_viewer_widget.hpp  |  18 +--
 .../parallel_coordinates_plot_widget.hpp      |  15 +-
 .../qpvt/widgets}/perf_data_viewer_widget.hpp |  21 +--
 .../include/qpvt/widgets}/range_h_slider.hpp  |  15 +-
 .../include/qpvt/widgets}/range_slider.hpp    |  16 +-
 .../include/qpvt/widgets}/range_v_slider.hpp  |  15 +-
 .../include/qpvt/widgets}/slice_slider.hpp    |  14 +-
 .../squarified_cushion_treemap_widget.hpp     |  14 +-
 .../include/qpvt/widgets}/viewer_widget.hpp   |  15 +-
 .../directed_variation_glyph_delegate.cpp     |   8 +-
 .../delegates}/severity_glyph_delegate.cpp    |   8 +-
 .../src/models}/cnode_impact_list_model.cpp   |   6 +-
 .../src/models}/cnode_tree_model.cpp          |   6 +-
 .../src/models}/correlated_views_model.cpp    |   6 +-
 .../src/models}/metric_tree_model.cpp         |   6 +-
 .../src => qpvt/src/utility}/camera_tools.cpp |   6 +-
 .../cartesian_topology_viewer_widget.cpp      |  24 ++-
 .../widgets}/cnode_impact_selector_widget.cpp |  10 +-
 .../src/widgets}/data_range_h_slider.cpp      |   6 +-
 .../src/widgets}/data_range_v_slider.cpp      |   6 +-
 .../src/widgets}/geometry_viewer_widget.cpp   |   9 +-
 .../parallel_coordinates_plot_widget.cpp      |   8 +-
 .../src/widgets}/perf_data_viewer_widget.cpp  |  18 +--
 .../src/widgets}/range_h_slider.cpp           |   6 +-
 .../src => qpvt/src/widgets}/range_slider.cpp |   6 +-
 .../src/widgets}/range_v_slider.cpp           |   6 +-
 .../src => qpvt/src/widgets}/slice_slider.cpp |   8 +-
 .../squarified_cushion_treemap_widget.cpp     |   6 +-
 .../src/widgets}/viewer_widget.cpp            |   6 +-
 56 files changed, 836 insertions(+), 282 deletions(-)
 create mode 100644 pvt/include/pvt/rendering/renderable_cartesian_grid.hpp
 create mode 100644 pvt/src/rendering/renderable_cartesian_grid.cpp
 create mode 100644 qpvt/CMakeLists.txt
 create mode 100644 qpvt/_SourceFiles.cmake
 create mode 100644 qpvt/include/qpvt/api.hpp
 rename {pv_app/src => qpvt/include/qpvt/delegates}/directed_variation_glyph_delegate.hpp (86%)
 rename {pv_app/src => qpvt/include/qpvt/delegates}/severity_glyph_delegate.hpp (86%)
 rename {pv_app/src => qpvt/include/qpvt/models}/cnode_impact_list_model.hpp (92%)
 rename {pv_app/src => qpvt/include/qpvt/models}/cnode_tree_model.hpp (87%)
 rename {pv_app/src => qpvt/include/qpvt/models}/correlated_views_model.hpp (90%)
 rename {pv_app/src => qpvt/include/qpvt/models}/metric_tree_model.hpp (84%)
 rename {pv_app/src => qpvt/include/qpvt/models}/perf_data_tree_model.hpp (96%)
 rename {pv_app/src => qpvt/include/qpvt/utility}/camera_tools.hpp (93%)
 rename {pv_app/src => qpvt/include/qpvt/widgets}/cartesian_topology_viewer_widget.hpp (96%)
 rename {pv_app/src => qpvt/include/qpvt/widgets}/cnode_impact_selector_widget.hpp (91%)
 rename {pv_app/src => qpvt/include/qpvt/widgets}/data_range_h_slider.hpp (92%)
 rename {pv_app/src => qpvt/include/qpvt/widgets}/data_range_v_slider.hpp (90%)
 rename {pv_app/src => qpvt/include/qpvt/widgets}/geometry_viewer_widget.hpp (90%)
 rename {pv_app/src => qpvt/include/qpvt/widgets}/parallel_coordinates_plot_widget.hpp (90%)
 rename {pv_app/src => qpvt/include/qpvt/widgets}/perf_data_viewer_widget.hpp (92%)
 rename {pv_app/src => qpvt/include/qpvt/widgets}/range_h_slider.hpp (86%)
 rename {pv_app/src => qpvt/include/qpvt/widgets}/range_slider.hpp (95%)
 rename {pv_app/src => qpvt/include/qpvt/widgets}/range_v_slider.hpp (87%)
 rename {pv_app/src => qpvt/include/qpvt/widgets}/slice_slider.hpp (93%)
 rename {pv_app/src => qpvt/include/qpvt/widgets}/squarified_cushion_treemap_widget.hpp (91%)
 rename {pv_app/src => qpvt/include/qpvt/widgets}/viewer_widget.hpp (90%)
 rename {pv_app/src => qpvt/src/delegates}/directed_variation_glyph_delegate.cpp (96%)
 rename {pv_app/src => qpvt/src/delegates}/severity_glyph_delegate.cpp (95%)
 rename {pv_app/src => qpvt/src/models}/cnode_impact_list_model.cpp (99%)
 rename {pv_app/src => qpvt/src/models}/cnode_tree_model.cpp (98%)
 rename {pv_app/src => qpvt/src/models}/correlated_views_model.cpp (97%)
 rename {pv_app/src => qpvt/src/models}/metric_tree_model.cpp (97%)
 rename {pv_app/src => qpvt/src/utility}/camera_tools.cpp (98%)
 rename {pv_app/src => qpvt/src/widgets}/cartesian_topology_viewer_widget.cpp (97%)
 rename {pv_app/src => qpvt/src/widgets}/cnode_impact_selector_widget.cpp (98%)
 rename {pv_app/src => qpvt/src/widgets}/data_range_h_slider.cpp (99%)
 rename {pv_app/src => qpvt/src/widgets}/data_range_v_slider.cpp (98%)
 rename {pv_app/src => qpvt/src/widgets}/geometry_viewer_widget.cpp (98%)
 rename {pv_app/src => qpvt/src/widgets}/parallel_coordinates_plot_widget.cpp (98%)
 rename {pv_app/src => qpvt/src/widgets}/perf_data_viewer_widget.cpp (98%)
 rename {pv_app/src => qpvt/src/widgets}/range_h_slider.cpp (97%)
 rename {pv_app/src => qpvt/src/widgets}/range_slider.cpp (98%)
 rename {pv_app/src => qpvt/src/widgets}/range_v_slider.cpp (98%)
 rename {pv_app/src => qpvt/src/widgets}/slice_slider.cpp (97%)
 rename {pv_app/src => qpvt/src/widgets}/squarified_cushion_treemap_widget.cpp (98%)
 rename {pv_app/src => qpvt/src/widgets}/viewer_widget.cpp (98%)

diff --git a/CMakeLists.txt b/CMakeLists.txt
index 581558a..85f23b7 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -30,4 +30,5 @@ set(CMAKE_MODULE_PATH ${CMAKE_SOURCE_DIR}/cmake)
 project(pv-toolkit)
 
 add_subdirectory(./pvt)
+add_subdirectory(./qpvt)
 add_subdirectory(./pv_app)
diff --git a/README.md b/README.md
index d22def9..271c660 100644
--- a/README.md
+++ b/README.md
@@ -12,7 +12,15 @@ by the Free Software Foundation, either version 3 of the License, or
 
 In the future, we may decide to add a commercial license 
 at our own discretion without further notice.
-    
+
+If you are using pvt in a project, work or publication,
+please mention "pvt performance visualization toolkit"
+and cite \[[1](#references)\] *and* 
+
+* \[[2](#references)\] if you are using the correlation analysis or 
+* \[[3](#references)\] if you are using the geometry mapping. 
+
+
 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
@@ -25,3 +33,11 @@ along with this program.  If not, see [http://www.gnu.org/licenses/].
 * Define an evironment variable `QT5_DIR`
   * Windows: it must be set to a specific build directory e.g., `/Qt/5.5/msvc2013_64/`
   * Mac (Homebrew): `/usr/local/opt/qt5` 
+
+## References
+
+[1] Tom Vierjahn, Marc-André Hermanns, Bernd Mohr, Matthias S. Müller, Torsten W. Kuhlen, Bernd Hentschel, "Using Directed Variance to Identify Meaningful Views in Call-Path Performance Profiles". Accepted for publication: 3rd Workshop on Visual Performance Analysis (VPA), 2016.
+
+[2] Tom Vierjahn, Marc-André Hermanns, Bernd Mohr, Matthias S. Müller, Torsten Wolfgang Kuhlen, Bernd Hentschel, "Correlating Sub-Phenomena in Performance Data in the Frequency Domain". Accepted for poster presentation: LDAV 2016 – The 6th IEEE Symposium on Large Data Analysis and Visualization, 2016.
+
+[3] Tom Vierjahn, Torsten W. Kuhlen, Matthias S. Müller, Bernd Hentschel, "Visualizing Performance Data With Respect to the Simulated Geometry". Presented at: 1st JARA-HPC Symposium, 2016.
diff --git a/pv_app/CMakeLists.txt b/pv_app/CMakeLists.txt
index c648536..e43bcaf 100644
--- a/pv_app/CMakeLists.txt
+++ b/pv_app/CMakeLists.txt
@@ -40,7 +40,7 @@ set(CMAKE_INCLUDE_CURRENT_DIR ON)
 ADD_DEFINITIONS(-std=c++11)
 
 if (BUILD_SHARED)
-  add_definitions(-DPVT_DLL)
+  add_definitions(-DPVT_DLL -DQPVT_DLL)
 endif()
 
 #-------------------------------------------------------------------------------
@@ -86,6 +86,7 @@ QT5_WRAP_UI      (QT_UI_SRCS   ${UI})
 
 # pvt
 include_directories(../pvt/include)
+include_directories(../qpvt/include)
 
 #-------------------------------------------------------------------------------
 # executable
@@ -117,6 +118,7 @@ target_link_libraries(${PROJECT_NAME}
   Qt5::OpenGL
   Qt5::Widgets
   pvt
+  qpvt
 )
 
 if (WIN32)
@@ -127,7 +129,7 @@ endif()
 if (MSVC)
   get_filename_component(FFTW_DIRECTORY ${FFTW_LIBRARIES} PATH)
   get_filename_component(GLEW_DIRECTORY ${GLEW_LIBRARY}   PATH)
-  set(ENVIRONMENT_PATH  ${FFTW_DIRECTORY};${GLEW_DIRECTORY};$ENV{QT5_DIR}/bin/;${pvt_BINARY_DIR}/\$\(Configuration\))
+  set(ENVIRONMENT_PATH  ${FFTW_DIRECTORY};${GLEW_DIRECTORY};$ENV{QT5_DIR}/bin/;${pvt_BINARY_DIR}/\$\(Configuration\);${qpvt_BINARY_DIR}/\$\(Configuration\))
   configure_file(${CMAKE_SOURCE_DIR}/cmake/VisualStudioUserFileTemplate.xml 
                  ${CMAKE_BINARY_DIR}/${PROJECT_NAME}/${PROJECT_NAME}.vcxproj.user 
                  @ONLY)
diff --git a/pv_app/src/_SourceFiles.cmake b/pv_app/src/_SourceFiles.cmake
index fe74a99..29ac335 100644
--- a/pv_app/src/_SourceFiles.cmake
+++ b/pv_app/src/_SourceFiles.cmake
@@ -29,48 +29,7 @@ set( RelativeSourceGroup "Source Files" )
 set(DirFiles
     application.cpp
     application.hpp
-    camera_tools.cpp
-    camera_tools.hpp
-    cartesian_topology_viewer_widget.cpp
-    cartesian_topology_viewer_widget.hpp
-    cnode_impact_list_model.cpp
-    cnode_impact_list_model.hpp
-    cnode_impact_selector_widget.cpp
-    cnode_impact_selector_widget.hpp
-    cnode_tree_model.cpp
-    cnode_tree_model.hpp
-    correlated_views_model.cpp
-    correlated_views_model.hpp
-    data_range_h_slider.cpp
-    data_range_h_slider.hpp
-    data_range_v_slider.cpp
-    data_range_v_slider.hpp
-    directed_variation_glyph_delegate.cpp
-    directed_variation_glyph_delegate.hpp
-    geometry_viewer_widget.cpp
-    geometry_viewer_widget.hpp
     main.cpp
-    metric_tree_model.cpp
-    metric_tree_model.hpp
-    parallel_coordinates_plot_widget.cpp
-    parallel_coordinates_plot_widget.hpp
-    perf_data_tree_model.hpp
-    perf_data_viewer_widget.cpp
-    perf_data_viewer_widget.hpp
-    range_slider.cpp
-    range_slider.hpp
-    range_h_slider.cpp
-    range_h_slider.hpp
-    range_v_slider.cpp
-    range_v_slider.hpp
-    severity_glyph_delegate.cpp
-    severity_glyph_delegate.hpp
-    slice_slider.cpp
-    slice_slider.hpp
-    squarified_cushion_treemap_widget.cpp
-    squarified_cushion_treemap_widget.hpp
-    viewer_widget.cpp
-    viewer_widget.hpp
     _SourceFiles.cmake
 )
 
diff --git a/pv_app/src/application.cpp b/pv_app/src/application.cpp
index acad19b..729af9c 100644
--- a/pv_app/src/application.cpp
+++ b/pv_app/src/application.cpp
@@ -38,8 +38,9 @@
 #include <pvt/severity_view.hpp>
 #include <pvt/rendering/camera.hpp>
 
+#include <qpvt/widgets/perf_data_viewer_widget.hpp>
+
 #include "application.hpp"
-#include "perf_data_viewer_widget.hpp"
 
 namespace pv_app {
 
@@ -91,17 +92,17 @@ application::setup_ui
   mp_main_splitter->setWindowTitle("pv_app");
   mp_main_splitter->setOrientation(Qt::Vertical);
   
-  mp_perf_data_viewer_widget_top    = new perf_data_viewer_widget(
+  mp_perf_data_viewer_widget_top    = new qpvt::perf_data_viewer_widget(
     &m_perf_data,
-    perf_data_viewer_widget::metric_cnode_views);
+    qpvt::perf_data_viewer_widget::metric_cnode_views);
 
-  mp_perf_data_viewer_widget_bottom = new perf_data_viewer_widget(
+  mp_perf_data_viewer_widget_bottom = new qpvt::perf_data_viewer_widget(
     &m_perf_data,
-    perf_data_viewer_widget::correlated_views);
+    qpvt::perf_data_viewer_widget::correlated_views);
   
   QObject::connect(
     mp_perf_data_viewer_widget_top,
-    &perf_data_viewer_widget::find_correlated_views_requested,
+    &qpvt::perf_data_viewer_widget::find_correlated_views_requested,
     [this] ()
     {
       find_correlated_views();
@@ -109,7 +110,7 @@ application::setup_ui
   
   QObject::connect(
     mp_perf_data_viewer_widget_top,
-    &perf_data_viewer_widget::filter_range_from_other_requested,
+    &qpvt::perf_data_viewer_widget::filter_range_from_other_requested,
     [this] ()
     {
       assign_filter_range_from_other(mp_perf_data_viewer_widget_bottom,
@@ -118,7 +119,7 @@ application::setup_ui
 
   QObject::connect(
     mp_perf_data_viewer_widget_bottom,
-    &perf_data_viewer_widget::filter_range_from_other_requested,
+    &qpvt::perf_data_viewer_widget::filter_range_from_other_requested,
     [this]()
     {
       assign_filter_range_from_other(mp_perf_data_viewer_widget_top,
@@ -194,8 +195,8 @@ application::find_correlated_views
 //------------------------------------------------------------------------------
 void
 application::assign_filter_range_from_other
-(perf_data_viewer_widget* p_source_perf_data_viewer_widget,
- perf_data_viewer_widget* p_target_perf_data_viewer_widget)
+(qpvt::perf_data_viewer_widget* p_source_perf_data_viewer_widget,
+ qpvt::perf_data_viewer_widget* p_target_perf_data_viewer_widget)
 {
   auto range = p_source_perf_data_viewer_widget->get_filter_range();
   p_target_perf_data_viewer_widget->set_filter_range(range.first, range.second);
diff --git a/pv_app/src/application.hpp b/pv_app/src/application.hpp
index 743336e..7a6ea68 100644
--- a/pv_app/src/application.hpp
+++ b/pv_app/src/application.hpp
@@ -26,16 +26,18 @@
 #ifndef PV_APP_APPLICATION_HPP_
 #define PV_APP_APPLICATION_HPP_
 
-#include <list>
+#include <vector>
 
 #include <pvt/correlated_severity_view.hpp>
 #include <pvt/perf_data.hpp>
 
 class QSplitter;
 
-namespace pv_app {
+namespace qpvt {
+  class perf_data_viewer_widget;
+}
 
-class perf_data_viewer_widget;
+namespace pv_app {
 
 //------------------------------------------------------------------------------
 class application
@@ -49,16 +51,15 @@ private:
   
   void find_correlated_views         ();
   void assign_filter_range_from_other(
-    perf_data_viewer_widget* p_source_perf_data_viewer_widget,
-    perf_data_viewer_widget* p_target_perf_data_viewer_widget);
+    qpvt::perf_data_viewer_widget* p_source_perf_data_viewer_widget,
+    qpvt::perf_data_viewer_widget* p_target_perf_data_viewer_widget);
 
   pvt::perf_data                             m_perf_data;
   std::vector<pvt::correlated_severity_view> m_correlated_views;
 
-  perf_data_viewer_widget* mp_perf_data_viewer_widget_top    = nullptr;
-  perf_data_viewer_widget* mp_perf_data_viewer_widget_bottom = nullptr;
-  QSplitter*               mp_main_splitter                  = nullptr;
-  
+  qpvt::perf_data_viewer_widget* mp_perf_data_viewer_widget_top    = nullptr;
+  qpvt::perf_data_viewer_widget* mp_perf_data_viewer_widget_bottom = nullptr;
+  QSplitter*                     mp_main_splitter                  = nullptr;
 };
 
 } // namespace pv_app
diff --git a/pvt/_SourceFiles.cmake b/pvt/_SourceFiles.cmake
index 3400cc6..106d410 100644
--- a/pvt/_SourceFiles.cmake
+++ b/pvt/_SourceFiles.cmake
@@ -68,6 +68,7 @@ set(SourceFiles
   include/pvt/rendering/cube_vertices.hpp
   include/pvt/rendering/renderable.hpp
   include/pvt/rendering/renderable_axes.hpp
+  include/pvt/rendering/renderable_cartesian_grid.hpp
   include/pvt/rendering/renderable_cartesian_topology.hpp
   include/pvt/rendering/renderable_geometry.hpp
   include/pvt/rendering/renderable_line_plot.hpp
@@ -129,6 +130,7 @@ set(SourceFiles
   src/rendering/camera.cpp
   src/rendering/clickable_scene.cpp
   src/rendering/renderable_axes.cpp
+  src/rendering/renderable_cartesian_grid.cpp
   src/rendering/renderable_cartesian_topology.cpp
   src/rendering/renderable_geometry.cpp
   src/rendering/renderable_line_plot.cpp
diff --git a/pvt/include/pvt/rendering/renderable_cartesian_grid.hpp b/pvt/include/pvt/rendering/renderable_cartesian_grid.hpp
new file mode 100644
index 0000000..f7ec818
--- /dev/null
+++ b/pvt/include/pvt/rendering/renderable_cartesian_grid.hpp
@@ -0,0 +1,103 @@
+//------------------------------------------------------------------------------
+// pvt performance visualization toolkit
+//
+// Copyright (c) 2014-2016 RWTH Aachen University, Germany,
+// Virtual Reality & Immersive Visualisation Group.
+//------------------------------------------------------------------------------
+//                                License
+//
+// This framework is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Lesser General Public License as published
+// by the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// In the future, we may decide to add a commercial license
+// at our own discretion without further notice.
+//
+// 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 Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+//------------------------------------------------------------------------------
+
+#ifndef PVT_RENDERABLE_CARTESIAN_GRID_HPP_
+#define PVT_RENDERABLE_CARTESIAN_GRID_HPP_
+
+#include <Eigen/Core>
+
+#include <pvt/api.hpp>
+#include <pvt/optional.hpp>
+#include <pvt/gl/buffer.hpp>
+#include <pvt/rendering/renderable.hpp>
+#include <pvt/rendering/vertex_array_shader_pair.hpp>
+
+namespace pvt {
+
+//------------------------------------------------------------------------------
+class PVT_API renderable_cartesian_grid 
+: public renderable, vertex_array_shader_pair
+{
+public:
+  renderable_cartesian_grid(const Eigen::Vector3f& size,
+                            const Eigen::Vector3f& block_size);
+  
+  const Eigen::Vector3f& get_translation() const
+  {
+    return m_translation;
+  }
+  const Eigen::Vector3f& get_size       () const
+  {
+    return m_size;
+  }
+  const Eigen::Vector3f& get_block_size () const
+  {
+    return m_block_size;
+  }
+  const Eigen::Vector4f& get_color      () const
+  {
+    return m_color;
+  }
+
+  void set_size       (const Eigen::Vector3f& size       )
+  {
+    m_size         = size;
+    m_needs_upload = true;
+  }
+  void set_block_size (const Eigen::Vector3f& block_size )
+  {
+    m_block_size   = block_size;
+    m_needs_upload = true;
+  }
+  void set_translation(const Eigen::Vector3f& translation)
+  {
+    m_translation  = translation;
+    m_needs_upload = true;
+  }
+  void set_color      (const Eigen::Vector4f& color      )
+  {
+    m_color        = color;
+    m_needs_upload = true;
+  }
+
+  void on_setup () override;
+  void on_render(const camera* p_camera) override;
+
+private:
+  void upload();
+
+  Eigen::Vector3f         m_size         ;
+  Eigen::Vector3f         m_block_size   ;
+  Eigen::Vector3f         m_translation  ;
+  Eigen::Vector4f         m_color        ;
+  optional<vertex_buffer> m_vertex_buffer;
+  optional<vertex_buffer> m_normal_buffer;
+  bool                    m_needs_upload = false;
+  std::size_t             m_draw_count   = 0    ;
+};
+
+} // namespace pvt
+
+#endif // #ifndef PVT_RENDERABLE_CARTESIAN_GRID_HPP_
diff --git a/pvt/include/pvt/rendering/shader_strings.hpp b/pvt/include/pvt/rendering/shader_strings.hpp
index 3ef3535..5407a75 100644
--- a/pvt/include/pvt/rendering/shader_strings.hpp
+++ b/pvt/include/pvt/rendering/shader_strings.hpp
@@ -38,6 +38,8 @@ namespace shader_strings {
 extern PVT_API std::string axes_vert;
 extern PVT_API std::string axes_geom;
 extern PVT_API std::string axes_frag;
+extern PVT_API std::string cartesian_grid_vert;
+extern PVT_API std::string cartesian_grid_frag;
 extern PVT_API std::string color_treemap_vert;
 extern PVT_API std::string color_treemap_frag;
 extern PVT_API std::string cover_vert;
diff --git a/pvt/src/io/perf_data_file_native_system_geometry_loader.cpp b/pvt/src/io/perf_data_file_native_system_geometry_loader.cpp
index a40d7e5..4e34a7f 100644
--- a/pvt/src/io/perf_data_file_native_system_geometry_loader.cpp
+++ b/pvt/src/io/perf_data_file_native_system_geometry_loader.cpp
@@ -123,7 +123,6 @@ perf_data_file_native_system_geometry_loader::load_geometry
     file >> delimiter;
     file >> vertices[i].y();
     file >> delimiter;
-    vertices[i].y() *= -1.0;
   }
 
   // Read number of indices.
diff --git a/pvt/src/rendering/renderable_cartesian_grid.cpp b/pvt/src/rendering/renderable_cartesian_grid.cpp
new file mode 100644
index 0000000..5378d8f
--- /dev/null
+++ b/pvt/src/rendering/renderable_cartesian_grid.cpp
@@ -0,0 +1,146 @@
+//------------------------------------------------------------------------------
+// pvt performance visualization toolkit
+//
+// Copyright (c) 2014-2016 RWTH Aachen University, Germany,
+// Virtual Reality & Immersive Visualisation Group.
+//------------------------------------------------------------------------------
+//                                License
+//
+// This framework is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Lesser General Public License as published
+// by the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// In the future, we may decide to add a commercial license
+// at our own discretion without further notice.
+//
+// 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 Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+//------------------------------------------------------------------------------
+
+#include <pvt/gl/shader.hpp>
+#include <pvt/rendering/renderable_cartesian_grid.hpp>
+#include <pvt/rendering/shader_strings.hpp>
+
+namespace pvt {
+
+//------------------------------------------------------------------------------
+renderable_cartesian_grid::renderable_cartesian_grid(
+  const Eigen::Vector3f& size,
+  const Eigen::Vector3f& block_size)
+  : m_size(size)
+  , m_block_size(block_size)
+  , m_translation({ 0.0, 0.0, 0.0 })
+  , m_color({ 0.5, 0.5, 0.5, 1.0 })
+{
+
+}
+
+void renderable_cartesian_grid::on_setup()
+{
+  vertex_array_shader_pair::setup();
+
+  m_vertex_buffer.emplace();
+  m_normal_buffer.emplace();
+
+  upload();
+
+  m_shader_program->attach_shader(vertex_shader  (shader_strings::cartesian_grid_vert));
+  m_shader_program->attach_shader(fragment_shader(shader_strings::cartesian_grid_frag));
+  m_shader_program->link();
+
+  m_shader_program->bind  ();
+  m_vertex_buffer ->bind  ();
+  m_shader_program->set_attribute_buffer  ("vertex", 3, GL_FLOAT);
+  m_shader_program->enable_attribute_array("vertex");
+  m_vertex_buffer ->unbind();
+  m_normal_buffer ->bind  ();
+  m_shader_program->set_attribute_buffer  ("normal", 3, GL_FLOAT);
+  m_shader_program->enable_attribute_array("normal");
+  m_normal_buffer ->unbind();
+
+  vertex_array_shader_pair::unbind();
+}
+
+void renderable_cartesian_grid::on_render(const camera* p_camera)
+{
+  vertex_array_shader_pair::pre_render(p_camera);
+
+  if (m_needs_upload)
+  {
+    upload();
+    m_needs_upload = false;
+  }
+
+  m_shader_program->set_uniform("translation", m_translation);
+  m_shader_program->set_uniform("color"      , m_color      );
+
+  glDrawArrays(GL_LINES, 0, m_draw_count);
+
+  vertex_array_shader_pair::post_render();
+}
+
+void renderable_cartesian_grid::upload()
+{
+  // Fill via m_size, m_block_size.
+  std::vector<float> vertices;
+  std::vector<float> normals ;
+
+  // Front and back face.
+  for (auto z = 0; z <= m_size.z(); z += m_size.z())
+  {
+    for (auto x = 0; x <= m_size.x(); x += m_block_size.x())
+    {
+      vertices.insert(vertices.end(), { (float)x, 0       , (float)z, (float)x  , m_size.y(), (float)z});
+      normals .insert(normals .end(), { 0, 0, z == 0 ? 1.0f : -1.0f, 0, 0, z == 0 ? 1.0f : -1.0f });
+    }
+    for (auto y = 0; y <= m_size.y(); y += m_block_size.y())
+    {
+      vertices.insert(vertices.end(), { 0       , (float)y, (float)z, m_size.x(), (float)y  , (float)z});
+      normals .insert(normals .end(), { 0, 0, z == 0 ? 1.0f : -1.0f, 0, 0, z == 0 ? 1.0f : -1.0f });
+    }
+  }
+  // Left and right.
+  for (auto x = 0; x <= m_size.x(); x += m_size.x())
+  {
+    for (auto y = 0; y <= m_size.y(); y += m_block_size.y())
+    {
+      vertices.insert(vertices.end(), { (float)x, (float)y, 0       , (float)x, (float)y  , m_size.z()});
+      normals .insert(normals .end(), { x == 0 ? 1.0f : -1.0f, 0, 0, x == 0 ? 1.0f : -1.0f, 0, 0});
+    }
+    for (auto z = 0; z <= m_size.z(); z += m_block_size.z())
+    {
+      vertices.insert(vertices.end(), { (float)x, 0       , (float)z, (float)x, m_size.y(), (float)z  });
+      normals .insert(normals .end(), { x == 0 ? 1.0f : -1.0f, 0, 0, x == 0 ? 1.0f : -1.0f, 0, 0});
+    }
+  }
+  // Top and bottom.
+  for (auto y = 0; y <= m_size.y(); y += m_size.y())
+  {
+    for (auto x = 0; x <= m_size.x(); x += m_block_size.x())
+    {
+      vertices.insert(vertices.end(), { (float)x, (float)y, 0       , (float)x  , (float)y, m_size.z()});
+      normals .insert(normals .end(), { 0, y == 0 ? 1.0f : -1.0f, 0, 0, y == 0 ? 1.0f : -1.0f, 0});
+    }
+    for (auto z = 0; z <= m_size.z(); z += m_block_size.z())
+    {
+      vertices.insert(vertices.end(), { 0       , (float)y, (float)z, m_size.x(), (float)y, (float)z  });
+      normals .insert(normals .end(), { 0, y == 0 ? 1.0f : -1.0f, 0, 0, y == 0 ? 1.0f : -1.0f, 0});
+    }
+  }
+    
+  m_vertex_buffer->bind    ();
+  m_vertex_buffer->set_data(vertices.size() * sizeof(float), vertices.data());
+  m_vertex_buffer->unbind  ();
+  m_normal_buffer->bind    ();
+  m_normal_buffer->set_data(normals .size() * sizeof(float), normals .data());
+  m_normal_buffer->unbind  ();
+  m_draw_count = vertices.size() / 2;
+}
+} // namespace pvt
+
diff --git a/pvt/src/rendering/shader_strings.cpp b/pvt/src/rendering/shader_strings.cpp
index 5a6cfc3..615882f 100644
--- a/pvt/src/rendering/shader_strings.cpp
+++ b/pvt/src/rendering/shader_strings.cpp
@@ -119,7 +119,39 @@ void main()
 {
   fragColor = color;
 }
-)";                                        
+)";
+std::string cartesian_grid_vert = R"(\
+#version 330 core
+uniform mat4  projection ;
+uniform mat4  view       ;
+uniform vec3  translation;
+in      vec3  vertex     ;
+in      vec3  normal     ;
+out     float visible    ;
+void main()
+{
+  gl_Position = projection * view * vec4(vertex + translation, 1.0);
+
+  vec3 vertex_normal  = (view * vec4(normal, 0.0)).xyz;
+  if(vertex_normal.z >= 0.0)
+    visible = 1.0;
+  else
+    visible = 0.0;
+}
+)";
+std::string cartesian_grid_frag = R"(\
+#version 330 core
+uniform vec4  color     ;
+in      float visible   ;
+out     vec4  frag_color;
+void main()
+{
+  if(visible == 0.0)
+    discard;
+  else
+    frag_color = color;
+}
+)";
 std::string color_treemap_vert = R"(\
 #version 400
 
diff --git a/qpvt/CMakeLists.txt b/qpvt/CMakeLists.txt
new file mode 100644
index 0000000..b09d739
--- /dev/null
+++ b/qpvt/CMakeLists.txt
@@ -0,0 +1,119 @@
+#-------------------------------------------------------------------------------
+# pvt performance visualization toolkit
+#
+# Copyright (c) 2014-2016 RWTH Aachen University, Germany,
+# Virtual Reality & Immersive Visualisation Group.
+#-------------------------------------------------------------------------------
+#                                 License
+#
+# This library is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Lesser General Public License as published
+# by the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# In the future, we may decide to add a commercial license
+# at our own discretion without further notice.
+#
+# 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 Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+#-------------------------------------------------------------------------------
+
+cmake_minimum_required(VERSION 2.8.11)
+
+set(CMAKE_MODULE_PATH ${CMAKE_SOURCE_DIR}/cmake)
+
+project(qpvt)
+
+include( "./_SourceFiles.cmake" )
+
+# Assign source groups.
+include("${CMAKE_SOURCE_DIR}/cmake/assign_source_group.cmake")
+assign_source_group(${SourceFiles})
+
+# Find includes in corresponding build directories
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+# C++11
+ADD_DEFINITIONS(
+  -std=c++11
+)
+
+include_directories(./include)
+
+#-------------------------------------------------------------------------------
+# dependencies
+#-------------------------------------------------------------------------------
+
+# Eigen3
+find_package(Eigen3 REQUIRED)
+include_directories(${EIGEN3_INCLUDE_DIR})
+
+# FFTW
+find_package(FFTW REQUIRED)
+include_directories(${FFTW_INCLUDES})
+
+# OpenGL
+find_package(OpenGL)
+include_directories(${OPENGL_INCLUDE_DIR})
+
+# GLEW (only on Windows for definitions of OpenGL 3.0)
+if(WIN32)
+  find_package(GLEW REQUIRED)
+  if(GLEW_FOUND)
+    include_directories(${GLEW_INCLUDE_DIRS})
+  endif()
+endif()
+
+# Qt5
+if (DEFINED ENV{QT5_DIR})
+  set(CMAKE_PREFIX_PATH ${CMAKE_PREFIX_PATH} $ENV{QT5_DIR})
+  include_directories(BEFORE $ENV{QT5_DIR}/include)
+endif()
+
+set(CMAKE_AUTOMOC ON)
+
+find_package(Qt5Core    REQUIRED)
+find_package(Qt5Network REQUIRED)
+find_package(Qt5OpenGL  REQUIRED)
+find_package(Qt5Widgets REQUIRED)
+
+QT5_ADD_RESOURCES(QT_RCC_SRCS  ${RESOURCES})
+QT5_WRAP_CPP     (QT_MOC_FILES ${QT_FILES_TO_MOC})
+QT5_WRAP_UI      (QT_UI_SRCS   ${UI})
+
+# pvt
+include_directories(../pvt/include)
+
+#-------------------------------------------------------------------------------
+# library
+#-------------------------------------------------------------------------------
+
+# Toggle for shared or static library.
+set(BUILD_SHARED OFF CACHE BOOL "Build as a shared library.")
+
+# Create library
+if   (BUILD_SHARED)
+  add_library(${PROJECT_NAME} SHARED ${SourceFiles} ./_SourceFiles.cmake)
+  add_definitions(-DPVT_DLL -DQPVT_DLL -DQPVT_EXPORT)
+else ()
+  add_library(${PROJECT_NAME}        ${SourceFiles} ./_SourceFiles.cmake)
+endif()
+
+target_link_libraries(${PROJECT_NAME}
+  ${OPENGL_LIBRARIES}
+  Qt5::Core
+  Qt5::OpenGL
+  Qt5::Widgets
+  pvt
+)
+
+if(WIN32)
+  target_link_libraries(${PROJECT_NAME} ${GLEW_LIBRARY})
+endif()
+
+set(${PROJECT_NAME}_BINARY_DIR ${CMAKE_CURRENT_BINARY_DIR} PARENT_SCOPE)
diff --git a/qpvt/_SourceFiles.cmake b/qpvt/_SourceFiles.cmake
new file mode 100644
index 0000000..100048c
--- /dev/null
+++ b/qpvt/_SourceFiles.cmake
@@ -0,0 +1,77 @@
+#-------------------------------------------------------------------------------
+# pvt performance visualization toolkit
+#
+# Copyright (c) 2014-2016 RWTH Aachen University, Germany,
+# Virtual Reality & Immersive Visualisation Group.
+#-------------------------------------------------------------------------------
+#                                 License
+#
+# This library is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Lesser General Public License as published
+# by the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# In the future, we may decide to add a commercial license
+# at our own discretion without further notice.
+#
+# 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 Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+#-------------------------------------------------------------------------------
+
+set(SourceFiles
+  include/qpvt/api.hpp
+
+  include/qpvt/delegates/directed_variation_glyph_delegate.hpp
+  include/qpvt/delegates/severity_glyph_delegate.hpp
+
+  include/qpvt/models/cnode_impact_list_model.hpp
+  include/qpvt/models/cnode_tree_model.hpp
+  include/qpvt/models/correlated_views_model.hpp
+  include/qpvt/models/metric_tree_model.hpp
+  include/qpvt/models/perf_data_tree_model.hpp
+
+  include/qpvt/utility/camera_tools.hpp
+  
+  include/qpvt/widgets/cartesian_topology_viewer_widget.hpp
+  include/qpvt/widgets/cnode_impact_selector_widget.hpp
+  include/qpvt/widgets/data_range_h_slider.hpp
+  include/qpvt/widgets/data_range_v_slider.hpp
+  include/qpvt/widgets/geometry_viewer_widget.hpp
+  include/qpvt/widgets/parallel_coordinates_plot_widget.hpp
+  include/qpvt/widgets/perf_data_viewer_widget.hpp
+  include/qpvt/widgets/range_h_slider.hpp
+  include/qpvt/widgets/range_slider.hpp
+  include/qpvt/widgets/range_v_slider.hpp
+  include/qpvt/widgets/slice_slider.hpp
+  include/qpvt/widgets/squarified_cushion_treemap_widget.hpp
+  include/qpvt/widgets/viewer_widget.hpp
+
+  src/delegates/directed_variation_glyph_delegate.cpp
+  src/delegates/severity_glyph_delegate.cpp
+  
+  src/models/cnode_impact_list_model.cpp
+  src/models/cnode_tree_model.cpp
+  src/models/correlated_views_model.cpp
+  src/models/metric_tree_model.cpp
+  
+  src/utility/camera_tools.cpp
+  
+  src/widgets/cartesian_topology_viewer_widget.cpp
+  src/widgets/cnode_impact_selector_widget.cpp
+  src/widgets/data_range_h_slider.cpp
+  src/widgets/data_range_v_slider.cpp
+  src/widgets/geometry_viewer_widget.cpp
+  src/widgets/parallel_coordinates_plot_widget.cpp
+  src/widgets/perf_data_viewer_widget.cpp
+  src/widgets/range_h_slider.cpp
+  src/widgets/range_slider.cpp
+  src/widgets/range_v_slider.cpp
+  src/widgets/slice_slider.cpp
+  src/widgets/squarified_cushion_treemap_widget.cpp
+  src/widgets/viewer_widget.cpp
+)
diff --git a/qpvt/include/qpvt/api.hpp b/qpvt/include/qpvt/api.hpp
new file mode 100644
index 0000000..a0cc0a3
--- /dev/null
+++ b/qpvt/include/qpvt/api.hpp
@@ -0,0 +1,47 @@
+//------------------------------------------------------------------------------
+// pvt performance visualization toolkit
+//
+// Copyright (c) 2014-2016 RWTH Aachen University, Germany,
+// Virtual Reality & Immersive Visualisation Group.
+//------------------------------------------------------------------------------
+//                                License
+//
+// This library is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Lesser General Public License as published
+// by the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// In the future, we may decide to add a commercial license
+// at our own discretion without further notice.
+//
+// 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 Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+//------------------------------------------------------------------------------
+
+#ifndef QPVT_API_HPP_
+#define QPVT_API_HPP_
+
+/// #define QPVT_DLL    when building or including as a .dll.
+/// #define QPVT_EXPORT when building as a .dll.
+/// Don't define anything on non-Windows platforms or when using as a lib.
+
+#if defined(_WIN32)
+  #ifdef QPVT_DLL
+    #ifdef QPVT_EXPORT
+      #define QPVT_API __declspec(dllexport)
+    #else
+      #define QPVT_API __declspec(dllimport)
+    #endif
+  #else
+    #define QPVT_API
+  #endif
+#else
+  #define QPVT_API
+#endif
+
+#endif // QPVT_CONFIG_HPP_
\ No newline at end of file
diff --git a/pv_app/src/directed_variation_glyph_delegate.hpp b/qpvt/include/qpvt/delegates/directed_variation_glyph_delegate.hpp
similarity index 86%
rename from pv_app/src/directed_variation_glyph_delegate.hpp
rename to qpvt/include/qpvt/delegates/directed_variation_glyph_delegate.hpp
index ae43509..ddf1e1f 100644
--- a/pv_app/src/directed_variation_glyph_delegate.hpp
+++ b/qpvt/include/qpvt/delegates/directed_variation_glyph_delegate.hpp
@@ -23,15 +23,17 @@
 // along with this program.  If not, see <http://www.gnu.org/licenses/>.
 //------------------------------------------------------------------------------
 
-#ifndef PV_APP_DIRECTED_VARIATION_GLYPH_DELEGATE_HPP_
-#define PV_APP_DIRECTED_VARIATION_GLYPH_DELEGATE_HPP_
+#ifndef QPVT_DIRECTED_VARIATION_GLYPH_DELEGATE_HPP_
+#define QPVT_DIRECTED_VARIATION_GLYPH_DELEGATE_HPP_
 
 #include <QAbstractItemDelegate>
 
-namespace pv_app {
+#include <qpvt/api.hpp>
+
+namespace qpvt {
 
 //------------------------------------------------------------------------------
-class directed_variation_glyph_delegate : public QAbstractItemDelegate
+class QPVT_API directed_variation_glyph_delegate : public QAbstractItemDelegate
 {
 Q_OBJECT
     
@@ -57,6 +59,6 @@ private:
   bool m_fade_out_enabled = true;
 };
 
-} // namespace pv_app
+} // namespace qpvt
 
-#endif // #ifndef PV_APP_DIRECTED_VARIATION_GLYPH_DELEGATE_HPP_
+#endif // #ifndef QPVT_DIRECTED_VARIATION_GLYPH_DELEGATE_HPP_
diff --git a/pv_app/src/severity_glyph_delegate.hpp b/qpvt/include/qpvt/delegates/severity_glyph_delegate.hpp
similarity index 86%
rename from pv_app/src/severity_glyph_delegate.hpp
rename to qpvt/include/qpvt/delegates/severity_glyph_delegate.hpp
index 849d5ec..78b1962 100644
--- a/pv_app/src/severity_glyph_delegate.hpp
+++ b/qpvt/include/qpvt/delegates/severity_glyph_delegate.hpp
@@ -23,15 +23,17 @@
 // along with this program.  If not, see <http://www.gnu.org/licenses/>.
 //------------------------------------------------------------------------------
 
-#ifndef PV_APP_SEVERITY_GLYPH_DELEGATE_HPP_
-#define PV_APP_SEVERITY_GLYPH_DELEGATE_HPP_
+#ifndef QPVT_SEVERITY_GLYPH_DELEGATE_HPP_
+#define QPVT_SEVERITY_GLYPH_DELEGATE_HPP_
 
 #include <QAbstractItemDelegate>
 
-namespace pv_app {
+#include <qpvt/api.hpp>
+
+namespace qpvt {
 
 //------------------------------------------------------------------------------
-class severity_glyph_delegate : public QAbstractItemDelegate
+class QPVT_API severity_glyph_delegate : public QAbstractItemDelegate
 {
   Q_OBJECT
   
@@ -45,6 +47,6 @@ public:
                  const QModelIndex&          index) const override;
 };
 
-} // namespace pv_app
+} // namespace qpvt
 
-#endif // #ifndef PV_APP_SEVERITY_GLYPH_DELEGATE_HPP_
+#endif // #ifndef QPVT_SEVERITY_GLYPH_DELEGATE_HPP_
diff --git a/pv_app/src/cnode_impact_list_model.hpp b/qpvt/include/qpvt/models/cnode_impact_list_model.hpp
similarity index 92%
rename from pv_app/src/cnode_impact_list_model.hpp
rename to qpvt/include/qpvt/models/cnode_impact_list_model.hpp
index 227fb56..fba8710 100644
--- a/pv_app/src/cnode_impact_list_model.hpp
+++ b/qpvt/include/qpvt/models/cnode_impact_list_model.hpp
@@ -23,11 +23,13 @@
 // along with this program.  If not, see <http://www.gnu.org/licenses/>.
 //------------------------------------------------------------------------------
 
-#ifndef PV_APP_CNODE_IMPACT_LIST_MODEL_HPP_
-#define PV_APP_CNODE_IMPACT_LIST_MODEL_HPP_
+#ifndef QPVT_CNODE_IMPACT_LIST_MODEL_HPP_
+#define QPVT_CNODE_IMPACT_LIST_MODEL_HPP_
 
 #include <QAbstractTableModel>
 
+#include <qpvt/api.hpp>
+
 namespace pvt {
 class cnode;
 class perf_data;
@@ -35,10 +37,10 @@ class severity_view;
 class suitable_3d_view_computer;
 }
 
-namespace pv_app {
+namespace qpvt {
 
 //------------------------------------------------------------------------------
-class cnode_impact_list_model : public QAbstractTableModel
+class QPVT_API cnode_impact_list_model : public QAbstractTableModel
 {
   Q_OBJECT
   
@@ -91,6 +93,6 @@ private:
   
 };
 
-} // namespace pv_app
+} // namespace qpvt
 
-#endif // #ifndef PV_APP_CNODE_IMPACT_LIST_MODEL_HPP_
+#endif // #ifndef QPVT_CNODE_IMPACT_LIST_MODEL_HPP_
diff --git a/pv_app/src/cnode_tree_model.hpp b/qpvt/include/qpvt/models/cnode_tree_model.hpp
similarity index 87%
rename from pv_app/src/cnode_tree_model.hpp
rename to qpvt/include/qpvt/models/cnode_tree_model.hpp
index f9bdb41..6f32d1a 100644
--- a/pv_app/src/cnode_tree_model.hpp
+++ b/qpvt/include/qpvt/models/cnode_tree_model.hpp
@@ -23,22 +23,23 @@
 // along with this program.  If not, see <http://www.gnu.org/licenses/>.
 //------------------------------------------------------------------------------
 
-#ifndef PV_APP_CNODE_TREE_MODEL_HPP_
-#define PV_APP_CNODE_TREE_MODEL_HPP_
+#ifndef QPVT_CNODE_TREE_MODEL_HPP_
+#define QPVT_CNODE_TREE_MODEL_HPP_
 
 #include <pvt/perf_data_cache_cnode.hpp>
 
-#include "perf_data_tree_model.hpp"
+#include <qpvt/api.hpp>
+#include <qpvt/models/perf_data_tree_model.hpp>
 
 namespace pvt {
 class cnode;
 class metric;
 }
 
-namespace pv_app {
+namespace qpvt {
 
 //------------------------------------------------------------------------------
-class cnode_tree_model : public perf_data_tree_model<pvt::cnode>
+class QPVT_API cnode_tree_model : public perf_data_tree_model<pvt::cnode>
 {
   Q_OBJECT
   
@@ -65,6 +66,6 @@ private:
   mutable pvt::perf_data_cache_cnode m_perf_data_cache;
 };
 
-} // namespace pv_app
+} // namespace qpvt
 
-#endif // #ifndef PV_APP_CNODE_TREE_MODEL_HPP_
+#endif // #ifndef QPVT_CNODE_TREE_MODEL_HPP_
diff --git a/pv_app/src/correlated_views_model.hpp b/qpvt/include/qpvt/models/correlated_views_model.hpp
similarity index 90%
rename from pv_app/src/correlated_views_model.hpp
rename to qpvt/include/qpvt/models/correlated_views_model.hpp
index 0f44b27..c1f3342 100644
--- a/pv_app/src/correlated_views_model.hpp
+++ b/qpvt/include/qpvt/models/correlated_views_model.hpp
@@ -23,8 +23,8 @@
 // along with this program.  If not, see <http://www.gnu.org/licenses/>.
 //------------------------------------------------------------------------------
 
-#ifndef PV_APP_CORRELATED_VIEWS_MODEL_HPP_
-#define PV_APP_CORRELATED_VIEWS_MODEL_HPP_
+#ifndef QPVT_CORRELATED_VIEWS_MODEL_HPP_
+#define QPVT_CORRELATED_VIEWS_MODEL_HPP_
 
 #include <vector>
 
@@ -32,10 +32,12 @@
 
 #include <pvt/correlated_severity_view.hpp>
 
-namespace pv_app {
+#include <qpvt/api.hpp>
+
+namespace qpvt {
 
 //------------------------------------------------------------------------------
-class correlated_views_model : public QAbstractTableModel
+class QPVT_API correlated_views_model : public QAbstractTableModel
 {
   Q_OBJECT
   
@@ -78,6 +80,6 @@ private:
   std::vector<pvt::correlated_severity_view> m_correlated_views;
 };
 
-} // namespace pv_app
+} // namespace qpvt
 
-#endif // #ifndef PV_APP_CORRELATED_VIEWS_MODEL_HPP_
+#endif // #ifndef QPVT_CORRELATED_VIEWS_MODEL_HPP_
diff --git a/pv_app/src/metric_tree_model.hpp b/qpvt/include/qpvt/models/metric_tree_model.hpp
similarity index 84%
rename from pv_app/src/metric_tree_model.hpp
rename to qpvt/include/qpvt/models/metric_tree_model.hpp
index 1717a81..951e6b6 100644
--- a/pv_app/src/metric_tree_model.hpp
+++ b/qpvt/include/qpvt/models/metric_tree_model.hpp
@@ -23,21 +23,22 @@
 // along with this program.  If not, see <http://www.gnu.org/licenses/>.
 //------------------------------------------------------------------------------
 
-#ifndef PV_APP_METRIC_TREE_MODEL_HPP_
-#define PV_APP_METRIC_TREE_MODEL_HPP_
+#ifndef QPVT_METRIC_TREE_MODEL_HPP_
+#define QPVT_METRIC_TREE_MODEL_HPP_
 
 #include <pvt/perf_data_cache_metric.hpp>
 
-#include "perf_data_tree_model.hpp"
+#include <qpvt/api.hpp>
+#include <qpvt/models/perf_data_tree_model.hpp>
 
 namespace pvt {
 class severity_view;
 }
 
-namespace pv_app {
+namespace qpvt {
 
 //------------------------------------------------------------------------------
-class metric_tree_model : public perf_data_tree_model<pvt::metric>
+class QPVT_API metric_tree_model : public perf_data_tree_model<pvt::metric>
 {
   Q_OBJECT
   
@@ -51,6 +52,6 @@ private:
   mutable pvt::perf_data_cache_metric m_perf_data_cache;
 };
 
-} // namespace pv_app
+} // namespace qpvt
 
-#endif // #ifndef PV_APP_METRIC_TREE_MODEL_HPP_
+#endif // #ifndef QPVT_METRIC_TREE_MODEL_HPP_
diff --git a/pv_app/src/perf_data_tree_model.hpp b/qpvt/include/qpvt/models/perf_data_tree_model.hpp
similarity index 96%
rename from pv_app/src/perf_data_tree_model.hpp
rename to qpvt/include/qpvt/models/perf_data_tree_model.hpp
index 7564a22..344ecbe 100644
--- a/pv_app/src/perf_data_tree_model.hpp
+++ b/qpvt/include/qpvt/models/perf_data_tree_model.hpp
@@ -23,8 +23,8 @@
 // along with this program.  If not, see <http://www.gnu.org/licenses/>.
 //------------------------------------------------------------------------------
 
-#ifndef PV_APP_PERF_DATA_TREE_MODEL_HPP_
-#define PV_APP_PERF_DATA_TREE_MODEL_HPP_
+#ifndef QPVT_PERF_DATA_TREE_MODEL_HPP_
+#define QPVT_PERF_DATA_TREE_MODEL_HPP_
 
 #include <QAbstractItemModel>
 
@@ -32,11 +32,13 @@
 #include <pvt/perf_data.hpp>
 #include <pvt/severity_view.hpp>
 
-namespace pv_app {
+#include <qpvt/api.hpp>
+
+namespace qpvt {
 
 //------------------------------------------------------------------------------
 template <typename perf_data_item>
-class perf_data_tree_model : public QAbstractItemModel
+class QPVT_API perf_data_tree_model : public QAbstractItemModel
 {
 public:
   struct column_info 
@@ -200,6 +202,6 @@ protected:
   std::vector<column_info>  m_column_infos;
 };
 
-} // namespace pv_app
+} // namespace qpvt
 
-#endif // #ifndef PV_APP_PERF_DATA_TREE_MODEL_HPP_
+#endif // #ifndef QPVT_PERF_DATA_TREE_MODEL_HPP_
diff --git a/pv_app/src/camera_tools.hpp b/qpvt/include/qpvt/utility/camera_tools.hpp
similarity index 93%
rename from pv_app/src/camera_tools.hpp
rename to qpvt/include/qpvt/utility/camera_tools.hpp
index a8b5ad9..0182b47 100644
--- a/pv_app/src/camera_tools.hpp
+++ b/qpvt/include/qpvt/utility/camera_tools.hpp
@@ -23,23 +23,25 @@
 // along with this program.  If not, see <http://www.gnu.org/licenses/>.
 //------------------------------------------------------------------------------
 
-#ifndef PV_APP_CAMERA_TOOLS_HPP_
-#define PV_APP_CAMERA_TOOLS_HPP_
+#ifndef QPVT_CAMERA_TOOLS_HPP_
+#define QPVT_CAMERA_TOOLS_HPP_
 
 #include <map>
 
 #include <Eigen/Core>
 
+#include <qpvt/api.hpp>
+
 class QMouseEvent;
 
 namespace pvt {
 class camera;
 }
 
-namespace pv_app {
+namespace qpvt {
 
 //------------------------------------------------------------------------------
-class camera_tools
+class QPVT_API camera_tools
 {
 public:
   enum tool
@@ -83,6 +85,6 @@ private:
   Eigen::Vector3f            m_initial_coi;
 };
 
-} // namespace pv_app
+} // namespace qpvt
 
-#endif // #ifndef PV_APP_CAMERA_TOOLS_HPP_
+#endif // #ifndef QPVT_CAMERA_TOOLS_HPP_
diff --git a/pv_app/src/cartesian_topology_viewer_widget.hpp b/qpvt/include/qpvt/widgets/cartesian_topology_viewer_widget.hpp
similarity index 96%
rename from pv_app/src/cartesian_topology_viewer_widget.hpp
rename to qpvt/include/qpvt/widgets/cartesian_topology_viewer_widget.hpp
index 10dde5b..9a880dc 100644
--- a/pv_app/src/cartesian_topology_viewer_widget.hpp
+++ b/qpvt/include/qpvt/widgets/cartesian_topology_viewer_widget.hpp
@@ -39,10 +39,12 @@
 #include <QWidget>
 
 #include <pvt/cartesian_topology.hpp>
+#include <pvt/rendering/renderable_cartesian_grid.hpp>
 #include <pvt/rendering/renderable_cartesian_topology.hpp>
 
-#include "slice_slider.hpp"
-#include "viewer_widget.hpp"
+#include <qpvt/api.hpp>
+#include <qpvt/widgets/slice_slider.hpp>
+#include <qpvt/widgets/viewer_widget.hpp>
 
 class QComboBox;
 class QDropEvent;
@@ -55,13 +57,13 @@ class renderable_axes;
 class scene;
 }
 
-namespace pv_app {
+namespace qpvt {
   
 class data_range_h_slider;
 class data_range_v_slider;
 
 //------------------------------------------------------------------------------
-class cartesian_topology_viewer_widget : public QWidget
+class QPVT_API cartesian_topology_viewer_widget : public QWidget
 {
   Q_OBJECT
 
@@ -160,6 +162,7 @@ private:
   
   pvt::cartesian_topology*            mp_cartesian_topology;
   pvt::scene*                         mp_renderable_scene;
+  pvt::renderable_cartesian_grid*     mp_renderable_cartesian_grid;
   pvt::renderable_cartesian_topology* mp_renderable_cartesian_topology;
   pvt::renderable_axes*               mp_renderable_axes;
   
@@ -257,6 +260,6 @@ cartesian_topology_viewer_widget::map_data_to_topology
   update_slider_plots();
 }
 
-} // namespace pv_app
+} // namespace qpvt
 
 #endif // #ifndef PV_CARTESIAN_TOPOLOGY_VIEWER_WIDGET__H_
diff --git a/pv_app/src/cnode_impact_selector_widget.hpp b/qpvt/include/qpvt/widgets/cnode_impact_selector_widget.hpp
similarity index 91%
rename from pv_app/src/cnode_impact_selector_widget.hpp
rename to qpvt/include/qpvt/widgets/cnode_impact_selector_widget.hpp
index e19d1a4..419025a 100644
--- a/pv_app/src/cnode_impact_selector_widget.hpp
+++ b/qpvt/include/qpvt/widgets/cnode_impact_selector_widget.hpp
@@ -23,11 +23,14 @@
 // along with this program.  If not, see <http://www.gnu.org/licenses/>.
 //------------------------------------------------------------------------------
 
-#ifndef PV_APP_CNODE_IMPACT_SELECTOR_WIDGET_HPP_
-#define PV_APP_CNODE_IMPACT_SELECTOR_WIDGET_HPP_
+#ifndef QPVT_CNODE_IMPACT_SELECTOR_WIDGET_HPP_
+#define QPVT_CNODE_IMPACT_SELECTOR_WIDGET_HPP_
 
 #include <QWidget>
 
+#include <qpvt/api.hpp>
+
+class QAbstractButton;
 class QButtonGroup;
 class QDialogButtonBox;
 class QGroupBox;
@@ -37,17 +40,18 @@ class QTableView;
 class QVBoxLayout;
 
 namespace pvt {
+class cnode;
 class perf_data;
 class severity_view;
 }
 
-namespace pv_app {
+namespace qpvt {
 
 class cnode_impact_list_model;
 class cnode_tree_model;
 
 //------------------------------------------------------------------------------
-class cnode_impact_selector_widget : public QWidget
+class QPVT_API cnode_impact_selector_widget : public QWidget
 {
   Q_OBJECT
   
@@ -99,6 +103,6 @@ private:
   QLineEdit*               mp_variation_threshold;
 };
 
-} // namespace pv_app
+} // namespace qpvt
 
-#endif // #ifndef PV_APP_CNODE_IMPACT_SELECTOR_WIDGET_HPP_
+#endif // #ifndef QPVT_CNODE_IMPACT_SELECTOR_WIDGET_HPP_
diff --git a/pv_app/src/data_range_h_slider.hpp b/qpvt/include/qpvt/widgets/data_range_h_slider.hpp
similarity index 92%
rename from pv_app/src/data_range_h_slider.hpp
rename to qpvt/include/qpvt/widgets/data_range_h_slider.hpp
index fde591b..aa0454b 100644
--- a/pv_app/src/data_range_h_slider.hpp
+++ b/qpvt/include/qpvt/widgets/data_range_h_slider.hpp
@@ -23,17 +23,18 @@
 // along with this program.  If not, see <http://www.gnu.org/licenses/>.
 //------------------------------------------------------------------------------
 
-#ifndef PV_APP_DATA_RANGE_H_SLIDER_HPP_
-#define PV_APP_DATA_RANGE_H_SLIDER_HPP_
+#ifndef QPVT_DATA_RANGE_H_SLIDER_HPP_
+#define QPVT_DATA_RANGE_H_SLIDER_HPP_
 
 #include <vector>
 
-#include "range_h_slider.hpp"
+#include <qpvt/api.hpp>
+#include <qpvt/widgets/range_h_slider.hpp>
 
-namespace pv_app {
+namespace qpvt {
 
 //------------------------------------------------------------------------------
-class data_range_h_slider : public range_h_slider
+class QPVT_API data_range_h_slider : public range_h_slider
 {
   Q_OBJECT
   
@@ -124,6 +125,6 @@ private:
   pvt::optional<pvt::shader_program> m_shader_program_v;
 };
 
-} // namespace pv_app
+} // namespace qpvt
 
-#endif // #ifndef PV_APP_DATA_RANGE_H_SLIDER_HPP_
+#endif // #ifndef QPVT_DATA_RANGE_H_SLIDER_HPP_
diff --git a/pv_app/src/data_range_v_slider.hpp b/qpvt/include/qpvt/widgets/data_range_v_slider.hpp
similarity index 90%
rename from pv_app/src/data_range_v_slider.hpp
rename to qpvt/include/qpvt/widgets/data_range_v_slider.hpp
index b87d333..56c9912 100644
--- a/pv_app/src/data_range_v_slider.hpp
+++ b/qpvt/include/qpvt/widgets/data_range_v_slider.hpp
@@ -23,17 +23,18 @@
 // along with this program.  If not, see <http://www.gnu.org/licenses/>.
 //------------------------------------------------------------------------------
 
-#ifndef PV_APP_DATA_RANGE_V_SLIDER_HPP_
-#define PV_APP_DATA_RANGE_V_SLIDER_HPP_
+#ifndef QPVT_DATA_RANGE_V_SLIDER_HPP_
+#define QPVT_DATA_RANGE_V_SLIDER_HPP_
 
 #include <vector>
 
-#include "range_v_slider.hpp"
+#include <qpvt/api.hpp>
+#include <qpvt/widgets/range_v_slider.hpp>
 
-namespace pv_app {
+namespace qpvt {
 
 //------------------------------------------------------------------------------
-class data_range_v_slider : public range_v_slider
+class QPVT_API data_range_v_slider : public range_v_slider
 {
   Q_OBJECT
   
@@ -86,6 +87,6 @@ private:
   pvt::optional<pvt::vertex_buffer>  m_vertex_buffer;
 };
 
-} // namespace pv_app
+} // namespace qpvt
 
-#endif // #ifndef PV_APP_DATA_RANGE_V_SLIDER_HPP_
+#endif // #ifndef QPVT_DATA_RANGE_V_SLIDER_HPP_
diff --git a/pv_app/src/geometry_viewer_widget.hpp b/qpvt/include/qpvt/widgets/geometry_viewer_widget.hpp
similarity index 90%
rename from pv_app/src/geometry_viewer_widget.hpp
rename to qpvt/include/qpvt/widgets/geometry_viewer_widget.hpp
index c412e0f..0b3fbfa 100644
--- a/pv_app/src/geometry_viewer_widget.hpp
+++ b/qpvt/include/qpvt/widgets/geometry_viewer_widget.hpp
@@ -23,8 +23,8 @@
 // along with this program.  If not, see <http://www.gnu.org/licenses/>.
 //------------------------------------------------------------------------------
 
-#ifndef PV_APP_GEOMETRY_VIEWER_WIDGET_HPP_
-#define PV_APP_GEOMETRY_VIEWER_WIDGET_HPP_
+#ifndef QPVT_GEOMETRY_VIEWER_WIDGET_HPP_
+#define QPVT_GEOMETRY_VIEWER_WIDGET_HPP_
 
 #include <memory>
 
@@ -38,14 +38,14 @@
 #include <pvt/rendering/clickable_scene.hpp>
 #include <pvt/rendering/renderable_geometry.hpp>
 
-#include "viewer_widget.hpp"
+#include <qpvt/api.hpp>
+#include <qpvt/widgets/parallel_coordinates_plot_widget.hpp>
+#include <qpvt/widgets/viewer_widget.hpp>
 
-namespace pv_app {
-
-class parallel_coordinates_plot_widget;
+namespace qpvt {
 
 //------------------------------------------------------------------------------
-class geometry_viewer_widget : public QSplitter
+class QPVT_API geometry_viewer_widget : public QSplitter
 {
   Q_OBJECT
 
@@ -107,6 +107,6 @@ geometry_viewer_widget::map_geometric_severities
   }
 }
 
-} // namespace pv_app
+} // namespace qpvt
 
-#endif // #ifndef PV_APP_GEOMETRY_VIEWER_WIDGET_HPP_
+#endif // #ifndef QPVT_GEOMETRY_VIEWER_WIDGET_HPP_
diff --git a/pv_app/src/parallel_coordinates_plot_widget.hpp b/qpvt/include/qpvt/widgets/parallel_coordinates_plot_widget.hpp
similarity index 90%
rename from pv_app/src/parallel_coordinates_plot_widget.hpp
rename to qpvt/include/qpvt/widgets/parallel_coordinates_plot_widget.hpp
index 644b490..4cbca28 100644
--- a/pv_app/src/parallel_coordinates_plot_widget.hpp
+++ b/qpvt/include/qpvt/widgets/parallel_coordinates_plot_widget.hpp
@@ -23,8 +23,8 @@
 // along with this program.  If not, see <http://www.gnu.org/licenses/>.
 //------------------------------------------------------------------------------
 
-#ifndef PV_APP_PARALLEL_COORDINATES_PLOT_WIDGET_HPP_
-#define PV_APP_PARALLEL_COORDINATES_PLOT_WIDGET_HPP_
+#ifndef QPVT_PARALLEL_COORDINATES_PLOT_WIDGET_HPP_
+#define QPVT_PARALLEL_COORDINATES_PLOT_WIDGET_HPP_
 
 #include <memory>
 
@@ -32,6 +32,9 @@
 
 #include <pvt/rendering/renderable_parallel_coordinates_plot.hpp>
 
+#include <qpvt/api.hpp>
+
+class QFrame;
 class QGridLayout;
 class QLabel;
 class QPushButton;
@@ -41,12 +44,12 @@ class camera;
 class scene;
 }
 
-namespace pv_app {
+namespace qpvt {
 
 class viewer_widget;
 
 //------------------------------------------------------------------------------
-class parallel_coordinates_plot_widget : public QWidget
+class QPVT_API parallel_coordinates_plot_widget : public QWidget
 {
   Q_OBJECT
 
@@ -87,6 +90,6 @@ private slots:
   void on_lower_button_clicked(int index);
 };
 
-} // namespace pv_app
+} // namespace qpvt
 
-#endif // #ifndef PV_APP_PARALLEL_COORDINATES_PLOT_WIDGET_HPP_
+#endif // #ifndef QPVT_PARALLEL_COORDINATES_PLOT_WIDGET_HPP_
diff --git a/pv_app/src/perf_data_viewer_widget.hpp b/qpvt/include/qpvt/widgets/perf_data_viewer_widget.hpp
similarity index 92%
rename from pv_app/src/perf_data_viewer_widget.hpp
rename to qpvt/include/qpvt/widgets/perf_data_viewer_widget.hpp
index 766026b..ab73e74 100644
--- a/pv_app/src/perf_data_viewer_widget.hpp
+++ b/qpvt/include/qpvt/widgets/perf_data_viewer_widget.hpp
@@ -23,8 +23,8 @@
 // along with this program.  If not, see <http://www.gnu.org/licenses/>.
 //------------------------------------------------------------------------------
 
-#ifndef PV_APP_PERF_DATA_VIEWER_WIDGET_HPP_
-#define PV_APP_PERF_DATA_VIEWER_WIDGET_HPP_
+#ifndef QPVT_PERF_DATA_VIEWER_WIDGET_HPP_
+#define QPVT_PERF_DATA_VIEWER_WIDGET_HPP_
 
 #include <list>
 
@@ -33,10 +33,11 @@
 #include <pvt/correlated_severity_view.hpp>
 #include <pvt/severity_view.hpp>
 
-#include "cartesian_topology_viewer_widget.hpp"
-#include "correlated_views_model.hpp"
-#include "geometry_viewer_widget.hpp"
-#include "squarified_cushion_treemap_widget.hpp"
+#include <qpvt/api.hpp>
+#include <qpvt/models/correlated_views_model.hpp>
+#include <qpvt/widgets/cartesian_topology_viewer_widget.hpp>
+#include <qpvt/widgets/geometry_viewer_widget.hpp>
+#include <qpvt/widgets/squarified_cushion_treemap_widget.hpp>
 
 class QCheckBox;
 class QItemSelection;
@@ -50,7 +51,7 @@ class camera;
 class perf_data;
 }
 
-namespace pv_app {
+namespace qpvt {
 
 class cnode_impact_selector_widget;
 class cnode_tree_model;
@@ -60,7 +61,7 @@ class metric_tree_model;
 class viewer_widget;
 
 //------------------------------------------------------------------------------
-class perf_data_viewer_widget : public QWidget
+class QPVT_API perf_data_viewer_widget : public QWidget
 {
   Q_OBJECT
   
@@ -164,6 +165,6 @@ private:
   std::vector<QCheckBox*>            m_filter_check_boxes;
 };
 
-} // namespace pv_app
+} // namespace qpvt
 
-#endif // #ifndef PV_APP_PERF_DATA_VIEWER_WIDGET_HPP_
+#endif // #ifndef QPVT_PERF_DATA_VIEWER_WIDGET_HPP_
diff --git a/pv_app/src/range_h_slider.hpp b/qpvt/include/qpvt/widgets/range_h_slider.hpp
similarity index 86%
rename from pv_app/src/range_h_slider.hpp
rename to qpvt/include/qpvt/widgets/range_h_slider.hpp
index 798f466..6135d5b 100644
--- a/pv_app/src/range_h_slider.hpp
+++ b/qpvt/include/qpvt/widgets/range_h_slider.hpp
@@ -23,15 +23,16 @@
 // along with this program.  If not, see <http://www.gnu.org/licenses/>.
 //------------------------------------------------------------------------------
 
-#ifndef PV_APP_RANGE_H_SLIDER_HPP_
-#define PV_APP_RANGE_H_SLIDER_HPP_
+#ifndef QPVT_RANGE_H_SLIDER_HPP_
+#define QPVT_RANGE_H_SLIDER_HPP_
 
-#include "range_slider.hpp"
+#include <qpvt/api.hpp>
+#include <qpvt/widgets/range_slider.hpp>
 
-namespace pv_app {
+namespace qpvt {
 
 //------------------------------------------------------------------------------
-class range_h_slider : public range_slider
+class QPVT_API range_h_slider : public range_slider
 {
   Q_OBJECT
 
@@ -49,6 +50,6 @@ protected:
   slider_handle inside_handle       (const QPointF& pos) const override;
 };
 
-} // namespace pv_app
+} // namespace qpvt
 
-#endif // #ifndef PV_APP_RANGE_H_SLIDER_HPP_
+#endif // #ifndef QPVT_RANGE_H_SLIDER_HPP_
diff --git a/pv_app/src/range_slider.hpp b/qpvt/include/qpvt/widgets/range_slider.hpp
similarity index 95%
rename from pv_app/src/range_slider.hpp
rename to qpvt/include/qpvt/widgets/range_slider.hpp
index 5169010..6c4660b 100644
--- a/pv_app/src/range_slider.hpp
+++ b/qpvt/include/qpvt/widgets/range_slider.hpp
@@ -23,23 +23,23 @@
 // along with this program.  If not, see <http://www.gnu.org/licenses/>.
 //------------------------------------------------------------------------------
 
-#ifndef PV_APP_RANGE_SLIDER_HPP_
-#define PV_APP_RANGE_SLIDER_HPP_
-
-#include <memory>
+#ifndef QPVT_RANGE_SLIDER_HPP_
+#define QPVT_RANGE_SLIDER_HPP_
 
 #include <pvt/optional.hpp>
 #include <pvt/gl/buffer.hpp>
 #include <pvt/gl/shader_program.hpp>
 #include <pvt/gl/vertex_array.hpp>
 
+#include <qpvt/api.hpp>
+
 // Native GL must be included before any other GL.
 #include <QOpenGLWidget>
 
-namespace pv_app {
+namespace qpvt {
 
 //------------------------------------------------------------------------------
-class range_slider : public QOpenGLWidget
+class QPVT_API range_slider : public QOpenGLWidget
 {
   Q_OBJECT
   
@@ -121,6 +121,6 @@ protected:
   pvt::optional<pvt::shader_program> m_cover_shader_program;
 };
 
-} // namespace pv_app
+} // namespace qpvt
 
-#endif // #ifndef PV_APP_RANGE_SLIDER_HPP_
+#endif // #ifndef QPVT_RANGE_SLIDER_HPP_
diff --git a/pv_app/src/range_v_slider.hpp b/qpvt/include/qpvt/widgets/range_v_slider.hpp
similarity index 87%
rename from pv_app/src/range_v_slider.hpp
rename to qpvt/include/qpvt/widgets/range_v_slider.hpp
index a680f3d..4960a2f 100644
--- a/pv_app/src/range_v_slider.hpp
+++ b/qpvt/include/qpvt/widgets/range_v_slider.hpp
@@ -23,15 +23,16 @@
 // along with this program.  If not, see <http://www.gnu.org/licenses/>.
 //------------------------------------------------------------------------------
 
-#ifndef PV_APP_RANGE_V_SLIDER_HPP_
-#define PV_APP_RANGE_V_SLIDER_HPP_
+#ifndef QPVT_RANGE_V_SLIDER_HPP_
+#define QPVT_RANGE_V_SLIDER_HPP_
 
-#include "range_slider.hpp"
+#include <qpvt/api.hpp>
+#include <qpvt/widgets/range_slider.hpp>
 
-namespace pv_app {
+namespace qpvt {
 
 //------------------------------------------------------------------------------
-class range_v_slider : public range_slider
+class QPVT_API range_v_slider : public range_slider
 {
   Q_OBJECT
 
@@ -52,6 +53,6 @@ protected:
   slider_handle inside_handle       (const QPointF& position) const override;
 };
 
-} // namespace pv_app
+} // namespace qpvt
 
-#endif // #ifndef PV_APP_RANGE_V_SLIDER_HPP_
+#endif // #ifndef QPVT_RANGE_V_SLIDER_HPP_
diff --git a/pv_app/src/slice_slider.hpp b/qpvt/include/qpvt/widgets/slice_slider.hpp
similarity index 93%
rename from pv_app/src/slice_slider.hpp
rename to qpvt/include/qpvt/widgets/slice_slider.hpp
index dba29c6..079c3cb 100644
--- a/pv_app/src/slice_slider.hpp
+++ b/qpvt/include/qpvt/widgets/slice_slider.hpp
@@ -23,11 +23,13 @@
 // along with this program.  If not, see <http://www.gnu.org/licenses/>.
 //------------------------------------------------------------------------------
 
-#ifndef PV_APP_SLICE_SLIDER_HPP_
-#define PV_APP_SLICE_SLIDER_HPP_
+#ifndef QPVT_SLICE_SLIDER_HPP_
+#define QPVT_SLICE_SLIDER_HPP_
 
 #include <QWidget>
 
+#include <qpvt/api.hpp>
+
 class QSlider;
 class QVBoxLayout;
 
@@ -37,11 +39,11 @@ class renderable_line_plot_axes;
 class scene;
 }
 
-namespace pv_app {
+namespace qpvt {
 class viewer_widget;
 
 //------------------------------------------------------------------------------
-class slice_slider : public QWidget
+class QPVT_API slice_slider : public QWidget
 {
   Q_OBJECT
   
@@ -99,6 +101,6 @@ private:
   QSlider*                        mp_slider;
 };
 
-} // namespace pv_app
+} // namespace qpvt
 
-#endif // #ifndef PV_APP_SLICE_SLIDER_HPP_
+#endif // #ifndef QPVT_SLICE_SLIDER_HPP_
diff --git a/pv_app/src/squarified_cushion_treemap_widget.hpp b/qpvt/include/qpvt/widgets/squarified_cushion_treemap_widget.hpp
similarity index 91%
rename from pv_app/src/squarified_cushion_treemap_widget.hpp
rename to qpvt/include/qpvt/widgets/squarified_cushion_treemap_widget.hpp
index 7996e6e..72043bd 100644
--- a/pv_app/src/squarified_cushion_treemap_widget.hpp
+++ b/qpvt/include/qpvt/widgets/squarified_cushion_treemap_widget.hpp
@@ -23,8 +23,8 @@
 // along with this program.  If not, see <http://www.gnu.org/licenses/>.
 //------------------------------------------------------------------------------
 
-#ifndef PV_APP_SQUARIFIED_CUSHION_TREEMAP_WIDGET_HPP_
-#define PV_APP_SQUARIFIED_CUSHION_TREEMAP_WIDGET_HPP_
+#ifndef QPVT_SQUARIFIED_CUSHION_TREEMAP_WIDGET_HPP_
+#define QPVT_SQUARIFIED_CUSHION_TREEMAP_WIDGET_HPP_
 
 #include <memory>
 
@@ -34,6 +34,8 @@
 #include <pvt/rendering/treemap_shading_policy_cushion.hpp>
 #include <pvt/rendering/treemap_tessellation_policy_squarified.hpp>
 
+#include <qpvt/api.hpp>
+
 // Native GL must be included before any other GL.
 #include <QOpenGLWidget>
 
@@ -41,7 +43,7 @@ namespace pvt {
 class perf_data;
 }
 
-namespace pv_app {
+namespace qpvt {
 
 typedef pvt::treemap<pvt::cnode,
                      pvt::treemap_tessellation_policy_squarified,
@@ -50,7 +52,7 @@ typedef pvt::treemap<pvt::cnode,
   squarified_cushion_cnode_treemap;
 
 //------------------------------------------------------------------------------
-class squarified_cushion_treemap_widget : public QOpenGLWidget
+class QPVT_API squarified_cushion_treemap_widget : public QOpenGLWidget
 {
   Q_OBJECT
 
@@ -86,6 +88,6 @@ private:
   pvt::metric* mp_cached_metric     = nullptr;
 };
 
-} // namespace pv_app
+} // namespace qpvt
 
-#endif // #ifndef PV_APP_SQUARIFIED_CUSHION_TREEMAP_WIDGET_HPP_
+#endif // #ifndef QPVT_SQUARIFIED_CUSHION_TREEMAP_WIDGET_HPP_
diff --git a/pv_app/src/viewer_widget.hpp b/qpvt/include/qpvt/widgets/viewer_widget.hpp
similarity index 90%
rename from pv_app/src/viewer_widget.hpp
rename to qpvt/include/qpvt/widgets/viewer_widget.hpp
index a30dd02..ce7a568 100644
--- a/pv_app/src/viewer_widget.hpp
+++ b/qpvt/include/qpvt/widgets/viewer_widget.hpp
@@ -23,22 +23,23 @@
 // along with this program.  If not, see <http://www.gnu.org/licenses/>.
 //------------------------------------------------------------------------------
 
-#ifndef PV_APP_VIEWER_WIDGET_HPP_
-#define PV_APP_VIEWER_WIDGET_HPP_
+#ifndef QPVT_VIEWER_WIDGET_HPP_
+#define QPVT_VIEWER_WIDGET_HPP_
 
 #include <QOpenGLWidget>
 
-#include "camera_tools.hpp"
+#include <qpvt/api.hpp>
+#include <qpvt/utility/camera_tools.hpp>
 
 namespace pvt {
 class scene;
 class camera;
 }
 
-namespace pv_app {
+namespace qpvt {
 
 //------------------------------------------------------------------------------
-class viewer_widget : public QOpenGLWidget
+class QPVT_API viewer_widget : public QOpenGLWidget
 {
   Q_OBJECT
   
@@ -88,6 +89,6 @@ private:
   float        m_clear_color[4];
 };
 
-} // namespace pv_app
+} // namespace qpvt
 
-#endif // #ifndef PV_APP_VIEWER_WIDGET_HPP_
+#endif // #ifndef QPVT_VIEWER_WIDGET_HPP_
diff --git a/pv_app/src/directed_variation_glyph_delegate.cpp b/qpvt/src/delegates/directed_variation_glyph_delegate.cpp
similarity index 96%
rename from pv_app/src/directed_variation_glyph_delegate.cpp
rename to qpvt/src/delegates/directed_variation_glyph_delegate.cpp
index adba31b..d64e6ab 100644
--- a/pv_app/src/directed_variation_glyph_delegate.cpp
+++ b/qpvt/src/delegates/directed_variation_glyph_delegate.cpp
@@ -27,10 +27,10 @@
 
 #include <QPainter>
 
-#include "cnode_tree_model.hpp"
-#include "directed_variation_glyph_delegate.hpp"
+#include <qpvt/delegates/directed_variation_glyph_delegate.hpp>
+#include <qpvt/models/cnode_tree_model.hpp>
 
-namespace pv_app {
+namespace qpvt {
 
 //------------------------------------------------------------------------------
 directed_variation_glyph_delegate::directed_variation_glyph_delegate
@@ -130,4 +130,4 @@ const
   return QSize(4,4);
 }
 
-} // namespace pv_app
+} // namespace qpvt
diff --git a/pv_app/src/severity_glyph_delegate.cpp b/qpvt/src/delegates/severity_glyph_delegate.cpp
similarity index 95%
rename from pv_app/src/severity_glyph_delegate.cpp
rename to qpvt/src/delegates/severity_glyph_delegate.cpp
index 41d25ea..94fc1f4 100644
--- a/pv_app/src/severity_glyph_delegate.cpp
+++ b/qpvt/src/delegates/severity_glyph_delegate.cpp
@@ -26,10 +26,10 @@
 #include <QPainter>
 #include <QTreeView>
 
-#include "cnode_tree_model.hpp"
-#include "severity_glyph_delegate.hpp"
+#include <qpvt/delegates/severity_glyph_delegate.hpp>
+#include <qpvt/models/cnode_tree_model.hpp>
 
-namespace pv_app {
+namespace qpvt {
 
 //------------------------------------------------------------------------------
 severity_glyph_delegate::severity_glyph_delegate
@@ -96,4 +96,4 @@ const
   return QSize(4,4);
 }
 
-} // namespace pv_app
+} // namespace qpvt
diff --git a/pv_app/src/cnode_impact_list_model.cpp b/qpvt/src/models/cnode_impact_list_model.cpp
similarity index 99%
rename from pv_app/src/cnode_impact_list_model.cpp
rename to qpvt/src/models/cnode_impact_list_model.cpp
index a5fc46a..8f93dd3 100644
--- a/pv_app/src/cnode_impact_list_model.cpp
+++ b/qpvt/src/models/cnode_impact_list_model.cpp
@@ -34,9 +34,9 @@
 #include <pvt/severity_view.hpp>
 #include <pvt/suitable_3d_view_computer.hpp>
 
-#include "cnode_impact_list_model.hpp"
+#include <qpvt/models/cnode_impact_list_model.hpp>
 
-namespace pv_app {
+namespace qpvt {
 
 //------------------------------------------------------------------------------
 cnode_impact_list_model::cnode_impact_list_model
@@ -433,4 +433,4 @@ const
   return sqrt(variance);
 }
 
-} // namespace pv_app
+} // namespace qpvt
diff --git a/pv_app/src/cnode_tree_model.cpp b/qpvt/src/models/cnode_tree_model.cpp
similarity index 98%
rename from pv_app/src/cnode_tree_model.cpp
rename to qpvt/src/models/cnode_tree_model.cpp
index 4e22534..d3ed660 100644
--- a/pv_app/src/cnode_tree_model.cpp
+++ b/qpvt/src/models/cnode_tree_model.cpp
@@ -25,9 +25,9 @@
 
 #include <pvt/metric.hpp>
 
-#include "cnode_tree_model.hpp"
+#include <qpvt/models/cnode_tree_model.hpp>
 
-namespace pv_app {
+namespace qpvt {
 
 //------------------------------------------------------------------------------
 cnode_tree_model::cnode_tree_model
@@ -142,4 +142,4 @@ const
   return directed_variances;
 }
 
-} // namespace pv_app
+} // namespace qpvt
diff --git a/pv_app/src/correlated_views_model.cpp b/qpvt/src/models/correlated_views_model.cpp
similarity index 97%
rename from pv_app/src/correlated_views_model.cpp
rename to qpvt/src/models/correlated_views_model.cpp
index 7b2b5ad..ecad387 100644
--- a/pv_app/src/correlated_views_model.cpp
+++ b/qpvt/src/models/correlated_views_model.cpp
@@ -27,9 +27,9 @@
 #include <pvt/metric.hpp>
 #include <pvt/perf_data.hpp>
 
-#include "correlated_views_model.hpp"
+#include <qpvt/models/correlated_views_model.hpp>
 
-namespace pv_app {
+namespace qpvt {
 
 //------------------------------------------------------------------------------
 // \todo Find a way to handle multiple selected Metrics, Cnodes
@@ -122,4 +122,4 @@ const
     severity_view.get_metric()->get_unit_of_measurement().c_str();
 }
 
-} // namespace pv_app
+} // namespace qpvt
diff --git a/pv_app/src/metric_tree_model.cpp b/qpvt/src/models/metric_tree_model.cpp
similarity index 97%
rename from pv_app/src/metric_tree_model.cpp
rename to qpvt/src/models/metric_tree_model.cpp
index 467d6a0..672c7c7 100644
--- a/pv_app/src/metric_tree_model.cpp
+++ b/qpvt/src/models/metric_tree_model.cpp
@@ -25,9 +25,9 @@
 
 #include <pvt/metric.hpp>
 
-#include "metric_tree_model.hpp"
+#include <qpvt/models/metric_tree_model.hpp>
 
-namespace pv_app {
+namespace qpvt {
 
 //------------------------------------------------------------------------------
 metric_tree_model::metric_tree_model
@@ -108,4 +108,4 @@ const
   return QVariant();
 };
 
-} // namespace pv_app
+} // namespace qpvt
diff --git a/pv_app/src/camera_tools.cpp b/qpvt/src/utility/camera_tools.cpp
similarity index 98%
rename from pv_app/src/camera_tools.cpp
rename to qpvt/src/utility/camera_tools.cpp
index 0d56541..1580e41 100644
--- a/pv_app/src/camera_tools.cpp
+++ b/qpvt/src/utility/camera_tools.cpp
@@ -27,9 +27,9 @@
 
 #include <pvt/rendering/camera.hpp>
 
-#include "camera_tools.hpp"
+#include <qpvt/utility/camera_tools.hpp>
 
-namespace pv_app {
+namespace qpvt {
 
 //------------------------------------------------------------------------------
 camera_tools::camera_tools
@@ -167,4 +167,4 @@ camera_tools::handle_mouse_release
   return false;
 }
 
-} // namespace pv_app
\ No newline at end of file
+} // namespace qpvt
diff --git a/pv_app/src/cartesian_topology_viewer_widget.cpp b/qpvt/src/widgets/cartesian_topology_viewer_widget.cpp
similarity index 97%
rename from pv_app/src/cartesian_topology_viewer_widget.cpp
rename to qpvt/src/widgets/cartesian_topology_viewer_widget.cpp
index 2ed724a..f644473 100644
--- a/pv_app/src/cartesian_topology_viewer_widget.cpp
+++ b/qpvt/src/widgets/cartesian_topology_viewer_widget.cpp
@@ -42,12 +42,12 @@
 #include <pvt/rendering/renderable_axes.hpp>
 #include <pvt/rendering/scene.hpp>
 
-#include "cartesian_topology_viewer_widget.hpp"
-#include "data_range_h_slider.hpp"
-#include "data_range_v_slider.hpp"
-#include "slice_slider.hpp"
+#include <qpvt/widgets/cartesian_topology_viewer_widget.hpp>
+#include <qpvt/widgets/data_range_h_slider.hpp>
+#include <qpvt/widgets/data_range_v_slider.hpp>
+#include <qpvt/widgets/slice_slider.hpp>
 
-namespace pv_app {
+namespace qpvt {
 
 //------------------------------------------------------------------------------
 cartesian_topology_viewer_widget::cartesian_topology_viewer_widget
@@ -69,6 +69,13 @@ cartesian_topology_viewer_widget::cartesian_topology_viewer_widget
   m_topology_mapping =
     new pvt::data_array<float>(cart_topo_idx.get_num_positions());
   
+  mp_renderable_cartesian_grid = new pvt::renderable_cartesian_grid(
+    Eigen::Vector3f(dimension_sizes[m_projection[0]],
+                    dimension_sizes[m_projection[1]],
+                    dimension_sizes[m_projection[2]]),
+    Eigen::Vector3f(1, 1, 1));
+  mp_renderable_scene->add_renderable(mp_renderable_cartesian_grid);
+
   mp_renderable_axes = new pvt::renderable_axes(Eigen::Vector3i(
     dimension_sizes[m_projection[0]],
     dimension_sizes[m_projection[1]],
@@ -1056,6 +1063,11 @@ cartesian_topology_viewer_widget::dropEvent
 
   mp_renderable_cartesian_topology->set_projection(m_projection);
   
+  mp_renderable_cartesian_grid->set_size(
+    Eigen::Vector3f(dimension_sizes[m_projection[0]],
+                    dimension_sizes[m_projection[1]],
+                    dimension_sizes[m_projection[2]]));
+
   mp_renderable_axes->set_lengths(
     Eigen::Vector3i(
     dimension_sizes[m_projection[0]],
@@ -1068,4 +1080,4 @@ cartesian_topology_viewer_widget::dropEvent
   update_axis_scales ();
 }
 
-} // namespace pv_app
+} // namespace qpvt
diff --git a/pv_app/src/cnode_impact_selector_widget.cpp b/qpvt/src/widgets/cnode_impact_selector_widget.cpp
similarity index 98%
rename from pv_app/src/cnode_impact_selector_widget.cpp
rename to qpvt/src/widgets/cnode_impact_selector_widget.cpp
index 2780b27..bca6bfb 100644
--- a/pv_app/src/cnode_impact_selector_widget.cpp
+++ b/qpvt/src/widgets/cnode_impact_selector_widget.cpp
@@ -41,11 +41,11 @@
 #include <pvt/cartesian_topology.hpp>
 #include <pvt/suitable_3d_view_computer.hpp>
 
-#include "cnode_impact_list_model.hpp"
-#include "cnode_impact_selector_widget.hpp"
-#include "cnode_tree_model.hpp"
+#include <qpvt/models/cnode_impact_list_model.hpp>
+#include <qpvt/models/cnode_tree_model.hpp>
+#include <qpvt/widgets/cnode_impact_selector_widget.hpp>
 
-namespace pv_app {
+namespace qpvt {
 
 //------------------------------------------------------------------------------
 cnode_impact_selector_widget::cnode_impact_selector_widget
@@ -396,5 +396,5 @@ cnode_impact_selector_widget::setup_layout
   mp_layout->addWidget(mp_filter_rows_group_box   );
 }
 
-} // namespace pv_app
+} // namespace qpvt
 
diff --git a/pv_app/src/data_range_h_slider.cpp b/qpvt/src/widgets/data_range_h_slider.cpp
similarity index 99%
rename from pv_app/src/data_range_h_slider.cpp
rename to qpvt/src/widgets/data_range_h_slider.cpp
index e29e59d..1ce0f7a 100644
--- a/pv_app/src/data_range_h_slider.cpp
+++ b/qpvt/src/widgets/data_range_h_slider.cpp
@@ -28,9 +28,9 @@
 #include <pvt/gl/shader.hpp>
 #include <pvt/rendering/shader_strings.hpp>
 
-#include "data_range_h_slider.hpp"
+#include <qpvt/widgets/data_range_h_slider.hpp>
 
-namespace pv_app {
+namespace qpvt {
 
 //------------------------------------------------------------------------------
 data_range_h_slider::data_range_h_slider
@@ -246,4 +246,4 @@ data_range_h_slider::paintGL
   draw_covers_handles();
 }
 
-} // namespace pv_app
+} // namespace qpvt
diff --git a/pv_app/src/data_range_v_slider.cpp b/qpvt/src/widgets/data_range_v_slider.cpp
similarity index 98%
rename from pv_app/src/data_range_v_slider.cpp
rename to qpvt/src/widgets/data_range_v_slider.cpp
index 9d646fa..6d20c5e 100644
--- a/pv_app/src/data_range_v_slider.cpp
+++ b/qpvt/src/widgets/data_range_v_slider.cpp
@@ -28,9 +28,9 @@
 #include <pvt/gl/shader.hpp>
 #include <pvt/rendering/shader_strings.hpp>
 
-#include "data_range_v_slider.hpp"
+#include <qpvt/widgets/data_range_v_slider.hpp>
 
-namespace pv_app {
+namespace qpvt {
 
 //------------------------------------------------------------------------------
 data_range_v_slider::data_range_v_slider
@@ -158,4 +158,4 @@ data_range_v_slider::paintGL
   draw_covers_handles();
 }
 
-} // namespace pv_app
+} // namespace qpvt
diff --git a/pv_app/src/geometry_viewer_widget.cpp b/qpvt/src/widgets/geometry_viewer_widget.cpp
similarity index 98%
rename from pv_app/src/geometry_viewer_widget.cpp
rename to qpvt/src/widgets/geometry_viewer_widget.cpp
index a217716..ccdf0ec 100644
--- a/pv_app/src/geometry_viewer_widget.cpp
+++ b/qpvt/src/widgets/geometry_viewer_widget.cpp
@@ -29,10 +29,10 @@
 
 #include <pvt/rendering/renderable_geometry.hpp>
 
-#include "geometry_viewer_widget.hpp"
-#include "parallel_coordinates_plot_widget.hpp"
+#include <qpvt/widgets/geometry_viewer_widget.hpp>
+#include <qpvt/widgets/parallel_coordinates_plot_widget.hpp>
 
-namespace pv_app {
+namespace qpvt {
 
 //------------------------------------------------------------------------------
 geometry_viewer_widget::geometry_viewer_widget
@@ -201,6 +201,7 @@ void geometry_viewer_widget::update_viewer
     renderable_geometry->set_selected(false);
   for (auto geometry_index : m_selected_indices)
     mp_renderable_geometries[geometry_index]->set_selected(true);
+  mp_viewer_widget->update();
 }
 
 
@@ -376,4 +377,4 @@ geometry_viewer_widget::handle_geometry_selection
   mp_table_widget          ->setFocus();
 
 }
-} // namespace pv_app
+} // namespace qpvt
diff --git a/pv_app/src/parallel_coordinates_plot_widget.cpp b/qpvt/src/widgets/parallel_coordinates_plot_widget.cpp
similarity index 98%
rename from pv_app/src/parallel_coordinates_plot_widget.cpp
rename to qpvt/src/widgets/parallel_coordinates_plot_widget.cpp
index fadb95e..f3c91b6 100644
--- a/pv_app/src/parallel_coordinates_plot_widget.cpp
+++ b/qpvt/src/widgets/parallel_coordinates_plot_widget.cpp
@@ -31,10 +31,10 @@
 #include <pvt/rendering/camera.hpp>
 #include <pvt/rendering/scene.hpp>
 
-#include "parallel_coordinates_plot_widget.hpp"
-#include "viewer_widget.hpp"
+#include <qpvt/widgets/parallel_coordinates_plot_widget.hpp>
+#include <qpvt/widgets/viewer_widget.hpp>
 
-namespace pv_app {
+namespace qpvt {
 
 //------------------------------------------------------------------------------
 parallel_coordinates_plot_widget::parallel_coordinates_plot_widget(QWidget* parent)
@@ -208,4 +208,4 @@ parallel_coordinates_plot_widget::on_lower_button_clicked
   toggle_axis(index, true);
 }
 
-} // namespace pv_app
+} // namespace qpvt
diff --git a/pv_app/src/perf_data_viewer_widget.cpp b/qpvt/src/widgets/perf_data_viewer_widget.cpp
similarity index 98%
rename from pv_app/src/perf_data_viewer_widget.cpp
rename to qpvt/src/widgets/perf_data_viewer_widget.cpp
index 190c5c8..44b9c9d 100644
--- a/pv_app/src/perf_data_viewer_widget.cpp
+++ b/qpvt/src/widgets/perf_data_viewer_widget.cpp
@@ -37,15 +37,15 @@
 #include <pvt/perf_data.hpp>
 #include <pvt/suitable_3d_view_computer.hpp>
 
-#include "cnode_impact_selector_widget.hpp"
-#include "cnode_tree_model.hpp"
-#include "correlated_views_model.hpp"
-#include "directed_variation_glyph_delegate.hpp"
-#include "metric_tree_model.hpp"
-#include "perf_data_viewer_widget.hpp"
-#include "severity_glyph_delegate.hpp"
+#include <qpvt/delegates/directed_variation_glyph_delegate.hpp>
+#include <qpvt/delegates/severity_glyph_delegate.hpp>
+#include <qpvt/models/cnode_tree_model.hpp>
+#include <qpvt/models/correlated_views_model.hpp>
+#include <qpvt/models/metric_tree_model.hpp>
+#include <qpvt/widgets/cnode_impact_selector_widget.hpp>
+#include <qpvt/widgets/perf_data_viewer_widget.hpp>
 
-namespace pv_app {
+namespace qpvt {
 
 //------------------------------------------------------------------------------
 perf_data_viewer_widget::perf_data_viewer_widget
@@ -875,4 +875,4 @@ perf_data_viewer_widget::select_and_focus_on_metric
                             QAbstractItemView::PositionAtCenter);
 }
 
-} // namespace pv_app
\ No newline at end of file
+} // namespace qpvt
diff --git a/pv_app/src/range_h_slider.cpp b/qpvt/src/widgets/range_h_slider.cpp
similarity index 97%
rename from pv_app/src/range_h_slider.cpp
rename to qpvt/src/widgets/range_h_slider.cpp
index c3a2403..6925878 100644
--- a/pv_app/src/range_h_slider.cpp
+++ b/qpvt/src/widgets/range_h_slider.cpp
@@ -23,9 +23,9 @@
 // along with this program.  If not, see <http://www.gnu.org/licenses/>.
 //------------------------------------------------------------------------------
 
-#include "range_h_slider.hpp"
+#include <qpvt/widgets/range_h_slider.hpp>
 
-namespace pv_app {
+namespace qpvt {
 
 //------------------------------------------------------------------------------
 range_h_slider::range_h_slider
@@ -128,4 +128,4 @@ const
   return no_handle;
 }
 
-} // namespace pv_app
+} // namespace qpvt
diff --git a/pv_app/src/range_slider.cpp b/qpvt/src/widgets/range_slider.cpp
similarity index 98%
rename from pv_app/src/range_slider.cpp
rename to qpvt/src/widgets/range_slider.cpp
index 576bfd3..880f52d 100644
--- a/pv_app/src/range_slider.cpp
+++ b/qpvt/src/widgets/range_slider.cpp
@@ -28,9 +28,9 @@
 #include <pvt/gl/shader.hpp>
 #include <pvt/rendering/shader_strings.hpp>
 
-#include "range_slider.hpp"
+#include <qpvt/widgets/range_slider.hpp>
 
-namespace pv_app {
+namespace qpvt {
 
 //------------------------------------------------------------------------------
 range_slider::range_slider
@@ -206,4 +206,4 @@ range_slider::mouseMoveEvent
   handle_cursor_change(p_event->localPos());
 }
 
-} // namespace pv_app
+} // namespace qpvt
diff --git a/pv_app/src/range_v_slider.cpp b/qpvt/src/widgets/range_v_slider.cpp
similarity index 98%
rename from pv_app/src/range_v_slider.cpp
rename to qpvt/src/widgets/range_v_slider.cpp
index 1922d52..88145af 100644
--- a/pv_app/src/range_v_slider.cpp
+++ b/qpvt/src/widgets/range_v_slider.cpp
@@ -27,9 +27,9 @@
 
 #include <QAction>
 
-#include "range_v_slider.hpp"
+#include <qpvt/widgets/range_v_slider.hpp>
 
-namespace pv_app {
+namespace qpvt {
 
 //------------------------------------------------------------------------------
 range_v_slider::range_v_slider
@@ -135,4 +135,4 @@ const
   return no_handle;
 }
 
-} // namespace pv_app
+} // namespace qpvt
diff --git a/pv_app/src/slice_slider.cpp b/qpvt/src/widgets/slice_slider.cpp
similarity index 97%
rename from pv_app/src/slice_slider.cpp
rename to qpvt/src/widgets/slice_slider.cpp
index db9c1d1..79d4548 100644
--- a/pv_app/src/slice_slider.cpp
+++ b/qpvt/src/widgets/slice_slider.cpp
@@ -31,10 +31,10 @@
 #include <pvt/rendering/renderable_line_plot_axes.hpp>
 #include <pvt/rendering/scene.hpp>
 
-#include "slice_slider.hpp"
-#include "viewer_widget.hpp"
+#include <qpvt/widgets/slice_slider.hpp>
+#include <qpvt/widgets/viewer_widget.hpp>
 
-namespace pv_app {
+namespace qpvt {
 
 //------------------------------------------------------------------------------
 slice_slider::slice_slider
@@ -167,4 +167,4 @@ slice_slider::manual_update
   }
 }
 
-} // namespace pv_app
+} // namespace qpvt
diff --git a/pv_app/src/squarified_cushion_treemap_widget.cpp b/qpvt/src/widgets/squarified_cushion_treemap_widget.cpp
similarity index 98%
rename from pv_app/src/squarified_cushion_treemap_widget.cpp
rename to qpvt/src/widgets/squarified_cushion_treemap_widget.cpp
index 1685fdf..33d409b 100644
--- a/pv_app/src/squarified_cushion_treemap_widget.cpp
+++ b/qpvt/src/widgets/squarified_cushion_treemap_widget.cpp
@@ -31,9 +31,9 @@
 #include <pvt/perf_data.hpp>
 #include <pvt/severity_view.hpp>
 
-#include "squarified_cushion_treemap_widget.hpp"
+#include <qpvt/widgets/squarified_cushion_treemap_widget.hpp>
 
-namespace pv_app {
+namespace qpvt {
 
 //------------------------------------------------------------------------------
 squarified_cushion_treemap_widget::squarified_cushion_treemap_widget(
@@ -280,4 +280,4 @@ squarified_cushion_treemap_widget::wheelEvent
   p_wheel_event->accept();
 }
 
-} // namespace pv_app
+} // namespace qpvt
diff --git a/pv_app/src/viewer_widget.cpp b/qpvt/src/widgets/viewer_widget.cpp
similarity index 98%
rename from pv_app/src/viewer_widget.cpp
rename to qpvt/src/widgets/viewer_widget.cpp
index b2a4f9e..19c83eb 100644
--- a/pv_app/src/viewer_widget.cpp
+++ b/qpvt/src/widgets/viewer_widget.cpp
@@ -29,9 +29,9 @@
 #include <pvt/rendering/camera.hpp>
 #include <pvt/rendering/scene.hpp>
 
-#include "viewer_widget.hpp"
+#include <qpvt/widgets/viewer_widget.hpp>
 
-namespace pv_app {
+namespace qpvt {
 
 //------------------------------------------------------------------------------
 viewer_widget::viewer_widget
@@ -139,4 +139,4 @@ viewer_widget::mouseReleaseEvent
   }
 }
 
-} // namespace pv_app
+} // namespace qpvt
-- 
GitLab