/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qt Creator. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ****************************************************************************/ #include "watchdelegatewidgets.h" #include #include #include enum { debug = 0 }; namespace Debugger { namespace Internal { // Basic watch line edit. WatchLineEdit::WatchLineEdit(QWidget *parent) : QLineEdit(parent) {} QVariant WatchLineEdit::modelData() const { return QVariant(text()); } void WatchLineEdit::setModelData(const QVariant &v) { if (debug) qDebug("WatchLineEdit::setModelData(%s, '%s')", v.typeName(), qPrintable(v.toString())); setText(v.toString()); } /* ------ IntegerWatchLineEdit helpers: * Integer validator using different number bases. */ class IntegerValidator : public QValidator { public: explicit IntegerValidator(QObject *parent); State validate(QString &, int &) const override; int base() const { return m_base; } void setBase(int b) { m_base = b; } bool isSigned() const { return m_signed; } void setSigned(bool s) { m_signed = s; } bool isBigInt() const { return m_bigInt; } void setBigInt(bool b) { m_bigInt = b; } static State validateEntry(const QString &s, int base, bool signedV, bool bigInt); private: static inline bool isCharAcceptable(const QChar &c, int base); int m_base; bool m_signed; bool m_bigInt; }; IntegerValidator::IntegerValidator(QObject *parent) : QValidator(parent), m_base(10), m_signed(true), m_bigInt(false) { } // Check valid digits depending on base. bool IntegerValidator::isCharAcceptable(const QChar &c, int base) { if (c.isLetter()) return base == 16 && c.toLower().toLatin1() <= 'f'; if (!c.isDigit()) return false; const int digit = c.toLatin1() - '0'; if (base == 8 && digit > 7) return false; if (base == 2 && digit > 1) return false; return true; } QValidator::State IntegerValidator::validate(QString &s, int &) const { return IntegerValidator::validateEntry(s, m_base, m_signed, m_bigInt); } QValidator::State IntegerValidator::validateEntry(const QString &s, int base, bool signedV, bool bigInt) { const int size = s.size(); if (!size) return QValidator::Intermediate; int pos = 0; // Skip sign. if (signedV && s.at(pos) == '-') { pos++; if (pos == size) return QValidator::Intermediate; } // Hexadecimal: '0x'? if (base == 16 && pos + 2 <= size && s.at(pos) == '0' && s.at(pos + 1) == 'x') { pos+= 2; if (pos == size) return QValidator::Intermediate; } // Check characters past sign. for (; pos < size; pos++) if (!isCharAcceptable(s.at(pos), base)) return QValidator::Invalid; // Check conversion unless big integer if (bigInt) return QValidator::Acceptable; bool ok; if (signedV) s.toLongLong(&ok, base); else s.toULongLong(&ok, base); return ok ? QValidator::Acceptable : QValidator::Intermediate; } IntegerWatchLineEdit::IntegerWatchLineEdit(QWidget *parent) : WatchLineEdit(parent), m_validator(new IntegerValidator(this)) { setValidator(m_validator); } bool IntegerWatchLineEdit::isUnsignedHexNumber(const QString &v) { return IntegerValidator::validateEntry(v, 16, false, true) == QValidator::Acceptable; } int IntegerWatchLineEdit::base() const { return m_validator->base(); } void IntegerWatchLineEdit::setBase(int b) { QTC_ASSERT(b, return); m_validator->setBase(b); } bool IntegerWatchLineEdit::isSigned() const { return m_validator->isSigned(); } void IntegerWatchLineEdit::setSigned(bool s) { m_validator->setSigned(s); } bool IntegerWatchLineEdit::isBigInt() const { return m_validator->isBigInt(); } void IntegerWatchLineEdit::setBigInt(bool b) { m_validator->setBigInt(b); } QVariant IntegerWatchLineEdit::modelDataI() const { if (isBigInt()) // Big integer: Plain text return QVariant(text()); bool ok; if (isSigned()) { const qint64 value = text().toLongLong(&ok, base()); if (ok) return QVariant(value); } else { const quint64 value = text().toULongLong(&ok, base()); if (ok) return QVariant(value); } return QVariant(); } QVariant IntegerWatchLineEdit::modelData() const { const QVariant data = modelDataI(); if (debug) qDebug("IntegerLineEdit::modelData(): base=%d, signed=%d, bigint=%d returns %s '%s'", base(), isSigned(), isBigInt(), data.typeName(), qPrintable(data.toString())); return data; } void IntegerWatchLineEdit::setModelData(const QVariant &v) { if (debug) qDebug(">IntegerLineEdit::setModelData(%s, '%s'): base=%d, signed=%d, bigint=%d", v.typeName(), qPrintable(v.toString()), base(), isSigned(), isBigInt()); switch (v.type()) { case QVariant::Int: case QVariant::LongLong: { const qint64 iv = v.toLongLong(); setSigned(true); setText(QString::number(iv, base())); } break; case QVariant::UInt: case QVariant::ULongLong: { const quint64 iv = v.toULongLong(); setSigned(false); setText(QString::number(iv, base())); } break; case QVariant::ByteArray: setNumberText(QString::fromLatin1(v.toByteArray())); break; case QVariant::String: setNumberText(v.toString()); break; default: qWarning("Invalid value (%s) passed to IntegerLineEdit::setModelData", v.typeName()); setText(QString('0')); break; } if (debug) qDebug("