summaryrefslogtreecommitdiffstats
path: root/src/widgets/widgets/qlcdnumber.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/widgets/widgets/qlcdnumber.cpp')
-rw-r--r--src/widgets/widgets/qlcdnumber.cpp1312
1 files changed, 1312 insertions, 0 deletions
diff --git a/src/widgets/widgets/qlcdnumber.cpp b/src/widgets/widgets/qlcdnumber.cpp
new file mode 100644
index 0000000000..1e034cf3ed
--- /dev/null
+++ b/src/widgets/widgets/qlcdnumber.cpp
@@ -0,0 +1,1312 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qlcdnumber.h"
+#ifndef QT_NO_LCDNUMBER
+#include "qbitarray.h"
+#include "qpainter.h"
+#include "private/qframe_p.h"
+
+QT_BEGIN_NAMESPACE
+
+class QLCDNumberPrivate : public QFramePrivate
+{
+ Q_DECLARE_PUBLIC(QLCDNumber)
+public:
+ void init();
+ void internalSetString(const QString& s);
+ void drawString(const QString& s, QPainter &, QBitArray * = 0, bool = true);
+ //void drawString(const QString &, QPainter &, QBitArray * = 0) const;
+ void drawDigit(const QPoint &, QPainter &, int, char, char = ' ');
+ void drawSegment(const QPoint &, char, QPainter &, int, bool = false);
+
+ int ndigits;
+ double val;
+ uint base : 2;
+ uint smallPoint : 1;
+ uint fill : 1;
+ uint shadow : 1;
+ QString digitStr;
+ QBitArray points;
+};
+
+/*!
+ \class QLCDNumber
+
+ \brief The QLCDNumber widget displays a number with LCD-like digits.
+
+ \ingroup basicwidgets
+
+
+ It can display a number in just about any size. It can display
+ decimal, hexadecimal, octal or binary numbers. It is easy to
+ connect to data sources using the display() slot, which is
+ overloaded to take any of five argument types.
+
+ There are also slots to change the base with setMode() and the
+ decimal point with setSmallDecimalPoint().
+
+ QLCDNumber emits the overflow() signal when it is asked to display
+ something beyond its range. The range is set by setDigitCount(),
+ but setSmallDecimalPoint() also influences it. If the display is
+ set to hexadecimal, octal or binary, the integer equivalent of the
+ value is displayed.
+
+ These digits and other symbols can be shown: 0/O, 1, 2, 3, 4, 5/S,
+ 6, 7, 8, 9/g, minus, decimal point, A, B, C, D, E, F, h, H, L, o,
+ P, r, u, U, Y, colon, degree sign (which is specified as single
+ quote in the string) and space. QLCDNumber substitutes spaces for
+ illegal characters.
+
+ It is not possible to retrieve the contents of a QLCDNumber
+ object, although you can retrieve the numeric value with value().
+ If you really need the text, we recommend that you connect the
+ signals that feed the display() slot to another slot as well and
+ store the value there.
+
+ Incidentally, QLCDNumber is the very oldest part of Qt, tracing
+ its roots back to a BASIC program on the \link
+ http://www.nvg.ntnu.no/sinclair/computers/zxspectrum/zxspectrum.htm
+ Sinclair Spectrum\endlink.
+
+ \table
+ \row \o \inlineimage motif-lcdnumber.png Screenshot of a Motif style LCD number widget
+ \inlineimage cde-lcdnumber.png Screenshot of a CDE style LCD number widget
+ \inlineimage windows-lcdnumber.png Screenshot of a Windows style LCD number widget
+ \inlineimage windowsxp-lcdnumber.png Screenshot of a Windows XP style LCD number widget
+ \inlineimage macintosh-lcdnumber.png Screenshot of a Macintosh style LCD number widget
+ \inlineimage plastique-lcdnumber.png Screenshot of a Plastique style LCD number widget
+ \row \o LCD number widgets shown in various widget styles (from left to right):
+ \l{Motif Style Widget Gallery}{Motif}, \l{CDE Style Widget Gallery}{CDE},
+ \l{Windows Style Widget Gallery}{Windows}, \l{Windows XP Style Widget Gallery}{Windows XP},
+ \l{Macintosh Style Widget Gallery}{Macintosh}, \l{Plastique Style Widget Gallery}{Plastique}.
+ \endtable
+
+ \sa QLabel, QFrame, {Digital Clock Example}, {Tetrix Example}
+*/
+
+/*!
+ \enum QLCDNumber::Mode
+
+ This type determines how numbers are shown.
+
+ \value Hex Hexadecimal
+ \value Dec Decimal
+ \value Oct Octal
+ \value Bin Binary
+ \omitvalue HEX
+ \omitvalue DEC
+ \omitvalue OCT
+ \omitvalue BIN
+
+ If the display is set to hexadecimal, octal or binary, the integer
+ equivalent of the value is displayed.
+*/
+
+/*!
+ \enum QLCDNumber::SegmentStyle
+
+ This type determines the visual appearance of the QLCDNumber
+ widget.
+
+ \value Outline gives raised segments filled with the background color.
+ \value Filled gives raised segments filled with the windowText color.
+ \value Flat gives flat segments filled with the windowText color.
+*/
+
+
+
+/*!
+ \fn void QLCDNumber::overflow()
+
+ This signal is emitted whenever the QLCDNumber is asked to display
+ a too-large number or a too-long string.
+
+ It is never emitted by setDigitCount().
+*/
+
+
+static QString int2string(int num, int base, int ndigits, bool *oflow)
+{
+ QString s;
+ bool negative;
+ if (num < 0) {
+ negative = true;
+ num = -num;
+ } else {
+ negative = false;
+ }
+ switch(base) {
+ case QLCDNumber::Hex:
+ s.sprintf("%*x", ndigits, num);
+ break;
+ case QLCDNumber::Dec:
+ s.sprintf("%*i", ndigits, num);
+ break;
+ case QLCDNumber::Oct:
+ s.sprintf("%*o", ndigits, num);
+ break;
+ case QLCDNumber::Bin:
+ {
+ char buf[42];
+ char *p = &buf[41];
+ uint n = num;
+ int len = 0;
+ *p = '\0';
+ do {
+ *--p = (char)((n&1)+'0');
+ n >>= 1;
+ len++;
+ } while (n != 0);
+ len = ndigits - len;
+ if (len > 0)
+ s.fill(QLatin1Char(' '), len);
+ s += QString::fromLatin1(p);
+ }
+ break;
+ }
+ if (negative) {
+ for (int i=0; i<(int)s.length(); i++) {
+ if (s[i] != QLatin1Char(' ')) {
+ if (i != 0) {
+ s[i-1] = QLatin1Char('-');
+ } else {
+ s.insert(0, QLatin1Char('-'));
+ }
+ break;
+ }
+ }
+ }
+ if (oflow)
+ *oflow = (int)s.length() > ndigits;
+ return s;
+}
+
+
+static QString double2string(double num, int base, int ndigits, bool *oflow)
+{
+ QString s;
+ if (base != QLCDNumber::Dec) {
+ bool of = num >= 2147483648.0 || num < -2147483648.0;
+ if (of) { // oops, integer overflow
+ if (oflow)
+ *oflow = true;
+ return s;
+ }
+ s = int2string((int)num, base, ndigits, 0);
+ } else { // decimal base
+ int nd = ndigits;
+ do {
+ s.sprintf("%*.*g", ndigits, nd, num);
+ int i = s.indexOf(QLatin1Char('e'));
+ if (i > 0 && s[i+1]==QLatin1Char('+')) {
+ s[i] = QLatin1Char(' ');
+ s[i+1] = QLatin1Char('e');
+ }
+ } while (nd-- && (int)s.length() > ndigits);
+ }
+ if (oflow)
+ *oflow = (int)s.length() > ndigits;
+ return s;
+}
+
+
+static const char *getSegments(char ch) // gets list of segments for ch
+{
+ static const char segments[30][8] =
+ { { 0, 1, 2, 4, 5, 6,99, 0}, // 0 0 / O
+ { 2, 5,99, 0, 0, 0, 0, 0}, // 1 1
+ { 0, 2, 3, 4, 6,99, 0, 0}, // 2 2
+ { 0, 2, 3, 5, 6,99, 0, 0}, // 3 3
+ { 1, 2, 3, 5,99, 0, 0, 0}, // 4 4
+ { 0, 1, 3, 5, 6,99, 0, 0}, // 5 5 / S
+ { 0, 1, 3, 4, 5, 6,99, 0}, // 6 6
+ { 0, 2, 5,99, 0, 0, 0, 0}, // 7 7
+ { 0, 1, 2, 3, 4, 5, 6,99}, // 8 8
+ { 0, 1, 2, 3, 5, 6,99, 0}, // 9 9 / g
+ { 3,99, 0, 0, 0, 0, 0, 0}, // 10 -
+ { 7,99, 0, 0, 0, 0, 0, 0}, // 11 .
+ { 0, 1, 2, 3, 4, 5,99, 0}, // 12 A
+ { 1, 3, 4, 5, 6,99, 0, 0}, // 13 B
+ { 0, 1, 4, 6,99, 0, 0, 0}, // 14 C
+ { 2, 3, 4, 5, 6,99, 0, 0}, // 15 D
+ { 0, 1, 3, 4, 6,99, 0, 0}, // 16 E
+ { 0, 1, 3, 4,99, 0, 0, 0}, // 17 F
+ { 1, 3, 4, 5,99, 0, 0, 0}, // 18 h
+ { 1, 2, 3, 4, 5,99, 0, 0}, // 19 H
+ { 1, 4, 6,99, 0, 0, 0, 0}, // 20 L
+ { 3, 4, 5, 6,99, 0, 0, 0}, // 21 o
+ { 0, 1, 2, 3, 4,99, 0, 0}, // 22 P
+ { 3, 4,99, 0, 0, 0, 0, 0}, // 23 r
+ { 4, 5, 6,99, 0, 0, 0, 0}, // 24 u
+ { 1, 2, 4, 5, 6,99, 0, 0}, // 25 U
+ { 1, 2, 3, 5, 6,99, 0, 0}, // 26 Y
+ { 8, 9,99, 0, 0, 0, 0, 0}, // 27 :
+ { 0, 1, 2, 3,99, 0, 0, 0}, // 28 '
+ {99, 0, 0, 0, 0, 0, 0, 0} }; // 29 empty
+
+ if (ch >= '0' && ch <= '9')
+ return segments[ch - '0'];
+ if (ch >= 'A' && ch <= 'F')
+ return segments[ch - 'A' + 12];
+ if (ch >= 'a' && ch <= 'f')
+ return segments[ch - 'a' + 12];
+
+ int n;
+ switch (ch) {
+ case '-':
+ n = 10; break;
+ case 'O':
+ n = 0; break;
+ case 'g':
+ n = 9; break;
+ case '.':
+ n = 11; break;
+ case 'h':
+ n = 18; break;
+ case 'H':
+ n = 19; break;
+ case 'l':
+ case 'L':
+ n = 20; break;
+ case 'o':
+ n = 21; break;
+ case 'p':
+ case 'P':
+ n = 22; break;
+ case 'r':
+ case 'R':
+ n = 23; break;
+ case 's':
+ case 'S':
+ n = 5; break;
+ case 'u':
+ n = 24; break;
+ case 'U':
+ n = 25; break;
+ case 'y':
+ case 'Y':
+ n = 26; break;
+ case ':':
+ n = 27; break;
+ case '\'':
+ n = 28; break;
+ default:
+ n = 29; break;
+ }
+ return segments[n];
+}
+
+
+#ifdef QT3_SUPPORT
+/*! \obsolete
+ Constructs an LCD number, sets the number of digits to 5, the base
+ to decimal, the decimal point mode to 'small' and the frame style
+ to a raised box. The segmentStyle() is set to \c Outline.
+
+ The \a parent and \a name arguments are passed to the QFrame
+ constructor.
+
+ \sa setDigitCount(), setSmallDecimalPoint()
+*/
+
+QLCDNumber::QLCDNumber(QWidget *parent, const char *name)
+ : QFrame(*new QLCDNumberPrivate, parent)
+{
+ setObjectName(QString::fromAscii(name));
+ Q_D(QLCDNumber);
+ d->ndigits = 5;
+ d->init();
+}
+
+
+/*! \obsolete
+ Constructs an LCD number, sets the number of digits to \a
+ numDigits, the base to decimal, the decimal point mode to 'small'
+ and the frame style to a raised box. The segmentStyle() is set to
+ \c Outline.
+
+ The \a parent and \a name arguments are passed to the QFrame
+ constructor.
+
+ \sa setDigitCount(), setSmallDecimalPoint()
+*/
+
+QLCDNumber::QLCDNumber(uint numDigits, QWidget *parent, const char *name)
+ : QFrame(*new QLCDNumberPrivate, parent)
+{
+ setObjectName(QString::fromAscii(name));
+ Q_D(QLCDNumber);
+ d->ndigits = numDigits;
+ d->init();
+}
+#endif //QT3_SUPPORT
+
+/*!
+ Constructs an LCD number, sets the number of digits to 5, the base
+ to decimal, the decimal point mode to 'small' and the frame style
+ to a raised box. The segmentStyle() is set to \c Outline.
+
+ The \a parent argument is passed to the QFrame constructor.
+
+ \sa setDigitCount(), setSmallDecimalPoint()
+*/
+
+QLCDNumber::QLCDNumber(QWidget *parent)
+ : QFrame(*new QLCDNumberPrivate, parent)
+{
+ Q_D(QLCDNumber);
+ d->ndigits = 5;
+ d->init();
+}
+
+
+/*!
+ Constructs an LCD number, sets the number of digits to \a
+ numDigits, the base to decimal, the decimal point mode to 'small'
+ and the frame style to a raised box. The segmentStyle() is set to
+ \c Filled.
+
+ The \a parent argument is passed to the QFrame constructor.
+
+ \sa setDigitCount(), setSmallDecimalPoint()
+*/
+
+QLCDNumber::QLCDNumber(uint numDigits, QWidget *parent)
+ : QFrame(*new QLCDNumberPrivate, parent)
+{
+ Q_D(QLCDNumber);
+ d->ndigits = numDigits;
+ d->init();
+}
+
+void QLCDNumberPrivate::init()
+{
+ Q_Q(QLCDNumber);
+
+ q->setFrameStyle(QFrame::Box | QFrame::Raised);
+ val = 0;
+ base = QLCDNumber::Dec;
+ smallPoint = false;
+ q->setDigitCount(ndigits);
+ q->setSegmentStyle(QLCDNumber::Filled);
+ q->setSizePolicy(QSizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum));
+}
+
+/*!
+ Destroys the LCD number.
+*/
+
+QLCDNumber::~QLCDNumber()
+{
+}
+
+
+/*!
+ \deprecated
+ \property QLCDNumber::numDigits
+ \brief the current number of digits displayed
+ \sa digitCount
+*/
+
+void QLCDNumber::setNumDigits(int numDigits)
+{
+ setDigitCount(numDigits);
+}
+
+/*!
+ \since 4.6
+ \property QLCDNumber::digitCount
+ \brief the current number of digits displayed
+
+ Corresponds to the current number of digits. If \l
+ QLCDNumber::smallDecimalPoint is false, the decimal point occupies
+ one digit position.
+
+ By default, this property contains a value of 5.
+
+ \sa smallDecimalPoint
+*/
+
+/*!
+ Sets the current number of digits to \a numDigits. Must
+ be in the range 0..99.
+ */
+void QLCDNumber::setDigitCount(int numDigits)
+{
+ Q_D(QLCDNumber);
+ if (numDigits > 99) {
+ qWarning("QLCDNumber::setNumDigits: (%s) Max 99 digits allowed",
+ objectName().toLocal8Bit().constData());
+ numDigits = 99;
+ }
+ if (numDigits < 0) {
+ qWarning("QLCDNumber::setNumDigits: (%s) Min 0 digits allowed",
+ objectName().toLocal8Bit().constData());
+ numDigits = 0;
+ }
+ if (d->digitStr.isNull()) { // from constructor
+ d->ndigits = numDigits;
+ d->digitStr.fill(QLatin1Char(' '), d->ndigits);
+ d->points.fill(0, d->ndigits);
+ d->digitStr[d->ndigits - 1] = QLatin1Char('0'); // "0" is the default number
+ } else {
+ bool doDisplay = d->ndigits == 0;
+ if (numDigits == d->ndigits) // no change
+ return;
+ register int i;
+ int dif;
+ if (numDigits > d->ndigits) { // expand
+ dif = numDigits - d->ndigits;
+ QString buf;
+ buf.fill(QLatin1Char(' '), dif);
+ d->digitStr.insert(0, buf);
+ d->points.resize(numDigits);
+ for (i=numDigits-1; i>=dif; i--)
+ d->points.setBit(i, d->points.testBit(i-dif));
+ for (i=0; i<dif; i++)
+ d->points.clearBit(i);
+ } else { // shrink
+ dif = d->ndigits - numDigits;
+ d->digitStr = d->digitStr.right(numDigits);
+ QBitArray tmpPoints = d->points;
+ d->points.resize(numDigits);
+ for (i=0; i<(int)numDigits; i++)
+ d->points.setBit(i, tmpPoints.testBit(i+dif));
+ }
+ d->ndigits = numDigits;
+ if (doDisplay)
+ display(value());
+ update();
+ }
+}
+
+int QLCDNumber::numDigits() const
+{
+ Q_D(const QLCDNumber);
+ return d->ndigits;
+}
+
+/*!
+ Returns the current number of digits.
+ */
+int QLCDNumber::digitCount() const
+{
+ Q_D(const QLCDNumber);
+ return d->ndigits;
+}
+
+/*!
+ \overload
+
+ Returns true if \a num is too big to be displayed in its entirety;
+ otherwise returns false.
+
+ \sa display(), digitCount(), smallDecimalPoint()
+*/
+
+bool QLCDNumber::checkOverflow(int num) const
+{
+ Q_D(const QLCDNumber);
+ bool of;
+ int2string(num, d->base, d->ndigits, &of);
+ return of;
+}
+
+
+/*!
+ Returns true if \a num is too big to be displayed in its entirety;
+ otherwise returns false.
+
+ \sa display(), digitCount(), smallDecimalPoint()
+*/
+
+bool QLCDNumber::checkOverflow(double num) const
+{
+ Q_D(const QLCDNumber);
+ bool of;
+ double2string(num, d->base, d->ndigits, &of);
+ return of;
+}
+
+
+/*!
+ \property QLCDNumber::mode
+ \brief the current display mode (number base)
+
+ Corresponds to the current display mode, which is one of \c Bin,
+ \c Oct, \c Dec (the default) and \c Hex. \c Dec mode can display
+ floating point values, the other modes display the integer
+ equivalent.
+
+ \sa smallDecimalPoint(), setHexMode(), setDecMode(), setOctMode(), setBinMode()
+*/
+
+QLCDNumber::Mode QLCDNumber::mode() const
+{
+ Q_D(const QLCDNumber);
+ return (QLCDNumber::Mode) d->base;
+}
+
+void QLCDNumber::setMode(Mode m)
+{
+ Q_D(QLCDNumber);
+ d->base = m;
+ display(d->val);
+}
+
+
+/*!
+ \property QLCDNumber::value
+ \brief the displayed value
+
+ This property corresponds to the current value displayed by the
+ LCDNumber.
+
+ If the displayed value is not a number, the property has a value
+ of 0.
+
+ By default, this property contains a value of 0.
+*/
+
+double QLCDNumber::value() const
+{
+ Q_D(const QLCDNumber);
+ return d->val;
+}
+
+/*!
+ \overload
+
+ Displays the number \a num.
+*/
+void QLCDNumber::display(double num)
+{
+ Q_D(QLCDNumber);
+ d->val = num;
+ bool of;
+ QString s = double2string(d->val, d->base, d->ndigits, &of);
+ if (of)
+ emit overflow();
+ else
+ d->internalSetString(s);
+}
+
+/*!
+ \property QLCDNumber::intValue
+ \brief the displayed value rounded to the nearest integer
+
+ This property corresponds to the nearest integer to the current
+ value displayed by the LCDNumber. This is the value used for
+ hexadecimal, octal and binary modes.
+
+ If the displayed value is not a number, the property has a value
+ of 0.
+
+ By default, this property contains a value of 0.
+*/
+int QLCDNumber::intValue() const
+{
+ Q_D(const QLCDNumber);
+ return qRound(d->val);
+}
+
+
+/*!
+ \overload
+
+ Displays the number \a num.
+*/
+void QLCDNumber::display(int num)
+{
+ Q_D(QLCDNumber);
+ d->val = (double)num;
+ bool of;
+ QString s = int2string(num, d->base, d->ndigits, &of);
+ if (of)
+ emit overflow();
+ else
+ d->internalSetString(s);
+}
+
+
+/*!
+ Displays the number represented by the string \a s.
+
+ This version of the function disregards mode() and
+ smallDecimalPoint().
+
+ These digits and other symbols can be shown: 0/O, 1, 2, 3, 4, 5/S,
+ 6, 7, 8, 9/g, minus, decimal point, A, B, C, D, E, F, h, H, L, o,
+ P, r, u, U, Y, colon, degree sign (which is specified as single
+ quote in the string) and space. QLCDNumber substitutes spaces for
+ illegal characters.
+*/
+
+void QLCDNumber::display(const QString &s)
+{
+ Q_D(QLCDNumber);
+ d->val = 0;
+ bool ok = false;
+ double v = s.toDouble(&ok);
+ if (ok)
+ d->val = v;
+ d->internalSetString(s);
+}
+
+/*!
+ Calls setMode(Hex). Provided for convenience (e.g. for
+ connecting buttons to it).
+
+ \sa setMode(), setDecMode(), setOctMode(), setBinMode(), mode()
+*/
+
+void QLCDNumber::setHexMode()
+{
+ setMode(Hex);
+}
+
+
+/*!
+ Calls setMode(Dec). Provided for convenience (e.g. for
+ connecting buttons to it).
+
+ \sa setMode(), setHexMode(), setOctMode(), setBinMode(), mode()
+*/
+
+void QLCDNumber::setDecMode()
+{
+ setMode(Dec);
+}
+
+
+/*!
+ Calls setMode(Oct). Provided for convenience (e.g. for
+ connecting buttons to it).
+
+ \sa setMode(), setHexMode(), setDecMode(), setBinMode(), mode()
+*/
+
+void QLCDNumber::setOctMode()
+{
+ setMode(Oct);
+}
+
+
+/*!
+ Calls setMode(Bin). Provided for convenience (e.g. for
+ connecting buttons to it).
+
+ \sa setMode(), setHexMode(), setDecMode(), setOctMode(), mode()
+*/
+
+void QLCDNumber::setBinMode()
+{
+ setMode(Bin);
+}
+
+
+/*!
+ \property QLCDNumber::smallDecimalPoint
+ \brief the style of the decimal point
+
+ If true the decimal point is drawn between two digit positions.
+ Otherwise it occupies a digit position of its own, i.e. is drawn
+ in a digit position. The default is false.
+
+ The inter-digit space is made slightly wider when the decimal
+ point is drawn between the digits.
+
+ \sa mode
+*/
+
+void QLCDNumber::setSmallDecimalPoint(bool b)
+{
+ Q_D(QLCDNumber);
+ d->smallPoint = b;
+ update();
+}
+
+bool QLCDNumber::smallDecimalPoint() const
+{
+ Q_D(const QLCDNumber);
+ return d->smallPoint;
+}
+
+
+
+/*!\reimp
+*/
+
+
+void QLCDNumber::paintEvent(QPaintEvent *)
+{
+ Q_D(QLCDNumber);
+ QPainter p(this);
+ drawFrame(&p);
+ p.setRenderHint(QPainter::Antialiasing);
+ if (d->shadow)
+ p.translate(0.5, 0.5);
+
+ if (d->smallPoint)
+ d->drawString(d->digitStr, p, &d->points, false);
+ else
+ d->drawString(d->digitStr, p, 0, false);
+}
+
+
+void QLCDNumberPrivate::internalSetString(const QString& s)
+{
+ Q_Q(QLCDNumber);
+ QString buffer;
+ int i;
+ int len = s.length();
+ QBitArray newPoints(ndigits);
+
+ if (!smallPoint) {
+ if (len == ndigits)
+ buffer = s;
+ else
+ buffer = s.right(ndigits).rightJustified(ndigits, QLatin1Char(' '));
+ } else {
+ int index = -1;
+ bool lastWasPoint = true;
+ newPoints.clearBit(0);
+ for (i=0; i<len; i++) {
+ if (s[i] == QLatin1Char('.')) {
+ if (lastWasPoint) { // point already set for digit?
+ if (index == ndigits - 1) // no more digits
+ break;
+ index++;
+ buffer[index] = QLatin1Char(' '); // 2 points in a row, add space
+ }
+ newPoints.setBit(index); // set decimal point
+ lastWasPoint = true;
+ } else {
+ if (index == ndigits - 1)
+ break;
+ index++;
+ buffer[index] = s[i];
+ newPoints.clearBit(index); // decimal point default off
+ lastWasPoint = false;
+ }
+ }
+ if (index < ((int) ndigits) - 1) {
+ for(i=index; i>=0; i--) {
+ buffer[ndigits - 1 - index + i] = buffer[i];
+ newPoints.setBit(ndigits - 1 - index + i,
+ newPoints.testBit(i));
+ }
+ for(i=0; i<ndigits-index-1; i++) {
+ buffer[i] = QLatin1Char(' ');
+ newPoints.clearBit(i);
+ }
+ }
+ }
+
+ if (buffer == digitStr)
+ return;
+
+ digitStr = buffer;
+ if (smallPoint)
+ points = newPoints;
+ q->update();
+}
+
+/*!
+ \internal
+*/
+
+void QLCDNumberPrivate::drawString(const QString &s, QPainter &p,
+ QBitArray *newPoints, bool newString)
+{
+ Q_Q(QLCDNumber);
+ QPoint pos;
+
+ int digitSpace = smallPoint ? 2 : 1;
+ int xSegLen = q->width()*5/(ndigits*(5 + digitSpace) + digitSpace);
+ int ySegLen = q->height()*5/12;
+ int segLen = ySegLen > xSegLen ? xSegLen : ySegLen;
+ int xAdvance = segLen*(5 + digitSpace)/5;
+ int xOffset = (q->width() - ndigits*xAdvance + segLen/5)/2;
+ int yOffset = (q->height() - segLen*2)/2;
+
+ for (int i=0; i<ndigits; i++) {
+ pos = QPoint(xOffset + xAdvance*i, yOffset);
+ if (newString)
+ drawDigit(pos, p, segLen, s[i].toLatin1(), digitStr[i].toLatin1());
+ else
+ drawDigit(pos, p, segLen, s[i].toLatin1());
+ if (newPoints) {
+ char newPoint = newPoints->testBit(i) ? '.' : ' ';
+ if (newString) {
+ char oldPoint = points.testBit(i) ? '.' : ' ';
+ drawDigit(pos, p, segLen, newPoint, oldPoint);
+ } else {
+ drawDigit(pos, p, segLen, newPoint);
+ }
+ }
+ }
+ if (newString) {
+ digitStr = s;
+ digitStr.truncate(ndigits);
+ if (newPoints)
+ points = *newPoints;
+ }
+}
+
+
+/*!
+ \internal
+*/
+
+void QLCDNumberPrivate::drawDigit(const QPoint &pos, QPainter &p, int segLen,
+ char newCh, char oldCh)
+{
+// Draws and/or erases segments to change display of a single digit
+// from oldCh to newCh
+
+ char updates[18][2]; // can hold 2 times number of segments, only
+ // first 9 used if segment table is correct
+ int nErases;
+ int nUpdates;
+ const char *segs;
+ int i,j;
+
+ const char erase = 0;
+ const char draw = 1;
+ const char leaveAlone = 2;
+
+ segs = getSegments(oldCh);
+ for (nErases=0; segs[nErases] != 99; nErases++) {
+ updates[nErases][0] = erase; // get segments to erase to
+ updates[nErases][1] = segs[nErases]; // remove old char
+ }
+ nUpdates = nErases;
+ segs = getSegments(newCh);
+ for(i = 0 ; segs[i] != 99 ; i++) {
+ for (j=0; j<nErases; j++)
+ if (segs[i] == updates[j][1]) { // same segment ?
+ updates[j][0] = leaveAlone; // yes, already on screen
+ break;
+ }
+ if (j == nErases) { // if not already on screen
+ updates[nUpdates][0] = draw;
+ updates[nUpdates][1] = segs[i];
+ nUpdates++;
+ }
+ }
+ for (i=0; i<nUpdates; i++) {
+ if (updates[i][0] == draw)
+ drawSegment(pos, updates[i][1], p, segLen);
+ if (updates[i][0] == erase)
+ drawSegment(pos, updates[i][1], p, segLen, true);
+ }
+}
+
+
+static void addPoint(QPolygon &a, const QPoint &p)
+{
+ uint n = a.size();
+ a.resize(n + 1);
+ a.setPoint(n, p);
+}
+
+/*!
+ \internal
+*/
+
+void QLCDNumberPrivate::drawSegment(const QPoint &pos, char segmentNo, QPainter &p,
+ int segLen, bool erase)
+{
+ Q_Q(QLCDNumber);
+ QPoint ppt;
+ QPoint pt = pos;
+ int width = segLen/5;
+
+ const QPalette &pal = q->palette();
+ QColor lightColor,darkColor,fgColor;
+ if (erase){
+ lightColor = pal.color(q->backgroundRole());
+ darkColor = lightColor;
+ fgColor = lightColor;
+ } else {
+ lightColor = pal.light().color();
+ darkColor = pal.dark().color();
+ fgColor = pal.color(q->foregroundRole());
+ }
+
+
+#define LINETO(X,Y) addPoint(a, QPoint(pt.x() + (X),pt.y() + (Y)))
+#define LIGHT
+#define DARK
+
+ if (fill) {
+ QPolygon a(0);
+ //The following is an exact copy of the switch below.
+ //don't make any changes here
+ switch (segmentNo) {
+ case 0 :
+ ppt = pt;
+ LIGHT;
+ LINETO(segLen - 1,0);
+ DARK;
+ LINETO(segLen - width - 1,width);
+ LINETO(width,width);
+ LINETO(0,0);
+ break;
+ case 1 :
+ pt += QPoint(0 , 1);
+ ppt = pt;
+ LIGHT;
+ LINETO(width,width);
+ DARK;
+ LINETO(width,segLen - width/2 - 2);
+ LINETO(0,segLen - 2);
+ LIGHT;
+ LINETO(0,0);
+ break;
+ case 2 :
+ pt += QPoint(segLen - 1 , 1);
+ ppt = pt;
+ DARK;
+ LINETO(0,segLen - 2);
+ LINETO(-width,segLen - width/2 - 2);
+ LIGHT;
+ LINETO(-width,width);
+ LINETO(0,0);
+ break;
+ case 3 :
+ pt += QPoint(0 , segLen);
+ ppt = pt;
+ LIGHT;
+ LINETO(width,-width/2);
+ LINETO(segLen - width - 1,-width/2);
+ LINETO(segLen - 1,0);
+ DARK;
+ if (width & 1) { // adjust for integer division error
+ LINETO(segLen - width - 3,width/2 + 1);
+ LINETO(width + 2,width/2 + 1);
+ } else {
+ LINETO(segLen - width - 1,width/2);
+ LINETO(width,width/2);
+ }
+ LINETO(0,0);
+ break;
+ case 4 :
+ pt += QPoint(0 , segLen + 1);
+ ppt = pt;
+ LIGHT;
+ LINETO(width,width/2);
+ DARK;
+ LINETO(width,segLen - width - 2);
+ LINETO(0,segLen - 2);
+ LIGHT;
+ LINETO(0,0);
+ break;
+ case 5 :
+ pt += QPoint(segLen - 1 , segLen + 1);
+ ppt = pt;
+ DARK;
+ LINETO(0,segLen - 2);
+ LINETO(-width,segLen - width - 2);
+ LIGHT;
+ LINETO(-width,width/2);
+ LINETO(0,0);
+ break;
+ case 6 :
+ pt += QPoint(0 , segLen*2);
+ ppt = pt;
+ LIGHT;
+ LINETO(width,-width);
+ LINETO(segLen - width - 1,-width);
+ LINETO(segLen - 1,0);
+ DARK;
+ LINETO(0,0);
+ break;
+ case 7 :
+ if (smallPoint) // if smallpoint place'.' between other digits
+ pt += QPoint(segLen + width/2 , segLen*2);
+ else
+ pt += QPoint(segLen/2 , segLen*2);
+ ppt = pt;
+ DARK;
+ LINETO(width,0);
+ LINETO(width,-width);
+ LIGHT;
+ LINETO(0,-width);
+ LINETO(0,0);
+ break;
+ case 8 :
+ pt += QPoint(segLen/2 - width/2 + 1 , segLen/2 + width);
+ ppt = pt;
+ DARK;
+ LINETO(width,0);
+ LINETO(width,-width);
+ LIGHT;
+ LINETO(0,-width);
+ LINETO(0,0);
+ break;
+ case 9 :
+ pt += QPoint(segLen/2 - width/2 + 1 , 3*segLen/2 + width);
+ ppt = pt;
+ DARK;
+ LINETO(width,0);
+ LINETO(width,-width);
+ LIGHT;
+ LINETO(0,-width);
+ LINETO(0,0);
+ break;
+ default :
+ qWarning("QLCDNumber::drawSegment: (%s) Illegal segment id: %d\n",
+ q->objectName().toLocal8Bit().constData(), segmentNo);
+ }
+ // End exact copy
+ p.setPen(Qt::NoPen);
+ p.setBrush(fgColor);
+ p.drawPolygon(a);
+ p.setBrush(Qt::NoBrush);
+
+ pt = pos;
+ }
+#undef LINETO
+#undef LIGHT
+#undef DARK
+
+#define LINETO(X,Y) p.drawLine(ppt.x(), ppt.y(), pt.x()+(X), pt.y()+(Y)); \
+ ppt = QPoint(pt.x()+(X), pt.y()+(Y))
+#define LIGHT p.setPen(lightColor)
+#define DARK p.setPen(darkColor)
+ if (shadow)
+ switch (segmentNo) {
+ case 0 :
+ ppt = pt;
+ LIGHT;
+ LINETO(segLen - 1,0);
+ DARK;
+ LINETO(segLen - width - 1,width);
+ LINETO(width,width);
+ LINETO(0,0);
+ break;
+ case 1 :
+ pt += QPoint(0,1);
+ ppt = pt;
+ LIGHT;
+ LINETO(width,width);
+ DARK;
+ LINETO(width,segLen - width/2 - 2);
+ LINETO(0,segLen - 2);
+ LIGHT;
+ LINETO(0,0);
+ break;
+ case 2 :
+ pt += QPoint(segLen - 1 , 1);
+ ppt = pt;
+ DARK;
+ LINETO(0,segLen - 2);
+ LINETO(-width,segLen - width/2 - 2);
+ LIGHT;
+ LINETO(-width,width);
+ LINETO(0,0);
+ break;
+ case 3 :
+ pt += QPoint(0 , segLen);
+ ppt = pt;
+ LIGHT;
+ LINETO(width,-width/2);
+ LINETO(segLen - width - 1,-width/2);
+ LINETO(segLen - 1,0);
+ DARK;
+ if (width & 1) { // adjust for integer division error
+ LINETO(segLen - width - 3,width/2 + 1);
+ LINETO(width + 2,width/2 + 1);
+ } else {
+ LINETO(segLen - width - 1,width/2);
+ LINETO(width,width/2);
+ }
+ LINETO(0,0);
+ break;
+ case 4 :
+ pt += QPoint(0 , segLen + 1);
+ ppt = pt;
+ LIGHT;
+ LINETO(width,width/2);
+ DARK;
+ LINETO(width,segLen - width - 2);
+ LINETO(0,segLen - 2);
+ LIGHT;
+ LINETO(0,0);
+ break;
+ case 5 :
+ pt += QPoint(segLen - 1 , segLen + 1);
+ ppt = pt;
+ DARK;
+ LINETO(0,segLen - 2);
+ LINETO(-width,segLen - width - 2);
+ LIGHT;
+ LINETO(-width,width/2);
+ LINETO(0,0);
+ break;
+ case 6 :
+ pt += QPoint(0 , segLen*2);
+ ppt = pt;
+ LIGHT;
+ LINETO(width,-width);
+ LINETO(segLen - width - 1,-width);
+ LINETO(segLen - 1,0);
+ DARK;
+ LINETO(0,0);
+ break;
+ case 7 :
+ if (smallPoint) // if smallpoint place'.' between other digits
+ pt += QPoint(segLen + width/2 , segLen*2);
+ else
+ pt += QPoint(segLen/2 , segLen*2);
+ ppt = pt;
+ DARK;
+ LINETO(width,0);
+ LINETO(width,-width);
+ LIGHT;
+ LINETO(0,-width);
+ LINETO(0,0);
+ break;
+ case 8 :
+ pt += QPoint(segLen/2 - width/2 + 1 , segLen/2 + width);
+ ppt = pt;
+ DARK;
+ LINETO(width,0);
+ LINETO(width,-width);
+ LIGHT;
+ LINETO(0,-width);
+ LINETO(0,0);
+ break;
+ case 9 :
+ pt += QPoint(segLen/2 - width/2 + 1 , 3*segLen/2 + width);
+ ppt = pt;
+ DARK;
+ LINETO(width,0);
+ LINETO(width,-width);
+ LIGHT;
+ LINETO(0,-width);
+ LINETO(0,0);
+ break;
+ default :
+ qWarning("QLCDNumber::drawSegment: (%s) Illegal segment id: %d\n",
+ q->objectName().toLocal8Bit().constData(), segmentNo);
+ }
+
+#undef LINETO
+#undef LIGHT
+#undef DARK
+}
+
+
+
+/*!
+ \property QLCDNumber::segmentStyle
+ \brief the style of the LCDNumber
+
+ \table
+ \header \i Style \i Result
+ \row \i \c Outline
+ \i Produces raised segments filled with the background color
+ \row \i \c Filled
+ (this is the default).
+ \i Produces raised segments filled with the foreground color.
+ \row \i \c Flat
+ \i Produces flat segments filled with the foreground color.
+ \endtable
+
+ \c Outline and \c Filled will additionally use
+ QPalette::light() and QPalette::dark() for shadow effects.
+*/
+void QLCDNumber::setSegmentStyle(SegmentStyle s)
+{
+ Q_D(QLCDNumber);
+ d->fill = (s == Flat || s == Filled);
+ d->shadow = (s == Outline || s == Filled);
+ update();
+}
+
+QLCDNumber::SegmentStyle QLCDNumber::segmentStyle() const
+{
+ Q_D(const QLCDNumber);
+ Q_ASSERT(d->fill || d->shadow);
+ if (!d->fill && d->shadow)
+ return Outline;
+ if (d->fill && d->shadow)
+ return Filled;
+ return Flat;
+}
+
+
+/*!\reimp
+*/
+QSize QLCDNumber::sizeHint() const
+{
+ return QSize(10 + 9 * (digitCount() + (smallDecimalPoint() ? 0 : 1)), 23);
+}
+
+/*! \reimp */
+bool QLCDNumber::event(QEvent *e)
+{
+ return QFrame::event(e);
+}
+
+/*!
+ \fn void QLCDNumber::setMargin(int margin)
+ Sets the width of the margin around the contents of the widget to \a margin.
+
+ Use QWidget::setContentsMargins() instead.
+ \sa margin(), QWidget::setContentsMargins()
+*/
+
+/*!
+ \fn int QLCDNumber::margin() const
+ Returns the width of the margin around the contents of the widget.
+
+ Use QWidget::getContentsMargins() instead.
+ \sa setMargin(), QWidget::getContentsMargins()
+*/
+
+QT_END_NAMESPACE
+
+#endif // QT_NO_LCDNUMBER