BornAgain  1.19.0
Simulate and fit neutron and x-ray scattering at grazing incidence
detailswidget.cpp
Go to the documentation of this file.
1 /****************************************************************************
2 **
3 ** Copyright (C) 2016 The Qt Company Ltd.
4 ** Contact: https://www.qt.io/licensing/
5 **
6 ** This file is part of Qt Creator.
7 **
8 ** Commercial License Usage
9 ** Licensees holding valid commercial Qt licenses may use this file in
10 ** accordance with the commercial license agreement provided with the
11 ** Software or, alternatively, in accordance with the terms contained in
12 ** a written agreement between you and The Qt Company. For licensing terms
13 ** and conditions see https://www.qt.io/terms-conditions. For further
14 ** information use the contact form at https://www.qt.io/contact-us.
15 **
16 ** GNU General Public License Usage
17 ** Alternatively, this file may be used under the terms of the GNU
18 ** General Public License version 3 as published by the Free Software
19 ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
20 ** included in the packaging of this file. Please review the following
21 ** information to ensure the GNU General Public License requirements will
22 ** be met: https://www.gnu.org/licenses/gpl-3.0.html.
23 **
24 ****************************************************************************/
25 
29 
30 #include <QApplication>
31 #include <QCheckBox>
32 #include <QGridLayout>
33 #include <QLabel>
34 #include <QPainter>
35 #include <QScrollArea>
36 #include <QStyle>
37 #include <qglobal.h>
38 /*!
39  \class Utils::DetailsWidget
40 
41  \brief The DetailsWidget class implements a button to expand a \e Details
42  area.
43 
44  This widget is using a grid layout and places the items
45  in the following way:
46 
47  \code
48 +------------+-------------------------+---------------+
49 +summaryLabel| toolwidget | detailsButton |
50 +------------+-------------------------+---------------+
51 + additional summary |
52 +------------+-------------------------+---------------+
53 | widget |
54 +------------+-------------------------+---------------+
55  \endcode
56 */
57 
58 namespace {
59 const bool FlatProjectsMode(false);
60 }
61 
62 namespace Utils {
63 
64 const int MARGIN = 8;
65 
67 public:
68  DetailsWidgetPrivate(QWidget* parent);
69 
70  void updateControls();
71  void changeHoverState(bool hovered);
72 
73  QWidget* q;
75  QGridLayout* m_grid;
77  QLabel* m_summaryLabel;
78  QCheckBox* m_summaryCheckBox;
81  QWidget* m_widget;
82 
85 
87  bool m_hovered;
89 };
90 
92  : q(parent)
93  , m_detailsButton(new DetailsButton)
94  , m_grid(new QGridLayout)
95  , m_summaryLabelIcon(new QLabel(parent))
96  , m_summaryLabel(new QLabel(parent))
97  , m_summaryCheckBox(new QCheckBox(parent))
98  , m_additionalSummaryLabel(new QLabel(parent))
99  , m_toolWidget(nullptr)
100  , m_widget(nullptr)
101  , m_state(DetailsWidget::Collapsed)
102  , m_hovered(false)
103  , m_useCheckBox(false)
104 {
105  QHBoxLayout* summaryLayout = new QHBoxLayout;
106  summaryLayout->setContentsMargins(MARGIN, MARGIN, MARGIN, MARGIN);
107  summaryLayout->setSpacing(0);
108 
109  m_summaryLabelIcon->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
110  m_summaryLabelIcon->setContentsMargins(0, 0, 0, 0);
111  m_summaryLabelIcon->setFixedWidth(0);
112  summaryLayout->addWidget(m_summaryLabelIcon);
113 
114  m_summaryLabel->setTextInteractionFlags(Qt::TextSelectableByMouse | Qt::LinksAccessibleByMouse);
115  m_summaryLabel->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Minimum);
116  m_summaryLabel->setContentsMargins(0, 0, 0, 0);
117  summaryLayout->addWidget(m_summaryLabel);
118 
119  m_summaryCheckBox->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Minimum);
120  m_summaryCheckBox->setAttribute(
121  Qt::WA_LayoutUsesWidgetRect); /* broken layout on mac otherwise */
122  m_summaryCheckBox->setVisible(false);
123  m_summaryCheckBox->setContentsMargins(0, 0, 0, 0);
124  summaryLayout->addWidget(m_summaryCheckBox);
125 
126  m_additionalSummaryLabel->setTextInteractionFlags(Qt::TextSelectableByMouse);
127  m_additionalSummaryLabel->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Minimum);
128  m_additionalSummaryLabel->setContentsMargins(MARGIN, MARGIN, MARGIN, MARGIN);
129  m_additionalSummaryLabel->setWordWrap(true);
130  m_additionalSummaryLabel->setVisible(false);
131 
132  m_grid->setContentsMargins(0, 0, 0, 0);
133  m_grid->setSpacing(0);
134  m_grid->addLayout(summaryLayout, 0, 0);
135  m_grid->addWidget(m_detailsButton, 0, 2);
136  m_grid->addWidget(m_additionalSummaryLabel, 1, 0, 1, 3);
137 }
138 
139 QPixmap DetailsWidget::createBackground(const QSize& size, int topHeight, QWidget* widget)
140 {
141  QPixmap pixmap(size);
142  pixmap.fill(Qt::transparent);
143  QPainter p(&pixmap);
144 
145  QRect topRect(0, 0, size.width(), topHeight);
146  QRect fullRect(0, 0, size.width(), size.height());
148  p.fillRect(fullRect, QApplication::palette().window().color());
149  else
150  p.fillRect(fullRect, QApplication::palette().window().color());
151 
152  if (!FlatProjectsMode) {
153  QLinearGradient lg(topRect.topLeft(), topRect.bottomLeft());
154  // lg.setStops(creatorTheme()->gradient(Theme::DetailsWidgetHeaderGradient));
155 
156  lg.setCoordinateMode(QGradient::ObjectBoundingMode);
157  lg.setFinalStop(0, 1);
158  // if (!checked) {
159  // lg.setColorAt(0, QColor(0, 0, 0, 10));
160  // lg.setColorAt(1, QColor(0, 0, 0, 16));
161  // } else {
162  lg.setColorAt(0, QColor(255, 255, 255, 0));
163  lg.setColorAt(1, QColor(255, 255, 255, 50));
164  // }
165 
166  p.fillRect(topRect, lg);
167  p.setRenderHint(QPainter::Antialiasing, true);
168  p.translate(0.5, 0.5);
169  p.setPen(QColor(0, 0, 0, 40));
170  p.setBrush(Qt::NoBrush);
171  p.drawRoundedRect(fullRect.adjusted(0, 0, -1, -1), 2, 2);
172  p.setBrush(Qt::NoBrush);
173  p.setPen(QColor(255, 255, 255, 140));
174  p.drawRoundedRect(fullRect.adjusted(1, 1, -2, -2), 2, 2);
175  p.setPen(QPen(widget->palette().color(QPalette::Mid)));
176  }
177 
178  return pixmap;
179 }
180 
182 {
183  if (m_widget)
192 
193  for (QWidget* w = q; w; w = w->parentWidget()) {
194  if (w->layout())
195  w->layout()->activate();
196  if (QScrollArea* area = qobject_cast<QScrollArea*>(w)) {
197  QEvent e(QEvent::LayoutRequest);
198  QCoreApplication::sendEvent(area, &e);
199  }
200  }
201 }
202 
204 {
205  if (!m_toolWidget)
206  return;
208  m_toolWidget->setOpacity(hovered ? 1.0 : 0);
209  else
210  m_toolWidget->fadeTo(hovered ? 1.0 : 0);
211  m_hovered = hovered;
212 }
213 
214 DetailsWidget::DetailsWidget(QWidget* parent) : QWidget(parent), d(new DetailsWidgetPrivate(this))
215 {
216  setLayout(d->m_grid);
217 
218  setUseCheckBox(false);
219 
220  connect(d->m_detailsButton, &QAbstractButton::toggled, this, &DetailsWidget::setExpanded);
221  connect(d->m_summaryCheckBox, &QAbstractButton::toggled, this, &DetailsWidget::checked);
222  connect(d->m_summaryLabel, &QLabel::linkActivated, this, &DetailsWidget::linkActivated);
223  d->updateControls();
224 }
225 
227 {
228  delete d;
229 }
230 
232 {
233  return d->m_useCheckBox;
234 }
235 
237 {
238  d->m_useCheckBox = b;
239  d->updateControls();
240 }
241 
243 {
244  d->m_summaryCheckBox->setChecked(b);
245 }
246 
248 {
249  return d->m_useCheckBox && d->m_summaryCheckBox->isChecked();
250 }
251 
253 {
254  QFont f;
255  f.setBold(b);
256  d->m_summaryCheckBox->setFont(f);
257  d->m_summaryLabel->setFont(f);
258 }
259 
260 void DetailsWidget::setIcon(const QIcon& icon)
261 {
262  int iconSize = style()->pixelMetric(QStyle::PM_ButtonIconSize, 0, this);
263  d->m_summaryLabelIcon->setFixedWidth(icon.isNull() ? 0 : iconSize);
264  d->m_summaryLabelIcon->setPixmap(icon.pixmap(iconSize, iconSize));
265  d->m_summaryCheckBox->setIcon(icon);
266 }
267 
268 void DetailsWidget::paintEvent(QPaintEvent* paintEvent)
269 {
270  QWidget::paintEvent(paintEvent);
271 
272  QPainter p(this);
273 
274  QWidget* topLeftWidget = d->m_useCheckBox ? static_cast<QWidget*>(d->m_summaryCheckBox)
275  : static_cast<QWidget*>(d->m_summaryLabelIcon);
276  QPoint topLeft(topLeftWidget->geometry().left() - MARGIN, contentsRect().top());
277  const QRect paintArea(topLeft, contentsRect().bottomRight());
278 
279  int topHeight = d->m_useCheckBox ? d->m_summaryCheckBox->height() : d->m_summaryLabel->height();
281  || d->m_state == DetailsWidget::Collapsed) // Details Button is shown
282  topHeight = qMax(d->m_detailsButton->height(), topHeight);
283 
284  if (d->m_state == Collapsed) {
285  if (d->m_collapsedPixmap.isNull() || d->m_collapsedPixmap.size() != size())
286  d->m_collapsedPixmap = createBackground(paintArea.size(), topHeight, this);
287  p.drawPixmap(paintArea, d->m_collapsedPixmap);
288  } else {
289  if (d->m_expandedPixmap.isNull() || d->m_expandedPixmap.size() != size())
290  d->m_expandedPixmap = createBackground(paintArea.size(), topHeight, this);
291  p.drawPixmap(paintArea, d->m_expandedPixmap);
292  }
293 }
294 
295 void DetailsWidget::enterEvent(QEvent* event)
296 {
297  QWidget::enterEvent(event);
298  d->changeHoverState(true);
299 }
300 
301 void DetailsWidget::leaveEvent(QEvent* event)
302 {
303  QWidget::leaveEvent(event);
304  d->changeHoverState(false);
305 }
306 
307 void DetailsWidget::setSummaryText(const QString& text)
308 {
309  if (d->m_useCheckBox)
310  d->m_summaryCheckBox->setText(text);
311  else
312  d->m_summaryLabel->setText(text);
313 }
314 
316 {
317  if (d->m_useCheckBox)
318  return d->m_summaryCheckBox->text();
319  return d->m_summaryLabel->text();
320 }
321 
323 {
324  return d->m_additionalSummaryLabel->text();
325 }
326 
328 {
329  d->m_additionalSummaryLabel->setText(text);
330  d->m_additionalSummaryLabel->setVisible(!text.isEmpty());
331 }
332 
334 {
335  return d->m_state;
336 }
337 
339 {
340  if (state == d->m_state)
341  return;
342  d->m_state = state;
343  d->updateControls();
344  emit expanded(d->m_state == Expanded);
345 }
346 
347 void DetailsWidget::setExpanded(bool expanded)
348 {
350 }
351 
352 QWidget* DetailsWidget::widget() const
353 {
354  return d->m_widget;
355 }
356 
358 {
359  QWidget* widget = d->m_widget;
360  d->m_widget = 0;
361  d->m_grid->removeWidget(widget);
362  if (widget)
363  widget->setParent(0);
364  return widget;
365 }
366 
367 void DetailsWidget::setWidget(QWidget* widget)
368 {
369  if (d->m_widget == widget)
370  return;
371 
372  if (d->m_widget) {
373  d->m_grid->removeWidget(d->m_widget);
374  delete d->m_widget;
375  }
376 
377  d->m_widget = widget;
378 
379  if (d->m_widget) {
380  d->m_widget->setContentsMargins(MARGIN, MARGIN, MARGIN, MARGIN);
381  d->m_grid->addWidget(d->m_widget, 2, 0, 1, 3);
382  }
383  d->updateControls();
384 }
385 
387 {
388  if (d->m_toolWidget == widget)
389  return;
390 
391  d->m_toolWidget = widget;
392 
393  if (!d->m_toolWidget)
394  return;
395 
396  d->m_toolWidget->adjustSize();
397  d->m_grid->addWidget(d->m_toolWidget, 0, 1, 1, 1, Qt::AlignRight);
398 
400  d->m_toolWidget->setOpacity(1.0);
402 }
403 
405 {
406  return d->m_toolWidget;
407 }
408 
409 } // namespace Utils
static bool isMacHost()
Definition: hostosinfo.h:69
DetailsButton * m_detailsButton
DetailsWidgetPrivate(QWidget *parent)
DetailsWidget::State m_state
void changeHoverState(bool hovered)
void setIcon(const QIcon &icon)
void setState(State state)
DetailsWidget(QWidget *parent=0)
void setSummaryFontBold(bool b)
void setAdditionalSummaryText(const QString &text)
void setWidget(QWidget *widget)
QWidget * toolWidget() const
QString additionalSummaryText
Definition: detailswidget.h:40
void linkActivated(const QString &link)
virtual void enterEvent(QEvent *event)
static QPixmap createBackground(const QSize &size, int topHeight, QWidget *widget)
void setToolWidget(FadingPanel *widget)
virtual void leaveEvent(QEvent *event)
void setUseCheckBox(bool b)
DetailsWidgetPrivate * d
Definition: detailswidget.h:93
virtual void paintEvent(QPaintEvent *paintEvent)
void setSummaryText(const QString &text)
QWidget * widget() const
virtual void setOpacity(qreal value)=0
virtual void fadeTo(qreal value)=0
Defines Utils namespace.
const int MARGIN