Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: [Env view] Fixed issues with environment variable view #882

Merged
merged 1 commit into from
Aug 9, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
199 changes: 199 additions & 0 deletions src/common/util/namevaluemodel.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,199 @@
// SPDX-FileCopyrightText: 2024 UnionTech Software Technology Co., Ltd.
//
// SPDX-License-Identifier: GPL-3.0-or-later

#include "namevaluemodel.h"

class NameValueModelPrivate
{
public:
int indexOf(const QString &name);
int findInsertPosition(const QString &name);

public:
QVariantMap itemMap;
};

int NameValueModelPrivate::indexOf(const QString &name)
{
for (int i = 0; i < itemMap.size(); ++i) {
if (itemMap.keys()[i] == name)
return i;
}

return -1;
}

int NameValueModelPrivate::findInsertPosition(const QString &name)
{
auto iter = itemMap.cbegin();
int i = 0;
for (; iter != itemMap.cend(); ++iter, ++i) {
if (iter.key().compare(name, Qt::CaseSensitive) > 0)
return i;
}

return itemMap.size();
}

NameValueModel::NameValueModel(QObject *parent)
: QAbstractTableModel(parent),
d(new NameValueModelPrivate)
{
}

NameValueModel::~NameValueModel()
{
delete d;
}

int NameValueModel::rowCount(const QModelIndex &parent) const
{
if (parent.isValid())
return 0;

return d->itemMap.size();
}

int NameValueModel::columnCount(const QModelIndex &parent) const
{
if (parent.isValid())
return 0;

return 2;
}

QVariant NameValueModel::data(const QModelIndex &index, int role) const
{
if (!index.isValid() || index.row() >= d->itemMap.size())
return QVariant();

auto name = d->itemMap.keys()[index.row()];
switch (role) {
case Qt::DisplayRole:
case Qt::EditRole:
case Qt::ToolTipRole:
if (index.column() == 0)
return name;

if (index.column() == 1)
return d->itemMap.value(name);
break;
}
return QVariant();
}

bool NameValueModel::setData(const QModelIndex &index, const QVariant &value, int role)
{
if (!index.isValid() || role != Qt::EditRole)
return false;

// ignore changes to already set values:
if (data(index, role) == value)
return true;

const QString oldName = data(this->index(index.row(), 0, QModelIndex())).toString();
const QString oldValue = data(this->index(index.row(), 1, QModelIndex()), Qt::EditRole).toString();
if (index.column() == 0) {
//fail if a variable with the same name already exists
const QString &newName = value.toString();
if (newName.isEmpty() || newName.contains('='))
return false;
// Does the new name exist already?
if (d->itemMap.contains(newName) || newName.isEmpty())
return false;

removeItem(index);
QModelIndex newIndex = addItem(newName, oldValue); // add the new variable
emit focusIndex(newIndex); // hint to focus on the name
return true;
} else if (index.column() == 1) {
d->itemMap[oldName] = value;
emit dataChanged(index, index);
return true;
}
return false;
}

Qt::ItemFlags NameValueModel::flags(const QModelIndex &index) const
{
Q_UNUSED(index)
return Qt::ItemIsSelectable | Qt::ItemIsEditable | Qt::ItemIsEnabled;
}

QVariant NameValueModel::headerData(int section, Qt::Orientation orientation, int role) const
{
if (orientation == Qt::Vertical || role != Qt::DisplayRole)
return QVariant();
return section == 0 ? tr("Variable") : tr("Value");
}

void NameValueModel::setItems(const QVariantMap &items)
{
beginResetModel();
d->itemMap = items;
endResetModel();
}

QVariantMap NameValueModel::items() const
{
return d->itemMap;
}

QModelIndex NameValueModel::addItem()
{
return addItem(tr("<VARIABLE>"), tr("<VALUE>"));
}

QModelIndex NameValueModel::addItem(const QString &name, const QVariant &value)
{
int pos = d->indexOf(name);
if (pos >= 0 && pos < d->itemMap.size())
return index(pos, 0, QModelIndex());

int insertPos = d->findInsertPosition(name);
beginInsertRows(QModelIndex(), insertPos, insertPos);
d->itemMap.insert(name, value);
endInsertRows();

return index(insertPos, 0, QModelIndex());
}

void NameValueModel::removeItem(const QModelIndex &index)
{
auto name = data(this->index(index.row(), 0, QModelIndex())).toString();
removeItem(name);
}

void NameValueModel::removeItem(const QString &variable)
{
int pos = d->indexOf(variable);
if (pos < 0)
return;

beginRemoveRows(QModelIndex(), pos, pos);
d->itemMap.remove(variable);
endRemoveRows();
}

void NameValueModel::clear()
{
beginResetModel();
d->itemMap.clear();
endResetModel();
}

QString NameValueModel::variableFromIndex(const QModelIndex &index) const

Check warning on line 186 in src/common/util/namevaluemodel.cpp

View workflow job for this annotation

GitHub Actions / cppcheck

The function 'variableFromIndex' is never used.
{
auto it = std::next(d->itemMap.cbegin(), index.row());
return it.key();
}

QModelIndex NameValueModel::indexFromVariable(const QString &name) const

Check warning on line 192 in src/common/util/namevaluemodel.cpp

View workflow job for this annotation

GitHub Actions / cppcheck

The function 'indexFromVariable' is never used.
{
int pos = d->indexOf(name);
if (pos == -1)
return {};

return index(pos, 0);
}
45 changes: 45 additions & 0 deletions src/common/util/namevaluemodel.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
// SPDX-FileCopyrightText: 2024 UnionTech Software Technology Co., Ltd.
//
// SPDX-License-Identifier: GPL-3.0-or-later

#ifndef NAMEVALUEMODEL_H
#define NAMEVALUEMODEL_H

#include <QAbstractTableModel>

class NameValueModelPrivate;
class NameValueModel : public QAbstractTableModel
{
Q_OBJECT
public:
explicit NameValueModel(QObject *parent = nullptr);
~NameValueModel() override;

int rowCount(const QModelIndex &parent) const override;
int columnCount(const QModelIndex &parent) const override;
QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
bool setData(const QModelIndex &index, const QVariant &value, int role = Qt::EditRole) override;
Qt::ItemFlags flags(const QModelIndex &index) const override;
QVariant headerData(int section,
Qt::Orientation orientation,
int role = Qt::DisplayRole) const override;

void setItems(const QVariantMap &items);
QVariantMap items() const;
QModelIndex addItem();
QModelIndex addItem(const QString &name, const QVariant &value);
void removeItem(const QModelIndex &index);
void removeItem(const QString &variable);
void clear();

QString variableFromIndex(const QModelIndex &index) const;
QModelIndex indexFromVariable(const QString &name) const;

signals:
void focusIndex(const QModelIndex &index);

private:
NameValueModelPrivate *const d;
};

#endif // NAMEVALUEMODEL_H
Loading
Loading