Reputation: 587
I have a custom class ConnectionStandardItem which is a subclass of QStandardItem. This item should contain information like server, username, password etc to be used later in QSqlDatabase.
ConnectionStandardItem::ConnectionStandardItem(QString const& connectionId) : QStandardItem()
{
QMap<QString, QVariant> m_connectionDefinition;
QSettings settings(QSettings::IniFormat, QSettings::UserScope, "goat", "connections");
if (!connectionId.isEmpty())
{
settings.beginGroup(connectionId.trimmed());
m_connectionDefinition[connectionId] = QVariant(connectionId.trimmed());
foreach(QString key, settings.childKeys())
{
m_connectionDefinition[key] = settings.value(key);
}
setText(m_connectionDefinition["name"].toString());
setData(m_connectionDefinition, Qt::UserRole);
settings.endGroup();
}
}
Extended QStandardItem is used in a dialog:
NewConnectionDialog::NewConnectionDialog(QWidget *parent) : QDialog(parent), ui(new Ui::NewConnectionDialog) {
ui->setupUi(this);
m_model = new QStandardItemModel(this);
m_driversModel = new QStandardItemModel(this);
m_connectionListModel = new QStandardItemModel(this);
ui->listDropdownDBDriver->setModel(m_driversModel);
ui->listViewConnections->setModel(m_connectionListModel);
/* set combobox */
QStandardItem* item_psql = new QStandardItem();
item_psql->setText("PostgreSQL");
item_psql->setData("QPSQL", Qt::UserRole);
m_driversModel->appendRow(item_psql);
QStandardItem* item_mysql = new QStandardItem();
item_mysql->setText("MySQL/MariaDB");
item_mysql->setData("QMYSQL", Qt::UserRole);
m_driversModel->appendRow(item_mysql);
updateConnectionListModel();
connect(ui->listViewConnections->selectionModel(), SIGNAL(selectionChanged(QItemSelection, QItemSelection)), this, SLOT(handleSelectionChanged(QItemSelection, QItemSelection)));
connect(m_connectionListModel, SIGNAL(itemChanged(QStandardItem*)), this, SLOT(updateListViewItem(QStandardItem*)));
}
void NewConnectionDialog::handleSelectionChanged(QItemSelection current, QItemSelection previous) {
const QModelIndex index = ui->listViewConnections->currentIndex();
ConnectionStandardItem* connection = m_connectionListModel->itemFromIndex(index)->data().value<ConnectionStandardItem*>();
QMap<QString, QVariant> connectionDefinition = connection->data().value<QMap<QString, QVariant>>();
//ui->listDropdownDBDriver->setCurrentIndex(index);
ui->txtUser->setText(connectionDefinition["username"].toString());
ui->txtPass->setText(connectionDefinition["pass"].toString());
ui->txtServer->setText(connectionDefinition["server"].toString());
ui->txtPort->setText(connectionDefinition["port"].toString());
ui->txtDatabase->setText(connectionDefinition["database"].toString());
}
void NewConnectionDialog::updateConnectionListModel() {
QSettings settings(QSettings::IniFormat, QSettings::UserScope, "goat", "connections");
foreach(QString key, settings.childGroups())
{
ConnectionStandardItem* item = new ConnectionStandardItem(key);
m_connectionListModel->appendRow(item);
}
}
Unfortunately, within dialog, i cannot access currently selected item's data. Method where i'm checking is handleSelectionChanged.
How can i properly extract Map object from the ConnenctionStandardItem so i can update GUI and vice versa, send changes in the gui back to the model (and through the model to the .ini settings file)? Is there a better way to approach this (differently organized classes)?
Upvotes: 2
Views: 618
Reputation: 243897
ConnectionStandardItem is not a data saved in the QStandardItem, but you have to cast ConnectionStandardItem from the QStandardItem.
On the other hand you save the data in the Qt::UserRole
role:
setData(m_connectionDefinition, Qt::UserRole);
But when using data()
you are using the Qt::UserRole + 1
role according to the documentation:
QVariant QStandardItem::data(int role = Qt::UserRole + 1) const
The solution is the next:
void NewConnectionDialog::handleSelectionChanged(QItemSelection current, QItemSelection previous) {
const QModelIndex index = ui->listViewConnections->currentIndex();
QStandardItem *item = m_connectionListModel->itemFromIndex(index);
ConnectionStandardItem* connection = static_cast<ConnectionStandardItem*>(item); // <---
QMap<QString, QVariant> connectionDefinition = connection->data(Qt::UserRole).value<QMap<QString, QVariant>>(); // <---
//ui->listDropdownDBDriver->setCurrentIndex(index);
ui->txtUser->setText(connectionDefinition["username"].toString());
ui->txtPass->setText(connectionDefinition["pass"].toString());
ui->txtServer->setText(connectionDefinition["server"].toString());
ui->txtPort->setText(connectionDefinition["port"].toString());
ui->txtDatabase->setText(connectionDefinition["database"].toString());
}
Although I see that casting is not necessary either, since we are not going to use a method implemented in ConnectionStandardItem
, so we could only use QStandardItem
:
void NewConnectionDialog::handleSelectionChanged(QItemSelection current, QItemSelection previous) {
const QModelIndex index = ui->listViewConnections->currentIndex();
QStandardItem *connection = m_connectionListModel->itemFromIndex(index);
QMap<QString, QVariant> connectionDefinition = connection->data(Qt::UserRole).value<QMap<QString, QVariant>>(); // <---
//ui->listDropdownDBDriver->setCurrentIndex(index);
ui->txtUser->setText(connectionDefinition["username"].toString());
ui->txtPass->setText(connectionDefinition["pass"].toString());
ui->txtServer->setText(connectionDefinition["server"].toString());
ui->txtPort->setText(connectionDefinition["port"].toString());
ui->txtDatabase->setText(connectionDefinition["database"].toString());
}
Upvotes: 2