crossplatform.ru

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

 
Ответить в данную темуНачать новую тему
> Табличное представление с виджетами, которое по функциональности мало отличалось бы от GridLayout
Vorchun
  опции профиля:
сообщение 8.2.2011, 15:56
Сообщение #1


Новичок


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

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




Репутация:   0  


Задача: Создать на базе модель представления таблицу из виджетов, таким образом чтоб она по функциональности не отличалась от виджетов помещенных в gridlayout

Частичное решение
Существует контейнер в котором хранится List из CalendarI

Существует модель ( прослойка между представлением и контейнером) умеющая через data() возвращать CalendarI
Существует виджет CalendarIW который умеет отображать CalendarI ( setItem() ) - у меня это виджет с кнопочками

Я сделал следующий делегат (немного криво, но в целом вполне функционально ):

CalendarD::CalendarD( QObject *qoParent )
: QStyledItemDelegate( qoParent )
{}

CalendarD::~CalendarD() {}

//virtual
void CalendarD::paint( QPainter *qpPainter
                     , const QStyleOptionViewItem &qsoviOption
                     , const QModelIndex &qmiIndex ) const
{
if ( ! qmiIndex.data( Qt::EditRole ).isValid() ) return;

QPalette qpPalette = qsoviOption.palette;

qpPalette.setBrush( QPalette::Window
                   , qpPalette.brush( QPalette::Base ) );

CalendarIW *ciw = new CalendarIW();
ciw->setPalette( qpPalette );
ciw->setItem( qmiIndex.data( Qt::EditRole ).value< CalendarI >() );
ciw->resize( qsoviOption.rect.size() );

qpPainter->save();
qpPainter->translate( qsoviOption.rect.topLeft() );
qpPainter->setClipRect( qsoviOption.rect.translated( -qsoviOption.rect.x()
                                                    , -qsoviOption.rect.y() ) );
ciw->render( qpPainter );

qpPainter->restore();

delete ciw;

}

//virtual
QSize CalendarD::sizeHint( const QStyleOptionViewItem &qsoviOption
                         , const QModelIndex &qmiIndex ) const
{
CalendarI ci( qmiIndex.data( Qt::EditRole ).value< CalendarI >() );

CalendarIW *ciw = new CalendarIW();
ciw->setItem( ci );

return ( ci.type() != CalendarI::Day )
        ? QSize( 0, 0 )
        : ciw->sizeHint();

delete ciw;
}

QWidget *CalendarD::createEditor( QWidget *qwParent
                                , const QStyleOptionViewItem &
                                , const QModelIndex &qmiIndex ) const
{
CalendarIW *ciw = new CalendarIW( qwParent );
ciw->setAutoFillBackground( true );
ciw->setMouseTracking( true );
return ciw;
}

void CalendarD::setEditorData( QWidget *qwEditor
                             , const QModelIndex &qmiIndex ) const
{
CalendarIW *ciw = dynamic_cast< CalendarIW * >( qwEditor );

Q_ASSERT( ciw );

CalendarI ci( qmiIndex.data( Qt::EditRole ).value< CalendarI >() );

ciw->setItem( ci );
}

void CalendarD::setModelData( QWidget *qwEditor
                            , QAbstractItemModel *qaimModel
                            , const QModelIndex &qmiIndex ) const
{}

void CalendarD::updateEditorGeometry( QWidget *qwEditor
                                    , const QStyleOptionViewItem &qsoviOption
                                    , const QModelIndex & ) const
{ qwEditor->setGeometry( qsoviOption.rect ); }

//protected:

bool CalendarD::eventFilter( QObject *qoEditor , QEvent *qeEvent )
{

if ( qeEvent->type() == QEvent::Leave )
{
  QWidget *qwWidget = qobject_cast< QWidget * >( qoEditor );

  emit closeEditor( qwWidget
                  , QAbstractItemDelegate::RevertModelCache );
  return true;
}

return QStyledItemDelegate::eventFilter( qoEditor , qeEvent );
}


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

bool CalendarD::eventFilter( QObject *qoEditor , QEvent *qeEvent ) - обеспечивает выход из виджета, когда мышь покидает область редактирования

Открывать ячейку на редактирование планировалось из представления следующим образом

CalendarV::CalendarV( QWidget *qwParent )
: QTableView( qwParent )
{
setMouseTracking( true );
connect( this, SIGNAL( entered( const QModelIndex & ) ), this , SLOT( openEditor(  const QModelIndex &  ) )  );

//public slots:
void CalendarV::openEditor(  const QModelIndex & qmiIndex )
{
  if (  state() != QAbstractItemView::NoState
     || ! qmiIndex.isValid()
     || ! qmiIndex.flags() & Qt::ItemIsEditable ) return;

edit( qmiIndex );
}


При таком подходе - юзер водит мышью по вьюву тыкает на кнопочки в виджетах - и вообще не догадывается что перед ним не Gridlayout. Это работает при медленном движении мыши. Все было бы хорошо если бы не одно НО - при быстром движении мыши возникает следующая ситуация:
1) мышь пролетает по первой ячейке - создается первая ячейка
2) мышь продолжает лететь - пока первая ячейка еще не создалась или еще хз почему - но мышь уже покинула эту ячейку - соответственно виджет редактора из делегата не получил событие QEvent::Leave приведшее к его уничтожению, те первая ячейка продолжает редактироваться
3) поскольку первая ячейка еще редактируется - все остальные ячейки не открываются на редактирование...

Вот!

Была идея, что надо отлавливать mousePressEvent() - открывать ячейку на редактирование, а потом повторно создавать событие нажатие мыши, чтоб его отловил уже открытый виджет - но как это сделать я не в курсе...

Есть ли у кого какие либо идеи еще?



Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
Алексей1153
  опции профиля:
сообщение 8.2.2011, 19:18
Сообщение #2


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

Группа: Участник
Сообщений: 2933
Регистрация: 19.6.2010
Из: Обливион
Пользователь №: 1822

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




Репутация:   34  


Цитата(Vorchun @ 8.2.2011, 17:56) *
Была идея, что надо отлавливать mousePressEvent()

только там имхо и надо. Но не пресс, а релиз только лучше
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
abc
  опции профиля:
сообщение 18.2.2011, 22:16
Сообщение #3


Участник
**

Группа: Участник
Сообщений: 221
Регистрация: 16.12.2010
Из: СПб
Пользователь №: 2272

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




Репутация:   4  


событие можно так создать:
QCoreApplication::sendEvent
в остальное я не вник)
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение

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


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




RSS Текстовая версия Сейчас: 25.9.2022, 11:47