Files
QTeletextMaker/x26model.cpp
G.K.MacGregor 1c03481c13 Add stacked widget to edit triplet parameters
The knowledge of how colour, character etc parameters fit within the
address and data triplets is no longer required. We now present
widgets that explicitly refer to colour, character that are more
user friendly.
2020-10-18 20:59:04 +01:00

792 lines
36 KiB
C++

/*
* Copyright (C) 2020 Gavin MacGregor
*
* This file is part of QTeletextMaker.
*
* QTeletextMaker is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* QTeletextMaker is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with QTeletextMaker. If not, see <https://www.gnu.org/licenses/>.
*/
#include <QList>
#include "x26model.h"
X26Model::X26Model(TeletextWidget *parent): QAbstractListModel(parent)
{
m_parentMainWidget = parent;
m_listLoaded = true;
}
void X26Model::setX26ListLoaded(bool newListLoaded)
{
beginResetModel();
m_listLoaded = newListLoaded;
endResetModel();
}
int X26Model::rowCount(const QModelIndex & /*parent*/) const
{
return m_listLoaded ? m_parentMainWidget->document()->currentSubPage()->localEnhance.size() : 0;
}
int X26Model::columnCount(const QModelIndex & /*parent*/) const
{
return 4;
}
QVariant X26Model::data(const QModelIndex &index, int role) const
{
int mode = m_parentMainWidget->document()->currentSubPage()->localEnhance.at(index.row()).mode();
// Qt::UserRole will always return the raw values
if (role == Qt::UserRole)
switch (index.column()) {
case 0:
return m_parentMainWidget->document()->currentSubPage()->localEnhance.at(index.row()).address();
case 1:
return m_parentMainWidget->document()->currentSubPage()->localEnhance.at(index.row()).mode();
case 2:
return m_parentMainWidget->document()->currentSubPage()->localEnhance.at(index.row()).data();
default:
return QVariant();
}
if (role == Qt::DisplayRole || role == Qt::EditRole)
switch (index.column()) {
case 0:
// Show row number only if address part of triplet actually represents a row
// i.e. Full row colour, Set Active Position and Origin Modifier
if (!m_parentMainWidget->document()->currentSubPage()->localEnhance.at(index.row()).isRowTriplet())
return QVariant();
// For Origin Modifier address of 40 refers to same row, so show it as 0
if (m_parentMainWidget->document()->currentSubPage()->localEnhance.at(index.row()).mode() == 0x10) {
if (m_parentMainWidget->document()->currentSubPage()->localEnhance.at(index.row()).address() == 40)
return 0;
else
return m_parentMainWidget->document()->currentSubPage()->localEnhance.at(index.row()).addressRow();
}
if (m_parentMainWidget->document()->currentSubPage()->localEnhance.at(index.row()).mode() == 0x01 || m_parentMainWidget->document()->currentSubPage()->localEnhance.at(index.row()).mode() == 0x04)
return m_parentMainWidget->document()->currentSubPage()->localEnhance.at(index.row()).addressRow();
else
return QVariant();
case 1:
if (!m_parentMainWidget->document()->currentSubPage()->localEnhance.at(index.row()).isRowTriplet())
return m_parentMainWidget->document()->currentSubPage()->localEnhance.at(index.row()).addressColumn();
// For Set Active Position and Origin Modifier, data is the column
else if (mode == 0x04 || mode == 0x10)
return m_parentMainWidget->document()->currentSubPage()->localEnhance.at(index.row()).data();
else
return QVariant();
}
if (!m_parentMainWidget->document()->currentSubPage()->localEnhance.at(index.row()).isRowTriplet())
mode |= 0x20;
QString result;
if (role == Qt::DisplayRole) {
if (index.column() == 2)
return (modeTripletName[mode]);
// Column 3 - describe effects of data/address triplet parameters in plain English
switch (mode) {
case 0x01: // Full row colour
case 0x07: // Address row 0
if ((m_parentMainWidget->document()->currentSubPage()->localEnhance.at(index.row()).data() & 0x60) == 0x60)
result = ", down to bottom";
else if ((m_parentMainWidget->document()->currentSubPage()->localEnhance.at(index.row()).data() & 0x60) == 0x00)
result = ", this row only";
// fall-through
case 0x00: // Full screen colour
if (!(result.isEmpty()) || (m_parentMainWidget->document()->currentSubPage()->localEnhance.at(index.row()).data() & 0x60) == 0x00) {
result.prepend(QString("CLUT %1:%2").arg((m_parentMainWidget->document()->currentSubPage()->localEnhance.at(index.row()).data() & 0x18) >> 3).arg(m_parentMainWidget->document()->currentSubPage()->localEnhance.at(index.row()).data() & 0x07));
return result;
}
break;
case 0x04: // Set Active Position
case 0x10: // Origin Modifier
// For Set Active Position and Origin Modifier, data is the column, so return blank
return QVariant();
case 0x11 ... 0x13: // Invoke object
switch (m_parentMainWidget->document()->currentSubPage()->localEnhance.at(index.row()).address() & 0x18) {
case 0x08:
return QString("Local: d%1 t%2").arg((m_parentMainWidget->document()->currentSubPage()->localEnhance.at(index.row()).data() >> 4) | ((m_parentMainWidget->document()->currentSubPage()->localEnhance.at(index.row()).address() & 0x01) << 3)).arg(m_parentMainWidget->document()->currentSubPage()->localEnhance.at(index.row()).data() & 0x0f);
case 0x10:
result = "POP";
break;
case 0x18:
result = "GPOP";
break;
// case 0x00: shouldn't happen since that would make a column triplet, not a row triplet
}
result.append(QString(": subpage %1 pkt %2 trplt %3 bits ").arg(m_parentMainWidget->document()->currentSubPage()->localEnhance.at(index.row()).data() & 0x0f).arg((m_parentMainWidget->document()->currentSubPage()->localEnhance.at(index.row()).address() & 0x03) + 1).arg(((m_parentMainWidget->document()->currentSubPage()->localEnhance.at(index.row()).data() & 0x60) >> 5) * 3 + (mode & 0x03)));
if (m_parentMainWidget->document()->currentSubPage()->localEnhance.at(index.row()).data() & 0x10)
result.append("10-18");
else
result.append("1-9");
return result;
case 0x15 ... 0x17: // Define object
result = (QString("Local: d%1 t%2, ").arg((m_parentMainWidget->document()->currentSubPage()->localEnhance.at(index.row()).data() >> 4) | ((m_parentMainWidget->document()->currentSubPage()->localEnhance.at(index.row()).address() & 1) << 3)).arg(m_parentMainWidget->document()->currentSubPage()->localEnhance.at(index.row()).data() & 0x0f));
switch (m_parentMainWidget->document()->currentSubPage()->localEnhance.at(index.row()).address() & 0x18) {
case 0x08:
result.append("L2.5 only");
break;
case 0x10:
result.append("L3.5 only");
break;
case 0x18:
result.append("L2.5 and 3.5");
break;
// case 0x00: shouldn't happen since that would make a column triplet, not a row triplet
}
return result;
case 0x18: // DRCS mode
result = (m_parentMainWidget->document()->currentSubPage()->localEnhance.at(index.row()).data() & 0x40) == 0x40 ? "Normal" : "Global";
result.append(QString(": subpage %1, ").arg(m_parentMainWidget->document()->currentSubPage()->localEnhance.at(index.row()).data() & 0x0f));
switch (m_parentMainWidget->document()->currentSubPage()->localEnhance.at(index.row()).data() & 0x30) {
case 0x10:
result.append("L2.5 only");
break;
case 0x20:
result.append("L3.5 only");
break;
case 0x30:
result.append("L2.5 and 3.5");
break;
//case 0x00:
// result = "Reserved";
// break;
}
return result;
case 0x1f: // Termination
switch (m_parentMainWidget->document()->currentSubPage()->localEnhance.at(index.row()).data() & 0x07) {
case 0x00:
return "Intermed (G)POP subpage. End of object, more follows";
break;
case 0x01:
return "Intermed (G)POP subpage. End of last object on page";
break;
case 0x02:
return "Last (G)POP subpage. End of object, more follows";
break;
case 0x03:
return "Last (G)POP subpage. End of last object on page";
break;
case 0x04:
return "Local object definitions. End of object, more follows";
break;
case 0x05:
return "Local object definitions. End of last object on page";
break;
case 0x06:
return "End of local enhance data. Local objects follow";
break;
case 0x07:
return "End of local enhance data. No local objects";
break;
}
break;
case 0x08 ... 0x0d: // PDC
return QString("0x%1").arg(m_parentMainWidget->document()->currentSubPage()->localEnhance.at(index.row()).data(), 2, 16, QChar('0'));
case 0x20: // Foreground colour
case 0x23: // Background colour
if (!(m_parentMainWidget->document()->currentSubPage()->localEnhance.at(index.row()).data() & 0x60))
return QString("CLUT %1:%2").arg((m_parentMainWidget->document()->currentSubPage()->localEnhance.at(index.row()).data() & 0x18) >> 3).arg(m_parentMainWidget->document()->currentSubPage()->localEnhance.at(index.row()).data() & 0x07);
break;
case 0x21: // G1 mosaic character
case 0x22: // G3 mosaic character at level 1.5
case 0x29: // G0 character
case 0x2b: // G3 mosaic character at level >=2.5
case 0x2f ... 0x3f: // G2 character or G0 diacrtitical mark
if (m_parentMainWidget->document()->currentSubPage()->localEnhance.at(index.row()).data() >= 0x20)
return QString("0x%1").arg(m_parentMainWidget->document()->currentSubPage()->localEnhance.at(index.row()).data(), 2, 16);
break;
case 0x27: // Flash functions
if (m_parentMainWidget->document()->currentSubPage()->localEnhance.at(index.row()).data() < 0x18) {
switch (m_parentMainWidget->document()->currentSubPage()->localEnhance.at(index.row()).data() & 0x03) {
case 0x00:
result = "Steady";
break;
case 0x01:
result = "Normal";
break;
case 0x02:
result = "Invert";
break;
case 0x03:
result = "Adj CLUT";
break;
}
switch (m_parentMainWidget->document()->currentSubPage()->localEnhance.at(index.row()).data() & 0x1c) {
case 0x00:
result.append(", 1Hz");
break;
case 0x04:
result.append(", 2Hz ph 1");
break;
case 0x08:
result.append(", 2Hz ph 2");
break;
case 0x0c:
result.append(", 2Hz ph 3");
break;
case 0x10:
result.append(", 2Hz inc");
break;
case 0x14:
result.append(", 2Hz dec");
break;
}
return result;
}
break;
//TODO case 0x28: // G0 and G2 designation
case 0x2c: // Display attributes
if (m_parentMainWidget->document()->currentSubPage()->localEnhance.at(index.row()).data() & 0x02)
result.append("Boxing ");
if (m_parentMainWidget->document()->currentSubPage()->localEnhance.at(index.row()).data() & 0x04)
result.append("Conceal ");
if (m_parentMainWidget->document()->currentSubPage()->localEnhance.at(index.row()).data() & 0x10)
result.append("Invert ");
if (m_parentMainWidget->document()->currentSubPage()->localEnhance.at(index.row()).data() & 0x20)
result.append("Underline ");
if (result.isEmpty())
result = "None";
else
// Chop off the last space
result.chop(1);
switch (m_parentMainWidget->document()->currentSubPage()->localEnhance.at(index.row()).data() & 0x41) {
case 0x00:
result.append(", normal size");
break;
case 0x01:
result.append(", double height");
break;
case 0x40:
result.append(", double width");
break;
case 0x41:
result.append(", double size");
break;
}
return result;
case 0x2d: // DRCS character
result = (m_parentMainWidget->document()->currentSubPage()->localEnhance.at(index.row()).data() & 0x40) == 0x40 ? "Normal" : "Global";
result.append(QString(": %1").arg(m_parentMainWidget->document()->currentSubPage()->localEnhance.at(index.row()).data() & 0x3f));
return result;
case 0x2e: // Font style
if (m_parentMainWidget->document()->currentSubPage()->localEnhance.at(index.row()).data() & 0x01)
result.append("Proportional ");
if (m_parentMainWidget->document()->currentSubPage()->localEnhance.at(index.row()).data() & 0x02)
result.append("Bold ");
if (m_parentMainWidget->document()->currentSubPage()->localEnhance.at(index.row()).data() & 0x04)
result.append("Italic ");
if (result.isEmpty())
result = "None";
else
// Chop off the last space
result.chop(1);
result.append(QString(", %1 row(s)").arg(m_parentMainWidget->document()->currentSubPage()->localEnhance.at(index.row()).data() >> 4));
return result;
case 0x28: // Modified G0 and G2 character set
case 0x26: // PDC
return QString("0x%1").arg(m_parentMainWidget->document()->currentSubPage()->localEnhance.at(index.row()).data(), 2, 16, QChar('0'));
default: // Reserved
return QString("Reserved 0x%1").arg(m_parentMainWidget->document()->currentSubPage()->localEnhance.at(index.row()).data(), 2, 16, QChar('0'));
}
// Reserved mode or data
return QString("Reserved 0x%1").arg(m_parentMainWidget->document()->currentSubPage()->localEnhance.at(index.row()).data(), 2, 16, QChar('0'));
}
if (role == Qt::EditRole && index.column() == 2) {
if (!m_parentMainWidget->document()->currentSubPage()->localEnhance.at(index.row()).isRowTriplet())
mode |= 0x20;
return mode;
}
if (role <= Qt::UserRole)
return QVariant();
switch (role) {
case Qt::UserRole+1:
switch (mode) {
case 0x00: // Full screen colour
case 0x01: // Full row colour
case 0x07: // Address row 0
case 0x20: // Foreground colour
case 0x23: // Background colour
// Colour index
return m_parentMainWidget->document()->currentSubPage()->localEnhance.at(index.row()).data() & 0x1f;
case 0x11 ... 0x13: // Invoke object
// Object source: Local, POP or GPOP
return ((m_parentMainWidget->document()->currentSubPage()->localEnhance.at(index.row()).address() & 0x18) >> 3) - 1;
break;
case 0x15 ... 0x17: // Define object
// Required at level 2.5
return (m_parentMainWidget->document()->currentSubPage()->localEnhance.at(index.row()).address() & 0x08) == 0x08;
case 0x18: // DRCS mode
// Required at level 2.5
return (m_parentMainWidget->document()->currentSubPage()->localEnhance.at(index.row()).data() & 0x10) == 0x10;
case 0x1f: // Termination
// Intermed POP subpage|Last POP subpage|Local Object|Local enhance
return ((m_parentMainWidget->document()->currentSubPage()->localEnhance.at(index.row()).data() & 0x06) >> 1);
case 0x27: // Flash functions
// Flash mode
return m_parentMainWidget->document()->currentSubPage()->localEnhance.at(index.row()).data() & 0x03;
case 0x2c: // Display attributes
// Text size
return (m_parentMainWidget->document()->currentSubPage()->localEnhance.at(index.row()).data() & 0x01) | ((m_parentMainWidget->document()->currentSubPage()->localEnhance.at(index.row()).data() & 0x40) >> 5);
case 0x2d: // DRCS character
// Normal or Global
return (m_parentMainWidget->document()->currentSubPage()->localEnhance.at(index.row()).data() & 0x40) == 0x40;
case 0x2e: // Font style
// Proportional
return (m_parentMainWidget->document()->currentSubPage()->localEnhance.at(index.row()).data() & 0x01) == 0x01;
default:
return m_parentMainWidget->document()->currentSubPage()->localEnhance.at(index.row()).data();
}
break;
case Qt::UserRole+2:
switch (mode) {
case 0x01: // Full row colour
case 0x07: // Address row 0
// "this row only" or "down to bottom"
return (m_parentMainWidget->document()->currentSubPage()->localEnhance.at(index.row()).data() & 0x60) == 0x60;
case 0x11 ... 0x13: // Invoke object
if ((m_parentMainWidget->document()->currentSubPage()->localEnhance.at(index.row()).address() & 0x08) == 0x08)
// Local object: Designation code
return ((m_parentMainWidget->document()->currentSubPage()->localEnhance.at(index.row()).address() & 0x01) << 3) | ((m_parentMainWidget->document()->currentSubPage()->localEnhance.at(index.row()).data() & 0x70) >> 4);
else
// (G)POP object: Subpage
return m_parentMainWidget->document()->currentSubPage()->localEnhance.at(index.row()).data() & 0x0f;
break;
case 0x15 ... 0x17: // Define object
// Local object: Designation code
return ((m_parentMainWidget->document()->currentSubPage()->localEnhance.at(index.row()).address() & 0x01) << 3) | ((m_parentMainWidget->document()->currentSubPage()->localEnhance.at(index.row()).data() & 0x70) >> 4);
case 0x18: // DRCS mode
// Required at level 3.5
return (m_parentMainWidget->document()->currentSubPage()->localEnhance.at(index.row()).data() & 0x20) == 0x20;
case 0x1f: // Termination
// More follows/Last
return (m_parentMainWidget->document()->currentSubPage()->localEnhance.at(index.row()).data() & 0x01) == 0x01;
case 0x27: // Flash functions
// Flash rate and phase
return m_parentMainWidget->document()->currentSubPage()->localEnhance.at(index.row()).data() >> 2;
case 0x2c: // Display attributes
// Boxing/window
return (m_parentMainWidget->document()->currentSubPage()->localEnhance.at(index.row()).data() & 0x02) == 0x02;
case 0x2d: // DRCS character
// Character number
return m_parentMainWidget->document()->currentSubPage()->localEnhance.at(index.row()).data() & 0x3f;
case 0x2e: // Font style
// Bold
return (m_parentMainWidget->document()->currentSubPage()->localEnhance.at(index.row()).data() & 0x02) == 0x02;
}
break;
case Qt::UserRole+3:
switch (mode) {
case 0x11 ... 0x13: // Invoke object
if ((m_parentMainWidget->document()->currentSubPage()->localEnhance.at(index.row()).address() & 0x08) == 0x08)
// Local object: Triplet number
return m_parentMainWidget->document()->currentSubPage()->localEnhance.at(index.row()).data() & 0x0f;
else
// (G)POP object: Pointer location
return (m_parentMainWidget->document()->currentSubPage()->localEnhance.at(index.row()).address() & 0x03) + 1;
break;
case 0x15 ... 0x17: // Define object
// Local object: Triplet number
return m_parentMainWidget->document()->currentSubPage()->localEnhance.at(index.row()).data() & 0x0f;
case 0x18: // DRCS mode
// Normal or Global
return (m_parentMainWidget->document()->currentSubPage()->localEnhance.at(index.row()).data() & 0x40) == 0x40;
case 0x2c: // Display attributes
// Conceal
return (m_parentMainWidget->document()->currentSubPage()->localEnhance.at(index.row()).data() & 0x04) == 0x04;
case 0x2e: // Font style
// Italics
return (m_parentMainWidget->document()->currentSubPage()->localEnhance.at(index.row()).data() & 0x04) == 0x04;
}
break;
case Qt::UserRole+4:
switch (mode) {
case 0x11 ... 0x13: // Invoke object
// (G)POP object: Triplet number
return m_parentMainWidget->document()->currentSubPage()->localEnhance.at(index.row()).data() >> 5;
case 0x15 ... 0x17: // Define object
// Required at level 3.5
return (m_parentMainWidget->document()->currentSubPage()->localEnhance.at(index.row()).address() & 0x10) == 0x10;
case 0x18: // DRCS mode
// Subpage
return m_parentMainWidget->document()->currentSubPage()->localEnhance.at(index.row()).data() & 0x0f;
case 0x2c: // Display attributes
// Invert
return (m_parentMainWidget->document()->currentSubPage()->localEnhance.at(index.row()).data() & 0x10) == 0x10;
case 0x2e: // Font style
// Number of rows
return m_parentMainWidget->document()->currentSubPage()->localEnhance.at(index.row()).data() >> 4;
}
break;
case Qt::UserRole+5:
switch (mode) {
case 0x11 ... 0x13: // Invoke object
// (G)POP object: Pointer position
return (m_parentMainWidget->document()->currentSubPage()->localEnhance.at(index.row()).data() & 0x10) >> 4;
case 0x2c: // Display attributes
// Underline/Separated
return (m_parentMainWidget->document()->currentSubPage()->localEnhance.at(index.row()).data() & 0x20) == 0x20;
}
break;
}
return QVariant();
}
bool X26Model::setData(const QModelIndex &index, const QVariant &value, int role)
{
if (!index.isValid())
return false;
// Raw address, mode and data values
if (role == Qt::UserRole && value.canConvert<int>() && index.column() <= 2) {
int intValue = value.toInt();
switch (index.column()) {
case 0:
m_parentMainWidget->document()->currentSubPage()->localEnhance[index.row()].setAddress(intValue);
break;
case 1:
m_parentMainWidget->document()->currentSubPage()->localEnhance[index.row()].setMode(intValue);
break;
case 2:
m_parentMainWidget->document()->currentSubPage()->localEnhance[index.row()].setData(intValue);
break;
}
emit dataChanged(createIndex(index.row(), 0), createIndex(index.row(), 3), {role});
m_parentMainWidget->refreshPage();
return true;
}
int mode = m_parentMainWidget->document()->currentSubPage()->localEnhance.at(index.row()).modeExt();
// Row, column and triplet mode
if (role == Qt::EditRole && value.canConvert<int>()) {
int intValue = value.toInt();
if (intValue < 0)
return false;
switch (index.column()) {
case 0:
if (intValue > 24)
return false;
if (((mode == 0x04) || (mode == 0x01)) && intValue == 0)
return false;
if (mode == 0x10)
m_parentMainWidget->document()->currentSubPage()->localEnhance[index.row()].setAddress(intValue + 40);
else
m_parentMainWidget->document()->currentSubPage()->localEnhance[index.row()].setAddressRow(intValue);
emit dataChanged(index, index, {role});
m_parentMainWidget->refreshPage();
return true;
case 1:
// Origin modifier allows columns up to 71
if (intValue > (mode == 0x10 ? 71 : 39))
return false;
// For Set Active Position and Origin Modifier, data is the column
if (mode == 0x04 || mode == 0x10)
m_parentMainWidget->document()->currentSubPage()->localEnhance[index.row()].setData(intValue);
else
m_parentMainWidget->document()->currentSubPage()->localEnhance[index.row()].setAddressColumn(intValue);
emit dataChanged(index, index, {role});
m_parentMainWidget->refreshPage();
return true;
case 2:
if (intValue < 0x20 && !m_parentMainWidget->document()->currentSubPage()->localEnhance.at(index.row()).isRowTriplet()) {
// Changing mode from column triplet to row triplet
m_parentMainWidget->document()->currentSubPage()->localEnhance[index.row()].setAddressRow(1);
m_parentMainWidget->document()->currentSubPage()->localEnhance[index.row()].setData(0);
}
if (intValue >= 0x20 && m_parentMainWidget->document()->currentSubPage()->localEnhance.at(index.row()).isRowTriplet()) {
// Changing mode from row triplet to column triplet
m_parentMainWidget->document()->currentSubPage()->localEnhance[index.row()].setAddressColumn(0);
m_parentMainWidget->document()->currentSubPage()->localEnhance[index.row()].setData(0);
}
m_parentMainWidget->document()->currentSubPage()->localEnhance[index.row()].setMode(intValue & 0x1f);
emit dataChanged(createIndex(index.row(), 0), createIndex(index.row(), 3), {role});
m_parentMainWidget->refreshPage();
return true;
}
return false;
}
if (role <= Qt::UserRole || !value.canConvert<int>())
return false;
int intValue = value.toInt();
if (intValue < 0)
return false;
// Triplet data
switch (role) {
case Qt::UserRole+1:
switch (mode) {
case 0x00: // Full screen colour
case 0x01: // Full row colour
case 0x07: // Address row 0
case 0x20: // Foreground colour
case 0x23: // Background colour
// Colour index
m_parentMainWidget->document()->currentSubPage()->localEnhance[index.row()].setData((m_parentMainWidget->document()->currentSubPage()->localEnhance.at(index.row()).data() & 0x60) | intValue);
break;
// case 0x04: // Set Active Position - data is the column
// m_parentMainWidget->document()->currentSubPage()->localEnhance[index.row()].setData(intValue);
// break;
case 0x11 ... 0x13: // Invoke object
// Object source: Local, POP or GPOP
m_parentMainWidget->document()->currentSubPage()->localEnhance[index.row()].setAddress((m_parentMainWidget->document()->currentSubPage()->localEnhance.at(index.row()).address() & 0x27) | ((intValue+1) << 3));
break;
case 0x15 ... 0x17: // Define object
// Required at level 2.5
m_parentMainWidget->document()->currentSubPage()->localEnhance[index.row()].setAddress((m_parentMainWidget->document()->currentSubPage()->localEnhance.at(index.row()).address() & 0x37) | (intValue << 2));
break;
case 0x18: // DRCS Mode
// Required at level 2.5
m_parentMainWidget->document()->currentSubPage()->localEnhance[index.row()].setData((m_parentMainWidget->document()->currentSubPage()->localEnhance.at(index.row()).data() & 0x6f) | (intValue << 3));
break;
case 0x1f: // Termination
// Intermed POP subpage|Last POP subpage|Local Object|Local enhance
m_parentMainWidget->document()->currentSubPage()->localEnhance[index.row()].setData((m_parentMainWidget->document()->currentSubPage()->localEnhance.at(index.row()).data() & 0x01) | (intValue << 1));
break;
case 0x27: // Flash functions
// Flash mode
m_parentMainWidget->document()->currentSubPage()->localEnhance[index.row()].setData((m_parentMainWidget->document()->currentSubPage()->localEnhance.at(index.row()).data() & 0x1c) | intValue);
break;
case 0x2c: // Display attributes
// Text size
m_parentMainWidget->document()->currentSubPage()->localEnhance[index.row()].setData((m_parentMainWidget->document()->currentSubPage()->localEnhance.at(index.row()).data() & 0x36) | ((intValue & 0x02) << 5) | (intValue & 0x01));
break;
case 0x2d: // DRCS character
// Normal or Global
m_parentMainWidget->document()->currentSubPage()->localEnhance[index.row()].setData((m_parentMainWidget->document()->currentSubPage()->localEnhance.at(index.row()).data() & 0x3f) | (intValue << 6));
break;
case 0x2e: // Font style
// Proportional
m_parentMainWidget->document()->currentSubPage()->localEnhance[index.row()].setData((m_parentMainWidget->document()->currentSubPage()->localEnhance.at(index.row()).data() & 0x7e) | intValue);
break;
default:
m_parentMainWidget->document()->currentSubPage()->localEnhance[index.row()].setData(intValue);
}
break;
case Qt::UserRole+2:
switch (mode) {
case 0x00: // Full screen colour
case 0x01: // Full row colour
case 0x07: // Address row 0
// "this row only" or "down to bottom"
m_parentMainWidget->document()->currentSubPage()->localEnhance[index.row()].setData((m_parentMainWidget->document()->currentSubPage()->localEnhance.at(index.row()).data() & 0x1f) | (intValue * 0x60));
break;
case 0x11 ... 0x13: // Invoke object
if ((m_parentMainWidget->document()->currentSubPage()->localEnhance.at(index.row()).address() & 0x08) == 0x08) {
// Local object: Designation code
m_parentMainWidget->document()->currentSubPage()->localEnhance[index.row()].setData((m_parentMainWidget->document()->currentSubPage()->localEnhance.at(index.row()).data() & 0x0f) | ((intValue & 0x07) << 4));
m_parentMainWidget->document()->currentSubPage()->localEnhance[index.row()].setAddress((m_parentMainWidget->document()->currentSubPage()->localEnhance.at(index.row()).address() & 0x3e) | (intValue >> 3));
} else
// (G)POP object: Subpage
m_parentMainWidget->document()->currentSubPage()->localEnhance[index.row()].setData((m_parentMainWidget->document()->currentSubPage()->localEnhance.at(index.row()).data() & 0x30) | intValue);
break;
case 0x15 ... 0x17: // Define object
// Local object: Designation code
m_parentMainWidget->document()->currentSubPage()->localEnhance[index.row()].setData((m_parentMainWidget->document()->currentSubPage()->localEnhance.at(index.row()).data() & 0x0f) | ((intValue & 0x07) << 4));
m_parentMainWidget->document()->currentSubPage()->localEnhance[index.row()].setAddress((m_parentMainWidget->document()->currentSubPage()->localEnhance.at(index.row()).address() & 0x3e) | (intValue >> 3));
break;
case 0x18: // DRCS Mode
// Required at level 3.5
m_parentMainWidget->document()->currentSubPage()->localEnhance[index.row()].setData((m_parentMainWidget->document()->currentSubPage()->localEnhance.at(index.row()).data() & 0x5f) | (intValue << 4));
break;
case 0x1f: // Termination
// More follows/Last
m_parentMainWidget->document()->currentSubPage()->localEnhance[index.row()].setData((m_parentMainWidget->document()->currentSubPage()->localEnhance.at(index.row()).data() & 0x06) | intValue);
break;
case 0x27: // Flash functions
// Flash rate and phase
m_parentMainWidget->document()->currentSubPage()->localEnhance[index.row()].setData((m_parentMainWidget->document()->currentSubPage()->localEnhance.at(index.row()).data() & 0x03) | (intValue << 2));
break;
case 0x2c: // Display attributes
// Boxing/window
m_parentMainWidget->document()->currentSubPage()->localEnhance[index.row()].setData((m_parentMainWidget->document()->currentSubPage()->localEnhance.at(index.row()).data() & 0x7d) | (intValue << 1));
break;
case 0x2d: // DRCS character
// Character number
m_parentMainWidget->document()->currentSubPage()->localEnhance[index.row()].setData((m_parentMainWidget->document()->currentSubPage()->localEnhance.at(index.row()).data() & 0x40) | intValue);
break;
case 0x2e: // Font style
// Bold
m_parentMainWidget->document()->currentSubPage()->localEnhance[index.row()].setData((m_parentMainWidget->document()->currentSubPage()->localEnhance.at(index.row()).data() & 0x7d) | (intValue << 1));
break;
}
break;
case Qt::UserRole+3:
switch (mode) {
case 0x11 ... 0x13: // Invoke object
if ((m_parentMainWidget->document()->currentSubPage()->localEnhance.at(index.row()).address() & 0x08) == 0x08)
// Local object: triplet number
m_parentMainWidget->document()->currentSubPage()->localEnhance[index.row()].setData((m_parentMainWidget->document()->currentSubPage()->localEnhance.at(index.row()).data() & 0x70) | intValue);
else
// (G)POP object: Pointer location
m_parentMainWidget->document()->currentSubPage()->localEnhance[index.row()].setAddress((m_parentMainWidget->document()->currentSubPage()->localEnhance.at(index.row()).address() & 0x7c) | (intValue - 1));
break;
case 0x15 ... 0x17: // Define object
// Local object: triplet number
m_parentMainWidget->document()->currentSubPage()->localEnhance[index.row()].setData((m_parentMainWidget->document()->currentSubPage()->localEnhance.at(index.row()).data() & 0x70) | intValue);
break;
case 0x18: // DRCS Mode
// Normal or Global
m_parentMainWidget->document()->currentSubPage()->localEnhance[index.row()].setData((m_parentMainWidget->document()->currentSubPage()->localEnhance.at(index.row()).data() & 0x3f) | (intValue << 6));
break;
case 0x2c: // Display attributes
// Conceal
m_parentMainWidget->document()->currentSubPage()->localEnhance[index.row()].setData((m_parentMainWidget->document()->currentSubPage()->localEnhance.at(index.row()).data() & 0x7b) | (intValue << 2));
break;
case 0x2e: // Font style
// Italics
m_parentMainWidget->document()->currentSubPage()->localEnhance[index.row()].setData((m_parentMainWidget->document()->currentSubPage()->localEnhance.at(index.row()).data() & 0x7b) | (intValue << 2));
break;
}
break;
case Qt::UserRole+4:
switch (mode) {
case 0x11 ... 0x13: // Invoke object
// (G)POP object: Triplet number
m_parentMainWidget->document()->currentSubPage()->localEnhance[index.row()].setData((m_parentMainWidget->document()->currentSubPage()->localEnhance.at(index.row()).data() & 0x1f) | (intValue << 5));
break;
case 0x15 ... 0x17: // Define object
// Required at level 3.5
m_parentMainWidget->document()->currentSubPage()->localEnhance[index.row()].setAddress((m_parentMainWidget->document()->currentSubPage()->localEnhance.at(index.row()).address() & 0x2f) | (intValue << 3));
break;
case 0x18: // DRCS Mode
// Subpage
m_parentMainWidget->document()->currentSubPage()->localEnhance[index.row()].setData((m_parentMainWidget->document()->currentSubPage()->localEnhance.at(index.row()).data() & 0x70) | intValue);
break;
case 0x2c: // Display attributes
// Invert
m_parentMainWidget->document()->currentSubPage()->localEnhance[index.row()].setData((m_parentMainWidget->document()->currentSubPage()->localEnhance.at(index.row()).data() & 0x6f) | (intValue << 4));
break;
case 0x2e: // Font style
// Number of rows
m_parentMainWidget->document()->currentSubPage()->localEnhance[index.row()].setData((m_parentMainWidget->document()->currentSubPage()->localEnhance.at(index.row()).data() & 0x07) | (intValue << 4));
break;
}
break;
case Qt::UserRole+5:
switch (mode) {
case 0x11 ... 0x13: // Invoke object
// (G)POP object: Pointer position
m_parentMainWidget->document()->currentSubPage()->localEnhance[index.row()].setData((m_parentMainWidget->document()->currentSubPage()->localEnhance.at(index.row()).data() & 0x6f) | (intValue << 4));
break;
case 0x2c: // Display attributes
// Invert
m_parentMainWidget->document()->currentSubPage()->localEnhance[index.row()].setData((m_parentMainWidget->document()->currentSubPage()->localEnhance.at(index.row()).data() & 0x5f) | (intValue << 5));
break;
}
break;
}
emit dataChanged(createIndex(index.row(), 0), createIndex(index.row(), 3), {role});
m_parentMainWidget->refreshPage();
return true;
}
QVariant X26Model::headerData(int section, Qt::Orientation orientation, int role) const
{
if (role == Qt::DisplayRole) {
if (orientation == Qt::Horizontal) {
switch (section) {
case 0:
return tr("Row");
case 1:
return tr("Col");
case 2:
return tr("Mode");
case 3:
return tr("Data");
default:
return QVariant();
}
} else if (orientation == Qt::Vertical)
return QString("d%1 t%2").arg(section / 13).arg(section % 13);
}
return QVariant();
}
bool X26Model::insertFirstRow()
{
X26Triplet firstTriplet;
firstTriplet.setAddress(63);
firstTriplet.setMode(31);
firstTriplet.setData(7);
beginInsertRows(QModelIndex(), 0, 0);
m_parentMainWidget->document()->currentSubPage()->localEnhance.insert(0, firstTriplet);
endInsertRows();
// Since we always insert a Termination Marker there's no need to refresh the page
return true;
}
bool X26Model::insertRows(int position, int rows, const QModelIndex &parent)
{
Q_UNUSED(parent);
X26Triplet copyTriplet = m_parentMainWidget->document()->currentSubPage()->localEnhance.at(position);
beginInsertRows(QModelIndex(), position, position+rows-1);
for (int row=0; row<rows; ++row)
m_parentMainWidget->document()->currentSubPage()->localEnhance.insert(position+row, copyTriplet);
endInsertRows();
// Since we always insert duplicates of the selected triplet there's no need to refresh the page
return true;
}
bool X26Model::removeRows(int position, int rows, const QModelIndex &index)
{
Q_UNUSED(index);
beginRemoveRows(QModelIndex(), position, position+rows-1);
for (int row=0; row<rows; ++row)
m_parentMainWidget->document()->currentSubPage()->localEnhance.removeAt(position+row);
endRemoveRows();
m_parentMainWidget->refreshPage();
return true;
}
/*
Qt::ItemFlags X26Model::flags(const QModelIndex &index) const
{
if (!index.isValid())
return QAbstractItemModel::flags(index);
if (index.column() <= 1)
return QAbstractItemModel::flags(index);
if (index.column() >= 2)
return QAbstractItemModel::flags(index) | Qt::ItemIsEditable;
return QAbstractItemModel::flags(index);
}
*/