crossplatform.ru

Здравствуйте, гость ( Вход | Регистрация )

2 страниц V  < 1 2  
Ответить в данную темуНачать новую тему
> Делегат для конкретной ячейки в QTableView
JuryS1806
  опции профиля:
сообщение 22.1.2011, 1:21
Сообщение #11


Студент
*

Группа: Участник
Сообщений: 93
Регистрация: 21.10.2009
Из: Нижний Новгород
Пользователь №: 1168

Спасибо сказали: 9 раз(а)




Репутация:   0  


вот и простейший делегат от тролей: QSqlRelationalDelegate
можно назначить делегат не для каждой строки, а для все таблицы.
Только вот когда вызывается CreateEditor?
Каждый раз при вхождении в ячейку?
Соответственно делегат нужно запихнуть в приватную секцию и добавить на него несколько Update'ов...

Вообщем, все делегаты нужно объединить в один и ПОЛОВИНУ ПРОГРАММЫ переписывать заново !
Пойду застрелюсь БЛИН!
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
igor_bogomolov
  опции профиля:
сообщение 22.1.2011, 1:33
Сообщение #12


Профессионал
*****

Группа: Сомодератор
Сообщений: 1215
Регистрация: 22.3.2009
Из: Саратов
Пользователь №: 630

Спасибо сказали: 235 раз(а)




Репутация:   29  


Цитата(JuryS1806 @ 22.1.2011, 1:21) *
Вообщем, все делегаты нужно объединить в один и ПОЛОВИНУ ПРОГРАММЫ переписывать заново !
Пойду застрелюсь БЛИН!
Не нужно так сгущать краски. Нет там ничего сложного, тем более что отдельные делегаты уже есть. В остальном коде изменений будет самый минимум.
Цитата(JuryS1806 @ 22.1.2011, 1:21) *
Только вот когда вызывается CreateEditor?
Это устанавливает void QAbstractItemView:setEditTriggers ( EditTriggers triggers ). Если писали другие делегаты, то должны бы это знать.
Цитата(JuryS1806 @ 22.1.2011, 1:21) *
Соответственно делегат нужно запихнуть в приватную секцию и добавить на него несколько Update'ов...
Не понятная какая то фраза. Каких еще update, зачем?
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
JuryS1806
  опции профиля:
сообщение 30.1.2011, 17:07
Сообщение #13


Студент
*

Группа: Участник
Сообщений: 93
Регистрация: 21.10.2009
Из: Нижний Новгород
Пользователь №: 1168

Спасибо сказали: 9 раз(а)




Репутация:   0  


Вообщем, приблизительно сделал так:

delegate.h :
Раскрывающийся текст

#ifndef DELEGATE_H
#define DELEGATE_H

#include <QtGui>

//! Универсальный делегат для ввода любых значний в зависимости от UserRole
// 0 - строка ввода
// 1 - чекбокс
// 2 - спинбокс
// 3 - комбобокс
// 4 - ввод денег
// 5 - ввод дробных и целых чисел
// 6 - ввод целых чисел
// 7 - пустрой делегат, нередактируемый

class UniversalDelegate : public QItemDelegate {
     Q_OBJECT
public:
     UniversalDelegate(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;
     void updateEditorGeometry(
             QWidget *editor,
             const QStyleOptionViewItem &option,
             const QModelIndex &index) const;
     void paint ( QPainter * painter, const QStyleOptionViewItem & option, const QModelIndex & index ) const;
     void setComboValuesForCell(const QModelIndex index,const QList< QPair<int,QString> > aValues);
     void setComboValuesForColumn(const int aColumn,const QList< QPair<int,QString> > aValues);
     void setColumnDelegate(const int aColumn,const int aDelegate) {aColumnDelegate[aColumn] = aDelegate;}
     void setCellDelegate(const QModelIndex index,const int aDelegate) {aCellDelegate[index] = aDelegate;}

     QList< QPair<int,QString> > getComboValuesForCell(const QModelIndex index) const;
     int getCurrentDelegate(const QModelIndex index) const;

     void Clear();

private slots:
     void ChangeComboBoxText(int);

private:
     QMap <QModelIndex,QList< QPair<int,QString> > > aValuesOfComboForCell;
     QMap <QModelIndex,QVector<int> > aIndexesOfComboForCell;

     QMap <int,QList< QPair<int,QString> > > aValuesOfComboForColumn;
     QMap <int,QVector<int> > aIndexesOfComboForColumn;

     QMap <int,int> aColumnDelegate;
     QMap <QModelIndex,int> aCellDelegate;
};

#endif



delegate.cpp :

Раскрывающийся текст


#include "delegate.h"

//! Универсальный делегат для ввода любых значний в зависимости от UserRole
UniversalDelegate::UniversalDelegate(QObject *parent)
             : QItemDelegate(parent)
{
}

QWidget *UniversalDelegate::createEditor(
            QWidget *parent,
            const QStyleOptionViewItem& /* option */,
            const QModelIndex& index) const {
//Для начала построю делегат для всего столбца
int aCurUserRole;
    aCurUserRole = aColumnDelegate.value(index.column(),-1);
if (aCurUserRole == -1) //А если все-таки делегат для конкретной ячейки, тогда узнаю из нее, какой нужен
    aCurUserRole = aCellDelegate.value(index,0);

    if (aCurUserRole==1) //чекбокс
    {
        QCheckBox *editor = new QCheckBox(parent);
        connect(editor,SIGNAL(stateChanged(int)),this,SLOT(ChangeComboBoxText(int)));
        return editor;
    }

    if (aCurUserRole==2) //спинбокс
    {
        QSpinBox *editor = new QSpinBox(parent);
        editor->setMinimum(0);
        editor->setMaximum(100);

        return editor;
    }

    if (aCurUserRole==3) //комбобокс
    {
        QComboBox *editor = new QComboBox(parent);

        QList< QPair<int,QString> > aValues;

        if (aColumnDelegate.contains(index.column()))
            aValues = aValuesOfComboForColumn.value(index.column());
        else
            aValues = aValuesOfComboForCell.value(index);

        QList< QPair<int,QString> >::const_iterator it=aValues.begin();
        while (it != aValues.end())
            {
                const QPair <int,QString> aPair = *it;
                editor->addItem(aPair.second);
                ++it;
            }
            return editor;
    }

    if (aCurUserRole==4) //ввод денег
    {
        QDoubleSpinBox *editor = new QDoubleSpinBox(parent);
        editor->setMinimum(0.00);
        editor->setMaximum(999999999);
        editor->setDecimals(2);
        editor->setSingleStep(0.1);
        return editor;
    }

    if (aCurUserRole==5) //ввод дробных и целых чисел
    {
        QLineEdit *editor = new QLineEdit(parent);
        return editor;
    }

    if (aCurUserRole==6) //ввод целых чисел
    {
        QLineEdit *editor = new QLineEdit(parent);
        return editor;
    }

    if (aCurUserRole==7) //пустрой делегат, нередактируемый
    {
        QLineEdit *editor = new QLineEdit(parent);
        editor->setReadOnly(true);
        return editor;
    }

    //строка ввода
        QLineEdit *editor = new QLineEdit(parent);
        return editor;
}

void UniversalDelegate::setEditorData(
                QWidget *editor,
                const QModelIndex &index) const {

//Для начала построю делегат для всего столбца
int aCurUserRole;
    aCurUserRole = aColumnDelegate.value(index.column(),-1);
if (aCurUserRole == -1) //А если все-таки делегат для конкретной ячейки, тогда узнаю из нее, какой нужен
    aCurUserRole = aCellDelegate.value(index,0);

    if (aCurUserRole==0) //строка ввода
    {
        if (index.model()->data(index, Qt::EditRole).isNull()) return;
        const QString value = index.model()->data(
                         index, Qt::EditRole).toString();
        QLineEdit *lineEdit = static_cast<QLineEdit*>(editor);
        lineEdit->setText(value);
    }

    if (aCurUserRole==1) //чекбокс
    {
        QCheckBox *checkBox = static_cast<QCheckBox*>(editor);
                if (index.model()->data(index, Qt::EditRole).toInt()!=1)
                {
                    checkBox->setChecked(false);
                    checkBox->setText(QString::fromUtf8("Нет"));
                }
                else
                {
                    checkBox->setChecked(true);
                    checkBox->setText(QString::fromUtf8("Да"));
                }
    }

    if (aCurUserRole==2) //спинбокс
    {
        const int value = index.model()->data(index, Qt::EditRole).toInt();

        QSpinBox *spinBox = static_cast<QSpinBox*>(editor);
        spinBox->setValue(value);
    }

    if (aCurUserRole==3) //комбобокс
    {
        QComboBox *comboBox = static_cast<QComboBox*>(editor);

        const int value = index.model()->data(index, Qt::EditRole).toInt();

        QVector<int> aIndexes;
        if (aColumnDelegate.contains(index.column()))
            aIndexes = aIndexesOfComboForColumn.value(index.column());
        else
            aIndexes = aIndexesOfComboForCell.value(index);

        comboBox->setCurrentIndex(aIndexes.indexOf(value));
    }

    if (aCurUserRole==4) //ввод денег
    {
        const double value = index.model()->data(
                             index, Qt::EditRole).toDouble();
        QDoubleSpinBox *doubleSpinBox = static_cast<QDoubleSpinBox*>(editor);
        doubleSpinBox->setValue(value);
    }

    if (aCurUserRole==5) //ввод дробных и целых чисел
    {
        if (index.model()->data(index, Qt::EditRole).isNull()) return;
        const QString value = index.model()->data(
                             index, Qt::EditRole).toString();
        QLineEdit *lineEdit = static_cast<QLineEdit*>(editor);
        lineEdit->setText(value);
    }

    if (aCurUserRole==6) //ввод целых чисел
    {
        if (index.model()->data(index, Qt::EditRole).isNull()) return;
        const QString value = index.model()->data(
                             index, Qt::EditRole).toString();
        QLineEdit *lineEdit = static_cast<QLineEdit*>(editor);
        lineEdit->setText(value);
    }

    if (aCurUserRole==7) //пустрой делегат, нередактируемый
    {
        return;
    }

}

void UniversalDelegate::setModelData(
            QWidget *editor,
            QAbstractItemModel *model,
            const QModelIndex& index) const {

//Для начала построю делегат для всего столбца
int aCurUserRole;
    aCurUserRole = aColumnDelegate.value(index.column(),-1);
if (aCurUserRole == -1) //А если все-таки делегат для конкретной ячейки, тогда узнаю из нее, какой нужен
    aCurUserRole = aCellDelegate.value(index,0);

    if (aCurUserRole==0) //строка ввода
    {
        QLineEdit *lineEdit = static_cast<QLineEdit*>(editor);
        model->setData(index, lineEdit->text());
    }

    if (aCurUserRole==1) //чекбокс
    {
        QCheckBox *checkBox = static_cast<QCheckBox*>(editor);
        if (checkBox->isChecked())
            model->setData(index, "1");
        else
            model->setData(index, "0");
    }

    if (aCurUserRole==2) //спинбокс
    {
        QSpinBox *spinBox = static_cast<QSpinBox*>(editor);
        spinBox->interpretText();
        const int value = spinBox->value();

        model->setData(index, value, Qt::EditRole);
    }

    if (aCurUserRole==3) //комбобокс
    {
        QComboBox *comboBox = static_cast<QComboBox*>(editor);

        QVector<int> aIndexes;
        if (aColumnDelegate.contains(index.column()))
            aIndexes = aIndexesOfComboForColumn.value(index.column());
        else
            aIndexes = aIndexesOfComboForCell.value(index);

        model->setData(index, aIndexes.at(comboBox->currentIndex()), Qt::EditRole);
    }
    if (aCurUserRole==4) //ввод денег
    {
        QDoubleSpinBox *doubleSpinBox = static_cast<QDoubleSpinBox*>(editor);
        doubleSpinBox->interpretText();
        model->setData(index, doubleSpinBox->text());
    }

    if (aCurUserRole==5) //ввод дробных и целых чисел
    {
        QLineEdit *lineEdit = static_cast<QLineEdit*>(editor);

        if (lineEdit->text().isEmpty())
        {
            model->setData(index, QVariant(QString::null));
            return;
        }

        const QString aValue = QString::number(lineEdit->text().toDouble());
        model->setData(index, aValue);
    }

    if (aCurUserRole==6) //ввод целых чисел
    {
        QLineEdit *lineEdit = static_cast<QLineEdit*>(editor);

        if (lineEdit->text().isEmpty())
        {
            model->setData(index, QVariant(QString::null));
            return;
        }

        const QString aValue = QString::number(lineEdit->text().toInt());
        model->setData(index, aValue);
    }

    if (aCurUserRole==7) //пустрой делегат, нередактируемый
    {
        return;
    }

}

void UniversalDelegate::updateEditorGeometry(
            QWidget *editor,
            const QStyleOptionViewItem &option,
            const QModelIndex& /* index */) const {
    editor->setGeometry(option.rect);
}


void UniversalDelegate::paint ( QPainter * painter, const QStyleOptionViewItem & option, const QModelIndex & index ) const
{

int aCurUserRole;
    aCurUserRole = aColumnDelegate.value(index.column(),-1);
if (aCurUserRole == -1) //А если все-таки делегат для конкретной ячейки, тогда узнаю из нее, какой нужен
    aCurUserRole = aCellDelegate.value(index,0);

    if (aCurUserRole==0 || aCurUserRole==2 || aCurUserRole==4 || aCurUserRole==5 || aCurUserRole==6) //строка ввода
    {
     if (option.state & QStyle::State_Editing)
         return; //Передаю управление QLineEdit

     if (index.data(Qt::EditRole).isNull())
         return; //Пустая ячейка

     //Прорисовываю текст редактируемой ячейки
     const QString aText = index.data(Qt::EditRole).toString();
     painter->drawText(
         QRect(option.rect.left()+1,option.rect.top(),option.rect.width(),option.rect.hei
ght()),
         Qt::AlignLeft | Qt::AlignVCenter,
         aText
     );

    }

    if (aCurUserRole==1) //чекбокс
    {
     if (option.state & QStyle::State_Selected)
        {
         return; //Передаю управление QCheckBox
        }

     QString aText;
                if (index.model()->data(index, Qt::EditRole).toInt()!=1)
                    aText = QString::fromUtf8("Нет");
                else
                    aText = QString::fromUtf8("Да");

         painter->drawText(
         QRect(option.rect.left()+1,option.rect.top(),option.rect.width(),option.rect.hei
ght()),
         Qt::AlignLeft | Qt::AlignVCenter,
         aText
     );

    }

    if (aCurUserRole==3) //комбобокс
    {

     if (option.state & QStyle::State_Editing)
         return; //Передаю управление QComboBox

     if (index.data(Qt::EditRole).isNull())
         return; //Пустая ячейка

     QString aText;
     const int aIntValue = index.data(Qt::EditRole).toInt();

        QList< QPair<int,QString> > aValues;

        if (aColumnDelegate.contains(index.column()))
            aValues = aValuesOfComboForColumn.value(index.column());
        else
            aValues = aValuesOfComboForCell.value(index);

                QList< QPair<int,QString> >::const_iterator it=aValues.begin();
                    while (it != aValues.end())
                        {
                            const QPair <int,QString> aPair = *it;
                            if (aPair.first == aIntValue)
                                {
                                    aText = aPair.second;
                                    break;
                                }
                        ++it;
                        }

     painter->drawText(
         QRect(option.rect.left()+1,option.rect.top(),option.rect.width(),option.rect.hei
ght()),
         Qt::AlignLeft | Qt::AlignVCenter,
         aText
     );

    }

    if (aCurUserRole==7) //пустрой делегат, нередактируемый
    {
        return;
    }

}


void UniversalDelegate::setComboValuesForCell(const QModelIndex index,const QList< QPair<int,QString> > aValues)
{
    aValuesOfComboForCell[index] = aValues;

    QVector<int> aIndexes;
    QList< QPair<int,QString> >::const_iterator it=aValues.begin();
while (it != aValues.end())
{
    const QPair <int,QString> aPair = *it;
        aIndexes.append(aPair.first);
    ++it;
}
aIndexesOfComboForCell[index] = aIndexes;

}

void UniversalDelegate::setComboValuesForColumn(const int aColumn,const QList< QPair<int,QString> > aValues)
{
    aValuesOfComboForColumn[aColumn] = aValues;

    QVector<int> aIndexes;
    QList< QPair<int,QString> >::const_iterator it=aValues.begin();
while (it != aValues.end())
{
    const QPair <int,QString> aPair = *it;
        aIndexes.append(aPair.first);
    ++it;
}
aIndexesOfComboForColumn[aColumn] = aIndexes;

}

QList< QPair<int,QString> > UniversalDelegate::getComboValuesForCell(const QModelIndex index) const
{
QList< QPair<int,QString> > aValues;
return aValuesOfComboForCell.value(index,aValues);
}

int UniversalDelegate::getCurrentDelegate(const QModelIndex index) const
{
return aCellDelegate.value(index,0);
}


void UniversalDelegate::Clear()
{
    aValuesOfComboForCell.clear();
    aIndexesOfComboForCell.clear();
    aValuesOfComboForColumn.clear();
    aIndexesOfComboForColumn.clear();
    aCellDelegate.clear();
    aColumnDelegate.clear();
}

void UniversalDelegate::ChangeComboBoxText(int aValue)
{
    QCheckBox* aCheckBox = qobject_cast<QCheckBox*>(sender());
    if (aValue != 0)
    {
        aCheckBox->setText(QString::fromUtf8("Да"));
    }
    else
        aCheckBox->setText(QString::fromUtf8("Нет"));
}




Работает неплохо, при этом можно назначить делегат для ячейки или целого столбца.
Один минус - не могу прорисовать делегат в неактивном состоянии.

Вылетает программа, try ... catch не спасает.
Поэтому например при прорисовке чекбокса в неактивном состоянии получаю просто текст Да или Нет, а сам флажок можно установить при редакции ячейки. В целом нормально...
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
JuryS1806
  опции профиля:
сообщение 1.2.2011, 2:28
Сообщение #14


Студент
*

Группа: Участник
Сообщений: 93
Регистрация: 21.10.2009
Из: Нижний Новгород
Пользователь №: 1168

Спасибо сказали: 9 раз(а)




Репутация:   0  


Еще массу наработок сделал. Если кому нужно, пишите.

И такой вопрос. А как все таки в комбобокс засунуть таблицу ? И еще я при работе в Linux получаю комбо бокс, у которого размер выпадающего списка соответствует размеру содержимого текста, а в Windows ставятся троеточия по середине текста.

Решил проблему под Windows приблизительно так:

    int w = 0, w1;
    QFontMetrics fm(editor->font());

        QList< QPair<int,QString> >::const_iterator it=aValues.begin();
        while (it != aValues.end())
            {
                const QPair <int,QString> aPair = *it;
                editor->addItem(aPair.second);
                w1 = fm.width(aPair.second);
                if (w1 > w) w = w1;
                ++it;
            }
        if (editor->width() < w)
            editor->view()->setFixedWidth(w+25);

Но все таки думаю может быть фирменное решение этого вопроса есть. И ведь в Linux почему-то на автомате списки нормально отображаются, значит в винде их как-то залочили ????
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
dragomir
  опции профиля:
сообщение 20.11.2011, 22:03
Сообщение #15


Новичок


Группа: Новичок
Сообщений: 1
Регистрация: 20.11.2011
Пользователь №: 3014

Спасибо сказали: 0 раз(а)




Репутация:   0  


Заранее извиняюсь.
Надо срочно использовать описанный здесь делегат - очень подходящее решение, которое мне нужно в курсовой.
Может кто нибудь привести пример реализации - код таблицы, в которой будут использоваться реализованные возможности?
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение

2 страниц V  < 1 2
Быстрый ответОтветить в данную темуНачать новую тему
Теги
Нет тегов для показа


1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0




RSS Текстовая версия Сейчас: 20.4.2024, 0:36