LeechCraft  0.6.70-16373-g319c272718
Modular cross-platform feature rich live environment.
statesaver.cpp
Go to the documentation of this file.
1 /**********************************************************************
2  * LeechCraft - modular cross-platform feature rich internet client.
3  * Copyright (C) 2006-2014 Georg Rudoy
4  *
5  * Distributed under the Boost Software License, Version 1.0.
6  * (See accompanying file LICENSE or copy at https://www.boost.org/LICENSE_1_0.txt)
7  **********************************************************************/
8 
9 #include "statesaver.h"
10 #include <numeric>
11 #include <QHeaderView>
12 #include <QSplitter>
14 #include <util/sll/throttle.h>
15 #include <util/sll/visitor.h>
16 #include <xmlsettingsdialog/basesettingsmanager.h>
17 
18 namespace LC::Util
19 {
20  namespace
21  {
22  QList<int> RedistributeWidths (int totalWidth, const Widths& widths)
23  {
24  const int occupiedWidth = std::accumulate (widths.begin (), widths.end (), 0,
25  [] (auto acc, auto elem) { return acc + elem.value_or (0); });
26  const int missingCount = std::count (widths.begin (), widths.end (), std::nullopt);
27 
28  const auto widthPerMissing = missingCount ?
29  std::max (1, (totalWidth - occupiedWidth) / missingCount) :
30  0;
31 
32  QList<int> result;
33  result.reserve (widths.size ());
34  for (const auto& w : widths)
35  result << w.value_or (widthPerMissing);
36  return result;
37  }
38 
39  QList<int> RedistributeWidths (int totalWidth, const Factors& factors)
40  {
41  const auto totalFactors = std::accumulate (factors.begin (), factors.end (), 0);
42 
43  QList<int> result;
44  result.reserve (factors.size ());
45  for (auto size : factors)
46  result << size * totalWidth / totalFactors;
47  return result;
48  }
49 
50  QList<int> RedistributeWidths (int totalWidth, const InitialDistr& initial)
51  {
52  return Visit (initial, [&] (const auto& value) { return RedistributeWidths (totalWidth, value); });
53  }
54 
55  QList<int> FromVariantList (const QVariantList& list)
56  {
57  QList<int> result;
58  result.reserve (list.size ());
59  for (const auto& var : list)
60  {
61  bool ok = true;
62  result << var.toInt (&ok);
63  if (!ok)
64  return {};
65  }
66  return result;
67  }
68 
69  QVariantList ToVariantList (const QList<int>& list)
70  {
71  QVariantList result;
72  result.reserve (list.size ());
73  for (auto num : list)
74  result << num;
75  return result;
76  }
77 
78  template<typename F>
79  auto SingleRun (F&& f)
80  {
81  return [f = std::forward<F> (f)] (QEvent*, QObject& pThis) mutable
82  {
83  std::invoke (std::forward<F> (f));
84  pThis.deleteLater ();
85  return false;
86  };
87  }
88 
89  template<typename F>
90  void OnResize (QWidget& widget, F&& f)
91  {
92  widget.installEventFilter (MakeLambdaEventFilter<QEvent::Resize> (SingleRun (std::move (f)), widget));
93  }
94  }
95 
96  void SetupStateSaver (QSplitter& splitter, const StateSaverParams& params)
97  {
98  OnResize (splitter,
99  [&splitter, params]
100  {
101  auto widths = FromVariantList (params.XSM_.Property (params.Id_, {}).value<QVariantList> ());
102  if (widths.isEmpty ())
103  widths = RedistributeWidths (splitter.width (), params.Initial_);
104  splitter.setSizes (widths);
105  });
106 
107  using namespace std::chrono_literals;
108  QObject::connect (&splitter,
109  &QSplitter::splitterMoved,
110  Throttled (1s, &splitter,
111  [&xsm = params.XSM_, id = params.Id_, &splitter]
112  {
113  xsm.setProperty (id.c_str (), ToVariantList (splitter.sizes ()));
114  }));
115  }
116 
117  void SetupStateSaver (QHeaderView& header, const StateSaverParams& params)
118  {
119  OnResize (header,
120  [&header, params]
121  {
122  const auto state = params.XSM_.Property (params.Id_, QByteArray {}).toByteArray ();
123  if (state.isEmpty () || !header.restoreState (state))
124  {
125  const auto scrollWidth = header.style ()->pixelMetric (QStyle::PM_ScrollBarExtent);
126  const auto slack = 10;
127  const auto totalWidth = header.width () - scrollWidth - slack;
128  const auto& widths = RedistributeWidths (totalWidth, params.Initial_);
129  for (int i = 0; i < widths.size (); ++i)
130  header.resizeSection (i, widths.at (i));
131  }
132  });
133 
134  using namespace std::chrono_literals;
135  const auto saver = Throttled (5s, &header,
136  [&xsm = params.XSM_, id = params.Id_, &header] { xsm.setProperty (id.c_str (), header.saveState ()); });
137  QObject::connect (&header,
138  &QHeaderView::sectionMoved,
139  saver);
140  QObject::connect (&header,
141  &QHeaderView::sectionResized,
142  saver);
143  }
144 }
constexpr detail::AggregateType< detail::AggregateFunction::Count, Ptr > count
Definition: oral.h:965
void SetupStateSaver(QSplitter &splitter, const StateSaverParams &params)
Definition: statesaver.cpp:96
constexpr detail::AggregateType< detail::AggregateFunction::Max, Ptr > max
Definition: oral.h:971
BaseSettingsManager & XSM_
Definition: statesaver.h:38
std::variant< Widths, Factors > InitialDistr
Definition: statesaver.h:34
auto Visit(const Either< Left, Right > &either, Args &&... args)
Definition: either.h:215
constexpr detail::ExprTree< detail::ExprType::LeafStaticPlaceholder, detail::MemberPtrs< Ptr > > f
Definition: oral.h:951
auto Throttled(std::chrono::milliseconds ms, QObject *parent, F &&f)
Definition: throttle.h:16