1 /***************************************************************************
2 * Copyright (C) 2005 by David Cuadrado *
5 * This program is free software; you can redistribute it and/or modify *
6 * it under the terms of the GNU General Public License as published by *
7 * the Free Software Foundation; either version 2 of the License, or *
8 * (at your option) any later version. *
10 * This program is distributed in the hope that it will be useful, *
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
13 * GNU General Public License for more details. *
15 * You should have received a copy of the GNU General Public License *
16 * along with this program; if not, write to the *
17 * Free Software Foundation, Inc., *
18 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
19 ***************************************************************************/
21 #include "framestable.h"
24 #include <QPaintEvent>
25 #include <QItemSelectionModel>
26 #include <QPainterPath>
28 #include <QHeaderView>
30 #include <QInputDialog>
32 #include <dcore/debug.h>
33 #include <dcore/algorithm.h>
40 ////////// FramesTableItemDelegate ///////////
42 class FramesTableItemDelegate
: public QAbstractItemDelegate
45 FramesTableItemDelegate(QObject
* parent
= 0 );
46 ~FramesTableItemDelegate();
47 virtual void paint ( QPainter
* painter
, const QStyleOptionViewItem
& option
, const QModelIndex
& index
) const;
48 virtual QSize
sizeHint ( const QStyleOptionViewItem
& option
, const QModelIndex
& index
) const;
51 FramesTableItemDelegate::FramesTableItemDelegate(QObject
* parent
) : QAbstractItemDelegate(parent
)
55 FramesTableItemDelegate::~FramesTableItemDelegate()
61 void FramesTableItemDelegate::paint ( QPainter
* painter
, const QStyleOptionViewItem
& option
, const QModelIndex
& index
) const
63 Q_ASSERT(index
.isValid());
65 FramesTable
*table
= qobject_cast
<FramesTable
*>(index
.model()->parent());
66 FramesTableItem
*item
= dynamic_cast<FramesTableItem
*>(table
->itemFromIndex(index
));
69 QStyleOptionViewItem opt
= option
;
71 // draw the background color
72 value
= index
.data( Qt::BackgroundColorRole
);
78 bool sound
= table
->isSoundLayer(index
.row());
82 painter
->fillRect(option
.rect
, value
.value
<QColor
>() );
90 bool sound
= table
->isSoundLayer(index
.row());
91 painter
->setPen(QPen(Qt::lightGray
, 1));
94 if ( index
.column() % 5 == 0 )
96 painter
->setBrush(Qt::lightGray
);
97 painter
->drawRect(option
.rect
); //FIXME: user paleta de colores
101 painter
->setBrush(Qt::white
);
102 painter
->drawRect(option
.rect
);//FIXME: user paleta de color
107 painter
->fillRect(option
.rect
, Qt::white
);
115 int offset
= option
.rect
.width() - 4;
117 if ( item
&& index
.isValid() )
122 painter
->setBrush(Qt::black
);
124 if( !item
->isSound() )
126 QColor color
= Qt::white
; //FIXME: user paleta de color
127 if ( item
->inGroupPosition() == FramesTableItem::Begin
)
129 painter
->fillRect(option
.rect
, color
);
130 painter
->drawLine(option
.rect
.topLeft(), option
.rect
.bottomLeft());
131 painter
->drawEllipse(option
.rect
.left()+2, option
.rect
.bottom() - (offset
+2), offset
, offset
);
133 else if ( item
->inGroupPosition() == FramesTableItem::End
)
135 painter
->fillRect(option
.rect
, color
);
136 painter
->drawLine(option
.rect
.topRight(), option
.rect
.bottomRight());
138 else if( item
->inGroupPosition() == FramesTableItem::Intermediate
)
140 painter
->fillRect(option
.rect
, color
);
144 painter
->drawEllipse(option
.rect
.left()+2, option
.rect
.bottom() - (offset
+2), offset
, offset
);
149 painter
->setPen(QPen(Qt::blue
, 1));
151 int y
= option
.rect
.center().y();
152 int xi
= option
.rect
.x();
153 int xf
= option
.rect
.width();
155 painter
->drawLine(QPoint(xi
, y
) , QPoint(xf
, y
));
161 if ( item
->isLocked() )
164 painter
->setBrush(Qt::red
);
166 painter
->drawEllipse(option
.rect
.left()+2, option
.rect
.bottom() - (offset
+2), offset
, offset
);
173 if (option
.showDecorationSelected
&& (option
.state
& QStyle::State_Selected
))
175 QPalette::ColorGroup cg
= option
.state
& QStyle::State_Enabled
? QPalette::Normal
: QPalette::Disabled
;
178 painter
->setPen(QPen(option
.palette
.brush(cg
, QPalette::Highlight
), 2));
180 QRectF rectSelection
= option
.rect
.adjusted(1,1,-1,-1);
181 painter
->drawRect(rectSelection
);
186 QPalette::ColorGroup cg
= option
.state
& QStyle::State_Enabled
? QPalette::Normal
: QPalette::Disabled
;
187 painter
->setPen(QPen(option
.palette
.brush(cg
, QPalette::Foreground
), 1)),
189 painter
->drawLine(option
.rect
.bottomLeft(), option
.rect
.bottomRight());
190 painter
->drawLine(option
.rect
.topLeft(), option
.rect
.topRight());
194 QSize
FramesTableItemDelegate::sizeHint ( const QStyleOptionViewItem
& option
, const QModelIndex
& index
) const
196 Q_ASSERT(index
.isValid());
197 const QAbstractItemModel
*model
= index
.model();
200 QVariant value
= model
->data(index
, Qt::FontRole
);
201 QFont fnt
= value
.isValid() ? qvariant_cast
<QFont
>(value
) : option
.font
;
202 QString text
= model
->data(index
, Qt::DisplayRole
).toString();
204 if (model
->data(index
, Qt::DecorationRole
).isValid())
205 pixmapRect
= QRect(0, 0, option
.decorationSize
.width(),
206 option
.decorationSize
.height());
208 QFontMetrics
fontMetrics(fnt
);
210 return (pixmapRect
).size();
214 ////////// FramesTableItem ////////
216 FramesTableItem::FramesTableItem()
220 FramesTableItem::~FramesTableItem()
225 bool FramesTableItem::isUsed()
227 return data(IsUsed
).toBool();
230 bool FramesTableItem::isLocked()
232 return data(IsLocked
).toBool();
235 bool FramesTableItem::isVisible()
237 return data(IsVisible
).toBool();
240 bool FramesTableItem::isSound()
242 QVariant data
= this->data(IsSound
);
244 if( data
.canConvert
<bool>() )
246 return data
.toBool();
251 bool FramesTableItem::isClone()
253 QVariant data
= this->data(IsClone
);
255 if( data
.canConvert
<bool>() )
257 return data
.toBool();
262 FramesTableItem::InGroupPositionType
FramesTableItem::inGroupPosition()
264 QVariant data
= this->data(InGroupPosition
);
266 if( data
.canConvert
<int>() )
268 return InGroupPositionType(data
.toInt());
276 struct FramesTable::Private
280 LayerItem() : lastItem(-1), sound(false) {};
286 void swapItem( QTableWidgetItem
*it
, QTableWidgetItem
*nextIt
)
288 QVariant data
= it
->data(FramesTableItem::IsUsed
);
290 it
->setData(FramesTableItem::IsUsed
, nextIt
->data(FramesTableItem::IsUsed
).toBool() );
291 nextIt
->setData(FramesTableItem::IsUsed
, data
);
293 data
= it
->data(FramesTableItem::IsLocked
);
294 it
->setData(FramesTableItem::IsLocked
, nextIt
->data(FramesTableItem::IsLocked
).toBool());
295 nextIt
->setData(FramesTableItem::IsLocked
, data
);
298 data
= it
->data(FramesTableItem::IsVisible
);
299 it
->setData(FramesTableItem::IsVisible
, nextIt
->data(FramesTableItem::IsVisible
).toBool());
300 nextIt
->setData(FramesTableItem::IsVisible
, data
);
302 data
= it
->data(FramesTableItem::IsSound
);
303 it
->setData(FramesTableItem::IsSound
, nextIt
->data(FramesTableItem::IsSound
).toBool());
304 nextIt
->setData(FramesTableItem::IsSound
, data
);
306 data
= it
->data(FramesTableItem::InGroupPosition
);
307 it
->setData(FramesTableItem::InGroupPosition
, nextIt
->data(FramesTableItem::InGroupPosition
));
308 nextIt
->setData(FramesTableItem::InGroupPosition
, data
);
312 int groupSize(FramesTable
*table
, int layer
, int beginFrame
)
314 QTableWidgetItem
*item
= table
->item(layer
, beginFrame
);
318 dfDebug
<< "begin Frame " << beginFrame
<< " type " << item
->data(FramesTableItem::InGroupPosition
).toInt();
320 if(item
->data(FramesTableItem::InGroupPosition
).toInt() == FramesTableItem::Begin
)
322 while(item
&& item
->data(FramesTableItem::InGroupPosition
).toInt() != FramesTableItem::End
)
325 item
= table
->item(layer
, beginFrame
+count
);
332 int rectWidth
, rectHeight
;
333 QList
<LayerItem
> layers
;
340 ToggleFrameVisibility
,
346 FramesTable::FramesTable(QWidget
*parent
) : QTableWidget(0, 100, parent
), d(new Private
)
348 d
->ruler
= new TLRuler
;
352 FramesTable::~FramesTable()
357 void FramesTable::setup()
359 setItemDelegate( new FramesTableItemDelegate(this) );
361 setSelectionBehavior(QAbstractItemView::SelectItems
);
362 setSelectionMode (QAbstractItemView::SingleSelection
);
364 setHorizontalHeader(d
->ruler
);
366 connect(d
->ruler
, SIGNAL(logicalSectionSelected( int )), this, SLOT(emitFrameSelected( int )));
367 // connect(this, SIGNAL(currentItemChanged( QTableWidgetItem *, QTableWidgetItem *)), this, SLOT(emitFrameSelected(QTableWidgetItem *, QTableWidgetItem *)));
368 verticalHeader()->hide();
371 connect(this, SIGNAL(itemSelectionChanged()), this, SLOT(onItemSelectionChanged()));
373 connect( this, SIGNAL(cellDoubleClicked ( int , int )), this, SLOT(onCellDoubleClicked(int, int)));
375 setItemSize( 10, 25 );
377 horizontalHeader()->setResizeMode(QHeaderView::Custom
);
378 verticalHeader()->setResizeMode(QHeaderView::Custom
);
381 setSelectionMode(QAbstractItemView::ContiguousSelection
);
385 void FramesTable::emitFrameSelected(int col
)
389 FramesTableItem
*item
= dynamic_cast<FramesTableItem
*>(this->item(currentRow(), col
));
395 emit
frameSelected(visualRow(this->row(item
)), visualColumn(this->column(item
)));
400 void FramesTable::onItemSelectionChanged()
402 FramesTableItem
*item
= dynamic_cast<FramesTableItem
*>(currentItem());
407 emit
frameSelected(visualRow(this->row(item
)), visualColumn(this->column(item
)));
412 emit
layerSelected(visualRow(currentRow()));
416 void FramesTable::mousePressEvent ( QMouseEvent
* event
)
418 QTableWidget::mousePressEvent(event
);
421 if(event
->buttons() == Qt::RightButton
)
423 QMenu
*menu
= new QMenu(tr("Frames"), this);
425 FramesTableItem
*item
= dynamic_cast<FramesTableItem
*>(currentItem());
428 menu
->addAction( tr("Insert frame"))->setData(Private::InsertFrame
);
432 menu
->addAction( tr("Remove frame"))->setData(Private::RemoveFrame
);
433 menu
->addAction( tr("Expand this frame"))->setData(Private::ExpandFrame
);
436 menu
->addSeparator();
440 menu
->addAction( tr("Unlock this frame"))->setData(Private::ToggleLockFrame
);
444 menu
->addAction( tr("Lock this frame"))->setData(Private::ToggleLockFrame
);
447 if(item
->isVisible())
449 menu
->addAction( tr("Hide this frame"))->setData(Private::ToggleFrameVisibility
);
453 menu
->addAction( tr("Show this frame"))->setData(Private::ToggleFrameVisibility
);
457 connect(menu
, SIGNAL(triggered(QAction
*)), this, SLOT(onMenuActionTriggered(QAction
* )));
458 menu
->exec( event
->globalPos() );
463 void FramesTable::onCellDoubleClicked(int row
, int column
)
465 row
= visualRow(row
);
466 if( lastFrameByLayer(row
)+1 == column
)
468 emit
requestInsertFrame(row
, column
);
472 void FramesTable::onMenuActionTriggered(QAction
* action
)
474 int layerPos
= visualRow(currentRow());
475 int framePos
= visualColumn(currentColumn());
477 switch(action
->data().toInt())
479 case Private::InsertFrame
:
481 FramesTableItem
*item
= dynamic_cast<FramesTableItem
*>(currentItem());
486 emit
requestInsertFrame(layerPos
, framePos
+1);
491 case Private::RemoveFrame
:
493 emit
requestRemoveFrame(layerPos
, framePos
);
496 case Private::ToggleLockFrame
:
498 FramesTableItem
*item
= dynamic_cast<FramesTableItem
*>(currentItem());
501 emit
requestLockFrame(layerPos
, framePos
, !item
->isLocked());
505 case Private::ToggleFrameVisibility
:
507 FramesTableItem
*item
= dynamic_cast<FramesTableItem
*>(currentItem());
510 emit
requestChangeFrameVisibility(layerPos
, framePos
, !item
->isVisible());
514 case Private::ExpandFrame
:
516 FramesTableItem
*item
= dynamic_cast<FramesTableItem
*>(currentItem());
520 int size
= QInputDialog::getInteger ( 0, tr("Expand frame"), tr("number of frames to enlarge this frame?"), 1, 1, 2000, 1, &ok
);
525 emit
requestExpandFrame(layerPos
, framePos
, size
);
533 void FramesTable::setItemSize(int w
, int h
)
541 void FramesTable::expandFrame( int layerPosition
, int position
, int size
)
543 groupFrames( layerPosition
, position
, position
+size
);
545 for(int i
= position
; i
< position
+size
; i
++)
547 QTableWidgetItem
*item
= this->item(layerPosition
, i
);
548 item
->setData(FramesTableItem::IsClone
, true);
553 void FramesTable::groupFrames( int layerPosition
, int from
, int to
)
555 for(int i
= from
+1; i
<= to
; i
++)
557 QTableWidgetItem
*item
= this->item(layerPosition
, i
);
561 item
->setData(FramesTableItem::InGroupPosition
, QVariant( FramesTableItem::Intermediate
));
565 QTableWidgetItem
*begin
= this->item(layerPosition
, from
);
569 begin
->setData(FramesTableItem::InGroupPosition
,QVariant(FramesTableItem::Begin
));
572 QTableWidgetItem
*end
= this->item(layerPosition
, to
);
576 QTableWidgetItem
*nextEnd
= this->item(layerPosition
, to
+1);
580 if(nextEnd
->data(FramesTableItem::InGroupPosition
).toInt() != FramesTableItem::None
|| nextEnd
->data(FramesTableItem::InGroupPosition
).toInt() != FramesTableItem::Begin
)
582 end
->setData(FramesTableItem::InGroupPosition
, QVariant(FramesTableItem::Intermediate
));
583 viewport()->update();
587 end
->setData(FramesTableItem::InGroupPosition
, QVariant(FramesTableItem::End
));
590 viewport()->update();
593 void FramesTable::destroyGroupFrames(int layerPosition
, int position
, int size
)
595 for(int i
= position
; i
<= position
+size
; i
++)
597 QTableWidgetItem
*item
= this->item(layerPosition
, i
);
601 item
->setData(FramesTableItem::InGroupPosition
, QVariant( FramesTableItem::None
));
602 item
->setData(FramesTableItem::IsClone
, false);
607 bool FramesTable::isSoundLayer(int row
)
609 if( row
< 0 && row
>= d
->layers
.count() )
612 return d
->layers
[row
].sound
;
615 void FramesTable::insertLayer(int pos
, const QString
&name
)
619 Private::LayerItem layer
;
621 d
->layers
.insert(pos
, layer
);
626 void FramesTable::insertSoundLayer(int layerPos
, const QString
&name
)
630 Private::LayerItem layer
;
632 d
->layers
.insert(layerPos
, layer
);
637 void FramesTable::removeCurrentLayer()
639 int pos
= verticalHeader()->logicalIndex(currentRow());
643 void FramesTable::removeLayer(int pos
)
645 pos
= verticalHeader()->logicalIndex(pos
);
647 d
->layers
.removeAt(pos
);
650 void FramesTable::moveLayer(int position
, int newPosition
)
652 if ( position
< 0 || position
>= rowCount() || newPosition
< 0 || newPosition
>= rowCount() ) return;
656 verticalHeader()->moveSection(position
, newPosition
);
661 int FramesTable::lastFrameByLayer(int layerPos
)
663 int pos
= verticalHeader()->logicalIndex(layerPos
);
664 if ( pos
< 0 || pos
> d
->layers
.count() )
668 return d
->layers
[pos
].lastItem
;
673 void FramesTable::addFrame(int layerPos
, const QString
&name
)
675 if ( layerPos
< 0 || layerPos
>= d
->layers
.count() ) return;
677 insertFrame(layerPos
, lastFrameByLayer(verticalHeader()->logicalIndex(layerPos
))+1, name
) ;
680 void FramesTable::insertFrame(int layerPos
, int framePos
, const QString
&name
)
683 if ( layerPos
< 0 || layerPos
>= d
->layers
.count() ) return;
685 layerPos
= verticalHeader()->logicalIndex(layerPos
);
687 d
->layers
[layerPos
].lastItem
++;
689 int position
= framePos
;
691 if(!d
->layers
[layerPos
].sound
)
693 position
= d
->layers
[layerPos
].lastItem
;
696 setAttribute( layerPos
, position
, FramesTableItem::IsUsed
, true);
697 setAttribute( layerPos
, position
, FramesTableItem::IsVisible
, true);
698 setAttribute( layerPos
, position
, FramesTableItem::IsSound
, d
->layers
[layerPos
].sound
);
699 item( layerPos
, position
)->setData(FramesTableItem::InGroupPosition
, FramesTableItem::None
);
701 if(!d
->layers
[layerPos
].sound
)
703 moveFrame(layerPos
, position
, framePos
);
705 if ( d
->layers
[layerPos
].lastItem
>= columnCount()-1 )
707 setColumnCount( d
->layers
[layerPos
].lastItem
+50 );
711 viewport()->update();
714 void FramesTable::setCurrentFrame(FramesTableItem
*item
)
716 setCurrentItem(item
);
719 void FramesTable::setCurrentLayer(int layerPos
)
721 setCurrentItem(item(verticalHeader()->logicalIndex(layerPos
), 0));
724 void FramesTable::selectFrame(int index
)
726 setCurrentItem( item( currentRow(), index
) );
729 void FramesTable::removeFrame(int layerPos
, int position
)
731 if ( layerPos
< 0 || layerPos
>= d
->layers
.count() )
737 QTableWidgetItem
*it
= this->item(layerPos
, position
);
739 moveFrame(layerPos
, position
, d
->layers
[layerPos
].lastItem
);
741 QTableWidgetItem
*toRemove
= takeItem(layerPos
, d
->layers
[layerPos
].lastItem
);
743 int type
= toRemove
->data(FramesTableItem::InGroupPosition
).toInt();
745 if(type
== FramesTableItem::Begin
)
747 it
= item(layerPos
, position
);
751 if(it
->data(FramesTableItem::InGroupPosition
).toInt() == FramesTableItem::Intermediate
)
753 it
->setData(FramesTableItem::InGroupPosition
, toRemove
->data(FramesTableItem::InGroupPosition
));
755 else if(it
->data(FramesTableItem::InGroupPosition
).toInt() == FramesTableItem::End
)
757 it
->setData(FramesTableItem::InGroupPosition
, FramesTableItem::None
);
758 it
->setData(FramesTableItem::IsClone
, false);
762 else if(toRemove
->data(FramesTableItem::InGroupPosition
).toInt() == FramesTableItem::End
)
764 it
= item(layerPos
, position
);
767 if(it
->data(FramesTableItem::InGroupPosition
).toInt() == FramesTableItem::Begin
)
769 it
->setData(FramesTableItem::InGroupPosition
, FramesTableItem::None
);
778 d
->layers
[layerPos
].lastItem
--;
780 viewport()->update( visualRect(indexFromItem(item(layerPos
, position
) )) );
781 viewport()->update();
784 void FramesTable::moveFrame(int layerPos
, int from
, int to
)
791 layerPos
= verticalHeader()->logicalIndex(layerPos
);
795 int fromSize
= d
->groupSize(this, layerPos
, from
);
796 int toSize
= d
->groupSize(this, layerPos
, to
);
798 for(int i
= 0; i
< fromSize
; i
++)
800 for(int index
= from
; index
< to
+toSize
-1; index
++ )
802 QTableWidgetItem
*it
= item(layerPos
, index
);
803 QTableWidgetItem
*nextIt
= item(layerPos
, index
+1);
806 d
->swapItem(it
, nextIt
);
813 int fromSize
= d
->groupSize(this, layerPos
, from
);
814 int toSize
= d
->groupSize(this, layerPos
, to
);
816 for(int i
= 0; i
< fromSize
; i
++)
818 for(int index
= from
+i
; index
> to
+i
; index
-- )
820 QTableWidgetItem
*it
= item(layerPos
, index
);
821 QTableWidgetItem
*nextIt
= item(layerPos
, index
-1);
824 d
->swapItem(it
, nextIt
);
830 viewport()->update();
833 void FramesTable::lockFrame(int layerPos
, int position
, bool locked
)
835 if ( layerPos
< 0 || layerPos
>= d
->layers
.count() )
840 layerPos
= verticalHeader()->logicalIndex(layerPos
);
842 setAttribute( layerPos
, position
, FramesTableItem::IsLocked
, locked
);
844 viewport()->update();
847 void FramesTable::setFrameVisibility(int layerPosition
, int position
, bool isVisible
)
849 if ( layerPosition
< 0 || layerPosition
>= d
->layers
.count() )
854 layerPosition
= verticalHeader()->logicalIndex(layerPosition
);
856 setAttribute( layerPosition
, position
, FramesTableItem::IsVisible
, isVisible
);
858 viewport()->update();
862 void FramesTable::setAttribute(int row
, int col
, FramesTableItem::Attributes att
, bool value
)
864 QTableWidgetItem
*item
= this->item(row
, col
);
868 item
= new FramesTableItem
;
869 setItem(row
, col
, item
);
872 item
->setData(att
, value
);
875 void FramesTable::fixSize()
877 for(int column
= 0; column
< columnCount(); column
++)
879 horizontalHeader()->resizeSection(column
, d
->rectWidth
);
881 for( int row
= 0; row
< rowCount(); row
++)
883 verticalHeader()->resizeSection(row
, d
->rectHeight
);