Russian Qt Forum
Май 17, 2024, 07:10 *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

Войти
 
  Начало   Форум  WIKI (Вики)FAQ Помощь Поиск Войти Регистрация  

Страниц: [1]   Вниз
  Печать  
Автор Тема: Автодополнение в QTableView  (Прочитано 4872 раз)
LEO
Гость
« : Июнь 11, 2013, 16:01 »

Добрый день, есть вопрос по ускорению заполнения данных в БД, в общем имею базу SQLITE и отображаю в QTableView, далее при вводе в определенную ячейку хочу получить выпадающий список с уже до этого введенными значениями, впринципе QCompleter справляется с данной задачей, делаю все это дело с помощью делегата, и применяю созданный делегат для соответствующей колонки
.h
Код:
class delegatenynn : public QStyledItemDelegate
{
    Q_OBJECT
public:
    explicit delegatenynn(QObject *parent = 0);
    QWidget *createEditor(QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index) const;
    void setEditorData(QWidget *editor, const QModelIndex &index) const;
    void setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const;
private slots:
   void  resizeLineEditToContents();
   void toUpper(const QString &text);
private:
   mutable QLineEdit *m_plineEdit;
   mutable QRect m_defaultRect;
};

.cpp
Код:
delegatenynn::delegatenynn(QObject *parent) :
    QStyledItemDelegate(parent)
{
}

QWidget *delegatenynn::createEditor(QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &) const
{
    QLineEdit *lineEdit = new QLineEdit(parent);
    QCompleter *productsCompleter=new QCompleter();
    QSqlQueryModel *sqlProductsQuery=new QSqlQueryModel(productsCompleter);
    sqlProductsQuery->setQuery("SELECT DISTINCT ncolumn FROM table order by id desc LIMIT 500");
    productsCompleter->setModel(sqlProductsQuery);
    lineEdit->setCompleter(productsCompleter);
    m_plineEdit = lineEdit;
    m_defaultRect = option.rect;
    m_plineEdit->text().toUpper();
    connect(lineEdit, SIGNAL(textChanged(QString)), this, SLOT(resizeLineEditToContents()));
    connect(lineEdit, SIGNAL(textEdited(const QString &)), SLOT(toUpper(const QString &)));
    lineEdit->setMaxLength(45);
    return lineEdit;
}

void delegatenynn::resizeLineEditToContents()
{
    QString text = m_plineEdit->text();
    if(text != "")
    {
        QFontMetrics fm = m_plineEdit->fontMetrics();
        int w = fm.boundingRect(text).width() + fm.maxWidth();

        if(w >= m_defaultRect.width())
        {
            m_plineEdit->resize(w, m_plineEdit->height());
        }
    }
}

void delegatenynn::toUpper(const QString &text)
{
    QLineEdit *le = qobject_cast<QLineEdit *>(sender());
    if (!le)
    return;
    le->setText(text.toUpper());
}

void delegatenynn:: setEditorData(QWidget *editor, const QModelIndex &index) const
{
    QString value = index.model()->data(index, Qt::EditRole).toString();
    QLineEdit *LineEdit = qobject_cast<QLineEdit *>(editor);
    LineEdit->setText(value);
}

void delegatenynn:: setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const
{
    QLineEdit *LineEdit = qobject_cast<QLineEdit *>(editor);
    QString text = LineEdit->text();
    model->setData(index,text);
    return;
}

делегат для одной колонки выглядит вот так примерно, неужели для каждой колонки надо создавать свой? или есть какие нить более рациональные методы , может кто делал уже подобное?
« Последнее редактирование: Июнь 12, 2013, 08:00 от LEO » Записан
VPS
Гость
« Ответ #1 : Июнь 12, 2013, 01:00 »

Если код делегатов для разных столбцов модели у Вас один и тот же, то, по моему, можно задать делегат для модели, а уже в методе "createEditor" для соответствующих столбцов создавать нужный редактор...
Еще, вместо того, чтобы каждый раз делать запрос к базе на получение элементов столбцов для автодополнения, можно сделать кеш из уникальных значений для каждого столбца...
« Последнее редактирование: Июнь 12, 2013, 01:18 от vps » Записан
LEO
Гость
« Ответ #2 : Июнь 12, 2013, 08:03 »

Код для делегатов каждого столбца по сути одинаков, но различие в методе createEditor есть, а именно суть в том что автодополнение должно производится по данным той колонки в которую вводятся новые данные, по сути различие в несколько строк, вот:

QSqlQueryModel *sqlProductsQuery=new QSqlQueryModel(productsCompleter);
sqlProductsQuery->setQuery("SELECT DISTINCT ncolumn FROM table order by id desc LIMIT 500");
productsCompleter->setModel(sqlProductsQuery);
lineEdit->setCompleter(productsCompleter);

по сути отличие будет в запросе только...
« Последнее редактирование: Июнь 12, 2013, 08:40 от LEO » Записан
VPS
Гость
« Ответ #3 : Июнь 12, 2013, 10:37 »

Ну тогда можно в этом методе номер колонки получать из QModelIndex, и строку с запросом формировать тут же (в зависимости от номера столбца). А дальше сделать выше написанное...
Записан
LEO
Гость
« Ответ #4 : Июнь 19, 2013, 10:47 »

Цитировать
Ну тогда можно в этом методе номер колонки получать из QModelIndex, и строку с запросом формировать тут же (в зависимости от номера столбца). А дальше сделать выше написанное...
Доброе время суток, спасибо за ответы, вариант с кэшем интересен  как я понимаю при запуске программы будут формироваться списки по каждой из колонок и  впринципе и вариант с запросами оч симпатичен, во всяком случае данные варианты смотрятся куда грамотнее чем 10 классов, не совсем понятно с реализацией сего чуда. На данный момент делаю все через делегат наследуясь от QStyledItemDelegate, у меня класс делегат не видит моих моделей и таблиц (tableview) чтобы я мог  взять у него индекс колонки, делегат я уже применяю непосредственно в файле .cpp своего виджета таким образом, 
ui->tableView->setItemDelegateForColumn(2, new delegatenynn());
может я что то не так делаю?
 Непонимающий

Записан
VPS
Гость
« Ответ #5 : Июнь 19, 2013, 13:03 »

На данный момент делаю все через делегат наследуясь от QStyledItemDelegate, у меня класс делегат не видит моих моделей и таблиц (tableview) чтобы я мог  взять у него индекс колонки, делегат я уже применяю непосредственно в файле .cpp своего виджета таким образом, 
ui->tableView->setItemDelegateForColumn(2, new delegatenynn());
может я что то не так делаю?
 Непонимающий

Может ошибка вот здесь (при реализации данного метода не используется индекс модели):
Код:
QWidget *delegatenynn::createEditor(QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &) const
Записан
LEO
Гость
« Ответ #6 : Июнь 19, 2013, 14:55 »

QWidget *delegatenynn::createEditor(QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index) const
впринципе вы правы, вывел индекс с помощью qDebug()<<index.column(); прописывает в выводе номер индекса который пытаюсь редактировать, просто думал что так не сработает и надо делать вот так ui->tableView->currentIndex().column(); ан нет вроде пашет, ок индекс я узнал, буду разбираться. Спасибо vps!
« Последнее редактирование: Июнь 19, 2013, 15:38 от LEO » Записан
Страниц: [1]   Вверх
  Печать  
 
Перейти в:  


Страница сгенерирована за 0.044 секунд. Запросов: 19.