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

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

Страниц: [1]   Вниз
  Печать  
Автор Тема: Вставить в QComboBox QCheckBox  (Прочитано 6306 раз)
PavelVX
Гость
« : Декабрь 14, 2011, 06:15 »

Хочу сделать QComboBox у которого элементами будут QCheckBox. Данные берутся с PostgreSQL сервака, но сохранять их обратно пока не требуется.
Для получения данных будет стандартный запрос, три колонки: bool(сам чек), capti (название которое с чеком светится), param (служебная инфа - очень нужная колонка, в ней инфа для пересчетов).
Порыл инет и наш форум, нашел http://www.prog.org.ru/topic_4240_0.html и это http://da-crystal.net/2008/06/checkbox-in-qcombobox/.
Второй случай все просто, но нельзя прикрутить модель со служебной инфой Грустный а без нее смысла нет огород городить.
А в первом случае не получается прикрутить модель. Лыжи у меня походу не той модели Улыбающийся
CheckBoxList.h
Код:
class QComboCheckBoxModel : public QSqlQueryModel {
        Q_OBJECT
    public:
        QComboCheckBoxModel(QObject *parent = 0);
        QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const;
    private:

        Qt::ItemFlags flags(const QModelIndex &index) const;
        bool setData(const QModelIndex &index, const QVariant &value, int role);

};


class QComboCheckBox: public QComboBox
{
      Q_OBJECT;

public:

      QComboCheckBox(QWidget *widget = 0);
      virtual ~QComboCheckBox();


      bool eventFilter(QObject * watched, QEvent * event);
      void showPopup();

private:
    QListView * m_listView;
    bool m_opening;

};
CheckBoxList.cpp
Код:
////////////////////////////////////////////////////////////////////////////////////
// конструктор
////////////////////////////////////////////////////////////////////////////////////
QComboCheckBox::QComboCheckBox(QWidget *parent) :
    QComboBox(parent)
{
    // заменяем стандартный вьювер
    m_listView = new QListView(this);
    setView(m_listView);
    // устанавливаем перехват событий
    m_listView->viewport()->installEventFilter(this);
    // флаг открытия комбобокса
    m_opening = false;
}

QComboCheckBox::~QComboCheckBox()
{
}

////////////////////////////////////////////////////////////////////////////////
//  Перехватчик событий для работы чекбоксов
////////////////////////////////////////////////////////////////////////////////
bool QComboCheckBox::eventFilter(QObject * watched, QEvent * event)
{
    // проверка тика отловленного события
    if (event->type() == QEvent::MouseButtonRelease)
    {
        // блокируем смену галочки при открытии
        if (m_opening)
        {
            m_opening = false;
            return QObject::eventFilter(watched, event);
        }
        // проверяем тип
        if (watched->parent()->inherits("QListView"))
        {
            // приводим к нужным типам
            QListView *tmp = (QListView *)(watched->parent());
            QMouseEvent *mEvent = (QMouseEvent *)event;
            QModelIndex ind = tmp->indexAt(mEvent->pos());
            // меняем состояние cheched
            bool checked = tmp->model()->data(ind,Qt::CheckStateRole).toBool();
            tmp->model()->setData(ind,!checked,Qt::CheckStateRole);
            // блокируем закрытие комбобокса
            return true;
        }
    }
    return QObject::eventFilter(watched, event);
}

////////////////////////////////////////////////////////////////////////////////
// функция раскрытия комбобокса
////////////////////////////////////////////////////////////////////////////////
void QComboCheckBox::showPopup()
{
    // флаг открытия комбобокса
    m_opening = true;
    // вызываем функцию класса - предка
    QComboBox::showPopup();
};

////////////////////////////////////////////////////////////////////////////////
// определяем модель для QComboCheckBox
////////////////////////////////////////////////////////////////////////////////
QComboCheckBoxModel::QComboCheckBoxModel(QObject *parent)
                 : QSqlQueryModel(parent) {
};

QVariant QComboCheckBoxModel::data(
             const QModelIndex &index,
             int role) const {
    QVariant value = QSqlQueryModel::data(index, role);
    if (index.column() == 0) value = value.toBool();
    return value;
}

Qt::ItemFlags QComboCheckBoxModel::flags(
        const QModelIndex &index) const
{
    Qt::ItemFlags flags = QSqlQueryModel::flags(index);
    if (index.column() == 0)
          flags = flags | Qt::ItemIsUserCheckable | Qt::ItemIsEditable;
    return flags;
}

bool QComboCheckBoxModel::setData(const QModelIndex &index, const QVariant &value, int role)
{
    if (index.column() == 0) return QSqlQueryModel::setData(index, value, role);
    return true;
}
Собственно использование:
//    QListView * tstView = new QListView(this);
//    QComboCheckBox * tstView = new QComboCheckBox(this);
    QTableView * tstView = new QTableView(this);
    QComboCheckBoxModel * tstModel = new QComboCheckBoxModel(this);
    strSQL = "SELECT 0, 'test', 'value' ";
    tstModel->setQuery(strSQL);
    tstView->setModel(tstModel);

В случае QTableView появляется и чекбокс и выбор true/false (почему - непонятно), в случае QListView - пустой список, а в случае QComboCheckBox сам комбобокс, но список не раскрывается.
Где и что я делаю не так???
Записан
PavelVX
Гость
« Ответ #1 : Декабрь 15, 2011, 10:27 »

Не получается у меня QListView заполнить правильно. В итоге переделал пример с ролями.
Неужели никто из более опытных товарищей не делал подобного? Это же очень удобно для сужения областей поиска и подобных вещей.
Записан
Авварон
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 3260


Просмотр профиля
« Ответ #2 : Декабрь 15, 2011, 11:37 »

в модели переопределяете флаги и делаете дату на чекед стейт роль. всё.
Записан
Странник
Гость
« Ответ #3 : Декабрь 15, 2011, 17:19 »

задача ваша что-то не очень понятна. сколько столбцов должно отображаться, три? что значит "пока" без возможности сохранения - то есть, в перспективе понадобится?
если я все понял правильно, и у вас три столбца, один из которых булева типа и должен отображаться как QCheckBox, я бы сделал свой QCheckBox делегат (неужели нет готовых?). в качестве view для QComboBox установил QTableView.

вариант, приведенный выше, тоже имеет право на жизнь. он более прост, пожалуй, но лично мне кажется менее логичным.
Записан
PavelVX
Гость
« Ответ #4 : Декабрь 16, 2011, 07:08 »

Отображается два столбца, булев + название, третий, скрытый, нужен для дальнейшей обработки. В нем, например, можно хранить ключи для дальнейшей обработки выбора. Сохранение в базу не нужно.
Своеобразным примером можно привести следующий случай: поиск по географическому положению.
уровень 1. комбобокс с чеками содержит региональные деления, что-то выбрав из него, вы уменьшили количество доступных вариантов в комбе 2 уровня.
уровень 2. комбо с чеками содержит области, причем только те, что разрешены на первом уровне.
уровень 3. комбо с чеками с названиями городов. Только те области, что разрешены на 2 уровне.
И тд и тп. Таким образом на выходе получим нужный набор элементов.
Если это можно как-то по другому получить, то выслушаю с вниманием.
Странник, я недопонял Грустный. Предлагается следующее: у QComboBox view сделать QTableView, а в нем сделать все делегатами на основе QCheckBox?
Авварон,
в data     if (index.column() == 0) value = value.toBool();
в flags if (index.column() == 0) flags = flags | Qt::ItemIsUserCheckable | Qt::ItemIsEditable;
Разве этого недостаточно, что бы первый столбец был редактируемым чеком?
Записан
Странник
Гость
« Ответ #5 : Декабрь 16, 2011, 10:49 »

Странник, я недопонял Грустный. Предлагается следующее: у QComboBox view сделать QTableView, а в нем сделать все делегатами на основе QCheckBox?
Авварон,
в data     if (index.column() == 0) value = value.toBool();
в flags if (index.column() == 0) flags = flags | Qt::ItemIsUserCheckable | Qt::ItemIsEditable;
Разве этого недостаточно, что бы первый столбец был редактируемым чеком?
для булевой колонки установить свой делегат. не придется наследоваться от модели.

чтобы получить желаемое при переопределении модели, вам необходимо:
1. отображать только столбец с названием
2. переопределить flags и для столбца с названием возвращать флаг Qt::ItemIsUserCheckable
3. переопределить data() и в CheckStateRole для столбца с названием возвращать Qt::Checked или Qt::Unckecked в зависимости от значения булева столбца
Записан
Страниц: [1]   Вверх
  Печать  
 
Перейти в:  


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