0

I am trying to use a QAction to turn a specific column of a QTableView into from the current format xxx:xxx into another format (xxx,xxx) and reverse.

I prepared a small minimal application that carries exactly the problem I have. The application is formed by:

1) A Main window that carries a QTableView with:

Id | name | age | salary | coordinate

Also the printscreen of the GUI is showed here for completeness:

GUI

Additionally the print screen of what I am trying t achieve is also shown below, notice that as soon as I click on the "coordinate" column it lights up and with right click I try to change the format from xxx:xxx to (xxx,xxx) but is not working:

GUI

I am trying to change the last column "coordinate" from format xxx:xxx into format (xxx,xxx) and reverse. As you click on any cell of the last column the entire column "coordinate" will be selectable.

What I tried so far:

I tried to change the format by following this source, which was useful but didn't totally address the problem.

Additionally I have implemented part of this solution that was trying to force decimal numbers into cells. However in my case I don't have a QStyledItemDelegate but just a QAction.

Also this was the closest help I could find. This example proposes a QStyledItemDelegate too but it is not what I am trying to achieve.

Also I wrote a QPoint Widget::parseCoordStringForTheTable(QString input) that accepts particular formats but I am not sure how to handle this exception.

This is a complete MCVE so it needs to solely be copied and paste and it should work right away:

main.cpp

#include "widget.h"
#include <QApplication>
int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    Widget w;
    w.show();
    return a.exec();
}

widget.h

#ifndef WIDGET_H
#define WIDGET_H
#include <QWidget>
#include <QtSql/QSqlDatabase>
#include <QtSql/QSqlQueryModel>

namespace Ui {
class Widget;
}
class QSqlQueryModel;
class Widget : public QWidget
{
    Q_OBJECT
public:
    explicit Widget(QWidget *parent = nullptr);
    ~Widget();
private slots:
    void on_add_clicked();
    void on_close_clicked();
    void on_modify_clicked();
    void currentColumnChanged(const QModelIndex &mi);
    void autoSelectMagicColumn();
private:
    Ui::Widget *ui;
    QSqlDatabase mDatabase;
    QSqlQueryModel *mModel;
    QAction *mTurnIntoExcelData;
    QPoint parseCoordStringForTheTable(QString input);
    const int magicColumnIndex = 4;
};

#endif // WIDGET_H

widget.cpp

#include "widget.h"
#include "ui_widget.h"
#include <QtSql/QSqlQueryModel>
#include <QSqlError>
#include <QSqlQuery>
#include <QMessageBox>
#include <QInputDialog>
#include <QTimer>
#include <QAction>

Widget::Widget(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::Widget)
{
    ui->setupUi(this);
    mTurnIntoExcelData = new QAction(QIcon(":"), tr("Turn into Excel format"), this);
    ui->tableView->setContextMenuPolicy(Qt::ActionsContextMenu);
    ui->tableView->addActions({mTurnIntoExcelData});
    connect(mTurnIntoExcelData, &QAction::triggered, [&]() {
        int row = -1, column = -1;
        QString reference;
        QString type;
        QModelIndex index;
        QPoint data;
        for(int i = 0; i < ui->tableView->model()->columnCount(); i++)
        {
          if(ui->tableView->model()->headerData(i, Qt::Horizontal).toString() == "coordinate") {
              column = i;
              type = "coordinate";
          data.setX(parseCoordStringForTheTable(index.sibling(row,4).data().toString()).x());
          data.setY(parseCoordStringForTheTable(index.sibling(row,4).data().toString()).y());
              //mModel->submitAll();
              ui->tableView->show();
          }
        }
        QModelIndexList selection = ui->tableView->selectionModel()->selectedColumns();
        if (selection.count() > 0) {
            QModelIndex index = selection.at(0);
            row = index.row();
        }
        if(row < 0 || column < 0)
        {
            QMessageBox::warning(this, "Warning", "DoubleCheck - Didnt work");
        }
        else {
            reference = ui->tableView->model()->data(ui->tableView->model()->index(row,column)).toString();
            if(reference == "No Coordinates Present")
                return;
        }
    });
    mDatabase = QSqlDatabase::addDatabase("QSQLITE");
mDatabase.setDatabaseName("/path/to/Desktop/tmp/StackOverflow.db");
    if(!mDatabase.open()) {
        QMessageBox::critical(this, "Error", mDatabase.lastError().text());
        return;
    }
    QSqlQuery qry;
    if (!qry.exec("CREATE TABLE IF NOT EXISTS persona " \
        "(id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL," \
        "name TEXT NOT NULL," \
        "age INTEGER NOT NULL," \
        "salary DOUBLE NOT NULL, "
        "coordinate TEXT NOT NULL)")) {
        QMessageBox::critical(this, "Error", qry.lastError().text());
        return;
    }
    mModel = new QSqlQueryModel(this);
    mModel->setQuery("SELECT * FROM persona");
    ui->tableView->setModel(mModel);
    connect(ui->tableView->selectionModel(), SIGNAL(currentColumnChanged(const QModelIndex &, const QModelIndex &)),
        this, SLOT(currentColumnChanged(const QModelIndex &)));
}

Widget::~Widget()
{delete ui;}
void Widget::on_add_clicked()
{
    QSqlQuery qry;
    if (!qry.exec(QString("INSERT INTO persona (name,age,salary,coordinate)"\
                      "VALUES ('%1',%2,%3,%4)").
         arg(ui->name->text()).
         arg(ui->age->value()).
         arg(ui->salary->value()).
         arg(ui->coordinate->text()))) {
        QMessageBox::critical(this, "Error", qry.lastError().text());
        return;
    }
    mModel->setQuery("SELECT * FROM persona");
    ui->tableView->setModel(mModel);
}

void Widget::on_close_clicked()
{close();}

void Widget::on_modify_clicked()
{
    auto uploadInt = [&](QWidget *parent, const QString &title, const QString &msg, int valor) {
        bool ok;
        int res = QInputDialog::getInt(parent, title, msg, valor,
                                   -2147483647, 2147483647, 1, &ok);
        if(ok) { return res; }
        return valor;
};
auto uploadName = [&](QWidget *parent, const QString &name) {
    bool ok;
    auto res = QInputDialog::getText(parent, "Name", "Name Input",
                                     QLineEdit::Normal, name, &ok);
    if(ok) { return res; }
    return name;
};
auto uploadSalary = [&](QWidget *parent, double salary) {
    bool ok;
    double res = QInputDialog::getDouble(parent, "Salary", "Salary Input", salary,
                                         -2147483647, 2147483647, 3, &ok);
    if(ok) { return res; }
    return salary;
};
auto uploadCoord = [&](QWidget *parent, int coord) {
    bool ok;
    int res = QInputDialog::getInt(parent, "Coordinate", "Input Coordinate", coord,
                                   -2147483647, 2147483647, 1, &ok);
    if(ok) { return res; }
    return coord;
    };
    int col = ui->tableView->currentIndex().column();
    int row = ui->tableView->currentIndex().row();
    QString sql;
    if(col == 0) {
        int id = mModel->index(row, col).data().toInt();
        sql = QString("UPDATE persona SET id = %1 WHERE id = %2").
        arg(uploadInt(this, "Id", "Id Input", id)).arg(id);
    } else if (col == 1) {
        auto name = mModel->index(row, col).data().toString();
        sql = QString("UPDATE persona SET name = '%1' WHERE name LIKE '%2'").
    arg(uploadName(this, name)).arg(name);
    } else if (col == 2) {
        int age = mModel->index(row, col).data().toInt();
        sql = QString("UPDATE persona SET age = %1 WHERE age = %2").
    arg(uploadInt(this, "Age", "Age Input", age)).arg(age);
    } else if (col == 3) {
        double salary = mModel->index(row, col).data().toDouble();
        sql = QString("UPDATE persona SET salary = %1 WHERE salary = %2").
    arg(uploadSalary(this, salary)).arg(salary);
    } else if (col == 4) {
        int coordinate = mModel->index(row, col).data().toInt();
        sql = QString("UPDATE persona SET coordinate = %1 WHERE salary = %2").
    arg(uploadCoord(this, coordinate)).arg(coordinate);
    }
    QSqlQuery qry;
    qry.exec(sql);
    mModel->setQuery("SELECT * FROM persona");
}

void Widget::currentColumnChanged(const QModelIndex &mi) {
        const int col = mi.column();
        if (col == magicColumnIndex) {
        QTimer::singleShot(100, this, SLOT(autoSelectMagicColumn()));
    }
}

void Widget::autoSelectMagicColumn()
{
    if (ui->tableView->selectionModel()->currentIndex().column() == magicColumnIndex) {
        ui->tableView->selectColumn(magicColumnIndex);
    }
}

QPoint Widget::parseCoordStringForTheTable(QString input)
{
    QPoint output;
    if(input.contains('(')) {
    output.setX(input.remove('(').remove(')').remove(',').split(" ")[0].toInt());

    output.setY(input.remove('(').remove(')').remove(',').split(" ")[1].toInt());
    } else {
        output.setX(input.split(":")[0].toInt());
        output.setY(input.split(":")[1].toInt());
    }
    return output;
}

Expected Result: change format of one specific column passing from current format xxx:xxx into format (xxx,xxx) and reverse as soon as I clic k on the "coordinate" column

Actual: Not working because nothing happens.

So to recap quickly: the image shown below is what I am trying to achieve, the last column will become entirely selectable as soon as the user clicks in any cell of that specific column, and with the right click I am attempting to change the entire format of the column from xxx:xxx, to (xxx,xxx):

GUI

Any possible insights will be useful, thanks.

  • Hello eyllanesc and thanks for your comment. I expect to change the entire column ACoord (so it would be column n.3) –  Feb 12 '19 at 02:50
  • Yes, this is part of a small minimal, and complete verifiable example I prepared to replicate the problem I have. Do you want me to post the entire small application? –  Feb 12 '19 at 03:08
  • No problem! I will post the complete MCVE! Thanks in advance! –  Feb 12 '19 at 03:30
  • Hello eyllanesc I just updated the complete MCVE. Copy and paste the entire code and it should compile without issue. –  Feb 14 '19 at 04:07
  • you could share your StackOverflow.db file, also change the format you just want to visual or want to be saved in the database. – eyllanesc Feb 14 '19 at 04:27
  • When you say to share the .db file do you mean that you would want me to share the small MCVE? Like on GitHub? I added a couple of other print screen that explain the problem I have, which is the .db file. To change the format I wrote a function called `QPoint Widget::parseCoordStringForTheTable(QString input)` but I don't understand to link it correctly to the QAction. –  Feb 14 '19 at 11:27
  • And of course SQL is not responding correctly, because I think it does not understand the format? –  Feb 14 '19 at 11:31

0 Answers0