leocad/common/lc_timelinewidget.cpp

434 lines
10 KiB
C++
Raw Normal View History

2016-10-05 23:28:52 +02:00
#include "lc_global.h"
#include "lc_timelinewidget.h"
#include "lc_model.h"
#include "piece.h"
#include "pieceinf.h"
#include "lc_mainwindow.h"
lcTimelineWidget::lcTimelineWidget(QWidget* Parent)
: QTreeWidget(Parent)
{
mIgnoreUpdates = false;
setSelectionMode(QAbstractItemView::ExtendedSelection);
setDragEnabled(true);
setDragDropMode(QAbstractItemView::InternalMove);
setUniformRowHeights(true);
setHeaderHidden(true);
setContextMenuPolicy(Qt::CustomContextMenu);
invisibleRootItem()->setFlags(invisibleRootItem()->flags() & ~Qt::ItemIsDropEnabled);
connect(this, SIGNAL(itemSelectionChanged()), SLOT(ItemSelectionChanged()));
connect(this, SIGNAL(customContextMenuRequested(QPoint)), SLOT(CustomMenuRequested(QPoint)));
}
lcTimelineWidget::~lcTimelineWidget()
{
}
void lcTimelineWidget::CustomMenuRequested(QPoint Pos)
{
QMenu* Menu = new QMenu(this);
lcObject* FocusObject = gMainWindow->GetActiveModel()->GetFocusObject();
2016-10-05 23:28:52 +02:00
if (FocusObject && FocusObject->IsPiece())
{
lcPiece* Piece = (lcPiece*)FocusObject;
if (Piece->mPieceInfo->IsModel())
{
Menu->addAction(gMainWindow->mActions[LC_PIECE_EDIT_SELECTED_SUBMODEL]);
Menu->addAction(gMainWindow->mActions[LC_PIECE_VIEW_SELECTED_MODEL]);
Menu->addAction(gMainWindow->mActions[LC_PIECE_INLINE_SELECTED_MODELS]);
2016-10-05 23:28:52 +02:00
Menu->addSeparator();
}
}
Menu->addAction(gMainWindow->mActions[LC_TIMELINE_SET_CURRENT]);
Menu->addAction(gMainWindow->mActions[LC_TIMELINE_INSERT]);
Menu->addAction(gMainWindow->mActions[LC_TIMELINE_DELETE]);
Menu->addAction(gMainWindow->mActions[LC_TIMELINE_MOVE_SELECTION]);
2016-10-05 23:28:52 +02:00
Menu->addSeparator();
Menu->addAction(gMainWindow->mActions[LC_PIECE_HIDE_SELECTED]);
Menu->addAction(gMainWindow->mActions[LC_PIECE_HIDE_UNSELECTED]);
Menu->addAction(gMainWindow->mActions[LC_PIECE_UNHIDE_SELECTED]);
Menu->addAction(gMainWindow->mActions[LC_PIECE_UNHIDE_ALL]);
Menu->exec(viewport()->mapToGlobal(Pos));
delete Menu;
2016-10-05 23:28:52 +02:00
}
void lcTimelineWidget::Update(bool Clear, bool UpdateItems)
{
if (mIgnoreUpdates)
return;
lcModel* Model = gMainWindow->GetActiveModel();
bool Blocked = blockSignals(true);
2016-10-05 23:28:52 +02:00
if (!Model)
{
mItems.clear();
clear();
blockSignals(Blocked);
2016-10-05 23:28:52 +02:00
return;
}
if (Clear)
{
mItems.clear();
clear();
}
lcStep LastStep = Model->GetLastStep();
if (Model->HasPieces())
LastStep++;
LastStep = lcMax(LastStep, Model->GetCurrentStep());
2016-10-05 23:28:52 +02:00
for (int TopLevelItemIdx = LastStep; TopLevelItemIdx < topLevelItemCount(); )
{
QTreeWidgetItem* StepItem = topLevelItem(TopLevelItemIdx);
while (StepItem->childCount())
{
QTreeWidgetItem* PieceItem = StepItem->child(0);
lcPiece* Piece = (lcPiece*)PieceItem->data(0, Qt::UserRole).value<uintptr_t>();
mItems.remove(Piece);
delete PieceItem;
}
delete StepItem;
}
for (unsigned int TopLevelItemIdx = topLevelItemCount(); TopLevelItemIdx < LastStep; TopLevelItemIdx++)
{
QTreeWidgetItem* StepItem = new QTreeWidgetItem(this, QStringList(tr("Step %1").arg(TopLevelItemIdx + 1)));
StepItem->setData(0, Qt::UserRole, qVariantFromValue<int>(TopLevelItemIdx + 1));
2016-10-05 23:28:52 +02:00
StepItem->setFlags(Qt::ItemIsEnabled | Qt::ItemIsDropEnabled);
addTopLevelItem(StepItem);
StepItem->setExpanded(true);
}
const lcArray<lcPiece*>& Pieces = Model->GetPieces();
QTreeWidgetItem* StepItem = nullptr;
2016-10-05 23:28:52 +02:00
int PieceItemIndex = 0;
lcStep Step = 0;
2019-03-29 01:59:58 +01:00
for (lcPiece* Piece : Pieces)
2016-10-05 23:28:52 +02:00
{
while (Step != Piece->GetStepShow())
{
if (StepItem)
{
while (PieceItemIndex < StepItem->childCount())
{
QTreeWidgetItem* PieceItem = StepItem->child(PieceItemIndex);
lcPiece* RemovePiece = (lcPiece*)PieceItem->data(0, Qt::UserRole).value<uintptr_t>();
if (Pieces.FindIndex(RemovePiece) == -1)
{
mItems.remove(RemovePiece);
delete PieceItem;
}
else
{
PieceItem->parent()->removeChild(PieceItem);
topLevelItem(RemovePiece->GetStepShow() - 1)->addChild(PieceItem);
}
}
}
Step++;
StepItem = topLevelItem(Step - 1);
PieceItemIndex = 0;
}
QTreeWidgetItem* PieceItem = mItems.value(Piece);
bool UpdateItem = UpdateItems;
2017-02-13 03:05:20 +01:00
if (StepItem)
2016-10-05 23:28:52 +02:00
{
2017-02-13 03:05:20 +01:00
if (!PieceItem)
{
PieceItem = new QTreeWidgetItem();
PieceItem->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled | Qt::ItemIsDragEnabled);
PieceItem->setData(0, Qt::UserRole, qVariantFromValue<uintptr_t>((uintptr_t)Piece));
StepItem->insertChild(PieceItemIndex, PieceItem);
mItems[Piece] = PieceItem;
2016-10-05 23:28:52 +02:00
2017-02-13 03:05:20 +01:00
UpdateItem = true;
}
else
2016-10-05 23:28:52 +02:00
{
2017-02-13 03:05:20 +01:00
if (PieceItemIndex >= StepItem->childCount() || PieceItem != StepItem->child(PieceItemIndex))
{
QTreeWidgetItem* PieceParent = PieceItem->parent();
2016-10-05 23:28:52 +02:00
2017-02-13 03:05:20 +01:00
if (PieceParent)
PieceParent->removeChild(PieceItem);
2016-10-05 23:28:52 +02:00
2017-02-13 03:05:20 +01:00
StepItem->insertChild(PieceItemIndex, PieceItem);
}
2016-10-05 23:28:52 +02:00
}
}
if (UpdateItem)
{
PieceItem->setText(0, Piece->mPieceInfo->m_strDescription);
int ColorIndex = Piece->mColorIndex;
if (!mIcons.contains(ColorIndex))
{
int Size = rowHeight(indexFromItem(PieceItem));
QImage Image(Size, Size, QImage::Format_ARGB32);
Image.fill(0);
float* Color = gColorList[ColorIndex].Value;
QPainter Painter(&Image);
Painter.setPen(Qt::darkGray);
2016-10-05 23:28:52 +02:00
Painter.setBrush(QColor::fromRgbF(Color[0], Color[1], Color[2]));
Painter.drawEllipse(0, 0, Size - 1, Size - 1);
2016-10-05 23:28:52 +02:00
mIcons[ColorIndex] = QIcon(QPixmap::fromImage(Image));
}
PieceItem->setIcon(0, mIcons[ColorIndex]);
QColor Color = palette().text().color();
if (Piece->IsHidden())
Color.setAlpha(128);
PieceItem->setTextColor(0, Color);
}
PieceItem->setSelected(Piece->IsSelected());
PieceItemIndex++;
}
if (Step == 0)
{
Step = 1;
StepItem = topLevelItem(0);
}
2017-02-13 03:05:20 +01:00
while (Step <= LastStep && StepItem)
2016-10-05 23:28:52 +02:00
{
while (PieceItemIndex < StepItem->childCount())
{
QTreeWidgetItem* PieceItem = StepItem->child(PieceItemIndex);
lcPiece* RemovePiece = (lcPiece*)PieceItem->data(0, Qt::UserRole).value<uintptr_t>();
mItems.remove(RemovePiece);
delete PieceItem;
}
Step++;
StepItem = topLevelItem(Step - 1);
PieceItemIndex = 0;
}
blockSignals(Blocked);
}
void lcTimelineWidget::UpdateSelection()
{
if (mIgnoreUpdates)
return;
QItemSelection ItemSelection;
for (int TopLevelItemIdx = 0; TopLevelItemIdx < topLevelItemCount(); TopLevelItemIdx++)
{
QTreeWidgetItem* StepItem = topLevelItem(TopLevelItemIdx);
for (int PieceItemIdx = 0; PieceItemIdx < StepItem->childCount(); PieceItemIdx++)
{
QTreeWidgetItem* PieceItem = StepItem->child(PieceItemIdx);
lcPiece* Piece = (lcPiece*)PieceItem->data(0, Qt::UserRole).value<uintptr_t>();
2017-07-03 05:12:17 +02:00
if (Piece && Piece->IsSelected())
2016-10-05 23:28:52 +02:00
{
QModelIndex Index = indexFromItem(PieceItem);
ItemSelection.select(Index, Index);
}
}
}
bool Blocked = blockSignals(true);
selectionModel()->select(ItemSelection, QItemSelectionModel::ClearAndSelect);
blockSignals(Blocked);
}
void lcTimelineWidget::InsertStep()
{
QTreeWidgetItem* CurrentItem = currentItem();
if (!CurrentItem)
return;
if (CurrentItem->parent())
CurrentItem = CurrentItem->parent();
int Step = indexOfTopLevelItem(CurrentItem);
if (Step == -1)
return;
gMainWindow->GetActiveModel()->InsertStep(Step + 1);
2016-10-05 23:28:52 +02:00
}
void lcTimelineWidget::RemoveStep()
{
QTreeWidgetItem* CurrentItem = currentItem();
if (!CurrentItem)
return;
if (CurrentItem->parent())
CurrentItem = CurrentItem->parent();
int Step = indexOfTopLevelItem(CurrentItem);
if (Step == -1)
return;
gMainWindow->GetActiveModel()->RemoveStep(Step + 1);
2016-10-05 23:28:52 +02:00
}
void lcTimelineWidget::MoveSelection()
{
QTreeWidgetItem* CurrentItem = currentItem();
if (!CurrentItem)
return;
if (CurrentItem->parent())
CurrentItem = CurrentItem->parent();
int Step = indexOfTopLevelItem(CurrentItem);
if (Step == -1)
return;
QList<QTreeWidgetItem*> SelectedItems = selectedItems();
2018-02-22 01:12:18 +01:00
for (QTreeWidgetItem* PieceItem : SelectedItems)
{
QTreeWidgetItem* Parent = PieceItem->parent();
if (!Parent)
continue;
int ChildIndex = Parent->indexOfChild(PieceItem);
CurrentItem->addChild(Parent->takeChild(ChildIndex));
}
UpdateModel();
}
void lcTimelineWidget::SetCurrentStep()
{
QTreeWidgetItem* CurrentItem = currentItem();
if (!CurrentItem)
return;
if (CurrentItem->parent())
CurrentItem = CurrentItem->parent();
int Step = indexOfTopLevelItem(CurrentItem);
if (Step == -1)
return;
gMainWindow->GetActiveModel()->SetCurrentStep(Step + 1);
}
2016-10-05 23:28:52 +02:00
void lcTimelineWidget::ItemSelectionChanged()
{
lcArray<lcObject*> Selection;
lcStep LastStep = 1;
2018-02-22 02:27:24 +01:00
QList<QTreeWidgetItem*> SelectedItems = selectedItems();
2016-10-05 23:28:52 +02:00
QTreeWidgetItem* CurrentItem = currentItem();
lcModel* Model = gMainWindow->GetActiveModel();
if (SelectedItems.isEmpty() && CurrentItem)
{
Model->SetCurrentStep(CurrentItem->data(0, Qt::UserRole).value<int>());
return;
}
2018-02-22 02:27:24 +01:00
for (QTreeWidgetItem* PieceItem : SelectedItems)
2016-10-05 23:28:52 +02:00
{
lcPiece* Piece = (lcPiece*)PieceItem->data(0, Qt::UserRole).value<uintptr_t>();
2017-07-03 05:12:17 +02:00
if (Piece)
{
LastStep = lcMax(LastStep, Piece->GetStepShow());
Selection.Add(Piece);
}
2016-10-05 23:28:52 +02:00
}
lcPiece* CurrentPiece = nullptr;
2016-10-05 23:28:52 +02:00
if (CurrentItem && CurrentItem->isSelected())
CurrentPiece = (lcPiece*)CurrentItem->data(0, Qt::UserRole).value<uintptr_t>();
bool Blocked = blockSignals(true);
mIgnoreUpdates = true;
if (LastStep > Model->GetCurrentStep())
Model->SetCurrentStep(LastStep);
Model->SetSelectionAndFocus(Selection, CurrentPiece, LC_PIECE_SECTION_POSITION, false);
2016-10-05 23:28:52 +02:00
mIgnoreUpdates = false;
blockSignals(Blocked);
}
void lcTimelineWidget::dropEvent(QDropEvent* Event)
{
QTreeWidget::dropEvent(Event);
UpdateModel();
}
void lcTimelineWidget::mousePressEvent(QMouseEvent* Event)
{
if (Event->button() == Qt::RightButton)
{
QItemSelection Selection = selectionModel()->selection();
bool Blocked = blockSignals(true);
QTreeWidget::mousePressEvent(Event);
blockSignals(Blocked);
selectionModel()->select(Selection, QItemSelectionModel::ClearAndSelect);
}
else
QTreeWidget::mousePressEvent(Event);
}
2016-10-05 23:28:52 +02:00
void lcTimelineWidget::UpdateModel()
{
2016-10-05 23:28:52 +02:00
QList<QPair<lcPiece*, lcStep>> PieceSteps;
for (int TopLevelItemIdx = 0; TopLevelItemIdx < topLevelItemCount(); TopLevelItemIdx++)
{
QTreeWidgetItem* StepItem = topLevelItem(TopLevelItemIdx);
for (int PieceItemIdx = 0; PieceItemIdx < StepItem->childCount(); PieceItemIdx++)
{
QTreeWidgetItem* PieceItem = StepItem->child(PieceItemIdx);
lcPiece* Piece = (lcPiece*)PieceItem->data(0, Qt::UserRole).value<uintptr_t>();
PieceSteps.append(QPair<lcPiece*, lcStep>(Piece, TopLevelItemIdx + 1));
}
}
mIgnoreUpdates = true;
gMainWindow->GetActiveModel()->SetPieceSteps(PieceSteps);
2016-10-05 23:28:52 +02:00
mIgnoreUpdates = false;
}