File indexing completed on 2024-06-23 05:48:45

0001 /*
0002     This file is part of the Okteta Kasten module, made within the KDE community.
0003 
0004     SPDX-FileCopyrightText: 2007 Friedrich W. H. Kossebau <kossebau@kde.org>
0005 
0006     SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
0007 */
0008 
0009 #include "bytetablemodel.hpp"
0010 
0011 // Okteta core
0012 #include <Okteta/Character>
0013 #include <Okteta/CharCodec>
0014 #include <Okteta/ValueCodec>
0015 // KF
0016 #include <KLocalizedString>
0017 #include <KColorScheme>
0018 // Qt
0019 #include <QApplication>
0020 #include <QFontDatabase>
0021 // Std
0022 #include <utility>
0023 
0024 namespace Kasten {
0025 
0026 static constexpr QChar ByteTableDefaultSubstituteChar =  QLatin1Char('.');
0027 static constexpr QChar ByteTableDefaultUndefinedChar =   QChar(QChar::ReplacementCharacter);
0028 static constexpr int ByteSetSize = 256;
0029 
0030 ByteTableModel::ByteTableModel(QObject* parent)
0031     : QAbstractTableModel(parent)
0032     , mCharCodec(Okteta::CharCodec::createCodec(Okteta::LocalEncoding))
0033     , mSubstituteChar(ByteTableDefaultSubstituteChar)
0034     , mUndefinedChar(ByteTableDefaultUndefinedChar)
0035     , mFixedFont(QFontDatabase::systemFont(QFontDatabase::FixedFont))
0036 {
0037     constexpr Okteta::ValueCoding CodingIds[NofOfValueCodings] = {
0038         Okteta::DecimalCoding,
0039         Okteta::HexadecimalCoding,
0040         Okteta::OctalCoding,
0041         Okteta::BinaryCoding
0042     };
0043     for (int i = 0; i < NofOfValueCodings; ++i) {
0044         mValueCodec[i] = Okteta::ValueCodec::createCodec(CodingIds[i]);
0045     }
0046 }
0047 
0048 ByteTableModel::~ByteTableModel()
0049 {
0050     for (auto* codec : std::as_const(mValueCodec)) {
0051         delete codec;
0052     }
0053 
0054     delete mCharCodec;
0055 }
0056 
0057 void ByteTableModel::setSubstituteChar(QChar substituteChar)
0058 {
0059     if (substituteChar.isNull()) {
0060         substituteChar = ByteTableDefaultSubstituteChar;
0061     }
0062 
0063     if (mSubstituteChar == substituteChar) {
0064         return;
0065     }
0066 
0067     mSubstituteChar = substituteChar;
0068 
0069     Q_EMIT dataChanged(index(0, CharacterId), index(ByteSetSize - 1, CharacterId));
0070 }
0071 
0072 void ByteTableModel::setUndefinedChar(QChar undefinedChar)
0073 {
0074     if (undefinedChar.isNull()) {
0075         undefinedChar = ByteTableDefaultUndefinedChar;
0076     }
0077 
0078     if (mUndefinedChar == undefinedChar) {
0079         return;
0080     }
0081 
0082     mUndefinedChar = undefinedChar;
0083 
0084     Q_EMIT dataChanged(index(0, CharacterId), index(ByteSetSize - 1, CharacterId));
0085 }
0086 
0087 void ByteTableModel::setCharCodec(const QString& codecName)
0088 {
0089     if (codecName == mCharCodec->name()) {
0090         return;
0091     }
0092 
0093     delete mCharCodec;
0094     mCharCodec = Okteta::CharCodec::createCodec(codecName);
0095 
0096     Q_EMIT dataChanged(index(0, CharacterId), index(ByteSetSize - 1, CharacterId));
0097 }
0098 
0099 int ByteTableModel::rowCount(const QModelIndex& parent) const
0100 {
0101     return (!parent.isValid()) ? ByteSetSize : 0;
0102 }
0103 
0104 int ByteTableModel::columnCount(const QModelIndex& parent) const
0105 {
0106     return (!parent.isValid()) ? NoOfIds : 0;
0107 }
0108 
0109 QVariant ByteTableModel::data(const QModelIndex& index, int role) const
0110 {
0111     QVariant result;
0112     if (role == Qt::DisplayRole) {
0113         QString content;
0114 
0115         const unsigned char byte = index.row();
0116         const int column = index.column();
0117         if (column == CharacterId) {
0118             const Okteta::Character decodedChar = mCharCodec->decode(byte);
0119             content =
0120                 decodedChar.isUndefined() ?
0121                     i18nc("@item:intable character is not defined", "undef.") :
0122                 !decodedChar.isPrint() ?
0123                     QString(mSubstituteChar) :
0124                     QString(static_cast<QChar>(decodedChar));
0125             // TODO: show proper descriptions for all control values, incl. space and delete
0126             // cmp. KCharSelect
0127         } else if (column < CharacterId) {
0128             mValueCodec[column]->encode(&content, 0, byte);
0129         }
0130 
0131         result = content;
0132     } else if (role == Qt::ForegroundRole) {
0133         const int column = index.column();
0134         if (column == CharacterId) {
0135             const unsigned char byte = index.row();
0136             const Okteta::Character decodedChar = mCharCodec->decode(byte);
0137             if (decodedChar.isUndefined() || !decodedChar.isPrint()) {
0138                 const QPalette& palette = QApplication::palette();
0139                 const KColorScheme colorScheme(palette.currentColorGroup(), KColorScheme::View);
0140                 result = colorScheme.foreground(KColorScheme::InactiveText);
0141             }
0142         }
0143     } else if (role == Qt::TextAlignmentRole) {
0144         result = static_cast<int>(Qt::AlignVCenter | Qt::AlignRight);
0145     } else if (role == Qt::FontRole) {
0146         result = mFixedFont;
0147     }
0148 
0149     return result;
0150 }
0151 
0152 QVariant ByteTableModel::headerData(int section, Qt::Orientation orientation, int role) const
0153 {
0154     QVariant result;
0155 
0156     if (role == Qt::DisplayRole) {
0157         const QString titel =
0158             section == DecimalId ?     i18nc("@title:column short for Decimal",     "Dec") :
0159             section == HexadecimalId ? i18nc("@title:column short for Hexadecimal", "Hex") :
0160             section == OctalId ?       i18nc("@title:column short for Octal",       "Oct") :
0161             section == BinaryId ?      i18nc("@title:column short for Binary",      "Bin") :
0162             section == CharacterId ?   i18nc("@title:column short for Character",   "Char") :
0163             QString();
0164         result = titel;
0165     } else if (role == Qt::ToolTipRole) {
0166         const QString titel =
0167             section == DecimalId ?
0168                 i18nc("@info:tooltip column contains the value in decimal format",     "Decimal") :
0169             section == HexadecimalId ?
0170                 i18nc("@info:tooltip column contains the value in hexadecimal format", "Hexadecimal") :
0171             section == OctalId ?
0172                 i18nc("@info:tooltip column contains the value in octal format",       "Octal") :
0173             section == BinaryId ?
0174                 i18nc("@info:tooltip column contains the value in binary format",      "Binary") :
0175             section == CharacterId ?
0176                 i18nc("@info:tooltip column contains the character with the value",    "Character") :
0177                 QString();
0178         result = titel;
0179     } else {
0180         result = QAbstractTableModel::headerData(section, orientation, role);
0181     }
0182 
0183     return result;
0184 }
0185 
0186 }
0187 
0188 #include "moc_bytetablemodel.cpp"