| |
| |
|
|
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| TEnv::IntVar FrameDisplayStyleInXsheetRowArea( |
| "FrameDisplayStyleInXsheetRowArea", 0); |
| |
| |
| namespace XsheetGUI { |
| //----------------------------------------------------------------------------- |
| |
| const int ColumnWidth = 74; |
| const int RowHeight = 20; |
| const int SCROLLBAR_WIDTH = 16; |
| const int TOOLBAR_HEIGHT = 29; |
| const int ZOOM_FACTOR_MAX = 100; |
| const int ZOOM_FACTOR_MIN = 20; |
| } |
| |
| |
| |
| |
| |
| void XsheetViewer::getCellTypeAndColors(int <ype, QColor &cellColor, |
| QColor &sideColor, const TXshCell &cell, |
| bool isSelected) { |
| if (cell.isEmpty()) |
| ltype = NO_XSHLEVEL; |
| else { |
| ltype = cell.m_level->getType(); |
| switch (ltype) { |
| case TZI_XSHLEVEL: |
| case OVL_XSHLEVEL: |
| cellColor = (isSelected) ? getSelectedFullcolorColumnColor() |
| : getFullcolorColumnColor(); |
| sideColor = getFullcolorColumnBorderColor(); |
| break; |
| case PLI_XSHLEVEL: |
| cellColor = (isSelected) ? getSelectedVectorColumnColor() |
| : getVectorColumnColor(); |
| sideColor = getVectorColumnBorderColor(); |
| break; |
| case TZP_XSHLEVEL: |
| cellColor = |
| (isSelected) ? getSelectedLevelColumnColor() : getLevelColumnColor(); |
| sideColor = getLevelColumnBorderColor(); |
| break; |
| case PLT_XSHLEVEL: |
| cellColor = (isSelected) ? getSelectedPaletteColumnColor() |
| : getPaletteColumnColor(); |
| sideColor = getPaletteColumnBorderColor(); |
| break; |
| case ZERARYFX_XSHLEVEL: |
| cellColor = |
| (isSelected) ? getSelectedFxColumnColor() : getFxColumnColor(); |
| sideColor = getFxColumnBorderColor(); |
| break; |
| case CHILD_XSHLEVEL: |
| cellColor = |
| (isSelected) ? getSelectedChildColumnColor() : getChildColumnColor(); |
| sideColor = getChildColumnBorderColor(); |
| break; |
| case SND_XSHLEVEL: |
| cellColor = |
| (isSelected) ? m_selectedSoundColumnColor : m_soundColumnColor; |
| sideColor = m_soundColumnBorderColor; |
| break; |
| case SND_TXT_XSHLEVEL: |
| cellColor = (isSelected) ? getSelectedSoundTextColumnColor() |
| : getSoundTextColumnColor(); |
| sideColor = getSoundTextColumnBorderColor(); |
| break; |
| case MESH_XSHLEVEL: |
| cellColor = |
| (isSelected) ? getSelectedMeshColumnColor() : getMeshColumnColor(); |
| sideColor = getMeshColumnBorderColor(); |
| break; |
| case UNKNOWN_XSHLEVEL: |
| case NO_XSHLEVEL: |
| default: |
| |
| cellColor = grey210; |
| sideColor = grey150; |
| } |
| } |
| } |
| |
| |
| |
| void XsheetViewer::getColumnColor(QColor &color, QColor &sideColor, int index, |
| TXsheet *xsh) { |
| if (index < 0 || xsh->isColumnEmpty(index)) return; |
| int r0, r1; |
| xsh->getCellRange(index, r0, r1); |
| if (0 <= r0 && r0 <= r1) { |
| |
| if (xsh->getColumn(index)->getSoundColumn()) { |
| color = m_soundColumnColor; |
| sideColor = m_soundColumnBorderColor; |
| } else { |
| TXshCell cell = xsh->getCell(r0, index); |
| int ltype; |
| getCellTypeAndColors(ltype, color, sideColor, cell); |
| } |
| } |
| if (xsh->getColumn(index)->isMask()) color = QColor(255, 0, 255); |
| } |
| |
| |
| |
| void XsheetViewer::getButton(const int &btype, QColor &bgColor, |
| QImage &iconImage, bool isTimeline) { |
| switch (btype) { |
| case PREVIEW_ON_XSHBUTTON: |
| bgColor = (isTimeline) ? getTimelinePreviewButtonBgOnColor() |
| : getXsheetPreviewButtonBgOnColor(); |
| iconImage = (isTimeline) ? getTimelinePreviewButtonOnImage() |
| : getXsheetPreviewButtonOnImage(); |
| break; |
| case PREVIEW_OFF_XSHBUTTON: |
| bgColor = (isTimeline) ? getTimelinePreviewButtonBgOffColor() |
| : getXsheetPreviewButtonBgOffColor(); |
| iconImage = (isTimeline) ? getTimelinePreviewButtonOffImage() |
| : getXsheetPreviewButtonOffImage(); |
| break; |
| case CAMSTAND_ON_XSHBUTTON: |
| bgColor = (isTimeline) ? getTimelineCamstandButtonBgOnColor() |
| : getXsheetCamstandButtonBgOnColor(); |
| iconImage = (isTimeline) ? getTimelineCamstandButtonOnImage() |
| : getXsheetCamstandButtonOnImage(); |
| break; |
| case CAMSTAND_TRANSP_XSHBUTTON: |
| bgColor = (isTimeline) ? getTimelineCamstandButtonBgOnColor() |
| : getXsheetCamstandButtonBgOnColor(); |
| iconImage = (isTimeline) ? getTimelineCamstandButtonTranspImage() |
| : getXsheetCamstandButtonTranspImage(); |
| break; |
| case CAMSTAND_OFF_XSHBUTTON: |
| bgColor = (isTimeline) ? getTimelineCamstandButtonBgOffColor() |
| : getXsheetCamstandButtonBgOffColor(); |
| iconImage = (isTimeline) ? getTimelineCamstandButtonOffImage() |
| : getXsheetCamstandButtonOffImage(); |
| break; |
| case LOCK_ON_XSHBUTTON: |
| bgColor = (isTimeline) ? getTimelineLockButtonBgOnColor() |
| : getXsheetLockButtonBgOnColor(); |
| iconImage = (isTimeline) ? getTimelineLockButtonOnImage() |
| : getXsheetLockButtonOnImage(); |
| break; |
| case LOCK_OFF_XSHBUTTON: |
| bgColor = (isTimeline) ? getTimelineLockButtonBgOffColor() |
| : getXsheetLockButtonBgOffColor(); |
| iconImage = (isTimeline) ? getTimelineLockButtonOffImage() |
| : getXsheetLockButtonOffImage(); |
| break; |
| case CONFIG_XSHBUTTON: |
| bgColor = (isTimeline) ? getTimelineConfigButtonBgColor() |
| : getXsheetConfigButtonBgColor(); |
| iconImage = (isTimeline) ? getTimelineConfigButtonImage() |
| : getXsheetConfigButtonImage(); |
| break; |
| default: |
| bgColor = grey210; |
| static QImage iconignored; |
| iconImage = iconignored; |
| } |
| } |
| |
| |
| |
| XsheetViewer::XsheetViewer(QWidget *parent, Qt::WindowFlags flags) |
| : QFrame(parent) |
| , m_timerId(0) |
| , m_autoPanSpeed(0, 0) |
| , m_dragTool(0) |
| , m_columnSelection(new TColumnSelection()) |
| , m_cellKeyframeSelection(new TCellKeyframeSelection( |
| new TCellSelection(), new TKeyframeSelection())) |
| , m_scrubCol(-1) |
| , m_scrubRow0(-1) |
| , m_scrubRow1(-1) |
| , m_isCurrentFrameSwitched(false) |
| , m_isCurrentColumnSwitched(false) |
| , m_isComputingSize(false) |
| , m_currentNoteIndex(0) |
| , m_qtModifiers(0) |
| , m_frameDisplayStyle(to_enum(FrameDisplayStyleInXsheetRowArea)) |
| , m_orientation(nullptr) |
| , m_xsheetLayout("Classic") |
| , m_frameZoomFactor(100) { |
| m_xsheetLayout = Preferences::instance()->getLoadedXsheetLayout(); |
| |
| setFocusPolicy(Qt::StrongFocus); |
| |
| setFrameStyle(QFrame::StyledPanel); |
| setObjectName("XsheetViewer"); |
| |
| m_orientation = Orientations::topToBottom(); |
| |
| m_cellKeyframeSelection->setXsheetHandle( |
| TApp::instance()->getCurrentXsheet()); |
| |
| m_toolbarScrollArea = new XsheetScrollArea(this); |
| m_toolbarScrollArea->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); |
| m_toolbarScrollArea->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff); |
| m_toolbar = new XsheetGUI::XSheetToolbar(this, 0, true); |
| m_toolbarScrollArea->setWidget(m_toolbar); |
| |
| m_noteArea = new XsheetGUI::NoteArea(this); |
| m_noteScrollArea = new XsheetScrollArea(this); |
| m_noteScrollArea->setObjectName("xsheetArea"); |
| m_noteScrollArea->setWidget(m_noteArea); |
| m_noteScrollArea->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); |
| m_noteScrollArea->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff); |
| |
| m_cellArea = new XsheetGUI::CellArea(this); |
| m_cellScrollArea = new XsheetScrollArea(this); |
| m_cellScrollArea->setObjectName("xsheetArea"); |
| m_cellScrollArea->setWidget(m_cellArea); |
| m_cellScrollArea->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOn); |
| m_cellScrollArea->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOn); |
| |
| m_columnArea = new XsheetGUI::ColumnArea(this); |
| m_columnScrollArea = new XsheetScrollArea(this); |
| m_columnScrollArea->setObjectName("xsheetArea"); |
| m_columnScrollArea->setWidget(m_columnArea); |
| m_columnScrollArea->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); |
| m_columnScrollArea->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff); |
| |
| m_rowArea = new XsheetGUI::RowArea(this); |
| m_rowScrollArea = new XsheetScrollArea(this); |
| m_rowScrollArea->setObjectName("xsheetArea"); |
| m_rowScrollArea->setWidget(m_rowArea); |
| m_rowScrollArea->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); |
| m_rowScrollArea->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff); |
| |
| m_layerFooterPanel = new LayerFooterPanel(this, this); |
| |
| m_frameScroller.setFrameScrollArea(m_cellScrollArea); |
| connect(&m_frameScroller, &Spreadsheet::FrameScroller::prepareToScrollOffset, |
| this, &XsheetViewer::onPrepareToScrollOffset); |
| connect(&m_frameScroller, &Spreadsheet::FrameScroller::zoomScrollAdjust, this, |
| &XsheetViewer::onZoomScrollAdjust); |
| |
| connectScrollBars(); |
| |
| connect(this, &XsheetViewer::orientationChanged, this, |
| &XsheetViewer::onOrientationChanged); |
| connect(m_toolbar, SIGNAL(updateVisibility()), this, |
| SLOT(positionSections())); |
| |
| emit orientationChanged(orientation()); |
| |
| onPreferenceChanged("XsheetCamera"); |
| } |
| |
| |
| |
| XsheetViewer::~XsheetViewer() { |
| delete m_cellKeyframeSelection; |
| delete m_dragTool; |
| } |
| |
| |
| |
| void XsheetViewer::setDragTool(XsheetGUI::DragTool *dragTool) { |
| assert(m_dragTool == 0); |
| m_dragTool = dragTool; |
| } |
| |
| |
| |
| void XsheetViewer::dragToolClick(QMouseEvent *e) { |
| if (m_dragTool) m_dragTool->onClick(e); |
| } |
| |
| void XsheetViewer::dragToolDrag(QMouseEvent *e) { |
| if (m_dragTool) m_dragTool->onDrag(e); |
| } |
| |
| void XsheetViewer::dragToolRelease(QMouseEvent *e) { |
| if (m_dragTool) { |
| m_dragTool->onRelease(e); |
| delete getDragTool(); |
| m_dragTool = 0; |
| } |
| } |
| |
| |
| |
| void XsheetViewer::dragToolClick(QDropEvent *e) { |
| if (m_dragTool) m_dragTool->onClick(e); |
| } |
| |
| void XsheetViewer::dragToolDrag(QDropEvent *e) { |
| if (m_dragTool) m_dragTool->onDrag(e); |
| } |
| |
| void XsheetViewer::dragToolRelease(QDropEvent *e) { |
| if (m_dragTool) { |
| m_dragTool->onRelease(e); |
| delete getDragTool(); |
| m_dragTool = 0; |
| } |
| } |
| |
| void XsheetViewer::dragToolLeave(QEvent *e) { |
| if (m_dragTool) { |
| delete getDragTool(); |
| m_dragTool = 0; |
| } |
| } |
| |
| |
| |
| const Orientation *XsheetViewer::orientation() const { |
| if (!m_orientation) throw std::runtime_error("!m_orientation"); |
| return m_orientation; |
| } |
| |
| void XsheetViewer::flipOrientation() { |
| m_orientation = orientation()->next(); |
| |
| int factor = (m_orientation->isVerticalTimeline()) ? m_frameZoomFactor : 100; |
| TApp::instance()->getCurrentXsheet()->notifyZoomScaleChanged(factor); |
| |
| emit orientationChanged(orientation()); |
| } |
| |
| void XsheetViewer::onOrientationChanged(const Orientation *newOrientation) { |
| disconnectScrollBars(); |
| |
| positionSections(); |
| m_frameScroller.setOrientation(newOrientation); |
| refreshContentSize(0, 0); |
| |
| connectScrollBars(); |
| |
| update(); |
| } |
| |
| void XsheetViewer::positionSections() { |
| if (!isVisible()) return; |
| const Orientation *o = orientation(); |
| QRect size = QRect(QPoint(0, 0), geometry().size()); |
| NumberRange allLayer = o->layerSide(size); |
| NumberRange allFrame = o->frameSide(size); |
| |
| NumberRange headerLayer = o->range(PredefinedRange::HEADER_LAYER); |
| NumberRange headerFrame = o->range(PredefinedRange::HEADER_FRAME); |
| NumberRange bodyLayer(headerLayer.to(), allLayer.to()); |
| NumberRange bodyFrame(headerFrame.to(), allFrame.to()); |
| |
| if (Preferences::instance()->isShowXSheetToolbarEnabled()) { |
| m_toolbar->showToolbar(true); |
| int w = visibleRegion().boundingRect().width(); |
| m_toolbarScrollArea->setGeometry(0, 0, w, XsheetGUI::TOOLBAR_HEIGHT); |
| m_toolbar->setFixedWidth(w); |
| if (o->isVerticalTimeline()) { |
| headerFrame = headerFrame.adjusted(XsheetGUI::TOOLBAR_HEIGHT, |
| XsheetGUI::TOOLBAR_HEIGHT); |
| bodyFrame = bodyFrame.adjusted(XsheetGUI::TOOLBAR_HEIGHT, 0); |
| } else { |
| headerLayer = headerLayer.adjusted(XsheetGUI::TOOLBAR_HEIGHT, |
| XsheetGUI::TOOLBAR_HEIGHT); |
| bodyLayer = bodyLayer.adjusted(XsheetGUI::TOOLBAR_HEIGHT, 0); |
| } |
| } else { |
| m_toolbar->showToolbar(false); |
| } |
| |
| m_noteScrollArea->setGeometry(o->frameLayerRect(headerFrame, headerLayer)); |
| m_cellScrollArea->setGeometry(o->frameLayerRect(bodyFrame, bodyLayer)); |
| m_columnScrollArea->setGeometry( |
| o->frameLayerRect(headerFrame.adjusted(-1, -1), |
| bodyLayer.adjusted(0, -XsheetGUI::SCROLLBAR_WIDTH))); |
| m_rowScrollArea->setGeometry(o->frameLayerRect( |
| bodyFrame.adjusted(0, -XsheetGUI::SCROLLBAR_WIDTH), headerLayer)); |
| |
| if (o->isVerticalTimeline()) { |
| m_layerFooterPanel->setGeometry(m_columnScrollArea->geometry().right() + 1, |
| m_columnScrollArea->geometry().top(), 14, |
| m_columnScrollArea->height()); |
| } else { |
| m_layerFooterPanel->setGeometry(0, |
| m_columnScrollArea->geometry().bottom() + 1, |
| m_columnScrollArea->width(), 14); |
| } |
| |
| m_layerFooterPanel->showOrHide(o); |
| } |
| |
| void XsheetViewer::disconnectScrollBars() { |
| connectOrDisconnectScrollBars(false); |
| } |
| void XsheetViewer::connectScrollBars() { connectOrDisconnectScrollBars(true); } |
| |
| void XsheetViewer::connectOrDisconnectScrollBars(bool toConnect) { |
| const Orientation *o = orientation(); |
| bool isVertical = o->isVerticalTimeline(); |
| QWidget *scrolledVertically = |
| (isVertical ? m_rowScrollArea : m_columnScrollArea)->verticalScrollBar(); |
| QWidget *scrolledHorizontally = |
| (isVertical ? m_columnScrollArea : m_rowScrollArea) |
| ->horizontalScrollBar(); |
| |
| connectOrDisconnect(toConnect, scrolledVertically, SIGNAL(valueChanged(int)), |
| m_cellScrollArea->verticalScrollBar(), |
| SLOT(setValue(int))); |
| connectOrDisconnect(toConnect, m_cellScrollArea->verticalScrollBar(), |
| SIGNAL(valueChanged(int)), scrolledVertically, |
| SLOT(setValue(int))); |
| |
| connectOrDisconnect( |
| toConnect, scrolledHorizontally, SIGNAL(valueChanged(int)), |
| m_cellScrollArea->horizontalScrollBar(), SLOT(setValue(int))); |
| connectOrDisconnect(toConnect, m_cellScrollArea->horizontalScrollBar(), |
| SIGNAL(valueChanged(int)), scrolledHorizontally, |
| SLOT(setValue(int))); |
| |
| connectOrDisconnect( |
| toConnect, m_cellScrollArea->verticalScrollBar(), |
| SIGNAL(valueChanged(int)), this, |
| isVertical ? SLOT(updateCellRowAree()) : SLOT(updateCellColumnAree())); |
| connectOrDisconnect( |
| toConnect, m_cellScrollArea->horizontalScrollBar(), |
| SIGNAL(valueChanged(int)), this, |
| isVertical ? SLOT(updateCellColumnAree()) : SLOT(updateCellRowAree())); |
| } |
| |
| void XsheetViewer::connectOrDisconnect(bool toConnect, QWidget *sender, |
| const char *signal, QWidget *receiver, |
| const char *slot) { |
| if (toConnect) |
| connect(sender, signal, receiver, slot); |
| else |
| disconnect(sender, signal, receiver, slot); |
| } |
| |
| |
| |
| TXsheet *XsheetViewer::getXsheet() const { |
| return TApp::instance()->getCurrentXsheet()->getXsheet(); |
| } |
| |
| |
| |
| int XsheetViewer::getCurrentColumn() const { |
| return TApp::instance()->getCurrentColumn()->getColumnIndex(); |
| } |
| |
| |
| |
| int XsheetViewer::getCurrentRow() const { |
| return TApp::instance()->getCurrentFrame()->getFrame(); |
| } |
| |
| |
| |
| TStageObjectId XsheetViewer::getObjectId(int col) const { |
| TXsheet *xsh = getXsheet(); |
| if (col < 0) return TStageObjectId::CameraId(xsh->getCameraColumnIndex()); |
| return TStageObjectId::ColumnId(col); |
| } |
| |
| |
| void XsheetViewer::setCurrentColumn(int col) { |
| TColumnHandle *columnHandle = TApp::instance()->getCurrentColumn(); |
| if (col != columnHandle->getColumnIndex() || !columnHandle->getColumn()) { |
| columnHandle->setColumnIndex(col); |
| |
| |
| |
| TObjectHandle *objectHandle = TApp::instance()->getCurrentObject(); |
| if (col >= 0 && objectHandle->isSpline()) objectHandle->setIsSpline(false); |
| updateCellColumnAree(); |
| if (col >= 0) { |
| objectHandle->setObjectId(TStageObjectId::ColumnId(col)); |
| TXsheet *xsh = getXsheet(); |
| TXshColumn *column = xsh->getColumn(col); |
| if (!column || !column->getZeraryFxColumn()) return; |
| TFx *fx = column->getZeraryFxColumn()->getZeraryColumnFx(); |
| TApp::instance()->getCurrentFx()->setFx(fx); |
| } |
| return; |
| } |
| } |
| |
| |
| |
| void XsheetViewer::setCurrentRow(int row) { |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| TApp::instance()->getCurrentFrame()->setFrame(row); |
| } |
| |
| |
| |
| void XsheetViewer::scroll(QPoint delta) { |
| int x = delta.x(); |
| int y = delta.y(); |
| |
| int valueH = m_cellScrollArea->horizontalScrollBar()->value() + x; |
| int valueV = m_cellScrollArea->verticalScrollBar()->value() + y; |
| int maxValueH = m_cellScrollArea->horizontalScrollBar()->maximum(); |
| int maxValueV = m_cellScrollArea->verticalScrollBar()->maximum(); |
| |
| bool notUpdateSizeH = maxValueH > valueH && x >= 0; |
| bool notUpdateSizeV = maxValueV > valueV && y >= 0; |
| if (!notUpdateSizeH && !notUpdateSizeV) |
| refreshContentSize(x, y); |
| else if (notUpdateSizeH && !notUpdateSizeV) |
| refreshContentSize(0, y); |
| else if (!notUpdateSizeH && notUpdateSizeV) |
| refreshContentSize(x, 0); |
| |
| |
| if (!notUpdateSizeH) |
| maxValueH = m_cellScrollArea->horizontalScrollBar()->maximum(); |
| if (!notUpdateSizeV) |
| maxValueV = m_cellScrollArea->verticalScrollBar()->maximum(); |
| |
| if (valueH > maxValueH && x > 0) |
| |
| valueH = m_cellScrollArea->horizontalScrollBar()->maximum(); |
| |
| if (valueV > maxValueV && y > 0) |
| |
| valueV = m_cellScrollArea->verticalScrollBar()->maximum(); |
| |
| m_cellScrollArea->horizontalScrollBar()->setValue(valueH); |
| m_cellScrollArea->verticalScrollBar()->setValue(valueV); |
| } |
| |
| |
| |
| int XsheetViewer::getColumnScrollValue() { |
| return m_columnScrollArea->horizontalScrollBar()->value(); |
| } |
| |
| |
| |
| void XsheetViewer::onPrepareToScrollOffset(const QPointF &offset) { |
| refreshContentSize((int)offset.x(), (int)offset.y()); |
| } |
| |
| |
| |
| void XsheetViewer::onZoomScrollAdjust(QPointF &offset, bool toZoom) { |
| double frameZoomFactor = (double)getFrameZoomFactor(); |
| |
| if (orientation()->isVerticalTimeline()) { |
| |
| |
| double newY; |
| if (toZoom) |
| newY = (offset.y() * frameZoomFactor) / 100.0; |
| else |
| newY = (offset.y() * 100.0) / frameZoomFactor; |
| |
| offset.setY(newY); |
| } else { |
| |
| |
| double newX; |
| if (toZoom) |
| newX = (offset.x() * frameZoomFactor) / 100.0; |
| else |
| newX = (offset.x() * 100.0) / frameZoomFactor; |
| |
| offset.setX(newX); |
| } |
| } |
| |
| |
| |
| void XsheetViewer::setAutoPanSpeed(const QPoint &speed) { |
| bool wasAutoPanning = isAutoPanning(); |
| m_autoPanSpeed = speed; |
| if (isAutoPanning() && !wasAutoPanning && m_timerId == 0) |
| m_timerId = startTimer(40); |
| else if (!isAutoPanning() && wasAutoPanning && m_timerId != 0) { |
| killTimer(m_timerId); |
| m_timerId = 0; |
| } |
| } |
| |
| |
| |
| static int getAutoPanSpeed(int pixels) { |
| int f = 40; |
| return std::min(100, (f - 1 + pixels * f) / 100); |
| } |
| |
| |
| |
| void XsheetViewer::setAutoPanSpeed(const QRect &widgetBounds, |
| const QPoint &mousePos) { |
| QPoint speed; |
| int limit = 100, factor = 30; |
| if (mousePos.x() < widgetBounds.left()) |
| speed.setX(-getAutoPanSpeed(widgetBounds.left() - mousePos.x())); |
| else if (mousePos.x() > widgetBounds.right()) |
| speed.setX(getAutoPanSpeed(mousePos.x() - widgetBounds.right())); |
| if (mousePos.y() < widgetBounds.top()) |
| speed.setY(-getAutoPanSpeed(widgetBounds.top() - mousePos.y())); |
| else if (mousePos.y() > widgetBounds.bottom()) |
| speed.setY(getAutoPanSpeed(mousePos.y() - widgetBounds.bottom())); |
| setAutoPanSpeed(speed); |
| m_lastAutoPanPos = mousePos; |
| } |
| |
| |
| |
| void XsheetViewer::timerEvent(QTimerEvent *) { |
| if (!isAutoPanning()) return; |
| scroll(m_autoPanSpeed); |
| if (!m_dragTool) return; |
| QMouseEvent mouseEvent(QEvent::MouseMove, m_lastAutoPanPos - m_autoPanSpeed, |
| Qt::NoButton, 0, m_qtModifiers); |
| m_dragTool->onDrag(&mouseEvent); |
| m_lastAutoPanPos += m_autoPanSpeed; |
| } |
| |
| |
| |
| |
| bool XsheetViewer::refreshContentSize(int dx, int dy) { |
| QSize viewportSize = m_cellScrollArea->viewport()->size(); |
| QPoint offset = m_cellArea->pos(); |
| offset = QPoint(std::min(0, offset.x() - dx), |
| std::min(0, offset.y() - dy)); |
| |
| TXsheet *xsh = getXsheet(); |
| int frameCount = xsh ? xsh->getFrameCount() : 0; |
| int columnCount = xsh ? xsh->getColumnCount() : 0; |
| QPoint contentSize; |
| |
| if (m_orientation->isVerticalTimeline()) |
| contentSize = positionToXY(CellPosition(frameCount + 1, columnCount + 1)); |
| else { |
| int firstCol = |
| Preferences::instance()->isXsheetCameraColumnVisible() ? -1 : 0; |
| contentSize = positionToXY(CellPosition(frameCount + 1, firstCol)); |
| |
| ColumnFan *fan = xsh->getColumnFan(m_orientation); |
| contentSize.setY(contentSize.y() + 1 + |
| (fan->isActive(firstCol) |
| ? m_orientation->cellHeight() |
| : m_orientation->foldedCellSize())); |
| } |
| |
| QSize actualSize(contentSize.x(), contentSize.y()); |
| int x = viewportSize.width() - offset.x(); |
| int y = viewportSize.height() - offset.y(); |
| if (x > actualSize.width()) actualSize.setWidth(x); |
| if (m_orientation->isVerticalTimeline() && y > actualSize.height()) |
| actualSize.setHeight(y); |
| |
| if (actualSize == m_cellArea->size()) |
| return false; |
| else { |
| const Orientation *o = orientation(); |
| NumberRange allLayer = o->layerSide(QRect(QPoint(0, 0), actualSize)); |
| NumberRange allFrame = o->frameSide(QRect(QPoint(0, 0), actualSize)); |
| NumberRange headerLayer = o->range(PredefinedRange::HEADER_LAYER); |
| NumberRange headerFrame = o->range(PredefinedRange::HEADER_FRAME); |
| |
| m_isComputingSize = true; |
| m_noteArea->setFixedSize(o->rect(PredefinedRect::NOTE_AREA).size()); |
| m_cellArea->setFixedSize(actualSize); |
| m_rowArea->setFixedSize(o->frameLayerRect(allFrame, headerLayer).size()); |
| m_columnArea->setFixedSize(o->frameLayerRect(headerFrame, allLayer).size()); |
| m_isComputingSize = false; |
| return true; |
| } |
| } |
| |
| |
| |
| |
| void XsheetViewer::updateAreeSize() { |
| const Orientation *o = orientation(); |
| QRect viewArea(QPoint(0, 0), m_cellScrollArea->geometry() |
| .adjusted(0, 0, -XsheetGUI::SCROLLBAR_WIDTH, |
| -XsheetGUI::SCROLLBAR_WIDTH) |
| .size()); |
| |
| QPoint areaFilled(0, 0); |
| TXsheet *xsh = getXsheet(); |
| if (xsh) { |
| if (o->isVerticalTimeline()) |
| areaFilled = positionToXY( |
| CellPosition(xsh->getFrameCount() + 1, xsh->getColumnCount() + 1)); |
| else { |
| int firstCol = |
| Preferences::instance()->isXsheetCameraColumnVisible() ? -1 : 0; |
| areaFilled = |
| positionToXY(CellPosition(xsh->getFrameCount() + 1, firstCol)); |
| |
| ColumnFan *fan = xsh->getColumnFan(m_orientation); |
| areaFilled.setY( |
| areaFilled.y() + 1 + |
| (fan->isActive(firstCol) ? o->cellHeight() : o->foldedCellSize())); |
| } |
| } |
| if (viewArea.width() < areaFilled.x()) viewArea.setWidth(areaFilled.x()); |
| if (viewArea.height() < areaFilled.y() || |
| (!o->isVerticalTimeline() && viewArea.height() != areaFilled.y())) |
| viewArea.setHeight(areaFilled.y()); |
| |
| NumberRange allLayer = o->layerSide(viewArea); |
| NumberRange allFrame = o->frameSide(viewArea); |
| NumberRange headerLayer = o->range(PredefinedRange::HEADER_LAYER); |
| NumberRange headerFrame = o->range(PredefinedRange::HEADER_FRAME); |
| |
| m_cellArea->setFixedSize(viewArea.size()); |
| m_rowArea->setFixedSize(o->frameLayerRect(allFrame, headerLayer).size()); |
| m_columnArea->setFixedSize(o->frameLayerRect(headerFrame, allLayer).size()); |
| } |
| |
| |
| |
| int XsheetViewer::colToTimelineLayerAxis(int layer) const { |
| const Orientation *o = orientation(); |
| TXsheet *xsh = getXsheet(); |
| if (!xsh) return 0; |
| ColumnFan *fan = xsh->getColumnFan(o); |
| |
| int yBottom = o->colToLayerAxis(layer, fan) + |
| (fan->isActive(layer) ? o->cellHeight() : o->foldedCellSize()) - |
| 1; |
| int columnCount = std::max(1, xsh->getColumnCount()); |
| int layerHeightActual = |
| m_columnArea->height() - 2; |
| |
| return layerHeightActual - yBottom; |
| } |
| |
| |
| |
| CellPosition XsheetViewer::xyToPosition(const QPoint &point) const { |
| const Orientation *o = orientation(); |
| QPoint usePoint = point; |
| TXsheet *xsh = getXsheet(); |
| |
| if (!xsh) return CellPosition(0, 0); |
| |
| ColumnFan *fan = xsh->getColumnFan(o); |
| |
| if (o->isVerticalTimeline()) |
| usePoint.setY((usePoint.y() * 100) / getFrameZoomFactor()); |
| else |
| usePoint.setX((usePoint.x() * 100) / getFrameZoomFactor()); |
| |
| if (o->isVerticalTimeline()) return o->xyToPosition(usePoint, fan); |
| |
| |
| |
| |
| int columnCount = std::max(1, xsh->getColumnCount()); |
| int colAreaHeight = o->colToLayerAxis(columnCount, fan); |
| |
| usePoint.setY(colAreaHeight - usePoint.y()); |
| |
| CellPosition resultCP = o->xyToPosition(usePoint, fan); |
| if (point.y() > colAreaHeight) { |
| int colsBelow = ((point.y() - colAreaHeight) / o->cellHeight()) + 1; |
| resultCP.setLayer(-colsBelow); |
| } |
| return resultCP; |
| } |
| CellPosition XsheetViewer::xyToPosition(const TPoint &point) const { |
| return xyToPosition(QPoint(point.x, point.y)); |
| } |
| CellPosition XsheetViewer::xyToPosition(const TPointD &point) const { |
| return xyToPosition(QPoint((int)point.x, (int)point.y)); |
| } |
| |
| |
| |
| QPoint XsheetViewer::positionToXY(const CellPosition &pos) const { |
| const Orientation *o = orientation(); |
| TXsheet *xsh = getXsheet(); |
| if (!xsh) return QPoint(0, 0); |
| ColumnFan *fan = xsh->getColumnFan(o); |
| QPoint usePoint = o->positionToXY(pos, fan); |
| |
| if (o->isVerticalTimeline()) |
| usePoint.setY((usePoint.y() * getFrameZoomFactor()) / 100); |
| else |
| usePoint.setX((usePoint.x() * getFrameZoomFactor()) / 100); |
| |
| if (o->isVerticalTimeline()) return usePoint; |
| |
| |
| |
| |
| |
| usePoint.setY( |
| usePoint.y() - o->cellHeight() + |
| (fan->isActive(pos.layer()) ? o->cellHeight() : o->foldedCellSize())); |
| int columnCount = std::max(1, xsh->getColumnCount()); |
| int colsHeight = o->colToLayerAxis(columnCount, fan); |
| |
| if (colsHeight) |
| usePoint.setY(colsHeight - usePoint.y() - o->cellHeight()); |
| else |
| usePoint.setY(0); |
| |
| return usePoint; |
| } |
| |
| int XsheetViewer::columnToLayerAxis(int layer) const { |
| const Orientation *o = orientation(); |
| TXsheet *xsh = getXsheet(); |
| if (!xsh) return 0; |
| if (o->isVerticalTimeline()) |
| return o->colToLayerAxis(layer, xsh->getColumnFan(o)); |
| else |
| return colToTimelineLayerAxis(layer); |
| } |
| int XsheetViewer::rowToFrameAxis(int frame) const { |
| int result = orientation()->rowToFrameAxis(frame); |
| |
| result = (result * getFrameZoomFactor()) / 100; |
| return result; |
| } |
| |
| |
| |
| CellRange XsheetViewer::xyRectToRange(const QRect &rect) const { |
| CellPosition topLeft = xyToPosition(rect.topLeft()); |
| CellPosition bottomRight = xyToPosition(rect.bottomRight()); |
| return CellRange(topLeft, bottomRight); |
| } |
| |
| |
| |
| QRect XsheetViewer::rangeToXYRect(const CellRange &range) const { |
| QPoint from = positionToXY(range.from()); |
| QPoint to = positionToXY(range.to()); |
| QPoint topLeft = |
| QPoint(std::min(from.x(), to.x()), std::min(from.y(), to.y())); |
| QPoint bottomRight = |
| QPoint(std::max(from.x(), to.x()), std::max(from.y(), to.y())); |
| return QRect(topLeft, bottomRight); |
| } |
| |
| |
| |
| void XsheetViewer::drawPredefinedPath(QPainter &p, PredefinedPath which, |
| const CellPosition &pos, |
| optional<QColor> fill, |
| optional<QColor> outline) const { |
| QPoint xy = positionToXY(pos); |
| QPainterPath path = orientation()->path(which).translated(xy); |
| if (fill) p.fillPath(path, QBrush(*fill)); |
| if (outline) { |
| p.setPen(*outline); |
| p.drawPath(path); |
| } |
| } |
| |
| |
| |
| void XsheetViewer::drawPredefinedPath(QPainter &p, PredefinedPath which, |
| QPoint xy, optional<QColor> fill, |
| optional<QColor> outline) const { |
| QPainterPath path = orientation()->path(which).translated(xy); |
| if (fill) p.fillPath(path, QBrush(*fill)); |
| if (outline) { |
| p.setPen(*outline); |
| p.drawPath(path); |
| } |
| } |
| |
| |
| |
| bool XsheetViewer::areCellsSelectedEmpty() { |
| int r0, c0, r1, c1; |
| getCellSelection()->getSelectedCells(r0, c0, r1, c1); |
| int i, j; |
| for (i = r0; i <= r1; i++) |
| for (j = c0; j <= c1; j++) |
| if (!getXsheet()->getCell(i, j).isEmpty()) return false; |
| return true; |
| } |
| |
| |
| |
| bool XsheetViewer::areSoundCellsSelected() { |
| int r0, c0, r1, c1; |
| getCellSelection()->getSelectedCells(r0, c0, r1, c1); |
| if (c0 < 0) return false; |
| int i, j; |
| for (i = r0; i <= r1; i++) |
| for (j = c0; j <= c1; j++) { |
| TXshCell cell = getXsheet()->getCell(i, j); |
| if (cell.isEmpty() || cell.getSoundLevel()) continue; |
| return false; |
| } |
| return !areCellsSelectedEmpty(); |
| } |
| |
| |
| |
| bool XsheetViewer::areSoundTextCellsSelected() { |
| int r0, c0, r1, c1; |
| getCellSelection()->getSelectedCells(r0, c0, r1, c1); |
| if (c0 < 0) return false; |
| int i, j; |
| for (i = r0; i <= r1; i++) |
| for (j = c0; j <= c1; j++) { |
| TXshCell cell = getXsheet()->getCell(i, j); |
| if (cell.isEmpty() || cell.getSoundTextLevel()) continue; |
| return false; |
| } |
| return !areCellsSelectedEmpty(); |
| } |
| |
| |
| |
| bool XsheetViewer::areCameraCellsSelected() { |
| int r0, c0, r1, c1; |
| getCellSelection()->getSelectedCells(r0, c0, r1, c1); |
| return c0 < 0; |
| } |
| |
| |
| |
| void XsheetViewer::setScrubHighlight(int row, int startRow, int col) { |
| if (m_scrubCol == -1) m_scrubCol = col; |
| m_scrubRow0 = std::min(row, startRow); |
| m_scrubRow1 = std::max(row, startRow); |
| return; |
| } |
| |
| |
| |
| void XsheetViewer::resetScrubHighlight() { |
| m_scrubCol = m_scrubRow0 = m_scrubRow1 = -1; |
| return; |
| } |
| |
| |
| |
| void XsheetViewer::getScrubHeighlight(int &R0, int &R1) { |
| R0 = m_scrubRow0; |
| R1 = m_scrubRow1; |
| return; |
| } |
| |
| |
| |
| bool XsheetViewer::isScrubHighlighted(int row, int col) { |
| if (m_scrubCol == col && m_scrubRow0 <= row && row <= m_scrubRow1) |
| return true; |
| return false; |
| } |
| |
| |
| |
| void XsheetViewer::showEvent(QShowEvent *) { |
| m_frameScroller.registerFrameScroller(); |
| if (m_isCurrentFrameSwitched) onCurrentFrameSwitched(); |
| if (m_isCurrentColumnSwitched) onCurrentColumnSwitched(); |
| m_isCurrentFrameSwitched = false; |
| |
| TApp *app = TApp::instance(); |
| |
| bool ret = connect(app->getCurrentColumn(), SIGNAL(columnIndexSwitched()), |
| this, SLOT(onCurrentColumnSwitched())); |
| ret = ret && connect(app->getCurrentFrame(), SIGNAL(frameSwitched()), this, |
| SLOT(onCurrentFrameSwitched())); |
| ret = ret && connect(app->getCurrentFrame(), SIGNAL(isPlayingStatusChanged()), |
| this, SLOT(onPlayingStatusChanged())); |
| ret = ret && connect(app->getCurrentFrame(), SIGNAL(scrubStopped()), this, |
| SLOT(onScrubStopped())); |
| |
| ret = ret && connect(app->getCurrentObject(), SIGNAL(objectChanged(bool)), |
| this, SLOT(updateAllAree(bool))); |
| |
| TSceneHandle *sceneHandle = app->getCurrentScene(); |
| ret = ret && connect(sceneHandle, SIGNAL(sceneSwitched()), this, |
| SLOT(onSceneSwitched())); |
| ret = ret && connect(sceneHandle, SIGNAL(nameSceneChanged()), this, |
| SLOT(changeWindowTitle())); |
| ret = ret && connect(sceneHandle, SIGNAL(preferenceChanged(const QString &)), |
| this, SLOT(onPreferenceChanged(const QString &))); |
| |
| TXsheetHandle *xsheetHandle = app->getCurrentXsheet(); |
| ret = ret && connect(xsheetHandle, SIGNAL(xsheetSwitched()), this, |
| SLOT(updateAllAree())); |
| ret = ret && connect(xsheetHandle, SIGNAL(xsheetSwitched()), this, |
| SLOT(resetXsheetNotes())); |
| ret = ret && connect(xsheetHandle, SIGNAL(xsheetChanged()), this, |
| SLOT(onXsheetChanged())); |
| ret = ret && connect(xsheetHandle, SIGNAL(xsheetChanged()), this, |
| SLOT(changeWindowTitle())); |
| |
| ret = ret && |
| connect(app->getCurrentSelection(), |
| SIGNAL(selectionSwitched(TSelection *, TSelection *)), this, |
| SLOT(onSelectionSwitched(TSelection *, TSelection *))); |
| |
| ret = ret && connect(app->getCurrentSelection(), |
| SIGNAL(selectionChanged(TSelection *)), this, |
| SLOT(onSelectionChanged(TSelection *))); |
| |
| ret = ret && |
| connect(app->getCurrentLevel(), SIGNAL(xshLevelSwitched(TXshLevel *)), |
| this, SLOT(changeWindowTitle())); |
| |
| ret = ret && connect(IconGenerator::instance(), SIGNAL(iconGenerated()), this, |
| SLOT(updateColumnArea())); |
| |
| assert(ret); |
| refreshContentSize(0, 0); |
| changeWindowTitle(); |
| |
| xsheetHandle->notifyZoomScaleChanged(m_frameZoomFactor); |
| } |
| |
| |
| |
| void XsheetViewer::hideEvent(QHideEvent *) { |
| m_frameScroller.unregisterFrameScroller(); |
| |
| TApp *app = TApp::instance(); |
| |
| disconnect(app->getCurrentColumn(), SIGNAL(columnIndexSwitched()), this, |
| SLOT(onCurrentColumnSwitched())); |
| disconnect(app->getCurrentFrame(), SIGNAL(frameSwitched()), this, |
| SLOT(onCurrentFrameSwitched())); |
| disconnect(app->getCurrentFrame(), SIGNAL(scrubStopped()), this, |
| SLOT(onScrubStopped())); |
| |
| disconnect(app->getCurrentObject(), SIGNAL(objectChanged(bool)), this, |
| SLOT(updateAllAree(bool))); |
| |
| TSceneHandle *sceneHandle = app->getCurrentScene(); |
| disconnect(sceneHandle, SIGNAL(sceneSwitched()), this, |
| SLOT(onSceneSwitched())); |
| disconnect(sceneHandle, SIGNAL(nameSceneChanged()), this, |
| SLOT(changeWindowTitle())); |
| |
| TXsheetHandle *xsheetHandle = app->getCurrentXsheet(); |
| disconnect(xsheetHandle, SIGNAL(xsheetSwitched()), this, |
| SLOT(updateAllAree())); |
| disconnect(xsheetHandle, SIGNAL(xsheetChanged()), this, |
| SLOT(onXsheetChanged())); |
| disconnect(xsheetHandle, SIGNAL(xsheetChanged()), this, |
| SLOT(changeWindowTitle())); |
| |
| disconnect(app->getCurrentSelection(), |
| SIGNAL(selectionSwitched(TSelection *, TSelection *)), this, |
| SLOT(onSelectionSwitched(TSelection *, TSelection *))); |
| |
| disconnect(app->getCurrentSelection(), SIGNAL(selectionChanged(TSelection *)), |
| this, SLOT(onSelectionChanged(TSelection *))); |
| |
| disconnect(app->getCurrentLevel(), SIGNAL(xshLevelSwitched(TXshLevel *)), |
| this, SLOT(changeWindowTitle())); |
| |
| disconnect(IconGenerator::instance(), SIGNAL(iconGenerated()), this, |
| SLOT(updateColumnArea())); |
| |
| xsheetHandle->notifyZoomScaleChanged(100); |
| } |
| |
| |
| |
| void XsheetViewer::resizeEvent(QResizeEvent *event) { |
| positionSections(); |
| |
| |
| refreshContentSize( |
| 0, |
| 0); |
| updateAllAree(); |
| } |
| |
| |
| |
| void XsheetViewer::wheelEvent(QWheelEvent *event) { |
| switch (event->source()) { |
| case Qt::MouseEventNotSynthesized: { |
| if (0 != (event->modifiers() & Qt::ControlModifier) && |
| event->angleDelta().y() != 0) { |
| QPoint pos(event->pos().x() - m_columnArea->geometry().width() + |
| m_cellArea->visibleRegion().boundingRect().left(), |
| event->pos().y()); |
| int targetFrame = xyToPosition(pos).frame(); |
| |
| int newFactor = |
| getFrameZoomFactor() + ((event->angleDelta().y() > 0 ? 1 : -1) * 10); |
| if (newFactor > XsheetGUI::ZOOM_FACTOR_MAX) |
| newFactor = XsheetGUI::ZOOM_FACTOR_MAX; |
| else if (newFactor < XsheetGUI::ZOOM_FACTOR_MIN) |
| newFactor = XsheetGUI::ZOOM_FACTOR_MIN; |
| zoomOnFrame(targetFrame, newFactor); |
| |
| event->accept(); |
| return; |
| } |
| |
| int markerDistance = 0, markerOffset = 0, secDistance; |
| TApp::instance() |
| ->getCurrentScene() |
| ->getScene() |
| ->getProperties() |
| ->getMarkers(markerDistance, markerOffset, secDistance); |
| |
| if (event->angleDelta().x() == 0) { |
| if (!orientation()->isVerticalTimeline()) markerDistance = 1; |
| int scrollPixels = (event->angleDelta().y() > 0 ? 1 : -1) * |
| markerDistance * orientation()->cellHeight(); |
| scroll(QPoint(0, -scrollPixels)); |
| } else { |
| if (orientation()->isVerticalTimeline()) markerDistance = 1; |
| int scrollPixels = (event->angleDelta().x() > 0 ? 1 : -1) * |
| markerDistance * orientation()->cellWidth(); |
| scroll(QPoint(-scrollPixels, 0)); |
| } |
| break; |
| } |
| |
| case Qt::MouseEventSynthesizedBySystem: |
| { |
| QPoint numPixels = event->pixelDelta(); |
| QPoint numDegrees = event->angleDelta() / 8; |
| if (!numPixels.isNull()) { |
| scroll(-numPixels); |
| } else if (!numDegrees.isNull()) { |
| QPoint numSteps = numDegrees / 15; |
| scroll(-numSteps); |
| } |
| break; |
| } |
| |
| default: |
| |
| { |
| std::cout << "not supported event: Qt::MouseEventSynthesizedByQt, " |
| "Qt::MouseEventSynthesizedByApplication" |
| << std::endl; |
| break; |
| } |
| |
| } |
| } |
| |
| |
| |
| void XsheetViewer::keyPressEvent(QKeyEvent *event) { |
| struct Locals { |
| XsheetViewer *m_this; |
| |
| void scrollVertTo(double y, const QRect &visibleRect) { |
| int deltaY = (y < visibleRect.top()) ? y - visibleRect.top() |
| : y - visibleRect.bottom(); |
| |
| m_this->scroll(QPoint(0, deltaY)); |
| } |
| |
| void scrollHorizTo(double x, const QRect &visibleRect) { |
| int deltaX = (x < visibleRect.left()) ? x - visibleRect.left() |
| : x - visibleRect.right(); |
| |
| m_this->scroll(QPoint(deltaX, 0)); |
| } |
| } locals = {this}; |
| |
| if (changeFrameSkippingHolds(event)) return; |
| |
| int frameCount = getXsheet()->getFrameCount(); |
| CellPosition now(getCurrentRow(), getCurrentColumn()); |
| CellPosition shift = orientation()->arrowShift(event->key()); |
| CellPosition stride(1, 1); |
| |
| TCellSelection *cellSel = |
| dynamic_cast<TCellSelection *>(TSelection::getCurrent()); |
| int firstCol = |
| Preferences::instance()->isXsheetCameraColumnVisible() ? -1 : 0; |
| |
| |
| if (Preferences::instance()->isUseArrowKeyToShiftCellSelectionEnabled() && |
| cellSel && !cellSel->isEmpty()) { |
| int r0, c0, r1, c1; |
| cellSel->getSelectedCells(r0, c0, r1, c1); |
| stride.setFrame(cellSel->getSelectedCells().getRowCount()); |
| |
| if (m_cellArea->isControlPressed()) { |
| if (r0 == r1 && shift.frame() < 0) return; |
| if (c0 == c1 && shift.layer() < firstCol) return; |
| cellSel->selectCells(r0, c0, r1 + shift.frame(), c1 + shift.layer()); |
| updateCells(); |
| TApp::instance()->getCurrentSelection()->notifySelectionChanged(); |
| return; |
| } else { |
| CellPosition offset(shift * stride); |
| int movedR0 = std::max(0, r0 + offset.frame()); |
| int movedC0 = std::max(firstCol, c0 + offset.layer()); |
| int diffFrame = movedR0 - r0; |
| int diffLayer = movedC0 - c0; |
| cellSel->selectCells(r0 + diffFrame, c0 + diffLayer, r1 + diffFrame, |
| c1 + diffLayer); |
| TApp::instance()->getCurrentSelection()->notifySelectionChanged(); |
| } |
| } |
| |
| if (shift) { |
| now = now + shift * stride; |
| now.ensureValid(); |
| if (now.layer() < firstCol) now.setLayer(firstCol); |
| setCurrentRow(now.frame()); |
| setCurrentColumn(now.layer()); |
| return; |
| } |
| |
| switch (int key = event->key()) { |
| case Qt::Key_Control: |
| |
| m_cellArea->onControlPressed(true); |
| m_columnArea->onControlPressed(true); |
| m_layerFooterPanel->onControlPressed(true); |
| break; |
| |
| default: { |
| QRect visibleRect = m_cellArea->visibleRegion().boundingRect(); |
| int visibleRowCount = visibleRect.height() / orientation()->cellHeight(); |
| |
| switch (key) { |
| case Qt::Key_PageUp: |
| locals.scrollVertTo( |
| visibleRect.top() - visibleRowCount * orientation()->cellHeight(), |
| visibleRect); |
| break; |
| case Qt::Key_PageDown: |
| locals.scrollVertTo( |
| visibleRect.bottom() + visibleRowCount * orientation()->cellHeight(), |
| visibleRect); |
| break; |
| case Qt::Key_Home: |
| if (orientation()->isVerticalTimeline()) |
| locals.scrollVertTo(0, visibleRect); |
| else |
| locals.scrollHorizTo(0, visibleRect); |
| |
| break; |
| case Qt::Key_End: |
| if (orientation()->isVerticalTimeline()) { |
| int y = (((frameCount + 1) * orientation()->cellHeight()) * |
| getFrameZoomFactor()) / |
| 100; |
| locals.scrollVertTo(y, visibleRect); |
| } else { |
| int x = (((frameCount + 1) * orientation()->cellWidth()) * |
| getFrameZoomFactor()) / |
| 100; |
| locals.scrollHorizTo(x, visibleRect); |
| } |
| break; |
| } |
| break; |
| } |
| } |
| } |
| |
| |
| |
| void XsheetViewer::keyReleaseEvent(QKeyEvent *event) { |
| if (event->key() == Qt::Key_Control) { |
| m_cellArea->onControlPressed(false); |
| m_columnArea->onControlPressed(false); |
| m_layerFooterPanel->onControlPressed(false); |
| } |
| } |
| |
| void XsheetViewer::enterEvent(QEvent *) { |
| m_cellArea->onControlPressed(false); |
| m_columnArea->onControlPressed(false); |
| TApp *app = TApp::instance(); |
| app->setCurrentXsheetViewer(this); |
| } |
| |
| |
| |
| |
| void XsheetViewer::scrollTo(int row, int col) { |
| QRect visibleRect = m_cellArea->visibleRegion().boundingRect(); |
| QPoint topLeft = positionToXY(CellPosition(row, col)); |
| QRect cellRect( |
| topLeft, QSize(orientation()->cellWidth(), orientation()->cellHeight())); |
| |
| int deltaX = 0; |
| int deltaY = 0; |
| |
| if (cellRect.left() < visibleRect.left()) |
| deltaX = cellRect.left() - visibleRect.left(); |
| else if (cellRect.right() > visibleRect.right()) |
| deltaX = cellRect.left() - visibleRect.left(); |
| |
| if (cellRect.top() < visibleRect.top()) |
| deltaY = cellRect.top() - visibleRect.top(); |
| else if (cellRect.bottom() > visibleRect.bottom()) |
| deltaY = cellRect.bottom() - visibleRect.bottom(); |
| |
| if (deltaX != 0 || deltaY != 0) { |
| scroll(QPoint(deltaX, deltaY)); |
| } |
| } |
| |
| |
| |
| void XsheetViewer::onSceneSwitched() { |
| refreshContentSize(0, 0); |
| updateAreeSize(); |
| updateAllAree(); |
| clearNoteWidgets(); |
| m_noteArea->updateButtons(); |
| } |
| |
| |
| |
| void XsheetViewer::onXsheetChanged() { |
| refreshContentSize(0, 0); |
| updateAllAree(); |
| |
| int row = TApp::instance()->getCurrentFrame()->getFrame(); |
| TXsheet *xsh = getXsheet(); |
| NavigationTags *navTags = xsh->getNavigationTags(); |
| int lastTag = navTags->getPrevTag(INT_MAX); |
| int firstTag = navTags->getNextTag(-1); |
| CommandManager::instance()->enable(MI_NextTaggedFrame, (row < lastTag)); |
| CommandManager::instance()->enable(MI_PrevTaggedFrame, |
| firstTag != -1 && row > firstTag); |
| CommandManager::instance()->enable(MI_EditTaggedFrame, |
| navTags->isTagged(row)); |
| CommandManager::instance()->enable(MI_ClearTags, (navTags->getCount() > 0)); |
| } |
| |
| |
| |
| void XsheetViewer::onPreferenceChanged(const QString &prefName) { |
| if (prefName == "XSheetToolbar") { |
| positionSections(); |
| refreshContentSize(0, 0); |
| } else if (prefName == "XsheetCamera") { |
| refreshContentSize(0, 0); |
| } |
| } |
| |
| |
| |
| void XsheetViewer::onCurrentFrameSwitched() { |
| int row = TApp::instance()->getCurrentFrame()->getFrame(); |
| QRect visibleRect = m_cellArea->visibleRegion().boundingRect(); |
| if (visibleRect.isEmpty()) { |
| m_isCurrentFrameSwitched = true; |
| return; |
| } |
| m_isCurrentFrameSwitched = false; |
| scrollToRow(row); |
| |
| TXsheet *xsh = getXsheet(); |
| NavigationTags *navTags = xsh->getNavigationTags(); |
| int lastTag = navTags->getPrevTag(INT_MAX); |
| int firstTag = navTags->getNextTag(-1); |
| CommandManager::instance()->enable(MI_NextTaggedFrame, (row < lastTag)); |
| CommandManager::instance()->enable(MI_PrevTaggedFrame, |
| firstTag != -1 && row > firstTag); |
| CommandManager::instance()->enable(MI_EditTaggedFrame, |
| navTags->isTagged(row)); |
| } |
| |
| |
| |
| void XsheetViewer::onPlayingStatusChanged() { |
| if (!Preferences::instance()->isXsheetAutopanEnabled()) |
| onCurrentFrameSwitched(); |
| } |
| |
| |
| |
| void XsheetViewer::onCurrentColumnSwitched() { |
| int col = TApp::instance()->getCurrentColumn()->getColumnIndex(); |
| QRect visibleRect = m_columnArea->visibleRegion().boundingRect(); |
| if (visibleRect.isEmpty()) { |
| m_isCurrentColumnSwitched = true; |
| return; |
| } |
| m_isCurrentColumnSwitched = false; |
| scrollToColumn(col); |
| } |
| |
| |
| |
| void XsheetViewer::scrollToColumn(int col) { |
| int colNext = col + (m_orientation->isVerticalTimeline() ? 1 : -1); |
| if (colNext < 0) colNext = -1; |
| int x0 = columnToLayerAxis(col); |
| int x1 = columnToLayerAxis(colNext); |
| |
| if (orientation()->isVerticalTimeline()) |
| scrollToHorizontalRange(x0, x1); |
| else { |
| if (colNext == col) x1 += m_orientation->cellHeight(); |
| |
| scrollToVerticalRange(x0, x1); |
| } |
| } |
| |
| |
| |
| void XsheetViewer::scrollToHorizontalRange(int x0, int x1) { |
| QRect visibleRect = m_cellArea->visibleRegion().boundingRect(); |
| if (visibleRect.isEmpty()) return; |
| int visibleLeft = visibleRect.left(); |
| int visibleRight = visibleRect.right(); |
| |
| if (visibleLeft > x0) { |
| int deltaX = x0 - visibleLeft; |
| if (!TApp::instance()->getCurrentFrame()->isPlaying() || |
| Preferences::instance()->isXsheetAutopanEnabled()) { |
| scroll(QPoint(deltaX, 0)); |
| return; |
| } |
| } |
| if (visibleRight < x1) { |
| int deltaX = x1 + 2 - visibleRight; |
| if (!TApp::instance()->getCurrentFrame()->isPlaying() || |
| Preferences::instance()->isXsheetAutopanEnabled()) { |
| scroll(QPoint(deltaX, 0)); |
| return; |
| } |
| } |
| if (orientation()->isVerticalTimeline()) |
| updateCellColumnAree(); |
| else |
| updateCellRowAree(); |
| } |
| |
| |
| |
| void XsheetViewer::scrollToRow(int row) { |
| int y0 = rowToFrameAxis(row); |
| int y1 = rowToFrameAxis(row + 1); |
| |
| if (orientation()->isVerticalTimeline()) |
| scrollToVerticalRange(y0, y1); |
| else |
| scrollToHorizontalRange(y0, y1); |
| } |
| |
| |
| |
| void XsheetViewer::scrollToVerticalRange(int y0, int y1) { |
| int yMin = std::min(y0, y1); |
| int yMax = std::max(y0, y1); |
| QRect visibleRect = m_cellArea->visibleRegion().boundingRect(); |
| if (visibleRect.isEmpty()) return; |
| int visibleTop = visibleRect.top(); |
| int visibleBottom = visibleRect.bottom(); |
| |
| if (visibleTop > yMin) { |
| int deltaY = yMin - visibleTop; |
| if (!TApp::instance()->getCurrentFrame()->isPlaying() || |
| Preferences::instance()->isXsheetAutopanEnabled()) { |
| scroll(QPoint(0, deltaY)); |
| return; |
| } |
| } |
| |
| if (visibleBottom < yMax) { |
| int deltaY = yMax + 2 - visibleBottom; |
| if (!TApp::instance()->getCurrentFrame()->isPlaying() || |
| Preferences::instance()->isXsheetAutopanEnabled()) { |
| scroll(QPoint(0, deltaY)); |
| return; |
| } |
| } |
| if (orientation()->isVerticalTimeline()) |
| updateCellRowAree(); |
| else |
| updateCellColumnAree(); |
| } |
| |
| |
| |
| void XsheetViewer::onSelectionSwitched(TSelection *oldSelection, |
| TSelection *newSelection) { |
| if ((TSelection *)getCellSelection() == oldSelection) { |
| m_cellArea->update(m_cellArea->visibleRegion()); |
| m_rowArea->update(m_rowArea->visibleRegion()); |
| changeWindowTitle(); |
| } else if ((TSelection *)m_columnSelection == oldSelection) |
| m_columnArea->update(m_columnArea->visibleRegion()); |
| } |
| |
| |
| |
| |
| void XsheetViewer::onSelectionChanged(TSelection *selection) { |
| if ((TSelection *)getCellSelection() == selection) { |
| changeWindowTitle(); |
| if (Preferences::instance()->isInputCellsWithoutDoubleClickingEnabled()) { |
| TCellSelection *cellSel = getCellSelection(); |
| if (cellSel->isEmpty()) |
| m_cellArea->hideRenameField(); |
| else |
| m_cellArea->showRenameField( |
| cellSel->getSelectedCells().m_r0, cellSel->getSelectedCells().m_c0, |
| cellSel->getSelectedCells().getColCount() > 1); |
| } |
| } |
| } |
| |
| |
| |
| void XsheetViewer::updateAllAree(bool isDragging) { |
| m_cellArea->update(m_cellArea->visibleRegion()); |
| if (!isDragging) { |
| m_rowArea->update(m_rowArea->visibleRegion()); |
| m_columnArea->update(m_columnArea->visibleRegion()); |
| } |
| m_toolbar->update(m_toolbar->visibleRegion()); |
| } |
| |
| |
| |
| void XsheetViewer::updateColumnArea() { |
| m_columnArea->update(m_columnArea->visibleRegion()); |
| } |
| |
| |
| |
| void XsheetViewer::updateCellColumnAree() { |
| if (!m_isComputingSize) refreshContentSize(0, 0); |
| m_columnArea->update(m_columnArea->visibleRegion()); |
| m_cellArea->update(m_cellArea->visibleRegion()); |
| } |
| |
| |
| |
| void XsheetViewer::updateCellRowAree() { |
| if (!m_isComputingSize) refreshContentSize(0, 0); |
| m_rowArea->update(m_rowArea->visibleRegion()); |
| m_cellArea->update(m_cellArea->visibleRegion()); |
| } |
| |
| |
| |
| void XsheetViewer::onScrubStopped() { |
| resetScrubHighlight(); |
| updateCells(); |
| } |
| |
| |
| |
| void XsheetViewer::discardNoteWidget() { |
| if (m_currentNoteIndex == -1) return; |
| TXshNoteSet *notes = getXsheet()->getNotes(); |
| int i; |
| for (i = m_currentNoteIndex + 1; i < m_noteWidgets.size(); i++) { |
| XsheetGUI::NoteWidget *w = m_noteWidgets.at(i); |
| int index = w->getNoteIndex(); |
| w->setNoteIndex(index - 1); |
| w->update(); |
| } |
| delete m_noteWidgets.at(m_currentNoteIndex); |
| m_noteWidgets.removeAt(m_currentNoteIndex); |
| m_noteArea->updateButtons(); |
| updateCells(); |
| } |
| |
| |
| |
| QList<XsheetGUI::NoteWidget *> XsheetViewer::getNotesWidget() const { |
| return m_noteWidgets; |
| } |
| |
| |
| |
| void XsheetViewer::addNoteWidget(XsheetGUI::NoteWidget *w) { |
| m_noteWidgets.push_back(w); |
| m_noteArea->updateButtons(); |
| } |
| |
| |
| |
| int XsheetViewer::getCurrentNoteIndex() const { return m_currentNoteIndex; } |
| |
| |
| |
| void XsheetViewer::setCurrentNoteIndex(int currentNoteIndex) { |
| m_currentNoteIndex = currentNoteIndex; |
| m_noteArea->updateButtons(); |
| |
| if (currentNoteIndex < 0) return; |
| |
| TXshNoteSet *notes = getXsheet()->getNotes(); |
| int row = notes->getNoteRow(currentNoteIndex); |
| int col = notes->getNoteCol(currentNoteIndex); |
| TPointD pos = notes->getNotePos(currentNoteIndex); |
| |
| QPoint topLeft = positionToXY(CellPosition(row, col)) + |
| QPoint(pos.x, pos.y); |
| QSize size(XsheetGUI::NoteWidth, XsheetGUI::NoteHeight); |
| QRect noteRect(topLeft, size); |
| scrollToHorizontalRange(noteRect.left(), noteRect.right()); |
| scrollToVerticalRange(noteRect.top(), noteRect.bottom()); |
| } |
| |
| |
| |
| void XsheetViewer::resetXsheetNotes() { m_noteArea->updateButtons(); } |
| |
| |
| |
| void XsheetViewer::updateNoteWidgets() { |
| int i; |
| for (i = 0; i < m_noteWidgets.size(); i++) m_noteWidgets.at(i)->update(); |
| m_noteArea->updatePopup(); |
| updateCells(); |
| } |
| |
| |
| |
| void XsheetViewer::clearNoteWidgets() { |
| int i; |
| for (i = 0; i < m_noteWidgets.size(); i++) delete m_noteWidgets.at(i); |
| m_noteWidgets.clear(); |
| } |
| |
| |
| |
| void XsheetViewer::changeWindowTitle() { |
| TApp *app = TApp::instance(); |
| ToonzScene *scene = app->getCurrentScene()->getScene(); |
| if (!scene || !app->getCurrentFrame()->isEditingScene()) return; |
| TProject *project = scene->getProject(); |
| QString sceneName = QString::fromStdWString(scene->getSceneName()); |
| if (sceneName.isEmpty()) sceneName = tr("Untitled"); |
| if (app->getCurrentScene()->getDirtyFlag()) sceneName += QString("*"); |
| QString name = tr("Scene: ") + sceneName; |
| int frameCount = scene->getFrameCount(); |
| name = name + " :: " + tr(std::to_string(frameCount).c_str()) + |
| (frameCount == 1 ? tr(" Frame") : tr(" Frames")); |
| |
| |
| ChildStack *childStack = scene->getChildStack(); |
| if (childStack && childStack->getAncestorCount() > 0) { |
| name += tr(" (Sub)"); |
| } |
| |
| TXshLevel *level = app->getCurrentLevel()->getLevel(); |
| if (level) { |
| QString levelName = QString::fromStdWString(level->getName()); |
| name += tr(" Level: ") + levelName; |
| } |
| |
| if ((TSelection *)getCellSelection() == |
| app->getCurrentSelection()->getSelection() && |
| !getCellSelection()->isEmpty()) { |
| int r0, r1, c0, c1; |
| getCellSelection()->getSelectedCells(r0, c0, r1, c1); |
| name += tr(" Selected: ") + QString::number(r1 - r0 + 1) + |
| ((r1 - r0 + 1 == 1) ? tr(" frame : ") : tr(" frames * ")) + |
| QString::number(c1 - c0 + 1) + |
| ((c1 - c0 + 1 == 1) ? tr(" column") : tr(" columns")); |
| } |
| |
| parentWidget()->setWindowTitle(name); |
| } |
| |
| |
| |
| |
| |
| QString XsheetViewer::getFrameNumberWithLetters(int frame) { |
| int letterNum = frame % 10; |
| QChar letter; |
| |
| switch (letterNum) { |
| case 0: |
| letter = QChar(); |
| break; |
| case 1: |
| letter = 'A'; |
| break; |
| case 2: |
| letter = 'B'; |
| break; |
| case 3: |
| letter = 'C'; |
| break; |
| case 4: |
| letter = 'D'; |
| break; |
| case 5: |
| letter = 'E'; |
| break; |
| case 6: |
| letter = 'F'; |
| break; |
| case 7: |
| letter = 'G'; |
| break; |
| case 8: |
| letter = 'H'; |
| break; |
| case 9: |
| letter = 'I'; |
| break; |
| default: |
| letter = QChar(); |
| break; |
| } |
| |
| QString number; |
| if (frame >= 10) { |
| number = QString::number(frame); |
| number.chop(1); |
| } else |
| number = "0"; |
| |
| return (QChar(letter).isNull()) ? number : number.append(letter); |
| } |
| |
| |
| void XsheetViewer::setFrameDisplayStyle(FrameDisplayStyle style) { |
| m_frameDisplayStyle = style; |
| FrameDisplayStyleInXsheetRowArea = (int)style; |
| } |
| |
| |
| |
| void XsheetViewer::save(QSettings &settings) const { |
| settings.setValue("orientation", orientation()->name()); |
| settings.setValue("frameZoomFactor", m_frameZoomFactor); |
| } |
| |
| void XsheetViewer::load(QSettings &settings) { |
| QVariant zoomFactor = settings.value("frameZoomFactor"); |
| QVariant name = settings.value("orientation"); |
| |
| if (zoomFactor.canConvert(QVariant::Int)) { |
| m_frameZoomFactor = zoomFactor.toInt(); |
| m_layerFooterPanel->setZoomSliderValue(m_frameZoomFactor); |
| } |
| |
| if (name.canConvert(QVariant::String)) { |
| m_orientation = Orientations::byName(name.toString()); |
| emit orientationChanged(orientation()); |
| } |
| } |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| QList<int> XsheetViewer::availableFramesPerPage() { |
| int frameRate = TApp::instance() |
| ->getCurrentScene() |
| ->getScene() |
| ->getProperties() |
| ->getOutputProperties() |
| ->getFrameRate(); |
| |
| QList<int> ret; |
| ret << frameRate; |
| if (frameRate % 2 == 0) ret << frameRate * 3 / 2; |
| ret << frameRate * 2; |
| ret << frameRate * 3; |
| ret << frameRate * 4; |
| ret << frameRate * 6; |
| |
| |
| int size = (orientation()->isVerticalTimeline()) |
| ? m_cellScrollArea->viewport()->height() |
| : m_cellScrollArea->viewport()->width(); |
| int scaleMin = (orientation()->isVerticalTimeline()) ? 50 : 20; |
| int scaleMax = 100; |
| |
| int frameMin = (int)std::ceil( |
| (double)size / |
| ((double)orientation()->dimension(PredefinedDimension::FRAME) * |
| (double)scaleMax / 100.0)); |
| int frameMax = (int)std::floor( |
| (double)size / |
| ((double)orientation()->dimension(PredefinedDimension::FRAME) * |
| (double)scaleMin / 100.0)); |
| |
| for (auto itr = ret.begin(); itr != ret.end();) { |
| |
| if (*itr < frameMin || *itr > frameMax) { |
| itr = ret.erase(itr); |
| continue; |
| } |
| itr++; |
| } |
| return ret; |
| } |
| |
| |
| |
| void XsheetViewer::zoomToFramesPerPage(int frames) { |
| int size = (orientation()->isVerticalTimeline()) |
| ? m_cellScrollArea->viewport()->height() |
| : m_cellScrollArea->viewport()->width(); |
| int frameDim = orientation()->dimension(PredefinedDimension::FRAME); |
| |
| double scale = (double)size / ((double)frameDim * (double)frames); |
| |
| |
| int factor; |
| if (orientation()->isVerticalTimeline()) |
| factor = (int)std::round((0.2 + (scale - 0.5) * 8.0 / 5.0) * 100); |
| else |
| factor = (int)std::round(scale * 100); |
| |
| zoomOnFrame(getCurrentRow(), factor); |
| } |
| |
| |
| int XsheetViewer::getFrameZoomFactor() const { |
| if (orientation()->isVerticalTimeline()) |
| return 50 + (m_frameZoomFactor - 20) * 5 / 8; |
| |
| return m_frameZoomFactor; |
| } |
| |
| QPoint XsheetViewer::getFrameZoomAdjustment() { |
| |
| |
| QRect frameRect = orientation()->rect(PredefinedRect::FRAME_HEADER); |
| int adj; |
| if (orientation()->isVerticalTimeline()) { |
| adj = frameRect.height() - |
| ((frameRect.height() * getFrameZoomFactor()) / 100) - 1; |
| return QPoint(0, std::max(0, adj)); |
| } else { |
| adj = frameRect.width() - |
| ((frameRect.width() * getFrameZoomFactor()) / 100) - 1; |
| return QPoint(std::max(0, adj), 0); |
| } |
| } |
| |
| void XsheetViewer::zoomOnFrame(int frame, int factor) { |
| QPoint xyOrig = positionToXY(CellPosition(frame, -1)); |
| |
| m_frameZoomFactor = factor; |
| m_layerFooterPanel->setZoomSliderValue(m_frameZoomFactor); |
| |
| QPoint xyNew = positionToXY(CellPosition(frame, -1)); |
| |
| scroll(xyNew - xyOrig); |
| |
| TApp::instance()->getCurrentXsheet()->notifyXsheetChanged(); |
| if (orientation()->isVerticalTimeline()) |
| TApp::instance()->getCurrentXsheet()->notifyZoomScaleChanged(factor); |
| m_rowArea->update(); |
| } |
| |
| QColor XsheetViewer::getSelectedColumnTextColor() const { |
| |
| TPixel currentColumnPixel; |
| Preferences::instance()->getCurrentColumnData(currentColumnPixel); |
| QColor currentColumnColor((int)currentColumnPixel.r, |
| (int)currentColumnPixel.g, |
| (int)currentColumnPixel.b, 255); |
| return currentColumnColor; |
| } |
| |
| |
| |
| |
| |
| OpenFloatingPanel openXsheetViewerCommand(MI_OpenXshView, "Xsheet", |
| QObject::tr("Xsheet")); |
| |
| OpenFloatingPanel openTimelineViewerCommand(MI_OpenTimelineView, "Timeline", |
| QObject::tr("Timeline")); |
| |