Russian Qt Forum

Qt => Кладовая готовых решений => Тема начата: asvil от Июль 28, 2011, 16:08



Название: QHeaderView + QCheckBox
Отправлено: asvil от Июль 28, 2011, 16:08
Господа, сегодя вы имеете честь лицезреть "QtCheckHeaderView" класс, который отрисовывает заголовок с виджетом типа "check box", по клику на котором, происходит снятие или выделение флажков во всех строках или столбцах данной секции заголовка.

Тестирование и критика всячески приветствуются.


Название: Re: QHeaderView + QCheckBox
Отправлено: Пантер от Июль 28, 2011, 16:23
И все колонки должны содержать чекбоксы?


Название: Re: QHeaderView + QCheckBox
Отправлено: asvil от Июль 28, 2011, 16:43
Заголовок будет рисовать чекбоксы только в тех секциях, которые вы укажете с помощью метода addCheckable.


Название: Re: QHeaderView + QCheckBox
Отправлено: Пантер от Июль 28, 2011, 16:45
Филоненко Михаил, тогда на скриншоте сделай пару секций без чекбоксов, а то не понятно.


Название: Re: QHeaderView + QCheckBox
Отправлено: asvil от Июль 28, 2011, 17:05
Готово.


Название: Re: QHeaderView + QCheckBox
Отправлено: GreatSnake от Сентябрь 28, 2011, 09:20
Господа, сегодя вы имеете честь лицезреть "QtCheckHeaderView" класс, который отрисовывает заголовок с виджетом типа "check box", по клику на котором, происходит снятие или выделение флажков во всех строках или столбцах данной секции заголовка.
Наверное нужно всё-таки внести пояснения насчёт виджета типа "check box". Ведь вы его не используете вовсе, а всего лишь отрисовываете ) Вот, если бы вы его действительно задействовали, а ещё лучше QAbstractButton, было бы намного интереснее)

Цитировать
Тестирование и критика всячески приветствуются.
Судя по тому, что в коде отсутствует перегруженный метод QHeaderView::sectionSizeFromContents(), расчёт размера секции делается без учёта check-box-a.


Название: Re: QHeaderView + QCheckBox
Отправлено: asvil от Сентябрь 28, 2011, 11:25
Добавьте его, пожалуйста, сами, что-то закоммитить не могу.

patch
Код:
diff --git a/QtCheckHeaderView.cpp b/QtCheckHeaderView.cpp
index 0b5e7e7..97f028c 100644
--- a/QtCheckHeaderView.cpp
+++ b/QtCheckHeaderView.cpp
@@ -255,9 +255,7 @@ void QtCheckHeaderView::paintSection(QPainter* painter, const QRect& rect, int l
         // ===============================================================
     }
     else
-    {
         QHeaderView::paintSection(painter, rect, logicalIndex);
-    }
 }
 
 void QtCheckHeaderView::updateCheckbox(int logicalIndex)
@@ -293,17 +291,11 @@ void QtCheckHeaderView::updateCheckbox(int logicalIndex)
         }
     }
     if (allunchecked)
-    {
         mCheckStates.insert(logicalIndex, Qt::Unchecked);
-    }
     else if (allchecked)
-    {
         mCheckStates.insert(logicalIndex, Qt::Checked);
-    }
     else
-    {
         mCheckStates.insert(logicalIndex, Qt::PartiallyChecked);
-    }
 }
 
 void QtCheckHeaderView::updateModel(int logicalIndex)
@@ -311,16 +303,25 @@ void QtCheckHeaderView::updateModel(int logicalIndex)
     Qt::CheckState checked = mCheckStates.value(logicalIndex);
 
     if (orientation() == Qt::Horizontal)
-    {
         for (int i = 0; i < model()->rowCount(rootIndex()); ++i)
-        {
             model()->setData(model()->index(i, logicalIndex, rootIndex()), checked, Qt::CheckStateRole);
-        }
-    } else if (orientation() == Qt::Vertical)
-    {
+    else if (orientation() == Qt::Vertical)
         for (int i = 0; i < model()->columnCount(rootIndex()); ++i)
-        {
             model()->setData(model()->index(logicalIndex, i, rootIndex()), checked, Qt::CheckStateRole);
-        }
-    }
+}
+
+QSize QtCheckHeaderView::sectionSizeFromContents(int logicalIndex) const
+{
+    QStyleOptionHeader opt;
+    initStyleOption(&opt);
+    QStyleOptionButton option;
+    option.QStyleOption::operator =(opt);
+
+    QRect cr = style()->subElementRect(QStyle::SE_ViewItemCheckIndicator, &opt);
+    QSize res = QHeaderView::sectionSizeFromContents(logicalIndex);
+    if (orientation() == Qt::Horizontal)
+        res.setWidth(res.width() + cr.width());
+    else
+        res.setHeight(res.height() + cr.height());
+    return res;
 }
diff --git a/QtCheckHeaderView.h b/QtCheckHeaderView.h
index 5fdd148..3281b08 100644
--- a/QtCheckHeaderView.h
+++ b/QtCheckHeaderView.h
@@ -45,6 +45,8 @@ class QtCheckHeaderView: public QHeaderView
         void mousePressEvent(QMouseEvent* event);
         void paintSection(QPainter* painter, const QRect& rect, int logicalIndex) const;
 
+        QSize sectionSizeFromContents(int logicalIndex) const;
+
         QList<int> mCheckableIndexes;
         QMap<int, Qt::CheckState> mCheckStates;
         bool blockDataChanged;

Цитировать
QAbstractButton
А зачем?


Название: Re: QHeaderView + QCheckBox
Отправлено: GreatSnake от Сентябрь 28, 2011, 11:35
Цитировать
QAbstractButton
А зачем?
Хочется по аналогии с QTabBar иметь возможность добавлять кнопки.
В принципе я это реализовал. Правда, повозиться пришлось не мало. Основная проблема была в отсечении части виджета, который частично не влезает в секцию.
Как только доберусь до рабочей тачки, выложу.


Название: Re: QHeaderView + QCheckBox
Отправлено: asvil от Сентябрь 28, 2011, 11:38
Таки это совсем другой функционал. Наследуйтесь же.


Название: Re: QHeaderView + QCheckBox
Отправлено: GreatSnake от Сентябрь 28, 2011, 11:42
Таки это совсем другой функционал.
Ну почему же другой? Имея такую возможность, не пришлось бы городить огород с отрисовкой check-box-ов. Достаточно было бы просто добавить на секцию QCheckBox.
Цитировать
Наследуйтесь же.
Повторюсь. На деле всё оказывается не так просто :(


Название: Re: QHeaderView + QCheckBox
Отправлено: asvil от Сентябрь 28, 2011, 11:56
Ну почему же, наследование в кути означает что надо, выдрать из родительских классов нужный код и зависимости этого кода от private методов, и на получившейся основе рисовать виджеты.

Огород был создан для того, чтобы не городить огород объектов/сигналов/слотов. И огород поэтому узкоспециализированный, рассчитанный на большое количество строк/столбцов (хотя, зачем на большом количестве строк, везде чекбоксы?:)) Кстати при добавлении в себя виджета, пришлось бы и его размер хэндлить, не менее феерическое занятие.


Название: Re: QHeaderView + QCheckBox
Отправлено: GreatSnake от Сентябрь 28, 2011, 12:17
Ну почему же, наследование в кути означает что надо, выдрать из родительских классов нужный код и зависимости этого кода от private методов, и на получившейся основе рисовать виджеты.
Вот именно "рисовать" виджеты в итоге пришлось через QWidget::render() в картинку и уже её рендерить, а сами виджеты выводить за границы QHeaderView.
В общем в итоге вылезла куча нюансов...


Название: Re: QHeaderView + QCheckBox
Отправлено: asvil от Сентябрь 28, 2011, 12:22
Цитировать
QWidget::render()
Так для этого же предусмотрен QStyle::drawControl();


Название: Re: QHeaderView + QCheckBox
Отправлено: GreatSnake от Сентябрь 28, 2011, 12:52
Цитировать
QWidget::render()
Так для этого же предусмотрен QStyle::drawControl();
Не годится, т.к. он типизирован. К тому же как-то нужно инициализить QStyleOption, а это ещё та работа. В случае с QWidget::render() не требуется вообще знать про тип виджета. Блин, сейчас нет доступа к исходникам. В понедельник покажу.