1 #ifndef MULTI_GEOMETRY_WIDGET_HPP__ 2 #define MULTI_GEOMETRY_WIDGET_HPP__ 3 4 #include <cstddef> 5 #include <utility> 6 #include <array> 7 8 #include <QWidget> 9 #include <QByteArray> 10 #include <QEvent> 11 12 // 13 // Class MultiGeometryWidget<N, Widget> - Decorate a QWidget type with 14 // switchable geometries 15 // 16 // The abstract base class imbues a Qt Widget type with N alternative 17 // geometries. Sub-classes can initialise the currently selected 18 // geometry and the initial geometries using geometries. To switch 19 // geometry call select_geometry(n) which saves the current geometry 20 // and switches to the n'th saved geometry. 21 // 22 template<std::size_t N, typename Widget=QWidget> 23 class MultiGeometryWidget 24 : public Widget 25 { 26 public: 27 template<typename... Args> MultiGeometryWidget(Args &&...args)28 explicit MultiGeometryWidget (Args&&... args) 29 : Widget {std::forward<Args> (args)...} 30 , current_geometry_ {0} 31 { 32 } 33 34 void geometries (std::size_t current 35 , std::array<QByteArray, N> const& the_geometries = std::array<QByteArray, N> {}) 36 { 37 Q_ASSERT (current < the_geometries.size ()); 38 saved_geometries_ = the_geometries; 39 current_geometry_ = current; 40 Widget::restoreGeometry (saved_geometries_[current_geometry_]); 41 } 42 geometries() const43 std::array<QByteArray, N> const& geometries () const {return saved_geometries_;} current()44 std::size_t current () {return current_geometry_;} 45 46 // Call this to select a new geometry denoted by the 'n' argument, 47 // any actual layout changes should be made in the implementation of 48 // the change_layout operation below. select_geometry(std::size_t n)49 void select_geometry (std::size_t n) 50 { 51 Q_ASSERT (n < N); 52 auto geometry = Widget::saveGeometry (); 53 change_layout (n); 54 saved_geometries_[current_geometry_] = geometry; 55 current_geometry_ = n; 56 57 // Defer restoration of the window geometry until the layour 58 // request event has been processed, this is necessary otherwise 59 // the final geometry may be affected by widgets not shown in the 60 // new layout. 61 desired_geometry_ = saved_geometries_[n]; 62 } 63 64 protected: ~MultiGeometryWidget()65 virtual ~MultiGeometryWidget () {} 66 67 private: 68 // Override this operation to implement any layout changes for the 69 // geometry specified by the argument 'n'. 70 virtual void change_layout (std::size_t n) = 0; 71 event(QEvent * e)72 bool event (QEvent * e) override 73 { 74 auto ret = Widget::event (e); 75 if (QEvent::LayoutRequest == e->type () 76 && desired_geometry_.size ()) 77 { 78 // Restore the new desired geometry and flag that we have done 79 // so by clearing the desired_geometry_ member variable. 80 QByteArray geometry; 81 std::swap (geometry, desired_geometry_); 82 Widget::restoreGeometry (geometry); 83 } 84 return ret; 85 } 86 87 std::size_t current_geometry_; 88 std::array<QByteArray, N> saved_geometries_; 89 QByteArray desired_geometry_; 90 }; 91 92 #endif 93