Политика конфиденциальностиКонтактыО сайтеОтзывыGitHubDonate
© EVILEG 2015-2018
Рекомендует хостинг
TIMEWEB
s
19 февраля 2018 г. 20:48

Qtableviev после сортировки

Qt

Сделал проект по уроку + добавил фильтр по "Типу устройств". Проблема заключается в редактировании записей после фильтрации.


На 1 скрине до фильтрации, а на 2 после.


16
s
  • 19 февраля 2018 г. 20:48

2 Скрин

0
s
  • 19 февраля 2018 г. 20:50

А вот что происходит, когда я пытаюсь отредактировать третью запись в отфильтрованной таблице :/

0
s
  • 19 февраля 2018 г. 20:56

EVILEG наведи на путь истинный, что делаю не так подскажи :(

0
s
  • 19 февраля 2018 г. 21:02
void MainWindow::on_SearchButton_clicked()
{
    modelDevice->setFilter(QString( DEVICE_TYPE "= '%1'").arg(ui->SearchLine->text()));
    modelDevice->select();
    
}

Фильтрую вот так, если что
0
Добрый день!
Как я понимаю, вы в качестве id используете номер строки. В вашем случае не получится так сделать.
QTableView поддерживает скрытие колонок. Так вот, вам нужно использовать колонку с ID записи. Эту колонку можно скрыть, чтобы он не мешалась в таблице.
Когда кликаете по QTableView с помощью метода data через индекс (QModelIndex) вам следует забрать ID записи и уже с помощью Id записи открывать диалог на редактирование.
0
s

"QTableView с помощью метода data через индекс (QModelIndex) "



Немного не понял, это как?
0

Ну вы используете слот для открытия диалога редактирования. Выглядеть он будет так.

void MainWindow::slotEditRecord(QModelIndex index)
{
    DialogAddDevice addDeviceDialog(index.row());
    connect(&addDeviceDialog, SIGNAL(signalReady()), this, SLOT(slotUpdateModel()));
 
    addDeviceDialog.setWindowTitle(trUtf8("Редактировать Устройство"));
    addDeviceDialog.exec();
}
Используете там index.row().
то есть открываете через номер строки. А нужно через информацию об ID записи, который обычно должен идти первой колонкой.
Поэтому можно сделать примерно так.
void MainWindow::slotEditRecord(QModelIndex index)
{
    // В качестве номера колонки будет 0, поскольку именно такую колонку чаще всего имеет ID
    DialogAddDevice addDeviceDialog(index.model()->data(index.model()->index(index.row(), 0)));
    connect(&addDeviceDialog, SIGNAL(signalReady()), this, SLOT(slotUpdateModel()));
 
    addDeviceDialog.setWindowTitle(trUtf8("Редактировать Устройство"));
    addDeviceDialog.exec();
}
1
s
До этого слот вот такой юзал

void MainWindow::slotEditRecord()
{
    
    DialogAddDevice *addDeviceDialog = new DialogAddDevice(ui->deviceTableView->selectionModel()->currentIndex().row(););
    connect(addDeviceDialog, SIGNAL(signalReady()),this, SLOT(slotUpdateModels()));
    addDeviceDialog->setWindowTitle(trUtf8("Редактировать Устройство"));
    addDeviceDialog->exec();
}

С вашим слотом выдаёт ошибку :(

0

Две последних строки с ошибками в коде вы не переписали. А в первой я забыл учесть один момент.

void MainWindow::slotEditRecord(QModelIndex index)
{
    // В качестве номера колонки будет 0, поскольку именно такую колонку чаще всего имеет ID
    DialogAddDevice addDeviceDialog(index.model()->data(index.model()->index(index.row(), 0)).toInt());
    connect(&addDeviceDialog, SIGNAL(signalReady()), this, SLOT(slotUpdateModel()));
 
    addDeviceDialog.setWindowTitle(trUtf8("Редактировать Устройство"));
    addDeviceDialog.exec();
}
1

А теперь ещё раз и внимательно смотрим моё последнее сообщение

1
s

Всё, поменял таки заработало. Но почему то оно выбирает строку с индексом больше на 1. В итоге вот что юзаю и оно корректно работает :)

 DialogAddDevice addDeviceDialog((index.model()->data(index.model()->index(index.row(), 0)).toInt())-1);
EVILEG Спасибо вам больше что помогли разобраться :)

0

Потому, что в mainwindow вы работаете уже с индексами, когда создаёте диалог для редактирования, а диалоге в всё ещё работаете со строками.

Вам нужно переписать диалог, чтобы также данные забирались через индекс, а не через строку. Поскольку когда будете удалять некоторые строки, то правка на -1 уже Вам не поможет. Там будет расхождение id со строкой гораздо больше.
1
s

Evileg, не совсем понимаю что тут нужно переписать, чтобы данные забирались через индекс, а не строку. :(


#include "dialogadddevice.h"
#include "ui_dialogadddevice.h"
#include <QDebug>

DialogAddDevice::DialogAddDevice(int row, QWidget *parent) :
    QDialog(parent),
    ui(new Ui::DialogAddDevice)
{
    ui->setupUi(this);

   
    setupModel();

    
    if(row == -1){
        model->insertRow(model->rowCount(QModelIndex()));
        mapper->toLast();
    /* В противном случае диалог настраивается на заданную запись
     * */
    } else {
        mapper->setCurrentModelIndex(model->index(row,0));
    }

    createUI();
}

DialogAddDevice::~DialogAddDevice()
{
    delete ui;
}

/* Метод настройки модели данных и mapper
 * */
void DialogAddDevice::setupModel()
{
    /* Инициализируем модель и делаем выборку из неё
     * */
    model = new QSqlTableModel(this);
    model->setTable(DEVICE);
    model->setEditStrategy(QSqlTableModel::OnManualSubmit);
    model->select();

    /* Инициализируем mapper и привязываем
     * поля данных к объектам LineEdit
     * */
    mapper = new QDataWidgetMapper();
    mapper->setModel(model);
    mapper->addMapping(ui->Device_Name, 1);
    mapper->addMapping(ui->Device_Type, 2);
    mapper->addMapping(ui->Dev_invent_number, 3);
    mapper->addMapping(ui->Dev_location, 4);
    mapper->addMapping(ui->Dev_status, 5);

  
    mapper->setSubmitPolicy(QDataWidgetMapper::ManualSubmit);

    qDebug() << ui->Device_Name->text();
    
    connect(ui->previousButton, SIGNAL(clicked()), mapper, SLOT(toPrevious()));
    connect(ui->nextButton, SIGNAL(clicked()), mapper, SLOT(toNext()));
    /* При изменении индекса в mapper изменяем состояние кнопок
     * */
    connect(mapper, SIGNAL(currentIndexChanged(int)), this, SLOT(updateButtons(int)));
}

void DialogAddDevice::createUI()
{

    QRegExp Name_Range("[a-zA-Z0-9]{20}");
    ui->Device_Name->setValidator(new QRegExpValidator (Name_Range,this));


    /*
    QString macRange = "(?:[0-9A-Fa-f][0-9A-Fa-f])";
    QRegExp macRegex ("^" + macRange
                      + "\\:" + macRange
                      + "\\:" + macRange
                      + "\\:" + macRange
                      + "\\:" + macRange
                      + "\\:" + macRange + "$");
    QRegExpValidator *macValidator = new QRegExpValidator(macRegex, this);
    ui->Device_Type->setValidator(macValidator);
    */
}

void DialogAddDevice::on_buttonBox_accepted()
{
    
    QSqlQuery query;
    QString str = QString("SELECT EXISTS (SELECT " DEVICE_NAME " FROM " DEVICE
                          /*" WHERE ( " DEVICE_NAME " = '%1' "*/" WHERE " DEVICE_INVENTORY_NUMBER " = '%1' "
                          " AND id NOT LIKE '%2' )")
            .arg(/*ui->Device_Name->text(),*/
                 ui->Dev_invent_number->text(),
                 model->data(model->index(mapper->currentIndex(),0), Qt::DisplayRole).toString());

    query.prepare(str);
    query.exec();
    query.next();

   
    if(query.value(0) != 0){
        QMessageBox::information(this, trUtf8("Ошибка добавления"),
                                 trUtf8("В базе уже присутствует устройство с таким серийным номером"));
    
    } else {
        mapper->submit();
        model->submitAll();
        emit signalReady();
        this->close();
    }
}

void DialogAddDevice::accept()
{
qDebug() << ui->Device_Name->text();
}


void DialogAddDevice::updateButtons(int row)
{
   
    ui->previousButton->setEnabled(row > 0);
    ui->nextButton->setEnabled(row < model->rowCount() - 1);
}
Кстати на удивление, удаление записей работает абсолютно нормально, без каких либо проблем вот с таким кодом:
void MainWindow::slotRemoveRecord()
{

    // Получение id_ строки
    int row = ui->deviceTableView->selectionModel()->currentIndex().row();
    
    if(row >= 0)
    {
        if (QMessageBox::warning(this, trUtf8("Удаление записи"),
                                       trUtf8("Вы уверены, что хотите удалить эту запись?"),
                                       QMessageBox::Yes | QMessageBox::No) == QMessageBox::No)
        {
            //Откат базы :)
            QSqlDatabase::database().rollback();
            return;

        }
        else 
        {
            if(!modelDevice->removeRow(row))
            {
                QMessageBox::warning(this, trUtf8("Проблема"),trUtf8("Не удалось удалить запись\nВозможно мешает какая то зависимость"));
            }
            modelDevice->select();
            ui->deviceTableView->setCurrentIndex(modelDevice->index(-1, -1));
        }
    }
}

Можешь навести пожалуйста, что мне нужно переписать в диалоге добавления :x
0

Вот так можно написать

DialogAddDevice::DialogAddDevice(int id, QWidget *parent) :
    QDialog(parent),
    ui(new Ui::DialogAddDevice)
{
    ui->setupUi(this);
   
    setupModel();
    
    if(row == -1){
        model->insertRow(model->rowCount(QModelIndex()));
        mapper->toLast();
    /* В противном случае диалог настраивается на заданную запись
     * */
    } else {
        for (int row = 0; row < model->rowCount(); ++row)
        {
            if (model->data(model->index(row, 0)).toInt() == id)
            {
                mapper->setCurrentModelIndex(model->index(row, 0));
            }
        }
    }

    createUI();
}
Внимательно только посмотрите изменение кода, там я немного поменял аргументы конструктора.
Вообще, как вариант можно передавать ещё и QModelIndex вместо Id, тогда будет ещё более гарантированный результат без ошибок, но в этом случае нужно будет иметь указатель на ту модель, которая находится в главном диалоге, а это уже более сложный для понимания вариант реализации.

Но в данном случа оба варианта будут рабочими.
1
s

Спасибо, всё заработало :)


Единственное вот тут row на id поменял и всё круто :))
if(id == -1){
        model->insertRow(model->rowCount(QModelIndex()));
        mapper->toLast();
0

Ответы

Только авторизованные пользователи могут отвечать на форуме.
Пожалуйста, авторизуйтесь или зарегистрируйтесь
m
19 декабря 2018 г. 10:37
maintumanov

Qt - Тест 001. Сигналы и слоты

  • Результат:68баллов,
  • Очки рейтинга-1
ИН
18 декабря 2018 г. 17:37
Игорь Носач

C++ - Тест 003. Условия и циклы

  • Результат:64баллов,
  • Очки рейтинга-1
ИН
18 декабря 2018 г. 17:22
Игорь Носач

C++ - Тест 003. Условия и циклы

  • Результат:35баллов,
  • Очки рейтинга-10
Последние комментарии
V
15 декабря 2018 г. 2:06
Vlad15007

Спасибо большое!Очень помогли!
11 декабря 2018 г. 21:01
Евгений Легоцкой

Не знаю, какой-там конкретно эффект и если честно не хочется fl studio ради того, чтобы посмотреть устанавливать, но из того, что увидел в интернете. Предполагаю, что то, что вы хотите с...
V
11 декабря 2018 г. 19:25
Vlad15007

Подскажите пожалуйста ( я новичок совсем)Можно ли организовать спрайт без этого окошка (как в fl studio fruity dance)?
11 декабря 2018 г. 15:06
Евгений Легоцкой

Что интересно, если написать так from <application_name>.<module_name> import <filename> ,то PyCharm сносит крышу, если разрабатываешь в рамках проекта приложение, ко...
11 декабря 2018 г. 14:52
Илья Чичак

Тут мне тоже есть что сказать=) Сами разрабы советуют импортировать следующим образом: from <application_name> import <module_name> Стоит избегать from . import &l...;
Сейчас обсуждают на форуме
М
19 декабря 2018 г. 8:43
Михаиллл

Здравствуйте.Говорят, если подключить ICU, то в SQLite появится регистронезависемый поиск.Я нашел скомпилированный ICU по этой ссылке https://www.npcglib.org/~stathis/blog/precompiled-...
18 декабря 2018 г. 19:58
Евгений Легоцкой

ну если у вас также будет внешний ключ на Serial, то получается следующая ситуация, Movie добавлен в Serial, а Serial имеет список Movie. То есть вам playlist как таковой вовсе не нужен....
R
18 декабря 2018 г. 12:25
RED_Spider

именно так, проблема в кодировке, а именно в отсутствии шрифтов на сервере, для меня вопрос решился в CentOS 7yum install curl cabextract xorg-x11-font-utils fontconfig всем спасибо за ...
U
18 декабря 2018 г. 10:39
Unreal_man

А вот этот коннект здесь и вовсе не нужен connect(ui->ok3, &QPushButton::clicked, this, &Widget::addToText); А как же без него? ============================== ...
m
17 декабря 2018 г. 19:03
melnik10

Спасибо, попробую!
Присоединяйтесь к нам в социальных сетях

Для зарегистрированных пользователей на сайте присутствует минимальное количество рекламы