Developer Documentation
ValenceHistogramWidget.cc
1 /*===========================================================================*\
2 * *
3 * OpenFlipper *
4  * Copyright (c) 2001-2015, RWTH-Aachen University *
5  * Department of Computer Graphics and Multimedia *
6  * All rights reserved. *
7  * www.openflipper.org *
8  * *
9  *---------------------------------------------------------------------------*
10  * This file is part of OpenFlipper. *
11  *---------------------------------------------------------------------------*
12  * *
13  * Redistribution and use in source and binary forms, with or without *
14  * modification, are permitted provided that the following conditions *
15  * are met: *
16  * *
17  * 1. Redistributions of source code must retain the above copyright notice, *
18  * this list of conditions and the following disclaimer. *
19  * *
20  * 2. Redistributions in binary form must reproduce the above copyright *
21  * notice, this list of conditions and the following disclaimer in the *
22  * documentation and/or other materials provided with the distribution. *
23  * *
24  * 3. Neither the name of the copyright holder nor the names of its *
25  * contributors may be used to endorse or promote products derived from *
26  * this software without specific prior written permission. *
27  * *
28  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS *
29  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED *
30  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
31  * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER *
32  * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, *
33  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, *
34  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR *
35  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF *
36  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING *
37  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS *
38  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *
39 * *
40 \*===========================================================================*/
41 
42 /*
43  * ValenceHistogramWidget.cc
44  *
45  * Created on: Jan 27, 2016
46  * Author: hc
47  */
48 
49 #include "ValenceHistogramWidget.hh"
50 
51 #include <QPainter>
52 
53 ValenceHistogramWidget::ValenceHistogramWidget(QWidget *parent) :
54  histogram_(0) {
55 
56 }
57 
58 void ValenceHistogramWidget::paintEvent(QPaintEvent *event) {
59  if (!histogram_) {
60  QWidget::paintEvent(event);
61  return;
62  }
63 
64  /*
65  * Analyze histogram/
66  */
67  std::vector<size_t>::iterator nonzero_begin = histogram_->begin();
68  for (; nonzero_begin != histogram_->end() && *nonzero_begin == 0;
69  ++nonzero_begin);
70  if (nonzero_begin == histogram_->end()) return;
71 
72  std::vector<size_t>::iterator nonzero_end = histogram_->end();
73  for (; (nonzero_end-1) != nonzero_begin && *(nonzero_end-1) == 0;
74  --nonzero_end);
75 
76  const size_t hist_size = std::distance(nonzero_begin, nonzero_end);
77  const size_t hist_max = *std::max_element(nonzero_begin, nonzero_end);
78  const size_t ofs = std::distance(histogram_->begin(), nonzero_begin);
79 
80  /*
81  * Establish regions
82  */
83  QRectF paint_rect = this->contentsRect();
84  QRectF bargraph_rect = paint_rect;
85  bargraph_rect.setBottom(bargraph_rect.bottom() - 16);
86  QRectF label_rect = paint_rect;
87  label_rect.setTop(bargraph_rect.bottom());
88  QPainter painter(this);
89 
90  /*
91  * Painter attributes.
92  */
93  painter.setRenderHint(QPainter::Antialiasing);
94  painter.setBrush(QColor::fromRgbF(0.518, 0.573, 0.643, 1.0));
95  painter.setFont(this->font());
96 
97  const qreal stride =
98  static_cast<qreal>(bargraph_rect.width()) / hist_size;
99  const qreal gap = (stride > 8) ? 1.0 : 0.0;
100  const qreal label_gap = 4;
101  QRectF barRect(0, 0, stride - gap, 0);
102  const qreal scale = static_cast<qreal>(bargraph_rect.height()) / hist_max;
103 
104  /*
105  * Draw.
106  */
107  int cnt = 0;
108  qreal lastLabelX = label_rect.left();
109  for (std::vector<size_t>::iterator it = nonzero_begin;
110  it != nonzero_end; ++it, ++cnt) {
111  // Bar
112  painter.setPen(Qt::NoPen);
113  barRect.setHeight(scale * (*it));
114  barRect.moveBottomLeft(
115  bargraph_rect.bottomLeft() + QPoint(stride * cnt, 0));
116  if (gap > 0.0)
117  painter.drawRoundedRect(barRect, 3, 3, Qt::AbsoluteSize);
118  else
119  painter.drawRect(barRect);
120 
121  // Label
122  painter.setPen(Qt::black);
123  QString labelText = QString::number(cnt + ofs);
124  QRectF labelBB =
125  painter.boundingRect(
126  QRectF(barRect.center().x()-50, label_rect.y(),
127  100.0, label_rect.height()),
128  Qt::AlignHCenter | Qt::AlignBottom, labelText);
129  if (labelBB.left() >= lastLabelX + label_gap) {
130  painter.drawText(labelBB, Qt::AlignHCenter | Qt::AlignBottom,
131  labelText);
132  lastLabelX = labelBB.right();
133  }
134  }
135 }
136 
137 void ValenceHistogramWidget::setHistogram(std::vector<size_t> *histogram) {
138  histogram_ = histogram;
139  this->update();
140 }