Доброе утро.Наконец-то я создал программу treeconfig для чтения txt, затем отредактировал ее в интерфейсе и сохранил, но у меня возникла проблема.
Я знаю, что есть пример модели дерева, который можно редактировать (http://doc.qt.io/qt-5/qtwidgets-itemviews-editabletreemodel-example.html),, но этот не использует libconfig.h ++
Я решил использовать libconfig.h ++ в моем Linux, потому что я могу фильтровать, какая информация отображается в значениях (int / string / ...), потому что в другом примере без libconfig он использует qVariant и принимает все типы входных данных.
Так что даже по сравнению с другим примером я не могу заставить работать следующее: Моя проблема в том, чтокогда я пытаюсь отредактировать одно значение, информация внутри исчезает, и если я щелкаю за пределами значения, оно становится равным 0. Как можно избежать обеих этих вещей? Я хочу, например, редактировать строку в середине или просто не удалятьзатем информация при неправильном нажатии или что-то в этом роде.
На изображениях ниже показана попытка редактирования значения для confTimeout. Обратите внимание, что текст внутри исчезаетпри нажатии в режиме редактирования и текст устанавливается в 0, если щелкнуть не в фокусе.
mainwindow.cpp
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QTextStream>
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
}
void MainWindow::setConfig(libconfig::Config *config)
{
tm = std::make_unique<TreeModel>(config, this);
ui->treeView->setModel(tm.get());
}
MainWindow::~MainWindow()
{
delete ui;
}
/*
void MainWindow::on_treeView_activated(const QModelIndex &index)
{
QString val = ui->treeView->model()->data(index).toString();
ui->lineEdit->setText(val);
}
*/
void MainWindow::on_pushButton_clicked()
{
tm->saveSettings();
}
treeitem.cpp
#include "treeitem.h"
#include <libconfig.h++>
static QVariant getIndexOrName(const libconfig::Setting &setting)
{
if (!setting.isRoot()) {
const auto &parent = setting.getParent();
if (parent.isArray() || parent.isList())
return setting.getIndex();
}
return setting.getName();
}
static QVariant getValueOrSize(const libconfig::Setting &setting)
{
using namespace libconfig;
switch (setting.getType()) {
// scalar types
case Setting::TypeInt:
return setting.operator int();
case Setting::TypeInt64:
return setting.operator long long();
case Setting::TypeFloat:
return setting.operator double();
case Setting::TypeString:
return setting.c_str();
case Setting::TypeBoolean:
return setting.operator bool();
// aggregate types
case Setting::TypeGroup:
return QString{"Group. Size: %1"}.arg(setting.getLength());
case Setting::TypeArray:
return QString{"Array. Size: %1"}.arg(setting.getLength());
case Setting::TypeList:
return QString{"List. Size: %1"}.arg(setting.getLength());
// not used
case Setting::TypeNone:
break;
}
return QVariant{};
}
static bool setValue(libconfig::Setting &setting, const QVariant &value)
{
using namespace libconfig;
switch (setting.getType()) {
// scalar types
case Setting::TypeInt:
if (value.canConvert(QVariant::Int)) {
setting = value.toInt();
return true;
}
case Setting::TypeInt64:
if (value.canConvert(QVariant::LongLong)) {
setting = value.toLongLong();
return true;
}
case Setting::TypeFloat:
if (value.canConvert(QVariant::Double)) {
setting = value.toFloat();
return true;
}
case Setting::TypeString:
if (value.canConvert(QVariant::String)) {
setting = value.toString().toStdString();
return true;
}
case Setting::TypeBoolean:
if (value.canConvert(QVariant::Bool)) {
setting = value.toBool();
return true;
}
default:
break;
}
return false;
}
TreeItem::TreeItem(libconfig::Setting *setting, TreeItem *parentItem)
: m_setting{setting}, m_parentItem{parentItem}
{
if (setting->isAggregate()) {
for (auto &setting : *setting) {
m_subSettings.push_back(new TreeItem(&setting, this));
}
}
}
TreeItem::~TreeItem() { qDeleteAll(m_subSettings); }
TreeItem *TreeItem::child(int row) { return m_subSettings.at(row); }
int TreeItem::childCount() const { return m_subSettings.size(); }
int TreeItem::columnCount() const { return 2; }
QVariant TreeItem::data(int column) const
{
switch (column) {
case 0:
return getIndexOrName(*m_setting);
case 1:
return getValueOrSize(*m_setting);
default:
return QVariant{};
}
}
bool TreeItem::setData(const QVariant &value)
{
if (m_setting->isAggregate())
return false;
return setValue(*m_setting, value);
}
int TreeItem::row() const
{
if (!m_parentItem)
return 0;
return m_parentItem->m_subSettings.indexOf(const_cast<TreeItem *>(this));
}
TreeItem *TreeItem::parentItem() { return m_parentItem; }
treemodel
#include "treemodel.h"
#include "treeitem.h"
#include <QFile>
#include <libconfig.h++>
#include <QDateTime>
TreeModel::TreeModel(libconfig::Config *config, QObject *parent)
: QAbstractItemModel{parent}, m_rootSetting{std::make_unique<TreeItem>(
&(config->getRoot()), nullptr)}, m_config{config}
{
}
TreeModel::~TreeModel()
{
}
QVariant TreeModel::data(const QModelIndex &index, int role) const
{
if (!index.isValid())
return QVariant();
if (role != Qt::DisplayRole)
return QVariant();
TreeItem *item = static_cast<TreeItem*>(index.internalPointer());
return item->data(index.column());
}
bool TreeModel::setData(const QModelIndex &index, const QVariant &value, int role)
{
if (!index.isValid())
return false;
if (role != Qt::EditRole)
return false;
TreeItem *item = static_cast<TreeItem*>(index.internalPointer());
return item->setData(value);
}
Qt::ItemFlags TreeModel::flags(const QModelIndex &index) const
{
if (!index.isValid())
//return Qt::NoItemFlags;
return 0;
//return QAbstractItemModel::flags(index);
return Qt::ItemIsEditable | QAbstractItemModel::flags(index);
}
QVariant TreeModel::headerData(int section, Qt::Orientation orientation,
int role) const
{
if (orientation != Qt::Horizontal || role != Qt::DisplayRole)
return QVariant{};
switch (section) {
case 0:
return "Name";
case 1:
return "Value";
default:
return QVariant{};
}
}
QModelIndex TreeModel::index(int row, int column,
const QModelIndex &parent) const
{
if (!hasIndex(row, column, parent))
return QModelIndex();
TreeItem *parentItem;
if (!parent.isValid())
parentItem = m_rootSetting.get();
else
parentItem = static_cast<TreeItem*>(parent.internalPointer());
TreeItem *childItem = parentItem->child(row);
if (childItem)
return createIndex(row, column, childItem);
else
return QModelIndex();
}
QModelIndex TreeModel::parent(const QModelIndex &index) const
{
if (!index.isValid())
return QModelIndex();
TreeItem *childItem = static_cast<TreeItem *>(index.internalPointer());
TreeItem *parentItem = childItem->parentItem();
if (parentItem == m_rootSetting.get())
return QModelIndex();
return createIndex(parentItem->row(), 0, parentItem);
}
int TreeModel::rowCount(const QModelIndex &parent) const
{
TreeItem *parentItem;
if (parent.column() > 0)
return 0;
if (!parent.isValid())
parentItem = m_rootSetting.get();
else
parentItem = static_cast<TreeItem*>(parent.internalPointer());
return parentItem->childCount();
}
int TreeModel::columnCount(const QModelIndex &parent) const
{
if (parent.isValid())
return static_cast<TreeItem*>(parent.internalPointer())->columnCount();
else
return m_rootSetting->columnCount();
}
bool TreeModel::saveSettings(QString filename) const
{
if (filename.isEmpty())
filename = QString::fromLocal8Bit(m_config->getRoot().getSourceFile());
QString today = QDateTime::currentDateTime().toString("_yyyy.MM.dd_hh:mm");
QFile::copy(filename, filename+today+".backup");
try {
m_config->writeFile(filename.toLocal8Bit().constData());
} catch (...) {
return false;
}
return true;
}
o
o
o
o
РЕДАКТИРОВАНИЕ :::
Прежде всего, спасибо @vahancho и @trebuchetMS.Я попытался с примером Vahancho, но он бросает проблему
Также я пытался с другими комбинациями, но он идея не разрешать, например,"string", где должно быть помещено "int".
Я также еще раз проверил editableTreeModel из QtExamples, но он разрешает строку, в которой должен быть помещен int, и я не хочу этого
QVariant TreeModel::data(const QModelIndex &index, int role) const
{
if (!index.isValid())
return QVariant();
if (role != Qt::DisplayRole && role != Qt::EditRole)
return QVariant();
TreeItem *item = getItem(index);
return item->data(index.column());
}
Есть идеи?