| |
| |
|
|
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| namespace Spreadsheet { |
| |
| //============================================================================= |
| FrameScroller::FrameScroller() |
| : m_orientation(Orientations::topToBottom()) |
| , m_scrollArea(nullptr) |
| , m_lastX(0) |
| , m_lastY(0) |
| , m_syncing(false) {} |
| |
| FrameScroller::~FrameScroller() {} |
| |
| void FrameScroller::setFrameScrollArea(QScrollArea *scrollArea) { |
| disconnectScrollbars(); |
| m_scrollArea = scrollArea; |
| connectScrollbars(); |
| } |
| |
| void FrameScroller::disconnectScrollbars() { |
| if (!m_scrollArea) return; |
| disconnect(m_scrollArea->verticalScrollBar(), &QScrollBar::valueChanged, this, |
| &FrameScroller::onVScroll); |
| disconnect(m_scrollArea->horizontalScrollBar(), &QScrollBar::valueChanged, |
| this, &FrameScroller::onHScroll); |
| } |
| |
| void FrameScroller::connectScrollbars() { |
| if (!m_scrollArea) return; |
| m_lastX = m_scrollArea->horizontalScrollBar()->value(); |
| m_lastY = m_scrollArea->verticalScrollBar()->value(); |
| connect(m_scrollArea->verticalScrollBar(), &QScrollBar::valueChanged, this, |
| &FrameScroller::onVScroll); |
| connect(m_scrollArea->horizontalScrollBar(), &QScrollBar::valueChanged, this, |
| &FrameScroller::onHScroll); |
| } |
| |
| void FrameScroller::onVScroll(int y) { |
| QPoint offset(0, y - m_lastY); |
| if (isSyncing()) return; |
| m_lastY = y; |
| |
| int senderMaximum = 0; |
| QScrollBar *scrollBar = dynamic_cast<QScrollBar *>(sender()); |
| if (scrollBar) senderMaximum = scrollBar->maximum(); |
| |
| setSyncing(true); |
| handleScroll(offset, senderMaximum, y); |
| setSyncing(false); |
| } |
| void FrameScroller::onHScroll(int x) { |
| QPoint offset(x - m_lastX, 0); |
| if (isSyncing()) return; |
| m_lastX = x; |
| |
| int senderMaximum = 0; |
| QScrollBar *scrollBar = dynamic_cast<QScrollBar *>(sender()); |
| if (scrollBar) senderMaximum = scrollBar->maximum(); |
| |
| setSyncing(true); |
| handleScroll(offset, senderMaximum, x); |
| setSyncing(false); |
| } |
| |
| static QList<FrameScroller *> frameScrollers; |
| |
| void FrameScroller::handleScroll(QPoint &offset, int senderMaximum, |
| int senderValue) { |
| if ((m_orientation->isVerticalTimeline() && offset.x()) || |
| (!m_orientation->isVerticalTimeline() && |
| offset.y())) |
| return; |
| |
| |
| |
| |
| |
| QList<FrameScroller *> scrollBarCue; |
| for (auto frameScroller : frameScrollers) |
| if (frameScroller != this) { |
| if (!frameScroller->isSyncing()) { |
| if (!frameScroller->exactScroll(senderMaximum, senderValue)) { |
| |
| |
| scrollBarCue.append(frameScroller); |
| } |
| } |
| } |
| |
| if (scrollBarCue.isEmpty()) return; |
| |
| QPointF offsetF(offset); |
| |
| |
| emit zoomScrollAdjust(offsetF, false); |
| |
| CellPositionRatio ratio = orientation()->xyToPositionRatio(offsetF); |
| |
| for (auto frameScroller : scrollBarCue) |
| if (frameScroller != this) { |
| if (!frameScroller->isSyncing()) { |
| frameScroller->onScroll(ratio); |
| break; |
| } |
| } |
| } |
| |
| void adjustScrollbar(QScrollBar *scrollBar, int add); |
| |
| |
| |
| bool FrameScroller::exactScroll(const int senderMaximum, |
| const int senderValue) { |
| QScrollBar *scrollBar = (m_orientation->isVerticalTimeline()) |
| ? m_scrollArea->verticalScrollBar() |
| : m_scrollArea->horizontalScrollBar(); |
| |
| if (scrollBar->maximum() == senderMaximum) { |
| scrollBar->setValue(senderValue); |
| return true; |
| } |
| |
| return false; |
| } |
| |
| void FrameScroller::onScroll(const CellPositionRatio &ratio) { |
| QPointF offset = orientation()->positionRatioToXY(ratio); |
| |
| |
| |
| |
| emit zoomScrollAdjust(offset, true); |
| |
| |
| |
| |
| |
| |
| if (offset.x() > 0.0 || offset.y() > 0.0) emit prepareToScrollOffset(offset); |
| if ((int)offset.x()) |
| adjustScrollbar(m_scrollArea->horizontalScrollBar(), (int)offset.x()); |
| if ((int)offset.y()) |
| adjustScrollbar(m_scrollArea->verticalScrollBar(), (int)offset.y()); |
| } |
| |
| void adjustScrollbar(QScrollBar *scrollBar, int add) { |
| scrollBar->setValue(scrollBar->value() + add); |
| } |
| |
| void FrameScroller::registerFrameScroller() { |
| if (!frameScrollers.contains(this)) frameScrollers.append(this); |
| } |
| |
| void FrameScroller::unregisterFrameScroller() { |
| if (frameScrollers.contains(this)) frameScrollers.removeAll(this); |
| } |
| |
| void FrameScroller::prepareToScrollOthers(const QPointF &offset) { |
| CellPositionRatio ratio = orientation()->xyToPositionRatio(offset); |
| for (int i = 0; i < frameScrollers.size(); i++) |
| if (frameScrollers[i] != this) |
| frameScrollers[i]->prepareToScrollRatio(ratio); |
| } |
| void FrameScroller::prepareToScrollRatio(const CellPositionRatio &ratio) { |
| QPointF offset = orientation()->positionRatioToXY(ratio); |
| emit prepareToScrollOffset(offset); |
| } |
| |
| |
| |
| void SetFrameDragTool::click(int row, int col, QMouseEvent *e) { |
| m_frameHandle->setFrame(row); |
| } |
| |
| void SetFrameDragTool::drag(int row, int col, QMouseEvent *e) { |
| if (row < 0) row = 0; |
| m_frameHandle->setFrame(row); |
| } |
| |
| void SetFrameDragTool::release(int row, int col, QMouseEvent *e) {} |
| |
| |
| |
| |
| |
| |
| |
| SelectionDragTool::SelectionDragTool(SpreadsheetViewer *viewer) |
| : m_viewer(viewer), m_firstRow(-1), m_firstCol(-1) {} |
| |
| void SelectionDragTool::click(int row, int col, QMouseEvent *e) { |
| m_firstCol = col; |
| m_firstRow = row; |
| QRect selectedCells(col, row, 1, 1); |
| m_viewer->selectCells(selectedCells); |
| } |
| |
| void SelectionDragTool::drag(int row, int col, QMouseEvent *e) { |
| int r0 = std::min(row, m_firstRow); |
| int r1 = std::max(row, m_firstRow); |
| int c0 = std::min(col, m_firstCol); |
| int c1 = std::max(col, m_firstCol); |
| QRect selectedCells(c0, r0, c1 - c0 + 1, r1 - r0 + 1); |
| m_viewer->selectCells(selectedCells); |
| } |
| |
| void SelectionDragTool::release(int row, int col, QMouseEvent *e) {} |
| |
| |
| |
| PanTool::PanTool(Spreadsheet::GenericPanel *panel) |
| : m_panel(panel), m_viewer(panel->getViewer()), m_lastPos() {} |
| |
| void PanTool::click(int row, int col, QMouseEvent *e) { |
| m_lastPos = e->pos(); |
| } |
| void PanTool::drag(int row, int col, QMouseEvent *e) { |
| QPoint pos = e->pos(); |
| |
| |
| |
| m_viewer->scroll(m_lastPos - pos); |
| } |
| void PanTool::release(int row, int col, QMouseEvent *e) { |
| |
| } |
| |
| |
| |
| ScrollArea::ScrollArea(QWidget *parent, Qt::WindowFlags flags) |
| : QScrollArea(parent) { |
| setFrameStyle(QFrame::Panel | QFrame::Raised); |
| setLineWidth(6); |
| setContentsMargins(10, 10, 10, 10); |
| } |
| |
| ScrollArea::~ScrollArea() {} |
| |
| void ScrollArea::keyPressEvent(QKeyEvent *e) { e->ignore(); } |
| |
| void ScrollArea::wheelEvent(QWheelEvent *e) { e->ignore(); } |
| |
| |
| |
| GenericPanel::GenericPanel(SpreadsheetViewer *viewer) |
| : QWidget(viewer), m_viewer(viewer), m_dragTool(0) { |
| setFocusPolicy(Qt::NoFocus); |
| } |
| |
| GenericPanel::~GenericPanel() {} |
| |
| void GenericPanel::paintEvent(QPaintEvent *e) { |
| QPainter p(this); |
| p.setPen(m_viewer->getLightLineColor()); |
| for (int c = 0;; c++) { |
| int x = getViewer()->columnToX(c); |
| if (x > width()) break; |
| p.drawLine(x, 0, x, height()); |
| } |
| for (int r = 0;; r++) { |
| int y = getViewer()->rowToY(r); |
| if (y > height()) break; |
| p.drawLine(0, y, width(), y); |
| } |
| p.setPen(Qt::magenta); |
| p.drawLine(e->rect().topLeft(), e->rect().bottomRight()); |
| } |
| |
| void GenericPanel::mousePressEvent(QMouseEvent *e) { |
| assert(!m_dragTool); |
| if (e->button() == Qt::MiddleButton) |
| m_dragTool = new PanTool(this); |
| else |
| m_dragTool = createDragTool(e); |
| |
| CellPosition cellPosition = getViewer()->xyToPosition(e->pos()); |
| int row = cellPosition.frame(); |
| int col = cellPosition.layer(); |
| if (m_dragTool) m_dragTool->click(row, col, e); |
| } |
| |
| void GenericPanel::mouseReleaseEvent(QMouseEvent *e) { |
| CellPosition cellPosition = getViewer()->xyToPosition(e->pos()); |
| int row = cellPosition.frame(); |
| int col = cellPosition.layer(); |
| m_viewer->stopAutoPan(); |
| if (m_dragTool) { |
| m_dragTool->release(row, col, e); |
| delete m_dragTool; |
| m_dragTool = 0; |
| } |
| } |
| |
| void GenericPanel::mouseMoveEvent(QMouseEvent *e) { |
| CellPosition cellPosition = getViewer()->xyToPosition(e->pos()); |
| int row = cellPosition.frame(); |
| int col = cellPosition.layer(); |
| if (e->buttons() != 0 && m_dragTool != 0) { |
| if ((e->buttons() & Qt::LeftButton) != 0 && |
| !visibleRegion().contains(e->pos())) { |
| QRect bounds = visibleRegion().boundingRect(); |
| m_viewer->setAutoPanSpeed(bounds, e->pos()); |
| } else |
| m_viewer->stopAutoPan(); |
| m_dragTool->drag(row, col, e); |
| } |
| } |
| |
| |
| |
| RowPanel::RowPanel(SpreadsheetViewer *viewer) |
| : GenericPanel(viewer), m_xa(12) {} |
| |
| |
| |
| DragTool *RowPanel::createDragTool(QMouseEvent *) { |
| TFrameHandle *frameHandle = getViewer()->getFrameHandle(); |
| if (frameHandle) |
| return new SetFrameDragTool(frameHandle); |
| else |
| return 0; |
| } |
| |
| |
| |
| void RowPanel::drawRows(QPainter &p, int r0, int r1) { |
| QString fontName = Preferences::instance()->getInterfaceFont(); |
| if (fontName == "") { |
| |
| fontName = "Arial"; |
| |
| fontName = "Helvetica"; |
| |
| } |
| static QFont font(fontName, -1, QFont::Bold); |
| font.setPixelSize(12); |
| p.setFont(font); |
| |
| QRect visibleRect = visibleRegion().boundingRect(); |
| int x0 = visibleRect.left(); |
| int x1 = visibleRect.right(); |
| int y0 = visibleRect.top(); |
| int y1 = visibleRect.bottom(); |
| |
| bool simpleView = getViewer()->getFrameZoomFactor() <= |
| Orientations::topToBottom()->dimension( |
| PredefinedDimension::SCALE_THRESHOLD); |
| int currentRow = getViewer()->getCurrentRow(); |
| int r; |
| int y = getViewer()->rowToY(r0); |
| for (r = r0; r <= r1; r++) { |
| int next_y = getViewer()->rowToY(r + 1); |
| |
| bool isMarkSecRow = getViewer()->isMarkSecRow(r); |
| bool isMarkRow = getViewer()->isMarkRow(r); |
| QColor color = (isMarkSecRow) ? getViewer()->getSecMarkerLineColor() |
| : (isMarkRow) ? getViewer()->getMarkerLineColor() |
| : getViewer()->getLightLineColor(); |
| p.setPen(QPen(color, |
| (isMarkSecRow) ? 3. |
| : (getViewer()->isSecMarkerActive() && isMarkRow) ? 2. |
| : 1., |
| Qt::SolidLine, Qt::FlatCap)); |
| p.drawLine(x0, y, x1, y); |
| |
| if (simpleView && r > 0 && !getViewer()->isMarkRow(r + 1)) { |
| y = next_y; |
| continue; |
| } |
| |
| |
| p.setPen((r == currentRow) ? getViewer()->getCurrentRowTextColor() |
| : getViewer()->getTextColor()); |
| |
| QString number = QString::number(r + 1); |
| p.drawText(QRect(x0, y + 1, width() - 4, next_y - y - 1), |
| Qt::AlignVCenter | Qt::AlignRight, number); |
| y = next_y; |
| } |
| } |
| |
| |
| |
| void RowPanel::drawCurrentRowGadget(QPainter &p, int r0, int r1) { |
| int currentRow = getViewer()->getCurrentRow(); |
| |
| if (currentRow < r0 || r1 < currentRow) return; |
| int top = getViewer()->rowToY(currentRow); |
| int bottom = getViewer()->rowToY(currentRow + 1) - 1; |
| QRect rect(1, top, width() - 1, bottom - top); |
| |
| p.fillRect(rect, getViewer()->getCurrentRowBgColor()); |
| } |
| |
| |
| |
| void RowPanel::paintEvent(QPaintEvent *e) { |
| QRect toBeUpdated = e->rect(); |
| QPainter p(this); |
| |
| CellRange visible = getViewer()->xyRectToRange(toBeUpdated); |
| |
| int r0 = visible.from().frame(); |
| int r1 = visible.to().frame(); |
| |
| p.setClipRect(toBeUpdated); |
| p.fillRect(toBeUpdated, QBrush(getViewer()->getLightLightBGColor())); |
| |
| drawCurrentRowGadget(p, r0, r1); |
| drawRows(p, r0, r1); |
| } |
| |
| |
| |
| ColumnPanel::ColumnPanel(SpreadsheetViewer *viewer) : GenericPanel(viewer) {} |
| |
| |
| |
| CellPanel::CellPanel(SpreadsheetViewer *viewer) : GenericPanel(viewer) {} |
| |
| DragTool *CellPanel::createDragTool(QMouseEvent *) { |
| |
| |
| return new SelectionDragTool(getViewer()); |
| } |
| |
| void CellPanel::paintEvent(QPaintEvent *e) { |
| QPainter painter(this); |
| |
| QRect toBeUpdated = e->rect(); |
| painter.setClipRect(toBeUpdated); |
| |
| int x0 = toBeUpdated.left() - 1; |
| int y0 = toBeUpdated.top(); |
| int x1 = toBeUpdated.right(), y1 = toBeUpdated.bottom(); |
| |
| QRect alteredRect(QPoint(x0, y0), QPoint(x1, y1)); |
| CellRange cellRange = getViewer()->xyRectToRange(alteredRect); |
| |
| int r0 = cellRange.from().frame(); |
| int r1 = cellRange.to().frame(); |
| |
| |
| int c0 = cellRange.from().layer(); |
| int c1 = cellRange.to().layer(); |
| |
| |
| int rowCount = getViewer()->getRowCount(); |
| |
| |
| painter.fillRect(toBeUpdated, getViewer()->getLightLightBGColor()); |
| |
| |
| int yLast = getViewer()->rowToY(rowCount); |
| if (yLast < y1) |
| painter.fillRect(x0, y0, x1 - x0, yLast - y0, getViewer()->getBGColor()); |
| else |
| painter.fillRect(toBeUpdated, getViewer()->getBGColor()); |
| |
| |
| drawCells(painter, r0, c0, r1, c1); |
| |
| |
| painter.setPen(getViewer()->getVerticalLineColor()); |
| for (int col = c0; col <= c1; col++) { |
| int x = getViewer()->columnToX(col); |
| painter.drawLine(x, y0, x, y1); |
| } |
| |
| |
| int currentRow = getViewer()->getCurrentRow(); |
| for (int r = r0; r <= r1; r++) { |
| int y = getViewer()->rowToY(r); |
| bool isMarkSecRow = getViewer()->isMarkSecRow(r); |
| bool isMarkRow = getViewer()->isMarkRow(r); |
| QColor color = (isMarkSecRow) ? getViewer()->getSecMarkerLineColor() |
| : (isMarkRow) ? getViewer()->getMarkerLineColor() |
| : getViewer()->getLightLineColor(); |
| painter.setPen(QPen(color, |
| (isMarkSecRow) ? 3. |
| : (getViewer()->isSecMarkerActive() && isMarkRow) ? 2. |
| : 1., |
| Qt::SolidLine, Qt::FlatCap)); |
| painter.drawLine(x0, y, x1, y); |
| } |
| } |
| |
| } |
| |
| |
| |
| SpreadsheetViewer::SpreadsheetViewer(QWidget *parent) |
| : QDialog(parent) |
| , m_columnScrollArea(0) |
| , m_rowScrollArea(0) |
| , m_cellScrollArea(0) |
| , m_frameHandle(0) |
| , m_columnWidth(50) |
| , m_rowHeight(20) |
| , m_scaleFactor(100) |
| , m_timerId(0) |
| , m_autoPanSpeed(0, 0) |
| , m_lastAutoPanPos(0, 0) |
| , m_rowCount(0) |
| , m_columnCount(0) |
| , m_currentRow(0) |
| , m_markRowDistance(6) |
| , m_markRowOffset(0) |
| , m_markSecRowDistance(-1) |
| , m_isComputingSize(false) |
| , m_frameScroller() { |
| |
| |
| setFocusPolicy(Qt::NoFocus); |
| |
| |
| setObjectName("Viewer"); |
| |
| |
| m_columnScrollArea = new Spreadsheet::ScrollArea; |
| m_columnScrollArea->setObjectName("ScrollColumnArea"); |
| m_columnScrollArea->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); |
| m_columnScrollArea->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff); |
| m_columnScrollArea->setFocusPolicy(Qt::NoFocus); |
| |
| |
| m_rowScrollArea = new Spreadsheet::ScrollArea; |
| m_rowScrollArea->setObjectName("ScrollRowArea"); |
| m_rowScrollArea->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); |
| m_rowScrollArea->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff); |
| m_rowScrollArea->setFocusPolicy(Qt::NoFocus); |
| |
| |
| m_cellScrollArea = new Spreadsheet::ScrollArea; |
| m_cellScrollArea->setObjectName("ScrollCellArea"); |
| m_cellScrollArea->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOn); |
| m_cellScrollArea->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOn); |
| |
| |
| m_cellScrollArea->setFocusPolicy(Qt::NoFocus); |
| |
| m_columnScrollArea->setSizePolicy( |
| QSizePolicy(QSizePolicy::Ignored, QSizePolicy::Fixed)); |
| m_rowScrollArea->setSizePolicy( |
| QSizePolicy(QSizePolicy::Fixed, QSizePolicy::Ignored)); |
| |
| m_rowScrollArea->setFixedWidth(30); |
| |
| if (Preferences::instance()->getLoadedXsheetLayout() == QString("Minimum") && |
| !Preferences::instance()->isShowXSheetToolbarEnabled() && |
| Preferences::instance()->isExpandFunctionHeaderEnabled() && |
| Preferences::instance()->getFunctionEditorToggle() != |
| Preferences::FunctionEditorToggle::ShowFunctionSpreadsheetInPopup) |
| m_columnScrollArea->setFixedHeight(m_rowHeight * 2 - 4); |
| else |
| m_columnScrollArea->setFixedHeight(m_rowHeight * 3 - 4); |
| |
| m_frameScroller.setFrameScrollArea(m_cellScrollArea); |
| connect(&m_frameScroller, &Spreadsheet::FrameScroller::prepareToScrollOffset, |
| this, &SpreadsheetViewer::onPrepareToScrollOffset); |
| connect(&m_frameScroller, &Spreadsheet::FrameScroller::zoomScrollAdjust, this, |
| &SpreadsheetViewer::onZoomScrollAdjust); |
| |
| |
| QGridLayout *layout = new QGridLayout(); |
| layout->setMargin(0); |
| layout->setSpacing(0); |
| { |
| layout->addWidget(m_columnScrollArea, 0, 1); |
| layout->addWidget(m_rowScrollArea, 1, 0); |
| layout->addWidget(m_cellScrollArea, 1, 1, 2, 2); |
| |
| int scrollBarWidth = 16; |
| |
| QWidget *w = new QWidget(this); |
| w->setFixedWidth(scrollBarWidth); |
| w->setFixedHeight(m_columnScrollArea->height()); |
| layout->addWidget(w, 0, 2); |
| |
| |
| w = new QWidget(this); |
| w->setFixedSize(QSize(30, scrollBarWidth)); |
| layout->addWidget(w, 2, 0); |
| |
| layout->setColumnStretch(0, 0); |
| layout->setColumnStretch(1, 1); |
| layout->setColumnStretch(2, 0); |
| layout->setRowStretch(0, 0); |
| layout->setRowStretch(1, 1); |
| layout->setRowStretch(2, 0); |
| } |
| setLayout(layout); |
| |
| |
| |
| |
| connect(m_rowScrollArea->verticalScrollBar(), SIGNAL(valueChanged(int)), |
| m_cellScrollArea->verticalScrollBar(), SLOT(setValue(int))); |
| connect(m_cellScrollArea->verticalScrollBar(), SIGNAL(valueChanged(int)), |
| m_rowScrollArea->verticalScrollBar(), SLOT(setValue(int))); |
| |
| |
| connect(m_columnScrollArea->horizontalScrollBar(), SIGNAL(valueChanged(int)), |
| m_cellScrollArea->horizontalScrollBar(), SLOT(setValue(int))); |
| connect(m_cellScrollArea->horizontalScrollBar(), SIGNAL(valueChanged(int)), |
| m_columnScrollArea->horizontalScrollBar(), SLOT(setValue(int))); |
| |
| connect(m_cellScrollArea->verticalScrollBar(), SIGNAL(valueChanged(int)), |
| SLOT(onVSliderChanged(int))); |
| connect(m_cellScrollArea->horizontalScrollBar(), SIGNAL(valueChanged(int)), |
| SLOT(onHSliderChanged(int))); |
| } |
| |
| SpreadsheetViewer::~SpreadsheetViewer() {} |
| |
| void SpreadsheetViewer::setFrameHandle(TFrameHandle *frameHandle) { |
| if (m_frameHandle == frameHandle) return; |
| if (m_frameHandle) m_frameHandle->disconnect(this); |
| m_frameHandle = frameHandle; |
| |
| if (isVisible() && m_frameHandle) { |
| connect(m_frameHandle, SIGNAL(frameSwitched()), this, |
| SLOT(onFrameSwitched())); |
| update(); |
| } |
| } |
| |
| void SpreadsheetViewer::setRowsPanel(Spreadsheet::RowPanel *rows) { |
| m_rowScrollArea->setWidget(rows); |
| } |
| |
| void SpreadsheetViewer::setColumnsPanel(Spreadsheet::ColumnPanel *columns) { |
| m_columnScrollArea->setWidget(columns); |
| |
| } |
| |
| void SpreadsheetViewer::setCellsPanel(Spreadsheet::CellPanel *cells) { |
| m_cellScrollArea->setWidget(cells); |
| } |
| |
| void SpreadsheetViewer::setButtonAreaWidget(QWidget *widget) { |
| QGridLayout *lay = dynamic_cast<QGridLayout *>(layout()); |
| lay->addWidget(widget, 0, 0); |
| } |
| |
| void SpreadsheetViewer::setRowCount(int rowCount) { |
| if (m_rowCount != rowCount) { |
| m_rowCount = rowCount; |
| refreshContentSize(0, 0); |
| } |
| } |
| |
| void SpreadsheetViewer::setColumnCount(int columnCount) { |
| if (m_columnCount != columnCount) { |
| m_columnCount = columnCount; |
| refreshContentSize(0, 0); |
| } |
| } |
| |
| void SpreadsheetViewer::scroll(QPoint delta) { |
| int x = delta.x(); |
| int y = delta.y(); |
| |
| QScrollBar *hSc = m_cellScrollArea->horizontalScrollBar(); |
| QScrollBar *vSc = m_cellScrollArea->verticalScrollBar(); |
| |
| int valueH = hSc->value() + x; |
| int valueV = vSc->value() + y; |
| int maxValueH = hSc->maximum(); |
| int maxValueV = vSc->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 = hSc->maximum(); |
| if (!notUpdateSizeV) maxValueV = vSc->maximum(); |
| |
| if (valueH > maxValueH && x > 0) valueH = hSc->maximum(); |
| |
| if (valueV > maxValueV && y > 0) valueV = vSc->maximum(); |
| |
| hSc->setValue(valueH); |
| vSc->setValue(valueV); |
| } |
| |
| void SpreadsheetViewer::onPrepareToScrollOffset(const QPointF &offset) { |
| refreshContentSize((int)offset.x(), (int)offset.y()); |
| } |
| |
| void SpreadsheetViewer::onZoomScrollAdjust(QPointF &offset, bool toZoom) { |
| double frameZoomFactor = (double)getFrameZoomFactor(); |
| |
| |
| |
| double newY; |
| if (toZoom) |
| newY = (offset.y() * frameZoomFactor) / 100.0; |
| else |
| newY = (offset.y() * 100.0) / frameZoomFactor; |
| |
| offset.setY(newY); |
| } |
| |
| void SpreadsheetViewer::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 SpreadsheetViewer::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; |
| } |
| |
| int SpreadsheetViewer::xToColumn(int x) const { |
| CellPosition pos = xyToPosition(QPoint(x, 0)); |
| return pos.layer(); |
| } |
| int SpreadsheetViewer::yToRow(int y) const { |
| CellPosition pos = xyToPosition(QPoint(0, y)); |
| return pos.frame(); |
| } |
| int SpreadsheetViewer::columnToX(int col) const { |
| QPoint xy = positionToXY(CellPosition(0, col)); |
| return xy.x(); |
| } |
| int SpreadsheetViewer::rowToY(int row) const { |
| QPoint xy = positionToXY(CellPosition(row, 0)); |
| return xy.y(); |
| } |
| |
| |
| CellPosition SpreadsheetViewer::xyToPosition(const QPoint &point) const { |
| int row = (point.y() * 100 / m_scaleFactor) / m_rowHeight; |
| int col = (point.x()) / m_columnWidth; |
| return CellPosition(row, col); |
| } |
| |
| |
| QPoint SpreadsheetViewer::positionToXY(const CellPosition &pos) const { |
| int x = (pos.layer() * m_columnWidth); |
| int y = pos.frame() * m_rowHeight * m_scaleFactor / 100; |
| |
| return QPoint(x, y); |
| } |
| |
| CellRange SpreadsheetViewer::xyRectToRange(const QRect &rect) const { |
| CellPosition topLeft = xyToPosition(rect.topLeft()); |
| CellPosition bottomRight = xyToPosition(rect.bottomRight()); |
| return CellRange(topLeft, bottomRight); |
| } |
| |
| bool SpreadsheetViewer::refreshContentSize(int scrollDx, int scrollDy) { |
| QSize viewportSize = m_cellScrollArea->viewport()->size(); |
| QPoint offset = m_cellScrollArea->widget()->pos(); |
| offset = QPoint(std::min(0, offset.x() - scrollDx), |
| std::min(0, offset.y() - scrollDy)); |
| |
| QSize contentSize(columnToX(m_columnCount + 1), rowToY(m_rowCount + 1)); |
| |
| QSize actualSize(contentSize); |
| int x = viewportSize.width() - offset.x(); |
| int y = viewportSize.height() - offset.y(); |
| if (x > actualSize.width()) actualSize.setWidth(x); |
| if (y > actualSize.height()) actualSize.setHeight(y); |
| |
| if (actualSize == m_cellScrollArea->widget()->size()) |
| return false; |
| else { |
| m_isComputingSize = true; |
| m_cellScrollArea->widget()->setFixedSize(actualSize); |
| m_rowScrollArea->widget()->setFixedSize( |
| m_rowScrollArea->viewport()->width(), actualSize.height()); |
| m_columnScrollArea->widget()->setFixedSize( |
| actualSize.width(), m_columnScrollArea->viewport()->height()); |
| m_isComputingSize = false; |
| |
| return true; |
| } |
| } |
| |
| void SpreadsheetViewer::showEvent(QShowEvent *) { |
| int viewportHeight = m_cellScrollArea->height(); |
| int contentHeight = rowToY(m_rowCount * 0 + 50); |
| QScrollBar *vSc = m_cellScrollArea->verticalScrollBar(); |
| int actualContentHeight = |
| std::max(contentHeight, vSc->value() + viewportHeight); |
| m_rowScrollArea->widget()->setFixedSize(m_rowScrollArea->viewport()->width(), |
| actualContentHeight); |
| m_cellScrollArea->widget()->setFixedHeight(actualContentHeight); |
| if (m_frameHandle) |
| connect(m_frameHandle, SIGNAL(frameSwitched()), this, |
| SLOT(onFrameSwitched())); |
| |
| |
| } |
| |
| void SpreadsheetViewer::hideEvent(QHideEvent *) { |
| if (m_frameHandle) m_frameHandle->disconnect(this); |
| } |
| |
| void SpreadsheetViewer::resizeEvent(QResizeEvent *e) { |
| QDialog::resizeEvent(e); |
| refreshContentSize(0, 0); |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| } |
| |
| void SpreadsheetViewer::wheelEvent(QWheelEvent *event) { |
| switch (event->source()) { |
| case Qt::MouseEventNotSynthesized: { |
| if (event->angleDelta().x() == 0) { |
| int scrollPixels = (event->angleDelta().y() > 0 ? 1 : -1) * |
| m_markRowDistance * m_rowHeight; |
| scroll(QPoint(0, -scrollPixels)); |
| } else { |
| int scrollPixels = (event->angleDelta().x() > 0 ? 1 : -1) * m_columnWidth; |
| 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 wheelEvent.source(): " |
| "Qt::MouseEventSynthesizedByQt, " |
| "Qt::MouseEventSynthesizedByApplication" |
| << std::endl; |
| break; |
| } |
| |
| } |
| } |
| |
| void SpreadsheetViewer::timerEvent(QTimerEvent *e) { |
| if (!isAutoPanning()) return; |
| scroll(m_autoPanSpeed); |
| m_lastAutoPanPos += m_autoPanSpeed; |
| |
| |
| |
| |
| |
| |
| |
| } |
| |
| void SpreadsheetViewer::keyPressEvent(QKeyEvent *e) { |
| int frameCount = m_rowCount; |
| int row = m_frameHandle->getFrame(); |
| |
| if (e->key() == Qt::Key_Up && |
| row > 0) { |
| m_frameHandle->setFrame(row - 1); |
| return; |
| } else if (e->key() == |
| Qt::Key_Down) { |
| m_frameHandle->setFrame(row + 1); |
| return; |
| } else if (e->key() == '0') { |
| QWidget *panel = parentWidget(); |
| QWidget *panelParent = panel->parentWidget(); |
| while (panelParent != 0 && dynamic_cast<QMainWindow *>(panelParent) == 0) { |
| panel = panelParent; |
| panelParent = panel->parentWidget(); |
| } |
| if (panelParent) { |
| QList<QDockWidget *> panels = panelParent->findChildren<QDockWidget *>(); |
| for (int i = 0; i < panels.size(); i++) { |
| QWidget *w = panels[i]; |
| } |
| } |
| return; |
| } |
| |
| int y = 0; |
| QRect visibleRect = |
| m_cellScrollArea->widget()->visibleRegion().boundingRect(); |
| int visibleRowCount = visibleRect.height() / m_rowHeight; |
| if (e->key() == |
| Qt::Key_PageUp) |
| y = visibleRect.top() - (visibleRowCount + 1) * m_rowHeight; |
| else if (e->key() == Qt::Key_PageDown) |
| |
| y = visibleRect.bottom() + (visibleRowCount + 1) * m_rowHeight; |
| else if (e->key() == Qt::Key_Home) |
| y = 0; |
| else if (e->key() == Qt::Key_End) |
| y = (frameCount + 1) * m_rowHeight; |
| else |
| return; |
| |
| int deltaY = 0; |
| if (y < visibleRect.top()) |
| deltaY = y - visibleRect.top(); |
| else |
| deltaY = y - visibleRect.bottom(); |
| scroll(QPoint(0, deltaY)); |
| } |
| |
| void SpreadsheetViewer::frameSwitched() {} |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| void SpreadsheetViewer::updateAreas() {} |
| |
| void SpreadsheetViewer::onVSliderChanged(int) { |
| if (!m_isComputingSize) refreshContentSize(0, 0); |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| } |
| |
| void SpreadsheetViewer::onHSliderChanged(int) { |
| if (!m_isComputingSize) refreshContentSize(0, 0); |
| } |
| |
| void SpreadsheetViewer::ensureVisibleCol(int col) { |
| int x = columnToX(col) + m_columnWidth / 2; |
| |
| int vertValue = m_cellScrollArea->verticalScrollBar()->value(); |
| m_cellScrollArea->ensureVisible(x, vertValue, m_columnWidth / 2, 0); |
| } |
| |
| bool SpreadsheetViewer::isSmallHeader() { |
| return ( |
| Preferences::instance()->getLoadedXsheetLayout() == QString("Minimum") && |
| !Preferences::instance()->isShowXSheetToolbarEnabled() && |
| Preferences::instance()->isExpandFunctionHeaderEnabled() && |
| Preferences::instance()->getFunctionEditorToggle() != |
| Preferences::FunctionEditorToggle::ShowFunctionSpreadsheetInPopup); |
| } |
| |
| void SpreadsheetViewer::updateHeaderHeight() { |
| if (isSmallHeader()) |
| m_columnScrollArea->setFixedHeight(m_rowHeight * 2 - 4); |
| else |
| m_columnScrollArea->setFixedHeight(m_rowHeight * 3 - 4); |
| } |