1
/***************************************************************************
2
* Project TUPI: Magia 2D *
3
* Project Contact: info@maefloresta.com *
4
* Project Website: http://www.maefloresta.com *
5
* Project Leader: Gustav Gonzalez <info@maefloresta.com> *
9
* Gustavo Gonzalez / xtingray *
20
* Copyright (C) 2010 Gustav Gonzalez - http://www.maefloresta.com *
22
* This program is free software; you can redistribute it and/or modify *
23
* it under the terms of the GNU General Public License as published by *
24
* the Free Software Foundation; either version 3 of the License, or *
25
* (at your option) any later version. *
27
* This program is distributed in the hope that it will be useful, *
28
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
29
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
30
* GNU General Public License for more details. *
32
* You should have received a copy of the GNU General Public License *
33
* along with this program. If not, see <http://www.gnu.org/licenses/>. *
34
***************************************************************************/
36
#include "ktexposuretable.h"
37
#include "ktexposureheader.h"
42
#include <QItemDelegate>
44
#include <QMouseEvent>
46
#include <QHeaderView>
49
* @author Jorge Cuadrado
53
class KTExposureVerticalHeader : public QHeaderView
58
KTExposureVerticalHeader(QWidget * parent = 0);
59
~KTExposureVerticalHeader();
60
void paintSection(QPainter *painter, const QRect & rect, int logicalIndex) const;
63
KTExposureVerticalHeader::KTExposureVerticalHeader(QWidget * parent) : QHeaderView(Qt::Vertical, parent)
69
KTExposureVerticalHeader::~KTExposureVerticalHeader()
73
void KTExposureVerticalHeader::paintSection(QPainter * painter, const QRect & rect, int logicalIndex) const
75
Q_UNUSED(logicalIndex);
80
QStyleOptionHeader headerOption;
81
headerOption.rect = rect;
82
headerOption.orientation = Qt::Vertical;
83
headerOption.position = QStyleOptionHeader::Middle;
84
headerOption.text = "";
86
QStyle::State state = QStyle::State_None;
89
state |= QStyle::State_Enabled;
91
if (window()->isActiveWindow())
92
state |= QStyle::State_Active;
94
style()->drawControl(QStyle::CE_HeaderSection, &headerOption, painter);
97
text = text.setNum(logicalIndex + 1);
98
QFont font("Arial", 7, QFont::Normal, false);
99
QFontMetrics fm(font);
101
int x = rect.normalized().x() + ((rect.normalized().width() - fm.width(text))/2);
102
int y = rect.normalized().bottomLeft().y() - (1 + (rect.normalized().height() - fm.height())/2);
104
painter->setFont(font);
105
painter->setPen(QPen(Qt::black, 1, Qt::SolidLine));
106
painter->drawText(x, y, text);
111
class KTExposureItemDelegate : public QItemDelegate
114
KTExposureItemDelegate(QObject * parent = 0);
115
~KTExposureItemDelegate();
116
virtual void paint(QPainter * painter, const QStyleOptionViewItem & option, const QModelIndex & index) const;
119
KTExposureItemDelegate::KTExposureItemDelegate(QObject * parent) : QItemDelegate(parent)
123
KTExposureItemDelegate::~KTExposureItemDelegate()
127
void KTExposureItemDelegate::paint(QPainter *painter, const QStyleOptionViewItem & option, const QModelIndex & index) const
129
QItemDelegate::paint(painter, option, index);
131
KTExposureTable *table = qobject_cast<KTExposureTable *>(index.model()->parent());
133
QTableWidgetItem *item = table->itemFromIndex(index);
138
if (item->data(KTExposureTable::IsLocked).toBool()) {
139
QPixmap pixmap(THEME_DIR + "icons/padlock.png");
140
painter->drawPixmap(1, 5, pixmap);
144
int x = option.rect.topLeft().x() + 2;
145
int y = option.rect.topLeft().y() + 2;
146
int w = option.rect.bottomRight().x() - x - 2;
147
int h = option.rect.bottomRight().y() - y - 2;
149
if (item->data(KTExposureTable::IsLocked).toBool()) {
150
painter->setPen(QColor(255, 255, 255, 200));
151
painter->drawRect(x, y, w, h);
154
if ((item->data(KTExposureTable::IsEmpty).toInt() == KTExposureTable::Empty) && !item->data(KTExposureTable::IsLocked).toBool()) {
155
QPen pen(QColor(100, 100, 100, 30));
156
pen.setStyle(Qt::DashLine);
157
painter->setPen(pen);
158
painter->drawRect(x, y, w, h);
161
if ((item->data(KTExposureTable::IsEmpty).toInt() == KTExposureTable::Used) && !item->data(KTExposureTable::IsLocked).toBool()) {
162
painter->setPen(QColor(0, 0, 0, 60));
163
painter->drawRect(x, y, w, h);
168
////////////////////////
170
struct KTExposureTable::Private
172
KTExposureHeader *header;
178
KTExposureTable::KTExposureTable(QWidget * parent) : QTableWidget(parent), k(new Private)
180
KTExposureVerticalHeader *verticalHeader = new KTExposureVerticalHeader(this);
181
setVerticalHeader(verticalHeader);
183
setItemDelegate(new KTExposureItemDelegate(this));
184
k->removingLayer = false;
185
k->removingFrame = false;
187
QTableWidgetItem *prototype = new QTableWidgetItem();
188
prototype->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEditable);
189
prototype->setTextAlignment(Qt::AlignCenter);
190
prototype->setData(IsEmpty, Unset);
192
setItemPrototype(prototype);
196
for (int i=0; i < 100; i++)
199
k->header = new KTExposureHeader(this);
201
connect(k->header, SIGNAL(visibilityChanged(int, bool)), this, SIGNAL(requestChangeVisibilityLayer(int, bool)));
202
connect(k->header, SIGNAL(changedName(int, const QString &)), this, SIGNAL(requestRenameLayer(int,
204
connect(k->header, SIGNAL(sectionMoved(int, int, int)), this, SLOT(emitRequestMoveLayer(int, int, int)));
205
connect(k->header, SIGNAL(selectionChanged(int)), this, SLOT(updateLayerSelection(int)));
207
setHorizontalHeader(k->header);
209
connect(this, SIGNAL(cellClicked(int, int)), this, SLOT(emitRequestSetUsedFrame(int, int)));
210
connect(this, SIGNAL(currentCellChanged(int, int, int, int)), this, SLOT(emitRequestSelectFrame(int, int, int, int)));
212
setSelectionBehavior(QAbstractItemView::SelectItems);
213
setSelectionMode(QAbstractItemView::SingleSelection);
218
void KTExposureTable::emitRequestRenameFrame(QTableWidgetItem * item)
220
QModelIndex index = indexFromItem(item);
221
emit requestRenameFrame(index.column(), index.row(), item->text());
224
void KTExposureTable::emitRequestSelectFrame(int currentSelectedRow, int currentColumn, int previousRow, int previousColumn)
230
if (!k->removingLayer) {
232
if (k->removingFrame) {
233
k->removingFrame = false;
234
if ((previousColumn != currentColumn) || (columnCount() == 1))
235
k->header->updateSelection(currentColumn);
239
if (previousRow != currentSelectedRow || previousColumn != currentColumn)
240
emit requestSelectFrame(currentLayer(), currentRow());
242
if ((previousColumn != currentColumn) || (columnCount() == 1))
243
k->header->updateSelection(currentColumn);
245
} else { // A layer is being removed
246
k->removingLayer = false;
247
selectFrame(currentColumn, currentSelectedRow);
249
if (previousColumn == 0)
250
k->header->updateSelection(0);
252
k->header->updateSelection(currentColumn);
256
void KTExposureTable::emitRequestMoveLayer(int logicalIndex, int oldVisualIndex, int newVisualIndex)
258
Q_UNUSED(logicalIndex);
260
if (! k->header->signalMovedBlocked()) {
261
k->header->moveLayer(newVisualIndex, oldVisualIndex);
262
emit requestMoveLayer(oldVisualIndex, newVisualIndex);
266
void KTExposureTable::updateLayerSelection(int layerIndex)
268
selectFrame(layerIndex, currentRow());
271
KTExposureTable::~KTExposureTable()
276
QString KTExposureTable::frameName(int indexLayer, int indexFrame)
278
QTableWidgetItem *frame = item(indexFrame , indexLayer);
280
return frame->text();
285
void KTExposureTable::setFrameName(int indexLayer, int indexFrame, const QString & name)
287
QTableWidgetItem *frame = item(indexFrame , indexLayer);
288
frame->setFont(QFont("Arial", 7, QFont::Normal, false));
291
if (frame->text() != name)
292
frame->setText(name);
296
void KTExposureTable::setLayerName(int indexLayer, const QString & name)
298
k->header->setLayerName(k->header->logicalIndex(indexLayer), name);
301
bool KTExposureTable::frameIsLocked(int indexLayer, int indexFrame)
303
QTableWidgetItem *frame = item(indexFrame, indexLayer);
305
return frame->data(IsLocked).toBool();
308
tWarning() << "KTExposureTable::frameIsLocked() - Layer: " << indexLayer << ", Frame: " << indexFrame << " doesn't exist";
314
KTExposureTable::FrameType KTExposureTable::frameState(int indexLayer, int indexFrame)
316
KTExposureTable::FrameType type = KTExposureTable::Unset;
317
QTableWidgetItem *frame = item(indexFrame, indexLayer);
319
type = KTExposureTable::FrameType(frame->data(KTExposureTable::IsEmpty).toInt());
324
void KTExposureTable::updateFrameState(int indexLayer, int indexFrame, KTExposureTable::FrameType value)
326
QTableWidgetItem *frame = item(indexFrame, indexLayer);
327
frame->setData(IsEmpty, value);
329
if (value == KTExposureTable::Used)
330
frame->setBackgroundColor(QColor(0xf0f0f0));
333
void KTExposureTable::selectFrame(int indexLayer, int indexFrame)
335
setCurrentCell(indexFrame, k->header->logicalIndex(indexLayer));
338
void KTExposureTable::setMenu(QMenu *menu)
343
int KTExposureTable::currentLayer() const
345
return k->header->visualIndex(currentColumn());
348
int KTExposureTable::currentFrame() const
354
QTableWidgetItem *frame = currentItem();
356
/* SQA: Old code. Remove it!
358
if (frame->data(IsEmpty).toBool()) {
361
return currentRow()-1; //???
367
if (frame->data(KTExposureTable::IsEmpty).toInt() != Unset)
374
void KTExposureTable::insertLayer(int index, const QString & name)
377
setColumnWidth(index, 70);
378
k->header->insertLayer(index, name);
381
void KTExposureTable::insertFrame(int indexLayer, int indexFrame, const QString & name, bool external)
383
QTableWidgetItem *frame = new QTableWidgetItem;
384
frame->setBackgroundColor(QColor(0xe6e6e6));
385
frame->setFont(QFont("Arial", 7, QFont::Normal, false));
386
frame->setSizeHint(QSize(65, 10));
387
frame->setText(name);
388
frame->setData(IsEmpty, Empty);
389
frame->setTextAlignment(Qt::AlignCenter);
391
int logicalIndex = k->header->logicalIndex(indexLayer);
393
k->header->setLastFrame(logicalIndex, k->header->lastFrame(logicalIndex) + 1);
395
setItem(k->header->lastFrame(logicalIndex)-1, logicalIndex, frame);
397
for (int i = k->header->lastFrame(logicalIndex)-1; i > indexFrame; i--)
398
exchangeFrame(indexLayer, i , indexLayer, i-1, external);
400
if (k->header->lastFrame(logicalIndex) == rowCount()) {
401
setRowCount(k->header->lastFrame(logicalIndex) + 100);
402
int last = k->header->lastFrame(logicalIndex);
403
for (int i=last; i < last + 100; i++)
408
void KTExposureTable::setLockFrame(int indexLayer, int indexFrame, bool locked)
410
int logicalIndex = k->header->logicalIndex(indexLayer);
411
QTableWidgetItem * frame = item(indexFrame, logicalIndex);
414
if (frame->data(KTExposureTable::IsEmpty).toInt() != Unset) {
416
frame->setBackgroundColor(QColor(250, 71, 53));
418
frame->setBackgroundColor(QColor(0xe6e6e6));
420
frame->setData(IsLocked, locked);
425
void KTExposureTable::setLockLayer(int indexLayer, bool locked)
427
k->header->setLockLayer(indexLayer, locked);
430
void KTExposureTable::setVisibilityChanged(int visualIndex, bool visibility)
432
k->header->setVisibilityChanged(k->header->logicalIndex(visualIndex), visibility);
435
void KTExposureTable::removeLayer(int indexLayer)
437
setUpdatesEnabled(false);
438
k->removingLayer = true;
440
k->header->removeLayer(indexLayer);
441
removeColumn(indexLayer);
443
setUpdatesEnabled(true);
446
void KTExposureTable::removeFrame(int indexLayer, int indexFrame, bool fromMenu)
448
//setUpdatesEnabled(false);
449
k->removingFrame = fromMenu;
451
QTableWidgetItem *item = takeItem(indexFrame, indexLayer);
453
for (int index = indexFrame + 1; index < k->header->lastFrame(indexLayer); index++) {
454
QTableWidgetItem * idx = takeItem(index, indexLayer);
456
setItem(index - 1, indexLayer, idx);
458
k->header->setLastFrame(indexLayer, k->header->lastFrame(indexLayer)-1);
461
//setUpdatesEnabled(true);
464
void KTExposureTable::exchangeFrame(int oldPosLayer, int oldPosFrame, int newPosLayer, int newPosFrame, bool external)
466
QTableWidgetItem * oldItem = takeItem(oldPosFrame, oldPosLayer);
467
QTableWidgetItem * newItem = takeItem(newPosFrame, newPosLayer);
469
setItem(newPosFrame, newPosLayer, oldItem);
470
setItem(oldPosFrame, oldPosLayer, newItem);
473
setCurrentItem(oldItem);
476
void KTExposureTable::moveLayer(int oldPosLayer, int newPosLayer)
478
k->header->moveLayer(oldPosLayer, newPosLayer);
481
void KTExposureTable::emitRequestSetUsedFrame(int indexFrame, int indexLayer)
487
int layer = k->header->visualIndex(indexLayer);
488
int lastFrame = k->header->lastFrame(indexLayer);
490
if (indexFrame >= lastFrame) {
491
for (int column=0; column<columnCount(); column++) {
492
int used = usedFrames(column);
493
if (lastFrame >= used) {
494
for (int frame=used; frame <= indexFrame; frame++)
495
emit requestSetUsedFrame(column, frame);
499
emit requestSelectFrame(layer, indexFrame);
503
int KTExposureTable::usedFrames(int column) const
505
return k->header->lastFrame(column);
508
bool KTExposureTable::edit(const QModelIndex & index, EditTrigger trigger, QEvent *event)
510
QTableWidgetItem *item = itemFromIndex(index);
513
if (item->data(KTExposureTable::IsEmpty).toInt() != Unset)
514
QTableWidget::edit(index, trigger, event);
522
void KTExposureTable::mousePressEvent(QMouseEvent * event)
524
int frame = rowAt(event->y());
525
if (event->button() == Qt::RightButton) {
526
if (k->header->lastFrame(currentLayer()) >= frame) {
529
k->menu->exec(event->globalPos());
536
QTableWidget::mousePressEvent(event);
539
void KTExposureTable::commitData(QWidget *editor)
541
QLineEdit *lineEdit = qobject_cast<QLineEdit *>(editor);
542
QTableWidget::commitData(0); // Don't rename
545
emit requestRenameFrame(currentLayer(), currentFrame(), lineEdit->text());
548
int KTExposureTable::layersTotal()
550
return k->header->layersTotal();
553
int KTExposureTable::framesTotal()
555
return k->header->lastFrame(0);
558
int KTExposureTable::framesTotalAtCurrentLayer()
560
return k->header->lastFrame(currentLayer());
563
void KTExposureTable::keyPressEvent(QKeyEvent * event)
565
if (event->key() == Qt::Key_Up) {
566
int row = currentRow()-1;
568
setCurrentCell(row, currentColumn());
572
if (event->key() == Qt::Key_Down) {
573
int limit = rowCount()-1;
574
int next = currentRow()+1;
576
setCurrentCell(next, currentColumn());
580
if (event->key() == Qt::Key_Right) {
581
int limit = columnCount()-1;
582
int next = currentColumn()+1;
584
setCurrentCell(currentRow(), next);
588
if (event->key() == Qt::Key_Left) {
589
int column = currentColumn()-1;
591
setCurrentCell(currentRow(), column);
595
if (event->key() == Qt::Key_Return) {
596
emitRequestSetUsedFrame(currentRow(), currentColumn());
601
void KTExposureTable::emitCellClicked(int frame, int layer)
603
emit cellClicked(frame, layer);
606
void KTExposureTable::enterEvent(QEvent *event)
611
QTableWidget::enterEvent(event);
614
void KTExposureTable::leaveEvent(QEvent *event)
619
QTableWidget::leaveEvent(event);
622
void KTExposureTable::reset()
624
int cols = columnCount();
626
for (int i=1; i < cols; i++)
630
int rows = rowCount();
631
for (int i=1; i < rows; i++) {
632
QTableWidgetItem *item = takeItem(i, 0);
635
k->header->setLastFrame(0, 1);