Files
edgetx-gx12/companion/src/labels.cpp
T
CliffandGitHub 333c2828ea fix(color): Limit label lengths, improve lbl display, prevent inv. char (#2287)
* (cpn) Add bullets & length warning

* (fw) Show labels with bullet separators

* (fw) Check all running twice. Remove from here

* (fw) Correct buffer overflow when labels too long

* (fw) Rem bullets in model label string

* (fw, cpn) Labels length

cpn,fw Limit label length
cpn Check correct model on rename length
cpn Focus issues
cpn Add rename,  move up/down.. still has an issue with selection. TODO...
cpn Switch to utf8 encoding
cpn Rename button ;)

* (cpn) Move up down working

re-Fix Checkbox, partially isn't what I thought (not greyed)

* (fw) Add CSV string funcs

Limit length of model edit shorter in portrait mode

* (cpn) Correct Label option showing on B&W

* (fw) Radio filename set but no file exists don't create

* (cpn) Simplify wording

* (fw) Correct debug values

* (fw) Reduce truncation length

* (both) Don't allow special chars in label name

(cpn) Prevent move when at top and bottom
(fw) Remove multiple label length defines
(fw) Shorten truncate length even more

* (fw) Close model_select on new model
2022-09-18 10:47:21 +10:00

255 lines
6.8 KiB
C++

#include "labels.h"
LabelsModel::LabelsModel(QItemSelectionModel *selectionModel,
RadioData *radioData, QObject *parent) :
QAbstractItemModel(parent),
modelsSelection(selectionModel),
radioData(radioData),
selectedModel(-1)
{
connect(modelsSelection, &QItemSelectionModel::currentChanged,
this, &LabelsModel::modelsSelectionChanged );
buildLabelsList();
}
LabelsModel::~LabelsModel()
{
}
Qt::ItemFlags LabelsModel::flags(const QModelIndex &index) const
{
Qt::ItemFlags flags = Qt::ItemIsEnabled;
if (index.column() == 0) {
flags |= Qt::ItemIsUserCheckable;
flags |= Qt::ItemIsSelectable;
flags |= Qt::ItemIsDropEnabled;
flags |= Qt::ItemIsEditable;
if (index.isValid())
flags |= Qt::ItemIsDragEnabled;
}
return flags;
}
bool LabelsModel::setData(const QModelIndex &index, const QVariant &value, int role)
{
if (!index.isValid() || index.column() != 0 ||
index.row() >= radioData->labels.size())
return false;
if (role == Qt::CheckStateRole) {
if (value==Qt::Unchecked && selectedModel != -1) {
if (radioData->removeLabelFromModel(selectedModel, radioData->labels.at(index.row())))
emit modelChanged(selectedModel);
} else {
try{
if (radioData->addLabelToModel(selectedModel, radioData->labels.at(index.row())))
emit modelChanged(selectedModel);
} catch(const std::length_error& le) {
emit labelsFault(tr("Unable to add label \"%1\" to model \"%2\" not enough room")\
.arg(radioData->labels.at(index.row())).arg(le.what()));
}
}
emit dataChanged(this->index(index.row(), 0),
this->index(index.row(), 0));
return true;
} else if (role == Qt::EditRole) {
QString replFrom = labels[index.row()].label;
QString replTo = value.toString();
if (replFrom == replTo) // User exits edit without changing
return true;
if (radioData->labels.indexOf(replTo) == -1) { // Don't allow duplicates
bool modelsChanged = false;
try{
modelsChanged = radioData->renameLabel(replFrom,replTo);
} catch(const std::length_error& le) {
emit labelsFault(tr("Unable to rename \"%1\" to \"%2\" not enough room in model %3")\
.arg(replFrom).arg(replTo).arg(le.what()));
return false;
}
labels[index.row()].label = replTo;
emit dataChanged(this->index(index.row(), 0),
this->index(index.row(), 0));
if (selectedModel != -1 && modelsChanged)
emit modelChanged(selectedModel);
} else {
emit labelsFault(tr("Unable to rename \"%1\" to \"%2\" the label already exists")\
.arg(replFrom).arg(replTo));
}
return true;
}
return false;
}
QVariant LabelsModel::data(const QModelIndex &index, int role) const
{
if (index.row() >= labels.size() || !index.isValid() )
return QVariant();
QString label = radioData->labels.at(index.row());
if (role == Qt::DisplayRole || role == Qt::EditRole) {
if (index.column() == 0) {
return labels.at(index.row()).label;
//return label;
}
} else if (role == Qt::CheckStateRole) {
if (index.column() == 0 && selectedModel >= 0 &&
selectedModel < (int)radioData->models.size()) {
QStringList modelLabels = QString(radioData->models.at(selectedModel).labels).split(',',QString::SkipEmptyParts);
label = RadioData::escapeCSV(label);
return modelLabels.indexOf(label)==-1?Qt::Unchecked:Qt::Checked;
} else if (index.column() == 0 && selectedModel == -1) {
return Qt::Unchecked;
}
}
return QVariant();
}
QModelIndex LabelsModel::index(int row, int column, const QModelIndex &parent) const
{
Q_UNUSED(parent)
if (row < labels.size())
return createIndex(row,0);
return QModelIndex();
}
QModelIndex LabelsModel::parent(const QModelIndex &index) const
{
return QModelIndex();
}
int LabelsModel::rowCount(const QModelIndex &parent) const
{
Q_UNUSED(parent);
return labels.size();
}
int LabelsModel::columnCount(const QModelIndex &parent) const
{
Q_UNUSED(parent);
return 1;
}
QVariant LabelsModel::headerData(int section, Qt::Orientation orientation, int role) const
{
if (role != Qt::DisplayRole ||
orientation != Qt::Horizontal ||
section != 0)
return QVariant();
return tr("Labels");
}
bool LabelsModel::insertRows(int row, int count, const QModelIndex &parent)
{
if (parent.isValid())
return false;
// Find a New Number
for (int i = 0; i < count; i++) {
int newNo=0;
QString newStr;
do {
newStr = QString(tr("New%1").arg(newNo));
if (newNo == 0)
newStr = QString(tr("New"));
newNo++;
} while(radioData->labels.indexOf(newStr) >= 0);
// Add it to radioData
radioData->labels.insert(row+i, newStr);
}
buildLabelsList();
return true;
}
bool LabelsModel::removeRows(int row, int count, const QModelIndex &parent)
{
if (parent.isValid() || row < 0)
return false;
bool deleted=false;
beginRemoveRows(parent, row, row + count - 1);
for (int i = 0; i != count; ++i)
if (radioData->deleteLabel(row+i)) {
deleted = true;
}
endRemoveRows();
// Refresh all
if (deleted)
emit modelChanged(-1);
buildLabelsList();
return true;
}
void LabelsModel::buildLabelsList()
{
labels.clear();
int i=0;
foreach(QString lbl, radioData->labels) {
LabelItem itm;
itm.label = lbl;
itm.radioLabelIndex = i++;
labels.append(itm);
}
if (i) {
emit dataChanged(index(0,0),
index(i-1,0));
}
}
void LabelsModel::modelsSelectionChanged()
{
QModelIndex index = modelsSelection->currentIndex();
if (index.isValid()) {
int mi = modelsSelection->currentIndex().row();
if (mi < (int)radioData->models.size()) {
selectedModel = mi;
buildLabelsList();
}
}
else
selectedModel = -1;
}
QValidator::State LabelValidator::validate(QString &label, int &pos) const
{
Q_UNUSED(pos)
QString lbl = RadioData::escapeCSV(label);
if (lbl.toUtf8().size() > LABEL_LENGTH)
return QValidator::Invalid;
if(lbl.contains('\\') || // TODO: Fix me to allow all, requires FW changes
lbl.contains('\"') ||
lbl.contains(':') ||
lbl.contains('-') ||
lbl.contains('\''))
return QValidator::Invalid;
if(lbl.size() == 0)
return QValidator::Intermediate;
return QValidator::Acceptable;
}
void LabelValidator::fixup(QString &input) const
{
QByteArray output = input.toUtf8();
if (output.size() > LABEL_LENGTH) {
int truncateAt = 0;
for (int i = LABEL_LENGTH; i > 0; i--) {
if ((output[i] & 0xC0) != 0x80) {
truncateAt = i;
break;
}
}
output.truncate(truncateAt);
}
input = QString(output);
input.remove('\\'); // TODO: Fix me to allow all, requires FW changes
input.remove('\"');
input.remove(':');
input.remove('-');
input.remove('\'');
}