#include "boardsettingspopup.h"
// Tnz6 includes
#include "tapp.h"
#include "filebrowser.h"
// TnzQt includes
#include "toonzqt/gutil.h"
#include "toonzqt/filefield.h"
#include "toonzqt/colorfield.h"
#include "toonzqt/intfield.h"
// TnzLib includes
#include "toutputproperties.h"
#include "toonz/tscenehandle.h"
#include "toonz/toonzscene.h"
#include "toonz/sceneproperties.h"
#include "toonz/tcamera.h"
#include "toonz/boardsettings.h"
#include "toonz/toonzfolders.h"
// TnzBase includes
#include "trasterfx.h"
// TnzCore includes
#include "tsystem.h"
#include "tlevel_io.h"
#include <QLineEdit>
#include <QLabel>
#include <QPushButton>
#include <QTextEdit>
#include <QComboBox>
#include <QFontComboBox>
#include <QHBoxLayout>
#include <QVBoxLayout>
#include <QGridLayout>
#include <QPainter>
#include <QRectF>
#include <QListWidget>
#include <QMap>
#include <QPixmap>
#include <QImageReader>
#include <QMouseEvent>
BoardItem* BoardSettingsPopup::currentBoardItem = nullptr;
namespace {
QMap<BoardItem::Type, QString> stringByItemType;
BoardItem* currentBoardItem() { return BoardSettingsPopup::currentBoardItem; }
void setCurrentBoardItem(BoardItem* item) {
BoardSettingsPopup::currentBoardItem = item;
}
void editListWidgetItem(QListWidgetItem* listItem, BoardItem* item) {
QString itemText = item->getName() + "\n(" +
stringByItemType.value(item->getType(), "Unknown type") +
")";
listItem->setText(itemText);
if (item->getType() == BoardItem::Image) {
ToonzScene* scene = TApp::instance()->getCurrentScene()->getScene();
TFilePath decodedImgPath = scene->decodeFilePath(item->getImgPath());
QPixmap iconPm = QPixmap::fromImage(
QImage(decodedImgPath.getQString()).scaled(QSize(20, 20)));
listItem->setIcon(QIcon(iconPm));
} else {
QPixmap iconPm(20, 20);
iconPm.fill(item->getColor());
listItem->setIcon(QIcon(iconPm));
}
}
} // namespace
//=============================================================================
BoardView::BoardView(QWidget* parent) : QWidget(parent) {
setMouseTracking(true);
}
void BoardView::paintEvent(QPaintEvent* event) {
ToonzScene* scene = TApp::instance()->getCurrentScene()->getScene();
if (!scene) return;
TOutputProperties* outProp = scene->getProperties()->getOutputProperties();
BoardSettings* boardSettings = outProp->getBoardSettings();
QPainter p(this);
p.fillRect(rect(), Qt::black);
// Duration must be more than 0 to save the clapperboard.
// Scene file can maintain compatibility with older versions if you set the
// duration to 0.
if (boardSettings->getDuration() == 0) {
p.setPen(Qt::white);
QFont font = p.font();
font.setPixelSize(30);
p.setFont(font);
p.drawText(
rect().adjusted(5, 5, -5, -5), Qt::AlignCenter | Qt::TextWordWrap,
tr("Please set the duration more than 0 frame first, or the "
"clapperboard settings will not be saved in the scene at all!"));
p.setPen(QPen(Qt::red, 2));
p.drawLine(5, 5, 150, 5);
p.drawLine(5, 10, 150, 10);
return;
}
if (!m_valid) {
int shrinkX = outProp->getRenderSettings().m_shrinkX,
shrinkY = outProp->getRenderSettings().m_shrinkY;
TDimension frameSize = scene->getCurrentCamera()->getRes();
TDimension cameraRes(frameSize.lx / shrinkX, frameSize.ly / shrinkY);
m_boardImg = boardSettings->getBoardImage(cameraRes, shrinkX, scene);
m_valid = true;
}
p.drawImage(m_boardImgRect, m_boardImg);
p.translate(m_boardImgRect.topLeft());
p.setBrush(Qt::NoBrush);
for (int i = 0; i < boardSettings->getItemCount(); i++) {
BoardItem* item = &(boardSettings->getItem(i));
if (item == currentBoardItem()) {
p.setPen(QPen(QColor(255, 100, 0), 2));
} else {
p.setPen(QPen(QColor(64, 64, 255), 1, Qt::DashLine));
}
p.drawRect(item->getItemRect(m_boardImgRect.size().toSize()));
}
}
void BoardView::resizeEvent(QResizeEvent* event) {
QSize boardRes;
if (m_valid) {
boardRes = m_boardImg.size();
} else {
ToonzScene* scene = TApp::instance()->getCurrentScene()->getScene();
TOutputProperties* outProp = scene->getProperties()->getOutputProperties();
int shrinkX = outProp->getRenderSettings().m_shrinkX,
shrinkY = outProp->getRenderSettings().m_shrinkY;
TDimension frameSize = scene->getCurrentCamera()->getRes();
boardRes = QSize(frameSize.lx / shrinkX, frameSize.ly / shrinkY);
}
float ratio = std::min((float)width() / (float)boardRes.width(),
(float)height() / (float)boardRes.height());
QSizeF imgSize = QSizeF(boardRes) * ratio;
QPointF imgTopLeft(((float)width() - imgSize.width()) * 0.5,
((float)height() - imgSize.height()) * 0.5);
m_boardImgRect = QRectF(imgTopLeft, imgSize);
}
void BoardView::mouseMoveEvent(QMouseEvent* event) {
// mouse move - change drag item
if (!(event->buttons() & Qt::LeftButton)) {
if (!currentBoardItem()) {
m_dragItem = None;
setCursor(Qt::ArrowCursor);
return;
}
QPointF posOnImg = QPointF(event->pos()) - m_boardImgRect.topLeft();
QRectF itemRect =
currentBoardItem()->getItemRect(m_boardImgRect.size().toSize());
qreal distance = 10.0;
if ((itemRect.topLeft() - posOnImg).manhattanLength() < distance) {
m_dragItem = TopLeftCorner;
setCursor(Qt::SizeFDiagCursor);
} else if ((itemRect.topRight() - posOnImg).manhattanLength() < distance) {
m_dragItem = TopRightCorner;
setCursor(Qt::SizeBDiagCursor);
} else if ((itemRect.bottomRight() - posOnImg).manhattanLength() <
distance) {
m_dragItem = BottomRightCorner;
setCursor(Qt::SizeFDiagCursor);
} else if ((itemRect.bottomLeft() - posOnImg).manhattanLength() <
distance) {
m_dragItem = BottomLeftCorner;
setCursor(Qt::SizeBDiagCursor);
} else if (std::abs(itemRect.top() - posOnImg.y()) < distance &&
itemRect.left() < posOnImg.x() &&
itemRect.right() > posOnImg.x()) {
m_dragItem = TopEdge;
setCursor(Qt::SizeVerCursor);
} else if (std::abs(itemRect.right() - posOnImg.x()) < distance &&
itemRect.top() < posOnImg.y() &&
itemRect.bottom() > posOnImg.y()) {
m_dragItem = RightEdge;
setCursor(Qt::SizeHorCursor);
} else if (std::abs(itemRect.bottom() - posOnImg.y()) < distance &&
itemRect.left() < posOnImg.x() &&
itemRect.right() > posOnImg.x()) {
m_dragItem = BottomEdge;
setCursor(Qt::SizeVerCursor);
} else if (std::abs(itemRect.left() - posOnImg.x()) < distance &&
itemRect.top() < posOnImg.y() &&
itemRect.bottom() > posOnImg.y()) {
m_dragItem = LeftEdge;
setCursor(Qt::SizeHorCursor);
} else if (itemRect.contains(posOnImg)) {
m_dragItem = Translate;
setCursor(Qt::SizeAllCursor);
} else {
m_dragItem = None;
setCursor(Qt::ArrowCursor);
}
return;
}
// left mouse drag
if (m_dragItem == None) return;
if (m_dragStartItemRect.isNull()) return;
QPointF posOnImg = QPointF(event->pos()) - m_boardImgRect.topLeft();
QPointF ratioPos = QPointF(posOnImg.x() / m_boardImgRect.width(),
posOnImg.y() / m_boardImgRect.height());
// with alt : center resize
bool altPressed = event->modifiers() & Qt::AltModifier;
// with shift : align to discrete position
bool shiftPressed = event->modifiers() & Qt::ShiftModifier;
auto adjVal = [&](double p) {
double step = 0.05;
if (!shiftPressed) return p;
return std::round(p / step) * step;
};
auto adjPos = [&](QPointF p) {
if (!shiftPressed) return p;
return QPointF(adjVal(p.x()), adjVal(p.y()));
};
QRectF newRect = m_dragStartItemRect;
QPointF d = ratioPos - m_dragStartPos;
switch (m_dragItem) {
case Translate:
newRect.translate(ratioPos - m_dragStartPos);
if (shiftPressed) {
newRect.setTopLeft(adjPos(newRect.topLeft()));
newRect.setBottomRight(adjPos(newRect.bottomRight()));
}
break;
case TopLeftCorner:
newRect.setTopLeft(adjPos(newRect.topLeft() + d));
if (altPressed) newRect.setBottomRight(adjPos(newRect.bottomRight() - d));
break;
case TopRightCorner:
newRect.setTopRight(adjPos(newRect.topRight() + d));
if (altPressed) newRect.setBottomLeft(adjPos(newRect.bottomLeft() - d));
break;
case BottomRightCorner:
newRect.setBottomRight(adjPos(newRect.bottomRight() + d));
if (altPressed) newRect.setTopLeft(adjPos(newRect.topLeft() - d));
break;
case BottomLeftCorner:
newRect.setBottomLeft(adjPos(newRect.bottomLeft() + d));
if (altPressed) newRect.setTopRight(adjPos(newRect.topRight() - d));
break;
case TopEdge:
newRect.setTop(adjVal(newRect.top() + d.y()));
if (altPressed) newRect.setBottom(adjVal(newRect.bottom() - d.y()));
break;
case RightEdge:
newRect.setRight(adjVal(newRect.right() + d.x()));
if (altPressed) newRect.setLeft(adjVal(newRect.left() - d.x()));
break;
case BottomEdge:
newRect.setBottom(adjVal(newRect.bottom() + d.y()));
if (altPressed) newRect.setTop(adjVal(newRect.top() - d.y()));
break;
case LeftEdge:
newRect.setLeft(adjVal(newRect.left() + d.x()));
if (altPressed) newRect.setRight(adjVal(newRect.right() - d.x()));
break;
default:
break;
}
currentBoardItem()->setRatioRect(newRect.normalized());
invalidate();
update();
}
void BoardView::mousePressEvent(QMouseEvent* event) {
// only the left button counts
if (event->button() != Qt::LeftButton) return;
// store the current item rect and mouse pos, relative to the image size
m_dragStartItemRect = currentBoardItem()->getRatioRect();
QPointF posOnImg = QPointF(event->pos()) - m_boardImgRect.topLeft();
m_dragStartPos = QPointF(posOnImg.x() / m_boardImgRect.width(),
posOnImg.y() / m_boardImgRect.height());
}
void BoardView::mouseReleaseEvent(QMouseEvent* event) {
m_dragStartItemRect = QRectF();
m_dragStartPos = QPointF();
}
//=============================================================================
ItemInfoView::ItemInfoView(QWidget* parent) : QStackedWidget(parent) {
m_nameEdit = new QLineEdit(this);
m_maxFontSizeEdit = new DVGui::IntLineEdit(this, 1, 1);
m_typeCombo = new QComboBox(this);
m_textEdit = new QTextEdit(this);
m_imgPathField = new DVGui::FileField(this);
m_fontCombo = new QFontComboBox(this);
m_boldButton = new QPushButton(createQIcon("bold"), tr("Bold"), this);
m_italicButton = new QPushButton(createQIcon("italic"), tr("Italic"), this);
m_fontColorField =
new DVGui::ColorField(this, true, TPixel32(0, 0, 0, 255), 25, false, 54);
m_imgARModeCombo = new QComboBox(this);
m_fontPropBox = new QWidget(this);
m_imgPropBox = new QWidget(this);
for (int i = 0; i < BoardItem::TypeCount; i++) {
m_typeCombo->addItem(stringByItemType[(BoardItem::Type)i]);
}
m_textEdit->setAcceptRichText(false);
m_textEdit->setStyleSheet(
"background:white;\ncolor:black;\nborder:1 solid black;");
m_boldButton->setIconSize(QSize(16, 16));
m_boldButton->setFixedHeight(25);
m_boldButton->setCheckable(true);
m_italicButton->setIconSize(QSize(16, 16));
m_italicButton->setFixedHeight(25);
m_italicButton->setCheckable(true);
QStringList filters;
for (QByteArray& format : QImageReader::supportedImageFormats())
filters += format;
m_imgPathField->setFilters(filters);
m_imgPathField->setFileMode(QFileDialog::ExistingFile);
m_imgARModeCombo->addItem(tr("Ignore"), Qt::IgnoreAspectRatio);
m_imgARModeCombo->addItem(tr("Keep"), Qt::KeepAspectRatio);
//----- layout
QGridLayout* mainLay = new QGridLayout();
mainLay->setMargin(5);
mainLay->setHorizontalSpacing(3);
mainLay->setVerticalSpacing(10);
{
mainLay->addWidget(new QLabel(tr("Name:"), this), 0, 0,
Qt::AlignRight | Qt::AlignVCenter);
mainLay->addWidget(m_nameEdit, 0, 1);
mainLay->addWidget(new QLabel(tr("Type:"), this), 1, 0,
Qt::AlignRight | Qt::AlignVCenter);
mainLay->addWidget(m_typeCombo, 1, 1);
QVBoxLayout* extraInfoLay = new QVBoxLayout();
extraInfoLay->setMargin(0);
extraInfoLay->setSpacing(0);
{
extraInfoLay->addWidget(m_textEdit, 1);
QGridLayout* imgPropLay = new QGridLayout();
imgPropLay->setMargin(0);
imgPropLay->setHorizontalSpacing(3);
imgPropLay->setVerticalSpacing(10);
{
imgPropLay->addWidget(new QLabel(tr("Path:"), this), 0, 0,
Qt::AlignRight | Qt::AlignVCenter);
imgPropLay->addWidget(m_imgPathField, 0, 1, 1, 2);
imgPropLay->addWidget(new QLabel(tr("Aspect Ratio:"), this), 1, 0,
Qt::AlignRight | Qt::AlignVCenter);
imgPropLay->addWidget(m_imgARModeCombo, 1, 1);
}
imgPropLay->setColumnStretch(0, 0);
imgPropLay->setColumnStretch(1, 0);
imgPropLay->setColumnStretch(2, 1);
m_imgPropBox->setLayout(imgPropLay);
extraInfoLay->addWidget(m_imgPropBox, 0);
extraInfoLay->addSpacing(5);
QGridLayout* fontPropLay = new QGridLayout();
fontPropLay->setMargin(0);
fontPropLay->setHorizontalSpacing(3);
fontPropLay->setVerticalSpacing(10);
{
fontPropLay->addWidget(new QLabel(tr("Font:"), this), 0, 0,
Qt::AlignRight | Qt::AlignVCenter);
fontPropLay->addWidget(m_fontCombo, 0, 1, 1, 4);
fontPropLay->addWidget(new QLabel(tr("Max Size:"), this), 1, 0,
Qt::AlignRight | Qt::AlignVCenter);
fontPropLay->addWidget(m_maxFontSizeEdit, 1, 1);
fontPropLay->addWidget(m_boldButton, 1, 2);
fontPropLay->addWidget(m_italicButton, 1, 3);
fontPropLay->addWidget(m_fontColorField, 2, 0, 1, 5);
}
fontPropLay->setColumnStretch(0, 0);
fontPropLay->setColumnStretch(1, 0);
fontPropLay->setColumnStretch(2, 0);
fontPropLay->setColumnStretch(3, 0);
fontPropLay->setColumnStretch(4, 1);
m_fontPropBox->setLayout(fontPropLay);
extraInfoLay->addWidget(m_fontPropBox, 0);
}
mainLay->addLayout(extraInfoLay, 2, 0, 1, 2);
}
mainLay->setColumnStretch(0, 0);
mainLay->setColumnStretch(1, 1);
mainLay->setRowStretch(0, 0);
mainLay->setRowStretch(1, 0);
mainLay->setRowStretch(2, 1);
QWidget* mainWidget = new QWidget(this);
mainWidget->setLayout(mainLay);
addWidget(mainWidget);
addWidget(new QLabel(tr("No item selected."), this));
bool ret = true;
ret = ret && connect(m_nameEdit, SIGNAL(editingFinished()), this,
SLOT(onNameEdited()));
ret = ret && connect(m_maxFontSizeEdit, SIGNAL(editingFinished()), this,
SLOT(onMaxFontSizeEdited()));
ret = ret && connect(m_typeCombo, SIGNAL(activated(int)), this,
SLOT(onTypeComboActivated(int)));
ret = ret && connect(m_textEdit, SIGNAL(textChanged()), this,
SLOT(onFreeTextChanged()));
ret = ret && connect(m_imgPathField, SIGNAL(pathChanged()), this,
SLOT(onImgPathChanged()));
ret = ret && connect(m_fontCombo, SIGNAL(currentFontChanged(const QFont&)),
this, SLOT(onFontComboChanged(const QFont&)));
ret = ret && connect(m_boldButton, SIGNAL(clicked(bool)), this,
SLOT(onBoldButtonClicked(bool)));
ret = ret && connect(m_italicButton, SIGNAL(clicked(bool)), this,
SLOT(onItalicButtonClicked(bool)));
ret = ret &&
connect(m_fontColorField, SIGNAL(colorChanged(const TPixel32&, bool)),
this, SLOT(onFontColorChanged(const TPixel32&, bool)));
ret = ret && connect(m_imgARModeCombo, SIGNAL(activated(int)), this,
SLOT(onImgARModeComboActivated()));
assert(ret);
}
// called on switching the current item
void ItemInfoView::setCurrentItem(int index) {
if (index == -1) {
if (!currentBoardItem()) return;
setCurrentBoardItem(nullptr);
setCurrentIndex(1); // set to "no item seleceted" page.
return;
}
setCurrentIndex(0); // set to normal page.
ToonzScene* scene = TApp::instance()->getCurrentScene()->getScene();
if (!scene) return;
TOutputProperties* outProp = scene->getProperties()->getOutputProperties();
BoardSettings* boardSettings = outProp->getBoardSettings();
if (index >= boardSettings->getItemCount()) return;
BoardItem* newItem = &(boardSettings->getItem(index));
if (currentBoardItem() == newItem) return;
setCurrentBoardItem(newItem);
// sync
m_nameEdit->setText(newItem->getName());
m_maxFontSizeEdit->setValue(newItem->getMaximumFontSize());
m_typeCombo->setCurrentIndex((int)newItem->getType());
m_textEdit->setText(newItem->getFreeText());
m_imgPathField->setPath(newItem->getImgPath().getQString());
m_fontCombo->setCurrentFont(newItem->font());
m_boldButton->setChecked(newItem->font().bold());
m_italicButton->setChecked(newItem->font().italic());
QColor col = newItem->getColor();
m_fontColorField->setColor(
TPixel32(col.red(), col.green(), col.blue(), col.alpha()));
int ARModeIndex = m_imgARModeCombo->findData(newItem->getImgARMode());
if (ARModeIndex >= 0) m_imgARModeCombo->setCurrentIndex(ARModeIndex);
switch (newItem->getType()) {
case BoardItem::FreeText:
m_textEdit->show();
m_imgPropBox->hide();
m_fontPropBox->show();
break;
case BoardItem::Image:
m_textEdit->hide();
m_imgPropBox->show();
m_fontPropBox->hide();
break;
default:
m_textEdit->hide();
m_imgPropBox->hide();
m_fontPropBox->show();
break;
}
}
void ItemInfoView::onNameEdited() {
assert(currentBoardItem());
QString newName = m_nameEdit->text();
if (newName.isEmpty()) {
newName = tr("Item");
m_nameEdit->setText(newName);
}
if (currentBoardItem()->getName() == newName) return;
currentBoardItem()->setName(newName);
emit itemPropertyChanged(true);
}
void ItemInfoView::onMaxFontSizeEdited() {
assert(currentBoardItem());
int maxFontSize = m_maxFontSizeEdit->getValue();
if (currentBoardItem()->getMaximumFontSize() == maxFontSize) return;
currentBoardItem()->setMaximumFontSize(maxFontSize);
emit itemPropertyChanged(false);
}
void ItemInfoView::onTypeComboActivated(int) {
assert(currentBoardItem());
BoardItem::Type newType = (BoardItem::Type)m_typeCombo->currentIndex();
if (currentBoardItem()->getType() == newType) return;
currentBoardItem()->setType(newType);
switch (newType) {
case BoardItem::FreeText:
m_textEdit->show();
m_imgPropBox->hide();
m_fontPropBox->show();
break;
case BoardItem::Image:
m_textEdit->hide();
m_imgPropBox->show();
m_fontPropBox->hide();
break;
default:
m_textEdit->hide();
m_imgPropBox->hide();
m_fontPropBox->show();
break;
}
emit itemPropertyChanged(true);
}
void ItemInfoView::onFreeTextChanged() {
assert(currentBoardItem());
currentBoardItem()->setFreeText(m_textEdit->toPlainText());
emit itemPropertyChanged(false);
}
void ItemInfoView::onImgPathChanged() {
assert(currentBoardItem());
TFilePath fp(m_imgPathField->getPath());
if (fp.isLevelName()) {
ToonzScene* scene = TApp::instance()->getCurrentScene()->getScene();
TLevelReaderP lr(scene->decodeFilePath(fp));
TLevelP level;
if (lr) level = lr->loadInfo();
if (level.getPointer() && level->getTable()->size() > 0) {
TFrameId firstFrame = level->begin()->first;
fp = fp.withFrame(firstFrame);
m_imgPathField->setPath(fp.getQString());
}
}
currentBoardItem()->setImgPath(fp);
emit itemPropertyChanged(true);
}
void ItemInfoView::onFontComboChanged(const QFont& newFont) {
assert(currentBoardItem());
currentBoardItem()->font().setFamily(newFont.family());
emit itemPropertyChanged(false);
}
void ItemInfoView::onBoldButtonClicked(bool on) {
assert(currentBoardItem());
currentBoardItem()->font().setBold(on);
emit itemPropertyChanged(false);
}
void ItemInfoView::onItalicButtonClicked(bool on) {
assert(currentBoardItem());
currentBoardItem()->font().setItalic(on);
emit itemPropertyChanged(false);
}
void ItemInfoView::onFontColorChanged(const TPixel32& color, bool isDragging) {
assert(currentBoardItem());
if (isDragging) return;
QColor newColor((int)color.r, (int)color.g, (int)color.b, (int)color.m);
if (currentBoardItem()->getColor() == newColor) return;
currentBoardItem()->setColor(newColor);
emit itemPropertyChanged(true);
}
void ItemInfoView::onImgARModeComboActivated() {
assert(currentBoardItem());
currentBoardItem()->setImgARMode(
(Qt::AspectRatioMode)m_imgARModeCombo->currentData().toInt());
emit itemPropertyChanged(false);
}
//=============================================================================
ItemListView::ItemListView(QWidget* parent) : QWidget(parent) {
QPushButton* newItemBtn =
new QPushButton(createQIcon("plus"), tr("Add"), this);
m_deleteItemBtn = new QPushButton(createQIcon("delete"), tr("Remove"), this);
m_moveUpBtn = new QPushButton(createQIcon("fb_up"), tr("Move Up"), this);
m_moveDownBtn =
new QPushButton(createQIcon("fb_down"), tr("Move Down"), this);
m_list = new QListWidget(this);
QSize iconSize(16, 16);
newItemBtn->setIconSize(iconSize);
m_deleteItemBtn->setIconSize(iconSize);
m_moveUpBtn->setIconSize(iconSize);
m_moveDownBtn->setIconSize(iconSize);
m_list->setIconSize(QSize(20, 20));
m_list->setAlternatingRowColors(true);
m_list->setMaximumWidth(225);
QHBoxLayout* mainLay = new QHBoxLayout();
mainLay->setMargin(5);
mainLay->setSpacing(5);
{
QVBoxLayout* buttonsLay = new QVBoxLayout();
buttonsLay->setMargin(0);
buttonsLay->setSpacing(3);
{
buttonsLay->addWidget(newItemBtn, 0);
buttonsLay->addWidget(m_deleteItemBtn, 0);
buttonsLay->addWidget(m_moveUpBtn, 0);
buttonsLay->addWidget(m_moveDownBtn, 0);
buttonsLay->addStretch(1);
}
mainLay->addLayout(buttonsLay, 0);
mainLay->addWidget(m_list, 1);
}
setLayout(mainLay);
bool ret = true;
ret = ret && connect(m_list, SIGNAL(currentRowChanged(int)), this,
SLOT(onCurrentItemSwitched(int)));
ret = ret && connect(newItemBtn, SIGNAL(clicked(bool)), this,
SLOT(onNewItemButtonClicked()));
ret = ret && connect(m_deleteItemBtn, SIGNAL(clicked(bool)), this,
SLOT(onDeleteItemButtonClicked()));
ret = ret && connect(m_moveUpBtn, SIGNAL(clicked(bool)), this,
SLOT(onMoveUpButtonClicked()));
ret = ret && connect(m_moveDownBtn, SIGNAL(clicked(bool)), this,
SLOT(onMoveDownButtonClicked()));
assert(ret);
}
void ItemListView::initialize() {
ToonzScene* scene = TApp::instance()->getCurrentScene()->getScene();
if (!scene) return;
TOutputProperties* outProp = scene->getProperties()->getOutputProperties();
BoardSettings* boardSettings = outProp->getBoardSettings();
// first, clear all the list items
m_list->clear();
if (boardSettings->getItemCount() == 0) return;
for (int i = 0; i < boardSettings->getItemCount(); i++) {
BoardItem* item = &(boardSettings->getItem(i));
QListWidgetItem* listItem = new QListWidgetItem(m_list);
editListWidgetItem(listItem, item);
}
// this will update information view
m_list->setCurrentRow(0, QItemSelectionModel::ClearAndSelect);
}
// called when the infoView is edited
void ItemListView::updateCurrentItem() {
ToonzScene* scene = TApp::instance()->getCurrentScene()->getScene();
if (!scene) return;
TOutputProperties* outProp = scene->getProperties()->getOutputProperties();
BoardSettings* boardSettings = outProp->getBoardSettings();
int currentItemIndex = m_list->currentRow();
if (currentItemIndex < 0 || currentItemIndex >= boardSettings->getItemCount())
return;
BoardItem* item = &(boardSettings->getItem(currentItemIndex));
editListWidgetItem(m_list->item(currentItemIndex), item);
}
void ItemListView::onCurrentItemSwitched(int currentRow) {
if (currentRow == -1) {
m_moveUpBtn->setEnabled(false);
m_moveDownBtn->setEnabled(false);
} else {
m_moveUpBtn->setEnabled(currentRow != 0);
m_moveDownBtn->setEnabled(currentRow != m_list->count() - 1);
}
emit currentItemSwitched(currentRow);
}
void ItemListView::onNewItemButtonClicked() {
ToonzScene* scene = TApp::instance()->getCurrentScene()->getScene();
if (!scene) return;
TOutputProperties* outProp = scene->getProperties()->getOutputProperties();
BoardSettings* boardSettings = outProp->getBoardSettings();
boardSettings->addNewItem();
QListWidgetItem* listItem = new QListWidgetItem();
BoardItem* item = &(boardSettings->getItem(0));
editListWidgetItem(listItem, item);
m_list->insertItem(0, listItem);
m_list->setCurrentRow(0, QItemSelectionModel::ClearAndSelect);
m_deleteItemBtn->setEnabled(true);
emit itemAddedOrDeleted();
}
void ItemListView::onDeleteItemButtonClicked() {
ToonzScene* scene = TApp::instance()->getCurrentScene()->getScene();
if (!scene) return;
TOutputProperties* outProp = scene->getProperties()->getOutputProperties();
BoardSettings* boardSettings = outProp->getBoardSettings();
int currentRow = m_list->currentRow();
assert(currentRow != -1);
boardSettings->removeItem(currentRow);
if (m_list->count() == 1) {
m_deleteItemBtn->setEnabled(false);
m_list->setCurrentRow(-1, QItemSelectionModel::ClearAndSelect);
} else if (currentRow == m_list->count() - 1)
m_list->setCurrentRow(m_list->count() - 2,
QItemSelectionModel::ClearAndSelect);
delete m_list->takeItem(currentRow);
emit itemAddedOrDeleted();
}
void ItemListView::onMoveUpButtonClicked() {
ToonzScene* scene = TApp::instance()->getCurrentScene()->getScene();
if (!scene) return;
TOutputProperties* outProp = scene->getProperties()->getOutputProperties();
BoardSettings* boardSettings = outProp->getBoardSettings();
int currentRow = m_list->currentRow();
assert(currentRow > 0);
boardSettings->swapItems(currentRow - 1, currentRow);
m_list->insertItem(currentRow - 1, m_list->takeItem(currentRow));
m_list->setCurrentRow(currentRow - 1);
emit itemAddedOrDeleted();
}
void ItemListView::onMoveDownButtonClicked() {
ToonzScene* scene = TApp::instance()->getCurrentScene()->getScene();
if (!scene) return;
TOutputProperties* outProp = scene->getProperties()->getOutputProperties();
BoardSettings* boardSettings = outProp->getBoardSettings();
int currentRow = m_list->currentRow();
assert(currentRow < m_list->count() - 1);
boardSettings->swapItems(currentRow, currentRow + 1);
QListWidgetItem* item = m_list->takeItem(currentRow);
m_list->insertItem(currentRow + 1, item);
m_list->setCurrentRow(currentRow + 1);
emit itemAddedOrDeleted();
}
//=============================================================================
BoardSettingsPopup::BoardSettingsPopup(QWidget* parent)
: DVGui::Dialog(parent, true, false, "ClapperboardSettings") {
setWindowTitle(tr("Clapperboard Settings"));
initializeItemTypeString();
m_boardView = new BoardView(this);
m_itemInfoView = new ItemInfoView(this);
m_itemListView = new ItemListView(this);
m_durationEdit = new DVGui::IntLineEdit(this, 1, 0);
QPushButton* loadPresetBtn =
new QPushButton(createQIcon("load"), tr("Load Preset"), this);
QPushButton* savePresetBtn =
new QPushButton(createQIcon("saveas"), tr("Save as Preset"), this);
QPushButton* closeButton = new QPushButton(tr("Close"), this);
//--- layout
QHBoxLayout* mainLay = new QHBoxLayout();
mainLay->setMargin(0);
mainLay->setSpacing(10);
{
QVBoxLayout* leftLay = new QVBoxLayout();
leftLay->setMargin(0);
leftLay->setSpacing(0);
{
QHBoxLayout* leftTopLay = new QHBoxLayout();
leftTopLay->setMargin(5);
leftTopLay->setSpacing(3);
{
leftTopLay->addWidget(new QLabel(tr("Duration (frames):"), this), 0);
leftTopLay->addWidget(m_durationEdit, 0);
leftTopLay->addSpacing(10);
leftTopLay->addWidget(loadPresetBtn, 0);
leftTopLay->addWidget(savePresetBtn, 0);
leftTopLay->addStretch(1);
}
leftLay->addLayout(leftTopLay, 0);
leftLay->addWidget(m_boardView, 1);
}
mainLay->addLayout(leftLay, 1);
QVBoxLayout* rightLay = new QVBoxLayout();
rightLay->setMargin(0);
rightLay->setSpacing(15);
{
rightLay->addWidget(m_itemInfoView, 0);
rightLay->addWidget(m_itemListView, 1);
}
mainLay->addLayout(rightLay, 0);
}
m_topLayout->addLayout(mainLay, 1);
addButtonBarWidget(closeButton);
bool ret = true;
ret = ret && connect(m_itemListView, SIGNAL(currentItemSwitched(int)), this,
SLOT(onCurrentItemSwitched(int)));
ret = ret && connect(m_itemListView, SIGNAL(itemAddedOrDeleted()), this,
SLOT(onItemAddedOrDeleted()));
ret = ret && connect(m_itemInfoView, SIGNAL(itemPropertyChanged(bool)), this,
SLOT(onItemPropertyChanged(bool)));
ret = ret && connect(m_durationEdit, SIGNAL(editingFinished()), this,
SLOT(onDurationEdited()));
ret = ret && connect(closeButton, SIGNAL(pressed()), this, SLOT(close()));
ret = ret &&
connect(loadPresetBtn, SIGNAL(pressed()), this, SLOT(onLoadPreset()));
ret = ret &&
connect(savePresetBtn, SIGNAL(pressed()), this, SLOT(onSavePreset()));
assert(ret);
}
void BoardSettingsPopup::initialize() {
ToonzScene* scene = TApp::instance()->getCurrentScene()->getScene();
if (!scene) return;
TOutputProperties* outProp = scene->getProperties()->getOutputProperties();
BoardSettings* boardSettings = outProp->getBoardSettings();
m_durationEdit->setValue(boardSettings->getDuration());
m_itemListView->initialize();
m_boardView->invalidate();
m_boardView->update();
}
void BoardSettingsPopup::initializeItemTypeString() {
if (!stringByItemType.isEmpty()) return;
stringByItemType[BoardItem::FreeText] = tr("Text"); // free text (m_text)
stringByItemType[BoardItem::ProjectName] = tr("Project name");
stringByItemType[BoardItem::SceneName] = tr("Scene name");
stringByItemType[BoardItem::Duration_Frame] = tr("Duration : Frame");
stringByItemType[BoardItem::Duration_SecFrame] = tr("Duration : Sec + Frame");
stringByItemType[BoardItem::Duration_HHMMSSFF] = tr("Duration : HH:MM:SS:FF");
stringByItemType[BoardItem::CurrentDate] = tr("Current date");
stringByItemType[BoardItem::CurrentDateTime] = tr("Current date and time");
stringByItemType[BoardItem::UserName] = tr("User name");
stringByItemType[BoardItem::ScenePath_Aliased] =
tr("Scene location : Aliased path");
stringByItemType[BoardItem::ScenePath_Full] =
tr("Scene location : Full path");
stringByItemType[BoardItem::MoviePath_Aliased] =
tr("Output location : Aliased path");
stringByItemType[BoardItem::MoviePath_Full] =
tr("Output location : Full path");
stringByItemType[BoardItem::Image] = tr("Image"); // m_imgPath
}
void BoardSettingsPopup::hideEvent(QHideEvent* event) {
setCurrentBoardItem(nullptr);
}
// called on changing the current row of ItemListView
void BoardSettingsPopup::onCurrentItemSwitched(int index) {
// update Info
m_itemInfoView->setCurrentItem(index);
m_boardView->update();
}
void BoardSettingsPopup::onItemAddedOrDeleted() {
m_boardView->invalidate();
m_boardView->update();
}
// called on modifying the infoView
void BoardSettingsPopup::onItemPropertyChanged(bool updateListView) {
m_boardView->invalidate();
m_boardView->update();
if (updateListView) m_itemListView->updateCurrentItem();
}
void BoardSettingsPopup::onDurationEdited() {
ToonzScene* scene = TApp::instance()->getCurrentScene()->getScene();
if (!scene) return;
TOutputProperties* outProp = scene->getProperties()->getOutputProperties();
BoardSettings* boardSettings = outProp->getBoardSettings();
boardSettings->setDuration(m_durationEdit->getValue());
m_boardView->update();
}
void BoardSettingsPopup::onLoadPreset() {
LoadBoardPresetFilePopup popup;
TFilePath fp = popup.getPath();
if (fp.isEmpty()) return;
TIStream is(fp);
if (!is) throw TException(fp.getWideString() + L": Can't open file");
try {
std::string tagName = "";
if (!is.matchTag(tagName)) throw TException("Bad file format");
if (tagName == "clapperboardSettingsPreset") {
ToonzScene* scene = TApp::instance()->getCurrentScene()->getScene();
if (!scene) return;
TOutputProperties* outProp =
scene->getProperties()->getOutputProperties();
BoardSettings* boardSettings = outProp->getBoardSettings();
boardSettings->loadData(is);
} else
throw TException("Bad file format");
} catch (const TSystemException& se) {
DVGui::warning(QString::fromStdWString(se.getMessage()));
} catch (...) {
DVGui::error(QObject::tr("Couldn't load %1").arg(fp.getQString()));
}
initialize();
}
void BoardSettingsPopup::onSavePreset() {
SaveBoardPresetFilePopup popup;
TFilePath fp = popup.getPath();
if (fp.isEmpty()) return;
try {
TFileStatus fs(fp);
if (fs.doesExist() && !fs.isWritable()) {
throw TSystemException(
fp, "The preset cannot be saved: it is a read only file.");
}
TOStream os(fp, false);
if (!os.checkStatus()) throw TException("Could not open file");
ToonzScene* scene = TApp::instance()->getCurrentScene()->getScene();
if (!scene) return;
TOutputProperties* outProp = scene->getProperties()->getOutputProperties();
BoardSettings* boardSettings = outProp->getBoardSettings();
os.openChild("clapperboardSettingsPreset");
boardSettings->saveData(os, true);
os.closeChild();
bool status = os.checkStatus();
if (!status) throw TException("Could not complete the save preset");
} catch (const TSystemException& se) {
DVGui::warning(QString::fromStdWString(se.getMessage()));
} catch (...) {
DVGui::error(QObject::tr("Couldn't save %1").arg(fp.getQString()));
}
}
//=============================================================================
SaveBoardPresetFilePopup::SaveBoardPresetFilePopup()
: GenericSaveFilePopup(tr("Save Clapperboard Settings As Preset")) {
m_browser->enableGlobalSelection(false);
setFilterTypes(QStringList("clapperboard"));
}
void SaveBoardPresetFilePopup::showEvent(QShowEvent* e) {
FileBrowserPopup::showEvent(e);
setFolder(ToonzFolder::getLibraryFolder() + "clapperboards");
}
//=============================================================================
LoadBoardPresetFilePopup::LoadBoardPresetFilePopup()
: GenericLoadFilePopup(tr("Load Clapperboard Settings Preset")) {
m_browser->enableGlobalSelection(false);
setFilterTypes(QStringList("clapperboard"));
}
void LoadBoardPresetFilePopup::showEvent(QShowEvent* e) {
FileBrowserPopup::showEvent(e);
setFolder(ToonzFolder::getLibraryFolder() + "clapperboards");
}