SDRAngel  4.11.5
Developer docs for <a href="https://github.com/f4exb/sdrangel">SDRangel<\a>, an Open Source Qt5 / OpenGL 3.0+ SDR and signal analyzer frontend to various hardware.
rollupwidget.cpp
Go to the documentation of this file.
1 #include <QEvent>
2 #include <QPainter>
3 #include <QMouseEvent>
4 #include "gui/rollupwidget.h"
5 #include "ui_glspectrumgui.h"
6 
7 RollupWidget::RollupWidget(QWidget* parent) :
8  QWidget(parent),
9  m_highlighted(false),
10  m_contextMenuType(ContextMenuNone),
11  m_streamIndicator("S")
12 {
13  setMinimumSize(250, 150);
14  setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::MinimumExpanding);
15  setBackgroundRole(QPalette::Window);
16 
17  setAutoFillBackground(false);
18  setAttribute(Qt::WA_OpaquePaintEvent, true);
19 
20  // Vorgaben aus der Palette
21  m_titleColor = palette().highlight().color();
22  m_titleTextColor = palette().highlightedText().color();
23 }
24 
25 QByteArray RollupWidget::saveState(int version) const
26 {
27  QByteArray state;
28  QDataStream stream(&state, QIODevice::WriteOnly);
29  int count = 0;
30 
31  for(int i = 0; i < children().count(); ++i) {
32  QWidget* r = qobject_cast<QWidget*>(children()[i]);
33  if(r != NULL)
34  count++;
35  }
36 
37  stream << VersionMarker;
38  stream << version;
39  stream << count;
40 
41  for(int i = 0; i < children().count(); ++i) {
42  QWidget* r = qobject_cast<QWidget*>(children()[i]);
43  if(r != NULL) {
44  stream << r->objectName();
45  if(r->isHidden())
46  stream << (int)0;
47  else stream << (int)1;
48  }
49  }
50 
51  return state;
52 }
53 
54 bool RollupWidget::restoreState(const QByteArray& state, int version)
55 {
56  if(state.isEmpty())
57  return false;
58  QByteArray sd = state;
59  QDataStream stream(&sd, QIODevice::ReadOnly);
60  int marker, v;
61  stream >> marker;
62  stream >> v;
63  if((stream.status() != QDataStream::Ok) || (marker != VersionMarker) || (v != version))
64  return false;
65 
66  int count;
67  stream >> count;
68 
69  if(stream.status() != QDataStream::Ok)
70  return false;
71  for(int i = 0; i < count; ++i) {
72  QString name;
73  int visible;
74 
75  stream >> name;
76  stream >> visible;
77 
78  if(stream.status() != QDataStream::Ok)
79  return false;
80 
81  for(int j = 0; j < children().count(); ++j) {
82  QWidget* r = qobject_cast<QWidget*>(children()[j]);
83  if(r != NULL) {
84  if(r->objectName() == name) {
85  if(visible)
86  r->show();
87  else r->hide();
88  break;
89  }
90  }
91  }
92  }
93 
94  return true;
95 }
96 
97 void RollupWidget::setTitleColor(const QColor& c)
98 {
99  m_titleColor = c;
100  float l = 0.2126*c.redF() + 0.7152*c.greenF() + 0.0722*c.blueF();
101  m_titleTextColor = l < 0.5f ? Qt::white : Qt::black;
102  update();
103 }
104 
105 void RollupWidget::setHighlighted(bool highlighted)
106 {
107  if (m_highlighted != highlighted)
108  {
109  m_highlighted = highlighted;
110  update();
111  }
112 }
113 
115 {
116  QFontMetrics fm(font());
117  int pos = fm.height() + 4;
118 
119  for(int i = 0; i < children().count(); ++i)
120  {
121  QWidget* r = qobject_cast<QWidget*>(children()[i]);
122  if (r != nullptr)
123  {
124  pos += fm.height() + 2;
125 
126  if (!r->isHidden() && (r->windowTitle() != "Basic channel settings") && (r->windowTitle() != "Select device stream"))
127  {
128  r->move(2, pos + 3);
129  int h = 0;
130 
131  if(r->hasHeightForWidth()) {
132  h = r->heightForWidth(width() - 4);
133  } else {
134  h = r->sizeHint().height();
135  }
136 
137  r->resize(width() - 4, h);
138  pos += r->height() + 5;
139  }
140  }
141  }
142 
143  setMinimumHeight(pos);
144  setMaximumHeight(pos);
145 
146  return pos;
147 }
148 
149 void RollupWidget::paintEvent(QPaintEvent*)
150 {
151  QPainter p(this);
152  QColor frame = palette().highlight().color();
153 
154  // Eigenbau
155  QFontMetrics fm(font());
156 
157  p.setRenderHint(QPainter::Antialiasing, true);
158 
159  // Ecken
160  p.setPen(Qt::NoPen);
161  p.setBrush(palette().base());
162  p.drawRect(0, 0, 5, 5);
163  p.drawRect(width() - 5, 0, 5, 5);
164  p.drawRect(0, height() - 5, 5, 5);
165  p.drawRect(width() - 5, height() - 5, 5, 5);
166 
167  // Rahmen
168  p.setPen(m_highlighted ? Qt::white : frame);
169  p.setBrush(palette().window());
170  QRectF r(rect());
171  r.adjust(0.5, 0.5, -0.5, -0.5);
172  p.drawRoundedRect(r, 3.0, 3.0, Qt::AbsoluteSize);
173 
174  // Titel-Hintergrund
175  p.setPen(Qt::NoPen);
176  p.setBrush(m_titleColor);
177  QPainterPath path;
178  path.moveTo(1.5, fm.height() + 2.5);
179  path.lineTo(width() - 1.5, fm.height() + 2.5);
180  path.lineTo(width() - 1.5, 3.5);
181  path.arcTo(QRectF(width() - 3.5, 0, 2.5, 2.5), 270, -90);
182  path.lineTo(3.5, 1.5);
183  path.arcTo(QRectF(1.5, 2.5, 2.5, 2.5), 90, 90);
184  p.drawPath(path);
185 
186  // Titel-Abschlusslinie
187  p.setPen(frame);
188  p.drawLine(QPointF(0.5, 2 + fm.height() + 1.5), QPointF(width() - 1.5, 2 + fm.height() + 1.5));
189 
190  // Aktiv-Button links
191  p.setPen(QPen(palette().windowText().color(), 1.0));
192  p.setBrush(palette().light());
193  p.drawRoundedRect(QRectF(3.5, 3.5, fm.ascent(), fm.ascent()), 2.0, 2.0, Qt::AbsoluteSize);
194  p.setPen(QPen(Qt::white, 1.0));
195  p.drawText(QRectF(3.5, 2.5, fm.ascent(), fm.ascent()), Qt::AlignCenter, "c");
196 
197  // Stromkanal-Button links
198  p.setPen(QPen(palette().windowText().color(), 1.0));
199  p.setBrush(palette().light());
200  p.drawRoundedRect(QRectF(5.5 + fm.ascent(), 2.5, fm.ascent() + 2.0, fm.ascent() + 2.0), 2.0, 2.0, Qt::AbsoluteSize);
201  p.setPen(QPen(Qt::white, 1.0));
202  p.drawText(QRectF(5.5 + fm.ascent(), 2.5, fm.ascent() + 2.0, fm.ascent() + 2.0), Qt::AlignCenter, m_streamIndicator);
203 
204  // Schließen-Button rechts
205  p.setRenderHint(QPainter::Antialiasing, true);
206  p.setPen(QPen(palette().windowText().color(), 1.0));
207  p.setBrush(palette().light());
208  r = QRectF(width() - 3.5 - fm.ascent(), 3.5, fm.ascent(), fm.ascent());
209  p.drawRoundedRect(r, 2.0, 2.0, Qt::AbsoluteSize);
210  p.setPen(QPen(palette().windowText().color(), 1.5));
211  p.drawLine(r.topLeft() + QPointF(1, 1), r.bottomRight() + QPointF(-1, -1));
212  p.drawLine(r.bottomLeft() + QPointF(1, -1), r.topRight() + QPointF(-1, 1));
213 
214  // Titel
215  //p.setPen(palette().highlightedText().color());
216  p.setPen(m_titleTextColor);
217  p.drawText(QRect(2 + 2*fm.height() + 2, 2, width() - 6 - 3*fm.height(), fm.height()),
218  fm.elidedText(windowTitle(), Qt::ElideMiddle, width() - 6 - 3*fm.height(), 0));
219 
220  // Rollups
221  int pos = fm.height() + 4;
222 
223  const QObjectList& c = children();
224  QObjectList::ConstIterator w = c.begin();
225  QObjectList::ConstIterator n = c.begin();
226 
227  for(n = c.begin(); n != c.end(); ++n) {
228  if(qobject_cast<QWidget*>(*n) != NULL)
229  break;
230  }
231  for(w = n; w != c.end(); w = n) {
232  if(n != c.end())
233  ++n;
234  for(; n != c.end(); ++n) {
235  if(qobject_cast<QWidget*>(*n) != NULL)
236  break;
237  }
238  pos += paintRollup(qobject_cast<QWidget*>(*w), pos, &p, n == c.end(), frame);
239  }
240 }
241 
242 int RollupWidget::paintRollup(QWidget* rollup, int pos, QPainter* p, bool last, const QColor& frame)
243 {
244  if ((rollup->windowTitle() == "Basic channel settings") || (rollup->windowTitle() == "Select device stream")) {
245  return 0;
246  }
247 
248  QFontMetrics fm(font());
249  int height = 1;
250 
251  // Titel-Abschlusslinie
252  if(!rollup->isHidden()) {
253  p->setPen(palette().dark().color());
254  p->drawLine(QPointF(1.5, pos + fm.height() + 1.5), QPointF(width() - 1.5, pos + fm.height() + 1.5));
255  p->setPen(palette().light().color());
256  p->drawLine(QPointF(1.5, pos + fm.height() + 2.5), QPointF(width() - 1.5, pos + fm.height() + 2.5));
257  height += 2;
258  } else {
259  if(!last) {
260  p->setPen(frame);
261  p->drawLine(QPointF(1.5, pos + fm.height() + 1.5), QPointF(width() - 1.5, pos + fm.height() + 1.5));
262  height++;
263  }
264  }
265 
266  // Titel
267  p->setPen(palette().windowText().color());
268  p->drawText(QRect(2 + fm.height(), pos, width() - 4 - fm.height(), fm.height()),
269  fm.elidedText(rollup->windowTitle(), Qt::ElideMiddle, width() - 4 - fm.height(), 0));
270  height += fm.height();
271 
272  // Ausklapp-Icon
273  p->setPen(palette().windowText().color());
274  p->setBrush(palette().windowText());
275  if(!rollup->isHidden()) {
276  QPolygonF a;
277  a.append(QPointF(3.5, pos + 2));
278  a.append(QPointF(3.5 + fm.ascent(), pos + 2));
279  a.append(QPointF(3.5 + fm.ascent() / 2.0, pos + fm.height() - 2));
280  p->drawPolygon(a);
281  } else {
282  QPolygonF a;
283  a.append(QPointF(3.5, pos + 2));
284  a.append(QPointF(3.5, pos + fm.height() - 2));
285  a.append(QPointF(3.5 + fm.ascent(), pos + fm.height() / 2));
286  p->drawPolygon(a);
287  }
288 
289  // Inhalt
290  if(!rollup->isHidden() && (!last)) {
291  // Rollup-Abschlusslinie
292  p->setPen(frame);
293  p->drawLine(QPointF(1.5, pos + fm.height() + rollup->height() + 6.5),
294  QPointF(width() - 1.5, pos + fm.height() + rollup->height() + 6.5));
295  height += rollup->height() + 4;
296  }
297 
298  return height;
299 }
300 
301 void RollupWidget::resizeEvent(QResizeEvent* size)
302 {
303  arrangeRollups();
304  QWidget::resizeEvent(size);
305 }
306 
308 {
309  QFontMetrics fm(font());
310 
311  // menu box left
312  if (QRectF(3.5, 3.5, fm.ascent(), fm.ascent()).contains(event->pos()))
313  {
315  emit customContextMenuRequested(event->globalPos());
316  return;
317  }
318 
319  // Stream channel menu left
320  if (QRectF(5.5 + fm.ascent(), 2.5, fm.ascent() + 2.0, fm.ascent() + 2.0).contains(event->pos()))
321  {
323  emit customContextMenuRequested(event->globalPos());
324  return;
325  }
326 
327  // close button right
328  if(QRectF(width() - 3.5 - fm.ascent(), 3.5, fm.ascent(), fm.ascent()).contains(event->pos())) {
329  close();
330  return;
331  }
332 
333  // check if we need to change a rollup widget
334  int pos = fm.height() + 4;
335  for(int i = 0; i < children().count(); ++i) {
336  QWidget* r = qobject_cast<QWidget*>(children()[i]);
337  if(r != NULL) {
338  if((event->y() >= pos) && (event->y() < (pos + fm.height() + 3))) {
339  if(r->isHidden()) {
340  r->show();
341  //emit widgetRolled(r, true);
342  } else {
343  r->hide();
344  //emit widgetRolled(r, false);
345  }
346  arrangeRollups();
347  repaint();
348  return;
349  } else {
350  pos += fm.height() + 2;
351  if(!r->isHidden())
352  pos += r->height() + 5;
353  }
354  }
355  }
356 }
357 
359 {
360  if(event->type() == QEvent::ChildAdded) {
361  ((QChildEvent*)event)->child()->installEventFilter(this);
362  arrangeRollups();
363  } else if(event->type() == QEvent::ChildRemoved) {
364  ((QChildEvent*)event)->child()->removeEventFilter(this);
365  arrangeRollups();
366  }
367  return QWidget::event(event);
368 }
369 
370 bool RollupWidget::eventFilter(QObject* object, QEvent* event)
371 {
372  if(event->type() == QEvent::Show) {
373  if(children().contains(object)) {
374  arrangeRollups();
375  emit widgetRolled(qobject_cast<QWidget*>(object), true);
376  }
377  } else if(event->type() == QEvent::Hide) {
378  if(children().contains(object)) {
379  arrangeRollups();
380  emit widgetRolled(qobject_cast<QWidget*>(object), false);
381  }
382  } else if(event->type() == QEvent::WindowTitleChange) {
383  if(children().contains(object))
384  repaint();
385  }
386  return QWidget::eventFilter(object, event);
387 }
388 
389 void RollupWidget::setStreamIndicator(const QString& indicator)
390 {
391  m_streamIndicator = indicator;
392  update();
393 }
bool restoreState(const QByteArray &state, int version=0)
QColor m_titleTextColor
Definition: rollupwidget.h:31
void paintEvent(QPaintEvent *)
int arrangeRollups()
bool event(QEvent *event)
ContextMenuType m_contextMenuType
Definition: rollupwidget.h:33
QColor m_titleColor
Definition: rollupwidget.h:30
RollupWidget(QWidget *parent=NULL)
Definition: rollupwidget.cpp:7
void setTitleColor(const QColor &c)
QByteArray saveState(int version=0) const
bool eventFilter(QObject *object, QEvent *event)
int32_t i
Definition: decimators.h:244
int paintRollup(QWidget *rollup, int pos, QPainter *p, bool last, const QColor &frame)
void mousePressEvent(QMouseEvent *event)
void setStreamIndicator(const QString &indicator)
void setHighlighted(bool highlighted)
void resizeEvent(QResizeEvent *size)
void widgetRolled(QWidget *widget, bool rollDown)
bool m_highlighted
Definition: rollupwidget.h:32
QString m_streamIndicator
Definition: rollupwidget.h:34