kwave  18.07.70
ScaleWidget.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  ScaleWidget.cpp - widget for drawing a scale under an image
3  -------------------
4  begin : Sep 18 2001
5  copyright : (C) 2001 by Thomas Eschenbacher
6  email : Thomas Eschenbacher <thomas.eschenbacher@gmx.de>
7  ***************************************************************************/
8 
9 /***************************************************************************
10  * *
11  * This program is free software; you can redistribute it and/or modify *
12  * it under the terms of the GNU General Public License as published by *
13  * the Free Software Foundation; either version 2 of the License, or *
14  * (at your option) any later version. *
15  * *
16  ***************************************************************************/
17 
18 #include "config.h"
19 
20 #include <math.h>
21 #include <stdio.h>
22 #include <stdlib.h>
23 
24 #include <QFont>
25 #include <QPaintEvent>
26 #include <QPainter>
27 #include <QtGlobal>
28 
29 #include "libkwave/String.h"
30 #include "libkwave/Utils.h"
31 
32 #include "libgui/ScaleWidget.h"
33 
34 #define FONTSIZE 6
35 
36 //***************************************************************************
38  :QWidget(parent), m_low(0), m_high(100), m_logmode(false),
39  m_unittext(_("%"))
40 {
41 }
42 
43 //***************************************************************************
44 Kwave::ScaleWidget::ScaleWidget(QWidget *parent, int low, int high,
45  const QString &unit)
46  :QWidget(parent), m_low(low), m_high(high), m_logmode(false),
47  m_unittext(unit)
48 {
49 }
50 
51 //***************************************************************************
53 {
54 }
55 
56 //***************************************************************************
57 void Kwave::ScaleWidget::setUnit(const QString &text)
58 {
59  m_unittext = text;
60  repaint();
61 }
62 
63 //***************************************************************************
65 {
66  if (m_logmode == log) return;
67  m_logmode = log;
68  repaint();
69 }
70 
71 //***************************************************************************
72 void Kwave::ScaleWidget::setMinMax(int min, int max)
73 {
74  if ((m_low == min) && (m_high == max)) return;
75  m_low = min;
76  m_high = max;
77  repaint();
78 }
79 
80 //***************************************************************************
81 void Kwave::ScaleWidget::paintText(QPainter &p, int x, int y,
82  bool reverse, const QString &text)
83 {
84  QFont font;
85  font.setStyleHint(QFont::SansSerif);
86  font.setFixedPitch(true);
87  font.setPixelSize(FONTSIZE);
88  font.setWeight(0);
89  font.setStyle(QFont::StyleNormal);
90  p.setFont(font);
91  QFontMetrics fm(font);
92 
93  if (reverse) {
94  x += FONTSIZE + 2;
95  y -= FONTSIZE + 2;
96  }
97 
98  QRect rect = fm.boundingRect(text);
99  const int th = rect.height();
100  const int tw = rect.width();
101  p.drawText(x, y, tw, th,
102  ((reverse) ? Qt::AlignLeft : Qt::AlignRight) | Qt::AlignBottom,
103  text);
104 }
105 
106 //***************************************************************************
107 void Kwave::ScaleWidget::drawLog(QPainter &p, int w, int h, bool inverse)
108 {
109  // only use base 10 for now, tested with others too,
110  // but not configurable through a property
111  const int base = 10;
112 
113  int dir = (inverse) ? -1 : +1;
114 
115  p.setPen(palette().dark().color());
116  p.drawLine (0, dir*(h-1), dir*w, dir*(h-1));
117  p.drawLine (dir*(w-1), 0, dir*(w-1), dir*(h-1));
118 
119  p.setPen(palette().text().color());
120 
121  int a, x;
122  const int h2 = h;
123 
124  Q_ASSERT(m_low >= 0);
125  Q_ASSERT(m_high > m_low);
126 
127  int dec_lo = (m_low) ? Kwave::toInt(floor(log(m_low)/log(base))) : 0;
128  int dec_hi = Kwave::toInt(ceil(log(m_high)/log(base)));
129  int decades = qAbs(dec_hi - dec_lo) + 1;
130 
131  // check if we have enough space for the small lines within a decade
132  int w1 = Kwave::toInt(w / decades); // pixels per decade
133  bool small_lines = (w1 - Kwave::toInt(
134  static_cast<double>(w1) * log(base-1)/log(base))) > 1;
135 
136  // print the lines
137  for (a = 0; a < decades; ++a) {
138  // big line, for each decade
139  x = Kwave::toInt((w-1) * a / decades);
140  p.drawLine (dir * x, dir * 1, dir * x, dir * (h2 - 2));
141 
142  w1 = Kwave::toInt((w - 1) * (a + 1) / decades) - x + 1;
143  if (small_lines) {
144  // small lines, within the decade
145  for (int i = 1; i < base; i++) {
146  int x1 = x + Kwave::toInt(static_cast<double>(w1) *
147  log(i) / log(base));
148  p.drawLine (dir * x1, dir * 1, dir * x1, dir * ((h2 / 2) - 2));
149  }
150  }
151  }
152 
153  // print the text
154  for (a = 0; a < decades; ++a) {
155  QString buf = _("%1 %2");
156  int value = Kwave::toInt(pow(base, dec_lo + a));
157  buf = buf.arg(value).arg(m_unittext);
158  x = ((w - 1) * a) / decades;
159  paintText(p, dir * (x + 4), dir * (h - FONTSIZE - 4), inverse, buf);
160  }
161 }
162 
163 //***************************************************************************
164 void Kwave::ScaleWidget::drawLinear(QPainter &p, int w, int h, bool inverse)
165 {
166  int dir = (inverse) ? -1 : +1;
167 
168  p.setPen(palette().dark().color());
169  p.drawLine(0, dir * (h - 1), dir * w, dir * (h - 1));
170  p.drawLine(dir * (w - 1), 0, dir * (w - 1), dir * (h - 1));
171 
172  p.setPen(palette().text().color());
173 
174  int a, x;
175  double ofs;
176  double t = w - 1;
177  int h2 = h;
178 
179  // print the lines
180  while ((t / 10 > 1) && (h2 > 0)) {
181  for (ofs = 0; ofs < w - 1; ofs += t) {
182  for (a = 0; a < 4; ++a) {
183  x = Kwave::toInt(ofs + (t * a / 4));
184  p.drawLine (dir * x, dir * 1, dir * x, dir * (h2 - 2));
185  }
186  }
187  h2 >>= 1;
188  t /= 4;
189  }
190 
191  // print the text
192  for (a = 0; a < 4; ++a) {
193  QString buf = _("%1 %2");
194  int value = m_low + (((m_high - m_low)* (inverse ? (4 - a) : a)) / 4);
195  buf = buf.arg(value).arg(m_unittext);
196  x = ((w - 1) * a) / 4;
197  paintText(p, dir * (x + 4), dir * (h - FONTSIZE - 4), inverse, buf);
198  }
199 
200 }
201 
202 //***************************************************************************
204 {
205  bool inverse = false;
206  int h = height();
207  int w = width();
208  QPainter p;
209 
210  p.begin(this);
211  p.save();
212  p.setPen(palette().light().color());
213 
214  p.drawLine(0, 0, w, 0);
215  if (h > w) {
216  p.setWindow(-w, 0, w, h);
217  p.rotate(-90);
218  h = width();
219  w = height();
220 
221  inverse = true;
222  }
223 
224  (m_logmode) ? drawLog(p, w, h, inverse) : drawLinear(p, w, h, inverse);
225 
226  p.restore();
227  p.end();
228 }
229 
230 //***************************************************************************
232 {
233  return QSize(4 * FONTSIZE, 4 * FONTSIZE);
234 }
235 
236 //***************************************************************************
238 {
239  return QSize(5 * 2 * FONTSIZE, 5 * 2 * FONTSIZE);
240 }
241 
242 //***************************************************************************
243 //***************************************************************************
virtual ~ScaleWidget() Q_DECL_OVERRIDE
Definition: ScaleWidget.cpp:52
virtual void paintEvent(QPaintEvent *) Q_DECL_OVERRIDE
void setLogMode(bool log)
Definition: ScaleWidget.cpp:64
#define FONTSIZE
Definition: ScaleWidget.cpp:34
void setMinMax(int min, int max)
Definition: ScaleWidget.cpp:72
void drawLog(QPainter &p, int w, int h, bool inverse)
int toInt(T x)
Definition: Utils.h:127
virtual QSize sizeHint() const Q_DECL_OVERRIDE
ScaleWidget(QWidget *parent)
Definition: ScaleWidget.cpp:37
virtual QSize minimumSize() const
#define _(m)
Definition: memcpy.c:66
void paintText(QPainter &p, int x, int y, bool reverse, const QString &text)
Definition: ScaleWidget.cpp:81
void setUnit(const QString &text)
Definition: ScaleWidget.cpp:57
static double rect(double param)
Definition: Functions.cpp:29
void drawLinear(QPainter &p, int w, int h, bool inverse)