Russian Qt Forum

Qt => Model-View (MV) => Тема начата: QCasper от Ноябрь 06, 2007, 11:44



Название: QItemDelegate
Отправлено: QCasper от Ноябрь 06, 2007, 11:44
Имею такой код:

Код:
QDirModel *dm = new QDirModel(this);
QTreeView *tw = new QTreeView(this);
tw->setModel(dm);

Тут все понятно - получим окошко с файловой иерархией.
Теперь я хочу сделать, чтобы значки некоторых файлов (итемов) были помечены, скажем красным крестиком, если в названии этих файлов встречается, скажем строка "preved!".
Я так предполагаю, что это надо делать через QItemDelegate, переопределить метод paint, смотреть там if (index.data(Qt::DisplayRole).toString().contains("preved!")) то рисовать этот крестик. Вопрос заключается в том, как именно и когда его рисовать, то есть какие должны быть флаги option и как вычислить координаты, так чтобы крестик приходился именно на значок?


Название: Re: QItemDelegate
Отправлено: pastor от Ноябрь 06, 2007, 11:50
А не легче ввести свою систему иконок и подсунуть уже готовую иконку с крестиком?


Название: Re: QItemDelegate
Отправлено: QCasper от Ноябрь 06, 2007, 12:00
Да я тоже об этом думал, но хотелось бы тому способу тоже научиться.


Название: Re: QItemDelegate
Отправлено: WW от Ноябрь 06, 2007, 13:55
ИМХО. проще отнаследоваться от QDirModel и переопределить метод data. Вначале вызываешь родетельский метод, а потом свою обработку. А как пееркинуть иконку в др. формат и на нем нарисовать свой крестик - может ассистент помочь.


Название: Re: QItemDelegate
Отправлено: QCasper от Ноябрь 06, 2007, 14:26
Хм... не совсем то. Дело в том, что сегодня это QDirModel, завтра это QTableModel, послезавтра это вообще SomeMegaModel и у всех перегружать дату, мягко говоря, не очень хорошо. Так установил себе делегат готовый и радуйся жизни.


Название: Re: QItemDelegate
Отправлено: fox от Ноябрь 06, 2007, 14:31
А может поможет переопределение в ItemModel метода QVariant data(const QModelIndex & index, int role) const
а там уже смотреть
Когда требуются данные для нужной ячейки и для role == Qt::DecorationRole возвращать нужную иконку?


Название: Re: QItemDelegate
Отправлено: QCasper от Ноябрь 06, 2007, 14:44
А может поможет переопределение в ItemModel метода QVariant data(const QModelIndex & index, int role) const
а там уже смотреть
Когда требуются данные для нужной ячейки и для role == Qt::DecorationRole возвращать нужную иконку?

A WW по Вашему что предложил? Я уже отписал, что я думаю по поводу этого способа.


Название: Re: QItemDelegate
Отправлено: fox от Ноябрь 06, 2007, 18:51
A WW по Вашему что предложил? Я уже отписал, что я думаю по поводу этого способа.
Ну тогда сначала переопределяеш
void paint(QPainter * painter, const QStyleOptionViewItem & option, const QModelIndex & index) const
затем нужно порисовать фон для случаев если ячейка выделена
Код:
QPalette::ColorGroup cg = option.state & QStyle::State_Enabled ? QPalette::Normal : QPalette::Disabled;
if(option.state & QStyle::State_Selected){
  painter->fillRect(option.rect, option.palette.color(cg, QPalette::Highlight));
}

затем определяешь координаты откуда рисовать
Код:
int x = option.rect.x();
int y = option.rect.y();

рисуешь иконку
Код:
painter->drawPixmap(x+offset, y+offset, QPixmap());

ну и в конце
Код:
drawFocus(painter, option, option.rect.adjusted(0, 0, -1, -1));

и для ячеек где не нужно перерисовывать что то

Код:
QItemDelegate::paint(painter, opt, index);


Название: Re: QItemDelegate
Отправлено: QCasper от Ноябрь 06, 2007, 19:54
offset откуда берется?


Название: Re: QItemDelegate
Отправлено: fox от Ноябрь 06, 2007, 22:05
offset откуда берется?
Высчитываете как вам угодно
Так x и y указывают на самый край ячейки
Смотрите на сколько вам нужно сместить от края
Только нужно следить чтобы не вылезти за край области отрисовки
А то тогда наедиш на изображение соседних ячеек


Название: Re: QItemDelegate
Отправлено: QCasper от Ноябрь 07, 2007, 01:10
Не, ну капец :) Вы вопрос мой вообще читали? То, что Вы написали и так понятно, и я это осветил в вопросе. Ладно я уж не стал придираться к тому, нафига Вы расписали про то, как рисовать рамку при выделении, фокус и прочий ненужный флуд. Но Вы ведь и на мой вопрос, цитирую: "какие должны быть флаги option и как вычислить координаты, так чтобы крестик приходился именно на значок?" ответа так и не дали.
А вернее нет, простите, на вторую часть ответ получил: "Высчитываете как вам угодно"  :D


Название: Re: QItemDelegate
Отправлено: vaprele07 от Ноябрь 07, 2007, 02:44
virtual void drawDecoration ( QPainter * painter, const QStyleOptionViewItem & option, const QRect & rect, const QPixmap & pixmap ) const
есть QStyle::State QStyleOption::state, но думаю оно тебе н*х не нужно.


Название: Re: QItemDelegate
Отправлено: fox от Ноябрь 07, 2007, 19:04
Не, ну капец :) Вы вопрос мой вообще читали?
Видимо пропустил часть вопроса при прочтении

virtual void drawDecoration ( QPainter * painter, const QStyleOptionViewItem & option, const QRect & rect, const QPixmap & pixmap ) const
есть QStyle::State QStyleOption::state, но думаю оно тебе н*х не нужно.
Это поможет в пачке если посмотреть как сделанные расчёты куда рисуется иконка в самом itemdelegate
Просто надо эти же расчёты перенести к себе в код чтобы точно рассчитать координаты иконки чтобы поверх рисовать самому


Название: Re: QItemDelegate
Отправлено: QCasper от Ноябрь 07, 2007, 19:50
Это поможет в пачке если посмотреть как сделанные расчёты куда рисуется иконка в самом itemdelegate
Просто надо эти же расчёты перенести к себе в код чтобы точно рассчитать координаты иконки чтобы поверх рисовать самому

бгг :) Какие расчеты? Куда переносить? :) Нужно просто нарисовать пайнтером, указатель на который приходит в drawDecoration, необходимый рисунок и всё :)

To vaprele07:
спасибо, хотя пока еще не пробовал, но думаю должно заработать.


Название: Re: QItemDelegate
Отправлено: fox от Ноябрь 07, 2007, 23:49
бгг :) Какие расчеты? Куда переносить? :) Нужно просто нарисовать пайнтером, указатель на который приходит в drawDecoration, необходимый рисунок и всё :)

Поправьте меня если я не прав, но правильно я понял вас что вы хотите после отрисовки иконки по верх ниё вывести что то своё?
В крации это будет как отрисовка иконка, затем определение области где была отрисована иконка и уже затем отрисовка в данной области чего то своего
А что будете передавать в const QRect & rect?
Если заглянуть в исходник qitemdelegate то перед вызовом отрисовки drawDecoration() как раз и создаётся rect для определения области где будет отрисовываться иконка


Название: Re: QItemDelegate
Отправлено: ритт от Ноябрь 08, 2007, 00:35
сдаётся мне, фокс - анонимус :)


Название: Re: QItemDelegate
Отправлено: QCasper от Ноябрь 08, 2007, 01:13
Если заглянуть в исходник qitemdelegate то перед вызовом отрисовки drawDecoration() как раз и создаётся rect для определения области где будет отрисовываться иконка

Вот именно! Наконец то :) Библиотека все посчитает за меня, и вызовет мне drawDecoration() с готовым рассчитанным ректом :) И мне только останется вызвать в этом drawDecoration() код типа painter->drawPixmap("my_mega_icon.png");



Название: Re: QItemDelegate
Отправлено: fox от Ноябрь 08, 2007, 01:29
Вот именно! Наконец то :) Библиотека все посчитает за меня, и вызовет мне drawDecoration() с готовым рассчитанным ректом :) И мне только останется вызвать в этом drawDecoration() код типа painter->drawPixmap("my_mega_icon.png");
Она посчитает для стандартной иконки
И используемый для отрисовки данной иконки QRect decorationRect; наружу не как из paintа не вылазит
Как вы собираетесь получить координаты иконки где она была нарисована?
Так как для drawDecoration() нужно указать область отрисовки полюбому
Или вы предлагаете переопределить drawDecoration()?


Название: Re: QItemDelegate
Отправлено: Sergey B. от Ноябрь 08, 2007, 07:06
Примет из книги Foundations of Qt Development.
Код:
class BarDelegate : public QAbstractItemDelegate
{
public:
BarDelegate( QObject *parent = 0 );
void paint( QPainter *painter,
const QStyleOptionViewItem &option,
const QModelIndex &index ) const;
QSize sizeHint( const QStyleOptionViewItem &option,
const QModelIndex &index ) const;
};

The sizeHint method is shown in Listing 5-10. It simply returns a size that is large enough
yet doesn’t exceed the size limitations. Remember that this is just a hint; the real size can be
changed by Qt for layout issues or by the user by adjusting the size of rows and columns.

Код:
QSize BarDelegate::sizeHint( const QStyleOptionViewItem &option,
const QModelIndex &index ) const
{
return QSize( 45, 15 );
}

Код:
void BarDelegate::paint( QPainter *painter,
const QStyleOptionViewItem &option, const QModelIndex &index ) const
{
if( option.state & QStyle::State_Selected )
painter->fillRect( option.rect, option.palette.highlight() );
int value = index.model()->data( index, Qt::DisplayRole ).toInt();
double factor = (double)value/100.0;
painter->save();
if( factor > 1 )
{
painter->setBrush( Qt::red );
factor = 1;
}
else
painter->setBrush( QColor( 0, (int)(factor*255), 255-(int)(factor*255) ) );
painter->setPen( Qt::black );
painter->drawRect( option.rect.x()+2, option.rect.y()+2,
(int)(factor*(option.rect.width()-5)), option.rect.height()-5 );
painter->restore();
}

Код:
QTableView table;
QStandardItemModel model( 10, 2 );
for( int r=0; r<10; ++r )
{
QStandardItem *item = new QStandardItem( QString("Row %1").arg(r+1) );
item->setEditable( false );
model.setItem( r, 0, item );
model.setItem( r, 1, new QStandardItem( QString::number((r*30)%100 )) );
}
table.setModel( &model );
BarDelegate delegate;
table.setItemDelegateForColumn( 1, &delegate );


Название: Re: QItemDelegate
Отправлено: QCasper от Ноябрь 08, 2007, 11:12
Или вы предлагаете переопределить drawDecoration()?

Вам действительно это только сейчас стало понятно? Это уже давно было предложено, правда vaprele07, а не мною. За что ему собственно и спасибо.


Название: Re: QItemDelegate
Отправлено: fox от Ноябрь 08, 2007, 12:14
Вам действительно это только сейчас стало понятно? Это уже давно было предложено, правда vaprele07, а не мною. За что ему собственно и спасибо.
Странный путь Но каждому свое


Название: Re: QItemDelegate
Отправлено: QCasper от Ноябрь 09, 2007, 13:57
Странный путь Но каждому свое

Это у меня то странный путь? :o :D Ну конечно, куда проще лопатить код библиотеки, в поисках необходимого кода, разбираться как он работает и тащить его в свою реализацию. Причем после этого еще наверняка всячески модифицировать и только потом (!!!) добавить код, рисующий крестик. Конечно, куда более сложное дело переопределить метод drawDecoration(painter, option, rect, pixmap), только добавив в него код, который рисует крестик в области rect :)


Название: Re: QItemDelegate
Отправлено: pastor от Ноябрь 09, 2007, 14:56
...куда проще лопатить код библиотеки, в поисках необходимого кода, разбираться как он работает и тащить его в свою реализацию.

Между прочим, это не так уж и плохо, знать как работает библиотека (конечно если это вам интересно). В коде самой библиотеке находиться много интересных решений и примеров использования того или иного метода. Чтение исходного кода бибилотеки может помочь при решении той или иной задачи. Так что зря вы так, fox прав, можно было хотябы подсмотреть...


Название: Re: QItemDelegate
Отправлено: fox от Ноябрь 09, 2007, 14:57
Это у меня то странный путь? :o :D Ну конечно, куда проще лопатить код библиотеки, в поисках необходимого кода, разбираться как он работает и тащить его в свою реализацию. Причем после этого еще наверняка всячески модифицировать и только потом (!!!) добавить код, рисующий крестик. Конечно, куда более сложное дело переопределить метод drawDecoration(painter, option, rect, pixmap), только добавив в него код, который рисует крестик в области rect :)
Поэтому я и написал каждому своё Тем более для случая если все картинки статичны на мой взгляд вообще нет смысла рисовать что то по верх них Проще заранее сделать нужные наборы

Тем более все равно придётся перетаскивать часть кода при переопределении drawDecoration() Так как если посмотреть что там делается то можно заметить что там не только тупая отрисовка картинки в определённых координатах но и как минимум проверка отрисовка картинки в выделенной ячейки или нет


Название: Re: QItemDelegate
Отправлено: QCasper от Ноябрь 09, 2007, 15:41
Тем более для случая если все картинки статичны на мой взгляд вообще нет смысла рисовать что то по верх них Проще заранее сделать нужные наборы
Не статичны, в определенный момент времени, нужно на стандартную иконку файла накладывать некоторое изображение. Например, если Вы когда-нибудь пользовались TortoiseSVN под винду, то видели как в проводнике появляются галочки и восклицательные знаки на файлах, которые up to date или changed соответственно. Вот мне нужно что-то вроде этого.

Тем более все равно придётся перетаскивать часть кода при переопределении drawDecoration() Так как если посмотреть что там делается то можно заметить что там не только тупая отрисовка картинки в определённых координатах но и как минимум проверка отрисовка картинки в выделенной ячейки или нет

Не придется. Мой делегат выглядит так:
Код:
void PatchItemDelegate::paint(QPainter *p, const QStyleOptionViewItem & o, const QModelIndex & i) const {
const_cast<PatchItemDelegate*>(this)->m_Operation = i.data(OperationRole).toInt();
QItemDelegate::paint(p, o, i);
}
void PatchItemDelegate::drawDecoration(QPainter *p, const QStyleOptionViewItem & o, const QRect & r, const QPixmap & px) const {
QItemDelegate::drawDecoration(p,o,r,px);

if (m_Operation == None) return;

int x = r.topLeft().x();
int y = r.topLeft().y() + r.height()/3;

p->drawPixmap(x,y, QPixmap(m_IconFiles[m_Operation]));
}

И всё! В зависимости от OperationRole конкретного итема, поверх его иконки рисуется соответствующее изображение (восклицательный знак или галочка по аналогии с TortoiseSVN). И не надо ниче считать, таскать куски кодов, где-то копаться, разбираться. И дело тут не в "каждому своё", а в оптимальном подходе к решению задачи.


Название: Re: QItemDelegate
Отправлено: QCasper от Ноябрь 09, 2007, 15:53
Между прочим, это не так уж и плохо, знать как работает библиотека (конечно если это вам интересно). В коде самой библиотеке находиться много интересных решений и примеров использования того или иного метода. Чтение исходного кода бибилотеки может помочь при решении той или иной задачи. Так что зря вы так, fox прав, можно было хотябы подсмотреть...

Я не говорю, что просмотр кода библиотеки в ста процентах случаев бесполезное занятие. Я говорю, что нафига решать через такие грабли данную задачу, когда можно обойтись и без этого?


Название: Re: QItemDelegate
Отправлено: fox от Ноябрь 09, 2007, 16:20
Не статичны, в определенный момент времени, нужно на стандартную иконку файла накладывать некоторое изображение. Например, если Вы когда-нибудь пользовались TortoiseSVN под винду, то видели как в проводнике появляются галочки и восклицательные знаки на файлах, которые up to date или changed соответственно. Вот мне нужно что-то вроде этого.
Не видел так как не пользуюсь

Не придется. Мой делегат выглядит так:
У этого решения есть один маленький визуальный минус связанный как раз с выделением или наоборот в зависимости от того что вы пытаетесь добиться В стандартном варианте поведения иконка при отрисовки в выделенной ячейке немного притеняется В вашем решении по верх притенённой иконки будет отрисованн яркий значек Хотя может это вы и хотите добиться Из ваших сообщений не совсем понятно

И всё! В зависимости от OperationRole конкретного итема, поверх его иконки рисуется соответствующее изображение (восклицательный знак или галочка по аналогии с TortoiseSVN). И не надо ниче считать, таскать куски кодов, где-то копаться, разбираться. И дело тут не в "каждому своё", а в оптимальном подходе к решению задачи.
Видимо у нас с вами разное понятие об оптимальности


Название: Re: QItemDelegate
Отправлено: fox от Ноябрь 09, 2007, 16:21
Я не говорю, что просмотр кода библиотеки в ста процентах случаев бесполезное занятие. Я говорю, что нафига решать через такие грабли данную задачу, когда можно обойтись и без этого?
Мы опять возвращаемся к точке зрения На мой взгляд и вкус данное решение будет граблями


Название: Re: QItemDelegate
Отправлено: QCasper от Ноябрь 09, 2007, 16:27
Мы опять возвращаемся к точке зрения На мой взгляд и вкус данное решение будет граблями

В чем грабельность моего (вернее vaprele07) решения мне не понятно. Если не принимать во внимание минус, упомянутый Вами в предыдущем посте, вобщем-то достаточно нормальное решение. По-крайней мере время точно экономит, да и по производительности вряд-ли уступает.


Название: Re: QItemDelegate
Отправлено: fox от Ноябрь 09, 2007, 16:51
В чем грабельность моего (вернее vaprele07) решения мне не понятно. Если не принимать во внимание минус, упомянутый Вами в предыдущем посте, вобщем-то достаточно нормальное решение. По-крайней мере время точно экономит, да и по производительности вряд-ли уступает.
Для меня лично он не лучше не хуже других решений, просто я бы не пошёл по данному пути решения по нескольким причинам
Про мизерный визуальный недостаток я упомянул
Так же остаётся вопрос про производительность Но данный вопрос нельзя обсуждать оторвано от задачи которая решается Так как в вашем случаи возможно это будет решение хорошее В моем случаи оно будет возможно снижать производительность
Возможно привести ещё доводы, начиная с того что в какой нибудь будущей версии Qt может измениться поведение drawDecoration() так что данное решение будет не работоспособным и тд Но это уже будут мелочи

Просто я предложил свои варианты и попытался понять предложеные варианты